orangeslice 2.1.2 → 2.1.4-beta.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/README.md +15 -3
- package/dist/api.js +1 -1
- package/dist/cli.js +102 -22
- package/dist/ctx.d.ts +62 -0
- package/dist/ctx.js +101 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -1
- package/docs/integrations/hubspot/getList.md +52 -0
- package/docs/integrations/hubspot/index.md +5 -1
- package/docs/lookalike-search/index.md +154 -0
- package/docs/prospecting/index.md +77 -67
- package/docs/prospecting/linkedin_data/QUICK_REF.md +3 -1
- package/docs/prospecting/linkedin_data/index.md +33 -12
- package/docs/services/builtWith/index.md +6 -6
- package/docs/services/builtWith/lookupDomain.ts +1 -1
- package/docs/services/builtWith/relationships.ts +1 -1
- package/docs/services/builtWith/searchByTech.ts +1 -1
- package/docs/services/company/getEmployeesFromLinkedin.md +26 -12
- package/docs/services/company/linkedin/enrich.md +2 -0
- package/docs/services/company/linkedin/search.md +4 -2
- package/docs/services/company/revenue.md +74 -0
- package/docs/services/ctx/index.md +68 -0
- package/docs/services/googleMaps/scrape.ts +1 -1
- package/docs/services/index.md +1 -0
- package/docs/services/ocean/search/companies.ts +130 -0
- package/docs/services/ocean/search/people.ts +120 -0
- package/docs/services/person/contact/get.ts +2 -2
- package/docs/services/person/linkedin/findUrl.md +2 -2
- package/docs/services/person/linkedin/search.md +4 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,13 +6,16 @@ Orangeslice provides a `services.*` API for B2B research, enrichment, scraping,
|
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
npx orangeslice
|
|
9
|
+
bunx orangeslice
|
|
10
|
+
pnpm dlx orangeslice
|
|
11
|
+
yarn dlx orangeslice
|
|
9
12
|
```
|
|
10
13
|
|
|
11
14
|
The CLI copies docs to `./orangeslice-docs`, creates `./orangeslice-docs/AGENTS.md`, initializes `package.json` when missing, installs `orangeslice` in the current directory, opens browser auth, and stores your API key in `~/.config/orangeslice/config.json`.
|
|
12
15
|
|
|
13
16
|
### Auth behavior
|
|
14
17
|
|
|
15
|
-
- `npx
|
|
18
|
+
- Any supported runner (`npx`, `bunx`, `pnpm dlx`, `yarn dlx`) uses browser-based device auth and auto-provisions an API key.
|
|
16
19
|
- SDK credential precedence:
|
|
17
20
|
1. `configure({ apiKey })`
|
|
18
21
|
2. `ORANGESLICE_API_KEY` env var
|
|
@@ -21,23 +24,32 @@ The CLI copies docs to `./orangeslice-docs`, creates `./orangeslice-docs/AGENTS.
|
|
|
21
24
|
### CLI auth commands
|
|
22
25
|
|
|
23
26
|
```bash
|
|
24
|
-
# One-time setup (also runs on plain `npx orangeslice` when unauthenticated)
|
|
27
|
+
# One-time setup (also runs on plain `npx orangeslice` / `bunx orangeslice` when unauthenticated)
|
|
25
28
|
npx orangeslice login
|
|
29
|
+
bunx orangeslice login
|
|
30
|
+
pnpm dlx orangeslice login
|
|
31
|
+
yarn dlx orangeslice login
|
|
26
32
|
|
|
27
33
|
# Force re-auth and replace local stored key
|
|
28
34
|
npx orangeslice login --force
|
|
35
|
+
bunx orangeslice login --force
|
|
29
36
|
|
|
30
37
|
# Remove locally stored key
|
|
31
38
|
npx orangeslice logout
|
|
39
|
+
bunx orangeslice logout
|
|
32
40
|
|
|
33
41
|
# Show current auth source (env or config file)
|
|
34
42
|
npx orangeslice auth status
|
|
43
|
+
bunx orangeslice auth status
|
|
35
44
|
```
|
|
36
45
|
|
|
37
46
|
Install as a dependency when writing app code:
|
|
38
47
|
|
|
39
48
|
```bash
|
|
40
49
|
npm install orangeslice
|
|
50
|
+
bun add orangeslice
|
|
51
|
+
pnpm add orangeslice
|
|
52
|
+
yarn add orangeslice
|
|
41
53
|
```
|
|
42
54
|
|
|
43
55
|
## Public API (services-first)
|
|
@@ -101,7 +113,7 @@ All service calls go through `post()` in `src/api.ts`.
|
|
|
101
113
|
|
|
102
114
|
## Docs installed by CLI
|
|
103
115
|
|
|
104
|
-
After
|
|
116
|
+
After running the CLI bootstrap command, you should have:
|
|
105
117
|
|
|
106
118
|
```text
|
|
107
119
|
orangeslice-docs/
|
package/dist/api.js
CHANGED
|
@@ -137,7 +137,7 @@ async function post(endpoint, payload) {
|
|
|
137
137
|
const apiKey = resolveApiKey();
|
|
138
138
|
if (!apiKey) {
|
|
139
139
|
throw new Error("[orangeslice] No API key configured. " +
|
|
140
|
-
"Run `npx orangeslice`, set ORANGESLICE_API_KEY in your environment, or call configure({ apiKey: 'osk_...' }).");
|
|
140
|
+
"Run `npx orangeslice`, `bunx orangeslice`, `pnpm dlx orangeslice`, or `yarn dlx orangeslice`, set ORANGESLICE_API_KEY in your environment, or call configure({ apiKey: 'osk_...' }).");
|
|
141
141
|
}
|
|
142
142
|
const url = `${baseUrl}${endpoint}`;
|
|
143
143
|
const body = JSON.stringify({ ...payload, inlineWaitMs: DEFAULT_INLINE_WAIT_MS });
|
package/dist/cli.js
CHANGED
|
@@ -47,6 +47,7 @@ const CONFIG_DIR = path.join(os.homedir(), ".config", "orangeslice");
|
|
|
47
47
|
const CONFIG_PATH = path.join(CONFIG_DIR, "config.json");
|
|
48
48
|
const AGENTS_IMPORT_LINE = "@orangeslice-docs/AGENTS.md";
|
|
49
49
|
const CLAUDE_IMPORT_LINE = "@orangeslice-docs/CLAUDE.md";
|
|
50
|
+
const SUPPORTED_RUNNERS = ["npm", "bun", "pnpm", "yarn"];
|
|
50
51
|
function isDir(p) {
|
|
51
52
|
try {
|
|
52
53
|
return fs.statSync(p).isDirectory();
|
|
@@ -71,6 +72,71 @@ function resolveDocsDir() {
|
|
|
71
72
|
}
|
|
72
73
|
return LEGACY_DOCS_DIR;
|
|
73
74
|
}
|
|
75
|
+
function hasFile(cwd, fileName) {
|
|
76
|
+
return fs.existsSync(path.join(cwd, fileName));
|
|
77
|
+
}
|
|
78
|
+
function readPackageManagerFromPackageJson(cwd) {
|
|
79
|
+
const packageJsonPath = path.join(cwd, "package.json");
|
|
80
|
+
if (!fs.existsSync(packageJsonPath))
|
|
81
|
+
return null;
|
|
82
|
+
try {
|
|
83
|
+
const parsed = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
84
|
+
const packageManager = parsed.packageManager?.toLowerCase() || "";
|
|
85
|
+
if (packageManager.startsWith("bun@"))
|
|
86
|
+
return "bun";
|
|
87
|
+
if (packageManager.startsWith("pnpm@"))
|
|
88
|
+
return "pnpm";
|
|
89
|
+
if (packageManager.startsWith("yarn@"))
|
|
90
|
+
return "yarn";
|
|
91
|
+
if (packageManager.startsWith("npm@"))
|
|
92
|
+
return "npm";
|
|
93
|
+
}
|
|
94
|
+
catch { }
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
function detectPackageManager(cwd) {
|
|
98
|
+
const fromPackageJson = readPackageManagerFromPackageJson(cwd);
|
|
99
|
+
if (fromPackageJson)
|
|
100
|
+
return fromPackageJson;
|
|
101
|
+
if (hasFile(cwd, "bun.lock") || hasFile(cwd, "bun.lockb"))
|
|
102
|
+
return "bun";
|
|
103
|
+
if (hasFile(cwd, "pnpm-lock.yaml"))
|
|
104
|
+
return "pnpm";
|
|
105
|
+
if (hasFile(cwd, "yarn.lock"))
|
|
106
|
+
return "yarn";
|
|
107
|
+
if (hasFile(cwd, "package-lock.json") || hasFile(cwd, "npm-shrinkwrap.json"))
|
|
108
|
+
return "npm";
|
|
109
|
+
const userAgent = process.env.npm_config_user_agent?.toLowerCase() || "";
|
|
110
|
+
if (userAgent.includes("bun/"))
|
|
111
|
+
return "bun";
|
|
112
|
+
if (userAgent.includes("pnpm/"))
|
|
113
|
+
return "pnpm";
|
|
114
|
+
if (userAgent.includes("yarn/"))
|
|
115
|
+
return "yarn";
|
|
116
|
+
return "npm";
|
|
117
|
+
}
|
|
118
|
+
function getRunnerCommand(packageManager, suffix = "") {
|
|
119
|
+
const command = packageManager === "bun"
|
|
120
|
+
? "bunx orangeslice"
|
|
121
|
+
: packageManager === "pnpm"
|
|
122
|
+
? "pnpm dlx orangeslice"
|
|
123
|
+
: packageManager === "yarn"
|
|
124
|
+
? "yarn dlx orangeslice"
|
|
125
|
+
: "npx orangeslice";
|
|
126
|
+
return suffix ? `${command} ${suffix}` : command;
|
|
127
|
+
}
|
|
128
|
+
function getInstallCommand(packageManager) {
|
|
129
|
+
if (packageManager === "bun")
|
|
130
|
+
return "bun add orangeslice";
|
|
131
|
+
if (packageManager === "pnpm")
|
|
132
|
+
return "pnpm add orangeslice";
|
|
133
|
+
if (packageManager === "yarn")
|
|
134
|
+
return "yarn add orangeslice";
|
|
135
|
+
return "npm install orangeslice";
|
|
136
|
+
}
|
|
137
|
+
function getSupportedRunnerExamples() {
|
|
138
|
+
return SUPPORTED_RUNNERS.map((packageManager) => getRunnerCommand(packageManager));
|
|
139
|
+
}
|
|
74
140
|
function copyDirSync(src, dest) {
|
|
75
141
|
fs.mkdirSync(dest, { recursive: true });
|
|
76
142
|
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
@@ -105,7 +171,7 @@ Use these docs as the source of truth. If there is any conflict between your pri
|
|
|
105
171
|
- \`import { services } from "orangeslice"\`
|
|
106
172
|
- \`import { configure, services } from "orangeslice"\` when setting API key programmatically
|
|
107
173
|
- Do NOT use \`import { services } from "./orangeslice"\` unless the user explicitly has a local wrapper file at that path.
|
|
108
|
-
- \`npx orangeslice\`
|
|
174
|
+
- The orangeslice bootstrap commands (\`npx orangeslice\`, \`bunx orangeslice\`, \`pnpm dlx orangeslice\`, \`yarn dlx orangeslice\`) sync docs, install the package, and handle auth. They do NOT execute user app scripts.
|
|
109
175
|
|
|
110
176
|
## Runtime Requirements
|
|
111
177
|
- If writing standalone scripts that use top-level \`await\`, use ESM:
|
|
@@ -194,12 +260,21 @@ function ensurePackageJson(cwd) {
|
|
|
194
260
|
const packageJsonPath = path.join(cwd, "package.json");
|
|
195
261
|
if (fs.existsSync(packageJsonPath))
|
|
196
262
|
return;
|
|
197
|
-
console.log(" No package.json found.
|
|
198
|
-
|
|
263
|
+
console.log(" No package.json found. Creating one...");
|
|
264
|
+
const defaultName = path
|
|
265
|
+
.basename(cwd)
|
|
266
|
+
.toLowerCase()
|
|
267
|
+
.replace(/[^a-z0-9._-]+/g, "-")
|
|
268
|
+
.replace(/^-+|-+$/g, "") || "orangeslice-app";
|
|
269
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify({
|
|
270
|
+
name: defaultName,
|
|
271
|
+
version: "1.0.0",
|
|
272
|
+
private: true
|
|
273
|
+
}, null, 2) + "\n", "utf8");
|
|
199
274
|
}
|
|
200
|
-
function installOrangeslice(cwd) {
|
|
201
|
-
console.log(
|
|
202
|
-
(0, child_process_1.execSync)(
|
|
275
|
+
function installOrangeslice(cwd, packageManager) {
|
|
276
|
+
console.log(` Installing orangeslice with ${packageManager}...`);
|
|
277
|
+
(0, child_process_1.execSync)(getInstallCommand(packageManager), { stdio: "inherit", cwd });
|
|
203
278
|
}
|
|
204
279
|
function readConfigFile() {
|
|
205
280
|
try {
|
|
@@ -312,13 +387,17 @@ async function setupApiKey(force = false) {
|
|
|
312
387
|
saveConfigFile({ apiKey });
|
|
313
388
|
console.log(` ✓ API key saved to ${CONFIG_PATH}\n`);
|
|
314
389
|
}
|
|
315
|
-
function printHelp() {
|
|
390
|
+
function printHelp(packageManager) {
|
|
316
391
|
console.log("Usage:");
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
console.log("
|
|
321
|
-
console.log("
|
|
392
|
+
for (const command of getSupportedRunnerExamples()) {
|
|
393
|
+
console.log(` ${command}`);
|
|
394
|
+
}
|
|
395
|
+
console.log("");
|
|
396
|
+
console.log("Commands:");
|
|
397
|
+
console.log(` ${getRunnerCommand(packageManager, "login [--force]")}`);
|
|
398
|
+
console.log(` ${getRunnerCommand(packageManager, "logout")}`);
|
|
399
|
+
console.log(` ${getRunnerCommand(packageManager, "auth <API_KEY>")}`);
|
|
400
|
+
console.log(` ${getRunnerCommand(packageManager, "auth status")}\n`);
|
|
322
401
|
}
|
|
323
402
|
async function runLogin(args) {
|
|
324
403
|
const force = args.includes("--force");
|
|
@@ -336,16 +415,16 @@ function runLogout() {
|
|
|
336
415
|
console.log(" Note: ORANGESLICE_API_KEY env var is still set in this shell.");
|
|
337
416
|
}
|
|
338
417
|
}
|
|
339
|
-
function runAuthSet(apiKey) {
|
|
418
|
+
function runAuthSet(apiKey, packageManager) {
|
|
340
419
|
const trimmed = apiKey.trim();
|
|
341
420
|
if (!trimmed) {
|
|
342
|
-
console.log(
|
|
421
|
+
console.log(` Usage: ${getRunnerCommand(packageManager, "auth <API_KEY>")}`);
|
|
343
422
|
return;
|
|
344
423
|
}
|
|
345
424
|
saveConfigFile({ apiKey: trimmed });
|
|
346
425
|
console.log(` ✓ API key saved to ${CONFIG_PATH} (${maskKey(trimmed)})`);
|
|
347
426
|
}
|
|
348
|
-
function runAuthStatus() {
|
|
427
|
+
function runAuthStatus(packageManager) {
|
|
349
428
|
const envKey = process.env.ORANGESLICE_API_KEY?.trim() || "";
|
|
350
429
|
if (envKey) {
|
|
351
430
|
console.log(` Authenticated via env var: ${maskKey(envKey)}`);
|
|
@@ -356,11 +435,13 @@ function runAuthStatus() {
|
|
|
356
435
|
console.log(` Authenticated via config file (${CONFIG_PATH}): ${maskKey(fileKey)}`);
|
|
357
436
|
return;
|
|
358
437
|
}
|
|
359
|
-
console.log(
|
|
438
|
+
console.log(` Not authenticated. Run \`${getRunnerCommand(packageManager, "login")}\`.`);
|
|
360
439
|
}
|
|
361
440
|
async function main() {
|
|
362
441
|
const args = process.argv.slice(2);
|
|
363
442
|
const command = args[0];
|
|
443
|
+
const cwd = process.cwd();
|
|
444
|
+
const packageManager = detectPackageManager(cwd);
|
|
364
445
|
if (command === "login") {
|
|
365
446
|
await runLogin(args.slice(1));
|
|
366
447
|
return;
|
|
@@ -372,18 +453,18 @@ async function main() {
|
|
|
372
453
|
if (command === "auth") {
|
|
373
454
|
const subcommand = args[1];
|
|
374
455
|
if (subcommand === "status") {
|
|
375
|
-
runAuthStatus();
|
|
456
|
+
runAuthStatus(packageManager);
|
|
376
457
|
return;
|
|
377
458
|
}
|
|
378
459
|
if (subcommand && subcommand !== "--help" && subcommand !== "-h") {
|
|
379
|
-
runAuthSet(subcommand);
|
|
460
|
+
runAuthSet(subcommand, packageManager);
|
|
380
461
|
return;
|
|
381
462
|
}
|
|
382
|
-
printHelp();
|
|
463
|
+
printHelp(packageManager);
|
|
383
464
|
return;
|
|
384
465
|
}
|
|
385
466
|
if (command && (command === "--help" || command === "-h" || command === "help")) {
|
|
386
|
-
printHelp();
|
|
467
|
+
printHelp(packageManager);
|
|
387
468
|
return;
|
|
388
469
|
}
|
|
389
470
|
console.log("\norangeslice\n");
|
|
@@ -396,11 +477,10 @@ async function main() {
|
|
|
396
477
|
writeClaudeGuide(TARGET_DIR);
|
|
397
478
|
console.log(` ✓ Docs (${path.basename(docsDir)}) → ./orangeslice-docs/\n`);
|
|
398
479
|
// Always set up package installation in the current directory.
|
|
399
|
-
const cwd = process.cwd();
|
|
400
480
|
ensureAgentsImport(cwd);
|
|
401
481
|
ensureClaudeImport(cwd);
|
|
402
482
|
ensurePackageJson(cwd);
|
|
403
|
-
installOrangeslice(cwd);
|
|
483
|
+
installOrangeslice(cwd, packageManager);
|
|
404
484
|
console.log(" ✓ Package installed in current directory\n");
|
|
405
485
|
// API key setup
|
|
406
486
|
await setupApiKey();
|
package/dist/ctx.d.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spreadsheet context API for the orangeslice SDK.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* import { ctx } from "orangeslice";
|
|
6
|
+
*
|
|
7
|
+
* const ss = await ctx.createSpreadsheet({ name: "Leads" });
|
|
8
|
+
* await ctx.sql(ss.id, 'CREATE TABLE contacts (name, email, website)');
|
|
9
|
+
* await ctx.sql(ss.id, "INSERT INTO contacts (name, email) VALUES ('Acme', 'hi@acme.com')");
|
|
10
|
+
* const { rows } = await ctx.sql(ss.id, "SELECT * FROM contacts");
|
|
11
|
+
*
|
|
12
|
+
* // Or bind to a spreadsheet for convenience:
|
|
13
|
+
* const bound = ctx.spreadsheet(ss.id);
|
|
14
|
+
* await bound.sql("SELECT * FROM contacts WHERE name = 'Acme'");
|
|
15
|
+
* await bound.sheet("contacts").addRow({ name: "Corp", email: "corp@example.com" });
|
|
16
|
+
*/
|
|
17
|
+
export interface Spreadsheet {
|
|
18
|
+
id: string;
|
|
19
|
+
name: string;
|
|
20
|
+
}
|
|
21
|
+
export interface SpreadsheetListItem {
|
|
22
|
+
id: string;
|
|
23
|
+
name: string;
|
|
24
|
+
createdAt: string;
|
|
25
|
+
updatedAt: string;
|
|
26
|
+
orgId: string | null;
|
|
27
|
+
userId: string | null;
|
|
28
|
+
}
|
|
29
|
+
export interface SqlQueryResult {
|
|
30
|
+
rows: Record<string, unknown>[];
|
|
31
|
+
rowIds: string[];
|
|
32
|
+
count?: number;
|
|
33
|
+
sql?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface SqlActionResult {
|
|
36
|
+
success: boolean;
|
|
37
|
+
id?: string;
|
|
38
|
+
columns?: Array<{
|
|
39
|
+
id: string;
|
|
40
|
+
name: string;
|
|
41
|
+
}>;
|
|
42
|
+
}
|
|
43
|
+
export type SqlResult = SqlQueryResult | SqlActionResult;
|
|
44
|
+
export declare const ctx: {
|
|
45
|
+
createSpreadsheet: (opts: {
|
|
46
|
+
name: string;
|
|
47
|
+
}) => Promise<Spreadsheet>;
|
|
48
|
+
listSpreadsheets: () => Promise<{
|
|
49
|
+
spreadsheets: SpreadsheetListItem[];
|
|
50
|
+
}>;
|
|
51
|
+
deleteSpreadsheet: (spreadsheetId: string) => Promise<{
|
|
52
|
+
success: boolean;
|
|
53
|
+
}>;
|
|
54
|
+
sql: (spreadsheetId: string, sql: string) => Promise<SqlResult>;
|
|
55
|
+
spreadsheet: (spreadsheetId: string) => {
|
|
56
|
+
sql: (sql: string) => Promise<SqlResult>;
|
|
57
|
+
sheet: (sheetName: string) => {
|
|
58
|
+
addRow: (row: Record<string, unknown>) => Promise<SqlResult>;
|
|
59
|
+
addRows: (rows: Record<string, unknown>[]) => Promise<SqlResult>;
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
};
|
package/dist/ctx.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Spreadsheet context API for the orangeslice SDK.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* import { ctx } from "orangeslice";
|
|
7
|
+
*
|
|
8
|
+
* const ss = await ctx.createSpreadsheet({ name: "Leads" });
|
|
9
|
+
* await ctx.sql(ss.id, 'CREATE TABLE contacts (name, email, website)');
|
|
10
|
+
* await ctx.sql(ss.id, "INSERT INTO contacts (name, email) VALUES ('Acme', 'hi@acme.com')");
|
|
11
|
+
* const { rows } = await ctx.sql(ss.id, "SELECT * FROM contacts");
|
|
12
|
+
*
|
|
13
|
+
* // Or bind to a spreadsheet for convenience:
|
|
14
|
+
* const bound = ctx.spreadsheet(ss.id);
|
|
15
|
+
* await bound.sql("SELECT * FROM contacts WHERE name = 'Acme'");
|
|
16
|
+
* await bound.sheet("contacts").addRow({ name: "Corp", email: "corp@example.com" });
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.ctx = void 0;
|
|
20
|
+
const api_1 = require("./api");
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// SQL builder helpers
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
function escapeValue(val) {
|
|
25
|
+
if (val === null || val === undefined)
|
|
26
|
+
return "NULL";
|
|
27
|
+
if (typeof val === "number") {
|
|
28
|
+
if (!Number.isFinite(val))
|
|
29
|
+
throw new Error(`[orangeslice] Cannot use ${val} as a SQL value`);
|
|
30
|
+
return String(val);
|
|
31
|
+
}
|
|
32
|
+
if (typeof val === "boolean")
|
|
33
|
+
return String(val);
|
|
34
|
+
const str = String(val).replace(/'/g, "''");
|
|
35
|
+
return `'${str}'`;
|
|
36
|
+
}
|
|
37
|
+
function escapeName(name) {
|
|
38
|
+
return `"${name.replace(/"/g, '""')}"`;
|
|
39
|
+
}
|
|
40
|
+
function buildInsertSQL(sheetName, rows) {
|
|
41
|
+
if (rows.length === 0)
|
|
42
|
+
throw new Error("[orangeslice] addRows requires at least one row");
|
|
43
|
+
const allKeys = new Set();
|
|
44
|
+
for (const row of rows) {
|
|
45
|
+
for (const key of Object.keys(row))
|
|
46
|
+
allKeys.add(key);
|
|
47
|
+
}
|
|
48
|
+
const columns = Array.from(allKeys);
|
|
49
|
+
const colList = columns.map(escapeName).join(", ");
|
|
50
|
+
const valueClauses = rows.map((row) => {
|
|
51
|
+
const vals = columns.map((col) => escapeValue(row[col]));
|
|
52
|
+
return `(${vals.join(", ")})`;
|
|
53
|
+
});
|
|
54
|
+
return `INSERT INTO ${escapeName(sheetName)} (${colList}) VALUES ${valueClauses.join(", ")}`;
|
|
55
|
+
}
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
// Validation
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
function assertNotRun(sql) {
|
|
60
|
+
const trimmed = sql.trim().toUpperCase();
|
|
61
|
+
if (trimmed.startsWith("RUN ") || trimmed === "RUN") {
|
|
62
|
+
throw new Error("[orangeslice] RUN commands are not supported via the API");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// ---------------------------------------------------------------------------
|
|
66
|
+
// Bound spreadsheet handle
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
function createSheetHandle(spreadsheetId, sheetName) {
|
|
69
|
+
return {
|
|
70
|
+
addRow: (row) => (0, api_1.post)("/ctx/sql", {
|
|
71
|
+
spreadsheetId,
|
|
72
|
+
sql: buildInsertSQL(sheetName, [row])
|
|
73
|
+
}),
|
|
74
|
+
addRows: (rows) => (0, api_1.post)("/ctx/sql", {
|
|
75
|
+
spreadsheetId,
|
|
76
|
+
sql: buildInsertSQL(sheetName, rows)
|
|
77
|
+
})
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function createSpreadsheetHandle(spreadsheetId) {
|
|
81
|
+
return {
|
|
82
|
+
sql: (sql) => {
|
|
83
|
+
assertNotRun(sql);
|
|
84
|
+
return (0, api_1.post)("/ctx/sql", { spreadsheetId, sql });
|
|
85
|
+
},
|
|
86
|
+
sheet: (sheetName) => createSheetHandle(spreadsheetId, sheetName)
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
// Top-level ctx object
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
exports.ctx = {
|
|
93
|
+
createSpreadsheet: (opts) => (0, api_1.post)("/ctx/spreadsheet/create", opts),
|
|
94
|
+
listSpreadsheets: () => (0, api_1.post)("/ctx/spreadsheet/list", {}),
|
|
95
|
+
deleteSpreadsheet: (spreadsheetId) => (0, api_1.post)("/ctx/spreadsheet/delete", { spreadsheetId }),
|
|
96
|
+
sql: (spreadsheetId, sql) => {
|
|
97
|
+
assertNotRun(sql);
|
|
98
|
+
return (0, api_1.post)("/ctx/sql", { spreadsheetId, sql });
|
|
99
|
+
},
|
|
100
|
+
spreadsheet: (spreadsheetId) => createSpreadsheetHandle(spreadsheetId)
|
|
101
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { configure } from "./api";
|
|
2
2
|
export type { OrangesliceConfig } from "./api";
|
|
3
|
+
export { ctx } from "./ctx";
|
|
4
|
+
export type { Spreadsheet, SpreadsheetListItem, SqlResult, SqlQueryResult, SqlActionResult } from "./ctx";
|
|
3
5
|
export { linkedinSearch } from "./b2b";
|
|
4
6
|
export type { LinkedInSearchParams, LinkedInSearchResponse } from "./b2b";
|
|
5
7
|
export { crunchbaseSearch } from "./crunchbase";
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.services = exports.builtWithSearchByTech = exports.builtWithRelationships = exports.builtWithLookupDomain = exports.geoParseAddress = exports.companyGetEmployeesFromLinkedin = exports.companyLinkedinFindUrl = exports.companyLinkedinEnrich = exports.personContactGet = exports.personLinkedinFindUrl = exports.personLinkedinEnrich = exports.PREDICT_LEADS_OPERATION_IDS = exports.predictLeads = exports.executePredictLeads = exports.googleMapsScrape = exports.runApifyActor = exports.browserExecute = exports.scrapeWebsite = exports.generateObject = exports.webBatchSearch = exports.webSearch = exports.crunchbaseSearch = exports.linkedinSearch = exports.configure = void 0;
|
|
3
|
+
exports.services = exports.builtWithSearchByTech = exports.builtWithRelationships = exports.builtWithLookupDomain = exports.geoParseAddress = exports.companyGetEmployeesFromLinkedin = exports.companyLinkedinFindUrl = exports.companyLinkedinEnrich = exports.personContactGet = exports.personLinkedinFindUrl = exports.personLinkedinEnrich = exports.PREDICT_LEADS_OPERATION_IDS = exports.predictLeads = exports.executePredictLeads = exports.googleMapsScrape = exports.runApifyActor = exports.browserExecute = exports.scrapeWebsite = exports.generateObject = exports.webBatchSearch = exports.webSearch = exports.crunchbaseSearch = exports.linkedinSearch = exports.ctx = exports.configure = void 0;
|
|
4
4
|
var api_1 = require("./api");
|
|
5
5
|
Object.defineProperty(exports, "configure", { enumerable: true, get: function () { return api_1.configure; } });
|
|
6
|
+
var ctx_1 = require("./ctx");
|
|
7
|
+
Object.defineProperty(exports, "ctx", { enumerable: true, get: function () { return ctx_1.ctx; } });
|
|
6
8
|
var b2b_1 = require("./b2b");
|
|
7
9
|
Object.defineProperty(exports, "linkedinSearch", { enumerable: true, get: function () { return b2b_1.linkedinSearch; } });
|
|
8
10
|
var crunchbase_1 = require("./crunchbase");
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# getList
|
|
2
|
+
|
|
3
|
+
Get a specific HubSpot list by ID.
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
// Fetch a list by ID
|
|
7
|
+
const list = await integrations.hubspot.getList("123456");
|
|
8
|
+
|
|
9
|
+
// Include the filter definition in the response
|
|
10
|
+
const detailedList = await integrations.hubspot.getList("123456", {
|
|
11
|
+
includeFilters: true
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
console.log(list.name); // "Target Accounts"
|
|
15
|
+
console.log(list.processingType); // "DYNAMIC"
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Input
|
|
19
|
+
|
|
20
|
+
| Parameter | Type | Description |
|
|
21
|
+
| ------------------------ | --------- | --------------------------------------------------------------------- |
|
|
22
|
+
| `listId` | `string` | The HubSpot list ID to retrieve |
|
|
23
|
+
| `options.includeFilters` | `boolean` | Include the list's filter definition in the response (default: false) |
|
|
24
|
+
|
|
25
|
+
## Output
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
{
|
|
29
|
+
listId: string;
|
|
30
|
+
listVersion: number;
|
|
31
|
+
name: string;
|
|
32
|
+
objectTypeId: string;
|
|
33
|
+
processingStatus: string;
|
|
34
|
+
processingType: string;
|
|
35
|
+
createdAt?: string;
|
|
36
|
+
updatedAt?: string;
|
|
37
|
+
deletedAt?: string;
|
|
38
|
+
createdById?: string;
|
|
39
|
+
updatedById?: string;
|
|
40
|
+
filtersUpdatedAt?: string;
|
|
41
|
+
size?: number;
|
|
42
|
+
membershipSettings?: Record<string, unknown>;
|
|
43
|
+
listPermissions?: Record<string, unknown>;
|
|
44
|
+
filterBranch?: Record<string, unknown>;
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Notes
|
|
49
|
+
|
|
50
|
+
- Set `includeFilters: true` when you need the list's filter definition
|
|
51
|
+
- `objectTypeId` identifies the CRM object type the list contains, such as contacts or companies
|
|
52
|
+
- `processingType` commonly indicates whether the list is dynamic, manual, or snapshot-based
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: HubSpot CRM - contacts, companies, deals, workflows
|
|
2
|
+
description: HubSpot CRM - contacts, companies, deals, lists, workflows
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
# HubSpot Integration
|
|
@@ -41,6 +41,10 @@ Typed functions for HubSpot CRM operations.
|
|
|
41
41
|
- `integrations.hubspot.updateFlow(flowId, input)` - Update an existing workflow
|
|
42
42
|
- `integrations.hubspot.deleteFlow(flowId)` - Delete a workflow
|
|
43
43
|
|
|
44
|
+
## Lists
|
|
45
|
+
|
|
46
|
+
- `integrations.hubspot.getList(listId, options?)` - Get list by ID
|
|
47
|
+
|
|
44
48
|
## Properties
|
|
45
49
|
|
|
46
50
|
- `integrations.hubspot.listProperties(objectType, options?)` - List all property definitions for an object type
|