refactor: bootstrap
This commit is contained in:
parent
cd62140a32
commit
47a3f19881
|
@ -7,6 +7,7 @@ import {
|
||||||
basename,
|
basename,
|
||||||
dirname,
|
dirname,
|
||||||
extname,
|
extname,
|
||||||
|
isAbsolute,
|
||||||
join,
|
join,
|
||||||
resolve,
|
resolve,
|
||||||
} from 'path';
|
} from 'path';
|
||||||
|
@ -20,6 +21,7 @@ import Flecks from '../flecks';
|
||||||
|
|
||||||
const {
|
const {
|
||||||
FLECKS_CORE_ROOT = process.cwd(),
|
FLECKS_CORE_ROOT = process.cwd(),
|
||||||
|
FLECKS_YML = 'flecks.yml',
|
||||||
} = process.env;
|
} = process.env;
|
||||||
|
|
||||||
const debug = D('@flecks/core/flecks/server');
|
const debug = D('@flecks/core/flecks/server');
|
||||||
|
@ -28,62 +30,10 @@ export default class ServerFlecks extends Flecks {
|
||||||
|
|
||||||
constructor(options = {}) {
|
constructor(options = {}) {
|
||||||
super(options);
|
super(options);
|
||||||
const {
|
this.overrideConfigFromEnvironment();
|
||||||
resolver = {},
|
this.buildConfigs = this.loadBuildConfigs();
|
||||||
rcs = {},
|
this.resolver = options.resolver || {};
|
||||||
} = options;
|
this.rcs = options.rcs || {};
|
||||||
const keys = Object.keys(process.env);
|
|
||||||
// Reverse-sorting means e.g. `@flecks/core/server` comes before `@flecks/core`.
|
|
||||||
// We want to select the most specific match.
|
|
||||||
//
|
|
||||||
// `FLECKS_ENV_FLECKS_CORE_SERVER_VARIABLE` is ambiguous as it can equate to both:
|
|
||||||
// - `flecks.set('@flecks/core.server.variable');`
|
|
||||||
// - `flecks.set('@flecks/core/server.variable');`
|
|
||||||
//
|
|
||||||
// The latter will take precedence.
|
|
||||||
const seen = [];
|
|
||||||
Object.keys(this.flecks)
|
|
||||||
.sort((l, r) => (l < r ? 1 : -1))
|
|
||||||
.forEach((fleck) => {
|
|
||||||
const prefix = `FLECKS_ENV_${this.constructor.environmentalize(fleck)}`;
|
|
||||||
keys
|
|
||||||
.filter((key) => key.startsWith(`${prefix}_`) && -1 === seen.indexOf(key))
|
|
||||||
.map((key) => {
|
|
||||||
seen.push(key);
|
|
||||||
debug('reading environment from %s...', key);
|
|
||||||
return [key, process.env[key]];
|
|
||||||
})
|
|
||||||
.map(([key, value]) => [key.slice(prefix.length + 1), value])
|
|
||||||
.map(([subkey, value]) => [subkey.split('_'), value])
|
|
||||||
.forEach(([path, jsonOrString]) => {
|
|
||||||
try {
|
|
||||||
this.set([fleck, ...path], JSON.parse(jsonOrString));
|
|
||||||
debug('read (%s) as JSON', jsonOrString);
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
this.set([fleck, ...path], jsonOrString);
|
|
||||||
debug('read (%s) as string', jsonOrString);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
this.buildConfigs = Object.fromEntries(
|
|
||||||
Object.entries(this.invoke('@flecks/core.build.config'))
|
|
||||||
.map(([fleck, configs]) => (
|
|
||||||
configs.map((config) => {
|
|
||||||
const defaults = {
|
|
||||||
fleck,
|
|
||||||
root: FLECKS_CORE_ROOT,
|
|
||||||
};
|
|
||||||
if (Array.isArray(config)) {
|
|
||||||
return [config[0], {...defaults, ...config[1]}];
|
|
||||||
}
|
|
||||||
return [config, defaults];
|
|
||||||
})
|
|
||||||
))
|
|
||||||
.flat(),
|
|
||||||
);
|
|
||||||
this.resolver = resolver;
|
|
||||||
this.rcs = rcs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
aliases() {
|
aliases() {
|
||||||
|
@ -115,53 +65,49 @@ export default class ServerFlecks extends Flecks {
|
||||||
|
|
||||||
static bootstrap(
|
static bootstrap(
|
||||||
{
|
{
|
||||||
|
config,
|
||||||
platforms = ['server'],
|
platforms = ['server'],
|
||||||
root = FLECKS_CORE_ROOT,
|
root = FLECKS_CORE_ROOT,
|
||||||
without = [],
|
without = [],
|
||||||
} = {},
|
} = {},
|
||||||
) {
|
) {
|
||||||
const resolvedRoot = resolve(FLECKS_CORE_ROOT, root);
|
// Load or use parameterized configuration.
|
||||||
let initial;
|
|
||||||
let configType;
|
let configType;
|
||||||
try {
|
if (!config) {
|
||||||
const {load} = R('js-yaml');
|
// eslint-disable-next-line no-param-reassign
|
||||||
const filename = join(resolvedRoot, 'build', 'flecks.yml');
|
[configType, config] = this.loadConfig(root);
|
||||||
const buffer = readFileSync(filename, 'utf8');
|
|
||||||
debug('parsing configuration from YML...');
|
|
||||||
initial = load(buffer, {filename}) || {};
|
|
||||||
configType = 'YML';
|
|
||||||
}
|
}
|
||||||
catch (error) {
|
else {
|
||||||
if ('ENOENT' !== error.code) {
|
configType = 'parameter';
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
initial = {'@flecks/core': {}, '@flecks/fleck': {}};
|
|
||||||
configType = 'barebones';
|
|
||||||
}
|
}
|
||||||
debug('bootstrap configuration (%s): %O', configType, initial);
|
debug('bootstrap configuration (%s): %O', configType, config);
|
||||||
// Fleck discovery.
|
// Fleck discovery.
|
||||||
const aliased = {};
|
const resolvedRoot = resolve(FLECKS_CORE_ROOT, root);
|
||||||
const config = {};
|
|
||||||
const resolver = {};
|
const resolver = {};
|
||||||
const keys = Object.keys(initial);
|
const keys = Object.keys(config);
|
||||||
for (let i = 0; i < keys.length; ++i) {
|
for (let i = 0; i < keys.length; ++i) {
|
||||||
const key = keys[i];
|
const key = keys[i];
|
||||||
const index = key.lastIndexOf(':');
|
// Parse the alias (if any).
|
||||||
const [path, alias] = -1 === index ? [key, key] : [key.slice(0, index), key.slice(index + 1)];
|
const index = key.indexOf(':');
|
||||||
|
const [path, alias] = -1 === index
|
||||||
|
? [key, undefined]
|
||||||
|
: [key.slice(0, index), key.slice(index + 1)];
|
||||||
|
// Run it by the exception list.
|
||||||
if (-1 !== without.indexOf(path.split('/').pop())) {
|
if (-1 !== without.indexOf(path.split('/').pop())) {
|
||||||
// eslint-disable-next-line no-continue
|
// eslint-disable-next-line no-continue
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const aliasPath = '.'.charCodeAt(0) === alias.charCodeAt(0)
|
// Resolve the path (if necessary).
|
||||||
? join(resolvedRoot, alias)
|
let resolvedPath;
|
||||||
: alias;
|
if (alias) {
|
||||||
|
resolvedPath = isAbsolute(alias) ? alias : join(resolvedRoot, alias);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resolvedPath = path;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
config[path] = initial[key];
|
R.resolve(resolvedPath);
|
||||||
R.resolve(aliasPath);
|
resolver[path] = resolvedPath;
|
||||||
if (path !== alias) {
|
|
||||||
aliased[path] = aliasPath;
|
|
||||||
}
|
|
||||||
resolver[path] = aliasPath;
|
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line no-empty
|
// eslint-disable-next-line no-empty
|
||||||
catch (error) {}
|
catch (error) {}
|
||||||
|
@ -169,14 +115,9 @@ export default class ServerFlecks extends Flecks {
|
||||||
if (platforms) {
|
if (platforms) {
|
||||||
platforms.forEach((platform) => {
|
platforms.forEach((platform) => {
|
||||||
try {
|
try {
|
||||||
const platformAliasPath = join(aliasPath, platform);
|
const resolvedPlatformPath = join(resolvedPath, platform);
|
||||||
const platformPath = join(path, platform);
|
R.resolve(resolvedPlatformPath);
|
||||||
R.resolve(platformAliasPath);
|
resolver[join(path, platform)] = resolvedPlatformPath;
|
||||||
if (path !== alias) {
|
|
||||||
aliased[platformPath] = platformAliasPath;
|
|
||||||
}
|
|
||||||
config[platformPath] = config[platformPath] || {};
|
|
||||||
resolver[platformPath] = platformAliasPath;
|
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line no-empty
|
// eslint-disable-next-line no-empty
|
||||||
catch (error) {}
|
catch (error) {}
|
||||||
|
@ -184,86 +125,65 @@ export default class ServerFlecks extends Flecks {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const paths = Object.keys(resolver);
|
const paths = Object.keys(resolver);
|
||||||
const rcs = {};
|
// Load RCs.
|
||||||
const roots = Array.from(new Set(
|
const rcs = this.loadRcs(resolver);
|
||||||
paths
|
|
||||||
.map((path) => this.root(resolver, path))
|
|
||||||
.filter((e) => !!e),
|
|
||||||
));
|
|
||||||
for (let i = 0; i < roots.length; ++i) {
|
|
||||||
const root = roots[i];
|
|
||||||
try {
|
|
||||||
rcs[root] = R(join(root, 'build', '.flecksrc'));
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
if ('MODULE_NOT_FOUND' !== error.code) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
debug('rcs: %O', rcs);
|
debug('rcs: %O', rcs);
|
||||||
// Stub platform-unfriendly modules.
|
// Merge aliases;
|
||||||
const stubs = this.stubs(platforms, rcs);
|
const aliases = {
|
||||||
|
// from fleck configuration above,
|
||||||
|
...(
|
||||||
|
Object.fromEntries(
|
||||||
|
Object.entries(resolver)
|
||||||
|
.filter(([from, to]) => from !== to),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
// from symlinks,
|
||||||
|
...(
|
||||||
|
Object.fromEntries(
|
||||||
|
paths.filter((path) => this.fleckIsSymlinked(resolver, path))
|
||||||
|
.map((path) => [path, this.sourcepath(R.resolve(this.resolve(resolver, path)))]),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
// and from RCs.
|
||||||
|
...this.aliases(rcs),
|
||||||
|
};
|
||||||
|
if (Object.keys(aliases).length > 0) {
|
||||||
|
debug('aliases: %O', aliases);
|
||||||
|
}
|
||||||
|
// Stub server-unfriendly modules.
|
||||||
|
const stubs = this.stubs(['server'], rcs);
|
||||||
if (stubs.length > 0) {
|
if (stubs.length > 0) {
|
||||||
debug('stubbing: %O', stubs);
|
debug('stubbing: %O', stubs);
|
||||||
const regex = new RegExp(stubs.join('|'));
|
}
|
||||||
R('pirates').addHook(
|
// Do we need to get up in `require()`'s guts?
|
||||||
() => '',
|
if (
|
||||||
{
|
Object.keys(aliases).length > 0
|
||||||
ignoreNodeModules: false,
|
|| stubs.length > 0
|
||||||
matcher: (path) => !!path.match(regex),
|
) {
|
||||||
},
|
const {Module} = R('module');
|
||||||
);
|
const {require: Mr} = Module.prototype;
|
||||||
|
Module.prototype.require = function hackedRequire(request, options) {
|
||||||
|
if (-1 !== stubs.indexOf(request)) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (aliases[request]) {
|
||||||
|
return Mr.call(this, aliases[request], options);
|
||||||
|
}
|
||||||
|
return Mr.call(this, request, options);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
// Flecks that are aliased or symlinked need compilation.
|
// Flecks that are aliased or symlinked need compilation.
|
||||||
const flecks = {};
|
const flecks = {};
|
||||||
const needCompilation = paths
|
const needCompilation = paths
|
||||||
.filter((path) => (
|
.filter((path) => (
|
||||||
this.fleckIsAliased(resolver, path) || this.fleckIsSymlinked(resolver, path)
|
this.fleckIsAliased(resolver, path)
|
||||||
|
|| this.fleckIsSymlinked(resolver, path)
|
||||||
));
|
));
|
||||||
// Lookups redirect require() requests.
|
|
||||||
const symlinked = paths
|
|
||||||
.filter((path) => this.fleckIsSymlinked(resolver, path));
|
|
||||||
if (symlinked.length > 0) {
|
|
||||||
const lookups = {
|
|
||||||
...Object.fromEntries(
|
|
||||||
symlinked
|
|
||||||
.map((path) => [
|
|
||||||
R.resolve(path),
|
|
||||||
this.sourcepath(R.resolve(this.resolve(resolver, path))),
|
|
||||||
]),
|
|
||||||
),
|
|
||||||
};
|
|
||||||
debug('symlink lookups: %O', lookups);
|
|
||||||
R('pirates').addHook(
|
|
||||||
(code, path) => `module.exports = require('${lookups[path]}')`,
|
|
||||||
{
|
|
||||||
ignoreNodeModules: false,
|
|
||||||
// eslint-disable-next-line arrow-body-style
|
|
||||||
matcher: (path) => {
|
|
||||||
return !!lookups[path];
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const {Module} = R('module');
|
|
||||||
const aliases = this.aliases(rcs);
|
|
||||||
debug('aliases: %O', aliases);
|
|
||||||
// Nasty hax to give us FULL CONTROL.
|
|
||||||
const {require: Mr} = Module.prototype;
|
|
||||||
const requirers = {
|
|
||||||
...aliased,
|
|
||||||
...aliases,
|
|
||||||
};
|
|
||||||
Module.prototype.require = function hackedRequire(request, options) {
|
|
||||||
if (requirers[request]) {
|
|
||||||
return Mr.call(this, requirers[request], options);
|
|
||||||
}
|
|
||||||
return Mr.call(this, request, options);
|
|
||||||
};
|
|
||||||
if (needCompilation.length > 0) {
|
if (needCompilation.length > 0) {
|
||||||
const rcBabel = this.babel(rcs);
|
const register = R('@babel/register');
|
||||||
debug('.flecksrc: babel: %O', rcBabel);
|
// Augment the compiler with babel config from flecksrc.
|
||||||
|
const rcBabelConfig = babelmerge(...this.babel(rcs).map(([, babel]) => babel));
|
||||||
|
debug('.flecksrc: babel: %O', rcBabelConfig);
|
||||||
// Key flecks needing compilation by their roots, so we can compile all common roots with a
|
// Key flecks needing compilation by their roots, so we can compile all common roots with a
|
||||||
// single invocation of `@babel/register`.
|
// single invocation of `@babel/register`.
|
||||||
const compilationRootMap = {};
|
const compilationRootMap = {};
|
||||||
|
@ -276,9 +196,14 @@ export default class ServerFlecks extends Flecks {
|
||||||
});
|
});
|
||||||
// Register a compiler for each root and require() the flecks underneath.
|
// Register a compiler for each root and require() the flecks underneath.
|
||||||
Object.entries(compilationRootMap).forEach(([root, compiling]) => {
|
Object.entries(compilationRootMap).forEach(([root, compiling]) => {
|
||||||
debug('compiling: %s', root);
|
debug('compiling at root: %s', root);
|
||||||
const resolved = dirname(R.resolve(join(root, 'package.json')));
|
const resolved = dirname(R.resolve(join(root, 'package.json')));
|
||||||
const sourcepath = this.sourcepath(resolved);
|
const sourcepath = this.sourcepath(resolved);
|
||||||
|
const sourceroot = join(sourcepath, '..');
|
||||||
|
// Load babel config from whichever we find first:
|
||||||
|
// - The fleck being compiled's build directory
|
||||||
|
// - The root build directory
|
||||||
|
// - Finally, the built-in babel config
|
||||||
const configFile = this.resolveBuildConfig(
|
const configFile = this.resolveBuildConfig(
|
||||||
resolver,
|
resolver,
|
||||||
[
|
[
|
||||||
|
@ -290,71 +215,26 @@ export default class ServerFlecks extends Flecks {
|
||||||
'babel.config.js',
|
'babel.config.js',
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
const register = R('@babel/register');
|
|
||||||
const config = {
|
const config = {
|
||||||
|
// Augment the selected config with the babel config from RCs.
|
||||||
configFile,
|
configFile,
|
||||||
// Augment the compiler with babel config from flecksrc.
|
// Target the compiler to avoid unnecessary work.
|
||||||
...babelmerge(...rcBabel.map(([, babel]) => babel)),
|
ignore: [resolve(join(sourceroot, 'node_modules'))],
|
||||||
ignore: [resolve(join(sourcepath, '..', 'node_modules'))],
|
only: [resolve(sourceroot)],
|
||||||
only: [resolve(join(sourcepath, '..'))],
|
|
||||||
sourceMaps: 'inline',
|
|
||||||
};
|
};
|
||||||
debug("require('@babel/register')(%O)", config);
|
debug("require('@babel/register')(%O)", config);
|
||||||
register({
|
register({
|
||||||
...config,
|
...config,
|
||||||
|
...rcBabelConfig,
|
||||||
// Make webpack goodies exist in nodespace.
|
// Make webpack goodies exist in nodespace.
|
||||||
plugins: [
|
plugins: this.nodespaceBabelPlugins(),
|
||||||
[
|
// Keep things debuggable.
|
||||||
'prepend',
|
sourceMaps: 'inline',
|
||||||
{
|
|
||||||
prepend: [
|
|
||||||
'require.context = (',
|
|
||||||
' directory,',
|
|
||||||
' useSubdirectories = true,',
|
|
||||||
' regExp = /^\\.\\/.*$/,',
|
|
||||||
' mode = "sync",',
|
|
||||||
') => {',
|
|
||||||
' const glob = require("glob");',
|
|
||||||
' const {resolve, sep} = require("path");',
|
|
||||||
' const keys = glob.sync(',
|
|
||||||
' useSubdirectories ? "**/*" : "*",',
|
|
||||||
' {cwd: resolve(__dirname, directory)},',
|
|
||||||
' )',
|
|
||||||
' .filter((key) => key.match(regExp))',
|
|
||||||
' .map(',
|
|
||||||
' (key) => (',
|
|
||||||
' -1 !== [".".charCodeAt(0), "/".charCodeAt(0)].indexOf(key.charCodeAt(0))',
|
|
||||||
' ? key',
|
|
||||||
' : ("." + sep + key)',
|
|
||||||
' ),',
|
|
||||||
' );',
|
|
||||||
' const R = (request) => require(keys[request]);',
|
|
||||||
' R.id = __filename',
|
|
||||||
' R.keys = () => keys;',
|
|
||||||
' return R;',
|
|
||||||
'};',
|
|
||||||
].join('\n'),
|
|
||||||
},
|
|
||||||
'require.context',
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'prepend',
|
|
||||||
{
|
|
||||||
prepend: 'const __non_webpack_require__ = require;',
|
|
||||||
},
|
|
||||||
'__non_webpack_require__',
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'prepend',
|
|
||||||
{
|
|
||||||
prepend: "require('source-map-support/register');",
|
|
||||||
},
|
|
||||||
'source-map-support',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
compiling.forEach((fleck) => {
|
compiling.forEach((fleck) => {
|
||||||
|
debug('compiling %s...', fleck);
|
||||||
flecks[fleck] = R(this.resolve(resolver, fleck));
|
flecks[fleck] = R(this.resolve(resolver, fleck));
|
||||||
|
debug('compiled');
|
||||||
// Remove the required fleck from the list still needing require().
|
// Remove the required fleck from the list still needing require().
|
||||||
paths.splice(paths.indexOf(fleck), 1);
|
paths.splice(paths.indexOf(fleck), 1);
|
||||||
});
|
});
|
||||||
|
@ -419,6 +299,152 @@ export default class ServerFlecks extends Flecks {
|
||||||
return realpath !== resolved;
|
return realpath !== resolved;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadBuildConfigs() {
|
||||||
|
return Object.fromEntries(
|
||||||
|
Object.entries(this.invoke('@flecks/core.build.config'))
|
||||||
|
.map(([fleck, configs]) => (
|
||||||
|
configs.map((config) => {
|
||||||
|
const defaults = {
|
||||||
|
fleck,
|
||||||
|
root: FLECKS_CORE_ROOT,
|
||||||
|
};
|
||||||
|
if (Array.isArray(config)) {
|
||||||
|
return [config[0], {...defaults, ...config[1]}];
|
||||||
|
}
|
||||||
|
return [config, defaults];
|
||||||
|
})
|
||||||
|
))
|
||||||
|
.flat(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static loadConfig(root) {
|
||||||
|
const resolvedRoot = resolve(FLECKS_CORE_ROOT, root);
|
||||||
|
try {
|
||||||
|
const {load} = R('js-yaml');
|
||||||
|
const filename = join(resolvedRoot, 'build', FLECKS_YML);
|
||||||
|
const buffer = readFileSync(filename, 'utf8');
|
||||||
|
debug('parsing configuration from YML...');
|
||||||
|
return ['YML', load(buffer, {filename}) || {}];
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
if ('ENOENT' !== error.code) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
return ['barebones', {'@flecks/core': {}, '@flecks/fleck': {}}];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static loadRcs(resolver) {
|
||||||
|
const rcs = {};
|
||||||
|
const roots = Array.from(new Set(
|
||||||
|
Object.keys(resolver)
|
||||||
|
.map((path) => this.root(resolver, path))
|
||||||
|
.filter((e) => !!e),
|
||||||
|
));
|
||||||
|
for (let i = 0; i < roots.length; ++i) {
|
||||||
|
const root = roots[i];
|
||||||
|
try {
|
||||||
|
rcs[root] = R(join(root, 'build', '.flecksrc'));
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
if ('MODULE_NOT_FOUND' !== error.code) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rcs;
|
||||||
|
}
|
||||||
|
|
||||||
|
static nodespaceBabelPlugins() {
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
'prepend',
|
||||||
|
{
|
||||||
|
prepend: [
|
||||||
|
'require.context = (',
|
||||||
|
' directory,',
|
||||||
|
' useSubdirectories = true,',
|
||||||
|
' regExp = /^\\.\\/.*$/,',
|
||||||
|
' mode = "sync",',
|
||||||
|
') => {',
|
||||||
|
' const glob = require("glob");',
|
||||||
|
' const {resolve, sep} = require("path");',
|
||||||
|
' const keys = glob.sync(',
|
||||||
|
' useSubdirectories ? "**/*" : "*",',
|
||||||
|
' {cwd: resolve(__dirname, directory)},',
|
||||||
|
' )',
|
||||||
|
' .filter((key) => key.match(regExp))',
|
||||||
|
' .map(',
|
||||||
|
' (key) => (',
|
||||||
|
' -1 !== [".".charCodeAt(0), "/".charCodeAt(0)].indexOf(key.charCodeAt(0))',
|
||||||
|
' ? key',
|
||||||
|
' : ("." + sep + key)',
|
||||||
|
' ),',
|
||||||
|
' );',
|
||||||
|
' const R = (request) => require(keys[request]);',
|
||||||
|
' R.id = __filename',
|
||||||
|
' R.keys = () => keys;',
|
||||||
|
' return R;',
|
||||||
|
'};',
|
||||||
|
].join('\n'),
|
||||||
|
},
|
||||||
|
'require.context',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'prepend',
|
||||||
|
{
|
||||||
|
prepend: 'const __non_webpack_require__ = require;',
|
||||||
|
},
|
||||||
|
'__non_webpack_require__',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'prepend',
|
||||||
|
{
|
||||||
|
prepend: "require('source-map-support/register');",
|
||||||
|
},
|
||||||
|
'source-map-support',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
overrideConfigFromEnvironment() {
|
||||||
|
const keys = Object.keys(process.env);
|
||||||
|
const seen = [];
|
||||||
|
Object.keys(this.flecks)
|
||||||
|
// Reverse-sorting means e.g. `@flecks/core/server` comes before `@flecks/core`.
|
||||||
|
// We want to select the most specific match.
|
||||||
|
//
|
||||||
|
// `FLECKS_ENV_FLECKS_CORE_SERVER_VARIABLE` is ambiguous as it can equate to both:
|
||||||
|
// - `flecks.set('@flecks/core.server.variable');`
|
||||||
|
// - `flecks.set('@flecks/core/server.variable');`
|
||||||
|
//
|
||||||
|
// The latter will take precedence.
|
||||||
|
.sort((l, r) => (l < r ? 1 : -1))
|
||||||
|
.forEach((fleck) => {
|
||||||
|
const prefix = `FLECKS_ENV_${this.constructor.environmentalize(fleck)}`;
|
||||||
|
keys
|
||||||
|
.filter((key) => key.startsWith(`${prefix}_`) && -1 === seen.indexOf(key))
|
||||||
|
.map((key) => {
|
||||||
|
seen.push(key);
|
||||||
|
debug('reading environment from %s...', key);
|
||||||
|
return [key, process.env[key]];
|
||||||
|
})
|
||||||
|
.map(([key, value]) => [key.slice(prefix.length + 1), value])
|
||||||
|
.map(([subkey, value]) => [subkey.split('_'), value])
|
||||||
|
.forEach(([path, jsonOrString]) => {
|
||||||
|
try {
|
||||||
|
this.set([fleck, ...path], JSON.parse(jsonOrString));
|
||||||
|
debug('read (%s) as JSON', jsonOrString);
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
this.set([fleck, ...path], jsonOrString);
|
||||||
|
debug('read (%s) as string', jsonOrString);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
rcs() {
|
rcs() {
|
||||||
return this.rcs;
|
return this.rcs;
|
||||||
}
|
}
|
||||||
|
@ -519,6 +545,7 @@ export default class ServerFlecks extends Flecks {
|
||||||
.forEach((root) => {
|
.forEach((root) => {
|
||||||
const resolved = dirname(R.resolve(join(root, 'package.json')));
|
const resolved = dirname(R.resolve(join(root, 'package.json')));
|
||||||
const sourcepath = this.sourcepath(resolved);
|
const sourcepath = this.sourcepath(resolved);
|
||||||
|
const sourceroot = join(sourcepath, '..');
|
||||||
const configFile = this.buildConfig('babel.config.js');
|
const configFile = this.buildConfig('babel.config.js');
|
||||||
debug('compiling: %s with %s', root, configFile);
|
debug('compiling: %s with %s', root, configFile);
|
||||||
const babel = {
|
const babel = {
|
||||||
|
@ -527,8 +554,8 @@ export default class ServerFlecks extends Flecks {
|
||||||
...babelmerge(...rcBabel.map(([, babel]) => babel)),
|
...babelmerge(...rcBabel.map(([, babel]) => babel)),
|
||||||
};
|
};
|
||||||
compileLoader({
|
compileLoader({
|
||||||
ignore: [join(sourcepath, '..')],
|
ignore: [sourceroot],
|
||||||
include: [join(sourcepath, '..')],
|
include: [sourceroot],
|
||||||
babel,
|
babel,
|
||||||
ruleId: `@flecks/${runtime}/runtime/compile[${root}]`,
|
ruleId: `@flecks/${runtime}/runtime/compile[${root}]`,
|
||||||
})(neutrino);
|
})(neutrino);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user