@arki/dot 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.
Files changed (107) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +201 -0
  3. package/dist/cli/discover.d.ts +65 -0
  4. package/dist/cli/discover.d.ts.map +1 -0
  5. package/dist/cli/discover.js +184 -0
  6. package/dist/cli/discover.js.map +1 -0
  7. package/dist/cli/error-codes.d.ts +49 -0
  8. package/dist/cli/error-codes.d.ts.map +1 -0
  9. package/dist/cli/error-codes.js +61 -0
  10. package/dist/cli/error-codes.js.map +1 -0
  11. package/dist/cli/files.d.ts +67 -0
  12. package/dist/cli/files.d.ts.map +1 -0
  13. package/dist/cli/files.js +80 -0
  14. package/dist/cli/files.js.map +1 -0
  15. package/dist/cli/index.d.ts +95 -0
  16. package/dist/cli/index.d.ts.map +1 -0
  17. package/dist/cli/index.js +456 -0
  18. package/dist/cli/index.js.map +1 -0
  19. package/dist/cli/json.d.ts +38 -0
  20. package/dist/cli/json.d.ts.map +1 -0
  21. package/dist/cli/json.js +18 -0
  22. package/dist/cli/json.js.map +1 -0
  23. package/dist/cli/new.d.ts +105 -0
  24. package/dist/cli/new.d.ts.map +1 -0
  25. package/dist/cli/new.js +322 -0
  26. package/dist/cli/new.js.map +1 -0
  27. package/dist/cli/observability-probe.d.ts +28 -0
  28. package/dist/cli/observability-probe.d.ts.map +1 -0
  29. package/dist/cli/observability-probe.js +44 -0
  30. package/dist/cli/observability-probe.js.map +1 -0
  31. package/dist/cli/render-doctor.d.ts +26 -0
  32. package/dist/cli/render-doctor.d.ts.map +1 -0
  33. package/dist/cli/render-doctor.js +183 -0
  34. package/dist/cli/render-doctor.js.map +1 -0
  35. package/dist/cli/render-explain.d.ts +43 -0
  36. package/dist/cli/render-explain.d.ts.map +1 -0
  37. package/dist/cli/render-explain.js +127 -0
  38. package/dist/cli/render-explain.js.map +1 -0
  39. package/dist/define-app.d.ts +125 -0
  40. package/dist/define-app.d.ts.map +1 -0
  41. package/dist/define-app.js +126 -0
  42. package/dist/define-app.js.map +1 -0
  43. package/dist/dependency-graph.d.ts +25 -0
  44. package/dist/dependency-graph.d.ts.map +1 -0
  45. package/dist/dependency-graph.js +86 -0
  46. package/dist/dependency-graph.js.map +1 -0
  47. package/dist/diagnostics.d.ts +83 -0
  48. package/dist/diagnostics.d.ts.map +1 -0
  49. package/dist/diagnostics.js +14 -0
  50. package/dist/diagnostics.js.map +1 -0
  51. package/dist/index.d.ts +24 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +17 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/kernel/app-instance.d.ts +62 -0
  56. package/dist/kernel/app-instance.d.ts.map +1 -0
  57. package/dist/kernel/app-instance.js +1040 -0
  58. package/dist/kernel/app-instance.js.map +1 -0
  59. package/dist/kernel/otel.d.ts +105 -0
  60. package/dist/kernel/otel.d.ts.map +1 -0
  61. package/dist/kernel/otel.js +218 -0
  62. package/dist/kernel/otel.js.map +1 -0
  63. package/dist/lifecycle-observer.d.ts +95 -0
  64. package/dist/lifecycle-observer.d.ts.map +1 -0
  65. package/dist/lifecycle-observer.js +19 -0
  66. package/dist/lifecycle-observer.js.map +1 -0
  67. package/dist/lifecycle.d.ts +94 -0
  68. package/dist/lifecycle.d.ts.map +1 -0
  69. package/dist/lifecycle.js +78 -0
  70. package/dist/lifecycle.js.map +1 -0
  71. package/dist/manifest.d.ts +75 -0
  72. package/dist/manifest.d.ts.map +1 -0
  73. package/dist/manifest.js +14 -0
  74. package/dist/manifest.js.map +1 -0
  75. package/dist/pip-contract.d.ts +219 -0
  76. package/dist/pip-contract.d.ts.map +1 -0
  77. package/dist/pip-contract.js +90 -0
  78. package/dist/pip-contract.js.map +1 -0
  79. package/dist/pip.d.ts +33 -0
  80. package/dist/pip.d.ts.map +1 -0
  81. package/dist/pip.js +25 -0
  82. package/dist/pip.js.map +1 -0
  83. package/dist/plugin-contract.d.ts +175 -0
  84. package/dist/plugin-contract.d.ts.map +1 -0
  85. package/dist/plugin-contract.js +45 -0
  86. package/dist/plugin-contract.js.map +1 -0
  87. package/dist/plugin.d.ts +30 -0
  88. package/dist/plugin.d.ts.map +1 -0
  89. package/dist/plugin.js +24 -0
  90. package/dist/plugin.js.map +1 -0
  91. package/dist/test-harness.d.ts +42 -0
  92. package/dist/test-harness.d.ts.map +1 -0
  93. package/dist/test-harness.js +46 -0
  94. package/dist/test-harness.js.map +1 -0
  95. package/dist/timeline.d.ts +43 -0
  96. package/dist/timeline.d.ts.map +1 -0
  97. package/dist/timeline.js +121 -0
  98. package/dist/timeline.js.map +1 -0
  99. package/package.json +68 -0
  100. package/templates/app-minimal/.gitignore.tmpl +6 -0
  101. package/templates/app-minimal/AGENTS.md.tmpl +66 -0
  102. package/templates/app-minimal/README.md.tmpl +24 -0
  103. package/templates/app-minimal/package.json.tmpl +21 -0
  104. package/templates/app-minimal/src/app.ts.tmpl +20 -0
  105. package/templates/app-minimal/src/env.ts.tmpl +12 -0
  106. package/templates/app-minimal/tests/boot.test.ts.tmpl +25 -0
  107. package/templates/app-minimal/tsconfig.json.tmpl +22 -0
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Renderers for `dot explain`.
3
+ *
4
+ * Reads a configured (or booted) app's `manifest` and emits one of:
5
+ * - JSON envelope to stdout (when --json)
6
+ * - human-readable plain text to stdout (default)
7
+ *
8
+ * The JSON envelope shape matches the broader release-tooling envelope so
9
+ * agents can parse the output identically across CLI surfaces.
10
+ */
11
+ import type { DiagnosticIssue } from '../diagnostics.js';
12
+ import type { DotAppManifest } from '../manifest.js';
13
+ export type DotCliEnvelopeStatus = 'success' | 'failure' | 'warning';
14
+ export type DotCliEnvelope<T = unknown> = {
15
+ status: DotCliEnvelopeStatus;
16
+ command: string;
17
+ generatedAt: string;
18
+ data: T;
19
+ errors: DiagnosticIssue[];
20
+ };
21
+ export type ExplainSource = {
22
+ /** The static manifest produced by configure (or read off a booted app). */
23
+ manifest: DotAppManifest;
24
+ };
25
+ export type RenderOptions = {
26
+ /** Set to true to emit JSON to stdout; otherwise pretty text. */
27
+ json: boolean;
28
+ /** Override clock for deterministic test output. */
29
+ now?: () => Date;
30
+ /** Override stdout sink. Defaults to `process.stdout.write`. */
31
+ out?: (line: string) => void;
32
+ };
33
+ /**
34
+ * Build the envelope without writing anything. Useful for tests that need
35
+ * to assert shape and for embedding the CLI logic from other tools.
36
+ */
37
+ export declare function buildExplainEnvelope(source: ExplainSource, opts: RenderOptions): DotCliEnvelope<DotAppManifest>;
38
+ /**
39
+ * Render the explain output. Returns the envelope so callers can act on it
40
+ * (e.g. set the process exit code based on `status`).
41
+ */
42
+ export declare function renderExplain(source: ExplainSource, opts: RenderOptions): DotCliEnvelope<DotAppManifest>;
43
+ //# sourceMappingURL=render-explain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-explain.d.ts","sourceRoot":"","sources":["../../src/cli/render-explain.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAErE,MAAM,MAAM,cAAc,CAAC,CAAC,GAAG,OAAO,IAAI;IACxC,MAAM,EAAE,oBAAoB,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,CAAC,CAAC;IACR,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,4EAA4E;IAC5E,QAAQ,EAAE,cAAc,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,iEAAiE;IACjE,IAAI,EAAE,OAAO,CAAC;IACd,oDAAoD;IACpD,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,gEAAgE;IAChE,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9B,CAAC;AAWF;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,aAAa,GAAG,cAAc,CAAC,cAAc,CAAC,CAQ/G;AAsFD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,aAAa,GAAG,cAAc,CAAC,cAAc,CAAC,CAWxG"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Renderers for `dot explain`.
3
+ *
4
+ * Reads a configured (or booted) app's `manifest` and emits one of:
5
+ * - JSON envelope to stdout (when --json)
6
+ * - human-readable plain text to stdout (default)
7
+ *
8
+ * The JSON envelope shape matches the broader release-tooling envelope so
9
+ * agents can parse the output identically across CLI surfaces.
10
+ */
11
+ const defaultOut = (line) => {
12
+ process.stdout.write(line);
13
+ };
14
+ function nowIso(opts) {
15
+ const factory = opts.now ?? (() => new Date());
16
+ return factory().toISOString();
17
+ }
18
+ /**
19
+ * Build the envelope without writing anything. Useful for tests that need
20
+ * to assert shape and for embedding the CLI logic from other tools.
21
+ */
22
+ export function buildExplainEnvelope(source, opts) {
23
+ return {
24
+ status: 'success',
25
+ command: 'explain',
26
+ generatedAt: nowIso(opts),
27
+ data: source.manifest,
28
+ errors: [],
29
+ };
30
+ }
31
+ function pad(s, width) {
32
+ return s.length >= width ? s : s + ' '.repeat(width - s.length);
33
+ }
34
+ function renderTextManifest(manifest) {
35
+ const lines = [];
36
+ const title = `App: ${manifest.app.name}${manifest.app.version ? `@${manifest.app.version}` : ''}`;
37
+ lines.push(title);
38
+ lines.push('='.repeat(title.length));
39
+ lines.push('');
40
+ // Pips
41
+ lines.push(`Pips (${manifest.pips.length})`);
42
+ if (manifest.pips.length === 0) {
43
+ lines.push(' (none)');
44
+ }
45
+ else {
46
+ const widthName = Math.max(6, ...manifest.pips.map(p => p.name.length));
47
+ lines.push(` ${pad('NAME', widthName)} VERSION DEPENDENCIES`);
48
+ for (const p of manifest.pips) {
49
+ const version = p.version ?? '-';
50
+ const deps = p.dependencies.length > 0 ? p.dependencies.join(', ') : '-';
51
+ lines.push(` ${pad(p.name, widthName)} ${pad(version, 7)} ${deps}`);
52
+ }
53
+ }
54
+ lines.push('');
55
+ // Services
56
+ lines.push(`Services (${manifest.services.length})`);
57
+ if (manifest.services.length === 0) {
58
+ lines.push(' (none)');
59
+ }
60
+ else {
61
+ const widthName = Math.max(4, ...manifest.services.map(s => s.name.length));
62
+ const widthKind = Math.max(4, ...manifest.services.map(s => s.kind.length));
63
+ lines.push(` ${pad('NAME', widthName)} ${pad('KIND', widthKind)} PLUGIN`);
64
+ for (const s of manifest.services) {
65
+ lines.push(` ${pad(s.name, widthName)} ${pad(s.kind, widthKind)} ${s.pip}`);
66
+ }
67
+ }
68
+ lines.push('');
69
+ // Routes
70
+ lines.push(`Routes (${manifest.routes.length})`);
71
+ if (manifest.routes.length === 0) {
72
+ lines.push(' (none)');
73
+ }
74
+ else {
75
+ const widthId = Math.max(2, ...manifest.routes.map(r => r.id.length));
76
+ const widthMethod = Math.max(6, ...manifest.routes.map(r => (r.method ?? '-').length));
77
+ lines.push(` ${pad('ID', widthId)} ${pad('METHOD', widthMethod)} PATH/TRANSPORT PLUGIN`);
78
+ for (const r of manifest.routes) {
79
+ const method = r.method ?? '-';
80
+ const target = r.path ?? `(${r.transport})`;
81
+ lines.push(` ${pad(r.id, widthId)} ${pad(method, widthMethod)} ${pad(target, 14)} ${r.pip}`);
82
+ }
83
+ }
84
+ lines.push('');
85
+ // Dependencies
86
+ lines.push(`Dependencies (${manifest.dependencies.length})`);
87
+ if (manifest.dependencies.length === 0) {
88
+ lines.push(' (none)');
89
+ }
90
+ else {
91
+ for (const d of manifest.dependencies) {
92
+ lines.push(` ${d.from} --[${d.kind}]--> ${d.to}`);
93
+ }
94
+ }
95
+ lines.push('');
96
+ // Lifecycle
97
+ lines.push(`Lifecycle hooks (${manifest.lifecycle.length})`);
98
+ if (manifest.lifecycle.length === 0) {
99
+ lines.push(' (none)');
100
+ }
101
+ else {
102
+ const widthPip = Math.max(6, ...manifest.lifecycle.map(l => l.pip.length));
103
+ lines.push(` ${pad('PLUGIN', widthPip)} HOOKS`);
104
+ for (const l of manifest.lifecycle) {
105
+ const hooks = l.hooks.length > 0 ? l.hooks.join(', ') : '-';
106
+ lines.push(` ${pad(l.pip, widthPip)} ${hooks}`);
107
+ }
108
+ }
109
+ lines.push('');
110
+ return lines.join('\n');
111
+ }
112
+ /**
113
+ * Render the explain output. Returns the envelope so callers can act on it
114
+ * (e.g. set the process exit code based on `status`).
115
+ */
116
+ export function renderExplain(source, opts) {
117
+ const envelope = buildExplainEnvelope(source, opts);
118
+ const out = opts.out ?? defaultOut;
119
+ if (opts.json) {
120
+ out(`${JSON.stringify(envelope, null, 2)}\n`);
121
+ }
122
+ else {
123
+ out(`${renderTextManifest(source.manifest)}\n`);
124
+ }
125
+ return envelope;
126
+ }
127
+ //# sourceMappingURL=render-explain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-explain.js","sourceRoot":"","sources":["../../src/cli/render-explain.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Public entry point for the new DOT kernel.
3
+ *
4
+ * `defineApp(name)` returns a `DotAppBuilder` that accumulates pips via
5
+ * `.use(pip)`, then transitions through the 5-hook lifecycle:
6
+ *
7
+ * defineApp -> use* -> configure() -> boot() -> start() -> stop() -> dispose()
8
+ *
9
+ * Most callers don't need to call `configure()` explicitly — `boot()` runs it
10
+ * implicitly. `boot()` is also implicit when starting from `defined` via
11
+ * `start()`.
12
+ *
13
+ * See `./lifecycle.ts` for hook semantics, failure ordering, idempotency rules.
14
+ */
15
+ import type { DotDiagnosticsSnapshot } from './diagnostics.js';
16
+ import type { DotLifecycleObserver } from './lifecycle-observer.js';
17
+ import type { DotLifecycleState } from './lifecycle.js';
18
+ import type { DotAppManifest } from './manifest.js';
19
+ import type { DotPip } from './pip-contract.js';
20
+ /**
21
+ * Public DotApp surface. The internal `DotAppImpl` implements this; consumers
22
+ * see only these members.
23
+ */
24
+ export type DotApp<TServices extends Record<string, unknown>> = {
25
+ /** App name (passed to `defineApp`). */
26
+ readonly name: string;
27
+ /** Current lifecycle state. */
28
+ readonly state: DotLifecycleState;
29
+ /**
30
+ * Services published by booted pips, merged into a single record.
31
+ * Empty before `boot()` succeeds.
32
+ */
33
+ readonly services: TServices;
34
+ /** Declarative manifest — describes the static shape of the app. */
35
+ readonly manifest: DotAppManifest;
36
+ /** Point-in-time diagnostics snapshot. Re-computed on every access. */
37
+ readonly diagnostics: DotDiagnosticsSnapshot;
38
+ /**
39
+ * Start active work. Boots first if app is `defined` or `configured`.
40
+ * Idempotent while `started`. Throws if app is `failed` or `disposed`.
41
+ */
42
+ start(): Promise<void>;
43
+ /**
44
+ * Stop active work. Keeps booted resources for later cleanup.
45
+ * Idempotent while not `started`.
46
+ */
47
+ stop(): Promise<void>;
48
+ /**
49
+ * Release booted resources. Runs stop() first if `started`.
50
+ * Idempotent while `disposed`.
51
+ */
52
+ dispose(): Promise<void>;
53
+ /**
54
+ * Register an in-process lifecycle observer. Returns an unsubscribe
55
+ * function. Observers added here see events from this point onward —
56
+ * pass observers through `defineApp(name, { observers })` to catch
57
+ * `configure`-phase events too.
58
+ */
59
+ subscribe(observer: DotLifecycleObserver): () => void;
60
+ /**
61
+ * Render the recorded lifecycle as an ASCII waterfall. Reads from
62
+ * the current `diagnostics` snapshot — call after `boot()` /
63
+ * `dispose()` / a failure to see the full picture.
64
+ */
65
+ timeline(): string;
66
+ };
67
+ /**
68
+ * Intermediate type after `configure()` but before `boot()`.
69
+ * Exposes the manifest and diagnostics already, but no `services` yet.
70
+ */
71
+ export type DotAppConfigured<TServices extends Record<string, unknown>> = {
72
+ readonly name: string;
73
+ readonly state: DotLifecycleState;
74
+ readonly manifest: DotAppManifest;
75
+ readonly diagnostics: DotDiagnosticsSnapshot;
76
+ /** Continue the lifecycle. */
77
+ boot(): Promise<DotApp<TServices>>;
78
+ start(): Promise<DotApp<TServices>>;
79
+ /** See {@link DotApp.subscribe}. */
80
+ subscribe(observer: DotLifecycleObserver): () => void;
81
+ /** See {@link DotApp.timeline}. */
82
+ timeline(): string;
83
+ };
84
+ /**
85
+ * Builder produced by `defineApp(name)`.
86
+ *
87
+ * `.use(pip)` is type-tracking: services published by the pip are
88
+ * merged into `TServices` for the next builder.
89
+ */
90
+ export type DotAppBuilder<TServices extends Record<string, unknown>> = {
91
+ /** Register a pip. Returns a new builder with merged services. */
92
+ use<TNew extends Record<string, unknown>>(pip: DotPip<TNew>): DotAppBuilder<TServices & TNew>;
93
+ /** Run the configure phase synchronously. Throws on configure failure. */
94
+ configure(): DotAppConfigured<TServices>;
95
+ /** Run configure + boot. Throws on configure or boot failure. */
96
+ boot(): Promise<DotApp<TServices>>;
97
+ /** Convenience: configure + boot + start. */
98
+ start(): Promise<DotApp<TServices>>;
99
+ };
100
+ /**
101
+ * Create a new DOT app builder.
102
+ *
103
+ * @example
104
+ * const app = await defineApp('my-app')
105
+ * .use(dbPip)
106
+ * .use(authPip)
107
+ * .boot();
108
+ *
109
+ * await app.start();
110
+ * console.log(app.manifest);
111
+ * // ...
112
+ * await app.dispose();
113
+ */
114
+ export declare function defineApp<TServices extends Record<string, unknown> = Record<string, never>>(name: string, options?: {
115
+ version?: string;
116
+ config?: Readonly<Record<string, unknown>>;
117
+ /**
118
+ * In-process lifecycle observers, registered before the first phase
119
+ * fires. Required if you want to see `configure`-phase events — after
120
+ * configure runs, observers can be added post-hoc via
121
+ * `configured.subscribe(...)` or `app.subscribe(...)`.
122
+ */
123
+ observers?: readonly DotLifecycleObserver[];
124
+ }): DotAppBuilder<TServices>;
125
+ //# sourceMappingURL=define-app.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-app.d.ts","sourceRoot":"","sources":["../src/define-app.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Public entry point for the new DOT kernel.
3
+ *
4
+ * `defineApp(name)` returns a `DotAppBuilder` that accumulates pips via
5
+ * `.use(pip)`, then transitions through the 5-hook lifecycle:
6
+ *
7
+ * defineApp -> use* -> configure() -> boot() -> start() -> stop() -> dispose()
8
+ *
9
+ * Most callers don't need to call `configure()` explicitly — `boot()` runs it
10
+ * implicitly. `boot()` is also implicit when starting from `defined` via
11
+ * `start()`.
12
+ *
13
+ * See `./lifecycle.ts` for hook semantics, failure ordering, idempotency rules.
14
+ */
15
+ import { DotAppImpl } from './kernel/app-instance.js';
16
+ import { renderTimeline } from './timeline.js';
17
+ /**
18
+ * Create a new DOT app builder.
19
+ *
20
+ * @example
21
+ * const app = await defineApp('my-app')
22
+ * .use(dbPip)
23
+ * .use(authPip)
24
+ * .boot();
25
+ *
26
+ * await app.start();
27
+ * console.log(app.manifest);
28
+ * // ...
29
+ * await app.dispose();
30
+ */
31
+ export function defineApp(name, options = {}) {
32
+ const state = {
33
+ appName: name,
34
+ appVersion: options.version,
35
+ pips: [],
36
+ config: options.config,
37
+ observers: options.observers,
38
+ };
39
+ return makeBuilder(state);
40
+ }
41
+ function buildImpl(state) {
42
+ return new DotAppImpl({
43
+ appName: state.appName,
44
+ appVersion: state.appVersion,
45
+ pips: state.pips,
46
+ config: state.config,
47
+ observers: state.observers,
48
+ });
49
+ }
50
+ function makeBuilder(state) {
51
+ return {
52
+ use(pip) {
53
+ const nextState = {
54
+ ...state,
55
+ pips: [...state.pips, pip],
56
+ };
57
+ return makeBuilder(nextState);
58
+ },
59
+ configure() {
60
+ const impl = buildImpl(state);
61
+ impl.runConfigure();
62
+ return wrapConfigured(impl);
63
+ },
64
+ async boot() {
65
+ const impl = buildImpl(state);
66
+ await impl.boot();
67
+ return wrapApp(impl);
68
+ },
69
+ async start() {
70
+ const impl = buildImpl(state);
71
+ await impl.start();
72
+ return wrapApp(impl);
73
+ },
74
+ };
75
+ }
76
+ function wrapApp(impl) {
77
+ return {
78
+ get name() {
79
+ return impl.name;
80
+ },
81
+ get state() {
82
+ return impl.state;
83
+ },
84
+ get services() {
85
+ return impl.services;
86
+ },
87
+ get manifest() {
88
+ return impl.manifest;
89
+ },
90
+ get diagnostics() {
91
+ return impl.diagnostics;
92
+ },
93
+ start: () => impl.start(),
94
+ stop: () => impl.stop(),
95
+ dispose: () => impl.dispose(),
96
+ subscribe: observer => impl.subscribe(observer),
97
+ timeline: () => renderTimeline(impl.diagnostics),
98
+ };
99
+ }
100
+ function wrapConfigured(impl) {
101
+ return {
102
+ get name() {
103
+ return impl.name;
104
+ },
105
+ get state() {
106
+ return impl.state;
107
+ },
108
+ get manifest() {
109
+ return impl.manifest;
110
+ },
111
+ get diagnostics() {
112
+ return impl.diagnostics;
113
+ },
114
+ async boot() {
115
+ await impl.boot();
116
+ return wrapApp(impl);
117
+ },
118
+ async start() {
119
+ await impl.start();
120
+ return wrapApp(impl);
121
+ },
122
+ subscribe: observer => impl.subscribe(observer),
123
+ timeline: () => renderTimeline(impl.diagnostics),
124
+ };
125
+ }
126
+ //# sourceMappingURL=define-app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-app.js","sourceRoot":"","sources":["../src/define-app.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Topological sort + cycle detection for pip dependencies.
3
+ *
4
+ * Internal to the kernel. Tests must reach it through `defineApp(...)`, never
5
+ * directly.
6
+ */
7
+ import type { AnyDotPip } from './pip-contract.js';
8
+ /**
9
+ * Sort pips so that every pip appears after the pips it depends on.
10
+ *
11
+ * @throws {DotLifecycleError}
12
+ * - `DOT_LIFECYCLE_E009` if the dependency graph contains a cycle.
13
+ * - `DOT_LIFECYCLE_E010` if a declared dependency isn't registered.
14
+ * - `DOT_LIFECYCLE_E011` if the same pip name appears twice.
15
+ */
16
+ export declare function topologicalSort(pips: readonly AnyDotPip[]): readonly AnyDotPip[];
17
+ /** Reverse a sorted pip array — used for `stop` and `dispose` ordering. */
18
+ export declare function reverseTopologicalSort(pips: readonly AnyDotPip[]): readonly AnyDotPip[];
19
+ /** Build the list of dependency edges for the manifest. */
20
+ export declare function buildDependencyEdges(pips: readonly AnyDotPip[]): readonly {
21
+ from: string;
22
+ to: string;
23
+ kind: 'requires';
24
+ }[];
25
+ //# sourceMappingURL=dependency-graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependency-graph.d.ts","sourceRoot":"","sources":["../src/dependency-graph.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAInD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,SAAS,EAAE,GAAG,SAAS,SAAS,EAAE,CA4DhF;AAED,2EAA2E;AAC3E,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,SAAS,SAAS,EAAE,GAAG,SAAS,SAAS,EAAE,CAGvF;AAED,2DAA2D;AAC3D,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,SAAS,SAAS,EAAE,GACzB,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAE,EAAE,CAQ3D"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Topological sort + cycle detection for pip dependencies.
3
+ *
4
+ * Internal to the kernel. Tests must reach it through `defineApp(...)`, never
5
+ * directly.
6
+ */
7
+ import { DotLifecycleError, DotLifecycleErrorCode } from './lifecycle.js';
8
+ import { pipDependencies } from './pip-contract.js';
9
+ /**
10
+ * Sort pips so that every pip appears after the pips it depends on.
11
+ *
12
+ * @throws {DotLifecycleError}
13
+ * - `DOT_LIFECYCLE_E009` if the dependency graph contains a cycle.
14
+ * - `DOT_LIFECYCLE_E010` if a declared dependency isn't registered.
15
+ * - `DOT_LIFECYCLE_E011` if the same pip name appears twice.
16
+ */
17
+ export function topologicalSort(pips) {
18
+ const byName = new Map();
19
+ for (const pip of pips) {
20
+ if (byName.has(pip.name)) {
21
+ throw new DotLifecycleError({
22
+ code: DotLifecycleErrorCode.DuplicatePip,
23
+ phase: 'configure',
24
+ pip: pip.name,
25
+ message: `Pip "${pip.name}" is registered twice`,
26
+ });
27
+ }
28
+ byName.set(pip.name, pip);
29
+ }
30
+ const sorted = [];
31
+ const permanent = new Set();
32
+ const temporary = new Set();
33
+ const stack = [];
34
+ const visit = (name) => {
35
+ if (permanent.has(name))
36
+ return;
37
+ if (temporary.has(name)) {
38
+ const cyclePath = [...stack.slice(stack.indexOf(name)), name].join(' -> ');
39
+ throw new DotLifecycleError({
40
+ code: DotLifecycleErrorCode.DependencyCycle,
41
+ phase: 'configure',
42
+ pip: name,
43
+ message: `Dependency cycle detected: ${cyclePath}`,
44
+ });
45
+ }
46
+ const pip = byName.get(name);
47
+ if (!pip) {
48
+ throw new DotLifecycleError({
49
+ code: DotLifecycleErrorCode.MissingDependency,
50
+ phase: 'configure',
51
+ pip: name,
52
+ message: `Pip "${name}" is required as a dependency but is not registered`,
53
+ });
54
+ }
55
+ temporary.add(name);
56
+ stack.push(name);
57
+ for (const dep of pipDependencies(pip)) {
58
+ visit(dep);
59
+ }
60
+ stack.pop();
61
+ // eslint-disable-next-line drizzle/enforce-delete-with-where -- `temporary` is a JS Set, not a Drizzle query.
62
+ temporary.delete(name);
63
+ permanent.add(name);
64
+ sorted.push(pip);
65
+ };
66
+ for (const name of byName.keys()) {
67
+ visit(name);
68
+ }
69
+ return sorted;
70
+ }
71
+ /** Reverse a sorted pip array — used for `stop` and `dispose` ordering. */
72
+ export function reverseTopologicalSort(pips) {
73
+ // eslint-disable-next-line unicorn/no-array-reverse -- lib target is ES2022, toReversed is ES2023.
74
+ return [...pips].reverse();
75
+ }
76
+ /** Build the list of dependency edges for the manifest. */
77
+ export function buildDependencyEdges(pips) {
78
+ const edges = [];
79
+ for (const pip of pips) {
80
+ for (const dep of pipDependencies(pip)) {
81
+ edges.push({ from: pip.name, to: dep, kind: 'requires' });
82
+ }
83
+ }
84
+ return edges;
85
+ }
86
+ //# sourceMappingURL=dependency-graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependency-graph.js","sourceRoot":"","sources":["../src/dependency-graph.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Diagnostics types for the DOT kernel.
3
+ *
4
+ * Where the manifest describes the static shape of an app, a
5
+ * `DotDiagnosticsSnapshot` is a point-in-time observability record: the
6
+ * lifecycle state of the app and every pip, plus structured issues with
7
+ * remediation guidance.
8
+ *
9
+ * CONTRACT: `DotDiagnosticsSnapshot` always exposes the same five arrays
10
+ * (`pips`, `routes`, `services`, `lifecycle`, `issues`). Consumers must
11
+ * never see an omitted array — empty is empty, but never missing.
12
+ * This is the "5 arrays" contract referenced by the kernel spec.
13
+ */
14
+ import type { DotLifecycleHook, DotLifecycleState } from './lifecycle.js';
15
+ /** Severity of a single diagnostic issue. */
16
+ export type DiagnosticSeverity = 'info' | 'warning' | 'error';
17
+ /** Status of a pip/route/service/lifecycle entry. */
18
+ export type DiagnosticStatus = 'ok' | 'degraded' | 'failed' | 'skipped' | 'missing';
19
+ /**
20
+ * Single point-in-time diagnostic snapshot of a DotApp.
21
+ *
22
+ * Five top-level arrays — pips, routes, services, lifecycle, issues —
23
+ * are guaranteed to be present even when empty.
24
+ */
25
+ export type DotDiagnosticsSnapshot = {
26
+ /** ISO-8601 timestamp at which the snapshot was generated. */
27
+ generatedAt: string;
28
+ app: {
29
+ name: string;
30
+ state: DotLifecycleState;
31
+ };
32
+ pips: PipDiagnostic[];
33
+ routes: RouteDiagnostic[];
34
+ services: ServiceDiagnostic[];
35
+ lifecycle: LifecycleDiagnostic[];
36
+ issues: DiagnosticIssue[];
37
+ };
38
+ export type PipDiagnostic = {
39
+ pip: string;
40
+ status: Extract<DiagnosticStatus, 'ok' | 'degraded' | 'failed' | 'skipped'>;
41
+ issues: DiagnosticIssue[];
42
+ };
43
+ export type RouteDiagnostic = {
44
+ id: string;
45
+ pip: string;
46
+ status: Extract<DiagnosticStatus, 'ok' | 'degraded' | 'failed'>;
47
+ issues: DiagnosticIssue[];
48
+ };
49
+ export type ServiceDiagnostic = {
50
+ service: string;
51
+ pip: string;
52
+ status: Extract<DiagnosticStatus, 'ok' | 'degraded' | 'failed' | 'missing'>;
53
+ issues: DiagnosticIssue[];
54
+ };
55
+ export type LifecycleDiagnostic = {
56
+ pip: string;
57
+ hook: DotLifecycleHook;
58
+ state: DotLifecycleState;
59
+ /** 0-based topological order of this pip within the hook pass. */
60
+ order: number;
61
+ /** Wall-clock duration of the hook call, in milliseconds. */
62
+ durationMs?: number;
63
+ issues: DiagnosticIssue[];
64
+ };
65
+ /**
66
+ * Single structured issue surfaced by the kernel or by a pip.
67
+ *
68
+ * `code`, `message`, `remediation` and `docsUrl` are required so that issues
69
+ * are always actionable — never just "something went wrong".
70
+ */
71
+ export type DiagnosticIssue = {
72
+ /** Stable machine-readable code, e.g. `DOT_LIFECYCLE_E003`. */
73
+ code: string;
74
+ severity: DiagnosticSeverity;
75
+ pip?: string;
76
+ message: string;
77
+ /** Human-readable remediation: what the developer should do. */
78
+ remediation: string;
79
+ /** Link to the relevant docs page for this issue. */
80
+ docsUrl: string;
81
+ metadata?: Record<string, unknown>;
82
+ };
83
+ //# sourceMappingURL=diagnostics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAE1E,6CAA6C;AAC7C,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;AAE9D,qDAAqD;AACrD,MAAM,MAAM,gBAAgB,GAAG,IAAI,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;AAEpF;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,8DAA8D;IAC9D,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE;QACH,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,iBAAiB,CAAC;KAC1B,CAAC;IACF,IAAI,EAAE,aAAa,EAAE,CAAC;IACtB,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,SAAS,EAAE,mBAAmB,EAAE,CAAC;IACjC,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,OAAO,CAAC,gBAAgB,EAAE,IAAI,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC,CAAC;IAC5E,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,OAAO,CAAC,gBAAgB,EAAE,IAAI,GAAG,UAAU,GAAG,QAAQ,CAAC,CAAC;IAChE,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,OAAO,CAAC,gBAAgB,EAAE,IAAI,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC,CAAC;IAC5E,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,gBAAgB,CAAC;IACvB,KAAK,EAAE,iBAAiB,CAAC;IACzB,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,WAAW,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC,CAAC"}