@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.
- package/LICENSE +21 -0
- package/README.md +201 -0
- package/dist/cli/discover.d.ts +65 -0
- package/dist/cli/discover.d.ts.map +1 -0
- package/dist/cli/discover.js +184 -0
- package/dist/cli/discover.js.map +1 -0
- package/dist/cli/error-codes.d.ts +49 -0
- package/dist/cli/error-codes.d.ts.map +1 -0
- package/dist/cli/error-codes.js +61 -0
- package/dist/cli/error-codes.js.map +1 -0
- package/dist/cli/files.d.ts +67 -0
- package/dist/cli/files.d.ts.map +1 -0
- package/dist/cli/files.js +80 -0
- package/dist/cli/files.js.map +1 -0
- package/dist/cli/index.d.ts +95 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +456 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/json.d.ts +38 -0
- package/dist/cli/json.d.ts.map +1 -0
- package/dist/cli/json.js +18 -0
- package/dist/cli/json.js.map +1 -0
- package/dist/cli/new.d.ts +105 -0
- package/dist/cli/new.d.ts.map +1 -0
- package/dist/cli/new.js +322 -0
- package/dist/cli/new.js.map +1 -0
- package/dist/cli/observability-probe.d.ts +28 -0
- package/dist/cli/observability-probe.d.ts.map +1 -0
- package/dist/cli/observability-probe.js +44 -0
- package/dist/cli/observability-probe.js.map +1 -0
- package/dist/cli/render-doctor.d.ts +26 -0
- package/dist/cli/render-doctor.d.ts.map +1 -0
- package/dist/cli/render-doctor.js +183 -0
- package/dist/cli/render-doctor.js.map +1 -0
- package/dist/cli/render-explain.d.ts +43 -0
- package/dist/cli/render-explain.d.ts.map +1 -0
- package/dist/cli/render-explain.js +127 -0
- package/dist/cli/render-explain.js.map +1 -0
- package/dist/define-app.d.ts +125 -0
- package/dist/define-app.d.ts.map +1 -0
- package/dist/define-app.js +126 -0
- package/dist/define-app.js.map +1 -0
- package/dist/dependency-graph.d.ts +25 -0
- package/dist/dependency-graph.d.ts.map +1 -0
- package/dist/dependency-graph.js +86 -0
- package/dist/dependency-graph.js.map +1 -0
- package/dist/diagnostics.d.ts +83 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.js +14 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/kernel/app-instance.d.ts +62 -0
- package/dist/kernel/app-instance.d.ts.map +1 -0
- package/dist/kernel/app-instance.js +1040 -0
- package/dist/kernel/app-instance.js.map +1 -0
- package/dist/kernel/otel.d.ts +105 -0
- package/dist/kernel/otel.d.ts.map +1 -0
- package/dist/kernel/otel.js +218 -0
- package/dist/kernel/otel.js.map +1 -0
- package/dist/lifecycle-observer.d.ts +95 -0
- package/dist/lifecycle-observer.d.ts.map +1 -0
- package/dist/lifecycle-observer.js +19 -0
- package/dist/lifecycle-observer.js.map +1 -0
- package/dist/lifecycle.d.ts +94 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/lifecycle.js +78 -0
- package/dist/lifecycle.js.map +1 -0
- package/dist/manifest.d.ts +75 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +14 -0
- package/dist/manifest.js.map +1 -0
- package/dist/pip-contract.d.ts +219 -0
- package/dist/pip-contract.d.ts.map +1 -0
- package/dist/pip-contract.js +90 -0
- package/dist/pip-contract.js.map +1 -0
- package/dist/pip.d.ts +33 -0
- package/dist/pip.d.ts.map +1 -0
- package/dist/pip.js +25 -0
- package/dist/pip.js.map +1 -0
- package/dist/plugin-contract.d.ts +175 -0
- package/dist/plugin-contract.d.ts.map +1 -0
- package/dist/plugin-contract.js +45 -0
- package/dist/plugin-contract.js.map +1 -0
- package/dist/plugin.d.ts +30 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +24 -0
- package/dist/plugin.js.map +1 -0
- package/dist/test-harness.d.ts +42 -0
- package/dist/test-harness.d.ts.map +1 -0
- package/dist/test-harness.js +46 -0
- package/dist/test-harness.js.map +1 -0
- package/dist/timeline.d.ts +43 -0
- package/dist/timeline.d.ts.map +1 -0
- package/dist/timeline.js +121 -0
- package/dist/timeline.js.map +1 -0
- package/package.json +68 -0
- package/templates/app-minimal/.gitignore.tmpl +6 -0
- package/templates/app-minimal/AGENTS.md.tmpl +66 -0
- package/templates/app-minimal/README.md.tmpl +24 -0
- package/templates/app-minimal/package.json.tmpl +21 -0
- package/templates/app-minimal/src/app.ts.tmpl +20 -0
- package/templates/app-minimal/src/env.ts.tmpl +12 -0
- package/templates/app-minimal/tests/boot.test.ts.tmpl +25 -0
- package/templates/app-minimal/tsconfig.json.tmpl +22 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public plugin contract for the DOT kernel.
|
|
3
|
+
*
|
|
4
|
+
* A `DotPlugin` is a plain object with a name, optional dependency list, and
|
|
5
|
+
* up to five lifecycle hooks. The kernel calls each hook in dependency order
|
|
6
|
+
* (or reverse-dependency order for `stop`/`dispose`).
|
|
7
|
+
*
|
|
8
|
+
* Design constraints:
|
|
9
|
+
*
|
|
10
|
+
* - `configure` is SYNC. Returning a Promise is an error — the kernel will
|
|
11
|
+
* throw {@link DotLifecycleError} with code `DOT_LIFECYCLE_E001`.
|
|
12
|
+
* - `boot` may publish services into the app; downstream plugins see them via
|
|
13
|
+
* {@link DotBootContext.services}.
|
|
14
|
+
* - `stop` and `dispose` continue through individual plugin failures and
|
|
15
|
+
* report an aggregate error.
|
|
16
|
+
*/
|
|
17
|
+
import type { DotLifecycleHook } from './lifecycle.js';
|
|
18
|
+
import type { DependencyEdgeKind, RouteTransport, ServiceKind } from './manifest.js';
|
|
19
|
+
/**
|
|
20
|
+
* Aggregate registration record produced during the `configure` phase.
|
|
21
|
+
*
|
|
22
|
+
* The kernel exposes one of these to each plugin via {@link DotConfigureContext}
|
|
23
|
+
* and uses the merged result to build the final `DotAppManifest`.
|
|
24
|
+
*/
|
|
25
|
+
export type DotManifestContribution = {
|
|
26
|
+
/** Services this plugin publishes. */
|
|
27
|
+
services?: readonly {
|
|
28
|
+
name: string;
|
|
29
|
+
kind: ServiceKind;
|
|
30
|
+
}[];
|
|
31
|
+
/** Routes this plugin exposes. */
|
|
32
|
+
routes?: readonly {
|
|
33
|
+
id: string;
|
|
34
|
+
method?: string;
|
|
35
|
+
path?: string;
|
|
36
|
+
transport: RouteTransport;
|
|
37
|
+
}[];
|
|
38
|
+
/** Additional `provides` capability strings (joined with the plugin's `provides`). */
|
|
39
|
+
provides?: readonly string[];
|
|
40
|
+
/** Additional dependency edges. */
|
|
41
|
+
dependencies?: readonly {
|
|
42
|
+
to: string;
|
|
43
|
+
kind?: DependencyEdgeKind;
|
|
44
|
+
}[];
|
|
45
|
+
};
|
|
46
|
+
/** Context provided to a `manifest` callback. */
|
|
47
|
+
export type DotManifestContext<TServices extends Record<string, unknown>> = {
|
|
48
|
+
pluginName: string;
|
|
49
|
+
/** Services published by dependencies that have already booted (read-only). */
|
|
50
|
+
services: Readonly<Partial<TServices>>;
|
|
51
|
+
};
|
|
52
|
+
/** Context provided to a `configure` hook. */
|
|
53
|
+
export type DotConfigureContext = {
|
|
54
|
+
pluginName: string;
|
|
55
|
+
/** App name. */
|
|
56
|
+
appName: string;
|
|
57
|
+
/**
|
|
58
|
+
* Register a service this plugin publishes.
|
|
59
|
+
* Registration is metadata-only — the actual service instance is returned
|
|
60
|
+
* from the `boot` hook in `DotBootResult.services`.
|
|
61
|
+
*/
|
|
62
|
+
registerService(name: string, kind: ServiceKind): void;
|
|
63
|
+
/** Register a route this plugin exposes. */
|
|
64
|
+
registerRoute(route: {
|
|
65
|
+
id: string;
|
|
66
|
+
method?: string;
|
|
67
|
+
path?: string;
|
|
68
|
+
transport: RouteTransport;
|
|
69
|
+
}): void;
|
|
70
|
+
/** Mark the plugin as participating in a lifecycle hook. */
|
|
71
|
+
registerLifecycleHook(hook: DotLifecycleHook): void;
|
|
72
|
+
/** Append `provides` capability strings. */
|
|
73
|
+
declareProvides(...capabilities: string[]): void;
|
|
74
|
+
/** Append an extra dependency edge (alongside `plugin.dependencies`). */
|
|
75
|
+
declareDependency(to: string, kind?: DependencyEdgeKind): void;
|
|
76
|
+
};
|
|
77
|
+
/** Context provided to a `boot` hook. */
|
|
78
|
+
export type DotBootContext = {
|
|
79
|
+
pluginName: string;
|
|
80
|
+
appName: string;
|
|
81
|
+
/**
|
|
82
|
+
* Services published by prior-booted plugins, keyed by service name.
|
|
83
|
+
* Use this for dependency injection between plugins.
|
|
84
|
+
*/
|
|
85
|
+
services: ReadonlyMap<string, unknown>;
|
|
86
|
+
/** Read-only configuration bag. */
|
|
87
|
+
config: Readonly<Record<string, unknown>>;
|
|
88
|
+
};
|
|
89
|
+
/** Context provided to a `start` hook. */
|
|
90
|
+
export type DotStartContext<TServices extends Record<string, unknown>> = {
|
|
91
|
+
pluginName: string;
|
|
92
|
+
appName: string;
|
|
93
|
+
services: TServices;
|
|
94
|
+
};
|
|
95
|
+
/** Context provided to a `stop` hook. */
|
|
96
|
+
export type DotStopContext<TServices extends Record<string, unknown>> = {
|
|
97
|
+
pluginName: string;
|
|
98
|
+
appName: string;
|
|
99
|
+
services: TServices;
|
|
100
|
+
};
|
|
101
|
+
/** Context provided to a `dispose` hook. */
|
|
102
|
+
export type DotDisposeContext<TServices extends Record<string, unknown>> = {
|
|
103
|
+
pluginName: string;
|
|
104
|
+
appName: string;
|
|
105
|
+
services: TServices;
|
|
106
|
+
};
|
|
107
|
+
/** Return value of a `boot` hook. */
|
|
108
|
+
export type DotBootResult<TServices extends Record<string, unknown>> = {
|
|
109
|
+
/** Services this plugin publishes — added to `app.services` and visible to dependent plugins. */
|
|
110
|
+
services?: TServices;
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* The DOT plugin contract.
|
|
114
|
+
*
|
|
115
|
+
* Default `TServices` is `Record<string, never>` so plugins that don't publish
|
|
116
|
+
* services don't have to specify a type argument. Default `TManifest` is the
|
|
117
|
+
* full contribution shape.
|
|
118
|
+
*/
|
|
119
|
+
export type DotPlugin<TServices extends Record<string, unknown> = Record<string, never>, TManifest extends DotManifestContribution = DotManifestContribution> = {
|
|
120
|
+
/** Unique identifier for this plugin within the app. */
|
|
121
|
+
name: string;
|
|
122
|
+
/** Optional semantic version string. */
|
|
123
|
+
version?: string;
|
|
124
|
+
/**
|
|
125
|
+
* Names of plugins this one depends on.
|
|
126
|
+
* The kernel ensures dependencies are configured/booted/started first, and
|
|
127
|
+
* stopped/disposed last.
|
|
128
|
+
*/
|
|
129
|
+
dependencies?: readonly string[];
|
|
130
|
+
/** Capability strings this plugin advertises (for `dependencies` resolution by capability). */
|
|
131
|
+
provides?: readonly string[];
|
|
132
|
+
/**
|
|
133
|
+
* Optional static or callback-form manifest contribution. The kernel merges
|
|
134
|
+
* this into the final manifest after `configure` runs.
|
|
135
|
+
*/
|
|
136
|
+
manifest?: TManifest | ((ctx: DotManifestContext<TServices>) => TManifest);
|
|
137
|
+
/**
|
|
138
|
+
* SYNC registration hook. Declare metadata, register routes/services/jobs.
|
|
139
|
+
* MUST NOT perform IO, MUST NOT return a Promise.
|
|
140
|
+
*/
|
|
141
|
+
configure?: (ctx: DotConfigureContext) => void;
|
|
142
|
+
/** Async open-resources hook. Returns published services for DI. */
|
|
143
|
+
boot?: (ctx: DotBootContext) => Promise<DotBootResult<TServices>> | DotBootResult<TServices>;
|
|
144
|
+
/** Async begin-active-work hook. Runs after every plugin's `boot` succeeds. */
|
|
145
|
+
start?: (ctx: DotStartContext<TServices>) => Promise<void> | void;
|
|
146
|
+
/** Async halt-active-work hook. Runs in reverse-topological order. */
|
|
147
|
+
stop?: (ctx: DotStopContext<TServices>) => Promise<void> | void;
|
|
148
|
+
/** Async release-resources hook. Runs in reverse-topological order. */
|
|
149
|
+
dispose?: (ctx: DotDisposeContext<TServices>) => Promise<void> | void;
|
|
150
|
+
};
|
|
151
|
+
/**
|
|
152
|
+
* Type-narrowing helper for plugin authors.
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* export const myPlugin = defineDotPlugin<{ db: MyDb }>({
|
|
156
|
+
* name: 'my-plugin',
|
|
157
|
+
* async boot() {
|
|
158
|
+
* const db = await openDb();
|
|
159
|
+
* return { services: { db } };
|
|
160
|
+
* },
|
|
161
|
+
* async dispose({ services }) {
|
|
162
|
+
* await services.db.close();
|
|
163
|
+
* },
|
|
164
|
+
* });
|
|
165
|
+
*/
|
|
166
|
+
export declare function defineDotPlugin<TServices extends Record<string, unknown> = Record<string, never>>(plugin: DotPlugin<TServices>): DotPlugin<TServices>;
|
|
167
|
+
/** Internal type alias used by the kernel to erase plugin service generics. */
|
|
168
|
+
export type AnyDotPlugin = DotPlugin<Record<string, unknown>, DotManifestContribution>;
|
|
169
|
+
/** Internal helper: extract the `provides` field from a plugin (always returns an array). */
|
|
170
|
+
export declare function pluginProvides(plugin: AnyDotPlugin): readonly string[];
|
|
171
|
+
/** Internal helper: extract the `dependencies` field from a plugin (always returns an array). */
|
|
172
|
+
export declare function pluginDependencies(plugin: AnyDotPlugin): readonly string[];
|
|
173
|
+
/** Re-exported for downstream typing. */
|
|
174
|
+
export { type DotAppManifest, type PluginManifest } from './manifest.js';
|
|
175
|
+
//# sourceMappingURL=plugin-contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-contract.d.ts","sourceRoot":"","sources":["../src/plugin-contract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public plugin contract for the DOT kernel.
|
|
3
|
+
*
|
|
4
|
+
* A `DotPlugin` is a plain object with a name, optional dependency list, and
|
|
5
|
+
* up to five lifecycle hooks. The kernel calls each hook in dependency order
|
|
6
|
+
* (or reverse-dependency order for `stop`/`dispose`).
|
|
7
|
+
*
|
|
8
|
+
* Design constraints:
|
|
9
|
+
*
|
|
10
|
+
* - `configure` is SYNC. Returning a Promise is an error — the kernel will
|
|
11
|
+
* throw {@link DotLifecycleError} with code `DOT_LIFECYCLE_E001`.
|
|
12
|
+
* - `boot` may publish services into the app; downstream plugins see them via
|
|
13
|
+
* {@link DotBootContext.services}.
|
|
14
|
+
* - `stop` and `dispose` continue through individual plugin failures and
|
|
15
|
+
* report an aggregate error.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Type-narrowing helper for plugin authors.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* export const myPlugin = defineDotPlugin<{ db: MyDb }>({
|
|
22
|
+
* name: 'my-plugin',
|
|
23
|
+
* async boot() {
|
|
24
|
+
* const db = await openDb();
|
|
25
|
+
* return { services: { db } };
|
|
26
|
+
* },
|
|
27
|
+
* async dispose({ services }) {
|
|
28
|
+
* await services.db.close();
|
|
29
|
+
* },
|
|
30
|
+
* });
|
|
31
|
+
*/
|
|
32
|
+
export function defineDotPlugin(plugin) {
|
|
33
|
+
return plugin;
|
|
34
|
+
}
|
|
35
|
+
/** Internal helper: extract the `provides` field from a plugin (always returns an array). */
|
|
36
|
+
export function pluginProvides(plugin) {
|
|
37
|
+
return plugin.provides ?? [];
|
|
38
|
+
}
|
|
39
|
+
/** Internal helper: extract the `dependencies` field from a plugin (always returns an array). */
|
|
40
|
+
export function pluginDependencies(plugin) {
|
|
41
|
+
return plugin.dependencies ?? [];
|
|
42
|
+
}
|
|
43
|
+
/** Re-exported for downstream typing. */
|
|
44
|
+
export {} from './manifest.js';
|
|
45
|
+
//# sourceMappingURL=plugin-contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-contract.js","sourceRoot":"","sources":["../src/plugin-contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAsJH;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,eAAe,CAC7B,MAA4B;IAE5B,OAAO,MAAM,CAAC;AAChB,CAAC;AAKD,6FAA6F;AAC7F,MAAM,UAAU,cAAc,CAAC,MAAoB;IACjD,OAAO,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC;AAC/B,CAAC;AAED,iGAAiG;AACjG,MAAM,UAAU,kBAAkB,CAAC,MAAoB;IACrD,OAAO,MAAM,CAAC,YAAY,IAAI,EAAE,CAAC;AACnC,CAAC;AAED,yCAAyC;AAEzC,OAAO,EAA4C,MAAM,eAAe,CAAC"}
|
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Narrow public surface for plugin authors.
|
|
3
|
+
*
|
|
4
|
+
* Exposes the new-kernel plugin contract and the entry points a plugin
|
|
5
|
+
* author needs to author + test plugins — `defineDotPlugin`, `defineApp`,
|
|
6
|
+
* `testApp` / `bootTestApp`, plus lifecycle / manifest / diagnostics types.
|
|
7
|
+
*
|
|
8
|
+
* Does NOT re-export the legacy `Dot` / `createDot` builder or the legacy
|
|
9
|
+
* auth/db/event-sourcing modules. Adapter packages (e.g. `@arki/env/dot`,
|
|
10
|
+
* `@arki/kv/dot`, `@arki/db/dot`) import from this subpath so their
|
|
11
|
+
* `*.d.ts` graphs do not pull in the legacy surface — keeping their
|
|
12
|
+
* compile times tight and decoupling adapters from the legacy retirement
|
|
13
|
+
* schedule (Task 12).
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { defineDotPlugin, type DotPlugin } from '@arki/dot/plugin';
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export { defineDotPlugin } from './plugin-contract.js';
|
|
21
|
+
export type { AnyDotPlugin, DotPlugin, DotBootContext, DotBootResult, DotConfigureContext, DotDisposeContext, DotManifestContext, DotManifestContribution, DotStartContext, DotStopContext, } from './plugin-contract.js';
|
|
22
|
+
export { defineApp } from './define-app.js';
|
|
23
|
+
export type { DotApp, DotAppBuilder, DotAppConfigured } from './define-app.js';
|
|
24
|
+
export { testApp, bootTestApp } from './test-harness.js';
|
|
25
|
+
export type { TestAppOptions } from './test-harness.js';
|
|
26
|
+
export type { DotLifecycleHook, DotLifecycleState, DotLifecyclePluginFailure, DotLifecycleErrorCodeValue, } from './lifecycle.js';
|
|
27
|
+
export { DotLifecycleError, DotLifecycleErrorCode, DOT_LIFECYCLE_HOOKS } from './lifecycle.js';
|
|
28
|
+
export type { DotAppManifest, PluginManifest, RouteManifest, ServiceManifest, LifecycleManifest, DependencyEdge, DependencyEdgeKind, ServiceKind, RouteTransport, } from './manifest.js';
|
|
29
|
+
export type { DotDiagnosticsSnapshot, PluginDiagnostic, RouteDiagnostic, ServiceDiagnostic, LifecycleDiagnostic, DiagnosticIssue, DiagnosticSeverity, DiagnosticStatus, } from './diagnostics.js';
|
|
30
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,YAAY,EACV,YAAY,EACZ,SAAS,EACT,cAAc,EACd,aAAa,EACb,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,uBAAuB,EACvB,eAAe,EACf,cAAc,GACf,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAE/E,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACzD,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,yBAAyB,EACzB,0BAA0B,GAC3B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE/F,YAAY,EACV,cAAc,EACd,cAAc,EACd,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,WAAW,EACX,cAAc,GACf,MAAM,eAAe,CAAC;AAEvB,YAAY,EACV,sBAAsB,EACtB,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,EACf,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,kBAAkB,CAAC"}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Narrow public surface for plugin authors.
|
|
3
|
+
*
|
|
4
|
+
* Exposes the new-kernel plugin contract and the entry points a plugin
|
|
5
|
+
* author needs to author + test plugins — `defineDotPlugin`, `defineApp`,
|
|
6
|
+
* `testApp` / `bootTestApp`, plus lifecycle / manifest / diagnostics types.
|
|
7
|
+
*
|
|
8
|
+
* Does NOT re-export the legacy `Dot` / `createDot` builder or the legacy
|
|
9
|
+
* auth/db/event-sourcing modules. Adapter packages (e.g. `@arki/env/dot`,
|
|
10
|
+
* `@arki/kv/dot`, `@arki/db/dot`) import from this subpath so their
|
|
11
|
+
* `*.d.ts` graphs do not pull in the legacy surface — keeping their
|
|
12
|
+
* compile times tight and decoupling adapters from the legacy retirement
|
|
13
|
+
* schedule (Task 12).
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { defineDotPlugin, type DotPlugin } from '@arki/dot/plugin';
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export { defineDotPlugin } from './plugin-contract.js';
|
|
21
|
+
export { defineApp } from './define-app.js';
|
|
22
|
+
export { testApp, bootTestApp } from './test-harness.js';
|
|
23
|
+
export { DotLifecycleError, DotLifecycleErrorCode, DOT_LIFECYCLE_HOOKS } from './lifecycle.js';
|
|
24
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAcvD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AASzD,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test harness for unit-testing DOT pips.
|
|
3
|
+
*
|
|
4
|
+
* Provides `testApp` — a convenience wrapper that lets pip authors verify
|
|
5
|
+
* lifecycle behaviour, registration, and service publishing without dragging
|
|
6
|
+
* in concrete framework dependencies.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* import { testApp, defineDotPip } from '@arki/dot';
|
|
10
|
+
*
|
|
11
|
+
* const myPip = defineDotPip<{ counter: { value: number } }>({
|
|
12
|
+
* name: 'counter',
|
|
13
|
+
* async boot() {
|
|
14
|
+
* return { services: { counter: { value: 0 } } };
|
|
15
|
+
* },
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* it('publishes a counter service', async () => {
|
|
19
|
+
* const app = await testApp([myPip]).boot();
|
|
20
|
+
* expect(app.services.counter.value).toBe(0);
|
|
21
|
+
* await app.dispose();
|
|
22
|
+
* });
|
|
23
|
+
*/
|
|
24
|
+
import type { DotApp, DotAppBuilder } from './define-app.js';
|
|
25
|
+
import type { AnyDotPip, DotPip } from './pip-contract.js';
|
|
26
|
+
export type TestAppOptions = {
|
|
27
|
+
/** App name used in the manifest. Defaults to `'test-app'`. */
|
|
28
|
+
name?: string;
|
|
29
|
+
/** Runtime config bag passed to every boot hook. */
|
|
30
|
+
config?: Readonly<Record<string, unknown>>;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Build a DOT app builder pre-populated with the given pips, ready to
|
|
34
|
+
* `.configure()`, `.boot()` or `.start()` from a test.
|
|
35
|
+
*/
|
|
36
|
+
export declare function testApp<TServices extends Record<string, unknown> = Record<string, never>>(pips?: readonly DotPip<never>[] | readonly DotPip<Record<string, never>>[] | readonly AnyDotPip[], options?: TestAppOptions): DotAppBuilder<TServices>;
|
|
37
|
+
/**
|
|
38
|
+
* Convenience: build, boot, return the running app. Caller is responsible for
|
|
39
|
+
* calling `app.dispose()` when finished.
|
|
40
|
+
*/
|
|
41
|
+
export declare function bootTestApp<TServices extends Record<string, unknown> = Record<string, never>>(pips?: readonly DotPip<never>[] | readonly DotPip<Record<string, never>>[] | readonly AnyDotPip[], options?: TestAppOptions): Promise<DotApp<TServices>>;
|
|
42
|
+
//# sourceMappingURL=test-harness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-harness.d.ts","sourceRoot":"","sources":["../src/test-harness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAG3D,MAAM,MAAM,cAAc,GAAG;IAC3B,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC5C,CAAC;AAEF;;;GAGG;AACH,wBAAgB,OAAO,CAAC,SAAS,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAGvF,IAAI,GAAE,SAAS,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,SAAS,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,SAAS,SAAS,EAAO,EACrG,OAAO,GAAE,cAAmB,GAC3B,aAAa,CAAC,SAAS,CAAC,CAM1B;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,SAAS,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EACjG,IAAI,GAAE,SAAS,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,SAAS,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,SAAS,SAAS,EAAO,EACrG,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAE5B"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test harness for unit-testing DOT pips.
|
|
3
|
+
*
|
|
4
|
+
* Provides `testApp` — a convenience wrapper that lets pip authors verify
|
|
5
|
+
* lifecycle behaviour, registration, and service publishing without dragging
|
|
6
|
+
* in concrete framework dependencies.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* import { testApp, defineDotPip } from '@arki/dot';
|
|
10
|
+
*
|
|
11
|
+
* const myPip = defineDotPip<{ counter: { value: number } }>({
|
|
12
|
+
* name: 'counter',
|
|
13
|
+
* async boot() {
|
|
14
|
+
* return { services: { counter: { value: 0 } } };
|
|
15
|
+
* },
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* it('publishes a counter service', async () => {
|
|
19
|
+
* const app = await testApp([myPip]).boot();
|
|
20
|
+
* expect(app.services.counter.value).toBe(0);
|
|
21
|
+
* await app.dispose();
|
|
22
|
+
* });
|
|
23
|
+
*/
|
|
24
|
+
import { defineApp } from './define-app.js';
|
|
25
|
+
/**
|
|
26
|
+
* Build a DOT app builder pre-populated with the given pips, ready to
|
|
27
|
+
* `.configure()`, `.boot()` or `.start()` from a test.
|
|
28
|
+
*/
|
|
29
|
+
export function testApp(
|
|
30
|
+
// Accept any pip shape — tests routinely mix services types. Internally
|
|
31
|
+
// we erase to `AnyDotPip` for the kernel.
|
|
32
|
+
pips = [], options = {}) {
|
|
33
|
+
let builder = defineApp(options.name ?? 'test-app', { config: options.config });
|
|
34
|
+
for (const pip of pips) {
|
|
35
|
+
builder = builder.use(pip);
|
|
36
|
+
}
|
|
37
|
+
return builder;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Convenience: build, boot, return the running app. Caller is responsible for
|
|
41
|
+
* calling `app.dispose()` when finished.
|
|
42
|
+
*/
|
|
43
|
+
export async function bootTestApp(pips = [], options = {}) {
|
|
44
|
+
return testApp(pips, options).boot();
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=test-harness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-harness.js","sourceRoot":"","sources":["../src/test-harness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAS5C;;;GAGG;AACH,MAAM,UAAU,OAAO;AACrB,wEAAwE;AACxE,0CAA0C;AAC1C,OAAmG,EAAE,EACrG,UAA0B,EAAE;IAE5B,IAAI,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,IAAI,UAAU,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAChF,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,GAAsC,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,OAAmC,CAAC;AAC7C,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,OAAmG,EAAE,EACrG,UAA0B,EAAE;IAE5B,OAAO,OAAO,CAAY,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ASCII waterfall renderer for DOT lifecycle diagnostics.
|
|
3
|
+
*
|
|
4
|
+
* Given a `DotDiagnosticsSnapshot`, builds a compact per-phase, per-pip
|
|
5
|
+
* duration chart suitable for printing in a terminal or embedding in a
|
|
6
|
+
* `dot doctor` text report. No colour, no Unicode beyond `█` so the
|
|
7
|
+
* output stays clean in log aggregators and CI.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```
|
|
11
|
+
* Timeline: my-app (state=booted)
|
|
12
|
+
* ─────────────────────────────────────────────────────────
|
|
13
|
+
* configure
|
|
14
|
+
* env 0.5ms █
|
|
15
|
+
* db 1.4ms █████
|
|
16
|
+
* kv 0.3ms █
|
|
17
|
+
*
|
|
18
|
+
* boot
|
|
19
|
+
* env 2.8ms █████████
|
|
20
|
+
* db 32.9ms ███████████████████████████████████████████
|
|
21
|
+
* kv 3.9ms ████████████
|
|
22
|
+
* ─────────────────────────────────────────────────────────
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @see packages/dot/docs/observability.md
|
|
26
|
+
*/
|
|
27
|
+
import type { DotDiagnosticsSnapshot } from './diagnostics.js';
|
|
28
|
+
export type RenderTimelineOptions = {
|
|
29
|
+
/** Maximum bar width in characters (default `50`). */
|
|
30
|
+
readonly barWidth?: number;
|
|
31
|
+
/**
|
|
32
|
+
* When `true`, also emit any pip's diagnostic `issues[]` underneath
|
|
33
|
+
* the bar so failure reasons are visible in the timeline view.
|
|
34
|
+
* Default `true`.
|
|
35
|
+
*/
|
|
36
|
+
readonly showIssues?: boolean;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Render the snapshot's lifecycle records as a per-phase waterfall.
|
|
40
|
+
* Pure — no IO. Caller is responsible for printing the result.
|
|
41
|
+
*/
|
|
42
|
+
export declare function renderTimeline(snapshot: DotDiagnosticsSnapshot, opts?: RenderTimelineOptions): string;
|
|
43
|
+
//# sourceMappingURL=timeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeline.d.ts","sourceRoot":"","sources":["../src/timeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAuB,MAAM,kBAAkB,CAAC;AASpF,MAAM,MAAM,qBAAqB,GAAG;IAClC,sDAAsD;IACtD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;CAC/B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,sBAAsB,EAAE,IAAI,GAAE,qBAA0B,GAAG,MAAM,CA+DzG"}
|
package/dist/timeline.js
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ASCII waterfall renderer for DOT lifecycle diagnostics.
|
|
3
|
+
*
|
|
4
|
+
* Given a `DotDiagnosticsSnapshot`, builds a compact per-phase, per-pip
|
|
5
|
+
* duration chart suitable for printing in a terminal or embedding in a
|
|
6
|
+
* `dot doctor` text report. No colour, no Unicode beyond `█` so the
|
|
7
|
+
* output stays clean in log aggregators and CI.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```
|
|
11
|
+
* Timeline: my-app (state=booted)
|
|
12
|
+
* ─────────────────────────────────────────────────────────
|
|
13
|
+
* configure
|
|
14
|
+
* env 0.5ms █
|
|
15
|
+
* db 1.4ms █████
|
|
16
|
+
* kv 0.3ms █
|
|
17
|
+
*
|
|
18
|
+
* boot
|
|
19
|
+
* env 2.8ms █████████
|
|
20
|
+
* db 32.9ms ███████████████████████████████████████████
|
|
21
|
+
* kv 3.9ms ████████████
|
|
22
|
+
* ─────────────────────────────────────────────────────────
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @see packages/dot/docs/observability.md
|
|
26
|
+
*/
|
|
27
|
+
const PHASE_ORDER = ['configure', 'boot', 'start', 'stop', 'dispose'];
|
|
28
|
+
const BAR_CHAR = '█';
|
|
29
|
+
const DEFAULT_BAR_WIDTH = 50;
|
|
30
|
+
const MIN_BAR_FOR_NONZERO = 1;
|
|
31
|
+
/**
|
|
32
|
+
* Render the snapshot's lifecycle records as a per-phase waterfall.
|
|
33
|
+
* Pure — no IO. Caller is responsible for printing the result.
|
|
34
|
+
*/
|
|
35
|
+
export function renderTimeline(snapshot, opts = {}) {
|
|
36
|
+
const barWidth = opts.barWidth ?? DEFAULT_BAR_WIDTH;
|
|
37
|
+
const showIssues = opts.showIssues ?? true;
|
|
38
|
+
// Group lifecycle entries by phase, preserving execution order within
|
|
39
|
+
// each phase. The kernel pushes entries in execution order; we filter
|
|
40
|
+
// and re-order here to make the output deterministic when phases are
|
|
41
|
+
// interleaved (currently they aren't, but be defensive).
|
|
42
|
+
const byPhase = new Map();
|
|
43
|
+
for (const entry of snapshot.lifecycle) {
|
|
44
|
+
const bucket = byPhase.get(entry.hook);
|
|
45
|
+
if (bucket)
|
|
46
|
+
bucket.push(entry);
|
|
47
|
+
else
|
|
48
|
+
byPhase.set(entry.hook, [entry]);
|
|
49
|
+
}
|
|
50
|
+
// Scale: the longest duration across all entries sets the full-width bar.
|
|
51
|
+
// Using a single global scale lets readers compare durations across
|
|
52
|
+
// phases at a glance ("boot.db is 10x configure.env").
|
|
53
|
+
let maxDuration = 0;
|
|
54
|
+
for (const entry of snapshot.lifecycle) {
|
|
55
|
+
const d = entry.durationMs ?? 0;
|
|
56
|
+
if (d > maxDuration)
|
|
57
|
+
maxDuration = d;
|
|
58
|
+
}
|
|
59
|
+
const lines = [];
|
|
60
|
+
const title = `Timeline: ${snapshot.app.name} (state=${snapshot.app.state})`;
|
|
61
|
+
lines.push(title);
|
|
62
|
+
lines.push('─'.repeat(title.length));
|
|
63
|
+
// Layout: 2-space indent, 10-char pip column, 8-char duration column, then bar.
|
|
64
|
+
const PIP_COL = 12;
|
|
65
|
+
const DUR_COL = 8;
|
|
66
|
+
const indent = ' ';
|
|
67
|
+
let anyRendered = false;
|
|
68
|
+
for (const phase of PHASE_ORDER) {
|
|
69
|
+
const entries = byPhase.get(phase);
|
|
70
|
+
if (!entries || entries.length === 0)
|
|
71
|
+
continue;
|
|
72
|
+
if (anyRendered)
|
|
73
|
+
lines.push('');
|
|
74
|
+
anyRendered = true;
|
|
75
|
+
lines.push(phase);
|
|
76
|
+
for (const entry of entries) {
|
|
77
|
+
const durationMs = entry.durationMs ?? 0;
|
|
78
|
+
const bar = makeBar(durationMs, maxDuration, barWidth);
|
|
79
|
+
const failedMark = entry.state === 'failed' ? ' ✗' : '';
|
|
80
|
+
const pipCol = entry.pip.padEnd(PIP_COL);
|
|
81
|
+
const durCol = formatDuration(durationMs).padStart(DUR_COL);
|
|
82
|
+
lines.push(`${indent}${pipCol}${durCol} ${bar}${failedMark}`);
|
|
83
|
+
if (showIssues && entry.issues.length > 0) {
|
|
84
|
+
for (const issue of entry.issues) {
|
|
85
|
+
lines.push(`${indent} └─ ${issue.code}: ${issue.message}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (!anyRendered) {
|
|
91
|
+
lines.push('(no lifecycle entries — app has not run any phase yet)');
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
lines.push('─'.repeat(title.length));
|
|
95
|
+
}
|
|
96
|
+
return lines.join('\n');
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Build the bar string. Zero-duration entries get a single block (so they
|
|
100
|
+
* are still visually present); otherwise width is proportional to the
|
|
101
|
+
* global max.
|
|
102
|
+
*/
|
|
103
|
+
function makeBar(duration, max, width) {
|
|
104
|
+
if (max <= 0)
|
|
105
|
+
return '';
|
|
106
|
+
if (duration <= 0)
|
|
107
|
+
return BAR_CHAR.repeat(MIN_BAR_FOR_NONZERO);
|
|
108
|
+
const cells = Math.max(MIN_BAR_FOR_NONZERO, Math.round((duration / max) * width));
|
|
109
|
+
return BAR_CHAR.repeat(cells);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Format a duration in milliseconds with one decimal place. Caps the
|
|
113
|
+
* decimal at sub-second values; values ≥ 1000ms render as integer ms
|
|
114
|
+
* to keep the column tight.
|
|
115
|
+
*/
|
|
116
|
+
function formatDuration(ms) {
|
|
117
|
+
if (ms >= 1000)
|
|
118
|
+
return `${Math.round(ms)}ms`;
|
|
119
|
+
return `${ms.toFixed(1)}ms`;
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=timeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeline.js","sourceRoot":"","sources":["../src/timeline.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@arki/dot",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "TypeScript-first application composition framework for the ARKI package family — lifecycle-aware pips, deterministic boot order, manifest/diagnostics envelopes, and an agent-native CLI. A DOT app is the sum of its pips.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/arki-labs/arki.git"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://arki.dev/dot",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/arki-labs/arki/issues"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"arki",
|
|
16
|
+
"typescript",
|
|
17
|
+
"framework",
|
|
18
|
+
"pip",
|
|
19
|
+
"pips",
|
|
20
|
+
"lifecycle",
|
|
21
|
+
"diagnostics",
|
|
22
|
+
"manifest",
|
|
23
|
+
"agent-native",
|
|
24
|
+
"dot"
|
|
25
|
+
],
|
|
26
|
+
"type": "module",
|
|
27
|
+
"sideEffects": false,
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"import": "./src/index.ts",
|
|
32
|
+
"default": "./dist/index.js"
|
|
33
|
+
},
|
|
34
|
+
"./pip": {
|
|
35
|
+
"types": "./dist/pip.d.ts",
|
|
36
|
+
"import": "./dist/pip.js",
|
|
37
|
+
"default": "./dist/pip.js"
|
|
38
|
+
},
|
|
39
|
+
"./package.json": "./package.json",
|
|
40
|
+
"./cli": {
|
|
41
|
+
"types": "./dist/cli/index.d.ts",
|
|
42
|
+
"import": "./src/cli/index.ts",
|
|
43
|
+
"default": "./dist/cli/index.js"
|
|
44
|
+
},
|
|
45
|
+
"./test-harness": {
|
|
46
|
+
"types": "./dist/test-harness.d.ts",
|
|
47
|
+
"import": "./src/test-harness.ts",
|
|
48
|
+
"default": "./dist/test-harness.js"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"files": [
|
|
52
|
+
"dist/**",
|
|
53
|
+
"templates/**",
|
|
54
|
+
"README.md",
|
|
55
|
+
"LICENSE",
|
|
56
|
+
"package.json"
|
|
57
|
+
],
|
|
58
|
+
"dependencies": {
|
|
59
|
+
"@arki/assert": "0.0.1",
|
|
60
|
+
"@arki/contracts": "0.0.1",
|
|
61
|
+
"@arki/log": "0.0.1",
|
|
62
|
+
"@opentelemetry/api": "^1.9.0",
|
|
63
|
+
"zod": "4.3.5"
|
|
64
|
+
},
|
|
65
|
+
"publishConfig": {
|
|
66
|
+
"access": "public"
|
|
67
|
+
}
|
|
68
|
+
}
|