refactor: config gen
This commit is contained in:
parent
72042d0ee6
commit
31238b18da
2
TODO.md
2
TODO.md
|
@ -19,7 +19,7 @@
|
|||
- [x] renamed to 'build/config'?
|
||||
- [x] automatically generated list of build config
|
||||
- [ ] static documentation site generator
|
||||
- [ ] autogenerated config dox page
|
||||
- [x] autogenerated config dox page
|
||||
- [x] remove `invokeParallel()`
|
||||
- [x] Specialize `invokeReduce()` with `invokeMerge()`.
|
||||
- [x] Rename all hooks to dot-first notation; rewrite `lookupFlecks()`.
|
|
@ -69,6 +69,9 @@ export default {
|
|||
whatever: 'configuration',
|
||||
your: 1337,
|
||||
fleck: 'needs',
|
||||
/**
|
||||
* Also, comments like this will be used to automatically generate documentation.
|
||||
*/
|
||||
though: 'you should keep the values serializable',
|
||||
}),
|
||||
|
||||
|
|
|
@ -16,6 +16,9 @@ export {
|
|||
export default {
|
||||
[Hooks]: {
|
||||
'@flecks/core.config': () => ({
|
||||
/**
|
||||
* The ID of your application.
|
||||
*/
|
||||
id: 'flecks',
|
||||
}),
|
||||
},
|
||||
|
|
|
@ -63,6 +63,9 @@ export default {
|
|||
],
|
||||
'@flecks/core.commands': commands,
|
||||
'@flecks/core.config': () => ({
|
||||
/**
|
||||
* Build targets to exclude from ESLint.
|
||||
*/
|
||||
'eslint.exclude': [],
|
||||
}),
|
||||
},
|
||||
|
|
|
@ -12,11 +12,31 @@ export {createDatabaseConnection};
|
|||
export default {
|
||||
[Hooks]: {
|
||||
'@flecks/core.config': () => ({
|
||||
/**
|
||||
* The database to connect to.
|
||||
*/
|
||||
database: ':memory:',
|
||||
/**
|
||||
* SQL dialect.
|
||||
*
|
||||
* See: https://sequelize.org/v5/manual/dialects.html
|
||||
*/
|
||||
dialect: 'sqlite',
|
||||
/**
|
||||
* Database server host.
|
||||
*/
|
||||
host: undefined,
|
||||
/**
|
||||
* Database server password.
|
||||
*/
|
||||
password: undefined,
|
||||
/**
|
||||
* Database server port.
|
||||
*/
|
||||
port: undefined,
|
||||
/**
|
||||
* Database server username.
|
||||
*/
|
||||
username: undefined,
|
||||
}),
|
||||
'@flecks/core.starting': (flecks) => {
|
||||
|
|
|
@ -6,6 +6,9 @@ import startContainer from './start-container';
|
|||
export default {
|
||||
[Hooks]: {
|
||||
'@flecks/core.config': () => ({
|
||||
/**
|
||||
* Whether to run docker containers.
|
||||
*/
|
||||
enabled: true,
|
||||
}),
|
||||
'@flecks/core.commands': commands,
|
||||
|
|
|
@ -5,6 +5,7 @@ import {D} from '@flecks/core';
|
|||
|
||||
import {
|
||||
generateBuildConfigsPage,
|
||||
generateConfigPage,
|
||||
generateHookPage,
|
||||
generateTodoPage,
|
||||
} from './generate';
|
||||
|
@ -33,6 +34,9 @@ export default (program, flecks) => {
|
|||
debug('Generating build configs page...');
|
||||
const buildConfigsPage = generateBuildConfigsPage(state.buildConfigs);
|
||||
debug('generated');
|
||||
debug('Generating config page...');
|
||||
const configPage = generateConfigPage(state.configs);
|
||||
debug('generated');
|
||||
const output = join(FLECKS_CORE_ROOT, 'dox');
|
||||
await mkdir(output, {recursive: true});
|
||||
/* eslint-disable no-console */
|
||||
|
@ -47,6 +51,9 @@ export default (program, flecks) => {
|
|||
debug('Writing build configs page...');
|
||||
await writeFile(join(output, 'build-configs.md'), buildConfigsPage);
|
||||
console.log('build-configs.md');
|
||||
debug('Writing config page...');
|
||||
await writeFile(join(output, 'config.md'), configPage);
|
||||
console.log('config.md');
|
||||
console.groupEnd();
|
||||
console.log('');
|
||||
/* eslint-enable no-console */
|
||||
|
|
|
@ -25,6 +25,31 @@ export const generateBuildConfigsPage = (buildConfigs) => {
|
|||
return source.join('\n');
|
||||
};
|
||||
|
||||
export const generateConfigPage = (configs) => {
|
||||
const source = [];
|
||||
source.push('# Configuration');
|
||||
source.push('');
|
||||
source.push('This page documents all the configuration in this project.');
|
||||
source.push('');
|
||||
Object.entries(configs)
|
||||
.sort(([l], [r]) => (l < r ? -1 : 1))
|
||||
.forEach(([fleck, configs]) => {
|
||||
source.push(`## \`${fleck}\``);
|
||||
source.push('');
|
||||
configs.forEach(({comment, config, defaultValue}) => {
|
||||
comment.split('\n').forEach((line) => {
|
||||
source.push(`> ${line}`);
|
||||
});
|
||||
source.push('');
|
||||
source.push('```javascript');
|
||||
source.push(`${config}: ${defaultValue}`);
|
||||
source.push('```');
|
||||
source.push('');
|
||||
});
|
||||
});
|
||||
return source.join('\n');
|
||||
};
|
||||
|
||||
export const generateHookPage = (hooks, flecks) => {
|
||||
const {filenameRewriters} = flecks.get('@flecks/dox/server');
|
||||
const rewriteFilename = makeFilenameRewriter(filenameRewriters);
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
import {readFile} from 'fs/promises';
|
||||
import {dirname, join} from 'path';
|
||||
import {
|
||||
basename,
|
||||
dirname,
|
||||
extname,
|
||||
join,
|
||||
} from 'path';
|
||||
|
||||
import {transformAsync} from '@babel/core';
|
||||
import traverse from '@babel/traverse';
|
||||
|
@ -23,6 +28,7 @@ class ParserState {
|
|||
|
||||
constructor() {
|
||||
this.buildConfigs = [];
|
||||
this.configs = {};
|
||||
this.hooks = {};
|
||||
this.todos = [];
|
||||
}
|
||||
|
@ -31,6 +37,20 @@ class ParserState {
|
|||
this.buildConfigs.push({comment, config});
|
||||
}
|
||||
|
||||
addConfig(config, comment, filename, defaultValue) {
|
||||
const ext = extname(filename);
|
||||
const trimmed = join(dirname(filename), basename(filename, ext)).replace('/src', '');
|
||||
const fleck = 'index' === basename(trimmed) ? dirname(trimmed) : trimmed;
|
||||
if (!this.configs[fleck]) {
|
||||
this.configs[fleck] = [];
|
||||
}
|
||||
this.configs[fleck].push({
|
||||
comment,
|
||||
config,
|
||||
defaultValue,
|
||||
});
|
||||
}
|
||||
|
||||
addImplementation(hook, filename, loc) {
|
||||
this.hooks[hook] = this.hooks[hook] || {};
|
||||
this.hooks[hook].implementations = this.hooks[hook].implementations || [];
|
||||
|
@ -92,16 +112,47 @@ const FlecksBuildConfigs = (state) => (
|
|||
config = element.elements[0].value;
|
||||
}
|
||||
}
|
||||
if (config && element.leadingComments.length > 0) {
|
||||
if (config) {
|
||||
state.addBuildConfig(
|
||||
config,
|
||||
element.leadingComments.pop().value.split('\n')
|
||||
(element.leadingComments?.length > 0)
|
||||
? element.leadingComments.pop().value.split('\n')
|
||||
.map((line) => line.trim())
|
||||
.map((line) => line.replace(/^\*/, ''))
|
||||
.map((line) => line.trim())
|
||||
.filter((line) => !!line)
|
||||
.join(' ')
|
||||
.trim(),
|
||||
.trim()
|
||||
: '*No description provided.*',
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
const FlecksConfigs = (state, filename, source) => (
|
||||
implementationVisitor((property) => {
|
||||
if ('@flecks/core.config' === property.key.value) {
|
||||
if (isArrowFunctionExpression(property.value)) {
|
||||
if (isObjectExpression(property.value.body)) {
|
||||
property.value.body.properties.forEach((property) => {
|
||||
if (isIdentifier(property.key) || isStringLiteral(property.key)) {
|
||||
state.addConfig(
|
||||
property.key.name || property.key.value,
|
||||
(property.leadingComments?.length > 0)
|
||||
? property.leadingComments.pop().value.split('\n')
|
||||
.map((line) => line.trim())
|
||||
.map((line) => line.replace(/^\*/, ''))
|
||||
.map((line) => line.trim())
|
||||
.filter((line) => !!line)
|
||||
.join(' ')
|
||||
.trim()
|
||||
: '*No description provided.*',
|
||||
filename,
|
||||
source.slice(property.value.start, property.value.end),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -232,8 +283,10 @@ export const parseCode = async (code) => {
|
|||
|
||||
export const parseFile = async (filename, resolved, state) => {
|
||||
const buffer = await readFile(filename);
|
||||
const ast = await parseCode(buffer.toString('utf8'));
|
||||
const source = buffer.toString('utf8');
|
||||
const ast = await parseCode(source);
|
||||
traverse(ast, FlecksBuildConfigs(state, resolved));
|
||||
traverse(ast, FlecksConfigs(state, resolved, source));
|
||||
traverse(ast, FlecksInvocations(state, resolved));
|
||||
traverse(ast, FlecksImplementations(state, resolved));
|
||||
traverse(ast, FlecksTodos(state, resolved));
|
||||
|
|
|
@ -6,6 +6,11 @@ export default {
|
|||
[Hooks]: {
|
||||
'@flecks/core.commands': commands,
|
||||
'@flecks/core.config': () => ({
|
||||
/**
|
||||
* Rewrite the output filenames of source files.
|
||||
*
|
||||
* `filename.replace(new RegExp([key]), [value]);`
|
||||
*/
|
||||
filenameRewriters: {},
|
||||
}),
|
||||
},
|
||||
|
|
|
@ -8,6 +8,9 @@ export {default as createLimiter} from './limiter';
|
|||
export default {
|
||||
[Hooks]: {
|
||||
'@flecks/core.config': () => ({
|
||||
/**
|
||||
* All keys used to determine fingerprint.
|
||||
*/
|
||||
keys: ['ip'],
|
||||
http: {
|
||||
keys: ['ip'],
|
||||
|
|
|
@ -45,15 +45,39 @@ export default {
|
|||
'template.ejs',
|
||||
],
|
||||
'@flecks/core.config': () => ({
|
||||
/**
|
||||
* (webpack-dev-server) Host to bind.
|
||||
*/
|
||||
devHost: 'localhost',
|
||||
/**
|
||||
* (webpack-dev-server) Port to bind.
|
||||
*/
|
||||
devPort: undefined,
|
||||
/**
|
||||
* (webpack-dev-server) Public path to serve.
|
||||
*/
|
||||
devPublic: undefined,
|
||||
/**
|
||||
* (webpack-dev-server) Webpack stats output.
|
||||
*/
|
||||
devStats: 'minimal',
|
||||
/**
|
||||
* Host to bind.
|
||||
*/
|
||||
host: '0.0.0.0',
|
||||
/**
|
||||
* Build path.
|
||||
*/
|
||||
output: 'http',
|
||||
/**
|
||||
* Port to bind.
|
||||
*/
|
||||
port: 32340,
|
||||
'request.route': [],
|
||||
'request.socket': [],
|
||||
/**
|
||||
* Proxies to trust.
|
||||
*
|
||||
* See: https://www.npmjs.com/package/proxy-addr
|
||||
*/
|
||||
trust: false,
|
||||
}),
|
||||
'@flecks/core.starting': (flecks) => {
|
||||
|
|
|
@ -16,6 +16,9 @@ export {default as usePrevious} from './hooks/use-previous';
|
|||
export default {
|
||||
[Hooks]: {
|
||||
'@flecks/core.config': () => ({
|
||||
/**
|
||||
* Whether to enable server-side rendering.
|
||||
*/
|
||||
ssr: true,
|
||||
}),
|
||||
},
|
||||
|
|
|
@ -30,7 +30,13 @@ export const keys = (client, pattern) => safeKeys(client, pattern, 0);
|
|||
export default {
|
||||
[Hooks]: {
|
||||
'@flecks/core.config': () => ({
|
||||
/**
|
||||
* Redis server host.
|
||||
*/
|
||||
host: 'localhost',
|
||||
/**
|
||||
* Redis server port.
|
||||
*/
|
||||
port: 6379,
|
||||
}),
|
||||
'@flecks/docker.containers': containers,
|
||||
|
|
|
@ -3,9 +3,21 @@ import {Hooks} from '@flecks/core';
|
|||
export default {
|
||||
[Hooks]: {
|
||||
'@flecks/core.config': () => ({
|
||||
/**
|
||||
* Whether HMR is enabled.
|
||||
*/
|
||||
hot: false,
|
||||
/**
|
||||
* Whether the Node inspector is enabled.
|
||||
*/
|
||||
inspect: false,
|
||||
/**
|
||||
* Whether node profiling is enabled.
|
||||
*/
|
||||
profile: false,
|
||||
/**
|
||||
* Whether to start the server after building.
|
||||
*/
|
||||
start: false,
|
||||
}),
|
||||
},
|
||||
|
|
|
@ -5,10 +5,6 @@ import Sockets from './sockets';
|
|||
|
||||
export default {
|
||||
[Hooks]: {
|
||||
'@flecks/core.config': () => ({
|
||||
connect: [],
|
||||
'request.socket': [],
|
||||
}),
|
||||
'@flecks/http/server.request.socket': ({config: {'$flecks/socket.sockets': sockets}}) => (req, res, next) => {
|
||||
req.intercom = createIntercom(sockets, 'http');
|
||||
next();
|
||||
|
|
|
@ -7,7 +7,13 @@ import LocalStrategy from 'passport-local';
|
|||
export default {
|
||||
[Hooks]: {
|
||||
'@flecks/core.config': () => ({
|
||||
/**
|
||||
* Path to redirect to after failed login.
|
||||
*/
|
||||
failureRedirect: '/',
|
||||
/**
|
||||
* Path to redirect to after successful login.
|
||||
*/
|
||||
successRedirect: '/',
|
||||
}),
|
||||
'@flecks/db/server.models.decorate': (
|
||||
|
|
|
@ -7,6 +7,11 @@ const debug = D('@flecks/user/session');
|
|||
export default {
|
||||
[Hooks]: {
|
||||
'@flecks/core.config': () => ({
|
||||
/**
|
||||
* Set the cookie secret for session encryption.
|
||||
*
|
||||
* See: http://expressjs.com/en/resources/middleware/cookie-parser.html
|
||||
*/
|
||||
cookieSecret: (
|
||||
'Set the FLECKS_ENV_FLECKS_USER_SESSION_SERVER_cookieSecret environment variable!'
|
||||
),
|
||||
|
|
Loading…
Reference in New Issue
Block a user