@dyrected/sdk 2.5.60 → 2.5.62
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.cjs +146 -36
- package/dist/index.d.cts +94 -5
- package/dist/index.d.ts +94 -5
- package/dist/index.js +143 -35
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -22,7 +22,9 @@ var index_exports = {};
|
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
DyrectedClient: () => DyrectedClient,
|
|
24
24
|
DyrectedError: () => DyrectedError,
|
|
25
|
-
|
|
25
|
+
PREVIEW_TOKEN_PARAM: () => PREVIEW_TOKEN_PARAM,
|
|
26
|
+
createClient: () => createClient,
|
|
27
|
+
getPreviewToken: () => getPreviewToken
|
|
26
28
|
});
|
|
27
29
|
module.exports = __toCommonJS(index_exports);
|
|
28
30
|
|
|
@@ -163,6 +165,13 @@ var DyrectedClient = class {
|
|
|
163
165
|
getBaseUrl() {
|
|
164
166
|
return this.baseUrl;
|
|
165
167
|
}
|
|
168
|
+
/**
|
|
169
|
+
* Inject the client's configured `defaultDepth` when a read did not specify
|
|
170
|
+
* its own `depth`. A per-call `depth` (including `0`) always wins.
|
|
171
|
+
*/
|
|
172
|
+
applyDefaultDepth(args) {
|
|
173
|
+
return args.depth === void 0 ? { ...args, depth: this.defaultDepth } : args;
|
|
174
|
+
}
|
|
166
175
|
async getSchemas() {
|
|
167
176
|
return this.request("/api/schemas");
|
|
168
177
|
}
|
|
@@ -177,27 +186,48 @@ var DyrectedClient = class {
|
|
|
177
186
|
}
|
|
178
187
|
async getPreference(key, options) {
|
|
179
188
|
const scopeParam = options?.scope ? `?scope=${options.scope}` : "";
|
|
180
|
-
return this.request(
|
|
189
|
+
return this.request(
|
|
190
|
+
`/api/preferences/${encodeURIComponent(key)}${scopeParam}`
|
|
191
|
+
);
|
|
181
192
|
}
|
|
182
193
|
async setPreference(key, value, options) {
|
|
183
194
|
const scopeParam = options?.scope ? `?scope=${options.scope}` : "";
|
|
184
|
-
return this.request(
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
195
|
+
return this.request(
|
|
196
|
+
`/api/preferences/${encodeURIComponent(key)}${scopeParam}`,
|
|
197
|
+
{
|
|
198
|
+
method: "PUT",
|
|
199
|
+
body: JSON.stringify({ value })
|
|
200
|
+
}
|
|
201
|
+
);
|
|
188
202
|
}
|
|
189
203
|
async deletePreference(key, options) {
|
|
190
204
|
const scopeParam = options?.scope ? `?scope=${options.scope}` : "";
|
|
191
|
-
return this.request(
|
|
192
|
-
|
|
193
|
-
|
|
205
|
+
return this.request(
|
|
206
|
+
`/api/preferences/${encodeURIComponent(key)}${scopeParam}`,
|
|
207
|
+
{
|
|
208
|
+
method: "DELETE"
|
|
209
|
+
}
|
|
210
|
+
);
|
|
194
211
|
}
|
|
195
212
|
/**
|
|
196
213
|
* Fetch draft data for a specific preview token.
|
|
197
214
|
* Used in "token" preview mode.
|
|
198
215
|
*/
|
|
199
216
|
async getPreviewData(token) {
|
|
200
|
-
return this.request(`/api/preview-data?token=${token}`);
|
|
217
|
+
return this.request(`/api/preview-data?token=${encodeURIComponent(token)}`);
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Mint a short-lived preview token that carries the current (unsaved) draft
|
|
221
|
+
* data. Used by the Admin in `previewMode: "token"` to hand draft content to
|
|
222
|
+
* a server-rendered frontend that cannot receive it over `postMessage`.
|
|
223
|
+
*
|
|
224
|
+
* Requires an authenticated request (the Admin is logged in).
|
|
225
|
+
*/
|
|
226
|
+
async createPreviewToken(input) {
|
|
227
|
+
return this.request(`/api/preview-token`, {
|
|
228
|
+
method: "POST",
|
|
229
|
+
body: JSON.stringify(input)
|
|
230
|
+
});
|
|
201
231
|
}
|
|
202
232
|
async find(collection, args = {}) {
|
|
203
233
|
const { initialData, ...queryArgs } = args;
|
|
@@ -205,13 +235,22 @@ var DyrectedClient = class {
|
|
|
205
235
|
if (queryArgs.where && typeof queryArgs.where === "object") {
|
|
206
236
|
normalizedArgs.where = JSON.stringify(queryArgs.where);
|
|
207
237
|
}
|
|
208
|
-
const query = stringifyQuery(normalizedArgs, {
|
|
209
|
-
|
|
238
|
+
const query = stringifyQuery(this.applyDefaultDepth(normalizedArgs), {
|
|
239
|
+
addQueryPrefix: true
|
|
240
|
+
});
|
|
241
|
+
const res = await this.request(
|
|
242
|
+
`/api/collections/${collection}${query}`
|
|
243
|
+
);
|
|
210
244
|
if (res.docs.length === 0 && initialData && initialData.length > 0) {
|
|
211
245
|
this.request(`/api/collections/${collection}/seed`, {
|
|
212
246
|
method: "POST",
|
|
213
247
|
body: JSON.stringify({ data: initialData })
|
|
214
|
-
}).catch(
|
|
248
|
+
}).catch(
|
|
249
|
+
(err) => console.error(
|
|
250
|
+
`[dyrected/sdk] Failed to auto-seed collection "${collection}":`,
|
|
251
|
+
err
|
|
252
|
+
)
|
|
253
|
+
);
|
|
215
254
|
return {
|
|
216
255
|
docs: initialData,
|
|
217
256
|
total: initialData.length,
|
|
@@ -235,11 +274,12 @@ var DyrectedClient = class {
|
|
|
235
274
|
(collectionName, queryArgs) => this.find(collectionName, queryArgs)
|
|
236
275
|
);
|
|
237
276
|
if (args) {
|
|
238
|
-
if (args.where && typeof args.where === "object")
|
|
277
|
+
if (args.where && typeof args.where === "object")
|
|
278
|
+
qb.where(args.where);
|
|
239
279
|
if (args.sort) qb.sort(args.sort);
|
|
240
280
|
if (args.limit) qb.limit(args.limit);
|
|
241
281
|
if (args.page) qb.page(args.page);
|
|
242
|
-
if (args.depth) qb.depth(args.depth);
|
|
282
|
+
if (args.depth !== void 0) qb.depth(args.depth);
|
|
243
283
|
if (args.initialData) qb.seed(args.initialData);
|
|
244
284
|
}
|
|
245
285
|
return qb;
|
|
@@ -332,7 +372,12 @@ var DyrectedClient = class {
|
|
|
332
372
|
* comment: 'Please add more detail to section 2.',
|
|
333
373
|
* })
|
|
334
374
|
*/
|
|
335
|
-
transition: (id, transitionName, opts) => this.transition(
|
|
375
|
+
transition: (id, transitionName, opts) => this.transition(
|
|
376
|
+
slug,
|
|
377
|
+
id,
|
|
378
|
+
transitionName,
|
|
379
|
+
opts
|
|
380
|
+
),
|
|
336
381
|
/**
|
|
337
382
|
* Fetch the workflow history for a single document — every transition that
|
|
338
383
|
* has ever been performed, newest first.
|
|
@@ -362,7 +407,9 @@ var DyrectedClient = class {
|
|
|
362
407
|
}
|
|
363
408
|
async findOne(collection, id, args = {}) {
|
|
364
409
|
const { initialData, ...queryArgs } = args;
|
|
365
|
-
const query = stringifyQuery(queryArgs, {
|
|
410
|
+
const query = stringifyQuery(this.applyDefaultDepth(queryArgs), {
|
|
411
|
+
addQueryPrefix: true
|
|
412
|
+
});
|
|
366
413
|
try {
|
|
367
414
|
return await this.request(`/api/collections/${collection}/${id}${query}`);
|
|
368
415
|
} catch (err) {
|
|
@@ -371,7 +418,10 @@ var DyrectedClient = class {
|
|
|
371
418
|
method: "POST",
|
|
372
419
|
body: JSON.stringify({ data: [{ id, ...initialData }] })
|
|
373
420
|
}).catch(
|
|
374
|
-
(err2) => console.error(
|
|
421
|
+
(err2) => console.error(
|
|
422
|
+
`[dyrected/sdk] Failed to auto-seed document "${id}" in collection "${collection}":`,
|
|
423
|
+
err2
|
|
424
|
+
)
|
|
375
425
|
);
|
|
376
426
|
return initialData;
|
|
377
427
|
}
|
|
@@ -410,10 +460,13 @@ var DyrectedClient = class {
|
|
|
410
460
|
* const updated = await client.transition('posts', postId, 'publish')
|
|
411
461
|
*/
|
|
412
462
|
async transition(collection, id, transitionName, opts = {}) {
|
|
413
|
-
return this.request(
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
463
|
+
return this.request(
|
|
464
|
+
`/api/collections/${collection}/${id}/transitions/${encodeURIComponent(transitionName)}`,
|
|
465
|
+
{
|
|
466
|
+
method: "POST",
|
|
467
|
+
body: JSON.stringify(opts)
|
|
468
|
+
}
|
|
469
|
+
);
|
|
417
470
|
}
|
|
418
471
|
/**
|
|
419
472
|
* Fetch the workflow history for a document.
|
|
@@ -426,7 +479,9 @@ var DyrectedClient = class {
|
|
|
426
479
|
*/
|
|
427
480
|
async workflowHistory(collection, id, args = {}) {
|
|
428
481
|
const query = args.limit ? `?limit=${args.limit}` : "";
|
|
429
|
-
return this.request(
|
|
482
|
+
return this.request(
|
|
483
|
+
`/api/collections/${collection}/${id}/workflow-history${query}`
|
|
484
|
+
);
|
|
430
485
|
}
|
|
431
486
|
/**
|
|
432
487
|
* Fetch audit entries across every audited collection the current caller can read.
|
|
@@ -434,7 +489,9 @@ var DyrectedClient = class {
|
|
|
434
489
|
* Sends `GET /api/audit`.
|
|
435
490
|
*/
|
|
436
491
|
async audit(args = {}) {
|
|
437
|
-
const query = stringifyQuery(normalizeQueryArgs(args), {
|
|
492
|
+
const query = stringifyQuery(normalizeQueryArgs(args), {
|
|
493
|
+
addQueryPrefix: true
|
|
494
|
+
});
|
|
438
495
|
return this.request(`/api/audit${query}`);
|
|
439
496
|
}
|
|
440
497
|
/**
|
|
@@ -443,7 +500,9 @@ var DyrectedClient = class {
|
|
|
443
500
|
* Sends `GET /api/collections/:collection/__audit`.
|
|
444
501
|
*/
|
|
445
502
|
async collectionAudit(collection, args = {}) {
|
|
446
|
-
const query = stringifyQuery(normalizeQueryArgs(args), {
|
|
503
|
+
const query = stringifyQuery(normalizeQueryArgs(args), {
|
|
504
|
+
addQueryPrefix: true
|
|
505
|
+
});
|
|
447
506
|
return this.request(`/api/collections/${collection}/__audit${query}`);
|
|
448
507
|
}
|
|
449
508
|
async deleteMany(collection, ids) {
|
|
@@ -454,7 +513,9 @@ var DyrectedClient = class {
|
|
|
454
513
|
}
|
|
455
514
|
async getGlobal(slug, args = {}) {
|
|
456
515
|
const { initialData, ...queryArgs } = args;
|
|
457
|
-
const query = stringifyQuery(queryArgs, {
|
|
516
|
+
const query = stringifyQuery(this.applyDefaultDepth(queryArgs), {
|
|
517
|
+
addQueryPrefix: true
|
|
518
|
+
});
|
|
458
519
|
try {
|
|
459
520
|
const res = await this.request(`/api/globals/${slug}${query}`);
|
|
460
521
|
if ((!res || isFunctionallyEmpty(res)) && !isFunctionallyEmpty(initialData)) {
|
|
@@ -462,7 +523,12 @@ var DyrectedClient = class {
|
|
|
462
523
|
this.request(`/api/globals/${slug}/seed`, {
|
|
463
524
|
method: "POST",
|
|
464
525
|
body: JSON.stringify({ data: initialData })
|
|
465
|
-
}).catch(
|
|
526
|
+
}).catch(
|
|
527
|
+
(err) => console.error(
|
|
528
|
+
`[dyrected/sdk] Failed to auto-seed global "${slug}":`,
|
|
529
|
+
err
|
|
530
|
+
)
|
|
531
|
+
);
|
|
466
532
|
return initialData;
|
|
467
533
|
}
|
|
468
534
|
return res;
|
|
@@ -471,7 +537,12 @@ var DyrectedClient = class {
|
|
|
471
537
|
this.request(`/api/globals/${slug}/seed`, {
|
|
472
538
|
method: "POST",
|
|
473
539
|
body: JSON.stringify({ data: initialData })
|
|
474
|
-
}).catch(
|
|
540
|
+
}).catch(
|
|
541
|
+
(err2) => console.error(
|
|
542
|
+
`[dyrected/sdk] Failed to auto-seed global "${slug}":`,
|
|
543
|
+
err2
|
|
544
|
+
)
|
|
545
|
+
);
|
|
475
546
|
return initialData;
|
|
476
547
|
}
|
|
477
548
|
throw err;
|
|
@@ -484,8 +555,13 @@ var DyrectedClient = class {
|
|
|
484
555
|
});
|
|
485
556
|
}
|
|
486
557
|
async listMedia(args = {}, collection = "media") {
|
|
487
|
-
const query = stringifyQuery(
|
|
488
|
-
|
|
558
|
+
const query = stringifyQuery(
|
|
559
|
+
this.applyDefaultDepth(normalizeQueryArgs(args)),
|
|
560
|
+
{ addQueryPrefix: true }
|
|
561
|
+
);
|
|
562
|
+
return this.request(
|
|
563
|
+
`/api/collections/${collection}${query}`
|
|
564
|
+
);
|
|
489
565
|
}
|
|
490
566
|
/** @deprecated Use client.collection('media').upload(file, data) instead */
|
|
491
567
|
async uploadMedia(file, collection = "media") {
|
|
@@ -530,7 +606,9 @@ var DyrectedClient = class {
|
|
|
530
606
|
reject(new DyrectedError("Upload aborted", 0));
|
|
531
607
|
return;
|
|
532
608
|
}
|
|
533
|
-
options.signal.addEventListener("abort", () => xhr.abort(), {
|
|
609
|
+
options.signal.addEventListener("abort", () => xhr.abort(), {
|
|
610
|
+
once: true
|
|
611
|
+
});
|
|
534
612
|
}
|
|
535
613
|
xhr.upload.onprogress = (event) => {
|
|
536
614
|
if (event.lengthComputable) {
|
|
@@ -558,7 +636,13 @@ var DyrectedClient = class {
|
|
|
558
636
|
})
|
|
559
637
|
);
|
|
560
638
|
}
|
|
561
|
-
reject(
|
|
639
|
+
reject(
|
|
640
|
+
new DyrectedError(
|
|
641
|
+
body.message || `Request failed with status ${xhr.status}`,
|
|
642
|
+
xhr.status,
|
|
643
|
+
body.code
|
|
644
|
+
)
|
|
645
|
+
);
|
|
562
646
|
};
|
|
563
647
|
xhr.onerror = () => reject(new DyrectedError("Network error during upload", 0));
|
|
564
648
|
xhr.onabort = () => reject(new DyrectedError("Upload aborted", 0));
|
|
@@ -577,7 +661,9 @@ var DyrectedClient = class {
|
|
|
577
661
|
});
|
|
578
662
|
if (res && typeof res.ok === "boolean") {
|
|
579
663
|
if (!res.ok) {
|
|
580
|
-
const body = await res.json().catch(() => ({
|
|
664
|
+
const body = await res.json().catch(() => ({
|
|
665
|
+
message: "Unknown error"
|
|
666
|
+
}));
|
|
581
667
|
if (res.status === 429 && typeof window !== "undefined") {
|
|
582
668
|
window.dispatchEvent(
|
|
583
669
|
new CustomEvent("dyrected:rate-limit", {
|
|
@@ -586,7 +672,11 @@ var DyrectedClient = class {
|
|
|
586
672
|
);
|
|
587
673
|
}
|
|
588
674
|
console.log("[DyrectedError]", body, res.status);
|
|
589
|
-
throw new DyrectedError(
|
|
675
|
+
throw new DyrectedError(
|
|
676
|
+
body.message || `Request failed with status ${res.status}`,
|
|
677
|
+
res.status,
|
|
678
|
+
body.code
|
|
679
|
+
);
|
|
590
680
|
}
|
|
591
681
|
return res.json();
|
|
592
682
|
}
|
|
@@ -596,6 +686,22 @@ var DyrectedClient = class {
|
|
|
596
686
|
function createClient(config) {
|
|
597
687
|
return new DyrectedClient(config);
|
|
598
688
|
}
|
|
689
|
+
var PREVIEW_TOKEN_PARAM = "dyPreview";
|
|
690
|
+
function getPreviewToken(search) {
|
|
691
|
+
if (!search) return null;
|
|
692
|
+
let value;
|
|
693
|
+
if (typeof search === "string") {
|
|
694
|
+
value = new URLSearchParams(
|
|
695
|
+
search.startsWith("?") ? search.slice(1) : search
|
|
696
|
+
).get(PREVIEW_TOKEN_PARAM);
|
|
697
|
+
} else if (search instanceof URLSearchParams) {
|
|
698
|
+
value = search.get(PREVIEW_TOKEN_PARAM);
|
|
699
|
+
} else {
|
|
700
|
+
value = search[PREVIEW_TOKEN_PARAM];
|
|
701
|
+
}
|
|
702
|
+
if (Array.isArray(value)) value = value[0];
|
|
703
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
704
|
+
}
|
|
599
705
|
function isFunctionallyEmpty(obj) {
|
|
600
706
|
if (obj === null || obj === void 0 || obj === "") return true;
|
|
601
707
|
if (Array.isArray(obj)) {
|
|
@@ -605,7 +711,9 @@ function isFunctionallyEmpty(obj) {
|
|
|
605
711
|
if (typeof obj === "object") {
|
|
606
712
|
const keys = Object.keys(obj);
|
|
607
713
|
if (keys.length === 0) return true;
|
|
608
|
-
return keys.every(
|
|
714
|
+
return keys.every(
|
|
715
|
+
(key) => isFunctionallyEmpty(obj[key])
|
|
716
|
+
);
|
|
609
717
|
}
|
|
610
718
|
return false;
|
|
611
719
|
}
|
|
@@ -639,5 +747,7 @@ function normalizeQueryArgs(args) {
|
|
|
639
747
|
0 && (module.exports = {
|
|
640
748
|
DyrectedClient,
|
|
641
749
|
DyrectedError,
|
|
642
|
-
|
|
750
|
+
PREVIEW_TOKEN_PARAM,
|
|
751
|
+
createClient,
|
|
752
|
+
getPreviewToken
|
|
643
753
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PaginatedResult, CollectionConfig, GlobalConfig, AdminConfig, PublicAdminAuthConfig, FileData, WorkflowMetadata } from '@dyrected/core';
|
|
1
|
+
import { PaginatedResult, Block, CollectionConfig, GlobalConfig, AdminConfig, PublicAdminAuthConfig, FileData, WorkflowMetadata } from '@dyrected/core';
|
|
2
2
|
export { AdminIconName, Block, CollectionConfig, EmailField, Field, FieldType, GlobalConfig, IconField, LifecycleEvent, FileData as Media, NumberField, PaginatedResult, TextField, TextareaField, UrlField, WorkflowMetadata } from '@dyrected/core';
|
|
3
3
|
|
|
4
4
|
type UnknownRecord$1 = Record<string, unknown>;
|
|
@@ -27,6 +27,7 @@ declare class QueryBuilder<T = UnknownRecord$1> {
|
|
|
27
27
|
|
|
28
28
|
type UnknownRecord = Record<string, unknown>;
|
|
29
29
|
type SchemaResponse = {
|
|
30
|
+
blocks?: Block[];
|
|
30
31
|
collections: CollectionConfig[];
|
|
31
32
|
globals: GlobalConfig[];
|
|
32
33
|
admin?: AdminConfig;
|
|
@@ -129,13 +130,63 @@ interface DyrectedClientConfig {
|
|
|
129
130
|
siteId?: string;
|
|
130
131
|
headers?: Record<string, string>;
|
|
131
132
|
fetch?: typeof fetch;
|
|
132
|
-
/**
|
|
133
|
+
/**
|
|
134
|
+
* Default relationship population depth applied to document reads
|
|
135
|
+
* (`find`, `findOne`, `global().get()`, and media listing) when a call
|
|
136
|
+
* does not pass its own `depth`. Defaults to `1`.
|
|
137
|
+
*/
|
|
133
138
|
defaultDepth?: number;
|
|
134
139
|
}
|
|
135
140
|
interface BaseSchema {
|
|
136
141
|
collections: Record<string, UnknownRecord>;
|
|
137
142
|
globals: Record<string, UnknownRecord>;
|
|
138
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* The structural bound used as the generic *constraint* for {@link DyrectedClient}
|
|
146
|
+
* and the framework hooks. Its map values are `object` rather than
|
|
147
|
+
* `Record<string, unknown>`.
|
|
148
|
+
*
|
|
149
|
+
* This matters because a generated `DyrectedSchema` is built from named
|
|
150
|
+
* `interface`s (one per collection/global), and TypeScript interfaces have **no
|
|
151
|
+
* implicit index signature** — so they are assignable to `object` but *not* to
|
|
152
|
+
* `Record<string, unknown>`. Constraining against {@link BaseSchema} would
|
|
153
|
+
* reject every real generated schema; constraining against `SchemaShape`
|
|
154
|
+
* accepts them while {@link BaseSchema} remains the rich fallback default.
|
|
155
|
+
*/
|
|
156
|
+
interface SchemaShape {
|
|
157
|
+
collections: Record<string, object>;
|
|
158
|
+
globals: Record<string, object>;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Global registration seam for your generated schema.
|
|
162
|
+
*
|
|
163
|
+
* `dyrected generate:types` emits a module augmentation that registers your
|
|
164
|
+
* `DyrectedSchema` here:
|
|
165
|
+
*
|
|
166
|
+
* ```ts
|
|
167
|
+
* declare module "@dyrected/sdk" {
|
|
168
|
+
* interface Register { schema: DyrectedSchema }
|
|
169
|
+
* }
|
|
170
|
+
* ```
|
|
171
|
+
*
|
|
172
|
+
* Once that generated file is part of your compilation, every client and
|
|
173
|
+
* framework hook is typed against your schema automatically — no per-call
|
|
174
|
+
* generics. Until then, this stays empty and everything falls back to the
|
|
175
|
+
* loosely-typed {@link BaseSchema}.
|
|
176
|
+
*/
|
|
177
|
+
interface Register {
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* The schema the SDK and framework hooks type themselves against. Resolves to
|
|
181
|
+
* your registered {@link Register} schema when the generated types are present,
|
|
182
|
+
* otherwise to {@link BaseSchema}. This is the default type parameter for
|
|
183
|
+
* {@link DyrectedClient} and {@link createClient}, so `client.collection("...")`
|
|
184
|
+
* and the React/Vue hooks pick up your collections and document shapes with no
|
|
185
|
+
* explicit generic.
|
|
186
|
+
*/
|
|
187
|
+
type RegisteredSchema = Register extends {
|
|
188
|
+
schema: infer S;
|
|
189
|
+
} ? S extends SchemaShape ? S : BaseSchema : BaseSchema;
|
|
139
190
|
/**
|
|
140
191
|
* Options for file uploads.
|
|
141
192
|
* When `onProgress` is provided and the runtime supports XMLHttpRequest (browsers),
|
|
@@ -148,7 +199,7 @@ interface UploadOptions {
|
|
|
148
199
|
/** Abort the in-flight upload. */
|
|
149
200
|
signal?: AbortSignal;
|
|
150
201
|
}
|
|
151
|
-
declare class DyrectedClient<TSchema extends
|
|
202
|
+
declare class DyrectedClient<TSchema extends SchemaShape = RegisteredSchema> {
|
|
152
203
|
private baseUrl;
|
|
153
204
|
private headers;
|
|
154
205
|
private fetch;
|
|
@@ -171,6 +222,11 @@ declare class DyrectedClient<TSchema extends BaseSchema = BaseSchema> {
|
|
|
171
222
|
*/
|
|
172
223
|
getAuthHeaders(): Record<string, string>;
|
|
173
224
|
getBaseUrl(): string;
|
|
225
|
+
/**
|
|
226
|
+
* Inject the client's configured `defaultDepth` when a read did not specify
|
|
227
|
+
* its own `depth`. A per-call `depth` (including `0`) always wins.
|
|
228
|
+
*/
|
|
229
|
+
private applyDefaultDepth;
|
|
174
230
|
getSchemas(): Promise<SchemaResponse>;
|
|
175
231
|
getAdminAuthConfig(): Promise<PublicAdminAuthConfig>;
|
|
176
232
|
exchangeAdminAuth(providerId: string, body: Record<string, unknown>): Promise<{
|
|
@@ -200,6 +256,21 @@ declare class DyrectedClient<TSchema extends BaseSchema = BaseSchema> {
|
|
|
200
256
|
* Used in "token" preview mode.
|
|
201
257
|
*/
|
|
202
258
|
getPreviewData<T = unknown>(token: string): Promise<T>;
|
|
259
|
+
/**
|
|
260
|
+
* Mint a short-lived preview token that carries the current (unsaved) draft
|
|
261
|
+
* data. Used by the Admin in `previewMode: "token"` to hand draft content to
|
|
262
|
+
* a server-rendered frontend that cannot receive it over `postMessage`.
|
|
263
|
+
*
|
|
264
|
+
* Requires an authenticated request (the Admin is logged in).
|
|
265
|
+
*/
|
|
266
|
+
createPreviewToken(input: {
|
|
267
|
+
collectionSlug: string;
|
|
268
|
+
documentId?: string;
|
|
269
|
+
data: unknown;
|
|
270
|
+
}): Promise<{
|
|
271
|
+
token: string;
|
|
272
|
+
expiresAt: string;
|
|
273
|
+
}>;
|
|
203
274
|
find<K extends keyof TSchema["collections"]>(collection: K & string, args?: QueryArgs<TSchema["collections"][K]>): Promise<PaginatedResult<TSchema["collections"][K]>>;
|
|
204
275
|
/**
|
|
205
276
|
* Returns a fluent query builder for a collection.
|
|
@@ -412,6 +483,24 @@ declare class DyrectedClient<TSchema extends BaseSchema = BaseSchema> {
|
|
|
412
483
|
}>;
|
|
413
484
|
private request;
|
|
414
485
|
}
|
|
415
|
-
declare function createClient<TSchema extends
|
|
486
|
+
declare function createClient<TSchema extends SchemaShape = RegisteredSchema>(config: DyrectedClientConfig): DyrectedClient<TSchema>;
|
|
487
|
+
/**
|
|
488
|
+
* The query-string parameter the Admin appends to a preview URL in
|
|
489
|
+
* `previewMode: "token"`. Read it on your frontend to decide whether to fetch
|
|
490
|
+
* draft data instead of published content.
|
|
491
|
+
*/
|
|
492
|
+
declare const PREVIEW_TOKEN_PARAM = "dyPreview";
|
|
493
|
+
/**
|
|
494
|
+
* Extract the preview token from a request's query string. Accepts a raw query
|
|
495
|
+
* string, a `URLSearchParams`, or a plain params object (e.g. Nuxt's
|
|
496
|
+
* `route.query` or Next's `searchParams`). Returns `null` when absent.
|
|
497
|
+
*
|
|
498
|
+
* @example
|
|
499
|
+
* const token = getPreviewToken(route.query);
|
|
500
|
+
* const doc = token
|
|
501
|
+
* ? (await client.getPreviewData(token)).data
|
|
502
|
+
* : (await client.find("pages", { where })).docs[0];
|
|
503
|
+
*/
|
|
504
|
+
declare function getPreviewToken(search: string | URLSearchParams | Record<string, unknown> | undefined | null): string | null;
|
|
416
505
|
|
|
417
|
-
export { type AuditEntry, type BaseSchema, DyrectedClient, type DyrectedClientConfig, DyrectedError, type InferSchema, type TransitionOptions, type UploadOptions, type WorkflowDocument, type WorkflowHistoryEntry, createClient };
|
|
506
|
+
export { type AuditEntry, type BaseSchema, DyrectedClient, type DyrectedClientConfig, DyrectedError, type InferSchema, PREVIEW_TOKEN_PARAM, type Register, type RegisteredSchema, type SchemaShape, type TransitionOptions, type UploadOptions, type WorkflowDocument, type WorkflowHistoryEntry, createClient, getPreviewToken };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PaginatedResult, CollectionConfig, GlobalConfig, AdminConfig, PublicAdminAuthConfig, FileData, WorkflowMetadata } from '@dyrected/core';
|
|
1
|
+
import { PaginatedResult, Block, CollectionConfig, GlobalConfig, AdminConfig, PublicAdminAuthConfig, FileData, WorkflowMetadata } from '@dyrected/core';
|
|
2
2
|
export { AdminIconName, Block, CollectionConfig, EmailField, Field, FieldType, GlobalConfig, IconField, LifecycleEvent, FileData as Media, NumberField, PaginatedResult, TextField, TextareaField, UrlField, WorkflowMetadata } from '@dyrected/core';
|
|
3
3
|
|
|
4
4
|
type UnknownRecord$1 = Record<string, unknown>;
|
|
@@ -27,6 +27,7 @@ declare class QueryBuilder<T = UnknownRecord$1> {
|
|
|
27
27
|
|
|
28
28
|
type UnknownRecord = Record<string, unknown>;
|
|
29
29
|
type SchemaResponse = {
|
|
30
|
+
blocks?: Block[];
|
|
30
31
|
collections: CollectionConfig[];
|
|
31
32
|
globals: GlobalConfig[];
|
|
32
33
|
admin?: AdminConfig;
|
|
@@ -129,13 +130,63 @@ interface DyrectedClientConfig {
|
|
|
129
130
|
siteId?: string;
|
|
130
131
|
headers?: Record<string, string>;
|
|
131
132
|
fetch?: typeof fetch;
|
|
132
|
-
/**
|
|
133
|
+
/**
|
|
134
|
+
* Default relationship population depth applied to document reads
|
|
135
|
+
* (`find`, `findOne`, `global().get()`, and media listing) when a call
|
|
136
|
+
* does not pass its own `depth`. Defaults to `1`.
|
|
137
|
+
*/
|
|
133
138
|
defaultDepth?: number;
|
|
134
139
|
}
|
|
135
140
|
interface BaseSchema {
|
|
136
141
|
collections: Record<string, UnknownRecord>;
|
|
137
142
|
globals: Record<string, UnknownRecord>;
|
|
138
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* The structural bound used as the generic *constraint* for {@link DyrectedClient}
|
|
146
|
+
* and the framework hooks. Its map values are `object` rather than
|
|
147
|
+
* `Record<string, unknown>`.
|
|
148
|
+
*
|
|
149
|
+
* This matters because a generated `DyrectedSchema` is built from named
|
|
150
|
+
* `interface`s (one per collection/global), and TypeScript interfaces have **no
|
|
151
|
+
* implicit index signature** — so they are assignable to `object` but *not* to
|
|
152
|
+
* `Record<string, unknown>`. Constraining against {@link BaseSchema} would
|
|
153
|
+
* reject every real generated schema; constraining against `SchemaShape`
|
|
154
|
+
* accepts them while {@link BaseSchema} remains the rich fallback default.
|
|
155
|
+
*/
|
|
156
|
+
interface SchemaShape {
|
|
157
|
+
collections: Record<string, object>;
|
|
158
|
+
globals: Record<string, object>;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Global registration seam for your generated schema.
|
|
162
|
+
*
|
|
163
|
+
* `dyrected generate:types` emits a module augmentation that registers your
|
|
164
|
+
* `DyrectedSchema` here:
|
|
165
|
+
*
|
|
166
|
+
* ```ts
|
|
167
|
+
* declare module "@dyrected/sdk" {
|
|
168
|
+
* interface Register { schema: DyrectedSchema }
|
|
169
|
+
* }
|
|
170
|
+
* ```
|
|
171
|
+
*
|
|
172
|
+
* Once that generated file is part of your compilation, every client and
|
|
173
|
+
* framework hook is typed against your schema automatically — no per-call
|
|
174
|
+
* generics. Until then, this stays empty and everything falls back to the
|
|
175
|
+
* loosely-typed {@link BaseSchema}.
|
|
176
|
+
*/
|
|
177
|
+
interface Register {
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* The schema the SDK and framework hooks type themselves against. Resolves to
|
|
181
|
+
* your registered {@link Register} schema when the generated types are present,
|
|
182
|
+
* otherwise to {@link BaseSchema}. This is the default type parameter for
|
|
183
|
+
* {@link DyrectedClient} and {@link createClient}, so `client.collection("...")`
|
|
184
|
+
* and the React/Vue hooks pick up your collections and document shapes with no
|
|
185
|
+
* explicit generic.
|
|
186
|
+
*/
|
|
187
|
+
type RegisteredSchema = Register extends {
|
|
188
|
+
schema: infer S;
|
|
189
|
+
} ? S extends SchemaShape ? S : BaseSchema : BaseSchema;
|
|
139
190
|
/**
|
|
140
191
|
* Options for file uploads.
|
|
141
192
|
* When `onProgress` is provided and the runtime supports XMLHttpRequest (browsers),
|
|
@@ -148,7 +199,7 @@ interface UploadOptions {
|
|
|
148
199
|
/** Abort the in-flight upload. */
|
|
149
200
|
signal?: AbortSignal;
|
|
150
201
|
}
|
|
151
|
-
declare class DyrectedClient<TSchema extends
|
|
202
|
+
declare class DyrectedClient<TSchema extends SchemaShape = RegisteredSchema> {
|
|
152
203
|
private baseUrl;
|
|
153
204
|
private headers;
|
|
154
205
|
private fetch;
|
|
@@ -171,6 +222,11 @@ declare class DyrectedClient<TSchema extends BaseSchema = BaseSchema> {
|
|
|
171
222
|
*/
|
|
172
223
|
getAuthHeaders(): Record<string, string>;
|
|
173
224
|
getBaseUrl(): string;
|
|
225
|
+
/**
|
|
226
|
+
* Inject the client's configured `defaultDepth` when a read did not specify
|
|
227
|
+
* its own `depth`. A per-call `depth` (including `0`) always wins.
|
|
228
|
+
*/
|
|
229
|
+
private applyDefaultDepth;
|
|
174
230
|
getSchemas(): Promise<SchemaResponse>;
|
|
175
231
|
getAdminAuthConfig(): Promise<PublicAdminAuthConfig>;
|
|
176
232
|
exchangeAdminAuth(providerId: string, body: Record<string, unknown>): Promise<{
|
|
@@ -200,6 +256,21 @@ declare class DyrectedClient<TSchema extends BaseSchema = BaseSchema> {
|
|
|
200
256
|
* Used in "token" preview mode.
|
|
201
257
|
*/
|
|
202
258
|
getPreviewData<T = unknown>(token: string): Promise<T>;
|
|
259
|
+
/**
|
|
260
|
+
* Mint a short-lived preview token that carries the current (unsaved) draft
|
|
261
|
+
* data. Used by the Admin in `previewMode: "token"` to hand draft content to
|
|
262
|
+
* a server-rendered frontend that cannot receive it over `postMessage`.
|
|
263
|
+
*
|
|
264
|
+
* Requires an authenticated request (the Admin is logged in).
|
|
265
|
+
*/
|
|
266
|
+
createPreviewToken(input: {
|
|
267
|
+
collectionSlug: string;
|
|
268
|
+
documentId?: string;
|
|
269
|
+
data: unknown;
|
|
270
|
+
}): Promise<{
|
|
271
|
+
token: string;
|
|
272
|
+
expiresAt: string;
|
|
273
|
+
}>;
|
|
203
274
|
find<K extends keyof TSchema["collections"]>(collection: K & string, args?: QueryArgs<TSchema["collections"][K]>): Promise<PaginatedResult<TSchema["collections"][K]>>;
|
|
204
275
|
/**
|
|
205
276
|
* Returns a fluent query builder for a collection.
|
|
@@ -412,6 +483,24 @@ declare class DyrectedClient<TSchema extends BaseSchema = BaseSchema> {
|
|
|
412
483
|
}>;
|
|
413
484
|
private request;
|
|
414
485
|
}
|
|
415
|
-
declare function createClient<TSchema extends
|
|
486
|
+
declare function createClient<TSchema extends SchemaShape = RegisteredSchema>(config: DyrectedClientConfig): DyrectedClient<TSchema>;
|
|
487
|
+
/**
|
|
488
|
+
* The query-string parameter the Admin appends to a preview URL in
|
|
489
|
+
* `previewMode: "token"`. Read it on your frontend to decide whether to fetch
|
|
490
|
+
* draft data instead of published content.
|
|
491
|
+
*/
|
|
492
|
+
declare const PREVIEW_TOKEN_PARAM = "dyPreview";
|
|
493
|
+
/**
|
|
494
|
+
* Extract the preview token from a request's query string. Accepts a raw query
|
|
495
|
+
* string, a `URLSearchParams`, or a plain params object (e.g. Nuxt's
|
|
496
|
+
* `route.query` or Next's `searchParams`). Returns `null` when absent.
|
|
497
|
+
*
|
|
498
|
+
* @example
|
|
499
|
+
* const token = getPreviewToken(route.query);
|
|
500
|
+
* const doc = token
|
|
501
|
+
* ? (await client.getPreviewData(token)).data
|
|
502
|
+
* : (await client.find("pages", { where })).docs[0];
|
|
503
|
+
*/
|
|
504
|
+
declare function getPreviewToken(search: string | URLSearchParams | Record<string, unknown> | undefined | null): string | null;
|
|
416
505
|
|
|
417
|
-
export { type AuditEntry, type BaseSchema, DyrectedClient, type DyrectedClientConfig, DyrectedError, type InferSchema, type TransitionOptions, type UploadOptions, type WorkflowDocument, type WorkflowHistoryEntry, createClient };
|
|
506
|
+
export { type AuditEntry, type BaseSchema, DyrectedClient, type DyrectedClientConfig, DyrectedError, type InferSchema, PREVIEW_TOKEN_PARAM, type Register, type RegisteredSchema, type SchemaShape, type TransitionOptions, type UploadOptions, type WorkflowDocument, type WorkflowHistoryEntry, createClient, getPreviewToken };
|
package/dist/index.js
CHANGED
|
@@ -135,6 +135,13 @@ var DyrectedClient = class {
|
|
|
135
135
|
getBaseUrl() {
|
|
136
136
|
return this.baseUrl;
|
|
137
137
|
}
|
|
138
|
+
/**
|
|
139
|
+
* Inject the client's configured `defaultDepth` when a read did not specify
|
|
140
|
+
* its own `depth`. A per-call `depth` (including `0`) always wins.
|
|
141
|
+
*/
|
|
142
|
+
applyDefaultDepth(args) {
|
|
143
|
+
return args.depth === void 0 ? { ...args, depth: this.defaultDepth } : args;
|
|
144
|
+
}
|
|
138
145
|
async getSchemas() {
|
|
139
146
|
return this.request("/api/schemas");
|
|
140
147
|
}
|
|
@@ -149,27 +156,48 @@ var DyrectedClient = class {
|
|
|
149
156
|
}
|
|
150
157
|
async getPreference(key, options) {
|
|
151
158
|
const scopeParam = options?.scope ? `?scope=${options.scope}` : "";
|
|
152
|
-
return this.request(
|
|
159
|
+
return this.request(
|
|
160
|
+
`/api/preferences/${encodeURIComponent(key)}${scopeParam}`
|
|
161
|
+
);
|
|
153
162
|
}
|
|
154
163
|
async setPreference(key, value, options) {
|
|
155
164
|
const scopeParam = options?.scope ? `?scope=${options.scope}` : "";
|
|
156
|
-
return this.request(
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
165
|
+
return this.request(
|
|
166
|
+
`/api/preferences/${encodeURIComponent(key)}${scopeParam}`,
|
|
167
|
+
{
|
|
168
|
+
method: "PUT",
|
|
169
|
+
body: JSON.stringify({ value })
|
|
170
|
+
}
|
|
171
|
+
);
|
|
160
172
|
}
|
|
161
173
|
async deletePreference(key, options) {
|
|
162
174
|
const scopeParam = options?.scope ? `?scope=${options.scope}` : "";
|
|
163
|
-
return this.request(
|
|
164
|
-
|
|
165
|
-
|
|
175
|
+
return this.request(
|
|
176
|
+
`/api/preferences/${encodeURIComponent(key)}${scopeParam}`,
|
|
177
|
+
{
|
|
178
|
+
method: "DELETE"
|
|
179
|
+
}
|
|
180
|
+
);
|
|
166
181
|
}
|
|
167
182
|
/**
|
|
168
183
|
* Fetch draft data for a specific preview token.
|
|
169
184
|
* Used in "token" preview mode.
|
|
170
185
|
*/
|
|
171
186
|
async getPreviewData(token) {
|
|
172
|
-
return this.request(`/api/preview-data?token=${token}`);
|
|
187
|
+
return this.request(`/api/preview-data?token=${encodeURIComponent(token)}`);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Mint a short-lived preview token that carries the current (unsaved) draft
|
|
191
|
+
* data. Used by the Admin in `previewMode: "token"` to hand draft content to
|
|
192
|
+
* a server-rendered frontend that cannot receive it over `postMessage`.
|
|
193
|
+
*
|
|
194
|
+
* Requires an authenticated request (the Admin is logged in).
|
|
195
|
+
*/
|
|
196
|
+
async createPreviewToken(input) {
|
|
197
|
+
return this.request(`/api/preview-token`, {
|
|
198
|
+
method: "POST",
|
|
199
|
+
body: JSON.stringify(input)
|
|
200
|
+
});
|
|
173
201
|
}
|
|
174
202
|
async find(collection, args = {}) {
|
|
175
203
|
const { initialData, ...queryArgs } = args;
|
|
@@ -177,13 +205,22 @@ var DyrectedClient = class {
|
|
|
177
205
|
if (queryArgs.where && typeof queryArgs.where === "object") {
|
|
178
206
|
normalizedArgs.where = JSON.stringify(queryArgs.where);
|
|
179
207
|
}
|
|
180
|
-
const query = stringifyQuery(normalizedArgs, {
|
|
181
|
-
|
|
208
|
+
const query = stringifyQuery(this.applyDefaultDepth(normalizedArgs), {
|
|
209
|
+
addQueryPrefix: true
|
|
210
|
+
});
|
|
211
|
+
const res = await this.request(
|
|
212
|
+
`/api/collections/${collection}${query}`
|
|
213
|
+
);
|
|
182
214
|
if (res.docs.length === 0 && initialData && initialData.length > 0) {
|
|
183
215
|
this.request(`/api/collections/${collection}/seed`, {
|
|
184
216
|
method: "POST",
|
|
185
217
|
body: JSON.stringify({ data: initialData })
|
|
186
|
-
}).catch(
|
|
218
|
+
}).catch(
|
|
219
|
+
(err) => console.error(
|
|
220
|
+
`[dyrected/sdk] Failed to auto-seed collection "${collection}":`,
|
|
221
|
+
err
|
|
222
|
+
)
|
|
223
|
+
);
|
|
187
224
|
return {
|
|
188
225
|
docs: initialData,
|
|
189
226
|
total: initialData.length,
|
|
@@ -207,11 +244,12 @@ var DyrectedClient = class {
|
|
|
207
244
|
(collectionName, queryArgs) => this.find(collectionName, queryArgs)
|
|
208
245
|
);
|
|
209
246
|
if (args) {
|
|
210
|
-
if (args.where && typeof args.where === "object")
|
|
247
|
+
if (args.where && typeof args.where === "object")
|
|
248
|
+
qb.where(args.where);
|
|
211
249
|
if (args.sort) qb.sort(args.sort);
|
|
212
250
|
if (args.limit) qb.limit(args.limit);
|
|
213
251
|
if (args.page) qb.page(args.page);
|
|
214
|
-
if (args.depth) qb.depth(args.depth);
|
|
252
|
+
if (args.depth !== void 0) qb.depth(args.depth);
|
|
215
253
|
if (args.initialData) qb.seed(args.initialData);
|
|
216
254
|
}
|
|
217
255
|
return qb;
|
|
@@ -304,7 +342,12 @@ var DyrectedClient = class {
|
|
|
304
342
|
* comment: 'Please add more detail to section 2.',
|
|
305
343
|
* })
|
|
306
344
|
*/
|
|
307
|
-
transition: (id, transitionName, opts) => this.transition(
|
|
345
|
+
transition: (id, transitionName, opts) => this.transition(
|
|
346
|
+
slug,
|
|
347
|
+
id,
|
|
348
|
+
transitionName,
|
|
349
|
+
opts
|
|
350
|
+
),
|
|
308
351
|
/**
|
|
309
352
|
* Fetch the workflow history for a single document — every transition that
|
|
310
353
|
* has ever been performed, newest first.
|
|
@@ -334,7 +377,9 @@ var DyrectedClient = class {
|
|
|
334
377
|
}
|
|
335
378
|
async findOne(collection, id, args = {}) {
|
|
336
379
|
const { initialData, ...queryArgs } = args;
|
|
337
|
-
const query = stringifyQuery(queryArgs, {
|
|
380
|
+
const query = stringifyQuery(this.applyDefaultDepth(queryArgs), {
|
|
381
|
+
addQueryPrefix: true
|
|
382
|
+
});
|
|
338
383
|
try {
|
|
339
384
|
return await this.request(`/api/collections/${collection}/${id}${query}`);
|
|
340
385
|
} catch (err) {
|
|
@@ -343,7 +388,10 @@ var DyrectedClient = class {
|
|
|
343
388
|
method: "POST",
|
|
344
389
|
body: JSON.stringify({ data: [{ id, ...initialData }] })
|
|
345
390
|
}).catch(
|
|
346
|
-
(err2) => console.error(
|
|
391
|
+
(err2) => console.error(
|
|
392
|
+
`[dyrected/sdk] Failed to auto-seed document "${id}" in collection "${collection}":`,
|
|
393
|
+
err2
|
|
394
|
+
)
|
|
347
395
|
);
|
|
348
396
|
return initialData;
|
|
349
397
|
}
|
|
@@ -382,10 +430,13 @@ var DyrectedClient = class {
|
|
|
382
430
|
* const updated = await client.transition('posts', postId, 'publish')
|
|
383
431
|
*/
|
|
384
432
|
async transition(collection, id, transitionName, opts = {}) {
|
|
385
|
-
return this.request(
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
433
|
+
return this.request(
|
|
434
|
+
`/api/collections/${collection}/${id}/transitions/${encodeURIComponent(transitionName)}`,
|
|
435
|
+
{
|
|
436
|
+
method: "POST",
|
|
437
|
+
body: JSON.stringify(opts)
|
|
438
|
+
}
|
|
439
|
+
);
|
|
389
440
|
}
|
|
390
441
|
/**
|
|
391
442
|
* Fetch the workflow history for a document.
|
|
@@ -398,7 +449,9 @@ var DyrectedClient = class {
|
|
|
398
449
|
*/
|
|
399
450
|
async workflowHistory(collection, id, args = {}) {
|
|
400
451
|
const query = args.limit ? `?limit=${args.limit}` : "";
|
|
401
|
-
return this.request(
|
|
452
|
+
return this.request(
|
|
453
|
+
`/api/collections/${collection}/${id}/workflow-history${query}`
|
|
454
|
+
);
|
|
402
455
|
}
|
|
403
456
|
/**
|
|
404
457
|
* Fetch audit entries across every audited collection the current caller can read.
|
|
@@ -406,7 +459,9 @@ var DyrectedClient = class {
|
|
|
406
459
|
* Sends `GET /api/audit`.
|
|
407
460
|
*/
|
|
408
461
|
async audit(args = {}) {
|
|
409
|
-
const query = stringifyQuery(normalizeQueryArgs(args), {
|
|
462
|
+
const query = stringifyQuery(normalizeQueryArgs(args), {
|
|
463
|
+
addQueryPrefix: true
|
|
464
|
+
});
|
|
410
465
|
return this.request(`/api/audit${query}`);
|
|
411
466
|
}
|
|
412
467
|
/**
|
|
@@ -415,7 +470,9 @@ var DyrectedClient = class {
|
|
|
415
470
|
* Sends `GET /api/collections/:collection/__audit`.
|
|
416
471
|
*/
|
|
417
472
|
async collectionAudit(collection, args = {}) {
|
|
418
|
-
const query = stringifyQuery(normalizeQueryArgs(args), {
|
|
473
|
+
const query = stringifyQuery(normalizeQueryArgs(args), {
|
|
474
|
+
addQueryPrefix: true
|
|
475
|
+
});
|
|
419
476
|
return this.request(`/api/collections/${collection}/__audit${query}`);
|
|
420
477
|
}
|
|
421
478
|
async deleteMany(collection, ids) {
|
|
@@ -426,7 +483,9 @@ var DyrectedClient = class {
|
|
|
426
483
|
}
|
|
427
484
|
async getGlobal(slug, args = {}) {
|
|
428
485
|
const { initialData, ...queryArgs } = args;
|
|
429
|
-
const query = stringifyQuery(queryArgs, {
|
|
486
|
+
const query = stringifyQuery(this.applyDefaultDepth(queryArgs), {
|
|
487
|
+
addQueryPrefix: true
|
|
488
|
+
});
|
|
430
489
|
try {
|
|
431
490
|
const res = await this.request(`/api/globals/${slug}${query}`);
|
|
432
491
|
if ((!res || isFunctionallyEmpty(res)) && !isFunctionallyEmpty(initialData)) {
|
|
@@ -434,7 +493,12 @@ var DyrectedClient = class {
|
|
|
434
493
|
this.request(`/api/globals/${slug}/seed`, {
|
|
435
494
|
method: "POST",
|
|
436
495
|
body: JSON.stringify({ data: initialData })
|
|
437
|
-
}).catch(
|
|
496
|
+
}).catch(
|
|
497
|
+
(err) => console.error(
|
|
498
|
+
`[dyrected/sdk] Failed to auto-seed global "${slug}":`,
|
|
499
|
+
err
|
|
500
|
+
)
|
|
501
|
+
);
|
|
438
502
|
return initialData;
|
|
439
503
|
}
|
|
440
504
|
return res;
|
|
@@ -443,7 +507,12 @@ var DyrectedClient = class {
|
|
|
443
507
|
this.request(`/api/globals/${slug}/seed`, {
|
|
444
508
|
method: "POST",
|
|
445
509
|
body: JSON.stringify({ data: initialData })
|
|
446
|
-
}).catch(
|
|
510
|
+
}).catch(
|
|
511
|
+
(err2) => console.error(
|
|
512
|
+
`[dyrected/sdk] Failed to auto-seed global "${slug}":`,
|
|
513
|
+
err2
|
|
514
|
+
)
|
|
515
|
+
);
|
|
447
516
|
return initialData;
|
|
448
517
|
}
|
|
449
518
|
throw err;
|
|
@@ -456,8 +525,13 @@ var DyrectedClient = class {
|
|
|
456
525
|
});
|
|
457
526
|
}
|
|
458
527
|
async listMedia(args = {}, collection = "media") {
|
|
459
|
-
const query = stringifyQuery(
|
|
460
|
-
|
|
528
|
+
const query = stringifyQuery(
|
|
529
|
+
this.applyDefaultDepth(normalizeQueryArgs(args)),
|
|
530
|
+
{ addQueryPrefix: true }
|
|
531
|
+
);
|
|
532
|
+
return this.request(
|
|
533
|
+
`/api/collections/${collection}${query}`
|
|
534
|
+
);
|
|
461
535
|
}
|
|
462
536
|
/** @deprecated Use client.collection('media').upload(file, data) instead */
|
|
463
537
|
async uploadMedia(file, collection = "media") {
|
|
@@ -502,7 +576,9 @@ var DyrectedClient = class {
|
|
|
502
576
|
reject(new DyrectedError("Upload aborted", 0));
|
|
503
577
|
return;
|
|
504
578
|
}
|
|
505
|
-
options.signal.addEventListener("abort", () => xhr.abort(), {
|
|
579
|
+
options.signal.addEventListener("abort", () => xhr.abort(), {
|
|
580
|
+
once: true
|
|
581
|
+
});
|
|
506
582
|
}
|
|
507
583
|
xhr.upload.onprogress = (event) => {
|
|
508
584
|
if (event.lengthComputable) {
|
|
@@ -530,7 +606,13 @@ var DyrectedClient = class {
|
|
|
530
606
|
})
|
|
531
607
|
);
|
|
532
608
|
}
|
|
533
|
-
reject(
|
|
609
|
+
reject(
|
|
610
|
+
new DyrectedError(
|
|
611
|
+
body.message || `Request failed with status ${xhr.status}`,
|
|
612
|
+
xhr.status,
|
|
613
|
+
body.code
|
|
614
|
+
)
|
|
615
|
+
);
|
|
534
616
|
};
|
|
535
617
|
xhr.onerror = () => reject(new DyrectedError("Network error during upload", 0));
|
|
536
618
|
xhr.onabort = () => reject(new DyrectedError("Upload aborted", 0));
|
|
@@ -549,7 +631,9 @@ var DyrectedClient = class {
|
|
|
549
631
|
});
|
|
550
632
|
if (res && typeof res.ok === "boolean") {
|
|
551
633
|
if (!res.ok) {
|
|
552
|
-
const body = await res.json().catch(() => ({
|
|
634
|
+
const body = await res.json().catch(() => ({
|
|
635
|
+
message: "Unknown error"
|
|
636
|
+
}));
|
|
553
637
|
if (res.status === 429 && typeof window !== "undefined") {
|
|
554
638
|
window.dispatchEvent(
|
|
555
639
|
new CustomEvent("dyrected:rate-limit", {
|
|
@@ -558,7 +642,11 @@ var DyrectedClient = class {
|
|
|
558
642
|
);
|
|
559
643
|
}
|
|
560
644
|
console.log("[DyrectedError]", body, res.status);
|
|
561
|
-
throw new DyrectedError(
|
|
645
|
+
throw new DyrectedError(
|
|
646
|
+
body.message || `Request failed with status ${res.status}`,
|
|
647
|
+
res.status,
|
|
648
|
+
body.code
|
|
649
|
+
);
|
|
562
650
|
}
|
|
563
651
|
return res.json();
|
|
564
652
|
}
|
|
@@ -568,6 +656,22 @@ var DyrectedClient = class {
|
|
|
568
656
|
function createClient(config) {
|
|
569
657
|
return new DyrectedClient(config);
|
|
570
658
|
}
|
|
659
|
+
var PREVIEW_TOKEN_PARAM = "dyPreview";
|
|
660
|
+
function getPreviewToken(search) {
|
|
661
|
+
if (!search) return null;
|
|
662
|
+
let value;
|
|
663
|
+
if (typeof search === "string") {
|
|
664
|
+
value = new URLSearchParams(
|
|
665
|
+
search.startsWith("?") ? search.slice(1) : search
|
|
666
|
+
).get(PREVIEW_TOKEN_PARAM);
|
|
667
|
+
} else if (search instanceof URLSearchParams) {
|
|
668
|
+
value = search.get(PREVIEW_TOKEN_PARAM);
|
|
669
|
+
} else {
|
|
670
|
+
value = search[PREVIEW_TOKEN_PARAM];
|
|
671
|
+
}
|
|
672
|
+
if (Array.isArray(value)) value = value[0];
|
|
673
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
674
|
+
}
|
|
571
675
|
function isFunctionallyEmpty(obj) {
|
|
572
676
|
if (obj === null || obj === void 0 || obj === "") return true;
|
|
573
677
|
if (Array.isArray(obj)) {
|
|
@@ -577,7 +681,9 @@ function isFunctionallyEmpty(obj) {
|
|
|
577
681
|
if (typeof obj === "object") {
|
|
578
682
|
const keys = Object.keys(obj);
|
|
579
683
|
if (keys.length === 0) return true;
|
|
580
|
-
return keys.every(
|
|
684
|
+
return keys.every(
|
|
685
|
+
(key) => isFunctionallyEmpty(obj[key])
|
|
686
|
+
);
|
|
581
687
|
}
|
|
582
688
|
return false;
|
|
583
689
|
}
|
|
@@ -610,5 +716,7 @@ function normalizeQueryArgs(args) {
|
|
|
610
716
|
export {
|
|
611
717
|
DyrectedClient,
|
|
612
718
|
DyrectedError,
|
|
613
|
-
|
|
719
|
+
PREVIEW_TOKEN_PARAM,
|
|
720
|
+
createClient,
|
|
721
|
+
getPreviewToken
|
|
614
722
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dyrected/sdk",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.62",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"tsup": "^8.5.1",
|
|
31
31
|
"typescript": "^5.4.5",
|
|
32
32
|
"vitest": "^1.0.0",
|
|
33
|
-
"@dyrected/core": "2.5.
|
|
33
|
+
"@dyrected/core": "2.5.62"
|
|
34
34
|
},
|
|
35
35
|
"license": "BSL-1.1",
|
|
36
36
|
"author": "Busola Okeowo <busolaokemoney@gmail.com>",
|