@dimensional-innovations/tool-config 1.0.0

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 (50) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +646 -0
  3. package/bin/setup-tool-config.js +675 -0
  4. package/package.json +168 -0
  5. package/src/detectors.js +261 -0
  6. package/src/index.js +64 -0
  7. package/src/tools/eslint/index.js +287 -0
  8. package/src/tools/eslint/presets/base.js +82 -0
  9. package/src/tools/eslint/presets/environments/browser.js +16 -0
  10. package/src/tools/eslint/presets/environments/node.js +21 -0
  11. package/src/tools/eslint/presets/environments/universal.js +18 -0
  12. package/src/tools/eslint/presets/frameworks/angular.js +74 -0
  13. package/src/tools/eslint/presets/frameworks/astro.js +38 -0
  14. package/src/tools/eslint/presets/frameworks/node.js +57 -0
  15. package/src/tools/eslint/presets/frameworks/react.js +76 -0
  16. package/src/tools/eslint/presets/frameworks/solid.js +45 -0
  17. package/src/tools/eslint/presets/frameworks/svelte.js +78 -0
  18. package/src/tools/eslint/presets/frameworks/vanilla.js +16 -0
  19. package/src/tools/eslint/presets/frameworks/vue.js +125 -0
  20. package/src/tools/eslint/presets/imports.js +41 -0
  21. package/src/tools/eslint/presets/typescript.js +131 -0
  22. package/src/tools/prettier/README.md +398 -0
  23. package/src/tools/prettier/index.js +114 -0
  24. package/src/tools/prettier/presets/base.js +36 -0
  25. package/src/tools/prettier/presets/frameworks/astro.js +15 -0
  26. package/src/tools/prettier/presets/frameworks/react.js +15 -0
  27. package/src/tools/prettier/presets/frameworks/svelte.js +22 -0
  28. package/src/tools/prettier/presets/frameworks/vanilla.js +13 -0
  29. package/src/tools/prettier/presets/frameworks/vue.js +20 -0
  30. package/src/tools/prettier/presets/prettierignore.js +56 -0
  31. package/src/tools/semantic-release/CI_SETUP.md +66 -0
  32. package/src/tools/semantic-release/README.md +533 -0
  33. package/src/tools/semantic-release/index.js +130 -0
  34. package/src/tools/semantic-release/presets/default.js +37 -0
  35. package/src/tools/semantic-release/presets/library.js +58 -0
  36. package/src/tools/semantic-release/presets/monorepo.js +48 -0
  37. package/src/tools/semantic-release/templates/.gitlab-ci.yml +85 -0
  38. package/src/tools/semantic-release/templates/bitbucket-pipelines.yml +100 -0
  39. package/src/tools/semantic-release/templates/github-workflow.yml +107 -0
  40. package/src/tools/stylelint/README.md +425 -0
  41. package/src/tools/stylelint/index.js +191 -0
  42. package/src/tools/stylelint/presets/base.js +50 -0
  43. package/src/tools/stylelint/presets/css-modules.js +43 -0
  44. package/src/tools/stylelint/presets/frameworks/react.js +18 -0
  45. package/src/tools/stylelint/presets/frameworks/svelte.js +28 -0
  46. package/src/tools/stylelint/presets/frameworks/vanilla.js +14 -0
  47. package/src/tools/stylelint/presets/frameworks/vue.js +38 -0
  48. package/src/tools/stylelint/presets/scss.js +83 -0
  49. package/src/tools/stylelint/presets/tailwind.js +49 -0
  50. package/src/utils/package-reader.js +42 -0
package/package.json ADDED
@@ -0,0 +1,168 @@
1
+ {
2
+ "name": "@dimensional-innovations/tool-config",
3
+ "version": "1.0.0",
4
+ "description": "Universal configuration package for ESLint, Prettier, Stylelint, and semantic-release with auto-detection for React, Vue, Svelte, Solid, Astro, Angular, and more",
5
+ "license": "MIT",
6
+ "author": {
7
+ "name": "J.D. Hillen",
8
+ "email": "jdhillen@dimin.com",
9
+ "url": "https://dimin.com"
10
+ },
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://gitlab.com/dimensional-innovations/tool-config.git"
14
+ },
15
+ "homepage": "https://gitlab.com/dimensional-innovations/tool-config#readme",
16
+ "bugs": {
17
+ "url": "https://gitlab.com/dimensional-innovations/tool-config/issues"
18
+ },
19
+ "keywords": [
20
+ "eslint",
21
+ "eslint-config",
22
+ "prettier",
23
+ "stylelint",
24
+ "semantic-release",
25
+ "react",
26
+ "vue",
27
+ "svelte",
28
+ "solid",
29
+ "astro",
30
+ "angular",
31
+ "typescript",
32
+ "javascript",
33
+ "auto-detect",
34
+ "universal",
35
+ "config",
36
+ "tool-config"
37
+ ],
38
+ "type": "module",
39
+ "main": "./src/index.js",
40
+ "bin": {
41
+ "setup-tool-config": "bin/setup-tool-config.js"
42
+ },
43
+ "files": [
44
+ "src/**",
45
+ "bin/**",
46
+ "README.md",
47
+ "LICENSE"
48
+ ],
49
+ "engines": {
50
+ "node": ">=22.12.0"
51
+ },
52
+ "scripts": {
53
+ "lint": "eslint .",
54
+ "lint:fix": "eslint --fix .",
55
+ "prettier": "npx prettier --check .",
56
+ "prettier:fix": "npx prettier --write .",
57
+ "test": "vitest run",
58
+ "test:watch": "vitest",
59
+ "test:ui": "vitest --ui",
60
+ "test:coverage": "vitest run --coverage",
61
+ "release": "semantic-release",
62
+ "prepare": "husky",
63
+ "style": "stylelint \"**/*.css\"",
64
+ "style:fix": "stylelint \"**/*.css\" --fix"
65
+ },
66
+ "dependencies": {
67
+ "@eslint/compat": "^1.4.0",
68
+ "@eslint/js": "^9.37.0",
69
+ "@typescript-eslint/eslint-plugin": "^8.46.0",
70
+ "@typescript-eslint/parser": "^8.46.0",
71
+ "astro-eslint-parser": "^1.2.2",
72
+ "eslint": ">=9.0.0",
73
+ "eslint-plugin-astro": "^1.3.1",
74
+ "eslint-plugin-import": "^2.32.0",
75
+ "eslint-plugin-react": "^7.37.0",
76
+ "eslint-plugin-react-hooks": "^6.1.1",
77
+ "eslint-plugin-solid": "^0.14.5",
78
+ "eslint-plugin-svelte": "^3.12.4",
79
+ "eslint-plugin-vue": "^10.5.0",
80
+ "globals": "^16.4.0",
81
+ "postcss-scss": "^4.0.9",
82
+ "prettier": ">=3.0.0",
83
+ "prompts": "^2.4.2",
84
+ "stylelint": ">=16.0.0",
85
+ "stylelint-config-standard": "^39.0.1",
86
+ "stylelint-config-standard-scss": "^16.0.0",
87
+ "svelte-eslint-parser": "^1.3.3",
88
+ "typescript-eslint": "^8.46.0",
89
+ "vue-eslint-parser": "^10.2.0"
90
+ },
91
+ "peerDependencies": {
92
+ "astro": ">=3.0.0 || >=4.0.0 || >=5.0.0",
93
+ "eslint": ">=9.0.0",
94
+ "less": ">=4.0.0",
95
+ "postcss-html": ">=1.0.0",
96
+ "prettier": ">=3.0.0",
97
+ "prettier-plugin-astro": ">=0.12.0",
98
+ "prettier-plugin-svelte": ">=3.0.0",
99
+ "sass": ">=1.0.0",
100
+ "solid-js": ">=1.0.0",
101
+ "stylelint": ">=16.0.0",
102
+ "stylelint-config-standard-vue": ">=1.0.0",
103
+ "svelte": ">=3.0.0 || >=4.0.0 || >=5.0.0",
104
+ "tailwindcss": ">=3.0.0",
105
+ "typescript": ">=5.0.0"
106
+ },
107
+ "peerDependenciesMeta": {
108
+ "astro": {
109
+ "optional": true
110
+ },
111
+ "eslint": {
112
+ "optional": true
113
+ },
114
+ "less": {
115
+ "optional": true
116
+ },
117
+ "postcss-html": {
118
+ "optional": true
119
+ },
120
+ "prettier": {
121
+ "optional": true
122
+ },
123
+ "prettier-plugin-astro": {
124
+ "optional": true
125
+ },
126
+ "prettier-plugin-svelte": {
127
+ "optional": true
128
+ },
129
+ "sass": {
130
+ "optional": true
131
+ },
132
+ "solid-js": {
133
+ "optional": true
134
+ },
135
+ "stylelint": {
136
+ "optional": true
137
+ },
138
+ "stylelint-config-standard-vue": {
139
+ "optional": true
140
+ },
141
+ "svelte": {
142
+ "optional": true
143
+ },
144
+ "tailwindcss": {
145
+ "optional": true
146
+ },
147
+ "typescript": {
148
+ "optional": true
149
+ }
150
+ },
151
+ "devDependencies": {
152
+ "@semantic-release/changelog": "^6.0.3",
153
+ "@semantic-release/git": "^10.0.1",
154
+ "@semantic-release/gitlab": "^13.2.9",
155
+ "@vitest/coverage-v8": "^3.2.4",
156
+ "@vitest/ui": "^3.2.4",
157
+ "astro": "^5.14.1",
158
+ "husky": "^9.1.7",
159
+ "semantic-release": "^24.2.9",
160
+ "solid-js": "^1.9.9",
161
+ "svelte": "^5.39.9",
162
+ "typescript": "^5.9.3",
163
+ "vitest": "^3.2.4"
164
+ },
165
+ "publishConfig": {
166
+ "access": "public"
167
+ }
168
+ }
@@ -0,0 +1,261 @@
1
+ import { execSync } from 'child_process'
2
+ import { existsSync } from 'fs'
3
+ import { join } from 'path'
4
+
5
+ import { getAllDependencies, readPackageJson } from './utils/package-reader.js'
6
+
7
+ /**
8
+ * Check for React meta-frameworks
9
+ */
10
+ function detectReactMetaFramework(deps) {
11
+ return (
12
+ deps.next ||
13
+ deps['@next/core'] ||
14
+ deps.remix ||
15
+ deps['@remix-run/react'] ||
16
+ deps['@remix-run/node'] ||
17
+ deps.gatsby ||
18
+ deps['gatsby-link']
19
+ )
20
+ }
21
+
22
+ /**
23
+ * Check for Vue meta-frameworks
24
+ */
25
+ function detectVueMetaFramework(deps) {
26
+ return deps.nuxt || deps['nuxt3']
27
+ }
28
+
29
+ /**
30
+ * Check for Svelte meta-frameworks
31
+ */
32
+ function detectSvelteMetaFramework(deps) {
33
+ return deps['@sveltejs/kit']
34
+ }
35
+
36
+ /**
37
+ * Check for base framework dependencies
38
+ */
39
+ function detectBaseFramework(deps) {
40
+ if (deps.react || deps['react-dom']) return 'react'
41
+ if (deps.vue || deps['@vue/runtime-core']) return 'vue'
42
+ if (deps['@angular/core']) return 'angular'
43
+ if (deps.svelte) return 'svelte'
44
+ if (deps['solid-js']) return 'solid'
45
+ if (deps.astro) return 'astro'
46
+ return null
47
+ }
48
+
49
+ /**
50
+ * Check if project is a Node.js backend
51
+ */
52
+ function isNodeBackend(pkg, deps, cwd) {
53
+ if (pkg.type !== 'module') return false
54
+
55
+ const hasNodeFramework = deps.express || deps.fastify || deps.koa || deps['@hapi/hapi']
56
+ const hasServerFiles =
57
+ existsSync(join(cwd, 'server.js')) ||
58
+ existsSync(join(cwd, 'app.js')) ||
59
+ (existsSync(join(cwd, 'index.js')) && existsSync(join(cwd, 'routes')))
60
+
61
+ return hasNodeFramework || hasServerFiles
62
+ }
63
+
64
+ /**
65
+ * Detect the framework being used in the project
66
+ * @param {string} cwd - Current working directory
67
+ * @returns {string} Detected framework name
68
+ */
69
+ export function detectFramework(cwd = process.cwd()) {
70
+ const pkg = readPackageJson(cwd)
71
+
72
+ if (!pkg) {
73
+ console.warn('⚠️ Could not find package.json, defaulting to vanilla JavaScript')
74
+ return 'vanilla'
75
+ }
76
+
77
+ const deps = getAllDependencies(pkg)
78
+
79
+ // Check meta-frameworks first
80
+ if (detectReactMetaFramework(deps)) return 'react'
81
+ if (detectVueMetaFramework(deps)) return 'vue'
82
+ if (detectSvelteMetaFramework(deps)) return 'svelte'
83
+
84
+ // Check base frameworks
85
+ const baseFramework = detectBaseFramework(deps)
86
+ if (baseFramework) return baseFramework
87
+
88
+ // Check Node.js backend
89
+ if (isNodeBackend(pkg, deps, cwd)) return 'node'
90
+
91
+ // Default to vanilla JavaScript
92
+ return 'vanilla'
93
+ }
94
+
95
+ /**
96
+ * Detect the environment (browser, node, or universal)
97
+ * @param {string} framework - Detected framework
98
+ * @param {string} cwd - Current working directory
99
+ * @returns {string} Environment type
100
+ */
101
+ export function detectEnvironment(framework, cwd = process.cwd()) {
102
+ // Framework-specific defaults
103
+ if (framework === 'node') {
104
+ return 'node'
105
+ }
106
+
107
+ // Frontend frameworks default to browser
108
+ if (['react', 'vue', 'svelte', 'solid', 'angular'].includes(framework)) {
109
+ return 'browser'
110
+ }
111
+
112
+ // Astro uses islands architecture (both browser and node)
113
+ if (framework === 'astro') {
114
+ return 'universal'
115
+ }
116
+
117
+ // Check for mixed environment indicators
118
+ const hasServerCode =
119
+ existsSync(join(cwd, 'server')) ||
120
+ existsSync(join(cwd, 'api')) ||
121
+ existsSync(join(cwd, 'backend'))
122
+
123
+ if (hasServerCode) {
124
+ return 'universal'
125
+ }
126
+
127
+ // Default to browser for frontend projects
128
+ return 'browser'
129
+ }
130
+
131
+ /**
132
+ * Detect if TypeScript is being used
133
+ * @param {string} cwd - Current working directory
134
+ * @returns {boolean} True if TypeScript is detected
135
+ */
136
+ export function detectTypeScript(cwd = process.cwd()) {
137
+ return existsSync(join(cwd, 'tsconfig.json'))
138
+ }
139
+
140
+ /**
141
+ * Detect Git provider from repository URL
142
+ * @param {string} cwd - Current working directory
143
+ * @returns {string} Git provider ('gitlab', 'github', 'bitbucket', or null)
144
+ */
145
+ export function detectGitProvider(cwd = process.cwd()) {
146
+ // Try package.json repository field first
147
+ const pkg = readPackageJson(cwd)
148
+ if (pkg?.repository) {
149
+ const repoUrl = typeof pkg.repository === 'string' ? pkg.repository : pkg.repository.url || ''
150
+
151
+ if (repoUrl.includes('gitlab.com')) return 'gitlab'
152
+ if (repoUrl.includes('github.com')) return 'github'
153
+ if (repoUrl.includes('bitbucket.org')) return 'bitbucket'
154
+
155
+ // If repository field exists but provider not recognized, return null
156
+ // Don't fallback to git remote if package.json explicitly specifies a repo
157
+ return null
158
+ }
159
+
160
+ // Try git remote as fallback only if no repository field in package.json
161
+ try {
162
+ const remoteUrl = execSync('git remote get-url origin', {
163
+ cwd,
164
+ encoding: 'utf8',
165
+ stdio: ['pipe', 'pipe', 'ignore']
166
+ }).trim()
167
+
168
+ if (remoteUrl.includes('gitlab.com')) return 'gitlab'
169
+ if (remoteUrl.includes('github.com')) return 'github'
170
+ if (remoteUrl.includes('bitbucket.org')) return 'bitbucket'
171
+ } catch {
172
+ // Git command failed or not a git repository
173
+ }
174
+
175
+ // Default to null (no provider detected)
176
+ return null
177
+ }
178
+
179
+ /**
180
+ * Detect CSS type and variants
181
+ * @param {string} cwd - Current working directory
182
+ * @returns {Object} CSS type detection results
183
+ */
184
+ export function detectCssType(cwd = process.cwd()) {
185
+ const pkg = readPackageJson(cwd)
186
+
187
+ const results = {
188
+ preprocessor: null, // 'scss', 'sass', 'less', null
189
+ tailwind: false,
190
+ modules: false,
191
+ postcss: false
192
+ }
193
+
194
+ // Detect SCSS/Sass
195
+ const hasSass =
196
+ pkg?.dependencies?.sass ||
197
+ pkg?.devDependencies?.sass ||
198
+ pkg?.dependencies?.['node-sass'] ||
199
+ pkg?.devDependencies?.['node-sass'] ||
200
+ pkg?.dependencies?.['sass-embedded'] ||
201
+ pkg?.devDependencies?.['sass-embedded']
202
+
203
+ if (hasSass) {
204
+ results.preprocessor = 'scss'
205
+ }
206
+
207
+ // Detect Less
208
+ const hasLess = pkg?.dependencies?.less || pkg?.devDependencies?.less
209
+
210
+ if (hasLess && !hasSass) {
211
+ // SCSS takes precedence if both exist
212
+ results.preprocessor = 'less'
213
+ }
214
+
215
+ // Detect Tailwind CSS
216
+ const hasTailwind = pkg?.dependencies?.tailwindcss || pkg?.devDependencies?.tailwindcss
217
+
218
+ if (hasTailwind) {
219
+ // Check for config file
220
+ results.tailwind =
221
+ existsSync(join(cwd, 'tailwind.config.js')) ||
222
+ existsSync(join(cwd, 'tailwind.config.ts')) ||
223
+ existsSync(join(cwd, 'tailwind.config.mjs')) ||
224
+ existsSync(join(cwd, 'tailwind.config.cjs'))
225
+ }
226
+
227
+ // Detect PostCSS config
228
+ results.postcss =
229
+ existsSync(join(cwd, 'postcss.config.js')) ||
230
+ existsSync(join(cwd, 'postcss.config.cjs')) ||
231
+ existsSync(join(cwd, 'postcss.config.mjs')) ||
232
+ existsSync(join(cwd, '.postcssrc')) ||
233
+ existsSync(join(cwd, '.postcssrc.json'))
234
+
235
+ // Note: CSS Modules detection is tricky without scanning files
236
+ // Framework-based heuristic: React/Next.js projects often use CSS Modules
237
+ // Will be set to true if React/Next.js detected (handled in Stylelint factory)
238
+
239
+ return results
240
+ }
241
+
242
+ /**
243
+ * Auto-detect all configuration options
244
+ * @param {string} cwd - Current working directory
245
+ * @returns {Object} Detected configuration
246
+ */
247
+ export function autoDetect(cwd = process.cwd()) {
248
+ const framework = detectFramework(cwd)
249
+ const environment = detectEnvironment(framework, cwd)
250
+ const typescript = detectTypeScript(cwd)
251
+ const gitProvider = detectGitProvider(cwd)
252
+ const cssType = detectCssType(cwd)
253
+
254
+ return {
255
+ framework,
256
+ environment,
257
+ typescript,
258
+ gitProvider,
259
+ cssType
260
+ }
261
+ }
package/src/index.js ADDED
@@ -0,0 +1,64 @@
1
+ /**
2
+ * @dimensional-innovations/tool-config
3
+ * Universal configuration package for development tools
4
+ *
5
+ * Supports: ESLint, Prettier, Stylelint, semantic-release
6
+ * Auto-detects: React, Vue, Svelte, Solid, Astro, Angular, Vanilla JS, Node.js
7
+ */
8
+
9
+ /**
10
+ * Create a configuration for a specific tool
11
+ *
12
+ * @param {string} tool - Tool name ('eslint' | 'prettier' | 'stylelint' | 'semantic-release')
13
+ * @param {Object} options - Configuration options
14
+ * @returns {Promise<any>|any} Tool-specific configuration
15
+ *
16
+ * @example
17
+ * // ESLint configuration
18
+ * import { createConfig } from '@dimensional-innovations/tool-config';
19
+ * export default await createConfig('eslint', {
20
+ * framework: 'auto',
21
+ * environment: 'auto',
22
+ * typescript: 'auto'
23
+ * });
24
+ *
25
+ * @example
26
+ * // Prettier configuration
27
+ * import { createConfig } from '@dimensional-innovations/tool-config';
28
+ * export default createConfig('prettier', {
29
+ * framework: 'auto'
30
+ * });
31
+ */
32
+ export async function createConfig(tool, options = {}) {
33
+ switch (tool) {
34
+ case 'eslint': {
35
+ const { createEslintConfig } = await import('./tools/eslint/index.js')
36
+ return createEslintConfig(options)
37
+ }
38
+ case 'prettier': {
39
+ const { createPrettierConfig } = await import('./tools/prettier/index.js')
40
+ return createPrettierConfig(options)
41
+ }
42
+ case 'stylelint': {
43
+ const { createStylelintConfig } = await import('./tools/stylelint/index.js')
44
+ return createStylelintConfig(options)
45
+ }
46
+ case 'semantic-release': {
47
+ const { createReleaseConfig } = await import('./tools/semantic-release/index.js')
48
+ return createReleaseConfig(options)
49
+ }
50
+ default:
51
+ throw new Error(
52
+ `Unknown tool: "${tool}". Supported tools: eslint, prettier, stylelint, semantic-release`
53
+ )
54
+ }
55
+ }
56
+
57
+ // Named exports for convenience
58
+ export { createEslintConfig } from './tools/eslint/index.js'
59
+ export { createPrettierConfig } from './tools/prettier/index.js'
60
+ export { createStylelintConfig } from './tools/stylelint/index.js'
61
+ export { createReleaseConfig } from './tools/semantic-release/index.js'
62
+
63
+ // Re-export detection utilities for advanced users
64
+ export { autoDetect, detectFramework, detectEnvironment, detectTypeScript } from './detectors.js'