@uniformdev/canvas 20.63.1-alpha.12 → 20.63.1-alpha.17

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.js CHANGED
@@ -8,6 +8,9 @@ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
8
  var __typeError = (msg) => {
9
9
  throw TypeError(msg);
10
10
  };
11
+ var __commonJS = (cb, mod) => function __require() {
12
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
13
+ };
11
14
  var __export = (target, all) => {
12
15
  for (var name in all)
13
16
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -33,6 +36,355 @@ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot
33
36
  var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
34
37
  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);
35
38
 
39
+ // ../../node_modules/.pnpm/yocto-queue@0.1.0/node_modules/yocto-queue/index.js
40
+ var require_yocto_queue = __commonJS({
41
+ "../../node_modules/.pnpm/yocto-queue@0.1.0/node_modules/yocto-queue/index.js"(exports2, module2) {
42
+ "use strict";
43
+ var Node = class {
44
+ /// value;
45
+ /// next;
46
+ constructor(value) {
47
+ this.value = value;
48
+ this.next = void 0;
49
+ }
50
+ };
51
+ var Queue = class {
52
+ // TODO: Use private class fields when targeting Node.js 12.
53
+ // #_head;
54
+ // #_tail;
55
+ // #_size;
56
+ constructor() {
57
+ this.clear();
58
+ }
59
+ enqueue(value) {
60
+ const node = new Node(value);
61
+ if (this._head) {
62
+ this._tail.next = node;
63
+ this._tail = node;
64
+ } else {
65
+ this._head = node;
66
+ this._tail = node;
67
+ }
68
+ this._size++;
69
+ }
70
+ dequeue() {
71
+ const current = this._head;
72
+ if (!current) {
73
+ return;
74
+ }
75
+ this._head = this._head.next;
76
+ this._size--;
77
+ return current.value;
78
+ }
79
+ clear() {
80
+ this._head = void 0;
81
+ this._tail = void 0;
82
+ this._size = 0;
83
+ }
84
+ get size() {
85
+ return this._size;
86
+ }
87
+ *[Symbol.iterator]() {
88
+ let current = this._head;
89
+ while (current) {
90
+ yield current.value;
91
+ current = current.next;
92
+ }
93
+ }
94
+ };
95
+ module2.exports = Queue;
96
+ }
97
+ });
98
+
99
+ // ../../node_modules/.pnpm/p-limit@3.1.0/node_modules/p-limit/index.js
100
+ var require_p_limit = __commonJS({
101
+ "../../node_modules/.pnpm/p-limit@3.1.0/node_modules/p-limit/index.js"(exports2, module2) {
102
+ "use strict";
103
+ var Queue = require_yocto_queue();
104
+ var pLimit2 = (concurrency) => {
105
+ if (!((Number.isInteger(concurrency) || concurrency === Infinity) && concurrency > 0)) {
106
+ throw new TypeError("Expected `concurrency` to be a number from 1 and up");
107
+ }
108
+ const queue = new Queue();
109
+ let activeCount = 0;
110
+ const next = () => {
111
+ activeCount--;
112
+ if (queue.size > 0) {
113
+ queue.dequeue()();
114
+ }
115
+ };
116
+ const run = async (fn, resolve, ...args) => {
117
+ activeCount++;
118
+ const result = (async () => fn(...args))();
119
+ resolve(result);
120
+ try {
121
+ await result;
122
+ } catch (e) {
123
+ }
124
+ next();
125
+ };
126
+ const enqueue = (fn, resolve, ...args) => {
127
+ queue.enqueue(run.bind(null, fn, resolve, ...args));
128
+ (async () => {
129
+ await Promise.resolve();
130
+ if (activeCount < concurrency && queue.size > 0) {
131
+ queue.dequeue()();
132
+ }
133
+ })();
134
+ };
135
+ const generator = (fn, ...args) => new Promise((resolve) => {
136
+ enqueue(fn, resolve, ...args);
137
+ });
138
+ Object.defineProperties(generator, {
139
+ activeCount: {
140
+ get: () => activeCount
141
+ },
142
+ pendingCount: {
143
+ get: () => queue.size
144
+ },
145
+ clearQueue: {
146
+ value: () => {
147
+ queue.clear();
148
+ }
149
+ }
150
+ });
151
+ return generator;
152
+ };
153
+ module2.exports = pLimit2;
154
+ }
155
+ });
156
+
157
+ // ../../node_modules/.pnpm/retry@0.13.1/node_modules/retry/lib/retry_operation.js
158
+ var require_retry_operation = __commonJS({
159
+ "../../node_modules/.pnpm/retry@0.13.1/node_modules/retry/lib/retry_operation.js"(exports2, module2) {
160
+ "use strict";
161
+ function RetryOperation(timeouts, options) {
162
+ if (typeof options === "boolean") {
163
+ options = { forever: options };
164
+ }
165
+ this._originalTimeouts = JSON.parse(JSON.stringify(timeouts));
166
+ this._timeouts = timeouts;
167
+ this._options = options || {};
168
+ this._maxRetryTime = options && options.maxRetryTime || Infinity;
169
+ this._fn = null;
170
+ this._errors = [];
171
+ this._attempts = 1;
172
+ this._operationTimeout = null;
173
+ this._operationTimeoutCb = null;
174
+ this._timeout = null;
175
+ this._operationStart = null;
176
+ this._timer = null;
177
+ if (this._options.forever) {
178
+ this._cachedTimeouts = this._timeouts.slice(0);
179
+ }
180
+ }
181
+ module2.exports = RetryOperation;
182
+ RetryOperation.prototype.reset = function() {
183
+ this._attempts = 1;
184
+ this._timeouts = this._originalTimeouts.slice(0);
185
+ };
186
+ RetryOperation.prototype.stop = function() {
187
+ if (this._timeout) {
188
+ clearTimeout(this._timeout);
189
+ }
190
+ if (this._timer) {
191
+ clearTimeout(this._timer);
192
+ }
193
+ this._timeouts = [];
194
+ this._cachedTimeouts = null;
195
+ };
196
+ RetryOperation.prototype.retry = function(err) {
197
+ if (this._timeout) {
198
+ clearTimeout(this._timeout);
199
+ }
200
+ if (!err) {
201
+ return false;
202
+ }
203
+ var currentTime = (/* @__PURE__ */ new Date()).getTime();
204
+ if (err && currentTime - this._operationStart >= this._maxRetryTime) {
205
+ this._errors.push(err);
206
+ this._errors.unshift(new Error("RetryOperation timeout occurred"));
207
+ return false;
208
+ }
209
+ this._errors.push(err);
210
+ var timeout = this._timeouts.shift();
211
+ if (timeout === void 0) {
212
+ if (this._cachedTimeouts) {
213
+ this._errors.splice(0, this._errors.length - 1);
214
+ timeout = this._cachedTimeouts.slice(-1);
215
+ } else {
216
+ return false;
217
+ }
218
+ }
219
+ var self = this;
220
+ this._timer = setTimeout(function() {
221
+ self._attempts++;
222
+ if (self._operationTimeoutCb) {
223
+ self._timeout = setTimeout(function() {
224
+ self._operationTimeoutCb(self._attempts);
225
+ }, self._operationTimeout);
226
+ if (self._options.unref) {
227
+ self._timeout.unref();
228
+ }
229
+ }
230
+ self._fn(self._attempts);
231
+ }, timeout);
232
+ if (this._options.unref) {
233
+ this._timer.unref();
234
+ }
235
+ return true;
236
+ };
237
+ RetryOperation.prototype.attempt = function(fn, timeoutOps) {
238
+ this._fn = fn;
239
+ if (timeoutOps) {
240
+ if (timeoutOps.timeout) {
241
+ this._operationTimeout = timeoutOps.timeout;
242
+ }
243
+ if (timeoutOps.cb) {
244
+ this._operationTimeoutCb = timeoutOps.cb;
245
+ }
246
+ }
247
+ var self = this;
248
+ if (this._operationTimeoutCb) {
249
+ this._timeout = setTimeout(function() {
250
+ self._operationTimeoutCb();
251
+ }, self._operationTimeout);
252
+ }
253
+ this._operationStart = (/* @__PURE__ */ new Date()).getTime();
254
+ this._fn(this._attempts);
255
+ };
256
+ RetryOperation.prototype.try = function(fn) {
257
+ console.log("Using RetryOperation.try() is deprecated");
258
+ this.attempt(fn);
259
+ };
260
+ RetryOperation.prototype.start = function(fn) {
261
+ console.log("Using RetryOperation.start() is deprecated");
262
+ this.attempt(fn);
263
+ };
264
+ RetryOperation.prototype.start = RetryOperation.prototype.try;
265
+ RetryOperation.prototype.errors = function() {
266
+ return this._errors;
267
+ };
268
+ RetryOperation.prototype.attempts = function() {
269
+ return this._attempts;
270
+ };
271
+ RetryOperation.prototype.mainError = function() {
272
+ if (this._errors.length === 0) {
273
+ return null;
274
+ }
275
+ var counts = {};
276
+ var mainError = null;
277
+ var mainErrorCount = 0;
278
+ for (var i = 0; i < this._errors.length; i++) {
279
+ var error = this._errors[i];
280
+ var message = error.message;
281
+ var count = (counts[message] || 0) + 1;
282
+ counts[message] = count;
283
+ if (count >= mainErrorCount) {
284
+ mainError = error;
285
+ mainErrorCount = count;
286
+ }
287
+ }
288
+ return mainError;
289
+ };
290
+ }
291
+ });
292
+
293
+ // ../../node_modules/.pnpm/retry@0.13.1/node_modules/retry/lib/retry.js
294
+ var require_retry = __commonJS({
295
+ "../../node_modules/.pnpm/retry@0.13.1/node_modules/retry/lib/retry.js"(exports2) {
296
+ "use strict";
297
+ var RetryOperation = require_retry_operation();
298
+ exports2.operation = function(options) {
299
+ var timeouts = exports2.timeouts(options);
300
+ return new RetryOperation(timeouts, {
301
+ forever: options && (options.forever || options.retries === Infinity),
302
+ unref: options && options.unref,
303
+ maxRetryTime: options && options.maxRetryTime
304
+ });
305
+ };
306
+ exports2.timeouts = function(options) {
307
+ if (options instanceof Array) {
308
+ return [].concat(options);
309
+ }
310
+ var opts = {
311
+ retries: 10,
312
+ factor: 2,
313
+ minTimeout: 1 * 1e3,
314
+ maxTimeout: Infinity,
315
+ randomize: false
316
+ };
317
+ for (var key in options) {
318
+ opts[key] = options[key];
319
+ }
320
+ if (opts.minTimeout > opts.maxTimeout) {
321
+ throw new Error("minTimeout is greater than maxTimeout");
322
+ }
323
+ var timeouts = [];
324
+ for (var i = 0; i < opts.retries; i++) {
325
+ timeouts.push(this.createTimeout(i, opts));
326
+ }
327
+ if (options && options.forever && !timeouts.length) {
328
+ timeouts.push(this.createTimeout(i, opts));
329
+ }
330
+ timeouts.sort(function(a, b) {
331
+ return a - b;
332
+ });
333
+ return timeouts;
334
+ };
335
+ exports2.createTimeout = function(attempt, opts) {
336
+ var random = opts.randomize ? Math.random() + 1 : 1;
337
+ var timeout = Math.round(random * Math.max(opts.minTimeout, 1) * Math.pow(opts.factor, attempt));
338
+ timeout = Math.min(timeout, opts.maxTimeout);
339
+ return timeout;
340
+ };
341
+ exports2.wrap = function(obj, options, methods) {
342
+ if (options instanceof Array) {
343
+ methods = options;
344
+ options = null;
345
+ }
346
+ if (!methods) {
347
+ methods = [];
348
+ for (var key in obj) {
349
+ if (typeof obj[key] === "function") {
350
+ methods.push(key);
351
+ }
352
+ }
353
+ }
354
+ for (var i = 0; i < methods.length; i++) {
355
+ var method = methods[i];
356
+ var original = obj[method];
357
+ obj[method] = function retryWrapper(original2) {
358
+ var op = exports2.operation(options);
359
+ var args = Array.prototype.slice.call(arguments, 1);
360
+ var callback = args.pop();
361
+ args.push(function(err) {
362
+ if (op.retry(err)) {
363
+ return;
364
+ }
365
+ if (err) {
366
+ arguments[0] = op.mainError();
367
+ }
368
+ callback.apply(this, arguments);
369
+ });
370
+ op.attempt(function() {
371
+ original2.apply(obj, args);
372
+ });
373
+ }.bind(obj, original);
374
+ obj[method].options = options;
375
+ }
376
+ };
377
+ }
378
+ });
379
+
380
+ // ../../node_modules/.pnpm/retry@0.13.1/node_modules/retry/index.js
381
+ var require_retry2 = __commonJS({
382
+ "../../node_modules/.pnpm/retry@0.13.1/node_modules/retry/index.js"(exports2, module2) {
383
+ "use strict";
384
+ module2.exports = require_retry();
385
+ }
386
+ });
387
+
36
388
  // src/index.ts
37
389
  var src_exports = {};
38
390
  __export(src_exports, {
@@ -113,11 +465,13 @@ __export(src_exports, {
113
465
  PreviewClient: () => PreviewClient,
114
466
  ProjectClient: () => ProjectClient,
115
467
  PromptClient: () => PromptClient,
468
+ REFERENCE_DATA_TYPE_ID: () => REFERENCE_DATA_TYPE_ID,
116
469
  RelationshipClient: () => RelationshipClient,
117
470
  ReleaseClient: () => ReleaseClient,
118
471
  ReleaseContentsClient: () => ReleaseContentsClient,
119
472
  RouteClient: () => RouteClient,
120
473
  SECRET_QUERY_STRING_PARAM: () => SECRET_QUERY_STRING_PARAM,
474
+ SELECT_QUERY_PREFIX: () => SELECT_QUERY_PREFIX,
121
475
  UncachedCanvasClient: () => UncachedCanvasClient,
122
476
  UncachedCategoryClient: () => UncachedCategoryClient,
123
477
  UncachedContentClient: () => UncachedContentClient,
@@ -199,10 +553,13 @@ __export(src_exports, {
199
553
  localize: () => localize,
200
554
  mapSlotToPersonalizedVariations: () => mapSlotToPersonalizedVariations,
201
555
  mapSlotToTestVariations: () => mapSlotToTestVariations,
556
+ matchesProjectionPattern: () => matchesProjectionPattern,
202
557
  mergeAssetConfigWithDefaults: () => mergeAssetConfigWithDefaults,
203
558
  nullLimitPolicy: () => nullLimitPolicy,
204
559
  parseComponentPlaceholderId: () => parseComponentPlaceholderId,
205
560
  parseVariableExpression: () => parseVariableExpression,
561
+ projectionToQuery: () => projectionToQuery,
562
+ queryToProjection: () => queryToProjection,
206
563
  version: () => version,
207
564
  walkNodeTree: () => walkNodeTree,
208
565
  walkPropertyValues: () => walkPropertyValues
@@ -214,15 +571,176 @@ var import_api2 = require("@uniformdev/context/api");
214
571
 
215
572
  // src/enhancement/createLimitPolicy.ts
216
573
  var import_api = require("@uniformdev/context/api");
217
- var import_p_limit = __toESM(require("p-limit"));
218
- var import_p_retry = __toESM(require("p-retry"));
219
- var import_p_throttle = __toESM(require("p-throttle"));
574
+ var import_p_limit = __toESM(require_p_limit());
575
+
576
+ // ../../node_modules/.pnpm/p-retry@5.1.2/node_modules/p-retry/index.js
577
+ var import_retry = __toESM(require_retry2(), 1);
578
+ var networkErrorMsgs = /* @__PURE__ */ new Set([
579
+ "Failed to fetch",
580
+ // Chrome
581
+ "NetworkError when attempting to fetch resource.",
582
+ // Firefox
583
+ "The Internet connection appears to be offline.",
584
+ // Safari
585
+ "Network request failed",
586
+ // `cross-fetch`
587
+ "fetch failed"
588
+ // Undici (Node.js)
589
+ ]);
590
+ var AbortError = class extends Error {
591
+ constructor(message) {
592
+ super();
593
+ if (message instanceof Error) {
594
+ this.originalError = message;
595
+ ({ message } = message);
596
+ } else {
597
+ this.originalError = new Error(message);
598
+ this.originalError.stack = this.stack;
599
+ }
600
+ this.name = "AbortError";
601
+ this.message = message;
602
+ }
603
+ };
604
+ var decorateErrorWithCounts = (error, attemptNumber, options) => {
605
+ const retriesLeft = options.retries - (attemptNumber - 1);
606
+ error.attemptNumber = attemptNumber;
607
+ error.retriesLeft = retriesLeft;
608
+ return error;
609
+ };
610
+ var isNetworkError = (errorMessage) => networkErrorMsgs.has(errorMessage);
611
+ var getDOMException = (errorMessage) => globalThis.DOMException === void 0 ? new Error(errorMessage) : new DOMException(errorMessage);
612
+ async function pRetry(input, options) {
613
+ return new Promise((resolve, reject) => {
614
+ options = {
615
+ onFailedAttempt() {
616
+ },
617
+ retries: 10,
618
+ ...options
619
+ };
620
+ const operation = import_retry.default.operation(options);
621
+ operation.attempt(async (attemptNumber) => {
622
+ try {
623
+ resolve(await input(attemptNumber));
624
+ } catch (error) {
625
+ if (!(error instanceof Error)) {
626
+ reject(new TypeError(`Non-error was thrown: "${error}". You should only throw errors.`));
627
+ return;
628
+ }
629
+ if (error instanceof AbortError) {
630
+ operation.stop();
631
+ reject(error.originalError);
632
+ } else if (error instanceof TypeError && !isNetworkError(error.message)) {
633
+ operation.stop();
634
+ reject(error);
635
+ } else {
636
+ decorateErrorWithCounts(error, attemptNumber, options);
637
+ try {
638
+ await options.onFailedAttempt(error);
639
+ } catch (error2) {
640
+ reject(error2);
641
+ return;
642
+ }
643
+ if (!operation.retry(error)) {
644
+ reject(operation.mainError());
645
+ }
646
+ }
647
+ }
648
+ });
649
+ if (options.signal && !options.signal.aborted) {
650
+ options.signal.addEventListener("abort", () => {
651
+ operation.stop();
652
+ const reason = options.signal.reason === void 0 ? getDOMException("The operation was aborted.") : options.signal.reason;
653
+ reject(reason instanceof Error ? reason : getDOMException(reason));
654
+ }, {
655
+ once: true
656
+ });
657
+ }
658
+ });
659
+ }
660
+
661
+ // ../../node_modules/.pnpm/p-throttle@5.0.0/node_modules/p-throttle/index.js
662
+ var AbortError2 = class extends Error {
663
+ constructor() {
664
+ super("Throttled function aborted");
665
+ this.name = "AbortError";
666
+ }
667
+ };
668
+ function pThrottle({ limit, interval, strict }) {
669
+ if (!Number.isFinite(limit)) {
670
+ throw new TypeError("Expected `limit` to be a finite number");
671
+ }
672
+ if (!Number.isFinite(interval)) {
673
+ throw new TypeError("Expected `interval` to be a finite number");
674
+ }
675
+ const queue = /* @__PURE__ */ new Map();
676
+ let currentTick = 0;
677
+ let activeCount = 0;
678
+ function windowedDelay() {
679
+ const now = Date.now();
680
+ if (now - currentTick > interval) {
681
+ activeCount = 1;
682
+ currentTick = now;
683
+ return 0;
684
+ }
685
+ if (activeCount < limit) {
686
+ activeCount++;
687
+ } else {
688
+ currentTick += interval;
689
+ activeCount = 1;
690
+ }
691
+ return currentTick - now;
692
+ }
693
+ const strictTicks = [];
694
+ function strictDelay() {
695
+ const now = Date.now();
696
+ if (strictTicks.length < limit) {
697
+ strictTicks.push(now);
698
+ return 0;
699
+ }
700
+ const earliestTime = strictTicks.shift() + interval;
701
+ if (now >= earliestTime) {
702
+ strictTicks.push(now);
703
+ return 0;
704
+ }
705
+ strictTicks.push(earliestTime);
706
+ return earliestTime - now;
707
+ }
708
+ const getDelay = strict ? strictDelay : windowedDelay;
709
+ return (function_) => {
710
+ const throttled = function(...args) {
711
+ if (!throttled.isEnabled) {
712
+ return (async () => function_.apply(this, args))();
713
+ }
714
+ let timeout;
715
+ return new Promise((resolve, reject) => {
716
+ const execute = () => {
717
+ resolve(function_.apply(this, args));
718
+ queue.delete(timeout);
719
+ };
720
+ timeout = setTimeout(execute, getDelay());
721
+ queue.set(timeout, reject);
722
+ });
723
+ };
724
+ throttled.abort = () => {
725
+ for (const timeout of queue.keys()) {
726
+ clearTimeout(timeout);
727
+ queue.get(timeout)(new AbortError2());
728
+ }
729
+ queue.clear();
730
+ strictTicks.splice(0, strictTicks.length);
731
+ };
732
+ throttled.isEnabled = true;
733
+ return throttled;
734
+ };
735
+ }
736
+
737
+ // src/enhancement/createLimitPolicy.ts
220
738
  function createLimitPolicy({
221
739
  throttle = { interval: 1e3, limit: 10 },
222
- retry = { retries: 1, factor: 1.66 },
740
+ retry: retry2 = { retries: 1, factor: 1.66 },
223
741
  limit = 10
224
742
  }) {
225
- const throttler = throttle ? (0, import_p_throttle.default)(throttle) : null;
743
+ const throttler = throttle ? pThrottle(throttle) : null;
226
744
  const limiter = limit ? (0, import_p_limit.default)(limit) : null;
227
745
  return function limitPolicy(func) {
228
746
  let currentFunc = async () => await func();
@@ -234,13 +752,13 @@ function createLimitPolicy({
234
752
  const limitFunc = currentFunc;
235
753
  currentFunc = () => limiter(limitFunc);
236
754
  }
237
- if (retry) {
755
+ if (retry2) {
238
756
  const retryFunc = currentFunc;
239
- currentFunc = () => (0, import_p_retry.default)(retryFunc, {
240
- ...retry,
757
+ currentFunc = () => pRetry(retryFunc, {
758
+ ...retry2,
241
759
  onFailedAttempt: async (error) => {
242
- if (retry.onFailedAttempt) {
243
- await retry.onFailedAttempt(error);
760
+ if (retry2.onFailedAttempt) {
761
+ await retry2.onFailedAttempt(error);
244
762
  }
245
763
  if (error instanceof import_api.ApiClientError && typeof error.statusCode === "number" && error.statusCode >= 400 && error.statusCode < 500 && error.statusCode !== 429 && error.statusCode !== 408) {
246
764
  throw error;
@@ -253,6 +771,51 @@ function createLimitPolicy({
253
771
  }
254
772
  var nullLimitPolicy = async (func) => await func();
255
773
 
774
+ // src/projection/types.ts
775
+ var SELECT_QUERY_PREFIX = "select.";
776
+
777
+ // src/projection/projectionToQuery.ts
778
+ function appendCsv(out, key, values) {
779
+ if (values === void 0) {
780
+ return;
781
+ }
782
+ out[key] = values.join(",");
783
+ }
784
+ function projectionToQuery(spec) {
785
+ const out = {};
786
+ if (!spec) {
787
+ return out;
788
+ }
789
+ const { fields, fieldTypes, slots } = spec;
790
+ const p = SELECT_QUERY_PREFIX;
791
+ if (fields) {
792
+ appendCsv(out, `${p}fields[only]`, fields.only);
793
+ appendCsv(out, `${p}fields[except]`, fields.except);
794
+ appendCsv(out, `${p}fields[locales]`, fields.locales);
795
+ }
796
+ if (fieldTypes) {
797
+ appendCsv(out, `${p}fieldTypes[only]`, fieldTypes.only);
798
+ appendCsv(out, `${p}fieldTypes[except]`, fieldTypes.except);
799
+ }
800
+ if (slots) {
801
+ appendCsv(out, `${p}slots[only]`, slots.only);
802
+ appendCsv(out, `${p}slots[except]`, slots.except);
803
+ if (typeof slots.depth === "number") {
804
+ out[`${p}slots[depth]`] = String(slots.depth);
805
+ }
806
+ if (slots.named) {
807
+ const slotNames = Object.keys(slots.named).sort();
808
+ for (const slotName of slotNames) {
809
+ const named = slots.named[slotName];
810
+ if (named && typeof named.depth === "number") {
811
+ out[`${p}slots.${slotName}[depth]`] = String(named.depth);
812
+ }
813
+ }
814
+ }
815
+ }
816
+ return out;
817
+ }
818
+
256
819
  // src/CanvasClient.ts
257
820
  var CANVAS_URL = "/api/v1/canvas";
258
821
  var CanvasClient = class extends import_api2.ApiClient {
@@ -268,17 +831,24 @@ var CanvasClient = class extends import_api2.ApiClient {
268
831
  /** Fetches lists of Canvas compositions, optionally by type */
269
832
  async getCompositionList(params = {}) {
270
833
  const { projectId } = this.options;
271
- const { resolveData, filters, ...originParams } = params;
834
+ const { resolveData, filters, select, ...originParams } = params;
272
835
  const rewrittenFilters = (0, import_api2.rewriteFiltersForApi)(filters);
836
+ const rewrittenSelect = projectionToQuery(select);
273
837
  if (!resolveData) {
274
- const fetchUri = this.createUrl(CANVAS_URL, { ...originParams, projectId, ...rewrittenFilters });
838
+ const fetchUri = this.createUrl(CANVAS_URL, {
839
+ ...originParams,
840
+ projectId,
841
+ ...rewrittenFilters,
842
+ ...rewrittenSelect
843
+ });
275
844
  return this.apiClient(fetchUri);
276
845
  }
277
846
  const edgeParams = {
278
847
  ...originParams,
279
848
  projectId,
280
849
  diagnostics: typeof params.diagnostics === "boolean" ? params.diagnostics : params.diagnostics === "no-data" ? "no-data" : void 0,
281
- ...rewrittenFilters
850
+ ...rewrittenFilters,
851
+ ...rewrittenSelect
282
852
  };
283
853
  const edgeUrl = this.createUrl("/api/v1/compositions", edgeParams, this.edgeApiHost);
284
854
  return this.apiClient(edgeUrl, this.edgeApiRequestInit);
@@ -438,15 +1008,21 @@ var _ContentClient = class _ContentClient extends import_api4.ApiClient {
438
1008
  }
439
1009
  getEntries(options) {
440
1010
  const { projectId } = this.options;
441
- const { skipDataResolution, filters, ...params } = options;
1011
+ const { skipDataResolution, filters, select, ...params } = options;
442
1012
  const rewrittenFilters = (0, import_api4.rewriteFiltersForApi)(filters);
1013
+ const rewrittenSelect = projectionToQuery(select);
443
1014
  if (skipDataResolution) {
444
- const url = this.createUrl(__privateGet(_ContentClient, _entriesUrl), { ...params, ...rewrittenFilters, projectId });
1015
+ const url = this.createUrl(__privateGet(_ContentClient, _entriesUrl), {
1016
+ ...params,
1017
+ ...rewrittenFilters,
1018
+ ...rewrittenSelect,
1019
+ projectId
1020
+ });
445
1021
  return this.apiClient(url);
446
1022
  }
447
1023
  const edgeUrl = this.createUrl(
448
1024
  __privateGet(_ContentClient, _entriesUrl),
449
- { ...this.getEdgeOptions(params), ...rewrittenFilters },
1025
+ { ...this.getEdgeOptions(params), ...rewrittenFilters, ...rewrittenSelect },
450
1026
  this.edgeApiHost
451
1027
  );
452
1028
  return this.apiClient(
@@ -775,6 +1351,7 @@ var EDGE_CACHE_DISABLED = -1;
775
1351
  var ASSET_PARAMETER_TYPE = "asset";
776
1352
  var ASSETS_SOURCE_UNIFORM = "uniform-assets";
777
1353
  var ASSETS_SOURCE_CUSTOM_URL = "custom-url";
1354
+ var REFERENCE_DATA_TYPE_ID = "uniformContentInternalReference";
778
1355
 
779
1356
  // src/utils/guards.ts
780
1357
  function isRootEntryReference(root) {
@@ -2074,8 +2651,7 @@ function extractLocales({ component }) {
2074
2651
  return variations;
2075
2652
  }
2076
2653
  function localize(options) {
2077
- const nodes = options.nodes;
2078
- const locale = options.locale;
2654
+ const { nodes, locale, keepLocalesFor } = options;
2079
2655
  if (!locale) {
2080
2656
  return;
2081
2657
  }
@@ -2083,7 +2659,7 @@ function localize(options) {
2083
2659
  walkNodeTree(nodes, (context) => {
2084
2660
  const { type, node, actions } = context;
2085
2661
  if (type !== "component") {
2086
- localizeProperties(node, locale, vizControlLocaleRule);
2662
+ localizeProperties(node, locale, vizControlLocaleRule, keepLocalesFor);
2087
2663
  return;
2088
2664
  }
2089
2665
  const result = evaluateWalkTreeNodeVisibility({
@@ -2104,7 +2680,7 @@ function localize(options) {
2104
2680
  if (replaceComponent == null ? void 0 : replaceComponent.length) {
2105
2681
  replaceComponent.forEach((component) => {
2106
2682
  removeLocaleProperty(component);
2107
- localizeProperties(component, locale, vizControlLocaleRule);
2683
+ localizeProperties(component, locale, vizControlLocaleRule, keepLocalesFor);
2108
2684
  });
2109
2685
  const [first, ...rest] = replaceComponent;
2110
2686
  actions.replace(first);
@@ -2115,7 +2691,7 @@ function localize(options) {
2115
2691
  actions.remove();
2116
2692
  }
2117
2693
  } else {
2118
- localizeProperties(node, locale, vizControlLocaleRule);
2694
+ localizeProperties(node, locale, vizControlLocaleRule, keepLocalesFor);
2119
2695
  }
2120
2696
  });
2121
2697
  }
@@ -2134,7 +2710,7 @@ function removeLocaleProperty(component) {
2134
2710
  }
2135
2711
  }
2136
2712
  }
2137
- function localizeProperties(node, locale, rules) {
2713
+ function localizeProperties(node, locale, rules, keepLocalesFor) {
2138
2714
  const properties = getPropertiesValue(node);
2139
2715
  if (!properties) {
2140
2716
  return void 0;
@@ -2153,10 +2729,16 @@ function localizeProperties(node, locale, rules) {
2153
2729
  if (currentLocaleConditionalValues !== void 0) {
2154
2730
  propertyValue.conditions = currentLocaleConditionalValues;
2155
2731
  }
2156
- delete propertyValue.locales;
2157
- delete propertyValue.localesConditions;
2732
+ const preserveLocales = (keepLocalesFor == null ? void 0 : keepLocalesFor(propertyId)) === true;
2733
+ if (!preserveLocales) {
2734
+ delete propertyValue.locales;
2735
+ delete propertyValue.localesConditions;
2736
+ }
2158
2737
  if (propertyValue.value === void 0 && propertyValue.conditions === void 0) {
2159
- delete properties[propertyId];
2738
+ const hasLocales = preserveLocales && (propertyValue.locales || propertyValue.localesConditions);
2739
+ if (!hasLocales) {
2740
+ delete properties[propertyId];
2741
+ }
2160
2742
  }
2161
2743
  });
2162
2744
  evaluateWalkTreePropertyCriteria({
@@ -2835,6 +3417,173 @@ __privateAdd(_ProjectClient, _url2, "/api/v1/project");
2835
3417
  __privateAdd(_ProjectClient, _projectsUrl, "/api/v1/projects");
2836
3418
  var ProjectClient = _ProjectClient;
2837
3419
 
3420
+ // src/projection/matchesProjectionPattern.ts
3421
+ var DISALLOWED_PATTERN_CHARS = /[,&=?#[\]\s]/;
3422
+ var REGEX_METACHAR = /[\\^$.|?*+()[\]{}]/g;
3423
+ function isValidProjectionPattern(pattern) {
3424
+ if (typeof pattern !== "string" || pattern.length === 0) {
3425
+ return false;
3426
+ }
3427
+ if (DISALLOWED_PATTERN_CHARS.test(pattern)) {
3428
+ return false;
3429
+ }
3430
+ return true;
3431
+ }
3432
+ function compilePattern(pattern) {
3433
+ let regexSource = "^";
3434
+ for (const ch of pattern) {
3435
+ if (ch === "*") {
3436
+ regexSource += ".*";
3437
+ } else {
3438
+ regexSource += ch.replace(REGEX_METACHAR, "\\$&");
3439
+ }
3440
+ }
3441
+ regexSource += "$";
3442
+ return new RegExp(regexSource);
3443
+ }
3444
+ var PATTERN_CACHE_MAX = 1024;
3445
+ var patternRegexCache = /* @__PURE__ */ new Map();
3446
+ function matchesProjectionPattern(pattern, value) {
3447
+ let re = patternRegexCache.get(pattern);
3448
+ if (re === void 0) {
3449
+ if (!isValidProjectionPattern(pattern)) {
3450
+ throw new Error(`Invalid projection pattern: ${JSON.stringify(pattern)}`);
3451
+ }
3452
+ re = compilePattern(pattern);
3453
+ if (patternRegexCache.size >= PATTERN_CACHE_MAX) {
3454
+ const oldest = patternRegexCache.keys().next().value;
3455
+ if (oldest !== void 0) patternRegexCache.delete(oldest);
3456
+ }
3457
+ patternRegexCache.set(pattern, re);
3458
+ }
3459
+ return re.test(value);
3460
+ }
3461
+
3462
+ // src/projection/queryToProjection.ts
3463
+ var TOP_LEVEL_OPERATOR_KEY = /^(fields|fieldTypes|slots)\[([A-Za-z]+)\]$/;
3464
+ var SLOTS_NAMED_KEY = /^slots\.([A-Za-z0-9_-]+)\[([A-Za-z]+)\]$/;
3465
+ function toStringValue2(value) {
3466
+ if (Array.isArray(value)) {
3467
+ return value.join(",");
3468
+ }
3469
+ return value;
3470
+ }
3471
+ function parseCsv(value) {
3472
+ const str = toStringValue2(value);
3473
+ if (!str) {
3474
+ return [];
3475
+ }
3476
+ return str.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
3477
+ }
3478
+ function parseDepth(value, key) {
3479
+ const str = toStringValue2(value);
3480
+ if (str === void 0 || str === "") {
3481
+ throw new Error(`Invalid select projection: '${key}' requires a non-negative integer value`);
3482
+ }
3483
+ if (!/^\d+$/.test(str)) {
3484
+ throw new Error(
3485
+ `Invalid select projection: '${key}' must be a non-negative integer (got ${JSON.stringify(str)})`
3486
+ );
3487
+ }
3488
+ return Number(str);
3489
+ }
3490
+ function extractSelectKeys(source) {
3491
+ if (source instanceof URLSearchParams) {
3492
+ let out2;
3493
+ for (const [key, value] of source.entries()) {
3494
+ if (!key.startsWith(SELECT_QUERY_PREFIX)) continue;
3495
+ out2 != null ? out2 : out2 = {};
3496
+ out2[key] = out2[key] === void 0 ? value : `${out2[key]},${value}`;
3497
+ }
3498
+ return out2;
3499
+ }
3500
+ let out;
3501
+ for (const key in source) {
3502
+ if (!key.startsWith(SELECT_QUERY_PREFIX)) continue;
3503
+ out != null ? out : out = {};
3504
+ out[key] = source[key];
3505
+ }
3506
+ return out;
3507
+ }
3508
+ function queryToProjection(source) {
3509
+ var _a, _b, _c, _d, _e;
3510
+ if (!source) {
3511
+ return void 0;
3512
+ }
3513
+ const query = extractSelectKeys(source);
3514
+ if (!query) {
3515
+ return void 0;
3516
+ }
3517
+ const spec = {};
3518
+ for (const [rawKey, value] of Object.entries(query)) {
3519
+ const key = rawKey.slice(SELECT_QUERY_PREFIX.length);
3520
+ const namedMatch = SLOTS_NAMED_KEY.exec(key);
3521
+ if (namedMatch) {
3522
+ const [, slotName, operator2] = namedMatch;
3523
+ if (operator2 !== "depth") {
3524
+ throw new Error(
3525
+ `Invalid select projection: unsupported operator '${operator2}' for slots.${slotName}`
3526
+ );
3527
+ }
3528
+ const slots = (_a = spec.slots) != null ? _a : spec.slots = {};
3529
+ const named = (_b = slots.named) != null ? _b : slots.named = {};
3530
+ named[slotName] = { ...named[slotName], depth: parseDepth(value, rawKey) };
3531
+ continue;
3532
+ }
3533
+ const topMatch = TOP_LEVEL_OPERATOR_KEY.exec(key);
3534
+ if (!topMatch) {
3535
+ throw new Error(`Invalid select projection key: ${JSON.stringify(rawKey)}`);
3536
+ }
3537
+ const [, bucket, operator] = topMatch;
3538
+ if (bucket === "fields") {
3539
+ const fields = (_c = spec.fields) != null ? _c : spec.fields = {};
3540
+ switch (operator) {
3541
+ case "only":
3542
+ fields.only = parseCsv(value);
3543
+ break;
3544
+ case "except":
3545
+ fields.except = parseCsv(value);
3546
+ break;
3547
+ case "locales":
3548
+ fields.locales = parseCsv(value);
3549
+ break;
3550
+ default:
3551
+ throw new Error(`Invalid select projection: unsupported operator 'fields[${operator}]'`);
3552
+ }
3553
+ } else if (bucket === "fieldTypes") {
3554
+ const fieldTypes = (_d = spec.fieldTypes) != null ? _d : spec.fieldTypes = {};
3555
+ switch (operator) {
3556
+ case "only":
3557
+ fieldTypes.only = parseCsv(value);
3558
+ break;
3559
+ case "except":
3560
+ fieldTypes.except = parseCsv(value);
3561
+ break;
3562
+ default:
3563
+ throw new Error(`Invalid select projection: unsupported operator 'fieldTypes[${operator}]'`);
3564
+ }
3565
+ } else if (bucket === "slots") {
3566
+ const slots = (_e = spec.slots) != null ? _e : spec.slots = {};
3567
+ switch (operator) {
3568
+ case "only":
3569
+ slots.only = parseCsv(value);
3570
+ break;
3571
+ case "except":
3572
+ slots.except = parseCsv(value);
3573
+ break;
3574
+ case "depth":
3575
+ slots.depth = parseDepth(value, rawKey);
3576
+ break;
3577
+ default:
3578
+ throw new Error(`Invalid select projection: unsupported operator 'slots[${operator}]'`);
3579
+ }
3580
+ } else {
3581
+ throw new Error(`Invalid select projection key: ${JSON.stringify(rawKey)}`);
3582
+ }
3583
+ }
3584
+ return spec;
3585
+ }
3586
+
2838
3587
  // src/PromptClient.ts
2839
3588
  var import_api13 = require("@uniformdev/context/api");
2840
3589
  var PromptsUrl = "/api/v1/prompts";
@@ -2963,7 +3712,9 @@ var RouteClient = class extends import_api17.ApiClient {
2963
3712
  /** Fetches lists of Canvas compositions, optionally by type */
2964
3713
  async getRoute(options) {
2965
3714
  const { projectId } = this.options;
2966
- const fetchUri = this.createUrl(ROUTE_URL, { ...options, projectId }, this.edgeApiHost);
3715
+ const { select, ...rest } = options != null ? options : {};
3716
+ const rewrittenSelect = projectionToQuery(select);
3717
+ const fetchUri = this.createUrl(ROUTE_URL, { ...rest, projectId, ...rewrittenSelect }, this.edgeApiHost);
2967
3718
  return await this.apiClient(
2968
3719
  fetchUri,
2969
3720
  this.options.disableSWR ? { headers: { "x-disable-swr": "true" } } : void 0
@@ -3326,7 +4077,7 @@ function handleRichTextNodeBinding(object, options) {
3326
4077
  var import_api19 = require("@uniformdev/context/api");
3327
4078
 
3328
4079
  // src/.version.ts
3329
- var version = "20.63.0";
4080
+ var version = "20.66.0";
3330
4081
 
3331
4082
  // src/WorkflowClient.ts
3332
4083
  var import_api18 = require("@uniformdev/context/api");
@@ -3442,11 +4193,13 @@ var CanvasClientError = import_api19.ApiClientError;
3442
4193
  PreviewClient,
3443
4194
  ProjectClient,
3444
4195
  PromptClient,
4196
+ REFERENCE_DATA_TYPE_ID,
3445
4197
  RelationshipClient,
3446
4198
  ReleaseClient,
3447
4199
  ReleaseContentsClient,
3448
4200
  RouteClient,
3449
4201
  SECRET_QUERY_STRING_PARAM,
4202
+ SELECT_QUERY_PREFIX,
3450
4203
  UncachedCanvasClient,
3451
4204
  UncachedCategoryClient,
3452
4205
  UncachedContentClient,
@@ -3528,10 +4281,13 @@ var CanvasClientError = import_api19.ApiClientError;
3528
4281
  localize,
3529
4282
  mapSlotToPersonalizedVariations,
3530
4283
  mapSlotToTestVariations,
4284
+ matchesProjectionPattern,
3531
4285
  mergeAssetConfigWithDefaults,
3532
4286
  nullLimitPolicy,
3533
4287
  parseComponentPlaceholderId,
3534
4288
  parseVariableExpression,
4289
+ projectionToQuery,
4290
+ queryToProjection,
3535
4291
  version,
3536
4292
  walkNodeTree,
3537
4293
  walkPropertyValues