@akanjs/cli 2.4.0 → 2.4.1-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/agent.command-h4afc69n.js +26 -0
- package/application.command-47mj9qsy.js +165 -0
- package/applicationBuildRunner-yz144508.js +284 -0
- package/applicationReleasePackager-brvth6rs.js +245 -0
- package/capacitorApp-y0h6cgft.js +58 -0
- package/cloud.command-qgjxja3n.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-77crfweb.js +1884 -0
- package/index-85msc0wg.js +161 -0
- package/index-8pkbzj26.js +840 -0
- package/index-8rc0bm04.js +514 -0
- package/index-a5rmdgy4.js +4359 -0
- package/index-a6sbyy0b.js +2769 -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-sgmas1fc.js +462 -0
- package/index-ss469dec.js +11 -0
- package/index-swf4bmbg.js +25 -0
- package/index-wnp7hwq7.js +193 -0
- package/index-wq8jwx8z.js +224 -0
- package/index-x53a5nya.js +301 -0
- package/index-y3hdhy4p.js +229 -0
- package/index-z9gvz7b0.js +83 -0
- package/index.js +54 -23340
- package/library.command-r15zdqvp.js +33 -0
- package/localRegistry.command-p1pgxw78.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-xk68sd6c.js +435 -0
|
@@ -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 };
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
pluralizeName
|
|
4
|
+
} from "./index-ss469dec.js";
|
|
5
|
+
import {
|
|
6
|
+
Prompter
|
|
7
|
+
} from "./index-qaq13qk3.js";
|
|
8
|
+
import {
|
|
9
|
+
createPassedPrimitiveReport,
|
|
10
|
+
generatedFilesForSync,
|
|
11
|
+
scalarChangedFiles
|
|
12
|
+
} from "./index-h6ca6qg0.js";
|
|
13
|
+
import {
|
|
14
|
+
AiSession
|
|
15
|
+
} from "./index-5vvwc0cz.js";
|
|
16
|
+
import {
|
|
17
|
+
runner,
|
|
18
|
+
script
|
|
19
|
+
} from "./index-hdqztm58.js";
|
|
20
|
+
|
|
21
|
+
// pkgs/@akanjs/cli/scalar/scalar.prompt.ts
|
|
22
|
+
import { input } from "@inquirer/prompts";
|
|
23
|
+
class ScalarPrompt extends Prompter {
|
|
24
|
+
sys;
|
|
25
|
+
name;
|
|
26
|
+
constructor(sys, name) {
|
|
27
|
+
super();
|
|
28
|
+
this.sys = sys;
|
|
29
|
+
this.name = name;
|
|
30
|
+
}
|
|
31
|
+
async requestUpdateConstant() {
|
|
32
|
+
const request = await input({ message: `What do you want to change?` });
|
|
33
|
+
return { request, validate: undefined };
|
|
34
|
+
}
|
|
35
|
+
async requestCreateConstant() {
|
|
36
|
+
const constantFiles = await this.sys.getConstantFilesWithLibs();
|
|
37
|
+
const description = await input({ message: "description of scalar" });
|
|
38
|
+
const schemaDescription = await input({ message: "schema description of scalar" });
|
|
39
|
+
await this.sys.applyTemplate({
|
|
40
|
+
basePath: "./lib/__scalar",
|
|
41
|
+
template: "__scalar",
|
|
42
|
+
dict: { model: this.name, models: pluralizeName(this.name), sysName: this.sys.name }
|
|
43
|
+
});
|
|
44
|
+
const boilerplate = await this.sys.readFile(`lib/__scalar/${this.name}/${this.name}.constant.ts`);
|
|
45
|
+
return await this.#requestConstant({
|
|
46
|
+
modelDesc: description,
|
|
47
|
+
modelSchemaDesign: schemaDescription,
|
|
48
|
+
boilerplate,
|
|
49
|
+
constantFiles
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
async#requestConstant({
|
|
53
|
+
modelDesc,
|
|
54
|
+
modelSchemaDesign,
|
|
55
|
+
boilerplate,
|
|
56
|
+
constantFiles
|
|
57
|
+
}) {
|
|
58
|
+
const scanInfo = await this.sys.scan();
|
|
59
|
+
const guideJson = await Prompter.getGuideJson("scalarConstant");
|
|
60
|
+
const request = await this.makeTsFileUpdatePrompt({
|
|
61
|
+
context: `
|
|
62
|
+
1. Overview of __scalar/<model>/<model>.constant.ts file
|
|
63
|
+
${await this.getDocumentation("scalarConstant")}
|
|
64
|
+
|
|
65
|
+
2. How to write Enums in __scalar/<model>/<model>.constant.ts file
|
|
66
|
+
${await this.getDocumentation("enumConstant")}
|
|
67
|
+
|
|
68
|
+
3. How to write Fields in __scalar/<model>/<model>.constant.ts file
|
|
69
|
+
${await this.getDocumentation("fieldRule")}
|
|
70
|
+
|
|
71
|
+
4. List of constant.ts files in other libraries connected to current ${this.sys.name} ${this.sys.type === "app" ? "Application" : "Library"} ${scanInfo.getLibs().map((lib) => lib).join(", ")}
|
|
72
|
+
Please understand the content and file patterns below, and feel free to reuse any constants or enums if available.
|
|
73
|
+
${constantFiles.map((constant) => `
|
|
74
|
+
\`\`\`typescript
|
|
75
|
+
// File: ${constant.filePath}
|
|
76
|
+
${constant.content}
|
|
77
|
+
\`\`\`
|
|
78
|
+
`).join(`
|
|
79
|
+
`)}
|
|
80
|
+
`,
|
|
81
|
+
request: `
|
|
82
|
+
Based on the above content, please organize it according to the boilerplate below for easy parsing
|
|
83
|
+
|
|
84
|
+
Application name: ${this.sys.name} (${this.sys.type === "app" ? "Application" : "Library"})
|
|
85
|
+
Model name: ${this.name}
|
|
86
|
+
Model description: ${modelDesc}
|
|
87
|
+
Model schema design: ${modelSchemaDesign}
|
|
88
|
+
Model filename(You can create another connected scalar model file if needed): ${this.name}.constant.ts
|
|
89
|
+
\`\`\`typescript
|
|
90
|
+
// File: lib/__scalar/${this.name}/${this.name}.constant.ts
|
|
91
|
+
${boilerplate}
|
|
92
|
+
\`\`\`
|
|
93
|
+
|
|
94
|
+
If additional connected scalar models need to be written besides ${this.name}.constant.ts file, please write them in the following format
|
|
95
|
+
\`\`\`typescript
|
|
96
|
+
// File: lib/__scalar/otherModel/otherModel.constant.ts
|
|
97
|
+
...file content
|
|
98
|
+
\`\`\`
|
|
99
|
+
|
|
100
|
+
Please provide only the file results without any other content.`
|
|
101
|
+
});
|
|
102
|
+
return { request, validate: guideJson.update.rules };
|
|
103
|
+
}
|
|
104
|
+
async requestUpdateDictonaryWithInstruction() {
|
|
105
|
+
const constant = await this.sys.readFile(`lib/__scalar/${this.name}/${this.name}.constant.ts`);
|
|
106
|
+
const boilerplate = await this.sys.readFile(`lib/__scalar/${this.name}/${this.name}.dictionary.ts`);
|
|
107
|
+
const guideJson = await Prompter.getGuideJson("scalarDictionary");
|
|
108
|
+
const request = `\uB2E4\uC74C ${this.name}.dictionary.ts \uD30C\uC77C\uB3C4 \uC644\uC131\uB41C ${this.name}.constant.ts \uD30C\uC77C\uC744 \uAE30\uBC18\uC73C\uB85C \uC791\uC131\uD574\uC918.
|
|
109
|
+
1. Dictionary \uC791\uC131\uBC95
|
|
110
|
+
${await this.getDocumentation("scalarDictionary")}
|
|
111
|
+
|
|
112
|
+
Model constant file
|
|
113
|
+
\`\`\`typescript
|
|
114
|
+
// File: lib/__scalar/${this.name}/${this.name}.constant.ts
|
|
115
|
+
${constant}
|
|
116
|
+
\`\`\`
|
|
117
|
+
|
|
118
|
+
Model filename: ${this.name}.dictionary.ts
|
|
119
|
+
\`\`\`typescript
|
|
120
|
+
// File: lib/__scalar/${this.name}/${this.name}.dictionary.ts
|
|
121
|
+
${boilerplate}
|
|
122
|
+
\`\`\`
|
|
123
|
+
`;
|
|
124
|
+
return { request, validate: guideJson.update.rules };
|
|
125
|
+
}
|
|
126
|
+
async requestUpdateDictonaryWithFollowing() {
|
|
127
|
+
const [constant, boilerplate] = await Promise.all([
|
|
128
|
+
this.sys.readFile(`lib/__scalar/${this.name}/${this.name}.constant.ts`),
|
|
129
|
+
this.sys.readFile(`lib/__scalar/${this.name}/${this.name}.dictionary.ts`)
|
|
130
|
+
]);
|
|
131
|
+
const request = `\uB2E4\uC74C ${this.name}.dictionary.ts \uD30C\uC77C\uB3C4 \uC644\uC131\uB41C ${this.name}.constant.ts \uD30C\uC77C\uC744 \uAE30\uBC18\uC73C\uB85C \uC791\uC131\uD574\uC918.
|
|
132
|
+
Model constant file
|
|
133
|
+
\`\`\`typescript
|
|
134
|
+
// File: lib/__scalar/${this.name}/${this.name}.constant.ts
|
|
135
|
+
${constant}
|
|
136
|
+
\`\`\`
|
|
137
|
+
|
|
138
|
+
Model filename: ${this.name}.dictionary.ts
|
|
139
|
+
\`\`\`typescript
|
|
140
|
+
// File: lib/__scalar/${this.name}/${this.name}.dictionary.ts
|
|
141
|
+
${boilerplate}
|
|
142
|
+
\`\`\`
|
|
143
|
+
`;
|
|
144
|
+
return { request, validate: [] };
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// pkgs/@akanjs/cli/scalar/scalar.runner.ts
|
|
149
|
+
class ScalarRunner extends runner("scalar") {
|
|
150
|
+
async applyScalarTemplate(sys, scalarName) {
|
|
151
|
+
await sys.applyTemplate({
|
|
152
|
+
basePath: "./lib/__scalar",
|
|
153
|
+
template: "__scalar",
|
|
154
|
+
dict: { model: scalarName, models: pluralizeName(scalarName), sysName: sys.name },
|
|
155
|
+
overwrite: false
|
|
156
|
+
});
|
|
157
|
+
return {
|
|
158
|
+
abstract: {
|
|
159
|
+
filename: `${scalarName}.abstract.md`,
|
|
160
|
+
content: await sys.readFile(`lib/__scalar/${scalarName}/${scalarName}.abstract.md`)
|
|
161
|
+
},
|
|
162
|
+
constant: {
|
|
163
|
+
filename: `${scalarName}.constant.ts`,
|
|
164
|
+
content: await sys.readFile(`lib/__scalar/${scalarName}/${scalarName}.constant.ts`)
|
|
165
|
+
},
|
|
166
|
+
dictionary: {
|
|
167
|
+
filename: `${scalarName}.dictionary.ts`,
|
|
168
|
+
content: await sys.readFile(`lib/__scalar/${scalarName}/${scalarName}.dictionary.ts`)
|
|
169
|
+
},
|
|
170
|
+
document: {
|
|
171
|
+
filename: `${scalarName}.document.ts`,
|
|
172
|
+
content: await sys.readFile(`lib/__scalar/${scalarName}/${scalarName}.document.ts`)
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
async createScalarConstant(sys, scalarName) {
|
|
177
|
+
const isContinued = await sys.exists(`lib/__scalar/${scalarName}/${scalarName}.constant.ts`);
|
|
178
|
+
const prompt = new ScalarPrompt(sys, scalarName);
|
|
179
|
+
const session = new AiSession("createScalar", { workspace: sys.workspace, cacheKey: scalarName, isContinued });
|
|
180
|
+
const { request, validate } = session.isCacheLoaded ? await prompt.requestUpdateConstant() : await prompt.requestCreateConstant();
|
|
181
|
+
const writes = await session.writeTypescripts(request, sys, { validate });
|
|
182
|
+
const scalarNames = writes.map(({ filePath }) => filePath.split("/").at(-2)).filter((name) => !!name);
|
|
183
|
+
if (!scalarNames.includes(scalarName))
|
|
184
|
+
scalarNames.unshift(scalarName);
|
|
185
|
+
for (const name of scalarNames)
|
|
186
|
+
await this.applyScalarTemplate(sys, name);
|
|
187
|
+
return { session, scalarNames, writes, prompt };
|
|
188
|
+
}
|
|
189
|
+
async updateScalarDictionaries(sys, scalarNames, { session }) {
|
|
190
|
+
const [firstScalarName, ...followingScalarNames] = scalarNames;
|
|
191
|
+
const prompt = new ScalarPrompt(sys, firstScalarName);
|
|
192
|
+
const { request, validate } = await prompt.requestUpdateDictonaryWithInstruction();
|
|
193
|
+
await session.writeTypescripts(request, sys, { validate });
|
|
194
|
+
for (const scalarName of followingScalarNames) {
|
|
195
|
+
const prompt2 = new ScalarPrompt(sys, scalarName);
|
|
196
|
+
const { request: request2, validate: validate2 } = await prompt2.requestUpdateDictonaryWithFollowing();
|
|
197
|
+
await session.writeTypescripts(request2, sys, { validate: validate2 });
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// pkgs/@akanjs/cli/scalar/scalar.script.ts
|
|
203
|
+
class ScalarScript extends script("scalar", [ScalarRunner]) {
|
|
204
|
+
async createScalar(sys, scalarName) {
|
|
205
|
+
const files = await this.scalarRunner.applyScalarTemplate(sys, scalarName);
|
|
206
|
+
return createPassedPrimitiveReport({
|
|
207
|
+
command: "create-scalar",
|
|
208
|
+
changedFiles: scalarChangedFiles(sys, scalarName, files),
|
|
209
|
+
generatedFiles: generatedFilesForSync(sys),
|
|
210
|
+
target: sys.name
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
async createScalarWithAi(sys, scalarName) {
|
|
214
|
+
const { session, scalarNames } = await this.scalarRunner.createScalarConstant(sys, scalarName);
|
|
215
|
+
await this.scalarRunner.updateScalarDictionaries(sys, scalarNames, { session });
|
|
216
|
+
const fileMaps = await Promise.all(scalarNames.map(async (name) => ({ name, files: await this.scalarRunner.applyScalarTemplate(sys, name) })));
|
|
217
|
+
return createPassedPrimitiveReport({
|
|
218
|
+
command: "create-scalar",
|
|
219
|
+
changedFiles: fileMaps.flatMap(({ name, files }) => scalarChangedFiles(sys, name, files)),
|
|
220
|
+
generatedFiles: generatedFilesForSync(sys),
|
|
221
|
+
target: sys.name
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
async removeScalar(sys, scalarName) {
|
|
225
|
+
await sys.removeDir(`lib/__scalar/${scalarName}`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export { ScalarScript };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
CloudRunner
|
|
4
|
+
} from "./index-sgmas1fc.js";
|
|
5
|
+
import {
|
|
6
|
+
ApplicationScript
|
|
7
|
+
} from "./index-77crfweb.js";
|
|
8
|
+
import {
|
|
9
|
+
PackageScript
|
|
10
|
+
} from "./index-wq8jwx8z.js";
|
|
11
|
+
import {
|
|
12
|
+
AiSession,
|
|
13
|
+
CloudApi,
|
|
14
|
+
GlobalConfig
|
|
15
|
+
} from "./index-5vvwc0cz.js";
|
|
16
|
+
import {
|
|
17
|
+
script
|
|
18
|
+
} from "./index-hdqztm58.js";
|
|
19
|
+
import {
|
|
20
|
+
PkgExecutor
|
|
21
|
+
} from "./index-a6sbyy0b.js";
|
|
22
|
+
|
|
23
|
+
// pkgs/@akanjs/cli/cloud/cloud.script.ts
|
|
24
|
+
import { Logger } from "akanjs/common";
|
|
25
|
+
class CloudScript extends script("cloud", [CloudRunner, ApplicationScript, PackageScript]) {
|
|
26
|
+
async login(workspace, host = GlobalConfig.akanCloudHost) {
|
|
27
|
+
await this.cloudRunner.login(host, workspace);
|
|
28
|
+
}
|
|
29
|
+
async logout(workspace, host = GlobalConfig.akanCloudHost) {
|
|
30
|
+
await this.cloudRunner.logout(host);
|
|
31
|
+
}
|
|
32
|
+
async setLlm(workspace) {
|
|
33
|
+
await this.cloudRunner.setLlm();
|
|
34
|
+
}
|
|
35
|
+
resetLlm(workspace) {
|
|
36
|
+
this.cloudRunner.resetLlm();
|
|
37
|
+
}
|
|
38
|
+
async ask(question, workspace) {
|
|
39
|
+
const session = new AiSession("general", { workspace, isContinued: true });
|
|
40
|
+
await session.ask(question);
|
|
41
|
+
}
|
|
42
|
+
async downloadEnv(workspace, workspaceId = workspace.getWorkspaceId({ allowEmpty: true }), { host = GlobalConfig.akanCloudHost } = {}) {
|
|
43
|
+
if (workspaceId) {
|
|
44
|
+
await this.login(workspace, host);
|
|
45
|
+
const cloudApi = await CloudApi.fromHost(workspace, host);
|
|
46
|
+
await this.cloudRunner.downloadEnv(cloudApi, workspace, workspaceId);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
await this.cloudRunner.downloadEnvByScp(workspace);
|
|
50
|
+
}
|
|
51
|
+
async uploadEnv(workspace, { host = GlobalConfig.akanCloudHost } = {}) {
|
|
52
|
+
const workspaceId = workspace.getWorkspaceId({ allowEmpty: true });
|
|
53
|
+
const { path } = await this.cloudRunner.gatherEnvFiles(workspace);
|
|
54
|
+
if (workspaceId) {
|
|
55
|
+
await this.login(workspace, host);
|
|
56
|
+
const cloudApi = await CloudApi.fromHost(workspace, host);
|
|
57
|
+
await this.cloudRunner.uploadEnv(cloudApi, workspaceId, path);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
await this.cloudRunner.uploadEnvByScp(workspace, path);
|
|
61
|
+
}
|
|
62
|
+
async deployAkan(workspace, { test = true, registryUrl } = {}) {
|
|
63
|
+
const akanPkgs = await this.cloudRunner.getAkanPkgs(workspace);
|
|
64
|
+
await this.packageScript.updateWorskpaceRootPackageJson(workspace);
|
|
65
|
+
const pkgs = akanPkgs.map((pkgName) => PkgExecutor.from(workspace, pkgName));
|
|
66
|
+
if (test)
|
|
67
|
+
for (const pkg of pkgs)
|
|
68
|
+
await this.applicationScript.test(pkg);
|
|
69
|
+
for (const pkg of pkgs)
|
|
70
|
+
await this.packageScript.buildPackage(pkg);
|
|
71
|
+
await this.packageScript.verifyAkanPublishPackages(workspace);
|
|
72
|
+
await this.cloudRunner.deployAkan(workspace, akanPkgs, { registryUrl });
|
|
73
|
+
}
|
|
74
|
+
async update(workspace, tag = "latest", { registryUrl } = {}) {
|
|
75
|
+
const spinner = workspace.spinning("Updating Akan.js packages and CLI...");
|
|
76
|
+
await this.cloudRunner.update(workspace, tag, { registryUrl });
|
|
77
|
+
spinner.succeed("Akan.js packages and CLI updated, global version is below");
|
|
78
|
+
Logger.raw("> Akan version: ");
|
|
79
|
+
await workspace.spawn("akan", ["--version"], { stdio: "inherit" });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export { CloudScript };
|