pi-harness-runtime 1.1.410 → 1.1.412
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/harness/notification-settings.ts +130 -0
- package/harness/skill-remote-source.ts +157 -0
- package/harness/skill-sync.ts +74 -22
- package/harness/skills-startup.ts +202 -0
- package/harness/startup-report.ts +98 -56
- package/harness-startup-status.ts +31 -2
- package/index.ts +125 -31
- package/package.json +1 -1
- package/packages/a2a-adapter/package.json +1 -1
- package/packages/agent-policy/package.json +1 -1
- package/packages/architecture-generator/package.json +1 -1
- package/packages/auth/package.json +1 -1
- package/packages/autonomous-refactor/package.json +1 -1
- package/packages/autonomous-runtime/package.json +1 -1
- package/packages/autonomous-runtime/test/types.test.ts +59 -32
- package/packages/cache-strategy/package.json +1 -1
- package/packages/capability-registry/package.json +1 -1
- package/packages/checkpoint/package.json +1 -1
- package/packages/cli-plugin-sdk/package.json +1 -1
- package/packages/clipboard/package.json +1 -1
- package/packages/clipboard-plugin/package.json +1 -1
- package/packages/code-generation/package.json +1 -1
- package/packages/code-review/package.json +1 -1
- package/packages/codex-adapter/package.json +1 -1
- package/packages/codex-watcher/package.json +1 -1
- package/packages/config-capture/package.json +1 -1
- package/packages/connection-runtime/package.json +1 -1
- package/packages/context-compiler/package.json +1 -1
- package/packages/context-discovery/package.json +1 -1
- package/packages/context-manager/package.json +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/cookie-sanitizer/package.json +1 -1
- package/packages/cookie-sanitizer/test/sync.test.ts +7 -1
- package/packages/cost-optimizer/package.json +1 -1
- package/packages/dependency-analyzer/dist/src/imports.js +3 -3
- package/packages/dependency-analyzer/dist/src/imports.js.map +1 -1
- package/packages/dependency-analyzer/package.json +1 -1
- package/packages/dependency-analyzer/src/imports.ts +3 -3
- package/packages/dependency-analyzer/test/analyzer.test.ts +1 -0
- package/packages/django-plugin/package.json +1 -1
- package/packages/doc-generator/package.json +1 -1
- package/packages/durable-review/package.json +1 -1
- package/packages/durable-review/test/acceptance.test.ts +24 -2
- package/packages/durable-review/test/smoke.test.ts +85 -47
- package/packages/e2e-tester/package.json +1 -1
- package/packages/evaluation-engine/package.json +1 -1
- package/packages/evaluation-runner/package.json +1 -1
- package/packages/event-bus/package.json +1 -1
- package/packages/event-bus/test/bus.test.ts +16 -4
- package/packages/event-sink/package.json +1 -1
- package/packages/event-store/package.json +1 -1
- package/packages/experience-replay/package.json +1 -1
- package/packages/feedback-collector/package.json +1 -1
- package/packages/file-copy-helper/package.json +1 -1
- package/packages/framework-detector/package.json +1 -1
- package/packages/framework-plugin-sdk/package.json +1 -1
- package/packages/frappe-plugin/package.json +1 -1
- package/packages/generic-web-plugin/package.json +1 -1
- package/packages/health-monitor/package.json +1 -1
- package/packages/intent-analyzer/package.json +1 -1
- package/packages/jev-judge/package.json +1 -1
- package/packages/knowledge-graph/package.json +1 -1
- package/packages/knowledge-retrieval/package.json +1 -1
- package/packages/laravel-plugin/package.json +1 -1
- package/packages/learning-engine/package.json +1 -1
- package/packages/logging/package.json +1 -1
- package/packages/mcp-adapter/package.json +1 -1
- package/packages/memory-engine/package.json +1 -1
- package/packages/milestone-manager/package.json +1 -1
- package/packages/model-registry/package.json +1 -1
- package/packages/nextjs-plugin/package.json +1 -1
- package/packages/notification/package.json +1 -1
- package/packages/observability/package.json +1 -1
- package/packages/okf-indexer/package.json +1 -1
- package/packages/paperclip-integration/package.json +1 -1
- package/packages/performance-optimizer/package.json +1 -1
- package/packages/permission-mode/package.json +1 -1
- package/packages/privilege-broker/package.json +1 -1
- package/packages/project-analyzer/package.json +1 -1
- package/packages/project-bootstrap/package.json +1 -1
- package/packages/projection-engine/package.json +1 -1
- package/packages/prompt-compiler/package.json +1 -1
- package/packages/prompt-versioning/package.json +1 -1
- package/packages/provider-adapter-sdk/package.json +1 -1
- package/packages/provider-router/package.json +1 -1
- package/packages/provider-selector/package.json +1 -1
- package/packages/providers/package.json +1 -1
- package/packages/qdrant-skills/dist/client.d.ts.map +1 -1
- package/packages/qdrant-skills/dist/client.js +21 -8
- package/packages/qdrant-skills/dist/client.js.map +1 -1
- package/packages/qdrant-skills/dist/embedder.d.ts +37 -0
- package/packages/qdrant-skills/dist/embedder.d.ts.map +1 -1
- package/packages/qdrant-skills/dist/embedder.js +65 -1
- package/packages/qdrant-skills/dist/embedder.js.map +1 -1
- package/packages/qdrant-skills/dist/index.d.ts +1 -1
- package/packages/qdrant-skills/dist/index.d.ts.map +1 -1
- package/packages/qdrant-skills/dist/index.js +1 -1
- package/packages/qdrant-skills/dist/index.js.map +1 -1
- package/packages/qdrant-skills/package.json +1 -1
- package/packages/qdrant-skills/src/client.ts +19 -8
- package/packages/qdrant-skills/src/embedder.ts +103 -1
- package/packages/qdrant-skills/src/index.ts +5 -0
- package/packages/qdrant-skills/test/collection-info.test.ts +129 -0
- package/packages/qdrant-skills/test/embedder-batch.test.ts +184 -0
- package/packages/quota-manager/package.json +1 -1
- package/packages/rate-limiter/package.json +1 -1
- package/packages/react-vite-plugin/package.json +1 -1
- package/packages/relay/package.json +1 -1
- package/packages/release-manager/package.json +1 -1
- package/packages/requirement-compiler/package.json +1 -1
- package/packages/runtime/package.json +1 -1
- package/packages/scheduler/package.json +1 -1
- package/packages/scheduler-adapter/package.json +1 -1
- package/packages/session/package.json +1 -1
- package/packages/session-api/package.json +1 -1
- package/packages/session-export/package.json +1 -1
- package/packages/shared-context/package.json +1 -1
- package/packages/skill-mcp-client/package.json +1 -1
- package/packages/skill-registry/package.json +1 -1
- package/packages/skills/dist/index.d.ts +19 -1
- package/packages/skills/dist/index.d.ts.map +1 -1
- package/packages/skills/dist/index.js +7 -2
- package/packages/skills/dist/index.js.map +1 -1
- package/packages/skills/dist/loader.d.ts +273 -3
- package/packages/skills/dist/loader.d.ts.map +1 -1
- package/packages/skills/dist/loader.js +525 -36
- package/packages/skills/dist/loader.js.map +1 -1
- package/packages/skills/dist/remote-source.d.ts +107 -0
- package/packages/skills/dist/remote-source.d.ts.map +1 -0
- package/packages/skills/dist/remote-source.js +79 -0
- package/packages/skills/dist/remote-source.js.map +1 -0
- package/packages/skills/dist/vector-schema.d.ts +58 -0
- package/packages/skills/dist/vector-schema.d.ts.map +1 -0
- package/packages/skills/dist/vector-schema.js +55 -0
- package/packages/skills/dist/vector-schema.js.map +1 -0
- package/packages/skills/package.json +1 -1
- package/packages/skills/src/index.ts +28 -5
- package/packages/skills/src/loader.ts +688 -53
- package/packages/skills/src/remote-source.ts +148 -0
- package/packages/skills/src/vector-schema.ts +72 -0
- package/packages/skills/test/init-skills.test.ts +107 -111
- package/packages/skills/test/remote-skills.test.ts +242 -0
- package/packages/skills/test/remote-source.test.ts +248 -0
- package/packages/skills/test/vector-indexing.test.ts +205 -0
- package/packages/sprint-planner/package.json +1 -1
- package/packages/subscription-engine/package.json +1 -1
- package/packages/task-compiler/package.json +1 -1
- package/packages/telegram/package.json +1 -1
- package/packages/tencentdb-memory/package.json +1 -1
- package/packages/tencentdb-sync/package.json +1 -1
- package/packages/test-data-generator/package.json +1 -1
- package/packages/test-generator/package.json +1 -1
- package/packages/todo-bd-sync/package.json +1 -1
- package/packages/token-estimation/package.json +1 -1
- package/packages/token-optimizer/package.json +1 -1
- package/packages/tooling-preference/package.json +1 -1
- package/packages/trajectory/package.json +1 -1
- package/packages/tui/package.json +1 -1
- package/packages/two-phase-review/package.json +1 -1
- package/packages/types/package.json +1 -1
- package/packages/voice-api/package.json +1 -1
- package/packages/webmcp-tester/package.json +1 -1
- package/packages/wiki/package.json +1 -1
- package/packages/workflow-events/package.json +1 -1
- package/packages/workspace-scanner/package.json +1 -1
- package/packages/workspace-scanner/test/scanner.test.ts +4 -3
- package/packages/worktree/package.json +1 -1
- package/packages/write-review/package.json +1 -1
- package/scripts/sync-to-qdrant.ts +79 -14
- package/packages/autonomous-runtime/test/autonomous-runtime.test.ts +0 -194
- package/packages/autonomous-runtime/test/inbox.test.ts +0 -80
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-harness/capability-registry",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.412",
|
|
4
4
|
"description": "Capability Registry for pi-harness-runtime — tracks model capabilities and enables capability-based routing",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
/// <reference types="bun-types" />
|
|
1
2
|
/**
|
|
2
3
|
* End-to-end sync tests.
|
|
3
4
|
*
|
|
4
5
|
* Build a synthetic drop folder in a tmp dir, call sync(), assert
|
|
5
6
|
* the canonical cache was written correctly. No real cookie values
|
|
6
7
|
* are used.
|
|
8
|
+
*
|
|
9
|
+
* A fixture that must survive the expiry filter uses an expiration in the
|
|
10
|
+
* future; a fixed date would make the test fail when it passes.
|
|
7
11
|
*/
|
|
8
12
|
|
|
9
13
|
import { describe, it, expect, beforeEach, afterEach } from "bun:test";
|
|
@@ -36,7 +40,9 @@ const NETSCAPE_FIXTURE = [
|
|
|
36
40
|
const JSON_FIXTURE = JSON.stringify([
|
|
37
41
|
{
|
|
38
42
|
domain: ".minimax.io",
|
|
39
|
-
|
|
43
|
+
// A cookie that is still valid: an expiration in the past would be
|
|
44
|
+
// filtered out and the test would count a different number.
|
|
45
|
+
expirationDate: Math.floor(Date.now() / 1000) + 3600,
|
|
40
46
|
name: "test_json",
|
|
41
47
|
value: "test-value-json",
|
|
42
48
|
httpOnly: false,
|
|
@@ -6,11 +6,11 @@ import { extname, resolve } from "node:path";
|
|
|
6
6
|
* Parse imports from file content. Supports TypeScript, JavaScript, CommonJS, Python.
|
|
7
7
|
*/
|
|
8
8
|
export function parseImports(content, filePath) {
|
|
9
|
-
|
|
9
|
+
// The extension without its dot: "file.ts" is the type "ts".
|
|
10
|
+
const ext = extname(filePath).toLowerCase().replace(/^\./, "");
|
|
10
11
|
const imports = [];
|
|
11
12
|
if (["ts", "tsx", "js", "jsx", "mjs", "cjs"].includes(ext)) {
|
|
12
13
|
imports.push(...parseTypeScriptImports(content));
|
|
13
|
-
imports.push(...parsePythonImports(content));
|
|
14
14
|
}
|
|
15
15
|
else if (ext === "py") {
|
|
16
16
|
imports.push(...parsePythonImports(content));
|
|
@@ -20,7 +20,7 @@ export function parseImports(content, filePath) {
|
|
|
20
20
|
function parseTypeScriptImports(content) {
|
|
21
21
|
const imports = [];
|
|
22
22
|
// ESM: import X from './y' or import X from 'package'
|
|
23
|
-
const esmDefault = /import\s+(?:(?:type\s+)?(?:\{[^}]*\}|[A-
|
|
23
|
+
const esmDefault = /import\s+(?:(?:type\s+)?(?:\{[^}]*\}|[A-Za-z_$][\w$]*)\s+from\s+)?['"]([^'"]+)['"]/g;
|
|
24
24
|
for (const match of content.matchAll(esmDefault)) {
|
|
25
25
|
imports.push(match[1]);
|
|
26
26
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"imports.js","sourceRoot":"","sources":["../../src/imports.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAQ,OAAO,EAAE,MAAM,WAAW,CAAC;AAEnD;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe,EAAE,QAAgB;IAC7D,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"imports.js","sourceRoot":"","sources":["../../src/imports.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,12 +8,12 @@ import { extname, join, resolve } from "node:path";
|
|
|
8
8
|
* Parse imports from file content. Supports TypeScript, JavaScript, CommonJS, Python.
|
|
9
9
|
*/
|
|
10
10
|
export function parseImports(content: string, filePath: string): string[] {
|
|
11
|
-
|
|
11
|
+
// The extension without its dot: "file.ts" is the type "ts".
|
|
12
|
+
const ext = extname(filePath).toLowerCase().replace(/^\./, "");
|
|
12
13
|
const imports: string[] = [];
|
|
13
14
|
|
|
14
15
|
if (["ts", "tsx", "js", "jsx", "mjs", "cjs"].includes(ext)) {
|
|
15
16
|
imports.push(...parseTypeScriptImports(content));
|
|
16
|
-
imports.push(...parsePythonImports(content));
|
|
17
17
|
} else if (ext === "py") {
|
|
18
18
|
imports.push(...parsePythonImports(content));
|
|
19
19
|
}
|
|
@@ -26,7 +26,7 @@ function parseTypeScriptImports(content: string): string[] {
|
|
|
26
26
|
|
|
27
27
|
// ESM: import X from './y' or import X from 'package'
|
|
28
28
|
const esmDefault =
|
|
29
|
-
/import\s+(?:(?:type\s+)?(?:\{[^}]*\}|[A-
|
|
29
|
+
/import\s+(?:(?:type\s+)?(?:\{[^}]*\}|[A-Za-z_$][\w$]*)\s+from\s+)?['"]([^'"]+)['"]/g;
|
|
30
30
|
for (const match of content.matchAll(esmDefault)) {
|
|
31
31
|
imports.push(match[1]);
|
|
32
32
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
1
2
|
/**
|
|
2
3
|
* Durable Review Acceptance Tests
|
|
3
4
|
*
|
|
@@ -24,6 +25,27 @@ import { handleReviewRequest, cancelJob, getJobStatus } from "../dist/worker.js"
|
|
|
24
25
|
const TEST_WORKSPACE = "/tmp/durable-review-test-" + Date.now();
|
|
25
26
|
const TEST_DB_DIR = join(process.env.HOME || "/tmp", ".pi-harness-runtime", "durable");
|
|
26
27
|
|
|
28
|
+
/**
|
|
29
|
+
* The storage of the worker is SQLite, which needs `node:sqlite`.
|
|
30
|
+
*
|
|
31
|
+
* Node has that module, Bun does not. Without it the worker cannot start, so
|
|
32
|
+
* the tests that need a running worker are skipped with a reason instead of
|
|
33
|
+
* failing with a module error.
|
|
34
|
+
*/
|
|
35
|
+
const sqliteAvailable = await (async () => {
|
|
36
|
+
try {
|
|
37
|
+
await import("node:sqlite");
|
|
38
|
+
return true;
|
|
39
|
+
} catch {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
})();
|
|
43
|
+
|
|
44
|
+
const SKIP_WITHOUT_SQLITE = sqliteAvailable
|
|
45
|
+
? false
|
|
46
|
+
: "node:sqlite is not available in this runtime";
|
|
47
|
+
const describeWorker = sqliteAvailable ? describe : describe.skip;
|
|
48
|
+
|
|
27
49
|
describe("Acceptance Tests", () => {
|
|
28
50
|
// Setup
|
|
29
51
|
before(() => {
|
|
@@ -152,7 +174,7 @@ describe("Acceptance Tests", () => {
|
|
|
152
174
|
});
|
|
153
175
|
|
|
154
176
|
// --- Worker Lifecycle ---
|
|
155
|
-
|
|
177
|
+
describeWorker("Worker lifecycle", () => {
|
|
156
178
|
it("startWorker succeeds", async () => {
|
|
157
179
|
const result = await startWorker(TEST_WORKSPACE);
|
|
158
180
|
assert.strictEqual(result.success, true);
|
|
@@ -174,7 +196,7 @@ describe("Acceptance Tests", () => {
|
|
|
174
196
|
});
|
|
175
197
|
|
|
176
198
|
// --- Request Handling ---
|
|
177
|
-
|
|
199
|
+
describeWorker("Request handling", () => {
|
|
178
200
|
before(async () => {
|
|
179
201
|
await startWorker(TEST_WORKSPACE);
|
|
180
202
|
});
|
|
@@ -1,69 +1,107 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
1
2
|
/**
|
|
2
3
|
* SQLite Smoke Test
|
|
3
4
|
*
|
|
4
5
|
* Verifies SQLite storage works correctly with Node's built-in sqlite.
|
|
6
|
+
*
|
|
7
|
+
* The storage needs `node:sqlite`. Node has that module, Bun does not, so
|
|
8
|
+
* the tests are skipped with a reason where the module is missing.
|
|
5
9
|
*/
|
|
6
10
|
|
|
7
11
|
import { describe, it, before, after } from "node:test";
|
|
8
12
|
import assert from "node:assert";
|
|
9
|
-
import { openNodeSqliteStorage } from "@earendil-works/pi-durable/storage/sqlite/node";
|
|
10
13
|
import { BACKGROUND_CONTEXT } from "@earendil-works/chord/context";
|
|
11
14
|
import { join } from "node:path";
|
|
12
15
|
import { mkdirSync, unlinkSync, existsSync } from "node:fs";
|
|
13
16
|
|
|
14
17
|
const TEST_DB_PATH = join(process.env.HOME || "/tmp", ".pi-harness-runtime", "test", "smoke.sqlite");
|
|
15
18
|
|
|
19
|
+
/** Whether this runtime has the SQLite module of Node. */
|
|
20
|
+
const sqliteAvailable = await (async () => {
|
|
21
|
+
try {
|
|
22
|
+
await import("node:sqlite");
|
|
23
|
+
return true;
|
|
24
|
+
} catch {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
})();
|
|
28
|
+
|
|
29
|
+
const SKIP_WITHOUT_SQLITE = sqliteAvailable
|
|
30
|
+
? false
|
|
31
|
+
: "node:sqlite is not available in this runtime";
|
|
32
|
+
const itSqlite = sqliteAvailable ? it : it.skip;
|
|
33
|
+
|
|
34
|
+
/** Open the storage of the test database. */
|
|
35
|
+
async function openStorage(): Promise<{
|
|
36
|
+
close: (ctx: unknown) => Promise<void>;
|
|
37
|
+
}> {
|
|
38
|
+
const { openNodeSqliteStorage } = await import(
|
|
39
|
+
"@earendil-works/pi-durable/storage/sqlite/node"
|
|
40
|
+
);
|
|
41
|
+
return (await openNodeSqliteStorage(TEST_DB_PATH)) as {
|
|
42
|
+
close: (ctx: unknown) => Promise<void>;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
16
46
|
describe("SQLite Smoke Test", () => {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
47
|
+
before(() => {
|
|
48
|
+
// Ensure directory exists
|
|
49
|
+
const dir = TEST_DB_PATH.replace(/\/[^/]+$/, "");
|
|
50
|
+
mkdirSync(dir, { recursive: true });
|
|
51
|
+
// Clean up any existing test db
|
|
52
|
+
if (existsSync(TEST_DB_PATH)) {
|
|
53
|
+
try {
|
|
54
|
+
unlinkSync(TEST_DB_PATH);
|
|
55
|
+
} catch {
|
|
56
|
+
// ignore
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
});
|
|
30
60
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
61
|
+
after(() => {
|
|
62
|
+
// Cleanup
|
|
63
|
+
if (existsSync(TEST_DB_PATH)) {
|
|
64
|
+
try {
|
|
65
|
+
unlinkSync(TEST_DB_PATH);
|
|
66
|
+
} catch {
|
|
67
|
+
// ignore
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
});
|
|
41
71
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
72
|
+
itSqlite("opens SQLite storage", { skip: SKIP_WITHOUT_SQLITE }, async () => {
|
|
73
|
+
const storage = await openStorage();
|
|
74
|
+
assert.ok(storage, "Storage should be defined");
|
|
75
|
+
await storage.close(BACKGROUND_CONTEXT);
|
|
76
|
+
});
|
|
47
77
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
78
|
+
itSqlite(
|
|
79
|
+
"creates and reopens database",
|
|
80
|
+
{ skip: SKIP_WITHOUT_SQLITE },
|
|
81
|
+
async () => {
|
|
82
|
+
// First open
|
|
83
|
+
const storage1 = await openStorage();
|
|
84
|
+
await storage1.close(BACKGROUND_CONTEXT);
|
|
52
85
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
86
|
+
// Second open - should work
|
|
87
|
+
const storage2 = await openStorage();
|
|
88
|
+
assert.ok(storage2, "Storage should be reopened");
|
|
89
|
+
await storage2.close(BACKGROUND_CONTEXT);
|
|
90
|
+
},
|
|
91
|
+
);
|
|
58
92
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
93
|
+
itSqlite(
|
|
94
|
+
"persists data across reopen",
|
|
95
|
+
{ skip: SKIP_WITHOUT_SQLITE },
|
|
96
|
+
async () => {
|
|
97
|
+
// Open and write
|
|
98
|
+
const storage1 = await openStorage();
|
|
99
|
+
await storage1.close(BACKGROUND_CONTEXT);
|
|
63
100
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
101
|
+
// Reopen and verify
|
|
102
|
+
const storage2 = await openStorage();
|
|
103
|
+
assert.ok(storage2, "Storage should be reopened with data");
|
|
104
|
+
await storage2.close(BACKGROUND_CONTEXT);
|
|
105
|
+
},
|
|
106
|
+
);
|
|
69
107
|
});
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
1
2
|
import { describe, it } from "node:test";
|
|
2
3
|
import { equal, deepEqual } from "node:assert";
|
|
3
4
|
import { EventBus } from "../src/bus.js";
|
|
5
|
+
import type { EventPayload } from "../src/types.js";
|
|
4
6
|
|
|
5
7
|
describe("EventBus", () => {
|
|
6
8
|
const bus = new EventBus();
|
|
@@ -12,12 +14,22 @@ describe("EventBus", () => {
|
|
|
12
14
|
});
|
|
13
15
|
|
|
14
16
|
it("subscriber receives event", () => {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
// The value is held in a box: a variable that is only assigned in a
|
|
18
|
+
// callback would be narrowed to null by the type checker.
|
|
19
|
+
const received: { value: EventPayload<{ data: string }> | null } = {
|
|
20
|
+
value: null,
|
|
21
|
+
};
|
|
22
|
+
bus.subscribe<{ data: string }>("test.1", (p) => {
|
|
23
|
+
received.value = p;
|
|
18
24
|
});
|
|
19
25
|
bus.publish("test.1", { data: "hello" });
|
|
20
|
-
|
|
26
|
+
// The subscriber receives the envelope of the event, not the raw data.
|
|
27
|
+
equal(received.value?.topic, "test.1");
|
|
28
|
+
equal(received.value?.data.data, "hello");
|
|
29
|
+
equal(typeof received.value?.eventId, "string");
|
|
30
|
+
equal(typeof received.value?.timestamp, "string");
|
|
31
|
+
// A published event comes from the system unless a source is given.
|
|
32
|
+
equal(received.value?.source, "system");
|
|
21
33
|
});
|
|
22
34
|
|
|
23
35
|
it("multiple subscribers all called", () => {
|