-
I discovered presetter yesterday and today we played with it. I'm excited about a tool that can turn boilerplate into a reusable package! I have a few questions and comments; my apologies if issues are not the right channel for it. I looked at the sample preset. Unfortunately it contains quite a bit of code, which makes it somewhat difficult to comprehend what is essential for a preset and what is incidental. I think I understand from the documentation that the essential contract is quite minimal, but it's hard to see. I think a very minimal preset that just contains one config file, a single development dependency and a single script would be very helpful. The example preset offers a particular system for managing configuration files as yaml files and then converting them into a json format, with the option for overrides. I think it would be interesting to consider extracting this and create a reusable package that presets can build on. That would be another way to make the example preset less intimidating as well. My first reaction is to wonder why the files are maintained in the yaml format while they are generated as JSON. It makes it harder for me to recognize familiar configuration files. Is this because with yaml you can address overrides in a convenient manner? It won't work for all possible configuration files as not everything is expressed as JSON; I see for I spent a bit of time looking for a way to interpolate template variables, but I didn't find any. While most config files don't need a variables, in some cases it would be very useful to be able to refer to the repository or package name within a particular config file. Perhaps the system could even automatically extract this from In the example preset I don't see any examples of configuration that is stored in a directory. husky is an example of such a configuration system. Does presetter support this? Another use case is to store github actions configuration in Finally I have a question about the way scripts are integrated. We noticed that when running a script it would modify the Thanks again for producing this very interesting tool! I'm going to experiment with it some more. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 10 replies
-
Hi @faassen. I really appreciate your comments. It took me a few days to digest them and think about how to improve presetter. In fact, when I'm using presetter myself, I faced a similar issue when I was creating other presets for different project types, for example, a project for my backend with Pulumi, a project for a Gatsby site, or a project for a React component library. Initially, presetter was designed to let each preset decide how to generate the configuration files. They can dynamically decide which content to generate based on the supplied config from However, the more preset I create the more I realise there is a common pattern on how a preset is created and I don't want to copy and paste the same code to create a preset too! So to simplify the preset creation process, I'm writing V3. And here is an example of how a future preset can be created: Just one single simple typescript file as a resource manifests together with a number of templates (like this), no more other code is need. Have a look: import { resolve } from 'path';
// paths to the template directory
const TEMPLATES = resolve(__dirname, '..', 'templates');
/** config for this preset */
export interface PresetConfig {
/** configuration to be merged with .babelrc */
babel?: Record<string, unknown>;
/** configuration to be merged with .eslintrc */
eslint?: Record<string, unknown>;
/** configuration to be merged with .jestrc */
jest?: Record<string, unknown>;
/** configuration to be merged with .lintstagedrc */
lintstaged?: Record<string, unknown>;
/** patterns to be added to .npmignore */
npmignore?: string[];
/** configuration to be merged with .presetterrc */
prettier?: Record<string, unknown>;
/** configuration to be merged with tsconfig.json */
tsconfig?: Record<string, unknown>;
}
/** List of configurable variables */
export interface Variable {
/** the directory containing the whole repository (default: .) */
root?: string;
/** the directory containing all source code (default: source) */
source?: string;
/** the directory containing all extra typing files (default: types) */
types?: string;
/** the directory containing all the compiled files (default: lib) */
output?: string;
/** the directory containing all test files (default: spec) */
test?: string;
}
/** detail of linked/created configuration files and script templates */
export interface PresetAsset {
/** mapping of files generated from configuration template files (key: file path relative to the target project's root, value: template path) */
create?: Record<string, string>;
/** mapping of symlinks to generated configuration (key: file path relative to the target project's root, value: template path) */
symlink?: Record<string, string>;
/** path to the scripts template */
scripts?: string;
/** default variables */
variable?: Variable;
}
export const DEFAULT_VARIABLE: Variable = {
root: '.',
source: 'source',
types: 'types',
output: 'lib',
test: 'spec',
};
/**
* get the list of templates provided by this preset
* @returns list of preset templates
*/
export default async function (): Promise<PresetAsset> {
return {
create: {
'.gitignore': resolve(TEMPLATES, 'gitignore'),
'.github/workflows/test.yaml': resolve(TEMPLATES, 'github_workflows', 'test.yaml'),
},
symlink: {
'.babelrc.json': resolve(TEMPLATES, 'babelrc.yaml'),
'.eslintrc.json': resolve(TEMPLATES, 'eslintrc.yaml'),
'.jestrc.json': resolve(TEMPLATES, 'jestrc.yaml'),
'.lintstagedrc.json': resolve(TEMPLATES, 'lintstagedrc.yaml'),
'.npmignore': resolve(TEMPLATES, 'npmignore'),
'.prettierrc.json': resolve(TEMPLATES, 'prettierrc.yaml'),
'tsconfig.json': resolve(TEMPLATES, 'tsconfig.yaml'),
'tsconfig.build.json': resolve(TEMPLATES, 'tsconfig.build.yaml'),
},
scripts: resolve(TEMPLATES, 'scripts.yaml'),
variable: DEFAULT_VARIABLE,
};
} Regarding your question, with V3, you can provide a configuration template in For a For extends:
- eslint:recommended and you want to further extend it with {
"preset": "<your preset package>",
"config": {
"eslint": {
"extends": ["prettier"]
}
}
} Then your generated {
"extends": ["eslint:recommended", "prettier"]
} The output format will be completely depending on the extension given by the preset. For example, For variables, now I think you can see how they are set from the preset. Also, you can configure them in {
"preset": "<your preset package>",
"variable": {
"output": "dist"
}
} Let me know what do you think? |
Beta Was this translation helpful? Give feedback.
-
Regarding how scripts are integrated with your existing
The reason for this flow is to avoid reinventing the |
Beta Was this translation helpful? Give feedback.
Regarding how scripts are integrated with your existing
package.json
, here is the workflow:npm run <task name>
as usualThe reason for this flow is to avoid reinventing the
npm run
mechanism.Also, it makes sure other toolsets (e.g. npm-run-all) work too.