@venizia/ignis-docs 0.0.3 → 0.0.4-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 (131) hide show
  1. package/README.md +1 -1
  2. package/package.json +4 -2
  3. package/wiki/best-practices/api-usage-examples.md +591 -0
  4. package/wiki/best-practices/architectural-patterns.md +415 -0
  5. package/wiki/best-practices/architecture-decisions.md +488 -0
  6. package/wiki/{get-started/best-practices → best-practices}/code-style-standards.md +406 -17
  7. package/wiki/{get-started/best-practices → best-practices}/common-pitfalls.md +109 -4
  8. package/wiki/{get-started/best-practices → best-practices}/contribution-workflow.md +34 -7
  9. package/wiki/best-practices/data-modeling.md +376 -0
  10. package/wiki/best-practices/deployment-strategies.md +698 -0
  11. package/wiki/best-practices/index.md +27 -0
  12. package/wiki/best-practices/performance-optimization.md +196 -0
  13. package/wiki/best-practices/security-guidelines.md +218 -0
  14. package/wiki/{get-started/best-practices → best-practices}/troubleshooting-tips.md +97 -1
  15. package/wiki/changelogs/2025-12-16-initial-architecture.md +1 -1
  16. package/wiki/changelogs/2025-12-16-model-repo-datasource-refactor.md +1 -1
  17. package/wiki/changelogs/2025-12-17-refactor.md +1 -1
  18. package/wiki/changelogs/2025-12-18-performance-optimizations.md +5 -5
  19. package/wiki/changelogs/2025-12-18-repository-validation-security.md +13 -7
  20. package/wiki/changelogs/2025-12-26-nested-relations-and-generics.md +2 -2
  21. package/wiki/changelogs/2025-12-29-dynamic-binding-registration.md +104 -0
  22. package/wiki/changelogs/2025-12-29-snowflake-uid-helper.md +100 -0
  23. package/wiki/changelogs/2025-12-30-repository-enhancements.md +214 -0
  24. package/wiki/changelogs/2025-12-31-json-path-filtering-array-operators.md +214 -0
  25. package/wiki/changelogs/2025-12-31-string-id-custom-generator.md +137 -0
  26. package/wiki/changelogs/2026-01-02-default-filter-and-repository-mixins.md +418 -0
  27. package/wiki/changelogs/index.md +6 -0
  28. package/wiki/changelogs/planned-schema-migrator.md +0 -8
  29. package/wiki/{get-started/core-concepts → guides/core-concepts/application}/bootstrapping.md +18 -5
  30. package/wiki/{get-started/core-concepts/application.md → guides/core-concepts/application/index.md} +47 -104
  31. package/wiki/guides/core-concepts/components-guide.md +509 -0
  32. package/wiki/{get-started → guides}/core-concepts/components.md +24 -17
  33. package/wiki/{get-started → guides}/core-concepts/controllers.md +30 -13
  34. package/wiki/{get-started → guides}/core-concepts/dependency-injection.md +97 -0
  35. package/wiki/guides/core-concepts/persistent/datasources.md +179 -0
  36. package/wiki/guides/core-concepts/persistent/index.md +119 -0
  37. package/wiki/guides/core-concepts/persistent/models.md +241 -0
  38. package/wiki/guides/core-concepts/persistent/repositories.md +219 -0
  39. package/wiki/guides/core-concepts/persistent/transactions.md +170 -0
  40. package/wiki/{get-started → guides}/core-concepts/services.md +26 -3
  41. package/wiki/{get-started → guides/get-started}/5-minute-quickstart.md +59 -14
  42. package/wiki/guides/get-started/philosophy.md +682 -0
  43. package/wiki/guides/get-started/setup.md +157 -0
  44. package/wiki/guides/index.md +89 -0
  45. package/wiki/guides/reference/glossary.md +243 -0
  46. package/wiki/{get-started → guides/reference}/mcp-docs-server.md +0 -10
  47. package/wiki/{get-started → guides/tutorials}/building-a-crud-api.md +134 -132
  48. package/wiki/{get-started/quickstart.md → guides/tutorials/complete-installation.md} +107 -71
  49. package/wiki/guides/tutorials/ecommerce-api.md +1399 -0
  50. package/wiki/guides/tutorials/realtime-chat.md +1261 -0
  51. package/wiki/guides/tutorials/testing.md +723 -0
  52. package/wiki/index.md +176 -37
  53. package/wiki/references/base/application.md +27 -0
  54. package/wiki/references/base/bootstrapping.md +30 -26
  55. package/wiki/references/base/components.md +24 -7
  56. package/wiki/references/base/controllers.md +51 -20
  57. package/wiki/references/base/datasources.md +30 -0
  58. package/wiki/references/base/dependency-injection.md +39 -3
  59. package/wiki/references/base/filter-system/application-usage.md +224 -0
  60. package/wiki/references/base/filter-system/array-operators.md +132 -0
  61. package/wiki/references/base/filter-system/comparison-operators.md +109 -0
  62. package/wiki/references/base/filter-system/default-filter.md +428 -0
  63. package/wiki/references/base/filter-system/fields-order-pagination.md +155 -0
  64. package/wiki/references/base/filter-system/index.md +127 -0
  65. package/wiki/references/base/filter-system/json-filtering.md +197 -0
  66. package/wiki/references/base/filter-system/list-operators.md +71 -0
  67. package/wiki/references/base/filter-system/logical-operators.md +156 -0
  68. package/wiki/references/base/filter-system/null-operators.md +58 -0
  69. package/wiki/references/base/filter-system/pattern-matching.md +108 -0
  70. package/wiki/references/base/filter-system/quick-reference.md +431 -0
  71. package/wiki/references/base/filter-system/range-operators.md +63 -0
  72. package/wiki/references/base/filter-system/tips.md +190 -0
  73. package/wiki/references/base/filter-system/use-cases.md +452 -0
  74. package/wiki/references/base/index.md +90 -0
  75. package/wiki/references/base/middlewares.md +602 -0
  76. package/wiki/references/base/models.md +215 -23
  77. package/wiki/references/base/providers.md +732 -0
  78. package/wiki/references/base/repositories/advanced.md +555 -0
  79. package/wiki/references/base/repositories/index.md +228 -0
  80. package/wiki/references/base/repositories/mixins.md +331 -0
  81. package/wiki/references/base/repositories/relations.md +486 -0
  82. package/wiki/references/base/repositories.md +40 -635
  83. package/wiki/references/base/services.md +28 -4
  84. package/wiki/references/components/authentication.md +22 -2
  85. package/wiki/references/components/health-check.md +12 -0
  86. package/wiki/references/components/index.md +23 -0
  87. package/wiki/references/components/mail.md +687 -0
  88. package/wiki/references/components/request-tracker.md +16 -0
  89. package/wiki/references/components/socket-io.md +18 -0
  90. package/wiki/references/components/static-asset.md +14 -26
  91. package/wiki/references/components/swagger.md +17 -0
  92. package/wiki/references/configuration/environment-variables.md +427 -0
  93. package/wiki/references/configuration/index.md +73 -0
  94. package/wiki/references/helpers/cron.md +14 -0
  95. package/wiki/references/helpers/crypto.md +15 -0
  96. package/wiki/references/helpers/env.md +16 -0
  97. package/wiki/references/helpers/error.md +17 -0
  98. package/wiki/references/helpers/index.md +14 -0
  99. package/wiki/references/helpers/inversion.md +24 -4
  100. package/wiki/references/helpers/logger.md +19 -0
  101. package/wiki/references/helpers/network.md +11 -0
  102. package/wiki/references/helpers/queue.md +19 -0
  103. package/wiki/references/helpers/redis.md +21 -0
  104. package/wiki/references/helpers/socket-io.md +24 -5
  105. package/wiki/references/helpers/storage.md +18 -10
  106. package/wiki/references/helpers/testing.md +18 -0
  107. package/wiki/references/helpers/types.md +16 -0
  108. package/wiki/references/helpers/uid.md +167 -0
  109. package/wiki/references/helpers/worker-thread.md +16 -0
  110. package/wiki/references/index.md +177 -0
  111. package/wiki/references/quick-reference.md +634 -0
  112. package/wiki/references/src-details/boot.md +3 -3
  113. package/wiki/references/src-details/dev-configs.md +0 -4
  114. package/wiki/references/src-details/docs.md +2 -2
  115. package/wiki/references/src-details/index.md +86 -0
  116. package/wiki/references/src-details/inversion.md +1 -6
  117. package/wiki/references/src-details/mcp-server.md +3 -15
  118. package/wiki/references/utilities/index.md +86 -10
  119. package/wiki/references/utilities/jsx.md +577 -0
  120. package/wiki/references/utilities/request.md +0 -2
  121. package/wiki/references/utilities/statuses.md +740 -0
  122. package/wiki/get-started/best-practices/api-usage-examples.md +0 -266
  123. package/wiki/get-started/best-practices/architectural-patterns.md +0 -170
  124. package/wiki/get-started/best-practices/data-modeling.md +0 -177
  125. package/wiki/get-started/best-practices/deployment-strategies.md +0 -121
  126. package/wiki/get-started/best-practices/performance-optimization.md +0 -97
  127. package/wiki/get-started/best-practices/security-guidelines.md +0 -99
  128. package/wiki/get-started/core-concepts/persistent.md +0 -539
  129. package/wiki/get-started/index.md +0 -65
  130. package/wiki/get-started/philosophy.md +0 -296
  131. package/wiki/get-started/prerequisites.md +0 -113
@@ -0,0 +1,415 @@
1
+ # Architectural Patterns
2
+
3
+ Ignis promotes separation of concerns, dependency injection, and modularity for scalable, maintainable applications.
4
+
5
+ > **Deep Dive:** See [Core Framework Reference](../references/src-details/core.md) for implementation details.
6
+
7
+ ## 1. Layered Architecture
8
+
9
+ Each layer has a single responsibility. Ignis supports **two architectural approaches**:
10
+
11
+ ```mermaid
12
+ graph TD
13
+ Client[Client/API Consumer]
14
+
15
+ Client -->|HTTP Request| Controller[Controllers]
16
+
17
+ Controller -->|Simple CRUD| Repo[Repositories]
18
+ Controller -->|Complex Logic| Service[Services]
19
+
20
+ Service --> Repo
21
+
22
+ Repo --> DataSource[DataSources]
23
+ DataSource --> DB[(Database)]
24
+
25
+ style Service fill:#e1f5ff
26
+ style Repo fill:#fff4e1
27
+ style Controller fill:#ffe1f5
28
+ ```
29
+
30
+ | Layer | Responsibility | Example |
31
+ |-------|---------------|---------|
32
+ | **Controllers** | Handle HTTP - parse requests, validate, format responses | `ConfigurationController` (uses `ControllerFactory`) |
33
+ | **Services** | Business logic - orchestrate operations | `AuthenticationService` (auth logic) |
34
+ | **Repositories** | Data access - CRUD operations | `ConfigurationRepository` (extends `DefaultCRUDRepository`) |
35
+ | **DataSources** | Database connections | `PostgresDataSource` (connects to PostgreSQL) |
36
+ | **Models** | Data structure - Drizzle schemas + Entity classes | `Configuration`, `User` models |
37
+
38
+ **Key Principle - Two Approaches:**
39
+
40
+ ```
41
+ Simple CRUD (no business logic):
42
+ ┌────────────┐
43
+ │ Controller │──────────────┐
44
+ └────────────┘ │
45
+
46
+ ┌──────────────┐
47
+ │ Repository │
48
+ └──────────────┘
49
+
50
+
51
+ Database
52
+
53
+ Complex Logic (validation, orchestration):
54
+ ┌────────────┐
55
+ │ Controller │────┐
56
+ └────────────┘ │
57
+
58
+ ┌─────────┐
59
+ │ Service │
60
+ └─────────┘
61
+
62
+
63
+ ┌──────────────┐
64
+ │ Repository │
65
+ └──────────────┘
66
+
67
+
68
+ Database
69
+ ```
70
+
71
+ **When to use each:**
72
+ - **Controller → Repository** - Simple CRUD (list, get by ID, create, update, delete)
73
+ - **Controller → Service → Repository** - Business logic, validation, orchestrating multiple repositories
74
+
75
+ ## 2. Dependency Injection (DI)
76
+
77
+ Classes declare dependencies in their constructor - the framework automatically provides them at runtime.
78
+
79
+ **Benefits:**
80
+ - Loosely coupled code
81
+ - Easy to test (mock dependencies)
82
+ - Easy to swap implementations
83
+
84
+ **Example:**
85
+ ```typescript
86
+ @controller({ path: BASE_PATH })
87
+ export class ConfigurationController extends _Controller {
88
+ constructor(
89
+ // The @inject decorator tells the container to provide
90
+ // an instance of ConfigurationRepository here.
91
+ @inject({
92
+ key: BindingKeys.build({
93
+ namespace: BindingNamespaces.REPOSITORY,
94
+ key: ConfigurationRepository.name,
95
+ }),
96
+ })
97
+ repository: ConfigurationRepository,
98
+ ) {
99
+ super(repository);
100
+ }
101
+ }
102
+ ```
103
+
104
+ ## 3. Component-Based Modularity
105
+
106
+ Components bundle a group of related, reusable, and pluggable features into self-contained modules. A single component can encapsulate multiple providers, services, controllers, and repositories, essentially functioning as a mini-application that can be easily "plugged in" to any Ignis project.
107
+
108
+ **Built-in Components:**
109
+ - `AuthenticateComponent` - JWT authentication
110
+ - `SwaggerComponent` - OpenAPI documentation
111
+ - `HealthCheckComponent` - Health check endpoint
112
+ - `RequestTrackerComponent` - Request logging
113
+
114
+ **Example:**
115
+ ```typescript
116
+ // src/application.ts
117
+
118
+ export class Application extends BaseApplication {
119
+ // ...
120
+ preConfigure(): ValueOrPromise<void> {
121
+ // ...
122
+ // Registering components plugs their functionality into the application.
123
+ this.component(HealthCheckComponent);
124
+ this.component(SwaggerComponent);
125
+ // ...
126
+ }
127
+ }
128
+ ```
129
+ This architecture keeps the main `Application` class clean and focused on high-level assembly, while the details of each feature are neatly encapsulated within their respective components.
130
+
131
+ ## 4. Custom Components
132
+
133
+ You can encapsulate your own logic or third-party integrations (like Socket.IO, Redis, specific Cron jobs) into reusable Components.
134
+
135
+ **Structure of a Component:**
136
+ 1. Extend `BaseComponent`.
137
+ 2. Define default `bindings` (optional configuration/options).
138
+ 3. Implement `binding()` to register services, providers, or attach logic to the application.
139
+
140
+ **Example (`SocketIOComponent`):**
141
+
142
+ ```typescript
143
+ import { BaseComponent, inject, CoreBindings, Binding } from '@venizia/ignis';
144
+
145
+ export class MySocketComponent extends BaseComponent {
146
+ constructor(
147
+ @inject({ key: CoreBindings.APPLICATION_INSTANCE }) private application: BaseApplication,
148
+ ) {
149
+ super({
150
+ scope: MySocketComponent.name,
151
+ // Automatically register bindings when component is loaded
152
+ initDefault: { enable: true, container: application },
153
+ bindings: {
154
+ // Define default configuration binding
155
+ 'my.socket.options': Binding.bind({ key: 'my.socket.options' }).toValue({ port: 8080 }),
156
+ },
157
+ });
158
+ }
159
+
160
+ // The binding method is called during application startup (preConfigure)
161
+ override binding(): void {
162
+ const options = this.application.get({ key: 'my.socket.options' });
163
+
164
+ this.logger.info('Initializing Socket.IO with options: %j', options);
165
+
166
+ // Perform setup logic, register other services, etc.
167
+ // this.application.bind(...).toValue(...);
168
+ }
169
+ }
170
+ ```
171
+
172
+ ## 5. Application Lifecycle Hooks
173
+
174
+ Ignis applications follow a predictable startup sequence with hooks for customization:
175
+
176
+ ```
177
+ ┌─────────────────────────────────────────────────────────────┐
178
+ │ initialize() │
179
+ ├─────────────────────────────────────────────────────────────┤
180
+ │ 1. printStartUpInfo() - Log startup configuration │
181
+ │ 2. validateEnvs() - Validate APP_ENV_* variables │
182
+ │ 3. registerDefaultMiddlewares() - Error handlers, favicon │
183
+ │ 4. staticConfigure() - Configure static file serving │
184
+ │ │
185
+ │ ┌─────────────────────────────────────────────────────┐ │
186
+ │ │ 5. preConfigure() ← YOUR CODE HERE │ │
187
+ │ │ - Register DataSources │ │
188
+ │ │ - Register Repositories │ │
189
+ │ │ - Register Services │ │
190
+ │ │ - Register Controllers │ │
191
+ │ │ - Register Components │ │
192
+ │ └─────────────────────────────────────────────────────┘ │
193
+ │ │
194
+ │ 6. registerDataSources() - Initialize DB connections │
195
+ │ 7. registerComponents() - Configure all components │
196
+ │ 8. registerControllers() - Mount routes to router │
197
+ │ │
198
+ │ ┌─────────────────────────────────────────────────────┐ │
199
+ │ │ 9. postConfigure() ← YOUR CODE HERE │ │
200
+ │ │ - Seed data │ │
201
+ │ │ - Start background jobs │ │
202
+ │ │ - Custom initialization │ │
203
+ │ └─────────────────────────────────────────────────────┘ │
204
+ └─────────────────────────────────────────────────────────────┘
205
+ ```
206
+
207
+ **Lifecycle Methods:**
208
+
209
+ | Method | When | Purpose |
210
+ |--------|------|---------|
211
+ | `staticConfigure()` | Before DI registration | Configure static file serving |
212
+ | `preConfigure()` | Before auto-registration | Register all bindings (datasources, repos, services, controllers, components) |
213
+ | `postConfigure()` | After everything is registered | Seed data, start jobs, custom logic |
214
+
215
+ **Example:**
216
+ ```typescript
217
+ export class Application extends BaseApplication {
218
+ // Called before automatic registration
219
+ async preConfigure(): Promise<void> {
220
+ // DataSources (order matters - first)
221
+ this.dataSource(PostgresDataSource);
222
+
223
+ // Repositories
224
+ this.repository(UserRepository);
225
+ this.repository(OrderRepository);
226
+
227
+ // Services
228
+ this.service(AuthService);
229
+ this.service(EmailService);
230
+
231
+ // Controllers
232
+ this.controller(UserController);
233
+ this.controller(OrderController);
234
+
235
+ // Components
236
+ this.component(AuthenticateComponent);
237
+ this.component(SwaggerComponent);
238
+ }
239
+
240
+ // Called after all registrations complete
241
+ async postConfigure(): Promise<void> {
242
+ // Access registered services
243
+ const userRepo = this.get<UserRepository>({
244
+ key: BindingKeys.build({
245
+ namespace: BindingNamespaces.REPOSITORY,
246
+ key: UserRepository.name,
247
+ }),
248
+ });
249
+
250
+ // Seed initial data
251
+ const adminExists = await userRepo.findOne({
252
+ filter: { where: { role: 'admin' } },
253
+ });
254
+ if (!adminExists.data) {
255
+ await userRepo.create({ data: { name: 'Admin', role: 'admin' } });
256
+ }
257
+ }
258
+
259
+ // Configure static file serving
260
+ staticConfigure(): void {
261
+ this.static({ restPath: '/public/*', folderPath: './public' });
262
+ }
263
+ }
264
+ ```
265
+
266
+ > [!WARNING]
267
+ > Do not register new datasources, components, or controllers in `postConfigure()`. They will not be automatically initialized. Use `preConfigure()` for all registrations.
268
+
269
+ ## 6. Mixin Pattern
270
+
271
+ Mixins enable class composition without deep inheritance hierarchies. Ignis uses mixins to add capabilities to the `BaseApplication` class.
272
+
273
+ **How Mixins Work:**
274
+ ```typescript
275
+ // A mixin is a function that takes a class and returns an extended class
276
+ const ServiceMixin = <T extends TMixinTarget<AbstractApplication>>(baseClass: T) => {
277
+ return class extends baseClass {
278
+ service<Base extends IService>(ctor: TClass<Base>): Binding<Base> {
279
+ return this.bind<Base>({
280
+ key: BindingKeys.build({
281
+ namespace: BindingNamespaces.SERVICE,
282
+ key: ctor.name,
283
+ }),
284
+ }).toClass(ctor);
285
+ }
286
+ };
287
+ };
288
+ ```
289
+
290
+ **Available Mixins:**
291
+
292
+ | Mixin | Methods Added | Purpose |
293
+ |-------|---------------|---------|
294
+ | `ServiceMixin` | `service()` | Register service classes |
295
+ | `RepositoryMixin` | `repository()`, `dataSource()`, `registerDataSources()` | Register data layer |
296
+ | `ControllerMixin` | `controller()` | Register HTTP controllers |
297
+ | `ComponentMixin` | `component()` | Register modular components |
298
+
299
+ **Composing Mixins:**
300
+ ```typescript
301
+ // The framework composes mixins like this:
302
+ class AbstractApplication extends ComponentMixin(
303
+ ControllerMixin(
304
+ ServiceMixin(
305
+ RepositoryMixin(BaseClass)
306
+ )
307
+ )
308
+ ) {
309
+ // Now has: service(), repository(), dataSource(), controller(), component()
310
+ }
311
+ ```
312
+
313
+ **Why Mixins?**
314
+ - Avoid "diamond inheritance" problems
315
+ - Add capabilities selectively
316
+ - Keep base classes focused
317
+ - Enable code reuse across unrelated classes
318
+
319
+ ## 7. Controller Factory Pattern
320
+
321
+ `ControllerFactory.defineCrudController()` generates a complete CRUD controller from an entity definition. This reduces boilerplate while maintaining full customization.
322
+
323
+ **Basic Usage:**
324
+ ```typescript
325
+ const _Controller = ControllerFactory.defineCrudController({
326
+ entity: () => User,
327
+ repository: { name: UserRepository.name },
328
+ controller: {
329
+ name: 'UserController',
330
+ basePath: '/users',
331
+ isStrict: true, // Enable strict validation
332
+ defaultLimit: 50, // Default pagination limit
333
+ },
334
+ });
335
+
336
+ @controller({ path: '/users' })
337
+ export class UserController extends _Controller {
338
+ constructor(
339
+ @inject({ key: BindingKeys.build({ namespace: BindingNamespaces.REPOSITORY, key: UserRepository.name }) })
340
+ repository: UserRepository,
341
+ ) {
342
+ super(repository);
343
+ }
344
+ }
345
+ ```
346
+
347
+ **Per-Route Authentication:**
348
+ ```typescript
349
+ const _Controller = ControllerFactory.defineCrudController({
350
+ entity: () => User,
351
+ repository: { name: UserRepository.name },
352
+ controller: { name: 'UserController', basePath: '/users' },
353
+
354
+ // Apply JWT to all routes by default
355
+ authStrategies: [Authentication.STRATEGY_JWT],
356
+
357
+ // Override per-route
358
+ routes: {
359
+ // Public read endpoints
360
+ find: { skipAuth: true },
361
+ findById: { skipAuth: true },
362
+ count: { skipAuth: true },
363
+
364
+ // Protected write endpoints (use controller-level auth)
365
+ create: {},
366
+ updateById: {},
367
+ deleteById: {},
368
+ },
369
+ });
370
+ ```
371
+
372
+ **Custom Schemas Per Route:**
373
+ ```typescript
374
+ const _Controller = ControllerFactory.defineCrudController({
375
+ entity: () => User,
376
+ repository: { name: UserRepository.name },
377
+ controller: { name: 'UserController', basePath: '/users' },
378
+
379
+ routes: {
380
+ // Custom request body schema for create
381
+ create: {
382
+ authStrategies: [Authentication.STRATEGY_JWT],
383
+ requestBody: z.object({
384
+ email: z.string().email(),
385
+ name: z.string().min(2),
386
+ // Exclude sensitive fields from client input
387
+ }),
388
+ },
389
+
390
+ // Custom response schema
391
+ find: {
392
+ skipAuth: true,
393
+ schema: z.array(z.object({
394
+ id: z.string(),
395
+ name: z.string(),
396
+ // Exclude internal fields from response
397
+ })),
398
+ },
399
+ },
400
+ });
401
+ ```
402
+
403
+ **Generated Routes:**
404
+
405
+ | Route | Method | Path | Description |
406
+ |-------|--------|------|-------------|
407
+ | `count` | GET | `/count` | Count records matching filter |
408
+ | `find` | GET | `/` | List records with filter |
409
+ | `findById` | GET | `/:id` | Get single record |
410
+ | `findOne` | GET | `/find-one` | Get first matching record |
411
+ | `create` | POST | `/` | Create new record |
412
+ | `updateById` | PATCH | `/:id` | Update record by ID |
413
+ | `updateBy` | PATCH | `/` | Bulk update by filter |
414
+ | `deleteById` | DELETE | `/:id` | Delete by ID |
415
+ | `deleteBy` | DELETE | `/` | Bulk delete by filter |