@cosmicdrift/kumiko-framework 0.146.3 → 0.147.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 +6 -2
- package/src/api/auth-routes.ts +32 -67
- package/src/api/routes.ts +1 -3
- package/src/bun-db/__tests__/PATTERN.md +0 -1
- package/src/db/__tests__/assert-no-unreachable-live-rows.integration.test.ts +29 -3
- package/src/db/__tests__/schema-inspection.test.ts +7 -0
- package/src/db/event-store-executor-context.ts +398 -0
- package/src/db/event-store-executor-read.ts +276 -0
- package/src/db/event-store-executor-write.ts +615 -0
- package/src/db/event-store-executor.ts +29 -1166
- package/src/db/queries/shadow-swap.ts +3 -1
- package/src/db/schema-inspection.ts +1 -1
- package/src/engine/__tests__/boot-validator-dashboard.test.ts +10 -0
- package/src/engine/__tests__/engine.test.ts +45 -1
- package/src/engine/__tests__/event-migration-declarative.test.ts +6 -0
- package/src/engine/__tests__/membership-roles.test.ts +4 -10
- package/src/engine/__tests__/screen.test.ts +26 -0
- package/src/engine/boot-validator/entity-list-screens.ts +1 -1
- package/src/engine/boot-validator/gdpr-storage.ts +1 -1
- package/src/engine/boot-validator/index.ts +12 -8
- package/src/engine/boot-validator/nav.ts +120 -0
- package/src/engine/boot-validator/{screens-nav.ts → screens.ts} +12 -190
- package/src/engine/boot-validator/workspaces.ts +68 -0
- package/src/engine/define-feature.ts +77 -1011
- package/src/engine/feature-ast/__tests__/fixtures/cross-file-registrar/feature.ts +9 -0
- package/src/engine/feature-ast/__tests__/fixtures/cross-file-registrar/screens.ts +4 -0
- package/src/engine/feature-ast/__tests__/parse-real-features.test.ts +18 -8
- package/src/engine/feature-ast/__tests__/parse.test.ts +291 -2
- package/src/engine/feature-ast/__tests__/patcher.test.ts +1 -1
- package/src/engine/feature-ast/__tests__/render-roundtrip.test.ts +73 -0
- package/src/engine/feature-ast/extractors/round1.ts +3 -3
- package/src/engine/feature-ast/extractors/round4.ts +45 -10
- package/src/engine/feature-ast/extractors/shared.ts +64 -6
- package/src/engine/feature-ast/parse.ts +123 -10
- package/src/engine/feature-ast/patterns.ts +14 -7
- package/src/engine/feature-ast/render.ts +28 -7
- package/src/engine/feature-builder-state.ts +165 -0
- package/src/engine/feature-config-events-jobs.ts +303 -0
- package/src/engine/feature-entity-handlers.ts +161 -0
- package/src/engine/feature-ui-extensions.ts +413 -0
- package/src/engine/index.ts +0 -2
- package/src/engine/pattern-library/library.ts +44 -1131
- package/src/engine/pattern-library/mixed-schemas.ts +484 -0
- package/src/engine/pattern-library/opaque-schemas.ts +124 -0
- package/src/engine/pattern-library/shared-fields.ts +80 -0
- package/src/engine/pattern-library/static-schemas.ts +456 -0
- package/src/engine/registry-facade.ts +349 -0
- package/src/engine/registry-ingest.ts +473 -0
- package/src/engine/registry-state.ts +388 -0
- package/src/engine/registry-validate.ts +660 -0
- package/src/engine/registry.ts +79 -1695
- package/src/engine/types/screen.ts +4 -2
- package/src/engine/types/tree-node.ts +2 -5
- package/src/event-store/snapshot.ts +7 -7
- package/src/i18n/required-surface-keys.ts +2 -0
- package/src/jobs/job-runner.ts +1 -1
- package/src/observability/standard-metrics.ts +4 -3
- package/src/pipeline/dispatch-batch.ts +3 -3
- package/src/pipeline/dispatch-shared.ts +17 -10
- package/src/pipeline/event-dispatcher-admin.ts +289 -0
- package/src/pipeline/event-dispatcher-delivery.ts +264 -0
- package/src/pipeline/event-dispatcher.ts +28 -540
- package/src/pipeline/projection-rebuild.ts +1 -1
- package/src/stack/__tests__/setup-test-stack-jobs.integration.test.ts +95 -0
- package/src/stack/test-stack.ts +46 -1
- package/src/testing/boot-validator-fixture.ts +1 -2
- package/src/engine/__tests__/deep-link.test.ts +0 -35
- package/src/engine/deep-link.ts +0 -23
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
// Static pattern schemas (form-only, no closures).
|
|
2
|
+
|
|
3
|
+
import { CLAIM_KEY_TYPE_OPTIONS, ID_TYPE_OPTIONS } from "./shared-fields";
|
|
4
|
+
import type { PatternFormSchema } from "./types";
|
|
5
|
+
|
|
6
|
+
// --- Static patterns (form-only, no closures) -----------------------------
|
|
7
|
+
|
|
8
|
+
export const requiresSchema: PatternFormSchema = {
|
|
9
|
+
kind: "requires",
|
|
10
|
+
label: { en: "Requires", de: "Benötigt" },
|
|
11
|
+
summary: { en: "Hard dependency on other features." },
|
|
12
|
+
category: "meta",
|
|
13
|
+
editability: "static",
|
|
14
|
+
singleton: true,
|
|
15
|
+
fields: [
|
|
16
|
+
{
|
|
17
|
+
path: "featureNames",
|
|
18
|
+
label: { en: "Feature names", de: "Feature-Namen" },
|
|
19
|
+
input: "string-list",
|
|
20
|
+
itemPlaceholder: "auth",
|
|
21
|
+
required: true,
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const optionalRequiresSchema: PatternFormSchema = {
|
|
27
|
+
kind: "optionalRequires",
|
|
28
|
+
label: { en: "Optional requires", de: "Optional benötigt" },
|
|
29
|
+
summary: { en: "Soft dependency — used if available, otherwise skipped." },
|
|
30
|
+
category: "meta",
|
|
31
|
+
editability: "static",
|
|
32
|
+
singleton: true,
|
|
33
|
+
fields: [
|
|
34
|
+
{
|
|
35
|
+
path: "featureNames",
|
|
36
|
+
label: { en: "Feature names", de: "Feature-Namen" },
|
|
37
|
+
input: "string-list",
|
|
38
|
+
itemPlaceholder: "analytics",
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const readsConfigSchema: PatternFormSchema = {
|
|
44
|
+
kind: "readsConfig",
|
|
45
|
+
label: { en: "Reads config", de: "Liest Config" },
|
|
46
|
+
summary: { en: "Declares which qualified config keys this feature reads." },
|
|
47
|
+
category: "meta",
|
|
48
|
+
editability: "static",
|
|
49
|
+
singleton: true,
|
|
50
|
+
fields: [
|
|
51
|
+
{
|
|
52
|
+
path: "qualifiedKeys",
|
|
53
|
+
label: { en: "Qualified keys", de: "Qualifizierte Keys" },
|
|
54
|
+
input: "string-list",
|
|
55
|
+
itemPlaceholder: "billing:plan",
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const systemScopeSchema: PatternFormSchema = {
|
|
61
|
+
kind: "systemScope",
|
|
62
|
+
label: { en: "System scope", de: "System-Scope" },
|
|
63
|
+
summary: { en: "Marks this feature as system-tenant only." },
|
|
64
|
+
category: "meta",
|
|
65
|
+
editability: "static",
|
|
66
|
+
singleton: true,
|
|
67
|
+
fields: [],
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const toggleableSchema: PatternFormSchema = {
|
|
71
|
+
kind: "toggleable",
|
|
72
|
+
label: { en: "Toggleable", de: "Umschaltbar" },
|
|
73
|
+
summary: { en: "Operator can switch this feature on/off per tenant." },
|
|
74
|
+
category: "meta",
|
|
75
|
+
editability: "static",
|
|
76
|
+
singleton: true,
|
|
77
|
+
fields: [
|
|
78
|
+
{
|
|
79
|
+
path: "default",
|
|
80
|
+
label: { en: "Enabled by default", de: "Standardmäßig aktiviert" },
|
|
81
|
+
input: "boolean",
|
|
82
|
+
required: true,
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export const describeSchema: PatternFormSchema = {
|
|
88
|
+
kind: "describe",
|
|
89
|
+
label: { en: "Description", de: "Beschreibung" },
|
|
90
|
+
summary: { en: "One-to-three-sentence docs-lead: what the feature does + when you need it." },
|
|
91
|
+
category: "meta",
|
|
92
|
+
editability: "static",
|
|
93
|
+
singleton: true,
|
|
94
|
+
fields: [
|
|
95
|
+
{
|
|
96
|
+
path: "text",
|
|
97
|
+
label: { en: "Text", de: "Text" },
|
|
98
|
+
input: "textarea",
|
|
99
|
+
required: true,
|
|
100
|
+
placeholder: "Stores per-tenant widgets and exposes CRUD handlers for them.",
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export const uiHintsSchema: PatternFormSchema = {
|
|
106
|
+
kind: "uiHints",
|
|
107
|
+
label: { en: "UI hints", de: "UI-Hinweise" },
|
|
108
|
+
summary: { en: "Picker/scaffolder metadata. Opaque to the Designer; rendered as raw TS source." },
|
|
109
|
+
category: "meta",
|
|
110
|
+
editability: "opaque",
|
|
111
|
+
singleton: true,
|
|
112
|
+
fields: [],
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export const entitySchema: PatternFormSchema = {
|
|
116
|
+
kind: "entity",
|
|
117
|
+
label: { en: "Entity", de: "Entität" },
|
|
118
|
+
summary: { en: "An aggregate stored as event-sourced read-model." },
|
|
119
|
+
category: "data",
|
|
120
|
+
editability: "static",
|
|
121
|
+
fields: [
|
|
122
|
+
{
|
|
123
|
+
path: "entityName",
|
|
124
|
+
label: { en: "Name", de: "Name" },
|
|
125
|
+
input: "text",
|
|
126
|
+
required: true,
|
|
127
|
+
placeholder: "task",
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
path: "definition.fields",
|
|
131
|
+
label: { en: "Fields", de: "Felder" },
|
|
132
|
+
input: "entity-fields-editor",
|
|
133
|
+
required: true,
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
path: "definition.idType",
|
|
137
|
+
label: { en: "ID type", de: "ID-Typ" },
|
|
138
|
+
input: "select",
|
|
139
|
+
options: ID_TYPE_OPTIONS,
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
path: "definition.softDelete",
|
|
143
|
+
label: { en: "Soft delete", de: "Soft-Delete" },
|
|
144
|
+
hint: { en: "Mark rows isDeleted=true instead of removing them." },
|
|
145
|
+
input: "boolean",
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
path: "definition.table",
|
|
149
|
+
label: { en: "Table name (override)", de: "Tabellenname (Override)" },
|
|
150
|
+
hint: { en: "Defaults to read_<plural-snake-case-name>." },
|
|
151
|
+
input: "text",
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
export const relationSchema: PatternFormSchema = {
|
|
157
|
+
kind: "relation",
|
|
158
|
+
label: { en: "Relation", de: "Beziehung" },
|
|
159
|
+
summary: { en: "Foreign-key relationship between entities." },
|
|
160
|
+
category: "data",
|
|
161
|
+
editability: "static",
|
|
162
|
+
fields: [
|
|
163
|
+
{
|
|
164
|
+
path: "entityName",
|
|
165
|
+
label: { en: "Owner entity", de: "Besitzende Entität" },
|
|
166
|
+
input: "entity-ref",
|
|
167
|
+
required: true,
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
path: "relationName",
|
|
171
|
+
label: { en: "Relation name", de: "Beziehungs-Name" },
|
|
172
|
+
input: "text",
|
|
173
|
+
required: true,
|
|
174
|
+
placeholder: "owner",
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
path: "definition",
|
|
178
|
+
label: { en: "Type", de: "Typ" },
|
|
179
|
+
input: "discriminated-union",
|
|
180
|
+
discriminator: "type",
|
|
181
|
+
variants: [
|
|
182
|
+
{
|
|
183
|
+
tag: "belongsTo",
|
|
184
|
+
label: { en: "Belongs to", de: "Gehört zu" },
|
|
185
|
+
fields: [
|
|
186
|
+
{
|
|
187
|
+
path: "definition.target",
|
|
188
|
+
label: { en: "Target entity", de: "Ziel-Entität" },
|
|
189
|
+
input: "entity-ref",
|
|
190
|
+
required: true,
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
path: "definition.foreignKey",
|
|
194
|
+
label: { en: "Foreign key column", de: "FK-Spalte" },
|
|
195
|
+
input: "text",
|
|
196
|
+
required: true,
|
|
197
|
+
},
|
|
198
|
+
],
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
tag: "hasMany",
|
|
202
|
+
label: { en: "Has many", de: "Hat viele" },
|
|
203
|
+
fields: [
|
|
204
|
+
{
|
|
205
|
+
path: "definition.target",
|
|
206
|
+
label: { en: "Target entity", de: "Ziel-Entität" },
|
|
207
|
+
input: "entity-ref",
|
|
208
|
+
required: true,
|
|
209
|
+
},
|
|
210
|
+
],
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
tag: "manyToMany",
|
|
214
|
+
label: { en: "Many to many", de: "Viele zu viele" },
|
|
215
|
+
fields: [
|
|
216
|
+
{
|
|
217
|
+
path: "definition.target",
|
|
218
|
+
label: { en: "Target entity", de: "Ziel-Entität" },
|
|
219
|
+
input: "entity-ref",
|
|
220
|
+
required: true,
|
|
221
|
+
},
|
|
222
|
+
],
|
|
223
|
+
},
|
|
224
|
+
],
|
|
225
|
+
},
|
|
226
|
+
],
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
export const navSchema: PatternFormSchema = {
|
|
230
|
+
kind: "nav",
|
|
231
|
+
label: { en: "Navigation entry", de: "Navigations-Eintrag" },
|
|
232
|
+
summary: { en: "Side-bar / menu link." },
|
|
233
|
+
category: "ui",
|
|
234
|
+
editability: "static",
|
|
235
|
+
fields: [
|
|
236
|
+
{
|
|
237
|
+
path: "definition.id",
|
|
238
|
+
label: { en: "ID", de: "ID" },
|
|
239
|
+
input: "text",
|
|
240
|
+
required: true,
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
path: "definition.label",
|
|
244
|
+
label: { en: "Label", de: "Beschriftung" },
|
|
245
|
+
input: "text",
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
path: "definition.screen",
|
|
249
|
+
label: { en: "Screen QN", de: "Screen-QN" },
|
|
250
|
+
hint: { en: "<feature>:screen:<id> qualified name." },
|
|
251
|
+
input: "text",
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
path: "definition.parent",
|
|
255
|
+
label: { en: "Parent nav", de: "Eltern-Nav" },
|
|
256
|
+
input: "text",
|
|
257
|
+
},
|
|
258
|
+
],
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
export const workspaceSchema: PatternFormSchema = {
|
|
262
|
+
kind: "workspace",
|
|
263
|
+
label: { en: "Workspace", de: "Arbeitsbereich" },
|
|
264
|
+
summary: { en: "Persona-/role-scoped UI surface." },
|
|
265
|
+
category: "ui",
|
|
266
|
+
editability: "static",
|
|
267
|
+
fields: [
|
|
268
|
+
{
|
|
269
|
+
path: "definition.id",
|
|
270
|
+
label: { en: "ID", de: "ID" },
|
|
271
|
+
input: "text",
|
|
272
|
+
required: true,
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
path: "definition.label",
|
|
276
|
+
label: { en: "Label", de: "Beschriftung" },
|
|
277
|
+
input: "text",
|
|
278
|
+
},
|
|
279
|
+
],
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
export const configSchema: PatternFormSchema = {
|
|
283
|
+
kind: "config",
|
|
284
|
+
label: { en: "Config keys", de: "Config-Keys" },
|
|
285
|
+
summary: { en: "Typed runtime configuration." },
|
|
286
|
+
category: "meta",
|
|
287
|
+
editability: "static",
|
|
288
|
+
singleton: true,
|
|
289
|
+
fields: [
|
|
290
|
+
{
|
|
291
|
+
path: "keys",
|
|
292
|
+
label: { en: "Keys", de: "Keys" },
|
|
293
|
+
input: "key-value-map",
|
|
294
|
+
keyPlaceholder: "maxItems",
|
|
295
|
+
valueInput: "json-readonly",
|
|
296
|
+
required: true,
|
|
297
|
+
},
|
|
298
|
+
],
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
export const translationsSchema: PatternFormSchema = {
|
|
302
|
+
kind: "translations",
|
|
303
|
+
label: { en: "Translations", de: "Übersetzungen" },
|
|
304
|
+
summary: { en: "i18n strings keyed by locale." },
|
|
305
|
+
category: "meta",
|
|
306
|
+
editability: "static",
|
|
307
|
+
singleton: true,
|
|
308
|
+
fields: [
|
|
309
|
+
{
|
|
310
|
+
path: "keys",
|
|
311
|
+
label: { en: "Locales", de: "Sprachen" },
|
|
312
|
+
input: "key-value-map",
|
|
313
|
+
keyPlaceholder: "en",
|
|
314
|
+
valueInput: "json-readonly",
|
|
315
|
+
required: true,
|
|
316
|
+
},
|
|
317
|
+
],
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
export const metricSchema: PatternFormSchema = {
|
|
321
|
+
kind: "metric",
|
|
322
|
+
label: { en: "Metric", de: "Metrik" },
|
|
323
|
+
summary: { en: "Prometheus-style counter / gauge / histogram." },
|
|
324
|
+
category: "meta",
|
|
325
|
+
editability: "static",
|
|
326
|
+
fields: [
|
|
327
|
+
{
|
|
328
|
+
path: "shortName",
|
|
329
|
+
label: { en: "Short name", de: "Kurzname" },
|
|
330
|
+
hint: { en: "Snake-case; auto-prefixed with kumiko_<feature>_." },
|
|
331
|
+
input: "text",
|
|
332
|
+
required: true,
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
path: "options.type",
|
|
336
|
+
label: { en: "Type", de: "Typ" },
|
|
337
|
+
input: "select",
|
|
338
|
+
options: [
|
|
339
|
+
{ value: "counter", label: { en: "Counter" } },
|
|
340
|
+
{ value: "gauge", label: { en: "Gauge" } },
|
|
341
|
+
{ value: "histogram", label: { en: "Histogram" } },
|
|
342
|
+
],
|
|
343
|
+
required: true,
|
|
344
|
+
},
|
|
345
|
+
],
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
export const secretSchema: PatternFormSchema = {
|
|
349
|
+
kind: "secret",
|
|
350
|
+
label: { en: "Secret", de: "Secret" },
|
|
351
|
+
summary: { en: "Tenant-scoped encrypted credential." },
|
|
352
|
+
category: "meta",
|
|
353
|
+
editability: "static",
|
|
354
|
+
fields: [
|
|
355
|
+
{
|
|
356
|
+
path: "shortName",
|
|
357
|
+
label: { en: "Short name", de: "Kurzname" },
|
|
358
|
+
input: "text",
|
|
359
|
+
required: true,
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
path: "options.label",
|
|
363
|
+
label: { en: "UI label (i18n)", de: "UI-Label (i18n)" },
|
|
364
|
+
hint: { en: "{ en: 'API Key', de: 'API-Schlüssel' }" },
|
|
365
|
+
input: "json-readonly",
|
|
366
|
+
required: true,
|
|
367
|
+
},
|
|
368
|
+
{
|
|
369
|
+
path: "options.scope",
|
|
370
|
+
label: { en: "Scope", de: "Geltungsbereich" },
|
|
371
|
+
input: "select",
|
|
372
|
+
options: [
|
|
373
|
+
{ value: "tenant", label: { en: "Tenant" } },
|
|
374
|
+
{ value: "system", label: { en: "System" } },
|
|
375
|
+
],
|
|
376
|
+
},
|
|
377
|
+
],
|
|
378
|
+
};
|
|
379
|
+
|
|
380
|
+
export const claimKeySchema: PatternFormSchema = {
|
|
381
|
+
kind: "claimKey",
|
|
382
|
+
label: { en: "Claim key", de: "Claim-Key" },
|
|
383
|
+
summary: { en: "Typed JWT claim contributed at login." },
|
|
384
|
+
category: "meta",
|
|
385
|
+
editability: "static",
|
|
386
|
+
fields: [
|
|
387
|
+
{
|
|
388
|
+
path: "shortName",
|
|
389
|
+
label: { en: "Short name", de: "Kurzname" },
|
|
390
|
+
input: "text",
|
|
391
|
+
required: true,
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
path: "claimType",
|
|
395
|
+
label: { en: "Type", de: "Typ" },
|
|
396
|
+
input: "select",
|
|
397
|
+
options: CLAIM_KEY_TYPE_OPTIONS,
|
|
398
|
+
required: true,
|
|
399
|
+
},
|
|
400
|
+
],
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
export const referenceDataSchema: PatternFormSchema = {
|
|
404
|
+
kind: "referenceData",
|
|
405
|
+
label: { en: "Reference data", de: "Referenzdaten" },
|
|
406
|
+
summary: { en: "Seed data for an entity (currencies, categories, …)." },
|
|
407
|
+
category: "data",
|
|
408
|
+
editability: "static",
|
|
409
|
+
fields: [
|
|
410
|
+
{
|
|
411
|
+
path: "entityName",
|
|
412
|
+
label: { en: "Entity", de: "Entität" },
|
|
413
|
+
input: "entity-ref",
|
|
414
|
+
required: true,
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
path: "data",
|
|
418
|
+
label: { en: "Rows", de: "Zeilen" },
|
|
419
|
+
input: "json-readonly",
|
|
420
|
+
required: true,
|
|
421
|
+
},
|
|
422
|
+
{
|
|
423
|
+
path: "upsertKey",
|
|
424
|
+
label: { en: "Upsert key", de: "Upsert-Key" },
|
|
425
|
+
hint: { en: "Field name to deduplicate on." },
|
|
426
|
+
input: "text",
|
|
427
|
+
},
|
|
428
|
+
],
|
|
429
|
+
};
|
|
430
|
+
|
|
431
|
+
export const useExtensionSchema: PatternFormSchema = {
|
|
432
|
+
kind: "useExtension",
|
|
433
|
+
label: { en: "Use extension", de: "Erweiterung nutzen" },
|
|
434
|
+
summary: { en: "Apply a registered registrar-extension to an entity." },
|
|
435
|
+
category: "advanced",
|
|
436
|
+
editability: "static",
|
|
437
|
+
fields: [
|
|
438
|
+
{
|
|
439
|
+
path: "extensionName",
|
|
440
|
+
label: { en: "Extension name", de: "Erweiterungs-Name" },
|
|
441
|
+
input: "text",
|
|
442
|
+
required: true,
|
|
443
|
+
},
|
|
444
|
+
{
|
|
445
|
+
path: "entityName",
|
|
446
|
+
label: { en: "Entity", de: "Entität" },
|
|
447
|
+
input: "entity-ref",
|
|
448
|
+
required: true,
|
|
449
|
+
},
|
|
450
|
+
{
|
|
451
|
+
path: "options",
|
|
452
|
+
label: { en: "Options", de: "Optionen" },
|
|
453
|
+
input: "json-readonly",
|
|
454
|
+
},
|
|
455
|
+
],
|
|
456
|
+
};
|