@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,301 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
FileSys
|
|
4
|
+
} from "./index-61keag0s.js";
|
|
5
|
+
|
|
6
|
+
// pkgs/@akanjs/devkit/dependencyScanner.ts
|
|
7
|
+
import { builtinModules } from "module";
|
|
8
|
+
import * as path from "path";
|
|
9
|
+
import ignore from "ignore";
|
|
10
|
+
import ts from "typescript";
|
|
11
|
+
var testFileRegex = /\.(?:test|spec)\.[cm]?[tj]sx?$/;
|
|
12
|
+
var builtinModuleSet = new Set([...builtinModules, ...builtinModules.map((mod) => `node:${mod}`)]);
|
|
13
|
+
var stripShebang = (source) => source.replace(/^#!.*(?:\r?\n|$)/, "");
|
|
14
|
+
|
|
15
|
+
class TypeScriptDependencyScanner {
|
|
16
|
+
#fileDependencies = new Map;
|
|
17
|
+
#fileRuntimeDependencies = new Map;
|
|
18
|
+
#fileTypeDependencies = new Map;
|
|
19
|
+
#visitedFiles = new Set;
|
|
20
|
+
#tsTranspiler = new Bun.Transpiler({ loader: "ts" });
|
|
21
|
+
#tsxTranspiler = new Bun.Transpiler({ loader: "tsx" });
|
|
22
|
+
directory;
|
|
23
|
+
rootPackageJson;
|
|
24
|
+
ig;
|
|
25
|
+
workspaceRoot;
|
|
26
|
+
constructor(directory, {
|
|
27
|
+
workspaceRoot,
|
|
28
|
+
rootPackageJson,
|
|
29
|
+
gitignorePatterns = []
|
|
30
|
+
}) {
|
|
31
|
+
this.directory = directory;
|
|
32
|
+
this.rootPackageJson = rootPackageJson;
|
|
33
|
+
this.ig = ignore().add(gitignorePatterns);
|
|
34
|
+
this.workspaceRoot = workspaceRoot;
|
|
35
|
+
}
|
|
36
|
+
async getMonorepoDependencies(projectName, { pkgs = [], libs = [] } = {}) {
|
|
37
|
+
const npmSet = new Set(Object.keys({ ...this.rootPackageJson.dependencies, ...this.rootPackageJson.devDependencies }));
|
|
38
|
+
const pkgPathSet = new Set(pkgs);
|
|
39
|
+
const libPathSet = new Set(libs.map((lib) => `@libs/${lib}`));
|
|
40
|
+
await this.getDependencies();
|
|
41
|
+
const [npmDepSet, pkgPathDepSet, libPathDepSet] = this.#getImportSetsFromDependencies([npmSet, pkgPathSet, libPathSet], this.#fileRuntimeDependencies);
|
|
42
|
+
const [npmDevDepSet] = this.#getImportSetsFromDependencies([npmSet], this.#fileTypeDependencies);
|
|
43
|
+
const pkgDeps = [...pkgPathDepSet];
|
|
44
|
+
const libDeps = [...libPathDepSet].map((path2) => path2.replace("@libs/", "")).filter((libName) => libName !== projectName);
|
|
45
|
+
return {
|
|
46
|
+
pkgDeps,
|
|
47
|
+
libDeps,
|
|
48
|
+
npmDeps: [...npmDepSet],
|
|
49
|
+
npmDevDeps: [...npmDevDepSet].filter((dep) => !npmDepSet.has(dep))
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
async getPackageBuildDependencies(projectName) {
|
|
53
|
+
const runtimeDeps = new Set;
|
|
54
|
+
const devDeps = new Set;
|
|
55
|
+
const sourceFiles = await this.#findTypeScriptFiles(this.directory, {
|
|
56
|
+
excludeBuildFiles: true,
|
|
57
|
+
excludeTestFiles: true
|
|
58
|
+
});
|
|
59
|
+
const cssFiles = await this.#findCssFiles(this.directory);
|
|
60
|
+
for (const filePath of sourceFiles) {
|
|
61
|
+
const fileContent = await FileSys.readText(filePath);
|
|
62
|
+
const { imports, typeImports } = this.#extractImports(fileContent, filePath);
|
|
63
|
+
this.#addNormalizedImports(runtimeDeps, imports, projectName);
|
|
64
|
+
this.#addNormalizedImports(devDeps, typeImports, projectName);
|
|
65
|
+
}
|
|
66
|
+
for (const filePath of cssFiles) {
|
|
67
|
+
const fileContent = await FileSys.readText(filePath);
|
|
68
|
+
this.#addNormalizedImports(runtimeDeps, this.#extractCssPluginImports(fileContent), projectName);
|
|
69
|
+
}
|
|
70
|
+
const buildFilePath = path.join(this.directory, "build.ts");
|
|
71
|
+
if (await FileSys.fileExists(buildFilePath)) {
|
|
72
|
+
const fileContent = await FileSys.readText(buildFilePath);
|
|
73
|
+
const { imports, typeImports } = this.#extractImports(fileContent, buildFilePath);
|
|
74
|
+
this.#addNormalizedImports(devDeps, [...imports, ...typeImports], projectName);
|
|
75
|
+
}
|
|
76
|
+
for (const dep of runtimeDeps)
|
|
77
|
+
devDeps.delete(dep);
|
|
78
|
+
const rootDeps = { ...this.rootPackageJson.dependencies, ...this.rootPackageJson.devDependencies };
|
|
79
|
+
const missingDeps = [];
|
|
80
|
+
for (const dep of [...runtimeDeps, ...devDeps]) {
|
|
81
|
+
if (rootDeps[dep] || await this.#hasWorkspacePackage(dep))
|
|
82
|
+
continue;
|
|
83
|
+
missingDeps.push(dep);
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
npmDeps: [...runtimeDeps].sort(),
|
|
87
|
+
npmDevDeps: [...devDeps].sort(),
|
|
88
|
+
missingDeps: missingDeps.sort()
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
async#hasWorkspacePackage(dep) {
|
|
92
|
+
const packageJsonPath = path.join(this.workspaceRoot, "pkgs", dep, "package.json");
|
|
93
|
+
if (!await Bun.file(packageJsonPath).exists())
|
|
94
|
+
return false;
|
|
95
|
+
try {
|
|
96
|
+
const packageJson = await FileSys.readJson(packageJsonPath);
|
|
97
|
+
return packageJson.name === dep && !!packageJson.version;
|
|
98
|
+
} catch {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
async getImportSets(depSets) {
|
|
103
|
+
const fileDependencies = await this.getDependencies();
|
|
104
|
+
return this.#getImportSetsFromDependencies(depSets, fileDependencies);
|
|
105
|
+
}
|
|
106
|
+
#getImportSetsFromDependencies(depSets, fileDependencies) {
|
|
107
|
+
const importedDepSets = new Array(depSets.length);
|
|
108
|
+
for (let i = 0;i < depSets.length; i++)
|
|
109
|
+
importedDepSets[i] = new Set;
|
|
110
|
+
fileDependencies.forEach((imps) => {
|
|
111
|
+
imps.forEach((imp) => {
|
|
112
|
+
if (imp.startsWith("."))
|
|
113
|
+
return;
|
|
114
|
+
const moduleName = imp;
|
|
115
|
+
const moduleNameParts = moduleName.split("/");
|
|
116
|
+
const subModuleLength = moduleNameParts.length;
|
|
117
|
+
for (let i = 0;i < subModuleLength; i++) {
|
|
118
|
+
const importName = moduleNameParts.slice(0, i + 1).join("/");
|
|
119
|
+
for (let j = 0;j < depSets.length; j++) {
|
|
120
|
+
if (depSets[j]?.has(importName)) {
|
|
121
|
+
importedDepSets[j]?.add(importName);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
return importedDepSets;
|
|
129
|
+
}
|
|
130
|
+
async getDependencies() {
|
|
131
|
+
this.#fileDependencies.clear();
|
|
132
|
+
this.#fileRuntimeDependencies.clear();
|
|
133
|
+
this.#fileTypeDependencies.clear();
|
|
134
|
+
this.#visitedFiles.clear();
|
|
135
|
+
const files = await this.#findTypeScriptFiles(this.directory);
|
|
136
|
+
for (const file of files)
|
|
137
|
+
await this.#analyzeFile(file, this.directory);
|
|
138
|
+
return this.#fileDependencies;
|
|
139
|
+
}
|
|
140
|
+
async#findTypeScriptFiles(directory, {
|
|
141
|
+
excludeBuildFiles = false,
|
|
142
|
+
excludeTestFiles = false
|
|
143
|
+
} = {}) {
|
|
144
|
+
const files = [];
|
|
145
|
+
const skipDirs = ["node_modules", "dist", "build", ".git", ".next", "public", "ios", "android"];
|
|
146
|
+
const glob = new Bun.Glob("**/*.{ts,tsx}");
|
|
147
|
+
for await (const filePath of glob.scan({ cwd: directory, onlyFiles: true })) {
|
|
148
|
+
if (skipDirs.some((dir) => filePath.includes(`/${dir}/`) || filePath.startsWith(`${dir}/`)))
|
|
149
|
+
continue;
|
|
150
|
+
if (excludeBuildFiles && filePath === "build.ts")
|
|
151
|
+
continue;
|
|
152
|
+
if (excludeTestFiles && testFileRegex.test(filePath))
|
|
153
|
+
continue;
|
|
154
|
+
const fullPath = path.join(directory, filePath);
|
|
155
|
+
const relativePath = path.relative(this.workspaceRoot, fullPath);
|
|
156
|
+
if (this.ig.ignores(relativePath))
|
|
157
|
+
continue;
|
|
158
|
+
files.push(fullPath);
|
|
159
|
+
}
|
|
160
|
+
return files;
|
|
161
|
+
}
|
|
162
|
+
async#findCssFiles(directory) {
|
|
163
|
+
const files = [];
|
|
164
|
+
const skipDirs = ["node_modules", "dist", "build", ".git", ".next", "public", "ios", "android"];
|
|
165
|
+
const glob = new Bun.Glob("**/*.css");
|
|
166
|
+
for await (const filePath of glob.scan({ cwd: directory, onlyFiles: true })) {
|
|
167
|
+
if (skipDirs.some((dir) => filePath.includes(`/${dir}/`) || filePath.startsWith(`${dir}/`)))
|
|
168
|
+
continue;
|
|
169
|
+
const fullPath = path.join(directory, filePath);
|
|
170
|
+
const relativePath = path.relative(this.workspaceRoot, fullPath);
|
|
171
|
+
if (this.ig.ignores(relativePath))
|
|
172
|
+
continue;
|
|
173
|
+
files.push(fullPath);
|
|
174
|
+
}
|
|
175
|
+
return files;
|
|
176
|
+
}
|
|
177
|
+
async#analyzeFile(filePath, baseDir) {
|
|
178
|
+
if (this.#visitedFiles.has(filePath))
|
|
179
|
+
return;
|
|
180
|
+
this.#visitedFiles.add(filePath);
|
|
181
|
+
try {
|
|
182
|
+
const fileContent = await FileSys.readText(filePath);
|
|
183
|
+
const { imports, typeImports } = this.#extractImports(fileContent, filePath);
|
|
184
|
+
const resolvedImports = await this.#resolveImports(imports, filePath, baseDir);
|
|
185
|
+
const resolvedTypeImports = await this.#resolveImports(typeImports, filePath, baseDir);
|
|
186
|
+
const relativePath = path.relative(baseDir, filePath);
|
|
187
|
+
this.#fileDependencies.set(relativePath, [...new Set([...resolvedImports, ...resolvedTypeImports])]);
|
|
188
|
+
this.#fileRuntimeDependencies.set(relativePath, resolvedImports);
|
|
189
|
+
this.#fileTypeDependencies.set(relativePath, resolvedTypeImports);
|
|
190
|
+
} catch {}
|
|
191
|
+
}
|
|
192
|
+
async#resolveImports(imports, filePath, baseDir) {
|
|
193
|
+
return await Promise.all(imports.map(async (importPath) => {
|
|
194
|
+
if (importPath.startsWith(".")) {
|
|
195
|
+
const resolvedPath = `./${path.join(path.relative(baseDir, filePath), importPath)}`;
|
|
196
|
+
return await this.#ensureExtension(resolvedPath);
|
|
197
|
+
}
|
|
198
|
+
return importPath;
|
|
199
|
+
}));
|
|
200
|
+
}
|
|
201
|
+
async#ensureExtension(filePath) {
|
|
202
|
+
if (await FileSys.fileExists(`${filePath}.ts`))
|
|
203
|
+
return `${filePath}.ts`;
|
|
204
|
+
else if (await FileSys.fileExists(`${filePath}.tsx`))
|
|
205
|
+
return `${filePath}.tsx`;
|
|
206
|
+
else if (await FileSys.fileExists(filePath))
|
|
207
|
+
return filePath;
|
|
208
|
+
return `${filePath}.ts`;
|
|
209
|
+
}
|
|
210
|
+
#extractImports(source, filePath) {
|
|
211
|
+
const transpiler = filePath.endsWith(".tsx") ? this.#tsxTranspiler : this.#tsTranspiler;
|
|
212
|
+
const scanSource = stripShebang(source);
|
|
213
|
+
const imports = new Set(transpiler.scanImports(scanSource).map((imp) => imp.path).filter(Boolean));
|
|
214
|
+
const typeImports = new Set;
|
|
215
|
+
const sourceFile = ts.createSourceFile(filePath, scanSource, ts.ScriptTarget.Latest, true);
|
|
216
|
+
for (const statement of sourceFile.statements) {
|
|
217
|
+
if (!ts.isImportDeclaration(statement))
|
|
218
|
+
continue;
|
|
219
|
+
if (!ts.isStringLiteral(statement.moduleSpecifier))
|
|
220
|
+
continue;
|
|
221
|
+
const importPath = statement.moduleSpecifier.text;
|
|
222
|
+
const namedBindings = statement.importClause?.namedBindings;
|
|
223
|
+
const isNamedTypeOnlyImport = namedBindings && ts.isNamedImports(namedBindings) && namedBindings.elements.length > 0 && namedBindings.elements.every((element) => element.isTypeOnly);
|
|
224
|
+
if ((statement.importClause?.isTypeOnly || isNamedTypeOnlyImport) && !imports.has(importPath)) {
|
|
225
|
+
typeImports.add(importPath);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return { imports: [...imports], typeImports: [...typeImports] };
|
|
229
|
+
}
|
|
230
|
+
#extractCssPluginImports(source) {
|
|
231
|
+
const imports = new Set;
|
|
232
|
+
const pluginRegex = /@plugin\s+(?:url\()?["']([^"')]+)["']\)?/g;
|
|
233
|
+
for (const match of source.matchAll(pluginRegex)) {
|
|
234
|
+
const importPath = match[1];
|
|
235
|
+
if (importPath)
|
|
236
|
+
imports.add(importPath);
|
|
237
|
+
}
|
|
238
|
+
return [...imports];
|
|
239
|
+
}
|
|
240
|
+
#addNormalizedImports(deps, imports, projectName) {
|
|
241
|
+
for (const importPath of imports) {
|
|
242
|
+
const dep = this.#normalizePackageImport(importPath, projectName);
|
|
243
|
+
if (dep)
|
|
244
|
+
deps.add(dep);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
#normalizePackageImport(importPath, projectName) {
|
|
248
|
+
if (importPath.startsWith(".") || importPath.startsWith("/") || importPath.startsWith("#") || importPath.startsWith("bun:") || builtinModuleSet.has(importPath))
|
|
249
|
+
return null;
|
|
250
|
+
const parts = importPath.split("/");
|
|
251
|
+
const packageName = importPath.startsWith("@") ? parts.slice(0, 2).join("/") : parts[0];
|
|
252
|
+
if (!packageName || packageName === projectName || importPath.startsWith(`${projectName}/`))
|
|
253
|
+
return null;
|
|
254
|
+
return packageName;
|
|
255
|
+
}
|
|
256
|
+
generateDependencyGraph() {
|
|
257
|
+
let graph = `Dependency Graph:
|
|
258
|
+
|
|
259
|
+
`;
|
|
260
|
+
for (const [file, imports] of this.#fileDependencies.entries()) {
|
|
261
|
+
graph += `${file}:
|
|
262
|
+
`;
|
|
263
|
+
const projectImports = imports.filter((i) => !i.startsWith("react") && !i.startsWith("@"));
|
|
264
|
+
const externalImports = imports.filter((i) => i.startsWith("react") || i.startsWith("@"));
|
|
265
|
+
if (projectImports.length > 0) {
|
|
266
|
+
graph += ` Project dependencies:
|
|
267
|
+
`;
|
|
268
|
+
projectImports.forEach((imp) => {
|
|
269
|
+
graph += ` \u2192 ${imp}
|
|
270
|
+
`;
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
if (externalImports.length > 0) {
|
|
274
|
+
graph += ` External dependencies:
|
|
275
|
+
`;
|
|
276
|
+
externalImports.forEach((imp) => {
|
|
277
|
+
graph += ` \u2192 ${imp}
|
|
278
|
+
`;
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
graph += `
|
|
282
|
+
`;
|
|
283
|
+
}
|
|
284
|
+
return graph;
|
|
285
|
+
}
|
|
286
|
+
static async from(exec) {
|
|
287
|
+
const [tsconfig, rootPackageJson, gitignorePatterns] = await Promise.all([
|
|
288
|
+
exec.getTsConfig(),
|
|
289
|
+
exec.workspace.getPackageJson(),
|
|
290
|
+
exec.workspace.getGitignorePatterns()
|
|
291
|
+
]);
|
|
292
|
+
return new TypeScriptDependencyScanner(exec.cwdPath, {
|
|
293
|
+
workspaceRoot: exec.workspace.cwdPath,
|
|
294
|
+
tsconfig,
|
|
295
|
+
rootPackageJson,
|
|
296
|
+
gitignorePatterns
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
export { TypeScriptDependencyScanner };
|