@wix/sdk 1.17.3 → 1.17.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/event-handlers-modules.js +27 -2
- package/build/modified-fields-manipulator.d.ts +35 -0
- package/build/modified-fields-manipulator.js +200 -0
- package/cjs/build/event-handlers-modules.js +27 -2
- package/cjs/build/modified-fields-manipulator.d.ts +35 -0
- package/cjs/build/modified-fields-manipulator.js +208 -0
- package/package.json +12 -9
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { EventDefinition, } from '@wix/sdk-types';
|
|
2
|
+
import { attemptTransformationWithModifiedFields } from './modified-fields-manipulator.js';
|
|
2
3
|
import { createNanoEvents } from './nanoevents.js';
|
|
3
4
|
export const isEventHandlerModule = (val) => val.__type === 'event-definition';
|
|
4
5
|
export function buildEventDefinition(eventDefinition, registerHandler) {
|
|
@@ -32,9 +33,19 @@ function runHandler(eventDefinition, handler, payload, baseEventMetadata) {
|
|
|
32
33
|
metadata,
|
|
33
34
|
};
|
|
34
35
|
}
|
|
36
|
+
else if (updatedEvent) {
|
|
37
|
+
envelope = {
|
|
38
|
+
entity: updatedEvent.currentEntity,
|
|
39
|
+
metadata,
|
|
40
|
+
...(updatedEvent.modifiedFields
|
|
41
|
+
? { modifiedFields: updatedEvent.modifiedFields }
|
|
42
|
+
: {}),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
35
45
|
else {
|
|
46
|
+
// createdEvent
|
|
36
47
|
envelope = {
|
|
37
|
-
entity: createdEvent?.entity
|
|
48
|
+
entity: createdEvent?.entity,
|
|
38
49
|
metadata,
|
|
39
50
|
};
|
|
40
51
|
}
|
|
@@ -46,7 +57,21 @@ function runHandler(eventDefinition, handler, payload, baseEventMetadata) {
|
|
|
46
57
|
};
|
|
47
58
|
}
|
|
48
59
|
const transformFromRESTFn = eventDefinition.transformations ?? ((x) => x);
|
|
49
|
-
|
|
60
|
+
let originalEnvelope = envelope;
|
|
61
|
+
const envelopeAny = envelope;
|
|
62
|
+
if (envelopeAny.modifiedFields) {
|
|
63
|
+
const modifiedFieldsValue = envelopeAny.modifiedFields;
|
|
64
|
+
if (typeof modifiedFieldsValue === 'object' &&
|
|
65
|
+
modifiedFieldsValue !== null &&
|
|
66
|
+
!Array.isArray(modifiedFieldsValue)) {
|
|
67
|
+
originalEnvelope = structuredClone(envelope);
|
|
68
|
+
const transformedEnvelope = attemptTransformationWithModifiedFields(envelopeAny, transformFromRESTFn);
|
|
69
|
+
if (transformedEnvelope) {
|
|
70
|
+
return handler(transformedEnvelope);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return handler(transformFromRESTFn(originalEnvelope));
|
|
50
75
|
}
|
|
51
76
|
export function eventHandlersModules(authStrategy) {
|
|
52
77
|
const eventHandlers = new Map();
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export declare class ModifiedFieldsManipulator {
|
|
2
|
+
private readonly BRACKET_PATTERN;
|
|
3
|
+
private readonly NUMERIC_PATTERN;
|
|
4
|
+
private readonly ESCAPED_DOT_PATTERN;
|
|
5
|
+
private readonly ESCAPED_LEFT_BRACKET_PATTERN;
|
|
6
|
+
private readonly ESCAPED_RIGHT_BRACKET_PATTERN;
|
|
7
|
+
private readonly SPLIT_PATTERN;
|
|
8
|
+
private readonly DOT_BEFORE_BRACKET_PATTERN;
|
|
9
|
+
private readonly ESCAPED_DOT_PLACEHOLDER;
|
|
10
|
+
private readonly ESCAPED_RIGHT_BRACKET_PLACEHOLDER;
|
|
11
|
+
private readonly ESCAPED_LEFT_BRACKET_PLACEHOLDER;
|
|
12
|
+
private readonly modifiedFields;
|
|
13
|
+
private cleanedModifiedFields;
|
|
14
|
+
constructor(modifiedFields: Record<string, unknown>);
|
|
15
|
+
private replaceEscapedCharacters;
|
|
16
|
+
private restoreEscapedCharacters;
|
|
17
|
+
unflatten(): Record<string, unknown>;
|
|
18
|
+
flatten(transformedModifiedFields: Record<string, unknown>): Record<string, unknown>;
|
|
19
|
+
private splitPath;
|
|
20
|
+
private navigatePath;
|
|
21
|
+
private buildPathString;
|
|
22
|
+
private bracketToDotNotation;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Transforms an envelope while preserving the structure of modifiedFields.
|
|
26
|
+
*
|
|
27
|
+
* Modified fields come as flattened objects, while transformations are applied to the nested object (e.g. "a.b.c" -> { a: { b: { c: 'value' } } }).
|
|
28
|
+
* This function handles the transformation of envelopes that contain flattened modifiedFields.
|
|
29
|
+
* It unflattens the modifiedFields, applies the transformation function, and then flattens
|
|
30
|
+
* the modifiedFields back to their original format while preserving the transformation.
|
|
31
|
+
* @param envelope - The envelope object containing flattened modifiedFields
|
|
32
|
+
* @param transformFromRESTFn - Function to transform the envelope from REST format to SDK format
|
|
33
|
+
* @returns The transformed envelope with flattened modifiedFields, or null if transformation fails
|
|
34
|
+
*/
|
|
35
|
+
export declare function attemptTransformationWithModifiedFields(envelope: any, transformFromRESTFn: (envelope: unknown) => unknown): unknown;
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { unflatten } from 'flat';
|
|
2
|
+
import lodash from 'lodash';
|
|
3
|
+
import { RESTResponseToSDKResponseRenameMap } from '@wix/sdk-runtime/rest-modules';
|
|
4
|
+
const { camelCase } = lodash;
|
|
5
|
+
export class ModifiedFieldsManipulator {
|
|
6
|
+
BRACKET_PATTERN = /\[(\d+)\]/g;
|
|
7
|
+
NUMERIC_PATTERN = /^\d+$/;
|
|
8
|
+
ESCAPED_DOT_PATTERN = /\\\./g;
|
|
9
|
+
ESCAPED_LEFT_BRACKET_PATTERN = /\\\[/g;
|
|
10
|
+
ESCAPED_RIGHT_BRACKET_PATTERN = /\\\]/g;
|
|
11
|
+
SPLIT_PATTERN = /\.|\[(\d+)\]/g;
|
|
12
|
+
DOT_BEFORE_BRACKET_PATTERN = /\.\[/g;
|
|
13
|
+
ESCAPED_DOT_PLACEHOLDER = '__DOT__';
|
|
14
|
+
ESCAPED_RIGHT_BRACKET_PLACEHOLDER = '__RB__';
|
|
15
|
+
ESCAPED_LEFT_BRACKET_PLACEHOLDER = '__LB__';
|
|
16
|
+
modifiedFields;
|
|
17
|
+
cleanedModifiedFields;
|
|
18
|
+
constructor(modifiedFields) {
|
|
19
|
+
this.modifiedFields = modifiedFields;
|
|
20
|
+
}
|
|
21
|
+
replaceEscapedCharacters(key) {
|
|
22
|
+
return key
|
|
23
|
+
.replace(this.ESCAPED_DOT_PATTERN, this.ESCAPED_DOT_PLACEHOLDER)
|
|
24
|
+
.replace(this.ESCAPED_LEFT_BRACKET_PATTERN, this.ESCAPED_LEFT_BRACKET_PLACEHOLDER)
|
|
25
|
+
.replace(this.ESCAPED_RIGHT_BRACKET_PATTERN, this.ESCAPED_RIGHT_BRACKET_PLACEHOLDER);
|
|
26
|
+
}
|
|
27
|
+
restoreEscapedCharacters(key) {
|
|
28
|
+
return key
|
|
29
|
+
.replace(this.ESCAPED_DOT_PLACEHOLDER, '\\.')
|
|
30
|
+
.replace(this.ESCAPED_RIGHT_BRACKET_PLACEHOLDER, '\\]')
|
|
31
|
+
.replace(this.ESCAPED_LEFT_BRACKET_PLACEHOLDER, '\\[');
|
|
32
|
+
}
|
|
33
|
+
unflatten() {
|
|
34
|
+
this.cleanedModifiedFields = Object.fromEntries(Object.entries(this.modifiedFields).map(([key, value]) => [
|
|
35
|
+
this.replaceEscapedCharacters(this.bracketToDotNotation(key)),
|
|
36
|
+
value,
|
|
37
|
+
]));
|
|
38
|
+
return unflatten(this.cleanedModifiedFields);
|
|
39
|
+
}
|
|
40
|
+
flatten(transformedModifiedFields) {
|
|
41
|
+
let result = {};
|
|
42
|
+
for (const originalKey of Object.keys(this.cleanedModifiedFields)) {
|
|
43
|
+
const pathParts = this.splitPath(originalKey);
|
|
44
|
+
const value = this.navigatePath(transformedModifiedFields, pathParts);
|
|
45
|
+
result = { ...result, ...value };
|
|
46
|
+
}
|
|
47
|
+
return Object.fromEntries(Object.entries(result).map(([key, value]) => [
|
|
48
|
+
this.restoreEscapedCharacters(key),
|
|
49
|
+
value,
|
|
50
|
+
]));
|
|
51
|
+
}
|
|
52
|
+
splitPath(path) {
|
|
53
|
+
const parts = [];
|
|
54
|
+
let lastIndex = 0;
|
|
55
|
+
const matches = Array.from(path.matchAll(this.SPLIT_PATTERN));
|
|
56
|
+
for (const match of matches) {
|
|
57
|
+
if (match.index > lastIndex) {
|
|
58
|
+
parts.push(path.substring(lastIndex, match.index));
|
|
59
|
+
}
|
|
60
|
+
if (match[1]) {
|
|
61
|
+
parts.push(match[1]);
|
|
62
|
+
}
|
|
63
|
+
lastIndex = match.index + match[0].length;
|
|
64
|
+
}
|
|
65
|
+
if (lastIndex < path.length) {
|
|
66
|
+
parts.push(path.substring(lastIndex));
|
|
67
|
+
}
|
|
68
|
+
return parts;
|
|
69
|
+
}
|
|
70
|
+
navigatePath(obj, pathParts) {
|
|
71
|
+
let current = obj;
|
|
72
|
+
const transformedPath = [];
|
|
73
|
+
const handleArray = (part) => {
|
|
74
|
+
if (!Array.isArray(current)) {
|
|
75
|
+
throw new Error(`Expected array at path ${this.buildPathString(transformedPath)}, but got ${typeof current}`);
|
|
76
|
+
}
|
|
77
|
+
transformedPath.push(`[${part}]`);
|
|
78
|
+
current = current[parseInt(part, 10)];
|
|
79
|
+
};
|
|
80
|
+
const handleTransformedKeyName = (part, currentObj) => {
|
|
81
|
+
const transformedKey = part in RESTResponseToSDKResponseRenameMap
|
|
82
|
+
? RESTResponseToSDKResponseRenameMap[part]
|
|
83
|
+
: undefined;
|
|
84
|
+
if (transformedKey && transformedKey in currentObj) {
|
|
85
|
+
transformedPath.push(transformedKey);
|
|
86
|
+
current = currentObj[transformedKey];
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const camelCaseKey = camelCase(part);
|
|
90
|
+
if (camelCaseKey && camelCaseKey in currentObj) {
|
|
91
|
+
transformedPath.push(camelCaseKey);
|
|
92
|
+
current = currentObj[camelCaseKey];
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
throw new Error(`Cannot find key '${part}' or its transformations at path ${this.buildPathString(transformedPath)}`);
|
|
96
|
+
};
|
|
97
|
+
const handleObject = (part, currentObj) => {
|
|
98
|
+
transformedPath.push(part);
|
|
99
|
+
current = currentObj[part];
|
|
100
|
+
return;
|
|
101
|
+
};
|
|
102
|
+
for (const part of pathParts) {
|
|
103
|
+
if (this.NUMERIC_PATTERN.test(part)) {
|
|
104
|
+
handleArray(part);
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
if (current === null || typeof current !== 'object') {
|
|
108
|
+
throw new Error(`Cannot access property '${part}' on ${typeof current} at path ${this.buildPathString(transformedPath)}`);
|
|
109
|
+
}
|
|
110
|
+
const currentObj = current;
|
|
111
|
+
if (part in current) {
|
|
112
|
+
handleObject(part, currentObj);
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
handleTransformedKeyName(part, currentObj);
|
|
116
|
+
}
|
|
117
|
+
return { [this.buildPathString(transformedPath)]: current };
|
|
118
|
+
}
|
|
119
|
+
buildPathString(pathParts) {
|
|
120
|
+
return pathParts.join('.').replace(this.DOT_BEFORE_BRACKET_PATTERN, '[');
|
|
121
|
+
}
|
|
122
|
+
bracketToDotNotation(key) {
|
|
123
|
+
return key.replace(this.BRACKET_PATTERN, (match, number, offset) => {
|
|
124
|
+
if (offset > 0 && key[offset - 1] === '\\') {
|
|
125
|
+
return match;
|
|
126
|
+
}
|
|
127
|
+
return '.' + number;
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Transforms an envelope while preserving the structure of modifiedFields.
|
|
133
|
+
*
|
|
134
|
+
* Modified fields come as flattened objects, while transformations are applied to the nested object (e.g. "a.b.c" -> { a: { b: { c: 'value' } } }).
|
|
135
|
+
* This function handles the transformation of envelopes that contain flattened modifiedFields.
|
|
136
|
+
* It unflattens the modifiedFields, applies the transformation function, and then flattens
|
|
137
|
+
* the modifiedFields back to their original format while preserving the transformation.
|
|
138
|
+
* @param envelope - The envelope object containing flattened modifiedFields
|
|
139
|
+
* @param transformFromRESTFn - Function to transform the envelope from REST format to SDK format
|
|
140
|
+
* @returns The transformed envelope with flattened modifiedFields, or null if transformation fails
|
|
141
|
+
*/
|
|
142
|
+
export function attemptTransformationWithModifiedFields(envelope, transformFromRESTFn) {
|
|
143
|
+
const modifiedFields = envelope?.modifiedFields;
|
|
144
|
+
if (!modifiedFields) {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
const unflattenedResult = attemptUnflatten(modifiedFields);
|
|
148
|
+
if (!unflattenedResult) {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
const { unflattenedModifiedFields, modifiedFieldsManipulator } = unflattenedResult;
|
|
152
|
+
envelope = {
|
|
153
|
+
...envelope,
|
|
154
|
+
modifiedFields: unflattenedModifiedFields,
|
|
155
|
+
};
|
|
156
|
+
const transformedEnvelope = transformFromRESTFn(envelope);
|
|
157
|
+
const transformedModifiedFields = transformedEnvelope
|
|
158
|
+
?.modifiedFields;
|
|
159
|
+
if (!transformedModifiedFields) {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
const flattened = attemptFlatten(transformedModifiedFields, modifiedFieldsManipulator);
|
|
163
|
+
if (flattened !== null) {
|
|
164
|
+
transformedEnvelope.modifiedFields = flattened;
|
|
165
|
+
return transformedEnvelope;
|
|
166
|
+
}
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
function attemptUnflatten(modifiedFields) {
|
|
170
|
+
if (typeof modifiedFields === 'object' &&
|
|
171
|
+
modifiedFields !== null &&
|
|
172
|
+
!Array.isArray(modifiedFields)) {
|
|
173
|
+
try {
|
|
174
|
+
const modifiedFieldsManipulator = new ModifiedFieldsManipulator(modifiedFields);
|
|
175
|
+
const unflattened = modifiedFieldsManipulator.unflatten();
|
|
176
|
+
return {
|
|
177
|
+
unflattenedModifiedFields: unflattened,
|
|
178
|
+
modifiedFieldsManipulator,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
function attemptFlatten(transformedModifiedFields, modifiedFieldsManipulator) {
|
|
188
|
+
if (typeof transformedModifiedFields === 'object' &&
|
|
189
|
+
transformedModifiedFields !== null &&
|
|
190
|
+
!Array.isArray(transformedModifiedFields)) {
|
|
191
|
+
try {
|
|
192
|
+
const flattened = modifiedFieldsManipulator.flatten(transformedModifiedFields);
|
|
193
|
+
return flattened;
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
@@ -4,6 +4,7 @@ exports.isEventHandlerModule = void 0;
|
|
|
4
4
|
exports.buildEventDefinition = buildEventDefinition;
|
|
5
5
|
exports.eventHandlersModules = eventHandlersModules;
|
|
6
6
|
const sdk_types_1 = require("@wix/sdk-types");
|
|
7
|
+
const modified_fields_manipulator_js_1 = require("./modified-fields-manipulator.js");
|
|
7
8
|
const nanoevents_js_1 = require("./nanoevents.js");
|
|
8
9
|
const isEventHandlerModule = (val) => val.__type === 'event-definition';
|
|
9
10
|
exports.isEventHandlerModule = isEventHandlerModule;
|
|
@@ -38,9 +39,19 @@ function runHandler(eventDefinition, handler, payload, baseEventMetadata) {
|
|
|
38
39
|
metadata,
|
|
39
40
|
};
|
|
40
41
|
}
|
|
42
|
+
else if (updatedEvent) {
|
|
43
|
+
envelope = {
|
|
44
|
+
entity: updatedEvent.currentEntity,
|
|
45
|
+
metadata,
|
|
46
|
+
...(updatedEvent.modifiedFields
|
|
47
|
+
? { modifiedFields: updatedEvent.modifiedFields }
|
|
48
|
+
: {}),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
41
51
|
else {
|
|
52
|
+
// createdEvent
|
|
42
53
|
envelope = {
|
|
43
|
-
entity: createdEvent?.entity
|
|
54
|
+
entity: createdEvent?.entity,
|
|
44
55
|
metadata,
|
|
45
56
|
};
|
|
46
57
|
}
|
|
@@ -52,7 +63,21 @@ function runHandler(eventDefinition, handler, payload, baseEventMetadata) {
|
|
|
52
63
|
};
|
|
53
64
|
}
|
|
54
65
|
const transformFromRESTFn = eventDefinition.transformations ?? ((x) => x);
|
|
55
|
-
|
|
66
|
+
let originalEnvelope = envelope;
|
|
67
|
+
const envelopeAny = envelope;
|
|
68
|
+
if (envelopeAny.modifiedFields) {
|
|
69
|
+
const modifiedFieldsValue = envelopeAny.modifiedFields;
|
|
70
|
+
if (typeof modifiedFieldsValue === 'object' &&
|
|
71
|
+
modifiedFieldsValue !== null &&
|
|
72
|
+
!Array.isArray(modifiedFieldsValue)) {
|
|
73
|
+
originalEnvelope = structuredClone(envelope);
|
|
74
|
+
const transformedEnvelope = (0, modified_fields_manipulator_js_1.attemptTransformationWithModifiedFields)(envelopeAny, transformFromRESTFn);
|
|
75
|
+
if (transformedEnvelope) {
|
|
76
|
+
return handler(transformedEnvelope);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return handler(transformFromRESTFn(originalEnvelope));
|
|
56
81
|
}
|
|
57
82
|
function eventHandlersModules(authStrategy) {
|
|
58
83
|
const eventHandlers = new Map();
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export declare class ModifiedFieldsManipulator {
|
|
2
|
+
private readonly BRACKET_PATTERN;
|
|
3
|
+
private readonly NUMERIC_PATTERN;
|
|
4
|
+
private readonly ESCAPED_DOT_PATTERN;
|
|
5
|
+
private readonly ESCAPED_LEFT_BRACKET_PATTERN;
|
|
6
|
+
private readonly ESCAPED_RIGHT_BRACKET_PATTERN;
|
|
7
|
+
private readonly SPLIT_PATTERN;
|
|
8
|
+
private readonly DOT_BEFORE_BRACKET_PATTERN;
|
|
9
|
+
private readonly ESCAPED_DOT_PLACEHOLDER;
|
|
10
|
+
private readonly ESCAPED_RIGHT_BRACKET_PLACEHOLDER;
|
|
11
|
+
private readonly ESCAPED_LEFT_BRACKET_PLACEHOLDER;
|
|
12
|
+
private readonly modifiedFields;
|
|
13
|
+
private cleanedModifiedFields;
|
|
14
|
+
constructor(modifiedFields: Record<string, unknown>);
|
|
15
|
+
private replaceEscapedCharacters;
|
|
16
|
+
private restoreEscapedCharacters;
|
|
17
|
+
unflatten(): Record<string, unknown>;
|
|
18
|
+
flatten(transformedModifiedFields: Record<string, unknown>): Record<string, unknown>;
|
|
19
|
+
private splitPath;
|
|
20
|
+
private navigatePath;
|
|
21
|
+
private buildPathString;
|
|
22
|
+
private bracketToDotNotation;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Transforms an envelope while preserving the structure of modifiedFields.
|
|
26
|
+
*
|
|
27
|
+
* Modified fields come as flattened objects, while transformations are applied to the nested object (e.g. "a.b.c" -> { a: { b: { c: 'value' } } }).
|
|
28
|
+
* This function handles the transformation of envelopes that contain flattened modifiedFields.
|
|
29
|
+
* It unflattens the modifiedFields, applies the transformation function, and then flattens
|
|
30
|
+
* the modifiedFields back to their original format while preserving the transformation.
|
|
31
|
+
* @param envelope - The envelope object containing flattened modifiedFields
|
|
32
|
+
* @param transformFromRESTFn - Function to transform the envelope from REST format to SDK format
|
|
33
|
+
* @returns The transformed envelope with flattened modifiedFields, or null if transformation fails
|
|
34
|
+
*/
|
|
35
|
+
export declare function attemptTransformationWithModifiedFields(envelope: any, transformFromRESTFn: (envelope: unknown) => unknown): unknown;
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ModifiedFieldsManipulator = void 0;
|
|
7
|
+
exports.attemptTransformationWithModifiedFields = attemptTransformationWithModifiedFields;
|
|
8
|
+
const flat_1 = require("flat");
|
|
9
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
10
|
+
const rest_modules_1 = require("@wix/sdk-runtime/rest-modules");
|
|
11
|
+
const { camelCase } = lodash_1.default;
|
|
12
|
+
class ModifiedFieldsManipulator {
|
|
13
|
+
BRACKET_PATTERN = /\[(\d+)\]/g;
|
|
14
|
+
NUMERIC_PATTERN = /^\d+$/;
|
|
15
|
+
ESCAPED_DOT_PATTERN = /\\\./g;
|
|
16
|
+
ESCAPED_LEFT_BRACKET_PATTERN = /\\\[/g;
|
|
17
|
+
ESCAPED_RIGHT_BRACKET_PATTERN = /\\\]/g;
|
|
18
|
+
SPLIT_PATTERN = /\.|\[(\d+)\]/g;
|
|
19
|
+
DOT_BEFORE_BRACKET_PATTERN = /\.\[/g;
|
|
20
|
+
ESCAPED_DOT_PLACEHOLDER = '__DOT__';
|
|
21
|
+
ESCAPED_RIGHT_BRACKET_PLACEHOLDER = '__RB__';
|
|
22
|
+
ESCAPED_LEFT_BRACKET_PLACEHOLDER = '__LB__';
|
|
23
|
+
modifiedFields;
|
|
24
|
+
cleanedModifiedFields;
|
|
25
|
+
constructor(modifiedFields) {
|
|
26
|
+
this.modifiedFields = modifiedFields;
|
|
27
|
+
}
|
|
28
|
+
replaceEscapedCharacters(key) {
|
|
29
|
+
return key
|
|
30
|
+
.replace(this.ESCAPED_DOT_PATTERN, this.ESCAPED_DOT_PLACEHOLDER)
|
|
31
|
+
.replace(this.ESCAPED_LEFT_BRACKET_PATTERN, this.ESCAPED_LEFT_BRACKET_PLACEHOLDER)
|
|
32
|
+
.replace(this.ESCAPED_RIGHT_BRACKET_PATTERN, this.ESCAPED_RIGHT_BRACKET_PLACEHOLDER);
|
|
33
|
+
}
|
|
34
|
+
restoreEscapedCharacters(key) {
|
|
35
|
+
return key
|
|
36
|
+
.replace(this.ESCAPED_DOT_PLACEHOLDER, '\\.')
|
|
37
|
+
.replace(this.ESCAPED_RIGHT_BRACKET_PLACEHOLDER, '\\]')
|
|
38
|
+
.replace(this.ESCAPED_LEFT_BRACKET_PLACEHOLDER, '\\[');
|
|
39
|
+
}
|
|
40
|
+
unflatten() {
|
|
41
|
+
this.cleanedModifiedFields = Object.fromEntries(Object.entries(this.modifiedFields).map(([key, value]) => [
|
|
42
|
+
this.replaceEscapedCharacters(this.bracketToDotNotation(key)),
|
|
43
|
+
value,
|
|
44
|
+
]));
|
|
45
|
+
return (0, flat_1.unflatten)(this.cleanedModifiedFields);
|
|
46
|
+
}
|
|
47
|
+
flatten(transformedModifiedFields) {
|
|
48
|
+
let result = {};
|
|
49
|
+
for (const originalKey of Object.keys(this.cleanedModifiedFields)) {
|
|
50
|
+
const pathParts = this.splitPath(originalKey);
|
|
51
|
+
const value = this.navigatePath(transformedModifiedFields, pathParts);
|
|
52
|
+
result = { ...result, ...value };
|
|
53
|
+
}
|
|
54
|
+
return Object.fromEntries(Object.entries(result).map(([key, value]) => [
|
|
55
|
+
this.restoreEscapedCharacters(key),
|
|
56
|
+
value,
|
|
57
|
+
]));
|
|
58
|
+
}
|
|
59
|
+
splitPath(path) {
|
|
60
|
+
const parts = [];
|
|
61
|
+
let lastIndex = 0;
|
|
62
|
+
const matches = Array.from(path.matchAll(this.SPLIT_PATTERN));
|
|
63
|
+
for (const match of matches) {
|
|
64
|
+
if (match.index > lastIndex) {
|
|
65
|
+
parts.push(path.substring(lastIndex, match.index));
|
|
66
|
+
}
|
|
67
|
+
if (match[1]) {
|
|
68
|
+
parts.push(match[1]);
|
|
69
|
+
}
|
|
70
|
+
lastIndex = match.index + match[0].length;
|
|
71
|
+
}
|
|
72
|
+
if (lastIndex < path.length) {
|
|
73
|
+
parts.push(path.substring(lastIndex));
|
|
74
|
+
}
|
|
75
|
+
return parts;
|
|
76
|
+
}
|
|
77
|
+
navigatePath(obj, pathParts) {
|
|
78
|
+
let current = obj;
|
|
79
|
+
const transformedPath = [];
|
|
80
|
+
const handleArray = (part) => {
|
|
81
|
+
if (!Array.isArray(current)) {
|
|
82
|
+
throw new Error(`Expected array at path ${this.buildPathString(transformedPath)}, but got ${typeof current}`);
|
|
83
|
+
}
|
|
84
|
+
transformedPath.push(`[${part}]`);
|
|
85
|
+
current = current[parseInt(part, 10)];
|
|
86
|
+
};
|
|
87
|
+
const handleTransformedKeyName = (part, currentObj) => {
|
|
88
|
+
const transformedKey = part in rest_modules_1.RESTResponseToSDKResponseRenameMap
|
|
89
|
+
? rest_modules_1.RESTResponseToSDKResponseRenameMap[part]
|
|
90
|
+
: undefined;
|
|
91
|
+
if (transformedKey && transformedKey in currentObj) {
|
|
92
|
+
transformedPath.push(transformedKey);
|
|
93
|
+
current = currentObj[transformedKey];
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const camelCaseKey = camelCase(part);
|
|
97
|
+
if (camelCaseKey && camelCaseKey in currentObj) {
|
|
98
|
+
transformedPath.push(camelCaseKey);
|
|
99
|
+
current = currentObj[camelCaseKey];
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
throw new Error(`Cannot find key '${part}' or its transformations at path ${this.buildPathString(transformedPath)}`);
|
|
103
|
+
};
|
|
104
|
+
const handleObject = (part, currentObj) => {
|
|
105
|
+
transformedPath.push(part);
|
|
106
|
+
current = currentObj[part];
|
|
107
|
+
return;
|
|
108
|
+
};
|
|
109
|
+
for (const part of pathParts) {
|
|
110
|
+
if (this.NUMERIC_PATTERN.test(part)) {
|
|
111
|
+
handleArray(part);
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
if (current === null || typeof current !== 'object') {
|
|
115
|
+
throw new Error(`Cannot access property '${part}' on ${typeof current} at path ${this.buildPathString(transformedPath)}`);
|
|
116
|
+
}
|
|
117
|
+
const currentObj = current;
|
|
118
|
+
if (part in current) {
|
|
119
|
+
handleObject(part, currentObj);
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
handleTransformedKeyName(part, currentObj);
|
|
123
|
+
}
|
|
124
|
+
return { [this.buildPathString(transformedPath)]: current };
|
|
125
|
+
}
|
|
126
|
+
buildPathString(pathParts) {
|
|
127
|
+
return pathParts.join('.').replace(this.DOT_BEFORE_BRACKET_PATTERN, '[');
|
|
128
|
+
}
|
|
129
|
+
bracketToDotNotation(key) {
|
|
130
|
+
return key.replace(this.BRACKET_PATTERN, (match, number, offset) => {
|
|
131
|
+
if (offset > 0 && key[offset - 1] === '\\') {
|
|
132
|
+
return match;
|
|
133
|
+
}
|
|
134
|
+
return '.' + number;
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
exports.ModifiedFieldsManipulator = ModifiedFieldsManipulator;
|
|
139
|
+
/**
|
|
140
|
+
* Transforms an envelope while preserving the structure of modifiedFields.
|
|
141
|
+
*
|
|
142
|
+
* Modified fields come as flattened objects, while transformations are applied to the nested object (e.g. "a.b.c" -> { a: { b: { c: 'value' } } }).
|
|
143
|
+
* This function handles the transformation of envelopes that contain flattened modifiedFields.
|
|
144
|
+
* It unflattens the modifiedFields, applies the transformation function, and then flattens
|
|
145
|
+
* the modifiedFields back to their original format while preserving the transformation.
|
|
146
|
+
* @param envelope - The envelope object containing flattened modifiedFields
|
|
147
|
+
* @param transformFromRESTFn - Function to transform the envelope from REST format to SDK format
|
|
148
|
+
* @returns The transformed envelope with flattened modifiedFields, or null if transformation fails
|
|
149
|
+
*/
|
|
150
|
+
function attemptTransformationWithModifiedFields(envelope, transformFromRESTFn) {
|
|
151
|
+
const modifiedFields = envelope?.modifiedFields;
|
|
152
|
+
if (!modifiedFields) {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
const unflattenedResult = attemptUnflatten(modifiedFields);
|
|
156
|
+
if (!unflattenedResult) {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
const { unflattenedModifiedFields, modifiedFieldsManipulator } = unflattenedResult;
|
|
160
|
+
envelope = {
|
|
161
|
+
...envelope,
|
|
162
|
+
modifiedFields: unflattenedModifiedFields,
|
|
163
|
+
};
|
|
164
|
+
const transformedEnvelope = transformFromRESTFn(envelope);
|
|
165
|
+
const transformedModifiedFields = transformedEnvelope
|
|
166
|
+
?.modifiedFields;
|
|
167
|
+
if (!transformedModifiedFields) {
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
const flattened = attemptFlatten(transformedModifiedFields, modifiedFieldsManipulator);
|
|
171
|
+
if (flattened !== null) {
|
|
172
|
+
transformedEnvelope.modifiedFields = flattened;
|
|
173
|
+
return transformedEnvelope;
|
|
174
|
+
}
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
function attemptUnflatten(modifiedFields) {
|
|
178
|
+
if (typeof modifiedFields === 'object' &&
|
|
179
|
+
modifiedFields !== null &&
|
|
180
|
+
!Array.isArray(modifiedFields)) {
|
|
181
|
+
try {
|
|
182
|
+
const modifiedFieldsManipulator = new ModifiedFieldsManipulator(modifiedFields);
|
|
183
|
+
const unflattened = modifiedFieldsManipulator.unflatten();
|
|
184
|
+
return {
|
|
185
|
+
unflattenedModifiedFields: unflattened,
|
|
186
|
+
modifiedFieldsManipulator,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
function attemptFlatten(transformedModifiedFields, modifiedFieldsManipulator) {
|
|
196
|
+
if (typeof transformedModifiedFields === 'object' &&
|
|
197
|
+
transformedModifiedFields !== null &&
|
|
198
|
+
!Array.isArray(transformedModifiedFields)) {
|
|
199
|
+
try {
|
|
200
|
+
const flattened = modifiedFieldsManipulator.flatten(transformedModifiedFields);
|
|
201
|
+
return flattened;
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return null;
|
|
208
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/sdk",
|
|
3
|
-
"version": "1.17.
|
|
3
|
+
"version": "1.17.5",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Ronny Ringel",
|
|
@@ -73,12 +73,14 @@
|
|
|
73
73
|
},
|
|
74
74
|
"dependencies": {
|
|
75
75
|
"@wix/identity": "^1.0.104",
|
|
76
|
-
"@wix/image-kit": "^1.
|
|
76
|
+
"@wix/image-kit": "^1.114.0",
|
|
77
77
|
"@wix/redirects": "^1.0.70",
|
|
78
78
|
"@wix/sdk-context": "0.0.1",
|
|
79
|
-
"@wix/sdk-runtime": "0.
|
|
80
|
-
"@wix/sdk-types": "1.
|
|
79
|
+
"@wix/sdk-runtime": "1.0.1",
|
|
80
|
+
"@wix/sdk-types": "1.16.0",
|
|
81
|
+
"flat": "^6.0.1",
|
|
81
82
|
"jose": "^5.10.0",
|
|
83
|
+
"lodash": "4.17.20",
|
|
82
84
|
"type-fest": "^4.41.0"
|
|
83
85
|
},
|
|
84
86
|
"optionalDependencies": {
|
|
@@ -86,19 +88,20 @@
|
|
|
86
88
|
},
|
|
87
89
|
"devDependencies": {
|
|
88
90
|
"@types/is-ci": "^3.0.4",
|
|
89
|
-
"@types/
|
|
91
|
+
"@types/lodash": "4.14.202",
|
|
92
|
+
"@types/node": "^20.19.25",
|
|
90
93
|
"@vitest/ui": "^1.6.1",
|
|
91
94
|
"@wix/ecom": "^1.0.886",
|
|
92
95
|
"@wix/events": "^1.0.382",
|
|
93
96
|
"@wix/metro": "^1.0.93",
|
|
94
97
|
"@wix/metro-runtime": "^1.1891.0",
|
|
95
|
-
"@wix/sdk-runtime": "0.
|
|
98
|
+
"@wix/sdk-runtime": "1.0.1",
|
|
96
99
|
"eslint": "^8.57.1",
|
|
97
|
-
"eslint-config-sdk": "
|
|
100
|
+
"eslint-config-sdk": "1.0.0",
|
|
98
101
|
"graphql": "^16.8.0",
|
|
99
102
|
"is-ci": "^3.0.1",
|
|
100
103
|
"jsdom": "^22.1.0",
|
|
101
|
-
"msw": "^2.12.
|
|
104
|
+
"msw": "^2.12.2",
|
|
102
105
|
"typescript": "^5.9.3",
|
|
103
106
|
"vitest": "^1.6.1",
|
|
104
107
|
"vitest-teamcity-reporter": "^0.3.1"
|
|
@@ -126,5 +129,5 @@
|
|
|
126
129
|
"wallaby": {
|
|
127
130
|
"autoDetect": true
|
|
128
131
|
},
|
|
129
|
-
"falconPackageHash": "
|
|
132
|
+
"falconPackageHash": "55220a3363629bf5db4212d74519a60b4fc3fd6bd5021522eaed06c1"
|
|
130
133
|
}
|