@donotdev/cli 0.0.13 → 0.0.14
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/dependencies-matrix.json +2 -2
- package/dist/bin/commands/agent-setup.d.ts +6 -0
- package/dist/bin/commands/agent-setup.d.ts.map +1 -0
- package/dist/bin/commands/agent-setup.js +623 -0
- package/dist/bin/commands/agent-setup.js.map +1 -0
- package/dist/bin/commands/build.js +13 -12
- package/dist/bin/commands/bump.js +70 -28
- package/dist/bin/commands/cacheout.js +13 -12
- package/dist/bin/commands/create-app.js +53 -151
- package/dist/bin/commands/create-project.js +72 -166
- package/dist/bin/commands/deploy.js +16 -15
- package/dist/bin/commands/dev.js +13 -12
- package/dist/bin/commands/emu.js +13 -12
- package/dist/bin/commands/format.js +13 -12
- package/dist/bin/commands/lint.js +13 -12
- package/dist/bin/commands/preview.js +13 -12
- package/dist/bin/commands/sync-secrets.js +13 -12
- package/dist/bin/commands/wai.js +7397 -11
- package/dist/index.js +74 -55
- package/package.json +1 -1
- package/templates/root-consumer/.claude/commands/brainstorm.md.example +1 -1
- package/templates/root-consumer/.claude/commands/build.md.example +1 -1
- package/templates/root-consumer/.claude/commands/design.md.example +1 -1
- package/templates/root-consumer/.claude/commands/polish.md.example +1 -1
- package/templates/root-consumer/.dndev/args.json.example +6 -0
- package/templates/root-consumer/.gemini/settings.json.example +2 -2
- package/templates/root-consumer/AI.md.example +25 -14
- package/templates/root-consumer/CLAUDE.md.example +10 -4
- package/templates/root-consumer/guides/dndev/AGENT_START_HERE.md.example +34 -0
- package/templates/root-consumer/guides/dndev/GOTCHAS.md.example +186 -0
- package/templates/root-consumer/guides/dndev/INDEX.md.example +1 -0
- package/templates/root-consumer/guides/dndev/SETUP_FUNCTIONS.md.example +12 -7
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# Framework Gotchas
|
|
2
|
+
|
|
3
|
+
**Common mistakes. Read before coding. Phase tags show when each matters most.**
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Imports [Phase 1, 2, 3]
|
|
8
|
+
|
|
9
|
+
**Server code MUST use `/server` imports — client imports crash on deploy.**
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
// ✅ CORRECT
|
|
13
|
+
import { getFirebaseAdminFirestore } from '@donotdev/firebase/server';
|
|
14
|
+
import { handleError } from '@donotdev/core/server';
|
|
15
|
+
|
|
16
|
+
// ❌ WRONG - crashes on deploy
|
|
17
|
+
import { getFirestore } from '@donotdev/firebase';
|
|
18
|
+
import { handleError } from '@donotdev/core';
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**Rule:** Always use `/server` suffix for `@donotdev/firebase/server`, `@donotdev/core/server`, `@donotdev/utils/server`.
|
|
22
|
+
|
|
23
|
+
**ESM only — never use `require()`.**
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
// ❌ WRONG
|
|
27
|
+
const { something } = require('@donotdev/package');
|
|
28
|
+
|
|
29
|
+
// ✅ CORRECT
|
|
30
|
+
import { something } from '@donotdev/package';
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Import ordering is mandatory:**
|
|
34
|
+
1. React (values, then types)
|
|
35
|
+
2. Other vendors (values, then types)
|
|
36
|
+
3. `@donotdev/*` packages (values, then types)
|
|
37
|
+
4. Relative imports (values, then types)
|
|
38
|
+
|
|
39
|
+
One line for values, one line for types. Blank line between categories.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Routing [Phase 1, 3]
|
|
44
|
+
|
|
45
|
+
**Never import from `react-router-dom` — use framework routing.**
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
// ❌ WRONG - breaks framework features
|
|
49
|
+
import { Link, useNavigate, useParams } from 'react-router-dom';
|
|
50
|
+
|
|
51
|
+
// ✅ CORRECT
|
|
52
|
+
import { Link, useNavigate, useParams } from '@donotdev/ui/routing';
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Routes are auto-discovered** from `src/pages/*Page.tsx` with `pageMeta`. Don't use `<Routes>`, `<Route>`, or manual `<Outlet />`.
|
|
56
|
+
|
|
57
|
+
**Use `useRouteParam('id')` for typed route params** — not `useParams()` from react-router-dom.
|
|
58
|
+
|
|
59
|
+
**Navigation is auto-built.** Use `<DnDevNavigationMenu>` or `useNavigationItems()`. Don't build nav manually — you lose auth filtering and route discovery.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Styling [Phase 3, 4]
|
|
64
|
+
|
|
65
|
+
**No inline `fontSize` or `font-size` — use `Text` level prop.**
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
// ❌ WRONG
|
|
69
|
+
<Text style={{ fontSize: '18px' }}>Title</Text>
|
|
70
|
+
|
|
71
|
+
// ✅ CORRECT
|
|
72
|
+
<Text level="h2">Title</Text>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Levels: `h1`, `h2`, `h3`, `h4`, `body`, `small`, `caption`. Limit to 2–3 levels per page.
|
|
76
|
+
|
|
77
|
+
**RTL: Always use `start`/`end` — never `left`/`right`.**
|
|
78
|
+
|
|
79
|
+
```css
|
|
80
|
+
/* ❌ WRONG - breaks RTL */
|
|
81
|
+
text-align: left;
|
|
82
|
+
|
|
83
|
+
/* ✅ CORRECT - works in both LTR and RTL */
|
|
84
|
+
text-align: start;
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Same for inline styles: `textAlign: 'start'` not `textAlign: 'left'`. Same for data attributes: `data-text-align="start|center|end"`.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Components [Phase 3]
|
|
92
|
+
|
|
93
|
+
**Always `lookup_symbol` before using any `@donotdev` component.** Never guess props.
|
|
94
|
+
|
|
95
|
+
Common wrong props:
|
|
96
|
+
- `Button`: no `size`, `tone`, `gap` — use `variant`, `display`
|
|
97
|
+
- `Text`: no `size`, `tone`, `color` — use `level`, `variant`
|
|
98
|
+
- `Stack`: no `spacing`, `size` — use `gap`
|
|
99
|
+
- `Card`: no `padding`, `margin`, `size` — use `title`, `subtitle`, `content`, `footer`
|
|
100
|
+
- `Grid`: no `columns` — use `cols`
|
|
101
|
+
|
|
102
|
+
**If you can't do it with framework components:** Stop. Tell the user what's missing. Don't invent custom workarounds.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## CRUD [Phase 2, 3]
|
|
107
|
+
|
|
108
|
+
**Hidden fields are auto-added by `defineEntity()` — don't define them manually:**
|
|
109
|
+
- `id`, `createdAt`, `updatedAt`, `createdById`, `updatedById`, `status`
|
|
110
|
+
|
|
111
|
+
**Scope field is auto-added** when `scope` is configured. Don't manually define the scope field (e.g., `companyId`).
|
|
112
|
+
|
|
113
|
+
**Custom form fields MUST use framework's `useController`:**
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
// ❌ WRONG
|
|
117
|
+
import { useController } from 'react-hook-form';
|
|
118
|
+
|
|
119
|
+
// ✅ CORRECT
|
|
120
|
+
import { useController } from '@donotdev/crud';
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**Form components receive `control` prop, not `field` prop.**
|
|
124
|
+
|
|
125
|
+
**Price field is structured:** `{ amount, currency, vatIncluded, discountPercent }`. Don't store computed discount amounts.
|
|
126
|
+
|
|
127
|
+
**File uploads are deferred** — files upload on form submit, not on selection. Images show optimistic blob URLs.
|
|
128
|
+
|
|
129
|
+
**Entity namespace defaults to `entity-{name}`** (lowercase). Translation files must match: `locales/entity-product_en.json`.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Functions [Phase 3, 4]
|
|
134
|
+
|
|
135
|
+
**Use `createFunction` for custom functions — 3 params, everything included:**
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
import { createFunction } from '@donotdev/functions/firebase';
|
|
139
|
+
|
|
140
|
+
export const myFunction = createFunction(schema, 'operation_name', async (data, { uid }) => {
|
|
141
|
+
// Your logic
|
|
142
|
+
});
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
**Use `createBaseFunction` only when you need custom config** (memory, timeout, region override).
|
|
146
|
+
|
|
147
|
+
**Deploy with `dndev deploy`** — not `firebase deploy`. Manual deploy causes CORS 403 on preflight because Cloud Run blocks unauthenticated OPTIONS by default.
|
|
148
|
+
|
|
149
|
+
**Naming:** Export in camelCase (`getDashboardMetrics`), operation ID in snake_case (`get_dashboard_metrics`).
|
|
150
|
+
|
|
151
|
+
**CRUD functions are one-liner:** `export const crud = createCrudFunctions(entities);` — generates all CRUD endpoints per entity. Access controlled via `entity.access`.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## i18n [Phase 3, 4]
|
|
156
|
+
|
|
157
|
+
**Phase 3: hardcode strings. Phase 4: add translations.** Don't i18n too early.
|
|
158
|
+
|
|
159
|
+
**Two loading strategies:**
|
|
160
|
+
- **Eager** (always loaded): `src/locales/common_en.json` — navigation, buttons, common UI
|
|
161
|
+
- **Lazy** (loaded per page): `src/pages/locales/home_en.json` — page-specific content
|
|
162
|
+
|
|
163
|
+
**Status field translations** fall back: `entity-{name}` namespace → `crud` namespace.
|
|
164
|
+
|
|
165
|
+
**Rich text uses `<Trans>` component** with supported tags only: `<accent>`, `<primary>`, `<muted>`, `<success>`, `<warning>`, `<error>`, `<bold>`, `<code>`.
|
|
166
|
+
|
|
167
|
+
**Array translations use `tList`:**
|
|
168
|
+
```tsx
|
|
169
|
+
import { tList } from '@donotdev/ui';
|
|
170
|
+
<Card content={tList(t, 'features.items', 4)} />
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Dependencies [Phase 1]
|
|
176
|
+
|
|
177
|
+
**Apps don't declare bundled deps.** Framework packages (`@donotdev/*`) provide everything. Don't add `react-router-dom`, `react-hook-form`, `valibot`, etc. to app's `package.json` — they come through framework deps.
|
|
178
|
+
|
|
179
|
+
**Environment variables:**
|
|
180
|
+
- Client: `apps/my-app/.env` (prefix with `VITE_*`)
|
|
181
|
+
- Server: `functions/.env` (secrets: `STRIPE_*`, OAuth tokens)
|
|
182
|
+
- Local overrides: `.env.local` (gitignored)
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
**When in doubt: search the codebase first, ask the user second, never guess.**
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
## Getting Started
|
|
10
10
|
|
|
11
11
|
- [ENV_SETUP.md](./ENV_SETUP.md) - **START HERE** — Full onboarding flow (install → firebase → deploy)
|
|
12
|
+
- [GOTCHAS.md](./GOTCHAS.md) - **Common mistakes & pitfalls** (phase-tagged, read before coding)
|
|
12
13
|
- [SETUP_FIREBASE.md](./SETUP_FIREBASE.md) - Firebase project setup (`dndev firebase:setup`)
|
|
13
14
|
- [SETUP_TESTING.md](./SETUP_TESTING.md) - Test generation (Phase 4)
|
|
14
15
|
|
|
@@ -47,21 +47,26 @@ export const crud = createCrudFunctions(entities);
|
|
|
47
47
|
|
|
48
48
|
## Custom Functions
|
|
49
49
|
|
|
50
|
-
**
|
|
50
|
+
**Use `createFunction` — handles config, validation, auth, rate limiting, metrics automatically:**
|
|
51
51
|
|
|
52
52
|
```typescript
|
|
53
|
-
import
|
|
54
|
-
import {
|
|
53
|
+
import * as v from 'valibot';
|
|
54
|
+
import { createFunction } from '@donotdev/functions/firebase';
|
|
55
55
|
import { getFirebaseAdminFirestore } from '@donotdev/firebase/server';
|
|
56
|
-
import { handleError } from '@donotdev/core/server';
|
|
57
56
|
|
|
58
|
-
|
|
57
|
+
const schema = v.object({ productId: v.string() });
|
|
58
|
+
|
|
59
|
+
export const getProductDetails = createFunction(schema, 'get_product_details', async (data, { uid }) => {
|
|
59
60
|
const db = getFirebaseAdminFirestore();
|
|
60
|
-
|
|
61
|
-
return
|
|
61
|
+
const doc = await db.collection('products').doc(data.productId).get();
|
|
62
|
+
return doc.data();
|
|
62
63
|
});
|
|
63
64
|
```
|
|
64
65
|
|
|
66
|
+
**That's it.** Rate limiting, metrics, auth, schema validation — all included by default. No config needed.
|
|
67
|
+
|
|
68
|
+
**Advanced:** Use `createBaseFunction` if you need custom config (memory, timeout, region override).
|
|
69
|
+
|
|
65
70
|
---
|
|
66
71
|
|
|
67
72
|
## Post-Deployment: Cloud Run IAM
|