@uniformdev/canvas 20.48.1-alpha.28 → 20.48.1-alpha.33.sha-eb3f272086

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/dist/index.esm.js CHANGED
@@ -1,608 +1,748 @@
1
- var __create = Object.create;
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __getProtoOf = Object.getPrototypeOf;
6
- var __hasOwnProp = Object.prototype.hasOwnProperty;
7
1
  var __typeError = (msg) => {
8
2
  throw TypeError(msg);
9
3
  };
10
- var __commonJS = (cb, mod) => function __require() {
11
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
12
- };
13
- var __copyProps = (to, from, except, desc) => {
14
- if (from && typeof from === "object" || typeof from === "function") {
15
- for (let key of __getOwnPropNames(from))
16
- if (!__hasOwnProp.call(to, key) && key !== except)
17
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
- }
19
- return to;
20
- };
21
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
- // If the importer is in node compatibility mode or this is not an ESM
23
- // file that has been converted to a CommonJS file using a Babel-
24
- // compatible transform (i.e. "__esModule" has not been set), then set
25
- // "default" to the CommonJS "module.exports" for node compatibility.
26
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
- mod
28
- ));
29
4
  var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
30
5
  var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
31
6
  var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
32
7
 
33
- // ../../node_modules/.pnpm/yocto-queue@0.1.0/node_modules/yocto-queue/index.js
34
- var require_yocto_queue = __commonJS({
35
- "../../node_modules/.pnpm/yocto-queue@0.1.0/node_modules/yocto-queue/index.js"(exports, module) {
36
- "use strict";
37
- var Node = class {
38
- /// value;
39
- /// next;
40
- constructor(value) {
41
- this.value = value;
42
- this.next = void 0;
43
- }
44
- };
45
- var Queue = class {
46
- // TODO: Use private class fields when targeting Node.js 12.
47
- // #_head;
48
- // #_tail;
49
- // #_size;
50
- constructor() {
51
- this.clear();
52
- }
53
- enqueue(value) {
54
- const node = new Node(value);
55
- if (this._head) {
56
- this._tail.next = node;
57
- this._tail = node;
58
- } else {
59
- this._head = node;
60
- this._tail = node;
61
- }
62
- this._size++;
63
- }
64
- dequeue() {
65
- const current = this._head;
66
- if (!current) {
67
- return;
68
- }
69
- this._head = this._head.next;
70
- this._size--;
71
- return current.value;
72
- }
73
- clear() {
74
- this._head = void 0;
75
- this._tail = void 0;
76
- this._size = 0;
77
- }
78
- get size() {
79
- return this._size;
80
- }
81
- *[Symbol.iterator]() {
82
- let current = this._head;
83
- while (current) {
84
- yield current.value;
85
- current = current.next;
86
- }
87
- }
88
- };
89
- module.exports = Queue;
90
- }
91
- });
92
-
93
- // ../../node_modules/.pnpm/p-limit@3.1.0/node_modules/p-limit/index.js
94
- var require_p_limit = __commonJS({
95
- "../../node_modules/.pnpm/p-limit@3.1.0/node_modules/p-limit/index.js"(exports, module) {
96
- "use strict";
97
- var Queue = require_yocto_queue();
98
- var pLimit2 = (concurrency) => {
99
- if (!((Number.isInteger(concurrency) || concurrency === Infinity) && concurrency > 0)) {
100
- throw new TypeError("Expected `concurrency` to be a number from 1 and up");
101
- }
102
- const queue = new Queue();
103
- let activeCount = 0;
104
- const next = () => {
105
- activeCount--;
106
- if (queue.size > 0) {
107
- queue.dequeue()();
108
- }
109
- };
110
- const run = async (fn, resolve, ...args) => {
111
- activeCount++;
112
- const result = (async () => fn(...args))();
113
- resolve(result);
114
- try {
115
- await result;
116
- } catch (e) {
117
- }
118
- next();
119
- };
120
- const enqueue = (fn, resolve, ...args) => {
121
- queue.enqueue(run.bind(null, fn, resolve, ...args));
122
- (async () => {
123
- await Promise.resolve();
124
- if (activeCount < concurrency && queue.size > 0) {
125
- queue.dequeue()();
8
+ // src/CategoryClient.ts
9
+ import { ApiClient } from "@uniformdev/context/api";
10
+
11
+ // src/enhancement/createLimitPolicy.ts
12
+ import { ApiClientError } from "@uniformdev/context/api";
13
+ import pLimit from "p-limit";
14
+ import pRetry from "p-retry";
15
+ import pThrottle from "p-throttle";
16
+ function createLimitPolicy({
17
+ throttle = { interval: 1e3, limit: 10 },
18
+ retry = { retries: 1, factor: 1.66 },
19
+ limit = 10
20
+ }) {
21
+ const throttler = throttle ? pThrottle(throttle) : null;
22
+ const limiter = limit ? pLimit(limit) : null;
23
+ return function limitPolicy(func) {
24
+ let currentFunc = async () => await func();
25
+ if (throttler) {
26
+ const throttleFunc = currentFunc;
27
+ currentFunc = throttler(throttleFunc);
28
+ }
29
+ if (limiter) {
30
+ const limitFunc = currentFunc;
31
+ currentFunc = () => limiter(limitFunc);
32
+ }
33
+ if (retry) {
34
+ const retryFunc = currentFunc;
35
+ currentFunc = () => pRetry(retryFunc, {
36
+ ...retry,
37
+ onFailedAttempt: async (error) => {
38
+ if (retry.onFailedAttempt) {
39
+ await retry.onFailedAttempt(error);
126
40
  }
127
- })();
128
- };
129
- const generator = (fn, ...args) => new Promise((resolve) => {
130
- enqueue(fn, resolve, ...args);
131
- });
132
- Object.defineProperties(generator, {
133
- activeCount: {
134
- get: () => activeCount
135
- },
136
- pendingCount: {
137
- get: () => queue.size
138
- },
139
- clearQueue: {
140
- value: () => {
141
- queue.clear();
41
+ if (error instanceof ApiClientError && typeof error.statusCode === "number" && error.statusCode >= 400 && error.statusCode < 500 && error.statusCode !== 429 && error.statusCode !== 408) {
42
+ throw error;
142
43
  }
143
44
  }
144
45
  });
145
- return generator;
146
- };
147
- module.exports = pLimit2;
46
+ }
47
+ return currentFunc();
48
+ };
49
+ }
50
+ var nullLimitPolicy = async (func) => await func();
51
+
52
+ // src/CategoryClient.ts
53
+ var CATEGORIES_URL = "/api/v1/categories";
54
+ var CategoryClient = class extends ApiClient {
55
+ constructor(options) {
56
+ if (!options.limitPolicy) {
57
+ options.limitPolicy = createLimitPolicy({});
58
+ }
59
+ super(options);
60
+ }
61
+ /** Fetches a list of categories created in given project */
62
+ async list(options) {
63
+ const { projectId } = this.options;
64
+ const fetchUri = this.createUrl("/api/v1/categories", { ...options, projectId });
65
+ return await this.apiClient(fetchUri);
66
+ }
67
+ /** @deprecated Use {@link list} instead. */
68
+ async getCategories(options) {
69
+ return this.list(options);
70
+ }
71
+ /** Updates or creates a category, also used to re-order them */
72
+ async save(categories) {
73
+ const { projectId } = this.options;
74
+ const fetchUri = this.createUrl(CATEGORIES_URL);
75
+ return await this.apiClient(fetchUri, {
76
+ method: "PUT",
77
+ body: JSON.stringify({ categories, projectId }),
78
+ expectNoContent: true
79
+ });
80
+ }
81
+ /** @deprecated Use {@link save} instead. */
82
+ async upsertCategories(categories) {
83
+ return this.save(categories);
84
+ }
85
+ /** Deletes a category */
86
+ async remove(options) {
87
+ const { projectId } = this.options;
88
+ const fetchUri = this.createUrl(CATEGORIES_URL);
89
+ return await this.apiClient(fetchUri, {
90
+ method: "DELETE",
91
+ body: JSON.stringify({ projectId, categoryId: options.categoryId }),
92
+ expectNoContent: true
93
+ });
94
+ }
95
+ /** @deprecated Use {@link remove} instead. */
96
+ async removeCategory(options) {
97
+ return this.remove(options);
98
+ }
99
+ };
100
+ var UncachedCategoryClient = class extends CategoryClient {
101
+ constructor(options) {
102
+ super({ ...options, bypassCache: true });
103
+ }
104
+ };
105
+
106
+ // src/clients/ComponentDefinitionClient.ts
107
+ import { ApiClientError as ApiClientError2 } from "@uniformdev/context/api";
108
+
109
+ // src/clients/ContentClientBase.ts
110
+ import { ApiClient as ApiClient2 } from "@uniformdev/context/api";
111
+ var CANONICAL_FORMAT = "canonical";
112
+ var ContentClientBase = class extends ApiClient2 {
113
+ constructor(options, defaultBypassCache) {
114
+ var _a, _b;
115
+ super({
116
+ ...options,
117
+ limitPolicy: (_a = options.limitPolicy) != null ? _a : createLimitPolicy({}),
118
+ bypassCache: (_b = options.bypassCache) != null ? _b : defaultBypassCache
119
+ });
148
120
  }
149
- });
121
+ };
150
122
 
151
- // ../../node_modules/.pnpm/retry@0.13.1/node_modules/retry/lib/retry_operation.js
152
- var require_retry_operation = __commonJS({
153
- "../../node_modules/.pnpm/retry@0.13.1/node_modules/retry/lib/retry_operation.js"(exports, module) {
154
- "use strict";
155
- function RetryOperation(timeouts, options) {
156
- if (typeof options === "boolean") {
157
- options = { forever: options };
158
- }
159
- this._originalTimeouts = JSON.parse(JSON.stringify(timeouts));
160
- this._timeouts = timeouts;
161
- this._options = options || {};
162
- this._maxRetryTime = options && options.maxRetryTime || Infinity;
163
- this._fn = null;
164
- this._errors = [];
165
- this._attempts = 1;
166
- this._operationTimeout = null;
167
- this._operationTimeoutCb = null;
168
- this._timeout = null;
169
- this._operationStart = null;
170
- this._timer = null;
171
- if (this._options.forever) {
172
- this._cachedTimeouts = this._timeouts.slice(0);
173
- }
123
+ // src/clients/ComponentDefinitionClient.ts
124
+ var DEFINITIONS_URL = "/api/v1/canvas-definitions";
125
+ var ComponentDefinitionClient = class extends ContentClientBase {
126
+ constructor(options) {
127
+ super(
128
+ options,
129
+ /* defaultBypassCache */
130
+ true
131
+ );
132
+ }
133
+ /** Fetches one component definition by id (throws `ApiClientError(404)` if absent). */
134
+ async get(args) {
135
+ var _a;
136
+ const url = this.createUrl(DEFINITIONS_URL, {
137
+ componentId: args.componentId,
138
+ projectId: this.options.projectId
139
+ });
140
+ const res = await this.apiClient(url);
141
+ const definition = (_a = res.componentDefinitions) == null ? void 0 : _a[0];
142
+ if (!definition) {
143
+ throw new ApiClientError2("Component definition not found", "GET", url.toString(), 404, "Not Found");
174
144
  }
175
- module.exports = RetryOperation;
176
- RetryOperation.prototype.reset = function() {
177
- this._attempts = 1;
178
- this._timeouts = this._originalTimeouts.slice(0);
179
- };
180
- RetryOperation.prototype.stop = function() {
181
- if (this._timeout) {
182
- clearTimeout(this._timeout);
183
- }
184
- if (this._timer) {
185
- clearTimeout(this._timer);
186
- }
187
- this._timeouts = [];
188
- this._cachedTimeouts = null;
189
- };
190
- RetryOperation.prototype.retry = function(err) {
191
- if (this._timeout) {
192
- clearTimeout(this._timeout);
193
- }
194
- if (!err) {
195
- return false;
196
- }
197
- var currentTime = (/* @__PURE__ */ new Date()).getTime();
198
- if (err && currentTime - this._operationStart >= this._maxRetryTime) {
199
- this._errors.push(err);
200
- this._errors.unshift(new Error("RetryOperation timeout occurred"));
201
- return false;
202
- }
203
- this._errors.push(err);
204
- var timeout = this._timeouts.shift();
205
- if (timeout === void 0) {
206
- if (this._cachedTimeouts) {
207
- this._errors.splice(0, this._errors.length - 1);
208
- timeout = this._cachedTimeouts.slice(-1);
209
- } else {
210
- return false;
211
- }
212
- }
213
- var self = this;
214
- this._timer = setTimeout(function() {
215
- self._attempts++;
216
- if (self._operationTimeoutCb) {
217
- self._timeout = setTimeout(function() {
218
- self._operationTimeoutCb(self._attempts);
219
- }, self._operationTimeout);
220
- if (self._options.unref) {
221
- self._timeout.unref();
222
- }
223
- }
224
- self._fn(self._attempts);
225
- }, timeout);
226
- if (this._options.unref) {
227
- this._timer.unref();
228
- }
229
- return true;
230
- };
231
- RetryOperation.prototype.attempt = function(fn, timeoutOps) {
232
- this._fn = fn;
233
- if (timeoutOps) {
234
- if (timeoutOps.timeout) {
235
- this._operationTimeout = timeoutOps.timeout;
236
- }
237
- if (timeoutOps.cb) {
238
- this._operationTimeoutCb = timeoutOps.cb;
239
- }
240
- }
241
- var self = this;
242
- if (this._operationTimeoutCb) {
243
- this._timeout = setTimeout(function() {
244
- self._operationTimeoutCb();
245
- }, self._operationTimeout);
246
- }
247
- this._operationStart = (/* @__PURE__ */ new Date()).getTime();
248
- this._fn(this._attempts);
249
- };
250
- RetryOperation.prototype.try = function(fn) {
251
- console.log("Using RetryOperation.try() is deprecated");
252
- this.attempt(fn);
253
- };
254
- RetryOperation.prototype.start = function(fn) {
255
- console.log("Using RetryOperation.start() is deprecated");
256
- this.attempt(fn);
257
- };
258
- RetryOperation.prototype.start = RetryOperation.prototype.try;
259
- RetryOperation.prototype.errors = function() {
260
- return this._errors;
261
- };
262
- RetryOperation.prototype.attempts = function() {
263
- return this._attempts;
264
- };
265
- RetryOperation.prototype.mainError = function() {
266
- if (this._errors.length === 0) {
267
- return null;
268
- }
269
- var counts = {};
270
- var mainError = null;
271
- var mainErrorCount = 0;
272
- for (var i = 0; i < this._errors.length; i++) {
273
- var error = this._errors[i];
274
- var message = error.message;
275
- var count = (counts[message] || 0) + 1;
276
- counts[message] = count;
277
- if (count >= mainErrorCount) {
278
- mainError = error;
279
- mainErrorCount = count;
145
+ return definition;
146
+ }
147
+ /** Fetches a list of component definitions. */
148
+ list(args) {
149
+ const url = this.createUrl(DEFINITIONS_URL, { ...args, projectId: this.options.projectId });
150
+ return this.apiClient(url);
151
+ }
152
+ /** Creates or updates a component definition. */
153
+ async save(def) {
154
+ const url = this.createUrl(DEFINITIONS_URL);
155
+ await this.apiClient(url, {
156
+ method: "PUT",
157
+ body: JSON.stringify({ ...def, projectId: this.options.projectId }),
158
+ expectNoContent: true
159
+ });
160
+ }
161
+ /** Deletes a component definition. */
162
+ async remove(args) {
163
+ const url = this.createUrl(DEFINITIONS_URL);
164
+ await this.apiClient(url, {
165
+ method: "DELETE",
166
+ body: JSON.stringify({ ...args, projectId: this.options.projectId }),
167
+ expectNoContent: true
168
+ });
169
+ }
170
+ };
171
+
172
+ // src/clients/CompositionDeliveryClient.ts
173
+ import { rewriteFiltersForApi } from "@uniformdev/context/api";
174
+
175
+ // src/projection/types.ts
176
+ var SELECT_QUERY_PREFIX = "select.";
177
+
178
+ // src/projection/projectionToQuery.ts
179
+ function appendCsv(out, key, values) {
180
+ if (values === void 0) {
181
+ return;
182
+ }
183
+ out[key] = values.join(",");
184
+ }
185
+ function projectionToQuery(spec) {
186
+ const out = {};
187
+ if (!spec) {
188
+ return out;
189
+ }
190
+ const { fields, fieldTypes, slots } = spec;
191
+ const p = SELECT_QUERY_PREFIX;
192
+ if (fields) {
193
+ appendCsv(out, `${p}fields[only]`, fields.only);
194
+ appendCsv(out, `${p}fields[except]`, fields.except);
195
+ appendCsv(out, `${p}fields[locales]`, fields.locales);
196
+ if (fields.blockDepth === "preserveAll" || typeof fields.blockDepth === "number") {
197
+ out[`${p}fields[blockDepth]`] = String(fields.blockDepth);
198
+ }
199
+ }
200
+ if (fieldTypes) {
201
+ appendCsv(out, `${p}fieldTypes[only]`, fieldTypes.only);
202
+ appendCsv(out, `${p}fieldTypes[except]`, fieldTypes.except);
203
+ }
204
+ if (slots) {
205
+ appendCsv(out, `${p}slots[only]`, slots.only);
206
+ appendCsv(out, `${p}slots[except]`, slots.except);
207
+ if (typeof slots.depth === "number") {
208
+ out[`${p}slots[depth]`] = String(slots.depth);
209
+ }
210
+ if (slots.named) {
211
+ const slotNames = Object.keys(slots.named).sort();
212
+ for (const slotName of slotNames) {
213
+ const named = slots.named[slotName];
214
+ if (named && typeof named.depth === "number") {
215
+ out[`${p}slots.${slotName}[depth]`] = String(named.depth);
280
216
  }
281
217
  }
282
- return mainError;
283
- };
218
+ }
284
219
  }
285
- });
286
-
287
- // ../../node_modules/.pnpm/retry@0.13.1/node_modules/retry/lib/retry.js
288
- var require_retry = __commonJS({
289
- "../../node_modules/.pnpm/retry@0.13.1/node_modules/retry/lib/retry.js"(exports) {
290
- "use strict";
291
- var RetryOperation = require_retry_operation();
292
- exports.operation = function(options) {
293
- var timeouts = exports.timeouts(options);
294
- return new RetryOperation(timeouts, {
295
- forever: options && (options.forever || options.retries === Infinity),
296
- unref: options && options.unref,
297
- maxRetryTime: options && options.maxRetryTime
298
- });
299
- };
300
- exports.timeouts = function(options) {
301
- if (options instanceof Array) {
302
- return [].concat(options);
303
- }
304
- var opts = {
305
- retries: 10,
306
- factor: 2,
307
- minTimeout: 1 * 1e3,
308
- maxTimeout: Infinity,
309
- randomize: false
310
- };
311
- for (var key in options) {
312
- opts[key] = options[key];
313
- }
314
- if (opts.minTimeout > opts.maxTimeout) {
315
- throw new Error("minTimeout is greater than maxTimeout");
316
- }
317
- var timeouts = [];
318
- for (var i = 0; i < opts.retries; i++) {
319
- timeouts.push(this.createTimeout(i, opts));
320
- }
321
- if (options && options.forever && !timeouts.length) {
322
- timeouts.push(this.createTimeout(i, opts));
323
- }
324
- timeouts.sort(function(a, b) {
325
- return a - b;
326
- });
327
- return timeouts;
328
- };
329
- exports.createTimeout = function(attempt, opts) {
330
- var random = opts.randomize ? Math.random() + 1 : 1;
331
- var timeout = Math.round(random * Math.max(opts.minTimeout, 1) * Math.pow(opts.factor, attempt));
332
- timeout = Math.min(timeout, opts.maxTimeout);
333
- return timeout;
220
+ return out;
221
+ }
222
+
223
+ // src/utils/constants.ts
224
+ var CANVAS_PERSONALIZE_TYPE = "$personalization";
225
+ var CANVAS_TEST_TYPE = "$test";
226
+ var CANVAS_LOCALIZATION_TYPE = "$localization";
227
+ var CANVAS_SLOT_SECTION_TYPE = "$slotSection";
228
+ var CANVAS_INTENT_TAG_PARAM = "intentTag";
229
+ var CANVAS_LOCALE_TAG_PARAM = "locale";
230
+ var CANVAS_BLOCK_PARAM_TYPE = "$block";
231
+ var CANVAS_PERSONALIZE_SLOT = "pz";
232
+ var CANVAS_TEST_SLOT = "test";
233
+ var CANVAS_LOCALIZATION_SLOT = "localized";
234
+ var CANVAS_SLOT_SECTION_SLOT = "$slotSectionItems";
235
+ var CANVAS_SLOT_SECTION_NAME_PARAM = "name";
236
+ var CANVAS_SLOT_SECTION_MIN_PARAM = "min";
237
+ var CANVAS_SLOT_SECTION_MAX_PARAM = "max";
238
+ var CANVAS_SLOT_SECTION_GROUP_TYPE_PARAM = "groupType";
239
+ var CANVAS_SLOT_SECTION_SPECIFIC_PARAM = "specific";
240
+ var CANVAS_DRAFT_STATE = 0;
241
+ var CANVAS_PUBLISHED_STATE = 64;
242
+ var CANVAS_EDITOR_STATE = 63;
243
+ var CANVAS_PERSONALIZATION_PARAM = "$pzCrit";
244
+ var CANVAS_PERSONALIZATION_EVENT_NAME_PARAM = "trackingEventName";
245
+ var CANVAS_PERSONALIZATION_ALGORITHM_PARAM = "algorithm";
246
+ var CANVAS_PERSONALIZATION_ALGORITHM_TYPE = "pzAlgorithm";
247
+ var CANVAS_PERSONALIZATION_TAKE_PARAM = "count";
248
+ var CANVAS_TEST_VARIANT_PARAM = "$tstVrnt";
249
+ var CANVAS_ENRICHMENT_TAG_PARAM = "$enr";
250
+ var CANVAS_INTERNAL_PARAM_PREFIX = "$internal_";
251
+ var CANVAS_COMPONENT_DISPLAY_NAME_PARAM = `${CANVAS_INTERNAL_PARAM_PREFIX}displayName`;
252
+ var CANVAS_HYPOTHESIS_PARAM = `${CANVAS_INTERNAL_PARAM_PREFIX}hypothesis`;
253
+ var CANVAS_CONTEXTUAL_EDITING_PARAM = "$contextualEditing";
254
+ var SECRET_QUERY_STRING_PARAM = "secret";
255
+ var IN_CONTEXT_EDITOR_QUERY_STRING_PARAM = "is_incontext_editing_mode";
256
+ var IN_CONTEXT_EDITOR_PLAYGROUND_QUERY_STRING_PARAM = "is_incontext_editing_playground";
257
+ var IN_CONTEXT_EDITOR_FORCED_SETTINGS_QUERY_STRING_PARAM = "is_incontext_editing_forced_settings";
258
+ var IN_CONTEXT_EDITOR_CONFIG_CHECK_QUERY_STRING_PARAM = "is_config_check";
259
+ var IN_CONTEXT_EDITOR_COMPONENT_START_ROLE = "uniform-component-start";
260
+ var IN_CONTEXT_EDITOR_COMPONENT_END_ROLE = "uniform-component-end";
261
+ var IN_CONTEXT_EDITOR_EMBED_SCRIPT_ID = "uniform-canvas-preview-script";
262
+ var IS_RENDERED_BY_UNIFORM_ATTRIBUTE = "data-is-rendered-by-uniform";
263
+ var PLACEHOLDER_ID = "placeholder";
264
+ var EMPTY_COMPOSITION = {
265
+ _id: "_empty_composition_id",
266
+ _name: "An empty composition used for contextual editing",
267
+ type: "_empty_composition_type"
268
+ };
269
+ var EDGE_MIN_CACHE_TTL = 10;
270
+ var EDGE_MAX_CACHE_TTL = 24 * 60 * 60;
271
+ var EDGE_DEFAULT_CACHE_TTL = 30;
272
+ var EDGE_CACHE_DISABLED = -1;
273
+ var ASSET_PARAMETER_TYPE = "asset";
274
+ var ASSETS_SOURCE_UNIFORM = "uniform-assets";
275
+ var ASSETS_SOURCE_CUSTOM_URL = "custom-url";
276
+ var REFERENCE_DATA_TYPE_ID = "uniformContentInternalReference";
277
+
278
+ // src/clients/compositionHelpers.ts
279
+ function resolveCompositionSelector(args) {
280
+ if ("compositionId" in args) {
281
+ const { compositionId, editionId, versionId, ...readOptions } = args;
282
+ return {
283
+ readOptions,
284
+ // raw mode matches on composition OR edition id via the compositionId param
285
+ compositionId: editionId != null ? editionId : compositionId,
286
+ versionId,
287
+ hasCompositionId: true,
288
+ pinnedEdition: editionId !== void 0
334
289
  };
335
- exports.wrap = function(obj, options, methods) {
336
- if (options instanceof Array) {
337
- methods = options;
338
- options = null;
339
- }
340
- if (!methods) {
341
- methods = [];
342
- for (var key in obj) {
343
- if (typeof obj[key] === "function") {
344
- methods.push(key);
345
- }
346
- }
347
- }
348
- for (var i = 0; i < methods.length; i++) {
349
- var method = methods[i];
350
- var original = obj[method];
351
- obj[method] = function retryWrapper(original2) {
352
- var op = exports.operation(options);
353
- var args = Array.prototype.slice.call(arguments, 1);
354
- var callback = args.pop();
355
- args.push(function(err) {
356
- if (op.retry(err)) {
357
- return;
358
- }
359
- if (err) {
360
- arguments[0] = op.mainError();
361
- }
362
- callback.apply(this, arguments);
363
- });
364
- op.attempt(function() {
365
- original2.apply(obj, args);
366
- });
367
- }.bind(obj, original);
368
- obj[method].options = options;
369
- }
290
+ }
291
+ return { readOptions: args, hasCompositionId: false, pinnedEdition: false };
292
+ }
293
+
294
+ // src/clients/DeliveryClientBase.ts
295
+ var DEFAULT_EDGE_API_HOST = "https://uniform.global";
296
+ var DeliveryClientBase = class extends ContentClientBase {
297
+ constructor(options) {
298
+ var _a;
299
+ super(
300
+ options,
301
+ /* defaultBypassCache */
302
+ false
303
+ );
304
+ this.edgeApiHost = (_a = options.edgeApiHost) != null ? _a : DEFAULT_EDGE_API_HOST;
305
+ this.edgeRequestInit = options.disableSWR ? { headers: { "x-disable-swr": "true" } } : void 0;
306
+ }
307
+ /** Coerces the `diagnostics` option into the shape the edge endpoints accept. */
308
+ coerceDiagnostics(diagnostics) {
309
+ return typeof diagnostics === "boolean" ? diagnostics : diagnostics === "no-data" ? "no-data" : void 0;
310
+ }
311
+ };
312
+
313
+ // src/clients/CompositionDeliveryClient.ts
314
+ var EDGE_SINGLE_URL = "/api/v1/composition";
315
+ var EDGE_LIST_URL = "/api/v1/compositions";
316
+ var CompositionDeliveryClient = class extends DeliveryClientBase {
317
+ constructor(options) {
318
+ super(options);
319
+ }
320
+ /** Fetches exactly one composition (throws `ApiClientError(404)` if absent). */
321
+ get(args) {
322
+ var _a;
323
+ const { diagnostics, select, ...rest } = args;
324
+ const { readOptions, compositionId, versionId, pinnedEdition } = resolveCompositionSelector(rest);
325
+ const url = this.createUrl(
326
+ EDGE_SINGLE_URL,
327
+ {
328
+ ...readOptions,
329
+ ...projectionToQuery(select),
330
+ // A pinned edition is folded into compositionId (raw matches edition or
331
+ // composition id); there is no editionId query param on this endpoint.
332
+ compositionId,
333
+ versionId,
334
+ projectId: this.options.projectId,
335
+ state: (_a = args.state) != null ? _a : CANVAS_PUBLISHED_STATE,
336
+ // editionId pins a specific edition for preview; otherwise locale-best.
337
+ editions: pinnedEdition ? "raw" : "auto",
338
+ diagnostics: this.coerceDiagnostics(diagnostics)
339
+ },
340
+ this.edgeApiHost
341
+ );
342
+ return this.apiClient(url, this.edgeRequestInit);
343
+ }
344
+ /** Fetches a list of compositions, optionally filtered. */
345
+ list(args = {}) {
346
+ var _a;
347
+ const { diagnostics, filters, select, ...rest } = args;
348
+ const url = this.createUrl(
349
+ EDGE_LIST_URL,
350
+ {
351
+ ...rest,
352
+ ...rewriteFiltersForApi(filters),
353
+ ...projectionToQuery(select),
354
+ projectId: this.options.projectId,
355
+ state: (_a = args.state) != null ? _a : CANVAS_PUBLISHED_STATE,
356
+ diagnostics: this.coerceDiagnostics(diagnostics)
357
+ },
358
+ this.edgeApiHost
359
+ );
360
+ return this.apiClient(url, this.edgeRequestInit);
361
+ }
362
+ };
363
+
364
+ // src/clients/CompositionManagementClient.ts
365
+ import { rewriteFiltersForApi as rewriteFiltersForApi2 } from "@uniformdev/context/api";
366
+
367
+ // src/clients/resolveManagementEditions.ts
368
+ function resolveManagementEditions({
369
+ explicit,
370
+ pinnedEdition,
371
+ hasId,
372
+ hasLocale
373
+ }) {
374
+ if (explicit) {
375
+ return explicit;
376
+ }
377
+ if (pinnedEdition) {
378
+ return "raw";
379
+ }
380
+ if (!hasId) {
381
+ return void 0;
382
+ }
383
+ return hasLocale ? "auto" : "raw";
384
+ }
385
+
386
+ // src/clients/CompositionManagementClient.ts
387
+ var CANVAS_URL = "/api/v1/canvas";
388
+ var CANVAS_HISTORY_URL = "/api/v1/canvas-history";
389
+ var CompositionManagementClient = class extends ContentClientBase {
390
+ constructor(options) {
391
+ super(
392
+ options,
393
+ /* defaultBypassCache */
394
+ true
395
+ );
396
+ }
397
+ /**
398
+ * Fetches one composition in canonical shape (throws `ApiClientError(404)` if
399
+ * absent).
400
+ */
401
+ get(args) {
402
+ var _a;
403
+ const { select, ...selectorArgs } = args;
404
+ const { readOptions, compositionId, versionId, hasCompositionId, pinnedEdition } = resolveCompositionSelector(selectorArgs);
405
+ const url = this.createUrl(CANVAS_URL, {
406
+ format: CANONICAL_FORMAT,
407
+ // Caller-supplied shaping flags and non-id selector keys ride along and
408
+ // override the format alias server-side.
409
+ ...readOptions,
410
+ ...projectionToQuery(select),
411
+ // A pinned edition is folded into compositionId; there is no editionId
412
+ // query param on this endpoint.
413
+ compositionId,
414
+ versionId,
415
+ projectId: this.options.projectId,
416
+ state: (_a = args.state) != null ? _a : CANVAS_DRAFT_STATE,
417
+ editions: resolveManagementEditions({
418
+ explicit: readOptions.editions,
419
+ pinnedEdition,
420
+ hasId: hasCompositionId,
421
+ hasLocale: readOptions.locale != null
422
+ })
423
+ });
424
+ return this.apiClient(url);
425
+ }
426
+ /** Fetches a list of compositions in canonical shape. */
427
+ list(args = {}) {
428
+ var _a;
429
+ const { filters, select, ...rest } = args;
430
+ const url = this.createUrl(CANVAS_URL, {
431
+ format: CANONICAL_FORMAT,
432
+ ...rest,
433
+ ...rewriteFiltersForApi2(filters),
434
+ ...projectionToQuery(select),
435
+ projectId: this.options.projectId,
436
+ state: (_a = args.state) != null ? _a : CANVAS_DRAFT_STATE
437
+ });
438
+ return this.apiClient(url);
439
+ }
440
+ /** Creates or updates a composition. Returns the new `x-modified-at` timestamp. */
441
+ async save(body, opts) {
442
+ const url = this.createUrl(CANVAS_URL);
443
+ const headers = {};
444
+ if (opts == null ? void 0 : opts.ifUnmodifiedSince) {
445
+ headers["x-if-unmodified-since"] = opts.ifUnmodifiedSince;
446
+ }
447
+ const { response } = await this.apiClientWithResponse(url, {
448
+ method: "PUT",
449
+ body: JSON.stringify({ ...body, projectId: this.options.projectId }),
450
+ expectNoContent: true,
451
+ headers
452
+ });
453
+ return { modified: response.headers.get("x-modified-at") };
454
+ }
455
+ /**
456
+ * Saves the draft and publishes in one call (two PUTs). The optimistic
457
+ * concurrency guard, if any, applies to the draft write.
458
+ */
459
+ async saveAndPublish(body, opts) {
460
+ await this.save({ ...body, state: CANVAS_DRAFT_STATE }, opts);
461
+ return this.save({ ...body, state: CANVAS_PUBLISHED_STATE });
462
+ }
463
+ /**
464
+ * Removes only the published state, leaving the draft intact. Scoped to a
465
+ * single edition when `editionId` is supplied; otherwise unpublishes all editions.
466
+ * To unpublish only the base edition, pass editionId and compositionId as the same value.
467
+ */
468
+ async unpublish(selector) {
469
+ await this.deleteComposition({ ...selector, state: CANVAS_PUBLISHED_STATE });
470
+ }
471
+ /**
472
+ * Deletes across all states. Scoped to a single edition when `editionId` is
473
+ * supplied; otherwise deletes all states and editions.
474
+ * Use `unpublish` to drop only the published state.
475
+ */
476
+ async remove(selector) {
477
+ await this.deleteComposition(selector);
478
+ }
479
+ /** Fetches historical versions of a composition or pattern. */
480
+ history(args) {
481
+ const url = this.createUrl(CANVAS_HISTORY_URL, { ...args, projectId: this.options.projectId });
482
+ return this.apiClient(url);
483
+ }
484
+ async deleteComposition(body) {
485
+ const url = this.createUrl(CANVAS_URL);
486
+ await this.apiClient(url, {
487
+ method: "DELETE",
488
+ body: JSON.stringify({ ...body, projectId: this.options.projectId }),
489
+ expectNoContent: true
490
+ });
491
+ }
492
+ };
493
+
494
+ // src/clients/ContentTypeClient.ts
495
+ import { ApiClientError as ApiClientError3 } from "@uniformdev/context/api";
496
+ var CONTENT_TYPES_URL = "/api/v1/content-types";
497
+ var ContentTypeClient = class extends ContentClientBase {
498
+ constructor(options) {
499
+ super(
500
+ options,
501
+ /* defaultBypassCache */
502
+ true
503
+ );
504
+ }
505
+ /** Fetches one content type by id (throws `ApiClientError(404)` if absent). */
506
+ async get(args) {
507
+ var _a;
508
+ const url = this.createUrl(CONTENT_TYPES_URL, {
509
+ contentTypeIDs: [args.contentTypeId],
510
+ limit: 1,
511
+ projectId: this.options.projectId
512
+ });
513
+ const res = await this.apiClient(url);
514
+ const contentType = (_a = res.contentTypes) == null ? void 0 : _a[0];
515
+ if (!contentType) {
516
+ throw new ApiClientError3("Content type not found", "GET", url.toString(), 404, "Not Found");
517
+ }
518
+ return contentType;
519
+ }
520
+ /** Fetches a list of content types. */
521
+ list(args) {
522
+ const url = this.createUrl(CONTENT_TYPES_URL, { ...args, projectId: this.options.projectId });
523
+ return this.apiClient(url);
524
+ }
525
+ /** Creates or updates a content type. */
526
+ async save(body, opts = {}) {
527
+ const url = this.createUrl(CONTENT_TYPES_URL);
528
+ let contentType = body.contentType;
529
+ if (typeof contentType.slugSettings === "object" && contentType.slugSettings !== null && Object.keys(contentType.slugSettings).length === 0) {
530
+ const { slugSettings: _omitEmptySlugSettings, ...rest } = contentType;
531
+ contentType = rest;
532
+ }
533
+ await this.apiClient(url, {
534
+ method: "PUT",
535
+ body: JSON.stringify({ ...body, contentType, projectId: this.options.projectId }),
536
+ expectNoContent: true,
537
+ headers: opts.autogenerateDataTypes ? { "x-uniform-autogenerate-data-types": "true" } : {}
538
+ });
539
+ }
540
+ /** Deletes a content type. */
541
+ async remove(args) {
542
+ const url = this.createUrl(CONTENT_TYPES_URL);
543
+ await this.apiClient(url, {
544
+ method: "DELETE",
545
+ body: JSON.stringify({ ...args, projectId: this.options.projectId }),
546
+ expectNoContent: true
547
+ });
548
+ }
549
+ };
550
+
551
+ // src/clients/EntryDeliveryClient.ts
552
+ import { rewriteFiltersForApi as rewriteFiltersForApi3 } from "@uniformdev/context/api";
553
+
554
+ // src/clients/entryHelpers.ts
555
+ import { ApiClientError as ApiClientError4 } from "@uniformdev/context/api";
556
+ function resolveEntrySelector(args) {
557
+ if ("entryId" in args) {
558
+ const { entryId, editionId, versionId, ...readOptions2 } = args;
559
+ return {
560
+ readOptions: readOptions2,
561
+ entryIDs: [editionId != null ? editionId : entryId],
562
+ versionId,
563
+ pinnedEdition: editionId !== void 0
370
564
  };
371
565
  }
372
- });
373
-
374
- // ../../node_modules/.pnpm/retry@0.13.1/node_modules/retry/index.js
375
- var require_retry2 = __commonJS({
376
- "../../node_modules/.pnpm/retry@0.13.1/node_modules/retry/index.js"(exports, module) {
377
- "use strict";
378
- module.exports = require_retry();
566
+ const { slug, ...readOptions } = args;
567
+ return { readOptions, slug, pinnedEdition: false };
568
+ }
569
+ function unwrapSingleEntry(res, url) {
570
+ var _a;
571
+ const entry = (_a = res.entries) == null ? void 0 : _a[0];
572
+ if (!entry) {
573
+ throw new ApiClientError4("Entry not found", "GET", url.toString(), 404, "Not Found");
574
+ }
575
+ return entry;
576
+ }
577
+
578
+ // src/clients/EntryDeliveryClient.ts
579
+ var ENTRIES_URL = "/api/v1/entries";
580
+ var EntryDeliveryClient = class extends DeliveryClientBase {
581
+ constructor(options) {
582
+ super(options);
583
+ }
584
+ /** Fetches exactly one entry by id or slug (throws `ApiClientError(404)` if absent). */
585
+ async get(args) {
586
+ var _a, _b;
587
+ const { diagnostics, select, ...rest } = args;
588
+ const { entryIDs, slug, versionId, pinnedEdition, readOptions } = resolveEntrySelector(rest);
589
+ const url = this.createUrl(
590
+ ENTRIES_URL,
591
+ {
592
+ ...readOptions,
593
+ ...projectionToQuery(select),
594
+ projectId: this.options.projectId,
595
+ state: (_a = args.state) != null ? _a : CANVAS_PUBLISHED_STATE,
596
+ entryIDs,
597
+ slug,
598
+ versionId,
599
+ // A pinned edition is fetched exactly; otherwise locale-best.
600
+ editions: pinnedEdition ? "raw" : "auto",
601
+ // An id lookup wants that exact entity regardless of type, so default the
602
+ // pattern filter to 'any' (origin default `false` would 404 a pattern id).
603
+ // Scoped to id lookups; slug reads keep the origin default. Explicit
604
+ // `pattern` overrides via the `...readOptions` spread above.
605
+ pattern: (_b = args.pattern) != null ? _b : entryIDs ? "any" : void 0,
606
+ diagnostics: this.coerceDiagnostics(diagnostics)
607
+ },
608
+ this.edgeApiHost
609
+ );
610
+ const res = await this.apiClient(url, this.edgeRequestInit);
611
+ return unwrapSingleEntry(res, url);
612
+ }
613
+ /** Fetches a list of entries, optionally filtered. */
614
+ list(args = {}) {
615
+ var _a;
616
+ const { diagnostics, filters, select, ...rest } = args;
617
+ const url = this.createUrl(
618
+ ENTRIES_URL,
619
+ {
620
+ ...rest,
621
+ ...rewriteFiltersForApi3(filters),
622
+ ...projectionToQuery(select),
623
+ projectId: this.options.projectId,
624
+ state: (_a = args.state) != null ? _a : CANVAS_PUBLISHED_STATE,
625
+ diagnostics: this.coerceDiagnostics(diagnostics)
626
+ },
627
+ this.edgeApiHost
628
+ );
629
+ return this.apiClient(url, this.edgeRequestInit);
630
+ }
631
+ };
632
+
633
+ // src/clients/EntryManagementClient.ts
634
+ import { rewriteFiltersForApi as rewriteFiltersForApi4 } from "@uniformdev/context/api";
635
+ var ENTRIES_URL2 = "/api/v1/entries";
636
+ var ENTRIES_HISTORY_URL = "/api/v1/entries-history";
637
+ var EntryManagementClient = class extends ContentClientBase {
638
+ constructor(options) {
639
+ super(
640
+ options,
641
+ /* defaultBypassCache */
642
+ true
643
+ );
644
+ }
645
+ /**
646
+ * Fetches one entry by id or slug in canonical shape (throws
647
+ * `ApiClientError(404)` if absent).
648
+ */
649
+ async get(args) {
650
+ var _a, _b;
651
+ const { select, ...selectorArgs } = args;
652
+ const { entryIDs, slug, versionId, readOptions, pinnedEdition } = resolveEntrySelector(selectorArgs);
653
+ const url = this.createUrl(ENTRIES_URL2, {
654
+ format: CANONICAL_FORMAT,
655
+ ...readOptions,
656
+ ...projectionToQuery(select),
657
+ projectId: this.options.projectId,
658
+ state: (_a = args.state) != null ? _a : CANVAS_DRAFT_STATE,
659
+ editions: resolveManagementEditions({
660
+ explicit: readOptions.editions,
661
+ pinnedEdition,
662
+ hasId: entryIDs != null,
663
+ hasLocale: readOptions.locale != null
664
+ }),
665
+ // An id lookup wants that exact entity regardless of type, so default the
666
+ // pattern filter to 'any' (origin default `false` would 404 a pattern id).
667
+ // Scoped to id lookups; slug reads keep the origin default. Explicit
668
+ // `pattern` overrides via the `...readOptions` spread above.
669
+ pattern: (_b = args.pattern) != null ? _b : entryIDs ? "any" : void 0,
670
+ entryIDs,
671
+ slug,
672
+ versionId
673
+ });
674
+ const res = await this.apiClient(url);
675
+ return unwrapSingleEntry(res, url);
676
+ }
677
+ /** Fetches a list of entries in canonical shape. */
678
+ list(args = {}) {
679
+ var _a;
680
+ const { filters, select, ...rest } = args;
681
+ const url = this.createUrl(ENTRIES_URL2, {
682
+ format: CANONICAL_FORMAT,
683
+ ...rest,
684
+ ...rewriteFiltersForApi4(filters),
685
+ ...projectionToQuery(select),
686
+ projectId: this.options.projectId,
687
+ state: (_a = args.state) != null ? _a : CANVAS_DRAFT_STATE
688
+ });
689
+ return this.apiClient(url);
690
+ }
691
+ /** Creates or updates an entry. Returns the new `x-modified-at` timestamp. */
692
+ async save(body, opts) {
693
+ const url = this.createUrl(ENTRIES_URL2);
694
+ const headers = {};
695
+ if (opts == null ? void 0 : opts.ifUnmodifiedSince) {
696
+ headers["x-if-unmodified-since"] = opts.ifUnmodifiedSince;
697
+ }
698
+ const { response } = await this.apiClientWithResponse(url, {
699
+ method: "PUT",
700
+ body: JSON.stringify({ ...body, projectId: this.options.projectId }),
701
+ expectNoContent: true,
702
+ headers
703
+ });
704
+ return { modified: response.headers.get("x-modified-at") };
705
+ }
706
+ /** Saves the draft and publishes in one call (two PUTs). */
707
+ async saveAndPublish(body, opts) {
708
+ await this.save({ ...body, state: CANVAS_DRAFT_STATE }, opts);
709
+ return this.save({ ...body, state: CANVAS_PUBLISHED_STATE });
710
+ }
711
+ /**
712
+ * Removes only the published state, leaving the draft intact. Scoped to a
713
+ * single edition when `editionId` is supplied; otherwise unpublishes all editions.
714
+ * To unpublish only the base edition, pass editionId and entryId as the same value.
715
+ */
716
+ async unpublish(selector) {
717
+ await this.deleteEntry({ ...selector, state: CANVAS_PUBLISHED_STATE });
718
+ }
719
+ /**
720
+ * Deletes across all states. Scoped to a single edition when `editionId` is
721
+ * supplied; otherwise deletes all states and editions.
722
+ * Use `unpublish` to drop only the published state.
723
+ */
724
+ async remove(selector) {
725
+ await this.deleteEntry(selector);
379
726
  }
380
- });
381
-
382
- // src/CanvasClient.ts
383
- import { ApiClient } from "@uniformdev/context/api";
384
-
385
- // src/enhancement/createLimitPolicy.ts
386
- var import_p_limit = __toESM(require_p_limit());
387
- import { ApiClientError } from "@uniformdev/context/api";
388
-
389
- // ../../node_modules/.pnpm/p-retry@5.1.2/node_modules/p-retry/index.js
390
- var import_retry = __toESM(require_retry2(), 1);
391
- var networkErrorMsgs = /* @__PURE__ */ new Set([
392
- "Failed to fetch",
393
- // Chrome
394
- "NetworkError when attempting to fetch resource.",
395
- // Firefox
396
- "The Internet connection appears to be offline.",
397
- // Safari
398
- "Network request failed",
399
- // `cross-fetch`
400
- "fetch failed"
401
- // Undici (Node.js)
402
- ]);
403
- var AbortError = class extends Error {
404
- constructor(message) {
405
- super();
406
- if (message instanceof Error) {
407
- this.originalError = message;
408
- ({ message } = message);
409
- } else {
410
- this.originalError = new Error(message);
411
- this.originalError.stack = this.stack;
412
- }
413
- this.name = "AbortError";
414
- this.message = message;
727
+ /** Fetches historical versions of an entry. */
728
+ history(args) {
729
+ const url = this.createUrl(ENTRIES_HISTORY_URL, { ...args, projectId: this.options.projectId });
730
+ return this.apiClient(url);
415
731
  }
416
- };
417
- var decorateErrorWithCounts = (error, attemptNumber, options) => {
418
- const retriesLeft = options.retries - (attemptNumber - 1);
419
- error.attemptNumber = attemptNumber;
420
- error.retriesLeft = retriesLeft;
421
- return error;
422
- };
423
- var isNetworkError = (errorMessage) => networkErrorMsgs.has(errorMessage);
424
- var getDOMException = (errorMessage) => globalThis.DOMException === void 0 ? new Error(errorMessage) : new DOMException(errorMessage);
425
- async function pRetry(input, options) {
426
- return new Promise((resolve, reject) => {
427
- options = {
428
- onFailedAttempt() {
429
- },
430
- retries: 10,
431
- ...options
432
- };
433
- const operation = import_retry.default.operation(options);
434
- operation.attempt(async (attemptNumber) => {
435
- try {
436
- resolve(await input(attemptNumber));
437
- } catch (error) {
438
- if (!(error instanceof Error)) {
439
- reject(new TypeError(`Non-error was thrown: "${error}". You should only throw errors.`));
440
- return;
441
- }
442
- if (error instanceof AbortError) {
443
- operation.stop();
444
- reject(error.originalError);
445
- } else if (error instanceof TypeError && !isNetworkError(error.message)) {
446
- operation.stop();
447
- reject(error);
448
- } else {
449
- decorateErrorWithCounts(error, attemptNumber, options);
450
- try {
451
- await options.onFailedAttempt(error);
452
- } catch (error2) {
453
- reject(error2);
454
- return;
455
- }
456
- if (!operation.retry(error)) {
457
- reject(operation.mainError());
458
- }
459
- }
460
- }
732
+ async deleteEntry(body) {
733
+ const url = this.createUrl(ENTRIES_URL2);
734
+ await this.apiClient(url, {
735
+ method: "DELETE",
736
+ body: JSON.stringify({ ...body, projectId: this.options.projectId }),
737
+ expectNoContent: true
461
738
  });
462
- if (options.signal && !options.signal.aborted) {
463
- options.signal.addEventListener("abort", () => {
464
- operation.stop();
465
- const reason = options.signal.reason === void 0 ? getDOMException("The operation was aborted.") : options.signal.reason;
466
- reject(reason instanceof Error ? reason : getDOMException(reason));
467
- }, {
468
- once: true
469
- });
470
- }
471
- });
472
- }
473
-
474
- // ../../node_modules/.pnpm/p-throttle@5.0.0/node_modules/p-throttle/index.js
475
- var AbortError2 = class extends Error {
476
- constructor() {
477
- super("Throttled function aborted");
478
- this.name = "AbortError";
479
739
  }
480
740
  };
481
- function pThrottle({ limit, interval, strict }) {
482
- if (!Number.isFinite(limit)) {
483
- throw new TypeError("Expected `limit` to be a finite number");
484
- }
485
- if (!Number.isFinite(interval)) {
486
- throw new TypeError("Expected `interval` to be a finite number");
487
- }
488
- const queue = /* @__PURE__ */ new Map();
489
- let currentTick = 0;
490
- let activeCount = 0;
491
- function windowedDelay() {
492
- const now = Date.now();
493
- if (now - currentTick > interval) {
494
- activeCount = 1;
495
- currentTick = now;
496
- return 0;
497
- }
498
- if (activeCount < limit) {
499
- activeCount++;
500
- } else {
501
- currentTick += interval;
502
- activeCount = 1;
503
- }
504
- return currentTick - now;
505
- }
506
- const strictTicks = [];
507
- function strictDelay() {
508
- const now = Date.now();
509
- if (strictTicks.length < limit) {
510
- strictTicks.push(now);
511
- return 0;
512
- }
513
- const earliestTime = strictTicks.shift() + interval;
514
- if (now >= earliestTime) {
515
- strictTicks.push(now);
516
- return 0;
517
- }
518
- strictTicks.push(earliestTime);
519
- return earliestTime - now;
520
- }
521
- const getDelay = strict ? strictDelay : windowedDelay;
522
- return (function_) => {
523
- const throttled = function(...args) {
524
- if (!throttled.isEnabled) {
525
- return (async () => function_.apply(this, args))();
526
- }
527
- let timeout;
528
- return new Promise((resolve, reject) => {
529
- const execute = () => {
530
- resolve(function_.apply(this, args));
531
- queue.delete(timeout);
532
- };
533
- timeout = setTimeout(execute, getDelay());
534
- queue.set(timeout, reject);
535
- });
536
- };
537
- throttled.abort = () => {
538
- for (const timeout of queue.keys()) {
539
- clearTimeout(timeout);
540
- queue.get(timeout)(new AbortError2());
541
- }
542
- queue.clear();
543
- strictTicks.splice(0, strictTicks.length);
544
- };
545
- throttled.isEnabled = true;
546
- return throttled;
547
- };
548
- }
549
-
550
- // src/enhancement/createLimitPolicy.ts
551
- function createLimitPolicy({
552
- throttle = { interval: 1e3, limit: 10 },
553
- retry: retry2 = { retries: 1, factor: 1.66 },
554
- limit = 10
555
- }) {
556
- const throttler = throttle ? pThrottle(throttle) : null;
557
- const limiter = limit ? (0, import_p_limit.default)(limit) : null;
558
- return function limitPolicy(func) {
559
- let currentFunc = async () => await func();
560
- if (throttler) {
561
- const throttleFunc = currentFunc;
562
- currentFunc = throttler(throttleFunc);
563
- }
564
- if (limiter) {
565
- const limitFunc = currentFunc;
566
- currentFunc = () => limiter(limitFunc);
567
- }
568
- if (retry2) {
569
- const retryFunc = currentFunc;
570
- currentFunc = () => pRetry(retryFunc, {
571
- ...retry2,
572
- onFailedAttempt: async (error) => {
573
- if (retry2.onFailedAttempt) {
574
- await retry2.onFailedAttempt(error);
575
- }
576
- if (error instanceof ApiClientError && typeof error.statusCode === "number" && error.statusCode >= 400 && error.statusCode < 500 && error.statusCode !== 429 && error.statusCode !== 408) {
577
- throw error;
578
- }
579
- }
580
- });
581
- }
582
- return currentFunc();
583
- };
584
- }
585
- var nullLimitPolicy = async (func) => await func();
586
-
587
- // src/utils/rewriteFilters.ts
588
- var isPlainObject = (obj) => typeof obj === "object" && obj !== null && !Array.isArray(obj);
589
- function rewriteFilters(filters) {
590
- return Object.entries(filters != null ? filters : {}).reduce(
591
- (acc, [key, value]) => {
592
- const lhs = `filters.${key}` + (isPlainObject(value) ? `[${Object.keys(value)[0]}]` : "");
593
- const rhs = isPlainObject(value) ? Object.values(value)[0] : value;
594
- return {
595
- ...acc,
596
- [lhs]: Array.isArray(rhs) ? rhs.map((v) => `${v}`.trim()).join(",") : `${rhs}`.trim()
597
- };
598
- },
599
- {}
600
- );
601
- }
602
741
 
603
- // src/CanvasClient.ts
604
- var CANVAS_URL = "/api/v1/canvas";
605
- var CanvasClient = class extends ApiClient {
742
+ // src/clients/deprecated/CanvasClient.ts
743
+ import { ApiClient as ApiClient3, rewriteFiltersForApi as rewriteFiltersForApi5 } from "@uniformdev/context/api";
744
+ var CANVAS_URL2 = "/api/v1/canvas";
745
+ var CanvasClient = class extends ApiClient3 {
606
746
  constructor(options) {
607
747
  var _a;
608
748
  if (!options.limitPolicy) {
@@ -615,17 +755,24 @@ var CanvasClient = class extends ApiClient {
615
755
  /** Fetches lists of Canvas compositions, optionally by type */
616
756
  async getCompositionList(params = {}) {
617
757
  const { projectId } = this.options;
618
- const { resolveData, filters, ...originParams } = params;
619
- const rewrittenFilters = rewriteFilters(filters);
758
+ const { resolveData, filters, select, ...originParams } = params;
759
+ const rewrittenFilters = rewriteFiltersForApi5(filters);
760
+ const rewrittenSelect = projectionToQuery(select);
620
761
  if (!resolveData) {
621
- const fetchUri = this.createUrl(CANVAS_URL, { ...originParams, projectId, ...rewrittenFilters });
762
+ const fetchUri = this.createUrl(CANVAS_URL2, {
763
+ ...originParams,
764
+ projectId,
765
+ ...rewrittenFilters,
766
+ ...rewrittenSelect
767
+ });
622
768
  return this.apiClient(fetchUri);
623
769
  }
624
770
  const edgeParams = {
625
771
  ...originParams,
626
772
  projectId,
627
773
  diagnostics: typeof params.diagnostics === "boolean" ? params.diagnostics : params.diagnostics === "no-data" ? "no-data" : void 0,
628
- ...rewrittenFilters
774
+ ...rewrittenFilters,
775
+ ...rewrittenSelect
629
776
  };
630
777
  const edgeUrl = this.createUrl("/api/v1/compositions", edgeParams, this.edgeApiHost);
631
778
  return this.apiClient(edgeUrl, this.edgeApiRequestInit);
@@ -660,7 +807,7 @@ var CanvasClient = class extends ApiClient {
660
807
  }) {
661
808
  const { projectId } = this.options;
662
809
  if (skipDataResolution) {
663
- return this.apiClient(this.createUrl(CANVAS_URL, { ...params, projectId }));
810
+ return this.apiClient(this.createUrl(CANVAS_URL2, { ...params, projectId }));
664
811
  }
665
812
  const edgeParams = {
666
813
  ...params,
@@ -672,7 +819,7 @@ var CanvasClient = class extends ApiClient {
672
819
  }
673
820
  /** Updates or creates a Canvas component definition */
674
821
  async updateComposition(body, options) {
675
- const fetchUri = this.createUrl(CANVAS_URL);
822
+ const fetchUri = this.createUrl(CANVAS_URL2);
676
823
  const headers = {};
677
824
  if (options == null ? void 0 : options.ifUnmodifiedSince) {
678
825
  headers["x-if-unmodified-since"] = options.ifUnmodifiedSince;
@@ -687,7 +834,7 @@ var CanvasClient = class extends ApiClient {
687
834
  }
688
835
  /** Deletes a Canvas component definition */
689
836
  async removeComposition(body) {
690
- const fetchUri = this.createUrl(CANVAS_URL);
837
+ const fetchUri = this.createUrl(CANVAS_URL2);
691
838
  const { projectId } = this.options;
692
839
  await this.apiClient(fetchUri, {
693
840
  method: "DELETE",
@@ -726,53 +873,10 @@ var UncachedCanvasClient = class extends CanvasClient {
726
873
  }
727
874
  };
728
875
 
729
- // src/CategoryClient.ts
730
- import { ApiClient as ApiClient2 } from "@uniformdev/context/api";
731
- var CATEGORIES_URL = "/api/v1/categories";
732
- var CategoryClient = class extends ApiClient2 {
733
- constructor(options) {
734
- if (!options.limitPolicy) {
735
- options.limitPolicy = createLimitPolicy({});
736
- }
737
- super(options);
738
- }
739
- /** Fetches all categories created in given project */
740
- async getCategories(options) {
741
- const { projectId } = this.options;
742
- const fetchUri = this.createUrl("/api/v1/categories", { ...options, projectId });
743
- return await this.apiClient(fetchUri);
744
- }
745
- /** Updates or creates a category, also used to re-order them */
746
- async upsertCategories(categories) {
747
- const { projectId } = this.options;
748
- const fetchUri = this.createUrl(CATEGORIES_URL);
749
- return await this.apiClient(fetchUri, {
750
- method: "PUT",
751
- body: JSON.stringify({ categories, projectId }),
752
- expectNoContent: true
753
- });
754
- }
755
- /** Deletes a category */
756
- async removeCategory(options) {
757
- const { projectId } = this.options;
758
- const fetchUri = this.createUrl(CATEGORIES_URL);
759
- return await this.apiClient(fetchUri, {
760
- method: "DELETE",
761
- body: JSON.stringify({ projectId, categoryId: options.categoryId }),
762
- expectNoContent: true
763
- });
764
- }
765
- };
766
- var UncachedCategoryClient = class extends CategoryClient {
767
- constructor(options) {
768
- super({ ...options, bypassCache: true });
769
- }
770
- };
771
-
772
- // src/ContentClient.ts
773
- import { ApiClient as ApiClient3 } from "@uniformdev/context/api";
876
+ // src/clients/deprecated/ContentClient.ts
877
+ import { ApiClient as ApiClient4, rewriteFiltersForApi as rewriteFiltersForApi6 } from "@uniformdev/context/api";
774
878
  var _contentTypesUrl, _entriesUrl;
775
- var _ContentClient = class _ContentClient extends ApiClient3 {
879
+ var _ContentClient = class _ContentClient extends ApiClient4 {
776
880
  constructor(options) {
777
881
  var _a;
778
882
  super(options);
@@ -785,15 +889,21 @@ var _ContentClient = class _ContentClient extends ApiClient3 {
785
889
  }
786
890
  getEntries(options) {
787
891
  const { projectId } = this.options;
788
- const { skipDataResolution, filters, ...params } = options;
789
- const rewrittenFilters = rewriteFilters(filters);
892
+ const { skipDataResolution, filters, select, ...params } = options;
893
+ const rewrittenFilters = rewriteFiltersForApi6(filters);
894
+ const rewrittenSelect = projectionToQuery(select);
790
895
  if (skipDataResolution) {
791
- const url = this.createUrl(__privateGet(_ContentClient, _entriesUrl), { ...params, ...rewrittenFilters, projectId });
896
+ const url = this.createUrl(__privateGet(_ContentClient, _entriesUrl), {
897
+ ...params,
898
+ ...rewrittenFilters,
899
+ ...rewrittenSelect,
900
+ projectId
901
+ });
792
902
  return this.apiClient(url);
793
903
  }
794
904
  const edgeUrl = this.createUrl(
795
905
  __privateGet(_ContentClient, _entriesUrl),
796
- { ...this.getEdgeOptions(params), ...rewrittenFilters },
906
+ { ...this.getEdgeOptions(params), ...rewrittenFilters, ...rewrittenSelect },
797
907
  this.edgeApiHost
798
908
  );
799
909
  return this.apiClient(
@@ -873,27 +983,31 @@ var UncachedContentClient = class extends ContentClient {
873
983
  };
874
984
 
875
985
  // src/DataSourceClient.ts
876
- import { ApiClient as ApiClient4 } from "@uniformdev/context/api";
986
+ import { ApiClient as ApiClient5 } from "@uniformdev/context/api";
877
987
  var dataSourceUrl = "/api/v1/data-source";
878
988
  var dataSourcesUrl = "/api/v1/data-sources";
879
- var DataSourceClient = class extends ApiClient4 {
989
+ var DataSourceClient = class extends ApiClient5 {
880
990
  constructor(options) {
881
991
  super(options);
882
992
  }
883
- /** Fetches all DataSources for a project */
993
+ /** Fetches a single DataSource by id (with decrypted secrets). */
884
994
  async get(options) {
885
995
  const { projectId } = this.options;
886
996
  const fetchUri = this.createUrl(dataSourceUrl, { ...options, projectId });
887
997
  return await this.apiClient(fetchUri);
888
998
  }
889
- /** Fetches all DataSources for a project */
890
- async getList(options) {
999
+ /** Fetches the list of DataSources for a project (secrets masked). */
1000
+ async list(options) {
891
1001
  const { projectId } = this.options;
892
1002
  const fetchUri = this.createUrl(dataSourcesUrl, { ...options, projectId });
893
1003
  return await this.apiClient(fetchUri);
894
1004
  }
1005
+ /** @deprecated Use {@link list} instead. */
1006
+ async getList(options) {
1007
+ return this.list(options);
1008
+ }
895
1009
  /** Updates or creates (based on id) a DataSource */
896
- async upsert(body) {
1010
+ async save(body) {
897
1011
  const fetchUri = this.createUrl(dataSourceUrl);
898
1012
  await this.apiClient(fetchUri, {
899
1013
  method: "PUT",
@@ -901,6 +1015,10 @@ var DataSourceClient = class extends ApiClient4 {
901
1015
  expectNoContent: true
902
1016
  });
903
1017
  }
1018
+ /** @deprecated Use {@link save} instead. */
1019
+ async upsert(body) {
1020
+ return this.save(body);
1021
+ }
904
1022
  /** Deletes a DataSource */
905
1023
  async remove(body) {
906
1024
  const fetchUri = this.createUrl(dataSourceUrl);
@@ -913,20 +1031,24 @@ var DataSourceClient = class extends ApiClient4 {
913
1031
  };
914
1032
 
915
1033
  // src/DataTypeClient.ts
916
- import { ApiClient as ApiClient5 } from "@uniformdev/context/api";
1034
+ import { ApiClient as ApiClient6 } from "@uniformdev/context/api";
917
1035
  var _url;
918
- var _DataTypeClient = class _DataTypeClient extends ApiClient5 {
1036
+ var _DataTypeClient = class _DataTypeClient extends ApiClient6 {
919
1037
  constructor(options) {
920
1038
  super(options);
921
1039
  }
922
- /** Fetches all DataTypes for a project */
923
- async get(options) {
1040
+ /** Fetches a list of DataTypes for a project */
1041
+ async list(options) {
924
1042
  const { projectId } = this.options;
925
1043
  const fetchUri = this.createUrl(__privateGet(_DataTypeClient, _url), { ...options, projectId });
926
1044
  return await this.apiClient(fetchUri);
927
1045
  }
1046
+ /** @deprecated Use {@link list} instead. */
1047
+ async get(options) {
1048
+ return this.list(options);
1049
+ }
928
1050
  /** Updates or creates (based on id) a DataType */
929
- async upsert(body) {
1051
+ async save(body) {
930
1052
  const fetchUri = this.createUrl(__privateGet(_DataTypeClient, _url));
931
1053
  await this.apiClient(fetchUri, {
932
1054
  method: "PUT",
@@ -934,6 +1056,10 @@ var _DataTypeClient = class _DataTypeClient extends ApiClient5 {
934
1056
  expectNoContent: true
935
1057
  });
936
1058
  }
1059
+ /** @deprecated Use {@link save} instead. */
1060
+ async upsert(body) {
1061
+ return this.save(body);
1062
+ }
937
1063
  /** Deletes a DataType */
938
1064
  async remove(body) {
939
1065
  const fetchUri = this.createUrl(__privateGet(_DataTypeClient, _url));
@@ -966,7 +1092,7 @@ var BatchEntry = class {
966
1092
  this._reject(reason);
967
1093
  this._isCompleted = true;
968
1094
  }
969
- /** @return Whether the batch entry has been completed (resolved or rejected). */
1095
+ /** @returns Whether the batch entry has been completed (resolved or rejected). */
970
1096
  get isCompleted() {
971
1097
  return this._isCompleted;
972
1098
  }
@@ -1069,60 +1195,6 @@ function getComponentPath(ancestorsAndSelf) {
1069
1195
  return `.${path.join(".")}`;
1070
1196
  }
1071
1197
 
1072
- // src/utils/constants.ts
1073
- var CANVAS_PERSONALIZE_TYPE = "$personalization";
1074
- var CANVAS_TEST_TYPE = "$test";
1075
- var CANVAS_LOCALIZATION_TYPE = "$localization";
1076
- var CANVAS_SLOT_SECTION_TYPE = "$slotSection";
1077
- var CANVAS_INTENT_TAG_PARAM = "intentTag";
1078
- var CANVAS_LOCALE_TAG_PARAM = "locale";
1079
- var CANVAS_BLOCK_PARAM_TYPE = "$block";
1080
- var CANVAS_PERSONALIZE_SLOT = "pz";
1081
- var CANVAS_TEST_SLOT = "test";
1082
- var CANVAS_LOCALIZATION_SLOT = "localized";
1083
- var CANVAS_SLOT_SECTION_SLOT = "$slotSectionItems";
1084
- var CANVAS_SLOT_SECTION_NAME_PARAM = "name";
1085
- var CANVAS_SLOT_SECTION_MIN_PARAM = "min";
1086
- var CANVAS_SLOT_SECTION_MAX_PARAM = "max";
1087
- var CANVAS_SLOT_SECTION_GROUP_TYPE_PARAM = "groupType";
1088
- var CANVAS_SLOT_SECTION_SPECIFIC_PARAM = "specific";
1089
- var CANVAS_DRAFT_STATE = 0;
1090
- var CANVAS_PUBLISHED_STATE = 64;
1091
- var CANVAS_EDITOR_STATE = 63;
1092
- var CANVAS_PERSONALIZATION_PARAM = "$pzCrit";
1093
- var CANVAS_PERSONALIZATION_EVENT_NAME_PARAM = "trackingEventName";
1094
- var CANVAS_PERSONALIZATION_ALGORITHM_PARAM = "algorithm";
1095
- var CANVAS_PERSONALIZATION_ALGORITHM_TYPE = "pzAlgorithm";
1096
- var CANVAS_PERSONALIZATION_TAKE_PARAM = "count";
1097
- var CANVAS_TEST_VARIANT_PARAM = "$tstVrnt";
1098
- var CANVAS_ENRICHMENT_TAG_PARAM = "$enr";
1099
- var CANVAS_INTERNAL_PARAM_PREFIX = "$internal_";
1100
- var CANVAS_COMPONENT_DISPLAY_NAME_PARAM = `${CANVAS_INTERNAL_PARAM_PREFIX}displayName`;
1101
- var CANVAS_HYPOTHESIS_PARAM = `${CANVAS_INTERNAL_PARAM_PREFIX}hypothesis`;
1102
- var CANVAS_CONTEXTUAL_EDITING_PARAM = "$contextualEditing";
1103
- var SECRET_QUERY_STRING_PARAM = "secret";
1104
- var IN_CONTEXT_EDITOR_QUERY_STRING_PARAM = "is_incontext_editing_mode";
1105
- var IN_CONTEXT_EDITOR_PLAYGROUND_QUERY_STRING_PARAM = "is_incontext_editing_playground";
1106
- var IN_CONTEXT_EDITOR_FORCED_SETTINGS_QUERY_STRING_PARAM = "is_incontext_editing_forced_settings";
1107
- var IN_CONTEXT_EDITOR_CONFIG_CHECK_QUERY_STRING_PARAM = "is_config_check";
1108
- var IN_CONTEXT_EDITOR_COMPONENT_START_ROLE = "uniform-component-start";
1109
- var IN_CONTEXT_EDITOR_COMPONENT_END_ROLE = "uniform-component-end";
1110
- var IN_CONTEXT_EDITOR_EMBED_SCRIPT_ID = "uniform-canvas-preview-script";
1111
- var IS_RENDERED_BY_UNIFORM_ATTRIBUTE = "data-is-rendered-by-uniform";
1112
- var PLACEHOLDER_ID = "placeholder";
1113
- var EMPTY_COMPOSITION = {
1114
- _id: "_empty_composition_id",
1115
- _name: "An empty composition used for contextual editing",
1116
- type: "_empty_composition_type"
1117
- };
1118
- var EDGE_MIN_CACHE_TTL = 10;
1119
- var EDGE_MAX_CACHE_TTL = 24 * 60 * 60;
1120
- var EDGE_DEFAULT_CACHE_TTL = 30;
1121
- var EDGE_CACHE_DISABLED = -1;
1122
- var ASSET_PARAMETER_TYPE = "asset";
1123
- var ASSETS_SOURCE_UNIFORM = "uniform-assets";
1124
- var ASSETS_SOURCE_CUSTOM_URL = "custom-url";
1125
-
1126
1198
  // src/utils/guards.ts
1127
1199
  function isRootEntryReference(root) {
1128
1200
  return root.type === "root" && isEntryData(root.node);
@@ -1189,10 +1261,12 @@ function flattenSingleNodeValues(data, options = {}) {
1189
1261
  ) : properties;
1190
1262
  }
1191
1263
 
1192
- // src/utils/variables/parseVariableExpression.ts
1193
- var escapeCharacter = "\\";
1264
+ // src/utils/variables/variableSyntax.ts
1194
1265
  var variablePrefix = "${";
1195
1266
  var variableSuffix = "}";
1267
+
1268
+ // src/utils/variables/parseVariableExpression.ts
1269
+ var escapeCharacter = "\\";
1196
1270
  function parseVariableExpression(serialized, onToken) {
1197
1271
  if (typeof serialized !== "string") {
1198
1272
  throw new TypeError("Variable expression must be a string");
@@ -1200,9 +1274,9 @@ function parseVariableExpression(serialized, onToken) {
1200
1274
  let bufferStartIndex = 0;
1201
1275
  let bufferEndIndex = 0;
1202
1276
  let tokenCount = 0;
1203
- const handleToken = (token, type) => {
1277
+ const handleToken = (token, type, offset) => {
1204
1278
  tokenCount++;
1205
- return onToken == null ? void 0 : onToken(token, type);
1279
+ return onToken == null ? void 0 : onToken(token, type, offset);
1206
1280
  };
1207
1281
  let state = "text";
1208
1282
  for (let index = 0; index < serialized.length; index++) {
@@ -1213,20 +1287,26 @@ function parseVariableExpression(serialized, onToken) {
1213
1287
  if (char === variablePrefix[0] && serialized[index + 1] === variablePrefix[1]) {
1214
1288
  if (serialized[index - 1] === escapeCharacter) {
1215
1289
  bufferEndIndex -= escapeCharacter.length;
1216
- if (handleToken(serialized.substring(bufferStartIndex, bufferEndIndex), "text") === false) {
1290
+ if (handleToken(serialized.substring(bufferStartIndex, bufferEndIndex), "text", bufferStartIndex) === false) {
1217
1291
  return tokenCount;
1218
1292
  }
1219
1293
  bufferStartIndex = index;
1220
1294
  bufferEndIndex = index + 1;
1221
1295
  continue;
1222
1296
  }
1223
- state = "variable";
1224
- if (bufferEndIndex > bufferStartIndex) {
1225
- if (handleToken(serialized.substring(bufferStartIndex, bufferEndIndex), "text") === false) {
1297
+ if (state === "variable") {
1298
+ const textStart = bufferStartIndex - variablePrefix.length;
1299
+ if (handleToken(serialized.substring(textStart, bufferEndIndex), "text", textStart) === false) {
1300
+ return tokenCount;
1301
+ }
1302
+ bufferStartIndex = bufferEndIndex;
1303
+ } else if (bufferEndIndex > bufferStartIndex) {
1304
+ if (handleToken(serialized.substring(bufferStartIndex, bufferEndIndex), "text", bufferStartIndex) === false) {
1226
1305
  return tokenCount;
1227
1306
  }
1228
1307
  bufferStartIndex = bufferEndIndex;
1229
1308
  }
1309
+ state = "variable";
1230
1310
  index += variablePrefix.length - 1;
1231
1311
  bufferStartIndex += variablePrefix.length;
1232
1312
  continue;
@@ -1239,7 +1319,7 @@ function parseVariableExpression(serialized, onToken) {
1239
1319
  state = "text";
1240
1320
  if (bufferEndIndex > bufferStartIndex) {
1241
1321
  const unescapedVariableName = serialized.substring(bufferStartIndex, bufferEndIndex).replace(/\\([${}])/g, "$1");
1242
- if (handleToken(unescapedVariableName, "variable") === false) {
1322
+ if (handleToken(unescapedVariableName, "variable", bufferStartIndex) === false) {
1243
1323
  return tokenCount;
1244
1324
  }
1245
1325
  bufferStartIndex = bufferEndIndex + variableSuffix.length;
@@ -1248,12 +1328,12 @@ function parseVariableExpression(serialized, onToken) {
1248
1328
  }
1249
1329
  bufferEndIndex++;
1250
1330
  }
1251
- if (bufferEndIndex > bufferStartIndex) {
1252
- if (state === "variable") {
1253
- state = "text";
1254
- bufferStartIndex -= variablePrefix.length;
1255
- }
1256
- handleToken(serialized.substring(bufferStartIndex), state);
1331
+ if (state === "variable") {
1332
+ state = "text";
1333
+ bufferStartIndex -= variablePrefix.length;
1334
+ }
1335
+ if (bufferStartIndex < serialized.length) {
1336
+ handleToken(serialized.substring(bufferStartIndex), state, bufferStartIndex);
1257
1337
  }
1258
1338
  return tokenCount;
1259
1339
  }
@@ -1274,7 +1354,7 @@ function hasReferencedVariables(value) {
1274
1354
 
1275
1355
  // src/enhancement/walkNodeTree.ts
1276
1356
  function walkNodeTree(node, visitor, options) {
1277
- var _a, _b;
1357
+ var _a, _b, _c;
1278
1358
  const componentQueue = [
1279
1359
  {
1280
1360
  ancestorsAndSelf: Array.isArray(node) ? node : [{ node, type: "root" }],
@@ -1282,12 +1362,14 @@ function walkNodeTree(node, visitor, options) {
1282
1362
  }
1283
1363
  ];
1284
1364
  const childContexts = /* @__PURE__ */ new Map();
1365
+ const order = (_a = options == null ? void 0 : options.order) != null ? _a : "dfs";
1366
+ const takeNext = () => order === "bfs" ? componentQueue.shift() : componentQueue.pop();
1285
1367
  do {
1286
- const currentQueueEntry = componentQueue.pop();
1368
+ const currentQueueEntry = takeNext();
1287
1369
  if (!currentQueueEntry) continue;
1288
1370
  const currentComponent = currentQueueEntry.ancestorsAndSelf[0];
1289
1371
  let visitDescendants = true;
1290
- let descendantContext = (_a = childContexts.get(currentComponent.node)) != null ? _a : currentQueueEntry.context;
1372
+ let descendantContext = (_b = childContexts.get(currentComponent.node)) != null ? _b : currentQueueEntry.context;
1291
1373
  let visitorInfo;
1292
1374
  if (currentComponent.type === "root" && isRootEntryReference(currentComponent) || currentComponent.type === "block") {
1293
1375
  visitorInfo = {
@@ -1389,7 +1471,8 @@ function walkNodeTree(node, visitor, options) {
1389
1471
  "_dataResources",
1390
1472
  "_overridability",
1391
1473
  "_overrides",
1392
- "_patternDataResources"
1474
+ "_patternDataResources",
1475
+ "_patternOptedInQueryStrings"
1393
1476
  ];
1394
1477
  propertiesToCheck.forEach((property) => {
1395
1478
  if (!replacementComponent[property]) {
@@ -1452,61 +1535,33 @@ function walkNodeTree(node, visitor, options) {
1452
1535
  })
1453
1536
  );
1454
1537
  }
1455
- } else {
1456
- throw new Error("Unknown type");
1457
- }
1458
- },
1459
- stopProcessingDescendants() {
1460
- visitDescendants = false;
1461
- },
1462
- setDescendantsContext(context) {
1463
- descendantContext = context;
1464
- },
1465
- setChildContext(child, context) {
1466
- childContexts.set(child, context);
1467
- }
1468
- },
1469
- context: descendantContext
1470
- };
1471
- }
1472
- visitor(visitorInfo);
1473
- if (!visitDescendants) {
1474
- continue;
1475
- }
1476
- const slots = "slots" in currentComponent.node && currentComponent.node.slots;
1477
- if (slots) {
1478
- const slotKeys = Object.keys(slots);
1479
- for (let slotIndex = slotKeys.length - 1; slotIndex >= 0; slotIndex--) {
1480
- const slotKey = slotKeys[slotIndex];
1481
- const components = slots[slotKey];
1482
- for (let componentIndex = components.length - 1; componentIndex >= 0; componentIndex--) {
1483
- const enqueueingComponent = components[componentIndex];
1484
- const parentSlotIndexFn = () => {
1485
- const result = currentComponent.node.slots[slotKey].findIndex(
1486
- (x) => x === enqueueingComponent
1487
- );
1488
- return result;
1489
- };
1490
- componentQueue.push({
1491
- ancestorsAndSelf: [
1492
- {
1493
- type: "slot",
1494
- node: enqueueingComponent,
1495
- parentSlot: slotKey,
1496
- parentSlotIndexFn
1497
- },
1498
- ...currentQueueEntry.ancestorsAndSelf
1499
- ],
1500
- context: descendantContext
1501
- });
1502
- }
1503
- }
1538
+ } else {
1539
+ throw new Error("Unknown type");
1540
+ }
1541
+ },
1542
+ stopProcessingDescendants() {
1543
+ visitDescendants = false;
1544
+ },
1545
+ setDescendantsContext(context) {
1546
+ descendantContext = context;
1547
+ },
1548
+ setChildContext(child, context) {
1549
+ childContexts.set(child, context);
1550
+ }
1551
+ },
1552
+ context: descendantContext
1553
+ };
1504
1554
  }
1555
+ visitor(visitorInfo);
1556
+ if (!visitDescendants) {
1557
+ continue;
1558
+ }
1559
+ const slots = "slots" in currentComponent.node && currentComponent.node.slots;
1560
+ const childEntries = [];
1505
1561
  const properties = getPropertiesValue(currentComponent.node);
1506
1562
  if (properties) {
1507
1563
  const propertyEntries = Object.entries(properties);
1508
- for (let propIndex = propertyEntries.length - 1; propIndex >= 0; propIndex--) {
1509
- const [propKey, propObject] = propertyEntries[propIndex];
1564
+ for (const [propKey, propObject] of propertyEntries) {
1510
1565
  if (!isNestedNodeType(propObject.type)) {
1511
1566
  continue;
1512
1567
  }
@@ -1526,13 +1581,12 @@ function walkNodeTree(node, visitor, options) {
1526
1581
  continue;
1527
1582
  }
1528
1583
  }
1529
- const blocks = (_b = propObject.value) != null ? _b : [];
1530
- for (let blockIndex = blocks.length - 1; blockIndex >= 0; blockIndex--) {
1531
- const enqueueingBlock = blocks[blockIndex];
1584
+ const blocks = (_c = propObject.value) != null ? _c : [];
1585
+ for (const enqueueingBlock of blocks) {
1532
1586
  const blockIndexFn = () => {
1533
1587
  return getBlockValue(currentComponent.node, propKey).findIndex((x) => x === enqueueingBlock);
1534
1588
  };
1535
- componentQueue.push({
1589
+ childEntries.push({
1536
1590
  ancestorsAndSelf: [
1537
1591
  {
1538
1592
  type: "block",
@@ -1547,6 +1601,36 @@ function walkNodeTree(node, visitor, options) {
1547
1601
  }
1548
1602
  }
1549
1603
  }
1604
+ if (slots) {
1605
+ const slotKeys = Object.keys(slots);
1606
+ for (const slotKey of slotKeys) {
1607
+ const components = slots[slotKey];
1608
+ for (const enqueueingComponent of components) {
1609
+ const parentSlotIndexFn = () => {
1610
+ const result = currentComponent.node.slots[slotKey].findIndex(
1611
+ (x) => x === enqueueingComponent
1612
+ );
1613
+ return result;
1614
+ };
1615
+ childEntries.push({
1616
+ ancestorsAndSelf: [
1617
+ {
1618
+ type: "slot",
1619
+ node: enqueueingComponent,
1620
+ parentSlot: slotKey,
1621
+ parentSlotIndexFn
1622
+ },
1623
+ ...currentQueueEntry.ancestorsAndSelf
1624
+ ],
1625
+ context: descendantContext
1626
+ });
1627
+ }
1628
+ }
1629
+ }
1630
+ if (order === "dfs") {
1631
+ childEntries.reverse();
1632
+ }
1633
+ componentQueue.push(...childEntries);
1550
1634
  } while (componentQueue.length > 0);
1551
1635
  }
1552
1636
  function isNestedNodeType(type) {
@@ -1972,7 +2056,7 @@ function getLocaleMatch(index, locale, greedy) {
1972
2056
  }
1973
2057
  const match = index[locale];
1974
2058
  if (match === void 0 && greedy) {
1975
- return Object.values(index)[0];
2059
+ return Object.values(index).find((value) => value !== void 0);
1976
2060
  }
1977
2061
  return match;
1978
2062
  }
@@ -1980,6 +2064,9 @@ function getLocaleMatch(index, locale, greedy) {
1980
2064
  // src/enhancement/visibility/evaluateVisibilityCriteriaGroup.ts
1981
2065
  function evaluateVisibilityCriteriaGroup(options) {
1982
2066
  const { criteriaGroup, simplifyCriteria } = options;
2067
+ if (criteriaGroup.clauses.length === 0) {
2068
+ return true;
2069
+ }
1983
2070
  const earlyExitResult = criteriaGroup.op === "&" || !criteriaGroup.op ? false : true;
1984
2071
  let hasIndeterminateClauses = false;
1985
2072
  for (let index = criteriaGroup.clauses.length - 1; index >= 0; index--) {
@@ -1988,6 +2075,9 @@ function evaluateVisibilityCriteriaGroup(options) {
1988
2075
  if (criteriaResult === null) {
1989
2076
  hasIndeterminateClauses = true;
1990
2077
  } else if (criteriaResult === earlyExitResult) {
2078
+ if (simplifyCriteria && earlyExitResult) {
2079
+ criteriaGroup.clauses.splice(0);
2080
+ }
1991
2081
  return earlyExitResult;
1992
2082
  } else if (criteriaResult !== null && simplifyCriteria) {
1993
2083
  criteriaGroup.clauses.splice(index, 1);
@@ -2175,7 +2265,11 @@ function evaluateWalkTreePropertyCriteria({
2175
2265
  delete properties[propertyName];
2176
2266
  }
2177
2267
  } else {
2178
- const { currentValue, remainingConditionalValues } = evaluatePropertyCriteria({
2268
+ const { currentValue, remainingConditionalValues } = property.conditions === void 0 ? (
2269
+ // most properties have no conditions: this is what evaluatePropertyCriteria returns for them,
2270
+ // without the cost of calling it for every property
2271
+ { currentValue: property.value, remainingConditionalValues: void 0 }
2272
+ ) : evaluatePropertyCriteria({
2179
2273
  baseValue: property.value,
2180
2274
  conditionalValues: property.conditions,
2181
2275
  rules,
@@ -2235,11 +2329,34 @@ var stringOperatorEvaluators = {
2235
2329
  endswith: endsWithEvaluator,
2236
2330
  empty: emptyEvaluator
2237
2331
  };
2332
+ var numericOperatorEvaluators = {
2333
+ gt: (left, right) => left > right,
2334
+ lt: (left, right) => left < right
2335
+ };
2336
+ function evaluateNumericOperator(criteria, matchValue) {
2337
+ const { op, value } = criteria;
2338
+ const evaluator = numericOperatorEvaluators[op];
2339
+ if (!evaluator) {
2340
+ return null;
2341
+ }
2342
+ if (typeof matchValue === "string" && matchValue.trim() === "" || typeof value === "string" && value.trim() === "") {
2343
+ return false;
2344
+ }
2345
+ const leftNum = Number(matchValue);
2346
+ const rightNum = Number(value);
2347
+ if (isNaN(leftNum) || isNaN(rightNum)) {
2348
+ return false;
2349
+ }
2350
+ return evaluator(leftNum, rightNum);
2351
+ }
2238
2352
  function evaluateStringMatch(criteria, matchValue, allow) {
2239
2353
  const { op, value } = criteria;
2240
2354
  if (allow && !allow.has(op)) {
2241
2355
  return null;
2242
2356
  }
2357
+ if (op in numericOperatorEvaluators) {
2358
+ return evaluateNumericOperator(criteria, matchValue);
2359
+ }
2243
2360
  let opMatch = op;
2244
2361
  const negation = op.startsWith("!");
2245
2362
  if (negation) {
@@ -2288,17 +2405,49 @@ var dynamicTokenVisibilityOperators = /* @__PURE__ */ new Set([
2288
2405
  "endswith",
2289
2406
  "!endswith",
2290
2407
  "empty",
2291
- "!empty"
2408
+ "!empty",
2409
+ "gt",
2410
+ "lt"
2292
2411
  ]);
2293
2412
  var CANVAS_VIZ_DYNAMIC_TOKEN_RULE = "$dt";
2413
+ function toStringValue(value) {
2414
+ if (typeof value === "string") {
2415
+ return value;
2416
+ }
2417
+ if (typeof value === "number" || typeof value === "boolean") {
2418
+ return String(value);
2419
+ }
2420
+ return "";
2421
+ }
2422
+ function toStringCriteriaValue(value) {
2423
+ if (Array.isArray(value)) {
2424
+ return value.map((v) => toStringValue(v));
2425
+ }
2426
+ return toStringValue(value);
2427
+ }
2428
+ function isUnbound(value) {
2429
+ if (value === void 0 || value === null) {
2430
+ return true;
2431
+ }
2432
+ if (typeof value === "string") {
2433
+ return hasReferencedVariables(value) > 0;
2434
+ }
2435
+ return false;
2436
+ }
2294
2437
  function createDynamicTokenVisibilityRule() {
2295
2438
  return {
2296
2439
  [CANVAS_VIZ_DYNAMIC_TOKEN_RULE]: (criterion) => {
2297
- var _a;
2298
- if (typeof criterion.source !== "string" || hasReferencedVariables(criterion.source)) {
2440
+ const { source, value } = criterion;
2441
+ if (isUnbound(source)) {
2299
2442
  return null;
2300
2443
  }
2301
- return evaluateStringMatch(criterion, (_a = criterion.source) != null ? _a : "", dynamicTokenVisibilityOperators);
2444
+ const stringSource = toStringValue(source);
2445
+ const stringValue = toStringCriteriaValue(value);
2446
+ const stringCriterion = {
2447
+ ...criterion,
2448
+ value: stringValue
2449
+ };
2450
+ return evaluateStringMatch(stringCriterion, stringSource, dynamicTokenVisibilityOperators);
2302
2451
  }
2303
2452
  };
2304
2453
  }
@@ -2357,8 +2506,7 @@ function extractLocales({ component }) {
2357
2506
  return variations;
2358
2507
  }
2359
2508
  function localize(options) {
2360
- const nodes = options.nodes;
2361
- const locale = options.locale;
2509
+ const { nodes, locale, keepLocalesFor } = options;
2362
2510
  if (!locale) {
2363
2511
  return;
2364
2512
  }
@@ -2366,7 +2514,7 @@ function localize(options) {
2366
2514
  walkNodeTree(nodes, (context) => {
2367
2515
  const { type, node, actions } = context;
2368
2516
  if (type !== "component") {
2369
- localizeProperties(node, locale, vizControlLocaleRule);
2517
+ localizeProperties(node, locale, vizControlLocaleRule, keepLocalesFor);
2370
2518
  return;
2371
2519
  }
2372
2520
  const result = evaluateWalkTreeNodeVisibility({
@@ -2387,7 +2535,7 @@ function localize(options) {
2387
2535
  if (replaceComponent == null ? void 0 : replaceComponent.length) {
2388
2536
  replaceComponent.forEach((component) => {
2389
2537
  removeLocaleProperty(component);
2390
- localizeProperties(component, locale, vizControlLocaleRule);
2538
+ localizeProperties(component, locale, vizControlLocaleRule, keepLocalesFor);
2391
2539
  });
2392
2540
  const [first, ...rest] = replaceComponent;
2393
2541
  actions.replace(first);
@@ -2398,7 +2546,7 @@ function localize(options) {
2398
2546
  actions.remove();
2399
2547
  }
2400
2548
  } else {
2401
- localizeProperties(node, locale, vizControlLocaleRule);
2549
+ localizeProperties(node, locale, vizControlLocaleRule, keepLocalesFor);
2402
2550
  }
2403
2551
  });
2404
2552
  }
@@ -2417,7 +2565,7 @@ function removeLocaleProperty(component) {
2417
2565
  }
2418
2566
  }
2419
2567
  }
2420
- function localizeProperties(node, locale, rules) {
2568
+ function localizeProperties(node, locale, rules, keepLocalesFor) {
2421
2569
  const properties = getPropertiesValue(node);
2422
2570
  if (!properties) {
2423
2571
  return void 0;
@@ -2436,10 +2584,16 @@ function localizeProperties(node, locale, rules) {
2436
2584
  if (currentLocaleConditionalValues !== void 0) {
2437
2585
  propertyValue.conditions = currentLocaleConditionalValues;
2438
2586
  }
2439
- delete propertyValue.locales;
2440
- delete propertyValue.localesConditions;
2587
+ const preserveLocales = (keepLocalesFor == null ? void 0 : keepLocalesFor(propertyId)) === true;
2588
+ if (!preserveLocales) {
2589
+ delete propertyValue.locales;
2590
+ delete propertyValue.localesConditions;
2591
+ }
2441
2592
  if (propertyValue.value === void 0 && propertyValue.conditions === void 0) {
2442
- delete properties[propertyId];
2593
+ const hasLocales = preserveLocales && (propertyValue.locales || propertyValue.localesConditions);
2594
+ if (!hasLocales) {
2595
+ delete properties[propertyId];
2596
+ }
2443
2597
  }
2444
2598
  });
2445
2599
  evaluateWalkTreePropertyCriteria({
@@ -2507,24 +2661,28 @@ function walkPropertyValues(property, visitor) {
2507
2661
  }
2508
2662
 
2509
2663
  // src/EntityReleasesClient.ts
2510
- import { ApiClient as ApiClient6 } from "@uniformdev/context/api";
2511
- var releaseContentsUrl = "/api/v1/entity-releases";
2512
- var EntityReleasesClient = class extends ApiClient6 {
2664
+ import { ApiClient as ApiClient7 } from "@uniformdev/context/api";
2665
+ var entityReleasesUrl = "/api/v1/entity-releases";
2666
+ var EntityReleasesClient = class extends ApiClient7 {
2513
2667
  constructor(options) {
2514
2668
  super(options);
2515
2669
  }
2516
2670
  /** Fetches entity across all releases (and base) */
2517
- async get(options) {
2671
+ async list(options) {
2518
2672
  const { projectId } = this.options;
2519
- const fetchUri = this.createUrl(releaseContentsUrl, { ...options, projectId });
2673
+ const fetchUri = this.createUrl(entityReleasesUrl, { ...options, projectId });
2520
2674
  return await this.apiClient(fetchUri);
2521
2675
  }
2676
+ /** @deprecated Use {@link list} instead. */
2677
+ async get(options) {
2678
+ return this.list(options);
2679
+ }
2522
2680
  };
2523
2681
 
2524
2682
  // src/IntegrationPropertyEditorsClient.ts
2525
- import { ApiClient as ApiClient7 } from "@uniformdev/context/api";
2683
+ import { ApiClient as ApiClient8 } from "@uniformdev/context/api";
2526
2684
  var _baseUrl;
2527
- var _IntegrationPropertyEditorsClient = class _IntegrationPropertyEditorsClient extends ApiClient7 {
2685
+ var _IntegrationPropertyEditorsClient = class _IntegrationPropertyEditorsClient extends ApiClient8 {
2528
2686
  constructor(options) {
2529
2687
  super(options);
2530
2688
  this.teamId = options.teamId;
@@ -2566,21 +2724,74 @@ _baseUrl = new WeakMap();
2566
2724
  __privateAdd(_IntegrationPropertyEditorsClient, _baseUrl, "/api/v1/integration-property-editors");
2567
2725
  var IntegrationPropertyEditorsClient = _IntegrationPropertyEditorsClient;
2568
2726
 
2727
+ // src/LabelClient.ts
2728
+ import { ApiClient as ApiClient9 } from "@uniformdev/context/api";
2729
+ var LABELS_URL = "/api/v1/labels";
2730
+ var LabelClient = class extends ApiClient9 {
2731
+ /** Fetches a list of labels for the current project. */
2732
+ async list(options) {
2733
+ const { projectId } = this.options;
2734
+ const fetchUri = this.createUrl(LABELS_URL, { ...options, projectId });
2735
+ return await this.apiClient(fetchUri);
2736
+ }
2737
+ /** @deprecated Use {@link list} instead. */
2738
+ async getLabels(options) {
2739
+ return this.list(options);
2740
+ }
2741
+ /** Updates or creates a label. */
2742
+ async save(body) {
2743
+ const { projectId } = this.options;
2744
+ const fetchUri = this.createUrl(LABELS_URL);
2745
+ await this.apiClient(fetchUri, {
2746
+ method: "PUT",
2747
+ body: JSON.stringify({ ...body, projectId }),
2748
+ expectNoContent: true
2749
+ });
2750
+ }
2751
+ /** @deprecated Use {@link save} instead. */
2752
+ async upsertLabel(body) {
2753
+ return this.save(body);
2754
+ }
2755
+ /** Deletes a label by id. */
2756
+ async remove(options) {
2757
+ const { projectId } = this.options;
2758
+ const fetchUri = this.createUrl(LABELS_URL);
2759
+ await this.apiClient(fetchUri, {
2760
+ method: "DELETE",
2761
+ body: JSON.stringify({ ...options, projectId }),
2762
+ expectNoContent: true
2763
+ });
2764
+ }
2765
+ /** @deprecated Use {@link remove} instead. */
2766
+ async removeLabel(options) {
2767
+ return this.remove(options);
2768
+ }
2769
+ };
2770
+ var UncachedLabelClient = class extends LabelClient {
2771
+ constructor(options) {
2772
+ super({ ...options, bypassCache: true });
2773
+ }
2774
+ };
2775
+
2569
2776
  // src/LocaleClient.ts
2570
- import { ApiClient as ApiClient8 } from "@uniformdev/context/api";
2777
+ import { ApiClient as ApiClient10 } from "@uniformdev/context/api";
2571
2778
  var localesUrl = "/api/v1/locales";
2572
- var LocaleClient = class extends ApiClient8 {
2779
+ var LocaleClient = class extends ApiClient10 {
2573
2780
  constructor(options) {
2574
2781
  super(options);
2575
2782
  }
2576
- /** Fetches all locales for a project */
2577
- async get(options) {
2783
+ /** Fetches a list of locales for a project */
2784
+ async list(options) {
2578
2785
  const { projectId } = this.options;
2579
2786
  const fetchUri = this.createUrl(localesUrl, { ...options, projectId });
2580
2787
  return await this.apiClient(fetchUri);
2581
2788
  }
2789
+ /** @deprecated Use {@link list} instead. */
2790
+ async get(options) {
2791
+ return this.list(options);
2792
+ }
2582
2793
  /** Updates or creates (based on id) a locale */
2583
- async upsert(body) {
2794
+ async save(body) {
2584
2795
  const fetchUri = this.createUrl(localesUrl);
2585
2796
  await this.apiClient(fetchUri, {
2586
2797
  method: "PUT",
@@ -2588,6 +2799,10 @@ var LocaleClient = class extends ApiClient8 {
2588
2799
  expectNoContent: true
2589
2800
  });
2590
2801
  }
2802
+ /** @deprecated Use {@link save} instead. */
2803
+ async upsert(body) {
2804
+ return this.save(body);
2805
+ }
2591
2806
  /** Deletes a locale */
2592
2807
  async remove(body) {
2593
2808
  const fetchUri = this.createUrl(localesUrl);
@@ -2624,6 +2839,12 @@ var isSelectComponentMessage = (message) => {
2624
2839
  var isReadyMessage = (message) => {
2625
2840
  return message.type === "ready";
2626
2841
  };
2842
+ var isSessionPendingMessage = (message) => {
2843
+ return message.type === "session-pending";
2844
+ };
2845
+ var isAwaitingReadyMessage = (message) => {
2846
+ return message.type === "awaiting-ready";
2847
+ };
2627
2848
  var isComponentActionMessage = (message) => {
2628
2849
  return message.type === "trigger-component-action";
2629
2850
  };
@@ -2726,6 +2947,14 @@ var createCanvasChannel = ({
2726
2947
  };
2727
2948
  postMessage(message);
2728
2949
  };
2950
+ const sessionPending = () => {
2951
+ const message = { type: "session-pending" };
2952
+ postMessage(message);
2953
+ };
2954
+ const awaitingReady = () => {
2955
+ const message = { type: "awaiting-ready" };
2956
+ postMessage(message);
2957
+ };
2729
2958
  const on = (types, handler) => {
2730
2959
  const handlerId = ++handlerCounter;
2731
2960
  handlers[handlerId] = {
@@ -2925,6 +3154,8 @@ var createCanvasChannel = ({
2925
3154
  return {
2926
3155
  broadcastTo: broadcastToItems,
2927
3156
  ready,
3157
+ sessionPending,
3158
+ awaitingReady,
2928
3159
  destroy,
2929
3160
  addBroadcastTarget,
2930
3161
  triggerComponentAction,
@@ -2955,10 +3186,10 @@ var createCanvasChannel = ({
2955
3186
  };
2956
3187
 
2957
3188
  // src/PreviewClient.ts
2958
- import { ApiClient as ApiClient9 } from "@uniformdev/context/api";
3189
+ import { ApiClient as ApiClient11 } from "@uniformdev/context/api";
2959
3190
  var previewUrlsUrl = "/api/v1/preview-urls";
2960
3191
  var previewViewportsUrl = "/api/v1/preview-viewports";
2961
- var PreviewClient = class extends ApiClient9 {
3192
+ var PreviewClient = class extends ApiClient11 {
2962
3193
  constructor(options) {
2963
3194
  super(options);
2964
3195
  }
@@ -3021,9 +3252,9 @@ var PreviewClient = class extends ApiClient9 {
3021
3252
  };
3022
3253
 
3023
3254
  // src/ProjectClient.ts
3024
- import { ApiClient as ApiClient10 } from "@uniformdev/context/api";
3025
- var _url2;
3026
- var _ProjectClient = class _ProjectClient extends ApiClient10 {
3255
+ import { ApiClient as ApiClient12 } from "@uniformdev/context/api";
3256
+ var _url2, _projectsUrl;
3257
+ var _ProjectClient = class _ProjectClient extends ApiClient12 {
3027
3258
  constructor(options) {
3028
3259
  super({ ...options, bypassCache: true });
3029
3260
  }
@@ -3032,16 +3263,33 @@ var _ProjectClient = class _ProjectClient extends ApiClient10 {
3032
3263
  const fetchUri = this.createUrl(__privateGet(_ProjectClient, _url2), { ...options });
3033
3264
  return await this.apiClient(fetchUri);
3034
3265
  }
3266
+ /**
3267
+ * Fetches projects grouped by team.
3268
+ * When teamId is provided, returns a single team with its projects.
3269
+ * When omitted, returns all accessible teams and their projects.
3270
+ */
3271
+ async list(options) {
3272
+ const fetchUri = this.createUrl(__privateGet(_ProjectClient, _projectsUrl), options ? { ...options } : {});
3273
+ return await this.apiClient(fetchUri);
3274
+ }
3275
+ /** @deprecated Use {@link list} instead. */
3276
+ async getProjects(options) {
3277
+ return this.list(options);
3278
+ }
3035
3279
  /** Updates or creates (based on id) a Project */
3036
- async upsert(body) {
3280
+ async save(body) {
3037
3281
  const fetchUri = this.createUrl(__privateGet(_ProjectClient, _url2));
3038
3282
  return await this.apiClient(fetchUri, {
3039
3283
  method: "PUT",
3040
3284
  body: JSON.stringify({ ...body })
3041
3285
  });
3042
3286
  }
3287
+ /** @deprecated Use {@link save} instead. */
3288
+ async upsert(body) {
3289
+ return this.save(body);
3290
+ }
3043
3291
  /** Deletes a Project */
3044
- async delete(body) {
3292
+ async remove(body) {
3045
3293
  const fetchUri = this.createUrl(__privateGet(_ProjectClient, _url2));
3046
3294
  await this.apiClient(fetchUri, {
3047
3295
  method: "DELETE",
@@ -3049,15 +3297,203 @@ var _ProjectClient = class _ProjectClient extends ApiClient10 {
3049
3297
  expectNoContent: true
3050
3298
  });
3051
3299
  }
3300
+ /** @deprecated Use {@link remove} instead. */
3301
+ async delete(body) {
3302
+ return this.remove(body);
3303
+ }
3052
3304
  };
3053
3305
  _url2 = new WeakMap();
3306
+ _projectsUrl = new WeakMap();
3054
3307
  __privateAdd(_ProjectClient, _url2, "/api/v1/project");
3308
+ __privateAdd(_ProjectClient, _projectsUrl, "/api/v1/projects");
3055
3309
  var ProjectClient = _ProjectClient;
3056
3310
 
3311
+ // src/projection/matchesProjectionPattern.ts
3312
+ var DISALLOWED_PATTERN_CHARS = /[,&=?#[\]\s]/;
3313
+ var REGEX_METACHAR = /[\\^$.|?*+()[\]{}]/g;
3314
+ function isValidProjectionPattern(pattern) {
3315
+ if (typeof pattern !== "string" || pattern.length === 0) {
3316
+ return false;
3317
+ }
3318
+ if (DISALLOWED_PATTERN_CHARS.test(pattern)) {
3319
+ return false;
3320
+ }
3321
+ return true;
3322
+ }
3323
+ function compilePattern(pattern) {
3324
+ let regexSource = "^";
3325
+ for (const ch of pattern) {
3326
+ if (ch === "*") {
3327
+ regexSource += ".*";
3328
+ } else {
3329
+ regexSource += ch.replace(REGEX_METACHAR, "\\$&");
3330
+ }
3331
+ }
3332
+ regexSource += "$";
3333
+ return new RegExp(regexSource);
3334
+ }
3335
+ var PATTERN_CACHE_MAX = 1024;
3336
+ var patternRegexCache = /* @__PURE__ */ new Map();
3337
+ function matchesProjectionPattern(pattern, value) {
3338
+ let re = patternRegexCache.get(pattern);
3339
+ if (re === void 0) {
3340
+ if (!isValidProjectionPattern(pattern)) {
3341
+ throw new Error(`Invalid projection pattern: ${JSON.stringify(pattern)}`);
3342
+ }
3343
+ re = compilePattern(pattern);
3344
+ if (patternRegexCache.size >= PATTERN_CACHE_MAX) {
3345
+ const oldest = patternRegexCache.keys().next().value;
3346
+ if (oldest !== void 0) patternRegexCache.delete(oldest);
3347
+ }
3348
+ patternRegexCache.set(pattern, re);
3349
+ }
3350
+ return re.test(value);
3351
+ }
3352
+
3353
+ // src/projection/queryToProjection.ts
3354
+ var TOP_LEVEL_OPERATOR_KEY = /^(fields|fieldTypes|slots)\[([A-Za-z]+)\]$/;
3355
+ var SLOTS_NAMED_KEY = /^slots\.([A-Za-z0-9_-]+)\[([A-Za-z]+)\]$/;
3356
+ function toStringValue2(value) {
3357
+ if (Array.isArray(value)) {
3358
+ return value.join(",");
3359
+ }
3360
+ return value;
3361
+ }
3362
+ function parseCsv(value) {
3363
+ const str = toStringValue2(value);
3364
+ if (!str) {
3365
+ return [];
3366
+ }
3367
+ return str.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
3368
+ }
3369
+ function parseDepth(value, key) {
3370
+ const str = toStringValue2(value);
3371
+ if (str === void 0 || str === "") {
3372
+ throw new Error(`Invalid select projection: '${key}' requires a non-negative integer value`);
3373
+ }
3374
+ if (!/^\d+$/.test(str)) {
3375
+ throw new Error(
3376
+ `Invalid select projection: '${key}' must be a non-negative integer (got ${JSON.stringify(str)})`
3377
+ );
3378
+ }
3379
+ return Number(str);
3380
+ }
3381
+ function parseBlockDepth(value, key) {
3382
+ const str = toStringValue2(value);
3383
+ if (str === "preserveAll") {
3384
+ return "preserveAll";
3385
+ }
3386
+ if (str === void 0 || str === "" || !/^\d+$/.test(str)) {
3387
+ throw new Error(
3388
+ `Invalid select projection: '${key}' must be a non-negative integer or 'preserveAll' (got ${JSON.stringify(str)})`
3389
+ );
3390
+ }
3391
+ return Number(str);
3392
+ }
3393
+ function extractSelectKeys(source) {
3394
+ if (source instanceof URLSearchParams) {
3395
+ let out2;
3396
+ for (const [key, value] of source.entries()) {
3397
+ if (!key.startsWith(SELECT_QUERY_PREFIX)) continue;
3398
+ out2 != null ? out2 : out2 = {};
3399
+ out2[key] = out2[key] === void 0 ? value : `${out2[key]},${value}`;
3400
+ }
3401
+ return out2;
3402
+ }
3403
+ let out;
3404
+ for (const key in source) {
3405
+ if (!key.startsWith(SELECT_QUERY_PREFIX)) continue;
3406
+ out != null ? out : out = {};
3407
+ out[key] = source[key];
3408
+ }
3409
+ return out;
3410
+ }
3411
+ function queryToProjection(source) {
3412
+ var _a, _b, _c, _d, _e;
3413
+ if (!source) {
3414
+ return void 0;
3415
+ }
3416
+ const query = extractSelectKeys(source);
3417
+ if (!query) {
3418
+ return void 0;
3419
+ }
3420
+ const spec = {};
3421
+ for (const [rawKey, value] of Object.entries(query)) {
3422
+ const key = rawKey.slice(SELECT_QUERY_PREFIX.length);
3423
+ const namedMatch = SLOTS_NAMED_KEY.exec(key);
3424
+ if (namedMatch) {
3425
+ const [, slotName, operator2] = namedMatch;
3426
+ if (operator2 !== "depth") {
3427
+ throw new Error(
3428
+ `Invalid select projection: unsupported operator '${operator2}' for slots.${slotName}`
3429
+ );
3430
+ }
3431
+ const slots = (_a = spec.slots) != null ? _a : spec.slots = {};
3432
+ const named = (_b = slots.named) != null ? _b : slots.named = {};
3433
+ named[slotName] = { ...named[slotName], depth: parseDepth(value, rawKey) };
3434
+ continue;
3435
+ }
3436
+ const topMatch = TOP_LEVEL_OPERATOR_KEY.exec(key);
3437
+ if (!topMatch) {
3438
+ throw new Error(`Invalid select projection key: ${JSON.stringify(rawKey)}`);
3439
+ }
3440
+ const [, bucket, operator] = topMatch;
3441
+ if (bucket === "fields") {
3442
+ const fields = (_c = spec.fields) != null ? _c : spec.fields = {};
3443
+ switch (operator) {
3444
+ case "only":
3445
+ fields.only = parseCsv(value);
3446
+ break;
3447
+ case "except":
3448
+ fields.except = parseCsv(value);
3449
+ break;
3450
+ case "locales":
3451
+ fields.locales = parseCsv(value);
3452
+ break;
3453
+ case "blockDepth":
3454
+ fields.blockDepth = parseBlockDepth(value, rawKey);
3455
+ break;
3456
+ default:
3457
+ throw new Error(`Invalid select projection: unsupported operator 'fields[${operator}]'`);
3458
+ }
3459
+ } else if (bucket === "fieldTypes") {
3460
+ const fieldTypes = (_d = spec.fieldTypes) != null ? _d : spec.fieldTypes = {};
3461
+ switch (operator) {
3462
+ case "only":
3463
+ fieldTypes.only = parseCsv(value);
3464
+ break;
3465
+ case "except":
3466
+ fieldTypes.except = parseCsv(value);
3467
+ break;
3468
+ default:
3469
+ throw new Error(`Invalid select projection: unsupported operator 'fieldTypes[${operator}]'`);
3470
+ }
3471
+ } else if (bucket === "slots") {
3472
+ const slots = (_e = spec.slots) != null ? _e : spec.slots = {};
3473
+ switch (operator) {
3474
+ case "only":
3475
+ slots.only = parseCsv(value);
3476
+ break;
3477
+ case "except":
3478
+ slots.except = parseCsv(value);
3479
+ break;
3480
+ case "depth":
3481
+ slots.depth = parseDepth(value, rawKey);
3482
+ break;
3483
+ default:
3484
+ throw new Error(`Invalid select projection: unsupported operator 'slots[${operator}]'`);
3485
+ }
3486
+ } else {
3487
+ throw new Error(`Invalid select projection key: ${JSON.stringify(rawKey)}`);
3488
+ }
3489
+ }
3490
+ return spec;
3491
+ }
3492
+
3057
3493
  // src/PromptClient.ts
3058
- import { ApiClient as ApiClient11 } from "@uniformdev/context/api";
3494
+ import { ApiClient as ApiClient13 } from "@uniformdev/context/api";
3059
3495
  var PromptsUrl = "/api/v1/prompts";
3060
- var PromptClient = class extends ApiClient11 {
3496
+ var PromptClient = class extends ApiClient13 {
3061
3497
  constructor(options) {
3062
3498
  super(options);
3063
3499
  }
@@ -3088,34 +3524,42 @@ var PromptClient = class extends ApiClient11 {
3088
3524
  };
3089
3525
 
3090
3526
  // src/RelationshipClient.ts
3091
- import { ApiClient as ApiClient12 } from "@uniformdev/context/api";
3527
+ import { ApiClient as ApiClient14 } from "@uniformdev/context/api";
3092
3528
  var RELATIONSHIPS_URL = "/api/v1/relationships";
3093
- var RelationshipClient = class extends ApiClient12 {
3529
+ var RelationshipClient = class extends ApiClient14 {
3094
3530
  constructor(options) {
3095
3531
  super(options);
3096
- this.get = async (options) => {
3532
+ this.list = async (options) => {
3097
3533
  const { projectId } = this.options;
3098
3534
  const url = this.createUrl(RELATIONSHIPS_URL, { ...options, projectId });
3099
3535
  return this.apiClient(url);
3100
3536
  };
3537
+ /** @deprecated Use {@link list} instead. */
3538
+ this.get = async (options) => {
3539
+ return this.list(options);
3540
+ };
3101
3541
  }
3102
3542
  };
3103
3543
 
3104
3544
  // src/ReleaseClient.ts
3105
- import { ApiClient as ApiClient13 } from "@uniformdev/context/api";
3545
+ import { ApiClient as ApiClient15 } from "@uniformdev/context/api";
3106
3546
  var releasesUrl = "/api/v1/releases";
3107
- var ReleaseClient = class extends ApiClient13 {
3547
+ var ReleaseClient = class extends ApiClient15 {
3108
3548
  constructor(options) {
3109
3549
  super(options);
3110
3550
  }
3111
- /** Fetches all releases for a project */
3112
- async get(options) {
3551
+ /** Fetches a list of releases for a project */
3552
+ async list(options) {
3113
3553
  const { projectId } = this.options;
3114
3554
  const fetchUri = this.createUrl(releasesUrl, { ...options, projectId });
3115
3555
  return await this.apiClient(fetchUri);
3116
3556
  }
3557
+ /** @deprecated Use {@link list} instead. */
3558
+ async get(options) {
3559
+ return this.list(options);
3560
+ }
3117
3561
  /** Updates or creates (based on id) a release */
3118
- async upsert(body) {
3562
+ async save(body) {
3119
3563
  const fetchUri = this.createUrl(releasesUrl);
3120
3564
  await this.apiClient(fetchUri, {
3121
3565
  method: "PUT",
@@ -3123,6 +3567,10 @@ var ReleaseClient = class extends ApiClient13 {
3123
3567
  expectNoContent: true
3124
3568
  });
3125
3569
  }
3570
+ /** @deprecated Use {@link save} instead. */
3571
+ async upsert(body) {
3572
+ return this.save(body);
3573
+ }
3126
3574
  /** Deletes a release */
3127
3575
  async remove(body) {
3128
3576
  const fetchUri = this.createUrl(releasesUrl);
@@ -3144,21 +3592,25 @@ var ReleaseClient = class extends ApiClient13 {
3144
3592
  };
3145
3593
 
3146
3594
  // src/ReleaseContentsClient.ts
3147
- import { ApiClient as ApiClient14 } from "@uniformdev/context/api";
3148
- var releaseContentsUrl2 = "/api/v1/release-contents";
3149
- var ReleaseContentsClient = class extends ApiClient14 {
3595
+ import { ApiClient as ApiClient16 } from "@uniformdev/context/api";
3596
+ var releaseContentsUrl = "/api/v1/release-contents";
3597
+ var ReleaseContentsClient = class extends ApiClient16 {
3150
3598
  constructor(options) {
3151
3599
  super(options);
3152
3600
  }
3153
- /** Fetches all entities added to a release */
3154
- async get(options) {
3601
+ /** Fetches a list of entities added to a release */
3602
+ async list(options) {
3155
3603
  const { projectId } = this.options;
3156
- const fetchUri = this.createUrl(releaseContentsUrl2, { ...options, projectId });
3604
+ const fetchUri = this.createUrl(releaseContentsUrl, { ...options, projectId });
3157
3605
  return await this.apiClient(fetchUri);
3158
3606
  }
3607
+ /** @deprecated Use {@link list} instead. */
3608
+ async get(options) {
3609
+ return this.list(options);
3610
+ }
3159
3611
  /** Removes a release content from a release */
3160
3612
  async remove(body) {
3161
- const fetchUri = this.createUrl(releaseContentsUrl2);
3613
+ const fetchUri = this.createUrl(releaseContentsUrl);
3162
3614
  await this.apiClient(fetchUri, {
3163
3615
  method: "DELETE",
3164
3616
  body: JSON.stringify({ ...body, projectId: this.options.projectId }),
@@ -3168,9 +3620,9 @@ var ReleaseContentsClient = class extends ApiClient14 {
3168
3620
  };
3169
3621
 
3170
3622
  // src/RouteClient.ts
3171
- import { ApiClient as ApiClient15 } from "@uniformdev/context/api";
3623
+ import { ApiClient as ApiClient17 } from "@uniformdev/context/api";
3172
3624
  var ROUTE_URL = "/api/v1/route";
3173
- var RouteClient = class extends ApiClient15 {
3625
+ var RouteClient = class extends ApiClient17 {
3174
3626
  constructor(options) {
3175
3627
  var _a;
3176
3628
  if (!options.limitPolicy) {
@@ -3179,15 +3631,27 @@ var RouteClient = class extends ApiClient15 {
3179
3631
  super(options);
3180
3632
  this.edgeApiHost = (_a = options.edgeApiHost) != null ? _a : "https://uniform.global";
3181
3633
  }
3182
- /** Fetches lists of Canvas compositions, optionally by type */
3183
- async getRoute(options) {
3634
+ /**
3635
+ * Resolves a route to a composition, redirect, or not-found result.
3636
+ *
3637
+ * An optional `select` projection applies to the resolved composition when
3638
+ * the route matches one; redirect / notFound responses pass through
3639
+ * untouched.
3640
+ */
3641
+ async get(options) {
3184
3642
  const { projectId } = this.options;
3185
- const fetchUri = this.createUrl(ROUTE_URL, { ...options, projectId }, this.edgeApiHost);
3643
+ const { select, ...rest } = options != null ? options : {};
3644
+ const rewrittenSelect = projectionToQuery(select);
3645
+ const fetchUri = this.createUrl(ROUTE_URL, { ...rest, projectId, ...rewrittenSelect }, this.edgeApiHost);
3186
3646
  return await this.apiClient(
3187
3647
  fetchUri,
3188
3648
  this.options.disableSWR ? { headers: { "x-disable-swr": "true" } } : void 0
3189
3649
  );
3190
3650
  }
3651
+ /** @deprecated use {@link RouteClient.get} instead (renamed). */
3652
+ async getRoute(options) {
3653
+ return this.get(options);
3654
+ }
3191
3655
  };
3192
3656
 
3193
3657
  // src/types/locales.ts
@@ -3295,6 +3759,7 @@ function convertEntryToPutEntry(entry) {
3295
3759
  releaseId: entry.releaseId,
3296
3760
  workflowId: entry.workflowId,
3297
3761
  workflowStageId: entry.workflowStageId,
3762
+ instanceWorkflowId: entry.instanceWorkflowId,
3298
3763
  editionId: entry.editionId,
3299
3764
  editionName: entry.editionName,
3300
3765
  editionPriority: entry.editionPriority
@@ -3345,8 +3810,13 @@ var getParameterAttributes = ({
3345
3810
  };
3346
3811
 
3347
3812
  // src/utils/isAllowedReferrer.ts
3813
+ var ALLOWED_REFERRER_ORIGIN = /^https:\/\/([\w-]+\.)*(uniform\.(app|wtf)|uniformcode\.ai)$|^https?:\/\/localhost:\d{4}$/;
3348
3814
  var isAllowedReferrer = (referrer) => {
3349
- return Boolean(referrer == null ? void 0 : referrer.match(/(^https:\/\/|\.)(uniform.app|uniform.wtf|localhost:\d{4})\//));
3815
+ try {
3816
+ return ALLOWED_REFERRER_ORIGIN.test(new URL(referrer != null ? referrer : "").origin);
3817
+ } catch (e) {
3818
+ return false;
3819
+ }
3350
3820
  };
3351
3821
 
3352
3822
  // src/utils/isSystemComponentDefinition.ts
@@ -3430,6 +3900,9 @@ function bindVariables({
3430
3900
  errorPrefix = "Variable",
3431
3901
  handleBinding
3432
3902
  }) {
3903
+ if (!value.includes(variablePrefix)) {
3904
+ return { result: value, boundCount: 0, errors: void 0 };
3905
+ }
3433
3906
  let boundCount = 0;
3434
3907
  let tokenCount = 0;
3435
3908
  const errors = [];
@@ -3460,13 +3933,15 @@ function bindVariables({
3460
3933
  }
3461
3934
 
3462
3935
  // src/utils/variables/bindVariablesToObject.ts
3463
- import { isDraft, produce } from "immer";
3464
3936
  function bindVariablesToObject(options) {
3465
- return bindVariablesToObjectRecursive(options);
3937
+ const { value } = options;
3938
+ const bindableObjects = typeof value === "object" && value !== null ? findBindableObjects(value) : void 0;
3939
+ return bindVariablesToObjectRecursive({ ...options, bindableObjects });
3466
3940
  }
3467
3941
  function bindVariablesToObjectRecursive({
3468
3942
  value,
3469
3943
  recursivePath,
3944
+ bindableObjects,
3470
3945
  ...bindVariablesOptions
3471
3946
  }) {
3472
3947
  let boundCount = 0;
@@ -3481,50 +3956,93 @@ function bindVariablesToObjectRecursive({
3481
3956
  if (richTextNodeResult !== void 0) {
3482
3957
  return richTextNodeResult;
3483
3958
  }
3484
- const produceToUse = !isDraft(value) ? produce : (produceValue, producer) => {
3485
- producer(produceValue);
3486
- return produceValue;
3959
+ if (bindableObjects && !bindableObjects.has(value)) {
3960
+ return { boundCount: 0, result: value };
3961
+ }
3962
+ let copy;
3963
+ const assign = (property, boundValue) => {
3964
+ copy != null ? copy : copy = Array.isArray(value) ? value.slice() : Object.assign(Object.create(Object.getPrototypeOf(value)), value);
3965
+ copy[property] = boundValue;
3487
3966
  };
3488
- const result = produceToUse(value, (draft) => {
3489
- Object.entries(draft).forEach(([property, oldValue]) => {
3490
- const currentObjectPath = recursivePath ? `${recursivePath}.${property}` : property;
3491
- if (typeof oldValue === "string") {
3492
- const bindResult = bindVariables({ ...bindVariablesOptions, value: oldValue });
3493
- if (oldValue !== bindResult.result || bindResult.errors) {
3494
- boundCount += bindResult.boundCount;
3495
- draft[property] = bindResult.result;
3496
- if (bindResult.errors) {
3497
- errors.push(
3498
- ...bindResult.errors.map((e) => {
3499
- if (typeof e === "string") {
3500
- return `${currentObjectPath}: ${e}`;
3501
- }
3502
- e.message = `${currentObjectPath}: ${e.message}`;
3503
- return e;
3504
- })
3505
- );
3506
- }
3507
- }
3967
+ Object.entries(value).forEach(([property, oldValue]) => {
3968
+ const currentObjectPath = recursivePath ? `${recursivePath}.${property}` : property;
3969
+ if (typeof oldValue === "string") {
3970
+ if (!oldValue.includes(variablePrefix)) {
3508
3971
  return;
3509
3972
  }
3510
- const childBind = bindVariablesToObjectRecursive({
3511
- ...bindVariablesOptions,
3512
- value: oldValue,
3513
- recursivePath: currentObjectPath
3514
- });
3515
- if (childBind.boundCount || childBind.errors) {
3516
- boundCount += childBind.boundCount;
3517
- draft[property] = childBind.result;
3518
- if (childBind.errors) {
3519
- errors.push(...childBind.errors);
3973
+ const bindResult = bindVariables({ ...bindVariablesOptions, value: oldValue });
3974
+ if (oldValue !== bindResult.result || bindResult.errors) {
3975
+ boundCount += bindResult.boundCount;
3976
+ assign(property, bindResult.result);
3977
+ if (bindResult.errors) {
3978
+ errors.push(
3979
+ ...bindResult.errors.map((e) => {
3980
+ if (typeof e === "string") {
3981
+ return `${currentObjectPath}: ${e}`;
3982
+ }
3983
+ e.message = `${currentObjectPath}: ${e.message}`;
3984
+ return e;
3985
+ })
3986
+ );
3520
3987
  }
3521
3988
  }
3989
+ return;
3990
+ }
3991
+ const childBind = bindVariablesToObjectRecursive({
3992
+ ...bindVariablesOptions,
3993
+ value: oldValue,
3994
+ recursivePath: currentObjectPath,
3995
+ bindableObjects
3522
3996
  });
3997
+ if (childBind.boundCount || childBind.errors) {
3998
+ boundCount += childBind.boundCount;
3999
+ assign(property, childBind.result);
4000
+ if (childBind.errors) {
4001
+ errors.push(...childBind.errors);
4002
+ }
4003
+ }
3523
4004
  });
4005
+ const result = copy != null ? copy : value;
3524
4006
  return { boundCount, result, errors: errors.length > 0 ? errors : void 0 };
3525
4007
  }
4008
+ function findBindableObjects(root) {
4009
+ const bindable = /* @__PURE__ */ new Set();
4010
+ const visit = (value) => {
4011
+ if (typeof value === "string") {
4012
+ return value.includes(variablePrefix);
4013
+ }
4014
+ if (typeof value !== "object" || value === null) {
4015
+ return false;
4016
+ }
4017
+ if (bindable.has(value)) {
4018
+ return true;
4019
+ }
4020
+ let found = isRichTextVariableNode(value);
4021
+ if (!found) {
4022
+ if (Array.isArray(value)) {
4023
+ for (let i = 0; i < value.length; i++) {
4024
+ found = visit(value[i]) || found;
4025
+ }
4026
+ } else {
4027
+ const keys = Object.keys(value);
4028
+ for (let i = 0; i < keys.length; i++) {
4029
+ found = visit(value[keys[i]]) || found;
4030
+ }
4031
+ }
4032
+ }
4033
+ if (found) {
4034
+ bindable.add(value);
4035
+ }
4036
+ return found;
4037
+ };
4038
+ visit(root);
4039
+ return bindable;
4040
+ }
4041
+ function isRichTextVariableNode(object) {
4042
+ return "type" in object && object.type === "variable" && "reference" in object && typeof object.reference === "string" && "version" in object && object.version === 1;
4043
+ }
3526
4044
  function handleRichTextNodeBinding(object, options) {
3527
- if ("type" in object && object.type === "variable" && "reference" in object && typeof object.reference === "string" && "version" in object && object.version === 1) {
4045
+ if (isRichTextVariableNode(object)) {
3528
4046
  const value = createVariableReference(object.reference);
3529
4047
  const bindResult = bindVariables({ ...options, value });
3530
4048
  const bindResultAsTextNode = {
@@ -3542,26 +4060,30 @@ function handleRichTextNodeBinding(object, options) {
3542
4060
  }
3543
4061
 
3544
4062
  // src/index.ts
3545
- import { ApiClientError as ApiClientError2 } from "@uniformdev/context/api";
4063
+ import { ApiClientError as ApiClientError5 } from "@uniformdev/context/api";
3546
4064
 
3547
4065
  // src/.version.ts
3548
- var version = "20.48.0";
4066
+ var version = "20.87.0";
3549
4067
 
3550
4068
  // src/WorkflowClient.ts
3551
- import { ApiClient as ApiClient16 } from "@uniformdev/context/api";
4069
+ import { ApiClient as ApiClient18 } from "@uniformdev/context/api";
3552
4070
  var workflowsUrl = "/api/v1/workflows";
3553
- var WorkflowClient = class extends ApiClient16 {
4071
+ var WorkflowClient = class extends ApiClient18 {
3554
4072
  constructor(options) {
3555
4073
  super(options);
3556
4074
  }
3557
- /** Fetches workflows for a project */
3558
- async get(options) {
4075
+ /** Fetches a list of workflows for a project */
4076
+ async list(options) {
3559
4077
  const { projectId } = this.options;
3560
4078
  const fetchUri = this.createUrl(workflowsUrl, { ...options, projectId });
3561
4079
  return await this.apiClient(fetchUri);
3562
4080
  }
4081
+ /** @deprecated Use {@link list} instead. */
4082
+ async get(options) {
4083
+ return this.list(options);
4084
+ }
3563
4085
  /** Updates or creates a workflow definition */
3564
- async upsert(body) {
4086
+ async save(body) {
3565
4087
  const fetchUri = this.createUrl(workflowsUrl);
3566
4088
  await this.apiClient(fetchUri, {
3567
4089
  method: "PUT",
@@ -3569,6 +4091,10 @@ var WorkflowClient = class extends ApiClient16 {
3569
4091
  expectNoContent: true
3570
4092
  });
3571
4093
  }
4094
+ /** @deprecated Use {@link save} instead. */
4095
+ async upsert(body) {
4096
+ return this.save(body);
4097
+ }
3572
4098
  /** Deletes a workflow definition */
3573
4099
  async remove(body) {
3574
4100
  const fetchUri = this.createUrl(workflowsUrl);
@@ -3581,7 +4107,7 @@ var WorkflowClient = class extends ApiClient16 {
3581
4107
  };
3582
4108
 
3583
4109
  // src/index.ts
3584
- var CanvasClientError = ApiClientError2;
4110
+ var CanvasClientError = ApiClientError5;
3585
4111
  export {
3586
4112
  ASSETS_SOURCE_CUSTOM_URL,
3587
4113
  ASSETS_SOURCE_UNIFORM,
@@ -3592,7 +4118,7 @@ export {
3592
4118
  ATTRIBUTE_PARAMETER_TYPE,
3593
4119
  ATTRIBUTE_PARAMETER_VALUE,
3594
4120
  ATTRIBUTE_PLACEHOLDER,
3595
- ApiClientError2 as ApiClientError,
4121
+ ApiClientError5 as ApiClientError,
3596
4122
  BatchEntry,
3597
4123
  BlockFormatError,
3598
4124
  CANVAS_BLOCK_PARAM_TYPE,
@@ -3634,7 +4160,11 @@ export {
3634
4160
  CanvasClientError,
3635
4161
  CategoryClient,
3636
4162
  ChildEnhancerBuilder,
4163
+ ComponentDefinitionClient,
4164
+ CompositionDeliveryClient,
4165
+ CompositionManagementClient,
3637
4166
  ContentClient,
4167
+ ContentTypeClient,
3638
4168
  DataSourceClient,
3639
4169
  DataTypeClient,
3640
4170
  EDGE_CACHE_DISABLED,
@@ -3644,6 +4174,8 @@ export {
3644
4174
  EMPTY_COMPOSITION,
3645
4175
  EnhancerBuilder,
3646
4176
  EntityReleasesClient,
4177
+ EntryDeliveryClient,
4178
+ EntryManagementClient,
3647
4179
  IN_CONTEXT_EDITOR_COMPONENT_END_ROLE,
3648
4180
  IN_CONTEXT_EDITOR_COMPONENT_START_ROLE,
3649
4181
  IN_CONTEXT_EDITOR_CONFIG_CHECK_QUERY_STRING_PARAM,
@@ -3654,19 +4186,23 @@ export {
3654
4186
  IS_RENDERED_BY_UNIFORM_ATTRIBUTE,
3655
4187
  IntegrationPropertyEditorsClient,
3656
4188
  LOCALE_DYNAMIC_INPUT_NAME,
4189
+ LabelClient,
3657
4190
  LocaleClient,
3658
4191
  PLACEHOLDER_ID,
3659
4192
  PreviewClient,
3660
4193
  ProjectClient,
3661
4194
  PromptClient,
4195
+ REFERENCE_DATA_TYPE_ID,
3662
4196
  RelationshipClient,
3663
4197
  ReleaseClient,
3664
4198
  ReleaseContentsClient,
3665
4199
  RouteClient,
3666
4200
  SECRET_QUERY_STRING_PARAM,
4201
+ SELECT_QUERY_PREFIX,
3667
4202
  UncachedCanvasClient,
3668
4203
  UncachedCategoryClient,
3669
4204
  UncachedContentClient,
4205
+ UncachedLabelClient,
3670
4206
  UniqueBatchEntries,
3671
4207
  WorkflowClient,
3672
4208
  autoFixParameterGroups,
@@ -3713,6 +4249,7 @@ export {
3713
4249
  isAllowedReferrer,
3714
4250
  isAssetParamValue,
3715
4251
  isAssetParamValueItem,
4252
+ isAwaitingReadyMessage,
3716
4253
  isComponentActionMessage,
3717
4254
  isComponentPlaceholderId,
3718
4255
  isContextStorageUpdatedMessage,
@@ -3728,6 +4265,7 @@ export {
3728
4265
  isRootEntryReference,
3729
4266
  isSelectComponentMessage,
3730
4267
  isSelectParameterMessage,
4268
+ isSessionPendingMessage,
3731
4269
  isSuggestComponentMessage,
3732
4270
  isSystemComponentDefinition,
3733
4271
  isTriggerCompositionActionMessage,
@@ -3742,10 +4280,13 @@ export {
3742
4280
  localize,
3743
4281
  mapSlotToPersonalizedVariations,
3744
4282
  mapSlotToTestVariations,
4283
+ matchesProjectionPattern,
3745
4284
  mergeAssetConfigWithDefaults,
3746
4285
  nullLimitPolicy,
3747
4286
  parseComponentPlaceholderId,
3748
4287
  parseVariableExpression,
4288
+ projectionToQuery,
4289
+ queryToProjection,
3749
4290
  version,
3750
4291
  walkNodeTree,
3751
4292
  walkPropertyValues