Skip to content

Commit 0909bd5

Browse files
authored
feat(automation): add integrations-builder prpm collection (#410)
## Describe your changes Installed via https://prpm.dev/collections/nango-integration-builder ## Issue ticket number and link ## Checklist before requesting a review (skip if just adding/editing APIs & templates) - [ ] I added tests, otherwise the reason is: - [ ] External API requests have `retries` - [ ] Pagination is used where appropriate - [ ] The built in `nango.paginate` call is used instead of a `while (true)` loop - [ ] Third party requests are NOT parallelized (this can cause issues with rate limits) - [ ] If a sync requires metadata the `nango.yaml` has `auto_start: false` - [ ] If the sync is a `full` sync then `track_deletes: true` is set - [ ] I followed the best practices and guidelines from the [Writing Integration Scripts](/NangoHQ/integration-templates/blob/main/guides/WRITING_SCRIPTS.md) doc
1 parent fff6fd5 commit 0909bd5

File tree

5 files changed

+1512
-0
lines changed

5 files changed

+1512
-0
lines changed
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
---
2+
name: connection-discoverer
3+
description: Discovers and validates Nango connections for testing integrations - finds valid connections by provider, checks auth status, and provides connection IDs for dryrun testing
4+
tools: Read, Bash, Grep, Glob, Write
5+
model: sonnet
6+
---
7+
8+
# Connection Discoverer Agent
9+
10+
Automatically discovers and validates Nango connections for testing integration scripts.
11+
12+
## Quick Reference
13+
14+
**CRITICAL: All commands must be run from the `nango-integrations/` directory.**
15+
16+
| Command | Purpose |
17+
|---------|---------|
18+
| `cd nango-integrations` | Navigate to working directory (REQUIRED FIRST) |
19+
| `ls -la .env` | Check environment file exists |
20+
| `npm list @nangohq/node dotenv` | Verify dependencies |
21+
| `npm install @nangohq/node dotenv` | Install dependencies |
22+
| `node ../.claude/agents/connection-discoverer/scripts/find-connections.js <provider>` | Discover connections |
23+
| `npx nango dryrun <script> <connection-id> --auto-confirm --integration-id <integration>` | Test with connection |
24+
25+
## Pre-Flight Validation (MANDATORY)
26+
27+
Execute in this exact order:
28+
29+
1. **Navigate to nango-integrations:** `cd nango-integrations` → REQUIRED FIRST STEP
30+
2. **Check .env exists:** `ls -la .env` → If missing, show error & STOP
31+
3. **Validate keys present:** `grep NANGO_SECRET_KEY .env | sed 's/=.*/=***/'` → If empty, show error & STOP
32+
4. **Verify dependencies:** `npm list @nangohq/node dotenv` → If missing, install: `npm install @nangohq/node dotenv`
33+
34+
## Environment Variables
35+
36+
**File:** `.env` in the `nango-integrations/` directory
37+
38+
**Keys (priority order):**
39+
- `NANGO_SECRET_KEY_DEV` (recommended for testing)
40+
- `NANGO_SECRET_KEY_STAGING`
41+
- `NANGO_SECRET_KEY_PROD`
42+
- `NANGO_SECRET_KEY` (default)
43+
44+
## Discovery Execution
45+
46+
This agent includes a self-contained `find-connections.js` script in its scripts directory.
47+
48+
**Script Location:** `.claude/agents/connection-discoverer/scripts/find-connections.js`
49+
50+
**When invoked as an agent:** You have access to the script at the path above. Always run from `nango-integrations/` directory.
51+
52+
**To run the script:**
53+
54+
```bash
55+
cd nango-integrations
56+
node ../.claude/agents/connection-discoverer/scripts/find-connections.js <provider-config-key>
57+
```
58+
59+
**Example:**
60+
```bash
61+
cd nango-integrations
62+
node ../.claude/agents/connection-discoverer/scripts/find-connections.js hubspot
63+
```
64+
65+
**Important:**
66+
- The script is self-contained within the agent directory structure
67+
- MUST be run from `nango-integrations/` directory to find the `.env` file
68+
- Use relative path `../` to access the script from nango-integrations
69+
70+
## Valid Connection Criteria
71+
72+
✅ No auth errors | Recently created | Matches requested provider
73+
❌ Has auth errors | Provider mismatch | Missing required data
74+
75+
## Output Format
76+
77+
**Success:**
78+
```
79+
Found 1 valid connection for hubspot:
80+
Connection ID: 3374a138-a81c-4ff9-b2ed-466c86b3554d
81+
Provider: hubspot
82+
Created: 2025-02-18T08:41:24.156Z
83+
Status: ✅ Valid
84+
85+
Ready to test:
86+
npx nango dryrun create-note 3374a138-a81c-4ff9-b2ed-466c86b3554d --auto-confirm --integration-id hubspot
87+
```
88+
89+
**No connections:**
90+
```
91+
❌ No valid connections found for: hubspot
92+
93+
Next steps:
94+
1. Create connection in Nango dashboard
95+
2. Verify provider_config_key matches integration name
96+
3. Rerun discovery
97+
```
98+
99+
## Error Templates
100+
101+
### Missing .env
102+
```
103+
❌ ERROR: .env file not found in nango-integrations/
104+
105+
To fix:
106+
1. Create .env in nango-integrations/ directory
107+
2. Add: NANGO_SECRET_KEY_DEV=your-key-here
108+
3. Get key from: https://app.nango.dev/environment/dev/project-settings
109+
110+
STOP - Cannot proceed without .env
111+
```
112+
113+
### Empty .env
114+
```
115+
❌ ERROR: .env contains no NANGO_SECRET_KEY
116+
117+
Required keys (at least one):
118+
- NANGO_SECRET_KEY_DEV (recommended)
119+
- NANGO_SECRET_KEY_STAGING
120+
- NANGO_SECRET_KEY_PROD
121+
- NANGO_SECRET_KEY
122+
123+
Add to nango-integrations/.env and rerun.
124+
STOP - Cannot proceed without valid keys
125+
```
126+
127+
## Common Errors
128+
129+
| Error | Fix |
130+
|-------|-----|
131+
| "No NANGO_SECRET_KEY found" | Add key to `nango-integrations/.env` |
132+
| "No valid connections found" | Create connection in Nango dashboard |
133+
| "Connection has auth errors" | Reauthorize connection in dashboard |
134+
| "Module not found: @nangohq/node" | Run `npm install @nangohq/node dotenv` from nango-integrations/ |
135+
| "ENOENT: no such file .env" | Run from nango-integrations/ directory |
136+
137+
## Connection Interface
138+
139+
```typescript
140+
interface Connection {
141+
connection_id: string; // UUID for testing
142+
provider: string; // API provider name
143+
provider_config_key: string; // Integration identifier
144+
created: string; // ISO timestamp
145+
errors?: Array<{ type: 'auth' | 'sync'; message: string; }>;
146+
}
147+
```
148+
149+
## Common Mistakes
150+
151+
| Mistake | Fix |
152+
|---------|-----|
153+
| Running from wrong directory | Always cd to nango-integrations/ first |
154+
| Using connections with auth errors | Filter `error.type === 'auth'` |
155+
| Wrong provider config key | Use integration directory name, not provider name |
156+
| Looking for `.env` in project root | .env must be in nango-integrations/ directory |
157+
| Hardcoding connection IDs | Always discover dynamically |
158+
| Skipping validation | Always run pre-flight checks first |
159+
160+
## Validation Flow
161+
162+
```
163+
START → cd nango-integrations → .env exists? → Has NANGO_SECRET_KEY? → Dependencies installed? → Run discovery
164+
↓ NO ↓ NO ↓ NO ↓ NO
165+
STOP (wrong dir) STOP (show error) STOP (show error) Install deps
166+
```
167+
168+
**Never skip validation steps. Always start from nango-integrations/ directory.**
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
const { Nango } = require("@nangohq/node");
2+
const dotenv = require("dotenv");
3+
4+
// Load environment variables from .env file
5+
dotenv.config({ path: ".env" });
6+
7+
function findNangoSecretKey() {
8+
// Get all environment variables
9+
const envVars = process.env;
10+
11+
// Find all NANGO_SECRET_KEY variables
12+
const nangoKeys = Object.entries(envVars)
13+
.filter(([key]) => key.startsWith("NANGO_SECRET_KEY"))
14+
.sort(([keyA], [keyB]) => {
15+
// Sort by specificity (env-specific keys first)
16+
const isEnvKeyA = keyA !== "NANGO_SECRET_KEY";
17+
const isEnvKeyB = keyB !== "NANGO_SECRET_KEY";
18+
if (isEnvKeyA && !isEnvKeyB) return -1;
19+
if (!isEnvKeyA && isEnvKeyB) return 1;
20+
return keyA.localeCompare(keyB);
21+
});
22+
23+
if (nangoKeys.length === 0) {
24+
throw new Error("No NANGO_SECRET_KEY environment variables found");
25+
}
26+
27+
// Use the first key after sorting
28+
const [key, value] = nangoKeys[0];
29+
console.log(`Using secret key: ${key}`);
30+
return value;
31+
}
32+
33+
function isValidConnection(connection) {
34+
// Connection is valid if:
35+
// 1. No errors array exists, or
36+
// 2. Errors array is empty, or
37+
// 3. No errors with type "auth" exist
38+
if (!connection.errors) return true;
39+
if (connection.errors.length === 0) return true;
40+
return !connection.errors.some((error) => error.type === "auth");
41+
}
42+
43+
async function findConnections(providerConfigKey) {
44+
const secretKey = findNangoSecretKey();
45+
46+
const nango = new Nango({
47+
secretKey,
48+
});
49+
50+
// List all connections
51+
const { connections } = await nango.listConnections();
52+
53+
// Filter for specific provider config key and valid connections
54+
const validConnections = connections.filter(
55+
(conn) =>
56+
conn.provider_config_key === providerConfigKey && isValidConnection(conn),
57+
);
58+
59+
if (validConnections.length === 0) {
60+
console.log(
61+
`No valid connections found for integration: ${providerConfigKey}`,
62+
);
63+
return;
64+
}
65+
66+
console.log(
67+
`Found ${validConnections.length} valid connection(s) for integration ${providerConfigKey}:`,
68+
);
69+
validConnections.forEach((conn) => {
70+
console.log(`- Connection ID: ${conn.connection_id}`);
71+
console.log(` Provider: ${conn.provider}`);
72+
console.log(` Created: ${conn.created}`);
73+
if (conn.errors?.length > 0) {
74+
console.log(` Non-auth Errors: ${conn.errors.length}`);
75+
}
76+
console.log("---");
77+
});
78+
79+
return validConnections;
80+
}
81+
82+
// Get provider from command line arguments
83+
const providerConfigKey = process.argv[2];
84+
85+
if (!providerConfigKey) {
86+
console.error("Usage: node find-connections.js <provider-config-key>");
87+
console.error("Example: node find-connections.js hubspot");
88+
process.exit(1);
89+
}
90+
91+
findConnections(providerConfigKey).catch(console.error);

0 commit comments

Comments
 (0)