You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
`GeneratorOptions.appExtensions` is `AppExtensionType[]` where `AppExtensionType = 'custom-panel' | 'custom-modal'`. Check membership with `.includes('custom-panel')`, not boolean equality.
**There is no template directory.** Generators build file content as strings using `dedent()`, with conditional string interpolation for optional features (webhooks, app extension types). The `src/utils/writeFile.ts` utility writes files, creates parent directories, and auto-formats output with Prettier — generated code is formatted automatically without an explicit format step.
47
-
48
-
`app.ts` is the main example of the conditional pattern: imports and router mounts are included only when the relevant features are enabled, and the result is written once.
60
+
**There is no template directory.** Generators build file content as strings using `dedent()`, with conditional string interpolation for optional features. The `src/utils/writeFile.ts` utility writes files, creates parent directories, and auto-formats output with Prettier — generated code is formatted automatically without an explicit format step.
49
61
50
62
### Generated project structure
51
63
52
64
```
53
65
<project-name>/
54
-
backend/
55
-
oauth/ # Authorization redirect, callback, token exchange, refresh, state validation
56
-
pipedrive-client/ # Official API client wrapper with preconfigured auth
57
-
database/ # Tenant/account mapping, tokens, scopes, installation status
panel/ # Express router serving built frontend (custom-panel)
75
+
modal/ # Express router serving built frontend (custom-modal)
59
76
frontend/
60
-
app-extension-ui/ # Optional: React or Vanilla iframe UI with App Extensions SDK
77
+
app-extension-ui/ # Vite + React iframe UI (only when App Extensions selected)
61
78
.env.example
62
79
README.md
63
80
docker-compose.yml
64
81
marketplace-checklist.md
65
82
```
66
83
67
-
## Adding features
84
+
## App Extensions pattern
68
85
69
-
-**New prompt**: add `src/prompts/<feature>.ts` + `.test.ts`, export from `cli.ts`
70
-
-**New generator**: add `src/generators/node/<feature>.ts` + `.test.ts`, call from `nodeGenerator`
71
-
-**Modify generated scaffold**: edit template strings in the corresponding generator file
86
+
Each extension type (panel, modal) contributes a `ReactSnippetContribution` — an object with `{ sdkImports, handlers, buttons }` — that gets merged into the generated `App.tsx`. This lets panel.ts and modal.ts independently declare what SDK imports and JSX they need without knowing about each other.
87
+
88
+
When App Extensions are enabled, `docker-compose up --watch` starts both the Express backend and the Vite dev server in containers with Compose Watch for live code sync. The Vite server must be exposed via a public HTTPS tunnel and configured in Developer Hub as the iframe URL.
89
+
90
+
The backend serves the built frontend at `/extensions/panel` and `/extensions/modal` via Express static routing (using the shared `routerContent()` from `appExtensions/router.ts`). In production, `npm run build` builds both backend TypeScript and the Vite bundle.
- Use `RouterMountBuilder` (`src/utils/templates.ts`) to accumulate `app.use()` calls conditionally
97
116
- Use plain `dedent` for static content (YAML, JSON, `.env`, SQL)
98
117
99
-
## MVP Scope
100
-
101
-
The initial implementation targets:
102
-
-**Runtime**: Node.js + TypeScript
103
-
-**Backend**: Express or Fastify
104
-
-**Database**: Postgres via Docker Compose
105
-
-**Auth**: Full OAuth 2.0 install/callback/token-refresh flow
106
-
-**API client**: Pipedrive Node.js client wrapper
107
-
-**Frontend** (optional): React App Extensions UI
108
-
- Outputs `.env.example` and a Marketplace readiness checklist
118
+
## Adding features
109
119
110
-
PHP and MySQL/SQLite backends come after MVP. The PHP generator exists but throws "not yet implemented". App Extensions frontend is prompted but not yet generated.
120
+
-**New prompt**: add `src/prompts/<feature>.ts` + `.test.ts`, export from `cli.ts`
121
+
-**New generator**: add `src/generators/node/<feature>.ts` + `.test.ts`, call from `nodeGenerator`
122
+
-**New App Extension type**: add a file under `src/generators/node/appExtensions/` that exports an `async generate*` function and a `*ReactSnippets()` function returning `ReactSnippetContribution`, then wire it in `appExtensions.ts` and `frontend.ts`
123
+
-**Modify generated scaffold**: edit template strings in the corresponding generator file
111
124
112
125
## Core Modules
113
126
114
127
### OAuth (`backend/oauth/`)
115
128
Full OAuth 2.0: app registration guidance, authorization redirect, callback handling, token exchange, token refresh, state validation.
116
129
117
130
### Database (`backend/database/`)
118
-
Uses **Drizzle ORM** (`drizzle-orm` + `drizzle-kit`) for schema definition and migrations. Drizzle is chosen because it supports Postgres, MySQL, and SQLite with the same TypeScript API — matching the three database options the CLI offers — and produces readable schema files with no codegen step.
131
+
Uses **Drizzle ORM** (`drizzle-orm` + `drizzle-kit`) for schema definition and migrations. Supports Postgres, MySQL, and SQLite with the same TypeScript API.
Only generated when the user opts in. Iframe-based UI using the App Extensions SDK, supporting: initialization, resizing, modals, notifications/snackbars, theme handling.
142
+
Generated when the user selects `custom-panel` and/or `custom-modal`. Iframe-based React + Vite UI using the App Extensions SDK (`usePipedriveSdk` hook), with: SDK initialization, theme handling, resize, snackbar, confirmation dialog, signed token, and extension-type-specific actions (open modal from panel, close modal).
130
143
131
144
## Tests
132
145
133
-
Vitest. Tests generate files into a `tmpdir()/cpa-app-test` directory, read them back to verify content, and clean up in `afterEach`. Run a single test file:
134
-
135
-
```bash
136
-
npx vitest run src/generators/node/app.test.ts
137
-
```
146
+
Vitest. Tests generate files into a `tmpdir()/cpa-app-test` directory, read them back to verify content, and clean up in `afterEach`.
When App Extensions are selected, the generated project also includes a shared React iframe app for custom panels and custom modals. `docker-compose up --watch` starts the backend and Vite dev server in containers with Compose Watch. Local Developer Hub iframe URLs should point at an HTTPS tunnel to the Vite dev server, for example `https://<your-vite-tunnel>/extensions/panel` or `https://<your-vite-tunnel>/extensions/modal`. After `npm run build`, production iframe URLs can point at the backend-hosted `/extensions/panel` and `/extensions/modal` routes.
41
+
37
42
## Next steps after generation
38
43
39
44
```bash
40
45
cd<project-name>
41
46
cp .env.example .env
42
-
docker-compose up -d # if Postgres or MySQL was selected
47
+
docker-compose up -d db # if Postgres or MySQL was selected
43
48
npm install
44
49
npm run dev
45
50
```
46
51
52
+
If App Extensions were selected, use Compose Watch instead of the local dev server:
53
+
54
+
```bash
55
+
docker-compose up --watch
56
+
```
57
+
47
58
Fill in `PIPEDRIVE_CLIENT_ID`, `PIPEDRIVE_CLIENT_SECRET`, and `DATABASE_URL` in `.env`.
48
59
49
60
## Requirements
50
61
51
62
- Node.js 18+
52
-
- Docker (if using Postgresor MySQL)
63
+
- Docker (if using Postgres, MySQL, or App Extensions frontend development)
0 commit comments