fix(Smartjson): Cross-platform buffer/base64 handling, safer folding with cycle detection, parsing fixes, docs and dependency updates

This commit is contained in:
2025-09-12 19:16:52 +00:00
parent 9bb6e0b497
commit 2f012fc0ad
9 changed files with 5547 additions and 3223 deletions

View File

@@ -11,10 +11,11 @@ interface JsonObject {
export const parse = bufferhandling.parse;
export const parseJsonL = (jsonlData: string): JsonObject[] => {
const lines = jsonlData.trim().split('\n');
const lines = jsonlData.split('\n');
const parsedData: JsonObject[] = lines.reduce((acc, line) => {
if (line.trim().length > 0) {
acc.push(JSON.parse(line));
const trimmed = line.trim();
if (trimmed.length > 0) {
acc.push(parse(trimmed));
}
return acc;
}, [] as JsonObject[]);
@@ -49,18 +50,18 @@ export const stringifyBase64 = (...args: Parameters<typeof stringify>): string =
};
export const parseBase64 = (base64JsonStringArg: string) => {
const simpleStringified = plugins.smartstring.base64.decode(base64JsonStringArg);
const base64 = plugins.smartstring.base64 as any;
const decodeFn: (input: string) => string = base64.decodeUri || base64.decode;
const simpleStringified = decodeFn(base64JsonStringArg);
return parse(simpleStringified);
};
parse;
export class Smartjson {
/**
* enfolds data from an object
*/
public static enfoldFromObject(objectArg) {
const newInstance = new this();
public static enfoldFromObject<T extends typeof Smartjson>(this: T, objectArg: any): InstanceType<T> {
const newInstance = new this() as InstanceType<T>;
for (const keyName in objectArg) {
if (newInstance.saveableProperties.indexOf(keyName) !== -1) {
newInstance[keyName] = objectArg[keyName];
@@ -72,7 +73,7 @@ export class Smartjson {
/**
* enfold from json
*/
public static enfoldFromJson(jsonArg: string) {
public static enfoldFromJson<T extends typeof Smartjson>(this: T, jsonArg: string): InstanceType<T> {
const objectFromJson = parse(jsonArg);
return this.enfoldFromObject(objectFromJson);
}
@@ -88,21 +89,49 @@ export class Smartjson {
*/
public foldToObject() {
const newFoldedObject: { [key: string]: any } = {};
const trackMap = [];
for (const keyName of this.saveableProperties) {
let value = this[keyName];
if (value instanceof Smartjson) {
if (trackMap.includes(value)) {
const trackSet = new Set<Smartjson>();
const foldValue = (val: any): any => {
if (val instanceof Smartjson) {
if (trackSet.has(val)) {
throw new Error('cycle detected');
}
trackMap.push(value);
value = value.foldToObject();
trackSet.add(val);
return val.foldToObjectInternal(trackSet);
}
newFoldedObject[keyName] = plugins.lodashCloneDeep(value);
if (Array.isArray(val)) {
return val.map((item) => foldValue(item));
}
return plugins.lodashCloneDeep(val);
};
for (const keyName of this.saveableProperties) {
const value = this[keyName];
newFoldedObject[keyName] = foldValue(value);
}
return newFoldedObject;
}
private foldToObjectInternal(trackSet: Set<Smartjson>) {
const result: { [key: string]: any } = {};
const foldValue = (val: any): any => {
if (val instanceof Smartjson) {
if (trackSet.has(val)) {
throw new Error('cycle detected');
}
trackSet.add(val);
return val.foldToObjectInternal(trackSet);
}
if (Array.isArray(val)) {
return val.map((item) => foldValue(item));
}
return plugins.lodashCloneDeep(val);
};
for (const keyName of this.saveableProperties) {
const value = this[keyName];
result[keyName] = foldValue(value);
}
return result;
}
/**
* folds a class into an object
*/
@@ -131,17 +160,7 @@ export const deepEqualObjects = (object1: any, object2: any): boolean => {
};
export const deepEqualJsonLStrings = (jsonLString1: string, jsonLString2: string): boolean => {
const firstArray = [];
jsonLString1.split('\n').forEach((line) => {
if (line) {
firstArray.push(parse(line));
}
});
const secondArray = [];
jsonLString2.split('\n').forEach((line) => {
if (line) {
secondArray.push(parse(line));
}
});
const firstArray = parseJsonL(jsonLString1);
const secondArray = parseJsonL(jsonLString2);
return deepEqualObjects(firstArray, secondArray);
}