@loutrejs/loutre 0.9.2 → 0.10.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/aws-lambda.d.ts +1 -1
- package/dist/adapters/aws-lambda.js +8 -2
- package/dist/adapters/bun.d.ts +3 -2
- package/dist/adapters/bun.js +12 -6
- package/dist/adapters/cloudflare-workers.d.ts +1 -1
- package/dist/adapters/cloudflare-workers.js +2 -1
- package/dist/adapters/electron.d.ts +1 -1
- package/dist/adapters/electron.js +8 -51
- package/dist/adapters/server-transports.js +2 -2
- package/dist/adapters/websocket-native.js +4 -1
- package/dist/application/definition.d.ts +4 -7
- package/dist/application/definition.js +3 -1
- package/dist/application/kernel.d.ts +0 -2
- package/dist/application/kernel.js +1 -3
- package/dist/core/args.d.ts +1 -0
- package/dist/core/args.js +2 -1
- package/dist/core/env.d.ts +1 -0
- package/dist/core/env.js +2 -1
- package/dist/core/extension.d.ts +23 -13
- package/dist/core/extension.js +3 -1
- package/dist/core/generic-layer.d.ts +9 -2
- package/dist/core/generic-layer.js +2 -1
- package/dist/core/identity.d.ts +18 -0
- package/dist/core/identity.js +5 -0
- package/dist/core/index.d.ts +13 -5
- package/dist/core/index.js +7 -1
- package/dist/core/injection.d.ts +2 -1
- package/dist/core/instrumentation.d.ts +7 -5
- package/dist/core/lifecycle.d.ts +4 -0
- package/dist/core/logger-identity.d.ts +4 -0
- package/dist/core/logger-identity.js +9 -0
- package/dist/core/logger-internal.d.ts +5 -0
- package/dist/core/logger-internal.js +27 -0
- package/dist/core/logger-module.d.ts +5 -0
- package/dist/core/logger-module.js +8 -0
- package/dist/core/logger.d.ts +42 -0
- package/dist/core/logger.js +221 -0
- package/dist/core/model/context.d.ts +6 -3
- package/dist/core/model/context.js +17 -17
- package/dist/core/model/identity.d.ts +19 -0
- package/dist/core/model/identity.js +8 -0
- package/dist/core/model/lifecycle.d.ts +3 -2
- package/dist/core/model/lifecycle.js +7 -3
- package/dist/core/model/logger.d.ts +3 -0
- package/dist/core/model/logger.js +59 -0
- package/dist/core/model/modules.d.ts +4 -1
- package/dist/core/model/modules.js +6 -4
- package/dist/core/model/providers.d.ts +1 -1
- package/dist/core/model/providers.js +8 -8
- package/dist/core/model/types.d.ts +25 -18
- package/dist/core/model/validation.js +3 -2
- package/dist/core/model/visibility.js +7 -2
- package/dist/core/model.js +15 -7
- package/dist/core/module.d.ts +7 -7
- package/dist/core/module.js +0 -3
- package/dist/core/runtime-input.d.ts +2 -1
- package/dist/core/source-location.d.ts +14 -2
- package/dist/core/source-location.js +8 -3
- package/dist/core/token-internal.js +3 -1
- package/dist/core/token.d.ts +4 -2
- package/dist/core/token.js +3 -0
- package/dist/core/units.d.ts +22 -0
- package/dist/core/units.js +14 -0
- package/dist/devtools/capsule.d.ts +17 -13
- package/dist/devtools/capsule.js +14 -10
- package/dist/devtools/decoder.d.ts +15 -0
- package/dist/devtools/decoder.js +179 -0
- package/dist/devtools/identity-internal.d.ts +6 -0
- package/dist/devtools/identity-internal.js +5 -0
- package/dist/devtools/identity.d.ts +21 -0
- package/dist/devtools/identity.js +7 -0
- package/dist/devtools/index.d.ts +3 -0
- package/dist/devtools/index.js +2 -0
- package/dist/devtools/inspector.d.ts +18 -16
- package/dist/devtools/observer.d.ts +32 -28
- package/dist/devtools/runtime.js +34 -30
- package/dist/devtools/values.js +3 -5
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/graph/model.d.ts +25 -14
- package/dist/http/auth.d.ts +4 -2
- package/dist/http/client.d.ts +6 -3
- package/dist/http/client.js +8 -9
- package/dist/http/cors-internal.d.ts +7 -5
- package/dist/http/cors-internal.js +8 -6
- package/dist/http/extension.d.ts +60 -21
- package/dist/http/extension.js +91 -20
- package/dist/http/identity.d.ts +20 -0
- package/dist/http/identity.js +10 -0
- package/dist/http/index.d.ts +6 -2
- package/dist/http/index.js +3 -1
- package/dist/http/openapi-identity.d.ts +9 -0
- package/dist/http/openapi-identity.js +4 -0
- package/dist/http/openapi.d.ts +1 -1
- package/dist/http/openapi.js +10 -7
- package/dist/http/path.d.ts +8 -5
- package/dist/http/route-validation.js +2 -1
- package/dist/http/runtime/request.d.ts +3 -2
- package/dist/http/runtime/request.js +1 -4
- package/dist/http/websocket-upgrade.d.ts +2 -0
- package/dist/http/websocket-upgrade.js +4 -0
- package/dist/internal/brand.d.ts +8 -0
- package/dist/internal/brand.js +1 -0
- package/dist/message-port/extension.d.ts +4 -2
- package/dist/message-port/extension.js +15 -8
- package/dist/message-port/identity.d.ts +9 -0
- package/dist/message-port/identity.js +16 -0
- package/dist/message-port/index.d.ts +2 -0
- package/dist/message-port/index.js +1 -0
- package/dist/message-port/transport.d.ts +4 -2
- package/dist/message-port/transport.js +6 -1
- package/dist/runtime/async-iterator-lifecycle.d.ts +2 -1
- package/dist/runtime/async-iterator-lifecycle.js +2 -1
- package/dist/runtime/capability.d.ts +6 -2
- package/dist/runtime/capability.js +3 -1
- package/dist/runtime/di.d.ts +1 -3
- package/dist/runtime/di.js +62 -35
- package/dist/runtime/error.d.ts +3 -1
- package/dist/runtime/index.d.ts +6 -2
- package/dist/runtime/index.js +3 -1
- package/dist/runtime/kernel.d.ts +0 -2
- package/dist/runtime/kernel.js +68 -30
- package/dist/runtime/logger-source.d.ts +4 -0
- package/dist/runtime/logger-source.js +47 -0
- package/dist/runtime/logger.d.ts +2 -38
- package/dist/runtime/logger.js +1 -209
- package/dist/runtime/node-capabilities.d.ts +1 -1
- package/dist/runtime/node-capabilities.js +2 -1
- package/dist/runtime/server-port.d.ts +5 -1
- package/dist/runtime/server-port.js +2 -1
- package/dist/runtime/shutdown-hooks.d.ts +1 -1
- package/dist/runtime/shutdown-hooks.js +5 -4
- package/dist/tasks/extension.d.ts +18 -16
- package/dist/tasks/extension.js +28 -23
- package/dist/tasks/identity.d.ts +9 -0
- package/dist/tasks/identity.js +4 -0
- package/dist/tasks/index.d.ts +1 -0
- package/dist/tasks/runtime/cron.d.ts +6 -2
- package/dist/tasks/runtime/cron.js +9 -0
- package/dist/websocket/extension.d.ts +19 -9
- package/dist/websocket/extension.js +103 -30
- package/dist/websocket/identity.d.ts +9 -0
- package/dist/websocket/identity.js +4 -0
- package/dist/websocket/index.d.ts +1 -0
- package/package.json +1 -1
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { moduleName } from '../identity.js';
|
|
1
2
|
import { collectInjectedDependencies } from '../injection.js';
|
|
2
3
|
import { diagnostic } from '../diagnostic.js';
|
|
3
4
|
import { normalizeProvider } from '../provider.js';
|
|
4
5
|
import { tokenName } from '../token.js';
|
|
6
|
+
import { findProviderNode } from './context.js';
|
|
5
7
|
import { appendLifecycleNodes } from './lifecycle.js';
|
|
6
8
|
import { snapshotProvider } from './snapshot.js';
|
|
7
9
|
import { getSourceLocation } from '../source-location.js';
|
|
@@ -12,10 +14,10 @@ export function collectModuleDeclarations(context) {
|
|
|
12
14
|
for (const module of modules) {
|
|
13
15
|
const moduleId = moduleIds.get(module);
|
|
14
16
|
if (module.definition.name) {
|
|
15
|
-
if (moduleNames.has(module.definition.name)) {
|
|
17
|
+
if (moduleNames.has(moduleName(module.definition.name))) {
|
|
16
18
|
diagnostics.push(diagnostic('LUTRE_MODULE_NAME_COLLISION', `Module name ${module.definition.name} is already registered.`, moduleId));
|
|
17
19
|
}
|
|
18
|
-
moduleNames.add(module.definition.name);
|
|
20
|
+
moduleNames.add(moduleName(module.definition.name));
|
|
19
21
|
}
|
|
20
22
|
const moduleSource = getSourceLocation(module) ?? getSourceLocation(module.template);
|
|
21
23
|
nodes.push({
|
|
@@ -41,7 +43,7 @@ export function collectModuleDeclarations(context) {
|
|
|
41
43
|
? getSourceLocation(normalized.useClass)
|
|
42
44
|
: getSourceLocation(declaration);
|
|
43
45
|
const providerId = context.nextProviderId();
|
|
44
|
-
const existingProvider =
|
|
46
|
+
const existingProvider = findProviderNode(context, provider.provide);
|
|
45
47
|
if (existingProvider?.provider.kind === 'environment' &&
|
|
46
48
|
provider.kind === 'environment') {
|
|
47
49
|
edges.push({ from: moduleId, to: existingProvider.id, kind: 'owns' });
|
|
@@ -78,7 +80,7 @@ export function collectModuleDeclarations(context) {
|
|
|
78
80
|
appendLifecycleNodes(module, moduleId, nodes, edges);
|
|
79
81
|
}
|
|
80
82
|
}
|
|
81
|
-
function collectProviderDependencies(provider) {
|
|
83
|
+
export function collectProviderDependencies(provider) {
|
|
82
84
|
return match(provider)
|
|
83
85
|
.with({ kind: 'class' }, (candidate) => Object.freeze(collectInjectedDependencies(candidate.provide, () => Reflect.construct(candidate.useClass, []))))
|
|
84
86
|
.with({ kind: 'factory' }, (candidate) => Object.freeze([...candidate.inject]))
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ModelBuildContext } from './context.js';
|
|
2
2
|
export declare function resolveModuleExports(context: ModelBuildContext): void;
|
|
3
3
|
export declare function compileArgumentsProvider(context: ModelBuildContext): void;
|
|
4
4
|
export declare function resolveProviderDependencies(context: ModelBuildContext): void;
|
|
@@ -1,17 +1,19 @@
|
|
|
1
|
+
import { isLoggerToken } from '../logger-internal.js';
|
|
1
2
|
import { diagnostic } from '../diagnostic.js';
|
|
2
3
|
import { argumentsProvider } from '../provider.js';
|
|
3
4
|
import { isFrameworkProvidedToken } from '../token-internal.js';
|
|
4
5
|
import { tokenName } from '../token.js';
|
|
6
|
+
import { findProviderNode } from './context.js';
|
|
5
7
|
import { snapshotProvider } from './snapshot.js';
|
|
6
8
|
import { isTokenVisible, moduleDeclaresToken } from './visibility.js';
|
|
7
9
|
export function resolveModuleExports(context) {
|
|
8
|
-
const { modules, moduleIds,
|
|
10
|
+
const { modules, moduleIds, edges, diagnostics } = context;
|
|
9
11
|
for (const module of modules) {
|
|
10
12
|
const moduleId = moduleIds.get(module);
|
|
11
13
|
for (const exported of module.definition.exports ?? []) {
|
|
12
14
|
if (moduleDeclaresToken(module, exported))
|
|
13
15
|
continue;
|
|
14
|
-
const provider =
|
|
16
|
+
const provider = findProviderNode(context, exported);
|
|
15
17
|
const providerModule = provider
|
|
16
18
|
? modules.find((candidate) => moduleIds.get(candidate) === provider.moduleId)
|
|
17
19
|
: undefined;
|
|
@@ -49,17 +51,15 @@ export function compileArgumentsProvider(context) {
|
|
|
49
51
|
export function resolveProviderDependencies(context) {
|
|
50
52
|
const { providerNodes, modules, moduleIds, edges, diagnostics } = context;
|
|
51
53
|
for (const provider of providerNodes.values()) {
|
|
52
|
-
if (provider.moduleId === 'application')
|
|
53
|
-
continue;
|
|
54
54
|
const sourceModule = modules.find((candidate) => moduleIds.get(candidate) === provider.moduleId);
|
|
55
|
-
if (!sourceModule)
|
|
56
|
-
continue;
|
|
57
55
|
for (const dependency of provider.dependencies) {
|
|
58
|
-
const target =
|
|
56
|
+
const target = findProviderNode(context, dependency);
|
|
59
57
|
if (target) {
|
|
60
58
|
edges.push({ from: provider.id, to: target.id, kind: 'injects' });
|
|
61
59
|
const targetModule = modules.find((candidate) => moduleIds.get(candidate) === target.moduleId);
|
|
62
|
-
if (
|
|
60
|
+
if (sourceModule &&
|
|
61
|
+
!isLoggerToken(dependency) &&
|
|
62
|
+
targetModule &&
|
|
63
63
|
target.moduleId !== provider.moduleId &&
|
|
64
64
|
!moduleDeclaresToken(sourceModule, dependency) &&
|
|
65
65
|
!isTokenVisible(context, sourceModule, targetModule, dependency)) {
|
|
@@ -1,32 +1,33 @@
|
|
|
1
|
+
import type { ModuleId, ProviderNodeId, ExecutionNodeId, LifecycleNodeId, CapabilityNodeId, ExtensionNodeId } from './identity.js';
|
|
1
2
|
import type { ArgsClass } from '../args.js';
|
|
2
3
|
import type { AnyExecutionExtension, ExecutionExtension, RuntimeCapability } from '../extension.js';
|
|
3
4
|
import type { LifecycleHook } from '../lifecycle.js';
|
|
4
|
-
import type { ModuleInstance
|
|
5
|
+
import type { ModuleInstance } from '../module.js';
|
|
5
6
|
import type { ProviderDescriptor } from '../provider.js';
|
|
6
7
|
import type { Diagnostic } from '../diagnostic.js';
|
|
7
8
|
import type { TokenLike } from '../token.js';
|
|
8
9
|
import type { SourceLocation } from '../source-location.js';
|
|
9
10
|
export interface ModuleModelNode {
|
|
10
11
|
readonly kind: 'module';
|
|
11
|
-
readonly id:
|
|
12
|
+
readonly id: ModuleId;
|
|
12
13
|
readonly name?: string;
|
|
13
14
|
readonly description?: string;
|
|
14
15
|
readonly source?: SourceLocation;
|
|
15
16
|
}
|
|
16
17
|
export interface ProviderModelNode {
|
|
17
18
|
readonly kind: 'provider';
|
|
18
|
-
readonly id:
|
|
19
|
+
readonly id: ProviderNodeId;
|
|
19
20
|
readonly token: TokenLike;
|
|
20
21
|
readonly provider: ProviderDescriptor;
|
|
21
|
-
readonly moduleId:
|
|
22
|
+
readonly moduleId: ModuleId | 'application';
|
|
22
23
|
readonly dependencies: readonly TokenLike[];
|
|
23
24
|
readonly source?: SourceLocation;
|
|
24
25
|
}
|
|
25
26
|
export interface ExecutionModelNode<TCompiled = unknown> {
|
|
26
27
|
readonly kind: 'execution';
|
|
27
|
-
readonly id:
|
|
28
|
+
readonly id: ExecutionNodeId;
|
|
28
29
|
readonly executionKind: string;
|
|
29
|
-
readonly moduleId:
|
|
30
|
+
readonly moduleId: ModuleId;
|
|
30
31
|
readonly dependencies: readonly TokenLike[];
|
|
31
32
|
readonly capabilities: readonly RuntimeCapability[];
|
|
32
33
|
readonly compiled: TCompiled;
|
|
@@ -34,25 +35,30 @@ export interface ExecutionModelNode<TCompiled = unknown> {
|
|
|
34
35
|
}
|
|
35
36
|
export interface LifecycleModelNode {
|
|
36
37
|
readonly kind: 'lifecycle';
|
|
37
|
-
readonly id:
|
|
38
|
-
readonly moduleId:
|
|
38
|
+
readonly id: LifecycleNodeId;
|
|
39
|
+
readonly moduleId: ModuleId;
|
|
39
40
|
readonly phase: string;
|
|
40
41
|
readonly hook: LifecycleHook<any>;
|
|
41
42
|
readonly source?: SourceLocation;
|
|
42
43
|
}
|
|
43
|
-
export
|
|
44
|
+
export type FrameworkModelNode = {
|
|
44
45
|
readonly kind: 'framework';
|
|
45
|
-
readonly id: string;
|
|
46
|
-
readonly frameworkKind: 'runtime-capability' | 'execution-extension';
|
|
47
46
|
readonly name: string;
|
|
48
47
|
readonly source?: SourceLocation;
|
|
49
|
-
}
|
|
48
|
+
} & ({
|
|
49
|
+
readonly frameworkKind: 'runtime-capability';
|
|
50
|
+
readonly id: CapabilityNodeId;
|
|
51
|
+
} | {
|
|
52
|
+
readonly frameworkKind: 'execution-extension';
|
|
53
|
+
readonly id: ExtensionNodeId;
|
|
54
|
+
});
|
|
50
55
|
export type ApplicationModelNode = ModuleModelNode | ProviderModelNode | ExecutionModelNode | LifecycleModelNode | FrameworkModelNode;
|
|
51
|
-
|
|
52
|
-
readonly
|
|
53
|
-
readonly
|
|
54
|
-
readonly
|
|
55
|
-
}
|
|
56
|
+
type Edge<Kind, From, To> = {
|
|
57
|
+
readonly kind: Kind;
|
|
58
|
+
readonly from: From;
|
|
59
|
+
readonly to: To;
|
|
60
|
+
};
|
|
61
|
+
export type ApplicationModelEdge = Edge<'owns', ModuleId, ProviderNodeId | ExecutionNodeId | LifecycleNodeId> | Edge<'imports', ModuleId, ModuleId> | Edge<'exports', ModuleId, ProviderNodeId> | Edge<'injects', ProviderNodeId | ExecutionNodeId | LifecycleNodeId, ProviderNodeId> | Edge<'references', ExecutionNodeId, ExecutionNodeId> | Edge<'requires', ExecutionNodeId, CapabilityNodeId> | Edge<'starts', ExtensionNodeId, ExecutionNodeId> | Edge<'wraps', ApplicationModelNode['id'], ApplicationModelNode['id']>;
|
|
56
62
|
export type CompiledOf<TExtension extends AnyExecutionExtension> = TExtension extends ExecutionExtension<any, infer TCompiled, any, any, any> ? TCompiled : never;
|
|
57
63
|
export interface ApplicationModelExtension<TExtension extends AnyExecutionExtension = AnyExecutionExtension> {
|
|
58
64
|
readonly extension: TExtension;
|
|
@@ -73,6 +79,7 @@ export interface ApplicationModel {
|
|
|
73
79
|
readonly diagnostics: readonly Diagnostic[];
|
|
74
80
|
}
|
|
75
81
|
export interface ApplicationModelBuildOptions {
|
|
76
|
-
readonly modules: readonly
|
|
82
|
+
readonly modules: readonly ModuleInstance[];
|
|
77
83
|
readonly arguments?: ArgsClass;
|
|
78
84
|
}
|
|
85
|
+
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { hostNamespace } from '../identity.js';
|
|
1
2
|
import { diagnostic } from '../diagnostic.js';
|
|
2
3
|
export function validateHostNamespaces(extensions, diagnostics) {
|
|
3
4
|
const reserved = new Set([
|
|
@@ -20,12 +21,12 @@ export function validateHostNamespaces(extensions, diagnostics) {
|
|
|
20
21
|
diagnostics.push(diagnostic('LUTRE_HOST_NAMESPACE_RESERVED', `Host namespace ${namespace} is reserved by the Application or runtime adapter API.`, `host.${namespace}`));
|
|
21
22
|
continue;
|
|
22
23
|
}
|
|
23
|
-
const owner = owners.get(namespace);
|
|
24
|
+
const owner = owners.get(hostNamespace(namespace));
|
|
24
25
|
if (owner && owner.identity !== extension.identity) {
|
|
25
26
|
diagnostics.push(diagnostic('LUTRE_HOST_NAMESPACE_COLLISION', `Host namespace ${namespace} is contributed by both ${owner.name} and ${extension.name}.`, `host.${namespace}`));
|
|
26
27
|
continue;
|
|
27
28
|
}
|
|
28
|
-
owners.set(namespace, extension);
|
|
29
|
+
owners.set(hostNamespace(namespace), extension);
|
|
29
30
|
}
|
|
30
31
|
}
|
|
31
32
|
export function validateNodeIds(nodes, diagnostics) {
|
|
@@ -1,13 +1,18 @@
|
|
|
1
|
+
import { isLoggerToken } from '../logger-internal.js';
|
|
1
2
|
import { normalizeProvider } from '../provider.js';
|
|
2
3
|
export function moduleDeclaresToken(module, token) {
|
|
3
|
-
return (module.definition.providers ?? []).some((declaration) =>
|
|
4
|
+
return (module.definition.providers ?? []).some((declaration) => {
|
|
5
|
+
const provided = normalizeProvider(declaration).provide;
|
|
6
|
+
return (provided === token || (isLoggerToken(provided) && isLoggerToken(token)));
|
|
7
|
+
});
|
|
4
8
|
}
|
|
5
9
|
export function isTokenVisible(context, source, target, token, visited = new Set()) {
|
|
6
10
|
if (visited.has(source))
|
|
7
11
|
return false;
|
|
8
12
|
visited.add(source);
|
|
9
13
|
for (const imported of context.imports.get(source) ?? []) {
|
|
10
|
-
if (!imported.definition.exports?.
|
|
14
|
+
if (!imported.definition.exports?.some((exported) => exported === token ||
|
|
15
|
+
(isLoggerToken(exported) && isLoggerToken(token))))
|
|
11
16
|
continue;
|
|
12
17
|
if (imported === target)
|
|
13
18
|
return true;
|
package/dist/core/model.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { executionNodeId, capabilityNodeId, extensionNodeId, } from './model/identity.js';
|
|
1
2
|
import { diagnostic, isErrorDiagnostic } from './diagnostic.js';
|
|
2
3
|
import { isExecutionDefinition, flattenExecutions, } from './extension.js';
|
|
3
4
|
import { isFrameworkProvidedToken } from './token-internal.js';
|
|
@@ -8,6 +9,9 @@ import { collectModuleDeclarations } from './model/modules.js';
|
|
|
8
9
|
import { compileArgumentsProvider, resolveModuleExports, resolveProviderDependencies, } from './model/providers.js';
|
|
9
10
|
import { snapshotExecutionExtension } from './model/snapshot.js';
|
|
10
11
|
import { validateHostNamespaces, validateNodeIds } from './model/validation.js';
|
|
12
|
+
import { compileApplicationLogger, validateApplicationLogger, } from './model/logger.js';
|
|
13
|
+
import { findProviderNode } from './model/context.js';
|
|
14
|
+
import { isLoggerToken } from './logger-internal.js';
|
|
11
15
|
import { getSourceLocation } from './source-location.js';
|
|
12
16
|
import { isTokenVisible, moduleDeclaresToken } from './model/visibility.js';
|
|
13
17
|
class ApplicationModelExtensionRegistry {
|
|
@@ -47,11 +51,12 @@ export function assertValidApplicationModel(model) {
|
|
|
47
51
|
export function buildApplicationModel(options) {
|
|
48
52
|
const context = createModelBuildContext(options);
|
|
49
53
|
collectModuleDeclarations(context);
|
|
50
|
-
resolveModuleExports(context);
|
|
51
54
|
compileArgumentsProvider(context);
|
|
55
|
+
compileApplicationLogger(context);
|
|
56
|
+
resolveModuleExports(context);
|
|
52
57
|
resolveProviderDependencies(context);
|
|
53
58
|
resolveLifecycleDependencies(context);
|
|
54
|
-
const { modules, moduleIds, nodes, edges, diagnostics, providers, executions,
|
|
59
|
+
const { modules, moduleIds, nodes, edges, diagnostics, providers, executions, } = context;
|
|
55
60
|
const extensionExecutions = new Map();
|
|
56
61
|
const extensionNames = new Map();
|
|
57
62
|
const extensionIdentities = new Map();
|
|
@@ -216,14 +221,15 @@ export function buildApplicationModel(options) {
|
|
|
216
221
|
diagnostics.push(diagnostic('LUTRE_EXTENSION_COMPILE', describeError(error), path));
|
|
217
222
|
continue;
|
|
218
223
|
}
|
|
219
|
-
if (executionIds.has(contribution.id)) {
|
|
224
|
+
if (executionIds.has(executionNodeId(contribution.id))) {
|
|
220
225
|
diagnostics.push(diagnostic('LUTRE_EXECUTION_ID_COLLISION', `Execution id ${contribution.id} is already registered.`, path));
|
|
221
226
|
continue;
|
|
222
227
|
}
|
|
223
|
-
executionIds.add(contribution.id);
|
|
228
|
+
executionIds.add(executionNodeId(contribution.id));
|
|
224
229
|
const executionSource = getSourceLocation(value);
|
|
225
230
|
const execution = Object.freeze({
|
|
226
231
|
...contribution,
|
|
232
|
+
id: executionNodeId(contribution.id),
|
|
227
233
|
dependencies: Object.freeze([...contribution.dependencies]),
|
|
228
234
|
capabilities: Object.freeze([...contribution.capabilities]),
|
|
229
235
|
moduleId,
|
|
@@ -240,11 +246,12 @@ export function buildApplicationModel(options) {
|
|
|
240
246
|
grouped.executions.push(execution);
|
|
241
247
|
extensionExecutions.set(extension.identity, grouped);
|
|
242
248
|
for (const dependency of execution.dependencies) {
|
|
243
|
-
const provider =
|
|
249
|
+
const provider = findProviderNode(context, dependency);
|
|
244
250
|
if (provider) {
|
|
245
251
|
edges.push({ from: execution.id, to: provider.id, kind: 'injects' });
|
|
246
252
|
const providerModule = modules.find((candidate) => moduleIds.get(candidate) === provider.moduleId);
|
|
247
253
|
if (providerModule &&
|
|
254
|
+
!isLoggerToken(dependency) &&
|
|
248
255
|
provider.moduleId !== moduleId &&
|
|
249
256
|
!moduleDeclaresToken(module, dependency) &&
|
|
250
257
|
!isTokenVisible(context, module, providerModule, dependency)) {
|
|
@@ -256,7 +263,7 @@ export function buildApplicationModel(options) {
|
|
|
256
263
|
}
|
|
257
264
|
}
|
|
258
265
|
for (const capability of execution.capabilities) {
|
|
259
|
-
const capabilityId =
|
|
266
|
+
const capabilityId = capabilityNodeId(capability.id);
|
|
260
267
|
if (!capabilityNodeIds.has(capabilityId)) {
|
|
261
268
|
capabilityNodeIds.add(capabilityId);
|
|
262
269
|
nodes.push({
|
|
@@ -312,7 +319,7 @@ export function buildApplicationModel(options) {
|
|
|
312
319
|
edges.push({ from: from.id, to: to.id, kind: 'references' });
|
|
313
320
|
}
|
|
314
321
|
const extensionGroups = [...extensionExecutions.values()].map(({ extension, executions: ownedExecutions }) => {
|
|
315
|
-
const extensionId =
|
|
322
|
+
const extensionId = extensionNodeId(extension.name);
|
|
316
323
|
nodes.push({
|
|
317
324
|
kind: 'framework',
|
|
318
325
|
id: extensionId,
|
|
@@ -336,6 +343,7 @@ export function buildApplicationModel(options) {
|
|
|
336
343
|
});
|
|
337
344
|
});
|
|
338
345
|
const extensions = new ApplicationModelExtensionRegistry(extensionGroups);
|
|
346
|
+
validateApplicationLogger(context);
|
|
339
347
|
validateHostNamespaces(extensionGroups, diagnostics);
|
|
340
348
|
validateNodeIds(nodes, diagnostics);
|
|
341
349
|
return Object.freeze({
|
package/dist/core/module.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Descriptor } from '../internal/brand.js';
|
|
1
2
|
import type { EnvClass } from './env.js';
|
|
2
3
|
import type { ExecutionDeclaration, ExtensionOfDefinition, HostApiOfExtension } from './extension.js';
|
|
3
4
|
import type { ModuleLifecycle } from './lifecycle.js';
|
|
@@ -5,7 +6,7 @@ import { type ProviderDeclaration } from './provider.js';
|
|
|
5
6
|
export interface ModuleDefinition {
|
|
6
7
|
readonly name?: string;
|
|
7
8
|
readonly description?: string;
|
|
8
|
-
readonly imports?: readonly
|
|
9
|
+
readonly imports?: readonly ModuleInstance[];
|
|
9
10
|
readonly environment?: readonly EnvClass[];
|
|
10
11
|
readonly providers?: readonly ProviderDeclaration[];
|
|
11
12
|
readonly executions?: readonly ExecutionDeclaration[];
|
|
@@ -17,18 +18,18 @@ export interface ModuleTypeInfo<TDefinition extends ModuleDefinition = ModuleDef
|
|
|
17
18
|
readonly extensions: ExtensionsOfModuleDefinition<TDefinition>;
|
|
18
19
|
}
|
|
19
20
|
type DirectExtensions<TDefinition extends ModuleDefinition> = TDefinition['executions'] extends readonly ExecutionDeclaration[] ? ExtensionOfDefinition<TDefinition['executions'][number]> : never;
|
|
20
|
-
type ImportedExtensions<TDefinition extends ModuleDefinition> = TDefinition['imports'] extends readonly
|
|
21
|
+
type ImportedExtensions<TDefinition extends ModuleDefinition> = TDefinition['imports'] extends readonly ModuleInstance[] ? ModuleExtensions<TDefinition['imports'][number]> : never;
|
|
21
22
|
export type ExtensionsOfModuleDefinition<TDefinition extends ModuleDefinition> = DirectExtensions<TDefinition> | ImportedExtensions<TDefinition>;
|
|
22
|
-
export type ModuleExtensions<TModule> = TModule extends ModuleInstance<infer TDefinition> ? ExtensionsOfModuleDefinition<TDefinition> :
|
|
23
|
+
export type ModuleExtensions<TModule> = TModule extends ModuleInstance<infer TDefinition> ? ExtensionsOfModuleDefinition<TDefinition> : never;
|
|
23
24
|
export type ModuleHostApis<TModule> = HostApiOfExtension<ModuleExtensions<TModule>>;
|
|
24
|
-
export interface ModuleInstance<TDefinition extends ModuleDefinition = ModuleDefinition> {
|
|
25
|
+
export interface ModuleInstance<TDefinition extends ModuleDefinition = ModuleDefinition> extends Descriptor<'module-instance'> {
|
|
25
26
|
readonly kind: 'module-instance';
|
|
26
27
|
readonly template: AnyModuleTemplate;
|
|
27
28
|
readonly args: unknown;
|
|
28
29
|
readonly definition: TDefinition;
|
|
29
30
|
readonly [moduleTypeInfo]?: ModuleTypeInfo<TDefinition>;
|
|
30
31
|
}
|
|
31
|
-
export interface AnyModuleTemplate {
|
|
32
|
+
export interface AnyModuleTemplate extends Descriptor<'module-template'> {
|
|
32
33
|
(args?: any): ModuleInstance<any>;
|
|
33
34
|
readonly kind: 'module-template';
|
|
34
35
|
readonly instantiate: (args: any) => ModuleInstance<any>;
|
|
@@ -40,11 +41,10 @@ export type ModuleTemplate<Args, TDefinition extends ModuleDefinition = ModuleDe
|
|
|
40
41
|
(args: Args): ModuleInstance<TDefinition>;
|
|
41
42
|
}) & {
|
|
42
43
|
readonly kind: 'module-template';
|
|
44
|
+
readonly '~loutre.descriptor': 'module-template';
|
|
43
45
|
readonly instantiate: (args: Args) => ModuleInstance<TDefinition>;
|
|
44
46
|
readonly [moduleTypeInfo]?: ModuleTypeInfo<TDefinition>;
|
|
45
47
|
};
|
|
46
|
-
export type ModuleInput = ModuleInstance | ModuleTemplate<void>;
|
|
47
48
|
export declare function defineModule<const TDefinition extends ModuleDefinition>(definition: TDefinition): ModuleInstance<TDefinition>;
|
|
48
49
|
export declare function defineModule<Args = void, const TDefinition extends ModuleDefinition = ModuleDefinition>(factory: (args: Args) => TDefinition): ModuleTemplate<Args, TDefinition>;
|
|
49
|
-
export declare function asModuleInstance(module: ModuleInput): ModuleInstance;
|
|
50
50
|
export {};
|
package/dist/core/module.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import type { Descriptor } from '../internal/brand.js';
|
|
1
2
|
import type { TokenLike } from './token.js';
|
|
2
3
|
export type RuntimeInputContract = TokenLike<object> & {
|
|
3
4
|
readonly name: string;
|
|
4
5
|
};
|
|
5
|
-
export interface RuntimeInputKey<TValue = unknown> {
|
|
6
|
+
export interface RuntimeInputKey<TValue = unknown> extends Descriptor<'runtime-input-key'> {
|
|
6
7
|
readonly kind: 'runtime-input-key';
|
|
7
8
|
readonly source: 'environment' | 'arguments';
|
|
8
9
|
readonly contract: RuntimeInputContract;
|
|
@@ -1,8 +1,20 @@
|
|
|
1
|
-
|
|
1
|
+
import type { Brand } from '../internal/brand.js';
|
|
2
|
+
export type SourceFileReference = Brand<string, 'source.file-reference'>;
|
|
3
|
+
export type SourceLine = Brand<number, 'source.line'>;
|
|
4
|
+
export type SourceColumn = Brand<number, 'source.column'>;
|
|
5
|
+
export declare const sourceFileReference: (value: string) => SourceFileReference;
|
|
6
|
+
export declare const sourceLine: (value: number) => SourceLine;
|
|
7
|
+
export declare const sourceColumn: (value: number) => SourceColumn;
|
|
8
|
+
export interface SourceLocationInput {
|
|
2
9
|
readonly file: string;
|
|
3
10
|
readonly line?: number;
|
|
4
11
|
readonly column?: number;
|
|
5
12
|
}
|
|
6
|
-
export
|
|
13
|
+
export interface SourceLocation {
|
|
14
|
+
readonly file: SourceFileReference;
|
|
15
|
+
readonly line?: SourceLine;
|
|
16
|
+
readonly column?: SourceColumn;
|
|
17
|
+
}
|
|
18
|
+
export declare function registerSourceLocation<T>(value: T, source: SourceLocationInput): T;
|
|
7
19
|
export declare function getSourceLocation(value: unknown): SourceLocation | undefined;
|
|
8
20
|
export declare function inheritSourceLocation<T>(target: T, source: unknown): T;
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
export const sourceFileReference = (value) => value;
|
|
2
|
+
export const sourceLine = (value) => value;
|
|
3
|
+
export const sourceColumn = (value) => value;
|
|
1
4
|
const sourceMetadata = new WeakMap();
|
|
2
5
|
function asObject(value) {
|
|
3
6
|
return (typeof value === 'object' && value !== null) ||
|
|
@@ -7,9 +10,11 @@ function asObject(value) {
|
|
|
7
10
|
}
|
|
8
11
|
function snapshotSourceLocation(source) {
|
|
9
12
|
return Object.freeze({
|
|
10
|
-
file: source.file,
|
|
11
|
-
...(source.line === undefined ? {} : { line: source.line }),
|
|
12
|
-
...(source.column === undefined
|
|
13
|
+
file: sourceFileReference(source.file),
|
|
14
|
+
...(source.line === undefined ? {} : { line: sourceLine(source.line) }),
|
|
15
|
+
...(source.column === undefined
|
|
16
|
+
? {}
|
|
17
|
+
: { column: sourceColumn(source.column) }),
|
|
13
18
|
});
|
|
14
19
|
}
|
|
15
20
|
export function registerSourceLocation(value, source) {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export const frameworkProvidedTokenBrand = Symbol.for('loutre.framework-provided-token');
|
|
2
2
|
export function isFrameworkProvidedToken(token) {
|
|
3
|
-
return (token
|
|
3
|
+
return (Object.hasOwn(token, frameworkProvidedTokenBrand) &&
|
|
4
|
+
frameworkProvidedTokenBrand in token &&
|
|
5
|
+
token[frameworkProvidedTokenBrand] === true);
|
|
4
6
|
}
|
package/dist/core/token.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
import type { Descriptor } from '../internal/brand.js';
|
|
2
|
+
import type { TokenKey } from './identity.js';
|
|
1
3
|
export interface TokenOptions {
|
|
2
4
|
readonly description?: string;
|
|
3
5
|
}
|
|
4
|
-
export interface Token<T> {
|
|
6
|
+
export interface Token<T> extends Descriptor<'token'> {
|
|
5
7
|
readonly kind: 'token';
|
|
6
8
|
readonly id: string;
|
|
7
9
|
readonly description?: string;
|
|
8
|
-
readonly key:
|
|
10
|
+
readonly key: TokenKey;
|
|
9
11
|
readonly '~type'?: T;
|
|
10
12
|
}
|
|
11
13
|
export type Class<T = unknown> = new (...args: any[]) => T;
|
package/dist/core/token.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isLoggerTokenIdentity } from './logger-identity.js';
|
|
1
2
|
export function token(id, options = {}) {
|
|
2
3
|
return Object.freeze({
|
|
3
4
|
kind: 'token',
|
|
@@ -9,5 +10,7 @@ export function token(id, options = {}) {
|
|
|
9
10
|
});
|
|
10
11
|
}
|
|
11
12
|
export function tokenName(value) {
|
|
13
|
+
if (isLoggerTokenIdentity(value))
|
|
14
|
+
return 'LoggerToken';
|
|
12
15
|
return typeof value === 'function' ? value.name : value.id;
|
|
13
16
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Brand } from '../internal/brand.js';
|
|
2
|
+
export type DurationMs = Brand<number, 'duration.ms'>;
|
|
3
|
+
export type DurationSeconds = Brand<number, 'duration.seconds'>;
|
|
4
|
+
export type EpochMs = Brand<number, 'time.epoch-ms'>;
|
|
5
|
+
export type MonotonicMs = Brand<number, 'time.monotonic-ms'>;
|
|
6
|
+
export type ByteLength = Brand<number, 'bytes.length'>;
|
|
7
|
+
export type ByteLimit = Brand<number, 'bytes.limit'>;
|
|
8
|
+
export type CaptureDepthLimit = Brand<number, 'capture.depth-limit'>;
|
|
9
|
+
export declare const milliseconds: (value: number) => DurationMs;
|
|
10
|
+
export declare const seconds: (value: number) => DurationSeconds;
|
|
11
|
+
export declare const epochMilliseconds: (value: number) => EpochMs;
|
|
12
|
+
export declare const monotonicMilliseconds: (value: number) => MonotonicMs;
|
|
13
|
+
export declare const byteLimit: (value: number) => ByteLimit;
|
|
14
|
+
export declare const captureDepthLimit: (value: number) => CaptureDepthLimit;
|
|
15
|
+
export declare const utf8ByteLength: (value: string) => ByteLength;
|
|
16
|
+
export declare const epochNow: () => EpochMs;
|
|
17
|
+
export declare const monotonicNow: () => MonotonicMs;
|
|
18
|
+
export declare const elapsed: (start: MonotonicMs, end: MonotonicMs) => DurationMs;
|
|
19
|
+
export declare const expiresAt: (now: EpochMs, ttl: DurationMs) => EpochMs;
|
|
20
|
+
export declare const epochFromMonotonic: (value: MonotonicMs) => EpochMs;
|
|
21
|
+
export declare const secondsToMilliseconds: (value: DurationSeconds) => DurationMs;
|
|
22
|
+
export declare const epochDifference: (start: EpochMs, end: EpochMs) => DurationMs;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const milliseconds = (value) => value;
|
|
2
|
+
export const seconds = (value) => value;
|
|
3
|
+
export const epochMilliseconds = (value) => value;
|
|
4
|
+
export const monotonicMilliseconds = (value) => value;
|
|
5
|
+
export const byteLimit = (value) => value;
|
|
6
|
+
export const captureDepthLimit = (value) => value;
|
|
7
|
+
export const utf8ByteLength = (value) => new TextEncoder().encode(value).byteLength;
|
|
8
|
+
export const epochNow = () => epochMilliseconds(Date.now());
|
|
9
|
+
export const monotonicNow = () => monotonicMilliseconds(performance.now());
|
|
10
|
+
export const elapsed = (start, end) => milliseconds(end - start);
|
|
11
|
+
export const expiresAt = (now, ttl) => epochMilliseconds(now + ttl);
|
|
12
|
+
export const epochFromMonotonic = (value) => epochMilliseconds(performance.timeOrigin + value);
|
|
13
|
+
export const secondsToMilliseconds = (value) => milliseconds(value * 1_000);
|
|
14
|
+
export const epochDifference = (start, end) => milliseconds(end - start);
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import type { RunId, TraceId, SpanId, CapsuleId, CaptureHandleId } from './identity.js';
|
|
2
|
+
import type { ModelNodeId } from '../core/model/identity.js';
|
|
3
|
+
import type { RuntimeExecutionId } from '../core/identity.js';
|
|
4
|
+
import type { EpochMs } from '../core/units.js';
|
|
1
5
|
import type { RuntimeExecutionMetadata } from '../core/instrumentation.js';
|
|
2
6
|
import type { DevtoolsModuleOptions } from './module.js';
|
|
3
7
|
import type { ReplayCapsuleRequest, ReplayExecutionContext, RuntimeInvocationResult } from './inspector.js';
|
|
@@ -11,23 +15,23 @@ export type CapturedValue = {
|
|
|
11
15
|
readonly value: unknown;
|
|
12
16
|
} | {
|
|
13
17
|
readonly mode: 'reference';
|
|
14
|
-
readonly handleId:
|
|
18
|
+
readonly handleId: CaptureHandleId;
|
|
15
19
|
} | {
|
|
16
20
|
readonly mode: 'unavailable';
|
|
17
21
|
readonly reason: string;
|
|
18
22
|
};
|
|
19
23
|
export interface ExecutionReplayCapsulePreview {
|
|
20
|
-
readonly id:
|
|
24
|
+
readonly id: CapsuleId;
|
|
21
25
|
readonly kind: 'execution';
|
|
22
|
-
readonly runId:
|
|
23
|
-
readonly traceId:
|
|
24
|
-
readonly spanId:
|
|
25
|
-
readonly createdAt:
|
|
26
|
-
readonly expiresAt:
|
|
26
|
+
readonly runId: RunId;
|
|
27
|
+
readonly traceId: TraceId;
|
|
28
|
+
readonly spanId: SpanId;
|
|
29
|
+
readonly createdAt: EpochMs;
|
|
30
|
+
readonly expiresAt: EpochMs;
|
|
27
31
|
readonly execution: {
|
|
28
|
-
readonly executionId:
|
|
32
|
+
readonly executionId: RuntimeExecutionId;
|
|
29
33
|
readonly executionKind: string;
|
|
30
|
-
readonly graphNodeId?:
|
|
34
|
+
readonly graphNodeId?: ModelNodeId;
|
|
31
35
|
readonly name: string;
|
|
32
36
|
};
|
|
33
37
|
readonly input: DevtoolsValuePreview;
|
|
@@ -42,10 +46,10 @@ export interface ReplayCapsuleStoreOptions {
|
|
|
42
46
|
}
|
|
43
47
|
export declare class ReplayCapsuleStore {
|
|
44
48
|
#private;
|
|
45
|
-
constructor(runId:
|
|
46
|
-
createExecution(traceId:
|
|
47
|
-
preview(capsuleId:
|
|
49
|
+
constructor(runId: RunId, options?: ReplayCapsuleStoreOptions);
|
|
50
|
+
createExecution(traceId: TraceId, spanId: SpanId, observation: RuntimeExecutionMetadata, registration: ReplayRegistration): ExecutionReplayCapsulePreview;
|
|
51
|
+
preview(capsuleId: CapsuleId): ExecutionReplayCapsulePreview | undefined;
|
|
48
52
|
replay(request: ReplayCapsuleRequest): Promise<RuntimeInvocationResult>;
|
|
49
|
-
discard(capsuleId:
|
|
53
|
+
discard(capsuleId: CapsuleId): void;
|
|
50
54
|
clear(): void;
|
|
51
55
|
}
|
package/dist/devtools/capsule.js
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
function capsuleLimit(value) {
|
|
2
|
+
if (!Number.isInteger(value) || value < 1)
|
|
3
|
+
throw new TypeError('maxCapsules must be a positive integer.');
|
|
4
|
+
return value;
|
|
5
|
+
}
|
|
6
|
+
import { createCapsuleId, createCaptureHandleId } from './identity-internal.js';
|
|
7
|
+
import { milliseconds, epochNow, expiresAt } from '../core/units.js';
|
|
1
8
|
import { serializeDevtoolsError } from './observer.js';
|
|
2
9
|
import { previewDevtoolsValue } from './values.js';
|
|
3
10
|
import { match } from 'ts-pattern';
|
|
@@ -13,21 +20,18 @@ export class ReplayCapsuleStore {
|
|
|
13
20
|
#references = new Map();
|
|
14
21
|
constructor(runId, options = {}) {
|
|
15
22
|
this.#runId = runId;
|
|
16
|
-
this.#ttlMs = options.ttlMs ?? defaultCapsuleTtlMs;
|
|
17
|
-
this.#maxCapsules = options.maxCapsules ?? defaultMaxCapsules;
|
|
23
|
+
this.#ttlMs = milliseconds(options.ttlMs ?? defaultCapsuleTtlMs);
|
|
24
|
+
this.#maxCapsules = capsuleLimit(options.maxCapsules ?? defaultMaxCapsules);
|
|
18
25
|
this.#capture = options.capture;
|
|
19
26
|
this.#redact = options.redact ?? [];
|
|
20
27
|
if (!Number.isFinite(this.#ttlMs) || this.#ttlMs <= 0) {
|
|
21
28
|
throw new TypeError('capsuleTtlMs must be a positive finite number.');
|
|
22
29
|
}
|
|
23
|
-
if (!Number.isInteger(this.#maxCapsules) || this.#maxCapsules < 1) {
|
|
24
|
-
throw new TypeError('maxCapsules must be a positive integer.');
|
|
25
|
-
}
|
|
26
30
|
}
|
|
27
31
|
createExecution(traceId, spanId, observation, registration) {
|
|
28
32
|
this.#purgeExpired();
|
|
29
|
-
const id =
|
|
30
|
-
const createdAt =
|
|
33
|
+
const id = createCapsuleId();
|
|
34
|
+
const createdAt = epochNow();
|
|
31
35
|
const captured = this.#captureValue(registration.input);
|
|
32
36
|
const preview = {
|
|
33
37
|
id,
|
|
@@ -36,7 +40,7 @@ export class ReplayCapsuleStore {
|
|
|
36
40
|
traceId,
|
|
37
41
|
spanId,
|
|
38
42
|
createdAt,
|
|
39
|
-
expiresAt: createdAt
|
|
43
|
+
expiresAt: expiresAt(createdAt, this.#ttlMs),
|
|
40
44
|
execution: {
|
|
41
45
|
executionId: observation.executionId,
|
|
42
46
|
executionKind: observation.executionKind,
|
|
@@ -145,7 +149,7 @@ export class ReplayCapsuleStore {
|
|
|
145
149
|
// cloneできない値を失うより、同一process内だけで有効な参照として保持する。
|
|
146
150
|
}
|
|
147
151
|
if (value !== undefined) {
|
|
148
|
-
const handleId =
|
|
152
|
+
const handleId = createCaptureHandleId();
|
|
149
153
|
this.#references.set(handleId, value);
|
|
150
154
|
return { mode: 'reference', handleId };
|
|
151
155
|
}
|
|
@@ -166,7 +170,7 @@ export class ReplayCapsuleStore {
|
|
|
166
170
|
.exhaustive();
|
|
167
171
|
}
|
|
168
172
|
#purgeExpired() {
|
|
169
|
-
const now =
|
|
173
|
+
const now = epochNow();
|
|
170
174
|
for (const [id, capsule] of this.#capsules) {
|
|
171
175
|
if (capsule.preview.expiresAt > now)
|
|
172
176
|
continue;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { RuntimeEvent } from './observer.js';
|
|
2
|
+
import type { ReplayCapsuleRequest, ProviderPlaygroundRequest, ProviderMethodInvocationRequest } from './inspector.js';
|
|
3
|
+
export declare const isDevtoolsRecord: (value: unknown) => value is Record<string, unknown>;
|
|
4
|
+
export declare function decodeRuntimeEvent(value: unknown): RuntimeEvent | undefined;
|
|
5
|
+
export type InspectorCommand = {
|
|
6
|
+
readonly type: 'command.replay-capsule';
|
|
7
|
+
readonly request: ReplayCapsuleRequest;
|
|
8
|
+
} | {
|
|
9
|
+
readonly type: 'command.provider-playground';
|
|
10
|
+
readonly request: ProviderPlaygroundRequest;
|
|
11
|
+
} | {
|
|
12
|
+
readonly type: 'command.invoke-provider-method';
|
|
13
|
+
readonly request: ProviderMethodInvocationRequest;
|
|
14
|
+
};
|
|
15
|
+
export declare function decodeInspectorCommand(value: unknown): InspectorCommand | undefined;
|