@reventlessdev/reventless-spec 3.0.0-alpha.128 → 3.0.0-alpha.130
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/CHANGELOG.md +56 -0
- package/package.json +2 -2
- package/schema/platform-api.graphql +1 -0
- package/src/AnsiStyle.res +31 -7
- package/src/AnsiStyle.res.mjs +16 -2
- package/src/components/DcbTag.res +229 -32
- package/src/components/DcbTag.res.mjs +232 -41
- package/src/components/Plugin.res +106 -89
- package/src/components/Plugin.res.mjs +47 -82
- package/src/components/Reference.res +48 -0
- package/src/components/Reference.res.mjs +28 -0
- package/src/generator/Codegen.res +14 -1
- package/src/generator/Codegen.res.mjs +9 -5
- package/src/generator/GraftTrait.res +5 -4
- package/src/generator/GraftTrait.res.mjs +4 -4
- package/src/generator/PluginGenerator.res +4 -1
- package/src/generator/PluginGenerator.res.mjs +2 -1
- package/src/types/Message.res +14 -12
- package/src/types/Message.res.mjs +2 -1
- package/src/types/Transition.res +30 -3
- package/src/types/Transition.res.mjs +13 -4
|
@@ -73,13 +73,13 @@ type apiSchemaFragment = {encoded: string, protocol: string}
|
|
|
73
73
|
@schema
|
|
74
74
|
type apiTarget = Domain | Platform
|
|
75
75
|
|
|
76
|
-
//
|
|
77
|
-
//
|
|
76
|
+
// Every optional below carries sury's default `option` encoding: the key is omitted,
|
|
77
|
+
// never written as `null`. That is the shape the rest of the repo already uses
|
|
78
|
+
// (`Message.meta`, `storedEvent.tags`), so there is one optional form on the wire and
|
|
79
|
+
// nothing to annotate. The `T | null` these fields used to carry worked around a sury
|
|
80
|
+
// bug — undefined failing jsonableValidation inside a union variant payload — fixed in
|
|
81
|
+
// 11.0.0-alpha.11. `Offload` below is not an optional wrapper but an either-or codec.
|
|
78
82
|
let apiSchemaFragmentOffloadSchema = Offload.optionSchema(~store="pluginApiFragments", apiSchemaFragmentSchema)
|
|
79
|
-
let dcbEventLogOptionSchema = dcbEventLogDefinitionSchema->S.nullAsOption
|
|
80
|
-
let stringOptionSchema = S.string->S.nullAsOption
|
|
81
|
-
let stringArrayOptionSchema = S.array(S.string)->S.nullAsOption
|
|
82
|
-
let boolOptionSchema = S.bool->S.nullAsOption
|
|
83
83
|
|
|
84
84
|
// ── UI fragment manifest types ────────────────────────────────────────────────
|
|
85
85
|
|
|
@@ -89,14 +89,14 @@ type panelManifestEntry = {
|
|
|
89
89
|
title: string,
|
|
90
90
|
description: string,
|
|
91
91
|
positions: array<string>,
|
|
92
|
-
requiredAccess:
|
|
92
|
+
requiredAccess: option<string>,
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
@schema
|
|
96
96
|
type menuEntry = {
|
|
97
97
|
label: string,
|
|
98
|
-
icon:
|
|
99
|
-
group:
|
|
98
|
+
icon: option<string>,
|
|
99
|
+
group: option<string>,
|
|
100
100
|
sortOrder: int,
|
|
101
101
|
}
|
|
102
102
|
|
|
@@ -105,7 +105,7 @@ type pageManifestEntry = {
|
|
|
105
105
|
fragmentId: string,
|
|
106
106
|
title: string,
|
|
107
107
|
menuEntry: menuEntry,
|
|
108
|
-
requiredAccess:
|
|
108
|
+
requiredAccess: option<string>,
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
@schema
|
|
@@ -115,18 +115,44 @@ type uiFragmentManifest = {
|
|
|
115
115
|
pages: array<pageManifestEntry>,
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
let uiFragmentManifestOptionSchema =
|
|
118
|
+
let uiFragmentManifestOptionSchema = S.option(uiFragmentManifestSchema)
|
|
119
119
|
|
|
120
120
|
// ── Plugin structure types (component metadata for Auto UI and event graph) ──
|
|
121
121
|
|
|
122
122
|
@schema
|
|
123
123
|
type commandLevel = Collection | Instance
|
|
124
124
|
|
|
125
|
+
/** One command's lifecycle edge as the component's own scenarios describe it:
|
|
126
|
+
where a scenario shows the command taking effect, where those scenarios land,
|
|
127
|
+
and whether it brings a row into existence or acts on one.
|
|
128
|
+
|
|
129
|
+
Harvested from the GWT corpus by `check:lifecycle` and committed beside the
|
|
130
|
+
plugin as `src/LifecycleModel.res`, so structure assembly reads a value rather
|
|
131
|
+
than the test tree — which is not published with a plugin package.
|
|
132
|
+
|
|
133
|
+
No `@schema`: nothing serialises this. It is read once, while the structure is
|
|
134
|
+
assembled, and what leaves is the `commandDef` fields it resolved. */
|
|
135
|
+
type derivedEdge = {
|
|
136
|
+
/** The writable's `Spec.name`, which is what the structure knows it by. */
|
|
137
|
+
component: string,
|
|
138
|
+
command: string,
|
|
139
|
+
/** Absent where the corpus could not label a history — the honest answer when
|
|
140
|
+
the linked views declare no lifecycle field, and the reason the name-stem
|
|
141
|
+
guess is still there to fall back to. */
|
|
142
|
+
level?: commandLevel,
|
|
143
|
+
/** States a scenario shows the command taking effect from. Empty means the
|
|
144
|
+
corpus said nothing, NOT that the command belongs nowhere. */
|
|
145
|
+
allowedStates: array<string>,
|
|
146
|
+
/** States those scenarios land in. More than one is an edge a single
|
|
147
|
+
`targetState` cannot carry, so it is left to the declaration. */
|
|
148
|
+
targets: array<string>,
|
|
149
|
+
}
|
|
150
|
+
|
|
125
151
|
@schema
|
|
126
152
|
type fieldReference = {
|
|
127
153
|
fieldName: string,
|
|
128
154
|
entity: string,
|
|
129
|
-
plugin:
|
|
155
|
+
plugin: option<string>,
|
|
130
156
|
}
|
|
131
157
|
|
|
132
158
|
@schema
|
|
@@ -134,23 +160,40 @@ type commandDef = {
|
|
|
134
160
|
name: string,
|
|
135
161
|
schema: string,
|
|
136
162
|
level: commandLevel,
|
|
137
|
-
aggregateIdField:
|
|
163
|
+
aggregateIdField: option<string>,
|
|
138
164
|
mutationField: string,
|
|
139
165
|
references: array<fieldReference>,
|
|
140
|
-
/** The
|
|
141
|
-
|
|
142
|
-
allowedStates:
|
|
143
|
-
/** The
|
|
144
|
-
|
|
145
|
-
targetState:
|
|
166
|
+
/** The *from* set — lifecycle states this command is meaningful in. `None`
|
|
167
|
+
means always available; `Some([])` means never show. */
|
|
168
|
+
allowedStates: option<array<string>>,
|
|
169
|
+
/** The *to* state this command's handler writes. `None` with a from-set present
|
|
170
|
+
means the command does not move the row. */
|
|
171
|
+
targetState: option<string>,
|
|
172
|
+
/** Where the from-set came from, ranking an inherited edge against an authored
|
|
173
|
+
one the way `queryableDef.labelFieldSource` does for its field:
|
|
174
|
+
|
|
175
|
+
- `"derived"` — the component's own scenarios.
|
|
176
|
+
- `"declared"` — its `commandTransition` switch.
|
|
177
|
+
- `"unrestricted"` — the switch declares the command legal in *every*
|
|
178
|
+
state, so there is no from-set to publish and `allowedStates` is absent.
|
|
179
|
+
|
|
180
|
+
Absent means the command names no states to come from and nothing said that
|
|
181
|
+
was deliberate — a spec that wrote no switch, or one whose command creates
|
|
182
|
+
the row. So a consumer drawing a state machine can tell an edge left
|
|
183
|
+
unconstrained on purpose from one that simply has no from-set.
|
|
184
|
+
|
|
185
|
+
It speaks for the from-set only. The two halves of an edge are reported
|
|
186
|
+
separately because they fail separately: a corpus routinely shows a command
|
|
187
|
+
taking effect without ever showing where it lands. */
|
|
188
|
+
allowedStatesSource?: string,
|
|
146
189
|
/** Whether the variant is exposed in the generated API (non-`@noApi`). */
|
|
147
|
-
apiExposed:
|
|
190
|
+
apiExposed: option<bool>,
|
|
148
191
|
/** Access keys — any one of them — a caller needs to be *offered* this command.
|
|
149
192
|
A hint derived from the server's rule, never the refusal itself. */
|
|
150
|
-
requiredAccess:
|
|
193
|
+
requiredAccess: option<array<string>>,
|
|
151
194
|
/** The `@owner` command field the server stamps with the caller's identity; a
|
|
152
195
|
client omits it from a form, since whatever it collects is discarded. */
|
|
153
|
-
ownerField:
|
|
196
|
+
ownerField: option<string>,
|
|
154
197
|
}
|
|
155
198
|
|
|
156
199
|
@schema
|
|
@@ -168,41 +211,41 @@ type queryableDef = {
|
|
|
168
211
|
searchableFields: array<string>,
|
|
169
212
|
/** Which rung produced `labelField`, so a consumer can rank it against its own
|
|
170
213
|
rule: `"annotation"` | `"convention"` | `"position"` | `"fallback"`. */
|
|
171
|
-
labelFieldSource:
|
|
214
|
+
labelFieldSource: option<string>,
|
|
172
215
|
/** The state field holding the row's lifecycle, paired with
|
|
173
216
|
`commandDef.allowedStates`. From `@lifecycle`, else an enum named `lifecycle`. */
|
|
174
|
-
lifecycleField:
|
|
217
|
+
lifecycleField: option<string>,
|
|
175
218
|
/** The `@owner` state field. Reads of this view are narrowed server-side to a
|
|
176
219
|
non-elevated caller's own rows. */
|
|
177
|
-
ownerField:
|
|
220
|
+
ownerField: option<string>,
|
|
178
221
|
/** The `@retired` state field withdrawing a row from ordinary reads. From the
|
|
179
222
|
annotation only — no fallback by name, since guessing hides data. */
|
|
180
|
-
retiredField:
|
|
223
|
+
retiredField: option<string>,
|
|
181
224
|
/** The states a row is retired *in* (state form of `@retired`); `None` is the
|
|
182
225
|
boolean form, where the excluded value is always `true`. */
|
|
183
|
-
retiredValues:
|
|
226
|
+
retiredValues: option<array<string>>,
|
|
184
227
|
/** Whether the view publishes the by-ids reference door that names a retired row
|
|
185
228
|
to any caller holding a pointer (`@namedWhenRetired`). Never true without
|
|
186
229
|
`retiredField`. */
|
|
187
|
-
namedWhenRetired:
|
|
230
|
+
namedWhenRetired: option<bool>,
|
|
188
231
|
/** `@@reventless.visibility`. `Some("Internal")` hides the component from AutoUI;
|
|
189
232
|
it is still carried here for developer tooling. `None` means Public. */
|
|
190
|
-
visibility:
|
|
233
|
+
visibility: option<string>,
|
|
191
234
|
/** Intra-plugin grouping band, the first non-kind path segment under `src/`.
|
|
192
235
|
`None` renders flat. */
|
|
193
|
-
chapter:
|
|
236
|
+
chapter: option<string>,
|
|
194
237
|
/** The singular counterpart of `queryField` (`Plugin_Order`), also the prefix of
|
|
195
238
|
the generated input types. Not derivable without `Api_Naming.singularize`. */
|
|
196
|
-
singleQueryField:
|
|
239
|
+
singleQueryField: option<string>,
|
|
197
240
|
/** The state field identifying a row, as opposed to a reference to another entity.
|
|
198
241
|
`None` means unresolved — no key-derived filter or sort until `@id` is declared. */
|
|
199
|
-
idField:
|
|
242
|
+
idField: option<string>,
|
|
200
243
|
/** Which rung produced `idField`, as `labelFieldSource` does: `"annotation"` |
|
|
201
244
|
`"convention"` | `"sole"`. */
|
|
202
|
-
idFieldSource:
|
|
245
|
+
idFieldSource: option<string>,
|
|
203
246
|
/** Access keys — any one of them — a caller needs to be *offered* this view. A
|
|
204
247
|
denied read comes back empty rather than erroring, hence the hint. */
|
|
205
|
-
requiredAccess:
|
|
248
|
+
requiredAccess: option<array<string>>,
|
|
206
249
|
}
|
|
207
250
|
|
|
208
251
|
/** One emitted event of a write side. `name` is the variant name, `schema` its
|
|
@@ -230,7 +273,7 @@ type writableDef = {
|
|
|
230
273
|
producedEventTypes: array<string>,
|
|
231
274
|
consumedEventTypes: array<string>,
|
|
232
275
|
linkedViews: array<string>,
|
|
233
|
-
consistencyRead:
|
|
276
|
+
consistencyRead: option<string>,
|
|
234
277
|
/** Emitted-event field schemas; `[]` when there are none. */
|
|
235
278
|
events: array<eventDef>,
|
|
236
279
|
/** Declared-error field schemas. Required, but a persisted structure predating a
|
|
@@ -238,7 +281,7 @@ type writableDef = {
|
|
|
238
281
|
`[]` on read, and a new one must be added there too. */
|
|
239
282
|
errors: array<errorDef>,
|
|
240
283
|
/** Chapter grouping band — see `queryableDef.chapter`. */
|
|
241
|
-
chapter:
|
|
284
|
+
chapter: option<string>,
|
|
242
285
|
}
|
|
243
286
|
|
|
244
287
|
@schema
|
|
@@ -248,7 +291,7 @@ type automationSliceDef = {
|
|
|
248
291
|
producedCommandTypes: array<string>,
|
|
249
292
|
targetName: string,
|
|
250
293
|
/** Chapter grouping band — see `queryableDef.chapter`. */
|
|
251
|
-
chapter:
|
|
294
|
+
chapter: option<string>,
|
|
252
295
|
}
|
|
253
296
|
|
|
254
297
|
@schema
|
|
@@ -256,11 +299,11 @@ type outboundTranslationSliceDef = {
|
|
|
256
299
|
name: string,
|
|
257
300
|
consumedEventTypes: array<string>,
|
|
258
301
|
inboundCommandTypes: array<string>,
|
|
259
|
-
targetName:
|
|
302
|
+
targetName: option<string>,
|
|
260
303
|
// Foreign system this slice publishes to — drives the external box (Event Graph).
|
|
261
|
-
externalSystem:
|
|
304
|
+
externalSystem: option<string>,
|
|
262
305
|
/** Chapter grouping band — see `queryableDef.chapter`. */
|
|
263
|
-
chapter:
|
|
306
|
+
chapter: option<string>,
|
|
264
307
|
/** The topics this slice subscribes to, as `Spec.sourceNames` declares them —
|
|
265
308
|
an Aggregate's `Spec.name` or a DCB source name. `Some([])` is the declared
|
|
266
309
|
default and means this plugin's own DCB log; `None` is an older structure
|
|
@@ -268,7 +311,7 @@ type outboundTranslationSliceDef = {
|
|
|
268
311
|
which names event types and not where they came from — two topics carrying
|
|
269
312
|
an event of the same name are indistinguishable there. Optional so an older
|
|
270
313
|
reader ignores it. */
|
|
271
|
-
consumedSources:
|
|
314
|
+
consumedSources: option<array<string>>,
|
|
272
315
|
}
|
|
273
316
|
|
|
274
317
|
@schema
|
|
@@ -277,9 +320,9 @@ type inboundTranslationSliceDef = {
|
|
|
277
320
|
commandTypes: array<string>,
|
|
278
321
|
targetName: string,
|
|
279
322
|
// Foreign system this slice receives from — drives the external box (Event Graph).
|
|
280
|
-
externalSystem:
|
|
323
|
+
externalSystem: option<string>,
|
|
281
324
|
/** Chapter grouping band — see `queryableDef.chapter`. */
|
|
282
|
-
chapter:
|
|
325
|
+
chapter: option<string>,
|
|
283
326
|
}
|
|
284
327
|
|
|
285
328
|
/** A published event of an extension point and the internal events producing it.
|
|
@@ -291,8 +334,6 @@ type publishedEventDef = {
|
|
|
291
334
|
fromEventTypes: array<string>,
|
|
292
335
|
}
|
|
293
336
|
|
|
294
|
-
let publishedEventDefArrayOptionSchema = S.array(publishedEventDefSchema)->S.nullAsOption
|
|
295
|
-
|
|
296
337
|
/** The command direction's producer half: a command an extension point takes and
|
|
297
338
|
the delegate commands it routes to. `name` is EP-qualified, `toCommandTypes`
|
|
298
339
|
plugin-qualified. */
|
|
@@ -302,8 +343,6 @@ type acceptedCommandDef = {
|
|
|
302
343
|
toCommandTypes: array<string>,
|
|
303
344
|
}
|
|
304
345
|
|
|
305
|
-
let acceptedCommandDefArrayOptionSchema = S.array(acceptedCommandDefSchema)->S.nullAsOption
|
|
306
|
-
|
|
307
346
|
/** The subscriber's half: a published event and the commands it routes to. A
|
|
308
347
|
delegate command is plugin-qualified, one sent back to the EP is EP-qualified. */
|
|
309
348
|
@schema
|
|
@@ -312,8 +351,6 @@ type handledEventDef = {
|
|
|
312
351
|
toCommandTypes: array<string>,
|
|
313
352
|
}
|
|
314
353
|
|
|
315
|
-
let handledEventDefArrayOptionSchema = S.array(handledEventDefSchema)->S.nullAsOption
|
|
316
|
-
|
|
317
354
|
/** The command direction's subscriber half: a command sent back to the port and
|
|
318
355
|
the internal events producing it. `name` is EP-qualified, `fromEventTypes`
|
|
319
356
|
plugin-qualified. */
|
|
@@ -323,21 +360,19 @@ type issuedCommandDef = {
|
|
|
323
360
|
fromEventTypes: array<string>,
|
|
324
361
|
}
|
|
325
362
|
|
|
326
|
-
let issuedCommandDefArrayOptionSchema = S.array(issuedCommandDefSchema)->S.nullAsOption
|
|
327
|
-
|
|
328
363
|
@schema
|
|
329
364
|
type extensionDef = {
|
|
330
365
|
name: string,
|
|
331
366
|
delegateNames: array<string>,
|
|
332
367
|
eventTypes: array<string>,
|
|
333
368
|
commandTypes: array<string>,
|
|
334
|
-
/** Which published event routes to which commands.
|
|
369
|
+
/** Which published event routes to which commands. Optional like
|
|
335
370
|
`extensionPointDef.commandTypes`; re-emit definitions persisted before it. */
|
|
336
|
-
handledEvents:
|
|
371
|
+
handledEvents: option<array<handledEventDef>>,
|
|
337
372
|
/** Which internal event sends which command back to the port. `None` means a
|
|
338
373
|
definition persisted before the field, NOT an extension that issues nothing —
|
|
339
374
|
a reader joining the two halves must keep them apart. */
|
|
340
|
-
issuedCommands:
|
|
375
|
+
issuedCommands: option<array<issuedCommandDef>>,
|
|
341
376
|
}
|
|
342
377
|
|
|
343
378
|
/**
|
|
@@ -346,28 +381,21 @@ An extension point owned by a plugin, from the producer side.
|
|
|
346
381
|
`sourceEventTypes` are the `Delegate`'s events feeding the published protocol,
|
|
347
382
|
plugin-qualified to match `writableDef.producedEventTypes`. `commandTypes` is the
|
|
348
383
|
EP's inbound protocol — None (read as []) for a `command = unit` EP, which routes
|
|
349
|
-
nothing.
|
|
350
|
-
lifecycle Message union); definitions persisted before a field must be re-emitted.
|
|
384
|
+
nothing. Definitions persisted before a field was added must be re-emitted.
|
|
351
385
|
*/
|
|
352
386
|
@schema
|
|
353
387
|
type extensionPointDef = {
|
|
354
388
|
name: string,
|
|
355
389
|
delegateNames: array<string>,
|
|
356
390
|
sourceEventTypes: array<string>,
|
|
357
|
-
commandTypes:
|
|
391
|
+
commandTypes: option<array<string>>,
|
|
358
392
|
/** Which internal event becomes which published event. */
|
|
359
|
-
publishedEvents:
|
|
360
|
-
option<array<publishedEventDef>>,
|
|
393
|
+
publishedEvents: option<array<publishedEventDef>>,
|
|
361
394
|
/** Which arriving command becomes which delegate command. `None` means a
|
|
362
395
|
definition persisted before the field, NOT a port that accepts nothing. */
|
|
363
|
-
acceptedCommands:
|
|
364
|
-
option<array<acceptedCommandDef>>,
|
|
396
|
+
acceptedCommands: option<array<acceptedCommandDef>>,
|
|
365
397
|
}
|
|
366
398
|
|
|
367
|
-
// js_nullable creates `array | null` (not `| undefined`), which passes sury's
|
|
368
|
-
// jsonableValidation inside the pluginStructure union variant payload.
|
|
369
|
-
let extensionPointDefArrayOptionSchema = S.array(extensionPointDefSchema)->S.nullAsOption
|
|
370
|
-
|
|
371
399
|
/**
|
|
372
400
|
One field's store requirement, with its provenance.
|
|
373
401
|
|
|
@@ -382,12 +410,9 @@ type requiredStoreDeclaration = {
|
|
|
382
410
|
store: string,
|
|
383
411
|
component: string,
|
|
384
412
|
field: string,
|
|
385
|
-
annotation:
|
|
413
|
+
annotation: option<string>,
|
|
386
414
|
}
|
|
387
415
|
|
|
388
|
-
let requiredStoreDeclarationArrayOptionSchema =
|
|
389
|
-
S.array(requiredStoreDeclarationSchema)->S.nullAsOption
|
|
390
|
-
|
|
391
416
|
/**
|
|
392
417
|
One component's capability requirement, with its provenance.
|
|
393
418
|
|
|
@@ -400,9 +425,6 @@ expressible as an annotation on one, which is why the need is declared.
|
|
|
400
425
|
@schema
|
|
401
426
|
type requiredCapabilityDeclaration = {capability: string, component: string}
|
|
402
427
|
|
|
403
|
-
let requiredCapabilityDeclarationArrayOptionSchema =
|
|
404
|
-
S.array(requiredCapabilityDeclarationSchema)->S.nullAsOption
|
|
405
|
-
|
|
406
428
|
/**
|
|
407
429
|
One graft's provenance: which trait, at which version, on which component.
|
|
408
430
|
|
|
@@ -427,14 +449,13 @@ type traitDeclaration = {
|
|
|
427
449
|
component: string,
|
|
428
450
|
}
|
|
429
451
|
|
|
430
|
-
let traitDeclarationArrayOptionSchema = S.array(traitDeclarationSchema)->S.nullAsOption
|
|
431
|
-
|
|
432
452
|
/**
|
|
433
453
|
Adding a field here? It must be a shape a stale event can be healed into — the
|
|
434
454
|
lifecycle aggregate replays its own log before every decision, so one event that
|
|
435
|
-
fails to decode freezes that plugin's registration. `
|
|
436
|
-
|
|
437
|
-
and
|
|
455
|
+
fails to decode freezes that plugin's registration. Make it `option`, which
|
|
456
|
+
`Message.parseJsonTolerant` heals to `None` whatever the inner type is. A required
|
|
457
|
+
array heals to `[]` and a required enum to its first variant; a required *scalar*
|
|
458
|
+
is fabricated and warned about, so it is the one shape to avoid. Regression suite:
|
|
438
459
|
`PluginLifecycleCorpusTest` — if it goes red, re-shape the field, not the fixtures.
|
|
439
460
|
*/
|
|
440
461
|
@schema
|
|
@@ -449,27 +470,23 @@ type pluginStructure = {
|
|
|
449
470
|
extensions: array<extensionDef>,
|
|
450
471
|
// Extension points owned by this plugin (producer side). Optional so older
|
|
451
472
|
// definitions still decode (absent → None, read as []).
|
|
452
|
-
extensionPoints:
|
|
453
|
-
option<array<extensionPointDef>>,
|
|
473
|
+
extensionPoints: option<array<extensionPointDef>>,
|
|
454
474
|
/** The object stores this plugin's fields declare they need, deduplicated and
|
|
455
475
|
qualified as `{plugin}.{store}` even for the same-plugin case. */
|
|
456
|
-
requiredStores:
|
|
476
|
+
requiredStores: option<array<string>>,
|
|
457
477
|
/** Provenance for `requiredStores`: one entry per declaring `(component, field)`.
|
|
458
478
|
`requiredStores` is derived from it, so the two cannot disagree. */
|
|
459
|
-
requiredStoreDeclarations:
|
|
460
|
-
option<array<requiredStoreDeclaration>>,
|
|
479
|
+
requiredStoreDeclarations: option<array<requiredStoreDeclaration>>,
|
|
461
480
|
/** The platform capabilities this plugin's components declare they need, one
|
|
462
481
|
entry per declaring component. Object stores are not here — a store need is
|
|
463
482
|
a field's, and travels as `requiredStores`. Absent → None, read as []. */
|
|
464
|
-
requiredCapabilities:
|
|
465
|
-
option<array<requiredCapabilityDeclaration>>,
|
|
483
|
+
requiredCapabilities: option<array<requiredCapabilityDeclaration>>,
|
|
466
484
|
/** The domain traits grafted into this plugin, one entry per declaring
|
|
467
485
|
component. Absent → None, read as []. The only signal a graft leaves that
|
|
468
486
|
survives into a deployed plugin — every other one (the dependency, the
|
|
469
487
|
variant spread, the rules alias, the conformance binding) is source-side.
|
|
470
488
|
A claim about origin, never about behaviour: see `Trait`. */
|
|
471
|
-
traitDeclarations:
|
|
472
|
-
option<array<traitDeclaration>>,
|
|
489
|
+
traitDeclarations: option<array<traitDeclaration>>,
|
|
473
490
|
}
|
|
474
491
|
|
|
475
492
|
let pluginStructureOffloadSchema = Offload.optionSchema(~store="pluginStructures", pluginStructureSchema)
|
|
@@ -496,15 +513,15 @@ type pluginDefinition = {
|
|
|
496
513
|
apiSchemaFragment: @s.matches(apiSchemaFragmentOffloadSchema) option<Offload.payload<apiSchemaFragment>>,
|
|
497
514
|
// Schema routing in split-API mode: None/"Domain" → DomainApi, Some("Platform") →
|
|
498
515
|
// PlatformApi (and excluded from the DomainApi runtime schema).
|
|
499
|
-
apiTarget:
|
|
516
|
+
apiTarget: option<string>,
|
|
500
517
|
// Component graph metadata, offloadable like apiSchemaFragment. Absent for older
|
|
501
518
|
// protocol versions.
|
|
502
519
|
structure: @s.matches(pluginStructureOffloadSchema) option<Offload.payload<pluginStructure>>,
|
|
503
520
|
// EventTopic ARN of a bundled DcbEventLog, so the admin can subscribe peer
|
|
504
521
|
// EventCollectors to it. None for plugins without one.
|
|
505
|
-
dcbEventLog:
|
|
522
|
+
dcbEventLog: option<dcbEventLogDefinition>,
|
|
506
523
|
// Mandatory; `Domain` is resolved as the default in Plugin_Builder. Payload-less
|
|
507
|
-
// variant → a bare JSON string
|
|
524
|
+
// variant → a bare JSON string.
|
|
508
525
|
kind: pluginKind,
|
|
509
526
|
}
|
|
510
527
|
|