@celilo/cli 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/cli/commands/events.test.ts +2 -2
- package/src/config/paths.ts +4 -3
- package/src/module/import.ts +32 -7
- package/src/services/celilo-events.test.ts +3 -3
- package/src/services/events-daemon.test.ts +3 -3
- package/src/services/events-daemon.ts +2 -2
- package/src/services/module-subscriptions.test.ts +2 -2
package/package.json
CHANGED
|
@@ -22,10 +22,10 @@ describe('celilo events command handlers', () => {
|
|
|
22
22
|
beforeEach(() => {
|
|
23
23
|
dir = mkdtempSync(join(tmpdir(), 'events-cmd-test-'));
|
|
24
24
|
dbPath = join(dir, 'events.db');
|
|
25
|
-
process.env.
|
|
25
|
+
process.env.EVENT_BUS_DB = dbPath;
|
|
26
26
|
});
|
|
27
27
|
afterEach(() => {
|
|
28
|
-
process.env.
|
|
28
|
+
process.env.EVENT_BUS_DB = undefined;
|
|
29
29
|
try {
|
|
30
30
|
rmSync(dir, { recursive: true, force: true });
|
|
31
31
|
} catch {
|
package/src/config/paths.ts
CHANGED
|
@@ -96,7 +96,8 @@ export function getDbPath(): string {
|
|
|
96
96
|
* Get the SQLite event-bus database file path.
|
|
97
97
|
*
|
|
98
98
|
* Priority:
|
|
99
|
-
* 1.
|
|
99
|
+
* 1. EVENT_BUS_DB environment variable (the bus library's native name —
|
|
100
|
+
* used by the event-bus CLI, defineHandler, and any standalone tool)
|
|
100
101
|
* 2. <data-dir>/events.db (platform-specific)
|
|
101
102
|
*
|
|
102
103
|
* Kept separate from the main celilo.db so the bus library remains
|
|
@@ -105,8 +106,8 @@ export function getDbPath(): string {
|
|
|
105
106
|
* @returns Absolute path to event-bus database
|
|
106
107
|
*/
|
|
107
108
|
export function getEventBusPath(): string {
|
|
108
|
-
if (process.env.
|
|
109
|
-
return process.env.
|
|
109
|
+
if (process.env.EVENT_BUS_DB) {
|
|
110
|
+
return process.env.EVENT_BUS_DB;
|
|
110
111
|
}
|
|
111
112
|
return join(getDataDir(), 'events.db');
|
|
112
113
|
}
|
package/src/module/import.ts
CHANGED
|
@@ -23,6 +23,25 @@ import {
|
|
|
23
23
|
import { parseJsonWithValidation } from '../validation/schemas';
|
|
24
24
|
import { cleanupTempDir, extractPackage, verifyPackageIntegrity } from './packaging/extract';
|
|
25
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Phase-timing helper for `celilo module import`. Set CELILO_IMPORT_DEBUG=1
|
|
28
|
+
* to get a phase-by-phase breakdown to stderr — useful when an import is
|
|
29
|
+
* inexplicably slow (e.g. a Docker bind-mount fsync amplification, a stale
|
|
30
|
+
* lockfile triggering a fresh bun install, etc.).
|
|
31
|
+
*
|
|
32
|
+
* Zero overhead when disabled: the wrapper just calls the inner fn.
|
|
33
|
+
*/
|
|
34
|
+
async function timedPhase<T>(label: string, fn: () => Promise<T> | T): Promise<T> {
|
|
35
|
+
if (!process.env.CELILO_IMPORT_DEBUG) return await fn();
|
|
36
|
+
const start = Date.now();
|
|
37
|
+
try {
|
|
38
|
+
return await fn();
|
|
39
|
+
} finally {
|
|
40
|
+
const ms = Date.now() - start;
|
|
41
|
+
process.stderr.write(`[import-timing] ${label.padEnd(36)} ${ms}ms\n`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
26
45
|
/**
|
|
27
46
|
* Module import options
|
|
28
47
|
*/
|
|
@@ -547,7 +566,7 @@ export async function importModule(options: ModuleImportOptions): Promise<Module
|
|
|
547
566
|
|
|
548
567
|
// Execution: Copy files
|
|
549
568
|
try {
|
|
550
|
-
await copyModuleFiles(actualSourcePath, targetPath);
|
|
569
|
+
await timedPhase('copyModuleFiles', () => copyModuleFiles(actualSourcePath, targetPath));
|
|
551
570
|
} catch (error) {
|
|
552
571
|
if (tempDir) await cleanupTempDir(tempDir);
|
|
553
572
|
return {
|
|
@@ -563,7 +582,9 @@ export async function importModule(options: ModuleImportOptions): Promise<Module
|
|
|
563
582
|
// If no package.json exists but hook scripts do, auto-generate one with
|
|
564
583
|
// just the framework dep — smooths migration for existing modules.
|
|
565
584
|
try {
|
|
566
|
-
await installScriptDependencies
|
|
585
|
+
await timedPhase('installScriptDependencies', () =>
|
|
586
|
+
installScriptDependencies(targetPath, manifest),
|
|
587
|
+
);
|
|
567
588
|
} catch (error) {
|
|
568
589
|
// Non-fatal: the module is importable without deps, but hooks
|
|
569
590
|
// will fail at runtime. Warn and continue.
|
|
@@ -574,7 +595,7 @@ export async function importModule(options: ModuleImportOptions): Promise<Module
|
|
|
574
595
|
|
|
575
596
|
// Execution: Insert to database
|
|
576
597
|
try {
|
|
577
|
-
await insertModuleToDb(manifest, targetPath, db);
|
|
598
|
+
await timedPhase('insertModuleToDb', () => insertModuleToDb(manifest, targetPath, db));
|
|
578
599
|
} catch (error) {
|
|
579
600
|
if (tempDir) await cleanupTempDir(tempDir);
|
|
580
601
|
return {
|
|
@@ -586,8 +607,10 @@ export async function importModule(options: ModuleImportOptions): Promise<Module
|
|
|
586
607
|
|
|
587
608
|
// Execution: Register capabilities if module provides them
|
|
588
609
|
if (manifest.provides?.capabilities && manifest.provides.capabilities.length > 0) {
|
|
589
|
-
const
|
|
590
|
-
|
|
610
|
+
const capResult = await timedPhase('registerModuleCapabilities', async () => {
|
|
611
|
+
const { registerModuleCapabilities } = await import('../capabilities/registration');
|
|
612
|
+
return registerModuleCapabilities(manifest.id, manifest, db.$client, flags);
|
|
613
|
+
});
|
|
591
614
|
|
|
592
615
|
if (!capResult.success) {
|
|
593
616
|
if (tempDir) await cleanupTempDir(tempDir);
|
|
@@ -604,8 +627,10 @@ export async function importModule(options: ModuleImportOptions): Promise<Module
|
|
|
604
627
|
// can re-run the import after fixing the bus, and bus.subscribe is
|
|
605
628
|
// idempotent.
|
|
606
629
|
try {
|
|
607
|
-
|
|
608
|
-
|
|
630
|
+
await timedPhase('registerModuleSubscriptions', async () => {
|
|
631
|
+
const { registerModuleSubscriptions } = await import('../services/module-subscriptions');
|
|
632
|
+
registerModuleSubscriptions(manifest, targetPath);
|
|
633
|
+
});
|
|
609
634
|
} catch (error) {
|
|
610
635
|
const msg = error instanceof Error ? error.message : String(error);
|
|
611
636
|
log.warn(`Failed to register event-bus subscriptions: ${msg}`);
|
|
@@ -17,10 +17,10 @@ describe('celilo lifecycle events', () => {
|
|
|
17
17
|
beforeEach(() => {
|
|
18
18
|
dir = mkdtempSync(join(tmpdir(), 'celilo-events-test-'));
|
|
19
19
|
dbPath = join(dir, 'events.db');
|
|
20
|
-
process.env.
|
|
20
|
+
process.env.EVENT_BUS_DB = dbPath;
|
|
21
21
|
});
|
|
22
22
|
afterEach(() => {
|
|
23
|
-
process.env.
|
|
23
|
+
process.env.EVENT_BUS_DB = undefined;
|
|
24
24
|
try {
|
|
25
25
|
rmSync(dir, { recursive: true, force: true });
|
|
26
26
|
} catch {
|
|
@@ -92,7 +92,7 @@ describe('celilo lifecycle events', () => {
|
|
|
92
92
|
});
|
|
93
93
|
|
|
94
94
|
it('does not throw when the bus path is unwritable', () => {
|
|
95
|
-
process.env.
|
|
95
|
+
process.env.EVENT_BUS_DB = '/proc/no/such/place/events.db';
|
|
96
96
|
expect(() => emitDeployStarted({ module: 'x', startedAt: 0 })).not.toThrow();
|
|
97
97
|
});
|
|
98
98
|
});
|
|
@@ -23,7 +23,7 @@ describe('renderSystemdUnit', () => {
|
|
|
23
23
|
expect(out).toContain(
|
|
24
24
|
'ExecStart=/usr/local/bin/celilo events run --poll-ms 1000 --concurrency 4',
|
|
25
25
|
);
|
|
26
|
-
expect(out).toContain('Environment=
|
|
26
|
+
expect(out).toContain('Environment=EVENT_BUS_DB=/var/lib/celilo/events.db');
|
|
27
27
|
expect(out).toContain('Restart=on-failure');
|
|
28
28
|
expect(out).toContain('WantedBy=default.target');
|
|
29
29
|
});
|
|
@@ -141,9 +141,9 @@ describe('installDaemon / uninstallDaemon roundtrip', () => {
|
|
|
141
141
|
pollMs: 500,
|
|
142
142
|
});
|
|
143
143
|
const written = readFileSync(second.unitPath, 'utf-8');
|
|
144
|
-
expect(written).toContain('
|
|
144
|
+
expect(written).toContain('EVENT_BUS_DB=/db2');
|
|
145
145
|
expect(written).toContain('--poll-ms 500');
|
|
146
|
-
expect(written).not.toContain('
|
|
146
|
+
expect(written).not.toContain('EVENT_BUS_DB=/db1');
|
|
147
147
|
});
|
|
148
148
|
|
|
149
149
|
it('uninstall on a missing unit reports not-removed', () => {
|
|
@@ -119,7 +119,7 @@ Type=simple
|
|
|
119
119
|
ExecStart=${input.celiloPath} events run --poll-ms ${input.pollMs} --concurrency ${input.concurrency}
|
|
120
120
|
Restart=on-failure
|
|
121
121
|
RestartSec=10s
|
|
122
|
-
Environment=
|
|
122
|
+
Environment=EVENT_BUS_DB=${input.busDbPath}
|
|
123
123
|
# stdout/stderr are captured by journalctl --user -u celilo-events.service.
|
|
124
124
|
StandardOutput=journal
|
|
125
125
|
StandardError=journal
|
|
@@ -151,7 +151,7 @@ export function renderLaunchdPlist(input: UnitInputs): string {
|
|
|
151
151
|
</array>
|
|
152
152
|
<key>EnvironmentVariables</key>
|
|
153
153
|
<dict>
|
|
154
|
-
<key>
|
|
154
|
+
<key>EVENT_BUS_DB</key>
|
|
155
155
|
<string>${input.busDbPath}</string>
|
|
156
156
|
</dict>
|
|
157
157
|
<key>RunAtLoad</key>
|
|
@@ -78,10 +78,10 @@ describe('register / unregister roundtrip', () => {
|
|
|
78
78
|
beforeEach(() => {
|
|
79
79
|
dir = mkdtempSync(join(tmpdir(), 'modsubs-test-'));
|
|
80
80
|
dbPath = join(dir, 'events.db');
|
|
81
|
-
process.env.
|
|
81
|
+
process.env.EVENT_BUS_DB = dbPath;
|
|
82
82
|
});
|
|
83
83
|
afterEach(() => {
|
|
84
|
-
process.env.
|
|
84
|
+
process.env.EVENT_BUS_DB = undefined;
|
|
85
85
|
try {
|
|
86
86
|
rmSync(dir, { recursive: true, force: true });
|
|
87
87
|
} catch {
|