create-murasaki 0.0.6 → 0.0.7
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.
- package/index.mjs +126 -3
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -139,8 +139,111 @@ async function promptForName() {
|
|
|
139
139
|
return answer.trim() || 'my-app'
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
+
async function promptForLinter() {
|
|
143
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout })
|
|
144
|
+
const answer = await rl.question(` ${c(DEEP)}?${c(RESET)} ${c(BOLD)}Linter${c(RESET)} ${c(DIM)}(biome / eslint / none) [biome]:${c(RESET)} `)
|
|
145
|
+
rl.close()
|
|
146
|
+
const v = answer.trim().toLowerCase()
|
|
147
|
+
if (v === 'eslint' || v === 'e') return 'eslint'
|
|
148
|
+
if (v === 'none' || v === 'n') return 'none'
|
|
149
|
+
return 'biome' // default
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// ── Linter installers ─────────────────────────────────────────────────
|
|
153
|
+
async function applyBiome(targetDir) {
|
|
154
|
+
const biomeJson = `{
|
|
155
|
+
"$schema": "https://biomejs.dev/schemas/2.5.1/schema.json",
|
|
156
|
+
"vcs": {
|
|
157
|
+
"enabled": true,
|
|
158
|
+
"clientKind": "git",
|
|
159
|
+
"useIgnoreFile": true
|
|
160
|
+
},
|
|
161
|
+
"files": {
|
|
162
|
+
"includes": ["src/**/*.{ts,tsx,js,jsx}", "!**/node_modules", "!**/dist"]
|
|
163
|
+
},
|
|
164
|
+
"formatter": {
|
|
165
|
+
"enabled": true,
|
|
166
|
+
"indentStyle": "space",
|
|
167
|
+
"indentWidth": 2,
|
|
168
|
+
"lineWidth": 100
|
|
169
|
+
},
|
|
170
|
+
"linter": {
|
|
171
|
+
"enabled": true,
|
|
172
|
+
"rules": { "recommended": true }
|
|
173
|
+
},
|
|
174
|
+
"javascript": {
|
|
175
|
+
"formatter": {
|
|
176
|
+
"quoteStyle": "single",
|
|
177
|
+
"semicolons": "asNeeded",
|
|
178
|
+
"trailingCommas": "all"
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
`
|
|
183
|
+
await writeFile(join(targetDir, 'biome.json'), biomeJson)
|
|
184
|
+
await patchPackageJson(targetDir, (pkg) => {
|
|
185
|
+
pkg.devDependencies = { ...(pkg.devDependencies || {}), '@biomejs/biome': '^2.5.1' }
|
|
186
|
+
pkg.scripts = {
|
|
187
|
+
...(pkg.scripts || {}),
|
|
188
|
+
check: 'biome check',
|
|
189
|
+
format: 'biome format --write',
|
|
190
|
+
lint: 'biome lint',
|
|
191
|
+
fix: 'biome check --write',
|
|
192
|
+
}
|
|
193
|
+
})
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
async function applyEslint(targetDir) {
|
|
197
|
+
const eslintConfig = `// eslint.config.js — flat config (ESLint v9+)
|
|
198
|
+
|
|
199
|
+
import js from '@eslint/js'
|
|
200
|
+
import tseslint from 'typescript-eslint'
|
|
201
|
+
import reactPlugin from 'eslint-plugin-react'
|
|
202
|
+
import reactHooks from 'eslint-plugin-react-hooks'
|
|
203
|
+
|
|
204
|
+
export default tseslint.config(
|
|
205
|
+
js.configs.recommended,
|
|
206
|
+
...tseslint.configs.recommended,
|
|
207
|
+
{
|
|
208
|
+
files: ['src/**/*.{ts,tsx,js,jsx}'],
|
|
209
|
+
plugins: { react: reactPlugin, 'react-hooks': reactHooks },
|
|
210
|
+
rules: {
|
|
211
|
+
...reactPlugin.configs.recommended.rules,
|
|
212
|
+
...reactHooks.configs.recommended.rules,
|
|
213
|
+
'react/react-in-jsx-scope': 'off',
|
|
214
|
+
},
|
|
215
|
+
settings: { react: { version: 'detect' } },
|
|
216
|
+
},
|
|
217
|
+
{ ignores: ['node_modules/**', 'dist/**'] },
|
|
218
|
+
)
|
|
219
|
+
`
|
|
220
|
+
await writeFile(join(targetDir, 'eslint.config.js'), eslintConfig)
|
|
221
|
+
await patchPackageJson(targetDir, (pkg) => {
|
|
222
|
+
pkg.devDependencies = {
|
|
223
|
+
...(pkg.devDependencies || {}),
|
|
224
|
+
'eslint': '^9.20.0',
|
|
225
|
+
'@eslint/js': '^9.20.0',
|
|
226
|
+
'typescript-eslint': '^8.20.0',
|
|
227
|
+
'eslint-plugin-react': '^7.37.0',
|
|
228
|
+
'eslint-plugin-react-hooks': '^5.1.0',
|
|
229
|
+
}
|
|
230
|
+
pkg.scripts = {
|
|
231
|
+
...(pkg.scripts || {}),
|
|
232
|
+
lint: 'eslint .',
|
|
233
|
+
'lint:fix': 'eslint . --fix',
|
|
234
|
+
}
|
|
235
|
+
})
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
async function patchPackageJson(targetDir, mutator) {
|
|
239
|
+
const pkgPath = join(targetDir, 'package.json')
|
|
240
|
+
const pkg = JSON.parse(await readFile(pkgPath, 'utf8'))
|
|
241
|
+
mutator(pkg)
|
|
242
|
+
await writeFile(pkgPath, JSON.stringify(pkg, null, 2) + '\n')
|
|
243
|
+
}
|
|
244
|
+
|
|
142
245
|
// ── Scaffold ───────────────────────────────────────────────────────────
|
|
143
|
-
async function scaffold(projectName) {
|
|
246
|
+
async function scaffold(projectName, linter) {
|
|
144
247
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
145
248
|
const templateDir = join(__dirname, 'templates', 'default')
|
|
146
249
|
const targetDir = resolve(process.cwd(), projectName)
|
|
@@ -167,6 +270,15 @@ async function scaffold(projectName) {
|
|
|
167
270
|
const pkgPatched = pkgRaw.replace(/"__PROJECT_NAME__"/, JSON.stringify(projectName))
|
|
168
271
|
await writeFile(pkgPath, pkgPatched)
|
|
169
272
|
|
|
273
|
+
// Apply linter overlay
|
|
274
|
+
if (linter === 'biome') {
|
|
275
|
+
log(` ${c(DIM)}○${c(RESET)} Adding ${c(BOLD)}Biome${c(RESET)}...`)
|
|
276
|
+
await applyBiome(targetDir)
|
|
277
|
+
} else if (linter === 'eslint') {
|
|
278
|
+
log(` ${c(DIM)}○${c(RESET)} Adding ${c(BOLD)}ESLint${c(RESET)}...`)
|
|
279
|
+
await applyEslint(targetDir)
|
|
280
|
+
}
|
|
281
|
+
|
|
170
282
|
log(` ${c(GREEN)}${c(BOLD)}✓${c(RESET)} Created ${c(BOLD)}${projectName}/${c(RESET)}`)
|
|
171
283
|
|
|
172
284
|
// Install dependencies (Next.js-like behavior)
|
|
@@ -201,11 +313,22 @@ const banner = renderBanner()
|
|
|
201
313
|
process.stdout.write('\n' + banner + '\n\n')
|
|
202
314
|
process.stdout.write(` ${c(DIM)}desktop apps for Next.js developers${c(RESET)}\n`)
|
|
203
315
|
|
|
204
|
-
|
|
316
|
+
// ── Parse args ────────────────────────────────────────────────────────
|
|
317
|
+
const argName = process.argv[2] && !process.argv[2].startsWith('--') ? process.argv[2] : null
|
|
318
|
+
const argLinter = (() => {
|
|
319
|
+
const i = process.argv.indexOf('--linter')
|
|
320
|
+
if (i >= 0 && process.argv[i + 1]) {
|
|
321
|
+
const v = process.argv[i + 1].toLowerCase()
|
|
322
|
+
if (v === 'biome' || v === 'eslint' || v === 'none') return v
|
|
323
|
+
}
|
|
324
|
+
return null
|
|
325
|
+
})()
|
|
326
|
+
|
|
205
327
|
const projectName = argName || (await promptForName())
|
|
328
|
+
const linter = argLinter || (await promptForLinter())
|
|
206
329
|
|
|
207
330
|
try {
|
|
208
|
-
await scaffold(projectName)
|
|
331
|
+
await scaffold(projectName, linter)
|
|
209
332
|
} catch (err) {
|
|
210
333
|
log(`\n ${c(RED)}✗${c(RESET)} Scaffold failed: ${err.message}\n`)
|
|
211
334
|
process.exit(1)
|