@cosmicdrift/kumiko-framework 0.258.0 → 0.259.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 +3 -3
- package/src/__tests__/anonymous-access.integration.test.ts +3 -3
- package/src/__tests__/derived-fields.integration.test.ts +1 -1
- package/src/__tests__/entity-list-limits.integration.test.ts +1 -1
- package/src/__tests__/error-contract.integration.test.ts +1 -1
- package/src/__tests__/ownership-where-write-path.integration.test.ts +1 -1
- package/src/__tests__/ownership.integration.test.ts +7 -3
- package/src/__tests__/schema-cli-rebuild.integration.test.ts +2 -2
- package/src/__tests__/transition-guard.integration.test.ts +3 -3
- package/src/api/__tests__/api.test.ts +21 -3
- package/src/api/__tests__/batch.integration.test.ts +3 -3
- package/src/api/__tests__/body-limit.test.ts +7 -1
- package/src/api/__tests__/dispatcher-live.integration.test.ts +1 -1
- package/src/api/__tests__/http-route-rate-limit.integration.test.ts +7 -1
- package/src/api/__tests__/metrics-endpoint.test.ts +7 -1
- package/src/api/__tests__/nested-write.integration.test.ts +3 -3
- package/src/api/__tests__/server-boot-guards.test.ts +11 -4
- package/src/bun-db/__tests__/write-brand.test.ts +4 -1
- package/src/changes.json +6 -0
- package/src/db/__tests__/apply-entity-event-tenant.integration.test.ts +1 -1
- package/src/db/__tests__/assert-exists-in.integration.test.ts +1 -1
- package/src/db/__tests__/assert-no-unreachable-live-rows.integration.test.ts +2 -2
- package/src/db/__tests__/collect-table-metas.test.ts +9 -5
- package/src/db/__tests__/compound-types.test.ts +1 -1
- package/src/db/__tests__/config-seed.integration.test.ts +3 -3
- package/src/db/__tests__/eagerload.integration.test.ts +7 -7
- package/src/db/__tests__/entity-table-from-registry.test.ts +8 -2
- package/src/db/__tests__/entity-table-meta-source.test.ts +7 -3
- package/src/db/__tests__/entity-table-types.test.ts +4 -4
- package/src/db/__tests__/event-store-executor-list.integration.test.ts +9 -2
- package/src/db/__tests__/event-store-executor-reference-search.integration.test.ts +4 -4
- package/src/db/__tests__/event-store-executor-reference-sort.integration.test.ts +3 -3
- package/src/db/__tests__/event-store-executor-write-verbs.integration.test.ts +4 -4
- package/src/db/__tests__/event-store-executor.integration.test.ts +11 -6
- package/src/db/__tests__/event-store-system-stream.integration.test.ts +2 -2
- package/src/db/__tests__/implicit-projection-equivalence.integration.test.ts +6 -4
- package/src/db/__tests__/located-timestamp.test.ts +1 -1
- package/src/db/__tests__/money.test.ts +1 -1
- package/src/db/__tests__/multi-row-insert.integration.test.ts +3 -3
- package/src/db/__tests__/schema-migration.integration.test.ts +30 -14
- package/src/db/__tests__/source-shadow-create.integration.test.ts +1 -1
- package/src/db/__tests__/table-builder-indexes.test.ts +14 -12
- package/src/db/__tests__/table-builder-required.test.ts +2 -2
- package/src/db/__tests__/tenant-db-where-merge.integration.test.ts +1 -1
- package/src/db/__tests__/tenant-db-where-merge.test.ts +5 -2
- package/src/db/__tests__/tenant-db.integration.test.ts +2 -2
- package/src/db/__tests__/unique-violation-mapping.integration.test.ts +2 -2
- package/src/engine/__tests__/boot-validator-action-wiring.test.ts +50 -8
- package/src/engine/__tests__/boot-validator-dashboard.test.ts +138 -1
- package/src/engine/__tests__/boot-validator-detail-for.test.ts +28 -4
- package/src/engine/__tests__/boot-validator-entity-list.test.ts +20 -4
- package/src/engine/__tests__/boot-validator-i18n-keys.test.ts +9 -3
- package/src/engine/__tests__/boot-validator.test.ts +488 -91
- package/src/engine/__tests__/define-feature-entity-mapping.test.ts +2 -2
- package/src/engine/__tests__/engine.test.ts +128 -37
- package/src/engine/__tests__/entity-handlers.test.ts +3 -3
- package/src/engine/__tests__/entity-presave-wiring.integration.test.ts +4 -4
- package/src/engine/__tests__/entity-restore-tenant-isolation.integration.test.ts +1 -1
- package/src/engine/__tests__/entity-write-crosstenant.integration.test.ts +1 -1
- package/src/engine/__tests__/extend-entity-projection.test.ts +1 -1
- package/src/engine/__tests__/extends-registrar.test.ts +13 -3
- package/src/engine/__tests__/factories-long-text.test.ts +10 -6
- package/src/engine/__tests__/feature-crud-shorthand.test.ts +1 -1
- package/src/engine/__tests__/feature-crud-verb-access.integration.test.ts +1 -1
- package/src/engine/__tests__/multiselect-filter.integration.test.ts +1 -1
- package/src/engine/__tests__/nav.test.ts +1 -1
- package/src/engine/__tests__/pipeline-handler.integration.test.ts +1 -1
- package/src/engine/__tests__/pipeline-observability.integration.test.ts +1 -1
- package/src/engine/__tests__/pipeline-performance.integration.test.ts +1 -1
- package/src/engine/__tests__/projection-detail-actions.test.ts +6 -1
- package/src/engine/__tests__/projection-detail-singleton.test.ts +6 -1
- package/src/engine/__tests__/projection-detail-tabs.test.ts +6 -1
- package/src/engine/__tests__/projection-list-filter.integration.test.ts +7 -2
- package/src/engine/__tests__/projection.test.ts +1 -1
- package/src/engine/__tests__/registry.test.ts +13 -3
- package/src/engine/__tests__/schema-builder.test.ts +39 -11
- package/src/engine/__tests__/screen.test.ts +21 -15
- package/src/engine/__tests__/search-payload-extension.test.ts +15 -3
- package/src/engine/__tests__/store-table.test.ts +6 -3
- package/src/engine/__tests__/validate-projection-allowlist.test.ts +12 -4
- package/src/engine/__tests__/validation-hooks.test.ts +7 -1
- package/src/engine/boot-validator/__tests__/ownership.test.ts +2 -2
- package/src/engine/boot-validator/query-refs.ts +11 -0
- package/src/engine/boot-validator/screens.ts +45 -2
- package/src/engine/build-config-feature-schema.ts +2 -2
- package/src/engine/index.ts +2 -0
- package/src/engine/types/index.ts +2 -0
- package/src/es-ops/__tests__/runner.integration.test.ts +1 -1
- package/src/event-store/__tests__/upcaster.integration.test.ts +1 -1
- package/src/files/__tests__/file-field-pipeline.integration.test.ts +1 -1
- package/src/files/__tests__/files.integration.test.ts +1 -1
- package/src/files/file-ref-entity.ts +9 -9
- package/src/i18n/__tests__/i18n.test.ts +7 -1
- package/src/migrations/__tests__/kumiko-drift.integration.test.ts +3 -1
- package/src/migrations/__tests__/pending-rebuilds.integration.test.ts +2 -2
- package/src/pipeline/__tests__/archive-stream.integration.test.ts +1 -1
- package/src/pipeline/__tests__/cascade-handler.integration.test.ts +23 -8
- package/src/pipeline/__tests__/cascade-handler.test.ts +18 -3
- package/src/pipeline/__tests__/causation-chain.integration.test.ts +1 -1
- package/src/pipeline/__tests__/ctx-bridge.integration.test.ts +5 -3
- package/src/pipeline/__tests__/dispatcher.test.ts +42 -6
- package/src/pipeline/__tests__/domain-events-projections.integration.test.ts +2 -2
- package/src/pipeline/__tests__/fetch-for-writing.integration.test.ts +1 -1
- package/src/pipeline/__tests__/lifecycle-pipeline.test.ts +42 -6
- package/src/pipeline/__tests__/load-aggregate-query.integration.test.ts +2 -2
- package/src/pipeline/__tests__/msp-multi-hop.integration.test.ts +1 -1
- package/src/pipeline/__tests__/msp-rebuild.integration.test.ts +6 -2
- package/src/pipeline/__tests__/multi-stream-projection.integration.test.ts +6 -2
- package/src/pipeline/__tests__/perf-rebuild.integration.test.ts +1 -1
- package/src/pipeline/__tests__/post-query-hook.integration.test.ts +3 -3
- package/src/pipeline/__tests__/projection-rebuild.integration.test.ts +3 -3
- package/src/pipeline/__tests__/query-projection.integration.test.ts +1 -1
- package/src/pipeline/__tests__/rebuild-poison-quarantine.integration.test.ts +2 -2
- package/src/pipeline/__tests__/search-consumer-named-events.integration.test.ts +13 -2
- package/src/pipeline/__tests__/try-append-event.integration.test.ts +1 -1
- package/src/search/__tests__/reindex-entity.integration.test.ts +6 -1
- package/src/search/__tests__/search-pii-derived-index.integration.test.ts +7 -1
- package/src/stack/__tests__/ownership-boot-guard.integration.test.ts +1 -1
- package/src/testing/__tests__/e2e-generator.test.ts +15 -5
- package/src/testing/shared-entities.ts +4 -2
- package/src/ui-types/index.ts +2 -0
|
@@ -23,7 +23,7 @@ import { createTenantDb, type TenantDb } from "../tenant-db";
|
|
|
23
23
|
const customerEntity = createEntity({
|
|
24
24
|
table: "read_ref_search_customers",
|
|
25
25
|
fields: {
|
|
26
|
-
name: createTextField({ required: true }),
|
|
26
|
+
name: createTextField({ required: true, personal: false, reason: "test_fixture" }),
|
|
27
27
|
},
|
|
28
28
|
});
|
|
29
29
|
const customerTable = buildEntityTable("refSearchCustomer", customerEntity);
|
|
@@ -31,7 +31,7 @@ const customerTable = buildEntityTable("refSearchCustomer", customerEntity);
|
|
|
31
31
|
const orderEntity = createEntity({
|
|
32
32
|
table: "read_ref_search_orders",
|
|
33
33
|
fields: {
|
|
34
|
-
note: createTextField({ searchable: true }),
|
|
34
|
+
note: createTextField({ searchable: true, personal: false, reason: "test_fixture" }),
|
|
35
35
|
customerId: {
|
|
36
36
|
type: "reference",
|
|
37
37
|
entity: "refSearchCustomer",
|
|
@@ -48,7 +48,7 @@ const orderTable = buildEntityTable("refSearchOrder", orderEntity);
|
|
|
48
48
|
const restrictedOrderEntity = createEntity({
|
|
49
49
|
table: "read_ref_search_restricted_orders",
|
|
50
50
|
fields: {
|
|
51
|
-
note: createTextField({ searchable: true }),
|
|
51
|
+
note: createTextField({ searchable: true, personal: false, reason: "test_fixture" }),
|
|
52
52
|
customerId: {
|
|
53
53
|
type: "reference",
|
|
54
54
|
entity: "refSearchCustomer",
|
|
@@ -66,7 +66,7 @@ const restrictedOrderTable = buildEntityTable("refSearchRestrictedOrder", restri
|
|
|
66
66
|
// (LIST_ROW_META_REFERENCES) is what's under test, not tenant's full schema.
|
|
67
67
|
const tenantMetaEntity = createEntity({
|
|
68
68
|
table: "read_tenants",
|
|
69
|
-
fields: { name: createTextField({ required: true }) },
|
|
69
|
+
fields: { name: createTextField({ required: true, personal: false, reason: "test_fixture" }) },
|
|
70
70
|
});
|
|
71
71
|
const tenantMetaTable = buildEntityTable("tenant", tenantMetaEntity);
|
|
72
72
|
|
|
@@ -19,14 +19,14 @@ import { createTenantDb, type TenantDb } from "../tenant-db";
|
|
|
19
19
|
|
|
20
20
|
const customerEntity = createEntity({
|
|
21
21
|
table: "read_ref_sort_customers",
|
|
22
|
-
fields: { name: createTextField({ required: true }) },
|
|
22
|
+
fields: { name: createTextField({ required: true, personal: false, reason: "test_fixture" }) },
|
|
23
23
|
});
|
|
24
24
|
const customerTable = buildEntityTable("refSortCustomer", customerEntity);
|
|
25
25
|
|
|
26
26
|
const orderEntity = createEntity({
|
|
27
27
|
table: "read_ref_sort_orders",
|
|
28
28
|
fields: {
|
|
29
|
-
note: createTextField(),
|
|
29
|
+
note: createTextField({ personal: false, reason: "test_fixture" }),
|
|
30
30
|
customerId: {
|
|
31
31
|
type: "reference",
|
|
32
32
|
entity: "refSortCustomer",
|
|
@@ -43,7 +43,7 @@ const orderTable = buildEntityTable("refSortOrder", orderEntity);
|
|
|
43
43
|
const restrictedOrderEntity = createEntity({
|
|
44
44
|
table: "read_ref_sort_restricted_orders",
|
|
45
45
|
fields: {
|
|
46
|
-
note: createTextField(),
|
|
46
|
+
note: createTextField({ personal: false, reason: "test_fixture" }),
|
|
47
47
|
customerId: {
|
|
48
48
|
type: "reference",
|
|
49
49
|
entity: "refSortCustomer",
|
|
@@ -44,7 +44,7 @@ afterAll(async () => {
|
|
|
44
44
|
const restrictedEntity = createEntity({
|
|
45
45
|
table: "read_es_write_restricted",
|
|
46
46
|
fields: {
|
|
47
|
-
email: createTextField({ required: true }),
|
|
47
|
+
email: createTextField({ required: true, personal: false, reason: "test_fixture" }),
|
|
48
48
|
},
|
|
49
49
|
softDelete: true,
|
|
50
50
|
access: { write: { Admin: "all" } },
|
|
@@ -189,7 +189,7 @@ describe("event-store-executor write-verbs — entity-level ownership_denied", (
|
|
|
189
189
|
const hardDeleteEntity = createEntity({
|
|
190
190
|
table: "read_es_write_hard",
|
|
191
191
|
fields: {
|
|
192
|
-
email: createTextField({ required: true }),
|
|
192
|
+
email: createTextField({ required: true, personal: false, reason: "test_fixture" }),
|
|
193
193
|
},
|
|
194
194
|
});
|
|
195
195
|
const hardDeleteTable = buildEntityTable("esWriteHard", hardDeleteEntity);
|
|
@@ -340,7 +340,7 @@ describe("event-store-executor write-verbs — field-level ownership_denied", ()
|
|
|
340
340
|
const versionEntity = createEntity({
|
|
341
341
|
table: "read_es_write_version",
|
|
342
342
|
fields: {
|
|
343
|
-
email: createTextField({ required: true }),
|
|
343
|
+
email: createTextField({ required: true, personal: false, reason: "test_fixture" }),
|
|
344
344
|
},
|
|
345
345
|
});
|
|
346
346
|
const versionTable = buildEntityTable("esWriteVersion", versionEntity);
|
|
@@ -394,7 +394,7 @@ describe("event-store-executor write-verbs — version_conflict edge cases", ()
|
|
|
394
394
|
const raceEntity = createEntity({
|
|
395
395
|
table: "read_es_write_race",
|
|
396
396
|
fields: {
|
|
397
|
-
email: createTextField({ required: true }),
|
|
397
|
+
email: createTextField({ required: true, personal: false, reason: "test_fixture" }),
|
|
398
398
|
},
|
|
399
399
|
softDelete: true,
|
|
400
400
|
});
|
|
@@ -21,8 +21,13 @@ import { createTenantDb, type TenantDb } from "../tenant-db";
|
|
|
21
21
|
const entity = createEntity({
|
|
22
22
|
table: "read_es_exec_users",
|
|
23
23
|
fields: {
|
|
24
|
-
email: createTextField({
|
|
25
|
-
|
|
24
|
+
email: createTextField({
|
|
25
|
+
required: true,
|
|
26
|
+
searchable: true,
|
|
27
|
+
personal: false,
|
|
28
|
+
reason: "test_fixture",
|
|
29
|
+
}),
|
|
30
|
+
firstName: createTextField({ personal: false, reason: "test_fixture" }),
|
|
26
31
|
isEnabled: createBooleanField({ default: true }),
|
|
27
32
|
},
|
|
28
33
|
softDelete: true,
|
|
@@ -133,7 +138,7 @@ const SENSITIVE_TEST_KEY = Buffer.from("s3nS!t1vE.kP9xQ2@wN!vL$hR5yT8eU0").toStr
|
|
|
133
138
|
const sensitiveEntity = createEntity({
|
|
134
139
|
table: "read_es_exec_sensitive",
|
|
135
140
|
fields: {
|
|
136
|
-
email: createTextField({ required: true }),
|
|
141
|
+
email: createTextField({ required: true, personal: false, reason: "test_fixture" }),
|
|
137
142
|
passwordHash: createTextField({ sensitive: true, encrypted: true }),
|
|
138
143
|
apiToken: createTextField({ sensitive: true, encrypted: true }),
|
|
139
144
|
},
|
|
@@ -337,7 +342,7 @@ const ENCRYPTION_TEST_KEY = Buffer.from("a]bJm#kP9xQ2@wN!vL$hR5yT8eU0iO3f").toSt
|
|
|
337
342
|
const encryptedEntity = createEntity({
|
|
338
343
|
table: "read_es_exec_encrypted",
|
|
339
344
|
fields: {
|
|
340
|
-
email: createTextField({ required: true }),
|
|
345
|
+
email: createTextField({ required: true, personal: false, reason: "test_fixture" }),
|
|
341
346
|
secretNote: createTextField({ encrypted: true }),
|
|
342
347
|
},
|
|
343
348
|
});
|
|
@@ -346,7 +351,7 @@ const encryptedTable = buildEntityTable("esExecEncrypted", encryptedEntity);
|
|
|
346
351
|
const encryptedSoftDeleteEntity = createEntity({
|
|
347
352
|
table: "read_es_exec_enc_soft",
|
|
348
353
|
fields: {
|
|
349
|
-
email: createTextField({ required: true }),
|
|
354
|
+
email: createTextField({ required: true, personal: false, reason: "test_fixture" }),
|
|
350
355
|
secretNote: createTextField({ encrypted: true }),
|
|
351
356
|
},
|
|
352
357
|
softDelete: true,
|
|
@@ -699,7 +704,7 @@ const piiEntity = createEntity({
|
|
|
699
704
|
find: "none",
|
|
700
705
|
}),
|
|
701
706
|
authorId: createTextField(),
|
|
702
|
-
plain: createTextField(),
|
|
707
|
+
plain: createTextField({ personal: false, reason: "test_fixture" }),
|
|
703
708
|
},
|
|
704
709
|
});
|
|
705
710
|
const piiTable = buildEntityTable("esExecPii", piiEntity);
|
|
@@ -22,11 +22,11 @@ import { createTenantDb } from "../tenant-db";
|
|
|
22
22
|
const systemEntity = createEntity({
|
|
23
23
|
table: "sstream_sys",
|
|
24
24
|
systemStream: true,
|
|
25
|
-
fields: { name: createTextField({ required: true }) },
|
|
25
|
+
fields: { name: createTextField({ required: true, personal: false, reason: "test_fixture" }) },
|
|
26
26
|
});
|
|
27
27
|
const tenantOwnedEntity = createEntity({
|
|
28
28
|
table: "sstream_tn",
|
|
29
|
-
fields: { name: createTextField({ required: true }) },
|
|
29
|
+
fields: { name: createTextField({ required: true, personal: false, reason: "test_fixture" }) },
|
|
30
30
|
});
|
|
31
31
|
|
|
32
32
|
const systemTable = buildEntityTable("sstreamSys", systemEntity);
|
|
@@ -31,8 +31,8 @@ import { createTenantDb, type TenantDb } from "../tenant-db";
|
|
|
31
31
|
const userEntity = createEntity({
|
|
32
32
|
table: "read_implicit_users",
|
|
33
33
|
fields: {
|
|
34
|
-
email: createTextField({ required: true }),
|
|
35
|
-
firstName: createTextField(),
|
|
34
|
+
email: createTextField({ required: true, personal: false, reason: "test_fixture" }),
|
|
35
|
+
firstName: createTextField({ personal: false, reason: "test_fixture" }),
|
|
36
36
|
isEnabled: createBooleanField({ default: true }),
|
|
37
37
|
},
|
|
38
38
|
softDelete: true,
|
|
@@ -204,7 +204,9 @@ describe("implicit-projection / Live==Rebuild equivalence", () => {
|
|
|
204
204
|
test("ohne softDelete → keine restore-apply-key registriert", () => {
|
|
205
205
|
const hardDeleteEntity = createEntity({
|
|
206
206
|
table: "read_implicit_hard",
|
|
207
|
-
fields: {
|
|
207
|
+
fields: {
|
|
208
|
+
name: createTextField({ required: true, personal: false, reason: "test_fixture" }),
|
|
209
|
+
},
|
|
208
210
|
});
|
|
209
211
|
const hardFeature = defineFeature("implicithard", (r) => {
|
|
210
212
|
r.entity("widget", hardDeleteEntity);
|
|
@@ -249,7 +251,7 @@ const SENSITIVE_BIDX_KEY = decodeBlindIndexKey(SENSITIVE_BIDX_KEY_B64);
|
|
|
249
251
|
const sensitiveEntity = createEntity({
|
|
250
252
|
table: sensitiveTable,
|
|
251
253
|
fields: {
|
|
252
|
-
email: createTextField({ required: true }),
|
|
254
|
+
email: createTextField({ required: true, personal: false, reason: "test_fixture" }),
|
|
253
255
|
apiKey: createTextField({ personal: "self", find: "exact" }),
|
|
254
256
|
},
|
|
255
257
|
});
|
|
@@ -8,7 +8,7 @@ import { flattenLocatedTimestamp, rehydrateLocatedTimestamp } from "../located-t
|
|
|
8
8
|
|
|
9
9
|
const orderEntity: EntityDefinition = createEntity({
|
|
10
10
|
fields: {
|
|
11
|
-
clientName: createTextField(),
|
|
11
|
+
clientName: createTextField({ personal: false, reason: "test_fixture" }),
|
|
12
12
|
pickup: createLocatedTimestampField(),
|
|
13
13
|
delivery: createLocatedTimestampField(),
|
|
14
14
|
},
|
|
@@ -12,7 +12,7 @@ import { flattenMoney, type MoneyRead, moneyPayloadToMinorUnits, rehydrateMoney
|
|
|
12
12
|
const orderEntity: EntityDefinition = createEntity({
|
|
13
13
|
defaultCurrency: "EUR",
|
|
14
14
|
fields: {
|
|
15
|
-
label: createTextField(),
|
|
15
|
+
label: createTextField({ personal: false, reason: "test_fixture" }),
|
|
16
16
|
buyingPrice: createMoneyField(),
|
|
17
17
|
sellingPrice: createMoneyField(),
|
|
18
18
|
},
|
|
@@ -18,8 +18,8 @@ import { setupTestStack, type TestStack, unsafeCreateEntityTable } from "../../s
|
|
|
18
18
|
const linkEntity = createEntity({
|
|
19
19
|
table: "mri_links",
|
|
20
20
|
fields: {
|
|
21
|
-
leftId: createTextField({ required: true }),
|
|
22
|
-
rightId: createTextField({ required: true }),
|
|
21
|
+
leftId: createTextField({ required: true, personal: false, reason: "test_fixture" }),
|
|
22
|
+
rightId: createTextField({ required: true, personal: false, reason: "test_fixture" }),
|
|
23
23
|
},
|
|
24
24
|
});
|
|
25
25
|
const linkTable = buildEntityTable("link", linkEntity);
|
|
@@ -42,7 +42,7 @@ describe("instant() customType is forgiving with ISO strings", () => {
|
|
|
42
42
|
|
|
43
43
|
const tsEntity = createEntity({
|
|
44
44
|
table: "mri_ts",
|
|
45
|
-
fields: { name: createTextField({ required: true }) },
|
|
45
|
+
fields: { name: createTextField({ required: true, personal: false, reason: "test_fixture" }) },
|
|
46
46
|
});
|
|
47
47
|
const tsTable = buildEntityTable("ts-row", tsEntity);
|
|
48
48
|
|
|
@@ -80,8 +80,8 @@ describe("schema migration workflows", () => {
|
|
|
80
80
|
createEntity({
|
|
81
81
|
table: "wf1_posts",
|
|
82
82
|
fields: {
|
|
83
|
-
title: createTextField({ required: true }),
|
|
84
|
-
body: createTextField(),
|
|
83
|
+
title: createTextField({ required: true, personal: false, reason: "test_fixture" }),
|
|
84
|
+
body: createTextField({ personal: false, reason: "test_fixture" }),
|
|
85
85
|
viewCount: createNumberField(),
|
|
86
86
|
publishedAt: createDateField(),
|
|
87
87
|
isDraft: createBooleanField({ default: true }),
|
|
@@ -121,7 +121,7 @@ describe("schema migration workflows", () => {
|
|
|
121
121
|
"article",
|
|
122
122
|
createEntity({
|
|
123
123
|
table: "wf1b_articles",
|
|
124
|
-
fields: { title: createTextField() },
|
|
124
|
+
fields: { title: createTextField({ personal: false, reason: "test_fixture" }) },
|
|
125
125
|
}),
|
|
126
126
|
);
|
|
127
127
|
});
|
|
@@ -138,7 +138,7 @@ describe("schema migration workflows", () => {
|
|
|
138
138
|
// Initial entity with just email
|
|
139
139
|
const initialEntity = createEntity({
|
|
140
140
|
table: "wf2_users",
|
|
141
|
-
fields: { email: createTextField() },
|
|
141
|
+
fields: { email: createTextField({ personal: false, reason: "test_fixture" }) },
|
|
142
142
|
});
|
|
143
143
|
await unsafePushTables(testDb.db, { user: buildEntityTable("user", initialEntity) });
|
|
144
144
|
|
|
@@ -146,8 +146,8 @@ describe("schema migration workflows", () => {
|
|
|
146
146
|
const updatedEntity = createEntity({
|
|
147
147
|
table: "wf2_users",
|
|
148
148
|
fields: {
|
|
149
|
-
email: createTextField(),
|
|
150
|
-
displayName: createTextField(), // NEW FIELD
|
|
149
|
+
email: createTextField({ personal: false, reason: "test_fixture" }),
|
|
150
|
+
displayName: createTextField({ personal: false, reason: "test_fixture" }), // NEW FIELD
|
|
151
151
|
},
|
|
152
152
|
});
|
|
153
153
|
|
|
@@ -168,7 +168,7 @@ describe("schema migration workflows", () => {
|
|
|
168
168
|
// Initial entity with just name
|
|
169
169
|
const initialEntity = createEntity({
|
|
170
170
|
table: "wf3_projects",
|
|
171
|
-
fields: { name: createTextField() },
|
|
171
|
+
fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
|
|
172
172
|
});
|
|
173
173
|
const initialTable = buildEntityTable("project", initialEntity);
|
|
174
174
|
await unsafePushTables(testDb.db, { project: initialTable });
|
|
@@ -182,7 +182,10 @@ describe("schema migration workflows", () => {
|
|
|
182
182
|
// Developer adds boolean field with default
|
|
183
183
|
const updatedEntity = createEntity({
|
|
184
184
|
table: "wf3_projects",
|
|
185
|
-
fields: {
|
|
185
|
+
fields: {
|
|
186
|
+
name: createTextField({ personal: false, reason: "test_fixture" }),
|
|
187
|
+
isArchived: createBooleanField({ default: false }),
|
|
188
|
+
},
|
|
186
189
|
});
|
|
187
190
|
const updatedTable = buildEntityTable("project", updatedEntity);
|
|
188
191
|
await unsafePushTables(testDb.db, { project: updatedTable }, { project: initialTable });
|
|
@@ -202,7 +205,9 @@ describe("schema migration workflows", () => {
|
|
|
202
205
|
// greift.
|
|
203
206
|
const initialEntity = createEntity({
|
|
204
207
|
table: "wf3b_users",
|
|
205
|
-
fields: {
|
|
208
|
+
fields: {
|
|
209
|
+
email: createTextField({ required: true, personal: false, reason: "test_fixture" }),
|
|
210
|
+
},
|
|
206
211
|
});
|
|
207
212
|
const initialTable = buildEntityTable("user", initialEntity);
|
|
208
213
|
await unsafePushTables(testDb.db, { user: initialTable });
|
|
@@ -215,8 +220,13 @@ describe("schema migration workflows", () => {
|
|
|
215
220
|
const updatedEntity = createEntity({
|
|
216
221
|
table: "wf3b_users",
|
|
217
222
|
fields: {
|
|
218
|
-
email: createTextField({ required: true }),
|
|
219
|
-
roles: createTextField({
|
|
223
|
+
email: createTextField({ required: true, personal: false, reason: "test_fixture" }),
|
|
224
|
+
roles: createTextField({
|
|
225
|
+
required: true,
|
|
226
|
+
default: "[]",
|
|
227
|
+
personal: false,
|
|
228
|
+
reason: "test_fixture",
|
|
229
|
+
}),
|
|
220
230
|
},
|
|
221
231
|
});
|
|
222
232
|
const updatedTable = buildEntityTable("user", updatedEntity);
|
|
@@ -232,7 +242,7 @@ describe("schema migration workflows", () => {
|
|
|
232
242
|
"task",
|
|
233
243
|
createEntity({
|
|
234
244
|
table: "wf4_tasks",
|
|
235
|
-
fields: { title: createTextField() },
|
|
245
|
+
fields: { title: createTextField({ personal: false, reason: "test_fixture" }) },
|
|
236
246
|
softDelete: true,
|
|
237
247
|
}),
|
|
238
248
|
);
|
|
@@ -253,7 +263,10 @@ describe("schema migration workflows", () => {
|
|
|
253
263
|
const blogFeature = defineFeature("blog", (r) => {
|
|
254
264
|
r.entity(
|
|
255
265
|
"article",
|
|
256
|
-
createEntity({
|
|
266
|
+
createEntity({
|
|
267
|
+
table: "wf5_articles",
|
|
268
|
+
fields: { title: createTextField({ personal: false, reason: "test_fixture" }) },
|
|
269
|
+
}),
|
|
257
270
|
);
|
|
258
271
|
});
|
|
259
272
|
|
|
@@ -262,7 +275,10 @@ describe("schema migration workflows", () => {
|
|
|
262
275
|
"product",
|
|
263
276
|
createEntity({
|
|
264
277
|
table: "wf5_products",
|
|
265
|
-
fields: {
|
|
278
|
+
fields: {
|
|
279
|
+
name: createTextField({ personal: false, reason: "test_fixture" }),
|
|
280
|
+
price: createNumberField(),
|
|
281
|
+
},
|
|
266
282
|
}),
|
|
267
283
|
);
|
|
268
284
|
});
|
|
@@ -23,7 +23,7 @@ const sourceEntity = createEntity({
|
|
|
23
23
|
table: "ssc_source",
|
|
24
24
|
fields: {
|
|
25
25
|
// `source` collides with the EntityTableMeta discriminator key.
|
|
26
|
-
source: createTextField({ required: true }),
|
|
26
|
+
source: createTextField({ required: true, personal: false, reason: "test_fixture" }),
|
|
27
27
|
},
|
|
28
28
|
});
|
|
29
29
|
const sourceTable = buildEntityTable("source-row", sourceEntity);
|
|
@@ -40,8 +40,8 @@ describe("buildEntityTable — entity.indexes", () => {
|
|
|
40
40
|
test("composite unique-index landet als unique=true in Drizzle table-config", () => {
|
|
41
41
|
const entity = createEntity({
|
|
42
42
|
fields: {
|
|
43
|
-
key: createTextField({ required: true }),
|
|
44
|
-
userId: createTextField({}),
|
|
43
|
+
key: createTextField({ required: true, personal: false, reason: "test_fixture" }),
|
|
44
|
+
userId: createTextField({ personal: false, reason: "test_fixture" }),
|
|
45
45
|
},
|
|
46
46
|
indexes: [{ unique: true, columns: ["key", "tenantId", "userId"] }],
|
|
47
47
|
});
|
|
@@ -62,8 +62,8 @@ describe("buildEntityTable — entity.indexes", () => {
|
|
|
62
62
|
test("composite non-unique-index landet als unique=false in Drizzle table-config", () => {
|
|
63
63
|
const entity = createEntity({
|
|
64
64
|
fields: {
|
|
65
|
-
startedAt: createTextField({}),
|
|
66
|
-
endedAt: createTextField({}),
|
|
65
|
+
startedAt: createTextField({ personal: false, reason: "test_fixture" }),
|
|
66
|
+
endedAt: createTextField({ personal: false, reason: "test_fixture" }),
|
|
67
67
|
},
|
|
68
68
|
indexes: [{ columns: ["startedAt", "endedAt"] }],
|
|
69
69
|
});
|
|
@@ -78,7 +78,9 @@ describe("buildEntityTable — entity.indexes", () => {
|
|
|
78
78
|
|
|
79
79
|
test("custom name override wird respektiert", () => {
|
|
80
80
|
const entity = createEntity({
|
|
81
|
-
fields: {
|
|
81
|
+
fields: {
|
|
82
|
+
slug: createTextField({ required: true, personal: false, reason: "test_fixture" }),
|
|
83
|
+
},
|
|
82
84
|
indexes: [{ unique: true, columns: ["slug"], name: "my_custom_idx" }],
|
|
83
85
|
});
|
|
84
86
|
const tbl = buildEntityTable("page", entity);
|
|
@@ -91,7 +93,7 @@ describe("buildEntityTable — entity.indexes", () => {
|
|
|
91
93
|
test("ohne indexes — keine zusätzlichen Indices, kein Error", () => {
|
|
92
94
|
const entity = createEntity({
|
|
93
95
|
fields: {
|
|
94
|
-
title: createTextField({}),
|
|
96
|
+
title: createTextField({ personal: false, reason: "test_fixture" }),
|
|
95
97
|
},
|
|
96
98
|
});
|
|
97
99
|
expect(() => buildEntityTable("widget", entity)).not.toThrow();
|
|
@@ -120,7 +122,7 @@ describe("validateBoot — entity.indexes", () => {
|
|
|
120
122
|
test("Tippfehler im column-Namen wirft", () => {
|
|
121
123
|
const feature = defineFeature("widgetFeature", (r) => {
|
|
122
124
|
r.entity("widget", {
|
|
123
|
-
fields: { title: createTextField({}) },
|
|
125
|
+
fields: { title: createTextField({ personal: false, reason: "test_fixture" }) },
|
|
124
126
|
indexes: [{ columns: ["titel"] }], // typo
|
|
125
127
|
});
|
|
126
128
|
});
|
|
@@ -130,7 +132,7 @@ describe("validateBoot — entity.indexes", () => {
|
|
|
130
132
|
test("leere column-Liste wirft", () => {
|
|
131
133
|
const feature = defineFeature("widgetFeature", (r) => {
|
|
132
134
|
r.entity("widget", {
|
|
133
|
-
fields: { title: createTextField({}) },
|
|
135
|
+
fields: { title: createTextField({ personal: false, reason: "test_fixture" }) },
|
|
134
136
|
indexes: [{ columns: [] as never }],
|
|
135
137
|
});
|
|
136
138
|
});
|
|
@@ -140,7 +142,7 @@ describe("validateBoot — entity.indexes", () => {
|
|
|
140
142
|
test("single-column index nur auf tenantId ist redundant", () => {
|
|
141
143
|
const feature = defineFeature("widgetFeature", (r) => {
|
|
142
144
|
r.entity("widget", {
|
|
143
|
-
fields: { title: createTextField({}) },
|
|
145
|
+
fields: { title: createTextField({ personal: false, reason: "test_fixture" }) },
|
|
144
146
|
indexes: [{ columns: ["tenantId"] }],
|
|
145
147
|
});
|
|
146
148
|
});
|
|
@@ -155,7 +157,7 @@ describe("validateBoot — entity.indexes", () => {
|
|
|
155
157
|
// sonst fliegt der Branch beim nächsten Revert/Refactor stumm raus.
|
|
156
158
|
const feature = defineFeature("widgetFeature", (r) => {
|
|
157
159
|
r.entity("widget", {
|
|
158
|
-
fields: { title: createTextField({}) },
|
|
160
|
+
fields: { title: createTextField({ personal: false, reason: "test_fixture" }) },
|
|
159
161
|
indexes: [{ unique: true, columns: ["tenantId"] }],
|
|
160
162
|
});
|
|
161
163
|
});
|
|
@@ -166,7 +168,7 @@ describe("validateBoot — entity.indexes", () => {
|
|
|
166
168
|
const feature = defineFeature("widgetFeature", (r) => {
|
|
167
169
|
r.entity("widget", {
|
|
168
170
|
fields: {
|
|
169
|
-
key: createTextField({ required: true }),
|
|
171
|
+
key: createTextField({ required: true, personal: false, reason: "test_fixture" }),
|
|
170
172
|
archived: createBooleanField({}),
|
|
171
173
|
},
|
|
172
174
|
indexes: [{ unique: true, columns: ["key", "tenantId"] }],
|
|
@@ -178,7 +180,7 @@ describe("validateBoot — entity.indexes", () => {
|
|
|
178
180
|
test("base columns (id, tenantId, version) sind erlaubt", () => {
|
|
179
181
|
const feature = defineFeature("widgetFeature", (r) => {
|
|
180
182
|
r.entity("widget", {
|
|
181
|
-
fields: { key: createTextField({}) },
|
|
183
|
+
fields: { key: createTextField({ personal: false, reason: "test_fixture" }) },
|
|
182
184
|
indexes: [{ columns: ["tenantId", "version"] }],
|
|
183
185
|
});
|
|
184
186
|
});
|
|
@@ -44,8 +44,8 @@ describe("buildEntityTable — required: true → NOT NULL", () => {
|
|
|
44
44
|
test("text field — required true makes column NOT NULL", () => {
|
|
45
45
|
const entity = createEntity({
|
|
46
46
|
fields: {
|
|
47
|
-
title: createTextField({ required: true }),
|
|
48
|
-
subtitle: createTextField({}),
|
|
47
|
+
title: createTextField({ required: true, personal: false, reason: "test_fixture" }),
|
|
48
|
+
subtitle: createTextField({ personal: false, reason: "test_fixture" }),
|
|
49
49
|
},
|
|
50
50
|
});
|
|
51
51
|
const tbl = buildEntityTable("widget", entity);
|
|
@@ -25,7 +25,7 @@ import { buildEntityTable } from "../table-builder";
|
|
|
25
25
|
|
|
26
26
|
const noteEntity = createEntity({
|
|
27
27
|
fields: {
|
|
28
|
-
title: createTextField({ required: true }),
|
|
28
|
+
title: createTextField({ required: true, personal: false, reason: "test_fixture" }),
|
|
29
29
|
},
|
|
30
30
|
table: "where_merge_notes",
|
|
31
31
|
});
|
|
@@ -14,7 +14,7 @@ import { createTenantDb } from "../tenant-db";
|
|
|
14
14
|
|
|
15
15
|
const entity = createEntity({
|
|
16
16
|
table: "merge_items",
|
|
17
|
-
fields: { name: createTextField({ required: true }) },
|
|
17
|
+
fields: { name: createTextField({ required: true, personal: false, reason: "test_fixture" }) },
|
|
18
18
|
});
|
|
19
19
|
// Brand (#742) is compile-time-only; hold the handle at the unbranded TableColumns
|
|
20
20
|
// view so the method-form scoping test still compiles (runtime shape is identical).
|
|
@@ -130,7 +130,10 @@ describe("tenant-db WHERE merge — narrowing within the enforced scope", () =>
|
|
|
130
130
|
describe("tenant-db WHERE merge — unmanaged EntityTableMeta tables (deriveEntityTableMeta)", () => {
|
|
131
131
|
const unmanagedEntity = createEntity({
|
|
132
132
|
table: "merge_meta_items",
|
|
133
|
-
fields: {
|
|
133
|
+
fields: {
|
|
134
|
+
tenantId: createTextField({ required: true, personal: false, reason: "test_fixture" }),
|
|
135
|
+
name: createTextField({ personal: false, reason: "test_fixture" }),
|
|
136
|
+
},
|
|
134
137
|
});
|
|
135
138
|
const unmanagedTable = deriveEntityTableMeta("merge-meta-item", unmanagedEntity);
|
|
136
139
|
|
|
@@ -19,8 +19,8 @@ import { createTenantDb } from "../tenant-db";
|
|
|
19
19
|
const entity = createEntity({
|
|
20
20
|
table: "tenant_db_items",
|
|
21
21
|
fields: {
|
|
22
|
-
name: createTextField({ required: true }),
|
|
23
|
-
status: createTextField({ default: "draft" }),
|
|
22
|
+
name: createTextField({ required: true, personal: false, reason: "test_fixture" }),
|
|
23
|
+
status: createTextField({ default: "draft", personal: false, reason: "test_fixture" }),
|
|
24
24
|
isActive: createBooleanField({ default: true }),
|
|
25
25
|
},
|
|
26
26
|
softDelete: true,
|
|
@@ -27,8 +27,8 @@ import { createTenantDb, type TenantDb } from "../tenant-db";
|
|
|
27
27
|
const userEntity = createEntity({
|
|
28
28
|
table: "read_unique_users",
|
|
29
29
|
fields: {
|
|
30
|
-
email: createTextField({ required: true }),
|
|
31
|
-
displayName: createTextField({ required: true }),
|
|
30
|
+
email: createTextField({ required: true, personal: false, reason: "test_fixture" }),
|
|
31
|
+
displayName: createTextField({ required: true, personal: false, reason: "test_fixture" }),
|
|
32
32
|
},
|
|
33
33
|
// softDelete=true damit wir den restore-Pfad pinnen können (siehe
|
|
34
34
|
// restore-Test unten — "kein 23505 möglich" claim).
|
|
@@ -7,7 +7,12 @@ import { createEntity, createTextField } from "../factories";
|
|
|
7
7
|
describe("validateBoot — action wiring (no function values)", () => {
|
|
8
8
|
test("rowAction writeHandler payload as function → Throw", () => {
|
|
9
9
|
const feature = defineFeature("shop", (r) => {
|
|
10
|
-
r.entity(
|
|
10
|
+
r.entity(
|
|
11
|
+
"product",
|
|
12
|
+
createEntity({
|
|
13
|
+
fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
|
|
14
|
+
}),
|
|
15
|
+
);
|
|
11
16
|
r.screen({
|
|
12
17
|
id: "product-list",
|
|
13
18
|
type: "entityList",
|
|
@@ -33,7 +38,14 @@ describe("validateBoot — action wiring (no function values)", () => {
|
|
|
33
38
|
|
|
34
39
|
test("rowAction writeHandler payload as declarative pick → kein Throw", () => {
|
|
35
40
|
const feature = defineFeature("shop", (r) => {
|
|
36
|
-
r.entity(
|
|
41
|
+
r.entity(
|
|
42
|
+
"product",
|
|
43
|
+
createEntity({
|
|
44
|
+
fields: {
|
|
45
|
+
name: createTextField({ sortable: true, personal: false, reason: "test_fixture" }),
|
|
46
|
+
},
|
|
47
|
+
}),
|
|
48
|
+
);
|
|
37
49
|
r.screen({
|
|
38
50
|
id: "product-list",
|
|
39
51
|
type: "entityList",
|
|
@@ -65,7 +77,12 @@ describe("validateBoot — action wiring (no function values)", () => {
|
|
|
65
77
|
|
|
66
78
|
test("rowAction navigate visible as function → Throw", () => {
|
|
67
79
|
const feature = defineFeature("shop", (r) => {
|
|
68
|
-
r.entity(
|
|
80
|
+
r.entity(
|
|
81
|
+
"product",
|
|
82
|
+
createEntity({
|
|
83
|
+
fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
|
|
84
|
+
}),
|
|
85
|
+
);
|
|
69
86
|
r.screen({
|
|
70
87
|
id: "product-list",
|
|
71
88
|
type: "entityList",
|
|
@@ -88,7 +105,12 @@ describe("validateBoot — action wiring (no function values)", () => {
|
|
|
88
105
|
|
|
89
106
|
test("toolbarAction writeHandler payload as function → Throw", () => {
|
|
90
107
|
const feature = defineFeature("shop", (r) => {
|
|
91
|
-
r.entity(
|
|
108
|
+
r.entity(
|
|
109
|
+
"product",
|
|
110
|
+
createEntity({
|
|
111
|
+
fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
|
|
112
|
+
}),
|
|
113
|
+
);
|
|
92
114
|
r.screen({
|
|
93
115
|
id: "product-list",
|
|
94
116
|
type: "entityList",
|
|
@@ -136,7 +158,12 @@ describe("validateBoot — action wiring (no function values)", () => {
|
|
|
136
158
|
|
|
137
159
|
test("entityList column renderer as function → Throw", () => {
|
|
138
160
|
const feature = defineFeature("shop", (r) => {
|
|
139
|
-
r.entity(
|
|
161
|
+
r.entity(
|
|
162
|
+
"product",
|
|
163
|
+
createEntity({
|
|
164
|
+
fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
|
|
165
|
+
}),
|
|
166
|
+
);
|
|
140
167
|
r.screen({
|
|
141
168
|
id: "product-list",
|
|
142
169
|
type: "entityList",
|
|
@@ -152,7 +179,12 @@ describe("validateBoot — action wiring (no function values)", () => {
|
|
|
152
179
|
|
|
153
180
|
test("entityEdit field visible as function → Throw", () => {
|
|
154
181
|
const feature = defineFeature("shop", (r) => {
|
|
155
|
-
r.entity(
|
|
182
|
+
r.entity(
|
|
183
|
+
"product",
|
|
184
|
+
createEntity({
|
|
185
|
+
fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
|
|
186
|
+
}),
|
|
187
|
+
);
|
|
156
188
|
r.screen({
|
|
157
189
|
id: "product-edit",
|
|
158
190
|
type: "entityEdit",
|
|
@@ -173,7 +205,12 @@ describe("validateBoot — action wiring (no function values)", () => {
|
|
|
173
205
|
|
|
174
206
|
test("entityEdit field renderer as function → Throw", () => {
|
|
175
207
|
const feature = defineFeature("shop", (r) => {
|
|
176
|
-
r.entity(
|
|
208
|
+
r.entity(
|
|
209
|
+
"product",
|
|
210
|
+
createEntity({
|
|
211
|
+
fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
|
|
212
|
+
}),
|
|
213
|
+
);
|
|
177
214
|
r.screen({
|
|
178
215
|
id: "product-edit",
|
|
179
216
|
type: "entityEdit",
|
|
@@ -194,7 +231,12 @@ describe("validateBoot — action wiring (no function values)", () => {
|
|
|
194
231
|
|
|
195
232
|
test("entityEdit field with declarative visible/readOnly/required → kein Throw", () => {
|
|
196
233
|
const feature = defineFeature("shop", (r) => {
|
|
197
|
-
r.entity(
|
|
234
|
+
r.entity(
|
|
235
|
+
"product",
|
|
236
|
+
createEntity({
|
|
237
|
+
fields: { name: createTextField({ personal: false, reason: "test_fixture" }) },
|
|
238
|
+
}),
|
|
239
|
+
);
|
|
198
240
|
r.screen({
|
|
199
241
|
id: "product-edit",
|
|
200
242
|
type: "entityEdit",
|