@dyrected/sdk 2.5.61 → 2.5.63
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 +105 -33
- package/dist/index.d.cts +51 -4
- package/dist/index.d.ts +51 -4
- package/dist/index.js +105 -33
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -186,20 +186,28 @@ var DyrectedClient = class {
|
|
|
186
186
|
}
|
|
187
187
|
async getPreference(key, options) {
|
|
188
188
|
const scopeParam = options?.scope ? `?scope=${options.scope}` : "";
|
|
189
|
-
return this.request(
|
|
189
|
+
return this.request(
|
|
190
|
+
`/api/preferences/${encodeURIComponent(key)}${scopeParam}`
|
|
191
|
+
);
|
|
190
192
|
}
|
|
191
193
|
async setPreference(key, value, options) {
|
|
192
194
|
const scopeParam = options?.scope ? `?scope=${options.scope}` : "";
|
|
193
|
-
return this.request(
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
195
|
+
return this.request(
|
|
196
|
+
`/api/preferences/${encodeURIComponent(key)}${scopeParam}`,
|
|
197
|
+
{
|
|
198
|
+
method: "PUT",
|
|
199
|
+
body: JSON.stringify({ value })
|
|
200
|
+
}
|
|
201
|
+
);
|
|
197
202
|
}
|
|
198
203
|
async deletePreference(key, options) {
|
|
199
204
|
const scopeParam = options?.scope ? `?scope=${options.scope}` : "";
|
|
200
|
-
return this.request(
|
|
201
|
-
|
|
202
|
-
|
|
205
|
+
return this.request(
|
|
206
|
+
`/api/preferences/${encodeURIComponent(key)}${scopeParam}`,
|
|
207
|
+
{
|
|
208
|
+
method: "DELETE"
|
|
209
|
+
}
|
|
210
|
+
);
|
|
203
211
|
}
|
|
204
212
|
/**
|
|
205
213
|
* Fetch draft data for a specific preview token.
|
|
@@ -227,13 +235,22 @@ var DyrectedClient = class {
|
|
|
227
235
|
if (queryArgs.where && typeof queryArgs.where === "object") {
|
|
228
236
|
normalizedArgs.where = JSON.stringify(queryArgs.where);
|
|
229
237
|
}
|
|
230
|
-
const query = stringifyQuery(this.applyDefaultDepth(normalizedArgs), {
|
|
231
|
-
|
|
238
|
+
const query = stringifyQuery(this.applyDefaultDepth(normalizedArgs), {
|
|
239
|
+
addQueryPrefix: true
|
|
240
|
+
});
|
|
241
|
+
const res = await this.request(
|
|
242
|
+
`/api/collections/${collection}${query}`
|
|
243
|
+
);
|
|
232
244
|
if (res.docs.length === 0 && initialData && initialData.length > 0) {
|
|
233
245
|
this.request(`/api/collections/${collection}/seed`, {
|
|
234
246
|
method: "POST",
|
|
235
247
|
body: JSON.stringify({ data: initialData })
|
|
236
|
-
}).catch(
|
|
248
|
+
}).catch(
|
|
249
|
+
(err) => console.error(
|
|
250
|
+
`[dyrected/sdk] Failed to auto-seed collection "${collection}":`,
|
|
251
|
+
err
|
|
252
|
+
)
|
|
253
|
+
);
|
|
237
254
|
return {
|
|
238
255
|
docs: initialData,
|
|
239
256
|
total: initialData.length,
|
|
@@ -257,7 +274,8 @@ var DyrectedClient = class {
|
|
|
257
274
|
(collectionName, queryArgs) => this.find(collectionName, queryArgs)
|
|
258
275
|
);
|
|
259
276
|
if (args) {
|
|
260
|
-
if (args.where && typeof args.where === "object")
|
|
277
|
+
if (args.where && typeof args.where === "object")
|
|
278
|
+
qb.where(args.where);
|
|
261
279
|
if (args.sort) qb.sort(args.sort);
|
|
262
280
|
if (args.limit) qb.limit(args.limit);
|
|
263
281
|
if (args.page) qb.page(args.page);
|
|
@@ -354,7 +372,12 @@ var DyrectedClient = class {
|
|
|
354
372
|
* comment: 'Please add more detail to section 2.',
|
|
355
373
|
* })
|
|
356
374
|
*/
|
|
357
|
-
transition: (id, transitionName, opts) => this.transition(
|
|
375
|
+
transition: (id, transitionName, opts) => this.transition(
|
|
376
|
+
slug,
|
|
377
|
+
id,
|
|
378
|
+
transitionName,
|
|
379
|
+
opts
|
|
380
|
+
),
|
|
358
381
|
/**
|
|
359
382
|
* Fetch the workflow history for a single document — every transition that
|
|
360
383
|
* has ever been performed, newest first.
|
|
@@ -384,7 +407,9 @@ var DyrectedClient = class {
|
|
|
384
407
|
}
|
|
385
408
|
async findOne(collection, id, args = {}) {
|
|
386
409
|
const { initialData, ...queryArgs } = args;
|
|
387
|
-
const query = stringifyQuery(this.applyDefaultDepth(queryArgs), {
|
|
410
|
+
const query = stringifyQuery(this.applyDefaultDepth(queryArgs), {
|
|
411
|
+
addQueryPrefix: true
|
|
412
|
+
});
|
|
388
413
|
try {
|
|
389
414
|
return await this.request(`/api/collections/${collection}/${id}${query}`);
|
|
390
415
|
} catch (err) {
|
|
@@ -393,7 +418,10 @@ var DyrectedClient = class {
|
|
|
393
418
|
method: "POST",
|
|
394
419
|
body: JSON.stringify({ data: [{ id, ...initialData }] })
|
|
395
420
|
}).catch(
|
|
396
|
-
(err2) => console.error(
|
|
421
|
+
(err2) => console.error(
|
|
422
|
+
`[dyrected/sdk] Failed to auto-seed document "${id}" in collection "${collection}":`,
|
|
423
|
+
err2
|
|
424
|
+
)
|
|
397
425
|
);
|
|
398
426
|
return initialData;
|
|
399
427
|
}
|
|
@@ -432,10 +460,13 @@ var DyrectedClient = class {
|
|
|
432
460
|
* const updated = await client.transition('posts', postId, 'publish')
|
|
433
461
|
*/
|
|
434
462
|
async transition(collection, id, transitionName, opts = {}) {
|
|
435
|
-
return this.request(
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
463
|
+
return this.request(
|
|
464
|
+
`/api/collections/${collection}/${id}/transitions/${encodeURIComponent(transitionName)}`,
|
|
465
|
+
{
|
|
466
|
+
method: "POST",
|
|
467
|
+
body: JSON.stringify(opts)
|
|
468
|
+
}
|
|
469
|
+
);
|
|
439
470
|
}
|
|
440
471
|
/**
|
|
441
472
|
* Fetch the workflow history for a document.
|
|
@@ -448,7 +479,9 @@ var DyrectedClient = class {
|
|
|
448
479
|
*/
|
|
449
480
|
async workflowHistory(collection, id, args = {}) {
|
|
450
481
|
const query = args.limit ? `?limit=${args.limit}` : "";
|
|
451
|
-
return this.request(
|
|
482
|
+
return this.request(
|
|
483
|
+
`/api/collections/${collection}/${id}/workflow-history${query}`
|
|
484
|
+
);
|
|
452
485
|
}
|
|
453
486
|
/**
|
|
454
487
|
* Fetch audit entries across every audited collection the current caller can read.
|
|
@@ -456,7 +489,9 @@ var DyrectedClient = class {
|
|
|
456
489
|
* Sends `GET /api/audit`.
|
|
457
490
|
*/
|
|
458
491
|
async audit(args = {}) {
|
|
459
|
-
const query = stringifyQuery(normalizeQueryArgs(args), {
|
|
492
|
+
const query = stringifyQuery(normalizeQueryArgs(args), {
|
|
493
|
+
addQueryPrefix: true
|
|
494
|
+
});
|
|
460
495
|
return this.request(`/api/audit${query}`);
|
|
461
496
|
}
|
|
462
497
|
/**
|
|
@@ -465,7 +500,9 @@ var DyrectedClient = class {
|
|
|
465
500
|
* Sends `GET /api/collections/:collection/__audit`.
|
|
466
501
|
*/
|
|
467
502
|
async collectionAudit(collection, args = {}) {
|
|
468
|
-
const query = stringifyQuery(normalizeQueryArgs(args), {
|
|
503
|
+
const query = stringifyQuery(normalizeQueryArgs(args), {
|
|
504
|
+
addQueryPrefix: true
|
|
505
|
+
});
|
|
469
506
|
return this.request(`/api/collections/${collection}/__audit${query}`);
|
|
470
507
|
}
|
|
471
508
|
async deleteMany(collection, ids) {
|
|
@@ -476,7 +513,9 @@ var DyrectedClient = class {
|
|
|
476
513
|
}
|
|
477
514
|
async getGlobal(slug, args = {}) {
|
|
478
515
|
const { initialData, ...queryArgs } = args;
|
|
479
|
-
const query = stringifyQuery(this.applyDefaultDepth(queryArgs), {
|
|
516
|
+
const query = stringifyQuery(this.applyDefaultDepth(queryArgs), {
|
|
517
|
+
addQueryPrefix: true
|
|
518
|
+
});
|
|
480
519
|
try {
|
|
481
520
|
const res = await this.request(`/api/globals/${slug}${query}`);
|
|
482
521
|
if ((!res || isFunctionallyEmpty(res)) && !isFunctionallyEmpty(initialData)) {
|
|
@@ -484,7 +523,12 @@ var DyrectedClient = class {
|
|
|
484
523
|
this.request(`/api/globals/${slug}/seed`, {
|
|
485
524
|
method: "POST",
|
|
486
525
|
body: JSON.stringify({ data: initialData })
|
|
487
|
-
}).catch(
|
|
526
|
+
}).catch(
|
|
527
|
+
(err) => console.error(
|
|
528
|
+
`[dyrected/sdk] Failed to auto-seed global "${slug}":`,
|
|
529
|
+
err
|
|
530
|
+
)
|
|
531
|
+
);
|
|
488
532
|
return initialData;
|
|
489
533
|
}
|
|
490
534
|
return res;
|
|
@@ -493,7 +537,12 @@ var DyrectedClient = class {
|
|
|
493
537
|
this.request(`/api/globals/${slug}/seed`, {
|
|
494
538
|
method: "POST",
|
|
495
539
|
body: JSON.stringify({ data: initialData })
|
|
496
|
-
}).catch(
|
|
540
|
+
}).catch(
|
|
541
|
+
(err2) => console.error(
|
|
542
|
+
`[dyrected/sdk] Failed to auto-seed global "${slug}":`,
|
|
543
|
+
err2
|
|
544
|
+
)
|
|
545
|
+
);
|
|
497
546
|
return initialData;
|
|
498
547
|
}
|
|
499
548
|
throw err;
|
|
@@ -506,8 +555,13 @@ var DyrectedClient = class {
|
|
|
506
555
|
});
|
|
507
556
|
}
|
|
508
557
|
async listMedia(args = {}, collection = "media") {
|
|
509
|
-
const query = stringifyQuery(
|
|
510
|
-
|
|
558
|
+
const query = stringifyQuery(
|
|
559
|
+
this.applyDefaultDepth(normalizeQueryArgs(args)),
|
|
560
|
+
{ addQueryPrefix: true }
|
|
561
|
+
);
|
|
562
|
+
return this.request(
|
|
563
|
+
`/api/collections/${collection}${query}`
|
|
564
|
+
);
|
|
511
565
|
}
|
|
512
566
|
/** @deprecated Use client.collection('media').upload(file, data) instead */
|
|
513
567
|
async uploadMedia(file, collection = "media") {
|
|
@@ -552,7 +606,9 @@ var DyrectedClient = class {
|
|
|
552
606
|
reject(new DyrectedError("Upload aborted", 0));
|
|
553
607
|
return;
|
|
554
608
|
}
|
|
555
|
-
options.signal.addEventListener("abort", () => xhr.abort(), {
|
|
609
|
+
options.signal.addEventListener("abort", () => xhr.abort(), {
|
|
610
|
+
once: true
|
|
611
|
+
});
|
|
556
612
|
}
|
|
557
613
|
xhr.upload.onprogress = (event) => {
|
|
558
614
|
if (event.lengthComputable) {
|
|
@@ -580,7 +636,13 @@ var DyrectedClient = class {
|
|
|
580
636
|
})
|
|
581
637
|
);
|
|
582
638
|
}
|
|
583
|
-
reject(
|
|
639
|
+
reject(
|
|
640
|
+
new DyrectedError(
|
|
641
|
+
body.message || `Request failed with status ${xhr.status}`,
|
|
642
|
+
xhr.status,
|
|
643
|
+
body.code
|
|
644
|
+
)
|
|
645
|
+
);
|
|
584
646
|
};
|
|
585
647
|
xhr.onerror = () => reject(new DyrectedError("Network error during upload", 0));
|
|
586
648
|
xhr.onabort = () => reject(new DyrectedError("Upload aborted", 0));
|
|
@@ -599,7 +661,9 @@ var DyrectedClient = class {
|
|
|
599
661
|
});
|
|
600
662
|
if (res && typeof res.ok === "boolean") {
|
|
601
663
|
if (!res.ok) {
|
|
602
|
-
const body = await res.json().catch(() => ({
|
|
664
|
+
const body = await res.json().catch(() => ({
|
|
665
|
+
message: "Unknown error"
|
|
666
|
+
}));
|
|
603
667
|
if (res.status === 429 && typeof window !== "undefined") {
|
|
604
668
|
window.dispatchEvent(
|
|
605
669
|
new CustomEvent("dyrected:rate-limit", {
|
|
@@ -608,7 +672,11 @@ var DyrectedClient = class {
|
|
|
608
672
|
);
|
|
609
673
|
}
|
|
610
674
|
console.log("[DyrectedError]", body, res.status);
|
|
611
|
-
throw new DyrectedError(
|
|
675
|
+
throw new DyrectedError(
|
|
676
|
+
body.message || `Request failed with status ${res.status}`,
|
|
677
|
+
res.status,
|
|
678
|
+
body.code
|
|
679
|
+
);
|
|
612
680
|
}
|
|
613
681
|
return res.json();
|
|
614
682
|
}
|
|
@@ -623,7 +691,9 @@ function getPreviewToken(search) {
|
|
|
623
691
|
if (!search) return null;
|
|
624
692
|
let value;
|
|
625
693
|
if (typeof search === "string") {
|
|
626
|
-
value = new URLSearchParams(
|
|
694
|
+
value = new URLSearchParams(
|
|
695
|
+
search.startsWith("?") ? search.slice(1) : search
|
|
696
|
+
).get(PREVIEW_TOKEN_PARAM);
|
|
627
697
|
} else if (search instanceof URLSearchParams) {
|
|
628
698
|
value = search.get(PREVIEW_TOKEN_PARAM);
|
|
629
699
|
} else {
|
|
@@ -641,7 +711,9 @@ function isFunctionallyEmpty(obj) {
|
|
|
641
711
|
if (typeof obj === "object") {
|
|
642
712
|
const keys = Object.keys(obj);
|
|
643
713
|
if (keys.length === 0) return true;
|
|
644
|
-
return keys.every(
|
|
714
|
+
return keys.every(
|
|
715
|
+
(key) => isFunctionallyEmpty(obj[key])
|
|
716
|
+
);
|
|
645
717
|
}
|
|
646
718
|
return false;
|
|
647
719
|
}
|
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;
|
|
@@ -140,6 +141,52 @@ interface BaseSchema {
|
|
|
140
141
|
collections: Record<string, UnknownRecord>;
|
|
141
142
|
globals: Record<string, UnknownRecord>;
|
|
142
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;
|
|
143
190
|
/**
|
|
144
191
|
* Options for file uploads.
|
|
145
192
|
* When `onProgress` is provided and the runtime supports XMLHttpRequest (browsers),
|
|
@@ -152,7 +199,7 @@ interface UploadOptions {
|
|
|
152
199
|
/** Abort the in-flight upload. */
|
|
153
200
|
signal?: AbortSignal;
|
|
154
201
|
}
|
|
155
|
-
declare class DyrectedClient<TSchema extends
|
|
202
|
+
declare class DyrectedClient<TSchema extends SchemaShape = RegisteredSchema> {
|
|
156
203
|
private baseUrl;
|
|
157
204
|
private headers;
|
|
158
205
|
private fetch;
|
|
@@ -436,7 +483,7 @@ declare class DyrectedClient<TSchema extends BaseSchema = BaseSchema> {
|
|
|
436
483
|
}>;
|
|
437
484
|
private request;
|
|
438
485
|
}
|
|
439
|
-
declare function createClient<TSchema extends
|
|
486
|
+
declare function createClient<TSchema extends SchemaShape = RegisteredSchema>(config: DyrectedClientConfig): DyrectedClient<TSchema>;
|
|
440
487
|
/**
|
|
441
488
|
* The query-string parameter the Admin appends to a preview URL in
|
|
442
489
|
* `previewMode: "token"`. Read it on your frontend to decide whether to fetch
|
|
@@ -456,4 +503,4 @@ declare const PREVIEW_TOKEN_PARAM = "dyPreview";
|
|
|
456
503
|
*/
|
|
457
504
|
declare function getPreviewToken(search: string | URLSearchParams | Record<string, unknown> | undefined | null): string | null;
|
|
458
505
|
|
|
459
|
-
export { type AuditEntry, type BaseSchema, DyrectedClient, type DyrectedClientConfig, DyrectedError, type InferSchema, PREVIEW_TOKEN_PARAM, type TransitionOptions, type UploadOptions, type WorkflowDocument, type WorkflowHistoryEntry, createClient, getPreviewToken };
|
|
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;
|
|
@@ -140,6 +141,52 @@ interface BaseSchema {
|
|
|
140
141
|
collections: Record<string, UnknownRecord>;
|
|
141
142
|
globals: Record<string, UnknownRecord>;
|
|
142
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;
|
|
143
190
|
/**
|
|
144
191
|
* Options for file uploads.
|
|
145
192
|
* When `onProgress` is provided and the runtime supports XMLHttpRequest (browsers),
|
|
@@ -152,7 +199,7 @@ interface UploadOptions {
|
|
|
152
199
|
/** Abort the in-flight upload. */
|
|
153
200
|
signal?: AbortSignal;
|
|
154
201
|
}
|
|
155
|
-
declare class DyrectedClient<TSchema extends
|
|
202
|
+
declare class DyrectedClient<TSchema extends SchemaShape = RegisteredSchema> {
|
|
156
203
|
private baseUrl;
|
|
157
204
|
private headers;
|
|
158
205
|
private fetch;
|
|
@@ -436,7 +483,7 @@ declare class DyrectedClient<TSchema extends BaseSchema = BaseSchema> {
|
|
|
436
483
|
}>;
|
|
437
484
|
private request;
|
|
438
485
|
}
|
|
439
|
-
declare function createClient<TSchema extends
|
|
486
|
+
declare function createClient<TSchema extends SchemaShape = RegisteredSchema>(config: DyrectedClientConfig): DyrectedClient<TSchema>;
|
|
440
487
|
/**
|
|
441
488
|
* The query-string parameter the Admin appends to a preview URL in
|
|
442
489
|
* `previewMode: "token"`. Read it on your frontend to decide whether to fetch
|
|
@@ -456,4 +503,4 @@ declare const PREVIEW_TOKEN_PARAM = "dyPreview";
|
|
|
456
503
|
*/
|
|
457
504
|
declare function getPreviewToken(search: string | URLSearchParams | Record<string, unknown> | undefined | null): string | null;
|
|
458
505
|
|
|
459
|
-
export { type AuditEntry, type BaseSchema, DyrectedClient, type DyrectedClientConfig, DyrectedError, type InferSchema, PREVIEW_TOKEN_PARAM, type TransitionOptions, type UploadOptions, type WorkflowDocument, type WorkflowHistoryEntry, createClient, getPreviewToken };
|
|
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
|
@@ -156,20 +156,28 @@ var DyrectedClient = class {
|
|
|
156
156
|
}
|
|
157
157
|
async getPreference(key, options) {
|
|
158
158
|
const scopeParam = options?.scope ? `?scope=${options.scope}` : "";
|
|
159
|
-
return this.request(
|
|
159
|
+
return this.request(
|
|
160
|
+
`/api/preferences/${encodeURIComponent(key)}${scopeParam}`
|
|
161
|
+
);
|
|
160
162
|
}
|
|
161
163
|
async setPreference(key, value, options) {
|
|
162
164
|
const scopeParam = options?.scope ? `?scope=${options.scope}` : "";
|
|
163
|
-
return this.request(
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
165
|
+
return this.request(
|
|
166
|
+
`/api/preferences/${encodeURIComponent(key)}${scopeParam}`,
|
|
167
|
+
{
|
|
168
|
+
method: "PUT",
|
|
169
|
+
body: JSON.stringify({ value })
|
|
170
|
+
}
|
|
171
|
+
);
|
|
167
172
|
}
|
|
168
173
|
async deletePreference(key, options) {
|
|
169
174
|
const scopeParam = options?.scope ? `?scope=${options.scope}` : "";
|
|
170
|
-
return this.request(
|
|
171
|
-
|
|
172
|
-
|
|
175
|
+
return this.request(
|
|
176
|
+
`/api/preferences/${encodeURIComponent(key)}${scopeParam}`,
|
|
177
|
+
{
|
|
178
|
+
method: "DELETE"
|
|
179
|
+
}
|
|
180
|
+
);
|
|
173
181
|
}
|
|
174
182
|
/**
|
|
175
183
|
* Fetch draft data for a specific preview token.
|
|
@@ -197,13 +205,22 @@ var DyrectedClient = class {
|
|
|
197
205
|
if (queryArgs.where && typeof queryArgs.where === "object") {
|
|
198
206
|
normalizedArgs.where = JSON.stringify(queryArgs.where);
|
|
199
207
|
}
|
|
200
|
-
const query = stringifyQuery(this.applyDefaultDepth(normalizedArgs), {
|
|
201
|
-
|
|
208
|
+
const query = stringifyQuery(this.applyDefaultDepth(normalizedArgs), {
|
|
209
|
+
addQueryPrefix: true
|
|
210
|
+
});
|
|
211
|
+
const res = await this.request(
|
|
212
|
+
`/api/collections/${collection}${query}`
|
|
213
|
+
);
|
|
202
214
|
if (res.docs.length === 0 && initialData && initialData.length > 0) {
|
|
203
215
|
this.request(`/api/collections/${collection}/seed`, {
|
|
204
216
|
method: "POST",
|
|
205
217
|
body: JSON.stringify({ data: initialData })
|
|
206
|
-
}).catch(
|
|
218
|
+
}).catch(
|
|
219
|
+
(err) => console.error(
|
|
220
|
+
`[dyrected/sdk] Failed to auto-seed collection "${collection}":`,
|
|
221
|
+
err
|
|
222
|
+
)
|
|
223
|
+
);
|
|
207
224
|
return {
|
|
208
225
|
docs: initialData,
|
|
209
226
|
total: initialData.length,
|
|
@@ -227,7 +244,8 @@ var DyrectedClient = class {
|
|
|
227
244
|
(collectionName, queryArgs) => this.find(collectionName, queryArgs)
|
|
228
245
|
);
|
|
229
246
|
if (args) {
|
|
230
|
-
if (args.where && typeof args.where === "object")
|
|
247
|
+
if (args.where && typeof args.where === "object")
|
|
248
|
+
qb.where(args.where);
|
|
231
249
|
if (args.sort) qb.sort(args.sort);
|
|
232
250
|
if (args.limit) qb.limit(args.limit);
|
|
233
251
|
if (args.page) qb.page(args.page);
|
|
@@ -324,7 +342,12 @@ var DyrectedClient = class {
|
|
|
324
342
|
* comment: 'Please add more detail to section 2.',
|
|
325
343
|
* })
|
|
326
344
|
*/
|
|
327
|
-
transition: (id, transitionName, opts) => this.transition(
|
|
345
|
+
transition: (id, transitionName, opts) => this.transition(
|
|
346
|
+
slug,
|
|
347
|
+
id,
|
|
348
|
+
transitionName,
|
|
349
|
+
opts
|
|
350
|
+
),
|
|
328
351
|
/**
|
|
329
352
|
* Fetch the workflow history for a single document — every transition that
|
|
330
353
|
* has ever been performed, newest first.
|
|
@@ -354,7 +377,9 @@ var DyrectedClient = class {
|
|
|
354
377
|
}
|
|
355
378
|
async findOne(collection, id, args = {}) {
|
|
356
379
|
const { initialData, ...queryArgs } = args;
|
|
357
|
-
const query = stringifyQuery(this.applyDefaultDepth(queryArgs), {
|
|
380
|
+
const query = stringifyQuery(this.applyDefaultDepth(queryArgs), {
|
|
381
|
+
addQueryPrefix: true
|
|
382
|
+
});
|
|
358
383
|
try {
|
|
359
384
|
return await this.request(`/api/collections/${collection}/${id}${query}`);
|
|
360
385
|
} catch (err) {
|
|
@@ -363,7 +388,10 @@ var DyrectedClient = class {
|
|
|
363
388
|
method: "POST",
|
|
364
389
|
body: JSON.stringify({ data: [{ id, ...initialData }] })
|
|
365
390
|
}).catch(
|
|
366
|
-
(err2) => console.error(
|
|
391
|
+
(err2) => console.error(
|
|
392
|
+
`[dyrected/sdk] Failed to auto-seed document "${id}" in collection "${collection}":`,
|
|
393
|
+
err2
|
|
394
|
+
)
|
|
367
395
|
);
|
|
368
396
|
return initialData;
|
|
369
397
|
}
|
|
@@ -402,10 +430,13 @@ var DyrectedClient = class {
|
|
|
402
430
|
* const updated = await client.transition('posts', postId, 'publish')
|
|
403
431
|
*/
|
|
404
432
|
async transition(collection, id, transitionName, opts = {}) {
|
|
405
|
-
return this.request(
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
433
|
+
return this.request(
|
|
434
|
+
`/api/collections/${collection}/${id}/transitions/${encodeURIComponent(transitionName)}`,
|
|
435
|
+
{
|
|
436
|
+
method: "POST",
|
|
437
|
+
body: JSON.stringify(opts)
|
|
438
|
+
}
|
|
439
|
+
);
|
|
409
440
|
}
|
|
410
441
|
/**
|
|
411
442
|
* Fetch the workflow history for a document.
|
|
@@ -418,7 +449,9 @@ var DyrectedClient = class {
|
|
|
418
449
|
*/
|
|
419
450
|
async workflowHistory(collection, id, args = {}) {
|
|
420
451
|
const query = args.limit ? `?limit=${args.limit}` : "";
|
|
421
|
-
return this.request(
|
|
452
|
+
return this.request(
|
|
453
|
+
`/api/collections/${collection}/${id}/workflow-history${query}`
|
|
454
|
+
);
|
|
422
455
|
}
|
|
423
456
|
/**
|
|
424
457
|
* Fetch audit entries across every audited collection the current caller can read.
|
|
@@ -426,7 +459,9 @@ var DyrectedClient = class {
|
|
|
426
459
|
* Sends `GET /api/audit`.
|
|
427
460
|
*/
|
|
428
461
|
async audit(args = {}) {
|
|
429
|
-
const query = stringifyQuery(normalizeQueryArgs(args), {
|
|
462
|
+
const query = stringifyQuery(normalizeQueryArgs(args), {
|
|
463
|
+
addQueryPrefix: true
|
|
464
|
+
});
|
|
430
465
|
return this.request(`/api/audit${query}`);
|
|
431
466
|
}
|
|
432
467
|
/**
|
|
@@ -435,7 +470,9 @@ var DyrectedClient = class {
|
|
|
435
470
|
* Sends `GET /api/collections/:collection/__audit`.
|
|
436
471
|
*/
|
|
437
472
|
async collectionAudit(collection, args = {}) {
|
|
438
|
-
const query = stringifyQuery(normalizeQueryArgs(args), {
|
|
473
|
+
const query = stringifyQuery(normalizeQueryArgs(args), {
|
|
474
|
+
addQueryPrefix: true
|
|
475
|
+
});
|
|
439
476
|
return this.request(`/api/collections/${collection}/__audit${query}`);
|
|
440
477
|
}
|
|
441
478
|
async deleteMany(collection, ids) {
|
|
@@ -446,7 +483,9 @@ var DyrectedClient = class {
|
|
|
446
483
|
}
|
|
447
484
|
async getGlobal(slug, args = {}) {
|
|
448
485
|
const { initialData, ...queryArgs } = args;
|
|
449
|
-
const query = stringifyQuery(this.applyDefaultDepth(queryArgs), {
|
|
486
|
+
const query = stringifyQuery(this.applyDefaultDepth(queryArgs), {
|
|
487
|
+
addQueryPrefix: true
|
|
488
|
+
});
|
|
450
489
|
try {
|
|
451
490
|
const res = await this.request(`/api/globals/${slug}${query}`);
|
|
452
491
|
if ((!res || isFunctionallyEmpty(res)) && !isFunctionallyEmpty(initialData)) {
|
|
@@ -454,7 +493,12 @@ var DyrectedClient = class {
|
|
|
454
493
|
this.request(`/api/globals/${slug}/seed`, {
|
|
455
494
|
method: "POST",
|
|
456
495
|
body: JSON.stringify({ data: initialData })
|
|
457
|
-
}).catch(
|
|
496
|
+
}).catch(
|
|
497
|
+
(err) => console.error(
|
|
498
|
+
`[dyrected/sdk] Failed to auto-seed global "${slug}":`,
|
|
499
|
+
err
|
|
500
|
+
)
|
|
501
|
+
);
|
|
458
502
|
return initialData;
|
|
459
503
|
}
|
|
460
504
|
return res;
|
|
@@ -463,7 +507,12 @@ var DyrectedClient = class {
|
|
|
463
507
|
this.request(`/api/globals/${slug}/seed`, {
|
|
464
508
|
method: "POST",
|
|
465
509
|
body: JSON.stringify({ data: initialData })
|
|
466
|
-
}).catch(
|
|
510
|
+
}).catch(
|
|
511
|
+
(err2) => console.error(
|
|
512
|
+
`[dyrected/sdk] Failed to auto-seed global "${slug}":`,
|
|
513
|
+
err2
|
|
514
|
+
)
|
|
515
|
+
);
|
|
467
516
|
return initialData;
|
|
468
517
|
}
|
|
469
518
|
throw err;
|
|
@@ -476,8 +525,13 @@ var DyrectedClient = class {
|
|
|
476
525
|
});
|
|
477
526
|
}
|
|
478
527
|
async listMedia(args = {}, collection = "media") {
|
|
479
|
-
const query = stringifyQuery(
|
|
480
|
-
|
|
528
|
+
const query = stringifyQuery(
|
|
529
|
+
this.applyDefaultDepth(normalizeQueryArgs(args)),
|
|
530
|
+
{ addQueryPrefix: true }
|
|
531
|
+
);
|
|
532
|
+
return this.request(
|
|
533
|
+
`/api/collections/${collection}${query}`
|
|
534
|
+
);
|
|
481
535
|
}
|
|
482
536
|
/** @deprecated Use client.collection('media').upload(file, data) instead */
|
|
483
537
|
async uploadMedia(file, collection = "media") {
|
|
@@ -522,7 +576,9 @@ var DyrectedClient = class {
|
|
|
522
576
|
reject(new DyrectedError("Upload aborted", 0));
|
|
523
577
|
return;
|
|
524
578
|
}
|
|
525
|
-
options.signal.addEventListener("abort", () => xhr.abort(), {
|
|
579
|
+
options.signal.addEventListener("abort", () => xhr.abort(), {
|
|
580
|
+
once: true
|
|
581
|
+
});
|
|
526
582
|
}
|
|
527
583
|
xhr.upload.onprogress = (event) => {
|
|
528
584
|
if (event.lengthComputable) {
|
|
@@ -550,7 +606,13 @@ var DyrectedClient = class {
|
|
|
550
606
|
})
|
|
551
607
|
);
|
|
552
608
|
}
|
|
553
|
-
reject(
|
|
609
|
+
reject(
|
|
610
|
+
new DyrectedError(
|
|
611
|
+
body.message || `Request failed with status ${xhr.status}`,
|
|
612
|
+
xhr.status,
|
|
613
|
+
body.code
|
|
614
|
+
)
|
|
615
|
+
);
|
|
554
616
|
};
|
|
555
617
|
xhr.onerror = () => reject(new DyrectedError("Network error during upload", 0));
|
|
556
618
|
xhr.onabort = () => reject(new DyrectedError("Upload aborted", 0));
|
|
@@ -569,7 +631,9 @@ var DyrectedClient = class {
|
|
|
569
631
|
});
|
|
570
632
|
if (res && typeof res.ok === "boolean") {
|
|
571
633
|
if (!res.ok) {
|
|
572
|
-
const body = await res.json().catch(() => ({
|
|
634
|
+
const body = await res.json().catch(() => ({
|
|
635
|
+
message: "Unknown error"
|
|
636
|
+
}));
|
|
573
637
|
if (res.status === 429 && typeof window !== "undefined") {
|
|
574
638
|
window.dispatchEvent(
|
|
575
639
|
new CustomEvent("dyrected:rate-limit", {
|
|
@@ -578,7 +642,11 @@ var DyrectedClient = class {
|
|
|
578
642
|
);
|
|
579
643
|
}
|
|
580
644
|
console.log("[DyrectedError]", body, res.status);
|
|
581
|
-
throw new DyrectedError(
|
|
645
|
+
throw new DyrectedError(
|
|
646
|
+
body.message || `Request failed with status ${res.status}`,
|
|
647
|
+
res.status,
|
|
648
|
+
body.code
|
|
649
|
+
);
|
|
582
650
|
}
|
|
583
651
|
return res.json();
|
|
584
652
|
}
|
|
@@ -593,7 +661,9 @@ function getPreviewToken(search) {
|
|
|
593
661
|
if (!search) return null;
|
|
594
662
|
let value;
|
|
595
663
|
if (typeof search === "string") {
|
|
596
|
-
value = new URLSearchParams(
|
|
664
|
+
value = new URLSearchParams(
|
|
665
|
+
search.startsWith("?") ? search.slice(1) : search
|
|
666
|
+
).get(PREVIEW_TOKEN_PARAM);
|
|
597
667
|
} else if (search instanceof URLSearchParams) {
|
|
598
668
|
value = search.get(PREVIEW_TOKEN_PARAM);
|
|
599
669
|
} else {
|
|
@@ -611,7 +681,9 @@ function isFunctionallyEmpty(obj) {
|
|
|
611
681
|
if (typeof obj === "object") {
|
|
612
682
|
const keys = Object.keys(obj);
|
|
613
683
|
if (keys.length === 0) return true;
|
|
614
|
-
return keys.every(
|
|
684
|
+
return keys.every(
|
|
685
|
+
(key) => isFunctionallyEmpty(obj[key])
|
|
686
|
+
);
|
|
615
687
|
}
|
|
616
688
|
return false;
|
|
617
689
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dyrected/sdk",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.63",
|
|
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.63"
|
|
34
34
|
},
|
|
35
35
|
"license": "BSL-1.1",
|
|
36
36
|
"author": "Busola Okeowo <busolaokemoney@gmail.com>",
|