@devwithbobby/loops 0.1.0 → 0.1.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devwithbobby/loops",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Convex component for integrating with Loops.so email marketing platform",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -52,7 +52,7 @@
52
52
  "check:fix": "biome check --write .",
53
53
  "typecheck": "tsc --noEmit",
54
54
  "attw": "attw $(npm pack -s) --exclude-entrypoints ./convex.config --profile esm-only",
55
- "prepare": "bun run build",
55
+ "prepare": "npm run build || true",
56
56
  "changeset": "changeset",
57
57
  "ci:version": "changeset version && bun update",
58
58
  "ci:publish": "bun run preversion && changeset publish",
@@ -1,8 +0,0 @@
1
- # Changesets
2
-
3
- Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
4
- with multi-package repos, or single-package repos to help you version and publish your code. You can
5
- find the full documentation for it [in our repository](https://github.com/changesets/changesets)
6
-
7
- We have a quick list of common questions to get you started engaging with this project in
8
- [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
@@ -1,14 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json",
3
- "changelog": [
4
- "@changesets/changelog-github",
5
- { "repo": "samhoque/convex-component-template" }
6
- ],
7
- "commit": false,
8
- "fixed": [],
9
- "linked": [],
10
- "access": "public",
11
- "baseBranch": "main",
12
- "updateInternalDependencies": "patch",
13
- "ignore": []
14
- }
package/prds/CHANGELOG.md DELETED
@@ -1,38 +0,0 @@
1
- # Changelog
2
-
3
- All notable changes to this project will be documented in this file.
4
-
5
- The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
- and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
-
8
- ## [Unreleased]
9
-
10
- ### Changed
11
- - Moved `convex` and `react` to `peerDependencies` to prevent version conflicts
12
-
13
- ### Added
14
- - Added `@arethetypeswrong/cli` for package validation
15
- - Added `attw` script for validating package exports
16
-
17
- ## [0.1.0] - 2025-10-24
18
-
19
- ### Added
20
- - Initial release of the Convex component template
21
- - Sharded counter component implementation
22
- - React hooks for component integration (`useLoopsComponent`, `useIncrementCounter`, `useCounterValue`)
23
- - Complete Convex component architecture with example app
24
- - GitHub Actions workflow with `pkg.pr.new` integration
25
- - Lefthook for automated pre-commit checks
26
- - Biome for linting and formatting
27
- - Comprehensive test suite using `convex-test`
28
- - TypeScript support with strict mode
29
- - Bun-based development workflow
30
- - Live component sources for hot-reloading during development
31
-
32
- ### Documentation
33
- - README with setup and usage instructions
34
- - CLAUDE.md for AI-assisted development guidance
35
- - Example app demonstrating component usage
36
-
37
- [Unreleased]: https://github.com/robertalv/loops-component/compare/v0.1.0...HEAD
38
- [0.1.0]: https://github.com/robertalv/loops-component/releases/tag/v0.1.0
package/prds/CLAUDE.md DELETED
@@ -1,408 +0,0 @@
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)