@akanjs/devkit 2.1.1 → 2.1.2-rc.1
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/akanConfig/akanConfig.test.ts +167 -32
- package/akanConfig/akanConfig.ts +130 -31
- package/artifact/implicitRootLayout.test.ts +2 -0
- package/artifact/implicitRootLayout.ts +2 -2
- package/cloud/cloudApi.ts +26 -48
- package/executors.test.ts +47 -0
- package/executors.ts +166 -577
- package/package.json +2 -2
package/executors.ts
CHANGED
|
@@ -8,12 +8,7 @@ import {
|
|
|
8
8
|
spawn,
|
|
9
9
|
} from "node:child_process";
|
|
10
10
|
import { readFileSync } from "node:fs";
|
|
11
|
-
import {
|
|
12
|
-
copyFile,
|
|
13
|
-
mkdir,
|
|
14
|
-
readdir as readDirEntries,
|
|
15
|
-
stat,
|
|
16
|
-
} from "node:fs/promises";
|
|
11
|
+
import { copyFile, mkdir, readdir as readDirEntries, stat } from "node:fs/promises";
|
|
17
12
|
import path from "node:path";
|
|
18
13
|
import {
|
|
19
14
|
capitalize,
|
|
@@ -26,12 +21,7 @@ import {
|
|
|
26
21
|
import { $ } from "bun";
|
|
27
22
|
import chalk from "chalk";
|
|
28
23
|
import ts from "typescript";
|
|
29
|
-
import {
|
|
30
|
-
AkanAppConfig,
|
|
31
|
-
AkanLibConfig,
|
|
32
|
-
decreaseBuildNum,
|
|
33
|
-
increaseBuildNum,
|
|
34
|
-
} from "./akanConfig";
|
|
24
|
+
import { AkanAppConfig, AkanLibConfig, decreaseBuildNum, increaseBuildNum } from "./akanConfig";
|
|
35
25
|
import { FileSys } from "./fileSys";
|
|
36
26
|
import { getDirname } from "./getDirname";
|
|
37
27
|
import { Linter } from "./linter";
|
|
@@ -74,8 +64,7 @@ const staticTemplateFileExtensions = new Set([
|
|
|
74
64
|
".xml",
|
|
75
65
|
]);
|
|
76
66
|
|
|
77
|
-
const formatCommandArg = (value: string) =>
|
|
78
|
-
/^[\w@%+=:,./-]+$/.test(value) ? value : JSON.stringify(value);
|
|
67
|
+
const formatCommandArg = (value: string) => (/^[\w@%+=:,./-]+$/.test(value) ? value : JSON.stringify(value));
|
|
79
68
|
|
|
80
69
|
const formatCommandForDisplay = (command: string, args: string[] = []) =>
|
|
81
70
|
[command, ...args].map(formatCommandArg).join(" ");
|
|
@@ -111,21 +100,11 @@ export class CommandExecutionError extends Error {
|
|
|
111
100
|
cause,
|
|
112
101
|
}: CommandExecutionErrorOptions) {
|
|
113
102
|
const displayCommand = formatCommandForDisplay(command, args);
|
|
114
|
-
const status = signal
|
|
115
|
-
? `signal: ${signal}`
|
|
116
|
-
: `exit code: ${code ?? "unknown"}`;
|
|
103
|
+
const status = signal ? `signal: ${signal}` : `exit code: ${code ?? "unknown"}`;
|
|
117
104
|
const output = (stderr || stdout).trim();
|
|
118
|
-
super(
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
`cwd: ${cwd}`,
|
|
122
|
-
status,
|
|
123
|
-
output ? `\n${output}` : "",
|
|
124
|
-
].join("\n"),
|
|
125
|
-
{
|
|
126
|
-
cause,
|
|
127
|
-
},
|
|
128
|
-
);
|
|
105
|
+
super([`Command failed: ${displayCommand}`, `cwd: ${cwd}`, status, output ? `\n${output}` : ""].join("\n"), {
|
|
106
|
+
cause,
|
|
107
|
+
});
|
|
129
108
|
this.name = "CommandExecutionError";
|
|
130
109
|
this.command = command;
|
|
131
110
|
this.args = args;
|
|
@@ -159,17 +138,12 @@ const parseEnvFile = (envPath: string): Record<string, string> => {
|
|
|
159
138
|
for (const line of content.split(/\r?\n/)) {
|
|
160
139
|
const trimmed = line.trim();
|
|
161
140
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
162
|
-
const normalized = trimmed.startsWith("export ")
|
|
163
|
-
? trimmed.slice("export ".length).trim()
|
|
164
|
-
: trimmed;
|
|
141
|
+
const normalized = trimmed.startsWith("export ") ? trimmed.slice("export ".length).trim() : trimmed;
|
|
165
142
|
const separatorIndex = normalized.indexOf("=");
|
|
166
143
|
if (separatorIndex <= 0) continue;
|
|
167
144
|
const key = normalized.slice(0, separatorIndex).trim();
|
|
168
145
|
let value = normalized.slice(separatorIndex + 1).trim();
|
|
169
|
-
if (
|
|
170
|
-
(value.startsWith('"') && value.endsWith('"')) ||
|
|
171
|
-
(value.startsWith("'") && value.endsWith("'"))
|
|
172
|
-
) {
|
|
146
|
+
if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
|
|
173
147
|
value = value.slice(1, -1);
|
|
174
148
|
}
|
|
175
149
|
env[key] = value;
|
|
@@ -177,13 +151,7 @@ const parseEnvFile = (envPath: string): Record<string, string> => {
|
|
|
177
151
|
return env;
|
|
178
152
|
};
|
|
179
153
|
|
|
180
|
-
const PAGE_ROUTE_EXPORTS = new Set([
|
|
181
|
-
"default",
|
|
182
|
-
"pageConfig",
|
|
183
|
-
"head",
|
|
184
|
-
"generateHead",
|
|
185
|
-
"Loading",
|
|
186
|
-
]);
|
|
154
|
+
const PAGE_ROUTE_EXPORTS = new Set(["default", "pageConfig", "head", "generateHead", "Loading"]);
|
|
187
155
|
const ROOT_LAYOUT_EXPORTS = new Set([
|
|
188
156
|
"default",
|
|
189
157
|
"head",
|
|
@@ -195,13 +163,10 @@ const ROOT_LAYOUT_EXPORTS = new Set([
|
|
|
195
163
|
"layoutStyle",
|
|
196
164
|
"gaTrackingId",
|
|
197
165
|
"Loading",
|
|
166
|
+
"NotFound",
|
|
167
|
+
"Error",
|
|
198
168
|
]);
|
|
199
|
-
const LAYOUT_ROUTE_EXPORTS = new Set([
|
|
200
|
-
"default",
|
|
201
|
-
"head",
|
|
202
|
-
"generateHead",
|
|
203
|
-
"Loading",
|
|
204
|
-
]);
|
|
169
|
+
const LAYOUT_ROUTE_EXPORTS = new Set(["default", "head", "generateHead", "Loading", "NotFound", "Error"]);
|
|
205
170
|
|
|
206
171
|
function validateRouteSourceExports(
|
|
207
172
|
source: string,
|
|
@@ -209,42 +174,23 @@ function validateRouteSourceExports(
|
|
|
209
174
|
kind: "page" | "layout",
|
|
210
175
|
options: { rootLayout?: boolean } = {},
|
|
211
176
|
) {
|
|
212
|
-
const sourceFile = ts.createSourceFile(
|
|
213
|
-
filePath,
|
|
214
|
-
source,
|
|
215
|
-
ts.ScriptTarget.Latest,
|
|
216
|
-
true,
|
|
217
|
-
ts.ScriptKind.TSX,
|
|
218
|
-
);
|
|
177
|
+
const sourceFile = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
|
|
219
178
|
const allowed =
|
|
220
|
-
kind === "page"
|
|
221
|
-
? PAGE_ROUTE_EXPORTS
|
|
222
|
-
: options.rootLayout
|
|
223
|
-
? ROOT_LAYOUT_EXPORTS
|
|
224
|
-
: LAYOUT_ROUTE_EXPORTS;
|
|
179
|
+
kind === "page" ? PAGE_ROUTE_EXPORTS : options.rootLayout ? ROOT_LAYOUT_EXPORTS : LAYOUT_ROUTE_EXPORTS;
|
|
225
180
|
const exported = new Set<string>();
|
|
226
181
|
const assertExport = (name: string) => {
|
|
227
182
|
if (!allowed.has(name)) {
|
|
228
|
-
throw new Error(
|
|
229
|
-
`[route-convention] unsupported export "${name}" in ${filePath}`,
|
|
230
|
-
);
|
|
183
|
+
throw new Error(`[route-convention] unsupported export "${name}" in ${filePath}`);
|
|
231
184
|
}
|
|
232
185
|
exported.add(name);
|
|
233
186
|
};
|
|
234
187
|
|
|
235
188
|
for (const statement of sourceFile.statements) {
|
|
236
|
-
if (
|
|
237
|
-
ts.isInterfaceDeclaration(statement) ||
|
|
238
|
-
ts.isTypeAliasDeclaration(statement)
|
|
239
|
-
)
|
|
240
|
-
continue;
|
|
189
|
+
if (ts.isInterfaceDeclaration(statement) || ts.isTypeAliasDeclaration(statement)) continue;
|
|
241
190
|
if (ts.isExportDeclaration(statement)) {
|
|
242
191
|
if (statement.isTypeOnly) continue;
|
|
243
192
|
const clause = statement.exportClause;
|
|
244
|
-
if (!clause)
|
|
245
|
-
throw new Error(
|
|
246
|
-
`[route-convention] export * is not allowed in route modules: ${filePath}`,
|
|
247
|
-
);
|
|
193
|
+
if (!clause) throw new Error(`[route-convention] export * is not allowed in route modules: ${filePath}`);
|
|
248
194
|
if (ts.isNamedExports(clause)) {
|
|
249
195
|
for (const element of clause.elements) {
|
|
250
196
|
if (element.isTypeOnly) continue;
|
|
@@ -253,22 +199,17 @@ function validateRouteSourceExports(
|
|
|
253
199
|
}
|
|
254
200
|
continue;
|
|
255
201
|
}
|
|
256
|
-
const modifiers = ts.canHaveModifiers(statement)
|
|
257
|
-
|
|
258
|
-
: undefined;
|
|
259
|
-
const isExported =
|
|
260
|
-
modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) ?? false;
|
|
202
|
+
const modifiers = ts.canHaveModifiers(statement) ? ts.getModifiers(statement) : undefined;
|
|
203
|
+
const isExported = modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) ?? false;
|
|
261
204
|
if (!isExported) continue;
|
|
262
|
-
const isDefault =
|
|
263
|
-
modifiers?.some((m) => m.kind === ts.SyntaxKind.DefaultKeyword) ?? false;
|
|
205
|
+
const isDefault = modifiers?.some((m) => m.kind === ts.SyntaxKind.DefaultKeyword) ?? false;
|
|
264
206
|
if (isDefault) {
|
|
265
207
|
assertExport("default");
|
|
266
208
|
continue;
|
|
267
209
|
}
|
|
268
210
|
if (ts.isVariableStatement(statement)) {
|
|
269
211
|
for (const declaration of statement.declarationList.declarations) {
|
|
270
|
-
if (ts.isIdentifier(declaration.name))
|
|
271
|
-
assertExport(declaration.name.text);
|
|
212
|
+
if (ts.isIdentifier(declaration.name)) assertExport(declaration.name.text);
|
|
272
213
|
}
|
|
273
214
|
continue;
|
|
274
215
|
}
|
|
@@ -278,9 +219,7 @@ function validateRouteSourceExports(
|
|
|
278
219
|
}
|
|
279
220
|
}
|
|
280
221
|
if (exported.has("head") && exported.has("generateHead")) {
|
|
281
|
-
throw new Error(
|
|
282
|
-
`[route-convention] head and generateHead cannot both be exported in ${filePath}`,
|
|
283
|
-
);
|
|
222
|
+
throw new Error(`[route-convention] head and generateHead cannot both be exported in ${filePath}`);
|
|
284
223
|
}
|
|
285
224
|
}
|
|
286
225
|
|
|
@@ -353,11 +292,7 @@ export class Executor {
|
|
|
353
292
|
});
|
|
354
293
|
}
|
|
355
294
|
|
|
356
|
-
spawn(
|
|
357
|
-
command: string,
|
|
358
|
-
args: string[] = [],
|
|
359
|
-
options: SpawnOptions = {},
|
|
360
|
-
): Promise<string> {
|
|
295
|
+
spawn(command: string, args: string[] = [], options: SpawnOptions = {}): Promise<string> {
|
|
361
296
|
const cwd = options.cwd?.toString() ?? this.cwdPath;
|
|
362
297
|
const proc = spawn(command, args, {
|
|
363
298
|
cwd: this.cwdPath,
|
|
@@ -409,11 +344,7 @@ export class Executor {
|
|
|
409
344
|
});
|
|
410
345
|
});
|
|
411
346
|
}
|
|
412
|
-
spawnSync(
|
|
413
|
-
command: string,
|
|
414
|
-
args: string[] = [],
|
|
415
|
-
options: SpawnOptions = {},
|
|
416
|
-
): ChildProcess {
|
|
347
|
+
spawnSync(command: string, args: string[] = [], options: SpawnOptions = {}): ChildProcess {
|
|
417
348
|
const proc = spawn(command, args, {
|
|
418
349
|
cwd: this.cwdPath,
|
|
419
350
|
// stdio: "inherit",
|
|
@@ -494,8 +425,7 @@ export class Executor {
|
|
|
494
425
|
}
|
|
495
426
|
async mkdir(dirPath: string) {
|
|
496
427
|
const writePath = this.getPath(dirPath);
|
|
497
|
-
if (!(await FileSys.dirExists(writePath)))
|
|
498
|
-
await mkdir(writePath, { recursive: true });
|
|
428
|
+
if (!(await FileSys.dirExists(writePath))) await mkdir(writePath, { recursive: true });
|
|
499
429
|
this.logger.verbose(`Make directory ${writePath}`);
|
|
500
430
|
return this;
|
|
501
431
|
}
|
|
@@ -508,27 +438,16 @@ export class Executor {
|
|
|
508
438
|
return [];
|
|
509
439
|
}
|
|
510
440
|
}
|
|
511
|
-
async getAllFiles(
|
|
512
|
-
pattern = "**/*",
|
|
513
|
-
{ cwd }: { cwd?: string } = {},
|
|
514
|
-
): Promise<string[]> {
|
|
441
|
+
async getAllFiles(pattern = "**/*", { cwd }: { cwd?: string } = {}): Promise<string[]> {
|
|
515
442
|
const glob = new Bun.Glob(pattern);
|
|
516
|
-
return Array.from(
|
|
517
|
-
glob.scanSync({ cwd: cwd ?? this.cwdPath, onlyFiles: true }),
|
|
518
|
-
);
|
|
443
|
+
return Array.from(glob.scanSync({ cwd: cwd ?? this.cwdPath, onlyFiles: true }));
|
|
519
444
|
}
|
|
520
|
-
async getFilesAndDirs(
|
|
521
|
-
dirPath: string,
|
|
522
|
-
): Promise<{ files: string[]; dirs: string[] }> {
|
|
445
|
+
async getFilesAndDirs(dirPath: string): Promise<{ files: string[]; dirs: string[] }> {
|
|
523
446
|
const fullDirPath = this.getPath(dirPath);
|
|
524
447
|
const fileGlob = new Bun.Glob("*");
|
|
525
|
-
const files = Array.from(
|
|
526
|
-
fileGlob.scanSync({ cwd: fullDirPath, onlyFiles: true }),
|
|
527
|
-
);
|
|
448
|
+
const files = Array.from(fileGlob.scanSync({ cwd: fullDirPath, onlyFiles: true }));
|
|
528
449
|
const dirGlob = new Bun.Glob("*");
|
|
529
|
-
const allEntries = Array.from(
|
|
530
|
-
dirGlob.scanSync({ cwd: fullDirPath, onlyFiles: false }),
|
|
531
|
-
);
|
|
450
|
+
const allEntries = Array.from(dirGlob.scanSync({ cwd: fullDirPath, onlyFiles: false }));
|
|
532
451
|
const dirs = allEntries.filter((entry) => !files.includes(entry));
|
|
533
452
|
return { files, dirs };
|
|
534
453
|
}
|
|
@@ -556,8 +475,7 @@ export class Executor {
|
|
|
556
475
|
const writePath = this.getPath(filePath);
|
|
557
476
|
const dir = path.dirname(writePath);
|
|
558
477
|
if (!(await FileSys.dirExists(dir))) await mkdir(dir, { recursive: true });
|
|
559
|
-
let contentStr =
|
|
560
|
-
typeof content === "string" ? content : JSON.stringify(content, null, 2);
|
|
478
|
+
let contentStr = typeof content === "string" ? content : JSON.stringify(content, null, 2);
|
|
561
479
|
|
|
562
480
|
if (await FileSys.fileExists(writePath)) {
|
|
563
481
|
const currentContent = await FileSys.readText(writePath);
|
|
@@ -566,8 +484,7 @@ export class Executor {
|
|
|
566
484
|
contentStr = currentContent;
|
|
567
485
|
} else {
|
|
568
486
|
await FileSys.writeText(writePath, contentStr);
|
|
569
|
-
if (Logger.isVerbose())
|
|
570
|
-
this.logger.rawLog(chalk.yellow(`File Update: ${filePath}`));
|
|
487
|
+
if (Logger.isVerbose()) this.logger.rawLog(chalk.yellow(`File Update: ${filePath}`));
|
|
571
488
|
}
|
|
572
489
|
} else {
|
|
573
490
|
await FileSys.writeText(writePath, contentStr);
|
|
@@ -579,9 +496,7 @@ export class Executor {
|
|
|
579
496
|
await this.writeFile(filePath, content);
|
|
580
497
|
}
|
|
581
498
|
async getLocalFile(targetPath: string) {
|
|
582
|
-
const filePath = path.isAbsolute(targetPath)
|
|
583
|
-
? targetPath
|
|
584
|
-
: targetPath.replace(this.cwdPath, "");
|
|
499
|
+
const filePath = path.isAbsolute(targetPath) ? targetPath : targetPath.replace(this.cwdPath, "");
|
|
585
500
|
const content = await this.readFile(filePath);
|
|
586
501
|
return { filePath, content };
|
|
587
502
|
}
|
|
@@ -598,8 +513,7 @@ export class Executor {
|
|
|
598
513
|
const dest = this.getPath(destPath);
|
|
599
514
|
if (!(await FileSys.exists(src))) return;
|
|
600
515
|
const isDirectory = (await stat(src)).isDirectory();
|
|
601
|
-
if (!(await FileSys.exists(dest)) && isDirectory)
|
|
602
|
-
await mkdir(dest, { recursive: true });
|
|
516
|
+
if (!(await FileSys.exists(dest)) && isDirectory) await mkdir(dest, { recursive: true });
|
|
603
517
|
await $`cp -r ${src}${isDirectory ? "/." : ""} ${dest}`;
|
|
604
518
|
}
|
|
605
519
|
log(msg: string) {
|
|
@@ -614,22 +528,12 @@ export class Executor {
|
|
|
614
528
|
this.logger.debug(msg);
|
|
615
529
|
return this;
|
|
616
530
|
}
|
|
617
|
-
spinning(
|
|
618
|
-
msg: string,
|
|
619
|
-
{
|
|
620
|
-
prefix = `${this.emoji}${this.name}`,
|
|
621
|
-
indent = 0,
|
|
622
|
-
enableSpin = !Executor.verbose,
|
|
623
|
-
} = {},
|
|
624
|
-
) {
|
|
531
|
+
spinning(msg: string, { prefix = `${this.emoji}${this.name}`, indent = 0, enableSpin = !Executor.verbose } = {}) {
|
|
625
532
|
return new Spinner(msg, { prefix, indent, enableSpin }).start();
|
|
626
533
|
}
|
|
627
534
|
|
|
628
535
|
#tsconfig: TsConfigJson | null = null;
|
|
629
|
-
async getTsConfig(
|
|
630
|
-
pathname = "tsconfig.json",
|
|
631
|
-
{ refresh }: { refresh?: boolean } = {},
|
|
632
|
-
): Promise<TsConfigJson> {
|
|
536
|
+
async getTsConfig(pathname = "tsconfig.json", { refresh }: { refresh?: boolean } = {}): Promise<TsConfigJson> {
|
|
633
537
|
if (this.#tsconfig && !refresh) return this.#tsconfig;
|
|
634
538
|
const tsconfig = (await this.readJson(pathname)) as TsConfigJson;
|
|
635
539
|
if (tsconfig.extends) {
|
|
@@ -654,11 +558,7 @@ export class Executor {
|
|
|
654
558
|
}
|
|
655
559
|
|
|
656
560
|
#packageJson: PackageJson | null = null;
|
|
657
|
-
async getPackageJson({
|
|
658
|
-
refresh,
|
|
659
|
-
}: {
|
|
660
|
-
refresh?: boolean;
|
|
661
|
-
} = {}): Promise<PackageJson> {
|
|
561
|
+
async getPackageJson({ refresh }: { refresh?: boolean } = {}): Promise<PackageJson> {
|
|
662
562
|
if (this.#packageJson && !refresh) return this.#packageJson;
|
|
663
563
|
const packageJson = (await this.readJson("package.json")) as PackageJson;
|
|
664
564
|
this.#packageJson = packageJson;
|
|
@@ -705,55 +605,39 @@ export class Executor {
|
|
|
705
605
|
};
|
|
706
606
|
const result = await getContent.default(scanInfo ?? null, dict, options);
|
|
707
607
|
if (result === null) return null;
|
|
708
|
-
const filename =
|
|
709
|
-
typeof result === "object"
|
|
710
|
-
? result.filename
|
|
711
|
-
: path.basename(targetPath).replace(".js", ".ts");
|
|
608
|
+
const filename = typeof result === "object" ? result.filename : path.basename(targetPath).replace(".js", ".ts");
|
|
712
609
|
const content = typeof result === "object" ? result.content : result;
|
|
713
610
|
const dirname = path.dirname(targetPath);
|
|
714
611
|
const convertedTargetPath = Object.entries(dict).reduce(
|
|
715
|
-
(path, [key, value]) =>
|
|
716
|
-
path.replace(new RegExp(`__${key}__`, "g"), value),
|
|
612
|
+
(path, [key, value]) => path.replace(new RegExp(`__${key}__`, "g"), value),
|
|
717
613
|
`${dirname}/${filename}`,
|
|
718
614
|
);
|
|
719
|
-
this.logger.verbose(
|
|
720
|
-
`Apply template ${templatePath} to ${convertedTargetPath}`,
|
|
721
|
-
);
|
|
615
|
+
this.logger.verbose(`Apply template ${templatePath} to ${convertedTargetPath}`);
|
|
722
616
|
return this.writeFile(convertedTargetPath, content, { overwrite });
|
|
723
617
|
} else if (targetPath.endsWith(".template")) {
|
|
724
618
|
const content = await FileSys.readText(templatePath);
|
|
725
619
|
const convertedTargetPath = Object.entries(dict).reduce(
|
|
726
|
-
(path, [key, value]) =>
|
|
727
|
-
path.replace(new RegExp(`__${key}__`, "g"), value),
|
|
620
|
+
(path, [key, value]) => path.replace(new RegExp(`__${key}__`, "g"), value),
|
|
728
621
|
targetPath.slice(0, -9),
|
|
729
622
|
);
|
|
730
623
|
const convertedContent = Object.entries(dict).reduce(
|
|
731
|
-
(data, [key, value]) =>
|
|
732
|
-
data.replace(new RegExp(`<%= ${key} %>`, "g"), value),
|
|
624
|
+
(data, [key, value]) => data.replace(new RegExp(`<%= ${key} %>`, "g"), value),
|
|
733
625
|
content,
|
|
734
626
|
);
|
|
735
|
-
this.logger.verbose(
|
|
736
|
-
`Apply template ${templatePath} to ${convertedTargetPath}`,
|
|
737
|
-
);
|
|
627
|
+
this.logger.verbose(`Apply template ${templatePath} to ${convertedTargetPath}`);
|
|
738
628
|
return this.writeFile(convertedTargetPath, convertedContent, {
|
|
739
629
|
overwrite,
|
|
740
630
|
});
|
|
741
|
-
} else if (
|
|
742
|
-
staticTemplateFileExtensions.has(path.extname(targetPath).toLowerCase())
|
|
743
|
-
) {
|
|
631
|
+
} else if (staticTemplateFileExtensions.has(path.extname(targetPath).toLowerCase())) {
|
|
744
632
|
const convertedTargetPath = Object.entries(dict).reduce(
|
|
745
|
-
(path, [key, value]) =>
|
|
746
|
-
path.replace(new RegExp(`__${key}__`, "g"), value),
|
|
633
|
+
(path, [key, value]) => path.replace(new RegExp(`__${key}__`, "g"), value),
|
|
747
634
|
targetPath,
|
|
748
635
|
);
|
|
749
636
|
const writePath = this.getPath(convertedTargetPath);
|
|
750
637
|
const dirname = path.dirname(writePath);
|
|
751
|
-
if (!(await FileSys.dirExists(dirname)))
|
|
752
|
-
await mkdir(dirname, { recursive: true });
|
|
638
|
+
if (!(await FileSys.dirExists(dirname))) await mkdir(dirname, { recursive: true });
|
|
753
639
|
await copyFile(templatePath, writePath);
|
|
754
|
-
this.logger.verbose(
|
|
755
|
-
`Apply template ${templatePath} to ${convertedTargetPath}`,
|
|
756
|
-
);
|
|
640
|
+
this.logger.verbose(`Apply template ${templatePath} to ${convertedTargetPath}`);
|
|
757
641
|
return { filePath: writePath, content: "" };
|
|
758
642
|
} else return null;
|
|
759
643
|
}
|
|
@@ -841,10 +725,7 @@ export class Executor {
|
|
|
841
725
|
const dict = {
|
|
842
726
|
...(options.dict ?? {}),
|
|
843
727
|
...Object.fromEntries(
|
|
844
|
-
Object.entries(options.dict ?? {}).map(([key, value]) => [
|
|
845
|
-
capitalize(key),
|
|
846
|
-
capitalize(value),
|
|
847
|
-
]),
|
|
728
|
+
Object.entries(options.dict ?? {}).map(([key, value]) => [capitalize(key), capitalize(value)]),
|
|
848
729
|
),
|
|
849
730
|
};
|
|
850
731
|
return this._applyTemplate({ ...options, dict });
|
|
@@ -856,8 +737,7 @@ export class Executor {
|
|
|
856
737
|
typeCheck(filePath: string) {
|
|
857
738
|
const path = this.getPath(filePath);
|
|
858
739
|
const typeChecker = this.getTypeChecker();
|
|
859
|
-
const { fileDiagnostics, fileErrors, fileWarnings } =
|
|
860
|
-
typeChecker.check(path);
|
|
740
|
+
const { fileDiagnostics, fileErrors, fileWarnings } = typeChecker.check(path);
|
|
861
741
|
const message = typeChecker.formatDiagnostics(fileDiagnostics);
|
|
862
742
|
return { fileDiagnostics, fileErrors, fileWarnings, message };
|
|
863
743
|
}
|
|
@@ -879,11 +759,7 @@ export class Executor {
|
|
|
879
759
|
new Response(proc.stderr).text(),
|
|
880
760
|
proc.exited,
|
|
881
761
|
]);
|
|
882
|
-
if (exitCode !== 0)
|
|
883
|
-
throw new Error(
|
|
884
|
-
(stderr || stdout).trim() ||
|
|
885
|
-
`Typecheck failed with exit code ${exitCode}`,
|
|
886
|
-
);
|
|
762
|
+
if (exitCode !== 0) throw new Error((stderr || stdout).trim() || `Typecheck failed with exit code ${exitCode}`);
|
|
887
763
|
|
|
888
764
|
const result = JSON.parse(stdout) as {
|
|
889
765
|
fileDiagnosticsCount: number;
|
|
@@ -901,23 +777,14 @@ export class Executor {
|
|
|
901
777
|
async #resolveTypecheckWorkerEntry() {
|
|
902
778
|
const dirname = getDirname(import.meta.url);
|
|
903
779
|
const candidates = [
|
|
904
|
-
path.join(
|
|
905
|
-
|
|
906
|
-
"pkgs/@akanjs/devkit/typecheck/typecheck.proc.ts",
|
|
907
|
-
),
|
|
908
|
-
path.join(
|
|
909
|
-
process.cwd(),
|
|
910
|
-
"node_modules/@akanjs/devkit/typecheck/typecheck.proc.ts",
|
|
911
|
-
),
|
|
780
|
+
path.join(process.cwd(), "pkgs/@akanjs/devkit/typecheck/typecheck.proc.ts"),
|
|
781
|
+
path.join(process.cwd(), "node_modules/@akanjs/devkit/typecheck/typecheck.proc.ts"),
|
|
912
782
|
path.join(dirname, "typecheck/typecheck.proc.ts"),
|
|
913
783
|
path.join(dirname, "typecheck.proc.js"),
|
|
914
784
|
path.join(dirname, "typecheck.proc.ts"),
|
|
915
785
|
];
|
|
916
|
-
for (const candidate of candidates)
|
|
917
|
-
|
|
918
|
-
throw new Error(
|
|
919
|
-
`[devkit] typecheck worker entry not found; looked in: ${candidates.join(", ")}`,
|
|
920
|
-
);
|
|
786
|
+
for (const candidate of candidates) if (await Bun.file(candidate).exists()) return candidate;
|
|
787
|
+
throw new Error(`[devkit] typecheck worker entry not found; looked in: ${candidates.join(", ")}`);
|
|
921
788
|
}
|
|
922
789
|
getLinter() {
|
|
923
790
|
this.linter ??= new Linter(this.cwdPath);
|
|
@@ -965,16 +832,11 @@ export class WorkspaceExecutor extends Executor {
|
|
|
965
832
|
workspaceRoot?: string;
|
|
966
833
|
repoName?: string;
|
|
967
834
|
} = {}) {
|
|
968
|
-
return (
|
|
969
|
-
WorkspaceExecutor.#execs.get(repoName) ??
|
|
970
|
-
new WorkspaceExecutor({ workspaceRoot, repoName })
|
|
971
|
-
);
|
|
835
|
+
return WorkspaceExecutor.#execs.get(repoName) ?? new WorkspaceExecutor({ workspaceRoot, repoName });
|
|
972
836
|
}
|
|
973
837
|
static getBaseDevEnv(envPath?: string) {
|
|
974
838
|
// Bun auto-loads .env, so we use process.env directly
|
|
975
|
-
const sourceEnv = envPath
|
|
976
|
-
? { ...process.env, ...parseEnvFile(envPath) }
|
|
977
|
-
: process.env;
|
|
839
|
+
const sourceEnv = envPath ? { ...process.env, ...parseEnvFile(envPath) } : process.env;
|
|
978
840
|
|
|
979
841
|
const appName = sourceEnv.AKAN_PUBLIC_APP_NAME;
|
|
980
842
|
const workspaceRoot = sourceEnv.AKAN_WORKSPACE_ROOT;
|
|
@@ -1012,8 +874,7 @@ export class WorkspaceExecutor extends Executor {
|
|
|
1012
874
|
allowEmpty?: AllowEmpty;
|
|
1013
875
|
} = {}): AllowEmpty extends true ? string | undefined : string {
|
|
1014
876
|
const { workspaceId } = WorkspaceExecutor.getBaseDevEnv();
|
|
1015
|
-
if (!workspaceId && !allowEmpty)
|
|
1016
|
-
throw new Error("Workspace ID is not found");
|
|
877
|
+
if (!workspaceId && !allowEmpty) throw new Error("Workspace ID is not found");
|
|
1017
878
|
return workspaceId as AllowEmpty extends true ? string | undefined : string;
|
|
1018
879
|
}
|
|
1019
880
|
async scan(): Promise<WorkspaceInfo> {
|
|
@@ -1021,38 +882,22 @@ export class WorkspaceExecutor extends Executor {
|
|
|
1021
882
|
}
|
|
1022
883
|
async getApps() {
|
|
1023
884
|
if (!(await FileSys.dirExists(`${this.workspaceRoot}/apps`))) return [];
|
|
1024
|
-
return await this.#getDirHasFile(
|
|
1025
|
-
`${this.workspaceRoot}/apps`,
|
|
1026
|
-
"akan.config.ts",
|
|
1027
|
-
);
|
|
885
|
+
return await this.#getDirHasFile(`${this.workspaceRoot}/apps`, "akan.config.ts");
|
|
1028
886
|
}
|
|
1029
887
|
async getLibs() {
|
|
1030
888
|
if (!(await FileSys.dirExists(`${this.workspaceRoot}/libs`))) return [];
|
|
1031
|
-
return await this.#getDirHasFile(
|
|
1032
|
-
`${this.workspaceRoot}/libs`,
|
|
1033
|
-
"akan.config.ts",
|
|
1034
|
-
);
|
|
889
|
+
return await this.#getDirHasFile(`${this.workspaceRoot}/libs`, "akan.config.ts");
|
|
1035
890
|
}
|
|
1036
891
|
async getSyss() {
|
|
1037
|
-
const [appNames, libNames] = await Promise.all([
|
|
1038
|
-
this.getApps(),
|
|
1039
|
-
this.getLibs(),
|
|
1040
|
-
]);
|
|
892
|
+
const [appNames, libNames] = await Promise.all([this.getApps(), this.getLibs()]);
|
|
1041
893
|
return [appNames, libNames] as [string[], string[]];
|
|
1042
894
|
}
|
|
1043
895
|
async getPkgs() {
|
|
1044
896
|
if (!(await FileSys.dirExists(`${this.workspaceRoot}/pkgs`))) return [];
|
|
1045
|
-
return await this.#getDirHasFile(
|
|
1046
|
-
`${this.workspaceRoot}/pkgs`,
|
|
1047
|
-
"package.json",
|
|
1048
|
-
);
|
|
897
|
+
return await this.#getDirHasFile(`${this.workspaceRoot}/pkgs`, "package.json");
|
|
1049
898
|
}
|
|
1050
899
|
async getExecs() {
|
|
1051
|
-
const [appNames, libNames, pkgNames] = await Promise.all([
|
|
1052
|
-
this.getApps(),
|
|
1053
|
-
this.getLibs(),
|
|
1054
|
-
this.getPkgs(),
|
|
1055
|
-
]);
|
|
900
|
+
const [appNames, libNames, pkgNames] = await Promise.all([this.getApps(), this.getLibs(), this.getPkgs()]);
|
|
1056
901
|
return [appNames, libNames, pkgNames] as [string[], string[], string[]];
|
|
1057
902
|
}
|
|
1058
903
|
async setPkgTsPaths(name: string) {
|
|
@@ -1061,11 +906,7 @@ export class WorkspaceExecutor extends Executor {
|
|
|
1061
906
|
rootTsConfig.compilerOptions.paths[name] = [`./pkgs/${name}/index.ts`];
|
|
1062
907
|
rootTsConfig.compilerOptions.paths[`${name}/*`] = [`./pkgs/${name}/*`];
|
|
1063
908
|
if (rootTsConfig.references) {
|
|
1064
|
-
if (
|
|
1065
|
-
!rootTsConfig.references.some(
|
|
1066
|
-
(ref) => ref.path === `./pkgs/${name}/tsconfig.json`,
|
|
1067
|
-
)
|
|
1068
|
-
)
|
|
909
|
+
if (!rootTsConfig.references.some((ref) => ref.path === `./pkgs/${name}/tsconfig.json`))
|
|
1069
910
|
rootTsConfig.references.push({ path: `./pkgs/${name}/tsconfig.json` });
|
|
1070
911
|
}
|
|
1071
912
|
await this.writeJson("tsconfig.json", rootTsConfig);
|
|
@@ -1073,14 +914,11 @@ export class WorkspaceExecutor extends Executor {
|
|
|
1073
914
|
}
|
|
1074
915
|
async unsetPkgTsPaths(name: string) {
|
|
1075
916
|
const rootTsConfig = (await this.readJson("tsconfig.json")) as TsConfigJson;
|
|
1076
|
-
const filteredKeys = Object.keys(
|
|
1077
|
-
|
|
1078
|
-
)
|
|
917
|
+
const filteredKeys = Object.keys(rootTsConfig.compilerOptions.paths ?? {}).filter(
|
|
918
|
+
(key) => key !== name && key !== `${name}/*`,
|
|
919
|
+
);
|
|
1079
920
|
rootTsConfig.compilerOptions.paths = Object.fromEntries(
|
|
1080
|
-
filteredKeys.map((key) => [
|
|
1081
|
-
key,
|
|
1082
|
-
rootTsConfig.compilerOptions.paths?.[key] ?? [],
|
|
1083
|
-
]),
|
|
921
|
+
filteredKeys.map((key) => [key, rootTsConfig.compilerOptions.paths?.[key] ?? []]),
|
|
1084
922
|
);
|
|
1085
923
|
if (rootTsConfig.references) {
|
|
1086
924
|
rootTsConfig.references = rootTsConfig.references.filter(
|
|
@@ -1092,12 +930,7 @@ export class WorkspaceExecutor extends Executor {
|
|
|
1092
930
|
}
|
|
1093
931
|
async getDirInModule(basePath: string, name: string) {
|
|
1094
932
|
const AVOID_DIRS = ["__lib", "__scalar", `_`, `_${name}`];
|
|
1095
|
-
const getDirs = async (
|
|
1096
|
-
dirname: string,
|
|
1097
|
-
maxDepth = 3,
|
|
1098
|
-
results: string[] = [],
|
|
1099
|
-
prefix = "",
|
|
1100
|
-
) => {
|
|
933
|
+
const getDirs = async (dirname: string, maxDepth = 3, results: string[] = [], prefix = "") => {
|
|
1101
934
|
const dirs = await this.readdir(dirname);
|
|
1102
935
|
await Promise.all(
|
|
1103
936
|
dirs.map(async (dir) => {
|
|
@@ -1105,8 +938,7 @@ export class WorkspaceExecutor extends Executor {
|
|
|
1105
938
|
const dirPath = path.join(dirname, dir);
|
|
1106
939
|
if ((await stat(dirPath)).isDirectory()) {
|
|
1107
940
|
results.push(`${prefix}${dir}`);
|
|
1108
|
-
if (maxDepth > 0)
|
|
1109
|
-
await getDirs(dirPath, maxDepth - 1, results, `${prefix}${dir}/`);
|
|
941
|
+
if (maxDepth > 0) await getDirs(dirPath, maxDepth - 1, results, `${prefix}${dir}/`);
|
|
1110
942
|
}
|
|
1111
943
|
}),
|
|
1112
944
|
);
|
|
@@ -1114,34 +946,23 @@ export class WorkspaceExecutor extends Executor {
|
|
|
1114
946
|
};
|
|
1115
947
|
return await getDirs(basePath);
|
|
1116
948
|
}
|
|
1117
|
-
async commit(
|
|
1118
|
-
message: string,
|
|
1119
|
-
{ init = false, add = true }: { init?: boolean; add?: boolean } = {},
|
|
1120
|
-
) {
|
|
949
|
+
async commit(message: string, { init = false, add = true }: { init?: boolean; add?: boolean } = {}) {
|
|
1121
950
|
if (init) await this.exec(`git init --quiet`);
|
|
1122
951
|
if (add) await this.exec(`git add .`);
|
|
1123
952
|
await this.exec(`git commit --quiet -m "${message}"`);
|
|
1124
953
|
}
|
|
1125
954
|
async #getDirHasFile(basePath: string, targetFilename: string) {
|
|
1126
955
|
const AVOID_DIRS = ["node_modules", "dist", "public", "webkit"];
|
|
1127
|
-
const getDirs = async (
|
|
1128
|
-
dirname: string,
|
|
1129
|
-
maxDepth = 3,
|
|
1130
|
-
results: string[] = [],
|
|
1131
|
-
prefix = "",
|
|
1132
|
-
) => {
|
|
956
|
+
const getDirs = async (dirname: string, maxDepth = 3, results: string[] = [], prefix = "") => {
|
|
1133
957
|
const dirs = await this.readdir(dirname);
|
|
1134
958
|
await Promise.all(
|
|
1135
959
|
dirs.map(async (dir) => {
|
|
1136
960
|
if (AVOID_DIRS.includes(dir)) return;
|
|
1137
961
|
const dirPath = path.join(dirname, dir);
|
|
1138
962
|
if ((await stat(dirPath)).isDirectory()) {
|
|
1139
|
-
const hasTargetFile = await FileSys.fileExists(
|
|
1140
|
-
path.join(dirPath, targetFilename),
|
|
1141
|
-
);
|
|
963
|
+
const hasTargetFile = await FileSys.fileExists(path.join(dirPath, targetFilename));
|
|
1142
964
|
if (hasTargetFile) results.push(`${prefix}${dir}`);
|
|
1143
|
-
if (maxDepth > 0)
|
|
1144
|
-
await getDirs(dirPath, maxDepth - 1, results, `${prefix}${dir}/`);
|
|
965
|
+
if (maxDepth > 0) await getDirs(dirPath, maxDepth - 1, results, `${prefix}${dir}/`);
|
|
1145
966
|
}
|
|
1146
967
|
}),
|
|
1147
968
|
);
|
|
@@ -1154,18 +975,10 @@ export class WorkspaceExecutor extends Executor {
|
|
|
1154
975
|
const [appNames, libNames] = await this.getSyss();
|
|
1155
976
|
const scalarConstantExampleFiles = [
|
|
1156
977
|
...(
|
|
1157
|
-
await Promise.all(
|
|
1158
|
-
appNames.map((appName) =>
|
|
1159
|
-
AppExecutor.from(this, appName).getScalarConstantFiles(),
|
|
1160
|
-
),
|
|
1161
|
-
)
|
|
978
|
+
await Promise.all(appNames.map((appName) => AppExecutor.from(this, appName).getScalarConstantFiles()))
|
|
1162
979
|
).flat(),
|
|
1163
980
|
...(
|
|
1164
|
-
await Promise.all(
|
|
1165
|
-
libNames.map((libName) =>
|
|
1166
|
-
LibExecutor.from(this, libName).getScalarConstantFiles(),
|
|
1167
|
-
),
|
|
1168
|
-
)
|
|
981
|
+
await Promise.all(libNames.map((libName) => LibExecutor.from(this, libName).getScalarConstantFiles()))
|
|
1169
982
|
).flat(),
|
|
1170
983
|
];
|
|
1171
984
|
return scalarConstantExampleFiles;
|
|
@@ -1173,60 +986,24 @@ export class WorkspaceExecutor extends Executor {
|
|
|
1173
986
|
async getConstantFiles() {
|
|
1174
987
|
const [appNames, libNames] = await this.getSyss();
|
|
1175
988
|
const moduleConstantExampleFiles = [
|
|
1176
|
-
...(
|
|
1177
|
-
|
|
1178
|
-
appNames.map((appName) =>
|
|
1179
|
-
AppExecutor.from(this, appName).getConstantFiles(),
|
|
1180
|
-
),
|
|
1181
|
-
)
|
|
1182
|
-
).flat(),
|
|
1183
|
-
...(
|
|
1184
|
-
await Promise.all(
|
|
1185
|
-
libNames.map((libName) =>
|
|
1186
|
-
LibExecutor.from(this, libName).getConstantFiles(),
|
|
1187
|
-
),
|
|
1188
|
-
)
|
|
1189
|
-
).flat(),
|
|
989
|
+
...(await Promise.all(appNames.map((appName) => AppExecutor.from(this, appName).getConstantFiles()))).flat(),
|
|
990
|
+
...(await Promise.all(libNames.map((libName) => LibExecutor.from(this, libName).getConstantFiles()))).flat(),
|
|
1190
991
|
];
|
|
1191
992
|
return moduleConstantExampleFiles;
|
|
1192
993
|
}
|
|
1193
994
|
async getDictionaryFiles() {
|
|
1194
995
|
const [appNames, libNames] = await this.getSyss();
|
|
1195
996
|
const moduleDictionaryExampleFiles = [
|
|
1196
|
-
...(
|
|
1197
|
-
|
|
1198
|
-
appNames.map((appName) =>
|
|
1199
|
-
AppExecutor.from(this, appName).getDictionaryFiles(),
|
|
1200
|
-
),
|
|
1201
|
-
)
|
|
1202
|
-
).flat(),
|
|
1203
|
-
...(
|
|
1204
|
-
await Promise.all(
|
|
1205
|
-
libNames.map((libName) =>
|
|
1206
|
-
LibExecutor.from(this, libName).getDictionaryFiles(),
|
|
1207
|
-
),
|
|
1208
|
-
)
|
|
1209
|
-
).flat(),
|
|
997
|
+
...(await Promise.all(appNames.map((appName) => AppExecutor.from(this, appName).getDictionaryFiles()))).flat(),
|
|
998
|
+
...(await Promise.all(libNames.map((libName) => LibExecutor.from(this, libName).getDictionaryFiles()))).flat(),
|
|
1210
999
|
];
|
|
1211
1000
|
return moduleDictionaryExampleFiles;
|
|
1212
1001
|
}
|
|
1213
1002
|
async getViewFiles() {
|
|
1214
1003
|
const [appNames, libNames] = await this.getSyss();
|
|
1215
1004
|
const viewExampleFiles = [
|
|
1216
|
-
...(
|
|
1217
|
-
|
|
1218
|
-
appNames.map((appName) =>
|
|
1219
|
-
AppExecutor.from(this, appName).getViewsSourceCode(),
|
|
1220
|
-
),
|
|
1221
|
-
)
|
|
1222
|
-
).flat(),
|
|
1223
|
-
...(
|
|
1224
|
-
await Promise.all(
|
|
1225
|
-
libNames.map((libName) =>
|
|
1226
|
-
LibExecutor.from(this, libName).getViewsSourceCode(),
|
|
1227
|
-
),
|
|
1228
|
-
)
|
|
1229
|
-
).flat(),
|
|
1005
|
+
...(await Promise.all(appNames.map((appName) => AppExecutor.from(this, appName).getViewsSourceCode()))).flat(),
|
|
1006
|
+
...(await Promise.all(libNames.map((libName) => LibExecutor.from(this, libName).getViewsSourceCode()))).flat(),
|
|
1230
1007
|
];
|
|
1231
1008
|
return viewExampleFiles;
|
|
1232
1009
|
}
|
|
@@ -1245,11 +1022,7 @@ export class SysExecutor extends Executor {
|
|
|
1245
1022
|
override name: string;
|
|
1246
1023
|
type: "app" | "lib";
|
|
1247
1024
|
override emoji: string;
|
|
1248
|
-
constructor({
|
|
1249
|
-
workspace = WorkspaceExecutor.fromRoot(),
|
|
1250
|
-
name,
|
|
1251
|
-
type,
|
|
1252
|
-
}: SysExecutorOptions) {
|
|
1025
|
+
constructor({ workspace = WorkspaceExecutor.fromRoot(), name, type }: SysExecutorOptions) {
|
|
1253
1026
|
super(name, `${workspace.workspaceRoot}/${type}s/${name}`);
|
|
1254
1027
|
this.workspace = workspace;
|
|
1255
1028
|
this.name = name;
|
|
@@ -1266,8 +1039,7 @@ export class SysExecutor extends Executor {
|
|
|
1266
1039
|
return this.#akanConfig;
|
|
1267
1040
|
}
|
|
1268
1041
|
async getModules() {
|
|
1269
|
-
const path =
|
|
1270
|
-
this.type === "app" ? `apps/${this.name}/lib` : `libs/${this.name}/lib`;
|
|
1042
|
+
const path = this.type === "app" ? `apps/${this.name}/lib` : `libs/${this.name}/lib`;
|
|
1271
1043
|
return await this.workspace.getDirInModule(path, this.name);
|
|
1272
1044
|
}
|
|
1273
1045
|
|
|
@@ -1279,26 +1051,17 @@ export class SysExecutor extends Executor {
|
|
|
1279
1051
|
allowEmpty,
|
|
1280
1052
|
}: {
|
|
1281
1053
|
allowEmpty?: AllowEmpty;
|
|
1282
|
-
} = {}): AllowEmpty extends true
|
|
1283
|
-
|
|
1284
|
-
: AppInfo | LibInfo
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
return this.#scanInfo as AllowEmpty extends true
|
|
1288
|
-
? AppInfo | LibInfo | null
|
|
1289
|
-
: AppInfo | LibInfo;
|
|
1290
|
-
}
|
|
1291
|
-
#getScanTemplateTasks(
|
|
1292
|
-
scanInfo: AppInfo | LibInfo,
|
|
1293
|
-
): (Promise<FileContent[]> | null)[] {
|
|
1054
|
+
} = {}): AllowEmpty extends true ? AppInfo | LibInfo | null : AppInfo | LibInfo {
|
|
1055
|
+
if (!this.hasScanInfo() && !allowEmpty) throw new Error("Scan info is not available");
|
|
1056
|
+
return this.#scanInfo as AllowEmpty extends true ? AppInfo | LibInfo | null : AppInfo | LibInfo;
|
|
1057
|
+
}
|
|
1058
|
+
#getScanTemplateTasks(scanInfo: AppInfo | LibInfo): (Promise<FileContent[]> | null)[] {
|
|
1294
1059
|
return [
|
|
1295
1060
|
this._applyTemplate({ basePath: "env", template: "env", scanInfo }),
|
|
1296
1061
|
this._applyTemplate({ basePath: "lib", template: "lib", scanInfo }),
|
|
1297
1062
|
this._applyTemplate({ basePath: ".", template: "server.ts", scanInfo }),
|
|
1298
1063
|
this._applyTemplate({ basePath: ".", template: "client.ts", scanInfo }),
|
|
1299
|
-
this.type === "lib"
|
|
1300
|
-
? this._applyTemplate({ basePath: ".", template: "index.ts", scanInfo })
|
|
1301
|
-
: null,
|
|
1064
|
+
this.type === "lib" ? this._applyTemplate({ basePath: ".", template: "index.ts", scanInfo }) : null,
|
|
1302
1065
|
...scanFacetDirs.map((facet) =>
|
|
1303
1066
|
this._applyTemplate({
|
|
1304
1067
|
basePath: facet,
|
|
@@ -1359,11 +1122,7 @@ export class SysExecutor extends Executor {
|
|
|
1359
1122
|
if (writeLib) {
|
|
1360
1123
|
const libInfos = [...scanInfo.getLibInfos().values()];
|
|
1361
1124
|
await this.#updateDependencies(scanInfo);
|
|
1362
|
-
await Promise.all(
|
|
1363
|
-
libInfos.flatMap((libInfo) =>
|
|
1364
|
-
libInfo.exec.#getScanTemplateTasks(libInfo),
|
|
1365
|
-
),
|
|
1366
|
-
);
|
|
1125
|
+
await Promise.all(libInfos.flatMap((libInfo) => libInfo.exec.#getScanTemplateTasks(libInfo)));
|
|
1367
1126
|
}
|
|
1368
1127
|
}
|
|
1369
1128
|
this.#scanInfo = scanInfo;
|
|
@@ -1380,9 +1139,7 @@ export class SysExecutor extends Executor {
|
|
|
1380
1139
|
...libPackageJson,
|
|
1381
1140
|
dependencies: {
|
|
1382
1141
|
...Object.fromEntries(
|
|
1383
|
-
Object.entries(libPackageJson.dependencies ?? {}).filter(
|
|
1384
|
-
([dep]) => !devDependencySet.has(dep),
|
|
1385
|
-
),
|
|
1142
|
+
Object.entries(libPackageJson.dependencies ?? {}).filter(([dep]) => !devDependencySet.has(dep)),
|
|
1386
1143
|
),
|
|
1387
1144
|
...(Object.fromEntries(
|
|
1388
1145
|
dependencies
|
|
@@ -1393,134 +1150,82 @@ export class SysExecutor extends Executor {
|
|
|
1393
1150
|
},
|
|
1394
1151
|
devDependencies: {
|
|
1395
1152
|
...Object.fromEntries(
|
|
1396
|
-
Object.entries(libPackageJson.devDependencies ?? {}).filter(
|
|
1397
|
-
([dep]) => !dependencySet.has(dep),
|
|
1398
|
-
),
|
|
1153
|
+
Object.entries(libPackageJson.devDependencies ?? {}).filter(([dep]) => !dependencySet.has(dep)),
|
|
1399
1154
|
),
|
|
1400
1155
|
...(Object.fromEntries(
|
|
1401
1156
|
devDependencies
|
|
1402
|
-
.filter(
|
|
1403
|
-
(dep) =>
|
|
1404
|
-
rootPackageJson.dependencies?.[dep] ||
|
|
1405
|
-
rootPackageJson.devDependencies?.[dep],
|
|
1406
|
-
)
|
|
1157
|
+
.filter((dep) => rootPackageJson.dependencies?.[dep] || rootPackageJson.devDependencies?.[dep])
|
|
1407
1158
|
.sort()
|
|
1408
|
-
.map((dep) => [
|
|
1409
|
-
dep,
|
|
1410
|
-
rootPackageJson.devDependencies?.[dep] ??
|
|
1411
|
-
rootPackageJson.dependencies?.[dep],
|
|
1412
|
-
]),
|
|
1159
|
+
.map((dep) => [dep, rootPackageJson.devDependencies?.[dep] ?? rootPackageJson.dependencies?.[dep]]),
|
|
1413
1160
|
) as Record<string, string>),
|
|
1414
1161
|
},
|
|
1415
1162
|
};
|
|
1416
1163
|
await this.setPackageJson(libPkgJsonWithDeps);
|
|
1417
1164
|
}
|
|
1418
1165
|
override async getLocalFile(targetPath: string) {
|
|
1419
|
-
const filePath = path.isAbsolute(targetPath)
|
|
1420
|
-
? targetPath
|
|
1421
|
-
: `${this.type}s/${this.name}/${targetPath}`;
|
|
1166
|
+
const filePath = path.isAbsolute(targetPath) ? targetPath : `${this.type}s/${this.name}/${targetPath}`;
|
|
1422
1167
|
const content = await this.workspace.readFile(filePath);
|
|
1423
1168
|
return { filePath, content };
|
|
1424
1169
|
}
|
|
1425
1170
|
|
|
1426
1171
|
async getDatabaseModules() {
|
|
1427
1172
|
const databaseModules = (await this.readdir("lib"))
|
|
1428
|
-
.filter(
|
|
1429
|
-
|
|
1430
|
-
!name.startsWith("_") &&
|
|
1431
|
-
!name.startsWith("__") &&
|
|
1432
|
-
!name.endsWith(".ts"),
|
|
1433
|
-
)
|
|
1434
|
-
.filter((name) =>
|
|
1435
|
-
Bun.file(`${this.cwdPath}/lib/${name}/${name}.constant.ts`).exists(),
|
|
1436
|
-
);
|
|
1173
|
+
.filter((name) => !name.startsWith("_") && !name.startsWith("__") && !name.endsWith(".ts"))
|
|
1174
|
+
.filter((name) => Bun.file(`${this.cwdPath}/lib/${name}/${name}.constant.ts`).exists());
|
|
1437
1175
|
return databaseModules;
|
|
1438
1176
|
}
|
|
1439
1177
|
|
|
1440
1178
|
async getServiceModules() {
|
|
1441
1179
|
const serviceModules = (await this.readdir("lib"))
|
|
1442
1180
|
.filter((name) => name.startsWith("_") && !name.startsWith("__"))
|
|
1443
|
-
.filter((name) =>
|
|
1444
|
-
Bun.file(`${this.cwdPath}/lib/${name}/${name}.service.ts`).exists(),
|
|
1445
|
-
);
|
|
1181
|
+
.filter((name) => Bun.file(`${this.cwdPath}/lib/${name}/${name}.service.ts`).exists());
|
|
1446
1182
|
return serviceModules;
|
|
1447
1183
|
}
|
|
1448
1184
|
|
|
1449
1185
|
async getScalarModules() {
|
|
1450
1186
|
const scalarModules = (await this.readdir("lib/__scalar"))
|
|
1451
1187
|
.filter((name) => !name.startsWith("_"))
|
|
1452
|
-
.filter((name) =>
|
|
1453
|
-
Bun.file(
|
|
1454
|
-
`${this.cwdPath}/lib/__scalar/${name}/${name}.constant.ts`,
|
|
1455
|
-
).exists(),
|
|
1456
|
-
);
|
|
1188
|
+
.filter((name) => Bun.file(`${this.cwdPath}/lib/__scalar/${name}/${name}.constant.ts`).exists());
|
|
1457
1189
|
return scalarModules;
|
|
1458
1190
|
}
|
|
1459
1191
|
|
|
1460
1192
|
async getViewComponents() {
|
|
1461
1193
|
const viewComponents = (await this.readdir("lib"))
|
|
1462
|
-
.filter(
|
|
1463
|
-
|
|
1464
|
-
!name.startsWith("_") &&
|
|
1465
|
-
!name.startsWith("__") &&
|
|
1466
|
-
!name.endsWith(".ts"),
|
|
1467
|
-
)
|
|
1468
|
-
.filter((name) =>
|
|
1469
|
-
Bun.file(`${this.cwdPath}/lib/${name}/${name}.View.tsx`).exists(),
|
|
1470
|
-
);
|
|
1194
|
+
.filter((name) => !name.startsWith("_") && !name.startsWith("__") && !name.endsWith(".ts"))
|
|
1195
|
+
.filter((name) => Bun.file(`${this.cwdPath}/lib/${name}/${name}.View.tsx`).exists());
|
|
1471
1196
|
return viewComponents;
|
|
1472
1197
|
}
|
|
1473
1198
|
|
|
1474
1199
|
async getUnitComponents() {
|
|
1475
1200
|
const unitComponents = (await this.readdir("lib"))
|
|
1476
|
-
.filter(
|
|
1477
|
-
|
|
1478
|
-
!name.startsWith("_") &&
|
|
1479
|
-
!name.startsWith("__") &&
|
|
1480
|
-
!name.endsWith(".ts"),
|
|
1481
|
-
)
|
|
1482
|
-
.filter((name) =>
|
|
1483
|
-
Bun.file(`${this.cwdPath}/lib/${name}/${name}.Unit.tsx`).exists(),
|
|
1484
|
-
);
|
|
1201
|
+
.filter((name) => !name.startsWith("_") && !name.startsWith("__") && !name.endsWith(".ts"))
|
|
1202
|
+
.filter((name) => Bun.file(`${this.cwdPath}/lib/${name}/${name}.Unit.tsx`).exists());
|
|
1485
1203
|
return unitComponents;
|
|
1486
1204
|
}
|
|
1487
1205
|
async getTemplateComponents() {
|
|
1488
1206
|
const templateComponents = (await this.readdir("lib"))
|
|
1489
|
-
.filter(
|
|
1490
|
-
|
|
1491
|
-
!name.startsWith("_") &&
|
|
1492
|
-
!name.startsWith("__") &&
|
|
1493
|
-
!name.endsWith(".ts"),
|
|
1494
|
-
)
|
|
1495
|
-
.filter((name) =>
|
|
1496
|
-
Bun.file(`${this.cwdPath}/lib/${name}/${name}.Template.tsx`).exists(),
|
|
1497
|
-
);
|
|
1207
|
+
.filter((name) => !name.startsWith("_") && !name.startsWith("__") && !name.endsWith(".ts"))
|
|
1208
|
+
.filter((name) => Bun.file(`${this.cwdPath}/lib/${name}/${name}.Template.tsx`).exists());
|
|
1498
1209
|
return templateComponents;
|
|
1499
1210
|
}
|
|
1500
1211
|
|
|
1501
1212
|
async getViewsSourceCode() {
|
|
1502
1213
|
const viewComponents = await this.getViewComponents();
|
|
1503
1214
|
return Promise.all(
|
|
1504
|
-
viewComponents.map((viewComponent) =>
|
|
1505
|
-
this.getLocalFile(`lib/${viewComponent}/${viewComponent}.View.tsx`),
|
|
1506
|
-
),
|
|
1215
|
+
viewComponents.map((viewComponent) => this.getLocalFile(`lib/${viewComponent}/${viewComponent}.View.tsx`)),
|
|
1507
1216
|
);
|
|
1508
1217
|
}
|
|
1509
1218
|
async getUnitsSourceCode() {
|
|
1510
1219
|
const unitComponents = await this.getUnitComponents();
|
|
1511
1220
|
return Promise.all(
|
|
1512
|
-
unitComponents.map((unitComponent) =>
|
|
1513
|
-
this.getLocalFile(`lib/${unitComponent}/${unitComponent}.Unit.tsx`),
|
|
1514
|
-
),
|
|
1221
|
+
unitComponents.map((unitComponent) => this.getLocalFile(`lib/${unitComponent}/${unitComponent}.Unit.tsx`)),
|
|
1515
1222
|
);
|
|
1516
1223
|
}
|
|
1517
1224
|
async getTemplatesSourceCode() {
|
|
1518
1225
|
const templateComponents = await this.getTemplateComponents();
|
|
1519
1226
|
return Promise.all(
|
|
1520
1227
|
templateComponents.map((templateComponent) =>
|
|
1521
|
-
this.getLocalFile(
|
|
1522
|
-
`lib/${templateComponent}/${templateComponent}.Template.tsx`,
|
|
1523
|
-
),
|
|
1228
|
+
this.getLocalFile(`lib/${templateComponent}/${templateComponent}.Template.tsx`),
|
|
1524
1229
|
),
|
|
1525
1230
|
);
|
|
1526
1231
|
}
|
|
@@ -1529,9 +1234,7 @@ export class SysExecutor extends Executor {
|
|
|
1529
1234
|
const scalarModules = await this.getScalarModules();
|
|
1530
1235
|
return Promise.all(
|
|
1531
1236
|
scalarModules.map((scalarModule) =>
|
|
1532
|
-
this.getLocalFile(
|
|
1533
|
-
`lib/__scalar/${scalarModule}/${scalarModule}.constant.ts`,
|
|
1534
|
-
),
|
|
1237
|
+
this.getLocalFile(`lib/__scalar/${scalarModule}/${scalarModule}.constant.ts`),
|
|
1535
1238
|
),
|
|
1536
1239
|
);
|
|
1537
1240
|
}
|
|
@@ -1539,19 +1242,13 @@ export class SysExecutor extends Executor {
|
|
|
1539
1242
|
async getScalarDictionaryFiles() {
|
|
1540
1243
|
const scalarModules = await this.getScalarModules();
|
|
1541
1244
|
return Promise.all(
|
|
1542
|
-
scalarModules.map((scalarModule) =>
|
|
1543
|
-
this.getLocalFile(`lib/${scalarModule}/${scalarModule}.dictionary.ts`),
|
|
1544
|
-
),
|
|
1245
|
+
scalarModules.map((scalarModule) => this.getLocalFile(`lib/${scalarModule}/${scalarModule}.dictionary.ts`)),
|
|
1545
1246
|
);
|
|
1546
1247
|
}
|
|
1547
1248
|
|
|
1548
1249
|
async getConstantFiles() {
|
|
1549
1250
|
const modules = await this.getModules();
|
|
1550
|
-
return Promise.all(
|
|
1551
|
-
modules.map((module) =>
|
|
1552
|
-
this.getLocalFile(`lib/${module}/${module}.constant.ts`),
|
|
1553
|
-
),
|
|
1554
|
-
);
|
|
1251
|
+
return Promise.all(modules.map((module) => this.getLocalFile(`lib/${module}/${module}.constant.ts`)));
|
|
1555
1252
|
}
|
|
1556
1253
|
async getConstantFilesWithLibs() {
|
|
1557
1254
|
const scanInfo =
|
|
@@ -1567,19 +1264,11 @@ export class SysExecutor extends Executor {
|
|
|
1567
1264
|
...(await LibExecutor.from(this, lib).getScalarConstantFiles()),
|
|
1568
1265
|
]),
|
|
1569
1266
|
);
|
|
1570
|
-
return [
|
|
1571
|
-
...sysContantFiles,
|
|
1572
|
-
...sysScalarConstantFiles,
|
|
1573
|
-
...libConstantFiles.flat(),
|
|
1574
|
-
];
|
|
1267
|
+
return [...sysContantFiles, ...sysScalarConstantFiles, ...libConstantFiles.flat()];
|
|
1575
1268
|
}
|
|
1576
1269
|
async getDictionaryFiles() {
|
|
1577
1270
|
const modules = await this.getModules();
|
|
1578
|
-
return Promise.all(
|
|
1579
|
-
modules.map((module) =>
|
|
1580
|
-
this.getLocalFile(`lib/${module}/${module}.dictionary.ts`),
|
|
1581
|
-
),
|
|
1582
|
-
);
|
|
1271
|
+
return Promise.all(modules.map((module) => this.getLocalFile(`lib/${module}/${module}.dictionary.ts`)));
|
|
1583
1272
|
}
|
|
1584
1273
|
override async applyTemplate(options: {
|
|
1585
1274
|
basePath: string;
|
|
@@ -1590,10 +1279,7 @@ export class SysExecutor extends Executor {
|
|
|
1590
1279
|
const dict = {
|
|
1591
1280
|
...(options.dict ?? {}),
|
|
1592
1281
|
...Object.fromEntries(
|
|
1593
|
-
Object.entries(options.dict ?? {}).map(([key, value]) => [
|
|
1594
|
-
capitalize(key),
|
|
1595
|
-
capitalize(value),
|
|
1596
|
-
]),
|
|
1282
|
+
Object.entries(options.dict ?? {}).map(([key, value]) => [capitalize(key), capitalize(value)]),
|
|
1597
1283
|
),
|
|
1598
1284
|
};
|
|
1599
1285
|
const scanInfo = await this.scan();
|
|
@@ -1616,29 +1302,30 @@ export class AppExecutor extends SysExecutor {
|
|
|
1616
1302
|
override emoji = execEmoji.app;
|
|
1617
1303
|
constructor({ workspace, name }: AppExecutorOptions) {
|
|
1618
1304
|
super({ workspace, name, type: "app" });
|
|
1619
|
-
this.dist = new Executor(
|
|
1620
|
-
`dist/${name}`,
|
|
1621
|
-
`${this.workspace.workspaceRoot}/dist/apps/${name}`,
|
|
1622
|
-
);
|
|
1305
|
+
this.dist = new Executor(`dist/${name}`, `${this.workspace.workspaceRoot}/dist/apps/${name}`);
|
|
1623
1306
|
}
|
|
1624
1307
|
static #execs = new Map<string, AppExecutor>();
|
|
1625
1308
|
static from(executor: SysExecutor | WorkspaceExecutor, name: string) {
|
|
1626
1309
|
const exec = AppExecutor.#execs.get(name);
|
|
1627
1310
|
if (exec) return exec;
|
|
1628
|
-
else if (executor instanceof WorkspaceExecutor)
|
|
1629
|
-
return new AppExecutor({ workspace: executor, name });
|
|
1311
|
+
else if (executor instanceof WorkspaceExecutor) return new AppExecutor({ workspace: executor, name });
|
|
1630
1312
|
else return new AppExecutor({ workspace: executor.workspace, name });
|
|
1631
1313
|
}
|
|
1632
1314
|
getEnv() {
|
|
1633
1315
|
return WorkspaceExecutor.getBaseDevEnv().env;
|
|
1634
1316
|
}
|
|
1317
|
+
async getDevPort() {
|
|
1318
|
+
const basePort = 8282;
|
|
1319
|
+
const appNames = (await this.workspace.getApps()).sort((a, b) => a.localeCompare(b));
|
|
1320
|
+
const appIndex = Math.max(appNames.indexOf(this.name), 0);
|
|
1321
|
+
const portOffset = WorkspaceExecutor.getBaseDevEnv().portOffset;
|
|
1322
|
+
return basePort + appIndex + portOffset;
|
|
1323
|
+
}
|
|
1635
1324
|
getCommandEnv(env: Record<string, string> = {}): Record<string, string> {
|
|
1636
1325
|
const basePort = 8282;
|
|
1637
1326
|
const portOffset = WorkspaceExecutor.getBaseDevEnv().portOffset;
|
|
1638
1327
|
const PORT = basePort ? (basePort + portOffset).toString() : undefined;
|
|
1639
|
-
const AKAN_PUBLIC_SERVER_PORT = portOffset
|
|
1640
|
-
? (8282 + portOffset).toString()
|
|
1641
|
-
: undefined;
|
|
1328
|
+
const AKAN_PUBLIC_SERVER_PORT = portOffset ? (8282 + portOffset).toString() : undefined;
|
|
1642
1329
|
return {
|
|
1643
1330
|
...process.env,
|
|
1644
1331
|
AKAN_PUBLIC_APP_NAME: this.name,
|
|
@@ -1651,28 +1338,26 @@ export class AppExecutor extends SysExecutor {
|
|
|
1651
1338
|
}
|
|
1652
1339
|
async prepareCommand(type: "build" | "start") {
|
|
1653
1340
|
const akanConfig = await this.getConfig();
|
|
1654
|
-
const databaseMode =
|
|
1655
|
-
process.env.AKAN_DATABASE_MODE ??
|
|
1656
|
-
akanConfig.defaultDatabaseMode ??
|
|
1657
|
-
"single";
|
|
1341
|
+
const databaseMode = process.env.AKAN_DATABASE_MODE ?? akanConfig.defaultDatabaseMode ?? "single";
|
|
1658
1342
|
const routeEnv = {
|
|
1659
1343
|
AKAN_PUBLIC_BASE_PATHS: [...akanConfig.basePaths].join(","),
|
|
1660
1344
|
AKAN_DATABASE_MODE: databaseMode,
|
|
1661
1345
|
};
|
|
1662
1346
|
Object.assign(process.env, routeEnv);
|
|
1663
1347
|
if (type === "build") {
|
|
1664
|
-
if (await this.exists(this.dist.cwdPath))
|
|
1665
|
-
|
|
1666
|
-
await Promise.all([
|
|
1667
|
-
this.dist.mkdir("private"),
|
|
1668
|
-
this.dist.mkdir("public"),
|
|
1669
|
-
]);
|
|
1348
|
+
if (await this.exists(this.dist.cwdPath)) await this.dist.exec(`rm -rf ${this.dist.cwdPath}`);
|
|
1349
|
+
await Promise.all([this.dist.mkdir("private"), this.dist.mkdir("public")]);
|
|
1670
1350
|
await Promise.all([
|
|
1671
1351
|
this.cp("private", `${this.dist.cwdPath}/private`),
|
|
1672
1352
|
this.cp("public", `${this.dist.cwdPath}/public`),
|
|
1673
1353
|
]);
|
|
1674
1354
|
} else await this.removeDir(".akan");
|
|
1675
|
-
const
|
|
1355
|
+
const devPort = type === "start" ? (await this.getDevPort()).toString() : undefined;
|
|
1356
|
+
const env = this.getCommandEnv({
|
|
1357
|
+
AKAN_COMMAND_TYPE: type,
|
|
1358
|
+
...routeEnv,
|
|
1359
|
+
...(devPort ? { PORT: devPort, AKAN_PUBLIC_CLIENT_PORT: devPort, AKAN_PUBLIC_SERVER_PORT: devPort } : {}),
|
|
1360
|
+
});
|
|
1676
1361
|
return { env };
|
|
1677
1362
|
}
|
|
1678
1363
|
#publicEnv: Record<string, string> | null = null;
|
|
@@ -1704,11 +1389,7 @@ export class AppExecutor extends SysExecutor {
|
|
|
1704
1389
|
}
|
|
1705
1390
|
|
|
1706
1391
|
#pageKeys: string[] | null = null;
|
|
1707
|
-
async getPageKeys({
|
|
1708
|
-
refresh,
|
|
1709
|
-
}: {
|
|
1710
|
-
refresh?: boolean;
|
|
1711
|
-
} = {}): Promise<string[]> {
|
|
1392
|
+
async getPageKeys({ refresh }: { refresh?: boolean } = {}): Promise<string[]> {
|
|
1712
1393
|
if (this.#pageKeys && !refresh) return this.#pageKeys;
|
|
1713
1394
|
const akanConfig = await this.getConfig();
|
|
1714
1395
|
const glob = new Bun.Glob("**/*");
|
|
@@ -1736,18 +1417,10 @@ export class AppExecutor extends SysExecutor {
|
|
|
1736
1417
|
});
|
|
1737
1418
|
const parsed = parseRouteModuleKey(key);
|
|
1738
1419
|
if (parsed.isInternalRootLayout) {
|
|
1739
|
-
throw new Error(
|
|
1740
|
-
`[route-convention] __root_layout is reserved for Akan.js generated root layout: ${absPath}`,
|
|
1741
|
-
);
|
|
1420
|
+
throw new Error(`[route-convention] __root_layout is reserved for Akan.js generated root layout: ${absPath}`);
|
|
1742
1421
|
}
|
|
1743
|
-
const isRootLayout =
|
|
1744
|
-
|
|
1745
|
-
validateRouteSourceExports(
|
|
1746
|
-
await Bun.file(absPath).text(),
|
|
1747
|
-
absPath,
|
|
1748
|
-
parsed.kind,
|
|
1749
|
-
{ rootLayout: isRootLayout },
|
|
1750
|
-
);
|
|
1422
|
+
const isRootLayout = parsed.kind === "layout" && parsed.moduleSegments.at(-1) === "_layout";
|
|
1423
|
+
validateRouteSourceExports(await Bun.file(absPath).text(), absPath, parsed.kind, { rootLayout: isRootLayout });
|
|
1751
1424
|
pageKeys.push(key);
|
|
1752
1425
|
}
|
|
1753
1426
|
pageKeys.sort();
|
|
@@ -1763,56 +1436,27 @@ export class AppExecutor extends SysExecutor {
|
|
|
1763
1436
|
const projectAssetsPath = `${this.cwdPath}/private`;
|
|
1764
1437
|
const projectPublicLibPath = `${projectPublicPath}/libs`;
|
|
1765
1438
|
const projectAssetsLibPath = `${projectAssetsPath}/libs`;
|
|
1766
|
-
await Promise.all([
|
|
1767
|
-
this.removeDir(projectPublicLibPath),
|
|
1768
|
-
this.removeDir(projectAssetsLibPath),
|
|
1769
|
-
]);
|
|
1439
|
+
await Promise.all([this.removeDir(projectPublicLibPath), this.removeDir(projectAssetsLibPath)]);
|
|
1770
1440
|
const targetPublicDeps = [] as string[];
|
|
1771
1441
|
for (const dep of libDeps) {
|
|
1772
|
-
if (
|
|
1773
|
-
await this.exists(`${this.workspace.workspaceRoot}/libs/${dep}/public`)
|
|
1774
|
-
)
|
|
1775
|
-
targetPublicDeps.push(dep);
|
|
1442
|
+
if (await this.exists(`${this.workspace.workspaceRoot}/libs/${dep}/public`)) targetPublicDeps.push(dep);
|
|
1776
1443
|
}
|
|
1777
1444
|
const targetAssetsDeps = [] as string[];
|
|
1778
1445
|
for (const dep of libDeps) {
|
|
1779
|
-
if (
|
|
1780
|
-
await this.exists(`${this.workspace.workspaceRoot}/libs/${dep}/private`)
|
|
1781
|
-
)
|
|
1782
|
-
targetAssetsDeps.push(dep);
|
|
1446
|
+
if (await this.exists(`${this.workspace.workspaceRoot}/libs/${dep}/private`)) targetAssetsDeps.push(dep);
|
|
1783
1447
|
}
|
|
1784
|
-
await Promise.all(
|
|
1785
|
-
|
|
1786
|
-
this.mkdir(`${projectPublicLibPath}/${dep}`),
|
|
1787
|
-
),
|
|
1788
|
-
);
|
|
1789
|
-
await Promise.all(
|
|
1790
|
-
targetAssetsDeps.map((dep) =>
|
|
1791
|
-
this.mkdir(`${projectAssetsLibPath}/${dep}`),
|
|
1792
|
-
),
|
|
1793
|
-
);
|
|
1448
|
+
await Promise.all(targetPublicDeps.map((dep) => this.mkdir(`${projectPublicLibPath}/${dep}`)));
|
|
1449
|
+
await Promise.all(targetAssetsDeps.map((dep) => this.mkdir(`${projectAssetsLibPath}/${dep}`)));
|
|
1794
1450
|
await Promise.all([
|
|
1795
1451
|
...targetPublicDeps.map((dep) =>
|
|
1796
|
-
this.cp(
|
|
1797
|
-
`${this.workspace.workspaceRoot}/libs/${dep}/public`,
|
|
1798
|
-
`${projectPublicLibPath}/${dep}`,
|
|
1799
|
-
),
|
|
1452
|
+
this.cp(`${this.workspace.workspaceRoot}/libs/${dep}/public`, `${projectPublicLibPath}/${dep}`),
|
|
1800
1453
|
),
|
|
1801
1454
|
...targetAssetsDeps.map((dep) =>
|
|
1802
|
-
this.cp(
|
|
1803
|
-
`${this.workspace.workspaceRoot}/libs/${dep}/private`,
|
|
1804
|
-
`${projectAssetsLibPath}/${dep}`,
|
|
1805
|
-
),
|
|
1455
|
+
this.cp(`${this.workspace.workspaceRoot}/libs/${dep}/private`, `${projectAssetsLibPath}/${dep}`),
|
|
1806
1456
|
),
|
|
1807
1457
|
]);
|
|
1808
1458
|
}
|
|
1809
|
-
async scanSync({
|
|
1810
|
-
refresh = false,
|
|
1811
|
-
write = true,
|
|
1812
|
-
}: {
|
|
1813
|
-
refresh?: boolean;
|
|
1814
|
-
write?: boolean;
|
|
1815
|
-
} = {}) {
|
|
1459
|
+
async scanSync({ refresh = false, write = true }: { refresh?: boolean; write?: boolean } = {}) {
|
|
1816
1460
|
const scanInfo = (await this.scan({
|
|
1817
1461
|
refresh,
|
|
1818
1462
|
write,
|
|
@@ -1837,17 +1481,13 @@ export class LibExecutor extends SysExecutor {
|
|
|
1837
1481
|
override emoji = execEmoji.lib;
|
|
1838
1482
|
constructor({ workspace, name }: LibExecutorOptions) {
|
|
1839
1483
|
super({ workspace, name, type: "lib" });
|
|
1840
|
-
this.dist = new Executor(
|
|
1841
|
-
`dist/${name}`,
|
|
1842
|
-
`${this.workspace.workspaceRoot}/dist/libs/${name}`,
|
|
1843
|
-
);
|
|
1484
|
+
this.dist = new Executor(`dist/${name}`, `${this.workspace.workspaceRoot}/dist/libs/${name}`);
|
|
1844
1485
|
}
|
|
1845
1486
|
static #execs = new Map<string, LibExecutor>();
|
|
1846
1487
|
static from(executor: SysExecutor | WorkspaceExecutor, name: string) {
|
|
1847
1488
|
const exec = LibExecutor.#execs.get(name);
|
|
1848
1489
|
if (exec) return exec;
|
|
1849
|
-
else if (executor instanceof WorkspaceExecutor)
|
|
1850
|
-
return new LibExecutor({ workspace: executor, name });
|
|
1490
|
+
else if (executor instanceof WorkspaceExecutor) return new LibExecutor({ workspace: executor, name });
|
|
1851
1491
|
else return new LibExecutor({ workspace: executor.workspace, name });
|
|
1852
1492
|
}
|
|
1853
1493
|
|
|
@@ -1868,21 +1508,14 @@ export class PkgExecutor extends Executor {
|
|
|
1868
1508
|
override name: string;
|
|
1869
1509
|
dist: Executor;
|
|
1870
1510
|
override emoji = execEmoji.pkg;
|
|
1871
|
-
constructor({
|
|
1872
|
-
workspace = WorkspaceExecutor.fromRoot(),
|
|
1873
|
-
name,
|
|
1874
|
-
}: PkgExecutorOptions) {
|
|
1511
|
+
constructor({ workspace = WorkspaceExecutor.fromRoot(), name }: PkgExecutorOptions) {
|
|
1875
1512
|
super(name, `${workspace.workspaceRoot}/pkgs/${name}`);
|
|
1876
1513
|
this.workspace = workspace;
|
|
1877
1514
|
this.name = name;
|
|
1878
|
-
this.dist = new Executor(
|
|
1879
|
-
`dist/${name}`,
|
|
1880
|
-
`${this.workspace.workspaceRoot}/dist/pkgs/${name}`,
|
|
1881
|
-
);
|
|
1515
|
+
this.dist = new Executor(`dist/${name}`, `${this.workspace.workspaceRoot}/dist/pkgs/${name}`);
|
|
1882
1516
|
}
|
|
1883
1517
|
static from(executor: SysExecutor | WorkspaceExecutor, name: string) {
|
|
1884
|
-
if (executor instanceof WorkspaceExecutor)
|
|
1885
|
-
return new PkgExecutor({ workspace: executor, name });
|
|
1518
|
+
if (executor instanceof WorkspaceExecutor) return new PkgExecutor({ workspace: executor, name });
|
|
1886
1519
|
return new PkgExecutor({ workspace: executor.workspace, name });
|
|
1887
1520
|
}
|
|
1888
1521
|
|
|
@@ -1894,10 +1527,7 @@ export class PkgExecutor extends Executor {
|
|
|
1894
1527
|
this.#scanInfo = scanInfo;
|
|
1895
1528
|
return scanInfo;
|
|
1896
1529
|
}
|
|
1897
|
-
async #getDependencyVersion(
|
|
1898
|
-
rootPackageJson: PackageJson,
|
|
1899
|
-
dep: string,
|
|
1900
|
-
): Promise<string | undefined> {
|
|
1530
|
+
async #getDependencyVersion(rootPackageJson: PackageJson, dep: string): Promise<string | undefined> {
|
|
1901
1531
|
const rootDeps = {
|
|
1902
1532
|
...rootPackageJson.dependencies,
|
|
1903
1533
|
...rootPackageJson.devDependencies,
|
|
@@ -1907,15 +1537,9 @@ export class PkgExecutor extends Executor {
|
|
|
1907
1537
|
|
|
1908
1538
|
try {
|
|
1909
1539
|
const packageJsonPath = `pkgs/${dep}/package.json`;
|
|
1910
|
-
if (
|
|
1911
|
-
!(await Bun.file(
|
|
1912
|
-
path.join(this.workspace.workspaceRoot, packageJsonPath),
|
|
1913
|
-
).exists())
|
|
1914
|
-
)
|
|
1915
|
-
return undefined;
|
|
1540
|
+
if (!(await Bun.file(path.join(this.workspace.workspaceRoot, packageJsonPath)).exists())) return undefined;
|
|
1916
1541
|
const packageJson = await this.workspace.readJson(packageJsonPath);
|
|
1917
|
-
if ((packageJson as PackageJson).name === dep)
|
|
1918
|
-
return (packageJson as PackageJson).version;
|
|
1542
|
+
if ((packageJson as PackageJson).name === dep) return (packageJson as PackageJson).version;
|
|
1919
1543
|
} catch {
|
|
1920
1544
|
return undefined;
|
|
1921
1545
|
}
|
|
@@ -1926,9 +1550,7 @@ export class PkgExecutor extends Executor {
|
|
|
1926
1550
|
devDependencies: string[] = [],
|
|
1927
1551
|
): Promise<Pick<PackageJson, "dependencies" | "devDependencies">> {
|
|
1928
1552
|
const dependencyNames = [...new Set(dependencies)].sort();
|
|
1929
|
-
const devDependencyNames = [...new Set(devDependencies)]
|
|
1930
|
-
.filter((dep) => !dependencyNames.includes(dep))
|
|
1931
|
-
.sort();
|
|
1553
|
+
const devDependencyNames = [...new Set(devDependencies)].filter((dep) => !dependencyNames.includes(dep)).sort();
|
|
1932
1554
|
const dependencyVersions = new Map<string, string>();
|
|
1933
1555
|
const missingDeps: string[] = [];
|
|
1934
1556
|
for (const dep of [...dependencyNames, ...devDependencyNames]) {
|
|
@@ -1937,40 +1559,26 @@ export class PkgExecutor extends Executor {
|
|
|
1937
1559
|
else missingDeps.push(dep);
|
|
1938
1560
|
}
|
|
1939
1561
|
if (missingDeps.length > 0)
|
|
1940
|
-
throw new Error(
|
|
1941
|
-
`Missing dependency versions in root package.json: ${missingDeps.join(", ")}`,
|
|
1942
|
-
);
|
|
1562
|
+
throw new Error(`Missing dependency versions in root package.json: ${missingDeps.join(", ")}`);
|
|
1943
1563
|
|
|
1944
1564
|
const toDependencyEntries = (names: string[]) =>
|
|
1945
1565
|
names.map((dep) => {
|
|
1946
1566
|
const version = dependencyVersions.get(dep);
|
|
1947
|
-
if (!version)
|
|
1948
|
-
throw new Error(
|
|
1949
|
-
`Missing dependency versions in root package.json: ${dep}`,
|
|
1950
|
-
);
|
|
1567
|
+
if (!version) throw new Error(`Missing dependency versions in root package.json: ${dep}`);
|
|
1951
1568
|
return [dep, version] as const;
|
|
1952
1569
|
});
|
|
1953
1570
|
|
|
1954
1571
|
return {
|
|
1955
1572
|
dependencies: Object.fromEntries(toDependencyEntries(dependencyNames)),
|
|
1956
|
-
devDependencies: Object.fromEntries(
|
|
1957
|
-
toDependencyEntries(devDependencyNames),
|
|
1958
|
-
),
|
|
1573
|
+
devDependencies: Object.fromEntries(toDependencyEntries(devDependencyNames)),
|
|
1959
1574
|
};
|
|
1960
1575
|
}
|
|
1961
1576
|
async updatePackageJsonDependencies(
|
|
1962
1577
|
dependencies: string[] = [],
|
|
1963
1578
|
devDependencies: string[] = [],
|
|
1964
1579
|
): Promise<PackageJson> {
|
|
1965
|
-
const [rootPackageJson, pkgJson] = await Promise.all([
|
|
1966
|
-
|
|
1967
|
-
this.getPackageJson(),
|
|
1968
|
-
]);
|
|
1969
|
-
const dependencyMaps = await this.#toDependencyMap(
|
|
1970
|
-
rootPackageJson,
|
|
1971
|
-
dependencies,
|
|
1972
|
-
devDependencies,
|
|
1973
|
-
);
|
|
1580
|
+
const [rootPackageJson, pkgJson] = await Promise.all([this.workspace.getPackageJson(), this.getPackageJson()]);
|
|
1581
|
+
const dependencyMaps = await this.#toDependencyMap(rootPackageJson, dependencies, devDependencies);
|
|
1974
1582
|
const newPkgJson = {
|
|
1975
1583
|
...pkgJson,
|
|
1976
1584
|
...dependencyMaps,
|
|
@@ -1978,19 +1586,9 @@ export class PkgExecutor extends Executor {
|
|
|
1978
1586
|
await this.writeJson("package.json", newPkgJson);
|
|
1979
1587
|
return newPkgJson;
|
|
1980
1588
|
}
|
|
1981
|
-
async generateDistPackageJson(
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
): Promise<PackageJson> {
|
|
1985
|
-
const [rootPackageJson, pkgJson] = await Promise.all([
|
|
1986
|
-
this.workspace.getPackageJson(),
|
|
1987
|
-
this.getPackageJson(),
|
|
1988
|
-
]);
|
|
1989
|
-
const dependencyMaps = await this.#toDependencyMap(
|
|
1990
|
-
rootPackageJson,
|
|
1991
|
-
dependencies,
|
|
1992
|
-
devDependencies,
|
|
1993
|
-
);
|
|
1589
|
+
async generateDistPackageJson(dependencies: string[] = [], devDependencies: string[] = []): Promise<PackageJson> {
|
|
1590
|
+
const [rootPackageJson, pkgJson] = await Promise.all([this.workspace.getPackageJson(), this.getPackageJson()]);
|
|
1591
|
+
const dependencyMaps = await this.#toDependencyMap(rootPackageJson, dependencies, devDependencies);
|
|
1994
1592
|
const distPkgJson: PackageJson = {
|
|
1995
1593
|
...pkgJson,
|
|
1996
1594
|
type: "module",
|
|
@@ -2005,10 +1603,7 @@ export class PkgExecutor extends Executor {
|
|
|
2005
1603
|
engines: { bun: ">=1.3.13" },
|
|
2006
1604
|
...dependencyMaps,
|
|
2007
1605
|
};
|
|
2008
|
-
await Promise.all([
|
|
2009
|
-
this.dist.writeJson("package.json", distPkgJson),
|
|
2010
|
-
this.writeJson("package.json", distPkgJson),
|
|
2011
|
-
]);
|
|
1606
|
+
await Promise.all([this.dist.writeJson("package.json", distPkgJson), this.writeJson("package.json", distPkgJson)]);
|
|
2012
1607
|
return distPkgJson;
|
|
2013
1608
|
}
|
|
2014
1609
|
async build(): Promise<void> {
|
|
@@ -2021,10 +1616,7 @@ export class PkgExecutor extends Executor {
|
|
|
2021
1616
|
await this.cp(`${this.cwdPath}/dist`, this.dist.cwdPath);
|
|
2022
1617
|
}
|
|
2023
1618
|
async generateTsconfigJson(): Promise<TsConfigJson> {
|
|
2024
|
-
const [rootTsconfig, pkgTsconfig] = await Promise.all([
|
|
2025
|
-
this.workspace.getTsConfig(),
|
|
2026
|
-
this.getTsConfig(),
|
|
2027
|
-
]);
|
|
1619
|
+
const [rootTsconfig, pkgTsconfig] = await Promise.all([this.workspace.getTsConfig(), this.getTsConfig()]);
|
|
2028
1620
|
const tsconfig: TsConfigJson = {
|
|
2029
1621
|
...rootTsconfig,
|
|
2030
1622
|
...pkgTsconfig,
|
|
@@ -2047,10 +1639,7 @@ export class ModuleExecutor extends Executor {
|
|
|
2047
1639
|
sys: SysExecutor;
|
|
2048
1640
|
override emoji = execEmoji.module;
|
|
2049
1641
|
constructor({ sys, name }: ModuleExecutorOptions) {
|
|
2050
|
-
super(
|
|
2051
|
-
name,
|
|
2052
|
-
`${sys.workspace.workspaceRoot}/${sys.type}s/${sys.name}/lib/${name}`,
|
|
2053
|
-
);
|
|
1642
|
+
super(name, `${sys.workspace.workspaceRoot}/${sys.type}s/${sys.name}/lib/${name}`);
|
|
2054
1643
|
this.sys = sys;
|
|
2055
1644
|
}
|
|
2056
1645
|
static from(sysExecutor: SysExecutor, name: string) {
|