castle-web-cli 0.4.120 → 0.4.121

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/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
@@ -941,6 +982,9 @@ export function createIdeServer(opts) {
941
982
  if (favicon && !deckHasFile(deckDir, favicon)) {
942
983
  return serveShellFile(res, favicon);
943
984
  }
985
+ if (reqPath.startsWith(VENDOR_PREFIX)) {
986
+ return serveVendorFile(res, reqPath.slice(VENDOR_PREFIX.length));
987
+ }
944
988
  if (reqPath.startsWith(IDE_ASSET_PREFIX)) {
945
989
  return serveShellFile(res, reqPath.slice(IDE_ASSET_PREFIX.length) || 'index.html');
946
990
  }
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';