@zmdb/client 1.0.0-beta.1
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 +674 -0
- package/README.md +57 -0
- package/dist/body/index.d.ts +7 -0
- package/dist/body/index.d.ts.map +1 -0
- package/dist/body/index.js +55 -0
- package/dist/body/index.js.map +1 -0
- package/dist/errors/index.d.ts +59 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +117 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/headers/index.d.ts +6 -0
- package/dist/headers/index.d.ts.map +1 -0
- package/dist/headers/index.js +52 -0
- package/dist/headers/index.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime.d.ts +4 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +585 -0
- package/dist/runtime.js.map +1 -0
- package/dist/testing/index.d.ts +13 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +53 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/transport/index.d.ts +4 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +47 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/types.d.ts +116 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/url/index.d.ts +17 -0
- package/dist/url/index.d.ts.map +1 -0
- package/dist/url/index.js +98 -0
- package/dist/url/index.js.map +1 -0
- package/package.json +68 -0
- package/src/body/index.ts +58 -0
- package/src/errors/index.ts +152 -0
- package/src/headers/index.ts +57 -0
- package/src/index.ts +42 -0
- package/src/runtime.ts +741 -0
- package/src/testing/index.ts +67 -0
- package/src/transport/index.ts +56 -0
- package/src/types.ts +128 -0
- package/src/url/index.ts +113 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export function createFakeClientTransport() {
|
|
2
|
+
const observed = [];
|
|
3
|
+
const held = [];
|
|
4
|
+
const waiters = [];
|
|
5
|
+
const transport = request => new Promise((resolve, reject) => {
|
|
6
|
+
observed.push(request);
|
|
7
|
+
let settled = false;
|
|
8
|
+
const onAbort = () => {
|
|
9
|
+
if (settled)
|
|
10
|
+
return;
|
|
11
|
+
settled = true;
|
|
12
|
+
reject(request.signal?.reason);
|
|
13
|
+
};
|
|
14
|
+
request.signal?.addEventListener('abort', onAbort, { once: true });
|
|
15
|
+
const pending = Object.freeze({
|
|
16
|
+
request,
|
|
17
|
+
respond(response) {
|
|
18
|
+
if (settled)
|
|
19
|
+
return;
|
|
20
|
+
settled = true;
|
|
21
|
+
request.signal?.removeEventListener('abort', onAbort);
|
|
22
|
+
resolve(response);
|
|
23
|
+
},
|
|
24
|
+
fail(error) {
|
|
25
|
+
if (settled)
|
|
26
|
+
return;
|
|
27
|
+
settled = true;
|
|
28
|
+
request.signal?.removeEventListener('abort', onAbort);
|
|
29
|
+
reject(error);
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
const waiter = waiters.shift();
|
|
33
|
+
if (waiter === undefined)
|
|
34
|
+
held.push(pending);
|
|
35
|
+
else
|
|
36
|
+
waiter.resolve(pending);
|
|
37
|
+
});
|
|
38
|
+
return Object.freeze({
|
|
39
|
+
transport,
|
|
40
|
+
get requests() {
|
|
41
|
+
return Object.freeze([...observed]);
|
|
42
|
+
},
|
|
43
|
+
nextRequest() {
|
|
44
|
+
const pending = held.shift();
|
|
45
|
+
if (pending !== undefined)
|
|
46
|
+
return Promise.resolve(pending);
|
|
47
|
+
return new Promise(resolve => {
|
|
48
|
+
waiters.push({ resolve });
|
|
49
|
+
});
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAkBA,MAAM,UAAU,yBAAyB;IACvC,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,MAAM,IAAI,GAAwB,EAAE,CAAC;IACrC,MAAM,OAAO,GAAoB,EAAE,CAAC;IAEpC,MAAM,SAAS,GAAoB,OAAO,CAAC,EAAE,CAC3C,IAAI,OAAO,CAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC9C,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvB,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,MAAM,OAAO,GAAG,GAAS,EAAE;YACzB,IAAI,OAAO;gBAAE,OAAO;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACjC,CAAC,CAAC;QACF,OAAO,CAAC,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACnE,MAAM,OAAO,GAAsB,MAAM,CAAC,MAAM,CAAC;YAC/C,OAAO;YACP,OAAO,CAAC,QAAwB;gBAC9B,IAAI,OAAO;oBAAE,OAAO;gBACpB,OAAO,GAAG,IAAI,CAAC;gBACf,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBACtD,OAAO,CAAC,QAAQ,CAAC,CAAC;YACpB,CAAC;YACD,IAAI,CAAC,KAAc;gBACjB,IAAI,OAAO;oBAAE,OAAO;gBACpB,OAAO,GAAG,IAAI,CAAC;gBACf,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBACtD,MAAM,CAAC,KAAK,CAAC,CAAC;YAChB,CAAC;SACF,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;QAC/B,IAAI,MAAM,KAAK,SAAS;YAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;;YACxC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEL,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,SAAS;QACT,IAAI,QAAQ;YACV,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;QACtC,CAAC;QACD,WAAW;YACT,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;YAC7B,IAAI,OAAO,KAAK,SAAS;gBAAE,OAAO,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAC3D,OAAO,IAAI,OAAO,CAAoB,OAAO,CAAC,EAAE;gBAC9C,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;YAC5B,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/transport/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAiC,eAAe,EAAE,MAAM,aAAa,CAAC;AAElF,MAAM,MAAM,SAAS,GAAG,OAAO,UAAU,CAAC,KAAK,CAAC;AAchD,wBAAgB,oBAAoB,CAAC,QAAQ,CAAC,EAAE,SAAS,GAAG,eAAe,CAqC1E"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { ClientRequestError, TransportError } from '../errors/index.js';
|
|
2
|
+
import { normalizeClientHeaders } from '../headers/index.js';
|
|
3
|
+
function fetchFunction(injected) {
|
|
4
|
+
const candidate = injected ?? globalThis.fetch;
|
|
5
|
+
if (typeof candidate !== 'function') {
|
|
6
|
+
throw new ClientRequestError('Fetch is unavailable; inject a ClientTransport or Fetch implementation');
|
|
7
|
+
}
|
|
8
|
+
return candidate;
|
|
9
|
+
}
|
|
10
|
+
export function createFetchTransport(injected) {
|
|
11
|
+
const fetch = fetchFunction(injected);
|
|
12
|
+
return async (request) => {
|
|
13
|
+
if (request.headers.cookie !== undefined) {
|
|
14
|
+
throw new ClientRequestError('Fetch cannot guarantee an explicit cookie request header');
|
|
15
|
+
}
|
|
16
|
+
const init = {
|
|
17
|
+
method: request.method,
|
|
18
|
+
headers: request.headers,
|
|
19
|
+
redirect: 'manual',
|
|
20
|
+
...(request.body === undefined ? {} : { body: request.body }),
|
|
21
|
+
...(request.signal === undefined ? {} : { signal: request.signal }),
|
|
22
|
+
...(request.body instanceof ReadableStream ? { duplex: 'half' } : {}),
|
|
23
|
+
};
|
|
24
|
+
let response;
|
|
25
|
+
try {
|
|
26
|
+
response = await fetch(request.url, init);
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
if (request.signal?.aborted === true)
|
|
30
|
+
throw request.signal.reason;
|
|
31
|
+
throw new TransportError(undefined, error);
|
|
32
|
+
}
|
|
33
|
+
if (response.status <= 0 || response.type === 'opaqueredirect') {
|
|
34
|
+
throw new TransportError(undefined, new Error('Fetch returned an opaque redirect or unusable status'));
|
|
35
|
+
}
|
|
36
|
+
const headers = {};
|
|
37
|
+
response.headers.forEach((value, name) => {
|
|
38
|
+
headers[name.toLowerCase()] = value;
|
|
39
|
+
});
|
|
40
|
+
return Object.freeze({
|
|
41
|
+
status: response.status,
|
|
42
|
+
headers: normalizeClientHeaders(headers),
|
|
43
|
+
body: response.body,
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/transport/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAS7D,SAAS,aAAa,CAAC,QAA+B;IACpD,MAAM,SAAS,GAAG,QAAQ,IAAI,UAAU,CAAC,KAAK,CAAC;IAC/C,IAAI,OAAO,SAAS,KAAK,UAAU,EAAE,CAAC;QACpC,MAAM,IAAI,kBAAkB,CAAC,wEAAwE,CAAC,CAAC;IACzG,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,QAAoB;IACvD,MAAM,KAAK,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IAEtC,OAAO,KAAK,EAAE,OAAsB,EAA2B,EAAE;QAC/D,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACzC,MAAM,IAAI,kBAAkB,CAAC,0DAA0D,CAAC,CAAC;QAC3F,CAAC;QACD,MAAM,IAAI,GAAyB;YACjC,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,QAAQ,EAAE,QAAQ;YAClB,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC;YAC7D,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;YACnE,GAAG,CAAC,OAAO,CAAC,IAAI,YAAY,cAAc,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACtE,CAAC;QAEF,IAAI,QAAkB,CAAC;QACvB,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC5C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI;gBAAE,MAAM,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;YAClE,MAAM,IAAI,cAAc,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAC7C,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,IAAI,CAAC,IAAI,QAAQ,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;YAC/D,MAAM,IAAI,cAAc,CAAC,SAAS,EAAE,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC,CAAC;QACzG,CAAC;QAED,MAAM,OAAO,GAA2B,EAAE,CAAC;QAC3C,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;YACvC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,GAAG,KAAK,CAAC;QACtC,CAAC,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,MAAM,CAAC;YACnB,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,OAAO,EAAE,sBAAsB,CAAC,OAAO,CAAC;YACxC,IAAI,EAAE,QAAQ,CAAC,IAAI;SACpB,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
export type ClientHeaders = Readonly<Record<string, string>>;
|
|
2
|
+
export type ClientBytes = Uint8Array<ArrayBuffer>;
|
|
3
|
+
export type ClientBody = string | ClientBytes | ReadableStream<ClientBytes>;
|
|
4
|
+
export interface ClientRequest {
|
|
5
|
+
readonly method: string;
|
|
6
|
+
readonly url: string;
|
|
7
|
+
readonly headers: ClientHeaders;
|
|
8
|
+
readonly body?: ClientBody;
|
|
9
|
+
readonly signal?: AbortSignal;
|
|
10
|
+
}
|
|
11
|
+
export interface ClientResponse {
|
|
12
|
+
readonly status: number;
|
|
13
|
+
readonly headers: ClientHeaders;
|
|
14
|
+
readonly body: ReadableStream<ClientBytes> | null;
|
|
15
|
+
}
|
|
16
|
+
export type ClientTransport = (request: ClientRequest) => Promise<ClientResponse>;
|
|
17
|
+
export type ClientSecurityRequirement = Readonly<Record<string, readonly string[]>>;
|
|
18
|
+
export type ClientSecurityScheme = {
|
|
19
|
+
readonly type: 'http';
|
|
20
|
+
readonly scheme: 'bearer' | 'basic';
|
|
21
|
+
} | {
|
|
22
|
+
readonly type: 'apiKey';
|
|
23
|
+
readonly in: 'header' | 'query' | 'cookie';
|
|
24
|
+
readonly name: string;
|
|
25
|
+
} | {
|
|
26
|
+
readonly type: 'mutualTLS';
|
|
27
|
+
} | {
|
|
28
|
+
readonly type: 'oauth2';
|
|
29
|
+
} | {
|
|
30
|
+
readonly type: 'openIdConnect';
|
|
31
|
+
};
|
|
32
|
+
export interface AuthenticationContext {
|
|
33
|
+
readonly operationId: string;
|
|
34
|
+
readonly requirements: readonly ClientSecurityRequirement[];
|
|
35
|
+
readonly schemes: Readonly<Record<string, ClientSecurityScheme>>;
|
|
36
|
+
readonly version?: string;
|
|
37
|
+
readonly signal?: AbortSignal;
|
|
38
|
+
}
|
|
39
|
+
export interface AuthenticationPatch {
|
|
40
|
+
readonly requirement: number;
|
|
41
|
+
readonly headers?: ClientHeaders;
|
|
42
|
+
readonly query?: Readonly<Record<string, string | readonly string[]>>;
|
|
43
|
+
readonly cookies?: Readonly<Record<string, string>>;
|
|
44
|
+
}
|
|
45
|
+
export type AuthenticationProvider = (context: AuthenticationContext) => AuthenticationPatch | Promise<AuthenticationPatch>;
|
|
46
|
+
export interface ClientOptions {
|
|
47
|
+
readonly baseUrl: string | URL;
|
|
48
|
+
readonly transport?: ClientTransport;
|
|
49
|
+
readonly authentication?: AuthenticationProvider;
|
|
50
|
+
readonly headers?: ClientHeaders;
|
|
51
|
+
readonly maxResponseBytes?: number;
|
|
52
|
+
readonly maxErrorBodyBytes?: number;
|
|
53
|
+
}
|
|
54
|
+
export interface CallOptions {
|
|
55
|
+
readonly signal?: AbortSignal;
|
|
56
|
+
readonly timeoutMs?: number;
|
|
57
|
+
readonly authentication?: AuthenticationProvider;
|
|
58
|
+
}
|
|
59
|
+
export interface ClientQueryPair {
|
|
60
|
+
readonly name: string;
|
|
61
|
+
readonly value: string;
|
|
62
|
+
}
|
|
63
|
+
export interface PreparedClientRequest {
|
|
64
|
+
readonly path: string;
|
|
65
|
+
readonly query: readonly ClientQueryPair[];
|
|
66
|
+
readonly headers: ClientHeaders;
|
|
67
|
+
readonly cookies: readonly ClientQueryPair[];
|
|
68
|
+
readonly body?: ClientBody;
|
|
69
|
+
}
|
|
70
|
+
export type ClientVersionPlan = {
|
|
71
|
+
readonly kind: 'none';
|
|
72
|
+
} | {
|
|
73
|
+
readonly kind: 'header' | 'media-type';
|
|
74
|
+
readonly values: readonly string[];
|
|
75
|
+
readonly default: string;
|
|
76
|
+
};
|
|
77
|
+
export interface ValidationIssue {
|
|
78
|
+
readonly path: string;
|
|
79
|
+
readonly message: string;
|
|
80
|
+
}
|
|
81
|
+
export type DecodeResult<T> = {
|
|
82
|
+
readonly ok: true;
|
|
83
|
+
readonly value: T;
|
|
84
|
+
} | {
|
|
85
|
+
readonly ok: false;
|
|
86
|
+
readonly issues: readonly ValidationIssue[];
|
|
87
|
+
};
|
|
88
|
+
export interface ClientResponseBody {
|
|
89
|
+
empty(): Promise<void>;
|
|
90
|
+
json<T>(mediaType: string, decode: (wire: unknown) => DecodeResult<T>): Promise<T>;
|
|
91
|
+
text(mediaType: string): Promise<string>;
|
|
92
|
+
bytes(mediaType: string): Promise<ClientBytes>;
|
|
93
|
+
stream(mediaType: string): ReadableStream<ClientBytes>;
|
|
94
|
+
}
|
|
95
|
+
export interface ClientOperationResponse {
|
|
96
|
+
readonly status: number;
|
|
97
|
+
readonly headers: ClientHeaders;
|
|
98
|
+
readonly body: ClientResponseBody;
|
|
99
|
+
unexpectedStatus(): Promise<never>;
|
|
100
|
+
}
|
|
101
|
+
export interface GeneratedOperation<Input, Result> {
|
|
102
|
+
readonly abi: 1;
|
|
103
|
+
readonly operationId: string;
|
|
104
|
+
readonly method: string;
|
|
105
|
+
readonly security: readonly ClientSecurityRequirement[];
|
|
106
|
+
readonly schemes: Readonly<Record<string, ClientSecurityScheme>>;
|
|
107
|
+
readonly version: ClientVersionPlan;
|
|
108
|
+
prepare(input: Input, version: string | undefined): PreparedClientRequest;
|
|
109
|
+
read(response: ClientOperationResponse, version: string | undefined): Promise<Result>;
|
|
110
|
+
}
|
|
111
|
+
export interface ClientRuntime {
|
|
112
|
+
call<Input, Result>(operation: GeneratedOperation<Input, Result>, input: Input, options?: CallOptions & {
|
|
113
|
+
readonly version?: string;
|
|
114
|
+
}): Promise<Result>;
|
|
115
|
+
}
|
|
116
|
+
//# 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":""}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ClientQueryPair } from '../types.js';
|
|
2
|
+
export type ClientScalar = string | number | bigint | boolean | Date;
|
|
3
|
+
export type ClientBaseUrl = {
|
|
4
|
+
readonly kind: 'absolute';
|
|
5
|
+
readonly origin: string;
|
|
6
|
+
readonly pathname: string;
|
|
7
|
+
} | {
|
|
8
|
+
readonly kind: 'relative';
|
|
9
|
+
readonly pathname: string;
|
|
10
|
+
};
|
|
11
|
+
export declare function normalizeClientBaseUrl(input: string | URL): ClientBaseUrl;
|
|
12
|
+
export declare function stringifyClientScalar(value: ClientScalar): string;
|
|
13
|
+
export declare function encodeClientComponent(value: string): string;
|
|
14
|
+
export declare function substituteClientPath(path: string, name: string, value: ClientScalar): string;
|
|
15
|
+
export declare function serializeClientQuery(query: readonly ClientQueryPair[]): string;
|
|
16
|
+
export declare function resolveClientUrl(baseUrl: string | URL | ClientBaseUrl, path: string, query?: readonly ClientQueryPair[]): string;
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/url/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;AAErE,MAAM,MAAM,aAAa,GACrB;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACjF;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAa7D,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,aAAa,CA+BzE;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CASjE;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAK3D;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,MAAM,CAc5F;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,SAAS,eAAe,EAAE,GAAG,MAAM,CAS9E;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,GAAG,GAAG,GAAG,aAAa,EACrC,IAAI,EAAE,MAAM,EACZ,KAAK,GAAE,SAAS,eAAe,EAAO,GACrC,MAAM,CAUR"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { ClientRequestError } from '../errors/index.js';
|
|
2
|
+
const CONTROL = /[\0\r\n]/;
|
|
3
|
+
function requestError(message, cause) {
|
|
4
|
+
return new ClientRequestError(message, cause === undefined ? {} : { cause });
|
|
5
|
+
}
|
|
6
|
+
function prefixPath(pathname) {
|
|
7
|
+
const withoutTrailing = pathname.replace(/\/+$/u, '');
|
|
8
|
+
return withoutTrailing.length === 0 ? '/' : withoutTrailing;
|
|
9
|
+
}
|
|
10
|
+
export function normalizeClientBaseUrl(input) {
|
|
11
|
+
if (input instanceof URL) {
|
|
12
|
+
if (input.protocol !== 'http:' && input.protocol !== 'https:') {
|
|
13
|
+
throw requestError(`Client base URL protocol must be http: or https:, received ${input.protocol}`);
|
|
14
|
+
}
|
|
15
|
+
if (input.username.length > 0 || input.password.length > 0) {
|
|
16
|
+
throw requestError('Client base URL must not contain credentials');
|
|
17
|
+
}
|
|
18
|
+
if (input.search.length > 0 || input.hash.length > 0) {
|
|
19
|
+
throw requestError('Client base URL must not contain a query or fragment');
|
|
20
|
+
}
|
|
21
|
+
return Object.freeze({ kind: 'absolute', origin: input.origin, pathname: prefixPath(input.pathname) });
|
|
22
|
+
}
|
|
23
|
+
if (typeof input !== 'string' || input.length === 0 || CONTROL.test(input)) {
|
|
24
|
+
throw requestError('Client base URL must be a non-empty absolute or origin-relative URL');
|
|
25
|
+
}
|
|
26
|
+
if (input.startsWith('/') && !input.startsWith('//')) {
|
|
27
|
+
if (input.includes('?') || input.includes('#')) {
|
|
28
|
+
throw requestError('Client base URL must not contain a query or fragment');
|
|
29
|
+
}
|
|
30
|
+
return Object.freeze({ kind: 'relative', pathname: prefixPath(input) });
|
|
31
|
+
}
|
|
32
|
+
let absolute;
|
|
33
|
+
try {
|
|
34
|
+
absolute = new URL(input);
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
throw requestError('Client base URL must be absolute or begin with /', error);
|
|
38
|
+
}
|
|
39
|
+
return normalizeClientBaseUrl(absolute);
|
|
40
|
+
}
|
|
41
|
+
export function stringifyClientScalar(value) {
|
|
42
|
+
if (typeof value === 'string')
|
|
43
|
+
return value;
|
|
44
|
+
if (typeof value === 'number') {
|
|
45
|
+
if (!Number.isFinite(value))
|
|
46
|
+
throw requestError('Client URL scalar number must be finite');
|
|
47
|
+
return String(value);
|
|
48
|
+
}
|
|
49
|
+
if (typeof value === 'bigint' || typeof value === 'boolean')
|
|
50
|
+
return String(value);
|
|
51
|
+
if (Number.isNaN(value.getTime()))
|
|
52
|
+
throw requestError('Client URL scalar Date must be valid');
|
|
53
|
+
return value.toISOString();
|
|
54
|
+
}
|
|
55
|
+
export function encodeClientComponent(value) {
|
|
56
|
+
return encodeURIComponent(value).replace(/[!'()*]/gu, character => {
|
|
57
|
+
const code = character.codePointAt(0);
|
|
58
|
+
return code === undefined ? '' : `%${code.toString(16).toUpperCase()}`;
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
export function substituteClientPath(path, name, value) {
|
|
62
|
+
if (!path.startsWith('/') || path.includes('?') || path.includes('#') || CONTROL.test(path)) {
|
|
63
|
+
throw requestError('Client operation path must begin with / and contain no query, fragment, or controls');
|
|
64
|
+
}
|
|
65
|
+
const slot = `:${name}`;
|
|
66
|
+
const segments = path.split('/');
|
|
67
|
+
const indexes = segments.flatMap((segment, index) => (segment === slot ? [index] : []));
|
|
68
|
+
if (indexes.length !== 1) {
|
|
69
|
+
throw requestError(`Client operation path must contain exactly one ${slot} segment`);
|
|
70
|
+
}
|
|
71
|
+
const index = indexes[0];
|
|
72
|
+
if (index === undefined)
|
|
73
|
+
throw requestError(`Client operation path is missing ${slot}`);
|
|
74
|
+
segments[index] = encodeClientComponent(stringifyClientScalar(value));
|
|
75
|
+
return segments.join('/');
|
|
76
|
+
}
|
|
77
|
+
export function serializeClientQuery(query) {
|
|
78
|
+
return query
|
|
79
|
+
.map(pair => {
|
|
80
|
+
if (typeof pair.name !== 'string' || typeof pair.value !== 'string') {
|
|
81
|
+
throw requestError('Client query pairs must contain string names and values');
|
|
82
|
+
}
|
|
83
|
+
return `${encodeClientComponent(pair.name)}=${encodeClientComponent(pair.value)}`;
|
|
84
|
+
})
|
|
85
|
+
.join('&');
|
|
86
|
+
}
|
|
87
|
+
export function resolveClientUrl(baseUrl, path, query = []) {
|
|
88
|
+
if (!path.startsWith('/') || path.includes('?') || path.includes('#') || CONTROL.test(path)) {
|
|
89
|
+
throw requestError('Prepared client path must begin with / and contain no query, fragment, or controls');
|
|
90
|
+
}
|
|
91
|
+
const base = typeof baseUrl === 'string' || baseUrl instanceof URL ? normalizeClientBaseUrl(baseUrl) : baseUrl;
|
|
92
|
+
const prefix = base.pathname === '/' ? '' : base.pathname;
|
|
93
|
+
const pathname = `${prefix}${path}` || '/';
|
|
94
|
+
const serialized = serializeClientQuery(query);
|
|
95
|
+
const result = serialized.length === 0 ? pathname : `${pathname}?${serialized}`;
|
|
96
|
+
return base.kind === 'absolute' ? `${base.origin}${result}` : result;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/url/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zmdb/client",
|
|
3
|
+
"version": "1.0.0-beta.1",
|
|
4
|
+
"description": "Dependency-free HTTP client runtime for generated and manually declared zmdb operations.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"client",
|
|
7
|
+
"fetch",
|
|
8
|
+
"http",
|
|
9
|
+
"typescript",
|
|
10
|
+
"zmdb"
|
|
11
|
+
],
|
|
12
|
+
"homepage": "https://github.com/ambasta/zmdb#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/ambasta/zmdb/issues"
|
|
15
|
+
},
|
|
16
|
+
"license": "GPL-3.0-or-later",
|
|
17
|
+
"author": "zmdb contributors",
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/ambasta/zmdb.git",
|
|
21
|
+
"directory": "packages/client"
|
|
22
|
+
},
|
|
23
|
+
"type": "module",
|
|
24
|
+
"sideEffects": false,
|
|
25
|
+
"exports": {
|
|
26
|
+
".": {
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"import": "./dist/index.js"
|
|
29
|
+
},
|
|
30
|
+
"./body": {
|
|
31
|
+
"types": "./dist/body/index.d.ts",
|
|
32
|
+
"import": "./dist/body/index.js"
|
|
33
|
+
},
|
|
34
|
+
"./errors": {
|
|
35
|
+
"types": "./dist/errors/index.d.ts",
|
|
36
|
+
"import": "./dist/errors/index.js"
|
|
37
|
+
},
|
|
38
|
+
"./headers": {
|
|
39
|
+
"types": "./dist/headers/index.d.ts",
|
|
40
|
+
"import": "./dist/headers/index.js"
|
|
41
|
+
},
|
|
42
|
+
"./testing": {
|
|
43
|
+
"types": "./dist/testing/index.d.ts",
|
|
44
|
+
"import": "./dist/testing/index.js"
|
|
45
|
+
},
|
|
46
|
+
"./transport": {
|
|
47
|
+
"types": "./dist/transport/index.d.ts",
|
|
48
|
+
"import": "./dist/transport/index.js"
|
|
49
|
+
},
|
|
50
|
+
"./url": {
|
|
51
|
+
"types": "./dist/url/index.d.ts",
|
|
52
|
+
"import": "./dist/url/index.js"
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"publishConfig": {
|
|
56
|
+
"access": "public",
|
|
57
|
+
"tag": "beta"
|
|
58
|
+
},
|
|
59
|
+
"scripts": {
|
|
60
|
+
"build": "node ../../scripts/build-package.mjs",
|
|
61
|
+
"test": "vitest run"
|
|
62
|
+
},
|
|
63
|
+
"engines": {
|
|
64
|
+
"node": ">=26"
|
|
65
|
+
},
|
|
66
|
+
"main": "./dist/index.js",
|
|
67
|
+
"types": "./dist/index.d.ts"
|
|
68
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { ClientRequestError } from '../errors/index.js';
|
|
2
|
+
import type { ClientBody, ClientBytes } from '../types.js';
|
|
3
|
+
|
|
4
|
+
export const DEFAULT_MAX_RESPONSE_BYTES = 8 * 1024 * 1024;
|
|
5
|
+
export const DEFAULT_MAX_ERROR_BODY_BYTES = 8 * 1024;
|
|
6
|
+
|
|
7
|
+
export type ClientBodyKind = 'json' | 'text' | 'bytes' | 'stream' | 'empty';
|
|
8
|
+
|
|
9
|
+
const TEXT_BODY_KIND: ClientBodyKind = 'text';
|
|
10
|
+
|
|
11
|
+
function isClientBytes(value: unknown): value is ClientBytes {
|
|
12
|
+
return value instanceof Uint8Array && value.buffer instanceof ArrayBuffer;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function prepareClientBody(kind: ClientBodyKind, value: unknown): ClientBody | undefined {
|
|
16
|
+
if (kind === 'empty') {
|
|
17
|
+
if (value !== undefined) throw new ClientRequestError('An empty request body must be undefined');
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
if (kind === TEXT_BODY_KIND) {
|
|
21
|
+
if (typeof value !== 'string') throw new ClientRequestError('A text request body must be a string');
|
|
22
|
+
return value;
|
|
23
|
+
}
|
|
24
|
+
if (kind === 'bytes') {
|
|
25
|
+
if (!isClientBytes(value)) {
|
|
26
|
+
throw new ClientRequestError('A bytes request body must be a Uint8Array');
|
|
27
|
+
}
|
|
28
|
+
return value;
|
|
29
|
+
}
|
|
30
|
+
if (kind === 'stream') {
|
|
31
|
+
if (!(value instanceof ReadableStream)) {
|
|
32
|
+
throw new ClientRequestError('A stream request body must be a ReadableStream');
|
|
33
|
+
}
|
|
34
|
+
return value;
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
const serialized = JSON.stringify(value, (_key, item) => {
|
|
38
|
+
if (typeof item === 'number' && !Number.isFinite(item)) {
|
|
39
|
+
throw new ClientRequestError('A JSON request body must not contain a non-finite number');
|
|
40
|
+
}
|
|
41
|
+
return item;
|
|
42
|
+
});
|
|
43
|
+
if (serialized === undefined) {
|
|
44
|
+
throw new ClientRequestError('A JSON request body must have a serialisable top-level value');
|
|
45
|
+
}
|
|
46
|
+
return serialized;
|
|
47
|
+
} catch (error) {
|
|
48
|
+
if (error instanceof ClientRequestError) throw error;
|
|
49
|
+
throw new ClientRequestError('A JSON request body could not be serialised', { cause: error });
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function assertPositiveByteLimit(value: number, option: string): number {
|
|
54
|
+
if (!Number.isSafeInteger(value) || value <= 0) {
|
|
55
|
+
throw new ClientRequestError(`${option} must be a positive safe integer`);
|
|
56
|
+
}
|
|
57
|
+
return value;
|
|
58
|
+
}
|