AINATIVEM-41: CLI tool foundation — create-pipedrive-app scaffold#1
Conversation
There was a problem hiding this comment.
Pull request overview
This PR bootstraps the create-pipedrive-app CLI scaffold: interactive prompt flow, Node/TypeScript project generators, a formatting/write utility, and repo-level lint/test/CI configuration to validate generated output.
Changes:
- Added Clack-based prompt modules (project name, DB, app extensions, webhooks) with unit tests.
- Implemented a Node generator that writes a minimal Express/TS project scaffold, plus generator unit tests and an e2e
tsc --noEmitcheck. - Added repo tooling (Vitest, ESLint, Prettier, CI workflow) to support development and validation.
Reviewed changes
Copilot reviewed 31 out of 34 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| vitest.config.ts | Adds Vitest configuration for Node test environment. |
| tsconfig.json | Adds TypeScript compiler configuration for building the CLI. |
| src/utils/writeFile.ts | Introduces a Prettier-formatted file writer utility used by generators. |
| src/utils/writeFile.test.ts | Adds tests covering formatting behavior and fallback paths. |
| src/prompts/webhooks.ts | Adds a webhooks confirmation prompt with cancel handling. |
| src/prompts/webhooks.test.ts | Tests the webhooks prompt behavior (true/false/cancel). |
| src/prompts/projectName.ts | Adds project name prompt and basic validation. |
| src/prompts/projectName.test.ts | Tests project name prompt behavior and cancel handling. |
| src/prompts/database.ts | Adds database selection prompt (postgres/mysql/sqlite). |
| src/prompts/database.test.ts | Tests database selection prompt options and cancel handling. |
| src/prompts/appExtensions.ts | Adds app extensions prompt (confirm → multiselect) and cancel handling. |
| src/prompts/appExtensions.test.ts | Tests app extensions prompt flow and cancel handling. |
| src/generators/interface.ts | Defines generator options/types and generator interface. |
| src/generators/php/index.ts | Stubs a PHP generator placeholder throwing “not implemented”. |
| src/generators/node/webhooks.ts | Generates a stub webhooks router module. |
| src/generators/node/webhooks.test.ts | Tests webhooks generator output. |
| src/generators/node/oauth.ts | Generates a stub oauth router module. |
| src/generators/node/oauth.test.ts | Tests oauth generator output. |
| src/generators/node/database.ts | Generates a stub database module. |
| src/generators/node/database.test.ts | Tests database generator output. |
| src/generators/node/appExtensions.ts | Generates stub app-extension router modules based on selected types. |
| src/generators/node/appExtensions.test.ts | Tests conditional generation of app-extension stubs. |
| src/generators/node/app.ts | Generates Express app wiring with conditional imports/mounts. |
| src/generators/node/app.test.ts | Tests conditional imports/mounts in generated app.ts. |
| src/generators/node/index.ts | Orchestrates Node project generation and root config file generation. |
| src/generators/node/index.test.ts | Tests full/minimal generation and runs a nested npm install + tsc --noEmit e2e check. |
| src/cli.ts | Adds CLI entrypoint that runs prompts and invokes the Node generator. |
| package.json | Adds CLI package metadata, scripts, dependencies, and bin entry. |
| package-lock.json | Locks dependencies for reproducible installs in CI/dev. |
| eslint.config.js | Adds ESLint flat config using typescript-eslint. |
| .prettierrc | Adds Prettier configuration used by the repo (and potentially by generators). |
| .gitignore | Adds standard ignores for node/dist/env and docs artifacts. |
| CLAUDE.md | Adds contributor guidance and intended architecture notes. |
| .github/workflows/ci.yml | Adds CI workflow running install, lint, and tests on pushes/PRs. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| try { | ||
| const config = await resolveConfig(filePath); | ||
| formatted = await format(content, { singleQuote: true, ...config, filepath: filePath }); | ||
| } catch (error) { |
| const value = await clack.text({ | ||
| message: 'Project name?', | ||
| initialValue: initial, | ||
| validate: (v) => { | ||
| if (!v.trim()) return 'Project name is required'; | ||
| }, | ||
| }); |
| const projectName = await promptProjectName(process.argv[2]); | ||
| const database = await promptDatabase(); | ||
| const appExtensions = await promptAppExtensions(); | ||
| const webhooks = await promptWebhooks(); | ||
|
|
||
| const outputDir = join(process.cwd(), projectName); | ||
|
|
| it('generated project passes tsc --noEmit', async () => { | ||
| await nodeGenerator.generate(tmpDir, fullOptions); | ||
| execSync('npm install', { cwd: tmpDir, stdio: 'pipe' }); | ||
| expect(() => { | ||
| execSync('npx tsc --noEmit', { cwd: tmpDir, stdio: 'pipe' }); | ||
| }).not.toThrow(); | ||
| }, 60_000); |
| console.log(' npm run dev'); | ||
| } | ||
|
|
||
| main(); |
| The CLI asks for: | ||
| - Backend: Node.js/Express, Node.js/Fastify, or PHP/Laravel | ||
| - Database: Postgres, MySQL, or SQLite | ||
| - App Extensions frontend: React, Vanilla JS, or none | ||
| - Webhooks: Yes/No |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
dev app creation folder - app
|
|
||
| const app = express(); | ||
|
|
||
| app.use('/oauth', oauthRouter); |
There was a problem hiding this comment.
did we setup prettier for the cli project as well ? , these lines look a bit not aligned
There was a problem hiding this comment.
prettier does not format string literals. I will check for the solution that could be used here.
| @@ -0,0 +1,7 @@ | |||
| import type { Generator, GeneratorOptions } from '../interface.js'; | |||
There was a problem hiding this comment.
maybe lets remove the php generator placeholder since it's not in the scope of this mission
There was a problem hiding this comment.
I was thinking to leave it as a marketing before we implement it and show the structure of different generators we can add to the package 😺 we can remove it anytime
| }, | ||
| "dependencies": { | ||
| "@clack/prompts": "^0.9.0", | ||
| "fs-extra": "^11.2.0", |
There was a problem hiding this comment.
@dmitriyeff i think in newer versions of node they have promise based writeFile functions so maybe we don't need the fs-extra package ? , no strong opinion either way but would be nice if we can have one less dependency if possible
There was a problem hiding this comment.
will replace it 👍
Summary
create-pipedrive-appCLI tool: project scaffold, interactive prompts, programmatic code generators, and GitHub Actions CInpx create-pipedrive-app my-appcollects choices via Clack prompts (project name, database, App Extensions, webhooks) and generates a production-ready TypeScript projecttsc --noEmitout of the box — validated by an end-to-end test in the suiteWhat to review
Interactive prompts (
src/prompts/)process.exit(0)appExtensions.tshas a two-step flow: confirm → conditional multi-selectGenerator interface (
src/generators/interface.ts)GeneratorOptionsandGeneratorinterface shared by all generatorssrc/generators/php/index.ts) for a future ticketNode generator (
src/generators/node/)app.tsgenerator has conditional import/mount logic for webhooks, custom-panel, and custom-modal — worth checking the string interpolation approachindex.tsorchestrator conditionally skips webhooks/app-extensions generation and docker-compose based on user choicespackage.json,tsconfig.json,.env.example,docker-compose.yml(postgres/mysql only)writeFileutility (src/utils/writeFile.ts).env.example)CI (
.github/workflows/ci.yml)npm ci→npm run lint→npm teston every push and PR to masterWhat to test
To test the CLI interactively:
Then answer the prompts and inspect the generated folder — it should contain a working TypeScript Express project that passes
tsc --noEmitafternpm install.Example:

Notes
"files": ["dist"]topackage.jsonand a#!/usr/bin/env nodeshebang tosrc/cli.ts