@obsidiane/meridiane 2.0.7 → 2.0.11
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/README.md +19 -2
- package/cli.js +21 -37
- package/package.json +3 -3
- package/src/README.md +9 -0
- package/{tools/app → src/application}/bridge-workflow.js +15 -13
- package/src/application/generate-bridge.js +50 -0
- package/{tools/app → src/application}/run-build.js +1 -1
- package/{tools/app → src/application}/run-dev.js +30 -36
- package/{tools/app → src/application}/run-generate.js +3 -3
- package/{tools → src}/domain/bridge-options.js +8 -21
- package/src/domain/list-values.js +6 -0
- package/src/generators/bridge/write-bridge-files.js +100 -0
- package/src/generators/models/interface-schema.js +116 -0
- package/src/generators/models/model-selection.js +148 -0
- package/src/generators/models/oas-contract.js +170 -0
- package/{tools/generator → src/generators}/models/oas-schema-name.js +6 -15
- package/src/generators/models/openapi-to-models.js +136 -0
- package/{tools/generator → src/generators}/models/schema-utils.js +27 -3
- package/src/generators/models/templates/type-alias.hbs +2 -0
- package/src/generators/models/type-expression.js +65 -0
- package/src/generators/models/type-resolver.js +240 -0
- package/src/generators/models/utils.js +89 -0
- package/src/generators/models/write-model-files.js +55 -0
- package/src/infrastructure/dev-project.js +48 -0
- package/{tools/infra → src/infrastructure}/exec.js +3 -2
- package/src/infrastructure/local-package-install.js +104 -0
- package/src/infrastructure/spec-loader.js +65 -0
- package/{tools/infra → src/infrastructure}/standalone-workspace.js +31 -29
- package/templates/{_lib_template → angular-bridge}/README.md +22 -4
- package/templates/angular-bridge/src/lib/bridge/rest/api-platform.adapter.ts +82 -0
- package/templates/angular-bridge/src/lib/bridge/rest/http-request.options.ts +30 -0
- package/templates/{_lib_template → angular-bridge}/src/lib/bridge/rest/query-builder.ts +10 -10
- package/templates/angular-bridge/src/lib/bridge/sse/mercure-connections.ts +255 -0
- package/templates/angular-bridge/src/lib/bridge/sse/mercure-payload.ts +82 -0
- package/templates/angular-bridge/src/lib/bridge/sse/mercure-url.builder.ts +39 -0
- package/templates/angular-bridge/src/lib/bridge/sse/mercure.adapter.ts +358 -0
- package/templates/{_lib_template → angular-bridge}/src/lib/bridge/sse/ref-count-topic.registry.ts +3 -12
- package/templates/angular-bridge/src/lib/bridge/sse/subscription-claims.ts +76 -0
- package/templates/angular-bridge/src/lib/bridge-options.ts +59 -0
- package/templates/{_lib_template → angular-bridge}/src/lib/facades/bridge.facade.ts +52 -53
- package/templates/{_lib_template → angular-bridge}/src/lib/facades/facade.factory.ts +3 -4
- package/templates/angular-bridge/src/lib/facades/facade.interface.ts +13 -0
- package/templates/{_lib_template → angular-bridge}/src/lib/facades/resource.facade.ts +24 -31
- package/templates/angular-bridge/src/lib/interceptors/bearer-auth.interceptor.ts +33 -0
- package/templates/angular-bridge/src/lib/interceptors/bridge-defaults.interceptor.ts +65 -0
- package/templates/angular-bridge/src/lib/interceptors/content-type.interceptor.ts +37 -0
- package/templates/angular-bridge/src/lib/interceptors/scoped.interceptor.ts +9 -0
- package/templates/angular-bridge/src/lib/interceptors/singleflight.interceptor.ts +46 -0
- package/templates/{_lib_template → angular-bridge}/src/lib/ports/realtime.port.ts +6 -2
- package/templates/{_lib_template → angular-bridge}/src/lib/ports/resource-repository.port.ts +7 -7
- package/templates/angular-bridge/src/lib/provide-bridge.ts +98 -0
- package/templates/{_lib_template → angular-bridge}/src/lib/tokens.ts +9 -3
- package/templates/angular-bridge/src/lib/utils/iri.ts +6 -0
- package/templates/angular-bridge/src/lib/utils/request-url.ts +31 -0
- package/templates/{_lib_template → angular-bridge}/src/public-api.ts +2 -0
- package/templates/_lib_template/src/lib/bridge/rest/api-platform.adapter.ts +0 -84
- package/templates/_lib_template/src/lib/bridge/rest/http-request.options.ts +0 -21
- package/templates/_lib_template/src/lib/bridge/sse/mercure-url.builder.ts +0 -17
- package/templates/_lib_template/src/lib/bridge/sse/mercure.adapter.ts +0 -806
- package/templates/_lib_template/src/lib/facades/facade.interface.ts +0 -31
- package/templates/_lib_template/src/lib/interceptors/bridge-defaults.interceptor.ts +0 -53
- package/templates/_lib_template/src/lib/interceptors/content-type.interceptor.ts +0 -49
- package/templates/_lib_template/src/lib/interceptors/singleflight.interceptor.ts +0 -55
- package/templates/_lib_template/src/lib/provide-bridge.ts +0 -170
- package/tools/build.js +0 -1
- package/tools/dev.js +0 -1
- package/tools/domain/paths.js +0 -10
- package/tools/generate.js +0 -1
- package/tools/generator/models/oas-contract.js +0 -159
- package/tools/generator/models/openapi-to-models.js +0 -240
- package/tools/generator/models/type-resolver.js +0 -107
- package/tools/generator/models/utils.js +0 -62
- package/tools/infra/dev-support.js +0 -189
- package/tools/infra/generate/bridge.js +0 -212
- package/tools/infra/spec-loader.js +0 -59
- /package/{tools → src}/domain/lib-name.js +0 -0
- /package/{tools/generator → src/generators}/models/handlebars.js +0 -0
- /package/{tools/generator → src/generators}/models/templates/index.hbs +0 -0
- /package/{tools/generator → src/generators}/models/templates/model.hbs +0 -0
- /package/{tools/infra → src/infrastructure}/json.js +0 -0
- /package/{tools/infra → src/infrastructure}/logger.js +0 -0
- /package/templates/{_lib_template → angular-bridge}/ng-package.json +0 -0
- /package/templates/{_lib_template → angular-bridge}/package.json +0 -0
- /package/templates/{_lib_template → angular-bridge}/src/lib/bridge/sse/eventsource-wrapper.ts +0 -0
- /package/templates/{_lib_template → angular-bridge}/src/lib/bridge/sse/mercure-topic.mapper.ts +0 -0
- /package/templates/{_lib_template → angular-bridge}/src/lib/bridge.types.ts +0 -0
- /package/templates/{_lib_template → angular-bridge}/src/lib/interceptors/bridge-debug.interceptor.ts +0 -0
- /package/templates/{_lib_template → angular-bridge}/src/lib/utils/url.ts +0 -0
- /package/templates/{_lib_template → angular-bridge}/src/models/index.ts +0 -0
- /package/templates/{_lib_template → angular-bridge}/tsconfig.lib.json +0 -0
- /package/templates/{_lib_template → angular-bridge}/tsconfig.lib.prod.json +0 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import {EnvironmentProviders, makeEnvironmentProviders} from '@angular/core';
|
|
2
|
+
import {HttpInterceptorFn, provideHttpClient, withFetch, withInterceptors} from '@angular/common/http';
|
|
3
|
+
import {BridgeOptions} from './bridge-options';
|
|
4
|
+
import {BridgeLogger, MercureConnectionMode, MercureTopicMode} from './bridge.types';
|
|
5
|
+
import {createAuthInterceptors} from './interceptors/bearer-auth.interceptor';
|
|
6
|
+
import {bridgeDebugInterceptor} from './interceptors/bridge-debug.interceptor';
|
|
7
|
+
import {bridgeDefaultsInterceptor} from './interceptors/bridge-defaults.interceptor';
|
|
8
|
+
import {contentTypeInterceptor} from './interceptors/content-type.interceptor';
|
|
9
|
+
import {scopeInterceptor} from './interceptors/scoped.interceptor';
|
|
10
|
+
import {createSingleFlightInterceptor} from './interceptors/singleflight.interceptor';
|
|
11
|
+
import {
|
|
12
|
+
API_BASE_URL,
|
|
13
|
+
BRIDGE_DEFAULTS,
|
|
14
|
+
BRIDGE_HTTP_WITH_CREDENTIALS,
|
|
15
|
+
BRIDGE_LOGGER,
|
|
16
|
+
BRIDGE_MERCURE_WITH_CREDENTIALS,
|
|
17
|
+
MERCURE_CONNECTION_MODE,
|
|
18
|
+
MERCURE_HUB_URL,
|
|
19
|
+
MERCURE_MAX_URL_LENGTH,
|
|
20
|
+
MERCURE_TOPIC_MODE,
|
|
21
|
+
} from './tokens';
|
|
22
|
+
|
|
23
|
+
export type {BridgeAuth, BridgeHttpOptions, BridgeMercureOptions, BridgeOptions} from './bridge-options';
|
|
24
|
+
|
|
25
|
+
/** Registers the bridge HTTP client, interceptors, Mercure realtime adapter and configuration tokens. */
|
|
26
|
+
export function provideBridge(options: BridgeOptions): EnvironmentProviders {
|
|
27
|
+
const {
|
|
28
|
+
baseUrl,
|
|
29
|
+
auth,
|
|
30
|
+
http,
|
|
31
|
+
mercure,
|
|
32
|
+
defaults,
|
|
33
|
+
singleFlight = true,
|
|
34
|
+
debug = false,
|
|
35
|
+
extraInterceptors = [],
|
|
36
|
+
} = options;
|
|
37
|
+
|
|
38
|
+
if (!baseUrl) {
|
|
39
|
+
throw new Error("provideBridge(): missing 'baseUrl'");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const resolvedMercureInit: RequestInit = mercure?.init ?? {credentials: 'include' as RequestCredentials};
|
|
43
|
+
const resolvedMercureHubUrl = mercure?.hubUrl;
|
|
44
|
+
const resolvedMercureTopicMode: MercureTopicMode = mercure?.topicMode ?? 'url';
|
|
45
|
+
const resolvedMercureConnectionMode: MercureConnectionMode = mercure?.connectionMode ?? 'auto';
|
|
46
|
+
const resolvedMercureMaxUrlLength = normalizeMercureMaxUrlLength(mercure?.maxUrlLength, 1900);
|
|
47
|
+
const mercureWithCredentials = resolveWithCredentials(resolvedMercureInit);
|
|
48
|
+
const httpWithCredentials = http?.withCredentials ?? mercureWithCredentials;
|
|
49
|
+
|
|
50
|
+
const loggerProvider: BridgeLogger = createBridgeLogger(debug);
|
|
51
|
+
const scopeToBridge = (interceptor: HttpInterceptorFn) => scopeInterceptor(baseUrl, interceptor);
|
|
52
|
+
|
|
53
|
+
const interceptors: HttpInterceptorFn[] = [
|
|
54
|
+
scopeToBridge(contentTypeInterceptor),
|
|
55
|
+
scopeToBridge(bridgeDefaultsInterceptor),
|
|
56
|
+
...createAuthInterceptors(auth, baseUrl),
|
|
57
|
+
...(singleFlight ? [scopeToBridge(createSingleFlightInterceptor())] : []),
|
|
58
|
+
...(debug ? [scopeToBridge(bridgeDebugInterceptor)] : []),
|
|
59
|
+
...extraInterceptors,
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
return makeEnvironmentProviders([
|
|
63
|
+
provideHttpClient(
|
|
64
|
+
withFetch(),
|
|
65
|
+
withInterceptors(interceptors)
|
|
66
|
+
),
|
|
67
|
+
{provide: API_BASE_URL, useValue: baseUrl},
|
|
68
|
+
{provide: BRIDGE_HTTP_WITH_CREDENTIALS, useValue: httpWithCredentials},
|
|
69
|
+
{provide: BRIDGE_MERCURE_WITH_CREDENTIALS, useValue: mercureWithCredentials},
|
|
70
|
+
...(resolvedMercureHubUrl ? [{provide: MERCURE_HUB_URL, useValue: resolvedMercureHubUrl}] : []),
|
|
71
|
+
{provide: MERCURE_TOPIC_MODE, useValue: resolvedMercureTopicMode},
|
|
72
|
+
{provide: MERCURE_CONNECTION_MODE, useValue: resolvedMercureConnectionMode},
|
|
73
|
+
{provide: MERCURE_MAX_URL_LENGTH, useValue: resolvedMercureMaxUrlLength},
|
|
74
|
+
{provide: BRIDGE_DEFAULTS, useValue: defaults ?? {}},
|
|
75
|
+
{provide: BRIDGE_LOGGER, useValue: loggerProvider},
|
|
76
|
+
]);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function createBridgeLogger(debug: boolean): BridgeLogger {
|
|
80
|
+
const noop = () => undefined;
|
|
81
|
+
return {
|
|
82
|
+
debug: debug ? console.debug.bind(console) : noop,
|
|
83
|
+
info: debug ? console.info.bind(console) : noop,
|
|
84
|
+
warn: debug ? console.warn.bind(console) : noop,
|
|
85
|
+
error: console.error.bind(console),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function resolveWithCredentials(init: RequestInit | undefined): boolean {
|
|
90
|
+
if (!init) return false;
|
|
91
|
+
const anyInit = init as RequestInit & {withCredentials?: boolean};
|
|
92
|
+
return anyInit.withCredentials === true || init.credentials === 'include';
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function normalizeMercureMaxUrlLength(input: unknown, fallback: number): number {
|
|
96
|
+
const value = typeof input === 'number' ? Math.floor(input) : fallback;
|
|
97
|
+
return Number.isFinite(value) && value >= 256 ? value : fallback;
|
|
98
|
+
}
|
|
@@ -8,10 +8,16 @@ export const API_BASE_URL = new InjectionToken<string>('API_BASE_URL');
|
|
|
8
8
|
export const MERCURE_HUB_URL = new InjectionToken<string>('MERCURE_HUB_URL');
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* Default credential policy for HTTP requests
|
|
12
|
-
* When `true`, the bridge sets `withCredentials: true` on HTTP calls
|
|
11
|
+
* Default credential policy for HTTP requests.
|
|
12
|
+
* When `true`, the bridge sets `withCredentials: true` on HTTP calls.
|
|
13
13
|
*/
|
|
14
|
-
export const
|
|
14
|
+
export const BRIDGE_HTTP_WITH_CREDENTIALS = new InjectionToken<boolean>('BRIDGE_HTTP_WITH_CREDENTIALS');
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Default credential policy for Mercure EventSource.
|
|
18
|
+
* When `true`, the bridge opens SSE connections with cookies enabled.
|
|
19
|
+
*/
|
|
20
|
+
export const BRIDGE_MERCURE_WITH_CREDENTIALS = new InjectionToken<boolean>('BRIDGE_MERCURE_WITH_CREDENTIALS');
|
|
15
21
|
|
|
16
22
|
export const MERCURE_TOPIC_MODE = new InjectionToken<MercureTopicMode>('MERCURE_TOPIC_MODE');
|
|
17
23
|
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import {Iri} from '../ports/resource-repository.port';
|
|
2
|
+
|
|
3
|
+
export function toIriList(input: Iri | Iri[]): string[] {
|
|
4
|
+
const values = Array.isArray(input) ? input : [input];
|
|
5
|
+
return values.filter((value): value is string => typeof value === 'string' && value.length > 0);
|
|
6
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
type UrlKind = 'absolute' | 'protocol-relative' | 'relative';
|
|
2
|
+
|
|
3
|
+
/** Returns whether a request belongs to the configured API origin and path. */
|
|
4
|
+
export function isRequestWithinBaseUrl(requestUrl: string, baseUrl: string): boolean {
|
|
5
|
+
try {
|
|
6
|
+
const kind = classifyUrl(baseUrl);
|
|
7
|
+
if (kind !== classifyUrl(requestUrl)) return false;
|
|
8
|
+
|
|
9
|
+
const protocol = kind === 'absolute' && baseUrl.toLowerCase().startsWith('http://') ? 'http:' : 'https:';
|
|
10
|
+
const comparisonOrigin = `${protocol}//bridge.invalid`;
|
|
11
|
+
const base = new URL(baseUrl, `${comparisonOrigin}/`);
|
|
12
|
+
const request = new URL(requestUrl, `${comparisonOrigin}/`);
|
|
13
|
+
|
|
14
|
+
if (base.origin !== request.origin) return false;
|
|
15
|
+
|
|
16
|
+
const basePath = trimTrailingSlash(base.pathname);
|
|
17
|
+
return basePath === '/' || request.pathname === basePath || request.pathname.startsWith(`${basePath}/`);
|
|
18
|
+
} catch {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function classifyUrl(url: string): UrlKind {
|
|
24
|
+
if (/^https?:\/\//i.test(url)) return 'absolute';
|
|
25
|
+
if (url.startsWith('//')) return 'protocol-relative';
|
|
26
|
+
return 'relative';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function trimTrailingSlash(pathname: string): string {
|
|
30
|
+
return pathname === '/' ? pathname : pathname.replace(/\/+$/, '') || '/';
|
|
31
|
+
}
|
|
@@ -3,6 +3,8 @@ export * from './lib/bridge.types';
|
|
|
3
3
|
export * from './lib/facades/facade.factory';
|
|
4
4
|
export * from './lib/facades/bridge.facade';
|
|
5
5
|
export * from './lib/facades/resource.facade';
|
|
6
|
+
export * from './lib/facades/facade.interface';
|
|
7
|
+
export * from './lib/ports/realtime.port';
|
|
6
8
|
export * from './lib/ports/resource-repository.port';
|
|
7
9
|
export * from './lib/utils/url';
|
|
8
10
|
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import {HttpClient} from '@angular/common/http';
|
|
2
|
-
import {Observable} from 'rxjs';
|
|
3
|
-
import {toHttpParams} from './query-builder';
|
|
4
|
-
import {buildHttpRequestOptions} from './http-request.options';
|
|
5
|
-
import {
|
|
6
|
-
Collection,
|
|
7
|
-
HttpCallOptions,
|
|
8
|
-
HttpRequestConfig,
|
|
9
|
-
Iri,
|
|
10
|
-
IriRequired,
|
|
11
|
-
Item,
|
|
12
|
-
AnyQuery,
|
|
13
|
-
ResourceRepository,
|
|
14
|
-
} from '../../ports/resource-repository.port';
|
|
15
|
-
import {resolveUrl} from '../../utils/url';
|
|
16
|
-
|
|
17
|
-
export class ApiPlatformRestRepository<T extends Item> implements ResourceRepository<T> {
|
|
18
|
-
constructor(
|
|
19
|
-
private readonly http: HttpClient,
|
|
20
|
-
private readonly apiBase: string,
|
|
21
|
-
private readonly resourcePath: Iri,
|
|
22
|
-
private readonly withCredentialsDefault: boolean,
|
|
23
|
-
) {
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
getCollection$(query?: AnyQuery, opts?: HttpCallOptions): Observable<Collection<T>> {
|
|
27
|
-
const params = toHttpParams(query);
|
|
28
|
-
return this.http.get<Collection<T>>(this.resolveUrl(this.resourcePath), {
|
|
29
|
-
params,
|
|
30
|
-
headers: opts?.headers,
|
|
31
|
-
withCredentials: opts?.withCredentials ?? this.withCredentialsDefault,
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
get$(iri: IriRequired, opts?: HttpCallOptions): Observable<T> {
|
|
36
|
-
return this.http.get<T>(this.resolveUrl(iri), {
|
|
37
|
-
headers: opts?.headers,
|
|
38
|
-
withCredentials: opts?.withCredentials ?? this.withCredentialsDefault,
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
post$(payload: Partial<T>, opts?: HttpCallOptions): Observable<T> {
|
|
43
|
-
return this.http.post<T>(this.resolveUrl(this.resourcePath), payload, {
|
|
44
|
-
headers: opts?.headers,
|
|
45
|
-
withCredentials: opts?.withCredentials ?? this.withCredentialsDefault,
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
patch$(iri: IriRequired, changes: Partial<T>, opts?: HttpCallOptions): Observable<T> {
|
|
50
|
-
return this.http.patch<T>(this.resolveUrl(iri), changes, {
|
|
51
|
-
headers: opts?.headers,
|
|
52
|
-
withCredentials: opts?.withCredentials ?? this.withCredentialsDefault,
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
put$(iri: IriRequired, payload: Partial<T>, opts?: HttpCallOptions): Observable<T> {
|
|
57
|
-
return this.http.put<T>(this.resolveUrl(iri), payload, {
|
|
58
|
-
headers: opts?.headers,
|
|
59
|
-
withCredentials: opts?.withCredentials ?? this.withCredentialsDefault,
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
delete$(iri: IriRequired, opts?: HttpCallOptions): Observable<void> {
|
|
64
|
-
return this.http.delete<void>(this.resolveUrl(iri), {
|
|
65
|
-
headers: opts?.headers,
|
|
66
|
-
withCredentials: opts?.withCredentials ?? this.withCredentialsDefault,
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
request$<R = unknown, B = unknown>(req: HttpRequestConfig<B>): Observable<R> {
|
|
71
|
-
// Low-level escape hatch for non-standard endpoints (custom controllers, uploads, etc.).
|
|
72
|
-
const {method, url} = req;
|
|
73
|
-
|
|
74
|
-
const targetUrl = this.resolveUrl(url ?? this.resourcePath);
|
|
75
|
-
const mergedOptions = buildHttpRequestOptions(req, {withCredentialsDefault: this.withCredentialsDefault});
|
|
76
|
-
return this.http.request<R>(method, targetUrl, mergedOptions as {observe: 'body'});
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
private resolveUrl(path?: Iri): string {
|
|
80
|
-
const effectivePath = path ?? this.resourcePath;
|
|
81
|
-
if (!effectivePath) throw new Error('ApiPlatformRestRepository: missing url and resourcePath');
|
|
82
|
-
return resolveUrl(this.apiBase, effectivePath);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import {HttpRequestConfig} from '../../ports/resource-repository.port';
|
|
2
|
-
import {toHttpParams} from './query-builder';
|
|
3
|
-
|
|
4
|
-
export function buildHttpRequestOptions(
|
|
5
|
-
req: HttpRequestConfig,
|
|
6
|
-
{withCredentialsDefault}: {withCredentialsDefault: boolean}
|
|
7
|
-
): Record<string, unknown> {
|
|
8
|
-
const {query, body, headers, responseType, withCredentials, options = {}} = req;
|
|
9
|
-
const mergedOptions: Record<string, unknown> = {...options};
|
|
10
|
-
|
|
11
|
-
if (headers) mergedOptions['headers'] = headers;
|
|
12
|
-
if (query) mergedOptions['params'] = toHttpParams(query);
|
|
13
|
-
if (body !== undefined) mergedOptions['body'] = body;
|
|
14
|
-
|
|
15
|
-
mergedOptions['responseType'] = (responseType ?? (mergedOptions['responseType'] as any) ?? 'json') as any;
|
|
16
|
-
mergedOptions['withCredentials'] =
|
|
17
|
-
withCredentials ?? (mergedOptions['withCredentials'] as any) ?? withCredentialsDefault;
|
|
18
|
-
mergedOptions['observe'] = 'body';
|
|
19
|
-
|
|
20
|
-
return mergedOptions;
|
|
21
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export class MercureUrlBuilder {
|
|
2
|
-
/**
|
|
3
|
-
* Builds the Mercure hub URL with one `topic=` parameter per topic.
|
|
4
|
-
* The adapter is responsible for canonicalising topics beforehand.
|
|
5
|
-
*/
|
|
6
|
-
build(hubUrl: string, topics: ReadonlySet<string>, lastEventId?: string): string {
|
|
7
|
-
const url = new URL(hubUrl);
|
|
8
|
-
if (lastEventId) {
|
|
9
|
-
url.searchParams.set('lastEventID', lastEventId);
|
|
10
|
-
}
|
|
11
|
-
url.searchParams.delete('topic');
|
|
12
|
-
for (const topic of topics) {
|
|
13
|
-
url.searchParams.append('topic', topic);
|
|
14
|
-
}
|
|
15
|
-
return url.toString();
|
|
16
|
-
}
|
|
17
|
-
}
|