Files
glitch_bloodsugar/scripts/new-glitch-component.mjs
T

134 lines
3.2 KiB
JavaScript
Raw Normal View History

2026-03-24 11:30:14 +01:00
import fs from 'node:fs'
import path from 'node:path'
const cwd = process.cwd()
const templateDir = path.join(cwd, 'templates', 'react-vite-glitch-component')
function fail(message) {
console.error(message)
process.exit(1)
}
function toKebabCase(value) {
return value
.trim()
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
.replace(/[^a-zA-Z0-9]+/g, '-')
.replace(/^-+|-+$/g, '')
.toLowerCase()
}
function toSnakeCase(value) {
return value.replace(/-/g, '_')
}
function toPascalCase(value) {
return value
.split('-')
.filter(Boolean)
.map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))
.join('')
}
function toTitleCase(value) {
return value
.split('-')
.filter(Boolean)
.map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))
.join(' ')
}
function parseArgs(argv) {
const args = [...argv]
const result = {
componentId: '',
title: '',
dir: ''
}
while (args.length > 0) {
const arg = args.shift()
if (!arg) continue
if (!result.componentId && !arg.startsWith('--')) {
result.componentId = arg
continue
}
if (arg === '--title') {
result.title = args.shift() ?? ''
continue
}
if (arg === '--dir') {
result.dir = args.shift() ?? ''
continue
}
fail(`Unknown argument: ${arg}`)
}
return result
}
function copyTemplate(sourceDir, destinationDir, replacements) {
fs.mkdirSync(destinationDir, { recursive: true })
for (const entry of fs.readdirSync(sourceDir, { withFileTypes: true })) {
const sourcePath = path.join(sourceDir, entry.name)
const destinationPath = path.join(destinationDir, entry.name)
if (entry.isDirectory()) {
copyTemplate(sourcePath, destinationPath, replacements)
continue
}
const source = fs.readFileSync(sourcePath, 'utf8')
const rendered = Object.entries(replacements).reduce(
(content, [key, value]) => content.replaceAll(key, value),
source
)
fs.writeFileSync(destinationPath, rendered)
}
}
const options = parseArgs(process.argv.slice(2))
if (!options.componentId) {
fail('Usage: npm run glitch:new -- <component-id> --title "Display Name" [--dir /custom/path]')
}
if (!fs.existsSync(templateDir)) {
fail(`Template directory not found: ${templateDir}`)
}
const componentId = toKebabCase(options.componentId)
if (!componentId) {
fail('Component id resolved to an empty value.')
}
const folderName = `glitch_${toSnakeCase(componentId)}`
const displayName = options.title.trim() || toTitleCase(componentId)
const bundleName = componentId
const destinationDir = options.dir
? path.resolve(cwd, options.dir)
: path.join(cwd, folderName)
if (fs.existsSync(destinationDir)) {
fail(`Destination already exists: ${destinationDir}`)
}
copyTemplate(templateDir, destinationDir, {
'__COMPONENT_ID__': componentId,
'__COMPONENT_DISPLAY_NAME__': displayName,
'__LIB_GLOBAL_NAME__': toPascalCase(componentId),
'__FOLDER_NAME__': folderName,
'__BUNDLE_NAME__': bundleName
})
console.log(`Created ${folderName}`)
console.log(`Path: ${destinationDir}`)
console.log('Next steps:')
console.log(` cd ${folderName}`)
console.log(' npm install')
console.log(' npm run dev')