@cosmicdrift/kumiko-dev-server 1.0.0 → 2.0.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/bin/kumiko-schema-check.ts +7 -0
- package/package.json +12 -7
- package/src/__tests__/build-prod-bundle.integration.test.ts +1 -1
- package/src/__tests__/build-server-bundle.test.ts +62 -0
- package/src/__tests__/compose-stacks.test.ts +271 -0
- package/src/__tests__/create-kumiko-server-errors.test.ts +54 -0
- package/src/__tests__/create-kumiko-server-options.test.ts +33 -0
- package/src/__tests__/create-kumiko-server.integration.test.ts +128 -1
- package/src/__tests__/discover-format.test.ts +1 -1
- package/src/__tests__/env-schema.integration.test.ts +1 -1
- package/src/__tests__/few-shot-corpus.test.ts +16 -11
- package/src/__tests__/merge-extra-context.test.ts +56 -0
- package/src/__tests__/resolve-stylesheet.test.ts +16 -0
- package/src/__tests__/saas-identity-wire.integration.test.ts +430 -0
- package/src/__tests__/scaffold-app-feature.test.ts +59 -6
- package/src/__tests__/scaffold-app.test.ts +34 -2
- package/src/__tests__/schema-apply.integration.test.ts +5 -2
- package/src/__tests__/setup-test-stack-from-features.integration.test.ts +30 -0
- package/src/__tests__/walkthrough.integration.test.ts +22 -6
- package/src/build-server-bundle.ts +33 -15
- package/src/build.ts +1 -2
- package/src/codegen/__tests__/render-codegen.test.ts +2 -1
- package/src/codegen/__tests__/run-codegen.test.ts +2 -2
- package/src/codegen/__tests__/strict-mode-diagnostics.test.ts +6 -1
- package/src/codegen/__tests__/watch.test.ts +1 -2
- package/src/codegen/render.ts +6 -1
- package/src/codegen/scan-events.ts +7 -5
- package/src/codegen/watch.ts +7 -4
- package/src/compose-stacks.ts +184 -0
- package/src/create-kumiko-server.ts +28 -5
- package/src/few-shot-corpus.ts +4 -3
- package/src/index.ts +30 -12
- package/src/run-dev-app.ts +195 -61
- package/src/scaffold-app-feature.ts +118 -15
- package/src/scaffold-app.ts +151 -79
- package/src/scaffold-demo-tasks.ts +233 -0
- package/src/schema-apply.ts +15 -2
- package/src/schema-check-core.ts +1 -1
- package/src/setup-test-stack-from-features.ts +61 -0
- package/src/welcome-banner.ts +1 -4
- package/src/__tests__/boot-extra-context.test.ts +0 -140
- package/src/__tests__/build-prod-bundle.test.ts +0 -311
- package/src/__tests__/cache-headers.test.ts +0 -83
- package/src/__tests__/compose-features-wiring.integration.test.ts +0 -382
- package/src/__tests__/compose-features.test.ts +0 -129
- package/src/__tests__/config-seed-boot.integration.test.ts +0 -158
- package/src/__tests__/inject-schema.test.ts +0 -62
- package/src/__tests__/renderer-web-css-relocation.integration.test.ts +0 -85
- package/src/__tests__/renderer-web-shell-sentinel.test.ts +0 -35
- package/src/__tests__/require-env.test.ts +0 -29
- package/src/__tests__/resolve-auth-mail.test.ts +0 -69
- package/src/__tests__/resolve-tailwind-cli.test.ts +0 -81
- package/src/__tests__/run-prod-app-env-source.test.ts +0 -157
- package/src/__tests__/run-prod-app-spec.test.ts +0 -57
- package/src/__tests__/run-prod-app.integration.test.ts +0 -840
- package/src/__tests__/session-wiring.test.ts +0 -51
- package/src/__tests__/try-hono-first.test.ts +0 -63
- package/src/boot/apply-boot-seeds.ts +0 -18
- package/src/build-prod-bundle.ts +0 -697
- package/src/compose-features.ts +0 -145
- package/src/extra-routes-deps.ts +0 -47
- package/src/inject-schema.ts +0 -24
- package/src/resolve-tailwind-cli.ts +0 -45
- package/src/run-prod-app.ts +0 -1492
- package/src/session-wiring.ts +0 -29
- package/src/try-hono-first.ts +0 -46
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
// Composable SaaS stack presets — explicit opt-in blocks for run-config.ts.
|
|
2
|
+
// Presets export feature instances only; no implicit PAT scopes, anonymousAccess,
|
|
3
|
+
// or tier maps (those stay in bin/server.ts / app run-config).
|
|
4
|
+
|
|
5
|
+
import { createAuditFeature } from "@cosmicdrift/kumiko-bundled-features/audit";
|
|
6
|
+
import { authFoundationFeature } from "@cosmicdrift/kumiko-bundled-features/auth-foundation";
|
|
7
|
+
import {
|
|
8
|
+
type AuthMfaFeatureOptions,
|
|
9
|
+
createAuthMfaFeature,
|
|
10
|
+
} from "@cosmicdrift/kumiko-bundled-features/auth-mfa";
|
|
11
|
+
import { createComplianceProfilesFeature } from "@cosmicdrift/kumiko-bundled-features/compliance-profiles";
|
|
12
|
+
import { createDataRetentionFeature } from "@cosmicdrift/kumiko-bundled-features/data-retention";
|
|
13
|
+
import { createDeliveryFeature } from "@cosmicdrift/kumiko-bundled-features/delivery";
|
|
14
|
+
import { fileFoundationFeature } from "@cosmicdrift/kumiko-bundled-features/file-foundation";
|
|
15
|
+
import { fileProviderInMemoryFeature } from "@cosmicdrift/kumiko-bundled-features/file-provider-inmemory";
|
|
16
|
+
import { fileProviderS3Feature } from "@cosmicdrift/kumiko-bundled-features/file-provider-s3";
|
|
17
|
+
import { fileProviderS3EnvFeature } from "@cosmicdrift/kumiko-bundled-features/file-provider-s3-env";
|
|
18
|
+
import { createFilesFeature } from "@cosmicdrift/kumiko-bundled-features/files";
|
|
19
|
+
import { createJobsFeature } from "@cosmicdrift/kumiko-bundled-features/jobs";
|
|
20
|
+
import {
|
|
21
|
+
createLegalPagesFeature,
|
|
22
|
+
type LegalPagesOptions,
|
|
23
|
+
} from "@cosmicdrift/kumiko-bundled-features/legal-pages";
|
|
24
|
+
import { mailFoundationFeature } from "@cosmicdrift/kumiko-bundled-features/mail-foundation";
|
|
25
|
+
import { mailTransportInMemoryFeature } from "@cosmicdrift/kumiko-bundled-features/mail-transport-inmemory";
|
|
26
|
+
import { mailTransportSmtpFeature } from "@cosmicdrift/kumiko-bundled-features/mail-transport-smtp";
|
|
27
|
+
import { createRateLimitingFeature } from "@cosmicdrift/kumiko-bundled-features/rate-limiting";
|
|
28
|
+
import { createRendererFoundationFeature } from "@cosmicdrift/kumiko-bundled-features/renderer-foundation";
|
|
29
|
+
import { createRendererSimpleFeature } from "@cosmicdrift/kumiko-bundled-features/renderer-simple";
|
|
30
|
+
import { createSessionsFeature } from "@cosmicdrift/kumiko-bundled-features/sessions";
|
|
31
|
+
import { createTemplateResolverFeature } from "@cosmicdrift/kumiko-bundled-features/template-resolver";
|
|
32
|
+
import { createTenantLifecycleFeature } from "@cosmicdrift/kumiko-bundled-features/tenant-lifecycle";
|
|
33
|
+
import { createTextContentFeature } from "@cosmicdrift/kumiko-bundled-features/text-content";
|
|
34
|
+
import {
|
|
35
|
+
createUserDataRightsFeature,
|
|
36
|
+
type UserDataRightsOptions,
|
|
37
|
+
} from "@cosmicdrift/kumiko-bundled-features/user-data-rights";
|
|
38
|
+
import { createUserDataRightsDefaultsFeature } from "@cosmicdrift/kumiko-bundled-features/user-data-rights-defaults";
|
|
39
|
+
import type { FeatureDefinition } from "@cosmicdrift/kumiko-framework/engine";
|
|
40
|
+
|
|
41
|
+
export type FileProviderKind = "inmemory" | "s3" | "s3-env";
|
|
42
|
+
export type MailTransportKind = "inmemory" | "smtp";
|
|
43
|
+
export type GdprStackOrder = "retention-first" | "compliance-first";
|
|
44
|
+
|
|
45
|
+
export type FileStackOptions = {
|
|
46
|
+
readonly providers: readonly FileProviderKind[];
|
|
47
|
+
readonly includeFilesFeature?: boolean;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export type MailStackOptions = {
|
|
51
|
+
readonly transports: readonly MailTransportKind[];
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export type PagesStackOptions = {
|
|
55
|
+
readonly wrapLayout?: LegalPagesOptions["wrapLayout"];
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export type GdprStackOptions = {
|
|
59
|
+
readonly order?: GdprStackOrder;
|
|
60
|
+
readonly sessions?: boolean;
|
|
61
|
+
readonly tenantLifecycle?: boolean;
|
|
62
|
+
/** Optional tokenVerifier provider(s) (e.g. PAT) when `sessions` is on.
|
|
63
|
+
* Session-only stacks need none — sessions registers sessionStore, which
|
|
64
|
+
* satisfies auth-foundation's boot check (#1570). Pass providers when the
|
|
65
|
+
* app also wants Bearer/PAT auth. */
|
|
66
|
+
readonly providers?: readonly FeatureDefinition[];
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export type UserDataRightsStackOptions = {
|
|
70
|
+
readonly userDataRights?: UserDataRightsOptions;
|
|
71
|
+
readonly includeDefaults?: boolean;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// `sessions` may live on composeIdentityStack OR composeGdprStack — never both
|
|
75
|
+
// with sessions:true. composeOpsStack used to accept it too; combining presets
|
|
76
|
+
// that each push "sessions" crashes createRegistry with "duplicate feature".
|
|
77
|
+
export type OpsStackOptions = {
|
|
78
|
+
readonly delivery?: boolean;
|
|
79
|
+
readonly audit?: boolean;
|
|
80
|
+
readonly jobs?: boolean;
|
|
81
|
+
readonly rateLimiting?: boolean;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/** sessions (+ optional auth-mfa). config/user/tenant/auth-email-password stay
|
|
85
|
+
* on composeFeatures(includeBundled). Pass `mfa` options to mount TOTP.
|
|
86
|
+
* When `sessions` is on (the default), auth-foundation is mounted alongside it —
|
|
87
|
+
* the framework's registry now hard-requires it (sessions.requires("auth-foundation")).
|
|
88
|
+
* Session-only is enough for boot (#1570); optional Bearer/PAT still needs a
|
|
89
|
+
* tokenVerifier provider from the caller (e.g. createPersonalAccessTokensFeature
|
|
90
|
+
* ({ scopes })) — PAT scopes are app-specific, so they stay caller-owned. */
|
|
91
|
+
export type IdentityStackOptions = {
|
|
92
|
+
readonly sessions?: boolean;
|
|
93
|
+
readonly mfa?: AuthMfaFeatureOptions;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export function stackFeatureNames(features: readonly FeatureDefinition[]): string[] {
|
|
97
|
+
return features.map((f) => f.name);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function composePagesStack(options: PagesStackOptions = {}): FeatureDefinition[] {
|
|
101
|
+
return [
|
|
102
|
+
createTextContentFeature(),
|
|
103
|
+
createLegalPagesFeature(
|
|
104
|
+
options.wrapLayout !== undefined ? { wrapLayout: options.wrapLayout } : {},
|
|
105
|
+
),
|
|
106
|
+
];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function composeRendererStack(): FeatureDefinition[] {
|
|
110
|
+
return [
|
|
111
|
+
createTemplateResolverFeature(),
|
|
112
|
+
createRendererFoundationFeature(),
|
|
113
|
+
createRendererSimpleFeature(),
|
|
114
|
+
];
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function composeMailStack(options: MailStackOptions): FeatureDefinition[] {
|
|
118
|
+
const out: FeatureDefinition[] = [mailFoundationFeature];
|
|
119
|
+
for (const transport of options.transports) {
|
|
120
|
+
if (transport === "inmemory") out.push(mailTransportInMemoryFeature);
|
|
121
|
+
if (transport === "smtp") out.push(mailTransportSmtpFeature);
|
|
122
|
+
}
|
|
123
|
+
return out;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export function composeFileStack(options: FileStackOptions): FeatureDefinition[] {
|
|
127
|
+
const out: FeatureDefinition[] = [fileFoundationFeature];
|
|
128
|
+
for (const provider of options.providers) {
|
|
129
|
+
if (provider === "inmemory") out.push(fileProviderInMemoryFeature);
|
|
130
|
+
if (provider === "s3") out.push(fileProviderS3Feature);
|
|
131
|
+
if (provider === "s3-env") out.push(fileProviderS3EnvFeature);
|
|
132
|
+
}
|
|
133
|
+
if (options.includeFilesFeature ?? true) out.push(createFilesFeature());
|
|
134
|
+
return out;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** Retention + compliance (+ optional lifecycle/sessions). UDR/files mount separately — order varies per app. */
|
|
138
|
+
export function composeGdprStack(options: GdprStackOptions = {}): FeatureDefinition[] {
|
|
139
|
+
const order = options.order ?? "retention-first";
|
|
140
|
+
const retention = createDataRetentionFeature();
|
|
141
|
+
const compliance = createComplianceProfilesFeature();
|
|
142
|
+
const out: FeatureDefinition[] =
|
|
143
|
+
order === "compliance-first" ? [compliance, retention] : [retention, compliance];
|
|
144
|
+
if (options.tenantLifecycle) out.push(createTenantLifecycleFeature());
|
|
145
|
+
if (options.sessions) {
|
|
146
|
+
out.push(authFoundationFeature, createSessionsFeature());
|
|
147
|
+
if (options.providers) out.push(...options.providers);
|
|
148
|
+
}
|
|
149
|
+
return out;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export function composeUserDataRightsStack(
|
|
153
|
+
options: UserDataRightsStackOptions = {},
|
|
154
|
+
): FeatureDefinition[] {
|
|
155
|
+
const includeDefaults = options.includeDefaults ?? true;
|
|
156
|
+
const out: FeatureDefinition[] = [createUserDataRightsFeature(options.userDataRights ?? {})];
|
|
157
|
+
if (includeDefaults) out.push(createUserDataRightsDefaultsFeature());
|
|
158
|
+
return out;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export function composeOpsStack(options: OpsStackOptions = {}): FeatureDefinition[] {
|
|
162
|
+
const delivery = options.delivery ?? true;
|
|
163
|
+
const audit = options.audit ?? true;
|
|
164
|
+
const jobs = options.jobs ?? true;
|
|
165
|
+
const rateLimiting = options.rateLimiting ?? false;
|
|
166
|
+
const out: FeatureDefinition[] = [];
|
|
167
|
+
if (delivery) out.push(createDeliveryFeature());
|
|
168
|
+
if (audit) out.push(createAuditFeature());
|
|
169
|
+
if (jobs) out.push(createJobsFeature());
|
|
170
|
+
if (rateLimiting) out.push(createRateLimitingFeature());
|
|
171
|
+
return out;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/** Identity opt-ins: sessions by default; auth-mfa when `mfa` options given.
|
|
175
|
+
* Do not also pass `sessions: true` to composeGdprStack — duplicate feature. */
|
|
176
|
+
export function composeIdentityStack(options: IdentityStackOptions = {}): FeatureDefinition[] {
|
|
177
|
+
const sessions = options.sessions ?? true;
|
|
178
|
+
const out: FeatureDefinition[] = [];
|
|
179
|
+
if (sessions) {
|
|
180
|
+
out.push(authFoundationFeature, createSessionsFeature());
|
|
181
|
+
}
|
|
182
|
+
if (options.mfa !== undefined) out.push(createAuthMfaFeature(options.mfa));
|
|
183
|
+
return out;
|
|
184
|
+
}
|
|
@@ -19,6 +19,7 @@ import { existsSync, mkdtempSync, statSync } from "node:fs";
|
|
|
19
19
|
import { readFile, watch } from "node:fs/promises";
|
|
20
20
|
import { tmpdir } from "node:os";
|
|
21
21
|
import { join, resolve } from "node:path";
|
|
22
|
+
import { resolveAnonymousAccessFromRegistry } from "@cosmicdrift/kumiko-bundled-features/auth-foundation";
|
|
22
23
|
import { type AuthRoutesConfig, generateToken } from "@cosmicdrift/kumiko-framework/api";
|
|
23
24
|
import { buildAppSchema, type FeatureDefinition } from "@cosmicdrift/kumiko-framework/engine";
|
|
24
25
|
import { createEventsTable } from "@cosmicdrift/kumiko-framework/event-store";
|
|
@@ -29,11 +30,18 @@ import {
|
|
|
29
30
|
type TestStackOptions,
|
|
30
31
|
TestUsers,
|
|
31
32
|
} from "@cosmicdrift/kumiko-framework/stack";
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
import { startDevJobRunners } from "@cosmicdrift/kumiko-server-runtime/boot/job-run-logger";
|
|
34
|
+
import { buildBunServeOptions } from "@cosmicdrift/kumiko-server-runtime/bun-serve-options";
|
|
35
|
+
import {
|
|
36
|
+
type ExtraRoutesSystemDeps,
|
|
37
|
+
makeDispatchSystemWrite,
|
|
38
|
+
} from "@cosmicdrift/kumiko-server-runtime/extra-routes-deps";
|
|
39
|
+
import { injectSchema } from "@cosmicdrift/kumiko-server-runtime/inject-schema";
|
|
40
|
+
import {
|
|
41
|
+
canResolveTailwindStylesheet,
|
|
42
|
+
resolveTailwindCli,
|
|
43
|
+
} from "@cosmicdrift/kumiko-server-runtime/resolve-tailwind-cli";
|
|
44
|
+
import { tryHonoFirst } from "@cosmicdrift/kumiko-server-runtime/try-hono-first";
|
|
37
45
|
|
|
38
46
|
// Runtime-detection. The dev-server is meant to run under Bun (Kumiko's
|
|
39
47
|
// target runtime), but the test-suite runs under vitest on Node — we
|
|
@@ -335,6 +343,7 @@ async function watchDir(
|
|
|
335
343
|
} catch (err) {
|
|
336
344
|
// signal.abort() wirft AbortError aus dem async-iterator; das ist
|
|
337
345
|
// gewollt und kein Fehler. Andere Errors weiterreichen.
|
|
346
|
+
// skip: AbortSignal fired the abort, this is expected teardown not a real error
|
|
338
347
|
if ((err as { name?: string }).name === "AbortError") return;
|
|
339
348
|
throw err;
|
|
340
349
|
}
|
|
@@ -665,10 +674,14 @@ export async function createKumikoServer(
|
|
|
665
674
|
...(options.auth !== undefined && { authConfig: options.auth }),
|
|
666
675
|
...(options.extraContext !== undefined && { extraContext: options.extraContext }),
|
|
667
676
|
...(options.anonymousAccess !== undefined && { anonymousAccess: options.anonymousAccess }),
|
|
677
|
+
enrichAnonymousAccess: (base, deps) => resolveAnonymousAccessFromRegistry(base, deps),
|
|
668
678
|
...(options.files !== undefined && { files: options.files }),
|
|
669
679
|
...(options.effectiveFeatures !== undefined && {
|
|
670
680
|
effectiveFeatures: options.effectiveFeatures,
|
|
671
681
|
}),
|
|
682
|
+
// jobs: {} = enqueuer-only; startDevJobRunners below is the sole
|
|
683
|
+
// consumer/cron-scheduler per lane, so runOnBoot/cron jobs don't double-fire.
|
|
684
|
+
jobs: {},
|
|
672
685
|
});
|
|
673
686
|
await createEventsTable(stack.db);
|
|
674
687
|
await pushEntityProjectionTables(stack, stack.registry);
|
|
@@ -707,6 +720,14 @@ export async function createKumikoServer(
|
|
|
707
720
|
await stack.eventDispatcher.start();
|
|
708
721
|
}
|
|
709
722
|
|
|
723
|
+
const redisUrl = `redis://${stack.redis.redis.options.host}:${stack.redis.redis.options.port}/${stack.redis.redis.options.db}`;
|
|
724
|
+
const devJobRunners = await startDevJobRunners({
|
|
725
|
+
registry: stack.registry,
|
|
726
|
+
db: stack.db,
|
|
727
|
+
context: { db: stack.db, registry: stack.registry },
|
|
728
|
+
redisUrl,
|
|
729
|
+
});
|
|
730
|
+
|
|
710
731
|
// Dev user = TestUsers.admin. Demo features are openToAll but the
|
|
711
732
|
// auth-middleware still needs a valid JWT to let the request past.
|
|
712
733
|
// Nicht genutzt wenn `options.auth` gesetzt ist — dann macht der Client
|
|
@@ -936,6 +957,7 @@ export async function createKumikoServer(
|
|
|
936
957
|
dir,
|
|
937
958
|
async (filename) => {
|
|
938
959
|
const action = classifyChange(filename);
|
|
960
|
+
// skip: file change classified as ignore (test/css/json), nothing to rebuild
|
|
939
961
|
if (action === "ignore") return;
|
|
940
962
|
if (action === "restart") {
|
|
941
963
|
logInfo(
|
|
@@ -977,6 +999,7 @@ export async function createKumikoServer(
|
|
|
977
999
|
if (stack.eventDispatcher) {
|
|
978
1000
|
await stack.eventDispatcher.stop();
|
|
979
1001
|
}
|
|
1002
|
+
await devJobRunners.stop();
|
|
980
1003
|
await stack.cleanup();
|
|
981
1004
|
};
|
|
982
1005
|
|
package/src/few-shot-corpus.ts
CHANGED
|
@@ -52,7 +52,7 @@ export type CorpusWarning = {
|
|
|
52
52
|
/** Human-readable explanation. Currently only "parser-throw" but
|
|
53
53
|
* kept open-ended so future builders can add more (e.g.
|
|
54
54
|
* "duplicate-id", "no-feature-name"). */
|
|
55
|
-
readonly
|
|
55
|
+
readonly message: string;
|
|
56
56
|
};
|
|
57
57
|
|
|
58
58
|
export type FewShotEntry = {
|
|
@@ -161,7 +161,7 @@ export function buildFewShotCorpus(options: BuildFewShotCorpusOptions): FewShotC
|
|
|
161
161
|
// warning, drop the second occurrence.
|
|
162
162
|
warnings.push({
|
|
163
163
|
sourcePath: entry.sourcePath,
|
|
164
|
-
|
|
164
|
+
message: `duplicate-id: collides with ${previousPath}`,
|
|
165
165
|
});
|
|
166
166
|
continue;
|
|
167
167
|
}
|
|
@@ -198,7 +198,7 @@ function buildEntry(filePath: string, repoRoot: string): BuildEntryResult {
|
|
|
198
198
|
// hide newly broken feature-files until L2 hit them.
|
|
199
199
|
const detail = err instanceof Error ? err.message : String(err);
|
|
200
200
|
return {
|
|
201
|
-
warning: { sourcePath,
|
|
201
|
+
warning: { sourcePath, message: `parser-throw: ${detail}` },
|
|
202
202
|
};
|
|
203
203
|
}
|
|
204
204
|
|
|
@@ -295,6 +295,7 @@ function walkDir(dir: string, acc: string[]): void {
|
|
|
295
295
|
try {
|
|
296
296
|
entries = readdirSync(dir, { withFileTypes: true });
|
|
297
297
|
} catch {
|
|
298
|
+
// skip: directory missing/unreadable, nothing to walk
|
|
298
299
|
return;
|
|
299
300
|
}
|
|
300
301
|
for (const entry of entries) {
|
package/src/index.ts
CHANGED
|
@@ -13,6 +13,10 @@
|
|
|
13
13
|
// Login-Routes + Error-Map, ruft seedAdmin im onAfterSetup. Default
|
|
14
14
|
// für Sample-Apps und Showcases — 5-10 Zeilen Bootstrap statt 50.
|
|
15
15
|
|
|
16
|
+
export {
|
|
17
|
+
type ComposeFeaturesOptions,
|
|
18
|
+
composeFeatures,
|
|
19
|
+
} from "@cosmicdrift/kumiko-server-runtime/compose-features";
|
|
16
20
|
// Build-Toolchain (buildProdBundle, Bun.build, Tailwind-Pipeline, ts-morph) lebt
|
|
17
21
|
// im Sub-Path-Export `@cosmicdrift/kumiko-dev-server/build`. Damit zieht der Main-Barrel
|
|
18
22
|
// kein Bun-Toolchain-Bundle mehr in Production-Reads (z.B. wenn drizzle-kit
|
|
@@ -25,7 +29,27 @@ export {
|
|
|
25
29
|
type ScanWarning,
|
|
26
30
|
scanEvents,
|
|
27
31
|
} from "./codegen";
|
|
28
|
-
export {
|
|
32
|
+
export {
|
|
33
|
+
composeFileStack,
|
|
34
|
+
composeGdprStack,
|
|
35
|
+
composeIdentityStack,
|
|
36
|
+
composeMailStack,
|
|
37
|
+
composeOpsStack,
|
|
38
|
+
composePagesStack,
|
|
39
|
+
composeRendererStack,
|
|
40
|
+
composeUserDataRightsStack,
|
|
41
|
+
type FileProviderKind,
|
|
42
|
+
type FileStackOptions,
|
|
43
|
+
type GdprStackOptions,
|
|
44
|
+
type GdprStackOrder,
|
|
45
|
+
type IdentityStackOptions,
|
|
46
|
+
type MailStackOptions,
|
|
47
|
+
type MailTransportKind,
|
|
48
|
+
type OpsStackOptions,
|
|
49
|
+
type PagesStackOptions,
|
|
50
|
+
stackFeatureNames,
|
|
51
|
+
type UserDataRightsStackOptions,
|
|
52
|
+
} from "./compose-stacks";
|
|
29
53
|
export {
|
|
30
54
|
type CreateKumikoServerOptions,
|
|
31
55
|
createKumikoServer,
|
|
@@ -43,17 +67,6 @@ export type {
|
|
|
43
67
|
export { buildFewShotCorpus, pathToId } from "./few-shot-corpus";
|
|
44
68
|
export type { RunDevAppAuthOptions, RunDevAppOptions, SeedFn } from "./run-dev-app";
|
|
45
69
|
export { runDevApp } from "./run-dev-app";
|
|
46
|
-
export type {
|
|
47
|
-
EmailVerificationSetup,
|
|
48
|
-
InviteSetup,
|
|
49
|
-
PasswordResetSetup,
|
|
50
|
-
ProdAppHandle,
|
|
51
|
-
ProdSeedFn,
|
|
52
|
-
RunProdAppAuthOptions,
|
|
53
|
-
RunProdAppOptions,
|
|
54
|
-
SignupSetup,
|
|
55
|
-
} from "./run-prod-app";
|
|
56
|
-
export { runProdApp } from "./run-prod-app";
|
|
57
70
|
export type {
|
|
58
71
|
ScaffoldAppOptions,
|
|
59
72
|
ScaffoldAppResult,
|
|
@@ -73,4 +86,9 @@ export type {
|
|
|
73
86
|
export { scaffoldDeploy } from "./scaffold-deploy";
|
|
74
87
|
export type { ScaffoldFeatureOptions, ScaffoldFeatureResult } from "./scaffold-feature";
|
|
75
88
|
export { scaffoldFeature } from "./scaffold-feature";
|
|
89
|
+
export {
|
|
90
|
+
type SetupTestStackFromFeaturesOptions,
|
|
91
|
+
setupTestStackFromFeatures,
|
|
92
|
+
type TestStackPreset,
|
|
93
|
+
} from "./setup-test-stack-from-features";
|
|
76
94
|
export { renderWelcomeBanner, type WelcomeBannerInput } from "./welcome-banner";
|