@nwire/forge 0.7.1 → 0.8.17
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/README.md +169 -79
- package/dist/__tests__/action-hooks.test.d.ts +8 -0
- package/dist/__tests__/action-hooks.test.d.ts.map +1 -0
- package/dist/__tests__/action-hooks.test.js +95 -0
- package/dist/__tests__/action-hooks.test.js.map +1 -0
- package/dist/__tests__/actor-workflow-hooks.test.d.ts +8 -0
- package/dist/__tests__/actor-workflow-hooks.test.d.ts.map +1 -0
- package/dist/__tests__/actor-workflow-hooks.test.js +106 -0
- package/dist/__tests__/actor-workflow-hooks.test.js.map +1 -0
- package/dist/__tests__/lifecycle-logging.test.js +4 -2
- package/dist/__tests__/lifecycle-logging.test.js.map +1 -1
- package/dist/__tests__/plugin-app-narrow.test.d.ts +12 -0
- package/dist/__tests__/plugin-app-narrow.test.d.ts.map +1 -0
- package/dist/__tests__/plugin-app-narrow.test.js +77 -0
- package/dist/__tests__/plugin-app-narrow.test.js.map +1 -0
- package/dist/__tests__/plugin-stress.test.d.ts +21 -0
- package/dist/__tests__/plugin-stress.test.d.ts.map +1 -0
- package/dist/__tests__/plugin-stress.test.js +203 -0
- package/dist/__tests__/plugin-stress.test.js.map +1 -0
- package/dist/__tests__/public-marker.test.js +7 -3
- package/dist/__tests__/public-marker.test.js.map +1 -1
- package/dist/actor-store.d.ts +24 -0
- package/dist/actor-store.d.ts.map +1 -1
- package/dist/actor-store.js +29 -0
- package/dist/actor-store.js.map +1 -1
- package/dist/create-app.d.ts +16 -1
- package/dist/create-app.d.ts.map +1 -1
- package/dist/create-app.js +126 -19
- package/dist/create-app.js.map +1 -1
- package/dist/define-action.d.ts +75 -9
- package/dist/define-action.d.ts.map +1 -1
- package/dist/define-action.js +103 -26
- package/dist/define-action.js.map +1 -1
- package/dist/define-actor.d.ts +3 -1
- package/dist/define-actor.d.ts.map +1 -1
- package/dist/define-actor.js +11 -4
- package/dist/define-actor.js.map +1 -1
- package/dist/define-handler.d.ts +39 -3
- package/dist/define-handler.d.ts.map +1 -1
- package/dist/define-handler.js +10 -1
- package/dist/define-handler.js.map +1 -1
- package/dist/define-module.d.ts +3 -0
- package/dist/define-module.d.ts.map +1 -1
- package/dist/define-module.js +3 -0
- package/dist/define-module.js.map +1 -1
- package/dist/define-plugin.d.ts +25 -1
- package/dist/define-plugin.d.ts.map +1 -1
- package/dist/define-plugin.js +100 -14
- package/dist/define-plugin.js.map +1 -1
- package/dist/define-projection.d.ts +3 -1
- package/dist/define-projection.d.ts.map +1 -1
- package/dist/define-projection.js +3 -0
- package/dist/define-projection.js.map +1 -1
- package/dist/define-query.d.ts +69 -13
- package/dist/define-query.d.ts.map +1 -1
- package/dist/define-query.js +48 -17
- package/dist/define-query.js.map +1 -1
- package/dist/define-workflow.d.ts +19 -1
- package/dist/define-workflow.d.ts.map +1 -1
- package/dist/define-workflow.js +4 -0
- package/dist/define-workflow.js.map +1 -1
- package/dist/dev-logger.d.ts.map +1 -1
- package/dist/dev-logger.js +22 -1
- package/dist/dev-logger.js.map +1 -1
- package/dist/event-message.d.ts +9 -2
- package/dist/event-message.d.ts.map +1 -1
- package/dist/event-message.js +10 -3
- package/dist/event-message.js.map +1 -1
- package/dist/framework-events.d.ts +1 -64
- package/dist/framework-events.d.ts.map +1 -1
- package/dist/framework-events.js +3 -0
- package/dist/framework-events.js.map +1 -1
- package/dist/idempotency-store.d.ts +35 -0
- package/dist/idempotency-store.d.ts.map +1 -0
- package/dist/idempotency-store.js +32 -0
- package/dist/idempotency-store.js.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/runtime.d.ts +205 -5
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +518 -48
- package/dist/runtime.js.map +1 -1
- package/package.json +11 -10
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* createApp accepts the narrow `@nwire/app` plugin shape as well as the
|
|
3
|
+
* rich forge `definePlugin`. Verifies the adaptation at the boundary:
|
|
4
|
+
*
|
|
5
|
+
* - `provide(name, lifecycle)` produces a container binding whose value
|
|
6
|
+
* comes from `lifecycle.boot()`.
|
|
7
|
+
* - `boot(fn)` fires during app start.
|
|
8
|
+
* - `shutdown(fn)` fires during app stop.
|
|
9
|
+
* - `lifecycle.shutdown(value)` fires for materialized bindings.
|
|
10
|
+
*/
|
|
11
|
+
import { describe, it, expect } from "vitest";
|
|
12
|
+
import { z } from "zod";
|
|
13
|
+
import { definePlugin as defineAppPlugin } from "@nwire/app";
|
|
14
|
+
import { createApp, defineAction, defineHandler, defineModule } from "../foundation.js";
|
|
15
|
+
const Ping = defineAction({
|
|
16
|
+
name: "test/ping",
|
|
17
|
+
schema: z.object({ n: z.number() }),
|
|
18
|
+
});
|
|
19
|
+
const handler = defineHandler(Ping, async () => undefined);
|
|
20
|
+
const mod = defineModule("test", { actions: [Ping], handlers: [handler] });
|
|
21
|
+
describe("createApp + narrow @nwire/app plugin", () => {
|
|
22
|
+
it("adapts the narrow shape: provide + boot + shutdown all fire", async () => {
|
|
23
|
+
class Conn {
|
|
24
|
+
url;
|
|
25
|
+
constructor(url) {
|
|
26
|
+
this.url = url;
|
|
27
|
+
}
|
|
28
|
+
closed = false;
|
|
29
|
+
}
|
|
30
|
+
const calls = [];
|
|
31
|
+
const plugin = defineAppPlugin("db", ({ provide, boot, shutdown }) => {
|
|
32
|
+
provide("db", {
|
|
33
|
+
boot: () => new Conn("postgres://x"),
|
|
34
|
+
shutdown: (c) => {
|
|
35
|
+
c.closed = true;
|
|
36
|
+
calls.push("binding.shutdown");
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
boot(() => {
|
|
40
|
+
calls.push("plugin.boot");
|
|
41
|
+
});
|
|
42
|
+
shutdown(() => {
|
|
43
|
+
calls.push("plugin.shutdown");
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
const app = createApp({ modules: [mod], plugins: [plugin] });
|
|
47
|
+
await app.start();
|
|
48
|
+
// Force resolution so the binding's shutdown is reached at stop().
|
|
49
|
+
const conn = app.container.resolve("db");
|
|
50
|
+
expect(conn).toBeInstanceOf(Conn);
|
|
51
|
+
expect(conn.url).toBe("postgres://x");
|
|
52
|
+
expect(calls).toContain("plugin.boot");
|
|
53
|
+
await app.stop();
|
|
54
|
+
expect(conn.closed).toBe(true);
|
|
55
|
+
// Plugin shutdown runs BEFORE binding shutdown (matches app-plugin
|
|
56
|
+
// contract: "flush owned work before underlying resources go away").
|
|
57
|
+
expect(calls).toEqual(["plugin.boot", "plugin.shutdown", "binding.shutdown"]);
|
|
58
|
+
});
|
|
59
|
+
it("rich + narrow plugins coexist in the same plugins list", async () => {
|
|
60
|
+
const fired = [];
|
|
61
|
+
const richBoot = (await import("../define-plugin.js")).definePlugin("rich", ({ boot }) => {
|
|
62
|
+
boot(() => {
|
|
63
|
+
fired.push("rich.boot");
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
const narrowBoot = defineAppPlugin("narrow", ({ boot }) => {
|
|
67
|
+
boot(() => {
|
|
68
|
+
fired.push("narrow.boot");
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
const app = createApp({ modules: [mod], plugins: [richBoot, narrowBoot] });
|
|
72
|
+
await app.start();
|
|
73
|
+
await app.stop();
|
|
74
|
+
expect(fired).toEqual(["rich.boot", "narrow.boot"]);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
//# sourceMappingURL=plugin-app-narrow.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-app-narrow.test.js","sourceRoot":"","sources":["../../src/__tests__/plugin-app-narrow.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,IAAI,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAErF,MAAM,IAAI,GAAG,YAAY,CAAC;IACxB,IAAI,EAAE,WAAW;IACjB,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;CACpC,CAAC,CAAC;AACH,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,SAAS,CAAC,CAAC;AAC3D,MAAM,GAAG,GAAG,YAAY,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;AAE3E,QAAQ,CAAC,sCAAsC,EAAE,GAAG,EAAE;IACpD,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;QAC3E,MAAM,IAAI;YACoB;YAA5B,YAA4B,GAAW;gBAAX,QAAG,GAAH,GAAG,CAAQ;YAAG,CAAC;YAC3C,MAAM,GAAG,KAAK,CAAC;SAChB;QAED,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,MAAM,MAAM,GAAG,eAAe,CAAC,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE;YACnE,OAAO,CAAO,IAAI,EAAE;gBAClB,IAAI,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,CAAC,cAAc,CAAC;gBACpC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE;oBACd,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC;oBAChB,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;gBACjC,CAAC;aACF,CAAC,CAAC;YACH,IAAI,CAAC,GAAG,EAAE;gBACR,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAC5B,CAAC,CAAC,CAAC;YACH,QAAQ,CAAC,GAAG,EAAE;gBACZ,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YAChC,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,MAAM,GAAG,GAAG,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC7D,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QAElB,mEAAmE;QACnE,MAAM,IAAI,GAAG,GAAG,CAAC,SAAS,CAAC,OAAO,CAAO,IAAI,CAAC,CAAC;QAC/C,MAAM,CAAC,IAAI,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACtC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;QAEvC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QACjB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/B,mEAAmE;QACnE,qEAAqE;QACrE,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,iBAAiB,EAAE,kBAAkB,CAAC,CAAC,CAAC;IAChF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;QACtE,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,MAAM,QAAQ,GAAG,CAAC,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE;YACpF,IAAI,CAAC,GAAG,EAAE;gBACR,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC1B,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QACH,MAAM,UAAU,GAAG,eAAe,CAAC,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE;YACxD,IAAI,CAAC,GAAG,EAAE;gBACR,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAC5B,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,MAAM,GAAG,GAAG,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE,CAAC,CAAC;QAC3E,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAEjB,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin + module lifecycle stress test.
|
|
3
|
+
*
|
|
4
|
+
* Covers the failure modes that aren't exercised by `plugin.test.ts` /
|
|
5
|
+
* `plugin-closure.test.ts` / `lifecycle-logging.test.ts`:
|
|
6
|
+
*
|
|
7
|
+
* 1. Cross-plugin DI — plugin B reads plugin A's binding in its boot.
|
|
8
|
+
* 2. Slow boot timing — PluginBooted carries a real `durationMs`.
|
|
9
|
+
* 3. Boot failure recovery — A boots, B throws, stop() still cleans A.
|
|
10
|
+
* 4. Shutdown isolation — first plugin's shutdown throws but second still runs;
|
|
11
|
+
* the error surfaces from app.stop().
|
|
12
|
+
* 5. Ordering at scale — 10 plugins boot in registration order, shutdown reverse.
|
|
13
|
+
* 6. Module + plugin mixed — PluginRegistered fires with `kind:"module"` for
|
|
14
|
+
* modules first (topo order) then `kind:"plugin"` for plugins.
|
|
15
|
+
*
|
|
16
|
+
* Style follows `lifecycle-logging.test.ts` — real `createApp`, real
|
|
17
|
+
* `app.start()/stop()`, observe via the runtime's framework event bus
|
|
18
|
+
* (`runtime.frameworkEvents.onFire(...)`) and per-event subscriptions.
|
|
19
|
+
*/
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=plugin-stress.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-stress.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/plugin-stress.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG"}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin + module lifecycle stress test.
|
|
3
|
+
*
|
|
4
|
+
* Covers the failure modes that aren't exercised by `plugin.test.ts` /
|
|
5
|
+
* `plugin-closure.test.ts` / `lifecycle-logging.test.ts`:
|
|
6
|
+
*
|
|
7
|
+
* 1. Cross-plugin DI — plugin B reads plugin A's binding in its boot.
|
|
8
|
+
* 2. Slow boot timing — PluginBooted carries a real `durationMs`.
|
|
9
|
+
* 3. Boot failure recovery — A boots, B throws, stop() still cleans A.
|
|
10
|
+
* 4. Shutdown isolation — first plugin's shutdown throws but second still runs;
|
|
11
|
+
* the error surfaces from app.stop().
|
|
12
|
+
* 5. Ordering at scale — 10 plugins boot in registration order, shutdown reverse.
|
|
13
|
+
* 6. Module + plugin mixed — PluginRegistered fires with `kind:"module"` for
|
|
14
|
+
* modules first (topo order) then `kind:"plugin"` for plugins.
|
|
15
|
+
*
|
|
16
|
+
* Style follows `lifecycle-logging.test.ts` — real `createApp`, real
|
|
17
|
+
* `app.start()/stop()`, observe via the runtime's framework event bus
|
|
18
|
+
* (`runtime.frameworkEvents.onFire(...)`) and per-event subscriptions.
|
|
19
|
+
*/
|
|
20
|
+
import { describe, it, expect } from "vitest";
|
|
21
|
+
import { createApp, defineModule, definePlugin } from "../foundation.js";
|
|
22
|
+
import { PluginRegistered, PluginBooted } from "../framework-events.js";
|
|
23
|
+
import { InMemoryContainer } from "@nwire/container";
|
|
24
|
+
describe("plugin + module lifecycle stress", () => {
|
|
25
|
+
it("cross-plugin DI: plugin B's boot resolves a binding plugin A provided", async () => {
|
|
26
|
+
const pluginA = definePlugin("provider", ({ bind }) => {
|
|
27
|
+
bind("config-service", () => ({ name: "from-A" }));
|
|
28
|
+
});
|
|
29
|
+
const seen = [];
|
|
30
|
+
const pluginB = definePlugin("consumer", {
|
|
31
|
+
boot: (container) => {
|
|
32
|
+
seen.push(container.resolve("config-service"));
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
const app = createApp({
|
|
36
|
+
container: new InMemoryContainer(),
|
|
37
|
+
modules: [],
|
|
38
|
+
plugins: [pluginA, pluginB],
|
|
39
|
+
devLogs: false,
|
|
40
|
+
});
|
|
41
|
+
await app.start();
|
|
42
|
+
await app.stop();
|
|
43
|
+
expect(seen).toHaveLength(1);
|
|
44
|
+
expect(seen[0]).toEqual({ name: "from-A" });
|
|
45
|
+
});
|
|
46
|
+
it("slow boot timing: PluginBooted carries a durationMs >= the sleep", async () => {
|
|
47
|
+
const SLEEP_MS = 150;
|
|
48
|
+
const TOLERANCE_MS = 120;
|
|
49
|
+
const slow = definePlugin("slow-boot", {
|
|
50
|
+
boot: async () => {
|
|
51
|
+
await new Promise((resolve) => setTimeout(resolve, SLEEP_MS));
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
const app = createApp({
|
|
55
|
+
container: new InMemoryContainer(),
|
|
56
|
+
modules: [],
|
|
57
|
+
plugins: [slow],
|
|
58
|
+
devLogs: false,
|
|
59
|
+
});
|
|
60
|
+
const observed = [];
|
|
61
|
+
app.runtime.frameworkEvents.on(PluginBooted, (payload) => {
|
|
62
|
+
observed.push({ name: payload.pluginName, durationMs: payload.durationMs });
|
|
63
|
+
});
|
|
64
|
+
await app.start();
|
|
65
|
+
await app.stop();
|
|
66
|
+
const slowRecord = observed.find((r) => r.name === "slow-boot");
|
|
67
|
+
expect(slowRecord).toBeDefined();
|
|
68
|
+
expect(slowRecord.durationMs).toBeGreaterThanOrEqual(TOLERANCE_MS);
|
|
69
|
+
});
|
|
70
|
+
it("boot failure recovery: B throws, A booted, stop() still cleans up A", async () => {
|
|
71
|
+
const bootErr = new Error("plugin B boot exploded");
|
|
72
|
+
const pluginA = definePlugin("a", {
|
|
73
|
+
boot: () => {
|
|
74
|
+
/* succeeds */
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
const pluginB = definePlugin("b", {
|
|
78
|
+
boot: () => {
|
|
79
|
+
throw bootErr;
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
const pluginC = definePlugin("c", {
|
|
83
|
+
boot: () => {
|
|
84
|
+
/* should never run — B's failure aborts boot */
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
const app = createApp({
|
|
88
|
+
container: new InMemoryContainer(),
|
|
89
|
+
modules: [],
|
|
90
|
+
plugins: [pluginA, pluginB, pluginC],
|
|
91
|
+
devLogs: false,
|
|
92
|
+
});
|
|
93
|
+
const bootedNames = [];
|
|
94
|
+
app.runtime.frameworkEvents.on(PluginBooted, (payload) => {
|
|
95
|
+
bootedNames.push(payload.pluginName);
|
|
96
|
+
});
|
|
97
|
+
const shutdownNames = [];
|
|
98
|
+
// Use the catch-all observer the dev logger / Studio use, so we see
|
|
99
|
+
// every firing regardless of subscriber count.
|
|
100
|
+
app.runtime.frameworkEvents.onFire((rec) => {
|
|
101
|
+
if (rec.eventName === "nwire.plugin.shutdown") {
|
|
102
|
+
const p = rec.payload;
|
|
103
|
+
shutdownNames.push(p.pluginName);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
await expect(app.start()).rejects.toBe(bootErr);
|
|
107
|
+
// A booted before B threw. C should NOT have booted.
|
|
108
|
+
expect(bootedNames).toContain("a");
|
|
109
|
+
expect(bootedNames).not.toContain("c");
|
|
110
|
+
// Now tear the app down — shutdown should still emit PluginShutdown
|
|
111
|
+
// events in reverse declaration order so observers see a clean close.
|
|
112
|
+
await app.stop();
|
|
113
|
+
// A must appear in the shutdown sweep regardless of B's boot failure.
|
|
114
|
+
expect(shutdownNames).toContain("a");
|
|
115
|
+
// Reverse order: C is iterated first, then B, then A. (Their
|
|
116
|
+
// shutdown callbacks are no-ops because none was registered, but
|
|
117
|
+
// the framework still fires the lifecycle events.)
|
|
118
|
+
const aIdx = shutdownNames.indexOf("a");
|
|
119
|
+
const cIdx = shutdownNames.indexOf("c");
|
|
120
|
+
if (cIdx >= 0) {
|
|
121
|
+
// When C appears (framework also fires shutdown events for plugins
|
|
122
|
+
// that never booted), it must come BEFORE A.
|
|
123
|
+
expect(cIdx).toBeLessThan(aIdx);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
it("shutdown isolation: first plugin's shutdown throws, second still runs, error surfaces from stop()", async () => {
|
|
127
|
+
const shutErr = new Error("plugin A shutdown failed");
|
|
128
|
+
const cleanupRan = [];
|
|
129
|
+
const pluginA = definePlugin("a", {
|
|
130
|
+
shutdown: () => {
|
|
131
|
+
cleanupRan.push("a-attempted");
|
|
132
|
+
throw shutErr;
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
const pluginB = definePlugin("b", {
|
|
136
|
+
shutdown: () => {
|
|
137
|
+
cleanupRan.push("b-ran");
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
const app = createApp({
|
|
141
|
+
container: new InMemoryContainer(),
|
|
142
|
+
modules: [],
|
|
143
|
+
plugins: [pluginA, pluginB],
|
|
144
|
+
devLogs: false,
|
|
145
|
+
});
|
|
146
|
+
await app.start();
|
|
147
|
+
// Shutdown order is reverse: B first, then A. B should run cleanly;
|
|
148
|
+
// then A throws. The framework must surface A's error but only AFTER
|
|
149
|
+
// every other shutdown step has run.
|
|
150
|
+
await expect(app.stop()).rejects.toBe(shutErr);
|
|
151
|
+
expect(cleanupRan).toEqual(["b-ran", "a-attempted"]);
|
|
152
|
+
});
|
|
153
|
+
it("ordering at scale: 10 plugins boot in registration order, shutdown reverse", async () => {
|
|
154
|
+
const boots = [];
|
|
155
|
+
const shutdowns = [];
|
|
156
|
+
const plugins = Array.from({ length: 10 }, (_, i) => {
|
|
157
|
+
const name = `p${i}`;
|
|
158
|
+
return definePlugin(name, {
|
|
159
|
+
boot: () => {
|
|
160
|
+
boots.push(name);
|
|
161
|
+
},
|
|
162
|
+
shutdown: () => {
|
|
163
|
+
shutdowns.push(name);
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
const app = createApp({
|
|
168
|
+
container: new InMemoryContainer(),
|
|
169
|
+
modules: [],
|
|
170
|
+
plugins,
|
|
171
|
+
devLogs: false,
|
|
172
|
+
});
|
|
173
|
+
await app.start();
|
|
174
|
+
await app.stop();
|
|
175
|
+
expect(boots).toEqual(["p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8", "p9"]);
|
|
176
|
+
expect(shutdowns).toEqual(["p9", "p8", "p7", "p6", "p5", "p4", "p3", "p2", "p1", "p0"]);
|
|
177
|
+
});
|
|
178
|
+
it("module + plugin mixed: PluginRegistered fires for modules first (topo) then plugins, with correct kind", async () => {
|
|
179
|
+
const moduleA = defineModule("mod-a", {});
|
|
180
|
+
const moduleB = defineModule("mod-b", {});
|
|
181
|
+
const pluginX = definePlugin("plug-x", {});
|
|
182
|
+
const pluginY = definePlugin("plug-y", {});
|
|
183
|
+
const app = createApp({
|
|
184
|
+
container: new InMemoryContainer(),
|
|
185
|
+
modules: [moduleA, moduleB],
|
|
186
|
+
plugins: [pluginX, pluginY],
|
|
187
|
+
devLogs: false,
|
|
188
|
+
});
|
|
189
|
+
const registrations = [];
|
|
190
|
+
app.runtime.frameworkEvents.on(PluginRegistered, (payload) => {
|
|
191
|
+
registrations.push({ pluginName: payload.pluginName, kind: payload.kind });
|
|
192
|
+
});
|
|
193
|
+
await app.start();
|
|
194
|
+
await app.stop();
|
|
195
|
+
expect(registrations).toEqual([
|
|
196
|
+
{ pluginName: "mod-a", kind: "module" },
|
|
197
|
+
{ pluginName: "mod-b", kind: "module" },
|
|
198
|
+
{ pluginName: "plug-x", kind: "plugin" },
|
|
199
|
+
{ pluginName: "plug-y", kind: "plugin" },
|
|
200
|
+
]);
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
//# sourceMappingURL=plugin-stress.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-stress.test.js","sourceRoot":"","sources":["../../src/__tests__/plugin-stress.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -45,10 +45,14 @@ describe(".public() marker", () => {
|
|
|
45
45
|
expect(isPublic(exposed)).toBe(true);
|
|
46
46
|
expect(exposed.name).toBe("audit.on-wash");
|
|
47
47
|
});
|
|
48
|
-
it("$public is non-enumerable (
|
|
48
|
+
it("$public is non-enumerable (own-keys doesn't surface it)", () => {
|
|
49
|
+
// Action is now a callable factory (function), so JSON.stringify on it
|
|
50
|
+
// returns undefined entirely — the relevant invariant is that `$public`
|
|
51
|
+
// is non-enumerable and absent from Object.keys / property iteration.
|
|
49
52
|
const exposed = recordWash.public();
|
|
50
|
-
|
|
51
|
-
|
|
53
|
+
expect(Object.keys(exposed).includes("$public")).toBe(false);
|
|
54
|
+
// Same property must still be accessible by direct read.
|
|
55
|
+
expect(exposed.$public).toBe(true);
|
|
52
56
|
});
|
|
53
57
|
});
|
|
54
58
|
//# sourceMappingURL=public-marker.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-marker.test.js","sourceRoot":"","sources":["../../src/__tests__/public-marker.test.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"public-marker.test.js","sourceRoot":"","sources":["../../src/__tests__/public-marker.test.ts"],"names":[],"mappings":"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"}
|
package/dist/actor-store.d.ts
CHANGED
|
@@ -50,6 +50,19 @@ export interface ActorStore {
|
|
|
50
50
|
* index `activeTimers.fireAt` for efficient querying.
|
|
51
51
|
*/
|
|
52
52
|
listInstances(actorName: string, tenant?: string): Promise<readonly ActorInstance[]>;
|
|
53
|
+
/**
|
|
54
|
+
* Acquire a per-(actor, key, tenant) lock; resolve when the lock is
|
|
55
|
+
* held and return an `unlock` function. The runtime takes the lock
|
|
56
|
+
* around `load → reduce → save` so concurrent dispatches against the
|
|
57
|
+
* same actor key serialize — invariant safety without depending on
|
|
58
|
+
* storage-native locking.
|
|
59
|
+
*
|
|
60
|
+
* Implementations backed by real databases should prefer row-level
|
|
61
|
+
* locking (`SELECT … FOR UPDATE`, Mongo `findOneAndUpdate`, etc.)
|
|
62
|
+
* and treat this method as a no-op; in-memory stores need an explicit
|
|
63
|
+
* per-key Promise chain to avoid last-write-wins under burst load.
|
|
64
|
+
*/
|
|
65
|
+
lockKey?(actorName: string, key: string, tenant?: string): Promise<() => void>;
|
|
53
66
|
}
|
|
54
67
|
/**
|
|
55
68
|
* Process-local in-memory store. Each save deep-clones the instance to prevent
|
|
@@ -57,12 +70,23 @@ export interface ActorStore {
|
|
|
57
70
|
*/
|
|
58
71
|
export declare class InMemoryActorStore implements ActorStore {
|
|
59
72
|
private readonly entries;
|
|
73
|
+
/**
|
|
74
|
+
* Per-(actor, key, tenant) lock chain. Each lock acquisition awaits the
|
|
75
|
+
* tail of the chain and replaces it with its own resolved-on-release
|
|
76
|
+
* Promise. Concurrent dispatches against the same actor key serialize
|
|
77
|
+
* cleanly; different keys (or different actors / tenants) stay
|
|
78
|
+
* independent. Without this, two simultaneous dispatches both load the
|
|
79
|
+
* same pre-state, both compute next state, and the second save wins —
|
|
80
|
+
* the first event's effect vanishes.
|
|
81
|
+
*/
|
|
82
|
+
private readonly lockChain;
|
|
60
83
|
/**
|
|
61
84
|
* Storage key includes tenant first so prefix scans by `(actor, tenant)`
|
|
62
85
|
* are O(matching tenant) — and across-tenant scans (no tenant) are O(N)
|
|
63
86
|
* by intent.
|
|
64
87
|
*/
|
|
65
88
|
private cacheKey;
|
|
89
|
+
lockKey(actorName: string, key: string, tenant?: string): Promise<() => void>;
|
|
66
90
|
load(actorName: string, key: string, tenant?: string): Promise<ActorInstance | null>;
|
|
67
91
|
save(instance: ActorInstance): Promise<void>;
|
|
68
92
|
exists(actorName: string, key: string, tenant?: string): Promise<boolean>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actor-store.d.ts","sourceRoot":"","sources":["../src/actor-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEtD,MAAM,WAAW,aAAa,CAAC,KAAK,GAAG,OAAO;IAC5C,gEAAgE;IAChE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,gEAAgE;IAChE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,yEAAyE;IACzE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,0BAA0B;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,gEAAgE;IAChE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB;;;OAGG;IACH,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;CACnE;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACzB;;;;OAIG;IACH,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IACrF,IAAI,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1E;;;;;;OAMG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,aAAa,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"actor-store.d.ts","sourceRoot":"","sources":["../src/actor-store.ts"],"names":[],"mappings":"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"}
|
package/dist/actor-store.js
CHANGED
|
@@ -15,6 +15,16 @@
|
|
|
15
15
|
*/
|
|
16
16
|
export class InMemoryActorStore {
|
|
17
17
|
entries = new Map();
|
|
18
|
+
/**
|
|
19
|
+
* Per-(actor, key, tenant) lock chain. Each lock acquisition awaits the
|
|
20
|
+
* tail of the chain and replaces it with its own resolved-on-release
|
|
21
|
+
* Promise. Concurrent dispatches against the same actor key serialize
|
|
22
|
+
* cleanly; different keys (or different actors / tenants) stay
|
|
23
|
+
* independent. Without this, two simultaneous dispatches both load the
|
|
24
|
+
* same pre-state, both compute next state, and the second save wins —
|
|
25
|
+
* the first event's effect vanishes.
|
|
26
|
+
*/
|
|
27
|
+
lockChain = new Map();
|
|
18
28
|
/**
|
|
19
29
|
* Storage key includes tenant first so prefix scans by `(actor, tenant)`
|
|
20
30
|
* are O(matching tenant) — and across-tenant scans (no tenant) are O(N)
|
|
@@ -23,6 +33,25 @@ export class InMemoryActorStore {
|
|
|
23
33
|
cacheKey(actorName, key, tenant) {
|
|
24
34
|
return `${tenant}::${actorName}::${key}`;
|
|
25
35
|
}
|
|
36
|
+
async lockKey(actorName, key, tenant = "") {
|
|
37
|
+
const k = this.cacheKey(actorName, key, tenant);
|
|
38
|
+
const prev = this.lockChain.get(k) ?? Promise.resolve();
|
|
39
|
+
let release;
|
|
40
|
+
const next = new Promise((resolve) => {
|
|
41
|
+
release = resolve;
|
|
42
|
+
});
|
|
43
|
+
this.lockChain.set(k, next);
|
|
44
|
+
await prev;
|
|
45
|
+
return () => {
|
|
46
|
+
release();
|
|
47
|
+
// Clean up the chain entry IFF it's still ours — a later
|
|
48
|
+
// acquisition will have already replaced the value. Without this
|
|
49
|
+
// guard, slow chains keep `next` rooted indefinitely.
|
|
50
|
+
if (this.lockChain.get(k) === next) {
|
|
51
|
+
this.lockChain.delete(k);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
26
55
|
async load(actorName, key, tenant = "") {
|
|
27
56
|
const stored = this.entries.get(this.cacheKey(actorName, key, tenant));
|
|
28
57
|
return stored ? this.clone(stored) : null;
|
package/dist/actor-store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actor-store.js","sourceRoot":"","sources":["../src/actor-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"actor-store.js","sourceRoot":"","sources":["../src/actor-store.ts"],"names":[],"mappings":"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"}
|
package/dist/create-app.d.ts
CHANGED
|
@@ -31,6 +31,7 @@ import type { Logger } from "@nwire/logger";
|
|
|
31
31
|
import type { DeadLetterSink } from "@nwire/dead-letter";
|
|
32
32
|
import type { EventBus } from "@nwire/bus";
|
|
33
33
|
import { type PluginDefinition } from "./define-plugin.js";
|
|
34
|
+
import { type AppPluginDefinition } from "@nwire/app";
|
|
34
35
|
export interface TimerSchedulerOptions {
|
|
35
36
|
/** Polling interval in milliseconds. Default: 60_000 (1 minute). */
|
|
36
37
|
readonly intervalMs?: number;
|
|
@@ -45,8 +46,15 @@ export interface CreateAppOptions {
|
|
|
45
46
|
* plugins.
|
|
46
47
|
*
|
|
47
48
|
* Boot order: declaration order. Shutdown order: reverse declaration.
|
|
49
|
+
*
|
|
50
|
+
* Both plugin flavours are accepted:
|
|
51
|
+
* - rich forge `PluginDefinition` (middleware / actorHooks / before /
|
|
52
|
+
* after / closure form);
|
|
53
|
+
* - narrow `@nwire/app` `AppPluginDefinition` (provide / on / boot /
|
|
54
|
+
* shutdown). The narrow shape is adapted to the rich shape at the
|
|
55
|
+
* boundary so consumers don't have to know which is which.
|
|
48
56
|
*/
|
|
49
|
-
readonly plugins?: readonly PluginDefinition[];
|
|
57
|
+
readonly plugins?: readonly (PluginDefinition | AppPluginDefinition)[];
|
|
50
58
|
/**
|
|
51
59
|
* App-level config map — exposed to plugin closures via `PluginContext.config`.
|
|
52
60
|
* Typically loaded from env at boot.
|
|
@@ -104,6 +112,13 @@ export interface App {
|
|
|
104
112
|
readonly $nwireApp: true;
|
|
105
113
|
readonly runtime: Runtime;
|
|
106
114
|
readonly modules: readonly ModuleDefinition[];
|
|
115
|
+
/**
|
|
116
|
+
* Plugins registered into this app. Includes only proper plugins —
|
|
117
|
+
* modules participate in the SAME lifecycle event surface (PluginRegistered
|
|
118
|
+
* etc., with kind:"module") but appear in `modules`, not here. Scan +
|
|
119
|
+
* Studio consume both lists for the Plugins page.
|
|
120
|
+
*/
|
|
121
|
+
readonly plugins: readonly PluginDefinition[];
|
|
107
122
|
readonly container: Container;
|
|
108
123
|
readonly appName: string;
|
|
109
124
|
start(): Promise<void>;
|
package/dist/create-app.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-app.d.ts","sourceRoot":"","sources":["../src/create-app.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAiB,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"create-app.d.ts","sourceRoot":"","sources":["../src/create-app.ts"],"names":[],"mappings":"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"}
|