worldorbit 2.6.0 → 3.0.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/README.md +12 -5
- package/dist/browser/core/dist/atlas-edit.d.ts +11 -0
- package/dist/browser/core/dist/atlas-edit.js +347 -0
- package/dist/browser/core/dist/atlas-utils.d.ts +22 -0
- package/dist/browser/core/dist/atlas-utils.js +189 -0
- package/dist/browser/core/dist/atlas-validate.d.ts +2 -0
- package/dist/browser/core/dist/atlas-validate.js +488 -0
- package/dist/browser/core/dist/diagnostics.d.ts +10 -0
- package/dist/browser/core/dist/diagnostics.js +109 -0
- package/dist/browser/core/dist/draft-parse.d.ts +3 -0
- package/dist/browser/core/dist/draft-parse.js +1654 -0
- package/dist/browser/core/dist/draft.d.ts +21 -0
- package/dist/browser/core/dist/draft.js +482 -0
- package/dist/browser/core/dist/errors.d.ts +7 -0
- package/dist/browser/core/dist/errors.js +16 -0
- package/dist/browser/core/dist/format.d.ts +4 -0
- package/dist/browser/core/dist/format.js +613 -0
- package/dist/browser/core/dist/index.d.ts +29 -0
- package/dist/browser/core/dist/index.js +35 -6542
- package/dist/browser/core/dist/load.d.ts +4 -0
- package/dist/browser/core/dist/load.js +182 -0
- package/dist/browser/core/dist/markdown.d.ts +2 -0
- package/dist/browser/core/dist/markdown.js +37 -0
- package/dist/browser/core/dist/normalize.d.ts +2 -0
- package/dist/browser/core/dist/normalize.js +312 -0
- package/dist/browser/core/dist/parse.d.ts +2 -0
- package/dist/browser/core/dist/parse.js +133 -0
- package/dist/browser/core/dist/scene.d.ts +3 -0
- package/dist/browser/core/dist/scene.js +1901 -0
- package/dist/browser/core/dist/schema.d.ts +8 -0
- package/dist/browser/core/dist/schema.js +298 -0
- package/dist/browser/core/dist/spatial-scene.d.ts +3 -0
- package/dist/browser/core/dist/spatial-scene.js +420 -0
- package/dist/browser/core/dist/tokenize.d.ts +4 -0
- package/dist/browser/core/dist/tokenize.js +68 -0
- package/dist/browser/core/dist/types.d.ts +637 -0
- package/dist/browser/core/dist/types.js +1 -0
- package/dist/browser/core/dist/validate.d.ts +2 -0
- package/dist/browser/core/dist/validate.js +56 -0
- package/dist/browser/editor/dist/editor.d.ts +2 -0
- package/dist/browser/editor/dist/editor.js +3700 -0
- package/dist/browser/editor/dist/index.d.ts +2 -0
- package/dist/browser/editor/dist/index.js +1 -12250
- package/dist/browser/editor/dist/types.d.ts +59 -0
- package/dist/browser/editor/dist/types.js +1 -0
- package/dist/browser/markdown/dist/html.d.ts +3 -0
- package/dist/browser/markdown/dist/html.js +64 -0
- package/dist/browser/markdown/dist/index.d.ts +4 -0
- package/dist/browser/markdown/dist/index.js +3 -6179
- package/dist/browser/markdown/dist/rehype.d.ts +10 -0
- package/dist/browser/markdown/dist/rehype.js +49 -0
- package/dist/browser/markdown/dist/remark.d.ts +9 -0
- package/dist/browser/markdown/dist/remark.js +28 -0
- package/dist/browser/markdown/dist/types.d.ts +11 -0
- package/dist/browser/markdown/dist/types.js +1 -0
- package/dist/browser/viewer/dist/atlas-state.d.ts +12 -0
- package/dist/browser/viewer/dist/atlas-state.js +269 -0
- package/dist/browser/viewer/dist/atlas-viewer.d.ts +2 -0
- package/dist/browser/viewer/dist/atlas-viewer.js +495 -0
- package/dist/browser/viewer/dist/custom-element.d.ts +1 -0
- package/dist/browser/viewer/dist/custom-element.js +78 -0
- package/dist/browser/viewer/dist/embed.d.ts +24 -0
- package/dist/browser/viewer/dist/embed.js +172 -0
- package/dist/browser/viewer/dist/errors.d.ts +6 -0
- package/dist/browser/viewer/dist/errors.js +12 -0
- package/dist/browser/viewer/dist/index.d.ts +10 -0
- package/dist/browser/viewer/dist/index.js +9 -8334
- package/dist/browser/viewer/dist/minimap.d.ts +3 -0
- package/dist/browser/viewer/dist/minimap.js +63 -0
- package/dist/browser/viewer/dist/render.d.ts +6 -0
- package/dist/browser/viewer/dist/render.js +670 -0
- package/dist/browser/viewer/dist/runtime-3d.d.ts +19 -0
- package/dist/browser/viewer/dist/runtime-3d.js +494 -0
- package/dist/browser/viewer/dist/theme.d.ts +4 -0
- package/dist/browser/viewer/dist/theme.js +103 -0
- package/dist/browser/viewer/dist/tooltip.d.ts +3 -0
- package/dist/browser/viewer/dist/tooltip.js +198 -0
- package/dist/browser/viewer/dist/types.d.ts +292 -0
- package/dist/browser/viewer/dist/types.js +1 -0
- package/dist/browser/viewer/dist/vendor/three.module.js +53032 -0
- package/dist/browser/viewer/dist/viewer-state.d.ts +19 -0
- package/dist/browser/viewer/dist/viewer-state.js +162 -0
- package/dist/browser/viewer/dist/viewer.d.ts +2 -0
- package/dist/browser/viewer/dist/viewer.js +1662 -0
- package/dist/unpkg/core/dist/atlas-edit.d.ts +11 -0
- package/dist/unpkg/core/dist/atlas-edit.js +347 -0
- package/dist/unpkg/core/dist/atlas-utils.d.ts +22 -0
- package/dist/unpkg/core/dist/atlas-utils.js +189 -0
- package/dist/unpkg/core/dist/atlas-validate.d.ts +2 -0
- package/dist/unpkg/core/dist/atlas-validate.js +488 -0
- package/dist/unpkg/core/dist/diagnostics.d.ts +10 -0
- package/dist/unpkg/core/dist/diagnostics.js +109 -0
- package/dist/unpkg/core/dist/draft-parse.d.ts +3 -0
- package/dist/unpkg/core/dist/draft-parse.js +1654 -0
- package/dist/unpkg/core/dist/draft.d.ts +21 -0
- package/dist/unpkg/core/dist/draft.js +482 -0
- package/dist/unpkg/core/dist/errors.d.ts +7 -0
- package/dist/unpkg/core/dist/errors.js +16 -0
- package/dist/unpkg/core/dist/format.d.ts +4 -0
- package/dist/unpkg/core/dist/format.js +613 -0
- package/dist/unpkg/core/dist/index.d.ts +29 -0
- package/dist/unpkg/core/dist/index.js +35 -6614
- package/dist/unpkg/core/dist/load.d.ts +4 -0
- package/dist/unpkg/core/dist/load.js +182 -0
- package/dist/unpkg/core/dist/markdown.d.ts +2 -0
- package/dist/unpkg/core/dist/markdown.js +37 -0
- package/dist/unpkg/core/dist/normalize.d.ts +2 -0
- package/dist/unpkg/core/dist/normalize.js +312 -0
- package/dist/unpkg/core/dist/parse.d.ts +2 -0
- package/dist/unpkg/core/dist/parse.js +133 -0
- package/dist/unpkg/core/dist/scene.d.ts +3 -0
- package/dist/unpkg/core/dist/scene.js +1901 -0
- package/dist/unpkg/core/dist/schema.d.ts +8 -0
- package/dist/unpkg/core/dist/schema.js +298 -0
- package/dist/unpkg/core/dist/spatial-scene.d.ts +3 -0
- package/dist/unpkg/core/dist/spatial-scene.js +420 -0
- package/dist/unpkg/core/dist/tokenize.d.ts +4 -0
- package/dist/unpkg/core/dist/tokenize.js +68 -0
- package/dist/unpkg/core/dist/types.d.ts +637 -0
- package/dist/unpkg/core/dist/types.js +1 -0
- package/dist/unpkg/core/dist/validate.d.ts +2 -0
- package/dist/unpkg/core/dist/validate.js +56 -0
- package/dist/unpkg/editor/dist/editor.d.ts +2 -0
- package/dist/unpkg/editor/dist/editor.js +3700 -0
- package/dist/unpkg/editor/dist/index.d.ts +2 -0
- package/dist/unpkg/editor/dist/index.js +1 -12275
- package/dist/unpkg/editor/dist/types.d.ts +59 -0
- package/dist/unpkg/editor/dist/types.js +1 -0
- package/dist/unpkg/markdown/dist/html.d.ts +3 -0
- package/dist/unpkg/markdown/dist/html.js +64 -0
- package/dist/unpkg/markdown/dist/index.d.ts +4 -0
- package/dist/unpkg/markdown/dist/index.js +3 -6207
- package/dist/unpkg/markdown/dist/rehype.d.ts +10 -0
- package/dist/unpkg/markdown/dist/rehype.js +49 -0
- package/dist/unpkg/markdown/dist/remark.d.ts +9 -0
- package/dist/unpkg/markdown/dist/remark.js +28 -0
- package/dist/unpkg/markdown/dist/types.d.ts +11 -0
- package/dist/unpkg/markdown/dist/types.js +1 -0
- package/dist/unpkg/viewer/dist/atlas-state.d.ts +12 -0
- package/dist/unpkg/viewer/dist/atlas-state.js +269 -0
- package/dist/unpkg/viewer/dist/atlas-viewer.d.ts +2 -0
- package/dist/unpkg/viewer/dist/atlas-viewer.js +495 -0
- package/dist/unpkg/viewer/dist/custom-element.d.ts +1 -0
- package/dist/unpkg/viewer/dist/custom-element.js +78 -0
- package/dist/unpkg/viewer/dist/embed.d.ts +24 -0
- package/dist/unpkg/viewer/dist/embed.js +172 -0
- package/dist/unpkg/viewer/dist/errors.d.ts +6 -0
- package/dist/unpkg/viewer/dist/errors.js +12 -0
- package/dist/unpkg/viewer/dist/index.d.ts +10 -0
- package/dist/unpkg/viewer/dist/index.js +9 -8391
- package/dist/unpkg/viewer/dist/minimap.d.ts +3 -0
- package/dist/unpkg/viewer/dist/minimap.js +63 -0
- package/dist/unpkg/viewer/dist/render.d.ts +6 -0
- package/dist/unpkg/viewer/dist/render.js +670 -0
- package/dist/unpkg/viewer/dist/runtime-3d.d.ts +19 -0
- package/dist/unpkg/viewer/dist/runtime-3d.js +494 -0
- package/dist/unpkg/viewer/dist/theme.d.ts +4 -0
- package/dist/unpkg/viewer/dist/theme.js +103 -0
- package/dist/unpkg/viewer/dist/tooltip.d.ts +3 -0
- package/dist/unpkg/viewer/dist/tooltip.js +198 -0
- package/dist/unpkg/viewer/dist/types.d.ts +292 -0
- package/dist/unpkg/viewer/dist/types.js +1 -0
- package/dist/unpkg/viewer/dist/vendor/three.module.js +53032 -0
- package/dist/unpkg/viewer/dist/viewer-state.d.ts +19 -0
- package/dist/unpkg/viewer/dist/viewer-state.js +162 -0
- package/dist/unpkg/viewer/dist/viewer.d.ts +2 -0
- package/dist/unpkg/viewer/dist/viewer.js +1662 -0
- package/dist/unpkg/worldorbit-core.min.js +1 -12
- package/dist/unpkg/worldorbit-editor.min.js +1 -904
- package/dist/unpkg/worldorbit-markdown.min.js +1 -103
- package/dist/unpkg/worldorbit-viewer.min.js +1 -259
- package/dist/unpkg/worldorbit.js +2 -9704
- package/dist/unpkg/worldorbit.min.js +2 -263
- package/package.json +1 -1
- package/packages/core/dist/index.d.ts +1 -0
- package/packages/core/dist/index.js +1 -0
- package/packages/core/dist/spatial-scene.d.ts +3 -0
- package/packages/core/dist/spatial-scene.js +420 -0
- package/packages/core/dist/types.d.ts +105 -0
- package/packages/editor/dist/editor.js +25 -4
- package/packages/editor/dist/types.d.ts +4 -0
- package/packages/markdown/dist/html.js +10 -3
- package/packages/viewer/dist/atlas-state.js +3 -0
- package/packages/viewer/dist/atlas-viewer.js +1 -0
- package/packages/viewer/dist/custom-element.js +18 -4
- package/packages/viewer/dist/embed.d.ts +5 -1
- package/packages/viewer/dist/embed.js +58 -24
- package/packages/viewer/dist/errors.d.ts +6 -0
- package/packages/viewer/dist/errors.js +12 -0
- package/packages/viewer/dist/index.d.ts +1 -0
- package/packages/viewer/dist/index.js +1 -0
- package/packages/viewer/dist/runtime-3d.d.ts +19 -0
- package/packages/viewer/dist/runtime-3d.js +494 -0
- package/packages/viewer/dist/types.d.ts +21 -2
- package/packages/viewer/dist/vendor/three.module.js +53032 -0
- package/packages/viewer/dist/viewer.js +501 -41
package/README.md
CHANGED
|
@@ -118,7 +118,7 @@ For direct browser usage, use the browser bundle:
|
|
|
118
118
|
<html>
|
|
119
119
|
<head>
|
|
120
120
|
<meta charset="utf-8" />
|
|
121
|
-
<script src="https://unpkg.com/worldorbit@
|
|
121
|
+
<script src="https://unpkg.com/worldorbit@3.0.0/dist/unpkg/worldorbit.min.js"></script>
|
|
122
122
|
<style>
|
|
123
123
|
html, body {
|
|
124
124
|
margin: 0;
|
|
@@ -351,6 +351,7 @@ createInteractiveViewer(document.getElementById("preview"), {
|
|
|
351
351
|
document: loaded.document,
|
|
352
352
|
projection: "isometric",
|
|
353
353
|
theme: "atlas",
|
|
354
|
+
viewMode: "3d",
|
|
354
355
|
});
|
|
355
356
|
```
|
|
356
357
|
|
|
@@ -427,9 +428,12 @@ const scene = renderDocumentToScene(loaded.document, {
|
|
|
427
428
|
|
|
428
429
|
## Viewer Capabilities
|
|
429
430
|
|
|
430
|
-
Viewer features in `
|
|
431
|
+
Viewer features in `v3.0.0` include:
|
|
431
432
|
|
|
432
433
|
* scene-based SVG rendering
|
|
434
|
+
* renderer-neutral spatial scenes through `renderDocumentToSpatialScene(...)`
|
|
435
|
+
* a full 3D viewer mode on the same documents and placements as 2D
|
|
436
|
+
* deterministic orbit animation with play, pause, reset, and speed controls
|
|
433
437
|
* projections: `topdown`, `isometric`, `orthographic`, and `perspective`
|
|
434
438
|
* theme presets: `atlas`, `nightglass`, `ember`
|
|
435
439
|
* layer controls for background, guides, orbits, events, objects, labels, metadata, and relations
|
|
@@ -442,7 +446,7 @@ Viewer features in `v2.6` include:
|
|
|
442
446
|
|
|
443
447
|
## Markdown Integration
|
|
444
448
|
|
|
445
|
-
Use `worldorbit/markdown` to transform fenced `worldorbit` blocks into static or interactive output.
|
|
449
|
+
Use `worldorbit/markdown` to transform fenced `worldorbit` blocks into static output, interactive 2D output, or interactive 3D output.
|
|
446
450
|
|
|
447
451
|
```ts
|
|
448
452
|
import rehypeStringify from "rehype-stringify";
|
|
@@ -455,7 +459,7 @@ import { remarkWorldOrbit } from "worldorbit/markdown";
|
|
|
455
459
|
const html = String(
|
|
456
460
|
await unified()
|
|
457
461
|
.use(remarkParse)
|
|
458
|
-
.use(remarkWorldOrbit, { mode: "interactive" })
|
|
462
|
+
.use(remarkWorldOrbit, { mode: "interactive-3d" })
|
|
459
463
|
.use(remarkRehype, { allowDangerousHtml: true })
|
|
460
464
|
.use(rehypeStringify, { allowDangerousHtml: true })
|
|
461
465
|
.process(markdownSource),
|
|
@@ -468,7 +472,7 @@ In the browser:
|
|
|
468
472
|
import { mountWorldOrbitEmbeds } from "worldorbit/viewer";
|
|
469
473
|
|
|
470
474
|
mountWorldOrbitEmbeds(document, {
|
|
471
|
-
mode: "interactive",
|
|
475
|
+
mode: "interactive-3d",
|
|
472
476
|
});
|
|
473
477
|
```
|
|
474
478
|
|
|
@@ -477,6 +481,8 @@ mountWorldOrbitEmbeds(document, {
|
|
|
477
481
|
Examples live in:
|
|
478
482
|
|
|
479
483
|
* [examples/minimal.worldorbit](./examples/minimal.worldorbit)
|
|
484
|
+
* [examples/minimal-3d.worldorbit](./examples/minimal-3d.worldorbit)
|
|
485
|
+
* [examples/showcase-3d.worldorbit](./examples/showcase-3d.worldorbit)
|
|
480
486
|
* [examples/schema25-camera.worldorbit](./examples/schema25-camera.worldorbit)
|
|
481
487
|
* [examples/schema25-event-snapshot.worldorbit](./examples/schema25-event-snapshot.worldorbit)
|
|
482
488
|
* [examples/studio.schema25.worldorbit](./examples/studio.schema25.worldorbit)
|
|
@@ -496,6 +502,7 @@ Browser-facing examples and demos live in the repository under `demo/`, `studio/
|
|
|
496
502
|
* [migration guide: v1 to v2](./docs/migration-v1-to-v2.md)
|
|
497
503
|
* [migration guide: v2.0 to v2.1](./docs/migration-v2-to-v2.1.md)
|
|
498
504
|
* [migration guide: v2.1 to v2.5](./docs/migration-v2.1-to-v2.5.md)
|
|
505
|
+
* [migration guide: v2.6 to v3.0](./docs/migration-v2.6-to-v3.0.md)
|
|
499
506
|
* [language reference](./docs/language-reference.md)
|
|
500
507
|
* [language reference (DE)](./docs/language-reference.de.md)
|
|
501
508
|
* [API inventory](./docs/api-inventory.md)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { AtlasDocumentPath, AtlasResolvedDiagnostic, WorldOrbitAtlasDocument, WorldOrbitAtlasDocumentVersion, WorldOrbitDiagnostic } from "./types.js";
|
|
2
|
+
export declare function createEmptyAtlasDocument(systemId?: string, version?: WorldOrbitAtlasDocumentVersion): WorldOrbitAtlasDocument;
|
|
3
|
+
export declare function cloneAtlasDocument(document: WorldOrbitAtlasDocument): WorldOrbitAtlasDocument;
|
|
4
|
+
export declare function listAtlasDocumentPaths(document: WorldOrbitAtlasDocument): AtlasDocumentPath[];
|
|
5
|
+
export declare function getAtlasDocumentNode(document: WorldOrbitAtlasDocument, path: AtlasDocumentPath): unknown;
|
|
6
|
+
export declare function upsertAtlasDocumentNode(document: WorldOrbitAtlasDocument, path: AtlasDocumentPath, value: unknown): WorldOrbitAtlasDocument;
|
|
7
|
+
export declare function updateAtlasDocumentNode(document: WorldOrbitAtlasDocument, path: AtlasDocumentPath, updater: (value: unknown) => unknown): WorldOrbitAtlasDocument;
|
|
8
|
+
export declare function removeAtlasDocumentNode(document: WorldOrbitAtlasDocument, path: AtlasDocumentPath): WorldOrbitAtlasDocument;
|
|
9
|
+
export declare function resolveAtlasDiagnostics(document: WorldOrbitAtlasDocument, diagnostics: WorldOrbitDiagnostic[]): AtlasResolvedDiagnostic[];
|
|
10
|
+
export declare function resolveAtlasDiagnosticPath(document: WorldOrbitAtlasDocument, diagnostic: WorldOrbitDiagnostic): AtlasDocumentPath | null;
|
|
11
|
+
export declare function validateAtlasDocumentWithDiagnostics(document: WorldOrbitAtlasDocument): AtlasResolvedDiagnostic[];
|
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
import { collectAtlasDiagnostics } from "./atlas-validate.js";
|
|
2
|
+
export function createEmptyAtlasDocument(systemId = "WorldOrbit", version = "2.5") {
|
|
3
|
+
return {
|
|
4
|
+
format: "worldorbit",
|
|
5
|
+
version,
|
|
6
|
+
schemaVersion: version,
|
|
7
|
+
sourceVersion: "1.0",
|
|
8
|
+
system: {
|
|
9
|
+
type: "system",
|
|
10
|
+
id: systemId,
|
|
11
|
+
title: systemId,
|
|
12
|
+
description: null,
|
|
13
|
+
epoch: null,
|
|
14
|
+
referencePlane: null,
|
|
15
|
+
defaults: {
|
|
16
|
+
view: "topdown",
|
|
17
|
+
scale: null,
|
|
18
|
+
units: null,
|
|
19
|
+
preset: null,
|
|
20
|
+
theme: null,
|
|
21
|
+
},
|
|
22
|
+
atlasMetadata: {},
|
|
23
|
+
viewpoints: [],
|
|
24
|
+
annotations: [],
|
|
25
|
+
},
|
|
26
|
+
groups: [],
|
|
27
|
+
relations: [],
|
|
28
|
+
events: [],
|
|
29
|
+
objects: [],
|
|
30
|
+
diagnostics: [],
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export function cloneAtlasDocument(document) {
|
|
34
|
+
return structuredClone(document);
|
|
35
|
+
}
|
|
36
|
+
export function listAtlasDocumentPaths(document) {
|
|
37
|
+
const paths = [{ kind: "system" }, { kind: "defaults" }];
|
|
38
|
+
if (document.system) {
|
|
39
|
+
for (const key of Object.keys(document.system.atlasMetadata).sort()) {
|
|
40
|
+
paths.push({ kind: "metadata", key });
|
|
41
|
+
}
|
|
42
|
+
for (const viewpoint of [...document.system.viewpoints].sort(compareIdLike)) {
|
|
43
|
+
paths.push({ kind: "viewpoint", id: viewpoint.id });
|
|
44
|
+
}
|
|
45
|
+
for (const annotation of [...document.system.annotations].sort(compareIdLike)) {
|
|
46
|
+
paths.push({ kind: "annotation", id: annotation.id });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
for (const group of [...document.groups].sort(compareIdLike)) {
|
|
50
|
+
paths.push({ kind: "group", id: group.id });
|
|
51
|
+
}
|
|
52
|
+
for (const relation of [...document.relations].sort(compareIdLike)) {
|
|
53
|
+
paths.push({ kind: "relation", id: relation.id });
|
|
54
|
+
}
|
|
55
|
+
for (const event of [...document.events].sort(compareIdLike)) {
|
|
56
|
+
paths.push({ kind: "event", id: event.id });
|
|
57
|
+
for (const pose of [...event.positions].sort(comparePoseObjectId)) {
|
|
58
|
+
paths.push({ kind: "event-pose", id: event.id, key: pose.objectId });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
for (const object of [...document.objects].sort(compareIdLike)) {
|
|
62
|
+
paths.push({ kind: "object", id: object.id });
|
|
63
|
+
}
|
|
64
|
+
return paths;
|
|
65
|
+
}
|
|
66
|
+
export function getAtlasDocumentNode(document, path) {
|
|
67
|
+
switch (path.kind) {
|
|
68
|
+
case "system":
|
|
69
|
+
return document.system;
|
|
70
|
+
case "defaults":
|
|
71
|
+
return document.system?.defaults ?? null;
|
|
72
|
+
case "metadata":
|
|
73
|
+
return path.key ? (document.system?.atlasMetadata[path.key] ?? null) : null;
|
|
74
|
+
case "group":
|
|
75
|
+
return path.id ? findGroup(document, path.id) : null;
|
|
76
|
+
case "event":
|
|
77
|
+
return path.id ? findEvent(document, path.id) : null;
|
|
78
|
+
case "event-pose":
|
|
79
|
+
return path.id && path.key ? findEventPose(document, path.id, path.key) : null;
|
|
80
|
+
case "object":
|
|
81
|
+
return path.id ? findObject(document, path.id) : null;
|
|
82
|
+
case "viewpoint":
|
|
83
|
+
return path.id ? findViewpoint(document.system, path.id) : null;
|
|
84
|
+
case "annotation":
|
|
85
|
+
return path.id ? findAnnotation(document.system, path.id) : null;
|
|
86
|
+
case "relation":
|
|
87
|
+
return path.id ? findRelation(document, path.id) : null;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
export function upsertAtlasDocumentNode(document, path, value) {
|
|
91
|
+
const next = cloneAtlasDocument(document);
|
|
92
|
+
const system = ensureSystem(next);
|
|
93
|
+
switch (path.kind) {
|
|
94
|
+
case "system":
|
|
95
|
+
next.system = value;
|
|
96
|
+
return next;
|
|
97
|
+
case "defaults":
|
|
98
|
+
system.defaults = {
|
|
99
|
+
...system.defaults,
|
|
100
|
+
...value,
|
|
101
|
+
};
|
|
102
|
+
return next;
|
|
103
|
+
case "metadata":
|
|
104
|
+
if (!path.key) {
|
|
105
|
+
throw new Error('Metadata updates require a "key" value.');
|
|
106
|
+
}
|
|
107
|
+
if (value === null || value === undefined || value === "") {
|
|
108
|
+
delete system.atlasMetadata[path.key];
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
system.atlasMetadata[path.key] = String(value);
|
|
112
|
+
}
|
|
113
|
+
return next;
|
|
114
|
+
case "group":
|
|
115
|
+
if (!path.id) {
|
|
116
|
+
throw new Error('Group updates require an "id" value.');
|
|
117
|
+
}
|
|
118
|
+
upsertById(next.groups, value);
|
|
119
|
+
return next;
|
|
120
|
+
case "event":
|
|
121
|
+
if (!path.id) {
|
|
122
|
+
throw new Error('Event updates require an "id" value.');
|
|
123
|
+
}
|
|
124
|
+
upsertById(next.events, value);
|
|
125
|
+
return next;
|
|
126
|
+
case "event-pose":
|
|
127
|
+
if (!path.id || !path.key) {
|
|
128
|
+
throw new Error('Event pose updates require an event "id" and pose "key" value.');
|
|
129
|
+
}
|
|
130
|
+
upsertEventPose(next.events, path.id, value);
|
|
131
|
+
return next;
|
|
132
|
+
case "object":
|
|
133
|
+
if (!path.id) {
|
|
134
|
+
throw new Error('Object updates require an "id" value.');
|
|
135
|
+
}
|
|
136
|
+
upsertById(next.objects, value);
|
|
137
|
+
return next;
|
|
138
|
+
case "viewpoint":
|
|
139
|
+
if (!path.id) {
|
|
140
|
+
throw new Error('Viewpoint updates require an "id" value.');
|
|
141
|
+
}
|
|
142
|
+
upsertById(system.viewpoints, value);
|
|
143
|
+
return next;
|
|
144
|
+
case "annotation":
|
|
145
|
+
if (!path.id) {
|
|
146
|
+
throw new Error('Annotation updates require an "id" value.');
|
|
147
|
+
}
|
|
148
|
+
upsertById(system.annotations, value);
|
|
149
|
+
return next;
|
|
150
|
+
case "relation":
|
|
151
|
+
if (!path.id) {
|
|
152
|
+
throw new Error('Relation updates require an "id" value.');
|
|
153
|
+
}
|
|
154
|
+
upsertById(next.relations, value);
|
|
155
|
+
return next;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
export function updateAtlasDocumentNode(document, path, updater) {
|
|
159
|
+
return upsertAtlasDocumentNode(document, path, updater(getAtlasDocumentNode(document, path)));
|
|
160
|
+
}
|
|
161
|
+
export function removeAtlasDocumentNode(document, path) {
|
|
162
|
+
const next = cloneAtlasDocument(document);
|
|
163
|
+
const system = ensureSystem(next);
|
|
164
|
+
switch (path.kind) {
|
|
165
|
+
case "metadata":
|
|
166
|
+
if (path.key) {
|
|
167
|
+
delete system.atlasMetadata[path.key];
|
|
168
|
+
}
|
|
169
|
+
return next;
|
|
170
|
+
case "object":
|
|
171
|
+
if (path.id) {
|
|
172
|
+
next.objects = next.objects.filter((object) => object.id !== path.id);
|
|
173
|
+
}
|
|
174
|
+
return next;
|
|
175
|
+
case "group":
|
|
176
|
+
if (path.id) {
|
|
177
|
+
next.groups = next.groups.filter((group) => group.id !== path.id);
|
|
178
|
+
}
|
|
179
|
+
return next;
|
|
180
|
+
case "event":
|
|
181
|
+
if (path.id) {
|
|
182
|
+
next.events = next.events.filter((event) => event.id !== path.id);
|
|
183
|
+
}
|
|
184
|
+
return next;
|
|
185
|
+
case "event-pose":
|
|
186
|
+
if (path.id && path.key) {
|
|
187
|
+
const event = findEvent(next, path.id);
|
|
188
|
+
if (event) {
|
|
189
|
+
event.positions = event.positions.filter((pose) => pose.objectId !== path.key);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return next;
|
|
193
|
+
case "viewpoint":
|
|
194
|
+
if (path.id) {
|
|
195
|
+
system.viewpoints = system.viewpoints.filter((viewpoint) => viewpoint.id !== path.id);
|
|
196
|
+
}
|
|
197
|
+
return next;
|
|
198
|
+
case "annotation":
|
|
199
|
+
if (path.id) {
|
|
200
|
+
system.annotations = system.annotations.filter((annotation) => annotation.id !== path.id);
|
|
201
|
+
}
|
|
202
|
+
return next;
|
|
203
|
+
case "relation":
|
|
204
|
+
if (path.id) {
|
|
205
|
+
next.relations = next.relations.filter((relation) => relation.id !== path.id);
|
|
206
|
+
}
|
|
207
|
+
return next;
|
|
208
|
+
default:
|
|
209
|
+
return next;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
export function resolveAtlasDiagnostics(document, diagnostics) {
|
|
213
|
+
return diagnostics.map((diagnostic) => ({
|
|
214
|
+
diagnostic,
|
|
215
|
+
path: resolveAtlasDiagnosticPath(document, diagnostic),
|
|
216
|
+
}));
|
|
217
|
+
}
|
|
218
|
+
export function resolveAtlasDiagnosticPath(document, diagnostic) {
|
|
219
|
+
if (diagnostic.objectId && findObject(document, diagnostic.objectId)) {
|
|
220
|
+
return {
|
|
221
|
+
kind: "object",
|
|
222
|
+
id: diagnostic.objectId,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
if (diagnostic.field?.startsWith("group.")) {
|
|
226
|
+
const parts = diagnostic.field.split(".");
|
|
227
|
+
if (parts[1] && findGroup(document, parts[1])) {
|
|
228
|
+
return {
|
|
229
|
+
kind: "group",
|
|
230
|
+
id: parts[1],
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
if (diagnostic.field?.startsWith("viewpoint.")) {
|
|
235
|
+
const parts = diagnostic.field.split(".");
|
|
236
|
+
if (parts[1] && findViewpoint(document.system, parts[1])) {
|
|
237
|
+
return {
|
|
238
|
+
kind: "viewpoint",
|
|
239
|
+
id: parts[1],
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
if (diagnostic.field?.startsWith("annotation.")) {
|
|
244
|
+
const parts = diagnostic.field.split(".");
|
|
245
|
+
if (parts[1] && findAnnotation(document.system, parts[1])) {
|
|
246
|
+
return {
|
|
247
|
+
kind: "annotation",
|
|
248
|
+
id: parts[1],
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
if (diagnostic.field?.startsWith("relation.")) {
|
|
253
|
+
const parts = diagnostic.field.split(".");
|
|
254
|
+
if (parts[1] && findRelation(document, parts[1])) {
|
|
255
|
+
return {
|
|
256
|
+
kind: "relation",
|
|
257
|
+
id: parts[1],
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
if (diagnostic.field?.startsWith("event.")) {
|
|
262
|
+
const parts = diagnostic.field.split(".");
|
|
263
|
+
if (parts[1] && findEvent(document, parts[1])) {
|
|
264
|
+
if (parts[2] === "pose" && parts[3] && findEventPose(document, parts[1], parts[3])) {
|
|
265
|
+
return {
|
|
266
|
+
kind: "event-pose",
|
|
267
|
+
id: parts[1],
|
|
268
|
+
key: parts[3],
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
return {
|
|
272
|
+
kind: "event",
|
|
273
|
+
id: parts[1],
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
if (diagnostic.field && diagnostic.field in ensureSystem(document).atlasMetadata) {
|
|
278
|
+
return {
|
|
279
|
+
kind: "metadata",
|
|
280
|
+
key: diagnostic.field,
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
export function validateAtlasDocumentWithDiagnostics(document) {
|
|
286
|
+
const diagnostics = [
|
|
287
|
+
...document.diagnostics,
|
|
288
|
+
...collectAtlasDiagnostics(document, document.version),
|
|
289
|
+
];
|
|
290
|
+
return resolveAtlasDiagnostics(document, diagnostics);
|
|
291
|
+
}
|
|
292
|
+
function ensureSystem(document) {
|
|
293
|
+
if (document.system) {
|
|
294
|
+
return document.system;
|
|
295
|
+
}
|
|
296
|
+
document.system = createEmptyAtlasDocument().system;
|
|
297
|
+
return document.system;
|
|
298
|
+
}
|
|
299
|
+
function findObject(document, objectId) {
|
|
300
|
+
return document.objects.find((object) => object.id === objectId) ?? null;
|
|
301
|
+
}
|
|
302
|
+
function findGroup(document, groupId) {
|
|
303
|
+
return document.groups.find((group) => group.id === groupId) ?? null;
|
|
304
|
+
}
|
|
305
|
+
function findRelation(document, relationId) {
|
|
306
|
+
return document.relations.find((relation) => relation.id === relationId) ?? null;
|
|
307
|
+
}
|
|
308
|
+
function findEvent(document, eventId) {
|
|
309
|
+
return document.events.find((event) => event.id === eventId) ?? null;
|
|
310
|
+
}
|
|
311
|
+
function findEventPose(document, eventId, objectId) {
|
|
312
|
+
return findEvent(document, eventId)?.positions.find((pose) => pose.objectId === objectId) ?? null;
|
|
313
|
+
}
|
|
314
|
+
function findViewpoint(system, viewpointId) {
|
|
315
|
+
return system?.viewpoints.find((viewpoint) => viewpoint.id === viewpointId) ?? null;
|
|
316
|
+
}
|
|
317
|
+
function findAnnotation(system, annotationId) {
|
|
318
|
+
return system?.annotations.find((annotation) => annotation.id === annotationId) ?? null;
|
|
319
|
+
}
|
|
320
|
+
function upsertById(items, value) {
|
|
321
|
+
const index = items.findIndex((item) => item.id === value.id);
|
|
322
|
+
if (index === -1) {
|
|
323
|
+
items.push(value);
|
|
324
|
+
items.sort(compareIdLike);
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
items[index] = value;
|
|
328
|
+
}
|
|
329
|
+
function upsertEventPose(events, eventId, value) {
|
|
330
|
+
const event = events.find((entry) => entry.id === eventId);
|
|
331
|
+
if (!event) {
|
|
332
|
+
throw new Error(`Unknown event "${eventId}" for pose update.`);
|
|
333
|
+
}
|
|
334
|
+
const index = event.positions.findIndex((entry) => entry.objectId === value.objectId);
|
|
335
|
+
if (index === -1) {
|
|
336
|
+
event.positions.push(value);
|
|
337
|
+
event.positions.sort(comparePoseObjectId);
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
event.positions[index] = value;
|
|
341
|
+
}
|
|
342
|
+
function compareIdLike(left, right) {
|
|
343
|
+
return left.id.localeCompare(right.id);
|
|
344
|
+
}
|
|
345
|
+
function comparePoseObjectId(left, right) {
|
|
346
|
+
return left.objectId.localeCompare(right.objectId);
|
|
347
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { AstFieldNode, AstSourceLocation, AtReference, NormalizedValue, UnitValue, WorldOrbitObjectType } from "./types.js";
|
|
2
|
+
export interface AtlasFieldLike {
|
|
3
|
+
key: string;
|
|
4
|
+
values: string[];
|
|
5
|
+
location: AstSourceLocation;
|
|
6
|
+
}
|
|
7
|
+
export declare function normalizeIdentifier(value: string): string;
|
|
8
|
+
export declare function humanizeIdentifier(value: string): string;
|
|
9
|
+
export declare function parseAtlasUnitValue(input: string, location?: AstSourceLocation, fieldKey?: string): UnitValue;
|
|
10
|
+
export declare function tryParseAtlasUnitValue(input: string): UnitValue | null;
|
|
11
|
+
export declare function parseAtlasNumber(input: string, key: string, location?: AstSourceLocation): number;
|
|
12
|
+
export declare function parseAtlasBoolean(input: string, key: string, location?: AstSourceLocation): boolean;
|
|
13
|
+
export declare function parseAtlasFieldBoolean(field: AtlasFieldLike): boolean;
|
|
14
|
+
export declare function parseAtlasAtReference(target: string, location?: AstSourceLocation): AtReference;
|
|
15
|
+
export declare function validateAtlasImageSource(value: string, location?: AstSourceLocation): void;
|
|
16
|
+
export declare function normalizeLegacyScalarValue(key: string, values: string[], location: AstSourceLocation): NormalizedValue;
|
|
17
|
+
export declare function ensureAtlasFieldSupported(key: string, objectType: WorldOrbitObjectType, location: AstSourceLocation): void;
|
|
18
|
+
export declare function singleAtlasFieldValue(field: Pick<AtlasFieldLike, "key" | "values" | "location">): string;
|
|
19
|
+
export declare function singleAtlasValue(values: string[], key: string, location?: AstSourceLocation): string;
|
|
20
|
+
export declare function isStructureLikeObjectType(objectType: WorldOrbitObjectType): boolean;
|
|
21
|
+
export declare function cloneNormalizedValue(value: NormalizedValue): NormalizedValue;
|
|
22
|
+
export declare function cloneFieldNode(field: AstFieldNode): AstFieldNode;
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { WorldOrbitError } from "./errors.js";
|
|
2
|
+
import { getFieldSchema, unitFamilyAllowsUnit } from "./schema.js";
|
|
3
|
+
const UNIT_PATTERN = /^(-?\d+(?:\.\d+)?)(kpc|min|mj|rj|ky|my|gy|au|km|me|re|pc|ly|deg|sol|K|m|s|h|d|y)?$/;
|
|
4
|
+
const BOOLEAN_VALUES = new Map([
|
|
5
|
+
["true", true],
|
|
6
|
+
["false", false],
|
|
7
|
+
["yes", true],
|
|
8
|
+
["no", false],
|
|
9
|
+
]);
|
|
10
|
+
const URL_SCHEME_PATTERN = /^[A-Za-z][A-Za-z0-9+.-]*:/;
|
|
11
|
+
export function normalizeIdentifier(value) {
|
|
12
|
+
return value
|
|
13
|
+
.trim()
|
|
14
|
+
.toLowerCase()
|
|
15
|
+
.replace(/[^a-z0-9_-]+/g, "-")
|
|
16
|
+
.replace(/^-+|-+$/g, "");
|
|
17
|
+
}
|
|
18
|
+
export function humanizeIdentifier(value) {
|
|
19
|
+
return value
|
|
20
|
+
.split(/[-_]+/)
|
|
21
|
+
.filter(Boolean)
|
|
22
|
+
.map((segment) => segment[0].toUpperCase() + segment.slice(1))
|
|
23
|
+
.join(" ");
|
|
24
|
+
}
|
|
25
|
+
export function parseAtlasUnitValue(input, location, fieldKey) {
|
|
26
|
+
const match = input.match(UNIT_PATTERN);
|
|
27
|
+
if (!match) {
|
|
28
|
+
throw WorldOrbitError.fromLocation(`Invalid unit value "${input}"`, location);
|
|
29
|
+
}
|
|
30
|
+
const unitValue = {
|
|
31
|
+
value: Number(match[1]),
|
|
32
|
+
unit: match[2] ?? null,
|
|
33
|
+
};
|
|
34
|
+
if (fieldKey) {
|
|
35
|
+
const schema = getFieldSchema(fieldKey);
|
|
36
|
+
if (schema?.unitFamily && !unitFamilyAllowsUnit(schema.unitFamily, unitValue.unit)) {
|
|
37
|
+
throw WorldOrbitError.fromLocation(`Unit "${unitValue.unit ?? "none"}" is not valid for "${fieldKey}"`, location);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return unitValue;
|
|
41
|
+
}
|
|
42
|
+
export function tryParseAtlasUnitValue(input) {
|
|
43
|
+
const match = input.match(UNIT_PATTERN);
|
|
44
|
+
if (!match) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
value: Number(match[1]),
|
|
49
|
+
unit: match[2] ?? null,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export function parseAtlasNumber(input, key, location) {
|
|
53
|
+
const value = Number(input);
|
|
54
|
+
if (!Number.isFinite(value)) {
|
|
55
|
+
throw WorldOrbitError.fromLocation(`Invalid numeric value "${input}" for "${key}"`, location);
|
|
56
|
+
}
|
|
57
|
+
return value;
|
|
58
|
+
}
|
|
59
|
+
export function parseAtlasBoolean(input, key, location) {
|
|
60
|
+
const parsed = BOOLEAN_VALUES.get(input.toLowerCase());
|
|
61
|
+
if (parsed === undefined) {
|
|
62
|
+
throw WorldOrbitError.fromLocation(`Invalid boolean value "${input}" for "${key}"`, location);
|
|
63
|
+
}
|
|
64
|
+
return parsed;
|
|
65
|
+
}
|
|
66
|
+
export function parseAtlasFieldBoolean(field) {
|
|
67
|
+
return parseAtlasBoolean(singleAtlasFieldValue(field), field.key, field.location);
|
|
68
|
+
}
|
|
69
|
+
export function parseAtlasAtReference(target, location) {
|
|
70
|
+
if (/^[A-Za-z0-9._-]+-[A-Za-z0-9._-]+:L\d+$/i.test(target)) {
|
|
71
|
+
throw WorldOrbitError.fromLocation(`Invalid special position "${target}"`, location);
|
|
72
|
+
}
|
|
73
|
+
const pairedMatch = target.match(/^([A-Za-z0-9._-]+)-([A-Za-z0-9._-]+):(L[1-5])$/);
|
|
74
|
+
if (pairedMatch) {
|
|
75
|
+
return {
|
|
76
|
+
kind: "lagrange",
|
|
77
|
+
primary: pairedMatch[1],
|
|
78
|
+
secondary: pairedMatch[2],
|
|
79
|
+
point: pairedMatch[3],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
const simpleMatch = target.match(/^([A-Za-z0-9._-]+):(L[1-5])$/);
|
|
83
|
+
if (simpleMatch) {
|
|
84
|
+
return {
|
|
85
|
+
kind: "lagrange",
|
|
86
|
+
primary: simpleMatch[1],
|
|
87
|
+
secondary: null,
|
|
88
|
+
point: simpleMatch[2],
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
if (/^[A-Za-z0-9._-]+:L\d+$/i.test(target)) {
|
|
92
|
+
throw WorldOrbitError.fromLocation(`Invalid special position "${target}"`, location);
|
|
93
|
+
}
|
|
94
|
+
const anchorMatch = target.match(/^([A-Za-z0-9._-]+):([A-Za-z0-9._-]+)$/);
|
|
95
|
+
if (anchorMatch) {
|
|
96
|
+
return {
|
|
97
|
+
kind: "anchor",
|
|
98
|
+
objectId: anchorMatch[1],
|
|
99
|
+
anchor: anchorMatch[2],
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
kind: "named",
|
|
104
|
+
name: target,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
export function validateAtlasImageSource(value, location) {
|
|
108
|
+
if (!value) {
|
|
109
|
+
throw WorldOrbitError.fromLocation('Field "image" must not be empty', location);
|
|
110
|
+
}
|
|
111
|
+
if (value.startsWith("//")) {
|
|
112
|
+
throw WorldOrbitError.fromLocation('Field "image" must use a relative path, root-relative path, or an http/https URL', location);
|
|
113
|
+
}
|
|
114
|
+
const schemeMatch = value.match(URL_SCHEME_PATTERN);
|
|
115
|
+
if (!schemeMatch) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const scheme = schemeMatch[0].slice(0, -1).toLowerCase();
|
|
119
|
+
if (scheme !== "http" && scheme !== "https") {
|
|
120
|
+
throw WorldOrbitError.fromLocation(`Field "image" does not support the "${scheme}" scheme`, location);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
export function normalizeLegacyScalarValue(key, values, location) {
|
|
124
|
+
const schema = getFieldSchema(key);
|
|
125
|
+
if (!schema) {
|
|
126
|
+
throw WorldOrbitError.fromLocation(`Unknown field "${key}"`, location);
|
|
127
|
+
}
|
|
128
|
+
if (schema.arity === "single" && values.length !== 1) {
|
|
129
|
+
throw WorldOrbitError.fromLocation(`Field "${key}" expects exactly one value`, location);
|
|
130
|
+
}
|
|
131
|
+
switch (schema.kind) {
|
|
132
|
+
case "list":
|
|
133
|
+
return values;
|
|
134
|
+
case "boolean":
|
|
135
|
+
return parseAtlasBoolean(singleAtlasValue(values, key, location), key, location);
|
|
136
|
+
case "number":
|
|
137
|
+
return parseAtlasNumber(singleAtlasValue(values, key, location), key, location);
|
|
138
|
+
case "unit":
|
|
139
|
+
return parseAtlasUnitValue(singleAtlasValue(values, key, location), location, key);
|
|
140
|
+
case "string": {
|
|
141
|
+
const value = values.join(" ").trim();
|
|
142
|
+
if (key === "image") {
|
|
143
|
+
validateAtlasImageSource(value, location);
|
|
144
|
+
}
|
|
145
|
+
return value;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
export function ensureAtlasFieldSupported(key, objectType, location) {
|
|
150
|
+
const schema = getFieldSchema(key);
|
|
151
|
+
if (!schema) {
|
|
152
|
+
throw WorldOrbitError.fromLocation(`Unknown field "${key}"`, location);
|
|
153
|
+
}
|
|
154
|
+
if (!schema.objectTypes.includes(objectType)) {
|
|
155
|
+
throw WorldOrbitError.fromLocation(`Field "${key}" is not valid on "${objectType}"`, location);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
export function singleAtlasFieldValue(field) {
|
|
159
|
+
return singleAtlasValue(field.values, field.key, field.location);
|
|
160
|
+
}
|
|
161
|
+
export function singleAtlasValue(values, key, location) {
|
|
162
|
+
if (values.length !== 1) {
|
|
163
|
+
throw WorldOrbitError.fromLocation(`Field "${key}" expects exactly one value`, location);
|
|
164
|
+
}
|
|
165
|
+
return values[0];
|
|
166
|
+
}
|
|
167
|
+
export function isStructureLikeObjectType(objectType) {
|
|
168
|
+
return objectType === "structure" || objectType === "phenomenon";
|
|
169
|
+
}
|
|
170
|
+
export function cloneNormalizedValue(value) {
|
|
171
|
+
if (Array.isArray(value)) {
|
|
172
|
+
return [...value];
|
|
173
|
+
}
|
|
174
|
+
if (value && typeof value === "object" && "value" in value) {
|
|
175
|
+
return {
|
|
176
|
+
value: value.value,
|
|
177
|
+
unit: value.unit,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
return value;
|
|
181
|
+
}
|
|
182
|
+
export function cloneFieldNode(field) {
|
|
183
|
+
return {
|
|
184
|
+
type: "field",
|
|
185
|
+
key: field.key,
|
|
186
|
+
values: [...field.values],
|
|
187
|
+
location: { ...field.location },
|
|
188
|
+
};
|
|
189
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import type { WorldOrbitAnyDocumentVersion, WorldOrbitAtlasDocument, WorldOrbitDiagnostic, WorldOrbitDraftDocument } from "./types.js";
|
|
2
|
+
export declare function collectAtlasDiagnostics(document: WorldOrbitAtlasDocument | WorldOrbitDraftDocument, sourceSchemaVersion?: WorldOrbitAnyDocumentVersion): WorldOrbitDiagnostic[];
|