@akanjs/cli 2.4.0 → 2.4.1-rc.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/agent.command-h4afc69n.js +26 -0
- package/application.command-4ctkfdan.js +165 -0
- package/applicationBuildRunner-esa1kj7v.js +284 -0
- package/applicationReleasePackager-brvth6rs.js +245 -0
- package/capacitorApp-y0h6cgft.js +58 -0
- package/cloud.command-rpztn4fh.js +94 -0
- package/commandManifest.json +1 -0
- package/context.command-nqbtak4f.js +82 -0
- package/dependencyScanner-m4x5maek.js +9 -0
- package/guideline.command-ya0dh44f.js +356 -0
- package/incrementalBuilder.proc.js +89 -17394
- package/index-1xdrsbry.js +1447 -0
- package/index-45aj5ry0.js +990 -0
- package/index-5vvwc0cz.js +559 -0
- package/index-61keag0s.js +40 -0
- package/index-6pz1j0zj.js +62 -0
- package/index-73pr2cmy.js +534 -0
- package/index-76rn3g2c.js +76 -0
- package/index-85msc0wg.js +161 -0
- package/index-8pkbzj26.js +840 -0
- package/index-8rc0bm04.js +514 -0
- package/index-9sp6fsc5.js +1884 -0
- package/index-a6sbyy0b.js +2769 -0
- package/index-b0brjbp3.js +83 -0
- package/index-fgc8r6dj.js +33 -0
- package/index-h6ca6qg0.js +2777 -0
- package/index-hdqztm58.js +758 -0
- package/index-hwzpw9c1.js +202 -0
- package/index-pmm9e2jf.js +120 -0
- package/index-qaq13qk3.js +80 -0
- package/index-qhtr07v8.js +1072 -0
- package/index-r24hmh0q.js +4 -0
- package/index-ss469dec.js +11 -0
- package/index-swf4bmbg.js +25 -0
- package/index-w7fyqjrw.js +462 -0
- package/index-wnp7hwq7.js +193 -0
- package/index-wq8jwx8z.js +224 -0
- package/index-x53a5nya.js +301 -0
- package/index-xmc2w32q.js +4359 -0
- package/index-y3hdhy4p.js +229 -0
- package/index.js +54 -23340
- package/library.command-r15zdqvp.js +33 -0
- package/localRegistry.command-5tcahs3f.js +178 -0
- package/module.command-qrj3kmyz.js +54 -0
- package/package.command-r8sq5kzp.js +43 -0
- package/package.json +2 -2
- package/page.command-c6xdx0xm.js +24 -0
- package/primitive.command-pv9ssmtf.js +62 -0
- package/quality.command-es67wvdp.js +809 -0
- package/repair.command-677675vw.js +67 -0
- package/routeSourceValidator-wbhmbwpj.js +132 -0
- package/scalar.command-kabkd6wd.js +35 -0
- package/templates/facetIndex/index.ts +1 -1
- package/typeChecker-kravn7ns.js +8 -0
- package/typecheck.proc.js +4 -194
- package/workflow.command-64r6cw0w.js +108 -0
- package/workspace.command-vrws0rgx.js +435 -0
- package/README.ko.md +0 -72
- package/README.md +0 -85
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// pkgs/@akanjs/devkit/typeChecker.ts
|
|
3
|
+
import { readFileSync } from "fs";
|
|
4
|
+
import * as path from "path";
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
import * as ts from "typescript";
|
|
7
|
+
|
|
8
|
+
class TypeChecker {
|
|
9
|
+
configPath;
|
|
10
|
+
configFile;
|
|
11
|
+
config;
|
|
12
|
+
constructor(executor) {
|
|
13
|
+
const configPath = this.#findConfigFile(executor.cwdPath);
|
|
14
|
+
if (!configPath)
|
|
15
|
+
throw new Error("No tsconfig.json found in the project");
|
|
16
|
+
this.configPath = configPath;
|
|
17
|
+
this.configFile = ts.readConfigFile(this.configPath, (fileName) => ts.sys.readFile(fileName));
|
|
18
|
+
const parsedConfig = ts.parseJsonConfigFileContent(this.configFile.config, ts.sys, path.dirname(this.configPath), undefined, this.configPath);
|
|
19
|
+
if (parsedConfig.errors.length > 0) {
|
|
20
|
+
const errorMessages = parsedConfig.errors.map((error) => ts.flattenDiagnosticMessageText(error.messageText, `
|
|
21
|
+
`)).join(`
|
|
22
|
+
`);
|
|
23
|
+
throw new Error(`Error parsing tsconfig.json:
|
|
24
|
+
${errorMessages}`);
|
|
25
|
+
}
|
|
26
|
+
this.config = parsedConfig;
|
|
27
|
+
}
|
|
28
|
+
#findConfigFile(searchPath) {
|
|
29
|
+
return ts.findConfigFile(searchPath, (fileName) => ts.sys.fileExists(fileName), "tsconfig.json");
|
|
30
|
+
}
|
|
31
|
+
check(filePath) {
|
|
32
|
+
const program = ts.createProgram([filePath], this.config.options);
|
|
33
|
+
const diagnostics = [
|
|
34
|
+
...program.getSemanticDiagnostics(),
|
|
35
|
+
...program.getSyntacticDiagnostics(),
|
|
36
|
+
...this.config.options.declaration ? program.getDeclarationDiagnostics() : []
|
|
37
|
+
];
|
|
38
|
+
const errors = diagnostics.filter((diagnostic) => diagnostic.category === ts.DiagnosticCategory.Error);
|
|
39
|
+
const warnings = diagnostics.filter((diagnostic) => diagnostic.category === ts.DiagnosticCategory.Warning);
|
|
40
|
+
const fileDiagnostics = diagnostics.filter((diagnostic) => diagnostic.file?.fileName === filePath);
|
|
41
|
+
const fileErrors = fileDiagnostics.filter((diagnostic) => diagnostic.category === ts.DiagnosticCategory.Error);
|
|
42
|
+
const fileWarnings = fileDiagnostics.filter((diagnostic) => diagnostic.category === ts.DiagnosticCategory.Warning);
|
|
43
|
+
return { diagnostics, errors, warnings, fileDiagnostics, fileErrors, fileWarnings };
|
|
44
|
+
}
|
|
45
|
+
formatDiagnostics(diagnostics) {
|
|
46
|
+
if (diagnostics.length === 0)
|
|
47
|
+
return chalk.bold("\u2705 No type errors found");
|
|
48
|
+
const output = [];
|
|
49
|
+
let errorCount = 0;
|
|
50
|
+
let warningCount = 0;
|
|
51
|
+
let suggestionCount = 0;
|
|
52
|
+
const diagnosticsByFile = new Map;
|
|
53
|
+
diagnostics.forEach((diagnostic) => {
|
|
54
|
+
if (diagnostic.category === ts.DiagnosticCategory.Error)
|
|
55
|
+
errorCount++;
|
|
56
|
+
else if (diagnostic.category === ts.DiagnosticCategory.Warning)
|
|
57
|
+
warningCount++;
|
|
58
|
+
else if (diagnostic.category === ts.DiagnosticCategory.Suggestion)
|
|
59
|
+
suggestionCount++;
|
|
60
|
+
if (diagnostic.file) {
|
|
61
|
+
const fileName = diagnostic.file.fileName;
|
|
62
|
+
if (!diagnosticsByFile.has(fileName))
|
|
63
|
+
diagnosticsByFile.set(fileName, []);
|
|
64
|
+
const fileDiagnostics = diagnosticsByFile.get(fileName);
|
|
65
|
+
if (fileDiagnostics)
|
|
66
|
+
fileDiagnostics.push(diagnostic);
|
|
67
|
+
} else {
|
|
68
|
+
if (!diagnosticsByFile.has(""))
|
|
69
|
+
diagnosticsByFile.set("", []);
|
|
70
|
+
const fileDiagnostics = diagnosticsByFile.get("");
|
|
71
|
+
if (fileDiagnostics)
|
|
72
|
+
fileDiagnostics.push(diagnostic);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
diagnosticsByFile.forEach((fileDiagnostics, fileName) => {
|
|
76
|
+
if (fileName)
|
|
77
|
+
output.push(`
|
|
78
|
+
${chalk.cyan(fileName)}`);
|
|
79
|
+
fileDiagnostics.forEach((diagnostic) => {
|
|
80
|
+
const categoryText = diagnostic.category === ts.DiagnosticCategory.Error ? "error" : diagnostic.category === ts.DiagnosticCategory.Warning ? "warning" : "suggestion";
|
|
81
|
+
const categoryColor = diagnostic.category === ts.DiagnosticCategory.Error ? chalk.red : diagnostic.category === ts.DiagnosticCategory.Warning ? chalk.yellow : chalk.blue;
|
|
82
|
+
const icon = diagnostic.category === ts.DiagnosticCategory.Error ? "\u274C" : diagnostic.category === ts.DiagnosticCategory.Warning ? "\u26A0\uFE0F" : "\uD83D\uDCA1";
|
|
83
|
+
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, `
|
|
84
|
+
`);
|
|
85
|
+
const tsCode = chalk.dim(`(TS${diagnostic.code})`);
|
|
86
|
+
if (diagnostic.file && diagnostic.start !== undefined) {
|
|
87
|
+
const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
|
|
88
|
+
output.push(`
|
|
89
|
+
${icon} ${categoryColor(categoryText)}: ${message} ${tsCode}`);
|
|
90
|
+
output.push(` ${chalk.gray("at")} ${fileName}:${chalk.bold(`${line + 1}:${character + 1}`)}`);
|
|
91
|
+
const sourceLines = diagnostic.file.text.split(`
|
|
92
|
+
`);
|
|
93
|
+
if (line < sourceLines.length) {
|
|
94
|
+
const sourceLine = sourceLines[line];
|
|
95
|
+
const lineNumber = (line + 1).toString().padStart(5, " ");
|
|
96
|
+
output.push(`
|
|
97
|
+
${chalk.dim(`${lineNumber} |`)} ${sourceLine}`);
|
|
98
|
+
const underlinePrefix = " ".repeat(character);
|
|
99
|
+
const length = diagnostic.length ?? 1;
|
|
100
|
+
const underline = "~".repeat(Math.max(1, length));
|
|
101
|
+
output.push(`${chalk.dim(`${" ".repeat(lineNumber.length)} |`)} ${underlinePrefix}${categoryColor(underline)}`);
|
|
102
|
+
}
|
|
103
|
+
} else
|
|
104
|
+
output.push(`
|
|
105
|
+
${icon} ${categoryColor(categoryText)}: ${message} ${tsCode}`);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
const summary = [];
|
|
109
|
+
if (errorCount > 0)
|
|
110
|
+
summary.push(chalk.red(`${errorCount} error(s)`));
|
|
111
|
+
if (warningCount > 0)
|
|
112
|
+
summary.push(chalk.yellow(`${warningCount} warning(s)`));
|
|
113
|
+
if (suggestionCount > 0)
|
|
114
|
+
summary.push(chalk.blue(`${suggestionCount} suggestion(s)`));
|
|
115
|
+
return `
|
|
116
|
+
${summary.join(", ")} found${output.join(`
|
|
117
|
+
`)}`;
|
|
118
|
+
}
|
|
119
|
+
getDetailedDiagnostics(filePath) {
|
|
120
|
+
const { diagnostics } = this.check(filePath);
|
|
121
|
+
const sourceFile = ts.createSourceFile(filePath, readFileSync(filePath, "utf8"), ts.ScriptTarget.Latest, true);
|
|
122
|
+
const details = diagnostics.map((diagnostic) => {
|
|
123
|
+
if (diagnostic.file && diagnostic.start !== undefined) {
|
|
124
|
+
const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
|
|
125
|
+
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, `
|
|
126
|
+
`);
|
|
127
|
+
const lines = sourceFile.text.split(`
|
|
128
|
+
`);
|
|
129
|
+
const codeSnippet = line < lines.length ? lines[line] : undefined;
|
|
130
|
+
return { line: line + 1, column: character + 1, message, code: diagnostic.code, codeSnippet };
|
|
131
|
+
}
|
|
132
|
+
return {
|
|
133
|
+
line: 0,
|
|
134
|
+
column: 0,
|
|
135
|
+
message: ts.flattenDiagnosticMessageText(diagnostic.messageText, `
|
|
136
|
+
`),
|
|
137
|
+
code: diagnostic.code
|
|
138
|
+
};
|
|
139
|
+
});
|
|
140
|
+
return { diagnostics, details };
|
|
141
|
+
}
|
|
142
|
+
hasNoTypeErrors(filePath) {
|
|
143
|
+
try {
|
|
144
|
+
const { diagnostics } = this.check(filePath);
|
|
145
|
+
return diagnostics.length === 0;
|
|
146
|
+
} catch (error) {
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
static checkProject(configPath) {
|
|
151
|
+
const parsedConfig = TypeChecker.parseConfig(configPath);
|
|
152
|
+
const host = ts.createIncrementalCompilerHost(parsedConfig.options);
|
|
153
|
+
const builderProgram = ts.createIncrementalProgram({
|
|
154
|
+
rootNames: parsedConfig.fileNames,
|
|
155
|
+
options: parsedConfig.options,
|
|
156
|
+
projectReferences: parsedConfig.projectReferences,
|
|
157
|
+
configFileParsingDiagnostics: parsedConfig.errors,
|
|
158
|
+
host
|
|
159
|
+
});
|
|
160
|
+
const program = builderProgram.getProgram();
|
|
161
|
+
const diagnostics = [...ts.getPreEmitDiagnostics(program), ...builderProgram.emit().diagnostics];
|
|
162
|
+
const errors = diagnostics.filter((diagnostic) => diagnostic.category === ts.DiagnosticCategory.Error);
|
|
163
|
+
const warnings = diagnostics.filter((diagnostic) => diagnostic.category === ts.DiagnosticCategory.Warning);
|
|
164
|
+
return {
|
|
165
|
+
configPath,
|
|
166
|
+
diagnostics,
|
|
167
|
+
errors,
|
|
168
|
+
warnings,
|
|
169
|
+
message: TypeChecker.formatDiagnosticMessages(diagnostics)
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
static parseConfig(configPath) {
|
|
173
|
+
const configFile = ts.readConfigFile(configPath, (fileName) => ts.sys.readFile(fileName));
|
|
174
|
+
const configDiagnostics = configFile.error ? [configFile.error] : [];
|
|
175
|
+
if (!configFile.config) {
|
|
176
|
+
const message = TypeChecker.formatDiagnosticMessages(configDiagnostics);
|
|
177
|
+
throw new Error(message || `Error reading tsconfig.json: ${configPath}`);
|
|
178
|
+
}
|
|
179
|
+
const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, path.dirname(configPath), undefined, configPath);
|
|
180
|
+
if (parsedConfig.errors.length > 0)
|
|
181
|
+
throw new Error(TypeChecker.formatDiagnosticMessages(parsedConfig.errors));
|
|
182
|
+
return parsedConfig;
|
|
183
|
+
}
|
|
184
|
+
static formatDiagnosticMessages(diagnostics) {
|
|
185
|
+
return ts.formatDiagnosticsWithColorAndContext(diagnostics, {
|
|
186
|
+
getCanonicalFileName: (fileName) => fileName,
|
|
187
|
+
getCurrentDirectory: () => process.cwd(),
|
|
188
|
+
getNewLine: () => ts.sys.newLine
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export { TypeChecker };
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
runner,
|
|
4
|
+
script
|
|
5
|
+
} from "./index-hdqztm58.js";
|
|
6
|
+
import {
|
|
7
|
+
PkgExecutor
|
|
8
|
+
} from "./index-a6sbyy0b.js";
|
|
9
|
+
import {
|
|
10
|
+
TypeScriptDependencyScanner
|
|
11
|
+
} from "./index-x53a5nya.js";
|
|
12
|
+
import {
|
|
13
|
+
FileSys
|
|
14
|
+
} from "./index-61keag0s.js";
|
|
15
|
+
|
|
16
|
+
// pkgs/@akanjs/cli/package/package.runner.ts
|
|
17
|
+
import path from "path";
|
|
18
|
+
import { Logger } from "akanjs/common";
|
|
19
|
+
var {$ } = globalThis.Bun;
|
|
20
|
+
|
|
21
|
+
class PackageRunner extends runner("package") {
|
|
22
|
+
static publishableAkanPackages = [
|
|
23
|
+
"akanjs",
|
|
24
|
+
"@akanjs/cli",
|
|
25
|
+
"@akanjs/devkit",
|
|
26
|
+
"create-akan-workspace"
|
|
27
|
+
];
|
|
28
|
+
async version(workspace, { log = true } = {}) {
|
|
29
|
+
const pkgJson = process.env.USE_AKANJS_PKGS === "true" ? await FileSys.readJson(`${workspace?.workspaceRoot ?? process.cwd()}/pkgs/akanjs/package.json`) : await this.#getInstalledPackageJson();
|
|
30
|
+
const version = pkgJson.name === "akanjs" ? pkgJson.version : pkgJson.dependencies?.akanjs ?? pkgJson.version;
|
|
31
|
+
if (log)
|
|
32
|
+
Logger.rawLog(`akanjs@${version}`);
|
|
33
|
+
return version;
|
|
34
|
+
}
|
|
35
|
+
async#getInstalledPackageJson() {
|
|
36
|
+
const packageJsonCandidates = [
|
|
37
|
+
`${path.dirname(Bun.main)}/package.json`,
|
|
38
|
+
`${process.cwd()}/node_modules/akanjs/package.json`
|
|
39
|
+
];
|
|
40
|
+
try {
|
|
41
|
+
packageJsonCandidates.unshift(Bun.resolveSync("akanjs/package.json", path.dirname(Bun.main)));
|
|
42
|
+
} catch {}
|
|
43
|
+
for (const packageJsonPath of packageJsonCandidates) {
|
|
44
|
+
if (!await Bun.file(packageJsonPath).exists())
|
|
45
|
+
continue;
|
|
46
|
+
const packageJson = await FileSys.readJson(packageJsonPath);
|
|
47
|
+
if (packageJson.name === "akanjs" || packageJson.name === "@akanjs/cli")
|
|
48
|
+
return packageJson;
|
|
49
|
+
}
|
|
50
|
+
throw new Error(`[package] failed to locate akanjs package.json from ${path.dirname(Bun.main)}`);
|
|
51
|
+
}
|
|
52
|
+
async createPackage(workspace, pkgName) {
|
|
53
|
+
await workspace.applyTemplate({ basePath: `pkgs/${pkgName}`, template: "pkgRoot", dict: { pkgName } });
|
|
54
|
+
await workspace.setPkgTsPaths(pkgName);
|
|
55
|
+
}
|
|
56
|
+
async removePackage(pkg) {
|
|
57
|
+
await pkg.workspace.exec(`rm -rf pkgs/${pkg.name}`);
|
|
58
|
+
await pkg.workspace.unsetPkgTsPaths(pkg.name);
|
|
59
|
+
}
|
|
60
|
+
async scanSync(pkg) {
|
|
61
|
+
const scanResult = await pkg.scan();
|
|
62
|
+
return scanResult;
|
|
63
|
+
}
|
|
64
|
+
async buildPackage(pkg) {
|
|
65
|
+
await $`rm -rf ${pkg.dist.cwdPath}`;
|
|
66
|
+
await pkg.dist.mkdir(pkg.dist.cwdPath);
|
|
67
|
+
const scanner = await TypeScriptDependencyScanner.from(pkg);
|
|
68
|
+
const { npmDeps, npmDevDeps, missingDeps } = await scanner.getPackageBuildDependencies(pkg.name);
|
|
69
|
+
const packageRuntimeDependencies = {
|
|
70
|
+
"@akanjs/devkit": ["daisyui", "tailwind-scrollbar"]
|
|
71
|
+
};
|
|
72
|
+
const packageRuntimeDevDependencies = { akanjs: ["@biomejs/biome", "@types/bun"] };
|
|
73
|
+
if (pkg.name === "@akanjs/cli") {
|
|
74
|
+
const devkitPackageJson = await pkg.workspace.readJson("pkgs/@akanjs/devkit/package.json");
|
|
75
|
+
packageRuntimeDependencies[pkg.name] = [
|
|
76
|
+
...Object.keys(devkitPackageJson.dependencies ?? {}),
|
|
77
|
+
"daisyui",
|
|
78
|
+
"tailwind-scrollbar"
|
|
79
|
+
].filter((dep) => dep !== "akanjs" && dep !== "@akanjs/devkit");
|
|
80
|
+
}
|
|
81
|
+
const bundledRuntimeDeps = new Set(pkg.name === "@akanjs/cli" ? ["@akanjs/devkit"] : []);
|
|
82
|
+
const forcedRuntimeDeps = packageRuntimeDependencies[pkg.name] ?? [];
|
|
83
|
+
const forcedRuntimeDevDeps = packageRuntimeDevDependencies[pkg.name] ?? [];
|
|
84
|
+
const [rootPackageJson, pkgJson] = await Promise.all([pkg.workspace.getPackageJson(), pkg.getPackageJson()]);
|
|
85
|
+
const optionalPeerDeps = new Set(Object.entries(pkgJson.peerDependenciesMeta ?? {}).filter(([, meta]) => meta.optional).map(([dep]) => dep));
|
|
86
|
+
const packageRuntimeDeps = [...new Set([...npmDeps, ...forcedRuntimeDeps])].filter((dep) => !optionalPeerDeps.has(dep) && !bundledRuntimeDeps.has(dep));
|
|
87
|
+
const packageRuntimeDevDeps = [...new Set([...npmDevDeps, ...forcedRuntimeDevDeps])].filter((dep) => !optionalPeerDeps.has(dep));
|
|
88
|
+
const rootDeps = { ...rootPackageJson.dependencies, ...rootPackageJson.devDependencies };
|
|
89
|
+
const missingForcedDeps = forcedRuntimeDeps.filter((dep) => !rootDeps[dep]);
|
|
90
|
+
const missingForcedDevDeps = forcedRuntimeDevDeps.filter((dep) => !rootDeps[dep]);
|
|
91
|
+
const requiredMissingDeps = missingDeps.filter((dep) => !optionalPeerDeps.has(dep));
|
|
92
|
+
const allMissingDeps = [...new Set([...requiredMissingDeps, ...missingForcedDeps, ...missingForcedDevDeps])].sort();
|
|
93
|
+
if (allMissingDeps.length > 0)
|
|
94
|
+
throw new Error(`Missing dependency versions in root package.json: ${allMissingDeps.join(", ")}`);
|
|
95
|
+
await pkg.updatePackageJsonDependencies(packageRuntimeDeps, packageRuntimeDevDeps);
|
|
96
|
+
const hasBuildFile = await Bun.file(`${pkg.cwdPath}/build.ts`).exists();
|
|
97
|
+
if (hasBuildFile) {
|
|
98
|
+
await pkg.workspace.spawn(process.execPath, [`${pkg.cwdPath}/build.ts`], {
|
|
99
|
+
env: {
|
|
100
|
+
...process.env,
|
|
101
|
+
...pkg.name === "akanjs" ? { AKAN_BUILD_DECLARATION_DIAGNOSTICS: "error" } : {}
|
|
102
|
+
},
|
|
103
|
+
stdio: "inherit"
|
|
104
|
+
});
|
|
105
|
+
} else {
|
|
106
|
+
await $`cp -r ${pkg.cwdPath}/. ${pkg.dist.cwdPath}`;
|
|
107
|
+
await Promise.all([
|
|
108
|
+
pkg.generateDistPackageJson(packageRuntimeDeps, packageRuntimeDevDeps),
|
|
109
|
+
pkg.generateTsconfigJson()
|
|
110
|
+
]);
|
|
111
|
+
}
|
|
112
|
+
await this.#copyPackageReadmes(pkg);
|
|
113
|
+
}
|
|
114
|
+
async verifyDistPackage(pkg) {
|
|
115
|
+
const distPackageJsonPath = `${pkg.dist.cwdPath}/package.json`;
|
|
116
|
+
if (!await Bun.file(distPackageJsonPath).exists()) {
|
|
117
|
+
throw new Error(`[package] dist package not found for ${pkg.name}. Run build-package first.`);
|
|
118
|
+
}
|
|
119
|
+
const pkgJson = await FileSys.readJson(distPackageJsonPath);
|
|
120
|
+
if (pkgJson.name !== pkg.name) {
|
|
121
|
+
throw new Error(`[package] dist package name mismatch: expected ${pkg.name}, got ${pkgJson.name ?? "(missing)"}`);
|
|
122
|
+
}
|
|
123
|
+
if (!pkgJson.version)
|
|
124
|
+
throw new Error(`[package] dist package version is missing for ${pkg.name}`);
|
|
125
|
+
if (!pkgJson.publishConfig || pkgJson.publishConfig.access !== "public") {
|
|
126
|
+
throw new Error(`[package] ${pkg.name} must publish with publishConfig.access=public`);
|
|
127
|
+
}
|
|
128
|
+
if (!await Bun.file(`${pkg.dist.cwdPath}/README.md`).exists()) {
|
|
129
|
+
throw new Error(`[package] README.md is missing from dist package ${pkg.name}`);
|
|
130
|
+
}
|
|
131
|
+
if (!await Bun.file(`${pkg.dist.cwdPath}/README.ko.md`).exists()) {
|
|
132
|
+
throw new Error(`[package] README.ko.md is missing from dist package ${pkg.name}`);
|
|
133
|
+
}
|
|
134
|
+
const binEntries = typeof pkgJson.bin === "string" ? [pkgJson.bin] : Object.values(pkgJson.bin ?? {});
|
|
135
|
+
if (binEntries.some((binPath) => binPath.endsWith(".ts"))) {
|
|
136
|
+
throw new Error(`[package] ${pkg.name} dist bin entries must not point at TypeScript sources`);
|
|
137
|
+
}
|
|
138
|
+
if (pkg.name === "akanjs") {
|
|
139
|
+
const exports = pkgJson.exports;
|
|
140
|
+
const rootExport = exports?.["."];
|
|
141
|
+
if (!rootExport?.types?.startsWith("./types/")) {
|
|
142
|
+
throw new Error("[package] akanjs dist exports must point type declarations at ./types");
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
const packOutput = await pkg.workspace.spawn("npm", ["pack", "--dry-run", "--json", pkg.dist.cwdPath], {
|
|
146
|
+
cwd: pkg.workspace.workspaceRoot
|
|
147
|
+
});
|
|
148
|
+
const [packResult] = JSON.parse(packOutput);
|
|
149
|
+
return {
|
|
150
|
+
name: pkg.name,
|
|
151
|
+
version: pkgJson.version,
|
|
152
|
+
files: packResult?.files?.length ?? 0,
|
|
153
|
+
size: packResult?.size ?? 0
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
async verifyAkanPublishPackages(workspace) {
|
|
157
|
+
const results = [];
|
|
158
|
+
for (const pkgName of PackageRunner.publishableAkanPackages) {
|
|
159
|
+
results.push(await this.verifyDistPackage(PkgExecutor.from(workspace, pkgName)));
|
|
160
|
+
}
|
|
161
|
+
return results;
|
|
162
|
+
}
|
|
163
|
+
async#copyPackageReadmes(pkg) {
|
|
164
|
+
await Promise.all(["README.md", "README.ko.md"].map((fileName) => pkg.cp(fileName, `${pkg.dist.cwdPath}/${fileName}`)));
|
|
165
|
+
}
|
|
166
|
+
async updateWorskpaceRootPackageJson(workspace, rootPackageJson) {
|
|
167
|
+
const templatePath = "pkgs/@akanjs/cli/templates/workspaceRoot/package.json.template";
|
|
168
|
+
const pkgJsonTemplate = await workspace.readJson(templatePath);
|
|
169
|
+
const { dependencies = {}, devDependencies = {} } = pkgJsonTemplate;
|
|
170
|
+
const newRootPackageJson = {
|
|
171
|
+
...pkgJsonTemplate,
|
|
172
|
+
dependencies: Object.fromEntries(Object.entries(dependencies).map(([key, value]) => [key, rootPackageJson.dependencies?.[key] ?? value])),
|
|
173
|
+
devDependencies: Object.fromEntries(Object.entries(devDependencies).map(([key, value]) => [key, rootPackageJson.devDependencies?.[key] ?? value]))
|
|
174
|
+
};
|
|
175
|
+
await workspace.writeJson(templatePath, newRootPackageJson);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// pkgs/@akanjs/cli/package/package.script.ts
|
|
180
|
+
class PackageScript extends script("package", [PackageRunner]) {
|
|
181
|
+
async version(workspace, { log = true } = {}) {
|
|
182
|
+
return await this.packageRunner.version(workspace, { log });
|
|
183
|
+
}
|
|
184
|
+
async createPackage(workspace, pkgName) {
|
|
185
|
+
const spinner = workspace.spinning(`Creating package in pkgs/${pkgName}...`);
|
|
186
|
+
await this.packageRunner.createPackage(workspace, pkgName);
|
|
187
|
+
spinner.succeed(`Package in pkgs/${pkgName} is created`);
|
|
188
|
+
}
|
|
189
|
+
async removePackage(pkg) {
|
|
190
|
+
const spinner = pkg.spinning(`Removing package in pkgs/${pkg.name}...`);
|
|
191
|
+
await this.packageRunner.removePackage(pkg);
|
|
192
|
+
spinner.succeed("Package removed");
|
|
193
|
+
}
|
|
194
|
+
async syncPackage(pkg) {
|
|
195
|
+
const spinner = pkg.spinning("Scanning package...");
|
|
196
|
+
const scanResult = await this.packageRunner.scanSync(pkg);
|
|
197
|
+
spinner.succeed("Package scanned");
|
|
198
|
+
return scanResult;
|
|
199
|
+
}
|
|
200
|
+
async buildPackage(pkg, { showSpinner = true } = {}) {
|
|
201
|
+
const spinner = showSpinner ? pkg.spinning("Building package...") : undefined;
|
|
202
|
+
await this.packageRunner.buildPackage(pkg);
|
|
203
|
+
if (spinner)
|
|
204
|
+
spinner.succeed("Package built");
|
|
205
|
+
}
|
|
206
|
+
async verifyDistPackage(pkg) {
|
|
207
|
+
const spinner = pkg.spinning("Verifying dist package...");
|
|
208
|
+
const result = await this.packageRunner.verifyDistPackage(pkg);
|
|
209
|
+
spinner.succeed(`Package verified (${result.files} files, ${result.size} bytes packed)`);
|
|
210
|
+
return result;
|
|
211
|
+
}
|
|
212
|
+
async verifyAkanPublishPackages(workspace) {
|
|
213
|
+
const spinner = workspace.spinning("Verifying Akan publish packages...");
|
|
214
|
+
const results = await this.packageRunner.verifyAkanPublishPackages(workspace);
|
|
215
|
+
spinner.succeed(`Akan publish packages verified (${results.length} packages)`);
|
|
216
|
+
return results;
|
|
217
|
+
}
|
|
218
|
+
async updateWorskpaceRootPackageJson(workspace) {
|
|
219
|
+
const rootPackageJson = await workspace.getPackageJson();
|
|
220
|
+
await this.packageRunner.updateWorskpaceRootPackageJson(workspace, rootPackageJson);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export { PackageScript };
|