@defold-typescript/types 0.23.0 → 0.25.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 (38) hide show
  1. package/api-signatures.json +44 -44
  2. package/api-targets.json +57 -0
  3. package/generated/editor-vm/http.d.ts +56 -0
  4. package/generated/editor-vm/json.d.ts +10 -0
  5. package/generated/editor-vm/localization.d.ts +42 -0
  6. package/generated/editor-vm/tilemap_tiles.d.ts +80 -0
  7. package/generated/editor-vm/zip.d.ts +10 -0
  8. package/generated/editor-vm/zlib.d.ts +24 -0
  9. package/generated/editor.d.ts +1092 -0
  10. package/generated/go.d.ts +22 -22
  11. package/generated/kinds/editor-script.d.ts +13 -0
  12. package/generated/kinds/gui-script.d.ts +1 -0
  13. package/generated/kinds/render-script.d.ts +1 -0
  14. package/generated/kinds/script.d.ts +1 -0
  15. package/generated/versions/defold-1.12.4/go.d.ts +22 -22
  16. package/index.d.ts +6 -0
  17. package/package.json +9 -1
  18. package/scripts/materialize-version.ts +54 -13
  19. package/scripts/regen.ts +425 -42
  20. package/scripts/signature-store-fs.ts +2 -0
  21. package/scripts/sync-api-docs.ts +82 -6
  22. package/src/api-doc.ts +58 -0
  23. package/src/core-types.ts +18 -1
  24. package/src/doc-comment.ts +21 -3
  25. package/src/editor-overloads.d.ts +33 -0
  26. package/src/editor-vm-globals.d.ts +200 -0
  27. package/src/editor-vm-types.ts +44 -0
  28. package/src/editor.ts +117 -16
  29. package/src/emit-dts.ts +292 -79
  30. package/src/engine-globals.d.ts +2 -2
  31. package/src/go-overloads.d.ts +6 -6
  32. package/src/index.ts +12 -0
  33. package/src/library-signature.ts +11 -3
  34. package/src/msg-overloads.d.ts +3 -3
  35. package/src/scene-addresses.d.ts +62 -0
  36. package/src/script-api.ts +12 -2
  37. package/src/url-parameters.ts +174 -0
  38. package/url-parameters.json +285 -0
@@ -24,6 +24,10 @@ export interface SyncManifestEntry {
24
24
  // docs (e.g. `sys`) is reassembled before parse, so the emitter still sees one
25
25
  // fixture, one namespace.
26
26
  readonly mergeEntries?: readonly string[];
27
+ // Extract only this namespace's elements from `zipEntry` and rewrite
28
+ // `info.namespace`. One upstream document that carries several top-level
29
+ // namespaces (the editor apidoc) becomes one fixture per namespace.
30
+ readonly split?: true;
27
31
  }
28
32
 
29
33
  // namespace -> ref-doc.zip entry. Entry paths do not match the namespace (gui ->
@@ -122,7 +126,6 @@ const LUA_NAMESPACE = /^[a-z][a-z0-9]*(\.[a-z][a-z0-9]*)*$/;
122
126
  // `EMPTY_BY_UPSTREAM` allowlist shape). The upstream-coverage guard treats these
123
127
  // as covered. Adding a namespace here is a deliberate, reviewed act.
124
128
  export const IGNORED_UPSTREAM: ReadonlyMap<string, string> = new Map([
125
- ["editor", "editor-scripting API (editor.apidoc), not a runtime game namespace"],
126
129
  ["engine", "CLI/engine env doc, not a runtime Lua namespace"],
127
130
  [
128
131
  "builtins",
@@ -158,6 +161,46 @@ export const LUA_STDLIB_MANIFEST: readonly SyncManifestEntry[] = [
158
161
  entry("package", "doc/lua_package.doc_h_doc.json"),
159
162
  ];
160
163
 
164
+ // The editor-scripting API. It runs in the Defold *editor's* Lua VM, not the
165
+ // game runtime, so it is deliberately not a `MODULE_MANIFEST` citizen: that
166
+ // manifest drives every runtime kind's universal import set, the per-version
167
+ // targets, `api-availability.json` / `api-signatures.json` and the docs-site API
168
+ // pages, none of which describe the editor. It still syncs and emits through the
169
+ // same machinery (`EDITOR_MODULE_MANIFEST` in regen.ts writes
170
+ // `generated/editor.d.ts`), reached only through the `editor-script` kind index.
171
+ export const EDITOR_MANIFEST: readonly SyncManifestEntry[] = [
172
+ entry("editor", "doc/editor.apidoc_doc.json"),
173
+ ];
174
+
175
+ // The non-`editor.*` namespaces the same editor apidoc carries. Each is split
176
+ // out of that one document into its own fixture; the `editor` entry above keeps
177
+ // vendoring the document whole, so `editor_doc.json` is unaffected.
178
+ //
179
+ // Deliberately absent from `COVERAGE_MANIFEST`, `UPSTREAM_MAPPED_NAMESPACES`
180
+ // and `syncedDocs`: these exist only in the editor VM, so marking them mapped
181
+ // would tell the upstream-coverage guard the *runtime* covers `zip`, `pprint`
182
+ // and `tilemap.tiles` and silently suppress a future real miss. Fixture paths
183
+ // are explicit because the default would collide with the unrelated runtime
184
+ // `http_doc.json` / `json_doc.json` / `zlib_doc.json`.
185
+ export const EDITOR_VM_MANIFEST: readonly SyncManifestEntry[] = [
186
+ editorVm("http"),
187
+ editorVm("json"),
188
+ editorVm("localization"),
189
+ editorVm("zip"),
190
+ editorVm("zlib"),
191
+ editorVm("pprint"),
192
+ editorVm("tilemap.tiles"),
193
+ ];
194
+
195
+ function editorVm(namespace: string): SyncManifestEntry {
196
+ return {
197
+ namespace,
198
+ zipEntry: "doc/editor.apidoc_doc.json",
199
+ fixture: `fixtures/defold-${DEFOLD_VERSION}/editor_${namespace.replace(/\./g, "_")}_doc.json`,
200
+ split: true,
201
+ };
202
+ }
203
+
161
204
  function entry(
162
205
  namespace: string,
163
206
  zipEntry: string,
@@ -196,6 +239,21 @@ function ext(namespace: string, repo: string, tag: string, path: string): Extens
196
239
  };
197
240
  }
198
241
 
242
+ // Every vendored fixture set the coverage report audits, and the namespaces it
243
+ // counts as reached from upstream. Composed once here so the `--check` run and
244
+ // the guard over it cannot disagree about which sets are in scope.
245
+ export const COVERAGE_MANIFEST: readonly { readonly namespace: string }[] = [
246
+ ...SYNC_MANIFEST,
247
+ ...EXTENSION_MANIFEST,
248
+ ...EDITOR_MANIFEST,
249
+ ];
250
+
251
+ export const UPSTREAM_MAPPED_NAMESPACES: ReadonlySet<string> = new Set(
252
+ [...SYNC_MANIFEST, ...EXTENSION_MANIFEST, ...LUA_STDLIB_MANIFEST, ...EDITOR_MANIFEST].map(
253
+ (e) => e.namespace,
254
+ ),
255
+ );
256
+
199
257
  export const extensionRawUrl = (e: ExtensionManifestEntry): string =>
200
258
  `https://raw.githubusercontent.com/${e.repo}/${e.tag}/${e.path}`;
201
259
 
@@ -328,6 +386,21 @@ function normalizedArguments(value: unknown): string {
328
386
  );
329
387
  }
330
388
 
389
+ // Segment-wise ownership: `pprint` owns `pprint` and `pprint.x` but never
390
+ // `pprintx`, and `tilemap.tiles` never claims `tilemap.set_tile`.
391
+ function ownsElement(name: string, namespace: string): boolean {
392
+ return name === namespace || name.startsWith(`${namespace}.`);
393
+ }
394
+
395
+ function splitNamespace(contents: string, namespace: string): string {
396
+ const doc = JSON.parse(contents);
397
+ const elements = (Array.isArray(doc.elements) ? doc.elements : []).filter(
398
+ (element: unknown) =>
399
+ isRecord(element) && typeof element.name === "string" && ownsElement(element.name, namespace),
400
+ );
401
+ return JSON.stringify({ ...doc, info: { ...doc.info, namespace }, elements });
402
+ }
403
+
331
404
  export function extractFixtures(
332
405
  zip: ZipAccessor,
333
406
  manifest: readonly SyncManifestEntry[] = SYNC_MANIFEST,
@@ -339,10 +412,11 @@ export function extractFixtures(
339
412
  throw new Error(`zip is missing entry ${source} for namespace ${item.namespace}`);
340
413
  }
341
414
  }
342
- const contents =
415
+ const merged =
343
416
  item.mergeEntries === undefined
344
417
  ? zip.read(item.zipEntry)
345
418
  : JSON.stringify(mergeApiDocs(sources.map((source) => JSON.parse(zip.read(source)))));
419
+ const contents = item.split ? splitNamespace(merged, item.namespace) : merged;
346
420
  return { namespace: item.namespace, fixture: item.fixture, contents };
347
421
  });
348
422
  }
@@ -602,24 +676,26 @@ if (import.meta.main) {
602
676
  const coreFixtures = extractFixtures(zip);
603
677
  const extensionFixtures = await downloadExtensionFixtures();
604
678
  const luaStdlibFixtures = extractFixtures(zip, LUA_STDLIB_MANIFEST);
679
+ const editorFixtures = extractFixtures(zip, EDITOR_MANIFEST);
680
+ const editorVmFixtures = extractFixtures(zip, EDITOR_VM_MANIFEST);
605
681
  const results = [
606
682
  ...syncExtractedFixtures(coreFixtures, { check }),
607
683
  ...syncExtractedFixtures(extensionFixtures, { check }),
608
684
  ...syncExtractedFixtures(luaStdlibFixtures, { check }),
685
+ ...syncExtractedFixtures(editorFixtures, { check }),
686
+ ...syncExtractedFixtures(editorVmFixtures, { check }),
609
687
  ];
610
688
  const syncedDocs = [...coreFixtures, ...extensionFixtures].map((f) => ({
611
689
  namespace: f.namespace,
612
690
  doc: JSON.parse(f.contents),
613
691
  }));
614
692
  const report = buildCoverageReport({
615
- manifest: [...SYNC_MANIFEST, ...EXTENSION_MANIFEST],
693
+ manifest: COVERAGE_MANIFEST,
616
694
  moduleManifest: MODULE_MANIFEST,
617
695
  unmapped: UNMAPPED,
618
696
  syncedDocs,
619
697
  upstream: collectUpstreamNamespaces(zip),
620
- upstreamMapped: new Set(
621
- [...SYNC_MANIFEST, ...EXTENSION_MANIFEST, ...LUA_STDLIB_MANIFEST].map((e) => e.namespace),
622
- ),
698
+ upstreamMapped: UPSTREAM_MAPPED_NAMESPACES,
623
699
  ignoredUpstream: IGNORED_UPSTREAM,
624
700
  });
625
701
  printReport(results, report, check);
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
@@ -88,6 +88,7 @@ export interface Matrix4 {
88
88
  }
89
89
 
90
90
  declare const HashBrand: unique symbol;
91
+ declare const HashSource: unique symbol;
91
92
  /**
92
93
  * An opaque, branded handle to a *hashed name*: hold it and pass it back to the
93
94
  * engine API, but never inspect or construct it. Defold uses it in place of a
@@ -111,9 +112,22 @@ declare const HashBrand: unique symbol;
111
112
  * `hash_to_hex(h)` renders it as a hexadecimal string for logging, and `pprint`
112
113
  * shows it as `hash: [0x…]`. Two hashes are equal exactly when they name the
113
114
  * same thing, so a `Hash` is safe to compare, store, and use as a table key.
115
+ *
116
+ * The `S` parameter records the string `hash()` was called with, so a tool can
117
+ * *read* an address back out of `const SPRITE = hash("#sprite")`. It is not a
118
+ * checked constraint: it defaults to `string`, so every bare `Hash` keeps
119
+ * meaning what it always did, and its phantom member is optional, so `Hash` and
120
+ * `Hash<"#sprite">` stay assignable to each other in both directions. Nothing
121
+ * that compiles without it stops compiling with it.
114
122
  */
115
- export interface Hash {
123
+ export interface Hash<S extends string = string> {
116
124
  readonly [HashBrand]: "Hash";
125
+ // Method syntax, and load-bearing: a method's parameters are compared
126
+ // bivariantly, which is what keeps `Hash` and `Hash<"#sprite">` assignable in
127
+ // *both* directions. Written as a plain optional property (`?: S`) the
128
+ // parameter would be covariant, and passing a bare `Hash` where a sourced one
129
+ // is expected would start failing — the one thing this type must never do.
130
+ [HashSource]?(source: S): void;
117
131
  }
118
132
 
119
133
  declare const OpaqueBrand: unique symbol;
@@ -188,6 +202,9 @@ export const DEFOLD_TYPE_MAP: Readonly<Record<string, string>> = {
188
202
  vector4: "Vector4",
189
203
  quaternion: "Quaternion",
190
204
  matrix4: "Matrix4",
205
+ // Authored-README shorthand for `vmath.matrix4`; absent from every engine
206
+ // ref-doc, which a core-types.test.ts guard keeps true as releases import.
207
+ matrix: "Matrix4",
191
208
  "vmath.vector3": "Vector3",
192
209
  "vmath.vector4": "Vector4",
193
210
  "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}`);
@@ -0,0 +1,33 @@
1
+ /** @noSelfInFile */
2
+
3
+ import type { Opaque } from "./core-types";
4
+ import type { EditorCommand, EditorCommandQuery } from "./editor";
5
+
6
+ declare global {
7
+ namespace editor {
8
+ /**
9
+ * Create an editor command
10
+ *
11
+ * @param opts - A table with the following keys:`label string, message`required, user-visible command name, either a string or a localization message`locations string[]`required, a non-empty list of locations where the command is displayed in the editor, values are either `"Edit"`, `"View"`, `"Project"`, `"Debug"` (the editor menubar), `"Assets"` (the assets pane), or `"Outline"` (the outline pane)`query table`optional, a query that both controls the command availability and provides additional information to the command handler functions; a table with the following keys:`selection table`current selection, a table with the following keys:`type string`either `"resource"` (selected resource) or `"outline"` (selected outline node)`cardinality string`either `"one"` (will use first selected item) or `"many"` (will use all selected items)`argument table`the command argument`id string`optional, keyword identifier that may be used for assigning a shortcut to a command; should be a dot-separated identifier string, e.g. `"my-extension.do-stuff"``active function`optional function that additionally checks if a command is active in the current context; will receive opts table with values populated by the query; should be fast to execute since the editor might invoke it in response to UI interactions (on key typed, mouse clicked)`run function`optional function that is invoked when the user decides to execute the command; will receive opts table with values populated by the query
12
+ * @example
13
+ * ```ts
14
+ * // Print Git history for a file:
15
+ * // (`locations` is added here: upstream's own example omits it, but its
16
+ * // prose declares the key required.)
17
+ * editor.command({
18
+ * label: "Git History",
19
+ * locations: ["Assets"],
20
+ * query: { selection: { type: "resource", cardinality: "one" } },
21
+ * run: (opts) => {
22
+ * editor.execute("git", "log", "--follow", `.${editor.get(opts.selection, "path")}`, {
23
+ * reload_resources: false,
24
+ * });
25
+ * },
26
+ * });
27
+ * ```
28
+ */
29
+ function command<const Q extends EditorCommandQuery = Record<never, never>>(
30
+ opts: EditorCommand<Q>,
31
+ ): Opaque<"command">;
32
+ }
33
+ }
@@ -0,0 +1,200 @@
1
+ /** @noSelfInFile */
2
+
3
+ import type {
4
+ HttpRouteHandler,
5
+ ZipEntries,
6
+ ZipPackOptions,
7
+ ZipUnpackOptions,
8
+ } from "./editor-vm-types";
9
+
10
+ // The editor VM surfaces the emit leaves behind, hand-authored and pinned to
11
+ // their vendored fixtures by `test/editor-vm-globals-parity.test.ts`. Three
12
+ // shapes land here: `pprint` is a bare global function with no namespace to hang
13
+ // off; the two-segment VARIABLEs (`zip.METHOD.*`, `http.server.*`) are reachable
14
+ // by the emitter's nested pass but deliberately withheld, because a VARIABLE
15
+ // carries no type and would emit as `unknown` — useless to `ZipPackOptions`,
16
+ // which types `method` as a string — while its brief is an unreliable literal
17
+ // (upstream's own `zip.ON_CONFLICT.OVERWRITE` reads `"skip"`); and the functions
18
+ // whose *vendored signature* cannot be rendered soundly — an optional parameter
19
+ // sitting before a required one, or an empty `returnvalues` on a function
20
+ // upstream's own prose says returns a value — are written out here as overload
21
+ // sets. All three are withheld from the emit by `EDITOR_VM_SKIP_FUNCTIONS`. The
22
+ // contract is unchanged and still derived: this file declares exactly what the
23
+ // emit leaves behind. The namespaces below merge with the emitted
24
+ // `generated/editor-vm/` bodies rather than replacing them. Upstream records no
25
+ // type for a VARIABLE, so those annotations are read from each member's prose.
26
+
27
+ declare global {
28
+ /**
29
+ * Pretty-print a Lua value
30
+ */
31
+ function pprint(value: unknown): void;
32
+
33
+ namespace http {
34
+ namespace server {
35
+ /**
36
+ * Editor's HTTP server local url
37
+ */
38
+ const local_url: string;
39
+ /**
40
+ * Editor's HTTP server port
41
+ */
42
+ const port: number;
43
+ /**
44
+ * Editor's HTTP server url
45
+ */
46
+ const url: string;
47
+ /**
48
+ * Create route definition for the editor's HTTP server
49
+ *
50
+ * `method`, `as` and `openapi` are optional but sit before the required
51
+ * `handler`, so each documented call shape is its own overload. An optional
52
+ * is supplied only when every earlier optional is: `method` and `as` are
53
+ * both strings, so a form that skipped `method` alone would be
54
+ * indistinguishable from one that supplied it.
55
+ *
56
+ * @param path - HTTP URI path, starts with `/`; may include path patterns (`{name}` for a single segment and `{*name}` for the rest of the request path) that will be extracted from the path and provided to the handler as a part of the request
57
+ * @param method - HTTP request method, default `"GET"`
58
+ * @param as - Request body converter, either `"string"` or `"json"`; the body will be discarded if not specified
59
+ * @param openapi - Optional OpenAPI Operation Object for this route method, exposed from `/openapi.json`
60
+ * @param handler - Request handler function, receives the request table and returns either a single response value, or 0 or more arguments to `http.server.response()`
61
+ * @returns HTTP server route
62
+ * @example
63
+ * ```ts
64
+ * // Receive JSON and respond with JSON:
65
+ * http.server.route("/json", "POST", "json", (request) => {
66
+ * pprint(request);
67
+ * return 200;
68
+ * });
69
+ *
70
+ * // Extract parts of the path:
71
+ * http.server.route("/users/{user}/orders", (request) => {
72
+ * print((request as { user: string }).user);
73
+ * });
74
+ * ```
75
+ */
76
+ function route(path: string, handler: HttpRouteHandler): unknown;
77
+ function route(path: string, method: string, handler: HttpRouteHandler): unknown;
78
+ function route(path: string, method: string, as: string, handler: HttpRouteHandler): unknown;
79
+ function route(
80
+ path: string,
81
+ method: string,
82
+ as: string,
83
+ openapi: Record<string | number, unknown>,
84
+ handler: HttpRouteHandler,
85
+ ): unknown;
86
+ }
87
+ }
88
+
89
+ namespace json {
90
+ /**
91
+ * Decode JSON string to Lua value
92
+ *
93
+ * Upstream records no return value while its own brief names one, so the
94
+ * return is written here. `unknown` is the honest answer: `options.all`
95
+ * makes the result an array, and a JSON document may be a scalar.
96
+ *
97
+ * @param json - json data
98
+ * @param options - A table with the following keys:`all boolean`if `true`, decodes all json values in a string and returns an array
99
+ * @returns the decoded value
100
+ */
101
+ function decode(json: string, options?: Record<string | number, unknown>): unknown;
102
+ /**
103
+ * Encode Lua value to JSON string
104
+ *
105
+ * @param value - any Lua value that may be represented as JSON
106
+ * @returns the encoded document
107
+ */
108
+ function encode(value: unknown): string;
109
+ }
110
+
111
+ namespace zip {
112
+ namespace METHOD {
113
+ /**
114
+ * `"deflated"` compression method
115
+ */
116
+ const DEFLATED: string;
117
+ /**
118
+ * `"stored"` compression method, i.e. no compression
119
+ */
120
+ const STORED: string;
121
+ }
122
+ namespace ON_CONFLICT {
123
+ /**
124
+ * `"error"`, any conflict aborts extraction
125
+ */
126
+ const ERROR: string;
127
+ /**
128
+ * `"skip"`, existing file is preserved
129
+ */
130
+ const SKIP: string;
131
+ /**
132
+ * `"skip"`, existing file is overwritten
133
+ */
134
+ const OVERWRITE: string;
135
+ }
136
+ /**
137
+ * Create a ZIP archive
138
+ *
139
+ * `opts` is optional but sits before the required `entries`, so the two
140
+ * documented call shapes are separate overloads.
141
+ *
142
+ * @param output_path - output zip file path, resolved against project root if relative
143
+ * @param opts - compression options
144
+ * @param entries - entries to compress, either a relative path or a list of entries
145
+ * @example
146
+ * ```ts
147
+ * // Archive a file and a folder:
148
+ * zip.pack("build.zip", ["build", "game.project"]);
149
+ *
150
+ * // Change the location of the files within the archive:
151
+ * zip.pack("build.zip", [
152
+ * ["build/wasm-web", "."],
153
+ * ["configs/prod.json", "config.json"],
154
+ * ]);
155
+ *
156
+ * // Create archive without compression:
157
+ * zip.pack("build.zip", { method: zip.METHOD.STORED }, ["build", "resources"]);
158
+ *
159
+ * // Don't compress one of the folders:
160
+ * zip.pack("build.zip", [{ 1: "assets", method: zip.METHOD.STORED }, "build/wasm-web"]);
161
+ * ```
162
+ */
163
+ function pack(output_path: string, entries: ZipEntries): void;
164
+ function pack(output_path: string, opts: ZipPackOptions, entries: ZipEntries): void;
165
+ /**
166
+ * Extract a ZIP archive
167
+ *
168
+ * `target_path`, `opts` and `paths` are all optional and share the second
169
+ * slot, so the shape-discriminated forms come first: an all-optional
170
+ * `ZipUnpackOptions` cannot absorb a paths array, and vice versa.
171
+ *
172
+ * @param archive_path - zip file path, resolved against project root if relative
173
+ * @param target_path - target path for extraction, defaults to parent of `archive_path` if omitted
174
+ * @param opts - extraction options
175
+ * @param paths - entries to extract, relative string paths
176
+ * @example
177
+ * ```ts
178
+ * // Extract everything next to the archive:
179
+ * zip.unpack("build/dev/resources.zip");
180
+ *
181
+ * // Extract to a different directory:
182
+ * zip.unpack("build/dev/resources.zip", "build/dev/tmp");
183
+ *
184
+ * // Extract while overwriting existing files on conflict:
185
+ * zip.unpack("build/dev/resources.zip", { on_conflict: zip.ON_CONFLICT.OVERWRITE });
186
+ *
187
+ * // Extract a single file:
188
+ * zip.unpack("build/dev/resources.zip", ["config.json"]);
189
+ * ```
190
+ */
191
+ function unpack(archive_path: string, paths: readonly string[]): void;
192
+ function unpack(archive_path: string, opts: ZipUnpackOptions, paths?: readonly string[]): void;
193
+ function unpack(
194
+ archive_path: string,
195
+ target_path?: string,
196
+ opts?: ZipUnpackOptions,
197
+ paths?: readonly string[],
198
+ ): void;
199
+ }
200
+ }
@@ -0,0 +1,44 @@
1
+ /** @noSelfInFile */
2
+
3
+ // The named types the hand-authored editor VM overloads take. They live outside
4
+ // `src/editor-vm-globals.d.ts` on purpose: the parity test compares that file's
5
+ // declared set to the set the emit leaves behind, exactly, and a type alias
6
+ // declared there would count as an extra declaration with no upstream member to
7
+ // answer for it.
8
+
9
+ /**
10
+ * One entry in a `zip.pack` archive: a source path, a `[source, target]` pair
11
+ * that relocates it inside the archive, or a table carrying per-entry
12
+ * compression options alongside those positions.
13
+ */
14
+ export type ZipEntry = string | readonly string[] | Record<string | number, unknown>;
15
+
16
+ /**
17
+ * What `zip.pack` compresses: a single relative path, or a list of entries.
18
+ */
19
+ export type ZipEntries = string | readonly ZipEntry[];
20
+
21
+ /**
22
+ * Archive-wide compression options for `zip.pack`.
23
+ */
24
+ export interface ZipPackOptions {
25
+ /** Compression method, either `zip.METHOD.DEFLATED` (default) or `zip.METHOD.STORED`. */
26
+ readonly method?: string;
27
+ /** Compression level, 0 to 9; only useful with `zip.METHOD.DEFLATED`, defaults to 6. */
28
+ readonly level?: number;
29
+ }
30
+
31
+ /**
32
+ * Extraction options for `zip.unpack`. Every key is optional, which is what lets
33
+ * TypeScript tell this table apart from the paths list that shares its slot.
34
+ */
35
+ export interface ZipUnpackOptions {
36
+ /** Conflict resolution strategy, defaults to `zip.ON_CONFLICT.ERROR`. */
37
+ readonly on_conflict?: string;
38
+ }
39
+
40
+ /**
41
+ * A `http.server.route` handler. Left at the looseness the emit gave it: typing
42
+ * the request table is a separate slice.
43
+ */
44
+ export type HttpRouteHandler = (...args: unknown[]) => unknown;