@akanjs/cli 0.0.89 → 0.0.91

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 (25) hide show
  1. package/index.js +1097 -341
  2. package/package.json +1 -1
  3. package/pkgs/@akanjs/cli/src/application/application.command.d.ts +2 -2
  4. package/pkgs/@akanjs/cli/src/application/application.runner.d.ts +3 -1
  5. package/pkgs/@akanjs/cli/src/application/application.script.d.ts +3 -1
  6. package/pkgs/@akanjs/cli/src/cloud/cloud.command.d.ts +3 -0
  7. package/pkgs/@akanjs/cli/src/cloud/cloud.runner.d.ts +2 -0
  8. package/pkgs/@akanjs/cli/src/cloud/cloud.script.d.ts +3 -0
  9. package/pkgs/@akanjs/cli/src/library/library.command.d.ts +1 -1
  10. package/pkgs/@akanjs/cli/src/library/library.runner.d.ts +2 -0
  11. package/pkgs/@akanjs/cli/src/library/library.script.d.ts +2 -0
  12. package/pkgs/@akanjs/cli/src/module/module.prompt.d.ts +17 -8
  13. package/pkgs/@akanjs/cli/src/module/module.runner.d.ts +1 -3
  14. package/pkgs/@akanjs/cli/src/module/module.script.d.ts +1 -1
  15. package/pkgs/@akanjs/cli/src/package/package.command.d.ts +1 -1
  16. package/pkgs/@akanjs/cli/src/package/package.runner.d.ts +1 -0
  17. package/pkgs/@akanjs/cli/src/package/package.script.d.ts +1 -0
  18. package/pkgs/@akanjs/devkit/src/aiEditor.d.ts +14 -0
  19. package/pkgs/@akanjs/devkit/src/constants.d.ts +8 -1
  20. package/pkgs/@akanjs/devkit/src/executors.d.ts +21 -1
  21. package/pkgs/@akanjs/devkit/src/getRelatedCnsts.d.ts +52 -8
  22. package/src/templates/workspaceRoot/package.json.template +5 -0
  23. /package/pkgs/@akanjs/cli/src/{package/page → page}/page.command.d.ts +0 -0
  24. /package/pkgs/@akanjs/cli/src/{package/page → page}/page.runner.d.ts +0 -0
  25. /package/pkgs/@akanjs/cli/src/{package/page → page}/page.script.d.ts +0 -0
package/index.js CHANGED
@@ -58,8 +58,8 @@ var createTunnel = async ({ app, environment, port = 27017 }) => {
58
58
  };
59
59
 
60
60
  // pkgs/@akanjs/devkit/src/getCredentials.ts
61
- var import_fs = __toESM(require("fs"), 1);
62
- var import_js_yaml = __toESM(require("js-yaml"), 1);
61
+ var import_fs = __toESM(require("fs"));
62
+ var import_js_yaml = __toESM(require("js-yaml"));
63
63
  var getCredentials = (app, environment) => {
64
64
  const secret = import_js_yaml.default.load(
65
65
  import_fs.default.readFileSync(`${app.workspace.workspaceRoot}/infra/app/values/${app.name}-secret.yaml`, "utf-8")
@@ -68,9 +68,9 @@ var getCredentials = (app, environment) => {
68
68
  };
69
69
 
70
70
  // pkgs/@akanjs/devkit/src/uploadRelease.ts
71
- var import_axios = __toESM(require("axios"), 1);
72
- var import_form_data = __toESM(require("form-data"), 1);
73
- var import_fs2 = __toESM(require("fs"), 1);
71
+ var import_axios = __toESM(require("axios"));
72
+ var import_form_data = __toESM(require("form-data"));
73
+ var import_fs2 = __toESM(require("fs"));
74
74
  var uploadRelease = async (projectName, {
75
75
  workspaceRoot,
76
76
  environment,
@@ -119,58 +119,96 @@ var uploadRelease = async (projectName, {
119
119
  };
120
120
 
121
121
  // pkgs/@akanjs/devkit/src/getModelFileData.ts
122
- var import_fs3 = __toESM(require("fs"), 1);
123
- var getModelFileData = (modulePath, modelName) => {
124
- const moduleType = modulePath.startsWith("apps") ? "app" : "lib";
125
- const moduleName = modulePath.split("/")[1];
126
- const constantFilePath = `${modulePath}/lib/${modelName}/${modelName}.constant.ts`;
127
- const unitFilePath = `${modulePath}/lib/${modelName}/${modelName}.Unit.tsx`;
128
- const viewFilePath = `${modulePath}/lib/${modelName}/${modelName}.View.tsx`;
129
- const constantFileStr = import_fs3.default.readFileSync(constantFilePath, "utf8");
130
- const unitFileStr = import_fs3.default.readFileSync(unitFilePath, "utf8");
131
- const viewFileStr = import_fs3.default.readFileSync(viewFilePath, "utf8");
132
- const constantFileLines = constantFileStr.split("\n");
133
- const importLibNames = constantFileLines.filter((line) => line.startsWith("import { cnst as ")).map((line) => line.split("cnst as ")[1].split(" ")[0]);
134
- const importLocalPaths = constantFileLines.filter((line) => line.startsWith("import { ") && line.includes('from "../')).map((line) => line.split("from ")[1].split('"')[1]);
135
- const importModelNames = importLocalPaths.map((path7) => path7.split("/")[1]).filter((name) => !name.startsWith("_"));
136
- const hasImportScalar = !!importLocalPaths.map((path7) => path7.split("/")[1]).filter((name) => name.startsWith("_")).length;
137
- return {
138
- moduleType,
139
- moduleName,
140
- modelName,
141
- constantFilePath,
142
- unitFilePath,
143
- viewFilePath,
144
- importModelNames,
145
- hasImportScalar,
146
- importLibNames,
147
- constantFileStr,
148
- unitFileStr,
149
- viewFileStr
150
- };
151
- };
122
+ var import_fs3 = __toESM(require("fs"));
152
123
 
153
124
  // pkgs/@akanjs/devkit/src/getRelatedCnsts.ts
154
- var import_fs4 = __toESM(require("fs"), 1);
155
- var import_ora = __toESM(require("ora"), 1);
156
- var ts = __toESM(require("typescript"), 1);
157
- var getRelatedCnsts = (constantFilePath) => {
158
- const tsConfigPath = `./tsconfig.json`;
125
+ var fs4 = __toESM(require("fs"));
126
+ var import_ora = __toESM(require("ora"));
127
+ var ts = __toESM(require("typescript"));
128
+ var parseTsConfig = (tsConfigPath = "./tsconfig.json") => {
159
129
  const configFile = ts.readConfigFile(tsConfigPath, (path7) => {
160
130
  return ts.sys.readFile(path7);
161
131
  });
162
- const parsedConfig = ts.parseJsonConfigFileContent(
132
+ return ts.parseJsonConfigFileContent(
163
133
  configFile.config,
164
134
  ts.sys,
165
- import_fs4.default.realpathSync(tsConfigPath).replace(/[^/\\]+$/, "")
135
+ fs4.realpathSync(tsConfigPath).replace(/[^/\\]+$/, "")
166
136
  );
137
+ };
138
+ var collectImportedFiles = (constantFilePath, parsedConfig) => {
139
+ const allFilesToAnalyze = /* @__PURE__ */ new Set([constantFilePath]);
140
+ const analyzedFiles = /* @__PURE__ */ new Set();
141
+ const spinner = (0, import_ora.default)("Collecting related files...");
142
+ spinner.start();
143
+ function collectImported(filePath) {
144
+ if (analyzedFiles.has(filePath))
145
+ return;
146
+ analyzedFiles.add(filePath);
147
+ const tempProgram = ts.createProgram([filePath], parsedConfig.options);
148
+ const source = tempProgram.getSourceFile(filePath);
149
+ if (!source)
150
+ return;
151
+ function collectImports(node) {
152
+ if (ts.isImportDeclaration(node) && ts.isStringLiteral(node.moduleSpecifier)) {
153
+ const importPath = node.moduleSpecifier.text;
154
+ if (importPath.startsWith(".")) {
155
+ const resolved = ts.resolveModuleName(importPath, filePath, parsedConfig.options, ts.sys).resolvedModule?.resolvedFileName;
156
+ if (resolved && !allFilesToAnalyze.has(resolved)) {
157
+ allFilesToAnalyze.add(resolved);
158
+ collectImported(resolved);
159
+ }
160
+ }
161
+ }
162
+ ts.forEachChild(node, collectImports);
163
+ }
164
+ collectImports(source);
165
+ }
166
+ collectImported(constantFilePath);
167
+ spinner.succeed(`Found ${allFilesToAnalyze.size} related files.`);
168
+ return {
169
+ allFilesToAnalyze,
170
+ analyzedFiles
171
+ };
172
+ };
173
+ var createTsProgram = (filePaths, options) => {
174
+ const spinner = (0, import_ora.default)("Creating TypeScript program for all files...");
175
+ spinner.start();
176
+ const program2 = ts.createProgram(Array.from(filePaths), options);
177
+ const checker = program2.getTypeChecker();
178
+ spinner.succeed("TypeScript program created.");
179
+ return {
180
+ program: program2,
181
+ checker
182
+ };
183
+ };
184
+ var createSymbolCache = (checker) => {
185
+ const symbolCache = /* @__PURE__ */ new Map();
186
+ return (node) => {
187
+ const cacheKey = `${node.getSourceFile().fileName}:${node.pos}:${node.end}`;
188
+ if (!symbolCache.has(cacheKey)) {
189
+ symbolCache.set(cacheKey, checker.getSymbolAtLocation(node));
190
+ }
191
+ return symbolCache.get(cacheKey);
192
+ };
193
+ };
194
+ var analyzeProperties = (filesToAnalyze, program2, checker) => {
167
195
  const propertyMap = /* @__PURE__ */ new Map();
168
- function findPropertyOriginAll(filePath) {
169
- const program2 = ts.createProgram([filePath], parsedConfig.options);
170
- const checker = program2.getTypeChecker();
196
+ const analyzedFiles = /* @__PURE__ */ new Set();
197
+ const sourceLineCache = /* @__PURE__ */ new Map();
198
+ const getCachedSymbol = createSymbolCache(checker);
199
+ const spinner = (0, import_ora.default)("Analyzing property relationships...");
200
+ spinner.start();
201
+ function analyzeFileProperties(filePath) {
202
+ if (analyzedFiles.has(filePath))
203
+ return;
204
+ analyzedFiles.add(filePath);
171
205
  const source = program2.getSourceFile(filePath);
172
206
  if (!source)
173
- return null;
207
+ return;
208
+ if (!sourceLineCache.has(filePath)) {
209
+ sourceLineCache.set(filePath, source.getFullText().split("\n"));
210
+ }
211
+ const sourceLines = sourceLineCache.get(filePath);
174
212
  function visit(node) {
175
213
  if (!source)
176
214
  return;
@@ -178,37 +216,38 @@ var getRelatedCnsts = (constantFilePath) => {
178
216
  const left = node.expression;
179
217
  const right = node.name;
180
218
  const { line } = ts.getLineAndCharacterOfPosition(source, node.getStart());
181
- const sourceLines = source.getFullText().split("\n");
182
- if (ts.isIdentifier(left) && sourceLines.length && (sourceLines[line].includes(`@Field.Prop(() => ${left.text}.${right.text}`) || sourceLines[line].includes(`base.Filter(${left.text}.${right.text},`))) {
183
- const symbol = checker.getSymbolAtLocation(right);
219
+ if (ts.isIdentifier(left) && sourceLines && sourceLines.length > line && (sourceLines[line].includes(`@Field.Prop(() => ${left.text}.${right.text}`) || sourceLines[line].includes(`base.Filter(${left.text}.${right.text},`))) {
220
+ const symbol = getCachedSymbol(right);
184
221
  if (symbol?.declarations && symbol.declarations.length > 0) {
185
222
  const key = symbol.declarations[0].getSourceFile().fileName.split("/").pop()?.split(".")[0] ?? "";
186
223
  const property = propertyMap.get(key);
187
224
  const isScalar = symbol.declarations[0].getSourceFile().fileName.includes("_");
188
- const filePath2 = symbol.declarations[0].getSourceFile().fileName.replace(`${ts.sys.getCurrentDirectory()}/`, "");
225
+ const symbolFilePath = symbol.declarations[0].getSourceFile().fileName.replace(`${ts.sys.getCurrentDirectory()}/`, "");
189
226
  if (property) {
190
227
  propertyMap.set(`${left.text}.${right.text}`, {
191
- filePath: filePath2,
228
+ filePath: symbolFilePath,
192
229
  isLibModule: true,
193
230
  isImport: false,
194
231
  libName: left.text,
232
+ source: fs4.readFileSync(symbolFilePath, "utf-8"),
195
233
  isScalar
196
234
  });
197
- } else
235
+ } else {
198
236
  propertyMap.set(key, {
199
- filePath: filePath2,
237
+ filePath: symbolFilePath,
200
238
  isLibModule: true,
201
239
  isImport: false,
202
240
  libName: left.text,
203
- isScalar
241
+ isScalar,
242
+ source: fs4.readFileSync(symbolFilePath, "utf-8")
204
243
  });
205
- findPropertyOriginAll(filePath2);
244
+ }
206
245
  }
207
246
  }
208
- } else if (ts.isImportDeclaration(node)) {
209
- const importPath = node.moduleSpecifier.getText().slice(1, -1);
247
+ } else if (ts.isImportDeclaration(node) && ts.isStringLiteral(node.moduleSpecifier)) {
248
+ const importPath = node.moduleSpecifier.text;
210
249
  if (importPath.startsWith(".")) {
211
- const resolved = ts.resolveModuleName(importPath, filePath, parsedConfig.options, ts.sys).resolvedModule?.resolvedFileName;
250
+ const resolved = ts.resolveModuleName(importPath, filePath, program2.getCompilerOptions(), ts.sys).resolvedModule?.resolvedFileName;
212
251
  const moduleName = importPath.split("/").pop()?.split(".")[0] ?? "";
213
252
  const property = propertyMap.get(moduleName);
214
253
  const isScalar = importPath.includes("_");
@@ -217,87 +256,38 @@ var getRelatedCnsts = (constantFilePath) => {
217
256
  filePath: resolved,
218
257
  isLibModule: false,
219
258
  isImport: true,
220
- isScalar
259
+ isScalar,
260
+ source: fs4.readFileSync(resolved, "utf-8")
221
261
  });
222
- findPropertyOriginAll(resolved);
223
262
  }
224
263
  }
225
264
  }
226
265
  ts.forEachChild(node, visit);
227
266
  }
228
267
  visit(source);
229
- return propertyMap;
230
268
  }
231
- function findPropertyOrigin(filePath, aliasName, libName) {
232
- const program2 = ts.createProgram([filePath], parsedConfig.options);
233
- const checker = program2.getTypeChecker();
234
- const source = program2.getSourceFile(filePath);
235
- const propertyMap2 = /* @__PURE__ */ new Map();
236
- if (!source)
237
- return null;
238
- function visit(node) {
239
- if (ts.isPropertyAccessExpression(node)) {
240
- const left = node.expression;
241
- const right = node.name;
242
- if (ts.isIdentifier(left) && left.text === aliasName && right.text === libName) {
243
- const symbol = checker.getSymbolAtLocation(right);
244
- if (symbol?.declarations && symbol.declarations.length > 0) {
245
- return symbol.declarations[0].getSourceFile().fileName;
246
- }
247
- }
248
- }
249
- return ts.forEachChild(node, visit) || null;
250
- }
251
- return visit(source);
269
+ for (const filePath of filesToAnalyze) {
270
+ analyzeFileProperties(filePath);
252
271
  }
253
- const spinner = (0, import_ora.default)("Finding property origin...");
254
- spinner.start();
255
- const paths = findPropertyOriginAll(constantFilePath);
256
- spinner.succeed("property origin found.");
257
- return { paths };
272
+ spinner.succeed(`Analysis complete. Found ${propertyMap.size} properties.`);
273
+ return propertyMap;
274
+ };
275
+ var getRelatedCnsts = (constantFilePath) => {
276
+ const parsedConfig = parseTsConfig();
277
+ const { allFilesToAnalyze } = collectImportedFiles(constantFilePath, parsedConfig);
278
+ const { program: program2, checker } = createTsProgram(allFilesToAnalyze, parsedConfig.options);
279
+ const propertyMap = analyzeProperties(allFilesToAnalyze, program2, checker);
280
+ return Array.from(propertyMap.entries()).map(([key, value]) => ({ key, ...value }));
258
281
  };
259
282
 
260
283
  // pkgs/@akanjs/devkit/src/selectModel.ts
261
284
  var import_prompts = require("@inquirer/prompts");
262
- var import_fs5 = __toESM(require("fs"), 1);
285
+ var import_fs4 = __toESM(require("fs"));
263
286
 
264
287
  // pkgs/@akanjs/devkit/src/streamAi.ts
265
288
  var import_prompts2 = require("@langchain/core/prompts");
266
289
  var import_runnables = require("@langchain/core/runnables");
267
290
  var import_openai = require("@langchain/openai");
268
- var streamAi = async (question, callback = (chunk) => {
269
- process.stdout.write(chunk);
270
- }) => {
271
- const createStreamingModel = (apiKey = process.env.DEEPSEEK_API_KEY) => {
272
- if (!apiKey)
273
- throw new Error(`process.env.DEEPSEEK_API_KEY is not set`);
274
- return new import_openai.ChatOpenAI({
275
- modelName: "deepseek-reasoner",
276
- temperature: 0.7,
277
- streaming: true,
278
- // Enable streaming
279
- configuration: { baseURL: "https://api.deepseek.com/v1", apiKey }
280
- });
281
- };
282
- const createProcessingChain = () => {
283
- return import_runnables.RunnableSequence.from([import_prompts2.PromptTemplate.fromTemplate(`Answer concisely: {question}`), createStreamingModel()]);
284
- };
285
- try {
286
- const chain = createProcessingChain();
287
- const stream = await chain.stream({ question });
288
- let fullResponse = "";
289
- for await (const chunk of stream) {
290
- const content = chunk.content;
291
- if (typeof content === "string") {
292
- fullResponse += content;
293
- callback(content);
294
- }
295
- }
296
- return { content: fullResponse };
297
- } catch (error) {
298
- throw new Error("Failed to stream response");
299
- }
300
- };
301
291
 
302
292
  // pkgs/@akanjs/common/isDayjs.ts
303
293
  var import_dayjs = require("dayjs");
@@ -483,7 +473,7 @@ var sleep = async (ms) => {
483
473
  };
484
474
 
485
475
  // pkgs/@akanjs/config/src/akanConfig.ts
486
- var import_fs6 = __toESM(require("fs"));
476
+ var import_fs5 = __toESM(require("fs"));
487
477
  var import_path2 = __toESM(require("path"));
488
478
 
489
479
  // pkgs/@akanjs/config/src/nextConfig.ts
@@ -698,7 +688,7 @@ CMD ["npm", "start"]`,
698
688
  };
699
689
  var getAppConfig = async (appRoot, props) => {
700
690
  const akanConfigPath = import_path2.default.join(appRoot, "akan.config.ts");
701
- if (!import_fs6.default.existsSync(akanConfigPath))
691
+ if (!import_fs5.default.existsSync(akanConfigPath))
702
692
  throw new Error(`application akan.config.ts is not found ${appRoot}`);
703
693
  const configImp = (await import(`${appRoot}/akan.config.ts`)).default;
704
694
  const config = typeof configImp === "function" ? configImp(props) : configImp;
@@ -718,7 +708,7 @@ var makeLibConfig = (config, props) => {
718
708
  };
719
709
  var getLibConfig = async (libRoot, props) => {
720
710
  const akanConfigPath = import_path2.default.join(libRoot, "akan.config.ts");
721
- if (!import_fs6.default.existsSync(akanConfigPath))
711
+ if (!import_fs5.default.existsSync(akanConfigPath))
722
712
  throw new Error(`library akan.config.ts is not found ${libRoot}`);
723
713
  const configImp = (await import(`${libRoot}/akan.config.ts`)).default;
724
714
  const config = typeof configImp === "function" ? configImp(props) : configImp;
@@ -764,15 +754,15 @@ var getDefaultFileScan = () => ({
764
754
 
765
755
  // pkgs/@akanjs/devkit/src/executors.ts
766
756
  var import_child_process = require("child_process");
767
- var import_dotenv = __toESM(require("dotenv"), 1);
768
- var import_fs7 = __toESM(require("fs"), 1);
769
- var import_promises = __toESM(require("fs/promises"), 1);
770
- var import_path3 = __toESM(require("path"), 1);
757
+ var import_dotenv = __toESM(require("dotenv"));
758
+ var import_fs6 = __toESM(require("fs"));
759
+ var import_promises = __toESM(require("fs/promises"));
760
+ var import_path3 = __toESM(require("path"));
771
761
 
772
762
  // pkgs/@akanjs/devkit/src/dependencyScanner.ts
773
- var fs7 = __toESM(require("fs"), 1);
774
- var path3 = __toESM(require("path"), 1);
775
- var ts2 = __toESM(require("typescript"), 1);
763
+ var fs7 = __toESM(require("fs"));
764
+ var path3 = __toESM(require("path"));
765
+ var ts2 = __toESM(require("typescript"));
776
766
  var TypeScriptDependencyScanner = class {
777
767
  constructor(directory) {
778
768
  this.directory = directory;
@@ -923,8 +913,8 @@ var Executor = class {
923
913
  constructor(name, cwdPath) {
924
914
  this.logger = new Logger(name);
925
915
  this.cwdPath = cwdPath;
926
- if (!import_fs7.default.existsSync(cwdPath))
927
- import_fs7.default.mkdirSync(cwdPath, { recursive: true });
916
+ if (!import_fs6.default.existsSync(cwdPath))
917
+ import_fs6.default.mkdirSync(cwdPath, { recursive: true });
928
918
  }
929
919
  exec(command, options = {}) {
930
920
  const proc = (0, import_child_process.exec)(command, { cwd: this.cwdPath, ...options });
@@ -983,31 +973,31 @@ var Executor = class {
983
973
  }
984
974
  mkdir(dirPath) {
985
975
  const writePath = this.#getPath(dirPath);
986
- if (!import_fs7.default.existsSync(writePath))
987
- import_fs7.default.mkdirSync(writePath, { recursive: true });
976
+ if (!import_fs6.default.existsSync(writePath))
977
+ import_fs6.default.mkdirSync(writePath, { recursive: true });
988
978
  this.logger.verbose(`Make directory ${writePath}`);
989
979
  return this;
990
980
  }
991
981
  exists(filePath) {
992
982
  const readPath = this.#getPath(filePath);
993
- return import_fs7.default.existsSync(readPath);
983
+ return import_fs6.default.existsSync(readPath);
994
984
  }
995
985
  writeFile(filePath, content, { overwrite = true } = {}) {
996
986
  const writePath = this.#getPath(filePath);
997
987
  const dir = import_path3.default.dirname(writePath);
998
- if (!import_fs7.default.existsSync(dir))
999
- import_fs7.default.mkdirSync(dir, { recursive: true });
988
+ if (!import_fs6.default.existsSync(dir))
989
+ import_fs6.default.mkdirSync(dir, { recursive: true });
1000
990
  const contentStr = typeof content === "string" ? content : JSON.stringify(content, null, 2);
1001
- if (import_fs7.default.existsSync(writePath)) {
1002
- const currentContent = import_fs7.default.readFileSync(writePath, "utf8");
991
+ if (import_fs6.default.existsSync(writePath)) {
992
+ const currentContent = import_fs6.default.readFileSync(writePath, "utf8");
1003
993
  if (currentContent === contentStr || !overwrite)
1004
994
  this.logger.verbose(`File ${writePath} is unchanged`);
1005
995
  else {
1006
- import_fs7.default.writeFileSync(writePath, contentStr, "utf8");
996
+ import_fs6.default.writeFileSync(writePath, contentStr, "utf8");
1007
997
  this.logger.verbose(`File ${writePath} is changed`);
1008
998
  }
1009
999
  } else {
1010
- import_fs7.default.writeFileSync(writePath, contentStr, "utf8");
1000
+ import_fs6.default.writeFileSync(writePath, contentStr, "utf8");
1011
1001
  this.logger.verbose(`File ${writePath} is created`);
1012
1002
  }
1013
1003
  return this;
@@ -1023,11 +1013,11 @@ var Executor = class {
1023
1013
  }
1024
1014
  readFile(filePath) {
1025
1015
  const readPath = this.#getPath(filePath);
1026
- return import_fs7.default.readFileSync(readPath, "utf8");
1016
+ return import_fs6.default.readFileSync(readPath, "utf8");
1027
1017
  }
1028
1018
  readJson(filePath) {
1029
1019
  const readPath = this.#getPath(filePath);
1030
- return JSON.parse(import_fs7.default.readFileSync(readPath, "utf8"));
1020
+ return JSON.parse(import_fs6.default.readFileSync(readPath, "utf8"));
1031
1021
  }
1032
1022
  async cp(srcPath, destPath) {
1033
1023
  const src = this.#getPath(srcPath);
@@ -1096,7 +1086,7 @@ var Executor = class {
1096
1086
  overwrite = true
1097
1087
  }) {
1098
1088
  const templatePath = `${__dirname}/src/templates${template ? `/${template}` : ""}`.replace(".ts", ".js");
1099
- if (import_fs7.default.statSync(templatePath).isFile()) {
1089
+ if (import_fs6.default.statSync(templatePath).isFile()) {
1100
1090
  const filename = import_path3.default.basename(templatePath);
1101
1091
  await this.#applyTemplateFile(
1102
1092
  { templatePath, targetPath: import_path3.default.join(basePath2, filename), scanResult, overwrite },
@@ -1107,7 +1097,7 @@ var Executor = class {
1107
1097
  await Promise.all(
1108
1098
  subdirs.map(async (subdir) => {
1109
1099
  const subpath = import_path3.default.join(templatePath, subdir);
1110
- if (import_fs7.default.statSync(subpath).isFile())
1100
+ if (import_fs6.default.statSync(subpath).isFile())
1111
1101
  await this.#applyTemplateFile(
1112
1102
  { templatePath: subpath, targetPath: import_path3.default.join(basePath2, subdir), scanResult, overwrite },
1113
1103
  dict
@@ -1204,6 +1194,26 @@ var WorkspaceExecutor = class _WorkspaceExecutor extends Executor {
1204
1194
  this.writeJson("tsconfig.json", rootTsConfig);
1205
1195
  return this;
1206
1196
  }
1197
+ async getDirInModule(basePath2, name) {
1198
+ const AVOID_DIRS = ["__lib", "__scalar", `_${name}`];
1199
+ const getDirs = async (dirname, maxDepth = 3, results = [], prefix = "") => {
1200
+ const dirs = await import_promises.default.readdir(dirname);
1201
+ await Promise.all(
1202
+ dirs.map(async (dir) => {
1203
+ if (AVOID_DIRS.includes(dir))
1204
+ return;
1205
+ const dirPath = import_path3.default.join(dirname, dir);
1206
+ if (import_fs6.default.lstatSync(dirPath).isDirectory()) {
1207
+ results.push(`${name}/${prefix}${dir}`);
1208
+ if (maxDepth > 0)
1209
+ await getDirs(dirPath, maxDepth - 1, results, `${prefix}${dir}/`);
1210
+ }
1211
+ })
1212
+ );
1213
+ return results;
1214
+ };
1215
+ return await getDirs(basePath2);
1216
+ }
1207
1217
  async commit(message, { init = false, add = true } = {}) {
1208
1218
  if (init)
1209
1219
  await this.exec(`git init --quiet`);
@@ -1220,8 +1230,8 @@ var WorkspaceExecutor = class _WorkspaceExecutor extends Executor {
1220
1230
  if (AVOID_DIRS.includes(dir))
1221
1231
  return;
1222
1232
  const dirPath = import_path3.default.join(dirname, dir);
1223
- if (import_fs7.default.lstatSync(dirPath).isDirectory()) {
1224
- const hasTargetFile = import_fs7.default.existsSync(import_path3.default.join(dirPath, targetFilename));
1233
+ if (import_fs6.default.lstatSync(dirPath).isDirectory()) {
1234
+ const hasTargetFile = import_fs6.default.existsSync(import_path3.default.join(dirPath, targetFilename));
1225
1235
  if (hasTargetFile)
1226
1236
  results.push(`${prefix}${dir}`);
1227
1237
  if (maxDepth > 0)
@@ -1241,6 +1251,14 @@ var WorkspaceExecutor = class _WorkspaceExecutor extends Executor {
1241
1251
  ];
1242
1252
  return scalarConstantExampleFiles;
1243
1253
  }
1254
+ async getViewFiles() {
1255
+ const [appNames, libNames] = await this.getSyss();
1256
+ const viewExampleFiles = [
1257
+ ...(await Promise.all(appNames.map((appName) => AppExecutor.from(this, appName).getViewsSourceCode()))).flat(),
1258
+ ...(await Promise.all(libNames.map((libName) => LibExecutor.from(this, libName).getViewsSourceCode()))).flat()
1259
+ ];
1260
+ return viewExampleFiles;
1261
+ }
1244
1262
  };
1245
1263
  var SysExecutor = class extends Executor {
1246
1264
  workspace;
@@ -1255,6 +1273,10 @@ var SysExecutor = class extends Executor {
1255
1273
  async getConfig(command) {
1256
1274
  return this.type === "app" ? await getAppConfig(this.cwdPath, { ...this.workspace.getBaseDevEnv(), type: "app", name: this.name, command }) : await getLibConfig(this.cwdPath, { ...this.workspace.getBaseDevEnv(), type: "lib", name: this.name, command });
1257
1275
  }
1276
+ async getModules() {
1277
+ const path7 = this.type === "app" ? `apps/${this.name}/lib` : `libs/${this.name}/lib`;
1278
+ return await this.workspace.getDirInModule(path7, this.name);
1279
+ }
1258
1280
  async scan({
1259
1281
  tsconfig = this.getTsConfig(`${this.cwdPath}/tsconfig.json`),
1260
1282
  akanConfig
@@ -1279,11 +1301,11 @@ var SysExecutor = class extends Executor {
1279
1301
  const pathSplitLength = path7.split("/").length;
1280
1302
  return tsconfig.compilerOptions.paths[path7][0].split("/").slice(1, 1 + pathSplitLength).join("/");
1281
1303
  }).filter((libName) => libName !== this.name);
1282
- if (!import_fs7.default.existsSync(`${this.cwdPath}/lib/__scalar`))
1283
- import_fs7.default.mkdirSync(`${this.cwdPath}/lib/__scalar`, { recursive: true });
1304
+ if (!import_fs6.default.existsSync(`${this.cwdPath}/lib/__scalar`))
1305
+ import_fs6.default.mkdirSync(`${this.cwdPath}/lib/__scalar`, { recursive: true });
1284
1306
  const files = getDefaultFileScan();
1285
1307
  const dirnames = (await import_promises.default.readdir(`${this.cwdPath}/lib`)).filter(
1286
- (name) => import_fs7.default.lstatSync(`${this.cwdPath}/lib/${name}`).isDirectory()
1308
+ (name) => import_fs6.default.lstatSync(`${this.cwdPath}/lib/${name}`).isDirectory()
1287
1309
  );
1288
1310
  const databaseDirs = dirnames.filter((name) => !name.startsWith("_"));
1289
1311
  const serviceDirs = dirnames.filter((name) => name.startsWith("_") && !name.startsWith("__"));
@@ -1411,20 +1433,42 @@ var SysExecutor = class extends Executor {
1411
1433
  return { filepath, content };
1412
1434
  }
1413
1435
  async getDatabaseModules() {
1414
- const databaseModules = (await import_promises.default.readdir(`${this.cwdPath}/lib`)).filter((name) => !name.startsWith("_") && !name.startsWith("__") && !name.endsWith(".ts")).filter((name) => import_fs7.default.existsSync(`${this.cwdPath}/lib/${name}/${name}.constant.ts`));
1436
+ const databaseModules = (await import_promises.default.readdir(`${this.cwdPath}/lib`)).filter((name) => !name.startsWith("_") && !name.startsWith("__") && !name.endsWith(".ts")).filter((name) => import_fs6.default.existsSync(`${this.cwdPath}/lib/${name}/${name}.constant.ts`));
1415
1437
  return databaseModules;
1416
1438
  }
1417
1439
  async getServiceModules() {
1418
- const serviceModules = (await import_promises.default.readdir(`${this.cwdPath}/lib`)).filter((name) => name.startsWith("_") && !name.startsWith("__")).filter((name) => import_fs7.default.existsSync(`${this.cwdPath}/lib/${name}/${name}.service.ts`));
1440
+ const serviceModules = (await import_promises.default.readdir(`${this.cwdPath}/lib`)).filter((name) => name.startsWith("_") && !name.startsWith("__")).filter((name) => import_fs6.default.existsSync(`${this.cwdPath}/lib/${name}/${name}.service.ts`));
1419
1441
  return serviceModules;
1420
1442
  }
1421
1443
  async getScalarModules() {
1422
- const scalarModules = (await import_promises.default.readdir(`${this.cwdPath}/lib/__scalar`)).filter((name) => !name.startsWith("_")).filter((name) => import_fs7.default.existsSync(`${this.cwdPath}/lib/__scalar/${name}/${name}.constant.ts`));
1444
+ const scalarModules = (await import_promises.default.readdir(`${this.cwdPath}/lib/__scalar`)).filter((name) => !name.startsWith("_")).filter((name) => import_fs6.default.existsSync(`${this.cwdPath}/lib/__scalar/${name}/${name}.constant.ts`));
1423
1445
  return scalarModules;
1424
1446
  }
1425
- async getViewModules() {
1426
- const viewModules = (await import_promises.default.readdir(`${this.cwdPath}/lib`)).filter((name) => !name.startsWith("_") && !name.startsWith("__") && !name.endsWith(".ts")).filter((name) => import_fs7.default.existsSync(`${this.cwdPath}/lib/${name}/${name}.View.tsx`));
1427
- return viewModules;
1447
+ async getViewComponents() {
1448
+ const viewComponents = (await import_promises.default.readdir(`${this.cwdPath}/lib`)).filter((name) => !name.startsWith("_") && !name.startsWith("__") && !name.endsWith(".ts")).filter((name) => import_fs6.default.existsSync(`${this.cwdPath}/lib/${name}/${name}.View.tsx`));
1449
+ return viewComponents;
1450
+ }
1451
+ async getUnitComponents() {
1452
+ const unitComponents = (await import_promises.default.readdir(`${this.cwdPath}/lib`)).filter((name) => name.startsWith("_") && !name.startsWith("__")).filter((name) => import_fs6.default.existsSync(`${this.cwdPath}/lib/${name}/${name}.Unit.tsx`));
1453
+ return unitComponents;
1454
+ }
1455
+ async getTemplateComponents() {
1456
+ const templateComponents = (await import_promises.default.readdir(`${this.cwdPath}/lib`)).filter((name) => name.startsWith("_") && !name.startsWith("__")).filter((name) => import_fs6.default.existsSync(`${this.cwdPath}/lib/${name}/${name}.Template.tsx`));
1457
+ return templateComponents;
1458
+ }
1459
+ async getViewsSourceCode() {
1460
+ const viewComponents = await this.getViewComponents();
1461
+ return viewComponents.map((viewComponent) => this.getLocalFile(`lib/${viewComponent}/${viewComponent}.View.tsx`));
1462
+ }
1463
+ async getUnitsSourceCode() {
1464
+ const unitComponents = await this.getUnitComponents();
1465
+ return unitComponents.map((unitComponent) => this.getLocalFile(`lib/${unitComponent}/${unitComponent}.Unit.tsx`));
1466
+ }
1467
+ async getTemplatesSourceCode() {
1468
+ const templateComponents = await this.getTemplateComponents();
1469
+ return templateComponents.map(
1470
+ (templateComponent) => this.getLocalFile(`lib/${templateComponent}/${templateComponent}.Template.tsx`)
1471
+ );
1428
1472
  }
1429
1473
  async getScalarConstantFiles() {
1430
1474
  const scalarModules = await this.getScalarModules();
@@ -1464,9 +1508,9 @@ var AppExecutor = class _AppExecutor extends SysExecutor {
1464
1508
  }
1465
1509
  async syncAssets(libDeps) {
1466
1510
  const projectPublicLibPath = `${this.cwdPath}/public/libs`;
1467
- if (import_fs7.default.existsSync(projectPublicLibPath))
1511
+ if (import_fs6.default.existsSync(projectPublicLibPath))
1468
1512
  await import_promises.default.rm(projectPublicLibPath, { recursive: true });
1469
- const targetDeps = libDeps.filter((dep) => import_fs7.default.existsSync(`${this.workspace.workspaceRoot}/libs/${dep}/public`));
1513
+ const targetDeps = libDeps.filter((dep) => import_fs6.default.existsSync(`${this.workspace.workspaceRoot}/libs/${dep}/public`));
1470
1514
  await Promise.all(targetDeps.map((dep) => import_promises.default.mkdir(`${projectPublicLibPath}/${dep}`, { recursive: true })));
1471
1515
  await Promise.all(
1472
1516
  targetDeps.map(
@@ -1546,21 +1590,21 @@ var akanCloudHost = process.env.NEXT_PUBLIC_OPERATION_MODE === "local" ? "http:/
1546
1590
  var akanCloudBackendUrl = `${akanCloudHost}${process.env.NEXT_PUBLIC_OPERATION_MODE === "local" ? ":8080" : ""}/backend`;
1547
1591
  var akanCloudClientUrl = `${akanCloudHost}${process.env.NEXT_PUBLIC_OPERATION_MODE === "local" ? ":4200" : ""}`;
1548
1592
  var defaultHostConfig = {};
1549
- var defaultAkanGlobalConfig = {};
1593
+ var defaultAkanGlobalConfig = { cloudHost: {}, llm: null };
1550
1594
 
1551
1595
  // pkgs/@akanjs/devkit/src/auth.ts
1552
- var import_fs8 = __toESM(require("fs"), 1);
1596
+ var import_fs7 = __toESM(require("fs"));
1553
1597
  var getAkanGlobalConfig = () => {
1554
- const akanConfig = import_fs8.default.existsSync(configPath) ? JSON.parse(import_fs8.default.readFileSync(configPath, "utf8")) : defaultAkanGlobalConfig;
1598
+ const akanConfig = import_fs7.default.existsSync(configPath) ? JSON.parse(import_fs7.default.readFileSync(configPath, "utf8")) : defaultAkanGlobalConfig;
1555
1599
  return akanConfig;
1556
1600
  };
1557
1601
  var setAkanGlobalConfig = (akanConfig) => {
1558
- import_fs8.default.mkdirSync(basePath, { recursive: true });
1559
- import_fs8.default.writeFileSync(configPath, JSON.stringify(akanConfig, null, 2));
1602
+ import_fs7.default.mkdirSync(basePath, { recursive: true });
1603
+ import_fs7.default.writeFileSync(configPath, JSON.stringify(akanConfig, null, 2));
1560
1604
  };
1561
1605
  var getHostConfig = (host = akanCloudHost) => {
1562
1606
  const akanConfig = getAkanGlobalConfig();
1563
- return akanConfig[host] ?? defaultHostConfig;
1607
+ return akanConfig.cloudHost[host] ?? defaultHostConfig;
1564
1608
  };
1565
1609
  var setHostConfig = (host = akanCloudHost, config = {}) => {
1566
1610
  const akanConfig = getAkanGlobalConfig();
@@ -1579,7 +1623,7 @@ var getSelf = async (token) => {
1579
1623
 
1580
1624
  // pkgs/@akanjs/devkit/src/capacitorApp.ts
1581
1625
  var import_project = require("@trapezedev/project");
1582
- var import_fs9 = __toESM(require("fs"), 1);
1626
+ var import_fs8 = __toESM(require("fs"));
1583
1627
  var CapacitorApp = class {
1584
1628
  constructor(app) {
1585
1629
  this.app = app;
@@ -1605,7 +1649,7 @@ var CapacitorApp = class {
1605
1649
  await this.project.commit();
1606
1650
  }
1607
1651
  async releaseIos() {
1608
- const isAdded = import_fs9.default.existsSync(`${this.app.cwdPath}/ios/App/Podfile`);
1652
+ const isAdded = import_fs8.default.existsSync(`${this.app.cwdPath}/ios/App/Podfile`);
1609
1653
  if (!isAdded) {
1610
1654
  await this.app.spawn("npx cap add ios");
1611
1655
  await this.app.spawn("npx @capacitor/assets generate");
@@ -1614,7 +1658,7 @@ var CapacitorApp = class {
1614
1658
  await this.app.spawn("cross-env", ["APP_OPERATION_MODE=release", "npx", "cap", "sync", "ios"]);
1615
1659
  }
1616
1660
  async releaseAndroid() {
1617
- const isAdded = import_fs9.default.existsSync(`${this.app.cwdPath}/android/app/build.gradle`);
1661
+ const isAdded = import_fs8.default.existsSync(`${this.app.cwdPath}/android/app/build.gradle`);
1618
1662
  if (!isAdded) {
1619
1663
  await this.app.spawn("npx cap add android");
1620
1664
  await this.app.spawn("npx @capacitor/assets generate");
@@ -1855,7 +1899,7 @@ var Target = {
1855
1899
  // pkgs/@akanjs/devkit/src/commandDecorators/command.ts
1856
1900
  var import_prompts3 = require("@inquirer/prompts");
1857
1901
  var import_commander = require("commander");
1858
- var import_fs10 = __toESM(require("fs"), 1);
1902
+ var import_fs9 = __toESM(require("fs"));
1859
1903
  var camelToKebabCase = (str) => str.replace(/([A-Z])/g, "-$1").toLowerCase();
1860
1904
  var handleOption = (programCommand, argMeta) => {
1861
1905
  const {
@@ -1902,7 +1946,7 @@ var getOptionValue = async (argMeta, opt) => {
1902
1946
  const message = ask ?? `Do you want to set ${name}? ${desc ? ` (${desc})` : ""}: `;
1903
1947
  return await (0, import_prompts3.confirm)({ message });
1904
1948
  } else {
1905
- const message = ask ?? `Enter the ${name} value${example ? ` (example: ${example})` : ""}: `;
1949
+ const message = ask ? `${ask}: ` : `Enter the ${name} value${example ? ` (example: ${example})` : ""}: `;
1906
1950
  if (argMeta.argsOption.nullable)
1907
1951
  return await (0, import_prompts3.input)({ message });
1908
1952
  else
@@ -1951,8 +1995,8 @@ var getArgumentValue = async (argMeta, value, workspace) => {
1951
1995
  throw new Error(`Invalid system type: ${argMeta.type}`);
1952
1996
  };
1953
1997
  var runCommands = async (...commands) => {
1954
- const hasPackageJson = import_fs10.default.existsSync(`${__dirname}/package.json`);
1955
- const version = hasPackageJson ? JSON.parse(import_fs10.default.readFileSync(`${__dirname}/package.json`, "utf8")).version : "0.0.1";
1998
+ const hasPackageJson = import_fs9.default.existsSync(`${__dirname}/package.json`);
1999
+ const version = hasPackageJson ? JSON.parse(import_fs9.default.readFileSync(`${__dirname}/package.json`, "utf8")).version : "0.0.1";
1956
2000
  import_commander.program.version(version).description("Akan CLI");
1957
2001
  for (const command of commands) {
1958
2002
  const targetMetas = getTargetMetas(command);
@@ -2002,15 +2046,64 @@ var runCommands = async (...commands) => {
2002
2046
  var import_prompts4 = require("@inquirer/prompts");
2003
2047
  var import_messages = require("@langchain/core/messages");
2004
2048
  var import_openai2 = require("@langchain/openai");
2049
+ var import_chalk = __toESM(require("chalk"));
2005
2050
  var MAX_ASK_TRY = 300;
2051
+ var supportedLlmModels = ["deepseek-chat", "deepseek-reasoner"];
2006
2052
  var AiSession = class _AiSession {
2007
- static #chat = new import_openai2.ChatOpenAI({
2008
- modelName: "deepseek-chat",
2009
- temperature: 0.7,
2010
- streaming: true,
2011
- // Enable streaming
2012
- configuration: { baseURL: "https://api.deepseek.com/v1", apiKey: process.env.DEEPSEEK_API_KEY }
2013
- });
2053
+ static #chat = null;
2054
+ static async init({ temperature = 0.7, useExisting = true } = {}) {
2055
+ if (useExisting) {
2056
+ const llmConfig2 = this.getLlmConfig();
2057
+ if (llmConfig2)
2058
+ return this.#setChatModel(llmConfig2.model, llmConfig2.apiKey);
2059
+ }
2060
+ const llmConfig = await this.#requestLlmConfig();
2061
+ const { model, apiKey } = llmConfig;
2062
+ await this.#validateApiKey(model, apiKey);
2063
+ return this.#setChatModel(model, apiKey, { temperature }).setLlmConfig({ model, apiKey });
2064
+ }
2065
+ static #setChatModel(model, apiKey, { temperature = 0.7 } = {}) {
2066
+ this.#chat = new import_openai2.ChatOpenAI({
2067
+ modelName: model,
2068
+ temperature,
2069
+ streaming: true,
2070
+ configuration: { baseURL: "https://api.deepseek.com/v1", apiKey }
2071
+ });
2072
+ return this;
2073
+ }
2074
+ static getLlmConfig() {
2075
+ const akanConfig = getAkanGlobalConfig();
2076
+ return akanConfig.llm ?? null;
2077
+ }
2078
+ static setLlmConfig(llmConfig) {
2079
+ const akanConfig = getAkanGlobalConfig();
2080
+ akanConfig.llm = llmConfig;
2081
+ setAkanGlobalConfig(akanConfig);
2082
+ return this;
2083
+ }
2084
+ static async #requestLlmConfig() {
2085
+ const model = await (0, import_prompts4.select)({ message: "Select a LLM model", choices: supportedLlmModels });
2086
+ const apiKey = await (0, import_prompts4.input)({ message: "Enter your API key" });
2087
+ return { model, apiKey };
2088
+ }
2089
+ static async #validateApiKey(modelName, apiKey) {
2090
+ const chat = new import_openai2.ChatOpenAI({
2091
+ modelName,
2092
+ temperature: 0,
2093
+ configuration: { baseURL: "https://api.deepseek.com/v1", apiKey }
2094
+ });
2095
+ try {
2096
+ await chat.invoke("Hi, and just say 'ok'");
2097
+ return true;
2098
+ } catch (error) {
2099
+ Logger.rawLog(
2100
+ import_chalk.default.red(
2101
+ `LLM API key is invalid. Please check your API key and try again. You can set it again by running "akan set-llm" or reset by running "akan reset-llm"`
2102
+ )
2103
+ );
2104
+ throw error;
2105
+ }
2106
+ }
2014
2107
  messageHistory = [];
2015
2108
  constructor(messageHistory = []) {
2016
2109
  this.messageHistory = messageHistory;
@@ -2020,6 +2113,8 @@ var AiSession = class _AiSession {
2020
2113
  Logger.raw(chunk);
2021
2114
  }
2022
2115
  } = {}) {
2116
+ if (!_AiSession.#chat)
2117
+ throw new Error("Please initialize the AI session first");
2023
2118
  try {
2024
2119
  const humanMessage = new import_messages.HumanMessage(question);
2025
2120
  this.messageHistory.push(humanMessage);
@@ -2032,6 +2127,8 @@ var AiSession = class _AiSession {
2032
2127
  onChunk(content);
2033
2128
  }
2034
2129
  }
2130
+ fullResponse += "\n";
2131
+ onChunk("\n");
2035
2132
  this.messageHistory.push(new import_messages.AIMessage(fullResponse));
2036
2133
  return { content: fullResponse, messageHistory: this.messageHistory };
2037
2134
  } catch (error) {
@@ -2060,8 +2157,8 @@ var AiSession = class _AiSession {
2060
2157
  return this.#getTypescriptCode(content);
2061
2158
  }
2062
2159
  #getTypescriptCode(content) {
2063
- const code = /```typescript([\s\S]*?)```/.exec(content);
2064
- return code ? code[1] : content;
2160
+ const code = /```(typescript|tsx)([\s\S]*?)```/.exec(content);
2161
+ return code ? code[2] : content;
2065
2162
  }
2066
2163
  };
2067
2164
 
@@ -2074,11 +2171,15 @@ var LibraryRunner = class {
2074
2171
  const scanResult = await lib.scan({ akanConfig });
2075
2172
  return scanResult;
2076
2173
  }
2174
+ async createLibrary(libName, workspace) {
2175
+ }
2176
+ async removeLibrary(lib) {
2177
+ await lib.workspace.exec(`rm -rf libs/${lib.name}`);
2178
+ lib.log(`Library ${lib.name} removed`);
2179
+ }
2077
2180
  async installLibrary(workspace, libName) {
2078
2181
  workspace.log(`Installing ${libName} library as git subtree...`);
2079
- await workspace.exec(
2080
- `git subtree add --quiet --prefix=libs/${libName} git@github.com:akan-team/${libName}.git main`
2081
- );
2182
+ await workspace.exec(`git subtree add --prefix=libs/${libName} git@github.com:akan-team/${libName}.git main`);
2082
2183
  await workspace.cp(`libs/${libName}/env/env.server.example.ts`, `libs/${libName}/env/env.server.testing.ts`);
2083
2184
  workspace.setTsPaths("lib", libName);
2084
2185
  await workspace.commit(`Add ${libName} library`);
@@ -2112,13 +2213,13 @@ var LibraryRunner = class {
2112
2213
  }
2113
2214
  async pushLibrary(lib, branch) {
2114
2215
  await lib.workspace.exec(
2115
- `git subtree push --quiet --prefix=libs/${lib.name} git@github.com:akan-team/${lib.name}.git ${branch}`
2216
+ `git subtree push --prefix=libs/${lib.name} git@github.com:akan-team/${lib.name}.git ${branch}`
2116
2217
  );
2117
2218
  lib.logger.log(`${lib.name} library pushed to ${branch} branch`);
2118
2219
  }
2119
2220
  async pullLibrary(lib, branch) {
2120
2221
  await lib.workspace.exec(
2121
- `git subtree pull --quiet --prefix=libs/${lib.name} git@github.com:akan-team/${lib.name}.git ${branch}`
2222
+ `git subtree pull --prefix=libs/${lib.name} git@github.com:akan-team/${lib.name}.git ${branch}`
2122
2223
  );
2123
2224
  lib.logger.log(`${lib.name} library pulled from ${branch} branch`);
2124
2225
  }
@@ -2165,6 +2266,12 @@ var LibraryScript = class {
2165
2266
  for (const libName of scanResult.akanConfig.libs)
2166
2267
  await this.syncLibrary(LibExecutor.from(lib.workspace, libName), { recursive: false });
2167
2268
  }
2269
+ async createLibrary(libName, workspace) {
2270
+ await this.#runner.createLibrary(libName, workspace);
2271
+ }
2272
+ async removeLibrary(lib) {
2273
+ await this.#runner.removeLibrary(lib);
2274
+ }
2168
2275
  async installLibrary(workspace, libName) {
2169
2276
  const lib = await this.#runner.installLibrary(workspace, libName);
2170
2277
  workspace.log(`${libName} library installed`);
@@ -2191,7 +2298,7 @@ var import_openai3 = require("@langchain/openai");
2191
2298
  var import_plugin_react = __toESM(require("@vitejs/plugin-react"));
2192
2299
  var import_dotenv3 = __toESM(require("dotenv"));
2193
2300
  var esbuild = __toESM(require("esbuild"));
2194
- var import_fs12 = __toESM(require("fs"));
2301
+ var import_fs10 = __toESM(require("fs"));
2195
2302
  var import_promises2 = __toESM(require("fs/promises"));
2196
2303
  var import_js_yaml2 = __toESM(require("js-yaml"));
2197
2304
  var import_open = __toESM(require("open"));
@@ -2202,8 +2309,9 @@ var import_vite_plugin_node_polyfills = require("vite-plugin-node-polyfills");
2202
2309
  var import_vite_tsconfig_paths = __toESM(require("vite-tsconfig-paths"));
2203
2310
 
2204
2311
  // pkgs/@akanjs/cli/src/module/module.prompt.ts
2205
- var import_fs11 = __toESM(require("fs"));
2206
- var frameworkDescription = `\uB098\uB294 \uC880 \uB354 \uD6A8\uC728\uC801\uC73C\uB85C \uCF54\uB529\uC744 \uD558\uAE30 \uC704\uD574\uC11C \uC790\uCCB4 \uD504\uB808\uC784\uC6CC\uD06C\uB97C \uC81C\uC791\uD588\uC5B4. \uADF8\uB798\uC11C \uC6B0\uB9AC \uD504\uB808\uC784\uC6CC\uD06C\uC5D0 \uB300\uD55C \uC124\uBA85\uC744 \uD574\uC904\uD14C\uB2C8\uAE4C \uC798 \uC774\uD574\uD558\uB3C4\uB85D \uD574. \uC6B0\uB9AC \uD504\uB808\uC784\uC6CC\uD06C\uB294 next.js 13\uACFC nest.js, capacitor.js, nx, mongoDB \uAE30\uBC18\uC758 \uD504\uB860\uD2B8\uC5D4\uB4DC, \uC571, \uBC31\uC5D4\uB4DC \uD1B5\uD569 \uD504\uB808\uC784\uC6CC\uD06C\uC57C. \uADF8\uB798\uC11C \uBC31\uC5D4\uB4DC, \uD504\uB860\uD2B8\uC5D4\uB4DC, DB Schema\uC5D0 \uB300\uD55C \uCF54\uB4DC\uAC00 \uBAA8\uB450 \uD55C \uD3F4\uB354 \uC548\uC5D0 \uC788\uC5B4. \uADF8\uB798\uC11C \uC790\uBC14\uC2A4\uD06C\uB9BD\uD2B8, \uD0C0\uC785\uC2A4\uD06C\uB9BD\uD2B8, \uADF8\uB9AC\uACE0 \uD504\uB808\uC784\uC6CC\uD06C\uC5D0 \uB300\uD55C \uC774\uD574\uB9CC \uC788\uB2E4\uBA74 \uAD6C\uBD84\uC9D3\uC9C0 \uC54A\uACE0 \uC0AC\uC6A9\uD560 \uC218 \uC788\uB2E4\uB294 \uC7A5\uC810\uC774 \uC788\uC5B4.
2312
+ var frameworkDescription = `
2313
+ \uB098\uB294 \uC880 \uB354 \uD6A8\uC728\uC801\uC73C\uB85C \uCF54\uB529\uC744 \uD558\uAE30 \uC704\uD574\uC11C \uC790\uCCB4 \uD504\uB808\uC784\uC6CC\uD06C\uB97C \uC81C\uC791\uD588\uC5B4.
2314
+ \uADF8\uB798\uC11C \uC6B0\uB9AC \uD504\uB808\uC784\uC6CC\uD06C\uC5D0 \uB300\uD55C \uC124\uBA85\uC744 \uD574\uC904\uD14C\uB2C8\uAE4C \uC798 \uC774\uD574\uD558\uB3C4\uB85D \uD574. \uC6B0\uB9AC \uD504\uB808\uC784\uC6CC\uD06C\uB294 next.js 13\uACFC nest.js, capacitor.js, nx, mongoDB \uAE30\uBC18\uC758 \uD504\uB860\uD2B8\uC5D4\uB4DC, \uC571, \uBC31\uC5D4\uB4DC \uD1B5\uD569 \uD504\uB808\uC784\uC6CC\uD06C\uC57C. \uADF8\uB798\uC11C \uBC31\uC5D4\uB4DC, \uD504\uB860\uD2B8\uC5D4\uB4DC, DB Schema\uC5D0 \uB300\uD55C \uCF54\uB4DC\uAC00 \uBAA8\uB450 \uD55C \uD3F4\uB354 \uC548\uC5D0 \uC788\uC5B4. \uADF8\uB798\uC11C \uC790\uBC14\uC2A4\uD06C\uB9BD\uD2B8, \uD0C0\uC785\uC2A4\uD06C\uB9BD\uD2B8, \uADF8\uB9AC\uACE0 \uD504\uB808\uC784\uC6CC\uD06C\uC5D0 \uB300\uD55C \uC774\uD574\uB9CC \uC788\uB2E4\uBA74 \uAD6C\uBD84\uC9D3\uC9C0 \uC54A\uACE0 \uC0AC\uC6A9\uD560 \uC218 \uC788\uB2E4\uB294 \uC7A5\uC810\uC774 \uC788\uC5B4.
2207
2315
 
2208
2316
  \uAC00\uC7A5 \uC678\uBD80\uC758 \uAD6C\uC870\uB294
2209
2317
  - app
@@ -2721,6 +2829,433 @@ export const General = ({ className, \${dict.model}, self }: \${dict.Model}ViewP
2721
2829
 
2722
2830
  \uC77C\uB2E8 \uD504\uB808\uC784\uC6CC\uD06C\uC5D0 \uB300\uD55C \uC124\uBA85\uC740 \uC774 \uC815\uB3C4\uB85C \uD558\uACE0 \uC774 \uC815\uBCF4\uB4E4\uC744 \uAE30\uBC18\uC73C\uB85C \uB0B4\uAC00 \uC6D0\uD558\uB294 \uC694\uAD6C\uB97C \uB4E4\uC5B4\uC918.
2723
2831
  `;
2832
+ var moduleDesription = `
2833
+
2834
+ The project follows a modular architecture with clear separation of concerns. Each module in lib/<model>/ represents a domain
2835
+ entity with a standardized file structure that promotes consistency and maintainability.
2836
+
2837
+ ## Core Components
2838
+
2839
+ ### <Model>.View.tsx
2840
+ Presentation-only components that render data without managing state.
2841
+ It works as a server component, They accept model data as props and display it according to specific layouts.
2842
+ These components focus purely on how data looks to the user.
2843
+ only use the full model.
2844
+ This component is only viewing the component. So don't use click event or other interaction events.
2845
+ If you need interaction, possible to wrapping the component with the <Model>.Zone.tsx component.
2846
+ But useable the Link component for navigation.
2847
+ Components created in Model.View.tsx should primarily be made to show the entire detailed data of the model rather than showing only partial data of the model.
2848
+
2849
+
2850
+ ### <Model>.Template.tsx
2851
+ Reusable layout patterns with integrated state management. It works as a client component, These components provide consistent UI patterns and handle data
2852
+ binding, often using store hooks to access application state.
2853
+
2854
+ ### <Model>.Unit.tsx
2855
+ Small, self-contained UI components representing individual model instances. It works as a server component, They're designed for rendering single items in
2856
+ lists or grids, displaying model data in compact formats. only use the light model.
2857
+
2858
+ ### <Model>.Zone.tsx
2859
+ Top-level container components that orchestrate other components. It works as a client component, They compose views, templates, and units into complete UI
2860
+ sections while managing data flow to child components.
2861
+
2862
+ ### <Model>.Util.tsx
2863
+ Specialized components and utility functions specific to a model, It works as a client component, providing both UI components and helper functions for
2864
+ model-specific functionality.
2865
+
2866
+ ## Data Management
2867
+
2868
+ ### <model>.signal.ts
2869
+ Defines API endpoints with type safety using decorators for GraphQL queries and mutations, creating a type-safe bridge between
2870
+ frontend and backend.
2871
+
2872
+ ### <model>.store.ts
2873
+ Manages client-side state with typed actions and state, handling UI state, form state, and cached data.
2874
+
2875
+ ### <model>.service.ts
2876
+ Implements server-side business logic with dependency injection, handling data processing and complex operations.
2877
+
2878
+ ### <model>.constant.ts
2879
+ Defines type definitions and model schemas using decorators to structure model fields, validation, and relationships.
2880
+
2881
+ ### <model>.dictionary.ts
2882
+ Provides internationalization and label definitions for model properties and operations.
2883
+
2884
+ ### <model>.document.ts
2885
+ Defines database schema and model operations with decorators for database interaction.
2886
+
2887
+ ## Data Flow
2888
+ The architecture follows a clear data flow pattern:
2889
+ - Server-side: Document \u2192 Service \u2192 Signal \u2192 API
2890
+ - Client-side: API \u2192 Store \u2192 Components (Zone \u2192 Template/View/Unit)
2891
+
2892
+ This modular structure enables rapid development while maintaining consistency, type safety, and testability throughout the
2893
+ application.
2894
+ `;
2895
+ var utilUiDescription = `
2896
+ This UI kit is an internally developed UI kit within the Akan.js framework.
2897
+ The libs/util/ui directory contains a comprehensive React component library designed for modern web applications.
2898
+ This framework provides a complete set of production-ready, reusable UI components with consistent styling, type safety, and advanced functionality.
2899
+
2900
+ - Every component must be used exactly as described in the documentation.
2901
+ - Do not add any additional props to the components.
2902
+ - Must use the written props exactly.
2903
+ - Only the components explicitly listed in the documentation are available\u2014no additional components exist beyond those specified.
2904
+
2905
+
2906
+
2907
+ Architecture & Foundation
2908
+
2909
+ Core Technologies:
2910
+ - Built on React 18+ with TypeScript for strict type safety
2911
+ - Styled with Tailwind CSS and DaisyUI for consistent design system
2912
+ - Implements modern React patterns including hooks, context providers, and portals
2913
+ - Full internationalization (i18n) support for multilingual applications
2914
+ - Responsive-first design with mobile optimization
2915
+
2916
+ Design Principles:
2917
+ - Composable component architecture with predictable APIs
2918
+ - Accessibility (a11y) compliance throughout
2919
+ - Performance optimization with lazy loading and code splitting
2920
+ - Consistent error handling and validation patterns
2921
+ - Session storage integration for form state persistence
2922
+
2923
+ Component Categories
2924
+
2925
+ Core Input Components
2926
+
2927
+ Essential form controls with advanced validation and user experience features:
2928
+ - Button - Async-aware button with automatic loading/success/error states
2929
+ - Input - Comprehensive input system with real-time validation, multiple variants (Text, Password, Email, Number, Checkbox), and
2930
+ session caching
2931
+ - Select - Advanced dropdown with search, multi-select, and custom rendering
2932
+ - DatePicker - Date/time selection with range support and custom formatting
2933
+ - CodeInput - PIN/verification code input with auto-focus management
2934
+ - Upload - File upload system with drag-drop, progress tracking, image cropping, and multiple file support
2935
+
2936
+ Data Display Components
2937
+
2938
+ Components for presenting and organizing information:
2939
+ - Chart - Visualization suite (Bar, Line, Pie, Doughnut) built on Chart.js
2940
+ - Avatar - User profile images with intelligent fallbacks
2941
+ - ChatBubble - Chat interface with message grouping and timestamps
2942
+ - Empty - Customizable empty state displays
2943
+ - QRCode - QR code generation with click-to-open functionality
2944
+
2945
+ Layout & Navigation System
2946
+
2947
+ Comprehensive layout framework for application structure:
2948
+ - Layout - Complete layout system with Header (auto-hide), Sider (collapsible), Navbar (portal-based), BottomTab (with badges),
2949
+ and container components
2950
+ - Modal/Dialog - Composable dialog system with backdrop, animations, and gesture support
2951
+ - BottomSheet - Mobile-optimized bottom sheet with drag gestures
2952
+ - Menu - Navigation menus with horizontal/vertical modes and submenu support
2953
+ - Tab - Tabbed interfaces with lazy loading and scroll management
2954
+ - ScreenNavigator - Gesture-based screen navigation with spring animations
2955
+
2956
+ Interactive Components
2957
+
2958
+ Advanced user interaction components:
2959
+ - Pagination - Smart page navigation with ellipsis and responsive design
2960
+ - InfiniteScroll - Automatic content loading with intersection observer
2961
+ - DndKit - Drag and drop functionality with provider pattern
2962
+ - Radio - Radio button groups with custom styling
2963
+ - ToggleSelect - Button-based selection with single/multi-select modes
2964
+ - Share - Native share API with copy fallback
2965
+
2966
+ Utility & Feedback Components
2967
+
2968
+ Supporting components for enhanced user experience:
2969
+ - Loading - Comprehensive loading states (Area, Button, Input, Skeleton, Spin, ProgressBar) with animations
2970
+ - Link - Adaptive navigation links with SSR/CSR compatibility
2971
+ - MapView - Map integration supporting both Google Maps and Pigeon Maps with markers and overlays
2972
+ - Image - Optimized image component with blur placeholders and SSR support
2973
+ - Portal - Teleportation component for rendering outside component tree
2974
+
2975
+ Advanced Features
2976
+
2977
+ State Management Integration
2978
+
2979
+ - Context-driven architecture for complex components
2980
+ - Signal-based real-time communication components
2981
+ - Session storage integration for form persistence
2982
+ - Theme-aware styling with automatic adaptation
2983
+
2984
+ Performance Optimizations
2985
+
2986
+ - Lazy loading support for heavy components
2987
+ - Code splitting at component level
2988
+ - Optimized re-rendering with React.memo patterns
2989
+ - Intersection Observer for scroll-based interactions
2990
+
2991
+ Developer Experience
2992
+
2993
+ - Comprehensive TypeScript interfaces for all props
2994
+ - Consistent naming conventions and API patterns
2995
+ - Built-in error boundaries and fallback handling
2996
+ - Extensive JSDoc documentation
2997
+ - Hot reload support for development
2998
+
2999
+ Accessibility & Internationalization
3000
+
3001
+ - ARIA attributes and keyboard navigation support
3002
+ - Screen reader compatibility
3003
+ - RTL (right-to-left) language support
3004
+ - Localized date/time formatting
3005
+ - Color contrast compliance
3006
+
3007
+ Usage Patterns
3008
+
3009
+ The library follows a consistent component composition pattern where complex components are built from smaller, focused
3010
+ subcomponents. For example:
3011
+
3012
+ - Chart.Bar, Chart.Line for different visualization types
3013
+ - Dialog.Modal, Dialog.Title, Dialog.Content for composable modals
3014
+ - Layout.Header, Layout.Sider, Layout.Navbar for layout construction
3015
+ - Upload.File, Upload.Image, Upload.Images for different upload scenarios
3016
+
3017
+ This design enables maximum flexibility while maintaining consistency across the application. Components are designed to work
3018
+ seamlessly together, sharing common styling patterns, validation systems, and state management approaches.
3019
+
3020
+ The library serves as a comprehensive foundation for building modern, accessible, and performant web applications with a focus
3021
+ on developer productivity and end-user experience.
3022
+
3023
+ Avatar
3024
+ - Displays user profile images with automatic fallback to user icon
3025
+ - Props: className?: string, icon?: ReactNode, src?: string
3026
+
3027
+ Button
3028
+ - Enhanced button with automatic loading states and error handling
3029
+ - Props: onClick: (e, {onError}) => Promise<Result>, onSuccess?: (result) => void, className?, children, standard button props
3030
+
3031
+ Input
3032
+ - Comprehensive input system with real-time validation and caching
3033
+ - Props: value: string, validate: (value) => boolean | string, onChange?, nullable?, inputStyleType?: "bordered" | "borderless"
3034
+ | "underline", icon?, cacheKey?
3035
+ - Variants: Input.TextArea, Input.Password, Input.Email, Input.Number, Input.Checkbox
3036
+
3037
+ Select
3038
+ - Advanced dropdown with search and multi-select capabilities
3039
+ - Props: value: T | T[], options: {label, value}[], multiple?, searchable?, onChange, onSearch?, renderOption?, renderSelected?
3040
+
3041
+ DatePicker
3042
+ - Date/time picker with range selection support
3043
+ - Props: value?: Dayjs, onChange, showTime?, format?, disabledDate?
3044
+ - Variants: DatePicker.RangePicker, DatePicker.TimePicker
3045
+
3046
+ CodeInput
3047
+ - PIN/code input with individual character boxes
3048
+ - Props: maxNum: number, value: string, onChange, unitStyle?: "box" | "underline", autoComplete?
3049
+
3050
+ Display Components
3051
+
3052
+ Table
3053
+ - Feature-rich data table with pagination and responsive design
3054
+ - Props: columns: Column[], dataSource: any[], loading?, pagination?, onRow?, rowClassName?
3055
+
3056
+ Modal
3057
+ - Dialog modal with backdrop and action buttons
3058
+ - Props: open: boolean, onCancel, title?, action?, confirmClose?
3059
+ - Variants: Modal.Window
3060
+
3061
+ Image
3062
+ - Optimized image component with blur placeholder and SSR support
3063
+ - Props: src?, file?: ProtoFile, abstractData?, alt?, standard Next.js Image props
3064
+
3065
+ ChatBubble
3066
+ - Chat message bubble with avatar and timestamp
3067
+ - Props: avatar?, hasPrev?, hasNext?, isMe?, name?, at?: Dayjs, children
3068
+
3069
+ Empty
3070
+ - Empty state placeholder with customizable message
3071
+ - Props: description?, minHeight?, children?
3072
+
3073
+ QRCode
3074
+ - QR code generator with click-to-open functionality
3075
+ - Props: href: string, className?
3076
+
3077
+ Layout Components
3078
+
3079
+ BottomSheet
3080
+ - Only mobile bottom sheet with drag gestures
3081
+ - Props: open: boolean, onCancel, type: "full" | "half", children
3082
+
3083
+ Layout
3084
+ Layout - Complete layout framework with responsive design
3085
+ - Layout.Header - Top header with auto-hide functionality
3086
+ - Props: className?: string, type?: "static" | "hide", children?: any, height?: number
3087
+ - Features: Auto-hide on scroll, fixed positioning
3088
+ - Layout.Sider - Collapsible sidebar
3089
+ - Props: className?: string, bgClassName?: string, children?: any
3090
+ - Features: Drawer-based with toggle functionality
3091
+ - Layout.Navbar - Navigation bar with portal content
3092
+ - Props: className?: string, children?: ReactNode, height?:
3093
+
3094
+ Menu
3095
+ - Navigation menu with horizontal/vertical modes and submenu support
3096
+ - Props: items: MenuItem[], mode?: "horizontal" | "inline", selectedKeys?, onClick?, inlineCollapsed?
3097
+
3098
+
3099
+ Tab
3100
+ - Tabbed interface system
3101
+ - Tab.Provider - Tab context provider
3102
+ - Props: className?: string, defaultMenu?: string | null, children?: any
3103
+ - Tab.Menu - Tab menu item
3104
+ - Props: className?: string, activeClassName?: string, disabledClassName?: string, disabled?: boolean, menu: string, children:
3105
+ any, scrollToTop?: boolean, tooltip?: string
3106
+ - Tab.Panel - Tab content panel
3107
+ - Props: className?: string, menu: string, children?: any, loading?: "eager" | "lazy" | "every"
3108
+ - Features: Lazy loading support
3109
+
3110
+ ScreenNavigator
3111
+ - Gesture-based screen navigation
3112
+ - ScreenNavigator.Provider - Navigation context provider
3113
+ - Props: setMenu?: (menu: string) => void, children: ReactNode, menus: string[]
3114
+ - Features: Gesture-based navigation, spring animations
3115
+ - ScreenNavigator.Screen - Individual screen container
3116
+ - Props: children: ReactNode, className?: string
3117
+ - ScreenNavigator.NavbarItem - Navigation bar item
3118
+ - Props: menu: string, children: ReactNode, className?: string
3119
+
3120
+ Upload
3121
+ - File upload system with multiple modes
3122
+ - Upload
3123
+ - Basic file upload with drag & drop
3124
+ - Props: onChange?: (fileList: FileList) => void; multiple?: boolean; accept?: string; className?: string; uploadClassName?: string; children: React.ReactNode; disabled?: boolean;
3125
+ - Upload.File
3126
+ - Single file upload with preview
3127
+ - Props: multiple?: boolean; file: ProtoFile | null; render?: (file: ProtoFile) => React.ReactNode; onChange?: (e: File | FileList) => void | Promise<void>; onRemove?: (e: any) => void; children?: React.ReactNode; disabled?: boolean; maxCount?: number; className?: string; uploadClassName?: string; accept?: string;
3128
+ - Upload.FileList
3129
+ - Multiple files with table view and progress tracking
3130
+ - Props: multiple?: boolean; fileList: ProtoFile[]; render?: (file: ProtoFile) => React.ReactNode; onChange?: (e: File | FileList) => void | Promise<void>; onRemove?: (e: any) => void; children?: React.ReactNode; disabled?: boolean; maxCount?: number; className?: string; uploadClassName?: string; accept?: string;
3131
+ - Upload.Image
3132
+ - Image upload with integrated cropping functionality
3133
+ - Props: multiple?: boolean; file: ProtoFile | null; render?: (file: ProtoFile) => React.ReactNode; onChange?: (e: File | FileList) => void | Promise<void>; onRemove?: (e: any) => void; children?: React.ReactNode; disabled?: boolean; maxCount?: number; className?: string; uploadClassName?: string; accept?: string;
3134
+ - Upload.Images
3135
+ - Multiple image upload with gallery preview
3136
+ - Props: multiple?: boolean; fileList: ProtoFile[]; render?: (file: ProtoFile) => React.ReactNode; onChange?: (e: File | FileList) => void | Promise<void>; onRemove?: (e: any) => void; children?: React.ReactNode; disabled?: boolean; maxCount?: number; className?: string; uploadClassName?: string; accept?: string;
3137
+
3138
+ DndKit
3139
+ - Drag and drop functionality built on @dnd-kit
3140
+ - DndKit.Provider
3141
+ - DnD context provider
3142
+ - Props: className?: string + all DndContextProps
3143
+ - DndKit.DraggableUnit
3144
+ - Draggable item wrapper
3145
+ - Props: id: string, children: ReactNode, className?: string, onClick?: () => void | Promise<void>
3146
+ - DndKit.DroppableColumn
3147
+ - Drop target column
3148
+ - Props: id: string, items: T[], className?: string, children: ReactNode, onOver?: (id, items, event) => void, onEnd?: (id,
3149
+ item, event) => void
3150
+
3151
+ MapView
3152
+ - Map integration with multiple providers
3153
+ - MapView.Map
3154
+ - Main map container with theme awareness
3155
+ - Props: className?: string, onLoad?: () => void, onClick?: (coordinate) => void, onRightClick?: (coordinate) => void,
3156
+ onMouseMove?: (coordinate) => void, children: any
3157
+ - MapView.Marker
3158
+ - Map marker component
3159
+ - Props: coordinate: cnst.Coordinate, zIndex?: number, children?: any
3160
+ - MapView.Google
3161
+ - Google Maps implementation
3162
+ - Props: id?: string, className?: string, mapKey: string, onClick/onRightClick?: (coordinate) => void, center?:
3163
+ cnst.Coordinate, onChangeCenter?: (coordinate) => void, zoom?: number, onChangeZoom?: (zoom) => void, bounds?: {minLat, maxLat,
3164
+ minLng, maxLng}, onLoad?: () => void, onMouseMove?: (coordinate, event) => void, options?: google.maps.MapOptions, children: any
3165
+ - MapView.Pigeon
3166
+ - Pigeon Maps implementation (lightweight alternative)
3167
+ - Props: id?: string, className?: string, onLoad?: () => void, onClick/onRightClick?: (coordinate) => void, center?:
3168
+ cnst.Coordinate, onChangeCenter?: (coordinate) => void, zoom?: number, onChangeZoom?: (zoom) => void, bounds?: {minLat, maxLat,
3169
+ minLng, maxLng}, onChangeBounds?: (bounds) => void, mouseEvents?: boolean, onMouseMove?: (coordinate) => void, mapTiler?: (x, y,
3170
+ z, dpr) => string, children?: any, zoomControlStyle?: CSSProperties
3171
+
3172
+
3173
+ Pagination
3174
+ - Page navigation with smart ellipsis and responsive design
3175
+ - Props: currentPage: number, total: number, onPageSelect, itemsPerPage: number
3176
+
3177
+ Radio
3178
+ - Radio button group with custom styling support
3179
+ - Props: value, children: ReactElement[], onChange, disabled?
3180
+
3181
+ ToggleSelect
3182
+ - Button-based selection with single/multi-select modes
3183
+ - Props: items, value, validate, onChange, nullable
3184
+ - Variants: ToggleSelect.Multi
3185
+
3186
+ Share
3187
+ - Native share API with copy fallback
3188
+ - Props: title: string, url: string, children
3189
+
3190
+ Specialized Component Groups
3191
+
3192
+ Chart
3193
+ - Visualization components built on Chart.js and react-chartjs-2
3194
+ - Chart.Bar - Bar chart component
3195
+ - Props: data: ChartData<"bar">, options?: ChartOptions<"bar">
3196
+ - Features: Responsive layout, legend display, title configuration
3197
+ - Chart.Line - Line chart component
3198
+ - Props: data: ChartData<"line">, options?: ChartOptions<"line">
3199
+ - Features: Line-specific Chart.js configuration with curve interpolation
3200
+ - Chart.Pie - Pie chart component
3201
+ - Props: data: ChartData<"pie">, options?: ChartOptions<"pie">
3202
+ - Features: ArcElement rendering, responsive design
3203
+ - Chart.Doughnut - Doughnut chart component
3204
+ - Props: data: ChartData<"doughnut">, options?: ChartOptions<"doughnut">
3205
+ - Features: Similar to pie but with center cutout
3206
+
3207
+ Dialog
3208
+ - Composable modal dialog system built on Radix UI
3209
+ - Dialog.Provider - Dialog context provider
3210
+ - Props: className?: string, open?: boolean, defaultOpen?: boolean, children?: any
3211
+ - Dialog.Modal - Main modal container
3212
+ - Props: className?: string, bodyClassName?: string, confirmClose?: boolean, children?: any, onCancel?: () => void
3213
+ - Features: Drag gestures, spring animations, responsive design, close confirmation
3214
+ - Dialog.Title - Modal title component
3215
+ - Props: children?: ReactNode
3216
+ - Dialog.Content - Modal content area
3217
+ - Props: className?: string, children?: ReactNode
3218
+ - Dialog.Action - Modal action buttons container
3219
+ - Props: children?: ReactNode
3220
+ - Dialog.Trigger - Modal trigger element
3221
+ - Props: className?: string, children?: any
3222
+
3223
+ Link
3224
+ - Adaptive navigation system
3225
+ - Link
3226
+ - Main adaptive link (auto-switches between CSR/Next.js based on render mode)
3227
+ - Link.Back - Back navigation link
3228
+ - Props: className?: string, children?: any
3229
+ - Features: Browser history integration
3230
+ - Link.Close - Window close link
3231
+ - Props: Similar to Back but closes window
3232
+ - Link.CsrLink & Link.NextLink - Environment-specific implementations with active state support
3233
+
3234
+
3235
+ Loading
3236
+ - Loading states for different UI elements
3237
+ - Loading.Area - Full-screen loading overlay with animated dots
3238
+ - Loading.Button - Button loading skeleton
3239
+ - Props: className?: string, active?: boolean, style?: CSSProperties
3240
+ - Loading.Input - Input loading skeleton
3241
+ - Loading.Skeleton - Multi-line content skeleton with pulse animation
3242
+ - Loading.Spin - Custom loading spinner
3243
+ - Props: indicator?: ReactNode, isCenter?: boolean
3244
+ - Loading.ProgressBar - Animated progress bar
3245
+ - Props: className?: string, value: number, max: number
3246
+ - Features: React Spring animations
3247
+
3248
+ Key Framework Features
3249
+
3250
+ - TypeScript support with strict typing
3251
+ - Responsive design with mobile-first approach
3252
+ - Internationalization (i18n) integration
3253
+ - Session storage caching for form inputs
3254
+ - Accessibility compliance
3255
+ - Consistent DaisyUI/Tailwind CSS styling
3256
+ - Modern React patterns (hooks, context, providers)
3257
+ - Error handling and validation systems
3258
+ `;
2724
3259
  var frameworkAbstract = `
2725
3260
  Intro
2726
3261
  - Build an all-stack application at once.
@@ -2740,7 +3275,66 @@ Procedure
2740
3275
  - No Spaghetti Components anymore, build your page with domain-driven components
2741
3276
  - write one page, use SSR on Next.js and build Android&iOS CSR app with beautiful page transitions!
2742
3277
  - built-in ai code generation, tell about business, the logic is generated.
3278
+
3279
+
2743
3280
  `;
3281
+ var eslintDescription = `
3282
+ Core ESLint Extensions
3283
+
3284
+ Base Configurations:
3285
+ - eslint:recommended - Standard ESLint recommended rules
3286
+ - next & next/core-web-vitals - Next.js specific linting rules
3287
+ - @typescript-eslint/recommended-type-checked - TypeScript recommended rules with type checking
3288
+ - @typescript-eslint/strict-type-checked - Strict TypeScript type checking rules
3289
+ - @typescript-eslint/stylistic-type-checked - TypeScript stylistic rules with type checking
3290
+
3291
+ Third-Party Plugins
3292
+
3293
+ 1. eslint-plugin-unused-imports
3294
+ - Automatically detects and warns about unused imports
3295
+ - Helps keep code clean by removing unnecessary import statements
3296
+
3297
+ 2. eslint-plugin-simple-import-sort
3298
+ - Automatically sorts import statements in a consistent order
3299
+ - Enforces clean import organization throughout the codebase
3300
+
3301
+ Custom Plugin: @akanjs/lint
3302
+
3303
+ 1. useClientByFile
3304
+ - Enforces proper "use client" directive usage in Next.js App Router
3305
+ - Server files must NOT have "use client" directive
3306
+ - Client files MUST have "use client" directive at the top
3307
+
3308
+ 2. noImportClientFunctions
3309
+ - Prevents server files from importing client-side functions
3310
+ - Ensures proper separation between server and client code
3311
+
3312
+ 3. nonScalarPropsRestricted
3313
+ - Prevents non-scalar props (functions) in server components
3314
+ - Specifically targets page.tsx and layout.tsx files
3315
+ - Allows exceptions for specific props like "loader", "render", and "of"
3316
+
3317
+ 4. noImportExternalLibrary
3318
+ - Restricts external library imports in pure import/re-export files
3319
+ - Only allows imports from the same app scope (@appName/...)
3320
+ - Promotes clean architecture and prevents dependency leakage
3321
+
3322
+ Key Rule Configurations
3323
+
3324
+ Disabled Rules:
3325
+ - no-console: "error" - Prevents console statements in production code
3326
+ - Various TypeScript strict rules are disabled for flexibility
3327
+ - React and Next.js specific rules are relaxed for development ease
3328
+
3329
+ Import Management:
3330
+ - unused-imports/no-unused-imports: "warn" - Warns about unused imports
3331
+ - simple-import-sort/imports: "warn" - Enforces import sorting
3332
+ - import/first: "warn" - Ensures imports come first
3333
+ - import/newline-after-import: "warn" - Enforces newline after imports
3334
+
3335
+ This configuration creates a robust linting setup that enforces Next.js App Router best practices, maintains clean code
3336
+ organization, and ensures proper server/client code separation.
3337
+ `;
2744
3338
  var scalarConstantDescription = `
2745
3339
  Purpose and Structure
2746
3340
 
@@ -3095,10 +3689,10 @@ ${frameworkAbstract}
3095
3689
  2. <model>.constant.ts \uD30C\uC77C\uC5D0 \uB300\uD55C \uAC1C\uC694
3096
3690
  ${scalarConstantDescription}
3097
3691
 
3098
- 3. <model.constant.ts \uD30C\uC77C\uC758 Enum \uC791\uC131\uBC95
3692
+ 3. <model>.constant.ts \uD30C\uC77C\uC758 Enum \uC791\uC131\uBC95
3099
3693
  ${howToSetEnumInModelConstant}
3100
3694
 
3101
- 4. <model.constant.ts \uD30C\uC77C\uC758 Field \uC791\uC131\uBC95
3695
+ 4. <model>.constant.ts \uD30C\uC77C\uC758 Field \uC791\uC131\uBC95
3102
3696
  ${howToSetFieldInModelConstant}
3103
3697
 
3104
3698
  5. \uD604\uC7AC \uD504\uB85C\uC81D\uD2B8 \uB0B4 \uB2E4\uB978 constant.ts \uD30C\uC77C\uB4E4\uC5D0 \uB300\uD55C \uC608\uC2DC
@@ -3123,6 +3717,87 @@ Target filename: ${modelName}.constant.ts
3123
3717
  \`\`\`
3124
3718
  ${boilerplate}
3125
3719
  \`\`\`
3720
+ `;
3721
+ var requestView = ({
3722
+ sysName,
3723
+ modelName,
3724
+ ModelName,
3725
+ boilerplate,
3726
+ constant,
3727
+ properties,
3728
+ exampleFiles
3729
+ }) => `
3730
+
3731
+
3732
+ 1. Akan.js \uD504\uB808\uC784\uC6CC\uD06C\uC5D0 \uB300\uD55C \uAC1C\uC694
3733
+ ${frameworkAbstract}
3734
+
3735
+ 2. Akan.js\uD504\uB808\uC784\uC6CC\uD06C \uB370\uC774\uD130 \uAE30\uBC18 \uBAA8\uB4C8\uC5D0 \uB300\uD55C \uAC1C\uC694
3736
+ ${moduleDesription}
3737
+
3738
+ 3. Akan.js eslint \uC124\uC815\uC5D0 \uB300\uD55C \uAC1C\uC694
3739
+ ${eslintDescription}
3740
+
3741
+ 4. util/ui \uB0B4 ui\uD0B7\uC5D0 \uB300\uD55C \uAC1C\uC694
3742
+ ${utilUiDescription}
3743
+
3744
+
3745
+
3746
+ 5. ${ModelName}.constant.ts \uD30C\uC77C\uC5D0 \uB300\uD55C \uC815\uBCF4
3747
+ ${constant}
3748
+
3749
+ 6. ${modelName}\uC5D0\uC11C \uC885\uC18D\uB418\uB294 \uB2E4\uB978 \uBAA8\uB378\uB4E4\uC758 \uD0C0\uC785 \uC815\uC758
3750
+ ${properties.map(
3751
+ (property) => `
3752
+ \`\`\`
3753
+ ${property.key}.constant.ts
3754
+
3755
+
3756
+ ${property.source}
3757
+ \`\`\`
3758
+ `
3759
+ ).join("\n\n")}
3760
+
3761
+
3762
+ 7. \uC608\uC2DC \uD30C\uC77C\uB4E4
3763
+ ${exampleFiles.map(
3764
+ (example) => `
3765
+ Example filename: ${example.filepath}
3766
+ \`\`\`
3767
+ ${example.content}
3768
+ \`\`\`
3769
+ `
3770
+ ).join("\n\n")}
3771
+
3772
+
3773
+
3774
+ Application name: ${sysName}
3775
+ Model name: ${modelName}
3776
+ Target filename: ${ModelName}.View.tsx
3777
+
3778
+
3779
+ \uB108\uB294 Akan.js\uB77C\uB294 \uC0AC\uB0B4 \uD504\uB808\uC784\uC6CC\uD06C\uB85C Typescript \uAE30\uBC18 \uD504\uB85C\uADF8\uB7A8\uC744 \uC791\uC131\uD558\uB294 \uC2DC\uB2C8\uC5B4 \uAC1C\uBC1C\uC790\uC57C.
3780
+ \uADF8 \uC911\uC5D0\uC11C\uB3C4 \uD504\uB860\uD2B8\uC5D4\uB4DC \uAC1C\uBC1C\uC790.
3781
+ \uB9CC\uC57D\uC5D0 \uC544\uC774\uCF58 \uC0AC\uC6A9\uC774 \uD544\uC694\uD558\uBA74 react-icons \uB77C\uC774\uBE0C\uB7EC\uB9AC\uC5D0\uC11C \uC801\uD569\uD55C \uC544\uC774\uCF58\uC744 \uCC3E\uC544\uC11C \uC0AC\uC6A9\uD574\uC918.
3782
+ \uB610, \uC0C9\uC0C1\uC744 \uC0AC\uC6A9\uD558\uB824\uACE0 \uD558\uBA74 \uD558\uB4DC\uCF54\uB529\uB41C \uC0C9\uC0C1(bg-red)\uC774 \uC544\uB2CC \uD14C\uB9C8 \uC0C9\uC0C1(bg-primary)\uC744 \uC0AC\uC6A9\uD574\uC11C \uC791\uC131\uD574\uC918.
3783
+ \uADF8\uB9AC\uACE0 optional\uD55C \uD544\uB4DC\uB294 field && <div>... \uAC00 \uC544\uB2CC, field ? <div>... : null \uD615\uD0DC\uB85C \uC791\uC131\uD574\uC918.
3784
+ css\uB77C\uC774\uBE0C\uB7EC\uB9AC\uB294 DaisyUI\uB97C \uAE30\uBC18\uC73C\uB85C \uC791\uC131\uD574\uC8FC\uB294\uB370, btn, input, badge\uC640 \uAC19\uC740 \uB2E8\uC21C\uD55C \uAE30\uBCF8 css\uB294 \uC0AC\uC6A9\uD574\uB3C4 \uAD1C\uCC2E\uC544. \uADF8\uB7F0\uB370 card, hero\uAC19\uC774 \uBCF5\uC7A1\uD55C \uCEF4\uD3EC\uB10C\uD2B8\uB294 \uC0AC\uC6A9\uD558\uBA74 \uC548\uB3FC.
3785
+ \uBAA8\uB378\uC5D0 \uB300\uD574\uC11C object destructuring\uC740 \uD558\uC9C0\uB9D0\uACE0 ${modelName}.field \uD615\uD0DC\uB85C \uC811\uADFC\uD558\uACE0, \uD0C0\uC785\uC5D0 \uC5D0\uB7EC\uB294 \uC808\uB300\uB85C \uBC1C\uC0DD\uD558\uC9C0 \uC54A\uB3C4\uB85D ${modelName}.constant.ts\uC5D0 \uC791\uC131\uB418\uC788\uB294 \uC2A4\uD0A4\uB9C8\uB97C \uBCF4\uACE0 \uC791\uC131\uD574.
3786
+ \uC870\uAC74\uBD80 className\uC774 \uD544\uC694\uD55C \uACBD\uC6B0\uC5D0\uB294 clsx \uB77C\uC774\uBE0C\uB7EC\uB9AC\uB97C \uC0AC\uC6A9\uD574\uC57C\uB3FC.
3787
+ \uBAA8\uB4E0 \uBAA8\uB378 \uD544\uB4DC\uC5D0 \uC811\uADFC\uD558\uAE30 \uC804\uC5D0, \uAC01 \uC2A4\uD0A4\uB9C8\uC758 \uC2E4\uC81C \uD544\uB4DC \uB9AC\uC2A4\uD2B8\uB97C \uC791\uC131\uD558\uACE0 \uAC80\uD1A0\uD574. \uD2B9\uD788 \uC911\uCCA9\uB41C \uAC1D\uCCB4( ex) XXX.XXX.XXX )\uC5D0 \uC811\uADFC\uD560 \uB54C\uB294 \uB354\uC6B1 \uC8FC\uC758\uD574.
3788
+ \uB610\uD55C ${modelName}\uACFC \uC885\uC18D\uC131\uC774 \uC788\uB294 \uB2E4\uB978 \uBAA8\uB378\uB4E4\uC758 \uD0C0\uC785\uB4E4\uB3C4 \uBAA8\uB450 \uC704\uBC30\uD558\uC9C0\uB9D0\uACE0 \uC798 \uD30C\uC545\uD558\uACE0 \uC791\uC131\uD574.
3789
+ \uC704\uC5D0\uC11C \uC124\uBA85\uD55C \uBAA8\uB4E0 \uB8F0\uACFC \uC124\uBA85, \uD0C0\uC785\uC744 \uC808\uB300\uB85C \uC704\uBC30\uD558\uC9C0\uB9D0\uACE0 \uC798 \uD30C\uC545\uD558\uACE0 \uC791\uC131\uD574.(\uAC01 \uB370\uC774\uD130\uC758 \uD0C0\uC785, \uCEF4\uD3EC\uB10C\uD2B8\uC758 props\uB4F1...)
3790
+ \uC124\uBA85\uD55C \uB0B4\uC6A9 \uC774\uC678\uC5D0 \uB0B4\uC6A9\uC73C\uB85C \uB2C8\uAC00 \uCD94\uC0C1\uD574\uC11C \uC4F0\uC9C0\uB9D0\uACE0 \uC704\uC5D0 \uBA85\uC2DC\uB418\uC788\uB294 \uB8F0 \uC548\uC5D0\uC11C\uB9CC \uC791\uC131\uD574. \uC788\uC9C0\uB3C4 \uC54A\uC740 \uAC83\uB4E4 \uB9CC\uB4E4\uC5B4\uC11C \uCD94\uC0C1\uD654 \uC2DC\uCF1C\uC11C \uC790\uAFB8 \uC4F0\uB294 \uC77C\uC740 \uC808\uB300\uB85C \uD558\uC9C0\uB9C8.
3791
+ \uD2B9\uD788\uB098 \uBC29\uAE08 \uB9D0\uD55C \uC774 \uC704 \uB450 \uBB38\uC7A5\uC740 \uC808\uB300\uC801\uC73C\uB85C \uC9C0\uCF1C\uC57C \uD560 \uB8F0\uC774\uC57C \uC791\uC131\uD560 \uB54C \uD56D\uC0C1 \uC9C0\uD0A4\uACE0 \uB530\uB77C.
3792
+ ${ModelName}.View.tsx \uCF54\uB4DC\uB97C \uC791\uC131\uD574\uC918. \uC77C\uBC18\uC801\uC73C\uB85C \uC0AC\uC6A9\uD560 \uC218 \uC788\uB294 \uB514\uC790\uC778\uC758 \uCEF4\uD3EC\uB10C\uD2B8\uB97C 4\uAC1C \uC815\uB3C4 \uB9CC\uB4E4\uC5B4\uC918. (ex card, table...)
3793
+ \uC608\uC2DC \uB4E4\uC5B4\uC92C\uB2E4\uACE0 \uC608\uC2DC\uB9CC \uB9CC\uB4E4\uC9C0 \uB9D0\uACE0 \uB2C8 \uC0DD\uAC01\uC5D0 \uC77C\uBC18\uC801\uC73C\uB85C \uC0AC\uC6A9\uD55C\uB2E4 \uD558\uB294 \uCEF4\uD3EC\uB10C\uD2B8\uB85C \uC0DD\uAC01\uD574\uC11C \uB9CC\uB4E4\uC5B4.
3794
+
3795
+ Target filename: ${ModelName}.View.tsx
3796
+ \`\`\`
3797
+
3798
+ \`\`\`
3799
+
3800
+
3126
3801
  `;
3127
3802
 
3128
3803
  // pkgs/@akanjs/cli/src/application/application.prompt.ts
@@ -3174,6 +3849,10 @@ var ApplicationRunner = class {
3174
3849
  workspace.setTsPaths("app", appName);
3175
3850
  return AppExecutor.from(workspace, appName);
3176
3851
  }
3852
+ async removeApplication(app) {
3853
+ await app.workspace.exec(`rm -rf apps/${app.name}`);
3854
+ app.log(`Application ${app.name} removed`);
3855
+ }
3177
3856
  async scanSync(app) {
3178
3857
  const akanConfig = await getAppConfig(app.cwdPath, {
3179
3858
  ...app.workspace.getBaseDevEnv(),
@@ -3281,11 +3960,11 @@ var ApplicationRunner = class {
3281
3960
  ]);
3282
3961
  app.dist.writeFile("frontend/Dockerfile", akanConfig.frontend.dockerfile);
3283
3962
  }
3284
- async serveFrontend(app, { open: open2 = false } = {}) {
3963
+ async serveFrontend(app, { open: open2 = false, turbo = true } = {}) {
3285
3964
  const { env } = await this.#prepareCommand(app, "serve", "frontend");
3286
3965
  if (open2)
3287
3966
  setTimeout(() => (0, import_open.default)("http://localhost:4200"), 3e3);
3288
- await app.spawn("npx", ["next", "dev", "-p", "4200"], { env });
3967
+ await app.spawn("npx", ["next", "dev", "-p", "4200", ...turbo ? ["--turbo"] : []], { env });
3289
3968
  }
3290
3969
  async #getViteConfig(app) {
3291
3970
  const { env } = await this.#prepareCommand(app, "build", "csr");
@@ -3366,7 +4045,7 @@ var ApplicationRunner = class {
3366
4045
  setTimeout(() => (0, import_open.default)("http://localhost:4201"), 3e3);
3367
4046
  }
3368
4047
  async #prepareIos(app) {
3369
- const isAdded = import_fs12.default.existsSync(`${app.cwdPath}/ios/App/Podfile`);
4048
+ const isAdded = import_fs10.default.existsSync(`${app.cwdPath}/ios/App/Podfile`);
3370
4049
  if (!isAdded) {
3371
4050
  await app.spawn("npx", ["cap", "add", "ios"]);
3372
4051
  await app.spawn("npx", ["@capacitor/assets", "generate"]);
@@ -3401,7 +4080,7 @@ var ApplicationRunner = class {
3401
4080
  await capacitorApp.releaseIos();
3402
4081
  }
3403
4082
  async #prepareAndroid(app) {
3404
- const isAdded = import_fs12.default.existsSync(`${app.cwdPath}/android/app/build.gradle`);
4083
+ const isAdded = import_fs10.default.existsSync(`${app.cwdPath}/android/app/build.gradle`);
3405
4084
  if (!isAdded) {
3406
4085
  await app.spawn("npx", ["cap", "add", "android"]);
3407
4086
  await app.spawn("npx", ["@capacitor/assets", "generate"]);
@@ -3483,14 +4162,14 @@ var ApplicationRunner = class {
3483
4162
  const buildRoot = `${app.workspace.workspaceRoot}/releases/builds/${app.name}`;
3484
4163
  const appVersionInfo = import_js_yaml2.default.load(app.readFile("config.yaml"));
3485
4164
  const platformVersion = appVersionInfo.platforms.android.versionName;
3486
- if (import_fs12.default.existsSync(buildRoot))
4165
+ if (import_fs10.default.existsSync(buildRoot))
3487
4166
  await import_promises2.default.rm(buildRoot, { recursive: true, force: true });
3488
4167
  await import_promises2.default.mkdir(buildRoot, { recursive: true });
3489
- if (rebuild || !import_fs12.default.existsSync(`${app.dist.cwdPath}/backend`))
4168
+ if (rebuild || !import_fs10.default.existsSync(`${app.dist.cwdPath}/backend`))
3490
4169
  await this.buildBackend(app);
3491
- if (rebuild || !import_fs12.default.existsSync(`${app.dist.cwdPath}/frontend`))
4170
+ if (rebuild || !import_fs10.default.existsSync(`${app.dist.cwdPath}/frontend`))
3492
4171
  await this.buildFrontend(app);
3493
- if (rebuild || !import_fs12.default.existsSync(`${app.dist.cwdPath}/csr`))
4172
+ if (rebuild || !import_fs10.default.existsSync(`${app.dist.cwdPath}/csr`))
3494
4173
  await this.buildCsr(app);
3495
4174
  const buildVersion = `${platformVersion}-${buildNum}`;
3496
4175
  const buildPath = `${buildRoot}/${buildVersion}`;
@@ -3505,7 +4184,7 @@ var ApplicationRunner = class {
3505
4184
  buildRoot,
3506
4185
  "./"
3507
4186
  ]);
3508
- if (import_fs12.default.existsSync(`${app.dist.cwdPath}/csr`)) {
4187
+ if (import_fs10.default.existsSync(`${app.dist.cwdPath}/csr`)) {
3509
4188
  await import_promises2.default.cp(`${app.dist.cwdPath}/csr`, "./csr", { recursive: true });
3510
4189
  await app.workspace.spawn("zip", [
3511
4190
  "-r",
@@ -3515,7 +4194,7 @@ var ApplicationRunner = class {
3515
4194
  await import_promises2.default.rm("./csr", { recursive: true, force: true });
3516
4195
  }
3517
4196
  const sourceRoot = `${app.workspace.workspaceRoot}/releases/sources/${app.name}`;
3518
- if (import_fs12.default.existsSync(sourceRoot)) {
4197
+ if (import_fs10.default.existsSync(sourceRoot)) {
3519
4198
  const MAX_RETRY = 3;
3520
4199
  for (let i = 0; i < MAX_RETRY; i++) {
3521
4200
  try {
@@ -3535,7 +4214,7 @@ var ApplicationRunner = class {
3535
4214
  await Promise.all(
3536
4215
  [".next", "ios", "android", "public/libs"].map(async (path7) => {
3537
4216
  const targetPath = `${sourceRoot}/apps/${app.name}/${path7}`;
3538
- if (import_fs12.default.existsSync(targetPath))
4217
+ if (import_fs10.default.existsSync(targetPath))
3539
4218
  await import_promises2.default.rm(targetPath, { recursive: true, force: true });
3540
4219
  })
3541
4220
  );
@@ -3563,8 +4242,8 @@ var ApplicationRunner = class {
3563
4242
  []
3564
4243
  )
3565
4244
  ]);
3566
- import_fs12.default.writeFileSync(`${sourceRoot}/tsconfig.json`, JSON.stringify(tsconfig, null, 2));
3567
- import_fs12.default.writeFileSync(
4245
+ import_fs10.default.writeFileSync(`${sourceRoot}/tsconfig.json`, JSON.stringify(tsconfig, null, 2));
4246
+ import_fs10.default.writeFileSync(
3568
4247
  `${sourceRoot}/README.md`,
3569
4248
  `# ${app.name}
3570
4249
  \uBCF8 \uD504\uB85C\uC81D\uD2B8\uC758 \uC18C\uC2A4\uCF54\uB4DC \uBC0F \uAD00\uB828\uC790\uB8CC\uB294 \uBAA8\uB450 \uBE44\uBC00\uC815\uBCF4\uB85C \uAD00\uB9AC\uB429\uB2C8\uB2E4.
@@ -3670,6 +4349,9 @@ var ApplicationScript = class {
3670
4349
  if (serve)
3671
4350
  await this.serve(app, { open: true });
3672
4351
  }
4352
+ async removeApplication(app) {
4353
+ await this.#runner.removeApplication(app);
4354
+ }
3673
4355
  async scanApplication(app, verbose = false) {
3674
4356
  const scanResult = await this.#runner.scanSync(app);
3675
4357
  if (verbose)
@@ -3685,7 +4367,7 @@ var ApplicationScript = class {
3685
4367
  }
3686
4368
  async build(app) {
3687
4369
  await this.syncApplication(app);
3688
- await Promise.all([this.buildBackend(app), this.buildFrontend(app)]);
4370
+ await Promise.all([this.buildBackend(app, { sync: false }), this.buildFrontend(app, { sync: false })]);
3689
4371
  }
3690
4372
  async serve(app, { open: open2 = false } = {}) {
3691
4373
  await this.syncApplication(app);
@@ -3706,10 +4388,10 @@ var ApplicationScript = class {
3706
4388
  await this.syncApplication(app);
3707
4389
  await this.#runner.buildFrontend(app);
3708
4390
  }
3709
- async serveFrontend(app, { open: open2 = false, sync = true } = {}) {
4391
+ async serveFrontend(app, { open: open2 = false, turbo = false, sync = true } = {}) {
3710
4392
  if (sync)
3711
4393
  await this.syncApplication(app);
3712
- await this.#runner.serveFrontend(app, { open: open2 });
4394
+ await this.#runner.serveFrontend(app, { open: open2, turbo });
3713
4395
  }
3714
4396
  async buildCsr(app, { sync = true } = {}) {
3715
4397
  if (sync)
@@ -3800,7 +4482,8 @@ var ApplicationCommand = class {
3800
4482
  async createApplication(name, serve, workspace) {
3801
4483
  await this.applicationScript.createApplication(name, workspace, { serve });
3802
4484
  }
3803
- async removeApplication(app, workspace) {
4485
+ async removeApplication(app) {
4486
+ await this.applicationScript.removeApplication(app);
3804
4487
  }
3805
4488
  async scanApplication(app) {
3806
4489
  await this.applicationScript.scanApplication(app, true);
@@ -3829,8 +4512,8 @@ var ApplicationCommand = class {
3829
4512
  async serveBackend(app, open2) {
3830
4513
  await this.applicationScript.serveBackend(app, { open: open2 });
3831
4514
  }
3832
- async serveFrontend(app, open2) {
3833
- await this.applicationScript.serveFrontend(app, { open: open2 });
4515
+ async serveFrontend(app, open2, turbo) {
4516
+ await this.applicationScript.serveFrontend(app, { open: open2, turbo });
3834
4517
  }
3835
4518
  async serveCsr(app, open2) {
3836
4519
  await this.applicationScript.serveCsr(app, { open: open2 });
@@ -3880,8 +4563,7 @@ __decorateClass([
3880
4563
  ], ApplicationCommand.prototype, "createApplication", 1);
3881
4564
  __decorateClass([
3882
4565
  Target.Public(),
3883
- __decorateParam(0, App()),
3884
- __decorateParam(1, Workspace())
4566
+ __decorateParam(0, App())
3885
4567
  ], ApplicationCommand.prototype, "removeApplication", 1);
3886
4568
  __decorateClass([
3887
4569
  Target.Public(),
@@ -3924,7 +4606,8 @@ __decorateClass([
3924
4606
  __decorateClass([
3925
4607
  Target.Public({ short: true }),
3926
4608
  __decorateParam(0, App()),
3927
- __decorateParam(1, Option("open", { type: "boolean", desc: "open web browser", default: false }))
4609
+ __decorateParam(1, Option("open", { type: "boolean", desc: "open web browser", default: false })),
4610
+ __decorateParam(2, Option("turbo", { type: "boolean", desc: "turbo", default: false }))
3928
4611
  ], ApplicationCommand.prototype, "serveFrontend", 1);
3929
4612
  __decorateClass([
3930
4613
  Target.Public({ short: true }),
@@ -4012,7 +4695,7 @@ ApplicationCommand = __decorateClass([
4012
4695
  // pkgs/@akanjs/cli/src/package/package.runner.ts
4013
4696
  var esbuild2 = __toESM(require("esbuild"));
4014
4697
  var import_esbuild_plugin_d = require("esbuild-plugin-d.ts");
4015
- var import_fs13 = __toESM(require("fs"));
4698
+ var import_fs11 = __toESM(require("fs"));
4016
4699
  var import_promises3 = __toESM(require("fs/promises"));
4017
4700
  var PackageRunner = class {
4018
4701
  async version(workspace) {
@@ -4027,6 +4710,10 @@ var PackageRunner = class {
4027
4710
  dict: { pkgName, PkgName: capitalize(pkgName) }
4028
4711
  });
4029
4712
  }
4713
+ async removePackage(pkg) {
4714
+ await pkg.workspace.exec(`rm -rf pkgs/${pkg.name}`);
4715
+ pkg.log(`Package ${pkg.name} removed`);
4716
+ }
4030
4717
  async scanSync(pkg) {
4031
4718
  const scanResult = await pkg.scan();
4032
4719
  return scanResult;
@@ -4034,7 +4721,7 @@ var PackageRunner = class {
4034
4721
  async buildPackage(pkg) {
4035
4722
  const rootPackageJson = pkg.workspace.readJson("package.json");
4036
4723
  const pkgJson = pkg.readJson("package.json");
4037
- if (import_fs13.default.existsSync(pkg.dist.cwdPath))
4724
+ if (import_fs11.default.existsSync(pkg.dist.cwdPath))
4038
4725
  await pkg.workspace.exec(`rm -rf ${pkg.dist.cwdPath}`);
4039
4726
  let buildResult;
4040
4727
  if (pkg.name === "@akanjs/config") {
@@ -4152,6 +4839,9 @@ var PackageScript = class {
4152
4839
  async createPackage(workspace, pkgName) {
4153
4840
  await this.#runner.createPackage(workspace, pkgName);
4154
4841
  }
4842
+ async removePackage(pkg) {
4843
+ await this.#runner.removePackage(pkg);
4844
+ }
4155
4845
  async scanPackage(pkg) {
4156
4846
  const scanResult = await this.#runner.scanSync(pkg);
4157
4847
  pkg.logger.rawLog(JSON.stringify(scanResult, null, 2));
@@ -4163,7 +4853,7 @@ var PackageScript = class {
4163
4853
 
4164
4854
  // pkgs/@akanjs/cli/src/cloud/cloud.runner.ts
4165
4855
  var import_prompts7 = require("@inquirer/prompts");
4166
- var import_chalk = __toESM(require("chalk"));
4856
+ var import_chalk2 = __toESM(require("chalk"));
4167
4857
  var import_latest_version = __toESM(require("latest-version"));
4168
4858
  var import_open2 = __toESM(require("open"));
4169
4859
  var QRcode = __toESM(require("qrcode"));
@@ -4173,17 +4863,17 @@ var CloudRunner = class {
4173
4863
  const config = getHostConfig();
4174
4864
  const self = config.auth ? await getSelf(config.auth.token) : null;
4175
4865
  if (self) {
4176
- Logger.rawLog(import_chalk.default.green(`
4866
+ Logger.rawLog(import_chalk2.default.green(`
4177
4867
  \u2713 Already logged in akan cloud as ${self.nickname}
4178
4868
  `));
4179
4869
  return true;
4180
4870
  }
4181
4871
  const remoteId = (0, import_uuid.v4)();
4182
4872
  const signinUrl = `${akanCloudClientUrl}/signin?remoteId=${remoteId}`;
4183
- Logger.rawLog(import_chalk.default.bold(`
4184
- ${import_chalk.default.green("\u27A4")} Authentication Required`));
4185
- Logger.rawLog(import_chalk.default.dim("Please visit or click the following URL:"));
4186
- Logger.rawLog(import_chalk.default.cyan.underline(signinUrl) + "\n");
4873
+ Logger.rawLog(import_chalk2.default.bold(`
4874
+ ${import_chalk2.default.green("\u27A4")} Authentication Required`));
4875
+ Logger.rawLog(import_chalk2.default.dim("Please visit or click the following URL:"));
4876
+ Logger.rawLog(import_chalk2.default.cyan.underline(signinUrl) + "\n");
4187
4877
  try {
4188
4878
  const qrcode = await new Promise((resolve, reject) => {
4189
4879
  QRcode.toString(signinUrl, { type: "terminal", small: true }, (err, data) => {
@@ -4194,11 +4884,11 @@ ${import_chalk.default.green("\u27A4")} Authentication Required`));
4194
4884
  });
4195
4885
  Logger.rawLog(qrcode);
4196
4886
  await (0, import_open2.default)(signinUrl);
4197
- Logger.rawLog(import_chalk.default.dim("Opening browser..."));
4887
+ Logger.rawLog(import_chalk2.default.dim("Opening browser..."));
4198
4888
  } catch {
4199
- Logger.rawLog(import_chalk.default.yellow("Could not open browser. Please visit the URL manually."));
4889
+ Logger.rawLog(import_chalk2.default.yellow("Could not open browser. Please visit the URL manually."));
4200
4890
  }
4201
- Logger.rawLog(import_chalk.default.dim("Waiting for authentication..."));
4891
+ Logger.rawLog(import_chalk2.default.dim("Waiting for authentication..."));
4202
4892
  const MAX_RETRY = 300;
4203
4893
  for (let i = 0; i < MAX_RETRY; i++) {
4204
4894
  const res = await fetch(`${akanCloudBackendUrl}/user/getRemoteAuthToken/${remoteId}`);
@@ -4206,30 +4896,38 @@ ${import_chalk.default.green("\u27A4")} Authentication Required`));
4206
4896
  const self2 = jwt ? await getSelf(jwt) : null;
4207
4897
  if (jwt && self2) {
4208
4898
  setHostConfig(akanCloudHost, { auth: { token: jwt, self: self2 } });
4209
- Logger.rawLog(import_chalk.default.green(`\r\u2713 Authentication successful!`));
4210
- Logger.rawLog(import_chalk.default.green.bold(`
4899
+ Logger.rawLog(import_chalk2.default.green(`\r\u2713 Authentication successful!`));
4900
+ Logger.rawLog(import_chalk2.default.green.bold(`
4211
4901
  \u2728 Welcome aboard, ${self2.nickname}!`));
4212
- Logger.rawLog(import_chalk.default.dim("You're now ready to use Akan CLI!\n"));
4902
+ Logger.rawLog(import_chalk2.default.dim("You're now ready to use Akan CLI!\n"));
4213
4903
  return true;
4214
4904
  }
4215
4905
  await sleep(2e3);
4216
4906
  }
4217
- throw new Error(import_chalk.default.red("\u2716 Authentication timed out after 10 minutes. Please try again."));
4907
+ throw new Error(import_chalk2.default.red("\u2716 Authentication timed out after 10 minutes. Please try again."));
4218
4908
  }
4219
4909
  logout() {
4220
4910
  const config = getHostConfig();
4221
4911
  if (config.auth) {
4222
4912
  setHostConfig(akanCloudHost, {});
4223
- Logger.rawLog(import_chalk.default.magenta.bold(`
4913
+ Logger.rawLog(import_chalk2.default.magenta.bold(`
4224
4914
  \u{1F44B} Goodbye, ${config.auth.self.nickname}!`));
4225
- Logger.rawLog(import_chalk.default.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n"));
4226
- Logger.rawLog(import_chalk.default.cyan("You have been successfully logged out."));
4227
- Logger.rawLog(import_chalk.default.dim("Thank you for using Akan CLI. Come back soon! \u{1F31F}\n"));
4915
+ Logger.rawLog(import_chalk2.default.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n"));
4916
+ Logger.rawLog(import_chalk2.default.cyan("You have been successfully logged out."));
4917
+ Logger.rawLog(import_chalk2.default.dim("Thank you for using Akan CLI. Come back soon! \u{1F31F}\n"));
4228
4918
  } else {
4229
- Logger.rawLog(import_chalk.default.yellow.bold("\n\u26A0\uFE0F No active session found"));
4230
- Logger.rawLog(import_chalk.default.dim("You were not logged in to begin with\n"));
4919
+ Logger.rawLog(import_chalk2.default.yellow.bold("\n\u26A0\uFE0F No active session found"));
4920
+ Logger.rawLog(import_chalk2.default.dim("You were not logged in to begin with\n"));
4231
4921
  }
4232
4922
  }
4923
+ async setLlm() {
4924
+ await AiSession.init({ useExisting: true });
4925
+ Logger.rawLog(import_chalk2.default.green("LLM model set successfully"));
4926
+ }
4927
+ resetLlm() {
4928
+ AiSession.setLlmConfig(null);
4929
+ Logger.rawLog(import_chalk2.default.green("LLM model reset successfully"));
4930
+ }
4233
4931
  async getAkanPkgs(workspace) {
4234
4932
  const pkgs = await workspace.getPkgs();
4235
4933
  const akanPkgs = pkgs.filter((pkg) => pkg.startsWith("@akanjs/"));
@@ -4251,20 +4949,7 @@ ${import_chalk.default.green("\u27A4")} Authentication Required`));
4251
4949
  const newPackageJsonStr = JSON.stringify({ ...packageJson, version: nextVersion }, null, 2);
4252
4950
  workspace.writeFile(`pkgs/${library}/package.json`, newPackageJsonStr);
4253
4951
  const distPackageJson = workspace.readJson(`dist/pkgs/${library}/package.json`);
4254
- const newDistPackageJson = {
4255
- ...distPackageJson,
4256
- // ...(distPackageJson.dependencies
4257
- // ? {
4258
- // dependencies: Object.fromEntries(
4259
- // Object.entries(distPackageJson.dependencies).map(([key, value]) => [
4260
- // key,
4261
- // value.startsWith("^") ? value : `^${value}`,
4262
- // ])
4263
- // ),
4264
- // }
4265
- // : {}),
4266
- version: nextVersion
4267
- };
4952
+ const newDistPackageJson = { ...distPackageJson, version: nextVersion };
4268
4953
  workspace.writeJson(`dist/pkgs/${library}/package.json`, newDistPackageJson);
4269
4954
  }
4270
4955
  const isDeployConfirmed = await (0, import_prompts7.confirm)({
@@ -4295,6 +4980,17 @@ var CloudScript = class {
4295
4980
  logout() {
4296
4981
  this.#runner.logout();
4297
4982
  }
4983
+ async setLlm() {
4984
+ await this.#runner.setLlm();
4985
+ }
4986
+ resetLlm() {
4987
+ this.#runner.resetLlm();
4988
+ }
4989
+ async ask(question) {
4990
+ await AiSession.init();
4991
+ const session = new AiSession();
4992
+ await session.ask(question);
4993
+ }
4298
4994
  async deployAkan(workspace) {
4299
4995
  const akanPkgs = await this.#runner.getAkanPkgs(workspace);
4300
4996
  await Promise.all(
@@ -4313,6 +5009,15 @@ var CloudCommand = class {
4313
5009
  logout() {
4314
5010
  this.cloudScript.logout();
4315
5011
  }
5012
+ async setLlm() {
5013
+ await this.cloudScript.setLlm();
5014
+ }
5015
+ resetLlm() {
5016
+ this.cloudScript.resetLlm();
5017
+ }
5018
+ async ask(question) {
5019
+ await this.cloudScript.ask(question);
5020
+ }
4316
5021
  async deployAkan(workspace) {
4317
5022
  await this.cloudScript.deployAkan(workspace);
4318
5023
  }
@@ -4323,6 +5028,16 @@ __decorateClass([
4323
5028
  __decorateClass([
4324
5029
  Target.Public()
4325
5030
  ], CloudCommand.prototype, "logout", 1);
5031
+ __decorateClass([
5032
+ Target.Public()
5033
+ ], CloudCommand.prototype, "setLlm", 1);
5034
+ __decorateClass([
5035
+ Target.Public()
5036
+ ], CloudCommand.prototype, "resetLlm", 1);
5037
+ __decorateClass([
5038
+ Target.Public(),
5039
+ __decorateParam(0, Option("question", { ask: "question to ask" }))
5040
+ ], CloudCommand.prototype, "ask", 1);
4326
5041
  __decorateClass([
4327
5042
  Target.Public({ devOnly: true }),
4328
5043
  __decorateParam(0, Workspace())
@@ -4335,8 +5050,10 @@ CloudCommand = __decorateClass([
4335
5050
  var LibraryCommand = class {
4336
5051
  libraryScript = new LibraryScript();
4337
5052
  async createLibrary(name, workspace) {
5053
+ await this.libraryScript.createLibrary(name, workspace);
4338
5054
  }
4339
- async removeLibrary(lib, workspace) {
5055
+ async removeLibrary(lib) {
5056
+ await this.libraryScript.removeLibrary(lib);
4340
5057
  }
4341
5058
  async scanLibrary(lib) {
4342
5059
  await this.libraryScript.scanLibrary(lib, true);
@@ -4360,8 +5077,7 @@ __decorateClass([
4360
5077
  ], LibraryCommand.prototype, "createLibrary", 1);
4361
5078
  __decorateClass([
4362
5079
  Target.Public(),
4363
- __decorateParam(0, Lib()),
4364
- __decorateParam(1, Workspace())
5080
+ __decorateParam(0, Lib())
4365
5081
  ], LibraryCommand.prototype, "removeLibrary", 1);
4366
5082
  __decorateClass([
4367
5083
  Target.Public(),
@@ -4390,8 +5106,11 @@ LibraryCommand = __decorateClass([
4390
5106
  Commands()
4391
5107
  ], LibraryCommand);
4392
5108
 
5109
+ // pkgs/@akanjs/cli/src/module/module.script.ts
5110
+ var import_prompts8 = require("@inquirer/prompts");
5111
+ var import_fs12 = __toESM(require("fs"));
5112
+
4393
5113
  // pkgs/@akanjs/cli/src/module/module.runner.ts
4394
- var import_fs14 = __toESM(require("fs"));
4395
5114
  var ModuleRunner = class {
4396
5115
  async createModule(workspace, sysType, sysName, moduleName, description) {
4397
5116
  }
@@ -4469,56 +5188,64 @@ var ModuleRunner = class {
4469
5188
  }
4470
5189
  };
4471
5190
  }
4472
- async createUnit(sys2, modelName) {
4473
- const modelFileData = getModelFileData(sys2.cwdPath, modelName);
4474
- const { paths } = getRelatedCnsts(modelFileData.constantFilePath);
4475
- const names = { model: modelName, Model: capitalize(modelName), LightModel: `Light${capitalize(modelName)}` };
4476
- const prompt = `
4477
-
4478
- \uB108\uB294 React, Typescript, TailwindCSS\uB97C \uAE30\uBC18\uC73C\uB85C \uCF54\uB529\uD558\uB294 \uD504\uB860\uD2B8\uC5D4\uB4DC \uAC1C\uBC1C\uC790\uC57C.
4479
- ${names.Model}\uC774\uB77C\uB294 \uB3C4\uBA54\uC778\uC5D0 \uB300\uD574\uC11C ${names.LightModel} \uC2A4\uD0A4\uB9C8\uB97C \uB300\uC0C1\uC73C\uB85C react component\uB97C \uB514\uC790\uC778\uD558\uB824\uACE0 \uD574. \uC544\uB798\uB294 \uD604\uC7AC \uBCF4\uC77C\uB7EC\uD50C\uB808\uC774\uD2B8 \uD615\uD0DC\uC758 \uCEF4\uD3EC\uB10C\uD2B8\uC57C.
4480
-
4481
- \`\`\`
4482
- ${modelFileData.unitFileStr}
4483
- \`\`\`
4484
-
4485
- ${names.LightModel}\uC740 \uB2E4\uC74C\uACFC \uAC19\uC774 ${names.Model} \uC2A4\uD0A4\uB9C8\uC5D0\uC11C \uC77C\uBD80 \uD544\uB4DC\uB97C \uCD94\uCD9C\uD574\uC11C lightweight fetch\uB41C \uD615\uD0DC\uB85C \uC124\uACC4\uB418\uC5B4\uC788\uC5B4.
4486
- \`\`\`
4487
- ${modelFileData.constantFileStr}
4488
- \`\`\`
4489
-
4490
- \uC544\uB798\uB294 \uD604\uC7AC \uC2A4\uD0A4\uB9C8\uC640 \uC5F0\uAD00\uB41C \uC2A4\uD0A4\uB9C8 \uD30C\uC77C\uB4E4\uC774\uC57C. \uC2A4\uD0A4\uB9C8 \uD30C\uC77C\uB4E4\uC758 \uCF54\uB4DC\uB4E4\uC744 \uBCF4\uACE0 \uC11C\uB85C \uC5B4\uB5BB\uAC8C \uC5F0\uACC4 \uB418\uC5B4\uC788\uB294\uC9C0 \uC774\uD574\uD558\uB3C4\uB85D \uD574.
4491
- ${paths ? new Array(paths.size).fill(0).map((_, index) => {
4492
- const key = Array.from(paths.keys())[index];
4493
- const filePath = paths.get(key)?.filePath;
4494
- if (!filePath)
4495
- throw new Error("filePath is undefined");
4496
- return `${key}
4497
- \`\`\`${import_fs14.default.readFileSync(filePath, "utf8")}\`\`\`\`
4498
-
4499
- `;
4500
- }) : ""}
4501
-
4502
- \uCD94\uAC00\uB85C, \uB9CC\uC57D\uC5D0 \uC544\uC774\uCF58 \uC0AC\uC6A9\uC774 \uD544\uC694\uD558\uBA74 react-icons/bi \uB77C\uC774\uBE0C\uB7EC\uB9AC\uC5D0\uC11C \uC0AC\uC6A9\uD574\uC918.
4503
- \uB610, \uC0C9\uC0C1\uC744 \uC0AC\uC6A9\uD558\uB824\uACE0 \uD558\uBA74 \uD558\uB4DC\uCF54\uB529\uB41C \uC0C9\uC0C1(bg-red)\uC774 \uC544\uB2CC \uD14C\uB9C8 \uC0C9\uC0C1(bg-primary)\uC744 \uC0AC\uC6A9\uD574\uC11C \uC791\uC131\uD574\uC918.
4504
- \uADF8\uB9AC\uACE0 optional\uD55C \uD544\uB4DC\uB294 field && <div>... \uAC00 \uC544\uB2CC, field ? <div>... : null \uD615\uD0DC\uB85C \uC791\uC131\uD574\uC918.
4505
- css\uB77C\uC774\uBE0C\uB7EC\uB9AC\uB294 DaisyUI\uB97C \uAE30\uBC18\uC73C\uB85C \uC791\uC131\uD574\uC8FC\uB294\uB370, btn, input, badge\uC640 \uAC19\uC740 \uB2E8\uC21C\uD55C \uAE30\uBCF8 css\uB294 \uC0AC\uC6A9\uD574\uB3C4 \uAD1C\uCC2E\uC544. \uADF8\uB7F0\uB370 card, hero\uAC19\uC774 \uBCF5\uC7A1\uD55C \uCEF4\uD3EC\uB10C\uD2B8\uB294 \uC0AC\uC6A9\uD558\uBA74 \uC548\uB3FC.
4506
- \uC870\uAC74\uBD80 className\uC774 \uD544\uC694\uD55C \uACBD\uC6B0\uC5D0\uB294 clsx \uB77C\uC774\uBE0C\uB7EC\uB9AC\uB97C \uC0AC\uC6A9\uD574\uC11C \uC791\uC131\uD574\uC57C\uD574.
4507
- \uBAA8\uB378\uC5D0 \uB300\uD574\uC11C object destructuring\uC740 \uD558\uC9C0\uB9D0\uACE0 ${modelName}.field \uD615\uD0DC\uB85C \uC811\uADFC\uD558\uAC8C \uCF54\uB4DC\uB97C \uC791\uC131\uD574\uC57C\uD574.
4508
-
4509
- ${names.Model}.Unit.Card\uC758 \uB9AC\uC561\uD2B8 \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uB514\uC790\uC778\uD574\uC11C \uC791\uC131\uD574\uC918.
4510
- `;
4511
- try {
4512
- import_fs14.default.writeFileSync("./local/prompt.txt", prompt);
4513
- const { content } = await streamAi(prompt, (chunk) => {
4514
- process.stdout.write(chunk);
4515
- });
4516
- import_fs14.default.writeFileSync("./local/result.txt", content);
4517
- } catch (error) {
4518
- }
4519
- }
4520
- async createView(sys2, modelName) {
4521
- }
5191
+ // async createUnit(sys: App | Lib, modelName: string) {
5192
+ // const modelFileData = getModelFileData(sys.cwdPath, modelName);
5193
+ // const { paths } = getRelatedCnsts(modelFileData.constantFilePath);
5194
+ // const names = { model: modelName, Model: capitalize(modelName), LightModel: `Light${capitalize(modelName)}` };
5195
+ // const prompt = `
5196
+ // 너는 React, Typescript, TailwindCSS를 기반으로 코딩하는 프론트엔드 개발자야.
5197
+ // ${names.Model}이라는 도메인에 대해서 ${names.LightModel} 스키마를 대상으로 react component를 디자인하려고 해. 아래는 현재 보일러플레이트 형태의 컴포넌트야.
5198
+ // \`\`\`
5199
+ // ${modelFileData.unitFileStr}
5200
+ // \`\`\`
5201
+ // ${names.LightModel}은 다음과 같이 ${names.Model} 스키마에서 일부 필드를 추출해서 lightweight fetch된 형태로 설계되어있어.
5202
+ // \`\`\`
5203
+ // ${modelFileData.constantFileStr}
5204
+ // \`\`\`
5205
+ // 아래는 현재 스키마와 연관된 스키마 파일들이야. 스키마 파일들의 코드들을 보고 서로 어떻게 연계 되어있는지 이해하도록 해.
5206
+ // ${
5207
+ // paths
5208
+ // ? new Array(paths.size).fill(0).map((_, index) => {
5209
+ // //순서대로 paths key 추출
5210
+ // const key = Array.from(paths.keys())[index];
5211
+ // const filePath = paths.get(key)?.filePath;
5212
+ // if (!filePath) throw new Error("filePath is undefined");
5213
+ // return `${key}\n\`\`\`${fs.readFileSync(filePath, "utf8")}\`\`\`\`\n\n`;
5214
+ // })
5215
+ // : ""
5216
+ // }
5217
+ // 추가로, 만약에 아이콘 사용이 필요하면 react-icons/bi 라이브러리에서 사용해줘.
5218
+ // 또, 색상을 사용하려고 하면 하드코딩된 색상(bg-red)이 아닌 테마 색상(bg-primary)을 사용해서 작성해줘.
5219
+ // 그리고 optional한 필드는 field && <div>... 가 아닌, field ? <div>... : null 형태로 작성해줘.
5220
+ // css라이브러리는 DaisyUI를 기반으로 작성해주는데, btn, input, badge와 같은 단순한 기본 css는 사용해도 괜찮아. 그런데 card, hero같이 복잡한 컴포넌트는 사용하면 안돼.
5221
+ // 조건부 className이 필요한 경우에는 clsx 라이브러리를 사용해서 작성해야해.
5222
+ // 모델에 대해서 object destructuring은 하지말고 ${modelName}.field 형태로 접근하게 코드를 작성해야해.
5223
+ // ${names.Model}.Unit.Card의 리액트 컴포넌트를 디자인해서 작성해줘.
5224
+ // `;
5225
+ // try {
5226
+ // fs.writeFileSync("./local/prompt.txt", prompt);
5227
+ // const { content } = await streamAi(prompt, (chunk) => {
5228
+ // process.stdout.write(chunk);
5229
+ // });
5230
+ // fs.writeFileSync("./local/result.txt", content);
5231
+ // } catch (error) {
5232
+ // // console.error("Application error:", error);
5233
+ // }
5234
+ // }
5235
+ // async createView(sys: App | Lib, modelName: string) {
5236
+ // const modelFileData = getModelFileData(sys.cwdPath, modelName);
5237
+ // // const modelFileData = getModelFileData(sys.cwdPath, modelName);
5238
+ // // const { paths } = getRelatedCnsts(modelFileData.constantFilePath);
5239
+ // // const names = { model: modelName, Model: capitalize(modelName), LightModel: `Light${capitalize(modelName)}` };
5240
+ // // const prompt = prompt.requestView({
5241
+ // // sysName: sys.name,
5242
+ // // modelName,
5243
+ // // modelDesc: modelFileData.modelDesc,
5244
+ // // modelSchemaDesign: modelFileData.modelSchemaDesign,
5245
+ // // boilerplate: modelFileData.viewFileStr,
5246
+ // // paths,
5247
+ // // });
5248
+ // }
4522
5249
  };
4523
5250
 
4524
5251
  // pkgs/@akanjs/cli/src/module/module.script.ts
@@ -4563,38 +5290,67 @@ var ModuleScript = class {
4563
5290
  }
4564
5291
  async createTest(workspace, name) {
4565
5292
  }
4566
- async createUnit(workspace, type, appOrLibName, modelName) {
4567
- const sys2 = type === "app" ? AppExecutor.from(workspace, appOrLibName) : LibExecutor.from(workspace, appOrLibName);
4568
- await this.#runner.createUnit(sys2, modelName);
5293
+ async createUnit(sys2) {
5294
+ const libs = await sys2.getModules();
5295
+ const unitExampleFiles = await sys2.getUnitsSourceCode();
5296
+ const lib = await (0, import_prompts8.select)({
5297
+ message: "Select the lib",
5298
+ choices: libs
5299
+ }).catch((e) => {
5300
+ Logger.error("canceled");
5301
+ return null;
5302
+ });
5303
+ if (!lib)
5304
+ return;
5305
+ const name = lib.split("/").pop();
5306
+ if (!name)
5307
+ return;
5308
+ const Name = capitalize(name);
5309
+ const relatedCnsts = getRelatedCnsts(`${sys2.cwdPath}/lib/${name}/${name}.constant.ts`);
5310
+ const constant = import_fs12.default.readFileSync(`${sys2.cwdPath}/lib/${name}/${name}.constant.ts`, "utf-8");
5311
+ const session = new AiSession();
5312
+ const promptRst = requestView({
5313
+ sysName: sys2.name,
5314
+ modelName: name,
5315
+ ModelName: Name,
5316
+ constant,
5317
+ properties: relatedCnsts.map((r) => ({ key: r.key, source: r.source })),
5318
+ exampleFiles: randomPicks(unitExampleFiles, Math.min(10, unitExampleFiles.length))
5319
+ });
5320
+ const content = await session.editTypescript(promptRst);
5321
+ import_fs12.default.writeFileSync(`${sys2.cwdPath}/prompt.txt`, promptRst);
5322
+ import_fs12.default.writeFileSync(`${sys2.cwdPath}/result.txt`, content);
4569
5323
  }
4570
5324
  async createView(sys2) {
4571
- const [appNames, libNames] = await sys2.workspace.getSyss();
4572
- const viewExampleFiles = [
4573
- ...(await Promise.all(
4574
- appNames.map(async (appName) => {
4575
- const app = AppExecutor.from(sys2.workspace, appName);
4576
- const viewModules = await app.getViewModules();
4577
- return await Promise.all(
4578
- viewModules.map((viewModule) => ({
4579
- path: `${appName}/${viewModule}/${viewModule}.View.tsx`,
4580
- content: app.readFile(`lib/${viewModule}/${viewModule}.View.tsx`)
4581
- }))
4582
- );
4583
- })
4584
- )).flat(),
4585
- ...(await Promise.all(
4586
- libNames.map(async (libName) => {
4587
- const lib = LibExecutor.from(sys2.workspace, libName);
4588
- const viewModules = await lib.getViewModules();
4589
- return await Promise.all(
4590
- viewModules.map((viewModule) => ({
4591
- path: `${libName}/${viewModule}/${viewModule}.View.tsx`,
4592
- content: lib.readFile(`lib/${viewModule}/${viewModule}.View.tsx`)
4593
- }))
4594
- );
4595
- })
4596
- )).flat()
4597
- ];
5325
+ const libs = await sys2.getModules();
5326
+ const lib = await (0, import_prompts8.select)({
5327
+ message: "Select the lib",
5328
+ choices: libs
5329
+ }).catch((e) => {
5330
+ Logger.error("canceled");
5331
+ return null;
5332
+ });
5333
+ if (!lib)
5334
+ return;
5335
+ const name = lib.split("/").pop();
5336
+ if (!name)
5337
+ return;
5338
+ const viewExampleFiles = (await sys2.getViewsSourceCode()).filter((f) => f.filepath.includes(`${name}.View.tsx`));
5339
+ const Name = capitalize(name);
5340
+ const relatedCnsts = getRelatedCnsts(`${sys2.cwdPath}/lib/${name}/${name}.constant.ts`);
5341
+ const constant = import_fs12.default.readFileSync(`${sys2.cwdPath}/lib/${name}/${name}.constant.ts`, "utf-8");
5342
+ const session = new AiSession();
5343
+ const promptRst = requestView({
5344
+ sysName: sys2.name,
5345
+ modelName: name,
5346
+ ModelName: Name,
5347
+ constant,
5348
+ properties: relatedCnsts.map((r) => ({ key: r.key, source: r.source })),
5349
+ exampleFiles: randomPicks(viewExampleFiles, Math.min(20, viewExampleFiles.length))
5350
+ });
5351
+ const content = await session.editTypescript(promptRst);
5352
+ import_fs12.default.writeFileSync(`${sys2.cwdPath}/prompt.txt`, promptRst);
5353
+ import_fs12.default.writeFileSync(`${sys2.cwdPath}/result.txt`, content);
4598
5354
  }
4599
5355
  };
4600
5356
 
@@ -4677,7 +5433,8 @@ var PackageCommand = class {
4677
5433
  async createPackage(name, workspace) {
4678
5434
  await this.packageScript.createPackage(workspace, name);
4679
5435
  }
4680
- async removePackage(name, workspace) {
5436
+ async removePackage(pkg) {
5437
+ await this.packageScript.removePackage(pkg);
4681
5438
  }
4682
5439
  async scanPackage(pkg) {
4683
5440
  await this.packageScript.scanPackage(pkg);
@@ -4697,8 +5454,7 @@ __decorateClass([
4697
5454
  ], PackageCommand.prototype, "createPackage", 1);
4698
5455
  __decorateClass([
4699
5456
  Target.Public(),
4700
- __decorateParam(0, Option("name", { desc: "name of package" })),
4701
- __decorateParam(1, Workspace())
5457
+ __decorateParam(0, Pkg())
4702
5458
  ], PackageCommand.prototype, "removePackage", 1);
4703
5459
  __decorateClass([
4704
5460
  Target.Public(),
@@ -4712,13 +5468,13 @@ PackageCommand = __decorateClass([
4712
5468
  Commands()
4713
5469
  ], PackageCommand);
4714
5470
 
4715
- // pkgs/@akanjs/cli/src/package/page/page.runner.ts
5471
+ // pkgs/@akanjs/cli/src/page/page.runner.ts
4716
5472
  var PageRunner = class {
4717
5473
  async createPage(app, name) {
4718
5474
  }
4719
5475
  };
4720
5476
 
4721
- // pkgs/@akanjs/cli/src/package/page/page.script.ts
5477
+ // pkgs/@akanjs/cli/src/page/page.script.ts
4722
5478
  var PageScript = class {
4723
5479
  #runner = new PageRunner();
4724
5480
  async createPage(app, name) {
@@ -4726,7 +5482,7 @@ var PageScript = class {
4726
5482
  }
4727
5483
  };
4728
5484
 
4729
- // pkgs/@akanjs/cli/src/package/page/page.command.ts
5485
+ // pkgs/@akanjs/cli/src/page/page.command.ts
4730
5486
  var PageCommand = class {
4731
5487
  pageScript = new PageScript();
4732
5488
  async createPage(app, name) {
@@ -4868,8 +5624,8 @@ var WorkspaceCommand = class {
4868
5624
  };
4869
5625
  __decorateClass([
4870
5626
  Target.Public(),
4871
- __decorateParam(0, Option("name", { desc: "name of workspace" })),
4872
- __decorateParam(1, Option("app", { desc: "application name" })),
5627
+ __decorateParam(0, Option("name", { desc: "what is the name of your organization?" })),
5628
+ __decorateParam(1, Option("app", { desc: "describe your first application to create." })),
4873
5629
  __decorateParam(2, Option("dir", { desc: "directory of workspace", default: process.env.USE_AKANJS_PKGS === "true" ? "local" : "." }))
4874
5630
  ], WorkspaceCommand.prototype, "createWorkspace", 1);
4875
5631
  __decorateClass([
@@ -4891,7 +5647,6 @@ void runCommands(
4891
5647
  PageCommand,
4892
5648
  CloudCommand
4893
5649
  );
4894
- //!Field.Prop 거르기가 빡세네.
4895
5650
  //! Temp
4896
5651
  //! zip 명령어는 압축시 폴더 경로를 무시하는 게 안됨
4897
5652
  //! 두 가지 방법이 있음
@@ -4900,3 +5655,4 @@ void runCommands(
4900
5655
  //! execSync를 가져오기 싫으니 일단 2번 방법으로 해보자
4901
5656
  //! add path in tsconfig.json
4902
5657
  //! Temporary fix for barrel library
5658
+ //! 파일을 {name}.View.tsx에 저장.