@digitalpaws/starr 0.0.1
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.rst +75 -0
- package/data/.nfs.811bbb0d.43c34.4 +0 -0
- package/data/.nfs.81ba4cd0.ffff87804.4 +0 -0
- package/data/.nfs.82d127f7.fffff5704.4 +0 -0
- package/data/.nfs.82d127fe.fffff5704.4 +0 -0
- package/data/.nfs.82d159a5.fffff5aa4.4 +0 -0
- package/data/.nfs.82d159aa.fffff5aa4.4 +0 -0
- package/data/.nfs.82d15a9c.fffff5bb4.4 +0 -0
- package/data/.nfs.82d15aa1.fffff5bb4.4 +0 -0
- package/data/.nfs.82d15c65.fffff5c24.4 +0 -0
- package/data/.nfs.82d1852c.fffff5e24.4 +0 -0
- package/data/.nfs.82d18536.fffff5e24.4 +0 -0
- package/data/.nfs.82d18dbe.fffff5e44.4 +0 -0
- package/data/.nfs.82d18dc6.fffff5e44.4 +0 -0
- package/data/.nfs.8309a3f5.fffff82f4.4 +0 -0
- package/data/.nfs.8309a3fe.fffff82f4.4 +0 -0
- package/data/.nfs.8314122e.fffffb044.4 +0 -0
- package/data/.nfs.83141236.fffffb044.4 +0 -0
- package/data/.nfs.833c4fe9.fffffbc34.4 +0 -0
- package/data/.nfs.833c4ff3.fffffbc34.4 +0 -0
- package/data/logs/starr.log +66244 -0
- package/data/starr.db +0 -0
- package/data/starr.db-shm +0 -0
- package/data/starr.db-wal +0 -0
- package/data/starr.jwt +1 -0
- package/data/starr.key +1 -0
- package/dist/auth/auth-service.d.ts +42 -0
- package/dist/auth/auth-service.d.ts.map +1 -0
- package/dist/auth/auth-service.js +226 -0
- package/dist/auth/auth-service.js.map +1 -0
- package/dist/auth/http-server.d.ts +16 -0
- package/dist/auth/http-server.d.ts.map +1 -0
- package/dist/auth/http-server.js +207 -0
- package/dist/auth/http-server.js.map +1 -0
- package/dist/auth/jwt-secret.d.ts +6 -0
- package/dist/auth/jwt-secret.d.ts.map +1 -0
- package/dist/auth/jwt-secret.js +51 -0
- package/dist/auth/jwt-secret.js.map +1 -0
- package/dist/auth/oidc/oidc-flow.d.ts +60 -0
- package/dist/auth/oidc/oidc-flow.d.ts.map +1 -0
- package/dist/auth/oidc/oidc-flow.js +201 -0
- package/dist/auth/oidc/oidc-flow.js.map +1 -0
- package/dist/auth/oidc/oidc-provider-service.d.ts +59 -0
- package/dist/auth/oidc/oidc-provider-service.d.ts.map +1 -0
- package/dist/auth/oidc/oidc-provider-service.js +124 -0
- package/dist/auth/oidc/oidc-provider-service.js.map +1 -0
- package/dist/auth/oidc/user-service.d.ts +67 -0
- package/dist/auth/oidc/user-service.d.ts.map +1 -0
- package/dist/auth/oidc/user-service.js +177 -0
- package/dist/auth/oidc/user-service.js.map +1 -0
- package/dist/auth/rate-limiter.d.ts +31 -0
- package/dist/auth/rate-limiter.d.ts.map +1 -0
- package/dist/auth/rate-limiter.js +70 -0
- package/dist/auth/rate-limiter.js.map +1 -0
- package/dist/config/config-service.d.ts +83 -0
- package/dist/config/config-service.d.ts.map +1 -0
- package/dist/config/config-service.js +309 -0
- package/dist/config/config-service.js.map +1 -0
- package/dist/config/validate.d.ts +12 -0
- package/dist/config/validate.d.ts.map +1 -0
- package/dist/config/validate.js +140 -0
- package/dist/config/validate.js.map +1 -0
- package/dist/content-types/registry.d.ts +75 -0
- package/dist/content-types/registry.d.ts.map +1 -0
- package/dist/content-types/registry.js +171 -0
- package/dist/content-types/registry.js.map +1 -0
- package/dist/datastore/db.d.ts +9 -0
- package/dist/datastore/db.d.ts.map +1 -0
- package/dist/datastore/db.js +27 -0
- package/dist/datastore/db.js.map +1 -0
- package/dist/datastore/encrypt.d.ts +9 -0
- package/dist/datastore/encrypt.d.ts.map +1 -0
- package/dist/datastore/encrypt.js +84 -0
- package/dist/datastore/encrypt.js.map +1 -0
- package/dist/datastore/migrations.d.ts +10 -0
- package/dist/datastore/migrations.d.ts.map +1 -0
- package/dist/datastore/migrations.js +340 -0
- package/dist/datastore/migrations.js.map +1 -0
- package/dist/datastore/storage.d.ts +4 -0
- package/dist/datastore/storage.d.ts.map +1 -0
- package/dist/datastore/storage.js +60 -0
- package/dist/datastore/storage.js.map +1 -0
- package/dist/events/event-bus.d.ts +15 -0
- package/dist/events/event-bus.d.ts.map +1 -0
- package/dist/events/event-bus.js +140 -0
- package/dist/events/event-bus.js.map +1 -0
- package/dist/events/spine.d.ts +31 -0
- package/dist/events/spine.d.ts.map +1 -0
- package/dist/events/spine.js +68 -0
- package/dist/events/spine.js.map +1 -0
- package/dist/events/trace.d.ts +24 -0
- package/dist/events/trace.d.ts.map +1 -0
- package/dist/events/trace.js +33 -0
- package/dist/events/trace.js.map +1 -0
- package/dist/host.d.ts +65 -0
- package/dist/host.d.ts.map +1 -0
- package/dist/host.js +94 -0
- package/dist/host.js.map +1 -0
- package/dist/library/importer.d.ts +29 -0
- package/dist/library/importer.d.ts.map +1 -0
- package/dist/library/importer.js +145 -0
- package/dist/library/importer.js.map +1 -0
- package/dist/library/library-cache.d.ts +46 -0
- package/dist/library/library-cache.d.ts.map +1 -0
- package/dist/library/library-cache.js +152 -0
- package/dist/library/library-cache.js.map +1 -0
- package/dist/library/library-config.d.ts +12 -0
- package/dist/library/library-config.d.ts.map +1 -0
- package/dist/library/library-config.js +10 -0
- package/dist/library/library-config.js.map +1 -0
- package/dist/library/library-scanner.d.ts +62 -0
- package/dist/library/library-scanner.d.ts.map +1 -0
- package/dist/library/library-scanner.js +336 -0
- package/dist/library/library-scanner.js.map +1 -0
- package/dist/library/library-service.d.ts +65 -0
- package/dist/library/library-service.d.ts.map +1 -0
- package/dist/library/library-service.js +197 -0
- package/dist/library/library-service.js.map +1 -0
- package/dist/library/metadata-matcher.d.ts +56 -0
- package/dist/library/metadata-matcher.d.ts.map +1 -0
- package/dist/library/metadata-matcher.js +207 -0
- package/dist/library/metadata-matcher.js.map +1 -0
- package/dist/library/naming.d.ts +8 -0
- package/dist/library/naming.d.ts.map +1 -0
- package/dist/library/naming.js +47 -0
- package/dist/library/naming.js.map +1 -0
- package/dist/library/scan-controller.d.ts +95 -0
- package/dist/library/scan-controller.d.ts.map +1 -0
- package/dist/library/scan-controller.js +379 -0
- package/dist/library/scan-controller.js.map +1 -0
- package/dist/library/source-resolver.d.ts +17 -0
- package/dist/library/source-resolver.d.ts.map +1 -0
- package/dist/library/source-resolver.js +75 -0
- package/dist/library/source-resolver.js.map +1 -0
- package/dist/logging/logger.d.ts +3 -0
- package/dist/logging/logger.d.ts.map +1 -0
- package/dist/logging/logger.js +107 -0
- package/dist/logging/logger.js.map +1 -0
- package/dist/main.d.ts +36 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +229 -0
- package/dist/main.js.map +1 -0
- package/dist/plugins/context.d.ts +10 -0
- package/dist/plugins/context.d.ts.map +1 -0
- package/dist/plugins/context.js +110 -0
- package/dist/plugins/context.js.map +1 -0
- package/dist/plugins/discovery.d.ts +2 -0
- package/dist/plugins/discovery.d.ts.map +1 -0
- package/dist/plugins/discovery.js +32 -0
- package/dist/plugins/discovery.js.map +1 -0
- package/dist/plugins/loader.d.ts +9 -0
- package/dist/plugins/loader.d.ts.map +1 -0
- package/dist/plugins/loader.js +245 -0
- package/dist/plugins/loader.js.map +1 -0
- package/dist/state/request-intake.d.ts +26 -0
- package/dist/state/request-intake.d.ts.map +1 -0
- package/dist/state/request-intake.js +74 -0
- package/dist/state/request-intake.js.map +1 -0
- package/dist/state/state-store.d.ts +146 -0
- package/dist/state/state-store.d.ts.map +1 -0
- package/dist/state/state-store.js +465 -0
- package/dist/state/state-store.js.map +1 -0
- package/dist/state/trace-store.d.ts +12 -0
- package/dist/state/trace-store.d.ts.map +1 -0
- package/dist/state/trace-store.js +24 -0
- package/dist/state/trace-store.js.map +1 -0
- package/dist/types/plugin.d.ts +93 -0
- package/dist/types/plugin.d.ts.map +1 -0
- package/dist/types/plugin.js +4 -0
- package/dist/types/plugin.js.map +1 -0
- package/dist/web/index.d.ts +10 -0
- package/dist/web/index.d.ts.map +1 -0
- package/dist/web/index.js +153 -0
- package/dist/web/index.js.map +1 -0
- package/dist/web/routes/activity.d.ts +6 -0
- package/dist/web/routes/activity.d.ts.map +1 -0
- package/dist/web/routes/activity.js +31 -0
- package/dist/web/routes/activity.js.map +1 -0
- package/dist/web/routes/auth.d.ts +6 -0
- package/dist/web/routes/auth.d.ts.map +1 -0
- package/dist/web/routes/auth.js +142 -0
- package/dist/web/routes/auth.js.map +1 -0
- package/dist/web/routes/config.d.ts +7 -0
- package/dist/web/routes/config.d.ts.map +1 -0
- package/dist/web/routes/config.js +204 -0
- package/dist/web/routes/config.js.map +1 -0
- package/dist/web/routes/content-types.d.ts +6 -0
- package/dist/web/routes/content-types.d.ts.map +1 -0
- package/dist/web/routes/content-types.js +29 -0
- package/dist/web/routes/content-types.js.map +1 -0
- package/dist/web/routes/discovery.d.ts +6 -0
- package/dist/web/routes/discovery.d.ts.map +1 -0
- package/dist/web/routes/discovery.js +111 -0
- package/dist/web/routes/discovery.js.map +1 -0
- package/dist/web/routes/library-import.d.ts +6 -0
- package/dist/web/routes/library-import.d.ts.map +1 -0
- package/dist/web/routes/library-import.js +120 -0
- package/dist/web/routes/library-import.js.map +1 -0
- package/dist/web/routes/library-management.d.ts +6 -0
- package/dist/web/routes/library-management.d.ts.map +1 -0
- package/dist/web/routes/library-management.js +120 -0
- package/dist/web/routes/library-management.js.map +1 -0
- package/dist/web/routes/library.d.ts +6 -0
- package/dist/web/routes/library.d.ts.map +1 -0
- package/dist/web/routes/library.js +28 -0
- package/dist/web/routes/library.js.map +1 -0
- package/dist/web/routes/oidc.d.ts +9 -0
- package/dist/web/routes/oidc.d.ts.map +1 -0
- package/dist/web/routes/oidc.js +203 -0
- package/dist/web/routes/oidc.js.map +1 -0
- package/dist/web/routes/requests.d.ts +6 -0
- package/dist/web/routes/requests.d.ts.map +1 -0
- package/dist/web/routes/requests.js +183 -0
- package/dist/web/routes/requests.js.map +1 -0
- package/dist/web/routes/sse.d.ts +6 -0
- package/dist/web/routes/sse.d.ts.map +1 -0
- package/dist/web/routes/sse.js +54 -0
- package/dist/web/routes/sse.js.map +1 -0
- package/package.json +33 -0
- package/package.json.license +2 -0
- package/src/auth/auth-service.ts +333 -0
- package/src/auth/http-server.ts +249 -0
- package/src/auth/jwt-secret.ts +65 -0
- package/src/auth/oidc/oidc-flow.ts +266 -0
- package/src/auth/oidc/oidc-provider-service.ts +174 -0
- package/src/auth/oidc/user-service.ts +227 -0
- package/src/auth/rate-limiter.ts +85 -0
- package/src/config/config-service.ts +434 -0
- package/src/config/validate.ts +153 -0
- package/src/content-types/registry.ts +194 -0
- package/src/datastore/db.ts +38 -0
- package/src/datastore/encrypt.ts +107 -0
- package/src/datastore/migrations.ts +367 -0
- package/src/datastore/storage.ts +83 -0
- package/src/events/event-bus.ts +180 -0
- package/src/events/spine.ts +87 -0
- package/src/events/trace.ts +38 -0
- package/src/host.ts +130 -0
- package/src/library/importer.ts +174 -0
- package/src/library/library-cache.ts +212 -0
- package/src/library/library-config.ts +22 -0
- package/src/library/library-scanner.ts +404 -0
- package/src/library/library-service.ts +282 -0
- package/src/library/metadata-matcher.ts +285 -0
- package/src/library/naming.ts +59 -0
- package/src/library/scan-controller.ts +490 -0
- package/src/library/source-resolver.ts +92 -0
- package/src/logging/logger.ts +115 -0
- package/src/main.ts +364 -0
- package/src/plugins/context.ts +138 -0
- package/src/plugins/discovery.ts +29 -0
- package/src/plugins/loader.ts +309 -0
- package/src/state/request-intake.ts +101 -0
- package/src/state/state-store.ts +621 -0
- package/src/state/trace-store.ts +27 -0
- package/src/types/plugin.ts +110 -0
- package/src/web/index.ts +182 -0
- package/src/web/routes/activity.ts +41 -0
- package/src/web/routes/auth.ts +170 -0
- package/src/web/routes/config.ts +282 -0
- package/src/web/routes/content-types.ts +42 -0
- package/src/web/routes/discovery.ts +156 -0
- package/src/web/routes/library-import.ts +196 -0
- package/src/web/routes/library-management.ts +140 -0
- package/src/web/routes/library.ts +46 -0
- package/src/web/routes/oidc.ts +260 -0
- package/src/web/routes/requests.ts +250 -0
- package/src/web/routes/sse.ts +92 -0
- package/tests/auth.test.ts +510 -0
- package/tests/config-route.test.ts +345 -0
- package/tests/config.test.ts +612 -0
- package/tests/content-types.test.ts +376 -0
- package/tests/datastore.test.ts +345 -0
- package/tests/e2e.test.ts +430 -0
- package/tests/event-bus.test.ts +925 -0
- package/tests/host.test.ts +449 -0
- package/tests/library-cache.test.ts +171 -0
- package/tests/library-scanner.test.ts +177 -0
- package/tests/library.test.ts +210 -0
- package/tests/loader-context.test.ts +644 -0
- package/tests/logger-jsonl.test.ts +154 -0
- package/tests/metadata-matcher.test.ts +198 -0
- package/tests/oidc.test.ts +218 -0
- package/tests/scan-controller.test.ts +328 -0
- package/tests/source-resolver.test.ts +100 -0
- package/tests/starr-video-integration.test.ts +153 -0
- package/tests/state-store.test.ts +700 -0
- package/tests/trace-history.test.ts +356 -0
- package/tsconfig.json +8 -0
- package/tsconfig.json.license +2 -0
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
// SPDX-License-Identifier: 0BSD
|
|
2
|
+
// SPDX-FileCopyrightText: 2025 Digi <digitalpaws@proton.me>
|
|
3
|
+
import { readFile } from "node:fs/promises";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { pathToFileURL } from "node:url";
|
|
6
|
+
import { createContext } from "./context.js";
|
|
7
|
+
import { discoverPluginDirs } from "./discovery.js";
|
|
8
|
+
function withTimeout(promise, ms, label) {
|
|
9
|
+
return Promise.race([
|
|
10
|
+
promise,
|
|
11
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error(`${label} timed out after ${ms}ms`)), ms)),
|
|
12
|
+
]);
|
|
13
|
+
}
|
|
14
|
+
const pluginRegistry = new Map();
|
|
15
|
+
export async function loadPlugins(starr) {
|
|
16
|
+
const dirs = await discoverPluginDirs(starr.options.pluginsDir);
|
|
17
|
+
starr.logger.info("discovered plugins", {
|
|
18
|
+
count: dirs.length,
|
|
19
|
+
dirs: dirs.map((d) => path.basename(d)),
|
|
20
|
+
});
|
|
21
|
+
const db = starr.getDatabase();
|
|
22
|
+
if (!db)
|
|
23
|
+
throw new Error("datastore not initialized; call openDatastore first");
|
|
24
|
+
// ── Pass 1: Discover plugin IDs ──────────────────────────
|
|
25
|
+
// Trial registration to get canonical plugin IDs before querying instances.
|
|
26
|
+
const pluginIdMap = new Map();
|
|
27
|
+
for (const dir of dirs) {
|
|
28
|
+
let pkg;
|
|
29
|
+
try {
|
|
30
|
+
const pkgRaw = await readFile(path.join(dir, "package.json"), "utf8");
|
|
31
|
+
pkg = JSON.parse(pkgRaw);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
starr.logger.warn("skipping dir: no package.json", { dir });
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const entryUrl = pathToFileURL(path.resolve(dir, pkg.main)).href;
|
|
38
|
+
// Trial context (no real config service)
|
|
39
|
+
const trialCtx = createContext(starr, dir, db, undefined);
|
|
40
|
+
try {
|
|
41
|
+
const mod = await import(entryUrl);
|
|
42
|
+
const register = mod.default;
|
|
43
|
+
if (typeof register !== "function") {
|
|
44
|
+
starr.logger.warn("skipping dir: no default export function", { dir });
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
await register(trialCtx);
|
|
48
|
+
const meta = trialCtx.getMeta();
|
|
49
|
+
if (meta) {
|
|
50
|
+
pluginIdMap.set(meta.id, { dir, entryUrl });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
starr.logger.warn("trial registration failed for dir (will retry with real instances)", { dir, error: String(err) });
|
|
55
|
+
// Guess pluginId from directory basename
|
|
56
|
+
const guessedId = path.basename(dir);
|
|
57
|
+
pluginIdMap.set(guessedId, { dir, entryUrl });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// ── Clean up trial registrations — roll back any content types ──
|
|
61
|
+
// that were registered during Pass 1, so Pass 2 can register them
|
|
62
|
+
// with the real context without triggering duplicate errors.
|
|
63
|
+
for (const pluginId of pluginIdMap.keys()) {
|
|
64
|
+
starr.contentTypeRegistry.rollbackPlugin(pluginId);
|
|
65
|
+
}
|
|
66
|
+
// ── Pass 2: Load instances ───────────────────────────────
|
|
67
|
+
const seenIds = new Set();
|
|
68
|
+
const lifecycles = [];
|
|
69
|
+
for (const [pluginId, info] of pluginIdMap) {
|
|
70
|
+
// Get instance IDs from DB (or "default" if none)
|
|
71
|
+
const instanceRows = db
|
|
72
|
+
.prepare("SELECT DISTINCT instance_id FROM plugin_config WHERE plugin_id = ?")
|
|
73
|
+
.all(pluginId);
|
|
74
|
+
const instanceIds = instanceRows.length > 0
|
|
75
|
+
? instanceRows.map(r => r.instance_id)
|
|
76
|
+
: ["default"];
|
|
77
|
+
for (const instanceId of instanceIds) {
|
|
78
|
+
let ctx;
|
|
79
|
+
try {
|
|
80
|
+
ctx = createContext(starr, info.dir, db, starr.configService ?? undefined, instanceId);
|
|
81
|
+
const mod = await import(info.entryUrl);
|
|
82
|
+
const register = mod.default;
|
|
83
|
+
if (typeof register !== "function")
|
|
84
|
+
throw new Error("default export is not a function");
|
|
85
|
+
const lifecycle = (await register(ctx)) ?? {};
|
|
86
|
+
const meta = ctx.getMeta();
|
|
87
|
+
if (!meta)
|
|
88
|
+
throw new Error("register did not call ctx.define");
|
|
89
|
+
const fullInstanceId = `${meta.id}::${instanceId}`;
|
|
90
|
+
if (seenIds.has(fullInstanceId)) {
|
|
91
|
+
throw new Error(`duplicate instance: ${fullInstanceId}`);
|
|
92
|
+
}
|
|
93
|
+
seenIds.add(fullInstanceId);
|
|
94
|
+
const runtime = {
|
|
95
|
+
meta: { ...meta, id: fullInstanceId },
|
|
96
|
+
lifecycle,
|
|
97
|
+
startOrder: -1,
|
|
98
|
+
};
|
|
99
|
+
lifecycles.push(runtime);
|
|
100
|
+
pluginRegistry.set(fullInstanceId, { dir: info.dir, ctx: ctx, runtime });
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
starr.logger.error("instance registration failed", {
|
|
104
|
+
pluginId, instanceId, error: String(err),
|
|
105
|
+
});
|
|
106
|
+
if (ctx) {
|
|
107
|
+
ctx.unsubscribeAll();
|
|
108
|
+
ctx.deleteAllStorage().catch(e => starr.logger.error("storage rollback failed", { pluginId, instanceId, error: String(e) }));
|
|
109
|
+
const meta = ctx.getMeta();
|
|
110
|
+
if (meta) {
|
|
111
|
+
starr.contentTypeRegistry.rollbackPlugin(meta.id);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// Start pass
|
|
118
|
+
let order = 0;
|
|
119
|
+
for (const runtime of lifecycles) {
|
|
120
|
+
if (runtime.lifecycle.start) {
|
|
121
|
+
try {
|
|
122
|
+
await withTimeout(Promise.resolve(runtime.lifecycle.start()), 30_000, `start(${runtime.meta.id})`);
|
|
123
|
+
runtime.startOrder = order++;
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
starr.logger.error("plugin start failed", {
|
|
127
|
+
id: runtime.meta.id,
|
|
128
|
+
error: String(err),
|
|
129
|
+
});
|
|
130
|
+
runtime.startOrder = -1;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
runtime.startOrder = order++;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
starr.setRuntimes(lifecycles);
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Reload a single plugin in isolation: stop → unregister → re-import → start.
|
|
141
|
+
* In multi-instance mode, all instances of the plugin are reloaded.
|
|
142
|
+
*/
|
|
143
|
+
export async function reloadPlugin(starr, pluginId) {
|
|
144
|
+
// Find all instances matching this pluginId (pluginId::instanceId or plain pluginId)
|
|
145
|
+
const records = [];
|
|
146
|
+
for (const [fullId, record] of pluginRegistry) {
|
|
147
|
+
if (fullId === pluginId || fullId.startsWith(`${pluginId}::`)) {
|
|
148
|
+
records.push({ fullId, record });
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (records.length === 0) {
|
|
152
|
+
starr.logger.warn("reload requested for unknown plugin", { pluginId });
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
starr.logger.info("reloading plugin instances", { pluginId, count: records.length });
|
|
156
|
+
// 1. Stop all instances
|
|
157
|
+
for (const { fullId, record } of records) {
|
|
158
|
+
if (record.runtime.lifecycle.stop) {
|
|
159
|
+
try {
|
|
160
|
+
await withTimeout(Promise.resolve(record.runtime.lifecycle.stop()), 10_000, `reload-stop(${fullId})`);
|
|
161
|
+
}
|
|
162
|
+
catch (err) {
|
|
163
|
+
starr.logger.error("plugin stop failed during reload", {
|
|
164
|
+
pluginId: fullId,
|
|
165
|
+
error: String(err),
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
record.ctx.unsubscribeAll();
|
|
170
|
+
}
|
|
171
|
+
// 2. Remove from runtimes list
|
|
172
|
+
const runtimes = [...starr.getRuntimes()].filter((r) => !records.some(({ fullId }) => r.meta.id === fullId));
|
|
173
|
+
starr.setRuntimes(runtimes);
|
|
174
|
+
// 3. For each instance, re-import and start
|
|
175
|
+
for (const { fullId, record } of records) {
|
|
176
|
+
const pkgRaw = await readFile(path.join(record.dir, "package.json"), "utf8");
|
|
177
|
+
const pkg = JSON.parse(pkgRaw);
|
|
178
|
+
const entryUrl = pathToFileURL(path.resolve(record.dir, pkg.main)).href;
|
|
179
|
+
const cacheBustUrl = `${entryUrl}?reload=${Date.now()}`;
|
|
180
|
+
try {
|
|
181
|
+
const mod = await import(cacheBustUrl);
|
|
182
|
+
const register = mod.default;
|
|
183
|
+
if (typeof register !== "function") {
|
|
184
|
+
throw new Error("default export is not a function");
|
|
185
|
+
}
|
|
186
|
+
const db = starr.getDatabase();
|
|
187
|
+
if (!db)
|
|
188
|
+
throw new Error("datastore not available");
|
|
189
|
+
// Extract instanceId from fullId (pluginId::instanceId)
|
|
190
|
+
const instanceId = fullId.includes("::") ? fullId.split("::")[1] : "default";
|
|
191
|
+
const newCtx = createContext(starr, record.dir, db, starr.configService ?? undefined, instanceId);
|
|
192
|
+
const lifecycle = (await register(newCtx)) ?? {};
|
|
193
|
+
const meta = newCtx.getMeta();
|
|
194
|
+
if (!meta)
|
|
195
|
+
throw new Error("register did not call ctx.define");
|
|
196
|
+
const startOrder = runtimes.length;
|
|
197
|
+
if (lifecycle.start) {
|
|
198
|
+
try {
|
|
199
|
+
await withTimeout(Promise.resolve(lifecycle.start()), 30_000, `reload-start(${fullId})`);
|
|
200
|
+
}
|
|
201
|
+
catch (err) {
|
|
202
|
+
starr.logger.error("plugin start failed during reload", {
|
|
203
|
+
pluginId: fullId,
|
|
204
|
+
error: String(err),
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
const newRuntime = { meta: { ...meta, id: fullId }, lifecycle, startOrder };
|
|
209
|
+
pluginRegistry.set(fullId, {
|
|
210
|
+
dir: record.dir,
|
|
211
|
+
ctx: newCtx,
|
|
212
|
+
runtime: newRuntime,
|
|
213
|
+
});
|
|
214
|
+
runtimes.push(newRuntime);
|
|
215
|
+
starr.logger.info("plugin instance reloaded", { pluginId: fullId });
|
|
216
|
+
}
|
|
217
|
+
catch (err) {
|
|
218
|
+
starr.logger.error("plugin instance reload failed", {
|
|
219
|
+
pluginId: fullId,
|
|
220
|
+
error: String(err),
|
|
221
|
+
});
|
|
222
|
+
pluginRegistry.delete(fullId);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
starr.setRuntimes(runtimes);
|
|
226
|
+
}
|
|
227
|
+
export async function stopPlugins(starr) {
|
|
228
|
+
const runtimes = [...starr.getRuntimes()]
|
|
229
|
+
.filter((r) => r.startOrder >= 0)
|
|
230
|
+
.sort((a, b) => b.startOrder - a.startOrder);
|
|
231
|
+
for (const runtime of runtimes) {
|
|
232
|
+
if (runtime.lifecycle.stop) {
|
|
233
|
+
try {
|
|
234
|
+
await withTimeout(Promise.resolve(runtime.lifecycle.stop()), 10_000, `stop(${runtime.meta.id})`);
|
|
235
|
+
}
|
|
236
|
+
catch (err) {
|
|
237
|
+
starr.logger.error("plugin stop failed", {
|
|
238
|
+
id: runtime.meta.id,
|
|
239
|
+
error: String(err),
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/plugins/loader.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,4DAA4D;AAE5D,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAGpD,SAAS,WAAW,CAClB,OAAmB,EACnB,EAAU,EACV,KAAa;IAEb,OAAO,OAAO,CAAC,IAAI,CAAC;QAClB,OAAO;QACP,IAAI,OAAO,CAAI,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAC3B,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,GAAG,KAAK,oBAAoB,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAC5E;KACF,CAAC,CAAC;AACL,CAAC;AAUD,MAAM,cAAc,GAAG,IAAI,GAAG,EAAwB,CAAC;AAEvD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,KAAY;IAC5C,MAAM,IAAI,GAAG,MAAM,kBAAkB,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAChE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,oBAAoB,EAAE;QACtC,KAAK,EAAE,IAAI,CAAC,MAAM;QAClB,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;KACxC,CAAC,CAAC;IAEH,MAAM,EAAE,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAC/B,IAAI,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IAEhF,4DAA4D;IAC5D,4EAA4E;IAC5E,MAAM,WAAW,GAAG,IAAI,GAAG,EAA6C,CAAC;IAEzE,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAqB,CAAC;QAC1B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAAC;YACtE,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAqB,CAAC;QAC/C,CAAC;QAAC,MAAM,CAAC;YACP,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,+BAA+B,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;YAC5D,SAAS;QACX,CAAC;QACD,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;QAEjE,yCAAyC;QACzC,MAAM,QAAQ,GAAG,aAAa,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,SAAS,CAAC,CAAC;QAC1D,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;YACnC,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAqB,CAAC;YAC3C,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE,CAAC;gBACnC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,0CAA0C,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;gBACvE,SAAS;YACX,CAAC;YACD,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACzB,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC;YAChC,IAAI,IAAI,EAAE,CAAC;gBACT,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,oEAAoE,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACrH,yCAAyC;YACzC,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;YACrC,WAAW,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IAED,mEAAmE;IACnE,kEAAkE;IAClE,6DAA6D;IAC7D,KAAK,MAAM,QAAQ,IAAI,WAAW,CAAC,IAAI,EAAE,EAAE,CAAC;QAC1C,KAAK,CAAC,mBAAmB,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;IACrD,CAAC;IAED,4DAA4D;IAC5D,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,UAAU,GAAoB,EAAE,CAAC;IAEvC,KAAK,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,WAAW,EAAE,CAAC;QAC3C,kDAAkD;QAClD,MAAM,YAAY,GAAG,EAAE;aACpB,OAAO,CAAC,oEAAoE,CAAC;aAC7E,GAAG,CAAC,QAAQ,CAAmC,CAAC;QACnD,MAAM,WAAW,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC;YACzC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;YACtC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAEhB,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;YACrC,IAAI,GAAiD,CAAC;YACtD,IAAI,CAAC;gBACH,GAAG,GAAG,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,KAAK,CAAC,aAAa,IAAI,SAAS,EAAE,UAAU,CAAC,CAAC;gBACvF,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACxC,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAqB,CAAC;gBAC3C,IAAI,OAAO,QAAQ,KAAK,UAAU;oBAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;gBACxF,MAAM,SAAS,GAAG,CAAC,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC9C,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC;gBAC3B,IAAI,CAAC,IAAI;oBAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;gBAE/D,MAAM,cAAc,GAAG,GAAG,IAAI,CAAC,EAAE,KAAK,UAAU,EAAE,CAAC;gBACnD,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,CAAC;oBAChC,MAAM,IAAI,KAAK,CAAC,uBAAuB,cAAc,EAAE,CAAC,CAAC;gBAC3D,CAAC;gBACD,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;gBAE5B,MAAM,OAAO,GAAkB;oBAC7B,IAAI,EAAE,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,cAAc,EAAE;oBACrC,SAAS;oBACT,UAAU,EAAE,CAAC,CAAC;iBACf,CAAC;gBACF,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACzB,cAAc,CAAC,GAAG,CAAC,cAAc,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAI,EAAE,OAAO,EAAE,CAAC,CAAC;YAC5E,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA8B,EAAE;oBACjD,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC;iBACzC,CAAC,CAAC;gBACH,IAAI,GAAG,EAAE,CAAC;oBACR,GAAG,CAAC,cAAc,EAAE,CAAC;oBACrB,GAAG,CAAC,gBAAgB,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAC/B,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,yBAAyB,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAC1F,CAAC;oBACF,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC;oBAC3B,IAAI,IAAI,EAAE,CAAC;wBACT,KAAK,CAAC,mBAAmB,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;oBACpD,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,aAAa;IACb,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,OAAO,IAAI,UAAU,EAAE,CAAC;QACjC,IAAI,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;YAC5B,IAAI,CAAC;gBACH,MAAM,WAAW,CACf,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,EAC1C,MAAM,EACN,SAAS,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,CAC5B,CAAC;gBACF,OAAO,CAAC,UAAU,GAAG,KAAK,EAAE,CAAC;YAC/B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,EAAE;oBACxC,EAAE,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE;oBACnB,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC;iBACnB,CAAC,CAAC;gBACH,OAAO,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,UAAU,GAAG,KAAK,EAAE,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;AAChC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,KAAY,EACZ,QAAgB;IAEhB,qFAAqF;IACrF,MAAM,OAAO,GAAoD,EAAE,CAAC;IACpE,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,cAAc,EAAE,CAAC;QAC9C,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,UAAU,CAAC,GAAG,QAAQ,IAAI,CAAC,EAAE,CAAC;YAC9D,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,qCAAqC,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;QACvE,OAAO;IACT,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,4BAA4B,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAErF,wBAAwB;IACxB,KAAK,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;QACzC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;YAClC,IAAI,CAAC;gBACH,MAAM,WAAW,CACf,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,EAChD,MAAM,EACN,eAAe,MAAM,GAAG,CACzB,CAAC;YACJ,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,kCAAkC,EAAE;oBACrD,QAAQ,EAAE,MAAM;oBAChB,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC;iBACnB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC;IAC9B,CAAC;IAED,+BAA+B;IAC/B,MAAM,QAAQ,GAAG,CAAC,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,MAAM,CAC9C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,MAAM,CAAC,CAC3D,CAAC;IACF,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IAE5B,4CAA4C;IAC5C,KAAK,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;QACzC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAC3B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,cAAc,CAAC,EAAE,MAAM,CAC9C,CAAC;QACF,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAqB,CAAC;QACnD,MAAM,QAAQ,GAAG,aAAa,CAC5B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,CACnC,CAAC,IAAI,CAAC;QACP,MAAM,YAAY,GAAG,GAAG,QAAQ,WAAW,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;QAExD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;YACvC,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAqB,CAAC;YAC3C,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE,CAAC;gBACnC,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;YACtD,CAAC;YAED,MAAM,EAAE,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;YAC/B,IAAI,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;YAEpD,wDAAwD;YACxD,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAE7E,MAAM,MAAM,GAAG,aAAa,CAC1B,KAAK,EACL,MAAM,CAAC,GAAG,EACV,EAAE,EACF,KAAK,CAAC,aAAa,IAAI,SAAS,EAChC,UAAU,CACX,CAAC;YACF,MAAM,SAAS,GAAG,CAAC,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;YACjD,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;YAC9B,IAAI,CAAC,IAAI;gBAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;YAE/D,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC;YACnC,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;gBACpB,IAAI,CAAC;oBACH,MAAM,WAAW,CACf,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,EAClC,MAAM,EACN,gBAAgB,MAAM,GAAG,CAC1B,CAAC;gBACJ,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,mCAAmC,EAAE;wBACtD,QAAQ,EAAE,MAAM;wBAChB,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC;qBACnB,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YAED,MAAM,UAAU,GAAkB,EAAE,IAAI,EAAE,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC;YAC3F,cAAc,CAAC,GAAG,CAAC,MAAM,EAAE;gBACzB,GAAG,EAAE,MAAM,CAAC,GAAG;gBACf,GAAG,EAAE,MAAM;gBACX,OAAO,EAAE,UAAU;aACpB,CAAC,CAAC;YACH,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAE1B,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,0BAA0B,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;QACtE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,+BAA+B,EAAE;gBAClD,QAAQ,EAAE,MAAM;gBAChB,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC;aACnB,CAAC,CAAC;YACH,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,KAAY;IAC5C,MAAM,QAAQ,GAAG,CAAC,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;SACtC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC;SAChC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;IAC/C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACH,MAAM,WAAW,CACf,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,EACzC,MAAM,EACN,QAAQ,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,CAC3B,CAAC;YACJ,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,EAAE;oBACvC,EAAE,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE;oBACnB,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC;iBACnB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ContentItemBase } from "@digitalpaws/starr-types-core";
|
|
2
|
+
import type { EventBus, Logger } from "../types/plugin.js";
|
|
3
|
+
import { ContentTypeRegistryImpl } from "../content-types/registry.js";
|
|
4
|
+
import { StateStore } from "./state-store.js";
|
|
5
|
+
import type { LibraryService } from "../library/library-service.js";
|
|
6
|
+
export interface RequestIntakeInput {
|
|
7
|
+
/** The user making the request (v1: always "admin"). */
|
|
8
|
+
userId: string;
|
|
9
|
+
/** The content item selected from browse/discovery. */
|
|
10
|
+
item: ContentItemBase;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Process a user request for content.
|
|
14
|
+
*
|
|
15
|
+
* 1. Compute the item's contentIdentity via the content-type registry.
|
|
16
|
+
* 2. Look for an existing non-failed TrackedRequest with that identity (DU1).
|
|
17
|
+
* 3. If found: add the user as a watcher and return the existing requestId (DU2).
|
|
18
|
+
* 4. If not found (or prior is failed): create a new TrackedRequest in status
|
|
19
|
+
* "requested", then emit "content.requested" to start the pipeline (DU3).
|
|
20
|
+
*
|
|
21
|
+
* Resolves target library for the request via LibraryService (if available).
|
|
22
|
+
*
|
|
23
|
+
* @returns The requestId (either existing or newly created).
|
|
24
|
+
*/
|
|
25
|
+
export declare function requestIntake(input: RequestIntakeInput, store: StateStore, registry: ContentTypeRegistryImpl, bus: EventBus, logger: Logger, libraryService?: LibraryService): string;
|
|
26
|
+
//# sourceMappingURL=request-intake.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-intake.d.ts","sourceRoot":"","sources":["../../src/state/request-intake.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAA0B,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAC/F,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAEpE,MAAM,WAAW,kBAAkB;IACjC,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,IAAI,EAAE,eAAe,CAAC;CACvB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,kBAAkB,EACzB,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,uBAAuB,EACjC,GAAG,EAAE,QAAQ,EACb,MAAM,EAAE,MAAM,EACd,cAAc,CAAC,EAAE,cAAc,GAC9B,MAAM,CA+DR"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// SPDX-License-Identifier: 0BSD
|
|
2
|
+
// SPDX-FileCopyrightText: 2025 Digi <digitalpaws@proton.me>
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
4
|
+
import { computeContentIdentity } from "../content-types/registry.js";
|
|
5
|
+
/**
|
|
6
|
+
* Process a user request for content.
|
|
7
|
+
*
|
|
8
|
+
* 1. Compute the item's contentIdentity via the content-type registry.
|
|
9
|
+
* 2. Look for an existing non-failed TrackedRequest with that identity (DU1).
|
|
10
|
+
* 3. If found: add the user as a watcher and return the existing requestId (DU2).
|
|
11
|
+
* 4. If not found (or prior is failed): create a new TrackedRequest in status
|
|
12
|
+
* "requested", then emit "content.requested" to start the pipeline (DU3).
|
|
13
|
+
*
|
|
14
|
+
* Resolves target library for the request via LibraryService (if available).
|
|
15
|
+
*
|
|
16
|
+
* @returns The requestId (either existing or newly created).
|
|
17
|
+
*/
|
|
18
|
+
export function requestIntake(input, store, registry, bus, logger, libraryService) {
|
|
19
|
+
// 1. Compute content identity
|
|
20
|
+
const contentIdentity = computeContentIdentity(input.item, registry);
|
|
21
|
+
logger.debug("request intake: computed identity", {
|
|
22
|
+
contentTypeId: input.item.contentTypeId,
|
|
23
|
+
contentIdentity,
|
|
24
|
+
});
|
|
25
|
+
// 2. Look for existing non-failed request (DU1)
|
|
26
|
+
const existing = store.findByContentIdentity(contentIdentity);
|
|
27
|
+
if (existing) {
|
|
28
|
+
// 3. Found — attach as watcher (DU2)
|
|
29
|
+
logger.debug("request intake: attaching to existing request", {
|
|
30
|
+
existingRequestId: existing.requestId,
|
|
31
|
+
existingStatus: existing.status,
|
|
32
|
+
});
|
|
33
|
+
store.addWatcher(existing.requestId, input.userId);
|
|
34
|
+
return existing.requestId;
|
|
35
|
+
}
|
|
36
|
+
// 4. Not found (or only failed exists) — create new (DU3)
|
|
37
|
+
const requestId = randomUUID();
|
|
38
|
+
// Determine target library (FR-RIR-01)
|
|
39
|
+
let libraryId;
|
|
40
|
+
if (libraryService) {
|
|
41
|
+
const resolved = libraryService.resolveForContentType(input.item.contentTypeId);
|
|
42
|
+
if (resolved) {
|
|
43
|
+
libraryId = resolved.libraryId;
|
|
44
|
+
logger.debug("request intake: resolved library", {
|
|
45
|
+
contentTypeId: input.item.contentTypeId,
|
|
46
|
+
libraryId,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
logger.info("request intake: creating new tracked request", {
|
|
51
|
+
requestId,
|
|
52
|
+
contentTypeId: input.item.contentTypeId,
|
|
53
|
+
contentIdentity,
|
|
54
|
+
libraryId,
|
|
55
|
+
});
|
|
56
|
+
store.insert({
|
|
57
|
+
requestId,
|
|
58
|
+
contentTypeId: input.item.contentTypeId,
|
|
59
|
+
contentIdentity,
|
|
60
|
+
item: input.item,
|
|
61
|
+
ownerUserId: input.userId,
|
|
62
|
+
libraryId,
|
|
63
|
+
});
|
|
64
|
+
// Emit content.requested to start the acquisition pipeline
|
|
65
|
+
bus.emit("content.requested", {
|
|
66
|
+
requestId,
|
|
67
|
+
userId: input.userId,
|
|
68
|
+
contentTypeId: input.item.contentTypeId,
|
|
69
|
+
item: input.item,
|
|
70
|
+
libraryId,
|
|
71
|
+
});
|
|
72
|
+
return requestId;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=request-intake.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-intake.js","sourceRoot":"","sources":["../../src/state/request-intake.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,4DAA4D;AAE5D,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,OAAO,EAAE,sBAAsB,EAA2B,MAAM,8BAA8B,CAAC;AAW/F;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,aAAa,CAC3B,KAAyB,EACzB,KAAiB,EACjB,QAAiC,EACjC,GAAa,EACb,MAAc,EACd,cAA+B;IAE/B,8BAA8B;IAC9B,MAAM,eAAe,GAAG,sBAAsB,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACrE,MAAM,CAAC,KAAK,CAAC,mCAAmC,EAAE;QAChD,aAAa,EAAE,KAAK,CAAC,IAAI,CAAC,aAAa;QACvC,eAAe;KAChB,CAAC,CAAC;IAEH,gDAAgD;IAChD,MAAM,QAAQ,GAAG,KAAK,CAAC,qBAAqB,CAAC,eAAe,CAAC,CAAC;IAE9D,IAAI,QAAQ,EAAE,CAAC;QACb,qCAAqC;QACrC,MAAM,CAAC,KAAK,CAAC,+CAA+C,EAAE;YAC5D,iBAAiB,EAAE,QAAQ,CAAC,SAAS;YACrC,cAAc,EAAE,QAAQ,CAAC,MAAM;SAChC,CAAC,CAAC;QACH,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QACnD,OAAO,QAAQ,CAAC,SAAS,CAAC;IAC5B,CAAC;IAED,0DAA0D;IAC1D,MAAM,SAAS,GAAG,UAAU,EAAE,CAAC;IAE/B,uCAAuC;IACvC,IAAI,SAA6B,CAAC;IAClC,IAAI,cAAc,EAAE,CAAC;QACnB,MAAM,QAAQ,GAAG,cAAc,CAAC,qBAAqB,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAChF,IAAI,QAAQ,EAAE,CAAC;YACb,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC;YAC/B,MAAM,CAAC,KAAK,CAAC,kCAAkC,EAAE;gBAC/C,aAAa,EAAE,KAAK,CAAC,IAAI,CAAC,aAAa;gBACvC,SAAS;aACV,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,8CAA8C,EAAE;QAC1D,SAAS;QACT,aAAa,EAAE,KAAK,CAAC,IAAI,CAAC,aAAa;QACvC,eAAe;QACf,SAAS;KACV,CAAC,CAAC;IAEH,KAAK,CAAC,MAAM,CAAC;QACX,SAAS;QACT,aAAa,EAAE,KAAK,CAAC,IAAI,CAAC,aAAa;QACvC,eAAe;QACf,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,WAAW,EAAE,KAAK,CAAC,MAAM;QACzB,SAAS;KACV,CAAC,CAAC;IAEH,2DAA2D;IAC3D,GAAG,CAAC,IAAI,CAAC,mBAAmB,EAAE;QAC5B,SAAS;QACT,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,aAAa,EAAE,KAAK,CAAC,IAAI,CAAC,aAAa;QACvC,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,SAAS;KACV,CAAC,CAAC;IAEH,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import type Database from "better-sqlite3";
|
|
2
|
+
import type { ContentItemBase } from "@digitalpaws/starr-types-core";
|
|
3
|
+
import type { EventBus, Logger } from "../types/plugin.js";
|
|
4
|
+
/** Union of the v1 status values (§4). */
|
|
5
|
+
export type RequestStatus = "requested" | "searching" | "downloading" | "downloaded" | "importing" | "imported" | "failed";
|
|
6
|
+
/** The domain record as stored and returned to callers. */
|
|
7
|
+
export interface TrackedRequest {
|
|
8
|
+
requestId: string;
|
|
9
|
+
contentTypeId: string;
|
|
10
|
+
contentIdentity: string;
|
|
11
|
+
item: ContentItemBase;
|
|
12
|
+
ownerUserId: string;
|
|
13
|
+
watchers: string[];
|
|
14
|
+
status: RequestStatus;
|
|
15
|
+
statusDetail?: string;
|
|
16
|
+
chosenReleaseId?: string;
|
|
17
|
+
attempts: number;
|
|
18
|
+
libraryId?: string;
|
|
19
|
+
libraryName?: string;
|
|
20
|
+
createdAt: string;
|
|
21
|
+
updatedAt: string;
|
|
22
|
+
}
|
|
23
|
+
/** Minimal data needed to insert a new tracked request. */
|
|
24
|
+
export interface TrackedRequestData {
|
|
25
|
+
requestId: string;
|
|
26
|
+
contentTypeId: string;
|
|
27
|
+
contentIdentity: string;
|
|
28
|
+
item: ContentItemBase;
|
|
29
|
+
ownerUserId: string;
|
|
30
|
+
libraryId?: string;
|
|
31
|
+
}
|
|
32
|
+
/** A single captured spine event stored in the trace log. */
|
|
33
|
+
export interface TraceEntry {
|
|
34
|
+
id: number;
|
|
35
|
+
traceId: string;
|
|
36
|
+
requestId: string;
|
|
37
|
+
eventType: string;
|
|
38
|
+
/** JSON-serialized event envelope (envelope fields + payload). */
|
|
39
|
+
eventData: Record<string, unknown>;
|
|
40
|
+
timestamp: string;
|
|
41
|
+
}
|
|
42
|
+
export declare class StateStore {
|
|
43
|
+
private db;
|
|
44
|
+
private bus;
|
|
45
|
+
private logger;
|
|
46
|
+
private stmtGetByRequestId;
|
|
47
|
+
private stmtFindByIdentity;
|
|
48
|
+
private stmtInsert;
|
|
49
|
+
private stmtUpdateStatus;
|
|
50
|
+
private stmtIncrementAttempts;
|
|
51
|
+
private stmtAddWatcher;
|
|
52
|
+
private stmtListByUser;
|
|
53
|
+
private stmtInsertTrace;
|
|
54
|
+
private stmtGetIdsByTraceId;
|
|
55
|
+
private stmtGetTraceByRequestId;
|
|
56
|
+
private stmtResetAttempts;
|
|
57
|
+
private stmtResetForRetry;
|
|
58
|
+
private stmtDeleteRequest;
|
|
59
|
+
private stmtDeleteTraceByRequestId;
|
|
60
|
+
constructor(db: Database.Database, bus: EventBus, logger: Logger);
|
|
61
|
+
/** Retrieve a single tracked request by its domain id. */
|
|
62
|
+
getByRequestId(requestId: string): TrackedRequest | undefined;
|
|
63
|
+
/**
|
|
64
|
+
* Find a non-failed tracked request with the given content identity.
|
|
65
|
+
* Used by request intake for de-duplication (DU1).
|
|
66
|
+
* Returns the most recently created match, or undefined.
|
|
67
|
+
*/
|
|
68
|
+
findByContentIdentity(contentIdentity: string): TrackedRequest | undefined;
|
|
69
|
+
/**
|
|
70
|
+
* Insert a brand-new tracked request with status ``requested``.
|
|
71
|
+
* Called by request intake after de-dup check (DU3).
|
|
72
|
+
*/
|
|
73
|
+
insert(data: TrackedRequestData): void;
|
|
74
|
+
/**
|
|
75
|
+
* Add a userId to the watchers array of an existing request.
|
|
76
|
+
* Called by request intake when re-attaching to an existing request (DU2).
|
|
77
|
+
* No-op if the user is already the owner or a watcher.
|
|
78
|
+
*/
|
|
79
|
+
addWatcher(requestId: string, userId: string): void;
|
|
80
|
+
/**
|
|
81
|
+
* Return the ordered trace history for a tracked request.
|
|
82
|
+
*
|
|
83
|
+
* Returns an array of TraceEntry, oldest first. Returns an empty array
|
|
84
|
+
* if the requestId is unknown or has no captured events.
|
|
85
|
+
*
|
|
86
|
+
* This is the data surface for the admin "activity" view (DBG2).
|
|
87
|
+
* The UI (Task 022) renders the returned data; this task only provides
|
|
88
|
+
* the query.
|
|
89
|
+
*/
|
|
90
|
+
getTraceLog(requestId: string): TraceEntry[];
|
|
91
|
+
/**
|
|
92
|
+
* Reset a tracked request to 'requested' for a manual retry.
|
|
93
|
+
*
|
|
94
|
+
* Clears chosenReleaseId, resets attempts to 0, sets status to
|
|
95
|
+
* 'requested' with a detail message. This is called from the
|
|
96
|
+
* retry endpoint before re-emitting content.requested.
|
|
97
|
+
*
|
|
98
|
+
* Uses a transaction for atomicity.
|
|
99
|
+
* Emits item.updated so the UI reflects the change immediately.
|
|
100
|
+
*/
|
|
101
|
+
resetAndRetry(requestId: string): void;
|
|
102
|
+
/**
|
|
103
|
+
* Permanently delete a tracked request and its associated
|
|
104
|
+
* trace-log entries. This is unconditional (any status).
|
|
105
|
+
*
|
|
106
|
+
* Returns true if a row was deleted, false if the requestId
|
|
107
|
+
* did not exist.
|
|
108
|
+
*/
|
|
109
|
+
deleteRequest(requestId: string): boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Return ALL tracked requests (admin only).
|
|
112
|
+
*/
|
|
113
|
+
getLibraryPath(requestId: string): string | undefined;
|
|
114
|
+
getAllRequests(): TrackedRequest[];
|
|
115
|
+
/**
|
|
116
|
+
* List tracked requests visible to a given user (owner or watcher).
|
|
117
|
+
* Used by the UI to show the request list (UI-ST2).
|
|
118
|
+
*/
|
|
119
|
+
listByUser(userId: string): TrackedRequest[];
|
|
120
|
+
/**
|
|
121
|
+
* Capture a spine event into the trace log. Stores the full event data
|
|
122
|
+
* (envelope fields + payload) as JSON, then prunes if the per-traceId
|
|
123
|
+
* count exceeds TRACE_HISTORY_LIMIT.
|
|
124
|
+
*
|
|
125
|
+
* This is a no-op if TRACE_HISTORY_LIMIT is 0 (trace capture disabled).
|
|
126
|
+
*/
|
|
127
|
+
private captureTraceEvent;
|
|
128
|
+
private subscribe;
|
|
129
|
+
private onReleaseFound;
|
|
130
|
+
private onDownloadStarted;
|
|
131
|
+
private onDownloadCompleted;
|
|
132
|
+
private onDownloadFailed;
|
|
133
|
+
private onImportStarted;
|
|
134
|
+
private onImportCompleted;
|
|
135
|
+
private onImportFailed;
|
|
136
|
+
private onRequestFailed;
|
|
137
|
+
/**
|
|
138
|
+
* Update status, optional detail, and optional chosenReleaseId.
|
|
139
|
+
* Emits item.updated on every call (the caller guards transitions,
|
|
140
|
+
* so duplicate emissions are not a concern).
|
|
141
|
+
*/
|
|
142
|
+
private updateStatus;
|
|
143
|
+
/** Increment the attempts counter by 1. Called on download.started (SM4). */
|
|
144
|
+
private incrementAttempts;
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=state-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-store.d.ts","sourceRoot":"","sources":["../../src/state/state-store.ts"],"names":[],"mappings":"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"}
|