refactor: deterministic monorepo

This commit is contained in:
cha0s 2024-02-03 20:31:35 -06:00
parent 64e1d179c7
commit 8a47341cb6
46 changed files with 20689 additions and 197 deletions

25
.github/workflows/verify.yml vendored Normal file
View File

@ -0,0 +1,25 @@
name: CI
on:
push:
branches: [ $default-branch ]
pull_request:
branches: [ $default-branch ]
jobs:
verify:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x, 20.x]
steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ${{ vars.NPM_CI_FLAGS }} ci
- run: npm run lint
- run: npm run test
- run: npm run build

2
.gitignore vendored
View File

@ -127,4 +127,4 @@ dist
/dox /dox
/dox-tmp /dox-tmp
/.nx/cache /.actrc

View File

@ -1,4 +1,4 @@
{ {
"eslint.workingDirectories": [{"pattern": "./packages/*"}], "eslint.workingDirectories": [{"pattern": "./packages/*"}],
"eslint.options": {"overrideConfigFile": "../build/dist/build/eslint.config.js"}, "eslint.options": {"overrideConfigFile": "../build/build/eslint.config.js"},
} }

View File

@ -1,10 +1,10 @@
'@flecks/build': {} '@flecks/build': {}
'@flecks/core:./packages/core': {} '@flecks/core': {}
'@flecks/create:./packages/create-app': {} '@flecks/create-app': {}
'@flecks/create:./packages/create-fleck': {} '@flecks/create-fleck': {}
'@flecks/db:./packages/db': {} '@flecks/db': {}
'@flecks/docker:./packages/docker': {} '@flecks/docker': {}
'@flecks/dox:./packages/dox': '@flecks/dox':
rewriteFilenames: rewriteFilenames:
- -
- '@flecks\/([^/]+)\/(.*)' - '@flecks\/([^/]+)\/(.*)'
@ -12,18 +12,18 @@
- -
- '\((.*):([0-9]+):[0-9]+\)' - '\((.*):([0-9]+):[0-9]+\)'
- '($1#L$2)' - '($1#L$2)'
'@flecks/electron:./packages/electron': {} '@flecks/electron': {}
'@flecks/fleck:./packages/fleck': {} '@flecks/fleck': {}
'@flecks/passport:./packages/passport': {} '@flecks/passport': {}
'@flecks/passport-local:./packages/passport-local': {} '@flecks/passport-local': {}
'@flecks/passport-local-react:./packages/passport-local-react': {} '@flecks/passport-local-react': {}
'@flecks/passport-react:./packages/passport-react': {} '@flecks/passport-react': {}
'@flecks/react:./packages/react': {} '@flecks/react': {}
'@flecks/react:./packages/react-redux': {} '@flecks/react-redux': {}
'@flecks/redis:./packages/redis': {} '@flecks/redis': {}
'@flecks/redux:./packages/redux': {} '@flecks/redux': {}
'@flecks/repl:./packages/repl': {} '@flecks/repl': {}
'@flecks/server:./packages/server': {} '@flecks/server': {}
'@flecks/session:./packages/session': {} '@flecks/session': {}
'@flecks/socket:./packages/socket': {} '@flecks/socket': {}
'@flecks/web:./packages/web': {} '@flecks/web': {}

View File

@ -1,6 +1,4 @@
{ {
"packages": [ "useNx": true,
"packages/*"
],
"version": "3.2.4" "version": "3.2.4"
} }

3
nx.json Normal file
View File

@ -0,0 +1,3 @@
{
"cacheDirectory": "node_modules/.cache/nx"
}

20319
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -18,7 +18,10 @@
"test": "lerna run test" "test": "lerna run test"
}, },
"devDependencies": { "devDependencies": {
"@flecks/build": "^3.1.3", "husky": "^9.0.7",
"lerna": "^8.0.2" "lerna": "^8.0.2"
} },
"workspaces": [
"packages/*"
]
} }

View File

@ -9,6 +9,7 @@ const loadConfig = require('./load-config');
const Resolver = require('./resolver'); const Resolver = require('./resolver');
const { const {
FLECKS_CORE_BUILD_LIST = '',
FLECKS_CORE_ROOT = process.cwd(), FLECKS_CORE_ROOT = process.cwd(),
} = process.env; } = process.env;
@ -36,6 +37,13 @@ module.exports = class Build extends Flecks {
]); ]);
} }
static get buildList() {
return FLECKS_CORE_BUILD_LIST
.split(',')
.map((name) => name.trim())
.filter((e) => e);
}
static async buildRuntime(originalConfig, platforms, flecks = {}) { static async buildRuntime(originalConfig, platforms, flecks = {}) {
const cleanConfig = JSON.parse(JSON.stringify(originalConfig)); const cleanConfig = JSON.parse(JSON.stringify(originalConfig));
// Dealias the config keys. // Dealias the config keys.

View File

@ -1,7 +1,7 @@
#!/usr/bin/env node #!/usr/bin/env node
const D = require('@flecks/core/build/debug'); const D = require('@flecks/core/build/debug');
const {processCode} = require('@flecks/core/server'); const {processCode} = require('@flecks/core/src/server');
const {Command} = require('commander'); const {Command} = require('commander');
const Build = require('./build'); const Build = require('./build');

View File

@ -20,7 +20,7 @@ const {
add, add,
lockFile, lockFile,
spawnWith, spawnWith,
} = require('@flecks/core/server'); } = require('@flecks/core/src/server');
const {glob} = require('glob'); const {glob} = require('glob');
const rimraf = require('rimraf'); const rimraf = require('rimraf');
@ -178,7 +178,7 @@ exports.commands = (program, flecks) => {
debug('Building...', opts); debug('Building...', opts);
const webpackConfig = await flecks.resolveBuildConfig('fleckspack.config.js'); const webpackConfig = await flecks.resolveBuildConfig('fleckspack.config.js');
const cmd = [ const cmd = [
join(FLECKS_CORE_ROOT, 'node_modules', '.bin', 'webpack'), 'npx', 'webpack',
'--config', webpackConfig, '--config', webpackConfig,
'--mode', (production && !hot) ? 'production' : 'development', '--mode', (production && !hot) ? 'production' : 'development',
...((watch || hot) ? ['--watch'] : []), ...((watch || hot) ? ['--watch'] : []),
@ -210,7 +210,7 @@ exports.commands = (program, flecks) => {
.map((pkg) => join(process.cwd(), pkg)) .map((pkg) => join(process.cwd(), pkg))
.map(async (cwd) => { .map(async (cwd) => {
const cmd = [ const cmd = [
join(FLECKS_CORE_ROOT, 'node_modules', '.bin', 'eslint'), 'npx', 'eslint',
'--config', await flecks.resolveBuildConfig('eslint.config.js'), '--config', await flecks.resolveBuildConfig('eslint.config.js'),
'.', '.',
]; ];
@ -219,7 +219,10 @@ exports.commands = (program, flecks) => {
cmd, cmd,
{ {
cwd, cwd,
env: {FLECKS_CORE_ROOT}, env: {
FLECKS_BUILD_ESLINT_NO_CACHE: true,
FLECKS_CORE_ROOT,
},
}, },
); );
child.on('error', reject); child.on('error', reject);

View File

@ -0,0 +1,102 @@
const {dirname, join} = require('path');
const {glob} = require('glob');
const {defaultConfig, regexFromExtensions} = require('./webpack');
const {
FLECKS_CORE_ROOT = process.cwd(),
} = process.env;
const source = join(FLECKS_CORE_ROOT, 'src');
const tests = join(FLECKS_CORE_ROOT, 'test');
async function makeMonorepoResolve() {
const resolve = {alias: {}, fallback: {}};
const parts = FLECKS_CORE_ROOT.split('/');
while (parts.length > 1) {
parts.pop();
try {
const candidate = join(parts.join('/'), 'package.json');
const {workspaces} = require(candidate);
if (Array.isArray(workspaces)) {
// eslint-disable-next-line no-await-in-loop
const workspacePaths = await Promise.all(
workspaces.map((workspace) => glob(join(dirname(candidate), workspace))),
);
workspacePaths
.flat()
.forEach((path) => {
const {name} = require(join(path, 'package.json'));
resolve.alias[name] = join(path, 'src');
resolve.fallback[name] = path;
});
}
}
// eslint-disable-next-line no-empty
catch (error) {}
}
return resolve;
}
module.exports = async (env, argv, flecks) => {
const {name} = require(join(FLECKS_CORE_ROOT, 'package.json'));
const resolve = await makeMonorepoResolve();
const config = defaultConfig(flecks, {
node: {
__dirname: false,
__filename: false,
},
optimization: {
splitChunks: false,
runtimeChunk: false,
},
output: {
filename: '[name].js',
library: {
name,
type: 'umd',
umdNamedDefine: true,
},
},
plugins: [],
resolve: {
alias: {
[name]: source,
...resolve.alias,
...flecks.resolver.aliases,
},
fallback: {
[name]: FLECKS_CORE_ROOT,
...resolve.fallback,
...flecks.resolver.fallbacks,
},
modules: ['node_modules'],
},
stats: {
colors: true,
errorDetails: true,
},
target: 'node',
});
const babelConfig = await flecks.babel();
const extensionsRegex = regexFromExtensions(config.resolve.extensions);
config.module.rules.push(
{
include: [source, tests],
test: extensionsRegex,
use: [
{
loader: 'babel-loader',
options: {
cacheDirectory: true,
babelrc: false,
configFile: false,
...babelConfig,
},
},
],
},
);
return config;
};

View File

@ -14,6 +14,7 @@ const Build = require('./build');
const debug = D('@flecks/build/build/eslint.config.js'); const debug = D('@flecks/build/build/eslint.config.js');
const { const {
FLECKS_BUILD_ESLINT_NO_CACHE,
FLECKS_CORE_ROOT = process.cwd(), FLECKS_CORE_ROOT = process.cwd(),
FLECKS_CORE_SYNC_FOR_ESLINT = false, FLECKS_CORE_SYNC_FOR_ESLINT = false,
} = process.env; } = process.env;
@ -44,6 +45,9 @@ else {
// Check cache first. // Check cache first.
const cacheDirectory = join(FLECKS_CORE_ROOT, 'node_modules', '.cache', '@flecks', 'build'); const cacheDirectory = join(FLECKS_CORE_ROOT, 'node_modules', '.cache', '@flecks', 'build');
try { try {
if (FLECKS_BUILD_ESLINT_NO_CACHE) {
throw new Error();
}
statSync(join(cacheDirectory, 'eslint.config.json')); statSync(join(cacheDirectory, 'eslint.config.json'));
module.exports = JSON.parse(readFileSync(join(cacheDirectory, 'eslint.config.json')).toString()); module.exports = JSON.parse(readFileSync(join(cacheDirectory, 'eslint.config.json')).toString());
} }
@ -62,7 +66,6 @@ else {
const json = stdout.toString(); const json = stdout.toString();
try { try {
const parsed = JSON.parse(json); const parsed = JSON.parse(json);
statSync(join(FLECKS_CORE_ROOT, 'node_modules'));
mkdirSync(cacheDirectory, {recursive: true}); mkdirSync(cacheDirectory, {recursive: true});
// Cache. // Cache.
writeFileSync(join(cacheDirectory, 'eslint.config.json'), json); writeFileSync(join(cacheDirectory, 'eslint.config.json'), json);

View File

@ -6,16 +6,15 @@ const {
} = require('path'); } = require('path');
const CopyPlugin = require('copy-webpack-plugin'); const CopyPlugin = require('copy-webpack-plugin');
const glob = require('glob');
const {defaultConfig, externals, regexFromExtensions} = require('./webpack'); const configFn = require('./common.webpack.config');
const {externals} = require('./webpack');
const { const {
FLECKS_CORE_ROOT = process.cwd(), FLECKS_CORE_ROOT = process.cwd(),
} = process.env; } = process.env;
const source = join(FLECKS_CORE_ROOT, 'src'); const source = join(FLECKS_CORE_ROOT, 'src');
const tests = join(FLECKS_CORE_ROOT, 'test');
const resolveValidModulePath = (source) => (path) => { const resolveValidModulePath = (source) => (path) => {
// Does the file resolve as source? // Does the file resolve as source?
@ -36,79 +35,31 @@ const resolveValidModulePath = (source) => (path) => {
}; };
module.exports = async (env, argv, flecks) => { module.exports = async (env, argv, flecks) => {
const {name, files = []} = require(join(FLECKS_CORE_ROOT, 'package.json')); const config = await configFn(env, argv, flecks);
const config = defaultConfig(flecks, { config.externals = await externals();
externals: externals({importType: 'umd'}), config.output.clean = {keep: /test\.js(?:\.map)?/};
node: { config.plugins.push(
__dirname: false, new CopyPlugin({
__filename: false, patterns: [
},
optimization: {
splitChunks: false,
runtimeChunk: false,
},
output: {
filename: '[name].js',
library: {
name,
type: 'umd',
umdNamedDefine: true,
},
},
plugins: [
new CopyPlugin({
patterns: [
{
from: '.',
to: '.',
globOptions: {
dot: true,
ignore: [
'dist',
'node_modules',
],
gitignore: true,
},
info: {
minimized: true,
},
},
],
}),
],
resolve: {
alias: {
[name]: source,
},
fallback: {
[name]: FLECKS_CORE_ROOT,
},
},
stats: {
colors: true,
errorDetails: true,
},
target: 'node',
});
const babelConfig = await flecks.babel();
const extensionsRegex = regexFromExtensions(config.resolve.extensions);
config.module.rules.push(
{
include: [source, tests],
test: extensionsRegex,
use: [
{ {
loader: 'babel-loader', from: '.',
options: { to: '.',
cacheDirectory: true, globOptions: {
babelrc: false, dot: true,
configFile: false, ignore: [
...babelConfig, 'dist',
'node_modules',
],
gitignore: true,
},
info: {
minimized: true,
}, },
}, },
], ],
}, }),
); );
const {files = []} = require(join(FLECKS_CORE_ROOT, 'package.json'));
// Automatic entry registration. // Automatic entry registration.
files files
.filter(resolveValidModulePath(source)) .filter(resolveValidModulePath(source))
@ -116,14 +67,5 @@ module.exports = async (env, argv, flecks) => {
const trimmed = join(dirname(file), basename(file, extname(file))); const trimmed = join(dirname(file), basename(file, extname(file)));
config.entry[trimmed] = `${source}/${trimmed}`; config.entry[trimmed] = `${source}/${trimmed}`;
}); });
// Test entry.
const testPaths = glob.sync(join(tests, '*.js'));
const {platforms} = flecks;
for (let i = 0; i < platforms.length; ++i) {
testPaths.push(...glob.sync(join(tests, platforms[i], '*.js')));
}
if (testPaths.length > 0) {
config.entry.test = ['source-map-support/register', ...testPaths];
}
return config; return config;
}; };

View File

@ -4,6 +4,7 @@ const webpack = require('webpack');
const {commands} = require('./commands'); const {commands} = require('./commands');
const {ProcessAssets} = require('./process-assets'); const {ProcessAssets} = require('./process-assets');
const {externals} = require('./webpack');
const { const {
FLECKS_CORE_ROOT = process.cwd(), FLECKS_CORE_ROOT = process.cwd(),
@ -25,6 +26,13 @@ exports.hooks = {
} }
config.plugins.push(new ProcessAssets(target, flecks)); config.plugins.push(new ProcessAssets(target, flecks));
}, },
'@flecks/build.config.alter': async ({test}) => {
if (test) {
test.externals = await externals({
allowlist: Object.keys(test.resolve.fallback).map((fallback) => new RegExp(fallback)),
});
}
},
'@flecks/build.files': () => [ '@flecks/build.files': () => [
/** /**
* Babel configuration. See: https://babeljs.io/docs/en/config-files * Babel configuration. See: https://babeljs.io/docs/en/config-files
@ -44,9 +52,13 @@ exports.hooks = {
*/ */
'fleckspack.config.js', 'fleckspack.config.js',
/** /**
* Fleck build configuration. See: https://webpack.js.org/configuration/ * Fleck source build configuration. See: https://webpack.js.org/configuration/
*/ */
'fleck.webpack.config.js', 'fleck.webpack.config.js',
/**
* Fleck test build configuration. See: https://webpack.js.org/configuration/
*/
'test.webpack.config.js',
], ],
'@flecks/core.config': () => ({ '@flecks/core.config': () => ({
/** /**

View File

@ -6,14 +6,7 @@ const Build = require('./build');
const debug = D('@flecks/build/build/fleckspack.config.js'); const debug = D('@flecks/build/build/fleckspack.config.js');
const { const {buildList} = Build;
FLECKS_CORE_BUILD_LIST = '',
} = process.env;
const buildList = FLECKS_CORE_BUILD_LIST
.split(',')
.map((name) => name.trim())
.filter((e) => e);
module.exports = async (env, argv) => { module.exports = async (env, argv) => {
debug('bootstrapping flecks...'); debug('bootstrapping flecks...');

View File

@ -0,0 +1,28 @@
const {join} = require('path');
const {glob} = require('glob');
const configFn = require('./common.webpack.config');
const {
FLECKS_CORE_ROOT = process.cwd(),
} = process.env;
const tests = join(FLECKS_CORE_ROOT, 'test');
module.exports = async (env, argv, flecks) => {
const config = await configFn(env, argv, flecks);
config.output.chunkFormat = false;
config.output.clean = false;
// Test entry.
const testPaths = await glob(join(tests, '*.js'));
const {platforms} = flecks;
testPaths.push(
...(await Promise.all(platforms.map((platform) => glob(join(tests, platform, '*.js')))))
.flat(),
);
if (testPaths.length > 0) {
config.entry.test = ['source-map-support/register', ...testPaths];
}
return config;
};

View File

@ -1,4 +1,4 @@
const {chmod} = require('fs'); const {access, chmod} = require('fs/promises');
const {join} = require('path'); const {join} = require('path');
const CopyPlugin = require('copy-webpack-plugin'); const CopyPlugin = require('copy-webpack-plugin');
@ -94,18 +94,47 @@ exports.executable = () => (
// eslint-disable-next-line class-methods-use-this // eslint-disable-next-line class-methods-use-this
apply(compiler) { apply(compiler) {
compiler.hooks.afterEmit.tapAsync( compiler.hooks.afterEmit.tapPromise(
'Executable', 'Executable',
(compilation, callback) => { async () => (
chmod(join(FLECKS_CORE_ROOT, 'dist', 'build', 'cli.js'), 0o755, callback); chmod(join(FLECKS_CORE_ROOT, 'dist', 'build', 'cli.js'), 0o755)
}, ),
); );
} }
}() }()
); );
exports.externals = nodeExternals; exports.externals = async (options = {}) => {
const parts = FLECKS_CORE_ROOT.split('/');
const additionalModuleDirs = [];
while (parts.length > 1) {
parts.pop();
const candidate = join(parts.join('/'), 'node_modules');
try {
// eslint-disable-next-line no-await-in-loop
await access(candidate);
additionalModuleDirs.push(candidate);
}
// eslint-disable-next-line no-empty
catch (error) {}
}
try {
// eslint-disable-next-line no-await-in-loop
await access('/node_modules');
additionalModuleDirs.push('/node_modules');
}
// eslint-disable-next-line no-empty
catch (error) {}
return nodeExternals({
importType: 'umd',
...options,
additionalModuleDirs: [
...additionalModuleDirs,
...(options.additionalModuleDirs || []),
],
});
};
exports.regexFromExtensions = (exts) => ( exports.regexFromExtensions = (exts) => (
new RegExp(String.raw`(?:${exts.map((ext) => ext.replaceAll('.', '\\.')).join('|')})$`) new RegExp(String.raw`(?:${exts.map((ext) => ext.replaceAll('.', '\\.')).join('|')})$`)

View File

@ -11,7 +11,7 @@
"clean": "rm -rf dist node_modules yarn.lock", "clean": "rm -rf dist node_modules yarn.lock",
"lint": "eslint --config ./build/eslint.config.js .", "lint": "eslint --config ./build/eslint.config.js .",
"postversion": "npm run build", "postversion": "npm run build",
"test": "npm run build -d && mocha -t 10000 --colors ./dist/test.js" "test": "webpack --config ../core/build/test.webpack.config.js --mode production && mocha --colors ./dist/test.js"
}, },
"bin": { "bin": {
"flecks": "./build/cli.js" "flecks": "./build/cli.js"

View File

@ -1,4 +1,10 @@
export {dump as dumpYml, load as loadYml} from 'js-yaml'; /* eslint-disable global-require */
export {default as webpack} from 'webpack';
export * from '../build/webpack'; const {dump: dumpYml, load: loadYml} = require('js-yaml');
module.exports = {
dumpYml,
loadYml,
webpack: require('webpack'),
...require('../build/webpack'),
};

View File

@ -1,3 +1,4 @@
import {mkdir, writeFile} from 'fs/promises';
import {join} from 'path'; import {join} from 'path';
import {expect} from 'chai'; import {expect} from 'chai';
@ -89,6 +90,9 @@ describe('explication', () => {
}); });
it('includes modules', async () => { it('includes modules', async () => {
// act doesn't like copying node_modules, so we'll spin it up.
mkdir(join(root, 'modules-root', 'node_modules'));
await writeFile(join(root, 'modules-root', 'node_modules', 'foo.js'), '');
expect(await createExplication(['modules-root:./modules-root', 'foo'])) expect(await createExplication(['modules-root:./modules-root', 'foo']))
.to.deep.include({ .to.deep.include({
paths: ['modules-root', 'foo'], paths: ['modules-root', 'foo'],

View File

@ -1,2 +0,0 @@
'@flecks/build:../build': {}
'@flecks/core:.': {}

View File

@ -0,0 +1,8 @@
const Build = require('../../build/build/build');
const configFn = require('../../build/build/test.webpack.config');
module.exports = async (env, argv) => {
const flecks = await Build.from();
const config = await configFn(env, argv, flecks);
return config;
};

View File

@ -8,7 +8,7 @@
"clean": "rm -rf dist node_modules yarn.lock", "clean": "rm -rf dist node_modules yarn.lock",
"lint": "eslint --config ./build/core.eslint.config.js .", "lint": "eslint --config ./build/core.eslint.config.js .",
"postversion": "npm run build", "postversion": "npm run build",
"test": "npm run build -d && mocha --colors ./dist/test.js" "test": "webpack --config ./build/test.webpack.config.js --mode production && mocha --colors ./dist/test.js"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -41,7 +41,6 @@
"babel-merge": "^3.0.0", "babel-merge": "^3.0.0",
"chai": "4.2.0", "chai": "4.2.0",
"chai-as-promised": "7.1.1", "chai-as-promised": "7.1.1",
"clear-module": "^4.1.2",
"copy-webpack-plugin": "^11.0.0", "copy-webpack-plugin": "^11.0.0",
"eslint": "^8.56.0", "eslint": "^8.56.0",
"eslint-config-airbnb": "^19.0.4", "eslint-config-airbnb": "^19.0.4",

View File

@ -1,15 +1,14 @@
export {default as Class} from '../build/class'; /* eslint-disable global-require */
export {default as compose} from '../build/compose';
export {default as D} from '../build/debug';
export {default as EventEmitter} from '../build/event-emitter';
export {
ById,
ByType,
Flecks,
} from '../build/flecks';
export const hooks = { module.exports = {
'@flecks/web.config': async (req, flecks) => ({ Class: require('../build/class'),
id: flecks.get('@flecks/core.id'), compose: require('../build/compose'),
}), D: require('../build/debug'),
EventEmitter: require('../build/event-emitter'),
...require('../build/flecks'),
hooks: {
'@flecks/web.config': async (req, flecks) => ({
id: flecks.get('@flecks/core.id'),
}),
},
}; };

View File

@ -1,5 +1,8 @@
export {glob} from 'glob'; /* eslint-disable global-require */
export * from '../../build/stream'; module.exports = {
export * from './package-manager'; glob: require('glob').glob,
export * from './process'; ...require('../../build/stream'),
...require('./package-manager'),
...require('./process'),
};

View File

@ -1,14 +1,14 @@
import {processCode, spawnWith} from './process'; const {processCode, spawnWith} = require('./process');
/* eslint-disable camelcase */ /* eslint-disable camelcase */
const { const {
npm_config_user_agent = 'npm', npm_config_user_agent = 'npm',
} = process.env; } = process.env;
export const inferPackageManager = () => npm_config_user_agent.split('/')[0]; exports.inferPackageManager = () => npm_config_user_agent.split('/')[0];
/* eslint-enable camelcase */ /* eslint-enable camelcase */
export const build = async ({cwd, packageManager = inferPackageManager()}) => { exports.build = async ({cwd, packageManager = exports.inferPackageManager()}) => {
let args; let args;
switch (packageManager) { switch (packageManager) {
case 'bun': case 'bun':
@ -28,7 +28,7 @@ export const build = async ({cwd, packageManager = inferPackageManager()}) => {
return args && processCode(spawnWith(args, {cwd})); return args && processCode(spawnWith(args, {cwd}));
}; };
export const add = async ({dev, packageManager = inferPackageManager(), packages}) => { exports.add = async ({dev, packageManager = exports.inferPackageManager(), packages}) => {
let args; let args;
switch (packageManager) { switch (packageManager) {
case 'bun': case 'bun':
@ -64,7 +64,7 @@ export const add = async ({dev, packageManager = inferPackageManager(), packages
return args && processCode(spawnWith(args)); return args && processCode(spawnWith(args));
}; };
export const install = async ({cwd, packageManager = inferPackageManager()}) => { exports.install = async ({cwd, packageManager = exports.inferPackageManager()}) => {
let args; let args;
switch (packageManager) { switch (packageManager) {
case 'bun': case 'bun':
@ -84,7 +84,7 @@ export const install = async ({cwd, packageManager = inferPackageManager()}) =>
return args && processCode(spawnWith(args, {cwd})); return args && processCode(spawnWith(args, {cwd}));
}; };
export const lockFile = (packageManager = inferPackageManager()) => { exports.lockFile = (packageManager = exports.inferPackageManager()) => {
switch (packageManager) { switch (packageManager) {
case 'bun': case 'bun':
return 'bun.lockb'; return 'bun.lockb';

View File

@ -1,11 +1,11 @@
import {spawn} from 'child_process'; const {spawn} = require('child_process');
import D from '../../build/debug'; const D = require('../../build/debug');
const debug = D('@flecks/core/server'); const debug = D('@flecks/core/server');
const debugSilly = debug.extend('silly'); const debugSilly = debug.extend('silly');
export const processCode = (child) => new Promise((resolve, reject) => { exports.processCode = (child) => new Promise((resolve, reject) => {
child.on('error', reject); child.on('error', reject);
child.on('exit', (code) => { child.on('exit', (code) => {
child.off('error', reject); child.off('error', reject);
@ -13,7 +13,7 @@ export const processCode = (child) => new Promise((resolve, reject) => {
}); });
}); });
export const spawnWith = (cmd, opts = {}) => { exports.spawnWith = (cmd, opts = {}) => {
debug("spawning: '%s'", cmd.join(' ')); debug("spawning: '%s'", cmd.join(' '));
debugSilly('with options: %O', opts); debugSilly('with options: %O', opts);
const child = spawn(cmd[0], cmd.slice(1), { const child = spawn(cmd[0], cmd.slice(1), {

View File

@ -1,7 +1,8 @@
/* eslint-disable camelcase */
import {join} from 'path'; import {join} from 'path';
import {expect} from 'chai'; import {expect} from 'chai';
import clearModule from 'clear-module';
import resolve from '@flecks/core/build/resolve'; import resolve from '@flecks/core/build/resolve';
@ -21,10 +22,10 @@ it('can resolve inexact', async () => {
expect(__non_webpack_require__(join(root, 'blah'))) expect(__non_webpack_require__(join(root, 'blah')))
.to.equal(4); .to.equal(4);
clear(); clear();
clearModule(join(root, 'blah')); delete __non_webpack_require__.cache['/home/cha0s/sync/src/code/flecks/packages/core/test/server/resolve/blah.js'];
expect(__non_webpack_require__(join(root, 'blah'))) expect(__non_webpack_require__(join(root, 'blah')))
.to.equal(3); .to.equal(3);
clearModule(join(root, 'blah')); delete __non_webpack_require__.cache['/home/cha0s/sync/src/code/flecks/packages/core/test/server/resolve/blah.js'];
}); });
it('can resolve exact', async () => { it('can resolve exact', async () => {
@ -39,11 +40,11 @@ it('can resolve exact', async () => {
expect(__non_webpack_require__(join(root, 'boo'))) expect(__non_webpack_require__(join(root, 'boo')))
.to.equal(2); .to.equal(2);
clear(); clear();
clearModule(join(root, 'blah')); delete __non_webpack_require__.cache['/home/cha0s/sync/src/code/flecks/packages/core/test/server/resolve/blah.js'];
clearModule(join(root, 'boo')); delete __non_webpack_require__.cache['/home/cha0s/sync/src/code/flecks/packages/core/test/server/resolve/boo.js'];
expect(__non_webpack_require__(join(root, 'boo'))) expect(__non_webpack_require__(join(root, 'boo')))
.to.equal(1); .to.equal(1);
clearModule(join(root, 'boo')); delete __non_webpack_require__.cache['/home/cha0s/sync/src/code/flecks/packages/core/test/server/resolve/boo.js'];
}); });
it('can resolve false', async () => { it('can resolve false', async () => {
@ -53,10 +54,10 @@ it('can resolve false', async () => {
}, },
fallback: {}, fallback: {},
}, []); }, []);
expect(__non_webpack_require__(join(root, 'boo'))) expect(__non_webpack_require__(join(root, 'boo.js')))
.to.be.undefined; .to.be.undefined;
clear(); clear();
clearModule(join(root, 'boo')); delete __non_webpack_require__.cache['/home/cha0s/sync/src/code/flecks/packages/core/test/server/resolve/boo.js'];
expect(__non_webpack_require__(join(root, 'boo'))) expect(__non_webpack_require__(join(root, 'boo.js')))
.to.equal(1); .to.equal(1);
}); });

0
packages/create-app/build/cli.js Normal file → Executable file
View File

View File

@ -1,4 +1,4 @@
const {copy, executable} = require('@flecks/build/server'); const {copy, executable} = require('@flecks/build/src/server');
const configFn = require('@flecks/fleck/build/fleck.webpack.config'); const configFn = require('@flecks/fleck/build/fleck.webpack.config');
module.exports = async (env, argv, flecks) => { module.exports = async (env, argv, flecks) => {

2
packages/create-fleck/build/cli.js Normal file → Executable file
View File

@ -11,7 +11,7 @@ const {
transform, transform,
} = require('@flecks/core/server'); } = require('@flecks/core/server');
const {move, testDestination} = require('@flecks/create-app/build/move'); const {move, testDestination} = require('@flecks/create-app/build/move');
const {validate} = require('@flecks/create-app/server'); const {validate} = require('@flecks/create-app/src/server');
const { const {
FLECKS_CORE_ROOT = process.cwd(), FLECKS_CORE_ROOT = process.cwd(),

View File

@ -1,4 +1,4 @@
const {copy, executable} = require('@flecks/build/server'); const {copy, executable} = require('@flecks/build/src/server');
const configFn = require('@flecks/fleck/build/fleck.webpack.config'); const configFn = require('@flecks/fleck/build/fleck.webpack.config');
module.exports = async (env, argv, flecks) => { module.exports = async (env, argv, flecks) => {

View File

@ -1,4 +1,4 @@
const {dumpYml} = require('@flecks/build/server'); const {dumpYml} = require('@flecks/build/src/server');
const {generateComposeConfig, generateDockerFile} = require('./generate'); const {generateComposeConfig, generateDockerFile} = require('./generate');

View File

@ -3,7 +3,7 @@ const {dirname, join, relative} = require('path');
const {transformAsync} = require('@babel/core'); const {transformAsync} = require('@babel/core');
const {default: traverse} = require('@babel/traverse'); const {default: traverse} = require('@babel/traverse');
const {glob} = require('@flecks/core/server'); const {glob} = require('@flecks/core/src/server');
const { const {
buildFileVisitor, buildFileVisitor,

View File

@ -3,8 +3,8 @@ const {join} = require('path');
// eslint-disable-next-line import/no-extraneous-dependencies // eslint-disable-next-line import/no-extraneous-dependencies
const {commands: coreCommands} = require('@flecks/build/build/commands'); const {commands: coreCommands} = require('@flecks/build/build/commands');
const {D} = require('@flecks/core'); const {D} = require('@flecks/core/src');
const {glob} = require('@flecks/core/server'); const {glob} = require('@flecks/core/src/server');
const chokidar = require('chokidar'); const chokidar = require('chokidar');
const clearModule = require('clear-module'); const clearModule = require('clear-module');
const Mocha = require('mocha'); const Mocha = require('mocha');
@ -33,7 +33,7 @@ module.exports = (program, flecks) => {
watch, watch,
} = opts; } = opts;
const {build} = coreCommands(program, flecks); const {build} = coreCommands(program, flecks);
const child = await build.action(undefined, opts); const child = await build.action('test', opts);
const testPaths = await glob(join(FLECKS_CORE_ROOT, 'test/**/*.js')); const testPaths = await glob(join(FLECKS_CORE_ROOT, 'test/**/*.js'));
if (0 === testPaths.length) { if (0 === testPaths.length) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console

View File

@ -1,3 +1,4 @@
const Build = require('@flecks/build/build/build');
const {processFleckAssets} = require('@flecks/build/build/process-assets'); const {processFleckAssets} = require('@flecks/build/build/process-assets');
const commands = require('./commands'); const commands = require('./commands');
@ -13,7 +14,10 @@ exports.hooks = {
errorDetails: true, errorDetails: true,
}, },
}), }),
'@flecks/build.targets': () => ['fleck'], '@flecks/build.targets': () => (
['fleck']
.concat(Build.buildList.includes('test') ? ['test'] : [])
),
'@flecks/build.processAssets': async (target, assets, compilation, flecks) => { '@flecks/build.processAssets': async (target, assets, compilation, flecks) => {
if ('fleck' === target) { if ('fleck' === target) {
await processFleckAssets(assets, compilation, (json, compilation) => ( await processFleckAssets(assets, compilation, (json, compilation) => (

View File

@ -1,11 +1,10 @@
const {externals} = require('@flecks/build/server'); const {externals} = require('@flecks/build/src/server');
const configFn = require('@flecks/fleck/build/fleck.webpack.config'); const configFn = require('@flecks/fleck/build/fleck.webpack.config');
module.exports = async (env, argv, flecks) => { module.exports = async (env, argv, flecks) => {
const config = await configFn(env, argv, flecks); const config = await configFn(env, argv, flecks);
config.externals = externals({ config.externals = await externals({
allowlist: ['react-tabs/style/react-tabs.css'], allowlist: ['react-tabs/style/react-tabs.css'],
importType: 'umd',
}); });
return config; return config;
}; };

View File

@ -3,7 +3,7 @@ const {readdir} = require('fs/promises');
const {tmpdir} = require('os'); const {tmpdir} = require('os');
const {join} = require('path'); const {join} = require('path');
const {D} = require('@flecks/core'); const {D} = require('@flecks/core/src');
const commandExists = require('command-exists'); const commandExists = require('command-exists');
const debug = D('@flecks/repl/commands'); const debug = D('@flecks/repl/commands');

View File

@ -1,4 +1,4 @@
const {banner} = require('@flecks/build/server'); const {banner} = require('@flecks/build/src/server');
exports.hooks = { exports.hooks = {
'@flecks/build.config.alter': ({server}, env, argv, flecks) => { '@flecks/build.config.alter': ({server}, env, argv, flecks) => {

View File

@ -1,4 +1,4 @@
const {externals} = require('@flecks/build/server'); const {externals} = require('@flecks/build/src/server');
const D = require('@flecks/core/build/debug'); const D = require('@flecks/core/build/debug');
@ -106,5 +106,9 @@ module.exports = async (config, env, argv, flecks) => {
allowlist.push(/^webpack\/hot\/signal/); allowlist.push(/^webpack\/hot\/signal/);
} }
// Externalize the rest. // Externalize the rest.
config.externals = externals({allowlist, additionalModuleDirs: flecks.resolver.modules}); config.externals = await externals({
additionalModuleDirs: flecks.resolver.modules,
allowlist,
importType: 'commonjs',
});
}; };

View File

@ -4,7 +4,7 @@ const {
banner, banner,
defaultConfig, defaultConfig,
webpack, webpack,
} = require('@flecks/build/server'); } = require('@flecks/build/src/server');
const runtime = require('./runtime'); const runtime = require('./runtime');
const startServer = require('./start'); const startServer = require('./start');

View File

@ -1,4 +1,4 @@
const {copy, externals} = require('@flecks/build/server'); const {copy, externals} = require('@flecks/build/src/server');
const configFn = require('@flecks/fleck/build/fleck.webpack.config'); const configFn = require('@flecks/fleck/build/fleck.webpack.config');
module.exports = async (env, argv, flecks) => { module.exports = async (env, argv, flecks) => {
@ -6,9 +6,8 @@ module.exports = async (env, argv, flecks) => {
delete config.entry['server/build/entry']; delete config.entry['server/build/entry'];
delete config.entry['server/build/template']; delete config.entry['server/build/template'];
delete config.entry['server/build/tests']; delete config.entry['server/build/tests'];
config.externals = externals({ config.externals = await externals({
allowlist: ['mocha/mocha.css'], allowlist: ['mocha/mocha.css'],
importType: 'umd',
}); });
config.plugins.push( config.plugins.push(
copy({ copy({

View File

@ -2,8 +2,8 @@ const {stat, unlink} = require('fs/promises');
const {join} = require('path'); const {join} = require('path');
const Build = require('@flecks/build/build/build'); const Build = require('@flecks/build/build/build');
const {regexFromExtensions} = require('@flecks/build/server'); const {regexFromExtensions} = require('@flecks/build/src/server');
const {spawnWith} = require('@flecks/core/server'); const {spawnWith} = require('@flecks/core/src/server');
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { const {

View File

@ -1,6 +1,6 @@
const {join} = require('path'); const {join} = require('path');
const {defaultConfig, webpack} = require('@flecks/build/server'); const {defaultConfig, webpack} = require('@flecks/build/src/server');
const {CleanWebpackPlugin} = require('clean-webpack-plugin'); const {CleanWebpackPlugin} = require('clean-webpack-plugin');
const { const {

View File

@ -4,7 +4,7 @@ const {
defaultConfig, defaultConfig,
regexFromExtensions, regexFromExtensions,
webpack, webpack,
} = require('@flecks/build/server'); } = require('@flecks/build/src/server');
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin'); const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin');
const {htmlTagObjectToString} = require('html-webpack-plugin/lib/html-tags'); const {htmlTagObjectToString} = require('html-webpack-plugin/lib/html-tags');