@cosmicdrift/kumiko-cli 0.387.0 → 0.388.0
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 +11 -11
- package/src/changes.json +6 -0
- package/src/commands/agent.ts +6 -3
- package/src/commands/check-managed.ts +20 -2
- package/src/commands/check-scripts.ts +9 -1
- package/src/commands/load-app-config.ts +3 -6
- package/src/commands/ops/backfill-pii.ts +11 -9
- package/src/commands/ops/waitlist-migrate.ts +1 -1
- package/src/commands/sync-managed.ts +9 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.388.0",
|
|
4
4
|
"description": "CLI for Kumiko apps. `bunx @cosmicdrift/kumiko-cli new app <name>` scaffolds a runnable workspace; `add feature <name>` mounts a feature; `check` runs boot validation plus the guard suites with the step list derived from kumiko.json; `agent lint`, `project` and `consumer` operate on an existing app; `handbuch build` renders the HTML handbuch.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -36,18 +36,18 @@
|
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@cosmicdrift/kumiko-dev-server": "0.
|
|
40
|
-
"@cosmicdrift/kumiko-guards": "0.
|
|
41
|
-
"@cosmicdrift/kumiko-server-runtime": "0.
|
|
42
|
-
"@cosmicdrift/kumiko-testing": "0.
|
|
39
|
+
"@cosmicdrift/kumiko-dev-server": "0.388.0",
|
|
40
|
+
"@cosmicdrift/kumiko-guards": "0.388.0",
|
|
41
|
+
"@cosmicdrift/kumiko-server-runtime": "0.388.0",
|
|
42
|
+
"@cosmicdrift/kumiko-testing": "0.388.0",
|
|
43
43
|
"marked": "^18.0.3",
|
|
44
44
|
"zod": "^4.4.3"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
47
|
"sharp": "^0.35.5",
|
|
48
|
-
"@cosmicdrift/kumiko-bundled-features": "0.
|
|
49
|
-
"@cosmicdrift/kumiko-framework": "0.
|
|
50
|
-
"@cosmicdrift/kumiko-renderer": "0.
|
|
48
|
+
"@cosmicdrift/kumiko-bundled-features": "0.388.0",
|
|
49
|
+
"@cosmicdrift/kumiko-framework": "0.388.0",
|
|
50
|
+
"@cosmicdrift/kumiko-renderer": "0.388.0"
|
|
51
51
|
},
|
|
52
52
|
"peerDependenciesMeta": {
|
|
53
53
|
"sharp": {
|
|
@@ -64,9 +64,9 @@
|
|
|
64
64
|
}
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
|
-
"@cosmicdrift/kumiko-bundled-features": "0.
|
|
68
|
-
"@cosmicdrift/kumiko-framework": "0.
|
|
69
|
-
"@cosmicdrift/kumiko-renderer": "0.
|
|
67
|
+
"@cosmicdrift/kumiko-bundled-features": "0.388.0",
|
|
68
|
+
"@cosmicdrift/kumiko-framework": "0.388.0",
|
|
69
|
+
"@cosmicdrift/kumiko-renderer": "0.388.0",
|
|
70
70
|
"sharp": "^0.35.5"
|
|
71
71
|
},
|
|
72
72
|
"publishConfig": {
|
package/src/changes.json
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.388.0",
|
|
4
|
+
"type": "fix",
|
|
5
|
+
"title": "check, sync-managed and backfill-pii handle failure and subdirectories correctly",
|
|
6
|
+
"detail": "kumiko check only warns about unresolvable managed files or package.json scripts until kumiko.config.ts calls defineAppConfig. sync-managed resolves the repo root like check instead of using cwd. ops backfill-pii closes the KMS wiring when registry creation fails. The agent command reuses allAppFeatures from the framework config."
|
|
7
|
+
},
|
|
2
8
|
{
|
|
3
9
|
"version": "0.379.0",
|
|
4
10
|
"type": "improvement",
|
package/src/commands/agent.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
|
-
import {
|
|
2
|
+
import { allAppFeatures } from "@cosmicdrift/kumiko-framework/config";
|
|
3
|
+
import { loadAppConfig } from "./load-app-config";
|
|
3
4
|
import type { CliCommand } from "./types";
|
|
4
5
|
|
|
5
6
|
const LINT_SUBCOMMAND = "lint";
|
|
@@ -26,7 +27,9 @@ export const agentCommand: CliCommand = {
|
|
|
26
27
|
ctx.out.err(" // kumiko.config.ts");
|
|
27
28
|
ctx.out.err(' import { defineAppConfig } from "@cosmicdrift/kumiko-framework/config";');
|
|
28
29
|
ctx.out.err(' import { myFeature } from "./src/features/my-feature";');
|
|
29
|
-
ctx.out.err(
|
|
30
|
+
ctx.out.err(
|
|
31
|
+
' export default defineAppConfig({ features: [myFeature], client: { entries: ["src/client.tsx"] }, ports: { dev: 4173, e2e: 4174 } });',
|
|
32
|
+
);
|
|
30
33
|
ctx.out.err("");
|
|
31
34
|
return 1;
|
|
32
35
|
}
|
|
@@ -37,7 +40,7 @@ export const agentCommand: CliCommand = {
|
|
|
37
40
|
"@cosmicdrift/kumiko-bundled-features/agent-tools"
|
|
38
41
|
);
|
|
39
42
|
|
|
40
|
-
const features =
|
|
43
|
+
const features = allAppFeatures(config);
|
|
41
44
|
const gaps = findAgentDocGaps(features);
|
|
42
45
|
const translationGaps = findHandlerTranslationGaps(features);
|
|
43
46
|
|
|
@@ -35,8 +35,26 @@ export async function runManagedCheckStep(
|
|
|
35
35
|
uiRoots: readonly string[],
|
|
36
36
|
): Promise<number> {
|
|
37
37
|
const managed: ManagedFilesModule = await import("@cosmicdrift/kumiko-dev-server/managed-files");
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
let result: ReturnType<ManagedFilesModule["checkManagedFiles"]>;
|
|
39
|
+
try {
|
|
40
|
+
result = managed.checkManagedFiles(
|
|
41
|
+
managed.resolveManagedAppFacts({ appRoot: repoRoot, uiRoots }),
|
|
42
|
+
);
|
|
43
|
+
} catch (error) {
|
|
44
|
+
// Before defineAppConfig is adopted the managed step only warns, also when the facts cannot be resolved.
|
|
45
|
+
if (managed.readStaticAppConfig(repoRoot).kind === "defined") throw error;
|
|
46
|
+
out.log(` ! ${error instanceof Error ? error.message : String(error)}`);
|
|
47
|
+
out.log(` ${NOT_ADOPTED_NOTE}`);
|
|
48
|
+
return 0;
|
|
49
|
+
}
|
|
50
|
+
return reportManagedCheck(out, managed, result);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function reportManagedCheck(
|
|
54
|
+
out: Output,
|
|
55
|
+
managed: ManagedFilesModule,
|
|
56
|
+
result: ReturnType<ManagedFilesModule["checkManagedFiles"]>,
|
|
57
|
+
): number {
|
|
40
58
|
const drift = result.files.filter(managed.isManagedDrift);
|
|
41
59
|
const local = result.files.filter((report) => report.state === "local");
|
|
42
60
|
const okCount = result.files.length - drift.length - local.length;
|
|
@@ -28,8 +28,16 @@ export async function runScriptsCheckStep(
|
|
|
28
28
|
uiRoots: readonly string[],
|
|
29
29
|
): Promise<number> {
|
|
30
30
|
const managed: ManagedFilesModule = await import("@cosmicdrift/kumiko-dev-server/managed-files");
|
|
31
|
-
const report = managed.checkAppScripts(readScripts(repoRoot), { hasUi: uiRoots.length > 0 });
|
|
32
31
|
const adopted = managed.readStaticAppConfig(repoRoot).kind === "defined";
|
|
32
|
+
let scripts: Record<string, string>;
|
|
33
|
+
try {
|
|
34
|
+
scripts = readScripts(repoRoot);
|
|
35
|
+
} catch (error) {
|
|
36
|
+
if (adopted) throw error;
|
|
37
|
+
out.log(` ! ${error instanceof Error ? error.message : String(error)}`);
|
|
38
|
+
return 0;
|
|
39
|
+
}
|
|
40
|
+
const report = managed.checkAppScripts(scripts, { hasUi: uiRoots.length > 0 });
|
|
33
41
|
if (report.knownExtras.length > 0)
|
|
34
42
|
out.log(` extras (standard): ${report.knownExtras.join(", ")}`);
|
|
35
43
|
if (report.appExtras.length > 0) out.log(` extras (app): ${report.appExtras.join(", ")}`);
|
|
@@ -20,11 +20,6 @@ function isAppConfig(value: unknown): value is AppConfig {
|
|
|
20
20
|
);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
/** Everything prod mounts: lint and docs checks must see the prod-only features too. */
|
|
24
|
-
export function allConfiguredFeatures(config: AppConfig): readonly FeatureDefinition[] {
|
|
25
|
-
return [...config.features, ...(config.prodFeatures ?? [])];
|
|
26
|
-
}
|
|
27
|
-
|
|
28
23
|
// kumiko.config.ts is user-authored: a missing default export or `features`
|
|
29
24
|
// array must produce a readable message, not a TypeError further down.
|
|
30
25
|
export async function loadAppConfig(
|
|
@@ -38,7 +33,9 @@ export async function loadAppConfig(
|
|
|
38
33
|
ctx.out.err("");
|
|
39
34
|
ctx.out.err(` ${configPath} must default-export an object with a "features" array:`);
|
|
40
35
|
ctx.out.err(' import { defineAppConfig } from "@cosmicdrift/kumiko-framework/config";');
|
|
41
|
-
ctx.out.err(
|
|
36
|
+
ctx.out.err(
|
|
37
|
+
' export default defineAppConfig({ features: [myFeature], client: { entries: ["src/client.tsx"] }, ports: { dev: 4173, e2e: 4174 } });',
|
|
38
|
+
);
|
|
42
39
|
ctx.out.err("");
|
|
43
40
|
return null;
|
|
44
41
|
}
|
|
@@ -219,20 +219,22 @@ export async function runBackfillPii(ctx: CliCommandContext): Promise<number> {
|
|
|
219
219
|
ctx.out.err(errorMessage(e));
|
|
220
220
|
return 1;
|
|
221
221
|
}
|
|
222
|
-
crypto.configurePiiSubjectKms(wiring.kms);
|
|
223
|
-
crypto.configureBlindIndexKey(wiring.blindIndexKey);
|
|
224
|
-
|
|
225
|
-
const registry = createRegistry(config.features);
|
|
226
|
-
const { db, close } = createDbConnection({ url: databaseUrl, maxConnections: 4 });
|
|
227
222
|
try {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
223
|
+
crypto.configurePiiSubjectKms(wiring.kms);
|
|
224
|
+
crypto.configureBlindIndexKey(wiring.blindIndexKey);
|
|
225
|
+
const registry = createRegistry(config.features);
|
|
226
|
+
const { db, close } = createDbConnection({ url: databaseUrl, maxConnections: 4 });
|
|
227
|
+
try {
|
|
228
|
+
return args.mode === "rebuild"
|
|
229
|
+
? await rebuildPiiProjections(ctx, db, registry, crypto)
|
|
230
|
+
: await backfillPii(ctx, db, registry, args);
|
|
231
|
+
} finally {
|
|
232
|
+
await close();
|
|
233
|
+
}
|
|
231
234
|
} catch (e) {
|
|
232
235
|
ctx.out.err(`${LOG_PREFIX} ${errorMessage(e)}`);
|
|
233
236
|
return 1;
|
|
234
237
|
} finally {
|
|
235
|
-
await close();
|
|
236
238
|
// The KMS pool keeps the process alive otherwise.
|
|
237
239
|
await wiring.close();
|
|
238
240
|
}
|
|
@@ -57,7 +57,7 @@ export const waitlistMigrateOp = {
|
|
|
57
57
|
});
|
|
58
58
|
ctx.out.log("");
|
|
59
59
|
ctx.out.log(
|
|
60
|
-
` ${dryRun ? "[dry-run] " : ""}waitlist-migrate --from ${from}: read ${report.read}, ${dryRun ? "would create" : "created"} ${report.created}, already present ${report.skipped}, unreadable ${report.unreadable}, legacy streams archived ${report.archivedStreams}`,
|
|
60
|
+
` ${dryRun ? "[dry-run] " : ""}waitlist-migrate --from ${from}: read ${report.read}, ${dryRun ? "would create" : "created"} ${report.created}, already present ${report.skipped}, unreadable ${report.unreadable}, legacy streams ${dryRun ? "would archive" : "archived"} ${report.archivedStreams}`,
|
|
61
61
|
);
|
|
62
62
|
ctx.out.log("");
|
|
63
63
|
return report.unreadable > 0 ? 1 : 0;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { REPO_MANIFEST_FILE } from "../repo-manifest";
|
|
2
2
|
import type { CliCommand, CliCommandContext } from "./types";
|
|
3
3
|
|
|
4
4
|
const SYNC_FLAGS = ["--write", "--adopt"] as const;
|
|
@@ -11,9 +11,13 @@ export async function runSyncManaged(ctx: CliCommandContext): Promise<number> {
|
|
|
11
11
|
);
|
|
12
12
|
return 1;
|
|
13
13
|
}
|
|
14
|
-
const {
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
const { findLocalRepo } = await import("@cosmicdrift/kumiko-guards");
|
|
15
|
+
const repo = findLocalRepo(ctx.cwd);
|
|
16
|
+
if (repo === undefined) {
|
|
17
|
+
ctx.out.err(` No Kumiko repo above ${ctx.cwd}. Add a ${REPO_MANIFEST_FILE} at the repo root.`);
|
|
18
|
+
return 1;
|
|
19
|
+
}
|
|
20
|
+
const { manifest } = repo;
|
|
17
21
|
if (manifest.kind !== "app") {
|
|
18
22
|
ctx.out.err(
|
|
19
23
|
` sync-managed needs kind "app" in ${REPO_MANIFEST_FILE}, got "${manifest.kind}".`,
|
|
@@ -23,7 +27,7 @@ export async function runSyncManaged(ctx: CliCommandContext): Promise<number> {
|
|
|
23
27
|
const write = ctx.argv.includes("--write");
|
|
24
28
|
const managed = await import("@cosmicdrift/kumiko-dev-server/managed-files");
|
|
25
29
|
const facts = managed.resolveManagedAppFacts({
|
|
26
|
-
appRoot:
|
|
30
|
+
appRoot: repo.absPath,
|
|
27
31
|
uiRoots: manifest.uiRoots ?? [],
|
|
28
32
|
});
|
|
29
33
|
for (const error of managed.listManagedErrors(facts)) ctx.out.err(` ✗ ${error}`);
|