@w5s/mrm-preset 1.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/.eslintignore +1 -0
  2. package/CHANGELOG.md +17 -0
  3. package/README.md +56 -0
  4. package/bootstrap/README.md +5 -0
  5. package/bootstrap/index.js +97 -0
  6. package/ci/_gitlab/AutoDevops.gitlab-ci.yml +77 -0
  7. package/ci/_gitlab/AutoDevopsInclude.gitlab-ci.yml +251 -0
  8. package/ci/_gitlab/README.md +20 -0
  9. package/ci/_gitlab/Renovate.gitlab-ci.yml +30 -0
  10. package/ci/gitlab.js +38 -0
  11. package/ci/index.js +14 -0
  12. package/commitlint/index.js +40 -0
  13. package/config.json +20 -0
  14. package/contributing/index.js +26 -0
  15. package/contributing/templates/CODE_OF_CONDUCT.md +134 -0
  16. package/core/block.js +77 -0
  17. package/core/commitlint.js +39 -0
  18. package/core/cspell.js +66 -0
  19. package/core/eslint.js +22 -0
  20. package/core/file.js +29 -0
  21. package/core/git.js +73 -0
  22. package/core/githooks.js +71 -0
  23. package/core/gitlabCI.js +8 -0
  24. package/core/jest.js +105 -0
  25. package/core/jsonFile.js +65 -0
  26. package/core/lintStaged.js +36 -0
  27. package/core/npm.js +271 -0
  28. package/core/pkg.js +97 -0
  29. package/core/project.js +58 -0
  30. package/core/semanticRelease.js +43 -0
  31. package/core/typedoc.js +82 -0
  32. package/core/vscode.js +92 -0
  33. package/core/workspace.js +6 -0
  34. package/cspell/index.js +38 -0
  35. package/editorconfig/index.js +107 -0
  36. package/eslint/index.js +127 -0
  37. package/githooks/index.js +62 -0
  38. package/githooks/templates/CODEOWNERS +4 -0
  39. package/gitignore/index.js +25 -0
  40. package/gitignore/template.js +145 -0
  41. package/jest/index.js +19 -0
  42. package/lang/.eslintrc.json +8 -0
  43. package/lang/index.js +143 -0
  44. package/lang/templates/index.spec.ts +7 -0
  45. package/lang/templates/index.ts +6 -0
  46. package/package.json +48 -0
  47. package/postconfigure/index.js +17 -0
  48. package/project/index.js +232 -0
  49. package/release/index.js +29 -0
  50. package/renovate/index.js +61 -0
  51. package/tsconfig.json +13 -0
package/lang/index.js ADDED
@@ -0,0 +1,143 @@
1
+ const { join } = require('path');
2
+ const { json, file, template, packageJson } = require('mrm-core');
3
+ const npm = require('../core/npm');
4
+ const { gitIgnore } = require('../core/git');
5
+ const project = require('../core/project');
6
+ const { eslintIgnore } = require('../core/eslint');
7
+ const { useWorkspaces } = require('../core/workspace');
8
+ const { typedoc } = require('../core/typedoc');
9
+ const pkg = require('../core/pkg');
10
+
11
+ /**
12
+ *
13
+ * @param {{
14
+ * language: 'typescript',
15
+ * tsConfig: string,
16
+ * }} config
17
+ */
18
+ function createLang({ language: languageDefault = 'typescript', tsConfig: tsConfigDefault }) {
19
+ /**
20
+ *
21
+ * @param {{
22
+ * language: 'typescript',
23
+ * }} config
24
+ */
25
+ function task({ language }) {
26
+ return task[language]();
27
+ }
28
+ task.typescript = () => {
29
+ const tsConfigPreset = tsConfigDefault;
30
+ const isApplication = packageJson().get('mrmConfig.packageArchetype') === 'application';
31
+ const hasWorkspaces = useWorkspaces();
32
+ const tsConfigSettingsName = 'tsconfig.settings.json';
33
+ const tsConfigSettings = json(tsConfigSettingsName);
34
+ const tsConfig = json('tsconfig.json');
35
+
36
+ // Should be run first
37
+ gitIgnore('Typescript', ['lib/', '*.tsbuildinfo', 'typings/']);
38
+ eslintIgnore(['lib/']);
39
+
40
+ if (hasWorkspaces) {
41
+ tsConfig
42
+ .unset('compilerOptions.rootDir')
43
+ .unset('compilerOptions.outDir')
44
+ .unset('include')
45
+ .merge({
46
+ extends: `./${tsConfigSettingsName}`,
47
+ })
48
+ .save();
49
+
50
+ file('src/index.ts').delete();
51
+ file('src/index.spec.ts').delete();
52
+ } else {
53
+ tsConfigSettings
54
+ .merge({
55
+ compilerOptions: {},
56
+ extends: tsConfigPreset,
57
+ })
58
+ .save();
59
+ tsConfig
60
+ .merge({
61
+ compilerOptions: {
62
+ outDir: './lib',
63
+ rootDir: './src',
64
+ },
65
+ extends: `./${tsConfigSettingsName}`,
66
+ include: ['./src'],
67
+ })
68
+ .save();
69
+
70
+ // Create default index
71
+ const templateDir = join(__dirname, 'templates');
72
+ if (!file('src/index.ts').exists()) {
73
+ template('src/index.ts', join(templateDir, 'index.ts')).apply().save();
74
+ }
75
+ if (!file('src/index.spec.ts').exists()) {
76
+ template('src/index.spec.ts', join(templateDir, 'index.spec.ts')).apply().save();
77
+ }
78
+ }
79
+ // Application setup
80
+ pkg.withPackageJson((packageFile) => {
81
+ if (isApplication) {
82
+ pkg.script(packageFile, {
83
+ name: project.develop,
84
+ script:
85
+ "NODE_ENV=development ts-node-dev --require='tsconfig-paths/register' -r dotenv/config -- ./src/index.ts dotenv_config_path=.env",
86
+ state: 'present',
87
+ });
88
+ }
89
+ });
90
+ npm.dependency({
91
+ dev: true,
92
+ name: ['ts-node-dev', 'tsconfig-paths'],
93
+ state: isApplication ? 'present' : 'absent',
94
+ });
95
+
96
+ // Dependencies
97
+ npm.dependency({
98
+ dev: true,
99
+ name: ['typescript', '@types/node', tsConfigPreset],
100
+ state: 'present',
101
+ });
102
+
103
+ typedoc({
104
+ state: 'present',
105
+ update: (config) => ({
106
+ // Default values
107
+ tsconfig: 'tsconfig.json',
108
+ excludePrivate: true,
109
+ excludeExternals: true,
110
+ readme: 'README.md',
111
+ theme: 'default',
112
+ // Inherits current
113
+ ...config,
114
+ // Force values
115
+ out: 'public',
116
+ exclude: [
117
+ '**/build/**/*',
118
+ '**/example/**/*',
119
+ '**/lib/**/*',
120
+ '**/node_modules/**',
121
+ '**/__tests__/*.(ts|tsx)',
122
+ '**/*.(spec|test).(ts|tsx)',
123
+ ],
124
+ }),
125
+ });
126
+ };
127
+
128
+ task.description = 'Setup Programming Language';
129
+ task.parameters = {
130
+ language: {
131
+ default: languageDefault,
132
+ message: 'Enter Programming language name',
133
+ type: 'input',
134
+ },
135
+ };
136
+
137
+ return task;
138
+ }
139
+
140
+ module.exports = createLang({
141
+ language: 'typescript',
142
+ tsConfig: '@w5s/ts-config',
143
+ });
@@ -0,0 +1,7 @@
1
+ import { main } from '.';
2
+
3
+ describe('index', () => {
4
+ test('main', () => {
5
+ expect(typeof main).toBe('function');
6
+ });
7
+ });
@@ -0,0 +1,6 @@
1
+ export async function main(): Promise<void> {
2
+ // TODO
3
+ }
4
+
5
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
6
+ main();
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@w5s/mrm-preset",
3
+ "version": "1.0.0-alpha.1",
4
+ "description": "Mrm configuration presets",
5
+ "keywords": [
6
+ "mrm",
7
+ "config",
8
+ "bootstrap"
9
+ ],
10
+ "homepage": "https://github.com/w5s/project-config/blob/master/packages/mrm-preset#readme",
11
+ "bugs": {
12
+ "url": "https://github.com/w5s/project-config.git/issues"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/w5s/project-config.git",
17
+ "directory": "packages/mrm-preset"
18
+ },
19
+ "license": "MIT",
20
+ "author": "Julien Polo <julien.polo@gmail.com>",
21
+ "main": "config.json",
22
+ "scripts": {
23
+ "build": "npm-run-all -p 'build:*'",
24
+ "build:empty": ":",
25
+ "build:tsc": "tsc --noEmit --skipLibCheck",
26
+ "docs": "md-magic --path '**/*.md' --ignore='node_modules'",
27
+ "format": "eslint . --fix",
28
+ "lint": "eslint .",
29
+ "test": "mkdir _tester; cd _tester; ../node_modules/.bin/mrm bootstrap --dir ..; ../node_modules/.bin/mrm configure --dir .."
30
+ },
31
+ "dependencies": {
32
+ "debug": "^4.3.3",
33
+ "mrm-core": "^6.0.0",
34
+ "semver-intersect": "^1.4.0",
35
+ "sync-directory": "^4.0.0"
36
+ },
37
+ "devDependencies": {
38
+ "@types/debug": "^4.1.7",
39
+ "mrm": "3.0.10"
40
+ },
41
+ "engines": {
42
+ "node": ">=12.x",
43
+ "yarn": ">=1.x"
44
+ },
45
+ "publishConfig": {
46
+ "access": "public"
47
+ }
48
+ }
@@ -0,0 +1,17 @@
1
+ const { spawnSync } = require('child_process');
2
+ const { packageJson } = require('mrm-core');
3
+ const project = require('../core/project');
4
+ const pkg = require('../core/pkg');
5
+
6
+ function task() {
7
+ const packageFile = packageJson();
8
+ const packageManager = pkg.manager(packageFile);
9
+ const formatResult = spawnSync(packageManager, ['run', project.format]);
10
+ if (formatResult.status !== 0) {
11
+ // eslint-disable-next-line no-console
12
+ console.error('Error: to format code\n', formatResult.output.join(''));
13
+ }
14
+ }
15
+ task.description = 'Sort scripts';
16
+
17
+ module.exports = task;
@@ -0,0 +1,232 @@
1
+ const { packageJson, json, makeDirs } = require('mrm-core');
2
+ const git = require('../core/git');
3
+ const pkg = require('../core/pkg');
4
+ const npm = require('../core/npm');
5
+ const { vscodeTask } = require('../core/vscode');
6
+ const project = require('../core/project');
7
+ const mrmPackageJson = require('../package.json');
8
+
9
+ function task() {
10
+ const packageFile = packageJson();
11
+ const gitSupported = git.hasGit();
12
+ const useWorkspace = packageFile.get('mrmConfig.packageArchetype') === 'workspace';
13
+ const packageManager = pkg.manager(packageFile);
14
+
15
+ /**
16
+ *
17
+ * @param {string} script
18
+ */
19
+ const npmRun = (script) => {
20
+ switch (script) {
21
+ case project.install:
22
+ case project.test:
23
+ return `npm ${script}`;
24
+ default:
25
+ return `npm run ${script}`;
26
+ }
27
+ };
28
+ /**
29
+ *
30
+ * @param {string} script
31
+ */
32
+ const lernaRun = (script) => {
33
+ return `lerna run ${script}`;
34
+ };
35
+ /**
36
+ *
37
+ * @param {string} script
38
+ */
39
+ const npmRunAll = (script) => {
40
+ return `npm-run-all -p "${script}:*"`;
41
+ };
42
+
43
+ // Detect git repository
44
+ pkg.value(packageFile, {
45
+ path: 'repository',
46
+ state: 'present',
47
+ update: () => {
48
+ const gitRepository = git.remoteSync();
49
+ if (gitRepository) {
50
+ return {
51
+ type: 'git',
52
+ url: gitRepository,
53
+ };
54
+ }
55
+
56
+ return undefined;
57
+ },
58
+ });
59
+
60
+ // build & clean
61
+ pkg.script(packageFile, {
62
+ name: project.build,
63
+ script: npmRunAll(project.build),
64
+ state: 'present',
65
+ });
66
+ pkg.script(packageFile, {
67
+ name: `${project.build}:empty`,
68
+ script: pkg.emptyScript,
69
+ state: 'present',
70
+ });
71
+ pkg.script(packageFile, {
72
+ name: `${project.build}:packages`,
73
+ script: lernaRun(project.build),
74
+ state: useWorkspace ? 'present' : 'absent',
75
+ });
76
+ pkg.script(packageFile, {
77
+ name: project.clean,
78
+ script: useWorkspace ? lernaRun(project.clean) : pkg.emptyScript,
79
+ state: useWorkspace ? 'present' : 'default',
80
+ });
81
+
82
+ // develop & auto build & load
83
+ pkg.script(packageFile, {
84
+ name: project.develop,
85
+ script: pkg.emptyScript,
86
+ state: 'default',
87
+ });
88
+
89
+ // lint
90
+ pkg.script(packageFile, {
91
+ name: project.lint,
92
+ script: pkg.emptyScript,
93
+ state: 'default',
94
+ });
95
+ pkg.script(packageFile, {
96
+ name: project.format,
97
+ script: pkg.emptyScript,
98
+ state: 'default',
99
+ });
100
+
101
+ // test
102
+ pkg.script(packageFile, {
103
+ name: project.coverage,
104
+ script: pkg.emptyScript,
105
+ state: 'default',
106
+ });
107
+ pkg.script(packageFile, {
108
+ name: project.test,
109
+ script: useWorkspace ? lernaRun(project.test) : pkg.emptyScript,
110
+ state: useWorkspace ? 'present' : 'default',
111
+ });
112
+ pkg.script(packageFile, {
113
+ name: project.validate,
114
+ script: `${npmRun(project.build)} && ${npmRun(project.lint)} && ${npmRun(project.test)}`,
115
+ state: 'present',
116
+ });
117
+
118
+ // code analysis
119
+ pkg.script(packageFile, {
120
+ name: project.codeAnalysis,
121
+ script: pkg.emptyScript,
122
+ state: 'default',
123
+ });
124
+
125
+ // prepare
126
+ pkg.script(packageFile, {
127
+ name: project.prepare,
128
+ script: npmRunAll(project.prepare),
129
+ state: 'present',
130
+ });
131
+ pkg.script(packageFile, {
132
+ name: `${project.prepare}:empty`,
133
+ script: pkg.emptyScript,
134
+ state: 'default',
135
+ });
136
+ pkg.script(packageFile, {
137
+ name: `${project.prepare}:packages`,
138
+ script: 'lerna bootstrap',
139
+ state: useWorkspace ? 'present' : 'absent',
140
+ });
141
+
142
+ // rescue
143
+ pkg.script(packageFile, {
144
+ name: project.rescue,
145
+ script: `${gitSupported ? 'git clean -fdx' : ''};${packageManager} install`,
146
+ state: 'present',
147
+ });
148
+
149
+ // release
150
+ pkg.script(packageFile, {
151
+ name: project.release,
152
+ script: pkg.emptyScript,
153
+ state: 'default',
154
+ });
155
+
156
+ // workspace
157
+ const lernaConfig = json('lerna.json', {
158
+ version: packageFile.get('version'),
159
+ });
160
+ if (useWorkspace) {
161
+ const packages = ['packages/*'];
162
+ const versionIndependent = lernaConfig.get('version') === 'independent';
163
+ packageFile.merge({ workspaces: { packages } });
164
+ lernaConfig.merge({
165
+ command: {
166
+ publish: {
167
+ conventionalCommits: true,
168
+ npmClient: 'npm',
169
+ },
170
+ version: {
171
+ message: `chore(release): publish${versionIndependent ? '' : ' %s'}`,
172
+ },
173
+ },
174
+ npmClient: packageManager,
175
+ useWorkspaces: useWorkspace,
176
+ });
177
+ lernaConfig.save();
178
+ makeDirs('packages');
179
+ } else {
180
+ packageFile.unset('workspaces');
181
+ lernaConfig.delete();
182
+ }
183
+
184
+ // Engine
185
+ pkg.engineMinVersion(
186
+ packageFile,
187
+ Object.assign(
188
+ {
189
+ node: '>=12.x',
190
+ yarn: '>=1.x',
191
+ npm: '>=6.x',
192
+ },
193
+ mrmPackageJson.engines
194
+ )
195
+ );
196
+ packageFile.save();
197
+
198
+ // Dependencies
199
+ npm.dependency({
200
+ dev: true,
201
+ name: ['npm-run-all'],
202
+ state: 'present',
203
+ });
204
+ npm.dependency({
205
+ dev: true,
206
+ name: ['lerna'],
207
+ state: useWorkspace ? 'present' : 'absent',
208
+ });
209
+
210
+ // VSCode
211
+ vscodeTask({
212
+ group: {
213
+ isDefault: true,
214
+ kind: 'build',
215
+ },
216
+ script: 'build',
217
+ type: 'npm',
218
+ });
219
+ vscodeTask({
220
+ group: {
221
+ isDefault: true,
222
+ kind: 'test',
223
+ },
224
+ script: 'test',
225
+ type: 'npm',
226
+ });
227
+ }
228
+
229
+ task.description = 'Init project';
230
+ task.parameters = {};
231
+
232
+ module.exports = task;
@@ -0,0 +1,29 @@
1
+ const { packageJson } = require('mrm-core');
2
+ const pkg = require('../core/pkg');
3
+ const project = require('../core/project');
4
+ const { semanticRelease } = require('../core/semanticRelease');
5
+
6
+ function task() {
7
+ const useWorkspace = packageJson().get('mrmConfig.packageArchetype') === 'workspace';
8
+
9
+ // release
10
+ pkg.withPackageJson((packageFile) => {
11
+ pkg.script(packageFile, {
12
+ name: project.release,
13
+ // eslint-disable-next-line no-template-curly-in-string
14
+ script: useWorkspace ? 'CI=$(is-ci) lerna publish ${CI:+"--yes"}' : semanticRelease.command(),
15
+ state: 'present',
16
+ });
17
+ });
18
+
19
+ // Dependencies
20
+ semanticRelease({
21
+ state: useWorkspace ? 'absent' : 'present',
22
+ preset: '@semantic-release/gitlab-config', // TODO: cherry pick plugins depending on context (github, gitlab, etc)
23
+ });
24
+ }
25
+
26
+ task.description = 'Setup release task';
27
+ task.parameters = {};
28
+
29
+ module.exports = task;
@@ -0,0 +1,61 @@
1
+ const { json, packageJson } = require('mrm-core');
2
+ const { hasGit } = require('../core/git');
3
+
4
+ /**
5
+ *
6
+ * @param {{
7
+ * renovatePresetApplication: string
8
+ * renovatePresetLibrary: string
9
+ * }} config
10
+ */
11
+ function createRenovate({ renovatePresetApplication, renovatePresetLibrary }) {
12
+ /**
13
+ *
14
+ * @param {{
15
+ * renovatePreset: string
16
+ * }} parameters
17
+ */
18
+ function task({ renovatePreset }) {
19
+ const gitSupported = hasGit();
20
+
21
+ if (gitSupported) {
22
+ const packageArchetype = packageJson().get('mrmConfig.packageArchetype', 'library');
23
+ const renovatePresetResolved =
24
+ renovatePreset || (packageArchetype === 'application' ? renovatePresetApplication : renovatePresetLibrary);
25
+ const renovateFile = json('renovate.json');
26
+ renovateFile.merge({
27
+ $schema: 'https://docs.renovatebot.com/renovate-schema.json',
28
+ ignorePaths: ['**/node_modules/**'],
29
+ });
30
+ renovateFile.set(
31
+ 'extends',
32
+ [renovatePresetResolved].concat(
33
+ renovateFile.get('extends', []).filter(
34
+ /**
35
+ * @param {string} extension
36
+ */
37
+ (extension) => {
38
+ return extension !== renovatePresetApplication && extension !== renovatePresetLibrary;
39
+ }
40
+ )
41
+ )
42
+ );
43
+ renovateFile.save();
44
+ }
45
+ }
46
+
47
+ task.description = 'Setup Renovate';
48
+ task.parameters = {
49
+ renovatePreset: {
50
+ message: 'Enter Renovate preset name',
51
+ type: 'input',
52
+ },
53
+ };
54
+
55
+ return task;
56
+ }
57
+
58
+ module.exports = createRenovate({
59
+ renovatePresetApplication: '@w5s/renovate-config:application',
60
+ renovatePresetLibrary: '@w5s/renovate-config:library',
61
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "allowJs": true,
5
+ "checkJs": true,
6
+ "noEmit": true,
7
+ "resolveJsonModule": true
8
+ },
9
+ "exclude": [
10
+ "**/templates/**",
11
+ "_tester"
12
+ ]
13
+ }