qstd 0.3.26 → 0.3.28

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.
@@ -12,6 +12,7 @@ var clientS3 = require('@aws-sdk/client-s3');
12
12
  var s3RequestPresigner = require('@aws-sdk/s3-request-presigner');
13
13
  var s3PresignedPost = require('@aws-sdk/s3-presigned-post');
14
14
 
15
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
15
16
  var __defProp = Object.defineProperty;
16
17
  var __export = (target, all) => {
17
18
  for (var name in all)
@@ -636,6 +637,222 @@ var label = (name) => ({
636
637
  }
637
638
  });
638
639
 
640
+ // src/shared/api/index.ts
641
+ var api_exports = {};
642
+ __export(api_exports, {
643
+ RestError: () => RestError,
644
+ configure: () => configure,
645
+ get: () => get,
646
+ patch: () => patch,
647
+ post: () => post,
648
+ put: () => put,
649
+ remove: () => remove
650
+ });
651
+
652
+ // src/shared/api/types.ts
653
+ var RestError = class extends Error {
654
+ status;
655
+ body;
656
+ constructor(props) {
657
+ super(`REST ${props.status}: ${props.body}`);
658
+ this.name = "RestError";
659
+ this.status = props.status;
660
+ this.body = props.body;
661
+ }
662
+ };
663
+
664
+ // src/shared/api/fns.ts
665
+ var isDev = () => {
666
+ if (typeof process !== "undefined" && process.env?.NODE_ENV) {
667
+ return process.env.NODE_ENV !== "production";
668
+ }
669
+ if (typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)) }) !== "undefined" && undefined?.DEV !== void 0) {
670
+ return undefined.DEV;
671
+ }
672
+ return false;
673
+ };
674
+ var isAbsolute = (path) => path.startsWith("http");
675
+ var prepareUrl = (path, props) => {
676
+ if (isDev() && !isAbsolute(path) && path.includes("?") && path.split("?")[1]?.split("#")[0]) {
677
+ console.warn(
678
+ `[api] Query params detected in path string. Prefer using the 'params' option instead: Api.get("/path", { params: { ... } }). Path: ${path}`
679
+ );
680
+ }
681
+ const base = isAbsolute(path) ? "" : props.baseUrl;
682
+ let url = `${base}${path}`;
683
+ if (props.params) {
684
+ const searchParams = new URLSearchParams();
685
+ for (const [key, value] of Object.entries(props.params)) {
686
+ if (value != null) searchParams.set(key, String(value));
687
+ }
688
+ const qs = searchParams.toString();
689
+ if (qs) url += (url.includes("?") ? "&" : "?") + qs;
690
+ }
691
+ return url;
692
+ };
693
+ var prepareHeaders = async (props) => {
694
+ const { defaults, headersOption, input, body } = props;
695
+ if (headersOption === false) return void 0;
696
+ const headers = { ...defaults };
697
+ if (body instanceof FormData) ; else if (body instanceof Blob && body.type) {
698
+ headers["Content-Type"] = body.type;
699
+ } else if (input === "json") {
700
+ headers["Content-Type"] = "application/json";
701
+ } else if (input === "text") {
702
+ headers["Content-Type"] = "text/plain";
703
+ }
704
+ if (headersOption === void 0 || headersOption === true) {
705
+ return headers;
706
+ }
707
+ return await headersOption(headers);
708
+ };
709
+ var prepareBody = (body, input) => {
710
+ if (body === void 0) return void 0;
711
+ if (body instanceof FormData) return body;
712
+ if (body instanceof Blob) return body;
713
+ if (input === "json") return JSON.stringify(body);
714
+ if (input === "text") {
715
+ if (typeof body === "string") return body;
716
+ throw new Error("[api] input: 'text' requires a string body");
717
+ }
718
+ if (input === "form") {
719
+ const fd = new FormData();
720
+ for (const [k, v] of Object.entries(body)) {
721
+ fd.append(k, v);
722
+ }
723
+ return fd;
724
+ }
725
+ return body;
726
+ };
727
+ var parseResponse = async (response2, output, onProgress) => {
728
+ const out = output ?? "json";
729
+ if (out === "stream") {
730
+ return response2.body;
731
+ }
732
+ if (onProgress && response2.body) {
733
+ const total = Number(response2.headers.get("Content-Length")) || 0;
734
+ let loaded = 0;
735
+ const reader = response2.body.getReader();
736
+ const chunks = [];
737
+ while (true) {
738
+ const { done, value } = await reader.read();
739
+ if (done) break;
740
+ chunks.push(value);
741
+ loaded += value.length;
742
+ onProgress({
743
+ loaded,
744
+ total,
745
+ percent: total ? Math.round(loaded / total * 100) : 0
746
+ });
747
+ }
748
+ const blob = new Blob(chunks);
749
+ if (out === "blob") return blob;
750
+ if (out === "arrayBuffer")
751
+ return await blob.arrayBuffer();
752
+ if (out === "text") return await blob.text();
753
+ const text2 = await blob.text();
754
+ return text2 ? JSON.parse(text2) : null;
755
+ }
756
+ if (out === "blob")
757
+ return await response2.blob();
758
+ if (out === "arrayBuffer")
759
+ return await response2.arrayBuffer();
760
+ if (out === "text")
761
+ return await response2.text();
762
+ const text = await response2.text();
763
+ return text ? JSON.parse(text) : null;
764
+ };
765
+
766
+ // src/shared/api/domain.ts
767
+ var config = { baseUrl: "" };
768
+ var configure = (c) => {
769
+ config = c;
770
+ };
771
+ var configHeaders = async () => {
772
+ if (!config.headers) return {};
773
+ return typeof config.headers === "function" ? await config.headers() : config.headers;
774
+ };
775
+ var request = async (method, path, options, defaultInput) => {
776
+ const opts = options;
777
+ const url = prepareUrl(path, {
778
+ baseUrl: config.baseUrl,
779
+ ...opts?.params ? { params: opts.params } : {}
780
+ });
781
+ const rawBody = opts?.body;
782
+ const isAutoDetect = rawBody instanceof FormData || rawBody instanceof Blob;
783
+ const input = opts && "input" in opts && opts.input !== void 0 ? opts.input : isAutoDetect ? void 0 : defaultInput;
784
+ const headersOption = opts?.headers;
785
+ const isExternal = isAbsolute(path);
786
+ const defaults = headersOption !== false && !isExternal ? await configHeaders() : {};
787
+ const headers = await prepareHeaders({
788
+ defaults,
789
+ headersOption,
790
+ input,
791
+ body: rawBody
792
+ });
793
+ const body = prepareBody(rawBody, input);
794
+ const response2 = await fetch(url, {
795
+ method,
796
+ ...headers && { headers },
797
+ ...body !== void 0 && { body },
798
+ ...opts?.signal && { signal: opts.signal }
799
+ });
800
+ if (!response2.ok) {
801
+ const error2 = new RestError({
802
+ status: response2.status,
803
+ body: await response2.text()
804
+ });
805
+ if (opts?.onError) return opts.onError(error2);
806
+ throw error2;
807
+ }
808
+ const data = await parseResponse(
809
+ response2,
810
+ opts?.output,
811
+ opts?.onProgress
812
+ );
813
+ return opts?.onSuccess ? opts.onSuccess(data) : data;
814
+ };
815
+ function get(path, opts) {
816
+ return request(
817
+ "GET",
818
+ path,
819
+ opts
820
+ );
821
+ }
822
+ function post(path, body, opts) {
823
+ return request(
824
+ "POST",
825
+ path,
826
+ { ...opts, body },
827
+ "json"
828
+ );
829
+ }
830
+ function put(path, body, opts) {
831
+ return request(
832
+ "PUT",
833
+ path,
834
+ { ...opts, body },
835
+ "json"
836
+ );
837
+ }
838
+ function patch(path, body, opts) {
839
+ return request(
840
+ "PATCH",
841
+ path,
842
+ { ...opts, body },
843
+ "json"
844
+ );
845
+ }
846
+ function remove(path, body, opts) {
847
+ const defaultInput = body !== void 0 ? "json" : void 0;
848
+ return request(
849
+ "DELETE",
850
+ path,
851
+ { ...opts, body },
852
+ defaultInput
853
+ );
854
+ }
855
+
639
856
  // src/server/file/index.ts
640
857
  var file_exports = {};
641
858
  __export(file_exports, {
@@ -770,7 +987,7 @@ __export(ddb_exports, {
770
987
  lsiNormalized: () => lsiNormalized,
771
988
  lsiPhash: () => lsiPhash,
772
989
  lsiUsername: () => lsiUsername,
773
- remove: () => remove,
990
+ remove: () => remove2,
774
991
  save: () => save,
775
992
  tableExists: () => tableExists
776
993
  });
@@ -1059,7 +1276,7 @@ async function find(ddb, props) {
1059
1276
  throw err;
1060
1277
  }
1061
1278
  }
1062
- var remove = async (ddb, props) => {
1279
+ var remove2 = async (ddb, props) => {
1063
1280
  const TableName = getTableNameOrThrow(props.tableName, ddb.tableName);
1064
1281
  const command = new libDynamodb.DeleteCommand({ Key: props.key, TableName });
1065
1282
  return ddb.client.send(command);
@@ -1637,6 +1854,7 @@ var recordsFromSqs = (body) => {
1637
1854
  }
1638
1855
  };
1639
1856
 
1857
+ exports.Api = api_exports;
1640
1858
  exports.DDB = ddb_exports;
1641
1859
  exports.Dict = dict_exports;
1642
1860
  exports.File = file_exports;
@@ -7,6 +7,7 @@ export * as Time from "../shared/time";
7
7
  export * as Flow from "../shared/flow";
8
8
  export * as Random from "../shared/random";
9
9
  export * as Log from "../shared/log";
10
+ export * as Api from "../shared/api";
10
11
  export * as File from "./file";
11
12
  export * as Lambda from "./aws/lambda";
12
13
  export * as DDB from "./aws/ddb";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,IAAI,MAAM,gBAAgB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,gBAAgB,CAAC;AACvC,OAAO,KAAK,GAAG,MAAM,eAAe,CAAC;AACrC,OAAO,KAAK,GAAG,MAAM,eAAe,CAAC;AACrC,OAAO,KAAK,KAAK,MAAM,iBAAiB,CAAC;AACzC,OAAO,KAAK,IAAI,MAAM,gBAAgB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,gBAAgB,CAAC;AACvC,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;AAC3C,OAAO,KAAK,GAAG,MAAM,eAAe,CAAC;AAGrC,OAAO,KAAK,IAAI,MAAM,QAAQ,CAAC;AAC/B,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AACvC,OAAO,KAAK,GAAG,MAAM,WAAW,CAAC;AACjC,OAAO,KAAK,GAAG,MAAM,WAAW,CAAC;AACjC,OAAO,KAAK,GAAG,MAAM,WAAW,CAAC;AACjC,OAAO,KAAK,GAAG,MAAM,WAAW,CAAC;AACjC,OAAO,KAAK,EAAE,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,IAAI,MAAM,gBAAgB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,gBAAgB,CAAC;AACvC,OAAO,KAAK,GAAG,MAAM,eAAe,CAAC;AACrC,OAAO,KAAK,GAAG,MAAM,eAAe,CAAC;AACrC,OAAO,KAAK,KAAK,MAAM,iBAAiB,CAAC;AACzC,OAAO,KAAK,IAAI,MAAM,gBAAgB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,gBAAgB,CAAC;AACvC,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;AAC3C,OAAO,KAAK,GAAG,MAAM,eAAe,CAAC;AACrC,OAAO,KAAK,GAAG,MAAM,eAAe,CAAC;AAGrC,OAAO,KAAK,IAAI,MAAM,QAAQ,CAAC;AAC/B,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AACvC,OAAO,KAAK,GAAG,MAAM,WAAW,CAAC;AACjC,OAAO,KAAK,GAAG,MAAM,WAAW,CAAC;AACjC,OAAO,KAAK,GAAG,MAAM,WAAW,CAAC;AACjC,OAAO,KAAK,GAAG,MAAM,WAAW,CAAC;AACjC,OAAO,KAAK,EAAE,MAAM,UAAU,CAAC"}
@@ -634,6 +634,222 @@ var label = (name) => ({
634
634
  }
635
635
  });
636
636
 
637
+ // src/shared/api/index.ts
638
+ var api_exports = {};
639
+ __export(api_exports, {
640
+ RestError: () => RestError,
641
+ configure: () => configure,
642
+ get: () => get,
643
+ patch: () => patch,
644
+ post: () => post,
645
+ put: () => put,
646
+ remove: () => remove
647
+ });
648
+
649
+ // src/shared/api/types.ts
650
+ var RestError = class extends Error {
651
+ status;
652
+ body;
653
+ constructor(props) {
654
+ super(`REST ${props.status}: ${props.body}`);
655
+ this.name = "RestError";
656
+ this.status = props.status;
657
+ this.body = props.body;
658
+ }
659
+ };
660
+
661
+ // src/shared/api/fns.ts
662
+ var isDev = () => {
663
+ if (typeof process !== "undefined" && process.env?.NODE_ENV) {
664
+ return process.env.NODE_ENV !== "production";
665
+ }
666
+ if (typeof import.meta !== "undefined" && import.meta.env?.DEV !== void 0) {
667
+ return import.meta.env.DEV;
668
+ }
669
+ return false;
670
+ };
671
+ var isAbsolute = (path) => path.startsWith("http");
672
+ var prepareUrl = (path, props) => {
673
+ if (isDev() && !isAbsolute(path) && path.includes("?") && path.split("?")[1]?.split("#")[0]) {
674
+ console.warn(
675
+ `[api] Query params detected in path string. Prefer using the 'params' option instead: Api.get("/path", { params: { ... } }). Path: ${path}`
676
+ );
677
+ }
678
+ const base = isAbsolute(path) ? "" : props.baseUrl;
679
+ let url = `${base}${path}`;
680
+ if (props.params) {
681
+ const searchParams = new URLSearchParams();
682
+ for (const [key, value] of Object.entries(props.params)) {
683
+ if (value != null) searchParams.set(key, String(value));
684
+ }
685
+ const qs = searchParams.toString();
686
+ if (qs) url += (url.includes("?") ? "&" : "?") + qs;
687
+ }
688
+ return url;
689
+ };
690
+ var prepareHeaders = async (props) => {
691
+ const { defaults, headersOption, input, body } = props;
692
+ if (headersOption === false) return void 0;
693
+ const headers = { ...defaults };
694
+ if (body instanceof FormData) ; else if (body instanceof Blob && body.type) {
695
+ headers["Content-Type"] = body.type;
696
+ } else if (input === "json") {
697
+ headers["Content-Type"] = "application/json";
698
+ } else if (input === "text") {
699
+ headers["Content-Type"] = "text/plain";
700
+ }
701
+ if (headersOption === void 0 || headersOption === true) {
702
+ return headers;
703
+ }
704
+ return await headersOption(headers);
705
+ };
706
+ var prepareBody = (body, input) => {
707
+ if (body === void 0) return void 0;
708
+ if (body instanceof FormData) return body;
709
+ if (body instanceof Blob) return body;
710
+ if (input === "json") return JSON.stringify(body);
711
+ if (input === "text") {
712
+ if (typeof body === "string") return body;
713
+ throw new Error("[api] input: 'text' requires a string body");
714
+ }
715
+ if (input === "form") {
716
+ const fd = new FormData();
717
+ for (const [k, v] of Object.entries(body)) {
718
+ fd.append(k, v);
719
+ }
720
+ return fd;
721
+ }
722
+ return body;
723
+ };
724
+ var parseResponse = async (response2, output, onProgress) => {
725
+ const out = output ?? "json";
726
+ if (out === "stream") {
727
+ return response2.body;
728
+ }
729
+ if (onProgress && response2.body) {
730
+ const total = Number(response2.headers.get("Content-Length")) || 0;
731
+ let loaded = 0;
732
+ const reader = response2.body.getReader();
733
+ const chunks = [];
734
+ while (true) {
735
+ const { done, value } = await reader.read();
736
+ if (done) break;
737
+ chunks.push(value);
738
+ loaded += value.length;
739
+ onProgress({
740
+ loaded,
741
+ total,
742
+ percent: total ? Math.round(loaded / total * 100) : 0
743
+ });
744
+ }
745
+ const blob = new Blob(chunks);
746
+ if (out === "blob") return blob;
747
+ if (out === "arrayBuffer")
748
+ return await blob.arrayBuffer();
749
+ if (out === "text") return await blob.text();
750
+ const text2 = await blob.text();
751
+ return text2 ? JSON.parse(text2) : null;
752
+ }
753
+ if (out === "blob")
754
+ return await response2.blob();
755
+ if (out === "arrayBuffer")
756
+ return await response2.arrayBuffer();
757
+ if (out === "text")
758
+ return await response2.text();
759
+ const text = await response2.text();
760
+ return text ? JSON.parse(text) : null;
761
+ };
762
+
763
+ // src/shared/api/domain.ts
764
+ var config = { baseUrl: "" };
765
+ var configure = (c) => {
766
+ config = c;
767
+ };
768
+ var configHeaders = async () => {
769
+ if (!config.headers) return {};
770
+ return typeof config.headers === "function" ? await config.headers() : config.headers;
771
+ };
772
+ var request = async (method, path, options, defaultInput) => {
773
+ const opts = options;
774
+ const url = prepareUrl(path, {
775
+ baseUrl: config.baseUrl,
776
+ ...opts?.params ? { params: opts.params } : {}
777
+ });
778
+ const rawBody = opts?.body;
779
+ const isAutoDetect = rawBody instanceof FormData || rawBody instanceof Blob;
780
+ const input = opts && "input" in opts && opts.input !== void 0 ? opts.input : isAutoDetect ? void 0 : defaultInput;
781
+ const headersOption = opts?.headers;
782
+ const isExternal = isAbsolute(path);
783
+ const defaults = headersOption !== false && !isExternal ? await configHeaders() : {};
784
+ const headers = await prepareHeaders({
785
+ defaults,
786
+ headersOption,
787
+ input,
788
+ body: rawBody
789
+ });
790
+ const body = prepareBody(rawBody, input);
791
+ const response2 = await fetch(url, {
792
+ method,
793
+ ...headers && { headers },
794
+ ...body !== void 0 && { body },
795
+ ...opts?.signal && { signal: opts.signal }
796
+ });
797
+ if (!response2.ok) {
798
+ const error2 = new RestError({
799
+ status: response2.status,
800
+ body: await response2.text()
801
+ });
802
+ if (opts?.onError) return opts.onError(error2);
803
+ throw error2;
804
+ }
805
+ const data = await parseResponse(
806
+ response2,
807
+ opts?.output,
808
+ opts?.onProgress
809
+ );
810
+ return opts?.onSuccess ? opts.onSuccess(data) : data;
811
+ };
812
+ function get(path, opts) {
813
+ return request(
814
+ "GET",
815
+ path,
816
+ opts
817
+ );
818
+ }
819
+ function post(path, body, opts) {
820
+ return request(
821
+ "POST",
822
+ path,
823
+ { ...opts, body },
824
+ "json"
825
+ );
826
+ }
827
+ function put(path, body, opts) {
828
+ return request(
829
+ "PUT",
830
+ path,
831
+ { ...opts, body },
832
+ "json"
833
+ );
834
+ }
835
+ function patch(path, body, opts) {
836
+ return request(
837
+ "PATCH",
838
+ path,
839
+ { ...opts, body },
840
+ "json"
841
+ );
842
+ }
843
+ function remove(path, body, opts) {
844
+ const defaultInput = body !== void 0 ? "json" : void 0;
845
+ return request(
846
+ "DELETE",
847
+ path,
848
+ { ...opts, body },
849
+ defaultInput
850
+ );
851
+ }
852
+
637
853
  // src/server/file/index.ts
638
854
  var file_exports = {};
639
855
  __export(file_exports, {
@@ -768,7 +984,7 @@ __export(ddb_exports, {
768
984
  lsiNormalized: () => lsiNormalized,
769
985
  lsiPhash: () => lsiPhash,
770
986
  lsiUsername: () => lsiUsername,
771
- remove: () => remove,
987
+ remove: () => remove2,
772
988
  save: () => save,
773
989
  tableExists: () => tableExists
774
990
  });
@@ -1057,7 +1273,7 @@ async function find(ddb, props) {
1057
1273
  throw err;
1058
1274
  }
1059
1275
  }
1060
- var remove = async (ddb, props) => {
1276
+ var remove2 = async (ddb, props) => {
1061
1277
  const TableName = getTableNameOrThrow(props.tableName, ddb.tableName);
1062
1278
  const command = new DeleteCommand({ Key: props.key, TableName });
1063
1279
  return ddb.client.send(command);
@@ -1635,4 +1851,4 @@ var recordsFromSqs = (body) => {
1635
1851
  }
1636
1852
  };
1637
1853
 
1638
- export { ddb_exports as DDB, dict_exports as Dict, file_exports as File, flow_exports as Flow, int_exports as Int, lambda_exports as Lambda, list_exports as List, log_exports as Log, money_exports as Money, random_exports as Random, s3_exports as S3, ses_exports as SES, sns_exports as SNS, sqs_exports as SQS, str_exports as Str, time_exports as Time };
1854
+ export { api_exports as Api, ddb_exports as DDB, dict_exports as Dict, file_exports as File, flow_exports as Flow, int_exports as Int, lambda_exports as Lambda, list_exports as List, log_exports as Log, money_exports as Money, random_exports as Random, s3_exports as S3, ses_exports as SES, sns_exports as SNS, sqs_exports as SQS, str_exports as Str, time_exports as Time };
@@ -0,0 +1,181 @@
1
+ import type { BodylessOptions, Config, DataForOutput, JsonRes, Options, Output, ReqFrom, ResFrom } from "./types";
2
+ /**
3
+ * Configure the API client with base URL and default headers.
4
+ *
5
+ * Call this once at app startup before making any requests. The headers
6
+ * option can be a static object or an async function that returns headers,
7
+ * useful for dynamic auth tokens that refresh periodically.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * // Static headers
12
+ * Api.configure({
13
+ * baseUrl: "https://api.example.com",
14
+ * headers: { "X-API-Key": "secret" },
15
+ * });
16
+ *
17
+ * // Dynamic headers (called fresh on each request)
18
+ * Api.configure({
19
+ * baseUrl: import.meta.env.VITE_API_URL,
20
+ * headers: async () => ({
21
+ * Authorization: `Bearer ${await getAuthToken()}`,
22
+ * }),
23
+ * });
24
+ * ```
25
+ */
26
+ export declare const configure: (c: Config) => void;
27
+ /**
28
+ * Make a GET request to fetch data.
29
+ *
30
+ * GET requests don't have a body. Use `params` for query parameters.
31
+ * Response is parsed as JSON by default; use `output` for other formats.
32
+ *
33
+ * Notes:
34
+ * - Generics are compile-time only; `output` is what decides runtime decoding.
35
+ * - The return type is derived from `output` (e.g. `output: "blob"` returns `Blob`).
36
+ * - If you try to use a non-JSON decoded response type (like `Blob`) without setting
37
+ * `output`, TypeScript will raise a helpful error type to prevent mismatches.
38
+ *
39
+ * If the response is not ok, this throws a `RestError` unless you provide
40
+ * an `onError` handler to convert the error into a return value.
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * // Simple GET
45
+ * const users = await Api.get<User[]>("/users");
46
+ *
47
+ * // With query params
48
+ * const users = await Api.get<User[]>("/users", {
49
+ * params: { limit: 10, status: "active" },
50
+ * });
51
+ * // → GET /users?limit=10&status=active
52
+ *
53
+ * // Transform response
54
+ * const names = await Api.get("/users", {
55
+ * onSuccess: (users: User[]) => users.map(u => u.name),
56
+ * });
57
+ *
58
+ * // Download as blob
59
+ * const image = await Api.get("/avatar.png", { output: "blob" });
60
+ * ```
61
+ *
62
+ * @throws {RestError} When the response is not ok and no `onError` handler is provided.
63
+ */
64
+ export declare function get<TTypes = unknown, O extends Output | undefined = undefined, Return = unknown>(path: string, opts: Options<JsonRes<ResFrom<TTypes>>, Return, O> & {
65
+ onSuccess: (data: DataForOutput<JsonRes<ResFrom<TTypes>>, O>) => Return;
66
+ }): Promise<Return>;
67
+ export declare function get<TTypes = unknown, O extends Output | undefined = undefined, Return = never>(path: string, opts?: Options<JsonRes<ResFrom<TTypes>>, Return, O> & {
68
+ onSuccess?: undefined;
69
+ }): Promise<DataForOutput<JsonRes<ResFrom<TTypes>>, O> | Return>;
70
+ /**
71
+ * Make a POST request to create a resource.
72
+ *
73
+ * Body handling:
74
+ * - Objects are JSON-serialized by default (Content-Type: application/json)
75
+ * - FormData is auto-detected (browser sets Content-Type with boundary)
76
+ * - Blob is auto-detected (uses blob.type for Content-Type)
77
+ * - Use `input` option to override: "json" | "form" | "text"
78
+ *
79
+ * Notes:
80
+ * - Use named type-args to type both request and response:
81
+ * `Api.post<{ Req: CreateReq; Res: CreateRes }>(...)`
82
+ * - `output` controls runtime decoding and therefore the return type.
83
+ *
84
+ * If the response is not ok, this throws a `RestError` unless you provide
85
+ * an `onError` handler to convert the error into a return value.
86
+ *
87
+ * @example
88
+ * ```ts
89
+ * // JSON body (default for objects)
90
+ * const user = await Api.post<User>("/users", { name: "Alice" });
91
+ *
92
+ * // FormData auto-detected
93
+ * const result = await Api.post("/upload", formData);
94
+ *
95
+ * // External URL (never includes configured default headers like auth)
96
+ * await Api.post(presignedUrl, formData);
97
+ * ```
98
+ *
99
+ * @throws {RestError} When the response is not ok and no `onError` handler is provided.
100
+ */
101
+ export declare function post<TTypes = unknown, O extends Output | undefined = undefined, Return = unknown>(path: string, body: ReqFrom<TTypes>, opts: BodylessOptions<ReqFrom<TTypes>, JsonRes<ResFrom<TTypes>>, Return, O> & {
102
+ onSuccess: (data: DataForOutput<JsonRes<ResFrom<TTypes>>, O>) => Return;
103
+ }): Promise<Return>;
104
+ export declare function post<TTypes = unknown, O extends Output | undefined = undefined, Return = never>(path: string, body?: ReqFrom<TTypes>, opts?: BodylessOptions<ReqFrom<TTypes>, JsonRes<ResFrom<TTypes>>, Return, O> & {
105
+ onSuccess?: undefined;
106
+ }): Promise<DataForOutput<JsonRes<ResFrom<TTypes>>, O> | Return>;
107
+ /**
108
+ * Make a PUT request to replace a resource.
109
+ *
110
+ * Body is JSON-serialized by default. See `post` for `input` options.
111
+ *
112
+ * If the response is not ok, this throws a `RestError` unless you provide
113
+ * an `onError` handler to convert the error into a return value.
114
+ *
115
+ * @example
116
+ * ```ts
117
+ * const user = await Api.put<User>(`/users/${id}`, {
118
+ * name: "Alice",
119
+ * email: "alice@example.com",
120
+ * });
121
+ * ```
122
+ *
123
+ * @throws {RestError} When the response is not ok and no `onError` handler is provided.
124
+ */
125
+ export declare function put<TTypes = unknown, O extends Output | undefined = undefined, Return = unknown>(path: string, body: ReqFrom<TTypes>, opts: BodylessOptions<ReqFrom<TTypes>, JsonRes<ResFrom<TTypes>>, Return, O> & {
126
+ onSuccess: (data: DataForOutput<JsonRes<ResFrom<TTypes>>, O>) => Return;
127
+ }): Promise<Return>;
128
+ export declare function put<TTypes = unknown, O extends Output | undefined = undefined, Return = never>(path: string, body?: ReqFrom<TTypes>, opts?: BodylessOptions<ReqFrom<TTypes>, JsonRes<ResFrom<TTypes>>, Return, O> & {
129
+ onSuccess?: undefined;
130
+ }): Promise<DataForOutput<JsonRes<ResFrom<TTypes>>, O> | Return>;
131
+ /**
132
+ * Make a PATCH request to partially update a resource.
133
+ *
134
+ * Body is JSON-serialized by default. See `post` for `input` options.
135
+ *
136
+ * If the response is not ok, this throws a `RestError` unless you provide
137
+ * an `onError` handler to convert the error into a return value.
138
+ *
139
+ * @example
140
+ * ```ts
141
+ * const user = await Api.patch<User>(`/users/${id}`, { name: "New Name" });
142
+ * ```
143
+ *
144
+ * @throws {RestError} When the response is not ok and no `onError` handler is provided.
145
+ */
146
+ export declare function patch<TTypes = unknown, O extends Output | undefined = undefined, Return = unknown>(path: string, body: ReqFrom<TTypes>, opts: BodylessOptions<ReqFrom<TTypes>, JsonRes<ResFrom<TTypes>>, Return, O> & {
147
+ onSuccess: (data: DataForOutput<JsonRes<ResFrom<TTypes>>, O>) => Return;
148
+ }): Promise<Return>;
149
+ export declare function patch<TTypes = unknown, O extends Output | undefined = undefined, Return = never>(path: string, body?: ReqFrom<TTypes>, opts?: BodylessOptions<ReqFrom<TTypes>, JsonRes<ResFrom<TTypes>>, Return, O> & {
150
+ onSuccess?: undefined;
151
+ }): Promise<DataForOutput<JsonRes<ResFrom<TTypes>>, O> | Return>;
152
+ /**
153
+ * Make a DELETE request to remove a resource.
154
+ *
155
+ * Supports an optional body for batch deletes or similar use cases.
156
+ * Body is JSON-serialized by default when provided.
157
+ *
158
+ * If the response is not ok, this throws a `RestError` unless you provide
159
+ * an `onError` handler to convert the error into a return value.
160
+ *
161
+ * @example
162
+ * ```ts
163
+ * // Simple delete
164
+ * await Api.remove(`/users/${id}`);
165
+ *
166
+ * // With confirmation response
167
+ * const result = await Api.remove<{ deleted: boolean }>(`/users/${id}`);
168
+ *
169
+ * // Batch delete with body
170
+ * await Api.remove("/users", { ids: ["1", "2", "3"] });
171
+ * ```
172
+ *
173
+ * @throws {RestError} When the response is not ok and no `onError` handler is provided.
174
+ */
175
+ export declare function remove<TTypes = unknown, O extends Output | undefined = undefined, Return = unknown>(path: string, body: ReqFrom<TTypes>, opts: BodylessOptions<ReqFrom<TTypes>, JsonRes<ResFrom<TTypes>>, Return, O> & {
176
+ onSuccess: (data: DataForOutput<JsonRes<ResFrom<TTypes>>, O>) => Return;
177
+ }): Promise<Return>;
178
+ export declare function remove<TTypes = unknown, O extends Output | undefined = undefined, Return = never>(path: string, body?: ReqFrom<TTypes>, opts?: BodylessOptions<ReqFrom<TTypes>, JsonRes<ResFrom<TTypes>>, Return, O> & {
179
+ onSuccess?: undefined;
180
+ }): Promise<DataForOutput<JsonRes<ResFrom<TTypes>>, O> | Return>;
181
+ //# sourceMappingURL=domain.d.ts.map