@akanjs/cli 0.9.32 → 0.9.34

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 (32) hide show
  1. package/cjs/index.js +128 -108
  2. package/cjs/src/templates/app/app/[lang]/{(__appName__)/layout.js → layout.js} +1 -1
  3. package/cjs/src/templates/app/app/[lang]/{(__appName__)/(public)/page.js → page.js} +1 -1
  4. package/cjs/src/templates/app/app/[lang]/{(__appName__)/(public)/unknown → unknown}/page.js +1 -1
  5. package/cjs/src/templates/crudPages/[__model__Id]/edit/page.js +1 -1
  6. package/cjs/src/templates/crudPages/[__model__Id]/page.js +2 -3
  7. package/cjs/src/templates/crudPages/new/page.js +2 -2
  8. package/cjs/src/templates/crudPages/page.js +2 -2
  9. package/cjs/src/templates/module/__Model__.View.js +5 -6
  10. package/esm/index.js +128 -108
  11. package/esm/src/templates/app/app/[lang]/{(__appName__)/layout.js → layout.js} +1 -1
  12. package/esm/src/templates/app/app/[lang]/{(__appName__)/(public)/page.js → page.js} +1 -1
  13. package/esm/src/templates/app/app/[lang]/{(__appName__)/(public)/unknown → unknown}/page.js +1 -1
  14. package/esm/src/templates/crudPages/[__model__Id]/edit/page.js +1 -1
  15. package/esm/src/templates/crudPages/[__model__Id]/page.js +2 -3
  16. package/esm/src/templates/crudPages/new/page.js +2 -2
  17. package/esm/src/templates/crudPages/page.js +2 -2
  18. package/esm/src/templates/module/__Model__.View.js +5 -6
  19. package/package.json +1 -1
  20. package/src/module/module.command.d.ts +1 -1
  21. package/src/module/module.script.d.ts +9 -5
  22. package/src/page/page.command.d.ts +2 -2
  23. package/src/page/page.runner.d.ts +6 -2
  24. package/src/page/page.script.d.ts +6 -2
  25. package/cjs/src/templates/app/app/[lang]/admin/layout.js +0 -54
  26. package/esm/src/templates/app/app/[lang]/admin/layout.js +0 -34
  27. package/src/templates/app/app/[lang]/admin/layout.d.ts +0 -9
  28. /package/cjs/src/templates/app/app/[lang]/{(__appName__)/styles.css.template → styles.css.template} +0 -0
  29. /package/esm/src/templates/app/app/[lang]/{(__appName__)/styles.css.template → styles.css.template} +0 -0
  30. /package/src/templates/app/app/[lang]/{(__appName__)/layout.d.ts → layout.d.ts} +0 -0
  31. /package/src/templates/app/app/[lang]/{(__appName__)/(public)/page.d.ts → page.d.ts} +0 -0
  32. /package/src/templates/app/app/[lang]/{(__appName__)/(public)/unknown → unknown}/page.d.ts +0 -0
package/cjs/index.js CHANGED
@@ -717,6 +717,44 @@ import config from "./akan.config";
717
717
  export default getNextConfig(config, appInfo);
718
718
  `;
719
719
 
720
+ // pkgs/@akanjs/config/src/types.ts
721
+ var archs = ["amd64", "arm64"];
722
+ var getDefaultFileScan = () => ({
723
+ constants: {
724
+ databases: [],
725
+ scalars: []
726
+ },
727
+ dictionary: {
728
+ databases: [],
729
+ services: [],
730
+ scalars: []
731
+ },
732
+ documents: {
733
+ databases: [],
734
+ scalars: []
735
+ },
736
+ services: {
737
+ databases: [],
738
+ services: [],
739
+ scalars: []
740
+ },
741
+ signal: {
742
+ databases: [],
743
+ services: [],
744
+ scalars: []
745
+ },
746
+ store: {
747
+ databases: [],
748
+ services: [],
749
+ scalars: []
750
+ },
751
+ components: {
752
+ databases: [],
753
+ services: [],
754
+ scalars: []
755
+ }
756
+ });
757
+
720
758
  // pkgs/@akanjs/config/src/akanConfig.ts
721
759
  var makeAppConfig = (config, props) => {
722
760
  const { name, repoName, serveDomain, env, command = "build" } = props;
@@ -840,7 +878,7 @@ WORKDIR /workspace
840
878
  COPY ./package.json ./package.json
841
879
  RUN npx pnpm i --prod
842
880
  COPY . .
843
- ENV PORT 4200
881
+ ENV PORT=4200
844
882
  ENV NODE_OPTIONS=--max_old_space_size=8192
845
883
  ENV NEXT_PUBLIC_REPO_NAME=${repoName}
846
884
  ENV NEXT_PUBLIC_SERVE_DOMAIN=${serveDomain}
@@ -859,44 +897,6 @@ CMD [${command.map((c) => `"${c}"`).join(",")}]`;
859
897
  }
860
898
  };
861
899
 
862
- // pkgs/@akanjs/config/src/types.ts
863
- var archs = ["amd64", "arm64"];
864
- var getDefaultFileScan = () => ({
865
- constants: {
866
- databases: [],
867
- scalars: []
868
- },
869
- dictionary: {
870
- databases: [],
871
- services: [],
872
- scalars: []
873
- },
874
- documents: {
875
- databases: [],
876
- scalars: []
877
- },
878
- services: {
879
- databases: [],
880
- services: [],
881
- scalars: []
882
- },
883
- signal: {
884
- databases: [],
885
- services: [],
886
- scalars: []
887
- },
888
- store: {
889
- databases: [],
890
- services: [],
891
- scalars: []
892
- },
893
- components: {
894
- databases: [],
895
- services: [],
896
- scalars: []
897
- }
898
- });
899
-
900
900
  // pkgs/@akanjs/devkit/src/executors.ts
901
901
  var import_chalk3 = __toESM(require("chalk"));
902
902
  var import_child_process = require("child_process");
@@ -1790,10 +1790,11 @@ var WorkspaceExecutor = class _WorkspaceExecutor extends Executor {
1790
1790
  const serveDomain = process.env.NEXT_PUBLIC_SERVE_DOMAIN ?? envFile.NEXT_PUBLIC_SERVE_DOMAIN;
1791
1791
  if (!serveDomain)
1792
1792
  throw new Error("NEXT_PUBLIC_SERVE_DOMAIN is not set");
1793
+ const portOffset = parseInt(process.env.PORT_OFFSET ?? envFile.PORT_OFFSET ?? "0");
1793
1794
  const env = process.env.NEXT_PUBLIC_ENV ?? envFile.NEXT_PUBLIC_ENV ?? "debug";
1794
1795
  if (!env)
1795
1796
  throw new Error("NEXT_PUBLIC_ENV is not set");
1796
- return { ...appName ? { name: appName } : {}, repoName, serveDomain, env };
1797
+ return { ...appName ? { name: appName } : {}, repoName, serveDomain, env, portOffset };
1797
1798
  }
1798
1799
  async scan() {
1799
1800
  const [appNames, libNames, pkgNames] = await Promise.all([this.getApps(), this.getLibs(), this.getPkgs()]);
@@ -3412,9 +3413,9 @@ var import_dotenv2 = __toESM(require("dotenv"), 1);
3412
3413
  var LibraryRunner = class {
3413
3414
  async createLibrary(libName, workspace) {
3414
3415
  await workspace.exec(`mkdir -p libs/${libName}`);
3415
- const lib = LibExecutor.from(workspace, libName);
3416
- await lib.applyTemplate({ basePath: ".", template: "libRoot", dict: { libName } });
3416
+ await workspace.applyTemplate({ basePath: `libs/${libName}`, template: "libRoot", dict: { libName } });
3417
3417
  workspace.setTsPaths("lib", libName);
3418
+ const lib = LibExecutor.from(workspace, libName);
3418
3419
  return lib;
3419
3420
  }
3420
3421
  async removeLibrary(lib) {
@@ -3909,17 +3910,23 @@ var ApplicationRunner = class {
3909
3910
  });
3910
3911
  await app.spawn("node", [`scripts/${filename}.js`], {
3911
3912
  stdio: "inherit",
3912
- env: this.#getEnv(app)
3913
+ env: this.#getEnv(app, "backend")
3913
3914
  });
3914
3915
  }
3915
- #getEnv(app, env = {}) {
3916
+ #getEnv(app, target, env = {}) {
3916
3917
  const rootEnv = import_dotenv3.default.parse(app.workspace.readFile(".env"));
3918
+ const basePort = target === "backend" ? 8080 : target === "frontend" ? 4200 : target === "csr" ? 4201 : void 0;
3919
+ const portOffset = app.workspace.getBaseDevEnv().portOffset;
3920
+ const PORT = basePort ? (basePort + portOffset).toString() : void 0;
3921
+ const NEXT_PUBLIC_SERVER_PORT = portOffset ? (8080 + portOffset).toString() : void 0;
3917
3922
  return {
3918
3923
  ...process.env,
3919
3924
  ...rootEnv,
3920
3925
  NEXT_PUBLIC_APP_NAME: app.name,
3921
3926
  AKAN_WORKSPACE_ROOT: app.workspace.workspaceRoot,
3922
3927
  NODE_NO_WARNINGS: "1",
3928
+ ...PORT ? { PORT, NEXT_PUBLIC_CLIENT_PORT: PORT } : {},
3929
+ ...NEXT_PUBLIC_SERVER_PORT ? { NEXT_PUBLIC_SERVER_PORT } : {},
3923
3930
  ...env
3924
3931
  };
3925
3932
  }
@@ -3933,7 +3940,7 @@ var ApplicationRunner = class {
3933
3940
  await app.workspace.exec("rm -rf node_modules/.vite");
3934
3941
  else if (target === "backend")
3935
3942
  await app.cp("assets", import_path4.default.join(app.dist.cwdPath, "backend", "assets"));
3936
- return { env: this.#getEnv(app, { AKAN_COMMAND_TYPE: type }) };
3943
+ return { env: this.#getEnv(app, target, { AKAN_COMMAND_TYPE: type }) };
3937
3944
  }
3938
3945
  async buildBackend(app) {
3939
3946
  await this.#prepareCommand(app, "start", "backend");
@@ -4026,15 +4033,16 @@ var ApplicationRunner = class {
4026
4033
  } = {}) {
4027
4034
  const { env } = await this.#prepareCommand(app, "start", "frontend");
4028
4035
  if (open2)
4029
- setTimeout(() => (0, import_open.default)("http://localhost:4200"), 3e3);
4036
+ setTimeout(() => (0, import_open.default)(`http://localhost:${env.PORT ?? 4200}`), 3e3);
4030
4037
  onStart?.();
4031
- return app.spawnSync("npx", ["next", "dev", "-p", "4200", ...turbo ? ["--turbo"] : []], {
4038
+ return app.spawnSync("npx", ["next", "dev", ...env.PORT ? ["-p", env.PORT] : [], ...turbo ? ["--turbo"] : []], {
4032
4039
  env,
4033
4040
  stdio: withInk ? ["ignore", "pipe", "pipe"] : "inherit"
4034
4041
  });
4035
4042
  }
4036
4043
  async #getViteConfig(app, command, viteConfig = {}) {
4037
4044
  const { env } = await this.#prepareCommand(app, command, "csr");
4045
+ const { NODE_ENV, NODE_NO_WARNINGS, ...applyEnvs } = env;
4038
4046
  const tsconfig = app.workspace.getTsConfig();
4039
4047
  const akanConfig = await app.getConfig();
4040
4048
  const basePaths = akanConfig.frontend.routes ? [...new Set(akanConfig.frontend.routes.map(({ basePath: basePath2 }) => basePath2))].join(",") : void 0;
@@ -4094,13 +4102,13 @@ var ApplicationRunner = class {
4094
4102
  },
4095
4103
  define: {
4096
4104
  "process.env": {
4105
+ ...applyEnvs,
4097
4106
  AKAN_COMMAND_TYPE: "start",
4098
4107
  NEXT_PUBLIC_REPO_NAME: app.workspace.repoName,
4099
4108
  NEXT_PUBLIC_SERVE_DOMAIN: processEnv.NEXT_PUBLIC_SERVE_DOMAIN ?? "localhost",
4100
4109
  NEXT_PUBLIC_ENV: processEnv.NEXT_PUBLIC_ENV ?? "debug",
4101
4110
  NEXT_PUBLIC_OPERATION_MODE: processEnv.NEXT_PUBLIC_OPERATION_MODE ?? "local",
4102
4111
  NEXT_PUBLIC_LOG_LEVEL: processEnv.NEXT_PUBLIC_LOG_LEVEL ?? "log",
4103
- NEXT_PUBLIC_APP_NAME: app.name,
4104
4112
  APP_OPERATION_MODE: processEnv.APP_OPERATION_MODE ?? "local",
4105
4113
  AKAN_WORKSPACE_ROOT: app.workspace.workspaceRoot,
4106
4114
  AKAN_APP_ROOT: app.cwdPath,
@@ -4149,7 +4157,7 @@ var ApplicationRunner = class {
4149
4157
  } : {}
4150
4158
  );
4151
4159
  const server = await vite.createServer(config);
4152
- await server.listen(4201);
4160
+ await server.listen(4201 + app.workspace.getBaseDevEnv().portOffset);
4153
4161
  onStart?.();
4154
4162
  if (open2)
4155
4163
  setTimeout(() => (0, import_open.default)("http://localhost:4201"), 3e3);
@@ -4399,7 +4407,7 @@ var ApplicationRunner = class {
4399
4407
  ["node_modules/jest/bin/jest.js", `apps/${app.name}`, "-c", `apps/${app.name}/jest.config.ts`],
4400
4408
  {
4401
4409
  env: {
4402
- ...this.#getEnv(app),
4410
+ ...this.#getEnv(app, "backend"),
4403
4411
  NEXT_PUBLIC_ENV: "testing",
4404
4412
  NEXT_PUBLIC_OPERATION_MODE: "local",
4405
4413
  NEXT_PUBLIC_APP_NAME: app.name,
@@ -5218,6 +5226,25 @@ LibraryCommand = __decorateClass([
5218
5226
  // pkgs/@akanjs/cli/src/module/module.script.ts
5219
5227
  var import_fs11 = __toESM(require("fs"), 1);
5220
5228
 
5229
+ // pkgs/@akanjs/cli/src/page/page.runner.ts
5230
+ var PageRunner = class {
5231
+ async createCrudPage(module2, { app, basePath: basePath2, single = false }) {
5232
+ await app.applyTemplate({
5233
+ basePath: basePath2 ?? `app/[lang]/(${app.name})/(public)/${module2.name}`,
5234
+ template: single ? "crudSinglePage" : "crudPages",
5235
+ dict: { model: module2.name, appName: module2.sys.name }
5236
+ });
5237
+ }
5238
+ };
5239
+
5240
+ // pkgs/@akanjs/cli/src/page/page.script.ts
5241
+ var PageScript = class {
5242
+ #runner = new PageRunner();
5243
+ async createCrudPage(module2, { app, basePath: basePath2, single = false }) {
5244
+ await this.#runner.createCrudPage(module2, { app, basePath: basePath2, single });
5245
+ }
5246
+ };
5247
+
5221
5248
  // pkgs/@akanjs/cli/src/module/module.prompt.ts
5222
5249
  var componentDefaultDescription = ({
5223
5250
  modelName,
@@ -5592,10 +5619,13 @@ var ModuleRunner = class {
5592
5619
 
5593
5620
  // pkgs/@akanjs/cli/src/module/module.script.ts
5594
5621
  var ModuleScript = class {
5622
+ pageScript = new PageScript();
5595
5623
  #runner = new ModuleRunner();
5596
- async createModuleTemplate(sys3, name) {
5597
- const executor = ModuleExecutor.from(sys3, name);
5598
- await this.#runner.createModuleTemplate(executor);
5624
+ async createModuleTemplate(sys3, name, { page = false } = {}) {
5625
+ const mod = ModuleExecutor.from(sys3, name);
5626
+ await this.#runner.createModuleTemplate(mod);
5627
+ if (page && sys3.type === "app")
5628
+ await this.pageScript.createCrudPage(mod, { app: sys3, basePath: null, single: false });
5599
5629
  const akanConfig = await sys3.getConfig();
5600
5630
  await sys3.scan({ akanConfig });
5601
5631
  }
@@ -5646,25 +5676,25 @@ var ModuleScript = class {
5646
5676
  await this.createTemplate(executor);
5647
5677
  sys3.log(`Module ${name} created in ${sys3.type}s/${sys3.name}/lib/${name}`);
5648
5678
  }
5649
- removeModule(module2) {
5650
- this.#runner.removeModule(module2);
5679
+ removeModule(mod) {
5680
+ this.#runner.removeModule(mod);
5651
5681
  }
5652
5682
  async createService(workspace, name) {
5653
5683
  }
5654
5684
  async createTest(workspace, name) {
5655
5685
  }
5656
- async createTemplate(module2) {
5657
- const { component: template } = await this.#runner.createComponentTemplate(module2, "template");
5658
- const templateExampleFiles = (await module2.sys.getTemplatesSourceCode()).filter(
5659
- (f) => !f.filePath.includes(`${module2.name}.Template.tsx`)
5686
+ async createTemplate(mod) {
5687
+ const { component: template } = await this.#runner.createComponentTemplate(mod, "template");
5688
+ const templateExampleFiles = (await mod.sys.getTemplatesSourceCode()).filter(
5689
+ (f) => !f.filePath.includes(`${mod.name}.Template.tsx`)
5660
5690
  );
5661
- const Name = capitalize(module2.name);
5662
- const relatedCnsts = getRelatedCnsts(`${module2.sys.cwdPath}/lib/${module2.name}/${module2.name}.constant.ts`);
5663
- const constant = import_fs11.default.readFileSync(`${module2.sys.cwdPath}/lib/${module2.name}/${module2.name}.constant.ts`, "utf-8");
5664
- const session = new AiSession("createTemplate", { workspace: module2.sys.workspace, cacheKey: module2.name });
5691
+ const Name = capitalize(mod.name);
5692
+ const relatedCnsts = getRelatedCnsts(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`);
5693
+ const constant = import_fs11.default.readFileSync(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`, "utf-8");
5694
+ const session = new AiSession("createTemplate", { workspace: mod.sys.workspace, cacheKey: mod.name });
5665
5695
  const promptRst = requestTemplate({
5666
- sysName: module2.sys.name,
5667
- modelName: module2.name,
5696
+ sysName: mod.sys.name,
5697
+ modelName: mod.name,
5668
5698
  ModelName: Name,
5669
5699
  constant,
5670
5700
  boilerplate: template.content,
@@ -5672,20 +5702,20 @@ var ModuleScript = class {
5672
5702
  exampleFiles: randomPicks(templateExampleFiles, Math.min(20, templateExampleFiles.length))
5673
5703
  });
5674
5704
  const content = await session.editTypescript(promptRst);
5675
- module2.writeFile(`${Name}.Template.tsx`, content);
5705
+ mod.writeFile(`${Name}.Template.tsx`, content);
5676
5706
  }
5677
- async createUnit(module2) {
5678
- const { component: unit } = await this.#runner.createComponentTemplate(module2, "unit");
5679
- const Name = capitalize(module2.name);
5680
- const unitExampleFiles = (await module2.sys.getUnitsSourceCode()).filter(
5681
- (f) => !f.filePath.includes(`${module2.name}.Unit.tsx`)
5707
+ async createUnit(mod) {
5708
+ const { component: unit } = await this.#runner.createComponentTemplate(mod, "unit");
5709
+ const Name = capitalize(mod.name);
5710
+ const unitExampleFiles = (await mod.sys.getUnitsSourceCode()).filter(
5711
+ (f) => !f.filePath.includes(`${mod.name}.Unit.tsx`)
5682
5712
  );
5683
- const relatedCnsts = getRelatedCnsts(`${module2.sys.cwdPath}/lib/${module2.name}/${module2.name}.constant.ts`);
5684
- const constant = import_fs11.default.readFileSync(`${module2.sys.cwdPath}/lib/${module2.name}/${module2.name}.constant.ts`, "utf-8");
5685
- const session = new AiSession("createUnit", { workspace: module2.sys.workspace, cacheKey: module2.name });
5713
+ const relatedCnsts = getRelatedCnsts(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`);
5714
+ const constant = import_fs11.default.readFileSync(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`, "utf-8");
5715
+ const session = new AiSession("createUnit", { workspace: mod.sys.workspace, cacheKey: mod.name });
5686
5716
  const promptRst = requestUnit({
5687
- sysName: module2.sys.name,
5688
- modelName: module2.name,
5717
+ sysName: mod.sys.name,
5718
+ modelName: mod.name,
5689
5719
  ModelName: Name,
5690
5720
  constant,
5691
5721
  properties: relatedCnsts.map((r) => ({ key: r.key, source: r.source })),
@@ -5693,20 +5723,20 @@ var ModuleScript = class {
5693
5723
  boilerplate: unit.content
5694
5724
  });
5695
5725
  const content = await session.editTypescript(promptRst);
5696
- module2.writeFile(`${Name}.Unit.tsx`, content);
5726
+ mod.writeFile(`${Name}.Unit.tsx`, content);
5697
5727
  }
5698
- async createView(module2) {
5699
- const { component: view } = await this.#runner.createComponentTemplate(module2, "view");
5700
- const viewExampleFiles = (await module2.sys.getViewsSourceCode()).filter(
5701
- (f) => !f.filePath.includes(`${module2.name}.View.tsx`)
5728
+ async createView(mod) {
5729
+ const { component: view } = await this.#runner.createComponentTemplate(mod, "view");
5730
+ const viewExampleFiles = (await mod.sys.getViewsSourceCode()).filter(
5731
+ (f) => !f.filePath.includes(`${mod.name}.View.tsx`)
5702
5732
  );
5703
- const Name = capitalize(module2.name);
5704
- const relatedCnsts = getRelatedCnsts(`${module2.sys.cwdPath}/lib/${module2.name}/${module2.name}.constant.ts`);
5705
- const constant = import_fs11.default.readFileSync(`${module2.sys.cwdPath}/lib/${module2.name}/${module2.name}.constant.ts`, "utf-8");
5706
- const session = new AiSession("createView", { workspace: module2.sys.workspace, cacheKey: module2.name });
5733
+ const Name = capitalize(mod.name);
5734
+ const relatedCnsts = getRelatedCnsts(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`);
5735
+ const constant = import_fs11.default.readFileSync(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`, "utf-8");
5736
+ const session = new AiSession("createView", { workspace: mod.sys.workspace, cacheKey: mod.name });
5707
5737
  const promptRst = requestView({
5708
- sysName: module2.sys.name,
5709
- modelName: module2.name,
5738
+ sysName: mod.sys.name,
5739
+ modelName: mod.name,
5710
5740
  ModelName: Name,
5711
5741
  constant,
5712
5742
  boilerplate: view.content,
@@ -5714,16 +5744,16 @@ var ModuleScript = class {
5714
5744
  exampleFiles: randomPicks(viewExampleFiles, Math.min(20, viewExampleFiles.length))
5715
5745
  });
5716
5746
  const content = await session.editTypescript(promptRst);
5717
- module2.writeFile(`${Name}.View.tsx`, content);
5747
+ mod.writeFile(`${Name}.View.tsx`, content);
5718
5748
  }
5719
5749
  };
5720
5750
 
5721
5751
  // pkgs/@akanjs/cli/src/module/module.command.ts
5722
5752
  var ModuleCommand = class {
5723
5753
  moduleScript = new ModuleScript();
5724
- async createModule(moduleName, sys3) {
5754
+ async createModule(moduleName, sys3, page) {
5725
5755
  const name = lowerlize(moduleName.replace(/ /g, ""));
5726
- await this.moduleScript.createModuleTemplate(sys3, name);
5756
+ await this.moduleScript.createModuleTemplate(sys3, name, { page });
5727
5757
  }
5728
5758
  removeModule(module2) {
5729
5759
  this.moduleScript.removeModule(module2);
@@ -5741,7 +5771,8 @@ var ModuleCommand = class {
5741
5771
  __decorateClass([
5742
5772
  Target.Public(),
5743
5773
  __decorateParam(0, Argument("moduleName", { desc: "name of module" })),
5744
- __decorateParam(1, Sys())
5774
+ __decorateParam(1, Sys()),
5775
+ __decorateParam(2, Option("page", { type: "boolean", desc: "create page", default: false }))
5745
5776
  ], ModuleCommand.prototype, "createModule", 1);
5746
5777
  __decorateClass([
5747
5778
  Target.Public(),
@@ -5807,31 +5838,20 @@ PackageCommand = __decorateClass([
5807
5838
  Commands()
5808
5839
  ], PackageCommand);
5809
5840
 
5810
- // pkgs/@akanjs/cli/src/page/page.runner.ts
5811
- var PageRunner = class {
5812
- async createPage(app, name) {
5813
- }
5814
- };
5815
-
5816
- // pkgs/@akanjs/cli/src/page/page.script.ts
5817
- var PageScript = class {
5818
- #runner = new PageRunner();
5819
- async createPage(app, name) {
5820
- await this.#runner.createPage(app, name);
5821
- }
5822
- };
5823
-
5824
5841
  // pkgs/@akanjs/cli/src/page/page.command.ts
5825
5842
  var PageCommand = class {
5826
5843
  pageScript = new PageScript();
5827
- async createPage(app, name) {
5844
+ async createCrudPage(app, module2, basePath2, single) {
5845
+ await this.pageScript.createCrudPage(module2, { app, basePath: basePath2, single });
5828
5846
  }
5829
5847
  };
5830
5848
  __decorateClass([
5831
5849
  Target.Public(),
5832
5850
  __decorateParam(0, App()),
5833
- __decorateParam(1, Option("name", { desc: "name of page" }))
5834
- ], PageCommand.prototype, "createPage", 1);
5851
+ __decorateParam(1, Module()),
5852
+ __decorateParam(2, Option("basePath", { desc: "base path", nullable: true })),
5853
+ __decorateParam(3, Option("single", { desc: "single page", default: false }))
5854
+ ], PageCommand.prototype, "createCrudPage", 1);
5835
5855
  PageCommand = __decorateClass([
5836
5856
  Commands()
5837
5857
  ], PageCommand);
@@ -16,7 +16,7 @@ var __copyProps = (to, from, except, desc) => {
16
16
  };
17
17
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
18
 
19
- // pkgs/@akanjs/cli/src/templates/app/app/[lang]/(__appName__)/layout.tsx
19
+ // pkgs/@akanjs/cli/src/templates/app/app/[lang]/layout.tsx
20
20
  var layout_exports = {};
21
21
  __export(layout_exports, {
22
22
  default: () => getContent
@@ -16,7 +16,7 @@ var __copyProps = (to, from, except, desc) => {
16
16
  };
17
17
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
18
 
19
- // pkgs/@akanjs/cli/src/templates/app/app/[lang]/(__appName__)/(public)/page.tsx
19
+ // pkgs/@akanjs/cli/src/templates/app/app/[lang]/page.tsx
20
20
  var page_exports = {};
21
21
  __export(page_exports, {
22
22
  default: () => getContent
@@ -16,7 +16,7 @@ var __copyProps = (to, from, except, desc) => {
16
16
  };
17
17
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
18
 
19
- // pkgs/@akanjs/cli/src/templates/app/app/[lang]/(__appName__)/(public)/unknown/page.tsx
19
+ // pkgs/@akanjs/cli/src/templates/app/app/[lang]/unknown/page.tsx
20
20
  var page_exports = {};
21
21
  __export(page_exports, {
22
22
  default: () => getContent
@@ -59,7 +59,7 @@ export default function Page({ params }: PageProps) {
59
59
  onCancel="back"
60
60
  onSubmit="/${dict.model}"
61
61
  >
62
- ${dict.Model}.Template.General
62
+ <${dict.Model}.Template.General />
63
63
  </Load.Edit>
64
64
  </div>
65
65
  )}
@@ -27,8 +27,7 @@ function getContent(scanResult, dict) {
27
27
  filename: "page.tsx",
28
28
  content: `
29
29
  import { ${dict.Model}, fetch, usePage } from "${dict.appName}/client";
30
- import { Link } from "@akanjs/ui";
31
- import { Load } from "@akanjs/ui";
30
+ import { Link, Load } from "@akanjs/ui";
32
31
  import type { CsrConfig } from "@akanjs/client";
33
32
 
34
33
  interface PageProps {
@@ -61,7 +60,7 @@ export default function Page({ params }: PageProps) {
61
60
  render={({ ${dict.model}, ${dict.model}View }) => (
62
61
  <div className="container flex flex-col gap-4">
63
62
  <div className="flex gap-4 font-bold text-lg items-center">
64
- ${dict.Model}.Zone.View view={${dict.model}View} />
63
+ <${dict.Model}.Zone.View view={${dict.model}View} />
65
64
  <Link href={\`/${dict.model}/\${${dict.model}.id}/edit\`}>
66
65
  <button className="btn">
67
66
  {l("shared.updateModel", { model: l("${dict.model}.modelName") })}
@@ -27,7 +27,7 @@ function getContent(scanResult, dict) {
27
27
  filename: "page.tsx",
28
28
  content: `
29
29
  import { Load } from "@akanjs/ui";
30
- import { cnst, fetch, usePage, ${dict.Model} } from "${dict.appName}/client";
30
+ import { cnst, fetch, usePage, ${dict.Model} } from "@${dict.appName}/client";
31
31
  import type { CsrConfig } from "@akanjs/client";
32
32
 
33
33
  export default function Page() {
@@ -54,7 +54,7 @@ export default function Page() {
54
54
  onCancel="back"
55
55
  onSubmit="/${dict.model}"
56
56
  >
57
- ${dict.Model}.Template.General
57
+ <${dict.Model}.Template.General />
58
58
  </Load.Edit>
59
59
  </div>
60
60
  )}
@@ -26,7 +26,7 @@ function getContent(scanResult, dict) {
26
26
  return {
27
27
  filename: "page.tsx",
28
28
  content: `
29
- import { ${dict.Model}, fetch, usePage } from "${dict.appName}/client";
29
+ import { ${dict.Model}, fetch, usePage } from "@${dict.appName}/client";
30
30
  import { Link, Load } from "@akanjs/ui";
31
31
  import type { CsrConfig } from "@akanjs/client";
32
32
 
@@ -51,7 +51,7 @@ export default function Page() {
51
51
  </div>
52
52
  <div>{l("${dict.model}.modelDesc")}</div>
53
53
  <div className="flex px-6 mt-3 gap-4">
54
- ${dict.Model}.Zone.Card
54
+ <${dict.Model}.Zone.Card
55
55
  className="animate-fadeIn grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 justify-center gap-4 w-full"
56
56
  init={${dict.model}InitInPublic}
57
57
  />
@@ -27,19 +27,18 @@ function getContent(scanResult, dict) {
27
27
  filename: `${dict.Model}.View.tsx`,
28
28
  content: `
29
29
  import { clsx } from "@akanjs/client";
30
- import { cnst } from "@${dict.sysName}/client";
31
- import { Image } from "@akanjs/ui";
30
+ import { cnst, usePage } from "@${dict.sysName}/client";
32
31
 
33
32
  interface ${dict.Model}ViewProps {
34
33
  className?: string;
35
34
  ${dict.model}: cnst.${dict.Model};
36
- self?: { id?: string } | null;
37
35
  }
38
36
 
39
- export const General = ({ className, ${dict.model}, self }: ${dict.Model}ViewProps) => {
37
+ export const General = ({ className, ${dict.model} }: ${dict.Model}ViewProps) => {
38
+ const { l } = usePage();
40
39
  return (
41
- <div className={clsx(className, "animate-fadeIn w-full")}>
42
- <div>{${dict.model}.id}</div>
40
+ <div className={clsx("w-full", className)}>
41
+ <div>{l("${dict.model}.id")}: {${dict.model}.id}</div>
43
42
  </div>
44
43
  );
45
44
  };
package/esm/index.js CHANGED
@@ -697,6 +697,44 @@ import config from "./akan.config";
697
697
  export default getNextConfig(config, appInfo);
698
698
  `;
699
699
 
700
+ // pkgs/@akanjs/config/src/types.ts
701
+ var archs = ["amd64", "arm64"];
702
+ var getDefaultFileScan = () => ({
703
+ constants: {
704
+ databases: [],
705
+ scalars: []
706
+ },
707
+ dictionary: {
708
+ databases: [],
709
+ services: [],
710
+ scalars: []
711
+ },
712
+ documents: {
713
+ databases: [],
714
+ scalars: []
715
+ },
716
+ services: {
717
+ databases: [],
718
+ services: [],
719
+ scalars: []
720
+ },
721
+ signal: {
722
+ databases: [],
723
+ services: [],
724
+ scalars: []
725
+ },
726
+ store: {
727
+ databases: [],
728
+ services: [],
729
+ scalars: []
730
+ },
731
+ components: {
732
+ databases: [],
733
+ services: [],
734
+ scalars: []
735
+ }
736
+ });
737
+
700
738
  // pkgs/@akanjs/config/src/akanConfig.ts
701
739
  var makeAppConfig = (config, props) => {
702
740
  const { name, repoName, serveDomain, env, command = "build" } = props;
@@ -820,7 +858,7 @@ WORKDIR /workspace
820
858
  COPY ./package.json ./package.json
821
859
  RUN npx pnpm i --prod
822
860
  COPY . .
823
- ENV PORT 4200
861
+ ENV PORT=4200
824
862
  ENV NODE_OPTIONS=--max_old_space_size=8192
825
863
  ENV NEXT_PUBLIC_REPO_NAME=${repoName}
826
864
  ENV NEXT_PUBLIC_SERVE_DOMAIN=${serveDomain}
@@ -839,44 +877,6 @@ CMD [${command.map((c) => `"${c}"`).join(",")}]`;
839
877
  }
840
878
  };
841
879
 
842
- // pkgs/@akanjs/config/src/types.ts
843
- var archs = ["amd64", "arm64"];
844
- var getDefaultFileScan = () => ({
845
- constants: {
846
- databases: [],
847
- scalars: []
848
- },
849
- dictionary: {
850
- databases: [],
851
- services: [],
852
- scalars: []
853
- },
854
- documents: {
855
- databases: [],
856
- scalars: []
857
- },
858
- services: {
859
- databases: [],
860
- services: [],
861
- scalars: []
862
- },
863
- signal: {
864
- databases: [],
865
- services: [],
866
- scalars: []
867
- },
868
- store: {
869
- databases: [],
870
- services: [],
871
- scalars: []
872
- },
873
- components: {
874
- databases: [],
875
- services: [],
876
- scalars: []
877
- }
878
- });
879
-
880
880
  // pkgs/@akanjs/devkit/src/executors.ts
881
881
  import chalk3 from "chalk";
882
882
  import { exec, fork, spawn } from "child_process";
@@ -1769,10 +1769,11 @@ var WorkspaceExecutor = class _WorkspaceExecutor extends Executor {
1769
1769
  const serveDomain = process.env.NEXT_PUBLIC_SERVE_DOMAIN ?? envFile.NEXT_PUBLIC_SERVE_DOMAIN;
1770
1770
  if (!serveDomain)
1771
1771
  throw new Error("NEXT_PUBLIC_SERVE_DOMAIN is not set");
1772
+ const portOffset = parseInt(process.env.PORT_OFFSET ?? envFile.PORT_OFFSET ?? "0");
1772
1773
  const env = process.env.NEXT_PUBLIC_ENV ?? envFile.NEXT_PUBLIC_ENV ?? "debug";
1773
1774
  if (!env)
1774
1775
  throw new Error("NEXT_PUBLIC_ENV is not set");
1775
- return { ...appName ? { name: appName } : {}, repoName, serveDomain, env };
1776
+ return { ...appName ? { name: appName } : {}, repoName, serveDomain, env, portOffset };
1776
1777
  }
1777
1778
  async scan() {
1778
1779
  const [appNames, libNames, pkgNames] = await Promise.all([this.getApps(), this.getLibs(), this.getPkgs()]);
@@ -3394,9 +3395,9 @@ import dotenv2 from "dotenv";
3394
3395
  var LibraryRunner = class {
3395
3396
  async createLibrary(libName, workspace) {
3396
3397
  await workspace.exec(`mkdir -p libs/${libName}`);
3397
- const lib = LibExecutor.from(workspace, libName);
3398
- await lib.applyTemplate({ basePath: ".", template: "libRoot", dict: { libName } });
3398
+ await workspace.applyTemplate({ basePath: `libs/${libName}`, template: "libRoot", dict: { libName } });
3399
3399
  workspace.setTsPaths("lib", libName);
3400
+ const lib = LibExecutor.from(workspace, libName);
3400
3401
  return lib;
3401
3402
  }
3402
3403
  async removeLibrary(lib) {
@@ -3891,17 +3892,23 @@ var ApplicationRunner = class {
3891
3892
  });
3892
3893
  await app.spawn("node", [`scripts/${filename}.js`], {
3893
3894
  stdio: "inherit",
3894
- env: this.#getEnv(app)
3895
+ env: this.#getEnv(app, "backend")
3895
3896
  });
3896
3897
  }
3897
- #getEnv(app, env = {}) {
3898
+ #getEnv(app, target, env = {}) {
3898
3899
  const rootEnv = dotenv3.parse(app.workspace.readFile(".env"));
3900
+ const basePort = target === "backend" ? 8080 : target === "frontend" ? 4200 : target === "csr" ? 4201 : void 0;
3901
+ const portOffset = app.workspace.getBaseDevEnv().portOffset;
3902
+ const PORT = basePort ? (basePort + portOffset).toString() : void 0;
3903
+ const NEXT_PUBLIC_SERVER_PORT = portOffset ? (8080 + portOffset).toString() : void 0;
3899
3904
  return {
3900
3905
  ...process.env,
3901
3906
  ...rootEnv,
3902
3907
  NEXT_PUBLIC_APP_NAME: app.name,
3903
3908
  AKAN_WORKSPACE_ROOT: app.workspace.workspaceRoot,
3904
3909
  NODE_NO_WARNINGS: "1",
3910
+ ...PORT ? { PORT, NEXT_PUBLIC_CLIENT_PORT: PORT } : {},
3911
+ ...NEXT_PUBLIC_SERVER_PORT ? { NEXT_PUBLIC_SERVER_PORT } : {},
3905
3912
  ...env
3906
3913
  };
3907
3914
  }
@@ -3915,7 +3922,7 @@ var ApplicationRunner = class {
3915
3922
  await app.workspace.exec("rm -rf node_modules/.vite");
3916
3923
  else if (target === "backend")
3917
3924
  await app.cp("assets", path7.join(app.dist.cwdPath, "backend", "assets"));
3918
- return { env: this.#getEnv(app, { AKAN_COMMAND_TYPE: type }) };
3925
+ return { env: this.#getEnv(app, target, { AKAN_COMMAND_TYPE: type }) };
3919
3926
  }
3920
3927
  async buildBackend(app) {
3921
3928
  await this.#prepareCommand(app, "start", "backend");
@@ -4008,15 +4015,16 @@ var ApplicationRunner = class {
4008
4015
  } = {}) {
4009
4016
  const { env } = await this.#prepareCommand(app, "start", "frontend");
4010
4017
  if (open2)
4011
- setTimeout(() => openBrowser("http://localhost:4200"), 3e3);
4018
+ setTimeout(() => openBrowser(`http://localhost:${env.PORT ?? 4200}`), 3e3);
4012
4019
  onStart?.();
4013
- return app.spawnSync("npx", ["next", "dev", "-p", "4200", ...turbo ? ["--turbo"] : []], {
4020
+ return app.spawnSync("npx", ["next", "dev", ...env.PORT ? ["-p", env.PORT] : [], ...turbo ? ["--turbo"] : []], {
4014
4021
  env,
4015
4022
  stdio: withInk ? ["ignore", "pipe", "pipe"] : "inherit"
4016
4023
  });
4017
4024
  }
4018
4025
  async #getViteConfig(app, command, viteConfig = {}) {
4019
4026
  const { env } = await this.#prepareCommand(app, command, "csr");
4027
+ const { NODE_ENV, NODE_NO_WARNINGS, ...applyEnvs } = env;
4020
4028
  const tsconfig = app.workspace.getTsConfig();
4021
4029
  const akanConfig = await app.getConfig();
4022
4030
  const basePaths = akanConfig.frontend.routes ? [...new Set(akanConfig.frontend.routes.map(({ basePath: basePath2 }) => basePath2))].join(",") : void 0;
@@ -4076,13 +4084,13 @@ var ApplicationRunner = class {
4076
4084
  },
4077
4085
  define: {
4078
4086
  "process.env": {
4087
+ ...applyEnvs,
4079
4088
  AKAN_COMMAND_TYPE: "start",
4080
4089
  NEXT_PUBLIC_REPO_NAME: app.workspace.repoName,
4081
4090
  NEXT_PUBLIC_SERVE_DOMAIN: processEnv.NEXT_PUBLIC_SERVE_DOMAIN ?? "localhost",
4082
4091
  NEXT_PUBLIC_ENV: processEnv.NEXT_PUBLIC_ENV ?? "debug",
4083
4092
  NEXT_PUBLIC_OPERATION_MODE: processEnv.NEXT_PUBLIC_OPERATION_MODE ?? "local",
4084
4093
  NEXT_PUBLIC_LOG_LEVEL: processEnv.NEXT_PUBLIC_LOG_LEVEL ?? "log",
4085
- NEXT_PUBLIC_APP_NAME: app.name,
4086
4094
  APP_OPERATION_MODE: processEnv.APP_OPERATION_MODE ?? "local",
4087
4095
  AKAN_WORKSPACE_ROOT: app.workspace.workspaceRoot,
4088
4096
  AKAN_APP_ROOT: app.cwdPath,
@@ -4131,7 +4139,7 @@ var ApplicationRunner = class {
4131
4139
  } : {}
4132
4140
  );
4133
4141
  const server = await vite.createServer(config);
4134
- await server.listen(4201);
4142
+ await server.listen(4201 + app.workspace.getBaseDevEnv().portOffset);
4135
4143
  onStart?.();
4136
4144
  if (open2)
4137
4145
  setTimeout(() => openBrowser("http://localhost:4201"), 3e3);
@@ -4381,7 +4389,7 @@ var ApplicationRunner = class {
4381
4389
  ["node_modules/jest/bin/jest.js", `apps/${app.name}`, "-c", `apps/${app.name}/jest.config.ts`],
4382
4390
  {
4383
4391
  env: {
4384
- ...this.#getEnv(app),
4392
+ ...this.#getEnv(app, "backend"),
4385
4393
  NEXT_PUBLIC_ENV: "testing",
4386
4394
  NEXT_PUBLIC_OPERATION_MODE: "local",
4387
4395
  NEXT_PUBLIC_APP_NAME: app.name,
@@ -5200,6 +5208,25 @@ LibraryCommand = __decorateClass([
5200
5208
  // pkgs/@akanjs/cli/src/module/module.script.ts
5201
5209
  import fs15 from "fs";
5202
5210
 
5211
+ // pkgs/@akanjs/cli/src/page/page.runner.ts
5212
+ var PageRunner = class {
5213
+ async createCrudPage(module, { app, basePath: basePath2, single = false }) {
5214
+ await app.applyTemplate({
5215
+ basePath: basePath2 ?? `app/[lang]/(${app.name})/(public)/${module.name}`,
5216
+ template: single ? "crudSinglePage" : "crudPages",
5217
+ dict: { model: module.name, appName: module.sys.name }
5218
+ });
5219
+ }
5220
+ };
5221
+
5222
+ // pkgs/@akanjs/cli/src/page/page.script.ts
5223
+ var PageScript = class {
5224
+ #runner = new PageRunner();
5225
+ async createCrudPage(module, { app, basePath: basePath2, single = false }) {
5226
+ await this.#runner.createCrudPage(module, { app, basePath: basePath2, single });
5227
+ }
5228
+ };
5229
+
5203
5230
  // pkgs/@akanjs/cli/src/module/module.prompt.ts
5204
5231
  var componentDefaultDescription = ({
5205
5232
  modelName,
@@ -5574,10 +5601,13 @@ var ModuleRunner = class {
5574
5601
 
5575
5602
  // pkgs/@akanjs/cli/src/module/module.script.ts
5576
5603
  var ModuleScript = class {
5604
+ pageScript = new PageScript();
5577
5605
  #runner = new ModuleRunner();
5578
- async createModuleTemplate(sys3, name) {
5579
- const executor = ModuleExecutor.from(sys3, name);
5580
- await this.#runner.createModuleTemplate(executor);
5606
+ async createModuleTemplate(sys3, name, { page = false } = {}) {
5607
+ const mod = ModuleExecutor.from(sys3, name);
5608
+ await this.#runner.createModuleTemplate(mod);
5609
+ if (page && sys3.type === "app")
5610
+ await this.pageScript.createCrudPage(mod, { app: sys3, basePath: null, single: false });
5581
5611
  const akanConfig = await sys3.getConfig();
5582
5612
  await sys3.scan({ akanConfig });
5583
5613
  }
@@ -5628,25 +5658,25 @@ var ModuleScript = class {
5628
5658
  await this.createTemplate(executor);
5629
5659
  sys3.log(`Module ${name} created in ${sys3.type}s/${sys3.name}/lib/${name}`);
5630
5660
  }
5631
- removeModule(module) {
5632
- this.#runner.removeModule(module);
5661
+ removeModule(mod) {
5662
+ this.#runner.removeModule(mod);
5633
5663
  }
5634
5664
  async createService(workspace, name) {
5635
5665
  }
5636
5666
  async createTest(workspace, name) {
5637
5667
  }
5638
- async createTemplate(module) {
5639
- const { component: template } = await this.#runner.createComponentTemplate(module, "template");
5640
- const templateExampleFiles = (await module.sys.getTemplatesSourceCode()).filter(
5641
- (f) => !f.filePath.includes(`${module.name}.Template.tsx`)
5668
+ async createTemplate(mod) {
5669
+ const { component: template } = await this.#runner.createComponentTemplate(mod, "template");
5670
+ const templateExampleFiles = (await mod.sys.getTemplatesSourceCode()).filter(
5671
+ (f) => !f.filePath.includes(`${mod.name}.Template.tsx`)
5642
5672
  );
5643
- const Name = capitalize(module.name);
5644
- const relatedCnsts = getRelatedCnsts(`${module.sys.cwdPath}/lib/${module.name}/${module.name}.constant.ts`);
5645
- const constant = fs15.readFileSync(`${module.sys.cwdPath}/lib/${module.name}/${module.name}.constant.ts`, "utf-8");
5646
- const session = new AiSession("createTemplate", { workspace: module.sys.workspace, cacheKey: module.name });
5673
+ const Name = capitalize(mod.name);
5674
+ const relatedCnsts = getRelatedCnsts(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`);
5675
+ const constant = fs15.readFileSync(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`, "utf-8");
5676
+ const session = new AiSession("createTemplate", { workspace: mod.sys.workspace, cacheKey: mod.name });
5647
5677
  const promptRst = requestTemplate({
5648
- sysName: module.sys.name,
5649
- modelName: module.name,
5678
+ sysName: mod.sys.name,
5679
+ modelName: mod.name,
5650
5680
  ModelName: Name,
5651
5681
  constant,
5652
5682
  boilerplate: template.content,
@@ -5654,20 +5684,20 @@ var ModuleScript = class {
5654
5684
  exampleFiles: randomPicks(templateExampleFiles, Math.min(20, templateExampleFiles.length))
5655
5685
  });
5656
5686
  const content = await session.editTypescript(promptRst);
5657
- module.writeFile(`${Name}.Template.tsx`, content);
5687
+ mod.writeFile(`${Name}.Template.tsx`, content);
5658
5688
  }
5659
- async createUnit(module) {
5660
- const { component: unit } = await this.#runner.createComponentTemplate(module, "unit");
5661
- const Name = capitalize(module.name);
5662
- const unitExampleFiles = (await module.sys.getUnitsSourceCode()).filter(
5663
- (f) => !f.filePath.includes(`${module.name}.Unit.tsx`)
5689
+ async createUnit(mod) {
5690
+ const { component: unit } = await this.#runner.createComponentTemplate(mod, "unit");
5691
+ const Name = capitalize(mod.name);
5692
+ const unitExampleFiles = (await mod.sys.getUnitsSourceCode()).filter(
5693
+ (f) => !f.filePath.includes(`${mod.name}.Unit.tsx`)
5664
5694
  );
5665
- const relatedCnsts = getRelatedCnsts(`${module.sys.cwdPath}/lib/${module.name}/${module.name}.constant.ts`);
5666
- const constant = fs15.readFileSync(`${module.sys.cwdPath}/lib/${module.name}/${module.name}.constant.ts`, "utf-8");
5667
- const session = new AiSession("createUnit", { workspace: module.sys.workspace, cacheKey: module.name });
5695
+ const relatedCnsts = getRelatedCnsts(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`);
5696
+ const constant = fs15.readFileSync(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`, "utf-8");
5697
+ const session = new AiSession("createUnit", { workspace: mod.sys.workspace, cacheKey: mod.name });
5668
5698
  const promptRst = requestUnit({
5669
- sysName: module.sys.name,
5670
- modelName: module.name,
5699
+ sysName: mod.sys.name,
5700
+ modelName: mod.name,
5671
5701
  ModelName: Name,
5672
5702
  constant,
5673
5703
  properties: relatedCnsts.map((r) => ({ key: r.key, source: r.source })),
@@ -5675,20 +5705,20 @@ var ModuleScript = class {
5675
5705
  boilerplate: unit.content
5676
5706
  });
5677
5707
  const content = await session.editTypescript(promptRst);
5678
- module.writeFile(`${Name}.Unit.tsx`, content);
5708
+ mod.writeFile(`${Name}.Unit.tsx`, content);
5679
5709
  }
5680
- async createView(module) {
5681
- const { component: view } = await this.#runner.createComponentTemplate(module, "view");
5682
- const viewExampleFiles = (await module.sys.getViewsSourceCode()).filter(
5683
- (f) => !f.filePath.includes(`${module.name}.View.tsx`)
5710
+ async createView(mod) {
5711
+ const { component: view } = await this.#runner.createComponentTemplate(mod, "view");
5712
+ const viewExampleFiles = (await mod.sys.getViewsSourceCode()).filter(
5713
+ (f) => !f.filePath.includes(`${mod.name}.View.tsx`)
5684
5714
  );
5685
- const Name = capitalize(module.name);
5686
- const relatedCnsts = getRelatedCnsts(`${module.sys.cwdPath}/lib/${module.name}/${module.name}.constant.ts`);
5687
- const constant = fs15.readFileSync(`${module.sys.cwdPath}/lib/${module.name}/${module.name}.constant.ts`, "utf-8");
5688
- const session = new AiSession("createView", { workspace: module.sys.workspace, cacheKey: module.name });
5715
+ const Name = capitalize(mod.name);
5716
+ const relatedCnsts = getRelatedCnsts(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`);
5717
+ const constant = fs15.readFileSync(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`, "utf-8");
5718
+ const session = new AiSession("createView", { workspace: mod.sys.workspace, cacheKey: mod.name });
5689
5719
  const promptRst = requestView({
5690
- sysName: module.sys.name,
5691
- modelName: module.name,
5720
+ sysName: mod.sys.name,
5721
+ modelName: mod.name,
5692
5722
  ModelName: Name,
5693
5723
  constant,
5694
5724
  boilerplate: view.content,
@@ -5696,16 +5726,16 @@ var ModuleScript = class {
5696
5726
  exampleFiles: randomPicks(viewExampleFiles, Math.min(20, viewExampleFiles.length))
5697
5727
  });
5698
5728
  const content = await session.editTypescript(promptRst);
5699
- module.writeFile(`${Name}.View.tsx`, content);
5729
+ mod.writeFile(`${Name}.View.tsx`, content);
5700
5730
  }
5701
5731
  };
5702
5732
 
5703
5733
  // pkgs/@akanjs/cli/src/module/module.command.ts
5704
5734
  var ModuleCommand = class {
5705
5735
  moduleScript = new ModuleScript();
5706
- async createModule(moduleName, sys3) {
5736
+ async createModule(moduleName, sys3, page) {
5707
5737
  const name = lowerlize(moduleName.replace(/ /g, ""));
5708
- await this.moduleScript.createModuleTemplate(sys3, name);
5738
+ await this.moduleScript.createModuleTemplate(sys3, name, { page });
5709
5739
  }
5710
5740
  removeModule(module) {
5711
5741
  this.moduleScript.removeModule(module);
@@ -5723,7 +5753,8 @@ var ModuleCommand = class {
5723
5753
  __decorateClass([
5724
5754
  Target.Public(),
5725
5755
  __decorateParam(0, Argument("moduleName", { desc: "name of module" })),
5726
- __decorateParam(1, Sys())
5756
+ __decorateParam(1, Sys()),
5757
+ __decorateParam(2, Option("page", { type: "boolean", desc: "create page", default: false }))
5727
5758
  ], ModuleCommand.prototype, "createModule", 1);
5728
5759
  __decorateClass([
5729
5760
  Target.Public(),
@@ -5789,31 +5820,20 @@ PackageCommand = __decorateClass([
5789
5820
  Commands()
5790
5821
  ], PackageCommand);
5791
5822
 
5792
- // pkgs/@akanjs/cli/src/page/page.runner.ts
5793
- var PageRunner = class {
5794
- async createPage(app, name) {
5795
- }
5796
- };
5797
-
5798
- // pkgs/@akanjs/cli/src/page/page.script.ts
5799
- var PageScript = class {
5800
- #runner = new PageRunner();
5801
- async createPage(app, name) {
5802
- await this.#runner.createPage(app, name);
5803
- }
5804
- };
5805
-
5806
5823
  // pkgs/@akanjs/cli/src/page/page.command.ts
5807
5824
  var PageCommand = class {
5808
5825
  pageScript = new PageScript();
5809
- async createPage(app, name) {
5826
+ async createCrudPage(app, module, basePath2, single) {
5827
+ await this.pageScript.createCrudPage(module, { app, basePath: basePath2, single });
5810
5828
  }
5811
5829
  };
5812
5830
  __decorateClass([
5813
5831
  Target.Public(),
5814
5832
  __decorateParam(0, App()),
5815
- __decorateParam(1, Option("name", { desc: "name of page" }))
5816
- ], PageCommand.prototype, "createPage", 1);
5833
+ __decorateParam(1, Module()),
5834
+ __decorateParam(2, Option("basePath", { desc: "base path", nullable: true })),
5835
+ __decorateParam(3, Option("single", { desc: "single page", default: false }))
5836
+ ], PageCommand.prototype, "createCrudPage", 1);
5817
5837
  PageCommand = __decorateClass([
5818
5838
  Commands()
5819
5839
  ], PageCommand);
@@ -1,4 +1,4 @@
1
- // pkgs/@akanjs/cli/src/templates/app/app/[lang]/(__appName__)/layout.tsx
1
+ // pkgs/@akanjs/cli/src/templates/app/app/[lang]/layout.tsx
2
2
  function getContent(scanResult, dict) {
3
3
  return {
4
4
  filename: "layout.tsx",
@@ -1,4 +1,4 @@
1
- // pkgs/@akanjs/cli/src/templates/app/app/[lang]/(__appName__)/(public)/page.tsx
1
+ // pkgs/@akanjs/cli/src/templates/app/app/[lang]/page.tsx
2
2
  function getContent(scanResult, dict) {
3
3
  return {
4
4
  filename: "page.tsx",
@@ -1,4 +1,4 @@
1
- // pkgs/@akanjs/cli/src/templates/app/app/[lang]/(__appName__)/(public)/unknown/page.tsx
1
+ // pkgs/@akanjs/cli/src/templates/app/app/[lang]/unknown/page.tsx
2
2
  function getContent(scanResult, dict) {
3
3
  return {
4
4
  filename: "page.tsx",
@@ -36,7 +36,7 @@ export default function Page({ params }: PageProps) {
36
36
  onCancel="back"
37
37
  onSubmit="/${dict.model}"
38
38
  >
39
- ${dict.Model}.Template.General
39
+ <${dict.Model}.Template.General />
40
40
  </Load.Edit>
41
41
  </div>
42
42
  )}
@@ -4,8 +4,7 @@ function getContent(scanResult, dict) {
4
4
  filename: "page.tsx",
5
5
  content: `
6
6
  import { ${dict.Model}, fetch, usePage } from "${dict.appName}/client";
7
- import { Link } from "@akanjs/ui";
8
- import { Load } from "@akanjs/ui";
7
+ import { Link, Load } from "@akanjs/ui";
9
8
  import type { CsrConfig } from "@akanjs/client";
10
9
 
11
10
  interface PageProps {
@@ -38,7 +37,7 @@ export default function Page({ params }: PageProps) {
38
37
  render={({ ${dict.model}, ${dict.model}View }) => (
39
38
  <div className="container flex flex-col gap-4">
40
39
  <div className="flex gap-4 font-bold text-lg items-center">
41
- ${dict.Model}.Zone.View view={${dict.model}View} />
40
+ <${dict.Model}.Zone.View view={${dict.model}View} />
42
41
  <Link href={\`/${dict.model}/\${${dict.model}.id}/edit\`}>
43
42
  <button className="btn">
44
43
  {l("shared.updateModel", { model: l("${dict.model}.modelName") })}
@@ -4,7 +4,7 @@ function getContent(scanResult, dict) {
4
4
  filename: "page.tsx",
5
5
  content: `
6
6
  import { Load } from "@akanjs/ui";
7
- import { cnst, fetch, usePage, ${dict.Model} } from "${dict.appName}/client";
7
+ import { cnst, fetch, usePage, ${dict.Model} } from "@${dict.appName}/client";
8
8
  import type { CsrConfig } from "@akanjs/client";
9
9
 
10
10
  export default function Page() {
@@ -31,7 +31,7 @@ export default function Page() {
31
31
  onCancel="back"
32
32
  onSubmit="/${dict.model}"
33
33
  >
34
- ${dict.Model}.Template.General
34
+ <${dict.Model}.Template.General />
35
35
  </Load.Edit>
36
36
  </div>
37
37
  )}
@@ -3,7 +3,7 @@ function getContent(scanResult, dict) {
3
3
  return {
4
4
  filename: "page.tsx",
5
5
  content: `
6
- import { ${dict.Model}, fetch, usePage } from "${dict.appName}/client";
6
+ import { ${dict.Model}, fetch, usePage } from "@${dict.appName}/client";
7
7
  import { Link, Load } from "@akanjs/ui";
8
8
  import type { CsrConfig } from "@akanjs/client";
9
9
 
@@ -28,7 +28,7 @@ export default function Page() {
28
28
  </div>
29
29
  <div>{l("${dict.model}.modelDesc")}</div>
30
30
  <div className="flex px-6 mt-3 gap-4">
31
- ${dict.Model}.Zone.Card
31
+ <${dict.Model}.Zone.Card
32
32
  className="animate-fadeIn grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 justify-center gap-4 w-full"
33
33
  init={${dict.model}InitInPublic}
34
34
  />
@@ -4,19 +4,18 @@ function getContent(scanResult, dict) {
4
4
  filename: `${dict.Model}.View.tsx`,
5
5
  content: `
6
6
  import { clsx } from "@akanjs/client";
7
- import { cnst } from "@${dict.sysName}/client";
8
- import { Image } from "@akanjs/ui";
7
+ import { cnst, usePage } from "@${dict.sysName}/client";
9
8
 
10
9
  interface ${dict.Model}ViewProps {
11
10
  className?: string;
12
11
  ${dict.model}: cnst.${dict.Model};
13
- self?: { id?: string } | null;
14
12
  }
15
13
 
16
- export const General = ({ className, ${dict.model}, self }: ${dict.Model}ViewProps) => {
14
+ export const General = ({ className, ${dict.model} }: ${dict.Model}ViewProps) => {
15
+ const { l } = usePage();
17
16
  return (
18
- <div className={clsx(className, "animate-fadeIn w-full")}>
19
- <div>{${dict.model}.id}</div>
17
+ <div className={clsx("w-full", className)}>
18
+ <div>{l("${dict.model}.id")}: {${dict.model}.id}</div>
20
19
  </div>
21
20
  );
22
21
  };
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "type": "module",
3
3
  "sourceType": "module",
4
4
  "name": "@akanjs/cli",
5
- "version": "0.9.32",
5
+ "version": "0.9.34",
6
6
  "bin": {
7
7
  "akan": "esm/index.js"
8
8
  },
@@ -2,7 +2,7 @@ import { Module, Sys } from "@akanjs/devkit";
2
2
  import { ModuleScript } from "./module.script";
3
3
  export declare class ModuleCommand {
4
4
  moduleScript: ModuleScript;
5
- createModule(moduleName: string, sys: Sys): Promise<void>;
5
+ createModule(moduleName: string, sys: Sys, page: boolean): Promise<void>;
6
6
  removeModule(module: Module): void;
7
7
  createView(module: Module): Promise<void>;
8
8
  createUnit(module: Module): Promise<void>;
@@ -1,13 +1,17 @@
1
1
  import { type Module, type Sys, Workspace } from "@akanjs/devkit";
2
+ import { PageScript } from "../page/page.script";
2
3
  export declare class ModuleScript {
3
4
  #private;
4
- createModuleTemplate(sys: Sys, name: string): Promise<void>;
5
+ pageScript: PageScript;
6
+ createModuleTemplate(sys: Sys, name: string, { page }?: {
7
+ page?: boolean;
8
+ }): Promise<void>;
5
9
  createModule(sys: Sys, name: string, description?: string, schemaDescription?: string): Promise<void>;
6
10
  createModule_(sys: Sys, name: string, description: string, schemaDescription: string): Promise<void>;
7
- removeModule(module: Module): void;
11
+ removeModule(mod: Module): void;
8
12
  createService(workspace: Workspace, name: string): Promise<void>;
9
13
  createTest(workspace: Workspace, name: string): Promise<void>;
10
- createTemplate(module: Module): Promise<void>;
11
- createUnit(module: Module): Promise<void>;
12
- createView(module: Module): Promise<void>;
14
+ createTemplate(mod: Module): Promise<void>;
15
+ createUnit(mod: Module): Promise<void>;
16
+ createView(mod: Module): Promise<void>;
13
17
  }
@@ -1,6 +1,6 @@
1
- import { App } from "@akanjs/devkit";
1
+ import { App, Module } from "@akanjs/devkit";
2
2
  import { PageScript } from "./page.script";
3
3
  export declare class PageCommand {
4
4
  pageScript: PageScript;
5
- createPage(app: App, name: string): Promise<void>;
5
+ createCrudPage(app: App, module: Module, basePath: string | null, single: boolean): Promise<void>;
6
6
  }
@@ -1,4 +1,8 @@
1
- import { App } from "@akanjs/devkit";
1
+ import { App, Module } from "@akanjs/devkit";
2
2
  export declare class PageRunner {
3
- createPage(app: App, name: string): Promise<void>;
3
+ createCrudPage(module: Module, { app, basePath, single }: {
4
+ app: App;
5
+ basePath: string | null;
6
+ single: boolean;
7
+ }): Promise<void>;
4
8
  }
@@ -1,5 +1,9 @@
1
- import { App } from "@akanjs/devkit";
1
+ import { App, Module } from "@akanjs/devkit";
2
2
  export declare class PageScript {
3
3
  #private;
4
- createPage(app: App, name: string): Promise<void>;
4
+ createCrudPage(module: Module, { app, basePath, single }: {
5
+ app: App;
6
+ basePath: string | null;
7
+ single: boolean;
8
+ }): Promise<void>;
5
9
  }
@@ -1,54 +0,0 @@
1
- var __defProp = Object.defineProperty;
2
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
- var __getOwnPropNames = Object.getOwnPropertyNames;
4
- var __hasOwnProp = Object.prototype.hasOwnProperty;
5
- var __export = (target, all) => {
6
- for (var name in all)
7
- __defProp(target, name, { get: all[name], enumerable: true });
8
- };
9
- var __copyProps = (to, from, except, desc) => {
10
- if (from && typeof from === "object" || typeof from === "function") {
11
- for (let key of __getOwnPropNames(from))
12
- if (!__hasOwnProp.call(to, key) && key !== except)
13
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
- }
15
- return to;
16
- };
17
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
-
19
- // pkgs/@akanjs/cli/src/templates/app/app/[lang]/admin/layout.tsx
20
- var layout_exports = {};
21
- __export(layout_exports, {
22
- default: () => getContent
23
- });
24
- module.exports = __toCommonJS(layout_exports);
25
- function getContent(scanResult, dict) {
26
- return {
27
- filename: "layout.tsx",
28
- content: `
29
- import "../(${dict.appName})/styles.css";
30
- import { System } from "@akanjs/ui";
31
- import { env } from "@${dict.appName}/env/env.client";
32
- import { fetch } from "@${dict.appName}/client";
33
- import type { RootLayoutProps } from "@akanjs/client";
34
-
35
- export const metadata = { title: "${dict.appName}" };
36
-
37
- export default function Layout({ children, params }: RootLayoutProps) {
38
- return (
39
- <System.Provider
40
- of={Layout}
41
- appName="${dict.appName}"
42
- params={params}
43
- head={<link rel="icon" href="/favicon.ico" />}
44
- // className="bg-base-100"
45
- env={env}
46
- fetch={fetch}
47
- >
48
- {children}
49
- </System.Provider>
50
- );
51
- }
52
- `
53
- };
54
- }
@@ -1,34 +0,0 @@
1
- // pkgs/@akanjs/cli/src/templates/app/app/[lang]/admin/layout.tsx
2
- function getContent(scanResult, dict) {
3
- return {
4
- filename: "layout.tsx",
5
- content: `
6
- import "../(${dict.appName})/styles.css";
7
- import { System } from "@akanjs/ui";
8
- import { env } from "@${dict.appName}/env/env.client";
9
- import { fetch } from "@${dict.appName}/client";
10
- import type { RootLayoutProps } from "@akanjs/client";
11
-
12
- export const metadata = { title: "${dict.appName}" };
13
-
14
- export default function Layout({ children, params }: RootLayoutProps) {
15
- return (
16
- <System.Provider
17
- of={Layout}
18
- appName="${dict.appName}"
19
- params={params}
20
- head={<link rel="icon" href="/favicon.ico" />}
21
- // className="bg-base-100"
22
- env={env}
23
- fetch={fetch}
24
- >
25
- {children}
26
- </System.Provider>
27
- );
28
- }
29
- `
30
- };
31
- }
32
- export {
33
- getContent as default
34
- };
@@ -1,9 +0,0 @@
1
- import type { AppScanResult, LibScanResult } from "@akanjs/config";
2
- interface Dict {
3
- appName: string;
4
- }
5
- export default function getContent(scanResult: AppScanResult | LibScanResult | null, dict: Dict): {
6
- filename: string;
7
- content: string;
8
- };
9
- export {};