@zayne-labs/callapi 1.11.33 → 1.11.35
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 +1 -1
- package/dist/{guards-ZYV-Q_as.js → external-DXaCWLPN.js} +41 -9
- package/dist/external-DXaCWLPN.js.map +1 -0
- package/dist/{index-YnlEWnbR.d.ts → index-BEp4V3_c.d.ts} +39 -16
- package/dist/index.d.ts +1 -1
- package/dist/index.js +35 -38
- package/dist/index.js.map +1 -1
- package/dist/utils/external/index.d.ts +3 -9
- package/dist/utils/external/index.js +2 -27
- package/package.json +7 -7
- package/dist/guards-ZYV-Q_as.js.map +0 -1
- package/dist/utils/external/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
<a href="https://github.com/zayne-labs/callapi/blob/master/LICENSE"><img src="https://img.shields.io/npm/l/@zayne-labs/callapi?style=flat&color=EFBA5F" alt="license"></a>
|
|
11
11
|
<a href="https://www.npmjs.com/package/@zayne-labs/callapi"><img src="https://img.shields.io/npm/dm/@zayne-labs/callapi?style=flat&color=EFBA5F" alt="downloads per month"></a>
|
|
12
12
|
<a href="https://github.com/zayne-labs/callapi/graphs/commit-activity"><img src="https://img.shields.io/github/commit-activity/m/zayne-labs/callapi?style=flat&color=EFBA5F" alt="commit activity"></a>
|
|
13
|
-
<a href="https://code2tutorial.com/tutorial/f77cfbd0-3c37-4c37-9608-b3c977e46f00/index.md"><img src="https://img.shields.io/badge/Code2Tutorial-blue?color=blue&logo=victoriametrics" alt="Code2Tutorial"></a>
|
|
14
13
|
<a href="https://deepwiki.com/zayne-labs/callapi"><img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki"></a>
|
|
14
|
+
<a href="https://code2tutorial.com/tutorial/f77cfbd0-3c37-4c37-9608-b3c977e46f00/index.md"><img src="https://img.shields.io/badge/Code2Tutorial-blue?color=blue&logo=victoriametrics" alt="Code2Tutorial"></a>
|
|
15
15
|
</p>
|
|
16
16
|
|
|
17
17
|
<p align="center">
|
|
@@ -33,7 +33,7 @@ const isValidJsonString = (value) => {
|
|
|
33
33
|
return false;
|
|
34
34
|
}
|
|
35
35
|
};
|
|
36
|
-
const
|
|
36
|
+
const isSerializableObject = (value) => {
|
|
37
37
|
return isPlainObject(value) || isArray(value) || typeof value?.toJSON === "function";
|
|
38
38
|
};
|
|
39
39
|
const isFunction = (value) => typeof value === "function";
|
|
@@ -46,12 +46,20 @@ const isReadableStream = (value) => {
|
|
|
46
46
|
|
|
47
47
|
//#endregion
|
|
48
48
|
//#region src/utils/external/body.ts
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
const toStringOrStringify = (value) => {
|
|
50
|
+
return isString(value) ? value : JSON.stringify(value);
|
|
51
|
+
};
|
|
52
|
+
const toQueryString = (data) => {
|
|
53
|
+
const queryString = new URLSearchParams();
|
|
54
|
+
for (const [key, value] of Object.entries(data)) {
|
|
55
|
+
if (value == null) continue;
|
|
56
|
+
if (isArray(value)) {
|
|
57
|
+
for (const innerValue of value) queryString.append(key, toStringOrStringify(innerValue));
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
queryString.set(key, toStringOrStringify(value));
|
|
53
61
|
}
|
|
54
|
-
return
|
|
62
|
+
return queryString.toString();
|
|
55
63
|
};
|
|
56
64
|
const toBlobOrString = (value) => {
|
|
57
65
|
return isBlob(value) ? value : String(value);
|
|
@@ -96,7 +104,7 @@ const toFormData = (data) => {
|
|
|
96
104
|
const formData = new FormData();
|
|
97
105
|
for (const [key, value] of Object.entries(data)) {
|
|
98
106
|
if (isArray(value)) {
|
|
99
|
-
|
|
107
|
+
for (const innerValue of value) formData.append(key, toBlobOrString(innerValue));
|
|
100
108
|
continue;
|
|
101
109
|
}
|
|
102
110
|
if (isObject(value) && !isBlob(value)) {
|
|
@@ -175,6 +183,30 @@ var ValidationError = class ValidationError extends Error {
|
|
|
175
183
|
}
|
|
176
184
|
};
|
|
177
185
|
|
|
186
|
+
//#endregion
|
|
187
|
+
//#region src/utils/external/define.ts
|
|
188
|
+
const defineSchema = (routes, config) => {
|
|
189
|
+
return {
|
|
190
|
+
config: defineSchemaConfig(config),
|
|
191
|
+
routes: defineSchemaRoutes(routes)
|
|
192
|
+
};
|
|
193
|
+
};
|
|
194
|
+
const defineSchemaRoutes = (routes) => {
|
|
195
|
+
return routes;
|
|
196
|
+
};
|
|
197
|
+
const defineMainSchema = (mainSchema) => {
|
|
198
|
+
return mainSchema;
|
|
199
|
+
};
|
|
200
|
+
const defineSchemaConfig = (config) => {
|
|
201
|
+
return config;
|
|
202
|
+
};
|
|
203
|
+
const definePlugin = (plugin) => {
|
|
204
|
+
return plugin;
|
|
205
|
+
};
|
|
206
|
+
const defineBaseConfig = (baseConfig) => {
|
|
207
|
+
return baseConfig;
|
|
208
|
+
};
|
|
209
|
+
|
|
178
210
|
//#endregion
|
|
179
211
|
//#region src/utils/external/guards.ts
|
|
180
212
|
const isHTTPError = (error) => {
|
|
@@ -194,5 +226,5 @@ const isJavascriptError = (error) => {
|
|
|
194
226
|
};
|
|
195
227
|
|
|
196
228
|
//#endregion
|
|
197
|
-
export { isReadableStream as _, isValidationErrorInstance as a,
|
|
198
|
-
//# sourceMappingURL=
|
|
229
|
+
export { isReadableStream as C, isValidJsonString as E, isQueryString as S, isString as T, isBoolean as _, isValidationErrorInstance as a, isPlainObject as b, definePlugin as c, defineSchemaRoutes as d, HTTPError as f, isArray as g, toQueryString as h, isValidationError as i, defineSchema as l, toFormData as m, isHTTPErrorInstance as n, defineBaseConfig as o, ValidationError as p, isJavascriptError as r, defineMainSchema as s, isHTTPError as t, defineSchemaConfig as u, isFunction as v, isSerializableObject as w, isPromise as x, isObject as y };
|
|
230
|
+
//# sourceMappingURL=external-DXaCWLPN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"external-DXaCWLPN.js","names":["defineBaseConfig: DefineBaseConfig"],"sources":["../src/utils/guards.ts","../src/utils/external/body.ts","../src/utils/external/error.ts","../src/utils/external/define.ts","../src/utils/external/guards.ts"],"sourcesContent":["import type { AnyFunction } from \"../types/type-helpers\";\n\nexport const isArray = <TArrayItem>(value: unknown): value is TArrayItem[] => Array.isArray(value);\n\nexport const isBoolean = (value: unknown): value is boolean => typeof value === \"boolean\";\n\nexport const isBlob = (value: unknown): value is Blob => value instanceof Blob;\n\nexport const isObject = <TObject extends object>(value: unknown): value is TObject => {\n\treturn typeof value === \"object\" && value !== null;\n};\n\nconst hasObjectPrototype = (value: unknown) => {\n\treturn Object.prototype.toString.call(value) === \"[object Object]\";\n};\n\n/**\n * @description Copied from TanStack Query's isPlainObject\n * @see https://github.com/TanStack/query/blob/main/packages/query-core/src/utils.ts#L321\n */\nexport const isPlainObject = <TPlainObject extends Record<string, unknown>>(\n\tvalue: unknown\n): value is TPlainObject => {\n\tif (!hasObjectPrototype(value)) {\n\t\treturn false;\n\t}\n\n\t// If has no constructor\n\tconst constructor = (value as object | undefined)?.constructor;\n\tif (constructor === undefined) {\n\t\treturn true;\n\t}\n\n\t// If has modified prototype\n\tconst prototype = constructor.prototype as object;\n\tif (!hasObjectPrototype(prototype)) {\n\t\treturn false;\n\t}\n\n\t// If constructor does not have an Object-specific method\n\tif (!Object.hasOwn(prototype, \"isPrototypeOf\")) {\n\t\treturn false;\n\t}\n\n\t// Handles Objects created by Object.create(<arbitrary prototype>)\n\tif (Object.getPrototypeOf(value) !== Object.prototype) {\n\t\treturn false;\n\t}\n\n\t// It's probably a plain object at this point\n\treturn true;\n};\n\nexport const isValidJsonString = (value: unknown): value is string => {\n\tif (!isString(value)) {\n\t\treturn false;\n\t}\n\n\ttry {\n\t\tJSON.parse(value);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n};\n\nexport const isSerializableObject = (value: unknown) => {\n\treturn (\n\t\tisPlainObject(value)\n\t\t|| isArray(value)\n\t\t|| typeof (value as { toJSON: unknown } | undefined)?.toJSON === \"function\"\n\t);\n};\n\nexport const isFunction = <TFunction extends AnyFunction>(value: unknown): value is TFunction =>\n\ttypeof value === \"function\";\n\nexport const isQueryString = (value: unknown): value is string => isString(value) && value.includes(\"=\");\n\nexport const isString = (value: unknown) => typeof value === \"string\";\n\nexport const isPromise = (value: unknown) => value instanceof Promise;\n\nexport const isReadableStream = (value: unknown): value is ReadableStream<unknown> => {\n\treturn value instanceof ReadableStream;\n};\n\n// https://github.com/unjs/ofetch/blob/main/src/utils.ts\nexport const isJSONSerializable = (value: unknown) => {\n\tif (value === undefined) {\n\t\treturn false;\n\t}\n\tconst t = typeof value;\n\t// eslint-disable-next-line ts-eslint/no-unnecessary-condition -- No time to make this more type-safe\n\tif (t === \"string\" || t === \"number\" || t === \"boolean\" || t === null) {\n\t\treturn true;\n\t}\n\tif (t !== \"object\") {\n\t\treturn false;\n\t}\n\tif (isArray(value)) {\n\t\treturn true;\n\t}\n\tif ((value as Buffer | null)?.buffer) {\n\t\treturn false;\n\t}\n\n\treturn (\n\t\tvalue?.constructor.name === \"Object\"\n\t\t|| typeof (value as { toJSON: () => unknown } | null)?.toJSON === \"function\"\n\t);\n};\n","import type { CallApiRequestOptions } from \"../../types/common\";\nimport { isArray, isBlob, isObject, isString } from \"../guards\";\n\nconst toStringOrStringify = (value: unknown): string => {\n\treturn isString(value) ? value : JSON.stringify(value);\n};\n\nexport const toQueryString = (data: NonNullable<CallApiRequestOptions[\"body\"]>) => {\n\tconst queryString = new URLSearchParams();\n\n\tfor (const [key, value] of Object.entries(data)) {\n\t\tif (value == null) continue;\n\n\t\tif (isArray(value)) {\n\t\t\t// eslint-disable-next-line max-depth -- Allow\n\t\t\tfor (const innerValue of value) {\n\t\t\t\tqueryString.append(key, toStringOrStringify(innerValue));\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tqueryString.set(key, toStringOrStringify(value));\n\t}\n\n\treturn queryString.toString();\n};\n\nconst toBlobOrString = (value: unknown): string | Blob => {\n\treturn isBlob(value) ? value : String(value);\n};\n\n/**\n * @description Converts a plain object to FormData.\n *\n * Handles various data types:\n * - **Primitives** (string, number, boolean): Converted to strings\n * - **Blobs/Files**: Added directly to FormData\n * - **Arrays**: Each item is appended (allows multiple values for same key)\n * - **Objects**: JSON stringified before adding to FormData\n *\n * @example\n * ```ts\n * // Basic usage\n * const formData = toFormData({\n * name: \"John\",\n * age: 30,\n * active: true\n * });\n *\n * // With arrays\n * const formData = toFormData({\n * tags: [\"javascript\", \"typescript\"],\n * name: \"John\"\n * });\n *\n * // With files\n * const formData = toFormData({\n * avatar: fileBlob,\n * name: \"John\"\n * });\n *\n * // With nested objects (one level only)\n * const formData = toFormData({\n * user: { name: \"John\", age: 30 },\n * settings: { theme: \"dark\" }\n * });\n */\nexport const toFormData = (data: NonNullable<CallApiRequestOptions[\"body\"]>) => {\n\tconst formData = new FormData();\n\n\tfor (const [key, value] of Object.entries(data)) {\n\t\tif (isArray(value)) {\n\t\t\t// eslint-disable-next-line max-depth -- Allow for now\n\t\t\tfor (const innerValue of value) {\n\t\t\t\tformData.append(key, toBlobOrString(innerValue));\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (isObject(value) && !isBlob(value)) {\n\t\t\tformData.set(key, JSON.stringify(value));\n\t\t\tcontinue;\n\t\t}\n\n\t\tformData.set(key, toBlobOrString(value));\n\t}\n\n\treturn formData;\n};\n","import { extraOptionDefaults } from \"../../constants/defaults\";\nimport type { CallApiExtraOptions } from \"../../types/common\";\nimport type { StandardSchemaV1 } from \"../../types/standard-schema\";\nimport type { CallApiSchema, CallApiSchemaConfig } from \"../../validation\";\nimport { isObject, isString } from \"../guards\";\n\ntype HTTPErrorDetails<TErrorData> = Pick<CallApiExtraOptions, \"defaultHTTPErrorMessage\"> & {\n\terrorData: TErrorData;\n\tresponse: Response;\n};\n\nconst httpErrorSymbol = Symbol(\"HTTPError\");\n\nexport class HTTPError<TErrorData = Record<string, unknown>> extends Error {\n\terrorData: HTTPErrorDetails<TErrorData>[\"errorData\"];\n\n\treadonly httpErrorSymbol = httpErrorSymbol;\n\n\toverride name = \"HTTPError\" as const;\n\n\tresponse: HTTPErrorDetails<TErrorData>[\"response\"];\n\n\tconstructor(errorDetails: HTTPErrorDetails<TErrorData>, errorOptions?: ErrorOptions) {\n\t\tconst { defaultHTTPErrorMessage, errorData, response } = errorDetails;\n\n\t\tconst resolvedDefaultHTTPErrorMessage =\n\t\t\tisString(defaultHTTPErrorMessage) ? defaultHTTPErrorMessage : (\n\t\t\t\tdefaultHTTPErrorMessage?.({ errorData, response })\n\t\t\t);\n\n\t\tconst selectedDefaultErrorMessage =\n\t\t\tresolvedDefaultHTTPErrorMessage\n\t\t\t?? (response.statusText || extraOptionDefaults.defaultHTTPErrorMessage);\n\n\t\tconst message =\n\t\t\t(errorData as { message?: string } | undefined)?.message ?? selectedDefaultErrorMessage;\n\n\t\tsuper(message, errorOptions);\n\n\t\tthis.errorData = errorData;\n\t\tthis.response = response;\n\t}\n\n\t/**\n\t * @description Checks if the given error is an instance of HTTPError\n\t * @param error - The error to check\n\t * @returns true if the error is an instance of HTTPError, false otherwise\n\t */\n\tstatic override isError<TErrorData>(error: unknown): error is HTTPError<TErrorData> {\n\t\tif (!isObject<HTTPError>(error)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (error instanceof HTTPError) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst actualError = error as HTTPError;\n\n\t\treturn (\n\t\t\tactualError.httpErrorSymbol === httpErrorSymbol\n\t\t\t// eslint-disable-next-line ts-eslint/no-unnecessary-condition -- Allow\n\t\t\t&& actualError.name === \"HTTPError\"\n\t\t);\n\t}\n}\n\nconst prettifyPath = (path: ValidationError[\"errorData\"][number][\"path\"]) => {\n\tif (!path || path.length === 0) {\n\t\treturn \"\";\n\t}\n\n\tconst pathString = path.map((segment) => (isObject(segment) ? segment.key : segment)).join(\".\");\n\n\treturn ` → at ${pathString}`;\n};\n\nconst prettifyValidationIssues = (issues: ValidationError[\"errorData\"]) => {\n\tconst issuesString = issues.map((issue) => `✖ ${issue.message}${prettifyPath(issue.path)}`).join(\" | \");\n\n\treturn issuesString;\n};\n\ntype SafeExtract<TUnion, TKey extends TUnion> = Extract<TUnion, TKey>;\n\ntype ValidationErrorDetails = {\n\t/**\n\t * The cause of the validation error.\n\t *\n\t * It's either the name the schema for which validation failed, or the name of the schema config option that led to the validation error.\n\t */\n\tissueCause:\n\t\t| \"unknown\"\n\t\t| `schemaConfig-(${SafeExtract<keyof CallApiSchemaConfig, \"strict\">})`\n\t\t| keyof CallApiSchema;\n\n\t/**\n\t * The issues that caused the validation error.\n\t */\n\tissues: readonly StandardSchemaV1.Issue[];\n\n\t/**\n\t * The response from server, if any.\n\t */\n\tresponse: Response | null;\n};\n\nconst validationErrorSymbol = Symbol(\"ValidationErrorSymbol\");\n\nexport class ValidationError extends Error {\n\terrorData: ValidationErrorDetails[\"issues\"];\n\n\tissueCause: ValidationErrorDetails[\"issueCause\"];\n\n\toverride name = \"ValidationError\" as const;\n\n\tresponse: ValidationErrorDetails[\"response\"];\n\n\treadonly validationErrorSymbol = validationErrorSymbol;\n\n\tconstructor(details: ValidationErrorDetails, errorOptions?: ErrorOptions) {\n\t\tconst { issueCause, issues, response } = details;\n\n\t\tconst prettyMessage = prettifyValidationIssues(issues);\n\n\t\tconst message = `(${issueCause.toUpperCase()}) - ${prettyMessage}`;\n\n\t\tsuper(message, errorOptions);\n\n\t\tthis.errorData = issues;\n\t\tthis.response = response;\n\t\tthis.issueCause = issueCause;\n\t}\n\n\t/**\n\t * @description Checks if the given error is an instance of ValidationError\n\t * @param error - The error to check\n\t * @returns true if the error is an instance of ValidationError, false otherwise\n\t */\n\tstatic override isError(error: unknown): error is ValidationError {\n\t\tif (!isObject<ValidationError>(error)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (error instanceof ValidationError) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst actualError = error as ValidationError;\n\n\t\treturn (\n\t\t\tactualError.validationErrorSymbol === validationErrorSymbol\n\t\t\t// eslint-disable-next-line ts-eslint/no-unnecessary-condition -- Allow\n\t\t\t&& actualError.name === \"ValidationError\"\n\t\t);\n\t}\n}\n","import type { CallApiPlugin } from \"../../plugins\";\nimport type { BaseCallApiConfig } from \"../../types/common\";\nimport type { AnyFunction, Satisfies, Writeable } from \"../../types/type-helpers\";\nimport type {\n\tBaseCallApiSchemaAndConfig,\n\tBaseCallApiSchemaRoutes,\n\tCallApiSchema,\n\tCallApiSchemaConfig,\n} from \"../../validation\";\n\nexport const defineSchema = <\n\tconst TBaseSchemaRoutes extends BaseCallApiSchemaRoutes,\n\tconst TSchemaConfig extends CallApiSchemaConfig,\n>(\n\troutes: TBaseSchemaRoutes,\n\tconfig?: Satisfies<TSchemaConfig, CallApiSchemaConfig>\n) => {\n\treturn {\n\t\tconfig: defineSchemaConfig(config as NonNullable<typeof config>),\n\t\troutes: defineSchemaRoutes(routes),\n\t} satisfies BaseCallApiSchemaAndConfig;\n};\n\nexport const defineSchemaRoutes = <const TSchemaRoutes extends BaseCallApiSchemaRoutes>(\n\troutes: TSchemaRoutes\n) => {\n\treturn routes as Writeable<typeof routes, \"deep\">;\n};\n\nexport const defineMainSchema = <const TSchema extends CallApiSchema>(\n\tmainSchema: Satisfies<TSchema, CallApiSchema>\n) => {\n\treturn mainSchema as Writeable<typeof mainSchema, \"deep\">;\n};\n\nexport const defineSchemaConfig = <const TSchemaConfig extends CallApiSchemaConfig>(\n\tconfig: Satisfies<TSchemaConfig, CallApiSchemaConfig>\n) => {\n\treturn config as Writeable<typeof config, \"deep\">;\n};\n\nexport const definePlugin = <const TPlugin extends CallApiPlugin>(plugin: TPlugin) => {\n\treturn plugin as Writeable<typeof plugin, \"deep\">;\n};\n\ntype BaseConfigObject = Exclude<BaseCallApiConfig, AnyFunction>;\n\ntype BaseConfigFn = Extract<BaseCallApiConfig, AnyFunction>;\n\ntype DefineBaseConfig = {\n\t<const TBaseConfig extends BaseConfigObject>(\n\t\tbaseConfig: Satisfies<TBaseConfig, BaseConfigObject>\n\t): Writeable<typeof baseConfig, \"deep\">;\n\t<TBaseConfigFn extends BaseConfigFn>(baseConfig: TBaseConfigFn): TBaseConfigFn;\n};\n\nexport const defineBaseConfig: DefineBaseConfig = <const TBaseConfig extends BaseCallApiConfig>(\n\tbaseConfig: TBaseConfig\n) => {\n\treturn baseConfig;\n};\n","import type {\n\tCallApiResultErrorVariant,\n\tPossibleHTTPError,\n\tPossibleJavaScriptError,\n\tPossibleValidationError,\n} from \"../../result\";\nimport { isObject } from \"../guards\";\nimport { HTTPError, ValidationError } from \"./error\";\n\nexport const isHTTPError = <TErrorData>(\n\terror: CallApiResultErrorVariant<TErrorData>[\"error\"] | null\n): error is PossibleHTTPError<TErrorData> => {\n\treturn isObject(error) && error.name === \"HTTPError\";\n};\n\nexport const isHTTPErrorInstance = <TErrorData>(error: unknown) => {\n\treturn HTTPError.isError<TErrorData>(error);\n};\n\nexport const isValidationError = (\n\terror: CallApiResultErrorVariant<unknown>[\"error\"] | null\n): error is PossibleValidationError => {\n\treturn isObject(error) && error.name === \"ValidationError\";\n};\n\nexport const isValidationErrorInstance = (error: unknown): error is ValidationError => {\n\treturn ValidationError.isError(error);\n};\n\nexport const isJavascriptError = (\n\terror: CallApiResultErrorVariant<unknown>[\"error\"] | null\n): error is PossibleJavaScriptError => {\n\treturn isObject(error) && !isHTTPError(error) && !isValidationError(error);\n};\n"],"mappings":"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"}
|
|
@@ -183,7 +183,7 @@ interface CallApiSchemaConfig {
|
|
|
183
183
|
/**
|
|
184
184
|
* The base url of the schema. By default it's the baseURL of the callApi instance.
|
|
185
185
|
*/
|
|
186
|
-
baseURL?:
|
|
186
|
+
baseURL?: "" | AnyString;
|
|
187
187
|
/**
|
|
188
188
|
* Disables runtime validation for the schema.
|
|
189
189
|
*/
|
|
@@ -191,17 +191,18 @@ interface CallApiSchemaConfig {
|
|
|
191
191
|
/**
|
|
192
192
|
* If `true`, the original input value will be used instead of the transformed/validated output.
|
|
193
193
|
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
194
|
+
* When true, the original input is returned unchanged after validation, ignoring any schema-level
|
|
195
|
+
* transformations such as type coercion, default values, or field mapping. Only the validation
|
|
196
|
+
* step is executed; the resulting value is discarded in favor of the raw input.
|
|
196
197
|
*/
|
|
197
|
-
|
|
198
|
+
disableRuntimeValidationTransform?: boolean | BooleanObject;
|
|
198
199
|
/**
|
|
199
200
|
* Optional url prefix that will be substituted for the `baseURL` of the schemaConfig at runtime.
|
|
200
201
|
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
202
|
+
* Enables a short, stable prefix for routes while keeping the full `baseURL` centralized in config.
|
|
203
|
+
* Keeps route definitions concise and shields them from changes to the underlying base URL.
|
|
203
204
|
*/
|
|
204
|
-
prefix?:
|
|
205
|
+
prefix?: "" | AnyString;
|
|
205
206
|
/**
|
|
206
207
|
* Controls the strictness of API route validation.
|
|
207
208
|
*
|
|
@@ -385,7 +386,8 @@ interface URLOptions {
|
|
|
385
386
|
* @description Makes a type partial if the output type of TSchema is not provided or has undefined in the union, otherwise makes it required
|
|
386
387
|
*/
|
|
387
388
|
type MakeSchemaOptionRequiredIfDefined<TSchemaOption extends CallApiSchema[keyof CallApiSchema], TObject> = undefined extends InferSchemaOutput<TSchemaOption, undefined> ? TObject : Required<TObject>;
|
|
388
|
-
type
|
|
389
|
+
type MergePrefixWithRouteKey<TPrefix extends string, TRouteKey extends string> = TRouteKey extends `@${infer TMethod extends RouteKeyMethods}/${infer TRestOfRoutKey}` ? `@${TMethod}/${TPrefix extends `/${infer TPrefixWithoutSlash}` ? TPrefixWithoutSlash : TPrefix}${TRestOfRoutKey}` : `${TPrefix}${TRouteKey}`;
|
|
390
|
+
type ApplyURLBasedConfig<TSchemaConfig extends CallApiSchemaConfig, TSchemaRouteKeys extends string> = TSchemaConfig["prefix"] extends string ? MergePrefixWithRouteKey<TSchemaConfig["prefix"], TSchemaRouteKeys> : TSchemaConfig["baseURL"] extends string ? MergePrefixWithRouteKey<TSchemaConfig["baseURL"], TSchemaRouteKeys> : TSchemaRouteKeys;
|
|
389
391
|
type ApplyStrictConfig<TSchemaConfig extends CallApiSchemaConfig, TSchemaRouteKeys extends string> = TSchemaConfig["strict"] extends true ? TSchemaRouteKeys :
|
|
390
392
|
// eslint-disable-next-line perfectionist/sort-union-types -- Don't sort union types
|
|
391
393
|
TSchemaRouteKeys | Exclude<InitURLOrURLObject, RouteKeyMethodsURLUnion>;
|
|
@@ -459,19 +461,40 @@ type InferAuthOption<TSchema extends CallApiSchema> = MakeSchemaOptionRequiredIf
|
|
|
459
461
|
*
|
|
460
462
|
* @example
|
|
461
463
|
* ```ts
|
|
462
|
-
*
|
|
463
|
-
*
|
|
464
|
-
*
|
|
465
|
-
*
|
|
466
|
-
*
|
|
467
|
-
*
|
|
464
|
+
* // Bearer auth
|
|
465
|
+
* const response = await callMainApi({
|
|
466
|
+
* url: "https://example.com/api/data",
|
|
467
|
+
* auth: "123456",
|
|
468
|
+
* });
|
|
469
|
+
*
|
|
470
|
+
* // Bearer auth
|
|
471
|
+
* const response = await callMainApi({
|
|
472
|
+
* url: "https://example.com/api/data",
|
|
473
|
+
* auth: {
|
|
474
|
+
* type: "Bearer",
|
|
475
|
+
* value: "123456",
|
|
476
|
+
* },
|
|
477
|
+
})
|
|
478
|
+
*
|
|
479
|
+
* // Token auth
|
|
480
|
+
* const response = await callMainApi({
|
|
481
|
+
* url: "https://example.com/api/data",
|
|
482
|
+
* auth: {
|
|
483
|
+
* type: "Token",
|
|
484
|
+
* value: "123456",
|
|
468
485
|
* },
|
|
469
486
|
* });
|
|
470
487
|
*
|
|
488
|
+
* // Basic auth
|
|
471
489
|
* const response = await callMainApi({
|
|
472
490
|
* url: "https://example.com/api/data",
|
|
473
|
-
* auth:
|
|
491
|
+
* auth: {
|
|
492
|
+
* type: "Basic",
|
|
493
|
+
* username: "username",
|
|
494
|
+
* password: "password",
|
|
495
|
+
* },
|
|
474
496
|
* });
|
|
497
|
+
*
|
|
475
498
|
* ```
|
|
476
499
|
*/
|
|
477
500
|
auth?: InferSchemaOutput<TSchema["auth"], AuthOption>;
|
|
@@ -1855,4 +1878,4 @@ declare const callApi: <TData = unknown, TErrorData = unknown, TResultMode exten
|
|
|
1855
1878
|
}, TSchema, CallApiSchemaConfig, TSchemaConfig, TInitURL, TCurrentRouteSchemaKey, DefaultPluginArray, TPluginArray>) => Promise<TComputedResult>;
|
|
1856
1879
|
//#endregion
|
|
1857
1880
|
export { Writeable as $, ErrorContext as A, CallApiPlugin as B, InferExtendSchemaContext as C, ValidationError as D, HTTPError as E, ResponseContext as F, BaseCallApiSchemaRoutes as G, PluginSetupContext as H, ResponseErrorContext as I, CallApiSchemaConfig as J, BaseSchemaRouteKeyPrefixes as K, ResponseStreamContext as L, HooksOrHooksArray as M, RequestContext as N, RetryOptions as O, RequestStreamContext as P, Satisfies as Q, SuccessContext as R, GetExtendSchemaConfigContext as S, Register as T, InferParamsFromRoute as U, PluginHooks as V, URLOptions as W, InferSchemaOutput as X, InferSchemaInput as Y, AnyFunction as Z, CallApiExtraOptionsForHooks as _, CallApiResultSuccessOrErrorVariant as a, CallApiRequestOptionsForHooks as b, PossibleJavaScriptError as c, ResponseTypeType as d, ResultModeType as f, CallApiExtraOptions as g, CallApiConfig as h, CallApiResultErrorVariant as i, Hooks as j, DedupeOptions as k, PossibleJavaScriptOrValidationError as l, BaseCallApiExtraOptions as m, createFetchClient as n, CallApiResultSuccessVariant as o, BaseCallApiConfig as p, CallApiSchema as q, createFetchClientWithContext as r, PossibleHTTPError as s, callApi as t, PossibleValidationError as u, CallApiParameters as v, InstanceContext as w, CallApiResultLoose as x, CallApiRequestOptions as y, DefaultCallApiContext as z };
|
|
1858
|
-
//# sourceMappingURL=index-
|
|
1881
|
+
//# sourceMappingURL=index-BEp4V3_c.d.ts.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as ErrorContext, B as CallApiPlugin, C as InferExtendSchemaContext, F as ResponseContext, G as BaseCallApiSchemaRoutes, H as PluginSetupContext, I as ResponseErrorContext, J as CallApiSchemaConfig, K as BaseSchemaRouteKeyPrefixes, L as ResponseStreamContext, M as HooksOrHooksArray, N as RequestContext, O as RetryOptions, P as RequestStreamContext, R as SuccessContext, S as GetExtendSchemaConfigContext, T as Register, U as InferParamsFromRoute, V as PluginHooks, W as URLOptions, X as InferSchemaOutput, Y as InferSchemaInput, _ as CallApiExtraOptionsForHooks, a as CallApiResultSuccessOrErrorVariant, b as CallApiRequestOptionsForHooks, c as PossibleJavaScriptError, d as ResponseTypeType, f as ResultModeType, g as CallApiExtraOptions, h as CallApiConfig, i as CallApiResultErrorVariant, j as Hooks, k as DedupeOptions, l as PossibleJavaScriptOrValidationError, m as BaseCallApiExtraOptions, n as createFetchClient, o as CallApiResultSuccessVariant, p as BaseCallApiConfig, q as CallApiSchema, r as createFetchClientWithContext, s as PossibleHTTPError, t as callApi, u as PossibleValidationError, v as CallApiParameters, w as InstanceContext, x as CallApiResultLoose, y as CallApiRequestOptions, z as DefaultCallApiContext } from "./index-
|
|
1
|
+
import { A as ErrorContext, B as CallApiPlugin, C as InferExtendSchemaContext, F as ResponseContext, G as BaseCallApiSchemaRoutes, H as PluginSetupContext, I as ResponseErrorContext, J as CallApiSchemaConfig, K as BaseSchemaRouteKeyPrefixes, L as ResponseStreamContext, M as HooksOrHooksArray, N as RequestContext, O as RetryOptions, P as RequestStreamContext, R as SuccessContext, S as GetExtendSchemaConfigContext, T as Register, U as InferParamsFromRoute, V as PluginHooks, W as URLOptions, X as InferSchemaOutput, Y as InferSchemaInput, _ as CallApiExtraOptionsForHooks, a as CallApiResultSuccessOrErrorVariant, b as CallApiRequestOptionsForHooks, c as PossibleJavaScriptError, d as ResponseTypeType, f as ResultModeType, g as CallApiExtraOptions, h as CallApiConfig, i as CallApiResultErrorVariant, j as Hooks, k as DedupeOptions, l as PossibleJavaScriptOrValidationError, m as BaseCallApiExtraOptions, n as createFetchClient, o as CallApiResultSuccessVariant, p as BaseCallApiConfig, q as CallApiSchema, r as createFetchClientWithContext, s as PossibleHTTPError, t as callApi, u as PossibleValidationError, v as CallApiParameters, w as InstanceContext, x as CallApiResultLoose, y as CallApiRequestOptions, z as DefaultCallApiContext } from "./index-BEp4V3_c.js";
|
|
2
2
|
export { BaseCallApiConfig, BaseCallApiExtraOptions, BaseCallApiSchemaRoutes, BaseSchemaRouteKeyPrefixes, CallApiConfig, CallApiExtraOptions, CallApiExtraOptionsForHooks, CallApiParameters, CallApiPlugin, CallApiRequestOptions, CallApiRequestOptionsForHooks, CallApiResultLoose as CallApiResult, CallApiResultErrorVariant, CallApiResultSuccessOrErrorVariant, CallApiResultSuccessVariant, CallApiSchema, CallApiSchemaConfig, DedupeOptions, DefaultCallApiContext, ErrorContext, GetExtendSchemaConfigContext, Hooks, HooksOrHooksArray, InferExtendSchemaContext, InferParamsFromRoute, InferSchemaInput, InferSchemaOutput, InstanceContext, PluginHooks, PluginSetupContext, PossibleHTTPError, PossibleJavaScriptError, PossibleJavaScriptOrValidationError, PossibleValidationError, Register, RequestContext, RequestStreamContext, ResponseContext, ResponseErrorContext, ResponseStreamContext, ResponseTypeType, ResultModeType, RetryOptions, SuccessContext, URLOptions, callApi, createFetchClient, createFetchClientWithContext };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as requestOptionDefaults, r as defineEnum, t as extraOptionDefaults } from "./defaults-B-dOt2Dd.js";
|
|
2
|
-
import {
|
|
2
|
+
import { C as isReadableStream, E as isValidJsonString, S as isQueryString, T as isString, _ as isBoolean, a as isValidationErrorInstance, b as isPlainObject, f as HTTPError, g as isArray, h as toQueryString, n as isHTTPErrorInstance, p as ValidationError, v as isFunction, w as isSerializableObject, x as isPromise, y as isObject } from "./external-DXaCWLPN.js";
|
|
3
3
|
import { n as fetchSpecificKeys, t as fallBackRouteSchemaKey } from "./validation-DbbofkNi.js";
|
|
4
4
|
|
|
5
5
|
//#region src/auth.ts
|
|
@@ -78,8 +78,8 @@ const handleSchemaValidation = async (fullSchema, schemaName, validationOptions)
|
|
|
78
78
|
inputValue,
|
|
79
79
|
response
|
|
80
80
|
});
|
|
81
|
-
const disableResultApplicationBooleanObject = isObject(schemaConfig?.
|
|
82
|
-
if (schemaConfig?.
|
|
81
|
+
const disableResultApplicationBooleanObject = isObject(schemaConfig?.disableRuntimeValidationTransform) ? schemaConfig.disableRuntimeValidationTransform : {};
|
|
82
|
+
if (schemaConfig?.disableRuntimeValidationTransform === true || disableResultApplicationBooleanObject[schemaName] === true) return inputValue;
|
|
83
83
|
return validResult;
|
|
84
84
|
};
|
|
85
85
|
const extraOptionsToBeValidated = [
|
|
@@ -225,7 +225,7 @@ const ampersand = "&";
|
|
|
225
225
|
const mergeUrlWithQuery = (url, query) => {
|
|
226
226
|
if (!query) return url;
|
|
227
227
|
const queryString = toQueryString(query);
|
|
228
|
-
if (queryString
|
|
228
|
+
if (queryString.length === 0) return url;
|
|
229
229
|
if (url.endsWith(questionMark)) return `${url}${queryString}`;
|
|
230
230
|
if (url.includes(questionMark)) return `${url}${ampersand}${queryString}`;
|
|
231
231
|
return `${url}${questionMark}${queryString}`;
|
|
@@ -242,24 +242,8 @@ const mergeUrlWithQuery = (url, query) => {
|
|
|
242
242
|
*
|
|
243
243
|
* @example
|
|
244
244
|
* ```typescript
|
|
245
|
-
* // Method extraction from prefixed routes
|
|
246
245
|
* extractMethodFromURL("@get/users"); // Returns: "get"
|
|
247
246
|
* extractMethodFromURL("@post/users"); // Returns: "post"
|
|
248
|
-
* extractMethodFromURL("@put/users/:id"); // Returns: "put"
|
|
249
|
-
* extractMethodFromURL("@delete/users/:id"); // Returns: "delete"
|
|
250
|
-
* extractMethodFromURL("@patch/users/:id"); // Returns: "patch"
|
|
251
|
-
*
|
|
252
|
-
* // No method modifier
|
|
253
|
-
* extractMethodFromURL("/users"); // Returns: undefined
|
|
254
|
-
* extractMethodFromURL("users"); // Returns: undefined
|
|
255
|
-
*
|
|
256
|
-
* // Invalid or unsupported methods
|
|
257
|
-
* extractMethodFromURL("@invalid/users"); // Returns: undefined
|
|
258
|
-
* extractMethodFromURL("@/users"); // Returns: undefined
|
|
259
|
-
*
|
|
260
|
-
* // Edge cases
|
|
261
|
-
* extractMethodFromURL(undefined); // Returns: undefined
|
|
262
|
-
* extractMethodFromURL(""); // Returns: undefined
|
|
263
247
|
* ```
|
|
264
248
|
*/
|
|
265
249
|
const extractMethodFromURL = (initURL) => {
|
|
@@ -271,14 +255,19 @@ const extractMethodFromURL = (initURL) => {
|
|
|
271
255
|
const normalizeURL = (initURL) => {
|
|
272
256
|
const methodFromURL = extractMethodFromURL(initURL);
|
|
273
257
|
if (!methodFromURL) return initURL;
|
|
274
|
-
return initURL.replace(`@${methodFromURL}/`, "/");
|
|
258
|
+
return initURL.includes("http") ? initURL.replace(`@${methodFromURL}/`, "") : initURL.replace(`@${methodFromURL}/`, "/");
|
|
259
|
+
};
|
|
260
|
+
const getFullURL = (initURL, baseURL) => {
|
|
261
|
+
if (!baseURL || initURL.startsWith("http")) return initURL;
|
|
262
|
+
return initURL.length > 0 && !initURL.startsWith(slash) && !baseURL.endsWith(slash) ? `${baseURL}${slash}${initURL}` : `${baseURL}${initURL}`;
|
|
275
263
|
};
|
|
276
264
|
const getFullAndNormalizedURL = (options) => {
|
|
277
265
|
const { baseURL, initURL, params, query } = options;
|
|
278
266
|
const normalizedInitURL = normalizeURL(initURL);
|
|
279
|
-
const
|
|
267
|
+
const fullURL = getFullURL(mergeUrlWithQuery(mergeUrlWithParams(normalizedInitURL, params), query), baseURL);
|
|
268
|
+
if (!URL.canParse(fullURL)) console.error(`Invalid URL '${normalizedInitURL}'. Are you passing a relative url to CallApi but not setting the 'baseURL' option?`);
|
|
280
269
|
return {
|
|
281
|
-
fullURL
|
|
270
|
+
fullURL,
|
|
282
271
|
normalizedInitURL
|
|
283
272
|
};
|
|
284
273
|
};
|
|
@@ -336,29 +325,36 @@ const getResolvedHeaders = (options) => {
|
|
|
336
325
|
const { baseHeaders, headers } = options;
|
|
337
326
|
return objectifyHeaders(isFunction(headers) ? headers({ baseHeaders: objectifyHeaders(baseHeaders) }) : headers ?? baseHeaders);
|
|
338
327
|
};
|
|
328
|
+
const detectContentTypeHeader = (body) => {
|
|
329
|
+
if (isQueryString(body)) return { "Content-Type": "application/x-www-form-urlencoded" };
|
|
330
|
+
if (isSerializableObject(body) || isValidJsonString(body)) return {
|
|
331
|
+
Accept: "application/json",
|
|
332
|
+
"Content-Type": "application/json"
|
|
333
|
+
};
|
|
334
|
+
return null;
|
|
335
|
+
};
|
|
339
336
|
const getHeaders = async (options) => {
|
|
340
337
|
const { auth, body, resolvedHeaders } = options;
|
|
341
|
-
const
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
headersObject["Content-Type"] = "application/x-www-form-urlencoded";
|
|
347
|
-
return headersObject;
|
|
348
|
-
}
|
|
349
|
-
if (isSerializable(body) || isValidJsonString(body)) {
|
|
350
|
-
headersObject["Content-Type"] = "application/json";
|
|
351
|
-
headersObject.Accept = "application/json";
|
|
338
|
+
const authHeaderObject = await getAuthHeader(auth);
|
|
339
|
+
const resolvedHeadersObject = objectifyHeaders(resolvedHeaders);
|
|
340
|
+
if (!(Object.hasOwn(resolvedHeadersObject, "Content-Type") || Object.hasOwn(resolvedHeadersObject, "content-type"))) {
|
|
341
|
+
const contentTypeHeader = detectContentTypeHeader(body);
|
|
342
|
+
contentTypeHeader && Object.assign(resolvedHeadersObject, contentTypeHeader);
|
|
352
343
|
}
|
|
353
|
-
return
|
|
344
|
+
return {
|
|
345
|
+
...authHeaderObject,
|
|
346
|
+
...resolvedHeadersObject
|
|
347
|
+
};
|
|
354
348
|
};
|
|
355
349
|
const getMethod = (ctx) => {
|
|
356
350
|
const { initURL, method } = ctx;
|
|
357
351
|
return method?.toUpperCase() ?? extractMethodFromURL(initURL)?.toUpperCase() ?? requestOptionDefaults.method;
|
|
358
352
|
};
|
|
359
353
|
const getBody = (options) => {
|
|
360
|
-
const { body, bodySerializer } = options;
|
|
361
|
-
|
|
354
|
+
const { body, bodySerializer, resolvedHeaders } = options;
|
|
355
|
+
const existingContentType = new Headers(resolvedHeaders).get("content-type");
|
|
356
|
+
if (!existingContentType && isSerializableObject(body)) return (bodySerializer ?? extraOptionDefaults.bodySerializer)(body);
|
|
357
|
+
if (existingContentType === "application/x-www-form-urlencoded" && isSerializableObject(body)) return toQueryString(body);
|
|
362
358
|
return body;
|
|
363
359
|
};
|
|
364
360
|
const getInitFetchImpl = (customFetchImpl) => {
|
|
@@ -1065,7 +1061,8 @@ const createFetchClientWithContext = () => {
|
|
|
1065
1061
|
Object.assign(request, {
|
|
1066
1062
|
body: getBody({
|
|
1067
1063
|
body: requestOptionsValidationResult.body,
|
|
1068
|
-
bodySerializer: options.bodySerializer
|
|
1064
|
+
bodySerializer: options.bodySerializer,
|
|
1065
|
+
resolvedHeaders: requestOptionsValidationResult.headers
|
|
1069
1066
|
}),
|
|
1070
1067
|
headers: await getHeaders({
|
|
1071
1068
|
auth: options.auth,
|