@vgai/editor-sdk 0.5.18 → 0.5.20

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/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@vgai/editor-sdk",
3
3
  "author": "Volter AI, Inc.",
4
4
  "license": "Apache-2.0",
5
- "version": "0.5.18",
5
+ "version": "0.5.20",
6
6
  "type": "module",
7
7
  "repository": {
8
8
  "type": "git",
@@ -23,7 +23,7 @@
23
23
  },
24
24
  "dependencies": {
25
25
  "@types/three": "^0.180.0",
26
- "@vgai/sdk": "0.5.18"
26
+ "@vgai/sdk": "0.5.20"
27
27
  },
28
28
  "peerDependencies": {
29
29
  "@vgai/engine": "*",
@@ -1,5 +1,5 @@
1
1
  import type { AssetKind, EditorCameraState, EditorView, ViewPreset } from './types.js';
2
- import { EDITOR_VIEW_WORKSPACE_DOCUMENT_IDS } from './types.js';
2
+ import { EDITOR_VIEW_WORKSPACE_DOCUMENT_IDS, isEditorViewUtility } from './types.js';
3
3
 
4
4
  const PREFIX = 'view.';
5
5
  const MAX_QUERY_LENGTH = 4096;
@@ -21,7 +21,6 @@ const CAMERAS = new Set<ViewPreset | 'isometric'>([
21
21
  'isometric',
22
22
  ]);
23
23
  type EditorViewDiagnostic = NonNullable<NonNullable<EditorView['viewport']>['diagnostic']>;
24
- type EditorViewUtility = NonNullable<EditorView['utility']>;
25
24
  const DIAGNOSTICS = new Set<EditorViewDiagnostic>([
26
25
  'solid',
27
26
  'unlit',
@@ -33,13 +32,6 @@ const DIAGNOSTICS = new Set<EditorViewDiagnostic>([
33
32
  'bounds',
34
33
  'skeleton',
35
34
  ]);
36
- const UTILITIES = new Set<EditorViewUtility>([
37
- 'profiler',
38
- 'console',
39
- 'animation',
40
- 'light-explorer',
41
- ]);
42
-
43
35
  function nonEmpty(value: string | null): string | null {
44
36
  const trimmed = value?.trim();
45
37
  return trimmed ? trimmed : null;
@@ -210,9 +202,10 @@ export function editorViewFromUrl(value: string | URL): EditorView | null {
210
202
  if (ids.length) view.selection = { ids, focus: params.get(`${PREFIX}focus`) === '1' };
211
203
  const viewport = parseViewport(params);
212
204
  if (viewport) view.viewport = viewport;
205
+ // Shape check only: a `tool:` id names a utility the OPEN PROJECT
206
+ // contributes, so the URL cannot know whether it exists. The editor
207
+ // validates it against its live registry when the view is presented.
213
208
  const utility = params.get(`${PREFIX}utility`);
214
- if (utility && UTILITIES.has(utility as EditorViewUtility)) {
215
- view.utility = utility as EditorViewUtility;
216
- }
209
+ if (utility && isEditorViewUtility(utility)) view.utility = utility;
217
210
  return view;
218
211
  }
package/src/index.ts CHANGED
@@ -51,7 +51,9 @@ export type {
51
51
  EditorEntitySummary,
52
52
  EditorState,
53
53
  EditorView,
54
+ EditorViewBuiltInUtilityId,
54
55
  EditorViewDocument,
56
+ EditorViewUtility,
55
57
  GameCapture,
56
58
  GameplayRecordingCapture,
57
59
  GameplayRecordingOptions,
@@ -93,3 +95,8 @@ export type {
93
95
  ViewportCapture,
94
96
  ViewportTab,
95
97
  } from './types.js';
98
+ export {
99
+ EDITOR_VIEW_BUILT_IN_UTILITY_IDS,
100
+ EDITOR_VIEW_TOOL_UTILITY_PREFIX,
101
+ isEditorViewUtility,
102
+ } from './types.js';
package/src/types.ts CHANGED
@@ -670,6 +670,53 @@ export const EDITOR_VIEW_WORKSPACE_DOCUMENT_IDS = [
670
670
 
671
671
  export type EditorViewWorkspaceDocumentId = (typeof EDITOR_VIEW_WORKSPACE_DOCUMENT_IDS)[number];
672
672
 
673
+ /**
674
+ * The editor's OWN bottom-drawer instruments, as named in a shareable view.
675
+ * One runtime list owns both URL parsing and the public id type — the same
676
+ * discipline as {@link EDITOR_VIEW_WORKSPACE_DOCUMENT_IDS}, and for the same
677
+ * reason: a separate hand-written union and parser allowlist drift silently
678
+ * (`behavior` was in the union and missing from the allowlist, so a view
679
+ * carrying it round-tripped to nothing).
680
+ */
681
+ export const EDITOR_VIEW_BUILT_IN_UTILITY_IDS = [
682
+ 'profiler',
683
+ 'console',
684
+ 'animation',
685
+ 'behavior',
686
+ 'light-explorer',
687
+ ] as const;
688
+
689
+ export type EditorViewBuiltInUtilityId = (typeof EDITOR_VIEW_BUILT_IN_UTILITY_IDS)[number];
690
+
691
+ /** The prefix a PROJECT-contributed utility's id carries. The editor's tool
692
+ * loader namespaces every `workspace.utility` contribution as
693
+ * `tool:<contribution-id>`, exactly as a contributed center document is
694
+ * addressed by `{ kind: 'tool', id }`. */
695
+ export const EDITOR_VIEW_TOOL_UTILITY_PREFIX = 'tool:';
696
+
697
+ /**
698
+ * Which bottom-drawer utility a view reveals: one of the editor's own
699
+ * instruments, or a utility the OPEN PROJECT contributes.
700
+ *
701
+ * The project half cannot be an enum — which tabs exist depends entirely on
702
+ * the game that is open — so the address space admits the namespace and the
703
+ * EDITOR validates the id against its live utility registry when the view is
704
+ * presented, refusing an unregistered one by naming what IS registered.
705
+ */
706
+ export type EditorViewUtility =
707
+ | EditorViewBuiltInUtilityId
708
+ | `${typeof EDITOR_VIEW_TOOL_UTILITY_PREFIX}${string}`;
709
+
710
+ /** Whether `value` is addressable as a view's utility. Shape only — existence
711
+ * is the editor's answer at present-time, not the URL's. */
712
+ export function isEditorViewUtility(value: string): value is EditorViewUtility {
713
+ return (
714
+ (EDITOR_VIEW_BUILT_IN_UTILITY_IDS as readonly string[]).includes(value) ||
715
+ (value.startsWith(EDITOR_VIEW_TOOL_UTILITY_PREFIX) &&
716
+ value.length > EDITOR_VIEW_TOOL_UTILITY_PREFIX.length)
717
+ );
718
+ }
719
+
673
720
  /**
674
721
  * A durable, intentionally small projection of what an editor is presenting.
675
722
  * This is not workspace persistence: panel sizes, transient tool state, and
@@ -699,7 +746,7 @@ export interface EditorView {
699
746
  frame?: 'document' | 'selection';
700
747
  grid?: boolean;
701
748
  };
702
- utility?: 'profiler' | 'console' | 'animation' | 'behavior' | 'light-explorer';
749
+ utility?: EditorViewUtility;
703
750
  }
704
751
 
705
752
  export interface PresentedEditorView {