@cosmicdrift/kumiko-framework 0.362.0 → 0.364.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 +307 -0
- package/agents/examples/access-control.md +355 -0
- package/agents/examples/anonymous-access-multitenant.md +443 -0
- package/agents/examples/anonymous-access.md +300 -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 +323 -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 +314 -0
- package/agents/examples/custom-handlers.md +397 -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 +405 -0
- package/agents/examples/error-contract.md +539 -0
- package/agents/examples/event-sourcing.md +1287 -0
- package/agents/examples/feature-toggles.md +263 -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 +214 -0
- package/agents/examples/ledger-invoicing.md +235 -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 +345 -0
- package/agents/examples/ownership.md +396 -0
- package/agents/examples/pdf-audit-export.md +270 -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 +259 -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 +410 -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 +74 -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 +14 -5
- package/dist/api/auth-routes.js +5 -3
- 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/redis-sse-broker.js +10 -8
- package/dist/api/routes.js +48 -19
- package/dist/api/server.d.ts +2 -1
- package/dist/api/server.js +18 -6
- 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/index.d.ts +1 -1
- package/dist/bun-db/index.js +1 -1
- package/dist/bun-db/query.d.ts +12 -5
- package/dist/bun-db/query.js +88 -94
- package/dist/crypto/kek-source.js +5 -3
- package/dist/crypto/pii-field-encryption.d.ts +4 -1
- package/dist/crypto/pii-field-encryption.js +2 -2
- package/dist/db/apply-entity-event.js +2 -2
- package/dist/db/collect-table-metas.js +11 -7
- package/dist/db/cursor.js +2 -1
- package/dist/db/dialect.d.ts +1 -0
- package/dist/db/dialect.js +28 -13
- package/dist/db/eagerload.js +2 -2
- package/dist/db/entity-table-from-registry.js +1 -1
- package/dist/db/entity-table-meta.js +5 -13
- package/dist/db/event-store-executor-context.d.ts +5 -6
- package/dist/db/event-store-executor-context.js +29 -27
- package/dist/db/event-store-executor-read.js +40 -25
- package/dist/db/event-store-executor-write.js +18 -20
- package/dist/db/index.d.ts +1 -1
- package/dist/db/index.js +1 -1
- package/dist/db/lock-guard.d.ts +4 -0
- package/dist/db/lock-guard.js +14 -0
- package/dist/db/migrate-generator.js +6 -4
- package/dist/db/migrate-runner.js +32 -35
- package/dist/db/parent-ref-clause.js +2 -2
- package/dist/db/queries/backfill-pii.js +11 -9
- package/dist/db/queries/es-ops.js +1 -1
- package/dist/db/queries/event-consumer.js +17 -17
- package/dist/db/queries/event-store-admin.js +6 -6
- package/dist/db/queries/event-store-transfer.js +2 -2
- package/dist/db/queries/event-store.js +2 -2
- package/dist/db/queries/pii-backfill-state.js +2 -2
- package/dist/db/queries/raw-sql.js +1 -1
- package/dist/db/queries/test-stack.js +1 -1
- package/dist/db/reference-data.js +3 -5
- package/dist/db/table-builder.js +6 -4
- package/dist/db/table-introspection.d.ts +16 -0
- package/dist/db/table-introspection.js +76 -0
- 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 +5 -2
- package/dist/db/tenant-db.js +34 -14
- package/dist/derivatives/derivatives-context.js +1 -1
- package/dist/derivatives/variant-key.js +2 -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 +84 -35
- package/dist/engine/boot-validator/entity-list-screens.js +3 -3
- 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 +9 -9
- 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/screens.d.ts +2 -1
- package/dist/engine/boot-validator/screens.js +155 -96
- package/dist/engine/boot-validator/url-prefill-fields.js +54 -35
- package/dist/engine/changeset-changes.js +3 -3
- package/dist/engine/define-handler.d.ts +2 -2
- package/dist/engine/define-handler.js +11 -7
- package/dist/engine/embedded-derived.js +10 -6
- package/dist/engine/extensions/escape-hatch-usage.js +2 -1
- package/dist/engine/factories.js +5 -6
- package/dist/engine/feature-ast/extractors/events.js +43 -33
- package/dist/engine/feature-ast/extractors/handlers.js +2 -0
- package/dist/engine/feature-ast/patcher.d.ts +3 -3
- package/dist/engine/feature-ast/patcher.js +3 -3
- package/dist/engine/feature-ast/pattern-change-schema.d.ts +10 -8
- package/dist/engine/feature-ast/pattern-change-schema.js +4 -3
- package/dist/engine/feature-ast/patterns.d.ts +3 -3
- package/dist/engine/feature-ast/render.js +16 -5
- package/dist/engine/feature-changelog.d.ts +2 -1
- package/dist/engine/feature-changelog.js +8 -6
- package/dist/engine/feature-config-events-jobs.d.ts +17 -7
- package/dist/engine/feature-config-events-jobs.js +20 -5
- package/dist/engine/feature-entity-handlers.d.ts +2 -2
- package/dist/engine/feature-entity-handlers.js +12 -3
- package/dist/engine/feature-ui-extensions.js +2 -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 -2
- package/dist/engine/index.js +1 -0
- package/dist/engine/ownership.js +7 -20
- package/dist/engine/pattern-library/mixed-schemas.js +0 -1
- package/dist/engine/registry-ingest.d.ts +2 -1
- package/dist/engine/registry-ingest.js +85 -2
- package/dist/engine/registry-validate.d.ts +1 -0
- package/dist/engine/registry-validate.js +38 -8
- package/dist/engine/registry.js +2 -1
- package/dist/engine/schema-builder.js +3 -4
- package/dist/engine/soft-delete-cleanup.js +12 -4
- package/dist/engine/steps/call-feature.js +1 -3
- 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 +4 -15
- package/dist/engine/template-variables.d.ts +32 -0
- package/dist/engine/template-variables.js +80 -0
- package/dist/engine/tier-resolver-extension.js +2 -3
- package/dist/engine/types/index.d.ts +2 -2
- package/dist/engine/validate-projection-allowlist.js +12 -13
- package/dist/engine/where-rule-lint.js +8 -7
- package/dist/env/_zod-introspect.d.ts +1 -0
- package/dist/errors/classes.js +1 -0
- package/dist/errors/kumiko-error.d.ts +2 -0
- package/dist/errors/kumiko-error.js +2 -0
- package/dist/errors/reasons.d.ts +1 -0
- package/dist/errors/reasons.js +2 -0
- package/dist/errors/write-error-info.js +2 -0
- 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 +22 -0
- package/dist/files/create-file-ref.js +53 -25
- package/dist/files/file-handle.d.ts +1 -1
- package/dist/files/file-handle.js +8 -0
- package/dist/files/file-routes.js +2 -2
- package/dist/files/index.d.ts +2 -2
- package/dist/files/index.js +1 -1
- package/dist/files/load-save-file-refs.d.ts +10 -0
- package/dist/files/load-save-file-refs.js +47 -0
- package/dist/files/local-provider.js +2 -1
- package/dist/files/purge-expired-file-ref-bytes.d.ts +4 -1
- package/dist/files/purge-expired-file-ref-bytes.js +45 -19
- package/dist/i18n/index.d.ts +1 -1
- package/dist/i18n/index.js +1 -1
- package/dist/i18n/mail-registry.d.ts +2 -0
- package/dist/i18n/mail-registry.js +7 -0
- package/dist/jobs/index.d.ts +1 -1
- package/dist/jobs/job-runner.d.ts +4 -1
- package/dist/jobs/job-runner.js +13 -9
- package/dist/observability/escape-hatch-report.d.ts +1 -1
- package/dist/observability/escape-hatch-report.js +17 -5
- package/dist/pipeline/cascade-handler.js +5 -2
- package/dist/pipeline/dispatch-batch.js +79 -31
- package/dist/pipeline/dispatch-query.js +2 -3
- package/dist/pipeline/dispatch-shared.d.ts +7 -2
- package/dist/pipeline/dispatch-shared.js +142 -34
- package/dist/pipeline/dispatch-write.js +34 -22
- package/dist/pipeline/event-dispatcher-delivery.js +2 -3
- package/dist/pipeline/index.d.ts +2 -0
- package/dist/pipeline/index.js +2 -0
- package/dist/pipeline/member-read-only-transaction.js +1 -1
- package/dist/pipeline/notify-scope.d.ts +13 -0
- package/dist/pipeline/notify-scope.js +32 -0
- package/dist/pipeline/pre-transaction-reservations.d.ts +3 -1
- package/dist/pipeline/pre-transaction-reservations.js +28 -9
- package/dist/pipeline/system-hooks.js +2 -1
- package/dist/pipeline/system-identity-switch.js +2 -2
- 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/search/meilisearch-adapter.js +39 -13
- package/dist/secrets/stored-envelope.js +7 -7
- package/dist/stack/push-entity-projection-tables.js +2 -3
- package/dist/stack/table-helpers.js +10 -26
- package/dist/stack/test-stack.js +2 -5
- package/dist/testing/multipart-helper.d.ts +0 -6
- package/dist/testing/multipart-helper.js +5 -5
- package/dist/testing/without-ambient-temporal.js +4 -4
- package/dist/utils/is-plain-object.d.ts +1 -2
- package/dist/utils/is-plain-object.js +1 -4
- package/package.json +7 -5
- package/src/changes.json +251 -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
|
+
```
|