@kronos-ts/app 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.d.ts +228 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +519 -0
- package/dist/app.js.map +1 -0
- package/dist/components.d.ts +28 -0
- package/dist/components.d.ts.map +1 -0
- package/dist/components.js +14 -0
- package/dist/components.js.map +1 -0
- package/dist/decorator.d.ts +54 -0
- package/dist/decorator.d.ts.map +1 -0
- package/dist/decorator.js +36 -0
- package/dist/decorator.js.map +1 -0
- package/dist/defaults-handles.d.ts +25 -0
- package/dist/defaults-handles.d.ts.map +1 -0
- package/dist/defaults-handles.js +25 -0
- package/dist/defaults-handles.js.map +1 -0
- package/dist/defaults.d.ts +10 -0
- package/dist/defaults.d.ts.map +1 -0
- package/dist/defaults.js +49 -0
- package/dist/defaults.js.map +1 -0
- package/dist/errors.d.ts +37 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +53 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/kronos.d.ts +51 -0
- package/dist/kronos.d.ts.map +1 -0
- package/dist/kronos.js +74 -0
- package/dist/kronos.js.map +1 -0
- package/dist/lifecycle.d.ts +27 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/lifecycle.js +7 -0
- package/dist/lifecycle.js.map +1 -0
- package/dist/resolved.d.ts +18 -0
- package/dist/resolved.d.ts.map +1 -0
- package/dist/resolved.js +43 -0
- package/dist/resolved.js.map +1 -0
- package/dist/slot-registry.d.ts +35 -0
- package/dist/slot-registry.d.ts.map +1 -0
- package/dist/slot-registry.js +50 -0
- package/dist/slot-registry.js.map +1 -0
- package/dist/warnings.d.ts +19 -0
- package/dist/warnings.d.ts.map +1 -0
- package/dist/warnings.js +14 -0
- package/dist/warnings.js.map +1 -0
- package/package.json +59 -0
- package/src/app.ts +795 -0
- package/src/components.ts +48 -0
- package/src/decorator.ts +88 -0
- package/src/defaults-handles.ts +29 -0
- package/src/defaults.ts +64 -0
- package/src/errors.ts +62 -0
- package/src/index.ts +38 -0
- package/src/kronos.ts +117 -0
- package/src/lifecycle.ts +33 -0
- package/src/resolved.ts +54 -0
- package/src/slot-registry.ts +89 -0
- package/src/warnings.ts +32 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @internal — used by `Defaults` and by `kronos()` bootstrap (Plan 02) to
|
|
3
|
+
* mint pre-allocated framework-default handles with stable identity.
|
|
4
|
+
*/
|
|
5
|
+
export function makeFrameworkHandle(slot, name) {
|
|
6
|
+
return Object.freeze({
|
|
7
|
+
__slot: slot,
|
|
8
|
+
__id: Symbol(`${slot}.${name}`),
|
|
9
|
+
__name: name,
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Apply all decorator registrations for a given slot in two passes:
|
|
14
|
+
* 1. Framework defaults first (innermost, handler-adjacent)
|
|
15
|
+
* 2. User decorators after (outer; last .decorate() = outermost wrap)
|
|
16
|
+
*
|
|
17
|
+
* Both passes iterate `registrations` in registration order so a
|
|
18
|
+
* left-to-right reduce composes correctly (each factory wraps the current value).
|
|
19
|
+
*/
|
|
20
|
+
export function applyDecorators(slot, base, registrations, resolved) {
|
|
21
|
+
let current = base;
|
|
22
|
+
// Pass 1: framework defaults (innermost)
|
|
23
|
+
for (const reg of registrations) {
|
|
24
|
+
if (reg.handle.__slot !== slot || !reg.frameworkDefault)
|
|
25
|
+
continue;
|
|
26
|
+
current = reg.factory(current, resolved);
|
|
27
|
+
}
|
|
28
|
+
// Pass 2: user decorators (outer)
|
|
29
|
+
for (const reg of registrations) {
|
|
30
|
+
if (reg.handle.__slot !== slot || reg.frameworkDefault)
|
|
31
|
+
continue;
|
|
32
|
+
current = reg.factory(current, resolved);
|
|
33
|
+
}
|
|
34
|
+
return current;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=decorator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorator.js","sourceRoot":"","sources":["../src/decorator.ts"],"names":[],"mappings":"AA8CA;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CACjC,IAAO,EACP,IAAY;IAEZ,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,MAAM,EAAE,IAAI;QACZ,IAAI,EAAE,MAAM,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC;QAC/B,MAAM,EAAE,IAAI;KACb,CAAuB,CAAA;AAC1B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAC7B,IAAO,EACP,IAAyB,EACzB,aAA4C,EAC5C,QAAkB;IAElB,IAAI,OAAO,GAAG,IAAI,CAAA;IAClB,yCAAyC;IACzC,KAAK,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;QAChC,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,gBAAgB;YAAE,SAAQ;QACjE,OAAO,GAAI,GAAG,CAAC,OAA0C,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;IAC9E,CAAC;IACD,kCAAkC;IAClC,KAAK,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;QAChC,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,KAAK,IAAI,IAAI,GAAG,CAAC,gBAAgB;YAAE,SAAQ;QAChE,OAAO,GAAI,GAAG,CAAC,OAA0C,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;IAC9E,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type DecoratorHandle } from "./decorator.js";
|
|
2
|
+
/**
|
|
3
|
+
* Global static module export — frozen handle identities for framework-default
|
|
4
|
+
* decorators (D-54). Per-app decorator state lives on `AppState`; `Defaults`
|
|
5
|
+
* only carries handle *identities*.
|
|
6
|
+
*
|
|
7
|
+
* Plan 02 wires the actual factories in `kronos()` bootstrap, keyed by these
|
|
8
|
+
* handles. Plan 01 ships the handle constants only — having them in place
|
|
9
|
+
* lets users write `app.removeDecorator(Defaults.commandBus.intercepting)`
|
|
10
|
+
* even before Plan 02 registers the factories (the call will throw
|
|
11
|
+
* `UnknownDecoratorHandleError` until Plan 02 lands, which is correct
|
|
12
|
+
* behavior for now and ratchets to the real removal once Plan 02 ships).
|
|
13
|
+
*/
|
|
14
|
+
export declare const Defaults: {
|
|
15
|
+
readonly commandBus: {
|
|
16
|
+
readonly intercepting: DecoratorHandle<"commandBus">;
|
|
17
|
+
};
|
|
18
|
+
readonly queryBus: {
|
|
19
|
+
readonly intercepting: DecoratorHandle<"queryBus">;
|
|
20
|
+
};
|
|
21
|
+
readonly eventBus: {
|
|
22
|
+
readonly intercepting: DecoratorHandle<"eventBus">;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=defaults-handles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults-handles.d.ts","sourceRoot":"","sources":["../src/defaults-handles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAE1E;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,QAAQ,EAUf;IACJ,QAAQ,CAAC,UAAU,EAAE;QAAE,QAAQ,CAAC,YAAY,EAAE,eAAe,CAAC,YAAY,CAAC,CAAA;KAAE,CAAA;IAC7E,QAAQ,CAAC,QAAQ,EAAE;QAAE,QAAQ,CAAC,YAAY,EAAE,eAAe,CAAC,UAAU,CAAC,CAAA;KAAE,CAAA;IACzE,QAAQ,CAAC,QAAQ,EAAE;QAAE,QAAQ,CAAC,YAAY,EAAE,eAAe,CAAC,UAAU,CAAC,CAAA;KAAE,CAAA;CAC1E,CAAA"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { makeFrameworkHandle } from "./decorator.js";
|
|
2
|
+
/**
|
|
3
|
+
* Global static module export — frozen handle identities for framework-default
|
|
4
|
+
* decorators (D-54). Per-app decorator state lives on `AppState`; `Defaults`
|
|
5
|
+
* only carries handle *identities*.
|
|
6
|
+
*
|
|
7
|
+
* Plan 02 wires the actual factories in `kronos()` bootstrap, keyed by these
|
|
8
|
+
* handles. Plan 01 ships the handle constants only — having them in place
|
|
9
|
+
* lets users write `app.removeDecorator(Defaults.commandBus.intercepting)`
|
|
10
|
+
* even before Plan 02 registers the factories (the call will throw
|
|
11
|
+
* `UnknownDecoratorHandleError` until Plan 02 lands, which is correct
|
|
12
|
+
* behavior for now and ratchets to the real removal once Plan 02 ships).
|
|
13
|
+
*/
|
|
14
|
+
export const Defaults = Object.freeze({
|
|
15
|
+
commandBus: Object.freeze({
|
|
16
|
+
intercepting: makeFrameworkHandle("commandBus", "intercepting"),
|
|
17
|
+
}),
|
|
18
|
+
queryBus: Object.freeze({
|
|
19
|
+
intercepting: makeFrameworkHandle("queryBus", "intercepting"),
|
|
20
|
+
}),
|
|
21
|
+
eventBus: Object.freeze({
|
|
22
|
+
intercepting: makeFrameworkHandle("eventBus", "intercepting"),
|
|
23
|
+
}),
|
|
24
|
+
});
|
|
25
|
+
//# sourceMappingURL=defaults-handles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults-handles.js","sourceRoot":"","sources":["../src/defaults-handles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAwB,MAAM,gBAAgB,CAAA;AAE1E;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC;QACxB,YAAY,EAAE,mBAAmB,CAAC,YAAY,EAAE,cAAc,CAAC;KAChE,CAAC;IACF,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC;QACtB,YAAY,EAAE,mBAAmB,CAAC,UAAU,EAAE,cAAc,CAAC;KAC9D,CAAC;IACF,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC;QACtB,YAAY,EAAE,mBAAmB,CAAC,UAAU,EAAE,cAAc,CAAC;KAC9D,CAAC;CACH,CAIA,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { App } from "./app.js";
|
|
2
|
+
/**
|
|
3
|
+
* Register the 8 in-memory defaults (SLT-04, D-51).
|
|
4
|
+
* Slots flagged inMemory:true emit a startup warning at .start() unless the slot
|
|
5
|
+
* was overridden via .set/.forceSet (or another .setDefault won — but setDefault
|
|
6
|
+
* is ifAbsent, so only the FIRST setDefault wins; user setDefault calls on already-defaulted
|
|
7
|
+
* slots are no-ops, which is the intended SLT-02 semantics).
|
|
8
|
+
*/
|
|
9
|
+
export declare function registerInMemoryDefaults(app: App): void;
|
|
10
|
+
//# sourceMappingURL=defaults.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAgBnC;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,CAwCvD"}
|
package/dist/defaults.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { createInMemoryEventStore, createInMemorySnapshotStore, descriptorBasedTagResolver, } from "@kronos-ts/eventsourcing";
|
|
2
|
+
import { createSimpleCommandBus, createSimpleQueryBus, jsonSerializer, runInNewUoW, createInMemoryTokenStore, noTransactionManager, } from "@kronos-ts/messaging";
|
|
3
|
+
/**
|
|
4
|
+
* Register the 8 in-memory defaults (SLT-04, D-51).
|
|
5
|
+
* Slots flagged inMemory:true emit a startup warning at .start() unless the slot
|
|
6
|
+
* was overridden via .set/.forceSet (or another .setDefault won — but setDefault
|
|
7
|
+
* is ifAbsent, so only the FIRST setDefault wins; user setDefault calls on already-defaulted
|
|
8
|
+
* slots are no-ops, which is the intended SLT-02 semantics).
|
|
9
|
+
*/
|
|
10
|
+
export function registerInMemoryDefaults(app) {
|
|
11
|
+
// Durability-flagged defaults (SLT-04 warning fires unless overridden):
|
|
12
|
+
app.setDefault("eventStore", () => createInMemoryEventStore(), {
|
|
13
|
+
inMemory: true,
|
|
14
|
+
warning: "[kronos] eventStore: in-memory — not durable, configure an extension for production",
|
|
15
|
+
});
|
|
16
|
+
app.setDefault("snapshotStore", () => createInMemorySnapshotStore(), {
|
|
17
|
+
inMemory: true,
|
|
18
|
+
warning: "[kronos] snapshotStore: in-memory — not durable, configure an extension for production",
|
|
19
|
+
});
|
|
20
|
+
app.setDefault("commandBus", () => createSimpleCommandBus(), {
|
|
21
|
+
inMemory: true,
|
|
22
|
+
warning: "[kronos] commandBus: in-memory — single-process only, configure an extension for distribution",
|
|
23
|
+
});
|
|
24
|
+
app.setDefault("queryBus", () => createSimpleQueryBus(), {
|
|
25
|
+
inMemory: true,
|
|
26
|
+
warning: "[kronos] queryBus: in-memory — single-process only, configure an extension for distribution",
|
|
27
|
+
});
|
|
28
|
+
// EventBus default: in ES setups EventStore IS the EventBus (configurer mirrors this at line 796)
|
|
29
|
+
app.setDefault("eventBus", ({ eventStore }) => eventStore, {
|
|
30
|
+
inMemory: true,
|
|
31
|
+
warning: "[kronos] eventBus: in-memory — single-process only",
|
|
32
|
+
});
|
|
33
|
+
// Stateless / non-durability-implied defaults — NO inMemory flag, no warning emission:
|
|
34
|
+
app.setDefault("serializer", () => jsonSerializer());
|
|
35
|
+
app.setDefault("unitOfWorkFactory", () => runInNewUoW);
|
|
36
|
+
app.setDefault("tagResolver", () => descriptorBasedTagResolver());
|
|
37
|
+
// Plan 09-01 (D-84): typed slots for token persistence + transactional wrapping.
|
|
38
|
+
// Both default to in-memory — extensions (KronosDB, Drizzle/Knex/Kysely token stores,
|
|
39
|
+
// user-supplied TransactionManagers) override via app.set('tokenStore', ...) etc.
|
|
40
|
+
app.setDefault("tokenStore", () => createInMemoryTokenStore(), {
|
|
41
|
+
inMemory: true,
|
|
42
|
+
warning: "[kronos] tokenStore: in-memory — not durable, configure a persistence extension for production",
|
|
43
|
+
});
|
|
44
|
+
app.setDefault("transactionManager", () => noTransactionManager(), {
|
|
45
|
+
inMemory: true,
|
|
46
|
+
warning: "[kronos] transactionManager: in-memory — pass-through, configure a transactional extension for production",
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=defaults.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.js","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,wBAAwB,EACxB,2BAA2B,EAC3B,0BAA0B,GAC3B,MAAM,0BAA0B,CAAA;AACjC,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,cAAc,EACd,WAAW,EACX,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,sBAAsB,CAAA;AAE7B;;;;;;GAMG;AACH,MAAM,UAAU,wBAAwB,CAAC,GAAQ;IAC/C,wEAAwE;IACxE,GAAG,CAAC,UAAU,CAAC,YAAY,EAAE,GAAG,EAAE,CAAC,wBAAwB,EAAE,EAAE;QAC7D,QAAQ,EAAE,IAAI;QACd,OAAO,EAAE,qFAAqF;KAC/F,CAAC,CAAA;IACF,GAAG,CAAC,UAAU,CAAC,eAAe,EAAE,GAAG,EAAE,CAAC,2BAA2B,EAAE,EAAE;QACnE,QAAQ,EAAE,IAAI;QACd,OAAO,EAAE,wFAAwF;KAClG,CAAC,CAAA;IACF,GAAG,CAAC,UAAU,CAAC,YAAY,EAAE,GAAG,EAAE,CAAC,sBAAsB,EAAE,EAAE;QAC3D,QAAQ,EAAE,IAAI;QACd,OAAO,EAAE,+FAA+F;KACzG,CAAC,CAAA;IACF,GAAG,CAAC,UAAU,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC,oBAAoB,EAAE,EAAE;QACvD,QAAQ,EAAE,IAAI;QACd,OAAO,EAAE,6FAA6F;KACvG,CAAC,CAAA;IACF,kGAAkG;IAClG,GAAG,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,UAAiC,EAAE;QAChF,QAAQ,EAAE,IAAI;QACd,OAAO,EAAE,oDAAoD;KAC9D,CAAC,CAAA;IAEF,uFAAuF;IACvF,GAAG,CAAC,UAAU,CAAC,YAAY,EAAE,GAAG,EAAE,CAAC,cAAc,EAAE,CAAC,CAAA;IACpD,GAAG,CAAC,UAAU,CAAC,mBAAmB,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,CAAA;IACtD,GAAG,CAAC,UAAU,CAAC,aAAa,EAAE,GAAG,EAAE,CAAC,0BAA0B,EAAE,CAAC,CAAA;IAEjE,iFAAiF;IACjF,sFAAsF;IACtF,kFAAkF;IAClF,GAAG,CAAC,UAAU,CAAC,YAAY,EAAE,GAAG,EAAE,CAAC,wBAAwB,EAAE,EAAE;QAC7D,QAAQ,EAAE,IAAI;QACd,OAAO,EAAE,gGAAgG;KAC1G,CAAC,CAAA;IACF,GAAG,CAAC,UAAU,CAAC,oBAAoB,EAAE,GAAG,EAAE,CAAC,oBAAoB,EAAE,EAAE;QACjE,QAAQ,EAAE,IAAI;QACd,OAAO,EAAE,2GAA2G;KACrH,CAAC,CAAA;AACJ,CAAC"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { SlotName } from "./components.js";
|
|
2
|
+
import type { DecoratorHandle } from "./decorator.js";
|
|
3
|
+
/**
|
|
4
|
+
* Thrown when buildResolved detects a cycle: a factory's getter on Resolved re-enters
|
|
5
|
+
* a slot that is currently being resolved. (D-52 cycle-detection contract.)
|
|
6
|
+
*/
|
|
7
|
+
export declare class CircularSlotDependencyError extends Error {
|
|
8
|
+
readonly slot: SlotName;
|
|
9
|
+
readonly chain: readonly SlotName[];
|
|
10
|
+
constructor(slot: SlotName, chain: readonly SlotName[]);
|
|
11
|
+
}
|
|
12
|
+
/** Thrown when a Resolved getter touches a slot that has no registered factory. */
|
|
13
|
+
export declare class SlotNotRegisteredError extends Error {
|
|
14
|
+
readonly slot: SlotName;
|
|
15
|
+
constructor(slot: SlotName);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Thrown when `app.commandGateway` or `app.queryGateway` is accessed before
|
|
19
|
+
* the `register` lifecycle stage completes during `.start()`. Available inside
|
|
20
|
+
* `onStart('warmup'|'register'|'processors'|'serve', fn)` hooks AFTER register
|
|
21
|
+
* completes, and after `.start()` resolves. (Plan 08-01.)
|
|
22
|
+
*/
|
|
23
|
+
export declare class AppNotStartedError extends Error {
|
|
24
|
+
constructor(accessor: string);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Thrown by `app.removeDecorator(handle)` when the handle is not found in the
|
|
28
|
+
* app's registration list (D-59). Catches typos like
|
|
29
|
+
* `Defaults.commandBus.interceptingg` and removal of a handle that was never
|
|
30
|
+
* registered (e.g., framework default whose factory hasn't been wired yet).
|
|
31
|
+
*/
|
|
32
|
+
export declare class UnknownDecoratorHandleError extends Error {
|
|
33
|
+
readonly slot: SlotName;
|
|
34
|
+
readonly handleName: string;
|
|
35
|
+
constructor(handle: DecoratorHandle<SlotName>);
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAErD;;;GAGG;AACH,qBAAa,2BAA4B,SAAQ,KAAK;IACpD,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;IACvB,QAAQ,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAA;gBACvB,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,QAAQ,EAAE;CAMvD;AAED,mFAAmF;AACnF,qBAAa,sBAAuB,SAAQ,KAAK;IAC/C,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;gBACX,IAAI,EAAE,QAAQ;CAK3B;AAED;;;;;GAKG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,QAAQ,EAAE,MAAM;CAM7B;AAED;;;;;GAKG;AACH,qBAAa,2BAA4B,SAAQ,KAAK;IACpD,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;gBACf,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC;CAS9C"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thrown when buildResolved detects a cycle: a factory's getter on Resolved re-enters
|
|
3
|
+
* a slot that is currently being resolved. (D-52 cycle-detection contract.)
|
|
4
|
+
*/
|
|
5
|
+
export class CircularSlotDependencyError extends Error {
|
|
6
|
+
slot;
|
|
7
|
+
chain;
|
|
8
|
+
constructor(slot, chain) {
|
|
9
|
+
super(`[kronos] Circular slot dependency: "${slot}" via [${chain.join(" → ")}]`);
|
|
10
|
+
this.name = "CircularSlotDependencyError";
|
|
11
|
+
this.slot = slot;
|
|
12
|
+
this.chain = chain;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/** Thrown when a Resolved getter touches a slot that has no registered factory. */
|
|
16
|
+
export class SlotNotRegisteredError extends Error {
|
|
17
|
+
slot;
|
|
18
|
+
constructor(slot) {
|
|
19
|
+
super(`[kronos] Slot "${slot}" has no registered factory.`);
|
|
20
|
+
this.name = "SlotNotRegisteredError";
|
|
21
|
+
this.slot = slot;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Thrown when `app.commandGateway` or `app.queryGateway` is accessed before
|
|
26
|
+
* the `register` lifecycle stage completes during `.start()`. Available inside
|
|
27
|
+
* `onStart('warmup'|'register'|'processors'|'serve', fn)` hooks AFTER register
|
|
28
|
+
* completes, and after `.start()` resolves. (Plan 08-01.)
|
|
29
|
+
*/
|
|
30
|
+
export class AppNotStartedError extends Error {
|
|
31
|
+
constructor(accessor) {
|
|
32
|
+
super(`[kronos] App not started: ${accessor} is only accessible after register-stage completes during .start().`);
|
|
33
|
+
this.name = "AppNotStartedError";
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Thrown by `app.removeDecorator(handle)` when the handle is not found in the
|
|
38
|
+
* app's registration list (D-59). Catches typos like
|
|
39
|
+
* `Defaults.commandBus.interceptingg` and removal of a handle that was never
|
|
40
|
+
* registered (e.g., framework default whose factory hasn't been wired yet).
|
|
41
|
+
*/
|
|
42
|
+
export class UnknownDecoratorHandleError extends Error {
|
|
43
|
+
slot;
|
|
44
|
+
handleName;
|
|
45
|
+
constructor(handle) {
|
|
46
|
+
super(`[kronos] Unknown decorator handle "${handle.__name}" for slot "${handle.__slot}". ` +
|
|
47
|
+
`Either it was never registered or it was already removed.`);
|
|
48
|
+
this.name = "UnknownDecoratorHandleError";
|
|
49
|
+
this.slot = handle.__slot;
|
|
50
|
+
this.handleName = handle.__name;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,MAAM,OAAO,2BAA4B,SAAQ,KAAK;IAC3C,IAAI,CAAU;IACd,KAAK,CAAqB;IACnC,YAAY,IAAc,EAAE,KAA0B;QACpD,KAAK,CAAC,uCAAuC,IAAI,UAAU,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAChF,IAAI,CAAC,IAAI,GAAG,6BAA6B,CAAA;QACzC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;IACpB,CAAC;CACF;AAED,mFAAmF;AACnF,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IACtC,IAAI,CAAU;IACvB,YAAY,IAAc;QACxB,KAAK,CAAC,kBAAkB,IAAI,8BAA8B,CAAC,CAAA;QAC3D,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAA;QACpC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,QAAgB;QAC1B,KAAK,CACH,6BAA6B,QAAQ,qEAAqE,CAC3G,CAAA;QACD,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAA;IAClC,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,OAAO,2BAA4B,SAAQ,KAAK;IAC3C,IAAI,CAAU;IACd,UAAU,CAAQ;IAC3B,YAAY,MAAiC;QAC3C,KAAK,CACH,sCAAsC,MAAM,CAAC,MAAM,eAAe,MAAM,CAAC,MAAM,KAAK;YAClF,2DAA2D,CAC9D,CAAA;QACD,IAAI,CAAC,IAAI,GAAG,6BAA6B,CAAA;QACzC,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,CAAA;QACzB,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,CAAA;IACjC,CAAC;CACF"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type { KronosComponents, SlotName } from "./components.js";
|
|
2
|
+
export { ALL_SLOTS } from "./components.js";
|
|
3
|
+
export { CircularSlotDependencyError, SlotNotRegisteredError } from "./errors.js";
|
|
4
|
+
export { SlotRegistry, type SlotMeta, type SlotEntry, type SlotFactory } from "./slot-registry.js";
|
|
5
|
+
export { buildResolved, type Resolved } from "./resolved.js";
|
|
6
|
+
export { createWarningChannel, type WarningLogger, type WarningChannelOptions, type WarningChannel, } from "./warnings.js";
|
|
7
|
+
export { AppImpl, AppAlreadyStartedError, type App, type RunningApp, type Extension, type AppState, type AppImplOptions, type KronosIdentity, } from "./app.js";
|
|
8
|
+
export { registerInMemoryDefaults } from "./defaults.js";
|
|
9
|
+
export { kronos, type KronosPartialConfig } from "./kronos.js";
|
|
10
|
+
export { type DecoratorHandle, type DecoratorFactory, type DecoratorEntry, applyDecorators, } from "./decorator.js";
|
|
11
|
+
export { Defaults } from "./defaults-handles.js";
|
|
12
|
+
export { UnknownDecoratorHandleError, AppNotStartedError } from "./errors.js";
|
|
13
|
+
export type { LifecycleStage, LifecycleHook } from "./lifecycle.js";
|
|
14
|
+
export type { TokenStore, TransactionManager } from "@kronos-ts/messaging";
|
|
15
|
+
export type { HandlerEnhancerDefinition } from "@kronos-ts/messaging";
|
|
16
|
+
export type { StateOptions, StatesArg } from "./app.js";
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AACjE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,2BAA2B,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AACjF,OAAO,EAAE,YAAY,EAAE,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAClG,OAAO,EAAE,aAAa,EAAE,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,EACL,oBAAoB,EACpB,KAAK,aAAa,EAClB,KAAK,qBAAqB,EAC1B,KAAK,cAAc,GACpB,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,OAAO,EACP,sBAAsB,EACtB,KAAK,GAAG,EACR,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,cAAc,GACpB,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAA;AACxD,OAAO,EAAE,MAAM,EAAE,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAC9D,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,eAAe,GAChB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAChD,OAAO,EAAE,2BAA2B,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAC7E,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAGnE,YAAY,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAE1E,YAAY,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAA;AACrE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { ALL_SLOTS } from "./components.js";
|
|
2
|
+
export { CircularSlotDependencyError, SlotNotRegisteredError } from "./errors.js";
|
|
3
|
+
export { SlotRegistry } from "./slot-registry.js";
|
|
4
|
+
export { buildResolved } from "./resolved.js";
|
|
5
|
+
export { createWarningChannel, } from "./warnings.js";
|
|
6
|
+
export { AppImpl, AppAlreadyStartedError, } from "./app.js";
|
|
7
|
+
export { registerInMemoryDefaults } from "./defaults.js";
|
|
8
|
+
export { kronos } from "./kronos.js";
|
|
9
|
+
export { applyDecorators, } from "./decorator.js";
|
|
10
|
+
export { Defaults } from "./defaults-handles.js";
|
|
11
|
+
export { UnknownDecoratorHandleError, AppNotStartedError } from "./errors.js";
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,2BAA2B,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AACjF,OAAO,EAAE,YAAY,EAAmD,MAAM,oBAAoB,CAAA;AAClG,OAAO,EAAE,aAAa,EAAiB,MAAM,eAAe,CAAA;AAC5D,OAAO,EACL,oBAAoB,GAIrB,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,OAAO,EACP,sBAAsB,GAOvB,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAA;AACxD,OAAO,EAAE,MAAM,EAA4B,MAAM,aAAa,CAAA;AAC9D,OAAO,EAIL,eAAe,GAChB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAChD,OAAO,EAAE,2BAA2B,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA"}
|
package/dist/kronos.d.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { StateModule } from "@kronos-ts/modelling";
|
|
2
|
+
import type { CommandHandlerDefinition, QueryHandlerDefinition, EventProcessorModule } from "@kronos-ts/messaging";
|
|
3
|
+
import { type App } from "./app.js";
|
|
4
|
+
import { type WarningLogger } from "./warnings.js";
|
|
5
|
+
/**
|
|
6
|
+
* Partial-config shorthand options for kronos(). APP-02.
|
|
7
|
+
*
|
|
8
|
+
* Domain registrations passed here are appended to the same internal accumulators
|
|
9
|
+
* as fluent .states()/.commands()/etc. calls. quiet/logger configure the warning
|
|
10
|
+
* channel BEFORE in-memory defaults are registered.
|
|
11
|
+
*/
|
|
12
|
+
export interface KronosPartialConfig {
|
|
13
|
+
states?: StateModule[];
|
|
14
|
+
commands?: CommandHandlerDefinition<any, any>[];
|
|
15
|
+
queries?: QueryHandlerDefinition[];
|
|
16
|
+
processors?: EventProcessorModule[];
|
|
17
|
+
quiet?: boolean;
|
|
18
|
+
logger?: WarningLogger;
|
|
19
|
+
/** Stable logical service/application name. Same across replicas. */
|
|
20
|
+
serviceName?: string;
|
|
21
|
+
/** Unique physical runtime instance id. Different per process/pod. */
|
|
22
|
+
instanceId?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Per-stage timeout (ms) for native lifecycle execution (D-77).
|
|
25
|
+
* If a single stage exceeds this, AppImpl emits a warning and continues
|
|
26
|
+
* to the next stage WITHOUT cancelling the slow hooks (warn-then-continue).
|
|
27
|
+
*
|
|
28
|
+
* Default: 5000.
|
|
29
|
+
*/
|
|
30
|
+
stageTimeoutMs?: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Create a new Kronos App.
|
|
34
|
+
*
|
|
35
|
+
* ```typescript
|
|
36
|
+
* const app = await kronos()
|
|
37
|
+
* .states(Course)
|
|
38
|
+
* .commands(createCourseHandler)
|
|
39
|
+
* .start()
|
|
40
|
+
*
|
|
41
|
+
* await app.commandGateway.send(CreateCourse, { courseId: "cs-101", name: "Intro" }, emptyMetadata())
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* Or with a partial config (APP-02):
|
|
45
|
+
*
|
|
46
|
+
* ```typescript
|
|
47
|
+
* const app = await kronos({ states: [Course], commands: [createCourseHandler], quiet: true }).start()
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare function kronos(partial?: KronosPartialConfig): App;
|
|
51
|
+
//# sourceMappingURL=kronos.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kronos.d.ts","sourceRoot":"","sources":["../src/kronos.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,KAAK,EACV,wBAAwB,EACxB,sBAAsB,EACtB,oBAAoB,EACrB,MAAM,sBAAsB,CAAA;AAM7B,OAAO,EAAW,KAAK,GAAG,EAAE,MAAM,UAAU,CAAA;AAE5C,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,eAAe,CAAA;AAGxE;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,WAAW,EAAE,CAAA;IACtB,QAAQ,CAAC,EAAE,wBAAwB,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAA;IAC/C,OAAO,CAAC,EAAE,sBAAsB,EAAE,CAAA;IAClC,UAAU,CAAC,EAAE,oBAAoB,EAAE,CAAA;IACnC,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB,qEAAqE;IACrE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,MAAM,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,GAAG,CAsDzD"}
|
package/dist/kronos.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { createInterceptingCommandBus, createInterceptingQueryBus, createInterceptingEventBus, } from "@kronos-ts/messaging";
|
|
2
|
+
import { AppImpl } from "./app.js";
|
|
3
|
+
import { registerInMemoryDefaults } from "./defaults.js";
|
|
4
|
+
import { createWarningChannel } from "./warnings.js";
|
|
5
|
+
import { Defaults } from "./defaults-handles.js";
|
|
6
|
+
/**
|
|
7
|
+
* Create a new Kronos App.
|
|
8
|
+
*
|
|
9
|
+
* ```typescript
|
|
10
|
+
* const app = await kronos()
|
|
11
|
+
* .states(Course)
|
|
12
|
+
* .commands(createCourseHandler)
|
|
13
|
+
* .start()
|
|
14
|
+
*
|
|
15
|
+
* await app.commandGateway.send(CreateCourse, { courseId: "cs-101", name: "Intro" }, emptyMetadata())
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* Or with a partial config (APP-02):
|
|
19
|
+
*
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const app = await kronos({ states: [Course], commands: [createCourseHandler], quiet: true }).start()
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export function kronos(partial) {
|
|
25
|
+
const warningChannel = createWarningChannel({ quiet: partial?.quiet, logger: partial?.logger });
|
|
26
|
+
const app = new AppImpl({
|
|
27
|
+
warningChannel,
|
|
28
|
+
stageTimeoutMs: partial?.stageTimeoutMs,
|
|
29
|
+
serviceName: partial?.serviceName,
|
|
30
|
+
instanceId: partial?.instanceId,
|
|
31
|
+
});
|
|
32
|
+
// Register in-memory defaults FIRST so user partial-config / fluent calls override them
|
|
33
|
+
// via set/forceSet (setDefault is ifAbsent — first registration wins).
|
|
34
|
+
registerInMemoryDefaults(app);
|
|
35
|
+
// Register framework-default `intercepting` decorators for the 3 buses (DEC-02, D-57).
|
|
36
|
+
// Each closure reads `app._state.{bus}DispatchInterceptors` + `app._state.handlerInterceptors`
|
|
37
|
+
// at decoration time (i.e., during .start()) — extensions and user code populate these
|
|
38
|
+
// arrays before .start() runs, so the snapshot is complete by the time the closure fires.
|
|
39
|
+
// Removable via `removeDecorator(Defaults.{bus}.intercepting)`.
|
|
40
|
+
app._registerFrameworkDefaultDecorator(Defaults.commandBus.intercepting, (inner, _resolved) => {
|
|
41
|
+
const wrapped = createInterceptingCommandBus(inner);
|
|
42
|
+
for (const fn of app._state.commandDispatchInterceptors)
|
|
43
|
+
wrapped.registerDispatchInterceptor(fn);
|
|
44
|
+
for (const fn of app._state.handlerInterceptors)
|
|
45
|
+
wrapped.registerHandlerInterceptor(fn);
|
|
46
|
+
return wrapped;
|
|
47
|
+
});
|
|
48
|
+
app._registerFrameworkDefaultDecorator(Defaults.queryBus.intercepting, (inner, _resolved) => {
|
|
49
|
+
const wrapped = createInterceptingQueryBus(inner);
|
|
50
|
+
for (const fn of app._state.queryDispatchInterceptors)
|
|
51
|
+
wrapped.registerDispatchInterceptor(fn);
|
|
52
|
+
for (const fn of app._state.handlerInterceptors)
|
|
53
|
+
wrapped.registerHandlerInterceptor(fn);
|
|
54
|
+
return wrapped;
|
|
55
|
+
});
|
|
56
|
+
app._registerFrameworkDefaultDecorator(Defaults.eventBus.intercepting, (inner, _resolved) => {
|
|
57
|
+
// EventBus intercepting wrapper takes its dispatch interceptors at construction time;
|
|
58
|
+
// it has no register* methods and no handler interceptor concept (verified
|
|
59
|
+
// packages/messaging/src/intercepting-event-bus.ts — no handlerInterceptors field).
|
|
60
|
+
// Snapshot the array at decoration time; mutations after .start() are blocked
|
|
61
|
+
// by the AppAlreadyStartedError guard on `eventDispatchInterceptor()`.
|
|
62
|
+
return createInterceptingEventBus(inner, [...app._state.eventDispatchInterceptors]);
|
|
63
|
+
});
|
|
64
|
+
if (partial?.states)
|
|
65
|
+
app.states(...partial.states);
|
|
66
|
+
if (partial?.commands)
|
|
67
|
+
app.commands(...partial.commands);
|
|
68
|
+
if (partial?.queries)
|
|
69
|
+
app.queries(...partial.queries);
|
|
70
|
+
if (partial?.processors)
|
|
71
|
+
app.processors(...partial.processors);
|
|
72
|
+
return app;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=kronos.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kronos.js","sourceRoot":"","sources":["../src/kronos.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed lifecycle stages for app-level startup/shutdown hooks (LIF-01).
|
|
3
|
+
*
|
|
4
|
+
* Forward order on `.start()`: connect → warmup → register → processors → serve.
|
|
5
|
+
* Reverse order on `.stop()`: serve → processors → register → warmup → connect.
|
|
6
|
+
*
|
|
7
|
+
* Within a single stage, hooks execute in registration order (no `{stage, order}`
|
|
8
|
+
* tiebreaker — D-70 defers it until a real consumer asks).
|
|
9
|
+
*
|
|
10
|
+
* Closed string union by design (LIF-01). NOT extensible via declaration merging.
|
|
11
|
+
*/
|
|
12
|
+
export type LifecycleStage = "connect" | "register" | "warmup" | "processors" | "serve";
|
|
13
|
+
/**
|
|
14
|
+
* Hook signature for `app.onStart(stage, fn)` / `app.onStop(stage, fn)` (LIF-02, D-69).
|
|
15
|
+
*
|
|
16
|
+
* Bare zero-arg shape. Extensions close over their own state from the enclosing
|
|
17
|
+
* `(app: App) => void` extension scope (see DESIGN.md §12 KronosDB pattern).
|
|
18
|
+
*
|
|
19
|
+
* Why no `Resolved` arg: the Resolved proxy exists for slot-factory composition
|
|
20
|
+
* (Phase 5 D-52); lifecycle hooks are a different concern.
|
|
21
|
+
*
|
|
22
|
+
* Why no `Configuration` arg: matching the legacy `LifecycleHandler(config?: any)`
|
|
23
|
+
* signature would couple this public type to the configurer's `Configuration` —
|
|
24
|
+
* a Phase 8 deletion target.
|
|
25
|
+
*/
|
|
26
|
+
export type LifecycleHook = () => void | Promise<void>;
|
|
27
|
+
//# sourceMappingURL=lifecycle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../src/lifecycle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,YAAY,GAAG,OAAO,CAAA;AAEvF;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export {};
|
|
2
|
+
// Plan 08-03a (D-77): the legacy numeric-phase mapping is deleted. Native
|
|
3
|
+
// AppImpl.start() executes typed-stage hooks directly off
|
|
4
|
+
// AppState.startHooks/stopHooks — no numeric-phase bridge to the legacy
|
|
5
|
+
// LifecycleRegistry. Plan 03b's enhancer-bridge keeps a private inverted copy
|
|
6
|
+
// locally for the D-81 fallback path.
|
|
7
|
+
//# sourceMappingURL=lifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../src/lifecycle.ts"],"names":[],"mappings":";AA4BA,0EAA0E;AAC1E,0DAA0D;AAC1D,wEAAwE;AACxE,8EAA8E;AAC9E,sCAAsC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { KronosComponents } from "./components.js";
|
|
2
|
+
import type { SlotRegistry } from "./slot-registry.js";
|
|
3
|
+
/**
|
|
4
|
+
* Resolved is structurally identical to KronosComponents — the destructured arg
|
|
5
|
+
* passed to factories. We re-export the alias so user code reads `Resolved` not `KronosComponents`.
|
|
6
|
+
*/
|
|
7
|
+
export type Resolved = KronosComponents;
|
|
8
|
+
/**
|
|
9
|
+
* Build a lazy + memoized Resolved Proxy backed by the registry. (D-52.)
|
|
10
|
+
*
|
|
11
|
+
* - Each property access invokes the slot's factory once and memoizes
|
|
12
|
+
* - Factories receive the same proxy as their argument so dependency chains compose
|
|
13
|
+
* - A `resolving` Set detects cycles: if a getter is hit while its slot is mid-resolution,
|
|
14
|
+
* throw CircularSlotDependencyError with the offending chain
|
|
15
|
+
* - try/finally ensures `resolving` is cleaned even after errors so subsequent accesses still work
|
|
16
|
+
*/
|
|
17
|
+
export declare function buildResolved(registry: SlotRegistry): Resolved;
|
|
18
|
+
//# sourceMappingURL=resolved.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolved.d.ts","sourceRoot":"","sources":["../src/resolved.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAY,MAAM,iBAAiB,CAAA;AAEjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEtD;;;GAGG;AACH,MAAM,MAAM,QAAQ,GAAG,gBAAgB,CAAA;AAEvC;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,YAAY,GAAG,QAAQ,CAkC9D"}
|
package/dist/resolved.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { CircularSlotDependencyError, SlotNotRegisteredError } from "./errors.js";
|
|
2
|
+
/**
|
|
3
|
+
* Build a lazy + memoized Resolved Proxy backed by the registry. (D-52.)
|
|
4
|
+
*
|
|
5
|
+
* - Each property access invokes the slot's factory once and memoizes
|
|
6
|
+
* - Factories receive the same proxy as their argument so dependency chains compose
|
|
7
|
+
* - A `resolving` Set detects cycles: if a getter is hit while its slot is mid-resolution,
|
|
8
|
+
* throw CircularSlotDependencyError with the offending chain
|
|
9
|
+
* - try/finally ensures `resolving` is cleaned even after errors so subsequent accesses still work
|
|
10
|
+
*/
|
|
11
|
+
export function buildResolved(registry) {
|
|
12
|
+
const cache = new Map();
|
|
13
|
+
const resolving = new Set();
|
|
14
|
+
const resolvingOrder = [];
|
|
15
|
+
const handler = {
|
|
16
|
+
get(_target, prop) {
|
|
17
|
+
const slot = prop;
|
|
18
|
+
if (cache.has(slot))
|
|
19
|
+
return cache.get(slot);
|
|
20
|
+
if (resolving.has(slot)) {
|
|
21
|
+
throw new CircularSlotDependencyError(slot, [...resolvingOrder, slot]);
|
|
22
|
+
}
|
|
23
|
+
const entry = registry.getEntry(slot);
|
|
24
|
+
if (!entry) {
|
|
25
|
+
throw new SlotNotRegisteredError(slot);
|
|
26
|
+
}
|
|
27
|
+
resolving.add(slot);
|
|
28
|
+
resolvingOrder.push(slot);
|
|
29
|
+
try {
|
|
30
|
+
const value = entry.factory(proxy);
|
|
31
|
+
cache.set(slot, value);
|
|
32
|
+
return value;
|
|
33
|
+
}
|
|
34
|
+
finally {
|
|
35
|
+
resolving.delete(slot);
|
|
36
|
+
resolvingOrder.pop();
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
const proxy = new Proxy({}, handler);
|
|
41
|
+
return proxy;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=resolved.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolved.js","sourceRoot":"","sources":["../src/resolved.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,2BAA2B,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AASjF;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAAC,QAAsB;IAClD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAqB,CAAA;IAC1C,MAAM,SAAS,GAAG,IAAI,GAAG,EAAY,CAAA;IACrC,MAAM,cAAc,GAAe,EAAE,CAAA;IAErC,MAAM,OAAO,GAAyB;QACpC,GAAG,CAAC,OAAO,EAAE,IAAI;YACf,MAAM,IAAI,GAAG,IAAgB,CAAA;YAC7B,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;YAE3C,IAAI,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxB,MAAM,IAAI,2BAA2B,CAAC,IAAI,EAAE,CAAC,GAAG,cAAc,EAAE,IAAI,CAAC,CAAC,CAAA;YACxE,CAAC;YAED,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;YACrC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,IAAI,sBAAsB,CAAC,IAAI,CAAC,CAAA;YACxC,CAAC;YAED,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;YACnB,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACzB,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,KAAiB,CAAC,CAAA;gBAC9C,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;gBACtB,OAAO,KAAK,CAAA;YACd,CAAC;oBAAS,CAAC;gBACT,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;gBACtB,cAAc,CAAC,GAAG,EAAE,CAAA;YACtB,CAAC;QACH,CAAC;KACF,CAAA;IAED,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,EAAE,EAAE,OAAO,CAAa,CAAA;IAChD,OAAO,KAAK,CAAA;AACd,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { KronosComponents, SlotName } from "./components.js";
|
|
2
|
+
/**
|
|
3
|
+
* Optional metadata attached to a slot entry. Today the only field is
|
|
4
|
+
* `inMemory` + `warning` (D-51) — used by Plan 02 to emit startup warnings
|
|
5
|
+
* for any slot still using a flagged in-memory default at .start() time.
|
|
6
|
+
*/
|
|
7
|
+
export interface SlotMeta {
|
|
8
|
+
inMemory?: true;
|
|
9
|
+
warning?: string;
|
|
10
|
+
}
|
|
11
|
+
/** Each slot's resolution callable: a factory that takes the destructured Resolved and returns the component. */
|
|
12
|
+
export type SlotFactory<K extends SlotName> = (resolved: KronosComponents) => KronosComponents[K];
|
|
13
|
+
/** A registered slot entry: normalized factory + optional meta. */
|
|
14
|
+
export interface SlotEntry<K extends SlotName = SlotName> {
|
|
15
|
+
factory: SlotFactory<K>;
|
|
16
|
+
meta?: SlotMeta;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* SlotRegistry — the storage backing the App's three verbs.
|
|
20
|
+
* setDefault: ifAbsent (no-op if occupied)
|
|
21
|
+
* set: warn on double-set
|
|
22
|
+
* forceSet: silent overwrite
|
|
23
|
+
* (DESIGN.md §6, REQUIREMENTS.md SLT-02.)
|
|
24
|
+
*/
|
|
25
|
+
export declare class SlotRegistry {
|
|
26
|
+
private readonly slots;
|
|
27
|
+
setDefault<K extends SlotName>(slot: K, factoryOrInstance: SlotFactory<K> | KronosComponents[K], meta?: SlotMeta): void;
|
|
28
|
+
set<K extends SlotName>(slot: K, factoryOrInstance: SlotFactory<K> | KronosComponents[K]): void;
|
|
29
|
+
forceSet<K extends SlotName>(slot: K, factoryOrInstance: SlotFactory<K> | KronosComponents[K]): void;
|
|
30
|
+
/** @internal — used by buildResolved and by Plan 02's warning emitter. */
|
|
31
|
+
getEntry<K extends SlotName>(slot: K): SlotEntry<K> | undefined;
|
|
32
|
+
/** @internal — used by Plan 02 to iterate registered slots for startup warnings. */
|
|
33
|
+
has(slot: SlotName): boolean;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=slot-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slot-registry.d.ts","sourceRoot":"","sources":["../src/slot-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAEjE;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,EAAE,IAAI,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,iHAAiH;AACjH,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,QAAQ,IAAI,CAAC,QAAQ,EAAE,gBAAgB,KAAK,gBAAgB,CAAC,CAAC,CAAC,CAAA;AAEjG,mEAAmE;AACnE,MAAM,WAAW,SAAS,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ;IACtD,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,CAAA;IACvB,IAAI,CAAC,EAAE,QAAQ,CAAA;CAChB;AAgBD;;;;;;GAMG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiC;IAEvD,UAAU,CAAC,CAAC,SAAS,QAAQ,EAC3B,IAAI,EAAE,CAAC,EACP,iBAAiB,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,EACvD,IAAI,CAAC,EAAE,QAAQ,GACd,IAAI;IAKP,GAAG,CAAC,CAAC,SAAS,QAAQ,EACpB,IAAI,EAAE,CAAC,EACP,iBAAiB,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,GACtD,IAAI;IAeP,QAAQ,CAAC,CAAC,SAAS,QAAQ,EACzB,IAAI,EAAE,CAAC,EACP,iBAAiB,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,GACtD,IAAI;IAIP,0EAA0E;IAC1E,QAAQ,CAAC,CAAC,SAAS,QAAQ,EAAE,IAAI,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS;IAI/D,oFAAoF;IACpF,GAAG,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO;CAG7B"}
|