@spaceteams/warp 0.2.0 → 0.3.1
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/index.d.mts +72 -22
- package/dist/index.mjs +208 -66
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
|
+
//#region src/component/component-meta.d.ts
|
|
2
|
+
type ComponentKind = "repo" | "service" | "usecase" | "client";
|
|
3
|
+
type ComponentMeta = {
|
|
4
|
+
name?: string;
|
|
5
|
+
kind?: ComponentKind;
|
|
6
|
+
tags?: string[];
|
|
7
|
+
};
|
|
8
|
+
//#endregion
|
|
1
9
|
//#region src/run.d.ts
|
|
10
|
+
type WarpMeta = {
|
|
11
|
+
component?: ComponentMeta;
|
|
12
|
+
componentPath?: string;
|
|
13
|
+
componentKey?: string;
|
|
14
|
+
};
|
|
2
15
|
type Run<AmbientContext, ScopeContext = unknown, RunOptions = unknown> = AmbientContext & {
|
|
3
16
|
run: <T>(options: RunOptions, inner: (app: Run<AmbientContext & ScopeContext, ScopeContext, RunOptions>) => Promise<T> | T) => Promise<T> | T;
|
|
17
|
+
warp?: WarpMeta;
|
|
4
18
|
};
|
|
5
19
|
//#endregion
|
|
6
20
|
//#region src/component/index.d.ts
|
|
@@ -13,38 +27,45 @@ type ComponentRef<Ctx, ScopeContext, RunOptions, Out> = {
|
|
|
13
27
|
readonly __runOptions?: RunOptions;
|
|
14
28
|
readonly __out?: Out;
|
|
15
29
|
};
|
|
16
|
-
type
|
|
30
|
+
type ComponentFactoryFn<Ctx, ScopeContext, RunOptions, Deps, Out> = (ctx: Run<Ctx & Deps, ScopeContext, RunOptions>) => Out;
|
|
31
|
+
type ComponentFactory<Ctx, ScopeContext, RunOptions, Deps, Out> = ComponentFactoryFn<Ctx, ScopeContext, RunOptions, Deps, Out> & {
|
|
32
|
+
meta?: ComponentMeta;
|
|
33
|
+
};
|
|
17
34
|
type ComponentInput<Ctx, ScopeContext, RunOptions, Out> = ComponentRef<Ctx, ScopeContext, RunOptions, Out> | Out;
|
|
18
35
|
type Component<Ctx, ScopeContext, RunOptions, Deps, Out> = ComponentRef<Ctx, ScopeContext, RunOptions, Out> & {
|
|
19
36
|
factory: ComponentFactory<Ctx, ScopeContext, RunOptions, Deps, Out>;
|
|
20
37
|
deps?: { [K in keyof Deps]: ComponentRef<Ctx, ScopeContext, RunOptions, Deps[K]> };
|
|
21
|
-
|
|
38
|
+
meta?: ComponentMeta;
|
|
22
39
|
};
|
|
23
40
|
type ComponentDefinition<Ctx, ScopeContext, RunOptions, Deps, Out> = {
|
|
24
41
|
factory: ComponentFactory<Ctx, ScopeContext, RunOptions, Deps, Out>;
|
|
25
42
|
deps?: { [K in keyof Deps]: ComponentInput<Ctx, ScopeContext, RunOptions, Deps[K]> };
|
|
26
|
-
|
|
43
|
+
meta?: ComponentMeta;
|
|
27
44
|
};
|
|
28
|
-
type InferComponentParams<T> = T extends Component<infer Ctx, infer ScopeContext, infer RunOptions, infer Deps, infer Out> ? [Ctx, ScopeContext, RunOptions, Deps, Out] : never;
|
|
29
|
-
type InferComponentCtx<T> = InferComponentParams<T>[0];
|
|
30
|
-
type InferComponentScopeContext<T> = InferComponentParams<T>[1];
|
|
31
|
-
type InferComponentRunOptions<T> = InferComponentParams<T>[2];
|
|
32
|
-
type InferComponentDeps<T> = InferComponentParams<T>[3];
|
|
33
|
-
type InferComponentOut<T> = InferComponentParams<T>[4];
|
|
34
45
|
declare function brandComponent<T extends object, Ctx, ScopeContext, RunOptions, Out>(obj: T): T & ComponentRef<Ctx, ScopeContext, RunOptions, Out>;
|
|
35
46
|
declare function isComponent(value: unknown): value is Component<unknown, unknown, unknown, unknown, unknown>;
|
|
36
47
|
//#endregion
|
|
37
48
|
//#region src/middleware.d.ts
|
|
38
49
|
type NoRunOptions = NonNullable<unknown>;
|
|
39
50
|
type NoScopeContext = NonNullable<unknown>;
|
|
40
|
-
type Middleware<AmbientContext, RunOptions = NoRunOptions, ScopeContext = NoScopeContext> = <T>(ctx: AmbientContext, options: Partial<RunOptions>, next: (ctx: AmbientContext & ScopeContext) => Promise<T> | T) => Promise<T> | T;
|
|
51
|
+
type Middleware<AmbientContext, RunOptions = NoRunOptions, ScopeContext = NoScopeContext> = <T>(ctx: AmbientContext, options: Partial<RunOptions>, next: (ctx: AmbientContext & ScopeContext) => Promise<T> | T, warp?: WarpMeta | undefined) => Promise<T> | T;
|
|
41
52
|
//#endregion
|
|
42
|
-
//#region src/
|
|
53
|
+
//#region src/explain/index.d.ts
|
|
43
54
|
type ExplainResult = {
|
|
44
55
|
name: string | undefined;
|
|
56
|
+
kind?: string;
|
|
57
|
+
tags?: string[];
|
|
45
58
|
deps?: Record<string, ExplainResult>;
|
|
46
59
|
};
|
|
47
60
|
//#endregion
|
|
61
|
+
//#region src/lazy.d.ts
|
|
62
|
+
type Lazy<T, Args extends unknown[] = []> = (...args: Args) => T;
|
|
63
|
+
declare const Lazy: {
|
|
64
|
+
cached<T, Args extends unknown[] = []>(factory: Lazy<T, Args>): Lazy<T, Args>;
|
|
65
|
+
and<S, T, Args extends unknown[] = []>(l: Lazy<S, Args>, r: Lazy<T, Args>): Lazy<S & T, Args>;
|
|
66
|
+
map<S, T, Args extends unknown[] = []>(l: Lazy<S, Args>, fn: (v: S) => T): Lazy<T, Args>;
|
|
67
|
+
};
|
|
68
|
+
//#endregion
|
|
48
69
|
//#region src/runtime/runtime.d.ts
|
|
49
70
|
type SafeIntersect<A, B> = A extends undefined ? B : A & B;
|
|
50
71
|
type OptionalArg<A> = A extends undefined ? [] : [A];
|
|
@@ -52,19 +73,22 @@ declare class Runtime<Ctx, ActualContext extends Ctx, ScopeContext, RunOptions,
|
|
|
52
73
|
private readonly middleware;
|
|
53
74
|
private readonly ctx;
|
|
54
75
|
private readonly resolveFn;
|
|
55
|
-
constructor(middleware: Middleware<Ctx, RunOptions, ScopeContext>, ctx: ActualContext);
|
|
76
|
+
constructor(middleware: Middleware<Ctx, RunOptions, ScopeContext>, ctx: Lazy<ActualContext>);
|
|
56
77
|
provide<Extension>(ext: Extension): Runtime<Ctx, ActualContext & Extension, ScopeContext, RunOptions, Requirements>;
|
|
78
|
+
provideLazy<Extension>(ext: () => Extension): Runtime<Ctx, ActualContext & Extension, ScopeContext, RunOptions, Requirements>;
|
|
57
79
|
require<Extension>(): Runtime<Ctx, ActualContext, ScopeContext, RunOptions, SafeIntersect<Requirements, Extension>>;
|
|
58
80
|
resolve: <Deps, Out>(component: Component<SafeIntersect<Requirements, ActualContext>, ScopeContext, RunOptions, Deps, Out>, ...requirements: OptionalArg<Requirements>) => Out | Promise<Out>;
|
|
59
|
-
get component(): <Deps, F extends ComponentFactory<SafeIntersect<Requirements, ActualContext>, ScopeContext, RunOptions, Deps, ReturnType<F>>>(factory: F, deps?: { [T in keyof Deps]: ComponentInput<SafeIntersect<Requirements, ActualContext>, ScopeContext, RunOptions, Deps[T]> } | undefined,
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
explain<Deps, Out>(component: Component<SafeIntersect<Requirements, ActualContext>, ScopeContext, RunOptions, Deps, Out>, format: "
|
|
81
|
+
get component(): <Deps, F extends ComponentFactory<SafeIntersect<Requirements, ActualContext>, ScopeContext, RunOptions, Deps, ReturnType<F>>>(factory: F, deps?: { [T in keyof Deps]: ComponentInput<SafeIntersect<Requirements, ActualContext>, ScopeContext, RunOptions, Deps[T]> } | undefined, meta?: ComponentMeta | undefined) => Component<SafeIntersect<Requirements, ActualContext>, ScopeContext, RunOptions, Deps, ReturnType<F>>;
|
|
82
|
+
get singleton(): <Deps, F extends ComponentFactory<SafeIntersect<Requirements, ActualContext>, {}, RunOptions, Deps, ReturnType<F>>>(factory: F, deps?: { [T in keyof Deps]: ComponentInput<SafeIntersect<Requirements, ActualContext>, {}, RunOptions, Deps[T]> } | undefined, meta?: ComponentMeta | undefined) => Component<SafeIntersect<Requirements, ActualContext>, {}, RunOptions, Deps, ReturnType<F>>;
|
|
83
|
+
get classComponent(): <Deps, Ctor extends (new (deps: Run<SafeIntersect<Requirements, ActualContext> & Deps, ScopeContext, RunOptions>) => InstanceType<Ctor>) & {
|
|
84
|
+
meta?: ComponentMeta | undefined;
|
|
85
|
+
}>(ctor: Ctor, deps?: { [K in keyof Deps]: ComponentInput<SafeIntersect<Requirements, ActualContext>, ScopeContext, RunOptions, Deps[K]> } | undefined, meta?: ComponentMeta | undefined) => Component<SafeIntersect<Requirements, ActualContext>, ScopeContext, RunOptions, Deps, InstanceType<Ctor>>;
|
|
86
|
+
get classSingleton(): <Deps, Ctor extends (new (deps: Run<SafeIntersect<Requirements, ActualContext> & Deps, {}, RunOptions>) => InstanceType<Ctor>) & {
|
|
87
|
+
meta?: ComponentMeta | undefined;
|
|
88
|
+
}>(ctor: Ctor, deps?: { [K in keyof Deps]: ComponentInput<SafeIntersect<Requirements, ActualContext>, {}, RunOptions, Deps[K]> } | undefined, meta?: ComponentMeta | undefined) => Component<SafeIntersect<Requirements, ActualContext>, {}, RunOptions, Deps, InstanceType<Ctor>>;
|
|
89
|
+
explain<Deps, Out>(component: Component<SafeIntersect<Requirements, ActualContext>, ScopeContext, RunOptions, Deps, Out>, format: "native", showMeta?: boolean): ExplainResult;
|
|
90
|
+
explain<Deps, Out>(component: Component<SafeIntersect<Requirements, ActualContext>, ScopeContext, RunOptions, Deps, Out>, format: "ascii", showMeta?: boolean): string;
|
|
91
|
+
explain<Deps, Out>(component: Component<SafeIntersect<Requirements, ActualContext>, ScopeContext, RunOptions, Deps, Out>, format: "mermaid", showMeta?: boolean): string;
|
|
68
92
|
explain<Deps, Out>(component: Component<SafeIntersect<Requirements, ActualContext>, ScopeContext, RunOptions, Deps, Out>): ExplainResult;
|
|
69
93
|
}
|
|
70
94
|
//#endregion
|
|
@@ -74,10 +98,36 @@ declare class RuntimeBuilder<AmbientContext, ScopeContext = unknown, Options = u
|
|
|
74
98
|
constructor(middlewares?: Middleware<AmbientContext, Options, ScopeContext>[]);
|
|
75
99
|
use<A, S, H>(mw: Middleware<A, H, S>): RuntimeBuilder<AmbientContext & A, ScopeContext & S, Options & H>;
|
|
76
100
|
provide<ActualCtx extends AmbientContext>(ctx: ActualCtx): Runtime<AmbientContext, ActualCtx, ScopeContext, Options, undefined>;
|
|
101
|
+
provideLazy<ActualCtx extends AmbientContext>(ctx: () => ActualCtx): Runtime<AmbientContext, ActualCtx, ScopeContext, Options, undefined>;
|
|
77
102
|
private buildMiddleware;
|
|
78
103
|
}
|
|
79
104
|
//#endregion
|
|
80
105
|
//#region src/runtime/index.d.ts
|
|
81
106
|
declare function buildRuntime(): RuntimeBuilder<Record<string, unknown>, unknown>;
|
|
82
107
|
//#endregion
|
|
83
|
-
|
|
108
|
+
//#region src/semantic/callable.d.ts
|
|
109
|
+
type Callable<Ctx, ScopeContext, Args extends unknown[], Result, RunOptions> = ComponentFactory<Ctx, ScopeContext, RunOptions, unknown, (...args: Args) => Promise<Result>>;
|
|
110
|
+
declare function callable<Ctx, Args extends unknown[], Result, RunOptions = NoRunOptions, ScopeContext = NoScopeContext>(options: RunOptions & ComponentMeta, fn: (app: Run<Ctx, ScopeContext, RunOptions>) => (...args: Args) => Promise<Result>): Callable<Ctx, ScopeContext, Args, Result, RunOptions>;
|
|
111
|
+
type InferCallable<T> = T extends Callable<infer _Ctx, infer _ScopeContext, infer Args, infer Result, infer _RunOptions> ? (...args: Args) => Promise<Result> : never;
|
|
112
|
+
//#endregion
|
|
113
|
+
//#region src/semantic/client.d.ts
|
|
114
|
+
type Client<Ctx, ScopeContext, Out, RunOptions> = ComponentFactory<Ctx, ScopeContext, RunOptions, unknown, Out>;
|
|
115
|
+
declare function client<Ctx, Out, RunOptions = NoRunOptions, ScopeContext = NoScopeContext>(options: Omit<ComponentMeta, "kind">, fn: (app: Run<Ctx, ScopeContext, RunOptions>) => Out): Client<Ctx, ScopeContext, Out, RunOptions>;
|
|
116
|
+
type InferClient<T> = T extends Client<infer _Ctx, infer _ScopeContext, infer Out, infer _RunOptions> ? Out : never;
|
|
117
|
+
//#endregion
|
|
118
|
+
//#region src/semantic/repo.d.ts
|
|
119
|
+
type Repo<Ctx, ScopeContext, Out, RunOptions> = ComponentFactory<Ctx, ScopeContext, RunOptions, unknown, Out>;
|
|
120
|
+
declare function repo<Ctx, Out, RunOptions = NoRunOptions, ScopeContext = NoScopeContext>(options: Omit<ComponentMeta, "kind">, fn: (app: Run<Ctx, ScopeContext, RunOptions>) => Out): Repo<Ctx, ScopeContext, Out, RunOptions>;
|
|
121
|
+
type InferRepo<T> = T extends Repo<infer _Ctx, infer _ScopeContext, infer Out, infer _RunOptions> ? Out : never;
|
|
122
|
+
//#endregion
|
|
123
|
+
//#region src/semantic/service.d.ts
|
|
124
|
+
type Service<Ctx, ScopeContext, Out, RunOptions> = ComponentFactory<Ctx, ScopeContext, RunOptions, unknown, Out>;
|
|
125
|
+
declare function service<Ctx, Out, RunOptions = NoRunOptions, ScopeContext = NoScopeContext>(options: Omit<ComponentMeta, "kind"> | undefined, fn: (app: Run<Ctx, ScopeContext, RunOptions>) => Out): Service<Ctx, ScopeContext, Out, RunOptions>;
|
|
126
|
+
type InferService<T> = T extends Service<infer _Ctx, infer _ScopeContext, infer Out, infer _RunOptions> ? Out : never;
|
|
127
|
+
//#endregion
|
|
128
|
+
//#region src/semantic/usecase.d.ts
|
|
129
|
+
type Usecase<Ctx, ScopeContext, Args extends unknown[], Result, RunOptions> = Callable<Ctx, ScopeContext, Args, Result, RunOptions>;
|
|
130
|
+
declare function usecase<Ctx, Args extends unknown[], Result, RunOptions = NoRunOptions, ScopeContext = NoScopeContext>(options: RunOptions & Omit<ComponentMeta, "kind">, fn: (app: Run<Ctx, ScopeContext, RunOptions>) => (...args: Args) => Promise<Result>): Usecase<Ctx, ScopeContext, Args, Result, RunOptions>;
|
|
131
|
+
type InferUsecase<T> = InferCallable<T>;
|
|
132
|
+
//#endregion
|
|
133
|
+
export { Callable, Client, Component, ComponentDefinition, ComponentFactory, ComponentFactoryFn, ComponentInput, ComponentKind, ComponentMeta, ComponentRef, InferCallable, InferClient, InferRepo, InferService, InferUsecase, Middleware, NoDeps, NoRunOptions, NoScopeContext, Repo, Run, Service, Usecase, WarpMeta, brandComponent, buildRuntime, callable, client, isComponent, repo, service, usecase };
|
package/dist/index.mjs
CHANGED
|
@@ -13,31 +13,148 @@ function isComponent(value) {
|
|
|
13
13
|
return typeof value === "object" && value !== null && value[COMPONENT] === true;
|
|
14
14
|
}
|
|
15
15
|
//#endregion
|
|
16
|
+
//#region src/lazy.ts
|
|
17
|
+
const Lazy = {
|
|
18
|
+
cached(factory) {
|
|
19
|
+
let cached;
|
|
20
|
+
return (...args) => {
|
|
21
|
+
if (cached === void 0) cached = factory(...args);
|
|
22
|
+
return cached;
|
|
23
|
+
};
|
|
24
|
+
},
|
|
25
|
+
and(l, r) {
|
|
26
|
+
return (...args) => ({
|
|
27
|
+
...l(...args),
|
|
28
|
+
...r(...args)
|
|
29
|
+
});
|
|
30
|
+
},
|
|
31
|
+
map(l, fn) {
|
|
32
|
+
return (...args) => fn(l(...args));
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
//#endregion
|
|
16
36
|
//#region src/component/class-component.ts
|
|
17
37
|
function defineClassComponent() {
|
|
18
|
-
return (ctor, deps,
|
|
38
|
+
return (ctor, deps, meta) => {
|
|
19
39
|
const factory = (ctx) => {
|
|
20
40
|
return new ctor(ctx);
|
|
21
41
|
};
|
|
22
42
|
return brandComponent({
|
|
23
43
|
factory,
|
|
24
44
|
deps,
|
|
25
|
-
|
|
45
|
+
meta: {
|
|
46
|
+
name: (meta?.name ?? ctor.meta?.name) || void 0,
|
|
47
|
+
tags: (meta?.tags ?? ctor.meta?.tags) || void 0,
|
|
48
|
+
kind: (meta?.kind ?? ctor.meta?.kind) || void 0
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
//#endregion
|
|
54
|
+
//#region src/component/class-singleton.ts
|
|
55
|
+
function defineClassSingleton() {
|
|
56
|
+
return (ctor, deps, meta) => {
|
|
57
|
+
const factory = (ctx) => {
|
|
58
|
+
return new ctor(ctx);
|
|
59
|
+
};
|
|
60
|
+
return brandComponent({
|
|
61
|
+
factory: Lazy.cached(factory),
|
|
62
|
+
deps,
|
|
63
|
+
meta: {
|
|
64
|
+
name: (meta?.name ?? ctor.meta?.name) || void 0,
|
|
65
|
+
tags: (meta?.tags ?? ctor.meta?.tags) || void 0,
|
|
66
|
+
kind: (meta?.kind ?? ctor.meta?.kind) || void 0
|
|
67
|
+
}
|
|
26
68
|
});
|
|
27
69
|
};
|
|
28
70
|
}
|
|
29
71
|
//#endregion
|
|
30
72
|
//#region src/component/functional-component.ts
|
|
31
73
|
function defineFunctionalComponent() {
|
|
32
|
-
return (factory, deps,
|
|
74
|
+
return (factory, deps, meta) => {
|
|
33
75
|
return brandComponent({
|
|
34
76
|
factory,
|
|
35
77
|
deps,
|
|
36
|
-
|
|
78
|
+
meta: {
|
|
79
|
+
name: (meta?.name ?? factory.meta?.name) || void 0,
|
|
80
|
+
tags: (meta?.tags ?? factory.meta?.tags) || void 0,
|
|
81
|
+
kind: (meta?.kind ?? factory.meta?.kind) || void 0
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
//#endregion
|
|
87
|
+
//#region src/component/functional-singleton.ts
|
|
88
|
+
function defineFunctionalSingleton() {
|
|
89
|
+
return (factory, deps, meta) => {
|
|
90
|
+
return brandComponent({
|
|
91
|
+
factory: Lazy.cached(factory),
|
|
92
|
+
deps,
|
|
93
|
+
meta: {
|
|
94
|
+
name: (meta?.name ?? factory.meta?.name) || void 0,
|
|
95
|
+
tags: (meta?.tags ?? factory.meta?.tags) || void 0,
|
|
96
|
+
kind: (meta?.kind ?? factory.meta?.kind) || void 0
|
|
97
|
+
}
|
|
37
98
|
});
|
|
38
99
|
};
|
|
39
100
|
}
|
|
40
101
|
//#endregion
|
|
102
|
+
//#region src/explain/index.ts
|
|
103
|
+
const explain = (c) => {
|
|
104
|
+
const deps = {};
|
|
105
|
+
for (const [key, comp] of Object.entries(c.deps ?? {})) deps[key] = explain(comp);
|
|
106
|
+
return {
|
|
107
|
+
name: c.meta?.name,
|
|
108
|
+
kind: c.meta?.kind,
|
|
109
|
+
tags: c.meta?.tags,
|
|
110
|
+
deps
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
//#endregion
|
|
114
|
+
//#region src/explain/ascii.ts
|
|
115
|
+
const formatExplainLabel = (node, showMeta, edgeLabel) => {
|
|
116
|
+
let label = edgeLabel ?? node.name ?? "unnamed";
|
|
117
|
+
if (edgeLabel && showMeta && node.name) label += ` -> ${node.name}`;
|
|
118
|
+
if (showMeta && node.kind) label += ` [${node.kind}]`;
|
|
119
|
+
if (showMeta && node.tags?.length) label += ` {${node.tags.join(", ")}}`;
|
|
120
|
+
return label;
|
|
121
|
+
};
|
|
122
|
+
const toAsciiTree = (result, prefix = "", isLast = true, showMeta = false, edgeLabel) => {
|
|
123
|
+
const line = `${prefix}${isLast ? "└── " : "├── "}${formatExplainLabel(result, showMeta, edgeLabel)}`;
|
|
124
|
+
const deps = Object.entries(result.deps ?? {});
|
|
125
|
+
if (deps.length === 0) return line;
|
|
126
|
+
const childPrefix = prefix + (isLast ? " " : "│ ");
|
|
127
|
+
return [line, ...deps.map(([key, dep], index) => toAsciiTree(dep, childPrefix, index === deps.length - 1, showMeta, key))].join("\n");
|
|
128
|
+
};
|
|
129
|
+
//#endregion
|
|
130
|
+
//#region src/explain/mermaid.ts
|
|
131
|
+
const sanitizeMermaidId = (value) => value.replace(/[^a-zA-Z0-9_]/g, "_");
|
|
132
|
+
const escapeMermaidLabel = (value) => value.replace(/"/g, "\\\"");
|
|
133
|
+
const formatMermaidLabel = (node, showMeta, fallbackName) => {
|
|
134
|
+
let label = node.name ?? fallbackName;
|
|
135
|
+
if (showMeta) {
|
|
136
|
+
const metaParts = [];
|
|
137
|
+
if (node.kind) metaParts.push(node.kind);
|
|
138
|
+
if (node.tags?.length) metaParts.push(node.tags.join(", "));
|
|
139
|
+
if (metaParts.length > 0) label += `<br/>[${metaParts.join(" | ")}]`;
|
|
140
|
+
}
|
|
141
|
+
return escapeMermaidLabel(label);
|
|
142
|
+
};
|
|
143
|
+
const collectMermaidLines = (node, nodeId, showMeta, fallbackName) => {
|
|
144
|
+
const lines = [];
|
|
145
|
+
lines.push(` ${nodeId}["${formatMermaidLabel(node, showMeta, fallbackName)}"]`);
|
|
146
|
+
Object.entries(node.deps ?? {}).forEach(([key, dep], index) => {
|
|
147
|
+
const childId = sanitizeMermaidId(`${nodeId}__${key}__${dep.name ?? key ?? `node_${index}`}`);
|
|
148
|
+
lines.push(` ${nodeId} -->|${escapeMermaidLabel(key)}| ${childId}`);
|
|
149
|
+
lines.push(...collectMermaidLines(dep, childId, showMeta, key));
|
|
150
|
+
});
|
|
151
|
+
return lines;
|
|
152
|
+
};
|
|
153
|
+
const toMermaid = (result, showMeta = false) => {
|
|
154
|
+
const rootName = result.name ?? "root";
|
|
155
|
+
return ["graph TD", ...collectMermaidLines(result, sanitizeMermaidId(rootName), showMeta, rootName)].join("\n");
|
|
156
|
+
};
|
|
157
|
+
//#endregion
|
|
41
158
|
//#region src/runtime/create-resolver.ts
|
|
42
159
|
function createResolver(mw) {
|
|
43
160
|
return (root, ctx) => {
|
|
@@ -62,7 +179,7 @@ function createResolver(mw) {
|
|
|
62
179
|
get() {
|
|
63
180
|
if (cache.has(depName)) return cache.get(depName);
|
|
64
181
|
checkCyclicDependency(depPath);
|
|
65
|
-
const out = withStackTracking(depPath, () => bindInScope(depComp, scopeCtx, depPath));
|
|
182
|
+
const out = withStackTracking(depPath, () => bindInScope(depComp, scopeCtx, depPath, depName));
|
|
66
183
|
cache.set(depName, out);
|
|
67
184
|
return out;
|
|
68
185
|
}
|
|
@@ -71,77 +188,39 @@ function createResolver(mw) {
|
|
|
71
188
|
const attachDependencies = (runCtx, deps, scopeCtx, pathPrefix, cache) => {
|
|
72
189
|
for (const [depName, depComp] of Object.entries(deps)) defineDependencyProperty(runCtx, depName, pathPrefix ? `${pathPrefix}.${depName}` : depName, depComp, scopeCtx, cache);
|
|
73
190
|
};
|
|
74
|
-
const createBaseRunContext = (scopeCtx) => {
|
|
191
|
+
const createBaseRunContext = (scopeCtx, warp) => {
|
|
75
192
|
return {
|
|
76
193
|
...scopeCtx,
|
|
77
|
-
|
|
194
|
+
warp,
|
|
195
|
+
run: (nestedOptions, nestedInner) => runWithContext(scopeCtx, nestedOptions, nestedInner, warp)
|
|
78
196
|
};
|
|
79
197
|
};
|
|
80
|
-
const bindInScope = (comp, scopeCtx, path) => {
|
|
198
|
+
const bindInScope = (comp, scopeCtx, path, depName) => {
|
|
81
199
|
const localDepCache = /* @__PURE__ */ new Map();
|
|
82
|
-
const runCtx = createBaseRunContext(scopeCtx);
|
|
83
200
|
if (!isComponent(comp)) return comp;
|
|
201
|
+
const runCtx = createBaseRunContext(scopeCtx, {
|
|
202
|
+
component: comp.meta,
|
|
203
|
+
componentPath: path,
|
|
204
|
+
componentKey: depName
|
|
205
|
+
});
|
|
84
206
|
attachDependencies(runCtx, comp.deps ?? {}, scopeCtx, path, localDepCache);
|
|
85
207
|
return comp.factory(runCtx);
|
|
86
208
|
};
|
|
87
209
|
const makeRootRunContext = (scopeCtx) => {
|
|
88
210
|
const rootCache = /* @__PURE__ */ new Map();
|
|
89
|
-
const runCtx = createBaseRunContext(scopeCtx);
|
|
211
|
+
const runCtx = createBaseRunContext(scopeCtx, { component: root.meta });
|
|
90
212
|
attachDependencies(runCtx, root.deps ?? {}, scopeCtx, "", rootCache);
|
|
91
213
|
return runCtx;
|
|
92
214
|
};
|
|
93
|
-
const runWithContext = async (currentCtx, options, inner) => {
|
|
215
|
+
const runWithContext = async (currentCtx, options, inner, warp) => {
|
|
94
216
|
return await mw(currentCtx, options, (scopedCtx) => {
|
|
95
217
|
return inner(makeRootRunContext(scopedCtx));
|
|
96
|
-
});
|
|
218
|
+
}, warp);
|
|
97
219
|
};
|
|
98
220
|
return root.factory(makeRootRunContext(ctx));
|
|
99
221
|
};
|
|
100
222
|
}
|
|
101
223
|
//#endregion
|
|
102
|
-
//#region src/runtime/explain.ts
|
|
103
|
-
const explain = (c) => {
|
|
104
|
-
const deps = {};
|
|
105
|
-
for (const [key, comp] of Object.entries(c.deps ?? {})) deps[key] = explain(comp);
|
|
106
|
-
return {
|
|
107
|
-
name: c.name,
|
|
108
|
-
deps
|
|
109
|
-
};
|
|
110
|
-
};
|
|
111
|
-
const toAsciiTree = (result, prefix = "", isLast = true) => {
|
|
112
|
-
const lines = [];
|
|
113
|
-
const connector = isLast ? "└── " : "├── ";
|
|
114
|
-
lines.push(prefix + connector + result.name);
|
|
115
|
-
const deps = Object.entries(result.deps ?? {});
|
|
116
|
-
const newPrefix = prefix + (isLast ? " " : "│ ");
|
|
117
|
-
deps.forEach(([key, dep], index) => {
|
|
118
|
-
const isLastDep = index === deps.length - 1;
|
|
119
|
-
const connector = isLastDep ? "└── " : "├── ";
|
|
120
|
-
lines.push(`${newPrefix}${connector}[${key}]`);
|
|
121
|
-
const childLines = toAsciiTree(dep, newPrefix + (isLastDep ? " " : "│ "), true).split("\n").slice(1);
|
|
122
|
-
lines.push(...childLines);
|
|
123
|
-
});
|
|
124
|
-
return lines.join("\n");
|
|
125
|
-
};
|
|
126
|
-
const toMermaid = (result, nodeId, isRoot = true) => {
|
|
127
|
-
const lines = [];
|
|
128
|
-
if (isRoot) {
|
|
129
|
-
lines.push("graph TD");
|
|
130
|
-
nodeId = result.name ?? "root";
|
|
131
|
-
}
|
|
132
|
-
const sanitizedId = nodeId.replace(/[^a-zA-Z0-9_]/g, "_");
|
|
133
|
-
if (isRoot) lines.push(` ${sanitizedId}["${result.name}"]`);
|
|
134
|
-
Object.entries(result.deps ?? {}).forEach(([key, dep]) => {
|
|
135
|
-
const sanitizedDepId = (dep.name ? `${sanitizedId}_${dep.name}` : `${sanitizedId}_${key}`).replace(/[^a-zA-Z0-9_]/g, "_");
|
|
136
|
-
const displayName = dep.name ?? key;
|
|
137
|
-
lines.push(` ${sanitizedDepId}["${displayName}"]`);
|
|
138
|
-
lines.push(` ${sanitizedId} -->|${key}| ${sanitizedDepId}`);
|
|
139
|
-
const childLines = toMermaid(dep, sanitizedDepId, false).split("\n").slice(1);
|
|
140
|
-
lines.push(...childLines);
|
|
141
|
-
});
|
|
142
|
-
return lines.join("\n");
|
|
143
|
-
};
|
|
144
|
-
//#endregion
|
|
145
224
|
//#region src/runtime/runtime.ts
|
|
146
225
|
var Runtime = class Runtime {
|
|
147
226
|
resolveFn;
|
|
@@ -151,10 +230,10 @@ var Runtime = class Runtime {
|
|
|
151
230
|
this.resolveFn = createResolver(middleware);
|
|
152
231
|
}
|
|
153
232
|
provide(ext) {
|
|
154
|
-
return new Runtime(this.middleware,
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
233
|
+
return new Runtime(this.middleware, Lazy.and(this.ctx, () => ext));
|
|
234
|
+
}
|
|
235
|
+
provideLazy(ext) {
|
|
236
|
+
return new Runtime(this.middleware, Lazy.and(this.ctx, Lazy.cached(ext)));
|
|
158
237
|
}
|
|
159
238
|
require() {
|
|
160
239
|
return new Runtime(this.middleware, this.ctx);
|
|
@@ -162,22 +241,28 @@ var Runtime = class Runtime {
|
|
|
162
241
|
resolve = (component, ...requirements) => {
|
|
163
242
|
const req = requirements[0];
|
|
164
243
|
const ctx = req ? {
|
|
165
|
-
...this.ctx,
|
|
244
|
+
...this.ctx(),
|
|
166
245
|
...req
|
|
167
|
-
} : { ...this.ctx };
|
|
246
|
+
} : { ...this.ctx() };
|
|
168
247
|
return this.resolveFn(component, ctx);
|
|
169
248
|
};
|
|
170
249
|
get component() {
|
|
171
250
|
return defineFunctionalComponent();
|
|
172
251
|
}
|
|
252
|
+
get singleton() {
|
|
253
|
+
return defineFunctionalSingleton();
|
|
254
|
+
}
|
|
173
255
|
get classComponent() {
|
|
174
256
|
return defineClassComponent();
|
|
175
257
|
}
|
|
176
|
-
|
|
258
|
+
get classSingleton() {
|
|
259
|
+
return defineClassSingleton();
|
|
260
|
+
}
|
|
261
|
+
explain(component, format = "native", showMeta = false) {
|
|
177
262
|
const result = explain(component);
|
|
178
263
|
switch (format) {
|
|
179
|
-
case "ascii": return toAsciiTree(result);
|
|
180
|
-
case "mermaid": return toMermaid(result);
|
|
264
|
+
case "ascii": return toAsciiTree(result, "", true, showMeta);
|
|
265
|
+
case "mermaid": return toMermaid(result, showMeta);
|
|
181
266
|
case "native": return result;
|
|
182
267
|
}
|
|
183
268
|
}
|
|
@@ -193,7 +278,10 @@ var RuntimeBuilder = class RuntimeBuilder {
|
|
|
193
278
|
return new RuntimeBuilder([...this.middlewares, mw]);
|
|
194
279
|
}
|
|
195
280
|
provide(ctx) {
|
|
196
|
-
return new Runtime(this.buildMiddleware(), ctx);
|
|
281
|
+
return new Runtime(this.buildMiddleware(), () => ctx);
|
|
282
|
+
}
|
|
283
|
+
provideLazy(ctx) {
|
|
284
|
+
return new Runtime(this.buildMiddleware(), Lazy.cached(ctx));
|
|
197
285
|
}
|
|
198
286
|
buildMiddleware() {
|
|
199
287
|
const middlewares = this.middlewares;
|
|
@@ -216,4 +304,58 @@ function buildRuntime() {
|
|
|
216
304
|
return new RuntimeBuilder();
|
|
217
305
|
}
|
|
218
306
|
//#endregion
|
|
219
|
-
|
|
307
|
+
//#region src/semantic/callable.ts
|
|
308
|
+
function callable(options, fn) {
|
|
309
|
+
const factory = (ctx) => (...args) => {
|
|
310
|
+
return ctx.run(options, (inner) => fn(inner)(...args));
|
|
311
|
+
};
|
|
312
|
+
Object.assign(factory, { meta: {
|
|
313
|
+
kind: options.kind,
|
|
314
|
+
name: options.name,
|
|
315
|
+
tags: options.tags
|
|
316
|
+
} });
|
|
317
|
+
return factory;
|
|
318
|
+
}
|
|
319
|
+
//#endregion
|
|
320
|
+
//#region src/semantic/client.ts
|
|
321
|
+
function client(options, fn) {
|
|
322
|
+
const factory = fn;
|
|
323
|
+
Object.assign(factory, { meta: {
|
|
324
|
+
kind: "client",
|
|
325
|
+
name: options.name,
|
|
326
|
+
tags: options.tags
|
|
327
|
+
} });
|
|
328
|
+
return factory;
|
|
329
|
+
}
|
|
330
|
+
//#endregion
|
|
331
|
+
//#region src/semantic/repo.ts
|
|
332
|
+
function repo(options, fn) {
|
|
333
|
+
const factory = fn;
|
|
334
|
+
Object.assign(factory, { meta: {
|
|
335
|
+
kind: "repo",
|
|
336
|
+
name: options.name,
|
|
337
|
+
tags: options.tags
|
|
338
|
+
} });
|
|
339
|
+
return factory;
|
|
340
|
+
}
|
|
341
|
+
//#endregion
|
|
342
|
+
//#region src/semantic/service.ts
|
|
343
|
+
function service(options = {}, fn) {
|
|
344
|
+
const factory = fn;
|
|
345
|
+
Object.assign(factory, { meta: {
|
|
346
|
+
kind: "service",
|
|
347
|
+
name: options.name,
|
|
348
|
+
tags: options.tags
|
|
349
|
+
} });
|
|
350
|
+
return factory;
|
|
351
|
+
}
|
|
352
|
+
//#endregion
|
|
353
|
+
//#region src/semantic/usecase.ts
|
|
354
|
+
function usecase(options, fn) {
|
|
355
|
+
return callable({
|
|
356
|
+
kind: "usecase",
|
|
357
|
+
...options
|
|
358
|
+
}, fn);
|
|
359
|
+
}
|
|
360
|
+
//#endregion
|
|
361
|
+
export { brandComponent, buildRuntime, callable, client, isComponent, repo, service, usecase };
|