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