@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/README.md +343 -375
- package/package.json +2 -2
- package/.changeset/README.md +0 -8
- package/.changeset/config.json +0 -14
- package/prds/CHANGELOG.md +0 -38
- package/prds/CLAUDE.md +0 -408
- package/prds/CONTRIBUTING.md +0 -274
- package/prds/ENV_SETUP.md +0 -222
- package/prds/MONITORING.md +0 -301
- package/prds/RATE_LIMITING.md +0 -412
- package/prds/SECURITY.md +0 -246
package/prds/CONTRIBUTING.md
DELETED
|
@@ -1,274 +0,0 @@
|
|
|
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!
|
package/prds/ENV_SETUP.md
DELETED
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
# Environment Variable Setup
|
|
2
|
-
|
|
3
|
-
The Loops component requires a Loops.so API key to be configured. **For security, the API key should ONLY be stored in Convex environment variables.**
|
|
4
|
-
|
|
5
|
-
## Setting Up the API Key
|
|
6
|
-
|
|
7
|
-
### 1. Get Your Loops API Key
|
|
8
|
-
|
|
9
|
-
1. Log in to your [Loops.so dashboard](https://app.loops.so)
|
|
10
|
-
2. Navigate to Settings → API Keys
|
|
11
|
-
3. Copy your API key
|
|
12
|
-
|
|
13
|
-
### 2. Set Environment Variable in Convex
|
|
14
|
-
|
|
15
|
-
**Via Convex Dashboard:**
|
|
16
|
-
|
|
17
|
-
1. Go to your Convex project dashboard
|
|
18
|
-
2. Navigate to **Settings** → **Environment Variables**
|
|
19
|
-
3. Click **Add Variable**
|
|
20
|
-
4. Set:
|
|
21
|
-
- **Name:** `LOOPS_API_KEY`
|
|
22
|
-
- **Value:** Your Loops API key
|
|
23
|
-
5. Click **Save**
|
|
24
|
-
|
|
25
|
-
**Via Convex CLI:**
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
npx convex env set LOOPS_API_KEY "your-api-key-here"
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
**Important:** The API key will be automatically available as `process.env.LOOPS_API_KEY` in your Convex functions.
|
|
32
|
-
|
|
33
|
-
### 3. Initialize the Component
|
|
34
|
-
|
|
35
|
-
Once the environment variable is set, initialize the component in your app:
|
|
36
|
-
|
|
37
|
-
```typescript
|
|
38
|
-
// In your app's convex/loops.ts (or similar)
|
|
39
|
-
import { Loops } from "robertalv/loops-component";
|
|
40
|
-
import { components } from "./_generated/api";
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Initialize Loops client.
|
|
44
|
-
* The API key is automatically loaded from process.env.LOOPS_API_KEY
|
|
45
|
-
*/
|
|
46
|
-
const loops = new Loops(components.loopsComponent);
|
|
47
|
-
|
|
48
|
-
export const {
|
|
49
|
-
addContact,
|
|
50
|
-
sendTransactional,
|
|
51
|
-
// ... other functions
|
|
52
|
-
} = loops.api();
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
## Security Best Practices
|
|
56
|
-
|
|
57
|
-
### ✅ DO:
|
|
58
|
-
|
|
59
|
-
1. **Store API key in Convex environment variables only**
|
|
60
|
-
```typescript
|
|
61
|
-
// ✅ GOOD - Uses environment variable automatically
|
|
62
|
-
const loops = new Loops(components.loopsComponent);
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
2. **Use different keys for different environments**
|
|
66
|
-
- Development: Set `LOOPS_API_KEY` in your dev deployment
|
|
67
|
-
- Production: Set `LOOPS_API_KEY` in your prod deployment
|
|
68
|
-
- Each deployment has its own environment variables
|
|
69
|
-
|
|
70
|
-
3. **Rotate API keys regularly**
|
|
71
|
-
- Generate new keys in Loops dashboard
|
|
72
|
-
- Update environment variable
|
|
73
|
-
- Remove old keys
|
|
74
|
-
|
|
75
|
-
4. **Restrict API key access**
|
|
76
|
-
- Only give access to necessary team members
|
|
77
|
-
- Use Convex's role-based access control for dashboard access
|
|
78
|
-
|
|
79
|
-
### ❌ DON'T:
|
|
80
|
-
|
|
81
|
-
1. **Don't hardcode API keys in code**
|
|
82
|
-
```typescript
|
|
83
|
-
// ❌ BAD - Never do this!
|
|
84
|
-
const loops = new Loops(components.loopsComponent, {
|
|
85
|
-
apiKey: "sk-abc123..." // NEVER hardcode!
|
|
86
|
-
});
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
2. **Don't commit API keys to git**
|
|
90
|
-
```typescript
|
|
91
|
-
// ❌ BAD - API key in code = exposed in git history
|
|
92
|
-
const API_KEY = "sk-abc123...";
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
3. **Don't pass API keys from client-side code**
|
|
96
|
-
```typescript
|
|
97
|
-
// ❌ BAD - Never accept API keys from clients
|
|
98
|
-
export const sendEmail = action({
|
|
99
|
-
args: {
|
|
100
|
-
apiKey: v.string(), // NEVER accept API key as argument!
|
|
101
|
-
email: v.string(),
|
|
102
|
-
},
|
|
103
|
-
// ...
|
|
104
|
-
});
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
4. **Don't log API keys**
|
|
108
|
-
```typescript
|
|
109
|
-
// ❌ BAD - Never log API keys
|
|
110
|
-
console.log("API Key:", process.env.LOOPS_API_KEY);
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
5. **Don't store in client-side code or config files**
|
|
114
|
-
- Not in `.env.local` (if exposed to client)
|
|
115
|
-
- Not in React components
|
|
116
|
-
- Not in browser storage
|
|
117
|
-
|
|
118
|
-
## Environment Variable Management
|
|
119
|
-
|
|
120
|
-
### Viewing Environment Variables
|
|
121
|
-
|
|
122
|
-
```bash
|
|
123
|
-
# List all environment variables
|
|
124
|
-
npx convex env list
|
|
125
|
-
|
|
126
|
-
# View a specific variable (value is masked for security)
|
|
127
|
-
npx convex env get LOOPS_API_KEY
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
### Updating Environment Variables
|
|
131
|
-
|
|
132
|
-
```bash
|
|
133
|
-
# Update existing variable
|
|
134
|
-
npx convex env set LOOPS_API_KEY "new-api-key-here"
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
### Removing Environment Variables
|
|
138
|
-
|
|
139
|
-
```bash
|
|
140
|
-
# Remove a variable
|
|
141
|
-
npx convex env remove LOOPS_API_KEY
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
## Multiple Environments
|
|
145
|
-
|
|
146
|
-
If you have multiple Convex deployments (dev, staging, prod), set the environment variable in each:
|
|
147
|
-
|
|
148
|
-
```bash
|
|
149
|
-
# Development deployment
|
|
150
|
-
npx convex env set LOOPS_API_KEY "dev-key-here" --prod=false
|
|
151
|
-
|
|
152
|
-
# Production deployment
|
|
153
|
-
npx convex env set LOOPS_API_KEY "prod-key-here" --prod=true
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
## Verification
|
|
157
|
-
|
|
158
|
-
To verify your API key is set correctly:
|
|
159
|
-
|
|
160
|
-
```typescript
|
|
161
|
-
// In a test query or action
|
|
162
|
-
export const testLoopsConnection = query({
|
|
163
|
-
handler: async (ctx) => {
|
|
164
|
-
const apiKey = process.env.LOOPS_API_KEY;
|
|
165
|
-
if (!apiKey) {
|
|
166
|
-
return { error: "LOOPS_API_KEY not set in environment variables" };
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// Try a simple operation
|
|
170
|
-
const loops = new Loops(components.loopsComponent);
|
|
171
|
-
// If initialization succeeds, API key is valid
|
|
172
|
-
return { success: true, message: "Loops client initialized successfully" };
|
|
173
|
-
},
|
|
174
|
-
});
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
## Troubleshooting
|
|
178
|
-
|
|
179
|
-
### "Loops API key is required" Error
|
|
180
|
-
|
|
181
|
-
This means `LOOPS_API_KEY` is not set in your Convex environment variables:
|
|
182
|
-
|
|
183
|
-
1. Check if variable exists: `npx convex env list`
|
|
184
|
-
2. Set the variable: `npx convex env set LOOPS_API_KEY "your-key"`
|
|
185
|
-
3. Restart your Convex dev server if running locally
|
|
186
|
-
|
|
187
|
-
### API Key Not Working
|
|
188
|
-
|
|
189
|
-
1. Verify the key is correct in Loops dashboard
|
|
190
|
-
2. Check if the key has expired or been rotated
|
|
191
|
-
3. Ensure you're using the correct deployment's environment variables
|
|
192
|
-
4. Check Convex dashboard for any environment variable errors
|
|
193
|
-
|
|
194
|
-
### Testing Without Environment Variable
|
|
195
|
-
|
|
196
|
-
For testing purposes only, you can pass the API key directly (but never commit this):
|
|
197
|
-
|
|
198
|
-
```typescript
|
|
199
|
-
// ⚠️ TESTING ONLY - Remove before production
|
|
200
|
-
const loops = new Loops(components.loopsComponent, {
|
|
201
|
-
apiKey: process.env.TEST_LOOPS_API_KEY || "test-key",
|
|
202
|
-
});
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
**Important:** This should only be used for local testing. In production, always use environment variables.
|
|
206
|
-
|
|
207
|
-
## Security Checklist
|
|
208
|
-
|
|
209
|
-
- [ ] API key stored only in Convex environment variables
|
|
210
|
-
- [ ] API key NOT in source code
|
|
211
|
-
- [ ] API key NOT in git repository
|
|
212
|
-
- [ ] API key NOT in client-side code
|
|
213
|
-
- [ ] Different keys for dev/staging/prod environments
|
|
214
|
-
- [ ] API key access restricted to necessary team members
|
|
215
|
-
- [ ] Regular key rotation schedule in place
|
|
216
|
-
|
|
217
|
-
## Additional Resources
|
|
218
|
-
|
|
219
|
-
- [Convex Environment Variables Documentation](https://docs.convex.dev/production/environment-variables)
|
|
220
|
-
- [Loops.so API Documentation](https://loops.so/docs)
|
|
221
|
-
- [Component Security Guide](./SECURITY.md)
|
|
222
|
-
|