@wix/sdk 1.17.4 → 1.17.6

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.
@@ -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 ?? updatedEvent?.currentEntity,
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
- return handler(transformFromRESTFn(envelope));
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,205 @@
1
+ import { unflatten } from 'flat';
2
+ import { RESTResponseToSDKResponseRenameMap } from '@wix/sdk-runtime/rest-modules';
3
+ export class ModifiedFieldsManipulator {
4
+ BRACKET_PATTERN = /\[(\d+)\]/g;
5
+ NUMERIC_PATTERN = /^\d+$/;
6
+ ESCAPED_DOT_PATTERN = /\\\./g;
7
+ ESCAPED_LEFT_BRACKET_PATTERN = /\\\[/g;
8
+ ESCAPED_RIGHT_BRACKET_PATTERN = /\\\]/g;
9
+ SPLIT_PATTERN = /\.|\[(\d+)\]/g;
10
+ DOT_BEFORE_BRACKET_PATTERN = /\.\[/g;
11
+ ESCAPED_DOT_PLACEHOLDER = '__DOT__';
12
+ ESCAPED_RIGHT_BRACKET_PLACEHOLDER = '__RB__';
13
+ ESCAPED_LEFT_BRACKET_PLACEHOLDER = '__LB__';
14
+ modifiedFields;
15
+ cleanedModifiedFields;
16
+ constructor(modifiedFields) {
17
+ this.modifiedFields = modifiedFields;
18
+ }
19
+ replaceEscapedCharacters(key) {
20
+ return key
21
+ .replace(this.ESCAPED_DOT_PATTERN, this.ESCAPED_DOT_PLACEHOLDER)
22
+ .replace(this.ESCAPED_LEFT_BRACKET_PATTERN, this.ESCAPED_LEFT_BRACKET_PLACEHOLDER)
23
+ .replace(this.ESCAPED_RIGHT_BRACKET_PATTERN, this.ESCAPED_RIGHT_BRACKET_PLACEHOLDER);
24
+ }
25
+ restoreEscapedCharacters(key) {
26
+ return key
27
+ .replace(this.ESCAPED_DOT_PLACEHOLDER, '\\.')
28
+ .replace(this.ESCAPED_RIGHT_BRACKET_PLACEHOLDER, '\\]')
29
+ .replace(this.ESCAPED_LEFT_BRACKET_PLACEHOLDER, '\\[');
30
+ }
31
+ unflatten() {
32
+ this.cleanedModifiedFields = Object.fromEntries(Object.entries(this.modifiedFields).map(([key, value]) => [
33
+ this.replaceEscapedCharacters(this.bracketToDotNotation(key)),
34
+ value,
35
+ ]));
36
+ return unflatten(this.cleanedModifiedFields);
37
+ }
38
+ flatten(transformedModifiedFields) {
39
+ let result = {};
40
+ for (const originalKey of Object.keys(this.cleanedModifiedFields)) {
41
+ const pathParts = this.splitPath(originalKey);
42
+ const value = this.navigatePath(transformedModifiedFields, pathParts);
43
+ result = { ...result, ...value };
44
+ }
45
+ return Object.fromEntries(Object.entries(result).map(([key, value]) => [
46
+ this.restoreEscapedCharacters(key),
47
+ value,
48
+ ]));
49
+ }
50
+ splitPath(path) {
51
+ const parts = [];
52
+ let lastIndex = 0;
53
+ const matches = Array.from(path.matchAll(this.SPLIT_PATTERN));
54
+ for (const match of matches) {
55
+ if (match.index > lastIndex) {
56
+ parts.push(path.substring(lastIndex, match.index));
57
+ }
58
+ if (match[1]) {
59
+ parts.push(match[1]);
60
+ }
61
+ lastIndex = match.index + match[0].length;
62
+ }
63
+ if (lastIndex < path.length) {
64
+ parts.push(path.substring(lastIndex));
65
+ }
66
+ return parts;
67
+ }
68
+ navigatePath(obj, pathParts) {
69
+ let current = obj;
70
+ const transformedPath = [];
71
+ const handleArray = (part) => {
72
+ if (!Array.isArray(current)) {
73
+ throw new Error(`Expected array at path ${this.buildPathString(transformedPath)}, but got ${typeof current}`);
74
+ }
75
+ transformedPath.push(`[${part}]`);
76
+ current = current[parseInt(part, 10)];
77
+ };
78
+ const handleTransformedKeyName = (part, currentObj) => {
79
+ const transformedKey = part in RESTResponseToSDKResponseRenameMap
80
+ ? RESTResponseToSDKResponseRenameMap[part]
81
+ : undefined;
82
+ if (transformedKey && transformedKey in currentObj) {
83
+ transformedPath.push(transformedKey);
84
+ current = currentObj[transformedKey];
85
+ return;
86
+ }
87
+ const camelCaseKey = camelCase(part);
88
+ if (camelCaseKey && camelCaseKey in currentObj) {
89
+ transformedPath.push(camelCaseKey);
90
+ current = currentObj[camelCaseKey];
91
+ return;
92
+ }
93
+ throw new Error(`Cannot find key '${part}' or its transformations at path ${this.buildPathString(transformedPath)}`);
94
+ };
95
+ const handleObject = (part, currentObj) => {
96
+ transformedPath.push(part);
97
+ current = currentObj[part];
98
+ return;
99
+ };
100
+ for (const part of pathParts) {
101
+ if (this.NUMERIC_PATTERN.test(part)) {
102
+ handleArray(part);
103
+ continue;
104
+ }
105
+ if (current === null || typeof current !== 'object') {
106
+ throw new Error(`Cannot access property '${part}' on ${typeof current} at path ${this.buildPathString(transformedPath)}`);
107
+ }
108
+ const currentObj = current;
109
+ if (part in current) {
110
+ handleObject(part, currentObj);
111
+ continue;
112
+ }
113
+ handleTransformedKeyName(part, currentObj);
114
+ }
115
+ return { [this.buildPathString(transformedPath)]: current };
116
+ }
117
+ buildPathString(pathParts) {
118
+ return pathParts.join('.').replace(this.DOT_BEFORE_BRACKET_PATTERN, '[');
119
+ }
120
+ bracketToDotNotation(key) {
121
+ return key.replace(this.BRACKET_PATTERN, (match, number, offset) => {
122
+ if (offset > 0 && key[offset - 1] === '\\') {
123
+ return match;
124
+ }
125
+ return '.' + number;
126
+ });
127
+ }
128
+ }
129
+ /**
130
+ * Transforms an envelope while preserving the structure of modifiedFields.
131
+ *
132
+ * Modified fields come as flattened objects, while transformations are applied to the nested object (e.g. "a.b.c" -> { a: { b: { c: 'value' } } }).
133
+ * This function handles the transformation of envelopes that contain flattened modifiedFields.
134
+ * It unflattens the modifiedFields, applies the transformation function, and then flattens
135
+ * the modifiedFields back to their original format while preserving the transformation.
136
+ * @param envelope - The envelope object containing flattened modifiedFields
137
+ * @param transformFromRESTFn - Function to transform the envelope from REST format to SDK format
138
+ * @returns The transformed envelope with flattened modifiedFields, or null if transformation fails
139
+ */
140
+ export function attemptTransformationWithModifiedFields(envelope, transformFromRESTFn) {
141
+ const modifiedFields = envelope?.modifiedFields;
142
+ if (!modifiedFields) {
143
+ return null;
144
+ }
145
+ const unflattenedResult = attemptUnflatten(modifiedFields);
146
+ if (!unflattenedResult) {
147
+ return null;
148
+ }
149
+ const { unflattenedModifiedFields, modifiedFieldsManipulator } = unflattenedResult;
150
+ envelope = {
151
+ ...envelope,
152
+ modifiedFields: unflattenedModifiedFields,
153
+ };
154
+ const transformedEnvelope = transformFromRESTFn(envelope);
155
+ const transformedModifiedFields = transformedEnvelope
156
+ ?.modifiedFields;
157
+ if (!transformedModifiedFields) {
158
+ return null;
159
+ }
160
+ const flattened = attemptFlatten(transformedModifiedFields, modifiedFieldsManipulator);
161
+ if (flattened !== null) {
162
+ transformedEnvelope.modifiedFields = flattened;
163
+ return transformedEnvelope;
164
+ }
165
+ return null;
166
+ }
167
+ function attemptUnflatten(modifiedFields) {
168
+ if (typeof modifiedFields === 'object' &&
169
+ modifiedFields !== null &&
170
+ !Array.isArray(modifiedFields)) {
171
+ try {
172
+ const modifiedFieldsManipulator = new ModifiedFieldsManipulator(modifiedFields);
173
+ const unflattened = modifiedFieldsManipulator.unflatten();
174
+ return {
175
+ unflattenedModifiedFields: unflattened,
176
+ modifiedFieldsManipulator,
177
+ };
178
+ }
179
+ catch (error) {
180
+ return null;
181
+ }
182
+ }
183
+ return null;
184
+ }
185
+ function attemptFlatten(transformedModifiedFields, modifiedFieldsManipulator) {
186
+ if (typeof transformedModifiedFields === 'object' &&
187
+ transformedModifiedFields !== null &&
188
+ !Array.isArray(transformedModifiedFields)) {
189
+ try {
190
+ const flattened = modifiedFieldsManipulator.flatten(transformedModifiedFields);
191
+ return flattened;
192
+ }
193
+ catch (error) {
194
+ return null;
195
+ }
196
+ }
197
+ return null;
198
+ }
199
+ // Simple camelCase implementation to avoid lodash (which uses `new Function()` internally
200
+ // and breaks Cloudflare Workers/Edge runtimes)
201
+ function camelCase(str) {
202
+ return str
203
+ .replace(/[-_\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ''))
204
+ .replace(/^./, (c) => c.toLowerCase());
205
+ }
@@ -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 ?? updatedEvent?.currentEntity,
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
- return handler(transformFromRESTFn(envelope));
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,210 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ModifiedFieldsManipulator = void 0;
4
+ exports.attemptTransformationWithModifiedFields = attemptTransformationWithModifiedFields;
5
+ const flat_1 = require("flat");
6
+ const rest_modules_1 = require("@wix/sdk-runtime/rest-modules");
7
+ class ModifiedFieldsManipulator {
8
+ BRACKET_PATTERN = /\[(\d+)\]/g;
9
+ NUMERIC_PATTERN = /^\d+$/;
10
+ ESCAPED_DOT_PATTERN = /\\\./g;
11
+ ESCAPED_LEFT_BRACKET_PATTERN = /\\\[/g;
12
+ ESCAPED_RIGHT_BRACKET_PATTERN = /\\\]/g;
13
+ SPLIT_PATTERN = /\.|\[(\d+)\]/g;
14
+ DOT_BEFORE_BRACKET_PATTERN = /\.\[/g;
15
+ ESCAPED_DOT_PLACEHOLDER = '__DOT__';
16
+ ESCAPED_RIGHT_BRACKET_PLACEHOLDER = '__RB__';
17
+ ESCAPED_LEFT_BRACKET_PLACEHOLDER = '__LB__';
18
+ modifiedFields;
19
+ cleanedModifiedFields;
20
+ constructor(modifiedFields) {
21
+ this.modifiedFields = modifiedFields;
22
+ }
23
+ replaceEscapedCharacters(key) {
24
+ return key
25
+ .replace(this.ESCAPED_DOT_PATTERN, this.ESCAPED_DOT_PLACEHOLDER)
26
+ .replace(this.ESCAPED_LEFT_BRACKET_PATTERN, this.ESCAPED_LEFT_BRACKET_PLACEHOLDER)
27
+ .replace(this.ESCAPED_RIGHT_BRACKET_PATTERN, this.ESCAPED_RIGHT_BRACKET_PLACEHOLDER);
28
+ }
29
+ restoreEscapedCharacters(key) {
30
+ return key
31
+ .replace(this.ESCAPED_DOT_PLACEHOLDER, '\\.')
32
+ .replace(this.ESCAPED_RIGHT_BRACKET_PLACEHOLDER, '\\]')
33
+ .replace(this.ESCAPED_LEFT_BRACKET_PLACEHOLDER, '\\[');
34
+ }
35
+ unflatten() {
36
+ this.cleanedModifiedFields = Object.fromEntries(Object.entries(this.modifiedFields).map(([key, value]) => [
37
+ this.replaceEscapedCharacters(this.bracketToDotNotation(key)),
38
+ value,
39
+ ]));
40
+ return (0, flat_1.unflatten)(this.cleanedModifiedFields);
41
+ }
42
+ flatten(transformedModifiedFields) {
43
+ let result = {};
44
+ for (const originalKey of Object.keys(this.cleanedModifiedFields)) {
45
+ const pathParts = this.splitPath(originalKey);
46
+ const value = this.navigatePath(transformedModifiedFields, pathParts);
47
+ result = { ...result, ...value };
48
+ }
49
+ return Object.fromEntries(Object.entries(result).map(([key, value]) => [
50
+ this.restoreEscapedCharacters(key),
51
+ value,
52
+ ]));
53
+ }
54
+ splitPath(path) {
55
+ const parts = [];
56
+ let lastIndex = 0;
57
+ const matches = Array.from(path.matchAll(this.SPLIT_PATTERN));
58
+ for (const match of matches) {
59
+ if (match.index > lastIndex) {
60
+ parts.push(path.substring(lastIndex, match.index));
61
+ }
62
+ if (match[1]) {
63
+ parts.push(match[1]);
64
+ }
65
+ lastIndex = match.index + match[0].length;
66
+ }
67
+ if (lastIndex < path.length) {
68
+ parts.push(path.substring(lastIndex));
69
+ }
70
+ return parts;
71
+ }
72
+ navigatePath(obj, pathParts) {
73
+ let current = obj;
74
+ const transformedPath = [];
75
+ const handleArray = (part) => {
76
+ if (!Array.isArray(current)) {
77
+ throw new Error(`Expected array at path ${this.buildPathString(transformedPath)}, but got ${typeof current}`);
78
+ }
79
+ transformedPath.push(`[${part}]`);
80
+ current = current[parseInt(part, 10)];
81
+ };
82
+ const handleTransformedKeyName = (part, currentObj) => {
83
+ const transformedKey = part in rest_modules_1.RESTResponseToSDKResponseRenameMap
84
+ ? rest_modules_1.RESTResponseToSDKResponseRenameMap[part]
85
+ : undefined;
86
+ if (transformedKey && transformedKey in currentObj) {
87
+ transformedPath.push(transformedKey);
88
+ current = currentObj[transformedKey];
89
+ return;
90
+ }
91
+ const camelCaseKey = camelCase(part);
92
+ if (camelCaseKey && camelCaseKey in currentObj) {
93
+ transformedPath.push(camelCaseKey);
94
+ current = currentObj[camelCaseKey];
95
+ return;
96
+ }
97
+ throw new Error(`Cannot find key '${part}' or its transformations at path ${this.buildPathString(transformedPath)}`);
98
+ };
99
+ const handleObject = (part, currentObj) => {
100
+ transformedPath.push(part);
101
+ current = currentObj[part];
102
+ return;
103
+ };
104
+ for (const part of pathParts) {
105
+ if (this.NUMERIC_PATTERN.test(part)) {
106
+ handleArray(part);
107
+ continue;
108
+ }
109
+ if (current === null || typeof current !== 'object') {
110
+ throw new Error(`Cannot access property '${part}' on ${typeof current} at path ${this.buildPathString(transformedPath)}`);
111
+ }
112
+ const currentObj = current;
113
+ if (part in current) {
114
+ handleObject(part, currentObj);
115
+ continue;
116
+ }
117
+ handleTransformedKeyName(part, currentObj);
118
+ }
119
+ return { [this.buildPathString(transformedPath)]: current };
120
+ }
121
+ buildPathString(pathParts) {
122
+ return pathParts.join('.').replace(this.DOT_BEFORE_BRACKET_PATTERN, '[');
123
+ }
124
+ bracketToDotNotation(key) {
125
+ return key.replace(this.BRACKET_PATTERN, (match, number, offset) => {
126
+ if (offset > 0 && key[offset - 1] === '\\') {
127
+ return match;
128
+ }
129
+ return '.' + number;
130
+ });
131
+ }
132
+ }
133
+ exports.ModifiedFieldsManipulator = ModifiedFieldsManipulator;
134
+ /**
135
+ * Transforms an envelope while preserving the structure of modifiedFields.
136
+ *
137
+ * Modified fields come as flattened objects, while transformations are applied to the nested object (e.g. "a.b.c" -> { a: { b: { c: 'value' } } }).
138
+ * This function handles the transformation of envelopes that contain flattened modifiedFields.
139
+ * It unflattens the modifiedFields, applies the transformation function, and then flattens
140
+ * the modifiedFields back to their original format while preserving the transformation.
141
+ * @param envelope - The envelope object containing flattened modifiedFields
142
+ * @param transformFromRESTFn - Function to transform the envelope from REST format to SDK format
143
+ * @returns The transformed envelope with flattened modifiedFields, or null if transformation fails
144
+ */
145
+ function attemptTransformationWithModifiedFields(envelope, transformFromRESTFn) {
146
+ const modifiedFields = envelope?.modifiedFields;
147
+ if (!modifiedFields) {
148
+ return null;
149
+ }
150
+ const unflattenedResult = attemptUnflatten(modifiedFields);
151
+ if (!unflattenedResult) {
152
+ return null;
153
+ }
154
+ const { unflattenedModifiedFields, modifiedFieldsManipulator } = unflattenedResult;
155
+ envelope = {
156
+ ...envelope,
157
+ modifiedFields: unflattenedModifiedFields,
158
+ };
159
+ const transformedEnvelope = transformFromRESTFn(envelope);
160
+ const transformedModifiedFields = transformedEnvelope
161
+ ?.modifiedFields;
162
+ if (!transformedModifiedFields) {
163
+ return null;
164
+ }
165
+ const flattened = attemptFlatten(transformedModifiedFields, modifiedFieldsManipulator);
166
+ if (flattened !== null) {
167
+ transformedEnvelope.modifiedFields = flattened;
168
+ return transformedEnvelope;
169
+ }
170
+ return null;
171
+ }
172
+ function attemptUnflatten(modifiedFields) {
173
+ if (typeof modifiedFields === 'object' &&
174
+ modifiedFields !== null &&
175
+ !Array.isArray(modifiedFields)) {
176
+ try {
177
+ const modifiedFieldsManipulator = new ModifiedFieldsManipulator(modifiedFields);
178
+ const unflattened = modifiedFieldsManipulator.unflatten();
179
+ return {
180
+ unflattenedModifiedFields: unflattened,
181
+ modifiedFieldsManipulator,
182
+ };
183
+ }
184
+ catch (error) {
185
+ return null;
186
+ }
187
+ }
188
+ return null;
189
+ }
190
+ function attemptFlatten(transformedModifiedFields, modifiedFieldsManipulator) {
191
+ if (typeof transformedModifiedFields === 'object' &&
192
+ transformedModifiedFields !== null &&
193
+ !Array.isArray(transformedModifiedFields)) {
194
+ try {
195
+ const flattened = modifiedFieldsManipulator.flatten(transformedModifiedFields);
196
+ return flattened;
197
+ }
198
+ catch (error) {
199
+ return null;
200
+ }
201
+ }
202
+ return null;
203
+ }
204
+ // Simple camelCase implementation to avoid lodash (which uses `new Function()` internally
205
+ // and breaks Cloudflare Workers/Edge runtimes)
206
+ function camelCase(str) {
207
+ return str
208
+ .replace(/[-_\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ''))
209
+ .replace(/^./, (c) => c.toLowerCase());
210
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/sdk",
3
- "version": "1.17.4",
3
+ "version": "1.17.6",
4
4
  "license": "MIT",
5
5
  "author": {
6
6
  "name": "Ronny Ringel",
@@ -76,8 +76,9 @@
76
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": "1.0.0",
80
- "@wix/sdk-types": "1.14.0",
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",
82
83
  "type-fest": "^4.41.0"
83
84
  },
@@ -86,19 +87,19 @@
86
87
  },
87
88
  "devDependencies": {
88
89
  "@types/is-ci": "^3.0.4",
89
- "@types/node": "^20.19.24",
90
+ "@types/node": "^20.19.25",
90
91
  "@vitest/ui": "^1.6.1",
91
92
  "@wix/ecom": "^1.0.886",
92
93
  "@wix/events": "^1.0.382",
93
94
  "@wix/metro": "^1.0.93",
94
95
  "@wix/metro-runtime": "^1.1891.0",
95
- "@wix/sdk-runtime": "1.0.0",
96
+ "@wix/sdk-runtime": "1.0.1",
96
97
  "eslint": "^8.57.1",
97
98
  "eslint-config-sdk": "1.0.0",
98
99
  "graphql": "^16.8.0",
99
100
  "is-ci": "^3.0.1",
100
101
  "jsdom": "^22.1.0",
101
- "msw": "^2.12.0",
102
+ "msw": "^2.12.2",
102
103
  "typescript": "^5.9.3",
103
104
  "vitest": "^1.6.1",
104
105
  "vitest-teamcity-reporter": "^0.3.1"
@@ -126,5 +127,5 @@
126
127
  "wallaby": {
127
128
  "autoDetect": true
128
129
  },
129
- "falconPackageHash": "eacf57f635a721131d0cbb326058cde3c0bdde089387ae82f60df8d5"
130
+ "falconPackageHash": "25d16bf9f75c7cef263c96b55f2354cca27dc38f4cb230c62b00251f"
130
131
  }