Created
January 29, 2019 11:16
-
-
Save lll000111/1b5487dc6bd07bd8b798083e4149bfa2 to your computer and use it in GitHub Desktop.
build.js for Neo one
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
// @flow | |
'use strict'; | |
/* eslint-disable arrow-parens, no-console, no-await-in-loop */ | |
const {basename, dirname, join, relative} = require('path'); | |
const {promisify} = require('util'); | |
const crypto = require('crypto'); | |
const exec = promisify(require('child_process').exec); | |
const mkdir = promisify(require('fs').mkdir); | |
const readDir = promisify(require('fs').readdir); | |
const readFile = promisify(require('fs').readFile); | |
const writeFile = promisify(require('fs').writeFile); | |
const copyFile = promisify(require('fs').copyFile); | |
const {flat, memoize} = require('one.core/lib/util/function.js'); | |
// const babel = require('@babel/core'); | |
const babel = require('babel-core'); | |
const dependencyTree = require('dependency-tree'); | |
const BABEL_OPTS_6 = { | |
presets: [ | |
'babel-preset-es2015', | |
'babel-preset-stage-2' | |
// 'minify' | |
], | |
plugins: [ | |
'transform-flow-strip-types' | |
], | |
comments: false | |
}; | |
// const BABEL_OPTS_ES5 = { | |
// presets: [ | |
// '@babel/preset-env', | |
// '@babel/preset-flow' | |
// // 'minify' | |
// ], | |
// plugins: [ | |
// [ | |
// '@babel/plugin-transform-runtime', | |
// { | |
// 'corejs': false, | |
// 'helpers': true, | |
// 'regenerator': true, | |
// 'useESModules': false | |
// } | |
// ] | |
// ], | |
// comments: false | |
// }; | |
const hash = (s/*: string*/)/*: string*/ => { | |
return crypto.createHash('sha256').update(s, 'utf8').digest('hex'); | |
}; | |
/** | |
* Core node.js module dependencies are skipped - the package uses "precinct" | |
* (https://www.npmjs.com/package/precinct), function paperwork(), and sets its option | |
* includeCore=false. | |
* @param {string} file | |
* @returns {Array<string>} | |
*/ | |
const getDepTree = memoize( | |
(file/*: string*/)/*: Array<string>*/ => { | |
// The paths of the files in the returned array of files are absolute paths from / (root) | |
const deps = dependencyTree.toList({ | |
filename: file, | |
directory: dirname(file), | |
detective: { | |
amd: { | |
skipLazyLoaded: false | |
}, | |
es6: { | |
mixedImports: true | |
} | |
} | |
}) | |
.map(file => relative(__dirname, file)); | |
return deps; | |
} | |
); | |
const buildOneForLowJs = async ()/*: Promise<void>*/ => { | |
console.log('Building ONE for low.js'); | |
const { /* stdout, */ stderr} = await exec('./build.js low', {cwd: './node_modules/one.core'}); | |
if (stderr !== '') { | |
throw new Error(stderr); | |
} | |
}; | |
const mkdirs = async ()/*: Promise<void>*/ => { | |
await mkdir(join(__dirname, 'DEVICE'), {recursive: true}); | |
await mkdir(join(__dirname, 'DEVICE', 'DATA'), {recursive: true}); | |
}; | |
const processJsFile = async (file/*: string*/)/*: Promise<void>*/ => { | |
const code/*: string*/ = await readFile(file, 'utf8'); | |
const dest = join('DEVICE', file.startsWith('src') ? '' : dirname(file)); | |
let oldHash/*: string*/; | |
try { | |
const oldCode = await readFile(join(dest, basename(file)), 'utf8'); | |
oldHash = hash(oldCode); | |
} catch (err) { | |
if (err.code !== 'ENOENT') { | |
throw err; | |
} | |
} | |
// const transformedCode/*: Object*/ = await babel.transformAsync(code, BABEL_OPTS_ES5); | |
const transformedCode/*: Object*/ = babel.transform(code, BABEL_OPTS_6); | |
const newHash/*: string*/ = hash(transformedCode.code); | |
if (!file.startsWith('src')) { | |
await mkdir(dest, {recursive: true}); | |
} | |
if (newHash !== oldHash) { | |
await writeFile(join(dest, basename(file)), transformedCode.code, {flag: 'w'}); | |
console.log('Wrote', join(dest, basename(file))); | |
} | |
}; | |
const findDepsInDirectory = async (dir/*: string*/)/*: Promise<Array<string>>*/ => { | |
const files/*: Array<string>*/ = await readDir(dir); | |
return Array.from( | |
new Set( | |
flat( | |
await Promise.all( | |
files | |
.filter(file => file.endsWith('.js')) | |
.map(file => | |
getDepTree(join(dir, file)) | |
) | |
) | |
) | |
) | |
); | |
}; | |
const processDirectory = async (dir/*: string*/)/*: Promise<void>*/ => { | |
console.log(`Process directory ${dir}`); | |
const deps/*: Array<string>*/ = await findDepsInDirectory(join(__dirname, dir)); | |
await Promise.all( | |
deps.map(file => processJsFile(file)) | |
); | |
}; | |
const findBabelHelperDeps = async ()/*: Promise<void>*/ => { | |
console.log('Find all Babel helper imports'); | |
const deps/*: Array<string>*/ = await findDepsInDirectory(join(__dirname, 'DEVICE')); | |
await Promise.all( | |
// If the copy under DEVICE/ already exists the dependency-tree algorithm will find | |
// that file as dependency, if not it will find the version in | |
// <PROJECT_ROOT>/node_modules/@babel/ | |
// We can use that to only copy the file over when it does not already exist, plus, we | |
// need to filter for "@babel" dependencies only in any case, so the filter condition | |
// actually achieves two separate things in a single condition. | |
deps | |
.filter(file => file.startsWith('node_modules/@babel/')) | |
.map(async file => { | |
await mkdir(join(__dirname, 'DEVICE', dirname(file)), {recursive: true}); | |
await copyFile(join(__dirname, file), join(__dirname, 'DEVICE', file)); | |
console.log(`Copied to ${join('DEVICE', file)}`); | |
}) | |
); | |
}; | |
console.log(`Babel version ${babel.version}`); | |
// buildOneForLowJs() | |
// .then(mkdirs) | |
mkdirs() | |
.then(() => processDirectory('src')) | |
.then(findBabelHelperDeps) | |
.catch(console.log); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment