@forklaunch/universal-sdk 0.3.16 → 0.4.0

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.
Files changed (3) hide show
  1. package/lib/index.js +120 -117
  2. package/lib/index.mjs +125 -118
  3. package/package.json +8 -8
package/lib/index.js CHANGED
@@ -170,7 +170,33 @@ function mapContentType(contentType) {
170
170
  }
171
171
  }
172
172
 
173
- // src/core/refreshOpenApi.ts
173
+ // src/core/openApi.ts
174
+ function getSdkPathMap(registryOpenApiJson) {
175
+ const sdkPathMap = {};
176
+ Object.entries(registryOpenApiJson?.paths || {}).forEach(
177
+ ([path, pathItem]) => {
178
+ const methods = [
179
+ "get",
180
+ "post",
181
+ "put",
182
+ "patch",
183
+ "delete",
184
+ "options",
185
+ "head",
186
+ "trace"
187
+ ];
188
+ methods.forEach((method) => {
189
+ if (pathItem[method]?.operationId) {
190
+ sdkPathMap[pathItem[method].operationId] = {
191
+ method,
192
+ path
193
+ };
194
+ }
195
+ });
196
+ }
197
+ );
198
+ return sdkPathMap;
199
+ }
174
200
  async function refreshOpenApi(host, registryOptions, existingRegistryOpenApiHash) {
175
201
  if (existingRegistryOpenApiHash === "static" || "static" in registryOptions && registryOptions.static) {
176
202
  return {
@@ -181,7 +207,8 @@ async function refreshOpenApi(host, registryOptions, existingRegistryOpenApiHash
181
207
  return {
182
208
  updateRequired: true,
183
209
  registryOpenApiJson: registryOptions.raw,
184
- registryOpenApiHash: "static"
210
+ registryOpenApiHash: "static",
211
+ sdkPathMap: getSdkPathMap(registryOptions.raw)
185
212
  };
186
213
  }
187
214
  const registry = "path" in registryOptions ? `${host}/${registryOptions.path}` : "url" in registryOptions ? registryOptions.url : null;
@@ -196,7 +223,8 @@ async function refreshOpenApi(host, registryOptions, existingRegistryOpenApiHash
196
223
  return {
197
224
  updateRequired: true,
198
225
  registryOpenApiJson,
199
- registryOpenApiHash
226
+ registryOpenApiHash,
227
+ sdkPathMap: getSdkPathMap(registryOpenApiJson)
200
228
  };
201
229
  }
202
230
  return {
@@ -312,13 +340,14 @@ function getSdkPath(path) {
312
340
 
313
341
  // src/universalSdk.ts
314
342
  var UniversalSdk = class _UniversalSdk {
315
- constructor(host, ajv, registryOptions, contentTypeParserMap, registryOpenApiJson, registryOpenApiHash) {
343
+ constructor(host, ajv, registryOptions, contentTypeParserMap, registryOpenApiJson, registryOpenApiHash, sdkPathMap) {
316
344
  this.host = host;
317
345
  this.ajv = ajv;
318
346
  this.registryOptions = registryOptions;
319
347
  this.contentTypeParserMap = contentTypeParserMap;
320
348
  this.registryOpenApiJson = registryOpenApiJson;
321
349
  this.registryOpenApiHash = registryOpenApiHash;
350
+ this.sdkPathMap = sdkPathMap;
322
351
  }
323
352
  /**
324
353
  * Creates an instance of UniversalSdk.
@@ -329,9 +358,11 @@ var UniversalSdk = class _UniversalSdk {
329
358
  const refreshResult = await refreshOpenApi(host, registryOptions);
330
359
  let registryOpenApiJson;
331
360
  let registryOpenApiHash;
361
+ let sdkPathMap;
332
362
  if (refreshResult.updateRequired) {
333
363
  registryOpenApiJson = refreshResult.registryOpenApiJson;
334
364
  registryOpenApiHash = refreshResult.registryOpenApiHash;
365
+ sdkPathMap = refreshResult.sdkPathMap;
335
366
  }
336
367
  const ajv = new import_ajv.default({
337
368
  coerceTypes: true,
@@ -345,18 +376,11 @@ var UniversalSdk = class _UniversalSdk {
345
376
  registryOptions,
346
377
  contentTypeParserMap,
347
378
  registryOpenApiJson,
348
- registryOpenApiHash
379
+ registryOpenApiHash,
380
+ sdkPathMap
349
381
  );
350
382
  }
351
- /**
352
- * Executes an HTTP request.
353
- *
354
- * @param {string} route - The route path for the request.
355
- * @param {'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'} method - The HTTP method.
356
- * @param {RequestType} [request] - The request object.
357
- * @returns {Promise<ResponseType>} - The response object.
358
- */
359
- async execute(route, method, request) {
383
+ async executeFetchCall(path, request) {
360
384
  if (!this.host) {
361
385
  throw new Error("Host not initialized, please run .create(..) first");
362
386
  }
@@ -368,9 +392,53 @@ var UniversalSdk = class _UniversalSdk {
368
392
  if (refreshResult.updateRequired) {
369
393
  this.registryOpenApiJson = refreshResult.registryOpenApiJson;
370
394
  this.registryOpenApiHash = refreshResult.registryOpenApiHash;
395
+ this.sdkPathMap = refreshResult.sdkPathMap;
396
+ }
397
+ return this.execute(path, request?.method ?? "get", request);
398
+ }
399
+ async executeSdkCall(sdkPath, request) {
400
+ if (!this.host) {
401
+ throw new Error("Host not initialized, please run .create(..) first");
402
+ }
403
+ const refreshResult = await refreshOpenApi(
404
+ this.host,
405
+ this.registryOptions,
406
+ this.registryOpenApiHash
407
+ );
408
+ if (refreshResult.updateRequired) {
409
+ this.registryOpenApiJson = refreshResult.registryOpenApiJson;
410
+ this.registryOpenApiHash = refreshResult.registryOpenApiHash;
411
+ this.sdkPathMap = refreshResult.sdkPathMap;
412
+ }
413
+ if (this.sdkPathMap == null) {
414
+ throw new Error(
415
+ "Sdk path map not initialized, please run .create(..) first"
416
+ );
371
417
  }
418
+ const fullSdkPath = sdkPath.split(".");
419
+ while (fullSdkPath.length > 0) {
420
+ fullSdkPath.shift();
421
+ if (fullSdkPath.join(".") in this.sdkPathMap) {
422
+ break;
423
+ }
424
+ }
425
+ if (fullSdkPath.length === 0) {
426
+ throw new Error(`Sdk path not found: ${sdkPath}`);
427
+ }
428
+ const { method, path } = this.sdkPathMap?.[fullSdkPath.join(".")] || {};
429
+ return this.execute(path, method, request);
430
+ }
431
+ /**
432
+ * Executes an HTTP request.
433
+ *
434
+ * @param {string} route - The route path for the request.
435
+ * @param {'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'} method - The HTTP method.
436
+ * @param {RequestType} [request] - The request object.
437
+ * @returns {Promise<ResponseType>} - The response object.
438
+ */
439
+ async execute(path, method, request) {
372
440
  const { params, body, query, headers } = request || {};
373
- let url = getSdkPath(this.host + route);
441
+ let url = getSdkPath(this.host + path);
374
442
  if (params) {
375
443
  for (const key in params) {
376
444
  url = url.replace(`:${key}`, encodeURIComponent(params[key]));
@@ -379,7 +447,10 @@ var UniversalSdk = class _UniversalSdk {
379
447
  let defaultContentType = "application/json";
380
448
  let parsedBody;
381
449
  if (body != null) {
382
- if ("schema" in body && body.schema != null) {
450
+ if (body instanceof File || body instanceof Blob) {
451
+ defaultContentType = "application/octet-stream";
452
+ parsedBody = body;
453
+ } else if ("schema" in body && body.schema != null) {
383
454
  defaultContentType = "application/json";
384
455
  parsedBody = (0, import_common2.safeStringify)(body.schema);
385
456
  } else if ("json" in body && body.json != null) {
@@ -390,7 +461,7 @@ var UniversalSdk = class _UniversalSdk {
390
461
  parsedBody = body.text;
391
462
  } else if ("file" in body && body.file != null) {
392
463
  defaultContentType = "application/octet-stream";
393
- parsedBody = await body.file.text();
464
+ parsedBody = body.file;
394
465
  } else if ("multipartForm" in body && body.multipartForm != null) {
395
466
  defaultContentType = "multipart/form-data";
396
467
  const formData = new FormData();
@@ -431,17 +502,17 @@ var UniversalSdk = class _UniversalSdk {
431
502
  url += queryString ? `?${queryString}` : "";
432
503
  }
433
504
  const response = await fetch(encodeURI(url), {
434
- method: method.toUpperCase(),
505
+ method: method?.toUpperCase(),
435
506
  headers: {
436
507
  ...headers,
437
508
  ...defaultContentType != "multipart/form-data" ? { "Content-Type": body?.contentType ?? defaultContentType } : {}
438
509
  },
439
510
  body: parsedBody
440
511
  });
441
- const responseOpenApi = this.registryOpenApiJson?.paths?.[route]?.[method.toLowerCase()]?.responses?.[response.status];
512
+ const responseOpenApi = path != null && method != null ? this.registryOpenApiJson?.paths?.[(0, import_common2.openApiCompliantPath)(path)]?.[method?.toLowerCase()]?.responses?.[response.status] : null;
442
513
  if (responseOpenApi == null) {
443
514
  throw new Error(
444
- `Response ${response.status} not found in OpenAPI spec for route ${route}`
515
+ `Response ${response.status} not found in OpenAPI spec for ${path} with method ${method}`
445
516
  );
446
517
  }
447
518
  const contentType = (response.headers.get("content-type") || response.headers.get("Content-Type"))?.split(";")[0];
@@ -566,78 +637,6 @@ var UniversalSdk = class _UniversalSdk {
566
637
  headers: response.headers
567
638
  };
568
639
  }
569
- /**
570
- * Executes a request with path parameters.
571
- *
572
- * @param {string} route - The route path for the request.
573
- * @param {'GET' | 'DELETE'} method - The HTTP method.
574
- * @param {RequestType} [request] - The request object.
575
- * @returns {Promise<ResponseType>} - The response object.
576
- */
577
- async pathParamRequest(route, method, request) {
578
- return this.execute(route, method, request);
579
- }
580
- /**
581
- * Executes a request with a body.
582
- *
583
- * @param {string} route - The route path for the request.
584
- * @param {'POST' | 'PUT' | 'PATCH'} method - The HTTP method.
585
- * @param {RequestType} [request] - The request object.
586
- * @returns {Promise<ResponseType>} - The response object.
587
- */
588
- async bodyRequest(route, method, request) {
589
- return this.execute(route, method, request);
590
- }
591
- /**
592
- * Executes a GET request.
593
- *
594
- * @param {string} route - The route path for the request.
595
- * @param {RequestType} [request] - The request object.
596
- * @returns {Promise<ResponseType>} - The response object.
597
- */
598
- async get(route, request) {
599
- return this.pathParamRequest(route, "get", request);
600
- }
601
- /**
602
- * Executes a POST request.
603
- *
604
- * @param {string} route - The route path for the request.
605
- * @param {RequestType} [request] - The request object.
606
- * @returns {Promise<ResponseType>} - The response object.
607
- */
608
- async post(route, request) {
609
- return this.bodyRequest(route, "post", request);
610
- }
611
- /**
612
- * Executes a PUT request.
613
- *
614
- * @param {string} route - The route path for the request.
615
- * @param {RequestType} [request] - The request object.
616
- * @returns {Promise<ResponseType>} - The response object.
617
- */
618
- async put(route, request) {
619
- return this.bodyRequest(route, "put", request);
620
- }
621
- /**
622
- * Executes a PATCH request.
623
- *
624
- * @param {string} route - The route path for the request.
625
- * @param {RequestType} [request] - The request object.
626
- * @returns {Promise<ResponseType>} - The response object.
627
- */
628
- async patch(route, request) {
629
- return this.bodyRequest(route, "patch", request);
630
- }
631
- /**
632
- * Executes a DELETE request.
633
- *
634
- * @param {string} route - The route path for the request.
635
- * @param {RequestType} [request] - The request object.
636
- * @returns {Promise<ResponseType>} - The response object.
637
- */
638
- async delete(route, request) {
639
- return this.pathParamRequest(route, "delete", request);
640
- }
641
640
  };
642
641
 
643
642
  // index.ts
@@ -652,6 +651,9 @@ var universalSdk = async (options) => {
652
651
  if (prop === "then" || prop === "catch" || prop === "finally") {
653
652
  return void 0;
654
653
  }
654
+ if (prop === "fetch") {
655
+ return sdkInternal.executeFetchCall;
656
+ }
655
657
  if (typeof prop === "string" && prop in target) {
656
658
  const value = target[prop];
657
659
  if (typeof value === "function") {
@@ -659,33 +661,34 @@ var universalSdk = async (options) => {
659
661
  }
660
662
  return value;
661
663
  }
662
- return new Proxy(() => {
663
- }, {
664
- get(_innerTarget, innerProp) {
665
- if (typeof innerProp === "string" && innerProp in target) {
666
- const value = target[innerProp];
667
- if (typeof value === "function") {
668
- return value.bind(target);
669
- }
670
- return value;
671
- }
672
- return new Proxy(() => {
673
- }, {
674
- get(__innerTarget, deepProp) {
675
- if (typeof deepProp === "string" && deepProp in target) {
676
- const value = target[deepProp];
677
- if (typeof value === "function") {
678
- return value.bind(target);
679
- }
680
- return value;
681
- }
682
- return void 0;
683
- }
684
- });
685
- }
686
- });
664
+ return createSdkProxy([prop]);
687
665
  }
688
666
  });
667
+ function createSdkProxy(path) {
668
+ return new Proxy(() => {
669
+ }, {
670
+ get(_target, prop) {
671
+ if (prop === "then" || prop === "catch" || prop === "finally") {
672
+ return void 0;
673
+ }
674
+ if (typeof prop === "string" && prop in sdkInternal) {
675
+ const value = sdkInternal[prop];
676
+ if (typeof value === "function") {
677
+ return value.bind(sdkInternal);
678
+ }
679
+ return value;
680
+ }
681
+ const newPath = [...path, prop];
682
+ if (prop === Symbol.toPrimitive || prop === "valueOf" || prop === "toString") {
683
+ return () => sdkInternal.executeSdkCall(path.join("."));
684
+ }
685
+ return createSdkProxy(newPath);
686
+ },
687
+ apply(_target, _thisArg, args) {
688
+ return sdkInternal.executeSdkCall(path.join("."), ...args);
689
+ }
690
+ });
691
+ }
689
692
  return proxyInternal;
690
693
  };
691
694
  // Annotate the CommonJS export names for ESM import in node:
package/lib/index.mjs CHANGED
@@ -1,5 +1,9 @@
1
1
  // src/universalSdk.ts
2
- import { safeParse, safeStringify } from "@forklaunch/common";
2
+ import {
3
+ openApiCompliantPath,
4
+ safeParse,
5
+ safeStringify
6
+ } from "@forklaunch/common";
3
7
  import Ajv from "ajv";
4
8
  import addFormats from "ajv-formats";
5
9
 
@@ -134,7 +138,33 @@ function mapContentType(contentType) {
134
138
  }
135
139
  }
136
140
 
137
- // src/core/refreshOpenApi.ts
141
+ // src/core/openApi.ts
142
+ function getSdkPathMap(registryOpenApiJson) {
143
+ const sdkPathMap = {};
144
+ Object.entries(registryOpenApiJson?.paths || {}).forEach(
145
+ ([path, pathItem]) => {
146
+ const methods = [
147
+ "get",
148
+ "post",
149
+ "put",
150
+ "patch",
151
+ "delete",
152
+ "options",
153
+ "head",
154
+ "trace"
155
+ ];
156
+ methods.forEach((method) => {
157
+ if (pathItem[method]?.operationId) {
158
+ sdkPathMap[pathItem[method].operationId] = {
159
+ method,
160
+ path
161
+ };
162
+ }
163
+ });
164
+ }
165
+ );
166
+ return sdkPathMap;
167
+ }
138
168
  async function refreshOpenApi(host, registryOptions, existingRegistryOpenApiHash) {
139
169
  if (existingRegistryOpenApiHash === "static" || "static" in registryOptions && registryOptions.static) {
140
170
  return {
@@ -145,7 +175,8 @@ async function refreshOpenApi(host, registryOptions, existingRegistryOpenApiHash
145
175
  return {
146
176
  updateRequired: true,
147
177
  registryOpenApiJson: registryOptions.raw,
148
- registryOpenApiHash: "static"
178
+ registryOpenApiHash: "static",
179
+ sdkPathMap: getSdkPathMap(registryOptions.raw)
149
180
  };
150
181
  }
151
182
  const registry = "path" in registryOptions ? `${host}/${registryOptions.path}` : "url" in registryOptions ? registryOptions.url : null;
@@ -160,7 +191,8 @@ async function refreshOpenApi(host, registryOptions, existingRegistryOpenApiHash
160
191
  return {
161
192
  updateRequired: true,
162
193
  registryOpenApiJson,
163
- registryOpenApiHash
194
+ registryOpenApiHash,
195
+ sdkPathMap: getSdkPathMap(registryOpenApiJson)
164
196
  };
165
197
  }
166
198
  return {
@@ -276,13 +308,14 @@ function getSdkPath(path) {
276
308
 
277
309
  // src/universalSdk.ts
278
310
  var UniversalSdk = class _UniversalSdk {
279
- constructor(host, ajv, registryOptions, contentTypeParserMap, registryOpenApiJson, registryOpenApiHash) {
311
+ constructor(host, ajv, registryOptions, contentTypeParserMap, registryOpenApiJson, registryOpenApiHash, sdkPathMap) {
280
312
  this.host = host;
281
313
  this.ajv = ajv;
282
314
  this.registryOptions = registryOptions;
283
315
  this.contentTypeParserMap = contentTypeParserMap;
284
316
  this.registryOpenApiJson = registryOpenApiJson;
285
317
  this.registryOpenApiHash = registryOpenApiHash;
318
+ this.sdkPathMap = sdkPathMap;
286
319
  }
287
320
  /**
288
321
  * Creates an instance of UniversalSdk.
@@ -293,9 +326,11 @@ var UniversalSdk = class _UniversalSdk {
293
326
  const refreshResult = await refreshOpenApi(host, registryOptions);
294
327
  let registryOpenApiJson;
295
328
  let registryOpenApiHash;
329
+ let sdkPathMap;
296
330
  if (refreshResult.updateRequired) {
297
331
  registryOpenApiJson = refreshResult.registryOpenApiJson;
298
332
  registryOpenApiHash = refreshResult.registryOpenApiHash;
333
+ sdkPathMap = refreshResult.sdkPathMap;
299
334
  }
300
335
  const ajv = new Ajv({
301
336
  coerceTypes: true,
@@ -309,18 +344,11 @@ var UniversalSdk = class _UniversalSdk {
309
344
  registryOptions,
310
345
  contentTypeParserMap,
311
346
  registryOpenApiJson,
312
- registryOpenApiHash
347
+ registryOpenApiHash,
348
+ sdkPathMap
313
349
  );
314
350
  }
315
- /**
316
- * Executes an HTTP request.
317
- *
318
- * @param {string} route - The route path for the request.
319
- * @param {'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'} method - The HTTP method.
320
- * @param {RequestType} [request] - The request object.
321
- * @returns {Promise<ResponseType>} - The response object.
322
- */
323
- async execute(route, method, request) {
351
+ async executeFetchCall(path, request) {
324
352
  if (!this.host) {
325
353
  throw new Error("Host not initialized, please run .create(..) first");
326
354
  }
@@ -332,9 +360,53 @@ var UniversalSdk = class _UniversalSdk {
332
360
  if (refreshResult.updateRequired) {
333
361
  this.registryOpenApiJson = refreshResult.registryOpenApiJson;
334
362
  this.registryOpenApiHash = refreshResult.registryOpenApiHash;
363
+ this.sdkPathMap = refreshResult.sdkPathMap;
364
+ }
365
+ return this.execute(path, request?.method ?? "get", request);
366
+ }
367
+ async executeSdkCall(sdkPath, request) {
368
+ if (!this.host) {
369
+ throw new Error("Host not initialized, please run .create(..) first");
370
+ }
371
+ const refreshResult = await refreshOpenApi(
372
+ this.host,
373
+ this.registryOptions,
374
+ this.registryOpenApiHash
375
+ );
376
+ if (refreshResult.updateRequired) {
377
+ this.registryOpenApiJson = refreshResult.registryOpenApiJson;
378
+ this.registryOpenApiHash = refreshResult.registryOpenApiHash;
379
+ this.sdkPathMap = refreshResult.sdkPathMap;
380
+ }
381
+ if (this.sdkPathMap == null) {
382
+ throw new Error(
383
+ "Sdk path map not initialized, please run .create(..) first"
384
+ );
335
385
  }
386
+ const fullSdkPath = sdkPath.split(".");
387
+ while (fullSdkPath.length > 0) {
388
+ fullSdkPath.shift();
389
+ if (fullSdkPath.join(".") in this.sdkPathMap) {
390
+ break;
391
+ }
392
+ }
393
+ if (fullSdkPath.length === 0) {
394
+ throw new Error(`Sdk path not found: ${sdkPath}`);
395
+ }
396
+ const { method, path } = this.sdkPathMap?.[fullSdkPath.join(".")] || {};
397
+ return this.execute(path, method, request);
398
+ }
399
+ /**
400
+ * Executes an HTTP request.
401
+ *
402
+ * @param {string} route - The route path for the request.
403
+ * @param {'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'} method - The HTTP method.
404
+ * @param {RequestType} [request] - The request object.
405
+ * @returns {Promise<ResponseType>} - The response object.
406
+ */
407
+ async execute(path, method, request) {
336
408
  const { params, body, query, headers } = request || {};
337
- let url = getSdkPath(this.host + route);
409
+ let url = getSdkPath(this.host + path);
338
410
  if (params) {
339
411
  for (const key in params) {
340
412
  url = url.replace(`:${key}`, encodeURIComponent(params[key]));
@@ -343,7 +415,10 @@ var UniversalSdk = class _UniversalSdk {
343
415
  let defaultContentType = "application/json";
344
416
  let parsedBody;
345
417
  if (body != null) {
346
- if ("schema" in body && body.schema != null) {
418
+ if (body instanceof File || body instanceof Blob) {
419
+ defaultContentType = "application/octet-stream";
420
+ parsedBody = body;
421
+ } else if ("schema" in body && body.schema != null) {
347
422
  defaultContentType = "application/json";
348
423
  parsedBody = safeStringify(body.schema);
349
424
  } else if ("json" in body && body.json != null) {
@@ -354,7 +429,7 @@ var UniversalSdk = class _UniversalSdk {
354
429
  parsedBody = body.text;
355
430
  } else if ("file" in body && body.file != null) {
356
431
  defaultContentType = "application/octet-stream";
357
- parsedBody = await body.file.text();
432
+ parsedBody = body.file;
358
433
  } else if ("multipartForm" in body && body.multipartForm != null) {
359
434
  defaultContentType = "multipart/form-data";
360
435
  const formData = new FormData();
@@ -395,17 +470,17 @@ var UniversalSdk = class _UniversalSdk {
395
470
  url += queryString ? `?${queryString}` : "";
396
471
  }
397
472
  const response = await fetch(encodeURI(url), {
398
- method: method.toUpperCase(),
473
+ method: method?.toUpperCase(),
399
474
  headers: {
400
475
  ...headers,
401
476
  ...defaultContentType != "multipart/form-data" ? { "Content-Type": body?.contentType ?? defaultContentType } : {}
402
477
  },
403
478
  body: parsedBody
404
479
  });
405
- const responseOpenApi = this.registryOpenApiJson?.paths?.[route]?.[method.toLowerCase()]?.responses?.[response.status];
480
+ const responseOpenApi = path != null && method != null ? this.registryOpenApiJson?.paths?.[openApiCompliantPath(path)]?.[method?.toLowerCase()]?.responses?.[response.status] : null;
406
481
  if (responseOpenApi == null) {
407
482
  throw new Error(
408
- `Response ${response.status} not found in OpenAPI spec for route ${route}`
483
+ `Response ${response.status} not found in OpenAPI spec for ${path} with method ${method}`
409
484
  );
410
485
  }
411
486
  const contentType = (response.headers.get("content-type") || response.headers.get("Content-Type"))?.split(";")[0];
@@ -530,78 +605,6 @@ var UniversalSdk = class _UniversalSdk {
530
605
  headers: response.headers
531
606
  };
532
607
  }
533
- /**
534
- * Executes a request with path parameters.
535
- *
536
- * @param {string} route - The route path for the request.
537
- * @param {'GET' | 'DELETE'} method - The HTTP method.
538
- * @param {RequestType} [request] - The request object.
539
- * @returns {Promise<ResponseType>} - The response object.
540
- */
541
- async pathParamRequest(route, method, request) {
542
- return this.execute(route, method, request);
543
- }
544
- /**
545
- * Executes a request with a body.
546
- *
547
- * @param {string} route - The route path for the request.
548
- * @param {'POST' | 'PUT' | 'PATCH'} method - The HTTP method.
549
- * @param {RequestType} [request] - The request object.
550
- * @returns {Promise<ResponseType>} - The response object.
551
- */
552
- async bodyRequest(route, method, request) {
553
- return this.execute(route, method, request);
554
- }
555
- /**
556
- * Executes a GET request.
557
- *
558
- * @param {string} route - The route path for the request.
559
- * @param {RequestType} [request] - The request object.
560
- * @returns {Promise<ResponseType>} - The response object.
561
- */
562
- async get(route, request) {
563
- return this.pathParamRequest(route, "get", request);
564
- }
565
- /**
566
- * Executes a POST request.
567
- *
568
- * @param {string} route - The route path for the request.
569
- * @param {RequestType} [request] - The request object.
570
- * @returns {Promise<ResponseType>} - The response object.
571
- */
572
- async post(route, request) {
573
- return this.bodyRequest(route, "post", request);
574
- }
575
- /**
576
- * Executes a PUT request.
577
- *
578
- * @param {string} route - The route path for the request.
579
- * @param {RequestType} [request] - The request object.
580
- * @returns {Promise<ResponseType>} - The response object.
581
- */
582
- async put(route, request) {
583
- return this.bodyRequest(route, "put", request);
584
- }
585
- /**
586
- * Executes a PATCH request.
587
- *
588
- * @param {string} route - The route path for the request.
589
- * @param {RequestType} [request] - The request object.
590
- * @returns {Promise<ResponseType>} - The response object.
591
- */
592
- async patch(route, request) {
593
- return this.bodyRequest(route, "patch", request);
594
- }
595
- /**
596
- * Executes a DELETE request.
597
- *
598
- * @param {string} route - The route path for the request.
599
- * @param {RequestType} [request] - The request object.
600
- * @returns {Promise<ResponseType>} - The response object.
601
- */
602
- async delete(route, request) {
603
- return this.pathParamRequest(route, "delete", request);
604
- }
605
608
  };
606
609
 
607
610
  // index.ts
@@ -616,6 +619,9 @@ var universalSdk = async (options) => {
616
619
  if (prop === "then" || prop === "catch" || prop === "finally") {
617
620
  return void 0;
618
621
  }
622
+ if (prop === "fetch") {
623
+ return sdkInternal.executeFetchCall;
624
+ }
619
625
  if (typeof prop === "string" && prop in target) {
620
626
  const value = target[prop];
621
627
  if (typeof value === "function") {
@@ -623,33 +629,34 @@ var universalSdk = async (options) => {
623
629
  }
624
630
  return value;
625
631
  }
626
- return new Proxy(() => {
627
- }, {
628
- get(_innerTarget, innerProp) {
629
- if (typeof innerProp === "string" && innerProp in target) {
630
- const value = target[innerProp];
631
- if (typeof value === "function") {
632
- return value.bind(target);
633
- }
634
- return value;
635
- }
636
- return new Proxy(() => {
637
- }, {
638
- get(__innerTarget, deepProp) {
639
- if (typeof deepProp === "string" && deepProp in target) {
640
- const value = target[deepProp];
641
- if (typeof value === "function") {
642
- return value.bind(target);
643
- }
644
- return value;
645
- }
646
- return void 0;
647
- }
648
- });
649
- }
650
- });
632
+ return createSdkProxy([prop]);
651
633
  }
652
634
  });
635
+ function createSdkProxy(path) {
636
+ return new Proxy(() => {
637
+ }, {
638
+ get(_target, prop) {
639
+ if (prop === "then" || prop === "catch" || prop === "finally") {
640
+ return void 0;
641
+ }
642
+ if (typeof prop === "string" && prop in sdkInternal) {
643
+ const value = sdkInternal[prop];
644
+ if (typeof value === "function") {
645
+ return value.bind(sdkInternal);
646
+ }
647
+ return value;
648
+ }
649
+ const newPath = [...path, prop];
650
+ if (prop === Symbol.toPrimitive || prop === "valueOf" || prop === "toString") {
651
+ return () => sdkInternal.executeSdkCall(path.join("."));
652
+ }
653
+ return createSdkProxy(newPath);
654
+ },
655
+ apply(_target, _thisArg, args) {
656
+ return sdkInternal.executeSdkCall(path.join("."), ...args);
657
+ }
658
+ });
659
+ }
653
660
  return proxyInternal;
654
661
  };
655
662
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forklaunch/universal-sdk",
3
- "version": "0.3.16",
3
+ "version": "0.4.0",
4
4
  "description": "Cross runtime fetch library for forklaunch router sdks",
5
5
  "keywords": [
6
6
  "fetch",
@@ -33,18 +33,18 @@
33
33
  "dependencies": {
34
34
  "ajv": "^8.17.1",
35
35
  "ajv-formats": "^3.0.1",
36
- "@forklaunch/common": "0.3.14"
36
+ "@forklaunch/common": "0.4.0"
37
37
  },
38
38
  "devDependencies": {
39
- "@types/node": "^24.0.3",
40
- "@typescript/native-preview": "7.0.0-dev.20250619.1",
39
+ "@types/node": "^24.0.7",
40
+ "@typescript/native-preview": "7.0.0-dev.20250630.1",
41
41
  "fetch-mock": "^12.5.3",
42
- "jest": "^30.0.2",
43
- "openapi3-ts": "^4.4.0",
44
- "prettier": "^3.5.3",
42
+ "jest": "^30.0.3",
43
+ "openapi3-ts": "^4.5.0",
44
+ "prettier": "^3.6.2",
45
45
  "ts-jest": "^29.4.0",
46
46
  "tsup": "^8.5.0",
47
- "typedoc": "^0.28.5"
47
+ "typedoc": "^0.28.7"
48
48
  },
49
49
  "scripts": {
50
50
  "build": "tsgo --noEmit && tsup index.ts --format cjs,esm --no-splitting --dts --tsconfig tsconfig.json --out-dir lib --clean",