nmtjs 0.16.0 → 0.17.0-beta.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 (224) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +41 -1
  3. package/dist/index.d.ts +22 -121
  4. package/dist/index.js +24 -53
  5. package/dist/index.js.map +1 -1
  6. package/package.json +11 -63
  7. package/src/index.ts +71 -91
  8. package/bin/cli.js +0 -2
  9. package/dist/cli.d.ts +0 -1
  10. package/dist/cli.js +0 -137
  11. package/dist/cli.js.map +0 -1
  12. package/dist/codegen.d.ts +0 -5
  13. package/dist/codegen.js +0 -18
  14. package/dist/codegen.js.map +0 -1
  15. package/dist/config.d.ts +0 -47
  16. package/dist/config.js +0 -16
  17. package/dist/config.js.map +0 -1
  18. package/dist/entrypoints/cli.d.ts +0 -1
  19. package/dist/entrypoints/cli.js +0 -12
  20. package/dist/entrypoints/cli.js.map +0 -1
  21. package/dist/entrypoints/main.d.ts +0 -5
  22. package/dist/entrypoints/main.js +0 -248
  23. package/dist/entrypoints/main.js.map +0 -1
  24. package/dist/entrypoints/thread.d.ts +0 -16
  25. package/dist/entrypoints/thread.js +0 -182
  26. package/dist/entrypoints/thread.js.map +0 -1
  27. package/dist/entrypoints/worker.d.ts +0 -9
  28. package/dist/entrypoints/worker.js +0 -143
  29. package/dist/entrypoints/worker.js.map +0 -1
  30. package/dist/resolver.d.ts +0 -2
  31. package/dist/resolver.js +0 -7
  32. package/dist/resolver.js.map +0 -1
  33. package/dist/runtime/application/index.d.ts +0 -1
  34. package/dist/runtime/application/index.js +0 -2
  35. package/dist/runtime/application/index.js.map +0 -1
  36. package/dist/runtime/constants.d.ts +0 -8
  37. package/dist/runtime/constants.js +0 -5
  38. package/dist/runtime/constants.js.map +0 -1
  39. package/dist/runtime/enums.d.ts +0 -10
  40. package/dist/runtime/enums.js +0 -13
  41. package/dist/runtime/enums.js.map +0 -1
  42. package/dist/runtime/hooks.d.ts +0 -1
  43. package/dist/runtime/hooks.js +0 -2
  44. package/dist/runtime/hooks.js.map +0 -1
  45. package/dist/runtime/index.d.ts +0 -28
  46. package/dist/runtime/index.js +0 -29
  47. package/dist/runtime/index.js.map +0 -1
  48. package/dist/runtime/injectables.d.ts +0 -28
  49. package/dist/runtime/injectables.js +0 -24
  50. package/dist/runtime/injectables.js.map +0 -1
  51. package/dist/runtime/jobs/job.d.ts +0 -146
  52. package/dist/runtime/jobs/job.js +0 -89
  53. package/dist/runtime/jobs/job.js.map +0 -1
  54. package/dist/runtime/jobs/manager.d.ts +0 -131
  55. package/dist/runtime/jobs/manager.js +0 -309
  56. package/dist/runtime/jobs/manager.js.map +0 -1
  57. package/dist/runtime/jobs/router.d.ts +0 -296
  58. package/dist/runtime/jobs/router.js +0 -458
  59. package/dist/runtime/jobs/router.js.map +0 -1
  60. package/dist/runtime/jobs/runner.d.ts +0 -103
  61. package/dist/runtime/jobs/runner.js +0 -425
  62. package/dist/runtime/jobs/runner.js.map +0 -1
  63. package/dist/runtime/jobs/step.d.ts +0 -26
  64. package/dist/runtime/jobs/step.js +0 -18
  65. package/dist/runtime/jobs/step.js.map +0 -1
  66. package/dist/runtime/jobs/types.d.ts +0 -86
  67. package/dist/runtime/jobs/types.js +0 -5
  68. package/dist/runtime/jobs/types.js.map +0 -1
  69. package/dist/runtime/metrics/metric.d.ts +0 -8
  70. package/dist/runtime/metrics/metric.js +0 -11
  71. package/dist/runtime/metrics/metric.js.map +0 -1
  72. package/dist/runtime/metrics/registry.d.ts +0 -3
  73. package/dist/runtime/metrics/registry.js +0 -5
  74. package/dist/runtime/metrics/registry.js.map +0 -1
  75. package/dist/runtime/metrics/server.d.ts +0 -7
  76. package/dist/runtime/metrics/server.js +0 -53
  77. package/dist/runtime/metrics/server.js.map +0 -1
  78. package/dist/runtime/plugin.d.ts +0 -2
  79. package/dist/runtime/plugin.js +0 -2
  80. package/dist/runtime/plugin.js.map +0 -1
  81. package/dist/runtime/runtime.d.ts +0 -27
  82. package/dist/runtime/runtime.js +0 -77
  83. package/dist/runtime/runtime.js.map +0 -1
  84. package/dist/runtime/scheduler/index.d.ts +0 -22
  85. package/dist/runtime/scheduler/index.js +0 -20
  86. package/dist/runtime/scheduler/index.js.map +0 -1
  87. package/dist/runtime/server/applications.d.ts +0 -91
  88. package/dist/runtime/server/applications.js +0 -171
  89. package/dist/runtime/server/applications.js.map +0 -1
  90. package/dist/runtime/server/config.d.ts +0 -148
  91. package/dist/runtime/server/config.js +0 -33
  92. package/dist/runtime/server/config.js.map +0 -1
  93. package/dist/runtime/server/environment.d.ts +0 -43
  94. package/dist/runtime/server/environment.js +0 -33
  95. package/dist/runtime/server/environment.js.map +0 -1
  96. package/dist/runtime/server/error-policy.d.ts +0 -62
  97. package/dist/runtime/server/error-policy.js +0 -73
  98. package/dist/runtime/server/error-policy.js.map +0 -1
  99. package/dist/runtime/server/hmr-coordinator.d.ts +0 -37
  100. package/dist/runtime/server/hmr-coordinator.js +0 -94
  101. package/dist/runtime/server/hmr-coordinator.js.map +0 -1
  102. package/dist/runtime/server/jobs.d.ts +0 -54
  103. package/dist/runtime/server/jobs.js +0 -176
  104. package/dist/runtime/server/jobs.js.map +0 -1
  105. package/dist/runtime/server/lifecycle.d.ts +0 -85
  106. package/dist/runtime/server/lifecycle.js +0 -177
  107. package/dist/runtime/server/lifecycle.js.map +0 -1
  108. package/dist/runtime/server/managed-worker.d.ts +0 -158
  109. package/dist/runtime/server/managed-worker.js +0 -420
  110. package/dist/runtime/server/managed-worker.js.map +0 -1
  111. package/dist/runtime/server/pool-manager.d.ts +0 -85
  112. package/dist/runtime/server/pool-manager.js +0 -129
  113. package/dist/runtime/server/pool-manager.js.map +0 -1
  114. package/dist/runtime/server/proxy.d.ts +0 -21
  115. package/dist/runtime/server/proxy.js +0 -76
  116. package/dist/runtime/server/proxy.js.map +0 -1
  117. package/dist/runtime/server/server.d.ts +0 -60
  118. package/dist/runtime/server/server.js +0 -163
  119. package/dist/runtime/server/server.js.map +0 -1
  120. package/dist/runtime/server/types.d.ts +0 -31
  121. package/dist/runtime/server/types.js +0 -2
  122. package/dist/runtime/server/types.js.map +0 -1
  123. package/dist/runtime/server/worker-pool.d.ts +0 -121
  124. package/dist/runtime/server/worker-pool.js +0 -171
  125. package/dist/runtime/server/worker-pool.js.map +0 -1
  126. package/dist/runtime/store/index.d.ts +0 -3
  127. package/dist/runtime/store/index.js +0 -23
  128. package/dist/runtime/store/index.js.map +0 -1
  129. package/dist/runtime/subscription/manager.d.ts +0 -49
  130. package/dist/runtime/subscription/manager.js +0 -170
  131. package/dist/runtime/subscription/manager.js.map +0 -1
  132. package/dist/runtime/subscription/redis.d.ts +0 -18
  133. package/dist/runtime/subscription/redis.js +0 -120
  134. package/dist/runtime/subscription/redis.js.map +0 -1
  135. package/dist/runtime/types.d.ts +0 -95
  136. package/dist/runtime/types.js +0 -2
  137. package/dist/runtime/types.js.map +0 -1
  138. package/dist/runtime/workers/application.d.ts +0 -29
  139. package/dist/runtime/workers/application.js +0 -77
  140. package/dist/runtime/workers/application.js.map +0 -1
  141. package/dist/runtime/workers/base.d.ts +0 -16
  142. package/dist/runtime/workers/base.js +0 -46
  143. package/dist/runtime/workers/base.js.map +0 -1
  144. package/dist/runtime/workers/cli.d.ts +0 -1
  145. package/dist/runtime/workers/cli.js +0 -2
  146. package/dist/runtime/workers/cli.js.map +0 -1
  147. package/dist/runtime/workers/job.d.ts +0 -20
  148. package/dist/runtime/workers/job.js +0 -170
  149. package/dist/runtime/workers/job.js.map +0 -1
  150. package/dist/vite/builder.d.ts +0 -5
  151. package/dist/vite/builder.js +0 -79
  152. package/dist/vite/builder.js.map +0 -1
  153. package/dist/vite/config.d.ts +0 -28
  154. package/dist/vite/config.js +0 -22
  155. package/dist/vite/config.js.map +0 -1
  156. package/dist/vite/plugins.d.ts +0 -2
  157. package/dist/vite/plugins.js +0 -43
  158. package/dist/vite/plugins.js.map +0 -1
  159. package/dist/vite/runners/worker.d.ts +0 -3
  160. package/dist/vite/runners/worker.js +0 -34
  161. package/dist/vite/runners/worker.js.map +0 -1
  162. package/dist/vite/server.d.ts +0 -3
  163. package/dist/vite/server.js +0 -36
  164. package/dist/vite/server.js.map +0 -1
  165. package/dist/vite/servers/main.d.ts +0 -8
  166. package/dist/vite/servers/main.js +0 -24
  167. package/dist/vite/servers/main.js.map +0 -1
  168. package/dist/vite/servers/worker.d.ts +0 -13
  169. package/dist/vite/servers/worker.js +0 -124
  170. package/dist/vite/servers/worker.js.map +0 -1
  171. package/src/cli.ts +0 -162
  172. package/src/codegen.ts +0 -30
  173. package/src/config.ts +0 -69
  174. package/src/entrypoints/cli.ts +0 -13
  175. package/src/entrypoints/main.ts +0 -317
  176. package/src/entrypoints/thread.ts +0 -223
  177. package/src/entrypoints/worker.ts +0 -174
  178. package/src/resolver.ts +0 -7
  179. package/src/runtime/application/index.ts +0 -1
  180. package/src/runtime/constants.ts +0 -13
  181. package/src/runtime/enums.ts +0 -12
  182. package/src/runtime/hooks.ts +0 -1
  183. package/src/runtime/index.ts +0 -29
  184. package/src/runtime/injectables.ts +0 -72
  185. package/src/runtime/jobs/job.ts +0 -467
  186. package/src/runtime/jobs/manager.ts +0 -454
  187. package/src/runtime/jobs/router.ts +0 -967
  188. package/src/runtime/jobs/runner.ts +0 -583
  189. package/src/runtime/jobs/step.ts +0 -66
  190. package/src/runtime/jobs/types.ts +0 -116
  191. package/src/runtime/metrics/metric.ts +0 -18
  192. package/src/runtime/metrics/registry.ts +0 -11
  193. package/src/runtime/metrics/server.ts +0 -69
  194. package/src/runtime/plugin.ts +0 -2
  195. package/src/runtime/runtime.ts +0 -103
  196. package/src/runtime/scheduler/index.ts +0 -39
  197. package/src/runtime/server/applications.ts +0 -264
  198. package/src/runtime/server/config.ts +0 -199
  199. package/src/runtime/server/environment.ts +0 -71
  200. package/src/runtime/server/error-policy.ts +0 -132
  201. package/src/runtime/server/hmr-coordinator.ts +0 -116
  202. package/src/runtime/server/jobs.ts +0 -266
  203. package/src/runtime/server/lifecycle.ts +0 -234
  204. package/src/runtime/server/managed-worker.ts +0 -546
  205. package/src/runtime/server/pool-manager.ts +0 -187
  206. package/src/runtime/server/proxy.ts +0 -119
  207. package/src/runtime/server/server.ts +0 -218
  208. package/src/runtime/server/types.ts +0 -32
  209. package/src/runtime/server/worker-pool.ts +0 -275
  210. package/src/runtime/store/index.ts +0 -30
  211. package/src/runtime/subscription/manager.ts +0 -310
  212. package/src/runtime/subscription/redis.ts +0 -157
  213. package/src/runtime/types.ts +0 -84
  214. package/src/runtime/workers/application.ts +0 -133
  215. package/src/runtime/workers/base.ts +0 -71
  216. package/src/runtime/workers/cli.ts +0 -0
  217. package/src/runtime/workers/job.ts +0 -142
  218. package/src/vite/builder.ts +0 -94
  219. package/src/vite/config.ts +0 -45
  220. package/src/vite/plugins.ts +0 -53
  221. package/src/vite/runners/worker.ts +0 -55
  222. package/src/vite/server.ts +0 -55
  223. package/src/vite/servers/main.ts +0 -41
  224. package/src/vite/servers/worker.ts +0 -177
@@ -1,317 +0,0 @@
1
- import type { MessagePort, Worker } from 'node:worker_threads'
2
- import EventEmitter from 'node:events'
3
- import { fileURLToPath } from 'node:url'
4
-
5
- import type { ViteDevServer } from 'vite'
6
- import { createLogger } from '@nmtjs/core'
7
-
8
- import type { ServerConfig } from '../runtime/index.ts'
9
- import type { WorkerServerEventMap } from '../vite/servers/worker.ts'
10
- import {
11
- ApplicationServer,
12
- defaultPoolFactory,
13
- defaultWorkerFactory,
14
- isServerConfig,
15
- } from '../runtime/index.ts'
16
- import { createRuntimeEnvironment } from '../runtime/server/environment.ts'
17
- import { getErrorPolicy } from '../runtime/server/error-policy.ts'
18
- import { HMRCoordinator } from '../runtime/server/hmr-coordinator.ts'
19
- import { ServerLifecycle } from '../runtime/server/lifecycle.ts'
20
-
21
- declare global {
22
- const __VITE_CONFIG__: string
23
- const __APPLICATIONS_CONFIG__: string
24
- }
25
-
26
- class InvalidServerConfigError extends Error {
27
- constructor() {
28
- super(
29
- `Server config file does not have a default export, or it is not a valid server config. Please, make sure the server config is defined using defineServer().`,
30
- )
31
- this.name = 'InvalidServerConfigError'
32
- }
33
- }
34
-
35
- const _ext = new URL(import.meta.url).pathname.endsWith('.ts') ? '.ts' : '.js'
36
- const _vite = __VITE_CONFIG__ ? JSON.parse(__VITE_CONFIG__) : undefined
37
- const applicationsConfig: Record<
38
- string,
39
- { type: 'neemata' | 'custom'; specifier: string }
40
- > = __APPLICATIONS_CONFIG__ ? JSON.parse(__APPLICATIONS_CONFIG__) : {}
41
-
42
- // Runtime environment setup
43
- const mode = _vite?.mode === 'development' ? 'development' : 'production'
44
- const isDev = mode === 'development'
45
- const errorPolicy = getErrorPolicy(mode)
46
- const bootstrapLogger = createLogger(
47
- { pinoOptions: { level: isDev ? 'debug' : 'info' } },
48
- 'Main',
49
- )
50
-
51
- // Logger for main process (created lazily with config-based level)
52
- let logger: ReturnType<typeof createLogger> = bootstrapLogger
53
-
54
- // Vite server and events (dev only)
55
- let _viteServerEvents: EventEmitter<WorkerServerEventMap> | undefined
56
- let _viteServer: ViteDevServer | undefined
57
-
58
- // Server lifecycle management
59
- let lifecycle: ServerLifecycle | undefined
60
- let hmrCoordinator: HMRCoordinator | undefined
61
-
62
- // Current server config (updated on HMR)
63
- let currentServerConfig: ServerConfig | undefined
64
-
65
- // Track termination state
66
- let isTerminating = false
67
-
68
- function resolveViteRunnerTimeoutMs(): number | undefined {
69
- const raw = process.env.NMTJS_VITE_RUNNER_TIMEOUT_MS
70
- if (!raw) return undefined
71
-
72
- const parsed = Number.parseInt(raw, 10)
73
- if (!Number.isFinite(parsed) || parsed <= 0) {
74
- logger.warn(
75
- { value: raw },
76
- 'Invalid NMTJS_VITE_RUNNER_TIMEOUT_MS, falling back to default',
77
- )
78
- return undefined
79
- }
80
-
81
- return parsed
82
- }
83
-
84
- /**
85
- * Create the ApplicationServer instance using currentServerConfig.
86
- */
87
- function createServer(): ApplicationServer {
88
- if (!currentServerConfig) {
89
- throw new Error('Server config not initialized')
90
- }
91
-
92
- const workerConfig = {
93
- path: fileURLToPath(new URL(`./thread${_ext}`, import.meta.url)),
94
- workerData: {
95
- vite: _vite?.mode,
96
- viteModuleRunnerTimeoutMs: resolveViteRunnerTimeoutMs(),
97
- },
98
- worker: _viteServerEvents
99
- ? ({ worker, vitePort }: { worker: Worker; vitePort?: MessagePort }) => {
100
- _viteServerEvents!.emit('worker', { worker, vitePort })
101
- }
102
- : undefined,
103
- events: _viteServerEvents,
104
- }
105
-
106
- return new ApplicationServer(
107
- currentServerConfig,
108
- applicationsConfig,
109
- workerConfig,
110
- undefined, // runOptions
111
- errorPolicy,
112
- defaultWorkerFactory,
113
- defaultPoolFactory,
114
- )
115
- }
116
-
117
- /**
118
- * Initialize Vite dev server (dev mode only).
119
- */
120
- async function initializeVite() {
121
- if (!_vite) return
122
-
123
- const { createViteServer } = await import('../vite/servers/worker.ts')
124
- const neemataConfig = await import(
125
- /* @vite-ignore */
126
- _vite.options.configPath
127
- ).then((m) => m.default as import('../config.ts').NeemataConfig)
128
-
129
- _viteServerEvents = new EventEmitter<WorkerServerEventMap>()
130
- _viteServerEvents.on('hmr-update', handleHMRUpdate)
131
-
132
- _viteServer = await createViteServer(
133
- _vite.options,
134
- _vite.mode,
135
- neemataConfig,
136
- _viteServerEvents,
137
- )
138
- }
139
-
140
- /**
141
- * Initialize the server lifecycle (called once at startup).
142
- */
143
- function initializeLifecycle(configValue: ServerConfig) {
144
- if (!isServerConfig(configValue)) throw new InvalidServerConfigError()
145
-
146
- // Store initial config
147
- currentServerConfig = configValue
148
- const loggerOptions = currentServerConfig?.logger ?? {
149
- pinoOptions: { level: isDev ? 'debug' : 'info' },
150
- }
151
- logger = createLogger(loggerOptions, 'Main')
152
-
153
- // Create runtime environment
154
- const env = createRuntimeEnvironment(mode, {
155
- vite: _viteServer ?? undefined,
156
- hmr: undefined, // hmrCoordinator created after lifecycle
157
- })
158
-
159
- // Create lifecycle (singleton)
160
- lifecycle = new ServerLifecycle(env, createServer, logger)
161
-
162
- // Create HMR coordinator (dev only, singleton)
163
- if (isDev) {
164
- hmrCoordinator = new HMRCoordinator(lifecycle, logger)
165
- }
166
-
167
- // Listen for lifecycle errors (once)
168
- lifecycle.on('error', (error, handled) => {
169
- if (!handled) {
170
- logger.error(new Error('Unhandled lifecycle error', { cause: error }))
171
- }
172
- })
173
- }
174
-
175
- /**
176
- * Set up HMR acceptance for server config changes.
177
- */
178
- function setupHMR() {
179
- if (!import.meta.env.DEV || !import.meta.hot) return
180
-
181
- import.meta.hot.accept('#server', async (module) => {
182
- if (!module) return
183
- if (!isServerConfig(module.default)) throw new InvalidServerConfigError()
184
-
185
- // Update the config (createServer will use this on next reload)
186
- currentServerConfig = module.default
187
-
188
- // Use HMR coordinator to handle the reload
189
- if (hmrCoordinator) {
190
- try {
191
- await hmrCoordinator.scheduleReload()
192
- } catch (cause) {
193
- logger.error(new Error('Error during HMR reload', { cause }))
194
- }
195
- }
196
- })
197
- }
198
-
199
- /**
200
- * Handle HMR update event.
201
- * When an application file is updated and there are failed workers, restart them.
202
- */
203
- async function handleHMRUpdate(_event: { file: string }) {
204
- // If server is in failed state, try to start it
205
- if (lifecycle?.currentState === 'failed') {
206
- try {
207
- await lifecycle.start()
208
- } catch {
209
- // Error will be handled by lifecycle
210
- }
211
- return
212
- }
213
-
214
- // If server is running, restart any failed workers
215
- const server = lifecycle?.getServer()
216
- if (server) {
217
- try {
218
- const restarted = await server.restartFailedWorkers()
219
- if (restarted > 0) {
220
- logger.info(
221
- { count: restarted },
222
- 'Restarted failed workers after HMR update',
223
- )
224
- }
225
- } catch (error) {
226
- logger.error(
227
- new Error('Failed to restart workers after HMR update', {
228
- cause: error,
229
- }),
230
- )
231
- }
232
- }
233
- }
234
-
235
- /**
236
- * Handle startup error.
237
- */
238
- function handleStartupError(error: unknown) {
239
- const normalized = error instanceof Error ? error : new Error(String(error))
240
- logger.error(
241
- new Error('Failed to start application server', { cause: normalized }),
242
- )
243
- }
244
-
245
- /**
246
- * Handle process termination signals.
247
- */
248
- async function handleTermination() {
249
- if (isTerminating) return
250
- isTerminating = true
251
-
252
- logger.info('Shutting down...')
253
-
254
- try {
255
- await lifecycle?.stop()
256
- } catch (error) {
257
- logger.error(new Error('Failed to stop server', { cause: error as Error }))
258
- }
259
-
260
- try {
261
- await _viteServer?.close()
262
- } catch (error) {
263
- logger.error(new Error('Failed to close Vite server', { cause: error }))
264
- }
265
- process.exit(0)
266
- }
267
-
268
- /**
269
- * Handle unexpected errors.
270
- */
271
- function handleUnexpectedError(error: unknown) {
272
- const normalized = error instanceof Error ? error : new Error(String(error))
273
- logger.error(new Error('Unexpected Error', { cause: normalized }))
274
- }
275
-
276
- /**
277
- * Main entry point.
278
- */
279
- async function main() {
280
- // Set up process handlers
281
- process.once('SIGTERM', handleTermination)
282
- process.once('SIGINT', handleTermination)
283
- process.on('uncaughtException', handleUnexpectedError)
284
- process.on('unhandledRejection', handleUnexpectedError)
285
-
286
- // Initialize Vite (dev mode only)
287
- await initializeVite()
288
-
289
- // Load server config
290
- const serverConfig = await import(
291
- // @ts-expect-error
292
- '#server'
293
- ).then((m) => m.default)
294
-
295
- // Initialize lifecycle (sync, creates singletons)
296
- initializeLifecycle(serverConfig)
297
-
298
- // Set up HMR
299
- setupHMR()
300
-
301
- // Start the server
302
- try {
303
- await lifecycle!.start()
304
- } catch (error) {
305
- handleStartupError(error)
306
- if (!isDev) {
307
- process.exit(1)
308
- }
309
- }
310
- }
311
-
312
- main().catch((error) => {
313
- logger.fatal(new Error('Fatal error during startup', { cause: error }))
314
- if (!isDev) {
315
- process.exit(1)
316
- }
317
- })
@@ -1,223 +0,0 @@
1
- import type { MessagePort } from 'node:worker_threads'
2
- import { fileURLToPath } from 'node:url'
3
- import { workerData as _workerData } from 'node:worker_threads'
4
-
5
- import type { ModuleRunner } from 'vite/module-runner'
6
- import { createLogger } from '@nmtjs/core'
7
-
8
- import type {
9
- ThreadErrorMessage,
10
- ThreadPortMessage,
11
- WorkerThreadErrorOrigin,
12
- } from '../runtime/index.ts'
13
-
14
- export type RunWorkerOptions = {
15
- port: MessagePort
16
- vitePort?: MessagePort
17
- runtime:
18
- | { type: 'application'; name: string; path: string; transportsData: any }
19
- | { type: 'jobs'; jobWorkerPool: string }
20
- vite?: 'development' | 'production'
21
- viteModuleRunnerTimeoutMs?: number
22
- }
23
-
24
- const workerData = _workerData as RunWorkerOptions
25
-
26
- const logger = createLogger(
27
- {
28
- pinoOptions: {
29
- level: workerData.vite === 'development' ? 'debug' : 'info',
30
- },
31
- },
32
- 'Thread',
33
- )
34
-
35
- const ext = new URL(import.meta.url).pathname.endsWith('.ts') ? '.ts' : '.js'
36
- const workerPath = fileURLToPath(new URL(`./worker${ext}`, import.meta.url))
37
-
38
- type WorkerModule = typeof import('./worker.ts')
39
- type WorkerRuntime = Awaited<ReturnType<WorkerModule['run']>>
40
-
41
- const kReportedError = Symbol.for('nmtjs.worker.reported-error')
42
-
43
- let runner: ModuleRunner | undefined
44
- let workerModule: WorkerModule
45
- let runtime: WorkerRuntime | undefined
46
- let runtimeStarted = false
47
- let cleanupPromise: Promise<void> | null = null
48
-
49
- process.on('uncaughtException', (error) => {
50
- reportError(error, 'runtime', { fatal: true })
51
- })
52
-
53
- process.on('unhandledRejection', (error) => {
54
- reportError(error, 'runtime', { fatal: true })
55
- })
56
-
57
- process.once('SIGTERM', () => {
58
- void terminate(0)
59
- })
60
-
61
- process.once('SIGINT', () => {
62
- void terminate(0)
63
- })
64
-
65
- process.once('beforeExit', () => {
66
- if (!cleanupPromise && (runtimeStarted || runner)) {
67
- void cleanup()
68
- }
69
- })
70
-
71
- async function cleanup() {
72
- if (cleanupPromise) return cleanupPromise
73
-
74
- cleanupPromise = (async () => {
75
- await stopRuntime()
76
- await closeRunner()
77
- })().finally(() => {
78
- cleanupPromise = null
79
- })
80
-
81
- return cleanupPromise
82
- }
83
-
84
- async function terminate(code: number) {
85
- await cleanup()
86
- process.exit(code)
87
- }
88
-
89
- async function closeRunner() {
90
- if (!runner) return
91
- try {
92
- await runner.close()
93
- } catch (error) {
94
- reportError(error, 'runtime', { fatal: false })
95
- } finally {
96
- runner = undefined
97
- }
98
- }
99
-
100
- async function stopRuntime() {
101
- if (!runtime) return
102
- try {
103
- if (runtimeStarted) {
104
- await runtime.stop()
105
- }
106
- } catch (error) {
107
- reportError(error, 'runtime', { fatal: false })
108
- } finally {
109
- runtimeStarted = false
110
- }
111
- }
112
-
113
- function normalizeError(value: unknown): Error {
114
- if (value instanceof Error) return value
115
- if (typeof value === 'string') return new Error(value)
116
- if (value && typeof value === 'object') {
117
- try {
118
- return new Error(JSON.stringify(value))
119
- } catch {}
120
- }
121
- return new Error(String(value))
122
- }
123
-
124
- function serializeError(
125
- error: Error,
126
- origin: WorkerThreadErrorOrigin,
127
- fatal: boolean,
128
- ): ThreadErrorMessage {
129
- return {
130
- message: error.message,
131
- name: error.name,
132
- stack: error.stack,
133
- origin,
134
- fatal,
135
- }
136
- }
137
-
138
- function reportError(
139
- value: unknown,
140
- origin: WorkerThreadErrorOrigin,
141
- options: { fatal?: boolean } = {},
142
- ): Error {
143
- const fatal = options.fatal ?? origin !== 'runtime'
144
- const error = normalizeError(value)
145
- if (!(error as any)[kReportedError]) {
146
- try {
147
- workerData.port.postMessage({
148
- type: 'error',
149
- data: serializeError(error, origin, fatal),
150
- } satisfies ThreadPortMessage)
151
- } catch {}
152
- logger.error(new Error(`Worker thread ${origin} error`, { cause: error }))
153
- ;(error as any)[kReportedError] = true
154
- }
155
- return error
156
- }
157
-
158
- async function loadWorkerModule() {
159
- try {
160
- if (workerData.vite) {
161
- const { createModuleRunner } = (await import(
162
- '../vite/runners/worker.ts'
163
- )) as typeof import('../vite/runners/worker.ts')
164
-
165
- runner = createModuleRunner(
166
- workerData.vitePort,
167
- workerData.vite,
168
- workerData.viteModuleRunnerTimeoutMs,
169
- )
170
- workerModule = await runner.import(workerPath)
171
- } else {
172
- runner = undefined
173
- workerModule = await import(
174
- /* @vite-ignore */
175
- workerPath
176
- )
177
- }
178
- } catch (error) {
179
- throw reportError(error, 'bootstrap')
180
- }
181
- }
182
-
183
- async function initializeRuntime() {
184
- try {
185
- runtime = await workerModule.run(workerData.runtime)
186
- } catch (error) {
187
- throw reportError(error, 'bootstrap')
188
- }
189
-
190
- workerData.port.on('message', async (msg) => {
191
- if (msg.type === 'stop') {
192
- await terminate(0)
193
- }
194
- })
195
- }
196
-
197
- async function startRuntime() {
198
- if (!runtime) return
199
- try {
200
- const hosts = (await runtime.start()) || undefined
201
- runtimeStarted = true
202
- workerData.port.postMessage({
203
- type: 'ready',
204
- data: { hosts },
205
- } satisfies ThreadPortMessage)
206
- } catch (error) {
207
- throw reportError(error, 'start')
208
- }
209
- }
210
-
211
- async function main() {
212
- await loadWorkerModule()
213
- await initializeRuntime()
214
- await startRuntime()
215
- }
216
-
217
- main().catch(async (error) => {
218
- const normalized = error instanceof Error ? error : normalizeError(error)
219
- if (!(normalized as any)[kReportedError]) {
220
- reportError(normalized, 'bootstrap')
221
- }
222
- await terminate(1)
223
- })
@@ -1,174 +0,0 @@
1
- import { workerData } from 'node:worker_threads'
2
-
3
- import type { ServerConfig } from '../runtime/index.ts'
4
- import type { RunWorkerOptions } from './thread.ts'
5
- import {
6
- ApplicationWorkerRuntime,
7
- isApplicationHostDefinition,
8
- JobWorkerRuntime,
9
- } from '../runtime/index.ts'
10
-
11
- /**
12
- * Worker entry point.
13
- *
14
- * Handles initialization of application or job worker runtimes.
15
- * Includes HMR supersede logic for application workers.
16
- */
17
- export async function run(options: RunWorkerOptions['runtime']) {
18
- const serverConfig: ServerConfig = await import(
19
- // @ts-expect-error
20
- '#server'
21
- ).then((m) => m.default)
22
-
23
- if (options.type === 'application') {
24
- return initializeApplicationWorker(options, serverConfig)
25
- } else if (options.type === 'jobs') {
26
- return initializeJobWorker(options, serverConfig)
27
- } else {
28
- throw new Error(`Unknown runtime type: ${(options as any).type}`)
29
- }
30
- }
31
-
32
- /**
33
- * Initialize an application worker with HMR support.
34
- */
35
- async function initializeApplicationWorker(
36
- options: Extract<RunWorkerOptions['runtime'], { type: 'application' }>,
37
- serverConfig: ServerConfig,
38
- ) {
39
- const { name, path, transportsData } = options
40
-
41
- // Load initial application host definition
42
- const hostDefinition = await import(
43
- /* @vite-ignore */
44
- path
45
- ).then((m) => m.default)
46
-
47
- if (!isApplicationHostDefinition(hostDefinition)) {
48
- throw new Error(`Invalid application host definition: ${name}`)
49
- }
50
-
51
- // Create runtime
52
- const runtime = new ApplicationWorkerRuntime(
53
- serverConfig,
54
- { name, path, transports: transportsData },
55
- hostDefinition,
56
- )
57
-
58
- // Set up HMR with supersede logic
59
- setupApplicationHMR(runtime)
60
-
61
- return runtime
62
- }
63
-
64
- /**
65
- * Set up HMR acceptance for application host definition changes with supersede logic.
66
- *
67
- * When a reload is in progress and another HMR event arrives, the pending
68
- * reload is superseded - only the most recent config is applied.
69
- */
70
- function setupApplicationHMR(runtime: ApplicationWorkerRuntime) {
71
- const logger = runtime.logger.child({ component: 'HMR' })
72
-
73
- // Track active reload
74
- let activeReload: Promise<void> | null = null
75
-
76
- // Track pending reload (supersedes previous pending)
77
- let pendingConfig: unknown | null = null
78
- let pendingResolve: (() => void) | null = null
79
- let pendingReject: ((e: Error) => void) | null = null
80
-
81
- /**
82
- * Execute a reload with the given config.
83
- */
84
- const executeReload = async (config: any): Promise<void> => {
85
- activeReload = doReload(config)
86
-
87
- try {
88
- await activeReload
89
- } finally {
90
- activeReload = null
91
-
92
- // If there's a pending reload, execute it now
93
- if (pendingConfig !== null) {
94
- const config = pendingConfig
95
- const resolve = pendingResolve!
96
- const reject = pendingReject!
97
-
98
- pendingConfig = null
99
- pendingResolve = null
100
- pendingReject = null
101
-
102
- executeReload(config).then(resolve, reject)
103
- }
104
- }
105
- }
106
-
107
- /**
108
- * Perform the actual reload.
109
- */
110
- const doReload = async (config: any): Promise<void> => {
111
- try {
112
- logger.debug('Reloading application...')
113
- await runtime.reload(config)
114
- logger.info('Application reloaded successfully')
115
- } catch (error) {
116
- // Log error but keep worker alive for next HMR update
117
- logger.error(new Error('Error during HMR reload', { cause: error }))
118
- }
119
- }
120
-
121
- /**
122
- * Schedule a reload. If reload is in progress, supersedes any pending.
123
- */
124
- const scheduleReload = (config: any): Promise<void> => {
125
- // If no active reload, execute immediately
126
- if (!activeReload) {
127
- return executeReload(config)
128
- }
129
-
130
- logger.debug('Reload in progress, queuing update...')
131
- // Supersede any existing pending reload
132
- if (pendingResolve) {
133
- logger.debug('Superseding previous pending reload')
134
- pendingResolve() // Resolve old pending (it's superseded)
135
- }
136
-
137
- // Create new pending
138
- return new Promise((resolve, reject) => {
139
- pendingConfig = config
140
- pendingResolve = resolve
141
- pendingReject = reject
142
- })
143
- }
144
-
145
- // Register global hot accept handler
146
- globalThis._hotAccept = async (module: any) => {
147
- logger.debug('Received HMR update')
148
- if (!module) return
149
-
150
- if (!isApplicationHostDefinition(module.default)) {
151
- logger.error(
152
- new Error('Invalid application host definition during HMR reload'),
153
- )
154
- return
155
- }
156
-
157
- await scheduleReload(module.default)
158
- }
159
- }
160
-
161
- /**
162
- * Initialize a job worker.
163
- */
164
- async function initializeJobWorker(
165
- options: Extract<RunWorkerOptions['runtime'], { type: 'jobs' }>,
166
- serverConfig: ServerConfig,
167
- ) {
168
- const { jobWorkerPool } = options
169
- const runtime = new JobWorkerRuntime(serverConfig, {
170
- poolName: jobWorkerPool,
171
- port: workerData.port,
172
- })
173
- return runtime
174
- }
package/src/resolver.ts DELETED
@@ -1,7 +0,0 @@
1
- import { ResolverFactory } from 'oxc-resolver'
2
-
3
- export const resolver = new ResolverFactory({
4
- tsconfig: 'auto',
5
- extensions: ['.ts', '.js', '.mjs', '.mts', '.json', '.node', '.wasm'],
6
- mainFields: ['module', 'main'],
7
- })