@volter/project 0.5.211 → 0.5.213
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/NOTICE +2 -2
- package/README.md +8 -15
- package/package.json +5 -26
- package/schemas/volter-project.schema.json +33 -145
- package/schemas/volter-settings.schema.json +11 -49
- package/src/adapter/adapter-module.ts +208 -465
- package/src/adapter/adapter-surface.ts +4 -32
- package/src/adapter/authoring-seam-contract.ts +7 -24
- package/src/adapter/authoring.ts +126 -265
- package/src/adapter/editor-looks.ts +98 -127
- package/src/adapter/finders/registry.ts +6 -21
- package/src/adapter/host-context.ts +17 -72
- package/src/adapter/index.ts +4 -77
- package/src/adapter/manifest-interpreter.ts +7 -50
- package/src/adapter/physics-adapter-2d.ts +4 -21
- package/src/adapter/root-adapter.ts +37 -111
- package/src/adapter/root-seam-contract.ts +3 -6
- package/src/adapter/root-stacking.ts +4 -46
- package/src/adapter/seam-evidence.ts +0 -16
- package/src/adapter/system-adapter.ts +24 -656
- package/src/adapter/system-seam-contract.ts +1 -91
- package/src/adapter/transform.ts +4 -3
- package/src/adapter/workspace-arrangement.ts +33 -49
- package/src/manifest/editor-port.ts +10 -36
- package/src/manifest/filename.ts +3 -42
- package/src/manifest/load-file.ts +9 -15
- package/src/manifest/load.ts +44 -179
- package/src/manifest/locate.ts +8 -32
- package/src/manifest/schema.ts +155 -427
- package/src/semver.ts +16 -0
- package/src/settings/keys.ts +9 -11
- package/src/settings/schema.ts +55 -44
- package/schemas/engine-api.json +0 -57
- package/schemas/engine-api.md +0 -22
- package/src/adapter/binding.ts +0 -445
- package/src/adapter/debug-registry-ref.ts +0 -19
- package/src/adapter/frame-capture.ts +0 -80
- package/src/adapter/ingest/contract-system-slots.ts +0 -28
- package/src/adapter/ingest/game-contract-seams.ts +0 -86
- package/src/adapter/ingest/game-contract.ts +0 -506
- package/src/adapter/ingest/mount-readiness.ts +0 -140
- package/src/adapter/loop-gate-report.ts +0 -53
- package/src/adapter/native-entry-surface.ts +0 -100
- package/src/adapter/render-audio.ts +0 -20
- package/src/adapter/render-memory.ts +0 -34
- package/src/adapter/renderer-config.ts +0 -84
- package/src/adapter/system-slot.ts +0 -301
- package/src/core/system-phase.ts +0 -52
- package/src/inspection.ts +0 -281
- package/src/manifest/configuration-kinds.ts +0 -241
- package/src/manifest/kind-modules.ts +0 -58
- package/src/manifest/runtime-environment.ts +0 -48
package/src/adapter/authoring.ts
CHANGED
|
@@ -1,33 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Authoring providers expose document operations through opaque node ids. Each
|
|
3
|
+
* integration owns its model and adapter; the editor consumes these interfaces
|
|
4
|
+
* and declared capabilities without selecting an implementation by type.
|
|
4
5
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* The interface lives in the engine (not the editor) so `MountedThreeRoot.authoring`
|
|
12
|
-
* can reference it without the engine depending on the editor; implementers live
|
|
13
|
-
* in `packages/editor/src/authoring/`.
|
|
14
|
-
*
|
|
15
|
-
* **Reserved inspector paths convention:** the property paths `name`, `visible`,
|
|
16
|
-
* `locked`, `renderVisible` and `exclude` are reserved — an adapter that
|
|
17
|
-
* supports them exposes them through the ordinary `InspectorProvider.get`/`set`
|
|
18
|
-
* (no separate provider). The shell renders the hierarchy panel's rename field,
|
|
19
|
-
* eye (visibility) toggle, lock toggle, render-camera toggle and
|
|
20
|
-
* exclude checkbox against these paths, generically, for any adapter that
|
|
21
|
-
* reports them via `InspectorProvider.properties`.
|
|
22
|
-
*
|
|
23
|
-
* A COLUMN FOLLOWS WHAT THE ADAPTER ANSWERS, never a chrome knob (owner ruling,
|
|
24
|
-
* 2026-09-19). `renderVisible` and `exclude` are answered by almost nothing —
|
|
25
|
-
* three.js has ONE `Object3D.visible` governing viewport and render alike, and
|
|
26
|
-
* nothing but a view layer has an exclusion — so their columns are absent or a
|
|
27
|
-
* reserved blank cell, and appear the moment an adapter whose truth really does
|
|
28
|
-
* separate them says so. `exclude` and `renderVisible` are reported in the
|
|
29
|
-
* sense their name carries: `exclude: true` means EXCLUDED, `renderVisible:
|
|
30
|
-
* false` means hidden from renders.
|
|
6
|
+
* Reserved inspector paths `name`, `visible`, `locked`, `renderVisible` and
|
|
7
|
+
* `exclude` use ordinary InspectorProvider properties/get/set. Hierarchy columns
|
|
8
|
+
* follow the properties the adapter reports. `exclude: true` means excluded;
|
|
9
|
+
* `renderVisible: false` means hidden from renders. An adapter with one shared
|
|
10
|
+
* visibility flag need not invent separate render visibility or exclusion.
|
|
31
11
|
*/
|
|
32
12
|
|
|
33
13
|
import type { Transform } from './transform';
|
|
@@ -48,7 +28,7 @@ export interface AuthoringCapabilities {
|
|
|
48
28
|
|
|
49
29
|
/**
|
|
50
30
|
* The adapter's own answer to "what is truth behind these rows, and how
|
|
51
|
-
* writable is it"
|
|
31
|
+
* writable is it". Provenance never varies WITHIN one adapter's
|
|
52
32
|
* rows — it is a property of the world boundary — so it is declared ONCE per
|
|
53
33
|
* adapter and rendered at the SEAM (the composite's `world:<id>` group row,
|
|
54
34
|
* or the panel header for a bare adapter), never per row. Only the adapter
|
|
@@ -62,11 +42,11 @@ export interface AuthoringProvenance {
|
|
|
62
42
|
/**
|
|
63
43
|
* What the rows project:
|
|
64
44
|
* - `document` — an authored data file the editor owns (e.g. a scene file);
|
|
65
|
-
* - `source-code` — the
|
|
45
|
+
* - `source-code` — the project's own source is the document (e.g. JSX);
|
|
66
46
|
* - `foreign` — a live tree the editor does not own (an unmodified external
|
|
67
|
-
*
|
|
47
|
+
* project, or any world edited only through an overlay); edits go to the
|
|
68
48
|
* overlay, never the source;
|
|
69
|
-
* - `live` — a running
|
|
49
|
+
* - `live` — a running project adopted at play time; ordinary edits are not persisted;
|
|
70
50
|
* - `boundary` — a declared world with no live editing surface here.
|
|
71
51
|
*/
|
|
72
52
|
source: 'document' | 'source-code' | 'foreign' | 'live' | 'boundary';
|
|
@@ -82,7 +62,7 @@ export interface AuthoringProvenance {
|
|
|
82
62
|
* Semantic place a node occupies in the universal authoring hierarchy.
|
|
83
63
|
*
|
|
84
64
|
* `kind` below remains the adapter's native kind (`mesh`, `button`,
|
|
85
|
-
* `
|
|
65
|
+
* `sprite`,...). `role` says what the row MEANS to the editor shell,
|
|
86
66
|
* so presentation and interaction never have to infer semantics from an id,
|
|
87
67
|
* label, or substrate-specific kind string.
|
|
88
68
|
*/
|
|
@@ -99,11 +79,13 @@ export type EditorNodeRole =
|
|
|
99
79
|
|
|
100
80
|
/** A node in the authoring hierarchy — format-neutral. */
|
|
101
81
|
export interface EditorNode {
|
|
102
|
-
/**
|
|
82
|
+
/** Stable node id that survives reload. */
|
|
103
83
|
id: string;
|
|
104
84
|
label: string;
|
|
105
|
-
/**
|
|
106
|
-
*
|
|
85
|
+
/**
|
|
86
|
+
* Optional semantic role. Icon selection uses the native `kind` when no role
|
|
87
|
+
* is declared.
|
|
88
|
+
*/
|
|
107
89
|
role?: EditorNodeRole;
|
|
108
90
|
/** Optional source-owned context kept visually subordinate to `label`, such
|
|
109
91
|
* as `<header>` beneath a React component name or a document's file path. */
|
|
@@ -121,16 +103,14 @@ export interface EditorNode {
|
|
|
121
103
|
childIds: string[];
|
|
122
104
|
/**
|
|
123
105
|
* THIS ADAPTER'S OWN DEFAULT OPEN STATE for this row, overriding the shell's
|
|
124
|
-
* shape heuristic (`
|
|
106
|
+
* shape heuristic (`Hierarchy.tsx`'s `defaultExpansionByNode`, which
|
|
125
107
|
* infers openness from authored depth and branch shape).
|
|
126
108
|
*
|
|
127
109
|
* It exists because one adapter genuinely knows better than any shape rule
|
|
128
|
-
* can:
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
* closed" is a fact about the tree rather than a guess about it. Omitted —
|
|
133
|
-
* which is every other adapter — leaves the heuristic exactly as it was.
|
|
110
|
+
* can: a tree whose own model stores an explicit per-element open flag
|
|
111
|
+
* answers "collections open, objects closed" as a fact about the tree rather
|
|
112
|
+
* than a guess about it. Omitted — which is every adapter without such a
|
|
113
|
+
* flag — leaves the heuristic exactly as it was.
|
|
134
114
|
*/
|
|
135
115
|
defaultExpanded?: boolean;
|
|
136
116
|
/** Opaque project-owned identity shared by authored rows across adapter roots. */
|
|
@@ -160,15 +140,9 @@ export interface PropertyDescriptor {
|
|
|
160
140
|
readonlyReason?: string;
|
|
161
141
|
options?: unknown[];
|
|
162
142
|
/**
|
|
163
|
-
* Optional domain
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
* — omitted (or two descriptors with different/no `group`) renders exactly
|
|
167
|
-
* as before this field existed. This is the ONLY authoring-richness
|
|
168
|
-
* addition v1 makes; there is no schema and no new PropertyDescriptor
|
|
169
|
-
* `type` — a custom adapter reports its own domain concepts
|
|
170
|
-
* (health/score/an enum, …) through the SAME provider, merely labeled into
|
|
171
|
-
* a named group.
|
|
143
|
+
* Optional domain grouping. Properties with the same `group` label render in a
|
|
144
|
+
* named subsection of the generic inspector. Ungrouped properties retain the
|
|
145
|
+
* flat grid; grouping does not change descriptor types or write semantics.
|
|
172
146
|
*/
|
|
173
147
|
group?: string;
|
|
174
148
|
/**
|
|
@@ -216,18 +190,18 @@ export interface HierarchyProvider {
|
|
|
216
190
|
*/
|
|
217
191
|
crossSurfaceStructureSignature?(): string | null;
|
|
218
192
|
/**
|
|
219
|
-
* OPTIONAL,
|
|
220
|
-
* (null for a node this adapter has no object for), opaque here: its
|
|
221
|
-
* typing is
|
|
193
|
+
* OPTIONAL, STAGE-SURFACE — the live scene object for raycast/gizmo binding
|
|
194
|
+
* (null for a node this adapter has no object for), opaque here: its native
|
|
195
|
+
* typing is the 3D integration's. A canvas, DOM or React
|
|
222
196
|
* adapter has no scene object at all: it OMITS this method rather than
|
|
223
197
|
* implementing a `() => null` stub that pretends the concept applies. Callers
|
|
224
198
|
* already treat `null` as "no object here", so absence and `null` mean the
|
|
225
|
-
* same thing to them — optional-chain it (`hierarchy.
|
|
199
|
+
* same thing to them — optional-chain it (`hierarchy.nativeObject?.(id) ?? null`).
|
|
226
200
|
*/
|
|
227
|
-
|
|
228
|
-
/** OPTIONAL,
|
|
201
|
+
nativeObject?(id: string): unknown;
|
|
202
|
+
/** OPTIONAL, STAGE-SURFACE — inverse of {@link nativeObject}. Same rule: an
|
|
229
203
|
* adapter with no scene-object tree omits it. */
|
|
230
|
-
|
|
204
|
+
idForNativeObject?(o: unknown): string | null;
|
|
231
205
|
}
|
|
232
206
|
|
|
233
207
|
export interface SelectionProvider {
|
|
@@ -236,9 +210,11 @@ export interface SelectionProvider {
|
|
|
236
210
|
* already name a real node (for example a folded-internal light inventory);
|
|
237
211
|
* the default keeps the adapter's normal semantic component resolution. */
|
|
238
212
|
set(ids: string[], options?: { intent?: 'semantic' | 'exact' }): void;
|
|
239
|
-
/**
|
|
240
|
-
*
|
|
241
|
-
*
|
|
213
|
+
/**
|
|
214
|
+
* Resolve a native/render hit to its semantic authoring subject. The shell
|
|
215
|
+
* does not infer ownership from ancestry or substrate-specific kinds.
|
|
216
|
+
* Without this optional resolver, raw ids are the selection ids.
|
|
217
|
+
*/
|
|
242
218
|
resolve?(
|
|
243
219
|
rawId: string,
|
|
244
220
|
options?: { intent?: 'normal' | 'deep'; scopeId?: string | null },
|
|
@@ -274,16 +250,9 @@ export interface TransformEditability {
|
|
|
274
250
|
* protocol's removal door refuses by name instead of acking a revert it did
|
|
275
251
|
* not perform.
|
|
276
252
|
*
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
*
|
|
280
|
-
* attributes before saying yes). A lane whose client holds only an
|
|
281
|
-
* oid → file:line index and writes through a server that resolves the
|
|
282
|
-
* address — the vendored-ingest lane — can honestly answer only the SECOND,
|
|
283
|
-
* so that is what it answers, and `remove`'s own {@link WriteAck} reports
|
|
284
|
-
* whether an attribute was actually dropped (`persisted: false` when the
|
|
285
|
-
* callsite carried none). The inverse is what is forbidden on every lane:
|
|
286
|
-
* acking a drop that took no byte.
|
|
253
|
+
* A provider reads its own document before declaring an override. A client with only a
|
|
254
|
+
* source address leaves the decision to its writer; the removal's WriteAck reports whether
|
|
255
|
+
* bytes were removed, with persisted: false when the document carried no override.
|
|
287
256
|
*/
|
|
288
257
|
removable?: boolean;
|
|
289
258
|
}
|
|
@@ -362,7 +331,7 @@ export interface InspectorProvider {
|
|
|
362
331
|
/**
|
|
363
332
|
* Optional — SHOW a value without writing it, for a control the user drags.
|
|
364
333
|
*
|
|
365
|
-
* The gizmo already has this pair ({@link TransformProvider.
|
|
334
|
+
* The gizmo already has this pair ({@link TransformProvider.apply}
|
|
366
335
|
* live, {@link TransformProvider.endEdit} persisting), and a colour picker
|
|
367
336
|
* needs the same shape: it streams values continuously while the pointer
|
|
368
337
|
* moves, and persisting each one is a write burst the absorb cycle cannot
|
|
@@ -392,7 +361,7 @@ export interface InspectorProvider {
|
|
|
392
361
|
* edit/revert round trip and grades UNVERIFIABLE rather than passing.
|
|
393
362
|
*
|
|
394
363
|
* SAME ACK CONTRACT AS {@link set} — the pipe's per-edit {@link WriteAck}
|
|
395
|
-
*
|
|
364
|
+
* awaited. Removal is a write; it
|
|
396
365
|
* moves bytes, and the caller has the same right to be told where they went
|
|
397
366
|
* and whether they moved. Returning nothing means this provider performed no
|
|
398
367
|
* persisted write, and the shell reports the live-only floor.
|
|
@@ -406,36 +375,6 @@ export interface InspectorProvider {
|
|
|
406
375
|
remove?(id: string, path: string): void | WriteAck | Promise<void | WriteAck>;
|
|
407
376
|
}
|
|
408
377
|
|
|
409
|
-
/**
|
|
410
|
-
* An authored node that is itself an asset, even when its bytes are embedded
|
|
411
|
-
* in another source document instead of living at a standalone project path.
|
|
412
|
-
*
|
|
413
|
-
* The first concrete case is inline SVG in a DOM/React root: its `<path>` and
|
|
414
|
-
* `<g>` implementation is no more part of the authoring hierarchy than the
|
|
415
|
-
* meshes inside an imported model. The adapter owns the native-to-asset
|
|
416
|
-
* conversion; the shell only opens the returned image in its ordinary Asset
|
|
417
|
-
* Editor document.
|
|
418
|
-
*/
|
|
419
|
-
export interface AuthoringAssetSubject {
|
|
420
|
-
readonly kind: 'image';
|
|
421
|
-
readonly name: string;
|
|
422
|
-
readonly mediaType: 'image/svg+xml';
|
|
423
|
-
readonly text: string;
|
|
424
|
-
/** Project-root-relative source definition, when the adapter can prove it. */
|
|
425
|
-
readonly sourcePath?: string;
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
export interface AssetSubjectProvider {
|
|
429
|
-
get(id: string): AuthoringAssetSubject | null;
|
|
430
|
-
/**
|
|
431
|
-
* Assets known to this authoring document even when they are not in its
|
|
432
|
-
* currently focused hierarchy projection. React story boards use this to
|
|
433
|
-
* expose SVGs mounted in inactive story frames without flattening those
|
|
434
|
-
* frames into the active hierarchy.
|
|
435
|
-
*/
|
|
436
|
-
entries?(): ReadonlyArray<{ id: string; subject: AuthoringAssetSubject }>;
|
|
437
|
-
}
|
|
438
|
-
|
|
439
378
|
/** A semantic jump from one authored subject to another document/subject.
|
|
440
379
|
* The adapter owns resolution and opening; the inspector only presents the
|
|
441
380
|
* title and exposes the same verb to human and serialized projections. */
|
|
@@ -502,8 +441,7 @@ export interface ComponentInstancesProvider {
|
|
|
502
441
|
* `void` is the honest answer for a lane whose verb performs no write of its
|
|
503
442
|
* own (an in-memory adapter mutating a graph it already owns); a lane that
|
|
504
443
|
* writes returns the persistence pipe's own {@link WriteAck}
|
|
505
|
-
*
|
|
506
|
-
* verb has awaited the byte.
|
|
444
|
+
* awaited, so a caller that awaits the verb has awaited the byte.
|
|
507
445
|
*
|
|
508
446
|
* A structural verb resolves on ITS OWN verb: `remove` asks whether the struct
|
|
509
447
|
* writer is bound, never whether the PROP writer is — resolving on a
|
|
@@ -537,10 +475,7 @@ export type StructuralWriteOutcome = void | WriteAck | Promise<void | WriteAck>;
|
|
|
537
475
|
* `ack: undefined` (no write was attempted, which is exactly what `void` means
|
|
538
476
|
* in {@link StructuralWriteOutcome}).
|
|
539
477
|
*
|
|
540
|
-
*
|
|
541
|
-
* behind a `return ''` — is the shape this type exists to make unrepresentable:
|
|
542
|
-
* it left the caller unable to await the byte, which is how N same-file
|
|
543
|
-
* duplicates went out together, each reading the file before any wrote back.
|
|
478
|
+
* Callers await ack before starting another write to the same file.
|
|
544
479
|
*/
|
|
545
480
|
export interface StructuralIdWrite<Id extends string | null = string> {
|
|
546
481
|
/** The id the op produced — `''` when the lane cannot know it until its own
|
|
@@ -583,8 +518,7 @@ export interface StructureProvider {
|
|
|
583
518
|
* multi-delete's writes land strictly one at a time (see that function's own
|
|
584
519
|
* doc comment for why serialization + deletion order together are what make
|
|
585
520
|
* a per-id loop sound for an adapter whose OID index isn't reindexed between
|
|
586
|
-
* writes). An adapter with a synchronous
|
|
587
|
-
* `UIAuthoringAdapter`) returns `void` — `await`ing it is a harmless no-op.
|
|
521
|
+
* writes). An adapter with a synchronous in-memory remove can return void.
|
|
588
522
|
*
|
|
589
523
|
* A source-writing lane returns THIS removal's own {@link WriteAck} (see
|
|
590
524
|
* {@link StructuralWriteOutcome}).
|
|
@@ -613,12 +547,12 @@ export interface StructureProvider {
|
|
|
613
547
|
* an adapter-specific affordance outside the generic palette).
|
|
614
548
|
*/
|
|
615
549
|
creatableKinds?(parentId: string | null): CreatableKind[];
|
|
616
|
-
/**
|
|
550
|
+
/** wrap `id` in a new container element (default tag
|
|
617
551
|
* adapter-chosen, e.g. a `div`), re-parenting `id` as that container's sole
|
|
618
552
|
* child. Absent ⇒ the shell's context menu shows no Wrap item for this
|
|
619
553
|
* adapter. */
|
|
620
554
|
wrap?(id: string, wrapperTag?: string): StructuralWriteOutcome;
|
|
621
|
-
/**
|
|
555
|
+
/** replace `id` with its own children (the inverse of
|
|
622
556
|
* `wrap`). Absent ⇒ the shell's context menu shows no Unwrap item for this
|
|
623
557
|
* adapter. */
|
|
624
558
|
unwrap?(id: string): StructuralWriteOutcome;
|
|
@@ -636,25 +570,23 @@ export interface StructureProvider {
|
|
|
636
570
|
/** Preflight for an Ungroup affordance. Omit when ungroup is never offered. */
|
|
637
571
|
canUngroup?(id: string): boolean;
|
|
638
572
|
/**
|
|
639
|
-
*
|
|
573
|
+
* remove every id in `ids` as ONE undoable
|
|
640
574
|
* op (a single Ctrl+Z restores the whole batch), instead of the caller
|
|
641
575
|
* looping `remove(id)` per id (which — one `remove` call = one undo push
|
|
642
576
|
* per adapter, by design — produces N separate undo entries: Ctrl+Z then
|
|
643
577
|
* restores them one at a time, asymmetric with the first-party adapter's
|
|
644
578
|
* own single batched multi-delete undo). Absent ⇒ the shell falls back to
|
|
645
|
-
* the per-id `remove` loop
|
|
646
|
-
* honest degrade, not a silent behavior change, for any adapter that
|
|
579
|
+
* the per-id `remove` loop — an honest degrade for any adapter that
|
|
647
580
|
* hasn't implemented batching. May optionally return an awaitable, same
|
|
648
581
|
* widening `remove` documents above ({@link StructuralWriteOutcome}) and for
|
|
649
|
-
* the same reason
|
|
582
|
+
* the same reason: `deleteSelection`
|
|
650
583
|
* (`editor-hotkeys.ts`) awaits it so the caller can rely on the whole
|
|
651
584
|
* batch's write having landed before it returns. A synchronous/in-memory
|
|
652
|
-
* implementation
|
|
653
|
-
* is a harmless no-op.
|
|
585
|
+
* implementation can return void.
|
|
654
586
|
*/
|
|
655
587
|
removeMany?(ids: readonly string[]): StructuralWriteOutcome;
|
|
656
588
|
/** Copy authored entities through the host clipboard. The adapter owns the
|
|
657
|
-
* native payload (JSX for a source-backed
|
|
589
|
+
* native payload (JSX for a source-backed stage or canvas world, native records
|
|
658
590
|
* for a data-backed adapter); the shell never serializes an engine-private
|
|
659
591
|
* shape. */
|
|
660
592
|
copy?(ids: readonly string[]): boolean | Promise<boolean>;
|
|
@@ -691,30 +623,21 @@ export interface PersistenceProvider {
|
|
|
691
623
|
* Human/agent-readable destination this provider persists to — e.g.
|
|
692
624
|
* `"src/world.tsx"`, `"live-only (not saved)"`, or `"ephemeral
|
|
693
625
|
* (discarded on stop)"`. Drives the save-status UI and makes routing
|
|
694
|
-
* inspectable
|
|
626
|
+
* inspectable. Implementers whose destination can change during
|
|
695
627
|
* the session (a provider that tracks the currently focused document, say)
|
|
696
628
|
* should expose this as a live getter rather than a value captured once.
|
|
697
629
|
*/
|
|
698
630
|
readonly destination: string;
|
|
699
631
|
/**
|
|
700
|
-
*
|
|
701
|
-
*
|
|
702
|
-
*
|
|
703
|
-
*
|
|
704
|
-
* ephemeral provider reports.
|
|
705
|
-
*
|
|
706
|
-
* `rawContent`, when the host has it (the file-watcher SSE payload carries the
|
|
707
|
-
* artifact's exact bytes), is an OPTIONAL second parameter enabling own-echo
|
|
708
|
-
* detection — an event that is exactly what this provider itself last wrote is
|
|
709
|
-
* its own save reflected back, and should be skipped even outside the normal
|
|
710
|
-
* debounce window (see `EditorStore.applyExternalUpdate`'s doc comment). This
|
|
711
|
-
* stays optional/provider-specific — only the first-party provider currently
|
|
712
|
-
* uses it — so other implementers can ignore the parameter entirely.
|
|
632
|
+
* Optional adapter hook for applying an external artifact change to the
|
|
633
|
+
* running session. The adapter owns delivery of these changes and chooses
|
|
634
|
+
* whether to update in place or remount. A caller can supply exact artifact
|
|
635
|
+
* bytes in `rawContent` for provider-specific own-write detection.
|
|
713
636
|
*/
|
|
714
637
|
applyExternal?(content: unknown, rawContent?: string): void;
|
|
715
638
|
}
|
|
716
639
|
|
|
717
|
-
/**
|
|
640
|
+
/** per-layer viewport picking. Coordinates are client (browser) px. */
|
|
718
641
|
export interface PickProvider {
|
|
719
642
|
pick(clientX: number, clientY: number): string | null;
|
|
720
643
|
/**
|
|
@@ -727,7 +650,7 @@ export interface PickProvider {
|
|
|
727
650
|
candidates?(clientX: number, clientY: number, options?: { includeLocked?: boolean }): readonly string[];
|
|
728
651
|
}
|
|
729
652
|
|
|
730
|
-
/**
|
|
653
|
+
/** Storybook stories. */
|
|
731
654
|
export interface StoryRef {
|
|
732
655
|
id: string;
|
|
733
656
|
label: string;
|
|
@@ -736,57 +659,39 @@ export interface StoriesProvider {
|
|
|
736
659
|
storiesFor(nodeId: string): StoryRef[]; // [] = none
|
|
737
660
|
active(nodeId: string): string | null;
|
|
738
661
|
apply(nodeId: string, storyId: string | null): void; // null clears
|
|
739
|
-
/** Render ONLY this node against the story (storybook canvas); null exits. */
|
|
740
|
-
isolate?(nodeId: string | null, storyId?: string): void;
|
|
741
|
-
/**
|
|
742
|
-
* Display vocabulary for this provider's section — e.g. an ingested game's
|
|
743
|
-
* contract scenes say "Scenes"; absent means the default "Stories". The
|
|
744
|
-
* states are the same seam either way; only the word the human reads
|
|
745
|
-
* changes, so a game's own screens are never labelled with a design-time
|
|
746
|
-
* term the game never uses.
|
|
747
|
-
*/
|
|
748
|
-
readonly title?: string;
|
|
749
662
|
/**
|
|
750
663
|
* Why this provider could not enumerate, or `null` when it did. An empty
|
|
751
664
|
* `storiesFor` and an UNREAD one look identical from the section that draws
|
|
752
665
|
* them, and only the provider knows which it is — so the PROVIDER answers,
|
|
753
666
|
* and the shell never reaches past it into one particular provider's own
|
|
754
|
-
* discovery to find out (a CSF registry, a
|
|
667
|
+
* discovery to find out (a CSF registry, a project contract's screen list).
|
|
755
668
|
* Absent means the provider always ran.
|
|
756
669
|
*/
|
|
757
670
|
unavailable?(): string | null;
|
|
758
671
|
}
|
|
759
672
|
|
|
760
673
|
/**
|
|
761
|
-
*
|
|
762
|
-
*
|
|
763
|
-
*
|
|
764
|
-
* ignores it, and a caller with no point omits it — so neither side has to
|
|
765
|
-
* pretend. Coordinates are world-space, in the adapter's own units.
|
|
674
|
+
* What a drop places: a project component, named by its source module and
|
|
675
|
+
* export, and the surface it mounts on. The project's native source remains
|
|
676
|
+
* truth.
|
|
766
677
|
*/
|
|
767
678
|
export interface AssetDropContext {
|
|
768
|
-
readonly
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
readonly kind: 'component';
|
|
775
|
-
readonly name: string;
|
|
776
|
-
readonly sourcePath: string;
|
|
777
|
-
readonly exportKind: 'default' | 'named';
|
|
778
|
-
readonly surface: 'three' | 'canvas' | 'dom' | 'unknown';
|
|
779
|
-
};
|
|
679
|
+
readonly item: {
|
|
680
|
+
readonly name: string;
|
|
681
|
+
readonly sourcePath: string;
|
|
682
|
+
readonly exportKind: 'default' | 'named';
|
|
683
|
+
readonly surface: 'stage' | 'canvas' | 'dom' | 'unknown';
|
|
684
|
+
};
|
|
780
685
|
}
|
|
781
686
|
|
|
782
|
-
/**
|
|
687
|
+
/** Component drop (the canvas Add menu's project components). */
|
|
783
688
|
export interface AssetDropProvider {
|
|
784
|
-
accepts(nodeId: string, assetPath: string, context
|
|
785
|
-
/** A drop that lands as an ELEMENT in the
|
|
689
|
+
accepts(nodeId: string, assetPath: string, context: AssetDropContext): boolean;
|
|
690
|
+
/** A drop that lands as an ELEMENT in the project's own source is a structural
|
|
786
691
|
* write, so it answers with the same {@link StructuralWriteOutcome} the rest
|
|
787
692
|
* of {@link StructureProvider}'s writing verbs do — a lane whose drop only
|
|
788
693
|
* mutates the running graph returns `void`. */
|
|
789
|
-
drop(nodeId: string, assetPath: string, context
|
|
694
|
+
drop(nodeId: string, assetPath: string, context: AssetDropContext): StructuralWriteOutcome;
|
|
790
695
|
}
|
|
791
696
|
|
|
792
697
|
/** Plain-object rect shape shared by {@link RectProvider} — the same fields a real
|
|
@@ -799,11 +704,11 @@ export interface DOMRectLike {
|
|
|
799
704
|
height: number;
|
|
800
705
|
}
|
|
801
706
|
|
|
802
|
-
/**
|
|
803
|
-
*
|
|
804
|
-
*
|
|
805
|
-
*
|
|
806
|
-
|
|
707
|
+
/**
|
|
708
|
+
* Per-node screen geometry in host-relative pixels: relative to the adapter’s
|
|
709
|
+
* mounted surface, where the selection overlay draws. These are not viewport
|
|
710
|
+
* client coordinates.
|
|
711
|
+
*/
|
|
807
712
|
export interface RectProvider {
|
|
808
713
|
/** selectable node id → its current bounding rect, or null if unmounted/offscreen */
|
|
809
714
|
rect(id: string): { x: number; y: number; width: number; height: number } | null;
|
|
@@ -814,7 +719,7 @@ export interface RectProvider {
|
|
|
814
719
|
paddingBox?: DOMRectLike;
|
|
815
720
|
};
|
|
816
721
|
/**
|
|
817
|
-
*
|
|
722
|
+
* every currently-empty container this adapter's tree
|
|
818
723
|
* contains right now: no visible children, no text, a collapsed dimension
|
|
819
724
|
* (the `ui-source/inspect.ts:findEmptyContainers` math) — each with a
|
|
820
725
|
* grown-to-tappable placeholder rect and a display name, driving the
|
|
@@ -881,11 +786,10 @@ export interface BoxEditProvider {
|
|
|
881
786
|
referencePoint?(id: string): BoxEditReferencePoint | null;
|
|
882
787
|
}
|
|
883
788
|
|
|
884
|
-
/**
|
|
885
|
-
*
|
|
886
|
-
*
|
|
887
|
-
|
|
888
|
-
* concrete adapter's method. */
|
|
789
|
+
/**
|
|
790
|
+
* Text-content editing through the authoring contract. The overlay delegates
|
|
791
|
+
* in-place text edits to the owning adapter through this provider.
|
|
792
|
+
*/
|
|
889
793
|
export interface TextProvider {
|
|
890
794
|
/** the element's editable pure-text, or null if the body is dynamic/has child elements */
|
|
891
795
|
get(id: string): string | null;
|
|
@@ -893,7 +797,7 @@ export interface TextProvider {
|
|
|
893
797
|
}
|
|
894
798
|
|
|
895
799
|
/**
|
|
896
|
-
*
|
|
800
|
+
* background-color sampling at a viewport point, for the
|
|
897
801
|
* eyedropper's FALLBACK path (browsers with no native `EyeDropper` API). The
|
|
898
802
|
* native API, where available, samples real rendered pixels itself and needs
|
|
899
803
|
* none of this. Distinct from {@link PickProvider} (which returns a node id,
|
|
@@ -912,23 +816,23 @@ export interface ColorSampleProvider {
|
|
|
912
816
|
}
|
|
913
817
|
|
|
914
818
|
/**
|
|
915
|
-
* Where a node's live object CAME FROM in the
|
|
819
|
+
* Where a node's live object CAME FROM in the project's own truth.
|
|
916
820
|
*
|
|
917
821
|
* `display` is the string the editor shows verbatim. The unanchored shape
|
|
918
822
|
* carries a `reason` rather than a blank, because "we don't know" and "a
|
|
919
823
|
* library built it" are different facts and neither may present as silence
|
|
920
824
|
* (the honest-floor rule).
|
|
921
825
|
*
|
|
922
|
-
* TWO ANCHORED KINDS, because a
|
|
826
|
+
* TWO ANCHORED KINDS, because a project has two kinds of truth and only one of
|
|
923
827
|
* them is source.
|
|
924
828
|
*
|
|
925
829
|
* - `source` is the original: a `new` expression at a `file:line:col` in the
|
|
926
|
-
*
|
|
830
|
+
* project's own code, which is where an edit to a constructor literal has to be
|
|
927
831
|
* written.
|
|
928
|
-
* - `data` is the sibling a level-based
|
|
832
|
+
* - `data` is the sibling a level-based project needs. Its placed cargo — the
|
|
929
833
|
* enemies, the pickups, the objectives — reaches no source literal at all;
|
|
930
|
-
* it is binary records inside a level file that the
|
|
931
|
-
* authored move of one is therefore an edit to THE
|
|
834
|
+
* it is binary records inside a level file that the project parses at load. An
|
|
835
|
+
* authored move of one is therefore an edit to THE PROJECT'S OWN DATA, and
|
|
932
836
|
* the honest anchor is the data file plus the index of the record that
|
|
933
837
|
* addresses the object inside it.
|
|
934
838
|
*
|
|
@@ -946,7 +850,7 @@ export type NodeCreationSite =
|
|
|
946
850
|
| {
|
|
947
851
|
anchored: true;
|
|
948
852
|
kind: 'data';
|
|
949
|
-
/** Project-relative path of the
|
|
853
|
+
/** Project-relative path of the project's own data file, POSIX separators. */
|
|
950
854
|
file: string;
|
|
951
855
|
/** Index of the record inside that file which addresses this object. */
|
|
952
856
|
record: number;
|
|
@@ -964,15 +868,14 @@ export type NodeCreationSite =
|
|
|
964
868
|
* two are not the same fact — two nodes can both be `{ kind: 'source' }` at a
|
|
965
869
|
* `file:line` and still be written by different lanes with different gates.
|
|
966
870
|
*
|
|
967
|
-
* Each kind's
|
|
871
|
+
* Each kind's persistence contract:
|
|
968
872
|
*
|
|
969
|
-
* - `source-prop` — the value is a literal PROP on an element of the
|
|
873
|
+
* - `source-prop` — the value is a literal PROP on an element of the project's own
|
|
970
874
|
* source (a JSX attribute the serve-time authoring stamp addresses). Lands at
|
|
971
875
|
* the anchor; survives a cold remount, because the file is truth and the next
|
|
972
876
|
* mount re-derives from it.
|
|
973
|
-
* Proof: `packages/editor/test/oid-source-persistence.test.ts`.
|
|
974
877
|
* - `source-structure` — the edit is not a VALUE at all: it adds, removes,
|
|
975
|
-
* moves or re-nests an ELEMENT of the
|
|
878
|
+
* moves or re-nests an ELEMENT of the project's own source (`delete`,
|
|
976
879
|
* `duplicate`, `wrap`/`unwrap`, `create`, `reorder`, `reparent`, `group`).
|
|
977
880
|
* It is a kind rather than a flavour of `source-prop` because it resolves on
|
|
978
881
|
* a DIFFERENT DOOR — the dialect's structural writer, not its attribute
|
|
@@ -983,13 +886,11 @@ export type NodeCreationSite =
|
|
|
983
886
|
* does not have: the write is WHOLE-FILE and checksum-guarded, so an op
|
|
984
887
|
* resolved against a stale element index must fail rather than land at the
|
|
985
888
|
* wrong offset.
|
|
986
|
-
* Proof: `packages/editor/test/structural-write-pipe.test.ts`.
|
|
987
889
|
* - `construction-literal` — the value is a literal in the CONSTRUCTION
|
|
988
|
-
* EXPRESSION that built the object (
|
|
890
|
+
* EXPRESSION that built the object (a constructor call in the project's own
|
|
989
891
|
* served module). Same landing/remount contract, plus one gate the prop lane
|
|
990
892
|
* does not have: a site that constructed more than one object is refused,
|
|
991
893
|
* because rewriting its literal would move all of them.
|
|
992
|
-
* Proof: `packages/editor/test/ingest-source-persistence.test.ts`.
|
|
993
894
|
* - `physics-binding` — the node's own transform props are DEAD: a simulated
|
|
994
895
|
* body writes its matrix every frame from a spawn it reads elsewhere, so the
|
|
995
896
|
* write lands at the literal that binding reads (the component callsite whose
|
|
@@ -999,20 +900,14 @@ export type NodeCreationSite =
|
|
|
999
900
|
* body must have re-spawned at the AUTHORED pose, not at the old one. Being
|
|
1000
901
|
* silently re-posed by the owner is this kind's whole failure mode, and the
|
|
1001
902
|
* reason it is a kind rather than a flavour of `source-prop`.
|
|
1002
|
-
*
|
|
1003
|
-
* - `data-record` — the value is a field of a RECORD in the game's own data
|
|
903
|
+
* - `data-record` — the value is a field of a RECORD in the project's own data
|
|
1004
904
|
* file, addressed by index; no source literal mentions it. Lands in that
|
|
1005
|
-
* file through the
|
|
905
|
+
* file through the project's own declared writer; survives a cold remount for
|
|
1006
906
|
* the same reason source does.
|
|
1007
|
-
* Proof: `packages/editor/test/ingest-source-persistence.test.ts`
|
|
1008
|
-
* ("a level-data record is an anchor too").
|
|
1009
907
|
* - `live-only` — there is no anchor. The edit lands on the running object for
|
|
1010
908
|
* the session and NOTHING else, and the contract is that the surface SAYS SO:
|
|
1011
909
|
* a write ack that claims a destination it did not reach is the lie this kind
|
|
1012
910
|
* exists to keep nameable.
|
|
1013
|
-
* Proof: `packages/editor/test/oid-source-persistence.test.ts`
|
|
1014
|
-
* ("an object with no source stamp is refused by name")
|
|
1015
|
-
* + `packages/editor/test/inspection-write-destination.test.ts`.
|
|
1016
911
|
*/
|
|
1017
912
|
export type WriteAnchorKind =
|
|
1018
913
|
| 'source-prop'
|
|
@@ -1023,29 +918,15 @@ export type WriteAnchorKind =
|
|
|
1023
918
|
| 'live-only';
|
|
1024
919
|
|
|
1025
920
|
/**
|
|
1026
|
-
*
|
|
1027
|
-
* the
|
|
1028
|
-
*
|
|
1029
|
-
* It is deliberately NOT a property of an adapter, a session or a surface. The
|
|
1030
|
-
* fact it carries is per-edit, because that is the only granularity at which it
|
|
1031
|
-
* can be true: one composite may hold a source-backed three root beside a
|
|
1032
|
-
* live-only DOM root, and one three root holds body-placed nodes beside
|
|
1033
|
-
* ordinary JSX props. An answer computed from the SURFACE rather than from the
|
|
1034
|
-
* edit reports whichever child happened to be persist-capable — measured on the
|
|
1035
|
-
* vendored racing game, where a three-root edit acked the other root's
|
|
1036
|
-
* destination with `persisted: true`.
|
|
1037
|
-
*
|
|
1038
|
-
* `persisted: false` is an ANSWER, never a failure: `live-only` is a real
|
|
1039
|
-
* anchor kind and the contract of that kind is that the surface SAYS SO. What
|
|
1040
|
-
* is forbidden is a `destination` no byte reached being reported with
|
|
1041
|
-
* `persisted: true`.
|
|
921
|
+
* The persistence result for one edit, returned by the component that performed
|
|
922
|
+
* the write. Composite roots and nodes may have different destinations, so an
|
|
923
|
+
* adapter-wide destination cannot describe an individual edit.
|
|
1042
924
|
*
|
|
1043
|
-
*
|
|
1044
|
-
*
|
|
1045
|
-
*
|
|
1046
|
-
*
|
|
1047
|
-
*
|
|
1048
|
-
* save-status chrome.
|
|
925
|
+
* `persisted: false` is a valid live-only result. `persisted: true` requires that
|
|
926
|
+
* bytes reached the reported destination. A provider with no write result
|
|
927
|
+
* returns nothing and the shell reports the live-only floor.
|
|
928
|
+
* {@link PersistenceProvider.destination} describes where saves go for status
|
|
929
|
+
* chrome; it does not substitute for a per-edit result.
|
|
1049
930
|
*/
|
|
1050
931
|
export interface WriteAck {
|
|
1051
932
|
/** Where THIS edit's bytes landed, in the writer's own words — or the
|
|
@@ -1103,7 +984,7 @@ export function emptyWriteAnchorKindCounts(): Record<WriteAnchorKind, number> {
|
|
|
1103
984
|
* Present ⇒ every id gets an answer, anchored or reasoned.
|
|
1104
985
|
*/
|
|
1105
986
|
export interface AuthoringTruth {
|
|
1106
|
-
/** Where the runtime object came from in the
|
|
987
|
+
/** Where the runtime object came from in the project's own source or data. */
|
|
1107
988
|
readonly site: NodeCreationSite;
|
|
1108
989
|
/** The lane THIS property edit would actually take. `undefined` means the
|
|
1109
990
|
* subject is synthetic or otherwise has no write plan; `live-only` is a real
|
|
@@ -1111,12 +992,8 @@ export interface AuthoringTruth {
|
|
|
1111
992
|
readonly writeAnchorKind: WriteAnchorKind | undefined;
|
|
1112
993
|
}
|
|
1113
994
|
|
|
1114
|
-
/**
|
|
1115
|
-
*
|
|
1116
|
-
* from and where an edit to one of its properties lands. A caller may not read
|
|
1117
|
-
* those facts through separate providers: that was the classifier/writer split
|
|
1118
|
-
* the persistence pipe exists to remove.
|
|
1119
|
-
*/
|
|
995
|
+
/** One truth resolution describes a subject's creation site and the
|
|
996
|
+
* destination of its property writes. */
|
|
1120
997
|
export interface TruthProvider {
|
|
1121
998
|
resolve(id: string, property: string): AuthoringTruth;
|
|
1122
999
|
}
|
|
@@ -1188,7 +1065,7 @@ export interface SpatialDragHandle {
|
|
|
1188
1065
|
}
|
|
1189
1066
|
|
|
1190
1067
|
/** One adapter-owned component projection. `category` is a viewport overlay
|
|
1191
|
-
* channel (for example `audio`), not a
|
|
1068
|
+
* channel (for example `audio`), not a scene-object kind; unknown categories
|
|
1192
1069
|
* obey the master Helpers toggle instead of being rejected. */
|
|
1193
1070
|
export interface SpatialHandleLayer {
|
|
1194
1071
|
readonly id: string;
|
|
@@ -1218,7 +1095,7 @@ export interface SpatialHandlesProvider {
|
|
|
1218
1095
|
|
|
1219
1096
|
export interface AuthoringAdapter {
|
|
1220
1097
|
readonly capabilities: AuthoringCapabilities;
|
|
1221
|
-
/**
|
|
1098
|
+
/** Seam-level provenance ("what is truth behind these rows").
|
|
1222
1099
|
* Absent ⇒ the shell shows no provenance badge (degrade silently — never
|
|
1223
1100
|
* fabricate a claim the adapter didn't make). */
|
|
1224
1101
|
readonly provenance?: AuthoringProvenance;
|
|
@@ -1226,57 +1103,42 @@ export interface AuthoringAdapter {
|
|
|
1226
1103
|
readonly selection?: SelectionProvider;
|
|
1227
1104
|
readonly transforms?: TransformProvider;
|
|
1228
1105
|
readonly inspector?: InspectorProvider;
|
|
1229
|
-
/** The selected node is an atomic asset that can open in the Asset Editor. */
|
|
1230
|
-
readonly assetSubject?: AssetSubjectProvider;
|
|
1231
1106
|
readonly related?: RelatedSubjectsProvider;
|
|
1232
1107
|
/** Source-derived prefab/component instance overrides and native writes. */
|
|
1233
1108
|
readonly instances?: ComponentInstancesProvider;
|
|
1234
1109
|
readonly structure?: StructureProvider;
|
|
1235
1110
|
readonly persistence?: PersistenceProvider;
|
|
1236
|
-
/**
|
|
1111
|
+
/** per-layer viewport picking. Absent ⇒ this adapter is not pickable. */
|
|
1237
1112
|
readonly pickable?: PickProvider;
|
|
1238
|
-
/**
|
|
1113
|
+
/** per-node screen geometry for a DOM visual editor's overlay/
|
|
1239
1114
|
* snap/measure math. Absent ⇒ this adapter produces no rects (no overlay). */
|
|
1240
1115
|
readonly rects?: RectProvider;
|
|
1241
|
-
/**
|
|
1242
|
-
*
|
|
1116
|
+
/** spatial drag-resize/move → source/data write for DOM
|
|
1117
|
+
* nodes, which have no scene object. Absent ⇒ no box-edit gesture for this adapter. */
|
|
1243
1118
|
readonly boxEdit?: BoxEditProvider;
|
|
1244
|
-
/**
|
|
1245
|
-
*
|
|
1119
|
+
/**
|
|
1120
|
+
* Optional in-place text editing. Absent means this adapter does not
|
|
1121
|
+
* support the overlay’s double-click text edit gesture.
|
|
1122
|
+
*/
|
|
1246
1123
|
readonly text?: TextProvider;
|
|
1247
|
-
/**
|
|
1124
|
+
/** eyedropper fallback color sampling. Absent ⇒ the
|
|
1248
1125
|
* canvas eyedropper swatch has no non-native path for this adapter. */
|
|
1249
1126
|
readonly colorSample?: ColorSampleProvider;
|
|
1250
|
-
/**
|
|
1127
|
+
/** Storybook stories. Absent ⇒ no stories for any node in this adapter. */
|
|
1251
1128
|
readonly stories?: StoriesProvider;
|
|
1252
1129
|
/** Projection subject → source/data anchor and write lane, resolved together. */
|
|
1253
1130
|
readonly truth?: TruthProvider;
|
|
1254
1131
|
/** Adapter-owned component guides and direct-manipulation points. */
|
|
1255
1132
|
readonly spatialHandles?: SpatialHandlesProvider;
|
|
1256
|
-
/**
|
|
1133
|
+
/** Component drop (the canvas Add menu). Absent ⇒ this adapter accepts no drops. */
|
|
1257
1134
|
readonly assetDrop?: AssetDropProvider;
|
|
1258
1135
|
/** Change notification → UI refresh. */
|
|
1259
1136
|
subscribe?(listener: () => void): () => void;
|
|
1260
1137
|
}
|
|
1261
1138
|
|
|
1262
|
-
/**
|
|
1263
|
-
*
|
|
1264
|
-
*
|
|
1265
|
-
*
|
|
1266
|
-
* Why this exists: the editor's coverage warnings are supposed to make stopping
|
|
1267
|
-
* short of a native root IMPOSSIBLE, and they cannot do that while the row
|
|
1268
|
-
* vocabulary is a hand-written list frozen at what its author happened to know.
|
|
1269
|
-
* A list like that goes quiet at "all warnings closed" while whole capabilities
|
|
1270
|
-
* — stories, asset drop, related subjects, structure — were never enumerated at
|
|
1271
|
-
* all, so nothing ever warned about them. So the vocabulary IS the type: adding
|
|
1272
|
-
* a provider to `AuthoringAdapter` and forgetting it here is a COMPILE ERROR
|
|
1273
|
-
* (the `Record` below is missing a key), and inventing a key the type does not
|
|
1274
|
-
* have is an excess-property error. There is no third way to add a provider.
|
|
1275
|
-
*
|
|
1276
|
-
* `capabilities` and `hierarchy` are excluded because they are required members
|
|
1277
|
-
* — every adapter has them by construction, so "absent" is not a state they can
|
|
1278
|
-
* be in and a row about them could never say anything.
|
|
1279
|
-
*/
|
|
1139
|
+
/** Provider vocabulary derived from AuthoringAdapter. The exhaustive Record
|
|
1140
|
+
* requires an entry for each optional provider and rejects unknown keys.
|
|
1141
|
+
* Required capabilities and hierarchy are excluded because every adapter has them. */
|
|
1280
1142
|
export type AuthoringProviderKey = Exclude<keyof AuthoringAdapter, 'capabilities' | 'hierarchy'>;
|
|
1281
1143
|
|
|
1282
1144
|
/**
|
|
@@ -1290,7 +1152,6 @@ const AUTHORING_PROVIDER_PRESENCE: Readonly<Record<AuthoringProviderKey, true>>
|
|
|
1290
1152
|
selection: true,
|
|
1291
1153
|
transforms: true,
|
|
1292
1154
|
inspector: true,
|
|
1293
|
-
assetSubject: true,
|
|
1294
1155
|
related: true,
|
|
1295
1156
|
instances: true,
|
|
1296
1157
|
structure: true,
|
|
@@ -1322,7 +1183,7 @@ export const AUTHORING_PROVIDER_KEYS: readonly AuthoringProviderKey[] = Object.k
|
|
|
1322
1183
|
/**
|
|
1323
1184
|
* Which providers this adapter actually exposes — PRESENCE, measured off the
|
|
1324
1185
|
* object itself. Nothing here consults `capabilities`, the adapter's class, the
|
|
1325
|
-
* route that built it, or the
|
|
1186
|
+
* route that built it, or the project's id: an adapter this function has never
|
|
1326
1187
|
* heard of gets the same answer as one it has.
|
|
1327
1188
|
*/
|
|
1328
1189
|
export function measureAuthoringProviders(
|