@venizia/ignis-docs 0.0.6-3 → 0.0.7-1

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 (113) hide show
  1. package/README.md +125 -388
  2. package/dist/mcp-server/common/config.d.ts +0 -21
  3. package/dist/mcp-server/common/config.d.ts.map +1 -1
  4. package/dist/mcp-server/common/config.js +1 -36
  5. package/dist/mcp-server/common/config.js.map +1 -1
  6. package/dist/mcp-server/helpers/docs.helper.d.ts +0 -24
  7. package/dist/mcp-server/helpers/docs.helper.d.ts.map +1 -1
  8. package/dist/mcp-server/helpers/docs.helper.js +0 -25
  9. package/dist/mcp-server/helpers/docs.helper.js.map +1 -1
  10. package/dist/mcp-server/helpers/github.helper.d.ts +0 -13
  11. package/dist/mcp-server/helpers/github.helper.d.ts.map +1 -1
  12. package/dist/mcp-server/helpers/github.helper.js +3 -20
  13. package/dist/mcp-server/helpers/github.helper.js.map +1 -1
  14. package/dist/mcp-server/index.js +0 -20
  15. package/dist/mcp-server/index.js.map +1 -1
  16. package/dist/mcp-server/tools/base.tool.d.ts +2 -79
  17. package/dist/mcp-server/tools/base.tool.d.ts.map +1 -1
  18. package/dist/mcp-server/tools/base.tool.js +1 -38
  19. package/dist/mcp-server/tools/base.tool.js.map +1 -1
  20. package/dist/mcp-server/tools/docs/get-document-content.tool.d.ts.map +1 -1
  21. package/dist/mcp-server/tools/docs/get-document-content.tool.js +0 -9
  22. package/dist/mcp-server/tools/docs/get-document-content.tool.js.map +1 -1
  23. package/dist/mcp-server/tools/docs/get-document-metadata.tool.d.ts.map +1 -1
  24. package/dist/mcp-server/tools/docs/get-document-metadata.tool.js +0 -9
  25. package/dist/mcp-server/tools/docs/get-document-metadata.tool.js.map +1 -1
  26. package/dist/mcp-server/tools/docs/get-package-overview.tool.d.ts +0 -6
  27. package/dist/mcp-server/tools/docs/get-package-overview.tool.d.ts.map +1 -1
  28. package/dist/mcp-server/tools/docs/get-package-overview.tool.js +1 -24
  29. package/dist/mcp-server/tools/docs/get-package-overview.tool.js.map +1 -1
  30. package/dist/mcp-server/tools/docs/list-categories.tool.d.ts.map +1 -1
  31. package/dist/mcp-server/tools/docs/list-categories.tool.js +0 -9
  32. package/dist/mcp-server/tools/docs/list-categories.tool.js.map +1 -1
  33. package/dist/mcp-server/tools/docs/list-documents.tool.d.ts.map +1 -1
  34. package/dist/mcp-server/tools/docs/list-documents.tool.js +0 -9
  35. package/dist/mcp-server/tools/docs/list-documents.tool.js.map +1 -1
  36. package/dist/mcp-server/tools/docs/search-documents.tool.d.ts.map +1 -1
  37. package/dist/mcp-server/tools/docs/search-documents.tool.js +0 -9
  38. package/dist/mcp-server/tools/docs/search-documents.tool.js.map +1 -1
  39. package/dist/mcp-server/tools/github/list-project-files.tool.d.ts.map +1 -1
  40. package/dist/mcp-server/tools/github/list-project-files.tool.js +0 -9
  41. package/dist/mcp-server/tools/github/list-project-files.tool.js.map +1 -1
  42. package/dist/mcp-server/tools/github/search-code.tool.d.ts.map +1 -1
  43. package/dist/mcp-server/tools/github/search-code.tool.js +1 -13
  44. package/dist/mcp-server/tools/github/search-code.tool.js.map +1 -1
  45. package/dist/mcp-server/tools/github/verify-dependencies.tool.d.ts +0 -4
  46. package/dist/mcp-server/tools/github/verify-dependencies.tool.d.ts.map +1 -1
  47. package/dist/mcp-server/tools/github/verify-dependencies.tool.js +1 -18
  48. package/dist/mcp-server/tools/github/verify-dependencies.tool.js.map +1 -1
  49. package/dist/mcp-server/tools/github/view-source-file.tool.d.ts.map +1 -1
  50. package/dist/mcp-server/tools/github/view-source-file.tool.js +0 -9
  51. package/dist/mcp-server/tools/github/view-source-file.tool.js.map +1 -1
  52. package/dist/mcp-server/tools/index.d.ts.map +1 -1
  53. package/dist/mcp-server/tools/index.js +0 -2
  54. package/dist/mcp-server/tools/index.js.map +1 -1
  55. package/package.json +1 -1
  56. package/wiki/best-practices/api-usage-examples.md +7 -5
  57. package/wiki/best-practices/code-style-standards/advanced-patterns.md +1 -1
  58. package/wiki/best-practices/code-style-standards/constants-configuration.md +1 -1
  59. package/wiki/best-practices/code-style-standards/control-flow.md +1 -1
  60. package/wiki/best-practices/code-style-standards/function-patterns.md +1 -1
  61. package/wiki/best-practices/common-pitfalls.md +1 -1
  62. package/wiki/best-practices/data-modeling.md +33 -1
  63. package/wiki/best-practices/error-handling.md +7 -4
  64. package/wiki/best-practices/performance-optimization.md +1 -1
  65. package/wiki/best-practices/security-guidelines.md +5 -4
  66. package/wiki/guides/core-concepts/components-guide.md +1 -1
  67. package/wiki/guides/core-concepts/controllers.md +14 -8
  68. package/wiki/guides/core-concepts/persistent/models.md +32 -0
  69. package/wiki/guides/core-concepts/services.md +2 -1
  70. package/wiki/guides/get-started/5-minute-quickstart.md +1 -1
  71. package/wiki/guides/tutorials/building-a-crud-api.md +2 -1
  72. package/wiki/guides/tutorials/complete-installation.md +2 -2
  73. package/wiki/guides/tutorials/ecommerce-api.md +3 -3
  74. package/wiki/guides/tutorials/realtime-chat.md +7 -6
  75. package/wiki/index.md +2 -1
  76. package/wiki/references/base/application.md +28 -0
  77. package/wiki/references/base/components.md +2 -1
  78. package/wiki/references/base/controllers.md +31 -4
  79. package/wiki/references/base/datasources.md +6 -2
  80. package/wiki/references/base/dependency-injection.md +31 -0
  81. package/wiki/references/base/filter-system/fields-order-pagination.md +8 -1
  82. package/wiki/references/base/middlewares.md +2 -1
  83. package/wiki/references/base/models.md +144 -2
  84. package/wiki/references/base/repositories/advanced.md +2 -2
  85. package/wiki/references/base/repositories/index.md +24 -1
  86. package/wiki/references/base/repositories/soft-deletable.md +213 -0
  87. package/wiki/references/base/services.md +2 -1
  88. package/wiki/references/components/authentication/api.md +525 -205
  89. package/wiki/references/components/authentication/errors.md +502 -105
  90. package/wiki/references/components/authentication/index.md +388 -75
  91. package/wiki/references/components/authentication/usage.md +575 -247
  92. package/wiki/references/components/authorization/usage.md +62 -0
  93. package/wiki/references/components/health-check.md +2 -1
  94. package/wiki/references/components/socket-io/index.md +9 -4
  95. package/wiki/references/components/socket-io/usage.md +1 -1
  96. package/wiki/references/components/static-asset/index.md +3 -5
  97. package/wiki/references/components/swagger.md +2 -1
  98. package/wiki/references/configuration/environment-variables.md +2 -1
  99. package/wiki/references/configuration/index.md +40 -1
  100. package/wiki/references/helpers/error/index.md +1 -1
  101. package/wiki/references/helpers/inversion/index.md +1 -1
  102. package/wiki/references/helpers/redis/index.md +2 -9
  103. package/wiki/references/quick-reference.md +3 -5
  104. package/wiki/references/utilities/crypto.md +2 -2
  105. package/wiki/references/utilities/date.md +5 -5
  106. package/wiki/references/utilities/index.md +3 -11
  107. package/wiki/references/utilities/jsx.md +4 -2
  108. package/wiki/references/utilities/module.md +1 -1
  109. package/wiki/references/utilities/parse.md +24 -4
  110. package/wiki/references/utilities/performance.md +2 -2
  111. package/wiki/references/utilities/promise.md +4 -4
  112. package/wiki/references/utilities/request.md +2 -2
  113. package/wiki/references/utilities/schema.md +17 -8
@@ -689,6 +689,68 @@ const customRole = AuthorizationRole.build({ name: 'editor', priority: 100, deli
689
689
  customRole.identifier; // '100-editor'
690
690
  ```
691
691
 
692
+ ## Model-Based Resource References
693
+
694
+ Instead of hardcoding resource strings, use `AUTHORIZATION_SUBJECT` from your model classes. When a model declares `authorize.principal` in `@model` settings, the decorator auto-populates `AUTHORIZATION_SUBJECT`:
695
+
696
+ ```typescript
697
+ import { BaseEntity, model, generateIdColumnDefs } from '@venizia/ignis';
698
+ import { pgTable, text } from 'drizzle-orm/pg-core';
699
+
700
+ @model({
701
+ type: 'entity',
702
+ settings: {
703
+ authorize: { principal: 'article' },
704
+ },
705
+ })
706
+ export class Article extends BaseEntity<typeof Article.schema> {
707
+ static override schema = pgTable('Article', {
708
+ ...generateIdColumnDefs({ id: { dataType: 'string' } }),
709
+ title: text('title').notNull(),
710
+ });
711
+ }
712
+
713
+ // Article.AUTHORIZATION_SUBJECT === 'article'
714
+ ```
715
+
716
+ Use it in route configs for type-safe, refactor-friendly resource references:
717
+
718
+ ```typescript
719
+ import { AuthorizationActions } from '@venizia/ignis';
720
+ import { Article } from '../models/entities/article.model';
721
+
722
+ // Instead of: resource: 'article'
723
+ authorize: {
724
+ action: AuthorizationActions.READ,
725
+ resource: Article.AUTHORIZATION_SUBJECT,
726
+ }
727
+ ```
728
+
729
+ ### Querying All Principals
730
+
731
+ Use `MetadataRegistry` to retrieve all registered authorization principals at runtime:
732
+
733
+ ```typescript
734
+ import { MetadataRegistry } from '@venizia/ignis';
735
+
736
+ const registry = MetadataRegistry.getInstance();
737
+
738
+ // Flat array of principal names — ideal for Casbin policy setup
739
+ const principals = registry.getAuthorizeModelPrincipals({ format: 'array' });
740
+ // ['article', 'user', 'configuration']
741
+
742
+ // Record of model name → principal
743
+ const principalMap = registry.getAuthorizeModelPrincipals({ format: 'record' });
744
+ // { Article: 'article', User: 'user', Configuration: 'configuration' }
745
+
746
+ // Full settings with model registry entries (framework-level)
747
+ const settings = registry.getAuthorizeModelSettings({ format: 'array' });
748
+ // [{ name: 'Article', authorize: { principal: 'article' }, entry: IModelRegistryEntry }]
749
+ ```
750
+
751
+ > [!TIP]
752
+ > Defining `authorize.principal` on the model makes the model the single source of truth for its authorization subject. This eliminates string duplication across route configs and policy setup.
753
+
692
754
  ## See Also
693
755
 
694
756
  - [Setup & Configuration](./) -- Binding keys, options interfaces, and initial setup
@@ -214,8 +214,9 @@ The controller uses `this.definitions = RouteConfigs` to store route configurati
214
214
  ```typescript
215
215
  import {
216
216
  BaseController, IControllerOptions, TRouteContext,
217
- api, jsonContent, jsonResponse, HTTP, z,
217
+ api, jsonContent, jsonResponse, z,
218
218
  } from '@venizia/ignis';
219
+ import { HTTP } from '@venizia/ignis-helpers';
219
220
 
220
221
  const RouteConfigs = {
221
222
  ROOT: {
@@ -18,9 +18,12 @@
18
18
  import {
19
19
  SocketIOComponent,
20
20
  SocketIOBindingKeys,
21
+ } from '@venizia/ignis';
22
+
23
+ import {
21
24
  SocketIOServerHelper,
22
25
  RedisHelper,
23
- } from '@venizia/ignis';
26
+ } from '@venizia/ignis-helpers';
24
27
 
25
28
  import {
26
29
  SocketIOClientHelper,
@@ -70,11 +73,13 @@ import {
70
73
  BaseApplication,
71
74
  SocketIOComponent,
72
75
  SocketIOBindingKeys,
73
- RedisHelper,
76
+ ValueOrPromise,
77
+ } from '@venizia/ignis';
78
+ import { RedisHelper } from '@venizia/ignis-helpers';
79
+ import type {
74
80
  TSocketIOAuthenticateFn,
75
81
  TSocketIOValidateRoomFn,
76
82
  TSocketIOClientConnectedFn,
77
- ValueOrPromise,
78
83
  } from '@venizia/ignis';
79
84
 
80
85
  export class Application extends BaseApplication {
@@ -146,7 +151,7 @@ The `RedisHelper` is created with `autoConnect: false` because the server helper
146
151
  You can use either `RedisHelper` (single Redis instance) or `RedisClusterHelper` (Redis Cluster mode). Both extend `DefaultRedisHelper`, which is the type the component validates against:
147
152
 
148
153
  ```typescript
149
- import { RedisClusterHelper } from '@venizia/ignis';
154
+ import { RedisClusterHelper } from '@venizia/ignis-helpers';
150
155
 
151
156
  // For Redis Cluster deployments
152
157
  const redisHelper = new RedisClusterHelper({
@@ -13,10 +13,10 @@ import {
13
13
  BaseService,
14
14
  inject,
15
15
  SocketIOBindingKeys,
16
- SocketIOServerHelper,
17
16
  CoreBindings,
18
17
  BaseApplication,
19
18
  } from '@venizia/ignis';
19
+ import { SocketIOServerHelper } from '@venizia/ignis-helpers';
20
20
 
21
21
  export class NotificationService extends BaseService {
22
22
  // Lazy getter pattern -- helper is bound AFTER server starts
@@ -17,9 +17,8 @@ import {
17
17
  StaticAssetComponent,
18
18
  StaticAssetComponentBindingKeys,
19
19
  StaticAssetStorageTypes,
20
- DiskHelper,
21
- MinioHelper,
22
20
  } from '@venizia/ignis';
21
+ import { DiskHelper, MinioHelper } from '@venizia/ignis-helpers';
23
22
  import type {
24
23
  TStaticAssetsComponentOptions,
25
24
  TMetaLinkConfig,
@@ -46,12 +45,11 @@ import type {
46
45
  ```typescript
47
46
  import {
48
47
  BaseApplication,
49
- DiskHelper,
50
- MinioHelper,
51
48
  StaticAssetComponentBindingKeys,
52
49
  StaticAssetStorageTypes,
53
- TStaticAssetsComponentOptions,
54
50
  } from '@venizia/ignis';
51
+ import { DiskHelper, MinioHelper } from '@venizia/ignis-helpers';
52
+ import type { TStaticAssetsComponentOptions } from '@venizia/ignis';
55
53
 
56
54
  export class Application extends BaseApplication {
57
55
  preConfigure() {
@@ -67,7 +67,8 @@ To get the most out of the documentation, define your routes with `zod` schemas:
67
67
  ```typescript
68
68
  // src/controllers/hello.controller.ts
69
69
  import { z } from '@hono/zod-openapi';
70
- import { BaseController, controller, HTTP, jsonContent, ValueOrPromise } from '@venizia/ignis';
70
+ import { BaseController, controller, jsonContent, ValueOrPromise } from '@venizia/ignis';
71
+ import { HTTP } from '@venizia/ignis-helpers';
71
72
 
72
73
  @controller({ path: '/hello' })
73
74
  export class HelloController extends BaseController {
@@ -22,7 +22,8 @@ POSTGRES_HOST=localhost
22
22
  const host = process.env.APP_ENV_POSTGRES_HOST;
23
23
 
24
24
  // Using applicationEnvironment helper (recommended)
25
- import { applicationEnvironment, EnvironmentKeys } from '@venizia/ignis';
25
+ import { applicationEnvironment } from '@venizia/ignis-helpers';
26
+ import { EnvironmentKeys } from '@venizia/ignis';
26
27
  const host = applicationEnvironment.get<string>(EnvironmentKeys.APP_ENV_POSTGRES_HOST);
27
28
  ```
28
29
 
@@ -52,7 +52,8 @@ APP_ENV_POSTGRES_DATABASE=my_database
52
52
  const host = process.env.APP_ENV_POSTGRES_HOST;
53
53
 
54
54
  // 2. Using helper (recommended)
55
- import { applicationEnvironment, EnvironmentKeys } from '@venizia/ignis';
55
+ import { applicationEnvironment } from '@venizia/ignis-helpers';
56
+ import { EnvironmentKeys } from '@venizia/ignis';
56
57
  const host = applicationEnvironment.get<string>(EnvironmentKeys.APP_ENV_POSTGRES_HOST);
57
58
  ```
58
59
 
@@ -71,3 +72,41 @@ project/
71
72
  Ignis validates required variables on startup. Missing values cause clear error messages.
72
73
 
73
74
  > **Related:** [Environment Variables Reference](./environment-variables.md) | [DataSources Guide](../../guides/core-concepts/persistent/datasources)
75
+
76
+ ## EnvironmentKeys Class
77
+
78
+ ```typescript
79
+ import { EnvironmentKeys } from '@venizia/ignis';
80
+ ```
81
+
82
+ | Constant | Description |
83
+ |----------|-------------|
84
+ | `APP_ENV_APPLICATION_NAME` | Application display name |
85
+ | `APP_ENV_APPLICATION_TIMEZONE` | Application timezone (e.g., 'Asia/Ho_Chi_Minh') |
86
+ | `APP_ENV_APPLICATION_SECRET` | Application-wide secret key |
87
+ | `APP_ENV_JWT_SECRET` | JWT signing secret |
88
+ | `APP_ENV_JWT_EXPIRES_IN` | JWT token expiration |
89
+ | `APP_ENV_LOGGER_FOLDER_PATH` | Log file output directory |
90
+ | `APP_ENV_APPLICATION_ROLES` | Application role definitions |
91
+ | `APP_ENV_APPLICATION_DS_MIGRATION` | DataSource name for migrations |
92
+ | `APP_ENV_APPLICATION_DS_AUTHORIZE` | DataSource name for authorization |
93
+ | `APP_ENV_APPLICATION_DS_OAUTH2` | DataSource name for OAuth2 |
94
+ | `APP_ENV_OAUTH2_VIEW_FOLDER` | OAuth2 view templates folder |
95
+ | `APP_ENV_SERVER_HOST` | HTTP server host (e.g., '0.0.0.0') |
96
+ | `APP_ENV_SERVER_PORT` | HTTP server port (e.g., 3000) |
97
+ | `APP_ENV_SERVER_BASE_PATH` | Base URL path prefix |
98
+ | `APP_ENV_DATASOURCE_NAME` | Default datasource name |
99
+ | `APP_ENV_POSTGRES_HOST` | PostgreSQL host |
100
+ | `APP_ENV_POSTGRES_PORT` | PostgreSQL port |
101
+ | `APP_ENV_POSTGRES_USERNAME` | PostgreSQL username |
102
+ | `APP_ENV_POSTGRES_PASSWORD` | PostgreSQL password |
103
+ | `APP_ENV_POSTGRES_DATABASE` | PostgreSQL database name |
104
+
105
+ Usage:
106
+
107
+ ```typescript
108
+ import { applicationEnvironment } from '@venizia/ignis-helpers';
109
+ import { EnvironmentKeys } from '@venizia/ignis';
110
+
111
+ const dbHost = applicationEnvironment.get<string>(EnvironmentKeys.APP_ENV_POSTGRES_HOST);
112
+ ```
@@ -20,7 +20,7 @@ import type { TError } from '@venizia/ignis-helpers';
20
20
  ```
21
21
 
22
22
  > [!NOTE]
23
- > `ApplicationError`, `getError`, `ErrorSchema`, and `TError` are also available from `@venizia/ignis-inversion` and re-exported through `@venizia/ignis`.
23
+ > `ApplicationError`, `getError`, `ErrorSchema`, and `TError` are also available from `@venizia/ignis-inversion`. Their types are re-exported through `@venizia/ignis` (via `export type *`), but for runtime usage, import directly from `@venizia/ignis-helpers` or `@venizia/ignis-inversion`.
24
24
 
25
25
  ## Creating an Instance
26
26
 
@@ -50,7 +50,7 @@ import type {
50
50
  ```
51
51
 
52
52
  > [!NOTE]
53
- > The framework package `@venizia/ignis` re-exports everything from `@venizia/ignis-inversion` and adds higher-level helpers (`app.controller()`, `app.service()`, etc.).
53
+ > The framework package `@venizia/ignis` re-exports DI-specific symbols (`Binding`, `BindingKeys`, `BindingScopes`, `BindingValueTypes`, `IProvider`, `isClass`, `isClassProvider`, `isClassConstructor`, `TBindingScope`, `TBindingValueType`, `IBindingTag`) from `@venizia/ignis-inversion` and adds higher-level helpers (`app.controller()`, `app.service()`, etc.). All types from inversion are also available via type-only re-exports.
54
54
 
55
55
  ## Creating an Instance
56
56
 
@@ -20,21 +20,14 @@ import {
20
20
  RedisClusterHelper,
21
21
  } from '@venizia/ignis-helpers';
22
22
 
23
- // Or from the core package (re-exports everything)
24
- import {
25
- DefaultRedisHelper,
26
- RedisHelper,
27
- RedisClusterHelper,
28
- } from '@venizia/ignis';
29
-
30
- // Types
23
+ // Types are also available from the core package (via type-only re-export)
31
24
  import type {
32
25
  IRedisHelperOptions,
33
26
  IRedisClusterHelperOptions,
34
27
  IRedisHelperCallbacks,
35
28
  IRedisHelperProps,
36
29
  IRedisClusterHelperProps,
37
- } from '@venizia/ignis-helpers';
30
+ } from '@venizia/ignis-helpers'; // or from '@venizia/ignis'
38
31
  ```
39
32
 
40
33
  ## Creating an Instance
@@ -118,6 +118,7 @@ class User extends BaseEntity {
118
118
  **Key Properties:**
119
119
  - `static tableName` - Database table name
120
120
  - `static schema` - Drizzle schema definition
121
+ - `static AUTHORIZATION_SUBJECT` - Authorization principal (auto-set from `@model` settings `authorize.principal`)
121
122
 
122
123
 
123
124
  ## Route Decorators
@@ -396,11 +397,8 @@ import { MinIOHelper } from '@venizia/ignis-helpers/minio';
396
397
  ### Dependency Injection
397
398
 
398
399
  ```typescript
399
- import {
400
- Container,
401
- BindingKeys,
402
- BindingNamespaces,
403
- } from '@venizia/ignis-inversion';
400
+ import { Container, BindingKeys } from '@venizia/ignis-inversion';
401
+ import { BindingNamespaces } from '@venizia/ignis';
404
402
  ```
405
403
 
406
404
 
@@ -19,7 +19,7 @@ The `hash` function allows you to create a hash of a string using either `SHA256
19
19
  **MD5 Hash**
20
20
 
21
21
  ```typescript
22
- import { hash } from '@venizia/ignis';
22
+ import { hash } from '@venizia/ignis-helpers';
23
23
 
24
24
  const md5Hash = hash('some text', { algorithm: 'MD5', outputType: 'hex' });
25
25
  // => '552e21cd4cd99186789c2370c7482837'
@@ -28,7 +28,7 @@ const md5Hash = hash('some text', { algorithm: 'MD5', outputType: 'hex' });
28
28
  **SHA256 HMAC**
29
29
 
30
30
  ```typescript
31
- import { hash } from '@venizia/ignis';
31
+ import { hash } from '@venizia/ignis-helpers';
32
32
 
33
33
  const sha256Hash = hash('some text', {
34
34
  algorithm: 'SHA256',
@@ -7,7 +7,7 @@ The Date utility provides a set of functions for date and time manipulation, bui
7
7
  The `dayjs` object is re-exported, so you can use it directly for any date and time operations. It is pre-configured with the following plugins: `CustomParseFormat`, `UTC`, `Timezone`, `Weekday`, and `IsoWeek`.
8
8
 
9
9
  ```typescript
10
- import { dayjs } from '@venizia/ignis';
10
+ import { dayjs } from '@venizia/ignis-helpers';
11
11
 
12
12
  // Get the current date and time
13
13
  const now = dayjs();
@@ -21,7 +21,7 @@ const formatted = now.format('YYYY-MM-DD HH:mm:ss');
21
21
  The `sleep` function pauses execution for a specified number of milliseconds.
22
22
 
23
23
  ```typescript
24
- import { sleep } from '@venizia/ignis';
24
+ import { sleep } from '@venizia/ignis-helpers';
25
25
 
26
26
  async function myAsyncFunction() {
27
27
  console.log('Start');
@@ -37,7 +37,7 @@ async function myAsyncFunction() {
37
37
  - **`getNextWeekday(opts)`**: Returns the next weekday from a given date.
38
38
 
39
39
  ```typescript
40
- import { isWeekday, getPreviousWeekday } from '@venizia/ignis';
40
+ import { isWeekday, getPreviousWeekday } from '@venizia/ignis-helpers';
41
41
 
42
42
  const isTodayWeekday = isWeekday(new Date());
43
43
 
@@ -49,7 +49,7 @@ const lastBusinessDay = getPreviousWeekday();
49
49
  The `getDateTz` function allows you to get a `dayjs` object in a specific timezone, with an optional offset.
50
50
 
51
51
  ```typescript
52
- import { getDateTz } from '@venizia/ignis';
52
+ import { getDateTz } from '@venizia/ignis-helpers';
53
53
 
54
54
  const tokyoTime = getDateTz({
55
55
  date: '2023-10-27T10:00:00Z',
@@ -62,7 +62,7 @@ const tokyoTime = getDateTz({
62
62
  The `hrTime` function returns a high-resolution time measurement in seconds, useful for performance benchmarking.
63
63
 
64
64
  ```typescript
65
- import { hrTime } from '@venizia/ignis';
65
+ import { hrTime } from '@venizia/ignis-helpers';
66
66
 
67
67
  const start = hrTime();
68
68
  // ... some long-running operation
@@ -43,19 +43,11 @@ Pure, standalone functions providing common, reusable logic for the Ignis framew
43
43
 
44
44
  ## Usage Pattern
45
45
 
46
- All utilities are imported from `@venizia/ignis`:
46
+ Utilities are imported from `@venizia/ignis` (schema, JSX, and status helpers) or `@venizia/ignis-helpers` (runtime utilities):
47
47
 
48
48
  ```typescript
49
- import {
50
- hash,
51
- compare,
52
- formatDate,
53
- toBoolean,
54
- jsonContent,
55
- jsonResponse,
56
- htmlResponse,
57
- Statuses,
58
- } from '@venizia/ignis';
49
+ import { jsonContent, jsonResponse, htmlResponse, Statuses } from '@venizia/ignis';
50
+ import { hash, compare, formatDate, toBoolean } from '@venizia/ignis-helpers';
59
51
 
60
52
  // Crypto
61
53
  const hashed = await hash({ value: 'password123' });
@@ -184,7 +184,8 @@ export class PageController extends BaseController {
184
184
  ### HTML Email Preview
185
185
 
186
186
  ```typescript
187
- import { BaseController, get, htmlResponse, TRouteContext, HTTP, z } from '@venizia/ignis';
187
+ import { BaseController, get, htmlResponse, TRouteContext, z } from '@venizia/ignis';
188
+ import { HTTP } from '@venizia/ignis-helpers';
188
189
 
189
190
  const EmailRoutes = {
190
191
  PREVIEW: {
@@ -222,7 +223,8 @@ export class EmailController extends BaseController {
222
223
  ### Documentation Page
223
224
 
224
225
  ```typescript
225
- import { BaseController, get, htmlResponse, TRouteContext, HTTP, z } from '@venizia/ignis';
226
+ import { BaseController, get, htmlResponse, TRouteContext, z } from '@venizia/ignis';
227
+ import { HTTP } from '@venizia/ignis-helpers';
226
228
 
227
229
  const DocsRoutes = {
228
230
  GET_SECTION: {
@@ -17,7 +17,7 @@ The `validateModule` function checks if a list of modules can be resolved. If a
17
17
  The `SwaggerComponent` uses `validateModule` to ensure that `@hono/swagger-ui` is installed before attempting to use it.
18
18
 
19
19
  ```typescript
20
- import { validateModule } from '@venizia/ignis';
20
+ import { validateModule } from '@venizia/ignis-helpers';
21
21
 
22
22
  export class SwaggerComponent extends BaseComponent {
23
23
  // ...
@@ -15,7 +15,7 @@ The Parse utility provides a collection of functions for data type checking, con
15
15
  - **`toStringDecimal(input, digit = 2)`**: Formats a number to a string with a specified number of decimal places, using locale-specific formatting.
16
16
 
17
17
  ```typescript
18
- import { int, float, toBoolean } from '@venizia/ignis';
18
+ import { int, float, toBoolean } from '@venizia/ignis-helpers';
19
19
 
20
20
  const myInt = int('1,000'); // => 1000
21
21
  const myFloat = float('1,234.567', 2); // => 1234.57
@@ -28,7 +28,7 @@ const myBool = toBoolean('true'); // => true
28
28
  - **`keysToCamel(object)`**: Recursively converts all keys in an object (and nested objects) to camelCase.
29
29
 
30
30
  ```typescript
31
- import { toCamel, keysToCamel } from '@venizia/ignis';
31
+ import { toCamel, keysToCamel } from '@venizia/ignis-helpers';
32
32
 
33
33
  const camelString = toCamel('my-snake_case-string');
34
34
  // => 'mySnakeCaseString'
@@ -37,13 +37,33 @@ const camelObject = keysToCamel({ 'first-name': 'John', 'last_name': 'Doe' });
37
37
  // => { firstName: 'John', lastName: 'Doe' }
38
38
  ```
39
39
 
40
+ ## Number Parsing
41
+
42
+ - **`getNumberValue(input, opts?)`**: Parses a string to a number with locale support (US or EU format).
43
+
44
+ ```typescript
45
+ import { getNumberValue } from '@venizia/ignis-helpers';
46
+
47
+ // US format (default) — comma is thousands separator
48
+ getNumberValue('1,234.56', { method: 'float' }); // => 1234.56
49
+ getNumberValue('1,234', { method: 'int' }); // => 1234
50
+
51
+ // EU format — dot is thousands separator, comma is decimal
52
+ getNumberValue('1.234,56', { method: 'float', locale: 'eu' }); // => 1234.56
53
+ ```
54
+
55
+ | Option | Type | Default | Description |
56
+ |--------|------|---------|-------------|
57
+ | `method` | `'int' \| 'float'` | `'int'` | Parse as integer or float |
58
+ | `locale` | `'us' \| 'eu'` | `'us'` | Number format locale |
59
+
40
60
  ## Array Transformation
41
61
 
42
62
  - **`parseArrayToRecordWithKey(opts)`**: Transforms an array of objects into a record (plain object), using a specified property of the objects as keys.
43
63
  - **`parseArrayToMapWithKey(arr, keyMap)`**: Transforms an array of objects into a `Map`, using a specified property of the objects as keys. This is useful for efficient lookups.
44
64
 
45
65
  ```typescript
46
- import { parseArrayToMapWithKey } from '@venizia/ignis';
66
+ import { parseArrayToMapWithKey } from '@venizia/ignis-helpers';
47
67
 
48
68
  const users = [
49
69
  { id: 1, name: 'Alice' },
@@ -62,7 +82,7 @@ const user = usersMap.get(1);
62
82
  - **`getUID()`**: Generates a simple, short unique ID string.
63
83
 
64
84
  ```typescript
65
- import { getUID } from '@venizia/ignis';
85
+ import { getUID } from '@venizia/ignis-helpers';
66
86
 
67
87
  const uniqueId = getUID(); // => e.g., 'A1B2C3D4'
68
88
  ```
@@ -20,7 +20,7 @@ The `BaseApplication` uses this utility to measure the time taken to register co
20
20
 
21
21
  ```typescript
22
22
  // Inside BaseApplication class
23
- import { executeWithPerformanceMeasure } from '@venizia/ignis';
23
+ import { executeWithPerformanceMeasure } from '@venizia/ignis-helpers';
24
24
 
25
25
  // ...
26
26
 
@@ -53,7 +53,7 @@ For more granular measurements, you can use the lower-level functions:
53
53
  ### Example
54
54
 
55
55
  ```typescript
56
- import { getPerformanceCheckpoint, getExecutedPerformance } from '@venizia/ignis';
56
+ import { getPerformanceCheckpoint, getExecutedPerformance } from '@venizia/ignis-helpers';
57
57
 
58
58
  const start = getPerformanceCheckpoint();
59
59
 
@@ -16,7 +16,7 @@ This function executes an array of asynchronous tasks concurrently, but with a s
16
16
  ### Example
17
17
 
18
18
  ```typescript
19
- import { executePromiseWithLimit, sleep } from '@venizia/ignis';
19
+ import { executePromiseWithLimit, sleep } from '@venizia/ignis-helpers';
20
20
 
21
21
  const tasks = [
22
22
  () => sleep(1000).then(() => 'Task 1 done'),
@@ -43,7 +43,7 @@ console.log('All tasks finished:', results);
43
43
  A type guard function to check if a given value is a Promise-like object (i.e., it has a `then` method).
44
44
 
45
45
  ```typescript
46
- import { isPromiseLike } from '@venizia/ignis';
46
+ import { isPromiseLike } from '@venizia/ignis-helpers';
47
47
 
48
48
  const a = Promise.resolve(1);
49
49
  const b = 2;
@@ -62,7 +62,7 @@ if (isPromiseLike(b)) {
62
62
  This function applies a transformation function to a value that might be a direct value or a Promise.
63
63
 
64
64
  ```typescript
65
- import { transformValueOrPromise, isPromiseLike } from '@venizia/ignis';
65
+ import { transformValueOrPromise, isPromiseLike } from '@venizia/ignis-helpers';
66
66
 
67
67
  const double = (n: number) => n * 2;
68
68
 
@@ -75,7 +75,7 @@ const result2 = await transformValueOrPromise(Promise.resolve(5), double); // =>
75
75
  Safely retrieves a deeply nested property from an object using a dot-separated path string. It throws an error if any part of the path is null or undefined.
76
76
 
77
77
  ```typescript
78
- import { getDeepProperty } from '@venizia/ignis';
78
+ import { getDeepProperty } from '@venizia/ignis-helpers';
79
79
 
80
80
  const obj = { a: { b: { c: 'hello' } } };
81
81
 
@@ -31,8 +31,8 @@ The function returns a `Promise` that resolves to an array of `IParsedFile` obje
31
31
  Here is an example of how to use `parseMultipartBody` in a controller to handle a file upload.
32
32
 
33
33
  ```typescript
34
- import { BaseController, controller, HTTP } from '@venizia/ignis';
35
- import { parseMultipartBody } from '@venizia/ignis';
34
+ import { BaseController, controller } from '@venizia/ignis';
35
+ import { parseMultipartBody, HTTP } from '@venizia/ignis-helpers';
36
36
 
37
37
  @controller({ path: '/files' })
38
38
  export class FileController extends BaseController {
@@ -60,28 +60,37 @@ const schema = z.object({
60
60
 
61
61
  ## Predefined Schemas
62
62
 
63
- The utility also provides several predefined schemas for common use cases.
64
-
65
63
  - **`AnyObjectSchema`**: A flexible schema for any object (`z.object().catchall(z.any())`).
66
- - **`IdParamsSchema`**: A schema for a numeric path parameter named `id`.
67
- - **`UUIDParamsSchema`**: A schema for a UUID path parameter named `id`.
68
64
 
69
- ### Example
65
+ ### Type Utilities
66
+
67
+ ```typescript
68
+ import { TAnyObjectSchema, TInferSchema } from '@venizia/ignis';
69
+
70
+ // TAnyObjectSchema = z.ZodObject<z.ZodRawShape>
71
+ // TInferSchema<T> = z.infer<T> — infer TypeScript type from a Zod schema
72
+
73
+ type UserType = TInferSchema<typeof UserSchema>;
74
+ ```
75
+
76
+ ### Custom ID Params
77
+
78
+ Use the `idParamsSchema()` helper (from controller utilities) to generate path parameter schemas:
70
79
 
71
80
  ```typescript
72
- import { IdParamsSchema } from '@venizia/ignis';
81
+ import { idParamsSchema } from '@venizia/ignis';
73
82
 
74
83
  this.defineRoute({
75
84
  configs: {
76
85
  path: '/{id}',
77
86
  method: 'get',
78
87
  request: {
79
- params: IdParamsSchema,
88
+ params: idParamsSchema({ idType: 'number' }),
80
89
  },
81
90
  // ...
82
91
  },
83
92
  handler: (c) => {
84
- const { id } = c.req.valid('param'); // id is a number
93
+ const { id } = c.req.valid('param');
85
94
  // ...
86
95
  },
87
96
  });