@arch-cadre/modules 0.0.15 → 0.0.16
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/client/extension-point-client.cjs +1 -1
- package/dist/client/extension-point-client.d.cts.map +1 -1
- package/dist/client/extension-point-client.d.mts.map +1 -1
- package/dist/client/extension-point-client.mjs +1 -1
- package/dist/client/extension-point-client.mjs.map +1 -1
- package/dist/server/lifecycle.cjs +8 -8
- package/dist/server/lifecycle.d.cts.map +1 -1
- package/dist/server/lifecycle.d.mts.map +1 -1
- package/dist/server/lifecycle.mjs +8 -8
- package/dist/server/lifecycle.mjs.map +1 -1
- package/dist/server/ui.d.cts.map +1 -1
- package/dist/server/ui.d.mts.map +1 -1
- package/dist/server/ui.mjs.map +1 -1
- package/package.json +5 -5
|
@@ -7,7 +7,7 @@ react = require_runtime.__toESM(react);
|
|
|
7
7
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
8
8
|
|
|
9
9
|
//#region src/client/extension-point-client.tsx
|
|
10
|
-
/** biome-ignore-all lint/suspicious/noExplicitAny:
|
|
10
|
+
/** biome-ignore-all lint/suspicious/noExplicitAny: <> */
|
|
11
11
|
function ExtensionPointClient({ module, point, className, props, fallback }) {
|
|
12
12
|
const [extensions, setExtensions] = (0, react.useState)([]);
|
|
13
13
|
(0, react.useEffect)(() => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension-point-client.d.cts","names":[],"sources":["../../src/client/extension-point-client.tsx"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"extension-point-client.d.cts","names":[],"sources":["../../src/client/extension-point-client.tsx"],"mappings":";;;UAOU,mBAAA;EACR,MAAA;EACA,KAAA;EACA,SAAA;EACA,KAAA;EACA,QAAA,GAAW,KAAA,CAAM,SAAA;AAAA;AAAA,iBAGH,oBAAA,CAAA;EACd,MAAA;EACA,KAAA;EACA,SAAA;EACA,KAAA;EACA;AAAA,GACC,mBAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension-point-client.d.mts","names":[],"sources":["../../src/client/extension-point-client.tsx"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"extension-point-client.d.mts","names":[],"sources":["../../src/client/extension-point-client.tsx"],"mappings":";;;UAOU,mBAAA;EACR,MAAA;EACA,KAAA;EACA,SAAA;EACA,KAAA;EACA,QAAA,GAAW,KAAA,CAAM,SAAA;AAAA;AAAA,iBAGH,oBAAA,CAAA;EACd,MAAA;EACA,KAAA;EACA,SAAA;EACA,KAAA;EACA;AAAA,GACC,mBAAA"}
|
|
@@ -5,7 +5,7 @@ import { useEffect, useState } from "react";
|
|
|
5
5
|
import { jsx } from "react/jsx-runtime";
|
|
6
6
|
|
|
7
7
|
//#region src/client/extension-point-client.tsx
|
|
8
|
-
/** biome-ignore-all lint/suspicious/noExplicitAny:
|
|
8
|
+
/** biome-ignore-all lint/suspicious/noExplicitAny: <> */
|
|
9
9
|
function ExtensionPointClient({ module, point, className, props, fallback }) {
|
|
10
10
|
const [extensions, setExtensions] = useState([]);
|
|
11
11
|
useEffect(() => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension-point-client.mjs","names":[],"sources":["../../src/client/extension-point-client.tsx"],"sourcesContent":["/** biome-ignore-all lint/suspicious/noExplicitAny:
|
|
1
|
+
{"version":3,"file":"extension-point-client.mjs","names":[],"sources":["../../src/client/extension-point-client.tsx"],"sourcesContent":["/** biome-ignore-all lint/suspicious/noExplicitAny: <> */\n\"use client\";\nimport * as React from \"react\";\n\nimport { useEffect, useState } from \"react\";\nimport { getExtensions } from \"../server/ui\";\n\ninterface ExtensionPointProps {\n module: string;\n point: string;\n className?: string;\n props?: any;\n fallback?: React.ReactNode;\n}\n\nexport function ExtensionPointClient({\n module,\n point,\n className,\n props,\n fallback,\n}: ExtensionPointProps) {\n const [extensions, setExtensions] = useState<any[]>([]);\n\n useEffect(() => {\n getExtensions(module, point).then(setExtensions);\n }, [module, point]);\n\n if (extensions.length === 0) return (fallback as any) || null;\n\n return (\n <div className={className}>\n {extensions.map((ext) => {\n const Component = ext.component;\n if (!Component) return null;\n return <Component key={ext.id} {...props} />;\n })}\n </div>\n );\n}\n"],"mappings":";;;;;;;;AAeA,SAAgB,qBAAqB,EACnC,QACA,OACA,WACA,OACA,YACsB;CACtB,MAAM,CAAC,YAAY,iBAAiB,SAAgB,EAAE,CAAC;AAEvD,iBAAgB;AACd,gBAAc,QAAQ,MAAM,CAAC,KAAK,cAAc;IAC/C,CAAC,QAAQ,MAAM,CAAC;AAEnB,KAAI,WAAW,WAAW,EAAG,QAAQ,YAAoB;AAEzD,QACE,oBAAC;EAAe;YACb,WAAW,KAAK,QAAQ;GACvB,MAAM,YAAY,IAAI;AACtB,OAAI,CAAC,UAAW,QAAO;AACvB,UAAO,oBAAC,aAAuB,GAAI,SAAZ,IAAI,GAAiB;IAC5C;GACE"}
|
|
@@ -50,7 +50,9 @@ async function resolveSchemaPath(moduleId) {
|
|
|
50
50
|
await node_fs_promises.default.access(p);
|
|
51
51
|
console.log(`[Kernel:Lifecycle] Resolved schema for ${moduleId} at: ${p}`);
|
|
52
52
|
return p;
|
|
53
|
-
} catch {
|
|
53
|
+
} catch {
|
|
54
|
+
console.warn(`[Kernel:Lifecycle] Unresolved schema for ${moduleId} at: ${p}`);
|
|
55
|
+
}
|
|
54
56
|
console.warn(`[Kernel:Lifecycle] Could not resolve schema path for: ${moduleId}`);
|
|
55
57
|
return null;
|
|
56
58
|
}
|
|
@@ -105,12 +107,10 @@ async function performToggle(moduleId, isEnabled) {
|
|
|
105
107
|
const dep = allModules.find((m) => m.id === depId);
|
|
106
108
|
return dep && !dep.enabled && !dep.system;
|
|
107
109
|
});
|
|
108
|
-
if (pendingDeps.length > 0) {
|
|
109
|
-
await updateStep(moduleId,
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
await sleep(500);
|
|
113
|
-
}
|
|
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
114
|
}
|
|
115
115
|
}
|
|
116
116
|
await updateStep(moduleId, "Initializing...");
|
|
@@ -153,7 +153,7 @@ async function performToggle(moduleId, isEnabled) {
|
|
|
153
153
|
await updateStep(moduleId, `Deactivating dependents...`);
|
|
154
154
|
for (const dep of dependents) {
|
|
155
155
|
await performToggle(dep.id, false);
|
|
156
|
-
await sleep(
|
|
156
|
+
await sleep(500);
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
159
|
await updateStep(moduleId, "Deactivating...");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecycle.d.cts","names":[],"sources":["../../src/server/lifecycle.ts"],"mappings":";
|
|
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.d.mts","names":[],"sources":["../../src/server/lifecycle.ts"],"mappings":";
|
|
1
|
+
{"version":3,"file":"lifecycle.d.mts","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"}
|
|
@@ -47,7 +47,9 @@ async function resolveSchemaPath(moduleId) {
|
|
|
47
47
|
await fs.access(p);
|
|
48
48
|
console.log(`[Kernel:Lifecycle] Resolved schema for ${moduleId} at: ${p}`);
|
|
49
49
|
return p;
|
|
50
|
-
} catch {
|
|
50
|
+
} catch {
|
|
51
|
+
console.warn(`[Kernel:Lifecycle] Unresolved schema for ${moduleId} at: ${p}`);
|
|
52
|
+
}
|
|
51
53
|
console.warn(`[Kernel:Lifecycle] Could not resolve schema path for: ${moduleId}`);
|
|
52
54
|
return null;
|
|
53
55
|
}
|
|
@@ -102,12 +104,10 @@ async function performToggle(moduleId, isEnabled) {
|
|
|
102
104
|
const dep = allModules.find((m) => m.id === depId);
|
|
103
105
|
return dep && !dep.enabled && !dep.system;
|
|
104
106
|
});
|
|
105
|
-
if (pendingDeps.length > 0) {
|
|
106
|
-
await updateStep(moduleId,
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
await sleep(500);
|
|
110
|
-
}
|
|
107
|
+
if (pendingDeps.length > 0) for (const depId of pendingDeps) {
|
|
108
|
+
await updateStep(moduleId, `Waiting for dependency "${depId}"...`);
|
|
109
|
+
await performToggle(depId, true);
|
|
110
|
+
await sleep(500);
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
113
|
await updateStep(moduleId, "Initializing...");
|
|
@@ -150,7 +150,7 @@ async function performToggle(moduleId, isEnabled) {
|
|
|
150
150
|
await updateStep(moduleId, `Deactivating dependents...`);
|
|
151
151
|
for (const dep of dependents) {
|
|
152
152
|
await performToggle(dep.id, false);
|
|
153
|
-
await sleep(
|
|
153
|
+
await sleep(500);
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
await updateStep(moduleId, "Deactivating...");
|
|
@@ -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 }\n\n console.warn(\n `[Kernel:Lifecycle] Could not resolve schema path for: ${moduleId}`,\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 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 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(1000);\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\";\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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"}
|
package/dist/server/ui.d.cts.map
CHANGED
|
@@ -1 +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,
|
|
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.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.d.mts","names":[],"sources":["../../src/server/ui.ts"],"mappings":";;;iBAqDsB,0BAAA,CAA2B,IAAA,yBAA0B,OAAA,CAAA,MAAA,SAAA,gBAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"ui.d.mts","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 // await ensureSystemInitialized();\n // const { getCurrentSession } = await import(\"../auth/session\");\n // const { getModules, getModuleInstance } = await import(\"./manage\");\n\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\n // if (!instance?.navigation?.[type]) {\n // const navModule = await import(`@/modules/${mod.id}/navigation`).catch(\n // () => null,\n // );\n // if (navModule?.navigation?.[type]) {\n // const items = navModule.navigation[type] as ModuleNavElement[];\n // for (const rawItem of items) {\n // const item = filterNavItem(rawItem, userRoles, userPermissions);\n // if (item) {\n // all.push(item);\n // }\n // }\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 } else {\n // 2. Try loading from a dedicated routes file (better for bundling)\n // const routesModule = await import(`@/modules/${mod.id}/routes`).catch(\n // () => null,\n // );\n // if (routesModule?.publicRoutes) {\n // allRoutes.push(...routesModule.publicRoutes);\n // }\n }\n } catch {}\n }\n return allRoutes;\n}\n\nexport async function getPrivateModuleRoutes(): Promise<\n PrivateRouteDefinition[]\n> {\n // await ensureSystemInitialized();\n // const { getModules, getModuleInstance } = await import(\"./manage\");\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 } else {\n // 2. Try from routes file\n // const routesModule = await import(`@/modules/${mod.id}/routes`).catch(\n // () => null,\n // );\n // if (routesModule?.privateRoutes) {\n // allRoutes.push(...routesModule.privateRoutes);\n // }\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 // await ensureSystemInitialized();\n // const { getModules, getModuleInstance } = await import(\"./manage\");\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 // await ensureSystemInitialized();\n // const { getModules, getModuleInstance } = await import(\"./manage\");\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 // await ensureSystemInitialized();\n // const { getModules, getModuleInstance } = await import(\"./manage\");\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 // await ensureSystemInitialized();\n // const { getModules, getModuleInstance } = await import(\"./manage\");\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\";\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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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arch-cadre/modules",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.16",
|
|
4
4
|
"description": "Core Modules for Kryo framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -27,19 +27,19 @@
|
|
|
27
27
|
"build": "tsdown"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@arch-cadre/core": "^0.0.
|
|
30
|
+
"@arch-cadre/core": "^0.0.16",
|
|
31
31
|
"server-only": "^0.0.1",
|
|
32
32
|
"zod": "^4.1.12"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
|
-
"@arch-cadre/core": "^0.0.
|
|
36
|
-
"drizzle-orm": "1.0.0-beta.
|
|
35
|
+
"@arch-cadre/core": "^0.0.16",
|
|
36
|
+
"drizzle-orm": "1.0.0-beta.6-4414a19",
|
|
37
37
|
"next": ">=15.0.0",
|
|
38
38
|
"react": "^19.0.0",
|
|
39
39
|
"react-dom": "^19.0.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@arch-cadre/core": "^0.0.
|
|
42
|
+
"@arch-cadre/core": "^0.0.16",
|
|
43
43
|
"@types/react": "^19",
|
|
44
44
|
"@types/react-dom": "^19",
|
|
45
45
|
"tsdown": "^0.20.3",
|