@cosmicdrift/kumiko-bundled-features 0.178.0 → 0.178.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-bundled-features",
|
|
3
|
-
"version": "0.178.
|
|
3
|
+
"version": "0.178.1",
|
|
4
4
|
"description": "Built-in features — tenant, user, auth, delivery. The stuff you'd rewrite anyway, already typed.",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -120,12 +120,12 @@
|
|
|
120
120
|
"./step-dispatcher": "./src/step-dispatcher/index.ts"
|
|
121
121
|
},
|
|
122
122
|
"dependencies": {
|
|
123
|
-
"@cosmicdrift/kumiko-dispatcher-live": "0.178.
|
|
124
|
-
"@cosmicdrift/kumiko-framework": "0.178.
|
|
125
|
-
"@cosmicdrift/kumiko-headless": "0.178.
|
|
126
|
-
"@cosmicdrift/kumiko-renderer": "0.178.
|
|
127
|
-
"@cosmicdrift/kumiko-renderer-web": "0.178.
|
|
128
|
-
"@cosmicdrift/kumiko-types": "0.178.
|
|
123
|
+
"@cosmicdrift/kumiko-dispatcher-live": "0.178.1",
|
|
124
|
+
"@cosmicdrift/kumiko-framework": "0.178.1",
|
|
125
|
+
"@cosmicdrift/kumiko-headless": "0.178.1",
|
|
126
|
+
"@cosmicdrift/kumiko-renderer": "0.178.1",
|
|
127
|
+
"@cosmicdrift/kumiko-renderer-web": "0.178.1",
|
|
128
|
+
"@cosmicdrift/kumiko-types": "0.178.1",
|
|
129
129
|
"@mollie/api-client": "^4.5.0",
|
|
130
130
|
"imapflow": "^1.3.3",
|
|
131
131
|
"mailparser": "^3.9.8",
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
// TemplateResolverApi —
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// (siehe text-content/api.ts).
|
|
1
|
+
// TemplateResolverApi — cross-feature interface. renderer-foundation,
|
|
2
|
+
// delivery and apps import types ONLY and take the implementation from
|
|
3
|
+
// ctx.templateResolver at runtime.
|
|
5
4
|
|
|
6
5
|
import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
7
6
|
import type { DbConnection } from "@cosmicdrift/kumiko-framework/db";
|
|
@@ -15,14 +15,14 @@ import { upsertSystemWrite } from "./handlers/upsert-system.write";
|
|
|
15
15
|
import { upsertTenantWrite } from "./handlers/upsert-tenant.write";
|
|
16
16
|
import { templateResourceEntity } from "./table";
|
|
17
17
|
|
|
18
|
-
// template-resolver —
|
|
19
|
-
//
|
|
20
|
-
//
|
|
18
|
+
// template-resolver — structured template storage with tenant-override
|
|
19
|
+
// hierarchy, locale fallback and resource linking via file-foundation.
|
|
20
|
+
// Plan doc: kumiko-platform/docs/plans/features/template-resolver.md
|
|
21
21
|
//
|
|
22
|
-
//
|
|
23
|
-
// - Render
|
|
24
|
-
// - Admin
|
|
25
|
-
// - Cross-
|
|
22
|
+
// Consumption paths:
|
|
23
|
+
// - Render time: ctx.templateResolver.resolveTemplate(...) (see api.ts)
|
|
24
|
+
// - Admin UI: write/query handlers (upsertSystem, upsertTenant, publish, archive, findById, list)
|
|
25
|
+
// - Cross-feature: requireTemplateResolver(ctx, callerName)
|
|
26
26
|
export type TemplateResolverOptions = {
|
|
27
27
|
/** Content collections this app mounts. Declared here rather than inside the
|
|
28
28
|
* feature because `access` needs the host's role vocabulary — a bundled
|
|
@@ -50,7 +50,7 @@ export function createTemplateResolverFeature(opts: TemplateResolverOptions = {}
|
|
|
50
50
|
}
|
|
51
51
|
return defineFeature("template-resolver", (r) => {
|
|
52
52
|
r.describe(
|
|
53
|
-
"
|
|
53
|
+
"The one content store: notification and mail templates, PDF document templates, AI prompts and plain editable text blocks all live here as one entity, distinguished by `kind` (`notification`, `mail-html`, `document-pdf`, `ai-prompt`, `text-block`, `image-snapshot`). Resolution uses a 4-level fallback: tenant+locale \u2192 system+locale \u2192 tenant+fallback-locale \u2192 system+fallback-locale, so tenants can override system defaults without touching application code. Call `ctx.templateResolver.resolveTemplate({ tenantId, slug, kind, locale })` at render time; manage templates via the `upsertSystem`, `upsertTenant`, `publish` and `archive` write handlers. Apps that want an editable collection in their navigation declare it at mount: `createTemplateResolverFeature({ collections: [{ id, kind, access: { roles }, nav }] })` \u2014 `access` belongs to the mount because a bundled feature does not know the host's role vocabulary. Each collection gets its own `<id>-list` / `<id>-item` / `<id>-set` handlers carrying that collection's access rule, so the dispatcher enforces the separation. Replaces the former `text-content` feature, whose blocks now live here as kind `text-block`.",
|
|
54
54
|
);
|
|
55
55
|
r.uiHints({
|
|
56
56
|
displayLabel: "Template Resolver",
|
|
@@ -3,14 +3,13 @@ import { z } from "zod";
|
|
|
3
3
|
import { CONTENT_FORMATS, TEMPLATE_STATUSES, UPSERT_KINDS } from "../constants";
|
|
4
4
|
import { templateResourceEntity, templateResourcesTable } from "../table";
|
|
5
5
|
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
// Optimistic-Lock.
|
|
6
|
+
// One executor per bundle, shared by all four handlers for create/update via
|
|
7
|
+
// event store + optimistic lock.
|
|
9
8
|
export const executor = createEventStoreExecutor(templateResourcesTable, templateResourceEntity, {
|
|
10
9
|
entityName: "template-resource",
|
|
11
10
|
});
|
|
12
11
|
|
|
13
|
-
// Slug
|
|
12
|
+
// Slug regex follows the plan-doc naming convention.
|
|
14
13
|
export const slugSchema = z
|
|
15
14
|
.string()
|
|
16
15
|
.min(1)
|
|
@@ -18,12 +18,11 @@ export const upsertSystemWrite = defineWriteHandler({
|
|
|
18
18
|
access: { roles: ["SystemAdmin"] },
|
|
19
19
|
handler: async (event, ctx) => {
|
|
20
20
|
const db = ctx.db;
|
|
21
|
-
// @cast-boundary engine-payload — SYSTEM_TENANT_ID
|
|
22
|
-
//
|
|
21
|
+
// @cast-boundary engine-payload — SYSTEM_TENANT_ID is a UUID literal,
|
|
22
|
+
// asserted to the branded TenantId (parseTenantId equivalent).
|
|
23
23
|
const tenantId = SYSTEM_TENANT_ID as TenantId;
|
|
24
|
-
// executor
|
|
25
|
-
// event
|
|
26
|
-
// Pattern symmetrisch zu text-content setWrite Override-Branch.
|
|
24
|
+
// The executor user must carry SYSTEM_TENANT as tenantId, otherwise the
|
|
25
|
+
// event store looks up the stream under user.tenantId → conflict.
|
|
27
26
|
const executorUser = { ...event.user, tenantId };
|
|
28
27
|
|
|
29
28
|
const existing = await fetchOne<TemplateResourceRow>(db, templateResourcesTable, {
|