refactor: creators
This commit is contained in:
parent
73eb334e05
commit
f702e8b7f0
8
build/concurrent.js
Normal file
8
build/concurrent.js
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
module.exports = async function concurrent(inputs, task, jobs = require('os').cpus().length) {
|
||||||
|
const workers = new Array(jobs).fill(Promise.resolve(0));
|
||||||
|
inputs.forEach((input, i) => {
|
||||||
|
// then= :)
|
||||||
|
workers[i % jobs] = workers[i % jobs].then(async (code) => await task(input) || code);
|
||||||
|
});
|
||||||
|
return (await Promise.all(workers)).find((code) => code !== 0) || 0;
|
||||||
|
};
|
155
build/publish.js
155
build/publish.js
|
@ -1,43 +1,150 @@
|
||||||
|
const {Buffer} = require('buffer');
|
||||||
const {exec} = require('child_process');
|
const {exec} = require('child_process');
|
||||||
|
const {createHash} = require('crypto');
|
||||||
|
const {createReadStream} = require('fs');
|
||||||
|
const {cp, mkdir, writeFile} = require('fs/promises');
|
||||||
const {join} = require('path');
|
const {join} = require('path');
|
||||||
|
|
||||||
const {processCode, spawnWith} = require('@flecks/core/src/server');
|
const {
|
||||||
|
processCode,
|
||||||
|
spawnWith,
|
||||||
|
} = require('@flecks/core/src/server');
|
||||||
|
const Arborist = require('@npmcli/arborist');
|
||||||
const {glob} = require('glob');
|
const {glob} = require('glob');
|
||||||
|
|
||||||
|
const concurrent = require('./concurrent');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
FLECKS_CORE_ROOT = process.cwd(),
|
FLECKS_CORE_ROOT = process.cwd(),
|
||||||
} = process.env;
|
} = process.env;
|
||||||
|
|
||||||
const args = ['npm', 'publish', '--provenance'];
|
const args = ['npm', 'publish', ...process.argv.slice(2)];
|
||||||
|
const bumpedVersions = {};
|
||||||
|
const creators = ['create-app', 'create-fleck'];
|
||||||
|
const localVersions = {};
|
||||||
|
const packCache = join(FLECKS_CORE_ROOT, 'node_modules', '.cache', '@flecks', 'publish');
|
||||||
const {workspaces} = require(join(FLECKS_CORE_ROOT, 'package.json'));
|
const {workspaces} = require(join(FLECKS_CORE_ROOT, 'package.json'));
|
||||||
|
|
||||||
(async () => {
|
const run = (cmd) => (
|
||||||
const paths = (await Promise.all(workspaces.map((path) => glob(join(FLECKS_CORE_ROOT, path)))))
|
new Promise((resolve) => {
|
||||||
.flat();
|
exec(cmd, (error, stdout) => {
|
||||||
const cpus = new Array(require('os').cpus().length).fill(Promise.resolve(0));
|
|
||||||
paths.forEach((cwd, i) => {
|
|
||||||
// then= :)
|
|
||||||
cpus[i % cpus.length] = cpus[i % cpus.length]
|
|
||||||
.then(async (code) => {
|
|
||||||
const {name, version} = require(join(cwd, 'package.json'));
|
|
||||||
const [localVersion, remoteVersion] = await Promise.all([
|
|
||||||
version,
|
|
||||||
new Promise((resolve, reject) => {
|
|
||||||
exec(`npm view ${name} version`, (error, stdout) => {
|
|
||||||
if (error) {
|
if (error) {
|
||||||
reject(error)
|
resolve(undefined)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
resolve(stdout.trim());
|
resolve(stdout.trim());
|
||||||
});
|
});
|
||||||
}),
|
})
|
||||||
]);
|
);
|
||||||
if (localVersion === remoteVersion) {
|
|
||||||
return code;
|
// Get integrity sums for creator dependencies.
|
||||||
|
const packPkg = async (pkg) => {
|
||||||
|
await processCode(spawnWith(
|
||||||
|
['npm', 'pack', '--pack-destination', packCache],
|
||||||
|
{cwd: join(FLECKS_CORE_ROOT, 'packages', pkg, 'dist', 'fleck'), stdio: 'ignore'},
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
const bumpDependencies = (dependencies) => (
|
||||||
|
Object.fromEntries(
|
||||||
|
Object.entries(dependencies)
|
||||||
|
.map(([pkg, version]) => ([pkg, localVersions[pkg] || version])),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
const integrityForPkg = async (pkg) => {
|
||||||
|
const pack = join(packCache, `flecks-${pkg.split('/')[1]}-${localVersions[pkg]}.tgz`);
|
||||||
|
const buffers = [];
|
||||||
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
|
for await (const data of createReadStream(pack).pipe(createHash('sha512'))) {
|
||||||
|
buffers.push(data);
|
||||||
}
|
}
|
||||||
const publishCode = await processCode(spawnWith(args, {cwd: join(cwd, 'dist', 'fleck')}));
|
return `sha512-${Buffer.concat(buffers).toString('base64')}`;
|
||||||
return publishCode || code;
|
};
|
||||||
|
|
||||||
|
const shrinkwrap = async (path) => {
|
||||||
|
const arb = new Arborist({
|
||||||
|
path,
|
||||||
|
registry: await run('npm config get registry'),
|
||||||
});
|
});
|
||||||
});
|
const {meta} = await arb.buildIdealTree({saveType: 'prod'});
|
||||||
process.exitCode = (await Promise.all(cpus)).find((code) => code !== 0) || 0;
|
const shrinkwrap = await meta.commit();
|
||||||
|
shrinkwrap.packages = Object.fromEntries(
|
||||||
|
await Promise.all(
|
||||||
|
Object.entries(shrinkwrap.packages)
|
||||||
|
.map(async ([pkg, config]) => {
|
||||||
|
if (pkg.match(/node_modules\/@flecks\/[^/]+$/)) {
|
||||||
|
if (config.dependencies) {
|
||||||
|
config.dependencies = bumpDependencies(config.dependencies);
|
||||||
|
}
|
||||||
|
if (config.devDependencies) {
|
||||||
|
config.devDependencies = bumpDependencies(config.devDependencies);
|
||||||
|
}
|
||||||
|
const subpkg = pkg.split('/').slice(1).join('/');
|
||||||
|
config.version = localVersions[subpkg];
|
||||||
|
config.integrity = await integrityForPkg(subpkg);
|
||||||
|
}
|
||||||
|
return [pkg, config];
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return shrinkwrap;
|
||||||
|
};
|
||||||
|
|
||||||
|
const shrinkwrapsAndPublish = async (creator) => {
|
||||||
|
const dist = join(FLECKS_CORE_ROOT, 'packages', creator, 'dist', 'fleck');
|
||||||
|
const fakePackage = join(packCache, creator);
|
||||||
|
await mkdir(fakePackage, {recursive: true});
|
||||||
|
// Get a shrinkwrap from template package.json and insert it as a package-lock.json.
|
||||||
|
await cp(join(dist, 'template', 'package.json.noconflict'), join(fakePackage, 'package.json'));
|
||||||
|
await writeFile(
|
||||||
|
join(dist, 'template', 'package-lock.json.noconflict'),
|
||||||
|
JSON.stringify(await shrinkwrap(fakePackage), null, 2),
|
||||||
|
);
|
||||||
|
// Get a shrinkwrap from the built creator and insert it as shrinkwrap.
|
||||||
|
await writeFile(
|
||||||
|
join(dist, 'npm-shrinkwrap.json'),
|
||||||
|
JSON.stringify(await shrinkwrap(dist), null, 2),
|
||||||
|
);
|
||||||
|
// Publish.
|
||||||
|
await processCode(spawnWith(args, {cwd: dist}));
|
||||||
|
};
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
await concurrent(
|
||||||
|
(await Promise.all(workspaces.map((path) => glob(join(FLECKS_CORE_ROOT, path))))).flat(),
|
||||||
|
async (cwd) => {
|
||||||
|
const {name, version} = require(join(cwd, 'package.json'));
|
||||||
|
const [localVersion, remoteVersion] = await Promise.all([
|
||||||
|
version,
|
||||||
|
run(`npm view ${name} version`),
|
||||||
|
]);
|
||||||
|
localVersions[name] = version;
|
||||||
|
if (localVersion === remoteVersion) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
bumpedVersions[name] = version;
|
||||||
|
// Skip creators for now.
|
||||||
|
if (creators.some((creator) => name.endsWith(creator))) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return processCode(spawnWith(args, {cwd: join(cwd, 'dist', 'fleck')}));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
// No creators? Bail.
|
||||||
|
if (!bumpedVersions['@flecks/create-app'] && !bumpedVersions['@flecks/create-app']) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Pack dependencies.
|
||||||
|
await mkdir(packCache, {recursive: true});
|
||||||
|
const dependencies = ['build', 'core', 'fleck', 'server'];
|
||||||
|
await Promise.all(dependencies.map(packPkg));
|
||||||
|
if (bumpedVersions['@flecks/create-fleck']) {
|
||||||
|
await shrinkwrapsAndPublish('create-fleck');
|
||||||
|
}
|
||||||
|
if (bumpedVersions['@flecks/create-app']) {
|
||||||
|
// Needs packed create-fleck for package lock.
|
||||||
|
await packPkg('create-fleck');
|
||||||
|
await shrinkwrapsAndPublish('create-app');
|
||||||
|
}
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -3,21 +3,18 @@ const {join} = require('path');
|
||||||
const {processCode, spawnWith} = require('@flecks/core/src/server');
|
const {processCode, spawnWith} = require('@flecks/core/src/server');
|
||||||
const {glob} = require('glob');
|
const {glob} = require('glob');
|
||||||
|
|
||||||
|
const concurrent = require('./concurrent');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
FLECKS_CORE_ROOT = process.cwd(),
|
FLECKS_CORE_ROOT = process.cwd(),
|
||||||
} = process.env;
|
} = process.env;
|
||||||
|
|
||||||
const args = ['npm', 'run', ...process.argv.slice(2)];
|
const args = process.argv.slice(2);
|
||||||
const {workspaces} = require(join(FLECKS_CORE_ROOT, 'package.json'));
|
const {workspaces} = require(join(FLECKS_CORE_ROOT, 'package.json'));
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
const paths = (await Promise.all(workspaces.map((path) => glob(join(FLECKS_CORE_ROOT, path)))))
|
process.exitCode = await concurrent(
|
||||||
.flat();
|
(await Promise.all(workspaces.map((path) => glob(join(FLECKS_CORE_ROOT, path))))).flat(),
|
||||||
const cpus = new Array(require('os').cpus().length).fill(Promise.resolve(0));
|
(cwd) => processCode(spawnWith(args, {cwd})),
|
||||||
paths.forEach((cwd, i) => {
|
);
|
||||||
// then= :)
|
|
||||||
cpus[i % cpus.length] = cpus[i % cpus.length]
|
|
||||||
.then(async (code) => (await processCode(spawnWith(args, {cwd}))) || code);
|
|
||||||
});
|
|
||||||
process.exitCode = (await Promise.all(cpus)).find((code) => code !== 0) || 0;
|
|
||||||
})();
|
})();
|
||||||
|
|
3686
package-lock.json
generated
3686
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
13
package.json
13
package.json
|
@ -7,17 +7,20 @@
|
||||||
"url": "git+https://github.com/cha0s/flecks.git"
|
"url": "git+https://github.com/cha0s/flecks.git"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "node build/tasks build",
|
"build": "node build/tasks npm run build",
|
||||||
"ci": "act -j verify",
|
"ci": "act -j verify",
|
||||||
"dox:bump": "npm run dox:gh-pages && cd dox && git add . && git commit -m $(git -C .. rev-parse HEAD) && git push origin gh-pages",
|
"dox:bump": "npm run dox:gh-pages && cd dox && git add . && git commit -m $(git -C .. rev-parse HEAD) && git push origin gh-pages",
|
||||||
"dox:gh-pages": "flecks dox docusaurus && cd website && DOCUSAURUS_GENERATED_FILES_DIR_NAME=node_modules/.cache/docusaurus node_modules/.bin/docusaurus build --out-dir ../dox-tmp && cd .. && rm -rf dox/* && mv dox-tmp/* dox && rmdir dox-tmp",
|
"dox:gh-pages": "flecks dox docusaurus && cd website && DOCUSAURUS_GENERATED_FILES_DIR_NAME=node_modules/.cache/docusaurus node_modules/.bin/docusaurus build --out-dir ../dox-tmp && cd .. && rm -rf dox/* && mv dox-tmp/* dox && rmdir dox-tmp",
|
||||||
"dox:serve": "flecks dox docusaurus && cd website && DOCUSAURUS_GENERATED_FILES_DIR_NAME=node_modules/.cache/docusaurus node_modules/.bin/docusaurus build --no-minify --out-dir ../dox-tmp && node_modules/.bin/docusaurus serve --dir ../dox-tmp",
|
"dox:serve": "flecks dox docusaurus && cd website && DOCUSAURUS_GENERATED_FILES_DIR_NAME=node_modules/.cache/docusaurus node_modules/.bin/docusaurus build --no-minify --out-dir ../dox-tmp && node_modules/.bin/docusaurus serve --dir ../dox-tmp",
|
||||||
"dox": "flecks dox docusaurus && cd website && DOCUSAURUS_GENERATED_FILES_DIR_NAME=node_modules/.cache/docusaurus node_modules/.bin/docusaurus",
|
"dox": "flecks dox docusaurus && cd website && DOCUSAURUS_GENERATED_FILES_DIR_NAME=node_modules/.cache/docusaurus node_modules/.bin/docusaurus",
|
||||||
"lint": "node build/tasks lint",
|
"lint": "node build/tasks npm run lint",
|
||||||
"publish": "node build/publish",
|
"publish": "node build/publish --provenance",
|
||||||
"test": "node build/tasks -- test -t 300000"
|
"test": "node build/tasks npm run -- test -t 300000"
|
||||||
},
|
},
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
]
|
],
|
||||||
|
"devDependencies": {
|
||||||
|
"@npmcli/arborist": "^7.3.1"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,21 +19,20 @@ const {
|
||||||
isStringLiteral,
|
isStringLiteral,
|
||||||
stringLiteral,
|
stringLiteral,
|
||||||
} = require('@babel/types');
|
} = require('@babel/types');
|
||||||
|
const addPathsToYml = require('@flecks/core/build/add-paths-to-yml');
|
||||||
const D = require('@flecks/core/build/debug');
|
const D = require('@flecks/core/build/debug');
|
||||||
const {
|
const {
|
||||||
add,
|
add,
|
||||||
binaryPath,
|
binaryPath,
|
||||||
|
loadYml,
|
||||||
lockFile,
|
lockFile,
|
||||||
spawnWith,
|
spawnWith,
|
||||||
} = require('@flecks/core/src/server');
|
} = require('@flecks/core/src/server');
|
||||||
const chokidar = require('chokidar');
|
const chokidar = require('chokidar');
|
||||||
const {glob} = require('glob');
|
const {glob} = require('glob');
|
||||||
const {load: loadYml} = require('js-yaml');
|
|
||||||
const {paperwork} = require('precinct');
|
const {paperwork} = require('precinct');
|
||||||
const {rimraf} = require('rimraf');
|
const {rimraf} = require('rimraf');
|
||||||
|
|
||||||
const addPathsToYml = require('./add-paths-to-yml');
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
FLECKS_CORE_ROOT = process.cwd(),
|
FLECKS_CORE_ROOT = process.cwd(),
|
||||||
} = process.env;
|
} = process.env;
|
||||||
|
@ -236,6 +235,7 @@ exports.commands = (program, flecks) => {
|
||||||
...(target ? {FLECKS_CORE_BUILD_LIST: target} : {}),
|
...(target ? {FLECKS_CORE_BUILD_LIST: target} : {}),
|
||||||
...(hot ? {FLECKS_ENV__flecks_server__hot: 'true'} : {}),
|
...(hot ? {FLECKS_ENV__flecks_server__hot: 'true'} : {}),
|
||||||
},
|
},
|
||||||
|
// @todo This kills the pnpm. Let's use a real IPC channel.
|
||||||
useFork: true,
|
useFork: true,
|
||||||
...rest,
|
...rest,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
const {readFile} = require('fs/promises');
|
const {readFile} = require('fs/promises');
|
||||||
const {join} = require('path');
|
const {join} = require('path');
|
||||||
|
|
||||||
|
const {loadYml} = require('@flecks/core/src/server');
|
||||||
|
|
||||||
const D = require('@flecks/core/build/debug');
|
const D = require('@flecks/core/build/debug');
|
||||||
|
|
||||||
const debug = D('@flecks/build/build/load-config');
|
const debug = D('@flecks/build/build/load-config');
|
||||||
|
|
||||||
module.exports = async function loadConfig(root) {
|
module.exports = async function loadConfig(root) {
|
||||||
try {
|
try {
|
||||||
const {load} = require('js-yaml');
|
|
||||||
const filename = join(root, 'build', 'flecks.yml');
|
const filename = join(root, 'build', 'flecks.yml');
|
||||||
const buffer = await readFile(filename, 'utf8');
|
const buffer = await readFile(filename, 'utf8');
|
||||||
debug('parsing configuration from YML...');
|
debug('parsing configuration from YML...');
|
||||||
return ['YML', load(buffer, {filename})];
|
return ['YML', loadYml(buffer, {filename})];
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
if ('ENOENT' !== error.code) {
|
if ('ENOENT' !== error.code) {
|
||||||
|
|
|
@ -55,7 +55,6 @@
|
||||||
"glob": "^10.3.10",
|
"glob": "^10.3.10",
|
||||||
"globals": "^13.23.0",
|
"globals": "^13.23.0",
|
||||||
"graceful-fs": "^4.2.11",
|
"graceful-fs": "^4.2.11",
|
||||||
"js-yaml": "4.1.0",
|
|
||||||
"mocha": "^10.2.0",
|
"mocha": "^10.2.0",
|
||||||
"precinct": "^11.0.5",
|
"precinct": "^11.0.5",
|
||||||
"rimraf": "^5.0.5",
|
"rimraf": "^5.0.5",
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
/* eslint-disable global-require */
|
/* eslint-disable global-require */
|
||||||
|
|
||||||
const {dump: dumpYml, load: loadYml} = require('js-yaml');
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
dumpYml,
|
|
||||||
loadYml,
|
|
||||||
rimraf: require('rimraf').rimraf,
|
rimraf: require('rimraf').rimraf,
|
||||||
webpack: require('webpack'),
|
webpack: require('webpack'),
|
||||||
...require('../build/webpack'),
|
...require('../build/webpack'),
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import addPathsToYml from '@flecks/build/build/add-paths-to-yml';
|
import addPathsToYml from '@flecks/core/build/add-paths-to-yml';
|
||||||
|
import {loadYml} from '@flecks/core/server';
|
||||||
import {expect} from 'chai';
|
import {expect} from 'chai';
|
||||||
import {readFile, writeFile} from 'fs/promises';
|
import {readFile, writeFile} from 'fs/promises';
|
||||||
import {load as loadYml} from 'js-yaml';
|
|
||||||
|
|
||||||
it('can add paths to YML', async () => {
|
it('can add paths to YML', async () => {
|
||||||
await writeFile(
|
await writeFile(
|
||||||
|
|
|
@ -9,7 +9,7 @@ const {
|
||||||
|
|
||||||
module.exports = async (paths, root) => {
|
module.exports = async (paths, root) => {
|
||||||
const ymlPath = join(root || FLECKS_CORE_ROOT, 'build', 'flecks.yml');
|
const ymlPath = join(root || FLECKS_CORE_ROOT, 'build', 'flecks.yml');
|
||||||
let yml = loadYml(await readFile(ymlPath));
|
let yml = loadYml(await readFile(ymlPath)) || {};
|
||||||
yml = Object.fromEntries(Object.entries(yml).concat(paths.map((path) => [path, {}])));
|
yml = Object.fromEntries(Object.entries(yml).concat(paths.map((path) => [path, {}])));
|
||||||
await writeFile(ymlPath, dumpYml(yml, {sortKeys: true}));
|
await writeFile(ymlPath, dumpYml(yml, {sortKeys: true}));
|
||||||
};
|
};
|
16
packages/core/build/move.js
Normal file
16
packages/core/build/move.js
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
const {basename, dirname, join} = require('path');
|
||||||
|
|
||||||
|
const {JsonStream} = require('./stream');
|
||||||
|
const FileTree = require('./tree');
|
||||||
|
|
||||||
|
exports.move = async (name, source) => {
|
||||||
|
const fileTree = await FileTree.loadFrom(source);
|
||||||
|
// Renamed to avoid conflicts.
|
||||||
|
fileTree.glob('**/*.noconflict')
|
||||||
|
.forEach((path) => {
|
||||||
|
fileTree.move(path, join(dirname(path), basename(path, '.noconflict')));
|
||||||
|
});
|
||||||
|
// Add project name to `package.json`.
|
||||||
|
fileTree.pipe('package.json', new JsonStream((json) => ({name, ...json})));
|
||||||
|
return fileTree;
|
||||||
|
};
|
|
@ -1,57 +1,70 @@
|
||||||
// eslint-disable-next-line max-classes-per-file
|
// eslint-disable-next-line max-classes-per-file
|
||||||
|
const {dump: dumpYml, load: loadYml} = require('js-yaml');
|
||||||
const JsonParse = require('jsonparse');
|
const JsonParse = require('jsonparse');
|
||||||
const {Transform} = require('stream');
|
const {Transform} = require('stream');
|
||||||
|
|
||||||
exports.JsonStream = class JsonStream extends Transform {
|
exports.JsonStream = class JsonStream extends Transform {
|
||||||
|
|
||||||
constructor() {
|
constructor(decorator) {
|
||||||
super();
|
super();
|
||||||
const self = this;
|
|
||||||
this.done = undefined;
|
|
||||||
this.parser = new JsonParse();
|
this.parser = new JsonParse();
|
||||||
|
const self = this;
|
||||||
this.parser.onValue = function onValue(O) {
|
this.parser.onValue = function onValue(O) {
|
||||||
if (0 === this.stack.length) {
|
if (0 === this.stack.length) {
|
||||||
self.push(JSON.stringify(O));
|
self.transformed = JSON.stringify(decorator(O));
|
||||||
self.done();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
this.transformed = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-underscore-dangle
|
||||||
|
_flush(done) {
|
||||||
|
this.push(this.transformed);
|
||||||
|
done();
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line no-underscore-dangle
|
// eslint-disable-next-line no-underscore-dangle
|
||||||
_transform(chunk, encoding, done) {
|
_transform(chunk, encoding, done) {
|
||||||
this.done = done;
|
|
||||||
this.parser.write(chunk);
|
this.parser.write(chunk);
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.JsonStream.PrettyPrint = class extends Transform {
|
|
||||||
|
|
||||||
constructor(indent = 2) {
|
|
||||||
super();
|
|
||||||
this.indent = indent;
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line no-underscore-dangle
|
|
||||||
async _transform(chunk, encoding, done) {
|
|
||||||
this.push(JSON.stringify(JSON.parse(chunk), null, this.indent));
|
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.transform = (fn, opts = {}) => {
|
exports.JsonStream.PrettyPrint = class extends exports.JsonStream {
|
||||||
class EasyTransform extends Transform {
|
|
||||||
|
|
||||||
constructor() {
|
constructor(decorator, indent = 2) {
|
||||||
super(opts);
|
super(decorator);
|
||||||
|
const self = this;
|
||||||
|
this.parser.onValue = function onValue(O) {
|
||||||
|
if (0 === this.stack.length) {
|
||||||
|
self.transformed = JSON.stringify(O, null, indent);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.YamlStream = class YamlStream extends Transform {
|
||||||
|
|
||||||
|
constructor(decorator, options = {dump: {}, load: {}}) {
|
||||||
|
super();
|
||||||
|
this.buffers = [];
|
||||||
|
this.decorator = decorator;
|
||||||
|
this.options = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-underscore-dangle
|
||||||
|
_flush(done) {
|
||||||
|
const yml = loadYml(Buffer.concat(this.buffers).toString(), this.options.load);
|
||||||
|
this.push(dumpYml(this.decorator(yml), this.options.dump));
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-underscore-dangle
|
||||||
|
_transform(chunk, encoding, done) {
|
||||||
|
this.buffers.push(chunk);
|
||||||
|
done();
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line no-underscore-dangle, class-methods-use-this
|
|
||||||
_transform(chunk, encoding, done) {
|
|
||||||
fn(chunk, encoding, done, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return new EasyTransform();
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
const {createReadStream, createWriteStream} = require('fs');
|
const {createReadStream, createWriteStream} = require('fs');
|
||||||
const {mkdir, stat} = require('fs/promises');
|
const {mkdir, stat} = require('fs/promises');
|
||||||
|
|
||||||
const {glob, JsonStream} = require('@flecks/core/server');
|
const {glob} = require('glob');
|
||||||
const minimatch = require('minimatch');
|
const minimatch = require('minimatch');
|
||||||
const {dirname, join} = require('path');
|
const {dirname, join} = require('path');
|
||||||
|
|
||||||
|
const {JsonStream} = require('./stream');
|
||||||
|
|
||||||
module.exports = class FileTree {
|
module.exports = class FileTree {
|
||||||
|
|
||||||
constructor(files = {}) {
|
constructor(files = {}) {
|
||||||
|
@ -19,6 +21,12 @@ module.exports = class FileTree {
|
||||||
this.files[path] = stream;
|
this.files[path] = stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete(path) {
|
||||||
|
if (this.files[path]) {
|
||||||
|
delete this.files[path];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
glob(glob) {
|
glob(glob) {
|
||||||
return Object.keys(this.files).filter((path) => minimatch(path, glob, {dot: true}));
|
return Object.keys(this.files).filter((path) => minimatch(path, glob, {dot: true}));
|
||||||
}
|
}
|
||||||
|
@ -41,6 +49,13 @@ module.exports = class FileTree {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
move(from, to) {
|
||||||
|
if (this.files[from]) {
|
||||||
|
this.files[to] = this.files[from];
|
||||||
|
this.delete(from);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pipe(path, stream) {
|
pipe(path, stream) {
|
||||||
this.files[path] = this.files[path] ? this.files[path].pipe(stream) : undefined;
|
this.files[path] = this.files[path] ? this.files[path].pipe(stream) : undefined;
|
||||||
}
|
}
|
|
@ -26,8 +26,10 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"debug": "4.3.1",
|
"debug": "4.3.1",
|
||||||
"glob": "^10.3.10",
|
"glob": "^10.3.10",
|
||||||
|
"js-yaml": "4.1.0",
|
||||||
"jsonparse": "^1.3.1",
|
"jsonparse": "^1.3.1",
|
||||||
"lodash.get": "^4.4.2",
|
"lodash.get": "^4.4.2",
|
||||||
|
"minimatch": "^5.0.1",
|
||||||
"set-value": "^4.1.0",
|
"set-value": "^4.1.0",
|
||||||
"source-map-support": "0.5.19",
|
"source-map-support": "0.5.19",
|
||||||
"supports-color": "9.2.1"
|
"supports-color": "9.2.1"
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
/* eslint-disable global-require */
|
/* eslint-disable global-require */
|
||||||
|
|
||||||
|
const {dump: dumpYml, load: loadYml} = require('js-yaml');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
dumpYml,
|
||||||
glob: require('glob').glob,
|
glob: require('glob').glob,
|
||||||
|
loadYml,
|
||||||
...require('../../build/stream'),
|
...require('../../build/stream'),
|
||||||
...require('./package-manager'),
|
...require('./package-manager'),
|
||||||
...require('./process'),
|
...require('./process'),
|
||||||
|
|
|
@ -1,19 +1,17 @@
|
||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
const {stat} = require('fs/promises');
|
||||||
const {join} = require('path');
|
const {join} = require('path');
|
||||||
|
|
||||||
|
const {move} = require('@flecks/core/build/move');
|
||||||
const {
|
const {
|
||||||
build,
|
build,
|
||||||
install,
|
install,
|
||||||
transform,
|
YamlStream,
|
||||||
} = require('@flecks/core/server');
|
} = require('@flecks/core/src/server');
|
||||||
const {program} = require('commander');
|
const {program} = require('commander');
|
||||||
const {dump: dumpYml, load: loadYml} = require('js-yaml');
|
|
||||||
const validate = require('validate-npm-package-name');
|
const validate = require('validate-npm-package-name');
|
||||||
|
|
||||||
// const build = require('./build');
|
|
||||||
const {move, testDestination} = require('./move');
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
FLECKS_CORE_ROOT = process.cwd(),
|
FLECKS_CORE_ROOT = process.cwd(),
|
||||||
} = process.env;
|
} = process.env;
|
||||||
|
@ -32,22 +30,23 @@ const {
|
||||||
}
|
}
|
||||||
const destination = join(FLECKS_CORE_ROOT, app);
|
const destination = join(FLECKS_CORE_ROOT, app);
|
||||||
const name = app.startsWith('@') ? app : `@${app}/monorepo`;
|
const name = app.startsWith('@') ? app : `@${app}/monorepo`;
|
||||||
if (!await testDestination(destination)) {
|
try {
|
||||||
|
await stat(destination);
|
||||||
const error = new Error(
|
const error = new Error(
|
||||||
`@flecks/create-app: destination '${destination} already exists: aborting`,
|
`@flecks/create-app: destination '${destination} already exists: aborting`,
|
||||||
);
|
);
|
||||||
error.code = 129;
|
error.code = 129;
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
// eslint-disable-next-line no-empty
|
||||||
|
catch (error) {}
|
||||||
const fileTree = await move(name, join(__dirname, '..', 'template'));
|
const fileTree = await move(name, join(__dirname, '..', 'template'));
|
||||||
fileTree.pipe(
|
fileTree.pipe(
|
||||||
'build/flecks.yml',
|
'build/flecks.yml',
|
||||||
transform((chunk, encoding, done, stream) => {
|
new YamlStream(
|
||||||
const yml = loadYml(chunk);
|
(yml) => ({...yml, '@flecks/core': {id: app}}),
|
||||||
yml['@flecks/core'].id = app;
|
{dump: {forceQuotes: true, sortKeys: true}},
|
||||||
stream.push(dumpYml(yml, {forceQuotes: true, sortKeys: true}));
|
),
|
||||||
done();
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
// Write the tree.
|
// Write the tree.
|
||||||
await fileTree.writeTo(destination);
|
await fileTree.writeTo(destination);
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
const {stat} = require('fs/promises');
|
|
||||||
const {basename, dirname, join} = require('path');
|
|
||||||
|
|
||||||
const {transform} = require('@flecks/core/server');
|
|
||||||
|
|
||||||
const FileTree = require('./tree');
|
|
||||||
|
|
||||||
exports.testDestination = async (destination) => {
|
|
||||||
try {
|
|
||||||
await stat(destination);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
if ('ENOENT' !== error.code) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.move = async (name, source) => {
|
|
||||||
const fileTree = await FileTree.loadFrom(source);
|
|
||||||
// Renamed to avoid conflicts.
|
|
||||||
const {files} = fileTree;
|
|
||||||
fileTree.glob('**/*.noconflict')
|
|
||||||
.forEach((path) => {
|
|
||||||
files[join(dirname(path), basename(path, '.noconflict'))] = files[path];
|
|
||||||
delete files[path];
|
|
||||||
});
|
|
||||||
// Add project name to `package.json`.
|
|
||||||
fileTree.pipe(
|
|
||||||
'package.json',
|
|
||||||
transform((chunk, encoding, done, stream) => {
|
|
||||||
stream.push(JSON.stringify({name, ...JSON.parse(chunk)}));
|
|
||||||
done();
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
return fileTree;
|
|
||||||
};
|
|
|
@ -22,14 +22,13 @@
|
||||||
"create-app": "./build/cli.js"
|
"create-app": "./build/cli.js"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
|
"npm-shrinkwrap.json",
|
||||||
"server.js",
|
"server.js",
|
||||||
"template"
|
"template"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@flecks/core": "^4.0.2",
|
"@flecks/core": "^4.0.2",
|
||||||
"commander": "11.1.0",
|
"commander": "11.1.0",
|
||||||
"js-yaml": "4.1.0",
|
|
||||||
"minimatch": "^5.0.1",
|
|
||||||
"validate-npm-package-name": "^3.0.0"
|
"validate-npm-package-name": "^3.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -1 +1,5 @@
|
||||||
export {default as validate} from 'validate-npm-package-name';
|
/* eslint-disable global-require */
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
validate: require('validate-npm-package-name'),
|
||||||
|
};
|
||||||
|
|
|
@ -1,3 +1 @@
|
||||||
'@flecks/build': {}
|
|
||||||
'@flecks/core': {}
|
|
||||||
'@flecks/server': {}
|
'@flecks/server': {}
|
||||||
|
|
|
@ -11,12 +11,11 @@
|
||||||
"start": "DEBUG=@flecks/*,-*:silly npm run dev"
|
"start": "DEBUG=@flecks/*,-*:silly npm run dev"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@flecks/core": "^3.0.0",
|
"@flecks/server": "^4.0.0"
|
||||||
"@flecks/server": "^3.0.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@flecks/build": "^3.0.0",
|
"@flecks/build": "^4.0.0",
|
||||||
"@flecks/create-fleck": "^3.0.0",
|
"@flecks/create-fleck": "^4.0.0",
|
||||||
"patch-package": "^8.0.0"
|
"patch-package": "^8.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,115 +1,97 @@
|
||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
/* eslint-disable camelcase */
|
||||||
|
|
||||||
const {stat} = require('fs/promises');
|
const {
|
||||||
const {join} = require('path');
|
basename,
|
||||||
|
dirname,
|
||||||
|
join,
|
||||||
|
relative,
|
||||||
|
sep,
|
||||||
|
} = require('path');
|
||||||
|
|
||||||
const addPathsToYml = require('@flecks/build/build/add-paths-to-yml');
|
const addPathsToYml = require('@flecks/core/build/add-paths-to-yml');
|
||||||
const {program} = require('commander');
|
const {program} = require('commander');
|
||||||
|
const {move} = require('@flecks/core/build/move');
|
||||||
const {
|
const {
|
||||||
build,
|
build,
|
||||||
install,
|
install,
|
||||||
transform,
|
JsonStream,
|
||||||
} = require('@flecks/core/server');
|
} = require('@flecks/core/src/server');
|
||||||
const {move, testDestination} = require('@flecks/create-app/build/move');
|
|
||||||
const {validate} = require('@flecks/create-app/src/server');
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
FLECKS_CORE_ROOT = process.cwd(),
|
FLECKS_CORE_ROOT = process.cwd(),
|
||||||
} = process.env;
|
} = process.env;
|
||||||
|
|
||||||
const checkIsMonorepo = async () => {
|
const {
|
||||||
try {
|
npm_config_local_prefix,
|
||||||
await stat(join(FLECKS_CORE_ROOT, 'packages'));
|
npm_config_scope,
|
||||||
return true;
|
npm_package_json,
|
||||||
}
|
} = process.env;
|
||||||
catch (error) {
|
|
||||||
if ('ENOENT' !== error.code) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const monorepoScope = async () => {
|
|
||||||
try {
|
|
||||||
const {name} = require(join(FLECKS_CORE_ROOT, 'package.json'));
|
|
||||||
const [scope] = name.split('/');
|
|
||||||
return scope;
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
if ('MODULE_NOT_FOUND' !== error.code) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const target = async (fleck) => {
|
|
||||||
const {errors} = validate(fleck);
|
|
||||||
if (errors) {
|
|
||||||
throw new Error(`@flecks/create-fleck: invalid fleck name: ${errors.join(', ')}`);
|
|
||||||
}
|
|
||||||
const parts = fleck.split('/');
|
|
||||||
let pkg;
|
|
||||||
let scope;
|
|
||||||
if (1 === parts.length) {
|
|
||||||
pkg = fleck;
|
|
||||||
if (await checkIsMonorepo()) {
|
|
||||||
scope = await monorepoScope();
|
|
||||||
}
|
|
||||||
return [scope, pkg];
|
|
||||||
}
|
|
||||||
return parts;
|
|
||||||
};
|
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
program.argument('<fleck>', 'name of the fleck to create');
|
program.argument('[path]', "the path of the fleck (e.g.: 'packages/foobar')");
|
||||||
program.option('--no-add', 'do not add an entry to `build/flecks.yml`');
|
program.option('--no-add', 'do not add an entry to `build/flecks.yml`');
|
||||||
program.option('--no-alias', 'do not alias the fleck in `build/flecks.yml`');
|
program.option('--no-inherit-version', 'do not inherit root package version');
|
||||||
program.addOption(
|
program.option('--alias', 'alias the fleck in `build/flecks.yml`');
|
||||||
program.createOption('-pm,--package-manager <binary>', 'package manager binary')
|
program.option('--dry-run', 'just say what would be done without actually doing it');
|
||||||
.choices(['npm', 'bun', 'pnpm', 'yarn']),
|
program.action(async (
|
||||||
);
|
path,
|
||||||
program.action(async (fleck, {alias, add, packageManager}) => {
|
{
|
||||||
|
alias,
|
||||||
|
add,
|
||||||
|
inheritVersion,
|
||||||
|
packageManager,
|
||||||
|
},
|
||||||
|
) => {
|
||||||
try {
|
try {
|
||||||
const isMonorepo = await checkIsMonorepo();
|
if (!npm_config_local_prefix && !path) {
|
||||||
const [scope, pkg] = await target(fleck);
|
throw new Error('name required');
|
||||||
const name = [scope, pkg].filter((e) => !!e).join('/');
|
|
||||||
const destination = join(
|
|
||||||
join(...[FLECKS_CORE_ROOT].concat(isMonorepo ? ['packages'] : [])),
|
|
||||||
pkg,
|
|
||||||
);
|
|
||||||
if (!await testDestination(destination)) {
|
|
||||||
const error = new Error(
|
|
||||||
`@flecks/create-fleck: destination '${destination} already exists: aborting`,
|
|
||||||
);
|
|
||||||
error.code = 129;
|
|
||||||
throw error;
|
|
||||||
}
|
}
|
||||||
|
const root = npm_config_local_prefix || FLECKS_CORE_ROOT;
|
||||||
|
let rootJson;
|
||||||
|
try {
|
||||||
|
rootJson = require(join(root, 'package.json'));
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line no-empty
|
||||||
|
catch (error) {}
|
||||||
|
let scope;
|
||||||
|
if (npm_config_scope) {
|
||||||
|
scope = npm_config_scope;
|
||||||
|
}
|
||||||
|
else if (rootJson?.name) {
|
||||||
|
const inferredScope = rootJson.name.split('/')[0] || '';
|
||||||
|
if (inferredScope.startsWith('@')) {
|
||||||
|
scope = inferredScope;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const local = basename(path || root);
|
||||||
|
const name = scope ? `${scope}/${local}` : local;
|
||||||
const fileTree = await move(name, join(__dirname, '..', 'template'));
|
const fileTree = await move(name, join(__dirname, '..', 'template'));
|
||||||
if (isMonorepo) {
|
if (inheritVersion && rootJson?.version) {
|
||||||
const {version} = require(join(FLECKS_CORE_ROOT, 'package.json'));
|
|
||||||
// Inherit version from monorepo root.
|
// Inherit version from monorepo root.
|
||||||
fileTree.pipe(
|
const {version} = rootJson;
|
||||||
'package.json',
|
fileTree.pipe('package.json', new JsonStream((json) => ({...json, version})));
|
||||||
transform((chunk, encoding, done, stream) => {
|
|
||||||
stream.push(JSON.stringify({...JSON.parse(chunk), version}));
|
|
||||||
done();
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
// Write the tree.
|
// Write the tree.
|
||||||
|
const destination = path ? join(root, path) : dirname(npm_package_json);
|
||||||
await fileTree.writeTo(destination);
|
await fileTree.writeTo(destination);
|
||||||
// Install and build.
|
// Install and build.
|
||||||
await install({cwd: destination, packageManager});
|
await install({cwd: destination, packageManager});
|
||||||
await build({cwd: destination, packageManager});
|
await build({cwd: destination, packageManager});
|
||||||
if (isMonorepo && add) {
|
if (add) {
|
||||||
await addPathsToYml([[name].concat(alias ? `./packages/${pkg}` : []).join(':')]);
|
const maybeAliasedPath = [name]
|
||||||
|
.concat(alias ? `.${sep}${relative(root, destination)}` : [])
|
||||||
|
.join(':');
|
||||||
|
try {
|
||||||
|
await addPathsToYml([maybeAliasedPath], root);
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line no-empty
|
||||||
|
catch (error) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.error('Creation failed:', error);
|
console.error('creation failed:', error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
await program.parseAsync(process.argv);
|
await program.parseAsync(process.argv);
|
||||||
|
|
|
@ -22,15 +22,15 @@
|
||||||
"create-fleck": "./build/cli.js"
|
"create-fleck": "./build/cli.js"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
|
"npm-shrinkwrap.json",
|
||||||
"template"
|
"template"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@flecks/build": "^4.0.2",
|
|
||||||
"@flecks/core": "^4.0.2",
|
"@flecks/core": "^4.0.2",
|
||||||
"@flecks/create-app": "^4.0.2",
|
|
||||||
"commander": "11.1.0"
|
"commander": "11.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@flecks/build": "^4.0.2",
|
||||||
"@flecks/fleck": "^4.0.2"
|
"@flecks/fleck": "^4.0.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,10 +11,10 @@
|
||||||
"index.js"
|
"index.js"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@flecks/core": "^3.0.0"
|
"@flecks/core": "^4.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@flecks/build": "^3.0.0",
|
"@flecks/build": "^4.0.0",
|
||||||
"@flecks/fleck": "^3.0.0"
|
"@flecks/fleck": "^4.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const {dumpYml} = require('@flecks/build/src/server');
|
const {dumpYml} = require('@flecks/core/src/server');
|
||||||
|
|
||||||
const {generateComposeConfig, generateDockerFile} = require('./generate');
|
const {generateComposeConfig, generateDockerFile} = require('./generate');
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
const {banner} = require('@flecks/build/src/server');
|
const {banner} = require('@flecks/build/src/server');
|
||||||
|
|
||||||
|
exports.dependencies = ['@flecks/build'];
|
||||||
|
|
||||||
exports.hooks = {
|
exports.hooks = {
|
||||||
'@flecks/build.config.alter': ({server}, env, argv, flecks) => {
|
'@flecks/build.config.alter': ({server}, env, argv, flecks) => {
|
||||||
if (server) {
|
if (server) {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import {Buffer} from 'buffer';
|
||||||
import {Transform} from 'stream';
|
import {Transform} from 'stream';
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
@ -14,26 +15,42 @@ class InlineConfig extends Transform {
|
||||||
|
|
||||||
constructor(flecks, req) {
|
constructor(flecks, req) {
|
||||||
super();
|
super();
|
||||||
|
this.buffers = [];
|
||||||
this.flecks = flecks;
|
this.flecks = flecks;
|
||||||
this.req = req;
|
this.req = req;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line no-underscore-dangle
|
// eslint-disable-next-line no-underscore-dangle
|
||||||
async _transform(chunk, encoding, done) {
|
async _flush(done) {
|
||||||
const string = chunk.toString('utf8');
|
const string = Buffer.concat(this.buffers).toString();
|
||||||
const {appMountId} = this.flecks.get('@flecks/web');
|
const {appMountId} = this.flecks.get('@flecks/web');
|
||||||
const rendered = string.replaceAll(
|
const hideAttributes = 'production' === NODE_ENV ? 'data-flecks="ignore"' : '';
|
||||||
|
this.push(
|
||||||
|
string.replaceAll(
|
||||||
'<body>',
|
'<body>',
|
||||||
|
/* eslint-disable indent */
|
||||||
[
|
[
|
||||||
'<body>',
|
'<body>',
|
||||||
`<div id="${appMountId}-container">`,
|
`<div id="${appMountId}-container">`,
|
||||||
`<script${'production' === NODE_ENV ? 'data-flecks="ignore"' : ''}>window.document.querySelector('#${appMountId}-container').style.display = 'none'</script>`,
|
`<script${hideAttributes}>`,
|
||||||
`<script data-flecks="ignore">${await configSource(this.flecks, this.req)}</script>`,
|
`window.document.querySelector('#${appMountId}-container').style.display = 'none'`,
|
||||||
|
'</script>',
|
||||||
|
'<script data-flecks="ignore">',
|
||||||
|
await configSource(this.flecks, this.req),
|
||||||
|
'</script>',
|
||||||
`<div id="${appMountId}"></div>`,
|
`<div id="${appMountId}"></div>`,
|
||||||
'</div>',
|
'</div>',
|
||||||
].join(''),
|
].join(''),
|
||||||
|
/* eslint-enable indent */
|
||||||
|
),
|
||||||
);
|
);
|
||||||
this.push(rendered);
|
this.buffers = [];
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-underscore-dangle
|
||||||
|
_transform(chunk, encoding, done) {
|
||||||
|
this.buffers.push(chunk);
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user