phecda-server 8.0.2 → 8.1.0
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.
- package/bin/cli.mjs +18 -3
- package/package.json +1 -1
- package/register/export.mjs +7 -7
- package/register/index.mjs +27 -0
- package/register/loader.mjs +65 -65
- package/register/utils.mjs +12 -8
package/bin/cli.mjs
CHANGED
|
@@ -191,8 +191,10 @@ cli
|
|
|
191
191
|
console.log(`${pc.green('->')} press ${pc.green('e')} to exit`)
|
|
192
192
|
console.log(`${pc.green('->')} press ${pc.green('r')} to relaunch`)
|
|
193
193
|
console.log(`${pc.green('->')} press ${pc.green('c')} to clear terminal`)
|
|
194
|
+
console.log(`${pc.green('->')} press ${pc.green('i')} to debug`)
|
|
194
195
|
|
|
195
196
|
process.stdin.on('data', async (data) => {
|
|
197
|
+
const args = [...nodeArgs]
|
|
196
198
|
const input = data.toString().trim().toLocaleLowerCase()
|
|
197
199
|
if (input === 'r') {
|
|
198
200
|
if (child) {
|
|
@@ -200,12 +202,11 @@ cli
|
|
|
200
202
|
if (closePromise)
|
|
201
203
|
await closePromise
|
|
202
204
|
log('relaunch...')
|
|
203
|
-
startChild(file,
|
|
205
|
+
startChild(file, args)
|
|
204
206
|
}
|
|
205
207
|
else {
|
|
206
208
|
log('relaunch...')
|
|
207
|
-
|
|
208
|
-
startChild(file, nodeArgs)
|
|
209
|
+
startChild(file, args)
|
|
209
210
|
}
|
|
210
211
|
}
|
|
211
212
|
if (input === 'e')
|
|
@@ -213,6 +214,20 @@ cli
|
|
|
213
214
|
|
|
214
215
|
if (input === 'c')
|
|
215
216
|
console.clear()
|
|
217
|
+
|
|
218
|
+
if (input === 'i' || input.startsWith('i ')) {
|
|
219
|
+
const [, arg] = input.split(' ')
|
|
220
|
+
|
|
221
|
+
if (child) {
|
|
222
|
+
child.send({
|
|
223
|
+
type: 'inspect',
|
|
224
|
+
arg
|
|
225
|
+
})
|
|
226
|
+
} else {
|
|
227
|
+
args.push(`--inspect${arg ? `=${arg}` : ''}`)
|
|
228
|
+
startChild(file, args)
|
|
229
|
+
}
|
|
230
|
+
}
|
|
216
231
|
})
|
|
217
232
|
})
|
|
218
233
|
|
package/package.json
CHANGED
package/register/export.mjs
CHANGED
|
@@ -20,20 +20,20 @@ export default ['Addon', 'Arg', 'Assign', 'BadGatewayException', 'BadRequestExce
|
|
|
20
20
|
'Watcher', 'WorkerException',
|
|
21
21
|
'addAddon', 'addDecoToClass',
|
|
22
22
|
'addFilter', 'addGuard', 'addPipe', 'emitter',
|
|
23
|
-
'getMergedMeta','getMeta', 'getMetaKey', 'getMetaParams', 'getOwnMeta', 'getOwnMetaKey', 'getOwnMetaParams',
|
|
23
|
+
'getMergedMeta', 'getMeta', 'getMetaKey', 'getMetaParams', 'getOwnMeta', 'getOwnMetaKey', 'getOwnMetaParams',
|
|
24
24
|
'getTag',
|
|
25
25
|
'isPhecda', 'log', 'phecdaNamespace', 'runMiddleware',
|
|
26
26
|
'setInject',
|
|
27
27
|
'setLogger',
|
|
28
28
|
'setMeta',
|
|
29
29
|
'useS', 'wait', 'OneFile', 'ManyFiles',
|
|
30
|
-
'Rule','Required','Optional',
|
|
30
|
+
'Rule', 'Required', 'Optional',
|
|
31
31
|
'validate',
|
|
32
|
-
'Min','Max','Enum','OneOf','Nested',
|
|
33
|
-
|
|
34
|
-
'Doc','DocGenerator',
|
|
35
|
-
'pick','omit','partial',
|
|
36
|
-
'functionToClass','objectToClass'
|
|
32
|
+
'Min', 'Max', 'Enum', 'OneOf', 'Nested',
|
|
33
|
+
'Const',
|
|
34
|
+
'Doc', 'DocGenerator',
|
|
35
|
+
'pick', 'omit', 'partial',
|
|
36
|
+
'functionToClass', 'objectToClass'
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
]
|
package/register/index.mjs
CHANGED
|
@@ -2,6 +2,7 @@ import { register } from 'node:module'
|
|
|
2
2
|
import { MessageChannel } from 'node:worker_threads'
|
|
3
3
|
import { isPhecda, log } from '../dist/index.mjs'
|
|
4
4
|
import { RELAUNCH, RELOAD } from '../dist/helper.mjs'
|
|
5
|
+
import inspector from 'inspector'
|
|
5
6
|
const { port1, port2 } = new MessageChannel()
|
|
6
7
|
|
|
7
8
|
register('./loader.mjs', {
|
|
@@ -47,3 +48,29 @@ process.on('unhandledRejection', (err) => {
|
|
|
47
48
|
|
|
48
49
|
console.error(err)
|
|
49
50
|
})
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
process.on('message', (data) => {
|
|
54
|
+
if (data.type === 'inspect') {
|
|
55
|
+
if (inspector.url()) {
|
|
56
|
+
inspector.close();
|
|
57
|
+
log('close inspector', 'info');
|
|
58
|
+
} else {
|
|
59
|
+
const { arg } = data
|
|
60
|
+
|
|
61
|
+
if (arg) {
|
|
62
|
+
if (arg.includes(':')) {
|
|
63
|
+
const [host, port] = arg.split(':')
|
|
64
|
+
inspector.open(Number(port), host)
|
|
65
|
+
} else {
|
|
66
|
+
inspector.open(Number(arg))
|
|
67
|
+
}
|
|
68
|
+
}else {
|
|
69
|
+
inspector.open();
|
|
70
|
+
}
|
|
71
|
+
// address already in use
|
|
72
|
+
if (inspector.url())
|
|
73
|
+
log(`open "devtools://devtools/bundled/js_app.html?experiments=true&v8only=true&ws=${inspector.url().replace("ws://", '')}" in browser`, 'info');
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
})
|
package/register/loader.mjs
CHANGED
|
@@ -35,7 +35,7 @@ const dtsPath = process.env.PS_DTS_PATH || 'ps.d.ts'
|
|
|
35
35
|
const watchFiles = new Set()
|
|
36
36
|
const filesRecord = new Map()
|
|
37
37
|
const moduleGraph = {}
|
|
38
|
-
|
|
38
|
+
// ts
|
|
39
39
|
let tsconfig = {
|
|
40
40
|
module: ts.ModuleKind.ESNext,
|
|
41
41
|
moduleResolution: ts.ModuleResolutionKind.NodeNext,
|
|
@@ -81,7 +81,7 @@ export async function initialize(data) {
|
|
|
81
81
|
|
|
82
82
|
if (loaderPath) {
|
|
83
83
|
const loader = await
|
|
84
|
-
|
|
84
|
+
import(loaderPath.startsWith('.') ? resolvePath(workdir, loaderPath) : loaderPath)
|
|
85
85
|
|
|
86
86
|
if (typeof loader.load === 'function')
|
|
87
87
|
customLoad = loader.load
|
|
@@ -147,80 +147,80 @@ function getFileMid(file) {
|
|
|
147
147
|
return ret[1]
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
export const resolve = async(specifier, context, nextResolve) => {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}
|
|
150
|
+
export const resolve = async (specifier, context, nextResolve) => {
|
|
151
|
+
if (customResolve) {
|
|
152
|
+
const url = await customResolve(specifier, context)
|
|
153
|
+
if (url) {
|
|
154
|
+
return {
|
|
155
|
+
format: 'ts',
|
|
156
|
+
url,
|
|
157
|
+
shortCircuit: true,
|
|
159
158
|
}
|
|
160
159
|
}
|
|
160
|
+
}
|
|
161
161
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
162
|
+
// entrypoint
|
|
163
|
+
if (!context.parentURL)
|
|
164
|
+
return nextResolve(specifier)
|
|
165
165
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
166
|
+
// @todo skip resolve to improve performance
|
|
167
|
+
// if (context.parentURL.includes('/node_modules/') && specifier.includes('/node_modules/'))
|
|
168
|
+
// return nextResolve(specifier)
|
|
169
169
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
170
|
+
const { resolvedModule } = ts.resolveModuleName(
|
|
171
|
+
specifier,
|
|
172
|
+
fileURLToPath(context.parentURL),
|
|
173
|
+
tsconfig,
|
|
174
|
+
host,
|
|
175
|
+
moduleResolutionCache,
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
// import among files in local project
|
|
179
|
+
if (
|
|
180
|
+
resolvedModule &&
|
|
181
|
+
!resolvedModule.resolvedFileName.includes('/node_modules/') &&
|
|
182
|
+
EXTENSIONS.includes(resolvedModule.extension)
|
|
183
|
+
) {
|
|
184
|
+
const url = addUrlToGraph(
|
|
185
|
+
pathToFileURL(resolvedModule.resolvedFileName).href,
|
|
186
|
+
context.parentURL.split('?')[0],
|
|
176
187
|
)
|
|
177
188
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
) {
|
|
184
|
-
const url = addUrlToGraph(
|
|
185
|
-
pathToFileURL(resolvedModule.resolvedFileName).href,
|
|
186
|
-
context.parentURL.split('?')[0],
|
|
189
|
+
const importerMid = getFileMid(context.parentURL)
|
|
190
|
+
const sourceMid = getFileMid(resolvedModule.resolvedFileName)
|
|
191
|
+
if (config.resolve && importerMid && sourceMid) {
|
|
192
|
+
const resolver = config.resolve.find(
|
|
193
|
+
item => item.source === sourceMid && item.importer === importerMid,
|
|
187
194
|
)
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
item => item.source === sourceMid && item.importer === importerMid,
|
|
194
|
-
)
|
|
195
|
-
if (resolver) {
|
|
196
|
-
return {
|
|
197
|
-
format: 'ts',
|
|
198
|
-
url: pathToFileURL(resolvePath(workdir, resolver.path)).href,
|
|
199
|
-
shortCircuit: true,
|
|
200
|
-
}
|
|
195
|
+
if (resolver) {
|
|
196
|
+
return {
|
|
197
|
+
format: 'ts',
|
|
198
|
+
url: pathToFileURL(resolvePath(workdir, resolver.path)).href,
|
|
199
|
+
shortCircuit: true,
|
|
201
200
|
}
|
|
202
201
|
}
|
|
203
|
-
|
|
204
|
-
return {
|
|
205
|
-
format: 'ts',
|
|
206
|
-
url,
|
|
207
|
-
shortCircuit: true,
|
|
208
|
-
}
|
|
209
202
|
}
|
|
210
203
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
const [path, query] = resolveRet.url.split('?')
|
|
216
|
-
resolveRet.url = pathToFileURL(path).href + (query ? `?${query}` : '')
|
|
204
|
+
return {
|
|
205
|
+
format: 'ts',
|
|
206
|
+
url,
|
|
207
|
+
shortCircuit: true,
|
|
217
208
|
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const resolveRet = await nextResolve(specifier)
|
|
218
212
|
|
|
219
|
-
|
|
213
|
+
// ts resolve fail in some cases
|
|
214
|
+
if (resolveRet.url && isAbsolute(resolveRet.url)) {
|
|
215
|
+
const [path, query] = resolveRet.url.split('?')
|
|
216
|
+
resolveRet.url = pathToFileURL(path).href + (query ? `?${query}` : '')
|
|
220
217
|
}
|
|
221
|
-
// @todo the first params may be url or path, need to distinguish
|
|
222
218
|
|
|
223
|
-
|
|
219
|
+
return resolveRet
|
|
220
|
+
}
|
|
221
|
+
// @todo the first params may be url or path, need to distinguish
|
|
222
|
+
|
|
223
|
+
export const load = async (url, context, nextLoad) => {
|
|
224
224
|
let mode
|
|
225
225
|
if (context.importAttributes.ps) {
|
|
226
226
|
mode = context.importAttributes.ps
|
|
@@ -281,13 +281,13 @@ export const load = async(url, context, nextLoad) => {
|
|
|
281
281
|
}
|
|
282
282
|
}
|
|
283
283
|
|
|
284
|
-
|
|
284
|
+
|
|
285
285
|
// resolveModuleName failed
|
|
286
286
|
// I don't know why it failed
|
|
287
|
-
if (
|
|
287
|
+
if (url.endsWith('.ts'))
|
|
288
288
|
context.format = 'ts'
|
|
289
289
|
|
|
290
|
-
|
|
290
|
+
// module-typescript???
|
|
291
291
|
|
|
292
292
|
if (context.format === 'ts') {
|
|
293
293
|
const { source } = await nextLoad(url, context)
|
|
@@ -298,7 +298,7 @@ export const load = async(url, context, nextLoad) => {
|
|
|
298
298
|
|
|
299
299
|
if (unimportRet) {
|
|
300
300
|
const { injectImports } = unimportRet
|
|
301
|
-
|
|
301
|
+
|
|
302
302
|
return {
|
|
303
303
|
format: 'module',
|
|
304
304
|
source: (
|
|
@@ -327,7 +327,7 @@ function findTopScope(url, time, modules = new Set()) {
|
|
|
327
327
|
} else {
|
|
328
328
|
if (!moduleGraph[url])
|
|
329
329
|
throw new Error('root file update')
|
|
330
|
-
for (const i of[...moduleGraph[url]]) findTopScope(i, time, modules)
|
|
330
|
+
for (const i of [...moduleGraph[url]]) findTopScope(i, time, modules)
|
|
331
331
|
}
|
|
332
332
|
|
|
333
333
|
return modules
|
package/register/utils.mjs
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { basename } from 'path'
|
|
2
2
|
import { transform } from '@swc-node/core'
|
|
3
3
|
import psExports from './export.mjs'
|
|
4
|
+
import { fileURLToPath } from 'node:url'
|
|
5
|
+
import path from 'node:path'
|
|
6
|
+
|
|
4
7
|
const injectInlineSourceMap = ({ code, map }) => {
|
|
5
8
|
if (map) {
|
|
6
9
|
const base64Map = Buffer.from(map, 'utf8').toString('base64')
|
|
@@ -10,33 +13,34 @@ const injectInlineSourceMap = ({ code, map }) => {
|
|
|
10
13
|
return code
|
|
11
14
|
}
|
|
12
15
|
|
|
13
|
-
export async function compile(sourcecode,
|
|
14
|
-
if (
|
|
16
|
+
export async function compile(sourcecode, url, config = {}) {
|
|
17
|
+
if (url.endsWith('.d.ts'))
|
|
15
18
|
return ''
|
|
16
19
|
|
|
20
|
+
const filename = path.basename(url.startsWith('file:') ? fileURLToPath(url) : url)
|
|
21
|
+
|
|
17
22
|
const { code, map } = await transform(sourcecode, filename, {
|
|
18
|
-
sourcemap: true,
|
|
19
23
|
module: 'es6',
|
|
20
24
|
emitDecoratorMetadata: true,
|
|
21
25
|
experimentalDecorators: true,
|
|
22
26
|
esModuleInterop: false,
|
|
27
|
+
sourcemap:false,
|
|
23
28
|
...config
|
|
24
29
|
})
|
|
25
|
-
|
|
26
30
|
return injectInlineSourceMap({ code, map })
|
|
27
31
|
}
|
|
28
32
|
|
|
29
33
|
export async function genUnImportRet(opts) {
|
|
30
34
|
try {
|
|
31
35
|
const { createUnimport } = await
|
|
32
|
-
|
|
36
|
+
import('unimport')
|
|
33
37
|
return createUnimport({
|
|
34
38
|
...opts,
|
|
35
39
|
|
|
36
40
|
presets: [{
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
41
|
+
from: 'phecda-server',
|
|
42
|
+
imports: psExports,
|
|
43
|
+
},]
|
|
40
44
|
.concat(opts.presets || []),
|
|
41
45
|
})
|
|
42
46
|
} catch (e) {
|