phecda-server 6.1.0 → 7.0.0-alpha.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 (82) hide show
  1. package/assets/ps.json +24 -24
  2. package/bin/cli.mjs +165 -157
  3. package/dist/{chunk-NL6QBQAR.js → chunk-7YQ57BQS.js} +21 -22
  4. package/dist/chunk-GSPBHZBH.js +534 -0
  5. package/dist/{chunk-J7B24YSE.mjs → chunk-HMVLXNV3.mjs} +5 -14
  6. package/dist/{chunk-TVT62GIX.js → chunk-J5CFUN4V.js} +8 -1
  7. package/dist/{chunk-JDV2XJYE.js → chunk-MBCHNDAY.js} +27 -36
  8. package/dist/{chunk-2CFYUXPM.mjs → chunk-V7EI76QQ.mjs} +136 -141
  9. package/dist/{chunk-G7TD2VB7.mjs → chunk-WHJ5FALK.mjs} +7 -0
  10. package/dist/{chunk-3H3T54IC.mjs → chunk-XYVMNY2X.mjs} +4 -5
  11. package/dist/{core-P1CsH6jz.d.mts → core-BIcUwV18.d.mts} +1 -1
  12. package/dist/{core-BlN0Spy9.d.ts → core-CYwEPfN4.d.ts} +1 -1
  13. package/dist/helper.d.mts +4 -6
  14. package/dist/helper.d.ts +4 -6
  15. package/dist/helper.js +3 -3
  16. package/dist/helper.mjs +2 -2
  17. package/dist/{server → http}/elysia/index.d.mts +5 -5
  18. package/dist/{server → http}/elysia/index.d.ts +5 -5
  19. package/dist/{server → http}/elysia/index.js +80 -62
  20. package/dist/{server → http}/elysia/index.mjs +50 -32
  21. package/dist/{server → http}/express/index.d.mts +5 -5
  22. package/dist/{server → http}/express/index.d.ts +5 -5
  23. package/dist/{server → http}/express/index.js +71 -55
  24. package/dist/{server → http}/express/index.mjs +42 -26
  25. package/dist/{server → http}/fastify/index.d.mts +5 -5
  26. package/dist/{server → http}/fastify/index.d.ts +5 -5
  27. package/dist/{server → http}/fastify/index.js +72 -72
  28. package/dist/{server → http}/fastify/index.mjs +47 -47
  29. package/dist/{server → http}/h3/index.d.mts +5 -5
  30. package/dist/{server → http}/h3/index.d.ts +5 -5
  31. package/dist/http/h3/index.js +160 -0
  32. package/dist/{server → http}/h3/index.mjs +68 -62
  33. package/dist/{server → http}/hono/index.d.mts +5 -5
  34. package/dist/{server → http}/hono/index.d.ts +5 -5
  35. package/dist/{server → http}/hono/index.js +69 -54
  36. package/dist/{server → http}/hono/index.mjs +41 -26
  37. package/dist/{server → http}/hyper-express/index.d.mts +5 -5
  38. package/dist/{server → http}/hyper-express/index.d.ts +5 -5
  39. package/dist/{server → http}/hyper-express/index.js +69 -56
  40. package/dist/{server → http}/hyper-express/index.mjs +41 -28
  41. package/dist/{server → http}/koa/index.d.mts +5 -5
  42. package/dist/{server → http}/koa/index.d.ts +5 -5
  43. package/dist/{server → http}/koa/index.js +71 -55
  44. package/dist/{server → http}/koa/index.mjs +42 -26
  45. package/dist/index.d.mts +52 -41
  46. package/dist/index.d.ts +52 -41
  47. package/dist/index.js +59 -81
  48. package/dist/index.mjs +39 -61
  49. package/dist/{meta-KtfiBIde.d.ts → meta-BXKLFTgG.d.mts} +2 -3
  50. package/dist/{meta-KtfiBIde.d.mts → meta-BXKLFTgG.d.ts} +2 -3
  51. package/dist/rpc/bullmq/index.d.mts +6 -6
  52. package/dist/rpc/bullmq/index.d.ts +6 -6
  53. package/dist/rpc/bullmq/index.js +24 -24
  54. package/dist/rpc/bullmq/index.mjs +14 -14
  55. package/dist/rpc/kafka/index.d.mts +3 -3
  56. package/dist/rpc/kafka/index.d.ts +3 -3
  57. package/dist/rpc/kafka/index.js +25 -21
  58. package/dist/rpc/kafka/index.mjs +15 -11
  59. package/dist/rpc/nats/index.d.mts +3 -3
  60. package/dist/rpc/nats/index.d.ts +3 -3
  61. package/dist/rpc/nats/index.js +22 -21
  62. package/dist/rpc/nats/index.mjs +13 -12
  63. package/dist/rpc/rabbitmq/index.d.mts +3 -3
  64. package/dist/rpc/rabbitmq/index.d.ts +3 -3
  65. package/dist/rpc/rabbitmq/index.js +23 -22
  66. package/dist/rpc/rabbitmq/index.mjs +12 -11
  67. package/dist/rpc/redis/index.d.mts +3 -3
  68. package/dist/rpc/redis/index.d.ts +3 -3
  69. package/dist/rpc/redis/index.js +24 -20
  70. package/dist/rpc/redis/index.mjs +15 -11
  71. package/dist/test.d.mts +3 -3
  72. package/dist/test.d.ts +3 -3
  73. package/dist/test.js +6 -6
  74. package/dist/test.mjs +2 -2
  75. package/dist/{types-JVT0mgLD.d.ts → types-BtbL49Zs.d.mts} +2 -1
  76. package/dist/{types-DIw7B6Up.d.ts → types-VFzEM7LL.d.ts} +5 -5
  77. package/dist/{types-BvD3B5Ny.d.mts → types-h40T3cRG.d.mts} +5 -5
  78. package/dist/{types-t9D1fU6G.d.mts → types-m3IEDKjP.d.ts} +2 -1
  79. package/package.json +23 -23
  80. package/register/loader.mjs +366 -367
  81. package/dist/chunk-DVTBLV6I.js +0 -539
  82. package/dist/server/h3/index.js +0 -154
@@ -1,367 +1,366 @@
1
- import { fileURLToPath, pathToFileURL } from 'url'
2
- import { writeFile } from 'fs/promises'
3
- import {
4
- basename,
5
- extname,
6
- isAbsolute,
7
- relative,
8
- resolve as resolvePath,
9
- } from 'path'
10
- import { createRequire } from 'module'
11
- import ts from 'typescript'
12
- import chokidar from 'chokidar'
13
- import { log } from '../dist/index.mjs'
14
- import { compile, genUnImportRet, handleClassTypes, slash } from './utils.mjs'
15
-
16
- let port
17
-
18
- const isLowVersion = parseFloat(process.version.slice(1)) < 18.19
19
- // this part is important or not?
20
- const EXTENSIONS = [ts.Extension.Ts, ts.Extension.Tsx, ts.Extension.Mts]
21
- const tsconfig = {
22
- module: ts.ModuleKind.ESNext,
23
- moduleResolution: ts.ModuleResolutionKind.NodeNext,
24
- }
25
- const moduleResolutionCache = ts.createModuleResolutionCache(
26
- ts.sys.getCurrentDirectory(),
27
- x => x,
28
- tsconfig,
29
- )
30
- const host = {
31
- fileExists: ts.sys.fileExists,
32
- readFile: ts.sys.readFile,
33
- }
34
-
35
- let unimportRet
36
- const dtsPath = 'ps.d.ts'
37
-
38
- if (isLowVersion)
39
- await initialize()
40
-
41
- let config
42
-
43
- const workdir = process.env.PS_WORKDIR || process.cwd()
44
-
45
- const configPath = resolvePath(
46
- workdir,
47
- process.env.PS_CONFIG_FILE || 'ps.json',
48
- )
49
-
50
- const require = createRequire(import.meta.url)
51
- export async function initialize(data) {
52
- if (data)
53
- port = data.port
54
- log('read config...')
55
-
56
- config = require(configPath)
57
- if (!config.virtualFile)
58
- config.virtualFile = {}
59
-
60
- if (!process.env.PS_HMR_BAN) {
61
- chokidar.watch(configPath, { persistent: true }).on('change', () => {
62
- port.postMessage(
63
- JSON.stringify({
64
- type: 'relaunch',
65
- }),
66
- )
67
- })
68
- }
69
-
70
- if (!config.unimport)
71
- return
72
- unimportRet = await genUnImportRet(config.unimport)
73
- if (unimportRet) {
74
- log('auto import...')
75
- await unimportRet.init()
76
-
77
- writeFile(
78
- resolvePath(workdir, config.unimport.dtsPath || dtsPath),
79
- handleClassTypes(
80
- await unimportRet.generateTypeDeclarations({
81
- resolvePath: (i) => {
82
- if (i.from.startsWith('.') || isAbsolute(i.from)) {
83
- const related = slash(
84
- relative(workdir, i.from).replace(/\.ts(x)?$/, ''),
85
- )
86
-
87
- return !related.startsWith('.') ? `./${related}` : related
88
- }
89
- return i.from
90
- },
91
- }),
92
- ),
93
- )
94
- }
95
- }
96
-
97
- const watchFiles = new Set()
98
- const filesRecord = new Map()
99
- const moduleGraph = {}
100
-
101
- let entryUrl
102
-
103
- function addUrlToGraph(url, parent) {
104
- if (!(url in moduleGraph))
105
- moduleGraph[url] = new Set()
106
-
107
- moduleGraph[url].add(parent)
108
- return url + (filesRecord.has(url) ? `?t=${filesRecord.get(url)}` : '')
109
- }
110
-
111
- function getFileMid(file) {
112
- const filename = basename(file)
113
- const ret = filename.split('.')
114
- if (ret.length === 3)
115
- return ret[1]
116
- else return ''
117
- }
118
-
119
- export const resolve = async (specifier, context, nextResolve) => {
120
- // virtual file
121
- if (config.virtualFile[specifier]) {
122
- return {
123
- format: 'ts',
124
- url: specifier,
125
- shortCircuit: true,
126
- }
127
- }
128
- // entrypoint
129
- if (!context.parentURL) {
130
- entryUrl = specifier
131
- return {
132
- format: EXTENSIONS.some(ext => specifier.endsWith(ext))
133
- ? 'ts'
134
- : undefined,
135
- url: specifier,
136
- shortCircuit: true,
137
- }
138
- }
139
- // url import
140
- // it seems useless
141
- if (/^file:\/\/\//.test(specifier) && extname(specifier) === '.ts') {
142
- const url = addUrlToGraph(specifier, context.parentURL.split('?')[0])
143
- return {
144
- format: 'ts',
145
- url,
146
- shortCircuit: true,
147
- }
148
- }
149
-
150
- // hmr import
151
- if (
152
- context.parentURL.includes('/node_modules/phecda-server')
153
- && isAbsolute(specifier)
154
- ) {
155
- specifier = relative(fileURLToPath(entryUrl), specifier)
156
- .replace(/\.ts$/, '')
157
- .slice(1)
158
- context.parentURL = entryUrl
159
- }
160
-
161
- // import/require from external library
162
- if (context.parentURL.includes('/node_modules/'))
163
- return nextResolve(specifier)
164
- const { resolvedModule } = ts.resolveModuleName(
165
- specifier,
166
- fileURLToPath(context.parentURL),
167
- tsconfig,
168
- host,
169
- moduleResolutionCache,
170
- )
171
-
172
- // import between loacl projects
173
- if (
174
- resolvedModule
175
- && !resolvedModule.resolvedFileName.includes('/node_modules/')
176
- && EXTENSIONS.includes(resolvedModule.extension)
177
- ) {
178
- const url = addUrlToGraph(
179
- pathToFileURL(resolvedModule.resolvedFileName).href,
180
- context.parentURL.split('?')[0],
181
- )
182
-
183
- const importerMid = getFileMid(context.parentURL)
184
- const sourceMid = getFileMid(resolvedModule.resolvedFileName)
185
- if (config.resolve && importerMid && sourceMid) {
186
- const resolver = config.resolve.find(
187
- item => item.source === sourceMid && item.importer === importerMid,
188
- )
189
- if (resolver) {
190
- return {
191
- format: 'ts',
192
- url: pathToFileURL(resolvePath(workdir, resolver.path)).href,
193
- shortCircuit: true,
194
- }
195
- }
196
- }
197
-
198
- return {
199
- format: 'ts',
200
- url,
201
- shortCircuit: true,
202
- }
203
- }
204
-
205
- const resolveRet = await nextResolve(specifier)
206
-
207
- // ts resolve fail in some cases
208
- if (resolveRet.url && isAbsolute(resolveRet.url))
209
- resolveRet.url = pathToFileURL(resolveRet.url).href
210
-
211
- return resolveRet
212
- }
213
- // @todo the first params may be url or path, need to distinguish
214
-
215
- export const load = async (url, context, nextLoad) => {
216
- if (config.virtualFile[url]) {
217
- return {
218
- format: 'module',
219
- source: config.virtualFile[url],
220
- shortCircuit: true,
221
- }
222
- }
223
-
224
- url = url.split('?')[0]
225
- if (
226
- !url.includes('/node_modules/')
227
- && url.startsWith('file://')
228
- && !watchFiles.has(url)
229
- && !isLowVersion
230
- ) {
231
- watchFiles.add(url)
232
- // watch(
233
- // fileURLToPath(url),
234
- // debounce((type) => {
235
- // if (type === 'change') {
236
- // try {
237
- // const files = [...findTopScope(url, Date.now())].reverse()
238
-
239
- // port.postMessage(
240
- // JSON.stringify({
241
- // type: 'change',
242
- // files,
243
- // }),
244
- // )
245
- // }
246
- // catch (e) {
247
- // port.postMessage(
248
- // JSON.stringify({
249
- // type: 'relaunch',
250
- // }),
251
- // )
252
- // }
253
- // }
254
- // }),
255
- // )
256
-
257
- if (!process.env.PS_HMR_BAN) {
258
- chokidar.watch(fileURLToPath(url), { persistent: true }).on(
259
- 'change',
260
- debounce(() => {
261
- try {
262
- const files = [...findTopScope(url, Date.now())].reverse()
263
-
264
- port.postMessage(
265
- JSON.stringify({
266
- type: 'change',
267
- files,
268
- }),
269
- )
270
- }
271
- catch (e) {
272
- port.postMessage(
273
- JSON.stringify({
274
- type: 'relaunch',
275
- }),
276
- )
277
- }
278
- }),
279
- )
280
- }
281
- }
282
- // resolveModuleName failed
283
- // I don't know why it failed
284
- if (!context.format && url.endsWith('.ts'))
285
- context.format = 'ts'
286
-
287
- if (context.format === 'ts') {
288
- const { source } = await nextLoad(url, context)
289
-
290
- const code
291
- = typeof source === 'string' ? source : Buffer.from(source).toString()
292
- const compiled = await compile(code, url)
293
- if (unimportRet) {
294
- const { injectImports } = unimportRet
295
- return {
296
- format: 'module',
297
- source: (
298
- await injectImports(
299
- compiled,
300
- slash(url.startsWith('file://') ? fileURLToPath(url) : url),
301
- )
302
- ).code,
303
- shortCircuit: true,
304
- }
305
- }
306
- return {
307
- format: 'module',
308
- source: compiled,
309
- shortCircuit: true,
310
- }
311
- }
312
- else {
313
- return nextLoad(url, context)
314
- }
315
- }
316
-
317
- function findTopScope(url, time, modules = new Set()) {
318
- filesRecord.set(url, time)
319
- if (isModuleFileUrl(url)) {
320
- modules.add(fileURLToPath(url))
321
- }
322
- else {
323
- if (!moduleGraph[url])
324
- throw new Error('root file update')
325
- for (const i of [...moduleGraph[url]]) findTopScope(i, time, modules)
326
- }
327
-
328
- return modules
329
- }
330
-
331
- function debounce(cb, timeout = 500) {
332
- let timer
333
- return (...args) => {
334
- if (timer)
335
- return
336
-
337
- timer = setTimeout(() => {
338
- cb(...args)
339
- timer = undefined
340
- }, timeout)
341
- }
342
- }
343
-
344
- export function isModuleFileUrl(url) {
345
- const midName = getFileMid(url)
346
- if (!midName)
347
- return false
348
- if (
349
- [
350
- 'controller',
351
- 'rpc',
352
- 'service',
353
- 'module',
354
- 'extension',
355
- 'ext',
356
- 'guard',
357
- 'interceptor',
358
- 'plugin',
359
- 'filter',
360
- 'pipe',
361
- 'edge',
362
- ].includes(midName)
363
- )
364
- return true
365
-
366
- return config.moduleFile && config.moduleFile.includes(midName)
367
- }
1
+ import { fileURLToPath, pathToFileURL } from 'url'
2
+ import { writeFile } from 'fs/promises'
3
+ import {
4
+ basename,
5
+ extname,
6
+ isAbsolute,
7
+ relative,
8
+ resolve as resolvePath,
9
+ } from 'path'
10
+ import { createRequire } from 'module'
11
+ import ts from 'typescript'
12
+ import chokidar from 'chokidar'
13
+ import { log } from '../dist/index.mjs'
14
+ import { compile, genUnImportRet, handleClassTypes, slash } from './utils.mjs'
15
+
16
+ let port
17
+
18
+ const isLowVersion = parseFloat(process.version.slice(1)) < 18.19
19
+ // this part is important or not?
20
+ const EXTENSIONS = [ts.Extension.Ts, ts.Extension.Tsx, ts.Extension.Mts]
21
+ const tsconfig = {
22
+ module: ts.ModuleKind.ESNext,
23
+ moduleResolution: ts.ModuleResolutionKind.NodeNext,
24
+ }
25
+ const moduleResolutionCache = ts.createModuleResolutionCache(
26
+ ts.sys.getCurrentDirectory(),
27
+ x => x,
28
+ tsconfig,
29
+ )
30
+ const host = {
31
+ fileExists: ts.sys.fileExists,
32
+ readFile: ts.sys.readFile,
33
+ }
34
+
35
+ let unimportRet
36
+ const dtsPath = 'ps.d.ts'
37
+
38
+ if (isLowVersion)
39
+ await initialize()
40
+
41
+ let config
42
+
43
+ const workdir = process.env.PS_WORKDIR || process.cwd()
44
+
45
+ const configPath = resolvePath(
46
+ workdir,
47
+ process.env.PS_CONFIG_FILE || 'ps.json',
48
+ )
49
+
50
+ const require = createRequire(import.meta.url)
51
+ export async function initialize(data) {
52
+ if (data)
53
+ port = data.port
54
+ log('read config...')
55
+
56
+ config = require(configPath)
57
+ if (!config.virtualFile)
58
+ config.virtualFile = {}
59
+
60
+ if (!process.env.PS_HMR_BAN) {
61
+ chokidar.watch(configPath, { persistent: true }).on('change', () => {
62
+ port.postMessage(
63
+ JSON.stringify({
64
+ type: 'relaunch',
65
+ }),
66
+ )
67
+ })
68
+ }
69
+
70
+ if (!config.unimport)
71
+ return
72
+ unimportRet = await genUnImportRet(config.unimport)
73
+ if (unimportRet) {
74
+ log('auto import...')
75
+ await unimportRet.init()
76
+
77
+ writeFile(
78
+ resolvePath(workdir, config.unimport.dtsPath || dtsPath),
79
+ handleClassTypes(
80
+ await unimportRet.generateTypeDeclarations({
81
+ resolvePath: (i) => {
82
+ if (i.from.startsWith('.') || isAbsolute(i.from)) {
83
+ const related = slash(
84
+ relative(workdir, i.from).replace(/\.ts(x)?$/, ''),
85
+ )
86
+
87
+ return !related.startsWith('.') ? `./${related}` : related
88
+ }
89
+ return i.from
90
+ },
91
+ }),
92
+ ),
93
+ )
94
+ }
95
+ }
96
+
97
+ const watchFiles = new Set()
98
+ const filesRecord = new Map()
99
+ const moduleGraph = {}
100
+
101
+ let entryUrl
102
+
103
+ function addUrlToGraph(url, parent) {
104
+ if (!(url in moduleGraph))
105
+ moduleGraph[url] = new Set()
106
+
107
+ moduleGraph[url].add(parent)
108
+ return url + (filesRecord.has(url) ? `?t=${filesRecord.get(url)}` : '')
109
+ }
110
+
111
+ function getFileMid(file) {
112
+ const filename = basename(file)
113
+ const ret = filename.split('.')
114
+ if (ret.length === 3)
115
+ return ret[1]
116
+ else return ''
117
+ }
118
+
119
+ export const resolve = async (specifier, context, nextResolve) => {
120
+ // virtual file
121
+ if (config.virtualFile[specifier]) {
122
+ return {
123
+ format: 'ts',
124
+ url: specifier,
125
+ shortCircuit: true,
126
+ }
127
+ }
128
+ // entrypoint
129
+ if (!context.parentURL) {
130
+ entryUrl = specifier
131
+ return {
132
+ format: EXTENSIONS.some(ext => specifier.endsWith(ext))
133
+ ? 'ts'
134
+ : undefined,
135
+ url: specifier,
136
+ shortCircuit: true,
137
+ }
138
+ }
139
+ // url import
140
+ // it seems useless
141
+ if (/^file:\/\/\//.test(specifier) && extname(specifier) === '.ts') {
142
+ const url = addUrlToGraph(specifier, context.parentURL.split('?')[0])
143
+ return {
144
+ format: 'ts',
145
+ url,
146
+ shortCircuit: true,
147
+ }
148
+ }
149
+
150
+ // hmr import
151
+ if (
152
+ context.parentURL.includes('/node_modules/phecda-server')
153
+ && isAbsolute(specifier)
154
+ ) {
155
+ specifier = relative(fileURLToPath(entryUrl), specifier)
156
+ .replace(/\.ts$/, '')
157
+ .slice(1)
158
+ context.parentURL = entryUrl
159
+ }
160
+
161
+ // import/require from external library
162
+ if (context.parentURL.includes('/node_modules/'))
163
+ return nextResolve(specifier)
164
+ const { resolvedModule } = ts.resolveModuleName(
165
+ specifier,
166
+ fileURLToPath(context.parentURL),
167
+ tsconfig,
168
+ host,
169
+ moduleResolutionCache,
170
+ )
171
+
172
+ // import between loacl projects
173
+ if (
174
+ resolvedModule
175
+ && !resolvedModule.resolvedFileName.includes('/node_modules/')
176
+ && EXTENSIONS.includes(resolvedModule.extension)
177
+ ) {
178
+ const url = addUrlToGraph(
179
+ pathToFileURL(resolvedModule.resolvedFileName).href,
180
+ context.parentURL.split('?')[0],
181
+ )
182
+
183
+ const importerMid = getFileMid(context.parentURL)
184
+ const sourceMid = getFileMid(resolvedModule.resolvedFileName)
185
+ if (config.resolve && importerMid && sourceMid) {
186
+ const resolver = config.resolve.find(
187
+ item => item.source === sourceMid && item.importer === importerMid,
188
+ )
189
+ if (resolver) {
190
+ return {
191
+ format: 'ts',
192
+ url: pathToFileURL(resolvePath(workdir, resolver.path)).href,
193
+ shortCircuit: true,
194
+ }
195
+ }
196
+ }
197
+
198
+ return {
199
+ format: 'ts',
200
+ url,
201
+ shortCircuit: true,
202
+ }
203
+ }
204
+
205
+ const resolveRet = await nextResolve(specifier)
206
+
207
+ // ts resolve fail in some cases
208
+ if (resolveRet.url && isAbsolute(resolveRet.url))
209
+ resolveRet.url = pathToFileURL(resolveRet.url).href
210
+
211
+ return resolveRet
212
+ }
213
+ // @todo the first params may be url or path, need to distinguish
214
+
215
+ export const load = async (url, context, nextLoad) => {
216
+ if (config.virtualFile[url]) {
217
+ return {
218
+ format: 'module',
219
+ source: config.virtualFile[url],
220
+ shortCircuit: true,
221
+ }
222
+ }
223
+
224
+ url = url.split('?')[0]
225
+ if (
226
+ !url.includes('/node_modules/')
227
+ && url.startsWith('file://')
228
+ && !watchFiles.has(url)
229
+ && !isLowVersion
230
+ ) {
231
+ watchFiles.add(url)
232
+ // watch(
233
+ // fileURLToPath(url),
234
+ // debounce((type) => {
235
+ // if (type === 'change') {
236
+ // try {
237
+ // const files = [...findTopScope(url, Date.now())].reverse()
238
+
239
+ // port.postMessage(
240
+ // JSON.stringify({
241
+ // type: 'change',
242
+ // files,
243
+ // }),
244
+ // )
245
+ // }
246
+ // catch (e) {
247
+ // port.postMessage(
248
+ // JSON.stringify({
249
+ // type: 'relaunch',
250
+ // }),
251
+ // )
252
+ // }
253
+ // }
254
+ // }),
255
+ // )
256
+
257
+ if (!process.env.PS_HMR_BAN) {
258
+ chokidar.watch(fileURLToPath(url), { persistent: true }).on(
259
+ 'change',
260
+ debounce(() => {
261
+ try {
262
+ const files = [...findTopScope(url, Date.now())].reverse()
263
+
264
+ port.postMessage(
265
+ JSON.stringify({
266
+ type: 'change',
267
+ files,
268
+ }),
269
+ )
270
+ }
271
+ catch (e) {
272
+ port.postMessage(
273
+ JSON.stringify({
274
+ type: 'relaunch',
275
+ }),
276
+ )
277
+ }
278
+ }),
279
+ )
280
+ }
281
+ }
282
+ // resolveModuleName failed
283
+ // I don't know why it failed
284
+ if (!context.format && url.endsWith('.ts'))
285
+ context.format = 'ts'
286
+
287
+ if (context.format === 'ts') {
288
+ const { source } = await nextLoad(url, context)
289
+
290
+ const code
291
+ = typeof source === 'string' ? source : Buffer.from(source).toString()
292
+ const compiled = await compile(code, url)
293
+ if (unimportRet) {
294
+ const { injectImports } = unimportRet
295
+ return {
296
+ format: 'module',
297
+ source: (
298
+ await injectImports(
299
+ compiled,
300
+ slash(url.startsWith('file://') ? fileURLToPath(url) : url),
301
+ )
302
+ ).code,
303
+ shortCircuit: true,
304
+ }
305
+ }
306
+ return {
307
+ format: 'module',
308
+ source: compiled,
309
+ shortCircuit: true,
310
+ }
311
+ }
312
+ else {
313
+ return nextLoad(url, context)
314
+ }
315
+ }
316
+
317
+ function findTopScope(url, time, modules = new Set()) {
318
+ filesRecord.set(url, time)
319
+ if (isModuleFileUrl(url)) {
320
+ modules.add(fileURLToPath(url))
321
+ }
322
+ else {
323
+ if (!moduleGraph[url])
324
+ throw new Error('root file update')
325
+ for (const i of [...moduleGraph[url]]) findTopScope(i, time, modules)
326
+ }
327
+
328
+ return modules
329
+ }
330
+
331
+ function debounce(cb, timeout = 500) {
332
+ let timer
333
+ return (...args) => {
334
+ if (timer)
335
+ return
336
+
337
+ timer = setTimeout(() => {
338
+ cb(...args)
339
+ timer = undefined
340
+ }, timeout)
341
+ }
342
+ }
343
+
344
+ export function isModuleFileUrl(url) {
345
+ const midName = getFileMid(url)
346
+ if (!midName)
347
+ return false
348
+ if (
349
+ [
350
+ 'controller',
351
+ 'rpc',
352
+ 'service',
353
+ 'module',
354
+ 'extension',
355
+ 'ext',
356
+ 'guard',
357
+ 'addon',
358
+ 'filter',
359
+ 'pipe',
360
+ 'edge',
361
+ ].includes(midName)
362
+ )
363
+ return true
364
+
365
+ return config.moduleFile && config.moduleFile.includes(midName)
366
+ }