sickit
Version:
A SvelteKit Svelte 5 PocketBase Starter Kit with a CLI
162 lines (120 loc) • 3.92 kB
JavaScript
import { fileURLToPath } from 'node:url';
import * as p from '@clack/prompts';
import { bold, cyan, grey, yellow } from 'kleur/colors';
import path from 'node:path';
import fs from 'node:fs';
const { version } = JSON.parse(fs.readFileSync(new URL('package.json', import.meta.url), 'utf-8'));
let cwd = process.argv[2] || '.';
console.log(`
${grey(`sick-kit version ${version}`)}
`);
p.intro('Welcome to Sick Kit 😎');
if (fs.existsSync(cwd)) {
if (fs.readdirSync(cwd).length > 0) {
const force = await p.confirm({
message: 'Directory not empty. Continue?',
initialValue: false
});
// bail if `force` is `false` or the user cancelled with Ctrl-C
if (force !== true) {
process.exit(1);
}
}
}
export function dist(path) {
return fileURLToPath(new URL(`./${path}`, import.meta.url));
}
export const package_manager = get_package_manager() || 'npm';
function get_package_manager() {
if (!process.env.npm_config_user_agent) {
return undefined;
}
const user_agent = process.env.npm_config_user_agent;
const pm_spec = user_agent.split(' ')[0];
const separator_pos = pm_spec.lastIndexOf('/');
const name = pm_spec.substring(0, separator_pos);
return name === 'npminstall' ? 'cnpm' : name;
}
const options = await p.group(
{
template: () =>
p.select({
message: 'Which Sick template?',
options: fs.readdirSync(dist('templates')).map((dir) => {
const meta_file = dist(`templates/${dir}/.meta.json`);
const { title, description } = JSON.parse(fs.readFileSync(meta_file, 'utf8'));
return {
label: title,
hint: description,
value: dir
};
})
}),
},
{ onCancel: () => process.exit(1) }
)
function to_valid_package_name(name) {
return name
.trim()
.toLowerCase()
.replace(/\s+/g, '-')
.replace(/^[._]/, '')
.replace(/[^a-z0-9~.-]+/g, '-');
}
function replacePackageName(cwd, newName) {
// Read the package.json file
const packageJson = fs.readFileSync(cwd + '/package.json', 'utf8');
// Parse the JSON content
const packageData = JSON.parse(packageJson);
// Replace the name property with the provided variable
packageData.name = newName;
// Convert the updated data back to JSON
const updatedPackageJson = JSON.stringify(packageData, null, 2);
// Write the updated content back to the package.json file
fs.writeFileSync(cwd + '/package.json', updatedPackageJson, 'utf8');
}
function write_template_files(template, types, name, cwd) {
const dir = dist(`templates/${template}`);
copy(dir, cwd, to_valid_package_name(name));
copy(dir + "/example.env", cwd + "/.env");
replacePackageName(cwd, to_valid_package_name(name));
}
export function mkdirp(dir) {
try {
fs.mkdirSync(dir, { recursive: true });
} catch (e) {
if (/** @type {any} */ (e).code === 'EEXIST') return;
throw e;
}
}
function copy(from, to, rename, replace = false) {
const stats = fs.statSync(from);
if (stats.isDirectory()) {
fs.readdirSync(from).forEach((file) => {
copy(path.join(from, file), path.join(to, file));
});
} else {
mkdirp(path.dirname(to));
fs.copyFileSync(from, to);
}
}
async function create(cwd, options) {
mkdirp(cwd);
write_template_files(options.template, null, options.name, cwd);
}
await create(cwd, {
name: path.basename(path.resolve(cwd)),
template: options.template,
})
p.outro("Sick, T2D - time to dev.");
let i = 1;
const relative = path.relative(process.cwd(), cwd);
if (relative !== '') {
console.log(` ${i++}: ${bold(cyan(`cd ${relative}`))}`);
}
console.log(` ${i++}: ${bold(cyan(`${package_manager} install`))}`);
// prettier-ignore
console.log(` ${i++}: ${bold(cyan('git init && git add -A && git commit -m "Initial commit"'))} (optional)`);
console.log(` ${i++}: ${bold(cyan(`${package_manager} run dev -- --open`))}`);
console.log(`\nTo close the dev server, hit ${bold(cyan('Ctrl-C'))}`);