@dyrected/sdk 0.0.1 → 1.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/LICENSE.md +50 -0
- package/README.md +46 -1
- package/dist/index.cjs +187 -465
- package/dist/index.d.cts +118 -13
- package/dist/index.d.ts +118 -13
- package/dist/index.js +186 -465
- package/package.json +13 -2
package/dist/index.cjs
CHANGED
|
@@ -31,453 +31,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
DyrectedClient: () => DyrectedClient,
|
|
34
|
+
DyrectedError: () => DyrectedError,
|
|
34
35
|
createClient: () => createClient
|
|
35
36
|
});
|
|
36
37
|
module.exports = __toCommonJS(index_exports);
|
|
37
38
|
var import_qs = __toESM(require("qs"), 1);
|
|
38
39
|
|
|
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
40
|
// src/query-builder.ts
|
|
482
41
|
var QueryBuilder = class {
|
|
483
42
|
constructor(collection, executor) {
|
|
@@ -507,6 +66,10 @@ var QueryBuilder = class {
|
|
|
507
66
|
this.args.depth = depth;
|
|
508
67
|
return this;
|
|
509
68
|
}
|
|
69
|
+
seed(data) {
|
|
70
|
+
this.args.initialData = data;
|
|
71
|
+
return this;
|
|
72
|
+
}
|
|
510
73
|
async exec() {
|
|
511
74
|
return this.executor(this.collection, this.args);
|
|
512
75
|
}
|
|
@@ -517,28 +80,82 @@ var QueryBuilder = class {
|
|
|
517
80
|
};
|
|
518
81
|
|
|
519
82
|
// src/index.ts
|
|
83
|
+
var DyrectedError = class extends Error {
|
|
84
|
+
statusCode;
|
|
85
|
+
errors;
|
|
86
|
+
constructor(message, statusCode, errors = []) {
|
|
87
|
+
super(message);
|
|
88
|
+
this.name = "DyrectedError";
|
|
89
|
+
this.statusCode = statusCode;
|
|
90
|
+
this.errors = errors;
|
|
91
|
+
}
|
|
92
|
+
};
|
|
520
93
|
var DyrectedClient = class {
|
|
521
94
|
baseUrl;
|
|
522
95
|
headers;
|
|
523
96
|
fetch;
|
|
97
|
+
defaultDepth;
|
|
524
98
|
constructor(config) {
|
|
525
99
|
this.baseUrl = config.baseUrl.replace(/\/$/, "");
|
|
526
100
|
this.fetch = config.fetch || fetch;
|
|
101
|
+
this.defaultDepth = config.defaultDepth ?? 1;
|
|
527
102
|
this.headers = {
|
|
528
103
|
"Content-Type": "application/json",
|
|
529
|
-
...config.apiKey ? { "
|
|
104
|
+
...config.apiKey ? { "x-api-key": config.apiKey } : {},
|
|
105
|
+
...config.siteId ? { "x-site-id": config.siteId } : {},
|
|
530
106
|
...config.headers
|
|
531
107
|
};
|
|
532
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* Update the Authorization header with a Bearer token.
|
|
111
|
+
* Call this after a successful login.
|
|
112
|
+
*/
|
|
113
|
+
setToken(token) {
|
|
114
|
+
this.headers["Authorization"] = `Bearer ${token}`;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Remove the Authorization header.
|
|
118
|
+
* Call this after logout.
|
|
119
|
+
*/
|
|
120
|
+
clearToken() {
|
|
121
|
+
delete this.headers["Authorization"];
|
|
122
|
+
}
|
|
533
123
|
getBaseUrl() {
|
|
534
124
|
return this.baseUrl;
|
|
535
125
|
}
|
|
536
126
|
async getSchemas() {
|
|
537
127
|
return this.request("/api/schemas");
|
|
538
128
|
}
|
|
129
|
+
/**
|
|
130
|
+
* Fetch draft data for a specific preview token.
|
|
131
|
+
* Used in "token" preview mode.
|
|
132
|
+
*/
|
|
133
|
+
async getPreviewData(token) {
|
|
134
|
+
return this.request(`/api/preview-data?token=${token}`);
|
|
135
|
+
}
|
|
539
136
|
async find(collection, args = {}) {
|
|
540
|
-
const
|
|
137
|
+
const { initialData, ...queryArgs } = args;
|
|
138
|
+
const normalizedArgs = { ...queryArgs };
|
|
139
|
+
if (normalizedArgs.where && typeof normalizedArgs.where === "object") {
|
|
140
|
+
normalizedArgs.where = JSON.stringify(normalizedArgs.where);
|
|
141
|
+
}
|
|
142
|
+
const query = import_qs.default.stringify(normalizedArgs, { addQueryPrefix: true });
|
|
541
143
|
const res = await this.request(`/api/collections/${collection}${query}`);
|
|
144
|
+
if (res.docs.length === 0 && initialData && initialData.length > 0) {
|
|
145
|
+
this.request(`/api/collections/${collection}/seed`, {
|
|
146
|
+
method: "POST",
|
|
147
|
+
body: JSON.stringify({ data: initialData })
|
|
148
|
+
}).catch((err) => console.error(`[dyrected/sdk] Failed to auto-seed collection "${collection}":`, err));
|
|
149
|
+
return {
|
|
150
|
+
docs: initialData,
|
|
151
|
+
total: initialData.length,
|
|
152
|
+
limit: initialData.length,
|
|
153
|
+
page: 1,
|
|
154
|
+
totalPages: 1,
|
|
155
|
+
hasNextPage: false,
|
|
156
|
+
hasPrevPage: false
|
|
157
|
+
};
|
|
158
|
+
}
|
|
542
159
|
return res;
|
|
543
160
|
}
|
|
544
161
|
/**
|
|
@@ -554,18 +171,80 @@ var DyrectedClient = class {
|
|
|
554
171
|
if (args.limit) qb.limit(args.limit);
|
|
555
172
|
if (args.page) qb.page(args.page);
|
|
556
173
|
if (args.depth) qb.depth(args.depth);
|
|
174
|
+
if (args.initialData) qb.seed(args.initialData);
|
|
557
175
|
}
|
|
558
176
|
return qb;
|
|
559
177
|
},
|
|
560
178
|
findOne: (id, args = {}) => this.findOne(slug, id, args),
|
|
561
179
|
create: (data) => this.create(slug, data),
|
|
562
180
|
update: (id, data) => this.update(slug, id, data),
|
|
563
|
-
delete: (id) => this.delete(slug, id)
|
|
181
|
+
delete: (id) => this.delete(slug, id),
|
|
182
|
+
/**
|
|
183
|
+
* Upload a file to this collection. Sends as multipart/form-data.
|
|
184
|
+
* @param file - A File or Blob (browser) or Buffer with filename/mimeType (Node.js)
|
|
185
|
+
* @param data - Additional metadata fields to save alongside the file (e.g. alt, caption)
|
|
186
|
+
*/
|
|
187
|
+
upload: (file, data) => this._upload(slug, file, data),
|
|
188
|
+
// ---- Auth methods (only meaningful when the collection has auth: true) ----
|
|
189
|
+
/**
|
|
190
|
+
* Log in with email + password. Returns a JWT token and the user document.
|
|
191
|
+
* Call `client.setToken(token)` afterwards to authenticate subsequent requests.
|
|
192
|
+
*/
|
|
193
|
+
login: (email, password) => this.request(`/api/collections/${slug}/login`, {
|
|
194
|
+
method: "POST",
|
|
195
|
+
body: JSON.stringify({ email, password })
|
|
196
|
+
}),
|
|
197
|
+
/** Log out. Stateless — token must be discarded client-side; call client.clearToken() too. */
|
|
198
|
+
logout: () => this.request(`/api/collections/${slug}/logout`, { method: "POST" }),
|
|
199
|
+
/** Return the currently authenticated user (requires a token via setToken). */
|
|
200
|
+
me: () => this.request(`/api/collections/${slug}/me`),
|
|
201
|
+
/** Issue a fresh token for the currently authenticated user. */
|
|
202
|
+
refreshToken: () => this.request(`/api/collections/${slug}/refresh-token`, { method: "POST" }),
|
|
203
|
+
/** Check if this auth collection has any users (initialized). */
|
|
204
|
+
isInitialized: () => this.request(`/api/collections/${slug}/init`),
|
|
205
|
+
/** Register the very first user in an empty auth collection. */
|
|
206
|
+
registerFirstUser: (data) => this.request(`/api/collections/${slug}/first-user`, {
|
|
207
|
+
method: "POST",
|
|
208
|
+
body: JSON.stringify(data)
|
|
209
|
+
}),
|
|
210
|
+
/** Send an invitation email to a new user. Requires authentication. */
|
|
211
|
+
invite: (email) => this.request(`/api/collections/${slug}/invite`, {
|
|
212
|
+
method: "POST",
|
|
213
|
+
body: JSON.stringify({ email })
|
|
214
|
+
}),
|
|
215
|
+
/** Accept an invitation and create an account. Returns token + user. */
|
|
216
|
+
acceptInvite: (token, password, extraFields) => this.request(`/api/collections/${slug}/accept-invite`, {
|
|
217
|
+
method: "POST",
|
|
218
|
+
body: JSON.stringify({ token, password, ...extraFields })
|
|
219
|
+
})
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Access a global by its slug with a fluent builder.
|
|
224
|
+
* @example client.global('site-settings').get()
|
|
225
|
+
* @example client.global('site-settings').update({ siteName: 'My Site' })
|
|
226
|
+
*/
|
|
227
|
+
global(slug) {
|
|
228
|
+
return {
|
|
229
|
+
get: (args = {}) => this.getGlobal(slug, args),
|
|
230
|
+
update: (data) => this.updateGlobal(slug, data)
|
|
564
231
|
};
|
|
565
232
|
}
|
|
566
233
|
async findOne(collection, id, args = {}) {
|
|
567
|
-
const
|
|
568
|
-
|
|
234
|
+
const { initialData, ...queryArgs } = args;
|
|
235
|
+
const query = import_qs.default.stringify(queryArgs, { addQueryPrefix: true });
|
|
236
|
+
try {
|
|
237
|
+
return await this.request(`/api/collections/${collection}/${id}${query}`);
|
|
238
|
+
} catch (err) {
|
|
239
|
+
if (err instanceof DyrectedError && err.statusCode === 404 && initialData) {
|
|
240
|
+
this.request(`/api/collections/${collection}/seed`, {
|
|
241
|
+
method: "POST",
|
|
242
|
+
body: JSON.stringify({ data: [{ id, ...initialData }] })
|
|
243
|
+
}).catch((err2) => console.error(`[dyrected/sdk] Failed to auto-seed document "${id}" in collection "${collection}":`, err2));
|
|
244
|
+
return initialData;
|
|
245
|
+
}
|
|
246
|
+
throw err;
|
|
247
|
+
}
|
|
569
248
|
}
|
|
570
249
|
async create(collection, data) {
|
|
571
250
|
return this.request(`/api/collections/${collection}`, {
|
|
@@ -585,8 +264,28 @@ var DyrectedClient = class {
|
|
|
585
264
|
});
|
|
586
265
|
}
|
|
587
266
|
async getGlobal(slug, args = {}) {
|
|
588
|
-
const
|
|
589
|
-
|
|
267
|
+
const { initialData, ...queryArgs } = args;
|
|
268
|
+
const query = import_qs.default.stringify(queryArgs, { addQueryPrefix: true });
|
|
269
|
+
try {
|
|
270
|
+
const res = await this.request(`/api/globals/${slug}${query}`);
|
|
271
|
+
if ((!res || Object.keys(res).length === 0) && initialData) {
|
|
272
|
+
this.request(`/api/globals/${slug}/seed`, {
|
|
273
|
+
method: "POST",
|
|
274
|
+
body: JSON.stringify({ data: initialData })
|
|
275
|
+
}).catch((err) => console.error(`[dyrected/sdk] Failed to auto-seed global "${slug}":`, err));
|
|
276
|
+
return initialData;
|
|
277
|
+
}
|
|
278
|
+
return res;
|
|
279
|
+
} catch (err) {
|
|
280
|
+
if (err instanceof DyrectedError && err.statusCode === 404 && initialData) {
|
|
281
|
+
this.request(`/api/globals/${slug}/seed`, {
|
|
282
|
+
method: "POST",
|
|
283
|
+
body: JSON.stringify({ data: initialData })
|
|
284
|
+
}).catch((err2) => console.error(`[dyrected/sdk] Failed to auto-seed global "${slug}":`, err2));
|
|
285
|
+
return initialData;
|
|
286
|
+
}
|
|
287
|
+
throw err;
|
|
288
|
+
}
|
|
590
289
|
}
|
|
591
290
|
async updateGlobal(slug, data) {
|
|
592
291
|
return this.request(`/api/globals/${slug}`, {
|
|
@@ -594,37 +293,59 @@ var DyrectedClient = class {
|
|
|
594
293
|
body: JSON.stringify(data)
|
|
595
294
|
});
|
|
596
295
|
}
|
|
597
|
-
async listMedia(args = {}) {
|
|
598
|
-
|
|
599
|
-
|
|
296
|
+
async listMedia(args = {}, collection = "media") {
|
|
297
|
+
return this.find(collection, args);
|
|
298
|
+
}
|
|
299
|
+
/** @deprecated Use client.collection('media').upload(file, data) instead */
|
|
300
|
+
async uploadMedia(file, collection = "media") {
|
|
301
|
+
return this._upload(collection, file);
|
|
600
302
|
}
|
|
601
|
-
|
|
303
|
+
/**
|
|
304
|
+
* Internal upload implementation shared by collection().upload() and uploadMedia().
|
|
305
|
+
*/
|
|
306
|
+
async _upload(collection, file, data) {
|
|
602
307
|
const formData = new FormData();
|
|
603
308
|
formData.append("file", file);
|
|
309
|
+
if (data) {
|
|
310
|
+
for (const [key, value] of Object.entries(data)) {
|
|
311
|
+
formData.append(key, value);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
604
314
|
const { "Content-Type": _, ...headers } = this.headers;
|
|
605
|
-
return this.request(
|
|
315
|
+
return this.request(`/api/collections/${collection}`, {
|
|
606
316
|
method: "POST",
|
|
607
|
-
headers
|
|
317
|
+
headers: {
|
|
318
|
+
...headers,
|
|
319
|
+
"Content-Type": void 0
|
|
320
|
+
},
|
|
608
321
|
body: formData
|
|
609
322
|
});
|
|
610
323
|
}
|
|
611
|
-
async deleteMedia(id) {
|
|
612
|
-
return this.
|
|
613
|
-
method: "DELETE"
|
|
614
|
-
});
|
|
324
|
+
async deleteMedia(id, collection = "media") {
|
|
325
|
+
return this.delete(collection, id);
|
|
615
326
|
}
|
|
616
327
|
async request(path, init) {
|
|
617
328
|
const url = `${this.baseUrl}${path}`;
|
|
329
|
+
const allHeaders = {
|
|
330
|
+
...this.headers,
|
|
331
|
+
...init?.headers
|
|
332
|
+
};
|
|
333
|
+
Object.keys(allHeaders).forEach((key) => {
|
|
334
|
+
if (allHeaders[key] === void 0) {
|
|
335
|
+
delete allHeaders[key];
|
|
336
|
+
}
|
|
337
|
+
});
|
|
618
338
|
const res = await this.fetch(url, {
|
|
619
339
|
...init,
|
|
620
|
-
headers:
|
|
621
|
-
...this.headers,
|
|
622
|
-
...init?.headers
|
|
623
|
-
}
|
|
340
|
+
headers: allHeaders
|
|
624
341
|
});
|
|
625
342
|
if (!res.ok) {
|
|
626
|
-
const
|
|
627
|
-
throw new
|
|
343
|
+
const body = await res.json().catch(() => ({ message: "Unknown error" }));
|
|
344
|
+
throw new DyrectedError(
|
|
345
|
+
body.message || `Request failed with status ${res.status}`,
|
|
346
|
+
res.status,
|
|
347
|
+
body.errors || []
|
|
348
|
+
);
|
|
628
349
|
}
|
|
629
350
|
return res.json();
|
|
630
351
|
}
|
|
@@ -635,5 +356,6 @@ function createClient(config) {
|
|
|
635
356
|
// Annotate the CommonJS export names for ESM import in node:
|
|
636
357
|
0 && (module.exports = {
|
|
637
358
|
DyrectedClient,
|
|
359
|
+
DyrectedError,
|
|
638
360
|
createClient
|
|
639
361
|
});
|