fix(Smartjson): Cross-platform buffer/base64 handling, safer folding with cycle detection, parsing fixes, docs and dependency updates
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* autocreated commitinfo by @pushrocks/commitinfo
|
||||
* autocreated commitinfo by @push.rocks/commitinfo
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@push.rocks/smartjson',
|
||||
version: '5.0.20',
|
||||
version: '5.0.21',
|
||||
description: 'A library for handling typed JSON data, providing functionalities for parsing, stringifying, and working with JSON objects, including support for encoding and decoding buffers.'
|
||||
}
|
||||
|
@@ -16,10 +16,23 @@ type TParseReplacer = (this: any, key: string, value: any) => any;
|
||||
|
||||
// Utility functions to handle base64 encoding/decoding in a cross-platform way
|
||||
function base64Encode(data: Uint8Array): string {
|
||||
// Prefer Node's Buffer when available
|
||||
if (typeof Buffer !== 'undefined') {
|
||||
// @ts-ignore Buffer might not exist in browser builds
|
||||
return Buffer.from(data).toString('base64');
|
||||
}
|
||||
// Fallback for browsers
|
||||
return btoa(String.fromCharCode(...data));
|
||||
}
|
||||
|
||||
function base64Decode(str: string): Uint8Array {
|
||||
// Prefer Node's Buffer when available
|
||||
if (typeof Buffer !== 'undefined') {
|
||||
// @ts-ignore Buffer might not exist in browser builds
|
||||
const buf = Buffer.from(str, 'base64');
|
||||
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
||||
}
|
||||
// Fallback for browsers
|
||||
return new Uint8Array(Array.from(atob(str)).map((char) => char.charCodeAt(0)));
|
||||
}
|
||||
|
||||
|
77
ts/index.ts
77
ts/index.ts
@@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user