st-bundle
Version:
CLI for watching and bundling SpringType projects.
271 lines (270 loc) • 11 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const path = require("path");
const application_1 = require("../core/application");
const Module_1 = require("../core/Module");
const Package_1 = require("../core/Package");
const resolver_1 = require("../resolver/resolver");
function registerPackage(props) {
const collection = props.ctx.assembleContext.collection;
const resolved = props.resolved;
let pkg = collection.packages.get(resolved.package.meta.name, resolved.package.meta.version);
if (!pkg) {
props.ctx.log.info('assemble package', resolved.package.meta.name + ':' + resolved.package.meta.version);
pkg = Package_1.createPackage({ ctx: props.ctx, meta: resolved.package.meta });
collection.packages.add(pkg);
}
else {
// handle a very rare case where a package that has the same version is located
// in multiple sub_modules
if (resolved.package.meta.packageRoot !== pkg.props.meta.packageRoot) {
if (!pkg.props.meta.packageAltRoots)
pkg.props.meta.packageAltRoots = [];
// this will be used in order to make a fuseBoxPath
pkg.props.meta.packageAltRoots.push(resolved.package.meta.packageRoot);
}
}
// if we have a version conflict we need to notity the parent package
if (!props.pkg.externalPackages.includes(pkg)) {
props.pkg.externalPackages.push(pkg);
}
let target;
if (resolved.package.isEntry && !pkg.entry) {
pkg.entry = Module_1.createModule({
absPath: resolved.package.targetAbsPath,
ctx: props.ctx,
extension: resolved.package.targetExtension,
fuseBoxPath: resolved.package.targetFuseBoxPath,
}, pkg);
target = pkg.entry;
}
else if (!resolved.package.isEntry) {
let userEntry = pkg.userEntries.find(item => item.props.absPath === resolved.package.targetAbsPath);
if (!userEntry) {
userEntry = Module_1.createModule({
absPath: resolved.package.targetAbsPath,
ctx: props.ctx,
extension: resolved.package.targetExtension,
fuseBoxPath: resolved.package.targetFuseBoxPath,
}, pkg);
pkg.userEntries.push(userEntry);
}
target = userEntry;
}
if (target && !target.assembled && props.assemble) {
processModule(Object.assign(Object.assign({}, props), { module: target, pkg: pkg }));
}
return pkg;
}
function resolveStatement(opts, props) {
const collection = props.ctx.assembleContext.collection;
const config = props.ctx.config;
const log = props.ctx.log;
let typescriptPaths = props.pkg.isDefaultPackage && props.ctx.tsConfig.typescriptPaths;
// let's check for custom tsConfig typescript paths here.
if (props.ctx.tsConfigAtPaths && props.pkg.isDefaultPackage) {
// fine a path that's relative to any tsConfig
const typescriptPathsOverride = props.ctx.tsConfigAtPaths.find(item => {
const relativePath = path.relative(item.absPath, props.module.props.absPath);
return !relativePath.startsWith('..');
});
if (typescriptPathsOverride)
typescriptPaths = typescriptPathsOverride.tsConfig.typescriptPaths;
}
const resolved = resolver_1.resolveModule({
isDev: !props.ctx.config.production,
filePath: props.module.props.absPath,
homeDir: config.homeDir,
alias: config.alias,
javascriptFirst: props.module.isJavascriptModule(),
typescriptPaths: typescriptPaths,
packageMeta: !props.pkg.isDefaultPackage && props.pkg.props.meta,
buildTarget: config.target,
modules: config.modules,
importType: opts.importType,
target: opts.statement,
});
if (!resolved || (resolved && resolved.error)) {
if (log.ignoreStatementErrors && log.ignoreStatementErrors.find(re => re.test(opts.statement))) {
return;
}
let shouldIgnoreCaching = true; // will be toggled
log.warn(resolved && resolved.error
? resolved.error + ' / Import statement: "$statement" in <dim>$file</dim>'
: 'Cannot resolve $statement in <dim>$file</dim>', {
statement: opts.statement,
file: props.module.props.absPath,
});
if (shouldIgnoreCaching) {
props.module.errored = true;
}
return;
}
if (resolved.skip || resolved.isExternal) {
return;
}
if (resolved.package) {
// ignoring all dependencies if required
if (props.ctx.config.shoudIgnorePackage(resolved.package.meta.name)) {
return;
}
return {
resolver: resolved,
forcedStatement: resolved.forcedStatement,
package: registerPackage({ assemble: props.assemble, pkg: props.pkg, ctx: props.ctx, resolved: resolved }),
};
}
if (collection.modules.has(resolved.absPath)) {
return {
forcedStatement: resolved.forcedStatement,
processed: true,
module: collection.modules.get(resolved.absPath),
};
}
const _module = Module_1.createModule({
absPath: resolved.absPath,
ctx: props.ctx,
extension: resolved.extension,
fuseBoxPath: resolved.fuseBoxPath,
}, props.pkg);
if (resolved.monorepoModulesPath) {
_module.meta = _module.meta || {};
_module.meta.monorepoModulesPath = resolved.monorepoModulesPath;
}
if (resolved.tsConfigAtPath) {
_module.meta = _module.meta || {};
_module.meta.tsConfigAtPath = resolved.tsConfigAtPath;
// adding ts config to the global context to further resolution can be handled accordingly
props.ctx.addTsConfigAtPath(resolved.tsConfigAtPath);
}
collection.modules.set(resolved.absPath, _module);
return { processed: false, module: _module, forcedStatement: resolved.forcedStatement };
}
function processModule(props) {
const icp = props.ctx.ict;
const _module = props.module;
_module.errored = false;
icp.sync('assemble_module_init', { module: _module });
props.pkg.modules.push(props.module);
if (_module.isExecutable()) {
if (!_module.isCached) {
_module.read();
_module.fastAnalyse();
// temp hack to set jsx analysis based on extension
if (_module.props.extension === '.jsx') {
_module.fastAnalysis.report.containsJSX = true;
}
icp.sync('assemble_fast_analysis', { module: _module });
_module.fastAnalysis.replaceable = [];
// adding extra dependencies
if (props.extraDependencies) {
for (const dep of props.extraDependencies) {
_module.fastAnalysis.imports.push({ type: resolver_1.ImportType.RAW_IMPORT, statement: dep });
}
}
}
}
// local paths (in case of a monorepo wich is toggle by local:main in package.json)
// might have node_modules. That should solved the problem during development
// this path is added to the context to help FuseBox find modules
if (_module.meta && _module.meta.monorepoModulesPath) {
if (props.ctx.config.modules.indexOf(_module.meta.monorepoModulesPath) === -1) {
props.ctx.config.modules.push(_module.meta.monorepoModulesPath);
}
}
_module.assembled = true;
if (_module.fastAnalysis && _module.fastAnalysis.imports) {
const modules = [];
_module.fastAnalysis.imports.forEach(data => {
const response = resolveStatement({ statement: data.statement, importType: data.type }, props);
if (response) {
if (props.ctx.config.production) {
data.link = response;
}
// if (response.module) {
// if (!response.module.moduleDependants) response.module.moduleDependants = [];
// if (response.module.moduleDependants.indexOf(_module) === -1) {
// response.module.moduleDependants.push(_module);
// }
// }
if (response.forcedStatement) {
_module.fastAnalysis.replaceable.push({
type: data.type,
fromStatement: data.statement,
toStatement: response.forcedStatement,
});
}
modules.push(response);
}
});
modules.forEach(item => {
if (item) {
if (item.module) {
props.module.moduleDependencies.push(item.module);
}
if (item.package) {
props.module.externalDependencies.push(item.package);
}
if (item && !item.processed && item.module) {
processModule(Object.assign(Object.assign({}, props), { module: item.module, extraDependencies: undefined }));
}
}
});
}
}
exports.processModule = processModule;
function parseDefaultPackage(ctx, pkg) {
ctx.assembleContext.collection.modules.set(pkg.entry.props.absPath, pkg.entry);
// Production might require tslib so we need to add it here
if (ctx.config.production) {
if (!ctx.config.dependencies.include)
ctx.config.dependencies.include = [];
if (!ctx.config.dependencies.include.includes('tslib')) {
ctx.config.dependencies.include.push('tslib');
}
}
processModule({
ctx: ctx,
pkg: pkg,
module: pkg.entry,
extraDependencies: ctx.config.dependencies.include,
});
}
function assemblePackage(pkg, ctx) {
pkg.externalPackages.forEach(pkg => {
let modules = [...pkg.userEntries];
if (pkg.entry) {
modules.push(pkg.entry);
}
ctx.ict.sync('assemble_package_from_project', {
pkg,
userModules: modules,
assembleContext: ctx.assembleContext,
});
if (!pkg.isCached) {
modules.map(item => {
processModule({
assemble: true,
module: item,
pkg: pkg,
ctx: ctx,
});
});
}
});
}
function assemble(ctx, entryFile) {
// default package. Big Bang starts here/
const pkg = application_1.createApplicationPackage(ctx, entryFile);
if (!pkg)
return;
parseDefaultPackage(ctx, pkg);
assemblePackage(pkg, ctx);
const result = [pkg];
ctx.assembleContext.collection.packages.getAll(pkg => {
result.push(pkg);
});
ctx.packages = result;
return result;
}
exports.assemble = assemble;