Skip to content

Commit 78d17b1

Browse files
authored
feat: Add listCustomersByEmail and fix API response parsing (#70)
* feat: Add listCustomersByEmail and fix API response parsing - Add `listCustomersByEmail` function to search customers by email address - Refactor `listCustomersByName` and `listCustomersByEmail` to share common `searchCustomers` helper function, eliminating code duplication - Fix API response parsing to use correct field names: - Use `customers` array instead of `data` - Use `total_hits` instead of `total_count` - Update all test mocks to match actual API response format - Add test script (`examples/test-list-customers-by-name.ts`) for debugging customer search functionality The previous implementation was looking for `data` and `total_count` fields that the API never returns, causing searches to return empty results even when customers existed. * remove extra file that should not be in the repo
1 parent 6ed8e37 commit 78d17b1

File tree

5 files changed

+332
-26
lines changed

5 files changed

+332
-26
lines changed
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// Test script for listCustomersByName function
2+
// Usage: npm run test-list-customers -- <customer-name> <auth-token> [app-slug]
3+
// Or use environment variable: REPLICATED_API_TOKEN=token npm run test-list-customers -- <customer-name> [app-slug]
4+
5+
import { VendorPortalApi } from "../dist/configuration";
6+
import { listCustomersByName } from "../dist/customers";
7+
8+
// Debug: show all arguments
9+
console.log("=== Debug: process.argv ===");
10+
console.log(process.argv);
11+
console.log("");
12+
13+
// Get arguments from command line
14+
// When using npm run, arguments after -- start at index 2
15+
// process.argv[0] = node path
16+
// process.argv[1] = script path
17+
// process.argv[2+] = actual arguments
18+
19+
const customerName = process.argv[2];
20+
const authToken = process.env.REPLICATED_API_TOKEN || process.argv[3];
21+
const appSlug = process.env.REPLICATED_API_TOKEN ? process.argv[3] : process.argv[4]; // Optional
22+
23+
if (!customerName) {
24+
console.error("Error: Customer name is required");
25+
console.error("\nUsage: npm run test-list-customers -- <customer-name> <auth-token> [app-slug]");
26+
console.error(" Or: REPLICATED_API_TOKEN=token npm run test-list-customers -- <customer-name> [app-slug]");
27+
console.error("\nExample: npm run test-list-customers -- 'CI Test Customer 3' 'your-token-here'");
28+
process.exit(1);
29+
}
30+
31+
if (!authToken) {
32+
console.error("Error: Auth token is required");
33+
console.error("\nProvide token either as:");
34+
console.error(" 1. Third argument: npm run test-list-customers -- <name> <token>");
35+
console.error(" 2. Environment variable: REPLICATED_API_TOKEN=token npm run test-list-customers -- <name>");
36+
process.exit(1);
37+
}
38+
39+
console.log("=== Test Configuration ===");
40+
console.log(`Customer Name: ${customerName}`);
41+
console.log(`Auth Token: ${authToken.substring(0, 10)}...${authToken.substring(authToken.length - 4)} (length: ${authToken.length})`);
42+
console.log(`App Slug: ${appSlug || "undefined (will search across all apps)"}`);
43+
console.log(`Query that will be used: name:${customerName}`);
44+
console.log(`API Endpoint: https://api.replicated.com/vendor/v3`);
45+
console.log("");
46+
47+
const api = new VendorPortalApi();
48+
api.apiToken = authToken;
49+
50+
console.log("=== Calling listCustomersByName ===");
51+
listCustomersByName(api, appSlug, customerName)
52+
.then(customers => {
53+
console.log(`\n=== Results ===`);
54+
console.log(`Found ${customers.length} customer(s):`);
55+
56+
if (customers.length === 0) {
57+
console.log("No customers found!");
58+
console.log("\n=== Debug Info ===");
59+
console.log("This might indicate:");
60+
console.log("1. The query format might be different than expected");
61+
console.log("2. The include flags might be filtering out results");
62+
console.log("3. The app_id filter might be excluding results");
63+
console.log("\n=== Request Body Comparison ===");
64+
console.log("Your curl command sends:");
65+
console.log(" - include_test: true");
66+
console.log(" - include_active: true");
67+
console.log(" - include_archived: true <-- NOTE: This is TRUE in curl");
68+
console.log(" - include_inactive: true");
69+
console.log("\nFunction sends:");
70+
console.log(" - include_paid: true");
71+
console.log(" - include_inactive: true");
72+
console.log(" - include_dev: true");
73+
console.log(" - include_community: true");
74+
console.log(" - include_archived: false <-- NOTE: This is FALSE in function");
75+
console.log(" - include_active: true");
76+
console.log(" - include_test: true");
77+
console.log(" - include_trial: true");
78+
console.log("\n⚠️ POTENTIAL ISSUE: include_archived is false in function but true in curl!");
79+
console.log(" If the customer is archived, the function won't find it.");
80+
} else {
81+
customers.forEach((customer, index) => {
82+
console.log(`\n${index + 1}. Customer ID: ${customer.customerId}`);
83+
console.log(` Name: ${customer.name}`);
84+
});
85+
}
86+
})
87+
.catch(err => {
88+
console.error("\n=== Error ===");
89+
console.error(err.message);
90+
91+
if (err.message.includes("401")) {
92+
console.error("\n⚠️ 401 Unauthorized - Authentication failed!");
93+
console.error("Please verify:");
94+
console.error(" 1. Your auth token is correct");
95+
console.error(" 2. The token has the necessary permissions");
96+
console.error(` 3. Token being used: ${authToken.substring(0, 10)}...${authToken.substring(authToken.length - 4)}`);
97+
console.error("\nCompare with your curl command - make sure the token matches exactly.");
98+
}
99+
100+
console.error("\nFull error:", err);
101+
process.exit(1);
102+
});
103+

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
"create-object-store": "rm -rf examples/*.js && tsc examples/create-object-store.ts && node examples/create-object-store.js",
1010
"create-postgres": "rm -rf examples/*.js && tsc examples/create-postgres.ts && node examples/create-postgres.js",
1111
"expose-port": "rm -rf examples/*.js && tsc examples/expose-port.ts && node examples/expose-port.js",
12-
"poll-airgap": "rm -rf examples/*.js && tsc examples/poll-for-airgap-build.ts && node examples/poll-for-airgap-build.js"
12+
"poll-airgap": "rm -rf examples/*.js && tsc examples/poll-for-airgap-build.ts && node examples/poll-for-airgap-build.js",
13+
"test-list-customers": "rm -rf examples/*.js && npm run build && tsc examples/test-list-customers-by-name.ts && node examples/test-list-customers-by-name.js"
1314
},
1415
"main": "dist/index.js",
1516
"types": "dist/index.d.ts",

0 commit comments

Comments
 (0)