refactor: use create require instead use global require

Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
Innei
2022-09-11 16:10:31 +08:00
parent 748f4e6568
commit 84099f3ee3
9 changed files with 132 additions and 22 deletions

2
.gitignore vendored
View File

@@ -52,3 +52,5 @@ schema.gql
app.config.js app.config.js
webpack-dist webpack-dist
admin/

View File

@@ -0,0 +1,64 @@
import fs, { statSync } from 'fs'
import { resolve } from 'path'
const srcDir = resolve(process.cwd(), 'src')
const aliasMap = {
'~': srcDir,
}
/**
* every ts file relative import statement add `.js` ext
* @param dir
*/
function walkDir(dir: string) {
const files = fs.readdirSync(dir)
files.forEach((file) => {
const filePath = resolve(dir, file)
const stat = fs.statSync(filePath)
if (stat.isDirectory()) {
walkDir(filePath)
} else if (stat.isFile() && filePath.endsWith('.ts')) {
const content = fs.readFileSync(filePath, 'utf-8')
const newContent = content.replace(/from '(.*)'/g, (match, p1) => {
// if is startswith alphabet or @, this is a library path, return it
if (p1.startsWith('@') || /^[a-zA-Z]/.test(p1)) {
return match
}
// if this path is a folder, then add `/index.js` to the end
let path = ''
// if this path is a alias
if (p1.startsWith('~')) {
path = resolve(aliasMap['~'], p1.replace('~/', './'))
} else {
// if path is relative path
path = resolve(dir, p1)
}
console.log(path)
try {
const stat = statSync(path)
if (stat.isDirectory()) {
return `from '${p1}/index.js'`
}
} catch {}
if (p1.startsWith('.') || p1.startsWith('~')) {
return `from '${p1}.js'`
}
return match
})
fs.writeFileSync(filePath, newContent)
}
})
}
function main() {
walkDir(srcDir)
}
main()

View File

@@ -176,7 +176,7 @@
"prettier": "2.7.1", "prettier": "2.7.1",
"rimraf": "3.0.2", "rimraf": "3.0.2",
"socket.io": "*", "socket.io": "*",
"ts-jest": "29.0.0", "ts-jest": "28.0.8",
"ts-node": "10.9.1", "ts-node": "10.9.1",
"tsconfig-paths": "4.1.0", "tsconfig-paths": "4.1.0",
"typescript": "4.7.4" "typescript": "4.7.4"

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:50f786ff188b98559dd5f4c2cafe6b8e71cbbc03ce7743aefe5b297dd667dc16 oid sha256:3b5fda7c46b7a5cbf9b80a3f726d94bce75450e0379bf38e285bf2db9406b06b
size 95577 size 95949

49
pnpm-lock.yaml generated
View File

@@ -116,7 +116,7 @@ specifiers:
slugify: 1.6.5 slugify: 1.6.5
snakecase-keys: 5.4.4 snakecase-keys: 5.4.4
socket.io: '*' socket.io: '*'
ts-jest: 29.0.0 ts-jest: 28.0.8
ts-node: 10.9.1 ts-node: 10.9.1
tsconfig-paths: 4.1.0 tsconfig-paths: 4.1.0
typescript: 4.7.4 typescript: 4.7.4
@@ -243,7 +243,7 @@ devDependencies:
prettier: 2.7.1 prettier: 2.7.1
rimraf: 3.0.2 rimraf: 3.0.2
socket.io: 4.5.1 socket.io: 4.5.1
ts-jest: 29.0.0_3rf23fkdql6lla6jd4mas5qdae ts-jest: 28.0.8_3rf23fkdql6lla6jd4mas5qdae
ts-node: 10.9.1_blrqoobwf2eqte46qefu7nm2oe ts-node: 10.9.1_blrqoobwf2eqte46qefu7nm2oe
tsconfig-paths: 4.1.0 tsconfig-paths: 4.1.0
typescript: 4.7.4 typescript: 4.7.4
@@ -1220,6 +1220,13 @@ packages:
- supports-color - supports-color
dev: true dev: true
/@jest/schemas/28.1.3:
resolution: {integrity: sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==}
engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0}
dependencies:
'@sinclair/typebox': 0.24.28
dev: true
/@jest/schemas/29.0.0: /@jest/schemas/29.0.0:
resolution: {integrity: sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA==} resolution: {integrity: sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -1279,6 +1286,18 @@ packages:
- supports-color - supports-color
dev: true dev: true
/@jest/types/28.1.3:
resolution: {integrity: sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==}
engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0}
dependencies:
'@jest/schemas': 28.1.3
'@types/istanbul-lib-coverage': 2.0.4
'@types/istanbul-reports': 3.0.1
'@types/node': 17.0.31
'@types/yargs': 17.0.11
chalk: 4.1.2
dev: true
/@jest/types/29.0.3: /@jest/types/29.0.3:
resolution: {integrity: sha512-coBJmOQvurXjN1Hh5PzF7cmsod0zLIOXpP8KD161mqNlroMhLcwpODiEzi7ZsRl5Z/AIuxpeNm8DCl43F4kz8A==} resolution: {integrity: sha512-coBJmOQvurXjN1Hh5PzF7cmsod0zLIOXpP8KD161mqNlroMhLcwpODiEzi7ZsRl5Z/AIuxpeNm8DCl43F4kz8A==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -5231,6 +5250,18 @@ packages:
- supports-color - supports-color
dev: true dev: true
/jest-util/28.1.3:
resolution: {integrity: sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==}
engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0}
dependencies:
'@jest/types': 28.1.3
'@types/node': 17.0.31
chalk: 4.1.2
ci-info: 3.3.2
graceful-fs: 4.2.10
picomatch: 2.3.1
dev: true
/jest-util/29.0.3: /jest-util/29.0.3:
resolution: {integrity: sha512-Q0xaG3YRG8QiTC4R6fHjHQPaPpz9pJBEi0AeOE4mQh/FuWOijFjGXMMOfQEaU9i3z76cNR7FobZZUQnL6IyfdQ==} resolution: {integrity: sha512-Q0xaG3YRG8QiTC4R6fHjHQPaPpz9pJBEi0AeOE4mQh/FuWOijFjGXMMOfQEaU9i3z76cNR7FobZZUQnL6IyfdQ==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -7339,16 +7370,16 @@ packages:
hasBin: true hasBin: true
dev: true dev: true
/ts-jest/29.0.0_3rf23fkdql6lla6jd4mas5qdae: /ts-jest/28.0.8_3rf23fkdql6lla6jd4mas5qdae:
resolution: {integrity: sha512-OxUaigbv5Aon3OMLY9HBtwkGMs1upWE/URrmmVQFzzOcGlEPVuWzGmXUIkWGt/95Dj/T6MGuTrHHGL6kT6Yn8g==} resolution: {integrity: sha512-5FaG0lXmRPzApix8oFG8RKjAz4ehtm8yMKOTy5HX3fY6W8kmvOrmcY0hKDElW52FJov+clhUbrKAqofnj4mXTg==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0}
hasBin: true hasBin: true
peerDependencies: peerDependencies:
'@babel/core': '>=7.0.0-beta.0 <8' '@babel/core': '>=7.0.0-beta.0 <8'
'@jest/types': ^29.0.0 '@jest/types': ^28.0.0
babel-jest: ^29.0.0 babel-jest: ^28.0.0
esbuild: '*' esbuild: '*'
jest: ^29.0.0 jest: ^28.0.0
typescript: '>=4.3' typescript: '>=4.3'
peerDependenciesMeta: peerDependenciesMeta:
'@babel/core': '@babel/core':
@@ -7364,7 +7395,7 @@ packages:
bs-logger: 0.2.6 bs-logger: 0.2.6
fast-json-stable-stringify: 2.1.0 fast-json-stable-stringify: 2.1.0
jest: 29.0.3_hmlqgonttxlk2sdyntkgpf244q jest: 29.0.3_hmlqgonttxlk2sdyntkgpf244q
jest-util: 29.0.3 jest-util: 28.1.3
json5: 2.2.1 json5: 2.2.1
lodash.memoize: 4.1.2 lodash.memoize: 4.1.2
make-error: 1.3.6 make-error: 1.3.6

View File

@@ -1,11 +1,14 @@
import { isURL } from 'class-validator' import { isURL } from 'class-validator'
import fs, { mkdir, stat } from 'fs/promises' import fs, { mkdir, stat } from 'fs/promises'
import LRUCache from 'lru-cache' import LRUCache from 'lru-cache'
import { createRequire } from 'module'
import { mongo } from 'mongoose' import { mongo } from 'mongoose'
import path from 'path' import path, { resolve } from 'path'
import { nextTick } from 'process' import { nextTick } from 'process'
import { TransformOptions, parseAsync, transformAsync } from '@babel/core' import { TransformOptions, parseAsync, transformAsync } from '@babel/core'
import BabelPluginTransformCommonJS from '@babel/plugin-transform-modules-commonjs'
import BabelPluginTransformTS from '@babel/plugin-transform-typescript'
import * as t from '@babel/types' import * as t from '@babel/types'
import { VariableDeclaration } from '@babel/types' import { VariableDeclaration } from '@babel/types'
import { import {
@@ -232,6 +235,8 @@ export class ServerlessService {
const { raw: functionString } = model const { raw: functionString } = model
const logger = new Logger(`fx:${model.reference}/${model.name}`) const logger = new Logger(`fx:${model.reference}/${model.name}`)
const document = await this.model.findById(model.id) const document = await this.model.findById(model.id)
// eslint-disable-next-line @typescript-eslint/no-this-alias
const self = this
const globalContext = { const globalContext = {
context: { context: {
// inject app req, res // inject app req, res
@@ -293,7 +298,7 @@ export class ServerlessService {
require: this.inNewContextRequire(), require: this.inNewContextRequire(),
get import() { get import() {
return this.require return self.require
}, },
process: { process: {
@@ -333,9 +338,9 @@ export class ServerlessService {
return { return {
comments: false, comments: false,
plugins: [ plugins: [
require('@babel/plugin-transform-typescript'), BabelPluginTransformTS,
[ [
require('@babel/plugin-transform-modules-commonjs'), BabelPluginTransformCommonJS,
{ allowTopLevelThis: false, importInterop: 'node' }, { allowTopLevelThis: false, importInterop: 'node' },
], ],
function transformImport() { function transformImport() {
@@ -411,25 +416,33 @@ export class ServerlessService {
private resolvePath(id: string) { private resolvePath(id: string) {
try { try {
return require.resolve(id) return this.require.resolve(id)
} catch { } catch {
try { try {
const modulePath = path.resolve(NODE_REQUIRE_PATH, id) const modulePath = path.resolve(NODE_REQUIRE_PATH, id)
const resolvePath = require.resolve(modulePath) const resolvePath = this.require.resolve(modulePath)
return resolvePath return resolvePath
} catch { } catch (err) {
delete this.require.cache[id]
isDev && console.error(err)
throw new InternalServerErrorException(`module "${id}" not found.`) throw new InternalServerErrorException(`module "${id}" not found.`)
} }
} }
} }
private require = isTest
? createRequire(resolve(process.cwd(), './node_modules'))
: createRequire(NODE_REQUIRE_PATH)
private inNewContextRequire() { private inNewContextRequire() {
const __require = (id: string) => { const __require = (id: string) => {
const isBuiltin = isBuiltinModule(id) const isBuiltin = isBuiltinModule(id)
const resolvePath = this.resolvePath(id) const resolvePath = this.resolvePath(id)
const module = require(resolvePath) const module = this.require(resolvePath)
// TODO remove cache in-used package dependencies, because it will not exist in prod // TODO remove cache in-used package dependencies, because it will not exist in prod
// eslint-disable-next-line no-empty // eslint-disable-next-line no-empty
if (Object.keys(PKG.dependencies).includes(id) || isBuiltin) { if (Object.keys(PKG.dependencies).includes(id) || isBuiltin) {
@@ -441,7 +454,7 @@ export class ServerlessService {
} }
const __requireNoCache = (id: string) => { const __requireNoCache = (id: string) => {
delete require.cache[this.resolvePath(id)] delete this.require.cache[this.resolvePath(id)]
const clonedModule = __require(id) const clonedModule = __require(id)
return clonedModule return clonedModule

View File

@@ -139,7 +139,7 @@ describe('test /snippets', () => {
const json = res.json() const json = res.json()
expect(res.statusCode).toBe(200) expect(res.statusCode).toBe(200)
expect(json).toStrictEqual(JSON.parse(mockPayload1.raw)) expect(json).toStrictEqual(JSON.parse(mockPayload1.raw || '{}'))
}) })
}) })