@dyrected/sdk 0.0.1

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/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # @dyrected/sdk
2
+
3
+ This is the sdk package/app for the Dyrected ecosystem.
package/dist/index.cjs ADDED
@@ -0,0 +1,639 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ DyrectedClient: () => DyrectedClient,
34
+ createClient: () => createClient
35
+ });
36
+ module.exports = __toCommonJS(index_exports);
37
+ var import_qs = __toESM(require("qs"), 1);
38
+
39
+ // ../../node_modules/.pnpm/hono@4.12.18/node_modules/hono/dist/request/constants.js
40
+ var GET_MATCH_RESULT = /* @__PURE__ */ Symbol();
41
+
42
+ // ../../node_modules/.pnpm/hono@4.12.18/node_modules/hono/dist/utils/body.js
43
+ var parseBody = async (request, options = /* @__PURE__ */ Object.create(null)) => {
44
+ const { all = false, dot = false } = options;
45
+ const headers = request instanceof HonoRequest ? request.raw.headers : request.headers;
46
+ const contentType = headers.get("Content-Type");
47
+ if (contentType?.startsWith("multipart/form-data") || contentType?.startsWith("application/x-www-form-urlencoded")) {
48
+ return parseFormData(request, { all, dot });
49
+ }
50
+ return {};
51
+ };
52
+ async function parseFormData(request, options) {
53
+ const formData = await request.formData();
54
+ if (formData) {
55
+ return convertFormDataToBodyData(formData, options);
56
+ }
57
+ return {};
58
+ }
59
+ function convertFormDataToBodyData(formData, options) {
60
+ const form = /* @__PURE__ */ Object.create(null);
61
+ formData.forEach((value, key) => {
62
+ const shouldParseAllValues = options.all || key.endsWith("[]");
63
+ if (!shouldParseAllValues) {
64
+ form[key] = value;
65
+ } else {
66
+ handleParsingAllValues(form, key, value);
67
+ }
68
+ });
69
+ if (options.dot) {
70
+ Object.entries(form).forEach(([key, value]) => {
71
+ const shouldParseDotValues = key.includes(".");
72
+ if (shouldParseDotValues) {
73
+ handleParsingNestedValues(form, key, value);
74
+ delete form[key];
75
+ }
76
+ });
77
+ }
78
+ return form;
79
+ }
80
+ var handleParsingAllValues = (form, key, value) => {
81
+ if (form[key] !== void 0) {
82
+ if (Array.isArray(form[key])) {
83
+ ;
84
+ form[key].push(value);
85
+ } else {
86
+ form[key] = [form[key], value];
87
+ }
88
+ } else {
89
+ if (!key.endsWith("[]")) {
90
+ form[key] = value;
91
+ } else {
92
+ form[key] = [value];
93
+ }
94
+ }
95
+ };
96
+ var handleParsingNestedValues = (form, key, value) => {
97
+ if (/(?:^|\.)__proto__\./.test(key)) {
98
+ return;
99
+ }
100
+ let nestedForm = form;
101
+ const keys = key.split(".");
102
+ keys.forEach((key2, index) => {
103
+ if (index === keys.length - 1) {
104
+ nestedForm[key2] = value;
105
+ } else {
106
+ if (!nestedForm[key2] || typeof nestedForm[key2] !== "object" || Array.isArray(nestedForm[key2]) || nestedForm[key2] instanceof File) {
107
+ nestedForm[key2] = /* @__PURE__ */ Object.create(null);
108
+ }
109
+ nestedForm = nestedForm[key2];
110
+ }
111
+ });
112
+ };
113
+
114
+ // ../../node_modules/.pnpm/hono@4.12.18/node_modules/hono/dist/utils/url.js
115
+ var tryDecode = (str, decoder) => {
116
+ try {
117
+ return decoder(str);
118
+ } catch {
119
+ return str.replace(/(?:%[0-9A-Fa-f]{2})+/g, (match2) => {
120
+ try {
121
+ return decoder(match2);
122
+ } catch {
123
+ return match2;
124
+ }
125
+ });
126
+ }
127
+ };
128
+ var _decodeURI = (value) => {
129
+ if (!/[%+]/.test(value)) {
130
+ return value;
131
+ }
132
+ if (value.indexOf("+") !== -1) {
133
+ value = value.replace(/\+/g, " ");
134
+ }
135
+ return value.indexOf("%") !== -1 ? tryDecode(value, decodeURIComponent_) : value;
136
+ };
137
+ var _getQueryParam = (url, key, multiple) => {
138
+ let encoded;
139
+ if (!multiple && key && !/[%+]/.test(key)) {
140
+ let keyIndex2 = url.indexOf("?", 8);
141
+ if (keyIndex2 === -1) {
142
+ return void 0;
143
+ }
144
+ if (!url.startsWith(key, keyIndex2 + 1)) {
145
+ keyIndex2 = url.indexOf(`&${key}`, keyIndex2 + 1);
146
+ }
147
+ while (keyIndex2 !== -1) {
148
+ const trailingKeyCode = url.charCodeAt(keyIndex2 + key.length + 1);
149
+ if (trailingKeyCode === 61) {
150
+ const valueIndex = keyIndex2 + key.length + 2;
151
+ const endIndex = url.indexOf("&", valueIndex);
152
+ return _decodeURI(url.slice(valueIndex, endIndex === -1 ? void 0 : endIndex));
153
+ } else if (trailingKeyCode == 38 || isNaN(trailingKeyCode)) {
154
+ return "";
155
+ }
156
+ keyIndex2 = url.indexOf(`&${key}`, keyIndex2 + 1);
157
+ }
158
+ encoded = /[%+]/.test(url);
159
+ if (!encoded) {
160
+ return void 0;
161
+ }
162
+ }
163
+ const results = {};
164
+ encoded ??= /[%+]/.test(url);
165
+ let keyIndex = url.indexOf("?", 8);
166
+ while (keyIndex !== -1) {
167
+ const nextKeyIndex = url.indexOf("&", keyIndex + 1);
168
+ let valueIndex = url.indexOf("=", keyIndex);
169
+ if (valueIndex > nextKeyIndex && nextKeyIndex !== -1) {
170
+ valueIndex = -1;
171
+ }
172
+ let name = url.slice(
173
+ keyIndex + 1,
174
+ valueIndex === -1 ? nextKeyIndex === -1 ? void 0 : nextKeyIndex : valueIndex
175
+ );
176
+ if (encoded) {
177
+ name = _decodeURI(name);
178
+ }
179
+ keyIndex = nextKeyIndex;
180
+ if (name === "") {
181
+ continue;
182
+ }
183
+ let value;
184
+ if (valueIndex === -1) {
185
+ value = "";
186
+ } else {
187
+ value = url.slice(valueIndex + 1, nextKeyIndex === -1 ? void 0 : nextKeyIndex);
188
+ if (encoded) {
189
+ value = _decodeURI(value);
190
+ }
191
+ }
192
+ if (multiple) {
193
+ if (!(results[name] && Array.isArray(results[name]))) {
194
+ results[name] = [];
195
+ }
196
+ ;
197
+ results[name].push(value);
198
+ } else {
199
+ results[name] ??= value;
200
+ }
201
+ }
202
+ return key ? results[key] : results;
203
+ };
204
+ var getQueryParam = _getQueryParam;
205
+ var getQueryParams = (url, key) => {
206
+ return _getQueryParam(url, key, true);
207
+ };
208
+ var decodeURIComponent_ = decodeURIComponent;
209
+
210
+ // ../../node_modules/.pnpm/hono@4.12.18/node_modules/hono/dist/request.js
211
+ var tryDecodeURIComponent = (str) => tryDecode(str, decodeURIComponent_);
212
+ var HonoRequest = class {
213
+ /**
214
+ * `.raw` can get the raw Request object.
215
+ *
216
+ * @see {@link https://hono.dev/docs/api/request#raw}
217
+ *
218
+ * @example
219
+ * ```ts
220
+ * // For Cloudflare Workers
221
+ * app.post('/', async (c) => {
222
+ * const metadata = c.req.raw.cf?.hostMetadata?
223
+ * ...
224
+ * })
225
+ * ```
226
+ */
227
+ raw;
228
+ #validatedData;
229
+ // Short name of validatedData
230
+ #matchResult;
231
+ routeIndex = 0;
232
+ /**
233
+ * `.path` can get the pathname of the request.
234
+ *
235
+ * @see {@link https://hono.dev/docs/api/request#path}
236
+ *
237
+ * @example
238
+ * ```ts
239
+ * app.get('/about/me', (c) => {
240
+ * const pathname = c.req.path // `/about/me`
241
+ * })
242
+ * ```
243
+ */
244
+ path;
245
+ bodyCache = {};
246
+ constructor(request, path = "/", matchResult = [[]]) {
247
+ this.raw = request;
248
+ this.path = path;
249
+ this.#matchResult = matchResult;
250
+ this.#validatedData = {};
251
+ }
252
+ param(key) {
253
+ return key ? this.#getDecodedParam(key) : this.#getAllDecodedParams();
254
+ }
255
+ #getDecodedParam(key) {
256
+ const paramKey = this.#matchResult[0][this.routeIndex][1][key];
257
+ const param = this.#getParamValue(paramKey);
258
+ return param && /\%/.test(param) ? tryDecodeURIComponent(param) : param;
259
+ }
260
+ #getAllDecodedParams() {
261
+ const decoded = {};
262
+ const keys = Object.keys(this.#matchResult[0][this.routeIndex][1]);
263
+ for (const key of keys) {
264
+ const value = this.#getParamValue(this.#matchResult[0][this.routeIndex][1][key]);
265
+ if (value !== void 0) {
266
+ decoded[key] = /\%/.test(value) ? tryDecodeURIComponent(value) : value;
267
+ }
268
+ }
269
+ return decoded;
270
+ }
271
+ #getParamValue(paramKey) {
272
+ return this.#matchResult[1] ? this.#matchResult[1][paramKey] : paramKey;
273
+ }
274
+ query(key) {
275
+ return getQueryParam(this.url, key);
276
+ }
277
+ queries(key) {
278
+ return getQueryParams(this.url, key);
279
+ }
280
+ header(name) {
281
+ if (name) {
282
+ return this.raw.headers.get(name) ?? void 0;
283
+ }
284
+ const headerData = {};
285
+ this.raw.headers.forEach((value, key) => {
286
+ headerData[key] = value;
287
+ });
288
+ return headerData;
289
+ }
290
+ async parseBody(options) {
291
+ return parseBody(this, options);
292
+ }
293
+ #cachedBody = (key) => {
294
+ const { bodyCache, raw } = this;
295
+ const cachedBody = bodyCache[key];
296
+ if (cachedBody) {
297
+ return cachedBody;
298
+ }
299
+ const anyCachedKey = Object.keys(bodyCache)[0];
300
+ if (anyCachedKey) {
301
+ return bodyCache[anyCachedKey].then((body) => {
302
+ if (anyCachedKey === "json") {
303
+ body = JSON.stringify(body);
304
+ }
305
+ return new Response(body)[key]();
306
+ });
307
+ }
308
+ return bodyCache[key] = raw[key]();
309
+ };
310
+ /**
311
+ * `.json()` can parse Request body of type `application/json`
312
+ *
313
+ * @see {@link https://hono.dev/docs/api/request#json}
314
+ *
315
+ * @example
316
+ * ```ts
317
+ * app.post('/entry', async (c) => {
318
+ * const body = await c.req.json()
319
+ * })
320
+ * ```
321
+ */
322
+ json() {
323
+ return this.#cachedBody("text").then((text) => JSON.parse(text));
324
+ }
325
+ /**
326
+ * `.text()` can parse Request body of type `text/plain`
327
+ *
328
+ * @see {@link https://hono.dev/docs/api/request#text}
329
+ *
330
+ * @example
331
+ * ```ts
332
+ * app.post('/entry', async (c) => {
333
+ * const body = await c.req.text()
334
+ * })
335
+ * ```
336
+ */
337
+ text() {
338
+ return this.#cachedBody("text");
339
+ }
340
+ /**
341
+ * `.arrayBuffer()` parse Request body as an `ArrayBuffer`
342
+ *
343
+ * @see {@link https://hono.dev/docs/api/request#arraybuffer}
344
+ *
345
+ * @example
346
+ * ```ts
347
+ * app.post('/entry', async (c) => {
348
+ * const body = await c.req.arrayBuffer()
349
+ * })
350
+ * ```
351
+ */
352
+ arrayBuffer() {
353
+ return this.#cachedBody("arrayBuffer");
354
+ }
355
+ /**
356
+ * Parses the request body as a `Blob`.
357
+ * @example
358
+ * ```ts
359
+ * app.post('/entry', async (c) => {
360
+ * const body = await c.req.blob();
361
+ * });
362
+ * ```
363
+ * @see https://hono.dev/docs/api/request#blob
364
+ */
365
+ blob() {
366
+ return this.#cachedBody("blob");
367
+ }
368
+ /**
369
+ * Parses the request body as `FormData`.
370
+ * @example
371
+ * ```ts
372
+ * app.post('/entry', async (c) => {
373
+ * const body = await c.req.formData();
374
+ * });
375
+ * ```
376
+ * @see https://hono.dev/docs/api/request#formdata
377
+ */
378
+ formData() {
379
+ return this.#cachedBody("formData");
380
+ }
381
+ /**
382
+ * Adds validated data to the request.
383
+ *
384
+ * @param target - The target of the validation.
385
+ * @param data - The validated data to add.
386
+ */
387
+ addValidatedData(target, data) {
388
+ this.#validatedData[target] = data;
389
+ }
390
+ valid(target) {
391
+ return this.#validatedData[target];
392
+ }
393
+ /**
394
+ * `.url()` can get the request url strings.
395
+ *
396
+ * @see {@link https://hono.dev/docs/api/request#url}
397
+ *
398
+ * @example
399
+ * ```ts
400
+ * app.get('/about/me', (c) => {
401
+ * const url = c.req.url // `http://localhost:8787/about/me`
402
+ * ...
403
+ * })
404
+ * ```
405
+ */
406
+ get url() {
407
+ return this.raw.url;
408
+ }
409
+ /**
410
+ * `.method()` can get the method name of the request.
411
+ *
412
+ * @see {@link https://hono.dev/docs/api/request#method}
413
+ *
414
+ * @example
415
+ * ```ts
416
+ * app.get('/about/me', (c) => {
417
+ * const method = c.req.method // `GET`
418
+ * })
419
+ * ```
420
+ */
421
+ get method() {
422
+ return this.raw.method;
423
+ }
424
+ get [GET_MATCH_RESULT]() {
425
+ return this.#matchResult;
426
+ }
427
+ /**
428
+ * `.matchedRoutes()` can return a matched route in the handler
429
+ *
430
+ * @deprecated
431
+ *
432
+ * Use matchedRoutes helper defined in "hono/route" instead.
433
+ *
434
+ * @see {@link https://hono.dev/docs/api/request#matchedroutes}
435
+ *
436
+ * @example
437
+ * ```ts
438
+ * app.use('*', async function logger(c, next) {
439
+ * await next()
440
+ * c.req.matchedRoutes.forEach(({ handler, method, path }, i) => {
441
+ * const name = handler.name || (handler.length < 2 ? '[handler]' : '[middleware]')
442
+ * console.log(
443
+ * method,
444
+ * ' ',
445
+ * path,
446
+ * ' '.repeat(Math.max(10 - path.length, 0)),
447
+ * name,
448
+ * i === c.req.routeIndex ? '<- respond from here' : ''
449
+ * )
450
+ * })
451
+ * })
452
+ * ```
453
+ */
454
+ get matchedRoutes() {
455
+ return this.#matchResult[0].map(([[, route]]) => route);
456
+ }
457
+ /**
458
+ * `routePath()` can retrieve the path registered within the handler
459
+ *
460
+ * @deprecated
461
+ *
462
+ * Use routePath helper defined in "hono/route" instead.
463
+ *
464
+ * @see {@link https://hono.dev/docs/api/request#routepath}
465
+ *
466
+ * @example
467
+ * ```ts
468
+ * app.get('/posts/:id', (c) => {
469
+ * return c.json({ path: c.req.routePath })
470
+ * })
471
+ * ```
472
+ */
473
+ get routePath() {
474
+ return this.#matchResult[0].map(([[, route]]) => route)[this.routeIndex].path;
475
+ }
476
+ };
477
+
478
+ // ../../node_modules/.pnpm/hono@4.12.18/node_modules/hono/dist/router/reg-exp-router/node.js
479
+ var regExpMetaChars = new Set(".\\+*[^]$()");
480
+
481
+ // src/query-builder.ts
482
+ var QueryBuilder = class {
483
+ constructor(collection, executor) {
484
+ this.collection = collection;
485
+ this.executor = executor;
486
+ }
487
+ collection;
488
+ executor;
489
+ args = {};
490
+ where(where) {
491
+ this.args.where = { ...this.args.where, ...where };
492
+ return this;
493
+ }
494
+ sort(sort) {
495
+ this.args.sort = sort;
496
+ return this;
497
+ }
498
+ limit(limit) {
499
+ this.args.limit = limit;
500
+ return this;
501
+ }
502
+ page(page) {
503
+ this.args.page = page;
504
+ return this;
505
+ }
506
+ depth(depth) {
507
+ this.args.depth = depth;
508
+ return this;
509
+ }
510
+ async exec() {
511
+ return this.executor(this.collection, this.args);
512
+ }
513
+ // Thenable support for convenience
514
+ then(onfulfilled, onrejected) {
515
+ return this.exec().then(onfulfilled, onrejected);
516
+ }
517
+ };
518
+
519
+ // src/index.ts
520
+ var DyrectedClient = class {
521
+ baseUrl;
522
+ headers;
523
+ fetch;
524
+ constructor(config) {
525
+ this.baseUrl = config.baseUrl.replace(/\/$/, "");
526
+ this.fetch = config.fetch || fetch;
527
+ this.headers = {
528
+ "Content-Type": "application/json",
529
+ ...config.apiKey ? { "X-API-Key": config.apiKey } : {},
530
+ ...config.headers
531
+ };
532
+ }
533
+ getBaseUrl() {
534
+ return this.baseUrl;
535
+ }
536
+ async getSchemas() {
537
+ return this.request("/api/schemas");
538
+ }
539
+ async find(collection, args = {}) {
540
+ const query = import_qs.default.stringify(args, { addQueryPrefix: true });
541
+ const res = await this.request(`/api/collections/${collection}${query}`);
542
+ return res;
543
+ }
544
+ /**
545
+ * Returns a fluent query builder for a collection.
546
+ */
547
+ collection(slug) {
548
+ return {
549
+ find: (args) => {
550
+ const qb = new QueryBuilder(slug, (c, a) => this.find(c, a));
551
+ if (args) {
552
+ if (args.where) qb.where(args.where);
553
+ if (args.sort) qb.sort(args.sort);
554
+ if (args.limit) qb.limit(args.limit);
555
+ if (args.page) qb.page(args.page);
556
+ if (args.depth) qb.depth(args.depth);
557
+ }
558
+ return qb;
559
+ },
560
+ findOne: (id, args = {}) => this.findOne(slug, id, args),
561
+ create: (data) => this.create(slug, data),
562
+ update: (id, data) => this.update(slug, id, data),
563
+ delete: (id) => this.delete(slug, id)
564
+ };
565
+ }
566
+ async findOne(collection, id, args = {}) {
567
+ const query = import_qs.default.stringify(args, { addQueryPrefix: true });
568
+ return this.request(`/api/collections/${collection}/${id}${query}`);
569
+ }
570
+ async create(collection, data) {
571
+ return this.request(`/api/collections/${collection}`, {
572
+ method: "POST",
573
+ body: JSON.stringify(data)
574
+ });
575
+ }
576
+ async update(collection, id, data) {
577
+ return this.request(`/api/collections/${collection}/${id}`, {
578
+ method: "PATCH",
579
+ body: JSON.stringify(data)
580
+ });
581
+ }
582
+ async delete(collection, id) {
583
+ return this.request(`/api/collections/${collection}/${id}`, {
584
+ method: "DELETE"
585
+ });
586
+ }
587
+ async getGlobal(slug, args = {}) {
588
+ const query = import_qs.default.stringify(args, { addQueryPrefix: true });
589
+ return this.request(`/api/globals/${slug}${query}`);
590
+ }
591
+ async updateGlobal(slug, data) {
592
+ return this.request(`/api/globals/${slug}`, {
593
+ method: "PATCH",
594
+ body: JSON.stringify(data)
595
+ });
596
+ }
597
+ async listMedia(args = {}) {
598
+ const query = import_qs.default.stringify(args, { addQueryPrefix: true });
599
+ return this.request(`/api/media${query}`);
600
+ }
601
+ async uploadMedia(file) {
602
+ const formData = new FormData();
603
+ formData.append("file", file);
604
+ const { "Content-Type": _, ...headers } = this.headers;
605
+ return this.request("/api/media", {
606
+ method: "POST",
607
+ headers,
608
+ body: formData
609
+ });
610
+ }
611
+ async deleteMedia(id) {
612
+ return this.request(`/api/media/${id}`, {
613
+ method: "DELETE"
614
+ });
615
+ }
616
+ async request(path, init) {
617
+ const url = `${this.baseUrl}${path}`;
618
+ const res = await this.fetch(url, {
619
+ ...init,
620
+ headers: {
621
+ ...this.headers,
622
+ ...init?.headers
623
+ }
624
+ });
625
+ if (!res.ok) {
626
+ const error = await res.json().catch(() => ({ message: "Unknown error" }));
627
+ throw new Error(error.message || `Request failed with status ${res.status}`);
628
+ }
629
+ return res.json();
630
+ }
631
+ };
632
+ function createClient(config) {
633
+ return new DyrectedClient(config);
634
+ }
635
+ // Annotate the CommonJS export names for ESM import in node:
636
+ 0 && (module.exports = {
637
+ DyrectedClient,
638
+ createClient
639
+ });
@@ -0,0 +1,77 @@
1
+ import { PaginatedResult, FileData } from '@dyrected/core';
2
+ export { FileData as Media } from '@dyrected/core';
3
+
4
+ interface QueryArgs {
5
+ limit?: number;
6
+ page?: number;
7
+ depth?: number;
8
+ where?: any;
9
+ sort?: string;
10
+ }
11
+ declare class QueryBuilder<T = any> {
12
+ private collection;
13
+ private executor;
14
+ private args;
15
+ constructor(collection: string, executor: (collection: string, args: QueryArgs) => Promise<PaginatedResult<T>>);
16
+ where(where: any): this;
17
+ sort(sort: string): this;
18
+ limit(limit: number): this;
19
+ page(page: number): this;
20
+ depth(depth: number): this;
21
+ exec(): Promise<PaginatedResult<T>>;
22
+ then<TResult1 = PaginatedResult<T>, TResult2 = never>(onfulfilled?: ((value: PaginatedResult<T>) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>;
23
+ }
24
+
25
+ interface DyrectedClientConfig {
26
+ baseUrl: string;
27
+ apiKey?: string;
28
+ headers?: Record<string, string>;
29
+ fetch?: typeof fetch;
30
+ }
31
+ declare class DyrectedClient {
32
+ private baseUrl;
33
+ private headers;
34
+ private fetch;
35
+ constructor(config: DyrectedClientConfig);
36
+ getBaseUrl(): string;
37
+ getSchemas(): Promise<{
38
+ collections: any[];
39
+ globals: any[];
40
+ }>;
41
+ find<T = any>(collection: string, args?: QueryArgs): Promise<PaginatedResult<T>>;
42
+ /**
43
+ * Returns a fluent query builder for a collection.
44
+ */
45
+ collection<T = any>(slug: string): {
46
+ find: (args?: QueryArgs) => QueryBuilder<T>;
47
+ findOne: (id: string, args?: {
48
+ depth?: number;
49
+ }) => Promise<T>;
50
+ create: (data: any) => Promise<T>;
51
+ update: (id: string, data: any) => Promise<T>;
52
+ delete: (id: string) => Promise<{
53
+ message: string;
54
+ }>;
55
+ };
56
+ findOne<T = any>(collection: string, id: string, args?: {
57
+ depth?: number;
58
+ }): Promise<T>;
59
+ create<T = any>(collection: string, data: any): Promise<T>;
60
+ update<T = any>(collection: string, id: string, data: any): Promise<T>;
61
+ delete(collection: string, id: string): Promise<{
62
+ message: string;
63
+ }>;
64
+ getGlobal<T = any>(slug: string, args?: {
65
+ depth?: number;
66
+ }): Promise<T>;
67
+ updateGlobal<T = any>(slug: string, data: any): Promise<T>;
68
+ listMedia(args?: QueryArgs): Promise<PaginatedResult<FileData>>;
69
+ uploadMedia(file: File): Promise<FileData>;
70
+ deleteMedia(id: string): Promise<{
71
+ message: string;
72
+ }>;
73
+ private request;
74
+ }
75
+ declare function createClient(config: DyrectedClientConfig): DyrectedClient;
76
+
77
+ export { DyrectedClient, type DyrectedClientConfig, createClient };
@@ -0,0 +1,77 @@
1
+ import { PaginatedResult, FileData } from '@dyrected/core';
2
+ export { FileData as Media } from '@dyrected/core';
3
+
4
+ interface QueryArgs {
5
+ limit?: number;
6
+ page?: number;
7
+ depth?: number;
8
+ where?: any;
9
+ sort?: string;
10
+ }
11
+ declare class QueryBuilder<T = any> {
12
+ private collection;
13
+ private executor;
14
+ private args;
15
+ constructor(collection: string, executor: (collection: string, args: QueryArgs) => Promise<PaginatedResult<T>>);
16
+ where(where: any): this;
17
+ sort(sort: string): this;
18
+ limit(limit: number): this;
19
+ page(page: number): this;
20
+ depth(depth: number): this;
21
+ exec(): Promise<PaginatedResult<T>>;
22
+ then<TResult1 = PaginatedResult<T>, TResult2 = never>(onfulfilled?: ((value: PaginatedResult<T>) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>;
23
+ }
24
+
25
+ interface DyrectedClientConfig {
26
+ baseUrl: string;
27
+ apiKey?: string;
28
+ headers?: Record<string, string>;
29
+ fetch?: typeof fetch;
30
+ }
31
+ declare class DyrectedClient {
32
+ private baseUrl;
33
+ private headers;
34
+ private fetch;
35
+ constructor(config: DyrectedClientConfig);
36
+ getBaseUrl(): string;
37
+ getSchemas(): Promise<{
38
+ collections: any[];
39
+ globals: any[];
40
+ }>;
41
+ find<T = any>(collection: string, args?: QueryArgs): Promise<PaginatedResult<T>>;
42
+ /**
43
+ * Returns a fluent query builder for a collection.
44
+ */
45
+ collection<T = any>(slug: string): {
46
+ find: (args?: QueryArgs) => QueryBuilder<T>;
47
+ findOne: (id: string, args?: {
48
+ depth?: number;
49
+ }) => Promise<T>;
50
+ create: (data: any) => Promise<T>;
51
+ update: (id: string, data: any) => Promise<T>;
52
+ delete: (id: string) => Promise<{
53
+ message: string;
54
+ }>;
55
+ };
56
+ findOne<T = any>(collection: string, id: string, args?: {
57
+ depth?: number;
58
+ }): Promise<T>;
59
+ create<T = any>(collection: string, data: any): Promise<T>;
60
+ update<T = any>(collection: string, id: string, data: any): Promise<T>;
61
+ delete(collection: string, id: string): Promise<{
62
+ message: string;
63
+ }>;
64
+ getGlobal<T = any>(slug: string, args?: {
65
+ depth?: number;
66
+ }): Promise<T>;
67
+ updateGlobal<T = any>(slug: string, data: any): Promise<T>;
68
+ listMedia(args?: QueryArgs): Promise<PaginatedResult<FileData>>;
69
+ uploadMedia(file: File): Promise<FileData>;
70
+ deleteMedia(id: string): Promise<{
71
+ message: string;
72
+ }>;
73
+ private request;
74
+ }
75
+ declare function createClient(config: DyrectedClientConfig): DyrectedClient;
76
+
77
+ export { DyrectedClient, type DyrectedClientConfig, createClient };
package/dist/index.js ADDED
@@ -0,0 +1,603 @@
1
+ // src/index.ts
2
+ import qs from "qs";
3
+
4
+ // ../../node_modules/.pnpm/hono@4.12.18/node_modules/hono/dist/request/constants.js
5
+ var GET_MATCH_RESULT = /* @__PURE__ */ Symbol();
6
+
7
+ // ../../node_modules/.pnpm/hono@4.12.18/node_modules/hono/dist/utils/body.js
8
+ var parseBody = async (request, options = /* @__PURE__ */ Object.create(null)) => {
9
+ const { all = false, dot = false } = options;
10
+ const headers = request instanceof HonoRequest ? request.raw.headers : request.headers;
11
+ const contentType = headers.get("Content-Type");
12
+ if (contentType?.startsWith("multipart/form-data") || contentType?.startsWith("application/x-www-form-urlencoded")) {
13
+ return parseFormData(request, { all, dot });
14
+ }
15
+ return {};
16
+ };
17
+ async function parseFormData(request, options) {
18
+ const formData = await request.formData();
19
+ if (formData) {
20
+ return convertFormDataToBodyData(formData, options);
21
+ }
22
+ return {};
23
+ }
24
+ function convertFormDataToBodyData(formData, options) {
25
+ const form = /* @__PURE__ */ Object.create(null);
26
+ formData.forEach((value, key) => {
27
+ const shouldParseAllValues = options.all || key.endsWith("[]");
28
+ if (!shouldParseAllValues) {
29
+ form[key] = value;
30
+ } else {
31
+ handleParsingAllValues(form, key, value);
32
+ }
33
+ });
34
+ if (options.dot) {
35
+ Object.entries(form).forEach(([key, value]) => {
36
+ const shouldParseDotValues = key.includes(".");
37
+ if (shouldParseDotValues) {
38
+ handleParsingNestedValues(form, key, value);
39
+ delete form[key];
40
+ }
41
+ });
42
+ }
43
+ return form;
44
+ }
45
+ var handleParsingAllValues = (form, key, value) => {
46
+ if (form[key] !== void 0) {
47
+ if (Array.isArray(form[key])) {
48
+ ;
49
+ form[key].push(value);
50
+ } else {
51
+ form[key] = [form[key], value];
52
+ }
53
+ } else {
54
+ if (!key.endsWith("[]")) {
55
+ form[key] = value;
56
+ } else {
57
+ form[key] = [value];
58
+ }
59
+ }
60
+ };
61
+ var handleParsingNestedValues = (form, key, value) => {
62
+ if (/(?:^|\.)__proto__\./.test(key)) {
63
+ return;
64
+ }
65
+ let nestedForm = form;
66
+ const keys = key.split(".");
67
+ keys.forEach((key2, index) => {
68
+ if (index === keys.length - 1) {
69
+ nestedForm[key2] = value;
70
+ } else {
71
+ if (!nestedForm[key2] || typeof nestedForm[key2] !== "object" || Array.isArray(nestedForm[key2]) || nestedForm[key2] instanceof File) {
72
+ nestedForm[key2] = /* @__PURE__ */ Object.create(null);
73
+ }
74
+ nestedForm = nestedForm[key2];
75
+ }
76
+ });
77
+ };
78
+
79
+ // ../../node_modules/.pnpm/hono@4.12.18/node_modules/hono/dist/utils/url.js
80
+ var tryDecode = (str, decoder) => {
81
+ try {
82
+ return decoder(str);
83
+ } catch {
84
+ return str.replace(/(?:%[0-9A-Fa-f]{2})+/g, (match2) => {
85
+ try {
86
+ return decoder(match2);
87
+ } catch {
88
+ return match2;
89
+ }
90
+ });
91
+ }
92
+ };
93
+ var _decodeURI = (value) => {
94
+ if (!/[%+]/.test(value)) {
95
+ return value;
96
+ }
97
+ if (value.indexOf("+") !== -1) {
98
+ value = value.replace(/\+/g, " ");
99
+ }
100
+ return value.indexOf("%") !== -1 ? tryDecode(value, decodeURIComponent_) : value;
101
+ };
102
+ var _getQueryParam = (url, key, multiple) => {
103
+ let encoded;
104
+ if (!multiple && key && !/[%+]/.test(key)) {
105
+ let keyIndex2 = url.indexOf("?", 8);
106
+ if (keyIndex2 === -1) {
107
+ return void 0;
108
+ }
109
+ if (!url.startsWith(key, keyIndex2 + 1)) {
110
+ keyIndex2 = url.indexOf(`&${key}`, keyIndex2 + 1);
111
+ }
112
+ while (keyIndex2 !== -1) {
113
+ const trailingKeyCode = url.charCodeAt(keyIndex2 + key.length + 1);
114
+ if (trailingKeyCode === 61) {
115
+ const valueIndex = keyIndex2 + key.length + 2;
116
+ const endIndex = url.indexOf("&", valueIndex);
117
+ return _decodeURI(url.slice(valueIndex, endIndex === -1 ? void 0 : endIndex));
118
+ } else if (trailingKeyCode == 38 || isNaN(trailingKeyCode)) {
119
+ return "";
120
+ }
121
+ keyIndex2 = url.indexOf(`&${key}`, keyIndex2 + 1);
122
+ }
123
+ encoded = /[%+]/.test(url);
124
+ if (!encoded) {
125
+ return void 0;
126
+ }
127
+ }
128
+ const results = {};
129
+ encoded ??= /[%+]/.test(url);
130
+ let keyIndex = url.indexOf("?", 8);
131
+ while (keyIndex !== -1) {
132
+ const nextKeyIndex = url.indexOf("&", keyIndex + 1);
133
+ let valueIndex = url.indexOf("=", keyIndex);
134
+ if (valueIndex > nextKeyIndex && nextKeyIndex !== -1) {
135
+ valueIndex = -1;
136
+ }
137
+ let name = url.slice(
138
+ keyIndex + 1,
139
+ valueIndex === -1 ? nextKeyIndex === -1 ? void 0 : nextKeyIndex : valueIndex
140
+ );
141
+ if (encoded) {
142
+ name = _decodeURI(name);
143
+ }
144
+ keyIndex = nextKeyIndex;
145
+ if (name === "") {
146
+ continue;
147
+ }
148
+ let value;
149
+ if (valueIndex === -1) {
150
+ value = "";
151
+ } else {
152
+ value = url.slice(valueIndex + 1, nextKeyIndex === -1 ? void 0 : nextKeyIndex);
153
+ if (encoded) {
154
+ value = _decodeURI(value);
155
+ }
156
+ }
157
+ if (multiple) {
158
+ if (!(results[name] && Array.isArray(results[name]))) {
159
+ results[name] = [];
160
+ }
161
+ ;
162
+ results[name].push(value);
163
+ } else {
164
+ results[name] ??= value;
165
+ }
166
+ }
167
+ return key ? results[key] : results;
168
+ };
169
+ var getQueryParam = _getQueryParam;
170
+ var getQueryParams = (url, key) => {
171
+ return _getQueryParam(url, key, true);
172
+ };
173
+ var decodeURIComponent_ = decodeURIComponent;
174
+
175
+ // ../../node_modules/.pnpm/hono@4.12.18/node_modules/hono/dist/request.js
176
+ var tryDecodeURIComponent = (str) => tryDecode(str, decodeURIComponent_);
177
+ var HonoRequest = class {
178
+ /**
179
+ * `.raw` can get the raw Request object.
180
+ *
181
+ * @see {@link https://hono.dev/docs/api/request#raw}
182
+ *
183
+ * @example
184
+ * ```ts
185
+ * // For Cloudflare Workers
186
+ * app.post('/', async (c) => {
187
+ * const metadata = c.req.raw.cf?.hostMetadata?
188
+ * ...
189
+ * })
190
+ * ```
191
+ */
192
+ raw;
193
+ #validatedData;
194
+ // Short name of validatedData
195
+ #matchResult;
196
+ routeIndex = 0;
197
+ /**
198
+ * `.path` can get the pathname of the request.
199
+ *
200
+ * @see {@link https://hono.dev/docs/api/request#path}
201
+ *
202
+ * @example
203
+ * ```ts
204
+ * app.get('/about/me', (c) => {
205
+ * const pathname = c.req.path // `/about/me`
206
+ * })
207
+ * ```
208
+ */
209
+ path;
210
+ bodyCache = {};
211
+ constructor(request, path = "/", matchResult = [[]]) {
212
+ this.raw = request;
213
+ this.path = path;
214
+ this.#matchResult = matchResult;
215
+ this.#validatedData = {};
216
+ }
217
+ param(key) {
218
+ return key ? this.#getDecodedParam(key) : this.#getAllDecodedParams();
219
+ }
220
+ #getDecodedParam(key) {
221
+ const paramKey = this.#matchResult[0][this.routeIndex][1][key];
222
+ const param = this.#getParamValue(paramKey);
223
+ return param && /\%/.test(param) ? tryDecodeURIComponent(param) : param;
224
+ }
225
+ #getAllDecodedParams() {
226
+ const decoded = {};
227
+ const keys = Object.keys(this.#matchResult[0][this.routeIndex][1]);
228
+ for (const key of keys) {
229
+ const value = this.#getParamValue(this.#matchResult[0][this.routeIndex][1][key]);
230
+ if (value !== void 0) {
231
+ decoded[key] = /\%/.test(value) ? tryDecodeURIComponent(value) : value;
232
+ }
233
+ }
234
+ return decoded;
235
+ }
236
+ #getParamValue(paramKey) {
237
+ return this.#matchResult[1] ? this.#matchResult[1][paramKey] : paramKey;
238
+ }
239
+ query(key) {
240
+ return getQueryParam(this.url, key);
241
+ }
242
+ queries(key) {
243
+ return getQueryParams(this.url, key);
244
+ }
245
+ header(name) {
246
+ if (name) {
247
+ return this.raw.headers.get(name) ?? void 0;
248
+ }
249
+ const headerData = {};
250
+ this.raw.headers.forEach((value, key) => {
251
+ headerData[key] = value;
252
+ });
253
+ return headerData;
254
+ }
255
+ async parseBody(options) {
256
+ return parseBody(this, options);
257
+ }
258
+ #cachedBody = (key) => {
259
+ const { bodyCache, raw } = this;
260
+ const cachedBody = bodyCache[key];
261
+ if (cachedBody) {
262
+ return cachedBody;
263
+ }
264
+ const anyCachedKey = Object.keys(bodyCache)[0];
265
+ if (anyCachedKey) {
266
+ return bodyCache[anyCachedKey].then((body) => {
267
+ if (anyCachedKey === "json") {
268
+ body = JSON.stringify(body);
269
+ }
270
+ return new Response(body)[key]();
271
+ });
272
+ }
273
+ return bodyCache[key] = raw[key]();
274
+ };
275
+ /**
276
+ * `.json()` can parse Request body of type `application/json`
277
+ *
278
+ * @see {@link https://hono.dev/docs/api/request#json}
279
+ *
280
+ * @example
281
+ * ```ts
282
+ * app.post('/entry', async (c) => {
283
+ * const body = await c.req.json()
284
+ * })
285
+ * ```
286
+ */
287
+ json() {
288
+ return this.#cachedBody("text").then((text) => JSON.parse(text));
289
+ }
290
+ /**
291
+ * `.text()` can parse Request body of type `text/plain`
292
+ *
293
+ * @see {@link https://hono.dev/docs/api/request#text}
294
+ *
295
+ * @example
296
+ * ```ts
297
+ * app.post('/entry', async (c) => {
298
+ * const body = await c.req.text()
299
+ * })
300
+ * ```
301
+ */
302
+ text() {
303
+ return this.#cachedBody("text");
304
+ }
305
+ /**
306
+ * `.arrayBuffer()` parse Request body as an `ArrayBuffer`
307
+ *
308
+ * @see {@link https://hono.dev/docs/api/request#arraybuffer}
309
+ *
310
+ * @example
311
+ * ```ts
312
+ * app.post('/entry', async (c) => {
313
+ * const body = await c.req.arrayBuffer()
314
+ * })
315
+ * ```
316
+ */
317
+ arrayBuffer() {
318
+ return this.#cachedBody("arrayBuffer");
319
+ }
320
+ /**
321
+ * Parses the request body as a `Blob`.
322
+ * @example
323
+ * ```ts
324
+ * app.post('/entry', async (c) => {
325
+ * const body = await c.req.blob();
326
+ * });
327
+ * ```
328
+ * @see https://hono.dev/docs/api/request#blob
329
+ */
330
+ blob() {
331
+ return this.#cachedBody("blob");
332
+ }
333
+ /**
334
+ * Parses the request body as `FormData`.
335
+ * @example
336
+ * ```ts
337
+ * app.post('/entry', async (c) => {
338
+ * const body = await c.req.formData();
339
+ * });
340
+ * ```
341
+ * @see https://hono.dev/docs/api/request#formdata
342
+ */
343
+ formData() {
344
+ return this.#cachedBody("formData");
345
+ }
346
+ /**
347
+ * Adds validated data to the request.
348
+ *
349
+ * @param target - The target of the validation.
350
+ * @param data - The validated data to add.
351
+ */
352
+ addValidatedData(target, data) {
353
+ this.#validatedData[target] = data;
354
+ }
355
+ valid(target) {
356
+ return this.#validatedData[target];
357
+ }
358
+ /**
359
+ * `.url()` can get the request url strings.
360
+ *
361
+ * @see {@link https://hono.dev/docs/api/request#url}
362
+ *
363
+ * @example
364
+ * ```ts
365
+ * app.get('/about/me', (c) => {
366
+ * const url = c.req.url // `http://localhost:8787/about/me`
367
+ * ...
368
+ * })
369
+ * ```
370
+ */
371
+ get url() {
372
+ return this.raw.url;
373
+ }
374
+ /**
375
+ * `.method()` can get the method name of the request.
376
+ *
377
+ * @see {@link https://hono.dev/docs/api/request#method}
378
+ *
379
+ * @example
380
+ * ```ts
381
+ * app.get('/about/me', (c) => {
382
+ * const method = c.req.method // `GET`
383
+ * })
384
+ * ```
385
+ */
386
+ get method() {
387
+ return this.raw.method;
388
+ }
389
+ get [GET_MATCH_RESULT]() {
390
+ return this.#matchResult;
391
+ }
392
+ /**
393
+ * `.matchedRoutes()` can return a matched route in the handler
394
+ *
395
+ * @deprecated
396
+ *
397
+ * Use matchedRoutes helper defined in "hono/route" instead.
398
+ *
399
+ * @see {@link https://hono.dev/docs/api/request#matchedroutes}
400
+ *
401
+ * @example
402
+ * ```ts
403
+ * app.use('*', async function logger(c, next) {
404
+ * await next()
405
+ * c.req.matchedRoutes.forEach(({ handler, method, path }, i) => {
406
+ * const name = handler.name || (handler.length < 2 ? '[handler]' : '[middleware]')
407
+ * console.log(
408
+ * method,
409
+ * ' ',
410
+ * path,
411
+ * ' '.repeat(Math.max(10 - path.length, 0)),
412
+ * name,
413
+ * i === c.req.routeIndex ? '<- respond from here' : ''
414
+ * )
415
+ * })
416
+ * })
417
+ * ```
418
+ */
419
+ get matchedRoutes() {
420
+ return this.#matchResult[0].map(([[, route]]) => route);
421
+ }
422
+ /**
423
+ * `routePath()` can retrieve the path registered within the handler
424
+ *
425
+ * @deprecated
426
+ *
427
+ * Use routePath helper defined in "hono/route" instead.
428
+ *
429
+ * @see {@link https://hono.dev/docs/api/request#routepath}
430
+ *
431
+ * @example
432
+ * ```ts
433
+ * app.get('/posts/:id', (c) => {
434
+ * return c.json({ path: c.req.routePath })
435
+ * })
436
+ * ```
437
+ */
438
+ get routePath() {
439
+ return this.#matchResult[0].map(([[, route]]) => route)[this.routeIndex].path;
440
+ }
441
+ };
442
+
443
+ // ../../node_modules/.pnpm/hono@4.12.18/node_modules/hono/dist/router/reg-exp-router/node.js
444
+ var regExpMetaChars = new Set(".\\+*[^]$()");
445
+
446
+ // src/query-builder.ts
447
+ var QueryBuilder = class {
448
+ constructor(collection, executor) {
449
+ this.collection = collection;
450
+ this.executor = executor;
451
+ }
452
+ collection;
453
+ executor;
454
+ args = {};
455
+ where(where) {
456
+ this.args.where = { ...this.args.where, ...where };
457
+ return this;
458
+ }
459
+ sort(sort) {
460
+ this.args.sort = sort;
461
+ return this;
462
+ }
463
+ limit(limit) {
464
+ this.args.limit = limit;
465
+ return this;
466
+ }
467
+ page(page) {
468
+ this.args.page = page;
469
+ return this;
470
+ }
471
+ depth(depth) {
472
+ this.args.depth = depth;
473
+ return this;
474
+ }
475
+ async exec() {
476
+ return this.executor(this.collection, this.args);
477
+ }
478
+ // Thenable support for convenience
479
+ then(onfulfilled, onrejected) {
480
+ return this.exec().then(onfulfilled, onrejected);
481
+ }
482
+ };
483
+
484
+ // src/index.ts
485
+ var DyrectedClient = class {
486
+ baseUrl;
487
+ headers;
488
+ fetch;
489
+ constructor(config) {
490
+ this.baseUrl = config.baseUrl.replace(/\/$/, "");
491
+ this.fetch = config.fetch || fetch;
492
+ this.headers = {
493
+ "Content-Type": "application/json",
494
+ ...config.apiKey ? { "X-API-Key": config.apiKey } : {},
495
+ ...config.headers
496
+ };
497
+ }
498
+ getBaseUrl() {
499
+ return this.baseUrl;
500
+ }
501
+ async getSchemas() {
502
+ return this.request("/api/schemas");
503
+ }
504
+ async find(collection, args = {}) {
505
+ const query = qs.stringify(args, { addQueryPrefix: true });
506
+ const res = await this.request(`/api/collections/${collection}${query}`);
507
+ return res;
508
+ }
509
+ /**
510
+ * Returns a fluent query builder for a collection.
511
+ */
512
+ collection(slug) {
513
+ return {
514
+ find: (args) => {
515
+ const qb = new QueryBuilder(slug, (c, a) => this.find(c, a));
516
+ if (args) {
517
+ if (args.where) qb.where(args.where);
518
+ if (args.sort) qb.sort(args.sort);
519
+ if (args.limit) qb.limit(args.limit);
520
+ if (args.page) qb.page(args.page);
521
+ if (args.depth) qb.depth(args.depth);
522
+ }
523
+ return qb;
524
+ },
525
+ findOne: (id, args = {}) => this.findOne(slug, id, args),
526
+ create: (data) => this.create(slug, data),
527
+ update: (id, data) => this.update(slug, id, data),
528
+ delete: (id) => this.delete(slug, id)
529
+ };
530
+ }
531
+ async findOne(collection, id, args = {}) {
532
+ const query = qs.stringify(args, { addQueryPrefix: true });
533
+ return this.request(`/api/collections/${collection}/${id}${query}`);
534
+ }
535
+ async create(collection, data) {
536
+ return this.request(`/api/collections/${collection}`, {
537
+ method: "POST",
538
+ body: JSON.stringify(data)
539
+ });
540
+ }
541
+ async update(collection, id, data) {
542
+ return this.request(`/api/collections/${collection}/${id}`, {
543
+ method: "PATCH",
544
+ body: JSON.stringify(data)
545
+ });
546
+ }
547
+ async delete(collection, id) {
548
+ return this.request(`/api/collections/${collection}/${id}`, {
549
+ method: "DELETE"
550
+ });
551
+ }
552
+ async getGlobal(slug, args = {}) {
553
+ const query = qs.stringify(args, { addQueryPrefix: true });
554
+ return this.request(`/api/globals/${slug}${query}`);
555
+ }
556
+ async updateGlobal(slug, data) {
557
+ return this.request(`/api/globals/${slug}`, {
558
+ method: "PATCH",
559
+ body: JSON.stringify(data)
560
+ });
561
+ }
562
+ async listMedia(args = {}) {
563
+ const query = qs.stringify(args, { addQueryPrefix: true });
564
+ return this.request(`/api/media${query}`);
565
+ }
566
+ async uploadMedia(file) {
567
+ const formData = new FormData();
568
+ formData.append("file", file);
569
+ const { "Content-Type": _, ...headers } = this.headers;
570
+ return this.request("/api/media", {
571
+ method: "POST",
572
+ headers,
573
+ body: formData
574
+ });
575
+ }
576
+ async deleteMedia(id) {
577
+ return this.request(`/api/media/${id}`, {
578
+ method: "DELETE"
579
+ });
580
+ }
581
+ async request(path, init) {
582
+ const url = `${this.baseUrl}${path}`;
583
+ const res = await this.fetch(url, {
584
+ ...init,
585
+ headers: {
586
+ ...this.headers,
587
+ ...init?.headers
588
+ }
589
+ });
590
+ if (!res.ok) {
591
+ const error = await res.json().catch(() => ({ message: "Unknown error" }));
592
+ throw new Error(error.message || `Request failed with status ${res.status}`);
593
+ }
594
+ return res.json();
595
+ }
596
+ };
597
+ function createClient(config) {
598
+ return new DyrectedClient(config);
599
+ }
600
+ export {
601
+ DyrectedClient,
602
+ createClient
603
+ };
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@dyrected/sdk",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "require": "./dist/index.cjs"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "dependencies": {
19
+ "qs": "^6.12.1"
20
+ },
21
+ "devDependencies": {
22
+ "@types/qs": "^6.15.1",
23
+ "tsup": "^8.5.1",
24
+ "typescript": "^5.4.5",
25
+ "@dyrected/core": "0.0.1"
26
+ },
27
+ "scripts": {
28
+ "build": "tsup src/index.ts --format cjs,esm --dts",
29
+ "dev": "tsup src/index.ts --format cjs,esm --watch --dts",
30
+ "lint": "eslint src"
31
+ }
32
+ }