From aad39e9d2513679017cd524f351cc224ea5a43e0 Mon Sep 17 00:00:00 2001 From: Spring Chiu Date: Sun, 7 Jan 2024 16:08:14 +0800 Subject: [PATCH] feat: update reconstruct api --- examples/src/status-deserialize-class.js | 27 +++++++++++++------ .../near-sdk-js/lib/collections/subtype.js | 19 ++++++++----- packages/near-sdk-js/lib/utils.js | 12 ++++++--- .../near-sdk-js/src/collections/subtype.ts | 20 ++++++++------ packages/near-sdk-js/src/utils.ts | 11 +++++--- 5 files changed, 58 insertions(+), 31 deletions(-) diff --git a/examples/src/status-deserialize-class.js b/examples/src/status-deserialize-class.js index 270cd1b8c..db8d7fcc0 100644 --- a/examples/src/status-deserialize-class.js +++ b/examples/src/status-deserialize-class.js @@ -28,7 +28,8 @@ class Truck { static schema = { name: "string", speed: "number", - loads: {collection: {reconstructor: UnorderedMap.reconstruct, value: 'string'}} + // loads: {collection: {reconstructor: UnorderedMap.reconstruct, value: 'string'}} + loads: {class: UnorderedMap } }; constructor() { this.name = ""; @@ -41,6 +42,9 @@ class Truck { } } +// sdk should first try if UnorderedMap has a static schema and use it to recursively decode. +// In this case, UnorderedMap doesn't. +// So sdk should next try call UnorderedMap.reconstruct. @NearBindgen({}) export class StatusDeserializeClass { static schema = { @@ -48,13 +52,20 @@ export class StatusDeserializeClass { records: {map: { key: 'string', value: 'string' }}, truck: Truck, messages: {array: {value: 'string'}}, - efficient_recordes: {collection: {reconstructor: UnorderedMap.reconstruct, value: 'string'}}, - nested_efficient_recordes: {collection: {reconstructor: UnorderedMap.reconstruct, value: { collection: {reconstructor: UnorderedMap.reconstruct, value: 'string'}}}}, - nested_lookup_recordes: {collection: {reconstructor: UnorderedMap.reconstruct, value: { collection: {reconstructor: LookupMap.reconstruct, value: 'string'}}}}, - vector_nested_group: {collection: {reconstructor: Vector.reconstruct, value: { collection: {reconstructor: LookupMap.reconstruct, value: 'string'}}}}, - lookup_nest_vec: {collection: {reconstructor: LookupMap.reconstruct, value: { collection: { reconstructor: Vector.reconstruct, value: 'string' }}}}, - unordered_set: {collection: {reconstructor: UnorderedSet.reconstruct, value: 'string'}}, - user_car_map: {collection: {reconstructor: UnorderedMap.reconstruct, value: Car }}, + // efficient_recordes: {class: {reconstructor: UnorderedMap.reconstruct, value: 'string'}}, + efficient_recordes: {class: UnorderedMap}, + // nested_efficient_recordes: {collection: {reconstructor: UnorderedMap.reconstruct, value: { collection: {reconstructor: UnorderedMap.reconstruct, value: 'string'}}}}, + nested_efficient_recordes: {class: UnorderedMap, value: UnorderedMap}, + // nested_lookup_recordes: {collection: {reconstructor: UnorderedMap.reconstruct, value: { collection: {reconstructor: LookupMap.reconstruct, value: 'string'}}}}, + nested_lookup_recordes: {class: UnorderedMap, value: {class: LookupMap }}, + // vector_nested_group: {collection: {reconstructor: Vector.reconstruct, value: { collection: {reconstructor: LookupMap.reconstruct, value: 'string'}}}}, + vector_nested_group: {class: Vector, value: { class: LookupMap }}, + // lookup_nest_vec: {collection: {reconstructor: LookupMap.reconstruct, value: { collection: { reconstructor: Vector.reconstruct, value: 'string' }}}}, + lookup_nest_vec: { class: LookupMap, value: Vector }, + // unordered_set: {collection: {reconstructor: UnorderedSet.reconstruct, value: 'string'}}, + unordered_set: {class: UnorderedSet }, + // user_car_map: {collection: {reconstructor: UnorderedMap.reconstruct, value: Car }}, + user_car_map: {class: UnorderedMap, value: Car }, big_num: 'bigint', date: 'date' }; diff --git a/packages/near-sdk-js/lib/collections/subtype.js b/packages/near-sdk-js/lib/collections/subtype.js index af87b68c3..0b4ee206f 100644 --- a/packages/near-sdk-js/lib/collections/subtype.js +++ b/packages/near-sdk-js/lib/collections/subtype.js @@ -8,14 +8,19 @@ export class SubType { } const subtype = this.subtype(); if (options.reconstructor == undefined && - subtype != undefined && + subtype != undefined) { + if ( // eslint-disable-next-line no-prototype-builtins - subtype.hasOwnProperty("collection") && - typeof this.subtype().collection.reconstructor === "function") { - // { collection: {reconstructor: LookupMap.reconstruct, value: 'string'}} - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - options.reconstructor = this.subtype().collection.reconstructor; + subtype.hasOwnProperty("class") && + typeof subtype.class.reconstructor === "function") { + // { collection: {reconstructor: LookupMap.reconstruct, value: 'string'}} + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + options.reconstructor = subtype.class.reconstructor; + } + else if (subtype.reconstructor === "function") { + options.reconstructor = subtype.reconstructor; + } } return options; } diff --git a/packages/near-sdk-js/lib/utils.js b/packages/near-sdk-js/lib/utils.js index 45e34e83f..b0cfe8b00 100644 --- a/packages/near-sdk-js/lib/utils.js +++ b/packages/near-sdk-js/lib/utils.js @@ -143,7 +143,7 @@ export function deserialize(valueToDeserialize) { }); } export function decodeObj2class(class_instance, obj) { - if (typeof obj != "object" || + if (typeof obj != "object" || typeof obj === "bigint" || obj instanceof Date || class_instance.constructor.schema === undefined) { return obj; } @@ -179,16 +179,20 @@ export function decodeObj2class(class_instance, obj) { } // eslint-disable-next-line no-prototype-builtins } - else if (ty !== undefined && ty.hasOwnProperty("collection")) { + else if (ty !== undefined && ty.hasOwnProperty("class")) { // nested_lookup_recordes: {collection: {reconstructor: UnorderedMap.reconstruct, value: { collection: {reconstructor: LookupMap.reconstruct, value: 'string'}}}}, // {collection: {reconstructor: - class_instance[key] = ty["collection"]["reconstructor"](obj[key]); - const subtype_value = ty["collection"]["value"]; + class_instance[key] = ty["class"].reconstruct(obj[key]); + const subtype_value = ty["value"]; class_instance[key].subtype = function () { // example: { collection: {reconstructor: LookupMap.reconstruct, value: 'string'}} + // example: UnorderedMap return subtype_value; }; } + else if (ty !== undefined && typeof ty.reconstruct === "function") { + class_instance[key] = ty.reconstruct(obj[key]); + } else { // normal case with nested Class, such as field is truck: Truck, class_instance[key] = decodeObj2class(class_instance[key], obj[key]); diff --git a/packages/near-sdk-js/src/collections/subtype.ts b/packages/near-sdk-js/src/collections/subtype.ts index 1b1801624..07cd5944b 100644 --- a/packages/near-sdk-js/src/collections/subtype.ts +++ b/packages/near-sdk-js/src/collections/subtype.ts @@ -14,15 +14,19 @@ export abstract class SubType { const subtype = this.subtype(); if ( options.reconstructor == undefined && - subtype != undefined && - // eslint-disable-next-line no-prototype-builtins - subtype.hasOwnProperty("collection") && - typeof this.subtype().collection.reconstructor === "function" + subtype != undefined ) { - // { collection: {reconstructor: LookupMap.reconstruct, value: 'string'}} - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - options.reconstructor = this.subtype().collection.reconstructor; + if ( + // eslint-disable-next-line no-prototype-builtins + subtype.hasOwnProperty("class") && + typeof subtype.class.reconstructor === "function") { + // { collection: {reconstructor: LookupMap.reconstruct, value: 'string'}} + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + options.reconstructor = subtype.class.reconstructor; + } else if (subtype.reconstructor === "function") { + options.reconstructor = subtype.reconstructor; + } } return options; } diff --git a/packages/near-sdk-js/src/utils.ts b/packages/near-sdk-js/src/utils.ts index f611e0d21..2e3519fcf 100644 --- a/packages/near-sdk-js/src/utils.ts +++ b/packages/near-sdk-js/src/utils.ts @@ -208,7 +208,7 @@ export function deserialize(valueToDeserialize: Uint8Array): unknown { export function decodeObj2class(class_instance, obj) { if ( - typeof obj != "object" || + typeof obj != "object" || typeof obj === "bigint" || obj instanceof Date || class_instance.constructor.schema === undefined ) { return obj; @@ -246,15 +246,18 @@ export function decodeObj2class(class_instance, obj) { } } // eslint-disable-next-line no-prototype-builtins - } else if (ty !== undefined && ty.hasOwnProperty("collection")) { + } else if (ty !== undefined && ty.hasOwnProperty("class")) { // nested_lookup_recordes: {collection: {reconstructor: UnorderedMap.reconstruct, value: { collection: {reconstructor: LookupMap.reconstruct, value: 'string'}}}}, // {collection: {reconstructor: - class_instance[key] = ty["collection"]["reconstructor"](obj[key]); - const subtype_value = ty["collection"]["value"]; + class_instance[key] = ty["class"].reconstruct(obj[key]); + const subtype_value = ty["value"]; class_instance[key].subtype = function () { // example: { collection: {reconstructor: LookupMap.reconstruct, value: 'string'}} + // example: UnorderedMap return subtype_value; }; + } else if (ty !== undefined && typeof ty.reconstruct === "function") { + class_instance[key] = ty.reconstruct(obj[key]); } else { // normal case with nested Class, such as field is truck: Truck, class_instance[key] = decodeObj2class(class_instance[key], obj[key]);