@defold-typescript/library-types 0.22.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/api-doc/boom.json +3870 -0
- package/api-doc/{bridge.bridge.json → bridge.json} +754 -844
- package/api-doc/bzAnim.json +338 -0
- package/api-doc/decore.json +23 -23
- package/api-doc/defcon.json +150 -0
- package/api-doc/{defmath.defmath.json → defmath.json} +6 -46
- package/api-doc/defsave.json +518 -0
- package/api-doc/deftest.json +741 -0
- package/api-doc/{dicebag.dicebag.json → dicebag.json} +19 -1
- package/api-doc/druid.json +249 -1846
- package/api-doc/event.json +1074 -0
- package/api-doc/gooey.json +2050 -0
- package/api-doc/immutable.json +65 -0
- package/api-doc/in.accelerometer.json +75 -1
- package/api-doc/in.button.json +17 -10
- package/api-doc/in.cursor.json +26 -0
- package/api-doc/in.gesture.json +401 -6
- package/api-doc/in.keyboard.json +2 -0
- package/api-doc/in.mapper.json +12 -8
- package/api-doc/in.onscreen.json +61 -5
- package/api-doc/in.state.json +61 -13
- package/api-doc/in.textbox.json +23 -12
- package/api-doc/in.triggers.json +336 -0
- package/api-doc/lang.json +528 -0
- package/api-doc/{event.event.json → log.json} +96 -101
- package/api-doc/metrics.fps.json +61 -2
- package/api-doc/metrics.mem.json +61 -2
- package/api-doc/monarch.monarch.json +249 -7
- package/api-doc/monarch.transitions.easings.json +19 -26
- package/api-doc/monarch.transitions.gui.json +782 -79
- package/api-doc/nakama.engine.defold.json +31 -18
- package/api-doc/{nakama.nakama.json → nakama.json} +4752 -2554
- package/api-doc/nakama.util.log.json +32 -4
- package/api-doc/narrator.json +647 -0
- package/api-doc/openapi/nakama.nakama.json +7680 -0
- package/api-doc/orthographic.camera.json +96 -98
- package/api-doc/orthographic.json +602 -0
- package/api-doc/panthera.json +1183 -0
- package/api-doc/{persist.persist.json → persist.json} +26 -1
- package/api-doc/{platypus.platypus.json → platypus.json} +68 -14
- package/api-doc/proto.json +995 -0
- package/api-doc/{rendy.rendy.json → rendy.json} +46 -99
- package/api-doc/richtext.color.json +77 -0
- package/api-doc/richtext.richtext.json +375 -5
- package/api-doc/saver.saver.json +714 -263
- package/api-doc/saver.storage.json +283 -52
- package/api-doc/squid.json +846 -0
- package/api-doc/{starly.starly.json → starly.json} +1 -1
- package/api-doc/tweener.json +277 -0
- package/api-doc/{yagames.yagames.json → yagames.json} +784 -189
- package/api-doc/{zzfx.api.json → zzfx.json} +9 -9
- package/authored-targets.json +403 -0
- package/generated/{boom.boom.d.ts → boom.d.ts} +14 -0
- package/generated/bridge.d.ts +468 -0
- package/generated/{bzAnim.bzLibrary.d.ts → bzAnim.d.ts} +6 -0
- package/generated/decore.d.ts +37 -37
- package/generated/defcon.d.ts +43 -0
- package/generated/{defmath.defmath.d.ts → defmath.d.ts} +3 -2
- package/generated/defsave.d.ts +144 -0
- package/generated/{dicebag.dicebag.d.ts → dicebag.d.ts} +25 -0
- package/generated/druid.d.ts +198 -502
- package/generated/event.d.ts +318 -0
- package/generated/{gooey.gooey.d.ts → gooey.d.ts} +61 -6
- package/generated/immutable.d.ts +13 -0
- package/generated/in.onscreen.d.ts +5 -0
- package/generated/in.textbox.d.ts +4 -0
- package/generated/lang.d.ts +101 -0
- package/generated/log.d.ts +36 -0
- package/generated/metrics.fps.d.ts +19 -1
- package/generated/metrics.mem.d.ts +19 -1
- package/generated/monarch.monarch.d.ts +44 -1
- package/generated/monarch.transitions.easings.d.ts +0 -1
- package/generated/monarch.transitions.gui.d.ts +96 -12
- package/generated/nakama.d.ts +1158 -0
- package/generated/nakama.engine.defold.d.ts +3 -1
- package/generated/nakama.util.log.d.ts +6 -0
- package/generated/narrator.d.ts +121 -0
- package/generated/openapi/nakama.nakama.d.ts +884 -0
- package/generated/orthographic.camera.d.ts +24 -38
- package/generated/orthographic.d.ts +155 -0
- package/generated/panthera.d.ts +170 -0
- package/generated/{persist.persist.d.ts → persist.d.ts} +3 -0
- package/generated/{platypus.platypus.d.ts → platypus.d.ts} +9 -0
- package/generated/proto.d.ts +146 -0
- package/generated/{rendy.rendy.d.ts → rendy.d.ts} +33 -80
- package/generated/richtext.color.d.ts +15 -0
- package/generated/saver.saver.d.ts +289 -42
- package/generated/saver.storage.d.ts +79 -14
- package/generated/squid.d.ts +127 -0
- package/generated/tweener.d.ts +42 -0
- package/generated/{yagames.yagames.d.ts → yagames.d.ts} +151 -29
- package/generated/{zzfx.api.d.ts → zzfx.d.ts} +7 -0
- package/library-classification.json +0 -227
- package/library-targets.json +1 -284
- package/luals-targets.json +168 -1
- package/openapi-targets.json +17 -0
- package/package.json +9 -88
- package/script-api-targets.json +15 -0
- package/scripts/__snapshots__/parse-luals.test.ts.snap +504 -85
- package/scripts/apply-luals-overrides.ts +95 -0
- package/scripts/authored-parity.ts +718 -0
- package/scripts/emit-library-dts.ts +177 -19
- package/scripts/extract-api-doc.ts +189 -38
- package/scripts/fidelity-floor.ts +178 -0
- package/scripts/import-upstream-docs.ts +125 -0
- package/scripts/lower-api-doc.ts +69 -19
- package/scripts/luals-fidelity.ts +22 -10
- package/scripts/map-luals-types.ts +86 -22
- package/scripts/parse-lua-surface.ts +187 -0
- package/scripts/parse-luals.ts +473 -22
- package/scripts/parse-markdown-api.ts +247 -0
- package/scripts/parse-openapi-api.ts +313 -0
- package/scripts/sync-authored-types.ts +249 -0
- package/scripts/sync-library-types.ts +99 -3
- package/scripts/sync-luals-types.ts +29 -2
- package/scripts/sync-markdown-types.ts +761 -0
- package/scripts/sync-openapi-types.ts +308 -0
- package/scripts/sync-script-api-types.ts +367 -0
- package/api-doc/boom.boom.json +0 -26
- package/api-doc/bzAnim.bzLibrary.json +0 -156
- package/api-doc/defcon.console.json +0 -109
- package/api-doc/defsave.defsave.json +0 -175
- package/api-doc/deftest.deftest.json +0 -71
- package/api-doc/gooey.gooey.json +0 -963
- package/api-doc/immutable.immutable.json +0 -63
- package/api-doc/lang.lang.json +0 -411
- package/api-doc/log.log.json +0 -50
- package/api-doc/narrator.narrator.json +0 -150
- package/api-doc/proto.proto.json +0 -355
- package/api-doc/squid.squid.json +0 -660
- package/api-doc/tweener.tweener.json +0 -419
- package/generated/bridge.bridge.d.ts +0 -533
- package/generated/defcon.console.d.ts +0 -24
- package/generated/defsave.defsave.d.ts +0 -31
- package/generated/event.event.d.ts +0 -54
- package/generated/immutable.immutable.d.ts +0 -13
- package/generated/lang.lang.d.ts +0 -33
- package/generated/log.log.d.ts +0 -40
- package/generated/nakama.nakama.d.ts +0 -594
- package/generated/narrator.narrator.d.ts +0 -66
- package/generated/proto.proto.d.ts +0 -36
- package/generated/squid.squid.d.ts +0 -106
- package/generated/tweener.tweener.d.ts +0 -151
- /package/generated/{deftest.deftest.d.ts → deftest.d.ts} +0 -0
- /package/generated/{starly.starly.d.ts → starly.d.ts} +0 -0
|
@@ -15,7 +15,12 @@
|
|
|
15
15
|
* `name` is scoped into a child `MapContext` (an identity rename) so a bare `T`
|
|
16
16
|
* resolves to `T` instead of lowering to `unknown`, constraints and `extends`
|
|
17
17
|
* targets map through the existing rename map, and an `extends` clause is emitted
|
|
18
|
-
* only for parents that resolve to a declared interface.
|
|
18
|
+
* only for parents that resolve to a declared interface or an imported external type.
|
|
19
|
+
*
|
|
20
|
+
* A token owned by another target is declared through `externalTypes`: the emitter
|
|
21
|
+
* writes a real `import { <name> } from '<module>';` into the `declare module` block
|
|
22
|
+
* and resolves the token to that binding, so a cross-library reference carries its
|
|
23
|
+
* real type instead of lowering to `unknown`.
|
|
19
24
|
*/
|
|
20
25
|
|
|
21
26
|
import {
|
|
@@ -26,13 +31,16 @@ import {
|
|
|
26
31
|
varargElementType,
|
|
27
32
|
} from "@defold-typescript/types";
|
|
28
33
|
import {
|
|
34
|
+
LUALS_VARARG_TOKEN,
|
|
29
35
|
type MapContext,
|
|
36
|
+
mapLualsCallSignature,
|
|
30
37
|
mapLualsType,
|
|
31
38
|
matchSelfHookField,
|
|
32
39
|
scopeGenerics,
|
|
33
40
|
} from "./map-luals-types";
|
|
34
41
|
import type {
|
|
35
42
|
LibraryAlias,
|
|
43
|
+
LibraryField,
|
|
36
44
|
LibraryGeneric,
|
|
37
45
|
LibraryInterface,
|
|
38
46
|
LibraryMethod,
|
|
@@ -40,13 +48,38 @@ import type {
|
|
|
40
48
|
LibraryParam,
|
|
41
49
|
} from "./parse-luals";
|
|
42
50
|
|
|
51
|
+
/**
|
|
52
|
+
* A type token owned by another target: the module id that declares it and the name
|
|
53
|
+
* it exports. Resolving one emits a real `import` into the `declare module` block
|
|
54
|
+
* rather than lowering the token to `unknown`.
|
|
55
|
+
*/
|
|
56
|
+
export interface ExternalTypeRef {
|
|
57
|
+
module: string;
|
|
58
|
+
name: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
43
61
|
export interface EmitLibraryOptions {
|
|
44
62
|
moduleId: string;
|
|
45
63
|
typeRenames?: Record<string, string>;
|
|
64
|
+
externalTypes?: Record<string, ExternalTypeRef> | undefined;
|
|
46
65
|
}
|
|
47
66
|
|
|
48
67
|
const INDENT = "\t";
|
|
49
68
|
|
|
69
|
+
// A member with an explicit non-public visibility is internal surface; keep only
|
|
70
|
+
// members with no visibility or an explicit `public`, mirroring how LuaLS hides
|
|
71
|
+
// `private`/`protected`/`package` (and, for methods, `local`) from a class's public
|
|
72
|
+
// shape. Shared by all three consumers — the emitter, the api-doc lowering, and the
|
|
73
|
+
// fidelity report — so the declaration, documentation, and coverage surfaces
|
|
74
|
+
// describe one identical public member set.
|
|
75
|
+
export function isPublicField(field: LibraryField): boolean {
|
|
76
|
+
return field.visibility === undefined || field.visibility === "public";
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function isPublicMethod(method: LibraryMethod): boolean {
|
|
80
|
+
return method.visibility === undefined || method.visibility === "public";
|
|
81
|
+
}
|
|
82
|
+
|
|
50
83
|
/** A model type name (dotted like `druid.button`) reduced to a legal TS identifier. */
|
|
51
84
|
export function sanitizeTypeName(name: string): string {
|
|
52
85
|
const cleaned = name.replace(/[^A-Za-z0-9_$]/g, "_");
|
|
@@ -69,6 +102,42 @@ function safeParamName(name: string, index: number): string {
|
|
|
69
102
|
return TS_RESERVED_NAMES.has(name) ? `${name}_` : name;
|
|
70
103
|
}
|
|
71
104
|
|
|
105
|
+
/**
|
|
106
|
+
* The token -> local-alias rename map an `externalTypes` config contributes, aliasing
|
|
107
|
+
* exactly as a declared name would (dotted `event.foo` -> `event_foo`). Shared by the
|
|
108
|
+
* emitter, the fidelity report, and the api-doc lowering so all three resolve an
|
|
109
|
+
* external reference to the same identifier the import binds.
|
|
110
|
+
*/
|
|
111
|
+
export function externalTypeRenames(
|
|
112
|
+
externalTypes?: Record<string, ExternalTypeRef>,
|
|
113
|
+
): Record<string, string> {
|
|
114
|
+
const renames: Record<string, string> = {};
|
|
115
|
+
for (const token of Object.keys(externalTypes ?? {})) renames[token] = sanitizeTypeName(token);
|
|
116
|
+
return renames;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* `import { ... } from '<module>';` lines for the external tokens, one per source
|
|
121
|
+
* module with its names sorted and the modules sorted by id, so re-rendering is
|
|
122
|
+
* byte-identical. A token whose local alias differs from the export name binds
|
|
123
|
+
* through an `as` clause.
|
|
124
|
+
*/
|
|
125
|
+
function renderExternalImports(externalTypes?: Record<string, ExternalTypeRef>): string[] {
|
|
126
|
+
const byModule = new Map<string, Set<string>>();
|
|
127
|
+
for (const [token, ref] of Object.entries(externalTypes ?? {})) {
|
|
128
|
+
const alias = sanitizeTypeName(token);
|
|
129
|
+
const binding = alias === ref.name ? ref.name : `${ref.name} as ${alias}`;
|
|
130
|
+
const names = byModule.get(ref.module) ?? new Set<string>();
|
|
131
|
+
names.add(binding);
|
|
132
|
+
byModule.set(ref.module, names);
|
|
133
|
+
}
|
|
134
|
+
return [...byModule.entries()]
|
|
135
|
+
.sort(([a], [b]) => (a < b ? -1 : 1))
|
|
136
|
+
.map(
|
|
137
|
+
([module, names]) => `${INDENT}import { ${[...names].sort().join(", ")} } from '${module}';`,
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
72
141
|
export function mapTypes(types: readonly string[], ctx: MapContext): string {
|
|
73
142
|
if (types.length === 0) return "unknown";
|
|
74
143
|
return types.map((token) => mapLualsType(token, ctx).ts).join(" | ");
|
|
@@ -91,36 +160,67 @@ export function renderGenericParams(generics: readonly LibraryGeneric[], ctx: Ma
|
|
|
91
160
|
function renderHookReturn(returnTokens: readonly string[], ctx: MapContext): string {
|
|
92
161
|
if (returnTokens.length === 0) return "void";
|
|
93
162
|
if (returnTokens.length === 1) return mapTypes([returnTokens[0] as string], ctx);
|
|
94
|
-
return luaMultiReturn(
|
|
163
|
+
return luaMultiReturn(
|
|
164
|
+
returnTokens.map((token) => mapTypes([token], ctx)),
|
|
165
|
+
returnTokens.at(-1) === LUALS_VARARG_TOKEN,
|
|
166
|
+
);
|
|
95
167
|
}
|
|
96
168
|
|
|
97
169
|
/**
|
|
98
170
|
* An ` extends X, Y` clause built from `iface.extends` split on commas, keeping only
|
|
99
|
-
* parents that name a declared interface
|
|
100
|
-
* mapped through the rename map; `""` when none
|
|
171
|
+
* parents that name a declared interface or an imported external type (so no
|
|
172
|
+
* `extends unknown` is ever emitted), mapped through the rename map; `""` when none
|
|
173
|
+
* survive.
|
|
101
174
|
*/
|
|
102
175
|
function renderExtends(
|
|
103
176
|
iface: LibraryInterface,
|
|
104
177
|
ctx: MapContext,
|
|
105
178
|
interfaceNames: ReadonlySet<string>,
|
|
179
|
+
externalTokens: ReadonlySet<string>,
|
|
106
180
|
): string {
|
|
107
181
|
if (!iface.extends) return "";
|
|
108
182
|
const parents = iface.extends
|
|
109
183
|
.split(",")
|
|
110
184
|
.map((name) => name.trim())
|
|
111
|
-
.filter((name) => interfaceNames.has(name))
|
|
185
|
+
.filter((name) => interfaceNames.has(name) || externalTokens.has(name))
|
|
112
186
|
.map((name) => mapTypes([name], ctx));
|
|
113
187
|
return parents.length > 0 ? ` extends ${parents.join(", ")}` : "";
|
|
114
188
|
}
|
|
115
189
|
|
|
190
|
+
/**
|
|
191
|
+
* Which non-vararg params may be emitted with a trailing `?`. Walking right-to-left,
|
|
192
|
+
* a param is emitted-optional iff it is itself omittable (`isOptional || isNilable`)
|
|
193
|
+
* and every later non-vararg param is too — a required param blocks every param to
|
|
194
|
+
* its left, since TS forbids a required parameter after an optional one. A trailing
|
|
195
|
+
* vararg (rendered `...args`, never `?`) does not break the preceding run. Exported so
|
|
196
|
+
* the api-doc lowering keys `is_optional` off the identical rule, keeping the rendered
|
|
197
|
+
* `/api` signature byte-consistent with the `.d.ts`.
|
|
198
|
+
*/
|
|
199
|
+
export function paramOptionalFlags(params: readonly LibraryParam[]): boolean[] {
|
|
200
|
+
const flags = new Array<boolean>(params.length).fill(false);
|
|
201
|
+
let laterAllOptional = true;
|
|
202
|
+
for (let i = params.length - 1; i >= 0; i--) {
|
|
203
|
+
const param = params[i] as LibraryParam;
|
|
204
|
+
if (param.isVararg) continue;
|
|
205
|
+
const selfOptional = param.isOptional || param.isNilable === true;
|
|
206
|
+
if (laterAllOptional && selfOptional) {
|
|
207
|
+
flags[i] = true;
|
|
208
|
+
} else {
|
|
209
|
+
laterAllOptional = false;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return flags;
|
|
213
|
+
}
|
|
214
|
+
|
|
116
215
|
function renderParams(params: readonly LibraryParam[], ctx: MapContext): string {
|
|
216
|
+
const optionalFlags = paramOptionalFlags(params);
|
|
117
217
|
return params
|
|
118
218
|
.map((param, index) => {
|
|
119
219
|
const mapped = mapTypes(param.types, ctx);
|
|
120
220
|
if (param.isVararg) {
|
|
121
221
|
return `...args: ${varargElementType(mapped)}`;
|
|
122
222
|
}
|
|
123
|
-
const optional =
|
|
223
|
+
const optional = optionalFlags[index] ? "?" : "";
|
|
124
224
|
return `${safeParamName(param.name, index)}${optional}: ${mapped}`;
|
|
125
225
|
})
|
|
126
226
|
.join(", ");
|
|
@@ -129,16 +229,22 @@ function renderParams(params: readonly LibraryParam[], ctx: MapContext): string
|
|
|
129
229
|
function renderReturn(returns: readonly LibraryParam[], ctx: MapContext): string {
|
|
130
230
|
if (returns.length === 0) return "void";
|
|
131
231
|
if (returns.length === 1) return mapTypes((returns[0] as LibraryParam).types, ctx);
|
|
132
|
-
|
|
232
|
+
const last = returns[returns.length - 1] as LibraryParam;
|
|
233
|
+
const restTail = last.types.length === 1 && last.types[0] === LUALS_VARARG_TOKEN;
|
|
234
|
+
return luaMultiReturn(
|
|
235
|
+
returns.map((ret) => mapTypes(ret.types, ctx)),
|
|
236
|
+
restTail,
|
|
237
|
+
);
|
|
133
238
|
}
|
|
134
239
|
|
|
135
|
-
function pushDoc(lines: string[], summary: string, indent: string): void {
|
|
136
|
-
|
|
240
|
+
function pushDoc(lines: string[], summary: string, indent: string, deprecated?: string): void {
|
|
241
|
+
const parts = deprecated !== undefined ? { summary, deprecated } : { summary };
|
|
242
|
+
for (const line of renderDocComment(parts)) lines.push(`${indent}${line}`);
|
|
137
243
|
}
|
|
138
244
|
|
|
139
245
|
function renderAlias(alias: LibraryAlias, ctx: MapContext): string[] {
|
|
140
246
|
const lines: string[] = [];
|
|
141
|
-
pushDoc(lines, alias.doc, INDENT);
|
|
247
|
+
pushDoc(lines, alias.doc, INDENT, alias.deprecated);
|
|
142
248
|
lines.push(`${INDENT}type ${sanitizeTypeName(alias.name)} = ${mapTypes(alias.types, ctx)};`);
|
|
143
249
|
return lines;
|
|
144
250
|
}
|
|
@@ -147,15 +253,17 @@ function renderInterface(
|
|
|
147
253
|
iface: LibraryInterface,
|
|
148
254
|
ctx: MapContext,
|
|
149
255
|
interfaceNames: ReadonlySet<string>,
|
|
256
|
+
externalTokens: ReadonlySet<string>,
|
|
150
257
|
): string[] {
|
|
151
258
|
const lines: string[] = [];
|
|
152
|
-
pushDoc(lines, iface.brief, INDENT);
|
|
259
|
+
pushDoc(lines, iface.brief, INDENT, iface.deprecated);
|
|
153
260
|
const ifaceCtx = scopeGenerics(ctx, iface.generics);
|
|
154
261
|
const params = renderGenericParams(iface.generics, ifaceCtx);
|
|
155
|
-
const extendsClause = renderExtends(iface, ifaceCtx, interfaceNames);
|
|
262
|
+
const extendsClause = renderExtends(iface, ifaceCtx, interfaceNames, externalTokens);
|
|
156
263
|
lines.push(`${INDENT}interface ${sanitizeTypeName(iface.name)}${params}${extendsClause} {`);
|
|
157
264
|
const body = INDENT + INDENT;
|
|
158
265
|
for (const field of iface.fields) {
|
|
266
|
+
if (!isPublicField(field)) continue;
|
|
159
267
|
// A base's self-receiving lifecycle hook is emitted as a permissive optional
|
|
160
268
|
// method (`name?(...args: any[]): ret`) so a concrete subinterface's refined
|
|
161
269
|
// override stays assignable under `extends`; strict function-field variance
|
|
@@ -172,7 +280,8 @@ function renderInterface(
|
|
|
172
280
|
lines.push(`${body}${memberKey(field.name)}${optional}: ${mapTypes(field.types, ifaceCtx)};`);
|
|
173
281
|
}
|
|
174
282
|
for (const method of iface.methods) {
|
|
175
|
-
|
|
283
|
+
if (!isPublicMethod(method)) continue;
|
|
284
|
+
pushDoc(lines, method.brief, body, method.deprecated);
|
|
176
285
|
const methodCtx = scopeGenerics(ifaceCtx, method.generics);
|
|
177
286
|
const methodParams = renderGenericParams(method.generics, methodCtx);
|
|
178
287
|
lines.push(
|
|
@@ -182,13 +291,39 @@ function renderInterface(
|
|
|
182
291
|
)}): ${renderReturn(method.returns, methodCtx)};`,
|
|
183
292
|
);
|
|
184
293
|
}
|
|
294
|
+
// A class `@overload fun(...)` becomes an interface call signature, making the
|
|
295
|
+
// instance callable (`event(...)`, `promise(...)`) the way the metatable's `__call`
|
|
296
|
+
// does at runtime. Rendered after the members with its own doc comment.
|
|
297
|
+
for (const overload of iface.overloads ?? []) {
|
|
298
|
+
pushDoc(lines, overload.doc, body);
|
|
299
|
+
lines.push(`${body}${mapLualsCallSignature(overload.type, ifaceCtx).ts};`);
|
|
300
|
+
}
|
|
185
301
|
lines.push(`${INDENT}}`);
|
|
186
302
|
return lines;
|
|
187
303
|
}
|
|
188
304
|
|
|
305
|
+
/**
|
|
306
|
+
* The module object's public fields rendered as module-level `export const`s — the
|
|
307
|
+
* constants a returned module table (`return Squid`) carries. Emitted in place of the
|
|
308
|
+
* standalone interface, since consumers reach them as `squid.TRACE`, not `Squid.TRACE`.
|
|
309
|
+
*/
|
|
310
|
+
function renderModuleConstants(iface: LibraryInterface, ctx: MapContext): string[] {
|
|
311
|
+
const lines: string[] = [];
|
|
312
|
+
for (const field of iface.fields) {
|
|
313
|
+
if (!isPublicField(field)) continue;
|
|
314
|
+
pushDoc(lines, field.doc, INDENT);
|
|
315
|
+
const name =
|
|
316
|
+
TS_IDENTIFIER.test(field.name) && !TS_RESERVED_NAMES.has(field.name)
|
|
317
|
+
? field.name
|
|
318
|
+
: sanitizeTypeName(field.name);
|
|
319
|
+
lines.push(`${INDENT}export const ${name}: ${mapTypes(field.types, ctx)};`);
|
|
320
|
+
}
|
|
321
|
+
return lines;
|
|
322
|
+
}
|
|
323
|
+
|
|
189
324
|
function renderModuleFunction(fn: LibraryMethod, ctx: MapContext): string[] {
|
|
190
325
|
const lines: string[] = [];
|
|
191
|
-
pushDoc(lines, fn.brief, INDENT);
|
|
326
|
+
pushDoc(lines, fn.brief, INDENT, fn.deprecated);
|
|
192
327
|
const fnCtx = scopeGenerics(ctx, fn.generics);
|
|
193
328
|
const genericParams = renderGenericParams(fn.generics, fnCtx);
|
|
194
329
|
const params = renderParams(fn.params, fnCtx);
|
|
@@ -220,6 +355,7 @@ function renderModuleFunction(fn: LibraryMethod, ctx: MapContext): string[] {
|
|
|
220
355
|
export function buildModelContext(
|
|
221
356
|
model: LibraryModel,
|
|
222
357
|
typeRenames?: Record<string, string>,
|
|
358
|
+
externalTypes?: Record<string, ExternalTypeRef>,
|
|
223
359
|
): MapContext {
|
|
224
360
|
const declaredNames = [
|
|
225
361
|
...model.interfaces.map((iface) => iface.name),
|
|
@@ -227,9 +363,18 @@ export function buildModelContext(
|
|
|
227
363
|
];
|
|
228
364
|
const nameRenames: Record<string, string> = {};
|
|
229
365
|
for (const name of declaredNames) nameRenames[name] = sanitizeTypeName(name);
|
|
366
|
+
const externalRenames = externalTypeRenames(externalTypes);
|
|
367
|
+
for (const [token, alias] of Object.entries(externalRenames)) {
|
|
368
|
+
const collision = declaredNames.find((name) => sanitizeTypeName(name) === alias);
|
|
369
|
+
if (collision !== undefined) {
|
|
370
|
+
throw new Error(
|
|
371
|
+
`buildModelContext: external type "${token}" resolves to local name "${alias}", which the model already declares as "${collision}".`,
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
230
375
|
return {
|
|
231
|
-
knownNames: new Set(declaredNames),
|
|
232
|
-
typeRenames: { ...(typeRenames ?? {}), ...nameRenames },
|
|
376
|
+
knownNames: new Set([...declaredNames, ...Object.values(externalRenames)]),
|
|
377
|
+
typeRenames: { ...(typeRenames ?? {}), ...externalRenames, ...nameRenames },
|
|
233
378
|
};
|
|
234
379
|
}
|
|
235
380
|
|
|
@@ -240,13 +385,26 @@ export function buildModelContext(
|
|
|
240
385
|
* `unknown` inside `mapLualsType` exactly as the fidelity report records them.
|
|
241
386
|
*/
|
|
242
387
|
export function emitLibraryDeclarations(model: LibraryModel, opts: EmitLibraryOptions): string {
|
|
243
|
-
const ctx = buildModelContext(model, opts.typeRenames);
|
|
388
|
+
const ctx = buildModelContext(model, opts.typeRenames, opts.externalTypes);
|
|
244
389
|
|
|
245
390
|
const interfaceNames = new Set(model.interfaces.map((iface) => iface.name));
|
|
391
|
+
const externalTokens = new Set(Object.keys(opts.externalTypes ?? {}));
|
|
246
392
|
const out: string[] = ["/** @noResolution */", `declare module '${opts.moduleId}' {`];
|
|
393
|
+
out.push(...renderExternalImports(opts.externalTypes));
|
|
247
394
|
for (const alias of model.aliases) out.push(...renderAlias(alias, ctx));
|
|
248
|
-
for (const iface of model.interfaces)
|
|
249
|
-
|
|
395
|
+
for (const iface of model.interfaces) {
|
|
396
|
+
// The module object's fields become module-level `export const`s (below), so it is
|
|
397
|
+
// not also rendered as a standalone interface.
|
|
398
|
+
if (iface.name === model.moduleObject) {
|
|
399
|
+
out.push(...renderModuleConstants(iface, ctx));
|
|
400
|
+
continue;
|
|
401
|
+
}
|
|
402
|
+
out.push(...renderInterface(iface, ctx, interfaceNames, externalTokens));
|
|
403
|
+
}
|
|
404
|
+
for (const fn of model.moduleFunctions) {
|
|
405
|
+
if (!isPublicMethod(fn)) continue;
|
|
406
|
+
out.push(...renderModuleFunction(fn, ctx));
|
|
407
|
+
}
|
|
250
408
|
out.push("}");
|
|
251
409
|
return `${out.join("\n")}\n`;
|
|
252
410
|
}
|