@cosmicdrift/kumiko-dev-server 0.2.0 → 0.2.2
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/CHANGELOG.md +69 -0
- package/package.json +6 -6
- package/src/create-kumiko-server.ts +11 -0
- package/src/run-dev-app.ts +55 -1
- package/src/run-prod-app.ts +28 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# @cosmicdrift/kumiko-dev-server
|
|
2
|
+
|
|
3
|
+
## 0.2.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 7a7da3e: Re-publish 0.2.1 → 0.2.2 mit korrekt aufgelösten cross-package-Versionen.
|
|
8
|
+
0.2.1 hatte `workspace:*` als Wert in den dependencies (npm publish ohne
|
|
9
|
+
yarn-pack rewrite), Konsumenten bekamen "Workspace not found".
|
|
10
|
+
|
|
11
|
+
publish-with-oidc.sh nutzt jetzt `yarn pack` (rewrited workspace:\*) +
|
|
12
|
+
`npm publish <tarball>` (OIDC + provenance).
|
|
13
|
+
|
|
14
|
+
- Updated dependencies [7a7da3e]
|
|
15
|
+
- @cosmicdrift/kumiko-framework@0.2.2
|
|
16
|
+
- @cosmicdrift/kumiko-bundled-features@0.2.2
|
|
17
|
+
|
|
18
|
+
## 0.2.1
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- 48b7f6a: CI: switch publish to npm-CLI with OIDC Trusted Publishing + provenance.
|
|
23
|
+
No source changes — verifies the new publish path produces a verified-
|
|
24
|
+
provenance attestation on npmjs.com instead of token-based publish.
|
|
25
|
+
- Updated dependencies [48b7f6a]
|
|
26
|
+
- @cosmicdrift/kumiko-framework@0.2.1
|
|
27
|
+
- @cosmicdrift/kumiko-bundled-features@0.2.1
|
|
28
|
+
|
|
29
|
+
## 0.2.0
|
|
30
|
+
|
|
31
|
+
### Minor Changes
|
|
32
|
+
|
|
33
|
+
- 6c70b6f: fix(tenant): seedTenant idempotent gegen Event-Store-Projection-Drift.
|
|
34
|
+
|
|
35
|
+
Verhindert version_conflict beim App-Boot wenn Aggregat existiert aber
|
|
36
|
+
Projection-Row fehlt (rebuild-drift, async-lag, manueller DB-Eingriff).
|
|
37
|
+
|
|
38
|
+
### Patch Changes
|
|
39
|
+
|
|
40
|
+
- Updated dependencies [6c70b6f]
|
|
41
|
+
- @cosmicdrift/kumiko-framework@0.2.0
|
|
42
|
+
- @cosmicdrift/kumiko-bundled-features@0.2.0
|
|
43
|
+
|
|
44
|
+
## 0.1.0
|
|
45
|
+
|
|
46
|
+
### Minor Changes
|
|
47
|
+
|
|
48
|
+
- 59ba6d7: Initial public release of Kumiko — AI-native backend builder.
|
|
49
|
+
|
|
50
|
+
What ships in 0.1.0:
|
|
51
|
+
|
|
52
|
+
- **Engine** (`@cosmicdrift/kumiko-framework`): `defineFeature`, `r.entity`, `r.writeHandler`, `r.queryHandler`, `r.projection`, `r.multiStreamProjection`, `r.hook`, `r.translations`, `r.crud`, `r.referenceData`, `r.screen`, `r.nav`, `r.authClaims`, full lifecycle pipeline with field-level access checks
|
|
53
|
+
- **Pipeline** (`@cosmicdrift/kumiko-framework`): `createDispatcher`, JWT auth via jose, Zod schema validation, role-based access checks, command/write/query split
|
|
54
|
+
- **DB** (`@cosmicdrift/kumiko-framework`): Drizzle helpers (`buildDrizzleTable`, `applyCursorQuery`), CRUD executor, Postgres dialect, optimistic locking, soft delete, multi-tenant scoping
|
|
55
|
+
- **Event sourcing** (`@cosmicdrift/kumiko-framework`): aggregate streams, single + multi-stream projections, event upcasters, asOf queries, archive support, AsyncDaemon-pattern dispatcher
|
|
56
|
+
- **Bundled features** (`@cosmicdrift/kumiko-bundled-features`): auth-email-password, sessions, tenants, users, jobs, secrets, file-provider-s3, mail-transport-smtp/inmemory, billing-foundation, cap-counter, channel-in-app, delivery, feature-toggles, legal-pages
|
|
57
|
+
- **Renderer** (`@cosmicdrift/kumiko-renderer`, `@cosmicdrift/kumiko-renderer-web`): schema-driven CRUD UI for React + Expo Web, override paths, list debounce, theme tokens
|
|
58
|
+
- **Headless** (`@cosmicdrift/kumiko-headless`): view-models for list/edit screens, locale-aware
|
|
59
|
+
- **Dev server** (`@cosmicdrift/kumiko-dev-server`): `runDevApp`, `runProdApp`, `kumiko-build` for production bundles (client + server), Docker-ready
|
|
60
|
+
- **Realtime** (`@cosmicdrift/kumiko-dispatcher-live`): SSE broadcast across tenants, Redis Pub/Sub backend
|
|
61
|
+
- **CLI** (`bin/kumiko.ts`): interactive dev menu, test runners, check pipeline (Biome + TypeScript + 18 guards + Vitest)
|
|
62
|
+
|
|
63
|
+
This is a pre-1.0 release — APIs may change between minor versions. Breaking changes will be documented per release.
|
|
64
|
+
|
|
65
|
+
### Patch Changes
|
|
66
|
+
|
|
67
|
+
- Updated dependencies [59ba6d7]
|
|
68
|
+
- @cosmicdrift/kumiko-framework@0.1.0
|
|
69
|
+
- @cosmicdrift/kumiko-bundled-features@0.1.0
|
package/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-dev-server",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Development server bootstrap for Kumiko apps. Bundles the client, mints dev-JWTs, injects the resolved AppSchema, and seeds an admin. Not for production.",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
|
-
"url": "git+https://github.com/
|
|
9
|
+
"url": "git+https://github.com/CosmicDriftGameStudio/kumiko-framework.git",
|
|
10
10
|
"directory": "packages/dev-server"
|
|
11
11
|
},
|
|
12
12
|
"bugs": {
|
|
13
|
-
"url": "https://github.com/
|
|
13
|
+
"url": "https://github.com/CosmicDriftGameStudio/kumiko-framework/issues"
|
|
14
14
|
},
|
|
15
15
|
"homepage": "https://kumiko.so",
|
|
16
16
|
"type": "module",
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"kumiko-dev": "./bin/kumiko-dev.ts"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@cosmicdrift/kumiko-bundled-features": "
|
|
34
|
-
"@cosmicdrift/kumiko-framework": "
|
|
33
|
+
"@cosmicdrift/kumiko-bundled-features": "0.2.2",
|
|
34
|
+
"@cosmicdrift/kumiko-framework": "0.2.2"
|
|
35
35
|
},
|
|
36
36
|
"publishConfig": {
|
|
37
37
|
"registry": "https://registry.npmjs.org",
|
|
@@ -42,4 +42,4 @@
|
|
|
42
42
|
"README.md",
|
|
43
43
|
"LICENSE"
|
|
44
44
|
]
|
|
45
|
-
}
|
|
45
|
+
}
|
|
@@ -170,6 +170,14 @@ export type CreateKumikoServerOptions = {
|
|
|
170
170
|
* Handler `roles: ["anonymous"]` deklariert. Tenant-Resolution per
|
|
171
171
|
* Header/Cookie/Default; siehe AnonymousAccessConfig. */
|
|
172
172
|
readonly anonymousAccess?: TestStackOptions["anonymousAccess"];
|
|
173
|
+
/** Feature-toggle resolver — durchgereicht an setupTestStack. Wenn
|
|
174
|
+
* gesetzt, konsultiert der dispatcher-feature-gate, hook-filter, MSP-
|
|
175
|
+
* filter den callback; absent = alle features always-on. Erforderlich
|
|
176
|
+
* für Tier-Composition (Sprint 8) wo per-Tenant unterschiedliche
|
|
177
|
+
* features aktiv sein sollen. Die typische produktive Implementierung
|
|
178
|
+
* ist `() => globalFeatureToggleRuntime.effectiveFeatures` post-boot
|
|
179
|
+
* (createLateBoundHolder-pattern, weil runtime stack.db braucht). */
|
|
180
|
+
readonly effectiveFeatures?: TestStackOptions["effectiveFeatures"];
|
|
173
181
|
/** Wird nach dem Aufsetzen der Entity-Tabellen aufgerufen. Hook für
|
|
174
182
|
* non-entity-tables (unsafePushTables) und Seeding (admin user, initial
|
|
175
183
|
* tenant, …). Muss idempotent sein — im persistent-DB-Modus läuft
|
|
@@ -641,6 +649,9 @@ export async function createKumikoServer(
|
|
|
641
649
|
...(options.auth !== undefined && { authConfig: options.auth }),
|
|
642
650
|
...(options.extraContext !== undefined && { extraContext: options.extraContext }),
|
|
643
651
|
...(options.anonymousAccess !== undefined && { anonymousAccess: options.anonymousAccess }),
|
|
652
|
+
...(options.effectiveFeatures !== undefined && {
|
|
653
|
+
effectiveFeatures: options.effectiveFeatures,
|
|
654
|
+
}),
|
|
644
655
|
});
|
|
645
656
|
await createEventsTable(stack.db);
|
|
646
657
|
await pushEntityProjectionTables(stack, stack.registry);
|
package/src/run-dev-app.ts
CHANGED
|
@@ -26,7 +26,14 @@ import {
|
|
|
26
26
|
import { TenantQueries } from "@cosmicdrift/kumiko-bundled-features/tenant";
|
|
27
27
|
|
|
28
28
|
import type { SessionMetadata } from "@cosmicdrift/kumiko-framework/api";
|
|
29
|
-
import
|
|
29
|
+
import {
|
|
30
|
+
type EffectiveFeaturesResolver,
|
|
31
|
+
type FeatureDefinition,
|
|
32
|
+
findTierResolverUsage,
|
|
33
|
+
type SessionUser,
|
|
34
|
+
type TenantId,
|
|
35
|
+
type TierResolverPlugin,
|
|
36
|
+
} from "@cosmicdrift/kumiko-framework/engine";
|
|
30
37
|
import type { TestStack } from "@cosmicdrift/kumiko-framework/stack";
|
|
31
38
|
|
|
32
39
|
import { watchAndRegenerate } from "./codegen";
|
|
@@ -138,6 +145,13 @@ export type RunDevAppOptions = {
|
|
|
138
145
|
* Hono-app gehängt, läuft VOR dem static-asset-Pfad. Symmetrisch zur
|
|
139
146
|
* gleichnamigen Option in runProdApp. */
|
|
140
147
|
readonly extraRoutes?: CreateKumikoServerOptions["extraRoutes"];
|
|
148
|
+
/** Feature-toggle resolver — durchgereicht an createKumikoServer →
|
|
149
|
+
* setupTestStack. Sprint-8 Tier-Composition: per-Tenant unterschied-
|
|
150
|
+
* liche features aktiv via globalFeatureToggleRuntime. Pattern in
|
|
151
|
+
* bin/server.ts: createLateBoundHolder + post-boot runtime.initialize
|
|
152
|
+
* in einem seed-fn, weil die runtime stack.db braucht und die seed-
|
|
153
|
+
* Funktionen nach setupTestStack laufen. */
|
|
154
|
+
readonly effectiveFeatures?: CreateKumikoServerOptions["effectiveFeatures"];
|
|
141
155
|
};
|
|
142
156
|
|
|
143
157
|
export async function runDevApp(options: RunDevAppOptions): Promise<KumikoServerHandle> {
|
|
@@ -163,6 +177,33 @@ export async function runDevApp(options: RunDevAppOptions): Promise<KumikoServer
|
|
|
163
177
|
...(composeAuthOptions && { authOptions: composeAuthOptions }),
|
|
164
178
|
});
|
|
165
179
|
|
|
180
|
+
// Sprint-8a Tier-Composition auto-wire: scan features for a
|
|
181
|
+
// tenantTierResolver-extension. If found AND user didn't supply own
|
|
182
|
+
// effectiveFeatures, we wire a late-bound wrapper here and fill it
|
|
183
|
+
// in onAfterSetup (where stack.db + stack.registry are available).
|
|
184
|
+
// App-Author sees nothing — `createTierEngineFeature(opts)` mounts +
|
|
185
|
+
// framework auto-wires.
|
|
186
|
+
const tierResolverUsage = options.effectiveFeatures ? undefined : findTierResolverUsage(features);
|
|
187
|
+
const tierResolverHolder: { resolver: EffectiveFeaturesResolver | undefined } = {
|
|
188
|
+
resolver: undefined,
|
|
189
|
+
};
|
|
190
|
+
const finalEffectiveFeatures: EffectiveFeaturesResolver | undefined =
|
|
191
|
+
options.effectiveFeatures ??
|
|
192
|
+
(tierResolverUsage
|
|
193
|
+
? (tenantId: TenantId) => {
|
|
194
|
+
// Defensive: Server starts AFTER onAfterSetup completes, so the
|
|
195
|
+
// resolver is filled before any request comes in. Throwing here
|
|
196
|
+
// means a programming error (boot order) rather than silent
|
|
197
|
+
// "all-features-on" misbehavior.
|
|
198
|
+
if (!tierResolverHolder.resolver) {
|
|
199
|
+
throw new Error(
|
|
200
|
+
"tier-resolver: extension found but resolver not yet built — boot order issue?",
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
return tierResolverHolder.resolver(tenantId);
|
|
204
|
+
}
|
|
205
|
+
: undefined);
|
|
206
|
+
|
|
166
207
|
// configResolver-default fürs config-feature — im auth-mode immer
|
|
167
208
|
// hinzufügen, im no-auth-mode dem Caller überlassen. Factory-form
|
|
168
209
|
// wird gewrap't damit der spread auf das aufgerufene Result greift,
|
|
@@ -216,6 +257,9 @@ export async function runDevApp(options: RunDevAppOptions): Promise<KumikoServer
|
|
|
216
257
|
...(extraContext !== undefined && { extraContext }),
|
|
217
258
|
...(options.anonymousAccess !== undefined && { anonymousAccess: options.anonymousAccess }),
|
|
218
259
|
...(options.extraRoutes !== undefined && { extraRoutes: options.extraRoutes }),
|
|
260
|
+
...(finalEffectiveFeatures !== undefined && {
|
|
261
|
+
effectiveFeatures: finalEffectiveFeatures,
|
|
262
|
+
}),
|
|
219
263
|
...(options.auth && {
|
|
220
264
|
auth: {
|
|
221
265
|
membershipQuery: TenantQueries.memberships,
|
|
@@ -261,6 +305,16 @@ export async function runDevApp(options: RunDevAppOptions): Promise<KumikoServer
|
|
|
261
305
|
},
|
|
262
306
|
}),
|
|
263
307
|
onAfterSetup: async (stack) => {
|
|
308
|
+
// Sprint-8a: build tier-resolver BEFORE any seeds so seeds can rely
|
|
309
|
+
// on the resolver being live (e.g. seed that writes a SystemAdmin's
|
|
310
|
+
// tier-assignment can immediately read tier-cuts).
|
|
311
|
+
if (tierResolverUsage) {
|
|
312
|
+
const plugin = tierResolverUsage.options as TierResolverPlugin;
|
|
313
|
+
tierResolverHolder.resolver = await plugin.build({
|
|
314
|
+
db: stack.db,
|
|
315
|
+
registry: stack.registry,
|
|
316
|
+
});
|
|
317
|
+
}
|
|
264
318
|
if (options.auth?.sessions !== undefined) {
|
|
265
319
|
const expiresInMs = options.auth.sessions.expiresInMs;
|
|
266
320
|
sessionCallbacks = createSessionCallbacks({
|
package/src/run-prod-app.ts
CHANGED
|
@@ -46,7 +46,11 @@ import { createDbConnection } from "@cosmicdrift/kumiko-framework/db";
|
|
|
46
46
|
import {
|
|
47
47
|
buildAppSchema,
|
|
48
48
|
createRegistry,
|
|
49
|
+
type EffectiveFeaturesResolver,
|
|
49
50
|
type FeatureDefinition,
|
|
51
|
+
findTierResolverUsage,
|
|
52
|
+
type TenantId,
|
|
53
|
+
type TierResolverPlugin,
|
|
50
54
|
validateBoot,
|
|
51
55
|
} from "@cosmicdrift/kumiko-framework/engine";
|
|
52
56
|
import {
|
|
@@ -351,6 +355,12 @@ export type RunProdAppOptions = {
|
|
|
351
355
|
* the fetch-handler directly (Bun.serve isn't available under vitest +
|
|
352
356
|
* node), then call handle.listen() manually if needed. */
|
|
353
357
|
readonly autoListen?: boolean;
|
|
358
|
+
/** Feature-toggle resolver — durchgereicht an createApiEntrypoint's
|
|
359
|
+
* dispatcherOptions. Sprint-8 Tier-Composition: per-Tenant unterschied-
|
|
360
|
+
* liche features aktiv via globalFeatureToggleRuntime. Pattern:
|
|
361
|
+
* createLateBoundHolder + post-boot runtime.initialize in einem
|
|
362
|
+
* seed-fn (db ist erst nach migrations + features ready). */
|
|
363
|
+
readonly effectiveFeatures?: (tenantId: TenantId) => ReadonlySet<string>;
|
|
354
364
|
};
|
|
355
365
|
|
|
356
366
|
export type ProdAppHandle = {
|
|
@@ -403,6 +413,20 @@ export async function runProdApp(options: RunProdAppOptions): Promise<ProdAppHan
|
|
|
403
413
|
validateBoot(features);
|
|
404
414
|
const registry = createRegistry(features);
|
|
405
415
|
|
|
416
|
+
// Sprint-8a Tier-Composition auto-wire: scan features for a
|
|
417
|
+
// tenantTierResolver-extension. If found AND user didn't supply own
|
|
418
|
+
// effectiveFeatures, build the resolver here (db + registry are
|
|
419
|
+
// available) before the dispatcher is constructed. App-Author sees
|
|
420
|
+
// nothing — `createTierEngineFeature(opts)` mounts + framework auto-wires.
|
|
421
|
+
let resolvedEffectiveFeatures: EffectiveFeaturesResolver | undefined = options.effectiveFeatures;
|
|
422
|
+
if (resolvedEffectiveFeatures === undefined) {
|
|
423
|
+
const tierResolverUsage = findTierResolverUsage(features);
|
|
424
|
+
if (tierResolverUsage) {
|
|
425
|
+
const plugin = tierResolverUsage.options as TierResolverPlugin;
|
|
426
|
+
resolvedEffectiveFeatures = await plugin.build({ db, registry });
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
406
430
|
// 5. Schema-Drift-Gate. Drizzle-kit migrate (yarn kumiko migrate apply)
|
|
407
431
|
// läuft als CI-Step VOR dem Container-Rollout. Boot prüft hier nur:
|
|
408
432
|
// (a) Alle Migrations aus drizzle/migrations/meta/_journal.json
|
|
@@ -486,7 +510,10 @@ export async function runProdApp(options: RunProdAppOptions): Promise<ProdAppHan
|
|
|
486
510
|
jwtSecret,
|
|
487
511
|
...(jwtIssuer && { jwtIssuer }),
|
|
488
512
|
...(instanceId && { instanceId }),
|
|
489
|
-
dispatcherOptions: {
|
|
513
|
+
dispatcherOptions: {
|
|
514
|
+
idempotency,
|
|
515
|
+
...(resolvedEffectiveFeatures && { effectiveFeatures: resolvedEffectiveFeatures }),
|
|
516
|
+
},
|
|
490
517
|
eventDedup,
|
|
491
518
|
...(options.auth && {
|
|
492
519
|
auth: {
|