castle-web-cli 0.4.120 → 0.4.122

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.
Files changed (33) hide show
  1. package/dist/editorConfig.d.ts +6 -1
  2. package/dist/editorConfig.js +20 -1
  3. package/dist/ide.d.ts +1 -0
  4. package/dist/ide.js +47 -1
  5. package/dist/init.js +1 -1
  6. package/dist/shell/assets/{index-Cxmq9Sed.js → index-DXBpj3-y.js} +58 -58
  7. package/dist/shell/index.html +1 -1
  8. package/dist/vitePlugins.js +21 -8
  9. package/kits/physics-2d/CLAUDE.md +56 -5
  10. package/kits/physics-2d/behaviors/AnalogStick.jsx +40 -9
  11. package/kits/physics-2d/behaviors/Collider.jsx +12 -0
  12. package/kits/physics-2d/behaviors/Draggable.jsx +67 -23
  13. package/kits/physics-2d/behaviors/Goal.jsx +2 -0
  14. package/kits/physics-2d/behaviors/Joints.jsx +5 -0
  15. package/kits/physics-2d/behaviors/RigidBody.jsx +16 -0
  16. package/kits/physics-2d/behaviors/Slingshot.jsx +48 -16
  17. package/kits/physics-2d/behaviors/Sound.jsx +11 -0
  18. package/kits/physics-2d/behaviors/Sprite.jsx +7 -0
  19. package/kits/physics-2d/behaviors/Tone.jsx +12 -0
  20. package/kits/physics-2d/behaviors/Video.jsx +6 -0
  21. package/kits/physics-2d/castle.json +1 -1
  22. package/kits/physics-2d/editors/SceneEditor.jsx +42 -6
  23. package/kits/physics-2d/editors/SingleEditor.jsx +43 -2
  24. package/kits/physics-2d/editors/editorRegistry.jsx +34 -0
  25. package/kits/physics-2d/engine/ScenePlayer.jsx +9 -3
  26. package/kits/physics-2d/engine/autoInspector.jsx +28 -3
  27. package/kits/physics-2d/engine/physics/PhysicsSystem.js +117 -0
  28. package/kits/physics-2d/engine/physics/controls.js +43 -19
  29. package/kits/physics-2d/engine/propertyRanges.js +27 -0
  30. package/kits/physics-2d/engine/scene.js +86 -4
  31. package/kits/physics-2d/engine/ui.jsx +14 -1
  32. package/kits/physics-2d/main.jsx +11 -2
  33. package/package.json +2 -1
@@ -15,11 +15,16 @@ export interface FileTypeConfig {
15
15
  new?: string;
16
16
  icon?: string;
17
17
  editor?: string;
18
- data?: boolean;
18
+ data?: boolean | DataMode;
19
19
  unsupported?: string;
20
20
  }
21
+ export type DataMode = 'json' | 'text';
22
+ export declare function dataModeOf(type: {
23
+ data?: boolean | DataMode;
24
+ }): DataMode | null;
21
25
  export interface ResolvedFileType extends FileTypeConfig {
22
26
  from?: string;
27
+ module?: string;
23
28
  }
24
29
  export interface EditorConfig {
25
30
  initialPanels?: InitialPanel[];
@@ -17,6 +17,13 @@ import * as fs from 'fs';
17
17
  import * as path from 'path';
18
18
  import { readCastleJson } from './castleJson.js';
19
19
  import { IMPORTS_DIR } from './imports.js';
20
+ export function dataModeOf(type) {
21
+ if (type.data === true)
22
+ return 'json';
23
+ if (type.data === 'json' || type.data === 'text')
24
+ return type.data;
25
+ return null;
26
+ }
20
27
  // An array with no usable entries stays an (empty) array rather than becoming
21
28
  // undefined: "I declare no file types" is a real answer, distinct from "I say
22
29
  // nothing about file types", and only the second one defers to the imports.
@@ -121,5 +128,17 @@ export function resolveFileTypes(deckDir) {
121
128
  if (imported)
122
129
  add(imported, alias);
123
130
  }
124
- return anyDeclared ? [...byExt.values()] : null;
131
+ if (!anyDeclared)
132
+ return null;
133
+ // Rewrite each declared editor path so it is addressable from the DECK root.
134
+ // This is the whole routing decision: the deck's entry imports the named
135
+ // module, whoever declared it, instead of anything guessing which page owns
136
+ // the type.
137
+ for (const type of byExt.values()) {
138
+ if (!type.editor || type.editor === 'kit')
139
+ continue;
140
+ const declared = type.editor.replace(/^\.\//, '');
141
+ type.module = type.from ? `${IMPORTS_DIR}/${type.from}/${declared}` : declared;
142
+ }
143
+ return [...byExt.values()];
125
144
  }
package/dist/ide.d.ts CHANGED
@@ -3,6 +3,7 @@ import { Duplex } from 'stream';
3
3
  import { type RawData } from 'ws';
4
4
  export declare const IDE_ASSET_PREFIX = "/__castle/ide/";
5
5
  export declare const PTY_WS_PATH = "/__castle/pty";
6
+ export declare const VENDOR_PREFIX = "/__castle/vendor/";
6
7
  export declare const FAVICON_FILES: string[];
7
8
  export declare const FAVICON_LINK_TAGS: string;
8
9
  export declare const FILES_API_PREFIX = "/__castle/files/";
package/dist/ide.js CHANGED
@@ -10,6 +10,7 @@ import * as fs from 'fs';
10
10
  import * as path from 'path';
11
11
  import picomatch from 'picomatch';
12
12
  import { fileURLToPath } from 'url';
13
+ import { createRequire } from 'module';
13
14
  import { spawn as spawnPty } from '@lydell/node-pty';
14
15
  import headlessPkg from '@xterm/headless';
15
16
  import { SerializeAddon } from '@xterm/addon-serialize';
@@ -49,6 +50,32 @@ const SHELL_MIME = {
49
50
  function deckHasFile(deckDir, name) {
50
51
  return (fs.existsSync(path.join(deckDir, name)) || fs.existsSync(path.join(deckDir, 'public', name)));
51
52
  }
53
+ // Serve a vendored library from the CLI's own dependencies. Resolved through
54
+ // require rather than a path relative to dist/, so it works the same whether the
55
+ // CLI runs from a checkout or from a global npm install.
56
+ function serveVendorFile(res, asset) {
57
+ const spec = VENDOR_FILES[asset];
58
+ if (!spec) {
59
+ res.writeHead(404).end();
60
+ return true;
61
+ }
62
+ let filePath;
63
+ try {
64
+ filePath = createRequire(import.meta.url).resolve(spec);
65
+ }
66
+ catch {
67
+ res.writeHead(404).end();
68
+ return true;
69
+ }
70
+ res.writeHead(200, {
71
+ 'content-type': 'text/javascript; charset=utf-8',
72
+ // Immutable for the session: the file only changes when the CLI does, and
73
+ // a capture shouldn't pay for re-fetching 194KB every time.
74
+ 'cache-control': 'public, max-age=3600',
75
+ });
76
+ fs.createReadStream(filePath).pipe(res);
77
+ return true;
78
+ }
52
79
  // Serve a file from the bundled shell dir, guarding against path traversal.
53
80
  function serveShellFile(res, asset) {
54
81
  const rel = path.normalize(asset).replace(/^(\.\.[/\\])+/, '');
@@ -75,6 +102,20 @@ function serveShellFile(res, asset) {
75
102
  // upgrade handler on Vite's HTTP server).
76
103
  export const IDE_ASSET_PREFIX = '/__castle/ide/';
77
104
  export const PTY_WS_PATH = '/__castle/pty';
105
+ // Libraries the PLATFORM lends a deck at runtime, served from this serve's own
106
+ // origin rather than fetched from a CDN.
107
+ //
108
+ // html2canvas is the only one so far: the SDK composites a card (canvas + the
109
+ // deck's own DOM) with it to capture a cover. Serving it here instead of
110
+ // bundling it into the SDK keeps it out of every published deck -- it is ~194KB
111
+ // that only an editor ever runs, and a deck is bundled into a single file, so
112
+ // bundling it could not be made lazy. And it removes a live failure: a CDN
113
+ // import fails closed, silently downgrading a cover to canvas-only whenever the
114
+ // network is slow, blocked, or absent.
115
+ export const VENDOR_PREFIX = '/__castle/vendor/';
116
+ const VENDOR_FILES = {
117
+ 'html2canvas.js': 'html2canvas/dist/html2canvas.esm.js',
118
+ };
78
119
  // Castle's favicon (the same files castle.xyz serves), shipped in the shell
79
120
  // bundle and also served from the origin root so every page under the serve
80
121
  // gets it -- the shell at `/`, the deck page at `/index.html`, and the
@@ -209,7 +250,9 @@ function listDeckFiles(deckDir) {
209
250
  // editors, and the builtin code editor renders everything.
210
251
  function kitEditorExtensions(config, fileTypes) {
211
252
  if (fileTypes) {
212
- return fileTypes.filter((t) => t.editor === 'kit').map((t) => t.ext);
253
+ // ANY declared editor means "not the builtin code editor" -- the legacy
254
+ // "kit" (this deck's own dispatcher) and a named module both count.
255
+ return fileTypes.filter((t) => Boolean(t.editor)).map((t) => t.ext);
213
256
  }
214
257
  // A deck saved before file types existed named its kit extensions directly.
215
258
  return config.extensions ?? [];
@@ -941,6 +984,9 @@ export function createIdeServer(opts) {
941
984
  if (favicon && !deckHasFile(deckDir, favicon)) {
942
985
  return serveShellFile(res, favicon);
943
986
  }
987
+ if (reqPath.startsWith(VENDOR_PREFIX)) {
988
+ return serveVendorFile(res, reqPath.slice(VENDOR_PREFIX.length));
989
+ }
944
990
  if (reqPath.startsWith(IDE_ASSET_PREFIX)) {
945
991
  return serveShellFile(res, reqPath.slice(IDE_ASSET_PREFIX.length) || 'index.html');
946
992
  }
package/dist/init.js CHANGED
@@ -37,7 +37,7 @@ const DEFAULT_KIT = 'physics-2d';
37
37
  // Registry version of castle-web-sdk to inject when scaffolding from a
38
38
  // globally-installed castle-web (not from inside the workspace). Bumped
39
39
  // alongside cli/sdk version bumps.
40
- const PUBLISHED_SDK_VERSION = '0.4.12';
40
+ const PUBLISHED_SDK_VERSION = '0.4.13';
41
41
  // The account the first-party kits are (to be) published under, so a kit
42
42
  // imported from the CLI's copy is named the same as one fetched from the server.
43
43
  const KIT_AUTHOR = 'castle';