@akanjs/cli 0.0.88 → 0.0.90

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 (27) hide show
  1. package/index.js +1248 -486
  2. package/package.json +1 -1
  3. package/pkgs/@akanjs/cli/src/application/application.command.d.ts +6 -6
  4. package/pkgs/@akanjs/cli/src/application/application.runner.d.ts +15 -7
  5. package/pkgs/@akanjs/cli/src/application/application.script.d.ts +46 -16
  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 +3 -2
  17. package/pkgs/@akanjs/cli/src/package/package.script.d.ts +3 -2
  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 +24 -31
  21. package/pkgs/@akanjs/devkit/src/getRelatedCnsts.d.ts +52 -8
  22. package/pkgs/@akanjs/devkit/src/index.d.ts +0 -1
  23. package/src/templates/workspaceRoot/package.json.template +5 -0
  24. package/pkgs/@akanjs/devkit/src/installExternalLib.d.ts +0 -2
  25. /package/pkgs/@akanjs/cli/src/{package/page → page}/page.command.d.ts +0 -0
  26. /package/pkgs/@akanjs/cli/src/{package/page → page}/page.runner.d.ts +0 -0
  27. /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_fs7 = __toESM(require("fs"), 1);
768
- var import_promises = __toESM(require("fs/promises"), 1);
769
- var import_path3 = __toESM(require("path"), 1);
770
- var import_dotenv = __toESM(require("dotenv"), 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,12 +1194,32 @@ 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
- await this.exec(`git init`);
1219
+ await this.exec(`git init --quiet`);
1210
1220
  if (add)
1211
1221
  await this.exec(`git add .`);
1212
- await this.exec(`git commit -m "${message}"`);
1222
+ await this.exec(`git commit --quiet -m "${message}"`);
1213
1223
  }
1214
1224
  async #getDirHasFile(basePath2, targetFilename) {
1215
1225
  const AVOID_DIRS = ["node_modules", "dist", "public", "./next"];
@@ -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();
@@ -1444,8 +1488,10 @@ var SysExecutor = class extends Executor {
1444
1488
  }
1445
1489
  };
1446
1490
  var AppExecutor = class _AppExecutor extends SysExecutor {
1491
+ dist;
1447
1492
  constructor({ workspace, name }) {
1448
1493
  super({ workspace, name, type: "app" });
1494
+ this.dist = new Executor(`${name} Dist App Executor`, `${this.workspace.workspaceRoot}/dist/apps/${name}`);
1449
1495
  }
1450
1496
  static from(executor, name) {
1451
1497
  if (executor instanceof WorkspaceExecutor)
@@ -1462,9 +1508,9 @@ var AppExecutor = class _AppExecutor extends SysExecutor {
1462
1508
  }
1463
1509
  async syncAssets(libDeps) {
1464
1510
  const projectPublicLibPath = `${this.cwdPath}/public/libs`;
1465
- if (import_fs7.default.existsSync(projectPublicLibPath))
1511
+ if (import_fs6.default.existsSync(projectPublicLibPath))
1466
1512
  await import_promises.default.rm(projectPublicLibPath, { recursive: true });
1467
- 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`));
1468
1514
  await Promise.all(targetDeps.map((dep) => import_promises.default.mkdir(`${projectPublicLibPath}/${dep}`, { recursive: true })));
1469
1515
  await Promise.all(
1470
1516
  targetDeps.map(
@@ -1475,23 +1521,13 @@ var AppExecutor = class _AppExecutor extends SysExecutor {
1475
1521
  );
1476
1522
  }
1477
1523
  };
1478
- var DistAppExecutor = class _DistAppExecutor extends Executor {
1479
- name;
1480
- constructor({ workspace, name }) {
1481
- super(`${name} Dist App Executor`, `${workspace.workspaceRoot}/dist/apps/${name}`);
1482
- this.name = name;
1483
- }
1484
- static from(executor, name) {
1485
- if (executor instanceof WorkspaceExecutor)
1486
- return new _DistAppExecutor({ workspace: executor, name });
1487
- return new _DistAppExecutor({ workspace: executor.workspace, name });
1488
- }
1489
- };
1490
1524
  var LibExecutor = class _LibExecutor extends SysExecutor {
1491
1525
  workspaceRoot;
1492
1526
  repoName;
1527
+ dist;
1493
1528
  constructor({ workspace, name }) {
1494
1529
  super({ workspace, name, type: "lib" });
1530
+ this.dist = new Executor(`${name} Dist Lib Executor`, `${this.workspace.workspaceRoot}/dist/libs/${name}`);
1495
1531
  }
1496
1532
  static from(executor, name) {
1497
1533
  if (executor instanceof WorkspaceExecutor)
@@ -1510,10 +1546,12 @@ var LibExecutor = class _LibExecutor extends SysExecutor {
1510
1546
  var PkgExecutor = class _PkgExecutor extends Executor {
1511
1547
  workspace;
1512
1548
  name;
1549
+ dist;
1513
1550
  constructor({ workspace = WorkspaceExecutor.fromRoot(), name }) {
1514
1551
  super(`${name} Pkg Executor`, `${workspace.workspaceRoot}/pkgs/${name}`);
1515
1552
  this.workspace = workspace;
1516
1553
  this.name = name;
1554
+ this.dist = new Executor(`${name} Dist Pkg Executor`, `${this.workspace.workspaceRoot}/dist/pkgs/${name}`);
1517
1555
  }
1518
1556
  static from(executor, name) {
1519
1557
  if (executor instanceof WorkspaceExecutor)
@@ -1543,24 +1581,6 @@ var PkgExecutor = class _PkgExecutor extends Executor {
1543
1581
  return pkgScanResult;
1544
1582
  }
1545
1583
  };
1546
- var DistPkgExecutor = class _DistPkgExecutor extends Executor {
1547
- workspaceRoot;
1548
- repoName;
1549
- name;
1550
- constructor({ workspaceRoot, repoName, name }) {
1551
- super(`${name} Dist Pkg Executor`, `${workspaceRoot}/dist/pkgs/${name}`);
1552
- this.workspaceRoot = workspaceRoot;
1553
- this.repoName = repoName;
1554
- this.name = name;
1555
- }
1556
- static from(workspaceExecutor, name) {
1557
- return new _DistPkgExecutor({
1558
- workspaceRoot: workspaceExecutor.workspaceRoot,
1559
- repoName: workspaceExecutor.repoName,
1560
- name
1561
- });
1562
- }
1563
- };
1564
1584
 
1565
1585
  // pkgs/@akanjs/devkit/src/constants.ts
1566
1586
  var import_os = require("os");
@@ -1570,21 +1590,21 @@ var akanCloudHost = process.env.NEXT_PUBLIC_OPERATION_MODE === "local" ? "http:/
1570
1590
  var akanCloudBackendUrl = `${akanCloudHost}${process.env.NEXT_PUBLIC_OPERATION_MODE === "local" ? ":8080" : ""}/backend`;
1571
1591
  var akanCloudClientUrl = `${akanCloudHost}${process.env.NEXT_PUBLIC_OPERATION_MODE === "local" ? ":4200" : ""}`;
1572
1592
  var defaultHostConfig = {};
1573
- var defaultAkanGlobalConfig = {};
1593
+ var defaultAkanGlobalConfig = { cloudHost: {}, llm: null };
1574
1594
 
1575
1595
  // pkgs/@akanjs/devkit/src/auth.ts
1576
- var import_fs8 = __toESM(require("fs"), 1);
1596
+ var import_fs7 = __toESM(require("fs"));
1577
1597
  var getAkanGlobalConfig = () => {
1578
- 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;
1579
1599
  return akanConfig;
1580
1600
  };
1581
1601
  var setAkanGlobalConfig = (akanConfig) => {
1582
- import_fs8.default.mkdirSync(basePath, { recursive: true });
1583
- 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));
1584
1604
  };
1585
1605
  var getHostConfig = (host = akanCloudHost) => {
1586
1606
  const akanConfig = getAkanGlobalConfig();
1587
- return akanConfig[host] ?? defaultHostConfig;
1607
+ return akanConfig.cloudHost[host] ?? defaultHostConfig;
1588
1608
  };
1589
1609
  var setHostConfig = (host = akanCloudHost, config = {}) => {
1590
1610
  const akanConfig = getAkanGlobalConfig();
@@ -1603,7 +1623,7 @@ var getSelf = async (token) => {
1603
1623
 
1604
1624
  // pkgs/@akanjs/devkit/src/capacitorApp.ts
1605
1625
  var import_project = require("@trapezedev/project");
1606
- var import_fs9 = __toESM(require("fs"), 1);
1626
+ var import_fs8 = __toESM(require("fs"));
1607
1627
  var CapacitorApp = class {
1608
1628
  constructor(app) {
1609
1629
  this.app = app;
@@ -1629,7 +1649,7 @@ var CapacitorApp = class {
1629
1649
  await this.project.commit();
1630
1650
  }
1631
1651
  async releaseIos() {
1632
- 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`);
1633
1653
  if (!isAdded) {
1634
1654
  await this.app.spawn("npx cap add ios");
1635
1655
  await this.app.spawn("npx @capacitor/assets generate");
@@ -1638,7 +1658,7 @@ var CapacitorApp = class {
1638
1658
  await this.app.spawn("cross-env", ["APP_OPERATION_MODE=release", "npx", "cap", "sync", "ios"]);
1639
1659
  }
1640
1660
  async releaseAndroid() {
1641
- 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`);
1642
1662
  if (!isAdded) {
1643
1663
  await this.app.spawn("npx cap add android");
1644
1664
  await this.app.spawn("npx @capacitor/assets generate");
@@ -1879,7 +1899,7 @@ var Target = {
1879
1899
  // pkgs/@akanjs/devkit/src/commandDecorators/command.ts
1880
1900
  var import_prompts3 = require("@inquirer/prompts");
1881
1901
  var import_commander = require("commander");
1882
- var import_fs10 = __toESM(require("fs"), 1);
1902
+ var import_fs9 = __toESM(require("fs"));
1883
1903
  var camelToKebabCase = (str) => str.replace(/([A-Z])/g, "-$1").toLowerCase();
1884
1904
  var handleOption = (programCommand, argMeta) => {
1885
1905
  const {
@@ -1926,7 +1946,7 @@ var getOptionValue = async (argMeta, opt) => {
1926
1946
  const message = ask ?? `Do you want to set ${name}? ${desc ? ` (${desc})` : ""}: `;
1927
1947
  return await (0, import_prompts3.confirm)({ message });
1928
1948
  } else {
1929
- const message = ask ?? `Enter the ${name} value${example ? ` (example: ${example})` : ""}: `;
1949
+ const message = ask ? `${ask}: ` : `Enter the ${name} value${example ? ` (example: ${example})` : ""}: `;
1930
1950
  if (argMeta.argsOption.nullable)
1931
1951
  return await (0, import_prompts3.input)({ message });
1932
1952
  else
@@ -1975,8 +1995,8 @@ var getArgumentValue = async (argMeta, value, workspace) => {
1975
1995
  throw new Error(`Invalid system type: ${argMeta.type}`);
1976
1996
  };
1977
1997
  var runCommands = async (...commands) => {
1978
- const hasPackageJson = import_fs10.default.existsSync(`${__dirname}/package.json`);
1979
- 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";
1980
2000
  import_commander.program.version(version).description("Akan CLI");
1981
2001
  for (const command of commands) {
1982
2002
  const targetMetas = getTargetMetas(command);
@@ -2026,15 +2046,64 @@ var runCommands = async (...commands) => {
2026
2046
  var import_prompts4 = require("@inquirer/prompts");
2027
2047
  var import_messages = require("@langchain/core/messages");
2028
2048
  var import_openai2 = require("@langchain/openai");
2049
+ var import_chalk = __toESM(require("chalk"));
2029
2050
  var MAX_ASK_TRY = 300;
2051
+ var supportedLlmModels = ["deepseek-chat", "deepseek-reasoner"];
2030
2052
  var AiSession = class _AiSession {
2031
- static #chat = new import_openai2.ChatOpenAI({
2032
- modelName: "deepseek-chat",
2033
- temperature: 0.7,
2034
- streaming: true,
2035
- // Enable streaming
2036
- configuration: { baseURL: "https://api.deepseek.com/v1", apiKey: process.env.DEEPSEEK_API_KEY }
2037
- });
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
+ }
2038
2107
  messageHistory = [];
2039
2108
  constructor(messageHistory = []) {
2040
2109
  this.messageHistory = messageHistory;
@@ -2044,6 +2113,8 @@ var AiSession = class _AiSession {
2044
2113
  Logger.raw(chunk);
2045
2114
  }
2046
2115
  } = {}) {
2116
+ if (!_AiSession.#chat)
2117
+ throw new Error("Please initialize the AI session first");
2047
2118
  try {
2048
2119
  const humanMessage = new import_messages.HumanMessage(question);
2049
2120
  this.messageHistory.push(humanMessage);
@@ -2056,6 +2127,8 @@ var AiSession = class _AiSession {
2056
2127
  onChunk(content);
2057
2128
  }
2058
2129
  }
2130
+ fullResponse += "\n";
2131
+ onChunk("\n");
2059
2132
  this.messageHistory.push(new import_messages.AIMessage(fullResponse));
2060
2133
  return { content: fullResponse, messageHistory: this.messageHistory };
2061
2134
  } catch (error) {
@@ -2084,8 +2157,8 @@ var AiSession = class _AiSession {
2084
2157
  return this.#getTypescriptCode(content);
2085
2158
  }
2086
2159
  #getTypescriptCode(content) {
2087
- const code = /```typescript([\s\S]*?)```/.exec(content);
2088
- return code ? code[1] : content;
2160
+ const code = /```(typescript|tsx)([\s\S]*?)```/.exec(content);
2161
+ return code ? code[2] : content;
2089
2162
  }
2090
2163
  };
2091
2164
 
@@ -2098,9 +2171,17 @@ var LibraryRunner = class {
2098
2171
  const scanResult = await lib.scan({ akanConfig });
2099
2172
  return scanResult;
2100
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
+ }
2101
2180
  async installLibrary(workspace, libName) {
2102
2181
  workspace.log(`Installing ${libName} library as git subtree...`);
2103
- await workspace.exec(`git subtree add --prefix=libs/${libName} git@github.com:akan-team/${libName}.git main`);
2182
+ await workspace.exec(
2183
+ `git subtree add --quiet --prefix=libs/${libName} git@github.com:akan-team/${libName}.git main`
2184
+ );
2104
2185
  await workspace.cp(`libs/${libName}/env/env.server.example.ts`, `libs/${libName}/env/env.server.testing.ts`);
2105
2186
  workspace.setTsPaths("lib", libName);
2106
2187
  await workspace.commit(`Add ${libName} library`);
@@ -2129,18 +2210,18 @@ var LibraryRunner = class {
2129
2210
  });
2130
2211
  const newRootPackageJson = { ...rootPackageJson, dependencies, devDependencies };
2131
2212
  lib.workspace.writeJson("package.json", newRootPackageJson);
2132
- await lib.workspace.spawn("pnpm", ["install"]);
2213
+ await lib.workspace.spawn("pnpm", ["install", "--reporter=silent"]);
2133
2214
  await lib.workspace.commit(`Merge ${lib.name} library dependencies`);
2134
2215
  }
2135
2216
  async pushLibrary(lib, branch) {
2136
2217
  await lib.workspace.exec(
2137
- `git subtree push --prefix=libs/${lib.name} git@github.com:akan-team/${lib.name}.git ${branch}`
2218
+ `git subtree push --quiet --prefix=libs/${lib.name} git@github.com:akan-team/${lib.name}.git ${branch}`
2138
2219
  );
2139
2220
  lib.logger.log(`${lib.name} library pushed to ${branch} branch`);
2140
2221
  }
2141
2222
  async pullLibrary(lib, branch) {
2142
2223
  await lib.workspace.exec(
2143
- `git subtree pull --prefix=libs/${lib.name} git@github.com:akan-team/${lib.name}.git ${branch}`
2224
+ `git subtree pull --quiet --prefix=libs/${lib.name} git@github.com:akan-team/${lib.name}.git ${branch}`
2144
2225
  );
2145
2226
  lib.logger.log(`${lib.name} library pulled from ${branch} branch`);
2146
2227
  }
@@ -2187,6 +2268,12 @@ var LibraryScript = class {
2187
2268
  for (const libName of scanResult.akanConfig.libs)
2188
2269
  await this.syncLibrary(LibExecutor.from(lib.workspace, libName), { recursive: false });
2189
2270
  }
2271
+ async createLibrary(libName, workspace) {
2272
+ await this.#runner.createLibrary(libName, workspace);
2273
+ }
2274
+ async removeLibrary(lib) {
2275
+ await this.#runner.removeLibrary(lib);
2276
+ }
2190
2277
  async installLibrary(workspace, libName) {
2191
2278
  const lib = await this.#runner.installLibrary(workspace, libName);
2192
2279
  workspace.log(`${libName} library installed`);
@@ -2213,9 +2300,10 @@ var import_openai3 = require("@langchain/openai");
2213
2300
  var import_plugin_react = __toESM(require("@vitejs/plugin-react"));
2214
2301
  var import_dotenv3 = __toESM(require("dotenv"));
2215
2302
  var esbuild = __toESM(require("esbuild"));
2216
- var import_fs12 = __toESM(require("fs"));
2303
+ var import_fs10 = __toESM(require("fs"));
2217
2304
  var import_promises2 = __toESM(require("fs/promises"));
2218
2305
  var import_js_yaml2 = __toESM(require("js-yaml"));
2306
+ var import_open = __toESM(require("open"));
2219
2307
  var import_ora2 = __toESM(require("ora"));
2220
2308
  var import_path4 = __toESM(require("path"));
2221
2309
  var vite = __toESM(require("vite"));
@@ -2223,8 +2311,9 @@ var import_vite_plugin_node_polyfills = require("vite-plugin-node-polyfills");
2223
2311
  var import_vite_tsconfig_paths = __toESM(require("vite-tsconfig-paths"));
2224
2312
 
2225
2313
  // pkgs/@akanjs/cli/src/module/module.prompt.ts
2226
- var import_fs11 = __toESM(require("fs"));
2227
- 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.
2314
+ var frameworkDescription = `
2315
+ \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.
2316
+ \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.
2228
2317
 
2229
2318
  \uAC00\uC7A5 \uC678\uBD80\uC758 \uAD6C\uC870\uB294
2230
2319
  - app
@@ -2742,6 +2831,433 @@ export const General = ({ className, \${dict.model}, self }: \${dict.Model}ViewP
2742
2831
 
2743
2832
  \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.
2744
2833
  `;
2834
+ var moduleDesription = `
2835
+
2836
+ The project follows a modular architecture with clear separation of concerns. Each module in lib/<model>/ represents a domain
2837
+ entity with a standardized file structure that promotes consistency and maintainability.
2838
+
2839
+ ## Core Components
2840
+
2841
+ ### <Model>.View.tsx
2842
+ Presentation-only components that render data without managing state.
2843
+ It works as a server component, They accept model data as props and display it according to specific layouts.
2844
+ These components focus purely on how data looks to the user.
2845
+ only use the full model.
2846
+ This component is only viewing the component. So don't use click event or other interaction events.
2847
+ If you need interaction, possible to wrapping the component with the <Model>.Zone.tsx component.
2848
+ But useable the Link component for navigation.
2849
+ 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.
2850
+
2851
+
2852
+ ### <Model>.Template.tsx
2853
+ Reusable layout patterns with integrated state management. It works as a client component, These components provide consistent UI patterns and handle data
2854
+ binding, often using store hooks to access application state.
2855
+
2856
+ ### <Model>.Unit.tsx
2857
+ Small, self-contained UI components representing individual model instances. It works as a server component, They're designed for rendering single items in
2858
+ lists or grids, displaying model data in compact formats. only use the light model.
2859
+
2860
+ ### <Model>.Zone.tsx
2861
+ Top-level container components that orchestrate other components. It works as a client component, They compose views, templates, and units into complete UI
2862
+ sections while managing data flow to child components.
2863
+
2864
+ ### <Model>.Util.tsx
2865
+ Specialized components and utility functions specific to a model, It works as a client component, providing both UI components and helper functions for
2866
+ model-specific functionality.
2867
+
2868
+ ## Data Management
2869
+
2870
+ ### <model>.signal.ts
2871
+ Defines API endpoints with type safety using decorators for GraphQL queries and mutations, creating a type-safe bridge between
2872
+ frontend and backend.
2873
+
2874
+ ### <model>.store.ts
2875
+ Manages client-side state with typed actions and state, handling UI state, form state, and cached data.
2876
+
2877
+ ### <model>.service.ts
2878
+ Implements server-side business logic with dependency injection, handling data processing and complex operations.
2879
+
2880
+ ### <model>.constant.ts
2881
+ Defines type definitions and model schemas using decorators to structure model fields, validation, and relationships.
2882
+
2883
+ ### <model>.dictionary.ts
2884
+ Provides internationalization and label definitions for model properties and operations.
2885
+
2886
+ ### <model>.document.ts
2887
+ Defines database schema and model operations with decorators for database interaction.
2888
+
2889
+ ## Data Flow
2890
+ The architecture follows a clear data flow pattern:
2891
+ - Server-side: Document \u2192 Service \u2192 Signal \u2192 API
2892
+ - Client-side: API \u2192 Store \u2192 Components (Zone \u2192 Template/View/Unit)
2893
+
2894
+ This modular structure enables rapid development while maintaining consistency, type safety, and testability throughout the
2895
+ application.
2896
+ `;
2897
+ var utilUiDescription = `
2898
+ This UI kit is an internally developed UI kit within the Akan.js framework.
2899
+ The libs/util/ui directory contains a comprehensive React component library designed for modern web applications.
2900
+ This framework provides a complete set of production-ready, reusable UI components with consistent styling, type safety, and advanced functionality.
2901
+
2902
+ - Every component must be used exactly as described in the documentation.
2903
+ - Do not add any additional props to the components.
2904
+ - Must use the written props exactly.
2905
+ - Only the components explicitly listed in the documentation are available\u2014no additional components exist beyond those specified.
2906
+
2907
+
2908
+
2909
+ Architecture & Foundation
2910
+
2911
+ Core Technologies:
2912
+ - Built on React 18+ with TypeScript for strict type safety
2913
+ - Styled with Tailwind CSS and DaisyUI for consistent design system
2914
+ - Implements modern React patterns including hooks, context providers, and portals
2915
+ - Full internationalization (i18n) support for multilingual applications
2916
+ - Responsive-first design with mobile optimization
2917
+
2918
+ Design Principles:
2919
+ - Composable component architecture with predictable APIs
2920
+ - Accessibility (a11y) compliance throughout
2921
+ - Performance optimization with lazy loading and code splitting
2922
+ - Consistent error handling and validation patterns
2923
+ - Session storage integration for form state persistence
2924
+
2925
+ Component Categories
2926
+
2927
+ Core Input Components
2928
+
2929
+ Essential form controls with advanced validation and user experience features:
2930
+ - Button - Async-aware button with automatic loading/success/error states
2931
+ - Input - Comprehensive input system with real-time validation, multiple variants (Text, Password, Email, Number, Checkbox), and
2932
+ session caching
2933
+ - Select - Advanced dropdown with search, multi-select, and custom rendering
2934
+ - DatePicker - Date/time selection with range support and custom formatting
2935
+ - CodeInput - PIN/verification code input with auto-focus management
2936
+ - Upload - File upload system with drag-drop, progress tracking, image cropping, and multiple file support
2937
+
2938
+ Data Display Components
2939
+
2940
+ Components for presenting and organizing information:
2941
+ - Chart - Visualization suite (Bar, Line, Pie, Doughnut) built on Chart.js
2942
+ - Avatar - User profile images with intelligent fallbacks
2943
+ - ChatBubble - Chat interface with message grouping and timestamps
2944
+ - Empty - Customizable empty state displays
2945
+ - QRCode - QR code generation with click-to-open functionality
2946
+
2947
+ Layout & Navigation System
2948
+
2949
+ Comprehensive layout framework for application structure:
2950
+ - Layout - Complete layout system with Header (auto-hide), Sider (collapsible), Navbar (portal-based), BottomTab (with badges),
2951
+ and container components
2952
+ - Modal/Dialog - Composable dialog system with backdrop, animations, and gesture support
2953
+ - BottomSheet - Mobile-optimized bottom sheet with drag gestures
2954
+ - Menu - Navigation menus with horizontal/vertical modes and submenu support
2955
+ - Tab - Tabbed interfaces with lazy loading and scroll management
2956
+ - ScreenNavigator - Gesture-based screen navigation with spring animations
2957
+
2958
+ Interactive Components
2959
+
2960
+ Advanced user interaction components:
2961
+ - Pagination - Smart page navigation with ellipsis and responsive design
2962
+ - InfiniteScroll - Automatic content loading with intersection observer
2963
+ - DndKit - Drag and drop functionality with provider pattern
2964
+ - Radio - Radio button groups with custom styling
2965
+ - ToggleSelect - Button-based selection with single/multi-select modes
2966
+ - Share - Native share API with copy fallback
2967
+
2968
+ Utility & Feedback Components
2969
+
2970
+ Supporting components for enhanced user experience:
2971
+ - Loading - Comprehensive loading states (Area, Button, Input, Skeleton, Spin, ProgressBar) with animations
2972
+ - Link - Adaptive navigation links with SSR/CSR compatibility
2973
+ - MapView - Map integration supporting both Google Maps and Pigeon Maps with markers and overlays
2974
+ - Image - Optimized image component with blur placeholders and SSR support
2975
+ - Portal - Teleportation component for rendering outside component tree
2976
+
2977
+ Advanced Features
2978
+
2979
+ State Management Integration
2980
+
2981
+ - Context-driven architecture for complex components
2982
+ - Signal-based real-time communication components
2983
+ - Session storage integration for form persistence
2984
+ - Theme-aware styling with automatic adaptation
2985
+
2986
+ Performance Optimizations
2987
+
2988
+ - Lazy loading support for heavy components
2989
+ - Code splitting at component level
2990
+ - Optimized re-rendering with React.memo patterns
2991
+ - Intersection Observer for scroll-based interactions
2992
+
2993
+ Developer Experience
2994
+
2995
+ - Comprehensive TypeScript interfaces for all props
2996
+ - Consistent naming conventions and API patterns
2997
+ - Built-in error boundaries and fallback handling
2998
+ - Extensive JSDoc documentation
2999
+ - Hot reload support for development
3000
+
3001
+ Accessibility & Internationalization
3002
+
3003
+ - ARIA attributes and keyboard navigation support
3004
+ - Screen reader compatibility
3005
+ - RTL (right-to-left) language support
3006
+ - Localized date/time formatting
3007
+ - Color contrast compliance
3008
+
3009
+ Usage Patterns
3010
+
3011
+ The library follows a consistent component composition pattern where complex components are built from smaller, focused
3012
+ subcomponents. For example:
3013
+
3014
+ - Chart.Bar, Chart.Line for different visualization types
3015
+ - Dialog.Modal, Dialog.Title, Dialog.Content for composable modals
3016
+ - Layout.Header, Layout.Sider, Layout.Navbar for layout construction
3017
+ - Upload.File, Upload.Image, Upload.Images for different upload scenarios
3018
+
3019
+ This design enables maximum flexibility while maintaining consistency across the application. Components are designed to work
3020
+ seamlessly together, sharing common styling patterns, validation systems, and state management approaches.
3021
+
3022
+ The library serves as a comprehensive foundation for building modern, accessible, and performant web applications with a focus
3023
+ on developer productivity and end-user experience.
3024
+
3025
+ Avatar
3026
+ - Displays user profile images with automatic fallback to user icon
3027
+ - Props: className?: string, icon?: ReactNode, src?: string
3028
+
3029
+ Button
3030
+ - Enhanced button with automatic loading states and error handling
3031
+ - Props: onClick: (e, {onError}) => Promise<Result>, onSuccess?: (result) => void, className?, children, standard button props
3032
+
3033
+ Input
3034
+ - Comprehensive input system with real-time validation and caching
3035
+ - Props: value: string, validate: (value) => boolean | string, onChange?, nullable?, inputStyleType?: "bordered" | "borderless"
3036
+ | "underline", icon?, cacheKey?
3037
+ - Variants: Input.TextArea, Input.Password, Input.Email, Input.Number, Input.Checkbox
3038
+
3039
+ Select
3040
+ - Advanced dropdown with search and multi-select capabilities
3041
+ - Props: value: T | T[], options: {label, value}[], multiple?, searchable?, onChange, onSearch?, renderOption?, renderSelected?
3042
+
3043
+ DatePicker
3044
+ - Date/time picker with range selection support
3045
+ - Props: value?: Dayjs, onChange, showTime?, format?, disabledDate?
3046
+ - Variants: DatePicker.RangePicker, DatePicker.TimePicker
3047
+
3048
+ CodeInput
3049
+ - PIN/code input with individual character boxes
3050
+ - Props: maxNum: number, value: string, onChange, unitStyle?: "box" | "underline", autoComplete?
3051
+
3052
+ Display Components
3053
+
3054
+ Table
3055
+ - Feature-rich data table with pagination and responsive design
3056
+ - Props: columns: Column[], dataSource: any[], loading?, pagination?, onRow?, rowClassName?
3057
+
3058
+ Modal
3059
+ - Dialog modal with backdrop and action buttons
3060
+ - Props: open: boolean, onCancel, title?, action?, confirmClose?
3061
+ - Variants: Modal.Window
3062
+
3063
+ Image
3064
+ - Optimized image component with blur placeholder and SSR support
3065
+ - Props: src?, file?: ProtoFile, abstractData?, alt?, standard Next.js Image props
3066
+
3067
+ ChatBubble
3068
+ - Chat message bubble with avatar and timestamp
3069
+ - Props: avatar?, hasPrev?, hasNext?, isMe?, name?, at?: Dayjs, children
3070
+
3071
+ Empty
3072
+ - Empty state placeholder with customizable message
3073
+ - Props: description?, minHeight?, children?
3074
+
3075
+ QRCode
3076
+ - QR code generator with click-to-open functionality
3077
+ - Props: href: string, className?
3078
+
3079
+ Layout Components
3080
+
3081
+ BottomSheet
3082
+ - Only mobile bottom sheet with drag gestures
3083
+ - Props: open: boolean, onCancel, type: "full" | "half", children
3084
+
3085
+ Layout
3086
+ Layout - Complete layout framework with responsive design
3087
+ - Layout.Header - Top header with auto-hide functionality
3088
+ - Props: className?: string, type?: "static" | "hide", children?: any, height?: number
3089
+ - Features: Auto-hide on scroll, fixed positioning
3090
+ - Layout.Sider - Collapsible sidebar
3091
+ - Props: className?: string, bgClassName?: string, children?: any
3092
+ - Features: Drawer-based with toggle functionality
3093
+ - Layout.Navbar - Navigation bar with portal content
3094
+ - Props: className?: string, children?: ReactNode, height?:
3095
+
3096
+ Menu
3097
+ - Navigation menu with horizontal/vertical modes and submenu support
3098
+ - Props: items: MenuItem[], mode?: "horizontal" | "inline", selectedKeys?, onClick?, inlineCollapsed?
3099
+
3100
+
3101
+ Tab
3102
+ - Tabbed interface system
3103
+ - Tab.Provider - Tab context provider
3104
+ - Props: className?: string, defaultMenu?: string | null, children?: any
3105
+ - Tab.Menu - Tab menu item
3106
+ - Props: className?: string, activeClassName?: string, disabledClassName?: string, disabled?: boolean, menu: string, children:
3107
+ any, scrollToTop?: boolean, tooltip?: string
3108
+ - Tab.Panel - Tab content panel
3109
+ - Props: className?: string, menu: string, children?: any, loading?: "eager" | "lazy" | "every"
3110
+ - Features: Lazy loading support
3111
+
3112
+ ScreenNavigator
3113
+ - Gesture-based screen navigation
3114
+ - ScreenNavigator.Provider - Navigation context provider
3115
+ - Props: setMenu?: (menu: string) => void, children: ReactNode, menus: string[]
3116
+ - Features: Gesture-based navigation, spring animations
3117
+ - ScreenNavigator.Screen - Individual screen container
3118
+ - Props: children: ReactNode, className?: string
3119
+ - ScreenNavigator.NavbarItem - Navigation bar item
3120
+ - Props: menu: string, children: ReactNode, className?: string
3121
+
3122
+ Upload
3123
+ - File upload system with multiple modes
3124
+ - Upload
3125
+ - Basic file upload with drag & drop
3126
+ - Props: onChange?: (fileList: FileList) => void; multiple?: boolean; accept?: string; className?: string; uploadClassName?: string; children: React.ReactNode; disabled?: boolean;
3127
+ - Upload.File
3128
+ - Single file upload with preview
3129
+ - 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;
3130
+ - Upload.FileList
3131
+ - Multiple files with table view and progress tracking
3132
+ - 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;
3133
+ - Upload.Image
3134
+ - Image upload with integrated cropping functionality
3135
+ - 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;
3136
+ - Upload.Images
3137
+ - Multiple image upload with gallery preview
3138
+ - 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;
3139
+
3140
+ DndKit
3141
+ - Drag and drop functionality built on @dnd-kit
3142
+ - DndKit.Provider
3143
+ - DnD context provider
3144
+ - Props: className?: string + all DndContextProps
3145
+ - DndKit.DraggableUnit
3146
+ - Draggable item wrapper
3147
+ - Props: id: string, children: ReactNode, className?: string, onClick?: () => void | Promise<void>
3148
+ - DndKit.DroppableColumn
3149
+ - Drop target column
3150
+ - Props: id: string, items: T[], className?: string, children: ReactNode, onOver?: (id, items, event) => void, onEnd?: (id,
3151
+ item, event) => void
3152
+
3153
+ MapView
3154
+ - Map integration with multiple providers
3155
+ - MapView.Map
3156
+ - Main map container with theme awareness
3157
+ - Props: className?: string, onLoad?: () => void, onClick?: (coordinate) => void, onRightClick?: (coordinate) => void,
3158
+ onMouseMove?: (coordinate) => void, children: any
3159
+ - MapView.Marker
3160
+ - Map marker component
3161
+ - Props: coordinate: cnst.Coordinate, zIndex?: number, children?: any
3162
+ - MapView.Google
3163
+ - Google Maps implementation
3164
+ - Props: id?: string, className?: string, mapKey: string, onClick/onRightClick?: (coordinate) => void, center?:
3165
+ cnst.Coordinate, onChangeCenter?: (coordinate) => void, zoom?: number, onChangeZoom?: (zoom) => void, bounds?: {minLat, maxLat,
3166
+ minLng, maxLng}, onLoad?: () => void, onMouseMove?: (coordinate, event) => void, options?: google.maps.MapOptions, children: any
3167
+ - MapView.Pigeon
3168
+ - Pigeon Maps implementation (lightweight alternative)
3169
+ - Props: id?: string, className?: string, onLoad?: () => void, onClick/onRightClick?: (coordinate) => void, center?:
3170
+ cnst.Coordinate, onChangeCenter?: (coordinate) => void, zoom?: number, onChangeZoom?: (zoom) => void, bounds?: {minLat, maxLat,
3171
+ minLng, maxLng}, onChangeBounds?: (bounds) => void, mouseEvents?: boolean, onMouseMove?: (coordinate) => void, mapTiler?: (x, y,
3172
+ z, dpr) => string, children?: any, zoomControlStyle?: CSSProperties
3173
+
3174
+
3175
+ Pagination
3176
+ - Page navigation with smart ellipsis and responsive design
3177
+ - Props: currentPage: number, total: number, onPageSelect, itemsPerPage: number
3178
+
3179
+ Radio
3180
+ - Radio button group with custom styling support
3181
+ - Props: value, children: ReactElement[], onChange, disabled?
3182
+
3183
+ ToggleSelect
3184
+ - Button-based selection with single/multi-select modes
3185
+ - Props: items, value, validate, onChange, nullable
3186
+ - Variants: ToggleSelect.Multi
3187
+
3188
+ Share
3189
+ - Native share API with copy fallback
3190
+ - Props: title: string, url: string, children
3191
+
3192
+ Specialized Component Groups
3193
+
3194
+ Chart
3195
+ - Visualization components built on Chart.js and react-chartjs-2
3196
+ - Chart.Bar - Bar chart component
3197
+ - Props: data: ChartData<"bar">, options?: ChartOptions<"bar">
3198
+ - Features: Responsive layout, legend display, title configuration
3199
+ - Chart.Line - Line chart component
3200
+ - Props: data: ChartData<"line">, options?: ChartOptions<"line">
3201
+ - Features: Line-specific Chart.js configuration with curve interpolation
3202
+ - Chart.Pie - Pie chart component
3203
+ - Props: data: ChartData<"pie">, options?: ChartOptions<"pie">
3204
+ - Features: ArcElement rendering, responsive design
3205
+ - Chart.Doughnut - Doughnut chart component
3206
+ - Props: data: ChartData<"doughnut">, options?: ChartOptions<"doughnut">
3207
+ - Features: Similar to pie but with center cutout
3208
+
3209
+ Dialog
3210
+ - Composable modal dialog system built on Radix UI
3211
+ - Dialog.Provider - Dialog context provider
3212
+ - Props: className?: string, open?: boolean, defaultOpen?: boolean, children?: any
3213
+ - Dialog.Modal - Main modal container
3214
+ - Props: className?: string, bodyClassName?: string, confirmClose?: boolean, children?: any, onCancel?: () => void
3215
+ - Features: Drag gestures, spring animations, responsive design, close confirmation
3216
+ - Dialog.Title - Modal title component
3217
+ - Props: children?: ReactNode
3218
+ - Dialog.Content - Modal content area
3219
+ - Props: className?: string, children?: ReactNode
3220
+ - Dialog.Action - Modal action buttons container
3221
+ - Props: children?: ReactNode
3222
+ - Dialog.Trigger - Modal trigger element
3223
+ - Props: className?: string, children?: any
3224
+
3225
+ Link
3226
+ - Adaptive navigation system
3227
+ - Link
3228
+ - Main adaptive link (auto-switches between CSR/Next.js based on render mode)
3229
+ - Link.Back - Back navigation link
3230
+ - Props: className?: string, children?: any
3231
+ - Features: Browser history integration
3232
+ - Link.Close - Window close link
3233
+ - Props: Similar to Back but closes window
3234
+ - Link.CsrLink & Link.NextLink - Environment-specific implementations with active state support
3235
+
3236
+
3237
+ Loading
3238
+ - Loading states for different UI elements
3239
+ - Loading.Area - Full-screen loading overlay with animated dots
3240
+ - Loading.Button - Button loading skeleton
3241
+ - Props: className?: string, active?: boolean, style?: CSSProperties
3242
+ - Loading.Input - Input loading skeleton
3243
+ - Loading.Skeleton - Multi-line content skeleton with pulse animation
3244
+ - Loading.Spin - Custom loading spinner
3245
+ - Props: indicator?: ReactNode, isCenter?: boolean
3246
+ - Loading.ProgressBar - Animated progress bar
3247
+ - Props: className?: string, value: number, max: number
3248
+ - Features: React Spring animations
3249
+
3250
+ Key Framework Features
3251
+
3252
+ - TypeScript support with strict typing
3253
+ - Responsive design with mobile-first approach
3254
+ - Internationalization (i18n) integration
3255
+ - Session storage caching for form inputs
3256
+ - Accessibility compliance
3257
+ - Consistent DaisyUI/Tailwind CSS styling
3258
+ - Modern React patterns (hooks, context, providers)
3259
+ - Error handling and validation systems
3260
+ `;
2745
3261
  var frameworkAbstract = `
2746
3262
  Intro
2747
3263
  - Build an all-stack application at once.
@@ -2761,7 +3277,66 @@ Procedure
2761
3277
  - No Spaghetti Components anymore, build your page with domain-driven components
2762
3278
  - write one page, use SSR on Next.js and build Android&iOS CSR app with beautiful page transitions!
2763
3279
  - built-in ai code generation, tell about business, the logic is generated.
3280
+
3281
+
2764
3282
  `;
3283
+ var eslintDescription = `
3284
+ Core ESLint Extensions
3285
+
3286
+ Base Configurations:
3287
+ - eslint:recommended - Standard ESLint recommended rules
3288
+ - next & next/core-web-vitals - Next.js specific linting rules
3289
+ - @typescript-eslint/recommended-type-checked - TypeScript recommended rules with type checking
3290
+ - @typescript-eslint/strict-type-checked - Strict TypeScript type checking rules
3291
+ - @typescript-eslint/stylistic-type-checked - TypeScript stylistic rules with type checking
3292
+
3293
+ Third-Party Plugins
3294
+
3295
+ 1. eslint-plugin-unused-imports
3296
+ - Automatically detects and warns about unused imports
3297
+ - Helps keep code clean by removing unnecessary import statements
3298
+
3299
+ 2. eslint-plugin-simple-import-sort
3300
+ - Automatically sorts import statements in a consistent order
3301
+ - Enforces clean import organization throughout the codebase
3302
+
3303
+ Custom Plugin: @akanjs/lint
3304
+
3305
+ 1. useClientByFile
3306
+ - Enforces proper "use client" directive usage in Next.js App Router
3307
+ - Server files must NOT have "use client" directive
3308
+ - Client files MUST have "use client" directive at the top
3309
+
3310
+ 2. noImportClientFunctions
3311
+ - Prevents server files from importing client-side functions
3312
+ - Ensures proper separation between server and client code
3313
+
3314
+ 3. nonScalarPropsRestricted
3315
+ - Prevents non-scalar props (functions) in server components
3316
+ - Specifically targets page.tsx and layout.tsx files
3317
+ - Allows exceptions for specific props like "loader", "render", and "of"
3318
+
3319
+ 4. noImportExternalLibrary
3320
+ - Restricts external library imports in pure import/re-export files
3321
+ - Only allows imports from the same app scope (@appName/...)
3322
+ - Promotes clean architecture and prevents dependency leakage
3323
+
3324
+ Key Rule Configurations
3325
+
3326
+ Disabled Rules:
3327
+ - no-console: "error" - Prevents console statements in production code
3328
+ - Various TypeScript strict rules are disabled for flexibility
3329
+ - React and Next.js specific rules are relaxed for development ease
3330
+
3331
+ Import Management:
3332
+ - unused-imports/no-unused-imports: "warn" - Warns about unused imports
3333
+ - simple-import-sort/imports: "warn" - Enforces import sorting
3334
+ - import/first: "warn" - Ensures imports come first
3335
+ - import/newline-after-import: "warn" - Enforces newline after imports
3336
+
3337
+ This configuration creates a robust linting setup that enforces Next.js App Router best practices, maintains clean code
3338
+ organization, and ensures proper server/client code separation.
3339
+ `;
2765
3340
  var scalarConstantDescription = `
2766
3341
  Purpose and Structure
2767
3342
 
@@ -3116,10 +3691,10 @@ ${frameworkAbstract}
3116
3691
  2. <model>.constant.ts \uD30C\uC77C\uC5D0 \uB300\uD55C \uAC1C\uC694
3117
3692
  ${scalarConstantDescription}
3118
3693
 
3119
- 3. <model.constant.ts \uD30C\uC77C\uC758 Enum \uC791\uC131\uBC95
3694
+ 3. <model>.constant.ts \uD30C\uC77C\uC758 Enum \uC791\uC131\uBC95
3120
3695
  ${howToSetEnumInModelConstant}
3121
3696
 
3122
- 4. <model.constant.ts \uD30C\uC77C\uC758 Field \uC791\uC131\uBC95
3697
+ 4. <model>.constant.ts \uD30C\uC77C\uC758 Field \uC791\uC131\uBC95
3123
3698
  ${howToSetFieldInModelConstant}
3124
3699
 
3125
3700
  5. \uD604\uC7AC \uD504\uB85C\uC81D\uD2B8 \uB0B4 \uB2E4\uB978 constant.ts \uD30C\uC77C\uB4E4\uC5D0 \uB300\uD55C \uC608\uC2DC
@@ -3144,6 +3719,87 @@ Target filename: ${modelName}.constant.ts
3144
3719
  \`\`\`
3145
3720
  ${boilerplate}
3146
3721
  \`\`\`
3722
+ `;
3723
+ var requestView = ({
3724
+ sysName,
3725
+ modelName,
3726
+ ModelName,
3727
+ boilerplate,
3728
+ constant,
3729
+ properties,
3730
+ exampleFiles
3731
+ }) => `
3732
+
3733
+
3734
+ 1. Akan.js \uD504\uB808\uC784\uC6CC\uD06C\uC5D0 \uB300\uD55C \uAC1C\uC694
3735
+ ${frameworkAbstract}
3736
+
3737
+ 2. Akan.js\uD504\uB808\uC784\uC6CC\uD06C \uB370\uC774\uD130 \uAE30\uBC18 \uBAA8\uB4C8\uC5D0 \uB300\uD55C \uAC1C\uC694
3738
+ ${moduleDesription}
3739
+
3740
+ 3. Akan.js eslint \uC124\uC815\uC5D0 \uB300\uD55C \uAC1C\uC694
3741
+ ${eslintDescription}
3742
+
3743
+ 4. util/ui \uB0B4 ui\uD0B7\uC5D0 \uB300\uD55C \uAC1C\uC694
3744
+ ${utilUiDescription}
3745
+
3746
+
3747
+
3748
+ 5. ${ModelName}.constant.ts \uD30C\uC77C\uC5D0 \uB300\uD55C \uC815\uBCF4
3749
+ ${constant}
3750
+
3751
+ 6. ${modelName}\uC5D0\uC11C \uC885\uC18D\uB418\uB294 \uB2E4\uB978 \uBAA8\uB378\uB4E4\uC758 \uD0C0\uC785 \uC815\uC758
3752
+ ${properties.map(
3753
+ (property) => `
3754
+ \`\`\`
3755
+ ${property.key}.constant.ts
3756
+
3757
+
3758
+ ${property.source}
3759
+ \`\`\`
3760
+ `
3761
+ ).join("\n\n")}
3762
+
3763
+
3764
+ 7. \uC608\uC2DC \uD30C\uC77C\uB4E4
3765
+ ${exampleFiles.map(
3766
+ (example) => `
3767
+ Example filename: ${example.filepath}
3768
+ \`\`\`
3769
+ ${example.content}
3770
+ \`\`\`
3771
+ `
3772
+ ).join("\n\n")}
3773
+
3774
+
3775
+
3776
+ Application name: ${sysName}
3777
+ Model name: ${modelName}
3778
+ Target filename: ${ModelName}.View.tsx
3779
+
3780
+
3781
+ \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.
3782
+ \uADF8 \uC911\uC5D0\uC11C\uB3C4 \uD504\uB860\uD2B8\uC5D4\uB4DC \uAC1C\uBC1C\uC790.
3783
+ \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.
3784
+ \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.
3785
+ \uADF8\uB9AC\uACE0 optional\uD55C \uD544\uB4DC\uB294 field && <div>... \uAC00 \uC544\uB2CC, field ? <div>... : null \uD615\uD0DC\uB85C \uC791\uC131\uD574\uC918.
3786
+ 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.
3787
+ \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.
3788
+ \uC870\uAC74\uBD80 className\uC774 \uD544\uC694\uD55C \uACBD\uC6B0\uC5D0\uB294 clsx \uB77C\uC774\uBE0C\uB7EC\uB9AC\uB97C \uC0AC\uC6A9\uD574\uC57C\uB3FC.
3789
+ \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.
3790
+ \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.
3791
+ \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...)
3792
+ \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.
3793
+ \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.
3794
+ ${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...)
3795
+ \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.
3796
+
3797
+ Target filename: ${ModelName}.View.tsx
3798
+ \`\`\`
3799
+
3800
+ \`\`\`
3801
+
3802
+
3147
3803
  `;
3148
3804
 
3149
3805
  // pkgs/@akanjs/cli/src/application/application.prompt.ts
@@ -3195,6 +3851,10 @@ var ApplicationRunner = class {
3195
3851
  workspace.setTsPaths("app", appName);
3196
3852
  return AppExecutor.from(workspace, appName);
3197
3853
  }
3854
+ async removeApplication(app) {
3855
+ await app.workspace.exec(`rm -rf apps/${app.name}`);
3856
+ app.log(`Application ${app.name} removed`);
3857
+ }
3198
3858
  async scanSync(app) {
3199
3859
  const akanConfig = await getAppConfig(app.cwdPath, {
3200
3860
  ...app.workspace.getBaseDevEnv(),
@@ -3216,16 +3876,16 @@ var ApplicationRunner = class {
3216
3876
  ...env
3217
3877
  };
3218
3878
  }
3219
- async #prepareCommand(app, distApp, type, target) {
3220
- await distApp.exec(`rm -rf ${target}`);
3879
+ async #prepareCommand(app, type, target) {
3880
+ await app.dist.exec(`rm -rf ${target}`);
3221
3881
  if (target === "frontend") {
3222
3882
  await app.exec("rm -rf .next");
3223
3883
  app.writeFile("next.config.ts", defaultNextConfigFile);
3224
3884
  }
3225
3885
  return { env: this.#getEnv(app, { AKAN_COMMAND_TYPE: type }) };
3226
3886
  }
3227
- async buildBackend(app, distApp) {
3228
- await this.#prepareCommand(app, distApp, "serve", "backend");
3887
+ async buildBackend(app) {
3888
+ await this.#prepareCommand(app, "serve", "backend");
3229
3889
  const akanConfig = await app.getConfig("build");
3230
3890
  const buildResult = await esbuild.build({
3231
3891
  write: false,
@@ -3233,12 +3893,12 @@ var ApplicationRunner = class {
3233
3893
  bundle: true,
3234
3894
  packages: "external",
3235
3895
  platform: "node",
3236
- outdir: `${distApp.cwdPath}/backend`,
3896
+ outdir: `${app.dist.cwdPath}/backend`,
3237
3897
  logLevel: "warning"
3238
3898
  });
3239
3899
  const rootPackageJson = app.workspace.readJson("package.json");
3240
3900
  const dependencies = extractDependencies(buildResult.outputFiles, rootPackageJson);
3241
- buildResult.outputFiles.map((file) => distApp.writeFile(file.path, file.text));
3901
+ buildResult.outputFiles.map((file) => app.dist.writeFile(file.path, file.text));
3242
3902
  const appPackageJson = {
3243
3903
  name: `${app.name}/backend`,
3244
3904
  description: `${app.name} backend`,
@@ -3247,31 +3907,33 @@ var ApplicationRunner = class {
3247
3907
  engines: { node: ">=22" },
3248
3908
  dependencies
3249
3909
  };
3250
- distApp.writeJson("backend/package.json", appPackageJson);
3251
- distApp.writeFile(import_path4.default.join(distApp.cwdPath, "backend", "Dockerfile"), akanConfig.backend.dockerfile);
3910
+ app.dist.writeJson("backend/package.json", appPackageJson);
3911
+ app.dist.writeFile(import_path4.default.join(app.dist.cwdPath, "backend", "Dockerfile"), akanConfig.backend.dockerfile);
3252
3912
  }
3253
- async serveBackend(app, distApp) {
3254
- const { env } = await this.#prepareCommand(app, distApp, "serve", "backend");
3913
+ async serveBackend(app, { open: open2 = false } = {}) {
3914
+ const { env } = await this.#prepareCommand(app, "serve", "backend");
3255
3915
  const ctx = await esbuild.context({
3256
3916
  write: true,
3257
3917
  entryPoints: [`${app.cwdPath}/main.ts`],
3258
3918
  bundle: true,
3259
3919
  packages: "external",
3260
3920
  platform: "node",
3261
- outdir: import_path4.default.join(distApp.cwdPath, "backend"),
3921
+ outdir: import_path4.default.join(app.dist.cwdPath, "backend"),
3262
3922
  logLevel: "warning"
3263
3923
  });
3264
3924
  await ctx.watch();
3265
3925
  await sleep(100);
3266
- await distApp.spawn("node", ["--watch", "backend/main.js"], { env });
3926
+ if (open2)
3927
+ setTimeout(() => (0, import_open.default)("http://localhost:8080/backend/graphql"), 3e3);
3928
+ await app.dist.spawn("node", ["--watch", "backend/main.js"], { env });
3267
3929
  }
3268
- async buildFrontend(app, distApp) {
3269
- const { env } = await this.#prepareCommand(app, distApp, "build", "frontend");
3930
+ async buildFrontend(app) {
3931
+ const { env } = await this.#prepareCommand(app, "build", "frontend");
3270
3932
  const akanConfig = await app.getConfig("build");
3271
3933
  await app.spawn("npx", ["next", "build", "--no-lint"], { env });
3272
3934
  const buildResult = await esbuild.build({
3273
3935
  entryPoints: [`${app.cwdPath}/next.config.ts`],
3274
- outdir: `${distApp.cwdPath}/frontend`,
3936
+ outdir: `${app.dist.cwdPath}/frontend`,
3275
3937
  bundle: true,
3276
3938
  packages: "external",
3277
3939
  platform: "node",
@@ -3282,7 +3944,7 @@ var ApplicationRunner = class {
3282
3944
  });
3283
3945
  const rootPackageJson = app.workspace.readJson("package.json");
3284
3946
  const dependencies = extractDependencies(buildResult.outputFiles, rootPackageJson, ["next", "react", "react-dom"]);
3285
- buildResult.outputFiles.map((file) => distApp.writeFile(file.path, file.text));
3947
+ buildResult.outputFiles.map((file) => app.dist.writeFile(file.path, file.text));
3286
3948
  const appPackageJson = {
3287
3949
  name: `${app.name}/frontend`,
3288
3950
  description: `${app.name} frontend`,
@@ -3293,26 +3955,28 @@ var ApplicationRunner = class {
3293
3955
  start: "next start"
3294
3956
  }
3295
3957
  };
3296
- distApp.writeJson("frontend/package.json", appPackageJson);
3958
+ app.dist.writeJson("frontend/package.json", appPackageJson);
3297
3959
  await Promise.all([
3298
- app.cp(".next", import_path4.default.join(distApp.cwdPath, "frontend", ".next")),
3299
- app.cp("public", import_path4.default.join(distApp.cwdPath, "frontend", "public"))
3960
+ app.cp(".next", import_path4.default.join(app.dist.cwdPath, "frontend", ".next")),
3961
+ app.cp("public", import_path4.default.join(app.dist.cwdPath, "frontend", "public"))
3300
3962
  ]);
3301
- distApp.writeFile("frontend/Dockerfile", akanConfig.frontend.dockerfile);
3963
+ app.dist.writeFile("frontend/Dockerfile", akanConfig.frontend.dockerfile);
3302
3964
  }
3303
- async serveFrontend(app, distApp) {
3304
- const { env } = await this.#prepareCommand(app, distApp, "serve", "frontend");
3305
- await app.spawn("npx", ["next", "dev", "-p", "4200"], { env });
3965
+ async serveFrontend(app, { open: open2 = false, turbo = true } = {}) {
3966
+ const { env } = await this.#prepareCommand(app, "serve", "frontend");
3967
+ if (open2)
3968
+ setTimeout(() => (0, import_open.default)("http://localhost:4200"), 3e3);
3969
+ await app.spawn("npx", ["next", "dev", "-p", "4200", ...turbo ? ["--turbo"] : []], { env });
3306
3970
  }
3307
- async #getViteConfig(app, distApp) {
3308
- const { env } = await this.#prepareCommand(app, distApp, "build", "csr");
3971
+ async #getViteConfig(app) {
3972
+ const { env } = await this.#prepareCommand(app, "build", "csr");
3309
3973
  const processEnv = env;
3310
3974
  const akanjsPrefix = process.env.USE_AKANJS_PKGS === "true" ? "../../../../pkgs/" : "";
3311
3975
  const config = vite.defineConfig({
3312
3976
  root: `${app.cwdPath}/app`,
3313
3977
  base: "/",
3314
3978
  build: {
3315
- outDir: `${distApp.cwdPath}/csr`,
3979
+ outDir: `${app.dist.cwdPath}/csr`,
3316
3980
  sourcemap: false,
3317
3981
  emptyOutDir: true,
3318
3982
  rollupOptions: { external: ["next/server"], input: `${app.cwdPath}/app/index.html` }
@@ -3370,18 +4034,20 @@ var ApplicationRunner = class {
3370
4034
  });
3371
4035
  return config;
3372
4036
  }
3373
- async buildCsr(app, distApp) {
3374
- const config = await this.#getViteConfig(app, distApp);
4037
+ async buildCsr(app) {
4038
+ const config = await this.#getViteConfig(app);
3375
4039
  await vite.build(config);
3376
4040
  }
3377
- async serveCsr(app, distApp) {
3378
- const config = await this.#getViteConfig(app, distApp);
4041
+ async serveCsr(app, { open: open2 = false } = {}) {
4042
+ const config = await this.#getViteConfig(app);
3379
4043
  const server = await vite.createServer(config);
3380
4044
  await server.listen(4201);
3381
4045
  app.log(`CSR server is running on http://localhost:4201`);
4046
+ if (open2)
4047
+ setTimeout(() => (0, import_open.default)("http://localhost:4201"), 3e3);
3382
4048
  }
3383
4049
  async #prepareIos(app) {
3384
- const isAdded = import_fs12.default.existsSync(`${app.cwdPath}/ios/App/Podfile`);
4050
+ const isAdded = import_fs10.default.existsSync(`${app.cwdPath}/ios/App/Podfile`);
3385
4051
  if (!isAdded) {
3386
4052
  await app.spawn("npx", ["cap", "add", "ios"]);
3387
4053
  await app.spawn("npx", ["@capacitor/assets", "generate"]);
@@ -3416,7 +4082,7 @@ var ApplicationRunner = class {
3416
4082
  await capacitorApp.releaseIos();
3417
4083
  }
3418
4084
  async #prepareAndroid(app) {
3419
- const isAdded = import_fs12.default.existsSync(`${app.cwdPath}/android/app/build.gradle`);
4085
+ const isAdded = import_fs10.default.existsSync(`${app.cwdPath}/android/app/build.gradle`);
3420
4086
  if (!isAdded) {
3421
4087
  await app.spawn("npx", ["cap", "add", "android"]);
3422
4088
  await app.spawn("npx", ["@capacitor/assets", "generate"]);
@@ -3495,24 +4161,23 @@ var ApplicationRunner = class {
3495
4161
  await capacitorApp.save();
3496
4162
  }
3497
4163
  async releaseSource(app, { rebuild, buildNum = 0, environment = "debug", local = true } = {}) {
3498
- const distApp = DistAppExecutor.from(app, app.name);
3499
4164
  const buildRoot = `${app.workspace.workspaceRoot}/releases/builds/${app.name}`;
3500
4165
  const appVersionInfo = import_js_yaml2.default.load(app.readFile("config.yaml"));
3501
4166
  const platformVersion = appVersionInfo.platforms.android.versionName;
3502
- if (import_fs12.default.existsSync(buildRoot))
4167
+ if (import_fs10.default.existsSync(buildRoot))
3503
4168
  await import_promises2.default.rm(buildRoot, { recursive: true, force: true });
3504
4169
  await import_promises2.default.mkdir(buildRoot, { recursive: true });
3505
- if (rebuild || !import_fs12.default.existsSync(`${distApp.cwdPath}/backend`))
3506
- await this.buildBackend(app, distApp);
3507
- if (rebuild || !import_fs12.default.existsSync(`${distApp.cwdPath}/frontend`))
3508
- await this.buildFrontend(app, distApp);
3509
- if (rebuild || !import_fs12.default.existsSync(`${distApp.cwdPath}/csr`))
3510
- await this.buildCsr(app, distApp);
4170
+ if (rebuild || !import_fs10.default.existsSync(`${app.dist.cwdPath}/backend`))
4171
+ await this.buildBackend(app);
4172
+ if (rebuild || !import_fs10.default.existsSync(`${app.dist.cwdPath}/frontend`))
4173
+ await this.buildFrontend(app);
4174
+ if (rebuild || !import_fs10.default.existsSync(`${app.dist.cwdPath}/csr`))
4175
+ await this.buildCsr(app);
3511
4176
  const buildVersion = `${platformVersion}-${buildNum}`;
3512
4177
  const buildPath = `${buildRoot}/${buildVersion}`;
3513
4178
  await import_promises2.default.mkdir(buildPath, { recursive: true });
3514
- await import_promises2.default.cp(`${distApp.cwdPath}/backend`, `${buildPath}/backend`, { recursive: true });
3515
- await import_promises2.default.cp(distApp.cwdPath, buildRoot, { recursive: true });
4179
+ await import_promises2.default.cp(`${app.dist.cwdPath}/backend`, `${buildPath}/backend`, { recursive: true });
4180
+ await import_promises2.default.cp(app.dist.cwdPath, buildRoot, { recursive: true });
3516
4181
  await import_promises2.default.rm(`${buildRoot}/frontend/.next`, { recursive: true, force: true });
3517
4182
  await app.workspace.spawn("tar", [
3518
4183
  "-zcf",
@@ -3521,8 +4186,8 @@ var ApplicationRunner = class {
3521
4186
  buildRoot,
3522
4187
  "./"
3523
4188
  ]);
3524
- if (import_fs12.default.existsSync(`${distApp.cwdPath}/csr`)) {
3525
- await import_promises2.default.cp(`${distApp.cwdPath}/csr`, "./csr", { recursive: true });
4189
+ if (import_fs10.default.existsSync(`${app.dist.cwdPath}/csr`)) {
4190
+ await import_promises2.default.cp(`${app.dist.cwdPath}/csr`, "./csr", { recursive: true });
3526
4191
  await app.workspace.spawn("zip", [
3527
4192
  "-r",
3528
4193
  `${app.workspace.workspaceRoot}/releases/builds/${app.name}-appBuild.zip`,
@@ -3531,7 +4196,7 @@ var ApplicationRunner = class {
3531
4196
  await import_promises2.default.rm("./csr", { recursive: true, force: true });
3532
4197
  }
3533
4198
  const sourceRoot = `${app.workspace.workspaceRoot}/releases/sources/${app.name}`;
3534
- if (import_fs12.default.existsSync(sourceRoot)) {
4199
+ if (import_fs10.default.existsSync(sourceRoot)) {
3535
4200
  const MAX_RETRY = 3;
3536
4201
  for (let i = 0; i < MAX_RETRY; i++) {
3537
4202
  try {
@@ -3541,7 +4206,7 @@ var ApplicationRunner = class {
3541
4206
  }
3542
4207
  }
3543
4208
  await import_promises2.default.mkdir(sourceRoot, { recursive: true });
3544
- await import_promises2.default.cp(distApp.cwdPath, `${sourceRoot}/apps/${app.name}`, { recursive: true });
4209
+ await import_promises2.default.cp(app.dist.cwdPath, `${sourceRoot}/apps/${app.name}`, { recursive: true });
3545
4210
  const libDeps = ["social", "shared", "platform", "util"];
3546
4211
  await Promise.all(
3547
4212
  libDeps.map(
@@ -3551,7 +4216,7 @@ var ApplicationRunner = class {
3551
4216
  await Promise.all(
3552
4217
  [".next", "ios", "android", "public/libs"].map(async (path7) => {
3553
4218
  const targetPath = `${sourceRoot}/apps/${app.name}/${path7}`;
3554
- if (import_fs12.default.existsSync(targetPath))
4219
+ if (import_fs10.default.existsSync(targetPath))
3555
4220
  await import_promises2.default.rm(targetPath, { recursive: true, force: true });
3556
4221
  })
3557
4222
  );
@@ -3579,8 +4244,8 @@ var ApplicationRunner = class {
3579
4244
  []
3580
4245
  )
3581
4246
  ]);
3582
- import_fs12.default.writeFileSync(`${sourceRoot}/tsconfig.json`, JSON.stringify(tsconfig, null, 2));
3583
- import_fs12.default.writeFileSync(
4247
+ import_fs10.default.writeFileSync(`${sourceRoot}/tsconfig.json`, JSON.stringify(tsconfig, null, 2));
4248
+ import_fs10.default.writeFileSync(
3584
4249
  `${sourceRoot}/README.md`,
3585
4250
  `# ${app.name}
3586
4251
  \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.
@@ -3680,9 +4345,14 @@ var ApplicationRunner = class {
3680
4345
  var ApplicationScript = class {
3681
4346
  #runner = new ApplicationRunner();
3682
4347
  libraryScript = new LibraryScript();
3683
- async createApplication(appName, workspace) {
4348
+ async createApplication(appName, workspace, { serve = false } = {}) {
3684
4349
  const app = await this.#runner.createApplication(appName, workspace);
3685
4350
  await this.syncApplication(app);
4351
+ if (serve)
4352
+ await this.serve(app, { open: true });
4353
+ }
4354
+ async removeApplication(app) {
4355
+ await this.#runner.removeApplication(app);
3686
4356
  }
3687
4357
  async scanApplication(app, verbose = false) {
3688
4358
  const scanResult = await this.#runner.scanSync(app);
@@ -3697,64 +4367,78 @@ var ApplicationScript = class {
3697
4367
  for (const libName of scanResult.akanConfig.libs)
3698
4368
  await this.libraryScript.syncLibrary(LibExecutor.from(app, libName), { recursive: false });
3699
4369
  }
3700
- async build(app, distApp = DistAppExecutor.from(app, app.name)) {
3701
- await this.syncApplication(app);
3702
- await Promise.all([this.buildBackend(app, distApp), this.buildFrontend(app, distApp)]);
3703
- }
3704
- async serve(app, distApp = DistAppExecutor.from(app, app.name)) {
3705
- await this.syncApplication(app);
3706
- await Promise.all([this.#runner.serveBackend(app, distApp), this.#runner.serveFrontend(app, distApp)]);
3707
- }
3708
- async buildBackend(app, distApp = DistAppExecutor.from(app, app.name)) {
3709
- await this.syncApplication(app);
3710
- await this.#runner.buildBackend(app, distApp);
3711
- }
3712
- async serveBackend(app, distApp = DistAppExecutor.from(app, app.name)) {
3713
- await this.syncApplication(app);
3714
- await this.#runner.serveBackend(app, distApp);
3715
- }
3716
- async buildFrontend(app, distApp = DistAppExecutor.from(app, app.name)) {
3717
- await this.syncApplication(app);
3718
- await this.#runner.buildFrontend(app, distApp);
3719
- }
3720
- async serveFrontend(app, distApp = DistAppExecutor.from(app, app.name)) {
3721
- await this.syncApplication(app);
3722
- await this.#runner.serveFrontend(app, distApp);
3723
- }
3724
- async buildCsr(app, distApp = DistAppExecutor.from(app, app.name)) {
3725
- await this.syncApplication(app);
3726
- await this.#runner.buildCsr(app, distApp);
3727
- }
3728
- async serveCsr(app, distApp = DistAppExecutor.from(app, app.name)) {
4370
+ async build(app) {
3729
4371
  await this.syncApplication(app);
3730
- await this.#runner.serveCsr(app, distApp);
4372
+ await Promise.all([this.buildBackend(app, { sync: false }), this.buildFrontend(app, { sync: false })]);
3731
4373
  }
3732
- async buildIos(app) {
4374
+ async serve(app, { open: open2 = false } = {}) {
3733
4375
  await this.syncApplication(app);
3734
- await this.#runner.buildCsr(app, DistAppExecutor.from(app, app.name));
4376
+ await Promise.all([this.serveBackend(app, { open: open2, sync: false }), this.serveFrontend(app, { open: open2, sync: false })]);
4377
+ }
4378
+ async buildBackend(app, { sync = true } = {}) {
4379
+ if (sync)
4380
+ await this.syncApplication(app);
4381
+ await this.#runner.buildBackend(app);
4382
+ }
4383
+ async serveBackend(app, { open: open2 = false, sync = true } = {}) {
4384
+ if (sync)
4385
+ await this.syncApplication(app);
4386
+ await this.#runner.serveBackend(app, { open: open2 });
4387
+ }
4388
+ async buildFrontend(app, { sync = true } = {}) {
4389
+ if (sync)
4390
+ await this.syncApplication(app);
4391
+ await this.#runner.buildFrontend(app);
4392
+ }
4393
+ async serveFrontend(app, { open: open2 = false, turbo = false, sync = true } = {}) {
4394
+ if (sync)
4395
+ await this.syncApplication(app);
4396
+ await this.#runner.serveFrontend(app, { open: open2, turbo });
4397
+ }
4398
+ async buildCsr(app, { sync = true } = {}) {
4399
+ if (sync)
4400
+ await this.syncApplication(app);
4401
+ await this.#runner.buildCsr(app);
4402
+ }
4403
+ async serveCsr(app, { open: open2 = false, sync = true } = {}) {
4404
+ if (sync)
4405
+ await this.syncApplication(app);
4406
+ await this.#runner.serveCsr(app, { open: open2 });
4407
+ }
4408
+ async buildIos(app, { sync = true } = {}) {
4409
+ if (sync)
4410
+ await this.syncApplication(app);
3735
4411
  await this.#runner.buildIos(app);
3736
4412
  }
3737
- async serveIos(app, { open: open2 = false, operation = "local" } = {}) {
3738
- await this.syncApplication(app);
3739
- await this.#runner.buildCsr(app, DistAppExecutor.from(app, app.name));
4413
+ async serveIos(app, {
4414
+ open: open2 = false,
4415
+ operation = "local",
4416
+ sync = true
4417
+ } = {}) {
4418
+ if (sync)
4419
+ await this.syncApplication(app);
3740
4420
  await this.#runner.serveIos(app, { open: open2, operation });
3741
4421
  }
3742
- async releaseIos(app) {
3743
- await this.buildCsr(app);
4422
+ async releaseIos(app, { sync = true } = {}) {
4423
+ await this.buildCsr(app, { sync });
3744
4424
  await this.#runner.releaseIos(app);
3745
4425
  }
3746
- async buildAndroid(app) {
3747
- await this.syncApplication(app);
3748
- await this.#runner.buildCsr(app, DistAppExecutor.from(app, app.name));
4426
+ async buildAndroid(app, { sync = true } = {}) {
4427
+ if (sync)
4428
+ await this.syncApplication(app);
3749
4429
  await this.#runner.buildAndroid(app);
3750
4430
  }
3751
- async serveAndroid(app, { open: open2 = false, operation = "local" } = {}) {
3752
- await this.syncApplication(app);
3753
- await this.#runner.buildCsr(app, DistAppExecutor.from(app, app.name));
4431
+ async serveAndroid(app, {
4432
+ open: open2 = false,
4433
+ operation = "local",
4434
+ sync = true
4435
+ } = {}) {
4436
+ if (sync)
4437
+ await this.syncApplication(app);
3754
4438
  await this.#runner.serveAndroid(app, { open: open2, operation });
3755
4439
  }
3756
- async releaseAndroid(app) {
3757
- await this.buildCsr(app);
4440
+ async releaseAndroid(app, { sync = true } = {}) {
4441
+ await this.buildCsr(app, { sync });
3758
4442
  await this.#runner.releaseAndroid(app);
3759
4443
  }
3760
4444
  async dumpDatabase(app, environment) {
@@ -3797,10 +4481,11 @@ var ApplicationScript = class {
3797
4481
  // pkgs/@akanjs/cli/src/application/application.command.ts
3798
4482
  var ApplicationCommand = class {
3799
4483
  applicationScript = new ApplicationScript();
3800
- async createApplication(name, workspace) {
3801
- await this.applicationScript.createApplication(name, workspace);
4484
+ async createApplication(name, serve, workspace) {
4485
+ await this.applicationScript.createApplication(name, workspace, { serve });
3802
4486
  }
3803
- async removeApplication(app, workspace) {
4487
+ async removeApplication(app) {
4488
+ await this.applicationScript.removeApplication(app);
3804
4489
  }
3805
4490
  async scanApplication(app) {
3806
4491
  await this.applicationScript.scanApplication(app, true);
@@ -3823,17 +4508,17 @@ var ApplicationCommand = class {
3823
4508
  async buildAndroid(app) {
3824
4509
  await this.applicationScript.buildAndroid(app);
3825
4510
  }
3826
- async serve(app) {
3827
- await this.applicationScript.serve(app);
4511
+ async serve(app, open2) {
4512
+ await this.applicationScript.serve(app, { open: open2 });
3828
4513
  }
3829
- async serveBackend(app) {
3830
- await this.applicationScript.serveBackend(app);
4514
+ async serveBackend(app, open2) {
4515
+ await this.applicationScript.serveBackend(app, { open: open2 });
3831
4516
  }
3832
- async serveFrontend(app) {
3833
- await this.applicationScript.serveFrontend(app);
4517
+ async serveFrontend(app, open2, turbo) {
4518
+ await this.applicationScript.serveFrontend(app, { open: open2, turbo });
3834
4519
  }
3835
- async serveCsr(app) {
3836
- await this.applicationScript.serveCsr(app);
4520
+ async serveCsr(app, open2) {
4521
+ await this.applicationScript.serveCsr(app, { open: open2 });
3837
4522
  }
3838
4523
  async serveIos(app, open2, release) {
3839
4524
  await this.applicationScript.serveIos(app, { open: open2, operation: release ? "release" : "local" });
@@ -3875,12 +4560,12 @@ var ApplicationCommand = class {
3875
4560
  __decorateClass([
3876
4561
  Target.Public(),
3877
4562
  __decorateParam(0, Option("name", { desc: "name of application" })),
3878
- __decorateParam(1, Workspace())
4563
+ __decorateParam(1, Option("serve", { type: "boolean", desc: "serve application", default: false })),
4564
+ __decorateParam(2, Workspace())
3879
4565
  ], ApplicationCommand.prototype, "createApplication", 1);
3880
4566
  __decorateClass([
3881
4567
  Target.Public(),
3882
- __decorateParam(0, App()),
3883
- __decorateParam(1, Workspace())
4568
+ __decorateParam(0, App())
3884
4569
  ], ApplicationCommand.prototype, "removeApplication", 1);
3885
4570
  __decorateClass([
3886
4571
  Target.Public(),
@@ -3912,31 +4597,36 @@ __decorateClass([
3912
4597
  ], ApplicationCommand.prototype, "buildAndroid", 1);
3913
4598
  __decorateClass([
3914
4599
  Target.Public({ short: true }),
3915
- __decorateParam(0, App())
4600
+ __decorateParam(0, App()),
4601
+ __decorateParam(1, Option("open", { type: "boolean", desc: "open web browser", default: false }))
3916
4602
  ], ApplicationCommand.prototype, "serve", 1);
3917
4603
  __decorateClass([
3918
4604
  Target.Public({ short: true }),
3919
- __decorateParam(0, App())
4605
+ __decorateParam(0, App()),
4606
+ __decorateParam(1, Option("open", { type: "boolean", desc: "open graphql playground", default: false }))
3920
4607
  ], ApplicationCommand.prototype, "serveBackend", 1);
3921
4608
  __decorateClass([
3922
4609
  Target.Public({ short: true }),
3923
- __decorateParam(0, App())
4610
+ __decorateParam(0, App()),
4611
+ __decorateParam(1, Option("open", { type: "boolean", desc: "open web browser", default: false })),
4612
+ __decorateParam(2, Option("turbo", { type: "boolean", desc: "turbo", default: false }))
3924
4613
  ], ApplicationCommand.prototype, "serveFrontend", 1);
3925
4614
  __decorateClass([
3926
4615
  Target.Public({ short: true }),
3927
- __decorateParam(0, App())
4616
+ __decorateParam(0, App()),
4617
+ __decorateParam(1, Option("open", { type: "boolean", desc: "open web browser", default: false }))
3928
4618
  ], ApplicationCommand.prototype, "serveCsr", 1);
3929
4619
  __decorateClass([
3930
4620
  Target.Public({ short: true }),
3931
4621
  __decorateParam(0, App()),
3932
- __decorateParam(1, Option("open", { desc: "open ios simulator", default: false })),
3933
- __decorateParam(2, Option("release", { desc: "release mode", default: false }))
4622
+ __decorateParam(1, Option("open", { type: "boolean", desc: "open ios simulator", default: false })),
4623
+ __decorateParam(2, Option("release", { type: "boolean", desc: "release mode", default: false }))
3934
4624
  ], ApplicationCommand.prototype, "serveIos", 1);
3935
4625
  __decorateClass([
3936
4626
  Target.Public({ short: true }),
3937
4627
  __decorateParam(0, App()),
3938
- __decorateParam(1, Option("open", { desc: "open android simulator", default: false })),
3939
- __decorateParam(2, Option("release", { desc: "release mode", default: false }))
4628
+ __decorateParam(1, Option("open", { type: "boolean", desc: "open android simulator", default: false })),
4629
+ __decorateParam(2, Option("release", { type: "boolean", desc: "release mode", default: false }))
3940
4630
  ], ApplicationCommand.prototype, "serveAndroid", 1);
3941
4631
  __decorateClass([
3942
4632
  Target.Public(),
@@ -3949,10 +4639,10 @@ __decorateClass([
3949
4639
  __decorateClass([
3950
4640
  Target.Public(),
3951
4641
  __decorateParam(0, App()),
3952
- __decorateParam(1, Option("rebuild", { desc: "rebuild", default: false })),
4642
+ __decorateParam(1, Option("rebuild", { type: "boolean", desc: "rebuild", default: false })),
3953
4643
  __decorateParam(2, Option("buildNum", { desc: "build number", default: 0 })),
3954
4644
  __decorateParam(3, Option("environment", { desc: "environment", default: "debug" })),
3955
- __decorateParam(4, Option("local", { desc: "local", default: true }))
4645
+ __decorateParam(4, Option("local", { type: "boolean", desc: "local", default: true }))
3956
4646
  ], ApplicationCommand.prototype, "releaseSource", 1);
3957
4647
  __decorateClass([
3958
4648
  Target.Public(),
@@ -4007,7 +4697,7 @@ ApplicationCommand = __decorateClass([
4007
4697
  // pkgs/@akanjs/cli/src/package/package.runner.ts
4008
4698
  var esbuild2 = __toESM(require("esbuild"));
4009
4699
  var import_esbuild_plugin_d = require("esbuild-plugin-d.ts");
4010
- var import_fs13 = __toESM(require("fs"));
4700
+ var import_fs11 = __toESM(require("fs"));
4011
4701
  var import_promises3 = __toESM(require("fs/promises"));
4012
4702
  var PackageRunner = class {
4013
4703
  async version(workspace) {
@@ -4022,15 +4712,19 @@ var PackageRunner = class {
4022
4712
  dict: { pkgName, PkgName: capitalize(pkgName) }
4023
4713
  });
4024
4714
  }
4715
+ async removePackage(pkg) {
4716
+ await pkg.workspace.exec(`rm -rf pkgs/${pkg.name}`);
4717
+ pkg.log(`Package ${pkg.name} removed`);
4718
+ }
4025
4719
  async scanSync(pkg) {
4026
4720
  const scanResult = await pkg.scan();
4027
4721
  return scanResult;
4028
4722
  }
4029
- async buildPackage(pkg, distPkg) {
4723
+ async buildPackage(pkg) {
4030
4724
  const rootPackageJson = pkg.workspace.readJson("package.json");
4031
4725
  const pkgJson = pkg.readJson("package.json");
4032
- if (import_fs13.default.existsSync(distPkg.cwdPath))
4033
- await pkg.workspace.exec(`rm -rf ${distPkg.cwdPath}`);
4726
+ if (import_fs11.default.existsSync(pkg.dist.cwdPath))
4727
+ await pkg.workspace.exec(`rm -rf ${pkg.dist.cwdPath}`);
4034
4728
  let buildResult;
4035
4729
  if (pkg.name === "@akanjs/config") {
4036
4730
  buildResult = await esbuild2.build({
@@ -4039,7 +4733,7 @@ var PackageRunner = class {
4039
4733
  bundle: false,
4040
4734
  packages: "external",
4041
4735
  format: "cjs",
4042
- outdir: distPkg.cwdPath,
4736
+ outdir: pkg.dist.cwdPath,
4043
4737
  logLevel: "error",
4044
4738
  outExtension: { ".js": pkgJson.type === "module" ? ".cjs" : ".js" },
4045
4739
  plugins: [(0, import_esbuild_plugin_d.dtsPlugin)({ tsconfig: `${pkg.cwdPath}/tsconfig.json` })]
@@ -4050,10 +4744,9 @@ var PackageRunner = class {
4050
4744
  bundle: false,
4051
4745
  packages: "external",
4052
4746
  format: "esm",
4053
- outdir: distPkg.cwdPath,
4747
+ outdir: pkg.dist.cwdPath,
4054
4748
  logLevel: "error",
4055
4749
  outExtension: { ".js": pkgJson.type === "module" ? ".js" : ".mjs" },
4056
- // copy css files
4057
4750
  loader: { ".css": "copy", ".js": "copy" }
4058
4751
  });
4059
4752
  } else if (pkg.name === "@akanjs/cli") {
@@ -4063,7 +4756,7 @@ var PackageRunner = class {
4063
4756
  bundle: true,
4064
4757
  format: "cjs",
4065
4758
  packages: "external",
4066
- outdir: distPkg.cwdPath,
4759
+ outdir: pkg.dist.cwdPath,
4067
4760
  logLevel: "error",
4068
4761
  plugins: [(0, import_esbuild_plugin_d.dtsPlugin)({ tsconfig: `${pkg.cwdPath}/tsconfig.json` })]
4069
4762
  });
@@ -4071,14 +4764,14 @@ var PackageRunner = class {
4071
4764
  write: true,
4072
4765
  entryPoints: [`${pkg.cwdPath}/src/templates/**/*.ts`, `${pkg.cwdPath}/src/templates/**/*.tsx`],
4073
4766
  packages: "external",
4074
- outdir: `${distPkg.cwdPath}/src/templates`,
4767
+ outdir: `${pkg.dist.cwdPath}/src/templates`,
4075
4768
  outbase: `${pkg.cwdPath}/src/templates`,
4076
4769
  format: "cjs",
4077
4770
  platform: "node",
4078
4771
  footer: { js: "module.exports = module.exports.default;" }
4079
4772
  });
4080
4773
  await pkg.workspace.exec(
4081
- `rsync -aq --exclude="*.ts" --exclude="*.tsx" ${pkg.cwdPath}/src/templates/ ${distPkg.cwdPath}/src/templates/`
4774
+ `rsync -aq --exclude="*.ts" --exclude="*.tsx" ${pkg.cwdPath}/src/templates/ ${pkg.dist.cwdPath}/src/templates/`
4082
4775
  );
4083
4776
  } else {
4084
4777
  const platform = [
@@ -4097,7 +4790,7 @@ var PackageRunner = class {
4097
4790
  splitting: false,
4098
4791
  platform,
4099
4792
  format: "cjs",
4100
- outdir: distPkg.cwdPath,
4793
+ outdir: pkg.dist.cwdPath,
4101
4794
  outExtension: { ".js": pkgJson.type === "module" ? ".cjs" : ".js" },
4102
4795
  logLevel: "error",
4103
4796
  plugins: [(0, import_esbuild_plugin_d.dtsPlugin)({ tsconfig: `${pkg.cwdPath}/tsconfig.json` })]
@@ -4110,7 +4803,7 @@ var PackageRunner = class {
4110
4803
  splitting: false,
4111
4804
  platform,
4112
4805
  format: "esm",
4113
- outdir: distPkg.cwdPath,
4806
+ outdir: pkg.dist.cwdPath,
4114
4807
  outExtension: { ".js": pkgJson.type === "module" ? ".js" : ".mjs" },
4115
4808
  logLevel: "error",
4116
4809
  plugins: []
@@ -4133,8 +4826,8 @@ var PackageRunner = class {
4133
4826
  }
4134
4827
  };
4135
4828
  if (buildResult.outputFiles)
4136
- buildResult.outputFiles.map((file) => distPkg.writeFile(file.path, file.text));
4137
- distPkg.writeJson("package.json", pkgPackageJson);
4829
+ buildResult.outputFiles.map((file) => pkg.dist.writeFile(file.path, file.text));
4830
+ pkg.dist.writeJson("package.json", pkgPackageJson);
4138
4831
  pkg.writeJson("package.json", pkgPackageJson);
4139
4832
  }
4140
4833
  };
@@ -4148,20 +4841,23 @@ var PackageScript = class {
4148
4841
  async createPackage(workspace, pkgName) {
4149
4842
  await this.#runner.createPackage(workspace, pkgName);
4150
4843
  }
4844
+ async removePackage(pkg) {
4845
+ await this.#runner.removePackage(pkg);
4846
+ }
4151
4847
  async scanPackage(pkg) {
4152
4848
  const scanResult = await this.#runner.scanSync(pkg);
4153
4849
  pkg.logger.rawLog(JSON.stringify(scanResult, null, 2));
4154
4850
  }
4155
- async buildPackage(pkg, distPkg = DistPkgExecutor.from(pkg.workspace, pkg.name)) {
4156
- await this.#runner.buildPackage(pkg, distPkg);
4851
+ async buildPackage(pkg) {
4852
+ await this.#runner.buildPackage(pkg);
4157
4853
  }
4158
4854
  };
4159
4855
 
4160
4856
  // pkgs/@akanjs/cli/src/cloud/cloud.runner.ts
4161
4857
  var import_prompts7 = require("@inquirer/prompts");
4162
- var import_chalk = __toESM(require("chalk"));
4858
+ var import_chalk2 = __toESM(require("chalk"));
4163
4859
  var import_latest_version = __toESM(require("latest-version"));
4164
- var import_open = __toESM(require("open"));
4860
+ var import_open2 = __toESM(require("open"));
4165
4861
  var QRcode = __toESM(require("qrcode"));
4166
4862
  var import_uuid = require("uuid");
4167
4863
  var CloudRunner = class {
@@ -4169,17 +4865,17 @@ var CloudRunner = class {
4169
4865
  const config = getHostConfig();
4170
4866
  const self = config.auth ? await getSelf(config.auth.token) : null;
4171
4867
  if (self) {
4172
- Logger.rawLog(import_chalk.default.green(`
4868
+ Logger.rawLog(import_chalk2.default.green(`
4173
4869
  \u2713 Already logged in akan cloud as ${self.nickname}
4174
4870
  `));
4175
4871
  return true;
4176
4872
  }
4177
4873
  const remoteId = (0, import_uuid.v4)();
4178
4874
  const signinUrl = `${akanCloudClientUrl}/signin?remoteId=${remoteId}`;
4179
- Logger.rawLog(import_chalk.default.bold(`
4180
- ${import_chalk.default.green("\u27A4")} Authentication Required`));
4181
- Logger.rawLog(import_chalk.default.dim("Please visit or click the following URL:"));
4182
- Logger.rawLog(import_chalk.default.cyan.underline(signinUrl) + "\n");
4875
+ Logger.rawLog(import_chalk2.default.bold(`
4876
+ ${import_chalk2.default.green("\u27A4")} Authentication Required`));
4877
+ Logger.rawLog(import_chalk2.default.dim("Please visit or click the following URL:"));
4878
+ Logger.rawLog(import_chalk2.default.cyan.underline(signinUrl) + "\n");
4183
4879
  try {
4184
4880
  const qrcode = await new Promise((resolve, reject) => {
4185
4881
  QRcode.toString(signinUrl, { type: "terminal", small: true }, (err, data) => {
@@ -4189,12 +4885,12 @@ ${import_chalk.default.green("\u27A4")} Authentication Required`));
4189
4885
  });
4190
4886
  });
4191
4887
  Logger.rawLog(qrcode);
4192
- await (0, import_open.default)(signinUrl);
4193
- Logger.rawLog(import_chalk.default.dim("Opening browser..."));
4888
+ await (0, import_open2.default)(signinUrl);
4889
+ Logger.rawLog(import_chalk2.default.dim("Opening browser..."));
4194
4890
  } catch {
4195
- Logger.rawLog(import_chalk.default.yellow("Could not open browser. Please visit the URL manually."));
4891
+ Logger.rawLog(import_chalk2.default.yellow("Could not open browser. Please visit the URL manually."));
4196
4892
  }
4197
- Logger.rawLog(import_chalk.default.dim("Waiting for authentication..."));
4893
+ Logger.rawLog(import_chalk2.default.dim("Waiting for authentication..."));
4198
4894
  const MAX_RETRY = 300;
4199
4895
  for (let i = 0; i < MAX_RETRY; i++) {
4200
4896
  const res = await fetch(`${akanCloudBackendUrl}/user/getRemoteAuthToken/${remoteId}`);
@@ -4202,30 +4898,38 @@ ${import_chalk.default.green("\u27A4")} Authentication Required`));
4202
4898
  const self2 = jwt ? await getSelf(jwt) : null;
4203
4899
  if (jwt && self2) {
4204
4900
  setHostConfig(akanCloudHost, { auth: { token: jwt, self: self2 } });
4205
- Logger.rawLog(import_chalk.default.green(`\r\u2713 Authentication successful!`));
4206
- Logger.rawLog(import_chalk.default.green.bold(`
4901
+ Logger.rawLog(import_chalk2.default.green(`\r\u2713 Authentication successful!`));
4902
+ Logger.rawLog(import_chalk2.default.green.bold(`
4207
4903
  \u2728 Welcome aboard, ${self2.nickname}!`));
4208
- Logger.rawLog(import_chalk.default.dim("You're now ready to use Akan CLI!\n"));
4904
+ Logger.rawLog(import_chalk2.default.dim("You're now ready to use Akan CLI!\n"));
4209
4905
  return true;
4210
4906
  }
4211
4907
  await sleep(2e3);
4212
4908
  }
4213
- throw new Error(import_chalk.default.red("\u2716 Authentication timed out after 10 minutes. Please try again."));
4909
+ throw new Error(import_chalk2.default.red("\u2716 Authentication timed out after 10 minutes. Please try again."));
4214
4910
  }
4215
4911
  logout() {
4216
4912
  const config = getHostConfig();
4217
4913
  if (config.auth) {
4218
4914
  setHostConfig(akanCloudHost, {});
4219
- Logger.rawLog(import_chalk.default.magenta.bold(`
4915
+ Logger.rawLog(import_chalk2.default.magenta.bold(`
4220
4916
  \u{1F44B} Goodbye, ${config.auth.self.nickname}!`));
4221
- 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"));
4222
- Logger.rawLog(import_chalk.default.cyan("You have been successfully logged out."));
4223
- Logger.rawLog(import_chalk.default.dim("Thank you for using Akan CLI. Come back soon! \u{1F31F}\n"));
4917
+ 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"));
4918
+ Logger.rawLog(import_chalk2.default.cyan("You have been successfully logged out."));
4919
+ Logger.rawLog(import_chalk2.default.dim("Thank you for using Akan CLI. Come back soon! \u{1F31F}\n"));
4224
4920
  } else {
4225
- Logger.rawLog(import_chalk.default.yellow.bold("\n\u26A0\uFE0F No active session found"));
4226
- Logger.rawLog(import_chalk.default.dim("You were not logged in to begin with\n"));
4921
+ Logger.rawLog(import_chalk2.default.yellow.bold("\n\u26A0\uFE0F No active session found"));
4922
+ Logger.rawLog(import_chalk2.default.dim("You were not logged in to begin with\n"));
4227
4923
  }
4228
4924
  }
4925
+ async setLlm() {
4926
+ await AiSession.init({ useExisting: true });
4927
+ Logger.rawLog(import_chalk2.default.green("LLM model set successfully"));
4928
+ }
4929
+ resetLlm() {
4930
+ AiSession.setLlmConfig(null);
4931
+ Logger.rawLog(import_chalk2.default.green("LLM model reset successfully"));
4932
+ }
4229
4933
  async getAkanPkgs(workspace) {
4230
4934
  const pkgs = await workspace.getPkgs();
4231
4935
  const akanPkgs = pkgs.filter((pkg) => pkg.startsWith("@akanjs/"));
@@ -4247,20 +4951,7 @@ ${import_chalk.default.green("\u27A4")} Authentication Required`));
4247
4951
  const newPackageJsonStr = JSON.stringify({ ...packageJson, version: nextVersion }, null, 2);
4248
4952
  workspace.writeFile(`pkgs/${library}/package.json`, newPackageJsonStr);
4249
4953
  const distPackageJson = workspace.readJson(`dist/pkgs/${library}/package.json`);
4250
- const newDistPackageJson = {
4251
- ...distPackageJson,
4252
- // ...(distPackageJson.dependencies
4253
- // ? {
4254
- // dependencies: Object.fromEntries(
4255
- // Object.entries(distPackageJson.dependencies).map(([key, value]) => [
4256
- // key,
4257
- // value.startsWith("^") ? value : `^${value}`,
4258
- // ])
4259
- // ),
4260
- // }
4261
- // : {}),
4262
- version: nextVersion
4263
- };
4954
+ const newDistPackageJson = { ...distPackageJson, version: nextVersion };
4264
4955
  workspace.writeJson(`dist/pkgs/${library}/package.json`, newDistPackageJson);
4265
4956
  }
4266
4957
  const isDeployConfirmed = await (0, import_prompts7.confirm)({
@@ -4291,6 +4982,17 @@ var CloudScript = class {
4291
4982
  logout() {
4292
4983
  this.#runner.logout();
4293
4984
  }
4985
+ async setLlm() {
4986
+ await this.#runner.setLlm();
4987
+ }
4988
+ resetLlm() {
4989
+ this.#runner.resetLlm();
4990
+ }
4991
+ async ask(question) {
4992
+ await AiSession.init();
4993
+ const session = new AiSession();
4994
+ await session.ask(question);
4995
+ }
4294
4996
  async deployAkan(workspace) {
4295
4997
  const akanPkgs = await this.#runner.getAkanPkgs(workspace);
4296
4998
  await Promise.all(
@@ -4309,6 +5011,15 @@ var CloudCommand = class {
4309
5011
  logout() {
4310
5012
  this.cloudScript.logout();
4311
5013
  }
5014
+ async setLlm() {
5015
+ await this.cloudScript.setLlm();
5016
+ }
5017
+ resetLlm() {
5018
+ this.cloudScript.resetLlm();
5019
+ }
5020
+ async ask(question) {
5021
+ await this.cloudScript.ask(question);
5022
+ }
4312
5023
  async deployAkan(workspace) {
4313
5024
  await this.cloudScript.deployAkan(workspace);
4314
5025
  }
@@ -4319,6 +5030,16 @@ __decorateClass([
4319
5030
  __decorateClass([
4320
5031
  Target.Public()
4321
5032
  ], CloudCommand.prototype, "logout", 1);
5033
+ __decorateClass([
5034
+ Target.Public()
5035
+ ], CloudCommand.prototype, "setLlm", 1);
5036
+ __decorateClass([
5037
+ Target.Public()
5038
+ ], CloudCommand.prototype, "resetLlm", 1);
5039
+ __decorateClass([
5040
+ Target.Public(),
5041
+ __decorateParam(0, Option("question", { ask: "question to ask" }))
5042
+ ], CloudCommand.prototype, "ask", 1);
4322
5043
  __decorateClass([
4323
5044
  Target.Public({ devOnly: true }),
4324
5045
  __decorateParam(0, Workspace())
@@ -4331,8 +5052,10 @@ CloudCommand = __decorateClass([
4331
5052
  var LibraryCommand = class {
4332
5053
  libraryScript = new LibraryScript();
4333
5054
  async createLibrary(name, workspace) {
5055
+ await this.libraryScript.createLibrary(name, workspace);
4334
5056
  }
4335
- async removeLibrary(lib, workspace) {
5057
+ async removeLibrary(lib) {
5058
+ await this.libraryScript.removeLibrary(lib);
4336
5059
  }
4337
5060
  async scanLibrary(lib) {
4338
5061
  await this.libraryScript.scanLibrary(lib, true);
@@ -4356,8 +5079,7 @@ __decorateClass([
4356
5079
  ], LibraryCommand.prototype, "createLibrary", 1);
4357
5080
  __decorateClass([
4358
5081
  Target.Public(),
4359
- __decorateParam(0, Lib()),
4360
- __decorateParam(1, Workspace())
5082
+ __decorateParam(0, Lib())
4361
5083
  ], LibraryCommand.prototype, "removeLibrary", 1);
4362
5084
  __decorateClass([
4363
5085
  Target.Public(),
@@ -4386,8 +5108,11 @@ LibraryCommand = __decorateClass([
4386
5108
  Commands()
4387
5109
  ], LibraryCommand);
4388
5110
 
5111
+ // pkgs/@akanjs/cli/src/module/module.script.ts
5112
+ var import_prompts8 = require("@inquirer/prompts");
5113
+ var import_fs12 = __toESM(require("fs"));
5114
+
4389
5115
  // pkgs/@akanjs/cli/src/module/module.runner.ts
4390
- var import_fs14 = __toESM(require("fs"));
4391
5116
  var ModuleRunner = class {
4392
5117
  async createModule(workspace, sysType, sysName, moduleName, description) {
4393
5118
  }
@@ -4465,56 +5190,64 @@ var ModuleRunner = class {
4465
5190
  }
4466
5191
  };
4467
5192
  }
4468
- async createUnit(sys2, modelName) {
4469
- const modelFileData = getModelFileData(sys2.cwdPath, modelName);
4470
- const { paths } = getRelatedCnsts(modelFileData.constantFilePath);
4471
- const names = { model: modelName, Model: capitalize(modelName), LightModel: `Light${capitalize(modelName)}` };
4472
- const prompt = `
4473
-
4474
- \uB108\uB294 React, Typescript, TailwindCSS\uB97C \uAE30\uBC18\uC73C\uB85C \uCF54\uB529\uD558\uB294 \uD504\uB860\uD2B8\uC5D4\uB4DC \uAC1C\uBC1C\uC790\uC57C.
4475
- ${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.
4476
-
4477
- \`\`\`
4478
- ${modelFileData.unitFileStr}
4479
- \`\`\`
4480
-
4481
- ${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.
4482
- \`\`\`
4483
- ${modelFileData.constantFileStr}
4484
- \`\`\`
4485
-
4486
- \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.
4487
- ${paths ? new Array(paths.size).fill(0).map((_, index) => {
4488
- const key = Array.from(paths.keys())[index];
4489
- const filePath = paths.get(key)?.filePath;
4490
- if (!filePath)
4491
- throw new Error("filePath is undefined");
4492
- return `${key}
4493
- \`\`\`${import_fs14.default.readFileSync(filePath, "utf8")}\`\`\`\`
4494
-
4495
- `;
4496
- }) : ""}
4497
-
4498
- \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.
4499
- \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.
4500
- \uADF8\uB9AC\uACE0 optional\uD55C \uD544\uB4DC\uB294 field && <div>... \uAC00 \uC544\uB2CC, field ? <div>... : null \uD615\uD0DC\uB85C \uC791\uC131\uD574\uC918.
4501
- 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.
4502
- \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.
4503
- \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.
4504
-
4505
- ${names.Model}.Unit.Card\uC758 \uB9AC\uC561\uD2B8 \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uB514\uC790\uC778\uD574\uC11C \uC791\uC131\uD574\uC918.
4506
- `;
4507
- try {
4508
- import_fs14.default.writeFileSync("./local/prompt.txt", prompt);
4509
- const { content } = await streamAi(prompt, (chunk) => {
4510
- process.stdout.write(chunk);
4511
- });
4512
- import_fs14.default.writeFileSync("./local/result.txt", content);
4513
- } catch (error) {
4514
- }
4515
- }
4516
- async createView(sys2, modelName) {
4517
- }
5193
+ // async createUnit(sys: App | Lib, modelName: string) {
5194
+ // const modelFileData = getModelFileData(sys.cwdPath, modelName);
5195
+ // const { paths } = getRelatedCnsts(modelFileData.constantFilePath);
5196
+ // const names = { model: modelName, Model: capitalize(modelName), LightModel: `Light${capitalize(modelName)}` };
5197
+ // const prompt = `
5198
+ // 너는 React, Typescript, TailwindCSS를 기반으로 코딩하는 프론트엔드 개발자야.
5199
+ // ${names.Model}이라는 도메인에 대해서 ${names.LightModel} 스키마를 대상으로 react component를 디자인하려고 해. 아래는 현재 보일러플레이트 형태의 컴포넌트야.
5200
+ // \`\`\`
5201
+ // ${modelFileData.unitFileStr}
5202
+ // \`\`\`
5203
+ // ${names.LightModel}은 다음과 같이 ${names.Model} 스키마에서 일부 필드를 추출해서 lightweight fetch된 형태로 설계되어있어.
5204
+ // \`\`\`
5205
+ // ${modelFileData.constantFileStr}
5206
+ // \`\`\`
5207
+ // 아래는 현재 스키마와 연관된 스키마 파일들이야. 스키마 파일들의 코드들을 보고 서로 어떻게 연계 되어있는지 이해하도록 해.
5208
+ // ${
5209
+ // paths
5210
+ // ? new Array(paths.size).fill(0).map((_, index) => {
5211
+ // //순서대로 paths key 추출
5212
+ // const key = Array.from(paths.keys())[index];
5213
+ // const filePath = paths.get(key)?.filePath;
5214
+ // if (!filePath) throw new Error("filePath is undefined");
5215
+ // return `${key}\n\`\`\`${fs.readFileSync(filePath, "utf8")}\`\`\`\`\n\n`;
5216
+ // })
5217
+ // : ""
5218
+ // }
5219
+ // 추가로, 만약에 아이콘 사용이 필요하면 react-icons/bi 라이브러리에서 사용해줘.
5220
+ // 또, 색상을 사용하려고 하면 하드코딩된 색상(bg-red)이 아닌 테마 색상(bg-primary)을 사용해서 작성해줘.
5221
+ // 그리고 optional한 필드는 field && <div>... 가 아닌, field ? <div>... : null 형태로 작성해줘.
5222
+ // css라이브러리는 DaisyUI를 기반으로 작성해주는데, btn, input, badge와 같은 단순한 기본 css는 사용해도 괜찮아. 그런데 card, hero같이 복잡한 컴포넌트는 사용하면 안돼.
5223
+ // 조건부 className이 필요한 경우에는 clsx 라이브러리를 사용해서 작성해야해.
5224
+ // 모델에 대해서 object destructuring은 하지말고 ${modelName}.field 형태로 접근하게 코드를 작성해야해.
5225
+ // ${names.Model}.Unit.Card의 리액트 컴포넌트를 디자인해서 작성해줘.
5226
+ // `;
5227
+ // try {
5228
+ // fs.writeFileSync("./local/prompt.txt", prompt);
5229
+ // const { content } = await streamAi(prompt, (chunk) => {
5230
+ // process.stdout.write(chunk);
5231
+ // });
5232
+ // fs.writeFileSync("./local/result.txt", content);
5233
+ // } catch (error) {
5234
+ // // console.error("Application error:", error);
5235
+ // }
5236
+ // }
5237
+ // async createView(sys: App | Lib, modelName: string) {
5238
+ // const modelFileData = getModelFileData(sys.cwdPath, modelName);
5239
+ // // const modelFileData = getModelFileData(sys.cwdPath, modelName);
5240
+ // // const { paths } = getRelatedCnsts(modelFileData.constantFilePath);
5241
+ // // const names = { model: modelName, Model: capitalize(modelName), LightModel: `Light${capitalize(modelName)}` };
5242
+ // // const prompt = prompt.requestView({
5243
+ // // sysName: sys.name,
5244
+ // // modelName,
5245
+ // // modelDesc: modelFileData.modelDesc,
5246
+ // // modelSchemaDesign: modelFileData.modelSchemaDesign,
5247
+ // // boilerplate: modelFileData.viewFileStr,
5248
+ // // paths,
5249
+ // // });
5250
+ // }
4518
5251
  };
4519
5252
 
4520
5253
  // pkgs/@akanjs/cli/src/module/module.script.ts
@@ -4559,38 +5292,67 @@ var ModuleScript = class {
4559
5292
  }
4560
5293
  async createTest(workspace, name) {
4561
5294
  }
4562
- async createUnit(workspace, type, appOrLibName, modelName) {
4563
- const sys2 = type === "app" ? AppExecutor.from(workspace, appOrLibName) : LibExecutor.from(workspace, appOrLibName);
4564
- await this.#runner.createUnit(sys2, modelName);
5295
+ async createUnit(sys2) {
5296
+ const libs = await sys2.getModules();
5297
+ const unitExampleFiles = await sys2.getUnitsSourceCode();
5298
+ const lib = await (0, import_prompts8.select)({
5299
+ message: "Select the lib",
5300
+ choices: libs
5301
+ }).catch((e) => {
5302
+ Logger.error("canceled");
5303
+ return null;
5304
+ });
5305
+ if (!lib)
5306
+ return;
5307
+ const name = lib.split("/").pop();
5308
+ if (!name)
5309
+ return;
5310
+ const Name = capitalize(name);
5311
+ const relatedCnsts = getRelatedCnsts(`${sys2.cwdPath}/lib/${name}/${name}.constant.ts`);
5312
+ const constant = import_fs12.default.readFileSync(`${sys2.cwdPath}/lib/${name}/${name}.constant.ts`, "utf-8");
5313
+ const session = new AiSession();
5314
+ const promptRst = requestView({
5315
+ sysName: sys2.name,
5316
+ modelName: name,
5317
+ ModelName: Name,
5318
+ constant,
5319
+ properties: relatedCnsts.map((r) => ({ key: r.key, source: r.source })),
5320
+ exampleFiles: randomPicks(unitExampleFiles, Math.min(10, unitExampleFiles.length))
5321
+ });
5322
+ const content = await session.editTypescript(promptRst);
5323
+ import_fs12.default.writeFileSync(`${sys2.cwdPath}/prompt.txt`, promptRst);
5324
+ import_fs12.default.writeFileSync(`${sys2.cwdPath}/result.txt`, content);
4565
5325
  }
4566
5326
  async createView(sys2) {
4567
- const [appNames, libNames] = await sys2.workspace.getSyss();
4568
- const viewExampleFiles = [
4569
- ...(await Promise.all(
4570
- appNames.map(async (appName) => {
4571
- const app = AppExecutor.from(sys2.workspace, appName);
4572
- const viewModules = await app.getViewModules();
4573
- return await Promise.all(
4574
- viewModules.map((viewModule) => ({
4575
- path: `${appName}/${viewModule}/${viewModule}.View.tsx`,
4576
- content: app.readFile(`lib/${viewModule}/${viewModule}.View.tsx`)
4577
- }))
4578
- );
4579
- })
4580
- )).flat(),
4581
- ...(await Promise.all(
4582
- libNames.map(async (libName) => {
4583
- const lib = LibExecutor.from(sys2.workspace, libName);
4584
- const viewModules = await lib.getViewModules();
4585
- return await Promise.all(
4586
- viewModules.map((viewModule) => ({
4587
- path: `${libName}/${viewModule}/${viewModule}.View.tsx`,
4588
- content: lib.readFile(`lib/${viewModule}/${viewModule}.View.tsx`)
4589
- }))
4590
- );
4591
- })
4592
- )).flat()
4593
- ];
5327
+ const libs = await sys2.getModules();
5328
+ const lib = await (0, import_prompts8.select)({
5329
+ message: "Select the lib",
5330
+ choices: libs
5331
+ }).catch((e) => {
5332
+ Logger.error("canceled");
5333
+ return null;
5334
+ });
5335
+ if (!lib)
5336
+ return;
5337
+ const name = lib.split("/").pop();
5338
+ if (!name)
5339
+ return;
5340
+ const viewExampleFiles = (await sys2.getViewsSourceCode()).filter((f) => f.filepath.includes(`${name}.View.tsx`));
5341
+ const Name = capitalize(name);
5342
+ const relatedCnsts = getRelatedCnsts(`${sys2.cwdPath}/lib/${name}/${name}.constant.ts`);
5343
+ const constant = import_fs12.default.readFileSync(`${sys2.cwdPath}/lib/${name}/${name}.constant.ts`, "utf-8");
5344
+ const session = new AiSession();
5345
+ const promptRst = requestView({
5346
+ sysName: sys2.name,
5347
+ modelName: name,
5348
+ ModelName: Name,
5349
+ constant,
5350
+ properties: relatedCnsts.map((r) => ({ key: r.key, source: r.source })),
5351
+ exampleFiles: randomPicks(viewExampleFiles, Math.min(20, viewExampleFiles.length))
5352
+ });
5353
+ const content = await session.editTypescript(promptRst);
5354
+ import_fs12.default.writeFileSync(`${sys2.cwdPath}/prompt.txt`, promptRst);
5355
+ import_fs12.default.writeFileSync(`${sys2.cwdPath}/result.txt`, content);
4594
5356
  }
4595
5357
  };
4596
5358
 
@@ -4673,7 +5435,8 @@ var PackageCommand = class {
4673
5435
  async createPackage(name, workspace) {
4674
5436
  await this.packageScript.createPackage(workspace, name);
4675
5437
  }
4676
- async removePackage(name, workspace) {
5438
+ async removePackage(pkg) {
5439
+ await this.packageScript.removePackage(pkg);
4677
5440
  }
4678
5441
  async scanPackage(pkg) {
4679
5442
  await this.packageScript.scanPackage(pkg);
@@ -4693,8 +5456,7 @@ __decorateClass([
4693
5456
  ], PackageCommand.prototype, "createPackage", 1);
4694
5457
  __decorateClass([
4695
5458
  Target.Public(),
4696
- __decorateParam(0, Option("name", { desc: "name of package" })),
4697
- __decorateParam(1, Workspace())
5459
+ __decorateParam(0, Pkg())
4698
5460
  ], PackageCommand.prototype, "removePackage", 1);
4699
5461
  __decorateClass([
4700
5462
  Target.Public(),
@@ -4708,13 +5470,13 @@ PackageCommand = __decorateClass([
4708
5470
  Commands()
4709
5471
  ], PackageCommand);
4710
5472
 
4711
- // pkgs/@akanjs/cli/src/package/page/page.runner.ts
5473
+ // pkgs/@akanjs/cli/src/page/page.runner.ts
4712
5474
  var PageRunner = class {
4713
5475
  async createPage(app, name) {
4714
5476
  }
4715
5477
  };
4716
5478
 
4717
- // pkgs/@akanjs/cli/src/package/page/page.script.ts
5479
+ // pkgs/@akanjs/cli/src/page/page.script.ts
4718
5480
  var PageScript = class {
4719
5481
  #runner = new PageRunner();
4720
5482
  async createPage(app, name) {
@@ -4722,7 +5484,7 @@ var PageScript = class {
4722
5484
  }
4723
5485
  };
4724
5486
 
4725
- // pkgs/@akanjs/cli/src/package/page/page.command.ts
5487
+ // pkgs/@akanjs/cli/src/page/page.command.ts
4726
5488
  var PageCommand = class {
4727
5489
  pageScript = new PageScript();
4728
5490
  async createPage(app, name) {
@@ -4839,7 +5601,7 @@ var WorkspaceScript = class {
4839
5601
  };
4840
5602
  workspace.writeFile("package.json", packageJson);
4841
5603
  workspace.log("Installing dependencies...");
4842
- await workspace.spawn("pnpm", ["i"]);
5604
+ await workspace.spawn("pnpm", ["install", "--reporter=silent"]);
4843
5605
  workspace.log("Initializing git repository and commit...");
4844
5606
  await workspace.commit("Initial commit", { init: true });
4845
5607
  await this.libraryScript.installLibrary(workspace, "util");
@@ -4864,8 +5626,8 @@ var WorkspaceCommand = class {
4864
5626
  };
4865
5627
  __decorateClass([
4866
5628
  Target.Public(),
4867
- __decorateParam(0, Option("name", { desc: "name of workspace" })),
4868
- __decorateParam(1, Option("app", { desc: "application name" })),
5629
+ __decorateParam(0, Option("name", { desc: "what is the name of your organization?" })),
5630
+ __decorateParam(1, Option("app", { desc: "describe your first application to create." })),
4869
5631
  __decorateParam(2, Option("dir", { desc: "directory of workspace", default: process.env.USE_AKANJS_PKGS === "true" ? "local" : "." }))
4870
5632
  ], WorkspaceCommand.prototype, "createWorkspace", 1);
4871
5633
  __decorateClass([
@@ -4887,7 +5649,6 @@ void runCommands(
4887
5649
  PageCommand,
4888
5650
  CloudCommand
4889
5651
  );
4890
- //!Field.Prop 거르기가 빡세네.
4891
5652
  //! Temp
4892
5653
  //! zip 명령어는 압축시 폴더 경로를 무시하는 게 안됨
4893
5654
  //! 두 가지 방법이 있음
@@ -4896,3 +5657,4 @@ void runCommands(
4896
5657
  //! execSync를 가져오기 싫으니 일단 2번 방법으로 해보자
4897
5658
  //! add path in tsconfig.json
4898
5659
  //! Temporary fix for barrel library
5660
+ //! 파일을 {name}.View.tsx에 저장.