@field/cascade 0.7.1 → 0.10.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.
Files changed (117) hide show
  1. package/AGENTS.md +17 -1
  2. package/CHANGELOG.md +260 -0
  3. package/DESIGN.md +14 -0
  4. package/README.md +41 -25
  5. package/dist/assets/CodeEditor-DSZBpzdy.js +623 -0
  6. package/dist/assets/CodePanel-sY6sZa7B.js +2 -0
  7. package/dist/assets/CustomNodeDialog-BRKnqZhp.js +1 -0
  8. package/dist/assets/{ExportDialog-BJu2Bpvv.js → ExportDialog-C7dVGua4.js} +2 -2
  9. package/dist/assets/OpenGraphDialog-ZsgL-iwr.js +1 -0
  10. package/dist/assets/ProjectSettings-Cw17nNe3.js +2 -0
  11. package/dist/assets/SettingsDialog-p25h3tj0.js +1 -0
  12. package/dist/assets/VersionHistoryDialog-DzFLUotB.js +3 -0
  13. package/dist/assets/{core-DlkL34JF.js → core-BICrEt0y.js} +8 -8
  14. package/dist/assets/{cssMode-DaSSFZYi.js → cssMode-D7TXw57I.js} +1 -1
  15. package/dist/assets/definitions-DUww2Rt-.js +1 -0
  16. package/dist/assets/{editor.api-CHUMRaMm.js → editor.api-DvkCO3ko.js} +1 -1
  17. package/dist/assets/{freemarker2-DQ604q2A.js → freemarker2-BA2lxsF1.js} +1 -1
  18. package/dist/assets/geo-C2RHOVHC.js +1 -0
  19. package/dist/assets/{handlebars-09pcWz8x.js → handlebars-BcDiyPd8.js} +1 -1
  20. package/dist/assets/{html-DtIKrZiD.js → html-C7O4TyhX.js} +1 -1
  21. package/dist/assets/{htmlMode-DgJ_4m1_.js → htmlMode-WaDGF3Mj.js} +1 -1
  22. package/dist/assets/{image-CtUE4_I-.js → image-DR4oeyJB.js} +3 -3
  23. package/dist/assets/index-7vae6YFC.css +1 -0
  24. package/dist/assets/index-DyvDC6pS.js +219 -0
  25. package/dist/assets/index-client-DqYmKstU.js +1 -0
  26. package/dist/assets/{javascript-kbIBYYGo.js → javascript-CpIEK7tz.js} +1 -1
  27. package/dist/assets/{jsonMode-DblCG64t.js → jsonMode-B2FltW0f.js} +1 -1
  28. package/dist/assets/legacy-CTEeXeqF.js +2 -0
  29. package/dist/assets/{liquid-D-qdTGhQ.js → liquid-CN6FFHZE.js} +1 -1
  30. package/dist/assets/{lspLanguageFeatures-Bc6azcFQ.js → lspLanguageFeatures-QhV9XtLp.js} +1 -1
  31. package/dist/assets/math-DaDEgWKt.js +1 -0
  32. package/dist/assets/{mdx-TXg4xsyD.js → mdx-DE89pafV.js} +1 -1
  33. package/dist/assets/pop-pLH7L0PW.js +1 -0
  34. package/dist/assets/{python-C4SGyXJW.js → python-ByTllTB9.js} +1 -1
  35. package/dist/assets/{razor-BZ-lEgY9.js → razor-USYlRRCE.js} +1 -1
  36. package/dist/assets/studioScenes-8sq9FfFg.js +1 -0
  37. package/dist/assets/{tsMode-BoaO1D7x.js → tsMode-BXpN8iUz.js} +1 -1
  38. package/dist/assets/{typescript-D87dYk9k.js → typescript-DInBjGQQ.js} +1 -1
  39. package/dist/assets/{workers-ZrST7klJ.js → workers-C7Ye5B7D.js} +1 -1
  40. package/dist/assets/{xml-DT6r4F7G.js → xml-U0Uocqyo.js} +1 -1
  41. package/dist/assets/{yaml-DxmQ8XYb.js → yaml-CBw_PVYf.js} +1 -1
  42. package/dist/cli/index.js +20070 -3487
  43. package/dist/cli/runtime/stage.ts +70 -10
  44. package/dist/contracts/bundle.d.ts +75 -0
  45. package/dist/contracts/bundle.js +112 -0
  46. package/dist/contracts/definition.d.ts +67 -4
  47. package/dist/contracts/document.d.ts +29 -0
  48. package/dist/contracts/editor.d.ts +172 -0
  49. package/dist/contracts/editor.js +2 -0
  50. package/dist/contracts/index.d.ts +2 -0
  51. package/dist/contracts/index.js +2 -0
  52. package/dist/contracts/validate.js +59 -3
  53. package/dist/contracts/values.d.ts +3 -3
  54. package/dist/contracts/values.js +1 -0
  55. package/dist/index.html +6 -4
  56. package/dist/player/app.js +17 -5
  57. package/dist/player/editor.js +1894 -0
  58. package/dist/player/editorEngine.js +477 -0
  59. package/dist/runtime/builtins/core/bundle.d.ts +70 -0
  60. package/dist/runtime/builtins/core/bundle.js +81 -0
  61. package/dist/runtime/builtins/core/index.d.ts +3 -2
  62. package/dist/runtime/builtins/core/index.js +6 -2
  63. package/dist/runtime/builtins/core/routing.d.ts +27 -0
  64. package/dist/runtime/builtins/core/routing.js +28 -0
  65. package/dist/runtime/edit/document.d.ts +94 -0
  66. package/dist/runtime/edit/document.js +194 -0
  67. package/dist/runtime/edit/graphEditor.d.ts +223 -0
  68. package/dist/runtime/edit/graphEditor.js +893 -0
  69. package/dist/runtime/edit/index.d.ts +12 -0
  70. package/dist/runtime/edit/index.js +6 -0
  71. package/dist/runtime/edit/layout.d.ts +50 -0
  72. package/dist/runtime/edit/layout.js +126 -0
  73. package/dist/runtime/edit/operations.d.ts +65 -0
  74. package/dist/runtime/edit/operations.js +57 -0
  75. package/dist/runtime/edit/parameters.d.ts +75 -0
  76. package/dist/runtime/edit/parameters.js +284 -0
  77. package/dist/runtime/edit/read.d.ts +35 -0
  78. package/dist/runtime/edit/read.js +65 -0
  79. package/dist/runtime/editor/index.d.ts +104 -0
  80. package/dist/runtime/editor/index.js +439 -0
  81. package/dist/runtime/expressions/bundlePaths.d.ts +37 -0
  82. package/dist/runtime/expressions/bundlePaths.js +55 -0
  83. package/dist/runtime/expressions/index.d.ts +2 -0
  84. package/dist/runtime/expressions/index.js +1 -0
  85. package/dist/runtime/index.d.ts +2 -0
  86. package/dist/runtime/index.js +2 -0
  87. package/dist/runtime/params/animator.d.ts +5 -0
  88. package/dist/runtime/params/animator.js +16 -0
  89. package/dist/runtime/runtime.js +238 -12
  90. package/dist/runtime/seed.d.ts +29 -0
  91. package/dist/runtime/seed.js +52 -0
  92. package/dist/runtime/types.d.ts +12 -0
  93. package/dist/stage.js +40 -9
  94. package/dist/studio/panel.d.ts +2 -0
  95. package/doc/CLI_REFERENCE.md +100 -0
  96. package/doc/EDITOR_EXPORT.md +226 -0
  97. package/doc/HEADLESS_GPU.md +27 -0
  98. package/doc/MCP.md +53 -0
  99. package/doc/NODE_REFERENCE.md +66 -0
  100. package/doc/PROJECT_AUTHORING.md +137 -0
  101. package/package.json +15 -6
  102. package/dist/assets/CodeEditor-D-N0C2jT.js +0 -623
  103. package/dist/assets/CodePanel-EN411mp5.js +0 -2
  104. package/dist/assets/CustomNodeDialog-6z2n27VV.js +0 -1
  105. package/dist/assets/OpenGraphDialog-fMZjzIR3.js +0 -1
  106. package/dist/assets/ProjectSettings-BQ8PGNqo.js +0 -2
  107. package/dist/assets/SettingsDialog-IbYLm8Bx.js +0 -1
  108. package/dist/assets/VersionHistoryDialog-Bgh-q5Jg.js +0 -3
  109. package/dist/assets/definitions-CQBdsJYJ.js +0 -1
  110. package/dist/assets/geo-DcmMAcqM.js +0 -1
  111. package/dist/assets/index-CnylT98t.js +0 -212
  112. package/dist/assets/index-client-BoJgsN9M.js +0 -1
  113. package/dist/assets/index-ilgbOu6G.css +0 -1
  114. package/dist/assets/legacy-CAj2_7QE.js +0 -2
  115. package/dist/assets/math-CY11tkoN.js +0 -1
  116. package/dist/assets/pop-Dr5-ARqQ.js +0 -1
  117. package/dist/assets/projectSettingsApi-C1WvIwfP.js +0 -1
@@ -19,9 +19,9 @@ export const CAPABILITIES_BY_ENVIRONMENT = {
19
19
  };
20
20
  const ALLOWED = CAPABILITIES_BY_ENVIRONMENT;
21
21
  const fields = (names) => new Set(names.split(" "));
22
- const TOP_FIELDS = fields("apiVersion runsOn container capabilities label description icon inputs outputs props");
23
- const DATA_FIELDS = fields("kind type default description variadic min max step accept control options");
24
- const OUTPUT_FIELDS = fields("kind type description");
22
+ const TOP_FIELDS = fields("apiVersion runsOn container capabilities source label description icon inputs outputs props");
23
+ const DATA_FIELDS = fields("kind type default description variadic min max step accept control options schema fields");
24
+ const OUTPUT_FIELDS = fields("kind type description schema fields");
25
25
  const PROP_FIELDS = fields("type default label description min max step accept control options expression action");
26
26
  function diagnostic(code, message, path) {
27
27
  return { phase: "definition", code: `definition/${code}`, message, path };
@@ -94,6 +94,8 @@ export function validateNodeDefinition(value) {
94
94
  value.container !== "subnet" &&
95
95
  value.container !== "feedback")
96
96
  add("invalid-container", "container must be subnet or feedback", "container");
97
+ if (value.source !== undefined && value.source !== "live")
98
+ add("invalid-source", "source must be \"live\" when present", "source");
97
99
  const allowed = ALLOWED[environment] ?? [];
98
100
  if (value.capabilities !== undefined && !Array.isArray(value.capabilities))
99
101
  add("invalid-capabilities", "capabilities must be an array", "capabilities");
@@ -193,6 +195,8 @@ export function validateNodeDefinition(value) {
193
195
  add("invalid-type", `${String(type)} is not a Cascade type`, `${path}.type`);
194
196
  continue;
195
197
  }
198
+ if (section !== "props")
199
+ result.push(...bundleDiagnostics(raw, type, section, path));
196
200
  if (type === "texture" && environment !== "browser")
197
201
  add("texture-not-portable", "texture is browser-only", `${path}.type`);
198
202
  if (type === "texture" && "default" in raw)
@@ -229,6 +233,58 @@ export function validateNodeDefinition(value) {
229
233
  }
230
234
  return result;
231
235
  }
236
+ /** `schema` and `fields` on a port: bundle-only, and well-formed. */
237
+ function bundleDiagnostics(raw, type, section, path) {
238
+ const result = [];
239
+ const add = (code, message, at) => result.push(diagnostic(code, message, at));
240
+ for (const key of ["schema", "fields"])
241
+ if (key in raw && type !== "bundle")
242
+ add("bundle-metadata", `${key} is only valid on a bundle port`, `${path}.${key}`);
243
+ if (type !== "bundle")
244
+ return result;
245
+ if ("schema" in raw && (typeof raw.schema !== "string" || !IDENTIFIER.test(raw.schema)))
246
+ add("invalid-schema", "schema must be an identifier", `${path}.schema`);
247
+ if (!("fields" in raw))
248
+ return result;
249
+ const declared = raw.fields;
250
+ if (section === "inputs") {
251
+ if (!Array.isArray(declared)) {
252
+ add("invalid-fields", "an input's fields list the field names it reads", `${path}.fields`);
253
+ return result;
254
+ }
255
+ const seen = new Set();
256
+ for (const [index, field] of declared.entries()) {
257
+ if (typeof field !== "string" || !IDENTIFIER.test(field))
258
+ add("invalid-field", `${String(field)} is not a valid field name`, `${path}.fields[${index}]`);
259
+ else if (seen.has(field))
260
+ add("duplicate-field", `${field} is listed twice`, `${path}.fields[${index}]`);
261
+ else
262
+ seen.add(field);
263
+ }
264
+ return result;
265
+ }
266
+ if (!isRecord(declared)) {
267
+ add("invalid-fields", "an output's fields map each field name to its type", `${path}.fields`);
268
+ return result;
269
+ }
270
+ for (const [field, definition] of Object.entries(declared)) {
271
+ const at = `${path}.fields.${field}`;
272
+ if (!IDENTIFIER.test(field) || RESERVED.has(field))
273
+ add("invalid-field", `${field} is not a valid field name`, at);
274
+ const fieldType = typeof definition === "string"
275
+ ? definition
276
+ : isRecord(definition) ? definition.type : undefined;
277
+ if (isRecord(definition))
278
+ for (const key of Object.keys(definition))
279
+ if (key !== "type" && key !== "description")
280
+ add("unknown-field", `${at}.${key} is not allowed`, `${at}.${key}`);
281
+ if (!validType(fieldType))
282
+ add("invalid-type", `${String(fieldType)} is not a Cascade type`, at);
283
+ else if (fieldType === "texture")
284
+ add("texture-not-portable", "a bundle field cannot hold a texture", at);
285
+ }
286
+ return result;
287
+ }
232
288
  export function assertNodeDefinition(value) {
233
289
  const diagnostics = validateNodeDefinition(value);
234
290
  if (diagnostics.length)
@@ -2,7 +2,7 @@ import type { Camera } from "./camera.js";
2
2
  import type { Color } from "./color.js";
3
3
  import type { Light, Scene } from "./scene.js";
4
4
  import type { Geometry, GeometryFileRef, GeometryJson, GeometrySerialized } from "./geometry.js";
5
- export declare const CORE_TYPES: readonly ["float", "int", "bool", "string", "vec2", "vec3", "vec4", "vec2i", "vec3i", "vec4i", "mat2", "mat3", "mat4", "image", "texture", "geometry", "points", "lines", "polyline", "mesh", "rects", "color", "camera", "scene", "light", "asset", "array", "object", "any"];
5
+ export declare const CORE_TYPES: readonly ["float", "int", "bool", "string", "vec2", "vec3", "vec4", "vec2i", "vec3i", "vec4i", "mat2", "mat3", "mat4", "image", "texture", "geometry", "points", "lines", "polyline", "mesh", "rects", "color", "camera", "scene", "light", "asset", "array", "object", "bundle", "any"];
6
6
  export type CoreType = (typeof CORE_TYPES)[number];
7
7
  export type NamespacedType = `${string}.${string}`;
8
8
  export type CascadeType = CoreType | NamespacedType;
@@ -96,7 +96,7 @@ export interface AssetRef {
96
96
  readonly mediaType?: string;
97
97
  }
98
98
  export type SerializableValue = JsonValue | AssetRef | ImageRef | GeometryJson | GeometryFileRef;
99
- export type ValueForType<T extends CascadeType> = T extends "float" | "int" ? number : T extends "bool" ? boolean : T extends "string" ? string : T extends "vec2" ? Vec2 : T extends "vec3" ? Vec3 : T extends "vec4" ? Vec4 : T extends "vec2i" ? Vec2i : T extends "vec3i" ? Vec3i : T extends "vec4i" ? Vec4i : T extends "mat2" ? Mat2 : T extends "mat3" ? Mat3 : T extends "mat4" ? Mat4 : T extends "color" ? Color : T extends "camera" ? Camera : T extends "scene" ? Scene : T extends "light" ? Light : T extends "image" ? ImageRef : T extends "texture" ? TextureHandle : T extends "geometry" ? Geometry : T extends "points" ? PointSet : T extends "lines" ? LineSegments : T extends "polyline" ? Polyline : T extends "mesh" ? Mesh : T extends "rects" ? Rects : T extends "asset" ? AssetRef : T extends "array" ? readonly unknown[] : T extends "object" ? Readonly<Record<string, unknown>> : unknown;
100
- export type SerializableValueForType<T extends CascadeType> = T extends "texture" ? never : T extends "geometry" ? GeometrySerialized : T extends "array" ? readonly JsonValue[] : T extends "object" ? Readonly<Record<string, JsonValue>> : T extends "any" | NamespacedType ? JsonValue : ValueForType<T>;
99
+ export type ValueForType<T extends CascadeType> = T extends "float" | "int" ? number : T extends "bool" ? boolean : T extends "string" ? string : T extends "vec2" ? Vec2 : T extends "vec3" ? Vec3 : T extends "vec4" ? Vec4 : T extends "vec2i" ? Vec2i : T extends "vec3i" ? Vec3i : T extends "vec4i" ? Vec4i : T extends "mat2" ? Mat2 : T extends "mat3" ? Mat3 : T extends "mat4" ? Mat4 : T extends "color" ? Color : T extends "camera" ? Camera : T extends "scene" ? Scene : T extends "light" ? Light : T extends "image" ? ImageRef : T extends "texture" ? TextureHandle : T extends "geometry" ? Geometry : T extends "points" ? PointSet : T extends "lines" ? LineSegments : T extends "polyline" ? Polyline : T extends "mesh" ? Mesh : T extends "rects" ? Rects : T extends "asset" ? AssetRef : T extends "array" ? readonly unknown[] : T extends "object" | "bundle" ? Readonly<Record<string, unknown>> : unknown;
100
+ export type SerializableValueForType<T extends CascadeType> = T extends "texture" ? never : T extends "geometry" ? GeometrySerialized : T extends "array" ? readonly JsonValue[] : T extends "object" | "bundle" ? Readonly<Record<string, JsonValue>> : T extends "any" | NamespacedType ? JsonValue : ValueForType<T>;
101
101
  export {};
102
102
  //# sourceMappingURL=values.d.ts.map
@@ -27,6 +27,7 @@ export const CORE_TYPES = [
27
27
  "asset",
28
28
  "array",
29
29
  "object",
30
+ "bundle",
30
31
  "any",
31
32
  ];
32
33
  const TYPE_ALIASES = {
package/dist/index.html CHANGED
@@ -3,12 +3,14 @@
3
3
  <head>
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <!-- Pinterest browser extension: no Save buttons over canvases and previews -->
7
+ <meta name="pinterest" content="nopin">
6
8
  <title>Cascade</title>
7
- <script type="module" crossorigin src="/assets/index-CnylT98t.js"></script>
8
- <link rel="modulepreload" crossorigin href="/assets/legacy-CAj2_7QE.js">
9
- <link rel="modulepreload" crossorigin href="/assets/index-client-BoJgsN9M.js">
9
+ <script type="module" crossorigin src="/assets/index-DyvDC6pS.js"></script>
10
+ <link rel="modulepreload" crossorigin href="/assets/legacy-CTEeXeqF.js">
11
+ <link rel="modulepreload" crossorigin href="/assets/index-client-DqYmKstU.js">
10
12
  <link rel="modulepreload" crossorigin href="/assets/nodeTypeUtils-BDJsc2Ks.js">
11
- <link rel="stylesheet" crossorigin href="/assets/index-ilgbOu6G.css">
13
+ <link rel="stylesheet" crossorigin href="/assets/index-7vae6YFC.css">
12
14
  </head>
13
15
  <body>
14
16
  <div id="app"></div>
@@ -474,7 +474,7 @@ var BrowserPlayer = class {
474
474
  }
475
475
  if (typeof value === "string") {
476
476
  return new Blob([value], {
477
- type: value.trimStart().startsWith("<svg") ? "image/svg+xml" : "text/plain;charset=utf-8"
477
+ type: isSvgText(value) ? "image/svg+xml" : "text/plain;charset=utf-8"
478
478
  });
479
479
  }
480
480
  if ((isGeometry(value) || isScene(value)) && this.displayedElement instanceof HTMLCanvasElement)
@@ -572,7 +572,7 @@ var BrowserPlayer = class {
572
572
  let next;
573
573
  let nextRelease;
574
574
  const asset = isAssetRef(value) ? value : void 0;
575
- if (asset || typeof value === "string" && value.trimStart().startsWith("<svg")) {
575
+ if (asset || isSvgText(value)) {
576
576
  let url;
577
577
  if (asset) {
578
578
  const lease = await this.context.assets.resolveUrl(asset);
@@ -692,13 +692,13 @@ function createUi(hostDocument, root) {
692
692
  root.append(toolbar, error, output);
693
693
  return { play, frame, error, output };
694
694
  }
695
- function renderSceneCanvas(hostDocument, scene, width, height) {
695
+ function renderSceneCanvas(hostDocument, scene, width, height, stroke = [1, 1, 1, 1]) {
696
696
  let canvas;
697
697
  const camera = scene.camera ?? fitCamera(scene, width, height);
698
698
  renderScene(scene.geometry, {
699
699
  camera,
700
700
  size: [width, height],
701
- stroke: [1, 1, 1, 1],
701
+ stroke: [...stroke],
702
702
  strokeWidth: 1,
703
703
  opacity: 1,
704
704
  pointRadius: 1,
@@ -753,7 +753,7 @@ function preferredOutput(result) {
753
753
  for (const [nodeId, outputs] of result.outputs) {
754
754
  for (const [port, value] of outputs) {
755
755
  fallback = { nodeId, port };
756
- if (isAssetRef(value) || isScene(value) || isGeometry(value) || typeof value === "string" && value.trimStart().startsWith("<svg"))
756
+ if (isAssetRef(value) || isScene(value) || isGeometry(value) || isSvgText(value))
757
757
  preferred = { nodeId, port };
758
758
  }
759
759
  }
@@ -805,6 +805,18 @@ function requireFinite(value, label) {
805
805
  function asError(value) {
806
806
  return value instanceof Error ? value : new Error(String(value));
807
807
  }
808
+ function isSvgText(value) {
809
+ return typeof value === "string" && /^\s*(?:<\?xml[^>]*>\s*)?(?:<!--[\s\S]*?-->\s*|<!DOCTYPE[^>]*>\s*)*<svg[\s>]/i.test(value.slice(0, 2e3));
810
+ }
808
811
  export {
812
+ asError,
813
+ canvasBlob,
814
+ cleanupAll,
815
+ isAssetRef,
816
+ isGeometry,
817
+ isImageAsset,
818
+ isSvgText,
819
+ jsonReplacer,
820
+ renderSceneCanvas,
809
821
  startPlayer
810
822
  };