@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.
- package/api-signatures.json +44 -44
- package/api-targets.json +57 -0
- package/generated/editor-vm/http.d.ts +56 -0
- package/generated/editor-vm/json.d.ts +10 -0
- package/generated/editor-vm/localization.d.ts +42 -0
- package/generated/editor-vm/tilemap_tiles.d.ts +80 -0
- package/generated/editor-vm/zip.d.ts +10 -0
- package/generated/editor-vm/zlib.d.ts +24 -0
- package/generated/editor.d.ts +1092 -0
- package/generated/go.d.ts +22 -22
- package/generated/kinds/editor-script.d.ts +13 -0
- package/generated/kinds/gui-script.d.ts +1 -0
- package/generated/kinds/render-script.d.ts +1 -0
- package/generated/kinds/script.d.ts +1 -0
- package/generated/versions/defold-1.12.4/go.d.ts +22 -22
- package/index.d.ts +6 -0
- package/package.json +9 -1
- package/scripts/materialize-version.ts +54 -13
- package/scripts/regen.ts +425 -42
- package/scripts/signature-store-fs.ts +2 -0
- package/scripts/sync-api-docs.ts +82 -6
- package/src/api-doc.ts +58 -0
- package/src/core-types.ts +18 -1
- package/src/doc-comment.ts +21 -3
- package/src/editor-overloads.d.ts +33 -0
- package/src/editor-vm-globals.d.ts +200 -0
- package/src/editor-vm-types.ts +44 -0
- package/src/editor.ts +117 -16
- package/src/emit-dts.ts +292 -79
- package/src/engine-globals.d.ts +2 -2
- package/src/go-overloads.d.ts +6 -6
- package/src/index.ts +12 -0
- package/src/library-signature.ts +11 -3
- package/src/msg-overloads.d.ts +3 -3
- package/src/scene-addresses.d.ts +62 -0
- package/src/script-api.ts +12 -2
- package/src/url-parameters.ts +174 -0
- package/url-parameters.json +285 -0
package/scripts/sync-api-docs.ts
CHANGED
|
@@ -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
|
|
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:
|
|
693
|
+
manifest: COVERAGE_MANIFEST,
|
|
616
694
|
moduleManifest: MODULE_MANIFEST,
|
|
617
695
|
unmapped: UNMAPPED,
|
|
618
696
|
syncedDocs,
|
|
619
697
|
upstream: collectUpstreamNamespaces(zip),
|
|
620
|
-
upstreamMapped:
|
|
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",
|
package/src/doc-comment.ts
CHANGED
|
@@ -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
|
-
|
|
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;
|