@devwithbobby/loops 0.1.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/.changeset/README.md +8 -0
- package/.changeset/config.json +14 -0
- package/.config/commitlint.config.ts +11 -0
- package/.config/lefthook.yml +11 -0
- package/.github/workflows/release.yml +52 -0
- package/.github/workflows/test-and-lint.yml +39 -0
- package/README.md +517 -0
- package/biome.json +45 -0
- package/bun.lock +1166 -0
- package/bunfig.toml +7 -0
- package/convex.json +3 -0
- package/example/CLAUDE.md +106 -0
- package/example/README.md +21 -0
- package/example/bun-env.d.ts +17 -0
- package/example/convex/_generated/api.d.ts +53 -0
- package/example/convex/_generated/api.js +23 -0
- package/example/convex/_generated/dataModel.d.ts +60 -0
- package/example/convex/_generated/server.d.ts +149 -0
- package/example/convex/_generated/server.js +90 -0
- package/example/convex/convex.config.ts +7 -0
- package/example/convex/example.ts +76 -0
- package/example/convex/schema.ts +3 -0
- package/example/convex/tsconfig.json +34 -0
- package/example/src/App.tsx +185 -0
- package/example/src/frontend.tsx +39 -0
- package/example/src/index.css +15 -0
- package/example/src/index.html +12 -0
- package/example/src/index.tsx +19 -0
- package/example/tsconfig.json +28 -0
- package/package.json +95 -0
- package/prds/CHANGELOG.md +38 -0
- package/prds/CLAUDE.md +408 -0
- package/prds/CONTRIBUTING.md +274 -0
- package/prds/ENV_SETUP.md +222 -0
- package/prds/MONITORING.md +301 -0
- package/prds/RATE_LIMITING.md +412 -0
- package/prds/SECURITY.md +246 -0
- package/renovate.json +32 -0
- package/src/client/index.ts +530 -0
- package/src/client/types.ts +64 -0
- package/src/component/_generated/api.d.ts +55 -0
- package/src/component/_generated/api.js +23 -0
- package/src/component/_generated/dataModel.d.ts +60 -0
- package/src/component/_generated/server.d.ts +149 -0
- package/src/component/_generated/server.js +90 -0
- package/src/component/convex.config.ts +27 -0
- package/src/component/lib.ts +1125 -0
- package/src/component/schema.ts +17 -0
- package/src/component/tables/contacts.ts +16 -0
- package/src/component/tables/emailOperations.ts +22 -0
- package/src/component/validators.ts +39 -0
- package/src/utils.ts +6 -0
- package/test/client/_generated/_ignore.ts +1 -0
- package/test/client/index.test.ts +65 -0
- package/test/client/setup.test.ts +54 -0
- package/test/component/lib.test.ts +225 -0
- package/test/component/setup.test.ts +21 -0
- package/tsconfig.build.json +20 -0
- package/tsconfig.json +22 -0
package/prds/CLAUDE.md
ADDED
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
This is a **Convex component template** for building reusable Convex components. It uses:
|
|
8
|
+
- **Bun** for package management, testing, and development
|
|
9
|
+
- **Biome** for linting and formatting
|
|
10
|
+
- **convex-test** for testing Convex functions
|
|
11
|
+
- TypeScript with strict mode enabled
|
|
12
|
+
|
|
13
|
+
## Key Commands
|
|
14
|
+
|
|
15
|
+
### Development
|
|
16
|
+
```sh
|
|
17
|
+
bun run dev # Start both backend and frontend (with build watcher)
|
|
18
|
+
bun run dev:backend # Start Convex dev server with live component sources and typechecking
|
|
19
|
+
bun run dev:frontend # Start example frontend (Bun.serve with hot reload)
|
|
20
|
+
bun run build # Build TypeScript for distribution
|
|
21
|
+
bun run build:watch # Watch and rebuild on changes
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Testing
|
|
25
|
+
```sh
|
|
26
|
+
bun test # Run all tests
|
|
27
|
+
bun test --watch # Watch mode for continuous testing
|
|
28
|
+
bun test --coverage # Generate code coverage reports
|
|
29
|
+
bun test --bail # Stop after first failure
|
|
30
|
+
bun test -t "pattern" # Filter tests by name pattern
|
|
31
|
+
CLAUDECODE=1 bun test # AI-friendly quiet output (only shows failures)
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Linting and Formatting
|
|
35
|
+
```sh
|
|
36
|
+
bun run lint # Lint the codebase (Biome)
|
|
37
|
+
bun run lint:fix # Auto-fix linting issues
|
|
38
|
+
bun run format # Format code with Biome
|
|
39
|
+
bun run check # Run both lint and format checks
|
|
40
|
+
bun run check:fix # Auto-fix both lint and format issues
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Versioning and Releases
|
|
44
|
+
```sh
|
|
45
|
+
bun run changeset # Add a new changeset (run when making user-facing changes)
|
|
46
|
+
bun run ci:version # Update versions and changelogs (usually automated by GitHub Actions)
|
|
47
|
+
bun run ci:publish # Publish to npm (usually automated by GitHub Actions)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Project Structure
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
src/
|
|
54
|
+
component/ # The Convex component source code
|
|
55
|
+
convex.config.ts # Component configuration (exported via package.json)
|
|
56
|
+
schema.ts # Convex schema definition
|
|
57
|
+
lib.ts # Component functions (queries, mutations)
|
|
58
|
+
_generated/ # Auto-generated Convex types (gitignored)
|
|
59
|
+
|
|
60
|
+
client/ # Client library (runs in app context, not component)
|
|
61
|
+
index.ts # Helper class for easier component interaction
|
|
62
|
+
types.ts # Type utilities for component API
|
|
63
|
+
|
|
64
|
+
react/ # React hooks and components (optional)
|
|
65
|
+
index.ts # React hooks for using the component
|
|
66
|
+
|
|
67
|
+
test/
|
|
68
|
+
component/ # Component tests (separate from source to avoid bundling)
|
|
69
|
+
setup.test.ts # Test setup with module auto-discovery
|
|
70
|
+
*.test.ts # Unit tests for the component
|
|
71
|
+
|
|
72
|
+
client/ # Client library tests
|
|
73
|
+
setup.test.ts # Test setup that registers the component
|
|
74
|
+
*.test.ts # Unit tests for the client library
|
|
75
|
+
|
|
76
|
+
example/
|
|
77
|
+
convex/ # Example app that uses the component
|
|
78
|
+
convex.config.ts # Example app configuration that imports the component
|
|
79
|
+
schema.ts # Example app schema
|
|
80
|
+
example.ts # Example usage of the client library
|
|
81
|
+
_generated/ # Auto-generated Convex types (gitignored)
|
|
82
|
+
|
|
83
|
+
src/ # Example frontend (Bun.serve + React)
|
|
84
|
+
index.tsx # Bun server with hot reload
|
|
85
|
+
frontend.tsx # React entry point
|
|
86
|
+
App.tsx # Main React component
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Architecture
|
|
90
|
+
|
|
91
|
+
### Convex Component Pattern
|
|
92
|
+
This project follows the **Convex component architecture** with a three-layer structure:
|
|
93
|
+
|
|
94
|
+
1. **Component Layer** (`src/component/`):
|
|
95
|
+
- Defines the component with `defineComponent("loopsComponent")`
|
|
96
|
+
- Contains the actual Convex functions (queries, mutations, actions)
|
|
97
|
+
- Has isolated tables, file storage, and scheduled functions
|
|
98
|
+
- Exported via package.json `"./convex.config"` with `@convex-dev/component-source` condition
|
|
99
|
+
|
|
100
|
+
2. **Client Library Layer** (`src/client/`):
|
|
101
|
+
- Runs in the **app context** (not the component)
|
|
102
|
+
- Provides a helper class that wraps component API calls
|
|
103
|
+
- Can access `process.env` and `ctx.auth` from the app
|
|
104
|
+
- Exported via package.json `"."` (main entry point)
|
|
105
|
+
- Example: `LoopsComponent` class with `.add()` and `.count()` methods
|
|
106
|
+
|
|
107
|
+
3. **React Layer** (`src/react/`):
|
|
108
|
+
- Optional React hooks and components
|
|
109
|
+
- Uses the client library internally
|
|
110
|
+
- Provides optimistic updates and loading states
|
|
111
|
+
- Exported via package.json `"./react"`
|
|
112
|
+
- Example: `useLoopsComponent()` hook
|
|
113
|
+
|
|
114
|
+
**Usage Flow**:
|
|
115
|
+
```typescript
|
|
116
|
+
// 1. App mounts the component (example/convex/convex.config.ts)
|
|
117
|
+
import component from "robertalv/loops-component/convex.config"
|
|
118
|
+
app.use(component)
|
|
119
|
+
|
|
120
|
+
// 2. App creates client wrapper (example/convex/example.ts)
|
|
121
|
+
import { LoopsComponent } from "robertalv/loops-component"
|
|
122
|
+
const counter = new LoopsComponent(components.loopsComponent)
|
|
123
|
+
export const { add, count } = counter.api()
|
|
124
|
+
|
|
125
|
+
// 3. React component uses the hook (example/src/App.tsx)
|
|
126
|
+
import { useLoopsComponent } from "robertalv/loops-component/react"
|
|
127
|
+
const { count, add } = useLoopsComponent(api.example, "myCounter")
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Testing Pattern
|
|
131
|
+
This project uses `convex-test` with Bun's test runner. **Tests are kept separate from the component source** to prevent Convex from trying to bundle them during development.
|
|
132
|
+
|
|
133
|
+
#### Component Tests (`test/component/`)
|
|
134
|
+
Tests the component functions in isolation.
|
|
135
|
+
|
|
136
|
+
**Setup** (`test/component/setup.test.ts`):
|
|
137
|
+
- Auto-discovers all `.ts` files from `src/component/` using `Bun.Glob`
|
|
138
|
+
- Creates a `modules` map for convex-test
|
|
139
|
+
- Exports a `convexTest()` helper function
|
|
140
|
+
- Preloaded by Bun (configured in `bunfig.toml`)
|
|
141
|
+
|
|
142
|
+
**Example**:
|
|
143
|
+
```ts
|
|
144
|
+
import { test, expect } from "bun:test";
|
|
145
|
+
import { api } from "../../src/component/_generated/api";
|
|
146
|
+
import { convexTest } from "./setup.test";
|
|
147
|
+
|
|
148
|
+
test("component function works", async () => {
|
|
149
|
+
const t = convexTest();
|
|
150
|
+
const result = await t.query(api.lib.greet, { name: "Alice" });
|
|
151
|
+
expect(result).toBe("Hello, Alice!");
|
|
152
|
+
});
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
#### Client Library Tests (`test/client/`)
|
|
156
|
+
Tests the client library that wraps the component. This is more complex because it requires **registering the component**.
|
|
157
|
+
|
|
158
|
+
**Setup** (`test/client/setup.test.ts`):
|
|
159
|
+
- Auto-discovers client test files from `test/client/`
|
|
160
|
+
- Auto-discovers component files from `src/component/`
|
|
161
|
+
- Exports `initConvexTest()` that creates a test instance and registers the component
|
|
162
|
+
- Exports a mock `components` object for type-safe testing
|
|
163
|
+
|
|
164
|
+
**Example**:
|
|
165
|
+
```ts
|
|
166
|
+
import { test, expect } from "bun:test";
|
|
167
|
+
import { LoopsComponent } from "../../src/client/index.js";
|
|
168
|
+
import { components, initConvexTest } from "./setup.test.js";
|
|
169
|
+
|
|
170
|
+
test("client library works", async () => {
|
|
171
|
+
const t = initConvexTest();
|
|
172
|
+
const counter = new LoopsComponent(components.loopsComponent);
|
|
173
|
+
|
|
174
|
+
await t.run(async (ctx) => {
|
|
175
|
+
await counter.add(ctx, "test");
|
|
176
|
+
const count = await counter.count(ctx, "test");
|
|
177
|
+
expect(count).toBe(1);
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**Key difference**: Client tests use `t.registerComponent()` to mount the component within the test environment, simulating the real app usage pattern.
|
|
183
|
+
|
|
184
|
+
### Example App Frontend
|
|
185
|
+
The example app uses **Bun.serve** with HTML imports for a lightweight development experience.
|
|
186
|
+
|
|
187
|
+
**Architecture**:
|
|
188
|
+
- `example/src/index.tsx` - Bun server that serves HTML with hot reload
|
|
189
|
+
- `example/src/frontend.tsx` - React entry point that bootstraps the app
|
|
190
|
+
- `example/src/App.tsx` - Main React component using the component hooks
|
|
191
|
+
|
|
192
|
+
**Key features**:
|
|
193
|
+
- HTML files can directly import `.tsx` files (no bundler config needed)
|
|
194
|
+
- Hot module reloading via `bun --hot`
|
|
195
|
+
- Tailwind CSS via `bun-plugin-tailwind`
|
|
196
|
+
- Convex environment variables automatically passed through
|
|
197
|
+
|
|
198
|
+
**Running the frontend**:
|
|
199
|
+
```sh
|
|
200
|
+
bun run dev:frontend # or: cd example && bun --hot src/index.tsx
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Code Style
|
|
204
|
+
|
|
205
|
+
### Biome Configuration
|
|
206
|
+
- **Indentation**: Tabs (not spaces)
|
|
207
|
+
- **Quotes**: Double quotes for JavaScript/TypeScript
|
|
208
|
+
- **Imports**: Auto-organized via Biome assist
|
|
209
|
+
- **Ignores**: `_generated` directories are excluded from linting/formatting
|
|
210
|
+
|
|
211
|
+
### TypeScript Configuration
|
|
212
|
+
- Strict mode enabled with additional checks:
|
|
213
|
+
- `noUncheckedIndexedAccess: true`
|
|
214
|
+
- `noImplicitOverride: true`
|
|
215
|
+
- `noFallthroughCasesInSwitch: true`
|
|
216
|
+
- Module resolution: `bundler` mode
|
|
217
|
+
- JSX: `react-jsx` (automatic runtime)
|
|
218
|
+
|
|
219
|
+
## Package Exports Configuration
|
|
220
|
+
|
|
221
|
+
The `package.json` defines three entry points using conditional exports:
|
|
222
|
+
|
|
223
|
+
```json
|
|
224
|
+
{
|
|
225
|
+
"exports": {
|
|
226
|
+
".": {
|
|
227
|
+
"@convex-dev/component-source": "./src/client/index.ts",
|
|
228
|
+
"types": "./dist/client/index.d.ts",
|
|
229
|
+
"default": "./dist/client/index.js"
|
|
230
|
+
},
|
|
231
|
+
"./convex.config": {
|
|
232
|
+
"@convex-dev/component-source": "./src/component/convex.config.ts",
|
|
233
|
+
"types": "./dist/component/convex.config.d.ts",
|
|
234
|
+
"default": "./dist/component/convex.config.js"
|
|
235
|
+
},
|
|
236
|
+
"./react": {
|
|
237
|
+
"@convex-dev/component-source": "./src/react/index.ts",
|
|
238
|
+
"types": "./dist/react/index.d.ts",
|
|
239
|
+
"default": "./dist/react/index.js"
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
**`@convex-dev/component-source` condition**:
|
|
246
|
+
- Used during development with `--live-component-sources` flag
|
|
247
|
+
- Points directly to TypeScript source files for hot reloading
|
|
248
|
+
- Bypasses the built `dist/` directory for faster iteration
|
|
249
|
+
|
|
250
|
+
**Why this matters**:
|
|
251
|
+
- Production: Apps install the package and use built `.js` files from `dist/`
|
|
252
|
+
- Development: The `--live-component-sources` flag makes Convex use `.ts` files directly
|
|
253
|
+
- Type checking: TypeScript uses the `.d.ts` files from `dist/`
|
|
254
|
+
|
|
255
|
+
## Important Notes
|
|
256
|
+
|
|
257
|
+
- **Generated files**: Never edit files in `_generated/` directories - they are auto-generated by Convex
|
|
258
|
+
- **Test files**: Place all test files in `test/component/` or `test/client/` directories (separate from `src/`) to prevent Convex from bundling them during development
|
|
259
|
+
- **Component name**: Currently set to `"loopsComponent"` in convex.config.ts - change this for your component
|
|
260
|
+
- **Live reloading**: The `--live-component-sources` flag enables hot-reloading during development
|
|
261
|
+
- **Build exclusion**: Test files are excluded from the TypeScript build via `tsconfig.build.json`
|
|
262
|
+
- **Client vs Component**: Remember that `src/client/` runs in the app context and can access env vars, while `src/component/` is isolated
|
|
263
|
+
|
|
264
|
+
## Release Workflow (Changesets)
|
|
265
|
+
|
|
266
|
+
This project uses [Changesets](https://github.com/changesets/changesets) for versioning and publishing automation.
|
|
267
|
+
|
|
268
|
+
### When to Add a Changeset
|
|
269
|
+
|
|
270
|
+
Add a changeset whenever you make user-facing changes:
|
|
271
|
+
- ✅ New features (minor bump)
|
|
272
|
+
- ✅ Bug fixes (patch bump)
|
|
273
|
+
- ✅ Breaking changes (major bump)
|
|
274
|
+
- ✅ API changes
|
|
275
|
+
- ✅ Dependency updates that affect consumers
|
|
276
|
+
|
|
277
|
+
Don't add a changeset for:
|
|
278
|
+
- ❌ Documentation-only changes
|
|
279
|
+
- ❌ Test-only changes
|
|
280
|
+
- ❌ Internal refactoring with no API changes
|
|
281
|
+
- ❌ CI/build configuration updates
|
|
282
|
+
- ❌ Dev dependency updates
|
|
283
|
+
|
|
284
|
+
### Adding a Changeset (For Contributors)
|
|
285
|
+
|
|
286
|
+
1. Make your code changes
|
|
287
|
+
2. Run the changeset command:
|
|
288
|
+
```sh
|
|
289
|
+
bun run changeset
|
|
290
|
+
```
|
|
291
|
+
3. Follow the prompts:
|
|
292
|
+
- Select version bump type (patch, minor, or major)
|
|
293
|
+
- Write a summary of your changes
|
|
294
|
+
4. A markdown file will be created in `.changeset/` directory
|
|
295
|
+
5. Commit both your code changes AND the changeset file:
|
|
296
|
+
```sh
|
|
297
|
+
git add .
|
|
298
|
+
git commit -m "feat: your feature description"
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
**Changeset Summary Guidelines:**
|
|
302
|
+
- Write clear, concise descriptions
|
|
303
|
+
- Focus on **what** changed and **why**
|
|
304
|
+
- Include migration instructions for breaking changes
|
|
305
|
+
- Use markdown formatting for readability
|
|
306
|
+
|
|
307
|
+
**Example changeset file** (`.changeset/brave-lions-dance.md`):
|
|
308
|
+
```markdown
|
|
309
|
+
---
|
|
310
|
+
"robertalv/loops-component": minor
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
Added `useResetCounter` hook for resetting counter values.
|
|
314
|
+
|
|
315
|
+
You can now reset counters to zero:
|
|
316
|
+
\`\`\`tsx
|
|
317
|
+
const resetCounter = useResetCounter();
|
|
318
|
+
await resetCounter("myCounter");
|
|
319
|
+
\`\`\`
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Automated Release Process
|
|
323
|
+
|
|
324
|
+
The release workflow is fully automated via GitHub Actions:
|
|
325
|
+
|
|
326
|
+
1. **Developer adds changeset** and pushes to a feature branch
|
|
327
|
+
2. **PR is created** → `test-and-lint.yml` workflow runs
|
|
328
|
+
3. **PR is merged to main** → `release.yml` workflow runs
|
|
329
|
+
4. **Release workflow detects changesets** and creates a "Version Packages" PR
|
|
330
|
+
5. **Version PR is reviewed** → Check version bumps and CHANGELOG updates
|
|
331
|
+
6. **Version PR is merged** → Package is automatically published to npm
|
|
332
|
+
7. **GitHub release is created** with release notes
|
|
333
|
+
|
|
334
|
+
### Manual Release (If Needed)
|
|
335
|
+
|
|
336
|
+
If you need to publish manually (bypassing automation):
|
|
337
|
+
|
|
338
|
+
```sh
|
|
339
|
+
# 1. Update versions and changelogs from all changesets
|
|
340
|
+
bun run ci:version
|
|
341
|
+
|
|
342
|
+
# 2. Review changes to package.json and CHANGELOG.md
|
|
343
|
+
git diff
|
|
344
|
+
|
|
345
|
+
# 3. Commit the version changes
|
|
346
|
+
git add .
|
|
347
|
+
git commit -m "chore: version packages"
|
|
348
|
+
git push
|
|
349
|
+
|
|
350
|
+
# 4. Publish to npm (runs tests, build, and validation)
|
|
351
|
+
bun run ci:publish
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### Configuration Files
|
|
355
|
+
|
|
356
|
+
- **`.changeset/config.json`**: Changesets configuration
|
|
357
|
+
- `access: "public"` - Package is published publicly to npm
|
|
358
|
+
- `changelog: "@changesets/changelog-github"` - Generates changelogs with PR links and contributor attribution
|
|
359
|
+
- `baseBranch: "main"` - Git branch for comparisons
|
|
360
|
+
|
|
361
|
+
- **`.github/workflows/release.yml`**: GitHub Actions workflow for automated releases
|
|
362
|
+
- Triggers on push to `main` branch
|
|
363
|
+
- Creates version PRs when changesets exist
|
|
364
|
+
- Publishes to npm when version PR is merged
|
|
365
|
+
- Requires `NPM_TOKEN` secret in repository settings
|
|
366
|
+
|
|
367
|
+
### Setting Up NPM Publishing (One-Time Setup)
|
|
368
|
+
|
|
369
|
+
For the automated release workflow to publish packages, you need to configure an npm token:
|
|
370
|
+
|
|
371
|
+
1. Go to [npmjs.com](https://npmjs.com) → Account Settings → Access Tokens
|
|
372
|
+
2. Generate a new **Automation** token (bypasses 2FA for CI/CD)
|
|
373
|
+
3. Copy the token
|
|
374
|
+
4. In GitHub repository: Settings → Secrets and variables → Actions
|
|
375
|
+
5. Create new secret named `NPM_TOKEN` with the token value
|
|
376
|
+
6. Ensure GitHub Actions has write permissions:
|
|
377
|
+
- Settings → Actions → General → Workflow permissions
|
|
378
|
+
- Select "Read and write permissions"
|
|
379
|
+
- Check "Allow GitHub Actions to create and approve pull requests"
|
|
380
|
+
|
|
381
|
+
### Viewing Published Versions
|
|
382
|
+
|
|
383
|
+
After publishing:
|
|
384
|
+
- **npm**: `https://www.npmjs.com/package/robertalv/loops-component`
|
|
385
|
+
- **GitHub Releases**: `https://github.com/robertalv/loops-component/releases`
|
|
386
|
+
- **Changelog**: `CHANGELOG.md` in the repository root
|
|
387
|
+
|
|
388
|
+
### Troubleshooting
|
|
389
|
+
|
|
390
|
+
**Changesets not detected?**
|
|
391
|
+
- Ensure `.changeset/` files are committed and pushed
|
|
392
|
+
- Check that changeset files have `.md` extension
|
|
393
|
+
- Verify YAML frontmatter is properly formatted
|
|
394
|
+
|
|
395
|
+
**Version PR not created?**
|
|
396
|
+
- Check GitHub Actions tab for workflow errors
|
|
397
|
+
- Ensure `GITHUB_TOKEN` has sufficient permissions
|
|
398
|
+
- Verify no merge conflicts in the version PR
|
|
399
|
+
|
|
400
|
+
**Publishing failed?**
|
|
401
|
+
- Verify `NPM_TOKEN` is correctly set in repository secrets
|
|
402
|
+
- Check npm token hasn't expired (max 90 days for granular tokens)
|
|
403
|
+
- Ensure package name isn't already taken on npm
|
|
404
|
+
- Run `bun run preversion` locally to catch test/lint failures
|
|
405
|
+
|
|
406
|
+
**Multiple changesets in one PR?**
|
|
407
|
+
- This is fine! All changesets will be consolidated in the version PR
|
|
408
|
+
- Each changeset contributes to the overall version bump (highest semver wins)
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
# Contributing to Convex Component Template
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing! This document provides guidelines and instructions for contributing to this project.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Code of Conduct](#code-of-conduct)
|
|
8
|
+
- [Getting Started](#getting-started)
|
|
9
|
+
- [Development Workflow](#development-workflow)
|
|
10
|
+
- [Coding Standards](#coding-standards)
|
|
11
|
+
- [Testing](#testing)
|
|
12
|
+
- [Submitting Changes](#submitting-changes)
|
|
13
|
+
- [Release Process](#release-process)
|
|
14
|
+
|
|
15
|
+
## Code of Conduct
|
|
16
|
+
|
|
17
|
+
By participating in this project, you agree to maintain a respectful and inclusive environment for all contributors.
|
|
18
|
+
|
|
19
|
+
## Getting Started
|
|
20
|
+
|
|
21
|
+
### Prerequisites
|
|
22
|
+
|
|
23
|
+
- **Bun** (latest stable version)
|
|
24
|
+
- **Node.js** 18+ (for Convex CLI)
|
|
25
|
+
- **Git**
|
|
26
|
+
|
|
27
|
+
### Setup
|
|
28
|
+
|
|
29
|
+
1. Fork the repository on GitHub
|
|
30
|
+
2. Clone your fork locally:
|
|
31
|
+
```sh
|
|
32
|
+
git clone https://github.com/SamHoque/convex-component-template.git
|
|
33
|
+
cd convex-component-template
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
3. Install dependencies:
|
|
37
|
+
```sh
|
|
38
|
+
bun install
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
4. Set up your Convex dev environment:
|
|
42
|
+
```sh
|
|
43
|
+
bun run dev:backend
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
5. In another terminal, run the example app:
|
|
47
|
+
```sh
|
|
48
|
+
bun run dev:frontend
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Development Workflow
|
|
52
|
+
|
|
53
|
+
### Running the Dev Environment
|
|
54
|
+
|
|
55
|
+
The project uses a multi-process development setup:
|
|
56
|
+
|
|
57
|
+
```sh
|
|
58
|
+
# Start all dev processes (backend, frontend, build watch)
|
|
59
|
+
bun run dev
|
|
60
|
+
|
|
61
|
+
# Or run individually:
|
|
62
|
+
bun run dev:backend # Convex dev server with live component sources
|
|
63
|
+
bun run dev:frontend # Example app with hot reload
|
|
64
|
+
bun run build:watch # TypeScript build in watch mode
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Making Changes
|
|
68
|
+
|
|
69
|
+
1. Create a new branch for your feature or bugfix:
|
|
70
|
+
```sh
|
|
71
|
+
git checkout -b feature/your-feature-name
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
2. Make your changes following the [coding standards](#coding-standards)
|
|
75
|
+
|
|
76
|
+
3. Add tests for your changes in `test/component/`
|
|
77
|
+
|
|
78
|
+
4. Run the test suite:
|
|
79
|
+
```sh
|
|
80
|
+
bun test
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
5. Run linting and formatting:
|
|
84
|
+
```sh
|
|
85
|
+
bun run check:fix
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
6. Commit your changes with a descriptive message following [Conventional Commits](https://www.conventionalcommits.org/):
|
|
89
|
+
```sh
|
|
90
|
+
git commit -m "feat: add new counter increment limit"
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Commit Message Format
|
|
94
|
+
|
|
95
|
+
We use conventional commit messages with gitmoji:
|
|
96
|
+
|
|
97
|
+
- `✨ feat:` - New features
|
|
98
|
+
- `🐛 fix:` - Bug fixes
|
|
99
|
+
- `📝 docs:` - Documentation changes
|
|
100
|
+
- `🎨 style:` - Code style/formatting changes
|
|
101
|
+
- `♻️ refactor:` - Code refactoring
|
|
102
|
+
- `✅ test:` - Test additions or updates
|
|
103
|
+
- `🔧 chore:` - Build process or auxiliary tool changes
|
|
104
|
+
- `⚡️ perf:` - Performance improvements
|
|
105
|
+
- `👷 ci:` - CI/CD changes
|
|
106
|
+
|
|
107
|
+
## Coding Standards
|
|
108
|
+
|
|
109
|
+
### TypeScript
|
|
110
|
+
|
|
111
|
+
- Use **strict mode** TypeScript
|
|
112
|
+
- Enable all recommended checks
|
|
113
|
+
- Avoid `any` types - use proper typing
|
|
114
|
+
- Use `const` over `let` where possible
|
|
115
|
+
|
|
116
|
+
### Code Style
|
|
117
|
+
|
|
118
|
+
We use **Biome** for linting and formatting:
|
|
119
|
+
|
|
120
|
+
- **Indentation**: Tabs (not spaces)
|
|
121
|
+
- **Quotes**: Double quotes for strings
|
|
122
|
+
- **Line length**: 100 characters (recommended)
|
|
123
|
+
- **Semicolons**: Required
|
|
124
|
+
|
|
125
|
+
Run the following before committing:
|
|
126
|
+
|
|
127
|
+
```sh
|
|
128
|
+
# Check for issues
|
|
129
|
+
bun run check
|
|
130
|
+
|
|
131
|
+
# Auto-fix issues
|
|
132
|
+
bun run check:fix
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### File Organization
|
|
136
|
+
|
|
137
|
+
- **Component source**: `src/component/`
|
|
138
|
+
- **Tests**: `test/component/` (separate from source to avoid bundling)
|
|
139
|
+
- **React hooks**: `src/react/`
|
|
140
|
+
- **Client utilities**: `src/client/`
|
|
141
|
+
- **Example app**: `example/`
|
|
142
|
+
|
|
143
|
+
### Naming Conventions
|
|
144
|
+
|
|
145
|
+
- **Files**: camelCase for source files, kebab-case for config files
|
|
146
|
+
- **Functions**: camelCase
|
|
147
|
+
- **Components**: PascalCase (React)
|
|
148
|
+
- **Constants**: UPPER_SNAKE_CASE
|
|
149
|
+
- **Types/Interfaces**: PascalCase
|
|
150
|
+
|
|
151
|
+
## Testing
|
|
152
|
+
|
|
153
|
+
### Writing Tests
|
|
154
|
+
|
|
155
|
+
Place all test files in `test/component/` directory:
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
import { test, expect } from "bun:test";
|
|
159
|
+
import { api } from "../../src/component/_generated/api";
|
|
160
|
+
import { convexTest } from "./setup.test";
|
|
161
|
+
|
|
162
|
+
test("my query works", async () => {
|
|
163
|
+
const t = convexTest();
|
|
164
|
+
const result = await t.query(api.lib.myQuery, { arg: "value" });
|
|
165
|
+
expect(result).toBe("expected");
|
|
166
|
+
});
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Running Tests
|
|
170
|
+
|
|
171
|
+
```sh
|
|
172
|
+
# Run all tests
|
|
173
|
+
bun test
|
|
174
|
+
|
|
175
|
+
# Watch mode
|
|
176
|
+
bun test --watch
|
|
177
|
+
|
|
178
|
+
# With coverage
|
|
179
|
+
bun test --coverage
|
|
180
|
+
|
|
181
|
+
# Filter by name
|
|
182
|
+
bun test -t "pattern"
|
|
183
|
+
|
|
184
|
+
# Stop on first failure
|
|
185
|
+
bun test --bail
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Testing Authenticated Scenarios
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
test("authenticated query", async () => {
|
|
192
|
+
const t = convexTest();
|
|
193
|
+
const asUser = t.withIdentity({ subject: "user123" });
|
|
194
|
+
const result = await asUser.query(api.lib.userQuery, {});
|
|
195
|
+
expect(result).toBeDefined();
|
|
196
|
+
});
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Submitting Changes
|
|
200
|
+
|
|
201
|
+
### Pull Request Process
|
|
202
|
+
|
|
203
|
+
1. Ensure all tests pass: `bun test`
|
|
204
|
+
2. Ensure linting passes: `bun run check`
|
|
205
|
+
3. Ensure TypeScript compiles: `bun run typecheck`
|
|
206
|
+
4. Ensure package exports are correct: `bun run attw`
|
|
207
|
+
5. Update documentation if needed
|
|
208
|
+
6. Push your branch to your fork
|
|
209
|
+
7. Open a Pull Request against the `main` branch
|
|
210
|
+
8. Fill out the PR template with:
|
|
211
|
+
- Description of changes
|
|
212
|
+
- Related issue numbers
|
|
213
|
+
- Testing performed
|
|
214
|
+
- Breaking changes (if any)
|
|
215
|
+
|
|
216
|
+
### PR Review Process
|
|
217
|
+
|
|
218
|
+
- At least one maintainer approval is required
|
|
219
|
+
- All CI checks must pass
|
|
220
|
+
- Code must follow the project's coding standards
|
|
221
|
+
- Tests must be included for new features
|
|
222
|
+
|
|
223
|
+
### What Happens After Your PR is Merged
|
|
224
|
+
|
|
225
|
+
- Your changes will be included in the next release
|
|
226
|
+
- The CHANGELOG will be updated
|
|
227
|
+
- You'll be credited as a contributor
|
|
228
|
+
|
|
229
|
+
## Release Process
|
|
230
|
+
|
|
231
|
+
This section is for maintainers.
|
|
232
|
+
|
|
233
|
+
### Version Bumping
|
|
234
|
+
|
|
235
|
+
The project uses npm version scripts:
|
|
236
|
+
|
|
237
|
+
```sh
|
|
238
|
+
# Alpha release (pre-release)
|
|
239
|
+
bun run alpha
|
|
240
|
+
|
|
241
|
+
# Patch release (0.1.0 -> 0.1.1)
|
|
242
|
+
bun run release
|
|
243
|
+
|
|
244
|
+
# Manual version bump
|
|
245
|
+
npm version [major|minor|patch]
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### What Happens During Release
|
|
249
|
+
|
|
250
|
+
1. `preversion`: Runs tests, linting, typecheck, and package validation
|
|
251
|
+
2. `version`: Updates version, opens CHANGELOG.md for editing, formats it
|
|
252
|
+
3. `postversion`: Pushes changes and tags to GitHub
|
|
253
|
+
|
|
254
|
+
### Publishing
|
|
255
|
+
|
|
256
|
+
Publishing happens automatically after version bump:
|
|
257
|
+
|
|
258
|
+
```sh
|
|
259
|
+
# For alpha releases
|
|
260
|
+
npm publish --tag alpha
|
|
261
|
+
|
|
262
|
+
# For stable releases
|
|
263
|
+
npm publish
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Questions?
|
|
267
|
+
|
|
268
|
+
If you have questions, please:
|
|
269
|
+
|
|
270
|
+
- Check existing issues and discussions
|
|
271
|
+
- Open a new issue for bugs
|
|
272
|
+
- Start a discussion for questions
|
|
273
|
+
|
|
274
|
+
Thank you for contributing!
|