@astrale-os/shell 0.1.0
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/dist/adapters/iframe.shell-adapter.d.ts +10 -0
- package/dist/adapters/iframe.shell-adapter.d.ts.map +1 -0
- package/dist/adapters/iframe.shell-adapter.js +55 -0
- package/dist/adapters/kernel-client.adapter.d.ts +53 -0
- package/dist/adapters/kernel-client.adapter.d.ts.map +1 -0
- package/dist/adapters/kernel-client.adapter.js +69 -0
- package/dist/adapters/message-port.transport.d.ts +7 -0
- package/dist/adapters/message-port.transport.d.ts.map +1 -0
- package/dist/adapters/message-port.transport.js +42 -0
- package/dist/application/channels/children-channel.d.ts +21 -0
- package/dist/application/channels/children-channel.d.ts.map +1 -0
- package/dist/application/channels/children-channel.js +82 -0
- package/dist/application/channels/observer.d.ts +9 -0
- package/dist/application/channels/observer.d.ts.map +1 -0
- package/dist/application/channels/observer.js +23 -0
- package/dist/application/channels/parent-channel.d.ts +17 -0
- package/dist/application/channels/parent-channel.d.ts.map +1 -0
- package/dist/application/channels/parent-channel.js +21 -0
- package/dist/application/channels/types.d.ts +12 -0
- package/dist/application/channels/types.d.ts.map +1 -0
- package/dist/application/channels/types.js +29 -0
- package/dist/application/intent/pipeline-runner.d.ts +12 -0
- package/dist/application/intent/pipeline-runner.d.ts.map +1 -0
- package/dist/application/intent/pipeline-runner.js +27 -0
- package/dist/application/intent/request.d.ts +34 -0
- package/dist/application/intent/request.d.ts.map +1 -0
- package/dist/application/intent/request.js +70 -0
- package/dist/application/intent/router.d.ts +56 -0
- package/dist/application/intent/router.d.ts.map +1 -0
- package/dist/application/intent/router.js +94 -0
- package/dist/application/kernel-facade.d.ts +33 -0
- package/dist/application/kernel-facade.d.ts.map +1 -0
- package/dist/application/kernel-facade.js +77 -0
- package/dist/application/shell.d.ts +100 -0
- package/dist/application/shell.d.ts.map +1 -0
- package/dist/application/shell.js +256 -0
- package/dist/application/windowing/child-init.d.ts +23 -0
- package/dist/application/windowing/child-init.d.ts.map +1 -0
- package/dist/application/windowing/child-init.js +101 -0
- package/dist/application/windowing/handshake.d.ts +30 -0
- package/dist/application/windowing/handshake.d.ts.map +1 -0
- package/dist/application/windowing/handshake.js +63 -0
- package/dist/application/windowing/lifecycle-controller.d.ts +10 -0
- package/dist/application/windowing/lifecycle-controller.d.ts.map +1 -0
- package/dist/application/windowing/lifecycle-controller.js +30 -0
- package/dist/application/windowing/mount-controller.d.ts +25 -0
- package/dist/application/windowing/mount-controller.d.ts.map +1 -0
- package/dist/application/windowing/mount-controller.js +277 -0
- package/dist/application/windowing/protocol.d.ts +21 -0
- package/dist/application/windowing/protocol.d.ts.map +1 -0
- package/dist/application/windowing/protocol.js +19 -0
- package/dist/application/windowing/token-refresh.d.ts +19 -0
- package/dist/application/windowing/token-refresh.d.ts.map +1 -0
- package/dist/application/windowing/token-refresh.js +60 -0
- package/dist/domain/identity/delegation.d.ts +15 -0
- package/dist/domain/identity/delegation.d.ts.map +1 -0
- package/dist/domain/identity/delegation.js +12 -0
- package/dist/domain/identity/path.d.ts +11 -0
- package/dist/domain/identity/path.d.ts.map +1 -0
- package/dist/domain/identity/path.js +13 -0
- package/dist/domain/identity/resolve-self.d.ts +21 -0
- package/dist/domain/identity/resolve-self.d.ts.map +1 -0
- package/dist/domain/identity/resolve-self.js +36 -0
- package/dist/domain/intent/middleware/capabilities.d.ts +28 -0
- package/dist/domain/intent/middleware/capabilities.d.ts.map +1 -0
- package/dist/domain/intent/middleware/capabilities.js +18 -0
- package/dist/domain/intent/middleware/logging.d.ts +14 -0
- package/dist/domain/intent/middleware/logging.d.ts.map +1 -0
- package/dist/domain/intent/middleware/logging.js +21 -0
- package/dist/domain/intent/middleware/rate-limit.d.ts +20 -0
- package/dist/domain/intent/middleware/rate-limit.d.ts.map +1 -0
- package/dist/domain/intent/middleware/rate-limit.js +33 -0
- package/dist/domain/intent/pipeline.d.ts +3 -0
- package/dist/domain/intent/pipeline.d.ts.map +1 -0
- package/dist/domain/intent/pipeline.js +1 -0
- package/dist/domain/intent/router.d.ts +6 -0
- package/dist/domain/intent/router.d.ts.map +1 -0
- package/dist/domain/intent/router.js +1 -0
- package/dist/domain/message/errors.d.ts +2 -0
- package/dist/domain/message/errors.d.ts.map +1 -0
- package/dist/domain/message/errors.js +1 -0
- package/dist/domain/message/registries.d.ts +145 -0
- package/dist/domain/message/registries.d.ts.map +1 -0
- package/dist/domain/message/registries.js +1 -0
- package/dist/domain/message/types.d.ts +30 -0
- package/dist/domain/message/types.d.ts.map +1 -0
- package/dist/domain/message/types.js +1 -0
- package/dist/domain/window/config.d.ts +26 -0
- package/dist/domain/window/config.d.ts.map +1 -0
- package/dist/domain/window/config.js +1 -0
- package/dist/domain/window/lifecycle.d.ts +27 -0
- package/dist/domain/window/lifecycle.d.ts.map +1 -0
- package/dist/domain/window/lifecycle.js +36 -0
- package/dist/domain/window/window.d.ts +12 -0
- package/dist/domain/window/window.d.ts.map +1 -0
- package/dist/domain/window/window.js +1 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/ports/kernel-client.d.ts +33 -0
- package/dist/ports/kernel-client.d.ts.map +1 -0
- package/dist/ports/kernel-client.js +1 -0
- package/dist/ports/shell-adapter.d.ts +13 -0
- package/dist/ports/shell-adapter.d.ts.map +1 -0
- package/dist/ports/shell-adapter.js +1 -0
- package/dist/ports/transport.d.ts +7 -0
- package/dist/ports/transport.d.ts.map +1 -0
- package/dist/ports/transport.js +1 -0
- package/package.json +41 -0
- package/src/adapters/iframe.shell-adapter.ts +68 -0
- package/src/adapters/kernel-client.adapter.ts +138 -0
- package/src/adapters/message-port.transport.ts +50 -0
- package/src/application/channels/children-channel.ts +112 -0
- package/src/application/channels/observer.ts +33 -0
- package/src/application/channels/parent-channel.ts +43 -0
- package/src/application/channels/types.ts +41 -0
- package/src/application/intent/pipeline-runner.ts +36 -0
- package/src/application/intent/request.ts +87 -0
- package/src/application/intent/router.ts +161 -0
- package/src/application/kernel-facade.ts +143 -0
- package/src/application/shell.ts +433 -0
- package/src/application/windowing/child-init.ts +137 -0
- package/src/application/windowing/handshake.ts +98 -0
- package/src/application/windowing/lifecycle-controller.ts +40 -0
- package/src/application/windowing/mount-controller.ts +335 -0
- package/src/application/windowing/protocol.ts +37 -0
- package/src/application/windowing/token-refresh.ts +78 -0
- package/src/domain/identity/delegation.ts +25 -0
- package/src/domain/identity/path.ts +14 -0
- package/src/domain/identity/resolve-self.ts +38 -0
- package/src/domain/intent/middleware/capabilities.ts +53 -0
- package/src/domain/intent/middleware/logging.ts +45 -0
- package/src/domain/intent/middleware/rate-limit.ts +54 -0
- package/src/domain/intent/pipeline.ts +3 -0
- package/src/domain/intent/router.ts +6 -0
- package/src/domain/message/errors.ts +9 -0
- package/src/domain/message/registries.ts +76 -0
- package/src/domain/message/types.ts +32 -0
- package/src/domain/window/config.ts +28 -0
- package/src/domain/window/lifecycle.ts +39 -0
- package/src/domain/window/window.ts +13 -0
- package/src/index.ts +103 -0
- package/src/ports/kernel-client.ts +32 -0
- package/src/ports/shell-adapter.ts +11 -0
- package/src/ports/transport.ts +7 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { createKernelClientAdapter } from '../../adapters/kernel-client.adapter';
|
|
2
|
+
import { createMessagePortTransport } from '../../adapters/message-port.transport';
|
|
3
|
+
import { createParentChannel } from '../channels/parent-channel';
|
|
4
|
+
import { createDelegationKernelFacade, } from '../kernel-facade';
|
|
5
|
+
import { INIT_REQUEST_TYPE, isInitResponse } from './protocol';
|
|
6
|
+
const DEFAULT_TIMEOUT = 5_000;
|
|
7
|
+
/** Child-side init: post INIT_REQUEST, receive MessagePort + ctrl:handshake, ack. */
|
|
8
|
+
export function performChildInit(params) {
|
|
9
|
+
const { parent } = params;
|
|
10
|
+
const timeoutMs = params.timeoutMs ?? DEFAULT_TIMEOUT;
|
|
11
|
+
return new Promise((resolve, reject) => {
|
|
12
|
+
let port = null;
|
|
13
|
+
const timer = setTimeout(() => {
|
|
14
|
+
cleanup();
|
|
15
|
+
reject(new Error(`Shell child init timed out after ${timeoutMs}ms`));
|
|
16
|
+
}, timeoutMs);
|
|
17
|
+
function cleanup() {
|
|
18
|
+
clearTimeout(timer);
|
|
19
|
+
window.removeEventListener('message', onWindowMessage);
|
|
20
|
+
if (port)
|
|
21
|
+
port.onmessage = null;
|
|
22
|
+
}
|
|
23
|
+
function onHandshake(handshakePort) {
|
|
24
|
+
return (ev) => {
|
|
25
|
+
const msg = ev.data;
|
|
26
|
+
if (!msg || msg.type !== 'ctrl' || msg.action !== 'handshake')
|
|
27
|
+
return;
|
|
28
|
+
const data = msg.data;
|
|
29
|
+
handshakePort.postMessage({
|
|
30
|
+
type: 'ctrl',
|
|
31
|
+
version: 1,
|
|
32
|
+
action: 'handshakeAck',
|
|
33
|
+
data: { windowId: data.windowId },
|
|
34
|
+
});
|
|
35
|
+
cleanup();
|
|
36
|
+
const initialToken = {
|
|
37
|
+
credential: data.delegationToken,
|
|
38
|
+
scope: { functionId: data.functionId },
|
|
39
|
+
issuedAt: Date.now(),
|
|
40
|
+
expiresAt: data.tokenExpiresAt,
|
|
41
|
+
};
|
|
42
|
+
let currentToken = initialToken;
|
|
43
|
+
const adapter = createKernelClientAdapter({
|
|
44
|
+
url: data.kernelUrl,
|
|
45
|
+
schema: params.schema,
|
|
46
|
+
getCredential: () => currentToken.credential,
|
|
47
|
+
mintIdentity: data.mintIdentity,
|
|
48
|
+
});
|
|
49
|
+
const kernel = createDelegationKernelFacade({
|
|
50
|
+
adapter,
|
|
51
|
+
initialToken,
|
|
52
|
+
url: data.kernelUrl,
|
|
53
|
+
mintIdentity: data.mintIdentity,
|
|
54
|
+
onTokenChange: (next) => {
|
|
55
|
+
currentToken = next;
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
resolve({
|
|
59
|
+
windowId: data.windowId,
|
|
60
|
+
functionId: data.functionId,
|
|
61
|
+
kernelUrl: data.kernelUrl,
|
|
62
|
+
targetNodeId: data.targetNodeId,
|
|
63
|
+
mintIdentity: data.mintIdentity,
|
|
64
|
+
initialToken,
|
|
65
|
+
kernel,
|
|
66
|
+
parentChannel: (observer) => {
|
|
67
|
+
const transport = createMessagePortTransport({ port: handshakePort });
|
|
68
|
+
const channel = createParentChannel({ transport, observer });
|
|
69
|
+
channel.on('ctrl', (message) => {
|
|
70
|
+
if (message.action !== 'tokenRefresh')
|
|
71
|
+
return;
|
|
72
|
+
const refresh = message;
|
|
73
|
+
kernel.setToken({
|
|
74
|
+
credential: refresh.data.delegationToken,
|
|
75
|
+
scope: { functionId: data.functionId },
|
|
76
|
+
issuedAt: Date.now(),
|
|
77
|
+
expiresAt: refresh.data.tokenExpiresAt,
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
return channel;
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function onWindowMessage(ev) {
|
|
86
|
+
if (!isInitResponse(ev.data))
|
|
87
|
+
return;
|
|
88
|
+
if (ev.source !== parent)
|
|
89
|
+
return;
|
|
90
|
+
const [receivedPort] = ev.ports;
|
|
91
|
+
if (!receivedPort)
|
|
92
|
+
return;
|
|
93
|
+
port = receivedPort;
|
|
94
|
+
port.onmessage = onHandshake(receivedPort);
|
|
95
|
+
port.start();
|
|
96
|
+
}
|
|
97
|
+
window.addEventListener('message', onWindowMessage);
|
|
98
|
+
// targetOrigin="*" — the parent verifies our event.origin on its side.
|
|
99
|
+
parent.postMessage({ type: INIT_REQUEST_TYPE, version: 1 }, '*');
|
|
100
|
+
});
|
|
101
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type HandshakeParams = {
|
|
2
|
+
readonly iframe: HTMLIFrameElement;
|
|
3
|
+
readonly expectedOrigin: string;
|
|
4
|
+
readonly windowId: string;
|
|
5
|
+
readonly delegationToken: string;
|
|
6
|
+
readonly tokenExpiresAt: number;
|
|
7
|
+
readonly kernelUrl: string;
|
|
8
|
+
readonly functionId: string;
|
|
9
|
+
readonly targetNodeId?: string;
|
|
10
|
+
readonly mintIdentity?: string;
|
|
11
|
+
readonly timeoutMs: number;
|
|
12
|
+
};
|
|
13
|
+
export type HandshakeError = {
|
|
14
|
+
code: 'HANDSHAKE_TIMEOUT';
|
|
15
|
+
message: string;
|
|
16
|
+
} | {
|
|
17
|
+
code: 'ORIGIN_MISMATCH';
|
|
18
|
+
message: string;
|
|
19
|
+
actual: string;
|
|
20
|
+
expected: string;
|
|
21
|
+
} | {
|
|
22
|
+
code: 'HANDSHAKE_FAILED';
|
|
23
|
+
message: string;
|
|
24
|
+
};
|
|
25
|
+
export type HandshakeResult = {
|
|
26
|
+
readonly port: MessagePort;
|
|
27
|
+
};
|
|
28
|
+
/** Parent-side handshake: wait for INIT_REQUEST, transfer a MessagePort, complete ctrl:handshake. */
|
|
29
|
+
export declare function runParentHandshake(params: HandshakeParams): Promise<HandshakeResult>;
|
|
30
|
+
//# sourceMappingURL=handshake.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handshake.d.ts","sourceRoot":"","sources":["../../../src/application/windowing/handshake.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAA;IAClC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC3B,CAAA;AAED,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC9C;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC9E;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AAEjD,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;CAC3B,CAAA;AAED,qGAAqG;AACrG,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,CAsEpF"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { INIT_RESPONSE_TYPE, isInitRequest } from './protocol';
|
|
2
|
+
/** Parent-side handshake: wait for INIT_REQUEST, transfer a MessagePort, complete ctrl:handshake. */
|
|
3
|
+
export function runParentHandshake(params) {
|
|
4
|
+
const { iframe, expectedOrigin, timeoutMs } = params;
|
|
5
|
+
return new Promise((resolve, reject) => {
|
|
6
|
+
let port = null;
|
|
7
|
+
const timer = setTimeout(() => {
|
|
8
|
+
cleanup();
|
|
9
|
+
reject({
|
|
10
|
+
code: 'HANDSHAKE_TIMEOUT',
|
|
11
|
+
message: `handshake timed out after ${timeoutMs}ms`,
|
|
12
|
+
});
|
|
13
|
+
}, timeoutMs);
|
|
14
|
+
function cleanup() {
|
|
15
|
+
clearTimeout(timer);
|
|
16
|
+
window.removeEventListener('message', onInitRequest);
|
|
17
|
+
if (port)
|
|
18
|
+
port.onmessage = null;
|
|
19
|
+
}
|
|
20
|
+
function onInitRequest(event) {
|
|
21
|
+
if (event.source !== iframe.contentWindow)
|
|
22
|
+
return;
|
|
23
|
+
if (!isInitRequest(event.data))
|
|
24
|
+
return;
|
|
25
|
+
if (event.origin !== expectedOrigin) {
|
|
26
|
+
cleanup();
|
|
27
|
+
reject({
|
|
28
|
+
code: 'ORIGIN_MISMATCH',
|
|
29
|
+
message: `expected origin ${expectedOrigin}, got ${event.origin}`,
|
|
30
|
+
actual: event.origin,
|
|
31
|
+
expected: expectedOrigin,
|
|
32
|
+
});
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const channel = new MessageChannel();
|
|
36
|
+
port = channel.port1;
|
|
37
|
+
port.onmessage = (ev) => {
|
|
38
|
+
const msg = ev.data;
|
|
39
|
+
if (msg && msg.type === 'ctrl' && msg.action === 'handshakeAck') {
|
|
40
|
+
cleanup();
|
|
41
|
+
resolve({ port: channel.port1 });
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
port.start();
|
|
45
|
+
iframe.contentWindow?.postMessage({ type: INIT_RESPONSE_TYPE, version: 1, windowId: params.windowId }, expectedOrigin, [channel.port2]);
|
|
46
|
+
port.postMessage({
|
|
47
|
+
type: 'ctrl',
|
|
48
|
+
version: 1,
|
|
49
|
+
action: 'handshake',
|
|
50
|
+
data: {
|
|
51
|
+
delegationToken: params.delegationToken,
|
|
52
|
+
tokenExpiresAt: params.tokenExpiresAt,
|
|
53
|
+
windowId: params.windowId,
|
|
54
|
+
kernelUrl: params.kernelUrl,
|
|
55
|
+
functionId: params.functionId,
|
|
56
|
+
targetNodeId: params.targetNodeId,
|
|
57
|
+
mintIdentity: params.mintIdentity,
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
window.addEventListener('message', onInitRequest);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { WindowState } from '../../domain/window/window';
|
|
2
|
+
import { type LifecycleEvent } from '../../domain/window/lifecycle';
|
|
3
|
+
export interface LifecycleController {
|
|
4
|
+
register(windowId: string, initial?: WindowState): void;
|
|
5
|
+
apply(windowId: string, event: LifecycleEvent): WindowState | null;
|
|
6
|
+
markCrashed(windowId: string): void;
|
|
7
|
+
remove(windowId: string): void;
|
|
8
|
+
}
|
|
9
|
+
export declare function createLifecycleController(): LifecycleController;
|
|
10
|
+
//# sourceMappingURL=lifecycle-controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle-controller.d.ts","sourceRoot":"","sources":["../../../src/application/windowing/lifecycle-controller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;AAE7D,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAE/E,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,IAAI,CAAA;IACvD,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,WAAW,GAAG,IAAI,CAAA;IAClE,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACnC,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CAC/B;AAED,wBAAgB,yBAAyB,IAAI,mBAAmB,CA4B/D"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { transition } from '../../domain/window/lifecycle';
|
|
2
|
+
export function createLifecycleController() {
|
|
3
|
+
const states = new Map();
|
|
4
|
+
return {
|
|
5
|
+
register(windowId, initial = 'active') {
|
|
6
|
+
if (states.has(windowId))
|
|
7
|
+
return;
|
|
8
|
+
states.set(windowId, initial);
|
|
9
|
+
},
|
|
10
|
+
apply(windowId, event) {
|
|
11
|
+
const prev = states.get(windowId);
|
|
12
|
+
if (prev === undefined)
|
|
13
|
+
return null;
|
|
14
|
+
const result = transition(prev, event);
|
|
15
|
+
if (!result.ok)
|
|
16
|
+
return null;
|
|
17
|
+
states.set(windowId, result.next);
|
|
18
|
+
return result.next;
|
|
19
|
+
},
|
|
20
|
+
markCrashed(windowId) {
|
|
21
|
+
const prev = states.get(windowId);
|
|
22
|
+
if (prev === undefined || prev === 'closed')
|
|
23
|
+
return;
|
|
24
|
+
states.set(windowId, 'closed');
|
|
25
|
+
},
|
|
26
|
+
remove(windowId) {
|
|
27
|
+
states.delete(windowId);
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Window } from '../../domain/window/window';
|
|
2
|
+
import type { KernelClient } from '../../ports/kernel-client';
|
|
3
|
+
import type { ShellAdapter } from '../../ports/shell-adapter';
|
|
4
|
+
import type { ChildrenChannelController } from '../channels/children-channel';
|
|
5
|
+
import type { MountParams, MountedWindow, CloseResult } from '../shell';
|
|
6
|
+
import type { LifecycleController } from './lifecycle-controller';
|
|
7
|
+
export type MountControllerConfig = {
|
|
8
|
+
adapter: ShellAdapter;
|
|
9
|
+
kernel: KernelClient;
|
|
10
|
+
kernelUrl: string;
|
|
11
|
+
mintIdentity?: string;
|
|
12
|
+
childrenChannel: ChildrenChannelController;
|
|
13
|
+
windows: Map<string, Window>;
|
|
14
|
+
lifecycle: LifecycleController;
|
|
15
|
+
};
|
|
16
|
+
export interface MountController {
|
|
17
|
+
mount(params: MountParams): Promise<MountedWindow>;
|
|
18
|
+
close(windowId: string, opts?: {
|
|
19
|
+
force?: boolean;
|
|
20
|
+
timeoutMs?: number;
|
|
21
|
+
}): Promise<CloseResult>;
|
|
22
|
+
dispose(): Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
export declare function createMountController(config: MountControllerConfig): MountController;
|
|
25
|
+
//# sourceMappingURL=mount-controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mount-controller.d.ts","sourceRoot":"","sources":["../../../src/application/windowing/mount-controller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAgB,MAAM,2BAA2B,CAAA;AAC3E,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAA;AAC7E,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AACvE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAWjE,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,YAAY,CAAA;IACrB,MAAM,EAAE,YAAY,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,eAAe,EAAE,yBAAyB,CAAA;IAC1C,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5B,SAAS,EAAE,mBAAmB,CAAA;CAC/B,CAAA;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CAAA;IAClD,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;IAC7F,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACzB;AAiBD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,qBAAqB,GAAG,eAAe,CAqPpF"}
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import { createMessagePortTransport } from '../../adapters/message-port.transport';
|
|
2
|
+
import { runParentHandshake } from './handshake';
|
|
3
|
+
import { createTokenRefresher } from './token-refresh';
|
|
4
|
+
const DEFAULT_HANDSHAKE_TIMEOUT = 5_000;
|
|
5
|
+
const DEFAULT_DELEGATION_TTL = 3_600;
|
|
6
|
+
const DEFAULT_CLOSE_TIMEOUT = 3_000;
|
|
7
|
+
const PARENT_SENDER_ID = '<parent>';
|
|
8
|
+
/** No-op refresher for plain mounts (no token to refresh). */
|
|
9
|
+
const NOOP_REFRESHER = {
|
|
10
|
+
start: () => { },
|
|
11
|
+
stop: () => { },
|
|
12
|
+
forceRefreshNow: () => Promise.resolve(),
|
|
13
|
+
};
|
|
14
|
+
export function createMountController(config) {
|
|
15
|
+
const { adapter, kernel, kernelUrl, mintIdentity, childrenChannel, windows, lifecycle } = config;
|
|
16
|
+
// The child iframe is always a DIFFERENT origin from this parent window, so a
|
|
17
|
+
// relative kernelUrl (e.g. the SPA's same-origin `/api/`) handed across the
|
|
18
|
+
// handshake would resolve against the iframe's OWN origin and POST to the
|
|
19
|
+
// wrong host. Absolutize it against the parent's location once so every child
|
|
20
|
+
// calls THIS origin's kernel. (The parent's own calls keep using the relative
|
|
21
|
+
// form via its kernel client / fetch.)
|
|
22
|
+
const childKernelUrl = new URL(kernelUrl, window.location.href).href;
|
|
23
|
+
const entries = new Map();
|
|
24
|
+
let seq = 0;
|
|
25
|
+
let disposed = false;
|
|
26
|
+
function nextWindowId(functionId) {
|
|
27
|
+
seq += 1;
|
|
28
|
+
const slug = functionId.replace(/[^a-z0-9]/gi, '').slice(-8) || 'fn';
|
|
29
|
+
return `win-${slug}-${seq}`;
|
|
30
|
+
}
|
|
31
|
+
async function mint(ttlSeconds) {
|
|
32
|
+
const credential = await kernel.mintDelegation();
|
|
33
|
+
return { credential, expiresAt: Date.now() + ttlSeconds * 1_000 };
|
|
34
|
+
}
|
|
35
|
+
function originOf(url) {
|
|
36
|
+
try {
|
|
37
|
+
return new URL(url, window.location.href).origin;
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
throw new Error(`Invalid mount url: ${url}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Plain-iframe mount path — for hosted views that don't speak the shell
|
|
44
|
+
// protocol. No handshake, no transport, no delegation token, no refresher;
|
|
45
|
+
// the iframe just renders. `close()` skips the ack request (no channel) and
|
|
46
|
+
// falls straight to dispose.
|
|
47
|
+
async function mountPlain(params) {
|
|
48
|
+
const windowId = nextWindowId(params.functionId);
|
|
49
|
+
const { handle, dispose: disposeHandle } = adapter.mount({
|
|
50
|
+
functionId: params.functionId,
|
|
51
|
+
isolation: 'sandboxed',
|
|
52
|
+
capabilities: params.capabilities,
|
|
53
|
+
sandbox: params.sandbox,
|
|
54
|
+
});
|
|
55
|
+
if (!(handle.element instanceof HTMLIFrameElement)) {
|
|
56
|
+
disposeHandle();
|
|
57
|
+
throw new Error('Shell adapter did not produce an HTMLIFrameElement');
|
|
58
|
+
}
|
|
59
|
+
params.host.appendChild(handle.element);
|
|
60
|
+
handle.element.src = params.url;
|
|
61
|
+
windows.set(windowId, {
|
|
62
|
+
windowId,
|
|
63
|
+
functionId: params.functionId,
|
|
64
|
+
targetNodeId: params.targetNodeId,
|
|
65
|
+
isolation: 'sandboxed',
|
|
66
|
+
state: 'active',
|
|
67
|
+
delegationToken: null,
|
|
68
|
+
capabilities: params.capabilities,
|
|
69
|
+
});
|
|
70
|
+
lifecycle.register(windowId, 'active');
|
|
71
|
+
entries.set(windowId, {
|
|
72
|
+
handle,
|
|
73
|
+
dispose: disposeHandle,
|
|
74
|
+
refresher: NOOP_REFRESHER,
|
|
75
|
+
plain: true,
|
|
76
|
+
});
|
|
77
|
+
return {
|
|
78
|
+
windowId,
|
|
79
|
+
get window() {
|
|
80
|
+
return windows.get(windowId);
|
|
81
|
+
},
|
|
82
|
+
handle: { element: handle.element },
|
|
83
|
+
close: (opts) => controller.close(windowId, opts),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
const controller = {
|
|
87
|
+
async mount(params) {
|
|
88
|
+
if (disposed)
|
|
89
|
+
throw new Error('MountController is disposed');
|
|
90
|
+
// Plain (no-handshake) path: hosted views that don't speak the shell
|
|
91
|
+
// protocol. Skip mint/handshake/transport/refresher; the iframe still
|
|
92
|
+
// renders and `close()` falls through to dispose.
|
|
93
|
+
if (params.handshake === 'none')
|
|
94
|
+
return mountPlain(params);
|
|
95
|
+
const ttlSeconds = params.delegationTtlSeconds ?? DEFAULT_DELEGATION_TTL;
|
|
96
|
+
const handshakeTimeout = params.handshakeTimeoutMs ?? DEFAULT_HANDSHAKE_TIMEOUT;
|
|
97
|
+
const expectedOrigin = originOf(params.url);
|
|
98
|
+
const windowId = nextWindowId(params.functionId);
|
|
99
|
+
// Mint the token and create the iframe in parallel — the iframe
|
|
100
|
+
// doesn't need the credential until the handshake fires.
|
|
101
|
+
const [{ credential, expiresAt }, mounted] = await Promise.all([
|
|
102
|
+
mint(ttlSeconds),
|
|
103
|
+
Promise.resolve(adapter.mount({
|
|
104
|
+
functionId: params.functionId,
|
|
105
|
+
isolation: 'sandboxed',
|
|
106
|
+
capabilities: params.capabilities,
|
|
107
|
+
sandbox: params.sandbox,
|
|
108
|
+
})),
|
|
109
|
+
]);
|
|
110
|
+
const { handle, dispose: disposeHandle } = mounted;
|
|
111
|
+
if (!(handle.element instanceof HTMLIFrameElement)) {
|
|
112
|
+
disposeHandle();
|
|
113
|
+
throw new Error('Shell adapter did not produce an HTMLIFrameElement');
|
|
114
|
+
}
|
|
115
|
+
params.host.appendChild(handle.element);
|
|
116
|
+
handle.element.src = params.url;
|
|
117
|
+
let handshakeResult;
|
|
118
|
+
try {
|
|
119
|
+
handshakeResult = await runParentHandshake({
|
|
120
|
+
iframe: handle.element,
|
|
121
|
+
expectedOrigin,
|
|
122
|
+
windowId,
|
|
123
|
+
delegationToken: credential,
|
|
124
|
+
tokenExpiresAt: expiresAt,
|
|
125
|
+
kernelUrl: childKernelUrl,
|
|
126
|
+
functionId: params.functionId,
|
|
127
|
+
targetNodeId: params.targetNodeId,
|
|
128
|
+
mintIdentity,
|
|
129
|
+
timeoutMs: handshakeTimeout,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
catch (err) {
|
|
133
|
+
disposeHandle();
|
|
134
|
+
throw err;
|
|
135
|
+
}
|
|
136
|
+
const transport = createMessagePortTransport({
|
|
137
|
+
port: handshakeResult.port,
|
|
138
|
+
onClose: () => {
|
|
139
|
+
if (!entries.has(windowId))
|
|
140
|
+
return;
|
|
141
|
+
lifecycle.markCrashed(windowId);
|
|
142
|
+
void controller.close(windowId, { force: true }).catch(() => { });
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
childrenChannel.attach(windowId, transport);
|
|
146
|
+
windows.set(windowId, {
|
|
147
|
+
windowId,
|
|
148
|
+
functionId: params.functionId,
|
|
149
|
+
targetNodeId: params.targetNodeId,
|
|
150
|
+
isolation: 'sandboxed',
|
|
151
|
+
state: 'active',
|
|
152
|
+
delegationToken: credential,
|
|
153
|
+
capabilities: params.capabilities,
|
|
154
|
+
});
|
|
155
|
+
lifecycle.register(windowId, 'active');
|
|
156
|
+
// The live expiry advances on every refresh. The Window store only keeps
|
|
157
|
+
// the credential, so track expiry here — otherwise `token()` keeps
|
|
158
|
+
// returning the original expiry and `schedule()` collapses its lead time
|
|
159
|
+
// to 0, busy-looping `mint()` forever after the first refresh.
|
|
160
|
+
let currentExpiresAt = expiresAt;
|
|
161
|
+
const refresher = createTokenRefresher({
|
|
162
|
+
functionId: params.functionId,
|
|
163
|
+
token: () => {
|
|
164
|
+
const stored = windows.get(windowId);
|
|
165
|
+
return {
|
|
166
|
+
credential: stored?.delegationToken ?? credential,
|
|
167
|
+
expiresAt: currentExpiresAt,
|
|
168
|
+
issuedAt: 0,
|
|
169
|
+
scope: { functionId: params.functionId },
|
|
170
|
+
};
|
|
171
|
+
},
|
|
172
|
+
setToken: (next) => {
|
|
173
|
+
currentExpiresAt = next.expiresAt;
|
|
174
|
+
const stored = windows.get(windowId);
|
|
175
|
+
if (stored) {
|
|
176
|
+
windows.set(windowId, { ...stored, delegationToken: next.credential });
|
|
177
|
+
}
|
|
178
|
+
childrenChannel.send(windowId, {
|
|
179
|
+
type: 'ctrl',
|
|
180
|
+
version: 1,
|
|
181
|
+
action: 'tokenRefresh',
|
|
182
|
+
data: { delegationToken: next.credential, tokenExpiresAt: next.expiresAt },
|
|
183
|
+
});
|
|
184
|
+
},
|
|
185
|
+
mint: () => mint(ttlSeconds),
|
|
186
|
+
onFailure: () => {
|
|
187
|
+
void controller.close(windowId, { force: false }).catch(() => { });
|
|
188
|
+
},
|
|
189
|
+
});
|
|
190
|
+
refresher.start();
|
|
191
|
+
entries.set(windowId, { handle, dispose: disposeHandle, refresher });
|
|
192
|
+
return {
|
|
193
|
+
windowId,
|
|
194
|
+
get window() {
|
|
195
|
+
return windows.get(windowId);
|
|
196
|
+
},
|
|
197
|
+
handle: { element: handle.element },
|
|
198
|
+
close: (opts) => controller.close(windowId, opts),
|
|
199
|
+
};
|
|
200
|
+
},
|
|
201
|
+
async close(windowId, opts) {
|
|
202
|
+
const entry = entries.get(windowId);
|
|
203
|
+
if (!entry)
|
|
204
|
+
return { kind: 'noop' };
|
|
205
|
+
const timeoutMs = opts?.timeoutMs ?? DEFAULT_CLOSE_TIMEOUT;
|
|
206
|
+
// Plain mounts have no channel to ack a close; always force.
|
|
207
|
+
if (!opts?.force && !entry.plain) {
|
|
208
|
+
// Move the window into `closing` so the state machine accepts the
|
|
209
|
+
// subsequent `closeRefuse`/`forceClose` transition (both are only valid
|
|
210
|
+
// from `closing`).
|
|
211
|
+
lifecycle.apply(windowId, { kind: 'requestClose' });
|
|
212
|
+
const accepted = await requestCloseAck(childrenChannel, windowId, timeoutMs);
|
|
213
|
+
if (accepted.kind === 'refused') {
|
|
214
|
+
lifecycle.apply(windowId, { kind: 'closeRefuse' });
|
|
215
|
+
return { kind: 'refused', reason: accepted.reason };
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
lifecycle.apply(windowId, { kind: 'forceClose' });
|
|
219
|
+
entry.refresher.stop();
|
|
220
|
+
// Drop the entry before detaching: `detach` synchronously closes the
|
|
221
|
+
// transport, whose `onClose` re-enters `close()`. Removing the entry first
|
|
222
|
+
// makes that re-entrant call's `entries.has(windowId)` guard short-circuit,
|
|
223
|
+
// so `entry.dispose()` runs exactly once (adapters need not be idempotent).
|
|
224
|
+
entries.delete(windowId);
|
|
225
|
+
childrenChannel.detach(windowId);
|
|
226
|
+
windows.delete(windowId);
|
|
227
|
+
entry.dispose();
|
|
228
|
+
lifecycle.remove(windowId);
|
|
229
|
+
return { kind: 'closed' };
|
|
230
|
+
},
|
|
231
|
+
async dispose() {
|
|
232
|
+
if (disposed)
|
|
233
|
+
return;
|
|
234
|
+
disposed = true;
|
|
235
|
+
const ids = [...entries.keys()];
|
|
236
|
+
await Promise.all(ids.map((id) => controller.close(id, { force: true })));
|
|
237
|
+
},
|
|
238
|
+
};
|
|
239
|
+
return controller;
|
|
240
|
+
}
|
|
241
|
+
async function requestCloseAck(children, windowId, timeoutMs) {
|
|
242
|
+
return new Promise((resolve) => {
|
|
243
|
+
let settled = false;
|
|
244
|
+
const off = children.on('intent', (from, message) => {
|
|
245
|
+
if (from !== windowId)
|
|
246
|
+
return;
|
|
247
|
+
if (message.envelope.name === 'closeAck') {
|
|
248
|
+
settled = true;
|
|
249
|
+
off();
|
|
250
|
+
clearTimeout(timer);
|
|
251
|
+
resolve({ kind: 'ack' });
|
|
252
|
+
}
|
|
253
|
+
else if (message.envelope.name === 'closeRefuse') {
|
|
254
|
+
settled = true;
|
|
255
|
+
off();
|
|
256
|
+
clearTimeout(timer);
|
|
257
|
+
const reason = message.envelope.payload.reason;
|
|
258
|
+
resolve({ kind: 'refused', reason });
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
const timer = setTimeout(() => {
|
|
262
|
+
if (settled)
|
|
263
|
+
return;
|
|
264
|
+
off();
|
|
265
|
+
resolve({ kind: 'timeout' });
|
|
266
|
+
}, timeoutMs);
|
|
267
|
+
children.send(windowId, {
|
|
268
|
+
type: 'intent',
|
|
269
|
+
version: 1,
|
|
270
|
+
envelope: {
|
|
271
|
+
name: 'willClose',
|
|
272
|
+
payload: {},
|
|
273
|
+
sender: { windowId: PARENT_SENDER_ID },
|
|
274
|
+
},
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Out-of-band protocol for window-level postMessage handshake.
|
|
3
|
+
*
|
|
4
|
+
* These messages travel over `window.postMessage` (no MessagePort yet).
|
|
5
|
+
* Once the handshake succeeds, all further communication moves to the
|
|
6
|
+
* transferred MessagePort.
|
|
7
|
+
*/
|
|
8
|
+
export declare const INIT_REQUEST_TYPE = "astrale-shell/init-request";
|
|
9
|
+
export declare const INIT_RESPONSE_TYPE = "astrale-shell/init-response";
|
|
10
|
+
export type InitRequestMessage = {
|
|
11
|
+
readonly type: typeof INIT_REQUEST_TYPE;
|
|
12
|
+
readonly version: 1;
|
|
13
|
+
};
|
|
14
|
+
export type InitResponseMessage = {
|
|
15
|
+
readonly type: typeof INIT_RESPONSE_TYPE;
|
|
16
|
+
readonly version: 1;
|
|
17
|
+
readonly windowId: string;
|
|
18
|
+
};
|
|
19
|
+
export declare function isInitRequest(value: unknown): value is InitRequestMessage;
|
|
20
|
+
export declare function isInitResponse(value: unknown): value is InitResponseMessage;
|
|
21
|
+
//# sourceMappingURL=protocol.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../../src/application/windowing/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,eAAO,MAAM,iBAAiB,+BAA+B,CAAA;AAC7D,eAAO,MAAM,kBAAkB,gCAAgC,CAAA;AAE/D,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,CAAC,IAAI,EAAE,OAAO,iBAAiB,CAAA;IACvC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,IAAI,EAAE,OAAO,kBAAkB,CAAA;IACxC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAA;IACnB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B,CAAA;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,kBAAkB,CAMzE;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,mBAAmB,CAM3E"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Out-of-band protocol for window-level postMessage handshake.
|
|
3
|
+
*
|
|
4
|
+
* These messages travel over `window.postMessage` (no MessagePort yet).
|
|
5
|
+
* Once the handshake succeeds, all further communication moves to the
|
|
6
|
+
* transferred MessagePort.
|
|
7
|
+
*/
|
|
8
|
+
export const INIT_REQUEST_TYPE = 'astrale-shell/init-request';
|
|
9
|
+
export const INIT_RESPONSE_TYPE = 'astrale-shell/init-response';
|
|
10
|
+
export function isInitRequest(value) {
|
|
11
|
+
return (typeof value === 'object' &&
|
|
12
|
+
value !== null &&
|
|
13
|
+
value.type === INIT_REQUEST_TYPE);
|
|
14
|
+
}
|
|
15
|
+
export function isInitResponse(value) {
|
|
16
|
+
return (typeof value === 'object' &&
|
|
17
|
+
value !== null &&
|
|
18
|
+
value.type === INIT_RESPONSE_TYPE);
|
|
19
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { DelegationToken } from '../../domain/identity/delegation';
|
|
2
|
+
export type TokenRefreshConfig = {
|
|
3
|
+
readonly token: () => DelegationToken;
|
|
4
|
+
readonly setToken: (next: DelegationToken) => void;
|
|
5
|
+
readonly mint: () => Promise<{
|
|
6
|
+
credential: string;
|
|
7
|
+
expiresAt: number;
|
|
8
|
+
}>;
|
|
9
|
+
readonly functionId: string;
|
|
10
|
+
readonly onFailure?: (error: unknown) => void;
|
|
11
|
+
readonly now?: () => number;
|
|
12
|
+
};
|
|
13
|
+
export interface TokenRefresher {
|
|
14
|
+
start(): void;
|
|
15
|
+
stop(): void;
|
|
16
|
+
forceRefreshNow(): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
export declare function createTokenRefresher(config: TokenRefreshConfig): TokenRefresher;
|
|
19
|
+
//# sourceMappingURL=token-refresh.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-refresh.d.ts","sourceRoot":"","sources":["../../../src/application/windowing/token-refresh.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAA;AAIvE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,eAAe,CAAA;IACrC,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,CAAA;IAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,OAAO,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACvE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;IAC7C,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CAC5B,CAAA;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,IAAI,IAAI,CAAA;IACb,IAAI,IAAI,IAAI,CAAA;IACZ,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACjC;AAID,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,kBAAkB,GAAG,cAAc,CAoD/E"}
|