enlace 0.0.0-alpha.1 → 0.0.0-alpha.3
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/dist/chunk-PNORT7RX.mjs +101 -0
- package/dist/index.d.mts +19 -2
- package/dist/index.d.ts +19 -2
- package/dist/index.js +112 -2
- package/dist/index.mjs +12 -3
- package/dist/next/index.d.mts +16 -0
- package/dist/next/index.d.ts +16 -0
- package/dist/next/index.js +186 -0
- package/dist/next/index.mjs +66 -0
- package/dist/types-BX5MGIgP.d.mts +104 -0
- package/dist/types-BX5MGIgP.d.ts +104 -0
- package/package.json +10 -1
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// src/utils/buildUrl.ts
|
|
2
|
+
import qs from "query-string";
|
|
3
|
+
function buildUrl(baseUrl, path, query) {
|
|
4
|
+
const url = new URL(path.join("/"), baseUrl);
|
|
5
|
+
if (query) {
|
|
6
|
+
url.search = qs.stringify(query, { skipNull: true, skipEmptyString: true });
|
|
7
|
+
}
|
|
8
|
+
return url.toString();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// src/utils/isJsonBody.ts
|
|
12
|
+
function isJsonBody(body) {
|
|
13
|
+
if (body === null || body === void 0) return false;
|
|
14
|
+
if (body instanceof FormData) return false;
|
|
15
|
+
if (body instanceof Blob) return false;
|
|
16
|
+
if (body instanceof ArrayBuffer) return false;
|
|
17
|
+
if (body instanceof URLSearchParams) return false;
|
|
18
|
+
if (body instanceof ReadableStream) return false;
|
|
19
|
+
if (typeof body === "string") return false;
|
|
20
|
+
return typeof body === "object";
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// src/utils/mergeHeaders.ts
|
|
24
|
+
function mergeHeaders(defaultHeaders, requestHeaders) {
|
|
25
|
+
if (!defaultHeaders && !requestHeaders) return void 0;
|
|
26
|
+
if (!defaultHeaders) return requestHeaders;
|
|
27
|
+
if (!requestHeaders) return defaultHeaders;
|
|
28
|
+
return {
|
|
29
|
+
...Object.fromEntries(new Headers(defaultHeaders)),
|
|
30
|
+
...Object.fromEntries(new Headers(requestHeaders))
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// src/core/fetch.ts
|
|
35
|
+
async function executeFetch(baseUrl, path, method, defaultOptions, requestOptions) {
|
|
36
|
+
const url = buildUrl(baseUrl, path, requestOptions?.query);
|
|
37
|
+
let headers = mergeHeaders(defaultOptions.headers, requestOptions?.headers);
|
|
38
|
+
const fetchOptions = {
|
|
39
|
+
...defaultOptions,
|
|
40
|
+
method
|
|
41
|
+
};
|
|
42
|
+
if (headers) {
|
|
43
|
+
fetchOptions.headers = headers;
|
|
44
|
+
}
|
|
45
|
+
if (requestOptions?.body !== void 0) {
|
|
46
|
+
if (isJsonBody(requestOptions.body)) {
|
|
47
|
+
fetchOptions.body = JSON.stringify(requestOptions.body);
|
|
48
|
+
headers = mergeHeaders(headers, { "Content-Type": "application/json" });
|
|
49
|
+
if (headers) {
|
|
50
|
+
fetchOptions.headers = headers;
|
|
51
|
+
}
|
|
52
|
+
} else {
|
|
53
|
+
fetchOptions.body = requestOptions.body;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const response = await fetch(url, fetchOptions);
|
|
57
|
+
const contentType = response.headers.get("content-type");
|
|
58
|
+
const isJson = contentType?.includes("application/json");
|
|
59
|
+
if (response.ok) {
|
|
60
|
+
return {
|
|
61
|
+
ok: true,
|
|
62
|
+
status: response.status,
|
|
63
|
+
data: isJson ? await response.json() : response
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
ok: false,
|
|
68
|
+
status: response.status,
|
|
69
|
+
error: isJson ? await response.json() : response
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// src/core/proxy.ts
|
|
74
|
+
var HTTP_METHODS = {
|
|
75
|
+
get: "GET",
|
|
76
|
+
post: "POST",
|
|
77
|
+
put: "PUT",
|
|
78
|
+
patch: "PATCH",
|
|
79
|
+
delete: "DELETE"
|
|
80
|
+
};
|
|
81
|
+
function createProxyHandler(baseUrl, defaultOptions, path = [], fetchExecutor = executeFetch) {
|
|
82
|
+
const handler = {
|
|
83
|
+
get(_target, prop) {
|
|
84
|
+
if (typeof prop === "symbol") return void 0;
|
|
85
|
+
const method = HTTP_METHODS[prop];
|
|
86
|
+
if (method) {
|
|
87
|
+
return (options) => fetchExecutor(baseUrl, path, method, defaultOptions, options);
|
|
88
|
+
}
|
|
89
|
+
return createProxyHandler(baseUrl, defaultOptions, [...path, prop], fetchExecutor);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
return new Proxy({}, handler);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export {
|
|
96
|
+
buildUrl,
|
|
97
|
+
isJsonBody,
|
|
98
|
+
mergeHeaders,
|
|
99
|
+
executeFetch,
|
|
100
|
+
createProxyHandler
|
|
101
|
+
};
|
package/dist/index.d.mts
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
-
|
|
1
|
+
import { E as EnlaceOptions, F as FetchExecutor, R as RequestOptions, H as HttpMethod, a as EnlaceResponse, W as WildcardClient, b as EnlaceClient } from './types-BX5MGIgP.mjs';
|
|
2
|
+
export { c as Endpoint, M as MethodDefinition, S as SchemaMethod } from './types-BX5MGIgP.mjs';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
declare function createProxyHandler<TSchema extends object, TOptions = EnlaceOptions>(baseUrl: string, defaultOptions: TOptions, path?: string[], fetchExecutor?: FetchExecutor<TOptions, RequestOptions<unknown>>): TSchema;
|
|
5
|
+
|
|
6
|
+
declare function executeFetch<TData, TError>(baseUrl: string, path: string[], method: HttpMethod, defaultOptions: EnlaceOptions, requestOptions?: RequestOptions<unknown>): Promise<EnlaceResponse<TData, TError>>;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Creates an API client.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* // Typed mode - with schema
|
|
13
|
+
* const api = createEnlace<MyApi>('https://api.example.com');
|
|
14
|
+
*
|
|
15
|
+
* // Untyped mode - no schema
|
|
16
|
+
* const api = createEnlace('https://api.example.com');
|
|
17
|
+
*/
|
|
18
|
+
declare function createEnlace<TSchema = unknown>(baseUrl: string, defaultOptions?: EnlaceOptions): unknown extends TSchema ? WildcardClient : EnlaceClient<TSchema>;
|
|
19
|
+
|
|
20
|
+
export { EnlaceClient, EnlaceOptions, EnlaceResponse, FetchExecutor, HttpMethod, RequestOptions, WildcardClient, createEnlace, createProxyHandler, executeFetch };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
-
|
|
1
|
+
import { E as EnlaceOptions, F as FetchExecutor, R as RequestOptions, H as HttpMethod, a as EnlaceResponse, W as WildcardClient, b as EnlaceClient } from './types-BX5MGIgP.js';
|
|
2
|
+
export { c as Endpoint, M as MethodDefinition, S as SchemaMethod } from './types-BX5MGIgP.js';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
declare function createProxyHandler<TSchema extends object, TOptions = EnlaceOptions>(baseUrl: string, defaultOptions: TOptions, path?: string[], fetchExecutor?: FetchExecutor<TOptions, RequestOptions<unknown>>): TSchema;
|
|
5
|
+
|
|
6
|
+
declare function executeFetch<TData, TError>(baseUrl: string, path: string[], method: HttpMethod, defaultOptions: EnlaceOptions, requestOptions?: RequestOptions<unknown>): Promise<EnlaceResponse<TData, TError>>;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Creates an API client.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* // Typed mode - with schema
|
|
13
|
+
* const api = createEnlace<MyApi>('https://api.example.com');
|
|
14
|
+
*
|
|
15
|
+
* // Untyped mode - no schema
|
|
16
|
+
* const api = createEnlace('https://api.example.com');
|
|
17
|
+
*/
|
|
18
|
+
declare function createEnlace<TSchema = unknown>(baseUrl: string, defaultOptions?: EnlaceOptions): unknown extends TSchema ? WildcardClient : EnlaceClient<TSchema>;
|
|
19
|
+
|
|
20
|
+
export { EnlaceClient, EnlaceOptions, EnlaceResponse, FetchExecutor, HttpMethod, RequestOptions, WildcardClient, createEnlace, createProxyHandler, executeFetch };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,12 +17,120 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
21
31
|
var index_exports = {};
|
|
22
32
|
__export(index_exports, {
|
|
23
|
-
|
|
33
|
+
createEnlace: () => createEnlace,
|
|
34
|
+
createProxyHandler: () => createProxyHandler,
|
|
35
|
+
executeFetch: () => executeFetch
|
|
24
36
|
});
|
|
25
37
|
module.exports = __toCommonJS(index_exports);
|
|
26
|
-
|
|
38
|
+
|
|
39
|
+
// src/utils/buildUrl.ts
|
|
40
|
+
var import_query_string = __toESM(require("query-string"));
|
|
41
|
+
function buildUrl(baseUrl, path, query) {
|
|
42
|
+
const url = new URL(path.join("/"), baseUrl);
|
|
43
|
+
if (query) {
|
|
44
|
+
url.search = import_query_string.default.stringify(query, { skipNull: true, skipEmptyString: true });
|
|
45
|
+
}
|
|
46
|
+
return url.toString();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// src/utils/isJsonBody.ts
|
|
50
|
+
function isJsonBody(body) {
|
|
51
|
+
if (body === null || body === void 0) return false;
|
|
52
|
+
if (body instanceof FormData) return false;
|
|
53
|
+
if (body instanceof Blob) return false;
|
|
54
|
+
if (body instanceof ArrayBuffer) return false;
|
|
55
|
+
if (body instanceof URLSearchParams) return false;
|
|
56
|
+
if (body instanceof ReadableStream) return false;
|
|
57
|
+
if (typeof body === "string") return false;
|
|
58
|
+
return typeof body === "object";
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// src/utils/mergeHeaders.ts
|
|
62
|
+
function mergeHeaders(defaultHeaders, requestHeaders) {
|
|
63
|
+
if (!defaultHeaders && !requestHeaders) return void 0;
|
|
64
|
+
if (!defaultHeaders) return requestHeaders;
|
|
65
|
+
if (!requestHeaders) return defaultHeaders;
|
|
66
|
+
return {
|
|
67
|
+
...Object.fromEntries(new Headers(defaultHeaders)),
|
|
68
|
+
...Object.fromEntries(new Headers(requestHeaders))
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// src/core/fetch.ts
|
|
73
|
+
async function executeFetch(baseUrl, path, method, defaultOptions, requestOptions) {
|
|
74
|
+
const url = buildUrl(baseUrl, path, requestOptions?.query);
|
|
75
|
+
let headers = mergeHeaders(defaultOptions.headers, requestOptions?.headers);
|
|
76
|
+
const fetchOptions = {
|
|
77
|
+
...defaultOptions,
|
|
78
|
+
method
|
|
79
|
+
};
|
|
80
|
+
if (headers) {
|
|
81
|
+
fetchOptions.headers = headers;
|
|
82
|
+
}
|
|
83
|
+
if (requestOptions?.body !== void 0) {
|
|
84
|
+
if (isJsonBody(requestOptions.body)) {
|
|
85
|
+
fetchOptions.body = JSON.stringify(requestOptions.body);
|
|
86
|
+
headers = mergeHeaders(headers, { "Content-Type": "application/json" });
|
|
87
|
+
if (headers) {
|
|
88
|
+
fetchOptions.headers = headers;
|
|
89
|
+
}
|
|
90
|
+
} else {
|
|
91
|
+
fetchOptions.body = requestOptions.body;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const response = await fetch(url, fetchOptions);
|
|
95
|
+
const contentType = response.headers.get("content-type");
|
|
96
|
+
const isJson = contentType?.includes("application/json");
|
|
97
|
+
if (response.ok) {
|
|
98
|
+
return {
|
|
99
|
+
ok: true,
|
|
100
|
+
status: response.status,
|
|
101
|
+
data: isJson ? await response.json() : response
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
ok: false,
|
|
106
|
+
status: response.status,
|
|
107
|
+
error: isJson ? await response.json() : response
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// src/core/proxy.ts
|
|
112
|
+
var HTTP_METHODS = {
|
|
113
|
+
get: "GET",
|
|
114
|
+
post: "POST",
|
|
115
|
+
put: "PUT",
|
|
116
|
+
patch: "PATCH",
|
|
117
|
+
delete: "DELETE"
|
|
118
|
+
};
|
|
119
|
+
function createProxyHandler(baseUrl, defaultOptions, path = [], fetchExecutor = executeFetch) {
|
|
120
|
+
const handler = {
|
|
121
|
+
get(_target, prop) {
|
|
122
|
+
if (typeof prop === "symbol") return void 0;
|
|
123
|
+
const method = HTTP_METHODS[prop];
|
|
124
|
+
if (method) {
|
|
125
|
+
return (options) => fetchExecutor(baseUrl, path, method, defaultOptions, options);
|
|
126
|
+
}
|
|
127
|
+
return createProxyHandler(baseUrl, defaultOptions, [...path, prop], fetchExecutor);
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
return new Proxy({}, handler);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// src/core/index.ts
|
|
134
|
+
function createEnlace(baseUrl, defaultOptions = {}) {
|
|
135
|
+
return createProxyHandler(baseUrl, defaultOptions);
|
|
136
|
+
}
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
createProxyHandler,
|
|
3
|
+
executeFetch
|
|
4
|
+
} from "./chunk-PNORT7RX.mjs";
|
|
5
|
+
|
|
6
|
+
// src/core/index.ts
|
|
7
|
+
function createEnlace(baseUrl, defaultOptions = {}) {
|
|
8
|
+
return createProxyHandler(baseUrl, defaultOptions);
|
|
9
|
+
}
|
|
3
10
|
export {
|
|
4
|
-
|
|
11
|
+
createEnlace,
|
|
12
|
+
createProxyHandler,
|
|
13
|
+
executeFetch
|
|
5
14
|
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { E as EnlaceOptions, W as WildcardClient, b as EnlaceClient } from '../types-BX5MGIgP.mjs';
|
|
2
|
+
export { c as Endpoint, a as EnlaceResponse, F as FetchExecutor, H as HttpMethod, M as MethodDefinition, R as RequestOptions, S as SchemaMethod } from '../types-BX5MGIgP.mjs';
|
|
3
|
+
|
|
4
|
+
type NextFetchOptions = {
|
|
5
|
+
revalidate?: number | false;
|
|
6
|
+
tags?: string[];
|
|
7
|
+
};
|
|
8
|
+
type NextEnlaceOptions = EnlaceOptions;
|
|
9
|
+
type NextRequestOptionsBase = {
|
|
10
|
+
cache?: 'force-cache' | 'no-store';
|
|
11
|
+
next?: NextFetchOptions;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
declare function createEnlace<TSchema = unknown>(baseUrl: string, defaultOptions?: NextEnlaceOptions): unknown extends TSchema ? WildcardClient<NextRequestOptionsBase> : EnlaceClient<TSchema, NextRequestOptionsBase>;
|
|
15
|
+
|
|
16
|
+
export { EnlaceClient, EnlaceOptions, type NextEnlaceOptions, type NextFetchOptions, type NextRequestOptionsBase, WildcardClient, createEnlace };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { E as EnlaceOptions, W as WildcardClient, b as EnlaceClient } from '../types-BX5MGIgP.js';
|
|
2
|
+
export { c as Endpoint, a as EnlaceResponse, F as FetchExecutor, H as HttpMethod, M as MethodDefinition, R as RequestOptions, S as SchemaMethod } from '../types-BX5MGIgP.js';
|
|
3
|
+
|
|
4
|
+
type NextFetchOptions = {
|
|
5
|
+
revalidate?: number | false;
|
|
6
|
+
tags?: string[];
|
|
7
|
+
};
|
|
8
|
+
type NextEnlaceOptions = EnlaceOptions;
|
|
9
|
+
type NextRequestOptionsBase = {
|
|
10
|
+
cache?: 'force-cache' | 'no-store';
|
|
11
|
+
next?: NextFetchOptions;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
declare function createEnlace<TSchema = unknown>(baseUrl: string, defaultOptions?: NextEnlaceOptions): unknown extends TSchema ? WildcardClient<NextRequestOptionsBase> : EnlaceClient<TSchema, NextRequestOptionsBase>;
|
|
15
|
+
|
|
16
|
+
export { EnlaceClient, EnlaceOptions, type NextEnlaceOptions, type NextFetchOptions, type NextRequestOptionsBase, WildcardClient, createEnlace };
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/next/index.ts
|
|
31
|
+
var next_exports = {};
|
|
32
|
+
__export(next_exports, {
|
|
33
|
+
createEnlace: () => createEnlace
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(next_exports);
|
|
36
|
+
|
|
37
|
+
// src/utils/buildUrl.ts
|
|
38
|
+
var import_query_string = __toESM(require("query-string"));
|
|
39
|
+
function buildUrl(baseUrl, path, query) {
|
|
40
|
+
const url = new URL(path.join("/"), baseUrl);
|
|
41
|
+
if (query) {
|
|
42
|
+
url.search = import_query_string.default.stringify(query, { skipNull: true, skipEmptyString: true });
|
|
43
|
+
}
|
|
44
|
+
return url.toString();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// src/utils/isJsonBody.ts
|
|
48
|
+
function isJsonBody(body) {
|
|
49
|
+
if (body === null || body === void 0) return false;
|
|
50
|
+
if (body instanceof FormData) return false;
|
|
51
|
+
if (body instanceof Blob) return false;
|
|
52
|
+
if (body instanceof ArrayBuffer) return false;
|
|
53
|
+
if (body instanceof URLSearchParams) return false;
|
|
54
|
+
if (body instanceof ReadableStream) return false;
|
|
55
|
+
if (typeof body === "string") return false;
|
|
56
|
+
return typeof body === "object";
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// src/utils/mergeHeaders.ts
|
|
60
|
+
function mergeHeaders(defaultHeaders, requestHeaders) {
|
|
61
|
+
if (!defaultHeaders && !requestHeaders) return void 0;
|
|
62
|
+
if (!defaultHeaders) return requestHeaders;
|
|
63
|
+
if (!requestHeaders) return defaultHeaders;
|
|
64
|
+
return {
|
|
65
|
+
...Object.fromEntries(new Headers(defaultHeaders)),
|
|
66
|
+
...Object.fromEntries(new Headers(requestHeaders))
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// src/core/fetch.ts
|
|
71
|
+
async function executeFetch(baseUrl, path, method, defaultOptions, requestOptions) {
|
|
72
|
+
const url = buildUrl(baseUrl, path, requestOptions?.query);
|
|
73
|
+
let headers = mergeHeaders(defaultOptions.headers, requestOptions?.headers);
|
|
74
|
+
const fetchOptions = {
|
|
75
|
+
...defaultOptions,
|
|
76
|
+
method
|
|
77
|
+
};
|
|
78
|
+
if (headers) {
|
|
79
|
+
fetchOptions.headers = headers;
|
|
80
|
+
}
|
|
81
|
+
if (requestOptions?.body !== void 0) {
|
|
82
|
+
if (isJsonBody(requestOptions.body)) {
|
|
83
|
+
fetchOptions.body = JSON.stringify(requestOptions.body);
|
|
84
|
+
headers = mergeHeaders(headers, { "Content-Type": "application/json" });
|
|
85
|
+
if (headers) {
|
|
86
|
+
fetchOptions.headers = headers;
|
|
87
|
+
}
|
|
88
|
+
} else {
|
|
89
|
+
fetchOptions.body = requestOptions.body;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
const response = await fetch(url, fetchOptions);
|
|
93
|
+
const contentType = response.headers.get("content-type");
|
|
94
|
+
const isJson = contentType?.includes("application/json");
|
|
95
|
+
if (response.ok) {
|
|
96
|
+
return {
|
|
97
|
+
ok: true,
|
|
98
|
+
status: response.status,
|
|
99
|
+
data: isJson ? await response.json() : response
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
ok: false,
|
|
104
|
+
status: response.status,
|
|
105
|
+
error: isJson ? await response.json() : response
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// src/core/proxy.ts
|
|
110
|
+
var HTTP_METHODS = {
|
|
111
|
+
get: "GET",
|
|
112
|
+
post: "POST",
|
|
113
|
+
put: "PUT",
|
|
114
|
+
patch: "PATCH",
|
|
115
|
+
delete: "DELETE"
|
|
116
|
+
};
|
|
117
|
+
function createProxyHandler(baseUrl, defaultOptions, path = [], fetchExecutor = executeFetch) {
|
|
118
|
+
const handler = {
|
|
119
|
+
get(_target, prop) {
|
|
120
|
+
if (typeof prop === "symbol") return void 0;
|
|
121
|
+
const method = HTTP_METHODS[prop];
|
|
122
|
+
if (method) {
|
|
123
|
+
return (options) => fetchExecutor(baseUrl, path, method, defaultOptions, options);
|
|
124
|
+
}
|
|
125
|
+
return createProxyHandler(baseUrl, defaultOptions, [...path, prop], fetchExecutor);
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
return new Proxy({}, handler);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// src/next/fetch.ts
|
|
132
|
+
function generateTags(path) {
|
|
133
|
+
return path.map((_, i) => path.slice(0, i + 1).join("/"));
|
|
134
|
+
}
|
|
135
|
+
async function executeNextFetch(baseUrl, path, method, defaultOptions, requestOptions) {
|
|
136
|
+
const url = buildUrl(baseUrl, path, requestOptions?.query);
|
|
137
|
+
let headers = mergeHeaders(defaultOptions.headers, requestOptions?.headers);
|
|
138
|
+
const nextOptions = requestOptions?.next;
|
|
139
|
+
const tags = nextOptions?.tags ?? generateTags(path);
|
|
140
|
+
const fetchOptions = {
|
|
141
|
+
...defaultOptions,
|
|
142
|
+
method
|
|
143
|
+
};
|
|
144
|
+
if (requestOptions?.cache) {
|
|
145
|
+
fetchOptions.cache = requestOptions.cache;
|
|
146
|
+
}
|
|
147
|
+
const nextFetchOptions = { tags };
|
|
148
|
+
if (nextOptions?.revalidate !== void 0) {
|
|
149
|
+
nextFetchOptions.revalidate = nextOptions.revalidate;
|
|
150
|
+
}
|
|
151
|
+
fetchOptions.next = nextFetchOptions;
|
|
152
|
+
if (headers) {
|
|
153
|
+
fetchOptions.headers = headers;
|
|
154
|
+
}
|
|
155
|
+
if (requestOptions?.body !== void 0) {
|
|
156
|
+
if (isJsonBody(requestOptions.body)) {
|
|
157
|
+
fetchOptions.body = JSON.stringify(requestOptions.body);
|
|
158
|
+
headers = mergeHeaders(headers, { "Content-Type": "application/json" });
|
|
159
|
+
if (headers) {
|
|
160
|
+
fetchOptions.headers = headers;
|
|
161
|
+
}
|
|
162
|
+
} else {
|
|
163
|
+
fetchOptions.body = requestOptions.body;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
const response = await fetch(url, fetchOptions);
|
|
167
|
+
const contentType = response.headers.get("content-type");
|
|
168
|
+
const isJson = contentType?.includes("application/json");
|
|
169
|
+
if (response.ok) {
|
|
170
|
+
return {
|
|
171
|
+
ok: true,
|
|
172
|
+
status: response.status,
|
|
173
|
+
data: isJson ? await response.json() : response
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
ok: false,
|
|
178
|
+
status: response.status,
|
|
179
|
+
error: isJson ? await response.json() : response
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// src/next/index.ts
|
|
184
|
+
function createEnlace(baseUrl, defaultOptions = {}) {
|
|
185
|
+
return createProxyHandler(baseUrl, defaultOptions, [], executeNextFetch);
|
|
186
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildUrl,
|
|
3
|
+
createProxyHandler,
|
|
4
|
+
isJsonBody,
|
|
5
|
+
mergeHeaders
|
|
6
|
+
} from "../chunk-PNORT7RX.mjs";
|
|
7
|
+
|
|
8
|
+
// src/next/fetch.ts
|
|
9
|
+
function generateTags(path) {
|
|
10
|
+
return path.map((_, i) => path.slice(0, i + 1).join("/"));
|
|
11
|
+
}
|
|
12
|
+
async function executeNextFetch(baseUrl, path, method, defaultOptions, requestOptions) {
|
|
13
|
+
const url = buildUrl(baseUrl, path, requestOptions?.query);
|
|
14
|
+
let headers = mergeHeaders(defaultOptions.headers, requestOptions?.headers);
|
|
15
|
+
const nextOptions = requestOptions?.next;
|
|
16
|
+
const tags = nextOptions?.tags ?? generateTags(path);
|
|
17
|
+
const fetchOptions = {
|
|
18
|
+
...defaultOptions,
|
|
19
|
+
method
|
|
20
|
+
};
|
|
21
|
+
if (requestOptions?.cache) {
|
|
22
|
+
fetchOptions.cache = requestOptions.cache;
|
|
23
|
+
}
|
|
24
|
+
const nextFetchOptions = { tags };
|
|
25
|
+
if (nextOptions?.revalidate !== void 0) {
|
|
26
|
+
nextFetchOptions.revalidate = nextOptions.revalidate;
|
|
27
|
+
}
|
|
28
|
+
fetchOptions.next = nextFetchOptions;
|
|
29
|
+
if (headers) {
|
|
30
|
+
fetchOptions.headers = headers;
|
|
31
|
+
}
|
|
32
|
+
if (requestOptions?.body !== void 0) {
|
|
33
|
+
if (isJsonBody(requestOptions.body)) {
|
|
34
|
+
fetchOptions.body = JSON.stringify(requestOptions.body);
|
|
35
|
+
headers = mergeHeaders(headers, { "Content-Type": "application/json" });
|
|
36
|
+
if (headers) {
|
|
37
|
+
fetchOptions.headers = headers;
|
|
38
|
+
}
|
|
39
|
+
} else {
|
|
40
|
+
fetchOptions.body = requestOptions.body;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const response = await fetch(url, fetchOptions);
|
|
44
|
+
const contentType = response.headers.get("content-type");
|
|
45
|
+
const isJson = contentType?.includes("application/json");
|
|
46
|
+
if (response.ok) {
|
|
47
|
+
return {
|
|
48
|
+
ok: true,
|
|
49
|
+
status: response.status,
|
|
50
|
+
data: isJson ? await response.json() : response
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
ok: false,
|
|
55
|
+
status: response.status,
|
|
56
|
+
error: isJson ? await response.json() : response
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// src/next/index.ts
|
|
61
|
+
function createEnlace(baseUrl, defaultOptions = {}) {
|
|
62
|
+
return createProxyHandler(baseUrl, defaultOptions, [], executeNextFetch);
|
|
63
|
+
}
|
|
64
|
+
export {
|
|
65
|
+
createEnlace
|
|
66
|
+
};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
2
|
+
type SchemaMethod = '$get' | '$post' | '$put' | '$patch' | '$delete';
|
|
3
|
+
type EnlaceResponse<TData, TError> = {
|
|
4
|
+
ok: true;
|
|
5
|
+
status: number;
|
|
6
|
+
data: TData;
|
|
7
|
+
error?: never;
|
|
8
|
+
} | {
|
|
9
|
+
ok: false;
|
|
10
|
+
status: number;
|
|
11
|
+
data?: never;
|
|
12
|
+
error: TError;
|
|
13
|
+
};
|
|
14
|
+
type EnlaceOptions = Omit<RequestInit, 'method' | 'body'>;
|
|
15
|
+
type FetchExecutor<TOptions = EnlaceOptions, TRequestOptions = RequestOptions<unknown>> = <TData, TError>(baseUrl: string, path: string[], method: HttpMethod, defaultOptions: TOptions, requestOptions?: TRequestOptions) => Promise<EnlaceResponse<TData, TError>>;
|
|
16
|
+
type RequestOptions<TBody = never> = {
|
|
17
|
+
body?: TBody;
|
|
18
|
+
query?: Record<string, string | number | boolean | undefined>;
|
|
19
|
+
headers?: HeadersInit;
|
|
20
|
+
};
|
|
21
|
+
type MethodDefinition = {
|
|
22
|
+
data: unknown;
|
|
23
|
+
error: unknown;
|
|
24
|
+
body?: unknown;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Helper to define an endpoint with proper typing.
|
|
28
|
+
* Provides cleaner syntax than writing { data, error, body } manually.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* type MyApi = {
|
|
32
|
+
* posts: {
|
|
33
|
+
* $get: Endpoint<Post[], ApiError>;
|
|
34
|
+
* $post: Endpoint<Post, ApiError, CreatePost>; // with body
|
|
35
|
+
* _: {
|
|
36
|
+
* $get: Endpoint<Post, NotFoundError>;
|
|
37
|
+
* };
|
|
38
|
+
* };
|
|
39
|
+
* };
|
|
40
|
+
*/
|
|
41
|
+
type Endpoint<TData, TError, TBody = never> = [TBody] extends [never] ? {
|
|
42
|
+
data: TData;
|
|
43
|
+
error: TError;
|
|
44
|
+
} : {
|
|
45
|
+
data: TData;
|
|
46
|
+
error: TError;
|
|
47
|
+
body: TBody;
|
|
48
|
+
};
|
|
49
|
+
type ExtractMethodDef<TSchema, TMethod extends SchemaMethod> = TSchema extends {
|
|
50
|
+
[K in TMethod]: infer M;
|
|
51
|
+
} ? M extends MethodDefinition ? M : never : never;
|
|
52
|
+
type ExtractData<TSchema, TMethod extends SchemaMethod> = ExtractMethodDef<TSchema, TMethod> extends {
|
|
53
|
+
data: infer D;
|
|
54
|
+
} ? D : never;
|
|
55
|
+
type ExtractError<TSchema, TMethod extends SchemaMethod> = ExtractMethodDef<TSchema, TMethod> extends {
|
|
56
|
+
error: infer E;
|
|
57
|
+
} ? E : never;
|
|
58
|
+
type ExtractBody<TSchema, TMethod extends SchemaMethod> = ExtractMethodDef<TSchema, TMethod> extends {
|
|
59
|
+
body: infer B;
|
|
60
|
+
} ? B : never;
|
|
61
|
+
type HasMethod<TSchema, TMethod extends SchemaMethod> = TSchema extends {
|
|
62
|
+
[K in TMethod]: MethodDefinition;
|
|
63
|
+
} ? true : false;
|
|
64
|
+
type MethodFn<TSchema, TMethod extends SchemaMethod, TRequestOptionsBase = object> = HasMethod<TSchema, TMethod> extends true ? ExtractBody<TSchema, TMethod> extends never ? (options?: RequestOptions<never> & TRequestOptionsBase) => Promise<EnlaceResponse<ExtractData<TSchema, TMethod>, ExtractError<TSchema, TMethod>>> : (options: RequestOptions<ExtractBody<TSchema, TMethod>> & TRequestOptionsBase) => Promise<EnlaceResponse<ExtractData<TSchema, TMethod>, ExtractError<TSchema, TMethod>>> : never;
|
|
65
|
+
type IsSpecialKey<K> = K extends SchemaMethod | '_' ? true : false;
|
|
66
|
+
type StaticPathKeys<TSchema> = {
|
|
67
|
+
[K in keyof TSchema as IsSpecialKey<K> extends true ? never : K extends string ? K : never]: TSchema[K];
|
|
68
|
+
};
|
|
69
|
+
type ExtractDynamicSchema<TSchema> = TSchema extends {
|
|
70
|
+
_: infer D;
|
|
71
|
+
} ? D : never;
|
|
72
|
+
type MethodOrPath<TSchema, TMethodName extends string, TSchemaMethod extends SchemaMethod, TRequestOptionsBase = object> = TMethodName extends keyof TSchema ? EnlaceClient<TSchema[TMethodName], TRequestOptionsBase> : MethodFn<TSchema, TSchemaMethod, TRequestOptionsBase>;
|
|
73
|
+
type HttpMethods<TSchema, TRequestOptionsBase = object> = {
|
|
74
|
+
get: MethodOrPath<TSchema, 'get', '$get', TRequestOptionsBase>;
|
|
75
|
+
post: MethodOrPath<TSchema, 'post', '$post', TRequestOptionsBase>;
|
|
76
|
+
put: MethodOrPath<TSchema, 'put', '$put', TRequestOptionsBase>;
|
|
77
|
+
patch: MethodOrPath<TSchema, 'patch', '$patch', TRequestOptionsBase>;
|
|
78
|
+
delete: MethodOrPath<TSchema, 'delete', '$delete', TRequestOptionsBase>;
|
|
79
|
+
};
|
|
80
|
+
type DynamicAccess<TSchema, TRequestOptionsBase = object> = ExtractDynamicSchema<TSchema> extends never ? object : {
|
|
81
|
+
[key: string]: EnlaceClient<ExtractDynamicSchema<TSchema>, TRequestOptionsBase>;
|
|
82
|
+
[key: number]: EnlaceClient<ExtractDynamicSchema<TSchema>, TRequestOptionsBase>;
|
|
83
|
+
};
|
|
84
|
+
type MethodNameKeys = 'get' | 'post' | 'put' | 'patch' | 'delete';
|
|
85
|
+
type EnlaceClient<TSchema, TRequestOptionsBase = object> = HttpMethods<TSchema, TRequestOptionsBase> & DynamicAccess<TSchema, TRequestOptionsBase> & {
|
|
86
|
+
[K in keyof StaticPathKeys<TSchema> as K extends MethodNameKeys ? never : K]: EnlaceClient<TSchema[K], TRequestOptionsBase>;
|
|
87
|
+
};
|
|
88
|
+
type WildcardMethodFn<TRequestOptionsBase = object> = (options?: RequestOptions<unknown> & TRequestOptionsBase) => Promise<EnlaceResponse<unknown, unknown>>;
|
|
89
|
+
/**
|
|
90
|
+
* Wildcard client type - allows any path access when no schema is provided.
|
|
91
|
+
* All methods are available at every level and return unknown types.
|
|
92
|
+
*/
|
|
93
|
+
type WildcardClient<TRequestOptionsBase = object> = {
|
|
94
|
+
get: WildcardMethodFn<TRequestOptionsBase>;
|
|
95
|
+
post: WildcardMethodFn<TRequestOptionsBase>;
|
|
96
|
+
put: WildcardMethodFn<TRequestOptionsBase>;
|
|
97
|
+
patch: WildcardMethodFn<TRequestOptionsBase>;
|
|
98
|
+
delete: WildcardMethodFn<TRequestOptionsBase>;
|
|
99
|
+
} & {
|
|
100
|
+
[key: string]: WildcardClient<TRequestOptionsBase>;
|
|
101
|
+
[key: number]: WildcardClient<TRequestOptionsBase>;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export type { EnlaceOptions as E, FetchExecutor as F, HttpMethod as H, MethodDefinition as M, RequestOptions as R, SchemaMethod as S, WildcardClient as W, EnlaceResponse as a, EnlaceClient as b, Endpoint as c };
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
2
|
+
type SchemaMethod = '$get' | '$post' | '$put' | '$patch' | '$delete';
|
|
3
|
+
type EnlaceResponse<TData, TError> = {
|
|
4
|
+
ok: true;
|
|
5
|
+
status: number;
|
|
6
|
+
data: TData;
|
|
7
|
+
error?: never;
|
|
8
|
+
} | {
|
|
9
|
+
ok: false;
|
|
10
|
+
status: number;
|
|
11
|
+
data?: never;
|
|
12
|
+
error: TError;
|
|
13
|
+
};
|
|
14
|
+
type EnlaceOptions = Omit<RequestInit, 'method' | 'body'>;
|
|
15
|
+
type FetchExecutor<TOptions = EnlaceOptions, TRequestOptions = RequestOptions<unknown>> = <TData, TError>(baseUrl: string, path: string[], method: HttpMethod, defaultOptions: TOptions, requestOptions?: TRequestOptions) => Promise<EnlaceResponse<TData, TError>>;
|
|
16
|
+
type RequestOptions<TBody = never> = {
|
|
17
|
+
body?: TBody;
|
|
18
|
+
query?: Record<string, string | number | boolean | undefined>;
|
|
19
|
+
headers?: HeadersInit;
|
|
20
|
+
};
|
|
21
|
+
type MethodDefinition = {
|
|
22
|
+
data: unknown;
|
|
23
|
+
error: unknown;
|
|
24
|
+
body?: unknown;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Helper to define an endpoint with proper typing.
|
|
28
|
+
* Provides cleaner syntax than writing { data, error, body } manually.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* type MyApi = {
|
|
32
|
+
* posts: {
|
|
33
|
+
* $get: Endpoint<Post[], ApiError>;
|
|
34
|
+
* $post: Endpoint<Post, ApiError, CreatePost>; // with body
|
|
35
|
+
* _: {
|
|
36
|
+
* $get: Endpoint<Post, NotFoundError>;
|
|
37
|
+
* };
|
|
38
|
+
* };
|
|
39
|
+
* };
|
|
40
|
+
*/
|
|
41
|
+
type Endpoint<TData, TError, TBody = never> = [TBody] extends [never] ? {
|
|
42
|
+
data: TData;
|
|
43
|
+
error: TError;
|
|
44
|
+
} : {
|
|
45
|
+
data: TData;
|
|
46
|
+
error: TError;
|
|
47
|
+
body: TBody;
|
|
48
|
+
};
|
|
49
|
+
type ExtractMethodDef<TSchema, TMethod extends SchemaMethod> = TSchema extends {
|
|
50
|
+
[K in TMethod]: infer M;
|
|
51
|
+
} ? M extends MethodDefinition ? M : never : never;
|
|
52
|
+
type ExtractData<TSchema, TMethod extends SchemaMethod> = ExtractMethodDef<TSchema, TMethod> extends {
|
|
53
|
+
data: infer D;
|
|
54
|
+
} ? D : never;
|
|
55
|
+
type ExtractError<TSchema, TMethod extends SchemaMethod> = ExtractMethodDef<TSchema, TMethod> extends {
|
|
56
|
+
error: infer E;
|
|
57
|
+
} ? E : never;
|
|
58
|
+
type ExtractBody<TSchema, TMethod extends SchemaMethod> = ExtractMethodDef<TSchema, TMethod> extends {
|
|
59
|
+
body: infer B;
|
|
60
|
+
} ? B : never;
|
|
61
|
+
type HasMethod<TSchema, TMethod extends SchemaMethod> = TSchema extends {
|
|
62
|
+
[K in TMethod]: MethodDefinition;
|
|
63
|
+
} ? true : false;
|
|
64
|
+
type MethodFn<TSchema, TMethod extends SchemaMethod, TRequestOptionsBase = object> = HasMethod<TSchema, TMethod> extends true ? ExtractBody<TSchema, TMethod> extends never ? (options?: RequestOptions<never> & TRequestOptionsBase) => Promise<EnlaceResponse<ExtractData<TSchema, TMethod>, ExtractError<TSchema, TMethod>>> : (options: RequestOptions<ExtractBody<TSchema, TMethod>> & TRequestOptionsBase) => Promise<EnlaceResponse<ExtractData<TSchema, TMethod>, ExtractError<TSchema, TMethod>>> : never;
|
|
65
|
+
type IsSpecialKey<K> = K extends SchemaMethod | '_' ? true : false;
|
|
66
|
+
type StaticPathKeys<TSchema> = {
|
|
67
|
+
[K in keyof TSchema as IsSpecialKey<K> extends true ? never : K extends string ? K : never]: TSchema[K];
|
|
68
|
+
};
|
|
69
|
+
type ExtractDynamicSchema<TSchema> = TSchema extends {
|
|
70
|
+
_: infer D;
|
|
71
|
+
} ? D : never;
|
|
72
|
+
type MethodOrPath<TSchema, TMethodName extends string, TSchemaMethod extends SchemaMethod, TRequestOptionsBase = object> = TMethodName extends keyof TSchema ? EnlaceClient<TSchema[TMethodName], TRequestOptionsBase> : MethodFn<TSchema, TSchemaMethod, TRequestOptionsBase>;
|
|
73
|
+
type HttpMethods<TSchema, TRequestOptionsBase = object> = {
|
|
74
|
+
get: MethodOrPath<TSchema, 'get', '$get', TRequestOptionsBase>;
|
|
75
|
+
post: MethodOrPath<TSchema, 'post', '$post', TRequestOptionsBase>;
|
|
76
|
+
put: MethodOrPath<TSchema, 'put', '$put', TRequestOptionsBase>;
|
|
77
|
+
patch: MethodOrPath<TSchema, 'patch', '$patch', TRequestOptionsBase>;
|
|
78
|
+
delete: MethodOrPath<TSchema, 'delete', '$delete', TRequestOptionsBase>;
|
|
79
|
+
};
|
|
80
|
+
type DynamicAccess<TSchema, TRequestOptionsBase = object> = ExtractDynamicSchema<TSchema> extends never ? object : {
|
|
81
|
+
[key: string]: EnlaceClient<ExtractDynamicSchema<TSchema>, TRequestOptionsBase>;
|
|
82
|
+
[key: number]: EnlaceClient<ExtractDynamicSchema<TSchema>, TRequestOptionsBase>;
|
|
83
|
+
};
|
|
84
|
+
type MethodNameKeys = 'get' | 'post' | 'put' | 'patch' | 'delete';
|
|
85
|
+
type EnlaceClient<TSchema, TRequestOptionsBase = object> = HttpMethods<TSchema, TRequestOptionsBase> & DynamicAccess<TSchema, TRequestOptionsBase> & {
|
|
86
|
+
[K in keyof StaticPathKeys<TSchema> as K extends MethodNameKeys ? never : K]: EnlaceClient<TSchema[K], TRequestOptionsBase>;
|
|
87
|
+
};
|
|
88
|
+
type WildcardMethodFn<TRequestOptionsBase = object> = (options?: RequestOptions<unknown> & TRequestOptionsBase) => Promise<EnlaceResponse<unknown, unknown>>;
|
|
89
|
+
/**
|
|
90
|
+
* Wildcard client type - allows any path access when no schema is provided.
|
|
91
|
+
* All methods are available at every level and return unknown types.
|
|
92
|
+
*/
|
|
93
|
+
type WildcardClient<TRequestOptionsBase = object> = {
|
|
94
|
+
get: WildcardMethodFn<TRequestOptionsBase>;
|
|
95
|
+
post: WildcardMethodFn<TRequestOptionsBase>;
|
|
96
|
+
put: WildcardMethodFn<TRequestOptionsBase>;
|
|
97
|
+
patch: WildcardMethodFn<TRequestOptionsBase>;
|
|
98
|
+
delete: WildcardMethodFn<TRequestOptionsBase>;
|
|
99
|
+
} & {
|
|
100
|
+
[key: string]: WildcardClient<TRequestOptionsBase>;
|
|
101
|
+
[key: number]: WildcardClient<TRequestOptionsBase>;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export type { EnlaceOptions as E, FetchExecutor as F, HttpMethod as H, MethodDefinition as M, RequestOptions as R, SchemaMethod as S, WildcardClient as W, EnlaceResponse as a, EnlaceClient as b, Endpoint as c };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "enlace",
|
|
3
|
-
"version": "0.0.0-alpha.
|
|
3
|
+
"version": "0.0.0-alpha.3",
|
|
4
4
|
"files": [
|
|
5
5
|
"dist"
|
|
6
6
|
],
|
|
@@ -9,6 +9,11 @@
|
|
|
9
9
|
"types": "./dist/index.d.ts",
|
|
10
10
|
"import": "./dist/index.mjs",
|
|
11
11
|
"require": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./next": {
|
|
14
|
+
"types": "./dist/next/index.d.ts",
|
|
15
|
+
"import": "./dist/next/index.mjs",
|
|
16
|
+
"require": "./dist/next/index.js"
|
|
12
17
|
}
|
|
13
18
|
},
|
|
14
19
|
"license": "MIT",
|
|
@@ -27,9 +32,13 @@
|
|
|
27
32
|
"eslint": "^9.39.1",
|
|
28
33
|
"eslint-plugin-react": "^7.37.5",
|
|
29
34
|
"globals": "^16.5.0",
|
|
35
|
+
"jiti": "^2.6.1",
|
|
30
36
|
"tsup": "^8.5.1",
|
|
31
37
|
"tsx": "^4.21.0",
|
|
32
38
|
"typescript": "5.9.2",
|
|
33
39
|
"typescript-eslint": "^8.48.1"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"query-string": "^9.3.1"
|
|
34
43
|
}
|
|
35
44
|
}
|