@akanjs/cli 0.0.58 → 0.0.59

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 (80) hide show
  1. package/index.js +679 -91
  2. package/package.json +3 -4
  3. package/pkgs/@akanjs/cli/src/application/application.runner.d.ts +1 -0
  4. package/pkgs/@akanjs/cli/src/application/application.script.d.ts +2 -1
  5. package/pkgs/@akanjs/cli/src/library/library.command.d.ts +3 -1
  6. package/pkgs/@akanjs/cli/src/library/library.runner.d.ts +4 -1
  7. package/pkgs/@akanjs/cli/src/library/library.script.d.ts +4 -1
  8. package/pkgs/@akanjs/cli/src/module/module.command.d.ts +1 -1
  9. package/pkgs/@akanjs/cli/src/module/module.prompt.d.ts +1 -1
  10. package/pkgs/@akanjs/cli/src/module/module.script.d.ts +1 -1
  11. package/pkgs/@akanjs/cli/src/workspace/workspace.command.d.ts +1 -2
  12. package/pkgs/@akanjs/cli/src/workspace/workspace.runner.d.ts +0 -1
  13. package/pkgs/@akanjs/cli/src/workspace/workspace.script.d.ts +4 -1
  14. package/pkgs/@akanjs/devkit/src/aiEditor.d.ts +17 -0
  15. package/pkgs/@akanjs/devkit/src/executors.d.ts +26 -0
  16. package/pkgs/@akanjs/devkit/src/index.d.ts +1 -0
  17. package/pkgs/@akanjs/devkit/src/streamAi.d.ts +1 -1
  18. package/src/templates/app/akan.config.js +35 -0
  19. package/src/templates/app/env/env.client.debug.ts.template +7 -0
  20. package/src/templates/app/env/env.client.develop.ts.template +7 -0
  21. package/src/templates/app/env/env.client.main.ts.template +7 -0
  22. package/src/templates/app/env/env.client.testing.ts.template +7 -0
  23. package/src/templates/app/env/env.client.type.js +1 -1
  24. package/src/templates/app/env/env.server.debug.ts.template +15 -0
  25. package/src/templates/app/env/env.server.develop.ts.template +15 -0
  26. package/src/templates/app/env/env.server.main.ts.template +15 -0
  27. package/src/templates/app/env/env.server.testing.ts.template +7 -0
  28. package/src/templates/app/tsconfig.json.template +6 -6
  29. package/src/templates/workspaceRoot/.gitignore.template +117 -0
  30. package/src/templates/{workplaceRoot/eslint.config.js.template → workspaceRoot/eslint.config.ts.template} +14 -19
  31. package/src/templates/app/akan.config.ts.template +0 -5
  32. package/src/templates/workplaceRoot/.gitignore.template +0 -195
  33. /package/src/templates/app/app/[lang]/(__appName__)/(public)/forgotpassword/{page.js → page.jsx} +0 -0
  34. /package/src/templates/app/app/[lang]/(__appName__)/(public)/{page.js → page.jsx} +0 -0
  35. /package/src/templates/app/app/[lang]/(__appName__)/(public)/privacy/{page.js → page.jsx} +0 -0
  36. /package/src/templates/app/app/[lang]/(__appName__)/(public)/signin/{page.js → page.jsx} +0 -0
  37. /package/src/templates/app/app/[lang]/(__appName__)/(public)/termsofservice/{page.js → page.jsx} +0 -0
  38. /package/src/templates/app/app/[lang]/(__appName__)/(user)/{layout.js → layout.jsx} +0 -0
  39. /package/src/templates/app/app/[lang]/(__appName__)/(user)/self/{page.js → page.jsx} +0 -0
  40. /package/src/templates/app/app/[lang]/(__appName__)/{layout.js → layout.jsx} +0 -0
  41. /package/src/templates/app/app/[lang]/admin/{layout.js → layout.jsx} +0 -0
  42. /package/src/templates/app/app/[lang]/admin/{page.js → page.jsx} +0 -0
  43. /package/src/templates/app/app/{csr.js → csr.jsx} +0 -0
  44. /package/src/templates/app/app/{layout.js → layout.jsx} +0 -0
  45. /package/src/templates/app/lib/setting/{Setting.Template.js → Setting.Template.jsx} +0 -0
  46. /package/src/templates/app/lib/setting/{Setting.Unit.js → Setting.Unit.jsx} +0 -0
  47. /package/src/templates/app/lib/setting/{Setting.Util.js → Setting.Util.jsx} +0 -0
  48. /package/src/templates/app/lib/setting/{Setting.View.js → Setting.View.jsx} +0 -0
  49. /package/src/templates/app/lib/setting/{Setting.Zone.js → Setting.Zone.jsx} +0 -0
  50. /package/src/templates/app/lib/setting/{index.js → index.jsx} +0 -0
  51. /package/src/templates/app/lib/summary/{Summary.Template.js → Summary.Template.jsx} +0 -0
  52. /package/src/templates/app/lib/summary/{Summary.Unit.js → Summary.Unit.jsx} +0 -0
  53. /package/src/templates/app/lib/summary/{Summary.Util.js → Summary.Util.jsx} +0 -0
  54. /package/src/templates/app/lib/summary/{Summary.View.js → Summary.View.jsx} +0 -0
  55. /package/src/templates/app/lib/summary/{Summary.Zone.js → Summary.Zone.jsx} +0 -0
  56. /package/src/templates/app/lib/summary/{index.js → index.jsx} +0 -0
  57. /package/src/templates/app/lib/user/{User.Template.js → User.Template.jsx} +0 -0
  58. /package/src/templates/app/lib/user/{User.Unit.js → User.Unit.jsx} +0 -0
  59. /package/src/templates/app/lib/user/{User.Util.js → User.Util.jsx} +0 -0
  60. /package/src/templates/app/lib/user/{User.View.js → User.View.jsx} +0 -0
  61. /package/src/templates/app/lib/user/{User.Zone.js → User.Zone.jsx} +0 -0
  62. /package/src/templates/app/lib/user/{index.js → index.jsx} +0 -0
  63. /package/src/templates/app/ui/{Footer.js → Footer.jsx} +0 -0
  64. /package/src/templates/app/ui/{MainHeader.js → MainHeader.jsx} +0 -0
  65. /package/src/templates/crudPages/[__model__Id]/edit/{page.js → page.jsx} +0 -0
  66. /package/src/templates/crudPages/[__model__Id]/{page.js → page.jsx} +0 -0
  67. /package/src/templates/crudPages/new/{page.js → page.jsx} +0 -0
  68. /package/src/templates/crudPages/{page.js → page.jsx} +0 -0
  69. /package/src/templates/module/{__Model__.Template.js → __Model__.Template.jsx} +0 -0
  70. /package/src/templates/module/{__Model__.Unit.js → __Model__.Unit.jsx} +0 -0
  71. /package/src/templates/module/{__Model__.Util.js → __Model__.Util.jsx} +0 -0
  72. /package/src/templates/module/{__Model__.View.js → __Model__.View.jsx} +0 -0
  73. /package/src/templates/module/{__Model__.Zone.js → __Model__.Zone.jsx} +0 -0
  74. /package/src/templates/module/{index.js → index.jsx} +0 -0
  75. /package/src/templates/{workplaceRoot → workspaceRoot}/.env.template +0 -0
  76. /package/src/templates/{workplaceRoot → workspaceRoot}/.prettierignore.template +0 -0
  77. /package/src/templates/{workplaceRoot → workspaceRoot}/.prettierrc.json.template +0 -0
  78. /package/src/templates/{workplaceRoot → workspaceRoot}/.swcrc.template +0 -0
  79. /package/src/templates/{workplaceRoot → workspaceRoot}/README.md.template +0 -0
  80. /package/src/templates/{workplaceRoot → workspaceRoot}/tsconfig.json.template +0 -0
package/index.js CHANGED
@@ -283,7 +283,9 @@ var import_fs5 = __toESM(require("fs"), 1);
283
283
  var import_prompts2 = require("@langchain/core/prompts");
284
284
  var import_runnables = require("@langchain/core/runnables");
285
285
  var import_openai = require("@langchain/openai");
286
- var streamAi = async (question, callback) => {
286
+ var streamAi = async (question, callback = (chunk) => {
287
+ process.stdout.write(chunk);
288
+ }) => {
287
289
  const createStreamingModel = (apiKey = process.env.DEEPSEEK_API_KEY) => {
288
290
  if (!apiKey)
289
291
  throw new Error(`process.env.DEEPSEEK_API_KEY is not set`);
@@ -326,6 +328,21 @@ var import_dayjs3 = __toESM(require("dayjs"));
326
328
  var import_customParseFormat = __toESM(require("dayjs/plugin/customParseFormat"));
327
329
  import_dayjs3.default.extend(import_customParseFormat.default);
328
330
 
331
+ // pkgs/@akanjs/common/randomPicks.ts
332
+ var randomPicks = (arr, count = 1, allowDuplicate = false) => {
333
+ if (!allowDuplicate && arr.length <= count)
334
+ return arr;
335
+ const idxs = [];
336
+ let pickIdx;
337
+ for (let i = 0; i < count; i++) {
338
+ do {
339
+ pickIdx = Math.floor(Math.random() * arr.length);
340
+ } while (!allowDuplicate && idxs.includes(pickIdx));
341
+ idxs.push(pickIdx);
342
+ }
343
+ return idxs.map((idx) => arr[idx]);
344
+ };
345
+
329
346
  // pkgs/@akanjs/common/pluralize.ts
330
347
  var import_pluralize = __toESM(require("pluralize"));
331
348
 
@@ -470,7 +487,7 @@ var Logger = class _Logger {
470
487
  if (typeof window === "undefined" && method !== "console" && global.process)
471
488
  global.process.stdout.write(msg);
472
489
  else
473
- console.log(msg);
490
+ console.log(msg.trim());
474
491
  }
475
492
  };
476
493
 
@@ -1005,6 +1022,11 @@ var Executor = class {
1005
1022
  this.writeFile(filePath, JSON.stringify(content, null, 2));
1006
1023
  return this;
1007
1024
  }
1025
+ getLocalFile(filePath) {
1026
+ const filepath = import_path3.default.isAbsolute(filePath) ? filePath : filePath.replace(this.cwdPath, "");
1027
+ const content = this.readFile(filepath);
1028
+ return { filepath, content };
1029
+ }
1008
1030
  readFile(filePath) {
1009
1031
  const readPath = import_path3.default.isAbsolute(filePath) ? filePath : `${this.cwdPath}/${filePath}`;
1010
1032
  return import_fs7.default.readFileSync(readPath, "utf8");
@@ -1043,7 +1065,7 @@ var Executor = class {
1043
1065
  targetPath,
1044
1066
  scanResult
1045
1067
  }, dict = {}) {
1046
- if (targetPath.endsWith(".js")) {
1068
+ if (targetPath.endsWith(".js") || targetPath.endsWith(".jsx")) {
1047
1069
  const getContent = await import(templatePath);
1048
1070
  const content = getContent.default(scanResult ?? null, dict);
1049
1071
  const convertedTargetPath = Object.entries(dict).reduce(
@@ -1061,7 +1083,7 @@ var Executor = class {
1061
1083
  targetPath.slice(0, -9)
1062
1084
  );
1063
1085
  const convertedContent = Object.entries(dict).reduce(
1064
- (content2, [key, value]) => content2.replace(new RegExp(`<%= ${key} %>`, "g"), value),
1086
+ (data, [key, value]) => data.replace(new RegExp(`<%= ${key} %>`, "g"), value),
1065
1087
  content
1066
1088
  );
1067
1089
  this.logger.verbose(`Apply template ${templatePath} to ${convertedTargetPath}`);
@@ -1159,6 +1181,21 @@ var WorkspaceExecutor = class _WorkspaceExecutor extends Executor {
1159
1181
  async getPkgs() {
1160
1182
  return await this.#getDirHasFile(`${this.workspaceRoot}/pkgs`, "package.json");
1161
1183
  }
1184
+ setTsPaths(type, name) {
1185
+ const rootTsConfig = this.readJson("tsconfig.json");
1186
+ if (type === "lib")
1187
+ rootTsConfig.compilerOptions.paths[`@${name}`] = [`${type}s/${name}/index.ts`];
1188
+ rootTsConfig.compilerOptions.paths[`@${name}/*`] = [`${type}s/${name}/*`];
1189
+ this.writeJson("tsconfig.json", rootTsConfig);
1190
+ return this;
1191
+ }
1192
+ async commit(message, { init = false, add = true } = {}) {
1193
+ if (init)
1194
+ await this.exec(`git init`);
1195
+ if (add)
1196
+ await this.exec(`git add .`);
1197
+ await this.exec(`git commit -m "${message}"`);
1198
+ }
1162
1199
  async #getDirHasFile(basePath2, targetFilename) {
1163
1200
  const AVOID_DIRS = ["node_modules", "dist", "public", "./next"];
1164
1201
  const getDirs = async (dirname, maxDepth = 3, results = [], prefix = "") => {
@@ -1181,6 +1218,14 @@ var WorkspaceExecutor = class _WorkspaceExecutor extends Executor {
1181
1218
  };
1182
1219
  return await getDirs(basePath2);
1183
1220
  }
1221
+ async getScalarConstantFiles() {
1222
+ const [appNames, libNames] = await this.getSyss();
1223
+ const scalarConstantExampleFiles = [
1224
+ ...(await Promise.all(appNames.map((appName) => AppExecutor.from(this, appName).getScalarConstantFiles()))).flat(),
1225
+ ...(await Promise.all(libNames.map((libName) => LibExecutor.from(this, libName).getScalarConstantFiles()))).flat()
1226
+ ];
1227
+ return scalarConstantExampleFiles;
1228
+ }
1184
1229
  };
1185
1230
  var SysExecutor = class extends Executor {
1186
1231
  workspace;
@@ -1324,6 +1369,11 @@ var SysExecutor = class extends Executor {
1324
1369
  this.writeJson(`akan.${this.type}.json`, scanResult);
1325
1370
  return scanResult;
1326
1371
  }
1372
+ getLocalFile(filePath) {
1373
+ const filepath = import_path3.default.isAbsolute(filePath) ? filePath : `${this.type}s/${this.name}/${filePath}`;
1374
+ const content = this.workspace.readFile(filepath);
1375
+ return { filepath, content };
1376
+ }
1327
1377
  async getDatabaseModules() {
1328
1378
  const databaseModules = (await import_promises.default.readdir(`${this.cwdPath}/lib`)).filter((name) => !name.startsWith("_")).filter((name) => import_fs7.default.existsSync(`${this.cwdPath}/lib/${name}/${name}.constant.ts`));
1329
1379
  return databaseModules;
@@ -1336,6 +1386,22 @@ var SysExecutor = class extends Executor {
1336
1386
  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`));
1337
1387
  return scalarModules;
1338
1388
  }
1389
+ async getScalarConstantFiles() {
1390
+ const scalarModules = await this.getScalarModules();
1391
+ return scalarModules.map(
1392
+ (scalarModule) => this.getLocalFile(`lib/__scalar/${scalarModule}/${scalarModule}.constant.ts`)
1393
+ );
1394
+ }
1395
+ async getScalarDictionaryFiles() {
1396
+ const scalarModules = await this.getScalarModules();
1397
+ return scalarModules.map(
1398
+ (scalarModule) => this.getLocalFile(`lib/__scalar/${scalarModule}/${scalarModule}.dictionary.ts`)
1399
+ );
1400
+ }
1401
+ setTsPaths() {
1402
+ this.workspace.setTsPaths(this.type, this.name);
1403
+ return this;
1404
+ }
1339
1405
  };
1340
1406
  var AppExecutor = class _AppExecutor extends SysExecutor {
1341
1407
  constructor({ workspace, name }) {
@@ -1897,11 +1963,71 @@ var runCommands = async (...commands) => {
1897
1963
  await import_commander.program.parseAsync(process.argv);
1898
1964
  };
1899
1965
 
1900
- // pkgs/@akanjs/devkit/src/installExternalLib.ts
1901
- var installExternalLib = async (libName, workspace) => {
1902
- workspace.log(`Installing ${libName} library as git subtree...`);
1903
- await workspace.exec(`git remote add ${libName} git@github.com:akan-team/${libName}.git`);
1904
- await workspace.exec(`git subtree add --prefix=libs/${libName} ${libName} main`);
1966
+ // pkgs/@akanjs/devkit/src/aiEditor.ts
1967
+ var import_prompts4 = require("@inquirer/prompts");
1968
+ var import_messages = require("@langchain/core/messages");
1969
+ var import_openai2 = require("@langchain/openai");
1970
+ var MAX_ASK_TRY = 300;
1971
+ var AiSession = class _AiSession {
1972
+ static #chat = new import_openai2.ChatOpenAI({
1973
+ modelName: "deepseek-chat",
1974
+ temperature: 0.7,
1975
+ streaming: true,
1976
+ // Enable streaming
1977
+ configuration: { baseURL: "https://api.deepseek.com/v1", apiKey: process.env.DEEPSEEK_API_KEY }
1978
+ });
1979
+ messageHistory = [];
1980
+ constructor(messageHistory = []) {
1981
+ this.messageHistory = messageHistory;
1982
+ }
1983
+ async ask(question, {
1984
+ onChunk = (chunk) => {
1985
+ Logger.raw(chunk);
1986
+ }
1987
+ } = {}) {
1988
+ try {
1989
+ const humanMessage = new import_messages.HumanMessage(question);
1990
+ this.messageHistory.push(humanMessage);
1991
+ const stream = await _AiSession.#chat.stream(this.messageHistory);
1992
+ let fullResponse = "";
1993
+ for await (const chunk of stream) {
1994
+ const content = chunk.content;
1995
+ if (typeof content === "string") {
1996
+ fullResponse += content;
1997
+ onChunk(content);
1998
+ }
1999
+ }
2000
+ this.messageHistory.push(new import_messages.AIMessage(fullResponse));
2001
+ return { content: fullResponse, messageHistory: this.messageHistory };
2002
+ } catch (error) {
2003
+ throw new Error("Failed to stream response");
2004
+ }
2005
+ }
2006
+ async edit(question, { onChunk, maxTry = MAX_ASK_TRY } = {}) {
2007
+ for (let tryCount = 0; tryCount < maxTry; tryCount++) {
2008
+ const response = await this.ask(question, { onChunk });
2009
+ const isConfirmed = await (0, import_prompts4.select)({
2010
+ message: "Do you want to edit the response?",
2011
+ choices: [
2012
+ { name: "\u2705 Yes, confirm and apply this result", value: true },
2013
+ { name: "\u{1F504} No, I want to edit it more", value: false }
2014
+ ]
2015
+ });
2016
+ if (isConfirmed)
2017
+ return response.content;
2018
+ question = await (0, import_prompts4.input)({ message: "What do you want to change?" });
2019
+ tryCount++;
2020
+ }
2021
+ throw new Error("Failed to edit");
2022
+ }
2023
+ async editTypescript(question, options = {}) {
2024
+ const content = await this.edit(question, options);
2025
+ return this.#getTypescriptCode(content);
2026
+ }
2027
+ #getTypescriptCode(content) {
2028
+ const code = /```typescript([\s\S]*?)```/.exec(content);
2029
+ return code ? code[1] : content;
2030
+ }
1905
2031
  };
1906
2032
 
1907
2033
  // pkgs/@akanjs/cli/src/library/library.runner.ts
@@ -1911,6 +2037,21 @@ var LibraryRunner = class {
1911
2037
  const scanResult = await lib.scan({ akanConfig });
1912
2038
  return scanResult;
1913
2039
  }
2040
+ async installLibrary(workspace, libName) {
2041
+ workspace.log(`Installing ${libName} library as git subtree...`);
2042
+ await workspace.exec(`git subtree add --prefix=libs/${libName} git@github.com:akan-team/${libName}.git main`);
2043
+ await workspace.cp(`libs/${libName}/env/env.server.example.ts`, `libs/${libName}/env/env.server.testing.ts`);
2044
+ workspace.setTsPaths("lib", libName);
2045
+ await workspace.commit(`Add ${libName} library`);
2046
+ }
2047
+ async pushLibrary(lib, branch) {
2048
+ await lib.workspace.exec(`git subtree push --prefix=libs/${lib.name} ${lib.name} ${branch}`);
2049
+ lib.logger.log(`${lib.name} library pushed to ${branch} branch`);
2050
+ }
2051
+ async pullLibrary(lib, branch) {
2052
+ await lib.workspace.exec(`git subtree pull --prefix=libs/${lib.name} ${lib.name} ${branch}`);
2053
+ lib.logger.log(`${lib.name} library pulled from ${branch} branch`);
2054
+ }
1914
2055
  };
1915
2056
 
1916
2057
  // pkgs/@akanjs/cli/src/library/library.script.ts
@@ -1927,14 +2068,24 @@ var LibraryScript = class {
1927
2068
  await this.syncLibrary(LibExecutor.from(lib.workspace, libName), { recursive: false });
1928
2069
  }
1929
2070
  }
2071
+ async installLibrary(workspace, libName) {
2072
+ await this.#runner.installLibrary(workspace, libName);
2073
+ workspace.log(`${libName} library installed`);
2074
+ }
2075
+ async pushLibrary(lib, branch) {
2076
+ await this.#runner.pushLibrary(lib, branch);
2077
+ }
2078
+ async pullLibrary(lib, branch) {
2079
+ await this.#runner.pullLibrary(lib, branch);
2080
+ }
1930
2081
  };
1931
2082
 
1932
2083
  // pkgs/@akanjs/cli/src/application/application.runner.ts
1933
- var import_prompts4 = require("@inquirer/prompts");
2084
+ var import_prompts5 = require("@inquirer/prompts");
1934
2085
  var import_output_parsers = require("@langchain/core/output_parsers");
1935
- var import_prompts5 = require("@langchain/core/prompts");
2086
+ var import_prompts6 = require("@langchain/core/prompts");
1936
2087
  var import_runnables2 = require("@langchain/core/runnables");
1937
- var import_openai2 = require("@langchain/openai");
2088
+ var import_openai3 = require("@langchain/openai");
1938
2089
  var import_plugin_react = __toESM(require("@vitejs/plugin-react"));
1939
2090
  var import_dotenv = __toESM(require("dotenv"));
1940
2091
  var esbuild = __toESM(require("esbuild"));
@@ -2475,6 +2626,409 @@ dictionaryStart
2475
2626
 
2476
2627
  dictionaryEnd
2477
2628
 
2629
+ `;
2630
+ var frameworkAbstract = `
2631
+ Intro
2632
+ - Build an all-stack application at once.
2633
+ - Write one line, deploy on web, app, server, database, and infra.
2634
+ - Akan is a framework with least code, highest performance for typescript-written applications.
2635
+
2636
+ Key features
2637
+ - Integral interface: Akan serves an interface for building from schema, to service logic, api endpoint, state management, and component design.
2638
+ - Stable, Scalable, Safe built-in architecture: Fully type-safe, i18n, security, file management, text-search, automatic documentation, admin page, etc are all served with modular development.
2639
+ - application as a service: Akan deploys server, database, web, app at once through Akan cloud. Commit once, deploy and manage all.
2640
+
2641
+ Procedure
2642
+ - add field on database and api at once, with fully typed
2643
+ - add backend api endpoint and frontend fetch function at once, with fully typed
2644
+ - write query interface and use everywhere!
2645
+ - No spaghetti state management anymore, build your global store with domain-driven state&actions.
2646
+ - No Spaghetti Components anymore, build your page with domain-driven components
2647
+ - write one page, use SSR on Next.js and build Android&iOS CSR app with beautiful page transitions!
2648
+ - built-in ai code generation, tell about business, the logic is generated.
2649
+ `;
2650
+ var scalarConstantDescription = `
2651
+ Purpose and Structure
2652
+
2653
+ Scalar constant files define reusable data structures that can be embedded within other models. They represent complex field types
2654
+ that are not entities themselves but are used as components within larger data models. These are located in the __scalar directory
2655
+ within application or library modules.
2656
+
2657
+ Key Characteristics
2658
+
2659
+ - Defined with @Model.Scalar decorator (not @Model.Input, @Model.Object, etc.)
2660
+ - Do not have their own database collection
2661
+ - Cannot be queried independently
2662
+ - Used as embedded objects within other models
2663
+ - Often represent complex value objects or domain concepts
2664
+
2665
+ Creating Scalar Constant Files
2666
+
2667
+ File Organization
2668
+
2669
+ 1. Place scalar constants in the lib/__scalar/{scalarName}/ directory
2670
+ 2. Name the file {scalarName}.constant.ts
2671
+ 3. Register scalars in the _server.ts file in the __scalar directory
2672
+
2673
+ Basic Structure
2674
+
2675
+ import { Field, Model } from "@akanjs/constant";
2676
+ import { enumOf, Int, Dayjs } from "@akanjs/base"; // Import needed types
2677
+
2678
+ // Optional: Define enums used by this scalar
2679
+ export const ScalarEnum = enumOf(["value1", "value2", "value3"] as const);
2680
+ export type ScalarEnum = enumOf<typeof ScalarEnum>;
2681
+
2682
+ @Model.Scalar("ScalarName") // Use the @Model.Scalar decorator
2683
+ export class ScalarName {
2684
+ // Define properties with @Field.Prop decorator
2685
+ @Field.Prop(() => String)
2686
+ stringProperty: string;
2687
+
2688
+ @Field.Prop(() => Int, { min: 0 })
2689
+ numericProperty: number;
2690
+
2691
+ @Field.Prop(() => Boolean, { default: false })
2692
+ booleanProperty: boolean;
2693
+
2694
+ @Field.Prop(() => Date)
2695
+ dateProperty: Dayjs;
2696
+
2697
+ @Field.Prop(() => String, { enum: ScalarEnum })
2698
+ enumProperty: ScalarEnum;
2699
+
2700
+ @Field.Prop(() => String, { nullable: true })
2701
+ optionalProperty: string | null;
2702
+ }
2703
+
2704
+
2705
+ Common Types of Scalar Objects
2706
+
2707
+ Based on the analyzed codebase, here are common patterns for scalar objects:
2708
+
2709
+ 1. Value Objects
2710
+
2711
+ Simple structures that group related properties:
2712
+
2713
+ @Model.Scalar("Address")
2714
+ export class Address {
2715
+ @Field.Prop(() => String)
2716
+ street: string;
2717
+
2718
+ @Field.Prop(() => String)
2719
+ city: string;
2720
+
2721
+ @Field.Prop(() => String)
2722
+ zipCode: string;
2723
+
2724
+ @Field.Prop(() => String)
2725
+ country: string;
2726
+ }
2727
+
2728
+ 2. Configuration Objects
2729
+
2730
+ Objects holding configuration or settings:
2731
+
2732
+ @Model.Scalar("NotificationSettings")
2733
+ export class NotificationSettings {
2734
+ @Field.Prop(() => Boolean, { default: true })
2735
+ emailEnabled: boolean;
2736
+
2737
+ @Field.Prop(() => Boolean, { default: true })
2738
+ pushEnabled: boolean;
2739
+
2740
+ @Field.Prop(() => Boolean, { default: false })
2741
+ smsEnabled: boolean;
2742
+ }
2743
+
2744
+ 3. Metadata Objects
2745
+
2746
+ Objects providing metadata about other entities:
2747
+
2748
+ @Model.Scalar("FileMeta")
2749
+ export class FileMeta {
2750
+ @Field.Prop(() => Date)
2751
+ lastModifiedAt: Dayjs;
2752
+
2753
+ @Field.Prop(() => Int)
2754
+ size: number;
2755
+
2756
+ @Field.Prop(() => String, { nullable: true })
2757
+ mimeType: string | null;
2758
+ }
2759
+
2760
+ 4. Complex Value Type Objects
2761
+
2762
+ Objects representing domain-specific complex values:
2763
+
2764
+ @Model.Scalar("GeoLocation")
2765
+ export class GeoLocation {
2766
+ @Field.Prop(() => Float)
2767
+ latitude: number;
2768
+
2769
+ @Field.Prop(() => Float)
2770
+ longitude: number;
2771
+
2772
+ @Field.Prop(() => Float, { nullable: true })
2773
+ altitude: number | null;
2774
+ }
2775
+
2776
+ Best Practices
2777
+
2778
+ 1. Keep it Simple: Scalar objects should be focused on a single concept
2779
+ 2. No External References: Avoid referencing entities directly from scalar objects
2780
+ 3. Validation Rules: Include validation rules in field definitions
2781
+ 4. Default Values: Provide sensible defaults where appropriate
2782
+ 5. Documentation: Document the purpose and usage of each scalar type
2783
+ 6. Reusability: Design scalar objects to be reusable across different models
2784
+ 7. Immutability: Treat scalar objects as immutable value objects
2785
+ 8. Naming Convention: Use descriptive names that reflect the domain concept
2786
+
2787
+ Using Scalar Types in Models
2788
+
2789
+ After defining scalar objects, you can use them in your entity models:
2790
+
2791
+ import { Field, Model } from "@akanjs/constant";
2792
+ import { FileMeta } from "../__scalar/fileMeta/fileMeta.constant";
2793
+ import { ExternalLink } from "../__scalar/externalLink/externalLink.constant";
2794
+
2795
+ @Model.Input("ProfileInput")
2796
+ export class ProfileInput {
2797
+ @Field.Prop(() => String)
2798
+ name: string;
2799
+
2800
+ @Field.Prop(() => FileMeta, { nullable: true })
2801
+ avatar: FileMeta | null;
2802
+
2803
+ @Field.Prop(() => [ExternalLink])
2804
+ socialLinks: ExternalLink[];
2805
+ }
2806
+
2807
+ Key Differences from Regular Models
2808
+
2809
+ This structured approach to scalar objects helps maintain clean, modular, and reusable code across your application, while keeping
2810
+ the domain concepts well-organized and type-safe.
2811
+ `;
2812
+ var howToSetEnumInModelConstant = `
2813
+ Declaring Enumerations in Constant Files
2814
+
2815
+ Enumerations in the constant.ts files are declared using the enumOf utility function from the @akanjs/base package. This creates
2816
+ type-safe enumeration values with strong typing support.
2817
+
2818
+ Basic Enum Declaration
2819
+
2820
+ import { enumOf } from "@akanjs/base";
2821
+
2822
+ // Define the enum values as a const array
2823
+ // Export the type derived from the enum
2824
+ export const UserStatus = enumOf(["active", "inactive", "pending"] as const);
2825
+ export type UserStatus = enumOf<typeof UserStatus>;
2826
+
2827
+ Key Features
2828
+
2829
+ 1. Type Safety: The as const assertion ensures values are treated as literal types
2830
+ 2. Value Access: Enum values can be accessed via UserStatus.values
2831
+ 3. Auto-completion: TypeScript provides auto-completion for enum values
2832
+ 4. Validation: Prevents assigning invalid values to fields using this enum
2833
+
2834
+ Using Enums with Field Decorators
2835
+
2836
+ @Field.Prop(() => String, { enum: UserStatus, default: "active" })
2837
+ status: UserStatus;
2838
+
2839
+ // For array of enum values
2840
+ @Field.Prop(() => [String], { enum: UserRole, default: ["user"] })
2841
+ roles: UserRole[];
2842
+ `;
2843
+ var howToSetFieldInModelConstant = `
2844
+ # @Field Decorator Documentation
2845
+
2846
+ The \`@Field\` decorator is used in the Akamir framework to define properties for model classes. This documentation focuses on the usage of \`@Field.Prop()\` and its available options.
2847
+
2848
+ ## Basic Usage
2849
+
2850
+ The \`@Field.Prop()\` decorator is used to define properties in model classes with specific types and options:
2851
+
2852
+ \`\`\`typescript
2853
+ @Field.Prop(() => Type, { ...options })
2854
+ propertyName: PropertyType;
2855
+ \`\`\`
2856
+
2857
+ Where:
2858
+ - \`Type\` is the GraphQL type for the property (e.g., \`String\`, \`Int\`, \`ID\`, etc.)
2859
+ - \`options\` is an optional object containing configuration parameters
2860
+ - \`PropertyType\` is the TypeScript type of the property
2861
+
2862
+ ## Available Options
2863
+
2864
+ The following options can be provided to \`@Field.Prop()\`:
2865
+
2866
+ ### Basic Options
2867
+
2868
+ | Option | Type | Description | Example |
2869
+ |-------------|-----------------------------------------------|----------------------------------------------------|------------------------------------------------|
2870
+ | \`nullable\` | \`boolean\` | Specifies if the field can be null | \`{ nullable: true }\` |
2871
+ | \`default\` | \`string \\| number \\| boolean \\| object \\| null \\| Enum\` | Default value for the field | \`{ default: "active" }\` or \`{ default: 0 }\` |
2872
+ | \`enum\` | \`Enum<string \\| number>\` | Restricts field values to predefined enum values | \`{ enum: ProductStatus }\` |
2873
+ | \`type\` | \`"email" \\| "password" \\| "url"\` | Special field type for validation | \`{ type: "email" }\` |
2874
+
2875
+ ### Reference Options
2876
+
2877
+ | Option | Type | Description | Example |
2878
+ |-------------|-------------------------------|----------------------------------------------------|------------------------------------------------|
2879
+ | \`ref\` | \`string\` | Reference to another model (by model name) | \`{ ref: "product" }\` |
2880
+ | \`refPath\` | \`string\` | Path to field containing the model name | \`{ refPath: "modelType" }\` |
2881
+ | \`refType\` | \`"child" \\| "parent" \\| "relation"\` | Type of relationship between models | \`{ refType: "child" }\` |
2882
+
2883
+ ### Validation Options
2884
+
2885
+ | Option | Type | Description | Example |
2886
+ |-------------|-------------------------------|----------------------------------------------------|------------------------------------------------|
2887
+ | \`min\` | \`number\` | Minimum value for number fields | \`{ min: 0 }\` |
2888
+ | \`max\` | \`number\` | Maximum value for number fields | \`{ max: 100 }\` |
2889
+ | \`minlength\` | \`number\` | Minimum length for string fields | \`{ minlength: 3 }\` |
2890
+ | \`maxlength\` | \`number\` | Maximum length for string fields | \`{ maxlength: 50 }\` |
2891
+ | \`validate\` | \`(value: any, model: any) => boolean\` | Custom validation function | \`{ validate: isPhoneNumber }\` |
2892
+
2893
+ ### Field Behavior Options
2894
+
2895
+ | Option | Type | Description | Example |
2896
+ |-------------|-----------------------------------------------|----------------------------------------------------|------------------------------------------------|
2897
+ | \`fieldType\` | \`"property" \\| "hidden" \\| "resolve"\` | Determines how field is used in GraphQL schema | \`{ fieldType: "hidden" }\` |
2898
+ | \`immutable\` | \`boolean\` | Makes field immutable after creation | \`{ immutable: true }\` |
2899
+ | \`select\` | \`boolean\` | Controls if field is included in query results | \`{ select: false }\` |
2900
+ | \`query\` | \`QueryOf<any> \\| (() => QueryOf<any>)\` | MongoDB query for this field | \`{ query: {} }\` |
2901
+ | \`accumulate\`| \`AccumulatorOperator\` | MongoDB accumulator operator for aggregation | \`{ accumulate: { $sum: 1 } }\` |
2902
+ | \`text\` | \`"search" \\| "filter"\` | Enables text search or filter on this field | \`{ text: "search" }\` |
2903
+
2904
+ ### Other Options
2905
+
2906
+ | Option | Type | Description | Example |
2907
+ |-------------|-----------------------------------------------|----------------------------------------------------|------------------------------------------------|
2908
+ | \`of\` | \`GqlScalar\` | Used for Map type fields to specify value type | \`{ of: String }\` |
2909
+ | \`example\` | \`string \\| number \\| boolean \\| Dayjs \\| Array\` | Example value for documentation/playground | \`{ example: "example@email.com" }\` |
2910
+
2911
+ ## Examples
2912
+
2913
+ ### Basic Property Definition
2914
+
2915
+ \`\`\`typescript
2916
+ @Field.Prop(() => String)
2917
+ name: string;
2918
+ \`\`\`
2919
+
2920
+ ### Nullable Field with Default Value
2921
+
2922
+ \`\`\`typescript
2923
+ @Field.Prop(() => String, { nullable: true, default: "Default Description" })
2924
+ description: string | null;
2925
+ \`\`\`
2926
+
2927
+ ### Enum-Constrained Field
2928
+
2929
+ \`\`\`typescript
2930
+ @Field.Prop(() => String, { enum: ProductStatus, default: "active" })
2931
+ status: ProductStatus;
2932
+ \`\`\`
2933
+
2934
+ ### Number Field with Minimum Value
2935
+
2936
+ \`\`\`typescript
2937
+ @Field.Prop(() => Int, { min: 0, default: 0 })
2938
+ totalProduct: number;
2939
+ \`\`\`
2940
+
2941
+ ### Field with Custom Validation
2942
+
2943
+ \`\`\`typescript
2944
+ @Field.Prop(() => String, { validate: isPhoneNumber })
2945
+ phone: string;
2946
+ \`\`\`
2947
+
2948
+ ### Field with Special Type
2949
+
2950
+ \`\`\`typescript
2951
+ @Field.Prop(() => String, { type: "email" })
2952
+ email: string;
2953
+ \`\`\`
2954
+
2955
+ ### Relationship Field
2956
+
2957
+ \`\`\`typescript
2958
+ @Field.Prop(() => LightBizLicense, { nullable: true })
2959
+ bizLicense: LightBizLicense | null;
2960
+ \`\`\`
2961
+
2962
+ ### Aggregation Field
2963
+
2964
+ \`\`\`typescript
2965
+ @Field.Prop(() => Int, { default: 0, accumulate: { $sum: 1 } })
2966
+ count: number;
2967
+ \`\`\`
2968
+
2969
+ ## Usage Patterns
2970
+
2971
+ The \`@Field.Prop()\` decorator is commonly used in different model types:
2972
+
2973
+ - **Input Models** (\`@Model.Input\`): Used for creating/updating objects
2974
+ - **Object Models** (\`@Model.Object\`): Base model representation
2975
+ - **Light Models** (\`@Model.Light\`): Light version with selected fields
2976
+ - **Full Models** (\`@Model.Full\`): Complete model representation
2977
+ - **Insight Models** (\`@Model.Insight\`): Used for analytics/statistics
2978
+ - **Summary Models** (\`@Model.Summary\`): Used for data summaries
2979
+
2980
+ ## Notes
2981
+
2982
+ - The options allow for flexible field definition with both GraphQL and MongoDB integrations
2983
+ - Validation options help ensure data integrity at the model level
2984
+ - Reference options enable building relationships between different models
2985
+ - Aggregation options support analytics use cases
2986
+ `;
2987
+ var requestScalarConstant = ({
2988
+ sysName,
2989
+ modelName,
2990
+ modelDesc,
2991
+ modelSchemaDesign,
2992
+ boilerplate,
2993
+ otherConstants
2994
+ }) => `
2995
+ \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.
2996
+ \uB2E4\uC74C\uC758 \uBC30\uACBD \uC815\uBCF4\uB97C \uBC14\uD0D5\uC73C\uB85C ${modelName}.constant.ts \uD30C\uC77C\uC744 \uC791\uC131\uD574\uC918.
2997
+
2998
+ 1. Akan.js \uD504\uB808\uC784\uC6CC\uD06C\uC5D0 \uB300\uD55C \uAC1C\uC694
2999
+ ${frameworkAbstract}
3000
+
3001
+ 2. <model>.constant.ts \uD30C\uC77C\uC5D0 \uB300\uD55C \uAC1C\uC694
3002
+ ${scalarConstantDescription}
3003
+
3004
+ 3. <model.constant.ts \uD30C\uC77C\uC758 Enum \uC791\uC131\uBC95
3005
+ ${howToSetEnumInModelConstant}
3006
+
3007
+ 4. <model.constant.ts \uD30C\uC77C\uC758 Field \uC791\uC131\uBC95
3008
+ ${howToSetFieldInModelConstant}
3009
+
3010
+ 5. \uD604\uC7AC \uD504\uB85C\uC81D\uD2B8 \uB0B4 \uB2E4\uB978 constant.ts \uD30C\uC77C\uB4E4\uC5D0 \uB300\uD55C \uC608\uC2DC
3011
+ ${otherConstants.map(
3012
+ (constant) => `
3013
+ Example file: ${constant.filepath}
3014
+ \`\`\`
3015
+ ${constant.content}
3016
+ \`\`\`
3017
+ `
3018
+ ).join("\n")}
3019
+
3020
+
3021
+ \uC704 \uB0B4\uC6A9\uB4E4\uC744 \uBC14\uD0D5\uC73C\uB85C \uD30C\uC2F1\uD558\uAE30 \uC27D\uAC8C \uC544\uB798\uC5D0 \uBCF4\uC77C\uB7EC\uD50C\uB808\uC774\uD2B8\uC5D0 \uB9DE\uAC8C \uC815\uB9AC\uD574\uC11C \uC918
3022
+
3023
+ Application name: ${sysName}
3024
+ Model name: ${modelName}
3025
+ Model description: ${modelDesc}
3026
+ Model schema design: ${modelSchemaDesign}
3027
+
3028
+ Target filename: ${modelName}.constant.ts
3029
+ \`\`\`
3030
+ ${boilerplate}
3031
+ \`\`\`
2478
3032
  `;
2479
3033
 
2480
3034
  // pkgs/@akanjs/cli/src/application/application.prompt.ts
@@ -2511,6 +3065,20 @@ page.tsx_end
2511
3065
 
2512
3066
  // pkgs/@akanjs/cli/src/application/application.runner.ts
2513
3067
  var ApplicationRunner = class {
3068
+ async createApplication(appName, workspace) {
3069
+ await workspace.applyTemplate({
3070
+ basePath: `apps/${appName}`,
3071
+ template: "app",
3072
+ dict: {
3073
+ appName,
3074
+ AppName: capitalize(appName),
3075
+ companyName: workspace.repoName,
3076
+ CompanyName: capitalize(workspace.repoName),
3077
+ serveDomain: "localhost"
3078
+ }
3079
+ });
3080
+ workspace.setTsPaths("app", appName);
3081
+ }
2514
3082
  async scanSync(app) {
2515
3083
  const akanConfig = await getAppConfig(app.cwdPath, { ...getBaseDevEnv(), appName: app.name, command: "serve" });
2516
3084
  const scanResult = await app.scan({ akanConfig });
@@ -2786,11 +3354,11 @@ var ApplicationRunner = class {
2786
3354
  async configureApp(app) {
2787
3355
  const capacitorApp = new CapacitorApp(app);
2788
3356
  await capacitorApp.init();
2789
- if (await (0, import_prompts4.confirm)({ message: "want to add camera permission?" }))
3357
+ if (await (0, import_prompts5.confirm)({ message: "want to add camera permission?" }))
2790
3358
  await capacitorApp.addCamera();
2791
- if (await (0, import_prompts4.confirm)({ message: "want to add contact permission?" }))
3359
+ if (await (0, import_prompts5.confirm)({ message: "want to add contact permission?" }))
2792
3360
  await capacitorApp.addContact();
2793
- if (await (0, import_prompts4.confirm)({ message: "want to add location permission?" }))
3361
+ if (await (0, import_prompts5.confirm)({ message: "want to add location permission?" }))
2794
3362
  await capacitorApp.addLocation();
2795
3363
  await capacitorApp.save();
2796
3364
  }
@@ -2939,11 +3507,11 @@ var ApplicationRunner = class {
2939
3507
  const openAIApiKey = process.env.OPENAI_API_KEY;
2940
3508
  if (!openAIApiKey)
2941
3509
  throw new Error("OPENAI_API_KEY is not set");
2942
- const chatModel = new import_openai2.ChatOpenAI({ modelName: "gpt-4o", openAIApiKey });
2943
- const projectName = await (0, import_prompts4.input)({ message: "please enter project name." });
2944
- const projectDesc = await (0, import_prompts4.input)({ message: "please enter project description. (40 ~ 60 characters)" });
3510
+ const chatModel = new import_openai3.ChatOpenAI({ modelName: "gpt-4o", openAIApiKey });
3511
+ const projectName = await (0, import_prompts5.input)({ message: "please enter project name." });
3512
+ const projectDesc = await (0, import_prompts5.input)({ message: "please enter project description. (40 ~ 60 characters)" });
2945
3513
  const spinner = (0, import_ora2.default)("Gerating project files...");
2946
- const mainPrompt = import_prompts5.PromptTemplate.fromTemplate(requestApplication());
3514
+ const mainPrompt = import_prompts6.PromptTemplate.fromTemplate(requestApplication());
2947
3515
  const chain = import_runnables2.RunnableSequence.from([mainPrompt, chatModel, new import_output_parsers.StringOutputParser()]);
2948
3516
  const resultOne = await chain.invoke({ projectName, projectDesc });
2949
3517
  spinner.succeed("Loading complete!");
@@ -2965,6 +3533,9 @@ var ApplicationRunner = class {
2965
3533
  var ApplicationScript = class {
2966
3534
  #runner = new ApplicationRunner();
2967
3535
  libraryScript = new LibraryScript();
3536
+ async createApplication(appName, workspace) {
3537
+ await this.#runner.createApplication(appName, workspace);
3538
+ }
2968
3539
  async scanApplication(app) {
2969
3540
  const scanResult = await this.#runner.scanSync(app);
2970
3541
  app.logger.rawLog(JSON.stringify(scanResult, null, 2));
@@ -3054,6 +3625,7 @@ var ApplicationScript = class {
3054
3625
  var ApplicationCommand = class {
3055
3626
  applicationScript = new ApplicationScript();
3056
3627
  async createApplication(name, workspace) {
3628
+ await this.applicationScript.createApplication(name, workspace);
3057
3629
  }
3058
3630
  async removeApplication(app, workspace) {
3059
3631
  }
@@ -3233,13 +3805,12 @@ ApplicationCommand = __decorateClass([
3233
3805
  var esbuild2 = __toESM(require("esbuild"));
3234
3806
  var import_esbuild_plugin_d = require("esbuild-plugin-d.ts");
3235
3807
  var import_promises3 = __toESM(require("fs/promises"));
3236
- var import_lodash = require("lodash");
3237
3808
  var PackageRunner = class {
3238
3809
  async createPackage(workspace, pkgName) {
3239
3810
  await workspace.applyTemplate({
3240
3811
  basePath: `pkgs/${pkgName}`,
3241
3812
  template: "pkgRoot",
3242
- dict: { pkgName, PkgName: (0, import_lodash.capitalize)(pkgName) }
3813
+ dict: { pkgName, PkgName: capitalize(pkgName) }
3243
3814
  });
3244
3815
  }
3245
3816
  async scanSync(pkg) {
@@ -3277,7 +3848,7 @@ var PackageRunner = class {
3277
3848
  });
3278
3849
  await esbuild2.build({
3279
3850
  write: true,
3280
- entryPoints: [`${pkg.cwdPath}/src/templates/**/*.ts`, `${pkg.cwdPath}/src/templates/**/*.tsx`],
3851
+ entryPoints: [`${pkg.cwdPath}/src/templates/**/*.ts`],
3281
3852
  packages: "external",
3282
3853
  outdir: `${distPkg.cwdPath}/src/templates`,
3283
3854
  outbase: `${pkg.cwdPath}/src/templates`,
@@ -3285,16 +3856,36 @@ var PackageRunner = class {
3285
3856
  platform: "node",
3286
3857
  footer: { js: "module.exports = module.exports.default;" }
3287
3858
  });
3859
+ await esbuild2.build({
3860
+ write: true,
3861
+ entryPoints: [`${pkg.cwdPath}/src/templates/**/*.tsx`],
3862
+ packages: "external",
3863
+ outdir: `${distPkg.cwdPath}/src/templates`,
3864
+ outbase: `${pkg.cwdPath}/src/templates`,
3865
+ format: "cjs",
3866
+ platform: "node",
3867
+ footer: { js: "module.exports = module.exports.default;" },
3868
+ outExtension: { ".js": ".jsx" }
3869
+ });
3288
3870
  await pkg.workspace.exec(
3289
3871
  `rsync -aq --exclude="*.ts" --exclude="*.tsx" ${pkg.cwdPath}/src/templates/ ${distPkg.cwdPath}/src/templates/`
3290
3872
  );
3291
3873
  } else {
3874
+ const platform = [
3875
+ "@akanjs/devkit",
3876
+ "@akanjs/document",
3877
+ "@akanjs/lint",
3878
+ "@akanjs/nest",
3879
+ "@akanjs/server",
3880
+ "@akanjs/service"
3881
+ ].includes(pkg.name) ? "node" : ["@akanjs/client", "@akanjs/next", "@akanjs/store", "@akanjs/ui"].includes(pkg.name) ? "browser" : "neutral";
3292
3882
  buildResult = await esbuild2.build({
3293
3883
  write: false,
3294
3884
  entryPoints: [`${pkg.cwdPath}/**/*.ts`, `${pkg.cwdPath}/**/*.tsx`],
3295
3885
  bundle: false,
3296
3886
  packages: "external",
3297
3887
  splitting: false,
3888
+ platform,
3298
3889
  format: "cjs",
3299
3890
  outdir: distPkg.cwdPath,
3300
3891
  outExtension: { ".js": pkgJson.type === "module" ? ".cjs" : ".js" },
@@ -3307,6 +3898,7 @@ var PackageRunner = class {
3307
3898
  bundle: false,
3308
3899
  packages: "external",
3309
3900
  splitting: false,
3901
+ platform,
3310
3902
  format: "esm",
3311
3903
  outdir: distPkg.cwdPath,
3312
3904
  outExtension: { ".js": pkgJson.type === "module" ? ".js" : ".mjs" },
@@ -3352,7 +3944,7 @@ var PackageScript = class {
3352
3944
  };
3353
3945
 
3354
3946
  // pkgs/@akanjs/cli/src/cloud/cloud.runner.ts
3355
- var import_prompts6 = require("@inquirer/prompts");
3947
+ var import_prompts7 = require("@inquirer/prompts");
3356
3948
  var import_chalk = __toESM(require("chalk"));
3357
3949
  var import_latest_version = __toESM(require("latest-version"));
3358
3950
  var import_open = __toESM(require("open"));
@@ -3455,7 +4047,7 @@ ${import_chalk.default.green("\u27A4")} Authentication Required`));
3455
4047
  };
3456
4048
  workspace.writeJson(`dist/pkgs/${library}/package.json`, newDistPackageJson);
3457
4049
  }
3458
- const isDeployConfirmed = await (0, import_prompts6.confirm)({
4050
+ const isDeployConfirmed = await (0, import_prompts7.confirm)({
3459
4051
  message: "Are you sure you want to deploy the libraries?"
3460
4052
  });
3461
4053
  if (!isDeployConfirmed) {
@@ -3531,7 +4123,14 @@ var LibraryCommand = class {
3531
4123
  }
3532
4124
  async buildLibrary(lib) {
3533
4125
  }
3534
- async pushLibrary(lib) {
4126
+ async installLibrary(name, workspace) {
4127
+ await this.libraryScript.installLibrary(workspace, name);
4128
+ }
4129
+ async pushLibrary(lib, branch) {
4130
+ await this.libraryScript.pushLibrary(lib, branch);
4131
+ }
4132
+ async pullLibrary(lib, branch) {
4133
+ await this.libraryScript.pullLibrary(lib, branch);
3535
4134
  }
3536
4135
  };
3537
4136
  __decorateClass([
@@ -3552,29 +4151,39 @@ __decorateClass([
3552
4151
  Target.Public(),
3553
4152
  __decorateParam(0, Lib())
3554
4153
  ], LibraryCommand.prototype, "buildLibrary", 1);
4154
+ __decorateClass([
4155
+ Target.Public(),
4156
+ __decorateParam(0, Option("name", { desc: "name of library" })),
4157
+ __decorateParam(1, Workspace())
4158
+ ], LibraryCommand.prototype, "installLibrary", 1);
3555
4159
  __decorateClass([
3556
4160
  Target.Public({ devOnly: true }),
3557
- __decorateParam(0, Lib())
4161
+ __decorateParam(0, Lib()),
4162
+ __decorateParam(1, Option("branch", { desc: "branch to push", default: "main" }))
3558
4163
  ], LibraryCommand.prototype, "pushLibrary", 1);
4164
+ __decorateClass([
4165
+ Target.Public(),
4166
+ __decorateParam(0, Lib()),
4167
+ __decorateParam(1, Option("branch", { desc: "branch to pull", default: "main" }))
4168
+ ], LibraryCommand.prototype, "pullLibrary", 1);
3559
4169
  LibraryCommand = __decorateClass([
3560
4170
  Commands()
3561
4171
  ], LibraryCommand);
3562
4172
 
3563
4173
  // pkgs/@akanjs/cli/src/module/module.runner.ts
3564
4174
  var import_output_parsers2 = require("@langchain/core/output_parsers");
3565
- var import_prompts7 = require("@langchain/core/prompts");
4175
+ var import_prompts8 = require("@langchain/core/prompts");
3566
4176
  var import_runnables3 = require("@langchain/core/runnables");
3567
- var import_openai3 = require("@langchain/openai");
4177
+ var import_openai4 = require("@langchain/openai");
3568
4178
  var import_fs11 = __toESM(require("fs"));
3569
- var import_lodash2 = require("lodash");
3570
4179
  var ModuleRunner = class {
3571
4180
  async createModule(workspace, moduleName) {
3572
4181
  const openAIApiKey = process.env.OPENAI_API_KEY;
3573
4182
  if (!openAIApiKey)
3574
4183
  throw new Error("OPENAI_API_KEY is not set");
3575
- const chatModel = new import_openai3.ChatOpenAI({ modelName: "gpt-4o", openAIApiKey });
4184
+ const chatModel = new import_openai4.ChatOpenAI({ modelName: "gpt-4o", openAIApiKey });
3576
4185
  const projectConfig = JSON.parse(import_fs11.default.readFileSync(`rootPath/projectConfig.json`, "utf-8"));
3577
- const mainPrompt = import_prompts7.PromptTemplate.fromTemplate(requestModule());
4186
+ const mainPrompt = import_prompts8.PromptTemplate.fromTemplate(requestModule());
3578
4187
  const chain = import_runnables3.RunnableSequence.from([mainPrompt, chatModel, new import_output_parsers2.StringOutputParser()]);
3579
4188
  const resultOne = await chain.invoke({
3580
4189
  projectName: projectConfig.en.projectName,
@@ -3593,7 +4202,7 @@ var ModuleRunner = class {
3593
4202
  basePath: "./lib/__scalar",
3594
4203
  template: "__scalar",
3595
4204
  scanResult,
3596
- dict: { model: name, Model: (0, import_lodash2.capitalize)(name) }
4205
+ dict: { model: name, Model: capitalize(name) }
3597
4206
  });
3598
4207
  await sys2.scan({ akanConfig });
3599
4208
  return {
@@ -3607,7 +4216,7 @@ var ModuleRunner = class {
3607
4216
  async createUnit(sys2, modelName) {
3608
4217
  const modelFileData = getModelFileData(sys2.cwdPath, modelName);
3609
4218
  const { paths } = getRelatedCnsts(modelFileData.constantFilePath);
3610
- const names = { model: modelName, Model: (0, import_lodash2.capitalize)(modelName), LightModel: `Light${(0, import_lodash2.capitalize)(modelName)}` };
4219
+ const names = { model: modelName, Model: capitalize(modelName), LightModel: `Light${capitalize(modelName)}` };
3611
4220
  const prompt = `\uB108\uB294 React, Typescript, TailwindCSS\uB97C \uAE30\uBC18\uC73C\uB85C \uCF54\uB529\uD558\uB294 \uD504\uB860\uD2B8\uC5D4\uB4DC \uAC1C\uBC1C\uC790\uC57C.
3612
4221
  ${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.
3613
4222
 
@@ -3653,7 +4262,7 @@ ${names.Model}.Unit.Card\uC758 \uB9AC\uC561\uD2B8 \uCEF4\uD3EC\uB10C\uD2B8\uB97C
3653
4262
  async createView(sys2, modelName) {
3654
4263
  const modelFileData = getModelFileData(sys2.cwdPath, modelName);
3655
4264
  const { paths } = getRelatedCnsts(modelFileData.constantFilePath);
3656
- const names = { model: modelName, Model: (0, import_lodash2.capitalize)(modelName), LightModel: `Light${(0, import_lodash2.capitalize)(modelName)}` };
4265
+ const names = { model: modelName, Model: capitalize(modelName), LightModel: `Light${capitalize(modelName)}` };
3657
4266
  const prompt = `\uB108\uB294 React, Typescript, TailwindCSS\uB97C \uAE30\uBC18\uC73C\uB85C \uCF54\uB529\uD558\uB294 \uD504\uB860\uD2B8\uC5D4\uB4DC \uAC1C\uBC1C\uC790\uC57C.
3658
4267
  ${names.Model}\uC774\uB77C\uB294 \uB3C4\uBA54\uC778\uC5D0 \uB300\uD574\uC11C ${names.Model} \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.
3659
4268
 
@@ -3706,35 +4315,21 @@ var ModuleScript = class {
3706
4315
  }
3707
4316
  async removeModule(workspace, name) {
3708
4317
  }
3709
- async createScalar(sys2, name) {
3710
- const [appNames, libNames] = await sys2.workspace.getSyss();
3711
- const scalarConstantExampleFiles = [
3712
- ...(await Promise.all(
3713
- appNames.map(async (appName) => {
3714
- const app = AppExecutor.from(sys2.workspace, appName);
3715
- const scalarModules = await app.getScalarModules();
3716
- return await Promise.all(
3717
- scalarModules.map((scalarModule) => ({
3718
- path: `${appName}/${scalarModule}/${scalarModule}.constant.ts`,
3719
- content: app.readFile(`lib/__scalar/${scalarModule}/${scalarModule}.constant.ts`)
3720
- }))
3721
- );
3722
- })
3723
- )).flat(),
3724
- ...(await Promise.all(
3725
- libNames.map(async (libName) => {
3726
- const lib = LibExecutor.from(sys2.workspace, libName);
3727
- const scalarModules = await lib.getScalarModules();
3728
- return await Promise.all(
3729
- scalarModules.map((scalarModule) => ({
3730
- path: `${libName}/${scalarModule}/${scalarModule}.constant.ts`,
3731
- content: lib.readFile(`lib/__scalar/${scalarModule}/${scalarModule}.constant.ts`)
3732
- }))
3733
- );
3734
- })
3735
- )).flat()
3736
- ];
4318
+ async createScalar(sys2, name, description, schemaDescription) {
4319
+ const scalarConstantExampleFiles = await sys2.workspace.getScalarConstantFiles();
3737
4320
  const { constant, dictionary } = await this.#runner.createScalarTemplate(sys2, name);
4321
+ const session = new AiSession();
4322
+ const content = await session.editTypescript(
4323
+ requestScalarConstant({
4324
+ sysName: sys2.name,
4325
+ modelName: name,
4326
+ modelDesc: description,
4327
+ modelSchemaDesign: schemaDescription,
4328
+ boilerplate: constant.content,
4329
+ otherConstants: randomPicks(scalarConstantExampleFiles, Math.min(10, scalarConstantExampleFiles.length))
4330
+ })
4331
+ );
4332
+ sys2.writeFile(`lib/__scalar/${name}/${name}.constant.ts`, content);
3738
4333
  }
3739
4334
  async createService(workspace, name) {
3740
4335
  }
@@ -3759,8 +4354,8 @@ var ModuleCommand = class {
3759
4354
  }
3760
4355
  async scanModule(name, workspace) {
3761
4356
  }
3762
- async createScalar(sys2, name, workspace) {
3763
- await this.moduleScript.createScalar(sys2, name);
4357
+ async createScalar(sys2, name, description, schemaDescription, workspace) {
4358
+ await this.moduleScript.createScalar(sys2, name, description, schemaDescription);
3764
4359
  }
3765
4360
  async createService(name, workspace) {
3766
4361
  }
@@ -3790,7 +4385,9 @@ __decorateClass([
3790
4385
  Target.Public(),
3791
4386
  __decorateParam(0, Sys()),
3792
4387
  __decorateParam(1, Option("name", { desc: "name of scalar module" })),
3793
- __decorateParam(2, Workspace())
4388
+ __decorateParam(2, Option("description", { desc: "description of scalar module" })),
4389
+ __decorateParam(3, Option("schemaDescription", { desc: "schema description of scalar module" })),
4390
+ __decorateParam(4, Workspace())
3794
4391
  ], ModuleCommand.prototype, "createScalar", 1);
3795
4392
  __decorateClass([
3796
4393
  Target.Public(),
@@ -3929,16 +4526,13 @@ var WorkspaceRunner = class {
3929
4526
  };
3930
4527
  workspace.writeJson(`infra/master/mongo-connections.json`, mongoConnectionList);
3931
4528
  }
3932
- async installLibrary(workspace, libName) {
3933
- workspace.log(`Installing ${libName} library as git subtree...`);
3934
- await workspace.exec(`git remote add ${libName} git@github.com:akan-team/${libName}.git`);
3935
- await workspace.exec(`git subtree add --prefix=libs/${libName} ${libName} main`);
3936
- }
3937
4529
  };
3938
4530
 
3939
4531
  // pkgs/@akanjs/cli/src/workspace/workspace.script.ts
3940
4532
  var WorkspaceScript = class {
3941
4533
  #runner = new WorkspaceRunner();
4534
+ applicationScript = new ApplicationScript();
4535
+ libraryScript = new LibraryScript();
3942
4536
  async createWorkspace(repoName, appName, dirname = ".") {
3943
4537
  const cwdPath = process.cwd();
3944
4538
  const workspaceRoot = import_path5.default.join(cwdPath, dirname, repoName);
@@ -3975,34 +4569,33 @@ var WorkspaceScript = class {
3975
4569
  await workspace.applyTemplate({
3976
4570
  basePath: ".",
3977
4571
  template: "workspaceRoot",
3978
- dict: { repoName, RepoName: capitalize(repoName) }
4572
+ dict: {
4573
+ repoName,
4574
+ RepoName: capitalize(repoName),
4575
+ appName,
4576
+ AppName: capitalize(appName),
4577
+ serveDomain: "localhost"
4578
+ }
3979
4579
  });
3980
4580
  workspace.log("Installing dependencies...");
3981
4581
  await workspace.spawn("pnpm", ["i"]);
3982
4582
  workspace.log("Initializing git repository and commit...");
3983
- await workspace.exec(`git init`);
3984
- await workspace.exec(`git add .`);
3985
- await workspace.exec(`git commit -m "Initial commit"`);
3986
- await installExternalLib("util", workspace);
3987
- await installExternalLib("shared", workspace);
4583
+ await workspace.commit("Initial commit", { init: true });
4584
+ await this.libraryScript.installLibrary(workspace, "util");
4585
+ await this.libraryScript.installLibrary(workspace, "shared");
4586
+ await this.applicationScript.createApplication(appName, workspace);
3988
4587
  }
3989
4588
  async generateMongo(workspace) {
3990
4589
  await this.#runner.generateMongo(workspace);
3991
4590
  workspace.log(`Mongo connections generated in infra/master/mongo-connections.json`);
3992
4591
  }
3993
- async installLibrary(workspace, libName) {
3994
- await this.#runner.installLibrary(workspace, libName);
3995
- workspace.log(`${libName} library installed`);
3996
- }
3997
4592
  };
3998
4593
 
3999
4594
  // pkgs/@akanjs/cli/src/workspace/workspace.command.ts
4000
4595
  var WorkspaceCommand = class {
4001
4596
  workspaceScript = new WorkspaceScript();
4002
- async createWorkspace(name, dir, app) {
4003
- }
4004
- async installLibrary(name, workspace) {
4005
- await this.workspaceScript.installLibrary(workspace, name);
4597
+ async createWorkspace(name, app, dir) {
4598
+ await this.workspaceScript.createWorkspace(name, app, dir);
4006
4599
  }
4007
4600
  async generateMongo(workspace) {
4008
4601
  await this.workspaceScript.generateMongo(workspace);
@@ -4011,14 +4604,9 @@ var WorkspaceCommand = class {
4011
4604
  __decorateClass([
4012
4605
  Target.Public(),
4013
4606
  __decorateParam(0, Option("name", { desc: "name of workspace" })),
4014
- __decorateParam(1, Option("dir", { desc: "directory of workspace" })),
4015
- __decorateParam(2, Option("app", { desc: "application name" }))
4607
+ __decorateParam(1, Option("app", { desc: "application name" })),
4608
+ __decorateParam(2, Option("dir", { desc: "directory of workspace", default: process.env.USE_AKANJS_PKGS === "true" ? "local" : "." }))
4016
4609
  ], WorkspaceCommand.prototype, "createWorkspace", 1);
4017
- __decorateClass([
4018
- Target.Public(),
4019
- __decorateParam(0, Option("name", { desc: "name of library" })),
4020
- __decorateParam(1, Workspace())
4021
- ], WorkspaceCommand.prototype, "installLibrary", 1);
4022
4610
  __decorateClass([
4023
4611
  Target.Public(),
4024
4612
  __decorateParam(0, Workspace())