create-dowel-app 0.7.0 → 0.8.0
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 +7 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/branding.ts","../src/lib/errors.ts","../src/lib/files.ts","../src/lib/pm.ts","../src/lib/logger.ts","../src/templates.ts","../src/create.ts","../src/index.ts"],"sourcesContent":["/**\n * Branding, mirrored from the repository root config.\n *\n * Duplicated deliberately: the published scaffolder cannot import from the\n * monorepo root, and `pnpm rebrand` rewrites every copy in the same pass.\n */\nexport const branding = {\n libraryName: \"Dowel\",\n cliPackage: \"@dowel-ui/cli\",\n packageScope: \"@dowel-ui\",\n registryUrl: \"https://dowel-eight.vercel.app/r\",\n docsUrl: \"https://dowel-eight.vercel.app\",\n} as const;\n","/**\n * An error whose message is written for the person running the command.\n *\n * Anything thrown as a CreateError is printed as a clean message with no stack\n * trace; everything else is treated as a bug, where the stack is the useful\n * part.\n */\nexport class CreateError extends Error {\n readonly hint: string | undefined;\n\n constructor(message: string, hint?: string) {\n super(message);\n this.name = \"CreateError\";\n this.hint = hint;\n }\n}\n","import {\n cpSync,\n existsSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n renameSync,\n statSync,\n writeFileSync,\n} from \"node:fs\";\nimport { join } from \"node:path\";\n\n/**\n * Placeholders substituted into template files.\n *\n * Written as `__NAME__` rather than as a template syntax so every template file\n * stays valid TypeScript, valid JSON and valid CSS. A template you cannot\n * typecheck is a template that ships broken, and the only way to find out is to\n * generate from it.\n */\nexport type Replacements = Record<string, string>;\n\n/** Files npm will not publish under their real name. */\nconst RENAME_ON_COPY: Record<string, string> = {\n gitignore: \".gitignore\",\n npmrc: \".npmrc\",\n \"env.example\": \".env.example\",\n};\n\n/** Extensions worth substituting into. Anything else is copied byte for byte. */\nconst TEXT_EXTENSIONS = [\".ts\", \".tsx\", \".js\", \".mjs\", \".json\", \".css\", \".md\", \".txt\"];\n\nfunction isText(path: string): boolean {\n return TEXT_EXTENSIONS.some((extension) => path.endsWith(extension)) || !path.includes(\".\");\n}\n\nexport function substitute(content: string, replacements: Replacements): string {\n let result = content;\n for (const [key, value] of Object.entries(replacements)) {\n result = result.replaceAll(`__${key}__`, value);\n }\n return result;\n}\n\n/**\n * Copies one template layer over a destination, substituting as it goes.\n *\n * Layers are applied in order and a later one overwrites an earlier one, which\n * is how `saas` replaces the base landing page without the base having to know\n * that anything might.\n */\nexport function copyLayer(from: string, to: string, replacements: Replacements): string[] {\n const written: string[] = [];\n\n const walk = (source: string, target: string, prefix: string): void => {\n mkdirSync(target, { recursive: true });\n\n for (const entry of readdirSync(source, { withFileTypes: true })) {\n const name = RENAME_ON_COPY[entry.name] ?? entry.name;\n const sourcePath = join(source, entry.name);\n const targetPath = join(target, name);\n const relative = prefix ? `${prefix}/${name}` : name;\n\n if (entry.isDirectory()) {\n walk(sourcePath, targetPath, relative);\n continue;\n }\n\n if (isText(sourcePath)) {\n writeFileSync(targetPath, substitute(readFileSync(sourcePath, \"utf8\"), replacements));\n } else {\n cpSync(sourcePath, targetPath);\n }\n\n written.push(relative);\n }\n };\n\n walk(from, to, \"\");\n return written;\n}\n\n/** True when the directory does not exist, or exists and holds nothing. */\nexport function isEmptyDirectory(path: string): boolean {\n if (!existsSync(path)) return true;\n if (!statSync(path).isDirectory()) return false;\n return readdirSync(path).length === 0;\n}\n\nexport { renameSync };\n","import { execFileSync } from \"node:child_process\";\n\nexport type PackageManager = \"pnpm\" | \"npm\" | \"yarn\" | \"bun\";\n\nexport const PACKAGE_MANAGERS: PackageManager[] = [\"pnpm\", \"npm\", \"yarn\", \"bun\"];\n\nexport function isPackageManager(value: string): value is PackageManager {\n return (PACKAGE_MANAGERS as string[]).includes(value);\n}\n\n/**\n * Which package manager invoked this process.\n *\n * `npm_config_user_agent` is set by every one of them, and it is the only\n * reliable signal: someone running `pnpm create dowel-app` wants pnpm, and\n * asking them again is asking a question the environment already answered.\n */\nexport function detectPackageManager(): PackageManager {\n const agent = process.env.npm_config_user_agent ?? \"\";\n\n for (const candidate of PACKAGE_MANAGERS) {\n if (agent.startsWith(`${candidate}/`)) return candidate;\n }\n\n return \"npm\";\n}\n\nexport function installCommand(manager: PackageManager): string {\n return manager === \"npm\" ? \"npm install\" : `${manager} install`;\n}\n\nexport function runCommand(manager: PackageManager, script: string): string {\n return manager === \"npm\" ? `npm run ${script}` : `${manager} ${script}`;\n}\n\n/** The runner that executes a package's binary without installing it globally. */\nexport function dlx(manager: PackageManager): string[] {\n switch (manager) {\n case \"pnpm\":\n return [\"pnpm\", \"dlx\"];\n case \"yarn\":\n return [\"yarn\", \"dlx\"];\n case \"bun\":\n return [\"bunx\"];\n default:\n return [\"npx\", \"-y\"];\n }\n}\n\nexport function install(manager: PackageManager, cwd: string): void {\n const [command, ...args] = installCommand(manager).split(\" \");\n execFileSync(command ?? \"npm\", args, { cwd, stdio: \"inherit\" });\n}\n\n/** Runs the component CLI in the new project. */\nexport function runDowel(\n manager: PackageManager,\n cwd: string,\n cliPackage: string,\n args: string[],\n): void {\n const [command, ...runner] = dlx(manager);\n execFileSync(command ?? \"npx\", [...runner, cliPackage, ...args], { cwd, stdio: \"inherit\" });\n}\n","import pc from \"picocolors\";\n\n/**\n * All CLI output goes through here.\n *\n * A single place to route messages means the format stays consistent, and\n * anything that needs to change later — quiet mode, JSON output, writing to\n * stderr — changes in one file rather than in every command.\n */\nexport const logger = {\n info(message: string) {\n console.log(message);\n },\n success(message: string) {\n console.log(`${pc.green(\"✓\")} ${message}`);\n },\n warn(message: string) {\n console.warn(`${pc.yellow(\"!\")} ${message}`);\n },\n error(message: string) {\n console.error(`${pc.red(\"✕\")} ${message}`);\n },\n step(message: string) {\n console.log(`${pc.dim(\"·\")} ${message}`);\n },\n blank() {\n console.log(\"\");\n },\n};\n\nexport { pc };\n","import { branding } from \"./branding\";\n\n/**\n * What a template is, here.\n *\n * A directory of application files, plus a list of registry items to install\n * into it. The components are *not* in the template — they are fetched from the\n * registry at creation time by the same CLI a user would run themselves.\n *\n * That is the whole design. A template that carries its own copy of Button is a\n * copy that is wrong by the next release, and the person who generated from it\n * has no way to know. Fetching means a project created today is built from\n * today's registry, and means a template is a dozen files rather than a hundred.\n */\n\nexport interface Template {\n id: string;\n title: string;\n /** One line, shown in the picker. */\n description: string;\n /**\n * Template directories layered in order, so shared files are written once.\n * Later directories overwrite earlier ones.\n */\n layers: string[];\n /** Registry items installed with `add` after the files are written. */\n items: string[];\n /** Routes the template ships, for the \"what next\" summary. */\n routes: string[];\n}\n\nexport const TEMPLATES: Template[] = [\n {\n id: \"starter\",\n title: \"Starter\",\n description: `A Next.js app wired to ${branding.libraryName}: tokens, aliases and a landing page.`,\n layers: [\"base\", \"starter\"],\n items: [\"button\", \"card\", \"badge\"],\n routes: [\"/\"],\n },\n {\n id: \"saas\",\n title: \"SaaS\",\n description:\n \"Adds an application shell with dashboard, analytics, billing, settings and onboarding.\",\n layers: [\"base\", \"app-shell\", \"saas\"],\n items: [\"sidebar\", \"dashboard\", \"analytics\", \"billing\", \"settings\", \"onboarding\"],\n routes: [\"/\", \"/app\", \"/app/analytics\", \"/app/billing\", \"/app/settings\"],\n },\n {\n id: \"ai\",\n title: \"AI product\",\n description: \"Adds a chat surface, an agent console and a usage dashboard.\",\n layers: [\"base\", \"app-shell\", \"ai\"],\n items: [\"sidebar\", \"ai-chat\", \"agent-console\", \"ai-dashboard\"],\n routes: [\"/\", \"/app\", \"/app/agents\", \"/app/usage\"],\n },\n];\n\nexport function findTemplate(id: string): Template | undefined {\n return TEMPLATES.find((template) => template.id === id);\n}\n\n/** Presets the scaffolder offers, mirroring what the theme layer ships. */\nexport const THEMES = [\n \"default\",\n \"ocean\",\n \"emerald\",\n \"violet\",\n \"rose\",\n \"amber\",\n \"monochrome\",\n] as const;\n\nexport type Theme = (typeof THEMES)[number];\n\nexport function isTheme(value: string): value is Theme {\n return (THEMES as readonly string[]).includes(value);\n}\n","import * as prompts from \"@clack/prompts\";\nimport { existsSync, mkdirSync, readdirSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { branding } from \"./branding\";\nimport { CreateError } from \"./lib/errors\";\nimport { copyLayer, isEmptyDirectory, type Replacements } from \"./lib/files\";\nimport {\n detectPackageManager,\n install,\n installCommand,\n isPackageManager,\n runCommand,\n runDowel,\n type PackageManager,\n} from \"./lib/pm\";\nimport { logger, pc } from \"./lib/logger\";\nimport { findTemplate, isTheme, TEMPLATES, THEMES, type Template } from \"./templates\";\n\nexport interface CreateOptions {\n /** Directory to create, relative to cwd or absolute. */\n directory?: string;\n template?: string;\n theme?: string;\n packageManager?: string;\n /** Accept every default and never prompt. */\n yes: boolean;\n skipInstall: boolean;\n /** Write files but do not fetch components. Mostly for tests. */\n skipComponents: boolean;\n cwd: string;\n}\n\n/** Where the shipped templates live, relative to the built entry point. */\nconst templatesRoot = join(dirname(fileURLToPath(import.meta.url)), \"..\", \"templates\");\n\n/**\n * npm's rules for a package name, which is what this becomes.\n *\n * Checked before anything is written rather than after: a directory created and\n * then abandoned because the name was rejected is worse than a question asked\n * twice.\n */\nexport function validateProjectName(name: string): string | undefined {\n if (name.length === 0) return \"Give the project a name.\";\n if (name.length > 214) return \"That is longer than npm allows for a package name.\";\n if (name.startsWith(\".\") || name.startsWith(\"_\")) {\n return \"A package name cannot start with a dot or an underscore.\";\n }\n if (name !== name.toLowerCase()) return \"A package name has to be lowercase.\";\n if (!/^[a-z0-9._-]+$/.test(name)) {\n return \"Use lowercase letters, digits, dots, hyphens and underscores only.\";\n }\n return undefined;\n}\n\n/** The last segment of a path, as a package name. */\nexport function projectNameFrom(directory: string): string {\n return directory.split(\"/\").filter(Boolean).pop() ?? \"app\";\n}\n\n/** The nav for the app shell, written into its layout. */\nfunction appLinks(template: Template): string {\n const labels: Record<string, string> = {\n \"/app\": template.id === \"ai\" ? \"Chat\" : \"Dashboard\",\n \"/app/analytics\": \"Analytics\",\n \"/app/billing\": \"Billing\",\n \"/app/settings\": \"Settings\",\n \"/app/agents\": \"Agents\",\n \"/app/usage\": \"Usage\",\n };\n\n const links = template.routes\n .filter((route) => route !== \"/\")\n .map((route) => ` { href: \"${route}\", label: \"${labels[route] ?? route}\" },`);\n\n return `[\\n${links.join(\"\\n\")}\\n]`;\n}\n\nexport async function create(options: CreateOptions): Promise<void> {\n const interactive = !options.yes;\n\n if (interactive) {\n prompts.intro(`${branding.libraryName} — create an app`);\n }\n\n const directory = await resolveDirectory(options, interactive);\n const target = isAbsolute(directory) ? directory : resolve(options.cwd, directory);\n const name = projectNameFrom(directory);\n\n const invalid = validateProjectName(name);\n if (invalid) throw new CreateError(invalid);\n\n if (!isEmptyDirectory(target)) {\n throw new CreateError(\n `${directory} already exists and is not empty.`,\n \"Choose another name, or empty the directory first.\",\n );\n }\n\n const template = await resolveTemplate(options, interactive);\n const theme = await resolveTheme(options, interactive);\n const manager = resolvePackageManager(options);\n\n const replacements: Replacements = {\n PROJECT_NAME: name,\n LIBRARY_NAME: branding.libraryName,\n CLI_PACKAGE: branding.cliPackage,\n DOCS_URL: branding.docsUrl,\n THEME: theme,\n APP_LINKS: appLinks(template),\n };\n\n mkdirSync(target, { recursive: true });\n\n const written: string[] = [];\n for (const layer of template.layers) {\n const from = join(templatesRoot, layer);\n if (!existsSync(from)) {\n throw new CreateError(\n `The ${layer} template is missing from this installation.`,\n \"Reinstall create-dowel-app, or report this if it persists.\",\n );\n }\n written.push(...copyLayer(from, target, replacements));\n }\n\n logger.blank();\n logger.success(`Created ${pc.bold(name)} from the ${pc.bold(template.title)} template.`);\n logger.info(pc.dim(` ${String(new Set(written).size)} files in ${directory}`));\n\n if (!options.skipInstall) {\n logger.blank();\n logger.step(`Installing dependencies with ${manager}`);\n install(manager, target);\n }\n\n if (!options.skipComponents) {\n logger.blank();\n logger.step(\"Fetching components from the registry\");\n\n // Through the real CLI, not a bundled copy. A template that carried its own\n // Button would be carrying whichever Button was current the day it was\n // written, and nothing would ever say so.\n runDowel(manager, target, branding.cliPackage, [\"init\", \"--yes\", \"--skip-install\"]);\n runDowel(manager, target, branding.cliPackage, [\n \"add\",\n ...template.items,\n \"--yes\",\n ...(options.skipInstall ? [\"--skip-install\"] : []),\n ]);\n }\n\n summarise({ directory, template, theme, manager, options });\n}\n\ninterface SummaryContext {\n directory: string;\n template: Template;\n theme: string;\n manager: PackageManager;\n options: CreateOptions;\n}\n\nfunction summarise({ directory, template, theme, manager, options }: SummaryContext): void {\n logger.blank();\n logger.success(\"Done.\");\n logger.blank();\n\n logger.info(pc.dim(\"Next:\"));\n logger.info(` cd ${directory}`);\n if (options.skipInstall) logger.info(` ${installCommand(manager)}`);\n logger.info(` ${runCommand(manager, \"dev\")}`);\n\n logger.blank();\n logger.info(pc.dim(\"Routes:\"));\n for (const route of template.routes) logger.info(` ${route}`);\n\n logger.blank();\n logger.info(\n pc.dim(\n `Theme: ${theme}. Change it on <html data-theme> in src/app/layout.tsx — no component file changes.`,\n ),\n );\n logger.info(\n pc.dim(`Teach your coding agent what is installed: npx ${branding.cliPackage} agents`),\n );\n}\n\nasync function resolveDirectory(options: CreateOptions, interactive: boolean): Promise<string> {\n if (options.directory) return options.directory;\n if (!interactive) {\n throw new CreateError(\n \"No directory given.\",\n \"Pass one, e.g. `create-dowel-app my-app`, or drop --yes to be asked.\",\n );\n }\n\n const answer = await prompts.text({\n message: \"Where should it go?\",\n placeholder: \"my-app\",\n defaultValue: \"my-app\",\n validate: (value) => validateProjectName(projectNameFrom(value || \"my-app\")),\n });\n\n if (prompts.isCancel(answer)) throw new CreateError(\"Cancelled — nothing was written.\");\n return answer || \"my-app\";\n}\n\nasync function resolveTemplate(\n options: CreateOptions,\n interactive: boolean,\n): Promise<Template> {\n if (options.template) {\n const found = findTemplate(options.template);\n if (!found) {\n throw new CreateError(\n `Unknown template \"${options.template}\".`,\n `Choose from: ${TEMPLATES.map((entry) => entry.id).join(\", \")}.`,\n );\n }\n return found;\n }\n\n if (!interactive) return TEMPLATES[0]!;\n\n const answer = await prompts.select({\n message: \"What are you building?\",\n options: TEMPLATES.map((entry) => ({\n value: entry.id,\n label: entry.title,\n hint: entry.description,\n })),\n });\n\n if (prompts.isCancel(answer)) throw new CreateError(\"Cancelled — nothing was written.\");\n return findTemplate(answer) ?? TEMPLATES[0]!;\n}\n\nasync function resolveTheme(options: CreateOptions, interactive: boolean): Promise<string> {\n if (options.theme) {\n if (!isTheme(options.theme)) {\n throw new CreateError(\n `Unknown theme \"${options.theme}\".`,\n `Choose from: ${THEMES.join(\", \")}.`,\n );\n }\n return options.theme;\n }\n\n if (!interactive) return \"default\";\n\n const answer = await prompts.select({\n message: \"Which theme?\",\n options: THEMES.map((entry) => ({\n value: entry,\n label: entry,\n hint:\n entry === \"monochrome\"\n ? \"No colour at all — a standing check that nothing relies on it\"\n : undefined,\n })),\n });\n\n if (prompts.isCancel(answer)) throw new CreateError(\"Cancelled — nothing was written.\");\n return answer;\n}\n\nfunction resolvePackageManager(options: CreateOptions): PackageManager {\n if (!options.packageManager) return detectPackageManager();\n\n if (!isPackageManager(options.packageManager)) {\n throw new CreateError(\n `Unknown package manager \"${options.packageManager}\".`,\n \"Choose from: pnpm, npm, yarn, bun.\",\n );\n }\n\n return options.packageManager;\n}\n\nexport { readdirSync };\n","#!/usr/bin/env node\nimport { readFileSync } from \"node:fs\";\n\nimport { Command } from \"commander\";\n\nimport { branding } from \"./branding\";\nimport { create } from \"./create\";\nimport { CreateError } from \"./lib/errors\";\nimport { logger, pc } from \"./lib/logger\";\nimport { TEMPLATES, THEMES } from \"./templates\";\n\nconst { version } = JSON.parse(\n readFileSync(new URL(\"../package.json\", import.meta.url), \"utf8\"),\n) as { version: string };\n\nconst program = new Command();\n\nprogram\n .name(\"create-dowel-app\")\n .description(\n `Creates a Next.js application wired to ${branding.libraryName}, with the components ` +\n `fetched from the registry rather than copied out of a template.`,\n )\n .version(version)\n .argument(\"[directory]\", \"where to create it\")\n .option(\"-t, --template <name>\", `one of: ${TEMPLATES.map((entry) => entry.id).join(\", \")}`)\n .option(\"--theme <name>\", `one of: ${THEMES.join(\", \")}`)\n .option(\"--pm <manager>\", \"pnpm, npm, yarn or bun; detected from how this was run\")\n .option(\"-y, --yes\", \"accept every default and never prompt\", false)\n .option(\"--skip-install\", \"write files but do not install dependencies\", false)\n .option(\"--skip-components\", \"write files but do not fetch components\", false)\n .action(\n async (\n directory: string | undefined,\n options: {\n template?: string;\n theme?: string;\n pm?: string;\n yes: boolean;\n skipInstall: boolean;\n skipComponents: boolean;\n },\n ) => {\n await create({\n directory,\n template: options.template,\n theme: options.theme,\n packageManager: options.pm,\n yes: options.yes,\n skipInstall: options.skipInstall,\n skipComponents: options.skipComponents,\n cwd: process.cwd(),\n });\n },\n );\n\n/**\n * A CreateError is a message for the person running the command; anything else\n * is a bug, and its stack trace is the useful part.\n */\nasync function main(): Promise<void> {\n try {\n await program.parseAsync(process.argv);\n } catch (error) {\n logger.blank();\n if (error instanceof CreateError) {\n logger.error(error.message);\n if (error.hint) logger.info(pc.dim(` ${error.hint}`));\n } else {\n logger.error(\"Something went wrong.\");\n logger.info(String(error instanceof Error ? (error.stack ?? error.message) : error));\n }\n logger.blank();\n process.exitCode = 1;\n }\n}\n\nvoid main();\n\nexport { create };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/branding.ts","../src/lib/errors.ts","../src/lib/files.ts","../src/lib/pm.ts","../src/lib/logger.ts","../src/templates.ts","../src/create.ts","../src/index.ts"],"sourcesContent":["/**\n * Branding, mirrored from the repository root config.\n *\n * Duplicated deliberately: the published scaffolder cannot import from the\n * monorepo root, and `pnpm rebrand` rewrites every copy in the same pass.\n */\nexport const branding = {\n libraryName: \"Dowel\",\n cliPackage: \"@dowel-ui/cli\",\n packageScope: \"@dowel-ui\",\n registryUrl: \"https://dowel-eight.vercel.app/r\",\n docsUrl: \"https://dowel-eight.vercel.app\",\n} as const;\n","/**\n * An error whose message is written for the person running the command.\n *\n * Anything thrown as a CreateError is printed as a clean message with no stack\n * trace; everything else is treated as a bug, where the stack is the useful\n * part.\n */\nexport class CreateError extends Error {\n readonly hint: string | undefined;\n\n constructor(message: string, hint?: string) {\n super(message);\n this.name = \"CreateError\";\n this.hint = hint;\n }\n}\n","import {\n cpSync,\n existsSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n renameSync,\n statSync,\n writeFileSync,\n} from \"node:fs\";\nimport { join } from \"node:path\";\n\n/**\n * Placeholders substituted into template files.\n *\n * Written as `__NAME__` rather than as a template syntax so every template file\n * stays valid TypeScript, valid JSON and valid CSS. A template you cannot\n * typecheck is a template that ships broken, and the only way to find out is to\n * generate from it.\n */\nexport type Replacements = Record<string, string>;\n\n/** Files npm will not publish under their real name. */\nconst RENAME_ON_COPY: Record<string, string> = {\n gitignore: \".gitignore\",\n npmrc: \".npmrc\",\n \"env.example\": \".env.example\",\n};\n\n/** Extensions worth substituting into. Anything else is copied byte for byte. */\nconst TEXT_EXTENSIONS = [\".ts\", \".tsx\", \".js\", \".mjs\", \".json\", \".css\", \".md\", \".txt\"];\n\nfunction isText(path: string): boolean {\n return TEXT_EXTENSIONS.some((extension) => path.endsWith(extension)) || !path.includes(\".\");\n}\n\nexport function substitute(content: string, replacements: Replacements): string {\n let result = content;\n for (const [key, value] of Object.entries(replacements)) {\n result = result.replaceAll(`__${key}__`, value);\n }\n return result;\n}\n\n/**\n * Copies one template layer over a destination, substituting as it goes.\n *\n * Layers are applied in order and a later one overwrites an earlier one, which\n * is how `saas` replaces the base landing page without the base having to know\n * that anything might.\n */\nexport function copyLayer(from: string, to: string, replacements: Replacements): string[] {\n const written: string[] = [];\n\n const walk = (source: string, target: string, prefix: string): void => {\n mkdirSync(target, { recursive: true });\n\n for (const entry of readdirSync(source, { withFileTypes: true })) {\n const name = RENAME_ON_COPY[entry.name] ?? entry.name;\n const sourcePath = join(source, entry.name);\n const targetPath = join(target, name);\n const relative = prefix ? `${prefix}/${name}` : name;\n\n if (entry.isDirectory()) {\n walk(sourcePath, targetPath, relative);\n continue;\n }\n\n if (isText(sourcePath)) {\n writeFileSync(targetPath, substitute(readFileSync(sourcePath, \"utf8\"), replacements));\n } else {\n cpSync(sourcePath, targetPath);\n }\n\n written.push(relative);\n }\n };\n\n walk(from, to, \"\");\n return written;\n}\n\n/** True when the directory does not exist, or exists and holds nothing. */\nexport function isEmptyDirectory(path: string): boolean {\n if (!existsSync(path)) return true;\n if (!statSync(path).isDirectory()) return false;\n return readdirSync(path).length === 0;\n}\n\nexport { renameSync };\n","import { execFileSync } from \"node:child_process\";\n\nexport type PackageManager = \"pnpm\" | \"npm\" | \"yarn\" | \"bun\";\n\nexport const PACKAGE_MANAGERS: PackageManager[] = [\"pnpm\", \"npm\", \"yarn\", \"bun\"];\n\nexport function isPackageManager(value: string): value is PackageManager {\n return (PACKAGE_MANAGERS as string[]).includes(value);\n}\n\n/**\n * Which package manager invoked this process.\n *\n * `npm_config_user_agent` is set by every one of them, and it is the only\n * reliable signal: someone running `pnpm create dowel-app` wants pnpm, and\n * asking them again is asking a question the environment already answered.\n */\nexport function detectPackageManager(): PackageManager {\n const agent = process.env.npm_config_user_agent ?? \"\";\n\n for (const candidate of PACKAGE_MANAGERS) {\n if (agent.startsWith(`${candidate}/`)) return candidate;\n }\n\n return \"npm\";\n}\n\nexport function installCommand(manager: PackageManager): string {\n return manager === \"npm\" ? \"npm install\" : `${manager} install`;\n}\n\nexport function runCommand(manager: PackageManager, script: string): string {\n return manager === \"npm\" ? `npm run ${script}` : `${manager} ${script}`;\n}\n\n/** The runner that executes a package's binary without installing it globally. */\nexport function dlx(manager: PackageManager): string[] {\n switch (manager) {\n case \"pnpm\":\n return [\"pnpm\", \"dlx\"];\n case \"yarn\":\n return [\"yarn\", \"dlx\"];\n case \"bun\":\n return [\"bunx\"];\n default:\n return [\"npx\", \"-y\"];\n }\n}\n\nexport function install(manager: PackageManager, cwd: string): void {\n const [command, ...args] = installCommand(manager).split(\" \");\n execFileSync(command ?? \"npm\", args, { cwd, stdio: \"inherit\" });\n}\n\n/** Runs the component CLI in the new project. */\nexport function runDowel(\n manager: PackageManager,\n cwd: string,\n cliPackage: string,\n args: string[],\n): void {\n const [command, ...runner] = dlx(manager);\n execFileSync(command ?? \"npx\", [...runner, cliPackage, ...args], { cwd, stdio: \"inherit\" });\n}\n","import pc from \"picocolors\";\n\n/**\n * All CLI output goes through here.\n *\n * A single place to route messages means the format stays consistent, and\n * anything that needs to change later — quiet mode, JSON output, writing to\n * stderr — changes in one file rather than in every command.\n */\nexport const logger = {\n info(message: string) {\n console.log(message);\n },\n success(message: string) {\n console.log(`${pc.green(\"✓\")} ${message}`);\n },\n warn(message: string) {\n console.warn(`${pc.yellow(\"!\")} ${message}`);\n },\n error(message: string) {\n console.error(`${pc.red(\"✕\")} ${message}`);\n },\n step(message: string) {\n console.log(`${pc.dim(\"·\")} ${message}`);\n },\n blank() {\n console.log(\"\");\n },\n};\n\nexport { pc };\n","import { branding } from \"./branding\";\n\n/**\n * What a template is, here.\n *\n * A directory of application files, plus a list of registry items to install\n * into it. The components are *not* in the template — they are fetched from the\n * registry at creation time by the same CLI a user would run themselves.\n *\n * That is the whole design. A template that carries its own copy of Button is a\n * copy that is wrong by the next release, and the person who generated from it\n * has no way to know. Fetching means a project created today is built from\n * today's registry, and means a template is a dozen files rather than a hundred.\n */\n\nexport interface Template {\n id: string;\n title: string;\n /** One line, shown in the picker. */\n description: string;\n /**\n * Template directories layered in order, so shared files are written once.\n * Later directories overwrite earlier ones.\n */\n layers: string[];\n /** Registry items installed with `add` after the files are written. */\n items: string[];\n /** Routes the template ships, for the \"what next\" summary. */\n routes: string[];\n}\n\nexport const TEMPLATES: Template[] = [\n {\n id: \"starter\",\n title: \"Starter\",\n description: `A Next.js app wired to ${branding.libraryName}: tokens, aliases and a landing page.`,\n layers: [\"base\", \"starter\"],\n items: [\"button\", \"card\", \"badge\"],\n routes: [\"/\"],\n },\n {\n id: \"saas\",\n title: \"SaaS\",\n description:\n \"Adds an application shell with dashboard, analytics, billing, settings and onboarding.\",\n layers: [\"base\", \"app-shell\", \"saas\"],\n items: [\"sidebar\", \"dashboard\", \"analytics\", \"billing\", \"settings\", \"onboarding\"],\n routes: [\"/\", \"/app\", \"/app/analytics\", \"/app/billing\", \"/app/settings\"],\n },\n {\n id: \"ai\",\n title: \"AI product\",\n description: \"Adds a chat surface, an agent console and a usage dashboard.\",\n layers: [\"base\", \"app-shell\", \"ai\"],\n items: [\"sidebar\", \"ai-chat\", \"agent-console\", \"ai-dashboard\"],\n routes: [\"/\", \"/app\", \"/app/agents\", \"/app/usage\"],\n },\n];\n\nexport function findTemplate(id: string): Template | undefined {\n return TEMPLATES.find((template) => template.id === id);\n}\n\n/** Presets the scaffolder offers, mirroring what the theme layer ships. */\nexport const THEMES = [\n \"default\",\n \"ocean\",\n \"emerald\",\n \"violet\",\n \"rose\",\n \"amber\",\n \"monochrome\",\n \"candy\",\n \"indigo\",\n \"blue\",\n \"red\",\n \"orange\",\n \"green\",\n] as const;\n\nexport type Theme = (typeof THEMES)[number];\n\nexport function isTheme(value: string): value is Theme {\n return (THEMES as readonly string[]).includes(value);\n}\n","import * as prompts from \"@clack/prompts\";\nimport { existsSync, mkdirSync, readdirSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { branding } from \"./branding\";\nimport { CreateError } from \"./lib/errors\";\nimport { copyLayer, isEmptyDirectory, type Replacements } from \"./lib/files\";\nimport {\n detectPackageManager,\n install,\n installCommand,\n isPackageManager,\n runCommand,\n runDowel,\n type PackageManager,\n} from \"./lib/pm\";\nimport { logger, pc } from \"./lib/logger\";\nimport { findTemplate, isTheme, TEMPLATES, THEMES, type Template } from \"./templates\";\n\nexport interface CreateOptions {\n /** Directory to create, relative to cwd or absolute. */\n directory?: string;\n template?: string;\n theme?: string;\n packageManager?: string;\n /** Accept every default and never prompt. */\n yes: boolean;\n skipInstall: boolean;\n /** Write files but do not fetch components. Mostly for tests. */\n skipComponents: boolean;\n cwd: string;\n}\n\n/** Where the shipped templates live, relative to the built entry point. */\nconst templatesRoot = join(dirname(fileURLToPath(import.meta.url)), \"..\", \"templates\");\n\n/**\n * npm's rules for a package name, which is what this becomes.\n *\n * Checked before anything is written rather than after: a directory created and\n * then abandoned because the name was rejected is worse than a question asked\n * twice.\n */\nexport function validateProjectName(name: string): string | undefined {\n if (name.length === 0) return \"Give the project a name.\";\n if (name.length > 214) return \"That is longer than npm allows for a package name.\";\n if (name.startsWith(\".\") || name.startsWith(\"_\")) {\n return \"A package name cannot start with a dot or an underscore.\";\n }\n if (name !== name.toLowerCase()) return \"A package name has to be lowercase.\";\n if (!/^[a-z0-9._-]+$/.test(name)) {\n return \"Use lowercase letters, digits, dots, hyphens and underscores only.\";\n }\n return undefined;\n}\n\n/** The last segment of a path, as a package name. */\nexport function projectNameFrom(directory: string): string {\n return directory.split(\"/\").filter(Boolean).pop() ?? \"app\";\n}\n\n/** The nav for the app shell, written into its layout. */\nfunction appLinks(template: Template): string {\n const labels: Record<string, string> = {\n \"/app\": template.id === \"ai\" ? \"Chat\" : \"Dashboard\",\n \"/app/analytics\": \"Analytics\",\n \"/app/billing\": \"Billing\",\n \"/app/settings\": \"Settings\",\n \"/app/agents\": \"Agents\",\n \"/app/usage\": \"Usage\",\n };\n\n const links = template.routes\n .filter((route) => route !== \"/\")\n .map((route) => ` { href: \"${route}\", label: \"${labels[route] ?? route}\" },`);\n\n return `[\\n${links.join(\"\\n\")}\\n]`;\n}\n\nexport async function create(options: CreateOptions): Promise<void> {\n const interactive = !options.yes;\n\n if (interactive) {\n prompts.intro(`${branding.libraryName} — create an app`);\n }\n\n const directory = await resolveDirectory(options, interactive);\n const target = isAbsolute(directory) ? directory : resolve(options.cwd, directory);\n const name = projectNameFrom(directory);\n\n const invalid = validateProjectName(name);\n if (invalid) throw new CreateError(invalid);\n\n if (!isEmptyDirectory(target)) {\n throw new CreateError(\n `${directory} already exists and is not empty.`,\n \"Choose another name, or empty the directory first.\",\n );\n }\n\n const template = await resolveTemplate(options, interactive);\n const theme = await resolveTheme(options, interactive);\n const manager = resolvePackageManager(options);\n\n const replacements: Replacements = {\n PROJECT_NAME: name,\n LIBRARY_NAME: branding.libraryName,\n CLI_PACKAGE: branding.cliPackage,\n DOCS_URL: branding.docsUrl,\n THEME: theme,\n APP_LINKS: appLinks(template),\n };\n\n mkdirSync(target, { recursive: true });\n\n const written: string[] = [];\n for (const layer of template.layers) {\n const from = join(templatesRoot, layer);\n if (!existsSync(from)) {\n throw new CreateError(\n `The ${layer} template is missing from this installation.`,\n \"Reinstall create-dowel-app, or report this if it persists.\",\n );\n }\n written.push(...copyLayer(from, target, replacements));\n }\n\n logger.blank();\n logger.success(`Created ${pc.bold(name)} from the ${pc.bold(template.title)} template.`);\n logger.info(pc.dim(` ${String(new Set(written).size)} files in ${directory}`));\n\n if (!options.skipInstall) {\n logger.blank();\n logger.step(`Installing dependencies with ${manager}`);\n install(manager, target);\n }\n\n if (!options.skipComponents) {\n logger.blank();\n logger.step(\"Fetching components from the registry\");\n\n // Through the real CLI, not a bundled copy. A template that carried its own\n // Button would be carrying whichever Button was current the day it was\n // written, and nothing would ever say so.\n runDowel(manager, target, branding.cliPackage, [\"init\", \"--yes\", \"--skip-install\"]);\n runDowel(manager, target, branding.cliPackage, [\n \"add\",\n ...template.items,\n \"--yes\",\n ...(options.skipInstall ? [\"--skip-install\"] : []),\n ]);\n }\n\n summarise({ directory, template, theme, manager, options });\n}\n\ninterface SummaryContext {\n directory: string;\n template: Template;\n theme: string;\n manager: PackageManager;\n options: CreateOptions;\n}\n\nfunction summarise({ directory, template, theme, manager, options }: SummaryContext): void {\n logger.blank();\n logger.success(\"Done.\");\n logger.blank();\n\n logger.info(pc.dim(\"Next:\"));\n logger.info(` cd ${directory}`);\n if (options.skipInstall) logger.info(` ${installCommand(manager)}`);\n logger.info(` ${runCommand(manager, \"dev\")}`);\n\n logger.blank();\n logger.info(pc.dim(\"Routes:\"));\n for (const route of template.routes) logger.info(` ${route}`);\n\n logger.blank();\n logger.info(\n pc.dim(\n `Theme: ${theme}. Change it on <html data-theme> in src/app/layout.tsx — no component file changes.`,\n ),\n );\n logger.info(\n pc.dim(`Teach your coding agent what is installed: npx ${branding.cliPackage} agents`),\n );\n}\n\nasync function resolveDirectory(options: CreateOptions, interactive: boolean): Promise<string> {\n if (options.directory) return options.directory;\n if (!interactive) {\n throw new CreateError(\n \"No directory given.\",\n \"Pass one, e.g. `create-dowel-app my-app`, or drop --yes to be asked.\",\n );\n }\n\n const answer = await prompts.text({\n message: \"Where should it go?\",\n placeholder: \"my-app\",\n defaultValue: \"my-app\",\n validate: (value) => validateProjectName(projectNameFrom(value || \"my-app\")),\n });\n\n if (prompts.isCancel(answer)) throw new CreateError(\"Cancelled — nothing was written.\");\n return answer || \"my-app\";\n}\n\nasync function resolveTemplate(\n options: CreateOptions,\n interactive: boolean,\n): Promise<Template> {\n if (options.template) {\n const found = findTemplate(options.template);\n if (!found) {\n throw new CreateError(\n `Unknown template \"${options.template}\".`,\n `Choose from: ${TEMPLATES.map((entry) => entry.id).join(\", \")}.`,\n );\n }\n return found;\n }\n\n if (!interactive) return TEMPLATES[0]!;\n\n const answer = await prompts.select({\n message: \"What are you building?\",\n options: TEMPLATES.map((entry) => ({\n value: entry.id,\n label: entry.title,\n hint: entry.description,\n })),\n });\n\n if (prompts.isCancel(answer)) throw new CreateError(\"Cancelled — nothing was written.\");\n return findTemplate(answer) ?? TEMPLATES[0]!;\n}\n\nasync function resolveTheme(options: CreateOptions, interactive: boolean): Promise<string> {\n if (options.theme) {\n if (!isTheme(options.theme)) {\n throw new CreateError(\n `Unknown theme \"${options.theme}\".`,\n `Choose from: ${THEMES.join(\", \")}.`,\n );\n }\n return options.theme;\n }\n\n if (!interactive) return \"default\";\n\n const answer = await prompts.select({\n message: \"Which theme?\",\n options: THEMES.map((entry) => ({\n value: entry,\n label: entry,\n hint:\n entry === \"monochrome\"\n ? \"No colour at all — a standing check that nothing relies on it\"\n : undefined,\n })),\n });\n\n if (prompts.isCancel(answer)) throw new CreateError(\"Cancelled — nothing was written.\");\n return answer;\n}\n\nfunction resolvePackageManager(options: CreateOptions): PackageManager {\n if (!options.packageManager) return detectPackageManager();\n\n if (!isPackageManager(options.packageManager)) {\n throw new CreateError(\n `Unknown package manager \"${options.packageManager}\".`,\n \"Choose from: pnpm, npm, yarn, bun.\",\n );\n }\n\n return options.packageManager;\n}\n\nexport { readdirSync };\n","#!/usr/bin/env node\nimport { readFileSync } from \"node:fs\";\n\nimport { Command } from \"commander\";\n\nimport { branding } from \"./branding\";\nimport { create } from \"./create\";\nimport { CreateError } from \"./lib/errors\";\nimport { logger, pc } from \"./lib/logger\";\nimport { TEMPLATES, THEMES } from \"./templates\";\n\nconst { version } = JSON.parse(\n readFileSync(new URL(\"../package.json\", import.meta.url), \"utf8\"),\n) as { version: string };\n\nconst program = new Command();\n\nprogram\n .name(\"create-dowel-app\")\n .description(\n `Creates a Next.js application wired to ${branding.libraryName}, with the components ` +\n `fetched from the registry rather than copied out of a template.`,\n )\n .version(version)\n .argument(\"[directory]\", \"where to create it\")\n .option(\"-t, --template <name>\", `one of: ${TEMPLATES.map((entry) => entry.id).join(\", \")}`)\n .option(\"--theme <name>\", `one of: ${THEMES.join(\", \")}`)\n .option(\"--pm <manager>\", \"pnpm, npm, yarn or bun; detected from how this was run\")\n .option(\"-y, --yes\", \"accept every default and never prompt\", false)\n .option(\"--skip-install\", \"write files but do not install dependencies\", false)\n .option(\"--skip-components\", \"write files but do not fetch components\", false)\n .action(\n async (\n directory: string | undefined,\n options: {\n template?: string;\n theme?: string;\n pm?: string;\n yes: boolean;\n skipInstall: boolean;\n skipComponents: boolean;\n },\n ) => {\n await create({\n directory,\n template: options.template,\n theme: options.theme,\n packageManager: options.pm,\n yes: options.yes,\n skipInstall: options.skipInstall,\n skipComponents: options.skipComponents,\n cwd: process.cwd(),\n });\n },\n );\n\n/**\n * A CreateError is a message for the person running the command; anything else\n * is a bug, and its stack trace is the useful part.\n */\nasync function main(): Promise<void> {\n try {\n await program.parseAsync(process.argv);\n } catch (error) {\n logger.blank();\n if (error instanceof CreateError) {\n logger.error(error.message);\n if (error.hint) logger.info(pc.dim(` ${error.hint}`));\n } else {\n logger.error(\"Something went wrong.\");\n logger.info(String(error instanceof Error ? (error.stack ?? error.message) : error));\n }\n logger.blank();\n process.exitCode = 1;\n }\n}\n\nvoid main();\n\nexport { create };\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-dowel-app",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Creates a Next.js application wired to Dowel: design tokens, path aliases and the blocks for the kind of product you are building, installed as source you own.",
|
|
6
6
|
"keywords": [
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"tsdown": "0.22.14",
|
|
56
56
|
"typescript": "6.0.3",
|
|
57
57
|
"vitest": "4.1.10",
|
|
58
|
-
"@dowel-ui/config": "0.
|
|
58
|
+
"@dowel-ui/config": "0.8.0"
|
|
59
59
|
},
|
|
60
60
|
"scripts": {
|
|
61
61
|
"build": "tsdown",
|