@outfoxx/sunday 1.1.0 → 2.0.0-beta.10
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 +64 -0
- package/build/client-settings.d.ts +22 -0
- package/build/client-settings.js +147 -0
- package/build/client-settings.js.map +1 -0
- package/build/credentials.d.ts +58 -0
- package/build/credentials.js +51 -0
- package/build/credentials.js.map +1 -0
- package/build/event-parser.d.ts +2 -0
- package/build/event-parser.js.map +1 -1
- package/build/fetch-event-source.d.ts +15 -6
- package/build/fetch-event-source.js +109 -44
- package/build/fetch-event-source.js.map +1 -1
- package/build/fetch-oauth-token-provider.d.ts +28 -0
- package/build/fetch-oauth-token-provider.js +171 -0
- package/build/fetch-oauth-token-provider.js.map +1 -0
- package/build/{fetch-request-factory.d.ts → fetch-transport.d.ts} +15 -7
- package/build/{fetch-request-factory.js → fetch-transport.js} +95 -31
- package/build/fetch-transport.js.map +1 -0
- package/build/fetch.js +3 -2
- package/build/fetch.js.map +1 -1
- package/build/index.d.ts +15 -3
- package/build/index.js +15 -3
- package/build/index.js.map +1 -1
- package/build/media-type-codecs/cbor-encoder.d.ts +2 -2
- package/build/media-type-codecs/cbor-encoder.js +2 -2
- package/build/media-type-codecs/cbor-encoder.js.map +1 -1
- package/build/media-type-codecs/json-encoder.d.ts +3 -3
- package/build/media-type-codecs/json-encoder.js +4 -4
- package/build/media-type-codecs/json-encoder.js.map +1 -1
- package/build/media-type-codecs/media-type-encoder.d.ts +3 -3
- package/build/media-type-codecs/media-type-encoder.js.map +1 -1
- package/build/media-type-codecs/www-form-url-encoder.d.ts +2 -2
- package/build/media-type-codecs/www-form-url-encoder.js +2 -2
- package/build/media-type-codecs/www-form-url-encoder.js.map +1 -1
- package/build/model-construction.d.ts +5 -0
- package/build/model-construction.js +40 -0
- package/build/model-construction.js.map +1 -0
- package/build/model-schema.d.ts +9 -0
- package/build/model-schema.js +131 -0
- package/build/model-schema.js.map +1 -0
- package/build/oauth-wire.d.ts +33 -0
- package/build/oauth-wire.js +143 -0
- package/build/oauth-wire.js.map +1 -0
- package/build/operation-response.d.ts +33 -0
- package/build/operation-response.js +140 -0
- package/build/operation-response.js.map +1 -0
- package/build/operation.d.ts +64 -0
- package/build/operation.js +90 -0
- package/build/operation.js.map +1 -0
- package/build/problem.js +2 -1
- package/build/problem.js.map +1 -1
- package/build/request-adapters.d.ts +5 -5
- package/build/request-adapters.js +3 -3
- package/build/request-adapters.js.map +1 -1
- package/build/request-security.d.ts +16 -0
- package/build/request-security.js +167 -0
- package/build/request-security.js.map +1 -0
- package/build/request-validation-error.d.ts +4 -0
- package/build/request-validation-error.js +21 -0
- package/build/request-validation-error.js.map +1 -0
- package/build/schema-builtins.js +11 -21
- package/build/schema-builtins.js.map +1 -1
- package/build/schema-runtime.d.ts +21 -3
- package/build/schema-runtime.js +12 -3
- package/build/schema-runtime.js.map +1 -1
- package/build/security-binding.d.ts +22 -0
- package/build/{result-response.js → security-binding.js} +1 -1
- package/build/security-binding.js.map +1 -0
- package/build/streaming-body.d.ts +21 -0
- package/build/streaming-body.js +65 -0
- package/build/streaming-body.js.map +1 -0
- package/build/token-manager.d.ts +33 -0
- package/build/token-manager.js +199 -0
- package/build/token-manager.js.map +1 -0
- package/build/token-provider.d.ts +44 -0
- package/build/token-provider.js +31 -0
- package/build/token-provider.js.map +1 -0
- package/build/{request-factory.d.ts → transport.d.ts} +13 -8
- package/build/{request-factory.js → transport.js} +1 -1
- package/build/transport.js.map +1 -0
- package/build/unknown-variant.d.ts +12 -0
- package/build/unknown-variant.js +45 -0
- package/build/unknown-variant.js.map +1 -0
- package/build/url-template.d.ts +3 -0
- package/build/url-template.js +30 -2
- package/build/url-template.js.map +1 -1
- package/build/util/base64.d.ts +4 -0
- package/build/util/base64.js +46 -0
- package/build/util/base64.js.map +1 -0
- package/package.json +6 -2
- package/build/fetch-request-factory.js.map +0 -1
- package/build/request-factory.js.map +0 -1
- package/build/result-response.d.ts +0 -4
- package/build/result-response.js.map +0 -1
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** Acquisition endpoints selected by generation; deployment overrides never select another profile. */
|
|
2
|
+
export interface SecurityEndpoints {
|
|
3
|
+
readonly discoveryUrl?: string;
|
|
4
|
+
readonly authorizationUrl?: string;
|
|
5
|
+
readonly tokenUrl?: string;
|
|
6
|
+
readonly refreshUrl?: string;
|
|
7
|
+
}
|
|
8
|
+
/** One logical scheme in the complete alternative selected for an operation. */
|
|
9
|
+
export interface SecurityBinding extends SecurityEndpoints {
|
|
10
|
+
readonly scheme: string;
|
|
11
|
+
readonly provider: string;
|
|
12
|
+
readonly profile?: string;
|
|
13
|
+
readonly flow: 'clientCredentials' | 'authorizationCode' | 'external' | 'static';
|
|
14
|
+
readonly scopes: readonly string[];
|
|
15
|
+
readonly audience?: string;
|
|
16
|
+
readonly resource?: string;
|
|
17
|
+
readonly transport: {
|
|
18
|
+
readonly location: 'header' | 'query' | 'cookie';
|
|
19
|
+
readonly name: string;
|
|
20
|
+
readonly prefix?: string;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-binding.js","sourceRoot":"","sources":["../src/security-binding.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,EAAE;AACF,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,gDAAgD;AAChD,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Binary chunk values supported by streaming request bodies. */
|
|
2
|
+
export type StreamingBodyChunk = ArrayBuffer | Uint8Array;
|
|
3
|
+
/** Creates a fresh async byte sequence for a streaming request body. */
|
|
4
|
+
export type StreamingBodyBytesFactory = () => AsyncIterable<StreamingBodyChunk>;
|
|
5
|
+
/** Creates a fresh web readable stream for a streaming request body. */
|
|
6
|
+
export type StreamingBodyStreamFactory = () => ReadableStream<Uint8Array>;
|
|
7
|
+
/** A lazily-created request body for streaming uploads. */
|
|
8
|
+
export declare class StreamingBody {
|
|
9
|
+
private readonly createBody;
|
|
10
|
+
private constructor();
|
|
11
|
+
/** Creates a streaming body from a reusable web platform `Blob`. */
|
|
12
|
+
static blob(blob: Blob): StreamingBody;
|
|
13
|
+
/** Creates a streaming body from a fresh web `ReadableStream` factory. */
|
|
14
|
+
static stream(factory: StreamingBodyStreamFactory): StreamingBody;
|
|
15
|
+
/** Creates a streaming body from a fresh async byte iterable factory. */
|
|
16
|
+
static bytes(factory: StreamingBodyBytesFactory): StreamingBody;
|
|
17
|
+
/** Creates the web platform body value consumed by `fetch`. */
|
|
18
|
+
toBodyInit(): BodyInit;
|
|
19
|
+
}
|
|
20
|
+
/** Returns true when a value is a Sunday streaming request body. */
|
|
21
|
+
export declare function isStreamingBody(value: unknown): value is StreamingBody;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// Copyright 2020 Outfox, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
/** A lazily-created request body for streaming uploads. */
|
|
15
|
+
export class StreamingBody {
|
|
16
|
+
createBody;
|
|
17
|
+
constructor(createBody) {
|
|
18
|
+
this.createBody = createBody;
|
|
19
|
+
}
|
|
20
|
+
/** Creates a streaming body from a reusable web platform `Blob`. */
|
|
21
|
+
static blob(blob) {
|
|
22
|
+
return new StreamingBody(() => blob);
|
|
23
|
+
}
|
|
24
|
+
/** Creates a streaming body from a fresh web `ReadableStream` factory. */
|
|
25
|
+
static stream(factory) {
|
|
26
|
+
return new StreamingBody(factory);
|
|
27
|
+
}
|
|
28
|
+
/** Creates a streaming body from a fresh async byte iterable factory. */
|
|
29
|
+
static bytes(factory) {
|
|
30
|
+
return new StreamingBody(() => asyncBytesToReadableStream(factory()));
|
|
31
|
+
}
|
|
32
|
+
/** Creates the web platform body value consumed by `fetch`. */
|
|
33
|
+
toBodyInit() {
|
|
34
|
+
return this.createBody();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** Returns true when a value is a Sunday streaming request body. */
|
|
38
|
+
export function isStreamingBody(value) {
|
|
39
|
+
return value instanceof StreamingBody;
|
|
40
|
+
}
|
|
41
|
+
function asyncBytesToReadableStream(bytes) {
|
|
42
|
+
const iterator = bytes[Symbol.asyncIterator]();
|
|
43
|
+
return new ReadableStream({
|
|
44
|
+
async pull(controller) {
|
|
45
|
+
try {
|
|
46
|
+
const next = await iterator.next();
|
|
47
|
+
if (next.done === true) {
|
|
48
|
+
controller.close();
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
controller.enqueue(toUint8Array(next.value));
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
controller.error(error);
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
async cancel(reason) {
|
|
58
|
+
await iterator.return?.(reason);
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
function toUint8Array(chunk) {
|
|
63
|
+
return chunk instanceof Uint8Array ? chunk : new Uint8Array(chunk);
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=streaming-body.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streaming-body.js","sourceRoot":"","sources":["../src/streaming-body.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,EAAE;AACF,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,gDAAgD;AAChD,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAWjC,2DAA2D;AAC3D,MAAM,OAAO,aAAa;IAEL;IADnB,YACmB,UAA0B;QAA1B,eAAU,GAAV,UAAU,CAAgB;IAE7C,CAAC;IAED,oEAAoE;IACpE,MAAM,CAAC,IAAI,CAAC,IAAU;QACpB,OAAO,IAAI,aAAa,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IACvC,CAAC;IAED,0EAA0E;IAC1E,MAAM,CAAC,MAAM,CAAC,OAAmC;QAC/C,OAAO,IAAI,aAAa,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;IAED,yEAAyE;IACzE,MAAM,CAAC,KAAK,CAAC,OAAkC;QAC7C,OAAO,IAAI,aAAa,CAAC,GAAG,EAAE,CAAC,0BAA0B,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACxE,CAAC;IAED,+DAA+D;IAC/D,UAAU;QACR,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC;IAC3B,CAAC;CACF;AAED,oEAAoE;AACpE,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,OAAO,KAAK,YAAY,aAAa,CAAC;AACxC,CAAC;AAED,SAAS,0BAA0B,CACjC,KAAwC;IAExC,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;IAE/C,OAAO,IAAI,cAAc,CAAa;QACpC,KAAK,CAAC,IAAI,CAAC,UAAU;YACnB,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACnC,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;oBACvB,UAAU,CAAC,KAAK,EAAE,CAAC;oBACnB,OAAO;gBACT,CAAC;gBACD,UAAU,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;YAC/C,CAAC;YACD,OAAO,KAAK,EAAE,CAAC;gBACb,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,MAAM;YACjB,MAAM,QAAQ,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC;QAClC,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,SAAS,YAAY,CAAC,KAAyB;IAC7C,OAAO,KAAK,YAAY,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;AACrE,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { SecurityBinding } from './security-binding.js';
|
|
2
|
+
import { TokenProvider, TokenSet, TokenStore } from './token-provider.js';
|
|
3
|
+
/** A credential receipt used for conditional invalidation after an invalid-token response. */
|
|
4
|
+
export interface TokenLease {
|
|
5
|
+
readonly key: string;
|
|
6
|
+
readonly tokens: TokenSet;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Shared token lifecycle with one renewal per cache key. Canceling one caller leaves other waiters
|
|
10
|
+
* running; canceling the last waiter signals the provider. A failed renewal is never cached.
|
|
11
|
+
*/
|
|
12
|
+
export declare class TokenManager {
|
|
13
|
+
private readonly providers;
|
|
14
|
+
private readonly store;
|
|
15
|
+
private readonly renewals;
|
|
16
|
+
private readonly authorizationAttempts;
|
|
17
|
+
private readonly locks;
|
|
18
|
+
private readonly now;
|
|
19
|
+
private readonly skew;
|
|
20
|
+
constructor(providers: Readonly<Record<string, TokenProvider>>, options?: {
|
|
21
|
+
store?: TokenStore;
|
|
22
|
+
expirySkewMs?: number;
|
|
23
|
+
now?: () => number;
|
|
24
|
+
});
|
|
25
|
+
/** Acquires current credentials without invoking authorization twice for an expired interactive session. */
|
|
26
|
+
credentials(binding: SecurityBinding, signal?: AbortSignal): Promise<TokenLease>;
|
|
27
|
+
/** Invalidates only the credential that failed, preserving a token already renewed by another caller. */
|
|
28
|
+
invalidate(lease: TokenLease): Promise<void>;
|
|
29
|
+
private exclusive;
|
|
30
|
+
private renew;
|
|
31
|
+
private acquireOrRefresh;
|
|
32
|
+
private join;
|
|
33
|
+
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
// Copyright 2020 Outfox, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
import { AuthorizationRequiredError, TokenProviderError, } from './token-provider.js';
|
|
15
|
+
/**
|
|
16
|
+
* Shared token lifecycle with one renewal per cache key. Canceling one caller leaves other waiters
|
|
17
|
+
* running; canceling the last waiter signals the provider. A failed renewal is never cached.
|
|
18
|
+
*/
|
|
19
|
+
export class TokenManager {
|
|
20
|
+
providers;
|
|
21
|
+
store;
|
|
22
|
+
renewals = new Map();
|
|
23
|
+
authorizationAttempts = new Set();
|
|
24
|
+
locks = new Map();
|
|
25
|
+
now;
|
|
26
|
+
skew;
|
|
27
|
+
constructor(providers, options = {}) {
|
|
28
|
+
this.providers = new Map(Object.entries(providers));
|
|
29
|
+
this.store = options.store ?? new MemoryTokenStore();
|
|
30
|
+
this.now = options.now ?? Date.now;
|
|
31
|
+
this.skew = options.expirySkewMs ?? 30_000;
|
|
32
|
+
if (!Number.isFinite(this.skew) || this.skew < 0)
|
|
33
|
+
throw new RangeError('Invalid token expiry skew');
|
|
34
|
+
}
|
|
35
|
+
/** Acquires current credentials without invoking authorization twice for an expired interactive session. */
|
|
36
|
+
async credentials(binding, signal) {
|
|
37
|
+
signal?.throwIfAborted();
|
|
38
|
+
const provider = this.providers.get(binding.provider);
|
|
39
|
+
if (!provider)
|
|
40
|
+
throw new TokenProviderError();
|
|
41
|
+
let configuration;
|
|
42
|
+
try {
|
|
43
|
+
configuration = provider.configure(binding);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
throw new TokenProviderError();
|
|
47
|
+
}
|
|
48
|
+
if (!provider.identity.trim() || !configuration.clientIdentity.trim() ||
|
|
49
|
+
(binding.flow === 'authorizationCode' && !configuration.grantIdentity?.trim()))
|
|
50
|
+
throw new TokenProviderError();
|
|
51
|
+
const request = Object.freeze({
|
|
52
|
+
...binding,
|
|
53
|
+
discoveryUrl: configuration.endpoints?.discoveryUrl ?? binding.discoveryUrl,
|
|
54
|
+
authorizationUrl: configuration.endpoints?.authorizationUrl ?? binding.authorizationUrl,
|
|
55
|
+
tokenUrl: configuration.endpoints?.tokenUrl ?? binding.tokenUrl,
|
|
56
|
+
refreshUrl: configuration.endpoints?.refreshUrl ?? binding.refreshUrl,
|
|
57
|
+
clientIdentity: configuration.clientIdentity,
|
|
58
|
+
grantIdentity: configuration.grantIdentity,
|
|
59
|
+
scopes: Object.freeze([...new Set(binding.scopes)].sort(compareScopes)),
|
|
60
|
+
transport: Object.freeze({ ...binding.transport }),
|
|
61
|
+
});
|
|
62
|
+
const key = JSON.stringify([
|
|
63
|
+
request.scheme, binding.provider, provider.identity, request.clientIdentity, request.grantIdentity,
|
|
64
|
+
request.profile, request.flow, request.discoveryUrl, request.authorizationUrl, request.tokenUrl,
|
|
65
|
+
request.refreshUrl, request.scopes, request.audience, request.resource,
|
|
66
|
+
]);
|
|
67
|
+
let renewal = this.renewals.get(key);
|
|
68
|
+
if (!renewal || renewal.controller.signal.aborted) {
|
|
69
|
+
const controller = new AbortController();
|
|
70
|
+
const created = {
|
|
71
|
+
controller, waiters: 0, settled: false, committing: false,
|
|
72
|
+
promise: this.exclusive(key, () => this.renew(key, provider, request, controller.signal)),
|
|
73
|
+
};
|
|
74
|
+
this.renewals.set(key, created);
|
|
75
|
+
void created.promise.finally(() => {
|
|
76
|
+
created.settled = true;
|
|
77
|
+
if (this.renewals.get(key) === created)
|
|
78
|
+
this.renewals.delete(key);
|
|
79
|
+
}).catch(() => undefined);
|
|
80
|
+
renewal = created;
|
|
81
|
+
}
|
|
82
|
+
return this.join(renewal, signal);
|
|
83
|
+
}
|
|
84
|
+
/** Invalidates only the credential that failed, preserving a token already renewed by another caller. */
|
|
85
|
+
async invalidate(lease) {
|
|
86
|
+
try {
|
|
87
|
+
await this.exclusive(lease.key, async () => {
|
|
88
|
+
const current = await this.store.load(lease.key);
|
|
89
|
+
if (current?.accessToken === lease.tokens.accessToken) {
|
|
90
|
+
await this.store.save(lease.key, Object.freeze({ ...current, expiresAt: 0 }));
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
throw new TokenProviderError();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
exclusive(key, action) {
|
|
99
|
+
const prior = this.locks.get(key) ?? Promise.resolve();
|
|
100
|
+
const next = prior.catch(() => undefined).then(action);
|
|
101
|
+
this.locks.set(key, next);
|
|
102
|
+
void next.finally(() => {
|
|
103
|
+
if (this.locks.get(key) === next)
|
|
104
|
+
this.locks.delete(key);
|
|
105
|
+
}).catch(() => undefined);
|
|
106
|
+
return next;
|
|
107
|
+
}
|
|
108
|
+
async renew(key, provider, request, signal) {
|
|
109
|
+
try {
|
|
110
|
+
signal.throwIfAborted();
|
|
111
|
+
const stored = await this.store.load(key);
|
|
112
|
+
signal.throwIfAborted();
|
|
113
|
+
if (stored && (stored.expiresAt === undefined || stored.expiresAt > this.now() + this.skew)) {
|
|
114
|
+
return { key, tokens: Object.freeze({ ...stored }) };
|
|
115
|
+
}
|
|
116
|
+
const tokens = await this.acquireOrRefresh(key, stored, provider, request, signal);
|
|
117
|
+
if (!tokens.accessToken || (tokens.expiresAt !== undefined &&
|
|
118
|
+
(!Number.isFinite(tokens.expiresAt) || tokens.expiresAt <= this.now())))
|
|
119
|
+
throw new TokenProviderError();
|
|
120
|
+
const snapshot = Object.freeze({ ...tokens });
|
|
121
|
+
signal.throwIfAborted();
|
|
122
|
+
const renewal = this.renewals.get(key);
|
|
123
|
+
if (renewal?.controller.signal !== signal)
|
|
124
|
+
throw new DOMException('Renewal expired', 'AbortError');
|
|
125
|
+
// Once persistence begins, cancellation must not discard a rotated refresh token.
|
|
126
|
+
renewal.committing = true;
|
|
127
|
+
await this.store.save(key, snapshot);
|
|
128
|
+
return { key, tokens: snapshot };
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
if (signal.aborted)
|
|
132
|
+
throw signal.reason;
|
|
133
|
+
if (error instanceof AuthorizationRequiredError || error instanceof TokenProviderError)
|
|
134
|
+
throw error;
|
|
135
|
+
throw new TokenProviderError();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
async acquireOrRefresh(key, stored, provider, request, signal) {
|
|
139
|
+
if (stored?.refreshToken && provider.refresh) {
|
|
140
|
+
try {
|
|
141
|
+
const refreshed = await provider.refresh(request, stored.refreshToken, signal);
|
|
142
|
+
return { ...refreshed, refreshToken: refreshed.refreshToken ?? stored.refreshToken };
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
if (!(error instanceof TokenProviderError) || error.reason !== 'invalidGrant' || request.flow !== 'clientCredentials')
|
|
146
|
+
throw error;
|
|
147
|
+
signal.throwIfAborted();
|
|
148
|
+
await this.store.remove(key);
|
|
149
|
+
return provider.acquire(request, signal);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
else if (request.flow === 'authorizationCode' && (stored || this.authorizationAttempts.has(key))) {
|
|
153
|
+
throw new AuthorizationRequiredError();
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
if (request.flow === 'authorizationCode')
|
|
157
|
+
this.authorizationAttempts.add(key);
|
|
158
|
+
return provider.acquire(request, signal);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
join(renewal, signal) {
|
|
162
|
+
renewal.waiters++;
|
|
163
|
+
return new Promise((resolve, reject) => {
|
|
164
|
+
let completed = false;
|
|
165
|
+
const finish = (value, error) => {
|
|
166
|
+
if (completed)
|
|
167
|
+
return;
|
|
168
|
+
completed = true;
|
|
169
|
+
signal?.removeEventListener('abort', abort);
|
|
170
|
+
renewal.waiters--;
|
|
171
|
+
if (renewal.waiters === 0 && !renewal.settled && !renewal.committing)
|
|
172
|
+
renewal.controller.abort();
|
|
173
|
+
if (value)
|
|
174
|
+
resolve(value);
|
|
175
|
+
else
|
|
176
|
+
reject(error);
|
|
177
|
+
};
|
|
178
|
+
const abort = () => finish(undefined, signal?.reason);
|
|
179
|
+
signal?.addEventListener('abort', abort, { once: true });
|
|
180
|
+
if (signal?.aborted)
|
|
181
|
+
abort();
|
|
182
|
+
renewal.promise.then(value => finish(value), error => finish(undefined, error));
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
class MemoryTokenStore {
|
|
187
|
+
tokens = new Map();
|
|
188
|
+
load(key) { return Promise.resolve(this.tokens.get(key)); }
|
|
189
|
+
save(key, tokens) { this.tokens.set(key, tokens); return Promise.resolve(); }
|
|
190
|
+
remove(key) { this.tokens.delete(key); return Promise.resolve(); }
|
|
191
|
+
}
|
|
192
|
+
function compareScopes(left, right) {
|
|
193
|
+
if (left < right)
|
|
194
|
+
return -1;
|
|
195
|
+
if (left > right)
|
|
196
|
+
return 1;
|
|
197
|
+
return 0;
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=token-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-manager.js","sourceRoot":"","sources":["../src/token-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { SecurityBinding, SecurityEndpoints } from './security-binding.js';
|
|
2
|
+
/** Credentials returned by an application provider; values are never included in runtime diagnostics. */
|
|
3
|
+
export interface TokenSet {
|
|
4
|
+
readonly accessToken: string;
|
|
5
|
+
readonly expiresAt?: number;
|
|
6
|
+
readonly refreshToken?: string;
|
|
7
|
+
}
|
|
8
|
+
/** Non-secret identities isolate cache entries; grantIdentity must change with session or grant inputs. */
|
|
9
|
+
export interface TokenConfiguration {
|
|
10
|
+
readonly clientIdentity: string;
|
|
11
|
+
readonly grantIdentity?: string;
|
|
12
|
+
readonly endpoints?: SecurityEndpoints;
|
|
13
|
+
}
|
|
14
|
+
/** Fully selected acquisition parameters; this contains neither client secrets nor authorization codes. */
|
|
15
|
+
export interface TokenRequest extends SecurityBinding {
|
|
16
|
+
readonly clientIdentity: string;
|
|
17
|
+
readonly grantIdentity?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Application credential binding. OAuth providers exchange fresh authorization and refresh tokens;
|
|
21
|
+
* the shared manager owns caching, rotation, renewal coalescing, and cancellation.
|
|
22
|
+
*/
|
|
23
|
+
export interface TokenProvider {
|
|
24
|
+
readonly identity: string;
|
|
25
|
+
configure(binding: SecurityBinding): TokenConfiguration;
|
|
26
|
+
acquire(request: TokenRequest, signal: AbortSignal): Promise<TokenSet>;
|
|
27
|
+
refresh?(request: TokenRequest, refreshToken: string, signal: AbortSignal): Promise<TokenSet>;
|
|
28
|
+
}
|
|
29
|
+
/** Application-owned storage. Implementations must serialize writes and keep credentials private. */
|
|
30
|
+
export interface TokenStore {
|
|
31
|
+
load(key: string): Promise<TokenSet | undefined>;
|
|
32
|
+
save(key: string, tokens: TokenSet): Promise<void>;
|
|
33
|
+
remove(key: string): Promise<void>;
|
|
34
|
+
}
|
|
35
|
+
/** Signals that an interactive application must supply a fresh authorization session. */
|
|
36
|
+
export declare class AuthorizationRequiredError extends Error {
|
|
37
|
+
constructor();
|
|
38
|
+
}
|
|
39
|
+
/** Safe provider failure without a provider's potentially credential-bearing error message. */
|
|
40
|
+
export declare class TokenProviderError extends Error {
|
|
41
|
+
readonly reason: 'unavailable' | 'temporary' | 'invalidGrant';
|
|
42
|
+
/** Safe recovery classification; provider messages and credentials are never retained. */
|
|
43
|
+
constructor(reason?: 'unavailable' | 'temporary' | 'invalidGrant');
|
|
44
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Copyright 2020 Outfox, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
/** Signals that an interactive application must supply a fresh authorization session. */
|
|
15
|
+
export class AuthorizationRequiredError extends Error {
|
|
16
|
+
constructor() {
|
|
17
|
+
super('Fresh application authorization is required');
|
|
18
|
+
this.name = 'AuthorizationRequiredError';
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/** Safe provider failure without a provider's potentially credential-bearing error message. */
|
|
22
|
+
export class TokenProviderError extends Error {
|
|
23
|
+
reason;
|
|
24
|
+
/** Safe recovery classification; provider messages and credentials are never retained. */
|
|
25
|
+
constructor(reason = 'unavailable') {
|
|
26
|
+
super('The credential provider could not supply usable credentials');
|
|
27
|
+
this.reason = reason;
|
|
28
|
+
this.name = 'TokenProviderError';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=token-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-provider.js","sourceRoot":"","sources":["../src/token-provider.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,EAAE;AACF,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,gDAAgD;AAChD,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AA0CjC,yFAAyF;AACzF,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IACnD;QACE,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACrD,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAC;IAC3C,CAAC;CACF;AAED,+FAA+F;AAC/F,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAEtB;IADrB,0FAA0F;IAC1F,YAAqB,SAAuD,aAAa;QACvF,KAAK,CAAC,6DAA6D,CAAC,CAAC;QADlD,WAAM,GAAN,MAAM,CAA8D;QAEvF,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF"}
|
|
@@ -1,18 +1,19 @@
|
|
|
1
|
+
import { SecurityBinding } from './security-binding.js';
|
|
1
2
|
import { MediaType } from './media-type.js';
|
|
2
3
|
import { TextMediaTypeDecoder } from './media-type-codecs/media-type-decoder.js';
|
|
3
4
|
import { Problem } from './problem.js';
|
|
4
|
-
import {
|
|
5
|
+
import { OperationResponse } from './operation-response.js';
|
|
5
6
|
import { SchemaLike } from './schema-runtime.js';
|
|
6
7
|
import { URLTemplate } from './url-template.js';
|
|
7
8
|
import { Logger } from './logger.js';
|
|
8
|
-
export interface
|
|
9
|
+
export interface Transport<NativeRequest = Request> {
|
|
9
10
|
readonly baseUrl: URLTemplate;
|
|
10
11
|
registerProblem(type: URL | string, problemType: SchemaLike<Problem>): void;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
transportRequest(requestSpec: RequestSpec<unknown>): Promise<NativeRequest>;
|
|
13
|
+
transportResponse(request: NativeRequest, dataExpected?: boolean): Promise<Response>;
|
|
14
|
+
transportResponse<B>(requestSpec: RequestSpec<B>, dataExpected?: boolean): Promise<Response>;
|
|
15
|
+
response<B, R>(requestSpec: RequestSpec<B>, resultType: SchemaLike<R>): Promise<OperationResponse<R>>;
|
|
16
|
+
response<B>(requestSpec: RequestSpec<B>): Promise<OperationResponse<void>>;
|
|
16
17
|
result<B, R>(requestSpec: RequestSpec<B>, resultType: SchemaLike<R>): Promise<R>;
|
|
17
18
|
result<B>(requestSpec: RequestSpec<B>): Promise<void>;
|
|
18
19
|
eventSource(requestSpec: RequestSpec<void>): ExtEventSource;
|
|
@@ -29,11 +30,15 @@ export interface RequestSpec<B> {
|
|
|
29
30
|
queryParameters?: Record<string, unknown>;
|
|
30
31
|
body?: B;
|
|
31
32
|
bodyType?: SchemaLike<B>;
|
|
33
|
+
/** Revalidates typed parameters on every request build, before wire conversion. */
|
|
34
|
+
parameterValidation?: () => void;
|
|
32
35
|
contentTypes?: MediaType[];
|
|
33
36
|
acceptTypes?: MediaType[];
|
|
34
37
|
headers?: Record<string, unknown>;
|
|
35
38
|
signal?: AbortSignal;
|
|
39
|
+
/** Complete, explicitly selected credential bindings for this operation. */
|
|
40
|
+
security?: readonly SecurityBinding[];
|
|
36
41
|
}
|
|
37
42
|
export interface RequestAdapter {
|
|
38
|
-
adapt(
|
|
43
|
+
adapt(transport: Transport, request: Request): Promise<Request>;
|
|
39
44
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,EAAE;AACF,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,gDAAgD;AAChD,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/** Marks a fallback independently of its discriminator or structural fields. */
|
|
3
|
+
export declare const UnknownVariantTag: unique symbol;
|
|
4
|
+
/** An unknown discriminated payload whose original wire fields are preserved. */
|
|
5
|
+
export interface UnknownVariant {
|
|
6
|
+
readonly [UnknownVariantTag]: true;
|
|
7
|
+
readonly rawBody: Readonly<Record<string, unknown>>;
|
|
8
|
+
}
|
|
9
|
+
/** Identifies fallback instances even when their discriminator resembles a known branch. */
|
|
10
|
+
export declare function isUnknownVariant(value: unknown): value is UnknownVariant;
|
|
11
|
+
/** Dispatches encoding by fallback identity while retaining native schema validation. */
|
|
12
|
+
export declare function unionWithUnknown<K extends z.ZodType, U extends z.ZodType<UnknownVariant>>(known: K, unknown: U): z.ZodType<z.output<K> | z.output<U>>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Copyright 2020 Outfox, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
import { z } from 'zod';
|
|
15
|
+
/** Marks a fallback independently of its discriminator or structural fields. */
|
|
16
|
+
export const UnknownVariantTag = Symbol.for('@outfoxx/sunday/UnknownVariant');
|
|
17
|
+
/** Identifies fallback instances even when their discriminator resembles a known branch. */
|
|
18
|
+
export function isUnknownVariant(value) {
|
|
19
|
+
return typeof value === 'object' && value !== null
|
|
20
|
+
&& UnknownVariantTag in value && value[UnknownVariantTag] === true;
|
|
21
|
+
}
|
|
22
|
+
/** Dispatches encoding by fallback identity while retaining native schema validation. */
|
|
23
|
+
export function unionWithUnknown(known, unknown) {
|
|
24
|
+
const wire = z.union([known, unknown]);
|
|
25
|
+
return z.codec(z.unknown(), z.custom(), {
|
|
26
|
+
decode(value, context) {
|
|
27
|
+
const result = wire.safeParse(value);
|
|
28
|
+
if (!result.success) {
|
|
29
|
+
context.issues.push(...result.error.issues.map(issue => ({ ...issue, input: undefined })));
|
|
30
|
+
return z.NEVER;
|
|
31
|
+
}
|
|
32
|
+
return result.data;
|
|
33
|
+
},
|
|
34
|
+
encode(value, context) {
|
|
35
|
+
const schema = isUnknownVariant(value) ? unknown : known;
|
|
36
|
+
const result = schema.safeEncode(value);
|
|
37
|
+
if (!result.success) {
|
|
38
|
+
context.issues.push(...result.error.issues.map(issue => ({ ...issue, input: undefined })));
|
|
39
|
+
return z.NEVER;
|
|
40
|
+
}
|
|
41
|
+
return result.data;
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=unknown-variant.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unknown-variant.js","sourceRoot":"","sources":["../src/unknown-variant.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,EAAE;AACF,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,gDAAgD;AAChD,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,gFAAgF;AAChF,MAAM,CAAC,MAAM,iBAAiB,GAAkB,MAAM,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;AAQ7F,4FAA4F;AAC5F,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;WAC7C,iBAAiB,IAAI,KAAK,IAAI,KAAK,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;AACvE,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,gBAAgB,CAC9B,KAAQ,EACR,OAAU;IAEV,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;IACvC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,MAAM,EAA6B,EAAE;QACjE,MAAM,CAAC,KAAK,EAAE,OAAO;YACnB,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YACrC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACpB,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC;gBAC3F,OAAO,CAAC,CAAC,KAAK,CAAC;YACjB,CAAC;YACD,OAAO,MAAM,CAAC,IAAI,CAAC;QACrB,CAAC;QACD,MAAM,CAAC,KAAK,EAAE,OAAO;YACnB,MAAM,MAAM,GAAc,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;YACpE,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;YACxC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACpB,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC;gBAC3F,OAAO,CAAC,CAAC,KAAK,CAAC;YACjB,CAAC;YACD,OAAO,MAAM,CAAC,IAAI,CAAC;QACrB,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
package/build/url-template.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
/** An RFC 6570 URL template with reusable parameter defaults. */
|
|
1
2
|
export declare class URLTemplate {
|
|
2
3
|
template: string;
|
|
3
4
|
parameters: Record<string, unknown>;
|
|
5
|
+
/** Creates a template whose stored parameters can be overridden for each expansion. */
|
|
4
6
|
constructor(template: string, parameters?: Record<string, unknown>);
|
|
7
|
+
/** Expands base and relative templates, preserving empty values and omitting null or missing values. */
|
|
5
8
|
complete(relativeTemplate: string, parameters: Record<string, unknown>): URL;
|
|
6
9
|
}
|
package/build/url-template.js
CHANGED
|
@@ -11,14 +11,17 @@
|
|
|
11
11
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
// See the License for the specific language governing permissions and
|
|
13
13
|
// limitations under the License.
|
|
14
|
-
import { parse } from 'uri-template';
|
|
14
|
+
import { expandExpression, parse } from 'uri-template';
|
|
15
|
+
/** An RFC 6570 URL template with reusable parameter defaults. */
|
|
15
16
|
export class URLTemplate {
|
|
16
17
|
template;
|
|
17
18
|
parameters;
|
|
19
|
+
/** Creates a template whose stored parameters can be overridden for each expansion. */
|
|
18
20
|
constructor(template, parameters = {}) {
|
|
19
21
|
this.template = template;
|
|
20
22
|
this.parameters = parameters;
|
|
21
23
|
}
|
|
24
|
+
/** Expands base and relative templates, preserving empty values and omitting null or missing values. */
|
|
22
25
|
complete(relativeTemplate, parameters) {
|
|
23
26
|
const allParameters = { ...this.parameters, ...parameters };
|
|
24
27
|
const baseTempl = this.template.endsWith('/')
|
|
@@ -27,7 +30,32 @@ export class URLTemplate {
|
|
|
27
30
|
const relTempl = relativeTemplate.startsWith('/') || !relativeTemplate.length
|
|
28
31
|
? relativeTemplate
|
|
29
32
|
: `/${relativeTemplate}`;
|
|
30
|
-
|
|
33
|
+
const template = parse(baseTempl + relTempl);
|
|
34
|
+
const expanded = template.ast.parts
|
|
35
|
+
.map((part) => {
|
|
36
|
+
if (part.type === 'literal')
|
|
37
|
+
return part.value;
|
|
38
|
+
const value = expandExpression(part, allParameters);
|
|
39
|
+
// uri-template 2 drops the path prefix when defined variables expand to an empty string.
|
|
40
|
+
if (part.operator === '/' &&
|
|
41
|
+
value === '' &&
|
|
42
|
+
part.variables.some((variable) => isDefined(allParameters[variable.name]))) {
|
|
43
|
+
return '/';
|
|
44
|
+
}
|
|
45
|
+
return value;
|
|
46
|
+
})
|
|
47
|
+
.join('');
|
|
48
|
+
return new URL(expanded);
|
|
31
49
|
}
|
|
32
50
|
}
|
|
51
|
+
// RFC 6570 treats empty collections as undefined, but an empty string is defined.
|
|
52
|
+
function isDefined(value) {
|
|
53
|
+
if (value == null)
|
|
54
|
+
return false;
|
|
55
|
+
if (typeof value !== 'object')
|
|
56
|
+
return true;
|
|
57
|
+
if (Array.isArray(value))
|
|
58
|
+
return value.length > 0;
|
|
59
|
+
return Object.values(value).some((entry) => entry != null);
|
|
60
|
+
}
|
|
33
61
|
//# sourceMappingURL=url-template.js.map
|