@storylet-studio/runtime 0.2.0 → 0.4.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/dist/index.cjs +55 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -8
- package/dist/index.d.ts +18 -8
- package/dist/index.js +55 -18
- package/dist/index.js.map +1 -1
- package/package.json +8 -3
- package/dist/storyletengine.min.js +0 -2
- package/dist/storyletengine.min.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -2,6 +2,7 @@ import { ScalarValue, ScopeResolver, ExprNode } from '@wildwinter/expr';
|
|
|
2
2
|
export { Prng, makePrng, shuffleInPlace } from '@wildwinter/expr';
|
|
3
3
|
import { Bundle, Card, Expression, Deck, Box, Hand, HandTemplate, TagGroup, PropertyDecl, FlowSave, SaveEnvelope, PropertyType, ScalarValue as ScalarValue$1 } from '@storylet-studio/model';
|
|
4
4
|
import { PropertyBag, PropertyRow } from '@wildwinter/scoperegistry';
|
|
5
|
+
export { PropertyRow } from '@wildwinter/scoperegistry';
|
|
5
6
|
|
|
6
7
|
interface EngineOptions {
|
|
7
8
|
/** Default seed for each flow's PRNG; override per flow in openFlow
|
|
@@ -23,6 +24,16 @@ interface EngineOptions {
|
|
|
23
24
|
* once, each engine saves its own envelope (design/flows.md).
|
|
24
25
|
*/
|
|
25
26
|
world?: ScopeResolver;
|
|
27
|
+
/**
|
|
28
|
+
* Diagnostics hook (opt-in, dev tooling only): fired when `openFlow` REPLACES
|
|
29
|
+
* a flow that still had cards dealt, with the flow id and how many. The
|
|
30
|
+
* behaviour is unchanged - replacing is deliberate and the same in Patter -
|
|
31
|
+
* this only makes it observable, because the case it catches is a host
|
|
32
|
+
* calling `openFlow` straight after `loadGame` to "re-take" its handle and
|
|
33
|
+
* silently discarding the hand the save just restored (`getFlow` is the
|
|
34
|
+
* call). Zero cost when unset; leave it unset in shipped games.
|
|
35
|
+
*/
|
|
36
|
+
onReplacedFlow?: (id: string, dealt: number) => void;
|
|
26
37
|
}
|
|
27
38
|
interface OpenFlowOptions {
|
|
28
39
|
/** Seed for this flow's PRNG (defaults to the engine's `seed`). */
|
|
@@ -142,11 +153,6 @@ interface CardEntry {
|
|
|
142
153
|
deck: Deck<Expression>;
|
|
143
154
|
box: Box<Expression>;
|
|
144
155
|
}
|
|
145
|
-
/** One examiner row, addressed by the property-path grammar
|
|
146
|
-
* (getProperty / setProperty take the same `path`). */
|
|
147
|
-
interface PropertyView extends PropertyRow {
|
|
148
|
-
path: string;
|
|
149
|
-
}
|
|
150
156
|
/** One kernel bag with its store path prefix (story / box.<id> / deck.<id>
|
|
151
157
|
* / hand.<id> / value.<id>): the state logger's mount surface
|
|
152
158
|
* (design/engine-runtimes.md 3.4 - the logger builds on the PropertyBag
|
|
@@ -228,6 +234,9 @@ interface Internals {
|
|
|
228
234
|
shared: Partition;
|
|
229
235
|
/** @world: the host's resolver, or the self-backed bag's. */
|
|
230
236
|
worldResolver: ScopeResolver;
|
|
237
|
+
/** @world names declared `writable: false`: the story's promise, kept at
|
|
238
|
+
* runtime as the compiler keeps it at publish (Reboot.md 10). */
|
|
239
|
+
worldReadOnly: Set<string>;
|
|
231
240
|
/** `turn` is the box clock the event happened on, where the caller knows it
|
|
232
241
|
* - the same stamp the flow's own log carries. Unity and Unreal passed it
|
|
233
242
|
* from the start; JS and Godot dropped it, so their examiners printed "[-]"
|
|
@@ -239,6 +248,7 @@ interface Internals {
|
|
|
239
248
|
declare class Engine {
|
|
240
249
|
private readonly internals;
|
|
241
250
|
private readonly seed;
|
|
251
|
+
private readonly onReplacedFlow;
|
|
242
252
|
private readonly flowsById;
|
|
243
253
|
private readonly engineTraceHandlers;
|
|
244
254
|
/** The host's @world binding, if the engine was built with one: it
|
|
@@ -308,7 +318,7 @@ declare class Engine {
|
|
|
308
318
|
private resolveShared;
|
|
309
319
|
/** The shared surface as examiner rows: @world (read through the
|
|
310
320
|
* resolver) then the shared partitions. Per-flow rows live on each Flow. */
|
|
311
|
-
listProperties():
|
|
321
|
+
listProperties(): PropertyRow[];
|
|
312
322
|
/** The SHARED kernel bags with their store path prefixes (the state
|
|
313
323
|
* logger's mount surface). The @world container is the host's own bag -
|
|
314
324
|
* the host mounts it itself. */
|
|
@@ -525,7 +535,7 @@ declare class Flow {
|
|
|
525
535
|
* resolver, then per scope the shared values and this flow's own.
|
|
526
536
|
* Bundle order: world, story, then per-box / per-deck / per-hand /
|
|
527
537
|
* per-tag stores. */
|
|
528
|
-
listProperties():
|
|
538
|
+
listProperties(): PropertyRow[];
|
|
529
539
|
/** Read by path: "world.x", "story.gold", "value.v_docks.danger",
|
|
530
540
|
* "box.b_x.heat", "deck.k_main.n", "hand.h_board.owner" - the flow's
|
|
531
541
|
* merged view, routed by the declaration's sharing. */
|
|
@@ -653,4 +663,4 @@ interface BundleDescription {
|
|
|
653
663
|
* throughout; the same shape every runtime returns. */
|
|
654
664
|
declare function describeBundle(bundle: Bundle): BundleDescription;
|
|
655
665
|
|
|
656
|
-
export { type BagMount, type BoxSummary, type BoxView, type BundleDescription, type BundleIdentity, type DealtCard, Engine, type EngineLogEntry, type EngineOptions, type EngineTraceHandler, Flow, type HandSummary, type LogEntry, type MapSummary, type OpenFlowOptions, type OutcomeView, type PlayOptions, type PropertyScopeKind, type PropertyScopeSummary, type PropertySummary, type
|
|
666
|
+
export { type BagMount, type BoxSummary, type BoxView, type BundleDescription, type BundleIdentity, type DealtCard, Engine, type EngineLogEntry, type EngineOptions, type EngineTraceHandler, Flow, type HandSummary, type LogEntry, type MapSummary, type OpenFlowOptions, type OutcomeView, type PlayOptions, type PropertyScopeKind, type PropertyScopeSummary, type PropertySummary, type RankedList, type TagGroupSummary, type TraceEvent, type TraceHandler, type TraceVerdict, describeBundle };
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { ScalarValue, ScopeResolver, ExprNode } from '@wildwinter/expr';
|
|
|
2
2
|
export { Prng, makePrng, shuffleInPlace } from '@wildwinter/expr';
|
|
3
3
|
import { Bundle, Card, Expression, Deck, Box, Hand, HandTemplate, TagGroup, PropertyDecl, FlowSave, SaveEnvelope, PropertyType, ScalarValue as ScalarValue$1 } from '@storylet-studio/model';
|
|
4
4
|
import { PropertyBag, PropertyRow } from '@wildwinter/scoperegistry';
|
|
5
|
+
export { PropertyRow } from '@wildwinter/scoperegistry';
|
|
5
6
|
|
|
6
7
|
interface EngineOptions {
|
|
7
8
|
/** Default seed for each flow's PRNG; override per flow in openFlow
|
|
@@ -23,6 +24,16 @@ interface EngineOptions {
|
|
|
23
24
|
* once, each engine saves its own envelope (design/flows.md).
|
|
24
25
|
*/
|
|
25
26
|
world?: ScopeResolver;
|
|
27
|
+
/**
|
|
28
|
+
* Diagnostics hook (opt-in, dev tooling only): fired when `openFlow` REPLACES
|
|
29
|
+
* a flow that still had cards dealt, with the flow id and how many. The
|
|
30
|
+
* behaviour is unchanged - replacing is deliberate and the same in Patter -
|
|
31
|
+
* this only makes it observable, because the case it catches is a host
|
|
32
|
+
* calling `openFlow` straight after `loadGame` to "re-take" its handle and
|
|
33
|
+
* silently discarding the hand the save just restored (`getFlow` is the
|
|
34
|
+
* call). Zero cost when unset; leave it unset in shipped games.
|
|
35
|
+
*/
|
|
36
|
+
onReplacedFlow?: (id: string, dealt: number) => void;
|
|
26
37
|
}
|
|
27
38
|
interface OpenFlowOptions {
|
|
28
39
|
/** Seed for this flow's PRNG (defaults to the engine's `seed`). */
|
|
@@ -142,11 +153,6 @@ interface CardEntry {
|
|
|
142
153
|
deck: Deck<Expression>;
|
|
143
154
|
box: Box<Expression>;
|
|
144
155
|
}
|
|
145
|
-
/** One examiner row, addressed by the property-path grammar
|
|
146
|
-
* (getProperty / setProperty take the same `path`). */
|
|
147
|
-
interface PropertyView extends PropertyRow {
|
|
148
|
-
path: string;
|
|
149
|
-
}
|
|
150
156
|
/** One kernel bag with its store path prefix (story / box.<id> / deck.<id>
|
|
151
157
|
* / hand.<id> / value.<id>): the state logger's mount surface
|
|
152
158
|
* (design/engine-runtimes.md 3.4 - the logger builds on the PropertyBag
|
|
@@ -228,6 +234,9 @@ interface Internals {
|
|
|
228
234
|
shared: Partition;
|
|
229
235
|
/** @world: the host's resolver, or the self-backed bag's. */
|
|
230
236
|
worldResolver: ScopeResolver;
|
|
237
|
+
/** @world names declared `writable: false`: the story's promise, kept at
|
|
238
|
+
* runtime as the compiler keeps it at publish (Reboot.md 10). */
|
|
239
|
+
worldReadOnly: Set<string>;
|
|
231
240
|
/** `turn` is the box clock the event happened on, where the caller knows it
|
|
232
241
|
* - the same stamp the flow's own log carries. Unity and Unreal passed it
|
|
233
242
|
* from the start; JS and Godot dropped it, so their examiners printed "[-]"
|
|
@@ -239,6 +248,7 @@ interface Internals {
|
|
|
239
248
|
declare class Engine {
|
|
240
249
|
private readonly internals;
|
|
241
250
|
private readonly seed;
|
|
251
|
+
private readonly onReplacedFlow;
|
|
242
252
|
private readonly flowsById;
|
|
243
253
|
private readonly engineTraceHandlers;
|
|
244
254
|
/** The host's @world binding, if the engine was built with one: it
|
|
@@ -308,7 +318,7 @@ declare class Engine {
|
|
|
308
318
|
private resolveShared;
|
|
309
319
|
/** The shared surface as examiner rows: @world (read through the
|
|
310
320
|
* resolver) then the shared partitions. Per-flow rows live on each Flow. */
|
|
311
|
-
listProperties():
|
|
321
|
+
listProperties(): PropertyRow[];
|
|
312
322
|
/** The SHARED kernel bags with their store path prefixes (the state
|
|
313
323
|
* logger's mount surface). The @world container is the host's own bag -
|
|
314
324
|
* the host mounts it itself. */
|
|
@@ -525,7 +535,7 @@ declare class Flow {
|
|
|
525
535
|
* resolver, then per scope the shared values and this flow's own.
|
|
526
536
|
* Bundle order: world, story, then per-box / per-deck / per-hand /
|
|
527
537
|
* per-tag stores. */
|
|
528
|
-
listProperties():
|
|
538
|
+
listProperties(): PropertyRow[];
|
|
529
539
|
/** Read by path: "world.x", "story.gold", "value.v_docks.danger",
|
|
530
540
|
* "box.b_x.heat", "deck.k_main.n", "hand.h_board.owner" - the flow's
|
|
531
541
|
* merged view, routed by the declaration's sharing. */
|
|
@@ -653,4 +663,4 @@ interface BundleDescription {
|
|
|
653
663
|
* throughout; the same shape every runtime returns. */
|
|
654
664
|
declare function describeBundle(bundle: Bundle): BundleDescription;
|
|
655
665
|
|
|
656
|
-
export { type BagMount, type BoxSummary, type BoxView, type BundleDescription, type BundleIdentity, type DealtCard, Engine, type EngineLogEntry, type EngineOptions, type EngineTraceHandler, Flow, type HandSummary, type LogEntry, type MapSummary, type OpenFlowOptions, type OutcomeView, type PlayOptions, type PropertyScopeKind, type PropertyScopeSummary, type PropertySummary, type
|
|
666
|
+
export { type BagMount, type BoxSummary, type BoxView, type BundleDescription, type BundleIdentity, type DealtCard, Engine, type EngineLogEntry, type EngineOptions, type EngineTraceHandler, Flow, type HandSummary, type LogEntry, type MapSummary, type OpenFlowOptions, type OutcomeView, type PlayOptions, type PropertyScopeKind, type PropertyScopeSummary, type PropertySummary, type RankedList, type TagGroupSummary, type TraceEvent, type TraceHandler, type TraceVerdict, describeBundle };
|
package/dist/index.js
CHANGED
|
@@ -423,8 +423,12 @@ var PropertyBag = class _PropertyBag {
|
|
|
423
423
|
* long-standing contract); a product whose names are case-significant
|
|
424
424
|
* passes identity. */
|
|
425
425
|
norm;
|
|
426
|
+
/** The address prefix this bag's rows carry, separator included (`@`,
|
|
427
|
+
* `@scene.`, `world.`, `deck.<id>.`). Empty means a row's path is its name. */
|
|
428
|
+
pathPrefix;
|
|
426
429
|
constructor(declarations = [], opts) {
|
|
427
430
|
this.norm = opts?.normalise ?? ((n) => n.toLowerCase());
|
|
431
|
+
this.pathPrefix = opts?.pathPrefix ?? "";
|
|
428
432
|
this.seed(declarations);
|
|
429
433
|
}
|
|
430
434
|
seed(declarations) {
|
|
@@ -468,7 +472,7 @@ var PropertyBag = class _PropertyBag {
|
|
|
468
472
|
/** Examiner rows: the declared surface only (stray values are storage,
|
|
469
473
|
* not surface). */
|
|
470
474
|
rows() {
|
|
471
|
-
return [...this.decls.entries()].map(([name, d]) => rowFor(d, this.get(name), void 0, name));
|
|
475
|
+
return [...this.decls.entries()].map(([name, d]) => rowFor(d, this.get(name), void 0, name, this.pathPrefix));
|
|
472
476
|
}
|
|
473
477
|
declarations() {
|
|
474
478
|
return [...this.decls.values()];
|
|
@@ -477,7 +481,7 @@ var PropertyBag = class _PropertyBag {
|
|
|
477
481
|
* duplicated, the normalisation policy carried, subscriptions NOT
|
|
478
482
|
* carried. */
|
|
479
483
|
clone() {
|
|
480
|
-
const c = new _PropertyBag([], { normalise: this.norm });
|
|
484
|
+
const c = new _PropertyBag([], { normalise: this.norm, pathPrefix: this.pathPrefix });
|
|
481
485
|
c.decls = new Map(this.decls);
|
|
482
486
|
Object.assign(c.values, structuredClone(this.values));
|
|
483
487
|
return c;
|
|
@@ -500,13 +504,19 @@ var PropertyBag = class _PropertyBag {
|
|
|
500
504
|
for (const [k, v] of Object.entries(values)) this.values[this.norm(k)] = v;
|
|
501
505
|
}
|
|
502
506
|
};
|
|
503
|
-
function rowFor(d, value, writable, name) {
|
|
507
|
+
function rowFor(d, value, writable, name, pathPrefix = "") {
|
|
508
|
+
const rowName = name ?? d.name.toLowerCase();
|
|
504
509
|
return {
|
|
505
|
-
name:
|
|
510
|
+
name: rowName,
|
|
511
|
+
path: pathPrefix + rowName,
|
|
506
512
|
type: d.type,
|
|
507
513
|
value,
|
|
508
514
|
default: d.default ?? defaultFor(d),
|
|
509
515
|
...d.values !== void 0 ? { values: d.values } : {},
|
|
516
|
+
// `stages` was added to the row so an examiner could offer a quality's ladder
|
|
517
|
+
// instead of a free-text box, and then never populated here: every quality row
|
|
518
|
+
// this function built came out without one. Fixed 2026-09-02.
|
|
519
|
+
...d.stages !== void 0 ? { stages: d.stages } : {},
|
|
510
520
|
writable: writable ?? d.writable ?? true
|
|
511
521
|
};
|
|
512
522
|
}
|
|
@@ -526,6 +536,13 @@ function defaultFor(d) {
|
|
|
526
536
|
// A quality starts at the first rung of its ladder.
|
|
527
537
|
case "quality":
|
|
528
538
|
return d.stages?.[0] ?? "";
|
|
539
|
+
// Unreachable for a well-typed declaration, and deliberately present anyway: a bundle
|
|
540
|
+
// is DATA, and a hand-edited or newer-than-this-build one can carry a type string the
|
|
541
|
+
// union does not have. Falling off the switch would seed `undefined`, which is not a
|
|
542
|
+
// ScalarValue and travels a long way before it fails. Patterplay's copy of this had the
|
|
543
|
+
// guard and this one did not, which is the drift you only find by removing a duplicate.
|
|
544
|
+
default:
|
|
545
|
+
return false;
|
|
529
546
|
}
|
|
530
547
|
}
|
|
531
548
|
|
|
@@ -533,7 +550,7 @@ function defaultFor(d) {
|
|
|
533
550
|
var tagKey = (groupId, tagId) => `${groupId}${tagId}`;
|
|
534
551
|
var cardIsShared = (card, deckShared) => card.shared ?? deckShared;
|
|
535
552
|
var sharedCap = (card) => card.sharedCopies ?? card.copies ?? 1;
|
|
536
|
-
var bagFromDecls = (decls) => new PropertyBag(decls, { normalise: (n) => n });
|
|
553
|
+
var bagFromDecls = (decls, pathPrefix) => new PropertyBag(decls, { normalise: (n) => n, pathPrefix });
|
|
537
554
|
function conditionPasses(v) {
|
|
538
555
|
if (typeof v === "boolean") return v;
|
|
539
556
|
if (typeof v === "number") return v !== 0;
|
|
@@ -553,18 +570,18 @@ var handDeclsOf = (internals, hand) => {
|
|
|
553
570
|
var buildPartition = (internals, half) => {
|
|
554
571
|
const b = internals.bundle;
|
|
555
572
|
return {
|
|
556
|
-
story: bagFromDecls(half("story", b.story.properties)),
|
|
557
|
-
box: new Map(b.boxes.map((box) => [box.id, bagFromDecls(half("box", box.properties))])),
|
|
573
|
+
story: bagFromDecls(half("story", b.story.properties), "story."),
|
|
574
|
+
box: new Map(b.boxes.map((box) => [box.id, bagFromDecls(half("box", box.properties), `box.${box.id}.`)])),
|
|
558
575
|
deck: new Map(b.boxes.flatMap((box) => box.decks.map(
|
|
559
|
-
(deck) => [deck.id, bagFromDecls(half("deck", deck.properties))]
|
|
576
|
+
(deck) => [deck.id, bagFromDecls(half("deck", deck.properties), `deck.${deck.id}.`)]
|
|
560
577
|
))),
|
|
561
578
|
// A template instance inherits the template's property declarations;
|
|
562
579
|
// a standalone hand declares its own (schema 2.6).
|
|
563
580
|
hand: new Map(b.boxes.flatMap((box) => box.hands.map(
|
|
564
|
-
(hand) => [hand.id, bagFromDecls(half("hand", handDeclsOf(internals, hand)))]
|
|
581
|
+
(hand) => [hand.id, bagFromDecls(half("hand", handDeclsOf(internals, hand)), `hand.${hand.id}.`)]
|
|
565
582
|
))),
|
|
566
583
|
value: new Map(b.boxes.flatMap((box) => box.tagGroups.flatMap((group) => group.tags.map(
|
|
567
|
-
(tag) => [tag.id, bagFromDecls(half("value", tag.properties ?? []))]
|
|
584
|
+
(tag) => [tag.id, bagFromDecls(half("value", tag.properties ?? []), `value.${tag.id}.`)]
|
|
568
585
|
))))
|
|
569
586
|
};
|
|
570
587
|
};
|
|
@@ -586,6 +603,7 @@ var loadPartition = (p, values) => {
|
|
|
586
603
|
var Engine = class {
|
|
587
604
|
internals;
|
|
588
605
|
seed;
|
|
606
|
+
onReplacedFlow;
|
|
589
607
|
flowsById = /* @__PURE__ */ new Map();
|
|
590
608
|
engineTraceHandlers = /* @__PURE__ */ new Set();
|
|
591
609
|
/** The host's @world binding, if the engine was built with one: it
|
|
@@ -594,6 +612,7 @@ var Engine = class {
|
|
|
594
612
|
hostWorld;
|
|
595
613
|
constructor(bundle, opts = {}) {
|
|
596
614
|
this.seed = opts.seed ?? 0;
|
|
615
|
+
this.onReplacedFlow = opts.onReplacedFlow;
|
|
597
616
|
if (opts.world !== void 0) this.hostWorld = opts.world;
|
|
598
617
|
const internals = {
|
|
599
618
|
bundle,
|
|
@@ -614,6 +633,7 @@ var Engine = class {
|
|
|
614
633
|
flowDecls: { story: [], box: /* @__PURE__ */ new Map(), deck: /* @__PURE__ */ new Map(), hand: /* @__PURE__ */ new Map(), value: /* @__PURE__ */ new Map() },
|
|
615
634
|
shared: void 0,
|
|
616
635
|
worldResolver: void 0,
|
|
636
|
+
worldReadOnly: /* @__PURE__ */ new Set(),
|
|
617
637
|
emitEngine: (flow, event, turn) => {
|
|
618
638
|
if (this.internals.logCap !== void 0) {
|
|
619
639
|
this.engineLog.push({ ...event, flow, seq: this.engineSeq++, ...turn !== void 0 ? { turn } : {} });
|
|
@@ -671,10 +691,11 @@ var Engine = class {
|
|
|
671
691
|
initShared(hostWorld) {
|
|
672
692
|
const internals = this.internals;
|
|
673
693
|
internals.shared = buildPartition(internals, sharedHalf);
|
|
694
|
+
internals.worldReadOnly = new Set(internals.bundle.world.properties.filter((d) => d.writable === false).map((d) => d.name));
|
|
674
695
|
if (hostWorld !== void 0) {
|
|
675
696
|
internals.worldResolver = hostWorld;
|
|
676
697
|
} else {
|
|
677
|
-
const bag = bagFromDecls(internals.bundle.world.properties);
|
|
698
|
+
const bag = bagFromDecls(internals.bundle.world.properties, "world.");
|
|
678
699
|
internals.worldResolver = {
|
|
679
700
|
get: (n) => bag.get(n),
|
|
680
701
|
set: (n, v) => {
|
|
@@ -714,7 +735,12 @@ var Engine = class {
|
|
|
714
735
|
* state; shared state is untouched. There is no default flow: "main" is
|
|
715
736
|
* a caller convention, not an engine rule. */
|
|
716
737
|
openFlow(id, opts = {}) {
|
|
717
|
-
this.flowsById.get(id)
|
|
738
|
+
const existing = this.flowsById.get(id);
|
|
739
|
+
if (existing) {
|
|
740
|
+
const dealt = existing.heldCardIds().length;
|
|
741
|
+
if (dealt > 0) this.onReplacedFlow?.(id, dealt);
|
|
742
|
+
existing.markClosed();
|
|
743
|
+
}
|
|
718
744
|
const flow = new Flow(this, this.internals, id, opts.seed ?? this.seed);
|
|
719
745
|
this.flowsById.set(id, flow);
|
|
720
746
|
return flow;
|
|
@@ -850,11 +876,16 @@ var Engine = class {
|
|
|
850
876
|
value: value ?? d.default,
|
|
851
877
|
default: d.default,
|
|
852
878
|
...d.values !== void 0 ? { values: d.values } : {},
|
|
853
|
-
...d.stages !== void 0 ? { stages: d.stages } : {}
|
|
879
|
+
...d.stages !== void 0 ? { stages: d.stages } : {},
|
|
880
|
+
// @world is FOREIGN - a host resolver backs it - so writability is whether that
|
|
881
|
+
// resolver can be written at all, which is the shared registry's own rule for a
|
|
882
|
+
// foreign scope. The `as PropertyView` cast this replaced was hiding the field's
|
|
883
|
+
// absence: the row type has always required it, and these rows shipped without one.
|
|
884
|
+
writable: this.internals.worldResolver.set !== void 0
|
|
854
885
|
});
|
|
855
886
|
}
|
|
856
|
-
const add = (
|
|
857
|
-
for (const row of bag.rows()) out.push(
|
|
887
|
+
const add = (_prefix, bag) => {
|
|
888
|
+
for (const row of bag.rows()) out.push(row);
|
|
858
889
|
};
|
|
859
890
|
add("story", this.internals.shared.story);
|
|
860
891
|
for (const [id, bag] of this.internals.shared.box) add(`box.${id}`, bag);
|
|
@@ -1675,6 +1706,7 @@ var Flow = class {
|
|
|
1675
1706
|
case "world": {
|
|
1676
1707
|
const resolver = this.internals.worldResolver;
|
|
1677
1708
|
if (!resolver.set) throw new Error(`@world.${name} cannot be written: the host bound @world read-only`);
|
|
1709
|
+
if (this.internals.worldReadOnly.has(name)) throw new Error(`'@world.${name}' is read-only (writable: false)`);
|
|
1678
1710
|
const prev = resolver.get(name);
|
|
1679
1711
|
resolver.set(name, value);
|
|
1680
1712
|
return { path: `world.${name}`, ...prev !== void 0 ? { prev } : {} };
|
|
@@ -1746,13 +1778,18 @@ var Flow = class {
|
|
|
1746
1778
|
value: value ?? d.default,
|
|
1747
1779
|
default: d.default,
|
|
1748
1780
|
...d.values !== void 0 ? { values: d.values } : {},
|
|
1749
|
-
...d.stages !== void 0 ? { stages: d.stages } : {}
|
|
1781
|
+
...d.stages !== void 0 ? { stages: d.stages } : {},
|
|
1782
|
+
// @world is FOREIGN - a host resolver backs it - so writability is whether that
|
|
1783
|
+
// resolver can be written at all, which is the shared registry's own rule for a
|
|
1784
|
+
// foreign scope. The `as PropertyView` cast this replaced was hiding the field's
|
|
1785
|
+
// absence: the row type has always required it, and these rows shipped without one.
|
|
1786
|
+
writable: this.internals.worldResolver.set !== void 0
|
|
1750
1787
|
});
|
|
1751
1788
|
}
|
|
1752
|
-
const add = (
|
|
1789
|
+
const add = (_prefix, shared, own) => {
|
|
1753
1790
|
for (const bag of [shared, own]) {
|
|
1754
1791
|
if (bag === void 0) continue;
|
|
1755
|
-
for (const row of bag.rows()) out.push(
|
|
1792
|
+
for (const row of bag.rows()) out.push(row);
|
|
1756
1793
|
}
|
|
1757
1794
|
};
|
|
1758
1795
|
add("story", this.internals.shared.story, this.stores.story);
|