@elsapiens/cli 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +105 -34
- package/dist/index.js.map +1 -1
- package/dist/templates/app/env-example.ejs +10 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -220,6 +220,44 @@ async function initCommand(projectName, options) {
|
|
|
220
220
|
if (!name) {
|
|
221
221
|
name = "my-elsapiens-app";
|
|
222
222
|
}
|
|
223
|
+
let httpsPort = "443";
|
|
224
|
+
let grpcPort = "9090";
|
|
225
|
+
let restPort = "8080";
|
|
226
|
+
if (!options.yes) {
|
|
227
|
+
httpsPort = await text2({
|
|
228
|
+
message: "HTTPS port:",
|
|
229
|
+
placeholder: "443",
|
|
230
|
+
initialValue: "443",
|
|
231
|
+
validate: (value) => {
|
|
232
|
+
const port = parseInt(value, 10);
|
|
233
|
+
if (isNaN(port) || port < 1 || port > 65535) {
|
|
234
|
+
return "Please enter a valid port number (1-65535)";
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}) || "443";
|
|
238
|
+
grpcPort = await text2({
|
|
239
|
+
message: "gRPC port:",
|
|
240
|
+
placeholder: "9090",
|
|
241
|
+
initialValue: "9090",
|
|
242
|
+
validate: (value) => {
|
|
243
|
+
const port = parseInt(value, 10);
|
|
244
|
+
if (isNaN(port) || port < 1 || port > 65535) {
|
|
245
|
+
return "Please enter a valid port number (1-65535)";
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}) || "9090";
|
|
249
|
+
restPort = await text2({
|
|
250
|
+
message: "REST API port:",
|
|
251
|
+
placeholder: "8080",
|
|
252
|
+
initialValue: "8080",
|
|
253
|
+
validate: (value) => {
|
|
254
|
+
const port = parseInt(value, 10);
|
|
255
|
+
if (isNaN(port) || port < 1 || port > 65535) {
|
|
256
|
+
return "Please enter a valid port number (1-65535)";
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}) || "8080";
|
|
260
|
+
}
|
|
223
261
|
const projectDir = resolvePath(name);
|
|
224
262
|
if (await directoryExists(projectDir)) {
|
|
225
263
|
const shouldOverwrite = options.yes ? false : await confirm2({
|
|
@@ -352,9 +390,13 @@ async function initCommand(projectName, options) {
|
|
|
352
390
|
);
|
|
353
391
|
const envExample = await renderApp("env-example", {
|
|
354
392
|
projectName: name,
|
|
355
|
-
pascalName
|
|
393
|
+
pascalName,
|
|
394
|
+
httpsPort,
|
|
395
|
+
grpcPort,
|
|
396
|
+
restPort
|
|
356
397
|
});
|
|
357
398
|
await writeFile(path3.join(projectDir, ".env.example"), envExample);
|
|
399
|
+
await writeFile(path3.join(projectDir, ".env"), envExample);
|
|
358
400
|
const eslintConfig = await renderApp("eslint-config", {
|
|
359
401
|
projectName: name,
|
|
360
402
|
pascalName
|
|
@@ -448,7 +490,7 @@ async function pageCommand(pageName, options) {
|
|
|
448
490
|
cancel2();
|
|
449
491
|
}
|
|
450
492
|
let name = pageName;
|
|
451
|
-
if (!name) {
|
|
493
|
+
if (!name && !options.yes) {
|
|
452
494
|
name = await text2({
|
|
453
495
|
message: "Page name:",
|
|
454
496
|
placeholder: "Users",
|
|
@@ -460,39 +502,66 @@ async function pageCommand(pageName, options) {
|
|
|
460
502
|
}
|
|
461
503
|
});
|
|
462
504
|
}
|
|
505
|
+
if (!name) {
|
|
506
|
+
logger.error("Page name is required");
|
|
507
|
+
process.exit(1);
|
|
508
|
+
}
|
|
463
509
|
const pascalName = toPascalCase(name);
|
|
464
510
|
const kebabName = toKebabCase(name);
|
|
465
511
|
const routePath = toRoutePath(name);
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
512
|
+
let template = options.template;
|
|
513
|
+
if (!options.yes) {
|
|
514
|
+
template = await select2({
|
|
515
|
+
message: "Select a template:",
|
|
516
|
+
options: [
|
|
517
|
+
{
|
|
518
|
+
value: "dashboard",
|
|
519
|
+
label: "Dashboard",
|
|
520
|
+
hint: "Overview page with stats, charts, and activity table"
|
|
521
|
+
},
|
|
522
|
+
{
|
|
523
|
+
value: "list",
|
|
524
|
+
label: "List",
|
|
525
|
+
hint: "Data listing with search, filters, and table"
|
|
526
|
+
},
|
|
527
|
+
{
|
|
528
|
+
value: "settings",
|
|
529
|
+
label: "Settings",
|
|
530
|
+
hint: "Configuration page with form sections"
|
|
531
|
+
}
|
|
532
|
+
],
|
|
533
|
+
initialValue: options.template
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
let title = pascalName;
|
|
537
|
+
if (!options.yes) {
|
|
538
|
+
title = await text2({
|
|
539
|
+
message: "Page title:",
|
|
540
|
+
initialValue: pascalName
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
let description = `Manage ${kebabName.replace(/-/g, " ")}`;
|
|
544
|
+
if (!options.yes) {
|
|
545
|
+
description = await text2({
|
|
546
|
+
message: "Page description:",
|
|
547
|
+
placeholder: "Manage your data",
|
|
548
|
+
initialValue: description
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
let icon = "Package";
|
|
552
|
+
let singularTitle = pascalName.endsWith("s") ? pascalName.slice(0, -1) : pascalName;
|
|
553
|
+
if (template === "list" && !options.yes) {
|
|
554
|
+
icon = await text2({
|
|
555
|
+
message: "Icon name (from lucide-react):",
|
|
556
|
+
placeholder: "Package",
|
|
557
|
+
initialValue: icon
|
|
558
|
+
});
|
|
559
|
+
singularTitle = await text2({
|
|
560
|
+
message: 'Singular title (for "Add Item" button):',
|
|
561
|
+
placeholder: singularTitle,
|
|
562
|
+
initialValue: singularTitle
|
|
563
|
+
});
|
|
564
|
+
}
|
|
496
565
|
let pagesDir = options.path ? resolvePath(options.path) : null;
|
|
497
566
|
if (!pagesDir) {
|
|
498
567
|
pagesDir = await findPagesDir();
|
|
@@ -512,7 +581,9 @@ async function pageCommand(pageName, options) {
|
|
|
512
581
|
kebabName,
|
|
513
582
|
title,
|
|
514
583
|
description,
|
|
515
|
-
routePath
|
|
584
|
+
routePath,
|
|
585
|
+
icon,
|
|
586
|
+
singularTitle
|
|
516
587
|
});
|
|
517
588
|
await writeFile(filePath, content);
|
|
518
589
|
logger.success(`Created ${path4.relative(getCwd(), filePath)}`);
|
|
@@ -625,7 +696,7 @@ function createCli() {
|
|
|
625
696
|
program.name("elsapiens").description("CLI scaffolding tool for elSapiens SDK projects").version(VERSION, "-v, --version", "Display version number");
|
|
626
697
|
program.command("init [project-name]").alias("create").description("Create a new elSapiens project with full setup").option("--no-git", "Skip git initialization").option("-y, --yes", "Skip prompts and use defaults").action(initCommand);
|
|
627
698
|
program.command("add").alias("generate").alias("g").description("Add a page or component to the project").addCommand(
|
|
628
|
-
new Command("page").argument("[name]", "Page name").description("Add a new page").option("-t, --template <type>", "Page template (dashboard, list, settings)", "dashboard").option("-p, --path <dir>", "Custom pages directory").action(addCommand.page)
|
|
699
|
+
new Command("page").argument("[name]", "Page name").description("Add a new page").option("-t, --template <type>", "Page template (dashboard, list, settings)", "dashboard").option("-p, --path <dir>", "Custom pages directory").option("-y, --yes", "Skip prompts and use defaults").action(addCommand.page)
|
|
629
700
|
).addCommand(
|
|
630
701
|
new Command("component").argument("[name]", "Component name").description("Add a new component").option("-t, --template <type>", "Component template (simple, stateful)", "simple").option("-p, --path <dir>", "Custom components directory").action(addCommand.component)
|
|
631
702
|
);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/commands/init.ts","../src/utils/file.ts","../src/utils/prompt.ts","../src/utils/template.ts","../src/utils/logger.ts","../src/commands/add/page.ts","../src/commands/add/component.ts","../src/commands/add/index.ts","../src/index.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { initCommand } from './commands/init.js';\nimport { addCommand } from './commands/add/index.js';\n\nconst VERSION = '0.1.0';\n\nexport function createCli(): Command {\n const program = new Command();\n\n program\n .name('elsapiens')\n .description('CLI scaffolding tool for elSapiens SDK projects')\n .version(VERSION, '-v, --version', 'Display version number');\n\n // Init command - create new project\n program\n .command('init [project-name]')\n .alias('create')\n .description('Create a new elSapiens project with full setup')\n .option('--no-git', 'Skip git initialization')\n .option('-y, --yes', 'Skip prompts and use defaults')\n .action(initCommand);\n\n // Add command - add pages, components, etc.\n program\n .command('add')\n .alias('generate')\n .alias('g')\n .description('Add a page or component to the project')\n .addCommand(\n new Command('page')\n .argument('[name]', 'Page name')\n .description('Add a new page')\n .option('-t, --template <type>', 'Page template (dashboard, list, settings)', 'dashboard')\n .option('-p, --path <dir>', 'Custom pages directory')\n .action(addCommand.page)\n )\n .addCommand(\n new Command('component')\n .argument('[name]', 'Component name')\n .description('Add a new component')\n .option('-t, --template <type>', 'Component template (simple, stateful)', 'simple')\n .option('-p, --path <dir>', 'Custom components directory')\n .action(addCommand.component)\n );\n\n return program;\n}\n","/**\n * Init Command Module\n *\n * This module provides the `init` command for creating new elSapiens projects.\n * It handles project scaffolding, template generation, and optional git initialization.\n *\n * @module commands/init\n */\n\nimport path from 'path';\nimport { execSync } from 'child_process';\nimport {\n directoryExists,\n ensureDir,\n writeFile,\n resolvePath,\n toPascalCase,\n} from '../utils/file.js';\nimport {\n intro,\n outro,\n text,\n confirm,\n spinner,\n note,\n cancel,\n} from '../utils/prompt.js';\nimport { renderApp } from '../utils/template.js';\nimport { logger } from '../utils/logger.js';\n\n/**\n * Options for the init command.\n *\n * @interface InitOptions\n * @property {boolean} git - Whether to initialize a git repository\n * @property {boolean} yes - Skip all prompts and use default values\n */\ninterface InitOptions {\n git: boolean;\n yes: boolean;\n}\n\n/**\n * Initializes a new elSapiens project with the complete setup.\n *\n * This command creates a complete project structure including:\n * - package.json with all dependencies\n * - Vite configuration\n * - Tailwind CSS configuration\n * - PostCSS configuration\n * - TypeScript configuration\n * - HTML entry point\n * - React application files (main.tsx, App.tsx with full layout)\n * - CSS styles with full design system\n * - Dashboard and Settings pages\n * - Translations setup\n * - Help topics setup\n * - Services setup (ShortcutManager, Logger, ApiClient)\n * - Environment example file\n * - .gitignore file\n *\n * @param projectName - The name of the project to create. If not provided,\n * the user will be prompted to enter one (unless --yes is used).\n * @param options - Configuration options for project initialization\n * @param options.git - Whether to initialize a git repository after creation\n * @param options.yes - Skip interactive prompts and use default values\n * @returns A promise that resolves when the project is created successfully\n *\n * @example\n * // Create a project with default settings\n * await initCommand('my-app', { git: true, yes: false });\n *\n * @example\n * // Create a project without prompts\n * await initCommand('my-dashboard', { git: true, yes: true });\n *\n * @example\n * // Interactive mode (no project name provided)\n * await initCommand(undefined, { git: false, yes: false });\n *\n * @throws Will exit with code 1 if project creation fails\n */\nexport async function initCommand(\n projectName: string | undefined,\n options: InitOptions\n): Promise<void> {\n intro('elSapiens CLI');\n\n // Get project name\n let name = projectName;\n if (!name && !options.yes) {\n name = await text({\n message: 'Project name:',\n placeholder: 'my-app',\n validate: (value) => {\n if (!value) return 'Project name is required';\n if (!/^[a-z0-9-_]+$/i.test(value)) {\n return 'Project name can only contain letters, numbers, hyphens, and underscores';\n }\n },\n });\n }\n\n if (!name) {\n name = 'my-elsapiens-app';\n }\n\n const projectDir = resolvePath(name);\n\n // Check if directory exists\n if (await directoryExists(projectDir)) {\n const shouldOverwrite = options.yes\n ? false\n : await confirm({\n message: `Directory \"${name}\" already exists. Continue anyway?`,\n initialValue: false,\n });\n\n if (!shouldOverwrite) {\n cancel('Project creation cancelled.');\n }\n }\n\n // Start creating project\n const s = spinner();\n s.start('Creating project...');\n\n try {\n await ensureDir(projectDir);\n\n // Generate files\n const pascalName = toPascalCase(name);\n\n // Create package.json\n const packageJson = await renderApp('package', {\n projectName: name,\n pascalName,\n });\n await writeFile(path.join(projectDir, 'package.json'), packageJson);\n\n // Create vite.config.ts\n const viteConfig = await renderApp('vite-config', {\n projectName: name,\n pascalName,\n });\n await writeFile(path.join(projectDir, 'vite.config.ts'), viteConfig);\n\n // Create tailwind.config.js\n const tailwindConfig = await renderApp('tailwind-config', {\n projectName: name,\n pascalName,\n });\n await writeFile(path.join(projectDir, 'tailwind.config.js'), tailwindConfig);\n\n // Create postcss.config.js\n const postcssConfig = await renderApp('postcss-config', {\n projectName: name,\n pascalName,\n });\n await writeFile(path.join(projectDir, 'postcss.config.js'), postcssConfig);\n\n // Create tsconfig.json\n const tsconfig = await renderApp('tsconfig', {\n projectName: name,\n });\n await writeFile(path.join(projectDir, 'tsconfig.json'), tsconfig);\n\n // Create tsconfig.node.json\n const tsconfigNode = await renderApp('tsconfig-node', {\n projectName: name,\n });\n await writeFile(path.join(projectDir, 'tsconfig.node.json'), tsconfigNode);\n\n // Create index.html\n const indexHtml = await renderApp('index-html', {\n projectName: name,\n pascalName,\n });\n await writeFile(path.join(projectDir, 'index.html'), indexHtml);\n\n // Create src/main.tsx\n const mainTsx = await renderApp('main', {\n projectName: name,\n pascalName,\n });\n await writeFile(path.join(projectDir, 'src', 'main.tsx'), mainTsx);\n\n // Create src/App.tsx\n const appTsx = await renderApp('app', {\n projectName: name,\n pascalName,\n });\n await writeFile(path.join(projectDir, 'src', 'App.tsx'), appTsx);\n\n // Create src/index.css\n const indexCss = await renderApp('index-css', {\n projectName: name,\n });\n await writeFile(path.join(projectDir, 'src', 'index.css'), indexCss);\n\n // Create src/vite-env.d.ts\n const viteEnv = await renderApp('vite-env', {\n projectName: name,\n });\n await writeFile(path.join(projectDir, 'src', 'vite-env.d.ts'), viteEnv);\n\n // Create src/pages/Dashboard.tsx\n const dashboardPage = await renderApp('page-dashboard', {\n projectName: name,\n pascalName,\n });\n await writeFile(\n path.join(projectDir, 'src', 'pages', 'Dashboard.tsx'),\n dashboardPage\n );\n\n // Create src/pages/Settings.tsx\n const settingsPage = await renderApp('page-settings', {\n projectName: name,\n pascalName,\n });\n await writeFile(\n path.join(projectDir, 'src', 'pages', 'Settings.tsx'),\n settingsPage\n );\n\n // Create src/translations/common/en.ts\n const translationsCommonEn = await renderApp('translations-common-en', {\n projectName: name,\n pascalName,\n });\n await writeFile(\n path.join(projectDir, 'src', 'translations', 'common', 'en.ts'),\n translationsCommonEn\n );\n\n // Create src/translations/common/index.ts\n const translationsCommonIndex = await renderApp('translations-common-index', {\n projectName: name,\n pascalName,\n });\n await writeFile(\n path.join(projectDir, 'src', 'translations', 'common', 'index.ts'),\n translationsCommonIndex\n );\n\n // Create src/translations/settings/en.ts\n const translationsSettingsEn = await renderApp('translations-settings-en', {\n projectName: name,\n pascalName,\n });\n await writeFile(\n path.join(projectDir, 'src', 'translations', 'settings', 'en.ts'),\n translationsSettingsEn\n );\n\n // Create src/translations/settings/index.ts\n const translationsSettingsIndex = await renderApp('translations-settings-index', {\n projectName: name,\n pascalName,\n });\n await writeFile(\n path.join(projectDir, 'src', 'translations', 'settings', 'index.ts'),\n translationsSettingsIndex\n );\n\n // Create src/help-topics.ts\n const helpTopics = await renderApp('help-topics', {\n projectName: name,\n pascalName,\n });\n await writeFile(\n path.join(projectDir, 'src', 'help-topics.ts'),\n helpTopics\n );\n\n // Create src/services/index.ts\n const servicesSetup = await renderApp('services-setup', {\n projectName: name,\n pascalName,\n });\n await writeFile(\n path.join(projectDir, 'src', 'services', 'index.ts'),\n servicesSetup\n );\n\n // Create .env.example\n const envExample = await renderApp('env-example', {\n projectName: name,\n pascalName,\n });\n await writeFile(path.join(projectDir, '.env.example'), envExample);\n\n // Create eslint.config.js\n const eslintConfig = await renderApp('eslint-config', {\n projectName: name,\n pascalName,\n });\n await writeFile(path.join(projectDir, 'eslint.config.js'), eslintConfig);\n\n // Create vitest.config.ts\n const vitestConfig = await renderApp('vitest-config', {\n projectName: name,\n pascalName,\n });\n await writeFile(path.join(projectDir, 'vitest.config.ts'), vitestConfig);\n\n // Create src/test/setup.ts\n const testSetup = await renderApp('test-setup', {\n projectName: name,\n pascalName,\n });\n await writeFile(path.join(projectDir, 'src', 'test', 'setup.ts'), testSetup);\n\n // Create .husky/pre-commit\n const huskyPreCommit = await renderApp('husky-pre-commit', {\n projectName: name,\n pascalName,\n });\n await writeFile(path.join(projectDir, '.husky', 'pre-commit'), huskyPreCommit);\n\n // Create .gitignore\n const gitignore = `# Dependencies\nnode_modules/\n\n# Build output\ndist/\n\n# IDE\n.idea/\n.vscode/\n*.swp\n*.swo\n\n# OS\n.DS_Store\nThumbs.db\n\n# Environment\n.env\n.env.local\n.env.*.local\n\n# Logs\n*.log\nnpm-debug.log*\n\n# Coverage\ncoverage/\n`;\n await writeFile(path.join(projectDir, '.gitignore'), gitignore);\n\n s.stop('Project created!');\n\n // Initialize git\n if (options.git) {\n const initGit = options.yes\n ? true\n : await confirm({\n message: 'Initialize git repository?',\n initialValue: true,\n });\n\n if (initGit) {\n try {\n execSync('git init -b main', { cwd: projectDir, stdio: 'ignore' });\n execSync('git add .', { cwd: projectDir, stdio: 'ignore' });\n execSync('git commit -m \"Initial commit\"', { cwd: projectDir, stdio: 'ignore' });\n logger.success('Git repository initialized with initial commit');\n } catch {\n logger.warn('Failed to initialize git repository');\n }\n }\n }\n\n // Show next steps\n note(\n `cd ${name}\npnpm install\npnpm dev`,\n 'Next steps'\n );\n\n outro('Happy coding!');\n } catch (error) {\n s.stop('Failed to create project');\n logger.error(\n error instanceof Error ? error.message : 'Unknown error occurred'\n );\n process.exit(1);\n }\n}\n","import fs from 'fs-extra';\nimport path from 'path';\n\n/**\n * Check if a directory exists\n */\nexport async function directoryExists(dirPath: string): Promise<boolean> {\n try {\n const stat = await fs.stat(dirPath);\n return stat.isDirectory();\n } catch {\n return false;\n }\n}\n\n/**\n * Check if a file exists\n */\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n const stat = await fs.stat(filePath);\n return stat.isFile();\n } catch {\n return false;\n }\n}\n\n/**\n * Create a directory (and parents) if it doesn't exist\n */\nexport async function ensureDir(dirPath: string): Promise<void> {\n await fs.ensureDir(dirPath);\n}\n\n/**\n * Write content to a file, creating directories as needed\n */\nexport async function writeFile(\n filePath: string,\n content: string\n): Promise<void> {\n await fs.ensureDir(path.dirname(filePath));\n await fs.writeFile(filePath, content, 'utf-8');\n}\n\n/**\n * Read file content\n */\nexport async function readFile(filePath: string): Promise<string> {\n return fs.readFile(filePath, 'utf-8');\n}\n\n/**\n * Copy a file\n */\nexport async function copyFile(src: string, dest: string): Promise<void> {\n await fs.ensureDir(path.dirname(dest));\n await fs.copyFile(src, dest);\n}\n\n/**\n * Copy a directory recursively\n */\nexport async function copyDir(src: string, dest: string): Promise<void> {\n await fs.copy(src, dest);\n}\n\n/**\n * Get the current working directory\n */\nexport function getCwd(): string {\n return process.cwd();\n}\n\n/**\n * Resolve a path relative to cwd\n */\nexport function resolvePath(...paths: string[]): string {\n return path.resolve(getCwd(), ...paths);\n}\n\n/**\n * Check if current directory is an elsapiens project\n */\nexport async function isElSapiensProject(dir: string = getCwd()): Promise<boolean> {\n const packageJsonPath = path.join(dir, 'package.json');\n\n if (!(await fileExists(packageJsonPath))) {\n return false;\n }\n\n try {\n const content = await readFile(packageJsonPath);\n const pkg = JSON.parse(content);\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n\n // Check for any @elsapiens package\n return Object.keys(deps).some((dep) => dep.startsWith('@elsapiens/'));\n } catch {\n return false;\n }\n}\n\n/**\n * Find the pages directory in a project\n */\nexport async function findPagesDir(dir: string = getCwd()): Promise<string | null> {\n const candidates = [\n path.join(dir, 'src', 'pages'),\n path.join(dir, 'src', 'app'),\n path.join(dir, 'pages'),\n ];\n\n for (const candidate of candidates) {\n if (await directoryExists(candidate)) {\n return candidate;\n }\n }\n\n return null;\n}\n\n/**\n * Find the components directory in a project\n */\nexport async function findComponentsDir(\n dir: string = getCwd()\n): Promise<string | null> {\n const candidates = [\n path.join(dir, 'src', 'components'),\n path.join(dir, 'components'),\n ];\n\n for (const candidate of candidates) {\n if (await directoryExists(candidate)) {\n return candidate;\n }\n }\n\n return null;\n}\n\n/**\n * Convert a string to PascalCase\n */\nexport function toPascalCase(str: string): string {\n return str\n .split(/[-_\\s]+/)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join('');\n}\n\n/**\n * Convert a string to kebab-case\n */\nexport function toKebabCase(str: string): string {\n return str\n .replace(/([a-z])([A-Z])/g, '$1-$2')\n .replace(/[\\s_]+/g, '-')\n .toLowerCase();\n}\n\n/**\n * Convert a string to a valid route path\n */\nexport function toRoutePath(str: string): string {\n return '/' + toKebabCase(str);\n}\n","import * as p from '@clack/prompts';\nimport pc from 'picocolors';\n\n/**\n * Show intro banner\n */\nexport function intro(message: string): void {\n p.intro(pc.bgCyan(pc.black(` ${message} `)));\n}\n\n/**\n * Show outro message\n */\nexport function outro(message: string): void {\n p.outro(pc.green(message));\n}\n\n/**\n * Show a cancel message and exit\n */\nexport function cancel(message: string = 'Operation cancelled.'): never {\n p.cancel(message);\n process.exit(0);\n}\n\n/**\n * Check if the user cancelled the prompt\n */\nexport function isCancel(value: unknown): value is symbol {\n return p.isCancel(value);\n}\n\n/**\n * Handle cancel - exit if cancelled, return value otherwise\n */\nexport function handleCancel<T>(value: T | symbol): T {\n if (isCancel(value)) {\n cancel();\n }\n return value as T;\n}\n\n/**\n * Ask for text input\n */\nexport async function text(options: {\n message: string;\n placeholder?: string;\n initialValue?: string;\n validate?: (value: string) => string | void;\n}): Promise<string> {\n const result = await p.text(options);\n return handleCancel(result);\n}\n\n/**\n * Ask for a selection from options\n */\nexport async function select<T extends string>(options: {\n message: string;\n options: { value: T; label: string; hint?: string }[];\n initialValue?: T;\n}): Promise<T> {\n const result = await p.select(options);\n return handleCancel(result) as T;\n}\n\n/**\n * Ask for multiple selections\n */\nexport async function multiselect<T extends string>(options: {\n message: string;\n options: { value: T; label: string; hint?: string }[];\n required?: boolean;\n}): Promise<T[]> {\n const result = await p.multiselect(options);\n return handleCancel(result) as T[];\n}\n\n/**\n * Ask for confirmation\n */\nexport async function confirm(options: {\n message: string;\n initialValue?: boolean;\n}): Promise<boolean> {\n const result = await p.confirm(options);\n return handleCancel(result);\n}\n\n/**\n * Show a spinner during async operation\n */\nexport function spinner(): {\n start: (message?: string) => void;\n stop: (message?: string, code?: number) => void;\n message: (message?: string) => void;\n} {\n return p.spinner();\n}\n\n/**\n * Show a group of tasks\n */\nexport async function tasks(\n items: { title: string; task: () => Promise<string> }[]\n): Promise<void> {\n await p.tasks(items);\n}\n\n/**\n * Log a note/info message\n */\nexport function note(message: string, title?: string): void {\n p.note(message, title);\n}\n\n/**\n * Log a message during prompts\n */\nexport function log(options: { message?: string; symbol?: string }): void {\n p.log.message(options.message ?? '', { symbol: options.symbol });\n}\n","import ejs from 'ejs';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport { readFile } from './file.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n// Templates are in dist/templates when bundled (same level as index.js)\nconst TEMPLATES_DIR = path.resolve(__dirname, 'templates');\n\nexport interface TemplateData {\n [key: string]: unknown;\n}\n\n/**\n * Get the path to a template file\n */\nexport function getTemplatePath(category: string, name: string): string {\n return path.join(TEMPLATES_DIR, category, `${name}.ejs`);\n}\n\n/**\n * Render an EJS template with the given data\n */\nexport async function renderTemplate(\n templatePath: string,\n data: TemplateData\n): Promise<string> {\n const template = await readFile(templatePath);\n return ejs.render(template, data, {\n async: false,\n });\n}\n\n/**\n * Render a named template from the templates directory\n */\nexport async function render(\n category: string,\n name: string,\n data: TemplateData\n): Promise<string> {\n const templatePath = getTemplatePath(category, name);\n return renderTemplate(templatePath, data);\n}\n\n/**\n * Render a page template\n */\nexport async function renderPage(\n templateName: string,\n data: {\n name: string;\n pascalName: string;\n title: string;\n description: string;\n [key: string]: unknown;\n }\n): Promise<string> {\n return render('pages', templateName, data);\n}\n\n/**\n * Render a component template\n */\nexport async function renderComponent(\n templateName: string,\n data: {\n name: string;\n pascalName: string;\n [key: string]: unknown;\n }\n): Promise<string> {\n return render('components', templateName, data);\n}\n\n/**\n * Render an app template\n */\nexport async function renderApp(\n templateName: string,\n data: {\n projectName: string;\n [key: string]: unknown;\n }\n): Promise<string> {\n return render('app', templateName, data);\n}\n","import pc from 'picocolors';\n\nexport const logger = {\n info: (message: string) => {\n console.log(pc.blue('ℹ'), message);\n },\n\n success: (message: string) => {\n console.log(pc.green('✓'), message);\n },\n\n warn: (message: string) => {\n console.log(pc.yellow('⚠'), message);\n },\n\n error: (message: string) => {\n console.log(pc.red('✗'), message);\n },\n\n log: (message: string) => {\n console.log(message);\n },\n\n blank: () => {\n console.log();\n },\n\n title: (message: string) => {\n console.log();\n console.log(pc.bold(pc.cyan(message)));\n },\n\n step: (message: string) => {\n console.log(pc.dim(' -'), message);\n },\n\n code: (code: string) => {\n console.log(pc.dim(' ') + pc.cyan(code));\n },\n\n box: (message: string) => {\n const line = '─'.repeat(message.length + 2);\n console.log(pc.dim(`┌${line}┐`));\n console.log(pc.dim('│ ') + pc.bold(message) + pc.dim(' │'));\n console.log(pc.dim(`└${line}┘`));\n },\n};\n\nexport default logger;\n","/**\n * Add Page Command Module\n *\n * This module provides the `add page` command for creating new page components\n * in an existing elSapiens project. It supports multiple page templates and\n * generates the necessary routing code.\n *\n * @module commands/add/page\n */\n\nimport path from 'path';\nimport {\n fileExists,\n findPagesDir,\n isElSapiensProject,\n writeFile,\n resolvePath,\n toPascalCase,\n toKebabCase,\n toRoutePath,\n getCwd,\n} from '../../utils/file.js';\nimport {\n intro,\n outro,\n text,\n select,\n note,\n cancel,\n} from '../../utils/prompt.js';\nimport { renderPage } from '../../utils/template.js';\nimport { logger } from '../../utils/logger.js';\n\n/**\n * Options for the page command.\n *\n * @interface PageOptions\n * @property {('dashboard' | 'list' | 'settings')} template - The page template to use\n * @property {string} [path] - Optional custom path for the pages directory\n */\ninterface PageOptions {\n template: 'dashboard' | 'list' | 'settings';\n path?: string;\n}\n\n/**\n * Creates a new page component in an elSapiens project.\n *\n * This command generates a page file based on the selected template and provides\n * instructions for integrating it into the application's routing configuration.\n *\n * Available templates:\n * - `dashboard` - Overview page with stats, charts, and activity table\n * - `list` - Data listing page with search, filters, and table\n * - `settings` - Configuration page with form sections\n *\n * The command will:\n * 1. Verify the current directory is an elSapiens project\n * 2. Prompt for page name if not provided\n * 3. Allow template selection\n * 4. Prompt for page title and description\n * 5. Generate the page file in the pages directory\n * 6. Display routing instructions for App.tsx integration\n *\n * @param pageName - The name of the page to create. Should be in PascalCase or\n * will be converted. If not provided, user will be prompted.\n * @param options - Configuration options for page generation\n * @param options.template - The page template to use ('dashboard', 'list', or 'settings')\n * @param options.path - Custom path for the pages directory (defaults to auto-detected)\n * @returns A promise that resolves when the page is created successfully\n *\n * @example\n * // Create a dashboard page named 'Analytics'\n * await pageCommand('Analytics', { template: 'dashboard' });\n *\n * @example\n * // Create a list page with custom path\n * await pageCommand('Users', { template: 'list', path: './src/views' });\n *\n * @example\n * // Interactive mode (no page name provided)\n * await pageCommand(undefined, { template: 'settings' });\n *\n * @throws Will exit with code 1 if page creation fails\n * @throws Will cancel if not in an elSapiens project directory\n * @throws Will cancel if the page file already exists\n */\nexport async function pageCommand(\n pageName: string | undefined,\n options: PageOptions\n): Promise<void> {\n intro('Add Page');\n\n // Check if we're in an elsapiens project\n const isProject = await isElSapiensProject();\n if (!isProject) {\n logger.warn('This does not appear to be an elSapiens project.');\n logger.info('Run \"el init\" to create a new project first.');\n cancel();\n }\n\n // Get page name\n let name = pageName;\n if (!name) {\n name = await text({\n message: 'Page name:',\n placeholder: 'Users',\n validate: (value) => {\n if (!value) return 'Page name is required';\n if (!/^[a-zA-Z][a-zA-Z0-9]*$/.test(value)) {\n return 'Page name must start with a letter and contain only letters and numbers';\n }\n },\n });\n }\n\n const pascalName = toPascalCase(name);\n const kebabName = toKebabCase(name);\n const routePath = toRoutePath(name);\n\n // Get template\n const template = await select({\n message: 'Select a template:',\n options: [\n {\n value: 'dashboard',\n label: 'Dashboard',\n hint: 'Overview page with stats, charts, and activity table',\n },\n {\n value: 'list',\n label: 'List',\n hint: 'Data listing with search, filters, and table',\n },\n {\n value: 'settings',\n label: 'Settings',\n hint: 'Configuration page with form sections',\n },\n ],\n initialValue: options.template,\n });\n\n // Get page title\n const title = await text({\n message: 'Page title:',\n initialValue: pascalName,\n });\n\n // Get page description\n const description = await text({\n message: 'Page description:',\n placeholder: 'Manage your data',\n initialValue: `Manage ${kebabName.replace(/-/g, ' ')}`,\n });\n\n // Find pages directory\n let pagesDir = options.path ? resolvePath(options.path) : null;\n if (!pagesDir) {\n pagesDir = await findPagesDir();\n if (!pagesDir) {\n pagesDir = resolvePath('src', 'pages');\n }\n }\n\n const filePath = path.join(pagesDir, `${pascalName}.tsx`);\n\n // Check if file exists\n if (await fileExists(filePath)) {\n logger.error(`File already exists: ${filePath}`);\n cancel();\n }\n\n try {\n // Render template\n const content = await renderPage(template, {\n name,\n pascalName,\n kebabName,\n title,\n description,\n routePath,\n });\n\n // Write file\n await writeFile(filePath, content);\n\n logger.success(`Created ${path.relative(getCwd(), filePath)}`);\n\n // Show routing instructions\n note(\n `Add this route to your App.tsx:\n\nimport ${pascalName} from './pages/${pascalName}';\n\n<Route path=\"${routePath}\" element={<${pascalName} />} />\n\nAnd add to navigation:\n{ id: '${kebabName}', path: '${routePath}', label: '${title}', icon: <Icon /> }`,\n 'Next steps'\n );\n\n outro('Page created!');\n } catch (error) {\n logger.error(\n error instanceof Error ? error.message : 'Failed to create page'\n );\n process.exit(1);\n }\n}\n","/**\n * Add Component Command Module\n *\n * This module provides the `add component` command for creating new React components\n * in an existing elSapiens project. It supports simple and stateful component templates.\n *\n * @module commands/add/component\n */\n\nimport path from 'path';\nimport {\n fileExists,\n findComponentsDir,\n isElSapiensProject,\n writeFile,\n resolvePath,\n toPascalCase,\n getCwd,\n} from '../../utils/file.js';\nimport { intro, outro, text, select, note, cancel } from '../../utils/prompt.js';\nimport { renderComponent } from '../../utils/template.js';\nimport { logger } from '../../utils/logger.js';\n\n/**\n * Options for the component command.\n *\n * @interface ComponentOptions\n * @property {('simple' | 'stateful')} template - The component template to use\n * @property {string} [path] - Optional custom path for the components directory\n */\ninterface ComponentOptions {\n template: 'simple' | 'stateful';\n path?: string;\n}\n\n/**\n * Creates a new React component in an elSapiens project.\n *\n * This command generates a component file based on the selected template and\n * provides usage instructions for importing and using the component.\n *\n * Available templates:\n * - `simple` - Basic functional component with props and className support\n * - `stateful` - Component with useState hook and onChange callback pattern\n *\n * The command will:\n * 1. Verify the current directory is an elSapiens project\n * 2. Prompt for component name if not provided\n * 3. Allow template selection (simple or stateful)\n * 4. Generate the component file in the components directory\n * 5. Display usage instructions for importing the component\n *\n * @param componentName - The name of the component to create. Should be in PascalCase\n * or will be converted. If not provided, user will be prompted.\n * @param options - Configuration options for component generation\n * @param options.template - The component template to use ('simple' or 'stateful')\n * @param options.path - Custom path for the components directory (defaults to auto-detected)\n * @returns A promise that resolves when the component is created successfully\n *\n * @example\n * // Create a simple component named 'UserCard'\n * await componentCommand('UserCard', { template: 'simple' });\n *\n * @example\n * // Create a stateful component with custom path\n * await componentCommand('Counter', { template: 'stateful', path: './src/ui' });\n *\n * @example\n * // Interactive mode (no component name provided)\n * await componentCommand(undefined, { template: 'simple' });\n *\n * @throws Will exit with code 1 if component creation fails\n * @throws Will cancel if not in an elSapiens project directory\n * @throws Will cancel if the component file already exists\n */\nexport async function componentCommand(\n componentName: string | undefined,\n options: ComponentOptions\n): Promise<void> {\n intro('Add Component');\n\n // Check if we're in an elsapiens project\n const isProject = await isElSapiensProject();\n if (!isProject) {\n logger.warn('This does not appear to be an elSapiens project.');\n logger.info('Run \"el init\" to create a new project first.');\n cancel();\n }\n\n // Get component name\n let name = componentName;\n if (!name) {\n name = await text({\n message: 'Component name:',\n placeholder: 'UserCard',\n validate: (value) => {\n if (!value) return 'Component name is required';\n if (!/^[a-zA-Z][a-zA-Z0-9]*$/.test(value)) {\n return 'Component name must start with a letter and contain only letters and numbers';\n }\n },\n });\n }\n\n const pascalName = toPascalCase(name);\n\n // Get template\n const template = await select({\n message: 'Select a template:',\n options: [\n {\n value: 'simple',\n label: 'Simple',\n hint: 'Basic component with props and className',\n },\n {\n value: 'stateful',\n label: 'Stateful',\n hint: 'Component with useState and onChange callback',\n },\n ],\n initialValue: options.template,\n });\n\n // Find components directory\n let componentsDir = options.path ? resolvePath(options.path) : null;\n if (!componentsDir) {\n componentsDir = await findComponentsDir();\n if (!componentsDir) {\n componentsDir = resolvePath('src', 'components');\n }\n }\n\n const filePath = path.join(componentsDir, `${pascalName}.tsx`);\n\n // Check if file exists\n if (await fileExists(filePath)) {\n logger.error(`File already exists: ${filePath}`);\n cancel();\n }\n\n try {\n // Render template\n const content = await renderComponent(template, {\n name,\n pascalName,\n });\n\n // Write file\n await writeFile(filePath, content);\n\n logger.success(`Created ${path.relative(getCwd(), filePath)}`);\n\n // Show usage instructions\n note(\n `Import and use your component:\n\nimport { ${pascalName} } from './components/${pascalName}';\n\n<${pascalName} className=\"...\" />`,\n 'Usage'\n );\n\n outro('Component created!');\n } catch (error) {\n logger.error(\n error instanceof Error ? error.message : 'Failed to create component'\n );\n process.exit(1);\n }\n}\n","import { pageCommand } from './page.js';\nimport { componentCommand } from './component.js';\n\nexport const addCommand = {\n page: pageCommand,\n component: componentCommand,\n};\n","/**\n * elSapiens CLI Entry Point\n *\n * This module serves as the main entry point for the elSapiens CLI application.\n * It initializes and starts the command-line interface by creating and parsing\n * the CLI instance.\n *\n * @module cli\n *\n * @example\n * // Running the CLI from the command line:\n * npx el init my-project\n * npx el add page Users\n * npx el add component UserCard\n */\n\nimport { createCli } from './cli.js';\n\n/**\n * Creates the CLI instance and parses command-line arguments.\n *\n * The CLI supports the following commands:\n * - `init [name]` - Initialize a new elSapiens project\n * - `add page [name]` - Add a new page to an existing project\n * - `add component [name]` - Add a new component to an existing project\n *\n * @example\n * // The CLI is automatically invoked when running the package:\n * // npx el init my-app --template full --git\n */\nconst cli = createCli();\ncli.parse();\n"],"mappings":"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","names":["path","intro","outro","cancel","isCancel","text","select","confirm","spinner","note","path","path","pc","intro","text","confirm","cancel","spinner","path","note","outro","path","intro","cancel","text","select","path","note","outro","path","intro","cancel","text","select","path","note","outro"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/commands/init.ts","../src/utils/file.ts","../src/utils/prompt.ts","../src/utils/template.ts","../src/utils/logger.ts","../src/commands/add/page.ts","../src/commands/add/component.ts","../src/commands/add/index.ts","../src/index.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { initCommand } from './commands/init.js';\nimport { addCommand } from './commands/add/index.js';\n\nconst VERSION = '0.1.0';\n\nexport function createCli(): Command {\n const program = new Command();\n\n program\n .name('elsapiens')\n .description('CLI scaffolding tool for elSapiens SDK projects')\n .version(VERSION, '-v, --version', 'Display version number');\n\n // Init command - create new project\n program\n .command('init [project-name]')\n .alias('create')\n .description('Create a new elSapiens project with full setup')\n .option('--no-git', 'Skip git initialization')\n .option('-y, --yes', 'Skip prompts and use defaults')\n .action(initCommand);\n\n // Add command - add pages, components, etc.\n program\n .command('add')\n .alias('generate')\n .alias('g')\n .description('Add a page or component to the project')\n .addCommand(\n new Command('page')\n .argument('[name]', 'Page name')\n .description('Add a new page')\n .option('-t, --template <type>', 'Page template (dashboard, list, settings)', 'dashboard')\n .option('-p, --path <dir>', 'Custom pages directory')\n .option('-y, --yes', 'Skip prompts and use defaults')\n .action(addCommand.page)\n )\n .addCommand(\n new Command('component')\n .argument('[name]', 'Component name')\n .description('Add a new component')\n .option('-t, --template <type>', 'Component template (simple, stateful)', 'simple')\n .option('-p, --path <dir>', 'Custom components directory')\n .action(addCommand.component)\n );\n\n return program;\n}\n","/**\n * Init Command Module\n *\n * This module provides the `init` command for creating new elSapiens projects.\n * It handles project scaffolding, template generation, and optional git initialization.\n *\n * @module commands/init\n */\n\nimport path from 'path';\nimport { execSync } from 'child_process';\nimport {\n directoryExists,\n ensureDir,\n writeFile,\n resolvePath,\n toPascalCase,\n} from '../utils/file.js';\nimport {\n intro,\n outro,\n text,\n confirm,\n spinner,\n note,\n cancel,\n} from '../utils/prompt.js';\nimport { renderApp } from '../utils/template.js';\nimport { logger } from '../utils/logger.js';\n\n/**\n * Options for the init command.\n *\n * @interface InitOptions\n * @property {boolean} git - Whether to initialize a git repository\n * @property {boolean} yes - Skip all prompts and use default values\n */\ninterface InitOptions {\n git: boolean;\n yes: boolean;\n}\n\n/**\n * Initializes a new elSapiens project with the complete setup.\n *\n * This command creates a complete project structure including:\n * - package.json with all dependencies\n * - Vite configuration\n * - Tailwind CSS configuration\n * - PostCSS configuration\n * - TypeScript configuration\n * - HTML entry point\n * - React application files (main.tsx, App.tsx with full layout)\n * - CSS styles with full design system\n * - Dashboard and Settings pages\n * - Translations setup\n * - Help topics setup\n * - Services setup (ShortcutManager, Logger, ApiClient)\n * - Environment example file\n * - .gitignore file\n *\n * @param projectName - The name of the project to create. If not provided,\n * the user will be prompted to enter one (unless --yes is used).\n * @param options - Configuration options for project initialization\n * @param options.git - Whether to initialize a git repository after creation\n * @param options.yes - Skip interactive prompts and use default values\n * @returns A promise that resolves when the project is created successfully\n *\n * @example\n * // Create a project with default settings\n * await initCommand('my-app', { git: true, yes: false });\n *\n * @example\n * // Create a project without prompts\n * await initCommand('my-dashboard', { git: true, yes: true });\n *\n * @example\n * // Interactive mode (no project name provided)\n * await initCommand(undefined, { git: false, yes: false });\n *\n * @throws Will exit with code 1 if project creation fails\n */\nexport async function initCommand(\n projectName: string | undefined,\n options: InitOptions\n): Promise<void> {\n intro('elSapiens CLI');\n\n // Get project name\n let name = projectName;\n if (!name && !options.yes) {\n name = await text({\n message: 'Project name:',\n placeholder: 'my-app',\n validate: (value) => {\n if (!value) return 'Project name is required';\n if (!/^[a-z0-9-_]+$/i.test(value)) {\n return 'Project name can only contain letters, numbers, hyphens, and underscores';\n }\n },\n });\n }\n\n if (!name) {\n name = 'my-elsapiens-app';\n }\n\n // Get API configuration\n let httpsPort = '443';\n let grpcPort = '9090';\n let restPort = '8080';\n\n if (!options.yes) {\n httpsPort = await text({\n message: 'HTTPS port:',\n placeholder: '443',\n initialValue: '443',\n validate: (value) => {\n const port = parseInt(value, 10);\n if (isNaN(port) || port < 1 || port > 65535) {\n return 'Please enter a valid port number (1-65535)';\n }\n },\n }) || '443';\n\n grpcPort = await text({\n message: 'gRPC port:',\n placeholder: '9090',\n initialValue: '9090',\n validate: (value) => {\n const port = parseInt(value, 10);\n if (isNaN(port) || port < 1 || port > 65535) {\n return 'Please enter a valid port number (1-65535)';\n }\n },\n }) || '9090';\n\n restPort = await text({\n message: 'REST API port:',\n placeholder: '8080',\n initialValue: '8080',\n validate: (value) => {\n const port = parseInt(value, 10);\n if (isNaN(port) || port < 1 || port > 65535) {\n return 'Please enter a valid port number (1-65535)';\n }\n },\n }) || '8080';\n }\n\n const projectDir = resolvePath(name);\n\n // Check if directory exists\n if (await directoryExists(projectDir)) {\n const shouldOverwrite = options.yes\n ? false\n : await confirm({\n message: `Directory \"${name}\" already exists. Continue anyway?`,\n initialValue: false,\n });\n\n if (!shouldOverwrite) {\n cancel('Project creation cancelled.');\n }\n }\n\n // Start creating project\n const s = spinner();\n s.start('Creating project...');\n\n try {\n await ensureDir(projectDir);\n\n // Generate files\n const pascalName = toPascalCase(name);\n\n // Create package.json\n const packageJson = await renderApp('package', {\n projectName: name,\n pascalName,\n });\n await writeFile(path.join(projectDir, 'package.json'), packageJson);\n\n // Create vite.config.ts\n const viteConfig = await renderApp('vite-config', {\n projectName: name,\n pascalName,\n });\n await writeFile(path.join(projectDir, 'vite.config.ts'), viteConfig);\n\n // Create tailwind.config.js\n const tailwindConfig = await renderApp('tailwind-config', {\n projectName: name,\n pascalName,\n });\n await writeFile(path.join(projectDir, 'tailwind.config.js'), tailwindConfig);\n\n // Create postcss.config.js\n const postcssConfig = await renderApp('postcss-config', {\n projectName: name,\n pascalName,\n });\n await writeFile(path.join(projectDir, 'postcss.config.js'), postcssConfig);\n\n // Create tsconfig.json\n const tsconfig = await renderApp('tsconfig', {\n projectName: name,\n });\n await writeFile(path.join(projectDir, 'tsconfig.json'), tsconfig);\n\n // Create tsconfig.node.json\n const tsconfigNode = await renderApp('tsconfig-node', {\n projectName: name,\n });\n await writeFile(path.join(projectDir, 'tsconfig.node.json'), tsconfigNode);\n\n // Create index.html\n const indexHtml = await renderApp('index-html', {\n projectName: name,\n pascalName,\n });\n await writeFile(path.join(projectDir, 'index.html'), indexHtml);\n\n // Create src/main.tsx\n const mainTsx = await renderApp('main', {\n projectName: name,\n pascalName,\n });\n await writeFile(path.join(projectDir, 'src', 'main.tsx'), mainTsx);\n\n // Create src/App.tsx\n const appTsx = await renderApp('app', {\n projectName: name,\n pascalName,\n });\n await writeFile(path.join(projectDir, 'src', 'App.tsx'), appTsx);\n\n // Create src/index.css\n const indexCss = await renderApp('index-css', {\n projectName: name,\n });\n await writeFile(path.join(projectDir, 'src', 'index.css'), indexCss);\n\n // Create src/vite-env.d.ts\n const viteEnv = await renderApp('vite-env', {\n projectName: name,\n });\n await writeFile(path.join(projectDir, 'src', 'vite-env.d.ts'), viteEnv);\n\n // Create src/pages/Dashboard.tsx\n const dashboardPage = await renderApp('page-dashboard', {\n projectName: name,\n pascalName,\n });\n await writeFile(\n path.join(projectDir, 'src', 'pages', 'Dashboard.tsx'),\n dashboardPage\n );\n\n // Create src/pages/Settings.tsx\n const settingsPage = await renderApp('page-settings', {\n projectName: name,\n pascalName,\n });\n await writeFile(\n path.join(projectDir, 'src', 'pages', 'Settings.tsx'),\n settingsPage\n );\n\n // Create src/translations/common/en.ts\n const translationsCommonEn = await renderApp('translations-common-en', {\n projectName: name,\n pascalName,\n });\n await writeFile(\n path.join(projectDir, 'src', 'translations', 'common', 'en.ts'),\n translationsCommonEn\n );\n\n // Create src/translations/common/index.ts\n const translationsCommonIndex = await renderApp('translations-common-index', {\n projectName: name,\n pascalName,\n });\n await writeFile(\n path.join(projectDir, 'src', 'translations', 'common', 'index.ts'),\n translationsCommonIndex\n );\n\n // Create src/translations/settings/en.ts\n const translationsSettingsEn = await renderApp('translations-settings-en', {\n projectName: name,\n pascalName,\n });\n await writeFile(\n path.join(projectDir, 'src', 'translations', 'settings', 'en.ts'),\n translationsSettingsEn\n );\n\n // Create src/translations/settings/index.ts\n const translationsSettingsIndex = await renderApp('translations-settings-index', {\n projectName: name,\n pascalName,\n });\n await writeFile(\n path.join(projectDir, 'src', 'translations', 'settings', 'index.ts'),\n translationsSettingsIndex\n );\n\n // Create src/help-topics.ts\n const helpTopics = await renderApp('help-topics', {\n projectName: name,\n pascalName,\n });\n await writeFile(\n path.join(projectDir, 'src', 'help-topics.ts'),\n helpTopics\n );\n\n // Create src/services/index.ts\n const servicesSetup = await renderApp('services-setup', {\n projectName: name,\n pascalName,\n });\n await writeFile(\n path.join(projectDir, 'src', 'services', 'index.ts'),\n servicesSetup\n );\n\n // Create .env.example\n const envExample = await renderApp('env-example', {\n projectName: name,\n pascalName,\n httpsPort,\n grpcPort,\n restPort,\n });\n await writeFile(path.join(projectDir, '.env.example'), envExample);\n\n // Create .env with same values\n await writeFile(path.join(projectDir, '.env'), envExample);\n\n // Create eslint.config.js\n const eslintConfig = await renderApp('eslint-config', {\n projectName: name,\n pascalName,\n });\n await writeFile(path.join(projectDir, 'eslint.config.js'), eslintConfig);\n\n // Create vitest.config.ts\n const vitestConfig = await renderApp('vitest-config', {\n projectName: name,\n pascalName,\n });\n await writeFile(path.join(projectDir, 'vitest.config.ts'), vitestConfig);\n\n // Create src/test/setup.ts\n const testSetup = await renderApp('test-setup', {\n projectName: name,\n pascalName,\n });\n await writeFile(path.join(projectDir, 'src', 'test', 'setup.ts'), testSetup);\n\n // Create .husky/pre-commit\n const huskyPreCommit = await renderApp('husky-pre-commit', {\n projectName: name,\n pascalName,\n });\n await writeFile(path.join(projectDir, '.husky', 'pre-commit'), huskyPreCommit);\n\n // Create .gitignore\n const gitignore = `# Dependencies\nnode_modules/\n\n# Build output\ndist/\n\n# IDE\n.idea/\n.vscode/\n*.swp\n*.swo\n\n# OS\n.DS_Store\nThumbs.db\n\n# Environment\n.env\n.env.local\n.env.*.local\n\n# Logs\n*.log\nnpm-debug.log*\n\n# Coverage\ncoverage/\n`;\n await writeFile(path.join(projectDir, '.gitignore'), gitignore);\n\n s.stop('Project created!');\n\n // Initialize git\n if (options.git) {\n const initGit = options.yes\n ? true\n : await confirm({\n message: 'Initialize git repository?',\n initialValue: true,\n });\n\n if (initGit) {\n try {\n execSync('git init -b main', { cwd: projectDir, stdio: 'ignore' });\n execSync('git add .', { cwd: projectDir, stdio: 'ignore' });\n execSync('git commit -m \"Initial commit\"', { cwd: projectDir, stdio: 'ignore' });\n logger.success('Git repository initialized with initial commit');\n } catch {\n logger.warn('Failed to initialize git repository');\n }\n }\n }\n\n // Show next steps\n note(\n `cd ${name}\npnpm install\npnpm dev`,\n 'Next steps'\n );\n\n outro('Happy coding!');\n } catch (error) {\n s.stop('Failed to create project');\n logger.error(\n error instanceof Error ? error.message : 'Unknown error occurred'\n );\n process.exit(1);\n }\n}\n","import fs from 'fs-extra';\nimport path from 'path';\n\n/**\n * Check if a directory exists\n */\nexport async function directoryExists(dirPath: string): Promise<boolean> {\n try {\n const stat = await fs.stat(dirPath);\n return stat.isDirectory();\n } catch {\n return false;\n }\n}\n\n/**\n * Check if a file exists\n */\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n const stat = await fs.stat(filePath);\n return stat.isFile();\n } catch {\n return false;\n }\n}\n\n/**\n * Create a directory (and parents) if it doesn't exist\n */\nexport async function ensureDir(dirPath: string): Promise<void> {\n await fs.ensureDir(dirPath);\n}\n\n/**\n * Write content to a file, creating directories as needed\n */\nexport async function writeFile(\n filePath: string,\n content: string\n): Promise<void> {\n await fs.ensureDir(path.dirname(filePath));\n await fs.writeFile(filePath, content, 'utf-8');\n}\n\n/**\n * Read file content\n */\nexport async function readFile(filePath: string): Promise<string> {\n return fs.readFile(filePath, 'utf-8');\n}\n\n/**\n * Copy a file\n */\nexport async function copyFile(src: string, dest: string): Promise<void> {\n await fs.ensureDir(path.dirname(dest));\n await fs.copyFile(src, dest);\n}\n\n/**\n * Copy a directory recursively\n */\nexport async function copyDir(src: string, dest: string): Promise<void> {\n await fs.copy(src, dest);\n}\n\n/**\n * Get the current working directory\n */\nexport function getCwd(): string {\n return process.cwd();\n}\n\n/**\n * Resolve a path relative to cwd\n */\nexport function resolvePath(...paths: string[]): string {\n return path.resolve(getCwd(), ...paths);\n}\n\n/**\n * Check if current directory is an elsapiens project\n */\nexport async function isElSapiensProject(dir: string = getCwd()): Promise<boolean> {\n const packageJsonPath = path.join(dir, 'package.json');\n\n if (!(await fileExists(packageJsonPath))) {\n return false;\n }\n\n try {\n const content = await readFile(packageJsonPath);\n const pkg = JSON.parse(content);\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n\n // Check for any @elsapiens package\n return Object.keys(deps).some((dep) => dep.startsWith('@elsapiens/'));\n } catch {\n return false;\n }\n}\n\n/**\n * Find the pages directory in a project\n */\nexport async function findPagesDir(dir: string = getCwd()): Promise<string | null> {\n const candidates = [\n path.join(dir, 'src', 'pages'),\n path.join(dir, 'src', 'app'),\n path.join(dir, 'pages'),\n ];\n\n for (const candidate of candidates) {\n if (await directoryExists(candidate)) {\n return candidate;\n }\n }\n\n return null;\n}\n\n/**\n * Find the components directory in a project\n */\nexport async function findComponentsDir(\n dir: string = getCwd()\n): Promise<string | null> {\n const candidates = [\n path.join(dir, 'src', 'components'),\n path.join(dir, 'components'),\n ];\n\n for (const candidate of candidates) {\n if (await directoryExists(candidate)) {\n return candidate;\n }\n }\n\n return null;\n}\n\n/**\n * Convert a string to PascalCase\n */\nexport function toPascalCase(str: string): string {\n return str\n .split(/[-_\\s]+/)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join('');\n}\n\n/**\n * Convert a string to kebab-case\n */\nexport function toKebabCase(str: string): string {\n return str\n .replace(/([a-z])([A-Z])/g, '$1-$2')\n .replace(/[\\s_]+/g, '-')\n .toLowerCase();\n}\n\n/**\n * Convert a string to a valid route path\n */\nexport function toRoutePath(str: string): string {\n return '/' + toKebabCase(str);\n}\n","import * as p from '@clack/prompts';\nimport pc from 'picocolors';\n\n/**\n * Show intro banner\n */\nexport function intro(message: string): void {\n p.intro(pc.bgCyan(pc.black(` ${message} `)));\n}\n\n/**\n * Show outro message\n */\nexport function outro(message: string): void {\n p.outro(pc.green(message));\n}\n\n/**\n * Show a cancel message and exit\n */\nexport function cancel(message: string = 'Operation cancelled.'): never {\n p.cancel(message);\n process.exit(0);\n}\n\n/**\n * Check if the user cancelled the prompt\n */\nexport function isCancel(value: unknown): value is symbol {\n return p.isCancel(value);\n}\n\n/**\n * Handle cancel - exit if cancelled, return value otherwise\n */\nexport function handleCancel<T>(value: T | symbol): T {\n if (isCancel(value)) {\n cancel();\n }\n return value as T;\n}\n\n/**\n * Ask for text input\n */\nexport async function text(options: {\n message: string;\n placeholder?: string;\n initialValue?: string;\n validate?: (value: string) => string | void;\n}): Promise<string> {\n const result = await p.text(options);\n return handleCancel(result);\n}\n\n/**\n * Ask for a selection from options\n */\nexport async function select<T extends string>(options: {\n message: string;\n options: { value: T; label: string; hint?: string }[];\n initialValue?: T;\n}): Promise<T> {\n const result = await p.select(options);\n return handleCancel(result) as T;\n}\n\n/**\n * Ask for multiple selections\n */\nexport async function multiselect<T extends string>(options: {\n message: string;\n options: { value: T; label: string; hint?: string }[];\n required?: boolean;\n}): Promise<T[]> {\n const result = await p.multiselect(options);\n return handleCancel(result) as T[];\n}\n\n/**\n * Ask for confirmation\n */\nexport async function confirm(options: {\n message: string;\n initialValue?: boolean;\n}): Promise<boolean> {\n const result = await p.confirm(options);\n return handleCancel(result);\n}\n\n/**\n * Show a spinner during async operation\n */\nexport function spinner(): {\n start: (message?: string) => void;\n stop: (message?: string, code?: number) => void;\n message: (message?: string) => void;\n} {\n return p.spinner();\n}\n\n/**\n * Show a group of tasks\n */\nexport async function tasks(\n items: { title: string; task: () => Promise<string> }[]\n): Promise<void> {\n await p.tasks(items);\n}\n\n/**\n * Log a note/info message\n */\nexport function note(message: string, title?: string): void {\n p.note(message, title);\n}\n\n/**\n * Log a message during prompts\n */\nexport function log(options: { message?: string; symbol?: string }): void {\n p.log.message(options.message ?? '', { symbol: options.symbol });\n}\n","import ejs from 'ejs';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport { readFile } from './file.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n// Templates are in dist/templates when bundled (same level as index.js)\nconst TEMPLATES_DIR = path.resolve(__dirname, 'templates');\n\nexport interface TemplateData {\n [key: string]: unknown;\n}\n\n/**\n * Get the path to a template file\n */\nexport function getTemplatePath(category: string, name: string): string {\n return path.join(TEMPLATES_DIR, category, `${name}.ejs`);\n}\n\n/**\n * Render an EJS template with the given data\n */\nexport async function renderTemplate(\n templatePath: string,\n data: TemplateData\n): Promise<string> {\n const template = await readFile(templatePath);\n return ejs.render(template, data, {\n async: false,\n });\n}\n\n/**\n * Render a named template from the templates directory\n */\nexport async function render(\n category: string,\n name: string,\n data: TemplateData\n): Promise<string> {\n const templatePath = getTemplatePath(category, name);\n return renderTemplate(templatePath, data);\n}\n\n/**\n * Render a page template\n */\nexport async function renderPage(\n templateName: string,\n data: {\n name: string;\n pascalName: string;\n title: string;\n description: string;\n [key: string]: unknown;\n }\n): Promise<string> {\n return render('pages', templateName, data);\n}\n\n/**\n * Render a component template\n */\nexport async function renderComponent(\n templateName: string,\n data: {\n name: string;\n pascalName: string;\n [key: string]: unknown;\n }\n): Promise<string> {\n return render('components', templateName, data);\n}\n\n/**\n * Render an app template\n */\nexport async function renderApp(\n templateName: string,\n data: {\n projectName: string;\n [key: string]: unknown;\n }\n): Promise<string> {\n return render('app', templateName, data);\n}\n","import pc from 'picocolors';\n\nexport const logger = {\n info: (message: string) => {\n console.log(pc.blue('ℹ'), message);\n },\n\n success: (message: string) => {\n console.log(pc.green('✓'), message);\n },\n\n warn: (message: string) => {\n console.log(pc.yellow('⚠'), message);\n },\n\n error: (message: string) => {\n console.log(pc.red('✗'), message);\n },\n\n log: (message: string) => {\n console.log(message);\n },\n\n blank: () => {\n console.log();\n },\n\n title: (message: string) => {\n console.log();\n console.log(pc.bold(pc.cyan(message)));\n },\n\n step: (message: string) => {\n console.log(pc.dim(' -'), message);\n },\n\n code: (code: string) => {\n console.log(pc.dim(' ') + pc.cyan(code));\n },\n\n box: (message: string) => {\n const line = '─'.repeat(message.length + 2);\n console.log(pc.dim(`┌${line}┐`));\n console.log(pc.dim('│ ') + pc.bold(message) + pc.dim(' │'));\n console.log(pc.dim(`└${line}┘`));\n },\n};\n\nexport default logger;\n","/**\n * Add Page Command Module\n *\n * This module provides the `add page` command for creating new page components\n * in an existing elSapiens project. It supports multiple page templates and\n * generates the necessary routing code.\n *\n * @module commands/add/page\n */\n\nimport path from 'path';\nimport {\n fileExists,\n findPagesDir,\n isElSapiensProject,\n writeFile,\n resolvePath,\n toPascalCase,\n toKebabCase,\n toRoutePath,\n getCwd,\n} from '../../utils/file.js';\nimport {\n intro,\n outro,\n text,\n select,\n note,\n cancel,\n} from '../../utils/prompt.js';\nimport { renderPage } from '../../utils/template.js';\nimport { logger } from '../../utils/logger.js';\n\n/**\n * Options for the page command.\n *\n * @interface PageOptions\n * @property {('dashboard' | 'list' | 'settings')} template - The page template to use\n * @property {string} [path] - Optional custom path for the pages directory\n * @property {boolean} [yes] - Skip prompts and use defaults\n */\ninterface PageOptions {\n template: 'dashboard' | 'list' | 'settings';\n path?: string;\n yes?: boolean;\n}\n\n/**\n * Creates a new page component in an elSapiens project.\n *\n * This command generates a page file based on the selected template and provides\n * instructions for integrating it into the application's routing configuration.\n *\n * Available templates:\n * - `dashboard` - Overview page with stats, charts, and activity table\n * - `list` - Data listing page with search, filters, and table\n * - `settings` - Configuration page with form sections\n *\n * The command will:\n * 1. Verify the current directory is an elSapiens project\n * 2. Prompt for page name if not provided\n * 3. Allow template selection\n * 4. Prompt for page title and description\n * 5. Generate the page file in the pages directory\n * 6. Display routing instructions for App.tsx integration\n *\n * @param pageName - The name of the page to create. Should be in PascalCase or\n * will be converted. If not provided, user will be prompted.\n * @param options - Configuration options for page generation\n * @param options.template - The page template to use ('dashboard', 'list', or 'settings')\n * @param options.path - Custom path for the pages directory (defaults to auto-detected)\n * @returns A promise that resolves when the page is created successfully\n *\n * @example\n * // Create a dashboard page named 'Analytics'\n * await pageCommand('Analytics', { template: 'dashboard' });\n *\n * @example\n * // Create a list page with custom path\n * await pageCommand('Users', { template: 'list', path: './src/views' });\n *\n * @example\n * // Interactive mode (no page name provided)\n * await pageCommand(undefined, { template: 'settings' });\n *\n * @throws Will exit with code 1 if page creation fails\n * @throws Will cancel if not in an elSapiens project directory\n * @throws Will cancel if the page file already exists\n */\nexport async function pageCommand(\n pageName: string | undefined,\n options: PageOptions\n): Promise<void> {\n intro('Add Page');\n\n // Check if we're in an elsapiens project\n const isProject = await isElSapiensProject();\n if (!isProject) {\n logger.warn('This does not appear to be an elSapiens project.');\n logger.info('Run \"el init\" to create a new project first.');\n cancel();\n }\n\n // Get page name\n let name = pageName;\n if (!name && !options.yes) {\n name = await text({\n message: 'Page name:',\n placeholder: 'Users',\n validate: (value) => {\n if (!value) return 'Page name is required';\n if (!/^[a-zA-Z][a-zA-Z0-9]*$/.test(value)) {\n return 'Page name must start with a letter and contain only letters and numbers';\n }\n },\n });\n }\n\n if (!name) {\n logger.error('Page name is required');\n process.exit(1);\n }\n\n const pascalName = toPascalCase(name);\n const kebabName = toKebabCase(name);\n const routePath = toRoutePath(name);\n\n // Get template\n let template = options.template;\n if (!options.yes) {\n template = await select({\n message: 'Select a template:',\n options: [\n {\n value: 'dashboard',\n label: 'Dashboard',\n hint: 'Overview page with stats, charts, and activity table',\n },\n {\n value: 'list',\n label: 'List',\n hint: 'Data listing with search, filters, and table',\n },\n {\n value: 'settings',\n label: 'Settings',\n hint: 'Configuration page with form sections',\n },\n ],\n initialValue: options.template,\n });\n }\n\n // Get page title\n let title = pascalName;\n if (!options.yes) {\n title = await text({\n message: 'Page title:',\n initialValue: pascalName,\n });\n }\n\n // Get page description\n let description = `Manage ${kebabName.replace(/-/g, ' ')}`;\n if (!options.yes) {\n description = await text({\n message: 'Page description:',\n placeholder: 'Manage your data',\n initialValue: description,\n });\n }\n\n // Get additional options for list template\n let icon = 'Package';\n let singularTitle = pascalName.endsWith('s') ? pascalName.slice(0, -1) : pascalName;\n\n if (template === 'list' && !options.yes) {\n icon = await text({\n message: 'Icon name (from lucide-react):',\n placeholder: 'Package',\n initialValue: icon,\n });\n\n singularTitle = await text({\n message: 'Singular title (for \"Add Item\" button):',\n placeholder: singularTitle,\n initialValue: singularTitle,\n });\n }\n\n // Find pages directory\n let pagesDir = options.path ? resolvePath(options.path) : null;\n if (!pagesDir) {\n pagesDir = await findPagesDir();\n if (!pagesDir) {\n pagesDir = resolvePath('src', 'pages');\n }\n }\n\n const filePath = path.join(pagesDir, `${pascalName}.tsx`);\n\n // Check if file exists\n if (await fileExists(filePath)) {\n logger.error(`File already exists: ${filePath}`);\n cancel();\n }\n\n try {\n // Render template\n const content = await renderPage(template, {\n name,\n pascalName,\n kebabName,\n title,\n description,\n routePath,\n icon,\n singularTitle,\n });\n\n // Write file\n await writeFile(filePath, content);\n\n logger.success(`Created ${path.relative(getCwd(), filePath)}`);\n\n // Show routing instructions\n note(\n `Add this route to your App.tsx:\n\nimport ${pascalName} from './pages/${pascalName}';\n\n<Route path=\"${routePath}\" element={<${pascalName} />} />\n\nAnd add to navigation:\n{ id: '${kebabName}', path: '${routePath}', label: '${title}', icon: <Icon /> }`,\n 'Next steps'\n );\n\n outro('Page created!');\n } catch (error) {\n logger.error(\n error instanceof Error ? error.message : 'Failed to create page'\n );\n process.exit(1);\n }\n}\n","/**\n * Add Component Command Module\n *\n * This module provides the `add component` command for creating new React components\n * in an existing elSapiens project. It supports simple and stateful component templates.\n *\n * @module commands/add/component\n */\n\nimport path from 'path';\nimport {\n fileExists,\n findComponentsDir,\n isElSapiensProject,\n writeFile,\n resolvePath,\n toPascalCase,\n getCwd,\n} from '../../utils/file.js';\nimport { intro, outro, text, select, note, cancel } from '../../utils/prompt.js';\nimport { renderComponent } from '../../utils/template.js';\nimport { logger } from '../../utils/logger.js';\n\n/**\n * Options for the component command.\n *\n * @interface ComponentOptions\n * @property {('simple' | 'stateful')} template - The component template to use\n * @property {string} [path] - Optional custom path for the components directory\n */\ninterface ComponentOptions {\n template: 'simple' | 'stateful';\n path?: string;\n}\n\n/**\n * Creates a new React component in an elSapiens project.\n *\n * This command generates a component file based on the selected template and\n * provides usage instructions for importing and using the component.\n *\n * Available templates:\n * - `simple` - Basic functional component with props and className support\n * - `stateful` - Component with useState hook and onChange callback pattern\n *\n * The command will:\n * 1. Verify the current directory is an elSapiens project\n * 2. Prompt for component name if not provided\n * 3. Allow template selection (simple or stateful)\n * 4. Generate the component file in the components directory\n * 5. Display usage instructions for importing the component\n *\n * @param componentName - The name of the component to create. Should be in PascalCase\n * or will be converted. If not provided, user will be prompted.\n * @param options - Configuration options for component generation\n * @param options.template - The component template to use ('simple' or 'stateful')\n * @param options.path - Custom path for the components directory (defaults to auto-detected)\n * @returns A promise that resolves when the component is created successfully\n *\n * @example\n * // Create a simple component named 'UserCard'\n * await componentCommand('UserCard', { template: 'simple' });\n *\n * @example\n * // Create a stateful component with custom path\n * await componentCommand('Counter', { template: 'stateful', path: './src/ui' });\n *\n * @example\n * // Interactive mode (no component name provided)\n * await componentCommand(undefined, { template: 'simple' });\n *\n * @throws Will exit with code 1 if component creation fails\n * @throws Will cancel if not in an elSapiens project directory\n * @throws Will cancel if the component file already exists\n */\nexport async function componentCommand(\n componentName: string | undefined,\n options: ComponentOptions\n): Promise<void> {\n intro('Add Component');\n\n // Check if we're in an elsapiens project\n const isProject = await isElSapiensProject();\n if (!isProject) {\n logger.warn('This does not appear to be an elSapiens project.');\n logger.info('Run \"el init\" to create a new project first.');\n cancel();\n }\n\n // Get component name\n let name = componentName;\n if (!name) {\n name = await text({\n message: 'Component name:',\n placeholder: 'UserCard',\n validate: (value) => {\n if (!value) return 'Component name is required';\n if (!/^[a-zA-Z][a-zA-Z0-9]*$/.test(value)) {\n return 'Component name must start with a letter and contain only letters and numbers';\n }\n },\n });\n }\n\n const pascalName = toPascalCase(name);\n\n // Get template\n const template = await select({\n message: 'Select a template:',\n options: [\n {\n value: 'simple',\n label: 'Simple',\n hint: 'Basic component with props and className',\n },\n {\n value: 'stateful',\n label: 'Stateful',\n hint: 'Component with useState and onChange callback',\n },\n ],\n initialValue: options.template,\n });\n\n // Find components directory\n let componentsDir = options.path ? resolvePath(options.path) : null;\n if (!componentsDir) {\n componentsDir = await findComponentsDir();\n if (!componentsDir) {\n componentsDir = resolvePath('src', 'components');\n }\n }\n\n const filePath = path.join(componentsDir, `${pascalName}.tsx`);\n\n // Check if file exists\n if (await fileExists(filePath)) {\n logger.error(`File already exists: ${filePath}`);\n cancel();\n }\n\n try {\n // Render template\n const content = await renderComponent(template, {\n name,\n pascalName,\n });\n\n // Write file\n await writeFile(filePath, content);\n\n logger.success(`Created ${path.relative(getCwd(), filePath)}`);\n\n // Show usage instructions\n note(\n `Import and use your component:\n\nimport { ${pascalName} } from './components/${pascalName}';\n\n<${pascalName} className=\"...\" />`,\n 'Usage'\n );\n\n outro('Component created!');\n } catch (error) {\n logger.error(\n error instanceof Error ? error.message : 'Failed to create component'\n );\n process.exit(1);\n }\n}\n","import { pageCommand } from './page.js';\nimport { componentCommand } from './component.js';\n\nexport const addCommand = {\n page: pageCommand,\n component: componentCommand,\n};\n","/**\n * elSapiens CLI Entry Point\n *\n * This module serves as the main entry point for the elSapiens CLI application.\n * It initializes and starts the command-line interface by creating and parsing\n * the CLI instance.\n *\n * @module cli\n *\n * @example\n * // Running the CLI from the command line:\n * npx el init my-project\n * npx el add page Users\n * npx el add component UserCard\n */\n\nimport { createCli } from './cli.js';\n\n/**\n * Creates the CLI instance and parses command-line arguments.\n *\n * The CLI supports the following commands:\n * - `init [name]` - Initialize a new elSapiens project\n * - `add page [name]` - Add a new page to an existing project\n * - `add component [name]` - Add a new component to an existing project\n *\n * @example\n * // The CLI is automatically invoked when running the package:\n * // npx el init my-app --template full --git\n */\nconst cli = createCli();\ncli.parse();\n"],"mappings":"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","names":["path","intro","outro","cancel","isCancel","text","select","confirm","spinner","note","path","path","pc","intro","text","confirm","cancel","spinner","path","note","outro","path","intro","cancel","text","select","path","note","outro","path","intro","cancel","text","select","path","note","outro"]}
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
# API Configuration
|
|
2
|
+
VITE_API_URL=https://api.example.com
|
|
3
|
+
VITE_HTTPS_PORT=<%= httpsPort %>
|
|
4
|
+
VITE_GRPC_PORT=<%= grpcPort %>
|
|
5
|
+
VITE_REST_PORT=<%= restPort %>
|
|
6
|
+
|
|
1
7
|
# Authentication
|
|
2
8
|
VITE_AUTH_URL=https://auth.example.com
|
|
3
9
|
VITE_ROOT_DOMAIN=example.com
|
|
10
|
+
|
|
11
|
+
# Feature Flags
|
|
12
|
+
VITE_ENABLE_GRPC=true
|
|
13
|
+
VITE_ENABLE_REST=true
|