@defold-typescript/types 0.39.0 → 0.41.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 (227) hide show
  1. package/api-availability.json +4024 -716
  2. package/api-migrations.json +27 -0
  3. package/api-signatures.json +18118 -10264
  4. package/api-targets.json +448 -11
  5. package/examples/translations.json +619 -148
  6. package/fixtures/messages_doc.json +96 -0
  7. package/generated/b2d.d.ts +680 -4
  8. package/generated/b2d_body.d.ts +29 -103
  9. package/generated/b2d_chain.d.ts +5 -6
  10. package/generated/b2d_fixture.d.ts +34 -38
  11. package/generated/b2d_joint.d.ts +503 -25
  12. package/generated/b2d_shape.d.ts +199 -14
  13. package/generated/b2d_world.d.ts +57 -63
  14. package/generated/buffer.d.ts +33 -29
  15. package/generated/builtin-messages.d.ts +7 -1
  16. package/generated/bullet3d.d.ts +91 -0
  17. package/generated/bullet3d_collision_object.d.ts +433 -0
  18. package/generated/bullet3d_constraint.d.ts +818 -0
  19. package/generated/bullet3d_rigid_body.d.ts +429 -0
  20. package/generated/bullet3d_shape.d.ts +123 -0
  21. package/generated/bullet3d_world.d.ts +492 -0
  22. package/generated/camera.d.ts +31 -34
  23. package/generated/collectionfactory.d.ts +26 -27
  24. package/generated/collectionproxy.d.ts +22 -6
  25. package/generated/compute.d.ts +12 -238
  26. package/generated/crash.d.ts +24 -10
  27. package/generated/editor-vm/http.d.ts +90 -7
  28. package/generated/editor-vm/image.d.ts +7 -7
  29. package/generated/editor-vm/json.d.ts +11 -0
  30. package/generated/editor-vm/localization.d.ts +7 -7
  31. package/generated/editor-vm/tilemap_tiles.d.ts +56 -10
  32. package/generated/editor-vm/zip.d.ts +28 -0
  33. package/generated/editor.d.ts +1496 -430
  34. package/generated/factory.d.ts +21 -25
  35. package/generated/font.d.ts +64 -22
  36. package/generated/go.d.ts +243 -186
  37. package/generated/graphics.d.ts +374 -84
  38. package/generated/gui.d.ts +282 -492
  39. package/generated/html5.d.ts +5 -3
  40. package/generated/http.d.ts +31 -36
  41. package/generated/image.d.ts +127 -85
  42. package/generated/json.d.ts +34 -16
  43. package/generated/kinds/gui-script.d.ts +8 -0
  44. package/generated/kinds/render-script.d.ts +8 -0
  45. package/generated/kinds/script.d.ts +8 -0
  46. package/generated/label.d.ts +77 -7
  47. package/generated/liveupdate.d.ts +13 -10
  48. package/generated/material.d.ts +312 -360
  49. package/generated/model.d.ts +72 -42
  50. package/generated/particlefx.d.ts +19 -28
  51. package/generated/physics.d.ts +378 -144
  52. package/generated/profiler.d.ts +14 -24
  53. package/generated/render.d.ts +294 -297
  54. package/generated/resource.d.ts +753 -641
  55. package/generated/socket.d.ts +131 -134
  56. package/generated/sound.d.ts +65 -34
  57. package/generated/sprite.d.ts +39 -17
  58. package/generated/sys.d.ts +237 -182
  59. package/generated/tilemap.d.ts +21 -16
  60. package/generated/timer.d.ts +34 -21
  61. package/generated/versions/defold-1.12.4/b2d_body.d.ts +0 -7
  62. package/generated/versions/defold-1.12.4/buffer.d.ts +18 -17
  63. package/generated/versions/defold-1.12.4/camera.d.ts +23 -23
  64. package/generated/versions/defold-1.12.4/collectionfactory.d.ts +21 -19
  65. package/generated/versions/defold-1.12.4/collectionproxy.d.ts +2 -2
  66. package/generated/versions/defold-1.12.4/crash.d.ts +2 -2
  67. package/generated/versions/defold-1.12.4/factory.d.ts +15 -16
  68. package/generated/versions/defold-1.12.4/go.d.ts +15 -17
  69. package/generated/versions/defold-1.12.4/gui.d.ts +111 -193
  70. package/generated/versions/defold-1.12.4/html5.d.ts +4 -2
  71. package/generated/versions/defold-1.12.4/http.d.ts +4 -15
  72. package/generated/versions/defold-1.12.4/image.d.ts +38 -46
  73. package/generated/versions/defold-1.12.4/index.d.ts +2 -0
  74. package/generated/versions/defold-1.12.4/json.d.ts +10 -6
  75. package/generated/versions/defold-1.12.4/label.d.ts +2 -3
  76. package/generated/versions/defold-1.12.4/liveupdate.d.ts +5 -3
  77. package/generated/versions/defold-1.12.4/model.d.ts +34 -13
  78. package/generated/versions/defold-1.12.4/particlefx.d.ts +2 -5
  79. package/generated/versions/defold-1.12.4/physics.d.ts +82 -78
  80. package/generated/versions/defold-1.12.4/profiler.d.ts +3 -6
  81. package/generated/versions/defold-1.12.4/render.d.ts +160 -132
  82. package/generated/versions/defold-1.12.4/resource.d.ts +212 -209
  83. package/generated/versions/defold-1.12.4/socket.d.ts +45 -61
  84. package/generated/versions/defold-1.12.4/sound.d.ts +11 -11
  85. package/generated/versions/defold-1.12.4/sprite.d.ts +24 -6
  86. package/generated/versions/defold-1.12.4/sys.d.ts +45 -68
  87. package/generated/versions/defold-1.12.4/tilemap.d.ts +18 -11
  88. package/generated/versions/defold-1.12.4/timer.d.ts +5 -3
  89. package/generated/versions/defold-1.12.4/vmath.d.ts +5 -26
  90. package/generated/versions/defold-1.12.4/window.d.ts +1 -16
  91. package/generated/versions/defold-1.13.0/b2d_body.d.ts +10 -55
  92. package/generated/versions/defold-1.13.0/b2d_fixture.d.ts +25 -25
  93. package/generated/versions/defold-1.13.0/b2d_shape.d.ts +188 -5
  94. package/generated/versions/defold-1.13.0/b2d_world.d.ts +16 -10
  95. package/generated/versions/defold-1.13.0/buffer.d.ts +18 -17
  96. package/generated/versions/defold-1.13.0/camera.d.ts +27 -27
  97. package/generated/versions/defold-1.13.0/collectionfactory.d.ts +21 -19
  98. package/generated/versions/defold-1.13.0/collectionproxy.d.ts +2 -2
  99. package/generated/versions/defold-1.13.0/compute.d.ts +1 -70
  100. package/generated/versions/defold-1.13.0/crash.d.ts +2 -2
  101. package/generated/versions/defold-1.13.0/editor-vm/tilemap_tiles.d.ts +3 -3
  102. package/generated/versions/defold-1.13.0/editor.d.ts +34 -24
  103. package/generated/versions/defold-1.13.0/factory.d.ts +15 -16
  104. package/generated/versions/defold-1.13.0/go.d.ts +15 -17
  105. package/generated/versions/defold-1.13.0/graphics.d.ts +121 -37
  106. package/generated/versions/defold-1.13.0/gui.d.ts +111 -193
  107. package/generated/versions/defold-1.13.0/html5.d.ts +4 -2
  108. package/generated/versions/defold-1.13.0/http.d.ts +4 -15
  109. package/generated/versions/defold-1.13.0/image.d.ts +38 -46
  110. package/generated/versions/defold-1.13.0/index.d.ts +2 -0
  111. package/generated/versions/defold-1.13.0/json.d.ts +10 -6
  112. package/generated/versions/defold-1.13.0/label.d.ts +2 -3
  113. package/generated/versions/defold-1.13.0/liveupdate.d.ts +7 -5
  114. package/generated/versions/defold-1.13.0/material.d.ts +69 -107
  115. package/generated/versions/defold-1.13.0/model.d.ts +34 -13
  116. package/generated/versions/defold-1.13.0/particlefx.d.ts +2 -5
  117. package/generated/versions/defold-1.13.0/physics.d.ts +82 -78
  118. package/generated/versions/defold-1.13.0/profiler.d.ts +3 -6
  119. package/generated/versions/defold-1.13.0/render.d.ts +160 -132
  120. package/generated/versions/defold-1.13.0/resource.d.ts +217 -210
  121. package/generated/versions/defold-1.13.0/socket.d.ts +45 -61
  122. package/generated/versions/defold-1.13.0/sound.d.ts +11 -11
  123. package/generated/versions/defold-1.13.0/sprite.d.ts +24 -6
  124. package/generated/versions/defold-1.13.0/sys.d.ts +45 -68
  125. package/generated/versions/defold-1.13.0/tilemap.d.ts +18 -11
  126. package/generated/versions/defold-1.13.0/timer.d.ts +5 -3
  127. package/generated/versions/defold-1.13.0/vmath.d.ts +5 -26
  128. package/generated/versions/defold-1.13.0/window.d.ts +1 -16
  129. package/generated/versions/defold-1.13.1/b2d.d.ts +33 -0
  130. package/generated/versions/defold-1.13.1/b2d_body.d.ts +636 -0
  131. package/generated/versions/defold-1.13.1/b2d_chain.d.ts +106 -0
  132. package/generated/versions/defold-1.13.1/b2d_fixture.d.ts +157 -0
  133. package/generated/versions/defold-1.13.1/b2d_joint.d.ts +823 -0
  134. package/generated/versions/defold-1.13.1/b2d_shape.d.ts +400 -0
  135. package/generated/versions/defold-1.13.1/b2d_world.d.ts +320 -0
  136. package/generated/versions/defold-1.13.1/buffer.d.ts +189 -0
  137. package/generated/versions/defold-1.13.1/camera.d.ts +303 -0
  138. package/generated/versions/defold-1.13.1/collectionfactory.d.ts +151 -0
  139. package/generated/versions/defold-1.13.1/collectionproxy.d.ts +93 -0
  140. package/generated/versions/defold-1.13.1/compute.d.ts +237 -0
  141. package/generated/versions/defold-1.13.1/crash.d.ts +143 -0
  142. package/generated/versions/defold-1.13.1/editor-vm/http.d.ts +56 -0
  143. package/generated/versions/defold-1.13.1/editor-vm/image.d.ts +48 -0
  144. package/generated/versions/defold-1.13.1/editor-vm/json.d.ts +10 -0
  145. package/generated/versions/defold-1.13.1/editor-vm/localization.d.ts +42 -0
  146. package/generated/versions/defold-1.13.1/editor-vm/tilemap_tiles.d.ts +80 -0
  147. package/generated/versions/defold-1.13.1/editor-vm/zip.d.ts +10 -0
  148. package/generated/versions/defold-1.13.1/editor-vm/zlib.d.ts +24 -0
  149. package/generated/versions/defold-1.13.1/editor.d.ts +1121 -0
  150. package/generated/versions/defold-1.13.1/factory.d.ts +124 -0
  151. package/generated/versions/defold-1.13.1/font.d.ts +81 -0
  152. package/generated/versions/defold-1.13.1/go.d.ts +1107 -0
  153. package/generated/versions/defold-1.13.1/graphics.d.ts +411 -0
  154. package/generated/versions/defold-1.13.1/gui.d.ts +2353 -0
  155. package/generated/versions/defold-1.13.1/html5.d.ts +55 -0
  156. package/generated/versions/defold-1.13.1/http.d.ts +77 -0
  157. package/generated/versions/defold-1.13.1/image.d.ts +131 -0
  158. package/generated/versions/defold-1.13.1/index.d.ts +57 -0
  159. package/generated/versions/defold-1.13.1/json.d.ts +80 -0
  160. package/generated/versions/defold-1.13.1/kinds/editor-script.d.ts +14 -0
  161. package/generated/versions/defold-1.13.1/label.d.ts +93 -0
  162. package/generated/versions/defold-1.13.1/liveupdate.d.ts +142 -0
  163. package/generated/versions/defold-1.13.1/material.d.ts +408 -0
  164. package/generated/versions/defold-1.13.1/model.d.ts +272 -0
  165. package/generated/versions/defold-1.13.1/msg.d.ts +10 -0
  166. package/generated/versions/defold-1.13.1/particlefx.d.ts +163 -0
  167. package/generated/versions/defold-1.13.1/physics.d.ts +559 -0
  168. package/generated/versions/defold-1.13.1/profiler.d.ts +235 -0
  169. package/generated/versions/defold-1.13.1/render.d.ts +1190 -0
  170. package/generated/versions/defold-1.13.1/resource.d.ts +1523 -0
  171. package/generated/versions/defold-1.13.1/socket.d.ts +784 -0
  172. package/generated/versions/defold-1.13.1/sound.d.ts +292 -0
  173. package/generated/versions/defold-1.13.1/sprite.d.ts +175 -0
  174. package/generated/versions/defold-1.13.1/sys.d.ts +678 -0
  175. package/generated/versions/defold-1.13.1/tilemap.d.ts +208 -0
  176. package/generated/versions/defold-1.13.1/timer.d.ts +125 -0
  177. package/generated/versions/defold-1.13.1/types.d.ts +61 -0
  178. package/generated/versions/defold-1.13.1/vmath.d.ts +774 -0
  179. package/generated/versions/defold-1.13.1/window.d.ts +183 -0
  180. package/generated/versions/defold-1.13.1/zlib.d.ts +41 -0
  181. package/generated/vmath.d.ts +6 -26
  182. package/generated/window.d.ts +71 -71
  183. package/identity-vocabulary.json +561 -0
  184. package/index.d.ts +8 -0
  185. package/package.json +13 -2
  186. package/scripts/example-store-io.ts +12 -1
  187. package/scripts/extension-goldens.ts +1 -0
  188. package/scripts/fidelity-baseline.json +146 -46
  189. package/scripts/generate-api-availability.ts +90 -12
  190. package/scripts/generate-api-signatures.ts +14 -3
  191. package/scripts/import-defold-release.ts +85 -24
  192. package/scripts/prose-constants.ts +157 -0
  193. package/scripts/regen.ts +396 -78
  194. package/scripts/shared-handle-methods.ts +53 -0
  195. package/scripts/signature-store-fs.ts +1 -0
  196. package/scripts/sync-api-docs.ts +16 -5
  197. package/src/api-availability.ts +0 -0
  198. package/src/api-doc.ts +201 -3
  199. package/src/api-identity.ts +252 -0
  200. package/src/component-properties.d.ts +33 -0
  201. package/src/core-types.ts +28 -3
  202. package/src/correction-pins.ts +49 -0
  203. package/src/custom-messages.d.ts +4 -3
  204. package/src/doc-comment.ts +139 -23
  205. package/src/doc-corrections.ts +108 -0
  206. package/src/editor-vm-globals.d.ts +5 -2
  207. package/src/emit-dts.ts +2474 -281
  208. package/src/emit-messages.ts +52 -0
  209. package/src/engine-globals.d.ts +2 -2
  210. package/src/example-store.ts +125 -14
  211. package/src/field-correction-coverage.ts +204 -0
  212. package/src/fnv1a.ts +16 -0
  213. package/src/go-overloads.d.ts +33 -13
  214. package/src/index-base-table.ts +145 -0
  215. package/src/index-slot-classifications.ts +588 -0
  216. package/src/index.ts +39 -2
  217. package/src/library-index-slot-classifications.ts +332 -0
  218. package/src/lifecycle.ts +61 -199
  219. package/src/luals-type-expr.ts +354 -0
  220. package/src/msg-overloads.d.ts +0 -1
  221. package/src/param-correction-provenance.ts +64 -0
  222. package/src/return-correction-provenance.ts +58 -16
  223. package/src/script-api.ts +3 -1
  224. package/src/sys-overloads.d.ts +48 -0
  225. package/src/vmath-overloads.d.ts +27 -1
  226. package/src/window-event-guard.d.ts +6 -9
  227. package/url-parameters.json +1 -2
@@ -85,6 +85,58 @@ export function applyMessageDeprecations(
85
85
  return { entries };
86
86
  }
87
87
 
88
+ // A payload field whose documented type the engine refuses, with the type it
89
+ // takes instead. `upstream` is the documented type the correction replaces:
90
+ // once the catalog stops declaring it the entry throws and is deleted.
91
+ export interface MessageFieldCorrection {
92
+ readonly origin: string;
93
+ readonly name: string;
94
+ readonly field: string;
95
+ readonly types: readonly string[];
96
+ readonly upstream: readonly string[];
97
+ readonly reason: string;
98
+ }
99
+
100
+ // Demonstrated by the engine probe only: each entry is a payload the running
101
+ // engine rejected when it held the documented type.
102
+ export const MESSAGE_FIELD_CORRECTIONS: readonly MessageFieldCorrection[] = [
103
+ {
104
+ origin: "camera",
105
+ name: "set_camera",
106
+ field: "orthographic_projection",
107
+ types: ["number"],
108
+ upstream: ["boolean"],
109
+ reason:
110
+ "the engine decodes the payload into a number field and raises `number expected, got boolean` for the documented boolean",
111
+ },
112
+ ];
113
+
114
+ export function applyMessageFieldCorrections(
115
+ catalog: MessageCatalog,
116
+ overlay: readonly MessageFieldCorrection[] = MESSAGE_FIELD_CORRECTIONS,
117
+ ): MessageCatalog {
118
+ const entries = catalog.entries.map((entry) => ({
119
+ ...entry,
120
+ payload: entry.payload.map((field) => ({ ...field })),
121
+ }));
122
+ for (const correction of overlay) {
123
+ const field = entries
124
+ .find((entry) => entry.origin === correction.origin && entry.name === correction.name)
125
+ ?.payload.find((candidate) => candidate.name === correction.field);
126
+ const identity = `(origin=${correction.origin}, name=${correction.name}, field=${correction.field})`;
127
+ if (field === undefined) {
128
+ throw new Error(`applyMessageFieldCorrections: no catalog field matches ${identity}`);
129
+ }
130
+ if (field.types.join("|") !== correction.upstream.join("|")) {
131
+ throw new Error(
132
+ `applyMessageFieldCorrections: upstream now declares ${field.types.join("|")} for ${identity}; delete the correction`,
133
+ );
134
+ }
135
+ field.types = [...correction.types];
136
+ }
137
+ return { entries };
138
+ }
139
+
88
140
  const TS_IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
89
141
  const ENGINE_TYPES = [
90
142
  "Hash",
@@ -12,8 +12,8 @@ declare global {
12
12
  function hash<S extends string>(s: S): Core.Hash<S>;
13
13
  /** Render a `Hash` handle as its hexadecimal string. */
14
14
  function hash_to_hex(h: Core.Hash): string;
15
- /** Pretty-print any value to the console for debugging. */
16
- function pprint(v: unknown): void;
15
+ /** Pretty-print any values to the console for debugging. */
16
+ function pprint(...args: unknown[]): void;
17
17
  /**
18
18
  * A typed handle to a resource the engine owns — a GUI node, a texture, a
19
19
  * render target, a physics body, a socket, and so on. You get one back from an
@@ -1,3 +1,7 @@
1
+ import type { ApiModule } from "./api-doc";
2
+ import { htmlToDocText, summaryFor } from "./doc-comment";
3
+ import { fnv1a64 } from "./fnv1a";
4
+
1
5
  // A hand-authored TypeScript translation of one element's ref-doc `@example`,
2
6
  // pinned by a hash of the exact source Lua it replaces. A ref-doc re-pin that
3
7
  // changes the source Lua flips the hash, so a stale translation stops matching
@@ -5,6 +9,10 @@
5
9
  export interface Translation {
6
10
  sourceHash: string;
7
11
  ts: string;
12
+ // The authored replacement for the upstream sentence that introduces this
13
+ // segment. Pinned by the same `sourceHash`, so an upstream rewrite of the
14
+ // example body drops the caption together with the body.
15
+ prose?: string;
8
16
  }
9
17
 
10
18
  // An FQN maps to one translation per distinct example body it carries: an
@@ -17,25 +25,20 @@ export interface Translation {
17
25
  // replacing the entry silently regresses every demoted surface to raw Lua.
18
26
  export type TranslationStore = Record<string, Translation[]>;
19
27
 
20
- const FNV_OFFSET_BASIS = 0xcbf29ce484222325n;
21
- const FNV_PRIME = 0x100000001b3n;
22
- const U64_MASK = 0xffffffffffffffffn;
28
+ // A prose Lua fence deliberately left as Lua, pinned like a translation by the
29
+ // hash of the fence body, with the reason no TypeScript form fits. Keyed the
30
+ // way `proseLuaFences` keys the fence.
31
+ export type ProseLuaKeepStore = Record<string, { sourceHash: string; reason: string }[]>;
23
32
 
24
- // A pure, dependency-free FNV-1a 64-bit hash over the source's UTF-16 code
25
- // units, returned as zero-padded hex. Deliberately node- and Bun-free: this
26
- // module is reachable from `index.ts` (via `emit-dts`), so a `node:crypto` or
27
- // ambient-`Bun` reference here would fail type-checking in every downstream
28
- // consumer that compiles the shipped `src/` graph.
33
+ // The `fnv1a64` hash of an example's source, which must stay node- and Bun-free
34
+ // for the reason given there: this module is reachable from `index.ts` (via
35
+ // `emit-dts`).
29
36
  //
30
37
  // The input is the already-normalized post-`htmlToCodeText` string (per-line
31
38
  // trailing whitespace and surrounding blank lines stripped), so the hash is
32
39
  // independent of trailing whitespace in the original ref-doc HTML.
33
40
  export function hashExampleSource(source: string): string {
34
- let hash = FNV_OFFSET_BASIS;
35
- for (let i = 0; i < source.length; i++) {
36
- hash = ((hash ^ BigInt(source.charCodeAt(i))) * FNV_PRIME) & U64_MASK;
37
- }
38
- return hash.toString(16).padStart(16, "0");
41
+ return fnv1a64(source);
39
42
  }
40
43
 
41
44
  // Return the stored TypeScript body only when the FQN exists and one of its
@@ -60,7 +63,7 @@ export function lookupTranslation(
60
63
  * emitted as several `@example` blocks only when every one of them has an
61
64
  * authored body. A partial resolve would document some of the element's
62
65
  * examples and silently drop the rest, so the caller falls back to the
63
- * whole-blob body instead. An empty hash list is a miss for the same reason —
66
+ * upstream Lua instead. An empty hash list is a miss for the same reason —
64
67
  * it would otherwise report success while documenting nothing.
65
68
  */
66
69
  export function lookupExampleTranslations(
@@ -77,3 +80,111 @@ export function lookupExampleTranslations(
77
80
  }
78
81
  return bodies;
79
82
  }
83
+
84
+ /**
85
+ * The stored body and caption for each of a blob's segments, in the order
86
+ * given, or `null` the moment one of them does not resolve.
87
+ *
88
+ * Same all-or-nothing and empty-list rules as `lookupExampleTranslations`. Each
89
+ * caption is the entry's authored `prose` when it carries one, else the
90
+ * segment's upstream prose.
91
+ */
92
+ export function lookupExampleSegments(
93
+ store: TranslationStore,
94
+ fqn: string,
95
+ segments: readonly { code: string; prose: string }[],
96
+ ): { ts: string; prose: string }[] | null {
97
+ const entries = store[fqn];
98
+ if (!entries || segments.length === 0) return null;
99
+ const resolved: { ts: string; prose: string }[] = [];
100
+ for (const segment of segments) {
101
+ const sourceHash = hashExampleSource(segment.code);
102
+ const entry = entries.find((candidate) => candidate.sourceHash === sourceHash);
103
+ if (!entry) return null;
104
+ resolved.push({ ts: entry.ts, prose: entry.prose ?? segment.prose });
105
+ }
106
+ return resolved;
107
+ }
108
+
109
+ // A fence `htmlToDocText` opened on a line of its own, located by line index:
110
+ // `open` is the opener, `close` the closing ``` line.
111
+ interface DocFence {
112
+ open: number;
113
+ close: number;
114
+ }
115
+
116
+ // The one reader of prose fences, shared by the enumeration and the swap so the
117
+ // body one hashes is the body the other replaces. Every fence is walked, so a
118
+ // closing ``` of a `text` fence is never read as the opener of the next one.
119
+ function luaDocFences(lines: readonly string[]): DocFence[] {
120
+ const fences: DocFence[] = [];
121
+ for (let open = 0; open < lines.length; open += 1) {
122
+ if (!lines[open]?.startsWith("```")) continue;
123
+ let close = open + 1;
124
+ while (close < lines.length && !lines[close]?.startsWith("```")) close += 1;
125
+ if (close >= lines.length) break;
126
+ if (lines[open] === "```lua") fences.push({ open, close });
127
+ open = close;
128
+ }
129
+ return fences;
130
+ }
131
+
132
+ function fenceBody(lines: readonly string[], fence: DocFence): string {
133
+ return lines.slice(fence.open + 1, fence.close).join("\n");
134
+ }
135
+
136
+ /**
137
+ * Swap each ```lua fence in `htmlToDocText` output for the TypeScript pinned
138
+ * under `key` to its body's hash, leaving every other byte alone. A fence with
139
+ * no matching entry stays Lua, the same fallback the `@example` ladder keeps.
140
+ * With `keepSource`, each swapped fence is followed by a blank line and its
141
+ * untouched body as a ```lua original fence, the pairing the API reference
142
+ * renders as TypeScript and Lua tabs.
143
+ */
144
+ export function translateProseFences(
145
+ markdown: string,
146
+ key: string,
147
+ store: TranslationStore,
148
+ options: { keepSource?: boolean } = {},
149
+ ): string {
150
+ if (!store[key]) return markdown;
151
+ const lines = markdown.split("\n");
152
+ const fences = luaDocFences(lines);
153
+ for (const fence of fences.reverse()) {
154
+ const lua = fenceBody(lines, fence);
155
+ const ts = lookupTranslation(store, key, hashExampleSource(lua));
156
+ if (ts === null) continue;
157
+ const source = options.keepSource ? ["", "```lua original", ...lua.split("\n"), "```"] : [];
158
+ lines.splice(
159
+ fence.open,
160
+ fence.close - fence.open + 1,
161
+ "```ts",
162
+ ...ts.split("\n"),
163
+ "```",
164
+ ...source,
165
+ );
166
+ }
167
+ return lines.join("\n");
168
+ }
169
+
170
+ /**
171
+ * Every ```lua fence in the prose a module documents, keyed the way the emit
172
+ * and the API reference look its translation up: the namespace description
173
+ * under the namespace, and a function's summary, parameter and return docs
174
+ * under the function's name.
175
+ */
176
+ export function proseLuaFences(module: ApiModule): { key: string; lua: string }[] {
177
+ const slots: [string, string][] = [
178
+ [module.namespace, summaryFor(module.brief, module.description)],
179
+ ];
180
+ for (const fn of module.functions) {
181
+ slots.push([fn.name, summaryFor(fn.brief, fn.description)]);
182
+ for (const slot of [...fn.parameters, ...fn.returnValues]) slots.push([fn.name, slot.doc]);
183
+ }
184
+ const out: { key: string; lua: string }[] = [];
185
+ for (const [key, html] of slots) {
186
+ const lines = htmlToDocText(html).split("\n");
187
+ for (const fence of luaDocFences(lines)) out.push({ key, lua: fenceBody(lines, fence) });
188
+ }
189
+ return out;
190
+ }
@@ -0,0 +1,204 @@
1
+ import type { ApiFunction, ApiModule, ApiParameter, ApiStruct } from "./api-doc";
2
+ import {
3
+ LIST_FIELD_CORRECTIONS,
4
+ memberCorrectionKey,
5
+ REQUIRED_FIELD_CORRECTIONS,
6
+ RETURN_FIELD_OPTIONALITY_CORRECTIONS,
7
+ } from "./emit-dts";
8
+ import { matchBracket, splitTopLevel } from "./luals-type-expr";
9
+
10
+ // The slot-keyed field corrections are applied to fields recovered from a prose
11
+ // `table` slot. A release that types the slot as a `STRUCT` or an inline record
12
+ // recovers no fields, so each such entry must be stated upstream already or be
13
+ // carried by a member-keyed entry on the struct; anything else would go inert.
14
+ export interface FieldCorrectionTables {
15
+ readonly required: ReadonlyMap<string, unknown>;
16
+ readonly list: ReadonlyMap<string, unknown>;
17
+ readonly optionality: ReadonlyMap<string, unknown>;
18
+ }
19
+
20
+ export const FIELD_CORRECTION_TABLES: FieldCorrectionTables = {
21
+ required: REQUIRED_FIELD_CORRECTIONS,
22
+ list: LIST_FIELD_CORRECTIONS,
23
+ optionality: RETURN_FIELD_OPTIONALITY_CORRECTIONS,
24
+ };
25
+
26
+ export interface FieldCorrectionGap {
27
+ readonly key: string;
28
+ // The struct whose member would carry the correction, when the path reached one.
29
+ readonly struct?: string;
30
+ readonly reason: string;
31
+ }
32
+
33
+ type Kind = keyof FieldCorrectionTables;
34
+
35
+ interface Member {
36
+ readonly name: string;
37
+ readonly type: string;
38
+ readonly optional: boolean;
39
+ }
40
+
41
+ // A slot or member type resolved to the members it declares: a `STRUCT` by name,
42
+ // or an inline `{ name:type, ... }` record.
43
+ interface Shape {
44
+ readonly struct?: string;
45
+ readonly members: readonly Member[];
46
+ }
47
+
48
+ const PROSE_TABLE = "table";
49
+
50
+ function stripList(type: string): string {
51
+ let t = type.trim();
52
+ while (t.endsWith("[]")) t = t.slice(0, -2).trim();
53
+ while (t.startsWith("(") && matchBracket(t, 0) === t.length - 1) t = t.slice(1, -1).trim();
54
+ return t;
55
+ }
56
+
57
+ function recordMembers(record: string): Member[] {
58
+ return splitTopLevel(record.slice(1, -1), ",")
59
+ .map((part) => part.trim())
60
+ .filter((part) => part.length > 0)
61
+ .map((part) => {
62
+ const colon = part.indexOf(":");
63
+ const raw = colon === -1 ? part : part.slice(0, colon).trim();
64
+ const optional = raw.endsWith("?");
65
+ return {
66
+ name: optional ? raw.slice(0, -1) : raw,
67
+ type: colon === -1 ? "" : part.slice(colon + 1).trim(),
68
+ optional,
69
+ };
70
+ });
71
+ }
72
+
73
+ function shapeOf(type: string, structs: ReadonlyMap<string, ApiStruct>): Shape | null {
74
+ const t = stripList(type);
75
+ if (t.startsWith("{") && matchBracket(t, 0) === t.length - 1) {
76
+ return { members: recordMembers(t) };
77
+ }
78
+ const struct = structs.get(t);
79
+ if (struct === undefined) return null;
80
+ return {
81
+ struct: struct.name,
82
+ members: struct.members.map((member) => ({
83
+ name: member.name,
84
+ type: member.type,
85
+ optional: member.isOptional,
86
+ })),
87
+ };
88
+ }
89
+
90
+ function parseKey(key: string): {
91
+ element: string;
92
+ kind: "param" | "return";
93
+ slot: string;
94
+ segments: string[];
95
+ } | null {
96
+ const [element, kind, slot, path, ...rest] = key.split(":");
97
+ if (
98
+ element === undefined ||
99
+ slot === undefined ||
100
+ path === undefined ||
101
+ rest.length > 0 ||
102
+ (kind !== "param" && kind !== "return")
103
+ ) {
104
+ return null;
105
+ }
106
+ return { element, kind, slot, segments: path.split(".").map((s) => s.replace(/\[\]$/, "")) };
107
+ }
108
+
109
+ function slotsNamed(
110
+ overloads: readonly ApiFunction[],
111
+ kind: "param" | "return",
112
+ slot: string,
113
+ ): ApiParameter[] {
114
+ return overloads.flatMap((fn) =>
115
+ (kind === "param" ? fn.parameters : fn.returnValues).filter((p) => p.name === slot),
116
+ );
117
+ }
118
+
119
+ function slotGap(
120
+ key: string,
121
+ table: Kind,
122
+ slotTypes: readonly string[],
123
+ segments: readonly string[],
124
+ structs: ReadonlyMap<string, ApiStruct>,
125
+ tables: FieldCorrectionTables,
126
+ ): FieldCorrectionGap | null {
127
+ const shapes = slotTypes.map((type) => shapeOf(type, structs)).filter((s) => s !== null);
128
+ if (shapes.length === 0) {
129
+ return { key, reason: `slot is typed ${slotTypes.join("|")}, which declares no members` };
130
+ }
131
+ for (const initial of shapes) {
132
+ let shape: Shape = initial;
133
+ for (const [index, name] of segments.entries()) {
134
+ const member = shape.members.find((candidate) => candidate.name === name);
135
+ const struct = shape.struct === undefined ? {} : { struct: shape.struct };
136
+ if (member === undefined) return { key, ...struct, reason: `no member ${name}` };
137
+ if (index < segments.length - 1) {
138
+ const next = shapeOf(member.type, structs);
139
+ if (next === null) {
140
+ return { key, ...struct, reason: `member ${name} is typed ${member.type}` };
141
+ }
142
+ shape = next;
143
+ continue;
144
+ }
145
+ const carried =
146
+ shape.struct !== undefined && tables[table].has(memberCorrectionKey(shape.struct, name));
147
+ const upstream =
148
+ table === "required" ? !member.optional : table === "optionality" ? member.optional : false;
149
+ if (!carried && !upstream) {
150
+ return {
151
+ key,
152
+ ...struct,
153
+ reason: `neither upstream nor a member-keyed ${table} correction states it`,
154
+ };
155
+ }
156
+ }
157
+ }
158
+ return null;
159
+ }
160
+
161
+ /**
162
+ * Every slot-keyed field correction that goes inert on these modules — one
163
+ * target's, after its skip rules, since a slot in `b2d.fixture` can name a struct
164
+ * `b2d` declares. An element the target does not declare, and a slot still typed
165
+ * as a prose `table`, are out of scope and report nothing.
166
+ */
167
+ export function fieldCorrectionGaps(
168
+ modules: readonly ApiModule[],
169
+ tables: FieldCorrectionTables = FIELD_CORRECTION_TABLES,
170
+ ): FieldCorrectionGap[] {
171
+ const structs = new Map(
172
+ modules.flatMap((module) => module.structs ?? []).map((struct) => [struct.name, struct]),
173
+ );
174
+ const functions = modules.flatMap((module) => module.functions);
175
+ const gaps: FieldCorrectionGap[] = [];
176
+ for (const table of ["required", "list", "optionality"] as const) {
177
+ for (const key of tables[table].keys()) {
178
+ const parsed = parseKey(key);
179
+ if (parsed === null) continue;
180
+ const overloads = functions.filter((fn) => fn.name === parsed.element);
181
+ if (overloads.length === 0) continue;
182
+ const slots = slotsNamed(overloads, parsed.kind, parsed.slot);
183
+ if (slots.length === 0) {
184
+ gaps.push({ key, reason: `${parsed.element} declares no ${parsed.kind} ${parsed.slot}` });
185
+ continue;
186
+ }
187
+ for (const slot of slots) {
188
+ if (slot.types.includes(PROSE_TABLE)) continue;
189
+ const gap = slotGap(key, table, slot.types, parsed.segments, structs, tables);
190
+ if (gap !== null) {
191
+ gaps.push(gap);
192
+ break;
193
+ }
194
+ }
195
+ }
196
+ }
197
+ return gaps;
198
+ }
199
+
200
+ export function formatFieldCorrectionGaps(gaps: readonly FieldCorrectionGap[]): string {
201
+ return gaps
202
+ .map((gap) => `${gap.key}${gap.struct === undefined ? "" : ` (${gap.struct})`}: ${gap.reason}`)
203
+ .join("\n");
204
+ }
package/src/fnv1a.ts ADDED
@@ -0,0 +1,16 @@
1
+ const FNV_OFFSET_BASIS = 0xcbf29ce484222325n;
2
+ const FNV_PRIME = 0x100000001b3n;
3
+ const U64_MASK = 0xffffffffffffffffn;
4
+
5
+ // A pure, dependency-free FNV-1a 64-bit hash over the text's UTF-16 code units,
6
+ // returned as zero-padded hex. Deliberately node- and Bun-free: this module is
7
+ // reachable from `index.ts`, so a `node:crypto` or ambient-`Bun` reference here
8
+ // would fail type-checking in every downstream consumer that compiles the
9
+ // shipped `src/` graph.
10
+ export function fnv1a64(text: string): string {
11
+ let hash = FNV_OFFSET_BASIS;
12
+ for (let i = 0; i < text.length; i++) {
13
+ hash = ((hash ^ BigInt(text.charCodeAt(i))) * FNV_PRIME) & U64_MASK;
14
+ }
15
+ return hash.toString(16).padStart(16, "0");
16
+ }
@@ -6,12 +6,26 @@ interface ScriptProperty<TValue> {
6
6
  readonly __defoldScriptProperty: TValue;
7
7
  }
8
8
 
9
+ // True when `A` and `B` are identical, `readonly` modifiers included, which
10
+ // plain assignability ignores.
11
+ type Identical<A, B> =
12
+ (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? true : false;
13
+
14
+ // The keys of `P` a write may name: every key but a `readonly` one, which the
15
+ // engine refuses to set.
16
+ type WritableKey<P> = {
17
+ [K in keyof P]-?: Identical<{ [Q in K]: P[K] }, { -readonly [Q in K]: P[K] }> extends true
18
+ ? K
19
+ : never;
20
+ }[keyof P];
21
+
9
22
  declare global {
10
23
  namespace go {
11
24
  interface GoPropertyOptions {
25
+ /** **⚠️ 1-based index into an array property; passed to Defold unchanged.** */
12
26
  index?: number;
13
- key?: Hash;
14
- keys?: Record<string | number, unknown>;
27
+ key?: Hash | string;
28
+ keys?: (Hash | string)[];
15
29
  }
16
30
 
17
31
  /**
@@ -20,9 +34,9 @@ declare global {
20
34
  * @param url - url of the game object or component having the property
21
35
  * @param property - id of the property to retrieve
22
36
  * @param options - optional options table
23
- * - index number index into array property (1 based)
24
- * - key hash name of internal property
25
- * - keys table array of internal component resources identified by key (e.g. a particle fx emitter, see examples below)
37
+ * - index number **⚠️ 1-based index into an array property; passed to Defold unchanged.**
38
+ * - key hash or string name of internal property
39
+ * - keys array of hashes or strings identifying internal component resources (e.g. a particle fx emitter, see examples below)
26
40
  * @returns the value of the specified property
27
41
  * @example
28
42
  * ```ts
@@ -52,20 +66,21 @@ declare global {
52
66
  *
53
67
  * @param url - url of the game object or component having the property
54
68
  * @param property - id of the property to set
55
- * @param value - the value to set
69
+ * @param value - the value to set, or an array of vector4 to set a material property array
56
70
  * @param options - optional options table
57
- * - index integer index into array property (1 based)
58
- * - key hash name of internal property
59
- * - keys table array of internal component resources identified by key (e.g. a particle fx emitter, see examples below)
71
+ * - index integer **⚠️ 1-based index into an array property; passed to Defold unchanged.**
72
+ * - key hash or string name of internal property
73
+ * - keys array of hashes or strings identifying internal component resources (e.g. a particle fx emitter, see examples below)
60
74
  * @example
61
75
  * ```ts
62
76
  * go.set("#sprite", "tint", vmath.vector4(1, 0, 0, 1));
63
77
  * // Name the target component to gate the value to its property type. The
64
- * // empty call applies the type argument, then the inner call infers the key:
78
+ * // empty call applies the type argument, then the inner call infers the key.
79
+ * // A read-only property such as "animation" is not a key it accepts:
65
80
  * go.set<sprite.properties>()("#sprite", "playback_rate", 2);
66
81
  * ```
67
82
  */
68
- function set<P>(): <K extends keyof P>(
83
+ function set<P>(): <K extends WritableKey<P>>(
69
84
  url: SceneAddress | Hash | Url,
70
85
  property: K,
71
86
  value: P[K],
@@ -80,11 +95,14 @@ declare global {
80
95
  function set(
81
96
  url: SceneAddress | Hash | Url,
82
97
  property: string | Hash,
83
- value: number | boolean | Hash | Url | Vector3 | Vector4 | Quaternion,
98
+ value: number | boolean | Hash | Url | Vector3 | Vector4 | Quaternion | Vector4[],
84
99
  options?: GoPropertyOptions,
85
100
  ): void;
86
101
  /**
87
- * Registers a Defold editor script property (deprecated escape hatch).
102
+ * Registers a script property, which the Defold editor exposes on every game
103
+ * object and collection that uses the script. Defold accepts the call only at
104
+ * the top level of the script, outside callbacks such as `init` and `update`.
105
+ * A `string` default needs Defold 1.13.2 or later.
88
106
  *
89
107
  * @deprecated Don't call `go.property` yourself. Declare the property in
90
108
  * `defineScript({ properties })` — that is the only form that types it onto
@@ -121,5 +139,7 @@ declare global {
121
139
  function property(name: string, value: Vector4): ScriptProperty<Vector4>;
122
140
  /** @deprecated Declare quaternions via the `defineScript({ properties })` field. */
123
141
  function property(name: string, value: Quaternion): ScriptProperty<Quaternion>;
142
+ /** @deprecated Declare text via the `defineScript({ properties })` field; needs Defold 1.13.2. */
143
+ function property(name: string, value: string): ScriptProperty<string>;
124
144
  }
125
145
  }