@defold-typescript/types 0.23.0 → 0.24.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defold-typescript/types",
3
- "version": "0.23.0",
3
+ "version": "0.24.0",
4
4
  "description": "TypeScript types for the Defold engine's Lua APIs.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -22,6 +22,8 @@ export const PACKAGE_SIGNATURES_PATH = resolve(import.meta.dir, "..", "signature
22
22
  export const BASE_SIGNATURES_PATH = resolve(import.meta.dir, "..", "signatures", "base.json");
23
23
  export const SOCKET_SIGNATURES_PATH = resolve(import.meta.dir, "..", "signatures", "socket.json");
24
24
  export const VMATH_SIGNATURES_PATH = resolve(import.meta.dir, "..", "signatures", "vmath.json");
25
+ export const GO_SIGNATURES_PATH = resolve(import.meta.dir, "..", "signatures", "go.json");
26
+ export const MSG_SIGNATURES_PATH = resolve(import.meta.dir, "..", "signatures", "msg.json");
25
27
 
26
28
  export function loadSignatureFile(path: string): SignatureStore {
27
29
  let raw: string;
package/src/api-doc.ts CHANGED
@@ -20,12 +20,16 @@ export interface ApiTypedef {
20
20
  name: string;
21
21
  functions?: ApiFunction[];
22
22
  properties?: ApiVariable[];
23
+ /** See {@link ApiFunction.global}. */
24
+ global?: true;
23
25
  }
24
26
 
25
27
  export interface ApiConstant {
26
28
  name: string;
27
29
  brief: string;
28
30
  description: string;
31
+ /** See {@link ApiFunction.global}. */
32
+ global?: true;
29
33
  }
30
34
 
31
35
  export interface ApiFunction {
@@ -41,6 +45,27 @@ export interface ApiFunction {
41
45
  * library functions; engine ref-docs carry no `generics`, so it stays absent.
42
46
  */
43
47
  generics?: string;
48
+ /**
49
+ * Present exactly when the source carried a `@deprecated` tag; `""` for a bare
50
+ * tag. Absence is the only encoding of "not deprecated", so a bare tag stays
51
+ * distinguishable from an untagged symbol.
52
+ */
53
+ deprecated?: string;
54
+ /**
55
+ * Present exactly when the source declared the symbol as an ambient global —
56
+ * outside the library's `declare module` block — so it is reachable without
57
+ * the module import. Absence is the only encoding of "module member"; the key
58
+ * is never written as `false`.
59
+ */
60
+ global?: true;
61
+ /**
62
+ * Present exactly when this symbol's prose was imported from the upstream
63
+ * source rather than written in the declaration — the authored/forked library
64
+ * lane lowers upstream's own LuaDoc summary for a member its fork documents
65
+ * nowhere. Absence is the only encoding of first-party prose, so every engine
66
+ * and hand-authored symbol reads as before.
67
+ */
68
+ docSource?: "upstream";
44
69
  }
45
70
 
46
71
  export interface ApiParameter {
@@ -67,6 +92,30 @@ export interface ApiVariable {
67
92
  brief: string;
68
93
  description: string;
69
94
  types: string[];
95
+ /**
96
+ * True for an optional member of a typedef shape (`clear?: boolean`). Set only
97
+ * when the element carries `is_optional: "True"`, so a module-level engine
98
+ * ref-doc VARIABLE — which never carries the key — leaves it absent.
99
+ */
100
+ isOptional?: boolean;
101
+ /** See {@link ApiFunction.deprecated}. */
102
+ deprecated?: string;
103
+ /** See {@link ApiFunction.global}. */
104
+ global?: true;
105
+ /** See {@link ApiFunction.docSource}. */
106
+ docSource?: "upstream";
107
+ }
108
+
109
+ /** The `{ global }` key to spread onto a parsed element, empty for a module member. */
110
+ function globalKey(element: Record<string, unknown>): { global?: true } {
111
+ return element.global === true ? { global: true } : {};
112
+ }
113
+
114
+ /** The `{ docSource }` key to spread onto a parsed element, empty for first-party
115
+ * prose. Only the one recognised value yields a key: an unknown provenance would
116
+ * otherwise reach a page with no marker the render layer knows how to draw. */
117
+ function docSourceKey(element: Record<string, unknown>): { docSource?: "upstream" } {
118
+ return element.docSource === "upstream" ? { docSource: "upstream" } : {};
70
119
  }
71
120
 
72
121
  export function parseDefoldApiDoc(input: unknown): ApiModule {
@@ -119,6 +168,7 @@ function parseTypedef(element: Record<string, unknown>): ApiTypedef {
119
168
  name: stringOr(element.name, ""),
120
169
  ...(functions.length > 0 ? { functions } : {}),
121
170
  ...(properties.length > 0 ? { properties } : {}),
171
+ ...globalKey(element),
122
172
  };
123
173
  }
124
174
 
@@ -145,6 +195,7 @@ function parseConstant(element: Record<string, unknown>): ApiConstant {
145
195
  name: stringOr(element.name, ""),
146
196
  brief: stringOr(element.brief, ""),
147
197
  description: stringOr(element.description, ""),
198
+ ...globalKey(element),
148
199
  };
149
200
  }
150
201
 
@@ -157,6 +208,9 @@ function parseFunction(element: Record<string, unknown>): ApiFunction {
157
208
  returnValues: parseParameterList(element.returnvalues),
158
209
  examples: stringOr(element.examples, ""),
159
210
  ...(typeof element.generics === "string" ? { generics: element.generics } : {}),
211
+ ...(typeof element.deprecated === "string" ? { deprecated: element.deprecated } : {}),
212
+ ...globalKey(element),
213
+ ...docSourceKey(element),
160
214
  };
161
215
  }
162
216
 
@@ -166,6 +220,10 @@ function parseVariable(element: Record<string, unknown>): ApiVariable {
166
220
  brief: stringOr(element.brief, ""),
167
221
  description: stringOr(element.description, ""),
168
222
  types: parseStringArray(element.types),
223
+ ...(element.is_optional === "True" ? { isOptional: true } : {}),
224
+ ...(typeof element.deprecated === "string" ? { deprecated: element.deprecated } : {}),
225
+ ...globalKey(element),
226
+ ...docSourceKey(element),
169
227
  };
170
228
  }
171
229
 
package/src/core-types.ts CHANGED
@@ -188,6 +188,9 @@ export const DEFOLD_TYPE_MAP: Readonly<Record<string, string>> = {
188
188
  vector4: "Vector4",
189
189
  quaternion: "Quaternion",
190
190
  matrix4: "Matrix4",
191
+ // Authored-README shorthand for `vmath.matrix4`; absent from every engine
192
+ // ref-doc, which a core-types.test.ts guard keeps true as releases import.
193
+ matrix: "Matrix4",
191
194
  "vmath.vector3": "Vector3",
192
195
  "vmath.vector4": "Vector4",
193
196
  "vmath.matrix4": "Matrix4",
@@ -107,6 +107,10 @@ export function examplesHtmlToMarkdown(html: string): string {
107
107
 
108
108
  export interface DocCommentParts {
109
109
  summary: string;
110
+ // Present exactly when the source carried a deprecation tag; `""` is the bare
111
+ // form and still renders, so this is tested against `undefined` rather than for
112
+ // truthiness the way the other optional parts are.
113
+ deprecated?: string;
110
114
  params?: { name: string; doc: string }[];
111
115
  returns?: string;
112
116
  example?: string;
@@ -122,8 +126,15 @@ export function renderDocComment(parts: DocCommentParts): string[] {
122
126
  const params = (parts.params ?? []).filter((p) => p.doc.trim() !== "");
123
127
  const returns = parts.returns?.trim() ? parts.returns : "";
124
128
  const example = parts.example?.trim() ? parts.example : "";
125
-
126
- if (summaryLines.length === 0 && params.length === 0 && returns === "" && example === "") {
129
+ const deprecated = parts.deprecated;
130
+
131
+ if (
132
+ summaryLines.length === 0 &&
133
+ params.length === 0 &&
134
+ returns === "" &&
135
+ example === "" &&
136
+ deprecated === undefined
137
+ ) {
127
138
  return [];
128
139
  }
129
140
 
@@ -132,11 +143,18 @@ export function renderDocComment(parts: DocCommentParts): string[] {
132
143
  lines.push(line === "" ? " *" : ` * ${line}`);
133
144
  }
134
145
 
135
- const hasTags = params.length > 0 || returns !== "" || example !== "";
146
+ const hasTags = deprecated !== undefined || params.length > 0 || returns !== "" || example !== "";
136
147
  if (summaryLines.length > 0 && hasTags) {
137
148
  lines.push(" *");
138
149
  }
139
150
 
151
+ if (deprecated !== undefined) {
152
+ const [first, ...rest] = deprecated.split("\n");
153
+ lines.push(first === "" ? " * @deprecated" : ` * @deprecated ${first}`);
154
+ for (const line of rest) {
155
+ lines.push(line === "" ? " *" : ` * ${line}`);
156
+ }
157
+ }
140
158
  for (const param of params) {
141
159
  const [first, ...rest] = param.doc.split("\n");
142
160
  lines.push(` * @param ${param.name} - ${first}`);
@@ -29,7 +29,15 @@ export function varargElementType(mapped: string): string {
29
29
  return needsArrayParens(mapped) ? `(${mapped})[]` : `${mapped}[]`;
30
30
  }
31
31
 
32
- /** Wrap `>1` mapped return tokens in the `LuaMultiReturn<[...]>` tuple form. */
33
- export function luaMultiReturn(mapped: readonly string[]): string {
34
- return `LuaMultiReturn<[${mapped.join(", ")}]>`;
32
+ /**
33
+ * Wrap `>1` mapped return tokens in the `LuaMultiReturn<[...]>` tuple form. With
34
+ * `restTail`, the last element renders as a rest element — the shape a LuaLS
35
+ * multi-return whose final value is a bare vararg (`fun(): T, ...`) calls for.
36
+ */
37
+ export function luaMultiReturn(mapped: readonly string[], restTail = false): string {
38
+ const elements =
39
+ restTail && mapped.length > 0
40
+ ? [...mapped.slice(0, -1), `...${varargElementType(mapped[mapped.length - 1] as string)}`]
41
+ : mapped;
42
+ return `LuaMultiReturn<[${elements.join(", ")}]>`;
35
43
  }
package/src/script-api.ts CHANGED
@@ -27,6 +27,17 @@ function stringOr(value: unknown, fallback: string): string {
27
27
  return typeof value === "string" ? value : fallback;
28
28
  }
29
29
 
30
+ // A `.script_api` `type:` may spell a union inline (`string | nil`), where the
31
+ // core ref-doc format carries one token per alternative. Splitting here keeps the
32
+ // downstream emitter and fidelity resolver working in single tokens.
33
+ function splitTypeTokens(type: unknown): string[] {
34
+ if (typeof type !== "string") return [];
35
+ return type
36
+ .split("|")
37
+ .map((token) => token.trim())
38
+ .filter((token) => token.length > 0);
39
+ }
40
+
30
41
  function mapParameters(raw: unknown): RefDocParameter[] {
31
42
  if (!Array.isArray(raw)) return [];
32
43
  const out: RefDocParameter[] = [];
@@ -36,11 +47,10 @@ function mapParameters(raw: unknown): RefDocParameter[] {
36
47
  // The script_api lists the implicit `self` the engine passes; the emitter
37
48
  // stamps @noSelfInFile, so generated signatures must not declare it.
38
49
  if (name === "self") continue;
39
- const type = item.type;
40
50
  out.push({
41
51
  name,
42
52
  doc: stringOr(item.desc, ""),
43
- types: typeof type === "string" ? [type] : [],
53
+ types: splitTypeTokens(item.type),
44
54
  });
45
55
  }
46
56
  return out;