@tstdl/base 0.90.68 → 0.90.70
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/api/client/client.d.ts +6 -5
- package/api/client/client.js +19 -1
- package/api/types.d.ts +5 -1
- package/api/types.js +2 -1
- package/dom/files-select.d.ts +7 -0
- package/dom/files-select.js +19 -0
- package/dom/index.d.ts +1 -0
- package/dom/index.js +1 -0
- package/file/index.d.ts +1 -0
- package/file/index.js +1 -0
- package/http/client/http-client-request.d.ts +16 -21
- package/http/client/http-client-request.js +9 -9
- package/http/client/http-client.js +4 -4
- package/package.json +3 -2
package/api/client/client.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import {
|
|
3
|
-
import type
|
|
4
|
-
import type { ApiClientImplementation, ApiDefinition, ApiEndpointDefinition } from '../types.js';
|
|
1
|
+
import { HttpClient, type HttpClientOptions } from '../../http/client/index.js';
|
|
2
|
+
import { type Resolvable } from '../../injector/interfaces.js';
|
|
3
|
+
import { type ApiClientImplementation, type ApiDefinition, type ApiEndpointDefinition } from '../types.js';
|
|
5
4
|
export type ApiClient<T extends ApiDefinition> = new (httpClientOrOptions?: HttpClient | HttpClientOptions) => ApiClientImplementation<T> & Resolvable<HttpClient | HttpClientOptions>;
|
|
6
5
|
export type ClientOptions = {
|
|
7
6
|
/**
|
|
8
|
-
*
|
|
7
|
+
* Url prefix
|
|
9
8
|
* @default `api/`
|
|
10
9
|
*/
|
|
11
10
|
prefix?: string;
|
|
@@ -17,3 +16,5 @@ export type ApiClientHttpRequestContext = {
|
|
|
17
16
|
export declare const httpClientSymbol: unique symbol;
|
|
18
17
|
export declare const apiDefinitionSymbol: unique symbol;
|
|
19
18
|
export declare function compileClient<T extends ApiDefinition>(definition: T, options?: ClientOptions): ApiClient<T>;
|
|
19
|
+
export declare function getHttpClientOfApiClient(apiClient: any): HttpClient;
|
|
20
|
+
export declare function getApiDefinitionOfApiClient(apiClient: any): ApiDefinition;
|
package/api/client/client.js
CHANGED
|
@@ -10,6 +10,7 @@ import { objectEntries } from '../../utils/object/object.js';
|
|
|
10
10
|
import { toTitleCase } from '../../utils/string/title-case.js';
|
|
11
11
|
import { isArray, isBlob, isDefined, isObject, isReadableStream, isString, isUint8Array, isUndefined } from '../../utils/type-guards.js';
|
|
12
12
|
import { buildUrl } from '../../utils/url-builder.js';
|
|
13
|
+
import { resolveValueOrProvider } from '../../utils/value-or-provider.js';
|
|
13
14
|
import { normalizedApiDefinitionEndpointsEntries } from '../types.js';
|
|
14
15
|
import { getFullApiEndpointResource } from '../utils.js';
|
|
15
16
|
export const httpClientSymbol = Symbol('ApiTransport');
|
|
@@ -27,6 +28,17 @@ export function compileClient(definition, options = {}) {
|
|
|
27
28
|
this[httpClientSymbol] = (httpClientOrOptions instanceof HttpClient) ? httpClientOrOptions : inject(HttpClient, httpClientOrOptions);
|
|
28
29
|
this[apiDefinitionSymbol] = definition;
|
|
29
30
|
}
|
|
31
|
+
getEndpointResource(endpoint, parameters) {
|
|
32
|
+
const resource = getFullApiEndpointResource({ api: definition, endpoint: resolveValueOrProvider(definition.endpoints[endpoint]), defaultPrefix: options.prefix });
|
|
33
|
+
if (isUndefined(parameters)) {
|
|
34
|
+
return resource;
|
|
35
|
+
}
|
|
36
|
+
return buildUrl(resource, parameters).parsedUrl;
|
|
37
|
+
}
|
|
38
|
+
getEndpointUrl(endpoint, parameters) {
|
|
39
|
+
const url = this.getEndpointResource(endpoint, parameters);
|
|
40
|
+
return new URL(url, this[httpClientSymbol].options.baseUrl);
|
|
41
|
+
}
|
|
30
42
|
}
|
|
31
43
|
}[apiName];
|
|
32
44
|
Injector.registerSingleton(api, {
|
|
@@ -40,7 +52,7 @@ export function compileClient(definition, options = {}) {
|
|
|
40
52
|
const methods = isArray(endpoint.method) ? endpoint.method : [endpoint.method ?? 'GET'];
|
|
41
53
|
const resource = getFullApiEndpointResource({ api: definition, endpoint, defaultPrefix: options.prefix });
|
|
42
54
|
const hasGet = methods.includes('GET');
|
|
43
|
-
const fallbackMethod = methods.
|
|
55
|
+
const fallbackMethod = methods.find((method) => method != 'GET') ?? 'GET';
|
|
44
56
|
const apiEndpointFunction = {
|
|
45
57
|
async [name](parameters, requestBody) {
|
|
46
58
|
const context = { endpoint };
|
|
@@ -119,3 +131,9 @@ function getServerSentEvents(baseUrl, resource, endpoint, parameters) {
|
|
|
119
131
|
}
|
|
120
132
|
return new ServerSentEvents(url.toString(), { withCredentials: endpoint.credentials });
|
|
121
133
|
}
|
|
134
|
+
export function getHttpClientOfApiClient(apiClient) {
|
|
135
|
+
return apiClient[httpClientSymbol];
|
|
136
|
+
}
|
|
137
|
+
export function getApiDefinitionOfApiClient(apiClient) {
|
|
138
|
+
return apiClient[apiDefinitionSymbol];
|
|
139
|
+
}
|
package/api/types.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { SchemaOutput, SchemaTestable } from '../schema/index.js';
|
|
|
4
4
|
import type { ServerSentEventsSource } from '../sse/server-sent-events-source.js';
|
|
5
5
|
import type { ServerSentEvents } from '../sse/server-sent-events.js';
|
|
6
6
|
import type { NonUndefinable, OneOrMany, Record, ReturnTypeOrT } from '../types.js';
|
|
7
|
+
import { type ValueOrProvider } from '../utils/value-or-provider.js';
|
|
7
8
|
import type { ApiGatewayMiddlewareContext } from './server/index.js';
|
|
8
9
|
export type ApiRegistrationOptions = {
|
|
9
10
|
name?: string;
|
|
@@ -69,7 +70,7 @@ export type ApiEndpointDefinition = {
|
|
|
69
70
|
credentials?: boolean;
|
|
70
71
|
cors?: ApiEndpointDefinitionCors;
|
|
71
72
|
};
|
|
72
|
-
export type ApiEndpointsDefinition = Record<string, ApiEndpointDefinition
|
|
73
|
+
export type ApiEndpointsDefinition = Record<string, ValueOrProvider<ApiEndpointDefinition>>;
|
|
73
74
|
export type ApiDefinition<Resource extends string = string, Endpoints extends ApiEndpointsDefinition = ApiEndpointsDefinition> = {
|
|
74
75
|
/**
|
|
75
76
|
* Default root resource for endpoints.
|
|
@@ -112,6 +113,9 @@ export type ApiController<T extends ApiDefinition = any> = {
|
|
|
112
113
|
};
|
|
113
114
|
export type ApiClientImplementation<T extends ApiDefinition = any> = {
|
|
114
115
|
[P in ApiEndpointKeys<T>]: ApiEndpointClientImplementation<T, P>;
|
|
116
|
+
} & {
|
|
117
|
+
getEndpointResource<E extends ApiEndpointKeys<T>>(endpoint: E, parameters?: ApiParameters<T, E>): string;
|
|
118
|
+
getEndpointUrl<E extends ApiEndpointKeys<T>>(endpoint: E, parameters?: ApiParameters<T, E>): string;
|
|
115
119
|
};
|
|
116
120
|
export declare function defineApi<T extends ApiDefinition>(definition: T): T;
|
|
117
121
|
export declare function resolveApiEndpointDataProvider<T>(request: HttpServerRequest, context: ApiGatewayMiddlewareContext, provider: ApiEndpointDataProvider<T>): Promise<T>;
|
package/api/types.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { objectEntries } from '../utils/object/object.js';
|
|
2
2
|
import { isFunction } from '../utils/type-guards.js';
|
|
3
|
+
import { resolveValueOrProvider } from '../utils/value-or-provider.js';
|
|
3
4
|
export function defineApi(definition) {
|
|
4
5
|
return definition;
|
|
5
6
|
}
|
|
@@ -14,5 +15,5 @@ export function normalizedApiDefinitionEndpoints(apiDefinitionEndpoints) {
|
|
|
14
15
|
return Object.fromEntries(entries);
|
|
15
16
|
}
|
|
16
17
|
export function normalizedApiDefinitionEndpointsEntries(apiDefinition) {
|
|
17
|
-
return objectEntries(apiDefinition).map(([key, def]) => [key,
|
|
18
|
+
return objectEntries(apiDefinition).map(([key, def]) => [key, resolveValueOrProvider(def)]);
|
|
18
19
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { OneOrMany } from '../types.js';
|
|
2
|
+
export type FileSelectDialogOptions = {
|
|
3
|
+
accept?: OneOrMany<string>;
|
|
4
|
+
multiple?: boolean;
|
|
5
|
+
capture?: string;
|
|
6
|
+
};
|
|
7
|
+
export declare function openFileSelectDialog({ accept, multiple, capture }?: FileSelectDialogOptions): Promise<File[] | null>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { isDefined, isString } from '../utils/type-guards.js';
|
|
2
|
+
export async function openFileSelectDialog({ accept, multiple, capture } = {}) {
|
|
3
|
+
const fileInput = document.createElement('input');
|
|
4
|
+
fileInput.type = 'file';
|
|
5
|
+
if (isDefined(accept)) {
|
|
6
|
+
fileInput.accept = isString(accept) ? accept : accept.join(',');
|
|
7
|
+
}
|
|
8
|
+
if (isDefined(multiple)) {
|
|
9
|
+
fileInput.multiple = multiple;
|
|
10
|
+
}
|
|
11
|
+
if (isDefined(capture)) {
|
|
12
|
+
fileInput.capture = capture;
|
|
13
|
+
}
|
|
14
|
+
fileInput.click();
|
|
15
|
+
return new Promise((resolve) => {
|
|
16
|
+
fileInput.addEventListener('change', () => resolve(Array.from(fileInput.files ?? [])));
|
|
17
|
+
fileInput.addEventListener('cancel', () => resolve(null));
|
|
18
|
+
});
|
|
19
|
+
}
|
package/dom/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './files-select.js';
|
package/dom/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './files-select.js';
|
package/file/index.d.ts
CHANGED
package/file/index.js
CHANGED
|
@@ -1,17 +1,12 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import type
|
|
3
|
-
import { dispose } from '../../disposable/index.js';
|
|
1
|
+
import { type CancellationSignal } from '../../cancellation/index.js';
|
|
2
|
+
import { dispose, type Disposable } from '../../disposable/index.js';
|
|
4
3
|
import type { Record, TypedOmit, UndefinableJson, UndefinableJsonObject } from '../../types.js';
|
|
5
|
-
import type
|
|
6
|
-
import {
|
|
7
|
-
import type
|
|
8
|
-
import {
|
|
9
|
-
import type { HttpQueryObject } from '../http-query.js';
|
|
10
|
-
import { HttpQuery } from '../http-query.js';
|
|
11
|
-
import type { HttpUrlParametersObject } from '../http-url-parameters.js';
|
|
12
|
-
import { HttpUrlParameters } from '../http-url-parameters.js';
|
|
4
|
+
import { HttpForm, type HttpFormObject } from '../http-form.js';
|
|
5
|
+
import { HttpHeaders, type HttpHeadersObject } from '../http-headers.js';
|
|
6
|
+
import { HttpQuery, type HttpQueryObject } from '../http-query.js';
|
|
7
|
+
import { HttpUrlParameters, type HttpUrlParametersObject } from '../http-url-parameters.js';
|
|
13
8
|
import type { HttpMethod } from '../types.js';
|
|
14
|
-
/**
|
|
9
|
+
/** Only one type at a time is supported. If multiple are set, behaviour is undefined */
|
|
15
10
|
export type HttpRequestBody = {
|
|
16
11
|
text?: string;
|
|
17
12
|
json?: UndefinableJson;
|
|
@@ -54,7 +49,7 @@ export declare class HttpClientRequest implements Disposable {
|
|
|
54
49
|
method: HttpMethod;
|
|
55
50
|
headers: HttpHeaders;
|
|
56
51
|
/**
|
|
57
|
-
*
|
|
52
|
+
* Automatically maps parameters to `urlParameters`, `query` and `body`
|
|
58
53
|
* depending on whether the `url` has parameters specified, the request `method`
|
|
59
54
|
* and if there is already a `body` or not
|
|
60
55
|
* @see mapParameters
|
|
@@ -63,13 +58,13 @@ export declare class HttpClientRequest implements Disposable {
|
|
|
63
58
|
* @see mapParametersToBody
|
|
64
59
|
*/
|
|
65
60
|
parameters: UndefinableJsonObject | undefined;
|
|
66
|
-
/**
|
|
61
|
+
/** If false, disable parameters mapping completely */
|
|
67
62
|
mapParameters: boolean;
|
|
68
63
|
mapParametersToUrl: boolean;
|
|
69
64
|
mapParametersToQuery: boolean;
|
|
70
65
|
mapParametersToBody: boolean;
|
|
71
66
|
/**
|
|
72
|
-
*
|
|
67
|
+
* Parameters for url
|
|
73
68
|
* @example
|
|
74
69
|
* {
|
|
75
70
|
* url: 'http://domain.tld/users/:userId',
|
|
@@ -79,7 +74,7 @@ export declare class HttpClientRequest implements Disposable {
|
|
|
79
74
|
*/
|
|
80
75
|
urlParameters: HttpUrlParameters;
|
|
81
76
|
/**
|
|
82
|
-
*
|
|
77
|
+
* Separator for url parameter array
|
|
83
78
|
* @default ','
|
|
84
79
|
* @example
|
|
85
80
|
* {
|
|
@@ -91,7 +86,7 @@ export declare class HttpClientRequest implements Disposable {
|
|
|
91
86
|
*/
|
|
92
87
|
urlParametersSeparator: string;
|
|
93
88
|
/**
|
|
94
|
-
*
|
|
89
|
+
* Url query
|
|
95
90
|
* @example
|
|
96
91
|
* {
|
|
97
92
|
* url: 'http://domain.tld/search',
|
|
@@ -104,25 +99,25 @@ export declare class HttpClientRequest implements Disposable {
|
|
|
104
99
|
authorization: HttpRequestAuthorization | undefined;
|
|
105
100
|
body: HttpRequestBody | undefined;
|
|
106
101
|
/**
|
|
107
|
-
*
|
|
102
|
+
* Request timeout in milliseconds
|
|
108
103
|
* @default 30000
|
|
109
104
|
*/
|
|
110
105
|
timeout: number;
|
|
111
106
|
throwOnNon200: boolean;
|
|
112
107
|
/**
|
|
113
|
-
*
|
|
108
|
+
* Can be used to store data for middleware etc.
|
|
114
109
|
*
|
|
115
110
|
* will not be used for actual request
|
|
116
111
|
*/
|
|
117
112
|
context: Record<string>;
|
|
118
113
|
/**
|
|
119
|
-
*
|
|
114
|
+
* Can be used to cancel the request. Throws HttpError
|
|
120
115
|
*/
|
|
121
116
|
get abortSignal(): CancellationSignal;
|
|
122
117
|
constructor(url: string, method?: HttpMethod, options?: HttpClientRequestOptions);
|
|
123
118
|
constructor(requestObject: HttpClientRequestObject);
|
|
124
119
|
[dispose](): void;
|
|
125
|
-
/**
|
|
120
|
+
/** Abort the request */
|
|
126
121
|
abort(): void;
|
|
127
122
|
clone(): HttpClientRequest;
|
|
128
123
|
asObject(): HttpClientRequestObject;
|
|
@@ -12,7 +12,7 @@ export class HttpClientRequest {
|
|
|
12
12
|
method;
|
|
13
13
|
headers;
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
15
|
+
* Automatically maps parameters to `urlParameters`, `query` and `body`
|
|
16
16
|
* depending on whether the `url` has parameters specified, the request `method`
|
|
17
17
|
* and if there is already a `body` or not
|
|
18
18
|
* @see mapParameters
|
|
@@ -21,13 +21,13 @@ export class HttpClientRequest {
|
|
|
21
21
|
* @see mapParametersToBody
|
|
22
22
|
*/
|
|
23
23
|
parameters;
|
|
24
|
-
/**
|
|
24
|
+
/** If false, disable parameters mapping completely */
|
|
25
25
|
mapParameters;
|
|
26
26
|
mapParametersToUrl;
|
|
27
27
|
mapParametersToQuery;
|
|
28
28
|
mapParametersToBody;
|
|
29
29
|
/**
|
|
30
|
-
*
|
|
30
|
+
* Parameters for url
|
|
31
31
|
* @example
|
|
32
32
|
* {
|
|
33
33
|
* url: 'http://domain.tld/users/:userId',
|
|
@@ -37,7 +37,7 @@ export class HttpClientRequest {
|
|
|
37
37
|
*/
|
|
38
38
|
urlParameters;
|
|
39
39
|
/**
|
|
40
|
-
*
|
|
40
|
+
* Separator for url parameter array
|
|
41
41
|
* @default ','
|
|
42
42
|
* @example
|
|
43
43
|
* {
|
|
@@ -49,7 +49,7 @@ export class HttpClientRequest {
|
|
|
49
49
|
*/
|
|
50
50
|
urlParametersSeparator;
|
|
51
51
|
/**
|
|
52
|
-
*
|
|
52
|
+
* Url query
|
|
53
53
|
* @example
|
|
54
54
|
* {
|
|
55
55
|
* url: 'http://domain.tld/search',
|
|
@@ -62,19 +62,19 @@ export class HttpClientRequest {
|
|
|
62
62
|
authorization;
|
|
63
63
|
body;
|
|
64
64
|
/**
|
|
65
|
-
*
|
|
65
|
+
* Request timeout in milliseconds
|
|
66
66
|
* @default 30000
|
|
67
67
|
*/
|
|
68
68
|
timeout;
|
|
69
69
|
throwOnNon200;
|
|
70
70
|
/**
|
|
71
|
-
*
|
|
71
|
+
* Can be used to store data for middleware etc.
|
|
72
72
|
*
|
|
73
73
|
* will not be used for actual request
|
|
74
74
|
*/
|
|
75
75
|
context;
|
|
76
76
|
/**
|
|
77
|
-
*
|
|
77
|
+
* Can be used to cancel the request. Throws HttpError
|
|
78
78
|
*/
|
|
79
79
|
get abortSignal() {
|
|
80
80
|
return this.#abortToken.signal;
|
|
@@ -110,7 +110,7 @@ export class HttpClientRequest {
|
|
|
110
110
|
this.#abortToken.set();
|
|
111
111
|
this.#abortToken.complete();
|
|
112
112
|
}
|
|
113
|
-
/**
|
|
113
|
+
/** Abort the request */
|
|
114
114
|
abort() {
|
|
115
115
|
this.#abortToken.set();
|
|
116
116
|
this.#abortToken.complete();
|
|
@@ -272,14 +272,14 @@ function mapParameters(request, baseUrl) {
|
|
|
272
272
|
const filteredParameterEntries = objectEntries(request.parameters ?? {}).filter(([_, value]) => isDefined(value));
|
|
273
273
|
const filteredParameters = Object.fromEntries(filteredParameterEntries);
|
|
274
274
|
let parameterEntries = new Set(filteredParameterEntries);
|
|
275
|
-
if (
|
|
276
|
-
url = new URL(request.url, baseUrl);
|
|
277
|
-
}
|
|
278
|
-
else {
|
|
275
|
+
if (request.mapParametersToUrl) {
|
|
279
276
|
const { parsedUrl, parametersRest } = buildUrl(request.url, filteredParameters, { arraySeparator: request.urlParametersSeparator });
|
|
280
277
|
url = new URL(parsedUrl, baseUrl);
|
|
281
278
|
parameterEntries = new Set(objectEntries(parametersRest));
|
|
282
279
|
}
|
|
280
|
+
else {
|
|
281
|
+
url = new URL(request.url, baseUrl);
|
|
282
|
+
}
|
|
283
283
|
if (request.mapParametersToBody && !isGetOrHead && isUndefined(request.body)) {
|
|
284
284
|
request.body = { json: Object.fromEntries(parameterEntries) };
|
|
285
285
|
parameterEntries.clear();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tstdl/base",
|
|
3
|
-
"version": "0.90.
|
|
3
|
+
"version": "0.90.70",
|
|
4
4
|
"author": "Patrick Hein",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"./decorators": "./decorators/index.js",
|
|
42
42
|
"./disposable": "./disposable/index.js",
|
|
43
43
|
"./distributed-loop": "./distributed-loop/index.js",
|
|
44
|
+
"./dom": "./dom/index.js",
|
|
44
45
|
"./enumerable": "./enumerable/index.js",
|
|
45
46
|
"./errors": "./errors/index.js",
|
|
46
47
|
"./file": "./file/index.js",
|
|
@@ -110,7 +111,7 @@
|
|
|
110
111
|
"luxon": "^3.4",
|
|
111
112
|
"reflect-metadata": "^0.2",
|
|
112
113
|
"rxjs": "^7.8",
|
|
113
|
-
"type-fest": "4.
|
|
114
|
+
"type-fest": "4.16"
|
|
114
115
|
},
|
|
115
116
|
"devDependencies": {
|
|
116
117
|
"@mxssfd/typedoc-theme": "1.1",
|