@defold-typescript/cli 0.5.5 → 0.7.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/README.md +2 -2
- 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 +11 -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/src/build-session.ts
CHANGED
|
@@ -8,8 +8,10 @@ import {
|
|
|
8
8
|
import {
|
|
9
9
|
type BuildConfig,
|
|
10
10
|
collectFailures,
|
|
11
|
-
|
|
11
|
+
computeOutputRel,
|
|
12
|
+
detectSourceOutputKind,
|
|
12
13
|
isTranspilerSource,
|
|
14
|
+
outputRelsForSource,
|
|
13
15
|
readBuildConfig,
|
|
14
16
|
throwIfFailures,
|
|
15
17
|
toPosix,
|
|
@@ -35,7 +37,20 @@ export function createBuildSession(opts: CreateBuildSessionOptions): BuildSessio
|
|
|
35
37
|
const config: BuildConfig = readBuildConfig(cwd);
|
|
36
38
|
const session: TranspileSession = createTranspileSession();
|
|
37
39
|
|
|
38
|
-
function
|
|
40
|
+
function pruneOutputs(rel: string, keepRel?: string): void {
|
|
41
|
+
for (const outputRel of outputRelsForSource(rel, config)) {
|
|
42
|
+
if (outputRel !== keepRel && outputRel !== `${keepRel}.map`) {
|
|
43
|
+
rmSync(path.join(cwd, outputRel), { force: true });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function writeOutputs(
|
|
49
|
+
result: TranspileProjectResult,
|
|
50
|
+
keys: readonly string[],
|
|
51
|
+
sources: Record<string, string>,
|
|
52
|
+
pruneAlternatives = false,
|
|
53
|
+
): BuildResult {
|
|
39
54
|
const failures = collectFailures(result.diagnostics);
|
|
40
55
|
const written: string[] = [];
|
|
41
56
|
for (const rel of keys) {
|
|
@@ -46,12 +61,15 @@ export function createBuildSession(opts: CreateBuildSessionOptions): BuildSessio
|
|
|
46
61
|
if (lua === undefined) {
|
|
47
62
|
continue;
|
|
48
63
|
}
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
64
|
+
const outputRel = computeOutputRel(rel, config, detectSourceOutputKind(sources[rel] ?? ""));
|
|
65
|
+
if (pruneAlternatives) {
|
|
66
|
+
pruneOutputs(rel, outputRel);
|
|
67
|
+
}
|
|
68
|
+
writeScriptFile(cwd, outputRel, lua, result.sourceMaps[rel]);
|
|
69
|
+
written.push(outputRel);
|
|
52
70
|
}
|
|
53
71
|
throwIfFailures(failures);
|
|
54
|
-
return { written };
|
|
72
|
+
return { written: written.sort() };
|
|
55
73
|
}
|
|
56
74
|
|
|
57
75
|
function buildAll(): BuildResult {
|
|
@@ -72,7 +90,7 @@ export function createBuildSession(opts: CreateBuildSessionOptions): BuildSessio
|
|
|
72
90
|
}
|
|
73
91
|
|
|
74
92
|
const result = session.update(files);
|
|
75
|
-
return writeOutputs(result, sources);
|
|
93
|
+
return writeOutputs(result, sources, files);
|
|
76
94
|
}
|
|
77
95
|
|
|
78
96
|
function applyEvents(changed: string[], removed: string[]): BuildResult {
|
|
@@ -89,12 +107,14 @@ export function createBuildSession(opts: CreateBuildSessionOptions): BuildSessio
|
|
|
89
107
|
const result = session.update(changes);
|
|
90
108
|
|
|
91
109
|
for (const rel of sourceRemoved) {
|
|
92
|
-
|
|
93
|
-
rmSync(scriptAbs, { force: true });
|
|
94
|
-
rmSync(`${scriptAbs}.map`, { force: true });
|
|
110
|
+
pruneOutputs(rel);
|
|
95
111
|
}
|
|
96
112
|
|
|
97
|
-
|
|
113
|
+
const changedSources: Record<string, string> = {};
|
|
114
|
+
for (const rel of sourceChanged) {
|
|
115
|
+
changedSources[rel] = changes[rel] ?? "";
|
|
116
|
+
}
|
|
117
|
+
return writeOutputs(result, sourceChanged, changedSources, true);
|
|
98
118
|
}
|
|
99
119
|
|
|
100
120
|
return { buildAll, applyEvents };
|
package/src/build.ts
CHANGED
|
@@ -3,7 +3,8 @@ import * as path from "node:path";
|
|
|
3
3
|
import { transpileProject } from "@defold-typescript/transpiler";
|
|
4
4
|
import {
|
|
5
5
|
collectFailures,
|
|
6
|
-
|
|
6
|
+
computeOutputRel,
|
|
7
|
+
detectSourceOutputKind,
|
|
7
8
|
readBuildConfig,
|
|
8
9
|
throwIfFailures,
|
|
9
10
|
toPosix,
|
|
@@ -52,11 +53,11 @@ export function runBuild(opts: RunBuildOptions): RunBuildResult {
|
|
|
52
53
|
if (!lua) {
|
|
53
54
|
continue;
|
|
54
55
|
}
|
|
55
|
-
const
|
|
56
|
-
writeScriptFile(cwd,
|
|
57
|
-
written.push(
|
|
56
|
+
const outputRel = computeOutputRel(rel, config, detectSourceOutputKind(files[rel] ?? ""));
|
|
57
|
+
writeScriptFile(cwd, outputRel, lua, result.sourceMaps[rel]);
|
|
58
|
+
written.push(outputRel);
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
throwIfFailures(failures);
|
|
61
|
-
return { written };
|
|
62
|
+
return { written: written.sort() };
|
|
62
63
|
}
|
package/src/debug-launcher.ts
CHANGED
|
@@ -7,28 +7,44 @@ export interface EngineTarget {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
// `enginePlatform` keys the d.defold.com download path; `buildFolder` keys the
|
|
10
|
-
// native-extension build output.
|
|
11
|
-
//
|
|
10
|
+
// native-extension build output. Current Defold uses the same `-macos` identifier
|
|
11
|
+
// for both, but they are tracked separately so a future divergence stays local.
|
|
12
|
+
// Keyed by `${process.platform}-${process.arch}` because Apple Silicon and Intel
|
|
13
|
+
// resolve to different engine archives (`arm64-macos` vs `x86_64-macos`).
|
|
12
14
|
const PLATFORM_TARGETS: Record<string, EngineTarget> = {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
"darwin-arm64": {
|
|
16
|
+
enginePlatform: "arm64-macos",
|
|
17
|
+
buildFolder: "arm64-macos",
|
|
18
|
+
executable: "dmengine",
|
|
19
|
+
},
|
|
20
|
+
"darwin-x64": {
|
|
21
|
+
enginePlatform: "x86_64-macos",
|
|
22
|
+
buildFolder: "x86_64-macos",
|
|
23
|
+
executable: "dmengine",
|
|
24
|
+
},
|
|
25
|
+
"linux-x64": {
|
|
26
|
+
enginePlatform: "x86_64-linux",
|
|
27
|
+
buildFolder: "x86_64-linux",
|
|
28
|
+
executable: "dmengine",
|
|
29
|
+
},
|
|
30
|
+
"win32-x64": {
|
|
16
31
|
enginePlatform: "x86_64-win32",
|
|
17
32
|
buildFolder: "x86_64-win32",
|
|
18
33
|
executable: "dmengine.exe",
|
|
19
34
|
},
|
|
20
35
|
};
|
|
21
36
|
|
|
22
|
-
const ENGINE_INFO_URL = "https://d.defold.com/stable/info.json";
|
|
23
|
-
const ENGINE_ARCHIVE_BASE = "https://d.defold.com/archive/stable";
|
|
37
|
+
export const ENGINE_INFO_URL = "https://d.defold.com/stable/info.json";
|
|
38
|
+
export const ENGINE_ARCHIVE_BASE = "https://d.defold.com/archive/stable";
|
|
24
39
|
|
|
25
40
|
export const DEBUG_LAUNCHER_REL = ".vscode/defold-debug.ts";
|
|
26
41
|
|
|
27
|
-
export function targetPlatform(platform: NodeJS.Platform): EngineTarget {
|
|
28
|
-
const
|
|
42
|
+
export function targetPlatform(platform: NodeJS.Platform, arch: string): EngineTarget {
|
|
43
|
+
const key = `${platform}-${arch}`;
|
|
44
|
+
const target = PLATFORM_TARGETS[key];
|
|
29
45
|
if (!target) {
|
|
30
46
|
throw new Error(
|
|
31
|
-
`defold-typescript debug: unsupported platform "${
|
|
47
|
+
`defold-typescript debug: unsupported platform "${key}"; expected one of ${Object.keys(
|
|
32
48
|
PLATFORM_TARGETS,
|
|
33
49
|
).join(", ")}.`,
|
|
34
50
|
);
|
|
@@ -69,6 +85,14 @@ export function debugLaunchConfig() {
|
|
|
69
85
|
internalConsoleOptions: "openOnSessionStart",
|
|
70
86
|
program: { command: "bun" },
|
|
71
87
|
args: [DEBUG_LAUNCHER_REL],
|
|
88
|
+
// Local Lua Debugger (>=0.3.0) pre-scans `scriptFiles` for the emitted
|
|
89
|
+
// `--# sourceMappingURL=` trailers so a breakpoint in a `.ts` resolves
|
|
90
|
+
// ahead of time; without it no source-mapped breakpoint ever binds. Every
|
|
91
|
+
// build emits `<name>.ts.script` under `src/`. `scriptRoots` lets the
|
|
92
|
+
// debugger resolve the running Defold chunk path (`/src/...`) and the map's
|
|
93
|
+
// bare `sources` entry (`player.ts`) back to files on disk.
|
|
94
|
+
scriptFiles: ["src/**/*.ts.script"],
|
|
95
|
+
scriptRoots: [".", "src"],
|
|
72
96
|
};
|
|
73
97
|
}
|
|
74
98
|
|
|
@@ -103,9 +127,9 @@ const PLATFORM_TARGETS: Record<string, EngineTarget> = ${targets};
|
|
|
103
127
|
const ENGINE_INFO_URL = "${ENGINE_INFO_URL}";
|
|
104
128
|
const ENGINE_ARCHIVE_BASE = "${ENGINE_ARCHIVE_BASE}";
|
|
105
129
|
|
|
106
|
-
const target = PLATFORM_TARGETS[process.platform];
|
|
130
|
+
const target = PLATFORM_TARGETS[\`\${process.platform}-\${process.arch}\`];
|
|
107
131
|
if (!target) {
|
|
108
|
-
console.error(\`Unsupported platform: \${process.platform}\`);
|
|
132
|
+
console.error(\`Unsupported platform: \${process.platform}-\${process.arch}\`);
|
|
109
133
|
process.exit(1);
|
|
110
134
|
}
|
|
111
135
|
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { detectSourceOutputKind, isTranspilerSource, readBuildConfig } from "./build-output";
|
|
4
|
+
import { scanFilesSync } from "./scan";
|
|
5
|
+
import {
|
|
6
|
+
isSkipped,
|
|
7
|
+
type ScriptKind,
|
|
8
|
+
selectDirectoryWalls,
|
|
9
|
+
selectScriptKind,
|
|
10
|
+
selectScriptKindEntrypoint,
|
|
11
|
+
} from "./script-kind";
|
|
12
|
+
|
|
13
|
+
export interface DirectoryWall {
|
|
14
|
+
readonly dir: string;
|
|
15
|
+
readonly kind: ScriptKind;
|
|
16
|
+
readonly typesEntrypoint: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function describeWall(dir: string, kind: ScriptKind): DirectoryWall {
|
|
20
|
+
return {
|
|
21
|
+
dir,
|
|
22
|
+
kind,
|
|
23
|
+
typesEntrypoint: selectScriptKindEntrypoint(new Set([kind])),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function planDirectoryWalls(cwd: string): DirectoryWall[] {
|
|
28
|
+
return [...selectDirectoryWalls(cwd)]
|
|
29
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
30
|
+
.map(([dir, kind]) => describeWall(dir, kind));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function groupSourceScriptKindsByDirectory(cwd: string): Map<string, Set<ScriptKind>> {
|
|
34
|
+
const byDir = new Map<string, Set<ScriptKind>>();
|
|
35
|
+
const seen = new Set<string>();
|
|
36
|
+
for (const pattern of readBuildConfig(cwd).include) {
|
|
37
|
+
for (const match of scanFilesSync(cwd, pattern)) {
|
|
38
|
+
const rel = match.split(path.sep).join("/");
|
|
39
|
+
if (seen.has(rel) || !isTranspilerSource(rel) || isSkipped(rel)) {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
seen.add(rel);
|
|
43
|
+
const kind = detectSourceOutputKind(readFileSync(path.join(cwd, match), "utf8"));
|
|
44
|
+
if (kind === "module") {
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
const dir = path.posix.dirname(rel);
|
|
48
|
+
let set = byDir.get(dir);
|
|
49
|
+
if (set === undefined) {
|
|
50
|
+
set = new Set<ScriptKind>();
|
|
51
|
+
byDir.set(dir, set);
|
|
52
|
+
}
|
|
53
|
+
set.add(kind);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return byDir;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function planSourceDirectoryWalls(cwd: string): DirectoryWall[] {
|
|
60
|
+
const walls: DirectoryWall[] = [];
|
|
61
|
+
for (const [dir, kinds] of groupSourceScriptKindsByDirectory(cwd)) {
|
|
62
|
+
const kind = selectScriptKind(kinds);
|
|
63
|
+
if (kind !== null) {
|
|
64
|
+
walls.push(describeWall(dir, kind));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return walls.sort((a, b) => (a.dir < b.dir ? -1 : a.dir > b.dir ? 1 : 0));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
interface WallTsconfig {
|
|
71
|
+
readonly extends: string;
|
|
72
|
+
readonly compilerOptions: {
|
|
73
|
+
readonly composite: true;
|
|
74
|
+
readonly typeRoots: null;
|
|
75
|
+
readonly types: string[];
|
|
76
|
+
};
|
|
77
|
+
readonly include: readonly ["**/*.ts"];
|
|
78
|
+
readonly exclude: readonly [];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function directoryWallTsconfig(wall: DirectoryWall): WallTsconfig {
|
|
82
|
+
const depth = wall.dir.split("/").length;
|
|
83
|
+
return {
|
|
84
|
+
extends: `${"../".repeat(depth)}tsconfig.json`,
|
|
85
|
+
compilerOptions: { composite: true, typeRoots: null, types: [wall.typesEntrypoint] },
|
|
86
|
+
include: ["**/*.ts"],
|
|
87
|
+
exclude: [],
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function writeJson(filePath: string, value: unknown): void {
|
|
92
|
+
mkdirSync(path.dirname(filePath), { recursive: true });
|
|
93
|
+
writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
interface RootTsconfig {
|
|
97
|
+
exclude?: string[];
|
|
98
|
+
files?: string[];
|
|
99
|
+
references?: Array<{ path: string }>;
|
|
100
|
+
[key: string]: unknown;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function sortedWallDirs(walls: readonly DirectoryWall[]): string[] {
|
|
104
|
+
return walls
|
|
105
|
+
.map((w) => w.dir)
|
|
106
|
+
.filter((dir) => dir !== ".")
|
|
107
|
+
.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function isInsideAnyDir(rel: string, dirs: readonly string[]): boolean {
|
|
111
|
+
return dirs.some((dir) => rel === dir || rel.startsWith(`${dir}/`));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function hasRootOwnedTranspilerSources(cwd: string, wallDirs: readonly string[]): boolean {
|
|
115
|
+
const seen = new Set<string>();
|
|
116
|
+
for (const pattern of readBuildConfig(cwd).include) {
|
|
117
|
+
for (const match of scanFilesSync(cwd, pattern)) {
|
|
118
|
+
const rel = match.split(path.sep).join("/");
|
|
119
|
+
if (seen.has(rel) || !isTranspilerSource(rel) || isSkipped(rel)) {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
seen.add(rel);
|
|
123
|
+
if (!isInsideAnyDir(rel, wallDirs)) {
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function wireWallReferences(cwd: string, walls: readonly DirectoryWall[]): void {
|
|
132
|
+
const rootPath = path.join(cwd, "tsconfig.json");
|
|
133
|
+
const current = JSON.parse(readFileSync(rootPath, "utf8")) as RootTsconfig;
|
|
134
|
+
const wallDirs = sortedWallDirs(walls);
|
|
135
|
+
const previousReferences = current.references ?? [];
|
|
136
|
+
const previousManaged = new Set(previousReferences.map((ref) => ref.path));
|
|
137
|
+
const nextExclude = [
|
|
138
|
+
...new Set([
|
|
139
|
+
...(current.exclude ?? []).filter((entry) => !previousManaged.has(entry)),
|
|
140
|
+
...wallDirs,
|
|
141
|
+
]),
|
|
142
|
+
];
|
|
143
|
+
const next: RootTsconfig = { ...current };
|
|
144
|
+
|
|
145
|
+
if (wallDirs.length > 0) {
|
|
146
|
+
next.references = wallDirs.map((dir) => ({ path: dir }));
|
|
147
|
+
} else {
|
|
148
|
+
delete next.references;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (nextExclude.length > 0) {
|
|
152
|
+
next.exclude = nextExclude;
|
|
153
|
+
} else {
|
|
154
|
+
delete next.exclude;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (wallDirs.length > 0 && !hasRootOwnedTranspilerSources(cwd, wallDirs)) {
|
|
158
|
+
next.files = [];
|
|
159
|
+
} else if (previousReferences.length > 0 && JSON.stringify(next.files) === JSON.stringify([])) {
|
|
160
|
+
delete next.files;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (JSON.stringify(next) !== JSON.stringify(current)) {
|
|
164
|
+
writeJson(rootPath, next);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export function writeDirectoryWallTsconfigs(cwd: string, walls: DirectoryWall[]): string[] {
|
|
169
|
+
const written: string[] = [];
|
|
170
|
+
for (const w of walls) {
|
|
171
|
+
if (w.dir === ".") {
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
const rel = `${w.dir}/tsconfig.json`;
|
|
175
|
+
const target = path.join(cwd, w.dir, "tsconfig.json");
|
|
176
|
+
const desired = directoryWallTsconfig(w);
|
|
177
|
+
if (existsSync(target)) {
|
|
178
|
+
const current = JSON.parse(readFileSync(target, "utf8")) as {
|
|
179
|
+
extends?: string;
|
|
180
|
+
compilerOptions?: Record<string, unknown>;
|
|
181
|
+
[key: string]: unknown;
|
|
182
|
+
};
|
|
183
|
+
const options = current.compilerOptions ?? {};
|
|
184
|
+
// Skip the write when already narrowed so a consumer's formatting is not
|
|
185
|
+
// churned to JSON.stringify's layout on every build.
|
|
186
|
+
const alreadyNarrowed =
|
|
187
|
+
current.extends === desired.extends &&
|
|
188
|
+
options.composite === desired.compilerOptions.composite &&
|
|
189
|
+
options.typeRoots === desired.compilerOptions.typeRoots &&
|
|
190
|
+
JSON.stringify(options.types) === JSON.stringify(desired.compilerOptions.types) &&
|
|
191
|
+
JSON.stringify(current.include) === JSON.stringify(desired.include) &&
|
|
192
|
+
JSON.stringify(current.exclude) === JSON.stringify(desired.exclude);
|
|
193
|
+
if (!alreadyNarrowed) {
|
|
194
|
+
writeJson(target, {
|
|
195
|
+
...current,
|
|
196
|
+
extends: desired.extends,
|
|
197
|
+
compilerOptions: {
|
|
198
|
+
...options,
|
|
199
|
+
composite: desired.compilerOptions.composite,
|
|
200
|
+
typeRoots: desired.compilerOptions.typeRoots,
|
|
201
|
+
types: desired.compilerOptions.types,
|
|
202
|
+
},
|
|
203
|
+
include: desired.include,
|
|
204
|
+
exclude: desired.exclude,
|
|
205
|
+
});
|
|
206
|
+
written.push(rel);
|
|
207
|
+
}
|
|
208
|
+
} else {
|
|
209
|
+
writeJson(target, desired);
|
|
210
|
+
written.push(rel);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return written.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
|
|
214
|
+
}
|