@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.
Files changed (57) hide show
  1. package/agent.command-h4afc69n.js +26 -0
  2. package/application.command-47mj9qsy.js +165 -0
  3. package/applicationBuildRunner-yz144508.js +284 -0
  4. package/applicationReleasePackager-brvth6rs.js +245 -0
  5. package/capacitorApp-y0h6cgft.js +58 -0
  6. package/cloud.command-qgjxja3n.js +94 -0
  7. package/commandManifest.json +1 -0
  8. package/context.command-nqbtak4f.js +82 -0
  9. package/dependencyScanner-m4x5maek.js +9 -0
  10. package/guideline.command-ya0dh44f.js +356 -0
  11. package/incrementalBuilder.proc.js +89 -17394
  12. package/index-1xdrsbry.js +1447 -0
  13. package/index-45aj5ry0.js +990 -0
  14. package/index-5vvwc0cz.js +559 -0
  15. package/index-61keag0s.js +40 -0
  16. package/index-6pz1j0zj.js +62 -0
  17. package/index-73pr2cmy.js +534 -0
  18. package/index-76rn3g2c.js +76 -0
  19. package/index-77crfweb.js +1884 -0
  20. package/index-85msc0wg.js +161 -0
  21. package/index-8pkbzj26.js +840 -0
  22. package/index-8rc0bm04.js +514 -0
  23. package/index-a5rmdgy4.js +4359 -0
  24. package/index-a6sbyy0b.js +2769 -0
  25. package/index-fgc8r6dj.js +33 -0
  26. package/index-h6ca6qg0.js +2777 -0
  27. package/index-hdqztm58.js +758 -0
  28. package/index-hwzpw9c1.js +202 -0
  29. package/index-pmm9e2jf.js +120 -0
  30. package/index-qaq13qk3.js +80 -0
  31. package/index-qhtr07v8.js +1072 -0
  32. package/index-r24hmh0q.js +4 -0
  33. package/index-sgmas1fc.js +462 -0
  34. package/index-ss469dec.js +11 -0
  35. package/index-swf4bmbg.js +25 -0
  36. package/index-wnp7hwq7.js +193 -0
  37. package/index-wq8jwx8z.js +224 -0
  38. package/index-x53a5nya.js +301 -0
  39. package/index-y3hdhy4p.js +229 -0
  40. package/index-z9gvz7b0.js +83 -0
  41. package/index.js +54 -23340
  42. package/library.command-r15zdqvp.js +33 -0
  43. package/localRegistry.command-p1pgxw78.js +178 -0
  44. package/module.command-qrj3kmyz.js +54 -0
  45. package/package.command-r8sq5kzp.js +43 -0
  46. package/package.json +2 -2
  47. package/page.command-c6xdx0xm.js +24 -0
  48. package/primitive.command-pv9ssmtf.js +62 -0
  49. package/quality.command-es67wvdp.js +809 -0
  50. package/repair.command-677675vw.js +67 -0
  51. package/routeSourceValidator-wbhmbwpj.js +132 -0
  52. package/scalar.command-kabkd6wd.js +35 -0
  53. package/templates/facetIndex/index.ts +1 -1
  54. package/typeChecker-kravn7ns.js +8 -0
  55. package/typecheck.proc.js +4 -194
  56. package/workflow.command-64r6cw0w.js +108 -0
  57. 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 };