@descix/frqtl-node 0.6.0-p1.1 → 0.6.0-p4.1
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/CLAUDE.md +1 -1
- package/README.md +3 -3
- package/dist/dist-manifest.json +27 -25
- package/dist/eyes/index.js +5 -2
- package/dist/frqtl/objects/FrqtlApp.js +28 -1
- package/dist/frqtl/objects/RecipeContext.js +178 -12
- package/dist/frqtl/objects/instruments/hosted-eyes.js +200 -29
- package/dist/frqtl/objects/record/Record.js +326 -0
- package/dist/frqtl/objects/record/open-record.js +22 -0
- package/dist/frqtl/parts/FrqtlVision.js +21 -6
- package/dist/shim/bundle/index.js +112 -96
- package/dist/shim/bundle/indexHtml.js +66 -39
- package/dist/shim/engine/router.js +2 -2
- package/dist/shim/index.js +1 -1
- package/dist/shim/notebook/format.js +1 -1
- package/dist/shim/notebook/store.js +2 -3
- package/dist/shim/project/index.js +16 -3
- package/dist/shim/project/link.js +181 -43
- package/dist/shim/project/manifest.js +151 -0
- package/dist/shim/project/parts-writer.js +9 -5
- package/dist/shim/project/record-format.js +345 -0
- package/dist/shim/project/specifiers.js +1 -1
- package/dist/shim/registry/index.js +1 -1
- package/dist/shim/registry/scene-source.js +44 -30
- package/dist/shim/registry/walkthrough.js +4 -3
- package/dist/shim/storage/codec-chains.js +88 -0
- package/dist/shim/storage/folders.js +205 -0
- package/dist/shim/storage/index.js +64 -8
- package/dist/shim/storage/make-namespace-store.js +5 -5
- package/llms.txt +2 -2
- package/package.json +1 -1
- package/dist/shim/bundle/frqnb.js +0 -112
- package/dist/shim/bundle/manifest.js +0 -95
- package/dist/shim/storage/modules.js +0 -249
- package/dist/shim/storage/projects.js +0 -150
package/CLAUDE.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
A discrete cellular-automata physics engine (compiled Rust → WASM) for node: the same modules as
|
|
4
4
|
`@descix/frqtl-web` (one source, built twice), plus the node engine door `bootNode` and the hosted eyes.
|
|
5
|
-
Pre-release `0.6.0-
|
|
5
|
+
Pre-release `0.6.0-p4.1` (npm dist-tag `next`). Node ≥ 22.12.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
npm install @descix/frqtl-node@next
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ FRQTL for node: a discrete cellular-automata physics engine (compiled Rust → W
|
|
|
4
4
|
local per-pixel rules — a frame moves one pixel per tick, single occupancy, momentum — rather than force
|
|
5
5
|
equations. Interference, blackbody spectra and atom-like binding emerge from the automaton.
|
|
6
6
|
|
|
7
|
-
Pre-release `0.6.0-
|
|
7
|
+
Pre-release `0.6.0-p4.1` (npm dist-tag `next`). Node ≥ 22.12.
|
|
8
8
|
|
|
9
9
|
## Install
|
|
10
10
|
|
|
@@ -31,8 +31,8 @@ const tick = u.doTick(); // TickData: fr
|
|
|
31
31
|
| `.` | the parts (`Wall`, `SphereEmitter`, `Tunnel`, `FrqtlVision`, …), `bootNode`, the engine accessors (`engine`, `engineState`), the capture contracts (`FrqtlCapture`, `RenderStages`, `FieldBuilder`, `CaptureEnvelope`) and `validateRendererProvider` |
|
|
32
32
|
| `./eyes` | `openHostedEyes` — a `composite` still through the REAL renderer, in a managed headless browser (pulls the pinned `playwright`) |
|
|
33
33
|
| `./parts`, `./parts/*` | the parts barrel; one part = one file |
|
|
34
|
-
| `./project` | `FRQTL_WEB_SPECIFIERS`, `libPathOf`, `importMapFor`, `pageImportMapFor`, `linkProject`, `sketchProject`, `SKETCH_ENTRY`, `projectIdentity` |
|
|
35
|
-
| `./registry` | the walk-through rungs, the showcase roster, the experiment registry, `
|
|
34
|
+
| `./project` | `FRQTL_WEB_SPECIFIERS`, `libPathOf`, `importMapFor`, `pageImportMapFor`, `FRQTL_WEB_HOST_SPECIFIERS`, `linkProject`, `sketchProject`, `SKETCH_ENTRY`, `projectIdentity`, `MANIFEST_FILE`, `MANIFEST_KEYS`, `normalizeManifest`, `parseManifest`, `serializeManifest`, `manifestFor`, `RECORD_FILES`, `RECORD_KEYS`, `CHANGE_KEYS`, `OPS`, `BY`, `CLIP_SECONDS`, `CLIP_NAME`, `clipName`, `jsonText`, `recordFolderFaults` |
|
|
35
|
+
| `./registry` | the walk-through rungs, the showcase roster, the experiment registry, `projectOf` |
|
|
36
36
|
| `./kinds` | `registerKind`, `kindNamed`, `kindOf`, `registeredKinds` |
|
|
37
37
|
| `./register` | installs the resolve hook for a sketch's `@descix/frqtl-web/...` imports (`node --import @descix/frqtl-node/register`) |
|
|
38
38
|
| `./shim/controls/registry.js`, `./shim/render/sun-look.js`, `./compat/renderer/display-slot.js`, `./compat/renderer/orbit-bag.js`, `./objects/setup/_collisionMatrixLanes.js`, `./compat/engine.js` | the six non-part modules a scene may import (the rows of `FRQTL_WEB_SPECIFIERS`) |
|
package/dist/dist-manifest.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@descix/frqtl-node",
|
|
3
|
-
"version": "0.6.0-
|
|
3
|
+
"version": "0.6.0-p4.1",
|
|
4
4
|
"files": {
|
|
5
|
-
"eyes/index.js": "
|
|
5
|
+
"eyes/index.js": "b3563421030bb7fdd277eb697959fbe9107463cbb5478160edc7d887daa67be3",
|
|
6
6
|
"fat/pkg-node/egpt_wasm.js": "5e6af1f6725c93c0e9ad7386f1785cbe639ce596a4caa19ca85729c1f2bea04d",
|
|
7
7
|
"fat/pkg-node/egpt_wasm_bg.wasm": "e204498ac7439c294653476c0d214345713e6170819281b27bbbcba217a5a5e9",
|
|
8
8
|
"fat/pkg-node/package.json": "a0c04cd40b60be10e9ddd6e1d4763fd578808321d663c6d4201530e2a4ebdba4",
|
|
@@ -38,15 +38,15 @@
|
|
|
38
38
|
"frqtl/compat/vendor.js": "2393ada71cdbe750d409174e1ba9b098148796efdff746b315d706a0b32e58e8",
|
|
39
39
|
"frqtl/experiments/_shared/boot-failure.js": "1a92e85b06acdefede5613f2fac7cd4e61d2aba590820f1bfa92f6829fcbbdd4",
|
|
40
40
|
"frqtl/node-entry.js": "a401039b4fcf53ac620edbd80985aa4448122f2e3caaeaf4d5595f5e9d512b60",
|
|
41
|
-
"frqtl/objects/FrqtlApp.js": "
|
|
41
|
+
"frqtl/objects/FrqtlApp.js": "0537a6e6b71fc763e92404952263d3bef4dbf273c86d45c5609ee72e69a30a56",
|
|
42
42
|
"frqtl/objects/ObjectFactory.js": "a8f050ce61b7ab9c9b4f81e9eeaebf05c3cc0b532c741ce93d6e952489772b11",
|
|
43
|
-
"frqtl/objects/RecipeContext.js": "
|
|
43
|
+
"frqtl/objects/RecipeContext.js": "b21ca03f799a28848b190834274c061f6dde7fa7f3d17e5eac015550db90d8d7",
|
|
44
44
|
"frqtl/objects/collectors/DataCollector.js": "8736d6cb77eec36ce2adcf2bc3b0d2436eeb70a73b77182ff053efdc6ca071df",
|
|
45
45
|
"frqtl/objects/constants/WallBehaviors.js": "8a9cbdb96eadf84f1d61d215f6921124ec5dbf9e2938c09894a0aa083ddcaea0",
|
|
46
46
|
"frqtl/objects/geometry/SlabFace.js": "847921b124d3bc1692e88c363c087d392a1baa7c652a3a61e381d0f8a8342e57",
|
|
47
47
|
"frqtl/objects/instruments/capture-host.js": "ba5001afa2d8f4e438c5eacb2a5456d903401de8584d170c0b02ff3014794edd",
|
|
48
48
|
"frqtl/objects/instruments/capture.js": "53a746cb51e1c83326eebaa98083861c7ee593f2bcb2317473446a1a02b59b5c",
|
|
49
|
-
"frqtl/objects/instruments/hosted-eyes.js": "
|
|
49
|
+
"frqtl/objects/instruments/hosted-eyes.js": "0d70708546f2e5917deb0a5638a535d7822f2141d69595db406cb0e074225883",
|
|
50
50
|
"frqtl/objects/kinds-entry.js": "a7818357864dc900bd93350635016f938c3dca8dcb665a62df802ba5cd0b3c93",
|
|
51
51
|
"frqtl/objects/kinds.js": "107b166c96c93fd517f173fdbe7006d6f0b2694d5f799f7ec9d4f695313f1832",
|
|
52
52
|
"frqtl/objects/objects/Box.js": "0c08fa4753b78ef56d07aae3393a6268647b550ead58e409cff13eabc8b34b5d",
|
|
@@ -73,6 +73,8 @@
|
|
|
73
73
|
"frqtl/objects/objects/slitLinerScatter.js": "9413cc7efa2132c68d7b4d5030af28d92e8d085e127d5c8e1568d0028da2fc13",
|
|
74
74
|
"frqtl/objects/objects/sustainedSource.js": "0c324cef1583226d090b4d1014c2576ef8237f1bad47c1511bed3c3f81e04206",
|
|
75
75
|
"frqtl/objects/objects/tagger.js": "e2a5ef9ae68466afb6b157ca6d7ce03a6f126d8c91c9f9d4be6dba8e928535eb",
|
|
76
|
+
"frqtl/objects/record/Record.js": "7dce4e1ac5b5ab842fac9f6c9d754322b3696afb7b774e8c2ac018f803a780a6",
|
|
77
|
+
"frqtl/objects/record/open-record.js": "2da2abcccd3ad5bc39eb7fcfb764601cd031dd0afa9b3c9cb96b0669621827df",
|
|
76
78
|
"frqtl/objects/schema/engine-scopes.js": "1777dd3d2443df7c7d7fbcd25974bcb758606bdf3efa5c21408009167d00e3e6",
|
|
77
79
|
"frqtl/objects/schema/index.js": "74ba0b6a6e057cfd40edf2ce41fcce7206c0204e90eeee4a8db3b711f10ffd33",
|
|
78
80
|
"frqtl/objects/schema/scopes.js": "3b9c2d4f20604d6384ec625ab5e4a38085fa9696c5e443ff66b45a8f2330c5f6",
|
|
@@ -110,7 +112,7 @@
|
|
|
110
112
|
"frqtl/parts/DetectorWall.js": "49d9d9526b5e36180122617dd84b16e44624eee76fb2d547868e8cd41eeacbe0",
|
|
111
113
|
"frqtl/parts/FrqtlControlOverlay.js": "f862b1529265224aa96878b56b0c1c6e65683ba3fd6b517df86e17e92147f9c4",
|
|
112
114
|
"frqtl/parts/FrqtlControlsPanel.js": "792d03dea218bdc335ba7e04362be620edbfa331bed9de087d61942299728cc1",
|
|
113
|
-
"frqtl/parts/FrqtlVision.js": "
|
|
115
|
+
"frqtl/parts/FrqtlVision.js": "118d0874249fa55783b196fd01297b3347951267a4add93381433a72c46e8622",
|
|
114
116
|
"frqtl/parts/GraphingDetectorWall.js": "6bff06f951459a3cd327c2eb235d159520933762be0343e1925d153fc2fe6423",
|
|
115
117
|
"frqtl/parts/LargeObject.js": "637ea4c4b5052b916dace520cbb6772f1f8f2e367764ea399dab2a74fff4ed65",
|
|
116
118
|
"frqtl/parts/LightColor.js": "8637e5a09bbad3a4fdd2034ccb44dfc1fda743e29b12b4c685a64b9e1df28daa",
|
|
@@ -155,10 +157,8 @@
|
|
|
155
157
|
"frqtl/scenes/sun.js": "fa06cac429af5a2ad4fe846969a7bf763f2a76d9d9b169328cd1f45bad6bda8f",
|
|
156
158
|
"frqtl/scenes/two-source.js": "1444a0e503f4a5e349d4364e31e698bc67d723a4b2864f262603e75ba5f9f088",
|
|
157
159
|
"frqtl/scenes/wave.js": "cabbece84daceca9199bbea22be610281bdf3137c8c5724bc601758e711f111f",
|
|
158
|
-
"shim/bundle/
|
|
159
|
-
"shim/bundle/
|
|
160
|
-
"shim/bundle/indexHtml.js": "6d3ce242c4f139b542981164fe2b1d8b1c37d9423904bc1299531f594ce4ccc6",
|
|
161
|
-
"shim/bundle/manifest.js": "796e25411d4f1d335277e954cf245352f95f324a1403062caa430142b9e8748c",
|
|
160
|
+
"shim/bundle/index.js": "ea7891e417a929e2b90dc8337750d247a355f84f7f581cf361d4bc8f473d42b5",
|
|
161
|
+
"shim/bundle/indexHtml.js": "2c4fbc502bb33fce93596cee19e143a58bb63c18d0b18ea597f81610e3a9a027",
|
|
162
162
|
"shim/bundle/zip.js": "00f7b5fb5f36ff40a59d86758c503d9d7fb43949c1b5a4f2e7367c43d92786f9",
|
|
163
163
|
"shim/bus.js": "dac2eeccd8774268c51014be4c46c00b9985fdf49ebb44355aa370e949c8c5bc",
|
|
164
164
|
"shim/controls/index.js": "2aaf1f14b104bba8b912d68fe99068a8c544770b9eac43cdf6d992c311ec8f69",
|
|
@@ -166,15 +166,15 @@
|
|
|
166
166
|
"shim/engine/artifact-shell.js": "b4c1d8bf65403caea9357fecd91172a1689baed8aad89433160d595881f16010",
|
|
167
167
|
"shim/engine/boot-phases.js": "c6e12e12824bcf6f1a289f46e41c898a5416c80c131594525145aae9a3eefbfa",
|
|
168
168
|
"shim/engine/engine-stack-boot.js": "0abf57dcff2ca2bb025c787a17875d49d54d9218ac08c78cb9c678dbb6118d08",
|
|
169
|
-
"shim/engine/router.js": "
|
|
169
|
+
"shim/engine/router.js": "a4ec678ab0e38381f761e40e8fbcb34dfea76d96df31a634f3d9f0b57d743570",
|
|
170
170
|
"shim/experiment-frame/index.js": "5a0219aaa225d8f808c405b08623ce85ada37d83fb4f55f983db3303e431e47f",
|
|
171
171
|
"shim/expr/ast-schema.js": "4f1133b887639bbd86fab976292323bf4a955cdc873ff7ca8e8a8eb3b416923f",
|
|
172
172
|
"shim/field-descriptor/index.js": "6647d57d1523519114adc0a5cb66335ec5121c39ab294b9c97bdfb9e5d7f61e0",
|
|
173
173
|
"shim/frame-data/index.js": "df6957b0b4a8e0ee0035bc970647b90089b421ae7f05911cc047d48457164be6",
|
|
174
|
-
"shim/index.js": "
|
|
174
|
+
"shim/index.js": "141c68dbce88643815415645d5f896d55770208866e5b88b07b228d6a7d117e2",
|
|
175
175
|
"shim/notebook/canvas-guard.js": "b19d3a86df3835bd617c7130cde997b6f8a8a0c140f95338b733115d5947ed7b",
|
|
176
176
|
"shim/notebook/catalog.js": "68243a154e12bf36a76598aa554119f6e3b8b5363c8452d157c8a562b9c38dc1",
|
|
177
|
-
"shim/notebook/format.js": "
|
|
177
|
+
"shim/notebook/format.js": "f8b1da9eb37da3a9609f7721426e2242f1279780ea212ea08d9f3c50bb18b578",
|
|
178
178
|
"shim/notebook/frqtl-setups-importmap.js": "df86defa90cb85675564e7bb269451684b5cc7679f2c6b1884c07c8272e8ff1c",
|
|
179
179
|
"shim/notebook/kernel.js": "65cf7e4ba12b24521143997a38cb0e7d0a8aa63f9f46868494eff7a41a887c7b",
|
|
180
180
|
"shim/notebook/knob.js": "f07e9ac9697c7178aa68e4b2f4300145f8e2d2dc41b64aa0afede7e2d68705b1",
|
|
@@ -184,7 +184,7 @@
|
|
|
184
184
|
"shim/notebook/realm-registry.js": "ffee52e7c93447c8b82bfc0784b51346686b4373766da298f50a759d3443ab6a",
|
|
185
185
|
"shim/notebook/realm-transport.js": "5173676a94211f85122e0581a16abba925e9c4b5900b5891911bfaec5ea02daf",
|
|
186
186
|
"shim/notebook/setup-builder.js": "abf8a7fed017776634d5ae3b595de7f00b32779590319cd48d95a6d9d0523a96",
|
|
187
|
-
"shim/notebook/store.js": "
|
|
187
|
+
"shim/notebook/store.js": "fe34d31907e7a8f303dfcc35b9c0439faf2c32fbc5c0bb4f899692c25bef9a4d",
|
|
188
188
|
"shim/notebook/vendor-importmap.js": "0c6578567980225593690e06fb4d32f0b50c47fe87a7467741a03846f6da68ed",
|
|
189
189
|
"shim/notebook/view-builder.js": "1961962be16ef526934c43193828473447f2ec9ac0144f39bc5108c327d9069a",
|
|
190
190
|
"shim/notebook/view-ctx.js": "6287aee366104bece827eecccf675540571d6db2b6833bff837be49eb60ce111",
|
|
@@ -193,19 +193,21 @@
|
|
|
193
193
|
"shim/package.json": "609158e6c5fbc237939fa3ddf7faab80ab690bdc0c8d584414a885130103c4e8",
|
|
194
194
|
"shim/page-params/index.js": "f372a85af163a492425cee2584513fa631a642cb805fa283ad122d445ebec4b3",
|
|
195
195
|
"shim/project/identity.js": "5a0dbd07bfad5c5aa6a529994a604546dbf3e6978b9529ca97ce2c57aa8e563f",
|
|
196
|
-
"shim/project/index.js": "
|
|
197
|
-
"shim/project/link.js": "
|
|
196
|
+
"shim/project/index.js": "81d1a5d84c8bd5f31de8d9849d385509a73582e2ec6db4f779b018fe1b25404f",
|
|
197
|
+
"shim/project/link.js": "1774cde446c3217afb84e19fe44205d620764c863bff89e348a0645aed451ca2",
|
|
198
|
+
"shim/project/manifest.js": "442267af07ae1b977ff6aeaca49d98ce82b77f548cfdd1ed0f258b3429d75f31",
|
|
198
199
|
"shim/project/node-specifier-hook.mjs": "8601edf762bd9cd011632bc681d0589dfc77368cda0e994125d0eb123fea89d0",
|
|
199
200
|
"shim/project/parts-module.js": "b08e0149f086640692e1b2ff8e0d7ae0379c2bc934a0891418de5c2b8c0e8e60",
|
|
200
|
-
"shim/project/parts-writer.js": "
|
|
201
|
+
"shim/project/parts-writer.js": "c9e9be475299ba24a81190d19260119816b9773135491a5024b55c40dd92f859",
|
|
202
|
+
"shim/project/record-format.js": "b680c3752f20535c08be832c6808fae000c2d2325f8caee57f98351043d091be",
|
|
201
203
|
"shim/project/register-node.mjs": "9b408da7dc1b11d16237cd62caca281c823ea80173d386ad35e41ea17c34857f",
|
|
202
|
-
"shim/project/specifiers.js": "
|
|
204
|
+
"shim/project/specifiers.js": "f73a41a7ffbd16063be314973d67e5261607b56b7ef7ee7927d9eaa0d541f3cc",
|
|
203
205
|
"shim/registry/copy-gate.js": "cfbf52669c849b8837b326f2743458f1ead0720cad51a6c6d409c9bd6c7f9495",
|
|
204
206
|
"shim/registry/exhibits.js": "98736b6b0dd82b5c1436da28fe3bf8d2d3ee840af8f5256d00c23e296c3bca9a",
|
|
205
207
|
"shim/registry/experiments.js": "1d1484f144ade35ddcb94b23712df539b3b432a45130e159a6f47146de188165",
|
|
206
|
-
"shim/registry/index.js": "
|
|
207
|
-
"shim/registry/scene-source.js": "
|
|
208
|
-
"shim/registry/walkthrough.js": "
|
|
208
|
+
"shim/registry/index.js": "a3cef8c227d06ccc55735fe2989fbd07b0cf2f323d11b5bed23092fc967e88fc",
|
|
209
|
+
"shim/registry/scene-source.js": "0e873f9afa8175a318db14f0761d9379687024b1d49f69f2a0e3a22285d1029b",
|
|
210
|
+
"shim/registry/walkthrough.js": "65d74822585d271f4d74f0821fc158698bc39d7427b9bca3a61584c3c6d1a4a5",
|
|
209
211
|
"shim/render-state/apply.js": "fd0830ee4bb2668ac5b3254c29180bce9524d2ffb11bf6124e834ab8674a757a",
|
|
210
212
|
"shim/render-state/index.js": "9015405ef2ea3d88bf004a0aa3bea04eb6bdb86270d68ef5622538a9bae5fa6d",
|
|
211
213
|
"shim/render/capture-envelope.js": "2667a355169bb124fd8117e9cbf1d630085257b9f6fa537362f12d0aa649da2d",
|
|
@@ -215,10 +217,10 @@
|
|
|
215
217
|
"shim/rpc/index.js": "56af3afeed22e8d718cd2f7a8ad70db8745f54dbc139af9d71f1d73e2ca37698",
|
|
216
218
|
"shim/runtime/index.js": "cd728294c4693de3059f30f272f267b88b39c19a451edd30c75012e1bab755f5",
|
|
217
219
|
"shim/storage/boot.js": "689504e15dc075e32d08abf61c75a45b1d565c09f086b42400dae40d8186c411",
|
|
218
|
-
"shim/storage/
|
|
220
|
+
"shim/storage/codec-chains.js": "6eab30c3ab7d8bd26059f386f91f9e43a87a6a20980d36bf7271eb72b6d109c0",
|
|
221
|
+
"shim/storage/folders.js": "9d69b6fcbdc8ae6da561acd42946933ac2d453d5d0659fcaf1cfba410a47a45a",
|
|
222
|
+
"shim/storage/index.js": "0939d88bcdb0cde5b564e1fc1b03144363c9747e917e706c4cc1f55fe4ee1ace",
|
|
219
223
|
"shim/storage/local-storage-provider.js": "e14894e5d33bce961e66a2816e4b5c23b8e00534398ca9635d19de117f0f150e",
|
|
220
|
-
"shim/storage/make-namespace-store.js": "
|
|
221
|
-
"shim/storage/modules.js": "ceee32e0ea101ae49e5b0ab63007972a3f4127e9d81bbd2cf24cdb47d491623b",
|
|
222
|
-
"shim/storage/projects.js": "1c7398dedbb7a67c80acbfe0dfb08ba4f069db9a7d946266c4636212834bd671"
|
|
224
|
+
"shim/storage/make-namespace-store.js": "f88cfc65244cd7a3c3a43c173001855bb95571916a117b22f38d051823f2856f"
|
|
223
225
|
}
|
|
224
226
|
}
|
package/dist/eyes/index.js
CHANGED
|
@@ -46,12 +46,15 @@
|
|
|
46
46
|
* eyes.saveStill(still, 'out.png'); // …and the picture, in one line
|
|
47
47
|
* } finally { await eyes.dispose(); }
|
|
48
48
|
*
|
|
49
|
+
* The Record door rides the handle (`eyes.record.*`, `eyes.act.*`); `writeRecordFolder(folder, dir)` is the ONE node
|
|
50
|
+
* writer of the folder `eyes.record.stop()` returns (hosted-eyes.js).
|
|
51
|
+
*
|
|
49
52
|
* `FrqtlVision` is re-exported for the encoder itself (`FrqtlVision.toPNG(still)` → PNG bytes) — the
|
|
50
53
|
* node half of the one-encoder-per-host pair; it is the parts barrel's own instance.
|
|
51
54
|
*/
|
|
52
55
|
|
|
53
56
|
import { createRequire } from 'node:module';
|
|
54
|
-
import { FrqtlHostedEyes as HostedEyes } from '../frqtl/objects/instruments/hosted-eyes.js';
|
|
57
|
+
import { FrqtlHostedEyes as HostedEyes, writeRecordFolder } from '../frqtl/objects/instruments/hosted-eyes.js';
|
|
55
58
|
import { FrqtlVision } from '../frqtl/parts/index.js';
|
|
56
59
|
|
|
57
60
|
// The WRONG-HOST DOOR: `./eyes` DRIVES a browser from node; loaded IN a page it can only fail, so the
|
|
@@ -106,4 +109,4 @@ export function openHostedEyes(opts) {
|
|
|
106
109
|
return HostedEyes.open(bag);
|
|
107
110
|
}
|
|
108
111
|
|
|
109
|
-
export { FrqtlVision };
|
|
112
|
+
export { FrqtlVision, writeRecordFolder };
|
|
@@ -954,6 +954,11 @@ import { paintBootFailure } from '../experiments/_shared/boot-failure.js';
|
|
|
954
954
|
x.inParts = true;
|
|
955
955
|
};
|
|
956
956
|
|
|
957
|
+
/** beginWorld() — a (re-)inited world has not stepped: its last TickData is gone (worldTick reads 0, repaint draws nothing). */
|
|
958
|
+
FrqtlApp.prototype.beginWorld = function () {
|
|
959
|
+
this._lastTickData = null;
|
|
960
|
+
};
|
|
961
|
+
|
|
957
962
|
/** clearDeclared() — empty the registry. Called where the world re-inits (FrqtlApp.setup, and the
|
|
958
963
|
* RecipeContext co-init exp.createCanvas / exp.createScene): a fresh world has no declared objects. */
|
|
959
964
|
FrqtlApp.prototype.clearDeclared = function () {
|
|
@@ -2296,7 +2301,7 @@ import { paintBootFailure } from '../experiments/_shared/boot-failure.js';
|
|
|
2296
2301
|
this.stop();
|
|
2297
2302
|
var self = this;
|
|
2298
2303
|
function resume(result) {
|
|
2299
|
-
self.
|
|
2304
|
+
self.beginWorld();
|
|
2300
2305
|
// Always resume: "restart" means run the scene again from tick 0 — a restart
|
|
2301
2306
|
// that left the loop paused would read as a dead button.
|
|
2302
2307
|
self.start();
|
|
@@ -2572,6 +2577,28 @@ import { paintBootFailure } from '../experiments/_shared/boot-failure.js';
|
|
|
2572
2577
|
return this._tickSuspend;
|
|
2573
2578
|
};
|
|
2574
2579
|
|
|
2580
|
+
/**
|
|
2581
|
+
* runner.worldTick — READ-ONLY: the tick of THIS world: 0 before its first step, else the last delivered tick.
|
|
2582
|
+
* The 0 is a stated fact, not a default: `_lastTickData` is null until the world's first step, and beginWorld()
|
|
2583
|
+
* (the co-init and restart()) is the one writer of that null. It does NOT read `universe.tick`: the compat wrapper
|
|
2584
|
+
* keeps that field across a re-init until the next doTick, so after a restart it still answers the previous
|
|
2585
|
+
* world's tick. Every runner holds a world (its universe is built at construction), whether a sketch built it
|
|
2586
|
+
* through the replay door or a page built it by hand, so this always answers. THROWS when a delivered tick is not
|
|
2587
|
+
* a whole number ≥ 0.
|
|
2588
|
+
*/
|
|
2589
|
+
Object.defineProperty(FrqtlApp.prototype, 'worldTick', {
|
|
2590
|
+
configurable: true,
|
|
2591
|
+
get: function () {
|
|
2592
|
+
if (this._lastTickData === null) { return 0; }
|
|
2593
|
+
var t = this._lastTickData && this._lastTickData.universeData && this._lastTickData.universeData.tick;
|
|
2594
|
+
if (!(typeof t === 'number' && t >= 0 && t % 1 === 0)) {
|
|
2595
|
+
throw new Error('[FrqtlApp.worldTick] the last delivered TickData carries tick ' + String(t) +
|
|
2596
|
+
', not a whole number ≥ 0. (FAIL-LOUD.)');
|
|
2597
|
+
}
|
|
2598
|
+
return t;
|
|
2599
|
+
}
|
|
2600
|
+
});
|
|
2601
|
+
|
|
2575
2602
|
/** @returns {boolean} whether the tick clock is currently held. */
|
|
2576
2603
|
Object.defineProperty(FrqtlApp.prototype, 'ticksSuspended', {
|
|
2577
2604
|
configurable: true,
|
|
@@ -75,6 +75,8 @@ import { kindOf } from './kinds.js';
|
|
|
75
75
|
import { linkProject } from '../../shim/project/link.js';
|
|
76
76
|
import { patchParts, PARTS_EXPORT, entryKeys, entryLiteral } from '../../shim/project/parts-writer.js';
|
|
77
77
|
import { moduleOfKind } from '../../shim/project/parts-module.js';
|
|
78
|
+
import { MANIFEST_FILE } from '../../shim/project/manifest.js';
|
|
79
|
+
import { Record, openRecordOf } from './record/Record.js';
|
|
78
80
|
|
|
79
81
|
/** The world-init contract (objects/setup/_worldInit.js). */
|
|
80
82
|
function _worldInit() {
|
|
@@ -123,6 +125,8 @@ import { moduleOfKind } from '../../shim/project/parts-module.js';
|
|
|
123
125
|
this._parts = new Map(); // declared object → { key, baseline } — the objects in `parts`
|
|
124
126
|
this._code = new Map(); // declared object → baseline — the code declarations at build end
|
|
125
127
|
this._declaredOnce = false;
|
|
128
|
+
this._record = null; // the open Record (exp.startRecord), or null
|
|
129
|
+
this._reauthored = null; // the Record the last re-authoring closed (startRecord checks its close was heard)
|
|
126
130
|
}
|
|
127
131
|
|
|
128
132
|
function _requireWorld(self) {
|
|
@@ -195,6 +199,7 @@ import { moduleOfKind } from '../../shim/project/parts-module.js';
|
|
|
195
199
|
}
|
|
196
200
|
// A (re-)inited world has no declared objects; the recipe re-declares what it builds.
|
|
197
201
|
self._runner.clearDeclared();
|
|
202
|
+
self._runner.beginWorld(); // a (re-)inited world has not stepped
|
|
198
203
|
W.applyPreInit(cfg, u); // pre-init world keys (iframeIntervalSeconds) — the engine reads them at init
|
|
199
204
|
u.init.apply(u, args);
|
|
200
205
|
self._world = Object.freeze({ renderer: renderer, w: w, h: h, d: renderer === 'three' ? d : null,
|
|
@@ -300,7 +305,7 @@ import { moduleOfKind } from '../../shim/project/parts-module.js';
|
|
|
300
305
|
}
|
|
301
306
|
var obj = self.addObject(Kind, Object.assign({ name: key }, _plain(props)));
|
|
302
307
|
self._runner._adoptIntoParts(obj);
|
|
303
|
-
self._parts.set(obj, { key: key, baseline: _capture(self, obj) });
|
|
308
|
+
self._parts.set(obj, { key: key, baseline: _capture(self, obj), kind: self._runner.kindOf(obj) });
|
|
304
309
|
out[key] = obj;
|
|
305
310
|
});
|
|
306
311
|
return Object.freeze(out);
|
|
@@ -366,6 +371,22 @@ import { moduleOfKind } from '../../shim/project/parts-module.js';
|
|
|
366
371
|
return props;
|
|
367
372
|
}
|
|
368
373
|
|
|
374
|
+
/**
|
|
375
|
+
* Spell a touched `center` in the entry's OWN arity: two numbers when the entry
|
|
376
|
+
* spells two (a literal, or an array expression — entryLiteral's `length`) and the live z is 0; otherwise the
|
|
377
|
+
* live [x, y, z] (an entry spelled three, a 3D hand off z 0, an entry whose center is not an array). The
|
|
378
|
+
* read-back (_verifyWritten) guards every case. Mutates and returns `props`.
|
|
379
|
+
*/
|
|
380
|
+
function _spellCenter(text, name, props) {
|
|
381
|
+
var v = props.center;
|
|
382
|
+
if (!Array.isArray(v) || v.length !== 3 || v[2] !== 0) { return props; }
|
|
383
|
+
if (entryKeys(text, name).indexOf('center') === -1) { return props; }
|
|
384
|
+
var r = entryLiteral(text, name, 'center');
|
|
385
|
+
var n = r.literal ? (Array.isArray(r.value) ? r.value.length : null) : r.length;
|
|
386
|
+
if (n === 2) { props.center = [v[0], v[1]]; }
|
|
387
|
+
return props;
|
|
388
|
+
}
|
|
389
|
+
|
|
369
390
|
/**
|
|
370
391
|
* The post-patch check: what the patched text now declares for entry `name`, read back (entryLiteral) for every
|
|
371
392
|
* written key and folded with the baseline for every unwritten one, must equal the live capture — `rect` in its
|
|
@@ -379,6 +400,8 @@ import { moduleOfKind } from '../../shim/project/parts-module.js';
|
|
|
379
400
|
Object.keys(written).forEach(function (k) {
|
|
380
401
|
var r = entryLiteral(text, name, k);
|
|
381
402
|
decl[k] = r.literal ? r.value : undefined;
|
|
403
|
+
// A two-number center declares z 0 (the reading placeDeclaredAt gives an omitted z).
|
|
404
|
+
if (k === 'center' && Array.isArray(decl[k]) && decl[k].length === 2) { decl[k] = decl[k].concat([0]); }
|
|
382
405
|
});
|
|
383
406
|
function refuse(k, declared, liveV) {
|
|
384
407
|
refused.push({ op: 'set', name: name, key: k, reason: 'the written text declares ' + _JSON(declared) + ' but the live object is ' +
|
|
@@ -436,9 +459,10 @@ import { moduleOfKind } from '../../shim/project/parts-module.js';
|
|
|
436
459
|
* changes patchParts' changes (a `literalized` set names the expression it replaced)
|
|
437
460
|
* refused every hand not written, { op, name, key?, reason }
|
|
438
461
|
*/
|
|
439
|
-
RecipeContext.prototype.toSketch = async function () {
|
|
462
|
+
RecipeContext.prototype.toSketch = async function (opts) {
|
|
440
463
|
_requireWorld(this);
|
|
441
464
|
_requireHeld(this, 'toSketch');
|
|
465
|
+
var by = this._record ? Record.requireBy(opts && opts.by, 'RecipeContext.toSketch') : null;
|
|
442
466
|
var self = this;
|
|
443
467
|
var runner = this._runner;
|
|
444
468
|
var declared = runner.declared;
|
|
@@ -447,7 +471,7 @@ import { moduleOfKind } from '../../shim/project/parts-module.js';
|
|
|
447
471
|
var adopted = [];
|
|
448
472
|
var hands = runner._takeHandTouched();
|
|
449
473
|
this._parts.forEach(function (row, obj) {
|
|
450
|
-
if (declared.indexOf(obj) === -1) { edits.push({ op: 'remove', name: row.key }); return; }
|
|
474
|
+
if (declared.indexOf(obj) === -1) { edits.push({ op: 'remove', name: row.key, kind: row.kind, baseline: row.baseline }); return; }
|
|
451
475
|
if (!hands.has(obj)) { return; }
|
|
452
476
|
var kind = runner.kindOf(obj);
|
|
453
477
|
var t = _touched(kind, row.baseline, _capture(self, obj));
|
|
@@ -459,8 +483,10 @@ import { moduleOfKind } from '../../shim/project/parts-module.js';
|
|
|
459
483
|
refused.push({ op: 'set', name: row.key, key: k, reason: 'the live object no longer reports "' + k + '" — there is no value to write.' });
|
|
460
484
|
});
|
|
461
485
|
if (Object.keys(t.props).length) {
|
|
486
|
+
var raw = _plain(t.props); // the capture form, before the entry's spelling (the Record's row values)
|
|
462
487
|
_spell(self._project.files[self._project.entry], row.key, kind, t.props, row.baseline);
|
|
463
|
-
|
|
488
|
+
_spellCenter(self._project.files[self._project.entry], row.key, t.props);
|
|
489
|
+
if (Object.keys(t.props).length) { edits.push({ op: 'set', name: row.key, props: t.props, obj: obj, kind: kind, baseline: row.baseline, raw: raw }); }
|
|
464
490
|
}
|
|
465
491
|
});
|
|
466
492
|
this._code.forEach(function (baseline, obj) {
|
|
@@ -487,7 +513,9 @@ import { moduleOfKind } from '../../shim/project/parts-module.js';
|
|
|
487
513
|
});
|
|
488
514
|
var entry = this._project.entry;
|
|
489
515
|
var r = patchParts(this._project.files[entry], edits.map(function (e) {
|
|
490
|
-
|
|
516
|
+
if (e.op === 'set') { return { op: 'set', name: e.name, props: e.props }; }
|
|
517
|
+
if (e.op === 'remove') { return { op: 'remove', name: e.name }; }
|
|
518
|
+
return { op: 'add', name: e.name, Kind: e.Kind, module: e.module, props: e.props };
|
|
491
519
|
}), { entry: entry });
|
|
492
520
|
// Never decide it succeeded without asking: read the patched text back against each moved object.
|
|
493
521
|
edits.forEach(function (e) {
|
|
@@ -511,11 +539,76 @@ import { moduleOfKind } from '../../shim/project/parts-module.js';
|
|
|
511
539
|
var key = obj.name || runner.kindOf(obj);
|
|
512
540
|
if (refusedAdd[key]) { return; }
|
|
513
541
|
runner._adoptIntoParts(obj);
|
|
514
|
-
self._parts.set(obj, { key: key, baseline: _capture(self, obj) });
|
|
542
|
+
self._parts.set(obj, { key: key, baseline: _capture(self, obj), kind: runner.kindOf(obj) });
|
|
515
543
|
});
|
|
516
|
-
|
|
544
|
+
var allRefused = refused.concat(r.refused);
|
|
545
|
+
if (this._record) { _recordRows(this, edits, allRefused, by); }
|
|
546
|
+
return { files: Object.assign({}, files), changes: r.changes, refused: allRefused };
|
|
517
547
|
};
|
|
518
548
|
|
|
549
|
+
/**
|
|
550
|
+
* The Record's rows for one toSketch, from the writer's own edits as WRITTEN (a refused edit, or a refused key
|
|
551
|
+
* of one, makes no row), in edit order (R3). A `set` whose touched keys include the part's position authority
|
|
552
|
+
* (runner._placementAuthority: `center`, or `rect` with its derivedFrom reads) is a `move` with that ONE key in
|
|
553
|
+
* its capture form; its other touched keys are one `setDeclared` row. `add` → [kind, props as written];
|
|
554
|
+
* `remove` → [kind, the baseline's writable props].
|
|
555
|
+
*/
|
|
556
|
+
function _recordRows(self, edits, refused, by) {
|
|
557
|
+
var runner = self._runner;
|
|
558
|
+
var rec = self._record;
|
|
559
|
+
function refusedKeys(name, op) {
|
|
560
|
+
var keys = {};
|
|
561
|
+
var all = false;
|
|
562
|
+
refused.forEach(function (x) {
|
|
563
|
+
if (x.name !== name || x.op !== op) { return; }
|
|
564
|
+
if (x.key === undefined) { all = true; } else { keys[x.key] = true; }
|
|
565
|
+
});
|
|
566
|
+
return all ? null : keys;
|
|
567
|
+
}
|
|
568
|
+
function writableProps(kind, bag) {
|
|
569
|
+
var w = _writable(kind);
|
|
570
|
+
var out = {};
|
|
571
|
+
Object.keys(bag).forEach(function (k) { if (w[k] && k !== 'name') { out[k] = _plain(bag[k]); } });
|
|
572
|
+
return out;
|
|
573
|
+
}
|
|
574
|
+
edits.forEach(function (e) {
|
|
575
|
+
if (e.op === 'add') {
|
|
576
|
+
if (refusedKeys(e.name, 'add') === null) { return; }
|
|
577
|
+
rec._row({ name: e.name, op: 'add', by: by, from: null, to: [e.Kind, _plain(e.props)] });
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
580
|
+
if (e.op === 'remove') {
|
|
581
|
+
if (refusedKeys(e.name, 'remove') === null) { return; }
|
|
582
|
+
rec._row({ name: e.name, op: 'remove', by: by, from: [e.kind, writableProps(e.kind, e.baseline)], to: null });
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
var bad = refusedKeys(e.name, 'set');
|
|
586
|
+
if (bad === null) { return; }
|
|
587
|
+
var raw = e.raw;
|
|
588
|
+
var auth = (raw.center !== undefined || raw.rect !== undefined) ? runner._placementAuthority(e.obj) : null;
|
|
589
|
+
var authReads = {};
|
|
590
|
+
if (auth) {
|
|
591
|
+
authReads[auth] = true;
|
|
592
|
+
ObjectSchema.derivedReads(e.kind).forEach(function (d) { if (d.field === auth) { authReads[d.name] = true; } });
|
|
593
|
+
}
|
|
594
|
+
var moveRefused = Object.keys(bad).some(function (k) { return authReads[k]; });
|
|
595
|
+
if (auth && raw[auth] !== undefined && !moveRefused) {
|
|
596
|
+
var from = {}, to = {};
|
|
597
|
+
from[auth] = _plain(e.baseline[auth]);
|
|
598
|
+
to[auth] = _plain(raw[auth]);
|
|
599
|
+
rec._row({ name: e.name, op: 'move', by: by, from: from, to: to });
|
|
600
|
+
}
|
|
601
|
+
var pf = {}, pt = {}, any = false;
|
|
602
|
+
Object.keys(raw).forEach(function (k) {
|
|
603
|
+
if (k === auth || bad[k]) { return; }
|
|
604
|
+
pf[k] = e.baseline[k] === undefined ? null : _plain(e.baseline[k]);
|
|
605
|
+
pt[k] = _plain(raw[k]);
|
|
606
|
+
any = true;
|
|
607
|
+
});
|
|
608
|
+
if (any) { rec._row({ name: e.name, op: 'setDeclared', by: by, from: pf, to: pt }); }
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
|
|
519
612
|
/** The names of declared objects a hand marked whose live capture differs from their baseline (not yet written). */
|
|
520
613
|
function _unwrittenHands(self) {
|
|
521
614
|
var runner = self._runner;
|
|
@@ -553,11 +646,14 @@ import { moduleOfKind } from '../../shim/project/parts-module.js';
|
|
|
553
646
|
* setOrbit) are kept; `kept` lists 'cameraPose' only when a pose was captured and re-applied. A `rect` /
|
|
554
647
|
* `center` patch sets where the entry STARTS. The loop's run state is kept. REFUSES (throws) while a hand
|
|
555
648
|
* made since the last toSketch is unwritten (write it first: await exp.toSketch()), and a `name` patch (the
|
|
556
|
-
* key is the name).
|
|
649
|
+
* key is the name). `from` and `to` are the patched keys' capture (ObjectSchema.captureProps) before and after the
|
|
650
|
+
* re-run — one form on both sides (a z-slab wall's rect is 6 numbers even when the patch typed 4); the patch as
|
|
651
|
+
* typed is in `files`. With a Record open, its `setDeclared` row carries the same `from`/`to`, written after the re-run.
|
|
557
652
|
*/
|
|
558
|
-
RecipeContext.prototype.setDeclared = async function (name, patch) {
|
|
653
|
+
RecipeContext.prototype.setDeclared = async function (name, patch, opts) {
|
|
559
654
|
_requireWorld(this);
|
|
560
655
|
_requireHeld(this, 'setDeclared');
|
|
656
|
+
var by = this._record ? Record.requireBy(opts && opts.by, 'RecipeContext.setDeclared') : null;
|
|
561
657
|
var runner = this._runner;
|
|
562
658
|
var obj = null;
|
|
563
659
|
this._parts.forEach(function (row, o) { if (row.key === name) { obj = o; } });
|
|
@@ -615,7 +711,17 @@ import { moduleOfKind } from '../../shim/project/parts-module.js';
|
|
|
615
711
|
runner.cameraControl.setOrbit(pose);
|
|
616
712
|
kept.push('cameraPose');
|
|
617
713
|
}
|
|
618
|
-
|
|
714
|
+
// `to` is what the re-run declared, in the capture form `from` is in (the patch as typed is in the text).
|
|
715
|
+
var rebuilt = null;
|
|
716
|
+
this._parts.forEach(function (row, o) { if (row.key === name) { rebuilt = o; } });
|
|
717
|
+
if (!rebuilt) {
|
|
718
|
+
throw new Error('[RecipeContext.setDeclared] the re-run declared no "' + name + '" — the patched text dropped the entry. (FAIL-LOUD.)');
|
|
719
|
+
}
|
|
720
|
+
var after = _capture(this, rebuilt);
|
|
721
|
+
var to = {};
|
|
722
|
+
Object.keys(patch).forEach(function (k) { to[k] = after[k] === undefined ? null : _plain(after[k]); });
|
|
723
|
+
if (this._record) { this._record._row({ name: name, op: 'setDeclared', by: by, from: _plain(from), to: _plain(to) }); }
|
|
724
|
+
return { set: name, from: from, to: to, tick: 0, kept: kept, files: Object.assign({}, files) };
|
|
619
725
|
};
|
|
620
726
|
|
|
621
727
|
RecipeContext.prototype.addTickFunction = function (fn) {
|
|
@@ -683,8 +789,8 @@ import { moduleOfKind } from '../../shim/project/parts-module.js';
|
|
|
683
789
|
var linked = null;
|
|
684
790
|
if (sketch && typeof sketch === 'object' && typeof sketch.buildExperiment === 'function') {
|
|
685
791
|
if (!sketch.project || typeof sketch.project !== 'object' || !sketch.project.files || typeof sketch.project.entry !== 'string') {
|
|
686
|
-
throw new TypeError('[RecipeContext.build] build(linked): linked is linkProject\'s result
|
|
687
|
-
'
|
|
792
|
+
throw new TypeError('[RecipeContext.build] build(linked): linked is linkProject\'s result (its contract: ' +
|
|
793
|
+
'lib/shim/project/link.js). (FAIL-LOUD.)');
|
|
688
794
|
}
|
|
689
795
|
linked = sketch;
|
|
690
796
|
sketch = linked.buildExperiment;
|
|
@@ -693,6 +799,12 @@ import { moduleOfKind } from '../../shim/project/parts-module.js';
|
|
|
693
799
|
'linkProject\'s result (got ' + typeof sketch + '). (FAIL-LOUD.)');
|
|
694
800
|
}
|
|
695
801
|
if (typeof sketch === 'function') {
|
|
802
|
+
// ONE Record per booted world: a build of text that is not the held text re-authors it, and closes the
|
|
803
|
+
// open Record with the world before (a rebuild of the same text — restart, setDeclared's re-run — does not).
|
|
804
|
+
if (this._record && !(linked && this._project && _sameFiles(linked.project.files, this._project.files))) {
|
|
805
|
+
this._reauthored = this._record;
|
|
806
|
+
this._record._closeOnReauthor(this._project);
|
|
807
|
+
}
|
|
696
808
|
this._buildFn = sketch;
|
|
697
809
|
this._project = linked ? linked.project : null;
|
|
698
810
|
this._urls = linked ? (linked.urls || null) : null;
|
|
@@ -719,6 +831,60 @@ import { moduleOfKind } from '../../shim/project/parts-module.js';
|
|
|
719
831
|
return this;
|
|
720
832
|
};
|
|
721
833
|
|
|
834
|
+
/** Two file maps hold the same paths with byte-equal text. */
|
|
835
|
+
function _sameFiles(a, b) {
|
|
836
|
+
var ka = Object.keys(a), kb = Object.keys(b);
|
|
837
|
+
if (ka.length !== kb.length) { return false; }
|
|
838
|
+
return ka.every(function (k) { return Object.prototype.hasOwnProperty.call(b, k) && a[k] === b[k]; });
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
/**
|
|
842
|
+
* exp.startRecord() → Promise<Record> — open a Record (lib/frqtl/objects/record/Record.js) on this facade's world.
|
|
843
|
+
* REFUSES (rejects): a second open Record (one per facade, one per runner); a held project with no frqtl.json
|
|
844
|
+
* (a Record snapshots a folder); a hand the sketch text does not hold yet (as setDeclared). While it is open,
|
|
845
|
+
* toSketch({ by }) and setDeclared(name, patch, { by }) name who acted.
|
|
846
|
+
*/
|
|
847
|
+
RecipeContext.prototype.startRecord = async function () {
|
|
848
|
+
_requireWorld(this);
|
|
849
|
+
_requireHeld(this, 'startRecord');
|
|
850
|
+
if (this._record) {
|
|
851
|
+
throw new Error('[RecipeContext.startRecord] a Record is already open on this facade (one per booted world) — ' +
|
|
852
|
+
'await rec.stop() first. (FAIL-LOUD.)');
|
|
853
|
+
}
|
|
854
|
+
// A re-authoring closed the previous Record; if that close was REFUSED and nobody read it, its rows would be lost
|
|
855
|
+
// without a word: refuse until the host reads `rec.closed` (the rejection carries err.record).
|
|
856
|
+
var last = this._reauthored;
|
|
857
|
+
if (last) {
|
|
858
|
+
await last._settled;
|
|
859
|
+
if (last._refused && !last._closedRead) {
|
|
860
|
+
var err = new Error('[RecipeContext.startRecord] the previous Record of this facade was closed by a re-authoring and ' +
|
|
861
|
+
'REFUSED (' + last._refused.message + ') — nobody read rec.closed, so its ' + last._refused.record.changes.length +
|
|
862
|
+
' row(s) would be lost: read rec.closed (its rejection carries err.record = { changes, clips }) first. (FAIL-LOUD.)');
|
|
863
|
+
err.record = last._refused.record;
|
|
864
|
+
throw err;
|
|
865
|
+
}
|
|
866
|
+
this._reauthored = null;
|
|
867
|
+
}
|
|
868
|
+
if (openRecordOf(this._runner)) {
|
|
869
|
+
throw new Error('[RecipeContext.startRecord] another facade holds an open Record on this runner. (FAIL-LOUD.)');
|
|
870
|
+
}
|
|
871
|
+
if (!Object.prototype.hasOwnProperty.call(this._project.files, MANIFEST_FILE)) {
|
|
872
|
+
throw new Error('[RecipeContext.startRecord] a Record snapshots a folder; boot it as one — the held project carries ' +
|
|
873
|
+
'no ' + MANIFEST_FILE + ': add files[\'' + MANIFEST_FILE + '\'] = serializeManifest(manifestFor({ name, entry: SKETCH_ENTRY })) ' +
|
|
874
|
+
'(all from ./project) to the files you boot. (FAIL-LOUD.)');
|
|
875
|
+
}
|
|
876
|
+
var unwritten = _unwrittenHands(this);
|
|
877
|
+
if (unwritten.length) {
|
|
878
|
+
throw new Error('[RecipeContext.startRecord] "' + unwritten.join('", "') + '" carries a hand the sketch text does ' +
|
|
879
|
+
'not hold yet — write the hand first: await exp.toSketch(). (FAIL-LOUD.)');
|
|
880
|
+
}
|
|
881
|
+
var rec = new Record(this);
|
|
882
|
+
this._record = rec;
|
|
883
|
+
try { await rec._ready(this._project); }
|
|
884
|
+
catch (e) { rec._detach(); throw e; }
|
|
885
|
+
return rec;
|
|
886
|
+
};
|
|
887
|
+
|
|
722
888
|
RecipeContext.prototype.run = function (buildFn) {
|
|
723
889
|
if (buildFn && typeof buildFn === 'function' && !this._built) { this.build(buildFn); }
|
|
724
890
|
_requireWorld(this);
|