@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 +1 -1
- package/bin/kumiko-build.ts +1 -32
- package/dist/cli.d.ts +0 -1
- package/dist/cli.js +0 -1
- package/dist/compose-stacks.js +16 -17
- package/dist/create-kumiko-server.d.ts +1 -1
- package/dist/create-kumiko-server.js +2 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/run-dev-app.d.ts +1 -1
- package/dist/run-dev-app.js +2 -18
- package/dist/scaffold-agent-docs.d.ts +11 -1
- package/dist/scaffold-agent-docs.js +46 -12
- package/dist/scaffold-app.js +23 -19
- package/dist/scaffold-demo-tasks.js +1 -1
- package/dist/schema-apply.js +1 -1
- package/dist/setup-test-stack-from-features.d.ts +1 -1
- package/dist/setup-test-stack-from-features.js +1 -1
- package/package.json +15 -10
- package/src/changes.json +13 -0
- package/templates/AGENTS.app.md +27 -0
- package/dist/codegen/index.d.ts +0 -4
- package/dist/codegen/index.js +0 -4
- package/dist/codegen/render.d.ts +0 -55
- package/dist/codegen/render.js +0 -273
- package/dist/codegen/run-codegen.d.ts +0 -23
- package/dist/codegen/run-codegen.js +0 -229
- package/dist/codegen/scan-events.d.ts +0 -81
- package/dist/codegen/scan-events.js +0 -447
- package/dist/codegen/watch.d.ts +0 -42
- package/dist/codegen/watch.js +0 -112
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
|
|
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
|
|
package/bin/kumiko-build.ts
CHANGED
|
@@ -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 [
|
|
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";
|
package/dist/compose-stacks.js
CHANGED
|
@@ -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 {
|
|
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 {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
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 {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
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 = [
|
|
57
|
+
const out = [createMailFoundationFeature()];
|
|
59
58
|
for (const transport of options.transports) {
|
|
60
59
|
if (transport === "inmemory")
|
|
61
|
-
out.push(
|
|
60
|
+
out.push(createMailTransportInMemoryFeature());
|
|
62
61
|
if (transport === "smtp")
|
|
63
|
-
out.push(
|
|
62
|
+
out.push(createMailTransportSmtpFeature());
|
|
64
63
|
}
|
|
65
64
|
return out;
|
|
66
65
|
}
|
|
67
66
|
export function composeFileStack(options) {
|
|
68
|
-
const out = [
|
|
67
|
+
const out = [createFileFoundationFeature()];
|
|
69
68
|
for (const provider of options.providers) {
|
|
70
69
|
if (provider === "inmemory")
|
|
71
|
-
out.push(
|
|
70
|
+
out.push(createFileProviderInMemoryFeature());
|
|
72
71
|
if (provider === "s3")
|
|
73
|
-
out.push(
|
|
72
|
+
out.push(createFileProviderS3Feature());
|
|
74
73
|
if (provider === "s3-env")
|
|
75
|
-
out.push(
|
|
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(
|
|
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(
|
|
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 {
|
|
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";
|
package/dist/run-dev-app.d.ts
CHANGED
|
@@ -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";
|
package/dist/run-dev-app.js
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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`;
|
package/dist/scaffold-app.js
CHANGED
|
@@ -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: "
|
|
280
|
-
callExpression: "
|
|
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
|
|
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/
|
|
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 },
|
package/dist/schema-apply.js
CHANGED
|
@@ -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.
|
|
4
|
-
"description": "Dev-tooling for Kumiko apps: local dev-server bootstrap (runDevApp), scaffolding
|
|
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.
|
|
67
|
-
"@cosmicdrift/kumiko-framework": "0.
|
|
68
|
-
"@cosmicdrift/kumiko-headless": "0.
|
|
69
|
-
"@cosmicdrift/kumiko-renderer-mail-html": "0.
|
|
70
|
-
"@cosmicdrift/kumiko-renderer-web": "0.
|
|
71
|
-
"@cosmicdrift/kumiko-server-runtime": "0.
|
|
72
|
-
"@cosmicdrift/kumiko-
|
|
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.
|
package/dist/codegen/index.d.ts
DELETED
|
@@ -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";
|
package/dist/codegen/index.js
DELETED
|
@@ -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";
|