Comparing version 0.18.2 to 0.19.0
@@ -0,1 +1,9 @@ | ||
## 0.19.0 | ||
- Updated dependencies | ||
- Content server now supports ETags | ||
- Now supports `import.meta.hot` | ||
- Performance improvements | ||
- Add new option `externalHost` | ||
- Added [`TypeScriptPlugin`](/packages/plugin-typescript/README.md) | ||
## 0.18.2 | ||
@@ -2,0 +10,0 @@ - Fixed issue with CommonJS interop mode 1 |
@@ -12,3 +12,3 @@ "use strict"; | ||
const utils_1 = require("./utils"); | ||
exports.initCache = (config, plugins, log) => { | ||
const initCache = (config, plugins, log) => { | ||
let unsavedCacheInfos = {}; | ||
@@ -229,1 +229,2 @@ const noop = () => { }; | ||
}; | ||
exports.initCache = initCache; |
@@ -169,2 +169,3 @@ "use strict"; | ||
const initScriptHTML = `<script src="${initScriptPath}"></script>`; | ||
const etagKey = utils_1.uniqueID(10) + '-'; | ||
app.use(async (ctx, next) => { | ||
@@ -195,2 +196,14 @@ if (ctx.path === initScriptPath) { | ||
} | ||
if (contentServer.etag) { | ||
const etag = etagKey + Math.floor(fs_1.default.statSync(sentFilePath).mtimeMs); | ||
if (ctx.get('If-None-Match') === etag) { | ||
ctx.status = 304; | ||
ctx.body = undefined; | ||
ctx.remove('Content-Length'); | ||
return next(); | ||
} | ||
else { | ||
ctx.set('ETag', etag); | ||
} | ||
} | ||
if (/^\.html?$/.test(path_1.default.extname(sentFilePath))) { | ||
@@ -226,3 +239,3 @@ const htmlSource = await new Promise((res) => { | ||
}; | ||
exports.createContentServer = (instance) => { | ||
const createContentServer = (instance) => { | ||
const contentServer = new koa_1.default(); | ||
@@ -246,1 +259,2 @@ const config = instance.config; | ||
}; | ||
exports.createContentServer = createContentServer; |
@@ -7,3 +7,3 @@ "use strict"; | ||
const utils_1 = require("../../utils"); | ||
exports.CommonJSMode1Plugin = () => ({ | ||
const CommonJSMode1Plugin = () => ({ | ||
name: 'core-commonjs-mode-1-plugin', | ||
@@ -15,1 +15,2 @@ getCacheKey: () => 1, | ||
}); | ||
exports.CommonJSMode1Plugin = CommonJSMode1Plugin; |
@@ -9,3 +9,3 @@ "use strict"; | ||
const getReboostResolveCall = (source) => t.callExpression(t.identifier('__reboost_resolve'), [t.stringLiteral(source)]); | ||
exports.transformCommonJS = (ast, filePath, id) => { | ||
const transformCommonJS = (ast, filePath, id) => { | ||
let program; | ||
@@ -127,1 +127,2 @@ let usedModuleExports; | ||
}; | ||
exports.transformCommonJS = transformCommonJS; |
@@ -18,3 +18,3 @@ "use strict"; | ||
const export__cjsModuleTrue = () => t.exportNamedDeclaration(t.variableDeclaration('const', [t.variableDeclarator(t.identifier('__cjsModule'), t.booleanLiteral(true))])); | ||
exports.transformCommonJSToES6 = (ast, id) => { | ||
const transformCommonJSToES6 = (ast, id) => { | ||
// Most of variables are initialized lazily | ||
@@ -225,1 +225,2 @@ let importIdx = 0; | ||
}; | ||
exports.transformCommonJSToES6 = transformCommonJSToES6; |
@@ -9,3 +9,3 @@ "use strict"; | ||
const utils_1 = require("../../utils"); | ||
exports.CommonJSMode2Plugin = (instance) => { | ||
const CommonJSMode2Plugin = (instance) => { | ||
const test = (file) => (!anymatch_1.default(instance.config.commonJSInterop.exclude, file) && | ||
@@ -26,1 +26,2 @@ anymatch_1.default(instance.config.commonJSInterop.include, file)); | ||
}; | ||
exports.CommonJSMode2Plugin = CommonJSMode2Plugin; |
@@ -10,3 +10,3 @@ "use strict"; | ||
const commonjs_mode_2_1 = require("./commonjs-mode-2/"); | ||
exports.CorePlugins = (instance) => { | ||
const CorePlugins = (instance) => { | ||
const plugins = [ | ||
@@ -25,1 +25,2 @@ json_1.JSONPlugin(), | ||
}; | ||
exports.CorePlugins = CorePlugins; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.JSONPlugin = void 0; | ||
exports.JSONPlugin = () => ({ | ||
const JSONPlugin = () => ({ | ||
name: 'core-json-plugin', | ||
@@ -22,1 +22,2 @@ getCacheKey: () => 1, | ||
}); | ||
exports.JSONPlugin = JSONPlugin; |
@@ -7,3 +7,3 @@ "use strict"; | ||
const path_1 = tslib_1.__importDefault(require("path")); | ||
exports.LoaderPlugin = () => ({ | ||
const LoaderPlugin = () => ({ | ||
name: 'core-loader-plugin', | ||
@@ -16,1 +16,2 @@ getCacheKey: () => 1, | ||
}); | ||
exports.LoaderPlugin = LoaderPlugin; |
@@ -41,3 +41,3 @@ "use strict"; | ||
}; | ||
exports.runTransformation = (ast, mode) => { | ||
const runTransformation = (ast, mode) => { | ||
traverse_1.default(ast, { | ||
@@ -56,3 +56,4 @@ MemberExpression(path) { | ||
}; | ||
exports.NodeEnvPlugin = (instance) => ({ | ||
exports.runTransformation = runTransformation; | ||
const NodeEnvPlugin = (instance) => ({ | ||
name: 'core-node-env-plugin', | ||
@@ -64,1 +65,2 @@ getCacheKey: () => instance.config.mode, | ||
}); | ||
exports.NodeEnvPlugin = NodeEnvPlugin; |
@@ -13,3 +13,3 @@ "use strict"; | ||
}; | ||
exports.resolve = (instance, basePath, request, overrides) => { | ||
const resolve = (instance, basePath, request, overrides) => { | ||
if (!defaultResolver) { | ||
@@ -21,3 +21,4 @@ defaultResolver = enhanced_resolve_1.ResolverFactory.createResolver(Object.assign({}, instance.config.resolve, defaultOpts)); | ||
}; | ||
exports.ResolverPlugin = (instance) => { | ||
exports.resolve = resolve; | ||
const ResolverPlugin = (instance) => { | ||
const cacheMap = new Map(); | ||
@@ -48,1 +49,2 @@ return { | ||
}; | ||
exports.ResolverPlugin = ResolverPlugin; |
@@ -18,3 +18,3 @@ "use strict"; | ||
}; | ||
exports.createFileHandler = (instance) => { | ||
const createFileHandler = (instance) => { | ||
let initialized = false; | ||
@@ -168,1 +168,2 @@ let filesDir; | ||
}; | ||
exports.createFileHandler = createFileHandler; |
@@ -17,3 +17,2 @@ /// <reference types="babel__traverse" /> | ||
export { PluginOptions } from './plugins'; | ||
export * from './plugins/removed'; | ||
export type { babelTypes, RawSourceMap }; | ||
@@ -92,2 +91,4 @@ export interface LoadedData { | ||
basePath?: string; | ||
/** Enable ETag */ | ||
etag?: boolean; | ||
/** Extensions to resolve when no extension is present in the URL */ | ||
@@ -114,2 +115,4 @@ extensions?: false | string[]; | ||
entries: ([string, string] | [string, string, string])[]; | ||
/** Enable/disable external host. Set a string of IPv4 address to set the external host */ | ||
externalHost?: boolean | string; | ||
/** Enable/disable Hot reload */ | ||
@@ -116,0 +119,0 @@ hotReload?: boolean; |
@@ -20,4 +20,3 @@ "use strict"; | ||
exports.builtInPlugins = tslib_1.__importStar(require("./plugins")); | ||
tslib_1.__exportStar(require("./plugins/removed"), exports); | ||
const INCOMPATIBLE_BELOW = '0.17.0'; | ||
const INCOMPATIBLE_BELOW = '0.19.0'; | ||
const DEFAULT_PORT = 7456; | ||
@@ -34,2 +33,3 @@ exports.DefaultConfig = { | ||
entries: null, | ||
externalHost: true, | ||
hotReload: true, | ||
@@ -79,2 +79,3 @@ includeDefaultPlugins: true, | ||
basePath: '/', | ||
etag: true, | ||
extensions: ['.html'], | ||
@@ -224,3 +225,3 @@ hidden: false, | ||
const contentServer = it.config.contentServer ? content_server_1.createContentServer(it) : undefined; | ||
const externalHost = utils_1.getExternalHost(); | ||
const externalHost = await utils_1.getExternalHost(it); | ||
for (const { setup } of it.plugins) { | ||
@@ -250,3 +251,3 @@ if (setup) { | ||
} | ||
let fileContent = `import '${fullAddress}/setup';\n`; | ||
let fileContent = `import '${fullAddress}/runtime';\n`; | ||
fileContent += 'import'; | ||
@@ -265,5 +266,2 @@ if (libName) | ||
const contentServerPath = (host, port) => (`http://${host}:${port}${it.config.contentServer.basePath}`.replace(/\/$/, '')); | ||
const startedAt = (address) => { | ||
it.log('info', chalk_1.default.green(`Content server started at: ${address}`)); | ||
}; | ||
const localPort = await portfinder_1.default.getPortPromise({ | ||
@@ -274,3 +272,2 @@ port: it.config.contentServer.port | ||
await startServer('Local content server', contentServer, localPort); | ||
startedAt(contentServerLocal); | ||
const openOptions = it.config.contentServer.open; | ||
@@ -287,3 +284,2 @@ if (openOptions) { | ||
await startServer('External content server', contentServer, externalPort, externalHost); | ||
startedAt(contentServerExternal); | ||
it.exports = { | ||
@@ -307,2 +303,9 @@ stop, | ||
} | ||
it.log('info', chalk_1.default.green([ | ||
'Content server is running on:', | ||
' Local - ' + chalk_1.default.blue(it.exports.contentServer.local), | ||
...(it.exports.contentServer.external | ||
? [' External - ' + chalk_1.default.blue(it.exports.contentServer.external)] | ||
: []) | ||
].join('\n'))); | ||
} | ||
@@ -317,6 +320,7 @@ else { | ||
}; | ||
exports.start = async (config = {}) => { | ||
const start = async (config = {}) => { | ||
const instance = await createInstance(config); | ||
return instance && instance.exports; | ||
}; | ||
exports.start = start; | ||
if (fs_1.default.existsSync(path_1.default.join(__dirname, '../../src'))) { | ||
@@ -323,0 +327,0 @@ // @ts-expect-error We don't need types for this |
@@ -16,3 +16,3 @@ "use strict"; | ||
}; | ||
exports.getPlugins = (options) => { | ||
const getPlugins = (options) => { | ||
const extracted = { | ||
@@ -43,2 +43,3 @@ imports: [], | ||
}; | ||
exports.getPlugins = getPlugins; | ||
const normalizeURL = (url) => { | ||
@@ -56,3 +57,3 @@ if (url.startsWith('~')) { | ||
const importedValueRE = /i__const_/i; | ||
exports.generateModuleCode = (data) => { | ||
const generateModuleCode = (data) => { | ||
let code = ''; | ||
@@ -128,3 +129,2 @@ let defaultExportObjStr = '{}'; | ||
// Main style injection and its hot reload | ||
import { hot } from 'reboost/hot'; | ||
import { replaceReplacements, patchObject } from '#/css-runtime'; | ||
@@ -144,3 +144,3 @@ | ||
if (!hot.data) { | ||
if (!import.meta.hot.data) { | ||
style = document.createElement('style'); | ||
@@ -156,3 +156,3 @@ style.textContent = exportedCSS; | ||
hot.accept((...args) => updateListeners.forEach((cb) => cb(...args))); | ||
import.meta.hot.accept((...args) => updateListeners.forEach((cb) => cb(...args))); | ||
} | ||
@@ -179,3 +179,3 @@ | ||
code += ` | ||
if (!hot.data) { | ||
if (!import.meta.hot.data) { | ||
importedStyles.forEach(({ apply }) => apply()); | ||
@@ -196,2 +196,3 @@ updateListeners.add(({ __importedStyles }) => { | ||
}; | ||
exports.generateModuleCode = generateModuleCode; | ||
exports.runtimeCode = ` | ||
@@ -198,0 +199,0 @@ export const replaceReplacements = (str, replacements) => { |
@@ -89,3 +89,3 @@ "use strict"; | ||
console.error(err); | ||
resolve(); | ||
resolve(undefined); | ||
} | ||
@@ -92,0 +92,0 @@ }; |
@@ -15,4 +15,5 @@ "use strict"; | ||
const importRE = /@import/i; | ||
exports.hasImportsIn = (css) => importRE.test(css); | ||
exports.importParser = (imports, testerFn) => ({ | ||
const hasImportsIn = (css) => importRE.test(css); | ||
exports.hasImportsIn = hasImportsIn; | ||
const importParser = (imports, testerFn) => ({ | ||
postcssPlugin: 'import-parser', | ||
@@ -57,2 +58,3 @@ prepare: (result) => ({ | ||
}); | ||
exports.importParser = importParser; | ||
const urlRE = /url/i; | ||
@@ -73,4 +75,5 @@ const imageSetRE = /(-webkit-)?image-set/i; | ||
}; | ||
exports.hasURLsIn = (css) => hasURLOrImageSet.test(css); | ||
exports.urlParser = (urls, testerFn) => ({ | ||
const hasURLsIn = (css) => hasURLOrImageSet.test(css); | ||
exports.hasURLsIn = hasURLsIn; | ||
const urlParser = (urls, testerFn) => ({ | ||
postcssPlugin: 'url-parser', | ||
@@ -136,1 +139,2 @@ prepare: (result) => { | ||
}); | ||
exports.urlParser = urlParser; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.FilePlugin = void 0; | ||
exports.FilePlugin = () => ({ | ||
const FilePlugin = () => ({ | ||
name: 'core-file-plugin', | ||
@@ -15,1 +15,2 @@ getCacheKey: () => 1, | ||
}); | ||
exports.FilePlugin = FilePlugin; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ReplacePlugin = void 0; | ||
exports.ReplacePlugin = (replacements) => { | ||
const ReplacePlugin = (replacements) => { | ||
return { | ||
@@ -28,1 +28,2 @@ name: 'core-replace-plugin', | ||
}; | ||
exports.ReplacePlugin = ReplacePlugin; |
@@ -14,8 +14,8 @@ "use strict"; | ||
const webSockets = new Set(); | ||
exports.createRouter = (instance) => { | ||
const createRouter = (instance) => { | ||
const routedPaths = {}; | ||
routedPaths['/transformed'] = file_handler_1.createFileHandler(instance); | ||
const loadSetupCode = () => (fs_1.default.readFileSync(path_1.default.resolve(__dirname, '../browser/setup.js')).toString()); | ||
const setupCode = loadSetupCode(); | ||
routedPaths['/setup'] = (ctx) => { | ||
const loadRuntimeCode = () => (fs_1.default.readFileSync(path_1.default.resolve(__dirname, '../browser/runtime.js')).toString()); | ||
const runtimeCode = loadRuntimeCode(); | ||
routedPaths['/runtime'] = (ctx) => { | ||
ctx.type = 'text/javascript'; | ||
@@ -26,14 +26,17 @@ ctx.body = `const address = "${instance.proxyAddress}";\n`; | ||
ctx.body += `const hotReload = ${instance.config.hotReload};\n\n`; | ||
ctx.body += instance.config.debugMode ? loadSetupCode() : setupCode; | ||
ctx.body += instance.config.debugMode ? loadRuntimeCode() : runtimeCode; | ||
}; | ||
const eTagKey = utils_1.uniqueID(10) + '-'; | ||
routedPaths['/raw'] = async (ctx) => { | ||
const filePath = ctx.query.q; | ||
try { | ||
const mtime = Math.floor((await fs_1.default.promises.stat(filePath)).mtimeMs) + ''; | ||
if (ctx.get('If-None-Match') === mtime) { | ||
const stat = await fs_1.default.promises.stat(filePath); | ||
const etag = eTagKey + Math.floor(stat.mtimeMs); | ||
if (ctx.get('If-None-Match') === etag) { | ||
ctx.status = 304; | ||
} | ||
else { | ||
ctx.body = await fs_1.default.promises.readFile(filePath); | ||
ctx.set('ETag', mtime); | ||
ctx.body = fs_1.default.createReadStream(filePath); | ||
ctx.set('Content-Length', stat.size + ''); | ||
ctx.set('ETag', etag); | ||
} | ||
@@ -43,8 +46,6 @@ } | ||
}; | ||
const hotCode = fs_1.default.readFileSync(path_1.default.resolve(__dirname, '../browser/hot.js')).toString(); | ||
routedPaths['/hot'] = (ctx) => { | ||
ctx.type = 'text/javascript'; | ||
ctx.body = `const address = "${instance.proxyAddress}";\n`; | ||
ctx.body += `const filePath = ${JSON.stringify(ctx.query.q)};\n\n`; | ||
ctx.body += hotCode; | ||
ctx.body = 'import { Hot } from "/runtime";\n'; | ||
ctx.body += `export const hot = new Hot(${JSON.stringify(ctx.query.q)});`; | ||
}; | ||
@@ -81,3 +82,4 @@ const importerCode = fs_1.default.readFileSync(path_1.default.resolve(__dirname, '../browser/importer.js')).toString(); | ||
}; | ||
exports.createProxyServer = (instance) => { | ||
exports.createRouter = createRouter; | ||
const createProxyServer = (instance) => { | ||
const proxyServer = new koa_1.default(); | ||
@@ -98,4 +100,6 @@ const router = exports.createRouter(instance); | ||
}; | ||
exports.messageClient = (message) => { | ||
exports.createProxyServer = createProxyServer; | ||
const messageClient = (message) => { | ||
webSockets.forEach((ws) => ws.send(JSON.stringify(message))); | ||
}; | ||
exports.messageClient = messageClient; |
@@ -10,3 +10,3 @@ "use strict"; | ||
const utils_1 = require("../utils"); | ||
exports.resolveDependency = async (instance, pathToResolve, relativeTo) => { | ||
const resolveDependency = async (instance, pathToResolve, relativeTo) => { | ||
for (const hook of processor_1.getPluginHooks(instance).resolveHooks) { | ||
@@ -20,5 +20,6 @@ const resolvedPath = await hook(pathToResolve, relativeTo); | ||
}; | ||
exports.resolveDependency = resolveDependency; | ||
const isPathRouted = (path) => path.startsWith('#/'); | ||
const pathFromRouted = (path) => path.substring(1); | ||
exports.resolveImports = async (instance, ast, filePath) => { | ||
const resolveImports = async (instance, ast, filePath) => { | ||
let error = false; | ||
@@ -70,3 +71,5 @@ const imports = []; | ||
let astProgram; | ||
let hasImportMeta = false; | ||
traverse_1.default(ast, { | ||
noScope: true, | ||
Program(nodePath) { | ||
@@ -100,3 +103,3 @@ astProgram = nodePath; | ||
// Rewrite dynamic imports | ||
const importerIdentifier = nodePath.scope.generateUidIdentifier(`importer_${utils_1.uniqueID(6)}`); | ||
const importerIdentifier = t.identifier(`importer_${utils_1.uniqueID(6)}`); | ||
const importerDeclaration = t.importDeclaration([ | ||
@@ -111,9 +114,15 @@ t.importDefaultSpecifier(importerIdentifier) | ||
} | ||
}, | ||
MetaProperty(path) { | ||
if (t.isIdentifier(path.node.meta, { name: 'import' }) && | ||
t.isIdentifier(path.node.property, { name: 'meta' })) | ||
hasImportMeta = true; | ||
} | ||
}); | ||
const importMeta = t.metaProperty(t.identifier('import'), t.identifier('meta')); | ||
const importMetaUrl = t.memberExpression(importMeta, t.identifier('url')); | ||
astProgram.node.body.unshift(t.expressionStatement(t.assignmentExpression('=', importMetaUrl, t.stringLiteral(filePath)))); | ||
astProgram.node.body.unshift(t.expressionStatement(t.assignmentExpression('=', t.memberExpression(importMeta, t.identifier('absoluteUrl')), importMetaUrl))); | ||
astProgram.node.body.unshift(t.expressionStatement(t.assignmentExpression('=', t.memberExpression(importMeta, t.identifier('reboost')), t.booleanLiteral(true)))); | ||
if (hasImportMeta) { | ||
const importMeta = t.metaProperty(t.identifier('import'), t.identifier('meta')); | ||
const importMetaUrl = t.memberExpression(importMeta, t.identifier('url')); | ||
const localHotIdentifier = t.identifier('Hot_' + utils_1.uniqueID(4)); | ||
astProgram.node.body.unshift(t.importDeclaration([t.importSpecifier(localHotIdentifier, t.identifier('Hot'))], t.stringLiteral('/runtime')), t.expressionStatement(t.assignmentExpression('=', t.memberExpression(importMeta, t.identifier('reboost')), t.booleanLiteral(true))), t.expressionStatement(t.assignmentExpression('=', t.memberExpression(importMeta, t.identifier('absoluteUrl')), importMetaUrl)), t.expressionStatement(t.assignmentExpression('=', importMetaUrl, t.stringLiteral(filePath))), t.expressionStatement(t.assignmentExpression('=', t.memberExpression(importMeta, t.identifier('hot')), t.newExpression(localHotIdentifier, [t.stringLiteral(filePath)])))); | ||
} | ||
for (const execute of promiseExecutors) | ||
@@ -129,1 +138,2 @@ await execute(); | ||
}; | ||
exports.resolveImports = resolveImports; |
@@ -61,3 +61,3 @@ "use strict"; | ||
}); | ||
exports.createTransformer = (instance) => { | ||
const createTransformer = (instance) => { | ||
const processor = processor_1.createProcessor(instance); | ||
@@ -97,1 +97,2 @@ const transformFile = async (filePath) => { | ||
}; | ||
exports.createTransformer = createTransformer; |
@@ -15,3 +15,3 @@ "use strict"; | ||
const pluginHooksMap = new Map(); | ||
exports.getPluginHooks = (instance) => { | ||
const getPluginHooks = (instance) => { | ||
if (!pluginHooksMap.has(instance)) { | ||
@@ -32,96 +32,92 @@ const getHooks = (hookName) => (instance.plugins.map((plugin) => plugin[hookName]).filter((hook) => typeof hook === 'function')); | ||
}; | ||
exports.createProcessor = (instance) => { | ||
exports.getPluginHooks = getPluginHooks; | ||
const createProcessor = (instance) => { | ||
const handleError = ({ message }) => { | ||
instance.log('info', chalk_1.default.red(message)); | ||
const line = '-'.repeat(process.stdout.columns); | ||
instance.log('info', chalk_1.default.red(line + '\n' + message + '\n' + line)); | ||
return { error: message }; | ||
}; | ||
const process = async (filePath, pluginContext) => { | ||
const pluginHooks = exports.getPluginHooks(instance); | ||
let code; | ||
let sourceMap; | ||
let ast; | ||
let type; | ||
for (const hook of pluginHooks.loadHooks) { | ||
const result = await utils_1.bind(hook, pluginContext)(filePath); | ||
if (result) { | ||
({ code } = result); | ||
({ type } = result); | ||
if (result.map) | ||
sourceMap = result.map; | ||
break; | ||
} | ||
} | ||
const runTransformContentHooks = async (hooks) => { | ||
for (const hook of hooks) { | ||
const result = await utils_1.bind(hook, pluginContext)({ code, type, map: sourceMap }, filePath); | ||
return { | ||
process: async (filePath, pluginContext) => { | ||
const pluginHooks = exports.getPluginHooks(instance); | ||
let code; | ||
let sourceMap; | ||
let ast; | ||
let type; | ||
for (const hook of pluginHooks.loadHooks) { | ||
const result = await utils_1.bind(hook, pluginContext)(filePath); | ||
if (result) { | ||
if (result instanceof Error) | ||
return handleError(result); | ||
({ code } = result); | ||
if (result.map) { | ||
// Here source maps sources can be null, like when source map is generated using MagicString (npm package) | ||
result.map.sources = result.map.sources.map((sourcePath) => !sourcePath ? filePath : sourcePath); | ||
sourceMap = sourceMap ? await utils_1.mergeSourceMaps(sourceMap, result.map) : result.map; | ||
} | ||
if (result.type) | ||
type = result.type; | ||
({ type } = result); | ||
if (result.map) | ||
sourceMap = result.map; | ||
break; | ||
} | ||
} | ||
}; | ||
let transformContentError; | ||
transformContentError = await runTransformContentHooks(pluginHooks.transformContentHooks); | ||
if (transformContentError) | ||
return transformContentError; | ||
if (type !== 'js') { | ||
for (const hook of pluginHooks.transformIntoJSHooks) { | ||
const result = await utils_1.bind(hook, pluginContext)({ | ||
code, | ||
type, | ||
map: sourceMap | ||
}, filePath); | ||
if (result) { | ||
if (result instanceof Error) | ||
return handleError(result); | ||
({ code } = result); | ||
sourceMap = result.inputMap; | ||
type = 'js'; | ||
break; | ||
const runTransformContentHooks = async (hooks) => { | ||
for (const hook of hooks) { | ||
const result = await utils_1.bind(hook, pluginContext)({ code, type, map: sourceMap }, filePath); | ||
if (result) { | ||
if (result instanceof Error) | ||
return handleError(result); | ||
({ code } = result); | ||
if (result.map) { | ||
// Here source maps sources can be null, like when source map is generated using MagicString (npm package) | ||
result.map.sources = result.map.sources.map((sourcePath) => !sourcePath ? filePath : sourcePath); | ||
sourceMap = sourceMap ? await utils_1.mergeSourceMaps(sourceMap, result.map) : result.map; | ||
} | ||
if (result.type) | ||
type = result.type; | ||
} | ||
} | ||
}; | ||
let transformContentError; | ||
transformContentError = await runTransformContentHooks(pluginHooks.transformContentHooks); | ||
if (transformContentError) | ||
return transformContentError; | ||
if (type !== 'js') { | ||
for (const hook of pluginHooks.transformIntoJSHooks) { | ||
const result = await utils_1.bind(hook, pluginContext)({ | ||
code, | ||
type, | ||
map: sourceMap | ||
}, filePath); | ||
if (result) { | ||
if (result instanceof Error) | ||
return handleError(result); | ||
({ code } = result); | ||
sourceMap = result.inputMap; | ||
type = 'js'; | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
if (!['js', 'mjs', 'es6', 'es', 'cjs'].includes(type)) { | ||
let message = `${filePath}: File with type "${type}" is not supported. `; | ||
message += 'You may need proper loader to transform this kind of files into JS.'; | ||
return handleError({ message }); | ||
} | ||
transformContentError = await runTransformContentHooks(pluginHooks.transformJSContentHooks); | ||
if (transformContentError) | ||
return transformContentError; | ||
try { | ||
ast = parser_1.parse(code, { sourceType: 'module' }); | ||
} | ||
catch (e) /* istanbul ignore next */ { | ||
let message = ''; | ||
let consoleMessage = ''; | ||
const frameMessage = e.message.replace(/\s*\(.*\)$/, ''); | ||
let rawCode = code; | ||
let location = e.loc; | ||
let unableToLocateFile = false; | ||
message += `Error while parsing "${filePath}"\n`; | ||
message += 'You may need proper loader to handle this kind of files.\n\n'; | ||
consoleMessage += chalk_1.default.red(message); | ||
if (sourceMap) { | ||
const consumer = await new source_map_1.SourceMapConsumer(sourceMap); | ||
const originalLoc = consumer.originalPositionFor(e.loc); | ||
if (originalLoc.source) { | ||
const originalCode = consumer.sourceContentFor(originalLoc.source); | ||
if (originalCode) { | ||
rawCode = originalCode; | ||
location = originalLoc; | ||
location.column = location.column || 1; | ||
} | ||
else { | ||
const absPathToSource = path_1.default.join(instance.config.rootDir, originalLoc.source); | ||
if (fs_1.default.existsSync(absPathToSource)) { | ||
rawCode = fs_1.default.readFileSync(absPathToSource).toString(); | ||
if (!['js', 'mjs', 'es6', 'es', 'cjs'].includes(type)) { | ||
let message = `${filePath}: File with type "${type}" is not supported. `; | ||
message += 'You may need proper loader to transform this kind of files into JS.'; | ||
return handleError({ message }); | ||
} | ||
transformContentError = await runTransformContentHooks(pluginHooks.transformJSContentHooks); | ||
if (transformContentError) | ||
return transformContentError; | ||
try { | ||
ast = parser_1.parse(code, { sourceType: 'module' }); | ||
} | ||
catch (e) /* istanbul ignore next */ { | ||
let message = ''; | ||
let consoleMessage = ''; | ||
const frameMessage = e.message.replace(/\s*\(.*\)$/, ''); | ||
let rawCode = code; | ||
let location = e.loc; | ||
let unableToLocateFile = false; | ||
message += `Error while parsing "${filePath}"\n`; | ||
message += 'You may need proper loader to handle this kind of files.\n\n'; | ||
consoleMessage += chalk_1.default.red(message); | ||
if (sourceMap) { | ||
const consumer = await new source_map_1.SourceMapConsumer(sourceMap); | ||
const originalLoc = consumer.originalPositionFor(e.loc); | ||
if (originalLoc.source) { | ||
const originalCode = consumer.sourceContentFor(originalLoc.source); | ||
if (originalCode) { | ||
rawCode = originalCode; | ||
location = originalLoc; | ||
@@ -131,41 +127,49 @@ location.column = location.column || 1; | ||
else { | ||
unableToLocateFile = true; | ||
const absPathToSource = path_1.default.join(instance.config.rootDir, originalLoc.source); | ||
if (fs_1.default.existsSync(absPathToSource)) { | ||
rawCode = fs_1.default.readFileSync(absPathToSource).toString(); | ||
location = originalLoc; | ||
location.column = location.column || 1; | ||
} | ||
else { | ||
unableToLocateFile = true; | ||
} | ||
} | ||
} | ||
} | ||
if (unableToLocateFile) { | ||
let unableToLocateMsg = 'We are unable to locate the original file. '; | ||
unableToLocateMsg += 'This is not accurate, but it may help you at some point.\n\n'; | ||
message += unableToLocateMsg + code_frame_1.codeFrameColumns(code, { start: e.loc }, { | ||
message: frameMessage | ||
}); | ||
consoleMessage += unableToLocateMsg + code_frame_1.codeFrameColumns(code, { start: e.loc }, { | ||
highlightCode: true, | ||
message: frameMessage | ||
}); | ||
} | ||
else { | ||
message += code_frame_1.codeFrameColumns(rawCode, { start: location }, { | ||
message: frameMessage | ||
}); | ||
consoleMessage += code_frame_1.codeFrameColumns(rawCode, { start: location }, { | ||
highlightCode: true, | ||
message: frameMessage | ||
}); | ||
} | ||
instance.log('info', consoleMessage); | ||
return { | ||
error: message | ||
}; | ||
} | ||
if (unableToLocateFile) { | ||
let unableToLocateMsg = 'We are unable to locate the original file. '; | ||
unableToLocateMsg += 'This is not accurate, but it may help you at some point.\n\n'; | ||
message += unableToLocateMsg + code_frame_1.codeFrameColumns(code, { start: e.loc }, { | ||
message: frameMessage | ||
}); | ||
consoleMessage += unableToLocateMsg + code_frame_1.codeFrameColumns(code, { start: e.loc }, { | ||
highlightCode: true, | ||
message: frameMessage | ||
}); | ||
for (const hook of pluginHooks.transformASTHooks) { | ||
await utils_1.bind(hook, pluginContext)(ast, { traverse: traverse_1.default, types: babelTypes }, filePath); | ||
} | ||
else { | ||
message += code_frame_1.codeFrameColumns(rawCode, { start: location }, { | ||
message: frameMessage | ||
}); | ||
consoleMessage += code_frame_1.codeFrameColumns(rawCode, { start: location }, { | ||
highlightCode: true, | ||
message: frameMessage | ||
}); | ||
} | ||
instance.log('info', consoleMessage); | ||
return { | ||
error: message | ||
ast, | ||
sourceMap | ||
}; | ||
} | ||
for (const hook of pluginHooks.transformASTHooks) { | ||
await utils_1.bind(hook, pluginContext)(ast, { traverse: traverse_1.default, types: babelTypes }, filePath); | ||
} | ||
return { | ||
ast, | ||
sourceMap | ||
}; | ||
}; | ||
return { process }; | ||
}; | ||
exports.createProcessor = createProcessor; |
import Koa from 'koa'; | ||
import { RawSourceMap } from 'source-map'; | ||
import http from 'http'; | ||
import { ReboostInstance } from './index'; | ||
export declare type DeepRequire<T> = T extends Record<string, any> ? { | ||
@@ -34,3 +35,3 @@ [P in keyof T]-?: DeepRequire<T[P]>; | ||
export declare const onServerCreated: (app: Koa, cb: (server: http.Server) => void) => void; | ||
export declare const getExternalHost: () => string; | ||
export declare const getExternalHost: (instance: ReboostInstance) => Promise<string | void>; | ||
export declare const getReadableHRTime: ([seconds, nanoseconds]: [number, number]) => string; | ||
@@ -37,0 +38,0 @@ /** |
@@ -6,9 +6,14 @@ "use strict"; | ||
const source_map_1 = require("source-map"); | ||
const chalk_1 = tslib_1.__importDefault(require("chalk")); | ||
const fs_1 = tslib_1.__importDefault(require("fs")); | ||
const path_1 = tslib_1.__importDefault(require("path")); | ||
const os_1 = tslib_1.__importDefault(require("os")); | ||
exports.toPosix = (pathString) => pathString.replace(/\\/g, '/'); | ||
exports.uniqueID = (length = 32) => Array(length).fill(0).map(() => (Math.random() * 16 | 0).toString(16)).join(''); | ||
exports.isPlainObject = (data) => !!data && data.constructor === Object; | ||
exports.merge = (source, target) => { | ||
const net_1 = tslib_1.__importDefault(require("net")); | ||
const toPosix = (pathString) => pathString.replace(/\\/g, '/'); | ||
exports.toPosix = toPosix; | ||
const uniqueID = (length = 32) => Array(length).fill(0).map(() => (Math.random() * 16 | 0).toString(16)).join(''); | ||
exports.uniqueID = uniqueID; | ||
const isPlainObject = (data) => !!data && data.constructor === Object; | ||
exports.isPlainObject = isPlainObject; | ||
const merge = (source, target) => { | ||
for (const key in target) { | ||
@@ -24,3 +29,4 @@ if (exports.isPlainObject(source[key]) && exports.isPlainObject(target[key])) { | ||
}; | ||
exports.clone = (object) => { | ||
exports.merge = merge; | ||
const clone = (object) => { | ||
const cloned = Array.isArray(object) ? [] : {}; | ||
@@ -36,8 +42,11 @@ for (const key in object) { | ||
}; | ||
exports.ensureDir = (dirPath) => { | ||
exports.clone = clone; | ||
const ensureDir = (dirPath) => { | ||
if (!fs_1.default.existsSync(dirPath)) | ||
fs_1.default.mkdirSync(dirPath, { recursive: true }); | ||
}; | ||
exports.isDirectory = (dirPath) => fs_1.default.lstatSync(dirPath).isDirectory(); | ||
exports.rmDir = (dirPath) => { | ||
exports.ensureDir = ensureDir; | ||
const isDirectory = (dirPath) => fs_1.default.lstatSync(dirPath).isDirectory(); | ||
exports.isDirectory = isDirectory; | ||
const rmDir = (dirPath) => { | ||
if (!fs_1.default.existsSync(dirPath)) | ||
@@ -53,3 +62,4 @@ return; | ||
}; | ||
exports.deepFreeze = (obj) => { | ||
exports.rmDir = rmDir; | ||
const deepFreeze = (obj) => { | ||
for (const key in obj) { | ||
@@ -62,3 +72,4 @@ if (exports.isPlainObject(obj[key]) || Array.isArray(obj[key])) { | ||
}; | ||
exports.observable = (object, onChange) => { | ||
exports.deepFreeze = deepFreeze; | ||
const observable = (object, onChange) => { | ||
const handler = { | ||
@@ -80,3 +91,4 @@ set: (target, key, value, receiver) => { | ||
}; | ||
exports.objectPaths = (object, pPath) => { | ||
exports.observable = observable; | ||
const objectPaths = (object, pPath) => { | ||
const paths = []; | ||
@@ -94,3 +106,4 @@ Object.keys(object).forEach((key) => { | ||
}; | ||
exports.serializeObject = (object, excludePaths, stringify = true, pPath) => { | ||
exports.objectPaths = objectPaths; | ||
const serializeObject = (object, excludePaths, stringify = true, pPath) => { | ||
if (excludePaths && pPath !== '') { | ||
@@ -123,9 +136,12 @@ if (!Array.isArray(excludePaths)) { | ||
}; | ||
exports.serializeObject = serializeObject; | ||
// eslint-disable-next-line @typescript-eslint/ban-types | ||
exports.bind = (func, bindTo) => func.bind(bindTo); | ||
exports.diff = (oldA, newA) => ({ | ||
const bind = (func, bindTo) => func.bind(bindTo); | ||
exports.bind = bind; | ||
const diff = (oldA, newA) => ({ | ||
added: newA.filter((a) => !oldA.includes(a)), | ||
removed: oldA.filter((a) => !newA.includes(a)) | ||
}); | ||
exports.getTimestamp = () => { | ||
exports.diff = diff; | ||
const getTimestamp = () => { | ||
const date = new Date(); | ||
@@ -135,3 +151,4 @@ const f = (num) => ('' + num).length === 1 ? '0' + num : num; | ||
}; | ||
exports.isVersionLessThan = (version, toCompareWith) => { | ||
exports.getTimestamp = getTimestamp; | ||
const isVersionLessThan = (version, toCompareWith) => { | ||
const [aMajor, aMinor, aPatch] = version.split('.').map(Number); | ||
@@ -153,3 +170,4 @@ const [bMajor, bMinor, bPatch] = toCompareWith.split('.').map(Number); | ||
}; | ||
exports.onServerCreated = (app, cb) => { | ||
exports.isVersionLessThan = isVersionLessThan; | ||
const onServerCreated = (app, cb) => { | ||
const defaultListenFunc = app.listen; | ||
@@ -162,8 +180,37 @@ app.listen = (...args) => { | ||
}; | ||
exports.getExternalHost = () => { | ||
const interfaces = os_1.default.networkInterfaces(); | ||
for (const dev in interfaces) { | ||
for (const details of interfaces[dev]) { | ||
if (details.family === 'IPv4' && !details.internal) { | ||
return details.address; | ||
exports.onServerCreated = onServerCreated; | ||
const getExternalHost = async (instance) => { | ||
const { externalHost } = instance.config; | ||
if (typeof externalHost === 'string') { | ||
if (!net_1.default.isIPv4(externalHost)) { | ||
return instance.log('info', chalk_1.default.red(`The provided external host address "${externalHost}" is not a valid IPv4 address. ` + | ||
'Please provide a different host address.')); | ||
} | ||
const isServerUsable = await new Promise((resolve) => { | ||
const server = net_1.default.createServer(); | ||
server.once('listening', () => { | ||
server.close(); | ||
resolve(true); | ||
}); | ||
server.once('error', (err) => { | ||
server.close(); | ||
if (err.code === 'EADDRNOTAVAIL' || err.code === 'EINVAL') { | ||
resolve(false); | ||
} | ||
}); | ||
server.listen(/* Any port number */ 1678, externalHost); | ||
}); | ||
if (!isServerUsable) { | ||
return instance.log('info', chalk_1.default.red(`The provided external host "${externalHost}" is not available. ` + | ||
'Please provide a different host address.')); | ||
} | ||
return externalHost; | ||
} | ||
if (externalHost) { | ||
const interfaces = os_1.default.networkInterfaces(); | ||
for (const dev in interfaces) { | ||
for (const details of interfaces[dev]) { | ||
if (details.family === 'IPv4' && !details.internal) { | ||
return details.address; | ||
} | ||
} | ||
@@ -173,4 +220,5 @@ } | ||
}; | ||
exports.getExternalHost = getExternalHost; | ||
/* istanbul ignore next */ | ||
exports.getReadableHRTime = ([seconds, nanoseconds]) => { | ||
const getReadableHRTime = ([seconds, nanoseconds]) => { | ||
if (seconds) { | ||
@@ -182,2 +230,3 @@ return `${seconds}s ${Math.floor(nanoseconds / 1e6)}ms`; | ||
}; | ||
exports.getReadableHRTime = getReadableHRTime; | ||
const isUndefOrNull = (d) => d === null || d === undefined; | ||
@@ -189,3 +238,3 @@ /** | ||
*/ | ||
exports.mergeSourceMaps = async (oldMap, newMap) => { | ||
const mergeSourceMaps = async (oldMap, newMap) => { | ||
if (!oldMap) | ||
@@ -231,1 +280,2 @@ return newMap; | ||
}; | ||
exports.mergeSourceMaps = mergeSourceMaps; |
@@ -11,3 +11,3 @@ "use strict"; | ||
const proxy_server_1 = require("./proxy-server"); | ||
exports.createWatcher = (instance) => { | ||
const createWatcher = (instance) => { | ||
const { watchOptions } = instance.config; | ||
@@ -82,1 +82,2 @@ const watcher = new chokidar_1.FSWatcher(watchOptions.chokidar); | ||
}; | ||
exports.createWatcher = createWatcher; |
@@ -1,4 +0,4 @@ | ||
import { Hot } from './dist/browser/hot'; | ||
import { Hot } from './dist/browser/runtime'; | ||
export declare const hot: Hot; | ||
export { Hot } |
{ | ||
"name": "reboost", | ||
"version": "0.18.2", | ||
"version": "0.19.0", | ||
"description": "A super fast dev server for rapid web development", | ||
@@ -22,4 +22,4 @@ "main": "./dist/node/index.js", | ||
"test:watch": "jest --watch", | ||
"test:build": "tsc -p ./tests-src/build.tsconfig.json && node ./tests-src/createRequireAll", | ||
"test:build:watch": "tsc -p ./tests-src/build.tsconfig.json --incremental -w", | ||
"test:build": "tsc -p ./tests/build.tsconfig.json && node ./tests/createRequireAll", | ||
"test:build:watch": "tsc -p ./tests/build.tsconfig.json --incremental -w", | ||
"test:ci": "npm run build:mapped && npm run test:build && npm run test:coverage" | ||
@@ -43,10 +43,10 @@ }, | ||
"dependencies": { | ||
"@babel/code-frame": "^7.10.4", | ||
"@babel/generator": "^7.12.5", | ||
"@babel/parser": "^7.12.5", | ||
"@babel/traverse": "^7.12.5", | ||
"@babel/types": "^7.12.6", | ||
"@babel/code-frame": "^7.12.11", | ||
"@babel/generator": "^7.12.11", | ||
"@babel/parser": "^7.12.11", | ||
"@babel/traverse": "^7.12.10", | ||
"@babel/types": "^7.12.11", | ||
"@koa/cors": "^3.1.0", | ||
"@types/babel__generator": "^7.6.2", | ||
"@types/babel__traverse": "^7.0.15", | ||
"@types/babel__traverse": "^7.11.0", | ||
"@types/koa": "^2.11.6", | ||
@@ -56,6 +56,6 @@ "anymatch": "^3.1.1", | ||
"chokidar": "^3.4.3", | ||
"enhanced-resolve": "^5.3.1", | ||
"esbuild": "^0.8.10", | ||
"enhanced-resolve": "^5.4.0", | ||
"esbuild": "^0.8.23", | ||
"hash-sum": "^2.0.0", | ||
"icss-utils": "^5.0.0", | ||
"icss-utils": "^5.1.0", | ||
"koa": "^2.13.0", | ||
@@ -69,3 +69,3 @@ "koa-proxies": "^0.11.0", | ||
"portfinder": "^1.0.28", | ||
"postcss": "^8.1.7", | ||
"postcss": "^8.2.1", | ||
"postcss-modules-extract-imports": "^3.0.0", | ||
@@ -78,11 +78,11 @@ "postcss-modules-local-by-default": "^4.0.0", | ||
"tslib": "^2.0.3", | ||
"ws": "^7.4.0" | ||
"ws": "^7.4.1" | ||
}, | ||
"devDependencies": { | ||
"@types/babel__code-frame": "^7.0.2", | ||
"@types/jest": "^26.0.15", | ||
"@types/jest": "^26.0.19", | ||
"@types/koa-send": "^4.1.2", | ||
"@types/koa__cors": "^3.0.2", | ||
"@types/node": "^14.14.8", | ||
"@types/puppeteer": "^5.4.0", | ||
"@types/node": "^14.14.14", | ||
"@types/puppeteer": "^5.4.2", | ||
"@types/ws": "^7.4.0", | ||
@@ -93,5 +93,5 @@ "concurrently": "^5.3.0", | ||
"source-map-support": "^0.5.19", | ||
"typescript": "^4.0.5" | ||
"typescript": "^4.1.3" | ||
}, | ||
"gitHead": "88aec76fffff0c70740609c6b01245e88d1a62fc" | ||
"gitHead": "624daaec543585f5927b81314dd5735714c432e5" | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
303403
86
6859
14
3
Updated@babel/code-frame@^7.12.11
Updated@babel/generator@^7.12.11
Updated@babel/parser@^7.12.11
Updated@babel/traverse@^7.12.10
Updated@babel/types@^7.12.11
Updatedenhanced-resolve@^5.4.0
Updatedesbuild@^0.8.23
Updatedicss-utils@^5.1.0
Updatedpostcss@^8.2.1
Updatedws@^7.4.1