refactor: replace rfdc with native structuredClone

This commit is contained in:
2024-04-03 11:14:47 +02:00
committed by Rainer Killinger
parent 622481a3c9
commit 53c3d0ba0c
13 changed files with 33 additions and 70 deletions

View File

@@ -44,7 +44,6 @@ describe('Search route', async function () {
}); });
it('should reject GET, PUT with a valid search query', async function () { it('should reject GET, PUT with a valid search query', async function () {
// const expectedParams = JSON.parse(JSON.stringify(defaultParams));
const {status} = await testApp.get('/search').set('Accept', 'application/json').send({ const {status} = await testApp.get('/search').set('Accept', 'application/json').send({
query: 'Some search terms', query: 'Some search terms',
}); });

View File

@@ -21,10 +21,13 @@
"allowedCommonJsDependencies": [ "allowedCommonJsDependencies": [
"moment", "moment",
"opening_hours", "opening_hours",
"leaflet", "localforage",
"leaflet.markercluster", "i18next",
"localforge", "semver",
"guid-typescript" "suncalc",
"guid-typescript",
"fast-deep-equal",
"maplibre-gl"
], ],
"aot": true, "aot": true,
"assets": [ "assets": [

View File

@@ -104,7 +104,7 @@ describe('ConfigProvider', () => {
it('should throw error on wrong config version in storage', async () => { it('should throw error on wrong config version in storage', async () => {
storageProviderSpy.has.and.returnValue(Promise.resolve(true)); storageProviderSpy.has.and.returnValue(Promise.resolve(true));
const wrongConfig = JSON.parse(JSON.stringify(sampleIndexResponse)); const wrongConfig = structuredClone(sampleIndexResponse);
wrongConfig.backend.SCVersion = '0.1.0'; wrongConfig.backend.SCVersion = '0.1.0';
storageProviderSpy.get.and.returnValue(wrongConfig); storageProviderSpy.get.and.returnValue(wrongConfig);
spyOn(configProvider.client, 'handshake').and.returnValue(Promise.resolve(sampleIndexResponse)); spyOn(configProvider.client, 'handshake').and.returnValue(Promise.resolve(sampleIndexResponse));

View File

@@ -59,7 +59,7 @@ describe('SettingsProvider', () => {
}); });
it('should provide and get setting', async () => { it('should provide and get setting', async () => {
await settingsProvider.provideSetting(JSON.parse(JSON.stringify(CONFIG_SETTINGS_MOCK[0]))); await settingsProvider.provideSetting(structuredClone(CONFIG_SETTINGS_MOCK[0]));
const setting: SCSetting = await settingsProvider.getSetting( const setting: SCSetting = await settingsProvider.getSetting(
CONFIG_SETTINGS_MOCK[0].categories[0], CONFIG_SETTINGS_MOCK[0].categories[0],
CONFIG_SETTINGS_MOCK[0].name, CONFIG_SETTINGS_MOCK[0].name,
@@ -68,7 +68,7 @@ describe('SettingsProvider', () => {
}); });
it('should provide and get settings value', async () => { it('should provide and get settings value', async () => {
await settingsProvider.provideSetting(JSON.parse(JSON.stringify(CONFIG_SETTINGS_MOCK[0]))); await settingsProvider.provideSetting(structuredClone(CONFIG_SETTINGS_MOCK[0]));
const value = await settingsProvider.getValue( const value = await settingsProvider.getValue(
CONFIG_SETTINGS_MOCK[0].categories[0], CONFIG_SETTINGS_MOCK[0].categories[0],
CONFIG_SETTINGS_MOCK[0].name, CONFIG_SETTINGS_MOCK[0].name,
@@ -109,7 +109,7 @@ describe('SettingsProvider', () => {
}); });
it('should set value of a provided setting', async () => { it('should set value of a provided setting', async () => {
await settingsProvider.provideSetting(JSON.parse(JSON.stringify(CONFIG_SETTINGS_MOCK[1]))); await settingsProvider.provideSetting(structuredClone(CONFIG_SETTINGS_MOCK[1]));
await settingsProvider.setSettingValue( await settingsProvider.setSettingValue(
CONFIG_SETTINGS_MOCK[1].categories[0], CONFIG_SETTINGS_MOCK[1].categories[0],
CONFIG_SETTINGS_MOCK[1].name, CONFIG_SETTINGS_MOCK[1].name,
@@ -125,7 +125,7 @@ describe('SettingsProvider', () => {
it('should return copy of settingsCache', async () => { it('should return copy of settingsCache', async () => {
const category = CONFIG_SETTINGS_MOCK[0].categories[0]; const category = CONFIG_SETTINGS_MOCK[0].categories[0];
const name = CONFIG_SETTINGS_MOCK[0].name; const name = CONFIG_SETTINGS_MOCK[0].name;
await settingsProvider.provideSetting(JSON.parse(JSON.stringify(CONFIG_SETTINGS_MOCK[0]))); await settingsProvider.provideSetting(structuredClone(CONFIG_SETTINGS_MOCK[0]));
const settings = await settingsProvider.getCache(); const settings = await settingsProvider.getCache();
settings[category].settings[name].value = 'testValue'; settings[category].settings[name].value = 'testValue';
// cached setting value should still be defaultValue // cached setting value should still be defaultValue
@@ -133,7 +133,7 @@ describe('SettingsProvider', () => {
}); });
it('should call storage put on setSettingValue', async () => { it('should call storage put on setSettingValue', async () => {
await settingsProvider.provideSetting(JSON.parse(JSON.stringify(CONFIG_SETTINGS_MOCK[0]))); await settingsProvider.provideSetting(structuredClone(CONFIG_SETTINGS_MOCK[0]));
await settingsProvider.setSettingValue( await settingsProvider.setSettingValue(
CONFIG_SETTINGS_MOCK[0].categories[0], CONFIG_SETTINGS_MOCK[0].categories[0],
CONFIG_SETTINGS_MOCK[0].name, CONFIG_SETTINGS_MOCK[0].name,
@@ -150,7 +150,7 @@ describe('SettingsProvider', () => {
it('should reset settings', async () => { it('should reset settings', async () => {
const category = CONFIG_SETTINGS_MOCK[0].categories[0]; const category = CONFIG_SETTINGS_MOCK[0].categories[0];
const name = CONFIG_SETTINGS_MOCK[0].name; const name = CONFIG_SETTINGS_MOCK[0].name;
await settingsProvider.provideSetting(JSON.parse(JSON.stringify(CONFIG_SETTINGS_MOCK[0]))); await settingsProvider.provideSetting(structuredClone(CONFIG_SETTINGS_MOCK[0]));
await settingsProvider.setSettingValue(category, name, 'guest'); await settingsProvider.setSettingValue(category, name, 'guest');
await settingsProvider.resetDefault(); await settingsProvider.resetDefault();
const value = await settingsProvider.getValue( const value = await settingsProvider.getValue(
@@ -203,7 +203,7 @@ describe('SettingsProvider', () => {
*/ */
async function testValue(setting: SCSetting, value: unknown) { async function testValue(setting: SCSetting, value: unknown) {
let error: Error | undefined = undefined; let error: Error | undefined = undefined;
await settingsProvider.provideSetting(JSON.parse(JSON.stringify(setting))); await settingsProvider.provideSetting(structuredClone(setting));
try { try {
await settingsProvider.setSettingValue(setting.categories[0], setting.name, value as never); await settingsProvider.setSettingValue(setting.categories[0], setting.name, value as never);
} catch (error_) { } catch (error_) {

View File

@@ -271,7 +271,7 @@ export class SettingsProvider {
public async getCache(): Promise<SettingsCache> { public async getCache(): Promise<SettingsCache> {
await this.init(); await this.init();
return JSON.parse(JSON.stringify(this.settingsCache)); return structuredClone(this.settingsCache);
} }
/** /**
@@ -291,7 +291,7 @@ export class SettingsProvider {
await this.init(); await this.init();
if (this.settingExists(category, name)) { if (this.settingExists(category, name)) {
// return a copy of the settings // return a copy of the settings
return JSON.parse(JSON.stringify(this.settingsCache[category].settings[name])); return structuredClone(this.settingsCache[category].settings[name]);
} }
throw new Error(`Setting "${name}" not provided`); throw new Error(`Setting "${name}" not provided`);
} }
@@ -306,7 +306,7 @@ export class SettingsProvider {
await this.init(); await this.init();
if (this.settingExists(category, name)) { if (this.settingExists(category, name)) {
// return a copy of the settings value // return a copy of the settings value
return JSON.parse(JSON.stringify(this.settingsCache[category].settings[name].value)); return structuredClone(this.settingsCache[category].settings[name].value)!;
} }
throw new Error(`Setting "${name}" not provided`); throw new Error(`Setting "${name}" not provided`);
} }

View File

@@ -92,8 +92,8 @@ describe('e2e Connector', function () {
if ( if (
request.url.toString() === `http://localhost${bulkAddRoute.getUrlPath({UID: 'foo'}).toString()}` request.url.toString() === `http://localhost${bulkAddRoute.getUrlPath({UID: 'foo'}).toString()}`
) { ) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any const thing = request.body as SCThings;
storedThings.set((request.body as any).uid, JSON.parse(JSON.stringify(request.body))); storedThings.set(thing.uid, structuredClone(thing));
return { return {
body: {}, body: {},
@@ -143,7 +143,6 @@ describe('e2e Connector', function () {
}, },
); );
// tslint:disable-next-line: max-line-length
await e2eRun(httpClient, { await e2eRun(httpClient, {
to: 'http://localhost', to: 'http://localhost',
samplesLocation: './node_modules/@openstapps/core/test/resources', samplesLocation: './node_modules/@openstapps/core/test/resources',
@@ -151,7 +150,6 @@ describe('e2e Connector', function () {
failOnLookup = true; failOnLookup = true;
failOnCompare = false; failOnCompare = false;
// tslint:disable-next-line: max-line-length
await e2eRun(httpClient, { await e2eRun(httpClient, {
to: 'http://localhost', to: 'http://localhost',
samplesLocation: './node_modules/@openstapps/core/test/resources', samplesLocation: './node_modules/@openstapps/core/test/resources',
@@ -161,7 +159,6 @@ describe('e2e Connector', function () {
failOnLookup = false; failOnLookup = false;
failOnCompare = true; failOnCompare = true;
// tslint:disable-next-line: max-line-length
await e2eRun(httpClient, { await e2eRun(httpClient, {
to: 'http://localhost', to: 'http://localhost',
samplesLocation: './node_modules/@openstapps/core/test/resources', samplesLocation: './node_modules/@openstapps/core/test/resources',
@@ -178,7 +175,6 @@ describe('e2e Connector', function () {
}; };
}); });
// tslint:disable-next-line: max-line-length
return e2eRun(httpClient, { return e2eRun(httpClient, {
to: 'http://localhost', to: 'http://localhost',
samplesLocation: './node_modules/@openstapps/core/test/resources', samplesLocation: './node_modules/@openstapps/core/test/resources',

View File

@@ -76,8 +76,9 @@ export class ConnectorClient extends Client {
* @param thing Thing to remove references from * @param thing Thing to remove references from
*/ */
static removeReferences<THING extends SCThings>(thing: THING): SCAssociatedThingWithoutReferences<THING> { static removeReferences<THING extends SCThings>(thing: THING): SCAssociatedThingWithoutReferences<THING> {
const thingWithoutReferences = JSON.parse(JSON.stringify(thing)); const thingWithoutReferences = structuredClone(thing);
// @ts-expect-error it still thinks it's a thing with references
delete thingWithoutReferences.origin; delete thingWithoutReferences.origin;
// iterate over all properties // iterate over all properties
@@ -134,7 +135,7 @@ export class ConnectorClient extends Client {
} }
} }
return thingWithoutReferences as SCAssociatedThingWithoutReferences<THING>; return thingWithoutReferences as unknown as SCAssociatedThingWithoutReferences<THING>;
} }
/** /**

View File

@@ -378,7 +378,7 @@ describe('ConnectorClient', function () {
); );
for (const testInstance of testInstances) { for (const testInstance of testInstances) {
const checkInstance = JSON.parse(JSON.stringify(testInstance)); const checkInstance = structuredClone(testInstance);
const testInstanceWithoutReferences = ConnectorClient.removeReferences(testInstance); const testInstanceWithoutReferences = ConnectorClient.removeReferences(testInstance);
expect(doesContainThings(testInstanceWithoutReferences)).to.be.equal( expect(doesContainThings(testInstanceWithoutReferences)).to.be.equal(

View File

@@ -49,8 +49,7 @@
"fast-deep-equal": "3.1.3", "fast-deep-equal": "3.1.3",
"http-status-codes": "2.2.0", "http-status-codes": "2.2.0",
"json-patch": "0.7.0", "json-patch": "0.7.0",
"json-schema": "0.4.0", "json-schema": "0.4.0"
"rfdc": "1.3.0"
}, },
"devDependencies": { "devDependencies": {
"@openstapps/easy-ast": "workspace:*", "@openstapps/easy-ast": "workspace:*",

View File

@@ -14,7 +14,6 @@
* this program. If not, see <https://www.gnu.org/licenses/>. * this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import equal from 'fast-deep-equal/es6/index.js'; import equal from 'fast-deep-equal/es6/index.js';
import clone from 'rfdc';
import {SCLanguageCode} from './general/i18n.js'; import {SCLanguageCode} from './general/i18n.js';
import {isThing} from './guards.js'; import {isThing} from './guards.js';
import {SCClasses} from './meta.js'; import {SCClasses} from './meta.js';
@@ -223,7 +222,7 @@ export class SCThingTranslator {
return cachedInstance as T; return cachedInstance as T;
} }
} }
const translatedInstance = this.translateThingInPlaceDestructively(clone()(thing)); const translatedInstance = this.translateThingInPlaceDestructively(structuredClone(thing));
delete translatedInstance.translations; delete translatedInstance.translations;
this.cache.putObject(translatedInstance); this.cache.putObject(translatedInstance);
this.sourceCache.putObject(thing); this.sourceCache.putObject(thing);
@@ -254,7 +253,7 @@ export class SCThingTranslator {
return this.deeptranslate((objectTranslatedFromCache as any)[key]); return this.deeptranslate((objectTranslatedFromCache as any)[key]);
} }
} }
const objectTranslated = this.translateThingInPlaceDestructively(clone()(object)); const objectTranslated = this.translateThingInPlaceDestructively(structuredClone(object));
this.cache.putObject(objectTranslated); this.cache.putObject(objectTranslated);
this.sourceCache.putObject(thing); this.sourceCache.putObject(thing);

View File

@@ -13,7 +13,6 @@
* this program. If not, see <https://www.gnu.org/licenses/>. * this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import {expect} from 'chai'; import {expect} from 'chai';
import clone from 'rfdc';
import {SCThingRemoteOrigin} from '../src/index.js'; import {SCThingRemoteOrigin} from '../src/index.js';
import {SCDishMeta} from '../src/index.js'; import {SCDishMeta} from '../src/index.js';
import {SCThingTranslator} from '../src/index.js'; import {SCThingTranslator} from '../src/index.js';
@@ -164,7 +163,7 @@ describe('Translator', function () {
it('should omit LRU cache with changed source', function () { it('should omit LRU cache with changed source', function () {
const translatorDE = new SCThingTranslator('de'); const translatorDE = new SCThingTranslator('de');
const dishCopy = clone()(dish); const dishCopy = structuredClone(dish);
const translatedDish = translatorDE.translatedAccess(dish); const translatedDish = translatorDE.translatedAccess(dish);
const destructivelyTranslatedDish = translatorDE.translate(dish); const destructivelyTranslatedDish = translatorDE.translate(dish);
@@ -224,7 +223,7 @@ describe('MetaTranslator', function () {
}); });
it('should translate thing without meta class', function () { it('should translate thing without meta class', function () {
const dishCopy = clone()(dish); const dishCopy = structuredClone(dish);
const typeNonExistent = eval("(x) => x + 'typeNonExistent';"); const typeNonExistent = eval("(x) => x + 'typeNonExistent';");
// this will assign a non-existent SCThingType to dishCopy // this will assign a non-existent SCThingType to dishCopy
dishCopy.type = typeNonExistent(); dishCopy.type = typeNonExistent();

View File

@@ -68,10 +68,10 @@ export class LightweightProjectWithIndex {
return (deep ?? true) && isLightweightClass(object) return (deep ?? true) && isLightweightClass(object)
? this.applyInheritance(object) ? this.applyInheritance(object)
: JSON.parse(JSON.stringify(object)); : structuredClone(object);
}, },
), ),
JSON.parse(JSON.stringify(classLike)), structuredClone(classLike),
); );
} }

37
pnpm-lock.yaml generated
View File

@@ -1511,9 +1511,6 @@ importers:
json-schema: json-schema:
specifier: 0.4.0 specifier: 0.4.0
version: 0.4.0 version: 0.4.0
rfdc:
specifier: 1.3.0
version: 1.3.0
devDependencies: devDependencies:
'@openstapps/easy-ast': '@openstapps/easy-ast':
specifier: workspace:* specifier: workspace:*
@@ -4546,7 +4543,7 @@ packages:
object-assign: 4.1.1 object-assign: 4.1.1
open: 8.4.0 open: 8.4.0
proxy-middleware: 0.15.0 proxy-middleware: 0.15.0
send: 1.0.0-beta.2 send: 0.18.0
serve-index: 1.9.1 serve-index: 1.9.1
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@@ -10089,17 +10086,6 @@ packages:
dependencies: dependencies:
ms: 2.0.0 ms: 2.0.0
/debug@3.1.0:
resolution: {integrity: sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
dependencies:
ms: 2.0.0
dev: true
/debug@3.2.7(supports-color@5.5.0): /debug@3.2.7(supports-color@5.5.0):
resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
peerDependencies: peerDependencies:
@@ -17023,6 +17009,7 @@ packages:
/rfdc@1.3.0: /rfdc@1.3.0:
resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==} resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==}
dev: true
/rimraf@2.7.1: /rimraf@2.7.1:
resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==}
@@ -17306,26 +17293,6 @@ packages:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
/send@1.0.0-beta.2:
resolution: {integrity: sha512-k1yHu/FNK745PULKdsGpQ+bVSXYNwSk+bWnYzbxGZbt5obZc0JKDVANsCRuJD1X/EG15JtP9eZpwxkhUxIYEcg==}
engines: {node: '>= 0.10'}
dependencies:
debug: 3.1.0
destroy: 1.2.0
encodeurl: 1.0.2
escape-html: 1.0.3
etag: 1.8.1
fresh: 0.5.2
http-errors: 2.0.0
mime-types: 2.1.35
ms: 2.1.3
on-finished: 2.4.1
range-parser: 1.2.1
statuses: 2.0.1
transitivePeerDependencies:
- supports-color
dev: true
/serialize-javascript@6.0.0: /serialize-javascript@6.0.0:
resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==} resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==}
dependencies: dependencies: