@cratis/arc 20.1.0 → 20.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Globals.ts +7 -0
- package/ICanBeConfigured.ts +1 -1
- package/UrlHelpers.ts +14 -1
- package/dist/cjs/Globals.d.ts +2 -0
- package/dist/cjs/Globals.d.ts.map +1 -1
- package/dist/cjs/Globals.js +1 -0
- package/dist/cjs/Globals.js.map +1 -1
- package/dist/cjs/ICanBeConfigured.d.ts +1 -1
- package/dist/cjs/ICanBeConfigured.d.ts.map +1 -1
- package/dist/cjs/UrlHelpers.d.ts.map +1 -1
- package/dist/cjs/UrlHelpers.js +11 -1
- package/dist/cjs/UrlHelpers.js.map +1 -1
- package/dist/cjs/identity/IdentityProvider.d.ts +1 -1
- package/dist/cjs/identity/IdentityProvider.d.ts.map +1 -1
- package/dist/cjs/identity/IdentityProvider.js.map +1 -1
- package/dist/cjs/queries/ServerSentEventHubConnection.d.ts.map +1 -1
- package/dist/cjs/queries/ServerSentEventHubConnection.js +4 -2
- package/dist/cjs/queries/ServerSentEventHubConnection.js.map +1 -1
- package/dist/cjs/queries/for_QueryFor/given/TestQueries.d.ts +9 -0
- package/dist/cjs/queries/for_QueryFor/given/TestQueries.d.ts.map +1 -1
- package/dist/cjs/queries/for_QueryFor/given/a_query_for.d.ts +2 -1
- package/dist/cjs/queries/for_QueryFor/given/a_query_for.d.ts.map +1 -1
- package/dist/cjs/queries/for_QueryFor/when_performing/with_enumerable_parameter_descriptor_values.d.ts +2 -0
- package/dist/cjs/queries/for_QueryFor/when_performing/with_enumerable_parameter_descriptor_values.d.ts.map +1 -0
- package/dist/cjs/reflection/ParameterDescriptor.d.ts +2 -1
- package/dist/cjs/reflection/ParameterDescriptor.d.ts.map +1 -1
- package/dist/cjs/reflection/ParameterDescriptor.js +3 -1
- package/dist/cjs/reflection/ParameterDescriptor.js.map +1 -1
- package/dist/esm/Globals.d.ts +2 -0
- package/dist/esm/Globals.d.ts.map +1 -1
- package/dist/esm/Globals.js +1 -0
- package/dist/esm/Globals.js.map +1 -1
- package/dist/esm/ICanBeConfigured.d.ts +1 -1
- package/dist/esm/ICanBeConfigured.d.ts.map +1 -1
- package/dist/esm/UrlHelpers.d.ts.map +1 -1
- package/dist/esm/UrlHelpers.js +11 -1
- package/dist/esm/UrlHelpers.js.map +1 -1
- package/dist/esm/for_UrlHelpers/when_building_query_params/with_array_values.d.ts +2 -0
- package/dist/esm/for_UrlHelpers/when_building_query_params/with_array_values.d.ts.map +1 -0
- package/dist/esm/for_UrlHelpers/when_building_query_params/with_array_values.js +16 -0
- package/dist/esm/for_UrlHelpers/when_building_query_params/with_array_values.js.map +1 -0
- package/dist/esm/for_UrlHelpers/when_building_query_params/with_mixed_array_and_scalar_values.d.ts +2 -0
- package/dist/esm/for_UrlHelpers/when_building_query_params/with_mixed_array_and_scalar_values.d.ts.map +1 -0
- package/dist/esm/for_UrlHelpers/when_building_query_params/with_mixed_array_and_scalar_values.js +17 -0
- package/dist/esm/for_UrlHelpers/when_building_query_params/with_mixed_array_and_scalar_values.js.map +1 -0
- package/dist/esm/for_UrlHelpers/when_replacing_route_parameters/with_array_parameters.d.ts +2 -0
- package/dist/esm/for_UrlHelpers/when_replacing_route_parameters/with_array_parameters.d.ts.map +1 -0
- package/dist/esm/for_UrlHelpers/when_replacing_route_parameters/with_array_parameters.js +17 -0
- package/dist/esm/for_UrlHelpers/when_replacing_route_parameters/with_array_parameters.js.map +1 -0
- package/dist/esm/identity/IdentityProvider.d.ts +1 -1
- package/dist/esm/identity/IdentityProvider.d.ts.map +1 -1
- package/dist/esm/identity/IdentityProvider.js.map +1 -1
- package/dist/esm/queries/ServerSentEventHubConnection.d.ts.map +1 -1
- package/dist/esm/queries/ServerSentEventHubConnection.js +4 -2
- package/dist/esm/queries/ServerSentEventHubConnection.js.map +1 -1
- package/dist/esm/queries/for_QueryFor/given/TestQueries.d.ts +9 -0
- package/dist/esm/queries/for_QueryFor/given/TestQueries.d.ts.map +1 -1
- package/dist/esm/queries/for_QueryFor/given/TestQueries.js +16 -0
- package/dist/esm/queries/for_QueryFor/given/TestQueries.js.map +1 -1
- package/dist/esm/queries/for_QueryFor/given/a_query_for.d.ts +2 -1
- package/dist/esm/queries/for_QueryFor/given/a_query_for.d.ts.map +1 -1
- package/dist/esm/queries/for_QueryFor/given/a_query_for.js +3 -1
- package/dist/esm/queries/for_QueryFor/given/a_query_for.js.map +1 -1
- package/dist/esm/queries/for_QueryFor/when_performing/with_enumerable_parameter_descriptor_values.d.ts +2 -0
- package/dist/esm/queries/for_QueryFor/when_performing/with_enumerable_parameter_descriptor_values.d.ts.map +1 -0
- package/dist/esm/queries/for_QueryFor/when_performing/with_enumerable_parameter_descriptor_values.js +66 -0
- package/dist/esm/queries/for_QueryFor/when_performing/with_enumerable_parameter_descriptor_values.js.map +1 -0
- package/dist/esm/reflection/ParameterDescriptor.d.ts +2 -1
- package/dist/esm/reflection/ParameterDescriptor.d.ts.map +1 -1
- package/dist/esm/reflection/ParameterDescriptor.js +3 -1
- package/dist/esm/reflection/ParameterDescriptor.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/for_UrlHelpers/when_building_query_params/with_array_values.ts +22 -0
- package/for_UrlHelpers/when_building_query_params/with_mixed_array_and_scalar_values.ts +23 -0
- package/for_UrlHelpers/when_replacing_route_parameters/with_array_parameters.ts +23 -0
- package/identity/IdentityProvider.ts +1 -1
- package/package.json +2 -2
- package/queries/ServerSentEventHubConnection.ts +6 -2
- package/queries/for_QueryFor/given/TestQueries.ts +20 -0
- package/queries/for_QueryFor/given/a_query_for.ts +4 -1
- package/queries/for_QueryFor/when_performing/with_enumerable_parameter_descriptor_values.ts +82 -0
- package/reflection/ParameterDescriptor.ts +2 -1
package/Globals.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Copyright (c) Cratis. All rights reserved.
|
|
2
2
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
3
|
|
|
4
|
+
import { GetHttpHeaders } from './GetHttpHeaders';
|
|
4
5
|
import { QueryTransportMethod } from './queries/QueryTransportMethod';
|
|
5
6
|
|
|
6
7
|
export interface IGlobals {
|
|
@@ -23,6 +24,11 @@ export interface IGlobals {
|
|
|
23
24
|
* Defaults to false (use the centralized hub).
|
|
24
25
|
*/
|
|
25
26
|
queryDirectMode: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Callback that returns custom HTTP headers to include in hub transport requests
|
|
29
|
+
* (e.g. SSE subscribe/unsubscribe POST calls).
|
|
30
|
+
*/
|
|
31
|
+
httpHeadersCallback: GetHttpHeaders;
|
|
26
32
|
}
|
|
27
33
|
|
|
28
34
|
export const Globals: IGlobals = {
|
|
@@ -34,4 +40,5 @@ export const Globals: IGlobals = {
|
|
|
34
40
|
queryTransportMethod: QueryTransportMethod.WebSocket,
|
|
35
41
|
queryConnectionCount: 1,
|
|
36
42
|
queryDirectMode: false,
|
|
43
|
+
httpHeadersCallback: () => ({}),
|
|
37
44
|
};
|
package/ICanBeConfigured.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Copyright (c) Cratis. All rights reserved.
|
|
2
2
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
3
|
|
|
4
|
-
import { GetHttpHeaders } from 'GetHttpHeaders';
|
|
4
|
+
import { GetHttpHeaders } from './GetHttpHeaders';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Represents the concept of something that can be configured.
|
package/UrlHelpers.ts
CHANGED
|
@@ -33,6 +33,12 @@ export class UrlHelpers {
|
|
|
33
33
|
const unusedParameters: Partial<T> = { ...parameters };
|
|
34
34
|
|
|
35
35
|
for (const [key, value] of Object.entries(parameters)) {
|
|
36
|
+
// Array values cannot be encoded as a single route segment — leave them as unused so
|
|
37
|
+
// they are serialized as repeated query string parameters (e.g. ?ids=1&ids=2&ids=3).
|
|
38
|
+
if (Array.isArray(value)) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
|
|
36
42
|
const pattern = new RegExp(`\\{${key}\\}`, 'gi');
|
|
37
43
|
const newRoute = result.replace(pattern, encodeURIComponent(String(value)));
|
|
38
44
|
|
|
@@ -47,6 +53,7 @@ export class UrlHelpers {
|
|
|
47
53
|
|
|
48
54
|
/**
|
|
49
55
|
* Builds URLSearchParams from the given parameters and additional query parameters.
|
|
56
|
+
* Array values are serialized as repeated key=value pairs (e.g. ?ids=1&ids=2&ids=3).
|
|
50
57
|
* @param unusedParameters Parameters that were not used in route replacement.
|
|
51
58
|
* @param additionalParams Additional query parameters to include.
|
|
52
59
|
* @returns URLSearchParams containing all parameters.
|
|
@@ -56,7 +63,13 @@ export class UrlHelpers {
|
|
|
56
63
|
|
|
57
64
|
for (const [key, value] of Object.entries(unusedParameters)) {
|
|
58
65
|
if (value !== undefined && value !== null) {
|
|
59
|
-
|
|
66
|
+
if (Array.isArray(value)) {
|
|
67
|
+
for (const item of value) {
|
|
68
|
+
queryParams.append(key, String(item));
|
|
69
|
+
}
|
|
70
|
+
} else {
|
|
71
|
+
queryParams.set(key, String(value));
|
|
72
|
+
}
|
|
60
73
|
}
|
|
61
74
|
}
|
|
62
75
|
|
package/dist/cjs/Globals.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { GetHttpHeaders } from './GetHttpHeaders';
|
|
1
2
|
import { QueryTransportMethod } from './queries/QueryTransportMethod';
|
|
2
3
|
export interface IGlobals {
|
|
3
4
|
microservice: string;
|
|
@@ -8,6 +9,7 @@ export interface IGlobals {
|
|
|
8
9
|
queryTransportMethod: QueryTransportMethod;
|
|
9
10
|
queryConnectionCount: number;
|
|
10
11
|
queryDirectMode: boolean;
|
|
12
|
+
httpHeadersCallback: GetHttpHeaders;
|
|
11
13
|
}
|
|
12
14
|
export declare const Globals: IGlobals;
|
|
13
15
|
//# sourceMappingURL=Globals.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Globals.d.ts","sourceRoot":"","sources":["../../Globals.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAEtE,MAAM,WAAW,QAAQ;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB,EAAE,MAAM,CAAC;IAC/B,2BAA2B,EAAE,MAAM,CAAC;IACpC,oBAAoB,EAAE,oBAAoB,CAAC;IAO3C,oBAAoB,EAAE,MAAM,CAAC;IAM7B,eAAe,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"Globals.d.ts","sourceRoot":"","sources":["../../Globals.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAEtE,MAAM,WAAW,QAAQ;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB,EAAE,MAAM,CAAC;IAC/B,2BAA2B,EAAE,MAAM,CAAC;IACpC,oBAAoB,EAAE,oBAAoB,CAAC;IAO3C,oBAAoB,EAAE,MAAM,CAAC;IAM7B,eAAe,EAAE,OAAO,CAAC;IAKzB,mBAAmB,EAAE,cAAc,CAAC;CACvC;AAED,eAAO,MAAM,OAAO,EAAE,QAUrB,CAAC"}
|
package/dist/cjs/Globals.js
CHANGED
package/dist/cjs/Globals.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Globals.js","sources":["../../Globals.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { QueryTransportMethod } from './queries/QueryTransportMethod';\n\nexport interface IGlobals {\n microservice: string;\n apiBasePath: string;\n origin: string;\n microserviceHttpHeader: string;\n microserviceWSQueryArgument: string;\n queryTransportMethod: QueryTransportMethod;\n /**\n * Number of hub connections maintained for observable queries.\n * When greater than one, queries are distributed across the pool round-robin.\n * Only applies when {@link queryTransportMethod} is a centralized hub transport.\n * Defaults to 1.\n */\n queryConnectionCount: number;\n /**\n * When true, observable queries connect directly to the per-query WebSocket URL\n * instead of routing through the centralized hub endpoint.\n * Defaults to false (use the centralized hub).\n */\n queryDirectMode: boolean;\n}\n\nexport const Globals: IGlobals = {\n microservice: '',\n apiBasePath: '',\n origin: '',\n microserviceHttpHeader: 'x-cratis-microservice',\n microserviceWSQueryArgument: 'x-cratis-microservice',\n queryTransportMethod: QueryTransportMethod.WebSocket,\n queryConnectionCount: 1,\n queryDirectMode: false,\n};"],"names":["QueryTransportMethod"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"Globals.js","sources":["../../Globals.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { GetHttpHeaders } from './GetHttpHeaders';\nimport { QueryTransportMethod } from './queries/QueryTransportMethod';\n\nexport interface IGlobals {\n microservice: string;\n apiBasePath: string;\n origin: string;\n microserviceHttpHeader: string;\n microserviceWSQueryArgument: string;\n queryTransportMethod: QueryTransportMethod;\n /**\n * Number of hub connections maintained for observable queries.\n * When greater than one, queries are distributed across the pool round-robin.\n * Only applies when {@link queryTransportMethod} is a centralized hub transport.\n * Defaults to 1.\n */\n queryConnectionCount: number;\n /**\n * When true, observable queries connect directly to the per-query WebSocket URL\n * instead of routing through the centralized hub endpoint.\n * Defaults to false (use the centralized hub).\n */\n queryDirectMode: boolean;\n /**\n * Callback that returns custom HTTP headers to include in hub transport requests\n * (e.g. SSE subscribe/unsubscribe POST calls).\n */\n httpHeadersCallback: GetHttpHeaders;\n}\n\nexport const Globals: IGlobals = {\n microservice: '',\n apiBasePath: '',\n origin: '',\n microserviceHttpHeader: 'x-cratis-microservice',\n microserviceWSQueryArgument: 'x-cratis-microservice',\n queryTransportMethod: QueryTransportMethod.WebSocket,\n queryConnectionCount: 1,\n queryDirectMode: false,\n httpHeadersCallback: () => ({}),\n};"],"names":["QueryTransportMethod"],"mappings":";;;;AAiCO,MAAM,OAAO,GAAa;AAC7B,IAAA,YAAY,EAAE,EAAE;AAChB,IAAA,WAAW,EAAE,EAAE;AACf,IAAA,MAAM,EAAE,EAAE;AACV,IAAA,sBAAsB,EAAE,uBAAuB;AAC/C,IAAA,2BAA2B,EAAE,uBAAuB;IACpD,oBAAoB,EAAEA,yCAAoB,CAAC,SAAS;AACpD,IAAA,oBAAoB,EAAE,CAAC;AACvB,IAAA,eAAe,EAAE,KAAK;AACtB,IAAA,mBAAmB,EAAE,OAAO,EAAE,CAAC;;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ICanBeConfigured.d.ts","sourceRoot":"","sources":["../../ICanBeConfigured.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"ICanBeConfigured.d.ts","sourceRoot":"","sources":["../../ICanBeConfigured.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAKlD,MAAM,WAAW,gBAAgB;IAK7B,eAAe,CAAC,YAAY,EAAE,MAAM,OAAE;IAMtC,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAM1C,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAMhC,sBAAsB,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAC;CAC1D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UrlHelpers.d.ts","sourceRoot":"","sources":["../../UrlHelpers.ts"],"names":[],"mappings":"AAGA,qBAAa,UAAU;IAQnB,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,GAAG;IAe7E,MAAM,CAAC,sBAAsB,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,CAAC,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;KAAE;
|
|
1
|
+
{"version":3,"file":"UrlHelpers.d.ts","sourceRoot":"","sources":["../../UrlHelpers.ts"],"names":[],"mappings":"AAGA,qBAAa,UAAU;IAQnB,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,GAAG;IAe7E,MAAM,CAAC,sBAAsB,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,CAAC,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;KAAE;IAkC/H,MAAM,CAAC,gBAAgB,CAAC,gBAAgB,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GAAG,eAAe;CAuBzH"}
|
package/dist/cjs/UrlHelpers.js
CHANGED
|
@@ -14,6 +14,9 @@ class UrlHelpers {
|
|
|
14
14
|
let result = route;
|
|
15
15
|
const unusedParameters = { ...parameters };
|
|
16
16
|
for (const [key, value] of Object.entries(parameters)) {
|
|
17
|
+
if (Array.isArray(value)) {
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
17
20
|
const pattern = new RegExp(`\\{${key}\\}`, 'gi');
|
|
18
21
|
const newRoute = result.replace(pattern, encodeURIComponent(String(value)));
|
|
19
22
|
if (newRoute !== result) {
|
|
@@ -27,7 +30,14 @@ class UrlHelpers {
|
|
|
27
30
|
const queryParams = new URLSearchParams();
|
|
28
31
|
for (const [key, value] of Object.entries(unusedParameters)) {
|
|
29
32
|
if (value !== undefined && value !== null) {
|
|
30
|
-
|
|
33
|
+
if (Array.isArray(value)) {
|
|
34
|
+
for (const item of value) {
|
|
35
|
+
queryParams.append(key, String(item));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
queryParams.set(key, String(value));
|
|
40
|
+
}
|
|
31
41
|
}
|
|
32
42
|
}
|
|
33
43
|
if (additionalParams) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UrlHelpers.js","sources":["../../UrlHelpers.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nexport class UrlHelpers {\n /**\n * Creates a URL from the given origin, API base path, and route.\n * @param origin The origin of the request. If not provided, it defaults to the current document's origin.\n * @param apiBasePath The base path for the API.\n * @param route The specific route for the request.\n * @returns The constructed URL.\n */\n static createUrlFrom(origin: string, apiBasePath: string, route: string): URL {\n if ((!origin || origin.length === 0) && typeof document !== 'undefined') {\n origin = document.location?.origin ?? '';\n }\n\n return new URL(route, `${origin}${apiBasePath}`);\n }\n\n /**\n * Replaces route parameters in the route template with values from the parameters object.\n * Returns both the updated route and the parameters that were not used in the route.\n * @param route The route template with placeholders like {paramName}.\n * @param parameters The parameters to replace in the route.\n * @returns An object containing the updated route and unused parameters.\n */\n static replaceRouteParameters<T extends object>(route: string, parameters?: T): { route: string; unusedParameters: Partial<T> } {\n if (!parameters) {\n return { route, unusedParameters: {} };\n }\n\n let result = route;\n const unusedParameters: Partial<T> = { ...parameters };\n\n for (const [key, value] of Object.entries(parameters)) {\n const pattern = new RegExp(`\\\\{${key}\\\\}`, 'gi');\n const newRoute = result.replace(pattern, encodeURIComponent(String(value)));\n \n if (newRoute !== result) {\n delete unusedParameters[key as keyof T];\n result = newRoute;\n }\n }\n\n return { route: result, unusedParameters };\n }\n\n /**\n * Builds URLSearchParams from the given parameters and additional query parameters.\n * @param unusedParameters Parameters that were not used in route replacement.\n * @param additionalParams Additional query parameters to include.\n * @returns URLSearchParams containing all parameters.\n */\n static buildQueryParams(unusedParameters: object, additionalParams?: Record<string, string | number>): URLSearchParams {\n const queryParams = new URLSearchParams();\n\n for (const [key, value] of Object.entries(unusedParameters)) {\n if (value !== undefined && value !== null) {\n queryParams.set(key, String(value));\n }\n }\n\n if (additionalParams) {\n for (const [key, value] of Object.entries(additionalParams)) {\n queryParams.set(key, String(value));\n }\n }\n\n return queryParams;\n }\n}"],"names":[],"mappings":";;MAGa,UAAU,CAAA;AAQnB,IAAA,OAAO,aAAa,CAAC,MAAc,EAAE,WAAmB,EAAE,KAAa,EAAA;AACnE,QAAA,IAAI,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,KAAK,OAAO,QAAQ,KAAK,WAAW,EAAE;YACrE,MAAM,GAAG,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE;QAC5C;QAEA,OAAO,IAAI,GAAG,CAAC,KAAK,EAAE,CAAA,EAAG,MAAM,CAAA,EAAG,WAAW,CAAA,CAAE,CAAC;IACpD;AASA,IAAA,OAAO,sBAAsB,CAAmB,KAAa,EAAE,UAAc,EAAA;QACzE,IAAI,CAAC,UAAU,EAAE;AACb,YAAA,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAE,EAAE;QAC1C;QAEA,IAAI,MAAM,GAAG,KAAK;AAClB,QAAA,MAAM,gBAAgB,GAAe,EAAE,GAAG,UAAU,EAAE;AAEtD,QAAA,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE;
|
|
1
|
+
{"version":3,"file":"UrlHelpers.js","sources":["../../UrlHelpers.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nexport class UrlHelpers {\n /**\n * Creates a URL from the given origin, API base path, and route.\n * @param origin The origin of the request. If not provided, it defaults to the current document's origin.\n * @param apiBasePath The base path for the API.\n * @param route The specific route for the request.\n * @returns The constructed URL.\n */\n static createUrlFrom(origin: string, apiBasePath: string, route: string): URL {\n if ((!origin || origin.length === 0) && typeof document !== 'undefined') {\n origin = document.location?.origin ?? '';\n }\n\n return new URL(route, `${origin}${apiBasePath}`);\n }\n\n /**\n * Replaces route parameters in the route template with values from the parameters object.\n * Returns both the updated route and the parameters that were not used in the route.\n * @param route The route template with placeholders like {paramName}.\n * @param parameters The parameters to replace in the route.\n * @returns An object containing the updated route and unused parameters.\n */\n static replaceRouteParameters<T extends object>(route: string, parameters?: T): { route: string; unusedParameters: Partial<T> } {\n if (!parameters) {\n return { route, unusedParameters: {} };\n }\n\n let result = route;\n const unusedParameters: Partial<T> = { ...parameters };\n\n for (const [key, value] of Object.entries(parameters)) {\n // Array values cannot be encoded as a single route segment — leave them as unused so\n // they are serialized as repeated query string parameters (e.g. ?ids=1&ids=2&ids=3).\n if (Array.isArray(value)) {\n continue;\n }\n\n const pattern = new RegExp(`\\\\{${key}\\\\}`, 'gi');\n const newRoute = result.replace(pattern, encodeURIComponent(String(value)));\n \n if (newRoute !== result) {\n delete unusedParameters[key as keyof T];\n result = newRoute;\n }\n }\n\n return { route: result, unusedParameters };\n }\n\n /**\n * Builds URLSearchParams from the given parameters and additional query parameters.\n * Array values are serialized as repeated key=value pairs (e.g. ?ids=1&ids=2&ids=3).\n * @param unusedParameters Parameters that were not used in route replacement.\n * @param additionalParams Additional query parameters to include.\n * @returns URLSearchParams containing all parameters.\n */\n static buildQueryParams(unusedParameters: object, additionalParams?: Record<string, string | number>): URLSearchParams {\n const queryParams = new URLSearchParams();\n\n for (const [key, value] of Object.entries(unusedParameters)) {\n if (value !== undefined && value !== null) {\n if (Array.isArray(value)) {\n for (const item of value) {\n queryParams.append(key, String(item));\n }\n } else {\n queryParams.set(key, String(value));\n }\n }\n }\n\n if (additionalParams) {\n for (const [key, value] of Object.entries(additionalParams)) {\n queryParams.set(key, String(value));\n }\n }\n\n return queryParams;\n }\n}"],"names":[],"mappings":";;MAGa,UAAU,CAAA;AAQnB,IAAA,OAAO,aAAa,CAAC,MAAc,EAAE,WAAmB,EAAE,KAAa,EAAA;AACnE,QAAA,IAAI,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,KAAK,OAAO,QAAQ,KAAK,WAAW,EAAE;YACrE,MAAM,GAAG,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE;QAC5C;QAEA,OAAO,IAAI,GAAG,CAAC,KAAK,EAAE,CAAA,EAAG,MAAM,CAAA,EAAG,WAAW,CAAA,CAAE,CAAC;IACpD;AASA,IAAA,OAAO,sBAAsB,CAAmB,KAAa,EAAE,UAAc,EAAA;QACzE,IAAI,CAAC,UAAU,EAAE;AACb,YAAA,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAE,EAAE;QAC1C;QAEA,IAAI,MAAM,GAAG,KAAK;AAClB,QAAA,MAAM,gBAAgB,GAAe,EAAE,GAAG,UAAU,EAAE;AAEtD,QAAA,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE;AAGnD,YAAA,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;gBACtB;YACJ;YAEA,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,CAAA,GAAA,EAAM,GAAG,CAAA,GAAA,CAAK,EAAE,IAAI,CAAC;AAChD,YAAA,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AAE3E,YAAA,IAAI,QAAQ,KAAK,MAAM,EAAE;AACrB,gBAAA,OAAO,gBAAgB,CAAC,GAAc,CAAC;gBACvC,MAAM,GAAG,QAAQ;YACrB;QACJ;AAEA,QAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE;IAC9C;AASA,IAAA,OAAO,gBAAgB,CAAC,gBAAwB,EAAE,gBAAkD,EAAA;AAChG,QAAA,MAAM,WAAW,GAAG,IAAI,eAAe,EAAE;AAEzC,QAAA,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE;YACzD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE;AACvC,gBAAA,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;AACtB,oBAAA,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;wBACtB,WAAW,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;oBACzC;gBACJ;qBAAO;oBACH,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;gBACvC;YACJ;QACJ;QAEA,IAAI,gBAAgB,EAAE;AAClB,YAAA,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE;gBACzD,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;YACvC;QACJ;AAEA,QAAA,OAAO,WAAW;IACtB;AACH;;;;"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Constructor } from '@cratis/fundamentals';
|
|
2
2
|
import { IIdentityProvider } from './IIdentityProvider';
|
|
3
3
|
import { IIdentity } from './IIdentity';
|
|
4
|
-
import { GetHttpHeaders } from 'GetHttpHeaders';
|
|
4
|
+
import { GetHttpHeaders } from '../GetHttpHeaders';
|
|
5
5
|
export declare class IdentityProvider extends IIdentityProvider {
|
|
6
6
|
static readonly CookieName = ".cratis-identity";
|
|
7
7
|
static httpHeadersCallback: GetHttpHeaders | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IdentityProvider.d.ts","sourceRoot":"","sources":["../../../identity/IdentityProvider.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAkB,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAAE,cAAc,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"IdentityProvider.d.ts","sourceRoot":"","sources":["../../../identity/IdentityProvider.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAkB,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAQnD,qBAAa,gBAAiB,SAAQ,iBAAiB;IAEnD,MAAM,CAAC,QAAQ,CAAC,UAAU,sBAAsB;IAChD,MAAM,CAAC,mBAAmB,EAAE,cAAc,GAAG,SAAS,CAAC;IACvD,MAAM,CAAC,WAAW,EAAE,MAAM,CAAM;IAChC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM;IAM3B,MAAM,CAAC,sBAAsB,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI;IAQ7D,MAAM,CAAC,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAQhD,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;WAUzB,UAAU,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAsB/G,UAAU,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;WAIjG,OAAO,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IA0BlH,OAAO,CAAC,MAAM,CAAC,SAAS;IAYxB,OAAO,CAAC,MAAM,CAAC,WAAW;CAI7B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IdentityProvider.js","sources":["../../../identity/IdentityProvider.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Constructor, JsonSerializer } from '@cratis/fundamentals';\nimport { IIdentityProvider } from './IIdentityProvider';\nimport { IIdentity } from './IIdentity';\nimport { IdentityProviderResult } from './IdentityProviderResult';\nimport { GetHttpHeaders } from 'GetHttpHeaders';\nimport { Globals } from '../Globals';\nimport { UrlHelpers } from '../UrlHelpers';\nimport { joinPaths } from '../joinPaths';\n\n/**\n * Represents an implementation of {@link IIdentityProvider}.\n*/\nexport class IdentityProvider extends IIdentityProvider {\n\n static readonly CookieName = '.cratis-identity';\n static httpHeadersCallback: GetHttpHeaders | undefined;\n static apiBasePath: string = '';\n static origin: string = '';\n\n /**\n * Sets the HTTP headers callback.\n * @param callback Callback to set.\n */\n static setHttpHeadersCallback(callback: GetHttpHeaders): void {\n IdentityProvider.httpHeadersCallback = callback;\n }\n\n /**\n * Sets the API base path.\n * @param apiBasePath API base path to set.\n */\n static setApiBasePath(apiBasePath: string): void {\n IdentityProvider.apiBasePath = apiBasePath;\n }\n\n /**\n * Sets the origin.\n * @param origin Origin to set.\n */\n static setOrigin(origin: string): void {\n IdentityProvider.origin = origin;\n }\n\n /**\n * Gets the current identity by optionally specifying the details type.\n * @param type Optional constructor for the details type to enable type-safe deserialization.\n * @returns The current identity as {@link IIdentity}.\n * @remarks The `extends object` constraint is required for compatibility with JsonSerializer.deserializeFromInstance().\n */\n static async getCurrent<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>> {\n const cookie = this.getCookie();\n if (cookie.length == 2) {\n const json = atob(cookie[1]);\n const result = JSON.parse(json) as IdentityProviderResult;\n const details = type ? JsonSerializer.deserializeFromInstance(type, result.details) : result.details;\n return {\n id: result.id,\n name: result.name,\n roles: result.roles || [],\n details: details as TDetails,\n isSet: true,\n isInRole: (role: string) => (result.roles || []).includes(role),\n refresh: () => IdentityProvider.refresh(type)\n } as IIdentity<TDetails>;\n } else {\n const identity = await this.refresh<TDetails>(type);\n return identity;\n }\n }\n\n /** @inheritdoc */\n async getCurrent<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>> {\n return IdentityProvider.getCurrent<TDetails>(type);\n }\n\n static async refresh<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>> {\n IdentityProvider.clearCookie();\n const origin = IdentityProvider.origin || Globals.origin || '';\n const apiBasePath = IdentityProvider.apiBasePath || Globals.apiBasePath || '';\n const route = joinPaths(apiBasePath, '/.cratis/me');\n const url = UrlHelpers.createUrlFrom(origin, apiBasePath, route);\n const response = await fetch(\n url, {\n method: 'GET',\n headers: IdentityProvider.httpHeadersCallback?.() ?? {}\n });\n\n const result = await response.json() as IdentityProviderResult;\n const details = type ? JsonSerializer.deserializeFromInstance(type, result.details) : result.details;\n\n return {\n id: result.id,\n name: result.name,\n roles: result.roles || [],\n details: details as TDetails,\n isSet: true,\n isInRole: (role: string) => (result.roles || []).includes(role),\n refresh: () => IdentityProvider.refresh(type)\n };\n }\n\n private static getCookie() {\n if (typeof document === 'undefined') return [];\n const decoded = decodeURIComponent(document.cookie);\n const cookies = decoded.split(';').map(_ => _.trim());\n const cookie = cookies.find(_ => _.indexOf(`${IdentityProvider.CookieName}=`) == 0);\n if (cookie) {\n const keyValue = cookie.split('=');\n return [keyValue[0].trim(), keyValue[1].trim()];\n }\n return [];\n }\n\n private static clearCookie() {\n if (typeof document === 'undefined') return;\n document.cookie = `${IdentityProvider.CookieName}=;expires=Thu, 01 Jan 1970 00:00:00 GMT`;\n }\n}\n"],"names":["IIdentityProvider","JsonSerializer","Globals","joinPaths","UrlHelpers"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"IdentityProvider.js","sources":["../../../identity/IdentityProvider.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Constructor, JsonSerializer } from '@cratis/fundamentals';\nimport { IIdentityProvider } from './IIdentityProvider';\nimport { IIdentity } from './IIdentity';\nimport { IdentityProviderResult } from './IdentityProviderResult';\nimport { GetHttpHeaders } from '../GetHttpHeaders';\nimport { Globals } from '../Globals';\nimport { UrlHelpers } from '../UrlHelpers';\nimport { joinPaths } from '../joinPaths';\n\n/**\n * Represents an implementation of {@link IIdentityProvider}.\n*/\nexport class IdentityProvider extends IIdentityProvider {\n\n static readonly CookieName = '.cratis-identity';\n static httpHeadersCallback: GetHttpHeaders | undefined;\n static apiBasePath: string = '';\n static origin: string = '';\n\n /**\n * Sets the HTTP headers callback.\n * @param callback Callback to set.\n */\n static setHttpHeadersCallback(callback: GetHttpHeaders): void {\n IdentityProvider.httpHeadersCallback = callback;\n }\n\n /**\n * Sets the API base path.\n * @param apiBasePath API base path to set.\n */\n static setApiBasePath(apiBasePath: string): void {\n IdentityProvider.apiBasePath = apiBasePath;\n }\n\n /**\n * Sets the origin.\n * @param origin Origin to set.\n */\n static setOrigin(origin: string): void {\n IdentityProvider.origin = origin;\n }\n\n /**\n * Gets the current identity by optionally specifying the details type.\n * @param type Optional constructor for the details type to enable type-safe deserialization.\n * @returns The current identity as {@link IIdentity}.\n * @remarks The `extends object` constraint is required for compatibility with JsonSerializer.deserializeFromInstance().\n */\n static async getCurrent<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>> {\n const cookie = this.getCookie();\n if (cookie.length == 2) {\n const json = atob(cookie[1]);\n const result = JSON.parse(json) as IdentityProviderResult;\n const details = type ? JsonSerializer.deserializeFromInstance(type, result.details) : result.details;\n return {\n id: result.id,\n name: result.name,\n roles: result.roles || [],\n details: details as TDetails,\n isSet: true,\n isInRole: (role: string) => (result.roles || []).includes(role),\n refresh: () => IdentityProvider.refresh(type)\n } as IIdentity<TDetails>;\n } else {\n const identity = await this.refresh<TDetails>(type);\n return identity;\n }\n }\n\n /** @inheritdoc */\n async getCurrent<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>> {\n return IdentityProvider.getCurrent<TDetails>(type);\n }\n\n static async refresh<TDetails extends object = object>(type?: Constructor<TDetails>): Promise<IIdentity<TDetails>> {\n IdentityProvider.clearCookie();\n const origin = IdentityProvider.origin || Globals.origin || '';\n const apiBasePath = IdentityProvider.apiBasePath || Globals.apiBasePath || '';\n const route = joinPaths(apiBasePath, '/.cratis/me');\n const url = UrlHelpers.createUrlFrom(origin, apiBasePath, route);\n const response = await fetch(\n url, {\n method: 'GET',\n headers: IdentityProvider.httpHeadersCallback?.() ?? {}\n });\n\n const result = await response.json() as IdentityProviderResult;\n const details = type ? JsonSerializer.deserializeFromInstance(type, result.details) : result.details;\n\n return {\n id: result.id,\n name: result.name,\n roles: result.roles || [],\n details: details as TDetails,\n isSet: true,\n isInRole: (role: string) => (result.roles || []).includes(role),\n refresh: () => IdentityProvider.refresh(type)\n };\n }\n\n private static getCookie() {\n if (typeof document === 'undefined') return [];\n const decoded = decodeURIComponent(document.cookie);\n const cookies = decoded.split(';').map(_ => _.trim());\n const cookie = cookies.find(_ => _.indexOf(`${IdentityProvider.CookieName}=`) == 0);\n if (cookie) {\n const keyValue = cookie.split('=');\n return [keyValue[0].trim(), keyValue[1].trim()];\n }\n return [];\n }\n\n private static clearCookie() {\n if (typeof document === 'undefined') return;\n document.cookie = `${IdentityProvider.CookieName}=;expires=Thu, 01 Jan 1970 00:00:00 GMT`;\n }\n}\n"],"names":["IIdentityProvider","JsonSerializer","Globals","joinPaths","UrlHelpers"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServerSentEventHubConnection.d.ts","sourceRoot":"","sources":["../../../queries/ServerSentEventHubConnection.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,6BAA6B,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGtD,OAAO,EAA8B,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAoB3F,qBAAa,4BAA6B,YAAW,6BAA6B;IAwB1E,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,aAAa;IAE9B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO;IA7B5B,OAAO,CAAC,YAAY,CAAC,CAAc;IACnC,OAAO,CAAC,aAAa,CAAC,CAAS;IAC/B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,qBAAqB,CAA8C;IAC3E,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,eAAe,CAAgB;IACvC,OAAO,CAAC,oBAAoB,CAAC,CAAgC;IAC7D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;gBAe/B,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,MAAM,EACvB,aAAa,EAAE,MAAM,EACtC,mBAAmB,GAAE,MAAc,EAClB,iBAAiB,GAAE,MAAc,EACjC,OAAO,GAAE,gBAAwC;IActE,IAAI,UAAU,IAAI,MAAM,CAEvB;IAGD,IAAI,eAAe,IAAI,MAAM,CAE5B;IAGD,IAAI,cAAc,IAAI,MAAM,CAG3B;IAGD,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,YAAY,CAAC,GAAG,CAAC,GAAG,IAAI;IAe3F,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAclC,OAAO,IAAI,IAAI;IAYf,OAAO,CAAC,eAAe;IAYvB,OAAO,CAAC,KAAK;IAUb,OAAO,CAAC,eAAe;IAwCvB,OAAO,CAAC,SAAS;IAwBjB,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,aAAa;IA0BrB,OAAO,CAAC,eAAe;IAcvB,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,aAAa;
|
|
1
|
+
{"version":3,"file":"ServerSentEventHubConnection.d.ts","sourceRoot":"","sources":["../../../queries/ServerSentEventHubConnection.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,6BAA6B,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGtD,OAAO,EAA8B,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAoB3F,qBAAa,4BAA6B,YAAW,6BAA6B;IAwB1E,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,aAAa;IAE9B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO;IA7B5B,OAAO,CAAC,YAAY,CAAC,CAAc;IACnC,OAAO,CAAC,aAAa,CAAC,CAAS;IAC/B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,qBAAqB,CAA8C;IAC3E,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,eAAe,CAAgB;IACvC,OAAO,CAAC,oBAAoB,CAAC,CAAgC;IAC7D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;gBAe/B,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,MAAM,EACvB,aAAa,EAAE,MAAM,EACtC,mBAAmB,GAAE,MAAc,EAClB,iBAAiB,GAAE,MAAc,EACjC,OAAO,GAAE,gBAAwC;IActE,IAAI,UAAU,IAAI,MAAM,CAEvB;IAGD,IAAI,eAAe,IAAI,MAAM,CAE5B;IAGD,IAAI,cAAc,IAAI,MAAM,CAG3B;IAGD,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,YAAY,CAAC,GAAG,CAAC,GAAG,IAAI;IAe3F,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAclC,OAAO,IAAI,IAAI;IAYf,OAAO,CAAC,eAAe;IAYvB,OAAO,CAAC,KAAK;IAUb,OAAO,CAAC,eAAe;IAwCvB,OAAO,CAAC,SAAS;IAwBjB,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,aAAa;IA0BrB,OAAO,CAAC,eAAe;IAcvB,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,aAAa;IAoBrB,OAAO,CAAC,eAAe;CAkB1B"}
|
|
@@ -204,9 +204,10 @@ class ServerSentEventHubConnection {
|
|
|
204
204
|
queryId,
|
|
205
205
|
request,
|
|
206
206
|
};
|
|
207
|
+
const customHeaders = Globals.Globals.httpHeadersCallback?.() ?? {};
|
|
207
208
|
fetch(this._subscribeUrl, {
|
|
208
209
|
method: 'POST',
|
|
209
|
-
headers: { 'Content-Type': 'application/json' },
|
|
210
|
+
headers: { 'Content-Type': 'application/json', ...customHeaders },
|
|
210
211
|
body: JSON.stringify(body),
|
|
211
212
|
}).catch(error => {
|
|
212
213
|
console.error(`SSE hub: subscribe POST failed for '${queryId}'`, error);
|
|
@@ -219,9 +220,10 @@ class ServerSentEventHubConnection {
|
|
|
219
220
|
connectionId: this._connectionId,
|
|
220
221
|
queryId,
|
|
221
222
|
};
|
|
223
|
+
const customHeaders = Globals.Globals.httpHeadersCallback?.() ?? {};
|
|
222
224
|
fetch(this._unsubscribeUrl, {
|
|
223
225
|
method: 'POST',
|
|
224
|
-
headers: { 'Content-Type': 'application/json' },
|
|
226
|
+
headers: { 'Content-Type': 'application/json', ...customHeaders },
|
|
225
227
|
body: JSON.stringify(body),
|
|
226
228
|
}).catch(error => {
|
|
227
229
|
console.error(`SSE hub: unsubscribe POST failed for '${queryId}'`, error);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServerSentEventHubConnection.js","sources":["../../../queries/ServerSentEventHubConnection.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Globals } from '../Globals';\nimport { IObservableQueryHubConnection } from './IObservableQueryHubConnection';\nimport { DataReceived } from './ObservableQueryConnection';\nimport { HubConnectionKeepAlive } from './HubConnectionKeepAlive';\nimport { IReconnectPolicy } from './IReconnectPolicy';\nimport { ReconnectPolicy } from './ReconnectPolicy';\nimport { QueryResult } from './QueryResult';\nimport { HubMessage, HubMessageType, SubscriptionRequest } from './WebSocketHubConnection';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\ninterface ActiveSubscription {\n request: SubscriptionRequest;\n callback: DataReceived<any>;\n}\n\n/**\n * A multiplexed SSE hub connection that uses EventSource for server→client streaming\n * and fetch POST requests for client→server subscribe/unsubscribe commands.\n *\n * Protocol:\n * 1. Open EventSource to the SSE hub endpoint.\n * 2. Server sends a {@link HubMessageType.Connected} message with the connection identifier.\n * 3. Client sends POST to subscribe/unsubscribe endpoints using the connection identifier.\n * 4. Server streams {@link HubMessageType.QueryResult} messages tagged with queryId.\n * 5. When EventSource closes, server cleans up all subscriptions for this connection.\n */\nexport class ServerSentEventHubConnection implements IObservableQueryHubConnection {\n private _eventSource?: EventSource;\n private _connectionId?: string;\n private _disconnected = false;\n private _subscriptions: Map<string, ActiveSubscription> = new Map();\n private _pendingSubscriptions: Map<string, ActiveSubscription> = new Map();\n private _lastPongLatency: number = 0;\n private _latencySamples: number[] = [];\n private _connectTimeoutTimer?: ReturnType<typeof setTimeout>;\n private readonly _keepAlive: HubConnectionKeepAlive;\n\n /**\n * Initializes a new instance of {@link ServerSentEventHubConnection}.\n * @param {string} _sseUrl The SSE hub endpoint URL (e.g. `http://localhost:5000/.cratis/queries/sse`).\n * @param {string} _subscribeUrl The subscribe POST endpoint URL.\n * @param {string} _unsubscribeUrl The unsubscribe POST endpoint URL.\n * @param {string} _microservice The microservice name to pass as a query argument.\n * @param {number} keepAliveIntervalMs How long without any server message before the connection\n * is considered stale and a reconnect is forced (default: 30 000 ms).\n * @param {number} connectTimeoutMs How long to wait for the {@link HubMessageType.Connected}\n * message after the HTTP connection opens before giving up and retrying (default: 15 000 ms).\n * @param {IReconnectPolicy} _policy The reconnect policy to use (default: {@link ReconnectPolicy}).\n */\n constructor(\n private readonly _sseUrl: string,\n private readonly _subscribeUrl: string,\n private readonly _unsubscribeUrl: string,\n private readonly _microservice: string,\n keepAliveIntervalMs: number = 30000,\n private readonly _connectTimeoutMs: number = 15000,\n private readonly _policy: IReconnectPolicy = new ReconnectPolicy()\n ) {\n // SSE is server→client only: the client cannot send pings. Instead we watch for\n // inactivity — if the server stops sending messages (including its own keep-alive\n // pings) for the entire interval, the connection is stale and we reconnect.\n this._keepAlive = new HubConnectionKeepAlive(keepAliveIntervalMs, () => {\n if (!this._disconnected && this._subscriptions.size > 0) {\n console.warn(`SSE hub: no messages received for ${keepAliveIntervalMs}ms, reconnecting '${this._sseUrl}'`);\n this.reconnect();\n }\n });\n }\n\n /** @inheritdoc */\n get queryCount(): number {\n return this._subscriptions.size;\n }\n\n /** @inheritdoc */\n get lastPingLatency(): number {\n return this._lastPongLatency;\n }\n\n /** @inheritdoc */\n get averageLatency(): number {\n if (this._latencySamples.length === 0) return 0;\n return this._latencySamples.reduce((a, b) => a + b, 0) / this._latencySamples.length;\n }\n\n /** @inheritdoc */\n subscribe(queryId: string, request: SubscriptionRequest, callback: DataReceived<any>): void {\n const sub: ActiveSubscription = { request, callback };\n this._subscriptions.set(queryId, sub);\n\n this.ensureConnected();\n\n if (this._connectionId) {\n this.sendSubscribe(queryId, request);\n } else {\n // Not yet connected, queue for when Connected message arrives.\n this._pendingSubscriptions.set(queryId, sub);\n }\n }\n\n /** @inheritdoc */\n unsubscribe(queryId: string): void {\n this._subscriptions.delete(queryId);\n this._pendingSubscriptions.delete(queryId);\n\n if (this._connectionId) {\n this.sendUnsubscribe(queryId);\n }\n\n if (this._subscriptions.size === 0) {\n this.close();\n }\n }\n\n /** @inheritdoc */\n dispose(): void {\n this._disconnected = true;\n this._subscriptions.clear();\n this._pendingSubscriptions.clear();\n this._policy.cancel();\n this._keepAlive.stop();\n this.clearConnectTimeout();\n this._eventSource?.close();\n this._eventSource = undefined;\n this._connectionId = undefined;\n }\n\n private ensureConnected(): void {\n if (this._disconnected) {\n this._disconnected = false;\n }\n\n if (this._eventSource && this._eventSource.readyState !== EventSource.CLOSED) {\n return;\n }\n\n this.openEventSource();\n }\n\n private close(): void {\n this._disconnected = true;\n this._policy.cancel();\n this._keepAlive.stop();\n this.clearConnectTimeout();\n this._eventSource?.close();\n this._eventSource = undefined;\n this._connectionId = undefined;\n }\n\n private openEventSource(): void {\n let url = this._sseUrl;\n if (this._microservice?.length > 0) {\n const param = `${Globals.microserviceWSQueryArgument}=${encodeURIComponent(this._microservice)}`;\n url += (url.includes('?') ? '&' : '?') + param;\n }\n\n this._connectionId = undefined;\n this._eventSource = new EventSource(url);\n\n this._eventSource.onopen = () => {\n if (this._disconnected) return;\n console.log(`SSE hub connection established: '${url}'`);\n this._policy.reset();\n this._keepAlive.start();\n\n // If the server does not send a Connected message within the timeout, the\n // connection is broken. Close and retry via the reconnect policy.\n this.clearConnectTimeout();\n this._connectTimeoutTimer = setTimeout(() => {\n if (!this._disconnected && !this._connectionId) {\n console.warn(`SSE hub: no Connected message within ${this._connectTimeoutMs}ms, retrying '${url}'`);\n this.reconnect();\n }\n }, this._connectTimeoutMs);\n };\n\n this._eventSource.onmessage = (event: MessageEvent) => {\n if (this._disconnected) return;\n this._keepAlive.recordActivity();\n this.handleMessage(event.data as string);\n };\n\n this._eventSource.onerror = () => {\n if (this._disconnected) return;\n console.warn(`SSE hub connection error: '${url}'`);\n this.reconnect();\n };\n }\n\n private reconnect(): void {\n this._keepAlive.stop();\n this.clearConnectTimeout();\n\n // Close the EventSource so the reconnect policy manages the schedule.\n this._eventSource?.close();\n this._eventSource = undefined;\n this._connectionId = undefined;\n\n // Move all active subscriptions to pending so they re-subscribe when\n // the next Connected message arrives after the managed reconnect.\n for (const [queryId, sub] of this._subscriptions) {\n this._pendingSubscriptions.set(queryId, sub);\n }\n\n if (this._subscriptions.size === 0) return;\n\n this._policy.schedule(() => {\n if (!this._disconnected && this._subscriptions.size > 0) {\n this.openEventSource();\n }\n }, this._sseUrl);\n }\n\n private clearConnectTimeout(): void {\n if (this._connectTimeoutTimer !== undefined) {\n clearTimeout(this._connectTimeoutTimer);\n this._connectTimeoutTimer = undefined;\n }\n }\n\n private handleMessage(rawData: string): void {\n try {\n const message = JSON.parse(rawData) as HubMessage;\n\n switch (message.type) {\n case HubMessageType.Connected:\n this.handleConnected(message);\n break;\n case HubMessageType.QueryResult:\n this.handleQueryResult(message);\n break;\n case HubMessageType.Ping:\n // Server-sent keep-alive ping — activity already recorded in onmessage.\n break;\n case HubMessageType.Unauthorized:\n console.warn(`SSE hub: query '${message.queryId}' unauthorized`);\n break;\n case HubMessageType.Error:\n console.error(`SSE hub: query '${message.queryId}' error:`, message.payload);\n break;\n }\n } catch (error) {\n console.error('SSE hub: error parsing message', error);\n }\n }\n\n private handleConnected(message: HubMessage): void {\n this._connectionId = message.payload as string;\n console.log(`SSE hub: connected with id '${this._connectionId}'`);\n\n // Connected message arrived — cancel the connect timeout.\n this.clearConnectTimeout();\n\n // Send all pending subscriptions now that we have a connection ID.\n for (const [queryId, sub] of this._pendingSubscriptions) {\n this.sendSubscribe(queryId, sub.request);\n }\n this._pendingSubscriptions.clear();\n }\n\n private handleQueryResult(message: HubMessage): void {\n if (!message.queryId) return;\n\n const sub = this._subscriptions.get(message.queryId);\n if (!sub) return;\n\n const result = message.payload as QueryResult<any>;\n sub.callback(result);\n }\n\n private sendSubscribe(queryId: string, request: SubscriptionRequest): void {\n if (!this._connectionId) return;\n\n const body = {\n connectionId: this._connectionId,\n queryId,\n request,\n };\n\n fetch(this._subscribeUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n }).catch(error => {\n console.error(`SSE hub: subscribe POST failed for '${queryId}'`, error);\n });\n }\n\n private sendUnsubscribe(queryId: string): void {\n if (!this._connectionId) return;\n\n const body = {\n connectionId: this._connectionId,\n queryId,\n };\n\n fetch(this._unsubscribeUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n }).catch(error => {\n console.error(`SSE hub: unsubscribe POST failed for '${queryId}'`, error);\n });\n }\n}\n"],"names":["ReconnectPolicy","HubConnectionKeepAlive","Globals","HubMessageType"],"mappings":";;;;;;;MA8Ba,4BAA4B,CAAA;AAwBhB,IAAA,OAAA;AACA,IAAA,aAAA;AACA,IAAA,eAAA;AACA,IAAA,aAAA;AAEA,IAAA,iBAAA;AACA,IAAA,OAAA;AA7Bb,IAAA,YAAY;AACZ,IAAA,aAAa;IACb,aAAa,GAAG,KAAK;AACrB,IAAA,cAAc,GAAoC,IAAI,GAAG,EAAE;AAC3D,IAAA,qBAAqB,GAAoC,IAAI,GAAG,EAAE;IAClE,gBAAgB,GAAW,CAAC;IAC5B,eAAe,GAAa,EAAE;AAC9B,IAAA,oBAAoB;AACX,IAAA,UAAU;AAc3B,IAAA,WAAA,CACqB,OAAe,EACf,aAAqB,EACrB,eAAuB,EACvB,aAAqB,EACtC,mBAAA,GAA8B,KAAK,EAClB,iBAAA,GAA4B,KAAK,EACjC,OAAA,GAA4B,IAAIA,+BAAe,EAAE,EAAA;QANjD,IAAA,CAAA,OAAO,GAAP,OAAO;QACP,IAAA,CAAA,aAAa,GAAb,aAAa;QACb,IAAA,CAAA,eAAe,GAAf,eAAe;QACf,IAAA,CAAA,aAAa,GAAb,aAAa;QAEb,IAAA,CAAA,iBAAiB,GAAjB,iBAAiB;QACjB,IAAA,CAAA,OAAO,GAAP,OAAO;QAKxB,IAAI,CAAC,UAAU,GAAG,IAAIC,6CAAsB,CAAC,mBAAmB,EAAE,MAAK;AACnE,YAAA,IAAI,CAAC,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,cAAc,CAAC,IAAI,GAAG,CAAC,EAAE;gBACrD,OAAO,CAAC,IAAI,CAAC,CAAA,kCAAA,EAAqC,mBAAmB,CAAA,kBAAA,EAAqB,IAAI,CAAC,OAAO,CAAA,CAAA,CAAG,CAAC;gBAC1G,IAAI,CAAC,SAAS,EAAE;YACpB;AACJ,QAAA,CAAC,CAAC;IACN;AAGA,IAAA,IAAI,UAAU,GAAA;AACV,QAAA,OAAO,IAAI,CAAC,cAAc,CAAC,IAAI;IACnC;AAGA,IAAA,IAAI,eAAe,GAAA;QACf,OAAO,IAAI,CAAC,gBAAgB;IAChC;AAGA,IAAA,IAAI,cAAc,GAAA;AACd,QAAA,IAAI,IAAI,CAAC,eAAe,CAAC,MAAM,KAAK,CAAC;AAAE,YAAA,OAAO,CAAC;QAC/C,OAAO,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM;IACxF;AAGA,IAAA,SAAS,CAAC,OAAe,EAAE,OAA4B,EAAE,QAA2B,EAAA;AAChF,QAAA,MAAM,GAAG,GAAuB,EAAE,OAAO,EAAE,QAAQ,EAAE;QACrD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC;QAErC,IAAI,CAAC,eAAe,EAAE;AAEtB,QAAA,IAAI,IAAI,CAAC,aAAa,EAAE;AACpB,YAAA,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC;QACxC;aAAO;YAEH,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC;QAChD;IACJ;AAGA,IAAA,WAAW,CAAC,OAAe,EAAA;AACvB,QAAA,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC;AACnC,QAAA,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC,OAAO,CAAC;AAE1C,QAAA,IAAI,IAAI,CAAC,aAAa,EAAE;AACpB,YAAA,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC;QACjC;QAEA,IAAI,IAAI,CAAC,cAAc,CAAC,IAAI,KAAK,CAAC,EAAE;YAChC,IAAI,CAAC,KAAK,EAAE;QAChB;IACJ;IAGA,OAAO,GAAA;AACH,QAAA,IAAI,CAAC,aAAa,GAAG,IAAI;AACzB,QAAA,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE;AAC3B,QAAA,IAAI,CAAC,qBAAqB,CAAC,KAAK,EAAE;AAClC,QAAA,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;AACrB,QAAA,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;QACtB,IAAI,CAAC,mBAAmB,EAAE;AAC1B,QAAA,IAAI,CAAC,YAAY,EAAE,KAAK,EAAE;AAC1B,QAAA,IAAI,CAAC,YAAY,GAAG,SAAS;AAC7B,QAAA,IAAI,CAAC,aAAa,GAAG,SAAS;IAClC;IAEQ,eAAe,GAAA;AACnB,QAAA,IAAI,IAAI,CAAC,aAAa,EAAE;AACpB,YAAA,IAAI,CAAC,aAAa,GAAG,KAAK;QAC9B;AAEA,QAAA,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,YAAY,CAAC,UAAU,KAAK,WAAW,CAAC,MAAM,EAAE;YAC1E;QACJ;QAEA,IAAI,CAAC,eAAe,EAAE;IAC1B;IAEQ,KAAK,GAAA;AACT,QAAA,IAAI,CAAC,aAAa,GAAG,IAAI;AACzB,QAAA,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;AACrB,QAAA,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;QACtB,IAAI,CAAC,mBAAmB,EAAE;AAC1B,QAAA,IAAI,CAAC,YAAY,EAAE,KAAK,EAAE;AAC1B,QAAA,IAAI,CAAC,YAAY,GAAG,SAAS;AAC7B,QAAA,IAAI,CAAC,aAAa,GAAG,SAAS;IAClC;IAEQ,eAAe,GAAA;AACnB,QAAA,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO;QACtB,IAAI,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,CAAC,EAAE;AAChC,YAAA,MAAM,KAAK,GAAG,CAAA,EAAGC,eAAO,CAAC,2BAA2B,CAAA,CAAA,EAAI,kBAAkB,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE;AAChG,YAAA,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,IAAI,KAAK;QAClD;AAEA,QAAA,IAAI,CAAC,aAAa,GAAG,SAAS;QAC9B,IAAI,CAAC,YAAY,GAAG,IAAI,WAAW,CAAC,GAAG,CAAC;AAExC,QAAA,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,MAAK;YAC5B,IAAI,IAAI,CAAC,aAAa;gBAAE;AACxB,YAAA,OAAO,CAAC,GAAG,CAAC,oCAAoC,GAAG,CAAA,CAAA,CAAG,CAAC;AACvD,YAAA,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;AACpB,YAAA,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE;YAIvB,IAAI,CAAC,mBAAmB,EAAE;AAC1B,YAAA,IAAI,CAAC,oBAAoB,GAAG,UAAU,CAAC,MAAK;gBACxC,IAAI,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE;oBAC5C,OAAO,CAAC,IAAI,CAAC,CAAA,qCAAA,EAAwC,IAAI,CAAC,iBAAiB,CAAA,cAAA,EAAiB,GAAG,CAAA,CAAA,CAAG,CAAC;oBACnG,IAAI,CAAC,SAAS,EAAE;gBACpB;AACJ,YAAA,CAAC,EAAE,IAAI,CAAC,iBAAiB,CAAC;AAC9B,QAAA,CAAC;QAED,IAAI,CAAC,YAAY,CAAC,SAAS,GAAG,CAAC,KAAmB,KAAI;YAClD,IAAI,IAAI,CAAC,aAAa;gBAAE;AACxB,YAAA,IAAI,CAAC,UAAU,CAAC,cAAc,EAAE;AAChC,YAAA,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAc,CAAC;AAC5C,QAAA,CAAC;AAED,QAAA,IAAI,CAAC,YAAY,CAAC,OAAO,GAAG,MAAK;YAC7B,IAAI,IAAI,CAAC,aAAa;gBAAE;AACxB,YAAA,OAAO,CAAC,IAAI,CAAC,8BAA8B,GAAG,CAAA,CAAA,CAAG,CAAC;YAClD,IAAI,CAAC,SAAS,EAAE;AACpB,QAAA,CAAC;IACL;IAEQ,SAAS,GAAA;AACb,QAAA,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;QACtB,IAAI,CAAC,mBAAmB,EAAE;AAG1B,QAAA,IAAI,CAAC,YAAY,EAAE,KAAK,EAAE;AAC1B,QAAA,IAAI,CAAC,YAAY,GAAG,SAAS;AAC7B,QAAA,IAAI,CAAC,aAAa,GAAG,SAAS;QAI9B,KAAK,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,cAAc,EAAE;YAC9C,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC;QAChD;AAEA,QAAA,IAAI,IAAI,CAAC,cAAc,CAAC,IAAI,KAAK,CAAC;YAAE;AAEpC,QAAA,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAK;AACvB,YAAA,IAAI,CAAC,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,cAAc,CAAC,IAAI,GAAG,CAAC,EAAE;gBACrD,IAAI,CAAC,eAAe,EAAE;YAC1B;AACJ,QAAA,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC;IACpB;IAEQ,mBAAmB,GAAA;AACvB,QAAA,IAAI,IAAI,CAAC,oBAAoB,KAAK,SAAS,EAAE;AACzC,YAAA,YAAY,CAAC,IAAI,CAAC,oBAAoB,CAAC;AACvC,YAAA,IAAI,CAAC,oBAAoB,GAAG,SAAS;QACzC;IACJ;AAEQ,IAAA,aAAa,CAAC,OAAe,EAAA;AACjC,QAAA,IAAI;YACA,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAe;AAEjD,YAAA,QAAQ,OAAO,CAAC,IAAI;gBAChB,KAAKC,qCAAc,CAAC,SAAS;AACzB,oBAAA,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC;oBAC7B;gBACJ,KAAKA,qCAAc,CAAC,WAAW;AAC3B,oBAAA,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC;oBAC/B;gBACJ,KAAKA,qCAAc,CAAC,IAAI;oBAEpB;gBACJ,KAAKA,qCAAc,CAAC,YAAY;oBAC5B,OAAO,CAAC,IAAI,CAAC,CAAA,gBAAA,EAAmB,OAAO,CAAC,OAAO,CAAA,cAAA,CAAgB,CAAC;oBAChE;gBACJ,KAAKA,qCAAc,CAAC,KAAK;AACrB,oBAAA,OAAO,CAAC,KAAK,CAAC,CAAA,gBAAA,EAAmB,OAAO,CAAC,OAAO,CAAA,QAAA,CAAU,EAAE,OAAO,CAAC,OAAO,CAAC;oBAC5E;;QAEZ;QAAE,OAAO,KAAK,EAAE;AACZ,YAAA,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAE,KAAK,CAAC;QAC1D;IACJ;AAEQ,IAAA,eAAe,CAAC,OAAmB,EAAA;AACvC,QAAA,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,OAAiB;QAC9C,OAAO,CAAC,GAAG,CAAC,CAAA,4BAAA,EAA+B,IAAI,CAAC,aAAa,CAAA,CAAA,CAAG,CAAC;QAGjE,IAAI,CAAC,mBAAmB,EAAE;QAG1B,KAAK,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,qBAAqB,EAAE;YACrD,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC;QAC5C;AACA,QAAA,IAAI,CAAC,qBAAqB,CAAC,KAAK,EAAE;IACtC;AAEQ,IAAA,iBAAiB,CAAC,OAAmB,EAAA;QACzC,IAAI,CAAC,OAAO,CAAC,OAAO;YAAE;AAEtB,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC;AACpD,QAAA,IAAI,CAAC,GAAG;YAAE;AAEV,QAAA,MAAM,MAAM,GAAG,OAAO,CAAC,OAA2B;AAClD,QAAA,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC;IACxB;IAEQ,aAAa,CAAC,OAAe,EAAE,OAA4B,EAAA;QAC/D,IAAI,CAAC,IAAI,CAAC,aAAa;YAAE;AAEzB,QAAA,MAAM,IAAI,GAAG;YACT,YAAY,EAAE,IAAI,CAAC,aAAa;YAChC,OAAO;YACP,OAAO;SACV;AAED,QAAA,KAAK,CAAC,IAAI,CAAC,aAAa,EAAE;AACtB,YAAA,MAAM,EAAE,MAAM;AACd,YAAA,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;AAC/C,YAAA,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;AAC7B,SAAA,CAAC,CAAC,KAAK,CAAC,KAAK,IAAG;YACb,OAAO,CAAC,KAAK,CAAC,CAAA,oCAAA,EAAuC,OAAO,CAAA,CAAA,CAAG,EAAE,KAAK,CAAC;AAC3E,QAAA,CAAC,CAAC;IACN;AAEQ,IAAA,eAAe,CAAC,OAAe,EAAA;QACnC,IAAI,CAAC,IAAI,CAAC,aAAa;YAAE;AAEzB,QAAA,MAAM,IAAI,GAAG;YACT,YAAY,EAAE,IAAI,CAAC,aAAa;YAChC,OAAO;SACV;AAED,QAAA,KAAK,CAAC,IAAI,CAAC,eAAe,EAAE;AACxB,YAAA,MAAM,EAAE,MAAM;AACd,YAAA,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;AAC/C,YAAA,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;AAC7B,SAAA,CAAC,CAAC,KAAK,CAAC,KAAK,IAAG;YACb,OAAO,CAAC,KAAK,CAAC,CAAA,sCAAA,EAAyC,OAAO,CAAA,CAAA,CAAG,EAAE,KAAK,CAAC;AAC7E,QAAA,CAAC,CAAC;IACN;AACH;;;;"}
|
|
1
|
+
{"version":3,"file":"ServerSentEventHubConnection.js","sources":["../../../queries/ServerSentEventHubConnection.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Globals } from '../Globals';\nimport { IObservableQueryHubConnection } from './IObservableQueryHubConnection';\nimport { DataReceived } from './ObservableQueryConnection';\nimport { HubConnectionKeepAlive } from './HubConnectionKeepAlive';\nimport { IReconnectPolicy } from './IReconnectPolicy';\nimport { ReconnectPolicy } from './ReconnectPolicy';\nimport { QueryResult } from './QueryResult';\nimport { HubMessage, HubMessageType, SubscriptionRequest } from './WebSocketHubConnection';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\ninterface ActiveSubscription {\n request: SubscriptionRequest;\n callback: DataReceived<any>;\n}\n\n/**\n * A multiplexed SSE hub connection that uses EventSource for server→client streaming\n * and fetch POST requests for client→server subscribe/unsubscribe commands.\n *\n * Protocol:\n * 1. Open EventSource to the SSE hub endpoint.\n * 2. Server sends a {@link HubMessageType.Connected} message with the connection identifier.\n * 3. Client sends POST to subscribe/unsubscribe endpoints using the connection identifier.\n * 4. Server streams {@link HubMessageType.QueryResult} messages tagged with queryId.\n * 5. When EventSource closes, server cleans up all subscriptions for this connection.\n */\nexport class ServerSentEventHubConnection implements IObservableQueryHubConnection {\n private _eventSource?: EventSource;\n private _connectionId?: string;\n private _disconnected = false;\n private _subscriptions: Map<string, ActiveSubscription> = new Map();\n private _pendingSubscriptions: Map<string, ActiveSubscription> = new Map();\n private _lastPongLatency: number = 0;\n private _latencySamples: number[] = [];\n private _connectTimeoutTimer?: ReturnType<typeof setTimeout>;\n private readonly _keepAlive: HubConnectionKeepAlive;\n\n /**\n * Initializes a new instance of {@link ServerSentEventHubConnection}.\n * @param {string} _sseUrl The SSE hub endpoint URL (e.g. `http://localhost:5000/.cratis/queries/sse`).\n * @param {string} _subscribeUrl The subscribe POST endpoint URL.\n * @param {string} _unsubscribeUrl The unsubscribe POST endpoint URL.\n * @param {string} _microservice The microservice name to pass as a query argument.\n * @param {number} keepAliveIntervalMs How long without any server message before the connection\n * is considered stale and a reconnect is forced (default: 30 000 ms).\n * @param {number} connectTimeoutMs How long to wait for the {@link HubMessageType.Connected}\n * message after the HTTP connection opens before giving up and retrying (default: 15 000 ms).\n * @param {IReconnectPolicy} _policy The reconnect policy to use (default: {@link ReconnectPolicy}).\n */\n constructor(\n private readonly _sseUrl: string,\n private readonly _subscribeUrl: string,\n private readonly _unsubscribeUrl: string,\n private readonly _microservice: string,\n keepAliveIntervalMs: number = 30000,\n private readonly _connectTimeoutMs: number = 15000,\n private readonly _policy: IReconnectPolicy = new ReconnectPolicy()\n ) {\n // SSE is server→client only: the client cannot send pings. Instead we watch for\n // inactivity — if the server stops sending messages (including its own keep-alive\n // pings) for the entire interval, the connection is stale and we reconnect.\n this._keepAlive = new HubConnectionKeepAlive(keepAliveIntervalMs, () => {\n if (!this._disconnected && this._subscriptions.size > 0) {\n console.warn(`SSE hub: no messages received for ${keepAliveIntervalMs}ms, reconnecting '${this._sseUrl}'`);\n this.reconnect();\n }\n });\n }\n\n /** @inheritdoc */\n get queryCount(): number {\n return this._subscriptions.size;\n }\n\n /** @inheritdoc */\n get lastPingLatency(): number {\n return this._lastPongLatency;\n }\n\n /** @inheritdoc */\n get averageLatency(): number {\n if (this._latencySamples.length === 0) return 0;\n return this._latencySamples.reduce((a, b) => a + b, 0) / this._latencySamples.length;\n }\n\n /** @inheritdoc */\n subscribe(queryId: string, request: SubscriptionRequest, callback: DataReceived<any>): void {\n const sub: ActiveSubscription = { request, callback };\n this._subscriptions.set(queryId, sub);\n\n this.ensureConnected();\n\n if (this._connectionId) {\n this.sendSubscribe(queryId, request);\n } else {\n // Not yet connected, queue for when Connected message arrives.\n this._pendingSubscriptions.set(queryId, sub);\n }\n }\n\n /** @inheritdoc */\n unsubscribe(queryId: string): void {\n this._subscriptions.delete(queryId);\n this._pendingSubscriptions.delete(queryId);\n\n if (this._connectionId) {\n this.sendUnsubscribe(queryId);\n }\n\n if (this._subscriptions.size === 0) {\n this.close();\n }\n }\n\n /** @inheritdoc */\n dispose(): void {\n this._disconnected = true;\n this._subscriptions.clear();\n this._pendingSubscriptions.clear();\n this._policy.cancel();\n this._keepAlive.stop();\n this.clearConnectTimeout();\n this._eventSource?.close();\n this._eventSource = undefined;\n this._connectionId = undefined;\n }\n\n private ensureConnected(): void {\n if (this._disconnected) {\n this._disconnected = false;\n }\n\n if (this._eventSource && this._eventSource.readyState !== EventSource.CLOSED) {\n return;\n }\n\n this.openEventSource();\n }\n\n private close(): void {\n this._disconnected = true;\n this._policy.cancel();\n this._keepAlive.stop();\n this.clearConnectTimeout();\n this._eventSource?.close();\n this._eventSource = undefined;\n this._connectionId = undefined;\n }\n\n private openEventSource(): void {\n let url = this._sseUrl;\n if (this._microservice?.length > 0) {\n const param = `${Globals.microserviceWSQueryArgument}=${encodeURIComponent(this._microservice)}`;\n url += (url.includes('?') ? '&' : '?') + param;\n }\n\n this._connectionId = undefined;\n this._eventSource = new EventSource(url);\n\n this._eventSource.onopen = () => {\n if (this._disconnected) return;\n console.log(`SSE hub connection established: '${url}'`);\n this._policy.reset();\n this._keepAlive.start();\n\n // If the server does not send a Connected message within the timeout, the\n // connection is broken. Close and retry via the reconnect policy.\n this.clearConnectTimeout();\n this._connectTimeoutTimer = setTimeout(() => {\n if (!this._disconnected && !this._connectionId) {\n console.warn(`SSE hub: no Connected message within ${this._connectTimeoutMs}ms, retrying '${url}'`);\n this.reconnect();\n }\n }, this._connectTimeoutMs);\n };\n\n this._eventSource.onmessage = (event: MessageEvent) => {\n if (this._disconnected) return;\n this._keepAlive.recordActivity();\n this.handleMessage(event.data as string);\n };\n\n this._eventSource.onerror = () => {\n if (this._disconnected) return;\n console.warn(`SSE hub connection error: '${url}'`);\n this.reconnect();\n };\n }\n\n private reconnect(): void {\n this._keepAlive.stop();\n this.clearConnectTimeout();\n\n // Close the EventSource so the reconnect policy manages the schedule.\n this._eventSource?.close();\n this._eventSource = undefined;\n this._connectionId = undefined;\n\n // Move all active subscriptions to pending so they re-subscribe when\n // the next Connected message arrives after the managed reconnect.\n for (const [queryId, sub] of this._subscriptions) {\n this._pendingSubscriptions.set(queryId, sub);\n }\n\n if (this._subscriptions.size === 0) return;\n\n this._policy.schedule(() => {\n if (!this._disconnected && this._subscriptions.size > 0) {\n this.openEventSource();\n }\n }, this._sseUrl);\n }\n\n private clearConnectTimeout(): void {\n if (this._connectTimeoutTimer !== undefined) {\n clearTimeout(this._connectTimeoutTimer);\n this._connectTimeoutTimer = undefined;\n }\n }\n\n private handleMessage(rawData: string): void {\n try {\n const message = JSON.parse(rawData) as HubMessage;\n\n switch (message.type) {\n case HubMessageType.Connected:\n this.handleConnected(message);\n break;\n case HubMessageType.QueryResult:\n this.handleQueryResult(message);\n break;\n case HubMessageType.Ping:\n // Server-sent keep-alive ping — activity already recorded in onmessage.\n break;\n case HubMessageType.Unauthorized:\n console.warn(`SSE hub: query '${message.queryId}' unauthorized`);\n break;\n case HubMessageType.Error:\n console.error(`SSE hub: query '${message.queryId}' error:`, message.payload);\n break;\n }\n } catch (error) {\n console.error('SSE hub: error parsing message', error);\n }\n }\n\n private handleConnected(message: HubMessage): void {\n this._connectionId = message.payload as string;\n console.log(`SSE hub: connected with id '${this._connectionId}'`);\n\n // Connected message arrived — cancel the connect timeout.\n this.clearConnectTimeout();\n\n // Send all pending subscriptions now that we have a connection ID.\n for (const [queryId, sub] of this._pendingSubscriptions) {\n this.sendSubscribe(queryId, sub.request);\n }\n this._pendingSubscriptions.clear();\n }\n\n private handleQueryResult(message: HubMessage): void {\n if (!message.queryId) return;\n\n const sub = this._subscriptions.get(message.queryId);\n if (!sub) return;\n\n const result = message.payload as QueryResult<any>;\n sub.callback(result);\n }\n\n private sendSubscribe(queryId: string, request: SubscriptionRequest): void {\n if (!this._connectionId) return;\n\n const body = {\n connectionId: this._connectionId,\n queryId,\n request,\n };\n\n const customHeaders = Globals.httpHeadersCallback?.() ?? {};\n\n fetch(this._subscribeUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...customHeaders },\n body: JSON.stringify(body),\n }).catch(error => {\n console.error(`SSE hub: subscribe POST failed for '${queryId}'`, error);\n });\n }\n\n private sendUnsubscribe(queryId: string): void {\n if (!this._connectionId) return;\n\n const body = {\n connectionId: this._connectionId,\n queryId,\n };\n\n const customHeaders = Globals.httpHeadersCallback?.() ?? {};\n\n fetch(this._unsubscribeUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...customHeaders },\n body: JSON.stringify(body),\n }).catch(error => {\n console.error(`SSE hub: unsubscribe POST failed for '${queryId}'`, error);\n });\n }\n}\n"],"names":["ReconnectPolicy","HubConnectionKeepAlive","Globals","HubMessageType"],"mappings":"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"}
|
|
@@ -34,6 +34,15 @@ export declare class TestQueryForWithParameterDescriptorValues extends QueryFor<
|
|
|
34
34
|
get requiredRequestParameters(): string[];
|
|
35
35
|
constructor();
|
|
36
36
|
}
|
|
37
|
+
export declare class TestQueryForWithEnumerableParameterDescriptorValues extends QueryFor<string[], object> {
|
|
38
|
+
readonly route = "/api/search-by-lists";
|
|
39
|
+
readonly defaultValue: string[];
|
|
40
|
+
readonly parameterDescriptors: ParameterDescriptor[];
|
|
41
|
+
names?: string[];
|
|
42
|
+
ids?: number[];
|
|
43
|
+
get requiredRequestParameters(): string[];
|
|
44
|
+
constructor();
|
|
45
|
+
}
|
|
37
46
|
export interface TestQueryForWithMultipleRequiredParametersArguments {
|
|
38
47
|
userId: string;
|
|
39
48
|
category: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TestQueries.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryFor/given/TestQueries.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAE9E,qBAAa,YAAa,SAAQ,QAAQ,CAAC,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;IAC9D,QAAQ,CAAC,KAAK,oBAAoB;IAClC,QAAQ,CAAC,YAAY,MAAM;IAC3B,QAAQ,CAAC,oBAAoB,EAAE,mBAAmB,EAAE,CAElD;IAEF,IAAI,yBAAyB,IAAI,MAAM,EAAE,CAExC;;CAKJ;AAED,qBAAa,sBAAuB,SAAQ,QAAQ,CAAC,MAAM,EAAE,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;IAChF,QAAQ,CAAC,KAAK,2BAA2B;IACzC,QAAQ,CAAC,YAAY,EAAE,MAAM,EAAE,CAAM;IACrC,QAAQ,CAAC,oBAAoB,EAAE,mBAAmB,EAAE,CAElD;IAEF,IAAI,yBAAyB,IAAI,MAAM,EAAE,CAExC;;CAKJ;AAED,qBAAa,iCAAkC,SAAQ,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAC3E,QAAQ,CAAC,KAAK,cAAc;IAC5B,QAAQ,CAAC,YAAY,MAAM;IAC3B,QAAQ,CAAC,oBAAoB,EAAE,mBAAmB,EAAE,CAAM;IAE1D,IAAI,yBAAyB,IAAI,MAAM,EAAE,CAExC;;CAKJ;AAED,qBAAa,yCAA0C,SAAQ,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACnF,QAAQ,CAAC,KAAK,iBAAiB;IAC/B,QAAQ,CAAC,YAAY,MAAM;IAC3B,QAAQ,CAAC,oBAAoB,EAAE,mBAAmB,EAAE,CAGlD;IAEF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,IAAI,yBAAyB,IAAI,MAAM,EAAE,CAExC;;CAKJ;AAED,MAAM,WAAW,mDAAmD;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,0CAA2C,SAAQ,QAAQ,CAAC,MAAM,EAAE,mDAAmD,CAAC;IACjI,QAAQ,CAAC,KAAK,qCAAqC;IACnD,QAAQ,CAAC,YAAY,MAAM;IAC3B,QAAQ,CAAC,oBAAoB,EAAE,mBAAmB,EAAE,CAGlD;IAEF,IAAI,yBAAyB,IAAI,MAAM,EAAE,CAExC;;CAKJ"}
|
|
1
|
+
{"version":3,"file":"TestQueries.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryFor/given/TestQueries.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAE9E,qBAAa,YAAa,SAAQ,QAAQ,CAAC,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;IAC9D,QAAQ,CAAC,KAAK,oBAAoB;IAClC,QAAQ,CAAC,YAAY,MAAM;IAC3B,QAAQ,CAAC,oBAAoB,EAAE,mBAAmB,EAAE,CAElD;IAEF,IAAI,yBAAyB,IAAI,MAAM,EAAE,CAExC;;CAKJ;AAED,qBAAa,sBAAuB,SAAQ,QAAQ,CAAC,MAAM,EAAE,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;IAChF,QAAQ,CAAC,KAAK,2BAA2B;IACzC,QAAQ,CAAC,YAAY,EAAE,MAAM,EAAE,CAAM;IACrC,QAAQ,CAAC,oBAAoB,EAAE,mBAAmB,EAAE,CAElD;IAEF,IAAI,yBAAyB,IAAI,MAAM,EAAE,CAExC;;CAKJ;AAED,qBAAa,iCAAkC,SAAQ,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAC3E,QAAQ,CAAC,KAAK,cAAc;IAC5B,QAAQ,CAAC,YAAY,MAAM;IAC3B,QAAQ,CAAC,oBAAoB,EAAE,mBAAmB,EAAE,CAAM;IAE1D,IAAI,yBAAyB,IAAI,MAAM,EAAE,CAExC;;CAKJ;AAED,qBAAa,yCAA0C,SAAQ,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACnF,QAAQ,CAAC,KAAK,iBAAiB;IAC/B,QAAQ,CAAC,YAAY,MAAM;IAC3B,QAAQ,CAAC,oBAAoB,EAAE,mBAAmB,EAAE,CAGlD;IAEF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,IAAI,yBAAyB,IAAI,MAAM,EAAE,CAExC;;CAKJ;AAED,qBAAa,mDAAoD,SAAQ,QAAQ,CAAC,MAAM,EAAE,EAAE,MAAM,CAAC;IAC/F,QAAQ,CAAC,KAAK,0BAA0B;IACxC,QAAQ,CAAC,YAAY,EAAE,MAAM,EAAE,CAAM;IACrC,QAAQ,CAAC,oBAAoB,EAAE,mBAAmB,EAAE,CAGlD;IAEF,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IAEf,IAAI,yBAAyB,IAAI,MAAM,EAAE,CAExC;;CAKJ;AAED,MAAM,WAAW,mDAAmD;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,0CAA2C,SAAQ,QAAQ,CAAC,MAAM,EAAE,mDAAmD,CAAC;IACjI,QAAQ,CAAC,KAAK,qCAAqC;IACnD,QAAQ,CAAC,YAAY,MAAM;IAC3B,QAAQ,CAAC,oBAAoB,EAAE,mBAAmB,EAAE,CAGlD;IAEF,IAAI,yBAAyB,IAAI,MAAM,EAAE,CAExC;;CAKJ"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { TestQueryFor, TestEnumerableQueryFor, TestQueryForWithoutRequiredParams, TestQueryForWithParameterDescriptorValues, TestQueryForWithMultipleRequiredParameters } from './TestQueries';
|
|
1
|
+
import { TestQueryFor, TestEnumerableQueryFor, TestQueryForWithoutRequiredParams, TestQueryForWithParameterDescriptorValues, TestQueryForWithMultipleRequiredParameters, TestQueryForWithEnumerableParameterDescriptorValues } from './TestQueries';
|
|
2
2
|
export declare class a_query_for {
|
|
3
3
|
query: TestQueryFor;
|
|
4
4
|
enumerableQuery: TestEnumerableQueryFor;
|
|
5
5
|
queryWithoutParams: TestQueryForWithoutRequiredParams;
|
|
6
6
|
queryWithParameterDescriptorValues: TestQueryForWithParameterDescriptorValues;
|
|
7
|
+
queryWithEnumerableParameterDescriptorValues: TestQueryForWithEnumerableParameterDescriptorValues;
|
|
7
8
|
queryWithMultipleRequiredParameters: TestQueryForWithMultipleRequiredParameters;
|
|
8
9
|
constructor();
|
|
9
10
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"a_query_for.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryFor/given/a_query_for.ts"],"names":[],"mappings":"AAGA,OAAO,EACH,YAAY,EACZ,sBAAsB,EACtB,iCAAiC,EACjC,yCAAyC,EACzC,0CAA0C,
|
|
1
|
+
{"version":3,"file":"a_query_for.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryFor/given/a_query_for.ts"],"names":[],"mappings":"AAGA,OAAO,EACH,YAAY,EACZ,sBAAsB,EACtB,iCAAiC,EACjC,yCAAyC,EACzC,0CAA0C,EAC1C,mDAAmD,EACtD,MAAM,eAAe,CAAC;AAEvB,qBAAa,WAAW;IACpB,KAAK,EAAE,YAAY,CAAC;IACpB,eAAe,EAAE,sBAAsB,CAAC;IACxC,kBAAkB,EAAE,iCAAiC,CAAC;IACtD,kCAAkC,EAAE,yCAAyC,CAAC;IAC9E,4CAA4C,EAAE,mDAAmD,CAAC;IAClG,mCAAmC,EAAE,0CAA0C,CAAC;;CAUnF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with_enumerable_parameter_descriptor_values.d.ts","sourceRoot":"","sources":["../../../../../queries/for_QueryFor/when_performing/with_enumerable_parameter_descriptor_values.ts"],"names":[],"mappings":""}
|
|
@@ -2,6 +2,7 @@ import { Constructor } from '@cratis/fundamentals';
|
|
|
2
2
|
export declare class ParameterDescriptor {
|
|
3
3
|
readonly name: string;
|
|
4
4
|
readonly type: Constructor;
|
|
5
|
-
|
|
5
|
+
readonly isEnumerable: boolean;
|
|
6
|
+
constructor(name: string, type: Constructor, isEnumerable?: boolean);
|
|
6
7
|
}
|
|
7
8
|
//# sourceMappingURL=ParameterDescriptor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ParameterDescriptor.d.ts","sourceRoot":"","sources":["../../../reflection/ParameterDescriptor.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAKnD,qBAAa,mBAAmB;
|
|
1
|
+
{"version":3,"file":"ParameterDescriptor.d.ts","sourceRoot":"","sources":["../../../reflection/ParameterDescriptor.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAKnD,qBAAa,mBAAmB;IAOhB,QAAQ,CAAC,IAAI,EAAE,MAAM;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW;IAAE,QAAQ,CAAC,YAAY,EAAE,OAAO;gBAAxE,IAAI,EAAE,MAAM,EAAW,IAAI,EAAE,WAAW,EAAW,YAAY,GAAE,OAAe;CAExG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ParameterDescriptor.js","sources":["../../../reflection/ParameterDescriptor.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Constructor } from '@cratis/fundamentals';\n\n/**\n * Represents a parameter descriptor.\n */\nexport class ParameterDescriptor {\n /**\n * Initializes a new instance of the {@link ParameterDescriptor} class.\n * @param name Name of the parameter.\n * @param type Type of the parameter.\n */\n constructor(readonly name: string, readonly type: Constructor) {\n }\n}\n"],"names":[],"mappings":";;MAQa,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"ParameterDescriptor.js","sources":["../../../reflection/ParameterDescriptor.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { Constructor } from '@cratis/fundamentals';\n\n/**\n * Represents a parameter descriptor.\n */\nexport class ParameterDescriptor {\n /**\n * Initializes a new instance of the {@link ParameterDescriptor} class.\n * @param name Name of the parameter.\n * @param type Type of the parameter.\n * @param isEnumerable Whether the parameter is an enumerable (collection) type.\n */\n constructor(readonly name: string, readonly type: Constructor, readonly isEnumerable: boolean = false) {\n }\n}\n"],"names":[],"mappings":";;MAQa,mBAAmB,CAAA;AAOP,IAAA,IAAA;AAAuB,IAAA,IAAA;AAA4B,IAAA,YAAA;AAAxE,IAAA,WAAA,CAAqB,IAAY,EAAW,IAAiB,EAAW,eAAwB,KAAK,EAAA;QAAhF,IAAA,CAAA,IAAI,GAAJ,IAAI;QAAmB,IAAA,CAAA,IAAI,GAAJ,IAAI;QAAwB,IAAA,CAAA,YAAY,GAAZ,YAAY;IACpF;AACH;;;;"}
|
package/dist/esm/Globals.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { GetHttpHeaders } from './GetHttpHeaders';
|
|
1
2
|
import { QueryTransportMethod } from './queries/QueryTransportMethod';
|
|
2
3
|
export interface IGlobals {
|
|
3
4
|
microservice: string;
|
|
@@ -8,6 +9,7 @@ export interface IGlobals {
|
|
|
8
9
|
queryTransportMethod: QueryTransportMethod;
|
|
9
10
|
queryConnectionCount: number;
|
|
10
11
|
queryDirectMode: boolean;
|
|
12
|
+
httpHeadersCallback: GetHttpHeaders;
|
|
11
13
|
}
|
|
12
14
|
export declare const Globals: IGlobals;
|
|
13
15
|
//# sourceMappingURL=Globals.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Globals.d.ts","sourceRoot":"","sources":["../../Globals.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAEtE,MAAM,WAAW,QAAQ;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB,EAAE,MAAM,CAAC;IAC/B,2BAA2B,EAAE,MAAM,CAAC;IACpC,oBAAoB,EAAE,oBAAoB,CAAC;IAO3C,oBAAoB,EAAE,MAAM,CAAC;IAM7B,eAAe,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"Globals.d.ts","sourceRoot":"","sources":["../../Globals.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAEtE,MAAM,WAAW,QAAQ;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB,EAAE,MAAM,CAAC;IAC/B,2BAA2B,EAAE,MAAM,CAAC;IACpC,oBAAoB,EAAE,oBAAoB,CAAC;IAO3C,oBAAoB,EAAE,MAAM,CAAC;IAM7B,eAAe,EAAE,OAAO,CAAC;IAKzB,mBAAmB,EAAE,cAAc,CAAC;CACvC;AAED,eAAO,MAAM,OAAO,EAAE,QAUrB,CAAC"}
|
package/dist/esm/Globals.js
CHANGED
package/dist/esm/Globals.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Globals.js","sources":["../../Globals.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { QueryTransportMethod } from './queries/QueryTransportMethod';\n\nexport interface IGlobals {\n microservice: string;\n apiBasePath: string;\n origin: string;\n microserviceHttpHeader: string;\n microserviceWSQueryArgument: string;\n queryTransportMethod: QueryTransportMethod;\n /**\n * Number of hub connections maintained for observable queries.\n * When greater than one, queries are distributed across the pool round-robin.\n * Only applies when {@link queryTransportMethod} is a centralized hub transport.\n * Defaults to 1.\n */\n queryConnectionCount: number;\n /**\n * When true, observable queries connect directly to the per-query WebSocket URL\n * instead of routing through the centralized hub endpoint.\n * Defaults to false (use the centralized hub).\n */\n queryDirectMode: boolean;\n}\n\nexport const Globals: IGlobals = {\n microservice: '',\n apiBasePath: '',\n origin: '',\n microserviceHttpHeader: 'x-cratis-microservice',\n microserviceWSQueryArgument: 'x-cratis-microservice',\n queryTransportMethod: QueryTransportMethod.WebSocket,\n queryConnectionCount: 1,\n queryDirectMode: false,\n};"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"Globals.js","sources":["../../Globals.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { GetHttpHeaders } from './GetHttpHeaders';\nimport { QueryTransportMethod } from './queries/QueryTransportMethod';\n\nexport interface IGlobals {\n microservice: string;\n apiBasePath: string;\n origin: string;\n microserviceHttpHeader: string;\n microserviceWSQueryArgument: string;\n queryTransportMethod: QueryTransportMethod;\n /**\n * Number of hub connections maintained for observable queries.\n * When greater than one, queries are distributed across the pool round-robin.\n * Only applies when {@link queryTransportMethod} is a centralized hub transport.\n * Defaults to 1.\n */\n queryConnectionCount: number;\n /**\n * When true, observable queries connect directly to the per-query WebSocket URL\n * instead of routing through the centralized hub endpoint.\n * Defaults to false (use the centralized hub).\n */\n queryDirectMode: boolean;\n /**\n * Callback that returns custom HTTP headers to include in hub transport requests\n * (e.g. SSE subscribe/unsubscribe POST calls).\n */\n httpHeadersCallback: GetHttpHeaders;\n}\n\nexport const Globals: IGlobals = {\n microservice: '',\n apiBasePath: '',\n origin: '',\n microserviceHttpHeader: 'x-cratis-microservice',\n microserviceWSQueryArgument: 'x-cratis-microservice',\n queryTransportMethod: QueryTransportMethod.WebSocket,\n queryConnectionCount: 1,\n queryDirectMode: false,\n httpHeadersCallback: () => ({}),\n};"],"names":[],"mappings":";;AAiCO,MAAM,OAAO,GAAa;AAC7B,IAAA,YAAY,EAAE,EAAE;AAChB,IAAA,WAAW,EAAE,EAAE;AACf,IAAA,MAAM,EAAE,EAAE;AACV,IAAA,sBAAsB,EAAE,uBAAuB;AAC/C,IAAA,2BAA2B,EAAE,uBAAuB;IACpD,oBAAoB,EAAE,oBAAoB,CAAC,SAAS;AACpD,IAAA,oBAAoB,EAAE,CAAC;AACvB,IAAA,eAAe,EAAE,KAAK;AACtB,IAAA,mBAAmB,EAAE,OAAO,EAAE,CAAC;;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ICanBeConfigured.d.ts","sourceRoot":"","sources":["../../ICanBeConfigured.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"ICanBeConfigured.d.ts","sourceRoot":"","sources":["../../ICanBeConfigured.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAKlD,MAAM,WAAW,gBAAgB;IAK7B,eAAe,CAAC,YAAY,EAAE,MAAM,OAAE;IAMtC,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAM1C,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAMhC,sBAAsB,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAC;CAC1D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UrlHelpers.d.ts","sourceRoot":"","sources":["../../UrlHelpers.ts"],"names":[],"mappings":"AAGA,qBAAa,UAAU;IAQnB,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,GAAG;IAe7E,MAAM,CAAC,sBAAsB,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,CAAC,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;KAAE;
|
|
1
|
+
{"version":3,"file":"UrlHelpers.d.ts","sourceRoot":"","sources":["../../UrlHelpers.ts"],"names":[],"mappings":"AAGA,qBAAa,UAAU;IAQnB,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,GAAG;IAe7E,MAAM,CAAC,sBAAsB,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,CAAC,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;KAAE;IAkC/H,MAAM,CAAC,gBAAgB,CAAC,gBAAgB,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GAAG,eAAe;CAuBzH"}
|
package/dist/esm/UrlHelpers.js
CHANGED
|
@@ -12,6 +12,9 @@ class UrlHelpers {
|
|
|
12
12
|
let result = route;
|
|
13
13
|
const unusedParameters = { ...parameters };
|
|
14
14
|
for (const [key, value] of Object.entries(parameters)) {
|
|
15
|
+
if (Array.isArray(value)) {
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
15
18
|
const pattern = new RegExp(`\\{${key}\\}`, 'gi');
|
|
16
19
|
const newRoute = result.replace(pattern, encodeURIComponent(String(value)));
|
|
17
20
|
if (newRoute !== result) {
|
|
@@ -25,7 +28,14 @@ class UrlHelpers {
|
|
|
25
28
|
const queryParams = new URLSearchParams();
|
|
26
29
|
for (const [key, value] of Object.entries(unusedParameters)) {
|
|
27
30
|
if (value !== undefined && value !== null) {
|
|
28
|
-
|
|
31
|
+
if (Array.isArray(value)) {
|
|
32
|
+
for (const item of value) {
|
|
33
|
+
queryParams.append(key, String(item));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
queryParams.set(key, String(value));
|
|
38
|
+
}
|
|
29
39
|
}
|
|
30
40
|
}
|
|
31
41
|
if (additionalParams) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UrlHelpers.js","sources":["../../UrlHelpers.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nexport class UrlHelpers {\n /**\n * Creates a URL from the given origin, API base path, and route.\n * @param origin The origin of the request. If not provided, it defaults to the current document's origin.\n * @param apiBasePath The base path for the API.\n * @param route The specific route for the request.\n * @returns The constructed URL.\n */\n static createUrlFrom(origin: string, apiBasePath: string, route: string): URL {\n if ((!origin || origin.length === 0) && typeof document !== 'undefined') {\n origin = document.location?.origin ?? '';\n }\n\n return new URL(route, `${origin}${apiBasePath}`);\n }\n\n /**\n * Replaces route parameters in the route template with values from the parameters object.\n * Returns both the updated route and the parameters that were not used in the route.\n * @param route The route template with placeholders like {paramName}.\n * @param parameters The parameters to replace in the route.\n * @returns An object containing the updated route and unused parameters.\n */\n static replaceRouteParameters<T extends object>(route: string, parameters?: T): { route: string; unusedParameters: Partial<T> } {\n if (!parameters) {\n return { route, unusedParameters: {} };\n }\n\n let result = route;\n const unusedParameters: Partial<T> = { ...parameters };\n\n for (const [key, value] of Object.entries(parameters)) {\n const pattern = new RegExp(`\\\\{${key}\\\\}`, 'gi');\n const newRoute = result.replace(pattern, encodeURIComponent(String(value)));\n \n if (newRoute !== result) {\n delete unusedParameters[key as keyof T];\n result = newRoute;\n }\n }\n\n return { route: result, unusedParameters };\n }\n\n /**\n * Builds URLSearchParams from the given parameters and additional query parameters.\n * @param unusedParameters Parameters that were not used in route replacement.\n * @param additionalParams Additional query parameters to include.\n * @returns URLSearchParams containing all parameters.\n */\n static buildQueryParams(unusedParameters: object, additionalParams?: Record<string, string | number>): URLSearchParams {\n const queryParams = new URLSearchParams();\n\n for (const [key, value] of Object.entries(unusedParameters)) {\n if (value !== undefined && value !== null) {\n queryParams.set(key, String(value));\n }\n }\n\n if (additionalParams) {\n for (const [key, value] of Object.entries(additionalParams)) {\n queryParams.set(key, String(value));\n }\n }\n\n return queryParams;\n }\n}"],"names":[],"mappings":"MAGa,UAAU,CAAA;AAQnB,IAAA,OAAO,aAAa,CAAC,MAAc,EAAE,WAAmB,EAAE,KAAa,EAAA;AACnE,QAAA,IAAI,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,KAAK,OAAO,QAAQ,KAAK,WAAW,EAAE;YACrE,MAAM,GAAG,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE;QAC5C;QAEA,OAAO,IAAI,GAAG,CAAC,KAAK,EAAE,CAAA,EAAG,MAAM,CAAA,EAAG,WAAW,CAAA,CAAE,CAAC;IACpD;AASA,IAAA,OAAO,sBAAsB,CAAmB,KAAa,EAAE,UAAc,EAAA;QACzE,IAAI,CAAC,UAAU,EAAE;AACb,YAAA,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAE,EAAE;QAC1C;QAEA,IAAI,MAAM,GAAG,KAAK;AAClB,QAAA,MAAM,gBAAgB,GAAe,EAAE,GAAG,UAAU,EAAE;AAEtD,QAAA,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE;
|
|
1
|
+
{"version":3,"file":"UrlHelpers.js","sources":["../../UrlHelpers.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nexport class UrlHelpers {\n /**\n * Creates a URL from the given origin, API base path, and route.\n * @param origin The origin of the request. If not provided, it defaults to the current document's origin.\n * @param apiBasePath The base path for the API.\n * @param route The specific route for the request.\n * @returns The constructed URL.\n */\n static createUrlFrom(origin: string, apiBasePath: string, route: string): URL {\n if ((!origin || origin.length === 0) && typeof document !== 'undefined') {\n origin = document.location?.origin ?? '';\n }\n\n return new URL(route, `${origin}${apiBasePath}`);\n }\n\n /**\n * Replaces route parameters in the route template with values from the parameters object.\n * Returns both the updated route and the parameters that were not used in the route.\n * @param route The route template with placeholders like {paramName}.\n * @param parameters The parameters to replace in the route.\n * @returns An object containing the updated route and unused parameters.\n */\n static replaceRouteParameters<T extends object>(route: string, parameters?: T): { route: string; unusedParameters: Partial<T> } {\n if (!parameters) {\n return { route, unusedParameters: {} };\n }\n\n let result = route;\n const unusedParameters: Partial<T> = { ...parameters };\n\n for (const [key, value] of Object.entries(parameters)) {\n // Array values cannot be encoded as a single route segment — leave them as unused so\n // they are serialized as repeated query string parameters (e.g. ?ids=1&ids=2&ids=3).\n if (Array.isArray(value)) {\n continue;\n }\n\n const pattern = new RegExp(`\\\\{${key}\\\\}`, 'gi');\n const newRoute = result.replace(pattern, encodeURIComponent(String(value)));\n \n if (newRoute !== result) {\n delete unusedParameters[key as keyof T];\n result = newRoute;\n }\n }\n\n return { route: result, unusedParameters };\n }\n\n /**\n * Builds URLSearchParams from the given parameters and additional query parameters.\n * Array values are serialized as repeated key=value pairs (e.g. ?ids=1&ids=2&ids=3).\n * @param unusedParameters Parameters that were not used in route replacement.\n * @param additionalParams Additional query parameters to include.\n * @returns URLSearchParams containing all parameters.\n */\n static buildQueryParams(unusedParameters: object, additionalParams?: Record<string, string | number>): URLSearchParams {\n const queryParams = new URLSearchParams();\n\n for (const [key, value] of Object.entries(unusedParameters)) {\n if (value !== undefined && value !== null) {\n if (Array.isArray(value)) {\n for (const item of value) {\n queryParams.append(key, String(item));\n }\n } else {\n queryParams.set(key, String(value));\n }\n }\n }\n\n if (additionalParams) {\n for (const [key, value] of Object.entries(additionalParams)) {\n queryParams.set(key, String(value));\n }\n }\n\n return queryParams;\n }\n}"],"names":[],"mappings":"MAGa,UAAU,CAAA;AAQnB,IAAA,OAAO,aAAa,CAAC,MAAc,EAAE,WAAmB,EAAE,KAAa,EAAA;AACnE,QAAA,IAAI,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,KAAK,OAAO,QAAQ,KAAK,WAAW,EAAE;YACrE,MAAM,GAAG,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE;QAC5C;QAEA,OAAO,IAAI,GAAG,CAAC,KAAK,EAAE,CAAA,EAAG,MAAM,CAAA,EAAG,WAAW,CAAA,CAAE,CAAC;IACpD;AASA,IAAA,OAAO,sBAAsB,CAAmB,KAAa,EAAE,UAAc,EAAA;QACzE,IAAI,CAAC,UAAU,EAAE;AACb,YAAA,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAE,EAAE;QAC1C;QAEA,IAAI,MAAM,GAAG,KAAK;AAClB,QAAA,MAAM,gBAAgB,GAAe,EAAE,GAAG,UAAU,EAAE;AAEtD,QAAA,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE;AAGnD,YAAA,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;gBACtB;YACJ;YAEA,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,CAAA,GAAA,EAAM,GAAG,CAAA,GAAA,CAAK,EAAE,IAAI,CAAC;AAChD,YAAA,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AAE3E,YAAA,IAAI,QAAQ,KAAK,MAAM,EAAE;AACrB,gBAAA,OAAO,gBAAgB,CAAC,GAAc,CAAC;gBACvC,MAAM,GAAG,QAAQ;YACrB;QACJ;AAEA,QAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE;IAC9C;AASA,IAAA,OAAO,gBAAgB,CAAC,gBAAwB,EAAE,gBAAkD,EAAA;AAChG,QAAA,MAAM,WAAW,GAAG,IAAI,eAAe,EAAE;AAEzC,QAAA,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE;YACzD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE;AACvC,gBAAA,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;AACtB,oBAAA,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;wBACtB,WAAW,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;oBACzC;gBACJ;qBAAO;oBACH,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;gBACvC;YACJ;QACJ;QAEA,IAAI,gBAAgB,EAAE;AAClB,YAAA,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE;gBACzD,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;YACvC;QACJ;AAEA,QAAA,OAAO,WAAW;IACtB;AACH;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with_array_values.d.ts","sourceRoot":"","sources":["../../../../for_UrlHelpers/when_building_query_params/with_array_values.ts"],"names":[],"mappings":""}
|