@cellajs/create-cella 0.0.16 → 0.0.18

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 CHANGED
@@ -3,6 +3,7 @@
3
3
  // src/index.ts
4
4
  import { basename as basename2, resolve as resolve2 } from "node:path";
5
5
  import { existsSync as existsSync2 } from "node:fs";
6
+ import colors3 from "picocolors";
6
7
  import { input, confirm, select } from "@inquirer/prompts";
7
8
 
8
9
  // src/cli.ts
@@ -12,7 +13,7 @@ import { Command, InvalidArgumentError } from "commander";
12
13
  // package.json
13
14
  var package_default = {
14
15
  name: "@cellajs/create-cella",
15
- version: "0.0.16",
16
+ version: "0.0.18",
16
17
  private: false,
17
18
  license: "MIT",
18
19
  description: "Cella is a TypeScript template to create web apps with sync and offline capabilities.",
@@ -61,9 +62,11 @@ var package_default = {
61
62
  var NAME = "create-cella";
62
63
  var TEMPLATE_URL = "github:cellajs/cella";
63
64
  var CELLA_REMOTE_URL = "git@github.com:cellajs/cella.git";
65
+ var DESCRIPTION = package_default.description;
64
66
  var VERSION = package_default.version;
65
67
  var AUTHOR = package_default.author;
66
68
  var WEBSITE = package_default.homepage;
69
+ var GITHUB = package_default.repository.url;
67
70
  var TO_REMOVE = [
68
71
  "info",
69
72
  "./cli/create-cella"
@@ -77,7 +80,7 @@ var TO_COPY = {
77
80
  "./tus/.env.example": "./tus/.env",
78
81
  "./info/QUICKSTART.md": "README.md"
79
82
  };
80
- var CELLA_TITLE = `
83
+ var LOGO = `
81
84
  _ _
82
85
  \u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2593\u2592 ___ ___| | | __ _
83
86
  \u2592\u2593\u2588 \u2588\u2593\u2592 / __/ _ \\ | |/ _\` |
@@ -465,27 +468,32 @@ async function create({
465
468
  console.info(`${colors2.green("Success")} Created ${projectName} at ${targetFolder}`);
466
469
  console.info();
467
470
  const needsCd = originalCwd !== targetFolder;
471
+ const relativePath = relative(originalCwd, targetFolder);
468
472
  if (needsCd) {
469
- const relativePath = relative(originalCwd, targetFolder);
470
473
  console.info("now go to your project using:");
471
474
  console.info(colors2.cyan(` cd ${relativePath}`));
472
475
  console.info();
473
476
  }
474
- console.info(`${needsCd ? "then " : ""}quick start with:`);
477
+ console.info(`${needsCd ? "then " : ""}quick start using pglite with:`);
475
478
  console.info(colors2.cyan(` ${packageManager2} quick`));
476
479
  console.info();
477
- console.info("Check out the readme to get started: /README.md");
480
+ console.info("Already have docker installed? Then you can have a full setup with:");
481
+ console.info(colors2.cyan(` ${packageManager2} docker`));
482
+ console.info(colors2.cyan(` ${packageManager2} dev`));
483
+ console.info(colors2.cyan(` ${packageManager2} seed`));
484
+ console.info(`For more info, check out: ${relativePath}/README.md`);
478
485
  console.info(`Enjoy building ${projectName} using cella! \u{1F389}`);
479
486
  console.info();
480
487
  }
481
488
 
482
489
  // src/index.ts
483
490
  async function main() {
484
- console.info(CELLA_TITLE);
491
+ console.info(LOGO);
485
492
  console.info();
486
- console.info(`Cella CLI: ${VERSION}`);
487
- console.info(`Created by: ${AUTHOR}`);
488
- console.info(`Website: ${WEBSITE}`);
493
+ console.info(DESCRIPTION);
494
+ console.info(`Version ${colors3.green(VERSION)}`);
495
+ console.info(`Created by ${AUTHOR}`);
496
+ console.info(`${GITHUB} | ${WEBSITE}`);
489
497
  console.info();
490
498
  if (cli.options.skipNewBranch || cli.options.skipGit) {
491
499
  cli.createNewBranch = false;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/cli.ts","../package.json","../src/constants.ts","../src/utils/validate-project-name.ts","../src/utils/is-empty-directory.ts","../src/create.ts","../src/utils/run-package-manager-command.ts","../src/utils/clean-template.ts","../src/utils/run-git-command.ts","../src/add-remote.ts"],"sourcesContent":["#!/usr/bin/env tsx\n\nimport { basename, resolve } from 'node:path';\nimport { existsSync } from 'node:fs';\n\nimport { input, confirm, select } from '@inquirer/prompts';\n\nimport { cli } from './cli';\nimport { validateProjectName } from './utils/validate-project-name.ts';\nimport { isEmptyDirectory } from './utils/is-empty-directory.ts';\nimport { create } from './create.ts';\nimport { CELLA_TITLE, VERSION, WEBSITE, AUTHOR } from './constants.ts';\n\ninterface CreateOptions {\n projectName: string;\n targetFolder: string;\n newBranchName?: string | null;\n skipInstall: boolean;\n skipGit: boolean;\n skipClean: boolean;\n skipGenerate: boolean;\n packageManager: string;\n}\n\nasync function main(): Promise<void> {\n console.info(CELLA_TITLE);\n\n // Display CLI version and created by information\n console.info();\n console.info(`Cella CLI: ${VERSION}`);\n console.info(`Created by: ${AUTHOR}`);\n console.info(`Website: ${WEBSITE}`);\n console.info();\n\n // Skip creating a new branch if --skipNewBranch flag is provided or git is skipped\n if (cli.options.skipNewBranch || cli.options.skipGit) {\n cli.createNewBranch = false;\n cli.newBranchName = null;\n }\n\n // Skip generating sql files if --skipGenerate flag is provided\n if (cli.options.skipGenerate === true) {\n cli.options.skipGenerate = true;\n }\n\n // Skip installing packages if --skipInstall flag is provided\n if (cli.options.skipInstall === true) {\n cli.options.skipInstall = true;\n }\n\n // Skip cleaning the template if --skipClean flag is provided\n if (cli.options.skipClean === true) {\n cli.options.skipClean = true;\n }\n\n // Skip initializing git if --skipGit flag is provided\n if (cli.options.skipGit === true) {\n cli.options.skipGit = true;\n }\n\n // Prompt for project name if not provided\n if (!cli.directory) {\n cli.directory = await input({\n message: 'Enter your project name',\n default: 'my-cella-app',\n validate: (name) => {\n const validation = validateProjectName(basename(resolve(name)));\n return validation.valid ? true : `Invalid project name: ${validation.problems[0]}`;\n },\n });\n }\n\n // Prompt to create a new branch besides the main branch (if not skipped)\n if (cli.createNewBranch === null) {\n cli.createNewBranch = await confirm({\n message: 'Would you like to create a new branch (besides \"main\")?',\n default: true,\n });\n }\n\n // Prompt for new branch name, only if user opted to create a new branch\n if (!cli.newBranchName && cli.createNewBranch) {\n cli.newBranchName = await input({\n message: 'Enter the new branch name',\n default: 'development',\n validate: (name) => {\n const validation = validateProjectName(basename(resolve(name)));\n return validation.valid ? true : `Invalid branch name: ${validation.problems[0]}`;\n },\n });\n }\n\n const targetFolder = resolve(cli.directory);\n const projectName = basename(targetFolder);\n\n // Check if the target folder exists and is not empty\n if (existsSync(targetFolder) && !(await isEmptyDirectory(targetFolder))) {\n const dirName = cli.directory === '.' ? 'Current directory' : `Target directory \"${targetFolder}\"`;\n const message = `${dirName} is not empty. Please choose how you would like to proceed:`;\n\n const action = await select({\n message,\n choices: [\n { name: 'Cancel and exit', value: 'cancel' },\n { name: 'Ignore existing files and continue', value: 'ignore' },\n ],\n });\n\n if (action === 'cancel') {\n process.exit(1);\n }\n }\n\n // Proceed with the project creation\n const createOptions: CreateOptions = {\n projectName,\n targetFolder,\n newBranchName: cli.newBranchName,\n skipInstall: cli.options.skipInstall,\n skipGit: cli.options.skipGit,\n skipClean: cli.options.skipClean,\n skipGenerate: cli.options.skipGenerate,\n packageManager: cli.packageManager,\n };\n\n await create(createOptions);\n}\n\nmain().catch(console.error);\n","import { basename, resolve } from 'node:path';\nimport { Command, InvalidArgumentError } from 'commander';\n\nimport { NAME, VERSION } from './constants.ts';\nimport { validateProjectName } from './utils/validate-project-name.ts';\n\n// Define types for CLI options\ninterface CLIOptions {\n skipNewBranch: boolean;\n skipClean: boolean;\n skipGit: boolean;\n skipInstall: boolean;\n skipGenerate: boolean;\n newBranchName?: string;\n}\n\n// Define CLI configuration\ninterface CLIConfig {\n options: CLIOptions;\n args: string[];\n directory: string | null;\n newBranchName: string | null;\n createNewBranch: boolean | null;\n packageManager: string;\n}\n\n// Initialize CLI variables\nlet directory: string | null = null;\nlet newBranchName: string | null = null;\nlet createNewBranch: boolean | null = null;\nconst packageManager = 'pnpm';\n\n// Set up the CLI command using Commander\nexport const command = new Command(NAME)\n .version(\n VERSION,\n '-v, --version',\n `Output the current version of ${NAME}.`\n )\n .argument('[directory]', 'The directory name for the new project.')\n .usage('[directory] [options]')\n .helpOption('-h, --help', 'Display this help message.')\n .option('--skip-new-branch', 'Skip creating a new branch during initialization.', false)\n .option('--skip-install', 'Skip the installation of packages.', false)\n .option('--skip-generate', 'Skip generating SQL files.', false)\n .option('--skip-clean', 'Skip cleaning the `cella` template.', false)\n .option('--skip-git', 'Skip initializing a git repository.', false)\n .option(\n '--new-branch-name <name>',\n 'Specify a new branch name to create and use.',\n (name: string) => {\n if (typeof name === 'string') {\n name = name.trim();\n }\n\n if (name) {\n const validation = validateProjectName(basename(resolve(name)));\n\n if (!validation.valid) {\n throw new InvalidArgumentError(\n `Invalid branch name: ${validation.problems[0]}`\n );\n }\n \n createNewBranch = true;\n newBranchName = name;\n }\n }\n )\n .action((name: string) => {\n if (typeof name === 'string') {\n name = name.trim();\n }\n\n if (name) {\n const validation = validateProjectName(basename(resolve(name)));\n\n if (!validation.valid) {\n throw new InvalidArgumentError(\n `Invalid project name: ${validation.problems[0]}`\n );\n }\n\n directory = name;\n }\n })\n .parse();\n\n// Gather the CLI options and arguments\nconst options: CLIOptions = command.opts<CLIOptions>({\n skipNewBranch: false,\n skipClean: false,\n skipGit: false,\n skipInstall: false,\n skipGenerate: false,\n});\n\n// Export the CLI configuration for use in other modules\nexport const cli: CLIConfig = {\n options,\n args: command.args,\n directory,\n newBranchName,\n createNewBranch,\n packageManager,\n};\n","{\n \"name\": \"@cellajs/create-cella\",\n \"version\": \"0.0.16\",\n \"private\": false,\n \"license\": \"MIT\",\n \"description\": \"Cella is a TypeScript template to create web apps with sync and offline capabilities.\",\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/cellajs/cella\",\n \"directory\": \"cli/create-cella\"\n },\n \"homepage\": \"https://cellajs.com\",\n \"author\": \"CellaJS <info@cellajs.com>\",\n \"engines\": {\n \"node\": \">=20.14.0\"\n },\n \"type\": \"module\",\n \"main\": \"./src/index.ts\",\n \"bin\": {\n \"create-cella\": \"index.js\"\n },\n \"scripts\": {\n \"start\": \"tsx ./src/index.ts\",\n \"clean\": \"rimraf ./dist\",\n \"build\": \"tsup\",\n \"test-build\": \"pnpm run build && node index.js\",\n \"prepublishOnly\": \"pnpm run build\"\n },\n \"packageManager\": \"pnpm@9.11.0\",\n \"dependencies\": {\n \"@inquirer/prompts\": \"^6.0.1\",\n \"commander\": \"^12.1.0\",\n \"cross-spawn\": \"^7.0.3\",\n \"giget\": \"^1.2.3\",\n \"picocolors\": \"^1.1.0\",\n \"validate-npm-package-name\": \"^5.0.1\",\n \"yocto-spinner\": \"^0.1.0\"\n },\n \"devDependencies\": {\n \"tsup\": \"^8.3.5\",\n \"tsx\": \"^4.19.2\"\n }\n}\n","export const NAME = 'create-cella';\n\n// URL of the template repository\nexport const TEMPLATE_URL = 'github:cellajs/cella';\n\n// URL to the Cella repository\nexport const CELLA_REMOTE_URL: string = 'git@github.com:cellajs/cella.git';\n\n// Import package.json dynamically for version and website information\nimport packageJson from '../package.json' assert { type: 'json' };\n\n// Export version, website, and author from package.json\nexport const VERSION: string = packageJson.version;\nexport const AUTHOR: string = packageJson.author;\nexport const WEBSITE: string = packageJson.homepage;\n\n// Files or folders to be removed from the template after downloading\nexport const TO_REMOVE: string[] = [\n 'info',\n './cli/create-cella',\n];\n\n// Specific folder contents to be cleaned out from the template\nexport const TO_CLEAN: string[] = [\n './backend/drizzle',\n];\n\n// Files to copy/paste after downloading\nexport const TO_COPY: Record<string, string> = {\n './backend/.env.example': './backend/.env',\n './frontend/.env.example': './frontend/.env',\n './tus/.env.example': './tus/.env',\n './info/QUICKSTART.md': 'README.md',\n};\n\n// ASCII title for the CLI output\nexport const CELLA_TITLE = `\n _ _ \n ▒▓█████▓▒ ___ ___| | | __ _\n ▒▓█ █▓▒ / __/ _ \\\\ | |/ _\\` |\n ▒▓█ █▓▒ | (_| __/ | | (_| |\n ▒▓█████▓▒ \\\\___\\\\___|_|_|\\\\__,_|\n`;\n","import validate from 'validate-npm-package-name';\n\ninterface ValidationResult {\n valid: boolean;\n problems?: string[];\n}\n\nexport function validateProjectName(name: string): ValidationResult {\n const nameValidation = validate(name);\n\n if (nameValidation.validForNewPackages) {\n return { valid: true };\n }\n\n return {\n valid: false,\n problems: [\n ...(nameValidation.errors || []),\n ...(nameValidation.warnings || []),\n ],\n };\n}\n","import { readdir } from 'node:fs/promises';\n\n/**\n * Checks if a directory is empty or only contains a .git directory.\n * \n * @param path - The path of the directory to check.\n * @returns Resolves to true if the directory is empty or contains only a .git folder, false otherwise.\n * @throws Throws an error if the path is not a directory or if there's an issue reading the directory.\n */\nexport async function isEmptyDirectory(path: string): Promise<boolean> {\n const files = await readdir(path);\n\n // Check if directory is empty or contains only the .git directory\n return files.length === 0 || (files.length === 1 && files[0] === '.git');\n}\n","import { mkdir } from 'node:fs/promises';\nimport { existsSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport colors from 'picocolors';\nimport { downloadTemplate } from 'giget';\nimport yoctoSpinner from 'yocto-spinner';\n\nimport { TEMPLATE_URL } from './constants.ts';\n\nimport { install, generate } from './utils/run-package-manager-command.ts';\nimport { cleanTemplate } from './utils/clean-template.ts';\nimport { runGitCommand } from './utils/run-git-command.ts';\nimport { addRemote } from './add-remote.ts';\n\ninterface CreateOptions {\n projectName: string;\n targetFolder: string;\n newBranchName?: string | null;\n skipInstall: boolean;\n skipGit: boolean;\n skipClean: boolean;\n skipGenerate: boolean;\n packageManager: string;\n}\n\nexport async function create({\n projectName,\n targetFolder,\n newBranchName,\n skipInstall,\n skipGit,\n skipClean,\n skipGenerate,\n packageManager,\n}: CreateOptions): Promise<void> {\n // Save the original working directory\n const originalCwd = process.cwd();\n\n console.info();\n\n // Create the target folder if it doesn't exist\n const createFolderSpinner = yoctoSpinner({\n text: 'Creating project folder',\n }).start();\n\n await mkdir(targetFolder, { recursive: true });\n process.chdir(targetFolder);\n\n createFolderSpinner.success('Project folder created');\n\n // Download the template from the specified URL\n const downloadSpinner = yoctoSpinner({\n text: 'Downloading `cella` template',\n }).start();\n\n await downloadTemplate(TEMPLATE_URL, {\n cwd: process.cwd(),\n dir: targetFolder,\n force: true,\n provider: 'github',\n });\n\n downloadSpinner.success('`cella` template downloaded');\n\n // Clean the template if the skipClean flag is not set\n if (!skipClean) {\n const cleanSpinner = yoctoSpinner({\n text: 'cleaning `cella` template',\n }).start();\n\n try {\n await cleanTemplate({\n targetFolder,\n projectName,\n });\n cleanSpinner.success('`cella` template cleaned');\n } catch (e) {\n console.error(e);\n cleanSpinner.error('Failed to clean `cella` template');\n process.exit(1);\n }\n } else {\n console.info(`${colors.yellow('⚠')} --skip-clean > Skip cleaning \\`cella\\` template`);\n }\n\n // Install dependencies if the skipInstall flag is not set\n if (!skipInstall) {\n const installSpinner = yoctoSpinner({\n text: 'installing dependencies',\n }).start();\n\n try {\n await install(packageManager);\n installSpinner.success('Dependencies installed');\n } catch (e) {\n console.error(e);\n installSpinner.error('Failed to install dependencies');\n process.exit(1);\n }\n } else {\n console.info(`${colors.yellow('⚠')} --skip-install > Skip installing dependencies`);\n }\n\n // Generate SQL files if the skipGenerate flag is not set\n if (!skipGenerate) {\n const generateSpinner = yoctoSpinner({\n text: 'generating SQL files',\n }).start();\n\n try {\n await generate(packageManager);\n generateSpinner.success('SQL files generated');\n } catch (e) {\n console.error(e);\n generateSpinner.error('Failed to generate SQL files');\n process.exit(1);\n }\n } else {\n console.info(`${colors.yellow('⚠')} --skip-generate > Skip generating SQL files`);\n }\n\n // Initialize Git repository if skipGit flag is not set\n if (!skipGit) {\n const gitSpinner = yoctoSpinner({\n text: 'initializing git repository',\n }).start();\n\n const gitFolderPath = join(targetFolder, '.git');\n\n if (!existsSync(gitFolderPath)) {\n try {\n // Run Git commands to initialize the repository and make the first commit\n await runGitCommand({ targetFolder, command: 'init' });\n await runGitCommand({ targetFolder, command: 'add .' });\n await runGitCommand({ targetFolder, command: 'commit -m \"Initial commit\"' });\n\n // If a new branch name is specified, create and checkout the branch\n if (newBranchName) {\n await runGitCommand({ targetFolder, command: `branch ${newBranchName}` });\n await runGitCommand({ targetFolder, command: `checkout ${newBranchName}` });\n gitSpinner.success(`Git repository initialized, initial commit created, and new branch ${newBranchName} created`);\n } else {\n gitSpinner.success('Git repository initialized and initial commit created');\n }\n } catch (e) {\n console.error(e);\n gitSpinner.error('Failed to initialize Git repository or create branch');\n process.exit(1);\n }\n } else {\n gitSpinner.warning('Git repository already initialized > Skip git init');\n }\n } else {\n console.info(`${colors.yellow('⚠')} --skip-git > Skip git init`);\n }\n\n // Add Cella as upstream remote\n await addRemote({ targetFolder });\n\n // Final success message indicating project creation\n console.info();\n console.info(`${colors.green('Success')} Created ${projectName} at ${targetFolder}`);\n console.info();\n\n // Check if the working directory needs to be changed\n const needsCd = originalCwd !== targetFolder;\n if (needsCd) {\n // Calculate the relative path between the original working directory and the target folder\n const relativePath = relative(originalCwd, targetFolder);\n\n console.info('now go to your project using:');\n console.info(colors.cyan(` cd ${relativePath}`)); // Adding './' to make it clear it's a relative path\n console.info();\n }\n\n console.info(`${needsCd ? 'then ' : ''}quick start with:`);\n console.info(colors.cyan(` ${packageManager} quick`));\n console.info();\n\n console.info('Check out the readme to get started: /README.md');\n console.info(`Enjoy building ${projectName} using cella! 🎉`);\n console.info();\n}\n","import spawn from 'cross-spawn';\n\n/**\n * Executes a command using the specified package manager (e.g., pnpm).\n * \n * @param packageManager - The package manager to use (e.g., 'pnpm').\n * @param args - The arguments to pass to the package manager command.\n * @param env - Additional environment variables to set during command execution.\n * @returns A promise that resolves if the command executes successfully; otherwise, it rejects with an error message.\n */\nexport async function runPackageManagerCommand(\n packageManager: string,\n args: string[],\n env: Record<string, string> = {}\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(packageManager, args, {\n env: {\n ...process.env,\n ...env,\n },\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n // Buffer for capturing stderr and stdout output\n let stderrBuffer = '';\n let stdoutBuffer = '';\n\n // Capture stderr output\n child.stderr?.on('data', (data: Buffer) => {\n stderrBuffer += data.toString();\n });\n\n // Capture stdout output\n child.stdout?.on('data', (data: Buffer) => {\n stdoutBuffer += data.toString();\n });\n\n // Handle process exit\n child.on('close', (code: number | null) => {\n if (code !== 0) {\n reject(\n `\"${packageManager} ${args.join(' ')}\" failed ${stdoutBuffer} ${stderrBuffer}`\n );\n return;\n }\n resolve();\n });\n });\n}\n\n/**\n * Installs dependencies using the specified package manager.\n * \n * @param packageManager - The package manager to use for installation (e.g., 'pnpm').\n * @returns A promise that resolves if the installation completes successfully; otherwise, it rejects with an error.\n */\nexport async function install(packageManager: string): Promise<void> {\n return runPackageManagerCommand(packageManager, ['install'], {\n NODE_ENV: 'development',\n });\n}\n\n/**\n * Generates SQL files using the specified package manager.\n * \n * @param packageManager - The package manager to use for generation (e.g., 'pnpm').\n * @returns A promise that resolves if the generation completes successfully; otherwise, it rejects with an error.\n */\nexport async function generate(packageManager: string): Promise<void> {\n return runPackageManagerCommand(packageManager, ['generate'], {\n NODE_ENV: 'development',\n });\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport colors from 'picocolors';\n\nimport { TO_CLEAN, TO_REMOVE, TO_COPY } from '../constants.ts';\n\n/**\n * Cleans the specified template by removing designated folders and files.\n * @param params - Parameters containing the target folder and project name.\n */\nexport async function cleanTemplate({\n targetFolder,\n projectName,\n}: {\n targetFolder: string;\n projectName: string;\n}): Promise<void> {\n // Change the current working directory to targetFolder if not already set\n if (process.cwd() !== targetFolder) {\n process.chdir(targetFolder);\n }\n\n return new Promise<void>(async (resolve, reject) => {\n try {\n // Copy specified files\n for (const [src, dest] of Object.entries(TO_COPY)) {\n const srcAbsolutePath = path.resolve(targetFolder, src);\n const destAbsolutePath = path.resolve(targetFolder, dest);\n await copyFile(srcAbsolutePath, destAbsolutePath);\n }\n\n // Clean specified folder contents\n await Promise.all(\n TO_CLEAN.map((folderPath) => {\n const absolutePath = path.resolve(targetFolder, folderPath);\n return removeFolderContents(absolutePath);\n })\n );\n\n // Remove specified files and folders\n await Promise.all(\n TO_REMOVE.map((filePath) => {\n const absolutePath = path.resolve(targetFolder, filePath);\n return removeFileOrFolder(absolutePath);\n })\n );\n\n resolve();\n } catch (err) {\n reject(`Error during the cleaning process: ${err}`);\n }\n });\n}\n\n/**\n * Removes all contents within a specified folder.\n * @param folderPath - The path of the folder to clean.\n */\nexport async function removeFolderContents(folderPath: string): Promise<void> {\n // List all files in the folder\n const files = await fs.readdir(folderPath);\n\n await Promise.all(\n files.map(async (file) => {\n const filePath = path.join(folderPath, file);\n\n // Get the file or folder statistics\n const stat = await fs.lstat(filePath);\n\n // If it's a directory, remove it and all its contents\n if (stat.isDirectory()) {\n await fs.rm(filePath, { recursive: true, force: true });\n } else {\n // If it's a file, remove it\n await fs.rm(filePath);\n }\n })\n );\n}\n\n/**\n * Removes a specified file or folder.\n * @param pathToRemove - The path to the file or folder to remove.\n */\nexport async function removeFileOrFolder(pathToRemove: string): Promise<void> {\n await fs.rm(pathToRemove, { recursive: true, force: true });\n}\n\n/**\n * Helper function to copy files if the source exists.\n * @param src - The source file path.\n * @param dest - The destination file path.\n */\nexport async function copyFile(src: string, dest: string): Promise<void> {\n try {\n // Check if the source file exists\n await fs.access(src);\n\n // Ensure the destination directory exists\n await fs.mkdir(path.dirname(dest), { recursive: true });\n\n // Copy the file\n await fs.copyFile(src, dest);\n } catch (err: any) {\n if (err.code === 'ENOENT') {\n console.info(`\\n${colors.yellow('⚠')} Source file \"${src}\" does not exist > Skip copy`);\n } else {\n throw err;\n }\n }\n}\n","import { spawn } from 'node:child_process';\n\ntype GitCommandType = 'merge' | 'diff' | 'other';\n\ninterface RunGitCommandOptions {\n targetFolder: string;\n command: string;\n}\n\n// Helper to determine the type of Git command for custom handling\nfunction getGitCommandType(command: string): GitCommandType {\n if (command.startsWith('merge')) return 'merge';\n if (command.startsWith('diff')) return 'diff';\n return 'other';\n}\n\n// Helper to check if a Git command is successful\nfunction isGitCommandSuccess(gitCommand: GitCommandType, code: number | null, errOutput: string): boolean {\n if (gitCommand === 'merge') return code === 0 || (code === 1 && !errOutput);\n if (gitCommand === 'diff') return code === 0 || (code === 2 && !errOutput);\n return code === 0;\n}\n\n// Function to run a Git command and handle its output\nexport async function runGitCommand({ targetFolder, command }: RunGitCommandOptions): Promise<string> {\n return new Promise((resolve, reject) => {\n const gitCommand = getGitCommandType(command);\n const child = spawn(`git ${command}`, [], { cwd: targetFolder, shell: true, timeout: 60000 });\n\n let output = '';\n let errOutput = '';\n\n child.on('error', (error: Error) => {\n reject(error);\n });\n\n child.on('exit', (code: number | null) => {\n if (isGitCommandSuccess(gitCommand, code, errOutput)) {\n resolve(output.trim());\n } else {\n reject(\n `Git ${gitCommand} command failed with exit code ${code}, stderr: \"${errOutput.trim()}\", stdout: \"${output.trim()}\"`\n );\n }\n });\n\n // Collect stdout data\n child.stdout.on('data', (data: Buffer) => {\n output += data.toString();\n });\n\n // Collect stderr data\n child.stderr.on('data', (data: Buffer) => {\n errOutput += data.toString();\n });\n });\n}\n","import yoctoSpinner from 'yocto-spinner';\nimport { runGitCommand } from './utils/run-git-command.ts';\nimport { CELLA_REMOTE_URL } from './constants.ts';\n\ninterface AddRemoteOptions {\n targetFolder: string;\n remoteUrl?: string; // Optional, defaults to CELLA_REMOTE_URL\n remoteName?: string; // Optional, defaults to 'upstream'\n}\n\nexport async function addRemote({\n targetFolder,\n remoteUrl = CELLA_REMOTE_URL,\n remoteName = 'upstream',\n}: AddRemoteOptions): Promise<void> {\n\n // Spinner for adding remote\n const remoteSpinner = yoctoSpinner({\n text: 'Adding remote',\n }).start();\n\n try {\n // Check if the remote exists\n let remote: string | null = null;\n\n try {\n remote = await runGitCommand({ targetFolder, command: `remote get-url ${remoteName}` });\n } catch (error: any) {\n // If the remote doesn't exist, it throws a fatal error\n remote = null;\n }\n\n // Add or update the remote if it doesn't exist or differs from `remoteUrl`\n if (!remote) {\n await runGitCommand({ targetFolder, command: `remote add ${remoteName} ${remoteUrl}` });\n remoteSpinner.success('Remote added successfully.');\n } else if (remote !== remoteUrl) {\n // Remove existing remote and set the new URL\n await runGitCommand({ targetFolder, command: `remote remove ${remoteName}` });\n await runGitCommand({ targetFolder, command: `remote add ${remoteName} ${remoteUrl}` });\n remoteSpinner.success('Remote updated successfully.');\n } else {\n remoteSpinner.success('Remote is already configured correctly.');\n }\n } catch (error) {\n console.error(error);\n remoteSpinner.error('Failed to add remote.');\n process.exit(1);\n }\n}\n"],"mappings":"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","names":["basename","resolve","existsSync","path","colors","yoctoSpinner","packageManager","resolve","resolve","spawn","command","resolve","newBranchName","packageManager","yoctoSpinner","colors","basename","resolve","existsSync"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/cli.ts","../package.json","../src/constants.ts","../src/utils/validate-project-name.ts","../src/utils/is-empty-directory.ts","../src/create.ts","../src/utils/run-package-manager-command.ts","../src/utils/clean-template.ts","../src/utils/run-git-command.ts","../src/add-remote.ts"],"sourcesContent":["#!/usr/bin/env tsx\n\nimport { basename, resolve } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport colors from 'picocolors';\n\nimport { input, confirm, select } from '@inquirer/prompts';\n\nimport { cli } from './cli';\nimport { validateProjectName } from './utils/validate-project-name.ts';\nimport { isEmptyDirectory } from './utils/is-empty-directory.ts';\nimport { create } from './create.ts';\nimport { LOGO, VERSION, WEBSITE, AUTHOR, GITHUB, DESCRIPTION } from './constants.ts';\n\ninterface CreateOptions {\n projectName: string;\n targetFolder: string;\n newBranchName?: string | null;\n skipInstall: boolean;\n skipGit: boolean;\n skipClean: boolean;\n skipGenerate: boolean;\n packageManager: string;\n}\n\nasync function main(): Promise<void> {\n console.info(LOGO);\n\n // Display CLI version and created by information\n console.info();\n console.info(DESCRIPTION);\n console.info(`Version ${colors.green(VERSION)}`);\n console.info(`Created by ${AUTHOR}`);\n console.info(`${GITHUB} | ${WEBSITE}`);\n console.info();\n\n // Skip creating a new branch if --skipNewBranch flag is provided or git is skipped\n if (cli.options.skipNewBranch || cli.options.skipGit) {\n cli.createNewBranch = false;\n cli.newBranchName = null;\n }\n\n // Skip generating sql files if --skipGenerate flag is provided\n if (cli.options.skipGenerate === true) {\n cli.options.skipGenerate = true;\n }\n\n // Skip installing packages if --skipInstall flag is provided\n if (cli.options.skipInstall === true) {\n cli.options.skipInstall = true;\n }\n\n // Skip cleaning the template if --skipClean flag is provided\n if (cli.options.skipClean === true) {\n cli.options.skipClean = true;\n }\n\n // Skip initializing git if --skipGit flag is provided\n if (cli.options.skipGit === true) {\n cli.options.skipGit = true;\n }\n\n // Prompt for project name if not provided\n if (!cli.directory) {\n cli.directory = await input({\n message: 'Enter your project name',\n default: 'my-cella-app',\n validate: (name) => {\n const validation = validateProjectName(basename(resolve(name)));\n return validation.valid ? true : `Invalid project name: ${validation.problems[0]}`;\n },\n });\n }\n\n // Prompt to create a new branch besides the main branch (if not skipped)\n if (cli.createNewBranch === null) {\n cli.createNewBranch = await confirm({\n message: 'Would you like to create a new branch (besides \"main\")?',\n default: true,\n });\n }\n\n // Prompt for new branch name, only if user opted to create a new branch\n if (!cli.newBranchName && cli.createNewBranch) {\n cli.newBranchName = await input({\n message: 'Enter the new branch name',\n default: 'development',\n validate: (name) => {\n const validation = validateProjectName(basename(resolve(name)));\n return validation.valid ? true : `Invalid branch name: ${validation.problems[0]}`;\n },\n });\n }\n\n const targetFolder = resolve(cli.directory);\n const projectName = basename(targetFolder);\n\n // Check if the target folder exists and is not empty\n if (existsSync(targetFolder) && !(await isEmptyDirectory(targetFolder))) {\n const dirName = cli.directory === '.' ? 'Current directory' : `Target directory \"${targetFolder}\"`;\n const message = `${dirName} is not empty. Please choose how you would like to proceed:`;\n\n const action = await select({\n message,\n choices: [\n { name: 'Cancel and exit', value: 'cancel' },\n { name: 'Ignore existing files and continue', value: 'ignore' },\n ],\n });\n\n if (action === 'cancel') {\n process.exit(1);\n }\n }\n\n // Proceed with the project creation\n const createOptions: CreateOptions = {\n projectName,\n targetFolder,\n newBranchName: cli.newBranchName,\n skipInstall: cli.options.skipInstall,\n skipGit: cli.options.skipGit,\n skipClean: cli.options.skipClean,\n skipGenerate: cli.options.skipGenerate,\n packageManager: cli.packageManager,\n };\n\n await create(createOptions);\n}\n\nmain().catch(console.error);\n","import { basename, resolve } from 'node:path';\nimport { Command, InvalidArgumentError } from 'commander';\n\nimport { NAME, VERSION } from './constants.ts';\nimport { validateProjectName } from './utils/validate-project-name.ts';\n\n// Define types for CLI options\ninterface CLIOptions {\n skipNewBranch: boolean;\n skipClean: boolean;\n skipGit: boolean;\n skipInstall: boolean;\n skipGenerate: boolean;\n newBranchName?: string;\n}\n\n// Define CLI configuration\ninterface CLIConfig {\n options: CLIOptions;\n args: string[];\n directory: string | null;\n newBranchName: string | null;\n createNewBranch: boolean | null;\n packageManager: string;\n}\n\n// Initialize CLI variables\nlet directory: string | null = null;\nlet newBranchName: string | null = null;\nlet createNewBranch: boolean | null = null;\nconst packageManager = 'pnpm';\n\n// Set up the CLI command using Commander\nexport const command = new Command(NAME)\n .version(\n VERSION,\n '-v, --version',\n `Output the current version of ${NAME}.`\n )\n .argument('[directory]', 'The directory name for the new project.')\n .usage('[directory] [options]')\n .helpOption('-h, --help', 'Display this help message.')\n .option('--skip-new-branch', 'Skip creating a new branch during initialization.', false)\n .option('--skip-install', 'Skip the installation of packages.', false)\n .option('--skip-generate', 'Skip generating SQL files.', false)\n .option('--skip-clean', 'Skip cleaning the `cella` template.', false)\n .option('--skip-git', 'Skip initializing a git repository.', false)\n .option(\n '--new-branch-name <name>',\n 'Specify a new branch name to create and use.',\n (name: string) => {\n if (typeof name === 'string') {\n name = name.trim();\n }\n\n if (name) {\n const validation = validateProjectName(basename(resolve(name)));\n\n if (!validation.valid) {\n throw new InvalidArgumentError(\n `Invalid branch name: ${validation.problems[0]}`\n );\n }\n \n createNewBranch = true;\n newBranchName = name;\n }\n }\n )\n .action((name: string) => {\n if (typeof name === 'string') {\n name = name.trim();\n }\n\n if (name) {\n const validation = validateProjectName(basename(resolve(name)));\n\n if (!validation.valid) {\n throw new InvalidArgumentError(\n `Invalid project name: ${validation.problems[0]}`\n );\n }\n\n directory = name;\n }\n })\n .parse();\n\n// Gather the CLI options and arguments\nconst options: CLIOptions = command.opts<CLIOptions>({\n skipNewBranch: false,\n skipClean: false,\n skipGit: false,\n skipInstall: false,\n skipGenerate: false,\n});\n\n// Export the CLI configuration for use in other modules\nexport const cli: CLIConfig = {\n options,\n args: command.args,\n directory,\n newBranchName,\n createNewBranch,\n packageManager,\n};\n","{\n \"name\": \"@cellajs/create-cella\",\n \"version\": \"0.0.18\",\n \"private\": false,\n \"license\": \"MIT\",\n \"description\": \"Cella is a TypeScript template to create web apps with sync and offline capabilities.\",\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/cellajs/cella\",\n \"directory\": \"cli/create-cella\"\n },\n \"homepage\": \"https://cellajs.com\",\n \"author\": \"CellaJS <info@cellajs.com>\",\n \"engines\": {\n \"node\": \">=20.14.0\"\n },\n \"type\": \"module\",\n \"main\": \"./src/index.ts\",\n \"bin\": {\n \"create-cella\": \"index.js\"\n },\n \"scripts\": {\n \"start\": \"tsx ./src/index.ts\",\n \"clean\": \"rimraf ./dist\",\n \"build\": \"tsup\",\n \"test-build\": \"pnpm run build && node index.js\",\n \"prepublishOnly\": \"pnpm run build\"\n },\n \"packageManager\": \"pnpm@9.11.0\",\n \"dependencies\": {\n \"@inquirer/prompts\": \"^6.0.1\",\n \"commander\": \"^12.1.0\",\n \"cross-spawn\": \"^7.0.3\",\n \"giget\": \"^1.2.3\",\n \"picocolors\": \"^1.1.0\",\n \"validate-npm-package-name\": \"^5.0.1\",\n \"yocto-spinner\": \"^0.1.0\"\n },\n \"devDependencies\": {\n \"tsup\": \"^8.3.5\",\n \"tsx\": \"^4.19.2\"\n }\n}\n","export const NAME = 'create-cella';\n\n// URL of the template repository\nexport const TEMPLATE_URL = 'github:cellajs/cella';\n\n// URL to the repository\nexport const CELLA_REMOTE_URL: string = 'git@github.com:cellajs/cella.git';\n\n// Import package.json dynamically for version and website information\nimport packageJson from '../package.json' assert { type: 'json' };\n\n// Export details from package.json\nexport const DESCRIPTION: string = packageJson.description;\nexport const VERSION: string = packageJson.version;\nexport const AUTHOR: string = packageJson.author;\nexport const WEBSITE: string = packageJson.homepage;\nexport const GITHUB: string = packageJson.repository.url;\n\n// Files or folders to be removed from the template after downloading\nexport const TO_REMOVE: string[] = [\n 'info',\n './cli/create-cella',\n];\n\n// Specific folder contents to be cleaned out from the template\nexport const TO_CLEAN: string[] = [\n './backend/drizzle',\n];\n\n// Files to copy/paste after downloading\nexport const TO_COPY: Record<string, string> = {\n './backend/.env.example': './backend/.env',\n './frontend/.env.example': './frontend/.env',\n './tus/.env.example': './tus/.env',\n './info/QUICKSTART.md': 'README.md',\n};\n\n// ASCII logo for the CLI output\nexport const LOGO = `\n _ _ \n ▒▓█████▓▒ ___ ___| | | __ _\n ▒▓█ █▓▒ / __/ _ \\\\ | |/ _\\` |\n ▒▓█ █▓▒ | (_| __/ | | (_| |\n ▒▓█████▓▒ \\\\___\\\\___|_|_|\\\\__,_|\n`;\n","import validate from 'validate-npm-package-name';\n\ninterface ValidationResult {\n valid: boolean;\n problems?: string[];\n}\n\nexport function validateProjectName(name: string): ValidationResult {\n const nameValidation = validate(name);\n\n if (nameValidation.validForNewPackages) {\n return { valid: true };\n }\n\n return {\n valid: false,\n problems: [\n ...(nameValidation.errors || []),\n ...(nameValidation.warnings || []),\n ],\n };\n}\n","import { readdir } from 'node:fs/promises';\n\n/**\n * Checks if a directory is empty or only contains a .git directory.\n * \n * @param path - The path of the directory to check.\n * @returns Resolves to true if the directory is empty or contains only a .git folder, false otherwise.\n * @throws Throws an error if the path is not a directory or if there's an issue reading the directory.\n */\nexport async function isEmptyDirectory(path: string): Promise<boolean> {\n const files = await readdir(path);\n\n // Check if directory is empty or contains only the .git directory\n return files.length === 0 || (files.length === 1 && files[0] === '.git');\n}\n","import { mkdir } from 'node:fs/promises';\nimport { existsSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport colors from 'picocolors';\nimport { downloadTemplate } from 'giget';\nimport yoctoSpinner from 'yocto-spinner';\n\nimport { TEMPLATE_URL } from './constants.ts';\n\nimport { install, generate } from './utils/run-package-manager-command.ts';\nimport { cleanTemplate } from './utils/clean-template.ts';\nimport { runGitCommand } from './utils/run-git-command.ts';\nimport { addRemote } from './add-remote.ts';\n\ninterface CreateOptions {\n projectName: string;\n targetFolder: string;\n newBranchName?: string | null;\n skipInstall: boolean;\n skipGit: boolean;\n skipClean: boolean;\n skipGenerate: boolean;\n packageManager: string;\n}\n\nexport async function create({\n projectName,\n targetFolder,\n newBranchName,\n skipInstall,\n skipGit,\n skipClean,\n skipGenerate,\n packageManager,\n}: CreateOptions): Promise<void> {\n // Save the original working directory\n const originalCwd = process.cwd();\n\n console.info();\n\n // Create the target folder if it doesn't exist\n const createFolderSpinner = yoctoSpinner({\n text: 'Creating project folder',\n }).start();\n\n await mkdir(targetFolder, { recursive: true });\n process.chdir(targetFolder);\n\n createFolderSpinner.success('Project folder created');\n\n // Download the template from the specified URL\n const downloadSpinner = yoctoSpinner({\n text: 'Downloading `cella` template',\n }).start();\n\n await downloadTemplate(TEMPLATE_URL, {\n cwd: process.cwd(),\n dir: targetFolder,\n force: true,\n provider: 'github',\n });\n\n downloadSpinner.success('`cella` template downloaded');\n\n // Clean the template if the skipClean flag is not set\n if (!skipClean) {\n const cleanSpinner = yoctoSpinner({\n text: 'cleaning `cella` template',\n }).start();\n\n try {\n await cleanTemplate({\n targetFolder,\n projectName,\n });\n cleanSpinner.success('`cella` template cleaned');\n } catch (e) {\n console.error(e);\n cleanSpinner.error('Failed to clean `cella` template');\n process.exit(1);\n }\n } else {\n console.info(`${colors.yellow('⚠')} --skip-clean > Skip cleaning \\`cella\\` template`);\n }\n\n // Install dependencies if the skipInstall flag is not set\n if (!skipInstall) {\n const installSpinner = yoctoSpinner({\n text: 'installing dependencies',\n }).start();\n\n try {\n await install(packageManager);\n installSpinner.success('Dependencies installed');\n } catch (e) {\n console.error(e);\n installSpinner.error('Failed to install dependencies');\n process.exit(1);\n }\n } else {\n console.info(`${colors.yellow('⚠')} --skip-install > Skip installing dependencies`);\n }\n\n // Generate SQL files if the skipGenerate flag is not set\n if (!skipGenerate) {\n const generateSpinner = yoctoSpinner({\n text: 'generating SQL files',\n }).start();\n\n try {\n await generate(packageManager);\n generateSpinner.success('SQL files generated');\n } catch (e) {\n console.error(e);\n generateSpinner.error('Failed to generate SQL files');\n process.exit(1);\n }\n } else {\n console.info(`${colors.yellow('⚠')} --skip-generate > Skip generating SQL files`);\n }\n\n // Initialize Git repository if skipGit flag is not set\n if (!skipGit) {\n const gitSpinner = yoctoSpinner({\n text: 'initializing git repository',\n }).start();\n\n const gitFolderPath = join(targetFolder, '.git');\n\n if (!existsSync(gitFolderPath)) {\n try {\n // Run Git commands to initialize the repository and make the first commit\n await runGitCommand({ targetFolder, command: 'init' });\n await runGitCommand({ targetFolder, command: 'add .' });\n await runGitCommand({ targetFolder, command: 'commit -m \"Initial commit\"' });\n\n // If a new branch name is specified, create and checkout the branch\n if (newBranchName) {\n await runGitCommand({ targetFolder, command: `branch ${newBranchName}` });\n await runGitCommand({ targetFolder, command: `checkout ${newBranchName}` });\n gitSpinner.success(`Git repository initialized, initial commit created, and new branch ${newBranchName} created`);\n } else {\n gitSpinner.success('Git repository initialized and initial commit created');\n }\n } catch (e) {\n console.error(e);\n gitSpinner.error('Failed to initialize Git repository or create branch');\n process.exit(1);\n }\n } else {\n gitSpinner.warning('Git repository already initialized > Skip git init');\n }\n } else {\n console.info(`${colors.yellow('⚠')} --skip-git > Skip git init`);\n }\n\n // Add Cella as upstream remote\n await addRemote({ targetFolder });\n\n // Final success message indicating project creation\n console.info();\n console.info(`${colors.green('Success')} Created ${projectName} at ${targetFolder}`);\n console.info();\n\n // Check if the working directory needs to be changed\n const needsCd = originalCwd !== targetFolder;\n const relativePath = relative(originalCwd, targetFolder);\n\n if (needsCd) {\n // Calculate the relative path between the original working directory and the target folder\n\n console.info('now go to your project using:');\n console.info(colors.cyan(` cd ${relativePath}`)); // Adding './' to make it clear it's a relative path\n console.info();\n }\n\n console.info(`${needsCd ? 'then ' : ''}quick start using pglite with:`);\n console.info(colors.cyan(` ${packageManager} quick`));\n console.info();\n\n console.info('Already have docker installed? Then you can have a full setup with:');\n console.info(colors.cyan(` ${packageManager} docker`));\n console.info(colors.cyan(` ${packageManager} dev`));\n console.info(colors.cyan(` ${packageManager} seed`));\n\n console.info(`For more info, check out: ${relativePath}/README.md`);\n console.info(`Enjoy building ${projectName} using cella! 🎉`);\n console.info();\n}\n","import spawn from 'cross-spawn';\n\n/**\n * Executes a command using the specified package manager (e.g., pnpm).\n * \n * @param packageManager - The package manager to use (e.g., 'pnpm').\n * @param args - The arguments to pass to the package manager command.\n * @param env - Additional environment variables to set during command execution.\n * @returns A promise that resolves if the command executes successfully; otherwise, it rejects with an error message.\n */\nexport async function runPackageManagerCommand(\n packageManager: string,\n args: string[],\n env: Record<string, string> = {}\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(packageManager, args, {\n env: {\n ...process.env,\n ...env,\n },\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n // Buffer for capturing stderr and stdout output\n let stderrBuffer = '';\n let stdoutBuffer = '';\n\n // Capture stderr output\n child.stderr?.on('data', (data: Buffer) => {\n stderrBuffer += data.toString();\n });\n\n // Capture stdout output\n child.stdout?.on('data', (data: Buffer) => {\n stdoutBuffer += data.toString();\n });\n\n // Handle process exit\n child.on('close', (code: number | null) => {\n if (code !== 0) {\n reject(\n `\"${packageManager} ${args.join(' ')}\" failed ${stdoutBuffer} ${stderrBuffer}`\n );\n return;\n }\n resolve();\n });\n });\n}\n\n/**\n * Installs dependencies using the specified package manager.\n * \n * @param packageManager - The package manager to use for installation (e.g., 'pnpm').\n * @returns A promise that resolves if the installation completes successfully; otherwise, it rejects with an error.\n */\nexport async function install(packageManager: string): Promise<void> {\n return runPackageManagerCommand(packageManager, ['install'], {\n NODE_ENV: 'development',\n });\n}\n\n/**\n * Generates SQL files using the specified package manager.\n * \n * @param packageManager - The package manager to use for generation (e.g., 'pnpm').\n * @returns A promise that resolves if the generation completes successfully; otherwise, it rejects with an error.\n */\nexport async function generate(packageManager: string): Promise<void> {\n return runPackageManagerCommand(packageManager, ['generate'], {\n NODE_ENV: 'development',\n });\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport colors from 'picocolors';\n\nimport { TO_CLEAN, TO_REMOVE, TO_COPY } from '../constants.ts';\n\n/**\n * Cleans the specified template by removing designated folders and files.\n * @param params - Parameters containing the target folder and project name.\n */\nexport async function cleanTemplate({\n targetFolder,\n projectName,\n}: {\n targetFolder: string;\n projectName: string;\n}): Promise<void> {\n // Change the current working directory to targetFolder if not already set\n if (process.cwd() !== targetFolder) {\n process.chdir(targetFolder);\n }\n\n return new Promise<void>(async (resolve, reject) => {\n try {\n // Copy specified files\n for (const [src, dest] of Object.entries(TO_COPY)) {\n const srcAbsolutePath = path.resolve(targetFolder, src);\n const destAbsolutePath = path.resolve(targetFolder, dest);\n await copyFile(srcAbsolutePath, destAbsolutePath);\n }\n\n // Clean specified folder contents\n await Promise.all(\n TO_CLEAN.map((folderPath) => {\n const absolutePath = path.resolve(targetFolder, folderPath);\n return removeFolderContents(absolutePath);\n })\n );\n\n // Remove specified files and folders\n await Promise.all(\n TO_REMOVE.map((filePath) => {\n const absolutePath = path.resolve(targetFolder, filePath);\n return removeFileOrFolder(absolutePath);\n })\n );\n\n resolve();\n } catch (err) {\n reject(`Error during the cleaning process: ${err}`);\n }\n });\n}\n\n/**\n * Removes all contents within a specified folder.\n * @param folderPath - The path of the folder to clean.\n */\nexport async function removeFolderContents(folderPath: string): Promise<void> {\n // List all files in the folder\n const files = await fs.readdir(folderPath);\n\n await Promise.all(\n files.map(async (file) => {\n const filePath = path.join(folderPath, file);\n\n // Get the file or folder statistics\n const stat = await fs.lstat(filePath);\n\n // If it's a directory, remove it and all its contents\n if (stat.isDirectory()) {\n await fs.rm(filePath, { recursive: true, force: true });\n } else {\n // If it's a file, remove it\n await fs.rm(filePath);\n }\n })\n );\n}\n\n/**\n * Removes a specified file or folder.\n * @param pathToRemove - The path to the file or folder to remove.\n */\nexport async function removeFileOrFolder(pathToRemove: string): Promise<void> {\n await fs.rm(pathToRemove, { recursive: true, force: true });\n}\n\n/**\n * Helper function to copy files if the source exists.\n * @param src - The source file path.\n * @param dest - The destination file path.\n */\nexport async function copyFile(src: string, dest: string): Promise<void> {\n try {\n // Check if the source file exists\n await fs.access(src);\n\n // Ensure the destination directory exists\n await fs.mkdir(path.dirname(dest), { recursive: true });\n\n // Copy the file\n await fs.copyFile(src, dest);\n } catch (err: any) {\n if (err.code === 'ENOENT') {\n console.info(`\\n${colors.yellow('⚠')} Source file \"${src}\" does not exist > Skip copy`);\n } else {\n throw err;\n }\n }\n}\n","import { spawn } from 'node:child_process';\n\ntype GitCommandType = 'merge' | 'diff' | 'other';\n\ninterface RunGitCommandOptions {\n targetFolder: string;\n command: string;\n}\n\n// Helper to determine the type of Git command for custom handling\nfunction getGitCommandType(command: string): GitCommandType {\n if (command.startsWith('merge')) return 'merge';\n if (command.startsWith('diff')) return 'diff';\n return 'other';\n}\n\n// Helper to check if a Git command is successful\nfunction isGitCommandSuccess(gitCommand: GitCommandType, code: number | null, errOutput: string): boolean {\n if (gitCommand === 'merge') return code === 0 || (code === 1 && !errOutput);\n if (gitCommand === 'diff') return code === 0 || (code === 2 && !errOutput);\n return code === 0;\n}\n\n// Function to run a Git command and handle its output\nexport async function runGitCommand({ targetFolder, command }: RunGitCommandOptions): Promise<string> {\n return new Promise((resolve, reject) => {\n const gitCommand = getGitCommandType(command);\n const child = spawn(`git ${command}`, [], { cwd: targetFolder, shell: true, timeout: 60000 });\n\n let output = '';\n let errOutput = '';\n\n child.on('error', (error: Error) => {\n reject(error);\n });\n\n child.on('exit', (code: number | null) => {\n if (isGitCommandSuccess(gitCommand, code, errOutput)) {\n resolve(output.trim());\n } else {\n reject(\n `Git ${gitCommand} command failed with exit code ${code}, stderr: \"${errOutput.trim()}\", stdout: \"${output.trim()}\"`\n );\n }\n });\n\n // Collect stdout data\n child.stdout.on('data', (data: Buffer) => {\n output += data.toString();\n });\n\n // Collect stderr data\n child.stderr.on('data', (data: Buffer) => {\n errOutput += data.toString();\n });\n });\n}\n","import yoctoSpinner from 'yocto-spinner';\nimport { runGitCommand } from './utils/run-git-command.ts';\nimport { CELLA_REMOTE_URL } from './constants.ts';\n\ninterface AddRemoteOptions {\n targetFolder: string;\n remoteUrl?: string; // Optional, defaults to CELLA_REMOTE_URL\n remoteName?: string; // Optional, defaults to 'upstream'\n}\n\nexport async function addRemote({\n targetFolder,\n remoteUrl = CELLA_REMOTE_URL,\n remoteName = 'upstream',\n}: AddRemoteOptions): Promise<void> {\n\n // Spinner for adding remote\n const remoteSpinner = yoctoSpinner({\n text: 'Adding remote',\n }).start();\n\n try {\n // Check if the remote exists\n let remote: string | null = null;\n\n try {\n remote = await runGitCommand({ targetFolder, command: `remote get-url ${remoteName}` });\n } catch (error: any) {\n // If the remote doesn't exist, it throws a fatal error\n remote = null;\n }\n\n // Add or update the remote if it doesn't exist or differs from `remoteUrl`\n if (!remote) {\n await runGitCommand({ targetFolder, command: `remote add ${remoteName} ${remoteUrl}` });\n remoteSpinner.success('Remote added successfully.');\n } else if (remote !== remoteUrl) {\n // Remove existing remote and set the new URL\n await runGitCommand({ targetFolder, command: `remote remove ${remoteName}` });\n await runGitCommand({ targetFolder, command: `remote add ${remoteName} ${remoteUrl}` });\n remoteSpinner.success('Remote updated successfully.');\n } else {\n remoteSpinner.success('Remote is already configured correctly.');\n }\n } catch (error) {\n console.error(error);\n remoteSpinner.error('Failed to add remote.');\n process.exit(1);\n }\n}\n"],"mappings":"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","names":["basename","resolve","existsSync","colors","path","colors","yoctoSpinner","packageManager","resolve","resolve","spawn","command","resolve","newBranchName","packageManager","yoctoSpinner","colors","colors","basename","resolve","existsSync"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cellajs/create-cella",
3
- "version": "0.0.16",
3
+ "version": "0.0.18",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "description": "Cella is a TypeScript template to create web apps with sync and offline capabilities.",
package/src/constants.ts CHANGED
@@ -3,16 +3,18 @@ export const NAME = 'create-cella';
3
3
  // URL of the template repository
4
4
  export const TEMPLATE_URL = 'github:cellajs/cella';
5
5
 
6
- // URL to the Cella repository
6
+ // URL to the repository
7
7
  export const CELLA_REMOTE_URL: string = 'git@github.com:cellajs/cella.git';
8
8
 
9
9
  // Import package.json dynamically for version and website information
10
10
  import packageJson from '../package.json' assert { type: 'json' };
11
11
 
12
- // Export version, website, and author from package.json
12
+ // Export details from package.json
13
+ export const DESCRIPTION: string = packageJson.description;
13
14
  export const VERSION: string = packageJson.version;
14
15
  export const AUTHOR: string = packageJson.author;
15
16
  export const WEBSITE: string = packageJson.homepage;
17
+ export const GITHUB: string = packageJson.repository.url;
16
18
 
17
19
  // Files or folders to be removed from the template after downloading
18
20
  export const TO_REMOVE: string[] = [
@@ -33,8 +35,8 @@ export const TO_COPY: Record<string, string> = {
33
35
  './info/QUICKSTART.md': 'README.md',
34
36
  };
35
37
 
36
- // ASCII title for the CLI output
37
- export const CELLA_TITLE = `
38
+ // ASCII logo for the CLI output
39
+ export const LOGO = `
38
40
  _ _
39
41
  ▒▓█████▓▒ ___ ___| | | __ _
40
42
  ▒▓█ █▓▒ / __/ _ \\ | |/ _\` |
package/src/create.ts CHANGED
@@ -164,20 +164,26 @@ export async function create({
164
164
 
165
165
  // Check if the working directory needs to be changed
166
166
  const needsCd = originalCwd !== targetFolder;
167
+ const relativePath = relative(originalCwd, targetFolder);
168
+
167
169
  if (needsCd) {
168
170
  // Calculate the relative path between the original working directory and the target folder
169
- const relativePath = relative(originalCwd, targetFolder);
170
171
 
171
172
  console.info('now go to your project using:');
172
173
  console.info(colors.cyan(` cd ${relativePath}`)); // Adding './' to make it clear it's a relative path
173
174
  console.info();
174
175
  }
175
176
 
176
- console.info(`${needsCd ? 'then ' : ''}quick start with:`);
177
+ console.info(`${needsCd ? 'then ' : ''}quick start using pglite with:`);
177
178
  console.info(colors.cyan(` ${packageManager} quick`));
178
179
  console.info();
179
180
 
180
- console.info('Check out the readme to get started: /README.md');
181
+ console.info('Already have docker installed? Then you can have a full setup with:');
182
+ console.info(colors.cyan(` ${packageManager} docker`));
183
+ console.info(colors.cyan(` ${packageManager} dev`));
184
+ console.info(colors.cyan(` ${packageManager} seed`));
185
+
186
+ console.info(`For more info, check out: ${relativePath}/README.md`);
181
187
  console.info(`Enjoy building ${projectName} using cella! 🎉`);
182
188
  console.info();
183
189
  }
package/src/index.ts CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  import { basename, resolve } from 'node:path';
4
4
  import { existsSync } from 'node:fs';
5
+ import colors from 'picocolors';
5
6
 
6
7
  import { input, confirm, select } from '@inquirer/prompts';
7
8
 
@@ -9,7 +10,7 @@ import { cli } from './cli';
9
10
  import { validateProjectName } from './utils/validate-project-name.ts';
10
11
  import { isEmptyDirectory } from './utils/is-empty-directory.ts';
11
12
  import { create } from './create.ts';
12
- import { CELLA_TITLE, VERSION, WEBSITE, AUTHOR } from './constants.ts';
13
+ import { LOGO, VERSION, WEBSITE, AUTHOR, GITHUB, DESCRIPTION } from './constants.ts';
13
14
 
14
15
  interface CreateOptions {
15
16
  projectName: string;
@@ -23,13 +24,14 @@ interface CreateOptions {
23
24
  }
24
25
 
25
26
  async function main(): Promise<void> {
26
- console.info(CELLA_TITLE);
27
+ console.info(LOGO);
27
28
 
28
29
  // Display CLI version and created by information
29
30
  console.info();
30
- console.info(`Cella CLI: ${VERSION}`);
31
- console.info(`Created by: ${AUTHOR}`);
32
- console.info(`Website: ${WEBSITE}`);
31
+ console.info(DESCRIPTION);
32
+ console.info(`Version ${colors.green(VERSION)}`);
33
+ console.info(`Created by ${AUTHOR}`);
34
+ console.info(`${GITHUB} | ${WEBSITE}`);
33
35
  console.info();
34
36
 
35
37
  // Skip creating a new branch if --skipNewBranch flag is provided or git is skipped