@arch-cadre/modules 0.0.45 → 0.0.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_virtual/_rolldown/runtime.cjs +29 -0
- package/dist/index.cjs +4 -0
- package/dist/index.d.cts +2 -0
- package/dist/server/lifecycle.cjs +193 -0
- package/dist/server/lifecycle.d.cts +9 -0
- package/dist/server/lifecycle.d.cts.map +1 -0
- package/dist/server/lifecycle.mjs.map +1 -1
- package/dist/server/manage.cjs +126 -0
- package/dist/server/manage.d.cts +31 -0
- package/dist/server/manage.d.cts.map +1 -0
- package/dist/server/manage.mjs.map +1 -1
- package/dist/server/registry.cjs +86 -0
- package/dist/server/registry.d.cts +5 -0
- package/dist/server/registry.d.cts.map +1 -0
- package/dist/server/registry.mjs.map +1 -1
- package/dist/server/ui.cjs +180 -0
- package/dist/server/ui.d.cts +17 -0
- package/dist/server/ui.d.cts.map +1 -0
- package/dist/server/ui.mjs.map +1 -1
- package/dist/server.cjs +30 -0
- package/dist/server.d.cts +6 -0
- package/dist/types.cjs +19 -0
- package/dist/types.d.cts +117 -0
- package/dist/types.d.cts.map +1 -0
- package/package.json +12 -4
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
+
for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
+
key = keys[i];
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except) {
|
|
13
|
+
__defProp(to, key, {
|
|
14
|
+
get: ((k) => from[k]).bind(null, key),
|
|
15
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return to;
|
|
21
|
+
};
|
|
22
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
23
|
+
value: mod,
|
|
24
|
+
enumerable: true
|
|
25
|
+
}) : target, mod));
|
|
26
|
+
|
|
27
|
+
//#endregion
|
|
28
|
+
|
|
29
|
+
exports.__toESM = __toESM;
|
package/dist/index.cjs
ADDED
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { ApiRouteDefinition, IModule, ModuleExtension, ModuleManifest, ModuleManifestSchema, ModuleNavElement, ModuleNavigation, ModuleNavigationGroupMap, ModulePageProps, ModuleRouteDefinition, ModuleWidget, PrivateRouteDefinition, PublicRouteDefinition, SidebarGroupType, SidebarMenuItemType, SidebarMenuType, SystemEvent } from "./types.cjs";
|
|
2
|
+
export { ApiRouteDefinition, IModule, ModuleExtension, ModuleManifest, ModuleManifestSchema, ModuleNavElement, ModuleNavigation, ModuleNavigationGroupMap, ModulePageProps, ModuleRouteDefinition, ModuleWidget, PrivateRouteDefinition, PublicRouteDefinition, SidebarGroupType, SidebarMenuItemType, SidebarMenuType, SystemEvent };
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
|
|
3
|
+
const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
|
|
4
|
+
const require_manage = require('./manage.cjs');
|
|
5
|
+
let node_child_process = require("node:child_process");
|
|
6
|
+
let node_fs_promises = require("node:fs/promises");
|
|
7
|
+
node_fs_promises = require_runtime.__toESM(node_fs_promises);
|
|
8
|
+
let node_path = require("node:path");
|
|
9
|
+
node_path = require_runtime.__toESM(node_path);
|
|
10
|
+
let node_util = require("node:util");
|
|
11
|
+
let _arch_cadre_core = require("@arch-cadre/core");
|
|
12
|
+
let _arch_cadre_core_server = require("@arch-cadre/core/server");
|
|
13
|
+
let drizzle_orm = require("drizzle-orm");
|
|
14
|
+
|
|
15
|
+
//#region src/server/lifecycle.ts
|
|
16
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
17
|
+
async function updateStep(moduleId, step) {
|
|
18
|
+
console.log(`[Kernel] "${moduleId}" step: ${step}`);
|
|
19
|
+
await _arch_cadre_core_server.db.update(_arch_cadre_core.systemModulesTable).set({ lastStep: step }).where((0, drizzle_orm.eq)(_arch_cadre_core.systemModulesTable.id, moduleId));
|
|
20
|
+
}
|
|
21
|
+
async function resolveSchemaPath(moduleId) {
|
|
22
|
+
const root = process.cwd();
|
|
23
|
+
if (moduleId === "@arch-cadre/core" || moduleId === "core") {
|
|
24
|
+
const p = node_path.default.join(root, "node_modules", "@kryo", "core", "dist", "server", "database", "schema.cjs");
|
|
25
|
+
try {
|
|
26
|
+
await node_fs_promises.default.access(p);
|
|
27
|
+
return p;
|
|
28
|
+
} catch {
|
|
29
|
+
const devP = node_path.default.resolve(root, "../../packages/kryo-core/src/server/database/schema.ts");
|
|
30
|
+
try {
|
|
31
|
+
await node_fs_promises.default.access(devP);
|
|
32
|
+
return devP;
|
|
33
|
+
} catch {}
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
const cleanId = moduleId.replace("@arch-cadre/", "");
|
|
38
|
+
const possible = [
|
|
39
|
+
node_path.default.join(root, "modules", cleanId, "schema.ts"),
|
|
40
|
+
node_path.default.join(root, "modules", moduleId, "schema.ts"),
|
|
41
|
+
node_path.default.join(root, "node_modules", moduleId, "dist", "schema.cjs"),
|
|
42
|
+
node_path.default.join(root, "node_modules", `@arch-cadre/${cleanId}`, "dist", "schema.cjs"),
|
|
43
|
+
node_path.default.join(root, "node_modules", moduleId, "src", "schema.ts"),
|
|
44
|
+
node_path.default.join(root, "node_modules", `@arch-cadre/${cleanId}`, "src", "schema.ts"),
|
|
45
|
+
node_path.default.resolve(root, "../../packages", cleanId, "src", "schema.ts"),
|
|
46
|
+
node_path.default.resolve(root, "../../packages", `kryo-${cleanId}`, "src", "schema.ts"),
|
|
47
|
+
node_path.default.resolve(root, "../../packages", cleanId, "schema.ts")
|
|
48
|
+
];
|
|
49
|
+
for (const p of possible) try {
|
|
50
|
+
await node_fs_promises.default.access(p);
|
|
51
|
+
console.log(`[Kernel:Lifecycle] Resolved schema for ${moduleId} at: ${p}`);
|
|
52
|
+
return p;
|
|
53
|
+
} catch {
|
|
54
|
+
console.warn(`[Kernel:Lifecycle] Unresolved schema for ${moduleId} at: ${p}`);
|
|
55
|
+
}
|
|
56
|
+
console.warn(`[Kernel:Lifecycle] Could not resolve schema path for: ${moduleId}`);
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
async function pushModuleSchema(moduleId) {
|
|
60
|
+
const execAsync = (0, node_util.promisify)(node_child_process.exec);
|
|
61
|
+
console.log(`[Kernel:Lifecycle] Targeted sync for module: ${moduleId}`);
|
|
62
|
+
const root = process.cwd();
|
|
63
|
+
const enabledFromDb = await _arch_cadre_core_server.db.select({ id: _arch_cadre_core.systemModulesTable.id }).from(_arch_cadre_core.systemModulesTable).where((0, drizzle_orm.eq)(_arch_cadre_core.systemModulesTable.enabled, true));
|
|
64
|
+
const activeModuleIds = new Set(enabledFromDb.map((m) => m.id));
|
|
65
|
+
activeModuleIds.add("@arch-cadre/core");
|
|
66
|
+
activeModuleIds.add(moduleId);
|
|
67
|
+
const schemaPaths = [];
|
|
68
|
+
for (const id of Array.from(activeModuleIds)) {
|
|
69
|
+
const p = await resolveSchemaPath(id);
|
|
70
|
+
if (p) schemaPaths.push(p);
|
|
71
|
+
}
|
|
72
|
+
if (schemaPaths.length === 0) {
|
|
73
|
+
console.warn(`[Kernel:Lifecycle] No schema paths resolved for ${moduleId}, skipping push.`);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const configPath = node_path.default.join(root, "drizzle.config.ts");
|
|
77
|
+
const cmd = `"${node_path.default.join(root, "node_modules", ".bin", "drizzle-kit")}" push --force --config=${configPath}`;
|
|
78
|
+
console.log(`[Kernel:Lifecycle] Executing isolated migration. Modules: ${Array.from(activeModuleIds).join(", ")}`);
|
|
79
|
+
try {
|
|
80
|
+
await execAsync(cmd, {
|
|
81
|
+
env: {
|
|
82
|
+
...process.env,
|
|
83
|
+
CI: "true",
|
|
84
|
+
DRIZZLE_SCHEMA_OVERRIDE: schemaPaths.join(",")
|
|
85
|
+
},
|
|
86
|
+
cwd: root
|
|
87
|
+
});
|
|
88
|
+
console.log(`[Kernel:Lifecycle] Isolated migration successful for ${moduleId}`);
|
|
89
|
+
} catch (e) {
|
|
90
|
+
console.error(`[Kernel:Lifecycle] Isolated migration failed for ${moduleId}:`);
|
|
91
|
+
console.error(e.stdout || e.message);
|
|
92
|
+
throw new Error(`Migration failed: ${moduleId}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async function performToggle(moduleId, isEnabled) {
|
|
96
|
+
try {
|
|
97
|
+
const allModules = await require_manage.getModules();
|
|
98
|
+
const manifest = allModules.find((m) => m.id === moduleId);
|
|
99
|
+
await updateStep(moduleId, "Validate module...");
|
|
100
|
+
await sleep(500);
|
|
101
|
+
if (!manifest) return;
|
|
102
|
+
if (isEnabled) {
|
|
103
|
+
await updateStep(moduleId, "Queued...");
|
|
104
|
+
await sleep(500);
|
|
105
|
+
if (manifest.dependencies?.length) {
|
|
106
|
+
const pendingDeps = manifest.dependencies.filter((depId) => {
|
|
107
|
+
const dep = allModules.find((m) => m.id === depId);
|
|
108
|
+
return dep && !dep.enabled && !dep.system;
|
|
109
|
+
});
|
|
110
|
+
if (pendingDeps.length > 0) for (const depId of pendingDeps) {
|
|
111
|
+
await updateStep(moduleId, `Waiting for dependency "${depId}"...`);
|
|
112
|
+
await performToggle(depId, true);
|
|
113
|
+
await sleep(500);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
await updateStep(moduleId, "Initializing...");
|
|
117
|
+
await sleep(500);
|
|
118
|
+
await _arch_cadre_core_server.db.update(_arch_cadre_core.systemModulesTable).set({ enabled: true }).where((0, drizzle_orm.eq)(_arch_cadre_core.systemModulesTable.id, moduleId));
|
|
119
|
+
const instance = await require_manage.getModuleInstance(moduleId);
|
|
120
|
+
await updateStep(moduleId, "Migrate database...");
|
|
121
|
+
await sleep(500);
|
|
122
|
+
try {
|
|
123
|
+
if (instance?.onMigrate) await instance.onMigrate();
|
|
124
|
+
else await pushModuleSchema(moduleId);
|
|
125
|
+
await updateStep(moduleId, "Migration successful");
|
|
126
|
+
} catch (e) {
|
|
127
|
+
console.error(`[Kernel] Migration failed for ${moduleId}:`, e);
|
|
128
|
+
await updateStep(moduleId, `Migration failed: ${e.message}`);
|
|
129
|
+
await sleep(500);
|
|
130
|
+
}
|
|
131
|
+
if (instance?.onEnable) {
|
|
132
|
+
await updateStep(moduleId, "Running setup...");
|
|
133
|
+
await sleep(500);
|
|
134
|
+
await instance.onEnable();
|
|
135
|
+
}
|
|
136
|
+
await updateStep(moduleId, "Finishing...");
|
|
137
|
+
await sleep(500);
|
|
138
|
+
await _arch_cadre_core_server.db.update(_arch_cadre_core.systemModulesTable).set({
|
|
139
|
+
installed: true,
|
|
140
|
+
lastStep: null
|
|
141
|
+
}).where((0, drizzle_orm.eq)(_arch_cadre_core.systemModulesTable.id, moduleId));
|
|
142
|
+
} else {
|
|
143
|
+
const dependents = allModules.filter((m) => {
|
|
144
|
+
if (!m.enabled || m.id === moduleId) return false;
|
|
145
|
+
if (m.dependencies?.includes(moduleId)) return true;
|
|
146
|
+
if (m.extends?.includes(moduleId)) return m.extends.filter((targetId) => {
|
|
147
|
+
if (targetId === moduleId) return false;
|
|
148
|
+
return allModules.find((mod) => mod.id === targetId)?.enabled;
|
|
149
|
+
}).length === 0;
|
|
150
|
+
return false;
|
|
151
|
+
});
|
|
152
|
+
if (dependents.length > 0) {
|
|
153
|
+
await updateStep(moduleId, `Deactivating dependents...`);
|
|
154
|
+
for (const dep of dependents) {
|
|
155
|
+
await performToggle(dep.id, false);
|
|
156
|
+
await sleep(500);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
await updateStep(moduleId, "Deactivating...");
|
|
160
|
+
const instance = await require_manage.getModuleInstance(moduleId);
|
|
161
|
+
if (instance?.onDisable) await instance.onDisable();
|
|
162
|
+
await _arch_cadre_core_server.db.update(_arch_cadre_core.systemModulesTable).set({
|
|
163
|
+
enabled: false,
|
|
164
|
+
installed: false
|
|
165
|
+
}).where((0, drizzle_orm.eq)(_arch_cadre_core.systemModulesTable.id, moduleId));
|
|
166
|
+
await updateStep(moduleId, null);
|
|
167
|
+
}
|
|
168
|
+
} catch (e) {
|
|
169
|
+
console.error(`[Kernel] Fatal error for ${moduleId}:`, e);
|
|
170
|
+
await updateStep(moduleId, `Error: ${e.message}`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
async function toggleModuleState(moduleId, isEnabled) {
|
|
174
|
+
const manifest = (await require_manage.getModules()).find((m) => m.id === moduleId);
|
|
175
|
+
if (!manifest) throw new Error(`Module "${moduleId}" not found`);
|
|
176
|
+
if (manifest.enabled === isEnabled) return { success: true };
|
|
177
|
+
performToggle(moduleId, isEnabled);
|
|
178
|
+
return { success: true };
|
|
179
|
+
}
|
|
180
|
+
async function initOperationalModules() {
|
|
181
|
+
const allModules = await require_manage.getModules();
|
|
182
|
+
for (const mod of allModules) if (mod.enabled) try {
|
|
183
|
+
const instance = await require_manage.getModuleInstance(mod.id);
|
|
184
|
+
if (instance?.init) await instance.init();
|
|
185
|
+
} catch (e) {
|
|
186
|
+
console.error(`[Kernel] Failed to init module ${mod.id}:`, e);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
//#endregion
|
|
191
|
+
exports.initOperationalModules = initOperationalModules;
|
|
192
|
+
exports.pushModuleSchema = pushModuleSchema;
|
|
193
|
+
exports.toggleModuleState = toggleModuleState;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
//#region src/server/lifecycle.d.ts
|
|
2
|
+
declare function pushModuleSchema(moduleId: string): Promise<void>;
|
|
3
|
+
declare function toggleModuleState(moduleId: string, isEnabled: boolean): Promise<{
|
|
4
|
+
success: boolean;
|
|
5
|
+
}>;
|
|
6
|
+
declare function initOperationalModules(): Promise<void>;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { initOperationalModules, pushModuleSchema, toggleModuleState };
|
|
9
|
+
//# sourceMappingURL=lifecycle.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle.d.cts","names":[],"sources":["../../src/server/lifecycle.ts"],"mappings":";iBA4GsB,gBAAA,CAAiB,QAAA,WAAgB,OAAA;AAAA,iBAwLjC,iBAAA,CAAkB,QAAA,UAAkB,SAAA,YAAkB,OAAA;;;iBAWtD,sBAAA,CAAA,GAAsB,OAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecycle.mjs","names":[],"sources":["../../src/server/lifecycle.ts"],"sourcesContent":["\"use server\";\n\nimport { exec } from \"node:child_process\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { systemModulesTable } from \"@arch-cadre/core\";\nimport { db } from \"@arch-cadre/core/server\";\nimport { eq } from \"drizzle-orm\";\nimport { getModuleInstance, getModules } from \"./manage\";\n\nconst sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\nasync function updateStep(moduleId: string, step: string | null) {\n console.log(`[Kernel] \"${moduleId}\" step: ${step}`);\n await db\n .update(systemModulesTable)\n .set({ lastStep: step })\n .where(eq(systemModulesTable.id, moduleId));\n}\n\nasync function resolveSchemaPath(moduleId: string): Promise<string | null> {\n // const path = await import(\"node:path\");\n // const fs = await import(\"node:fs/promises\");\n const root = process.cwd();\n\n // 1. Special case for core\n if (moduleId === \"@arch-cadre/core\" || moduleId === \"core\") {\n const p = path.join(\n root,\n \"node_modules\",\n \"@kryo\",\n \"core\",\n \"dist\",\n \"server\",\n \"database\",\n \"schema.cjs\",\n );\n try {\n await fs.access(p);\n return p;\n } catch {\n // Monorepo dev fallback\n const devP = path.resolve(\n root,\n \"../../packages/kryo-core/src/server/database/schema.ts\",\n );\n try {\n await fs.access(devP);\n return devP;\n } catch {}\n }\n return null;\n }\n\n // Normalize moduleId (remove @arch-cadre/ prefix if present for directory searching)\n const cleanId = moduleId.replace(\"@arch-cadre/\", \"\");\n\n const possible = [\n // Local module\n path.join(root, \"modules\", cleanId, \"schema.ts\"),\n path.join(root, \"modules\", moduleId, \"schema.ts\"),\n\n // node_modules (installed or symlinked)\n path.join(root, \"node_modules\", moduleId, \"dist\", \"schema.cjs\"),\n path.join(\n root,\n \"node_modules\",\n `@arch-cadre/${cleanId}`,\n \"dist\",\n \"schema.cjs\",\n ),\n path.join(root, \"node_modules\", moduleId, \"src\", \"schema.ts\"),\n path.join(\n root,\n \"node_modules\",\n `@arch-cadre/${cleanId}`,\n \"src\",\n \"schema.ts\",\n ),\n\n // Monorepo packages (searching by various naming conventions)\n path.resolve(root, \"../../packages\", cleanId, \"src\", \"schema.ts\"),\n path.resolve(root, \"../../packages\", `kryo-${cleanId}`, \"src\", \"schema.ts\"),\n path.resolve(root, \"../../packages\", cleanId, \"schema.ts\"),\n ];\n\n for (const p of possible) {\n try {\n await fs.access(p);\n console.log(\n `[Kernel:Lifecycle] Resolved schema for ${moduleId} at: ${p}`,\n );\n return p;\n } catch {\n console.warn(\n `[Kernel:Lifecycle] Unresolved schema for ${moduleId} at: ${p}`,\n );\n }\n }\n\n console.warn(\n `[Kernel:Lifecycle] Could not resolve schema path for: ${moduleId}`,\n );\n\n return null;\n}\n\nexport async function pushModuleSchema(moduleId: string) {\n const execAsync = promisify(exec);\n\n console.log(`[Kernel:Lifecycle] Targeted sync for module: ${moduleId}`);\n\n const root = process.cwd();\n\n // 1. Get all currently enabled modules to avoid dropping their tables\n const enabledFromDb = await db\n .select({ id: systemModulesTable.id })\n .from(systemModulesTable)\n .where(eq(systemModulesTable.enabled, true));\n\n const activeModuleIds = new Set(enabledFromDb.map((m) => m.id));\n activeModuleIds.add(\"@arch-cadre/core\");\n activeModuleIds.add(moduleId);\n\n // 2. Resolve physical paths for all active schemas\n const schemaPaths: string[] = [];\n for (const id of Array.from(activeModuleIds)) {\n const p = await resolveSchemaPath(id);\n if (p) schemaPaths.push(p);\n }\n\n if (schemaPaths.length === 0) {\n console.warn(\n `[Kernel:Lifecycle] No schema paths resolved for ${moduleId}, skipping push.`,\n );\n return;\n }\n\n // 3. Prepare command\n const configPath = path.join(root, \"drizzle.config.ts\");\n const drizzleKitBin = path.join(root, \"node_modules\", \".bin\", \"drizzle-kit\");\n\n const cmd = `\"${drizzleKitBin}\" push --force --config=${configPath}`;\n\n console.log(\n `[Kernel:Lifecycle] Executing isolated migration. Modules: ${Array.from(activeModuleIds).join(\", \")}`,\n );\n\n try {\n await execAsync(cmd, {\n env: {\n ...process.env,\n CI: \"true\",\n // Pass the calculated schemas to our dynamic drizzle.config.ts\n DRIZZLE_SCHEMA_OVERRIDE: schemaPaths.join(\",\"),\n },\n cwd: root,\n });\n console.log(\n `[Kernel:Lifecycle] Isolated migration successful for ${moduleId}`,\n );\n } catch (e: any) {\n console.error(\n `[Kernel:Lifecycle] Isolated migration failed for ${moduleId}:`,\n );\n console.error(e.stdout || e.message);\n throw new Error(`Migration failed: ${moduleId}`);\n }\n}\n\nasync function performToggle(moduleId: string, isEnabled: boolean) {\n try {\n const allModules = await getModules();\n const manifest = allModules.find((m) => m.id === moduleId);\n\n await updateStep(moduleId, \"Validate module...\");\n await sleep(500);\n\n if (!manifest) return;\n\n if (isEnabled) {\n await updateStep(moduleId, \"Queued...\");\n await sleep(500);\n\n /*\n * 1. Check dependencies\n * 2. Enable module in DB (but not marked as installed yet)\n * 3. Run onMigrate (or default push) to sync DB\n * 4. Run onEnable\n * 5. Mark as installed\n */\n if (manifest.dependencies?.length) {\n const pendingDeps = manifest.dependencies.filter((depId) => {\n const dep = allModules.find((m) => m.id === depId);\n return dep && !dep.enabled && !dep.system;\n });\n\n if (pendingDeps.length > 0) {\n // await updateStep(moduleId, \"Waiting for dependencies...\");\n\n for (const depId of pendingDeps) {\n await updateStep(moduleId, `Waiting for dependency \"${depId}\"...`);\n await performToggle(depId, true);\n await sleep(500);\n }\n }\n }\n\n await updateStep(moduleId, \"Initializing...\");\n await sleep(500);\n await db\n .update(systemModulesTable)\n .set({ enabled: true })\n .where(eq(systemModulesTable.id, moduleId));\n\n const instance = await getModuleInstance(moduleId);\n\n await updateStep(moduleId, \"Migrate database...\");\n await sleep(500);\n\n try {\n if (instance?.onMigrate) {\n await instance.onMigrate();\n } else {\n // Fallback to default push if no hook provided but schema might exist\n await pushModuleSchema(moduleId);\n }\n await updateStep(moduleId, \"Migration successful\");\n } catch (e: any) {\n console.error(`[Kernel] Migration failed for ${moduleId}:`, e);\n await updateStep(moduleId, `Migration failed: ${e.message}`);\n await sleep(500);\n }\n\n if (instance?.onEnable) {\n await updateStep(moduleId, \"Running setup...\");\n await sleep(500);\n await instance.onEnable();\n }\n\n await updateStep(moduleId, \"Finishing...\");\n await sleep(500);\n await db\n .update(systemModulesTable)\n .set({ installed: true, lastStep: null })\n .where(eq(systemModulesTable.id, moduleId));\n } else {\n const dependents = allModules.filter((m) => {\n if (!m.enabled || m.id === moduleId) return false;\n\n if (m.dependencies?.includes(moduleId)) return true;\n\n if (m.extends?.includes(moduleId)) {\n const otherActiveTargets = m.extends.filter((targetId) => {\n if (targetId === moduleId) return false;\n const target = allModules.find((mod) => mod.id === targetId);\n return target?.enabled;\n });\n\n return otherActiveTargets.length === 0;\n }\n\n return false;\n });\n\n if (dependents.length > 0) {\n await updateStep(moduleId, `Deactivating dependents...`);\n for (const dep of dependents) {\n await performToggle(dep.id, false);\n await sleep(500);\n }\n }\n\n await updateStep(moduleId, \"Deactivating...\");\n\n const instance = await getModuleInstance(moduleId);\n if (instance?.onDisable) await instance.onDisable();\n\n await db\n .update(systemModulesTable)\n .set({ enabled: false, installed: false })\n .where(eq(systemModulesTable.id, moduleId));\n\n await updateStep(moduleId, null);\n }\n } catch (e) {\n console.error(`[Kernel] Fatal error for ${moduleId}:`, e);\n await updateStep(moduleId, `Error: ${(e as Error).message}`);\n }\n}\n\nexport async function toggleModuleState(moduleId: string, isEnabled: boolean) {\n const allModules = await getModules();\n const manifest = allModules.find((m) => m.id === moduleId);\n if (!manifest) throw new Error(`Module \"${moduleId}\" not found`);\n\n if (manifest.enabled === isEnabled) return { success: true };\n\n void performToggle(moduleId, isEnabled);\n return { success: true };\n}\n\nexport async function initOperationalModules() {\n const allModules = await getModules();\n for (const mod of allModules) {\n if (mod.enabled) {\n try {\n const instance = await getModuleInstance(mod.id);\n if (instance?.init) {\n await instance.init();\n }\n } catch (e) {\n console.error(`[Kernel] Failed to init module ${mod.id}:`, e);\n }\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lifecycle.mjs","names":[],"sources":["../../src/server/lifecycle.ts"],"sourcesContent":["\"use server\";\n\nimport { exec } from \"node:child_process\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { systemModulesTable } from \"@arch-cadre/core\";\nimport { db } from \"@arch-cadre/core/server\";\nimport { eq } from \"drizzle-orm\";\nimport { getModuleInstance, getModules } from \"./manage.js\";\n\nconst sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\nasync function updateStep(moduleId: string, step: string | null) {\n console.log(`[Kernel] \"${moduleId}\" step: ${step}`);\n await db\n .update(systemModulesTable)\n .set({ lastStep: step })\n .where(eq(systemModulesTable.id, moduleId));\n}\n\nasync function resolveSchemaPath(moduleId: string): Promise<string | null> {\n // const path = await import(\"node:path\");\n // const fs = await import(\"node:fs/promises\");\n const root = process.cwd();\n\n // 1. Special case for core\n if (moduleId === \"@arch-cadre/core\" || moduleId === \"core\") {\n const p = path.join(\n root,\n \"node_modules\",\n \"@kryo\",\n \"core\",\n \"dist\",\n \"server\",\n \"database\",\n \"schema.cjs\",\n );\n try {\n await fs.access(p);\n return p;\n } catch {\n // Monorepo dev fallback\n const devP = path.resolve(\n root,\n \"../../packages/kryo-core/src/server/database/schema.ts\",\n );\n try {\n await fs.access(devP);\n return devP;\n } catch { }\n }\n return null;\n }\n\n // Normalize moduleId (remove @arch-cadre/ prefix if present for directory searching)\n const cleanId = moduleId.replace(\"@arch-cadre/\", \"\");\n\n const possible = [\n // Local module\n path.join(root, \"modules\", cleanId, \"schema.ts\"),\n path.join(root, \"modules\", moduleId, \"schema.ts\"),\n\n // node_modules (installed or symlinked)\n path.join(root, \"node_modules\", moduleId, \"dist\", \"schema.cjs\"),\n path.join(\n root,\n \"node_modules\",\n `@arch-cadre/${cleanId}`,\n \"dist\",\n \"schema.cjs\",\n ),\n path.join(root, \"node_modules\", moduleId, \"src\", \"schema.ts\"),\n path.join(\n root,\n \"node_modules\",\n `@arch-cadre/${cleanId}`,\n \"src\",\n \"schema.ts\",\n ),\n\n // Monorepo packages (searching by various naming conventions)\n path.resolve(root, \"../../packages\", cleanId, \"src\", \"schema.ts\"),\n path.resolve(root, \"../../packages\", `kryo-${cleanId}`, \"src\", \"schema.ts\"),\n path.resolve(root, \"../../packages\", cleanId, \"schema.ts\"),\n ];\n\n for (const p of possible) {\n try {\n await fs.access(p);\n console.log(\n `[Kernel:Lifecycle] Resolved schema for ${moduleId} at: ${p}`,\n );\n return p;\n } catch {\n console.warn(\n `[Kernel:Lifecycle] Unresolved schema for ${moduleId} at: ${p}`,\n );\n }\n }\n\n console.warn(\n `[Kernel:Lifecycle] Could not resolve schema path for: ${moduleId}`,\n );\n\n return null;\n}\n\nexport async function pushModuleSchema(moduleId: string) {\n const execAsync = promisify(exec);\n\n console.log(`[Kernel:Lifecycle] Targeted sync for module: ${moduleId}`);\n\n const root = process.cwd();\n\n // 1. Get all currently enabled modules to avoid dropping their tables\n const enabledFromDb = await db\n .select({ id: systemModulesTable.id })\n .from(systemModulesTable)\n .where(eq(systemModulesTable.enabled, true));\n\n const activeModuleIds = new Set(enabledFromDb.map((m) => m.id));\n activeModuleIds.add(\"@arch-cadre/core\");\n activeModuleIds.add(moduleId);\n\n // 2. Resolve physical paths for all active schemas\n const schemaPaths: string[] = [];\n for (const id of Array.from(activeModuleIds)) {\n const p = await resolveSchemaPath(id);\n if (p) schemaPaths.push(p);\n }\n\n if (schemaPaths.length === 0) {\n console.warn(\n `[Kernel:Lifecycle] No schema paths resolved for ${moduleId}, skipping push.`,\n );\n return;\n }\n\n // 3. Prepare command\n const configPath = path.join(root, \"drizzle.config.ts\");\n const drizzleKitBin = path.join(root, \"node_modules\", \".bin\", \"drizzle-kit\");\n\n const cmd = `\"${drizzleKitBin}\" push --force --config=${configPath}`;\n\n console.log(\n `[Kernel:Lifecycle] Executing isolated migration. Modules: ${Array.from(activeModuleIds).join(\", \")}`,\n );\n\n try {\n await execAsync(cmd, {\n env: {\n ...process.env,\n CI: \"true\",\n // Pass the calculated schemas to our dynamic drizzle.config.ts\n DRIZZLE_SCHEMA_OVERRIDE: schemaPaths.join(\",\"),\n },\n cwd: root,\n });\n console.log(\n `[Kernel:Lifecycle] Isolated migration successful for ${moduleId}`,\n );\n } catch (e: any) {\n console.error(\n `[Kernel:Lifecycle] Isolated migration failed for ${moduleId}:`,\n );\n console.error(e.stdout || e.message);\n throw new Error(`Migration failed: ${moduleId}`);\n }\n}\n\nasync function performToggle(moduleId: string, isEnabled: boolean) {\n try {\n const allModules = await getModules();\n const manifest = allModules.find((m) => m.id === moduleId);\n\n await updateStep(moduleId, \"Validate module...\");\n await sleep(500);\n\n if (!manifest) return;\n\n if (isEnabled) {\n await updateStep(moduleId, \"Queued...\");\n await sleep(500);\n\n /*\n * 1. Check dependencies\n * 2. Enable module in DB (but not marked as installed yet)\n * 3. Run onMigrate (or default push) to sync DB\n * 4. Run onEnable\n * 5. Mark as installed\n */\n if (manifest.dependencies?.length) {\n const pendingDeps = manifest.dependencies.filter((depId) => {\n const dep = allModules.find((m) => m.id === depId);\n return dep && !dep.enabled && !dep.system;\n });\n\n if (pendingDeps.length > 0) {\n // await updateStep(moduleId, \"Waiting for dependencies...\");\n\n for (const depId of pendingDeps) {\n await updateStep(moduleId, `Waiting for dependency \"${depId}\"...`);\n await performToggle(depId, true);\n await sleep(500);\n }\n }\n }\n\n await updateStep(moduleId, \"Initializing...\");\n await sleep(500);\n await db\n .update(systemModulesTable)\n .set({ enabled: true })\n .where(eq(systemModulesTable.id, moduleId));\n\n const instance = await getModuleInstance(moduleId);\n\n await updateStep(moduleId, \"Migrate database...\");\n await sleep(500);\n\n try {\n if (instance?.onMigrate) {\n await instance.onMigrate();\n } else {\n // Fallback to default push if no hook provided but schema might exist\n await pushModuleSchema(moduleId);\n }\n await updateStep(moduleId, \"Migration successful\");\n } catch (e: any) {\n console.error(`[Kernel] Migration failed for ${moduleId}:`, e);\n await updateStep(moduleId, `Migration failed: ${e.message}`);\n await sleep(500);\n }\n\n if (instance?.onEnable) {\n await updateStep(moduleId, \"Running setup...\");\n await sleep(500);\n await instance.onEnable();\n }\n\n await updateStep(moduleId, \"Finishing...\");\n await sleep(500);\n await db\n .update(systemModulesTable)\n .set({ installed: true, lastStep: null })\n .where(eq(systemModulesTable.id, moduleId));\n } else {\n const dependents = allModules.filter((m) => {\n if (!m.enabled || m.id === moduleId) return false;\n\n if (m.dependencies?.includes(moduleId)) return true;\n\n if (m.extends?.includes(moduleId)) {\n const otherActiveTargets = m.extends.filter((targetId) => {\n if (targetId === moduleId) return false;\n const target = allModules.find((mod) => mod.id === targetId);\n return target?.enabled;\n });\n\n return otherActiveTargets.length === 0;\n }\n\n return false;\n });\n\n if (dependents.length > 0) {\n await updateStep(moduleId, `Deactivating dependents...`);\n for (const dep of dependents) {\n await performToggle(dep.id, false);\n await sleep(500);\n }\n }\n\n await updateStep(moduleId, \"Deactivating...\");\n\n const instance = await getModuleInstance(moduleId);\n if (instance?.onDisable) await instance.onDisable();\n\n await db\n .update(systemModulesTable)\n .set({ enabled: false, installed: false })\n .where(eq(systemModulesTable.id, moduleId));\n\n await updateStep(moduleId, null);\n }\n } catch (e) {\n console.error(`[Kernel] Fatal error for ${moduleId}:`, e);\n await updateStep(moduleId, `Error: ${(e as Error).message}`);\n }\n}\n\nexport async function toggleModuleState(moduleId: string, isEnabled: boolean) {\n const allModules = await getModules();\n const manifest = allModules.find((m) => m.id === moduleId);\n if (!manifest) throw new Error(`Module \"${moduleId}\" not found`);\n\n if (manifest.enabled === isEnabled) return { success: true };\n\n void performToggle(moduleId, isEnabled);\n return { success: true };\n}\n\nexport async function initOperationalModules() {\n const allModules = await getModules();\n for (const mod of allModules) {\n if (mod.enabled) {\n try {\n const instance = await getModuleInstance(mod.id);\n if (instance?.init) {\n await instance.init();\n }\n } catch (e) {\n console.error(`[Kernel] Failed to init module ${mod.id}:`, e);\n }\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
|
|
3
|
+
const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
|
|
4
|
+
const require_types = require('../types.cjs');
|
|
5
|
+
let node_fs_promises = require("node:fs/promises");
|
|
6
|
+
node_fs_promises = require_runtime.__toESM(node_fs_promises);
|
|
7
|
+
let node_path = require("node:path");
|
|
8
|
+
node_path = require_runtime.__toESM(node_path);
|
|
9
|
+
let _arch_cadre_core = require("@arch-cadre/core");
|
|
10
|
+
let _arch_cadre_core_server = require("@arch-cadre/core/server");
|
|
11
|
+
let drizzle_orm = require("drizzle-orm");
|
|
12
|
+
|
|
13
|
+
//#region src/server/manage.ts
|
|
14
|
+
const globalForModules = globalThis;
|
|
15
|
+
if (!globalForModules.__KRYO_REGISTERED_MODULES__) globalForModules.__KRYO_REGISTERED_MODULES__ = /* @__PURE__ */ new Map();
|
|
16
|
+
async function registerModules(modules) {
|
|
17
|
+
const store = globalForModules.__KRYO_REGISTERED_MODULES__;
|
|
18
|
+
for (const mod of modules) if (mod.manifest?.id) store.set(mod.manifest.id, mod);
|
|
19
|
+
}
|
|
20
|
+
async function getModules() {
|
|
21
|
+
try {
|
|
22
|
+
const modulesDir = await (0, _arch_cadre_core_server.getModulesDir)();
|
|
23
|
+
const manifests = [];
|
|
24
|
+
const entries = await node_fs_promises.default.readdir(modulesDir).catch(() => []);
|
|
25
|
+
for (const dir of entries) {
|
|
26
|
+
if (dir.startsWith(".")) continue;
|
|
27
|
+
try {
|
|
28
|
+
const content = await node_fs_promises.default.readFile(node_path.default.join(modulesDir, dir, "manifest.json"), "utf-8");
|
|
29
|
+
const manifest = require_types.ModuleManifestSchema.parse(JSON.parse(content));
|
|
30
|
+
manifests.push({
|
|
31
|
+
...manifest,
|
|
32
|
+
hasDocs: false
|
|
33
|
+
});
|
|
34
|
+
} catch {}
|
|
35
|
+
}
|
|
36
|
+
const store = globalForModules.__KRYO_REGISTERED_MODULES__;
|
|
37
|
+
for (const mod of store.values()) if (!manifests.some((m) => m.id === mod.manifest.id)) manifests.push({
|
|
38
|
+
...mod.manifest,
|
|
39
|
+
hasDocs: false
|
|
40
|
+
});
|
|
41
|
+
const dbModules = await _arch_cadre_core_server.db.select().from(_arch_cadre_core.systemModulesTable).catch(() => []);
|
|
42
|
+
const dbMap = new Map(dbModules.map((m) => [m.id, m]));
|
|
43
|
+
return manifests.map((mod) => {
|
|
44
|
+
const dbEntry = dbMap.get(mod.id);
|
|
45
|
+
return {
|
|
46
|
+
...mod,
|
|
47
|
+
enabled: mod.system ? true : dbEntry?.enabled ?? false,
|
|
48
|
+
installed: mod.system ? true : dbEntry?.installed ?? false,
|
|
49
|
+
lastStep: dbEntry?.lastStep,
|
|
50
|
+
hasDocs: mod.hasDocs
|
|
51
|
+
};
|
|
52
|
+
});
|
|
53
|
+
} catch {
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async function getModuleStatus(moduleId) {
|
|
58
|
+
try {
|
|
59
|
+
const [mod] = await _arch_cadre_core_server.db.select().from(_arch_cadre_core.systemModulesTable).where((0, drizzle_orm.eq)(_arch_cadre_core.systemModulesTable.id, moduleId));
|
|
60
|
+
return {
|
|
61
|
+
enabled: mod?.enabled,
|
|
62
|
+
installed: mod?.installed,
|
|
63
|
+
lastStep: mod?.lastStep
|
|
64
|
+
};
|
|
65
|
+
} catch {
|
|
66
|
+
return {
|
|
67
|
+
enabled: false,
|
|
68
|
+
installed: false,
|
|
69
|
+
lastStep: null
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async function isModuleEnabled(moduleId) {
|
|
74
|
+
try {
|
|
75
|
+
const [mod] = await _arch_cadre_core_server.db.select().from(_arch_cadre_core.systemModulesTable).where((0, drizzle_orm.eq)(_arch_cadre_core.systemModulesTable.id, moduleId));
|
|
76
|
+
return !!mod?.enabled || !!mod?.system;
|
|
77
|
+
} catch {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
async function getModuleInstance(moduleId) {
|
|
82
|
+
try {
|
|
83
|
+
const store = globalForModules.__KRYO_REGISTERED_MODULES__;
|
|
84
|
+
if (store.has(moduleId)) {
|
|
85
|
+
console.log(`[Kernel:Manage] Module "${moduleId}" found in registry.`);
|
|
86
|
+
return store.get(moduleId) || null;
|
|
87
|
+
}
|
|
88
|
+
console.log(`[Kernel:Manage] Module "${moduleId}" not in registry. Registry size: ${store.size}. Keys: ${Array.from(store.keys()).join(", ")}`);
|
|
89
|
+
if (!moduleId.startsWith(".") && !moduleId.startsWith("/")) try {
|
|
90
|
+
const mod = await import(`@arch-cadre/${moduleId}`);
|
|
91
|
+
console.log(`[Kernel:Manage] Module "${moduleId}" loaded via import().`);
|
|
92
|
+
return mod.default || mod || null;
|
|
93
|
+
} catch (e) {
|
|
94
|
+
console.warn(`[Kernel:Manage] Failed to import module "${moduleId} via import().": ${e.message}`);
|
|
95
|
+
}
|
|
96
|
+
return null;
|
|
97
|
+
} catch (error) {
|
|
98
|
+
console.error(`[Kernel:Manage] Error in getModuleInstance for "${moduleId}":`, error);
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
async function getModuleConfig(moduleId) {
|
|
103
|
+
try {
|
|
104
|
+
const [mod] = await _arch_cadre_core_server.db.select({ config: _arch_cadre_core.systemModulesTable.config }).from(_arch_cadre_core.systemModulesTable).where((0, drizzle_orm.eq)(_arch_cadre_core.systemModulesTable.id, moduleId));
|
|
105
|
+
if (!mod?.config) return null;
|
|
106
|
+
return JSON.parse(mod.config);
|
|
107
|
+
} catch {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
async function updateModuleConfig(moduleId, config) {
|
|
112
|
+
try {
|
|
113
|
+
await _arch_cadre_core_server.db.update(_arch_cadre_core.systemModulesTable).set({ config: JSON.stringify(config) }).where((0, drizzle_orm.eq)(_arch_cadre_core.systemModulesTable.id, moduleId));
|
|
114
|
+
} catch (e) {
|
|
115
|
+
console.warn(`[Kernel:Manage] Failed to update config for ${moduleId}:`, e);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
//#endregion
|
|
120
|
+
exports.getModuleConfig = getModuleConfig;
|
|
121
|
+
exports.getModuleInstance = getModuleInstance;
|
|
122
|
+
exports.getModuleStatus = getModuleStatus;
|
|
123
|
+
exports.getModules = getModules;
|
|
124
|
+
exports.isModuleEnabled = isModuleEnabled;
|
|
125
|
+
exports.registerModules = registerModules;
|
|
126
|
+
exports.updateModuleConfig = updateModuleConfig;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { IModule } from "../types.cjs";
|
|
2
|
+
|
|
3
|
+
//#region src/server/manage.d.ts
|
|
4
|
+
declare function registerModules(modules: IModule[]): Promise<void>;
|
|
5
|
+
declare function getModules(): Promise<{
|
|
6
|
+
enabled: boolean;
|
|
7
|
+
installed: boolean;
|
|
8
|
+
lastStep: string | null | undefined;
|
|
9
|
+
hasDocs: boolean;
|
|
10
|
+
id: string;
|
|
11
|
+
name: string;
|
|
12
|
+
version: string;
|
|
13
|
+
dependencies: string[];
|
|
14
|
+
extends: string[];
|
|
15
|
+
system: boolean;
|
|
16
|
+
description?: string | undefined;
|
|
17
|
+
npmDependencies?: string[] | undefined;
|
|
18
|
+
npmDevDependencies?: string[] | undefined;
|
|
19
|
+
}[]>;
|
|
20
|
+
declare function getModuleStatus(moduleId: string): Promise<{
|
|
21
|
+
enabled: boolean;
|
|
22
|
+
installed: boolean;
|
|
23
|
+
lastStep: string | null;
|
|
24
|
+
}>;
|
|
25
|
+
declare function isModuleEnabled(moduleId: string): Promise<boolean>;
|
|
26
|
+
declare function getModuleInstance(moduleId: string): Promise<IModule | null>;
|
|
27
|
+
declare function getModuleConfig<T>(moduleId: string): Promise<T | null>;
|
|
28
|
+
declare function updateModuleConfig(moduleId: string, config: any): Promise<void>;
|
|
29
|
+
//#endregion
|
|
30
|
+
export { getModuleConfig, getModuleInstance, getModuleStatus, getModules, isModuleEnabled, registerModules, updateModuleConfig };
|
|
31
|
+
//# sourceMappingURL=manage.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manage.d.cts","names":[],"sources":["../../src/server/manage.ts"],"mappings":";;;iBAesB,eAAA,CAAgB,OAAA,EAAS,OAAA,KAAS,OAAA;AAAA,iBASlC,UAAA,CAAA,GAAU,OAAA;;;;;;;;;;;;;;;iBAmDV,eAAA,CAAgB,QAAA,WAAgB,OAAA;;;;;iBAiBhC,eAAA,CAAgB,QAAA,WAAmB,OAAA;AAAA,iBAYnC,iBAAA,CACpB,QAAA,WACC,OAAA,CAAQ,OAAA;AAAA,iBA6CW,eAAA,GAAA,CAAmB,QAAA,WAAmB,OAAA,CAAQ,CAAA;AAAA,iBAa9C,kBAAA,CAAmB,QAAA,UAAkB,MAAA,QAAW,OAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manage.mjs","names":[],"sources":["../../src/server/manage.ts"],"sourcesContent":["\"use server\";\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { systemModulesTable } from \"@arch-cadre/core\";\nimport { db, getModulesDir } from \"@arch-cadre/core/server\";\nimport { eq } from \"drizzle-orm\";\nimport { type IModule, ModuleManifestSchema } from \"../types\";\n\nconst globalForModules = globalThis as any;\n\nif (!globalForModules.__KRYO_REGISTERED_MODULES__) {\n globalForModules.__KRYO_REGISTERED_MODULES__ = new Map<string, IModule>();\n}\n\nexport async function registerModules(modules: IModule[]) {\n const store = globalForModules.__KRYO_REGISTERED_MODULES__;\n for (const mod of modules) {\n if (mod.manifest?.id) {\n store.set(mod.manifest.id, mod);\n }\n }\n}\n\nexport async function getModules() {\n try {\n const modulesDir = await getModulesDir();\n const manifests = [];\n const entries = await fs.readdir(modulesDir).catch(() => []);\n\n for (const dir of entries) {\n if (dir.startsWith(\".\")) continue;\n try {\n const content = await fs.readFile(\n path.join(modulesDir, dir, \"manifest.json\"),\n \"utf-8\",\n );\n const manifest = ModuleManifestSchema.parse(JSON.parse(content));\n manifests.push({ ...manifest, hasDocs: false });\n } catch {}\n }\n\n const store = globalForModules.__KRYO_REGISTERED_MODULES__ as Map<\n string,\n IModule\n >;\n\n for (const mod of store.values()) {\n if (!manifests.some((m) => m.id === mod.manifest.id)) {\n manifests.push({ ...mod.manifest, hasDocs: false });\n }\n }\n\n const dbModules = await db\n .select()\n .from(systemModulesTable)\n .catch(() => []);\n\n const dbMap = new Map(dbModules.map((m) => [m.id, m]));\n\n return manifests.map((mod) => {\n const dbEntry = dbMap.get(mod.id);\n return {\n ...mod,\n enabled: mod.system ? true : (dbEntry?.enabled ?? false),\n installed: mod.system ? true : (dbEntry?.installed ?? false),\n lastStep: dbEntry?.lastStep,\n hasDocs: mod.hasDocs,\n };\n });\n } catch {\n return [];\n }\n}\n\nexport async function getModuleStatus(moduleId: string) {\n try {\n const [mod] = await db\n .select()\n .from(systemModulesTable)\n .where(eq(systemModulesTable.id, moduleId));\n\n return {\n enabled: mod?.enabled,\n installed: mod?.installed,\n lastStep: mod?.lastStep,\n };\n } catch {\n return { enabled: false, installed: false, lastStep: null };\n }\n}\n\nexport async function isModuleEnabled(moduleId: string): Promise<boolean> {\n try {\n const [mod] = await db\n .select()\n .from(systemModulesTable)\n .where(eq(systemModulesTable.id, moduleId));\n return !!mod?.enabled || !!mod?.system;\n } catch {\n return false;\n }\n}\n\nexport async function getModuleInstance(\n moduleId: string,\n): Promise<IModule | null> {\n try {\n const store = globalForModules.__KRYO_REGISTERED_MODULES__ as Map<\n string,\n IModule\n >;\n\n // 1. Check if module is already registered in the global store\n if (store.has(moduleId)) {\n console.log(`[Kernel:Manage] Module \"${moduleId}\" found in registry.`);\n return store.get(moduleId) || null;\n }\n\n console.log(\n `[Kernel:Manage] Module \"${moduleId}\" not in registry. Registry size: ${store.size}. Keys: ${Array.from(store.keys()).join(\", \")}`,\n );\n\n // 2. Try to load as an NPM package (for modules installed via npm/pnpm)\n // We only try this if it doesn't look like a local module path\n if (!moduleId.startsWith(\".\") && !moduleId.startsWith(\"/\")) {\n try {\n const mod = await import(`@arch-cadre/${moduleId}`);\n\n console.log(\n `[Kernel:Manage] Module \"${moduleId}\" loaded via import().`,\n );\n\n return mod.default || mod || null;\n } catch (e: any) {\n console.warn(\n `[Kernel:Manage] Failed to import module \"${moduleId} via import().\": ${e.message}`,\n );\n }\n }\n\n return null;\n } catch (error: any) {\n console.error(\n `[Kernel:Manage] Error in getModuleInstance for \"${moduleId}\":`,\n error,\n );\n return null;\n }\n}\n\nexport async function getModuleConfig<T>(moduleId: string): Promise<T | null> {\n try {\n const [mod] = await db\n .select({ config: systemModulesTable.config })\n .from(systemModulesTable)\n .where(eq(systemModulesTable.id, moduleId));\n if (!mod?.config) return null;\n return JSON.parse(mod.config) as T;\n } catch {\n return null;\n }\n}\n\nexport async function updateModuleConfig(moduleId: string, config: any) {\n try {\n await db\n .update(systemModulesTable)\n .set({ config: JSON.stringify(config) })\n .where(eq(systemModulesTable.id, moduleId));\n } catch (e) {\n console.warn(`[Kernel:Manage] Failed to update config for ${moduleId}:`, e);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"manage.mjs","names":[],"sources":["../../src/server/manage.ts"],"sourcesContent":["\"use server\";\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { systemModulesTable } from \"@arch-cadre/core\";\nimport { db, getModulesDir } from \"@arch-cadre/core/server\";\nimport { eq } from \"drizzle-orm\";\nimport { type IModule, ModuleManifestSchema } from \"../types.js\";\n\nconst globalForModules = globalThis as any;\n\nif (!globalForModules.__KRYO_REGISTERED_MODULES__) {\n globalForModules.__KRYO_REGISTERED_MODULES__ = new Map<string, IModule>();\n}\n\nexport async function registerModules(modules: IModule[]) {\n const store = globalForModules.__KRYO_REGISTERED_MODULES__;\n for (const mod of modules) {\n if (mod.manifest?.id) {\n store.set(mod.manifest.id, mod);\n }\n }\n}\n\nexport async function getModules() {\n try {\n const modulesDir = await getModulesDir();\n const manifests = [];\n const entries = await fs.readdir(modulesDir).catch(() => []);\n\n for (const dir of entries) {\n if (dir.startsWith(\".\")) continue;\n try {\n const content = await fs.readFile(\n path.join(modulesDir, dir, \"manifest.json\"),\n \"utf-8\",\n );\n const manifest = ModuleManifestSchema.parse(JSON.parse(content));\n manifests.push({ ...manifest, hasDocs: false });\n } catch { }\n }\n\n const store = globalForModules.__KRYO_REGISTERED_MODULES__ as Map<\n string,\n IModule\n >;\n\n for (const mod of store.values()) {\n if (!manifests.some((m) => m.id === mod.manifest.id)) {\n manifests.push({ ...mod.manifest, hasDocs: false });\n }\n }\n\n const dbModules = await db\n .select()\n .from(systemModulesTable)\n .catch(() => []);\n\n const dbMap = new Map(dbModules.map((m) => [m.id, m]));\n\n return manifests.map((mod) => {\n const dbEntry = dbMap.get(mod.id);\n return {\n ...mod,\n enabled: mod.system ? true : (dbEntry?.enabled ?? false),\n installed: mod.system ? true : (dbEntry?.installed ?? false),\n lastStep: dbEntry?.lastStep,\n hasDocs: mod.hasDocs,\n };\n });\n } catch {\n return [];\n }\n}\n\nexport async function getModuleStatus(moduleId: string) {\n try {\n const [mod] = await db\n .select()\n .from(systemModulesTable)\n .where(eq(systemModulesTable.id, moduleId));\n\n return {\n enabled: mod?.enabled,\n installed: mod?.installed,\n lastStep: mod?.lastStep,\n };\n } catch {\n return { enabled: false, installed: false, lastStep: null };\n }\n}\n\nexport async function isModuleEnabled(moduleId: string): Promise<boolean> {\n try {\n const [mod] = await db\n .select()\n .from(systemModulesTable)\n .where(eq(systemModulesTable.id, moduleId));\n return !!mod?.enabled || !!mod?.system;\n } catch {\n return false;\n }\n}\n\nexport async function getModuleInstance(\n moduleId: string,\n): Promise<IModule | null> {\n try {\n const store = globalForModules.__KRYO_REGISTERED_MODULES__ as Map<\n string,\n IModule\n >;\n\n // 1. Check if module is already registered in the global store\n if (store.has(moduleId)) {\n console.log(`[Kernel:Manage] Module \"${moduleId}\" found in registry.`);\n return store.get(moduleId) || null;\n }\n\n console.log(\n `[Kernel:Manage] Module \"${moduleId}\" not in registry. Registry size: ${store.size}. Keys: ${Array.from(store.keys()).join(\", \")}`,\n );\n\n // 2. Try to load as an NPM package (for modules installed via npm/pnpm)\n // We only try this if it doesn't look like a local module path\n if (!moduleId.startsWith(\".\") && !moduleId.startsWith(\"/\")) {\n try {\n const mod = await import(`@arch-cadre/${moduleId}`);\n\n console.log(\n `[Kernel:Manage] Module \"${moduleId}\" loaded via import().`,\n );\n\n return mod.default || mod || null;\n } catch (e: any) {\n console.warn(\n `[Kernel:Manage] Failed to import module \"${moduleId} via import().\": ${e.message}`,\n );\n }\n }\n\n return null;\n } catch (error: any) {\n console.error(\n `[Kernel:Manage] Error in getModuleInstance for \"${moduleId}\":`,\n error,\n );\n return null;\n }\n}\n\nexport async function getModuleConfig<T>(moduleId: string): Promise<T | null> {\n try {\n const [mod] = await db\n .select({ config: systemModulesTable.config })\n .from(systemModulesTable)\n .where(eq(systemModulesTable.id, moduleId));\n if (!mod?.config) return null;\n return JSON.parse(mod.config) as T;\n } catch {\n return null;\n }\n}\n\nexport async function updateModuleConfig(moduleId: string, config: any) {\n try {\n await db\n .update(systemModulesTable)\n .set({ config: JSON.stringify(config) })\n .where(eq(systemModulesTable.id, moduleId));\n } catch (e) {\n console.warn(`[Kernel:Manage] Failed to update config for ${moduleId}:`, e);\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
|
|
3
|
+
const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
|
|
4
|
+
const require_manage = require('./manage.cjs');
|
|
5
|
+
let _arch_cadre_core = require("@arch-cadre/core");
|
|
6
|
+
let _arch_cadre_core_server = require("@arch-cadre/core/server");
|
|
7
|
+
let drizzle_orm = require("drizzle-orm");
|
|
8
|
+
|
|
9
|
+
//#region src/server/registry.ts
|
|
10
|
+
const globalForRegistry = globalThis;
|
|
11
|
+
async function initModules(force = false) {
|
|
12
|
+
if (globalForRegistry.__KRYO_MODULES_INITIALIZED__ && !force) return;
|
|
13
|
+
if (force) {
|
|
14
|
+
console.log("[Kernel:Registry] Forcing re-initialization...");
|
|
15
|
+
_arch_cadre_core.eventBus.clearAll();
|
|
16
|
+
}
|
|
17
|
+
console.log("[Kernel:Registry] Synchronizing module listeners...");
|
|
18
|
+
globalForRegistry.__KRYO_MODULES_INITIALIZED__ = true;
|
|
19
|
+
await _arch_cadre_core.eventBus.publish("system:modules:init:start", { timestamp: Date.now() });
|
|
20
|
+
const processedModuleIds = /* @__PURE__ */ new Set();
|
|
21
|
+
let hasNewModules = true;
|
|
22
|
+
let iterations = 0;
|
|
23
|
+
const MAX_ITERATIONS = 10;
|
|
24
|
+
while (hasNewModules && iterations < MAX_ITERATIONS) {
|
|
25
|
+
hasNewModules = false;
|
|
26
|
+
iterations++;
|
|
27
|
+
const pendingModules = (await require_manage.getModules()).filter((mod) => !processedModuleIds.has(mod.id));
|
|
28
|
+
if (pendingModules.length === 0) break;
|
|
29
|
+
for (const mod of pendingModules) try {
|
|
30
|
+
await _arch_cadre_core_server.db.insert(_arch_cadre_core.systemModulesTable).values({
|
|
31
|
+
id: mod.id,
|
|
32
|
+
enabled: mod.system ?? false,
|
|
33
|
+
installed: mod.system ?? false,
|
|
34
|
+
system: mod.system ?? false
|
|
35
|
+
}).onConflictDoNothing();
|
|
36
|
+
} catch (_e) {}
|
|
37
|
+
const sortedPending = [...pendingModules].sort((a, b) => a.system === b.system ? 0 : a.system ? -1 : 1);
|
|
38
|
+
for (const mod of sortedPending) {
|
|
39
|
+
processedModuleIds.add(mod.id);
|
|
40
|
+
hasNewModules = true;
|
|
41
|
+
try {
|
|
42
|
+
const enabled = await require_manage.isModuleEnabled(mod.id);
|
|
43
|
+
if (!enabled) continue;
|
|
44
|
+
const instance = await require_manage.getModuleInstance(mod.id);
|
|
45
|
+
if (!instance) {
|
|
46
|
+
console.warn(`[Kernel:Registry] No instance found for module ${mod.id}. Ensure it is registered correctly.`);
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
let dbMod = null;
|
|
50
|
+
try {
|
|
51
|
+
[dbMod] = await _arch_cadre_core_server.db.select().from(_arch_cadre_core.systemModulesTable).where((0, drizzle_orm.eq)(_arch_cadre_core.systemModulesTable.id, mod.id));
|
|
52
|
+
} catch (_e) {}
|
|
53
|
+
if (enabled && (!dbMod || !dbMod.installed)) {
|
|
54
|
+
console.log(`[Kernel:Registry] Installing module ${mod.id}...`);
|
|
55
|
+
if (instance.onMigrate) {
|
|
56
|
+
console.log(`[Kernel:Registry] Running onMigrate for ${mod.id}...`);
|
|
57
|
+
await instance.onMigrate();
|
|
58
|
+
}
|
|
59
|
+
console.log(`[Kernel:Registry] Running onEnable for ${mod.id}...`);
|
|
60
|
+
if (instance.onEnable) await instance.onEnable();
|
|
61
|
+
try {
|
|
62
|
+
await _arch_cadre_core_server.db.update(_arch_cadre_core.systemModulesTable).set({
|
|
63
|
+
installed: true,
|
|
64
|
+
lastStep: null
|
|
65
|
+
}).where((0, drizzle_orm.eq)(_arch_cadre_core.systemModulesTable.id, mod.id));
|
|
66
|
+
} catch (_e) {}
|
|
67
|
+
}
|
|
68
|
+
if (instance.init) {
|
|
69
|
+
console.log(`[Kernel:Registry] Initializing ${mod.id}...`);
|
|
70
|
+
await instance.init();
|
|
71
|
+
console.log(`[Kernel:Registry] Module ${mod.id} is active.`);
|
|
72
|
+
}
|
|
73
|
+
} catch (error) {
|
|
74
|
+
console.error(`[Kernel:Registry] Critical failure for ${mod.id}:`, error);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (iterations >= MAX_ITERATIONS) console.warn("[Kernel:Registry] Max init iterations reached. Check for circular module registrations.");
|
|
79
|
+
await _arch_cadre_core.eventBus.publish("system:modules:init:end", {
|
|
80
|
+
timestamp: Date.now(),
|
|
81
|
+
moduleCount: processedModuleIds.size
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
//#endregion
|
|
86
|
+
exports.initModules = initModules;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.cts","names":[],"sources":["../../src/server/registry.ts"],"mappings":";iBAWsB,WAAA,CAAY,KAAA,aAAa,OAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.mjs","names":[],"sources":["../../src/server/registry.ts"],"sourcesContent":["\"use server\";\n\nimport { eventBus, systemModulesTable } from \"@arch-cadre/core\";\nimport { db } from \"@arch-cadre/core/server\";\nimport { eq } from \"drizzle-orm\";\nimport { getModuleInstance, getModules, isModuleEnabled } from \"./manage\";\n\nconst globalForRegistry = globalThis as unknown as {\n __KRYO_MODULES_INITIALIZED__: boolean | undefined;\n};\n\nexport async function initModules(force = false) {\n if (globalForRegistry.__KRYO_MODULES_INITIALIZED__ && !force) return;\n\n if (force) {\n console.log(\"[Kernel:Registry] Forcing re-initialization...\");\n eventBus.clearAll();\n }\n\n console.log(\"[Kernel:Registry] Synchronizing module listeners...\");\n globalForRegistry.__KRYO_MODULES_INITIALIZED__ = true;\n\n await eventBus.publish(\"system:modules:init:start\", {\n timestamp: Date.now(),\n });\n\n const processedModuleIds = new Set<string>();\n let hasNewModules = true;\n let iterations = 0;\n const MAX_ITERATIONS = 10; // Bezpiecznik przed nieskończoną pętlą\n\n while (hasNewModules && iterations < MAX_ITERATIONS) {\n hasNewModules = false;\n iterations++;\n\n // 1. Get ALL currently registered modules (including newly added ones)\n const currentModules = await getModules();\n\n // 2. Filter out modules that are already processed\n const pendingModules = currentModules.filter(\n (mod) => !processedModuleIds.has(mod.id),\n );\n\n if (pendingModules.length === 0) {\n break;\n }\n\n // 3. Synchronize new modules with database\n for (const mod of pendingModules) {\n try {\n await db\n .insert(systemModulesTable)\n .values({\n id: mod.id,\n enabled: mod.system ?? false,\n installed: mod.system ?? false,\n system: mod.system ?? false,\n })\n .onConflictDoNothing();\n } catch (_e) {\n // Table might not exist yet\n }\n }\n\n // 4. Sort pending modules: system modules first\n const sortedPending = [...pendingModules].sort((a, b) =>\n a.system === b.system ? 0 : a.system ? -1 : 1,\n );\n\n // 5. Initialize modules\n for (const mod of sortedPending) {\n // Mark as processed immediately to avoid cycles\n processedModuleIds.add(mod.id);\n hasNewModules = true; // We processed something, so we should check again in case it added more\n\n try {\n const enabled = await isModuleEnabled(mod.id);\n if (!enabled) continue;\n\n const instance = await getModuleInstance(mod.id);\n\n if (!instance) {\n console.warn(\n `[Kernel:Registry] No instance found for module ${mod.id}. Ensure it is registered correctly.`,\n );\n continue;\n }\n\n let dbMod: any = null;\n try {\n [dbMod] = await db\n .select()\n .from(systemModulesTable)\n .where(eq(systemModulesTable.id, mod.id));\n } catch (_e) {\n // Ignore missing table\n }\n\n // onEnable lifecycle\n if (enabled && (!dbMod || !dbMod.installed)) {\n console.log(`[Kernel:Registry] Installing module ${mod.id}...`);\n\n // 1. Run migrations first\n if (instance.onMigrate) {\n console.log(`[Kernel:Registry] Running onMigrate for ${mod.id}...`);\n await instance.onMigrate();\n }\n\n // 2. Run enable hook\n console.log(`[Kernel:Registry] Running onEnable for ${mod.id}...`);\n if (instance.onEnable) await instance.onEnable();\n\n try {\n await db\n .update(systemModulesTable)\n .set({ installed: true, lastStep: null })\n .where(eq(systemModulesTable.id, mod.id));\n } catch (_e) {\n // Ignore missing table\n }\n }\n\n // Operational init\n if (instance.init) {\n console.log(`[Kernel:Registry] Initializing ${mod.id}...`);\n await instance.init();\n console.log(`[Kernel:Registry] Module ${mod.id} is active.`);\n }\n } catch (error) {\n console.error(\n `[Kernel:Registry] Critical failure for ${mod.id}:`,\n error,\n );\n }\n }\n }\n\n if (iterations >= MAX_ITERATIONS) {\n console.warn(\n \"[Kernel:Registry] Max init iterations reached. Check for circular module registrations.\",\n );\n }\n\n await eventBus.publish(\"system:modules:init:end\", {\n timestamp: Date.now(),\n moduleCount: processedModuleIds.size,\n });\n}\n"],"mappings":";;;;;;;;AAOA,MAAM,oBAAoB;AAI1B,eAAsB,YAAY,QAAQ,OAAO;AAC/C,KAAI,kBAAkB,gCAAgC,CAAC,MAAO;AAE9D,KAAI,OAAO;AACT,UAAQ,IAAI,iDAAiD;AAC7D,WAAS,UAAU;;AAGrB,SAAQ,IAAI,sDAAsD;AAClE,mBAAkB,+BAA+B;AAEjD,OAAM,SAAS,QAAQ,6BAA6B,EAClD,WAAW,KAAK,KAAK,EACtB,CAAC;CAEF,MAAM,qCAAqB,IAAI,KAAa;CAC5C,IAAI,gBAAgB;CACpB,IAAI,aAAa;CACjB,MAAM,iBAAiB;AAEvB,QAAO,iBAAiB,aAAa,gBAAgB;AACnD,kBAAgB;AAChB;EAMA,MAAM,kBAHiB,MAAM,YAAY,EAGH,QACnC,QAAQ,CAAC,mBAAmB,IAAI,IAAI,GAAG,CACzC;AAED,MAAI,eAAe,WAAW,EAC5B;AAIF,OAAK,MAAM,OAAO,eAChB,KAAI;AACF,SAAM,GACH,OAAO,mBAAmB,CAC1B,OAAO;IACN,IAAI,IAAI;IACR,SAAS,IAAI,UAAU;IACvB,WAAW,IAAI,UAAU;IACzB,QAAQ,IAAI,UAAU;IACvB,CAAC,CACD,qBAAqB;WACjB,IAAI;EAMf,MAAM,gBAAgB,CAAC,GAAG,eAAe,CAAC,MAAM,GAAG,MACjD,EAAE,WAAW,EAAE,SAAS,IAAI,EAAE,SAAS,KAAK,EAC7C;AAGD,OAAK,MAAM,OAAO,eAAe;AAE/B,sBAAmB,IAAI,IAAI,GAAG;AAC9B,mBAAgB;AAEhB,OAAI;IACF,MAAM,UAAU,MAAM,gBAAgB,IAAI,GAAG;AAC7C,QAAI,CAAC,QAAS;IAEd,MAAM,WAAW,MAAM,kBAAkB,IAAI,GAAG;AAEhD,QAAI,CAAC,UAAU;AACb,aAAQ,KACN,kDAAkD,IAAI,GAAG,sCAC1D;AACD;;IAGF,IAAI,QAAa;AACjB,QAAI;AACF,MAAC,SAAS,MAAM,GACb,QAAQ,CACR,KAAK,mBAAmB,CACxB,MAAM,GAAG,mBAAmB,IAAI,IAAI,GAAG,CAAC;aACpC,IAAI;AAKb,QAAI,YAAY,CAAC,SAAS,CAAC,MAAM,YAAY;AAC3C,aAAQ,IAAI,uCAAuC,IAAI,GAAG,KAAK;AAG/D,SAAI,SAAS,WAAW;AACtB,cAAQ,IAAI,2CAA2C,IAAI,GAAG,KAAK;AACnE,YAAM,SAAS,WAAW;;AAI5B,aAAQ,IAAI,0CAA0C,IAAI,GAAG,KAAK;AAClE,SAAI,SAAS,SAAU,OAAM,SAAS,UAAU;AAEhD,SAAI;AACF,YAAM,GACH,OAAO,mBAAmB,CAC1B,IAAI;OAAE,WAAW;OAAM,UAAU;OAAM,CAAC,CACxC,MAAM,GAAG,mBAAmB,IAAI,IAAI,GAAG,CAAC;cACpC,IAAI;;AAMf,QAAI,SAAS,MAAM;AACjB,aAAQ,IAAI,kCAAkC,IAAI,GAAG,KAAK;AAC1D,WAAM,SAAS,MAAM;AACrB,aAAQ,IAAI,4BAA4B,IAAI,GAAG,aAAa;;YAEvD,OAAO;AACd,YAAQ,MACN,0CAA0C,IAAI,GAAG,IACjD,MACD;;;;AAKP,KAAI,cAAc,eAChB,SAAQ,KACN,0FACD;AAGH,OAAM,SAAS,QAAQ,2BAA2B;EAChD,WAAW,KAAK,KAAK;EACrB,aAAa,mBAAmB;EACjC,CAAC"}
|
|
1
|
+
{"version":3,"file":"registry.mjs","names":[],"sources":["../../src/server/registry.ts"],"sourcesContent":["\"use server\";\n\nimport { eventBus, systemModulesTable } from \"@arch-cadre/core\";\nimport { db } from \"@arch-cadre/core/server\";\nimport { eq } from \"drizzle-orm\";\nimport { getModuleInstance, getModules, isModuleEnabled } from \"./manage.js\";\n\nconst globalForRegistry = globalThis as unknown as {\n __KRYO_MODULES_INITIALIZED__: boolean | undefined;\n};\n\nexport async function initModules(force = false) {\n if (globalForRegistry.__KRYO_MODULES_INITIALIZED__ && !force) return;\n\n if (force) {\n console.log(\"[Kernel:Registry] Forcing re-initialization...\");\n eventBus.clearAll();\n }\n\n console.log(\"[Kernel:Registry] Synchronizing module listeners...\");\n globalForRegistry.__KRYO_MODULES_INITIALIZED__ = true;\n\n await eventBus.publish(\"system:modules:init:start\", {\n timestamp: Date.now(),\n });\n\n const processedModuleIds = new Set<string>();\n let hasNewModules = true;\n let iterations = 0;\n const MAX_ITERATIONS = 10; // Bezpiecznik przed nieskończoną pętlą\n\n while (hasNewModules && iterations < MAX_ITERATIONS) {\n hasNewModules = false;\n iterations++;\n\n // 1. Get ALL currently registered modules (including newly added ones)\n const currentModules = await getModules();\n\n // 2. Filter out modules that are already processed\n const pendingModules = currentModules.filter(\n (mod) => !processedModuleIds.has(mod.id),\n );\n\n if (pendingModules.length === 0) {\n break;\n }\n\n // 3. Synchronize new modules with database\n for (const mod of pendingModules) {\n try {\n await db\n .insert(systemModulesTable)\n .values({\n id: mod.id,\n enabled: mod.system ?? false,\n installed: mod.system ?? false,\n system: mod.system ?? false,\n })\n .onConflictDoNothing();\n } catch (_e) {\n // Table might not exist yet\n }\n }\n\n // 4. Sort pending modules: system modules first\n const sortedPending = [...pendingModules].sort((a, b) =>\n a.system === b.system ? 0 : a.system ? -1 : 1,\n );\n\n // 5. Initialize modules\n for (const mod of sortedPending) {\n // Mark as processed immediately to avoid cycles\n processedModuleIds.add(mod.id);\n hasNewModules = true; // We processed something, so we should check again in case it added more\n\n try {\n const enabled = await isModuleEnabled(mod.id);\n if (!enabled) continue;\n\n const instance = await getModuleInstance(mod.id);\n\n if (!instance) {\n console.warn(\n `[Kernel:Registry] No instance found for module ${mod.id}. Ensure it is registered correctly.`,\n );\n continue;\n }\n\n let dbMod: any = null;\n try {\n [dbMod] = await db\n .select()\n .from(systemModulesTable)\n .where(eq(systemModulesTable.id, mod.id));\n } catch (_e) {\n // Ignore missing table\n }\n\n // onEnable lifecycle\n if (enabled && (!dbMod || !dbMod.installed)) {\n console.log(`[Kernel:Registry] Installing module ${mod.id}...`);\n\n // 1. Run migrations first\n if (instance.onMigrate) {\n console.log(`[Kernel:Registry] Running onMigrate for ${mod.id}...`);\n await instance.onMigrate();\n }\n\n // 2. Run enable hook\n console.log(`[Kernel:Registry] Running onEnable for ${mod.id}...`);\n if (instance.onEnable) await instance.onEnable();\n\n try {\n await db\n .update(systemModulesTable)\n .set({ installed: true, lastStep: null })\n .where(eq(systemModulesTable.id, mod.id));\n } catch (_e) {\n // Ignore missing table\n }\n }\n\n // Operational init\n if (instance.init) {\n console.log(`[Kernel:Registry] Initializing ${mod.id}...`);\n await instance.init();\n console.log(`[Kernel:Registry] Module ${mod.id} is active.`);\n }\n } catch (error) {\n console.error(\n `[Kernel:Registry] Critical failure for ${mod.id}:`,\n error,\n );\n }\n }\n }\n\n if (iterations >= MAX_ITERATIONS) {\n console.warn(\n \"[Kernel:Registry] Max init iterations reached. Check for circular module registrations.\",\n );\n }\n\n await eventBus.publish(\"system:modules:init:end\", {\n timestamp: Date.now(),\n moduleCount: processedModuleIds.size,\n });\n}\n"],"mappings":";;;;;;;;AAOA,MAAM,oBAAoB;AAI1B,eAAsB,YAAY,QAAQ,OAAO;AAC/C,KAAI,kBAAkB,gCAAgC,CAAC,MAAO;AAE9D,KAAI,OAAO;AACT,UAAQ,IAAI,iDAAiD;AAC7D,WAAS,UAAU;;AAGrB,SAAQ,IAAI,sDAAsD;AAClE,mBAAkB,+BAA+B;AAEjD,OAAM,SAAS,QAAQ,6BAA6B,EAClD,WAAW,KAAK,KAAK,EACtB,CAAC;CAEF,MAAM,qCAAqB,IAAI,KAAa;CAC5C,IAAI,gBAAgB;CACpB,IAAI,aAAa;CACjB,MAAM,iBAAiB;AAEvB,QAAO,iBAAiB,aAAa,gBAAgB;AACnD,kBAAgB;AAChB;EAMA,MAAM,kBAHiB,MAAM,YAAY,EAGH,QACnC,QAAQ,CAAC,mBAAmB,IAAI,IAAI,GAAG,CACzC;AAED,MAAI,eAAe,WAAW,EAC5B;AAIF,OAAK,MAAM,OAAO,eAChB,KAAI;AACF,SAAM,GACH,OAAO,mBAAmB,CAC1B,OAAO;IACN,IAAI,IAAI;IACR,SAAS,IAAI,UAAU;IACvB,WAAW,IAAI,UAAU;IACzB,QAAQ,IAAI,UAAU;IACvB,CAAC,CACD,qBAAqB;WACjB,IAAI;EAMf,MAAM,gBAAgB,CAAC,GAAG,eAAe,CAAC,MAAM,GAAG,MACjD,EAAE,WAAW,EAAE,SAAS,IAAI,EAAE,SAAS,KAAK,EAC7C;AAGD,OAAK,MAAM,OAAO,eAAe;AAE/B,sBAAmB,IAAI,IAAI,GAAG;AAC9B,mBAAgB;AAEhB,OAAI;IACF,MAAM,UAAU,MAAM,gBAAgB,IAAI,GAAG;AAC7C,QAAI,CAAC,QAAS;IAEd,MAAM,WAAW,MAAM,kBAAkB,IAAI,GAAG;AAEhD,QAAI,CAAC,UAAU;AACb,aAAQ,KACN,kDAAkD,IAAI,GAAG,sCAC1D;AACD;;IAGF,IAAI,QAAa;AACjB,QAAI;AACF,MAAC,SAAS,MAAM,GACb,QAAQ,CACR,KAAK,mBAAmB,CACxB,MAAM,GAAG,mBAAmB,IAAI,IAAI,GAAG,CAAC;aACpC,IAAI;AAKb,QAAI,YAAY,CAAC,SAAS,CAAC,MAAM,YAAY;AAC3C,aAAQ,IAAI,uCAAuC,IAAI,GAAG,KAAK;AAG/D,SAAI,SAAS,WAAW;AACtB,cAAQ,IAAI,2CAA2C,IAAI,GAAG,KAAK;AACnE,YAAM,SAAS,WAAW;;AAI5B,aAAQ,IAAI,0CAA0C,IAAI,GAAG,KAAK;AAClE,SAAI,SAAS,SAAU,OAAM,SAAS,UAAU;AAEhD,SAAI;AACF,YAAM,GACH,OAAO,mBAAmB,CAC1B,IAAI;OAAE,WAAW;OAAM,UAAU;OAAM,CAAC,CACxC,MAAM,GAAG,mBAAmB,IAAI,IAAI,GAAG,CAAC;cACpC,IAAI;;AAMf,QAAI,SAAS,MAAM;AACjB,aAAQ,IAAI,kCAAkC,IAAI,GAAG,KAAK;AAC1D,WAAM,SAAS,MAAM;AACrB,aAAQ,IAAI,4BAA4B,IAAI,GAAG,aAAa;;YAEvD,OAAO;AACd,YAAQ,MACN,0CAA0C,IAAI,GAAG,IACjD,MACD;;;;AAKP,KAAI,cAAc,eAChB,SAAQ,KACN,0FACD;AAGH,OAAM,SAAS,QAAQ,2BAA2B;EAChD,WAAW,KAAK,KAAK;EACrB,aAAa,mBAAmB;EACjC,CAAC"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
|
|
3
|
+
const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
|
|
4
|
+
const require_manage = require('./manage.cjs');
|
|
5
|
+
let _arch_cadre_core_server = require("@arch-cadre/core/server");
|
|
6
|
+
|
|
7
|
+
//#region src/server/ui.ts
|
|
8
|
+
/**
|
|
9
|
+
* Helper to check and filter a navigation item based on roles and permissions.
|
|
10
|
+
* Returns the item (potentially with filtered sub-items) or null if access is denied.
|
|
11
|
+
*/
|
|
12
|
+
function filterNavItem(item, userRoles, userPermissions) {
|
|
13
|
+
if (item.roles && item.roles.length > 0) {
|
|
14
|
+
if (!item.roles.some((role) => userRoles.includes(role))) return null;
|
|
15
|
+
}
|
|
16
|
+
if (item.permissions && item.permissions.length > 0) {
|
|
17
|
+
if (!item.permissions.every((perm) => userPermissions.includes(perm))) return null;
|
|
18
|
+
}
|
|
19
|
+
if (item.items && item.items.length > 0) {
|
|
20
|
+
const filteredSubItems = item.items.map((subItem) => filterNavItem(subItem, userRoles, userPermissions)).filter((subItem) => subItem !== null);
|
|
21
|
+
return {
|
|
22
|
+
...item,
|
|
23
|
+
items: filteredSubItems
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
return item;
|
|
27
|
+
}
|
|
28
|
+
async function getModuleNavigationGrouped(type) {
|
|
29
|
+
const { user } = await (0, _arch_cadre_core_server.getCurrentSession)();
|
|
30
|
+
const userRoles = user?.roles || [];
|
|
31
|
+
const userPermissions = user?.permissions || [];
|
|
32
|
+
const active = (await require_manage.getModules()).filter((m) => m.enabled);
|
|
33
|
+
const groups = {};
|
|
34
|
+
for (const mod of active) try {
|
|
35
|
+
const instanceNav = (await require_manage.getModuleInstance(mod.id))?.navigation?.[type];
|
|
36
|
+
if (instanceNav) for (const [groupName, items] of Object.entries(instanceNav)) {
|
|
37
|
+
if (!groups[groupName]) groups[groupName] = [];
|
|
38
|
+
for (const rawItem of items) {
|
|
39
|
+
const item = filterNavItem(rawItem, userRoles, userPermissions);
|
|
40
|
+
if (item && !groups[groupName].some((existing) => existing.url === item.url)) groups[groupName].push(item);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
} catch (_e) {
|
|
44
|
+
console.warn(`[Kernel:UI] Failed to load navigation for module ${mod.id}:`, _e);
|
|
45
|
+
}
|
|
46
|
+
return groups;
|
|
47
|
+
}
|
|
48
|
+
async function getKryoPathPrefix() {
|
|
49
|
+
try {
|
|
50
|
+
return (await require_manage.getModuleConfig("kryo-panel"))?.pathPrefix ?? "/kryo";
|
|
51
|
+
} catch (_e) {
|
|
52
|
+
return "/kryo";
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async function getKryoModuleNavigationGrouped(type) {
|
|
56
|
+
const groups = await getModuleNavigationGrouped(type);
|
|
57
|
+
const prefix = await getKryoPathPrefix();
|
|
58
|
+
const prefixUrl = (url) => {
|
|
59
|
+
if (url.startsWith(prefix)) return url;
|
|
60
|
+
return url === "/" ? prefix : `${prefix}${url}`;
|
|
61
|
+
};
|
|
62
|
+
const processItems = (items) => {
|
|
63
|
+
return items.map((item) => ({
|
|
64
|
+
...item,
|
|
65
|
+
url: prefixUrl(item.url),
|
|
66
|
+
items: item.items ? processItems(item.items) : void 0
|
|
67
|
+
}));
|
|
68
|
+
};
|
|
69
|
+
const transformedGroups = {};
|
|
70
|
+
for (const [group, items] of Object.entries(groups)) transformedGroups[group] = processItems(items);
|
|
71
|
+
return transformedGroups;
|
|
72
|
+
}
|
|
73
|
+
async function getModuleNavigation(type) {
|
|
74
|
+
const { user } = await (0, _arch_cadre_core_server.getCurrentSession)();
|
|
75
|
+
const userRoles = user?.roles || [];
|
|
76
|
+
const userPermissions = user?.permissions || [];
|
|
77
|
+
const active = (await require_manage.getModules()).filter((m) => m.enabled);
|
|
78
|
+
const all = [];
|
|
79
|
+
for (const mod of active) try {
|
|
80
|
+
const instance = await require_manage.getModuleInstance(mod.id);
|
|
81
|
+
if (instance?.navigation?.[type]) {
|
|
82
|
+
const items = instance.navigation[type];
|
|
83
|
+
for (const rawItem of items) {
|
|
84
|
+
const item = filterNavItem(rawItem, userRoles, userPermissions);
|
|
85
|
+
if (item) all.push(item);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
} catch {}
|
|
89
|
+
return all;
|
|
90
|
+
}
|
|
91
|
+
async function getPublicModuleRoutes() {
|
|
92
|
+
const active = (await require_manage.getModules()).filter((m) => m.enabled);
|
|
93
|
+
const allRoutes = [];
|
|
94
|
+
for (const mod of active) try {
|
|
95
|
+
const instance = await require_manage.getModuleInstance(mod.id);
|
|
96
|
+
if (instance?.routes?.public) allRoutes.push(...instance.routes.public);
|
|
97
|
+
} catch {}
|
|
98
|
+
return allRoutes;
|
|
99
|
+
}
|
|
100
|
+
async function getPrivateModuleRoutes() {
|
|
101
|
+
const active = (await require_manage.getModules()).filter((m) => m.enabled);
|
|
102
|
+
const allRoutes = [];
|
|
103
|
+
for (const mod of active) try {
|
|
104
|
+
const instance = await require_manage.getModuleInstance(mod.id);
|
|
105
|
+
if (instance?.routes?.private) allRoutes.push(...instance.routes.private);
|
|
106
|
+
} catch {}
|
|
107
|
+
return allRoutes;
|
|
108
|
+
}
|
|
109
|
+
async function getKryoModuleRoutes() {
|
|
110
|
+
const routes = await getPrivateModuleRoutes();
|
|
111
|
+
const prefix = await getKryoPathPrefix();
|
|
112
|
+
return routes.map((route) => ({
|
|
113
|
+
...route,
|
|
114
|
+
path: route.path === "/" ? prefix : `${prefix}${route.path}`
|
|
115
|
+
}));
|
|
116
|
+
}
|
|
117
|
+
async function getApiModuleRoutes() {
|
|
118
|
+
const active = (await require_manage.getModules()).filter((m) => m.enabled);
|
|
119
|
+
const allRoutes = [];
|
|
120
|
+
for (const mod of active) try {
|
|
121
|
+
const instance = await require_manage.getModuleInstance(mod.id);
|
|
122
|
+
if (instance?.routes?.api) allRoutes.push(...instance.routes.api);
|
|
123
|
+
} catch {}
|
|
124
|
+
return allRoutes;
|
|
125
|
+
}
|
|
126
|
+
async function getModuleWidgets(area) {
|
|
127
|
+
const active = (await require_manage.getModules()).filter((m) => m.enabled);
|
|
128
|
+
const widgets = [];
|
|
129
|
+
for (const mod of active) try {
|
|
130
|
+
const instance = await require_manage.getModuleInstance(mod.id);
|
|
131
|
+
if (instance?.widgets) {
|
|
132
|
+
const matching = instance.widgets.filter((w) => w.area === area);
|
|
133
|
+
widgets.push(...matching);
|
|
134
|
+
}
|
|
135
|
+
} catch (_e) {}
|
|
136
|
+
return widgets.sort((a, b) => (a.priority || 0) - (b.priority || 0));
|
|
137
|
+
}
|
|
138
|
+
async function getExtensions(targetModule, point) {
|
|
139
|
+
const active = (await require_manage.getModules()).filter((m) => m.enabled);
|
|
140
|
+
const extensions = [];
|
|
141
|
+
for (const mod of active) try {
|
|
142
|
+
const instance = await require_manage.getModuleInstance(mod.id);
|
|
143
|
+
if (instance?.extensions) {
|
|
144
|
+
const matching = instance.extensions.filter((ext) => {
|
|
145
|
+
const isTarget = ext.targetModule === targetModule;
|
|
146
|
+
const isPoint = point ? ext.point === point : true;
|
|
147
|
+
return isTarget && isPoint;
|
|
148
|
+
});
|
|
149
|
+
extensions.push(...matching);
|
|
150
|
+
}
|
|
151
|
+
} catch (_e) {}
|
|
152
|
+
return extensions.sort((a, b) => (a.priority || 0) - (b.priority || 0));
|
|
153
|
+
}
|
|
154
|
+
async function hasExtension(targetModule, point) {
|
|
155
|
+
const active = (await require_manage.getModules()).filter((m) => m.enabled);
|
|
156
|
+
for (const mod of active) try {
|
|
157
|
+
const instance = await require_manage.getModuleInstance(mod.id);
|
|
158
|
+
if (instance?.extensions) {
|
|
159
|
+
if (instance.extensions.filter((ext) => {
|
|
160
|
+
const isTarget = ext.targetModule === targetModule;
|
|
161
|
+
const isPoint = point ? ext.point === point : true;
|
|
162
|
+
return isTarget && isPoint;
|
|
163
|
+
}).length > 0) return true;
|
|
164
|
+
}
|
|
165
|
+
} catch (_e) {}
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
//#endregion
|
|
170
|
+
exports.getApiModuleRoutes = getApiModuleRoutes;
|
|
171
|
+
exports.getExtensions = getExtensions;
|
|
172
|
+
exports.getKryoModuleNavigationGrouped = getKryoModuleNavigationGrouped;
|
|
173
|
+
exports.getKryoModuleRoutes = getKryoModuleRoutes;
|
|
174
|
+
exports.getKryoPathPrefix = getKryoPathPrefix;
|
|
175
|
+
exports.getModuleNavigation = getModuleNavigation;
|
|
176
|
+
exports.getModuleNavigationGrouped = getModuleNavigationGrouped;
|
|
177
|
+
exports.getModuleWidgets = getModuleWidgets;
|
|
178
|
+
exports.getPrivateModuleRoutes = getPrivateModuleRoutes;
|
|
179
|
+
exports.getPublicModuleRoutes = getPublicModuleRoutes;
|
|
180
|
+
exports.hasExtension = hasExtension;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ApiRouteDefinition, ModuleExtension, ModuleNavElement, ModuleWidget, PrivateRouteDefinition, PublicRouteDefinition } from "../types.cjs";
|
|
2
|
+
|
|
3
|
+
//#region src/server/ui.d.ts
|
|
4
|
+
declare function getModuleNavigationGrouped(type: "admin" | "settings"): Promise<Record<string, ModuleNavElement[]>>;
|
|
5
|
+
declare function getKryoPathPrefix(): Promise<string>;
|
|
6
|
+
declare function getKryoModuleNavigationGrouped(type: "admin" | "settings"): Promise<Record<string, ModuleNavElement[]>>;
|
|
7
|
+
declare function getModuleNavigation(type: "public"): Promise<ModuleNavElement[]>;
|
|
8
|
+
declare function getPublicModuleRoutes(): Promise<PublicRouteDefinition[]>;
|
|
9
|
+
declare function getPrivateModuleRoutes(): Promise<PrivateRouteDefinition[]>;
|
|
10
|
+
declare function getKryoModuleRoutes(): Promise<PrivateRouteDefinition[]>;
|
|
11
|
+
declare function getApiModuleRoutes(): Promise<ApiRouteDefinition[]>;
|
|
12
|
+
declare function getModuleWidgets(area: string): Promise<ModuleWidget[]>;
|
|
13
|
+
declare function getExtensions(targetModule: string, point?: string): Promise<ModuleExtension[]>;
|
|
14
|
+
declare function hasExtension(targetModule: string, point?: string): Promise<boolean>;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { getApiModuleRoutes, getExtensions, getKryoModuleNavigationGrouped, getKryoModuleRoutes, getKryoPathPrefix, getModuleNavigation, getModuleNavigationGrouped, getModuleWidgets, getPrivateModuleRoutes, getPublicModuleRoutes, hasExtension };
|
|
17
|
+
//# sourceMappingURL=ui.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.d.cts","names":[],"sources":["../../src/server/ui.ts"],"mappings":";;;iBAqDsB,0BAAA,CAA2B,IAAA,yBAA0B,OAAA,CAAA,MAAA,SAAA,gBAAA;AAAA,iBAyCrD,iBAAA,CAAA,GAAqB,OAAA;AAAA,iBASrB,8BAAA,CACpB,IAAA,yBAA0B,OAAA,CAAA,MAAA,SAAA,gBAAA;AAAA,iBA4BN,mBAAA,CACpB,IAAA,aACC,OAAA,CAAQ,gBAAA;AAAA,iBAwBW,qBAAA,CAAA,GAAyB,OAAA,CAC7C,qBAAA;AAAA,iBAmBoB,sBAAA,CAAA,GAA0B,OAAA,CAC9C,sBAAA;AAAA,iBAmBoB,mBAAA,CAAA,GAAuB,OAAA,CAAQ,sBAAA;AAAA,iBAU/B,kBAAA,CAAA,GAAsB,OAAA,CAAQ,kBAAA;AAAA,iBAgB9B,gBAAA,CAAiB,IAAA,WAAY,OAAA,CAAA,YAAA;AAAA,iBAqB7B,aAAA,CAAc,YAAA,UAAsB,KAAA,YAAc,OAAA,CAAA,eAAA;AAAA,iBAuBlD,YAAA,CAAa,YAAA,UAAsB,KAAA,YAAc,OAAA"}
|
package/dist/server/ui.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.mjs","names":[],"sources":["../../src/server/ui.ts"],"sourcesContent":["\"use server\";\n\nimport { getCurrentSession } from \"@arch-cadre/core/server\";\nimport type {\n ApiRouteDefinition,\n ModuleExtension,\n ModuleNavElement,\n ModuleNavigationGroupMap,\n ModuleWidget,\n PrivateRouteDefinition,\n PublicRouteDefinition,\n} from \"../types\";\nimport { getModuleConfig, getModuleInstance, getModules } from \"./manage\";\n\n/**\n * Helper to check and filter a navigation item based on roles and permissions.\n * Returns the item (potentially with filtered sub-items) or null if access is denied.\n */\nfunction filterNavItem(\n item: ModuleNavElement,\n userRoles: string[],\n userPermissions: string[],\n): ModuleNavElement | null {\n // 1. Check access for the item itself\n if (item.roles && item.roles.length > 0) {\n if (!item.roles.some((role) => userRoles.includes(role))) {\n return null;\n }\n }\n\n if (item.permissions && item.permissions.length > 0) {\n if (!item.permissions.every((perm) => userPermissions.includes(perm))) {\n return null;\n }\n }\n\n // 2. Recursively filter sub-items if they exist\n if (item.items && item.items.length > 0) {\n const filteredSubItems = item.items\n .map((subItem) =>\n filterNavItem(subItem as any, userRoles, userPermissions),\n )\n .filter((subItem): subItem is ModuleNavElement => subItem !== null);\n\n return {\n ...item,\n items: filteredSubItems as any,\n };\n }\n\n return item;\n}\n\nexport async function getModuleNavigationGrouped(type: \"admin\" | \"settings\") {\n const { user } = await getCurrentSession();\n const userRoles = user?.roles || [];\n const userPermissions = user?.permissions || [];\n\n const modules = await getModules();\n const active = modules.filter((m) => m.enabled);\n const groups: Record<string, ModuleNavElement[]> = {};\n\n for (const mod of active) {\n try {\n const instance = await getModuleInstance(mod.id);\n\n // 1. From instance\n const instanceNav = instance?.navigation?.[type];\n if (instanceNav) {\n for (const [groupName, items] of Object.entries(\n instanceNav as ModuleNavigationGroupMap,\n )) {\n if (!groups[groupName]) groups[groupName] = [];\n for (const rawItem of items) {\n const item = filterNavItem(rawItem, userRoles, userPermissions);\n if (\n item &&\n !groups[groupName].some((existing) => existing.url === item.url)\n ) {\n groups[groupName].push(item);\n }\n }\n }\n }\n } catch (_e) {\n console.warn(\n `[Kernel:UI] Failed to load navigation for module ${mod.id}:`,\n _e,\n );\n }\n }\n return groups;\n}\n\nexport async function getKryoPathPrefix(): Promise<string> {\n try {\n const config = await getModuleConfig<{ pathPrefix: string }>(\"kryo-panel\");\n return config?.pathPrefix ?? \"/kryo\";\n } catch (_e) {\n return \"/kryo\";\n }\n}\n\nexport async function getKryoModuleNavigationGrouped(\n type: \"admin\" | \"settings\",\n) {\n const groups = await getModuleNavigationGrouped(type);\n const prefix = await getKryoPathPrefix();\n\n const prefixUrl = (url: string) => {\n if (url.startsWith(prefix)) return url;\n return url === \"/\" ? prefix : `${prefix}${url}`;\n };\n\n const processItems = (items: ModuleNavElement[]): ModuleNavElement[] => {\n return items.map((item) => ({\n ...item,\n url: prefixUrl(item.url),\n items: item.items\n ? processItems(item.items as ModuleNavElement[])\n : undefined,\n })) as ModuleNavElement[];\n };\n\n const transformedGroups: Record<string, ModuleNavElement[]> = {};\n for (const [group, items] of Object.entries(groups)) {\n transformedGroups[group] = processItems(items);\n }\n\n return transformedGroups;\n}\n\nexport async function getModuleNavigation(\n type: \"public\",\n): Promise<ModuleNavElement[]> {\n const { user } = await getCurrentSession();\n const userRoles = user?.roles || [];\n const userPermissions = user?.permissions || [];\n\n const modules = await getModules();\n const active = modules.filter((m) => m.enabled);\n const all: ModuleNavElement[] = [];\n\n for (const mod of active) {\n try {\n const instance = await getModuleInstance(mod.id);\n if (instance?.navigation?.[type]) {\n const items = instance.navigation[type] as ModuleNavElement[];\n for (const rawItem of items) {\n const item = filterNavItem(rawItem, userRoles, userPermissions);\n if (item) all.push(item);\n }\n }\n } catch {}\n }\n return all;\n}\n\nexport async function getPublicModuleRoutes(): Promise<\n PublicRouteDefinition[]\n> {\n const modules = await getModules();\n const active = modules.filter((m) => m.enabled);\n const allRoutes: PublicRouteDefinition[] = [];\n\n for (const mod of active) {\n try {\n const instance = await getModuleInstance(mod.id);\n\n // 1. Try from instance (if pre-defined)\n if (instance?.routes?.public) {\n allRoutes.push(...instance.routes.public);\n }\n } catch {}\n }\n return allRoutes;\n}\n\nexport async function getPrivateModuleRoutes(): Promise<\n PrivateRouteDefinition[]\n> {\n const modules = await getModules();\n const active = modules.filter((m) => m.enabled);\n const allRoutes: PrivateRouteDefinition[] = [];\n\n for (const mod of active) {\n try {\n const instance = await getModuleInstance(mod.id);\n\n // 1. Try from instance\n if (instance?.routes?.private) {\n allRoutes.push(...instance.routes.private);\n }\n } catch {}\n }\n return allRoutes;\n}\n\nexport async function getKryoModuleRoutes(): Promise<PrivateRouteDefinition[]> {\n const routes = await getPrivateModuleRoutes();\n const prefix = await getKryoPathPrefix();\n\n return routes.map((route) => ({\n ...route,\n path: route.path === \"/\" ? prefix : `${prefix}${route.path}`,\n }));\n}\n\nexport async function getApiModuleRoutes(): Promise<ApiRouteDefinition[]> {\n const modules = await getModules();\n const active = modules.filter((m) => m.enabled);\n const allRoutes: ApiRouteDefinition[] = [];\n\n for (const mod of active) {\n try {\n const instance = await getModuleInstance(mod.id);\n if (instance?.routes?.api) {\n allRoutes.push(...instance.routes.api);\n }\n } catch {}\n }\n return allRoutes;\n}\n\nexport async function getModuleWidgets(area: string) {\n const modules = await getModules();\n const active = modules.filter((m) => m.enabled);\n const widgets: ModuleWidget[] = [];\n\n for (const mod of active) {\n try {\n const instance = await getModuleInstance(mod.id);\n\n if (instance?.widgets) {\n const matching = instance.widgets.filter(\n (w: ModuleWidget) => w.area === area,\n );\n widgets.push(...matching);\n }\n } catch (_e) {}\n }\n\n return widgets.sort((a, b) => (a.priority || 0) - (b.priority || 0));\n}\n\nexport async function getExtensions(targetModule: string, point?: string) {\n const modules = await getModules();\n const active = modules.filter((m) => m.enabled);\n const extensions: ModuleExtension[] = [];\n\n for (const mod of active) {\n try {\n const instance = await getModuleInstance(mod.id);\n\n if (instance?.extensions) {\n const matching = instance.extensions.filter((ext: ModuleExtension) => {\n const isTarget = ext.targetModule === targetModule;\n const isPoint = point ? ext.point === point : true;\n return isTarget && isPoint;\n });\n extensions.push(...matching);\n }\n } catch (_e) {}\n }\n\n return extensions.sort((a, b) => (a.priority || 0) - (b.priority || 0));\n}\n\nexport async function hasExtension(targetModule: string, point?: string) {\n const modules = await getModules();\n const active = modules.filter((m) => m.enabled);\n\n for (const mod of active) {\n try {\n const instance = await getModuleInstance(mod.id);\n\n if (instance?.extensions) {\n const matching = instance.extensions.filter((ext: ModuleExtension) => {\n const isTarget = ext.targetModule === targetModule;\n const isPoint = point ? ext.point === point : true;\n return isTarget && isPoint;\n });\n if (matching.length > 0) return true;\n }\n } catch (_e) {}\n }\n\n return false;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ui.mjs","names":[],"sources":["../../src/server/ui.ts"],"sourcesContent":["\"use server\";\n\nimport { getCurrentSession } from \"@arch-cadre/core/server\";\nimport type {\n ApiRouteDefinition,\n ModuleExtension,\n ModuleNavElement,\n ModuleNavigationGroupMap,\n ModuleWidget,\n PrivateRouteDefinition,\n PublicRouteDefinition,\n} from \"../types.js\";\nimport { getModuleConfig, getModuleInstance, getModules } from \"./manage.js\";\n\n/**\n * Helper to check and filter a navigation item based on roles and permissions.\n * Returns the item (potentially with filtered sub-items) or null if access is denied.\n */\nfunction filterNavItem(\n item: ModuleNavElement,\n userRoles: string[],\n userPermissions: string[],\n): ModuleNavElement | null {\n // 1. Check access for the item itself\n if (item.roles && item.roles.length > 0) {\n if (!item.roles.some((role) => userRoles.includes(role))) {\n return null;\n }\n }\n\n if (item.permissions && item.permissions.length > 0) {\n if (!item.permissions.every((perm) => userPermissions.includes(perm))) {\n return null;\n }\n }\n\n // 2. Recursively filter sub-items if they exist\n if (item.items && item.items.length > 0) {\n const filteredSubItems = item.items\n .map((subItem) =>\n filterNavItem(subItem as any, userRoles, userPermissions),\n )\n .filter((subItem): subItem is ModuleNavElement => subItem !== null);\n\n return {\n ...item,\n items: filteredSubItems as any,\n };\n }\n\n return item;\n}\n\nexport async function getModuleNavigationGrouped(type: \"admin\" | \"settings\") {\n const { user } = await getCurrentSession();\n const userRoles = user?.roles || [];\n const userPermissions = user?.permissions || [];\n\n const modules = await getModules();\n const active = modules.filter((m) => m.enabled);\n const groups: Record<string, ModuleNavElement[]> = {};\n\n for (const mod of active) {\n try {\n const instance = await getModuleInstance(mod.id);\n\n // 1. From instance\n const instanceNav = instance?.navigation?.[type];\n if (instanceNav) {\n for (const [groupName, items] of Object.entries(\n instanceNav as ModuleNavigationGroupMap,\n )) {\n if (!groups[groupName]) groups[groupName] = [];\n for (const rawItem of items) {\n const item = filterNavItem(rawItem, userRoles, userPermissions);\n if (\n item &&\n !groups[groupName].some((existing) => existing.url === item.url)\n ) {\n groups[groupName].push(item);\n }\n }\n }\n }\n } catch (_e) {\n console.warn(\n `[Kernel:UI] Failed to load navigation for module ${mod.id}:`,\n _e,\n );\n }\n }\n return groups;\n}\n\nexport async function getKryoPathPrefix(): Promise<string> {\n try {\n const config = await getModuleConfig<{ pathPrefix: string }>(\"kryo-panel\");\n return config?.pathPrefix ?? \"/kryo\";\n } catch (_e) {\n return \"/kryo\";\n }\n}\n\nexport async function getKryoModuleNavigationGrouped(\n type: \"admin\" | \"settings\",\n) {\n const groups = await getModuleNavigationGrouped(type);\n const prefix = await getKryoPathPrefix();\n\n const prefixUrl = (url: string) => {\n if (url.startsWith(prefix)) return url;\n return url === \"/\" ? prefix : `${prefix}${url}`;\n };\n\n const processItems = (items: ModuleNavElement[]): ModuleNavElement[] => {\n return items.map((item) => ({\n ...item,\n url: prefixUrl(item.url),\n items: item.items\n ? processItems(item.items as ModuleNavElement[])\n : undefined,\n })) as ModuleNavElement[];\n };\n\n const transformedGroups: Record<string, ModuleNavElement[]> = {};\n for (const [group, items] of Object.entries(groups)) {\n transformedGroups[group] = processItems(items);\n }\n\n return transformedGroups;\n}\n\nexport async function getModuleNavigation(\n type: \"public\",\n): Promise<ModuleNavElement[]> {\n const { user } = await getCurrentSession();\n const userRoles = user?.roles || [];\n const userPermissions = user?.permissions || [];\n\n const modules = await getModules();\n const active = modules.filter((m) => m.enabled);\n const all: ModuleNavElement[] = [];\n\n for (const mod of active) {\n try {\n const instance = await getModuleInstance(mod.id);\n if (instance?.navigation?.[type]) {\n const items = instance.navigation[type] as ModuleNavElement[];\n for (const rawItem of items) {\n const item = filterNavItem(rawItem, userRoles, userPermissions);\n if (item) all.push(item);\n }\n }\n } catch { }\n }\n return all;\n}\n\nexport async function getPublicModuleRoutes(): Promise<\n PublicRouteDefinition[]\n> {\n const modules = await getModules();\n const active = modules.filter((m) => m.enabled);\n const allRoutes: PublicRouteDefinition[] = [];\n\n for (const mod of active) {\n try {\n const instance = await getModuleInstance(mod.id);\n\n // 1. Try from instance (if pre-defined)\n if (instance?.routes?.public) {\n allRoutes.push(...instance.routes.public);\n }\n } catch { }\n }\n return allRoutes;\n}\n\nexport async function getPrivateModuleRoutes(): Promise<\n PrivateRouteDefinition[]\n> {\n const modules = await getModules();\n const active = modules.filter((m) => m.enabled);\n const allRoutes: PrivateRouteDefinition[] = [];\n\n for (const mod of active) {\n try {\n const instance = await getModuleInstance(mod.id);\n\n // 1. Try from instance\n if (instance?.routes?.private) {\n allRoutes.push(...instance.routes.private);\n }\n } catch { }\n }\n return allRoutes;\n}\n\nexport async function getKryoModuleRoutes(): Promise<PrivateRouteDefinition[]> {\n const routes = await getPrivateModuleRoutes();\n const prefix = await getKryoPathPrefix();\n\n return routes.map((route) => ({\n ...route,\n path: route.path === \"/\" ? prefix : `${prefix}${route.path}`,\n }));\n}\n\nexport async function getApiModuleRoutes(): Promise<ApiRouteDefinition[]> {\n const modules = await getModules();\n const active = modules.filter((m) => m.enabled);\n const allRoutes: ApiRouteDefinition[] = [];\n\n for (const mod of active) {\n try {\n const instance = await getModuleInstance(mod.id);\n if (instance?.routes?.api) {\n allRoutes.push(...instance.routes.api);\n }\n } catch { }\n }\n return allRoutes;\n}\n\nexport async function getModuleWidgets(area: string) {\n const modules = await getModules();\n const active = modules.filter((m) => m.enabled);\n const widgets: ModuleWidget[] = [];\n\n for (const mod of active) {\n try {\n const instance = await getModuleInstance(mod.id);\n\n if (instance?.widgets) {\n const matching = instance.widgets.filter(\n (w: ModuleWidget) => w.area === area,\n );\n widgets.push(...matching);\n }\n } catch (_e) { }\n }\n\n return widgets.sort((a, b) => (a.priority || 0) - (b.priority || 0));\n}\n\nexport async function getExtensions(targetModule: string, point?: string) {\n const modules = await getModules();\n const active = modules.filter((m) => m.enabled);\n const extensions: ModuleExtension[] = [];\n\n for (const mod of active) {\n try {\n const instance = await getModuleInstance(mod.id);\n\n if (instance?.extensions) {\n const matching = instance.extensions.filter((ext: ModuleExtension) => {\n const isTarget = ext.targetModule === targetModule;\n const isPoint = point ? ext.point === point : true;\n return isTarget && isPoint;\n });\n extensions.push(...matching);\n }\n } catch (_e) { }\n }\n\n return extensions.sort((a, b) => (a.priority || 0) - (b.priority || 0));\n}\n\nexport async function hasExtension(targetModule: string, point?: string) {\n const modules = await getModules();\n const active = modules.filter((m) => m.enabled);\n\n for (const mod of active) {\n try {\n const instance = await getModuleInstance(mod.id);\n\n if (instance?.extensions) {\n const matching = instance.extensions.filter((ext: ModuleExtension) => {\n const isTarget = ext.targetModule === targetModule;\n const isPoint = point ? ext.point === point : true;\n return isTarget && isPoint;\n });\n if (matching.length > 0) return true;\n }\n } catch (_e) { }\n }\n\n return false;\n}\n"],"mappings":"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"}
|
package/dist/server.cjs
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
const require_types = require('./types.cjs');
|
|
3
|
+
const require_manage = require('./server/manage.cjs');
|
|
4
|
+
const require_lifecycle = require('./server/lifecycle.cjs');
|
|
5
|
+
const require_registry = require('./server/registry.cjs');
|
|
6
|
+
const require_ui = require('./server/ui.cjs');
|
|
7
|
+
|
|
8
|
+
exports.ModuleManifestSchema = require_types.ModuleManifestSchema;
|
|
9
|
+
exports.getApiModuleRoutes = require_ui.getApiModuleRoutes;
|
|
10
|
+
exports.getExtensions = require_ui.getExtensions;
|
|
11
|
+
exports.getKryoModuleNavigationGrouped = require_ui.getKryoModuleNavigationGrouped;
|
|
12
|
+
exports.getKryoModuleRoutes = require_ui.getKryoModuleRoutes;
|
|
13
|
+
exports.getKryoPathPrefix = require_ui.getKryoPathPrefix;
|
|
14
|
+
exports.getModuleConfig = require_manage.getModuleConfig;
|
|
15
|
+
exports.getModuleInstance = require_manage.getModuleInstance;
|
|
16
|
+
exports.getModuleNavigation = require_ui.getModuleNavigation;
|
|
17
|
+
exports.getModuleNavigationGrouped = require_ui.getModuleNavigationGrouped;
|
|
18
|
+
exports.getModuleStatus = require_manage.getModuleStatus;
|
|
19
|
+
exports.getModuleWidgets = require_ui.getModuleWidgets;
|
|
20
|
+
exports.getModules = require_manage.getModules;
|
|
21
|
+
exports.getPrivateModuleRoutes = require_ui.getPrivateModuleRoutes;
|
|
22
|
+
exports.getPublicModuleRoutes = require_ui.getPublicModuleRoutes;
|
|
23
|
+
exports.hasExtension = require_ui.hasExtension;
|
|
24
|
+
exports.initModules = require_registry.initModules;
|
|
25
|
+
exports.initOperationalModules = require_lifecycle.initOperationalModules;
|
|
26
|
+
exports.isModuleEnabled = require_manage.isModuleEnabled;
|
|
27
|
+
exports.pushModuleSchema = require_lifecycle.pushModuleSchema;
|
|
28
|
+
exports.registerModules = require_manage.registerModules;
|
|
29
|
+
exports.toggleModuleState = require_lifecycle.toggleModuleState;
|
|
30
|
+
exports.updateModuleConfig = require_manage.updateModuleConfig;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ApiRouteDefinition, IModule, ModuleExtension, ModuleManifest, ModuleManifestSchema, ModuleNavElement, ModuleNavigation, ModuleNavigationGroupMap, ModulePageProps, ModuleRouteDefinition, ModuleWidget, PrivateRouteDefinition, PublicRouteDefinition, SidebarGroupType, SidebarMenuItemType, SidebarMenuType, SystemEvent } from "./types.cjs";
|
|
2
|
+
import { initOperationalModules, pushModuleSchema, toggleModuleState } from "./server/lifecycle.cjs";
|
|
3
|
+
import { getModuleConfig, getModuleInstance, getModuleStatus, getModules, isModuleEnabled, registerModules, updateModuleConfig } from "./server/manage.cjs";
|
|
4
|
+
import { initModules } from "./server/registry.cjs";
|
|
5
|
+
import { getApiModuleRoutes, getExtensions, getKryoModuleNavigationGrouped, getKryoModuleRoutes, getKryoPathPrefix, getModuleNavigation, getModuleNavigationGrouped, getModuleWidgets, getPrivateModuleRoutes, getPublicModuleRoutes, hasExtension } from "./server/ui.cjs";
|
|
6
|
+
export { ApiRouteDefinition, IModule, ModuleExtension, ModuleManifest, ModuleManifestSchema, ModuleNavElement, ModuleNavigation, ModuleNavigationGroupMap, ModulePageProps, ModuleRouteDefinition, ModuleWidget, PrivateRouteDefinition, PublicRouteDefinition, SidebarGroupType, SidebarMenuItemType, SidebarMenuType, SystemEvent, getApiModuleRoutes, getExtensions, getKryoModuleNavigationGrouped, getKryoModuleRoutes, getKryoPathPrefix, getModuleConfig, getModuleInstance, getModuleNavigation, getModuleNavigationGrouped, getModuleStatus, getModuleWidgets, getModules, getPrivateModuleRoutes, getPublicModuleRoutes, hasExtension, initModules, initOperationalModules, isModuleEnabled, pushModuleSchema, registerModules, toggleModuleState, updateModuleConfig };
|
package/dist/types.cjs
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
|
|
2
|
+
let zod = require("zod");
|
|
3
|
+
|
|
4
|
+
//#region src/types.ts
|
|
5
|
+
const ModuleManifestSchema = zod.z.object({
|
|
6
|
+
id: zod.z.string(),
|
|
7
|
+
name: zod.z.string(),
|
|
8
|
+
version: zod.z.string(),
|
|
9
|
+
description: zod.z.string().optional(),
|
|
10
|
+
dependencies: zod.z.array(zod.z.string()).default([]),
|
|
11
|
+
extends: zod.z.array(zod.z.string()).default([]),
|
|
12
|
+
enabled: zod.z.boolean().default(true),
|
|
13
|
+
system: zod.z.boolean().default(false),
|
|
14
|
+
npmDependencies: zod.z.array(zod.z.string()).optional(),
|
|
15
|
+
npmDevDependencies: zod.z.array(zod.z.string()).optional()
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
//#endregion
|
|
19
|
+
exports.ModuleManifestSchema = ModuleManifestSchema;
|
package/dist/types.d.cts
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { SystemEvent, UserPermission, UserRole } from "@arch-cadre/core";
|
|
2
|
+
import { Metadata } from "next";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
//#region src/types.d.ts
|
|
6
|
+
type SidebarGroupType = {
|
|
7
|
+
title: string;
|
|
8
|
+
items: SidebarMenuType;
|
|
9
|
+
};
|
|
10
|
+
type SidebarMenuItemType<T = Record<string, string>> = {
|
|
11
|
+
id?: string;
|
|
12
|
+
title: string;
|
|
13
|
+
icon?: string;
|
|
14
|
+
url: string;
|
|
15
|
+
roles?: string[];
|
|
16
|
+
permissions?: string[];
|
|
17
|
+
badge?: string | number | null | undefined;
|
|
18
|
+
badgeVariant?: "default" | "secondary" | "destructive" | "outline" | null | undefined;
|
|
19
|
+
} & T;
|
|
20
|
+
type SidebarMenuType = SidebarMenuItemType<{
|
|
21
|
+
items?: SidebarMenuItemType[];
|
|
22
|
+
}>[];
|
|
23
|
+
declare const ModuleManifestSchema: z.ZodObject<{
|
|
24
|
+
id: z.ZodString;
|
|
25
|
+
name: z.ZodString;
|
|
26
|
+
version: z.ZodString;
|
|
27
|
+
description: z.ZodOptional<z.ZodString>;
|
|
28
|
+
dependencies: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
29
|
+
extends: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
30
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
31
|
+
system: z.ZodDefault<z.ZodBoolean>;
|
|
32
|
+
npmDependencies: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
33
|
+
npmDevDependencies: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
34
|
+
}, z.core.$strip>;
|
|
35
|
+
type ModuleManifest = z.infer<typeof ModuleManifestSchema>;
|
|
36
|
+
interface ModuleExtension {
|
|
37
|
+
id: string;
|
|
38
|
+
targetModule: string;
|
|
39
|
+
point: string;
|
|
40
|
+
component: React.ComponentType<any>;
|
|
41
|
+
priority?: number;
|
|
42
|
+
metadata?: any;
|
|
43
|
+
}
|
|
44
|
+
interface ModulePageProps {
|
|
45
|
+
params: any;
|
|
46
|
+
searchParams: any;
|
|
47
|
+
}
|
|
48
|
+
interface ModuleRouteDefinition {
|
|
49
|
+
id?: string;
|
|
50
|
+
roles?: UserRole[];
|
|
51
|
+
permissions?: UserPermission[];
|
|
52
|
+
component: React.ComponentType<any>;
|
|
53
|
+
layout?: React.ComponentType<{
|
|
54
|
+
children: React.ReactNode;
|
|
55
|
+
}>;
|
|
56
|
+
generateMetadata?: (props: ModulePageProps) => Promise<Metadata> | Metadata;
|
|
57
|
+
}
|
|
58
|
+
interface ModuleWidget {
|
|
59
|
+
id: string;
|
|
60
|
+
name: string;
|
|
61
|
+
area: "dashboard-stats" | "dashboard-main" | "sidebar-bottom" | string;
|
|
62
|
+
component: React.ComponentType<any>;
|
|
63
|
+
priority?: number;
|
|
64
|
+
}
|
|
65
|
+
interface IModule {
|
|
66
|
+
manifest: ModuleManifest;
|
|
67
|
+
schema?: any;
|
|
68
|
+
onMigrate?: () => Promise<void>;
|
|
69
|
+
onEnable?: () => Promise<void>;
|
|
70
|
+
onDisable?: () => Promise<void>;
|
|
71
|
+
init?: () => Promise<void>;
|
|
72
|
+
widgets?: ModuleWidget[];
|
|
73
|
+
extensions?: ModuleExtension[];
|
|
74
|
+
navigation?: ModuleNavigation;
|
|
75
|
+
routes?: {
|
|
76
|
+
public?: PublicRouteDefinition[];
|
|
77
|
+
private?: PrivateRouteDefinition[];
|
|
78
|
+
api?: ApiRouteDefinition[];
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Element menu zarejestrowany przez moduł.
|
|
83
|
+
*/
|
|
84
|
+
type ModuleNavElement = SidebarMenuItemType<{
|
|
85
|
+
items?: SidebarMenuItemType[];
|
|
86
|
+
}>;
|
|
87
|
+
/**
|
|
88
|
+
* Mapa nawigacji modułu.
|
|
89
|
+
* Klucz: Nazwa grupy (np. "CMS", "Platform", "Journal")
|
|
90
|
+
* Vartość: Tablica elementów menu trafiających do tej grupy.
|
|
91
|
+
*/
|
|
92
|
+
type ModuleNavigationGroupMap = Record<string, ModuleNavElement[]>;
|
|
93
|
+
interface PublicRouteDefinition extends ModuleRouteDefinition {
|
|
94
|
+
path: string;
|
|
95
|
+
auth?: boolean;
|
|
96
|
+
}
|
|
97
|
+
interface PrivateRouteDefinition extends ModuleRouteDefinition {
|
|
98
|
+
path: string;
|
|
99
|
+
auth?: boolean;
|
|
100
|
+
}
|
|
101
|
+
interface ApiRouteDefinition {
|
|
102
|
+
id?: string;
|
|
103
|
+
path: string;
|
|
104
|
+
handler: (request: Request, context: any) => Promise<Response> | Response;
|
|
105
|
+
auth?: boolean;
|
|
106
|
+
roles?: UserRole[];
|
|
107
|
+
permissions?: UserPermission[];
|
|
108
|
+
}
|
|
109
|
+
interface ModuleNavigation {
|
|
110
|
+
public?: ModuleNavElement[];
|
|
111
|
+
admin?: ModuleNavigationGroupMap;
|
|
112
|
+
settings?: ModuleNavigationGroupMap;
|
|
113
|
+
globalRoutes?: (PublicRouteDefinition | PrivateRouteDefinition | ApiRouteDefinition)[];
|
|
114
|
+
}
|
|
115
|
+
//#endregion
|
|
116
|
+
export { ApiRouteDefinition, IModule, ModuleExtension, ModuleManifest, ModuleManifestSchema, ModuleNavElement, ModuleNavigation, ModuleNavigationGroupMap, ModulePageProps, ModuleRouteDefinition, ModuleWidget, PrivateRouteDefinition, PublicRouteDefinition, SidebarGroupType, SidebarMenuItemType, SidebarMenuType, type SystemEvent };
|
|
117
|
+
//# sourceMappingURL=types.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.cts","names":[],"sources":["../src/types.ts"],"mappings":";;;;;KAMY,gBAAA;EACV,KAAA;EACA,KAAA,EAAO,eAAA;AAAA;AAAA,KAGG,mBAAA,KAAwB,MAAA;EAClC,EAAA;EACA,KAAA;EACA,IAAA;EACA,GAAA;EACA,KAAA;EACA,WAAA;EACA,KAAA;EACA,YAAA;AAAA,IAOE,CAAA;AAAA,KAEQ,eAAA,GAAkB,mBAAA;EAC5B,KAAA,GAAQ,mBAAA;AAAA;AAAA,cAGG,oBAAA,EAAoB,CAAA,CAAA,SAAA;;;;;;;;;;;;KAarB,cAAA,GAAiB,CAAA,CAAE,KAAA,QAAa,oBAAA;AAAA,UAI3B,eAAA;EACf,EAAA;EACA,YAAA;EACA,KAAA;EACA,SAAA,EAAW,KAAA,CAAM,aAAA;EACjB,QAAA;EACA,QAAA;AAAA;AAAA,UAGe,eAAA;EACf,MAAA;EACA,YAAA;AAAA;AAAA,UAGe,qBAAA;EACf,EAAA;EACA,KAAA,GAAQ,QAAA;EACR,WAAA,GAAc,cAAA;EACd,SAAA,EAAW,KAAA,CAAM,aAAA;EACjB,MAAA,GAAS,KAAA,CAAM,aAAA;IAAgB,QAAA,EAAU,KAAA,CAAM,SAAA;EAAA;EAC/C,gBAAA,IAAoB,KAAA,EAAO,eAAA,KAAoB,OAAA,CAAQ,QAAA,IAAY,QAAA;AAAA;AAAA,UAKpD,YAAA;EACf,EAAA;EACA,IAAA;EACA,IAAA;EACA,SAAA,EAAW,KAAA,CAAM,aAAA;EACjB,QAAA;AAAA;AAAA,UAGe,OAAA;EACf,QAAA,EAAU,cAAA;EACV,MAAA;EACA,SAAA,SAAkB,OAAA;EAClB,QAAA,SAAiB,OAAA;EACjB,SAAA,SAAkB,OAAA;EAClB,IAAA,SAAa,OAAA;EACb,OAAA,GAAU,YAAA;EACV,UAAA,GAAa,eAAA;EACb,UAAA,GAAa,gBAAA;EACb,MAAA;IACE,MAAA,GAAS,qBAAA;IACT,OAAA,GAAU,sBAAA;IACV,GAAA,GAAM,kBAAA;EAAA;AAAA;;;;KASE,gBAAA,GAAmB,mBAAA;EAC7B,KAAA,GAAQ,mBAAA;AAAA;;;;;;KAQE,wBAAA,GAA2B,MAAA,SAAe,gBAAA;AAAA,UAErC,qBAAA,SAA8B,qBAAA;EAC7C,IAAA;EACA,IAAA;AAAA;AAAA,UAGe,sBAAA,SAA+B,qBAAA;EAC9C,IAAA;EACA,IAAA;AAAA;AAAA,UAGe,kBAAA;EACf,EAAA;EACA,IAAA;EACA,OAAA,GAAU,OAAA,EAAS,OAAA,EAAS,OAAA,UAAiB,OAAA,CAAQ,QAAA,IAAY,QAAA;EACjE,IAAA;EACA,KAAA,GAAQ,QAAA;EACR,WAAA,GAAc,cAAA;AAAA;AAAA,UAGC,gBAAA;EACf,MAAA,GAAS,gBAAA;EACT,KAAA,GAAQ,wBAAA;EACR,QAAA,GAAW,wBAAA;EACX,YAAA,IACI,qBAAA,GACA,sBAAA,GACA,kBAAA;AAAA"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arch-cadre/modules",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.47",
|
|
4
4
|
"description": "Core Modules for Kryo framework",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.mjs",
|
|
8
|
+
"types": "./dist/index.d.cts",
|
|
7
9
|
"exports": {
|
|
8
|
-
".":
|
|
9
|
-
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.cjs"
|
|
13
|
+
},
|
|
14
|
+
"./server": {
|
|
15
|
+
"import": "./dist/server.mjs",
|
|
16
|
+
"require": "./dist/server.cjs"
|
|
17
|
+
},
|
|
10
18
|
"./package.json": "./package.json"
|
|
11
19
|
},
|
|
12
20
|
"files": [
|