@defold-typescript/types 0.59.0 → 0.60.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.
@@ -7672,12 +7672,20 @@ function slotList(value) {
7672
7672
  return value.filter(isRecord3);
7673
7673
  return isRecord3(value) ? [value] : [];
7674
7674
  }
7675
+ function slotName(item) {
7676
+ return stringOr3(item.name, "").replace(REQUIRED_SUFFIX, "");
7677
+ }
7678
+ function isBracketed(item) {
7679
+ return BRACKETED_NAME.test(slotName(item));
7680
+ }
7675
7681
  function isFunctionName(name) {
7676
7682
  return name !== "None" && FUNCTION_NAME.test(name);
7677
7683
  }
7678
7684
  function mapSlot(item) {
7685
+ const name = slotName(item);
7686
+ const bracketed = BRACKETED_NAME.exec(name);
7679
7687
  const slot = {
7680
- name: stringOr3(item.name, "").replace(REQUIRED_SUFFIX, ""),
7688
+ name: bracketed ? (bracketed[1] ?? "").trim() : name,
7681
7689
  doc: stringOr3(item.desc, ""),
7682
7690
  types: splitTypeTokens2(item.type)
7683
7691
  };
@@ -7688,18 +7696,15 @@ function mapSlot(item) {
7688
7696
  ];
7689
7697
  if (nested.length > 0)
7690
7698
  slot.fields = nested.map(mapSlot);
7691
- if (item.optional === true)
7699
+ if (item.optional === true || bracketed)
7692
7700
  slot.is_optional = "True";
7693
7701
  return slot;
7694
7702
  }
7703
+ function callSlots(raw) {
7704
+ return slotList(raw).filter((item) => stringOr3(item.name, "") !== "self");
7705
+ }
7695
7706
  function mapParameters(raw) {
7696
- const out = [];
7697
- for (const item of slotList(raw)) {
7698
- if (stringOr3(item.name, "") === "self")
7699
- continue;
7700
- out.push(mapSlot(item));
7701
- }
7702
- return out;
7707
+ return callSlots(raw).map(mapSlot);
7703
7708
  }
7704
7709
  function escapeHtml(text) {
7705
7710
  return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
@@ -7750,17 +7755,27 @@ function scriptApiToRefDoc(parsed) {
7750
7755
  const members = Array.isArray(table.members) ? table.members : [];
7751
7756
  const elements = [];
7752
7757
  const fnElement = (name, member) => {
7758
+ const raw = callSlots(member.parameters ?? member.params ?? member.members);
7759
+ const parameters = raw.map(mapSlot);
7753
7760
  const element = {
7754
7761
  type: "FUNCTION",
7755
7762
  name,
7756
7763
  description: stringOr3(member.desc, ""),
7757
- parameters: mapParameters(member.parameters ?? member.params ?? member.members),
7764
+ parameters,
7758
7765
  returnvalues: mapParameters(member.returns ?? member.return)
7759
7766
  };
7760
7767
  const examples = examplesHtml(member.examples);
7761
7768
  if (examples !== "")
7762
7769
  element.examples = examples;
7763
- return element;
7770
+ const omissible = new Set(raw.flatMap((item, index) => isBracketed(item) && parameters.slice(index + 1).some((p) => p.is_optional === undefined) ? [index] : []));
7771
+ if (omissible.size === 0)
7772
+ return [element];
7773
+ const { examples: _examples, ...withoutExamples } = element;
7774
+ const omitted = {
7775
+ ...withoutExamples,
7776
+ parameters: parameters.filter((_, index) => !omissible.has(index))
7777
+ };
7778
+ return [omitted, element];
7764
7779
  };
7765
7780
  const constantElement = (name, member) => ({
7766
7781
  type: "CONSTANT",
@@ -7775,7 +7790,7 @@ function scriptApiToRefDoc(parsed) {
7775
7790
  if (member.type === "function") {
7776
7791
  if (!isFunctionName(stringOr3(member.name, "")))
7777
7792
  continue;
7778
- elements.push(fnElement(`${namespace}.${stringOr3(member.name, "")}`, member));
7793
+ elements.push(...fnElement(`${namespace}.${stringOr3(member.name, "")}`, member));
7779
7794
  continue;
7780
7795
  }
7781
7796
  if (isScalar(member)) {
@@ -7793,7 +7808,7 @@ function scriptApiToRefDoc(parsed) {
7793
7808
  const name = `${namespace}.${sub}.${stringOr3(subMember.name, "")}`;
7794
7809
  if (subMember.type === "function") {
7795
7810
  if (isFunctionName(stringOr3(subMember.name, "")))
7796
- elements.push(fnElement(name, subMember));
7811
+ elements.push(...fnElement(name, subMember));
7797
7812
  } else if (isScalar(subMember)) {
7798
7813
  elements.push(constantElement(name, subMember));
7799
7814
  }
@@ -7809,10 +7824,11 @@ function scriptApiToRefDoc(parsed) {
7809
7824
  function parseScriptApi(yamlText) {
7810
7825
  return scriptApiToRefDoc(parse(yamlText));
7811
7826
  }
7812
- var TYPE_TOKEN_ALIASES, REQUIRED_SUFFIX, FUNCTION_NAME, FENCED_BLOCK;
7827
+ var TYPE_TOKEN_ALIASES, REQUIRED_SUFFIX, BRACKETED_NAME, FUNCTION_NAME, FENCED_BLOCK;
7813
7828
  var init_script_api = __esm(() => {
7814
7829
  TYPE_TOKEN_ALIASES = new Map([["enum", "constant"]]);
7815
7830
  REQUIRED_SUFFIX = /\s*\(required\)$/i;
7831
+ BRACKETED_NAME = /^\[([^[\]]+)\]$/;
7816
7832
  FUNCTION_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
7817
7833
  FENCED_BLOCK = /^```([\w+#.-]*)[^\n]*\n([\s\S]*?)^```[ \t]*$/gm;
7818
7834
  });
@@ -8891,7 +8907,7 @@ var init_regen = __esm(async () => {
8891
8907
  extraModules: ["../../src/editor-overloads", "../../src/editor-vm-globals"],
8892
8908
  factory: "defineEditorScript",
8893
8909
  extraExports: ["defineEditorCommand"],
8894
- extraTypeExports: ["EditorCommandQuery", "EditorNode"],
8910
+ extraTypeExports: ["EditorCommand", "EditorCommandQuery", "EditorNode", "EditorScriptModule"],
8895
8911
  factoryFrom: "../../src/editor",
8896
8912
  propertyTypes: false,
8897
8913
  jit: false
@@ -3,8 +3,7 @@ export type { ApiFunction, ApiModule, ApiParameter, ApiVariable, SkipOverloadRul
3
3
  export { parseDefoldApiDoc, withholdOverloads } from "./api-doc";
4
4
  export { DEFOLD_TYPE_MAP, type Hash, type Matrix4, type Quaternion, type Url, type Vector, type Vector3, type Vector4, } from "./core-types";
5
5
  export { type DocCommentParts, type ExampleSegment, type ExampleSegmentation, examplesHtmlToMarkdown, htmlToCodeText, htmlToDocText, renderDocComment, segmentExampleRegions, splitExampleSources, } from "./doc-comment";
6
- export { defineEditorScript, type EditorCommand, type EditorScriptModule, } from "./editor";
7
- export { type EmitOptions, emitDeclarations, emitSymbolSignatures, firstSlotAlternativeOf, routeTypeDeclarations, type SlotType, type SlotTypes, type SymbolSignature, TS_IDENTIFIER, TS_RESERVED_NAMES, } from "./emit-dts";
6
+ export { type EmitOptions, emitDeclarations, emitSymbolSignatures, firstSlotAlternativeOf, isFunctionTypeText, routeTypeDeclarations, type SlotType, type SlotTypes, type SymbolSignature, TS_IDENTIFIER, TS_RESERVED_NAMES, } from "./emit-dts";
8
7
  export { ENGINE_TYPE_NAME_OVERRIDES, engineTypeName } from "./engine-type-name";
9
8
  export { hashExampleSource, lookupExampleSegments, lookupExampleTranslations, lookupTranslation, proseLuaFences, type Translation, type TranslationStore, translateProseFences, } from "./example-store";
10
9
  export { type EngineIndexBaseRow, engineIndexBaseRows, engineIndexBaseTable, } from "./index-base-table";
@@ -11,4 +11,4 @@ import "../../src/editor-overloads";
11
11
  import "../../src/editor-vm-globals";
12
12
 
13
13
  export { defineEditorScript, defineEditorCommand } from "../../src/editor";
14
- export type { EditorCommandQuery, EditorNode } from "../../src/editor";
14
+ export type { EditorCommand, EditorCommandQuery, EditorNode, EditorScriptModule } from "../../src/editor";
@@ -10,4 +10,4 @@ import "../../../../src/editor-overloads";
10
10
  import "../../../../src/editor-vm-globals";
11
11
 
12
12
  export { defineEditorScript, defineEditorCommand } from "../../../../src/editor";
13
- export type { EditorCommandQuery, EditorNode } from "../../../../src/editor";
13
+ export type { EditorCommand, EditorCommandQuery, EditorNode, EditorScriptModule } from "../../../../src/editor";
@@ -11,4 +11,4 @@ import "../../../../src/editor-overloads";
11
11
  import "../../../../src/editor-vm-globals";
12
12
 
13
13
  export { defineEditorScript, defineEditorCommand } from "../../../../src/editor";
14
- export type { EditorCommandQuery, EditorNode } from "../../../../src/editor";
14
+ export type { EditorCommand, EditorCommandQuery, EditorNode, EditorScriptModule } from "../../../../src/editor";
@@ -11,4 +11,4 @@ import "../../../../src/editor-overloads";
11
11
  import "../../../../src/editor-vm-globals";
12
12
 
13
13
  export { defineEditorScript, defineEditorCommand } from "../../../../src/editor";
14
- export type { EditorCommandQuery, EditorNode } from "../../../../src/editor";
14
+ export type { EditorCommand, EditorCommandQuery, EditorNode, EditorScriptModule } from "../../../../src/editor";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defold-typescript/types",
3
- "version": "0.59.0",
3
+ "version": "0.60.0",
4
4
  "description": "TypeScript types for the Defold engine's Lua APIs.",
5
5
  "license": "MIT",
6
6
  "repository": {
package/scripts/regen.ts CHANGED
@@ -1145,7 +1145,7 @@ export const KIND_MODULE_MANIFEST: readonly KindManifestEntry[] = [
1145
1145
  extraModules: ["../../src/editor-overloads", "../../src/editor-vm-globals"],
1146
1146
  factory: "defineEditorScript",
1147
1147
  extraExports: ["defineEditorCommand"],
1148
- extraTypeExports: ["EditorCommandQuery", "EditorNode"],
1148
+ extraTypeExports: ["EditorCommand", "EditorCommandQuery", "EditorNode", "EditorScriptModule"],
1149
1149
  factoryFrom: "../../src/editor",
1150
1150
  propertyTypes: false,
1151
1151
  jit: false,
package/src/emit-dts.ts CHANGED
@@ -6503,7 +6503,7 @@ function parameterType(
6503
6503
  return added.length === 0 ? kept : `${kept} | ${added.join(" | ")}`;
6504
6504
  }
6505
6505
 
6506
- function isFunctionTypeText(ts: string): boolean {
6506
+ export function isFunctionTypeText(ts: string): boolean {
6507
6507
  let depth = 0;
6508
6508
  for (let i = 0; i < ts.length - 1; i++) {
6509
6509
  const c = ts[i];
package/src/index.ts CHANGED
@@ -50,16 +50,12 @@ export {
50
50
  segmentExampleRegions,
51
51
  splitExampleSources,
52
52
  } from "./doc-comment";
53
- export {
54
- defineEditorScript,
55
- type EditorCommand,
56
- type EditorScriptModule,
57
- } from "./editor";
58
53
  export {
59
54
  type EmitOptions,
60
55
  emitDeclarations,
61
56
  emitSymbolSignatures,
62
57
  firstSlotAlternativeOf,
58
+ isFunctionTypeText,
63
59
  routeTypeDeclarations,
64
60
  type SlotType,
65
61
  type SlotTypes,
package/src/script-api.ts CHANGED
@@ -71,6 +71,18 @@ function slotList(value: unknown): Record<string, unknown>[] {
71
71
  // every slot is already required unless flagged optional, so the suffix is noise.
72
72
  const REQUIRED_SUFFIX = /\s*\(required\)$/i;
73
73
 
74
+ // Upstream writes an omissible slot in call-syntax brackets (`[options]`), the
75
+ // same convention its own `desc` prose uses for an optional argument.
76
+ const BRACKETED_NAME = /^\[([^[\]]+)\]$/;
77
+
78
+ function slotName(item: Record<string, unknown>): string {
79
+ return stringOr(item.name, "").replace(REQUIRED_SUFFIX, "");
80
+ }
81
+
82
+ function isBracketed(item: Record<string, unknown>): boolean {
83
+ return BRACKETED_NAME.test(slotName(item));
84
+ }
85
+
74
86
  // Generators emit placeholder or C-signature names (`None`, `int JoinRandomRoom`)
75
87
  // that cannot form a Lua member access, so no page or declaration can carry them.
76
88
  const FUNCTION_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
@@ -80,8 +92,10 @@ function isFunctionName(name: string): boolean {
80
92
  }
81
93
 
82
94
  function mapSlot(item: Record<string, unknown>): RefDocParameter {
95
+ const name = slotName(item);
96
+ const bracketed = BRACKETED_NAME.exec(name);
83
97
  const slot: RefDocParameter = {
84
- name: stringOr(item.name, "").replace(REQUIRED_SUFFIX, ""),
98
+ name: bracketed ? (bracketed[1] ?? "").trim() : name,
85
99
  doc: stringOr(item.desc, ""),
86
100
  types: splitTypeTokens(item.type),
87
101
  };
@@ -94,19 +108,18 @@ function mapSlot(item: Record<string, unknown>): RefDocParameter {
94
108
  ...slotList(item.members),
95
109
  ];
96
110
  if (nested.length > 0) slot.fields = nested.map(mapSlot);
97
- if (item.optional === true) slot.is_optional = "True";
111
+ if (item.optional === true || bracketed) slot.is_optional = "True";
98
112
  return slot;
99
113
  }
100
114
 
115
+ // The script_api lists the implicit `self` the engine passes; the emitter
116
+ // stamps @noSelfInFile, so generated signatures must not declare it.
117
+ function callSlots(raw: unknown): Record<string, unknown>[] {
118
+ return slotList(raw).filter((item) => stringOr(item.name, "") !== "self");
119
+ }
120
+
101
121
  function mapParameters(raw: unknown): RefDocParameter[] {
102
- const out: RefDocParameter[] = [];
103
- for (const item of slotList(raw)) {
104
- // The script_api lists the implicit `self` the engine passes; the emitter
105
- // stamps @noSelfInFile, so generated signatures must not declare it.
106
- if (stringOr(item.name, "") === "self") continue;
107
- out.push(mapSlot(item));
108
- }
109
- return out;
122
+ return callSlots(raw).map(mapSlot);
110
123
  }
111
124
 
112
125
  function escapeHtml(text: string): string {
@@ -166,7 +179,11 @@ function isScalar(member: Record<string, unknown>): boolean {
166
179
  * present of `parameters:`, `params:` or `members:` and its returns from
167
180
  * `returns:` or `return:`, any slot list may be a single mapping, a table slot's
168
181
  * `members:` nest like `fields:`, a `(REQUIRED)` name suffix is dropped, and a
169
- * function named `None` or not a Lua identifier is skipped.
182
+ * function named `None` or not a Lua identifier is skipped. A slot or field
183
+ * named in brackets (`[options]`) takes the bare name and `is_optional`, and a
184
+ * function with such a slot before a slot that is not optional is also
185
+ * converted, first and without its examples, as a form that leaves out every
186
+ * such bracketed slot.
170
187
  */
171
188
  export function scriptApiToRefDoc(parsed: unknown): RefDoc {
172
189
  if (!Array.isArray(parsed)) {
@@ -188,17 +205,35 @@ export function scriptApiToRefDoc(parsed: unknown): RefDoc {
188
205
  }
189
206
  const members = Array.isArray(table.members) ? table.members : [];
190
207
  const elements: RefDocElement[] = [];
191
- const fnElement = (name: string, member: Record<string, unknown>): RefDocFunctionElement => {
208
+ const fnElement = (name: string, member: Record<string, unknown>): RefDocFunctionElement[] => {
209
+ const raw = callSlots(member.parameters ?? member.params ?? member.members);
210
+ const parameters = raw.map(mapSlot);
192
211
  const element: RefDocFunctionElement = {
193
212
  type: "FUNCTION",
194
213
  name,
195
214
  description: stringOr(member.desc, ""),
196
- parameters: mapParameters(member.parameters ?? member.params ?? member.members),
215
+ parameters,
197
216
  returnvalues: mapParameters(member.returns ?? member.return),
198
217
  };
199
218
  const examples = examplesHtml(member.examples);
200
219
  if (examples !== "") element.examples = examples;
201
- return element;
220
+ // A bracketed slot a required one follows can only be left out by a call
221
+ // that skips it, so that call gets its own form; an explicit
222
+ // `optional: true` slot reads as passable-nil instead and gets none.
223
+ const omissible = new Set(
224
+ raw.flatMap((item, index) =>
225
+ isBracketed(item) && parameters.slice(index + 1).some((p) => p.is_optional === undefined)
226
+ ? [index]
227
+ : [],
228
+ ),
229
+ );
230
+ if (omissible.size === 0) return [element];
231
+ const { examples: _examples, ...withoutExamples } = element;
232
+ const omitted: RefDocFunctionElement = {
233
+ ...withoutExamples,
234
+ parameters: parameters.filter((_, index) => !omissible.has(index)),
235
+ };
236
+ return [omitted, element];
202
237
  };
203
238
  const constantElement = (
204
239
  name: string,
@@ -214,7 +249,7 @@ export function scriptApiToRefDoc(parsed: unknown): RefDoc {
214
249
  if (!isRecord(member)) continue;
215
250
  if (member.type === "function") {
216
251
  if (!isFunctionName(stringOr(member.name, ""))) continue;
217
- elements.push(fnElement(`${namespace}.${stringOr(member.name, "")}`, member));
252
+ elements.push(...fnElement(`${namespace}.${stringOr(member.name, "")}`, member));
218
253
  continue;
219
254
  }
220
255
  if (isScalar(member)) {
@@ -233,7 +268,7 @@ export function scriptApiToRefDoc(parsed: unknown): RefDoc {
233
268
  const name = `${namespace}.${sub}.${stringOr(subMember.name, "")}`;
234
269
  if (subMember.type === "function") {
235
270
  if (isFunctionName(stringOr(subMember.name, "")))
236
- elements.push(fnElement(name, subMember));
271
+ elements.push(...fnElement(name, subMember));
237
272
  } else if (isScalar(subMember)) {
238
273
  elements.push(constantElement(name, subMember));
239
274
  }