psrworld
Version:
A TypeScript-powered project scaffolding tool with dual CommonJS/ESM build support
1,449 lines (1,363 loc) • 60.1 kB
JavaScript
'use strict';
var fs$1 = require('node:fs');
var path$3 = require('node:path');
var require$$0$2 = require('child_process');
var require$$0$1 = require('path');
var require$$0 = require('fs');
function _mergeNamespaces(n, m) {
m.forEach(function (e) {
e && typeof e !== 'string' && !Array.isArray(e) && Object.keys(e).forEach(function (k) {
if (k !== 'default' && !(k in n)) {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
});
return Object.freeze(n);
}
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function getDefaultExportFromCjs (x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}
var picocolors$1 = {exports: {}};
let p = process || {}, argv = p.argv || [], env = p.env || {};
let isColorSupported =
!(!!env.NO_COLOR || argv.includes("--no-color")) &&
(!!env.FORCE_COLOR || argv.includes("--color") || p.platform === "win32" || ((p.stdout || {}).isTTY && env.TERM !== "dumb") || !!env.CI);
let formatter = (open, close, replace = open) =>
input => {
let string = "" + input, index = string.indexOf(close, open.length);
return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close
};
let replaceClose = (string, close, replace, index) => {
let result = "", cursor = 0;
do {
result += string.substring(cursor, index) + replace;
cursor = index + close.length;
index = string.indexOf(close, cursor);
} while (~index)
return result + string.substring(cursor)
};
let createColors = (enabled = isColorSupported) => {
let f = enabled ? formatter : () => String;
return {
isColorSupported: enabled,
reset: f("\x1b[0m", "\x1b[0m"),
bold: f("\x1b[1m", "\x1b[22m", "\x1b[22m\x1b[1m"),
dim: f("\x1b[2m", "\x1b[22m", "\x1b[22m\x1b[2m"),
italic: f("\x1b[3m", "\x1b[23m"),
underline: f("\x1b[4m", "\x1b[24m"),
inverse: f("\x1b[7m", "\x1b[27m"),
hidden: f("\x1b[8m", "\x1b[28m"),
strikethrough: f("\x1b[9m", "\x1b[29m"),
black: f("\x1b[30m", "\x1b[39m"),
red: f("\x1b[31m", "\x1b[39m"),
green: f("\x1b[32m", "\x1b[39m"),
yellow: f("\x1b[33m", "\x1b[39m"),
blue: f("\x1b[34m", "\x1b[39m"),
magenta: f("\x1b[35m", "\x1b[39m"),
cyan: f("\x1b[36m", "\x1b[39m"),
white: f("\x1b[37m", "\x1b[39m"),
gray: f("\x1b[90m", "\x1b[39m"),
bgBlack: f("\x1b[40m", "\x1b[49m"),
bgRed: f("\x1b[41m", "\x1b[49m"),
bgGreen: f("\x1b[42m", "\x1b[49m"),
bgYellow: f("\x1b[43m", "\x1b[49m"),
bgBlue: f("\x1b[44m", "\x1b[49m"),
bgMagenta: f("\x1b[45m", "\x1b[49m"),
bgCyan: f("\x1b[46m", "\x1b[49m"),
bgWhite: f("\x1b[47m", "\x1b[49m"),
blackBright: f("\x1b[90m", "\x1b[39m"),
redBright: f("\x1b[91m", "\x1b[39m"),
greenBright: f("\x1b[92m", "\x1b[39m"),
yellowBright: f("\x1b[93m", "\x1b[39m"),
blueBright: f("\x1b[94m", "\x1b[39m"),
magentaBright: f("\x1b[95m", "\x1b[39m"),
cyanBright: f("\x1b[96m", "\x1b[39m"),
whiteBright: f("\x1b[97m", "\x1b[39m"),
bgBlackBright: f("\x1b[100m", "\x1b[49m"),
bgRedBright: f("\x1b[101m", "\x1b[49m"),
bgGreenBright: f("\x1b[102m", "\x1b[49m"),
bgYellowBright: f("\x1b[103m", "\x1b[49m"),
bgBlueBright: f("\x1b[104m", "\x1b[49m"),
bgMagentaBright: f("\x1b[105m", "\x1b[49m"),
bgCyanBright: f("\x1b[106m", "\x1b[49m"),
bgWhiteBright: f("\x1b[107m", "\x1b[49m"),
}
};
picocolors$1.exports = createColors();
var createColors_1 = picocolors$1.exports.createColors = createColors;
var picocolorsExports = picocolors$1.exports;
var picocolors = /*@__PURE__*/getDefaultExportFromCjs(picocolorsExports);
var colors = /*#__PURE__*/_mergeNamespaces({
__proto__: null,
createColors: createColors_1,
default: picocolors
}, [picocolorsExports]);
const { blue: blue$1, blueBright: blueBright$1, cyan: cyan$2, green: green$1, greenBright: greenBright$1, magenta: magenta$1, red: red$1, redBright: redBright$1, reset, yellow: yellow$1, gray: gray$1, } = colors;
/**
* Framework configurations for project scaffolding
* Each framework contains variants with different setups and features
*/
const FRAMEWORKS = [
{
name: 'vanilla',
display: 'Vanilla',
color: yellow$1,
desc: 'Vanilla JavaScript with TypeScript, Vite, and modern tooling setup',
variants: [
{
name: 'vanilla-ts',
display: 'TypeScript',
color: blue$1,
templateDir: 'template-vanilla-ts',
desc: 'Vanilla JavaScript with TypeScript, Vite, and modern tooling setup',
tailwindCssVariants: [
{
name: 'tailwind-v4',
display: 'Tailwind V4',
color: green$1,
templateDir: 'v4-template-vanilla-ts',
desc: 'Tailwind CSS v4 with new CSS-first configuration and Lightning CSS engine',
},
{
name: 'tailwind-v3',
display: 'Tailwind V3',
color: blue$1,
templateDir: 'v3-template-vanilla-ts',
desc: 'Tailwind CSS v3 with traditional configuration and build process',
},
],
},
{
name: 'vanilla',
display: 'JavaScript',
color: yellow$1,
templateDir: 'template-vanilla',
desc: 'Pure vanilla JavaScript with Vite for fast development and building',
tailwindCssVariants: [
{
name: 'tailwind-v4',
display: 'Tailwind V4',
color: green$1,
templateDir: 'v4-template-vanilla',
desc: 'Tailwind CSS v4 with new CSS-first configuration and Lightning CSS engine',
},
{
name: 'tailwind-v3',
display: 'Tailwind V3',
color: blue$1,
templateDir: 'v3-template-vanilla',
desc: 'Tailwind CSS v3 with traditional configuration and build process',
},
],
},
],
},
{
name: 'vue',
display: 'Vue',
color: green$1,
variants: [
{
name: 'vue-ts',
display: 'TypeScript',
color: blue$1,
templateDir: 'template-vue-ts',
desc: 'Vue 3 with TypeScript, Composition API, and single file components',
tailwindCssVariants: [
{
name: 'tailwind-v4',
display: 'Tailwind V4',
color: green$1,
templateDir: 'v4-template-vue-ts',
desc: 'Tailwind CSS v4 with new CSS-first configuration and Lightning CSS engine',
},
{
name: 'tailwind-v3',
display: 'Tailwind V3',
color: blue$1,
templateDir: 'v3-template-vue-ts',
desc: 'Tailwind CSS v3 with traditional configuration and build process',
},
],
},
{
name: 'vue',
display: 'JavaScript',
color: yellow$1,
templateDir: 'template-vue',
desc: 'Vue 3 with JavaScript, Composition API, and reactive components',
tailwindCssVariants: [
{
name: 'tailwind-v4',
display: 'Tailwind V4',
color: green$1,
templateDir: 'v4-template-vue',
desc: 'Tailwind CSS v4 with new CSS-first configuration and Lightning CSS engine',
},
{
name: 'tailwind-v3',
display: 'Tailwind V3',
color: blue$1,
templateDir: 'v3-template-vue',
desc: 'Tailwind CSS v3 with traditional configuration and build process',
},
],
},
{
name: 'custom-create-vue',
display: 'Official Vue Starter ↗',
color: green$1,
customCommand: 'npm create vue@latest TARGET_DIR',
desc: 'Official Vue project generator with customizable features and tooling',
},
{
name: 'custom-nuxt',
display: 'Nuxt ↗',
color: greenBright$1,
customCommand: 'npm exec nuxi init TARGET_DIR',
desc: 'Full-stack Vue framework with SSR, file-based routing, and auto-imports',
},
],
},
{
name: 'react',
display: 'React',
color: cyan$2,
variants: [
{
name: 'react-ts',
display: 'TypeScript',
color: blue$1,
templateDir: 'template-react-ts',
desc: 'React 18 with TypeScript, JSX, hooks, and modern development setup',
tailwindCssVariants: [
{
name: 'tailwind-v4',
display: 'Tailwind V4',
color: green$1,
templateDir: 'v4-template-react-ts',
desc: 'Tailwind CSS v4 with new CSS-first configuration and Lightning CSS engine',
},
{
name: 'tailwind-v3',
display: 'Tailwind V3',
color: blue$1,
templateDir: 'v3-template-react-ts',
desc: 'Tailwind CSS v3 with traditional configuration and build process',
},
],
},
{
name: 'react-swc-ts',
display: 'TypeScript + SWC',
color: blue$1,
templateDir: 'template-react-swc-ts',
desc: 'React with TypeScript and SWC compiler for faster builds and HMR',
tailwindCssVariants: [
{
name: 'tailwind-v4',
display: 'Tailwind V4',
color: green$1,
templateDir: 'v4-template-react-swc-ts',
desc: 'Tailwind CSS v4 with new CSS-first configuration and Lightning CSS engine',
},
{
name: 'tailwind-v3',
display: 'Tailwind V3',
color: blue$1,
templateDir: 'v3-template-react-swc-ts',
desc: 'Tailwind CSS v3 with traditional configuration and build process',
},
],
},
{
name: 'react',
display: 'JavaScript',
color: yellow$1,
templateDir: 'template-react',
desc: 'React 18 with JavaScript, JSX, and component-based architecture',
tailwindCssVariants: [
{
name: 'tailwind-v4',
display: 'Tailwind V4',
color: green$1,
templateDir: 'v4-template-react',
desc: 'Tailwind CSS v4 with new CSS-first configuration and Lightning CSS engine',
},
{
name: 'tailwind-v3',
display: 'Tailwind V3',
color: blue$1,
templateDir: 'v3-template-react',
desc: 'Tailwind CSS v3 with traditional configuration and build process',
},
],
},
{
name: 'react-swc',
display: 'JavaScript + SWC',
color: yellow$1,
templateDir: 'template-react-swc',
desc: 'React with JavaScript and SWC compiler for enhanced performance',
tailwindCssVariants: [
{
name: 'tailwind-v4',
display: 'Tailwind V4',
color: green$1,
templateDir: 'v4-template-react-swc',
desc: 'Tailwind CSS v4 with new CSS-first configuration and Lightning CSS engine',
},
{
name: 'tailwind-v3',
display: 'Tailwind V3',
color: blue$1,
templateDir: 'v3-template-react-swc',
desc: 'Tailwind CSS v3 with traditional configuration and build process',
},
],
},
{
name: 'custom-react-router',
display: 'React Router v7 ↗',
color: cyan$2,
customCommand: 'npm create react-router@latest TARGET_DIR',
desc: 'React with declarative routing, nested routes, and navigation management',
},
{
name: 'custom-tanstack-router',
display: 'TanStack Router ↗',
color: cyan$2,
customCommand: 'npm create -- tsrouter-app@latest TARGET_DIR --framework React --interactive',
desc: 'Type-safe router with search params, loaders, and advanced routing features',
},
{
name: 'redwoodsdk-standard',
display: 'RedwoodSDK ↗',
color: red$1,
customCommand: 'npm exec degit redwoodjs/sdk/starters/standard TARGET_DIR',
desc: 'Full-stack React framework with GraphQL, Prisma, and JAMstack architecture',
},
{
name: 'rsc',
display: 'RSC ↗',
color: magenta$1,
customCommand: 'npm exec degit vitejs/vite-plugin-react/packages/plugin-rsc/examples/starter TARGET_DIR',
desc: 'React Server Components with server-side rendering and streaming',
},
],
},
{
name: 'preact',
display: 'Preact',
color: magenta$1,
variants: [
{
name: 'preact-ts',
display: 'TypeScript',
color: blue$1,
templateDir: 'template-preact-ts',
desc: 'Lightweight React alternative with TypeScript and 3KB runtime',
tailwindCssVariants: [
{
name: 'tailwind-v4',
display: 'Tailwind V4',
color: green$1,
templateDir: 'v4-template-preact-ts',
desc: 'Tailwind CSS v4 with new CSS-first configuration and Lightning CSS engine',
},
{
name: 'tailwind-v3',
display: 'Tailwind V3',
color: blue$1,
templateDir: 'v3-template-preact-ts',
desc: 'Tailwind CSS v3 with traditional configuration and build process',
},
],
},
{
name: 'preact',
display: 'JavaScript',
color: yellow$1,
templateDir: 'template-preact',
desc: 'Fast 3KB React alternative with same modern API and ecosystem',
tailwindCssVariants: [
{
name: 'tailwind-v4',
display: 'Tailwind V4',
color: green$1,
templateDir: 'v4-template-preact',
desc: 'Tailwind CSS v4 with new CSS-first configuration and Lightning CSS engine',
},
{
name: 'tailwind-v3',
display: 'Tailwind V3',
color: blue$1,
templateDir: 'v3-template-preact',
desc: 'Tailwind CSS v3 with traditional configuration and build process',
},
],
},
{
name: 'custom-create-preact',
display: 'Official Preact Starter ↗',
color: magenta$1,
customCommand: 'npm create preact@latest TARGET_DIR',
desc: 'Official Preact generator with PWA features and optimized builds',
},
],
},
{
name: 'lit',
display: 'Lit',
color: redBright$1,
variants: [
{
name: 'lit-ts',
display: 'TypeScript',
color: blue$1,
templateDir: 'template-lit-ts',
desc: 'Web Components with Lit library, TypeScript, and reactive properties',
tailwindCssVariants: [
{
name: 'tailwind-v4',
display: 'Tailwind V4',
color: green$1,
templateDir: 'v4-template-lit-ts',
desc: 'Tailwind CSS v4 with new CSS-first configuration and Lightning CSS engine',
},
{
name: 'tailwind-v3',
display: 'Tailwind V3',
color: blue$1,
templateDir: 'v3-template-lit-ts',
desc: 'Tailwind CSS v3 with traditional configuration and build process',
},
],
},
{
name: 'lit',
display: 'JavaScript',
color: yellow$1,
templateDir: 'template-lit',
desc: 'Simple and fast web components using Lit library and templates',
tailwindCssVariants: [
{
name: 'tailwind-v4',
display: 'Tailwind V4',
color: green$1,
templateDir: 'v4-template-lit',
desc: 'Tailwind CSS v4 with new CSS-first configuration and Lightning CSS engine',
},
{
name: 'tailwind-v3',
display: 'Tailwind V3',
color: blue$1,
templateDir: 'v3-template-lit',
desc: 'Tailwind CSS v3 with traditional configuration and build process',
},
],
},
],
},
{
name: 'svelte',
display: 'Svelte',
color: red$1,
variants: [
{
name: 'svelte-ts',
display: 'TypeScript',
color: blue$1,
templateDir: 'template-svelte-ts',
desc: 'Compile-time optimized framework with TypeScript and reactive state',
tailwindCssVariants: [
{
name: 'tailwind-v4',
display: 'Tailwind V4',
color: green$1,
templateDir: 'v4-template-svelte-ts',
desc: 'Tailwind CSS v4 with new CSS-first configuration and Lightning CSS engine',
},
{
name: 'tailwind-v3',
display: 'Tailwind V3',
color: blue$1,
templateDir: 'v3-template-svelte-ts',
desc: 'Tailwind CSS v3 with traditional configuration and build process',
},
],
},
{
name: 'svelte',
display: 'JavaScript',
color: yellow$1,
templateDir: 'template-svelte',
desc: 'No virtual DOM framework with compiled components and reactive updates',
tailwindCssVariants: [
{
name: 'tailwind-v4',
display: 'Tailwind V4',
color: green$1,
templateDir: 'v4-template-svelte',
desc: 'Tailwind CSS v4 with new CSS-first configuration and Lightning CSS engine',
},
{
name: 'tailwind-v3',
display: 'Tailwind V3',
color: blue$1,
templateDir: 'v3-template-svelte',
desc: 'Tailwind CSS v3 with traditional configuration and build process',
},
],
},
{
name: 'custom-svelte-kit',
display: 'SvelteKit ↗',
color: red$1,
customCommand: 'npm exec sv create TARGET_DIR',
desc: 'Full-stack Svelte framework with SSR, routing, and adapter system',
},
],
},
{
name: 'solid',
display: 'Solid',
color: blue$1,
variants: [
{
name: 'solid-ts',
display: 'TypeScript',
color: blue$1,
templateDir: 'template-solid-ts',
desc: 'Fine-grained reactive framework with TypeScript and JSX syntax',
tailwindCssVariants: [
{
name: 'tailwind-v4',
display: 'Tailwind V4',
color: green$1,
templateDir: 'v4-template-solid-ts',
desc: 'Tailwind CSS v4 with new CSS-first configuration and Lightning CSS engine',
},
{
name: 'tailwind-v3',
display: 'Tailwind V3',
color: blue$1,
templateDir: 'v3-template-solid-ts',
desc: 'Tailwind CSS v3 with traditional configuration and build process',
},
],
},
{
name: 'solid',
display: 'JavaScript',
color: yellow$1,
templateDir: 'template-solid',
desc: 'Performant reactive framework with signals and compiled templates',
tailwindCssVariants: [
{
name: 'tailwind-v4',
display: 'Tailwind V4',
color: green$1,
templateDir: 'v4-template-solid',
desc: 'Tailwind CSS v4 with new CSS-first configuration and Lightning CSS engine',
},
{
name: 'tailwind-v3',
display: 'Tailwind V3',
color: blue$1,
templateDir: 'v3-template-solid',
desc: 'Tailwind CSS v3 with traditional configuration and build process',
},
],
},
{
name: 'custom-tanstack-router',
display: 'TanStack Router ↗',
color: cyan$2,
customCommand: 'npm create -- tsrouter-app@latest TARGET_DIR --framework Solid --interactive',
desc: 'Solid with type-safe routing, search params, and data loading',
},
],
},
{
name: 'qwik',
display: 'Qwik',
color: blueBright$1,
variants: [
{
name: 'qwik-ts',
display: 'TypeScript',
color: blueBright$1,
templateDir: 'template-qwik-ts',
desc: 'Resumable framework with TypeScript and instant-on applications',
tailwindCssVariants: [
{
name: 'tailwind-v4',
display: 'Tailwind V4',
color: green$1,
templateDir: 'v4-template-qwik-ts',
desc: 'Tailwind CSS v4 with new CSS-first configuration and Lightning CSS engine',
},
{
name: 'tailwind-v3',
display: 'Tailwind V3',
color: blue$1,
templateDir: 'v3-template-qwik-ts',
desc: 'Tailwind CSS v3 with traditional configuration and build process',
},
],
},
{
name: 'qwik',
display: 'JavaScript',
color: yellow$1,
templateDir: 'template-qwik',
desc: 'Zero hydration framework with resumable execution and lazy loading',
tailwindCssVariants: [
{
name: 'tailwind-v4',
display: 'Tailwind V4',
color: green$1,
templateDir: 'v4-template-qwik',
desc: 'Tailwind CSS v4 with new CSS-first configuration and Lightning CSS engine',
},
{
name: 'tailwind-v3',
display: 'Tailwind V3',
color: blue$1,
templateDir: 'v3-template-qwik',
desc: 'Tailwind CSS v3 with traditional configuration and build process',
},
],
},
{
name: 'custom-qwik-city',
display: 'QwikCity ↗',
color: blueBright$1,
customCommand: 'npm create qwik@latest basic TARGET_DIR',
desc: 'Meta-framework for Qwik with routing, layouts, and SSR capabilities',
},
],
},
{
name: 'angular',
display: 'Angular',
color: red$1,
desc: 'Full-featured TypeScript framework with dependency injection and comprehensive tooling',
variants: [
{
name: 'custom-angular',
display: 'Angular ↗',
color: red$1,
customCommand: 'npm exec @angular/cli@latest new TARGET_DIR',
desc: 'Full-featured framework with TypeScript, dependency injection, and CLI tools',
},
{
name: 'custom-analog',
display: 'Analog ↗',
color: yellow$1,
customCommand: 'npm create analog@latest TARGET_DIR',
desc: 'Angular meta-framework with file-based routing and server-side rendering',
},
],
},
{
name: 'marko',
display: 'Marko',
color: magenta$1,
desc: "eBay's UI framework with streaming SSR and optimized performance",
variants: [
{
name: 'marko-run',
display: 'Marko Run ↗',
color: magenta$1,
customCommand: 'npm create -- marko@latest --name TARGET_DIR',
desc: "eBay's UI framework with streaming SSR and component compilation",
},
],
},
{
name: 'nextjs',
display: 'Next.js',
color: cyan$2,
desc: 'Production-ready React framework with SSR and full-stack capabilities',
variants: [
{
name: 'custom-nextjs',
display: 'Next.js ↗',
color: cyan$2,
customCommand: 'npm create next-app@latest TARGET_DIR',
desc: 'React framework with SSR, API routes, file-based routing, and deployment optimization',
},
],
},
{
name: 'astro',
display: 'Astro',
color: magenta$1,
desc: 'Content-focused framework with islands architecture and multi-framework support',
variants: [
{
name: 'custom-astro',
display: 'Astro ↗',
color: magenta$1,
customCommand: 'npm create astro@latest TARGET_DIR',
desc: 'Multi-framework static site generator with partial hydration and islands architecture',
},
],
},
{
name: 'remix',
display: 'Remix',
color: blue$1,
desc: 'Full-stack React framework focused on web standards and user experience',
variants: [
{
name: 'custom-remix',
display: 'Remix ↗',
color: blue$1,
customCommand: 'npx create-remix@latest TARGET_DIR',
desc: 'Full-stack React framework focusing on web standards and progressive enhancement',
},
],
},
{
name: 'meteor',
display: 'Meteor.js',
color: gray$1,
desc: 'Full-stack JavaScript platform with real-time capabilities and integrated toolchain',
variants: [
{
name: 'custom-meteor',
display: 'Meteor.js ↗',
color: gray$1,
customCommand: 'meteor create TARGET_DIR',
desc: 'Full-stack JavaScript platform with real-time data, MongoDB integration, and deployment tools',
},
],
},
{
name: 'gatsby',
display: 'Gatsby',
color: magenta$1,
desc: 'React-based static site generator with GraphQL and performance optimization',
variants: [
{
name: 'custom-gatsby',
display: 'Gatsby ↗',
color: magenta$1,
customCommand: 'npm init gatsby@latest TARGET_DIR',
desc: 'React-based static site generator with GraphQL data layer and plugin ecosystem',
},
],
},
{
name: 'symfony',
display: 'Symfony',
color: blue$1,
desc: 'Professional PHP framework with enterprise-grade components and architecture',
variants: [
{
name: 'custom-symfony',
display: 'Symfony ↗',
color: blue$1,
customCommand: 'symfony new TARGET_DIR',
desc: 'PHP framework with reusable components, dependency injection, and rapid development tools',
},
],
},
{
name: 'rails',
display: 'Rails',
color: redBright$1,
desc: 'Ruby web framework with convention over configuration and rapid development',
variants: [
{
name: 'custom-rails',
display: 'Rails ↗',
color: redBright$1,
customCommand: 'rails new TARGET_DIR',
desc: 'Ruby web framework with convention over configuration and MVC architecture',
},
],
},
{
name: 'phoenix',
display: 'Phoenix',
color: cyan$2,
desc: 'Elixir web framework with real-time features and fault-tolerant architecture',
variants: [
{
name: 'custom-phoenix',
display: 'Phoenix ↗',
color: cyan$2,
customCommand: 'mix phx.new TARGET_DIR',
desc: 'Elixir web framework with real-time features, fault tolerance, and high concurrency',
},
],
},
{
name: 'django',
display: 'Django',
color: green$1,
desc: 'Python web framework with batteries included and rapid development focus',
variants: [
{
name: 'custom-django',
display: 'Django ↗',
color: green$1,
customCommand: 'django-admin startproject TARGET_DIR',
desc: 'Python web framework with batteries included, admin interface, and ORM',
},
],
},
{
name: 'flask',
display: 'Flask',
color: yellow$1,
desc: 'Lightweight Python web framework with flexible architecture and simplicity',
variants: [
{
name: 'custom-flask',
display: 'Flask ↗',
color: yellow$1,
customCommand: 'flask new TARGET_DIR',
desc: 'Lightweight Python web framework with flexible architecture and extensibility',
},
],
},
{
name: 'blazor',
display: 'Blazor',
color: blueBright$1,
desc: 'C# web framework running in browser with WebAssembly and .NET ecosystem',
variants: [
{
name: 'custom-blazor',
display: 'Blazor ↗',
color: blueBright$1,
customCommand: 'dotnet new blazorwasm -o TARGET_DIR',
desc: 'C# web framework running in browser via WebAssembly with .NET ecosystem',
},
],
},
{
name: 'hugo',
display: 'Hugo',
color: gray$1,
desc: 'Fast static site generator written in Go with themes and content management',
variants: [
{
name: 'custom-hugo',
display: 'Hugo ↗',
color: gray$1,
customCommand: 'hugo new site TARGET_DIR',
desc: 'Fast static site generator written in Go with themes and content management',
},
],
},
{
name: 'others',
display: 'Others',
color: reset,
desc: 'Additional starters and specialized project templates',
variants: [
{
name: 'create-vite-extra',
display: 'Extra Vite Starters ↗',
color: reset,
customCommand: 'npm create vite-extra@latest TARGET_DIR',
desc: 'Additional Vite templates and starters for various frameworks and setups',
},
{
name: 'create-electron-vite',
display: 'Electron ↗',
color: reset,
customCommand: 'npm create electron-vite@latest TARGET_DIR',
desc: 'Desktop applications with Electron, Vite, and modern web technologies',
},
],
},
];
/**
* Find variant by name across all frameworks
* @param frameworks - Array of framework configurations
* @param variantName - Name of the variant to find
* @returns Object with variant and framework, or null if not found
*/
function getVariantByName(frameworks, variantName) {
for (const framework of frameworks) {
if (framework.variants) {
const variant = framework.variants.find(v => v.name === variantName);
if (variant) {
return { variant, framework };
}
}
}
return null;
}
/**
* Get Tailwind CSS variants for a specific framework variant
* @param variant - Framework variant
* @returns Array of Tailwind CSS variants or empty array if none
*/
function getTailwindVariants(variant) {
return variant.tailwindCssVariants || [];
}
/**
* Find Tailwind variant by name within a framework variant
* @param variant - Framework variant
* @param tailwindVariantName - Name of the Tailwind variant
* @returns Tailwind variant or null if not found
*/
function getTailwindVariantByName(variant, tailwindVariantName) {
if (!variant.tailwindCssVariants)
return null;
return (variant.tailwindCssVariants.find(tv => tv.name === tailwindVariantName) ||
null);
}
function formatTargetDir(targetDir) {
return targetDir?.trim().replace(/\/+$/g, '') || '';
}
function copy(src, dest) {
const stat = fs$1.statSync(src);
if (stat.isDirectory()) {
copyDir(src, dest);
}
else {
fs$1.copyFileSync(src, dest);
}
}
function isValidPackageName(projectName) {
return /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(projectName);
}
function toValidPackageName(projectName) {
return projectName
.trim()
.toLowerCase()
.replace(/\s+/g, '-')
.replace(/^[._]/, '')
.replace(/[^a-z0-9-~]+/g, '-')
.replace(/^-+|-+$/g, '') // Remove leading and trailing hyphens
.replace(/-+/g, '-'); // Replace multiple consecutive hyphens with single hyphen
}
function copyDir(srcDir, destDir) {
fs$1.mkdirSync(destDir, { recursive: true });
for (const file of fs$1.readdirSync(srcDir)) {
const srcFile = path$3.resolve(srcDir, file);
const destFile = path$3.resolve(destDir, file);
copy(srcFile, destFile);
}
}
function writeTemplate(src, dest, projectName) {
const stats = fs$1.statSync(src);
if (stats.isDirectory()) {
fs$1.mkdirSync(dest, { recursive: true });
for (const file of fs$1.readdirSync(src)) {
const srcFile = path$3.resolve(src, file);
const destFile = path$3.resolve(dest, file);
writeTemplate(srcFile, destFile, projectName);
}
}
else {
let content = fs$1.readFileSync(src, 'utf-8');
// Generate a valid package name from the project name
const packageName = toValidPackageName(projectName);
// Replace template variables
content = content.replace(/{{projectName}}/g, projectName);
content = content.replace(/{{package}}/g, packageName);
fs$1.writeFileSync(dest, content);
}
}
function isEmpty(path) {
const files = fs$1.readdirSync(path);
return files.length === 0 || (files.length === 1 && files[0] === '.git');
}
function emptyDir(dir) {
if (!fs$1.existsSync(dir)) {
return;
}
for (const file of fs$1.readdirSync(dir)) {
if (file === '.git') {
continue;
}
fs$1.rmSync(path$3.resolve(dir, file), { recursive: true, force: true });
}
}
function setupReactFiles(root, projectName) {
// Update package.json name
const pkgPath = path$3.join(root, 'package.json');
const pkg = JSON.parse(fs$1.readFileSync(pkgPath, 'utf-8'));
pkg.name = projectName;
fs$1.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
}
// Debounce function
function debounce(func, delay) {
let timeoutId;
return (...args) => {
if (timeoutId) {
clearTimeout(timeoutId);
}
timeoutId = setTimeout(() => {
func(...args);
}, delay);
};
}
// Simple Logger class
class SimpleLogger {
debug;
constructor(debug = false) {
this.debug = debug;
}
log(level, message, ...args) {
const timestamp = new Date().toISOString();
const logLevel = level.toUpperCase();
const logMessage = `[${timestamp}] [${logLevel}]`;
switch (level) {
case 'info':
console.log(logMessage, message, ...args);
break;
case 'warn':
console.warn(logMessage, message, ...args);
break;
case 'error':
console.error(logMessage, message, ...args);
break;
case 'debug':
if (this.debug) {
console.debug(logMessage, message, ...args);
}
break;
}
}
}
const { blue, blueBright, cyan: cyan$1, green, greenBright, magenta, red, redBright, yellow, gray, } = colors;
const helpMessage = `\
Usage: create-mycustomlib [OPTION]... [DIRECTORY]
Create a new project from a template.
With no arguments, start the CLI in interactive mode.
Options:
-h, --help show this help message
-t, --template NAME use a specific template
-y, --yes use default options (vanilla-ts with Tailwind v4)
Available templates:
${yellow('vanilla-ts vanilla')}
${green('vue-ts vue')}
${cyan$1('react-ts react')}
${cyan$1('react-swc-ts react-swc')}
${magenta('preact-ts preact')}
${redBright('lit-ts lit')}
${red('svelte-ts svelte')}
${blue('solid-ts solid')}
${blueBright('qwik-ts qwik')}
${cyan$1('custom-nextjs')}
${greenBright('nuxt nuxt')}
${magenta('astro astro')}
${blue('remix remix')}
${gray('meteor meteor')}
${magenta('gatsby gatsby')}
${blue('symfony symfony')}
${redBright('rails rails')}
${cyan$1('phoenix phoenix')}
${green('django django')}
${yellow('flask flask')}
${blueBright('blazor blazor')}
${gray('hugo hugo')}`;
function printHelp() {
console.log(helpMessage);
}
function pkgFromUserAgent(userAgent) {
if (!userAgent)
return undefined;
const pkgSpec = userAgent.split(' ')[0];
const pkgSpecArr = pkgSpec.split('/');
return {
name: pkgSpecArr[0],
version: pkgSpecArr[1],
};
}
var crossSpawn = {exports: {}};
var windows;
var hasRequiredWindows;
function requireWindows () {
if (hasRequiredWindows) return windows;
hasRequiredWindows = 1;
windows = isexe;
isexe.sync = sync;
var fs = require$$0;
function checkPathExt (path, options) {
var pathext = options.pathExt !== undefined ?
options.pathExt : process.env.PATHEXT;
if (!pathext) {
return true
}
pathext = pathext.split(';');
if (pathext.indexOf('') !== -1) {
return true
}
for (var i = 0; i < pathext.length; i++) {
var p = pathext[i].toLowerCase();
if (p && path.substr(-p.length).toLowerCase() === p) {
return true
}
}
return false
}
function checkStat (stat, path, options) {
if (!stat.isSymbolicLink() && !stat.isFile()) {
return false
}
return checkPathExt(path, options)
}
function isexe (path, options, cb) {
fs.stat(path, function (er, stat) {
cb(er, er ? false : checkStat(stat, path, options));
});
}
function sync (path, options) {
return checkStat(fs.statSync(path), path, options)
}
return windows;
}
var mode;
var hasRequiredMode;
function requireMode () {
if (hasRequiredMode) return mode;
hasRequiredMode = 1;
mode = isexe;
isexe.sync = sync;
var fs = require$$0;
function isexe (path, options, cb) {
fs.stat(path, function (er, stat) {
cb(er, er ? false : checkStat(stat, options));
});
}
function sync (path, options) {
return checkStat(fs.statSync(path), options)
}
function checkStat (stat, options) {
return stat.isFile() && checkMode(stat, options)
}
function checkMode (stat, options) {
var mod = stat.mode;
var uid = stat.uid;
var gid = stat.gid;
var myUid = options.uid !== undefined ?
options.uid : process.getuid && process.getuid();
var myGid = options.gid !== undefined ?
options.gid : process.getgid && process.getgid();
var u = parseInt('100', 8);
var g = parseInt('010', 8);
var o = parseInt('001', 8);
var ug = u | g;
var ret = (mod & o) ||
(mod & g) && gid === myGid ||
(mod & u) && uid === myUid ||
(mod & ug) && myUid === 0;
return ret
}
return mode;
}
var core;
if (process.platform === 'win32' || commonjsGlobal.TESTING_WINDOWS) {
core = requireWindows();
} else {
core = requireMode();
}
var isexe_1 = isexe$1;
isexe$1.sync = sync;
function isexe$1 (path, options, cb) {
if (typeof options === 'function') {
cb = options;
options = {};
}
if (!cb) {
if (typeof Promise !== 'function') {
throw new TypeError('callback not provided')
}
return new Promise(function (resolve, reject) {
isexe$1(path, options || {}, function (er, is) {
if (er) {
reject(er);
} else {
resolve(is);
}
});
})
}
core(path, options || {}, function (er, is) {
// ignore EACCES because that just means we aren't allowed to run it
if (er) {
if (er.code === 'EACCES' || options && options.ignoreErrors) {
er = null;
is = false;
}
}
cb(er, is);
});
}
function sync (path, options) {
// my kingdom for a filtered catch
try {
return core.sync(path, options || {})
} catch (er) {
if (options && options.ignoreErrors || er.code === 'EACCES') {
return false
} else {
throw er
}
}
}
const isWindows = process.platform === 'win32' ||
process.env.OSTYPE === 'cygwin' ||
process.env.OSTYPE === 'msys';
const path$2 = require$$0$1;
const COLON = isWindows ? ';' : ':';
const isexe = isexe_1;
const getNotFoundError = (cmd) =>
Object.assign(new Error(`not found: ${cmd}`), { code: 'ENOENT' });
const getPathInfo = (cmd, opt) => {
const colon = opt.colon || COLON;
// If it has a slash, then we don't bother searching the pathenv.
// just check the file itself, and that's it.
const pathEnv = cmd.match(/\//) || isWindows && cmd.match(/\\/) ? ['']
: (
[
// windows always checks the cwd first
...(isWindows ? [process.cwd()] : []),
...(opt.path || process.env.PATH ||
/* istanbul ignore next: very unusual */ '').split(colon),
]
);
const pathExtExe = isWindows
? opt.pathExt || process.env.PATHEXT || '.EXE;.CMD;.BAT;.COM'
: '';
const pathExt = isWindows ? pathExtExe.split(colon) : [''];
if (isWindows) {
if (cmd.indexOf('.') !== -1 && pathExt[0] !== '')
pathExt.unshift('');
}
return {
pathEnv,
pathExt,
pathExtExe,
}
};
const which$1 = (cmd, opt, cb) => {
if (typeof opt === 'function') {
cb = opt;
opt = {};
}
if (!opt)
opt = {};
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
const found = [];
const step = i => new Promise((resolve, reject) => {
if (i === pathEnv.length)
return opt.all && found.length ? resolve(found)
: reject(getNotFoundError(cmd))
const ppRaw = pathEnv[i];
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
const pCmd = path$2.join(pathPart, cmd);
const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd
: pCmd;
resolve(subStep(p, i, 0));
});
const subStep = (p, i, ii) => new Promise((resolve, reject) => {
if (ii === pathExt.length)
return resolve(step(i + 1))
const ext = pathExt[ii];
isexe(p + ext, { pathExt: pathExtExe }, (er, is) => {
if (!er && is) {
if (opt.all)
found.push(p + ext);
else
return resolve(p + ext)
}
return resolve(subStep(p, i, ii + 1))
});
});
return cb ? step(0).then(res => cb(null, res), cb) : step(0)
};
const whichSync = (cmd, opt) => {
opt = opt || {};
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
const found = [];
for (let i = 0; i < pathEnv.length; i ++) {
const ppRaw = pathEnv[i];
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
const pCmd = path$2.join(pathPart, cmd);
const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd
: pCmd;
for (let j = 0; j < pathExt.length; j ++) {
const cur = p + pathExt[j];
try {
const is = isexe.sync(cur, { pathExt: pathExtExe });
if (is) {
if (opt.all)
found.push(cur);
else
return cur
}
} catch (ex) {}
}
}
if (opt.all && found.length)
return found
if (opt.nothrow)
return null
throw getNotFoundError(cmd)
};
var which_1 = which$1;
which$1.sync = whichSync;
var pathKey$1 = {exports: {}};
const pathKey = (options = {}) => {
const environment = options.env || process.env;
const platform = options.platform || process.platform;
if (platform !== 'win32') {
return 'PATH';
}
return Object.keys(environment).reverse().find(key => key.toUpperCase() === 'PATH') || 'Path';
};
pathKey$1.exports = pathKey;
// TODO: Remove this for the next major release
pathKey$1.exports.default = pathKey;
var pathKeyExports = pathKey$1.exports;
const path$1 = require$$0$1;
const which = which_1;
const getPathKey = pathKeyExports;
function resolveCommandAttempt(parsed, withoutPathExt) {
const env = parsed.options.env || process.env;
const cwd = process.cwd();
const hasCustomCwd = parsed.options.cwd != null;
// Worker threads do not have process.chdir()
const shouldSwitchCwd = hasCustomCwd && process.chdir !== undefined && !process.chdir.disabled;
// If a custom `cwd` was specified, we need to change the process cwd
// because `which` will do stat calls but does not support a custom cwd
if (shouldSwitchCwd) {
try {
process.chdir(parsed.options.cwd);
} catch (err) {
/* Empty */
}
}
let resolved;
try {
resolved = which.sync(parsed.command, {
path: env[getPathKey({ env })],
pathExt: withoutPathExt ? path$1.delimiter : undefined,
});
} catch (e) {
/* Empty */
} finally {
if (shouldSwitchCwd) {
process.chdir(cwd);
}
}
// If we successfully resolved, ensure that an absolute path is returned
// Note that when a custom `cwd`