orangeslice 2.1.5 → 2.4.0-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.
Files changed (37) hide show
  1. package/README.md +20 -1
  2. package/dist/careers.d.ts +47 -0
  3. package/dist/careers.js +11 -0
  4. package/dist/cli.js +12 -1
  5. package/dist/index.d.ts +41 -0
  6. package/dist/index.js +29 -3
  7. package/dist/integrations.d.ts +60 -0
  8. package/dist/integrations.js +107 -0
  9. package/dist/ocean.d.ts +160 -0
  10. package/dist/ocean.js +23 -0
  11. package/dist/skills.d.ts +57 -0
  12. package/dist/skills.js +33 -0
  13. package/docs/data-enrichement/index.md +10 -2
  14. package/docs/integrations/gmail/createDraft.md +54 -0
  15. package/docs/integrations/gmail/fetchEmails.md +50 -0
  16. package/docs/integrations/gmail/fetchMessageByMessageId.md +36 -0
  17. package/docs/integrations/gmail/fetchMessageByThreadId.md +37 -0
  18. package/docs/integrations/gmail/getProfile.md +37 -0
  19. package/docs/integrations/gmail/index.md +19 -2
  20. package/docs/integrations/gmail/listLabels.md +34 -0
  21. package/docs/integrations/gmail/replyToThread.md +51 -0
  22. package/docs/integrations/index.md +14 -1
  23. package/docs/lookalike-search/index.md +24 -12
  24. package/docs/prospecting/index.md +2 -2
  25. package/docs/services/builtWith/index.md +2 -2
  26. package/docs/services/company/findCareersPage.md +137 -0
  27. package/docs/services/company/findCareersPage.ts +37 -0
  28. package/docs/services/company/linkedin/enrich.md +47 -1
  29. package/docs/services/company/scrapeCareersPage.md +150 -0
  30. package/docs/services/index.md +4 -2
  31. package/docs/services/integrations/index.md +128 -0
  32. package/docs/services/ocean/search/companies.ts +122 -119
  33. package/docs/services/person/linkedin/findUrl.md +2 -2
  34. package/docs/services/predictLeads/companyJobOpenings.ts +168 -94
  35. package/docs/services/skills/index.md +97 -0
  36. package/docs/services/web/search.md +29 -14
  37. package/package.json +1 -1
package/README.md CHANGED
@@ -52,6 +52,21 @@ pnpm add orangeslice
52
52
  yarn add orangeslice
53
53
  ```
54
54
 
55
+ ## Integrations & Skills
56
+
57
+ ```ts
58
+ import { integrations, skills } from "orangeslice";
59
+
60
+ // Connect a third-party service (opens browser for OAuth)
61
+ const hubspot = await integrations.connect("hubspot");
62
+
63
+ // List connected integrations
64
+ const { integrations: list } = await integrations.list();
65
+
66
+ // Create a knowledge skill
67
+ await skills.create({ name: "ICP", content: "B2B SaaS, 50-500 employees..." });
68
+ ```
69
+
55
70
  ## Public API (services-first)
56
71
 
57
72
  Use `services.*` as the primary API surface.
@@ -90,8 +105,10 @@ const startups = await services.crunchbase.search({
90
105
  ## Service map
91
106
 
92
107
  - `services.company.linkedin.search/enrich`
108
+ - `services.company.findCareersPage/scrapeCareersPage`
93
109
  - `services.crunchbase.search` (returns rows array directly)
94
110
  - `services.company.getEmployeesFromLinkedin` (database-only B2B path)
111
+ - `services.ocean.search.companies/people`
95
112
  - `services.person.linkedin.search/enrich`
96
113
  - `services.web.search/batchSearch`
97
114
  - `services.ai.generateObject`
@@ -101,12 +118,14 @@ const startups = await services.crunchbase.search({
101
118
  - `services.googleMaps.scrape`
102
119
  - `services.geo.parseAddress`
103
120
  - `services.builtWith.lookupDomain/relationships/searchByTech`
121
+ - `integrations.connect/list/get/create/update/delete`
122
+ - `skills.list/get/create/update/delete`
104
123
 
105
124
  ## How routing works today
106
125
 
107
126
  All service calls go through `post()` in `src/api.ts`.
108
127
 
109
- - Submit path: `https://enrichly-production.up.railway.app/function`
128
+ - Execute paths: `https://enrichly-production.up.railway.app/execute/*` and `https://enrichly-production.up.railway.app/ctx/*`
110
129
  - Pending responses (`pending: true` / `202`) poll batch-service result endpoints.
111
130
  - Polling timeout supports long-running workflows (up to 10 minutes).
112
131
  - This package now exposes only batch-backed services.
@@ -0,0 +1,47 @@
1
+ export interface FindCareersPageParams {
2
+ website?: string;
3
+ url?: string;
4
+ }
5
+ export interface FindCareersPageResult {
6
+ inputUrl: string;
7
+ normalizedWebsiteUrl: string;
8
+ careerPageUrl: string | null;
9
+ pageType: "ats" | "official" | "not_found";
10
+ atsProvider: string | null;
11
+ detectionMethod: "input-ats" | "homepage-ats-link" | "homepage-careers-link" | "deterministic-candidate" | "candidate-ats-link" | "embedded-ats" | "candidate-redirect" | "ats-unverified" | "not-found";
12
+ checkedUrls: string[];
13
+ }
14
+ export interface ScrapeCareersPageParams {
15
+ careersPageUrl?: string;
16
+ url?: string;
17
+ }
18
+ export interface ScrapeCareersPageJob {
19
+ id: string;
20
+ title: string;
21
+ url: string;
22
+ applyUrl: string | null;
23
+ location: string | null;
24
+ locations: string[];
25
+ department: string | null;
26
+ team: string | null;
27
+ employmentType: string | null;
28
+ workplaceType: string | null;
29
+ postedAt: string | null;
30
+ postedText: string | null;
31
+ requisitionId: string | null;
32
+ }
33
+ export interface ScrapeCareersPageResult {
34
+ status: "success" | "unsupported_url" | "unsupported_provider";
35
+ inputUrl: string;
36
+ normalizedBoardUrl: string | null;
37
+ atsProvider: string | null;
38
+ companyName: string | null;
39
+ source: "api" | "html" | null;
40
+ totalJobs: number;
41
+ jobs: ScrapeCareersPageJob[];
42
+ checkedUrls: string[];
43
+ supportedProviders: string[];
44
+ message: string | null;
45
+ }
46
+ export declare function findCareersPage(params: FindCareersPageParams): Promise<FindCareersPageResult>;
47
+ export declare function scrapeCareersPage(params: ScrapeCareersPageParams): Promise<ScrapeCareersPageResult>;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.findCareersPage = findCareersPage;
4
+ exports.scrapeCareersPage = scrapeCareersPage;
5
+ const api_1 = require("./api");
6
+ async function findCareersPage(params) {
7
+ return (0, api_1.post)("/execute/find-careers-page", { ...params });
8
+ }
9
+ async function scrapeCareersPage(params) {
10
+ return (0, api_1.post)("/execute/scrape-careers-page", { ...params });
11
+ }
package/dist/cli.js CHANGED
@@ -179,6 +179,7 @@ Use these docs as the source of truth. If there is any conflict between your pri
179
179
  ## Package Setup (Do Not Guess)
180
180
  - Import from the package name, not a local file path:
181
181
  - \`import { services } from "orangeslice"\`
182
+ - \`import { integrations, skills } from "orangeslice"\` for integration and skill management
182
183
  - \`import { configure, services } from "orangeslice"\` when setting API key programmatically
183
184
  - Do NOT use \`import { services } from "./orangeslice"\` unless the user explicitly has a local wrapper file at that path.
184
185
  - 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.
@@ -192,7 +193,9 @@ Use these docs as the source of truth. If there is any conflict between your pri
192
193
  ## Mandatory Read Order (Before writing code)
193
194
  1. \`./services/index.md\` - service map and capabilities
194
195
  2. Relevant docs under \`./services/**\` for every service you plan to call
195
- 3. \`./prospecting/index.md\` when doing discovery or lead generation tasks
196
+ 3. \`./services/integrations/index.md\` when connecting or managing third-party integrations
197
+ 4. \`./services/skills/index.md\` when managing knowledge skills
198
+ 5. \`./prospecting/index.md\` when doing discovery or lead generation tasks
196
199
 
197
200
  Do not call a service before reading its documentation.
198
201
 
@@ -203,6 +206,12 @@ Do not call a service before reading its documentation.
203
206
  - For broad scraping by URL, use \`services.scrape.website\`.
204
207
  - Use \`services.ai.generateObject\` for structured extraction/classification with a JSON schema.
205
208
 
209
+ ## Integration & Skill Management
210
+ - To connect a third-party service, use \`integrations.connect(provider)\`. This opens the browser for OAuth (HubSpot, Salesforce, Attio, Gmail, Slack) or prompts for an API key (Instantly, HeyReach).
211
+ - To list connected integrations, use \`integrations.list()\`.
212
+ - To manage knowledge skills (ICP descriptions, templates, etc.), use \`skills.create/list/update/delete\`.
213
+ - Read \`./services/integrations/index.md\` and \`./services/skills/index.md\` for full API details.
214
+
206
215
  ## Execution Rules
207
216
  - Parallelize independent async calls with \`Promise.all\`.
208
217
  - Avoid serial \`await\` inside loops when calls can run concurrently.
@@ -246,6 +255,8 @@ This project includes orangeslice for B2B sales operations, lead generation, enr
246
255
  - Structured AI generation
247
256
  - Website scraping and browser execution
248
257
  - PredictLeads and BuiltWith-backed discovery
258
+ - Integration management — connect HubSpot, Salesforce, Attio, Gmail, Slack, Instantly, HeyReach via \`integrations.connect(provider)\`
259
+ - Knowledge skills — create and manage reusable knowledge snippets via \`skills.create/list/update/delete\`
249
260
  `;
250
261
  fs.writeFileSync(CLAUDE_GUIDE_FILE, content, "utf8");
251
262
  }
package/dist/index.d.ts CHANGED
@@ -1,11 +1,19 @@
1
1
  export { configure } from "./api";
2
2
  export type { OrangesliceConfig } from "./api";
3
+ export { integrations } from "./integrations";
4
+ export type { Integration, IntegrationProvider, IntegrationListParams, IntegrationCreateParams, IntegrationUpdateParams, IntegrationConnectOptions } from "./integrations";
5
+ export { skills } from "./skills";
6
+ export type { Skill, SkillListParams, SkillCreateParams, SkillUpdateParams } from "./skills";
7
+ export { findCareersPage, scrapeCareersPage } from "./careers";
8
+ export type { FindCareersPageParams, FindCareersPageResult, ScrapeCareersPageParams, ScrapeCareersPageResult, ScrapeCareersPageJob } from "./careers";
3
9
  export { ctx } from "./ctx";
4
10
  export type { Spreadsheet, SpreadsheetListItem, SqlResult, SqlQueryResult, SqlActionResult, RowsAddResult } from "./ctx";
5
11
  export { linkedinSearch } from "./b2b";
6
12
  export type { LinkedInSearchParams, LinkedInSearchResponse } from "./b2b";
7
13
  export { crunchbaseSearch } from "./crunchbase";
8
14
  export type { CrunchbaseSearchParams } from "./crunchbase";
15
+ export { executeOcean, oceanSearchCompanies, oceanSearchPeople, OCEAN_OPERATION_IDS } from "./ocean";
16
+ export type { OceanOperationId, OceanCompaniesFilters, OceanPeopleFilters, OceanCompaniesSearchParams, OceanCompaniesSearchResponse, OceanCompanyResult, OceanCompanyMatch, OceanPeopleSearchParams, OceanPeopleSearchResponse, OceanPersonResult } from "./ocean";
9
17
  export { webSearch, webBatchSearch } from "./serp";
10
18
  export type { WebSearchQuery, WebSearchResult, WebSearchResponse, BatchWebSearchParams } from "./serp";
11
19
  export { generateObject } from "./generateObject";
@@ -25,11 +33,13 @@ export type { PersonLinkedinFindUrlParams, CompanyLinkedinFindUrlParams, PersonC
25
33
  import { runApifyActor } from "./apify";
26
34
  import { linkedinSearch } from "./b2b";
27
35
  import { browserExecute } from "./browser";
36
+ import { findCareersPage, scrapeCareersPage } from "./careers";
28
37
  import { crunchbaseSearch } from "./crunchbase";
29
38
  import { personLinkedinEnrich, personLinkedinFindUrl, personContactGet, companyLinkedinEnrich, companyLinkedinFindUrl, companyGetEmployeesFromLinkedin, geoParseAddress, builtWithLookupDomain, builtWithRelationships, builtWithSearchByTech } from "./expansion";
30
39
  import { scrapeWebsite } from "./firecrawl";
31
40
  import { generateObject } from "./generateObject";
32
41
  import { googleMapsScrape } from "./googleMaps";
42
+ import { oceanSearchCompanies, oceanSearchPeople } from "./ocean";
33
43
  import { webBatchSearch, webSearch } from "./serp";
34
44
  export declare const services: {
35
45
  crunchbase: {
@@ -42,6 +52,8 @@ export declare const services: {
42
52
  search: typeof linkedinSearch;
43
53
  };
44
54
  getEmployeesFromLinkedin: typeof companyGetEmployeesFromLinkedin;
55
+ findCareersPage: typeof findCareersPage;
56
+ scrapeCareersPage: typeof scrapeCareersPage;
45
57
  };
46
58
  person: {
47
59
  linkedin: {
@@ -75,11 +87,40 @@ export declare const services: {
75
87
  googleMaps: {
76
88
  scrape: typeof googleMapsScrape;
77
89
  };
90
+ ocean: {
91
+ search: {
92
+ companies: typeof oceanSearchCompanies;
93
+ people: typeof oceanSearchPeople;
94
+ };
95
+ };
78
96
  builtWith: {
79
97
  lookupDomain: typeof builtWithLookupDomain;
80
98
  relationships: typeof builtWithRelationships;
81
99
  searchByTech: typeof builtWithSearchByTech;
82
100
  };
83
101
  predictLeads: Readonly<import("./predictLeads").PredictLeadsServiceMap>;
102
+ integrations: {
103
+ connect: (provider: import("./integrations").IntegrationProvider, opts?: import("./integrations").IntegrationConnectOptions) => Promise<import("./integrations").Integration>;
104
+ list: (opts?: import("./integrations").IntegrationListParams) => Promise<{
105
+ integrations: import("./integrations").Integration[];
106
+ }>;
107
+ get: (id: string) => Promise<import("./integrations").Integration>;
108
+ create: (opts: import("./integrations").IntegrationCreateParams) => Promise<import("./integrations").Integration>;
109
+ update: (id: string, fields: import("./integrations").IntegrationUpdateParams) => Promise<import("./integrations").Integration>;
110
+ delete: (id: string) => Promise<{
111
+ success: boolean;
112
+ }>;
113
+ };
114
+ skills: {
115
+ list: (opts?: import("./skills").SkillListParams) => Promise<{
116
+ skills: import("./skills").Skill[];
117
+ }>;
118
+ get: (id: string) => Promise<import("./skills").Skill>;
119
+ create: (opts: import("./skills").SkillCreateParams) => Promise<import("./skills").Skill>;
120
+ update: (id: string, fields: import("./skills").SkillUpdateParams) => Promise<import("./skills").Skill>;
121
+ delete: (id: string) => Promise<{
122
+ success: boolean;
123
+ }>;
124
+ };
84
125
  };
85
126
  export default services;
package/dist/index.js CHANGED
@@ -1,14 +1,26 @@
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.ctx = 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.OCEAN_OPERATION_IDS = exports.oceanSearchPeople = exports.oceanSearchCompanies = exports.executeOcean = exports.crunchbaseSearch = exports.linkedinSearch = exports.ctx = exports.scrapeCareersPage = exports.findCareersPage = exports.skills = exports.integrations = 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 integrations_1 = require("./integrations");
7
+ Object.defineProperty(exports, "integrations", { enumerable: true, get: function () { return integrations_1.integrations; } });
8
+ var skills_1 = require("./skills");
9
+ Object.defineProperty(exports, "skills", { enumerable: true, get: function () { return skills_1.skills; } });
10
+ var careers_1 = require("./careers");
11
+ Object.defineProperty(exports, "findCareersPage", { enumerable: true, get: function () { return careers_1.findCareersPage; } });
12
+ Object.defineProperty(exports, "scrapeCareersPage", { enumerable: true, get: function () { return careers_1.scrapeCareersPage; } });
6
13
  var ctx_1 = require("./ctx");
7
14
  Object.defineProperty(exports, "ctx", { enumerable: true, get: function () { return ctx_1.ctx; } });
8
15
  var b2b_1 = require("./b2b");
9
16
  Object.defineProperty(exports, "linkedinSearch", { enumerable: true, get: function () { return b2b_1.linkedinSearch; } });
10
17
  var crunchbase_1 = require("./crunchbase");
11
18
  Object.defineProperty(exports, "crunchbaseSearch", { enumerable: true, get: function () { return crunchbase_1.crunchbaseSearch; } });
19
+ var ocean_1 = require("./ocean");
20
+ Object.defineProperty(exports, "executeOcean", { enumerable: true, get: function () { return ocean_1.executeOcean; } });
21
+ Object.defineProperty(exports, "oceanSearchCompanies", { enumerable: true, get: function () { return ocean_1.oceanSearchCompanies; } });
22
+ Object.defineProperty(exports, "oceanSearchPeople", { enumerable: true, get: function () { return ocean_1.oceanSearchPeople; } });
23
+ Object.defineProperty(exports, "OCEAN_OPERATION_IDS", { enumerable: true, get: function () { return ocean_1.OCEAN_OPERATION_IDS; } });
12
24
  var serp_1 = require("./serp");
13
25
  Object.defineProperty(exports, "webSearch", { enumerable: true, get: function () { return serp_1.webSearch; } });
14
26
  Object.defineProperty(exports, "webBatchSearch", { enumerable: true, get: function () { return serp_1.webBatchSearch; } });
@@ -40,11 +52,15 @@ Object.defineProperty(exports, "builtWithSearchByTech", { enumerable: true, get:
40
52
  const apify_2 = require("./apify");
41
53
  const b2b_2 = require("./b2b");
42
54
  const browser_2 = require("./browser");
55
+ const careers_2 = require("./careers");
43
56
  const crunchbase_2 = require("./crunchbase");
57
+ const integrations_2 = require("./integrations");
58
+ const skills_2 = require("./skills");
44
59
  const expansion_2 = require("./expansion");
45
60
  const firecrawl_2 = require("./firecrawl");
46
61
  const generateObject_2 = require("./generateObject");
47
62
  const googleMaps_2 = require("./googleMaps");
63
+ const ocean_2 = require("./ocean");
48
64
  const predictLeads_2 = require("./predictLeads");
49
65
  const serp_2 = require("./serp");
50
66
  exports.services = {
@@ -57,7 +73,9 @@ exports.services = {
57
73
  enrich: expansion_2.companyLinkedinEnrich,
58
74
  search: b2b_2.linkedinSearch
59
75
  },
60
- getEmployeesFromLinkedin: expansion_2.companyGetEmployeesFromLinkedin
76
+ getEmployeesFromLinkedin: expansion_2.companyGetEmployeesFromLinkedin,
77
+ findCareersPage: careers_2.findCareersPage,
78
+ scrapeCareersPage: careers_2.scrapeCareersPage
61
79
  },
62
80
  person: {
63
81
  linkedin: {
@@ -91,11 +109,19 @@ exports.services = {
91
109
  googleMaps: {
92
110
  scrape: googleMaps_2.googleMapsScrape
93
111
  },
112
+ ocean: {
113
+ search: {
114
+ companies: ocean_2.oceanSearchCompanies,
115
+ people: ocean_2.oceanSearchPeople
116
+ }
117
+ },
94
118
  builtWith: {
95
119
  lookupDomain: expansion_2.builtWithLookupDomain,
96
120
  relationships: expansion_2.builtWithRelationships,
97
121
  searchByTech: expansion_2.builtWithSearchByTech
98
122
  },
99
- predictLeads: predictLeads_2.predictLeads
123
+ predictLeads: predictLeads_2.predictLeads,
124
+ integrations: integrations_2.integrations,
125
+ skills: skills_2.skills
100
126
  };
101
127
  exports.default = exports.services;
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Integrations API for the orangeslice SDK.
3
+ *
4
+ * Usage:
5
+ * import { integrations } from "orangeslice";
6
+ *
7
+ * // Connect an OAuth provider (opens browser)
8
+ * const hubspot = await integrations.connect("hubspot");
9
+ *
10
+ * // List connected integrations
11
+ * const { integrations: list } = await integrations.list();
12
+ *
13
+ * // Programmatic API-key create (no browser)
14
+ * await integrations.create({ provider: "instantly", apiKey: "inst_..." });
15
+ */
16
+ export type IntegrationProvider = "hubspot" | "salesforce" | "attio" | "gmail" | "slack" | "instantly" | "heyreach";
17
+ export interface Integration {
18
+ id: string;
19
+ provider: string;
20
+ displayName: string;
21
+ isActive: boolean;
22
+ hasApiKey: boolean;
23
+ hasOauthToken: boolean;
24
+ createdAt: string;
25
+ updatedAt: string;
26
+ scope: "account" | "spreadsheet";
27
+ spreadsheetId?: string | null;
28
+ }
29
+ export interface IntegrationListParams {
30
+ spreadsheetId?: string;
31
+ provider?: IntegrationProvider;
32
+ }
33
+ export interface IntegrationCreateParams {
34
+ provider: IntegrationProvider;
35
+ apiKey: string;
36
+ displayName?: string;
37
+ config?: Record<string, string>;
38
+ spreadsheetId?: string;
39
+ }
40
+ export interface IntegrationUpdateParams {
41
+ apiKey?: string;
42
+ displayName?: string;
43
+ isActive?: boolean;
44
+ config?: Record<string, string>;
45
+ }
46
+ export interface IntegrationConnectOptions {
47
+ noBrowser?: boolean;
48
+ }
49
+ export declare const integrations: {
50
+ connect: (provider: IntegrationProvider, opts?: IntegrationConnectOptions) => Promise<Integration>;
51
+ list: (opts?: IntegrationListParams) => Promise<{
52
+ integrations: Integration[];
53
+ }>;
54
+ get: (id: string) => Promise<Integration>;
55
+ create: (opts: IntegrationCreateParams) => Promise<Integration>;
56
+ update: (id: string, fields: IntegrationUpdateParams) => Promise<Integration>;
57
+ delete: (id: string) => Promise<{
58
+ success: boolean;
59
+ }>;
60
+ };
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ /**
3
+ * Integrations API for the orangeslice SDK.
4
+ *
5
+ * Usage:
6
+ * import { integrations } from "orangeslice";
7
+ *
8
+ * // Connect an OAuth provider (opens browser)
9
+ * const hubspot = await integrations.connect("hubspot");
10
+ *
11
+ * // List connected integrations
12
+ * const { integrations: list } = await integrations.list();
13
+ *
14
+ * // Programmatic API-key create (no browser)
15
+ * await integrations.create({ provider: "instantly", apiKey: "inst_..." });
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.integrations = void 0;
19
+ const api_1 = require("./api");
20
+ // ---------------------------------------------------------------------------
21
+ // Constants
22
+ // ---------------------------------------------------------------------------
23
+ const DEFAULT_AUTH_BASE_URL = "https://www.orangeslice.ai";
24
+ const CONNECT_POLL_TIMEOUT_MS = 600000;
25
+ function resolveAuthBaseUrl() {
26
+ return (process.env.ORANGESLICE_AUTH_BASE_URL || DEFAULT_AUTH_BASE_URL).replace(/\/+$/, "");
27
+ }
28
+ // ---------------------------------------------------------------------------
29
+ // Browser helper (same as cli.ts)
30
+ // ---------------------------------------------------------------------------
31
+ function openBrowser(url) {
32
+ if (!process?.versions?.node) {
33
+ console.log(` Open this URL in your browser:\n ${url}\n`);
34
+ return;
35
+ }
36
+ try {
37
+ const { execFileSync } = require("child_process");
38
+ if (process.platform === "darwin") {
39
+ execFileSync("open", [url], { stdio: "ignore" });
40
+ return;
41
+ }
42
+ if (process.platform === "win32") {
43
+ execFileSync("cmd.exe", ["/c", "start", "", url], { stdio: "ignore" });
44
+ return;
45
+ }
46
+ execFileSync("xdg-open", [url], { stdio: "ignore" });
47
+ }
48
+ catch {
49
+ console.log(` Open this URL in your browser:\n ${url}\n`);
50
+ }
51
+ }
52
+ function sleep(ms) {
53
+ return new Promise((resolve) => setTimeout(resolve, ms));
54
+ }
55
+ // ---------------------------------------------------------------------------
56
+ // Connect (device flow via Next.js)
57
+ // ---------------------------------------------------------------------------
58
+ async function connectIntegration(provider, opts) {
59
+ const authBase = resolveAuthBaseUrl();
60
+ const startRes = await fetch(`${authBase}/api/orangeslice/integrations/connect/start`, {
61
+ method: "POST",
62
+ headers: { "Content-Type": "application/json" },
63
+ body: JSON.stringify({ provider })
64
+ });
65
+ if (!startRes.ok) {
66
+ const data = (await startRes.json().catch(() => ({})));
67
+ throw new Error(`[orangeslice] integrations.connect: ${data.error || "Failed to start connect flow"}`);
68
+ }
69
+ const start = (await startRes.json());
70
+ console.log(`\n Connect ${provider}: ${start.verificationUrl}\n`);
71
+ if (!opts?.noBrowser) {
72
+ openBrowser(start.verificationUrl);
73
+ }
74
+ const timeoutAt = Date.now() + CONNECT_POLL_TIMEOUT_MS;
75
+ let pollInterval = start.pollIntervalMs > 0 ? start.pollIntervalMs : 1000;
76
+ while (Date.now() < timeoutAt) {
77
+ await sleep(pollInterval);
78
+ const pollRes = await fetch(`${authBase}/api/orangeslice/integrations/connect/poll?deviceCode=${encodeURIComponent(start.deviceCode)}`, { method: "GET", headers: { "Content-Type": "application/json" } });
79
+ const data = (await pollRes.json());
80
+ if (data.status === "pending")
81
+ continue;
82
+ if (data.status === "approved" && data.integration) {
83
+ return data.integration;
84
+ }
85
+ if (data.status === "expired") {
86
+ throw new Error(`[orangeslice] integrations.connect: Device code expired. Please try again.`);
87
+ }
88
+ if (data.status === "consumed") {
89
+ throw new Error(`[orangeslice] integrations.connect: Device code already used.`);
90
+ }
91
+ if (!pollRes.ok) {
92
+ throw new Error(`[orangeslice] integrations.connect: ${data.error || "Polling failed"}`);
93
+ }
94
+ }
95
+ throw new Error(`[orangeslice] integrations.connect: Timed out waiting for authorization.`);
96
+ }
97
+ // ---------------------------------------------------------------------------
98
+ // CRUD (via batch-service)
99
+ // ---------------------------------------------------------------------------
100
+ exports.integrations = {
101
+ connect: (provider, opts) => connectIntegration(provider, opts),
102
+ list: (opts) => (0, api_1.post)("/ctx/integrations/list", (opts ?? {})),
103
+ get: (id) => (0, api_1.post)("/ctx/integrations/get", { id }),
104
+ create: (opts) => (0, api_1.post)("/ctx/integrations/create", opts),
105
+ update: (id, fields) => (0, api_1.post)("/ctx/integrations/update", { id, ...fields }),
106
+ delete: (id) => (0, api_1.post)("/ctx/integrations/delete", { id })
107
+ };
@@ -0,0 +1,160 @@
1
+ export declare const OCEAN_OPERATION_IDS: {
2
+ readonly searchCompanies: "search-companies";
3
+ readonly searchPeople: "search-people";
4
+ };
5
+ export type OceanOperationId = (typeof OCEAN_OPERATION_IDS)[keyof typeof OCEAN_OPERATION_IDS];
6
+ export interface OceanCompaniesFilters {
7
+ lookalikeDomains?: string[];
8
+ companySizes?: Array<"0-1" | "2-10" | "11-50" | "51-200" | "201-500" | "501-1000" | "1001-5000" | "5001-10000" | "10001+">;
9
+ countries?: string[];
10
+ industries?: string[];
11
+ ecommerce?: boolean;
12
+ }
13
+ export interface OceanPeopleFilters {
14
+ seniorities?: string[];
15
+ departments?: string[];
16
+ jobTitleKeywords?: string[];
17
+ countries?: string[];
18
+ lookalikePeopleIds?: string[];
19
+ }
20
+ export interface OceanCompaniesSearchParams {
21
+ companiesFilters?: OceanCompaniesFilters;
22
+ peopleFilters?: OceanPeopleFilters;
23
+ size?: number;
24
+ searchAfter?: string;
25
+ }
26
+ export interface OceanPhone {
27
+ country?: string;
28
+ number: string;
29
+ primary?: boolean;
30
+ }
31
+ export interface OceanMediaProfile {
32
+ url?: string;
33
+ handle?: string;
34
+ name?: string;
35
+ }
36
+ export interface OceanLocation {
37
+ primary?: boolean;
38
+ latitude?: number;
39
+ longitude?: number;
40
+ country?: string;
41
+ locality?: string;
42
+ region?: string;
43
+ postalCode?: string;
44
+ streetAddress?: string;
45
+ state?: string;
46
+ }
47
+ export interface OceanDepartmentSize {
48
+ department: string;
49
+ size: number;
50
+ }
51
+ export interface OceanHeadcountGrowth {
52
+ threeMonths?: number;
53
+ threeMonthsPercentage?: number;
54
+ sixMonths?: number;
55
+ sixMonthsPercentage?: number;
56
+ twelveMonths?: number;
57
+ twelveMonthsPercentage?: number;
58
+ }
59
+ export interface OceanCompanyResult {
60
+ domain: string;
61
+ name?: string;
62
+ legalName?: string;
63
+ description?: string;
64
+ countries?: string[];
65
+ primaryCountry?: string;
66
+ companySize?: string;
67
+ industryCategories?: string[];
68
+ industries?: string[];
69
+ linkedinIndustry?: string;
70
+ ecommerce?: boolean;
71
+ keywords?: string[];
72
+ employeeCountOcean?: number;
73
+ employeeCountLinkedin?: number;
74
+ revenue?: string;
75
+ yearFounded?: number;
76
+ emails?: string[];
77
+ phones?: OceanPhone[];
78
+ logo?: string;
79
+ technologies?: string[];
80
+ technologyCategories?: string[];
81
+ rootUrl?: string;
82
+ medias?: Record<string, OceanMediaProfile>;
83
+ locations?: OceanLocation[];
84
+ departmentSizes?: OceanDepartmentSize[];
85
+ headcountGrowth?: OceanHeadcountGrowth;
86
+ updatedAt?: string;
87
+ }
88
+ export interface OceanCompanyMatch {
89
+ company: OceanCompanyResult;
90
+ relevance?: string;
91
+ }
92
+ export interface OceanCompaniesSearchResponse {
93
+ detail?: string;
94
+ total: number;
95
+ searchAfter?: string;
96
+ companies: OceanCompanyMatch[];
97
+ redirectMap?: Record<string, string>;
98
+ }
99
+ export interface OceanPersonExperience {
100
+ dateFrom?: string;
101
+ dateTo?: string;
102
+ description?: string;
103
+ domain?: string;
104
+ jobTitle?: string;
105
+ }
106
+ export interface OceanContactField {
107
+ address?: string;
108
+ status?: string;
109
+ }
110
+ export interface OceanPhoneField {
111
+ numbers?: string[];
112
+ status?: string;
113
+ }
114
+ export interface OceanPersonCompanySnapshot {
115
+ companySize?: string;
116
+ logo?: string;
117
+ name?: string;
118
+ }
119
+ export interface OceanPersonResult {
120
+ id: string;
121
+ domain?: string;
122
+ name?: string;
123
+ firstName?: string;
124
+ lastName?: string;
125
+ country?: string;
126
+ state?: string;
127
+ location?: string;
128
+ linkedinUrl?: string;
129
+ seniorities?: string[];
130
+ departments?: string[];
131
+ photo?: string;
132
+ jobTitle?: string;
133
+ jobTitleEnglish?: string;
134
+ currentJobDescription?: string;
135
+ experiences?: OceanPersonExperience[];
136
+ summary?: string;
137
+ skills?: string[];
138
+ phone?: OceanPhoneField;
139
+ email?: OceanContactField;
140
+ updatedAt?: string;
141
+ company?: OceanPersonCompanySnapshot;
142
+ }
143
+ export interface OceanPeopleSearchParams {
144
+ companiesFilters?: OceanCompaniesFilters;
145
+ peopleFilters?: OceanPeopleFilters;
146
+ size?: number;
147
+ from?: number;
148
+ searchAfter?: string;
149
+ enableEmailSearch?: boolean;
150
+ enablePhoneSearch?: boolean;
151
+ }
152
+ export interface OceanPeopleSearchResponse {
153
+ total: number;
154
+ searchAfter?: string;
155
+ people: OceanPersonResult[];
156
+ redirectMap?: Record<string, string>;
157
+ }
158
+ export declare function executeOcean<T = unknown>(operationId: OceanOperationId, params?: Record<string, unknown>): Promise<T>;
159
+ export declare function oceanSearchCompanies(params: OceanCompaniesSearchParams): Promise<OceanCompaniesSearchResponse>;
160
+ export declare function oceanSearchPeople(params: OceanPeopleSearchParams): Promise<OceanPeopleSearchResponse>;
package/dist/ocean.js ADDED
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OCEAN_OPERATION_IDS = void 0;
4
+ exports.executeOcean = executeOcean;
5
+ exports.oceanSearchCompanies = oceanSearchCompanies;
6
+ exports.oceanSearchPeople = oceanSearchPeople;
7
+ const api_1 = require("./api");
8
+ exports.OCEAN_OPERATION_IDS = {
9
+ searchCompanies: "search-companies",
10
+ searchPeople: "search-people"
11
+ };
12
+ async function executeOcean(operationId, params) {
13
+ return (0, api_1.post)("/execute/oceanio", {
14
+ operationId,
15
+ params: params ?? {}
16
+ });
17
+ }
18
+ async function oceanSearchCompanies(params) {
19
+ return executeOcean(exports.OCEAN_OPERATION_IDS.searchCompanies, params);
20
+ }
21
+ async function oceanSearchPeople(params) {
22
+ return executeOcean(exports.OCEAN_OPERATION_IDS.searchPeople, params);
23
+ }