From 1ea2f55fd2b1e0a614d94dfeac25b1a777f5684f Mon Sep 17 00:00:00 2001 From: Lars-Erik Roald Date: Sat, 22 Jun 2024 19:21:40 +0000 Subject: [PATCH 01/15] cloneFromDb --- src/client/cloneFromDb.js | 25 +++++++++++++++++++++++++ src/client/index.js | 34 ++++++++++++++++++---------------- 2 files changed, 43 insertions(+), 16 deletions(-) create mode 100644 src/client/cloneFromDb.js diff --git a/src/client/cloneFromDb.js b/src/client/cloneFromDb.js new file mode 100644 index 00000000..bbe5d382 --- /dev/null +++ b/src/client/cloneFromDb.js @@ -0,0 +1,25 @@ +let dateToISOString = require('../dateToISOString'); + +function cloneFromDb(obj) { + if (obj === null || typeof obj !== 'object') + return obj; + if (Array.isArray(obj)) { + const arrClone = []; + for (let i = 0; i < obj.length; i++) { + arrClone[i] = cloneFromDb(obj[i]); + } + return arrClone; + } + else if (obj instanceof Date && !isNaN(obj)) + return dateToISOString(obj); + const clone = {}; + const keys = Object.keys(obj); + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + clone[key] = cloneFromDb(obj[key]); + } + return clone; +} + + +module.exports = cloneFromDb; \ No newline at end of file diff --git a/src/client/index.js b/src/client/index.js index f0998221..f0531ab6 100644 --- a/src/client/index.js +++ b/src/client/index.js @@ -1,5 +1,6 @@ const createPatch = require('./createPatch'); const stringify = require('./stringify'); +const cloneFromDb = require('./cloneFromDb'); const netAdapter = require('./netAdapter'); const toKeyPositionMap = require('./toKeyPositionMap'); const rootMap = new WeakMap(); @@ -483,7 +484,8 @@ function rdbClient(options = {}) { }; let innerProxy = new Proxy(array, handler); - rootMap.set(array, { json: stringify(array), strategy, originalArray: [...array] }); + //todo + rootMap.set(array, { json: cloneFromDb(array), strategy, originalArray: [...array] }); if (strategy !== undefined) { const { limit, ...cleanStrategy } = { ...strategy }; fetchingStrategyMap.set(array, cleanStrategy); @@ -496,13 +498,13 @@ function rdbClient(options = {}) { get(_target, property,) { if (property === 'save' || property === 'saveChanges') //call server then acceptChanges return saveRow.bind(null, row); - else if (property === 'delete') //call server then remove from jsonMap and original + else if (property === 'delete') //call server then remove from json and original return deleteRow.bind(null, row); else if (property === 'refresh') //refresh from server then acceptChanges return refreshRow.bind(null, row); - else if (property === 'clearChanges') //refresh from jsonMap, update original if present + else if (property === 'clearChanges') //refresh from json, update original if present return clearChangesRow.bind(null, row); - else if (property === 'acceptChanges') //remove from jsonMap + else if (property === 'acceptChanges') //remove from json return acceptChangesRow.bind(null, row); else if (property === 'toJSON') return () => { @@ -516,7 +518,7 @@ function rdbClient(options = {}) { }; let innerProxy = new Proxy(row, handler); - rootMap.set(row, { json: stringify(row), strategy }); + rootMap.set(row, { json: cloneFromDb(row), strategy }); fetchingStrategyMap.set(row, strategy); return innerProxy; } @@ -591,7 +593,7 @@ function rdbClient(options = {}) { strategy = extractFetchingStrategy(array, strategy); let meta = await getMeta(); - const patch = createPatch(JSON.parse(json), array, meta); + const patch = createPatch(json, array, meta); if (patch.length === 0) return; let body = stringify({ patch, options: { strategy, ...tableOptions, ...concurrencyOptions, deduceStrategy } }); @@ -606,7 +608,7 @@ function rdbClient(options = {}) { let insertedPositions = getInsertedRowsPosition(array); let { changed, strategy: newStrategy } = await p; copyIntoArray(changed, array, [...insertedPositions, ...updatedPositions]); - rootMap.set(array, { json: stringify(array), strategy: newStrategy, originalArray: [...array] }); + rootMap.set(array, { json: cloneFromDb(array), strategy: newStrategy, originalArray: [...array] }); } async function patch(patch, concurrencyOptions, strategy) { @@ -686,13 +688,13 @@ function rdbClient(options = {}) { function clearChangesArray(array) { let { json } = rootMap.get(array); - let old = JSON.parse(json); + let old = cloneFromDb(json); array.splice(0, old.length, ...old); } function acceptChangesArray(array) { const map = rootMap.get(array); - map.json = stringify(array); + map.json = cloneFromDb(array); map.originalArray = [...array]; } @@ -705,7 +707,7 @@ function rdbClient(options = {}) { let adapter = netAdapter(url, tableName, { axios: axiosInterceptor, tableOptions }); let { strategy } = await adapter.patch(body); array.length = 0; - rootMap.set(array, { jsonMap: stringify(array), strategy }); + rootMap.set(array, { json: cloneFromDb(array), strategy }); } function setMapValue(rowsMap, keys, row, index) { @@ -768,7 +770,7 @@ function rdbClient(options = {}) { array.splice(i + offset, 1); offset--; } - rootMap.set(array, { json: stringify(array), strategy, originalArray: [...array] }); + rootMap.set(array, { json: cloneFromDb(array), strategy, originalArray: [...array] }); fetchingStrategyMap.set(array, strategy); } @@ -794,7 +796,7 @@ function rdbClient(options = {}) { return; let meta = await getMeta(); - let patch = createPatch([JSON.parse(json)], [row], meta); + let patch = createPatch([json], [row], meta); if (patch.length === 0) return; @@ -803,7 +805,7 @@ function rdbClient(options = {}) { let adapter = netAdapter(url, tableName, { axios: axiosInterceptor, tableOptions }); let { changed, strategy: newStrategy } = await adapter.patch(body); copyInto(changed, [row]); - rootMap.set(row, { json: stringify(row), strategy: newStrategy }); + rootMap.set(row, { json: cloneFromDb(row), strategy: newStrategy }); } async function refreshRow(row, strategy) { @@ -827,20 +829,20 @@ function rdbClient(options = {}) { for (let p in rows[0]) { row[p] = rows[0][p]; } - rootMap.set(row, { json: stringify(row), strategy }); + rootMap.set(row, { json: cloneFromDb(row), strategy }); fetchingStrategyMap.set(row, strategy); } function acceptChangesRow(row) { const { strategy } = rootMap.get(row); - rootMap.set(row, { json: stringify(row), strategy }); + rootMap.set(row, { json: cloneFromDb(row), strategy }); } function clearChangesRow(row) { let { json } = rootMap.get(row); if (!json) return; - let old = JSON.parse(json); + let old = cloneFromDb(json); for (let p in row) { delete row[p]; } From f3b3adfb24c76ce188e324127cfcace8e61a131b Mon Sep 17 00:00:00 2001 From: Lars-Erik Roald Date: Sat, 22 Jun 2024 19:22:52 +0000 Subject: [PATCH 02/15] getManyDto --- src/getManyDto.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/getManyDto.js b/src/getManyDto.js index c4b45454..87d1c25b 100644 --- a/src/getManyDto.js +++ b/src/getManyDto.js @@ -123,19 +123,19 @@ async function decode(strategy, span, rows, keys = rows.length > 0 ? Object.keys } const column = columns[j]; outRow[column.alias] = column.decode(row[keys[j]]); - if (shouldCreateMap) - fkIds[i] = getIds(outRow); } - + for (let j = 0; j < aggregateKeys.length; j++) { const key = aggregateKeys[j]; const parse = span.aggregates[key].column?.decode || Number.parseFloat; outRow[key] = parse(row[keys[j+columnsLength]]); } - + outRows[i] = outRow; - if (shouldCreateMap) + if (shouldCreateMap) { + fkIds[i] = getIds(outRow); addToMap(rowsMap, primaryColumns, outRow); + } } span._rowsMap = rowsMap; span._ids = fkIds; From 9f14fe945d98e99c13950218ebd4f1a6bf5a3ce9 Mon Sep 17 00:00:00 2001 From: Lars-Erik Roald Date: Sat, 22 Jun 2024 19:41:23 +0000 Subject: [PATCH 03/15] lint --- src/client/cloneFromDb.js | 36 ++++++++++++++++++------------------ src/client/index.js | 2 +- src/getManyDto.js | 4 ++-- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/client/cloneFromDb.js b/src/client/cloneFromDb.js index bbe5d382..010f7075 100644 --- a/src/client/cloneFromDb.js +++ b/src/client/cloneFromDb.js @@ -1,24 +1,24 @@ let dateToISOString = require('../dateToISOString'); function cloneFromDb(obj) { - if (obj === null || typeof obj !== 'object') - return obj; - if (Array.isArray(obj)) { - const arrClone = []; - for (let i = 0; i < obj.length; i++) { - arrClone[i] = cloneFromDb(obj[i]); - } - return arrClone; - } - else if (obj instanceof Date && !isNaN(obj)) - return dateToISOString(obj); - const clone = {}; - const keys = Object.keys(obj); - for (let i = 0; i < keys.length; i++) { - const key = keys[i]; - clone[key] = cloneFromDb(obj[key]); - } - return clone; + if (obj === null || typeof obj !== 'object') + return obj; + if (Array.isArray(obj)) { + const arrClone = []; + for (let i = 0; i < obj.length; i++) { + arrClone[i] = cloneFromDb(obj[i]); + } + return arrClone; + } + else if (obj instanceof Date && !isNaN(obj)) + return dateToISOString(obj); + const clone = {}; + const keys = Object.keys(obj); + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + clone[key] = cloneFromDb(obj[key]); + } + return clone; } diff --git a/src/client/index.js b/src/client/index.js index f0531ab6..ea8fcca2 100644 --- a/src/client/index.js +++ b/src/client/index.js @@ -484,7 +484,7 @@ function rdbClient(options = {}) { }; let innerProxy = new Proxy(array, handler); - //todo + //todo rootMap.set(array, { json: cloneFromDb(array), strategy, originalArray: [...array] }); if (strategy !== undefined) { const { limit, ...cleanStrategy } = { ...strategy }; diff --git a/src/getManyDto.js b/src/getManyDto.js index 87d1c25b..4ac37479 100644 --- a/src/getManyDto.js +++ b/src/getManyDto.js @@ -124,13 +124,13 @@ async function decode(strategy, span, rows, keys = rows.length > 0 ? Object.keys const column = columns[j]; outRow[column.alias] = column.decode(row[keys[j]]); } - + for (let j = 0; j < aggregateKeys.length; j++) { const key = aggregateKeys[j]; const parse = span.aggregates[key].column?.decode || Number.parseFloat; outRow[key] = parse(row[keys[j+columnsLength]]); } - + outRows[i] = outRow; if (shouldCreateMap) { fkIds[i] = getIds(outRow); From a7542fa1e8ce2afb3a644073b593fac380659f42 Mon Sep 17 00:00:00 2001 From: Lars-Erik Roald Date: Sat, 22 Jun 2024 22:11:30 +0200 Subject: [PATCH 04/15] beta --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 57950814..780c2f15 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "orange-orm", - "version": "4.1.4", + "version": "4.2.0-beta.1", "main": "./src/index.js", "browser": "./src/client/index.mjs", "bin": { From b41f6828ae83fa2803fc1513dd78e0d9feaf21e8 Mon Sep 17 00:00:00 2001 From: Lars-Erik Roald Date: Sun, 23 Jun 2024 08:37:17 +0000 Subject: [PATCH 05/15] fastStringify --- src/client/index.js | 48 ++++++++++++++++++++++----------------------- src/getManyDto.js | 5 ++--- 2 files changed, 25 insertions(+), 28 deletions(-) diff --git a/src/client/index.js b/src/client/index.js index ea8fcca2..ca953350 100644 --- a/src/client/index.js +++ b/src/client/index.js @@ -1,6 +1,5 @@ const createPatch = require('./createPatch'); const stringify = require('./stringify'); -const cloneFromDb = require('./cloneFromDb'); const netAdapter = require('./netAdapter'); const toKeyPositionMap = require('./toKeyPositionMap'); const rootMap = new WeakMap(); @@ -229,7 +228,7 @@ function rdbClient(options = {}) { let args = [_, strategy].concat(Array.prototype.slice.call(arguments).slice(2)); let rows = await getManyCore.apply(null, args); await metaPromise; - return proxify(rows, strategy); + return proxify(rows, strategy, {fastStringify : true}); } async function groupBy(strategy) { @@ -261,7 +260,7 @@ function rdbClient(options = {}) { await metaPromise; if (rows.length === 0) return; - return proxify(rows[0], strategy); + return proxify(rows[0], strategy, {fastStringify : true}); } async function getById() { @@ -449,14 +448,14 @@ function rdbClient(options = {}) { } - function proxify(itemOrArray, strategy) { + function proxify(itemOrArray, strategy, options) { if (Array.isArray(itemOrArray)) - return proxifyArray(itemOrArray, strategy); + return proxifyArray(itemOrArray, strategy, options); else - return proxifyRow(itemOrArray, strategy); + return proxifyRow(itemOrArray, strategy, options); } - function proxifyArray(array, strategy) { + function proxifyArray(array, strategy, { fastStringify } = {}) { let _array = array; if (_reactive) array = _reactive(array); @@ -484,8 +483,7 @@ function rdbClient(options = {}) { }; let innerProxy = new Proxy(array, handler); - //todo - rootMap.set(array, { json: cloneFromDb(array), strategy, originalArray: [...array] }); + rootMap.set(array, { json: fastStringify ? JSON.stringify(array) : stringify(array), strategy, originalArray: [...array] }); if (strategy !== undefined) { const { limit, ...cleanStrategy } = { ...strategy }; fetchingStrategyMap.set(array, cleanStrategy); @@ -493,18 +491,18 @@ function rdbClient(options = {}) { return innerProxy; } - function proxifyRow(row, strategy) { + function proxifyRow(row, strategy, { fastStringify } = {}) { let handler = { get(_target, property,) { if (property === 'save' || property === 'saveChanges') //call server then acceptChanges return saveRow.bind(null, row); - else if (property === 'delete') //call server then remove from json and original + else if (property === 'delete') //call server then remove from jsonMap and original return deleteRow.bind(null, row); else if (property === 'refresh') //refresh from server then acceptChanges return refreshRow.bind(null, row); - else if (property === 'clearChanges') //refresh from json, update original if present + else if (property === 'clearChanges') //refresh from jsonMap, update original if present return clearChangesRow.bind(null, row); - else if (property === 'acceptChanges') //remove from json + else if (property === 'acceptChanges') //remove from jsonMap return acceptChangesRow.bind(null, row); else if (property === 'toJSON') return () => { @@ -518,7 +516,7 @@ function rdbClient(options = {}) { }; let innerProxy = new Proxy(row, handler); - rootMap.set(row, { json: cloneFromDb(row), strategy }); + rootMap.set(row, { json: fastStringify ? JSON.stringify(row) : stringify(row), strategy }); fetchingStrategyMap.set(row, strategy); return innerProxy; } @@ -593,7 +591,7 @@ function rdbClient(options = {}) { strategy = extractFetchingStrategy(array, strategy); let meta = await getMeta(); - const patch = createPatch(json, array, meta); + const patch = createPatch(JSON.parse(json), array, meta); if (patch.length === 0) return; let body = stringify({ patch, options: { strategy, ...tableOptions, ...concurrencyOptions, deduceStrategy } }); @@ -608,7 +606,7 @@ function rdbClient(options = {}) { let insertedPositions = getInsertedRowsPosition(array); let { changed, strategy: newStrategy } = await p; copyIntoArray(changed, array, [...insertedPositions, ...updatedPositions]); - rootMap.set(array, { json: cloneFromDb(array), strategy: newStrategy, originalArray: [...array] }); + rootMap.set(array, { json: stringify(array), strategy: newStrategy, originalArray: [...array] }); } async function patch(patch, concurrencyOptions, strategy) { @@ -688,13 +686,13 @@ function rdbClient(options = {}) { function clearChangesArray(array) { let { json } = rootMap.get(array); - let old = cloneFromDb(json); + let old = JSON.parse(json); array.splice(0, old.length, ...old); } function acceptChangesArray(array) { const map = rootMap.get(array); - map.json = cloneFromDb(array); + map.json = stringify(array); map.originalArray = [...array]; } @@ -707,7 +705,7 @@ function rdbClient(options = {}) { let adapter = netAdapter(url, tableName, { axios: axiosInterceptor, tableOptions }); let { strategy } = await adapter.patch(body); array.length = 0; - rootMap.set(array, { json: cloneFromDb(array), strategy }); + rootMap.set(array, { jsonMap: stringify(array), strategy }); } function setMapValue(rowsMap, keys, row, index) { @@ -770,7 +768,7 @@ function rdbClient(options = {}) { array.splice(i + offset, 1); offset--; } - rootMap.set(array, { json: cloneFromDb(array), strategy, originalArray: [...array] }); + rootMap.set(array, { json: stringify(array), strategy, originalArray: [...array] }); fetchingStrategyMap.set(array, strategy); } @@ -796,7 +794,7 @@ function rdbClient(options = {}) { return; let meta = await getMeta(); - let patch = createPatch([json], [row], meta); + let patch = createPatch([JSON.parse(json)], [row], meta); if (patch.length === 0) return; @@ -805,7 +803,7 @@ function rdbClient(options = {}) { let adapter = netAdapter(url, tableName, { axios: axiosInterceptor, tableOptions }); let { changed, strategy: newStrategy } = await adapter.patch(body); copyInto(changed, [row]); - rootMap.set(row, { json: cloneFromDb(row), strategy: newStrategy }); + rootMap.set(row, { json: stringify(row), strategy: newStrategy }); } async function refreshRow(row, strategy) { @@ -829,20 +827,20 @@ function rdbClient(options = {}) { for (let p in rows[0]) { row[p] = rows[0][p]; } - rootMap.set(row, { json: cloneFromDb(row), strategy }); + rootMap.set(row, { json: stringify(row), strategy }); fetchingStrategyMap.set(row, strategy); } function acceptChangesRow(row) { const { strategy } = rootMap.get(row); - rootMap.set(row, { json: cloneFromDb(row), strategy }); + rootMap.set(row, { json: stringify(row), strategy }); } function clearChangesRow(row) { let { json } = rootMap.get(row); if (!json) return; - let old = cloneFromDb(json); + let old = JSON.parse(json); for (let p in row) { delete row[p]; } diff --git a/src/getManyDto.js b/src/getManyDto.js index 4ac37479..4b7c37fb 100644 --- a/src/getManyDto.js +++ b/src/getManyDto.js @@ -140,9 +140,8 @@ async function decode(strategy, span, rows, keys = rows.length > 0 ? Object.keys span._rowsMap = rowsMap; span._ids = fkIds; - for (let i = 0; i < columnsLength + aggregateKeys.length; i++) { - keys.shift(); - } + keys.splice(0, columnsLength + aggregateKeys.length); + await decodeRelations(strategy, span, rows, outRows, keys); return outRows; From d6ada5268f0b1a649478bc197cb994aa382d6326 Mon Sep 17 00:00:00 2001 From: Lars-Erik Roald Date: Sun, 23 Jun 2024 08:39:54 +0000 Subject: [PATCH 06/15] beta 2 --- package.json | 2 +- src/client/index.mjs | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 57950814..9146e881 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "orange-orm", - "version": "4.1.4", + "version": "4.2.0-beta.2", "main": "./src/index.js", "browser": "./src/client/index.mjs", "bin": { diff --git a/src/client/index.mjs b/src/client/index.mjs index 47d22066..ffcbf5b4 100644 --- a/src/client/index.mjs +++ b/src/client/index.mjs @@ -3607,7 +3607,7 @@ function isAbsoluteURL(url) { */ function combineURLs(baseURL, relativeURL) { return relativeURL - ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '') + ? baseURL.replace(/\/?\/$/, '') + '/' + relativeURL.replace(/^\/+/, '') : baseURL; } @@ -4241,7 +4241,7 @@ function mergeConfig(config1, config2) { return config; } -const VERSION = "1.6.2"; +const VERSION = "1.6.3"; const validators$1 = {}; @@ -4857,7 +4857,7 @@ function httpAdapter(baseURL, path, axiosInterceptor) { const res = await axios.request(path, { headers, method: 'patch', data: body }); return res.data; } - catch (e) { + catch (e) { if (typeof e.response?.data === 'string') throw new Error(e.response.data.replace(/^Error: /, '')); else @@ -5524,7 +5524,7 @@ function rdbClient(options = {}) { let args = [_, strategy].concat(Array.prototype.slice.call(arguments).slice(2)); let rows = await getManyCore.apply(null, args); await metaPromise; - return proxify(rows, strategy); + return proxify(rows, strategy, {fastStringify : true}); } async function groupBy(strategy) { @@ -5556,7 +5556,7 @@ function rdbClient(options = {}) { await metaPromise; if (rows.length === 0) return; - return proxify(rows[0], strategy); + return proxify(rows[0], strategy, {fastStringify : true}); } async function getById() { @@ -5744,14 +5744,14 @@ function rdbClient(options = {}) { } - function proxify(itemOrArray, strategy) { + function proxify(itemOrArray, strategy, options) { if (Array.isArray(itemOrArray)) - return proxifyArray(itemOrArray, strategy); + return proxifyArray(itemOrArray, strategy, options); else - return proxifyRow(itemOrArray, strategy); + return proxifyRow(itemOrArray, strategy, options); } - function proxifyArray(array, strategy) { + function proxifyArray(array, strategy, { fastStringify } = {}) { let _array = array; if (_reactive) array = _reactive(array); @@ -5779,7 +5779,7 @@ function rdbClient(options = {}) { }; let innerProxy = new Proxy(array, handler); - rootMap.set(array, { json: stringify(array), strategy, originalArray: [...array] }); + rootMap.set(array, { json: fastStringify ? JSON.stringify(array) : stringify(array), strategy, originalArray: [...array] }); if (strategy !== undefined) { const { limit, ...cleanStrategy } = { ...strategy }; fetchingStrategyMap.set(array, cleanStrategy); @@ -5787,7 +5787,7 @@ function rdbClient(options = {}) { return innerProxy; } - function proxifyRow(row, strategy) { + function proxifyRow(row, strategy, { fastStringify } = {}) { let handler = { get(_target, property,) { if (property === 'save' || property === 'saveChanges') //call server then acceptChanges @@ -5812,7 +5812,7 @@ function rdbClient(options = {}) { }; let innerProxy = new Proxy(row, handler); - rootMap.set(row, { json: stringify(row), strategy }); + rootMap.set(row, { json: fastStringify ? JSON.stringify(row) : stringify(row), strategy }); fetchingStrategyMap.set(row, strategy); return innerProxy; } From 37cbfc3cf9ee9c4ddd71fd94d270044f07928dd7 Mon Sep 17 00:00:00 2001 From: Lars-Erik Roald Date: Sun, 23 Jun 2024 09:34:57 +0000 Subject: [PATCH 07/15] structuredClone --- package.json | 2 +- src/client/index.js | 42 ++++++++++++++++++++++-------------------- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index 9146e881..9101a62d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "orange-orm", - "version": "4.2.0-beta.2", + "version": "4.2.0-beta.3", "main": "./src/index.js", "browser": "./src/client/index.mjs", "bin": { diff --git a/src/client/index.js b/src/client/index.js index ca953350..bd0574d9 100644 --- a/src/client/index.js +++ b/src/client/index.js @@ -1,5 +1,6 @@ const createPatch = require('./createPatch'); const stringify = require('./stringify'); +const cloneFromDb = require('./cloneFromDb'); const netAdapter = require('./netAdapter'); const toKeyPositionMap = require('./toKeyPositionMap'); const rootMap = new WeakMap(); @@ -228,7 +229,7 @@ function rdbClient(options = {}) { let args = [_, strategy].concat(Array.prototype.slice.call(arguments).slice(2)); let rows = await getManyCore.apply(null, args); await metaPromise; - return proxify(rows, strategy, {fastStringify : true}); + return proxify(rows, strategy, {fast: true}); } async function groupBy(strategy) { @@ -260,7 +261,7 @@ function rdbClient(options = {}) { await metaPromise; if (rows.length === 0) return; - return proxify(rows[0], strategy, {fastStringify : true}); + return proxify(rows[0], strategy, {fast: true}); } async function getById() { @@ -455,7 +456,7 @@ function rdbClient(options = {}) { return proxifyRow(itemOrArray, strategy, options); } - function proxifyArray(array, strategy, { fastStringify } = {}) { + function proxifyArray(array, strategy, { fast } = { }) { let _array = array; if (_reactive) array = _reactive(array); @@ -483,7 +484,8 @@ function rdbClient(options = {}) { }; let innerProxy = new Proxy(array, handler); - rootMap.set(array, { json: fastStringify ? JSON.stringify(array) : stringify(array), strategy, originalArray: [...array] }); + //todo + rootMap.set(array, { json: fast ? structuredClone(array) : cloneFromDb(array), strategy, originalArray: [...array] }); if (strategy !== undefined) { const { limit, ...cleanStrategy } = { ...strategy }; fetchingStrategyMap.set(array, cleanStrategy); @@ -491,18 +493,18 @@ function rdbClient(options = {}) { return innerProxy; } - function proxifyRow(row, strategy, { fastStringify } = {}) { + function proxifyRow(row, strategy, { fast } = {}) { let handler = { get(_target, property,) { if (property === 'save' || property === 'saveChanges') //call server then acceptChanges return saveRow.bind(null, row); - else if (property === 'delete') //call server then remove from jsonMap and original + else if (property === 'delete') //call server then remove from json and original return deleteRow.bind(null, row); else if (property === 'refresh') //refresh from server then acceptChanges return refreshRow.bind(null, row); - else if (property === 'clearChanges') //refresh from jsonMap, update original if present + else if (property === 'clearChanges') //refresh from json, update original if present return clearChangesRow.bind(null, row); - else if (property === 'acceptChanges') //remove from jsonMap + else if (property === 'acceptChanges') //remove from json return acceptChangesRow.bind(null, row); else if (property === 'toJSON') return () => { @@ -516,7 +518,7 @@ function rdbClient(options = {}) { }; let innerProxy = new Proxy(row, handler); - rootMap.set(row, { json: fastStringify ? JSON.stringify(row) : stringify(row), strategy }); + rootMap.set(row, { json: fast ? structuredClone(row) : cloneFromDb(row), strategy }); fetchingStrategyMap.set(row, strategy); return innerProxy; } @@ -591,7 +593,7 @@ function rdbClient(options = {}) { strategy = extractFetchingStrategy(array, strategy); let meta = await getMeta(); - const patch = createPatch(JSON.parse(json), array, meta); + const patch = createPatch(json, array, meta); if (patch.length === 0) return; let body = stringify({ patch, options: { strategy, ...tableOptions, ...concurrencyOptions, deduceStrategy } }); @@ -606,7 +608,7 @@ function rdbClient(options = {}) { let insertedPositions = getInsertedRowsPosition(array); let { changed, strategy: newStrategy } = await p; copyIntoArray(changed, array, [...insertedPositions, ...updatedPositions]); - rootMap.set(array, { json: stringify(array), strategy: newStrategy, originalArray: [...array] }); + rootMap.set(array, { json: cloneFromDb(array), strategy: newStrategy, originalArray: [...array] }); } async function patch(patch, concurrencyOptions, strategy) { @@ -686,13 +688,13 @@ function rdbClient(options = {}) { function clearChangesArray(array) { let { json } = rootMap.get(array); - let old = JSON.parse(json); + let old = cloneFromDb(json); array.splice(0, old.length, ...old); } function acceptChangesArray(array) { const map = rootMap.get(array); - map.json = stringify(array); + map.json = cloneFromDb(array); map.originalArray = [...array]; } @@ -705,7 +707,7 @@ function rdbClient(options = {}) { let adapter = netAdapter(url, tableName, { axios: axiosInterceptor, tableOptions }); let { strategy } = await adapter.patch(body); array.length = 0; - rootMap.set(array, { jsonMap: stringify(array), strategy }); + rootMap.set(array, { json: cloneFromDb(array), strategy }); } function setMapValue(rowsMap, keys, row, index) { @@ -768,7 +770,7 @@ function rdbClient(options = {}) { array.splice(i + offset, 1); offset--; } - rootMap.set(array, { json: stringify(array), strategy, originalArray: [...array] }); + rootMap.set(array, { json: cloneFromDb(array), strategy, originalArray: [...array] }); fetchingStrategyMap.set(array, strategy); } @@ -794,7 +796,7 @@ function rdbClient(options = {}) { return; let meta = await getMeta(); - let patch = createPatch([JSON.parse(json)], [row], meta); + let patch = createPatch([json], [row], meta); if (patch.length === 0) return; @@ -803,7 +805,7 @@ function rdbClient(options = {}) { let adapter = netAdapter(url, tableName, { axios: axiosInterceptor, tableOptions }); let { changed, strategy: newStrategy } = await adapter.patch(body); copyInto(changed, [row]); - rootMap.set(row, { json: stringify(row), strategy: newStrategy }); + rootMap.set(row, { json: cloneFromDb(row), strategy: newStrategy }); } async function refreshRow(row, strategy) { @@ -827,20 +829,20 @@ function rdbClient(options = {}) { for (let p in rows[0]) { row[p] = rows[0][p]; } - rootMap.set(row, { json: stringify(row), strategy }); + rootMap.set(row, { json: cloneFromDb(row), strategy }); fetchingStrategyMap.set(row, strategy); } function acceptChangesRow(row) { const { strategy } = rootMap.get(row); - rootMap.set(row, { json: stringify(row), strategy }); + rootMap.set(row, { json: cloneFromDb(row), strategy }); } function clearChangesRow(row) { let { json } = rootMap.get(row); if (!json) return; - let old = JSON.parse(json); + let old = cloneFromDb(json); for (let p in row) { delete row[p]; } From 70de078c55eef5cba5bbd815d3216736c4bcba6d Mon Sep 17 00:00:00 2001 From: Lars-Erik Roald Date: Sun, 23 Jun 2024 10:01:57 +0000 Subject: [PATCH 08/15] fromDbFast --- package.json | 2 +- src/client/index.js | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 9101a62d..917a3ed0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "orange-orm", - "version": "4.2.0-beta.3", + "version": "4.2.0-beta.4", "main": "./src/index.js", "browser": "./src/client/index.mjs", "bin": { diff --git a/src/client/index.js b/src/client/index.js index bd0574d9..b6194bf3 100644 --- a/src/client/index.js +++ b/src/client/index.js @@ -229,7 +229,7 @@ function rdbClient(options = {}) { let args = [_, strategy].concat(Array.prototype.slice.call(arguments).slice(2)); let rows = await getManyCore.apply(null, args); await metaPromise; - return proxify(rows, strategy, {fast: true}); + return proxify(rows, strategy, true); } async function groupBy(strategy) { @@ -261,7 +261,7 @@ function rdbClient(options = {}) { await metaPromise; if (rows.length === 0) return; - return proxify(rows[0], strategy, {fast: true}); + return proxify(rows[0], strategy, true); } async function getById() { @@ -449,14 +449,14 @@ function rdbClient(options = {}) { } - function proxify(itemOrArray, strategy, options) { + function proxify(itemOrArray, strategy, fast) { if (Array.isArray(itemOrArray)) - return proxifyArray(itemOrArray, strategy, options); + return proxifyArray(itemOrArray, strategy, fast); else - return proxifyRow(itemOrArray, strategy, options); + return proxifyRow(itemOrArray, strategy, fast); } - function proxifyArray(array, strategy, { fast } = { }) { + function proxifyArray(array, strategy, fast) { let _array = array; if (_reactive) array = _reactive(array); @@ -485,7 +485,7 @@ function rdbClient(options = {}) { }; let innerProxy = new Proxy(array, handler); //todo - rootMap.set(array, { json: fast ? structuredClone(array) : cloneFromDb(array), strategy, originalArray: [...array] }); + rootMap.set(array, { json: cloneFromDb(array, fast), strategy, originalArray: [...array] }); if (strategy !== undefined) { const { limit, ...cleanStrategy } = { ...strategy }; fetchingStrategyMap.set(array, cleanStrategy); @@ -493,7 +493,7 @@ function rdbClient(options = {}) { return innerProxy; } - function proxifyRow(row, strategy, { fast } = {}) { + function proxifyRow(row, strategy, fast) { let handler = { get(_target, property,) { if (property === 'save' || property === 'saveChanges') //call server then acceptChanges @@ -518,7 +518,7 @@ function rdbClient(options = {}) { }; let innerProxy = new Proxy(row, handler); - rootMap.set(row, { json: fast ? structuredClone(row) : cloneFromDb(row), strategy }); + rootMap.set(row, { json: cloneFromDb(row, fast), strategy }); fetchingStrategyMap.set(row, strategy); return innerProxy; } From f94b2089ec3e86e407433cbfdee38c2e9ac06645 Mon Sep 17 00:00:00 2001 From: Lars-Erik Roald Date: Sun, 23 Jun 2024 10:02:50 +0000 Subject: [PATCH 09/15] clonefromdb --- src/client/cloneFromDb.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/client/cloneFromDb.js b/src/client/cloneFromDb.js index 010f7075..5398fb83 100644 --- a/src/client/cloneFromDb.js +++ b/src/client/cloneFromDb.js @@ -1,12 +1,18 @@ let dateToISOString = require('../dateToISOString'); -function cloneFromDb(obj) { +function cloneFromDbFast(obj) { + if (obj === null || typeof obj !== 'object') return obj; + if (Array.isArray(obj)) return obj.map(cloneFromDbFast); + return Object.fromEntries(Object.entries(obj).map(([key, value]) => [key, cloneFromDbFast(value)])); +} + +function cloneRegular(obj) { if (obj === null || typeof obj !== 'object') return obj; if (Array.isArray(obj)) { const arrClone = []; for (let i = 0; i < obj.length; i++) { - arrClone[i] = cloneFromDb(obj[i]); + arrClone[i] = cloneRegular(obj[i]); } return arrClone; } @@ -16,10 +22,16 @@ function cloneFromDb(obj) { const keys = Object.keys(obj); for (let i = 0; i < keys.length; i++) { const key = keys[i]; - clone[key] = cloneFromDb(obj[key]); + clone[key] = cloneRegular(obj[key]); } return clone; } +function cloneFromDb(obj, isFast) { + if (isFast) + return cloneFromDbFast(obj); + else + return cloneRegular(obj); +} module.exports = cloneFromDb; \ No newline at end of file From 693fdff698f658d43b3aaeddad4e7382ea6ede48 Mon Sep 17 00:00:00 2001 From: Lars-Erik Roald Date: Mon, 24 Jun 2024 10:55:46 +0000 Subject: [PATCH 10/15] beta 5 --- package.json | 2 +- src/client/cloneFromDb.js | 19 ++++++++++++++++--- src/client/index.js | 40 +++++++++++++++++++++++++++++++++++---- 3 files changed, 53 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 917a3ed0..d6d82dc7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "orange-orm", - "version": "4.2.0-beta.4", + "version": "4.2.0-beta.5", "main": "./src/index.js", "browser": "./src/client/index.mjs", "bin": { diff --git a/src/client/cloneFromDb.js b/src/client/cloneFromDb.js index 5398fb83..427bc46d 100644 --- a/src/client/cloneFromDb.js +++ b/src/client/cloneFromDb.js @@ -1,9 +1,22 @@ let dateToISOString = require('../dateToISOString'); function cloneFromDbFast(obj) { - if (obj === null || typeof obj !== 'object') return obj; - if (Array.isArray(obj)) return obj.map(cloneFromDbFast); - return Object.fromEntries(Object.entries(obj).map(([key, value]) => [key, cloneFromDbFast(value)])); + if (obj === null || typeof obj !== 'object') + return obj; + if (Array.isArray(obj)) { + const arrClone = []; + for (let i = 0; i < obj.length; i++) { + arrClone[i] = cloneFromDbFast(obj[i]); + } + return arrClone; + } + const clone = {}; + const keys = Object.keys(obj); + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + clone[key] = cloneFromDbFast(obj[key]); + } + return clone; } function cloneRegular(obj) { diff --git a/src/client/index.js b/src/client/index.js index b6194bf3..8db4d52a 100644 --- a/src/client/index.js +++ b/src/client/index.js @@ -483,9 +483,12 @@ function rdbClient(options = {}) { } }; - let innerProxy = new Proxy(array, handler); + + let watcher = onChange(array, () => { + rootMap.set(array, { json: cloneFromDb(array, fast), strategy, originalArray: [...array] }); + }); + let innerProxy = new Proxy(watcher, handler); //todo - rootMap.set(array, { json: cloneFromDb(array, fast), strategy, originalArray: [...array] }); if (strategy !== undefined) { const { limit, ...cleanStrategy } = { ...strategy }; fetchingStrategyMap.set(array, cleanStrategy); @@ -517,8 +520,10 @@ function rdbClient(options = {}) { } }; - let innerProxy = new Proxy(row, handler); - rootMap.set(row, { json: cloneFromDb(row, fast), strategy }); + let watcher = onChange(row, () => { + rootMap.set(row, { json: cloneFromDb(row, fast), strategy }); + }); + let innerProxy = new Proxy(watcher, handler); fetchingStrategyMap.set(row, strategy); return innerProxy; } @@ -1004,4 +1009,31 @@ function column(path, ...previous) { } +function onChange(target, onChange) { + + let notified = false; + const handler = { + get(target, prop, receiver) { + const value = Reflect.get(target, prop, receiver); + if (typeof value === 'object' && value !== null) { + return new Proxy(value, handler); + } + return value; + }, + set(target, prop, value, receiver) { + if (!notified) { + notified = true; + onChange(JSON.stringify(target)); + } + return Reflect.set(target, prop, value, receiver); + + } + + + }; + + return new Proxy(target, handler); +} + + module.exports = rdbClient(); \ No newline at end of file From 9d3ee2a4066399f1b9076c730724385135123b96 Mon Sep 17 00:00:00 2001 From: Lars-Erik Roald Date: Mon, 24 Jun 2024 13:18:20 +0200 Subject: [PATCH 11/15] null check --- src/client/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/index.js b/src/client/index.js index 8db4d52a..e2032e6e 100644 --- a/src/client/index.js +++ b/src/client/index.js @@ -844,7 +844,7 @@ function rdbClient(options = {}) { } function clearChangesRow(row) { - let { json } = rootMap.get(row); + let json = rootMap.get(row)?.json; if (!json) return; let old = cloneFromDb(json); From 6afc2ce24cc00edca9fbfa34c5fa07e8589f7cf8 Mon Sep 17 00:00:00 2001 From: Lars-Erik Roald Date: Mon, 24 Jun 2024 12:00:40 +0000 Subject: [PATCH 12/15] fixes --- src/client/index.js | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/client/index.js b/src/client/index.js index 8db4d52a..9f2a1a31 100644 --- a/src/client/index.js +++ b/src/client/index.js @@ -593,7 +593,9 @@ function rdbClient(options = {}) { async function saveArray(array, concurrencyOptions, strategy) { let deduceStrategy = false; - let { json } = rootMap.get(array); + let json = rootMap.get(array)?.json; + if (!json) + return; strategy = extractStrategy({ strategy }, array); strategy = extractFetchingStrategy(array, strategy); @@ -673,7 +675,7 @@ function rdbClient(options = {}) { return options.strategy; if (obj) { let context = rootMap.get(obj); - if (context.strategy !== undefined) { + if (context?.strategy !== undefined) { // @ts-ignore let { limit, ...strategy } = { ...context.strategy }; return strategy; @@ -692,13 +694,17 @@ function rdbClient(options = {}) { } function clearChangesArray(array) { - let { json } = rootMap.get(array); + let json = rootMap.get(array)?.json; + if (!json) + return; let old = cloneFromDb(json); array.splice(0, old.length, ...old); } function acceptChangesArray(array) { const map = rootMap.get(array); + if (!map) + return; map.json = cloneFromDb(array); map.originalArray = [...array]; } @@ -796,7 +802,7 @@ function rdbClient(options = {}) { strategy = extractStrategy({ strategy }, row); strategy = extractFetchingStrategy(row, strategy); - let { json } = rootMap.get(row); + let json = rootMap.get(row)?.json; if (!json) return; let meta = await getMeta(); @@ -839,12 +845,15 @@ function rdbClient(options = {}) { } function acceptChangesRow(row) { - const { strategy } = rootMap.get(row); + const data = rootMap.get(row); + if (!data) + return; + const { strategy } = data; rootMap.set(row, { json: cloneFromDb(row), strategy }); } function clearChangesRow(row) { - let { json } = rootMap.get(row); + let json = rootMap.get(row)?.json; if (!json) return; let old = cloneFromDb(json); From 415197500fc1eac1c904e76b91da9407688843fb Mon Sep 17 00:00:00 2001 From: Lars-Erik Roald Date: Mon, 24 Jun 2024 12:06:52 +0000 Subject: [PATCH 13/15] client --- src/client/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/index.js b/src/client/index.js index 9f2a1a31..c1f93ae6 100644 --- a/src/client/index.js +++ b/src/client/index.js @@ -595,7 +595,7 @@ function rdbClient(options = {}) { let deduceStrategy = false; let json = rootMap.get(array)?.json; if (!json) - return; + return; strategy = extractStrategy({ strategy }, array); strategy = extractFetchingStrategy(array, strategy); From 71cf06c097f43cd76b1001d2524b68aa4f1904a0 Mon Sep 17 00:00:00 2001 From: Lars-Erik Roald Date: Tue, 25 Jun 2024 07:08:27 +0000 Subject: [PATCH 14/15] fix --- src/client/index.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/client/index.js b/src/client/index.js index c1f93ae6..48330ed9 100644 --- a/src/client/index.js +++ b/src/client/index.js @@ -488,7 +488,6 @@ function rdbClient(options = {}) { rootMap.set(array, { json: cloneFromDb(array, fast), strategy, originalArray: [...array] }); }); let innerProxy = new Proxy(watcher, handler); - //todo if (strategy !== undefined) { const { limit, ...cleanStrategy } = { ...strategy }; fetchingStrategyMap.set(array, cleanStrategy); @@ -1036,9 +1035,14 @@ function onChange(target, onChange) { } return Reflect.set(target, prop, value, receiver); + }, + deleteProperty(target, prop) { + if (!notified) { + notified = true; + onChange(JSON.stringify(target)); + } + return Reflect.deleteProperty(target, prop); } - - }; return new Proxy(target, handler); From e3aa00953f3c4ce821aaff94ad904a27a594b48b Mon Sep 17 00:00:00 2001 From: Lars-Erik Roald Date: Tue, 25 Jun 2024 07:08:49 +0000 Subject: [PATCH 15/15] beta 6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d6d82dc7..2f709eaf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "orange-orm", - "version": "4.2.0-beta.5", + "version": "4.2.0-beta.6", "main": "./src/index.js", "browser": "./src/client/index.mjs", "bin": {