@defold-typescript/cli 0.5.4 → 0.6.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/dist/bin.js +1414 -395
- package/dist/bob-command.d.ts +31 -0
- package/dist/bob.d.ts +19 -0
- package/dist/boot-path.d.ts +5 -0
- package/dist/build-output.d.ts +7 -1
- package/dist/debug-launcher.d.ts +7 -1
- package/dist/directory-walls.d.ts +23 -0
- package/dist/dispatch.d.ts +6 -0
- package/dist/index.js +1268 -248
- package/dist/init.d.ts +1 -2
- package/dist/install-reminder.d.ts +1 -0
- package/dist/json-output.d.ts +26 -2
- package/dist/materialize.d.ts +0 -3
- package/dist/mise-scaffold.d.ts +1 -1
- package/dist/scan.d.ts +1 -0
- package/dist/script-kind.d.ts +2 -1
- package/dist/setup-debug.d.ts +40 -0
- package/dist/wall-interactive.d.ts +16 -0
- package/dist/wall.d.ts +4 -0
- package/dist/watch.d.ts +1 -0
- package/package.json +4 -3
- package/src/bob-command.ts +137 -0
- package/src/bob.ts +59 -0
- package/src/boot-path.ts +113 -0
- package/src/build-output.ts +67 -3
- package/src/build-session.ts +31 -11
- package/src/build.ts +6 -5
- package/src/debug-launcher.ts +36 -12
- package/src/directory-walls.ts +214 -0
- package/src/dispatch.ts +264 -18
- package/src/init.ts +83 -38
- package/src/install-reminder.ts +18 -0
- package/src/json-output.ts +52 -7
- package/src/materialize.ts +14 -12
- package/src/mise-scaffold.ts +16 -10
- package/src/scan.ts +7 -1
- package/src/script-kind.ts +31 -19
- package/src/setup-debug.ts +422 -0
- package/src/wall-interactive.ts +60 -0
- package/src/wall.ts +71 -0
- package/src/watch.ts +15 -3
package/dist/index.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
3
|
+
|
|
1
4
|
// src/build-session.ts
|
|
2
5
|
import { readFileSync as readFileSync2, rmSync } from "node:fs";
|
|
3
6
|
import * as path3 from "node:path";
|
|
@@ -39,18 +42,55 @@ function stripIncludeBase(pattern) {
|
|
|
39
42
|
const lastSlash = upToWildcard.lastIndexOf("/");
|
|
40
43
|
return lastSlash === -1 ? "" : upToWildcard.slice(0, lastSlash + 1);
|
|
41
44
|
}
|
|
42
|
-
|
|
45
|
+
var SCRIPT_SUFFIX_BY_KIND = {
|
|
46
|
+
script: ".ts.script",
|
|
47
|
+
"gui-script": ".ts.gui_script",
|
|
48
|
+
"render-script": ".ts.render_script"
|
|
49
|
+
};
|
|
50
|
+
var FACTORY_KINDS = [
|
|
51
|
+
["render-script", /\bdefineRenderScript\s*\(/],
|
|
52
|
+
["gui-script", /\bdefineGuiScript\s*\(/],
|
|
53
|
+
["script", /\bdefineScript\s*\(/]
|
|
54
|
+
];
|
|
55
|
+
function detectSourceOutputKind(source) {
|
|
56
|
+
for (const [kind, re] of FACTORY_KINDS) {
|
|
57
|
+
if (re.test(source)) {
|
|
58
|
+
return kind;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return "module";
|
|
62
|
+
}
|
|
63
|
+
function relUnderOutDir(rel, config) {
|
|
43
64
|
const { outDir, include } = config;
|
|
44
65
|
if (outDir === undefined || outDir === "" || outDir === ".") {
|
|
45
|
-
return rel
|
|
66
|
+
return rel;
|
|
46
67
|
}
|
|
47
68
|
const includeBase = include.map(stripIncludeBase).filter((base) => rel.startsWith(base)).sort((a, b) => b.length - a.length)[0] ?? "";
|
|
48
69
|
const relUnderBase = rel.slice(includeBase.length);
|
|
49
|
-
return path.posix.join(outDir, relUnderBase
|
|
70
|
+
return path.posix.join(outDir, relUnderBase);
|
|
71
|
+
}
|
|
72
|
+
function computeOutputRel(rel, config, kind) {
|
|
73
|
+
const baseRel = relUnderOutDir(rel, config);
|
|
74
|
+
if (kind === "module") {
|
|
75
|
+
return baseRel.replace(/\.ts$/, ".lua");
|
|
76
|
+
}
|
|
77
|
+
return baseRel.replace(/\.ts$/, SCRIPT_SUFFIX_BY_KIND[kind]);
|
|
78
|
+
}
|
|
79
|
+
function outputRelsForSource(rel, config) {
|
|
80
|
+
const outputs = [
|
|
81
|
+
computeOutputRel(rel, config, "module"),
|
|
82
|
+
computeOutputRel(rel, config, "script"),
|
|
83
|
+
computeOutputRel(rel, config, "gui-script"),
|
|
84
|
+
computeOutputRel(rel, config, "render-script")
|
|
85
|
+
];
|
|
86
|
+
return outputs.flatMap((output) => [output, `${output}.map`]);
|
|
50
87
|
}
|
|
51
88
|
function collectFailures(diagnostics) {
|
|
52
89
|
const failures = new Map;
|
|
53
90
|
for (const diag of diagnostics) {
|
|
91
|
+
if (diag.category === "warning") {
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
54
94
|
const bucket = diag.file ?? PROJECT_BUCKET;
|
|
55
95
|
const list = failures.get(bucket);
|
|
56
96
|
if (list) {
|
|
@@ -87,8 +127,11 @@ function writeScriptFile(cwd, scriptRel, lua, map) {
|
|
|
87
127
|
// src/scan.ts
|
|
88
128
|
import { globSync, statSync } from "node:fs";
|
|
89
129
|
import * as path2 from "node:path";
|
|
130
|
+
function normalizeScannedPath(rel) {
|
|
131
|
+
return rel.split(/[/\\]/).join("/");
|
|
132
|
+
}
|
|
90
133
|
function scanFilesSync(cwd, pattern) {
|
|
91
|
-
return globSync(pattern, { cwd }).filter((rel) => statSync(path2.join(cwd, rel)).isFile());
|
|
134
|
+
return globSync(pattern, { cwd }).map(normalizeScannedPath).filter((rel) => statSync(path2.join(cwd, rel)).isFile());
|
|
92
135
|
}
|
|
93
136
|
|
|
94
137
|
// src/build-session.ts
|
|
@@ -96,7 +139,14 @@ function createBuildSession(opts) {
|
|
|
96
139
|
const { cwd } = opts;
|
|
97
140
|
const config = readBuildConfig(cwd);
|
|
98
141
|
const session = createTranspileSession();
|
|
99
|
-
function
|
|
142
|
+
function pruneOutputs(rel, keepRel) {
|
|
143
|
+
for (const outputRel of outputRelsForSource(rel, config)) {
|
|
144
|
+
if (outputRel !== keepRel && outputRel !== `${keepRel}.map`) {
|
|
145
|
+
rmSync(path3.join(cwd, outputRel), { force: true });
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
function writeOutputs(result, keys, sources, pruneAlternatives = false) {
|
|
100
150
|
const failures = collectFailures(result.diagnostics);
|
|
101
151
|
const written = [];
|
|
102
152
|
for (const rel of keys) {
|
|
@@ -107,12 +157,15 @@ function createBuildSession(opts) {
|
|
|
107
157
|
if (lua === undefined) {
|
|
108
158
|
continue;
|
|
109
159
|
}
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
160
|
+
const outputRel = computeOutputRel(rel, config, detectSourceOutputKind(sources[rel] ?? ""));
|
|
161
|
+
if (pruneAlternatives) {
|
|
162
|
+
pruneOutputs(rel, outputRel);
|
|
163
|
+
}
|
|
164
|
+
writeScriptFile(cwd, outputRel, lua, result.sourceMaps[rel]);
|
|
165
|
+
written.push(outputRel);
|
|
113
166
|
}
|
|
114
167
|
throwIfFailures(failures);
|
|
115
|
-
return { written };
|
|
168
|
+
return { written: written.sort() };
|
|
116
169
|
}
|
|
117
170
|
function buildAll() {
|
|
118
171
|
const seen = new Set;
|
|
@@ -130,7 +183,7 @@ function createBuildSession(opts) {
|
|
|
130
183
|
files[rel] = readFileSync2(path3.join(cwd, rel), "utf8");
|
|
131
184
|
}
|
|
132
185
|
const result = session.update(files);
|
|
133
|
-
return writeOutputs(result, sources);
|
|
186
|
+
return writeOutputs(result, sources, files);
|
|
134
187
|
}
|
|
135
188
|
function applyEvents(changed, removed) {
|
|
136
189
|
const sourceChanged = changed.filter(isTranspilerSource);
|
|
@@ -144,21 +197,23 @@ function createBuildSession(opts) {
|
|
|
144
197
|
}
|
|
145
198
|
const result = session.update(changes);
|
|
146
199
|
for (const rel of sourceRemoved) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
200
|
+
pruneOutputs(rel);
|
|
201
|
+
}
|
|
202
|
+
const changedSources = {};
|
|
203
|
+
for (const rel of sourceChanged) {
|
|
204
|
+
changedSources[rel] = changes[rel] ?? "";
|
|
150
205
|
}
|
|
151
|
-
return writeOutputs(result, sourceChanged);
|
|
206
|
+
return writeOutputs(result, sourceChanged, changedSources, true);
|
|
152
207
|
}
|
|
153
208
|
return { buildAll, applyEvents };
|
|
154
209
|
}
|
|
155
210
|
// src/dispatch.ts
|
|
156
|
-
import { existsSync as
|
|
157
|
-
import * as
|
|
211
|
+
import { existsSync as existsSync10, readFileSync as readFileSync12 } from "node:fs";
|
|
212
|
+
import * as path15 from "node:path";
|
|
158
213
|
|
|
159
214
|
// src/api-registry.ts
|
|
160
215
|
import { existsSync, readFileSync as readFileSync3 } from "node:fs";
|
|
161
|
-
import { createRequire } from "node:module";
|
|
216
|
+
import { createRequire as createRequire2 } from "node:module";
|
|
162
217
|
import * as path4 from "node:path";
|
|
163
218
|
function findPackageRoot(start) {
|
|
164
219
|
let dir = start;
|
|
@@ -175,7 +230,7 @@ function findPackageRoot(start) {
|
|
|
175
230
|
}
|
|
176
231
|
function resolveTypesPackageRoot() {
|
|
177
232
|
try {
|
|
178
|
-
const require2 =
|
|
233
|
+
const require2 = createRequire2(import.meta.url);
|
|
179
234
|
const entry = require2.resolve("@defold-typescript/types");
|
|
180
235
|
return findPackageRoot(path4.dirname(entry));
|
|
181
236
|
} catch {
|
|
@@ -233,73 +288,32 @@ function selectApiSurface(resolvedVersion) {
|
|
|
233
288
|
return { surfaceId: null, available: false };
|
|
234
289
|
}
|
|
235
290
|
|
|
236
|
-
// src/
|
|
237
|
-
import {
|
|
238
|
-
import
|
|
239
|
-
import { transpileProject } from "@defold-typescript/transpiler";
|
|
240
|
-
function runBuild(opts) {
|
|
241
|
-
const { cwd } = opts;
|
|
242
|
-
const config = readBuildConfig(cwd);
|
|
243
|
-
const seen = new Set;
|
|
244
|
-
for (const pattern of config.include) {
|
|
245
|
-
for (const match of scanFilesSync(cwd, pattern)) {
|
|
246
|
-
seen.add(toPosix(match));
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
const sources = [...seen].sort();
|
|
250
|
-
if (sources.length === 0) {
|
|
251
|
-
return { written: [] };
|
|
252
|
-
}
|
|
253
|
-
const files = {};
|
|
254
|
-
for (const rel of sources) {
|
|
255
|
-
files[rel] = readFileSync4(path5.join(cwd, rel), "utf8");
|
|
256
|
-
}
|
|
257
|
-
const result = transpileProject({ files });
|
|
258
|
-
const failures = collectFailures(result.diagnostics);
|
|
259
|
-
const written = [];
|
|
260
|
-
for (const rel of sources) {
|
|
261
|
-
if (failures.has(rel)) {
|
|
262
|
-
continue;
|
|
263
|
-
}
|
|
264
|
-
const lua = result.lua[rel];
|
|
265
|
-
if (!lua) {
|
|
266
|
-
continue;
|
|
267
|
-
}
|
|
268
|
-
const scriptRel = computeScriptRel(rel, config);
|
|
269
|
-
writeScriptFile(cwd, scriptRel, lua, result.sourceMaps[rel]);
|
|
270
|
-
written.push(scriptRel);
|
|
271
|
-
}
|
|
272
|
-
throwIfFailures(failures);
|
|
273
|
-
return { written };
|
|
274
|
-
}
|
|
291
|
+
// src/bob-command.ts
|
|
292
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2 } from "node:fs";
|
|
293
|
+
import { delimiter, dirname as dirname3, join as join6 } from "node:path";
|
|
275
294
|
|
|
276
|
-
// src/
|
|
277
|
-
import {
|
|
278
|
-
import * as
|
|
279
|
-
import { fileURLToPath } from "node:url";
|
|
280
|
-
var VERSION_FALLBACK = "0.0.0";
|
|
281
|
-
function defaultPackageRoot() {
|
|
282
|
-
return path6.join(path6.dirname(fileURLToPath(import.meta.url)), "..");
|
|
283
|
-
}
|
|
284
|
-
function readCliVersion(packageRoot = defaultPackageRoot()) {
|
|
285
|
-
try {
|
|
286
|
-
const pkg = JSON.parse(readFileSync5(path6.join(packageRoot, "package.json"), "utf8"));
|
|
287
|
-
return typeof pkg.version === "string" ? pkg.version : VERSION_FALLBACK;
|
|
288
|
-
} catch {
|
|
289
|
-
return VERSION_FALLBACK;
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
// src/init.ts
|
|
294
|
-
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readdirSync, readFileSync as readFileSync6, writeFileSync as writeFileSync2 } from "node:fs";
|
|
295
|
-
import * as path7 from "node:path";
|
|
296
|
-
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
295
|
+
// src/bob.ts
|
|
296
|
+
import { homedir } from "node:os";
|
|
297
|
+
import * as path5 from "node:path";
|
|
297
298
|
|
|
298
299
|
// src/debug-launcher.ts
|
|
299
300
|
var PLATFORM_TARGETS = {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
301
|
+
"darwin-arm64": {
|
|
302
|
+
enginePlatform: "arm64-macos",
|
|
303
|
+
buildFolder: "arm64-macos",
|
|
304
|
+
executable: "dmengine"
|
|
305
|
+
},
|
|
306
|
+
"darwin-x64": {
|
|
307
|
+
enginePlatform: "x86_64-macos",
|
|
308
|
+
buildFolder: "x86_64-macos",
|
|
309
|
+
executable: "dmengine"
|
|
310
|
+
},
|
|
311
|
+
"linux-x64": {
|
|
312
|
+
enginePlatform: "x86_64-linux",
|
|
313
|
+
buildFolder: "x86_64-linux",
|
|
314
|
+
executable: "dmengine"
|
|
315
|
+
},
|
|
316
|
+
"win32-x64": {
|
|
303
317
|
enginePlatform: "x86_64-win32",
|
|
304
318
|
buildFolder: "x86_64-win32",
|
|
305
319
|
executable: "dmengine.exe"
|
|
@@ -317,7 +331,9 @@ function debugLaunchConfig() {
|
|
|
317
331
|
verbose: false,
|
|
318
332
|
internalConsoleOptions: "openOnSessionStart",
|
|
319
333
|
program: { command: "bun" },
|
|
320
|
-
args: [DEBUG_LAUNCHER_REL]
|
|
334
|
+
args: [DEBUG_LAUNCHER_REL],
|
|
335
|
+
scriptFiles: ["src/**/*.ts.script"],
|
|
336
|
+
scriptRoots: [".", "src"]
|
|
321
337
|
};
|
|
322
338
|
}
|
|
323
339
|
var VSCODE_LAUNCH_CONTENT = {
|
|
@@ -345,9 +361,9 @@ const PLATFORM_TARGETS: Record<string, EngineTarget> = ${targets};
|
|
|
345
361
|
const ENGINE_INFO_URL = "${ENGINE_INFO_URL}";
|
|
346
362
|
const ENGINE_ARCHIVE_BASE = "${ENGINE_ARCHIVE_BASE}";
|
|
347
363
|
|
|
348
|
-
const target = PLATFORM_TARGETS[process.platform];
|
|
364
|
+
const target = PLATFORM_TARGETS[\`\${process.platform}-\${process.arch}\`];
|
|
349
365
|
if (!target) {
|
|
350
|
-
console.error(\`Unsupported platform: \${process.platform}\`);
|
|
366
|
+
console.error(\`Unsupported platform: \${process.platform}-\${process.arch}\`);
|
|
351
367
|
process.exit(1);
|
|
352
368
|
}
|
|
353
369
|
|
|
@@ -405,22 +421,205 @@ process.exit(await proc.exited);
|
|
|
405
421
|
}
|
|
406
422
|
var DEBUG_LAUNCHER_SOURCE = renderDebugLauncher();
|
|
407
423
|
|
|
424
|
+
// src/bob.ts
|
|
425
|
+
function bobDownloadUrl(sha1) {
|
|
426
|
+
return `${ENGINE_ARCHIVE_BASE}/${sha1}/bob/bob.jar`;
|
|
427
|
+
}
|
|
428
|
+
function bobCacheDir(env = process.env, home = homedir) {
|
|
429
|
+
if (env.DEFOLD_TYPESCRIPT_CACHE) {
|
|
430
|
+
return path5.join(env.DEFOLD_TYPESCRIPT_CACHE, "bob");
|
|
431
|
+
}
|
|
432
|
+
return path5.join(env.XDG_CACHE_HOME ?? path5.join(home(), ".cache"), "defold-typescript", "bob");
|
|
433
|
+
}
|
|
434
|
+
function bobCachePath(opts) {
|
|
435
|
+
return path5.join(opts.cacheDir, opts.sha1, "bob.jar");
|
|
436
|
+
}
|
|
437
|
+
function resolveBobJar(opts) {
|
|
438
|
+
const jarPath = bobCachePath({ sha1: opts.sha1, cacheDir: opts.cacheDir });
|
|
439
|
+
return { jarPath, cached: opts.probe(jarPath) };
|
|
440
|
+
}
|
|
441
|
+
function resolveJava(opts) {
|
|
442
|
+
if (opts.override) {
|
|
443
|
+
return opts.override;
|
|
444
|
+
}
|
|
445
|
+
if (opts.probe("java")) {
|
|
446
|
+
return "java";
|
|
447
|
+
}
|
|
448
|
+
throw new Error('defold-typescript: no Java runtime found. Install a JDK and ensure "java" is on PATH, ' + "or pass --java <path> (or set DEFOLD_JAVA). bob.jar requires a JVM to run.");
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// src/bob-command.ts
|
|
452
|
+
var DEFOLD_SUBCOMMANDS = ["resolve", "build", "bundle"];
|
|
453
|
+
function isDefoldSubcommand(value) {
|
|
454
|
+
return value !== undefined && DEFOLD_SUBCOMMANDS.includes(value);
|
|
455
|
+
}
|
|
456
|
+
function composeBobArgv(opts) {
|
|
457
|
+
const base = [opts.java, "-jar", opts.jar];
|
|
458
|
+
const server = opts.buildServer ? ["--build-server", opts.buildServer] : [];
|
|
459
|
+
switch (opts.subcommand) {
|
|
460
|
+
case "resolve":
|
|
461
|
+
return [...base, ...server, "resolve"];
|
|
462
|
+
case "build":
|
|
463
|
+
return [...base, "--variant", "debug", ...server, "build"];
|
|
464
|
+
case "bundle":
|
|
465
|
+
return [...base, ...server, "bundle"];
|
|
466
|
+
default:
|
|
467
|
+
throw new Error(`defold-typescript: unknown defold subcommand "${opts.subcommand}"; expected resolve|build|bundle.`);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
async function runDefoldCommand(opts) {
|
|
471
|
+
const { io } = opts;
|
|
472
|
+
const sha = await io.fetchSha();
|
|
473
|
+
const { jarPath, cached } = resolveBobJar({
|
|
474
|
+
sha1: sha,
|
|
475
|
+
cacheDir: io.cacheDir,
|
|
476
|
+
probe: io.probe
|
|
477
|
+
});
|
|
478
|
+
if (!cached) {
|
|
479
|
+
await io.download(bobDownloadUrl(sha), jarPath);
|
|
480
|
+
}
|
|
481
|
+
const java = resolveJava({
|
|
482
|
+
...opts.java !== undefined ? { override: opts.java } : {},
|
|
483
|
+
probe: io.javaProbe
|
|
484
|
+
});
|
|
485
|
+
const argv = composeBobArgv({
|
|
486
|
+
java,
|
|
487
|
+
jar: jarPath,
|
|
488
|
+
subcommand: opts.subcommand,
|
|
489
|
+
...opts.buildServer !== undefined ? { buildServer: opts.buildServer } : {}
|
|
490
|
+
});
|
|
491
|
+
const exitCode = await io.spawn(argv, opts.cwd);
|
|
492
|
+
return { ok: exitCode === 0, subcommand: opts.subcommand, exitCode, argv };
|
|
493
|
+
}
|
|
494
|
+
async function fetchStableSha() {
|
|
495
|
+
const res = await fetch(ENGINE_INFO_URL);
|
|
496
|
+
if (!res.ok) {
|
|
497
|
+
throw new Error(`defold-typescript: could not resolve the stable Defold sha (${ENGINE_INFO_URL} -> ${res.status} ${res.statusText}).`);
|
|
498
|
+
}
|
|
499
|
+
const info = await res.json();
|
|
500
|
+
if (!info.sha1) {
|
|
501
|
+
throw new Error(`defold-typescript: ${ENGINE_INFO_URL} returned no sha1.`);
|
|
502
|
+
}
|
|
503
|
+
return info.sha1;
|
|
504
|
+
}
|
|
505
|
+
function javaOnPath(cmd, env = process.env) {
|
|
506
|
+
const pathVar = env.PATH ?? env.Path ?? "";
|
|
507
|
+
const exts = process.platform === "win32" ? [".exe", ".bat", ".cmd", ""] : [""];
|
|
508
|
+
for (const dir of pathVar.split(delimiter).filter(Boolean)) {
|
|
509
|
+
for (const ext of exts) {
|
|
510
|
+
if (existsSync2(join6(dir, cmd + ext))) {
|
|
511
|
+
return true;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
return false;
|
|
516
|
+
}
|
|
517
|
+
async function spawnInherit(argv, cwd) {
|
|
518
|
+
const proc = Bun.spawn(argv, { cwd, stdio: ["inherit", "inherit", "inherit"] });
|
|
519
|
+
return proc.exited;
|
|
520
|
+
}
|
|
521
|
+
async function downloadTo(url, dest) {
|
|
522
|
+
const res = await fetch(url);
|
|
523
|
+
if (!res.ok) {
|
|
524
|
+
throw new Error(`defold-typescript: bob.jar download failed (${url} -> ${res.status} ${res.statusText}).`);
|
|
525
|
+
}
|
|
526
|
+
mkdirSync2(dirname3(dest), { recursive: true });
|
|
527
|
+
await Bun.write(dest, res);
|
|
528
|
+
}
|
|
529
|
+
function defaultDefoldIo() {
|
|
530
|
+
return {
|
|
531
|
+
cacheDir: bobCacheDir(),
|
|
532
|
+
fetchSha: fetchStableSha,
|
|
533
|
+
probe: existsSync2,
|
|
534
|
+
javaProbe: (cmd) => javaOnPath(cmd),
|
|
535
|
+
spawn: spawnInherit,
|
|
536
|
+
download: downloadTo
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// src/build.ts
|
|
541
|
+
import { readFileSync as readFileSync4 } from "node:fs";
|
|
542
|
+
import * as path6 from "node:path";
|
|
543
|
+
import { transpileProject } from "@defold-typescript/transpiler";
|
|
544
|
+
function runBuild(opts) {
|
|
545
|
+
const { cwd } = opts;
|
|
546
|
+
const config = readBuildConfig(cwd);
|
|
547
|
+
const seen = new Set;
|
|
548
|
+
for (const pattern of config.include) {
|
|
549
|
+
for (const match of scanFilesSync(cwd, pattern)) {
|
|
550
|
+
seen.add(toPosix(match));
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
const sources = [...seen].sort();
|
|
554
|
+
if (sources.length === 0) {
|
|
555
|
+
return { written: [] };
|
|
556
|
+
}
|
|
557
|
+
const files = {};
|
|
558
|
+
for (const rel of sources) {
|
|
559
|
+
files[rel] = readFileSync4(path6.join(cwd, rel), "utf8");
|
|
560
|
+
}
|
|
561
|
+
const result = transpileProject({ files });
|
|
562
|
+
const failures = collectFailures(result.diagnostics);
|
|
563
|
+
const written = [];
|
|
564
|
+
for (const rel of sources) {
|
|
565
|
+
if (failures.has(rel)) {
|
|
566
|
+
continue;
|
|
567
|
+
}
|
|
568
|
+
const lua = result.lua[rel];
|
|
569
|
+
if (!lua) {
|
|
570
|
+
continue;
|
|
571
|
+
}
|
|
572
|
+
const outputRel = computeOutputRel(rel, config, detectSourceOutputKind(files[rel] ?? ""));
|
|
573
|
+
writeScriptFile(cwd, outputRel, lua, result.sourceMaps[rel]);
|
|
574
|
+
written.push(outputRel);
|
|
575
|
+
}
|
|
576
|
+
throwIfFailures(failures);
|
|
577
|
+
return { written: written.sort() };
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
// src/cli-version.ts
|
|
581
|
+
import { readFileSync as readFileSync5 } from "node:fs";
|
|
582
|
+
import * as path7 from "node:path";
|
|
583
|
+
import { fileURLToPath } from "node:url";
|
|
584
|
+
var VERSION_FALLBACK = "0.0.0";
|
|
585
|
+
function defaultPackageRoot() {
|
|
586
|
+
return path7.join(path7.dirname(fileURLToPath(import.meta.url)), "..");
|
|
587
|
+
}
|
|
588
|
+
function readCliVersion(packageRoot = defaultPackageRoot()) {
|
|
589
|
+
try {
|
|
590
|
+
const pkg = JSON.parse(readFileSync5(path7.join(packageRoot, "package.json"), "utf8"));
|
|
591
|
+
return typeof pkg.version === "string" ? pkg.version : VERSION_FALLBACK;
|
|
592
|
+
} catch {
|
|
593
|
+
return VERSION_FALLBACK;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// src/init.ts
|
|
598
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync3, readdirSync, readFileSync as readFileSync6, writeFileSync as writeFileSync2 } from "node:fs";
|
|
599
|
+
import * as path8 from "node:path";
|
|
600
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
601
|
+
|
|
408
602
|
// src/mise-scaffold.ts
|
|
409
603
|
var MANAGED_MARKER = "# managed by @defold-typescript";
|
|
410
604
|
var MISE_TASKS_TOML = `${MANAGED_MARKER}
|
|
411
605
|
[tasks."defold-typescript:build"]
|
|
412
|
-
description = "Build the TypeScript sources with the
|
|
413
|
-
run = "bunx
|
|
606
|
+
description = "Build the TypeScript sources with the defold-typescript CLI"
|
|
607
|
+
run = "bunx @defold-typescript/cli build"
|
|
414
608
|
|
|
415
609
|
${MANAGED_MARKER}
|
|
416
610
|
[tasks."defold-typescript:watch"]
|
|
417
|
-
description = "Watch and rebuild the TypeScript sources with the
|
|
418
|
-
run = "bunx
|
|
611
|
+
description = "Watch and rebuild the TypeScript sources with the defold-typescript CLI"
|
|
612
|
+
run = "bunx @defold-typescript/cli watch"
|
|
613
|
+
|
|
614
|
+
${MANAGED_MARKER}
|
|
615
|
+
[tasks."defold-typescript:setup-debug"]
|
|
616
|
+
description = "Wire the lldebugger game.project dependency and entry-script bootstrap with the defold-typescript CLI"
|
|
617
|
+
run = "bunx @defold-typescript/cli setup-debug"
|
|
419
618
|
|
|
420
619
|
${MANAGED_MARKER}
|
|
421
620
|
[tasks."defold-typescript:upgrade"]
|
|
422
621
|
description = "Upgrade the defold-typescript CLI to its latest release and re-pin the types dependency"
|
|
423
|
-
run = ["bunx @defold-typescript/cli@latest init --force", "bun install"]
|
|
622
|
+
run = ["bunx @defold-typescript/cli@latest init --force --suppress-install-reminder", "bun install"]
|
|
424
623
|
`;
|
|
425
624
|
function stripManagedBlocks(text) {
|
|
426
625
|
const lines = text.split(`
|
|
@@ -479,18 +678,6 @@ function isComponentPath(relPath) {
|
|
|
479
678
|
}
|
|
480
679
|
return Object.keys(KIND_BY_EXT).some((ext) => relPath.endsWith(ext));
|
|
481
680
|
}
|
|
482
|
-
function detectScriptKinds(cwd) {
|
|
483
|
-
const kinds = new Set;
|
|
484
|
-
for (const [ext, kind] of Object.entries(KIND_BY_EXT)) {
|
|
485
|
-
for (const match of scanFilesSync(cwd, `**/*${ext}`)) {
|
|
486
|
-
if (!isSkipped(match) && !isGeneratedScript(match)) {
|
|
487
|
-
kinds.add(kind);
|
|
488
|
-
break;
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
return kinds;
|
|
493
|
-
}
|
|
494
681
|
function selectScriptKind(kinds) {
|
|
495
682
|
if (kinds.size !== 1) {
|
|
496
683
|
return null;
|
|
@@ -504,19 +691,6 @@ function selectScriptKindEntrypoint(kinds) {
|
|
|
504
691
|
const kind = selectScriptKind(kinds);
|
|
505
692
|
return kind === null ? DEFAULT_TYPES_ENTRYPOINT : `${DEFAULT_TYPES_ENTRYPOINT}/${kind}`;
|
|
506
693
|
}
|
|
507
|
-
var RESTRICTED_MODULES = {
|
|
508
|
-
script: "",
|
|
509
|
-
"gui-script": "gui",
|
|
510
|
-
"render-script": "render"
|
|
511
|
-
};
|
|
512
|
-
var ALL_RESTRICTED_MODULES = ["gui", "render"];
|
|
513
|
-
function excludedModulesForKind(kind) {
|
|
514
|
-
if (kind === null) {
|
|
515
|
-
return new Set;
|
|
516
|
-
}
|
|
517
|
-
const allowed = RESTRICTED_MODULES[kind];
|
|
518
|
-
return new Set(ALL_RESTRICTED_MODULES.filter((mod) => mod !== allowed));
|
|
519
|
-
}
|
|
520
694
|
|
|
521
695
|
// src/init.ts
|
|
522
696
|
var CONFLICTING_TS_CONFIGS = [
|
|
@@ -533,11 +707,29 @@ var TSCONFIG_COMPILER_OPTIONS = {
|
|
|
533
707
|
strict: true,
|
|
534
708
|
skipLibCheck: true
|
|
535
709
|
};
|
|
536
|
-
var GITIGNORE_LINES = [
|
|
710
|
+
var GITIGNORE_LINES = [
|
|
711
|
+
"src/**/*.ts.script",
|
|
712
|
+
"src/**/*.ts.script.map",
|
|
713
|
+
"src/**/*.ts.gui_script",
|
|
714
|
+
"src/**/*.ts.gui_script.map",
|
|
715
|
+
"src/**/*.ts.render_script",
|
|
716
|
+
"src/**/*.ts.render_script.map",
|
|
717
|
+
"src/**/*.lua",
|
|
718
|
+
"src/**/*.lua.map"
|
|
719
|
+
];
|
|
537
720
|
var BIOME_JSON_CONTENT = {
|
|
538
721
|
$schema: "https://biomejs.dev/schemas/2.4.15/schema.json",
|
|
539
722
|
files: {
|
|
540
|
-
includes: [
|
|
723
|
+
includes: [
|
|
724
|
+
"src/**/*.ts",
|
|
725
|
+
"!**/dist",
|
|
726
|
+
"!**/node_modules",
|
|
727
|
+
"!**/*.ts.script",
|
|
728
|
+
"!**/*.ts.gui_script",
|
|
729
|
+
"!**/*.ts.render_script",
|
|
730
|
+
"!src/**/*.lua",
|
|
731
|
+
"!src/**/*.lua.map"
|
|
732
|
+
]
|
|
541
733
|
},
|
|
542
734
|
formatter: {
|
|
543
735
|
enabled: true,
|
|
@@ -569,9 +761,15 @@ var BIOME_JSON_CONTENT = {
|
|
|
569
761
|
}
|
|
570
762
|
};
|
|
571
763
|
var VSCODE_EXTENSIONS_CONTENT = {
|
|
572
|
-
recommendations: ["
|
|
764
|
+
recommendations: ["tomblind.local-lua-debugger-vscode"],
|
|
573
765
|
unwantedRecommendations: ["johnnymorganz.luau-lsp"]
|
|
574
766
|
};
|
|
767
|
+
var MANAGED_RECOMMENDATIONS = [
|
|
768
|
+
"tomblind.local-lua-debugger-vscode",
|
|
769
|
+
"sumneko.lua",
|
|
770
|
+
"astronachos.defold"
|
|
771
|
+
];
|
|
772
|
+
var MANAGED_UNWANTED = ["johnnymorganz.luau-lsp"];
|
|
575
773
|
var VSCODE_SETTINGS_CONTENT = {
|
|
576
774
|
"Lua.workspace.ignoreDir": ["src"]
|
|
577
775
|
};
|
|
@@ -616,7 +814,7 @@ function inlineSnippetBody(factory, includeOnInput) {
|
|
|
616
814
|
return [
|
|
617
815
|
`import { ${factory} } from "@defold-typescript/types";`,
|
|
618
816
|
"",
|
|
619
|
-
`export
|
|
817
|
+
`export default ${factory}({`,
|
|
620
818
|
` // ${HOOK_COMMENTS.init}`,
|
|
621
819
|
" init() {",
|
|
622
820
|
" return { $0 };",
|
|
@@ -634,7 +832,7 @@ function typedSnippetBody(factory, includeOnInput) {
|
|
|
634
832
|
" $1",
|
|
635
833
|
"};",
|
|
636
834
|
"",
|
|
637
|
-
`export
|
|
835
|
+
`export default ${factory}<Self>({`,
|
|
638
836
|
` // ${HOOK_COMMENTS.init}`,
|
|
639
837
|
" init(): Self {",
|
|
640
838
|
" return { $0 };",
|
|
@@ -681,21 +879,20 @@ var VSCODE_SNIPPETS_CONTENT = {
|
|
|
681
879
|
description: "Empty Defold render script with an explicit Self type."
|
|
682
880
|
}
|
|
683
881
|
};
|
|
684
|
-
var MAIN_TS_CONTENT = `
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
function final(self) end
|
|
882
|
+
var MAIN_TS_CONTENT = `import { defineScript } from "@defold-typescript/types";
|
|
883
|
+
|
|
884
|
+
export default defineScript({
|
|
885
|
+
init() {
|
|
886
|
+
const start = vmath.vector3(0, 0, 0);
|
|
887
|
+
return { start };
|
|
888
|
+
},
|
|
889
|
+
});
|
|
693
890
|
`;
|
|
694
891
|
var MAIN_COLLECTION_CONTENT = `name: "main"
|
|
695
892
|
scale_along_z: 0
|
|
696
893
|
embedded_instances {
|
|
697
894
|
id: "main"
|
|
698
|
-
data: "components {\\n id: \\"main\\"\\n component: \\"/
|
|
895
|
+
data: "components {\\n id: \\"main\\"\\n component: \\"/src/main.ts.script\\"\\n}\\n"
|
|
699
896
|
position { x: 0.0 y: 0.0 z: 0.0 }
|
|
700
897
|
rotation { x: 0.0 y: 0.0 z: 0.0 w: 1.0 }
|
|
701
898
|
scale3 { x: 1.0 y: 1.0 z: 1.0 }
|
|
@@ -703,8 +900,8 @@ embedded_instances {
|
|
|
703
900
|
`;
|
|
704
901
|
function typesVersionSpec() {
|
|
705
902
|
try {
|
|
706
|
-
const here =
|
|
707
|
-
const pkg = JSON.parse(readFileSync6(
|
|
903
|
+
const here = path8.dirname(fileURLToPath2(import.meta.url));
|
|
904
|
+
const pkg = JSON.parse(readFileSync6(path8.join(here, "..", "package.json"), "utf8"));
|
|
708
905
|
return pkg.version ? `^${pkg.version}` : "latest";
|
|
709
906
|
} catch {
|
|
710
907
|
return "latest";
|
|
@@ -728,8 +925,8 @@ function writeJson(filePath, value) {
|
|
|
728
925
|
`);
|
|
729
926
|
}
|
|
730
927
|
function writeGitignore(cwd) {
|
|
731
|
-
const gitignorePath =
|
|
732
|
-
if (
|
|
928
|
+
const gitignorePath = path8.join(cwd, ".gitignore");
|
|
929
|
+
if (existsSync3(gitignorePath)) {
|
|
733
930
|
const existing = readFileSync6(gitignorePath, "utf8");
|
|
734
931
|
const present = new Set(existing.split(`
|
|
735
932
|
`).map((line) => line.trim()));
|
|
@@ -750,16 +947,16 @@ function writeGitignore(cwd) {
|
|
|
750
947
|
}
|
|
751
948
|
}
|
|
752
949
|
function writeBiome(cwd, written) {
|
|
753
|
-
const biomePath =
|
|
754
|
-
if (
|
|
950
|
+
const biomePath = path8.join(cwd, "biome.json");
|
|
951
|
+
if (existsSync3(biomePath)) {
|
|
755
952
|
return;
|
|
756
953
|
}
|
|
757
954
|
writeJson(biomePath, BIOME_JSON_CONTENT);
|
|
758
955
|
written.push("biome.json");
|
|
759
956
|
}
|
|
760
957
|
function writeMiseTasks(cwd, written) {
|
|
761
|
-
const misePath =
|
|
762
|
-
const existing =
|
|
958
|
+
const misePath = path8.join(cwd, "mise.toml");
|
|
959
|
+
const existing = existsSync3(misePath) ? readFileSync6(misePath, "utf8") : undefined;
|
|
763
960
|
writeFileSync2(misePath, mergeMiseToml(existing));
|
|
764
961
|
written.push("mise.toml");
|
|
765
962
|
}
|
|
@@ -823,6 +1020,27 @@ function unionStrings(existing, additions) {
|
|
|
823
1020
|
}
|
|
824
1021
|
return out;
|
|
825
1022
|
}
|
|
1023
|
+
function reconcileManagedList(existing, managed, canonical) {
|
|
1024
|
+
const managedSet = new Set(managed);
|
|
1025
|
+
const canonicalSet = new Set(canonical);
|
|
1026
|
+
const out = [];
|
|
1027
|
+
const values = Array.isArray(existing) ? existing.filter((value) => typeof value === "string") : [];
|
|
1028
|
+
for (const value of values) {
|
|
1029
|
+
if (out.includes(value)) {
|
|
1030
|
+
continue;
|
|
1031
|
+
}
|
|
1032
|
+
if (managedSet.has(value) && !canonicalSet.has(value)) {
|
|
1033
|
+
continue;
|
|
1034
|
+
}
|
|
1035
|
+
out.push(value);
|
|
1036
|
+
}
|
|
1037
|
+
for (const value of canonical) {
|
|
1038
|
+
if (!out.includes(value)) {
|
|
1039
|
+
out.push(value);
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
return out;
|
|
1043
|
+
}
|
|
826
1044
|
function readVscodeJson(filePath) {
|
|
827
1045
|
try {
|
|
828
1046
|
const parsed = parseJsonc(readFileSync6(filePath, "utf8"));
|
|
@@ -832,26 +1050,29 @@ function readVscodeJson(filePath) {
|
|
|
832
1050
|
}
|
|
833
1051
|
}
|
|
834
1052
|
function writeVscodeExtensions(cwd, written) {
|
|
835
|
-
const dir =
|
|
836
|
-
const filePath =
|
|
837
|
-
if (
|
|
1053
|
+
const dir = path8.join(cwd, ".vscode");
|
|
1054
|
+
const filePath = path8.join(dir, "extensions.json");
|
|
1055
|
+
if (existsSync3(filePath)) {
|
|
838
1056
|
const existing = readVscodeJson(filePath);
|
|
839
1057
|
if (existing === null) {
|
|
840
1058
|
return;
|
|
841
1059
|
}
|
|
842
|
-
|
|
843
|
-
existing.
|
|
844
|
-
|
|
1060
|
+
const before = JSON.stringify(existing);
|
|
1061
|
+
existing.recommendations = reconcileManagedList(existing.recommendations, MANAGED_RECOMMENDATIONS, VSCODE_EXTENSIONS_CONTENT.recommendations);
|
|
1062
|
+
existing.unwantedRecommendations = reconcileManagedList(existing.unwantedRecommendations, MANAGED_UNWANTED, VSCODE_EXTENSIONS_CONTENT.unwantedRecommendations);
|
|
1063
|
+
if (JSON.stringify(existing) !== before) {
|
|
1064
|
+
writeJson(filePath, existing);
|
|
1065
|
+
}
|
|
845
1066
|
return;
|
|
846
1067
|
}
|
|
847
|
-
|
|
1068
|
+
mkdirSync3(dir, { recursive: true });
|
|
848
1069
|
writeJson(filePath, VSCODE_EXTENSIONS_CONTENT);
|
|
849
1070
|
written.push(".vscode/extensions.json");
|
|
850
1071
|
}
|
|
851
1072
|
function writeVscodeSettings(cwd, written) {
|
|
852
|
-
const dir =
|
|
853
|
-
const filePath =
|
|
854
|
-
if (
|
|
1073
|
+
const dir = path8.join(cwd, ".vscode");
|
|
1074
|
+
const filePath = path8.join(dir, "settings.json");
|
|
1075
|
+
if (existsSync3(filePath)) {
|
|
855
1076
|
const existing = readVscodeJson(filePath);
|
|
856
1077
|
if (existing === null) {
|
|
857
1078
|
return;
|
|
@@ -860,14 +1081,14 @@ function writeVscodeSettings(cwd, written) {
|
|
|
860
1081
|
writeJson(filePath, existing);
|
|
861
1082
|
return;
|
|
862
1083
|
}
|
|
863
|
-
|
|
1084
|
+
mkdirSync3(dir, { recursive: true });
|
|
864
1085
|
writeJson(filePath, VSCODE_SETTINGS_CONTENT);
|
|
865
1086
|
written.push(".vscode/settings.json");
|
|
866
1087
|
}
|
|
867
1088
|
function writeVscodeSnippets(cwd, written) {
|
|
868
|
-
const dir =
|
|
869
|
-
const filePath =
|
|
870
|
-
if (
|
|
1089
|
+
const dir = path8.join(cwd, ".vscode");
|
|
1090
|
+
const filePath = path8.join(dir, "defold-typescript.code-snippets");
|
|
1091
|
+
if (existsSync3(filePath)) {
|
|
871
1092
|
const existing = readVscodeJson(filePath);
|
|
872
1093
|
if (existing === null) {
|
|
873
1094
|
return;
|
|
@@ -880,15 +1101,15 @@ function writeVscodeSnippets(cwd, written) {
|
|
|
880
1101
|
writeJson(filePath, existing);
|
|
881
1102
|
return;
|
|
882
1103
|
}
|
|
883
|
-
|
|
1104
|
+
mkdirSync3(dir, { recursive: true });
|
|
884
1105
|
writeJson(filePath, VSCODE_SNIPPETS_CONTENT);
|
|
885
1106
|
written.push(".vscode/defold-typescript.code-snippets");
|
|
886
1107
|
}
|
|
887
1108
|
function writeVscodeLaunch(cwd, written) {
|
|
888
|
-
const dir =
|
|
889
|
-
const filePath =
|
|
1109
|
+
const dir = path8.join(cwd, ".vscode");
|
|
1110
|
+
const filePath = path8.join(dir, "launch.json");
|
|
890
1111
|
const ours = debugLaunchConfig();
|
|
891
|
-
if (
|
|
1112
|
+
if (existsSync3(filePath)) {
|
|
892
1113
|
const existing = readVscodeJson(filePath);
|
|
893
1114
|
if (existing === null) {
|
|
894
1115
|
return;
|
|
@@ -903,36 +1124,35 @@ function writeVscodeLaunch(cwd, written) {
|
|
|
903
1124
|
writeJson(filePath, existing);
|
|
904
1125
|
return;
|
|
905
1126
|
}
|
|
906
|
-
|
|
1127
|
+
mkdirSync3(dir, { recursive: true });
|
|
907
1128
|
writeJson(filePath, VSCODE_LAUNCH_CONTENT);
|
|
908
1129
|
written.push(".vscode/launch.json");
|
|
909
1130
|
}
|
|
910
1131
|
function writeVscodeDebugLauncher(cwd, written) {
|
|
911
|
-
const dir =
|
|
912
|
-
const filePath =
|
|
913
|
-
if (
|
|
1132
|
+
const dir = path8.join(cwd, ".vscode");
|
|
1133
|
+
const filePath = path8.join(dir, "defold-debug.ts");
|
|
1134
|
+
if (existsSync3(filePath)) {
|
|
914
1135
|
return;
|
|
915
1136
|
}
|
|
916
|
-
|
|
1137
|
+
mkdirSync3(dir, { recursive: true });
|
|
917
1138
|
writeFileSync2(filePath, DEBUG_LAUNCHER_SOURCE);
|
|
918
1139
|
written.push(".vscode/defold-debug.ts");
|
|
919
1140
|
}
|
|
920
1141
|
function writeTsSurface(cwd, written, force = false) {
|
|
921
|
-
|
|
922
|
-
writeFileSync2(
|
|
1142
|
+
mkdirSync3(path8.join(cwd, "src"), { recursive: true });
|
|
1143
|
+
writeFileSync2(path8.join(cwd, "src", "main.ts"), MAIN_TS_CONTENT);
|
|
923
1144
|
written.push("src/main.ts");
|
|
924
|
-
const kinds = detectScriptKinds(cwd);
|
|
925
1145
|
const tsconfig = {
|
|
926
1146
|
compilerOptions: {
|
|
927
1147
|
...TSCONFIG_COMPILER_OPTIONS,
|
|
928
|
-
types: [
|
|
1148
|
+
types: [DEFAULT_TYPES_ENTRYPOINT]
|
|
929
1149
|
},
|
|
930
1150
|
include: ["src/**/*.ts"]
|
|
931
1151
|
};
|
|
932
|
-
writeJson(
|
|
1152
|
+
writeJson(path8.join(cwd, "tsconfig.json"), tsconfig);
|
|
933
1153
|
written.push("tsconfig.json");
|
|
934
|
-
const pkgPath =
|
|
935
|
-
if (
|
|
1154
|
+
const pkgPath = path8.join(cwd, "package.json");
|
|
1155
|
+
if (existsSync3(pkgPath)) {
|
|
936
1156
|
const existing = JSON.parse(readFileSync6(pkgPath, "utf8"));
|
|
937
1157
|
const devDeps = { ...existing.devDependencies ?? {} };
|
|
938
1158
|
for (const [name, version] of Object.entries(SCAFFOLD_DEV_DEPS)) {
|
|
@@ -946,7 +1166,7 @@ function writeTsSurface(cwd, written, force = false) {
|
|
|
946
1166
|
writeJson(pkgPath, existing);
|
|
947
1167
|
} else {
|
|
948
1168
|
const fresh = {
|
|
949
|
-
name:
|
|
1169
|
+
name: path8.basename(cwd),
|
|
950
1170
|
version: "0.0.0",
|
|
951
1171
|
type: "module",
|
|
952
1172
|
devDependencies: { ...SCAFFOLD_DEV_DEPS },
|
|
@@ -964,43 +1184,56 @@ function writeTsSurface(cwd, written, force = false) {
|
|
|
964
1184
|
writeVscodeSnippets(cwd, written);
|
|
965
1185
|
writeVscodeLaunch(cwd, written);
|
|
966
1186
|
writeVscodeDebugLauncher(cwd, written);
|
|
967
|
-
return selectScriptKind(kinds);
|
|
968
1187
|
}
|
|
969
1188
|
function runNewProjectInit(cwd, force = false) {
|
|
970
|
-
if (!
|
|
971
|
-
|
|
1189
|
+
if (!existsSync3(cwd)) {
|
|
1190
|
+
mkdirSync3(cwd, { recursive: true });
|
|
972
1191
|
} else if (readdirSync(cwd).length > 0 && !force) {
|
|
973
1192
|
throw new Error(`defold-typescript init: refusing to synthesize a new Defold project into non-empty directory ${cwd}. Pass --force to proceed.`);
|
|
974
1193
|
}
|
|
975
1194
|
const written = [];
|
|
976
|
-
writeFileSync2(
|
|
977
|
-
title = ${
|
|
1195
|
+
writeFileSync2(path8.join(cwd, "game.project"), `[project]
|
|
1196
|
+
title = ${path8.basename(cwd)}
|
|
978
1197
|
main_collection = /main/main.collectionc
|
|
979
1198
|
`);
|
|
980
1199
|
written.push("game.project");
|
|
981
|
-
|
|
982
|
-
writeFileSync2(
|
|
1200
|
+
mkdirSync3(path8.join(cwd, "main"), { recursive: true });
|
|
1201
|
+
writeFileSync2(path8.join(cwd, "main", "main.collection"), MAIN_COLLECTION_CONTENT);
|
|
983
1202
|
written.push("main/main.collection");
|
|
984
|
-
|
|
985
|
-
written
|
|
986
|
-
const scriptKind = writeTsSurface(cwd, written, force);
|
|
987
|
-
return { written, scriptKind };
|
|
1203
|
+
writeTsSurface(cwd, written, force);
|
|
1204
|
+
return { written };
|
|
988
1205
|
}
|
|
989
1206
|
function runInit(opts) {
|
|
990
1207
|
const { cwd, force = false } = opts;
|
|
991
|
-
if (!
|
|
1208
|
+
if (!existsSync3(path8.join(cwd, "game.project"))) {
|
|
992
1209
|
return runNewProjectInit(cwd, force);
|
|
993
1210
|
}
|
|
994
1211
|
if (!force) {
|
|
995
1212
|
for (const rel of CONFLICTING_TS_CONFIGS) {
|
|
996
|
-
if (
|
|
1213
|
+
if (existsSync3(path8.join(cwd, rel))) {
|
|
997
1214
|
throw new Error(`defold-typescript init: refusing to overwrite existing TS config: ${rel}. Pass --force to overwrite.`);
|
|
998
1215
|
}
|
|
999
1216
|
}
|
|
1000
1217
|
}
|
|
1001
1218
|
const written = [];
|
|
1002
|
-
|
|
1003
|
-
return { written
|
|
1219
|
+
writeTsSurface(cwd, written, force);
|
|
1220
|
+
return { written };
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
// src/install-reminder.ts
|
|
1224
|
+
function installHint(env = process.env) {
|
|
1225
|
+
const agent = env.npm_config_user_agent ?? "";
|
|
1226
|
+
const manager = agent.split("/")[0];
|
|
1227
|
+
if (manager === "pnpm") {
|
|
1228
|
+
return "pnpm install";
|
|
1229
|
+
}
|
|
1230
|
+
if (manager === "yarn") {
|
|
1231
|
+
return "yarn install";
|
|
1232
|
+
}
|
|
1233
|
+
if (manager === "npm") {
|
|
1234
|
+
return "npm install";
|
|
1235
|
+
}
|
|
1236
|
+
return "bun install";
|
|
1004
1237
|
}
|
|
1005
1238
|
|
|
1006
1239
|
// src/json-output.ts
|
|
@@ -1009,24 +1242,43 @@ function renderResult(input) {
|
|
|
1009
1242
|
const base = ok ? { command: input.command, ok, written: input.written ?? [] } : { command: input.command, ok, error: input.error };
|
|
1010
1243
|
const withVersion = input.defoldVersion === undefined ? base : { ...base, defoldVersion: input.defoldVersion };
|
|
1011
1244
|
const withSurface = "apiSurface" in input ? { ...withVersion, apiSurface: input.apiSurface } : withVersion;
|
|
1012
|
-
const
|
|
1013
|
-
const
|
|
1245
|
+
const withMaterialized = "materializedSurface" in input ? { ...withSurface, materializedSurface: input.materializedSurface } : withSurface;
|
|
1246
|
+
const withWalls = "directoryWalls" in input ? { ...withMaterialized, directoryWalls: input.directoryWalls } : withMaterialized;
|
|
1247
|
+
const withEligible = "eligible" in input ? { ...withWalls, eligible: input.eligible } : withWalls;
|
|
1248
|
+
const withInstall = "installCommand" in input ? { ...withEligible, installCommand: input.installCommand } : withEligible;
|
|
1249
|
+
const withManual = "manualSteps" in input ? { ...withInstall, manualSteps: input.manualSteps } : withInstall;
|
|
1250
|
+
const withActions = "actions" in input ? { ...withManual, actions: input.actions } : withManual;
|
|
1251
|
+
const withAdded = "addedTo" in input ? { ...withActions, addedTo: input.addedTo } : withActions;
|
|
1252
|
+
const withRemoved = "removedFrom" in input ? { ...withAdded, removedFrom: input.removedFrom } : withAdded;
|
|
1253
|
+
const withBoot = "bootPath" in input ? { ...withRemoved, bootPath: input.bootPath } : withRemoved;
|
|
1254
|
+
const withSub = "subcommand" in input ? { ...withBoot, subcommand: input.subcommand } : withBoot;
|
|
1255
|
+
const payload = "exitCode" in input ? { ...withSub, exitCode: input.exitCode } : withSub;
|
|
1014
1256
|
return `${JSON.stringify(payload)}
|
|
1015
1257
|
`;
|
|
1016
1258
|
}
|
|
1259
|
+
function renderWatchEvent(input) {
|
|
1260
|
+
const ok = input.error === undefined;
|
|
1261
|
+
const base = ok ? { command: "watch", event: input.event, ok, written: input.written ?? [] } : { command: "watch", event: input.event, ok, error: input.error };
|
|
1262
|
+
const withChanged = "changed" in input ? { ...base, changed: input.changed } : base;
|
|
1263
|
+
const withRemoved = "removed" in input ? { ...withChanged, removed: input.removed } : withChanged;
|
|
1264
|
+
return `${JSON.stringify(withRemoved)}
|
|
1265
|
+
`;
|
|
1266
|
+
}
|
|
1017
1267
|
|
|
1018
1268
|
// src/materialize.ts
|
|
1019
1269
|
import {
|
|
1020
1270
|
copyFileSync,
|
|
1021
|
-
existsSync as
|
|
1022
|
-
mkdirSync as
|
|
1271
|
+
existsSync as existsSync4,
|
|
1272
|
+
mkdirSync as mkdirSync4,
|
|
1023
1273
|
readdirSync as readdirSync2,
|
|
1024
1274
|
readFileSync as readFileSync7,
|
|
1025
1275
|
rmSync as rmSync2,
|
|
1026
1276
|
writeFileSync as writeFileSync3
|
|
1027
1277
|
} from "node:fs";
|
|
1028
|
-
import * as
|
|
1278
|
+
import * as path9 from "node:path";
|
|
1029
1279
|
var MATERIALIZED_ROOT = ".defold-types";
|
|
1280
|
+
var CORE_TYPES_REEXPORT = `export * from "@defold-typescript/types/core-types";
|
|
1281
|
+
`;
|
|
1030
1282
|
function writeJson2(filePath, value) {
|
|
1031
1283
|
writeFileSync3(filePath, `${JSON.stringify(value, null, 2)}
|
|
1032
1284
|
`);
|
|
@@ -1040,17 +1292,16 @@ function materializeApiSurface(opts) {
|
|
|
1040
1292
|
return { materializedDir: null, active: null };
|
|
1041
1293
|
}
|
|
1042
1294
|
const { surfaceId } = surface;
|
|
1043
|
-
const relDir =
|
|
1044
|
-
const absDir =
|
|
1045
|
-
|
|
1046
|
-
const
|
|
1047
|
-
const
|
|
1048
|
-
const
|
|
1049
|
-
const
|
|
1050
|
-
const
|
|
1051
|
-
const
|
|
1052
|
-
const
|
|
1053
|
-
const includeEngineGlobals = includeCoreTypes && existsSync3(engineGlobalsSrc);
|
|
1295
|
+
const relDir = path9.posix.join(MATERIALIZED_ROOT, surfaceId);
|
|
1296
|
+
const absDir = path9.join(cwd, MATERIALIZED_ROOT, surfaceId);
|
|
1297
|
+
mkdirSync4(absDir, { recursive: true });
|
|
1298
|
+
const sources = listDts(sourceGeneratedDir).filter((file) => file !== "index.d.ts");
|
|
1299
|
+
const srcDir = path9.resolve(sourceGeneratedDir, "..", "src");
|
|
1300
|
+
const overloads = ["msg-overloads.d.ts", "message-guard.d.ts", "go-overloads.d.ts"].filter((file) => existsSync4(path9.join(srcDir, file)));
|
|
1301
|
+
const coreTypesSrc = path9.join(srcDir, "core-types.ts");
|
|
1302
|
+
const includeCoreTypes = overloads.length > 0 && existsSync4(coreTypesSrc);
|
|
1303
|
+
const engineGlobalsSrc = path9.join(srcDir, "engine-globals.d.ts");
|
|
1304
|
+
const includeEngineGlobals = includeCoreTypes && existsSync4(engineGlobalsSrc);
|
|
1054
1305
|
const wanted = new Set(sources);
|
|
1055
1306
|
for (const file of overloads) {
|
|
1056
1307
|
wanted.add(file);
|
|
@@ -1063,20 +1314,20 @@ function materializeApiSurface(opts) {
|
|
|
1063
1314
|
}
|
|
1064
1315
|
for (const existing of readdirSync2(absDir)) {
|
|
1065
1316
|
if (existing.endsWith(".d.ts") && existing !== "index.d.ts" && !wanted.has(existing)) {
|
|
1066
|
-
rmSync2(
|
|
1317
|
+
rmSync2(path9.join(absDir, existing));
|
|
1067
1318
|
}
|
|
1068
1319
|
}
|
|
1069
1320
|
for (const file of sources) {
|
|
1070
|
-
writeFileSync3(
|
|
1321
|
+
writeFileSync3(path9.join(absDir, file), readFileSync7(path9.join(sourceGeneratedDir, file), "utf8"));
|
|
1071
1322
|
}
|
|
1072
1323
|
if (includeCoreTypes) {
|
|
1073
|
-
writeFileSync3(
|
|
1324
|
+
writeFileSync3(path9.join(absDir, "core-types.d.ts"), CORE_TYPES_REEXPORT);
|
|
1074
1325
|
}
|
|
1075
1326
|
if (includeEngineGlobals) {
|
|
1076
|
-
writeFileSync3(
|
|
1327
|
+
writeFileSync3(path9.join(absDir, "engine-globals.d.ts"), readFileSync7(engineGlobalsSrc, "utf8"));
|
|
1077
1328
|
}
|
|
1078
1329
|
for (const file of overloads) {
|
|
1079
|
-
writeFileSync3(
|
|
1330
|
+
writeFileSync3(path9.join(absDir, file), readFileSync7(path9.join(srcDir, file), "utf8"));
|
|
1080
1331
|
}
|
|
1081
1332
|
const modules = [...sources, ...overloads].map((file) => file.replace(/\.d\.ts$/, ""));
|
|
1082
1333
|
if (includeEngineGlobals) {
|
|
@@ -1084,19 +1335,19 @@ function materializeApiSurface(opts) {
|
|
|
1084
1335
|
}
|
|
1085
1336
|
const imports = modules.map((mod) => `import "./${mod}";`).join(`
|
|
1086
1337
|
`);
|
|
1087
|
-
writeFileSync3(
|
|
1338
|
+
writeFileSync3(path9.join(absDir, "index.d.ts"), `${imports}
|
|
1088
1339
|
|
|
1089
1340
|
export {};
|
|
1090
1341
|
`);
|
|
1091
|
-
writeJson2(
|
|
1342
|
+
writeJson2(path9.join(absDir, "package.json"), {
|
|
1092
1343
|
name: `@defold-typescript/materialized-${surfaceId}`,
|
|
1093
1344
|
types: "index.d.ts"
|
|
1094
1345
|
});
|
|
1095
1346
|
return { materializedDir: relDir, active: surfaceId };
|
|
1096
1347
|
}
|
|
1097
1348
|
function ensureGitignoreLine(cwd, line) {
|
|
1098
|
-
const gitignorePath =
|
|
1099
|
-
if (!
|
|
1349
|
+
const gitignorePath = path9.join(cwd, ".gitignore");
|
|
1350
|
+
if (!existsSync4(gitignorePath)) {
|
|
1100
1351
|
writeFileSync3(gitignorePath, `${line}
|
|
1101
1352
|
`);
|
|
1102
1353
|
return;
|
|
@@ -1117,9 +1368,9 @@ function ensureMaterializedReference(cwd, materializedDir) {
|
|
|
1117
1368
|
if (materializedDir === null) {
|
|
1118
1369
|
return;
|
|
1119
1370
|
}
|
|
1120
|
-
const surfaceId =
|
|
1121
|
-
const tsconfigPath =
|
|
1122
|
-
if (
|
|
1371
|
+
const surfaceId = path9.posix.basename(materializedDir);
|
|
1372
|
+
const tsconfigPath = path9.join(cwd, "tsconfig.json");
|
|
1373
|
+
if (existsSync4(tsconfigPath)) {
|
|
1123
1374
|
const tsconfig = JSON.parse(readFileSync7(tsconfigPath, "utf8"));
|
|
1124
1375
|
const current = tsconfig.compilerOptions ?? {};
|
|
1125
1376
|
const alreadyRepointed = JSON.stringify(current.typeRoots) === JSON.stringify([MATERIALIZED_ROOT]) && JSON.stringify(current.types) === JSON.stringify([surfaceId]);
|
|
@@ -1136,7 +1387,7 @@ function ensureMaterializedReference(cwd, materializedDir) {
|
|
|
1136
1387
|
}
|
|
1137
1388
|
function resolveCurrentSurfaceGeneratedDir() {
|
|
1138
1389
|
const root = resolveTypesPackageRoot();
|
|
1139
|
-
return root === null ? null :
|
|
1390
|
+
return root === null ? null : path9.join(root, "generated");
|
|
1140
1391
|
}
|
|
1141
1392
|
async function materializeRefDocSurface(opts) {
|
|
1142
1393
|
const { cwd, surfaceId, resolveOpts } = opts;
|
|
@@ -1149,20 +1400,18 @@ async function materializeRefDocSurface(opts) {
|
|
|
1149
1400
|
if (target?.source?.kind !== "ref-doc") {
|
|
1150
1401
|
return { materializedDir: null, active: null };
|
|
1151
1402
|
}
|
|
1152
|
-
const
|
|
1153
|
-
const
|
|
1154
|
-
const absDir = path8.join(cwd, MATERIALIZED_ROOT, surfaceId);
|
|
1403
|
+
const relDir = path9.posix.join(MATERIALIZED_ROOT, surfaceId);
|
|
1404
|
+
const absDir = path9.join(cwd, MATERIALIZED_ROOT, surfaceId);
|
|
1155
1405
|
try {
|
|
1156
|
-
const mod = await import(
|
|
1406
|
+
const mod = await import(path9.join(root, "scripts", "materialize-version.ts"));
|
|
1157
1407
|
const selfContained = { ...target, coreTypesImport: "./core-types" };
|
|
1158
1408
|
await mod.materializeVersionedSurface(selfContained, {
|
|
1159
1409
|
destDir: absDir,
|
|
1160
|
-
...resolveOpts ? { resolveOpts } : {}
|
|
1161
|
-
...excludeModules.length > 0 ? { excludeModules } : {}
|
|
1410
|
+
...resolveOpts ? { resolveOpts } : {}
|
|
1162
1411
|
});
|
|
1163
|
-
|
|
1164
|
-
copyFileSync(
|
|
1165
|
-
const indexPath =
|
|
1412
|
+
writeFileSync3(path9.join(absDir, "core-types.d.ts"), CORE_TYPES_REEXPORT);
|
|
1413
|
+
copyFileSync(path9.join(root, "src", "engine-globals.d.ts"), path9.join(absDir, "engine-globals.d.ts"));
|
|
1414
|
+
const indexPath = path9.join(absDir, "index.d.ts");
|
|
1166
1415
|
writeFileSync3(indexPath, `import "./engine-globals";
|
|
1167
1416
|
${readFileSync7(indexPath, "utf8")}`);
|
|
1168
1417
|
} catch {
|
|
@@ -1172,9 +1421,582 @@ ${readFileSync7(indexPath, "utf8")}`);
|
|
|
1172
1421
|
return { materializedDir: relDir, active: surfaceId };
|
|
1173
1422
|
}
|
|
1174
1423
|
|
|
1424
|
+
// src/setup-debug.ts
|
|
1425
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync9, writeFileSync as writeFileSync4 } from "node:fs";
|
|
1426
|
+
import * as path11 from "node:path";
|
|
1427
|
+
|
|
1428
|
+
// src/boot-path.ts
|
|
1429
|
+
import { existsSync as existsSync5, readFileSync as readFileSync8 } from "node:fs";
|
|
1430
|
+
import * as path10 from "node:path";
|
|
1431
|
+
var MAIN_COLLECTION_RE = /^main_collection\s*=\s*(.+)$/m;
|
|
1432
|
+
var COMPONENT_RE = /component:\s*\\?"([^"\\]+)\\?"/;
|
|
1433
|
+
var COLLECTION_RE = /collection:\s*\\?"([^"\\]+\.collectionc?)\\?"/;
|
|
1434
|
+
var TOP_LEVEL_ID_RE = /^\s*id:\s*"([^"\\]+)"\s*$/;
|
|
1435
|
+
var TS_SCRIPT_SUFFIX = ".ts.script";
|
|
1436
|
+
function projectPathToAbs(cwd, projectPath) {
|
|
1437
|
+
return path10.join(cwd, projectPath.replace(/^\//, ""));
|
|
1438
|
+
}
|
|
1439
|
+
function relPosix(cwd, abs) {
|
|
1440
|
+
return path10.relative(cwd, abs).split(path10.sep).join("/");
|
|
1441
|
+
}
|
|
1442
|
+
function resolveBootPathScripts(cwd) {
|
|
1443
|
+
const gameProjectPath = path10.join(cwd, "game.project");
|
|
1444
|
+
if (!existsSync5(gameProjectPath)) {
|
|
1445
|
+
return [];
|
|
1446
|
+
}
|
|
1447
|
+
let gameProject;
|
|
1448
|
+
try {
|
|
1449
|
+
gameProject = readFileSync8(gameProjectPath, "utf8");
|
|
1450
|
+
} catch {
|
|
1451
|
+
return [];
|
|
1452
|
+
}
|
|
1453
|
+
const mainMatch = gameProject.match(MAIN_COLLECTION_RE);
|
|
1454
|
+
if (mainMatch?.[1] === undefined) {
|
|
1455
|
+
return [];
|
|
1456
|
+
}
|
|
1457
|
+
const mainCollection = mainMatch[1].trim().replace(/\.collectionc$/, ".collection");
|
|
1458
|
+
const candidates = [];
|
|
1459
|
+
const visited = new Set;
|
|
1460
|
+
const walk = (collectionAbs, tracePrefix) => {
|
|
1461
|
+
if (visited.has(collectionAbs)) {
|
|
1462
|
+
return;
|
|
1463
|
+
}
|
|
1464
|
+
visited.add(collectionAbs);
|
|
1465
|
+
if (!existsSync5(collectionAbs)) {
|
|
1466
|
+
return;
|
|
1467
|
+
}
|
|
1468
|
+
let content;
|
|
1469
|
+
try {
|
|
1470
|
+
content = readFileSync8(collectionAbs, "utf8");
|
|
1471
|
+
} catch {
|
|
1472
|
+
return;
|
|
1473
|
+
}
|
|
1474
|
+
const trace = [...tracePrefix, relPosix(cwd, collectionAbs)];
|
|
1475
|
+
const children = [];
|
|
1476
|
+
let currentId = null;
|
|
1477
|
+
for (const line of content.split(`
|
|
1478
|
+
`)) {
|
|
1479
|
+
const idMatch = line.match(TOP_LEVEL_ID_RE);
|
|
1480
|
+
if (idMatch?.[1] !== undefined) {
|
|
1481
|
+
currentId = idMatch[1];
|
|
1482
|
+
continue;
|
|
1483
|
+
}
|
|
1484
|
+
const componentMatch = line.match(COMPONENT_RE);
|
|
1485
|
+
const component = componentMatch?.[1];
|
|
1486
|
+
if (component?.endsWith(TS_SCRIPT_SUFFIX)) {
|
|
1487
|
+
const candidate = component.replace(/^\//, "").replace(/\.script$/, "");
|
|
1488
|
+
candidates.push({
|
|
1489
|
+
candidate,
|
|
1490
|
+
trace: [...trace, currentId ?? "?", component]
|
|
1491
|
+
});
|
|
1492
|
+
continue;
|
|
1493
|
+
}
|
|
1494
|
+
const collectionMatch = line.match(COLLECTION_RE);
|
|
1495
|
+
if (collectionMatch?.[1] !== undefined) {
|
|
1496
|
+
const ref = collectionMatch[1].replace(/\.collectionc$/, ".collection");
|
|
1497
|
+
children.push(projectPathToAbs(cwd, ref));
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
for (const child of children) {
|
|
1501
|
+
walk(child, trace);
|
|
1502
|
+
}
|
|
1503
|
+
};
|
|
1504
|
+
walk(projectPathToAbs(cwd, mainCollection), ["game.project"]);
|
|
1505
|
+
return candidates;
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
// src/setup-debug.ts
|
|
1509
|
+
var LLDEBUGGER_URL = "https://github.com/king8fisher/defold-typescript/releases/download/lldebugger-v1/lldebugger.zip";
|
|
1510
|
+
var LEGACY_BOOTSTRAP_MARKER = "// lldebugger-bootstrap: debug entry, inert in release builds";
|
|
1511
|
+
var AMBIENT_DTS_REL = "src/lldebugger.debug.d.ts";
|
|
1512
|
+
var AMBIENT_DECLARATION = `/** @noResolution */
|
|
1513
|
+
declare module "lldebugger.debug" {
|
|
1514
|
+
export function start(): void;
|
|
1515
|
+
}
|
|
1516
|
+
`;
|
|
1517
|
+
var BLOCK_BEGIN = "// defold-typescript:setup-debug BEGIN — managed block, do not edit";
|
|
1518
|
+
var BLOCK_END = "// defold-typescript:setup-debug END";
|
|
1519
|
+
var MANAGED_BLOCK = `${BLOCK_BEGIN}
|
|
1520
|
+
import * as lldebugger from "lldebugger.debug";
|
|
1521
|
+
|
|
1522
|
+
if (sys.get_engine_info().is_debug) {
|
|
1523
|
+
lldebugger.start();
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
${BLOCK_END}`;
|
|
1527
|
+
var FACTORY_NAMES = ["defineScript", "defineGuiScript", "defineRenderScript"];
|
|
1528
|
+
var MANUAL_STEPS = [
|
|
1529
|
+
"Install the Local Lua Debugger extension (tomblind.local-lua-debugger-vscode) in VS Code.",
|
|
1530
|
+
"Run Project -> Fetch Libraries in the Defold editor to download the lldebugger module."
|
|
1531
|
+
];
|
|
1532
|
+
function isProjectHeader(line) {
|
|
1533
|
+
return line.trim() === "[project]";
|
|
1534
|
+
}
|
|
1535
|
+
function isSectionHeader(line) {
|
|
1536
|
+
return /^\[.+\]\s*$/.test(line.trim());
|
|
1537
|
+
}
|
|
1538
|
+
function addLldebuggerDependency(gameProjectText) {
|
|
1539
|
+
const lines = gameProjectText.split(`
|
|
1540
|
+
`);
|
|
1541
|
+
if (!lines.some(isProjectHeader)) {
|
|
1542
|
+
throw new Error("defold-typescript setup-debug: game.project has no [project] section; this is not a Defold project.");
|
|
1543
|
+
}
|
|
1544
|
+
if (gameProjectText.includes(LLDEBUGGER_URL)) {
|
|
1545
|
+
return gameProjectText;
|
|
1546
|
+
}
|
|
1547
|
+
let inProject = false;
|
|
1548
|
+
let maxIndex = -1;
|
|
1549
|
+
let lastDepLine = -1;
|
|
1550
|
+
let lastProjectLine = -1;
|
|
1551
|
+
for (let i = 0;i < lines.length; i++) {
|
|
1552
|
+
const line = lines[i] ?? "";
|
|
1553
|
+
if (isSectionHeader(line)) {
|
|
1554
|
+
inProject = isProjectHeader(line);
|
|
1555
|
+
if (inProject) {
|
|
1556
|
+
lastProjectLine = i;
|
|
1557
|
+
}
|
|
1558
|
+
continue;
|
|
1559
|
+
}
|
|
1560
|
+
if (inProject && line.trim() !== "") {
|
|
1561
|
+
lastProjectLine = i;
|
|
1562
|
+
const dep = line.match(/^dependencies#(\d+)\s*=/);
|
|
1563
|
+
if (dep?.[1] !== undefined) {
|
|
1564
|
+
const n = Number(dep[1]);
|
|
1565
|
+
if (n > maxIndex) {
|
|
1566
|
+
maxIndex = n;
|
|
1567
|
+
}
|
|
1568
|
+
lastDepLine = i;
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
const newLine = `dependencies#${maxIndex + 1} = ${LLDEBUGGER_URL}`;
|
|
1573
|
+
const insertAt = (lastDepLine >= 0 ? lastDepLine : lastProjectLine) + 1;
|
|
1574
|
+
lines.splice(insertAt, 0, newLine);
|
|
1575
|
+
return lines.join(`
|
|
1576
|
+
`);
|
|
1577
|
+
}
|
|
1578
|
+
var LEGACY_BLOCK = `${LEGACY_BOOTSTRAP_MARKER}
|
|
1579
|
+
/** @noResolution */
|
|
1580
|
+
declare module "lldebugger.debug" {
|
|
1581
|
+
export function start(): void;
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1584
|
+
import * as lldebugger from "lldebugger.debug";
|
|
1585
|
+
|
|
1586
|
+
if (sys.get_engine_info().is_debug) {
|
|
1587
|
+
lldebugger.start();
|
|
1588
|
+
}
|
|
1589
|
+
`;
|
|
1590
|
+
function occurrences(haystack, needle) {
|
|
1591
|
+
return haystack.split(needle).length - 1;
|
|
1592
|
+
}
|
|
1593
|
+
function upsertManagedBlock(source) {
|
|
1594
|
+
const begins = occurrences(source, BLOCK_BEGIN);
|
|
1595
|
+
const ends = occurrences(source, BLOCK_END);
|
|
1596
|
+
if (begins !== ends || begins > 1) {
|
|
1597
|
+
throw new Error("defold-typescript setup-debug: malformed managed block (mismatched, duplicate, or out-of-order sentinels); refusing to edit.");
|
|
1598
|
+
}
|
|
1599
|
+
if (begins === 1) {
|
|
1600
|
+
const beginAt = source.indexOf(BLOCK_BEGIN);
|
|
1601
|
+
const endAt = source.indexOf(BLOCK_END);
|
|
1602
|
+
if (endAt < beginAt) {
|
|
1603
|
+
throw new Error("defold-typescript setup-debug: malformed managed block (END before BEGIN); refusing to edit.");
|
|
1604
|
+
}
|
|
1605
|
+
const regionEnd = endAt + BLOCK_END.length;
|
|
1606
|
+
const region = source.slice(beginAt, regionEnd);
|
|
1607
|
+
if (region === MANAGED_BLOCK) {
|
|
1608
|
+
return { text: source, action: "unchanged" };
|
|
1609
|
+
}
|
|
1610
|
+
const text = source.slice(0, beginAt) + MANAGED_BLOCK + source.slice(regionEnd);
|
|
1611
|
+
return { text, action: "refreshed" };
|
|
1612
|
+
}
|
|
1613
|
+
if (source.includes(LEGACY_BLOCK)) {
|
|
1614
|
+
return { text: source.replace(LEGACY_BLOCK, `${MANAGED_BLOCK}
|
|
1615
|
+
`), action: "refreshed" };
|
|
1616
|
+
}
|
|
1617
|
+
return { text: `${MANAGED_BLOCK}
|
|
1618
|
+
|
|
1619
|
+
${source}`, action: "injected" };
|
|
1620
|
+
}
|
|
1621
|
+
function stripManagedBlock(source) {
|
|
1622
|
+
const begins = occurrences(source, BLOCK_BEGIN);
|
|
1623
|
+
const ends = occurrences(source, BLOCK_END);
|
|
1624
|
+
if (begins === 0 && ends === 0) {
|
|
1625
|
+
return { text: source, removed: false };
|
|
1626
|
+
}
|
|
1627
|
+
if (begins !== ends || begins > 1) {
|
|
1628
|
+
throw new Error("defold-typescript setup-debug: malformed managed block (mismatched, duplicate, or out-of-order sentinels); refusing to edit.");
|
|
1629
|
+
}
|
|
1630
|
+
const beginAt = source.indexOf(BLOCK_BEGIN);
|
|
1631
|
+
const endAt = source.indexOf(BLOCK_END);
|
|
1632
|
+
if (endAt < beginAt) {
|
|
1633
|
+
throw new Error("defold-typescript setup-debug: malformed managed block (END before BEGIN); refusing to edit.");
|
|
1634
|
+
}
|
|
1635
|
+
const regionEnd = endAt + BLOCK_END.length;
|
|
1636
|
+
const after = source.slice(regionEnd).replace(/^\n{1,2}/, "");
|
|
1637
|
+
return { text: source.slice(0, beginAt) + after, removed: true };
|
|
1638
|
+
}
|
|
1639
|
+
function hasFactoryCall(text) {
|
|
1640
|
+
return FACTORY_NAMES.some((name) => text.includes(`${name}(`));
|
|
1641
|
+
}
|
|
1642
|
+
function findEntryScriptCandidates(cwd, scanner = scanFilesSync) {
|
|
1643
|
+
const srcDir = path11.join(cwd, "src");
|
|
1644
|
+
if (!existsSync6(srcDir)) {
|
|
1645
|
+
return [];
|
|
1646
|
+
}
|
|
1647
|
+
return scanner(cwd, "src/**/*.ts").map(normalizeScannedPath).filter((rel) => !isSkipped(rel)).filter((rel) => hasFactoryCall(readFileSync9(path11.join(cwd, rel), "utf8"))).sort();
|
|
1648
|
+
}
|
|
1649
|
+
function failure(error) {
|
|
1650
|
+
return { ok: false, written: [], actions: {}, manualSteps: MANUAL_STEPS, error };
|
|
1651
|
+
}
|
|
1652
|
+
async function defaultChooseScript(candidates) {
|
|
1653
|
+
const { select } = await import("@inquirer/prompts");
|
|
1654
|
+
return select({
|
|
1655
|
+
message: "Select the entry script to receive the debugger bootstrap:",
|
|
1656
|
+
choices: candidates.map((candidate) => ({ name: candidate, value: candidate }))
|
|
1657
|
+
});
|
|
1658
|
+
}
|
|
1659
|
+
async function pickCandidate(candidates, opts) {
|
|
1660
|
+
if (candidates.length === 1) {
|
|
1661
|
+
return candidates[0];
|
|
1662
|
+
}
|
|
1663
|
+
const chooser = opts.chooseScript ?? (opts.json ? undefined : defaultChooseScript);
|
|
1664
|
+
if (chooser === undefined) {
|
|
1665
|
+
return failure(`defold-typescript setup-debug: multiple entry scripts found (${candidates.join(", ")}); pass --script to choose one.`);
|
|
1666
|
+
}
|
|
1667
|
+
return chooser(candidates);
|
|
1668
|
+
}
|
|
1669
|
+
async function resolveTargetScript(opts) {
|
|
1670
|
+
const { cwd } = opts;
|
|
1671
|
+
const script = opts.script === undefined ? undefined : normalizeScannedPath(opts.script);
|
|
1672
|
+
const bootCandidates = resolveBootPathScripts(cwd).filter((entry) => existsSync6(path11.join(cwd, entry.candidate)));
|
|
1673
|
+
if (script !== undefined) {
|
|
1674
|
+
if (!existsSync6(path11.join(cwd, script))) {
|
|
1675
|
+
return failure(`defold-typescript setup-debug: script not found: ${script}`);
|
|
1676
|
+
}
|
|
1677
|
+
const onPath = bootCandidates.find((entry) => entry.candidate === script);
|
|
1678
|
+
return { target: script, bootPath: onPath?.trace ?? [] };
|
|
1679
|
+
}
|
|
1680
|
+
if (bootCandidates.length > 0) {
|
|
1681
|
+
const picked2 = await pickCandidate(bootCandidates.map((entry) => entry.candidate), opts);
|
|
1682
|
+
if (typeof picked2 !== "string") {
|
|
1683
|
+
return picked2;
|
|
1684
|
+
}
|
|
1685
|
+
const onPath = bootCandidates.find((entry) => entry.candidate === picked2);
|
|
1686
|
+
return { target: picked2, bootPath: onPath?.trace ?? [] };
|
|
1687
|
+
}
|
|
1688
|
+
const scanned = findEntryScriptCandidates(cwd, opts.scanFiles);
|
|
1689
|
+
if (scanned.length === 0) {
|
|
1690
|
+
return failure("defold-typescript setup-debug: no entry script with a lifecycle factory call found under src/.");
|
|
1691
|
+
}
|
|
1692
|
+
const picked = await pickCandidate(scanned, opts);
|
|
1693
|
+
if (typeof picked !== "string") {
|
|
1694
|
+
return picked;
|
|
1695
|
+
}
|
|
1696
|
+
return { target: picked, bootPath: [] };
|
|
1697
|
+
}
|
|
1698
|
+
async function runSetupDebug(opts) {
|
|
1699
|
+
const { cwd } = opts;
|
|
1700
|
+
const gameProjectPath = path11.join(cwd, "game.project");
|
|
1701
|
+
if (!existsSync6(gameProjectPath)) {
|
|
1702
|
+
return failure("defold-typescript setup-debug: no game.project here; this is not a Defold project.");
|
|
1703
|
+
}
|
|
1704
|
+
const resolved = await resolveTargetScript(opts);
|
|
1705
|
+
if (!("target" in resolved)) {
|
|
1706
|
+
return resolved;
|
|
1707
|
+
}
|
|
1708
|
+
const { target, bootPath } = resolved;
|
|
1709
|
+
const written = [];
|
|
1710
|
+
const actions = {};
|
|
1711
|
+
const dtsPath = path11.join(cwd, AMBIENT_DTS_REL);
|
|
1712
|
+
mkdirSync5(path11.dirname(dtsPath), { recursive: true });
|
|
1713
|
+
const existingDts = existsSync6(dtsPath) ? readFileSync9(dtsPath, "utf8") : null;
|
|
1714
|
+
if (existingDts === null) {
|
|
1715
|
+
writeFileSync4(dtsPath, AMBIENT_DECLARATION);
|
|
1716
|
+
actions[AMBIENT_DTS_REL] = "injected";
|
|
1717
|
+
} else if (existingDts !== AMBIENT_DECLARATION) {
|
|
1718
|
+
writeFileSync4(dtsPath, AMBIENT_DECLARATION);
|
|
1719
|
+
actions[AMBIENT_DTS_REL] = "refreshed";
|
|
1720
|
+
} else {
|
|
1721
|
+
actions[AMBIENT_DTS_REL] = "unchanged";
|
|
1722
|
+
}
|
|
1723
|
+
written.push(AMBIENT_DTS_REL);
|
|
1724
|
+
const scriptPath = path11.join(cwd, target);
|
|
1725
|
+
const source = readFileSync9(scriptPath, "utf8");
|
|
1726
|
+
const { text: injected, action: scriptAction } = upsertManagedBlock(source);
|
|
1727
|
+
if (injected !== source) {
|
|
1728
|
+
writeFileSync4(scriptPath, injected);
|
|
1729
|
+
}
|
|
1730
|
+
actions[target] = scriptAction;
|
|
1731
|
+
written.push(target);
|
|
1732
|
+
const gameProjectText = readFileSync9(gameProjectPath, "utf8");
|
|
1733
|
+
const updated = addLldebuggerDependency(gameProjectText);
|
|
1734
|
+
if (updated !== gameProjectText) {
|
|
1735
|
+
writeFileSync4(gameProjectPath, updated);
|
|
1736
|
+
actions["game.project"] = "injected";
|
|
1737
|
+
} else {
|
|
1738
|
+
actions["game.project"] = "unchanged";
|
|
1739
|
+
}
|
|
1740
|
+
written.push("game.project");
|
|
1741
|
+
const removedFrom = [];
|
|
1742
|
+
for (const scannedRel of (opts.scanFiles ?? scanFilesSync)(cwd, "src/**/*.ts")) {
|
|
1743
|
+
const rel = normalizeScannedPath(scannedRel);
|
|
1744
|
+
if (isSkipped(rel) || rel === target) {
|
|
1745
|
+
continue;
|
|
1746
|
+
}
|
|
1747
|
+
const otherPath = path11.join(cwd, rel);
|
|
1748
|
+
const otherSource = readFileSync9(otherPath, "utf8");
|
|
1749
|
+
let stripped;
|
|
1750
|
+
try {
|
|
1751
|
+
stripped = stripManagedBlock(otherSource);
|
|
1752
|
+
} catch {
|
|
1753
|
+
continue;
|
|
1754
|
+
}
|
|
1755
|
+
if (stripped.removed) {
|
|
1756
|
+
writeFileSync4(otherPath, stripped.text);
|
|
1757
|
+
actions[rel] = "removed";
|
|
1758
|
+
removedFrom.push(rel);
|
|
1759
|
+
}
|
|
1760
|
+
}
|
|
1761
|
+
removedFrom.sort();
|
|
1762
|
+
return {
|
|
1763
|
+
ok: true,
|
|
1764
|
+
written,
|
|
1765
|
+
actions,
|
|
1766
|
+
manualSteps: MANUAL_STEPS,
|
|
1767
|
+
addedTo: target,
|
|
1768
|
+
removedFrom,
|
|
1769
|
+
bootPath
|
|
1770
|
+
};
|
|
1771
|
+
}
|
|
1772
|
+
|
|
1773
|
+
// src/wall.ts
|
|
1774
|
+
import { existsSync as existsSync8, readFileSync as readFileSync11, rmSync as rmSync3 } from "node:fs";
|
|
1775
|
+
import * as path13 from "node:path";
|
|
1776
|
+
|
|
1777
|
+
// src/directory-walls.ts
|
|
1778
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync6, readFileSync as readFileSync10, writeFileSync as writeFileSync5 } from "node:fs";
|
|
1779
|
+
import * as path12 from "node:path";
|
|
1780
|
+
function describeWall(dir, kind) {
|
|
1781
|
+
return {
|
|
1782
|
+
dir,
|
|
1783
|
+
kind,
|
|
1784
|
+
typesEntrypoint: selectScriptKindEntrypoint(new Set([kind]))
|
|
1785
|
+
};
|
|
1786
|
+
}
|
|
1787
|
+
function groupSourceScriptKindsByDirectory(cwd) {
|
|
1788
|
+
const byDir = new Map;
|
|
1789
|
+
const seen = new Set;
|
|
1790
|
+
for (const pattern of readBuildConfig(cwd).include) {
|
|
1791
|
+
for (const match of scanFilesSync(cwd, pattern)) {
|
|
1792
|
+
const rel = match.split(path12.sep).join("/");
|
|
1793
|
+
if (seen.has(rel) || !isTranspilerSource(rel) || isSkipped(rel)) {
|
|
1794
|
+
continue;
|
|
1795
|
+
}
|
|
1796
|
+
seen.add(rel);
|
|
1797
|
+
const kind = detectSourceOutputKind(readFileSync10(path12.join(cwd, match), "utf8"));
|
|
1798
|
+
if (kind === "module") {
|
|
1799
|
+
continue;
|
|
1800
|
+
}
|
|
1801
|
+
const dir = path12.posix.dirname(rel);
|
|
1802
|
+
let set = byDir.get(dir);
|
|
1803
|
+
if (set === undefined) {
|
|
1804
|
+
set = new Set;
|
|
1805
|
+
byDir.set(dir, set);
|
|
1806
|
+
}
|
|
1807
|
+
set.add(kind);
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1810
|
+
return byDir;
|
|
1811
|
+
}
|
|
1812
|
+
function planSourceDirectoryWalls(cwd) {
|
|
1813
|
+
const walls = [];
|
|
1814
|
+
for (const [dir, kinds] of groupSourceScriptKindsByDirectory(cwd)) {
|
|
1815
|
+
const kind = selectScriptKind(kinds);
|
|
1816
|
+
if (kind !== null) {
|
|
1817
|
+
walls.push(describeWall(dir, kind));
|
|
1818
|
+
}
|
|
1819
|
+
}
|
|
1820
|
+
return walls.sort((a, b) => a.dir < b.dir ? -1 : a.dir > b.dir ? 1 : 0);
|
|
1821
|
+
}
|
|
1822
|
+
function directoryWallTsconfig(wall) {
|
|
1823
|
+
const depth = wall.dir.split("/").length;
|
|
1824
|
+
return {
|
|
1825
|
+
extends: `${"../".repeat(depth)}tsconfig.json`,
|
|
1826
|
+
compilerOptions: { composite: true, typeRoots: null, types: [wall.typesEntrypoint] },
|
|
1827
|
+
include: ["**/*.ts"],
|
|
1828
|
+
exclude: []
|
|
1829
|
+
};
|
|
1830
|
+
}
|
|
1831
|
+
function writeJson3(filePath, value) {
|
|
1832
|
+
mkdirSync6(path12.dirname(filePath), { recursive: true });
|
|
1833
|
+
writeFileSync5(filePath, `${JSON.stringify(value, null, 2)}
|
|
1834
|
+
`);
|
|
1835
|
+
}
|
|
1836
|
+
function sortedWallDirs(walls) {
|
|
1837
|
+
return walls.map((w) => w.dir).filter((dir) => dir !== ".").sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
1838
|
+
}
|
|
1839
|
+
function isInsideAnyDir(rel, dirs) {
|
|
1840
|
+
return dirs.some((dir) => rel === dir || rel.startsWith(`${dir}/`));
|
|
1841
|
+
}
|
|
1842
|
+
function hasRootOwnedTranspilerSources(cwd, wallDirs) {
|
|
1843
|
+
const seen = new Set;
|
|
1844
|
+
for (const pattern of readBuildConfig(cwd).include) {
|
|
1845
|
+
for (const match of scanFilesSync(cwd, pattern)) {
|
|
1846
|
+
const rel = match.split(path12.sep).join("/");
|
|
1847
|
+
if (seen.has(rel) || !isTranspilerSource(rel) || isSkipped(rel)) {
|
|
1848
|
+
continue;
|
|
1849
|
+
}
|
|
1850
|
+
seen.add(rel);
|
|
1851
|
+
if (!isInsideAnyDir(rel, wallDirs)) {
|
|
1852
|
+
return true;
|
|
1853
|
+
}
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
1856
|
+
return false;
|
|
1857
|
+
}
|
|
1858
|
+
function wireWallReferences(cwd, walls) {
|
|
1859
|
+
const rootPath = path12.join(cwd, "tsconfig.json");
|
|
1860
|
+
const current = JSON.parse(readFileSync10(rootPath, "utf8"));
|
|
1861
|
+
const wallDirs = sortedWallDirs(walls);
|
|
1862
|
+
const previousReferences = current.references ?? [];
|
|
1863
|
+
const previousManaged = new Set(previousReferences.map((ref) => ref.path));
|
|
1864
|
+
const nextExclude = [
|
|
1865
|
+
...new Set([
|
|
1866
|
+
...(current.exclude ?? []).filter((entry) => !previousManaged.has(entry)),
|
|
1867
|
+
...wallDirs
|
|
1868
|
+
])
|
|
1869
|
+
];
|
|
1870
|
+
const next = { ...current };
|
|
1871
|
+
if (wallDirs.length > 0) {
|
|
1872
|
+
next.references = wallDirs.map((dir) => ({ path: dir }));
|
|
1873
|
+
} else {
|
|
1874
|
+
delete next.references;
|
|
1875
|
+
}
|
|
1876
|
+
if (nextExclude.length > 0) {
|
|
1877
|
+
next.exclude = nextExclude;
|
|
1878
|
+
} else {
|
|
1879
|
+
delete next.exclude;
|
|
1880
|
+
}
|
|
1881
|
+
if (wallDirs.length > 0 && !hasRootOwnedTranspilerSources(cwd, wallDirs)) {
|
|
1882
|
+
next.files = [];
|
|
1883
|
+
} else if (previousReferences.length > 0 && JSON.stringify(next.files) === JSON.stringify([])) {
|
|
1884
|
+
delete next.files;
|
|
1885
|
+
}
|
|
1886
|
+
if (JSON.stringify(next) !== JSON.stringify(current)) {
|
|
1887
|
+
writeJson3(rootPath, next);
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
1890
|
+
function writeDirectoryWallTsconfigs(cwd, walls) {
|
|
1891
|
+
const written = [];
|
|
1892
|
+
for (const w of walls) {
|
|
1893
|
+
if (w.dir === ".") {
|
|
1894
|
+
continue;
|
|
1895
|
+
}
|
|
1896
|
+
const rel = `${w.dir}/tsconfig.json`;
|
|
1897
|
+
const target = path12.join(cwd, w.dir, "tsconfig.json");
|
|
1898
|
+
const desired = directoryWallTsconfig(w);
|
|
1899
|
+
if (existsSync7(target)) {
|
|
1900
|
+
const current = JSON.parse(readFileSync10(target, "utf8"));
|
|
1901
|
+
const options = current.compilerOptions ?? {};
|
|
1902
|
+
const alreadyNarrowed = current.extends === desired.extends && options.composite === desired.compilerOptions.composite && options.typeRoots === desired.compilerOptions.typeRoots && JSON.stringify(options.types) === JSON.stringify(desired.compilerOptions.types) && JSON.stringify(current.include) === JSON.stringify(desired.include) && JSON.stringify(current.exclude) === JSON.stringify(desired.exclude);
|
|
1903
|
+
if (!alreadyNarrowed) {
|
|
1904
|
+
writeJson3(target, {
|
|
1905
|
+
...current,
|
|
1906
|
+
extends: desired.extends,
|
|
1907
|
+
compilerOptions: {
|
|
1908
|
+
...options,
|
|
1909
|
+
composite: desired.compilerOptions.composite,
|
|
1910
|
+
typeRoots: desired.compilerOptions.typeRoots,
|
|
1911
|
+
types: desired.compilerOptions.types
|
|
1912
|
+
},
|
|
1913
|
+
include: desired.include,
|
|
1914
|
+
exclude: desired.exclude
|
|
1915
|
+
});
|
|
1916
|
+
written.push(rel);
|
|
1917
|
+
}
|
|
1918
|
+
} else {
|
|
1919
|
+
writeJson3(target, desired);
|
|
1920
|
+
written.push(rel);
|
|
1921
|
+
}
|
|
1922
|
+
}
|
|
1923
|
+
return written.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
1924
|
+
}
|
|
1925
|
+
|
|
1926
|
+
// src/wall.ts
|
|
1927
|
+
function sortDirs(items) {
|
|
1928
|
+
return items.sort((a, b) => a.dir < b.dir ? -1 : a.dir > b.dir ? 1 : 0);
|
|
1929
|
+
}
|
|
1930
|
+
function currentWalledDirs(cwd) {
|
|
1931
|
+
const rootPath = path13.join(cwd, "tsconfig.json");
|
|
1932
|
+
if (!existsSync8(rootPath)) {
|
|
1933
|
+
return [];
|
|
1934
|
+
}
|
|
1935
|
+
try {
|
|
1936
|
+
const parsed = JSON.parse(readFileSync11(rootPath, "utf8"));
|
|
1937
|
+
return (parsed.references ?? []).map((ref) => ref.path).sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
1938
|
+
} catch {
|
|
1939
|
+
return [];
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1942
|
+
function eligibleWalls(cwd) {
|
|
1943
|
+
return planSourceDirectoryWalls(cwd);
|
|
1944
|
+
}
|
|
1945
|
+
function applyWallSelection(cwd, desiredDirs) {
|
|
1946
|
+
const byDir = new Map(eligibleWalls(cwd).map((wall) => [wall.dir, wall]));
|
|
1947
|
+
const desired = [];
|
|
1948
|
+
const desiredSet = new Set;
|
|
1949
|
+
for (const dir of desiredDirs) {
|
|
1950
|
+
if (desiredSet.has(dir)) {
|
|
1951
|
+
continue;
|
|
1952
|
+
}
|
|
1953
|
+
const wall = byDir.get(dir);
|
|
1954
|
+
if (wall === undefined) {
|
|
1955
|
+
throw new Error(`defold-typescript wall: ${dir} is not a single-kind source directory that can be walled`);
|
|
1956
|
+
}
|
|
1957
|
+
desired.push(wall);
|
|
1958
|
+
desiredSet.add(dir);
|
|
1959
|
+
}
|
|
1960
|
+
for (const dir of currentWalledDirs(cwd)) {
|
|
1961
|
+
if (!desiredSet.has(dir)) {
|
|
1962
|
+
rmSync3(path13.join(cwd, dir, "tsconfig.json"), { force: true });
|
|
1963
|
+
}
|
|
1964
|
+
}
|
|
1965
|
+
writeDirectoryWallTsconfigs(cwd, desired);
|
|
1966
|
+
wireWallReferences(cwd, desired);
|
|
1967
|
+
return sortDirs(desired);
|
|
1968
|
+
}
|
|
1969
|
+
|
|
1970
|
+
// src/wall-interactive.ts
|
|
1971
|
+
function buildWallChoices(cwd) {
|
|
1972
|
+
const current = new Set(currentWalledDirs(cwd));
|
|
1973
|
+
const choices = [];
|
|
1974
|
+
for (const [dir, kinds] of groupSourceScriptKindsByDirectory(cwd)) {
|
|
1975
|
+
const kind = selectScriptKind(kinds);
|
|
1976
|
+
if (kind === null) {
|
|
1977
|
+
choices.push({ value: dir, name: dir, disabled: `mixed: ${[...kinds].sort().join(", ")}` });
|
|
1978
|
+
} else {
|
|
1979
|
+
choices.push({ value: dir, name: `${dir} (${kind})`, checked: current.has(dir) });
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1982
|
+
return choices.sort((a, b) => a.value < b.value ? -1 : a.value > b.value ? 1 : 0);
|
|
1983
|
+
}
|
|
1984
|
+
async function defaultCheckbox() {
|
|
1985
|
+
const { checkbox } = await import("@inquirer/prompts");
|
|
1986
|
+
return (opts) => checkbox({ message: opts.message, choices: opts.choices });
|
|
1987
|
+
}
|
|
1988
|
+
async function runWallInteractive(cwd, deps = {}) {
|
|
1989
|
+
const checkbox = deps.checkbox ?? await defaultCheckbox();
|
|
1990
|
+
const selection = await checkbox({
|
|
1991
|
+
message: "Select the source directories to wall (space toggles, enter confirms):",
|
|
1992
|
+
choices: buildWallChoices(cwd)
|
|
1993
|
+
});
|
|
1994
|
+
return applyWallSelection(cwd, selection);
|
|
1995
|
+
}
|
|
1996
|
+
|
|
1175
1997
|
// src/watch.ts
|
|
1176
|
-
import { existsSync as
|
|
1177
|
-
import * as
|
|
1998
|
+
import { existsSync as existsSync9, watch as fsWatch } from "node:fs";
|
|
1999
|
+
import * as path14 from "node:path";
|
|
1178
2000
|
var DEFAULT_DEBOUNCE_MS = 50;
|
|
1179
2001
|
var recursiveWatcherFactory = (srcDir, onEvent) => {
|
|
1180
2002
|
const w = fsWatch(srcDir, { recursive: true }, (eventType, filename) => {
|
|
@@ -1208,7 +2030,7 @@ function runWatch(opts) {
|
|
|
1208
2030
|
opts.syncSurface?.();
|
|
1209
2031
|
session = createBuildSession({ cwd });
|
|
1210
2032
|
const { written } = session.buildAll();
|
|
1211
|
-
stdout.write(formatBuildLine(written));
|
|
2033
|
+
stdout.write(opts.json ? renderWatchEvent({ event: "build", written }) : formatBuildLine(written));
|
|
1212
2034
|
} catch (err) {
|
|
1213
2035
|
rejectDone(rewrapInitError(err));
|
|
1214
2036
|
return {
|
|
@@ -1217,7 +2039,7 @@ function runWatch(opts) {
|
|
|
1217
2039
|
waitForIdle: () => Promise.resolve()
|
|
1218
2040
|
};
|
|
1219
2041
|
}
|
|
1220
|
-
const srcDir =
|
|
2042
|
+
const srcDir = path14.join(cwd, "src");
|
|
1221
2043
|
let scheduled = null;
|
|
1222
2044
|
let syncScheduled = null;
|
|
1223
2045
|
let rebuildBusy = false;
|
|
@@ -1241,7 +2063,7 @@ function runWatch(opts) {
|
|
|
1241
2063
|
const removed = [];
|
|
1242
2064
|
for (const rel of drained) {
|
|
1243
2065
|
const key = `src/${toPosix(rel)}`;
|
|
1244
|
-
if (
|
|
2066
|
+
if (existsSync9(path14.join(srcDir, rel))) {
|
|
1245
2067
|
changed.push(key);
|
|
1246
2068
|
} else {
|
|
1247
2069
|
removed.push(key);
|
|
@@ -1249,11 +2071,15 @@ function runWatch(opts) {
|
|
|
1249
2071
|
}
|
|
1250
2072
|
try {
|
|
1251
2073
|
const { written } = session.applyEvents(changed, removed);
|
|
1252
|
-
stdout.write(formatBuildLine(written));
|
|
2074
|
+
stdout.write(opts.json ? renderWatchEvent({ event: "rebuild", written, changed, removed }) : formatBuildLine(written));
|
|
1253
2075
|
} catch (err) {
|
|
1254
2076
|
const message = err instanceof Error ? err.message : String(err);
|
|
1255
|
-
|
|
2077
|
+
if (opts.json) {
|
|
2078
|
+
stdout.write(renderWatchEvent({ event: "rebuild", error: message }));
|
|
2079
|
+
} else {
|
|
2080
|
+
stderr.write(`${message}
|
|
1256
2081
|
`);
|
|
2082
|
+
}
|
|
1257
2083
|
}
|
|
1258
2084
|
rebuildBusy = false;
|
|
1259
2085
|
notifyIdle();
|
|
@@ -1323,7 +2149,9 @@ function runWatch(opts) {
|
|
|
1323
2149
|
}
|
|
1324
2150
|
|
|
1325
2151
|
// src/dispatch.ts
|
|
1326
|
-
var USAGE = `Usage: defold-typescript <init|build|watch> [path]
|
|
2152
|
+
var USAGE = `Usage: defold-typescript <init|build|watch|wall|setup-debug|defold> [path]
|
|
2153
|
+
`;
|
|
2154
|
+
var DEFOLD_USAGE = `Usage: defold-typescript defold <resolve|build|bundle> [path]
|
|
1327
2155
|
`;
|
|
1328
2156
|
function parseDefoldVersionFlag(argv) {
|
|
1329
2157
|
let flag;
|
|
@@ -1341,13 +2169,47 @@ function parseDefoldVersionFlag(argv) {
|
|
|
1341
2169
|
}
|
|
1342
2170
|
return { flag, rest };
|
|
1343
2171
|
}
|
|
2172
|
+
function parseScriptFlag(argv) {
|
|
2173
|
+
let script;
|
|
2174
|
+
const rest = [];
|
|
2175
|
+
for (let i = 0;i < argv.length; i++) {
|
|
2176
|
+
const arg = argv[i];
|
|
2177
|
+
if (arg === "--script") {
|
|
2178
|
+
script = argv[i + 1];
|
|
2179
|
+
i++;
|
|
2180
|
+
} else if (arg?.startsWith("--script=")) {
|
|
2181
|
+
script = arg.slice("--script=".length);
|
|
2182
|
+
} else if (arg !== undefined) {
|
|
2183
|
+
rest.push(arg);
|
|
2184
|
+
}
|
|
2185
|
+
}
|
|
2186
|
+
return { script, rest };
|
|
2187
|
+
}
|
|
2188
|
+
function parseValueFlag(argv, name) {
|
|
2189
|
+
const long = `--${name}`;
|
|
2190
|
+
const eq = `${long}=`;
|
|
2191
|
+
let value;
|
|
2192
|
+
const rest = [];
|
|
2193
|
+
for (let i = 0;i < argv.length; i++) {
|
|
2194
|
+
const arg = argv[i];
|
|
2195
|
+
if (arg === long) {
|
|
2196
|
+
value = argv[i + 1];
|
|
2197
|
+
i++;
|
|
2198
|
+
} else if (arg?.startsWith(eq)) {
|
|
2199
|
+
value = arg.slice(eq.length);
|
|
2200
|
+
} else if (arg !== undefined) {
|
|
2201
|
+
rest.push(arg);
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2204
|
+
return { value, rest };
|
|
2205
|
+
}
|
|
1344
2206
|
function readProjectPin(cwd) {
|
|
1345
|
-
const pkgPath =
|
|
1346
|
-
if (!
|
|
2207
|
+
const pkgPath = path15.join(cwd, "package.json");
|
|
2208
|
+
if (!existsSync10(pkgPath)) {
|
|
1347
2209
|
return;
|
|
1348
2210
|
}
|
|
1349
2211
|
try {
|
|
1350
|
-
return readDefoldVersionPin(JSON.parse(
|
|
2212
|
+
return readDefoldVersionPin(JSON.parse(readFileSync12(pkgPath, "utf8")));
|
|
1351
2213
|
} catch {
|
|
1352
2214
|
return;
|
|
1353
2215
|
}
|
|
@@ -1362,10 +2224,16 @@ function dispatch(argv, io, internals) {
|
|
|
1362
2224
|
return 0;
|
|
1363
2225
|
}
|
|
1364
2226
|
const force = argv.includes("--force");
|
|
1365
|
-
const
|
|
1366
|
-
const
|
|
2227
|
+
const suppressInstallReminder = argv.includes("--suppress-install-reminder");
|
|
2228
|
+
const wallRemove = argv.includes("--remove");
|
|
2229
|
+
const wallList = argv.includes("--list");
|
|
2230
|
+
const { flag: defoldVersionFlag, rest: afterVersionArgs } = parseDefoldVersionFlag(argv);
|
|
2231
|
+
const { script: scriptFlag, rest: afterScriptArgs } = parseScriptFlag(afterVersionArgs);
|
|
2232
|
+
const { value: javaFlag, rest: afterJavaArgs } = parseValueFlag(afterScriptArgs, "java");
|
|
2233
|
+
const { value: buildServerFlag, rest: nonFlagArgs } = parseValueFlag(afterJavaArgs, "build-server");
|
|
2234
|
+
const positional = nonFlagArgs.filter((a) => a !== "--json" && a !== "--force" && a !== "--suppress-install-reminder" && a !== "--remove" && a !== "--list");
|
|
1367
2235
|
const [command, ...rest] = positional;
|
|
1368
|
-
const cwd = rest[0] ?
|
|
2236
|
+
const cwd = rest[0] ? path15.resolve(rest[0]) : process.cwd();
|
|
1369
2237
|
const pin = readProjectPin(cwd);
|
|
1370
2238
|
const resolvedVersion = resolveDefoldVersion({
|
|
1371
2239
|
...defoldVersionFlag !== undefined ? { flag: defoldVersionFlag } : {},
|
|
@@ -1375,18 +2243,22 @@ function dispatch(argv, io, internals) {
|
|
|
1375
2243
|
const apiSurface = surface.surfaceId;
|
|
1376
2244
|
if (command === "init") {
|
|
1377
2245
|
try {
|
|
1378
|
-
const { written
|
|
2246
|
+
const { written } = runInit({ cwd, force });
|
|
1379
2247
|
if (json) {
|
|
1380
2248
|
io.stdout.write(renderResult({
|
|
1381
2249
|
command: "init",
|
|
1382
2250
|
written,
|
|
1383
2251
|
defoldVersion: resolvedVersion,
|
|
1384
2252
|
apiSurface,
|
|
1385
|
-
|
|
2253
|
+
installCommand: installHint()
|
|
1386
2254
|
}));
|
|
1387
2255
|
} else {
|
|
1388
2256
|
io.stdout.write(`defold-typescript init: wrote ${written.length} files: ${written.join(", ")}
|
|
1389
2257
|
`);
|
|
2258
|
+
if (!suppressInstallReminder) {
|
|
2259
|
+
io.stdout.write(`Next: run \`${installHint()}\` to install dependencies.
|
|
2260
|
+
`);
|
|
2261
|
+
}
|
|
1390
2262
|
}
|
|
1391
2263
|
return 0;
|
|
1392
2264
|
} catch (err) {
|
|
@@ -1400,8 +2272,52 @@ function dispatch(argv, io, internals) {
|
|
|
1400
2272
|
return 1;
|
|
1401
2273
|
}
|
|
1402
2274
|
}
|
|
2275
|
+
if (command === "setup-debug") {
|
|
2276
|
+
return (async () => {
|
|
2277
|
+
const result = await runSetupDebug({
|
|
2278
|
+
cwd,
|
|
2279
|
+
json,
|
|
2280
|
+
...scriptFlag !== undefined ? { script: scriptFlag } : {}
|
|
2281
|
+
});
|
|
2282
|
+
if (json) {
|
|
2283
|
+
io.stdout.write(renderResult(result.ok ? {
|
|
2284
|
+
command: "setup-debug",
|
|
2285
|
+
written: result.written,
|
|
2286
|
+
actions: result.actions,
|
|
2287
|
+
manualSteps: result.manualSteps,
|
|
2288
|
+
...result.addedTo !== undefined ? { addedTo: result.addedTo } : {},
|
|
2289
|
+
removedFrom: result.removedFrom ?? [],
|
|
2290
|
+
bootPath: result.bootPath ?? []
|
|
2291
|
+
} : { command: "setup-debug", error: result.error ?? "setup-debug failed" }));
|
|
2292
|
+
} else if (result.ok) {
|
|
2293
|
+
io.stdout.write(`defold-typescript setup-debug: wrote ${result.written.length} files: ${result.written.join(", ")}
|
|
2294
|
+
`);
|
|
2295
|
+
if (result.addedTo !== undefined) {
|
|
2296
|
+
io.stdout.write(`Debugger bootstrap added to: ${result.addedTo}
|
|
2297
|
+
`);
|
|
2298
|
+
}
|
|
2299
|
+
if (result.removedFrom !== undefined && result.removedFrom.length > 0) {
|
|
2300
|
+
io.stdout.write(`Removed stale bootstrap from: ${result.removedFrom.join(", ")}
|
|
2301
|
+
`);
|
|
2302
|
+
}
|
|
2303
|
+
if (result.bootPath !== undefined && result.bootPath.length > 0) {
|
|
2304
|
+
io.stdout.write(`Boot path: ${result.bootPath.join(" -> ")}
|
|
2305
|
+
`);
|
|
2306
|
+
}
|
|
2307
|
+
io.stdout.write(`Remaining manual steps:
|
|
2308
|
+
`);
|
|
2309
|
+
for (const step of result.manualSteps) {
|
|
2310
|
+
io.stdout.write(` - ${step}
|
|
2311
|
+
`);
|
|
2312
|
+
}
|
|
2313
|
+
} else {
|
|
2314
|
+
io.stderr.write(`${result.error}
|
|
2315
|
+
`);
|
|
2316
|
+
}
|
|
2317
|
+
return result.ok ? 0 : 1;
|
|
2318
|
+
})();
|
|
2319
|
+
}
|
|
1403
2320
|
if (command === "build") {
|
|
1404
|
-
const scriptKind = selectScriptKind(detectScriptKinds(cwd));
|
|
1405
2321
|
const reportBuild = (written, materializedDir) => {
|
|
1406
2322
|
ensureMaterializedReference(cwd, materializedDir);
|
|
1407
2323
|
if (json) {
|
|
@@ -1410,7 +2326,6 @@ function dispatch(argv, io, internals) {
|
|
|
1410
2326
|
written,
|
|
1411
2327
|
defoldVersion: resolvedVersion,
|
|
1412
2328
|
apiSurface,
|
|
1413
|
-
scriptKind,
|
|
1414
2329
|
materializedSurface: materializedDir
|
|
1415
2330
|
}));
|
|
1416
2331
|
} else {
|
|
@@ -1438,7 +2353,6 @@ function dispatch(argv, io, internals) {
|
|
|
1438
2353
|
const { materializedDir } = await materializeRefDocSurface({
|
|
1439
2354
|
cwd,
|
|
1440
2355
|
surfaceId,
|
|
1441
|
-
scriptKind,
|
|
1442
2356
|
...internals?.resolveOpts ? { resolveOpts: internals.resolveOpts } : {},
|
|
1443
2357
|
...internals?.refDocRegistry ? { registry: internals.refDocRegistry } : {}
|
|
1444
2358
|
});
|
|
@@ -1458,8 +2372,7 @@ function dispatch(argv, io, internals) {
|
|
|
1458
2372
|
const { materializedDir } = materializeApiSurface({
|
|
1459
2373
|
cwd,
|
|
1460
2374
|
surface,
|
|
1461
|
-
sourceGeneratedDir
|
|
1462
|
-
scriptKind
|
|
2375
|
+
sourceGeneratedDir
|
|
1463
2376
|
});
|
|
1464
2377
|
return reportBuild(written, materializedDir);
|
|
1465
2378
|
} catch (err) {
|
|
@@ -1473,12 +2386,10 @@ function dispatch(argv, io, internals) {
|
|
|
1473
2386
|
if (!isRefDocSurface) {
|
|
1474
2387
|
const sourceGeneratedDir = internals?.sourceGeneratedDir ?? resolveCurrentSurfaceGeneratedDir();
|
|
1475
2388
|
syncSurface = () => {
|
|
1476
|
-
const scriptKind = selectScriptKind(detectScriptKinds(cwd));
|
|
1477
2389
|
const { materializedDir } = materializeApiSurface({
|
|
1478
2390
|
cwd,
|
|
1479
2391
|
surface,
|
|
1480
|
-
sourceGeneratedDir
|
|
1481
|
-
scriptKind
|
|
2392
|
+
sourceGeneratedDir
|
|
1482
2393
|
});
|
|
1483
2394
|
ensureMaterializedReference(cwd, materializedDir);
|
|
1484
2395
|
};
|
|
@@ -1492,7 +2403,8 @@ function dispatch(argv, io, internals) {
|
|
|
1492
2403
|
...internals?.watcherFactory ? { watcherFactory: internals.watcherFactory } : {},
|
|
1493
2404
|
...internals?.debounceMs !== undefined ? { debounceMs: internals.debounceMs } : {},
|
|
1494
2405
|
...syncSurface ? { syncSurface } : {},
|
|
1495
|
-
...componentWatcherFactory ? { componentWatcherFactory } : {}
|
|
2406
|
+
...componentWatcherFactory ? { componentWatcherFactory } : {},
|
|
2407
|
+
...json ? { json: true } : {}
|
|
1496
2408
|
};
|
|
1497
2409
|
const handle = runWatch(watchOpts);
|
|
1498
2410
|
if (internals) {
|
|
@@ -1509,12 +2421,10 @@ function dispatch(argv, io, internals) {
|
|
|
1509
2421
|
};
|
|
1510
2422
|
if (isRefDocSurface) {
|
|
1511
2423
|
const surfaceId = surface.surfaceId;
|
|
1512
|
-
const scriptKind = selectScriptKind(detectScriptKinds(cwd));
|
|
1513
2424
|
return (async () => {
|
|
1514
2425
|
const { materializedDir } = await materializeRefDocSurface({
|
|
1515
2426
|
cwd,
|
|
1516
2427
|
surfaceId,
|
|
1517
|
-
scriptKind,
|
|
1518
2428
|
...internals?.resolveOpts ? { resolveOpts: internals.resolveOpts } : {},
|
|
1519
2429
|
...internals?.refDocRegistry ? { registry: internals.refDocRegistry } : {}
|
|
1520
2430
|
});
|
|
@@ -1524,6 +2434,116 @@ function dispatch(argv, io, internals) {
|
|
|
1524
2434
|
}
|
|
1525
2435
|
return launchWatch();
|
|
1526
2436
|
}
|
|
2437
|
+
if (command === "wall") {
|
|
2438
|
+
const wallCwd = internals?.cwd ?? process.cwd();
|
|
2439
|
+
const dirs = rest;
|
|
2440
|
+
const toJsonWall = (w) => ({
|
|
2441
|
+
dir: w.dir,
|
|
2442
|
+
kind: w.kind
|
|
2443
|
+
});
|
|
2444
|
+
const reportWalls = (walls) => {
|
|
2445
|
+
if (json) {
|
|
2446
|
+
io.stdout.write(renderResult({ command: "wall", directoryWalls: walls.map(toJsonWall) }));
|
|
2447
|
+
} else if (walls.length === 0) {
|
|
2448
|
+
io.stdout.write(`defold-typescript wall: no directories walled
|
|
2449
|
+
`);
|
|
2450
|
+
} else {
|
|
2451
|
+
io.stdout.write(`defold-typescript wall: walled ${walls.map((w) => w.dir).join(", ")}
|
|
2452
|
+
`);
|
|
2453
|
+
}
|
|
2454
|
+
};
|
|
2455
|
+
if (wallList) {
|
|
2456
|
+
const current = currentWalledDirs(wallCwd);
|
|
2457
|
+
const eligible = eligibleWalls(wallCwd);
|
|
2458
|
+
const currentWalls = eligible.filter((w) => current.includes(w.dir));
|
|
2459
|
+
if (json) {
|
|
2460
|
+
io.stdout.write(renderResult({
|
|
2461
|
+
command: "wall",
|
|
2462
|
+
directoryWalls: currentWalls.map(toJsonWall),
|
|
2463
|
+
eligible: eligible.map(toJsonWall)
|
|
2464
|
+
}));
|
|
2465
|
+
} else {
|
|
2466
|
+
io.stdout.write(`defold-typescript wall: walled [${current.join(", ")}]; eligible [${eligible.map((w) => w.dir).join(", ")}]
|
|
2467
|
+
`);
|
|
2468
|
+
}
|
|
2469
|
+
return 0;
|
|
2470
|
+
}
|
|
2471
|
+
if (dirs.length > 0) {
|
|
2472
|
+
try {
|
|
2473
|
+
const current = currentWalledDirs(wallCwd);
|
|
2474
|
+
const desired = wallRemove ? current.filter((d) => !dirs.includes(d)) : [...current, ...dirs];
|
|
2475
|
+
reportWalls(applyWallSelection(wallCwd, desired));
|
|
2476
|
+
return 0;
|
|
2477
|
+
} catch (err) {
|
|
2478
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2479
|
+
if (json) {
|
|
2480
|
+
io.stdout.write(renderResult({ command: "wall", error: message }));
|
|
2481
|
+
} else {
|
|
2482
|
+
io.stderr.write(`${message}
|
|
2483
|
+
`);
|
|
2484
|
+
}
|
|
2485
|
+
return 1;
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2488
|
+
const interactive = !json && (internals?.isTty ?? Boolean(process.stdout.isTTY));
|
|
2489
|
+
if (!interactive) {
|
|
2490
|
+
io.stderr.write(`defold-typescript wall: no directory given; pass <dir> or run in a terminal for the interactive menu
|
|
2491
|
+
`);
|
|
2492
|
+
return 1;
|
|
2493
|
+
}
|
|
2494
|
+
return (async () => {
|
|
2495
|
+
try {
|
|
2496
|
+
reportWalls(await runWallInteractive(wallCwd, internals?.wallCheckbox ? { checkbox: internals.wallCheckbox } : {}));
|
|
2497
|
+
return 0;
|
|
2498
|
+
} catch (err) {
|
|
2499
|
+
io.stderr.write(`${err instanceof Error ? err.message : String(err)}
|
|
2500
|
+
`);
|
|
2501
|
+
return 1;
|
|
2502
|
+
}
|
|
2503
|
+
})();
|
|
2504
|
+
}
|
|
2505
|
+
if (command === "defold") {
|
|
2506
|
+
const subcommand = rest[0];
|
|
2507
|
+
const defoldCwd = rest[1] ? path15.resolve(rest[1]) : process.cwd();
|
|
2508
|
+
if (!isDefoldSubcommand(subcommand)) {
|
|
2509
|
+
io.stderr.write(DEFOLD_USAGE);
|
|
2510
|
+
return 1;
|
|
2511
|
+
}
|
|
2512
|
+
const javaOverride = javaFlag ?? process.env.DEFOLD_JAVA;
|
|
2513
|
+
const defoldIo = { ...defaultDefoldIo(), ...internals?.defoldIo };
|
|
2514
|
+
return (async () => {
|
|
2515
|
+
try {
|
|
2516
|
+
const result = await runDefoldCommand({
|
|
2517
|
+
cwd: defoldCwd,
|
|
2518
|
+
subcommand,
|
|
2519
|
+
...javaOverride !== undefined ? { java: javaOverride } : {},
|
|
2520
|
+
...buildServerFlag !== undefined ? { buildServer: buildServerFlag } : {},
|
|
2521
|
+
io: defoldIo
|
|
2522
|
+
});
|
|
2523
|
+
if (json) {
|
|
2524
|
+
io.stdout.write(renderResult(result.ok ? { command: "defold", subcommand: result.subcommand, exitCode: result.exitCode } : {
|
|
2525
|
+
command: "defold",
|
|
2526
|
+
subcommand: result.subcommand,
|
|
2527
|
+
exitCode: result.exitCode,
|
|
2528
|
+
error: `bob ${result.subcommand} exited with code ${result.exitCode}`
|
|
2529
|
+
}));
|
|
2530
|
+
} else if (!result.ok) {
|
|
2531
|
+
io.stderr.write(`defold-typescript defold ${result.subcommand}: bob exited with code ${result.exitCode}
|
|
2532
|
+
`);
|
|
2533
|
+
}
|
|
2534
|
+
return result.exitCode;
|
|
2535
|
+
} catch (err) {
|
|
2536
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2537
|
+
if (json) {
|
|
2538
|
+
io.stdout.write(renderResult({ command: "defold", subcommand, error: message }));
|
|
2539
|
+
} else {
|
|
2540
|
+
io.stderr.write(`${message}
|
|
2541
|
+
`);
|
|
2542
|
+
}
|
|
2543
|
+
return 1;
|
|
2544
|
+
}
|
|
2545
|
+
})();
|
|
2546
|
+
}
|
|
1527
2547
|
io.stderr.write(USAGE);
|
|
1528
2548
|
return 1;
|
|
1529
2549
|
}
|