feat: 초기 프로젝트 설정 및 룰.md 파일 추가

This commit is contained in:
2025-07-28 09:53:31 +09:00
commit 09a4d38512
8165 changed files with 1021855 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2016-2019 Thomas Watson Steen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,79 @@
# require-in-the-middle
Hook into the Node.js `require` function. This allows you to modify
modules on-the-fly as they are being required.
[![npm](https://img.shields.io/npm/v/require-in-the-middle.svg)](https://www.npmjs.com/package/require-in-the-middle)
[![Test status](https://github.com/elastic/require-in-the-middle/workflows/Test/badge.svg)](https://github.com/elastic/require-in-the-middle/actions)
## Installation
```
npm install require-in-the-middle --save
```
## Usage
```js
const path = require('path')
const Hook = require('require-in-the-middle')
// Hook into the express and mongodb module
Hook(['express', 'mongodb'], function (exports, name, basedir) {
const version = require(path.join(basedir, 'package.json')).version
console.log('loading %s@%s', name, version)
// expose the module version as a property on its exports object
exports._version = version
// whatever you return will be returned by `require`
return exports
})
```
## API
The require-in-the-middle module exposes a single function:
### `hook = Hook([modules][, options], onrequire)`
When called a `hook` object is returned.
Arguments:
- `modules` <string[]> An optional array of module names to limit which modules
trigger a call of the `onrequire` callback. If specified, this must be the
first argument. Both regular modules (e.g. `react-dom`) and
sub-modules (e.g. `react-dom/server`) can be specified in the array.
- `options` <Object> An optional object containing fields that change when the
`onrequire` callback is called. If specified, this must be the second
argument.
- `options.internals` <boolean> Specifies whether `onrequire` should be called
when module-internal files are loaded; defaults to `false`.
- `onrequire` <Function> The function to call when a module is required.
The `onrequire` callback will be called the first time a module is
required. The function is called with three arguments:
- `exports` <Object> The value of the `module.exports` property that would
normally be exposed by the required module.
- `name` <string> The name of the module being required. If `options.internals`
was set to `true`, the path of module-internal files that are loaded
(relative to `basedir`) will be appended to the module name, separated by
`path.sep`.
- `basedir` <string> The directory where the module is located, or `undefined`
for core modules.
Return the value you want the module to expose (normally the `exports`
argument).
### `hook.unhook()`
Removes the `onrequire` callback so that it will not be triggerd by
subsequent calls to `require()`.
## License
[MIT](https://github.com/elastic/require-in-the-middle/blob/master/LICENSE)

View File

@@ -0,0 +1,196 @@
'use strict'
const path = require('path')
const Module = require('module')
const resolve = require('resolve')
const debug = require('debug')('require-in-the-middle')
const parse = require('module-details-from-path')
module.exports = Hook
/**
* Is the given module a "core" module?
* https://nodejs.org/api/modules.html#core-modules
*
* @type {(moduleName: string) => boolean}
*/
let isCore
if (Module.isBuiltin) { // as of node v18.6.0
isCore = Module.isBuiltin
} else {
isCore = moduleName => {
// Prefer `resolve.core` lookup to `resolve.isCore(moduleName)` because the
// latter is doing version range matches for every call.
return !!resolve.core[moduleName]
}
}
// 'foo/bar.js' or 'foo/bar/index.js' => 'foo/bar'
const normalize = /([/\\]index)?(\.js)?$/
function Hook (modules, options, onrequire) {
if ((this instanceof Hook) === false) return new Hook(modules, options, onrequire)
if (typeof modules === 'function') {
onrequire = modules
modules = null
options = null
} else if (typeof options === 'function') {
onrequire = options
options = null
}
if (typeof Module._resolveFilename !== 'function') {
console.error('Error: Expected Module._resolveFilename to be a function (was: %s) - aborting!', typeof Module._resolveFilename)
console.error('Please report this error as an issue related to Node.js %s at %s', process.version, require('./package.json').bugs.url)
return
}
this.cache = new Map()
this._unhooked = false
this._origRequire = Module.prototype.require
const self = this
const patching = new Set()
const internals = options ? options.internals === true : false
const hasWhitelist = Array.isArray(modules)
debug('registering require hook')
this._require = Module.prototype.require = function (id) {
if (self._unhooked === true) {
// if the patched require function could not be removed because
// someone else patched it after it was patched here, we just
// abort and pass the request onwards to the original require
debug('ignoring require call - module is soft-unhooked')
return self._origRequire.apply(this, arguments)
}
const core = isCore(id)
let filename // the string used for caching
if (core) {
filename = id
// If this is a builtin module that can be identified both as 'foo' and
// 'node:foo', then prefer 'foo' as the caching key.
if (id.startsWith('node:')) {
const idWithoutPrefix = id.slice(5)
if (isCore(idWithoutPrefix)) {
filename = idWithoutPrefix
}
}
} else {
filename = Module._resolveFilename(id, this)
}
let moduleName, basedir
debug('processing %s module require(\'%s\'): %s', core === true ? 'core' : 'non-core', id, filename)
// return known patched modules immediately
if (self.cache.has(filename) === true) {
debug('returning already patched cached module: %s', filename)
return self.cache.get(filename)
}
// Check if this module has a patcher in-progress already.
// Otherwise, mark this module as patching in-progress.
const isPatching = patching.has(filename)
if (isPatching === false) {
patching.add(filename)
}
const exports = self._origRequire.apply(this, arguments)
// If it's already patched, just return it as-is.
if (isPatching === true) {
debug('module is in the process of being patched already - ignoring: %s', filename)
return exports
}
// The module has already been loaded,
// so the patching mark can be cleaned up.
patching.delete(filename)
if (core === true) {
if (hasWhitelist === true && modules.includes(filename) === false) {
debug('ignoring core module not on whitelist: %s', filename)
return exports // abort if module name isn't on whitelist
}
moduleName = filename
} else if (hasWhitelist === true && modules.includes(filename)) {
// whitelist includes the absolute path to the file including extension
const parsedPath = path.parse(filename)
moduleName = parsedPath.name
basedir = parsedPath.dir
} else {
const stat = parse(filename)
if (stat === undefined) {
debug('could not parse filename: %s', filename)
return exports // abort if filename could not be parsed
}
moduleName = stat.name
basedir = stat.basedir
const fullModuleName = resolveModuleName(stat)
debug('resolved filename to module: %s (id: %s, resolved: %s, basedir: %s)', moduleName, id, fullModuleName, basedir)
// Ex: require('foo/lib/../bar.js')
// moduleName = 'foo'
// fullModuleName = 'foo/bar'
if (hasWhitelist === true && modules.includes(moduleName) === false) {
if (modules.includes(fullModuleName) === false) return exports // abort if module name isn't on whitelist
// if we get to this point, it means that we're requiring a whitelisted sub-module
moduleName = fullModuleName
} else {
// figure out if this is the main module file, or a file inside the module
let res
try {
res = resolve.sync(moduleName, { basedir })
} catch (e) {
debug('could not resolve module: %s', moduleName)
return exports // abort if module could not be resolved (e.g. no main in package.json and no index.js file)
}
if (res !== filename) {
// this is a module-internal file
if (internals === true) {
// use the module-relative path to the file, prefixed by original module name
moduleName = moduleName + path.sep + path.relative(basedir, filename)
debug('preparing to process require of internal file: %s', moduleName)
} else {
debug('ignoring require of non-main module file: %s', res)
return exports // abort if not main module file
}
}
}
}
// only call onrequire the first time a module is loaded
if (self.cache.has(filename) === false) {
// ensure that the cache entry is assigned a value before calling
// onrequire, in case calling onrequire requires the same module.
self.cache.set(filename, exports)
debug('calling require hook: %s', moduleName)
self.cache.set(filename, onrequire(exports, moduleName, basedir))
}
debug('returning module: %s', moduleName)
return self.cache.get(filename)
}
}
Hook.prototype.unhook = function () {
this._unhooked = true
if (this._require === Module.prototype.require) {
Module.prototype.require = this._origRequire
debug('unhook successful')
} else {
debug('unhook unsuccessful')
}
}
function resolveModuleName (stat) {
const normalizedPath = path.sep !== '/' ? stat.path.split(path.sep).join('/') : stat.path
return path.posix.join(stat.name, normalizedPath).replace(normalize, '')
}

View File

@@ -0,0 +1,55 @@
{
"name": "require-in-the-middle",
"version": "5.2.0",
"description": "Module to hook into the Node.js require function",
"main": "index.js",
"dependencies": {
"debug": "^4.1.1",
"module-details-from-path": "^1.0.3",
"resolve": "^1.22.1"
},
"devDependencies": {
"@babel/core": "^7.9.0",
"@babel/preset-env": "^7.9.5",
"@babel/preset-typescript": "^7.9.0",
"@babel/register": "^7.9.0",
"ipp-printer": "^1.0.0",
"patterns": "^1.0.3",
"roundround": "^0.2.0",
"semver": "^6.3.0",
"standard": "^14.3.1",
"tape": "^4.11.0"
},
"scripts": {
"test": "npm run test:lint && npm run test:tape && npm run test:babel",
"test:lint": "standard",
"test:tape": "tape test/*.js",
"test:babel": "node test/babel/babel-register.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/elastic/require-in-the-middle.git"
},
"keywords": [
"require",
"hook",
"shim",
"shimmer",
"shimming",
"patch",
"monkey",
"monkeypatch",
"module",
"load"
],
"files": [],
"author": "Thomas Watson Steen <w@tson.dk> (https://twitter.com/wa7son)",
"license": "MIT",
"bugs": {
"url": "https://github.com/elastic/require-in-the-middle/issues"
},
"homepage": "https://github.com/elastic/require-in-the-middle#readme",
"engines": {
"node": ">=6"
}
}