diff --git a/src/bundling/bindings-rewrite.ts b/src/bundling/bindings-rewrite.ts index 9d175aa..8d6c998 100644 --- a/src/bundling/bindings-rewrite.ts +++ b/src/bundling/bindings-rewrite.ts @@ -3,74 +3,6 @@ import * as path from 'path' import * as child from 'child_process' import { createHash } from 'crypto' -export interface ExtractNodeModuleOptions { - [key: string]: { additionalFiles: string[] } | true -} - -function hashName(name: string | Buffer) { - return createHash('md5') - .update(name) - .digest('hex') - .toString() - .slice(0, 8) -} - -export function embedDotNode( - options: ExtractNodeModuleOptions, - file: { contents: string; absPath: string } -) { - const contents = fs.readFileSync(file.absPath) - const modulePathParts = file.absPath.split(path.sep).reverse() - const module = modulePathParts[modulePathParts.findIndex(x => x === 'node_modules') - 1] - const bindingName = path.basename(file.absPath) - const settings = options[module] - const moduleDir = hashName(contents) - file.contents = ` - var fs=require('fs');var path=require('path');var binding='${contents.toString( - 'base64' - )}';function mkdirp(r,t){t=t||null,r=path.resolve(r);try{fs.mkdirSync(r),t=t||r}catch(c){if("ENOENT"===c.code)t=mkdirp(path.dirname(r),t),mkdirp(r,t);else{var i;try{i=fs.statSync(r)}catch(r){throw c}if(!i.isDirectory())throw c}}return t};` - - if (!settings || settings === true) { - file.contents += ` - mkdirp('${moduleDir}'); - var bindingPath = path.join(process.cwd(), '${moduleDir}', '${bindingName}') - require('fs').writeFileSync(bindingPath, Buffer.from(binding, 'base64')) - process.dlopen(module, bindingPath) - `.trim() - return - } - - let depth = 0 - settings.additionalFiles.forEach(file => { - let ownDepth = 0 - file.split('/').forEach(x => x === '..' && ownDepth++) - depth = ownDepth > depth ? ownDepth : depth - }) - let segments = [moduleDir] - while (depth--) { - segments.push(hashName(moduleDir + depth)) - } - segments.push(bindingName) - - file.contents += ` - var cwd = process.cwd() - var bindingFileParts = ${JSON.stringify(segments)}; - var bindingFile = path.join.apply(path, [cwd].concat(bindingFileParts)); - mkdirp(path.dirname(bindingFile)); - fs.writeFileSync(bindingFile, Buffer.from(binding, 'base64')); - ${settings.additionalFiles.reduce((code, filename, i) => { - const contents = fs.readFileSync(path.join(path.dirname(file.absPath), filename)) - return (code += ` - var file${i} = '${contents.toString('base64')}'; - var filePath${i} = path.join(cwd, bindingFileParts[0], '${filename.split('../').join('')}'); - mkdirp(path.dirname(filePath${i})); - fs.writeFileSync(filePath${i}, Buffer.from(file${i}, 'base64')); - `) - }, '')}; - process.dlopen(module, bindingFile) - ` -} - function findNativeModulePath(filePath: string, bindingsArg: string) { const dirname = path.dirname(filePath) const tempFile = Math.random() * 100 + '.js' diff --git a/src/bundling/embed-node.ts b/src/bundling/embed-node.ts new file mode 100644 index 0000000..3a03b98 --- /dev/null +++ b/src/bundling/embed-node.ts @@ -0,0 +1,71 @@ +import { createHash } from 'crypto' +import * as path from 'path' + +export interface EmbedNodeModuleOptions { + [key: string]: { additionalFiles: string[] } | true +} + +function hashName(name: string | Buffer) { + return createHash('md5') + .update(name) + .digest('hex') + .toString() + .slice(0, 8) +} + +export function embedDotNode( + options: EmbedNodeModuleOptions, + file: { contents: string; absPath: string } +) { + const contents = fs.readFileSync(file.absPath) + const modulePathParts = file.absPath.split(path.sep).reverse() + const module = modulePathParts[modulePathParts.findIndex(x => x === 'node_modules') - 1] + const bindingName = path.basename(file.absPath) + const settings = options[module] + const moduleDir = hashName(contents) + file.contents = ` + var fs=require('fs');var path=require('path');var binding='${contents.toString( + 'base64' + )}';function mkdirp(r,t){t=t||null,r=path.resolve(r);try{fs.mkdirSync(r),t=t||r}catch(c){if("ENOENT"===c.code)t=mkdirp(path.dirname(r),t),mkdirp(r,t);else{var i;try{i=fs.statSync(r)}catch(r){throw c}if(!i.isDirectory())throw c}}return t};` + + if (!settings || settings === true) { + file.contents += ` + mkdirp('${moduleDir}'); + var bindingPath = path.join(process.cwd(), '${moduleDir}', '${bindingName}') + + require('fs').writeFileSync(bindingPath, Buffer.from(binding, 'base64')) + process.dlopen(module, bindingPath) + `.trim() + return {} + } + + let depth = 0 + settings.additionalFiles.forEach(file => { + let ownDepth = 0 + file.split('/').forEach(x => x === '..' && ownDepth++) + depth = ownDepth > depth ? ownDepth : depth + }) + let segments = [moduleDir] + while (depth--) { + segments.push(hashName(moduleDir + depth)) + } + segments.push(bindingName) + + file.contents += ` + var cwd = process.cwd() + var bindingFileParts = ${JSON.stringify(segments)}; + var bindingFile = path.join.apply(path, [cwd].concat(bindingFileParts)); + mkdirp(path.dirname(bindingFile)); + fs.writeFileSync(bindingFile, Buffer.from(binding, 'base64')); + ${settings.additionalFiles.reduce((code, filename, i) => { + const contents = fs.readFileSync(path.join(path.dirname(file.absPath), filename)) + return (code += ` + var file${i} = '${contents.toString('base64')}'; + var filePath${i} = path.join(cwd, bindingFileParts[0], '${filename.split('../').join('')}'); + mkdirp(path.dirname(filePath${i})); + fs.writeFileSync(filePath${i}, Buffer.from(file${i}, 'base64')); + `) + }, '')}; + process.dlopen(module, bindingFile) + ` +} diff --git a/src/bundling/fuse-native-module-plugin.ts b/src/bundling/fuse-native-module-plugin.ts index eb4fdd1..389b2cf 100644 --- a/src/bundling/fuse-native-module-plugin.ts +++ b/src/bundling/fuse-native-module-plugin.ts @@ -1,4 +1,5 @@ -import { BindingsRewrite, embedDotNode, ExtractNodeModuleOptions } from './bindings-rewrite' +import { BindingsRewrite } from './bindings-rewrite' +import { embedDotNode, EmbedNodeModuleOptions } from './embed-node' export interface FuseBoxFile { info: { absPath: string } @@ -21,14 +22,14 @@ export interface FuseBoxFile { ): void } -export default function(options: ExtractNodeModuleOptions = {}) { +export default function(options: EmbedNodeModuleOptions = {}) { return new NativeModulePlugin(options) } export class NativeModulePlugin { public test = /node_modules.*(\.js|\.node)$|\.node$/ public limit2Project = false - private modules: (keyof ExtractNodeModuleOptions)[] + private modules: (keyof EmbedNodeModuleOptions)[] constructor(public options = {}) {}