create-stencil-components 1.0.3 → 1.0.5

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["variables: TemplateVariables","config: ProjectConfig","error: unknown","error: unknown"],"sources":["../src/utils.ts","../src/generator.ts","../src/prompts.ts","../src/cli.ts","../bin/index.ts"],"sourcesContent":["import fs from 'fs-extra';\r\nimport path from 'node:path';\r\n\r\n/**\r\n * Checks if a directory is empty.\r\n * @param dirPath - The path to the directory to check.\r\n * @returns A promise that resolves to true if the directory is empty, false otherwise.\r\n */\r\nexport async function isDirectoryEmpty(dirPath: string): Promise<boolean> {\r\n try {\r\n const files = await fs.readdir(dirPath);\r\n return files.length === 0;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Validates if a project name consists only of alphanumeric characters, hyphens, and underscores.\r\n * @param name - The project name to validate.\r\n * @returns True if the name is valid, false otherwise.\r\n */\r\nexport function validateProjectName(name: string): boolean {\r\n return /^[a-z0-9-_]+$/i.test(name);\r\n}\r\n\r\n/**\r\n * Checks if a file or directory exists at the given path.\r\n * @param filePath - The path to check.\r\n * @returns A promise that resolves to true if the file exists, false otherwise.\r\n */\r\nexport async function fileExists(filePath: string): Promise<boolean> {\r\n try {\r\n await fs.access(filePath);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Gets the absolute path to a specific template directory.\r\n * @param template - The name of the template.\r\n * @returns The absolute path to the template directory.\r\n */\r\nexport function getTemplateDir(template: string): string {\r\n return path.join(process.cwd(), 'templates', template);\r\n}\r\n\r\n/**\r\n * Converts a string to PascalCase.\r\n * @param str - The string to convert.\r\n * @returns The PascalCase string.\r\n */\r\nexport function toPascalCase(str: string): string {\r\n return str\r\n .replace(/[-_\\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ''))\r\n .replace(/^(.)/, (_, c) => c.toUpperCase());\r\n}\r\n\r\n/**\r\n * Converts a string to camelCase.\r\n * @param str - The string to convert.\r\n * @returns The camelCase string.\r\n */\r\nexport function toCamelCase(str: string): string {\r\n const pascal = toPascalCase(str);\r\n return pascal.charAt(0).toLowerCase() + pascal.slice(1);\r\n}\r\n\r\n/**\r\n * Converts a string to snake_case.\r\n * @param str - The string to convert.\r\n * @returns The snake_case string.\r\n */\r\nexport function toSnakeCase(str: string): string {\r\n return str\r\n .replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`)\r\n .replace(/[-\\s]+/g, '_')\r\n .replace(/^_/, '');\r\n}\r\n\r\n/**\r\n * Converts a string to kebab-case.\r\n * @param str - The string to convert.\r\n * @returns The kebab-case string.\r\n */\r\nexport function toKebabCase(str: string): string {\r\n return str\r\n .replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)\r\n .replace(/[_\\s]+/g, '-')\r\n .replace(/^-/, '');\r\n}","import * as prompts from '@clack/prompts';\r\nimport fs from 'fs-extra';\r\nimport { execSync } from 'node:child_process';\r\nimport path from 'node:path';\r\nimport { fileURLToPath } from 'node:url';\r\nimport pc from 'picocolors';\r\nimport type { ProjectConfig, TemplateVariables } from './types.js';\r\nimport { toCamelCase, toKebabCase, toPascalCase, toSnakeCase } from './utils.js';\r\n\r\nconst __filename = fileURLToPath(import.meta.url);\r\nconst __dirname = path.dirname(__filename);\r\n\r\n/**\r\n * Generates a new project based on the provided configuration.\r\n * @param config - The project configuration object.\r\n * @returns A promise that resolves when the project generation is complete.\r\n */\r\nexport async function generateProject(config: ProjectConfig): Promise<void> {\r\n const { projectName, template, packageManager = 'npm', git, install } = config;\r\n const targetDir = path.join(process.cwd(), projectName);\r\n\r\n // Check if directory already exists\r\n if (await fs.pathExists(targetDir)) {\r\n throw new Error(`Project directory ${projectName} already exists`);\r\n }\r\n\r\n await prompts.tasks([\r\n {\r\n title: 'Creating project directory',\r\n task: async () => {\r\n await fs.ensureDir(targetDir);\r\n await copyAndProcessTemplate(template, targetDir, config);\r\n return `Created project in ${targetDir}`;\r\n }\r\n },\r\n {\r\n title: 'Initializing git repository',\r\n task: async () => {\r\n if (git) {\r\n await initGit(targetDir);\r\n return `Initialized git repository`;\r\n }\r\n return `Skipped initializing git repository`;\r\n },\r\n enabled: false\r\n },\r\n {\r\n title: 'Installing dependencies',\r\n task: async () => {\r\n if (install) {\r\n await installDependencies(targetDir, packageManager);\r\n return `Installed dependencies`;\r\n }\r\n return `Skipped installing dependencies`;\r\n },\r\n enabled: false\r\n }\r\n ]);\r\n}\r\n\r\n/**\r\n * Copies the template files to the target directory and processes them.\r\n * @param template - The name of the template to use.\r\n * @param targetDir - The directory where the project will be created.\r\n * @param config - The project configuration.\r\n * @returns A promise that resolves when the template is copied and processed.\r\n */\r\nasync function copyAndProcessTemplate(\r\n template: string, \r\n targetDir: string,\r\n config: ProjectConfig\r\n): Promise<void> {\r\n const templatesRoot = path.join(__dirname, 'templates');\r\n const baseDir = path.join(templatesRoot, 'base');\r\n const templateDir = path.join(templatesRoot, 'variants', template);\r\n \r\n if (!await fs.pathExists(templateDir)) {\r\n throw new Error(`Template ${template} not found`);\r\n }\r\n\r\n // Prepare template variables\r\n const variables: TemplateVariables = {\r\n PROJECT_NAME: config.projectName,\r\n PROJECT_NAME_CAMEL: toCamelCase(config.projectName),\r\n PROJECT_NAME_KEBAB: toKebabCase(config.projectName),\r\n PROJECT_NAME_PASCAL: toPascalCase(config.projectName),\r\n PROJECT_NAME_SNAKE: toSnakeCase(config.projectName),\r\n ORGANIZATION_NAME: config.organizationName,\r\n LICENSE: config.license\r\n };\r\n\r\n // Step 1: Copy base template if it exists\r\n if (await fs.pathExists(baseDir)) {\r\n await fs.copy(baseDir, targetDir);\r\n // Rename gitignore if it exists\r\n await fs.move(\r\n path.join(targetDir, 'gitignore'), \r\n path.join(targetDir, '.gitignore')\r\n );\r\n }\r\n\r\n // Step 2: Copy template-specific files (overwrites base files if needed)\r\n await fs.copy(templateDir, targetDir, { overwrite: true });\r\n\r\n // Step 3: Rename folders with variables\r\n await renameFolders(targetDir, variables);\r\n \r\n // Step 4: Rename files with variables\r\n await renameFiles(targetDir, variables);\r\n \r\n // Step 5: Process all file contents\r\n await processTemplateFiles(targetDir, variables);\r\n}\r\n\r\n/**\r\n * Renames folders within a directory by replacing template variables in their names.\r\n * @param dir - The directory to process.\r\n * @param variables - The template variables to replace.\r\n * @returns A promise that resolves when folder renaming is complete.\r\n */\r\nasync function renameFolders(\r\n dir: string, \r\n variables: TemplateVariables\r\n): Promise<void> {\r\n const entries = await fs.readdir(dir, { withFileTypes: true });\r\n\r\n // Sort directories first, then process recursively\r\n for (const entry of entries) {\r\n const oldPath = path.join(dir, entry.name);\r\n\r\n if (entry.isDirectory()) {\r\n // First process subdirectories recursively\r\n await renameFolders(oldPath, variables);\r\n \r\n // Then rename this directory if needed\r\n const newName = replaceTemplateVariables(entry.name, variables);\r\n if (newName !== entry.name) {\r\n const newPath = path.join(dir, newName);\r\n await fs.move(oldPath, newPath);\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Renames files within a directory by replacing template variables in their names.\r\n * @param dir - The directory to process.\r\n * @param variables - The template variables to replace.\r\n * @returns A promise that resolves when file renaming is complete.\r\n */\r\nasync function renameFiles(\r\n dir: string, \r\n variables: TemplateVariables\r\n): Promise<void> {\r\n const entries = await fs.readdir(dir, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n const oldPath = path.join(dir, entry.name);\r\n\r\n if (entry.isDirectory()) {\r\n // Recursively process subdirectories\r\n await renameFiles(oldPath, variables);\r\n } else if (entry.isFile()) {\r\n // Rename file if it contains variables\r\n const newName = replaceTemplateVariables(entry.name, variables);\r\n if (newName !== entry.name) {\r\n const newPath = path.join(dir, newName);\r\n await fs.move(oldPath, newPath);\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Processes all files in a directory to replace template variables in their content.\r\n * @param dir - The directory to process.\r\n * @param variables - The template variables to replace.\r\n * @returns A promise that resolves when file processing is complete.\r\n */\r\nasync function processTemplateFiles(\r\n dir: string, \r\n variables: TemplateVariables\r\n): Promise<void> {\r\n const files = await fs.readdir(dir, { withFileTypes: true });\r\n\r\n for (const file of files) {\r\n const filePath = path.join(dir, file.name);\r\n\r\n if (file.isDirectory()) {\r\n // Recursively process subdirectories\r\n await processTemplateFiles(filePath, variables);\r\n } else if (file.isFile()) {\r\n // Process file based on extension\r\n await processFile(filePath, variables);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Processes a single file to replace template variables in its content.\r\n * @param filePath - The path to the file to process.\r\n * @param variables - The template variables to replace.\r\n * @returns A promise that resolves when the file is processed.\r\n */\r\nasync function processFile(\r\n filePath: string, \r\n variables: TemplateVariables\r\n): Promise<void> {\r\n const ext = path.extname(filePath);\r\n \r\n // Only process text files (not binaries like images)\r\n const textExtensions = [\r\n '.js', '.ts', '.jsx', '.tsx', '.json', '.md', '.html', \r\n '.css', '.scss', '.yaml', '.yml', '.txt', '.env', \r\n '.gitignore', '.npmrc', '.editorconfig'\r\n ];\r\n\r\n if (textExtensions.includes(ext) || !ext) {\r\n try {\r\n let content = await fs.readFile(filePath, 'utf8');\r\n \r\n // Replace template variables\r\n content = replaceTemplateVariables(content, variables);\r\n \r\n await fs.writeFile(filePath, content, 'utf8');\r\n } catch (error) {\r\n // Skip binary files that can't be read as text\r\n prompts.log.message(pc.gray(` Exception process file: ${error}`));\r\n prompts.log.message(pc.gray(` Skipping binary file: ${path.basename(filePath)}`));\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Replaces template variables in a string content.\r\n * @param content - The content string.\r\n * @param variables - The template variables to replace.\r\n * @returns The content with variables replaced.\r\n */\r\nfunction replaceTemplateVariables(\r\n content: string, \r\n variables: TemplateVariables\r\n): string {\r\n let result = content;\r\n\r\n // Replace {{VARIABLE_NAME}} tokens\r\n for (const [key, value] of Object.entries(variables)) {\r\n const regex = new RegExp(`{{\\\\s*${key}\\\\s*}}`, 'g');\r\n result = result.replace(regex, value);\r\n }\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Initializes a git repository in the target directory.\r\n * @param targetDir - The directory to initialize git in.\r\n * @returns A promise that resolves when git initialization is complete.\r\n */\r\nasync function initGit(targetDir: string): Promise<void> {\r\n try {\r\n execSync('git init', { cwd: targetDir, stdio: 'ignore' });\r\n } catch (error) {\r\n prompts.log.warn(pc.yellow(`Failed to initialize git repository: ${error}`));\r\n }\r\n}\r\n\r\n/**\r\n * Installs project dependencies using the specified package manager.\r\n * @param targetDir - The project directory.\r\n * @param packageManager - The package manager to use (e.g., 'npm', 'yarn', 'pnpm').\r\n * @returns A promise that resolves when dependencies are installed.\r\n */\r\nasync function installDependencies(targetDir: string, packageManager: string): Promise<void> { \r\n try {\r\n execSync(`${packageManager} install`, { \r\n cwd: targetDir, \r\n stdio: 'inherit' \r\n });\r\n } catch (error) {\r\n prompts.log.warn(pc.yellow(`Failed to install dependencies: ${error}`));\r\n prompts.log.info(pc.gray(` Run \"${packageManager} install\" manually`));\r\n }\r\n}","import * as prompts from '@clack/prompts';\r\nimport type { CLIOptions, PackageManager, ProjectConfig, TemplateType } from './types.js';\r\n\r\nimport { adjectives, colors, names, uniqueNamesGenerator } from 'unique-names-generator';\r\n\r\n/**\r\n * Prompts the user for project configuration details.\r\n * @param projectName - The name of the project, if provided as an argument.\r\n * @param options - Command-line options that pre-fill or configure the prompts.\r\n * @returns A promise that resolves to the complete project configuration.\r\n */\r\nexport async function getProjectQuestions(\r\n projectName: string | undefined,\r\n options: CLIOptions\r\n): Promise<ProjectConfig> {\r\n const answers = await prompts.group({\r\n projectName: async () => {\r\n return prompts.text({\r\n message: 'Project name:',\r\n initialValue: projectName || uniqueNamesGenerator({\r\n dictionaries: [adjectives, colors],\r\n separator: '-',\r\n style: 'lowerCase',\r\n length: 2,\r\n }),\r\n validate: (value: string) => {\r\n if (!value || value.trim() === '') {\r\n return 'Project name is required';\r\n }\r\n if (!/^[a-z0-9-_]+$/.test(value)) {\r\n return 'Invalid project name (can only contain lowercase letters, numbers, hyphens, and underscores)';\r\n }\r\n return undefined;\r\n }\r\n });\r\n },\r\n organizationName: async () => {\r\n return prompts.text({\r\n message: 'Organization name (used in the scope name field of the package.json):',\r\n initialValue: options?.organizationName || uniqueNamesGenerator({\r\n dictionaries: [names],\r\n style: 'lowerCase',\r\n length: 1\r\n }),\r\n validate: (value: string) => {\r\n if (!value || value.trim() === '') {\r\n return 'Organization name is required';\r\n }\r\n if (!/^[a-z]+$/.test(value)) {\r\n return 'Organization name can only contain lowercase letters';\r\n }\r\n return undefined;\r\n }\r\n });\r\n },\r\n template: async () => {\r\n return prompts.select({\r\n message: 'Select a framework:',\r\n options: [\r\n { label: 'angular', value: 'angular', hint: 'Angular framework' },\r\n { label: 'react', value: 'react', hint: 'React framework' },\r\n { label: 'vue', value: 'vue', hint: 'Vue framework' },\r\n { label: 'web-components', value: 'web-components', hint: 'Web components only' },\r\n { label: 'all', value: 'all', hint: 'Includes all frameworks' }\r\n ],\r\n initialValue: options.template || 'all',\r\n maxItems: 5\r\n });\r\n },\r\n packageManager: () => Promise.resolve('npm' as PackageManager),\r\n git: () => Promise.resolve(false),\r\n install: () => Promise.resolve(false)\r\n }, {\r\n onCancel: () => {\r\n prompts.cancel('Operation cancelled');\r\n process.exit(1);\r\n }\r\n });\r\n\r\n return {\r\n projectName: answers.projectName,\r\n organizationName: answers.organizationName,\r\n template: answers.template as TemplateType,\r\n packageManager: answers.packageManager,\r\n git: answers.git,\r\n install: answers.install\r\n };\r\n}\r\n\r\nexport default getProjectQuestions;","import * as prompts from '@clack/prompts';\r\nimport { Command } from 'commander';\r\nimport pc from 'picocolors';\r\nimport { generateProject } from './generator.js';\r\nimport { getProjectQuestions } from './prompts.js';\r\nimport type { CLIOptions, ProjectConfig } from './types.js';\r\n\r\n/**\r\n * The main entry point for the CLI.\r\n * Sets up the command-line interface, parses arguments, prompts the user for configuration,\r\n * and triggers the project generation process.\r\n * @returns A promise that resolves when the CLI execution is complete.\r\n */\r\nexport async function cli(): Promise<void> {\r\n const program = new Command();\r\n \r\n program\r\n .name('create-stencil-components')\r\n .description('Create a stencil component library project using Nx, TypeScript, and SASS.')\r\n .argument('[project-name]', 'Name of the project')\r\n .option('-o, --organization-name <name>', 'Name of the organization (used in the name field of the package.json)')\r\n .option('-t, --template <type>', 'Template type (angular, react, vue, web-components, all)')\r\n //.option('-p, --package-manager <pm>', 'Package manager (npm, yarn, pnpm)')\r\n //.option('--no-git', 'Skip git initialization')\r\n //.option('--no-install', 'Skip dependency installation')\r\n .parse();\r\n\r\n const options = program.opts<CLIOptions>();\r\n const [projectName] = program.args;\r\n\r\n prompts.intro(pc.cyan('Welcome to create-stencil-components!'));\r\n\r\n try {\r\n // Get user input through prompts\r\n const config: ProjectConfig = await getProjectQuestions(projectName, options);\r\n \r\n // Generate the project\r\n await generateProject(config);\r\n prompts.outro(pc.green('Your project is ready!'));\r\n printNextSteps(config);\r\n } catch (error: unknown) {\r\n if (error instanceof Error) {\r\n prompts.log.error(pc.red(`Error: ${error.message}`));\r\n }\r\n process.exit(1);\r\n }\r\n}\r\n\r\n/**\r\n * Prints the next steps for the user after the project has been successfully generated.\r\n * @param config - The configuration object containing project details like name and package manager.\r\n */\r\nfunction printNextSteps(config: ProjectConfig): void {\r\n const { projectName, packageManager = 'npm' } = config;\r\n \r\n console.log(pc.cyan('Next steps:'));\r\n console.log(` ${pc.gray('$')} cd ${projectName}`);\r\n \r\n if (config.install === false) {\r\n console.log(` ${pc.gray('$')} ${packageManager} install`);\r\n console.log(` ${pc.gray('$')} npx nx run-many -t build`);\r\n } else {\r\n console.log(` ${pc.gray('$')} npx nx run-many -t build`);\r\n }\r\n}","#!/usr/bin/env node\r\n\r\nimport { cli } from '../src/cli.js';\r\n\r\ntry {\r\n await cli();\r\n} catch (error: unknown) {\r\n if (error instanceof Error) {\r\n console.error(`Exception while doing something: ${error.message}`);\r\n }\r\n process.exit(1);\r\n}"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/utils.ts","../src/generator.ts","../src/prompts.ts","../src/cli.ts","../bin/index.ts"],"sourcesContent":["import fs from 'fs-extra';\r\nimport path from 'node:path';\r\n\r\n/**\r\n * Checks if a directory is empty.\r\n * @param dirPath - The path to the directory to check.\r\n * @returns A promise that resolves to true if the directory is empty, false otherwise.\r\n */\r\nexport async function isDirectoryEmpty(dirPath: string): Promise<boolean> {\r\n try {\r\n const files = await fs.readdir(dirPath);\r\n return files.length === 0;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Validates if a project name consists only of alphanumeric characters, hyphens, and underscores.\r\n * @param name - The project name to validate.\r\n * @returns True if the name is valid, false otherwise.\r\n */\r\nexport function validateProjectName(name: string): boolean {\r\n return /^[a-z0-9-_]+$/i.test(name);\r\n}\r\n\r\n/**\r\n * Checks if a file or directory exists at the given path.\r\n * @param filePath - The path to check.\r\n * @returns A promise that resolves to true if the file exists, false otherwise.\r\n */\r\nexport async function fileExists(filePath: string): Promise<boolean> {\r\n try {\r\n await fs.access(filePath);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Gets the absolute path to a specific template directory.\r\n * @param template - The name of the template.\r\n * @returns The absolute path to the template directory.\r\n */\r\nexport function getTemplateDir(template: string): string {\r\n return path.join(process.cwd(), 'templates', template);\r\n}\r\n\r\n/**\r\n * Converts a string to PascalCase.\r\n * @param str - The string to convert.\r\n * @returns The PascalCase string.\r\n */\r\nexport function toPascalCase(str: string): string {\r\n return str\r\n .replace(/[-_\\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ''))\r\n .replace(/^(.)/, (_, c) => c.toUpperCase());\r\n}\r\n\r\n/**\r\n * Converts a string to camelCase.\r\n * @param str - The string to convert.\r\n * @returns The camelCase string.\r\n */\r\nexport function toCamelCase(str: string): string {\r\n const pascal = toPascalCase(str);\r\n return pascal.charAt(0).toLowerCase() + pascal.slice(1);\r\n}\r\n\r\n/**\r\n * Converts a string to snake_case.\r\n * @param str - The string to convert.\r\n * @returns The snake_case string.\r\n */\r\nexport function toSnakeCase(str: string): string {\r\n return str\r\n .replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`)\r\n .replace(/[-\\s]+/g, '_')\r\n .replace(/^_/, '');\r\n}\r\n\r\n/**\r\n * Converts a string to kebab-case.\r\n * @param str - The string to convert.\r\n * @returns The kebab-case string.\r\n */\r\nexport function toKebabCase(str: string): string {\r\n return str\r\n .replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)\r\n .replace(/[_\\s]+/g, '-')\r\n .replace(/^-/, '');\r\n}","import * as prompts from '@clack/prompts';\r\nimport fs from 'fs-extra';\r\nimport { execSync } from 'node:child_process';\r\nimport path from 'node:path';\r\nimport { fileURLToPath } from 'node:url';\r\nimport pc from 'picocolors';\r\nimport type { ProjectConfig, TemplateVariables } from './types.js';\r\nimport { toCamelCase, toKebabCase, toPascalCase, toSnakeCase } from './utils.js';\r\n\r\nconst __filename = fileURLToPath(import.meta.url);\r\nconst __dirname = path.dirname(__filename);\r\n\r\n/**\r\n * Generates a new project based on the provided configuration.\r\n * @param config - The project configuration object.\r\n * @returns A promise that resolves when the project generation is complete.\r\n */\r\nexport async function generateProject(config: ProjectConfig): Promise<void> {\r\n const { projectName, template, packageManager = 'npm', git, install } = config;\r\n const targetDir = path.join(process.cwd(), projectName);\r\n\r\n // Check if directory already exists\r\n if (await fs.pathExists(targetDir)) {\r\n throw new Error(`Project directory ${projectName} already exists`);\r\n }\r\n\r\n await prompts.tasks([\r\n {\r\n title: 'Creating project directory',\r\n task: async () => {\r\n await fs.ensureDir(targetDir);\r\n await copyAndProcessTemplate(template, targetDir, config);\r\n return `Created project in ${targetDir}`;\r\n }\r\n },\r\n {\r\n title: 'Initializing git repository',\r\n task: async () => {\r\n if (git) {\r\n await initGit(targetDir);\r\n return `Initialized git repository`;\r\n }\r\n return `Skipped initializing git repository`;\r\n },\r\n enabled: false\r\n },\r\n {\r\n title: 'Installing dependencies',\r\n task: async () => {\r\n if (install) {\r\n await installDependencies(targetDir, packageManager);\r\n return `Installed dependencies`;\r\n }\r\n return `Skipped installing dependencies`;\r\n },\r\n enabled: false\r\n }\r\n ]);\r\n}\r\n\r\n/**\r\n * Copies the template files to the target directory and processes them.\r\n * @param template - The name of the template to use.\r\n * @param targetDir - The directory where the project will be created.\r\n * @param config - The project configuration.\r\n * @returns A promise that resolves when the template is copied and processed.\r\n */\r\nasync function copyAndProcessTemplate(\r\n template: string, \r\n targetDir: string,\r\n config: ProjectConfig\r\n): Promise<void> {\r\n const templatesRoot = path.join(__dirname, 'templates');\r\n const baseDir = path.join(templatesRoot, 'base');\r\n const templateDir = path.join(templatesRoot, 'variants', template);\r\n \r\n if (!await fs.pathExists(templateDir)) {\r\n throw new Error(`Template ${template} not found`);\r\n }\r\n\r\n // Prepare template variables\r\n const variables: TemplateVariables = {\r\n PROJECT_NAME: config.projectName,\r\n PROJECT_NAME_CAMEL: toCamelCase(config.projectName),\r\n PROJECT_NAME_KEBAB: toKebabCase(config.projectName),\r\n PROJECT_NAME_PASCAL: toPascalCase(config.projectName),\r\n PROJECT_NAME_SNAKE: toSnakeCase(config.projectName),\r\n ORGANIZATION_NAME: config.organizationName,\r\n LICENSE: config.license\r\n };\r\n\r\n // Step 1: Copy base template if it exists\r\n if (await fs.pathExists(baseDir)) {\r\n await fs.copy(baseDir, targetDir);\r\n // Rename gitignore if it exists\r\n await fs.move(\r\n path.join(targetDir, 'gitignore'), \r\n path.join(targetDir, '.gitignore')\r\n );\r\n }\r\n\r\n // Step 2: Copy template-specific files (overwrites base files if needed)\r\n await fs.copy(templateDir, targetDir, { overwrite: true });\r\n\r\n // Step 3: Rename folders with variables\r\n await renameFolders(targetDir, variables);\r\n \r\n // Step 4: Rename files with variables\r\n await renameFiles(targetDir, variables);\r\n \r\n // Step 5: Process all file contents\r\n await processTemplateFiles(targetDir, variables);\r\n}\r\n\r\n/**\r\n * Renames folders within a directory by replacing template variables in their names.\r\n * @param dir - The directory to process.\r\n * @param variables - The template variables to replace.\r\n * @returns A promise that resolves when folder renaming is complete.\r\n */\r\nasync function renameFolders(\r\n dir: string, \r\n variables: TemplateVariables\r\n): Promise<void> {\r\n const entries = await fs.readdir(dir, { withFileTypes: true });\r\n\r\n // Sort directories first, then process recursively\r\n for (const entry of entries) {\r\n const oldPath = path.join(dir, entry.name);\r\n\r\n if (entry.isDirectory()) {\r\n // First process subdirectories recursively\r\n await renameFolders(oldPath, variables);\r\n \r\n // Then rename this directory if needed\r\n const newName = replaceTemplateVariables(entry.name, variables);\r\n if (newName !== entry.name) {\r\n const newPath = path.join(dir, newName);\r\n await fs.move(oldPath, newPath);\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Renames files within a directory by replacing template variables in their names.\r\n * @param dir - The directory to process.\r\n * @param variables - The template variables to replace.\r\n * @returns A promise that resolves when file renaming is complete.\r\n */\r\nasync function renameFiles(\r\n dir: string, \r\n variables: TemplateVariables\r\n): Promise<void> {\r\n const entries = await fs.readdir(dir, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n const oldPath = path.join(dir, entry.name);\r\n\r\n if (entry.isDirectory()) {\r\n // Recursively process subdirectories\r\n await renameFiles(oldPath, variables);\r\n } else if (entry.isFile()) {\r\n // Rename file if it contains variables\r\n const newName = replaceTemplateVariables(entry.name, variables);\r\n if (newName !== entry.name) {\r\n const newPath = path.join(dir, newName);\r\n await fs.move(oldPath, newPath);\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Processes all files in a directory to replace template variables in their content.\r\n * @param dir - The directory to process.\r\n * @param variables - The template variables to replace.\r\n * @returns A promise that resolves when file processing is complete.\r\n */\r\nasync function processTemplateFiles(\r\n dir: string, \r\n variables: TemplateVariables\r\n): Promise<void> {\r\n const files = await fs.readdir(dir, { withFileTypes: true });\r\n\r\n for (const file of files) {\r\n const filePath = path.join(dir, file.name);\r\n\r\n if (file.isDirectory()) {\r\n // Recursively process subdirectories\r\n await processTemplateFiles(filePath, variables);\r\n } else if (file.isFile()) {\r\n // Process file based on extension\r\n await processFile(filePath, variables);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Processes a single file to replace template variables in its content.\r\n * @param filePath - The path to the file to process.\r\n * @param variables - The template variables to replace.\r\n * @returns A promise that resolves when the file is processed.\r\n */\r\nasync function processFile(\r\n filePath: string, \r\n variables: TemplateVariables\r\n): Promise<void> {\r\n const ext = path.extname(filePath);\r\n \r\n // Only process text files (not binaries like images)\r\n const textExtensions = [\r\n '.js', '.ts', '.jsx', '.tsx', '.json', '.md', '.html', \r\n '.css', '.scss', '.yaml', '.yml', '.txt', '.env', \r\n '.gitignore', '.npmrc', '.editorconfig'\r\n ];\r\n\r\n if (textExtensions.includes(ext) || !ext) {\r\n try {\r\n let content = await fs.readFile(filePath, 'utf8');\r\n \r\n // Replace template variables\r\n content = replaceTemplateVariables(content, variables);\r\n \r\n await fs.writeFile(filePath, content, 'utf8');\r\n } catch (error) {\r\n // Skip binary files that can't be read as text\r\n prompts.log.message(pc.gray(` Exception process file: ${error}`));\r\n prompts.log.message(pc.gray(` Skipping binary file: ${path.basename(filePath)}`));\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Replaces template variables in a string content.\r\n * @param content - The content string.\r\n * @param variables - The template variables to replace.\r\n * @returns The content with variables replaced.\r\n */\r\nfunction replaceTemplateVariables(\r\n content: string, \r\n variables: TemplateVariables\r\n): string {\r\n let result = content;\r\n\r\n // Replace {{VARIABLE_NAME}} tokens\r\n for (const [key, value] of Object.entries(variables)) {\r\n const regex = new RegExp(`{{\\\\s*${key}\\\\s*}}`, 'g');\r\n result = result.replace(regex, value);\r\n }\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Initializes a git repository in the target directory.\r\n * @param targetDir - The directory to initialize git in.\r\n * @returns A promise that resolves when git initialization is complete.\r\n */\r\nasync function initGit(targetDir: string): Promise<void> {\r\n try {\r\n execSync('git init', { cwd: targetDir, stdio: 'ignore' });\r\n } catch (error) {\r\n prompts.log.warn(pc.yellow(`Failed to initialize git repository: ${error}`));\r\n }\r\n}\r\n\r\n/**\r\n * Installs project dependencies using the specified package manager.\r\n * @param targetDir - The project directory.\r\n * @param packageManager - The package manager to use (e.g., 'npm', 'yarn', 'pnpm').\r\n * @returns A promise that resolves when dependencies are installed.\r\n */\r\nasync function installDependencies(targetDir: string, packageManager: string): Promise<void> { \r\n try {\r\n execSync(`${packageManager} install`, { \r\n cwd: targetDir, \r\n stdio: 'inherit' \r\n });\r\n } catch (error) {\r\n prompts.log.warn(pc.yellow(`Failed to install dependencies: ${error}`));\r\n prompts.log.info(pc.gray(` Run \"${packageManager} install\" manually`));\r\n }\r\n}","import * as prompts from '@clack/prompts';\r\nimport type { CLIOptions, PackageManager, ProjectConfig, TemplateType } from './types.js';\r\n\r\nimport { adjectives, colors, names, uniqueNamesGenerator } from 'unique-names-generator';\r\n\r\n/**\r\n * Prompts the user for project configuration details.\r\n * @param projectName - The name of the project, if provided as an argument.\r\n * @param options - Command-line options that pre-fill or configure the prompts.\r\n * @returns A promise that resolves to the complete project configuration.\r\n */\r\nexport async function getProjectQuestions(\r\n projectName: string | undefined,\r\n options: CLIOptions\r\n): Promise<ProjectConfig> {\r\n const answers = await prompts.group({\r\n projectName: async () => {\r\n return prompts.text({\r\n message: 'Project name:',\r\n initialValue: projectName || uniqueNamesGenerator({\r\n dictionaries: [adjectives, colors],\r\n separator: '-',\r\n style: 'lowerCase',\r\n length: 2,\r\n }),\r\n validate: (value: string) => {\r\n if (!value || value.trim() === '') {\r\n return 'Project name is required';\r\n }\r\n if (!/^[a-z0-9-_]+$/.test(value)) {\r\n return 'Invalid project name (can only contain lowercase letters, numbers, hyphens, and underscores)';\r\n }\r\n return undefined;\r\n }\r\n });\r\n },\r\n organizationName: async () => {\r\n return prompts.text({\r\n message: 'Organization name (used in the scope name field of the package.json):',\r\n initialValue: options?.organizationName || uniqueNamesGenerator({\r\n dictionaries: [names],\r\n style: 'lowerCase',\r\n length: 1\r\n }),\r\n validate: (value: string) => {\r\n if (!value || value.trim() === '') {\r\n return 'Organization name is required';\r\n }\r\n if (!/^[a-z]+$/.test(value)) {\r\n return 'Organization name can only contain lowercase letters';\r\n }\r\n return undefined;\r\n }\r\n });\r\n },\r\n template: async () => {\r\n return prompts.select({\r\n message: 'Select a framework:',\r\n options: [\r\n { label: 'angular', value: 'angular', hint: 'Angular framework' },\r\n { label: 'react', value: 'react', hint: 'React framework' },\r\n { label: 'vue', value: 'vue', hint: 'Vue framework' },\r\n { label: 'web-components', value: 'web-components', hint: 'Web components only' },\r\n { label: 'all', value: 'all', hint: 'Includes all frameworks' }\r\n ],\r\n initialValue: options.template || 'all',\r\n maxItems: 5\r\n });\r\n },\r\n packageManager: () => Promise.resolve('npm' as PackageManager),\r\n git: () => Promise.resolve(false),\r\n install: () => Promise.resolve(false)\r\n }, {\r\n onCancel: () => {\r\n prompts.cancel('Operation cancelled');\r\n process.exit(1);\r\n }\r\n });\r\n\r\n return {\r\n projectName: answers.projectName,\r\n organizationName: answers.organizationName,\r\n template: answers.template as TemplateType,\r\n packageManager: answers.packageManager,\r\n git: answers.git,\r\n install: answers.install\r\n };\r\n}\r\n\r\nexport default getProjectQuestions;","import * as prompts from '@clack/prompts';\r\nimport { Command } from 'commander';\r\nimport pc from 'picocolors';\r\nimport { generateProject } from './generator.js';\r\nimport { getProjectQuestions } from './prompts.js';\r\nimport type { CLIOptions, ProjectConfig } from './types.js';\r\n\r\n/**\r\n * The main entry point for the CLI.\r\n * Sets up the command-line interface, parses arguments, prompts the user for configuration,\r\n * and triggers the project generation process.\r\n * @returns A promise that resolves when the CLI execution is complete.\r\n */\r\nexport async function cli(): Promise<void> {\r\n const program = new Command();\r\n \r\n program\r\n .name('create-stencil-components')\r\n .description('Create a stencil component library project using Nx, TypeScript, and SASS.')\r\n .argument('[project-name]', 'Name of the project')\r\n .option('-o, --organization-name <name>', 'Name of the organization (used in the name field of the package.json)')\r\n .option('-t, --template <type>', 'Template type (angular, react, vue, web-components, all)')\r\n //.option('-p, --package-manager <pm>', 'Package manager (npm, yarn, pnpm)')\r\n //.option('--no-git', 'Skip git initialization')\r\n //.option('--no-install', 'Skip dependency installation')\r\n .parse();\r\n\r\n const options = program.opts<CLIOptions>();\r\n const [projectName] = program.args;\r\n\r\n prompts.intro(pc.cyan('Welcome to create-stencil-components!'));\r\n\r\n try {\r\n // Get user input through prompts\r\n const config: ProjectConfig = await getProjectQuestions(projectName, options);\r\n \r\n // Generate the project\r\n await generateProject(config);\r\n prompts.outro(pc.green('Your project is ready!'));\r\n printNextSteps(config);\r\n } catch (error: unknown) {\r\n if (error instanceof Error) {\r\n prompts.log.error(pc.red(`Error: ${error.message}`));\r\n }\r\n process.exit(1);\r\n }\r\n}\r\n\r\n/**\r\n * Prints the next steps for the user after the project has been successfully generated.\r\n * @param config - The configuration object containing project details like name and package manager.\r\n */\r\nfunction printNextSteps(config: ProjectConfig): void {\r\n const { projectName, packageManager = 'npm' } = config;\r\n \r\n console.log(pc.cyan('Next steps:'));\r\n console.log(` ${pc.gray('$')} cd ${projectName}`);\r\n \r\n if (config.install === false) {\r\n console.log(` ${pc.gray('$')} ${packageManager} install`);\r\n console.log(` ${pc.gray('$')} npx nx run-many -t build`);\r\n } else {\r\n console.log(` ${pc.gray('$')} npx nx run-many -t build`);\r\n }\r\n}","#!/usr/bin/env node\r\n\r\nimport { cli } from '../src/cli.js';\r\n\r\ntry {\r\n await cli();\r\n} catch (error: unknown) {\r\n if (error instanceof Error) {\r\n console.error(`Exception while doing something: ${error.message}`);\r\n }\r\n process.exit(1);\r\n}"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
 
2
- Strictly follow the rules in ./AGENTS.md
2
+ @AGENTS.md
3
3
 
4
4
  <!-- nx configuration start-->
5
5
  <!-- Leave the start & end comments to automatically receive updates. -->
@@ -1,83 +1,83 @@
1
- # @{{ORGANIZATION_NAME}}/{{PROJECT_NAME_KEBAB}}
2
-
3
- ## Overview
4
-
5
- Build modern, lightning-fast web applications for any platform using a single codebase. This toolkit utilizes [web components](https://www.webcomponents.org/introduction) to ensure premium quality and streamlined development.
6
-
7
- Stencil is a specialized compiler designed to generate standards-compliant Web Components (Custom Elements) compatible with any browser. By integrating premium features from modern frontend frameworks—including TypeScript, JSX, a virtual DOM, and reactive one-way data binding—into a compile-time engine, Stencil produces high-performance components. These components are framework-agnostic, allowing them to integrate seamlessly with any existing stack or operate as standalone elements.
8
-
9
- **Core Tech Stack:**
10
-
11
- - **Stencil**: The underlying Web Component compiler.
12
- - **TypeScript**: Ensures type safety and robust development.
13
- - **Nx**: Manages the build system and monorepo architecture.
14
- - **Sass**: Handles advanced, scalable CSS styling.
15
- - **Eslint & Stylelint**: Maintain code quality through static analysis for scripts and styles.
16
- - **Prettier**: Enforces consistent code formatting across the project.
17
-
18
- ## Build / Setup
19
-
20
- Follow these steps to set up and run the project locally.
21
-
22
- ### Prerequisites
23
-
24
- - **Volta:** The workspace uses [volta](https://volta.sh) to manage its npm and Node versions. [Install it](https://docs.volta.sh/guide/getting-started) before proceeding.
25
- - There's no need to install a specific version of npm or Node right now, it shall be done automatically for you.
26
- - **IDE:** We recommend [VS Code](https://code.visualstudio.com/) with the [Stencil Tools](https://marketplace.visualstudio.com/items?itemName=ionic.stencil-helper) extension.
27
-
28
- ### Installation & Running
29
-
30
- 1. **Install dependencies:**
31
-
32
- ```bash
33
- npm install
34
- ```
35
-
36
- 2. **Build for production:**
37
-
38
- ```bash
39
- npx nx run-many -t build
40
- ```
41
-
42
- 3. **Run unit tests:**
43
-
44
- ```bash
45
- npx nx run-many -t test
46
- ```
47
-
48
- ## Folder Hierarchy
49
-
50
- The repository structure is organized as follows:
51
-
52
- ```text
53
- ├── .eslintignore/ # ESLint ignore rules
54
- ├── .gitignore # Git ignore rules
55
- ├── .husky/ # Git hooks configuration
56
- ├── .mcp.json # MCP configuration
57
- ├── .nvmrc # NVM configuration
58
- ├── .prettierignore # Prettier ignore rules
59
- ├── .stylelintignore # Stylelint ignore rules
60
- ├── docs/ # Documentation files
61
- │ ├── CONTRIBUTING.md # Contributing guidelines
62
- │ ├── CODE_OF_CONDUCT.md # Contributor Code of Conduct
63
- | ├── LICENSE.md # License file
64
- │ └── STYLE_GUIDE.md # Stencil Style Guide
65
- ├── packages/ # Directory for npm workspaces
66
- │ └── [package-name]/ # Individual Stencil component library
67
- ├── AGENTS.md # AI context and guidelines for Nx
68
- ├── CLAUDE.md # AI context and guidelines for Nx
69
- ├── commitlint.config.mjs # Commitlint configuration
70
- ├── eslint.config.mjs # ESLint configuration
71
- ├── nx.json # Nx build system configuration
72
- ├── package-lock.json # NPM lock file
73
- ├── package.json # Root configuration: workspaces, dependencies, and scripts
74
- ├── prettier.config.mjs # Prettier configuration
75
- ├── stylelint.config.mjs # Stylelint configuration
76
- ├── tsconfig.base.json # Base TypeScript configuration
77
- └── README.md # Project documentation
78
- ```
79
-
80
- ## Contributing
81
-
82
- Thanks for your interest in contributing!
83
- Please take a moment to read up on our guidelines for [contributing](/docs/CONTRIBUTING.md). Please note that this project is released with a [Contributor Code of Conduct](/docs/CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms.
1
+ # @{{ORGANIZATION_NAME}}/{{PROJECT_NAME_KEBAB}}
2
+
3
+ ## Overview
4
+
5
+ Build modern, lightning-fast web applications for any platform using a single codebase. This toolkit utilizes [web components](https://www.webcomponents.org/introduction) to ensure premium quality and streamlined development.
6
+
7
+ Stencil is a specialized compiler designed to generate standards-compliant Web Components (Custom Elements) compatible with any browser. By integrating premium features from modern frontend frameworks—including TypeScript, JSX, a virtual DOM, and reactive one-way data binding—into a compile-time engine, Stencil produces high-performance components. These components are framework-agnostic, allowing them to integrate seamlessly with any existing stack or operate as standalone elements.
8
+
9
+ **Core Tech Stack:**
10
+
11
+ - **Stencil**: The underlying Web Component compiler.
12
+ - **TypeScript**: Ensures type safety and robust development.
13
+ - **Nx**: Manages the build system and monorepo architecture.
14
+ - **Sass**: Handles advanced, scalable CSS styling.
15
+ - **Eslint & Stylelint**: Maintain code quality through static analysis for scripts and styles.
16
+ - **Prettier**: Enforces consistent code formatting across the project.
17
+
18
+ ## Build / Setup
19
+
20
+ Follow these steps to set up and run the project locally.
21
+
22
+ ### Prerequisites
23
+
24
+ - **Volta:** The workspace uses [volta](https://volta.sh) to manage its npm and Node versions. [Install it](https://docs.volta.sh/guide/getting-started) before proceeding.
25
+ - There's no need to install a specific version of npm or Node right now, it shall be done automatically for you.
26
+ - **IDE:** We recommend [VS Code](https://code.visualstudio.com/) with the [Stencil Tools](https://marketplace.visualstudio.com/items?itemName=ionic.stencil-helper) extension.
27
+
28
+ ### Installation & Running
29
+
30
+ 1. **Install dependencies:**
31
+
32
+ ```bash
33
+ npm install
34
+ ```
35
+
36
+ 2. **Build for production:**
37
+
38
+ ```bash
39
+ npx nx run-many -t build
40
+ ```
41
+
42
+ 3. **Run unit tests:**
43
+
44
+ ```bash
45
+ npx nx run-many -t test
46
+ ```
47
+
48
+ ## Folder Hierarchy
49
+
50
+ The repository structure is organized as follows:
51
+
52
+ ```text
53
+ ├── .eslintignore/ # ESLint ignore rules
54
+ ├── .gitignore # Git ignore rules
55
+ ├── .husky/ # Git hooks configuration
56
+ ├── .mcp.json # MCP configuration
57
+ ├── .nvmrc # NVM configuration
58
+ ├── .prettierignore # Prettier ignore rules
59
+ ├── .stylelintignore # Stylelint ignore rules
60
+ ├── docs/ # Documentation files
61
+ │ ├── CONTRIBUTING.md # Contributing guidelines
62
+ │ ├── CODE_OF_CONDUCT.md # Contributor Code of Conduct
63
+ | ├── LICENSE.md # License file
64
+ │ └── STYLE_GUIDE.md # Stencil Style Guide
65
+ ├── packages/ # Directory for npm workspaces
66
+ │ └── [package-name]/ # Individual Stencil component library
67
+ ├── AGENTS.md # AI context and guidelines for Nx
68
+ ├── CLAUDE.md # AI context and guidelines for Nx
69
+ ├── commitlint.config.mjs # Commitlint configuration
70
+ ├── eslint.config.mjs # ESLint configuration
71
+ ├── nx.json # Nx build system configuration
72
+ ├── package-lock.json # NPM lock file
73
+ ├── package.json # Root configuration: workspaces, dependencies, and scripts
74
+ ├── prettier.config.mjs # Prettier configuration
75
+ ├── stylelint.config.mjs # Stylelint configuration
76
+ ├── tsconfig.base.json # Base TypeScript configuration
77
+ └── README.md # Project documentation
78
+ ```
79
+
80
+ ## Contributing
81
+
82
+ Thanks for your interest in contributing!
83
+ Please take a moment to read up on our guidelines for [contributing](/docs/CONTRIBUTING.md). Please note that this project is released with a [Contributor Code of Conduct](/docs/CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms.
@@ -1,43 +1,43 @@
1
1
  {
2
- "name": "@{{ORGANIZATION_NAME}}/{{PROJECT_NAME_KEBAB}}",
3
- "version": "0.0.0",
4
- "description": "Build modern, lightning-fast web applications for any platform using a single codebase",
5
- "license": "{{LICENSE}}",
6
- "keywords": [
7
- "agnostic",
8
- "stencil",
9
- "stenciljs",
10
- "web components"
11
- ],
12
- "scripts": {
13
- "prepare": "node .husky/install.mjs"
14
- },
15
- "devDependencies": {
16
- "@commitlint/cli": "20.3.0",
17
- "@commitlint/config-conventional": "20.3.0",
18
- "@eslint/js": "9.39.2",
19
- "@nx/js": "22.3.3",
20
- "eslint": "9.39.2",
21
- "eslint-config-prettier": "10.1.8",
22
- "eslint-plugin-prettier": "5.5.4",
23
- "eslint-plugin-sonarjs": "3.0.5",
24
- "husky": "9.1.7",
25
- "nx": "22.3.3",
26
- "rimraf": "6.1.2",
27
- "stylelint": "16.26.1",
28
- "stylelint-config-standard": "39.0.1",
29
- "stylelint-config-standard-scss": "16.0.0",
30
- "stylelint-use-logical": "2.1.2",
31
- "ts-node": "10.9.2",
32
- "typescript": "5.9.3",
33
- "typescript-eslint": "8.51.0"
34
- },
35
- "nx": {},
36
- "volta": {
37
- "node": "25.2.1"
38
- },
39
- "workspaces": [
40
- "packages/*"
41
- ],
42
- "dependencies": {}
2
+ "name": "@{{ORGANIZATION_NAME}}/{{PROJECT_NAME_KEBAB}}",
3
+ "version": "0.0.0",
4
+ "description": "Build modern, lightning-fast web applications for any platform using a single codebase",
5
+ "license": "{{LICENSE}}",
6
+ "keywords": [
7
+ "agnostic",
8
+ "stencil",
9
+ "stenciljs",
10
+ "web components"
11
+ ],
12
+ "scripts": {
13
+ "prepare": "node .husky/install.mjs"
14
+ },
15
+ "devDependencies": {
16
+ "@commitlint/cli": "20.3.1",
17
+ "@commitlint/config-conventional": "20.3.1",
18
+ "@eslint/js": "9.39.2",
19
+ "@nx/js": "22.3.3",
20
+ "eslint": "9.39.2",
21
+ "eslint-config-prettier": "10.1.8",
22
+ "eslint-plugin-prettier": "5.5.5",
23
+ "eslint-plugin-sonarjs": "3.0.5",
24
+ "husky": "9.1.7",
25
+ "nx": "22.3.3",
26
+ "rimraf": "6.1.2",
27
+ "stylelint": "17.0.0",
28
+ "stylelint-config-standard": "40.0.0",
29
+ "stylelint-config-standard-scss": "17.0.0",
30
+ "stylelint-use-logical": "2.1.2",
31
+ "ts-node": "10.9.2",
32
+ "typescript": "5.9.3",
33
+ "typescript-eslint": "8.53.0"
34
+ },
35
+ "nx": {},
36
+ "volta": {
37
+ "node": "25.3.0"
38
+ },
39
+ "workspaces": [
40
+ "packages/*"
41
+ ],
42
+ "dependencies": {}
43
43
  }
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Overview
4
4
 
5
- A framework-agnostic collection of [web components](https://www.webcomponents.org/introduction) built for maximum compatibility. These components integrate seamlessly with popular libraries like React, Angular, and Vue, or can function entirely on their own using standard browser JavaScript.
5
+ A framework-agnostic collection of [web components](https://www.webcomponents.org/introduction) built for maximum compatibility. These components integrate seamlessly with popular libraries like React, Angular, and Vue, or can function entirely on their own using standard browser JavaScript.
6
6
 
7
7
  ## Tasks
8
8
 
@@ -21,7 +21,7 @@
21
21
  "rxjs": ">=7.8.2"
22
22
  },
23
23
  "devDependencies": {
24
- "ng-packagr": "21.0.1"
24
+ "ng-packagr": "21.1.0"
25
25
  },
26
26
  "license": "MIT"
27
27
  }
@@ -68,17 +68,17 @@
68
68
  "tslib": "2.8.1"
69
69
  },
70
70
  "devDependencies": {
71
- "@stencil/angular-output-target": "1.1.1",
72
- "@stencil/core": "4.41.0",
73
- "@stencil/react-output-target": "1.2.0",
71
+ "@stencil/angular-output-target": "1.2.0",
72
+ "@stencil/core": "4.41.2",
73
+ "@stencil/react-output-target": "1.3.0",
74
74
  "@stencil/sass": "3.2.3",
75
- "@stencil/vue-output-target": "0.11.8",
75
+ "@stencil/vue-output-target": "0.12.1",
76
76
  "@types/jest": "30.0.0",
77
- "@types/node": "25.0.3",
77
+ "@types/node": "25.0.9",
78
78
  "jest": "30.2.0",
79
79
  "jest-cli": "30.2.0",
80
- "puppeteer": "24.34.0",
81
- "sass": "1.97.1",
80
+ "puppeteer": "24.35.0",
81
+ "sass": "1.97.2",
82
82
  "stencil-inline-svg": "1.1.0"
83
83
  },
84
84
  "license": "MIT"
@@ -40,7 +40,7 @@
40
40
  "react": ">=18"
41
41
  },
42
42
  "devDependencies": {
43
- "@types/node": "25.0.3",
43
+ "@types/node": "25.0.9",
44
44
  "@types/react": ">=18"
45
45
  },
46
46
  "license": "MIT",
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Overview
4
4
 
5
- Vue specific wrappers for the @{{ORGANIZATION_NAME}}/components-{{PROJECT_NAME_KEBAB}}-vue package.
5
+ Vue specific wrappers for the @{{ORGANIZATION_NAME}}/components-{{PROJECT_NAME_KEBAB}}-core package.
6
6
 
7
7
  ## Tasks
8
8
 
@@ -21,7 +21,7 @@
21
21
  "rxjs": ">=7.8.2"
22
22
  },
23
23
  "devDependencies": {
24
- "ng-packagr": "21.0.1"
24
+ "ng-packagr": "21.1.0"
25
25
  },
26
26
  "license": "MIT"
27
27
  }
@@ -68,15 +68,15 @@
68
68
  "tslib": "2.8.1"
69
69
  },
70
70
  "devDependencies": {
71
- "@stencil/angular-output-target": "1.1.1",
72
- "@stencil/core": "4.41.0",
71
+ "@stencil/angular-output-target": "1.2.0",
72
+ "@stencil/core": "4.41.2",
73
73
  "@stencil/sass": "3.2.3",
74
74
  "@types/jest": "30.0.0",
75
- "@types/node": "25.0.3",
75
+ "@types/node": "25.0.9",
76
76
  "jest": "30.2.0",
77
77
  "jest-cli": "30.2.0",
78
- "puppeteer": "24.34.0",
79
- "sass": "1.97.1",
78
+ "puppeteer": "24.35.0",
79
+ "sass": "1.97.2",
80
80
  "stencil-inline-svg": "1.1.0"
81
81
  },
82
82
  "license": "MIT"
@@ -68,15 +68,15 @@
68
68
  "tslib": "2.8.1"
69
69
  },
70
70
  "devDependencies": {
71
- "@stencil/core": "4.41.0",
72
- "@stencil/react-output-target": "1.2.0",
71
+ "@stencil/core": "4.41.2",
72
+ "@stencil/react-output-target": "1.3.0",
73
73
  "@stencil/sass": "3.2.3",
74
74
  "@types/jest": "30.0.0",
75
- "@types/node": "25.0.3",
75
+ "@types/node": "25.0.9",
76
76
  "jest": "30.2.0",
77
77
  "jest-cli": "30.2.0",
78
- "puppeteer": "24.34.0",
79
- "sass": "1.97.1",
78
+ "puppeteer": "24.35.0",
79
+ "sass": "1.97.2",
80
80
  "stencil-inline-svg": "1.1.0"
81
81
  },
82
82
  "license": "MIT"
@@ -40,7 +40,7 @@
40
40
  "react": ">=18"
41
41
  },
42
42
  "devDependencies": {
43
- "@types/node": "25.0.3",
43
+ "@types/node": "25.0.9",
44
44
  "@types/react": ">=18"
45
45
  },
46
46
  "license": "MIT",
@@ -68,15 +68,15 @@
68
68
  "tslib": "2.8.1"
69
69
  },
70
70
  "devDependencies": {
71
- "@stencil/core": "4.41.0",
71
+ "@stencil/core": "4.41.2",
72
72
  "@stencil/sass": "3.2.3",
73
- "@stencil/vue-output-target": "0.11.8",
73
+ "@stencil/vue-output-target": "0.12.1",
74
74
  "@types/jest": "30.0.0",
75
- "@types/node": "25.0.3",
75
+ "@types/node": "25.0.9",
76
76
  "jest": "30.2.0",
77
77
  "jest-cli": "30.2.0",
78
- "puppeteer": "24.34.0",
79
- "sass": "1.97.1",
78
+ "puppeteer": "24.35.0",
79
+ "sass": "1.97.2",
80
80
  "stencil-inline-svg": "1.1.0"
81
81
  },
82
82
  "license": "MIT"
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Overview
4
4
 
5
- Vue specific wrappers for the @{{ORGANIZATION_NAME}}/components-{{PROJECT_NAME_KEBAB}}-vue package.
5
+ Vue specific wrappers for the @{{ORGANIZATION_NAME}}/components-{{PROJECT_NAME_KEBAB}}-core package.
6
6
 
7
7
  ## Tasks
8
8
 
@@ -68,14 +68,14 @@
68
68
  "tslib": "2.8.1"
69
69
  },
70
70
  "devDependencies": {
71
- "@stencil/core": "4.41.0",
71
+ "@stencil/core": "4.41.2",
72
72
  "@stencil/sass": "3.2.3",
73
73
  "@types/jest": "30.0.0",
74
- "@types/node": "25.0.3",
74
+ "@types/node": "25.0.9",
75
75
  "jest": "30.2.0",
76
76
  "jest-cli": "30.2.0",
77
- "puppeteer": "24.34.0",
78
- "sass": "1.97.1",
77
+ "puppeteer": "24.35.0",
78
+ "sass": "1.97.2",
79
79
  "stencil-inline-svg": "1.1.0"
80
80
  },
81
81
  "license": "MIT"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-stencil-components",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "Create a stencil component library project using Nx, TypeScript, and SASS",
5
5
  "license": "MIT",
6
6
  "author": "Jason Messmer <mezlight@gmail.com>",
@@ -20,7 +20,6 @@
20
20
  "bin": {
21
21
  "create-stencil-components": "dist/index.mjs"
22
22
  },
23
- "main": "./dist/index.mjs",
24
23
  "type": "module",
25
24
  "files": [
26
25
  "dist"
@@ -39,26 +38,25 @@
39
38
  "dependencies": {
40
39
  "@clack/prompts": "0.11.0",
41
40
  "commander": "14.0.2",
42
- "fs-extra": "11.3.2",
41
+ "fs-extra": "11.3.3",
43
42
  "picocolors": "1.1.1",
44
43
  "unique-names-generator": "4.7.1"
45
44
  },
46
45
  "devDependencies": {
47
- "@commitlint/cli": "20.3.0",
48
- "@commitlint/config-conventional": "20.3.0",
46
+ "@commitlint/cli": "20.3.1",
47
+ "@commitlint/config-conventional": "20.3.1",
49
48
  "@types/fs-extra": "11.0.4",
50
- "@types/node": "25.0.3",
49
+ "@types/node": "25.0.9",
51
50
  "@types/prompts": "2.4.9",
52
51
  "rimraf": "6.1.2",
53
- "tsdown": "0.18.4",
52
+ "tsdown": "0.19.0",
54
53
  "typescript": "5.9.3"
55
54
  },
56
- "module": "./dist/index.mjs",
57
55
  "exports": {
58
56
  ".": "./dist/index.mjs",
59
57
  "./package.json": "./package.json"
60
58
  },
61
59
  "volta": {
62
- "node": "25.2.1"
60
+ "node": "25.3.0"
63
61
  }
64
62
  }