@cosmicdrift/kumiko-framework 0.363.0 → 0.365.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/AGENTS.md +338 -0
- package/agents/examples/access-control.md +355 -0
- package/agents/examples/anonymous-access-multitenant.md +446 -0
- package/agents/examples/anonymous-access.md +288 -0
- package/agents/examples/apex-landing.md +528 -0
- package/agents/examples/apex-surface-auth.md +355 -0
- package/agents/examples/api-worker-split.md +434 -0
- package/agents/examples/auth-claims.md +351 -0
- package/agents/examples/auth-foundation-providers.md +155 -0
- package/agents/examples/auth-mfa.md +319 -0
- package/agents/examples/basic-entity.md +420 -0
- package/agents/examples/boot-check.md +122 -0
- package/agents/examples/chat-channels.md +254 -0
- package/agents/examples/compliance-profiles-demo.md +307 -0
- package/agents/examples/cross-feature-events.md +317 -0
- package/agents/examples/crypto-shredding-hr.md +314 -0
- package/agents/examples/currencies-global.md +609 -0
- package/agents/examples/currencies-per-tenant.md +453 -0
- package/agents/examples/custom-fields-basic.md +315 -0
- package/agents/examples/custom-handlers.md +444 -0
- package/agents/examples/dashboard-stats.md +229 -0
- package/agents/examples/delivery-notifications.md +432 -0
- package/agents/examples/designer-demo.md +86 -0
- package/agents/examples/e2e-generator.md +211 -0
- package/agents/examples/embedded-entity-form.md +598 -0
- package/agents/examples/embedded.md +649 -0
- package/agents/examples/encrypted-tenant-config.md +414 -0
- package/agents/examples/error-contract.md +535 -0
- package/agents/examples/event-sourcing.md +1287 -0
- package/agents/examples/feature-toggles.md +274 -0
- package/agents/examples/field-access.md +271 -0
- package/agents/examples/files-post-processing.md +433 -0
- package/agents/examples/i18n.md +166 -0
- package/agents/examples/idempotency.md +179 -0
- package/agents/examples/inbound-mail-triage.md +315 -0
- package/agents/examples/lane-routing.md +246 -0
- package/agents/examples/ledger-banking.md +215 -0
- package/agents/examples/ledger-invoicing.md +236 -0
- package/agents/examples/legal-pages.md +393 -0
- package/agents/examples/lifecycle-hooks.md +368 -0
- package/agents/examples/managed-config.md +428 -0
- package/agents/examples/managed-pages.md +353 -0
- package/agents/examples/notes-history-basic.md +346 -0
- package/agents/examples/ownership.md +404 -0
- package/agents/examples/pdf-audit-export.md +306 -0
- package/agents/examples/pipeline-basics.md +792 -0
- package/agents/examples/public-share-token.md +351 -0
- package/agents/examples/rate-limiting.md +211 -0
- package/agents/examples/realtime-sse.md +187 -0
- package/agents/examples/record-detail-layout.md +297 -0
- package/agents/examples/reference-data.md +151 -0
- package/agents/examples/relations.md +280 -0
- package/agents/examples/screens-nav.md +353 -0
- package/agents/examples/search.md +233 -0
- package/agents/examples/secrets-demo.md +417 -0
- package/agents/examples/security-baseline.md +187 -0
- package/agents/examples/seed-migration.md +99 -0
- package/agents/examples/session-revocation.md +250 -0
- package/agents/examples/state-machine.md +920 -0
- package/agents/examples/tags-basic.md +401 -0
- package/agents/examples/tenant-isolation.md +173 -0
- package/agents/examples/tenant-settings.md +275 -0
- package/agents/examples/tier-admin.md +347 -0
- package/agents/examples/timezones.md +366 -0
- package/agents/examples/user-data-rights.md +418 -0
- package/agents/examples/user-profile.md +226 -0
- package/agents/examples/webhook-step.md +597 -0
- package/agents/examples/wizard-form.md +379 -0
- package/agents/examples/workflow-engine.md +1731 -0
- package/agents/examples/writeform-section.md +300 -0
- package/agents/examples.md +75 -0
- package/agents/features.md +768 -0
- package/agents/widgets.md +181 -0
- package/dist/api/auth-middleware.d.ts +2 -0
- package/dist/api/auth-middleware.js +7 -0
- package/dist/api/auth-routes.d.ts +0 -1
- package/dist/api/auth-routes.js +49 -46
- package/dist/api/extra-route.d.ts +3 -0
- package/dist/api/index.d.ts +2 -2
- package/dist/api/index.js +1 -1
- package/dist/api/routes.js +46 -17
- package/dist/api/server.d.ts +4 -3
- package/dist/api/server.js +39 -10
- package/dist/api/session-cookies.d.ts +1 -0
- package/dist/api/session-cookies.js +20 -5
- package/dist/api/sse-route.js +16 -1
- package/dist/bun-db/connection.js +3 -16
- package/dist/bun-db/index.d.ts +1 -1
- package/dist/bun-db/index.js +1 -1
- package/dist/bun-db/query.d.ts +15 -3
- package/dist/bun-db/query.js +76 -24
- package/dist/crypto/owner-transition-rekey.d.ts +1 -0
- package/dist/crypto/owner-transition-rekey.js +7 -3
- package/dist/crypto/pii-field-encryption.d.ts +1 -0
- package/dist/crypto/pii-field-encryption.js +9 -2
- package/dist/crypto/subject-resolver.d.ts +1 -0
- package/dist/crypto/subject-resolver.js +7 -0
- package/dist/db/api.d.ts +4 -3
- package/dist/db/apply-entity-event.js +26 -2
- package/dist/db/blind-index-cleanup.js +2 -1
- package/dist/db/bun-provider.js +9 -18
- package/dist/db/collect-table-metas.js +11 -7
- package/dist/db/dialect.d.ts +1 -1
- package/dist/db/dialect.js +2 -0
- package/dist/db/eagerload.js +4 -3
- package/dist/db/event-store-executor-context.d.ts +6 -6
- package/dist/db/event-store-executor-context.js +25 -22
- package/dist/db/event-store-executor-read.js +31 -16
- package/dist/db/event-store-executor-write.d.ts +1 -1
- package/dist/db/event-store-executor-write.js +84 -63
- package/dist/db/index.d.ts +2 -1
- package/dist/db/index.js +2 -1
- package/dist/db/lock-guard.d.ts +4 -0
- package/dist/db/lock-guard.js +14 -0
- package/dist/db/migrate-generator.js +1 -1
- package/dist/db/migrate-runner.d.ts +1 -0
- package/dist/db/migrate-runner.js +64 -38
- package/dist/db/queries/backfill-pii.js +63 -25
- package/dist/db/queries/event-consumer.d.ts +6 -6
- package/dist/db/queries/event-consumer.js +2 -1
- package/dist/db/queries/event-store-transfer.js +15 -4
- package/dist/db/queries/event-store.d.ts +1 -1
- package/dist/db/queries/event-store.js +11 -10
- package/dist/db/queries/pii-backfill-state.js +3 -2
- package/dist/db/queries/postgres-array-literal.d.ts +2 -0
- package/dist/db/queries/postgres-array-literal.js +6 -0
- package/dist/db/queries/projection-rebuild.d.ts +1 -1
- package/dist/db/queries/projection-rebuild.js +3 -2
- package/dist/db/queries/shadow-swap.d.ts +1 -1
- package/dist/db/queries/shadow-swap.js +12 -8
- package/dist/db/query.d.ts +1 -1
- package/dist/db/query.js +1 -1
- package/dist/db/retired-framework-tables.js +22 -4
- package/dist/db/table-builder.js +6 -2
- package/dist/db/tenant-db-runner.d.ts +4 -0
- package/dist/db/tenant-db-runner.js +17 -0
- package/dist/db/tenant-db.d.ts +4 -0
- package/dist/db/tenant-db.js +50 -5
- package/dist/derivatives/delete-stored-file.d.ts +4 -0
- package/dist/derivatives/delete-stored-file.js +9 -0
- package/dist/derivatives/derivatives-context.js +1 -1
- package/dist/derivatives/index.d.ts +1 -1
- package/dist/derivatives/index.js +1 -1
- package/dist/engine/boot-validator/access-declarations.js +2 -2
- package/dist/engine/boot-validator/api-ext.js +3 -3
- package/dist/engine/boot-validator/boot-check.js +1 -1
- package/dist/engine/boot-validator/config-deps.js +13 -13
- package/dist/engine/boot-validator/detail-screens.js +1 -1
- package/dist/engine/boot-validator/entity-handler.d.ts +1 -0
- package/dist/engine/boot-validator/entity-handler.js +87 -35
- package/dist/engine/boot-validator/entity-list-screens.js +2 -2
- package/dist/engine/boot-validator/handler-field-references.js +19 -9
- package/dist/engine/boot-validator/i18n-keys.js +2 -2
- package/dist/engine/boot-validator/nav.js +1 -1
- package/dist/engine/boot-validator/pii-retention.js +8 -8
- package/dist/engine/boot-validator/projection-list-screens.js +5 -5
- package/dist/engine/boot-validator/query-output-columns.js +7 -7
- package/dist/engine/boot-validator/query-refs.js +14 -2
- package/dist/engine/boot-validator/screens.d.ts +2 -1
- package/dist/engine/boot-validator/screens.js +153 -95
- package/dist/engine/boot-validator/url-prefill-fields.js +54 -35
- package/dist/engine/dedupe-features.js +31 -4
- package/dist/engine/define-handler.d.ts +2 -2
- package/dist/engine/define-handler.js +8 -1
- package/dist/engine/entity-handlers.js +14 -7
- package/dist/engine/feature-ast/extractors/handlers.js +2 -0
- package/dist/engine/feature-ast/pattern-change-schema.d.ts +2 -0
- package/dist/engine/feature-ast/pattern-change-schema.js +1 -0
- package/dist/engine/feature-ast/render.js +10 -2
- package/dist/engine/feature-entity-handlers.d.ts +2 -2
- package/dist/engine/feature-entity-handlers.js +12 -3
- package/dist/engine/handler-field-references.d.ts +21 -2
- package/dist/engine/handler-field-references.js +55 -17
- package/dist/engine/index.d.ts +3 -3
- package/dist/engine/index.js +1 -1
- package/dist/engine/schema-builder.js +2 -1
- package/dist/engine/screen-helpers.d.ts +1 -0
- package/dist/engine/screen-helpers.js +2 -2
- package/dist/engine/soft-delete-cleanup.js +10 -3
- package/dist/engine/steps/_read-source.js +5 -2
- package/dist/engine/steps/retry.js +2 -1
- package/dist/engine/steps/unsafe-projection-delete.js +2 -2
- package/dist/engine/steps/unsafe-projection-upsert.js +2 -2
- package/dist/engine/template-variables.d.ts +3 -0
- package/dist/engine/template-variables.js +3 -0
- package/dist/engine/tier-resolver-extension.d.ts +1 -0
- package/dist/engine/tier-resolver-extension.js +6 -0
- package/dist/engine/types/index.d.ts +1 -1
- package/dist/entrypoint/index.d.ts +2 -2
- package/dist/env/_zod-introspect.d.ts +1 -0
- package/dist/errors/classes.js +1 -0
- package/dist/errors/docs-url.js +6 -6
- package/dist/errors/index.d.ts +1 -1
- package/dist/errors/index.js +1 -1
- package/dist/errors/kumiko-error.d.ts +2 -0
- package/dist/errors/kumiko-error.js +2 -0
- package/dist/errors/subject-erased.d.ts +1 -0
- package/dist/errors/subject-erased.js +6 -0
- package/dist/errors/write-error-info.js +2 -0
- package/dist/event-store/admin-api.js +3 -2
- package/dist/event-store/errors.d.ts +9 -0
- package/dist/event-store/errors.js +20 -0
- package/dist/event-store/event-store.d.ts +6 -0
- package/dist/event-store/event-store.js +28 -6
- package/dist/event-store/index.d.ts +1 -1
- package/dist/event-store/index.js +1 -1
- package/dist/event-store/tenant-db-append.js +2 -2
- package/dist/files/assert-file-refs-belong-to-tenant.d.ts +4 -5
- package/dist/files/assert-file-refs-belong-to-tenant.js +7 -15
- package/dist/files/bind-pending-file-refs.d.ts +2 -0
- package/dist/files/bind-pending-file-refs.js +3 -3
- package/dist/files/bind-referenced-files.write.d.ts +1 -1
- package/dist/files/bind-referenced-files.write.js +22 -13
- package/dist/files/create-file-ref-from-bytes.d.ts +6 -3
- package/dist/files/create-file-ref-from-bytes.js +67 -4
- package/dist/files/create-file-ref.d.ts +24 -1
- package/dist/files/create-file-ref.js +67 -25
- package/dist/files/dispose-removed-file-refs.js +21 -6
- package/dist/files/feature.d.ts +1 -0
- package/dist/files/feature.js +2 -1
- package/dist/files/file-handle.d.ts +1 -1
- package/dist/files/file-handle.js +12 -0
- package/dist/files/file-routes.js +10 -6
- package/dist/files/index.d.ts +3 -3
- package/dist/files/index.js +2 -2
- package/dist/files/load-save-file-refs.d.ts +10 -0
- package/dist/files/load-save-file-refs.js +47 -0
- package/dist/files/purge-expired-file-ref-bytes.d.ts +4 -1
- package/dist/files/purge-expired-file-ref-bytes.js +46 -21
- package/dist/files/resolve-content-type.js +40 -4
- package/dist/files/storage-tracking.js +5 -4
- package/dist/files/types.js +5 -8
- package/dist/files/zip-entry-names.d.ts +1 -0
- package/dist/files/zip-entry-names.js +46 -0
- package/dist/jobs/index.d.ts +1 -1
- package/dist/jobs/job-runner.d.ts +5 -1
- package/dist/jobs/job-runner.js +124 -37
- package/dist/observability/escape-hatch-report.d.ts +2 -1
- package/dist/observability/escape-hatch-report.js +48 -7
- package/dist/observability/index.d.ts +1 -1
- package/dist/observability/index.js +1 -1
- package/dist/observability/metrics-handle.d.ts +1 -0
- package/dist/observability/metrics-handle.js +7 -0
- package/dist/observability/standard-metrics.js +4 -4
- package/dist/pipeline/cascade-handler.js +5 -2
- package/dist/pipeline/dispatch-batch.js +79 -31
- package/dist/pipeline/dispatch-query.d.ts +2 -1
- package/dist/pipeline/dispatch-query.js +6 -6
- package/dist/pipeline/dispatch-shared.d.ts +7 -2
- package/dist/pipeline/dispatch-shared.js +136 -48
- package/dist/pipeline/dispatch-stream.js +10 -4
- package/dist/pipeline/dispatch-write.js +34 -22
- package/dist/pipeline/dispatcher.js +3 -1
- package/dist/pipeline/event-dispatcher.d.ts +2 -2
- package/dist/pipeline/event-dispatcher.js +11 -9
- package/dist/pipeline/event-retention.d.ts +1 -0
- package/dist/pipeline/event-retention.js +7 -1
- package/dist/pipeline/index.d.ts +1 -0
- package/dist/pipeline/index.js +1 -0
- package/dist/pipeline/notify-scope.js +3 -1
- package/dist/pipeline/pre-transaction-reservations.d.ts +3 -1
- package/dist/pipeline/pre-transaction-reservations.js +29 -9
- package/dist/rate-limit/bucket.d.ts +3 -3
- package/dist/rate-limit/bucket.js +14 -4
- package/dist/redis/cache-sync-bus.js +9 -3
- package/dist/schema-cli.js +12 -1
- package/dist/search/meilisearch-adapter.js +36 -9
- package/dist/stack/db.d.ts +2 -2
- package/dist/stack/test-stack.js +2 -1
- package/dist/testing/index.d.ts +1 -0
- package/dist/testing/index.js +1 -0
- package/dist/testing/multipart-helper.d.ts +6 -0
- package/dist/testing/multipart-helper.js +1 -1
- package/dist/testing/zip-fixture.d.ts +1 -0
- package/dist/testing/zip-fixture.js +33 -0
- package/dist/ui-types/card-column-roles.js +4 -2
- package/dist/ui-types/index.d.ts +1 -1
- package/dist/ui-types/index.js +1 -1
- package/dist/upgrade-cli.js +46 -13
- package/package.json +7 -5
- package/src/changes.json +512 -8
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
<!-- Generated by `bun run gen:agent-docs` from samples/recipes/e2e-generator. Do not edit. -->
|
|
2
|
+
|
|
3
|
+
# e2e-generator
|
|
4
|
+
|
|
5
|
+
generateE2ESpec + withBootValidatorFixture — Registry → JSON-Specs für externen Playwright-Worker. Zeigt die 4 Test-Kinds, Feldtyp→Interaktion-Mapping und welche Feldtypen heute noch nicht generisch unterstützt sind.
|
|
6
|
+
|
|
7
|
+
## README
|
|
8
|
+
|
|
9
|
+
# E2E generator
|
|
10
|
+
|
|
11
|
+
Generate Playwright E2E specs from the registry.
|
|
12
|
+
|
|
13
|
+
## What it shows
|
|
14
|
+
|
|
15
|
+
- `generateE2ESpec` (+ `withBootValidatorFixture` in the test) → JSON specs for an external Playwright worker
|
|
16
|
+
- The four test kinds and field-type → interaction mapping
|
|
17
|
+
|
|
18
|
+
## Source
|
|
19
|
+
|
|
20
|
+
Feature entry point: `src/feature.ts`.
|
|
21
|
+
|
|
22
|
+
## Tests
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
cd samples/recipes/e2e-generator
|
|
26
|
+
bun test
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Source files
|
|
30
|
+
|
|
31
|
+
### src/__tests__/feature.test.ts
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
// E2E-Generator Sample — Unit-Test.
|
|
35
|
+
//
|
|
36
|
+
// Zweck: zeigt einen realistischen Generator-Run (shop-Feature mit allen
|
|
37
|
+
// unterstützten + ein paar bewusst unsupported Feldtypen). Der Snapshot
|
|
38
|
+
// dokumentiert das Ergebnis; jeder Feature-Autor der den Generator zum
|
|
39
|
+
// ersten Mal anfasst kann hier reinschauen statt in die Implementation.
|
|
40
|
+
|
|
41
|
+
import { describe, expect, test } from "bun:test";
|
|
42
|
+
import {
|
|
43
|
+
createRegistry,
|
|
44
|
+
validateBoot as validateBootRaw,
|
|
45
|
+
} from "@cosmicdrift/kumiko-framework/engine";
|
|
46
|
+
import { generateE2ESpec, withBootValidatorFixture } from "@cosmicdrift/kumiko-framework/testing";
|
|
47
|
+
import { createShopFeature } from "../feature";
|
|
48
|
+
|
|
49
|
+
function validateBoot(features: Parameters<typeof validateBootRaw>[0]): void {
|
|
50
|
+
validateBootRaw(withBootValidatorFixture(features));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const shop = createShopFeature();
|
|
54
|
+
const registry = createRegistry([shop]);
|
|
55
|
+
|
|
56
|
+
describe("e2e-generator sample — shop feature", () => {
|
|
57
|
+
test("validateBoot akzeptiert das Feature", () => {
|
|
58
|
+
expect(() => validateBoot([shop])).not.toThrow();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test("generateE2ESpec liefert alle vier Kinds für das List+Edit-Paar", () => {
|
|
62
|
+
const specs = generateE2ESpec(registry);
|
|
63
|
+
const kinds = specs.map((s) => s.kind).sort();
|
|
64
|
+
expect(kinds).toEqual([
|
|
65
|
+
"edit-save-persists",
|
|
66
|
+
"edit-validates-required",
|
|
67
|
+
"list-has-fixture-row",
|
|
68
|
+
"list-renders",
|
|
69
|
+
]);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test("list-has-fixture-row referenziert den Create-Handler + nutzt name als Identifying", () => {
|
|
73
|
+
const specs = generateE2ESpec(registry);
|
|
74
|
+
const row = specs.find((s) => s.kind === "list-has-fixture-row");
|
|
75
|
+
if (row?.kind !== "list-has-fixture-row") throw new Error("unreachable");
|
|
76
|
+
|
|
77
|
+
expect(row.writeHandlerQn).toBe("shop:write:product:create");
|
|
78
|
+
expect(row.urlPath).toBe("/t/{tenant}/shop/product-list");
|
|
79
|
+
// name ist die erste Text-Column → Identifying-Value
|
|
80
|
+
expect(row.identifyingValue).toBe("e2e name");
|
|
81
|
+
// money hat eine generische Object-Fixture → landet im API-Seed (die API
|
|
82
|
+
// erwartet { amount, currency }), aber NICHT im Edit-Form (siehe
|
|
83
|
+
// edit-save-persists-Test unten — kein Form-Widget generisch).
|
|
84
|
+
expect(row.fixture["listPrice"]).toEqual({ amount: 1, currency: "EUR" });
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test("edit-validates-required listet nur echte required-Felder (name, price)", () => {
|
|
88
|
+
const specs = generateE2ESpec(registry);
|
|
89
|
+
const validates = specs.find((s) => s.kind === "edit-validates-required");
|
|
90
|
+
if (validates?.kind !== "edit-validates-required") throw new Error("unreachable");
|
|
91
|
+
expect(validates.requiredFields).toEqual(["name", "price"]);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test("edit-save-persists mapped Feldtypen auf die richtigen Playwright-Interaktionen", () => {
|
|
95
|
+
const specs = generateE2ESpec(registry);
|
|
96
|
+
const save = specs.find((s) => s.kind === "edit-save-persists");
|
|
97
|
+
if (save?.kind !== "edit-save-persists") throw new Error("unreachable");
|
|
98
|
+
|
|
99
|
+
const opsByField = new Map(save.fills.map((op) => [op.field, op.kind]));
|
|
100
|
+
expect(opsByField.get("name")).toBe("fill");
|
|
101
|
+
expect(opsByField.get("description")).toBe("fill");
|
|
102
|
+
expect(opsByField.get("price")).toBe("fill");
|
|
103
|
+
// DER eigentliche Regression-Guard: select darf NICHT auf .fill() landen,
|
|
104
|
+
// sonst zerschellt Playwright am ersten Dropdown.
|
|
105
|
+
expect(opsByField.get("status")).toBe("select");
|
|
106
|
+
expect(opsByField.get("featured")).toBe("check");
|
|
107
|
+
// money (listPrice) wird im Form bewusst übersprungen — komplexes
|
|
108
|
+
// Widget (Betrag + Währung), das der Generator nicht generisch
|
|
109
|
+
// automatisieren kann. API-Seed nutzt es trotzdem (siehe Test oben).
|
|
110
|
+
expect(opsByField.has("listPrice")).toBe(false);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test("Output ist JSON-serialisierbar (Prozess-Grenze zu Playwright-Worker)", () => {
|
|
114
|
+
// Das Sample-Feature muss sich rundtrippen lassen: TestSpec → JSON.stringify →
|
|
115
|
+
// JSON.parse. Im produktiven Setup schreibt ein bun-Subprozess (globalSetup)
|
|
116
|
+
// die JSON auf Platte, der Playwright-Worker liest sie — kein runtime-Import
|
|
117
|
+
// vom Framework im Test-Prozess (würde mit Playwrights expect kollidieren).
|
|
118
|
+
const specs = generateE2ESpec(registry);
|
|
119
|
+
const roundtripped = JSON.parse(JSON.stringify(specs));
|
|
120
|
+
expect(roundtripped).toEqual(specs);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### src/feature.ts
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
import {
|
|
129
|
+
createBooleanField,
|
|
130
|
+
createEntity,
|
|
131
|
+
createMoneyField,
|
|
132
|
+
createNumberField,
|
|
133
|
+
createSelectField,
|
|
134
|
+
createTextField,
|
|
135
|
+
defineFeature,
|
|
136
|
+
type FeatureDefinition,
|
|
137
|
+
} from "@cosmicdrift/kumiko-framework/engine";
|
|
138
|
+
|
|
139
|
+
export const productEntity = createEntity({
|
|
140
|
+
table: "read_products",
|
|
141
|
+
fields: {
|
|
142
|
+
name: createTextField({
|
|
143
|
+
personal: false,
|
|
144
|
+
reason: "is_business_data",
|
|
145
|
+
required: true,
|
|
146
|
+
maxLength: 200,
|
|
147
|
+
}),
|
|
148
|
+
description: createTextField({ maxLength: 2000, personal: false, reason: "is_business_data" }),
|
|
149
|
+
price: createNumberField({ required: true }),
|
|
150
|
+
status: createSelectField({ options: ["draft", "published", "archived"] as const }),
|
|
151
|
+
featured: createBooleanField({ default: false }),
|
|
152
|
+
listPrice: createMoneyField({}),
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
const editorWrite = { access: { roles: ["Admin", "Editor"] } } as const;
|
|
157
|
+
|
|
158
|
+
export function createShopFeature(): FeatureDefinition {
|
|
159
|
+
return defineFeature("shop", (r) => {
|
|
160
|
+
r.systemScope();
|
|
161
|
+
r.crud("product", productEntity, {
|
|
162
|
+
write: editorWrite,
|
|
163
|
+
verbs: { list: false, detail: false, restore: false },
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
r.screen({
|
|
167
|
+
id: "product-list",
|
|
168
|
+
type: "entityList",
|
|
169
|
+
entity: "product",
|
|
170
|
+
columns: [
|
|
171
|
+
"name",
|
|
172
|
+
{ field: "price", renderer: { format: "currency", symbol: "€" } },
|
|
173
|
+
"status",
|
|
174
|
+
"featured",
|
|
175
|
+
],
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
r.screen({
|
|
179
|
+
id: "product-edit",
|
|
180
|
+
type: "entityEdit",
|
|
181
|
+
entity: "product",
|
|
182
|
+
layout: {
|
|
183
|
+
sections: [
|
|
184
|
+
{
|
|
185
|
+
title: "shop:section.basics",
|
|
186
|
+
columns: 2,
|
|
187
|
+
fields: ["name", { field: "description", span: 2 }],
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
title: "shop:section.publishing",
|
|
191
|
+
columns: 2,
|
|
192
|
+
fields: ["price", "status", "featured"],
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
title: "shop:section.pricing",
|
|
196
|
+
fields: ["listPrice"],
|
|
197
|
+
},
|
|
198
|
+
],
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
r.nav({
|
|
203
|
+
id: "products",
|
|
204
|
+
label: "shop:nav.products",
|
|
205
|
+
icon: "package",
|
|
206
|
+
screen: "shop:screen:product-list",
|
|
207
|
+
order: 10,
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
```
|