exisjs 0.7.12 → 0.7.14

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 (132) hide show
  1. package/README.md +195 -39
  2. package/dist/cli/commands/run.d.ts.map +1 -1
  3. package/dist/cli/commands/run.js +3 -1
  4. package/dist/cli/commands/run.js.map +1 -1
  5. package/dist/config/types.d.ts +2 -2
  6. package/dist/config/types.d.ts.map +1 -1
  7. package/dist/decorators/params.d.ts +21 -0
  8. package/dist/decorators/params.d.ts.map +1 -1
  9. package/dist/decorators/params.js +21 -1
  10. package/dist/decorators/params.js.map +1 -1
  11. package/dist/di/container.d.ts +15 -6
  12. package/dist/di/container.d.ts.map +1 -1
  13. package/dist/di/container.js +26 -3
  14. package/dist/di/container.js.map +1 -1
  15. package/dist/di/index.d.ts +1 -1
  16. package/dist/di/index.d.ts.map +1 -1
  17. package/dist/di/index.js.map +1 -1
  18. package/dist/di/inject.d.ts +2 -1
  19. package/dist/di/inject.d.ts.map +1 -1
  20. package/dist/di/inject.js +2 -1
  21. package/dist/di/inject.js.map +1 -1
  22. package/dist/docs/ARCHITECTURE.md +130 -78
  23. package/dist/docs/BENCHMARKS.md +4 -4
  24. package/dist/docs/content/README.md +43 -44
  25. package/dist/docs/content/boundaries.mdx +138 -61
  26. package/dist/docs/content/cli/commands.mdx +151 -128
  27. package/dist/docs/content/cli/overview.mdx +61 -47
  28. package/dist/docs/content/cli/usage.mdx +107 -30
  29. package/dist/docs/content/config.mdx +145 -158
  30. package/dist/docs/content/controllers.mdx +193 -464
  31. package/dist/docs/content/cron.mdx +183 -69
  32. package/dist/docs/content/decorators.mdx +449 -154
  33. package/dist/docs/content/errors.mdx +202 -305
  34. package/dist/docs/content/exisjs-mcp.mdx +59 -49
  35. package/dist/docs/content/installation.mdx +243 -157
  36. package/dist/docs/content/introduction.mdx +220 -48
  37. package/dist/docs/content/middleware.mdx +171 -497
  38. package/dist/docs/content/modules.mdx +141 -83
  39. package/dist/docs/content/providers.mdx +216 -180
  40. package/dist/docs/content/requests.mdx +168 -488
  41. package/dist/docs/content/responses.mdx +200 -533
  42. package/dist/docs/content/routing.mdx +235 -598
  43. package/dist/docs/content/security.mdx +233 -57
  44. package/dist/docs/content/structure.mdx +151 -240
  45. package/dist/docs/content/swagger.mdx +192 -91
  46. package/dist/docs/content/testing.mdx +205 -74
  47. package/dist/docs/content/validation.mdx +479 -341
  48. package/dist/docs/reference/README.md +34 -2
  49. package/dist/docs/reference/config.mdx +277 -75
  50. package/dist/docs/reference/context.mdx +197 -106
  51. package/dist/docs/reference/cron.mdx +266 -152
  52. package/dist/docs/reference/database.mdx +135 -53
  53. package/dist/docs/reference/decorators.mdx +234 -116
  54. package/dist/docs/reference/di.mdx +146 -112
  55. package/dist/docs/reference/error.mdx +155 -178
  56. package/dist/docs/reference/exis.mdx +141 -70
  57. package/dist/docs/reference/logger.mdx +110 -126
  58. package/dist/docs/reference/middleware.mdx +235 -158
  59. package/dist/docs/reference/plugin.mdx +136 -64
  60. package/dist/docs/reference/router.mdx +275 -293
  61. package/dist/docs/reference/sanitize.mdx +91 -87
  62. package/dist/docs/reference/swagger.mdx +280 -100
  63. package/dist/docs/reference/testing.mdx +223 -89
  64. package/dist/docs/reference/validator.mdx +194 -206
  65. package/dist/lib/start-server.js +22 -8
  66. package/dist/lib/start-server.js.map +1 -1
  67. package/dist/module/module.d.ts +6 -3
  68. package/dist/module/module.d.ts.map +1 -1
  69. package/dist/module/module.js +17 -3
  70. package/dist/module/module.js.map +1 -1
  71. package/dist/router/controller-registrar.d.ts.map +1 -1
  72. package/dist/router/controller-registrar.js +26 -4
  73. package/dist/router/controller-registrar.js.map +1 -1
  74. package/dist/router/scanner/fs-scanner.d.ts.map +1 -1
  75. package/dist/router/scanner/fs-scanner.js +22 -0
  76. package/dist/router/scanner/fs-scanner.js.map +1 -1
  77. package/dist/router/types.d.ts +6 -4
  78. package/dist/router/types.d.ts.map +1 -1
  79. package/dist/server/app.d.ts +3 -1
  80. package/dist/server/app.d.ts.map +1 -1
  81. package/dist/server/app.js +24 -8
  82. package/dist/server/app.js.map +1 -1
  83. package/dist/server/bootstrapper.d.ts.map +1 -1
  84. package/dist/server/bootstrapper.js +19 -0
  85. package/dist/server/bootstrapper.js.map +1 -1
  86. package/dist/server/request.d.ts +2 -0
  87. package/dist/server/request.d.ts.map +1 -1
  88. package/dist/server/request.js +11 -0
  89. package/dist/server/request.js.map +1 -1
  90. package/dist/server/response.d.ts +10 -5
  91. package/dist/server/response.d.ts.map +1 -1
  92. package/dist/server/response.js +65 -18
  93. package/dist/server/response.js.map +1 -1
  94. package/dist/swagger/generator.d.ts.map +1 -1
  95. package/dist/swagger/generator.js +130 -10
  96. package/dist/swagger/generator.js.map +1 -1
  97. package/dist/telemetry/index.d.ts +12 -0
  98. package/dist/telemetry/index.d.ts.map +1 -0
  99. package/dist/telemetry/index.js +121 -0
  100. package/dist/telemetry/index.js.map +1 -0
  101. package/dist/testing/client.d.ts +1 -0
  102. package/dist/testing/client.d.ts.map +1 -1
  103. package/dist/testing/client.js +4 -1
  104. package/dist/testing/client.js.map +1 -1
  105. package/dist/testing/index.d.ts.map +1 -1
  106. package/dist/testing/index.js +11 -4
  107. package/dist/testing/index.js.map +1 -1
  108. package/dist/validator/builder.d.ts +26 -1
  109. package/dist/validator/builder.d.ts.map +1 -1
  110. package/dist/validator/builder.js +31 -0
  111. package/dist/validator/builder.js.map +1 -1
  112. package/dist/validator/engine.d.ts +23 -0
  113. package/dist/validator/engine.d.ts.map +1 -1
  114. package/dist/validator/engine.js +228 -31
  115. package/dist/validator/engine.js.map +1 -1
  116. package/dist/validator/index.d.ts +8 -4
  117. package/dist/validator/index.d.ts.map +1 -1
  118. package/dist/validator/index.js +4 -1
  119. package/dist/validator/index.js.map +1 -1
  120. package/dist/validator/tex-types.d.ts +19 -4
  121. package/dist/validator/tex-types.d.ts.map +1 -1
  122. package/dist/validator/tex-types.js +102 -0
  123. package/dist/validator/tex-types.js.map +1 -1
  124. package/dist/validator/tex.d.ts +1 -1
  125. package/dist/validator/tex.d.ts.map +1 -1
  126. package/dist/validator/tex.js +3 -1
  127. package/dist/validator/tex.js.map +1 -1
  128. package/dist/validator/types.d.ts +1 -0
  129. package/dist/validator/types.d.ts.map +1 -1
  130. package/package.json +46 -14
  131. package/dist/docs/content/dataloader.mdx +0 -170
  132. package/dist/docs/reference/dataloader.mdx +0 -91
@@ -1,113 +1,185 @@
1
1
  ---
2
- title: "Plugins"
3
- description: "API Reference for ExisJS Plugins (`exisjs/plugin`)."
2
+ title: "exisjs/plugin"
3
+ description: "API Reference for ExisJS plugin system: definePlugin, ExisPlugin interface, dependencies, encapsulation, and lifecycle hooks."
4
+ nextUrl: "/docs/reference/exis"
5
+ nextTitle: "App Reference"
4
6
  ---
5
7
 
6
- # Plugins (`exisjs/plugin`)
8
+ # `exisjs/plugin`
7
9
 
8
- ExisJS utilizes a highly optimized, encapsulated plugin architecture. Every major feature in ExisJS (Routing, WebSockets, Validation, Cron Jobs) is implemented as a Plugin under the hood.
10
+ The `exisjs/plugin` module provides tools and interfaces for authoring, typing, and distributing reusable ExisJS plugins, middleware packages, and third-party integrations.
9
11
 
10
- The `exisjs/plugin` module exposes everything you need to author, type, and distribute your own ExisJS plugins.
12
+ ---
13
+
14
+ ## Module Exports
15
+
16
+ ```typescript
17
+ import { definePlugin } from 'exisjs/plugin'
18
+ import type {
19
+ ExisPlugin,
20
+ ExisPluginInstance,
21
+ HookReady,
22
+ HookClose,
23
+ HookRequest,
24
+ HookResponse,
25
+ HookError,
26
+ HookRoute,
27
+ } from 'exisjs/plugin'
28
+ ```
29
+
30
+ ---
31
+
32
+ ## 1. `definePlugin(plugin)`
33
+
34
+ The `definePlugin` helper wraps a plugin definition object and returns a hybrid callable object. This allows developers to register the plugin directly without options (`app.register(myPlugin)`) or invoke it as a factory function to pass configuration parameters (`app.register(myPlugin({ apiKey: '...' }))`).
35
+
36
+ ```typescript
37
+ function definePlugin<TOptions = Record<string, unknown>>(
38
+ plugin: ExisPlugin<TOptions>
39
+ ): ExisPlugin<TOptions> & ((options?: TOptions) => ExisPluginInstance)
40
+ ```
41
+
42
+ ### Parameters
43
+
44
+ | Parameter | Type | Description |
45
+ | :--- | :--- | :--- |
46
+ | `plugin` | `ExisPlugin<TOptions>` | Object conforming to the `ExisPlugin` specification. |
11
47
 
12
48
  ---
13
49
 
14
- ## `definePlugin(plugin)`
50
+ ## 2. `ExisPlugin<TOptions>` Interface
15
51
 
16
- The `definePlugin` helper is the primary way to construct an ExisJS plugin.
52
+ The core specification contract for all plugins:
17
53
 
18
- It wraps your plugin object and returns a hybrid factory. This allows your users to either register the plugin directly (e.g., `app.register(myPlugin)`) or invoke it as a function to pass options (e.g., `app.register(myPlugin({ key: 'val' }))`).
54
+ | Property | Type | Default | Description |
55
+ | :--- | :--- | :--- | :--- |
56
+ | `name` | `string` | *(Required)* | Unique identifier for the plugin. Used to detect duplicate registrations. |
57
+ | `register` | `(app: App, options?: TOptions) => void \| Promise<void>` | *(Required)* | Lifecycle method executed during `app.register()`. |
58
+ | `version` | `string` | `undefined` | Semantic version string of the plugin package. |
59
+ | `dependencies` | `string[]` | `[]` | List of required plugin names that must be registered before this plugin boots. |
60
+ | `encapsulate` | `boolean` | `false` | When `true`, creates an isolated sub-router and dependency scope. |
19
61
 
20
- ### Basic Usage
62
+ ---
21
63
 
22
- ```typescript filename="src/plugins/logger.ts"
64
+ ## 3. Authoring Plugins
65
+
66
+ ### Basic Plugin
67
+
68
+ ```typescript filename="src/plugins/request-logger.plugin.ts"
23
69
  import { definePlugin } from 'exisjs/plugin'
24
70
 
25
- export const loggerPlugin = definePlugin({
26
- name: 'my-logger-plugin',
71
+ export const requestLoggerPlugin = definePlugin({
72
+ name: 'custom-request-logger',
27
73
  version: '1.0.0',
28
-
29
- // The register function is called when app.register() is executed
74
+
30
75
  async register(app) {
31
76
  app.use((req, res, next) => {
32
- console.log(`[${req.method}] ${req.path}`)
77
+ app.log.info({ method: req.method, url: req.url }, 'Incoming request')
33
78
  next()
34
79
  })
35
- }
80
+ },
36
81
  })
37
82
  ```
38
83
 
39
- ### With Options (Generics)
84
+ ---
40
85
 
41
- To make your plugin configurable, pass an interface to `definePlugin<TOptions>`. The options will automatically be injected as the second argument to your `register` function.
86
+ ### Configurable Generic Plugin with Lifecycle Teardown
42
87
 
43
- ```typescript filename="src/plugins/database.ts"
88
+ ```typescript filename="src/plugins/database.plugin.ts"
44
89
  import { definePlugin } from 'exisjs/plugin'
90
+ import { Pool } from 'pg'
45
91
 
46
- interface DatabaseOptions {
47
- url: string
48
- poolSize?: number
92
+ export interface DatabasePluginOptions {
93
+ connectionString: string
94
+ maxConnections?: number
49
95
  }
50
96
 
51
- export const databasePlugin = definePlugin<DatabaseOptions>({
52
- name: 'my-database-plugin',
53
-
97
+ export const databasePlugin = definePlugin<DatabasePluginOptions>({
98
+ name: 'postgres-database-plugin',
99
+ version: '1.2.0',
100
+
54
101
  async register(app, options) {
55
- if (!options?.url) throw new Error('Database URL is required')
56
-
57
- const db = new DatabaseConnection(options.url, options.poolSize)
58
- await db.connect()
102
+ if (!options?.connectionString) {
103
+ throw new Error('[databasePlugin] "connectionString" is required')
104
+ }
105
+
106
+ const pool = new Pool({
107
+ connectionString: options.connectionString,
108
+ max: options.maxConnections ?? 10,
109
+ })
59
110
 
60
- // Expose the database globally through the DI container
61
- app.provide('DB_CONNECTION', { useValue: db })
111
+ await pool.connect()
62
112
 
63
- // Clean up when the app closes
113
+ // Provide database pool to the DI container
114
+ app.provide('DB_POOL', { useValue: pool })
115
+
116
+ // Register graceful shutdown hook
64
117
  app.onClose(async () => {
65
- await db.disconnect()
118
+ await pool.end()
66
119
  })
67
- }
120
+ },
68
121
  })
69
122
  ```
70
123
 
71
- **Usage in Application:**
72
- ```typescript filename="src/server.ts"
73
- import { exis } from 'exisjs'
74
- import { databasePlugin } from './plugins/database'
124
+ ---
125
+
126
+ ### Plugin with Dependencies
127
+
128
+ ```typescript filename="src/plugins/auth.plugin.ts"
129
+ import { definePlugin } from 'exisjs/plugin'
75
130
 
76
- const app = exis()
131
+ export const authPlugin = definePlugin({
132
+ name: 'auth-plugin',
133
+ dependencies: ['postgres-database-plugin'], // Guarantees DB is registered first
77
134
 
78
- // The hybrid factory allows passing options directly!
79
- app.register(databasePlugin({
80
- url: 'postgres://localhost:5432/mydb',
81
- poolSize: 10
82
- }))
135
+ async register(app) {
136
+ const db = app.resolve('DB_POOL')
137
+ app.provide('AuthService', {
138
+ useFactory: () => new AuthService(db),
139
+ })
140
+ },
141
+ })
83
142
  ```
84
143
 
85
144
  ---
86
145
 
87
- ## `ExisPlugin<TOptions>` Interface
146
+ ## 4. Registering Plugins in Applications
88
147
 
89
- If you prefer building plugins using classes or pure objects without the `definePlugin` helper, you can directly implement the `ExisPlugin` TypeScript interface.
148
+ Plugins can be registered in `src/http/server.ts` using `app.register()` or statically declared in `exis.config.ts`:
90
149
 
91
- ### Properties
150
+ ### In `src/http/server.ts`
92
151
 
93
- - **`name`** *(string, required)*: The unique identifier for your plugin. ExisJS uses this to prevent duplicate registrations.
94
- - **`register`** *(function, required)*: The lifecycle method called during application boot. Receives the `App` instance and any options provided by the user. Can be `async`.
95
- - **`version`** *(string, optional)*: The version of your plugin.
96
- - **`dependencies`** *(string[], optional)*: An array of plugin names that *must* be registered before this plugin. If a dependency is missing, ExisJS will throw a fatal error during boot.
97
- - **`encapsulate`** *(boolean, optional)*: Determines if this plugin should create a scoped, isolated child container. (Useful for massive plugins that shouldn't leak routes or DI providers into the global scope).
98
-
99
- ### Example
152
+ ```typescript filename="src/http/server.ts"
153
+ import { exis } from 'exisjs'
154
+ import { databasePlugin } from '../plugins/database.plugin'
155
+ import { authPlugin } from '../plugins/auth.plugin'
156
+
157
+ export default exis({
158
+ async onStart(app) {
159
+ await app.register(
160
+ databasePlugin({
161
+ connectionString: process.env.DATABASE_URL!,
162
+ maxConnections: 20,
163
+ })
164
+ )
165
+ await app.register(authPlugin)
166
+ },
167
+ })
168
+ ```
100
169
 
101
- ```typescript filename="src/plugins/mailer.ts"
102
- import type { ExisPlugin } from 'exisjs/plugin'
103
- import type { App } from 'exisjs'
170
+ ### In `exis.config.ts`
104
171
 
105
- export class MailerPlugin implements ExisPlugin {
106
- name = 'exisjs-mailer'
107
- dependencies = ['my-database-plugin'] // Requires DB to load first
172
+ ```typescript filename="exis.config.ts"
173
+ import { defineConfig } from 'exisjs/config'
174
+ import { databasePlugin } from './src/plugins/database.plugin'
175
+ import { authPlugin } from './src/plugins/auth.plugin'
108
176
 
109
- async register(app: App) {
110
- app.provide('Mailer', { useClass: SmtpService })
111
- }
112
- }
177
+ export default defineConfig({
178
+ plugins: [
179
+ databasePlugin({
180
+ connectionString: process.env.DATABASE_URL!,
181
+ }),
182
+ authPlugin,
183
+ ],
184
+ })
113
185
  ```