@c9up/ream 0.1.34 → 0.2.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 (210) hide show
  1. package/dist/Application.d.ts +68 -0
  2. package/dist/Application.d.ts.map +1 -1
  3. package/dist/Application.js +142 -6
  4. package/dist/Application.js.map +1 -1
  5. package/dist/HealthCheck.d.ts +14 -7
  6. package/dist/HealthCheck.d.ts.map +1 -1
  7. package/dist/HealthCheck.js +21 -12
  8. package/dist/HealthCheck.js.map +1 -1
  9. package/dist/HttpKernel.d.ts +12 -0
  10. package/dist/HttpKernel.d.ts.map +1 -1
  11. package/dist/HttpKernel.js +15 -4
  12. package/dist/HttpKernel.js.map +1 -1
  13. package/dist/Ignitor.d.ts +8 -8
  14. package/dist/Ignitor.d.ts.map +1 -1
  15. package/dist/Ignitor.js +11 -0
  16. package/dist/Ignitor.js.map +1 -1
  17. package/dist/bodyparser/BodyParserMiddleware.d.ts +13 -2
  18. package/dist/bodyparser/BodyParserMiddleware.d.ts.map +1 -1
  19. package/dist/bodyparser/BodyParserMiddleware.js +50 -30
  20. package/dist/bodyparser/BodyParserMiddleware.js.map +1 -1
  21. package/dist/bodyparser/MultipartFile.d.ts +75 -6
  22. package/dist/bodyparser/MultipartFile.d.ts.map +1 -1
  23. package/dist/bodyparser/MultipartFile.js +128 -8
  24. package/dist/bodyparser/MultipartFile.js.map +1 -1
  25. package/dist/console/BaseCommand.d.ts +8 -1
  26. package/dist/console/BaseCommand.d.ts.map +1 -1
  27. package/dist/console/BaseCommand.js +1 -1
  28. package/dist/console/BaseCommand.js.map +1 -1
  29. package/dist/console/Kernel.d.ts +15 -0
  30. package/dist/console/Kernel.d.ts.map +1 -1
  31. package/dist/console/Kernel.js +17 -0
  32. package/dist/console/Kernel.js.map +1 -1
  33. package/dist/directories.d.ts +52 -0
  34. package/dist/directories.d.ts.map +1 -0
  35. package/dist/directories.js +38 -0
  36. package/dist/directories.js.map +1 -0
  37. package/dist/events/Emitter.d.ts +49 -6
  38. package/dist/events/Emitter.d.ts.map +1 -1
  39. package/dist/events/Emitter.js +117 -7
  40. package/dist/events/Emitter.js.map +1 -1
  41. package/dist/events/EventsBuffer.d.ts +47 -0
  42. package/dist/events/EventsBuffer.d.ts.map +1 -0
  43. package/dist/events/EventsBuffer.js +107 -0
  44. package/dist/events/EventsBuffer.js.map +1 -0
  45. package/dist/events/index.d.ts +2 -0
  46. package/dist/events/index.d.ts.map +1 -1
  47. package/dist/events/index.js +1 -0
  48. package/dist/events/index.js.map +1 -1
  49. package/dist/health/BaseCheck.d.ts +19 -0
  50. package/dist/health/BaseCheck.d.ts.map +1 -0
  51. package/dist/health/BaseCheck.js +24 -0
  52. package/dist/health/BaseCheck.js.map +1 -0
  53. package/dist/health/HealthChecks.d.ts +15 -0
  54. package/dist/health/HealthChecks.d.ts.map +1 -0
  55. package/dist/health/HealthChecks.js +69 -0
  56. package/dist/health/HealthChecks.js.map +1 -0
  57. package/dist/health/Result.d.ts +27 -0
  58. package/dist/health/Result.d.ts.map +1 -0
  59. package/dist/health/Result.js +55 -0
  60. package/dist/health/Result.js.map +1 -0
  61. package/dist/health/checks/DiskSpaceCheck.d.ts +29 -0
  62. package/dist/health/checks/DiskSpaceCheck.d.ts.map +1 -0
  63. package/dist/health/checks/DiskSpaceCheck.js +58 -0
  64. package/dist/health/checks/DiskSpaceCheck.js.map +1 -0
  65. package/dist/health/checks/MemoryHeapCheck.d.ts +21 -0
  66. package/dist/health/checks/MemoryHeapCheck.d.ts.map +1 -0
  67. package/dist/health/checks/MemoryHeapCheck.js +55 -0
  68. package/dist/health/checks/MemoryHeapCheck.js.map +1 -0
  69. package/dist/health/checks/MemoryRSSCheck.d.ts +21 -0
  70. package/dist/health/checks/MemoryRSSCheck.d.ts.map +1 -0
  71. package/dist/health/checks/MemoryRSSCheck.js +55 -0
  72. package/dist/health/checks/MemoryRSSCheck.js.map +1 -0
  73. package/dist/health/checks/memory.d.ts +24 -0
  74. package/dist/health/checks/memory.d.ts.map +1 -0
  75. package/dist/health/checks/memory.js +88 -0
  76. package/dist/health/checks/memory.js.map +1 -0
  77. package/dist/health/index.d.ts +9 -0
  78. package/dist/health/index.d.ts.map +1 -0
  79. package/dist/health/index.js +8 -0
  80. package/dist/health/index.js.map +1 -0
  81. package/dist/health/tracing.d.ts +12 -0
  82. package/dist/health/tracing.d.ts.map +1 -0
  83. package/dist/health/tracing.js +11 -0
  84. package/dist/health/tracing.js.map +1 -0
  85. package/dist/health/types.d.ts +51 -0
  86. package/dist/health/types.d.ts.map +1 -0
  87. package/dist/health/types.js +5 -0
  88. package/dist/health/types.js.map +1 -0
  89. package/dist/helpers/bytes.d.ts +28 -0
  90. package/dist/helpers/bytes.d.ts.map +1 -0
  91. package/dist/helpers/bytes.js +63 -0
  92. package/dist/helpers/bytes.js.map +1 -0
  93. package/dist/helpers/string.d.ts +4 -0
  94. package/dist/helpers/string.d.ts.map +1 -1
  95. package/dist/helpers/string.js +2 -0
  96. package/dist/helpers/string.js.map +1 -1
  97. package/dist/http/HttpContext.d.ts +30 -2
  98. package/dist/http/HttpContext.d.ts.map +1 -1
  99. package/dist/http/HttpContext.js +73 -3
  100. package/dist/http/HttpContext.js.map +1 -1
  101. package/dist/http/Request.d.ts +42 -3
  102. package/dist/http/Request.d.ts.map +1 -1
  103. package/dist/http/Request.js +51 -7
  104. package/dist/http/Request.js.map +1 -1
  105. package/dist/http/Response.d.ts +82 -2
  106. package/dist/http/Response.d.ts.map +1 -1
  107. package/dist/http/Response.js +240 -13
  108. package/dist/http/Response.js.map +1 -1
  109. package/dist/http/SseStream.d.ts +10 -0
  110. package/dist/http/SseStream.d.ts.map +1 -1
  111. package/dist/http/SseStream.js.map +1 -1
  112. package/dist/index.d.ts +7 -2
  113. package/dist/index.d.ts.map +1 -1
  114. package/dist/index.js +4 -1
  115. package/dist/index.js.map +1 -1
  116. package/dist/migrations/MigrationRegistry.d.ts +28 -0
  117. package/dist/migrations/MigrationRegistry.d.ts.map +1 -0
  118. package/dist/migrations/MigrationRegistry.js +41 -0
  119. package/dist/migrations/MigrationRegistry.js.map +1 -0
  120. package/dist/migrations/types.d.ts +64 -0
  121. package/dist/migrations/types.d.ts.map +1 -0
  122. package/dist/migrations/types.js +15 -0
  123. package/dist/migrations/types.js.map +1 -0
  124. package/dist/router/Router.d.ts +112 -9
  125. package/dist/router/Router.d.ts.map +1 -1
  126. package/dist/router/Router.js +206 -28
  127. package/dist/router/Router.js.map +1 -1
  128. package/dist/security/CookieSigner.d.ts +43 -4
  129. package/dist/security/CookieSigner.d.ts.map +1 -1
  130. package/dist/security/CookieSigner.js +68 -10
  131. package/dist/security/CookieSigner.js.map +1 -1
  132. package/dist/session/Session.d.ts +46 -1
  133. package/dist/session/Session.d.ts.map +1 -1
  134. package/dist/session/Session.js +57 -4
  135. package/dist/session/Session.js.map +1 -1
  136. package/dist/session/SessionMiddleware.d.ts.map +1 -1
  137. package/dist/session/SessionMiddleware.js +19 -9
  138. package/dist/session/SessionMiddleware.js.map +1 -1
  139. package/dist/session/drivers/CookieDriver.d.ts +1 -1
  140. package/dist/session/drivers/CookieDriver.d.ts.map +1 -1
  141. package/dist/session/drivers/CookieDriver.js +3 -3
  142. package/dist/session/drivers/CookieDriver.js.map +1 -1
  143. package/dist/session/drivers/DatabaseDriver.d.ts +1 -1
  144. package/dist/session/drivers/DatabaseDriver.d.ts.map +1 -1
  145. package/dist/session/drivers/DatabaseDriver.js +2 -2
  146. package/dist/session/drivers/DatabaseDriver.js.map +1 -1
  147. package/dist/session/drivers/FileDriver.d.ts +1 -1
  148. package/dist/session/drivers/FileDriver.d.ts.map +1 -1
  149. package/dist/session/drivers/FileDriver.js +7 -5
  150. package/dist/session/drivers/FileDriver.js.map +1 -1
  151. package/dist/session/drivers/MemoryDriver.d.ts +1 -1
  152. package/dist/session/drivers/MemoryDriver.d.ts.map +1 -1
  153. package/dist/session/drivers/MemoryDriver.js +1 -1
  154. package/dist/session/drivers/MemoryDriver.js.map +1 -1
  155. package/dist/session/drivers/RedisDriver.d.ts +1 -1
  156. package/dist/session/drivers/RedisDriver.d.ts.map +1 -1
  157. package/dist/session/drivers/RedisDriver.js +11 -4
  158. package/dist/session/drivers/RedisDriver.js.map +1 -1
  159. package/events.win32-x64-msvc.node +0 -0
  160. package/index.darwin-arm64.node +0 -0
  161. package/index.darwin-x64.node +0 -0
  162. package/index.linux-arm64-gnu.node +0 -0
  163. package/index.linux-x64-gnu.node +0 -0
  164. package/index.win32-x64-msvc.node +0 -0
  165. package/package.json +48 -31
  166. package/scheduler.win32-x64-msvc.node +0 -0
  167. package/src/Application.ts +169 -6
  168. package/src/HealthCheck.ts +27 -14
  169. package/src/HttpKernel.ts +27 -4
  170. package/src/Ignitor.ts +17 -8
  171. package/src/bodyparser/BodyParserMiddleware.ts +70 -36
  172. package/src/bodyparser/MultipartFile.ts +153 -8
  173. package/src/console/BaseCommand.ts +8 -1
  174. package/src/console/Kernel.ts +18 -0
  175. package/src/directories.ts +81 -0
  176. package/src/events/Emitter.ts +129 -13
  177. package/src/events/EventsBuffer.ts +131 -0
  178. package/src/events/index.ts +7 -0
  179. package/src/health/BaseCheck.ts +30 -0
  180. package/src/health/HealthChecks.ts +83 -0
  181. package/src/health/Result.ts +69 -0
  182. package/src/health/checks/DiskSpaceCheck.ts +69 -0
  183. package/src/health/checks/MemoryHeapCheck.ts +68 -0
  184. package/src/health/checks/MemoryRSSCheck.ts +68 -0
  185. package/src/health/checks/memory.ts +115 -0
  186. package/src/health/index.ts +13 -0
  187. package/src/health/tracing.ts +15 -0
  188. package/src/health/types.ts +51 -0
  189. package/src/helpers/bytes.ts +71 -0
  190. package/src/helpers/string.ts +2 -0
  191. package/src/http/HttpContext.ts +78 -4
  192. package/src/http/Request.ts +62 -10
  193. package/src/http/Response.ts +283 -14
  194. package/src/http/SseStream.ts +10 -0
  195. package/src/index.ts +27 -1
  196. package/src/migrations/MigrationRegistry.ts +49 -0
  197. package/src/migrations/types.ts +68 -0
  198. package/src/router/Router.ts +241 -32
  199. package/src/security/CookieSigner.ts +92 -18
  200. package/src/session/Session.ts +71 -5
  201. package/src/session/SessionMiddleware.ts +19 -9
  202. package/src/session/drivers/CookieDriver.ts +4 -4
  203. package/src/session/drivers/DatabaseDriver.ts +3 -3
  204. package/src/session/drivers/FileDriver.ts +8 -6
  205. package/src/session/drivers/MemoryDriver.ts +2 -2
  206. package/src/session/drivers/RedisDriver.ts +12 -5
  207. package/tsconfig.app.json +13 -13
  208. package/tsconfig.base.json +19 -0
  209. package/tsconfig.client.json +16 -0
  210. package/tsconfig.package.json +15 -0
@@ -79,13 +79,13 @@ export class RedisDriver {
79
79
  const client = await this.#client();
80
80
  const raw = await client.get(this.#key(sessionId));
81
81
  if (raw === null)
82
- return {};
82
+ return null;
83
83
  try {
84
84
  const parsed = JSON.parse(raw);
85
- return isPlainRecord(parsed) ? parsed : {};
85
+ return isPlainRecord(parsed) ? parsed : null;
86
86
  }
87
87
  catch {
88
- return {};
88
+ return null;
89
89
  }
90
90
  }
91
91
  async write(sessionId, data, ttl) {
@@ -125,7 +125,14 @@ export class RedisDriver {
125
125
  stale.push(id);
126
126
  continue;
127
127
  }
128
- sessions.push({ id, data: await this.read(id) });
128
+ // The EXISTS check above already established the key is there; a null
129
+ // here means it expired in the gap, and that device is no longer active.
130
+ const data = await this.read(id);
131
+ if (data === null) {
132
+ stale.push(id);
133
+ continue;
134
+ }
135
+ sessions.push({ id, data });
129
136
  }
130
137
  if (stale.length > 0)
131
138
  await client.srem(key, ...stale);
@@ -1 +1 @@
1
- {"version":3,"file":"RedisDriver.js","sourceRoot":"","sources":["../../../src/session/drivers/RedisDriver.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"RedisDriver.js","sourceRoot":"","sources":["../../../src/session/drivers/RedisDriver.ts"],"names":[],"mappings":"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"}
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c9up/ream",
3
- "version": "0.1.34",
3
+ "version": "0.2.1",
4
4
  "description": "Ream — Rust-powered Node.js application framework",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -43,10 +43,42 @@
43
43
  "types": "./dist/session/SessionMiddleware.d.ts",
44
44
  "import": "./dist/session/SessionMiddleware.js"
45
45
  },
46
+ "./helpers": {
47
+ "types": "./dist/helpers/index.d.ts",
48
+ "import": "./dist/helpers/index.js"
49
+ },
50
+ "./helpers/string": {
51
+ "types": "./dist/helpers/string.d.ts",
52
+ "import": "./dist/helpers/string.js"
53
+ },
54
+ "./helpers/is": {
55
+ "types": "./dist/helpers/is.d.ts",
56
+ "import": "./dist/helpers/is.js"
57
+ },
58
+ "./helpers/base64": {
59
+ "types": "./dist/helpers/base64.d.ts",
60
+ "import": "./dist/helpers/base64.js"
61
+ },
62
+ "./helpers/types": {
63
+ "types": "./dist/helpers/types.d.ts",
64
+ "import": "./dist/helpers/types.js"
65
+ },
66
+ "./testing": {
67
+ "types": "./dist/testing/TestClient.d.ts",
68
+ "import": "./dist/testing/TestClient.js"
69
+ },
70
+ "./bootstrap": {
71
+ "types": "./dist/bootstrap/hyper-server.d.ts",
72
+ "import": "./dist/bootstrap/hyper-server.js"
73
+ },
46
74
  "./events": {
47
75
  "types": "./dist/events/index.d.ts",
48
76
  "import": "./dist/events/index.js"
49
77
  },
78
+ "./health": {
79
+ "types": "./dist/health/index.d.ts",
80
+ "import": "./dist/health/index.js"
81
+ },
50
82
  "./events/provider": {
51
83
  "types": "./dist/events/EventsProvider.d.ts",
52
84
  "import": "./dist/events/EventsProvider.js"
@@ -95,36 +127,18 @@
95
127
  "types": "./dist/events/configure.d.ts",
96
128
  "import": "./dist/events/configure.js"
97
129
  },
98
- "./helpers": {
99
- "types": "./dist/helpers/index.d.ts",
100
- "import": "./dist/helpers/index.js"
101
- },
102
- "./helpers/string": {
103
- "types": "./dist/helpers/string.d.ts",
104
- "import": "./dist/helpers/string.js"
105
- },
106
- "./helpers/is": {
107
- "types": "./dist/helpers/is.d.ts",
108
- "import": "./dist/helpers/is.js"
109
- },
110
- "./helpers/base64": {
111
- "types": "./dist/helpers/base64.d.ts",
112
- "import": "./dist/helpers/base64.js"
113
- },
114
- "./helpers/types": {
115
- "types": "./dist/helpers/types.d.ts",
116
- "import": "./dist/helpers/types.js"
117
- },
118
- "./testing": {
119
- "types": "./dist/testing/TestClient.d.ts",
120
- "import": "./dist/testing/TestClient.js"
121
- },
122
- "./bootstrap": {
123
- "types": "./dist/bootstrap/hyper-server.d.ts",
124
- "import": "./dist/bootstrap/hyper-server.js"
125
- },
126
130
  "./tsconfig.app.json": "./tsconfig.app.json",
127
- "./swcrc.app.json": "./swcrc.app.json"
131
+ "./swcrc.app.json": "./swcrc.app.json",
132
+ "./tsconfig.package.json": "./tsconfig.package.json",
133
+ "./tsconfig.client.json": "./tsconfig.client.json",
134
+ "./session_middleware": {
135
+ "types": "./dist/session/SessionMiddleware.d.ts",
136
+ "import": "./dist/session/SessionMiddleware.js"
137
+ },
138
+ "./bodyparser_middleware": {
139
+ "types": "./dist/bodyparser/BodyParserMiddleware.d.ts",
140
+ "import": "./dist/bodyparser/BodyParserMiddleware.js"
141
+ }
128
142
  },
129
143
  "files": [
130
144
  "LICENSE",
@@ -136,7 +150,10 @@
136
150
  "scripts",
137
151
  "src",
138
152
  "swcrc.app.json",
139
- "tsconfig.app.json"
153
+ "tsconfig.app.json",
154
+ "tsconfig.base.json",
155
+ "tsconfig.package.json",
156
+ "tsconfig.client.json"
140
157
  ],
141
158
  "dependencies": {
142
159
  "etag": "^1.8.1",
Binary file
@@ -13,10 +13,11 @@
13
13
  * @implements FR17, FR20
14
14
  */
15
15
 
16
- import { join } from 'node:path'
16
+ import { join, relative } from 'node:path'
17
17
  import { fileURLToPath } from 'node:url'
18
18
  import { ConfigStore } from './ConfigLoader.js'
19
19
  import { Container } from './container/Container.js'
20
+ import { type DirectoriesNode, directories as defaultDirectories } from './directories.js'
20
21
  import type { AppContext, ProviderContract } from './Provider.js'
21
22
  import { callProviderPhase } from './Provider.js'
22
23
 
@@ -32,6 +33,7 @@ export class Application implements AppContext {
32
33
  readonly container: Container
33
34
  readonly config: ConfigStore
34
35
  #appRoot?: URL
36
+ #directories: DirectoriesNode = { ...defaultDirectories }
35
37
  private providers: ProviderContract[] = []
36
38
  private _booted = false
37
39
  #mode: ApplicationMode = 'run'
@@ -92,32 +94,193 @@ export class Application implements AppContext {
92
94
 
93
95
  /** Absolute path to a file/dir inside the project root. */
94
96
  makePath(...paths: string[]): string {
97
+ return join(fileURLToPath(this.#requireAppRoot()), ...paths)
98
+ }
99
+
100
+ /**
101
+ * A URL to a file/dir inside the project root, where {@link makePath} gives
102
+ * a path. What an importer wants.
103
+ */
104
+ makeURL(...paths: string[]): URL {
105
+ // Joined with '/', not `path.join`: a URL keeps forward slashes on every
106
+ // platform, and `join` would hand Windows a backslash-separated href.
107
+ return new URL(paths.join('/'), this.#requireAppRoot())
108
+ }
109
+
110
+ /** Turn an absolute path back into one relative to the project root. */
111
+ relativePath(absolutePath: string): string {
112
+ return relative(fileURLToPath(this.#requireAppRoot()), absolutePath)
113
+ }
114
+
115
+ #requireAppRoot(): URL {
95
116
  if (!this.#appRoot) {
96
117
  throw new Error(
97
118
  'Application.makePath: app root is not set — construct the Ignitor with `new Ignitor(new URL("../", import.meta.url))`.',
98
119
  )
99
120
  }
100
- return join(fileURLToPath(this.#appRoot), ...paths)
121
+ return this.#appRoot
122
+ }
123
+
124
+ /**
125
+ * The conventional directory layout, `reamrc.ts` overrides merged over the
126
+ * defaults. Every helper below reads it, so moving a directory is declared
127
+ * once.
128
+ */
129
+ get directories(): DirectoriesNode {
130
+ return this.#directories
131
+ }
132
+
133
+ /**
134
+ * Feed the loaded rc file to the application (AdonisJS `rcContents`).
135
+ *
136
+ * Today it reads one key, `directories`, merged over the defaults; the rest
137
+ * of the rc file is consumed by the Ignitor and the CLI, which own providers,
138
+ * preloads, commands and test suites.
139
+ */
140
+ rcContents(value: { directories?: Partial<DirectoriesNode> }): this {
141
+ if (value.directories) {
142
+ // Skip the undefined entries a `Partial` may carry: spreading them would
143
+ // blank a default rather than leave it alone.
144
+ for (const [key, path] of Object.entries(value.directories)) {
145
+ if (path !== undefined) this.#directories[key] = path
146
+ }
147
+ }
148
+ return this
149
+ }
150
+
151
+ /** Resolve inside one of the conventional directories. */
152
+ #inDirectory(key: keyof DirectoriesNode, paths: string[]): string {
153
+ return this.makePath(this.#directories[key], ...paths)
101
154
  }
102
155
 
103
156
  /** Absolute path inside the `config/` directory. */
104
157
  configPath(...paths: string[]): string {
105
- return this.makePath('config', ...paths)
158
+ return this.#inDirectory('config', paths)
106
159
  }
107
160
 
108
161
  /** Absolute path inside the `database/migrations/` directory. */
109
162
  migrationsPath(...paths: string[]): string {
110
- return this.makePath('database', 'migrations', ...paths)
163
+ return this.#inDirectory('migrations', paths)
111
164
  }
112
165
 
113
166
  /** Absolute path inside the `tmp/` directory. */
114
167
  tmpPath(...paths: string[]): string {
115
- return this.makePath('tmp', ...paths)
168
+ return this.#inDirectory('tmp', paths)
116
169
  }
117
170
 
118
171
  /** Absolute path inside the `public/` directory. */
119
172
  publicPath(...paths: string[]): string {
120
- return this.makePath('public', ...paths)
173
+ return this.#inDirectory('public', paths)
174
+ }
175
+
176
+ /** Absolute path inside the `providers/` directory. */
177
+ providersPath(...paths: string[]): string {
178
+ return this.#inDirectory('providers', paths)
179
+ }
180
+
181
+ /** Absolute path inside the `database/factories/` directory. */
182
+ factoriesPath(...paths: string[]): string {
183
+ return this.#inDirectory('factories', paths)
184
+ }
185
+
186
+ /** Absolute path inside the `database/seeders/` directory. */
187
+ seedersPath(...paths: string[]): string {
188
+ return this.#inDirectory('seeders', paths)
189
+ }
190
+
191
+ /** Absolute path inside the `resources/lang/` directory. */
192
+ languageFilesPath(...paths: string[]): string {
193
+ return this.#inDirectory('languageFiles', paths)
194
+ }
195
+
196
+ /** Absolute path inside the `resources/views/` directory. */
197
+ viewsPath(...paths: string[]): string {
198
+ return this.#inDirectory('views', paths)
199
+ }
200
+
201
+ /** Absolute path inside the `start/` directory. */
202
+ startPath(...paths: string[]): string {
203
+ return this.#inDirectory('start', paths)
204
+ }
205
+
206
+ /** Absolute path inside the `contracts/` directory. */
207
+ contractsPath(...paths: string[]): string {
208
+ return this.#inDirectory('contracts', paths)
209
+ }
210
+
211
+ /** Absolute path inside the `app/controllers/` directory. */
212
+ httpControllersPath(...paths: string[]): string {
213
+ return this.#inDirectory('httpControllers', paths)
214
+ }
215
+
216
+ /** Absolute path inside the `app/models/` directory. */
217
+ modelsPath(...paths: string[]): string {
218
+ return this.#inDirectory('models', paths)
219
+ }
220
+
221
+ /** Absolute path inside the `app/services/` directory. */
222
+ servicesPath(...paths: string[]): string {
223
+ return this.#inDirectory('services', paths)
224
+ }
225
+
226
+ /** Absolute path inside the `app/exceptions/` directory. */
227
+ exceptionsPath(...paths: string[]): string {
228
+ return this.#inDirectory('exceptions', paths)
229
+ }
230
+
231
+ /** Absolute path inside the `app/mailers/` directory. */
232
+ mailersPath(...paths: string[]): string {
233
+ return this.#inDirectory('mailers', paths)
234
+ }
235
+
236
+ /** Absolute path inside the `app/mails/` directory. */
237
+ mailsPath(...paths: string[]): string {
238
+ return this.#inDirectory('mails', paths)
239
+ }
240
+
241
+ /** Absolute path inside the `app/middleware/` directory. */
242
+ middlewarePath(...paths: string[]): string {
243
+ return this.#inDirectory('middleware', paths)
244
+ }
245
+
246
+ /** Absolute path inside the `app/policies/` directory. */
247
+ policiesPath(...paths: string[]): string {
248
+ return this.#inDirectory('policies', paths)
249
+ }
250
+
251
+ /** Absolute path inside the `app/validators/` directory. */
252
+ validatorsPath(...paths: string[]): string {
253
+ return this.#inDirectory('validators', paths)
254
+ }
255
+
256
+ /** Absolute path inside the `commands/` directory. */
257
+ commandsPath(...paths: string[]): string {
258
+ return this.#inDirectory('commands', paths)
259
+ }
260
+
261
+ /** Absolute path inside the `app/events/` directory. */
262
+ eventsPath(...paths: string[]): string {
263
+ return this.#inDirectory('events', paths)
264
+ }
265
+
266
+ /** Absolute path inside the `app/listeners/` directory. */
267
+ listenersPath(...paths: string[]): string {
268
+ return this.#inDirectory('listeners', paths)
269
+ }
270
+
271
+ /** Absolute path inside the `app/transformers/` directory. */
272
+ transformersPath(...paths: string[]): string {
273
+ return this.#inDirectory('transformers', paths)
274
+ }
275
+
276
+ /** Absolute path inside the generated-client directory (`.ream/client`). */
277
+ generatedClientPath(...paths: string[]): string {
278
+ return this.#inDirectory('generatedClient', paths)
279
+ }
280
+
281
+ /** Absolute path inside the generated-server directory (`.ream/server`). */
282
+ generatedServerPath(...paths: string[]): string {
283
+ return this.#inDirectory('generatedServer', paths)
121
284
  }
122
285
 
123
286
  // ─── Environment ──────────────────────────────────────────
@@ -27,24 +27,24 @@ const DEFAULT_CHECK_TIMEOUT = 5000
27
27
  * Manages health check registrations and produces aggregated status.
28
28
  */
29
29
  export class HealthCheck {
30
- private checkers: Map<string, HealthChecker> = new Map()
31
- private startTime = Date.now()
32
- private checkTimeout: number
30
+ readonly #checkers: Map<string, HealthChecker> = new Map()
31
+ readonly #startTime = Date.now()
32
+ readonly #checkTimeout: number
33
33
 
34
34
  constructor(options?: { checkTimeout?: number }) {
35
- this.checkTimeout = options?.checkTimeout ?? DEFAULT_CHECK_TIMEOUT
35
+ this.#checkTimeout = options?.checkTimeout ?? DEFAULT_CHECK_TIMEOUT
36
36
  }
37
37
 
38
38
  /** Register a health checker. */
39
39
  register(name: string, checker: HealthChecker): void {
40
- this.checkers.set(name, checker)
40
+ this.#checkers.set(name, checker)
41
41
  }
42
42
 
43
43
  /** Run all health checks and return aggregated status. */
44
44
  async check(): Promise<HealthStatus> {
45
45
  const checks: HealthCheckResult[] = []
46
46
 
47
- for (const [name, checker] of this.checkers) {
47
+ for (const [name, checker] of this.#checkers) {
48
48
  const start = Date.now()
49
49
  try {
50
50
  const result = await Promise.race([
@@ -52,8 +52,8 @@ export class HealthCheck {
52
52
  new Promise<never>((_, reject) =>
53
53
  setTimeout(
54
54
  () =>
55
- reject(new Error(`Health check '${name}' timed out after ${this.checkTimeout}ms`)),
56
- this.checkTimeout,
55
+ reject(new Error(`Health check '${name}' timed out after ${this.#checkTimeout}ms`)),
56
+ this.#checkTimeout,
57
57
  ),
58
58
  ),
59
59
  ])
@@ -76,21 +76,34 @@ export class HealthCheck {
76
76
 
77
77
  return {
78
78
  status: hasError ? 'error' : hasWarn ? 'degraded' : 'ok',
79
- uptime: Math.floor((Date.now() - this.startTime) / 1000),
79
+ uptime: Math.floor((Date.now() - this.#startTime) / 1000),
80
80
  timestamp: new Date().toISOString(),
81
81
  checks,
82
82
  }
83
83
  }
84
84
 
85
- /** Create the /health route handler. Returns 200 for ok, 503 for degraded/error. */
85
+ /**
86
+ * Create the /health route handler. Returns 200 for ok, 503 otherwise.
87
+ *
88
+ * The parameter is the narrowest shape a real `HttpContext` satisfies, so
89
+ * this can be mounted straight on a route. It used to assign
90
+ * `ctx.response.status` and `ctx.response.body` as PROPERTIES, which no Ream
91
+ * response has ever had — mounted for real it would have answered an empty
92
+ * 200 to every probe, marking a dead app healthy. Its only test built a fake
93
+ * context in that invented shape, so nothing caught it.
94
+ */
86
95
  handler(): (ctx: {
87
- response: { status: number; headers: Record<string, string>; body: string }
96
+ response: {
97
+ status(code: number): unknown
98
+ header(key: string, value: string): unknown
99
+ json(body: unknown): unknown
100
+ }
88
101
  }) => Promise<void> {
89
102
  return async (ctx) => {
90
103
  const health = await this.check()
91
- ctx.response.status = health.status === 'ok' ? 200 : 503
92
- ctx.response.headers['content-type'] = 'application/json'
93
- ctx.response.body = JSON.stringify(health)
104
+ ctx.response.status(health.status === 'ok' ? 200 : 503)
105
+ ctx.response.header('content-type', 'application/json')
106
+ ctx.response.json(health)
94
107
  }
95
108
  }
96
109
  }
package/src/HttpKernel.ts CHANGED
@@ -49,6 +49,18 @@ export interface HttpKernelConfig {
49
49
  * could rewrite itself into a DELETE.
50
50
  */
51
51
  allowMethodSpoofing?: boolean
52
+ /**
53
+ * Default callback name for `response.jsonp()` (AdonisJS
54
+ * `http.jsonpCallbackName`). Falls back to `callback`.
55
+ */
56
+ jsonpCallbackName?: string
57
+ /**
58
+ * Ceiling on a buffered response body, in bytes. Default 100MB — the same the
59
+ * Rust layer caps an incoming body at. Responses are not streamed yet, so the
60
+ * body is held whole in memory; this is what stops a large one growing until
61
+ * the process dies with no message.
62
+ */
63
+ maxResponseBytes?: number
52
64
  }
53
65
 
54
66
  export interface HttpKernelResponse {
@@ -170,6 +182,12 @@ export function createHttpKernel(
170
182
  // What Adonis binds on every request's resolver: the context itself, so a
171
183
  // controller or service can take `HttpContext` as a constructor dependency.
172
184
  resolver?.bindValue(HttpContext, ctx)
185
+ if (config.jsonpCallbackName !== undefined) {
186
+ ctx.response.setJsonpCallbackName(config.jsonpCallbackName)
187
+ }
188
+ if (config.maxResponseBytes !== undefined) {
189
+ ctx.response.setMaxBodyBytes(config.maxResponseBytes)
190
+ }
173
191
  if (config.allowMethodSpoofing === true) {
174
192
  // Was never wired: the setter existed but nothing called it, so a
175
193
  // migrated config asking for spoofing got a `_method` field that did
@@ -322,8 +340,13 @@ export function createHttpKernel(
322
340
  // the HyperServer keeps feeding a dead stream slot forever.
323
341
  await ctx.response.abortStream()
324
342
  try {
325
- await handler.handle(error, ctx)
343
+ // REPORT first, then handle — the AdonisJS order
344
+ // (`#requestErrorResponder`: `await report(error, ctx)` before
345
+ // `handle`). Handling first meant a throwing `handle()` fell into the
346
+ // catch below and the error was never reported: it vanished from the
347
+ // logs and the operator saw only "ExceptionHandler failed".
326
348
  await handler.report(error, ctx)
349
+ await handler.handle(error, ctx)
327
350
  } catch (handlerError) {
328
351
  console.error('ExceptionHandler failed:', handlerError)
329
352
  ctx.response
@@ -403,9 +426,9 @@ function readControllerGuardMetadata(
403
426
  }
404
427
 
405
428
  async function serializeResponse(ctx: HttpContext): Promise<HttpKernelResponse> {
406
- // A body still being drained by `response.stream()` — upstream returns void
407
- // there, so a migrated controller does not await it.
408
- await ctx.response.settle()
429
+ // The terminal step, as AdonisJS' server calls `response.finish()`: it
430
+ // stamps the request id and waits for a body still being produced.
431
+ await ctx.response.finish()
409
432
  const streamId = ctx.response.getStreamId()
410
433
  return {
411
434
  status: ctx.response.getStatus(),
package/src/Ignitor.ts CHANGED
@@ -17,6 +17,7 @@ import { Application } from './Application.js'
17
17
  import type { Console } from './console/Console.js'
18
18
  import type { CommandLoader, Kernel as ConsoleKernelInstance } from './console/Kernel.js'
19
19
  import { type CommandClass, isCommandClass } from './console/types.js'
20
+ import type { DirectoriesNode } from './directories.js'
20
21
  import type { ErrorEvent } from './ErrorBoundary.js'
21
22
  import { ErrorBoundary } from './ErrorBoundary.js'
22
23
  import { loadEnvFiles } from './env/loadEnvFiles.js'
@@ -32,6 +33,7 @@ import { ExceptionHandler } from './http/Exception.js'
32
33
  import { HttpContext } from './http/HttpContext.js'
33
34
  import type { MiddlewareFunction } from './middleware/Pipeline.js'
34
35
  import { MiddlewareRegistry } from './middleware/Pipeline.js'
36
+ import { MigrationRegistry } from './migrations/MigrationRegistry.js'
35
37
  import type { AppContext, ProviderContract } from './Provider.js'
36
38
  import { callProviderPhase } from './Provider.js'
37
39
  import { Router } from './router/Router.js'
@@ -64,6 +66,11 @@ export interface ReamrcConfig {
64
66
  environment?: string[]
65
67
  }
66
68
  >
69
+ /**
70
+ * Override the conventional directory layout. Merged over the defaults, so
71
+ * only the directories that moved need naming.
72
+ */
73
+ directories?: Partial<DirectoriesNode>
67
74
  commands?: Array<() => Promise<unknown>>
68
75
  /**
69
76
  * Command shorthands — Console's `commandsAliases`. The value is the command the
@@ -135,14 +142,6 @@ export interface TestsConfig {
135
142
  * `tests/bootstrap.ts`; that stays the default here, and this overrides it.
136
143
  */
137
144
  bootstrap?: string
138
- /**
139
- * Point `@japa/runner/core` at helix's shim in every worker, so official Japa
140
- * plugins (`@japa/assert`, …) instrument the runner that is actually running.
141
- *
142
- * Off by default: redirecting a package specifier is not something to do
143
- * behind a user's back, and a project with no Japa plugin gains nothing.
144
- */
145
- japaPlugins?: boolean
146
145
  }
147
146
 
148
147
  /** defineConfig helper — like AdonisJS defineConfig(). */
@@ -207,6 +206,8 @@ export class Ignitor {
207
206
  private router: Router
208
207
  private server: Server
209
208
  private middleware: MiddlewareRegistry
209
+ /** Where each data package registers its migration runner. See `MigrationRegistry`. */
210
+ private migrations: MigrationRegistry
210
211
  private errorBoundary: ErrorBoundary
211
212
  private _httpServer?: HyperServerLike
212
213
  private config: IgnitorConfig
@@ -248,12 +249,17 @@ export class Ignitor {
248
249
  this.router = new Router()
249
250
  this.server = new Server(this.router)
250
251
  this.middleware = new MiddlewareRegistry()
252
+ this.migrations = new MigrationRegistry()
251
253
  this.errorBoundary = new ErrorBoundary((event) => this.handleError(event), this.isDevMode())
252
254
 
253
255
  // Register framework services in container
254
256
  this.app.container.singleton('router', () => this.router)
255
257
  this.app.container.singleton('server', () => this.server)
256
258
  this.app.container.singleton('middleware', () => this.middleware)
259
+ // Always bound, even with no data package: an EMPTY registry is what lets
260
+ // the CLI tell "this app has no migrations" from "this app predates the
261
+ // registry" and say something useful in each case.
262
+ this.app.container.singleton('migrations', () => this.migrations)
257
263
  this.app.container.singleton('app', () => this.app)
258
264
  // The HttpContext CLASS, so an integration provider can extend it the way
259
265
  // AdonisJS does — `HttpContext.getter('view', …)` is how the view layer
@@ -325,6 +331,9 @@ export class Ignitor {
325
331
  */
326
332
  useRcFile(reamrc: ReamrcConfig): this {
327
333
  this.reamrc = reamrc
334
+ // Hand the app its directory overrides now rather than at boot: a path
335
+ // helper called from a provider's register() must already see them.
336
+ this.app.rcContents(reamrc)
328
337
  return this
329
338
  }
330
339