@cosmicdrift/kumiko-dev-server 0.367.0 → 0.368.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @cosmicdrift/kumiko-dev-server
2
2
 
3
- Dev tooling for Kumiko apps: local dev server (`runDevApp`), scaffolding and codegen, plus the `kumiko-*` build and schema commands.
3
+ Dev tooling for Kumiko apps: local dev server (`runDevApp`), scaffolding, plus the `kumiko-*` build and schema commands.
4
4
 
5
5
  ## Install
6
6
 
@@ -23,23 +23,19 @@ import {
23
23
  buildServerBundle,
24
24
  discoverServerEntry,
25
25
  formatBuildResult,
26
- formatScanWarning,
27
26
  formatServerBuildResult,
28
27
  readClientEntriesConfig,
29
28
  readExtraRuntimeExternals,
30
29
  resolveClientEntries,
31
- runCodegen,
32
30
  } from "@cosmicdrift/kumiko-dev-server/cli";
33
31
 
34
32
  if (process.argv.slice(2).some((arg) => arg === "--help" || arg === "-h")) {
35
33
  process.stdout.write(
36
- "Usage: kumiko-build [--check] [app-dir] build client (dist/) and server (dist-server/) bundles;\n" +
37
- " --check only verifies .kumiko/ is up to date (exit 1 on drift, writes nothing)\n",
34
+ "Usage: kumiko-build [app-dir] build client (dist/) and server (dist-server/) bundles\n",
38
35
  );
39
36
  process.exit(0);
40
37
  }
41
38
 
42
- const checkCodegenOnly = process.argv.includes("--check");
43
39
  const explicit = process.argv.slice(2).find((arg) => !arg.startsWith("-"));
44
40
  const cwd = explicit ? resolve(process.cwd(), explicit) : process.cwd();
45
41
 
@@ -47,20 +43,6 @@ const red = "\x1b[31m";
47
43
  const yellow = "\x1b[33m";
48
44
  const reset = "\x1b[0m";
49
45
 
50
- if (checkCodegenOnly) {
51
- const drift = runCodegen({ appRoot: cwd, checkOnly: true });
52
- for (const w of drift.warnings) {
53
- process.stderr.write(`${yellow}!${reset} [codegen] ${formatScanWarning(w)}\n`);
54
- }
55
- if (drift.didWriteTypes || drift.didWriteDefine || drift.didWriteSchemas) {
56
- process.stderr.write(
57
- `\n ${red}✗${reset} .kumiko/ is stale; run kumiko-build or the dev-server and commit.\n\n`,
58
- );
59
- process.exit(1);
60
- }
61
- process.exit(0);
62
- }
63
-
64
46
  try {
65
47
  // Read once up front — resolveClientEntries can throw (mutual exclusion,
66
48
  // malformed declaration, unmigrated legacy client-*.tsx files) and that
@@ -82,19 +64,6 @@ try {
82
64
  process.exit(1);
83
65
  }
84
66
 
85
- // Codegen-Pass vor dem Build — sicherstellt dass `.kumiko/define.ts`
86
- // und `types.generated.d.ts` synchron mit den r.defineEvent-Aufrufen
87
- // sind. Ohne diesen Pass würde ein veraltetes Wrapper-File ein
88
- // Build-Error oder schlimmer: einen Build mit stale Augmentation
89
- // erzeugen, der zur Laufzeit die falschen Events erlaubt.
90
- const cgResult = runCodegen({ appRoot: cwd });
91
- if (cgResult.warnings.length > 0) {
92
- for (const w of cgResult.warnings) {
93
- // biome-ignore lint/suspicious/noConsole: CLI-Output
94
- console.warn(`${yellow}!${reset} [codegen] ${formatScanWarning(w)}`);
95
- }
96
- }
97
-
98
67
  if (hasClient) {
99
68
  const t0 = performance.now();
100
69
  const result = await buildProdBundle({ cwd, ...declaredClientEntries });
package/dist/cli.d.ts CHANGED
@@ -1,4 +1,3 @@
1
1
  export { buildProdBundle, buildServerBundle, discoverServerEntry, formatBuildResult, formatServerBuildResult, readClientEntriesConfig, readExtraRuntimeExternals, resolveClientEntries, } from "./build.js";
2
- export { formatScanWarning, runCodegen } from "./codegen/index.js";
3
2
  export { createCrashTracker } from "./crash-tracker.js";
4
3
  export { runInitDeployCli } from "./init-deploy-cli.js";
package/dist/cli.js CHANGED
@@ -3,6 +3,5 @@
3
3
  // resolve to src in the workspace and to dist once installed from the
4
4
  // tarball, where `src` is not shipped.
5
5
  export { buildProdBundle, buildServerBundle, discoverServerEntry, formatBuildResult, formatServerBuildResult, readClientEntriesConfig, readExtraRuntimeExternals, resolveClientEntries, } from "./build.js";
6
- export { formatScanWarning, runCodegen } from "./codegen/index.js";
7
6
  export { createCrashTracker } from "./crash-tracker.js";
8
7
  export { runInitDeployCli } from "./init-deploy-cli.js";
@@ -8,21 +8,20 @@
8
8
  // Presets export feature instances only; no implicit PAT scopes, anonymousAccess,
9
9
  // or tier maps (those stay in bin/server.ts / app run-config).
10
10
  import { createAuditFeature } from "@cosmicdrift/kumiko-bundled-features/audit";
11
- import { authFoundationFeature } from "@cosmicdrift/kumiko-bundled-features/auth-foundation";
11
+ import { createAuthFoundationFeature } from "@cosmicdrift/kumiko-bundled-features/auth-foundation";
12
12
  import { createAuthMfaFeature, } from "@cosmicdrift/kumiko-bundled-features/auth-mfa";
13
13
  import { createComplianceProfilesFeature } from "@cosmicdrift/kumiko-bundled-features/compliance-profiles";
14
14
  import { createDataRetentionFeature } from "@cosmicdrift/kumiko-bundled-features/data-retention";
15
15
  import { createDeliveryFeature } from "@cosmicdrift/kumiko-bundled-features/delivery";
16
- import { fileFoundationFeature } from "@cosmicdrift/kumiko-bundled-features/file-foundation";
17
- import { fileProviderInMemoryFeature } from "@cosmicdrift/kumiko-bundled-features/file-provider-inmemory";
18
- import { fileProviderS3Feature } from "@cosmicdrift/kumiko-bundled-features/file-provider-s3";
19
- import { fileProviderS3EnvFeature } from "@cosmicdrift/kumiko-bundled-features/file-provider-s3-env";
16
+ import { createFileFoundationFeature } from "@cosmicdrift/kumiko-bundled-features/file-foundation";
17
+ import { createFileProviderInMemoryFeature } from "@cosmicdrift/kumiko-bundled-features/file-provider-inmemory";
18
+ import { createFileProviderS3Feature } from "@cosmicdrift/kumiko-bundled-features/file-provider-s3";
20
19
  import { createFilesFeature } from "@cosmicdrift/kumiko-bundled-features/files";
21
20
  import { createJobsFeature } from "@cosmicdrift/kumiko-bundled-features/jobs";
22
21
  import { createLegalPagesFeature, } from "@cosmicdrift/kumiko-bundled-features/legal-pages";
23
- import { mailFoundationFeature } from "@cosmicdrift/kumiko-bundled-features/mail-foundation";
24
- import { mailTransportInMemoryFeature } from "@cosmicdrift/kumiko-bundled-features/mail-transport-inmemory";
25
- import { mailTransportSmtpFeature } from "@cosmicdrift/kumiko-bundled-features/mail-transport-smtp";
22
+ import { createMailFoundationFeature } from "@cosmicdrift/kumiko-bundled-features/mail-foundation";
23
+ import { createMailTransportInMemoryFeature } from "@cosmicdrift/kumiko-bundled-features/mail-transport-inmemory";
24
+ import { createMailTransportSmtpFeature } from "@cosmicdrift/kumiko-bundled-features/mail-transport-smtp";
26
25
  import { createRateLimitingFeature } from "@cosmicdrift/kumiko-bundled-features/rate-limiting";
27
26
  import { createRendererFoundationFeature } from "@cosmicdrift/kumiko-bundled-features/renderer-foundation";
28
27
  import { createSessionsFeature } from "@cosmicdrift/kumiko-bundled-features/sessions";
@@ -55,24 +54,24 @@ export function composeRendererStack(options = {}) {
55
54
  ];
56
55
  }
57
56
  export function composeMailStack(options) {
58
- const out = [mailFoundationFeature];
57
+ const out = [createMailFoundationFeature()];
59
58
  for (const transport of options.transports) {
60
59
  if (transport === "inmemory")
61
- out.push(mailTransportInMemoryFeature);
60
+ out.push(createMailTransportInMemoryFeature());
62
61
  if (transport === "smtp")
63
- out.push(mailTransportSmtpFeature);
62
+ out.push(createMailTransportSmtpFeature());
64
63
  }
65
64
  return out;
66
65
  }
67
66
  export function composeFileStack(options) {
68
- const out = [fileFoundationFeature];
67
+ const out = [createFileFoundationFeature()];
69
68
  for (const provider of options.providers) {
70
69
  if (provider === "inmemory")
71
- out.push(fileProviderInMemoryFeature);
70
+ out.push(createFileProviderInMemoryFeature());
72
71
  if (provider === "s3")
73
- out.push(fileProviderS3Feature);
72
+ out.push(createFileProviderS3Feature());
74
73
  if (provider === "s3-env")
75
- out.push(fileProviderS3EnvFeature);
74
+ out.push(createFileProviderS3Feature({ fromEnv: true }));
76
75
  }
77
76
  if (options.includeFilesFeature ?? true)
78
77
  out.push(createFilesFeature());
@@ -87,7 +86,7 @@ export function composeGdprStack(options = {}) {
87
86
  if (options.tenantLifecycle)
88
87
  out.push(createTenantLifecycleFeature());
89
88
  if (options.sessions) {
90
- out.push(authFoundationFeature, createSessionsFeature());
89
+ out.push(createAuthFoundationFeature(), createSessionsFeature());
91
90
  if (options.providers)
92
91
  out.push(...options.providers);
93
92
  }
@@ -122,7 +121,7 @@ export function composeIdentityStack(options = {}) {
122
121
  const sessions = options.sessions ?? true;
123
122
  const out = [];
124
123
  if (sessions) {
125
- out.push(authFoundationFeature, createSessionsFeature());
124
+ out.push(createAuthFoundationFeature(), createSessionsFeature());
126
125
  }
127
126
  if (options.mfa !== undefined)
128
127
  out.push(createAuthMfaFeature(options.mfa));
@@ -2,9 +2,9 @@
2
2
  import { type AuthRoutesConfig, type ExtraRouteDefinition } from "@cosmicdrift/kumiko-framework/api";
3
3
  import { type FeatureDefinition } from "@cosmicdrift/kumiko-framework/engine";
4
4
  import type { ErrorDocsConfig } from "@cosmicdrift/kumiko-framework/errors";
5
- import { type TestStack, type TestStackOptions } from "@cosmicdrift/kumiko-framework/stack";
6
5
  import { type PageHeadResolver, type PageHeadSystemQuery } from "@cosmicdrift/kumiko-headless/apex";
7
6
  import { type SystemWireDeps } from "@cosmicdrift/kumiko-server-runtime/extra-routes-deps";
7
+ import { type TestStack, type TestStackOptions } from "@cosmicdrift/kumiko-testing/stack";
8
8
  type BunServer = typeof Bun extends undefined ? unknown : ReturnType<typeof Bun.serve>;
9
9
  export declare const logInfo: (msg: string) => void;
10
10
  /** Multi-entry mode for apps that ship several separate bundles (e.g.
@@ -24,7 +24,7 @@ import { AUTH_COOKIE_BASE, CSRF_COOKIE_BASE, createClientIpResolver, generateTok
24
24
  import { buildAppSchema } from "@cosmicdrift/kumiko-framework/engine";
25
25
  import { createEventsTable } from "@cosmicdrift/kumiko-framework/event-store";
26
26
  import { createMetricsForFactory } from "@cosmicdrift/kumiko-framework/observability";
27
- import { pushEntityProjectionTables, setupTestStack, TestUsers, } from "@cosmicdrift/kumiko-framework/stack";
27
+ import { TestUsers } from "@cosmicdrift/kumiko-framework/seeding";
28
28
  import { resolveAndInjectPageHead, } from "@cosmicdrift/kumiko-headless/apex";
29
29
  import { startDevJobRunners } from "@cosmicdrift/kumiko-server-runtime/boot/job-run-logger";
30
30
  import { buildBunServeOptions, resolveDerivedMaxRequestBodySize, } from "@cosmicdrift/kumiko-server-runtime/bun-serve-options";
@@ -33,6 +33,7 @@ import { RENDERER_WEB_FONT_FILE_PATTERN, RENDERER_WEB_FONTS_URL_PREFIX, resolveR
33
33
  import { buildRequestBoundSystemQuery } from "@cosmicdrift/kumiko-server-runtime/request-bound-system-query";
34
34
  import { canResolveTailwindStylesheet, resolveTailwindCli, } from "@cosmicdrift/kumiko-server-runtime/resolve-tailwind-cli";
35
35
  import { stripNoRouteMatchHeader, tryHonoFirst, } from "@cosmicdrift/kumiko-server-runtime/try-hono-first";
36
+ import { pushEntityProjectionTables, setupTestStack, } from "@cosmicdrift/kumiko-testing/stack";
36
37
  import { errorCodeOf } from "@cosmicdrift/kumiko-types/type-guards";
37
38
  import { isPersistentDevDb } from "./is-persistent-dev-db.js";
38
39
  // Runtime-detection. The dev-server is meant to run under Bun (Kumiko's
package/dist/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  export { type ComposeFeaturesOptions, composeFeatures, } from "@cosmicdrift/kumiko-server-runtime/compose-features";
2
- export { type CodegenOptions, type CodegenResult, runCodegen, type ScannedEvent, type ScanWarning, scanEvents, } from "./codegen/index.js";
3
2
  export { composeFileStack, composeGdprStack, composeIdentityStack, composeMailStack, composeOpsStack, composePagesStack, composeRendererStack, composeUserDataRightsStack, type FileProviderKind, type FileStackOptions, type GdprStackOptions, type GdprStackOrder, type IdentityStackOptions, type MailStackOptions, type MailTransportKind, type OpsStackOptions, type PagesStackOptions, stackFeatureNames, type UserDataRightsStackOptions, } from "./compose-stacks.js";
4
3
  export { type CreateKumikoServerOptions, createKumikoServer, type KumikoServerHandle, PROD_BUNDLES_ENV, resolveStylesheet, STYLESHEET_WATCH_ENV, } from "./create-kumiko-server.js";
5
4
  export { type FrameworkCoreEnv, frameworkCoreEnvSchema } from "./env-schema.js";
package/dist/index.js CHANGED
@@ -17,7 +17,6 @@ export { composeFeatures, } from "@cosmicdrift/kumiko-server-runtime/compose-fea
17
17
  // im Sub-Path-Export `@cosmicdrift/kumiko-dev-server/build`. Damit zieht der Main-Barrel
18
18
  // kein Bun-Toolchain-Bundle mehr in Production-Reads (z.B. wenn drizzle-kit
19
19
  // die App-Config unter Node lädt).
20
- export { runCodegen, scanEvents, } from "./codegen/index.js";
21
20
  export { composeFileStack, composeGdprStack, composeIdentityStack, composeMailStack, composeOpsStack, composePagesStack, composeRendererStack, composeUserDataRightsStack, stackFeatureNames, } from "./compose-stacks.js";
22
21
  export { createKumikoServer, PROD_BUNDLES_ENV, resolveStylesheet, STYLESHEET_WATCH_ENV, } from "./create-kumiko-server.js";
23
22
  export { frameworkCoreEnvSchema } from "./env-schema.js";
@@ -4,8 +4,8 @@ import { type KmsAdapter } from "@cosmicdrift/kumiko-framework/crypto";
4
4
  import { type FeatureDefinition, type Registry, type ValidateBootOptions } from "@cosmicdrift/kumiko-framework/engine";
5
5
  import type { ErrorDocsConfig } from "@cosmicdrift/kumiko-framework/errors";
6
6
  import type { EnvelopeCipher, MasterKeyProvider } from "@cosmicdrift/kumiko-framework/secrets";
7
- import type { TestStack } from "@cosmicdrift/kumiko-framework/stack";
8
7
  import type { PageHeadResolver } from "@cosmicdrift/kumiko-headless/apex";
8
+ import type { TestStack } from "@cosmicdrift/kumiko-testing/stack";
9
9
  import { type CreateKumikoServerOptions, type KumikoServerHandle } from "./create-kumiko-server.js";
10
10
  export type { AccountLockoutSetup, AccountUnlockSetup, AuthMailOptions, EmailVerificationSetup, InviteSetup, PasswordResetSetup, SignupSetup, } from "@cosmicdrift/kumiko-server-runtime/run-prod-app";
11
11
  import type { AccountLockoutSetup, AccountUnlockSetup, AuthMailOptions, EmailVerificationSetup, InviteSetup, PasswordResetSetup, SignupSetup } from "@cosmicdrift/kumiko-server-runtime/run-prod-app";
@@ -29,7 +29,6 @@ import { resolveBootCrypto } from "@cosmicdrift/kumiko-server-runtime/boot/boot-
29
29
  import { buildComposeAuthOptions, composeFeatures, } from "@cosmicdrift/kumiko-server-runtime/compose-features";
30
30
  import { assertPiiBootInvariants } from "@cosmicdrift/kumiko-server-runtime/pii-boot-gate";
31
31
  import { assertSessionBootInvariants } from "@cosmicdrift/kumiko-server-runtime/session-boot-gate";
32
- import { watchAndRegenerate } from "./codegen/index.js";
33
32
  import { createKumikoServer, logInfo, } from "./create-kumiko-server.js";
34
33
  import { captureEphemeralDevPiiKms, resolveDevPiiKms } from "./resolve-dev-pii-kms.js";
35
34
  import { renderWelcomeBanner } from "./welcome-banner.js";
@@ -62,11 +61,11 @@ export async function runDevApp(options) {
62
61
  env: { ...baseBootEnv, [FILE_STORAGE_PROVIDER_ENV]: FILE_STORAGE_PROVIDER_BOOT_SENTINEL },
63
62
  }
64
63
  : options.validateBootOptions;
65
- // Boot-Validation als allererstes — vor fs-Watcher und Server. Dieselbe
64
+ // Boot-Validation als allererstes — vor dem Server. Dieselbe
66
65
  // Fehlerklasse (unqualifizierte nav-/handler-QNs, screen-access etc.),
67
66
  // die früher nur runProdApp fing und sonst erst den Prod-Pod im
68
67
  // CrashLoopBackOff sterben ließ (#359). Wirft synchron, bevor ein
69
- // Socket oder Watcher (codegen-Write) aufgeht.
68
+ // Socket aufgeht.
70
69
  // Resolved before validateBoot: an app-supplied masterKey provider must satisfy the
71
70
  // encrypted-field gate here exactly as it does in runProdApp.
72
71
  const bootCrypto = resolveBootCrypto(envSource, options.masterKey);
@@ -76,21 +75,6 @@ export async function runDevApp(options) {
76
75
  });
77
76
  warnIfNonUtcServerTimeZone();
78
77
  validateAppCustomScreenWriteQns(process.cwd(), collectWriteHandlerQns(features));
79
- // Codegen + File-Watcher — schreibt `<appRoot>/.kumiko/types.generated.d.ts`
80
- // + `define.ts` aus den r.defineEvent-Aufrufen der App, einmal beim
81
- // Boot UND danach bei jeder relevanten Änderung unter `<appRoot>/src/`.
82
- // Idempotent (writeIfChanged) — der TS-Sprachserver kriegt nur einen
83
- // Reload-Tick wenn sich tatsächlich was geändert hat.
84
- //
85
- // App-Root ist process.cwd() (bun-dev läuft vom App-Workspace). Der
86
- // Watcher läuft solange der Dev-Server lebt; close() bei Shutdown
87
- // wird über das createKumikoServer-Handle implizit erledigt (Bun's
88
- // process-exit räumt fs.watch-handles auf).
89
- // Sammelt alle Write-Handler-QNs für den Codegen — damit
90
- // `types.generated.d.ts` eine `WriteHandlerQn`-Union exportieren
91
- // kann, die dispatcher.write-Aufrufe client-seitig typisiert.
92
- const handlerQns = collectWriteHandlerQns(features);
93
- watchAndRegenerate({ appRoot: process.cwd(), handlerQns: [...handlerQns] });
94
78
  // Sprint-8a Tier-Composition auto-wire: scan features for a
95
79
  // tenantTierResolver-extension. If found AND user didn't supply own
96
80
  // effectiveFeatures, we wire a late-bound wrapper here and fill it
@@ -1,3 +1,13 @@
1
1
  export declare const FRAMEWORK_AGENTS_IMPORT = "@node_modules/@cosmicdrift/kumiko-framework/AGENTS.md";
2
- export declare function renderAgentsMd(): string;
2
+ export declare function renderMountedFeatureList(features: ReadonlyArray<{
3
+ readonly name: string;
4
+ }> | undefined): string;
5
+ export type AgentsMdOptions = {
6
+ readonly productName: string;
7
+ readonly features: ReadonlyArray<{
8
+ readonly name: string;
9
+ }> | undefined;
10
+ readonly scriptNames: readonly string[];
11
+ };
12
+ export declare function renderAgentsMd(options: AgentsMdOptions): string;
3
13
  export declare function renderClaudeMd(): string;
@@ -1,16 +1,50 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { render } from "./scaffold-deploy.js";
1
5
  export const FRAMEWORK_AGENTS_IMPORT = "@node_modules/@cosmicdrift/kumiko-framework/AGENTS.md";
2
- const FRAMEWORK_AGENTS_PATH = "node_modules/@cosmicdrift/kumiko-framework/AGENTS.md";
3
- const FRAMEWORK_AGENTS_DIR = "node_modules/@cosmicdrift/kumiko-framework/agents/";
4
- export function renderAgentsMd() {
5
- return `# Agent instructions
6
-
7
- This app is built on Kumiko. The framework guide for coding agents ships with the installed package and matches its version:
8
-
9
- - \`${FRAMEWORK_AGENTS_PATH}\`: start here.
10
- - \`${FRAMEWORK_AGENTS_DIR}\`: generated indexes of bundled features, widgets and tested examples.
11
-
12
- Read the framework guide before you add or change a feature. App-specific rules go below.
13
- `;
6
+ const SCRIPT_DESCRIPTIONS = {
7
+ dev: "run the app with demo data",
8
+ boot: "boot validation without serving, needs no database",
9
+ typecheck: "type-check",
10
+ lint: "Biome check",
11
+ test: "unit tests",
12
+ "test:integration": "integration tests, need `docker compose up -d`",
13
+ "test:real": "tests against real providers, local only",
14
+ e2e: "browser tests, need `docker compose up -d`",
15
+ "e2e:real": "browser tests against real providers, local only",
16
+ "schema:generate": "new migration after an entity change or a newly mounted bundled feature",
17
+ "schema:apply": "apply the checked-in migrations",
18
+ build: "production build",
19
+ start: "run the production build",
20
+ };
21
+ const DEMO_TASKS_FEATURE_LINE = "- `tasks` (demo — list + edit screens)";
22
+ const FOUNDATION_FEATURE_LINES = ["- `secrets` (foundation)", "- `sessions` (foundation)"];
23
+ export function renderMountedFeatureList(features) {
24
+ const lines = features && features.length > 0
25
+ ? features.map((f) => `- \`${f.name}\``)
26
+ : FOUNDATION_FEATURE_LINES;
27
+ return [...lines, DEMO_TASKS_FEATURE_LINE].join("\n");
28
+ }
29
+ function renderCommandList(scriptNames) {
30
+ return scriptNames
31
+ .map((name) => {
32
+ const description = SCRIPT_DESCRIPTIONS[name];
33
+ return description === undefined
34
+ ? `- \`bun run ${name}\``
35
+ : `- \`bun run ${name}\`: ${description}`;
36
+ })
37
+ .join("\n");
38
+ }
39
+ function agentsTemplatePath() {
40
+ return join(dirname(fileURLToPath(import.meta.url)), "..", "templates", "AGENTS.app.md");
41
+ }
42
+ export function renderAgentsMd(options) {
43
+ return render(readFileSync(agentsTemplatePath(), "utf-8"), {
44
+ productName: options.productName,
45
+ featureList: renderMountedFeatureList(options.features),
46
+ commands: renderCommandList(options.scriptNames),
47
+ }, {});
14
48
  }
15
49
  export function renderClaudeMd() {
16
50
  return `${FRAMEWORK_AGENTS_IMPORT}\n@AGENTS.md\n`;
@@ -14,7 +14,7 @@ import { dirname, join, relative, resolve } from "node:path";
14
14
  import { collectTableMetas, generateMigration, writeSnapshotJson, } from "@cosmicdrift/kumiko-framework/db";
15
15
  import { composeFeatures } from "@cosmicdrift/kumiko-server-runtime/compose-features";
16
16
  import { isKebabSegment } from "./kebab.js";
17
- import { renderAgentsMd, renderClaudeMd } from "./scaffold-agent-docs.js";
17
+ import { renderAgentsMd, renderClaudeMd, renderMountedFeatureList } from "./scaffold-agent-docs.js";
18
18
  import { createDemoTasksFeature, renderDemoSeedFile, renderDemoTasksFeatureFile, renderDemoTasksI18n, renderDemoTasksIndex, renderDemoTasksWebIndex, } from "./scaffold-demo-tasks.js";
19
19
  import { scaffoldDeploy } from "./scaffold-deploy.js";
20
20
  // Exact pin (no caret): the generated files are formatted to this Biome's output,
@@ -24,7 +24,6 @@ const SCAFFOLD_GITIGNORE = `node_modules/
24
24
  dist/
25
25
  dist-server/
26
26
  .env
27
- .kumiko/
28
27
  test-results/
29
28
  playwright-report/
30
29
  `;
@@ -105,7 +104,11 @@ export async function scaffoldApp(options) {
105
104
  }
106
105
  write(join(destination, "README.md"), `${renderReadme(options.name, options.features)}${testSetup === undefined ? "" : `\n${testSetup.rulesMarkdown}`}`);
107
106
  files.push("README.md");
108
- write(join(destination, "AGENTS.md"), renderAgentsMd());
107
+ write(join(destination, "AGENTS.md"), renderAgentsMd({
108
+ productName: options.name,
109
+ features: options.features,
110
+ scriptNames: Object.keys(appScripts(testSetup)),
111
+ }));
109
112
  files.push("AGENTS.md");
110
113
  write(join(destination, "CLAUDE.md"), renderClaudeMd());
111
114
  files.push("CLAUDE.md");
@@ -115,23 +118,26 @@ export async function scaffoldApp(options) {
115
118
  function write(path, content) {
116
119
  writeFileSync(path, content);
117
120
  }
121
+ function appScripts(testSetup) {
122
+ return {
123
+ dev: "bun --watch bin/dev.ts",
124
+ build: "bun kumiko-build",
125
+ start: "bun run bin/main.ts",
126
+ boot: "KUMIKO_DRY_RUN_ENV=boot bun bin/main.ts",
127
+ typecheck: "tsc --noEmit",
128
+ lint: "biome check .",
129
+ ...(testSetup?.scripts ?? { test: "bun --config=bunfig.ci.toml test --dots" }),
130
+ "schema:apply": "bun kumiko-schema apply",
131
+ "schema:generate": "bun kumiko-schema generate",
132
+ };
133
+ }
118
134
  function renderPackageJson(name, version, testSetup) {
119
135
  return `${JSON.stringify({
120
136
  name,
121
137
  version: "0.1.0",
122
138
  private: true,
123
139
  type: "module",
124
- scripts: {
125
- dev: "bun --watch bin/dev.ts",
126
- build: "bun kumiko-build",
127
- start: "bun run bin/main.ts",
128
- boot: "KUMIKO_DRY_RUN_ENV=boot bun bin/main.ts",
129
- typecheck: "tsc --noEmit",
130
- lint: "biome check .",
131
- ...(testSetup?.scripts ?? { test: "bun --config=bunfig.ci.toml test --dots" }),
132
- "schema:apply": "bun kumiko-schema apply",
133
- "schema:generate": "bun kumiko-schema generate",
134
- },
140
+ scripts: appScripts(testSetup),
135
141
  dependencies: {
136
142
  "@cosmicdrift/kumiko-bundled-features": version,
137
143
  "@cosmicdrift/kumiko-dev-server": version,
@@ -276,8 +282,8 @@ const FOUNDATION_FEATURES = [
276
282
  {
277
283
  name: "auth-foundation",
278
284
  importPath: "@cosmicdrift/kumiko-bundled-features/auth-foundation",
279
- exportName: "authFoundationFeature",
280
- callExpression: "authFoundationFeature",
285
+ exportName: "createAuthFoundationFeature",
286
+ callExpression: "createAuthFoundationFeature()",
281
287
  },
282
288
  {
283
289
  name: "sessions",
@@ -621,9 +627,7 @@ volumes:
621
627
  `;
622
628
  }
623
629
  function renderReadme(appName, features) {
624
- const featureList = features && features.length > 0
625
- ? [...features.map((f) => `- \`${f.name}\``), "- `tasks` (demo — list + edit screens)"].join("\n")
626
- : "- `secrets` (foundation)\n- `sessions` (foundation)\n- `tasks` (demo — list + edit screens)";
630
+ const featureList = renderMountedFeatureList(features);
627
631
  return `# ${appName}
628
632
 
629
633
  Scaffolded by \`kumiko new app\`. Includes a demo **tasks** feature with list +
@@ -212,7 +212,7 @@ export function renderDemoSeedFile() {
212
212
  return `// Demo seed — a few tasks so \`bun dev\` shows a non-empty list.
213
213
 
214
214
  import type { SeedFn } from "@cosmicdrift/kumiko-dev-server";
215
- import { TestUsers } from "@cosmicdrift/kumiko-framework/stack";
215
+ import { TestUsers } from "@cosmicdrift/kumiko-framework/seeding";
216
216
 
217
217
  const DEMO_TASKS = [
218
218
  { title: "Welcome to Kumiko", status: "todo", priority: 1, isUrgent: false },
@@ -25,7 +25,7 @@ export async function runSchemaApply(opts) {
25
25
  console.error(`\n ${migrationsDir} fehlt — kumiko/migrations/ muss im Image liegen.\n`);
26
26
  return 1;
27
27
  }
28
- const { db, close } = createDbConnection(dbUrl);
28
+ const { db, close } = createDbConnection({ url: dbUrl });
29
29
  try {
30
30
  // Infra-Tabellen (event-store + pipeline-state) zuerst, alle
31
31
  // tableExists-gated idempotent: auf einer Bestands-DB no-op, auf einer
@@ -1,6 +1,6 @@
1
1
  import type { FeatureDefinition } from "@cosmicdrift/kumiko-framework/engine";
2
- import { type TestStack, type TestStackOptions } from "@cosmicdrift/kumiko-framework/stack";
3
2
  import { type ComposeFeaturesOptions } from "@cosmicdrift/kumiko-server-runtime/compose-features";
3
+ import { type TestStack, type TestStackOptions } from "@cosmicdrift/kumiko-testing/stack";
4
4
  export type TestStackPreset = "config" | "template-resolver";
5
5
  export type SetupTestStackFromFeaturesOptions = Omit<TestStackOptions, "features"> & {
6
6
  readonly includeBundled?: boolean;
@@ -2,10 +2,10 @@
2
2
  // Apps pass the same feature list as run-config (APP_FEATURES / buildAppFeatures).
3
3
  import { createConfigResolver, } from "@cosmicdrift/kumiko-bundled-features/config";
4
4
  import { createTemplateResolverApi } from "@cosmicdrift/kumiko-bundled-features/template-resolver";
5
- import { setupTestStack, } from "@cosmicdrift/kumiko-framework/stack";
6
5
  import { jobRunLoggerCallbacks } from "@cosmicdrift/kumiko-server-runtime/boot/job-run-logger";
7
6
  import { composeFeatures, } from "@cosmicdrift/kumiko-server-runtime/compose-features";
8
7
  import { addConfigAccessorFactory } from "@cosmicdrift/kumiko-server-runtime/run-prod-app";
8
+ import { setupTestStack, } from "@cosmicdrift/kumiko-testing/stack";
9
9
  function isConfigResolver(value) {
10
10
  return (typeof value === "object" && value !== null && "get" in value && typeof value.get === "function");
11
11
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-dev-server",
3
- "version": "0.367.0",
4
- "description": "Dev-tooling for Kumiko apps: local dev-server bootstrap (runDevApp), scaffolding, codegen. Its compose-stacks/env-schema subpaths are consumed at prod boot too — see @cosmicdrift/kumiko-server-runtime for the prod runner itself.",
3
+ "version": "0.368.0",
4
+ "description": "Dev-tooling for Kumiko apps: local dev-server bootstrap (runDevApp), scaffolding. Its compose-stacks/env-schema subpaths are consumed at prod boot too — see @cosmicdrift/kumiko-server-runtime for the prod runner itself.",
5
5
  "license": "BUSL-1.1",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
7
7
  "repository": {
@@ -15,7 +15,11 @@
15
15
  "homepage": "https://kumiko.rocks",
16
16
  "type": "module",
17
17
  "kumiko": {
18
- "runtime": "dev"
18
+ "runtime": "dev",
19
+ "bunOnlyExports": [
20
+ ".",
21
+ "./setup-test-stack-from-features"
22
+ ]
19
23
  },
20
24
  "exports": {
21
25
  ".": {
@@ -63,13 +67,14 @@
63
67
  "kumiko-upgrade": "./bin/kumiko-upgrade.ts"
64
68
  },
65
69
  "dependencies": {
66
- "@cosmicdrift/kumiko-bundled-features": "0.367.0",
67
- "@cosmicdrift/kumiko-framework": "0.367.0",
68
- "@cosmicdrift/kumiko-headless": "0.367.0",
69
- "@cosmicdrift/kumiko-renderer-mail-html": "0.367.0",
70
- "@cosmicdrift/kumiko-renderer-web": "0.367.0",
71
- "@cosmicdrift/kumiko-server-runtime": "0.367.0",
72
- "@cosmicdrift/kumiko-types": "0.367.0",
70
+ "@cosmicdrift/kumiko-bundled-features": "0.368.0",
71
+ "@cosmicdrift/kumiko-framework": "0.368.0",
72
+ "@cosmicdrift/kumiko-headless": "0.368.0",
73
+ "@cosmicdrift/kumiko-renderer-mail-html": "0.368.0",
74
+ "@cosmicdrift/kumiko-renderer-web": "0.368.0",
75
+ "@cosmicdrift/kumiko-server-runtime": "0.368.0",
76
+ "@cosmicdrift/kumiko-testing": "0.368.0",
77
+ "@cosmicdrift/kumiko-types": "0.368.0",
73
78
  "bun-types": "^1.3.13",
74
79
  "ts-morph": "^28.0.0",
75
80
  "zod": "^4.4.3"
package/src/changes.json CHANGED
@@ -1,4 +1,17 @@
1
1
  [
2
+ {
3
+ "version": "0.368.0",
4
+ "type": "breaking",
5
+ "title": "@app/define and kumiko codegen are removed",
6
+ "detail": "The .kumiko/ codegen (define.ts, types.generated.d.ts, schemas.generated.ts) is gone: runCodegen, scanEvents and their types are no longer exported, the dev server no longer watches r.defineEvent calls, `kumiko codegen` is removed, `kumiko-build --check` is removed and kumiko-build no longer runs a codegen pass. The scaffolded .gitignore no longer lists .kumiko/, so the upgrade marker .kumiko/upgrade-state.json can be committed. ctx.appendEvent stays bound to the augmentable KumikoEventTypeMap; to emit an event with a payload checked against its definition use emitEvent(ctx, eventDef, { aggregateId, aggregateType, payload, headers? }) with the EventDef that r.defineEvent returns (emitEvent now also accepts headers).",
7
+ "migration": "Replace `@app/define` imports with direct framework imports (defineWriteHandler/defineQueryHandler/defineFeature from @cosmicdrift/kumiko-framework/engine, events via r.defineEvent and emitEvent) and drop the `file:./.kumiko` dependency plus the bunfig/tsconfig resolver entries. Known sites: publicstatus 43 files, kumiko-platform 13 (samples), solon 3, money-horse 1, phronexsis 1."
8
+ },
9
+ {
10
+ "version": "0.368.0",
11
+ "type": "improvement",
12
+ "title": "Scaffolded apps get AGENTS.md from a template with placeholders",
13
+ "detail": "The scaffold renders AGENTS.md from templates/AGENTS.app.md instead of a fixed string. It fills in the app name, the mounted features and the commands that exist in the generated package.json. Purpose, production URL and app-specific rules stay as visible TODO(app owner) placeholders. CLAUDE.md is unchanged: it imports the framework guide and AGENTS.md."
14
+ },
2
15
  {
3
16
  "version": "0.365.0",
4
17
  "type": "fix",
@@ -0,0 +1,27 @@
1
+ # {{productName}}: agent instructions
2
+
3
+ {{productName}} is built on Kumiko. The framework guide for coding agents ships with the installed package and matches its version:
4
+
5
+ - `node_modules/@cosmicdrift/kumiko-framework/AGENTS.md`: start here.
6
+ - `node_modules/@cosmicdrift/kumiko-framework/agents/`: generated indexes of bundled features, widgets and tested examples.
7
+
8
+ Read the framework guide before you add or change a feature. The sections below are specific to this app.
9
+
10
+ ## Product
11
+
12
+ - Purpose: TODO(app owner): what {{productName}} does and for whom, in one or two sentences.
13
+ - Production URL: TODO(app owner): https://example.com
14
+
15
+ ## Mounted features
16
+
17
+ {{featureList}}
18
+
19
+ Mount more in `src/run-config.ts`. App code lives in `src/features/<name>/`.
20
+
21
+ ## Commands
22
+
23
+ {{commands}}
24
+
25
+ ## App-specific rules
26
+
27
+ TODO(app owner): decisions an agent cannot read from the code, such as domain terms, roles, data-retention limits or integrations that must not be touched.
@@ -1,4 +0,0 @@
1
- export { renderDefineFile, renderInlineSchemasFile, renderTypesAugmentation, renderWriteHandlerTypes, } from "./render.js";
2
- export { type CodegenOptions, type CodegenResult, runCodegen } from "./run-codegen.js";
3
- export { formatScanWarning, qualifiedNameToConstName, rewriteImportPath, type ScannedEvent, type ScanOptions, type ScanResult, type ScanWarning, type SchemaSource, scanEvents, } from "./scan-events.js";
4
- export { type WatchHandle, type WatchOptions, watchAndRegenerate } from "./watch.js";
@@ -1,4 +0,0 @@
1
- export { renderDefineFile, renderInlineSchemasFile, renderTypesAugmentation, renderWriteHandlerTypes, } from "./render.js";
2
- export { runCodegen } from "./run-codegen.js";
3
- export { formatScanWarning, qualifiedNameToConstName, rewriteImportPath, scanEvents, } from "./scan-events.js";
4
- export { watchAndRegenerate } from "./watch.js";