@cosmicdrift/kumiko-cli 0.389.0 → 0.390.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/bin/kumiko-upgrade.ts
CHANGED
|
@@ -12,7 +12,9 @@ const appCwd = process.env["INIT_CWD"] ?? process.cwd();
|
|
|
12
12
|
try {
|
|
13
13
|
const { runUpgradeCli } = await import("@cosmicdrift/kumiko-framework/upgrade-cli");
|
|
14
14
|
// Let the event loop drain stdout (piped by guard-upgrade-state) before exit.
|
|
15
|
-
process.exitCode = await runUpgradeCli(process.argv.slice(2), appCwd, out
|
|
15
|
+
process.exitCode = await runUpgradeCli(process.argv.slice(2), appCwd, out, {
|
|
16
|
+
codemodResolveFrom: import.meta.dir,
|
|
17
|
+
});
|
|
16
18
|
} catch (error) {
|
|
17
19
|
const message = missingPeerMessage(error);
|
|
18
20
|
if (message === undefined) throw error;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.390.1",
|
|
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,19 @@
|
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@cosmicdrift/kumiko-dev-server": "0.
|
|
40
|
-
"@cosmicdrift/kumiko-
|
|
41
|
-
"@cosmicdrift/kumiko-
|
|
42
|
-
"@cosmicdrift/kumiko-
|
|
39
|
+
"@cosmicdrift/kumiko-dev-server": "0.390.1",
|
|
40
|
+
"@cosmicdrift/kumiko-feature-ast": "0.390.1",
|
|
41
|
+
"@cosmicdrift/kumiko-guards": "0.390.1",
|
|
42
|
+
"@cosmicdrift/kumiko-server-runtime": "0.390.1",
|
|
43
|
+
"@cosmicdrift/kumiko-testing": "0.390.1",
|
|
43
44
|
"marked": "^18.0.3",
|
|
44
|
-
"zod": "^4.
|
|
45
|
+
"zod": "^4.6.7"
|
|
45
46
|
},
|
|
46
47
|
"peerDependencies": {
|
|
47
48
|
"sharp": "^0.35.5",
|
|
48
|
-
"@cosmicdrift/kumiko-bundled-features": "0.
|
|
49
|
-
"@cosmicdrift/kumiko-framework": "0.
|
|
50
|
-
"@cosmicdrift/kumiko-renderer": "0.
|
|
49
|
+
"@cosmicdrift/kumiko-bundled-features": "0.390.1",
|
|
50
|
+
"@cosmicdrift/kumiko-framework": "0.390.1",
|
|
51
|
+
"@cosmicdrift/kumiko-renderer": "0.390.1"
|
|
51
52
|
},
|
|
52
53
|
"peerDependenciesMeta": {
|
|
53
54
|
"sharp": {
|
|
@@ -64,9 +65,9 @@
|
|
|
64
65
|
}
|
|
65
66
|
},
|
|
66
67
|
"devDependencies": {
|
|
67
|
-
"@cosmicdrift/kumiko-bundled-features": "0.
|
|
68
|
-
"@cosmicdrift/kumiko-framework": "0.
|
|
69
|
-
"@cosmicdrift/kumiko-renderer": "0.
|
|
68
|
+
"@cosmicdrift/kumiko-bundled-features": "0.390.1",
|
|
69
|
+
"@cosmicdrift/kumiko-framework": "0.390.1",
|
|
70
|
+
"@cosmicdrift/kumiko-renderer": "0.390.1",
|
|
70
71
|
"sharp": "^0.35.5"
|
|
71
72
|
},
|
|
72
73
|
"publishConfig": {
|
package/src/commands/codemod.ts
CHANGED
|
@@ -39,13 +39,13 @@ async function runCodemod(ctx: CliCommandContext): Promise<number> {
|
|
|
39
39
|
|
|
40
40
|
const { resolveCodemodScript } = await import("@cosmicdrift/kumiko-framework/upgrade-cli");
|
|
41
41
|
const scriptField = `scripts/codemod/${name}.ts`;
|
|
42
|
-
// The project's own install wins; the
|
|
42
|
+
// The project's own install wins; the feature-ast package next to this CLI is the fallback.
|
|
43
43
|
const script =
|
|
44
44
|
resolveCodemodScript(ctx.cwd, scriptField) ??
|
|
45
45
|
resolveCodemodScript(import.meta.dir, scriptField);
|
|
46
46
|
if (script === null) {
|
|
47
47
|
ctx.out.err(
|
|
48
|
-
" Codemod script not found. Install @cosmicdrift/kumiko-
|
|
48
|
+
" Codemod script not found. Install @cosmicdrift/kumiko-feature-ast in this project.",
|
|
49
49
|
);
|
|
50
50
|
return 1;
|
|
51
51
|
}
|
package/src/commands/consumer.ts
CHANGED
|
@@ -62,30 +62,44 @@ export const consumerCommand: CliCommand = {
|
|
|
62
62
|
SEARCH_CONSUMER_NAME,
|
|
63
63
|
...registry.getAllMultiStreamProjections().keys(),
|
|
64
64
|
];
|
|
65
|
+
const { runInSystemRowLevelSecurityScope } = await import(
|
|
66
|
+
"@cosmicdrift/kumiko-framework/internal/row-level-security"
|
|
67
|
+
);
|
|
65
68
|
const { db, close } = createDbConnection({ url: databaseUrl });
|
|
66
69
|
|
|
67
70
|
try {
|
|
68
71
|
await createEventConsumerStateTable(db);
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
72
|
+
return await runInSystemRowLevelSecurityScope(
|
|
73
|
+
"operator consumer tool skips poison events, which reads the events of every tenant",
|
|
74
|
+
async () => {
|
|
75
|
+
switch (sub) {
|
|
76
|
+
case "list":
|
|
77
|
+
return await listConsumers(ctx, db, registeredConsumerNames, listConsumersWithState);
|
|
78
|
+
case "status":
|
|
79
|
+
return await showConsumerStatus(
|
|
80
|
+
ctx,
|
|
81
|
+
db,
|
|
82
|
+
arg,
|
|
83
|
+
registeredConsumerNames,
|
|
84
|
+
getConsumerState,
|
|
85
|
+
);
|
|
86
|
+
case "restart":
|
|
87
|
+
return await transitionOne(ctx, "restart", arg, "restarted", (name) =>
|
|
88
|
+
restartConsumer(db, name),
|
|
89
|
+
);
|
|
90
|
+
case "disable":
|
|
91
|
+
return await transitionOne(ctx, "disable", arg, "disabled", (name) =>
|
|
92
|
+
disableConsumer(db, name),
|
|
93
|
+
);
|
|
94
|
+
case "enable":
|
|
95
|
+
return await transitionOne(ctx, "enable", arg, "enabled", (name) =>
|
|
96
|
+
enableConsumer(db, name),
|
|
97
|
+
);
|
|
98
|
+
case "skip":
|
|
99
|
+
return await skipOne(ctx, db, arg, skipPoisonEvent);
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
);
|
|
89
103
|
} catch (e) {
|
|
90
104
|
ctx.out.err("");
|
|
91
105
|
ctx.out.err(` ✗ ${e instanceof Error ? e.message : String(e)}`);
|
|
@@ -223,11 +223,18 @@ export async function runBackfillPii(ctx: CliCommandContext): Promise<number> {
|
|
|
223
223
|
crypto.configurePiiSubjectKms(wiring.kms);
|
|
224
224
|
crypto.configureBlindIndexKey(wiring.blindIndexKey);
|
|
225
225
|
const registry = createRegistry(config.features);
|
|
226
|
+
const { runInSystemRowLevelSecurityScope } = await import(
|
|
227
|
+
"@cosmicdrift/kumiko-framework/internal/row-level-security"
|
|
228
|
+
);
|
|
226
229
|
const { db, close } = createDbConnection({ url: databaseUrl, maxConnections: 4 });
|
|
227
230
|
try {
|
|
228
|
-
return
|
|
229
|
-
|
|
230
|
-
|
|
231
|
+
return await runInSystemRowLevelSecurityScope(
|
|
232
|
+
"operator PII backfill rewrites events and projections of every tenant",
|
|
233
|
+
() =>
|
|
234
|
+
args.mode === "rebuild"
|
|
235
|
+
? rebuildPiiProjections(ctx, db, registry, crypto)
|
|
236
|
+
: backfillPii(ctx, db, registry, args),
|
|
237
|
+
);
|
|
231
238
|
} finally {
|
|
232
239
|
await close();
|
|
233
240
|
}
|
|
@@ -68,6 +68,9 @@ export const waitlistMigrateOp = {
|
|
|
68
68
|
|
|
69
69
|
const dryRun = ctx.argv.includes("--dry-run");
|
|
70
70
|
const { createDbConnection } = await import("@cosmicdrift/kumiko-framework/db");
|
|
71
|
+
const { runInSystemRowLevelSecurityScope } = await import(
|
|
72
|
+
"@cosmicdrift/kumiko-framework/internal/row-level-security"
|
|
73
|
+
);
|
|
71
74
|
const { db, close } = createDbConnection({ url: checked.databaseUrl });
|
|
72
75
|
let wiring: Awaited<ReturnType<typeof wireKmsFromEnv>> | undefined;
|
|
73
76
|
try {
|
|
@@ -80,12 +83,16 @@ export const waitlistMigrateOp = {
|
|
|
80
83
|
allowPlaintextPii: flagValue(ctx.argv, "--allow-plaintext-pii"),
|
|
81
84
|
consequence: "The import would store personal data as plaintext in the event log.",
|
|
82
85
|
});
|
|
83
|
-
const report = await
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
86
|
+
const report = await runInSystemRowLevelSecurityScope(
|
|
87
|
+
"operator waitlist migration imports signups into the platform tenant and archives legacy streams",
|
|
88
|
+
() =>
|
|
89
|
+
migrateLegacyWaitlist(db, {
|
|
90
|
+
from,
|
|
91
|
+
dryRun,
|
|
92
|
+
sourceTable: flagValue(ctx.argv, "--source-table") ?? DEFAULT_LEGACY_SOURCE_TABLE[from],
|
|
93
|
+
defaultLocale: flagValue(ctx.argv, "--locale") ?? DEFAULT_IMPORT_LOCALE,
|
|
94
|
+
}),
|
|
95
|
+
);
|
|
89
96
|
ctx.out.log("");
|
|
90
97
|
ctx.out.log(
|
|
91
98
|
` ${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}`,
|
package/src/commands/project.ts
CHANGED
|
@@ -67,6 +67,9 @@ export const projectCommand: CliCommand = {
|
|
|
67
67
|
} = await import("@cosmicdrift/kumiko-framework/pipeline");
|
|
68
68
|
|
|
69
69
|
const registry = createRegistry(config.features);
|
|
70
|
+
const { runInSystemRowLevelSecurityScope } = await import(
|
|
71
|
+
"@cosmicdrift/kumiko-framework/internal/row-level-security"
|
|
72
|
+
);
|
|
70
73
|
const { db, close } = createDbConnection({ url: databaseUrl });
|
|
71
74
|
let wiring: Awaited<ReturnType<typeof wireKmsFromEnv>> | undefined;
|
|
72
75
|
|
|
@@ -80,14 +83,19 @@ export const projectCommand: CliCommand = {
|
|
|
80
83
|
});
|
|
81
84
|
}
|
|
82
85
|
await createProjectionStateTable(db);
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
86
|
+
return await runInSystemRowLevelSecurityScope(
|
|
87
|
+
"operator projection tool reads and rebuilds projections of every tenant",
|
|
88
|
+
async () => {
|
|
89
|
+
switch (sub) {
|
|
90
|
+
case "list":
|
|
91
|
+
return await listProjections(ctx, db, registry, listProjectionsWithState);
|
|
92
|
+
case "status":
|
|
93
|
+
return await showProjectionStatus(ctx, db, arg, registry, getProjectionState);
|
|
94
|
+
case "rebuild":
|
|
95
|
+
return await rebuildOne(ctx, db, arg, registry, rebuildProjection);
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
);
|
|
91
99
|
} catch (e) {
|
|
92
100
|
ctx.out.err("");
|
|
93
101
|
ctx.out.err(` ✗ ${e instanceof Error ? e.message : String(e)}`);
|