@liteforge/client 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/client.d.ts +11 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +94 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +21 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +17 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/query.d.ts +28 -0
- package/dist/integrations/query.d.ts.map +1 -0
- package/dist/integrations/query.js +52 -0
- package/dist/integrations/query.js.map +1 -0
- package/dist/interceptors.d.ts +17 -0
- package/dist/interceptors.d.ts.map +1 -0
- package/dist/interceptors.js +55 -0
- package/dist/interceptors.js.map +1 -0
- package/dist/middleware.d.ts +15 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +28 -0
- package/dist/middleware.js.map +1 -0
- package/dist/request.d.ts +10 -0
- package/dist/request.d.ts.map +1 -0
- package/dist/request.js +123 -0
- package/dist/request.js.map +1 -0
- package/dist/resource.d.ts +9 -0
- package/dist/resource.d.ts.map +1 -0
- package/dist/resource.js +66 -0
- package/dist/resource.js.map +1 -0
- package/dist/types.d.ts +98 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/headers.d.ts +9 -0
- package/dist/utils/headers.d.ts.map +1 -0
- package/dist/utils/headers.js +19 -0
- package/dist/utils/headers.js.map +1 -0
- package/dist/utils/retry.d.ts +9 -0
- package/dist/utils/retry.d.ts.map +1 -0
- package/dist/utils/retry.js +38 -0
- package/dist/utils/retry.js.map +1 -0
- package/dist/utils/url.d.ts +14 -0
- package/dist/utils/url.d.ts.map +1 -0
- package/dist/utils/url.js +32 -0
- package/dist/utils/url.js.map +1 -0
- package/package.json +65 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 SchildW3rk
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* createClient — main entry point for @liteforge/client
|
|
3
|
+
*/
|
|
4
|
+
import type { Client, CreateClientOptions } from './types.js';
|
|
5
|
+
import type { QueryIntegration } from './integrations/query.js';
|
|
6
|
+
interface InternalCreateClientOptions extends CreateClientOptions {
|
|
7
|
+
query?: QueryIntegration;
|
|
8
|
+
}
|
|
9
|
+
export declare function createClient(opts: InternalCreateClientOptions): Client;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,MAAM,EACN,mBAAmB,EAOpB,MAAM,YAAY,CAAC;AAQpB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,UAAU,2BAA4B,SAAQ,mBAAmB;IAC/D,KAAK,CAAC,EAAE,gBAAgB,CAAC;CAC1B;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,2BAA2B,GAAG,MAAM,CAiHtE"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* createClient — main entry point for @liteforge/client
|
|
3
|
+
*/
|
|
4
|
+
import { executeFetch } from './request.js';
|
|
5
|
+
import { createInterceptorRegistry } from './interceptors.js';
|
|
6
|
+
import { createMiddlewarePipeline } from './middleware.js';
|
|
7
|
+
import { createResource } from './resource.js';
|
|
8
|
+
import { buildUrl } from './utils/url.js';
|
|
9
|
+
import { mergeHeaders } from './utils/headers.js';
|
|
10
|
+
import { retryRequest } from './utils/retry.js';
|
|
11
|
+
export function createClient(opts) {
|
|
12
|
+
const defaultHeaders = opts.headers ?? {};
|
|
13
|
+
const defaultTimeout = opts.timeout ?? 30000;
|
|
14
|
+
const defaultRetry = opts.retry ?? 0;
|
|
15
|
+
const defaultRetryDelay = opts.retryDelay ?? 300;
|
|
16
|
+
const interceptorRegistry = createInterceptorRegistry();
|
|
17
|
+
const middlewareList = [...(opts.middleware ?? [])];
|
|
18
|
+
// Seed initial interceptors
|
|
19
|
+
for (const h of opts.interceptors ?? []) {
|
|
20
|
+
interceptorRegistry.add(h);
|
|
21
|
+
}
|
|
22
|
+
// Core handler (always uses current middlewareList snapshot)
|
|
23
|
+
const coreHandler = (config) => executeFetch(config);
|
|
24
|
+
async function executeRequest(config) {
|
|
25
|
+
// 1. Merge client-level headers
|
|
26
|
+
const merged = {
|
|
27
|
+
...config,
|
|
28
|
+
headers: mergeHeaders(defaultHeaders, config.headers),
|
|
29
|
+
timeout: config.timeout ?? defaultTimeout,
|
|
30
|
+
retry: config.retry ?? defaultRetry,
|
|
31
|
+
};
|
|
32
|
+
// 2. Run request interceptors
|
|
33
|
+
let intercepted;
|
|
34
|
+
try {
|
|
35
|
+
intercepted = await interceptorRegistry.runRequest(merged);
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
return interceptorRegistry.runRequestError(err);
|
|
39
|
+
}
|
|
40
|
+
// 3. Build middleware pipeline fresh (captures current middlewareList)
|
|
41
|
+
const pipeline = createMiddlewarePipeline(middlewareList, coreHandler);
|
|
42
|
+
// 4. Execute with retry
|
|
43
|
+
const retryCount = intercepted.retry ?? 0;
|
|
44
|
+
const retryDelay = defaultRetryDelay;
|
|
45
|
+
let context;
|
|
46
|
+
try {
|
|
47
|
+
context = await retryRequest(() => pipeline(intercepted), retryCount, retryDelay);
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
// Import at runtime to avoid circular-dep issues in type-checking
|
|
51
|
+
const { ApiError } = await import('./errors.js');
|
|
52
|
+
if (err instanceof ApiError) {
|
|
53
|
+
return interceptorRegistry.runResponseError(err);
|
|
54
|
+
}
|
|
55
|
+
throw err;
|
|
56
|
+
}
|
|
57
|
+
// 5. Run response interceptors
|
|
58
|
+
const finalCtx = await interceptorRegistry.runResponse(context);
|
|
59
|
+
return finalCtx.data;
|
|
60
|
+
}
|
|
61
|
+
function get(path, config) {
|
|
62
|
+
return executeRequest({ ...config, method: 'GET', url: buildUrl(opts.baseUrl, path) });
|
|
63
|
+
}
|
|
64
|
+
function post(path, body, config) {
|
|
65
|
+
return executeRequest({ ...config, method: 'POST', url: buildUrl(opts.baseUrl, path), body });
|
|
66
|
+
}
|
|
67
|
+
function put(path, body, config) {
|
|
68
|
+
return executeRequest({ ...config, method: 'PUT', url: buildUrl(opts.baseUrl, path), body });
|
|
69
|
+
}
|
|
70
|
+
function patch(path, body, config) {
|
|
71
|
+
return executeRequest({ ...config, method: 'PATCH', url: buildUrl(opts.baseUrl, path), body });
|
|
72
|
+
}
|
|
73
|
+
function del(path, config) {
|
|
74
|
+
return executeRequest({ ...config, method: 'DELETE', url: buildUrl(opts.baseUrl, path) });
|
|
75
|
+
}
|
|
76
|
+
function resource(name, options = {}) {
|
|
77
|
+
const resourceBasePath = buildUrl(opts.baseUrl, options.path ?? name);
|
|
78
|
+
const resourceOpts = { ...options, path: resourceBasePath };
|
|
79
|
+
return createResource(name, resourceOpts, executeRequest, opts.query);
|
|
80
|
+
}
|
|
81
|
+
function addInterceptor(handlers) {
|
|
82
|
+
return interceptorRegistry.add(handlers);
|
|
83
|
+
}
|
|
84
|
+
function use(middleware) {
|
|
85
|
+
middlewareList.push(middleware);
|
|
86
|
+
return () => {
|
|
87
|
+
const idx = middlewareList.indexOf(middleware);
|
|
88
|
+
if (idx !== -1)
|
|
89
|
+
middlewareList.splice(idx, 1);
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
return { resource, get, post, put, patch, delete: del, addInterceptor, use };
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @liteforge/client — ApiError
|
|
3
|
+
*
|
|
4
|
+
* Thrown whenever a fetch response has a non-2xx status code.
|
|
5
|
+
*/
|
|
6
|
+
import type { RequestConfig, ResponseContext } from './types.js';
|
|
7
|
+
export declare class ApiError extends Error {
|
|
8
|
+
readonly status: number;
|
|
9
|
+
readonly statusText: string;
|
|
10
|
+
readonly data: unknown;
|
|
11
|
+
readonly config: RequestConfig;
|
|
12
|
+
readonly retry: () => Promise<ResponseContext>;
|
|
13
|
+
constructor(opts: {
|
|
14
|
+
status: number;
|
|
15
|
+
statusText: string;
|
|
16
|
+
data: unknown;
|
|
17
|
+
config: RequestConfig;
|
|
18
|
+
retry: () => Promise<ResponseContext>;
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEjE,qBAAa,QAAS,SAAQ,KAAK;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,eAAe,CAAC,CAAC;gBAEnC,IAAI,EAAE;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;QACnB,IAAI,EAAE,OAAO,CAAC;QACd,MAAM,EAAE,aAAa,CAAC;QACtB,KAAK,EAAE,MAAM,OAAO,CAAC,eAAe,CAAC,CAAC;KACvC;CASF"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @liteforge/client — ApiError
|
|
3
|
+
*
|
|
4
|
+
* Thrown whenever a fetch response has a non-2xx status code.
|
|
5
|
+
*/
|
|
6
|
+
export class ApiError extends Error {
|
|
7
|
+
constructor(opts) {
|
|
8
|
+
super(`Request failed with status ${opts.status} ${opts.statusText}`);
|
|
9
|
+
this.name = 'ApiError';
|
|
10
|
+
this.status = opts.status;
|
|
11
|
+
this.statusText = opts.statusText;
|
|
12
|
+
this.data = opts.data;
|
|
13
|
+
this.config = opts.config;
|
|
14
|
+
this.retry = opts.retry;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,MAAM,OAAO,QAAS,SAAQ,KAAK;IAOjC,YAAY,IAMX;QACC,KAAK,CAAC,8BAA8B,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;QACtE,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;QAClC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IAC1B,CAAC;CACF"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @liteforge/client
|
|
3
|
+
*
|
|
4
|
+
* TypeScript-first HTTP client with resource-based CRUD,
|
|
5
|
+
* interceptors, middleware, and optional @liteforge/query integration.
|
|
6
|
+
*/
|
|
7
|
+
export { createClient } from './client.js';
|
|
8
|
+
export { ApiError } from './errors.js';
|
|
9
|
+
export type { Client, ClientConfig, CreateClientOptions, Resource, ResourceOptions, RequestConfig, ResponseContext, InterceptorHandlers, Middleware, ListParams, ListResponse, ListMeta, HttpMethod, } from './types.js';
|
|
10
|
+
export type { QueryIntegration } from './integrations/query.js';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,YAAY,EACV,MAAM,EACN,YAAY,EACZ,mBAAmB,EACnB,QAAQ,EACR,eAAe,EACf,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,UAAU,EACV,UAAU,EACV,YAAY,EACZ,QAAQ,EACR,UAAU,GACX,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @liteforge/client
|
|
3
|
+
*
|
|
4
|
+
* TypeScript-first HTTP client with resource-based CRUD,
|
|
5
|
+
* interceptors, middleware, and optional @liteforge/query integration.
|
|
6
|
+
*/
|
|
7
|
+
export { createClient } from './client.js';
|
|
8
|
+
export { ApiError } from './errors.js';
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional @liteforge/query integration for @liteforge/client
|
|
3
|
+
*
|
|
4
|
+
* Provides `useList`, `useOne`, `useCreate`, `useUpdate`, `useDelete`
|
|
5
|
+
* methods on Resource instances when a QueryIntegration is supplied.
|
|
6
|
+
*/
|
|
7
|
+
import type { QueryResult, MutationResult, CreateQueryOptions, CreateMutationOptions } from '@liteforge/query';
|
|
8
|
+
import type { RequestConfig, ListParams, ListResponse } from '../types.js';
|
|
9
|
+
export interface QueryIntegration {
|
|
10
|
+
createQuery: <T>(options: CreateQueryOptions<T>) => QueryResult<T>;
|
|
11
|
+
createMutation: <TData, TVariables>(options: CreateMutationOptions<TData, TVariables>) => MutationResult<TData, TVariables>;
|
|
12
|
+
}
|
|
13
|
+
export interface QueryMethods<T, TCreate, TUpdate> {
|
|
14
|
+
useList: (params?: ListParams) => QueryResult<ListResponse<T>>;
|
|
15
|
+
useOne: (id: string | number) => QueryResult<T>;
|
|
16
|
+
useCreate: () => MutationResult<T, TCreate>;
|
|
17
|
+
useUpdate: () => MutationResult<T, {
|
|
18
|
+
id: string | number;
|
|
19
|
+
data: TUpdate;
|
|
20
|
+
}>;
|
|
21
|
+
useDelete: () => MutationResult<void, string | number>;
|
|
22
|
+
}
|
|
23
|
+
export declare function buildQueryMethods<T, TCreate, TUpdate>(
|
|
24
|
+
/** Short resource name used as query cache key (e.g. 'users') */
|
|
25
|
+
resourceKey: string,
|
|
26
|
+
/** Full base URL used for fetch requests (e.g. 'https://api.example.com/users') */
|
|
27
|
+
fetchUrl: string, request: <R>(config: RequestConfig) => Promise<R>, integration: QueryIntegration): QueryMethods<T, TCreate, TUpdate>;
|
|
28
|
+
//# sourceMappingURL=query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/integrations/query.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EACd,kBAAkB,EAClB,qBAAqB,EACtB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3E,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,kBAAkB,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC;IACnE,cAAc,EAAE,CAAC,KAAK,EAAE,UAAU,EAChC,OAAO,EAAE,qBAAqB,CAAC,KAAK,EAAE,UAAU,CAAC,KAC9C,cAAc,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;CACxC;AAED,MAAM,WAAW,YAAY,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO;IAC/C,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,UAAU,KAAK,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/D,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC;IAChD,SAAS,EAAE,MAAM,cAAc,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAC5C,SAAS,EAAE,MAAM,cAAc,CAAC,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC3E,SAAS,EAAE,MAAM,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;CACxD;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO;AACnD,iEAAiE;AACjE,WAAW,EAAE,MAAM;AACnB,mFAAmF;AACnF,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC,CAAC,CAAC,EACjD,WAAW,EAAE,gBAAgB,GAC5B,YAAY,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CA8CnC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional @liteforge/query integration for @liteforge/client
|
|
3
|
+
*
|
|
4
|
+
* Provides `useList`, `useOne`, `useCreate`, `useUpdate`, `useDelete`
|
|
5
|
+
* methods on Resource instances when a QueryIntegration is supplied.
|
|
6
|
+
*/
|
|
7
|
+
import { buildUrl } from '../utils/url.js';
|
|
8
|
+
export function buildQueryMethods(
|
|
9
|
+
/** Short resource name used as query cache key (e.g. 'users') */
|
|
10
|
+
resourceKey,
|
|
11
|
+
/** Full base URL used for fetch requests (e.g. 'https://api.example.com/users') */
|
|
12
|
+
fetchUrl, request, integration) {
|
|
13
|
+
function useList(params) {
|
|
14
|
+
const serialized = JSON.stringify(params ?? {});
|
|
15
|
+
return integration.createQuery({
|
|
16
|
+
key: () => [resourceKey, 'list', serialized],
|
|
17
|
+
fn: () => {
|
|
18
|
+
const cfg = { method: 'GET', url: fetchUrl };
|
|
19
|
+
if (params !== undefined) {
|
|
20
|
+
cfg.params = params;
|
|
21
|
+
}
|
|
22
|
+
return request(cfg);
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
function useOne(id) {
|
|
27
|
+
return integration.createQuery({
|
|
28
|
+
key: () => [resourceKey, 'one', String(id)],
|
|
29
|
+
fn: () => request({ method: 'GET', url: buildUrl(fetchUrl, String(id)) }),
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
function useCreate() {
|
|
33
|
+
return integration.createMutation({
|
|
34
|
+
fn: (data) => request({ method: 'POST', url: fetchUrl, body: data }),
|
|
35
|
+
invalidate: [fetchUrl],
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
function useUpdate() {
|
|
39
|
+
return integration.createMutation({
|
|
40
|
+
fn: (vars) => request({ method: 'PUT', url: buildUrl(fetchUrl, String(vars.id)), body: vars.data }),
|
|
41
|
+
invalidate: [fetchUrl],
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function useDelete() {
|
|
45
|
+
return integration.createMutation({
|
|
46
|
+
fn: (id) => request({ method: 'DELETE', url: buildUrl(fetchUrl, String(id)) }),
|
|
47
|
+
invalidate: [fetchUrl],
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return { useList, useOne, useCreate, useUpdate, useDelete };
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/integrations/query.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAiB3C,MAAM,UAAU,iBAAiB;AAC/B,iEAAiE;AACjE,WAAmB;AACnB,mFAAmF;AACnF,QAAgB,EAChB,OAAiD,EACjD,WAA6B;IAE7B,SAAS,OAAO,CAAC,MAAmB;QAClC,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;QAChD,OAAO,WAAW,CAAC,WAAW,CAAkB;YAC9C,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,CAAC;YAC5C,EAAE,EAAE,GAAG,EAAE;gBACP,MAAM,GAAG,GAAkB,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC;gBAC5D,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;oBACzB,GAAG,CAAC,MAAM,GAAG,MAAmD,CAAC;gBACnE,CAAC;gBACD,OAAO,OAAO,CAAkB,GAAG,CAAC,CAAC;YACvC,CAAC;SACF,CAAC,CAAC;IACL,CAAC;IAED,SAAS,MAAM,CAAC,EAAmB;QACjC,OAAO,WAAW,CAAC,WAAW,CAAI;YAChC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,WAAW,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;YAC3C,EAAE,EAAE,GAAG,EAAE,CAAC,OAAO,CAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;SAC7E,CAAC,CAAC;IACL,CAAC;IAED,SAAS,SAAS;QAChB,OAAO,WAAW,CAAC,cAAc,CAAa;YAC5C,EAAE,EAAE,CAAC,IAAa,EAAE,EAAE,CAAC,OAAO,CAAI,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;YAChF,UAAU,EAAE,CAAC,QAAQ,CAAC;SACvB,CAAC,CAAC;IACL,CAAC;IAED,SAAS,SAAS;QAChB,OAAO,WAAW,CAAC,cAAc,CAA4C;YAC3E,EAAE,EAAE,CAAC,IAA4C,EAAE,EAAE,CACnD,OAAO,CAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;YAC1F,UAAU,EAAE,CAAC,QAAQ,CAAC;SACvB,CAAC,CAAC;IACL,CAAC;IAED,SAAS,SAAS;QAChB,OAAO,WAAW,CAAC,cAAc,CAAwB;YACvD,EAAE,EAAE,CAAC,EAAmB,EAAE,EAAE,CAC1B,OAAO,CAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;YAC1E,UAAU,EAAE,CAAC,QAAQ,CAAC;SACvB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;AAC9D,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interceptor pipeline for @liteforge/client
|
|
3
|
+
*
|
|
4
|
+
* Request interceptors run in insertion order (FIFO).
|
|
5
|
+
* Response interceptors run in reverse insertion order (LIFO) — Axios-style.
|
|
6
|
+
*/
|
|
7
|
+
import type { InterceptorHandlers, RequestConfig, ResponseContext } from './types.js';
|
|
8
|
+
import type { ApiError } from './errors.js';
|
|
9
|
+
export interface InterceptorRegistry {
|
|
10
|
+
add: (handlers: InterceptorHandlers) => () => void;
|
|
11
|
+
runRequest: (config: RequestConfig) => Promise<RequestConfig>;
|
|
12
|
+
runResponse: (response: ResponseContext<unknown>) => Promise<ResponseContext<unknown>>;
|
|
13
|
+
runRequestError: (error: unknown) => Promise<never>;
|
|
14
|
+
runResponseError: (error: ApiError) => Promise<never>;
|
|
15
|
+
}
|
|
16
|
+
export declare function createInterceptorRegistry(): InterceptorRegistry;
|
|
17
|
+
//# sourceMappingURL=interceptors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interceptors.d.ts","sourceRoot":"","sources":["../src/interceptors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACtF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,CAAC,QAAQ,EAAE,mBAAmB,KAAK,MAAM,IAAI,CAAC;IACnD,UAAU,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC;IAC9D,WAAW,EAAE,CAAC,QAAQ,EAAE,eAAe,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;IACvF,eAAe,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,KAAK,CAAC,CAAC;IACpD,gBAAgB,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,OAAO,CAAC,KAAK,CAAC,CAAC;CACvD;AAED,wBAAgB,yBAAyB,IAAI,mBAAmB,CAoD/D"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interceptor pipeline for @liteforge/client
|
|
3
|
+
*
|
|
4
|
+
* Request interceptors run in insertion order (FIFO).
|
|
5
|
+
* Response interceptors run in reverse insertion order (LIFO) — Axios-style.
|
|
6
|
+
*/
|
|
7
|
+
export function createInterceptorRegistry() {
|
|
8
|
+
const handlers = [];
|
|
9
|
+
function add(h) {
|
|
10
|
+
handlers.push(h);
|
|
11
|
+
return () => {
|
|
12
|
+
const idx = handlers.indexOf(h);
|
|
13
|
+
if (idx !== -1)
|
|
14
|
+
handlers.splice(idx, 1);
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
async function runRequest(config) {
|
|
18
|
+
let current = config;
|
|
19
|
+
for (const h of handlers) {
|
|
20
|
+
if (h.onRequest) {
|
|
21
|
+
current = await h.onRequest(current);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return current;
|
|
25
|
+
}
|
|
26
|
+
async function runResponse(response) {
|
|
27
|
+
let current = response;
|
|
28
|
+
// LIFO order for response interceptors
|
|
29
|
+
for (let i = handlers.length - 1; i >= 0; i--) {
|
|
30
|
+
const h = handlers[i];
|
|
31
|
+
if (h !== undefined && h.onResponse) {
|
|
32
|
+
current = await h.onResponse(current);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return current;
|
|
36
|
+
}
|
|
37
|
+
async function runRequestError(error) {
|
|
38
|
+
for (const h of handlers) {
|
|
39
|
+
if (h.onRequestError) {
|
|
40
|
+
return h.onRequestError(error);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
async function runResponseError(error) {
|
|
46
|
+
for (const h of handlers) {
|
|
47
|
+
if (h.onResponseError) {
|
|
48
|
+
return h.onResponseError(error);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
return { add, runRequest, runResponse, runRequestError, runResponseError };
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=interceptors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interceptors.js","sourceRoot":"","sources":["../src/interceptors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAaH,MAAM,UAAU,yBAAyB;IACvC,MAAM,QAAQ,GAA0B,EAAE,CAAC;IAE3C,SAAS,GAAG,CAAC,CAAsB;QACjC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjB,OAAO,GAAG,EAAE;YACV,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YAChC,IAAI,GAAG,KAAK,CAAC,CAAC;gBAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAC1C,CAAC,CAAC;IACJ,CAAC;IAED,KAAK,UAAU,UAAU,CAAC,MAAqB;QAC7C,IAAI,OAAO,GAAG,MAAM,CAAC;QACrB,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YACzB,IAAI,CAAC,CAAC,SAAS,EAAE,CAAC;gBAChB,OAAO,GAAG,MAAM,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,UAAU,WAAW,CAAC,QAAkC;QAC3D,IAAI,OAAO,GAAG,QAAQ,CAAC;QACvB,uCAAuC;QACvC,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC9C,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YACtB,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;gBACpC,OAAO,GAAG,MAAM,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YACxC,CAAC;QACH,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,UAAU,eAAe,CAAC,KAAc;QAC3C,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YACzB,IAAI,CAAC,CAAC,cAAc,EAAE,CAAC;gBACrB,OAAO,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;IAED,KAAK,UAAU,gBAAgB,CAAC,KAAe;QAC7C,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YACzB,IAAI,CAAC,CAAC,eAAe,EAAE,CAAC;gBACtB,OAAO,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;YAClC,CAAC;QACH,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;IAED,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE,gBAAgB,EAAE,CAAC;AAC7E,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Middleware pipeline for @liteforge/client
|
|
3
|
+
*
|
|
4
|
+
* Middleware wraps the core fetch execution. The first middleware added
|
|
5
|
+
* is the outermost wrapper (compose-style).
|
|
6
|
+
*/
|
|
7
|
+
import type { Middleware, RequestConfig, ResponseContext } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Composes an array of middleware around a core handler.
|
|
10
|
+
*
|
|
11
|
+
* @param middlewares - List of middleware (outermost first)
|
|
12
|
+
* @param core - The innermost handler (executeFetch)
|
|
13
|
+
*/
|
|
14
|
+
export declare function createMiddlewarePipeline(middlewares: Middleware[], core: (config: RequestConfig) => Promise<ResponseContext>): (config: RequestConfig) => Promise<ResponseContext>;
|
|
15
|
+
//# sourceMappingURL=middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7E;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,UAAU,EAAE,EACzB,IAAI,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC,eAAe,CAAC,GACxD,CAAC,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC,eAAe,CAAC,CAcrD"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Middleware pipeline for @liteforge/client
|
|
3
|
+
*
|
|
4
|
+
* Middleware wraps the core fetch execution. The first middleware added
|
|
5
|
+
* is the outermost wrapper (compose-style).
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Composes an array of middleware around a core handler.
|
|
9
|
+
*
|
|
10
|
+
* @param middlewares - List of middleware (outermost first)
|
|
11
|
+
* @param core - The innermost handler (executeFetch)
|
|
12
|
+
*/
|
|
13
|
+
export function createMiddlewarePipeline(middlewares, core) {
|
|
14
|
+
if (middlewares.length === 0) {
|
|
15
|
+
return core;
|
|
16
|
+
}
|
|
17
|
+
// Build the chain from the inside out (right to left)
|
|
18
|
+
let handler = core;
|
|
19
|
+
for (let i = middlewares.length - 1; i >= 0; i--) {
|
|
20
|
+
const mw = middlewares[i];
|
|
21
|
+
if (mw === undefined)
|
|
22
|
+
continue;
|
|
23
|
+
const next = handler;
|
|
24
|
+
handler = (config) => mw(config, next);
|
|
25
|
+
}
|
|
26
|
+
return handler;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CACtC,WAAyB,EACzB,IAAyD;IAEzD,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,sDAAsD;IACtD,IAAI,OAAO,GAAwD,IAAI,CAAC;IACxE,KAAK,IAAI,CAAC,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACjD,MAAM,EAAE,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;QAC1B,IAAI,EAAE,KAAK,SAAS;YAAE,SAAS;QAC/B,MAAM,IAAI,GAAG,OAAO,CAAC;QACrB,OAAO,GAAG,CAAC,MAAqB,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core fetch execution for @liteforge/client
|
|
3
|
+
*/
|
|
4
|
+
import type { RequestConfig, ResponseContext } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Executes a fetch request described by `config` and returns a typed
|
|
7
|
+
* `ResponseContext`. Throws `ApiError` on non-2xx responses.
|
|
8
|
+
*/
|
|
9
|
+
export declare function executeFetch<T>(config: RequestConfig): Promise<ResponseContext<T>>;
|
|
10
|
+
//# sourceMappingURL=request.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../src/request.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGjE;;;GAGG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CA2ExF"}
|
package/dist/request.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core fetch execution for @liteforge/client
|
|
3
|
+
*/
|
|
4
|
+
import { ApiError } from './errors.js';
|
|
5
|
+
import { appendQueryParams } from './utils/url.js';
|
|
6
|
+
/**
|
|
7
|
+
* Executes a fetch request described by `config` and returns a typed
|
|
8
|
+
* `ResponseContext`. Throws `ApiError` on non-2xx responses.
|
|
9
|
+
*/
|
|
10
|
+
export async function executeFetch(config) {
|
|
11
|
+
// 1. Build full URL
|
|
12
|
+
let url = config.url;
|
|
13
|
+
if (config.params !== undefined && Object.keys(config.params).length > 0) {
|
|
14
|
+
url = appendQueryParams(url, config.params);
|
|
15
|
+
}
|
|
16
|
+
// 2. Construct headers (always lowercase keys for consistency)
|
|
17
|
+
const headersInit = {};
|
|
18
|
+
for (const [key, value] of Object.entries(config.headers ?? {})) {
|
|
19
|
+
headersInit[key.toLowerCase()] = value;
|
|
20
|
+
}
|
|
21
|
+
// 3. Build body
|
|
22
|
+
let body = null;
|
|
23
|
+
if (config.body !== undefined) {
|
|
24
|
+
if (typeof config.body === 'string') {
|
|
25
|
+
body = config.body;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
body = JSON.stringify(config.body);
|
|
29
|
+
// 4. Auto-set Content-Type if not already present
|
|
30
|
+
if (headersInit['content-type'] === undefined) {
|
|
31
|
+
headersInit['content-type'] = 'application/json';
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// 5. Timeout via AbortController
|
|
36
|
+
const controller = new AbortController();
|
|
37
|
+
const timeoutMs = config.timeout ?? 30000;
|
|
38
|
+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
39
|
+
// Merge with any external signal
|
|
40
|
+
const signal = config.signal
|
|
41
|
+
? mergeAbortSignals(config.signal, controller.signal)
|
|
42
|
+
: controller.signal;
|
|
43
|
+
const init = {
|
|
44
|
+
method: config.method,
|
|
45
|
+
headers: headersInit,
|
|
46
|
+
body,
|
|
47
|
+
signal,
|
|
48
|
+
};
|
|
49
|
+
let response;
|
|
50
|
+
try {
|
|
51
|
+
// 6. Execute fetch — network errors propagate as-is
|
|
52
|
+
response = await fetch(url, init);
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
clearTimeout(timeoutId);
|
|
56
|
+
}
|
|
57
|
+
// 7. Parse body (try JSON first, fall back to text)
|
|
58
|
+
const rawData = await parseBody(response);
|
|
59
|
+
// 8. Throw ApiError on non-2xx
|
|
60
|
+
if (!response.ok) {
|
|
61
|
+
throw new ApiError({
|
|
62
|
+
status: response.status,
|
|
63
|
+
statusText: response.statusText,
|
|
64
|
+
data: rawData,
|
|
65
|
+
config,
|
|
66
|
+
retry: () => executeFetch(config),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
// 9. Return ResponseContext
|
|
70
|
+
return {
|
|
71
|
+
data: rawData,
|
|
72
|
+
status: response.status,
|
|
73
|
+
statusText: response.statusText,
|
|
74
|
+
headers: response.headers,
|
|
75
|
+
config,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
// ============================================================================
|
|
79
|
+
// Helpers
|
|
80
|
+
// ============================================================================
|
|
81
|
+
async function parseBody(response) {
|
|
82
|
+
const contentType = response.headers.get('content-type') ?? '';
|
|
83
|
+
if (contentType.includes('application/json')) {
|
|
84
|
+
try {
|
|
85
|
+
return await response.json();
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// For empty bodies (e.g. 204 No Content) json() would fail; use text
|
|
92
|
+
const text = await response.text();
|
|
93
|
+
if (text === '')
|
|
94
|
+
return null;
|
|
95
|
+
// Try to parse as JSON anyway (some APIs omit the content-type header)
|
|
96
|
+
try {
|
|
97
|
+
return JSON.parse(text);
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return text;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Merges two AbortSignals: abort fires when either fires.
|
|
105
|
+
* Uses AbortSignal.any() if available (Node 20+), otherwise falls back.
|
|
106
|
+
*/
|
|
107
|
+
function mergeAbortSignals(external, internal) {
|
|
108
|
+
if ('any' in AbortSignal && typeof AbortSignal.any === 'function') {
|
|
109
|
+
return AbortSignal.any([external, internal]);
|
|
110
|
+
}
|
|
111
|
+
// Fallback: create a controller that mirrors both
|
|
112
|
+
const controller = new AbortController();
|
|
113
|
+
const abort = () => controller.abort();
|
|
114
|
+
if (external.aborted || internal.aborted) {
|
|
115
|
+
controller.abort();
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
external.addEventListener('abort', abort, { once: true });
|
|
119
|
+
internal.addEventListener('abort', abort, { once: true });
|
|
120
|
+
}
|
|
121
|
+
return controller.signal;
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=request.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request.js","sourceRoot":"","sources":["../src/request.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource factory for @liteforge/client
|
|
3
|
+
*
|
|
4
|
+
* Provides strongly-typed CRUD methods for a REST resource.
|
|
5
|
+
*/
|
|
6
|
+
import type { Resource, ResourceOptions, RequestConfig } from './types.js';
|
|
7
|
+
import type { QueryIntegration, QueryMethods } from './integrations/query.js';
|
|
8
|
+
export declare function createResource<T, TCreate, TUpdate>(name: string, options: ResourceOptions, request: <R>(config: RequestConfig) => Promise<R>, queryIntegration?: QueryIntegration): Resource<T, TCreate, TUpdate> & Partial<QueryMethods<T, TCreate, TUpdate>>;
|
|
9
|
+
//# sourceMappingURL=resource.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../src/resource.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,aAAa,EAA4B,MAAM,YAAY,CAAC;AACrG,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAI9E,wBAAgB,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAChD,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC,CAAC,CAAC,EACjD,gBAAgB,CAAC,EAAE,gBAAgB,GAClC,QAAQ,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CA8E5E"}
|
package/dist/resource.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource factory for @liteforge/client
|
|
3
|
+
*
|
|
4
|
+
* Provides strongly-typed CRUD methods for a REST resource.
|
|
5
|
+
*/
|
|
6
|
+
import { buildQueryMethods } from './integrations/query.js';
|
|
7
|
+
import { buildUrl, appendQueryParams } from './utils/url.js';
|
|
8
|
+
export function createResource(name, options, request, queryIntegration) {
|
|
9
|
+
const basePath = options.path ?? name;
|
|
10
|
+
const extraHeaders = options.headers;
|
|
11
|
+
function withHeaders(cfg) {
|
|
12
|
+
if (extraHeaders === undefined)
|
|
13
|
+
return cfg;
|
|
14
|
+
return { ...cfg, headers: { ...extraHeaders, ...cfg.headers } };
|
|
15
|
+
}
|
|
16
|
+
function getList(params) {
|
|
17
|
+
let url = basePath;
|
|
18
|
+
if (params !== undefined && Object.keys(params).length > 0) {
|
|
19
|
+
url = appendQueryParams(basePath, params);
|
|
20
|
+
}
|
|
21
|
+
return request(withHeaders({ method: 'GET', url }));
|
|
22
|
+
}
|
|
23
|
+
function getOne(id) {
|
|
24
|
+
return request(withHeaders({ method: 'GET', url: buildUrl(basePath, String(id)) }));
|
|
25
|
+
}
|
|
26
|
+
function create(data) {
|
|
27
|
+
return request(withHeaders({ method: 'POST', url: basePath, body: data }));
|
|
28
|
+
}
|
|
29
|
+
function update(id, data) {
|
|
30
|
+
return request(withHeaders({ method: 'PUT', url: buildUrl(basePath, String(id)), body: data }));
|
|
31
|
+
}
|
|
32
|
+
function patch(id, data) {
|
|
33
|
+
return request(withHeaders({ method: 'PATCH', url: buildUrl(basePath, String(id)), body: data }));
|
|
34
|
+
}
|
|
35
|
+
function del(id) {
|
|
36
|
+
return request(withHeaders({ method: 'DELETE', url: buildUrl(basePath, String(id)) }));
|
|
37
|
+
}
|
|
38
|
+
function action(actionName, data, id) {
|
|
39
|
+
const url = id !== undefined
|
|
40
|
+
? buildUrl(buildUrl(basePath, String(id)), actionName)
|
|
41
|
+
: buildUrl(basePath, actionName);
|
|
42
|
+
return request(withHeaders({ method: 'POST', url, body: data }));
|
|
43
|
+
}
|
|
44
|
+
function custom(cfg) {
|
|
45
|
+
const { path, ...rest } = cfg;
|
|
46
|
+
return request(withHeaders({ ...rest, url: buildUrl(basePath, path) }));
|
|
47
|
+
}
|
|
48
|
+
const resource = {
|
|
49
|
+
getList,
|
|
50
|
+
getOne,
|
|
51
|
+
create,
|
|
52
|
+
update,
|
|
53
|
+
patch,
|
|
54
|
+
delete: del,
|
|
55
|
+
action,
|
|
56
|
+
custom,
|
|
57
|
+
};
|
|
58
|
+
if (queryIntegration !== undefined) {
|
|
59
|
+
const queryMethods = buildQueryMethods(name, // short resource name → used as query cache key
|
|
60
|
+
basePath, // full fetch URL
|
|
61
|
+
request, queryIntegration);
|
|
62
|
+
return { ...resource, ...queryMethods };
|
|
63
|
+
}
|
|
64
|
+
return resource;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=resource.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource.js","sourceRoot":"","sources":["../src/resource.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @liteforge/client Types
|
|
3
|
+
*
|
|
4
|
+
* All TypeScript interfaces and types for the HTTP client.
|
|
5
|
+
*/
|
|
6
|
+
import type { ApiError } from './errors.js';
|
|
7
|
+
export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
8
|
+
export interface ClientConfig {
|
|
9
|
+
/** Base URL for all requests (e.g. 'https://api.example.com') */
|
|
10
|
+
baseUrl: string;
|
|
11
|
+
/** Default headers merged into every request */
|
|
12
|
+
headers?: Record<string, string>;
|
|
13
|
+
/** Request timeout in ms (default: 30_000) */
|
|
14
|
+
timeout?: number;
|
|
15
|
+
/** Number of retry attempts on network/5xx errors (default: 0) */
|
|
16
|
+
retry?: number;
|
|
17
|
+
/** Base delay in ms for exponential backoff (default: 300) */
|
|
18
|
+
retryDelay?: number;
|
|
19
|
+
}
|
|
20
|
+
export interface RequestConfig {
|
|
21
|
+
method: HttpMethod;
|
|
22
|
+
/** Full URL (built from baseUrl + path by the client) */
|
|
23
|
+
url: string;
|
|
24
|
+
headers?: Record<string, string>;
|
|
25
|
+
body?: unknown;
|
|
26
|
+
params?: Record<string, string | number | boolean>;
|
|
27
|
+
signal?: AbortSignal;
|
|
28
|
+
timeout?: number;
|
|
29
|
+
retry?: number;
|
|
30
|
+
}
|
|
31
|
+
export interface ResponseContext<T = unknown> {
|
|
32
|
+
data: T;
|
|
33
|
+
status: number;
|
|
34
|
+
statusText: string;
|
|
35
|
+
headers: Headers;
|
|
36
|
+
config: RequestConfig;
|
|
37
|
+
}
|
|
38
|
+
export interface InterceptorHandlers {
|
|
39
|
+
onRequest?: (config: RequestConfig) => RequestConfig | Promise<RequestConfig>;
|
|
40
|
+
onResponse?: (response: ResponseContext<unknown>) => ResponseContext<unknown> | Promise<ResponseContext<unknown>>;
|
|
41
|
+
onRequestError?: (error: unknown) => never | Promise<never>;
|
|
42
|
+
onResponseError?: (error: ApiError) => never | Promise<never>;
|
|
43
|
+
}
|
|
44
|
+
export type Middleware = (config: RequestConfig, next: (config: RequestConfig) => Promise<ResponseContext>) => Promise<ResponseContext>;
|
|
45
|
+
export interface ResourceOptions {
|
|
46
|
+
/** Override URL path (default: resource name) */
|
|
47
|
+
path?: string;
|
|
48
|
+
/** Extra headers merged into every resource request */
|
|
49
|
+
headers?: Record<string, string>;
|
|
50
|
+
/** Key used as the record identifier (default: 'id') */
|
|
51
|
+
idKey?: string;
|
|
52
|
+
}
|
|
53
|
+
export interface ListParams {
|
|
54
|
+
page?: number;
|
|
55
|
+
pageSize?: number;
|
|
56
|
+
sort?: string;
|
|
57
|
+
order?: 'asc' | 'desc';
|
|
58
|
+
[key: string]: string | number | boolean | undefined;
|
|
59
|
+
}
|
|
60
|
+
export interface ListMeta {
|
|
61
|
+
total: number;
|
|
62
|
+
page: number;
|
|
63
|
+
pageSize: number;
|
|
64
|
+
totalPages: number;
|
|
65
|
+
}
|
|
66
|
+
export interface ListResponse<T> {
|
|
67
|
+
data: T[];
|
|
68
|
+
meta: ListMeta;
|
|
69
|
+
}
|
|
70
|
+
export interface Resource<T, TCreate = Partial<T>, TUpdate = Partial<T>> {
|
|
71
|
+
getList: (params?: ListParams) => Promise<ListResponse<T>>;
|
|
72
|
+
getOne: (id: string | number) => Promise<T>;
|
|
73
|
+
create: (data: TCreate) => Promise<T>;
|
|
74
|
+
update: (id: string | number, data: TUpdate) => Promise<T>;
|
|
75
|
+
patch: (id: string | number, data: Partial<TUpdate>) => Promise<T>;
|
|
76
|
+
delete: (id: string | number) => Promise<void>;
|
|
77
|
+
action: (action: string, data?: unknown, id?: string | number) => Promise<unknown>;
|
|
78
|
+
custom: <TResult>(config: Omit<RequestConfig, 'url'> & {
|
|
79
|
+
path: string;
|
|
80
|
+
}) => Promise<TResult>;
|
|
81
|
+
}
|
|
82
|
+
export interface Client {
|
|
83
|
+
resource: <T, TCreate = Partial<T>, TUpdate = Partial<T>>(name: string, options?: ResourceOptions) => Resource<T, TCreate, TUpdate>;
|
|
84
|
+
get: <T>(path: string, config?: Partial<RequestConfig>) => Promise<T>;
|
|
85
|
+
post: <T>(path: string, body?: unknown, config?: Partial<RequestConfig>) => Promise<T>;
|
|
86
|
+
put: <T>(path: string, body?: unknown, config?: Partial<RequestConfig>) => Promise<T>;
|
|
87
|
+
patch: <T>(path: string, body?: unknown, config?: Partial<RequestConfig>) => Promise<T>;
|
|
88
|
+
delete: <T>(path: string, config?: Partial<RequestConfig>) => Promise<T>;
|
|
89
|
+
/** Add interceptor handlers. Returns a remove function. */
|
|
90
|
+
addInterceptor: (handlers: InterceptorHandlers) => () => void;
|
|
91
|
+
/** Add middleware. Returns a remove function. */
|
|
92
|
+
use: (middleware: Middleware) => () => void;
|
|
93
|
+
}
|
|
94
|
+
export interface CreateClientOptions extends ClientConfig {
|
|
95
|
+
interceptors?: InterceptorHandlers[];
|
|
96
|
+
middleware?: Middleware[];
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Header utilities for @liteforge/client
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Merges multiple header records into one. Later sources override earlier ones.
|
|
6
|
+
* All keys are lowercased for consistency.
|
|
7
|
+
*/
|
|
8
|
+
export declare function mergeHeaders(...sources: Array<Record<string, string> | undefined>): Record<string, string>;
|
|
9
|
+
//# sourceMappingURL=headers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headers.d.ts","sourceRoot":"","sources":["../../src/utils/headers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,GAAG,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC,GACpD,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAWxB"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Header utilities for @liteforge/client
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Merges multiple header records into one. Later sources override earlier ones.
|
|
6
|
+
* All keys are lowercased for consistency.
|
|
7
|
+
*/
|
|
8
|
+
export function mergeHeaders(...sources) {
|
|
9
|
+
const result = {};
|
|
10
|
+
for (const source of sources) {
|
|
11
|
+
if (source === undefined)
|
|
12
|
+
continue;
|
|
13
|
+
for (const [key, value] of Object.entries(source)) {
|
|
14
|
+
result[key.toLowerCase()] = value;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return result;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=headers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headers.js","sourceRoot":"","sources":["../../src/utils/headers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC1B,GAAG,OAAkD;IAErD,MAAM,MAAM,GAA2B,EAAE,CAAC;IAE1C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,MAAM,KAAK,SAAS;YAAE,SAAS;QACnC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAClD,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,GAAG,KAAK,CAAC;QACpC,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retry utility with exponential backoff for @liteforge/client
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Executes `fn`, retrying up to `times` times on retryable errors.
|
|
6
|
+
* Uses exponential backoff: delay = baseDelay * 2^attempt (0-indexed).
|
|
7
|
+
*/
|
|
8
|
+
export declare function retryRequest<T>(fn: () => Promise<T>, times: number, baseDelay: number): Promise<T>;
|
|
9
|
+
//# sourceMappingURL=retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/utils/retry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAiBH;;;GAGG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAClC,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,CAAC,CAAC,CAoBZ"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retry utility with exponential backoff for @liteforge/client
|
|
3
|
+
*/
|
|
4
|
+
import { ApiError } from '../errors.js';
|
|
5
|
+
function delay(ms) {
|
|
6
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
7
|
+
}
|
|
8
|
+
function isRetryable(error) {
|
|
9
|
+
if (error instanceof ApiError) {
|
|
10
|
+
// Only retry on 5xx (server errors) — never on 4xx (client errors)
|
|
11
|
+
return error.status >= 500;
|
|
12
|
+
}
|
|
13
|
+
// Network-level errors (fetch rejected, e.g. DNS failure) are always retryable
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Executes `fn`, retrying up to `times` times on retryable errors.
|
|
18
|
+
* Uses exponential backoff: delay = baseDelay * 2^attempt (0-indexed).
|
|
19
|
+
*/
|
|
20
|
+
export async function retryRequest(fn, times, baseDelay) {
|
|
21
|
+
let lastError;
|
|
22
|
+
for (let attempt = 0; attempt <= times; attempt++) {
|
|
23
|
+
try {
|
|
24
|
+
return await fn();
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
lastError = err;
|
|
28
|
+
if (!isRetryable(err) || attempt === times) {
|
|
29
|
+
throw err;
|
|
30
|
+
}
|
|
31
|
+
const waitMs = baseDelay * Math.pow(2, attempt);
|
|
32
|
+
await delay(waitMs);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// This path is unreachable but satisfies TypeScript
|
|
36
|
+
throw lastError;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/utils/retry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,WAAW,CAAC,KAAc;IACjC,IAAI,KAAK,YAAY,QAAQ,EAAE,CAAC;QAC9B,mEAAmE;QACnE,OAAO,KAAK,CAAC,MAAM,IAAI,GAAG,CAAC;IAC7B,CAAC;IACD,+EAA+E;IAC/E,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,EAAoB,EACpB,KAAa,EACb,SAAiB;IAEjB,IAAI,SAAkB,CAAC;IAEvB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC;QAClD,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,EAAE,CAAC;QACpB,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,SAAS,GAAG,GAAG,CAAC;YAEhB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,OAAO,KAAK,KAAK,EAAE,CAAC;gBAC3C,MAAM,GAAG,CAAC;YACZ,CAAC;YAED,MAAM,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAChD,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,oDAAoD;IACpD,MAAM,SAAS,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URL utilities for @liteforge/client
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Joins a base URL and a path, normalising slashes so there is exactly
|
|
6
|
+
* one `/` between them and no trailing slash is added.
|
|
7
|
+
*/
|
|
8
|
+
export declare function buildUrl(base: string, path: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* Appends a params object to a URL as a query string.
|
|
11
|
+
* `undefined` / `null` values are skipped.
|
|
12
|
+
*/
|
|
13
|
+
export declare function appendQueryParams(url: string, params: Record<string, string | number | boolean | undefined>): string;
|
|
14
|
+
//# sourceMappingURL=url.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../../src/utils/url.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAS3D;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,GAC5D,MAAM,CAaR"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URL utilities for @liteforge/client
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Joins a base URL and a path, normalising slashes so there is exactly
|
|
6
|
+
* one `/` between them and no trailing slash is added.
|
|
7
|
+
*/
|
|
8
|
+
export function buildUrl(base, path) {
|
|
9
|
+
const trimmedBase = base.replace(/\/+$/, '');
|
|
10
|
+
const trimmedPath = path.replace(/^\/+/, '');
|
|
11
|
+
if (trimmedPath === '') {
|
|
12
|
+
return trimmedBase;
|
|
13
|
+
}
|
|
14
|
+
return `${trimmedBase}/${trimmedPath}`;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Appends a params object to a URL as a query string.
|
|
18
|
+
* `undefined` / `null` values are skipped.
|
|
19
|
+
*/
|
|
20
|
+
export function appendQueryParams(url, params) {
|
|
21
|
+
const search = new URLSearchParams();
|
|
22
|
+
for (const [key, value] of Object.entries(params)) {
|
|
23
|
+
if (value !== undefined && value !== null) {
|
|
24
|
+
search.append(key, String(value));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const qs = search.toString();
|
|
28
|
+
if (qs === '')
|
|
29
|
+
return url;
|
|
30
|
+
return url.includes('?') ? `${url}&${qs}` : `${url}?${qs}`;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=url.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url.js","sourceRoot":"","sources":["../../src/utils/url.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,IAAY;IACjD,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC7C,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAE7C,IAAI,WAAW,KAAK,EAAE,EAAE,CAAC;QACvB,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,OAAO,GAAG,WAAW,IAAI,WAAW,EAAE,CAAC;AACzC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,GAAW,EACX,MAA6D;IAE7D,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;IAErC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YAC1C,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAED,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC7B,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,GAAG,CAAC;IAE1B,OAAO,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,EAAE,EAAE,CAAC;AAC7D,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@liteforge/client",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "TypeScript-first HTTP client. createClient, resource-based CRUD, interceptors, optional @liteforge/query integration.",
|
|
5
|
+
"author": "SchildW3rk <contact@schildw3rk.dev>",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/schildw3rk/liteforge",
|
|
10
|
+
"directory": "packages/client"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/schildw3rk/liteforge#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/schildw3rk/liteforge/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"liteforge",
|
|
18
|
+
"http",
|
|
19
|
+
"client",
|
|
20
|
+
"fetch",
|
|
21
|
+
"rest",
|
|
22
|
+
"api",
|
|
23
|
+
"signals",
|
|
24
|
+
"reactive"
|
|
25
|
+
],
|
|
26
|
+
"type": "module",
|
|
27
|
+
"main": "./dist/index.js",
|
|
28
|
+
"module": "./dist/index.js",
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"exports": {
|
|
31
|
+
".": {
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"import": "./dist/index.js"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"dist",
|
|
38
|
+
"README.md",
|
|
39
|
+
"LICENSE"
|
|
40
|
+
],
|
|
41
|
+
"sideEffects": false,
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=18"
|
|
44
|
+
},
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
},
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"@liteforge/query": ">=0.1.0"
|
|
50
|
+
},
|
|
51
|
+
"peerDependenciesMeta": {
|
|
52
|
+
"@liteforge/query": {
|
|
53
|
+
"optional": true
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@liteforge/query": "0.1.1"
|
|
58
|
+
},
|
|
59
|
+
"scripts": {
|
|
60
|
+
"build": "tsc -p tsconfig.build.json",
|
|
61
|
+
"dev": "tsc -p tsconfig.build.json --watch",
|
|
62
|
+
"typecheck": "tsc --noEmit",
|
|
63
|
+
"clean": "rm -rf dist *.tsbuildinfo"
|
|
64
|
+
}
|
|
65
|
+
}
|