@cosmicdrift/kumiko-samples 0.351.0 → 0.352.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/package.json +1 -1
- package/packages/bundled-features/package.json +2 -2
- package/packages/bundled-features/src/cap-counter/book-cap-usage.ts +95 -54
- package/packages/bundled-features/src/cap-counter/cap-reservation.ts +247 -0
- package/packages/bundled-features/src/cap-counter/changes.json +28 -0
- package/packages/bundled-features/src/cap-counter/constants.ts +8 -0
- package/packages/bundled-features/src/cap-counter/feature.ts +7 -0
- package/packages/bundled-features/src/cap-counter/handlers/increment-rolling.write.ts +5 -0
- package/packages/bundled-features/src/cap-counter/index.ts +9 -0
- package/packages/bundled-features/src/cap-counter/payload-field.ts +10 -0
- package/packages/bundled-features/src/cap-counter/reservation-chain.ts +51 -0
- package/packages/bundled-features/src/cap-counter/stock-cap-guard.ts +3 -0
- package/packages/bundled-features/src/cap-counter/tables.ts +53 -0
- package/packages/bundled-features/src/cap-counter/value-cap-guard.ts +70 -0
- package/packages/bundled-features/src/cap-counter/with-cap-enforcement.ts +63 -70
- package/packages/bundled-features/src/channel-discord/feature.ts +1 -0
- package/packages/bundled-features/src/channel-slack/feature.ts +1 -0
- package/packages/bundled-features/src/channel-teams/feature.ts +1 -0
- package/packages/bundled-features/src/delivery/attempt-log-retention.ts +40 -0
- package/packages/bundled-features/src/delivery/attempt-log.ts +26 -3
- package/packages/bundled-features/src/delivery/changes.json +12 -0
- package/packages/bundled-features/src/delivery/constants.ts +1 -0
- package/packages/bundled-features/src/delivery/events.ts +3 -0
- package/packages/bundled-features/src/delivery/feature.ts +50 -2
- package/packages/bundled-features/src/delivery/index.ts +6 -0
- package/packages/bundled-features/src/delivery/mask-recipient-address.ts +40 -0
- package/packages/bundled-features/src/delivery/public-names.ts +5 -0
- package/packages/bundled-features/src/delivery/types.ts +12 -2
- package/packages/bundled-features/src/derivatives-sharp/changes.json +6 -0
- package/packages/bundled-features/src/legal-pages/README.md +3 -3
- package/packages/bundled-features/src/legal-pages/changes.json +6 -0
- package/packages/bundled-features/src/renderer-foundation/types.ts +1 -1
- package/packages/bundled-features/src/renderer-simple/changes.json +6 -0
- package/packages/bundled-features/src/renderer-simple/feature.ts +4 -6
- package/packages/bundled-features/src/renderer-simple/index.ts +1 -0
- package/packages/bundled-features/src/renderer-simple/mail-blocks.ts +138 -0
- package/packages/bundled-features/src/renderer-simple/simple-renderer.ts +33 -4
- package/packages/bundled-features/src/tier-engine/changes.json +6 -0
- package/packages/bundled-features/src/tier-engine/index.ts +7 -0
- package/packages/bundled-features/src/tier-engine/tier-option-gate.ts +148 -0
- package/packages/bundled-features/src/user-data-rights-defaults/hooks/delivery-attempt.userdata-hook.ts +36 -6
- package/samples/apps/marketing-demo/src/app/seed-data.ts +2 -2
- package/samples/apps/styleguide/src/app/shell.tsx +1 -1
- package/samples/apps/styleguide/src/features/gallery/web/Gallery.tsx +9 -3
- package/samples/apps/ui-walkthrough/src/app/assistant-action.tsx +6 -5
- package/samples/apps/ui-walkthrough/src/app/shell.tsx +3 -2
- package/samples/apps/ui-walkthrough/src/features/tasks/i18n.ts +8 -0
- package/samples/recipes/files-post-processing/package.json +1 -1
- package/samples/recipes/seed-migration/README.md +13 -1
|
@@ -606,20 +606,26 @@ export function Gallery(): ReactNode {
|
|
|
606
606
|
<div className="flex flex-col gap-5 px-6 py-6">
|
|
607
607
|
<div className="flex items-center gap-4">
|
|
608
608
|
<div className="bg-muted text-foreground flex size-16 items-center justify-center rounded-full text-lg font-semibold">
|
|
609
|
-
|
|
609
|
+
AM
|
|
610
610
|
</div>
|
|
611
611
|
<Button variant="secondary">Change avatar</Button>
|
|
612
612
|
</div>
|
|
613
613
|
<div className="grid gap-4 sm:grid-cols-2">
|
|
614
614
|
<Field id="pf-name" label="Full name">
|
|
615
|
-
<Input
|
|
615
|
+
<Input
|
|
616
|
+
kind="text"
|
|
617
|
+
id="pf-name"
|
|
618
|
+
name="pf-name"
|
|
619
|
+
value="Alex Morgan"
|
|
620
|
+
onChange={noop}
|
|
621
|
+
/>
|
|
616
622
|
</Field>
|
|
617
623
|
<Field id="pf-email" label="Email">
|
|
618
624
|
<Input
|
|
619
625
|
kind="text"
|
|
620
626
|
id="pf-email"
|
|
621
627
|
name="pf-email"
|
|
622
|
-
value="
|
|
628
|
+
value="alex@example.com"
|
|
623
629
|
onChange={noop}
|
|
624
630
|
/>
|
|
625
631
|
</Field>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { usePrimitives } from "@cosmicdrift/kumiko-renderer";
|
|
1
|
+
import { usePrimitives, useTranslation } from "@cosmicdrift/kumiko-renderer";
|
|
2
2
|
import { WandSparkles } from "lucide-react";
|
|
3
3
|
import { type ReactNode, useEffect, useState } from "react";
|
|
4
4
|
|
|
@@ -6,6 +6,7 @@ const noop = (): void => {};
|
|
|
6
6
|
|
|
7
7
|
export function AssistantAction(): ReactNode {
|
|
8
8
|
const { Dialog } = usePrimitives();
|
|
9
|
+
const t = useTranslation();
|
|
9
10
|
const [open, setOpen] = useState(false);
|
|
10
11
|
|
|
11
12
|
// Registered here on purpose: an overflow menu that unmounts this component
|
|
@@ -30,7 +31,7 @@ export function AssistantAction(): ReactNode {
|
|
|
30
31
|
className="inline-flex h-9 items-center gap-2 rounded-md border border-border bg-card px-3 text-sm font-medium text-foreground hover:bg-accent"
|
|
31
32
|
>
|
|
32
33
|
<WandSparkles className="h-4 w-4" aria-hidden="true" />
|
|
33
|
-
|
|
34
|
+
{t("tasks.assistant.label")}
|
|
34
35
|
<kbd className="rounded border border-border px-1 font-sans text-xs text-muted-foreground">
|
|
35
36
|
⌘K
|
|
36
37
|
</kbd>
|
|
@@ -38,9 +39,9 @@ export function AssistantAction(): ReactNode {
|
|
|
38
39
|
<Dialog
|
|
39
40
|
open={open}
|
|
40
41
|
onOpenChange={setOpen}
|
|
41
|
-
title="
|
|
42
|
-
description="
|
|
43
|
-
confirmLabel="
|
|
42
|
+
title={t("tasks.assistant.label")}
|
|
43
|
+
description={t("tasks.assistant.description")}
|
|
44
|
+
confirmLabel={t("tasks.assistant.close")}
|
|
44
45
|
onConfirm={noop}
|
|
45
46
|
testId="assistant-dialog"
|
|
46
47
|
/>
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
SidebarBrand,
|
|
14
14
|
ThemeMenuItem,
|
|
15
15
|
ThemeToggle,
|
|
16
|
+
useTranslation,
|
|
16
17
|
} from "@cosmicdrift/kumiko-renderer-web";
|
|
17
18
|
import { MoonStar, Sun } from "lucide-react";
|
|
18
19
|
import type { ReactNode } from "react";
|
|
@@ -20,7 +21,6 @@ import { AssistantAction } from "./assistant-action";
|
|
|
20
21
|
import { BETA_TENANT_ID, DEV_TENANT_ID } from "./auth-constants";
|
|
21
22
|
|
|
22
23
|
const APP_NAME = "Kumiko Walkthrough";
|
|
23
|
-
const APP_TAGLINE = "Design-Referenz";
|
|
24
24
|
|
|
25
25
|
const tenantName = (tenantId: string): string => {
|
|
26
26
|
if (tenantId === DEV_TENANT_ID) return "Dev Tenant";
|
|
@@ -40,9 +40,10 @@ export function AppShell({
|
|
|
40
40
|
readonly children: ReactNode;
|
|
41
41
|
readonly schema: AppSchema;
|
|
42
42
|
}): ReactNode {
|
|
43
|
+
const t = useTranslation();
|
|
43
44
|
return (
|
|
44
45
|
<DefaultAppShell
|
|
45
|
-
brand={<SidebarBrand name={APP_NAME} plan={
|
|
46
|
+
brand={<SidebarBrand name={APP_NAME} plan={t("tasks.shell.tagline")} />}
|
|
46
47
|
schema={schema}
|
|
47
48
|
headerActions={
|
|
48
49
|
<>
|
|
@@ -5,6 +5,10 @@ import type { TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
|
|
|
5
5
|
|
|
6
6
|
export const tasksTranslations: TranslationsByLocale = {
|
|
7
7
|
de: {
|
|
8
|
+
"tasks.shell.tagline": "Design-Referenz",
|
|
9
|
+
"tasks.assistant.label": "Assistent",
|
|
10
|
+
"tasks.assistant.description": "Der Assistent ist im Walkthrough nicht angebunden.",
|
|
11
|
+
"tasks.assistant.close": "Schließen",
|
|
8
12
|
"tasks.nav.group": "Allgemein",
|
|
9
13
|
"tasks.nav.list": "Aufgaben",
|
|
10
14
|
"tasks.nav.new": "Neue Aufgabe",
|
|
@@ -21,6 +25,10 @@ export const tasksTranslations: TranslationsByLocale = {
|
|
|
21
25
|
"tasks:entity:task:field:notes": "Notizen",
|
|
22
26
|
},
|
|
23
27
|
en: {
|
|
28
|
+
"tasks.shell.tagline": "Design reference",
|
|
29
|
+
"tasks.assistant.label": "Assistant",
|
|
30
|
+
"tasks.assistant.description": "The assistant is not connected in the walkthrough.",
|
|
31
|
+
"tasks.assistant.close": "Close",
|
|
24
32
|
"tasks.nav.group": "General",
|
|
25
33
|
"tasks.nav.list": "Tasks",
|
|
26
34
|
"tasks.nav.new": "New task",
|
|
@@ -5,7 +5,7 @@ File-based migrations for Event-Sourcing operations — like `kumiko schema appl
|
|
|
5
5
|
## What it shows
|
|
6
6
|
|
|
7
7
|
- **`seedsDir`-Option** in `runProdApp({ seedsDir: "./seeds" })` — beim Boot werden pending Files in chronologischer Reihenfolge angewendet und in `kumiko_es_operations` markiert.
|
|
8
|
-
- **`SeedMigration`-Interface** — default-Export einer seed-File mit `description` + `run(ctx)`. ctx liefert `systemWriteAs` (System-User bypassed Access-Check) + Read-Helpers (`findUserByEmail`, `findMembershipsOfUser`, `findTenants`).
|
|
8
|
+
- **`SeedMigration`-Interface** — default-Export einer seed-File mit `description` + `run(ctx)`. ctx liefert `systemWriteAs` (System-User bypassed Access-Check) + Read-Helpers (`findUserByEmail`, `findMembershipsOfUser`, `findTenants`, `findTemplateResources`).
|
|
9
9
|
- **Idempotency** — Marker landet nach Erfolg in der Tracking-Tabelle, zweiter Boot skipped applied Seeds.
|
|
10
10
|
- **Tx-Atomicity** — Jede Migration läuft in eigener Transaction; Failure rollt zurück + bricht Boot ab (kein Partial-Apply).
|
|
11
11
|
- **Chronologische File-IDs** — Filename `<date>-<slug>.ts` (z.B. `2026-05-20-fix-admin-roles.ts`) ist die ID.
|
|
@@ -35,6 +35,18 @@ seed: 2026-05-20-fix-admin-roles.ts
|
|
|
35
35
|
|
|
36
36
|
Bei typo / drift fail-t mit klarer message + exit-code 1 — CI nutzt es als prä-build-step. App-Author muss in `smoke.ts` den `features`-Array gegen die eigene App-Feature-Set tauschen (siehe TODO im File).
|
|
37
37
|
|
|
38
|
+
### Archive template rows
|
|
39
|
+
|
|
40
|
+
`findTemplateResources({ slug?, kind?, status?, locale?, tenantId? })` replaces a raw `SELECT … FROM read_template_resources`. It defaults to the system tenant and returns `[]` when template-resolver is not mounted:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
for (const t of await ctx.findTemplateResources({ kind: "notification", status: "active" })) {
|
|
44
|
+
await ctx.systemWriteAs("template-resolver:write:archive", { id: t.id }, SYSTEM_TENANT_ID, [
|
|
45
|
+
"SystemAdmin",
|
|
46
|
+
]);
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
38
50
|
## When to reach for it
|
|
39
51
|
|
|
40
52
|
Du hast einen idempotent-Seeder der bei initialer Erstellung „Insert wenn nicht existiert" macht (z.B. `auth.admin.memberships`), und dann ändern sich die Soll-Daten — neue Rolle, anderer Tier, korrigierte Bezeichnung. Idempotent-Seeder skippen die existing Rows → DB driftet vom Code-Stand ab.
|