@akanjs/cli 0.9.48 → 0.9.49

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 (128) hide show
  1. package/cjs/index.js +63 -52
  2. package/cjs/src/guidelines/___library/sharedUiStructureDescription.en.md +1 -1
  3. package/cjs/src/guidelines/databaseModule/databaseModule.instruction.md +9 -21
  4. package/cjs/src/guidelines/fieldDecorator/fieldDecorator.instruction.md +0 -5
  5. package/cjs/src/guidelines/framework/framework.instruction.md +10 -12
  6. package/cjs/src/guidelines/modelConstant/modelConstant.generate.json +0 -7
  7. package/cjs/src/guidelines/modelConstant/modelConstant.instruction.md +14 -19
  8. package/cjs/src/guidelines/modelDocument/modelDocument.instruction.md +0 -24
  9. package/cjs/src/guidelines/modelService/modelService.generate.json +4 -11
  10. package/cjs/src/guidelines/modelService/modelService.instruction.md +12 -75
  11. package/cjs/src/guidelines/modelSignal/modelSignal.generate.json +0 -1
  12. package/cjs/src/guidelines/modelSignal/modelSignal.instruction.md +2 -38
  13. package/cjs/src/guidelines/modelStore/modelStore.instruction.md +1 -3
  14. package/cjs/src/guidelines/modelTemplate/modelTemplate.instruction.md +2 -2
  15. package/cjs/src/guidelines/modelUnit/modelUnit.instruction.md +2 -2
  16. package/cjs/src/guidelines/scalarConstant/scalarConstant.instruction.md +6 -11
  17. package/cjs/src/templates/__scalar/__model__/__model__.constant.js +5 -6
  18. package/cjs/src/templates/__scalar/__model__/__model__.dictionary.js +1 -1
  19. package/cjs/src/templates/app/app/[lang]/layout.js +0 -1
  20. package/cjs/src/templates/app/app/csr.js +3 -1
  21. package/cjs/src/templates/app/lib/___appName__/__appName__.dictionary.js +1 -1
  22. package/cjs/src/templates/app/lib/___appName__/__appName__.service.js +2 -3
  23. package/cjs/src/templates/app/lib/___appName__/__appName__.signal.js +2 -3
  24. package/cjs/src/templates/app/lib/___appName__/__appName__.store.js +2 -3
  25. package/cjs/src/templates/client.js +4 -4
  26. package/cjs/src/templates/crudPages/[__model__Id]/edit/page.js +1 -1
  27. package/cjs/src/templates/crudPages/[__model__Id]/page.js +1 -1
  28. package/cjs/src/templates/crudPages/new/page.js +1 -1
  29. package/cjs/src/templates/crudPages/page.js +1 -1
  30. package/cjs/src/templates/index.js +0 -1
  31. package/cjs/src/templates/lib/__lib/lib.constant.js +0 -1
  32. package/cjs/src/templates/lib/__lib/lib.dictionary.js +7 -4
  33. package/cjs/src/templates/lib/__lib/lib.document.js +4 -3
  34. package/cjs/src/templates/lib/__lib/lib.service.js +1 -1
  35. package/cjs/src/templates/lib/__lib/lib.signal.js +23 -4
  36. package/cjs/src/templates/lib/__lib/lib.store.js +19 -2
  37. package/cjs/src/templates/lib/cnst.js +12 -6
  38. package/cjs/src/templates/lib/db.js +10 -3
  39. package/cjs/src/templates/lib/dict.js +12 -4
  40. package/cjs/src/templates/lib/sig.js +20 -9
  41. package/cjs/src/templates/lib/srv.js +7 -6
  42. package/cjs/src/templates/lib/st.js +10 -8
  43. package/cjs/src/templates/lib/useClient.js +39 -0
  44. package/cjs/src/templates/lib/{usePage.js → useServer.js} +6 -8
  45. package/cjs/src/templates/libRoot/lib/___libName__/__libName__.service.js +2 -3
  46. package/cjs/src/templates/libRoot/lib/___libName__/__libName__.store.js +2 -3
  47. package/cjs/src/templates/module/__model__.constant.js +10 -30
  48. package/cjs/src/templates/module/__model__.dictionary.js +2 -2
  49. package/cjs/src/templates/module/__model__.document.js +2 -8
  50. package/cjs/src/templates/module/__model__.service.js +2 -3
  51. package/cjs/src/templates/module/__model__.signal.js +4 -5
  52. package/cjs/src/templates/module/__model__.store.js +3 -4
  53. package/cjs/src/templates/server.js +5 -4
  54. package/cjs/src/templates/workspaceRoot/.gitignore.template +5 -3
  55. package/esm/index.js +63 -52
  56. package/esm/src/guidelines/___library/sharedUiStructureDescription.en.md +1 -1
  57. package/esm/src/guidelines/databaseModule/databaseModule.instruction.md +9 -21
  58. package/esm/src/guidelines/fieldDecorator/fieldDecorator.instruction.md +0 -5
  59. package/esm/src/guidelines/framework/framework.instruction.md +10 -12
  60. package/esm/src/guidelines/modelConstant/modelConstant.generate.json +0 -7
  61. package/esm/src/guidelines/modelConstant/modelConstant.instruction.md +14 -19
  62. package/esm/src/guidelines/modelDocument/modelDocument.instruction.md +0 -24
  63. package/esm/src/guidelines/modelService/modelService.generate.json +4 -11
  64. package/esm/src/guidelines/modelService/modelService.instruction.md +12 -75
  65. package/esm/src/guidelines/modelSignal/modelSignal.generate.json +0 -1
  66. package/esm/src/guidelines/modelSignal/modelSignal.instruction.md +2 -38
  67. package/esm/src/guidelines/modelStore/modelStore.instruction.md +1 -3
  68. package/esm/src/guidelines/modelTemplate/modelTemplate.instruction.md +2 -2
  69. package/esm/src/guidelines/modelUnit/modelUnit.instruction.md +2 -2
  70. package/esm/src/guidelines/scalarConstant/scalarConstant.instruction.md +6 -11
  71. package/esm/src/templates/__scalar/__model__/__model__.constant.js +5 -6
  72. package/esm/src/templates/__scalar/__model__/__model__.dictionary.js +1 -1
  73. package/esm/src/templates/app/app/[lang]/layout.js +0 -1
  74. package/esm/src/templates/app/app/csr.js +3 -1
  75. package/esm/src/templates/app/lib/___appName__/__appName__.dictionary.js +1 -1
  76. package/esm/src/templates/app/lib/___appName__/__appName__.service.js +2 -3
  77. package/esm/src/templates/app/lib/___appName__/__appName__.signal.js +2 -3
  78. package/esm/src/templates/app/lib/___appName__/__appName__.store.js +2 -3
  79. package/esm/src/templates/client.js +4 -4
  80. package/esm/src/templates/crudPages/[__model__Id]/edit/page.js +1 -1
  81. package/esm/src/templates/crudPages/[__model__Id]/page.js +1 -1
  82. package/esm/src/templates/crudPages/new/page.js +1 -1
  83. package/esm/src/templates/crudPages/page.js +1 -1
  84. package/esm/src/templates/index.js +0 -1
  85. package/esm/src/templates/lib/__lib/lib.constant.js +0 -1
  86. package/esm/src/templates/lib/__lib/lib.dictionary.js +7 -4
  87. package/esm/src/templates/lib/__lib/lib.document.js +4 -3
  88. package/esm/src/templates/lib/__lib/lib.service.js +1 -1
  89. package/esm/src/templates/lib/__lib/lib.signal.js +23 -4
  90. package/esm/src/templates/lib/__lib/lib.store.js +19 -2
  91. package/esm/src/templates/lib/cnst.js +12 -6
  92. package/esm/src/templates/lib/db.js +10 -3
  93. package/esm/src/templates/lib/dict.js +12 -4
  94. package/esm/src/templates/lib/sig.js +20 -9
  95. package/esm/src/templates/lib/srv.js +7 -6
  96. package/esm/src/templates/lib/st.js +10 -8
  97. package/esm/src/templates/lib/useClient.js +19 -0
  98. package/esm/src/templates/lib/useServer.js +11 -0
  99. package/esm/src/templates/libRoot/lib/___libName__/__libName__.service.js +2 -3
  100. package/esm/src/templates/libRoot/lib/___libName__/__libName__.store.js +2 -3
  101. package/esm/src/templates/module/__model__.constant.js +10 -30
  102. package/esm/src/templates/module/__model__.dictionary.js +2 -2
  103. package/esm/src/templates/module/__model__.document.js +2 -8
  104. package/esm/src/templates/module/__model__.service.js +2 -3
  105. package/esm/src/templates/module/__model__.signal.js +4 -5
  106. package/esm/src/templates/module/__model__.store.js +3 -4
  107. package/esm/src/templates/server.js +5 -4
  108. package/esm/src/templates/workspaceRoot/.gitignore.template +5 -3
  109. package/package.json +1 -1
  110. package/src/application/application.command.d.ts +7 -7
  111. package/src/application/application.script.d.ts +3 -1
  112. package/src/guidelines/___library/sharedUiStructureDescription.en.md +1 -1
  113. package/src/guidelines/databaseModule/databaseModule.instruction.md +9 -21
  114. package/src/guidelines/fieldDecorator/fieldDecorator.instruction.md +0 -5
  115. package/src/guidelines/framework/framework.instruction.md +10 -12
  116. package/src/guidelines/modelConstant/modelConstant.instruction.md +14 -19
  117. package/src/guidelines/modelDocument/modelDocument.instruction.md +0 -24
  118. package/src/guidelines/modelService/modelService.instruction.md +12 -75
  119. package/src/guidelines/modelSignal/modelSignal.instruction.md +2 -38
  120. package/src/guidelines/modelStore/modelStore.instruction.md +1 -3
  121. package/src/guidelines/modelTemplate/modelTemplate.instruction.md +2 -2
  122. package/src/guidelines/modelUnit/modelUnit.instruction.md +2 -2
  123. package/src/guidelines/scalarConstant/scalarConstant.instruction.md +6 -11
  124. package/src/templates/lib/useServer.d.ts +4 -0
  125. package/src/workspace/workspace.command.d.ts +1 -0
  126. package/src/workspace/workspace.script.d.ts +1 -0
  127. package/esm/src/templates/lib/usePage.js +0 -13
  128. /package/src/templates/lib/{usePage.d.ts → useClient.d.ts} +0 -0
@@ -47,7 +47,7 @@ export const UserRole = enumOf(["user", "admin"] as const);
47
47
  export type UserRole = enumOf<typeof UserRole>;
48
48
 
49
49
  // Define input model (for create/update operations)
50
- @Model.Input("UserInput")
50
+
51
51
  export class UserInput {
52
52
  @Field.Prop(() => String, { validate: validate.email, type: "email", example: "user@example.com" })
53
53
  email: string;
@@ -57,7 +57,7 @@ export class UserInput {
57
57
  }
58
58
 
59
59
  // Define object model (full data model)
60
- @Model.Object("UserObject")
60
+
61
61
  export class UserObject extends via(UserInput) {
62
62
  @Field.Prop(() => [String], [{ enum: UserRole, example: ["user"] }])
63
63
  roles: (typeof UserRole.value)[];
@@ -67,7 +67,7 @@ export class UserObject extends via(UserInput) {
67
67
  }
68
68
 
69
69
  // Define light model (client-side model with essential fields)
70
- @Model.Light("LightUser")
70
+
71
71
  export class LightUser extends via(UserObject, ["email", "roles"] as const) {
72
72
  hasAccess(role: UserRole) {
73
73
  return this.roles.includes(role);
@@ -75,11 +75,11 @@ export class LightUser extends via(UserObject, ["email", "roles"] as const) {
75
75
  }
76
76
 
77
77
  // Define full model (server-side model with all fields)
78
- @Model.Full("User")
78
+
79
79
  export class User extends via(UserObject, LightUser) {}
80
80
 
81
81
  // Define filter model (for queries)
82
- @Model.Filter("UserFilter")
82
+
83
83
  export class UserFilter extends sortOf(User, {}) {
84
84
  @Filter.Mongo()
85
85
  byEmail(@Filter.Arg("email", () => String) email: string) {
@@ -99,12 +99,8 @@ import { hashPassword } from "@shared/nest";
99
99
 
100
100
  import * as cnst from "../cnst";
101
101
 
102
- // Input model for database operations
103
- @Database.Input(() => cnst.UserInput)
104
- export class UserInput extends by(cnst.UserInput) {}
105
-
106
102
  // Document model with methods
107
- @Database.Document(() => cnst.User)
103
+
108
104
  export class User extends by(cnst.User) {
109
105
  addRole(role: cnst.UserRole) {
110
106
  if (!this.roles.includes(role)) this.roles = [...this.roles, role];
@@ -118,7 +114,7 @@ export class User extends by(cnst.User) {
118
114
  }
119
115
 
120
116
  // Model with database operations
121
- @Database.Model(() => cnst.User)
117
+
122
118
  export class UserModel extends into(User, cnst.userCnst, ...user.models) {
123
119
  @Loader.ByField("email") userEmailLoader: Loader<string, User>;
124
120
 
@@ -132,7 +128,7 @@ export class UserModel extends into(User, cnst.userCnst, ...user.models) {
132
128
  }
133
129
 
134
130
  // Middleware for hooks and indexes
135
- @Database.Middleware(() => cnst.User)
131
+
136
132
  export class UserMiddleware extends beyond(UserModel, User) {
137
133
  onSchema(schema: SchemaOf<UserModel, User>) {
138
134
  // Hash password before saving
@@ -158,7 +154,7 @@ export class UserMiddleware extends beyond(UserModel, User) {
158
154
  Implement business logic in the service:
159
155
 
160
156
  ```typescript
161
- import { DbService, Service, Srv, Use } from "@akanjs/service";
157
+ import { DbService, Srv, Use } from "@akanjs/service";
162
158
  import { Account, type Me } from "@akanjs/signal";
163
159
  import { isPasswordMatch } from "@shared/nest";
164
160
 
@@ -167,7 +163,6 @@ import * as db from "../db";
167
163
  import type * as option from "../option";
168
164
  import type * as srv from "../srv";
169
165
 
170
- @Service("UserService")
171
166
  export class UserService extends DbService(db.userDb) {
172
167
  @Use() protected readonly config: option.SecurityConfig;
173
168
  @Srv() protected readonly securityService: srv.util.SecurityService;
@@ -211,7 +206,6 @@ import { Account, Arg, DbSignal, Me, Mutation, Query, resolve, Signal } from "@a
211
206
  import * as cnst from "../cnst";
212
207
  import type * as db from "../db";
213
208
 
214
- @Signal(() => cnst.User)
215
209
  export class UserSignal extends DbSignal(cnst.userCnst, cnst.Srvs, {
216
210
  guards: { get: Query.Public, cru: Mutation.Admin },
217
211
  }) {
@@ -584,36 +578,30 @@ export const Layout = () => (
584
578
  ## Best Practices
585
579
 
586
580
  1. **Naming Conventions**
587
-
588
581
  - Use PascalCase for classes and components (e.g., `UserService`, `User.Unit.tsx`)
589
582
  - Use camelCase for files (e.g., `user.service.ts`, `user.document.ts`)
590
583
 
591
584
  2. **Security**
592
-
593
585
  - Use `@Field.Secret` for sensitive data like passwords
594
586
  - Apply proper permission guards to queries and mutations (`@Query.Admin`, `@Mutation.Public`)
595
587
  - Validate input data using the `validate` option in `@Field.Prop`
596
588
 
597
589
  3. **Code Organization**
598
-
599
590
  - Keep business logic in service files
600
591
  - Use signals for API calls only, not for business logic
601
592
  - Define reusable utility methods in document models
602
593
 
603
594
  4. **Performance**
604
-
605
595
  - Use dataloader pattern (`@Loader.ByField`) for efficient database access
606
596
  - Create proper indexes in the middleware
607
597
  - Use projections to limit returned fields when appropriate
608
598
 
609
599
  5. **Testing**
610
-
611
600
  - Create signal tests for each API endpoint
612
601
  - Mock services for unit testing signals
613
602
  - Use integration tests for testing complex workflows
614
603
 
615
604
  6. **UI Components**
616
-
617
605
  - Follow the separation between Template, Unit, View, and Zone components
618
606
  - Make components reusable across different parts of the application
619
607
  - Use dictionary files for all UI text to support internationalization
@@ -348,7 +348,6 @@ code: string;
348
348
  ### Input Models
349
349
 
350
350
  ```typescript
351
- @Model.Input("ProductInput")
352
351
  export class ProductInput {
353
352
  @Field.Prop(() => String)
354
353
  name: string;
@@ -361,7 +360,6 @@ export class ProductInput {
361
360
  ### Object Models
362
361
 
363
362
  ```typescript
364
- @Model.Object("ProductObject")
365
363
  export class ProductObject extends via(ProductInput) {
366
364
  @Field.Prop(() => Date, { default: dayjs() })
367
365
  createdAt: Dayjs;
@@ -371,21 +369,18 @@ export class ProductObject extends via(ProductInput) {
371
369
  ### Light Models
372
370
 
373
371
  ```typescript
374
- @Model.Light("LightProduct")
375
372
  export class LightProduct extends via(ProductObject, ["name", "price", "status"] as const) {}
376
373
  ```
377
374
 
378
375
  ### Full Models
379
376
 
380
377
  ```typescript
381
- @Model.Full("Product")
382
378
  export class Product extends via(ProductObject, LightProduct) {}
383
379
  ```
384
380
 
385
381
  ### Scalar Models
386
382
 
387
383
  ```typescript
388
- @Model.Scalar("Address")
389
384
  export class Address {
390
385
  @Field.Prop(() => String)
391
386
  street: string;
@@ -203,12 +203,10 @@ import { Project } from "./project.constant";
203
203
  import { projectService } from "./project.service";
204
204
 
205
205
  export class ProjectSignal {
206
- @Signal()
207
206
  async projectList() {
208
207
  return projectService.getProjects();
209
208
  }
210
209
 
211
- @Signal()
212
210
  async createProject(data: Partial<Project>) {
213
211
  return projectService.createProject(data);
214
212
  }
@@ -229,7 +227,11 @@ export const ProjectView = () => {
229
227
  return (
230
228
  <div>
231
229
  <h1>{l("project.modelName")}</h1>
232
- <div className="grid gap-4">{data?.map((project) => <ProjectUnit key={project.id} project={project} />)}</div>
230
+ <div className="grid gap-4">
231
+ {data?.map((project) => (
232
+ <ProjectUnit key={project.id} project={project} />
233
+ ))}
234
+ </div>
233
235
  </div>
234
236
  );
235
237
  };
@@ -322,22 +324,18 @@ import { Task, TaskFilter } from "./task.constant";
322
324
  import { taskService } from "./task.service";
323
325
 
324
326
  export class TaskSignal {
325
- @Signal()
326
327
  async taskList(query: TaskFilter, skip = 0, limit = 20) {
327
328
  return taskService.getTasks(query);
328
329
  }
329
330
 
330
- @Signal()
331
331
  async task(taskId: string) {
332
332
  return taskService.getTask(taskId);
333
333
  }
334
334
 
335
- @Signal()
336
335
  async createTask(data: Partial<Task>) {
337
336
  return taskService.createTask(data);
338
337
  }
339
338
 
340
- @Signal()
341
339
  async updateTaskStatus(taskId: string, status: Task["status"]) {
342
340
  return taskService.updateTaskStatus(taskId, status);
343
341
  }
@@ -581,22 +579,18 @@ import { Product, ProductFilter } from "./product.constant";
581
579
  import { productService } from "./product.service";
582
580
 
583
581
  export class ProductSignal {
584
- @Signal()
585
582
  async productList(query: ProductFilter, skip = 0, limit = 20) {
586
583
  return productService.getProducts(query, skip, limit);
587
584
  }
588
585
 
589
- @Signal()
590
586
  async product(productId: string) {
591
587
  return productService.getProduct(productId);
592
588
  }
593
589
 
594
- @Signal()
595
590
  async createProduct(data: Partial<Product>) {
596
591
  return productService.createProduct(data);
597
592
  }
598
593
 
599
- @Signal()
600
594
  async updateProduct(productId: string, data: Partial<Product>) {
601
595
  return productService.updateProduct(productId, data);
602
596
  }
@@ -625,7 +619,11 @@ export const ProductList = () => {
625
619
  ) : error ? (
626
620
  <div>Error: {error.message}</div>
627
621
  ) : (
628
- <ul>{products?.map((product) => <li key={product.id}>{product.name}</li>)}</ul>
622
+ <ul>
623
+ {products?.map((product) => (
624
+ <li key={product.id}>{product.name}</li>
625
+ ))}
626
+ </ul>
629
627
  )}
630
628
 
631
629
  <button onClick={() => createProduct({ name: "New Product" })} disabled={isCreating}>
@@ -63,13 +63,6 @@
63
63
  "filterText": "enumOf",
64
64
  "sample": 3
65
65
  },
66
- {
67
- "type": "example",
68
- "description": "Models with custom Filter methods",
69
- "path": "{apps,libs}/*/lib/*/*.constant.ts",
70
- "filterText": "@Filter.Mongo",
71
- "sample": 2
72
- },
73
66
  {
74
67
  "type": "example",
75
68
  "description": "Models with reference fields",
@@ -48,21 +48,21 @@ export const StatusEnum = enumOf(["active", "inactive"] as const);
48
48
  export type StatusEnum = enumOf<typeof StatusEnum>;
49
49
 
50
50
  // 3. Input Model
51
- @Model.Input("DroneInput")
51
+
52
52
  export class DroneInput {
53
53
  @Field.Prop(() => String)
54
54
  name: string;
55
55
  }
56
56
 
57
57
  // 4. Object Model
58
- @Model.Object("DroneObject")
58
+
59
59
  export class DroneObject extends BaseModel(DroneInput) {
60
60
  @Field.Prop(() => String, { enum: StatusEnum, default: "offline" })
61
61
  status: StatusEnum;
62
62
  }
63
63
 
64
64
  // 5. Light Model
65
- @Model.Light("LightDrone")
65
+
66
66
  export class LightDrone extends Light(DroneObject, ["id", "name", "status"] as const) {
67
67
  isConnected() {
68
68
  return this.status !== "offline";
@@ -70,7 +70,7 @@ export class LightDrone extends Light(DroneObject, ["id", "name", "status"] as c
70
70
  }
71
71
 
72
72
  // 6. Full Model
73
- @Model.Full("Drone")
73
+
74
74
  export class Drone extends Full(DroneObject, LightDrone) {
75
75
  isAvailable() {
76
76
  return this.isConnected() && this.wsUri.startsWith("ws://");
@@ -78,7 +78,7 @@ export class Drone extends Full(DroneObject, LightDrone) {
78
78
  }
79
79
 
80
80
  // 7. Insight Model
81
- @Model.Insight("DroneInsight")
81
+
82
82
  export class DroneInsight {
83
83
  @Field.Prop(() => Int, { default: 0, accumulate: { $sum: 1 } })
84
84
  count: number;
@@ -113,7 +113,6 @@ import { LightCategory } from "../category/category.constant";
113
113
  The Input model defines fields required for data creation:
114
114
 
115
115
  ```typescript
116
- @Model.Input("DroneInput")
117
116
  export class DroneInput {
118
117
  @Field.Prop(() => String)
119
118
  name: string;
@@ -144,7 +143,6 @@ The Object model adds system-managed fields:
144
143
  export const droneStatuses = ["active", "offline", "inactive"] as const;
145
144
  export type DroneStatus = (typeof droneStatuses)[number];
146
145
 
147
- @Model.Object("DroneObject")
148
146
  export class DroneObject extends BaseModel(DroneInput) {
149
147
  @Field.Prop(() => String, { enum: droneStatuses, default: "offline" })
150
148
  status: DroneStatus;
@@ -172,7 +170,6 @@ const drone = st.use.drone(); // drone.status
172
170
  Light model defines lightweight schema for list queries:
173
171
 
174
172
  ```typescript
175
- @Model.Light("LightDrone")
176
173
  export class LightDrone extends Light(DroneObject, ["name", "status"] as const) {
177
174
  isConnected() {
178
175
  return this.status !== "offline";
@@ -196,7 +193,6 @@ const droneMap = st.use.droneMap(); // Map<string, LightDrone>
196
193
  Full model adds convenience functions:
197
194
 
198
195
  ```typescript
199
- @Model.Full("Drone")
200
196
  export class Drone extends Full(DroneObject, LightDrone) {
201
197
  static isDronesAllConnected(droneList: LightDrone[]) {
202
198
  return droneList.every((drone) => drone.isConnected());
@@ -226,7 +222,6 @@ const isAllConnected = cnst.Drone.isDroneAllConnected(droneList);
226
222
  Insight model defines statistical fields:
227
223
 
228
224
  ```typescript
229
- @Model.Insight("DroneInsight")
230
225
  export class DroneInsight {
231
226
  @Field.Prop(() => Int, { default: 0, accumulate: { $sum: 1 } })
232
227
  count: number;
@@ -371,13 +366,11 @@ graph LR
371
366
  ### 1. Scalar Embedded Style
372
367
 
373
368
  ```typescript
374
- @Model.Scalar("DronePhysicalState")
375
369
  export class DronePhysicalState {
376
370
  @Field.Prop(() => [Float], { default: [0, 0, 0] })
377
371
  rpy: [number, number, number];
378
372
  }
379
373
 
380
- @Model.Object("DroneObject")
381
374
  export class DroneObject {
382
375
  @Field.Prop(() => DronePhysicalState)
383
376
  physicalState: DronePhysicalState;
@@ -387,7 +380,6 @@ export class DroneObject {
387
380
  ### 2. Reference ID Style
388
381
 
389
382
  ```typescript
390
- @Model.Input("MissionInput")
391
383
  export class MissionInput {
392
384
  @Field.Prop(() => ID, { ref: "drone" })
393
385
  drone: string;
@@ -397,7 +389,6 @@ export class MissionInput {
397
389
  ### 3. Resolved Reference Style
398
390
 
399
391
  ```typescript
400
- @Model.Object("DroneObject")
401
392
  export class DroneObject {
402
393
  @Field.Prop(() => LightMission, { nullable: true })
403
394
  mission: LightMission | null;
@@ -417,6 +408,7 @@ import { LightMission } from "../cnst_";
417
408
  ## Best Practices for Maintainable Models
418
409
 
419
410
  1. **Consistent Naming**:
411
+
420
412
  - Input: `DroneInput`
421
413
  - Object: `DroneObject`
422
414
  - Light: `LightDrone`
@@ -424,16 +416,19 @@ import { LightMission } from "../cnst_";
424
416
  - Sort: `droneSort`
425
417
 
426
418
  2. **Reference Handling**:
419
+
427
420
  - Use Light models for references
428
421
  - Avoid circular dependencies
429
422
  - Prefer direct imports over barrel files
430
423
 
431
424
  3. **Field Design**:
425
+
432
426
  - Use proper field types (Prop, Hidden, Secret, Resolve)
433
427
  - Set appropriate defaults (especially for arrays)
434
428
  - Add validation where needed
435
429
 
436
430
  4. **Performance Optimization**:
431
+
437
432
  - Use Light models for list queries
438
433
  - Keep Insight/Summary models lean
439
434
  - Use appropriate indexes for queries
@@ -450,21 +445,21 @@ import { ID, Int, String } from "@akanjs/base";
450
445
  import { Field, Model } from "@akanjs/constant";
451
446
 
452
447
  // Input Model
453
- @Model.Input("DroneInput")
448
+
454
449
  export class DroneInput {
455
450
  @Field.Prop(() => String)
456
451
  name: string;
457
452
  }
458
453
 
459
454
  // Object Model
460
- @Model.Object("DroneObject")
455
+
461
456
  export class DroneObject extends BaseModel(DroneInput) {
462
457
  @Field.Prop(() => String, { enum: ["active", "offline"], default: "offline" })
463
458
  status: string;
464
459
  }
465
460
 
466
461
  // Light Model
467
- @Model.Light("LightDrone")
462
+
468
463
  export class LightDrone extends Light(DroneObject, ["id", "name", "status"] as const) {
469
464
  isConnected() {
470
465
  return this.status === "active";
@@ -472,7 +467,7 @@ export class LightDrone extends Light(DroneObject, ["id", "name", "status"] as c
472
467
  }
473
468
 
474
469
  // Full Model
475
- @Model.Full("Drone")
470
+
476
471
  export class Drone extends Full(DroneObject, LightDrone) {
477
472
  isAvailable() {
478
473
  return this.isConnected() && this.battery > 20;
@@ -480,7 +475,7 @@ export class Drone extends Full(DroneObject, LightDrone) {
480
475
  }
481
476
 
482
477
  // Insight Model
483
- @Model.Insight("DroneInsight")
478
+
484
479
  export class DroneInsight {
485
480
  @Field.Prop(() => Int, { accumulate: { $sum: 1 } })
486
481
  count: number;
@@ -16,21 +16,11 @@
16
16
 
17
17
  A `model.document.ts` file is structured into four distinct classes, each with a specific responsibility:
18
18
 
19
- ### 1. Input Class
20
-
21
- Defines the data structure for create/update operations:
22
-
23
- ```typescript
24
- @Database.Input(() => cnst.ExampleInput)
25
- export class ExampleInput extends by(cnst.ExampleInput) {}
26
- ```
27
-
28
19
  ### 2. Document Class
29
20
 
30
21
  Represents a MongoDB document with instance methods:
31
22
 
32
23
  ```typescript
33
- @Database.Document(() => cnst.Example)
34
24
  export class Example extends by(cnst.Example) {
35
25
  // Document methods here
36
26
  }
@@ -41,7 +31,6 @@ export class Example extends by(cnst.Example) {
41
31
  Represents the MongoDB collection with static methods:
42
32
 
43
33
  ```typescript
44
- @Database.Model(() => cnst.Example)
45
34
  export class ExampleModel extends into(Example, cnst.exampleCnst) {
46
35
  // Model statics here
47
36
  }
@@ -52,7 +41,6 @@ export class ExampleModel extends into(Example, cnst.exampleCnst) {
52
41
  Defines schema hooks and indexes:
53
42
 
54
43
  ```typescript
55
- @Database.Middleware(() => cnst.Example)
56
44
  export class ExampleMiddleware extends beyond(ExampleModel, Example) {
57
45
  onSchema(schema) {
58
46
  // Middleware and indexes here
@@ -74,7 +62,6 @@ Document methods operate on individual document instances and typically follow t
74
62
  ### Example of Document Methods:
75
63
 
76
64
  ```typescript
77
- @Database.Document(() => cnst.User)
78
65
  export class User extends by(cnst.User) {
79
66
  // Simple transformation method (synchronous)
80
67
  addRole(role: string) {
@@ -113,7 +100,6 @@ Model statics operate on the entire collection and are typically asynchronous. T
113
100
  ### Example of Model Statics:
114
101
 
115
102
  ```typescript
116
- @Database.Model(() => cnst.Order)
117
103
  export class OrderModel extends into(Order, cnst.orderCnst) {
118
104
  // Query by specific criteria
119
105
  async findPendingOrders(userId: string) {
@@ -206,7 +192,6 @@ Middleware allows you to intercept and modify document operations at various lif
206
192
  ### Example Middleware Implementation:
207
193
 
208
194
  ```typescript
209
- @Database.Middleware(() => cnst.User)
210
195
  export class UserMiddleware extends beyond(UserModel, User) {
211
196
  onSchema(schema: SchemaOf<UserModel, User>) {
212
197
  // Pre-save hook for password hashing
@@ -258,7 +243,6 @@ Indexes are crucial for query performance. Define them in the Middleware's `onSc
258
243
  ### Example Index Implementation:
259
244
 
260
245
  ```typescript
261
- @Database.Middleware(() => cnst.Product)
262
246
  export class ProductMiddleware extends beyond(ProductModel, Product) {
263
247
  onSchema(schema: SchemaOf<ProductModel, Product>) {
264
248
  // Single field index (1=ascending, -1=descending)
@@ -346,7 +330,6 @@ DataLoader batches and caches database requests to optimize performance, especia
346
330
  ### Example DataLoader Implementation:
347
331
 
348
332
  ```typescript
349
- @Database.Model(() => cnst.Order)
350
333
  export class OrderModel extends into(Order, cnst.orderCnst) {
351
334
  // Load orders by user ID
352
335
  @Loader.ByField("userId")
@@ -461,7 +444,6 @@ const resultCount = await productModel.searchCountProduct("wireless headphones")
461
444
  Use transactions for operations that need to be atomic:
462
445
 
463
446
  ```typescript
464
- @Database.Model(() => cnst.Order)
465
447
  export class OrderModel extends into(Order, cnst.orderCnst) {
466
448
  @Transaction()
467
449
  async createOrderWithItems(orderData, items) {
@@ -497,10 +479,6 @@ import { dayjs } from "@akanjs/base";
497
479
  import { beyond, by, Database, into, Loader, SchemaOf } from "@akanjs/document";
498
480
  import * as cnst from "../cnst";
499
481
 
500
- @Database.Input(() => cnst.ProductInput)
501
- export class ProductInput extends by(cnst.ProductInput) {}
502
-
503
- @Database.Document(() => cnst.Product)
504
482
  export class Product extends by(cnst.Product) {
505
483
  applyDiscount(percentage: number) {
506
484
  if (percentage < 0 || percentage > 100) {
@@ -529,7 +507,6 @@ export class Product extends by(cnst.Product) {
529
507
  }
530
508
  }
531
509
 
532
- @Database.Model(() => cnst.Product)
533
510
  export class ProductModel extends into(Product, cnst.productCnst) {
534
511
  @Loader.ByField("category")
535
512
  categoryProductsLoader: Loader<string, Product[]>;
@@ -579,7 +556,6 @@ export class ProductModel extends into(Product, cnst.productCnst) {
579
556
  }
580
557
  }
581
558
 
582
- @Database.Middleware(() => cnst.Product)
583
559
  export class ProductMiddleware extends beyond(ProductModel, Product) {
584
560
  onSchema(schema: SchemaOf<ProductModel, Product>) {
585
561
  // Update stock status on save
@@ -24,13 +24,6 @@
24
24
  "path": "libs/shared/lib/user/user.service.ts",
25
25
  "sample": 1
26
26
  },
27
- {
28
- "type": "example",
29
- "description": "@Service decorator examples",
30
- "path": "{apps,libs}/*/lib/*/*.service.ts",
31
- "filterText": "@Service",
32
- "sample": 2
33
- },
34
27
  {
35
28
  "type": "example",
36
29
  "description": "@Use decorator examples",
@@ -89,9 +82,9 @@
89
82
  },
90
83
  {
91
84
  "type": "example",
92
- "description": "LogService examples",
85
+ "description": "serve examples",
93
86
  "path": "{apps,libs}/*/lib/*/*.service.ts",
94
- "filterText": "LogService",
87
+ "filterText": "serve",
95
88
  "sample": 1
96
89
  },
97
90
  {
@@ -113,8 +106,8 @@
113
106
  "filePath": "./modelService.instruction.md",
114
107
  "contents": [
115
108
  "Purpose and role of model.service.ts files",
116
- "Service structure and inheritance (DbService, LogService, MixSrvs)",
117
- "Core decorators (@Service, @Srv, @Use, @Db, @Sig)",
109
+ "Service structure and inheritance (DbService, serve, MixSrvs)",
110
+ "Core decorators (@Srv, @Use, @Db, @Sig)",
118
111
  "Database operations (CRUD, queries, search)",
119
112
  "Customizing database operations (_preCreate, _postCreate, _preUpdate, _postUpdate, _preRemove, _postRemove)",
120
113
  "Working with other services (dependency injection patterns)",