@defold-typescript/cli 0.4.0 → 0.4.2
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 +116 -6
- package/dist/index.js +116 -6
- package/package.json +3 -3
- package/src/init.ts +140 -7
package/dist/bin.js
CHANGED
|
@@ -334,6 +334,13 @@ var BIOME_JSON_CONTENT = {
|
|
|
334
334
|
}
|
|
335
335
|
}
|
|
336
336
|
};
|
|
337
|
+
var VSCODE_EXTENSIONS_CONTENT = {
|
|
338
|
+
recommendations: ["sumneko.lua", "astrochili.defold"],
|
|
339
|
+
unwantedRecommendations: ["johnnymorganz.luau-lsp"]
|
|
340
|
+
};
|
|
341
|
+
var VSCODE_SETTINGS_CONTENT = {
|
|
342
|
+
"Lua.workspace.ignoreDir": ["src"]
|
|
343
|
+
};
|
|
337
344
|
var MAIN_TS_CONTENT = `export function init(): void {
|
|
338
345
|
const start = vmath.vector3(0, 0, 0);
|
|
339
346
|
msg.post("main:/hero", "spawn", { start });
|
|
@@ -367,9 +374,9 @@ var SCAFFOLD_DEV_DEPS = {
|
|
|
367
374
|
"@defold-typescript/types": typesVersionSpec(),
|
|
368
375
|
"@biomejs/biome": "^2.2.0"
|
|
369
376
|
};
|
|
370
|
-
function repairManagedDevDeps(devDeps) {
|
|
377
|
+
function repairManagedDevDeps(devDeps, force = false) {
|
|
371
378
|
delete devDeps["@defold-typescript/transpiler"];
|
|
372
|
-
if (devDeps["@defold-typescript/types"]?.startsWith("workspace:")) {
|
|
379
|
+
if (force || devDeps["@defold-typescript/types"]?.startsWith("workspace:")) {
|
|
373
380
|
devDeps["@defold-typescript/types"] = typesVersionSpec();
|
|
374
381
|
}
|
|
375
382
|
}
|
|
@@ -407,7 +414,108 @@ function writeBiome(cwd, written) {
|
|
|
407
414
|
writeJson(biomePath, BIOME_JSON_CONTENT);
|
|
408
415
|
written.push("biome.json");
|
|
409
416
|
}
|
|
410
|
-
function
|
|
417
|
+
function parseJsonc(text) {
|
|
418
|
+
let out = "";
|
|
419
|
+
let inString = false;
|
|
420
|
+
let inLineComment = false;
|
|
421
|
+
let inBlockComment = false;
|
|
422
|
+
for (let i = 0;i < text.length; i++) {
|
|
423
|
+
const ch = text[i];
|
|
424
|
+
const next = text[i + 1];
|
|
425
|
+
if (inLineComment) {
|
|
426
|
+
if (ch === `
|
|
427
|
+
`) {
|
|
428
|
+
inLineComment = false;
|
|
429
|
+
out += ch;
|
|
430
|
+
}
|
|
431
|
+
continue;
|
|
432
|
+
}
|
|
433
|
+
if (inBlockComment) {
|
|
434
|
+
if (ch === "*" && next === "/") {
|
|
435
|
+
inBlockComment = false;
|
|
436
|
+
i++;
|
|
437
|
+
}
|
|
438
|
+
continue;
|
|
439
|
+
}
|
|
440
|
+
if (inString) {
|
|
441
|
+
out += ch;
|
|
442
|
+
if (ch === "\\") {
|
|
443
|
+
out += next ?? "";
|
|
444
|
+
i++;
|
|
445
|
+
} else if (ch === '"') {
|
|
446
|
+
inString = false;
|
|
447
|
+
}
|
|
448
|
+
continue;
|
|
449
|
+
}
|
|
450
|
+
if (ch === '"') {
|
|
451
|
+
inString = true;
|
|
452
|
+
out += ch;
|
|
453
|
+
} else if (ch === "/" && next === "/") {
|
|
454
|
+
inLineComment = true;
|
|
455
|
+
i++;
|
|
456
|
+
} else if (ch === "/" && next === "*") {
|
|
457
|
+
inBlockComment = true;
|
|
458
|
+
i++;
|
|
459
|
+
} else {
|
|
460
|
+
out += ch;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
return JSON.parse(out.replace(/,(\s*[}\]])/g, "$1"));
|
|
464
|
+
}
|
|
465
|
+
function isJsonObject(value) {
|
|
466
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
467
|
+
}
|
|
468
|
+
function unionStrings(existing, additions) {
|
|
469
|
+
const out = Array.isArray(existing) ? existing.filter((v) => typeof v === "string") : [];
|
|
470
|
+
for (const value of additions) {
|
|
471
|
+
if (!out.includes(value)) {
|
|
472
|
+
out.push(value);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
return out;
|
|
476
|
+
}
|
|
477
|
+
function readVscodeJson(filePath) {
|
|
478
|
+
try {
|
|
479
|
+
const parsed = parseJsonc(readFileSync5(filePath, "utf8"));
|
|
480
|
+
return isJsonObject(parsed) ? parsed : null;
|
|
481
|
+
} catch {
|
|
482
|
+
return null;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
function writeVscodeExtensions(cwd, written) {
|
|
486
|
+
const dir = path6.join(cwd, ".vscode");
|
|
487
|
+
const filePath = path6.join(dir, "extensions.json");
|
|
488
|
+
if (existsSync2(filePath)) {
|
|
489
|
+
const existing = readVscodeJson(filePath);
|
|
490
|
+
if (existing === null) {
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
existing.recommendations = unionStrings(existing.recommendations, VSCODE_EXTENSIONS_CONTENT.recommendations);
|
|
494
|
+
existing.unwantedRecommendations = unionStrings(existing.unwantedRecommendations, VSCODE_EXTENSIONS_CONTENT.unwantedRecommendations);
|
|
495
|
+
writeJson(filePath, existing);
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
mkdirSync2(dir, { recursive: true });
|
|
499
|
+
writeJson(filePath, VSCODE_EXTENSIONS_CONTENT);
|
|
500
|
+
written.push(".vscode/extensions.json");
|
|
501
|
+
}
|
|
502
|
+
function writeVscodeSettings(cwd, written) {
|
|
503
|
+
const dir = path6.join(cwd, ".vscode");
|
|
504
|
+
const filePath = path6.join(dir, "settings.json");
|
|
505
|
+
if (existsSync2(filePath)) {
|
|
506
|
+
const existing = readVscodeJson(filePath);
|
|
507
|
+
if (existing === null) {
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
510
|
+
existing["Lua.workspace.ignoreDir"] = unionStrings(existing["Lua.workspace.ignoreDir"], VSCODE_SETTINGS_CONTENT["Lua.workspace.ignoreDir"]);
|
|
511
|
+
writeJson(filePath, existing);
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
mkdirSync2(dir, { recursive: true });
|
|
515
|
+
writeJson(filePath, VSCODE_SETTINGS_CONTENT);
|
|
516
|
+
written.push(".vscode/settings.json");
|
|
517
|
+
}
|
|
518
|
+
function writeTsSurface(cwd, written, force = false) {
|
|
411
519
|
mkdirSync2(path6.join(cwd, "src"), { recursive: true });
|
|
412
520
|
writeFileSync2(path6.join(cwd, "src", "main.ts"), MAIN_TS_CONTENT);
|
|
413
521
|
written.push("src/main.ts");
|
|
@@ -430,7 +538,7 @@ function writeTsSurface(cwd, written) {
|
|
|
430
538
|
devDeps[name] = version;
|
|
431
539
|
}
|
|
432
540
|
}
|
|
433
|
-
repairManagedDevDeps(devDeps);
|
|
541
|
+
repairManagedDevDeps(devDeps, force);
|
|
434
542
|
existing.devDependencies = devDeps;
|
|
435
543
|
existing["defold-typescript"] ??= { "defold-version": CURRENT_STABLE_DEFOLD_VERSION };
|
|
436
544
|
writeJson(pkgPath, existing);
|
|
@@ -448,6 +556,8 @@ function writeTsSurface(cwd, written) {
|
|
|
448
556
|
writeGitignore(cwd);
|
|
449
557
|
written.push(".gitignore");
|
|
450
558
|
writeBiome(cwd, written);
|
|
559
|
+
writeVscodeExtensions(cwd, written);
|
|
560
|
+
writeVscodeSettings(cwd, written);
|
|
451
561
|
return selectScriptKind(kinds);
|
|
452
562
|
}
|
|
453
563
|
function runNewProjectInit(cwd, force = false) {
|
|
@@ -467,7 +577,7 @@ main_collection = /main/main.collectionc
|
|
|
467
577
|
written.push("main/main.collection");
|
|
468
578
|
writeFileSync2(path6.join(cwd, "main", "main.script"), MAIN_SCRIPT_CONTENT);
|
|
469
579
|
written.push("main/main.script");
|
|
470
|
-
const scriptKind = writeTsSurface(cwd, written);
|
|
580
|
+
const scriptKind = writeTsSurface(cwd, written, force);
|
|
471
581
|
return { written, scriptKind };
|
|
472
582
|
}
|
|
473
583
|
function runInit(opts) {
|
|
@@ -483,7 +593,7 @@ function runInit(opts) {
|
|
|
483
593
|
}
|
|
484
594
|
}
|
|
485
595
|
const written = [];
|
|
486
|
-
const scriptKind = writeTsSurface(cwd, written);
|
|
596
|
+
const scriptKind = writeTsSurface(cwd, written, force);
|
|
487
597
|
return { written, scriptKind };
|
|
488
598
|
}
|
|
489
599
|
|
package/dist/index.js
CHANGED
|
@@ -398,6 +398,13 @@ var BIOME_JSON_CONTENT = {
|
|
|
398
398
|
}
|
|
399
399
|
}
|
|
400
400
|
};
|
|
401
|
+
var VSCODE_EXTENSIONS_CONTENT = {
|
|
402
|
+
recommendations: ["sumneko.lua", "astrochili.defold"],
|
|
403
|
+
unwantedRecommendations: ["johnnymorganz.luau-lsp"]
|
|
404
|
+
};
|
|
405
|
+
var VSCODE_SETTINGS_CONTENT = {
|
|
406
|
+
"Lua.workspace.ignoreDir": ["src"]
|
|
407
|
+
};
|
|
401
408
|
var MAIN_TS_CONTENT = `export function init(): void {
|
|
402
409
|
const start = vmath.vector3(0, 0, 0);
|
|
403
410
|
msg.post("main:/hero", "spawn", { start });
|
|
@@ -431,9 +438,9 @@ var SCAFFOLD_DEV_DEPS = {
|
|
|
431
438
|
"@defold-typescript/types": typesVersionSpec(),
|
|
432
439
|
"@biomejs/biome": "^2.2.0"
|
|
433
440
|
};
|
|
434
|
-
function repairManagedDevDeps(devDeps) {
|
|
441
|
+
function repairManagedDevDeps(devDeps, force = false) {
|
|
435
442
|
delete devDeps["@defold-typescript/transpiler"];
|
|
436
|
-
if (devDeps["@defold-typescript/types"]?.startsWith("workspace:")) {
|
|
443
|
+
if (force || devDeps["@defold-typescript/types"]?.startsWith("workspace:")) {
|
|
437
444
|
devDeps["@defold-typescript/types"] = typesVersionSpec();
|
|
438
445
|
}
|
|
439
446
|
}
|
|
@@ -471,7 +478,108 @@ function writeBiome(cwd, written) {
|
|
|
471
478
|
writeJson(biomePath, BIOME_JSON_CONTENT);
|
|
472
479
|
written.push("biome.json");
|
|
473
480
|
}
|
|
474
|
-
function
|
|
481
|
+
function parseJsonc(text) {
|
|
482
|
+
let out = "";
|
|
483
|
+
let inString = false;
|
|
484
|
+
let inLineComment = false;
|
|
485
|
+
let inBlockComment = false;
|
|
486
|
+
for (let i = 0;i < text.length; i++) {
|
|
487
|
+
const ch = text[i];
|
|
488
|
+
const next = text[i + 1];
|
|
489
|
+
if (inLineComment) {
|
|
490
|
+
if (ch === `
|
|
491
|
+
`) {
|
|
492
|
+
inLineComment = false;
|
|
493
|
+
out += ch;
|
|
494
|
+
}
|
|
495
|
+
continue;
|
|
496
|
+
}
|
|
497
|
+
if (inBlockComment) {
|
|
498
|
+
if (ch === "*" && next === "/") {
|
|
499
|
+
inBlockComment = false;
|
|
500
|
+
i++;
|
|
501
|
+
}
|
|
502
|
+
continue;
|
|
503
|
+
}
|
|
504
|
+
if (inString) {
|
|
505
|
+
out += ch;
|
|
506
|
+
if (ch === "\\") {
|
|
507
|
+
out += next ?? "";
|
|
508
|
+
i++;
|
|
509
|
+
} else if (ch === '"') {
|
|
510
|
+
inString = false;
|
|
511
|
+
}
|
|
512
|
+
continue;
|
|
513
|
+
}
|
|
514
|
+
if (ch === '"') {
|
|
515
|
+
inString = true;
|
|
516
|
+
out += ch;
|
|
517
|
+
} else if (ch === "/" && next === "/") {
|
|
518
|
+
inLineComment = true;
|
|
519
|
+
i++;
|
|
520
|
+
} else if (ch === "/" && next === "*") {
|
|
521
|
+
inBlockComment = true;
|
|
522
|
+
i++;
|
|
523
|
+
} else {
|
|
524
|
+
out += ch;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
return JSON.parse(out.replace(/,(\s*[}\]])/g, "$1"));
|
|
528
|
+
}
|
|
529
|
+
function isJsonObject(value) {
|
|
530
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
531
|
+
}
|
|
532
|
+
function unionStrings(existing, additions) {
|
|
533
|
+
const out = Array.isArray(existing) ? existing.filter((v) => typeof v === "string") : [];
|
|
534
|
+
for (const value of additions) {
|
|
535
|
+
if (!out.includes(value)) {
|
|
536
|
+
out.push(value);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
return out;
|
|
540
|
+
}
|
|
541
|
+
function readVscodeJson(filePath) {
|
|
542
|
+
try {
|
|
543
|
+
const parsed = parseJsonc(readFileSync6(filePath, "utf8"));
|
|
544
|
+
return isJsonObject(parsed) ? parsed : null;
|
|
545
|
+
} catch {
|
|
546
|
+
return null;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
function writeVscodeExtensions(cwd, written) {
|
|
550
|
+
const dir = path7.join(cwd, ".vscode");
|
|
551
|
+
const filePath = path7.join(dir, "extensions.json");
|
|
552
|
+
if (existsSync2(filePath)) {
|
|
553
|
+
const existing = readVscodeJson(filePath);
|
|
554
|
+
if (existing === null) {
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
existing.recommendations = unionStrings(existing.recommendations, VSCODE_EXTENSIONS_CONTENT.recommendations);
|
|
558
|
+
existing.unwantedRecommendations = unionStrings(existing.unwantedRecommendations, VSCODE_EXTENSIONS_CONTENT.unwantedRecommendations);
|
|
559
|
+
writeJson(filePath, existing);
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
mkdirSync2(dir, { recursive: true });
|
|
563
|
+
writeJson(filePath, VSCODE_EXTENSIONS_CONTENT);
|
|
564
|
+
written.push(".vscode/extensions.json");
|
|
565
|
+
}
|
|
566
|
+
function writeVscodeSettings(cwd, written) {
|
|
567
|
+
const dir = path7.join(cwd, ".vscode");
|
|
568
|
+
const filePath = path7.join(dir, "settings.json");
|
|
569
|
+
if (existsSync2(filePath)) {
|
|
570
|
+
const existing = readVscodeJson(filePath);
|
|
571
|
+
if (existing === null) {
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
574
|
+
existing["Lua.workspace.ignoreDir"] = unionStrings(existing["Lua.workspace.ignoreDir"], VSCODE_SETTINGS_CONTENT["Lua.workspace.ignoreDir"]);
|
|
575
|
+
writeJson(filePath, existing);
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
578
|
+
mkdirSync2(dir, { recursive: true });
|
|
579
|
+
writeJson(filePath, VSCODE_SETTINGS_CONTENT);
|
|
580
|
+
written.push(".vscode/settings.json");
|
|
581
|
+
}
|
|
582
|
+
function writeTsSurface(cwd, written, force = false) {
|
|
475
583
|
mkdirSync2(path7.join(cwd, "src"), { recursive: true });
|
|
476
584
|
writeFileSync2(path7.join(cwd, "src", "main.ts"), MAIN_TS_CONTENT);
|
|
477
585
|
written.push("src/main.ts");
|
|
@@ -494,7 +602,7 @@ function writeTsSurface(cwd, written) {
|
|
|
494
602
|
devDeps[name] = version;
|
|
495
603
|
}
|
|
496
604
|
}
|
|
497
|
-
repairManagedDevDeps(devDeps);
|
|
605
|
+
repairManagedDevDeps(devDeps, force);
|
|
498
606
|
existing.devDependencies = devDeps;
|
|
499
607
|
existing["defold-typescript"] ??= { "defold-version": CURRENT_STABLE_DEFOLD_VERSION };
|
|
500
608
|
writeJson(pkgPath, existing);
|
|
@@ -512,6 +620,8 @@ function writeTsSurface(cwd, written) {
|
|
|
512
620
|
writeGitignore(cwd);
|
|
513
621
|
written.push(".gitignore");
|
|
514
622
|
writeBiome(cwd, written);
|
|
623
|
+
writeVscodeExtensions(cwd, written);
|
|
624
|
+
writeVscodeSettings(cwd, written);
|
|
515
625
|
return selectScriptKind(kinds);
|
|
516
626
|
}
|
|
517
627
|
function runNewProjectInit(cwd, force = false) {
|
|
@@ -531,7 +641,7 @@ main_collection = /main/main.collectionc
|
|
|
531
641
|
written.push("main/main.collection");
|
|
532
642
|
writeFileSync2(path7.join(cwd, "main", "main.script"), MAIN_SCRIPT_CONTENT);
|
|
533
643
|
written.push("main/main.script");
|
|
534
|
-
const scriptKind = writeTsSurface(cwd, written);
|
|
644
|
+
const scriptKind = writeTsSurface(cwd, written, force);
|
|
535
645
|
return { written, scriptKind };
|
|
536
646
|
}
|
|
537
647
|
function runInit(opts) {
|
|
@@ -547,7 +657,7 @@ function runInit(opts) {
|
|
|
547
657
|
}
|
|
548
658
|
}
|
|
549
659
|
const written = [];
|
|
550
|
-
const scriptKind = writeTsSurface(cwd, written);
|
|
660
|
+
const scriptKind = writeTsSurface(cwd, written, force);
|
|
551
661
|
return { written, scriptKind };
|
|
552
662
|
}
|
|
553
663
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@defold-typescript/cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "End-user CLI for scaffolding and building Defold projects written in TypeScript.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"test": "bun test"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@defold-typescript/transpiler": "0.4.
|
|
35
|
-
"@defold-typescript/types": "0.4.
|
|
34
|
+
"@defold-typescript/transpiler": "0.4.2",
|
|
35
|
+
"@defold-typescript/types": "0.4.2"
|
|
36
36
|
}
|
|
37
37
|
}
|
package/src/init.ts
CHANGED
|
@@ -72,6 +72,15 @@ const BIOME_JSON_CONTENT = {
|
|
|
72
72
|
},
|
|
73
73
|
};
|
|
74
74
|
|
|
75
|
+
const VSCODE_EXTENSIONS_CONTENT = {
|
|
76
|
+
recommendations: ["sumneko.lua", "astrochili.defold"],
|
|
77
|
+
unwantedRecommendations: ["johnnymorganz.luau-lsp"],
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const VSCODE_SETTINGS_CONTENT = {
|
|
81
|
+
"Lua.workspace.ignoreDir": ["src"],
|
|
82
|
+
};
|
|
83
|
+
|
|
75
84
|
const MAIN_TS_CONTENT = `export function init(): void {
|
|
76
85
|
const start = vmath.vector3(0, 0, 0);
|
|
77
86
|
msg.post("main:/hero", "spawn", { start });
|
|
@@ -134,10 +143,11 @@ const SCAFFOLD_DEV_DEPS: Record<string, string> = {
|
|
|
134
143
|
// repairs an entry it didn't itself create, so repair them explicitly: the
|
|
135
144
|
// transpiler is CLI-internal and must not be a consumer dep at all, and a
|
|
136
145
|
// `workspace:` types pin must become a concrete published version. A concrete
|
|
137
|
-
// user-chosen types pin is left alone
|
|
138
|
-
|
|
146
|
+
// user-chosen types pin is left alone unless `force` is set, the explicit
|
|
147
|
+
// opt-in to refresh the managed pin (and only that pin) to the CLI's version.
|
|
148
|
+
function repairManagedDevDeps(devDeps: Record<string, string>, force = false): void {
|
|
139
149
|
delete devDeps["@defold-typescript/transpiler"];
|
|
140
|
-
if (devDeps["@defold-typescript/types"]?.startsWith("workspace:")) {
|
|
150
|
+
if (force || devDeps["@defold-typescript/types"]?.startsWith("workspace:")) {
|
|
141
151
|
devDeps["@defold-typescript/types"] = typesVersionSpec();
|
|
142
152
|
}
|
|
143
153
|
}
|
|
@@ -171,7 +181,127 @@ function writeBiome(cwd: string, written: string[]): void {
|
|
|
171
181
|
written.push("biome.json");
|
|
172
182
|
}
|
|
173
183
|
|
|
174
|
-
|
|
184
|
+
// Strip `//` line comments, `/* */` block comments, and trailing commas so a
|
|
185
|
+
// hand-edited JSONC `.vscode` file parses with `JSON.parse`. The walk tracks
|
|
186
|
+
// string state so a `//` or comma inside a value (e.g. a URL) is preserved.
|
|
187
|
+
function parseJsonc(text: string): unknown {
|
|
188
|
+
let out = "";
|
|
189
|
+
let inString = false;
|
|
190
|
+
let inLineComment = false;
|
|
191
|
+
let inBlockComment = false;
|
|
192
|
+
for (let i = 0; i < text.length; i++) {
|
|
193
|
+
const ch = text[i];
|
|
194
|
+
const next = text[i + 1];
|
|
195
|
+
if (inLineComment) {
|
|
196
|
+
if (ch === "\n") {
|
|
197
|
+
inLineComment = false;
|
|
198
|
+
out += ch;
|
|
199
|
+
}
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
if (inBlockComment) {
|
|
203
|
+
if (ch === "*" && next === "/") {
|
|
204
|
+
inBlockComment = false;
|
|
205
|
+
i++;
|
|
206
|
+
}
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
if (inString) {
|
|
210
|
+
out += ch;
|
|
211
|
+
if (ch === "\\") {
|
|
212
|
+
out += next ?? "";
|
|
213
|
+
i++;
|
|
214
|
+
} else if (ch === '"') {
|
|
215
|
+
inString = false;
|
|
216
|
+
}
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
if (ch === '"') {
|
|
220
|
+
inString = true;
|
|
221
|
+
out += ch;
|
|
222
|
+
} else if (ch === "/" && next === "/") {
|
|
223
|
+
inLineComment = true;
|
|
224
|
+
i++;
|
|
225
|
+
} else if (ch === "/" && next === "*") {
|
|
226
|
+
inBlockComment = true;
|
|
227
|
+
i++;
|
|
228
|
+
} else {
|
|
229
|
+
out += ch;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return JSON.parse(out.replace(/,(\s*[}\]])/g, "$1"));
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function isJsonObject(value: unknown): value is Record<string, unknown> {
|
|
236
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function unionStrings(existing: unknown, additions: readonly string[]): string[] {
|
|
240
|
+
const out = Array.isArray(existing)
|
|
241
|
+
? existing.filter((v): v is string => typeof v === "string")
|
|
242
|
+
: [];
|
|
243
|
+
for (const value of additions) {
|
|
244
|
+
if (!out.includes(value)) {
|
|
245
|
+
out.push(value);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
return out;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function readVscodeJson(filePath: string): Record<string, unknown> | null {
|
|
252
|
+
try {
|
|
253
|
+
const parsed = parseJsonc(readFileSync(filePath, "utf8"));
|
|
254
|
+
return isJsonObject(parsed) ? parsed : null;
|
|
255
|
+
} catch {
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function writeVscodeExtensions(cwd: string, written: string[]): void {
|
|
261
|
+
const dir = path.join(cwd, ".vscode");
|
|
262
|
+
const filePath = path.join(dir, "extensions.json");
|
|
263
|
+
if (existsSync(filePath)) {
|
|
264
|
+
const existing = readVscodeJson(filePath);
|
|
265
|
+
if (existing === null) {
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
existing.recommendations = unionStrings(
|
|
269
|
+
existing.recommendations,
|
|
270
|
+
VSCODE_EXTENSIONS_CONTENT.recommendations,
|
|
271
|
+
);
|
|
272
|
+
existing.unwantedRecommendations = unionStrings(
|
|
273
|
+
existing.unwantedRecommendations,
|
|
274
|
+
VSCODE_EXTENSIONS_CONTENT.unwantedRecommendations,
|
|
275
|
+
);
|
|
276
|
+
writeJson(filePath, existing);
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
mkdirSync(dir, { recursive: true });
|
|
280
|
+
writeJson(filePath, VSCODE_EXTENSIONS_CONTENT);
|
|
281
|
+
written.push(".vscode/extensions.json");
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function writeVscodeSettings(cwd: string, written: string[]): void {
|
|
285
|
+
const dir = path.join(cwd, ".vscode");
|
|
286
|
+
const filePath = path.join(dir, "settings.json");
|
|
287
|
+
if (existsSync(filePath)) {
|
|
288
|
+
const existing = readVscodeJson(filePath);
|
|
289
|
+
if (existing === null) {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
existing["Lua.workspace.ignoreDir"] = unionStrings(
|
|
293
|
+
existing["Lua.workspace.ignoreDir"],
|
|
294
|
+
VSCODE_SETTINGS_CONTENT["Lua.workspace.ignoreDir"],
|
|
295
|
+
);
|
|
296
|
+
writeJson(filePath, existing);
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
mkdirSync(dir, { recursive: true });
|
|
300
|
+
writeJson(filePath, VSCODE_SETTINGS_CONTENT);
|
|
301
|
+
written.push(".vscode/settings.json");
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
function writeTsSurface(cwd: string, written: string[], force = false): ScriptKind | null {
|
|
175
305
|
mkdirSync(path.join(cwd, "src"), { recursive: true });
|
|
176
306
|
writeFileSync(path.join(cwd, "src", "main.ts"), MAIN_TS_CONTENT);
|
|
177
307
|
written.push("src/main.ts");
|
|
@@ -196,7 +326,7 @@ function writeTsSurface(cwd: string, written: string[]): ScriptKind | null {
|
|
|
196
326
|
devDeps[name] = version;
|
|
197
327
|
}
|
|
198
328
|
}
|
|
199
|
-
repairManagedDevDeps(devDeps);
|
|
329
|
+
repairManagedDevDeps(devDeps, force);
|
|
200
330
|
existing.devDependencies = devDeps;
|
|
201
331
|
existing["defold-typescript"] ??= { "defold-version": CURRENT_STABLE_DEFOLD_VERSION };
|
|
202
332
|
writeJson(pkgPath, existing);
|
|
@@ -217,6 +347,9 @@ function writeTsSurface(cwd: string, written: string[]): ScriptKind | null {
|
|
|
217
347
|
|
|
218
348
|
writeBiome(cwd, written);
|
|
219
349
|
|
|
350
|
+
writeVscodeExtensions(cwd, written);
|
|
351
|
+
writeVscodeSettings(cwd, written);
|
|
352
|
+
|
|
220
353
|
return selectScriptKind(kinds);
|
|
221
354
|
}
|
|
222
355
|
|
|
@@ -243,7 +376,7 @@ export function runNewProjectInit(cwd: string, force = false): RunInitResult {
|
|
|
243
376
|
writeFileSync(path.join(cwd, "main", "main.script"), MAIN_SCRIPT_CONTENT);
|
|
244
377
|
written.push("main/main.script");
|
|
245
378
|
|
|
246
|
-
const scriptKind = writeTsSurface(cwd, written);
|
|
379
|
+
const scriptKind = writeTsSurface(cwd, written, force);
|
|
247
380
|
|
|
248
381
|
return { written, scriptKind };
|
|
249
382
|
}
|
|
@@ -266,6 +399,6 @@ export function runInit(opts: RunInitOptions): RunInitResult {
|
|
|
266
399
|
}
|
|
267
400
|
|
|
268
401
|
const written: string[] = [];
|
|
269
|
-
const scriptKind = writeTsSurface(cwd, written);
|
|
402
|
+
const scriptKind = writeTsSurface(cwd, written, force);
|
|
270
403
|
return { written, scriptKind };
|
|
271
404
|
}
|