@akanjs/cli 0.9.56 → 0.9.58-canary.0

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 (56) hide show
  1. package/cjs/index.js +76 -45
  2. package/cjs/src/guidelines/databaseModule/databaseModule.instruction.md +7 -1
  3. package/cjs/src/guidelines/modelSignal/modelSignal.instruction.md +3 -3
  4. package/cjs/src/guidelines/modelTemplate/modelTemplate.instruction.md +5 -5
  5. package/cjs/src/guidelines/sharedUiUsage/sharedUiUsage.generate.json +0 -7
  6. package/cjs/src/guidelines/sharedUiUsage/sharedUiUsage.instruction.md +7 -7
  7. package/cjs/src/templates/app/app/[lang]/layout.js +2 -0
  8. package/cjs/src/templates/app/app/[lang]/styles.css.template +1 -0
  9. package/cjs/src/templates/app/lib/option.js +6 -1
  10. package/cjs/src/templates/app/main.js +2 -2
  11. package/cjs/src/templates/lib/__lib/lib.dictionary.js +1 -2
  12. package/cjs/src/templates/lib/dict.js +22 -6
  13. package/cjs/src/templates/lib/sig.js +5 -2
  14. package/cjs/src/templates/lib/useClient.js +5 -4
  15. package/cjs/src/templates/libRoot/lib/option.js +5 -1
  16. package/cjs/src/templates/module/__Model__.Template.js +2 -2
  17. package/cjs/src/templates/module/__Model__.Util.js +8 -1
  18. package/cjs/src/templates/module/__model__.constant.js +3 -8
  19. package/cjs/src/templates/module/__model__.dictionary.js +21 -59
  20. package/cjs/src/templates/module/__model__.document.js +1 -1
  21. package/cjs/src/templates/module/__model__.signal.js +5 -4
  22. package/cjs/src/templates/server.js +11 -3
  23. package/esm/index.js +76 -45
  24. package/esm/src/guidelines/databaseModule/databaseModule.instruction.md +7 -1
  25. package/esm/src/guidelines/modelSignal/modelSignal.instruction.md +3 -3
  26. package/esm/src/guidelines/modelTemplate/modelTemplate.instruction.md +5 -5
  27. package/esm/src/guidelines/sharedUiUsage/sharedUiUsage.generate.json +0 -7
  28. package/esm/src/guidelines/sharedUiUsage/sharedUiUsage.instruction.md +7 -7
  29. package/esm/src/templates/app/app/[lang]/layout.js +2 -0
  30. package/esm/src/templates/app/app/[lang]/styles.css.template +1 -0
  31. package/esm/src/templates/app/lib/option.js +6 -1
  32. package/esm/src/templates/app/main.js +2 -2
  33. package/esm/src/templates/lib/__lib/lib.dictionary.js +1 -2
  34. package/esm/src/templates/lib/dict.js +22 -6
  35. package/esm/src/templates/lib/sig.js +5 -2
  36. package/esm/src/templates/lib/useClient.js +5 -4
  37. package/esm/src/templates/libRoot/lib/option.js +5 -1
  38. package/esm/src/templates/module/__Model__.Template.js +2 -2
  39. package/esm/src/templates/module/__Model__.Util.js +8 -1
  40. package/esm/src/templates/module/__model__.constant.js +3 -8
  41. package/esm/src/templates/module/__model__.dictionary.js +21 -59
  42. package/esm/src/templates/module/__model__.document.js +1 -1
  43. package/esm/src/templates/module/__model__.signal.js +5 -4
  44. package/esm/src/templates/server.js +11 -3
  45. package/package.json +1 -1
  46. package/src/guidelines/databaseModule/databaseModule.instruction.md +7 -1
  47. package/src/guidelines/modelSignal/modelSignal.instruction.md +3 -3
  48. package/src/guidelines/modelTemplate/modelTemplate.instruction.md +5 -5
  49. package/src/guidelines/sharedUiUsage/sharedUiUsage.instruction.md +7 -7
  50. package/src/module/module.command.d.ts +1 -1
  51. package/src/module/module.runner.d.ts +1 -1
  52. package/src/module/module.script.d.ts +1 -1
  53. package/src/scalar/scalar.command.d.ts +1 -1
  54. package/src/scalar/scalar.script.d.ts +1 -1
  55. package/src/workspace/workspace.command.d.ts +2 -0
  56. package/src/workspace/workspace.script.d.ts +2 -0
package/cjs/index.js CHANGED
@@ -228,7 +228,7 @@ var Logger = class _Logger {
228
228
  const contentMsg = this.#colorize(content, logLevel);
229
229
  const timeDiffMsg = clc.yellow(`+${now.diff(_Logger.#startAt, "ms")}ms`);
230
230
  if (typeof window === "undefined")
231
- process[writeStreamType].write(
231
+ process[writeStreamType]?.write(
232
232
  `${processMsg} ${timestampMsg} ${logLevelMsg} ${contextMsg} ${contentMsg} ${timeDiffMsg}
233
233
  `
234
234
  );
@@ -2008,10 +2008,10 @@ var Executor = class _Executor {
2008
2008
  this.logger.verbose(`Remove file ${readPath}`);
2009
2009
  return this;
2010
2010
  }
2011
- removeDir(dirPath) {
2011
+ async removeDir(dirPath) {
2012
2012
  const readPath = this.getPath(dirPath);
2013
2013
  if (import_fs4.default.existsSync(readPath))
2014
- import_fs4.default.rmSync(readPath, { recursive: true });
2014
+ await import_fs4.default.promises.rm(readPath, { recursive: true });
2015
2015
  this.logger.verbose(`Remove directory ${readPath}`);
2016
2016
  return this;
2017
2017
  }
@@ -2057,9 +2057,9 @@ var Executor = class _Executor {
2057
2057
  async cp(srcPath, destPath) {
2058
2058
  const src = this.getPath(srcPath);
2059
2059
  const dest = this.getPath(destPath);
2060
- const isDirectory = import_fs4.default.statSync(src).isDirectory();
2061
2060
  if (!import_fs4.default.existsSync(src))
2062
2061
  return;
2062
+ const isDirectory = import_fs4.default.statSync(src).isDirectory();
2063
2063
  if (!import_fs4.default.existsSync(dest) && isDirectory)
2064
2064
  await import_promises.default.mkdir(dest, { recursive: true });
2065
2065
  await import_promises.default.cp(src, dest, { recursive: true });
@@ -2615,32 +2615,23 @@ var AppExecutor = class _AppExecutor extends SysExecutor {
2615
2615
  return this.#akanConfig;
2616
2616
  }
2617
2617
  async syncAssets(libDeps) {
2618
- const projectPublicLibPath = `${this.cwdPath}/public/libs`;
2619
- const projectAssetsLibPath = `${this.cwdPath}/assets/libs`;
2618
+ const projectPublicPath = `${this.cwdPath}/public`;
2619
+ const projectAssetsPath = `${this.cwdPath}/assets`;
2620
+ const projectPublicLibPath = `${projectPublicPath}/libs`;
2621
+ const projectAssetsLibPath = `${projectAssetsPath}/libs`;
2622
+ await Promise.all([this.removeDir(projectPublicLibPath), this.removeDir(projectAssetsLibPath)]);
2623
+ const targetPublicDeps = libDeps.filter((dep) => this.exists(`${this.workspace.workspaceRoot}/libs/${dep}/public`));
2624
+ const targetAssetsDeps = libDeps.filter((dep) => this.exists(`${this.workspace.workspaceRoot}/libs/${dep}/assets`));
2620
2625
  await Promise.all([
2621
- import_fs4.default.existsSync(projectPublicLibPath) && import_promises.default.rm(projectPublicLibPath, { recursive: true }),
2622
- import_fs4.default.existsSync(projectAssetsLibPath) && import_promises.default.rm(projectAssetsLibPath, { recursive: true })
2623
- ]);
2624
- const targetPublicDeps = libDeps.filter(
2625
- (dep) => import_fs4.default.existsSync(`${this.workspace.workspaceRoot}/libs/${dep}/public`)
2626
- );
2627
- const targetAssetsDeps = libDeps.filter(
2628
- (dep) => import_fs4.default.existsSync(`${this.workspace.workspaceRoot}/libs/${dep}/assets`)
2629
- );
2630
- await Promise.all([
2631
- ...targetPublicDeps.map((dep) => import_promises.default.mkdir(`${projectPublicLibPath}/${dep}`, { recursive: true })),
2632
- ...targetAssetsDeps.map((dep) => import_promises.default.mkdir(`${projectAssetsLibPath}/${dep}`, { recursive: true }))
2626
+ ...targetPublicDeps.map((dep) => this.mkdir(`${projectPublicLibPath}/${dep}`)),
2627
+ ...targetAssetsDeps.map((dep) => this.mkdir(`${projectAssetsLibPath}/${dep}`))
2633
2628
  ]);
2634
2629
  await Promise.all([
2635
2630
  ...targetPublicDeps.map(
2636
- (dep) => import_promises.default.cp(`${this.workspace.workspaceRoot}/libs/${dep}/public`, `${projectPublicLibPath}/${dep}`, {
2637
- recursive: true
2638
- })
2631
+ (dep) => this.cp(`${this.workspace.workspaceRoot}/libs/${dep}/public`, `${projectPublicLibPath}/${dep}`)
2639
2632
  ),
2640
2633
  ...targetAssetsDeps.map(
2641
- (dep) => import_promises.default.cp(`${this.workspace.workspaceRoot}/libs/${dep}/assets`, `${projectAssetsLibPath}/${dep}`, {
2642
- recursive: true
2643
- })
2634
+ (dep) => this.cp(`${this.workspace.workspaceRoot}/libs/${dep}/assets`, `${projectAssetsLibPath}/${dep}`)
2644
2635
  )
2645
2636
  ]);
2646
2637
  }
@@ -4994,14 +4985,14 @@ var ApplicationScript = class {
4994
4985
  }
4995
4986
  async dumpDatabase(app, environment) {
4996
4987
  await this.dbdown(app.workspace);
4997
- const spinner = app.spinning("Dumping database...");
4988
+ const spinner = app.spinning(`Dumping database ${app.name} (${environment})...`);
4998
4989
  await this.#runner.dumpDatabase(app, environment);
4999
- spinner.succeed(`Database dumped to dump/${app.name}-${environment}`);
4990
+ spinner.succeed(`Database ${app.name} (${environment}) dumped to dump/${app.name}-${environment}`);
5000
4991
  }
5001
4992
  async restoreDatabase(app, source, target) {
5002
- const spinner = app.spinning("Restoring database...");
4993
+ const spinner = app.spinning(`Restoring database ${app.name} (${source}) to ${target}...`);
5003
4994
  await this.#runner.restoreDatabase(app, source, target);
5004
- spinner.succeed(`Database restored from dump/${app.name}-${source} to ${app.name}-${target}`);
4995
+ spinner.succeed(`Database ${app.name} (${source}) restored to ${target}`);
5005
4996
  }
5006
4997
  async pullDatabase(app, environment, dump) {
5007
4998
  const hasDump = app.workspace.exists(`dump/${app.name}-${environment}`);
@@ -5415,19 +5406,19 @@ ${import_chalk6.default.green("\u27A4")} Authentication Required`));
5415
5406
  }
5416
5407
  async deployAkan(workspace, akanPkgs) {
5417
5408
  const basePackageJson = workspace.readJson("pkgs/@akanjs/base/package.json");
5418
- const majorVersionOfBase = basePackageJson.version.split(".")[0];
5419
- const minorVersionOfBase = basePackageJson.version.split(".")[1];
5420
- const getNextVersion = async (major, minor) => {
5409
+ const [majorVersionOfBase, minorVersionOfBase, patchVersionOfBase, devPatchVersionOfBase] = basePackageJson.version.split(".");
5410
+ const targetVersionPrefix = devPatchVersionOfBase ? `${majorVersionOfBase}.${minorVersionOfBase}.${patchVersionOfBase}` : `${majorVersionOfBase}.${minorVersionOfBase}`;
5411
+ const getNextVersion = async (prefix) => {
5421
5412
  try {
5422
- const latestPublishedVersionOfBase = await (0, import_latest_version.default)("@akanjs/base", { version: `${major}.${minor}` });
5413
+ const latestPublishedVersionOfBase = await (0, import_latest_version.default)("@akanjs/base", { version: prefix });
5423
5414
  const latestPatch = parseInt(latestPublishedVersionOfBase.split(".")[2]);
5424
- const nextVersion2 = `${major}.${minor}.${latestPatch + 1}`;
5415
+ const nextVersion2 = `${prefix}.${latestPatch + 1}`;
5425
5416
  return { nextVersion: nextVersion2, latestPublishedVersion: latestPublishedVersionOfBase };
5426
5417
  } catch (e) {
5427
- return { nextVersion: `${major}.${minor}.0`, latestPublishedVersion: null };
5418
+ return { nextVersion: `${prefix}.0`, latestPublishedVersion: null };
5428
5419
  }
5429
5420
  };
5430
- const { nextVersion, latestPublishedVersion } = await getNextVersion(majorVersionOfBase, minorVersionOfBase);
5421
+ const { nextVersion, latestPublishedVersion } = await getNextVersion(targetVersionPrefix);
5431
5422
  Logger.info(`Latest published version of @akanjs/base: ${latestPublishedVersion ?? "none"}`);
5432
5423
  Logger.info(`Next version of @akanjs/base: ${nextVersion}`);
5433
5424
  for (const library of akanPkgs) {
@@ -5943,8 +5934,8 @@ var requestUnit = ({
5943
5934
  var ModuleRunner = class {
5944
5935
  async createModule(workspace, sysType, sysName, moduleName, description) {
5945
5936
  }
5946
- removeModule(module2) {
5947
- module2.sys.removeDir(`lib/${module2.name}`);
5937
+ async removeModule(module2) {
5938
+ await module2.sys.removeDir(`lib/${module2.name}`);
5948
5939
  }
5949
5940
  async createComponentTemplate(module2, type) {
5950
5941
  await module2.sys.applyTemplate({
@@ -6081,8 +6072,8 @@ var ModuleScript = class {
6081
6072
  await this.createTemplate(executor);
6082
6073
  sys3.log(`Module ${name} created in ${sys3.type}s/${sys3.name}/lib/${name}`);
6083
6074
  }
6084
- removeModule(mod) {
6085
- this.#runner.removeModule(mod);
6075
+ async removeModule(mod) {
6076
+ await this.#runner.removeModule(mod);
6086
6077
  }
6087
6078
  async createService(workspace, name) {
6088
6079
  }
@@ -6160,8 +6151,8 @@ var ModuleCommand = class {
6160
6151
  const name = lowerlize(moduleName.replace(/ /g, ""));
6161
6152
  await this.moduleScript.createModuleTemplate(sys3, name, { page });
6162
6153
  }
6163
- removeModule(module2) {
6164
- this.moduleScript.removeModule(module2);
6154
+ async removeModule(module2) {
6155
+ await this.moduleScript.removeModule(module2);
6165
6156
  }
6166
6157
  async createView(module2) {
6167
6158
  await this.moduleScript.createView(module2);
@@ -6414,6 +6405,16 @@ var WorkspaceScript = class {
6414
6405
  for (const appName of appNames)
6415
6406
  await this.applicationScript.syncApplication(AppExecutor.from(workspace, appName));
6416
6407
  }
6408
+ async dumpDatabaseAll(workspace, environment) {
6409
+ const appNames = await workspace.getApps();
6410
+ for (const appName of appNames)
6411
+ await this.applicationScript.dumpDatabase(AppExecutor.from(workspace, appName), environment);
6412
+ }
6413
+ async restoreDatabaseAll(workspace, source, target) {
6414
+ const appNames = await workspace.getApps();
6415
+ for (const appName of appNames)
6416
+ await this.applicationScript.restoreDatabase(AppExecutor.from(workspace, appName), source, target);
6417
+ }
6417
6418
  };
6418
6419
 
6419
6420
  // pkgs/@akanjs/cli/src/workspace/workspace.command.ts
@@ -6438,6 +6439,12 @@ var WorkspaceCommand = class {
6438
6439
  async syncAll(workspace) {
6439
6440
  await this.workspaceScript.syncAll(workspace);
6440
6441
  }
6442
+ async dumpDatabaseAll(environment, workspace) {
6443
+ await this.workspaceScript.dumpDatabaseAll(workspace, environment);
6444
+ }
6445
+ async restoreDatabaseAll(source, target, workspace) {
6446
+ await this.workspaceScript.restoreDatabaseAll(workspace, source, target);
6447
+ }
6441
6448
  };
6442
6449
  __decorateClass([
6443
6450
  Target.Public(),
@@ -6464,6 +6471,30 @@ __decorateClass([
6464
6471
  Target.Public(),
6465
6472
  __decorateParam(0, Workspace())
6466
6473
  ], WorkspaceCommand.prototype, "syncAll", 1);
6474
+ __decorateClass([
6475
+ Target.Public(),
6476
+ __decorateParam(0, Option("environment", {
6477
+ desc: "environment",
6478
+ default: "debug",
6479
+ enum: ["debug", "develop", "main"],
6480
+ ask: "Select the environment to dump the database"
6481
+ })),
6482
+ __decorateParam(1, Workspace())
6483
+ ], WorkspaceCommand.prototype, "dumpDatabaseAll", 1);
6484
+ __decorateClass([
6485
+ Target.Public(),
6486
+ __decorateParam(0, Option("source", {
6487
+ desc: "source environment",
6488
+ enum: ["debug", "develop", "main"],
6489
+ ask: "Select the source environment of local dump"
6490
+ })),
6491
+ __decorateParam(1, Option("target", {
6492
+ desc: "target environment",
6493
+ enum: ["debug", "develop", "main"],
6494
+ ask: "Select the target environment to restore the database"
6495
+ })),
6496
+ __decorateParam(2, Workspace())
6497
+ ], WorkspaceCommand.prototype, "restoreDatabaseAll", 1);
6467
6498
  WorkspaceCommand = __decorateClass([
6468
6499
  Commands()
6469
6500
  ], WorkspaceCommand);
@@ -6961,8 +6992,8 @@ var ScalarScript = class {
6961
6992
  const { session, scalarNames } = await this.#runner.createScalarConstant(sys3, scalarName);
6962
6993
  await this.#runner.updateScalarDictionaries(sys3, scalarNames, { session });
6963
6994
  }
6964
- removeScalar(sys3, scalarName) {
6965
- sys3.removeDir(`lib/__scalar/${scalarName}`);
6995
+ async removeScalar(sys3, scalarName) {
6996
+ await sys3.removeDir(`lib/__scalar/${scalarName}`);
6966
6997
  }
6967
6998
  };
6968
6999
 
@@ -6972,8 +7003,8 @@ var ScalarCommand = class {
6972
7003
  async createScalar(sys3, scalarName) {
6973
7004
  await this.scalarScript.createScalar(sys3, lowerlize(scalarName.replace(/ /g, "")));
6974
7005
  }
6975
- removeScalar(sys3, scalarName) {
6976
- this.scalarScript.removeScalar(sys3, scalarName);
7006
+ async removeScalar(sys3, scalarName) {
7007
+ await this.scalarScript.removeScalar(sys3, scalarName);
6977
7008
  }
6978
7009
  };
6979
7010
  __decorateClass([
@@ -207,7 +207,7 @@ import * as cnst from "../cnst";
207
207
  import type * as db from "../db";
208
208
 
209
209
  export class UserSignal extends DbSignal(cnst.userCnst, cnst.Srvs, {
210
- guards: { get: Query.Public, cru: Mutation.Admin },
210
+ guards: { root: Admin, get: Query.Public, cru: Mutation.Admin },
211
211
  }) {
212
212
  @Mutation.Public(() => cnst.util.AccessToken)
213
213
  async signin(
@@ -578,30 +578,36 @@ export const Layout = () => (
578
578
  ## Best Practices
579
579
 
580
580
  1. **Naming Conventions**
581
+
581
582
  - Use PascalCase for classes and components (e.g., `UserService`, `User.Unit.tsx`)
582
583
  - Use camelCase for files (e.g., `user.service.ts`, `user.document.ts`)
583
584
 
584
585
  2. **Security**
586
+
585
587
  - Use `@Field.Secret` for sensitive data like passwords
586
588
  - Apply proper permission guards to queries and mutations (`@Query.Admin`, `@Mutation.Public`)
587
589
  - Validate input data using the `validate` option in `@Field.Prop`
588
590
 
589
591
  3. **Code Organization**
592
+
590
593
  - Keep business logic in service files
591
594
  - Use signals for API calls only, not for business logic
592
595
  - Define reusable utility methods in document models
593
596
 
594
597
  4. **Performance**
598
+
595
599
  - Use dataloader pattern (`@Loader.ByField`) for efficient database access
596
600
  - Create proper indexes in the middleware
597
601
  - Use projections to limit returned fields when appropriate
598
602
 
599
603
  5. **Testing**
604
+
600
605
  - Create signal tests for each API endpoint
601
606
  - Mock services for unit testing signals
602
607
  - Use integration tests for testing complex workflows
603
608
 
604
609
  6. **UI Components**
610
+
605
611
  - Follow the separation between Template, Unit, View, and Zone components
606
612
  - Make components reusable across different parts of the application
607
613
  - Use dictionary files for all UI text to support internationalization
@@ -27,7 +27,7 @@ import * as cnst from "../cnst";
27
27
  import type * as db from "../db";
28
28
 
29
29
  export class ModelNameSignal extends DbSignal(cnst.modelNameCnst, cnst.Srvs, {
30
- guards: { get: Query.Public, cru: Mutation.User },
30
+ guards: { root: Admin, get: Query.Public, cru: Mutation.User },
31
31
  }) {
32
32
  // Signal methods here...
33
33
  }
@@ -259,7 +259,7 @@ DbSignal creates standard operations that you don't need to implement:
259
259
 
260
260
  ```typescript
261
261
  export class BoardSignal extends DbSignal(cnst.boardCnst, cnst.Srvs, {
262
- guards: { get: Query.Public, cru: Mutation.Admin },
262
+ guards: { root: Admin, get: Query.Public, cru: Mutation.Admin },
263
263
  }) {
264
264
  // Custom methods beyond CRUD go here
265
265
  }
@@ -378,7 +378,7 @@ async getProjectDetails(
378
378
 
379
379
  ```typescript
380
380
  export class ProductSignal extends DbSignal(cnst.productCnst, cnst.Srvs, {
381
- guards: { get: Query.Public, cru: Mutation.Admin },
381
+ guards: { root: Admin, get: Query.Public, cru: Mutation.Admin },
382
382
  }) {
383
383
  // Custom methods beyond auto-generated CRUD
384
384
  @Query.Public(() => [cnst.Product])
@@ -49,7 +49,7 @@ export const General = ({ id }: { id?: string }) => {
49
49
  return (
50
50
  <div className="grid grid-cols-1 gap-4">
51
51
  <Field.Text
52
- label={l.field("model", "fieldName")}
52
+ label={l("model.fieldName")}
53
53
  value={form.fieldName}
54
54
  onChange={(v) => st.do.setFieldNameOn[Model](v)}
55
55
  />
@@ -139,7 +139,7 @@ useEffect(() => {
139
139
 
140
140
  ```tsx
141
141
  <Field.List
142
- label={l.field("map", "spawnPositions")}
142
+ label={l("map.spawnPositions")}
143
143
  value={form.spawnPositions}
144
144
  onAdd={() => st.do.addSpawnPosition(defaultPosition)}
145
145
  renderItem={(position, idx) => (
@@ -201,12 +201,12 @@ useEffect(() => {
201
201
  const { l } = usePage();
202
202
 
203
203
  // Basic field
204
- <Field.Text label={l.field("model", "name")} />
204
+ <Field.Text label={l("model.name")} />
205
205
 
206
206
  // With description
207
207
  <Field.Text
208
- label={l.field("model", "email")}
209
- desc={l.desc("model", "email")}
208
+ label={l("model.email")}
209
+ desc={l("model.email.desc")}
210
210
  />
211
211
 
212
212
  // Dynamic content
@@ -85,13 +85,6 @@
85
85
  "path": "{apps,libs}/*/lib/*/*.{Template,Unit,View,Zone}.tsx",
86
86
  "filterText": "sliceName",
87
87
  "sample": 5
88
- },
89
- {
90
- "type": "example",
91
- "description": "Internationalization usage examples",
92
- "path": "{apps,libs}/*/lib/*/*.{Template,Unit,View}.tsx",
93
- "filterText": "l.field",
94
- "sample": 3
95
88
  }
96
89
  ],
97
90
  "update": {
@@ -64,8 +64,8 @@ const MyComponent = () => {
64
64
  return (
65
65
  <>
66
66
  <Field.Text
67
- label={l.field("myModel", "title")}
68
- desc={l.desc("myModel", "title")}
67
+ label={l("myModel.title")}
68
+ desc={l("myModel.title.desc")}
69
69
  value={formState.title}
70
70
  onChange={(value) => st.do.setTitleOnMyModel(value)}
71
71
  nullable={false}
@@ -73,8 +73,8 @@ const MyComponent = () => {
73
73
  />
74
74
 
75
75
  <Field.Number
76
- label={l.field("myModel", "amount")}
77
- desc={l.desc("myModel", "amount")}
76
+ label={l("myModel.amount")}
77
+ desc={l("myModel.amount.desc")}
78
78
  value={formState.amount}
79
79
  onChange={(value) => st.do.setAmountOnMyModel(value)}
80
80
  min={0}
@@ -83,8 +83,8 @@ const MyComponent = () => {
83
83
  />
84
84
 
85
85
  <Field.ToggleSelect
86
- label={l.field("myModel", "status")}
87
- desc={l.desc("myModel", "status")}
86
+ label={l("myModel.status")}
87
+ desc={l("myModel.status.desc")}
88
88
  value={formState.status}
89
89
  items={cnst.Status}
90
90
  onChange={(status) => st.do.setStatusOnMyModel(status)}
@@ -266,7 +266,7 @@ Components automatically integrate with the internationalization system:
266
266
  ```tsx
267
267
  const { l } = usePage();
268
268
 
269
- <Field.Text label={l.field("user", "name")} desc={l.desc("user", "name")} placeholder={l("user.namePlaceholder")} />;
269
+ <Field.Text label={l("user.name")} desc={l("user.name.desc")} placeholder={l("user.namePlaceholder")} />;
270
270
  ```
271
271
 
272
272
  ### State Management Integration
@@ -31,6 +31,7 @@ import { RootLayoutProps } from "@akanjs/client";
31
31
  import { System } from "@akanjs/ui";
32
32
  import { env } from "@${dict.appName}/env/env.client";
33
33
  import { fetch } from "@${dict.appName}/client";
34
+ import { Auth } from "@shared/ui";
34
35
 
35
36
  export const metadata = { title: "${dict.appName}" };
36
37
 
@@ -45,6 +46,7 @@ export default function Layout({ children, params }: RootLayoutProps) {
45
46
  env={env}
46
47
  >
47
48
  {children}
49
+ <Auth.User />
48
50
  </System.Provider>
49
51
  );
50
52
  }
@@ -3,6 +3,7 @@
3
3
 
4
4
  @plugin "daisyui" {
5
5
  logs: false;
6
+ exclude: properties;
6
7
  }
7
8
 
8
9
  @plugin "daisyui/theme" {
@@ -24,7 +24,7 @@ __export(option_exports, {
24
24
  module.exports = __toCommonJS(option_exports);
25
25
  function getContent(scanInfo, dict = {}) {
26
26
  return `
27
- import { useGlobals } from "@akanjs/server";
27
+ import { Middleware, useGlobals } from "@akanjs/server";
28
28
 
29
29
  import type { LibOptions } from "./__lib/lib.service";
30
30
 
@@ -38,5 +38,10 @@ export const registerGlobalModule = (options: ModulesOptions) => {
38
38
  useAsyncs: {},
39
39
  });
40
40
  };
41
+
42
+ export const registerGlobalMiddlewares = (options: ModulesOptions) => {
43
+ return [] as Middleware[];
44
+ };
45
+
41
46
  `;
42
47
  }
@@ -27,12 +27,12 @@ function getContent(scanInfo, dict) {
27
27
  import { createNestApp } from "@akanjs/server";
28
28
 
29
29
  import { env } from "./env/env.server";
30
- import { registerModules } from "./server";
30
+ import { registerModules, registerMiddlewares } from "./server";
31
31
 
32
32
  const bootstrap = async () => {
33
33
  const serverMode = process.env.SERVER_MODE as "federation" | "batch" | "all" | null;
34
34
  if (!serverMode) throw new Error("SERVER_MODE environment variable is not defined");
35
- await createNestApp({ registerModules, serverMode, env });
35
+ await createNestApp({ registerModules, registerMiddlewares, serverMode, env });
36
36
  };
37
37
  void bootstrap();
38
38
  `;
@@ -42,8 +42,7 @@ ${libs.map((lib) => `import { dict as ${lib} } from "@${lib}/server";`).join("\n
42
42
 
43
43
  ${Object.entries(extendedModels).map(([modelName, extendedModels2]) => {
44
44
  return `export const ${modelName} = {
45
- models: Object.assign({}, ${extendedModels2.map((libName) => `${libName}.${modelName}.modelDictionary`).join(", ")}),
46
- signals: Object.assign({}, ${extendedModels2.map((libName) => `${libName}.${modelName}.signalDictionary`).join(", ")}),
45
+ dictionaries: [${extendedModels2.map((libName) => `${libName}.${modelName}.dictionary`).join(", ")}] as const,
47
46
  };`;
48
47
  }).join("\n")}
49
48
 
@@ -22,6 +22,7 @@ __export(dict_exports, {
22
22
  default: () => getContent
23
23
  });
24
24
  module.exports = __toCommonJS(dict_exports);
25
+ var capitalize = (str) => str.charAt(0).toUpperCase() + str.slice(1);
25
26
  function getContent(scanInfo, dict = {}) {
26
27
  if (!scanInfo)
27
28
  return null;
@@ -29,7 +30,7 @@ function getContent(scanInfo, dict = {}) {
29
30
  const scalarModules = scanInfo.getScalarModules();
30
31
  const serviceModules = scanInfo.getServiceModules();
31
32
  return `
32
- import { makeDictionary, makeTrans } from "@akanjs/dictionary";
33
+ import { makeDictionary, makeTrans, registerScalarTrans, registerServiceTrans, registerModelTrans } from "@akanjs/dictionary";
33
34
 
34
35
  import { allLibs } from "./__lib/lib.dictionary";
35
36
  ${databaseModules.map((module2) => `import * as ${module2} from "./${module2}/${module2}.dictionary";`).join("\n")}
@@ -40,14 +41,29 @@ ${databaseModules.map((module2) => `export * as ${module2} from "./${module2}/${
40
41
  ${serviceModules.map((module2) => `export * as ${module2} from "./_${module2}/${module2}.dictionary";`).join("\n")}
41
42
  ${scalarModules.map((module2) => `export * as ${module2} from "./__scalar/${module2}/${module2}.dictionary";`).join("\n")}
42
43
 
44
+ ${databaseModules.map((module2) => `import type * as ${module2}Cnst from "./${module2}/${module2}.constant";`).join("\n")}
45
+ ${scalarModules.map((module2) => `import type * as ${module2}Cnst from "./__scalar/${module2}/${module2}.constant";`).join("\n")}
46
+
47
+ ${databaseModules.map((module2) => `import type * as ${module2}Doc from "./${module2}/${module2}.document";`).join("\n")}
48
+
49
+ ${databaseModules.map((module2) => `import type * as ${module2}Sig from "./${module2}/${module2}.signal";`).join("\n")}
50
+ ${serviceModules.map((module2) => `import type * as ${module2}Sig from "./_${module2}/${module2}.signal";`).join("\n")}
51
+
43
52
  export const dictionary = makeDictionary(...allLibs, {
44
53
  ${[
45
- ...databaseModules.map((module2) => `${module2}: { ...${module2}.modelDictionary, ...${module2}.signalDictionary }`),
46
- ...scalarModules.map((module2) => `${module2}: ${module2}.dictionary`),
47
- ...serviceModules.map((module2) => `${module2}: ${module2}.dictionary`)
54
+ ...databaseModules.map((module2) => {
55
+ const Module = capitalize(module2);
56
+ return `${module2}: registerModelTrans<"${module2}", ${module2}Cnst.${Module}, ${module2}Cnst.${Module}Insight, ${module2}Doc.${Module}Filter, ${module2}Sig.${Module}Slice, ${module2}Sig.${Module}Endpoint, typeof ${module2}.dictionary>(${module2}.dictionary)`;
57
+ }),
58
+ ...scalarModules.map(
59
+ (module2) => `${module2}: registerScalarTrans<"${module2}", ${module2}Cnst.${capitalize(module2)}, typeof ${module2}.dictionary>(${module2}.dictionary)`
60
+ ),
61
+ ...serviceModules.map(
62
+ (module2) => `${module2}: registerServiceTrans<"${module2}", ${module2}Sig.${capitalize(module2)}Endpoint, typeof ${module2}.dictionary>(${module2}.dictionary)`
63
+ )
48
64
  ].join(",\n ")}
49
- } as const);
65
+ });
50
66
 
51
- export const { Revert, translate, msg } = makeTrans(dictionary);
67
+ export const { Revert, translate, msg, __Dict_Key__, __Error_Key__ } = makeTrans(dictionary);
52
68
  `;
53
69
  }
@@ -30,7 +30,7 @@ function getContent(scanInfo, dict = {}) {
30
30
  const scalarConstantModules = [...scanInfo.scalar.entries()].filter(([_, files]) => files.has("constant")).map(([module2]) => module2);
31
31
  const serviceModules = [...scanInfo.service.entries()].filter(([_, files]) => files.has("signal")).map(([module2]) => module2);
32
32
  return `
33
- import { fetchOf, gqlOf, makeFetch, mergeSignals, signalInfo } from "@akanjs/signal";
33
+ import { fetchOf, gqlOf, makeFetch, mergeSignals, serverSignalOf, signalInfo } from "@akanjs/signal";
34
34
 
35
35
  import { root, libFetches } from "./__lib/lib.signal";
36
36
  import * as cnst from "./cnst";
@@ -46,9 +46,12 @@ ${[...scanInfo.database.entries()].filter(([_, files]) => files.has("signal")).m
46
46
  ([module2]) => `export class ${capitalize(module2)}Signal extends mergeSignals(${module2}Sig.${capitalize(module2)}Endpoint, ${module2}Sig.${capitalize(module2)}Internal, ${module2}Sig.${capitalize(module2)}Slice) {}`
47
47
  ).join("\n")}
48
48
  ${[...scanInfo.service.entries()].filter(([_, files]) => files.has("signal")).map(
49
- ([module2]) => `export const ${capitalize(module2)}Signal = mergeSignals(${module2}Sig.${capitalize(module2)}Endpoint, ${module2}Sig.${capitalize(module2)}Internal);`
49
+ ([module2]) => `export class ${capitalize(module2)}Signal extends mergeSignals(${module2}Sig.${capitalize(module2)}Endpoint, ${module2}Sig.${capitalize(module2)}Internal) {}`
50
50
  ).join("\n")}
51
51
 
52
+ ${[...scanInfo.database.entries()].filter(([_, files]) => files.has("signal")).map(([module2]) => `export class ${capitalize(module2)} extends serverSignalOf(${capitalize(module2)}Signal) {}`).join("\n")}
53
+ ${[...scanInfo.service.entries()].filter(([_, files]) => files.has("signal")).map(([module2]) => `export class ${capitalize(module2)} extends serverSignalOf(${capitalize(module2)}Signal) {}`).join("\n")}
54
+
52
55
  const signals = signalInfo.registerSignals(
53
56
  ${[...databaseModules, ...serviceModules].map((module2) => ` ${capitalize(module2)}Signal,`).join("\n")}
54
57
  );
@@ -25,13 +25,14 @@ module.exports = __toCommonJS(useClient_exports);
25
25
  function getContent(scanInfo, dict = {}) {
26
26
  return `
27
27
  import { makePageProto } from "@akanjs/client";
28
- import type * as signal from "./sig";
29
- import * as cnst from "./cnst";
30
28
 
31
- import type { dictionary } from "./dict";
29
+ import * as cnst from "./cnst";
30
+ import type { __Dict_Key__, __Error_Key__ } from "./dict";
31
+ import type * as signal from "./sig";
32
32
 
33
33
  export const { msg, Revert, usePage, sig, fetch, registerClient } = makePageProto<
34
- typeof dictionary,
34
+ typeof __Dict_Key__,
35
+ typeof __Error_Key__,
35
36
  typeof signal.fetch,
36
37
  typeof signal
37
38
  >(cnst);
@@ -24,7 +24,7 @@ __export(option_exports, {
24
24
  module.exports = __toCommonJS(option_exports);
25
25
  function getContent(scanInfo, dict = {}) {
26
26
  return `
27
- import { useGlobals } from "@akanjs/server";
27
+ import { Middleware, useGlobals } from "@akanjs/server";
28
28
 
29
29
  import type { LibOptions } from "./__lib/lib.service";
30
30
 
@@ -38,5 +38,9 @@ export const registerGlobalModule = (options: ModulesOptions) => {
38
38
  useAsyncs: {},
39
39
  });
40
40
  };
41
+
42
+ export const registerGlobalMiddlewares = (options: ModulesOptions) => {
43
+ return [] as Middleware[];
44
+ };
41
45
  `;
42
46
  }
@@ -40,8 +40,8 @@ export const General = ({ className }: ${dict.Model}EditProps) => {
40
40
  return (
41
41
  <Layout.Template className={className}>
42
42
  <Field.Text
43
- label={l.field("${dict.model}", "id")}
44
- desc={l.desc("${dict.model}", "id")}
43
+ label={l("${dict.model}.id")}
44
+ desc={l("${dict.model}.id.desc")}
45
45
  value={${dict.model}Form.id}
46
46
  onChange={st.do.setIdOn${dict.Model}}
47
47
  />
@@ -28,12 +28,19 @@ function getContent(scanInfo, dict) {
28
28
  content: `
29
29
  "use client";
30
30
  import { Model } from "@akanjs/ui";
31
+ import { usePage } from "@${dict.sysName}/client";
32
+ import { BiTrash } from "react-icons/bi";
31
33
 
32
34
  interface RemoveProps {
33
35
  ${dict.model}Id: string;
34
36
  }
35
37
  export const Remove = ({ ${dict.model}Id }: RemoveProps) => {
36
- return <Model.Remove modelId={${dict.model}Id} sliceName="${dict.model}" />;
38
+ const { l } = usePage();
39
+ return (
40
+ <Model.Remove modelId={${dict.model}Id} sliceName="${dict.model}">
41
+ <BiTrash /> {l("base.remove")}
42
+ </Model.Remove>
43
+ );
37
44
  };
38
45
  `
39
46
  };
@@ -24,21 +24,16 @@ __export(model_constant_exports, {
24
24
  module.exports = __toCommonJS(model_constant_exports);
25
25
  function getContent(scanInfo, dict) {
26
26
  return `
27
- import { enumOf, Int } from "@akanjs/base";
27
+ import { Int } from "@akanjs/base";
28
28
  import { via } from "@akanjs/constant";
29
29
 
30
- export const ${dict.Model}Status = enumOf(["active"] as const);
31
- export type ${dict.Model}Status = enumOf<typeof ${dict.Model}Status>;
32
-
33
30
  export class ${dict.Model}Input extends via((field) => ({
34
31
  field: field(String).optional(),
35
32
  })) {}
36
33
 
37
- export class ${dict.Model}Object extends via(${dict.Model}Input, (field) => ({
38
- status: field(${dict.Model}Status, { default: "active" }),
39
- })) {}
34
+ export class ${dict.Model}Object extends via(${dict.Model}Input, (field) => ({})) {}
40
35
 
41
- export class Light${dict.Model} extends via(${dict.Model}Object, ["status"] as const, (resolve) => ({})) {}
36
+ export class Light${dict.Model} extends via(${dict.Model}Object, [] as const, (resolve) => ({})) {}
42
37
 
43
38
  export class ${dict.Model} extends via(${dict.Model}Object, Light${dict.Model}, (resolve) => ({})) {}
44
39