castle-web-sdk 0.4.10 → 0.4.12

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 CHANGED
@@ -412,6 +412,23 @@ await writeFile("scenes/main.scene", JSON.stringify(scene, null, 2));
412
412
  Only works while editing locally with `castle-web serve`. Calls from a
413
413
  published deck fail.
414
414
 
415
+ ### `fileUrl(path): string`
416
+
417
+ A URL that serves a deck file as raw bytes. Point an `<img>`, `<audio>`,
418
+ or `<video>` at it when editor UI has to show a file the browser renders
419
+ natively — `writeFile`'s counterpart reads text, which is nothing an
420
+ image or a sound can be read as.
421
+
422
+ ```js
423
+ import { fileUrl } from "castle-web-sdk";
424
+
425
+ <img src={fileUrl("assets/logo.png")} alt="" />;
426
+ ```
427
+
428
+ Like `writeFile`, this only means anything while editing locally with
429
+ `castle-web serve` — a published deck has no serve to ask, and should
430
+ load its assets through the bundler instead.
431
+
415
432
  ## CastleError
416
433
 
417
434
  Every error the SDK throws is a `CastleError`. Check `code` to tell
package/dist/castle.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export { isEdit } from "./context";
2
2
  export { CastleError } from "./errors";
3
+ export { deckPrefixOf, IMPORTS_DIR, IMPORTS_PREFIX, isImportedFile, resolveDeckFile, } from "./files";
3
4
  export { Haptics } from "./haptics";
4
5
  export type { CastleHapticsApi, HapticsResult, HapticsStatus, HapticStyle } from "./haptics";
5
6
  export { Leaderboard } from "./leaderboard";
@@ -10,7 +11,7 @@ export { Pass } from "./passes";
10
11
  export type { CastlePassApi, PassOfferResult, PassOfferStatus, } from "./passes";
11
12
  export { Portal } from "./portal";
12
13
  export type { CastlePortalApi, PortalOpenResult, PortalOpenStatus, PortalPrefetchResult, PortalPrefetchStatus, } from "./portal";
13
- export { CARD_RATIO, initCard, onBeforeRestart, onFilesChanged, onSaveReloadState, requestReload, setup, takeReloadState, writeFile, } from "./runtime";
14
+ export { CARD_RATIO, fileUrl, initCard, onBeforeRestart, onFilesChanged, onSaveReloadState, requestReload, setup, takeReloadState, writeFile, } from "./runtime";
14
15
  export type { FileChange, FilesChangedEvent } from "./runtime";
15
16
  export { SharedStorage, Storage } from "./storage";
16
17
  export { Time } from "./time";
package/dist/castle.js CHANGED
@@ -1,12 +1,13 @@
1
1
  // Castle Web SDK
2
2
  export { isEdit } from "./context";
3
3
  export { CastleError } from "./errors";
4
+ export { deckPrefixOf, IMPORTS_DIR, IMPORTS_PREFIX, isImportedFile, resolveDeckFile, } from "./files";
4
5
  export { Haptics } from "./haptics";
5
6
  export { Leaderboard } from "./leaderboard";
6
7
  export { Lifecycle } from "./lifecycle";
7
8
  export { Pass } from "./passes";
8
9
  export { Portal } from "./portal";
9
- export { CARD_RATIO, initCard, onBeforeRestart, onFilesChanged, onSaveReloadState, requestReload, setup, takeReloadState, writeFile, } from "./runtime";
10
+ export { CARD_RATIO, fileUrl, initCard, onBeforeRestart, onFilesChanged, onSaveReloadState, requestReload, setup, takeReloadState, writeFile, } from "./runtime";
10
11
  export { SharedStorage, Storage } from "./storage";
11
12
  export { Time } from "./time";
12
13
  export { User } from "./user";
@@ -0,0 +1,15 @@
1
+ export declare const IMPORTS_PREFIX = "@imports/";
2
+ export declare const IMPORTS_DIR = "imports";
3
+ export declare function deckPrefixOf(filePath: string): string;
4
+ /**
5
+ * Resolve a reference to the key it names in the deck's file map.
6
+ *
7
+ * @param ref the reference as written -- `drawings/rock.pxart` or
8
+ * `@imports/someone.pack/drawings/rock.pxart`
9
+ * @param from the path of the file the reference was written in; a reference in
10
+ * a deck's own file resolves against the deck root, one in an
11
+ * import's file against that import.
12
+ */
13
+ export declare function resolveDeckFile(ref: string, from?: string): string;
14
+ /** Whether a path names a file some import owns (rather than the deck's own). */
15
+ export declare function isImportedFile(filePath: string): boolean;
package/dist/files.js ADDED
@@ -0,0 +1,52 @@
1
+ // How a deck names a file -- one rule, everywhere a path appears: in JS module
2
+ // specifiers, in a scene's `blueprint`, in a Sprite's `file`, in anything a kit
3
+ // invents later.
4
+ //
5
+ // drawings/rock.pxart a file of the deck the REFERENCE lives in
6
+ // @imports/<alias>/drawings/rock.pxart a file of that import
7
+ //
8
+ // The unprefixed form is deck-relative, and "the deck" means whichever deck the
9
+ // referencing file belongs to. So a kit's blueprint saying `drawings/cauldron.pxart`
10
+ // means the kit's own drawing whether the kit is the deck being played or an
11
+ // import of it -- the same text keeps meaning the same file after the kit is
12
+ // imported by somebody else. That is what makes a deck publishable as a
13
+ // dependency without rewriting its insides.
14
+ //
15
+ // `@imports/` is the only way to name someone else's file, so a cross-deck
16
+ // reference is visible as one at a glance, and it means the same thing from any
17
+ // depth: imports are flattened into one `imports/` at the deck root, so the
18
+ // prefix is positional in nothing.
19
+ export const IMPORTS_PREFIX = '@imports/';
20
+ // Where imports live on disk, relative to the deck root. `@imports/x/y` is
21
+ // exactly `imports/x/y` -- the alias exists so the reference reads as a
22
+ // cross-deck one and does not depend on where the referencing file sits.
23
+ export const IMPORTS_DIR = 'imports';
24
+ function stripDotSlash(path) {
25
+ return path.replace(/^\.\//, '');
26
+ }
27
+ // The deck a file belongs to, as a path prefix: `imports/<alias>/` for a file of
28
+ // an import, `''` for one of the deck's own.
29
+ export function deckPrefixOf(filePath) {
30
+ const match = new RegExp(`^(${IMPORTS_DIR}/[^/]+/)`).exec(filePath ?? '');
31
+ return match ? match[1] : '';
32
+ }
33
+ /**
34
+ * Resolve a reference to the key it names in the deck's file map.
35
+ *
36
+ * @param ref the reference as written -- `drawings/rock.pxart` or
37
+ * `@imports/someone.pack/drawings/rock.pxart`
38
+ * @param from the path of the file the reference was written in; a reference in
39
+ * a deck's own file resolves against the deck root, one in an
40
+ * import's file against that import.
41
+ */
42
+ export function resolveDeckFile(ref, from = '') {
43
+ const path = stripDotSlash(String(ref ?? ''));
44
+ if (path.startsWith(IMPORTS_PREFIX)) {
45
+ return `${IMPORTS_DIR}/${path.slice(IMPORTS_PREFIX.length)}`;
46
+ }
47
+ return deckPrefixOf(stripDotSlash(from)) + path;
48
+ }
49
+ /** Whether a path names a file some import owns (rather than the deck's own). */
50
+ export function isImportedFile(filePath) {
51
+ return deckPrefixOf(filePath) !== '';
52
+ }
package/dist/runtime.d.ts CHANGED
@@ -25,6 +25,7 @@ export interface FilesChangedEvent {
25
25
  }
26
26
  export declare function setup(): void;
27
27
  export declare function writeFile(path: string, contents: string): Promise<LocalResponse>;
28
+ export declare function fileUrl(path: string): string;
28
29
  export declare function initCard(): HTMLDivElement;
29
30
  export declare function sendLocalCommand<C extends CommandName>(command: C, params: CommandParams[C]): Promise<CommandResponseEnvelope>;
30
31
  export declare function onFilesChanged(listener: (event: FilesChangedEvent) => void): () => void;
package/dist/runtime.js CHANGED
@@ -30,6 +30,14 @@ export function writeFile(path, contents) {
30
30
  contents,
31
31
  });
32
32
  }
33
+ // A same-origin URL that serves a deck file as raw bytes. Editor UI that shows
34
+ // a file the browser renders natively -- an image in an `<img>`, a sound in an
35
+ // `<audio>` -- points at this instead of reading the file, which only speaks
36
+ // text. Only meaningful while editing locally with `castle-web serve`; a
37
+ // published deck has no serve to ask.
38
+ export function fileUrl(path) {
39
+ return `/__castle/files/raw?path=${encodeURIComponent(path)}`;
40
+ }
33
41
  export function initCard() {
34
42
  const style = document.createElement("style");
35
43
  style.textContent = `
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "castle-web-sdk",
3
- "version": "0.4.10",
3
+ "version": "0.4.12",
4
4
  "type": "module",
5
5
  "main": "dist/castle.js",
6
6
  "types": "dist/castle.d.ts",