hygen
hygen copied to clipboard
V5 take one
ideas from #119, #120, #142
It is pretty much a complete rewrite, but it should be backwards compatible and offers a lot new.
A functional pipeline. A config object is passed from the beginning of the process through to the end. Each stage involves running a function that takes and returns the config object, having changed it or performed an effect.
Promises everywhere, makes the pipeline part work.
Major lifecycle events are handled by 'resolvers'. These are: config, modules, yargsOptions, generator, yargsParams, params, templates, directives, render.
Each resolver has a set of hooks that are run during phases of the resolver. postConfig
, preRender
, missingTemplates
for example.
hooks can be added through your .hygen.js
or _templates/gen/action/index.js
files.
Modules are sets of hooks, functions, and tools that perform specific purpses. For example a logging module could add a postConfig
hook that logs out the path of the .hygen.js
file. The prompting system can be moved into a module.
TLDR - A pipeline through which a config obj flows to generate templates, with a tremendous amount of customization being possible.
This is interesting! I'll try to carve out some time this weekend to review :)
I've learned a lot, and I think this is coming along great. I built a scaffold for the resolvers with the sets of things they'd be doing. I think you can get a decent idea of the main program flow now.
I'm going to flesh out a module next, so that I can communicate how killer that idea is for a pipeline.
It's going to be great to test, powerful to use and I think, still compatible with existing templates.
.hygenjs, index.js, and prompt.js are already hygenConfig files.
There are 3 things I'd like to talk about changing. And my watchword is composition!
- single directory for
.hygen.js
and_templates
. I would like to have more of each. - frustrations with {inject:, to:} instead of {inject: {to: }, write: {to: }} (see below)
- testing environment. I'd like the test for
src/resolvers/config.jg
to besrc/resolvers/__test__/config.spec.js
I think the frontmatter needs a bit of a rethink. I'd like to set authors free by using it to set variables that they can use in the template below.
to: ...
cssFilename: styles<%- useCssModule && `.module` %>.css
---
import styles from `<%- cssFilename %>`
To do that, you have to render the frontmatter and incorporate add that to the context for rendering the body. Which is easy to do.
What I want to be true is that I can scan the keys of the front matter until I find one that I know how to do, and let that key contain the options for the 'directive'. but the most basic directive 'write to file' is the bramble in the patch.
// inject into file - I have a flag that tells me I should inject and where
to: some/file.js
inject: true
// write to file - something else has to not be here for me to do this
to: some/file.js
// I'd prefer to have 1 key per 'op' or 'directive'.
inject:
to: sdfsdf
prepend: true
file:
to: some.file
unless_exists: true
// Or as a fallback having to do this.
to: some/file.js
file: true
- The only data that matters is on hygenConfig. it will be born grow up get used and tossed aside.
- the core data flow is
(config: HygenConfig): Promise<HygenConfig>
. Resolvers and hooks use it to modify hygenConfig and pass it on. - A
.hygen.js
file is a hygenConfig object, so isprompt.js
andindex.js
and so will modules. When a config file or module is loaded, it is merged into the master object, changing data, tools, and providing hooks to customize with. - A directive maps frontmatter info into a rendering action for the template. So far: sh,message,inject,to
How do you feel about changing a few defaults?
- Allow
.hygen.js
to also be `hygen.js - renaming what used to be
{index,prompt}.js
to.hygen.js
- use
process.env.HYGEN_CONFIG_FILE
to set a specific path to find.hygen.js
- ignore directories below
_templates
name_hygen
- glob library for
.hygenignore
- better verbage to differentiate global and local sections?
#default paths
hygenConfig = {
configFile: {
templatePaths: ['_templates'],
/* this group to find config files frome cwd to root */
globalConfig: {
filenames: ['.hygen.js','hygen.js'],
searchStart: path.join(cwd, '.hygen.js'),
searchEnd: '/', /* could be /home/rincewind *./
searchLimit: 1, /* 0 for no limit */
}
hygenIgnore: {
filename: ['.hygenignore'],
searchLimit: 1, /* 0 for no limit */
}
/* to find action index/prompt files from _templates/generators/.../actions to _templates */
localConfig: {
localFilenames: ['.hygen.js','hygen.js'] /* add index.js and prompt.js here via module */
/* local search start is the action folder */
/* local search stop is always the templates dir */
searchLimit: 0,
}
/* to ignore when searching for generators, actions, and templates */
/* will use same syntax as .hygenignore */
/* not sure if this should all be one array or broken down as shown */
ignore: {
dirs: ['_hygen'],
files: ['.hygen.js','hygen.js', '.hygenignore']
actions: [],
generators: [],
templates: [],
}
}
}
starting to see where I over thought things, but mostly it's coming along well.
I'm really digging typescript, though I'm not sure of what conventions I should be using, especially when it comes to functions.
the most common type so far is
type HygenResolver = (config: HygenConfig) => Promise<HygenConfig>
I also worked out the merge rules, check src/v5/resolvers/merge/index.ts. functions are executed, arrays are concated, objects are merged only for the 2nd level, scalars are replaced.
A lot of the emerging complexity is coming from defining which files to look for in the config, ignore, prompt and param files plus the templates directory.
# defaults relative to project dir
HYGEN_TMPLS=_templates
HYGEN_CONFIG=.hygen.js
# defaults relative to action dir
HYGEN_PARAMS=index.js
HYGEN_PROMPT=prompt.js
# relative to project dir, templates dir, generator dir, action dir
HYGEN_IGNORE=.hygenignore
# treat them like $PATH and go nuts
HYGEN_TMPLS=_templates:~/code/common/hygen/templates:/shared/hygen/templates
HYGEN_CONFIG=.hygen.js:~/.config/hygen.js:~/code/.hygen.js
HYGEN_PARAMS=index.js:../index.js:../../index.js:hygen.js:../hygen.js:../../hygen.js
HYGEN_PROMPT=prompt.js:~/code/shared/hygen/typed_fields.js
HYGEN_IGNORE=.hygenignore:~/.config/.hygenignore
@jondot I could use some feedback before I do much more here.
@jondot Nice job with 5.0!
Now I really need to know if I should keep working on my idea here, or if I should spend my effort adding what I want to the current structure.
Closed in favor of #149
@jondot maybe this one should be closed, as is too outdated