orangeslice 2.1.3 → 2.1.4-beta.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/dist/ctx.d.ts +63 -0
- package/dist/ctx.js +102 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +5 -1
- package/docs/services/ctx/index.md +70 -0
- package/docs/services/index.md +1 -0
- package/package.json +1 -1
package/dist/ctx.d.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spreadsheet context API for the orangeslice SDK.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* import { services } from "orangeslice";
|
|
6
|
+
* const { ctx } = services;
|
|
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
|
+
export interface Spreadsheet {
|
|
19
|
+
id: string;
|
|
20
|
+
name: string;
|
|
21
|
+
}
|
|
22
|
+
export interface SpreadsheetListItem {
|
|
23
|
+
id: string;
|
|
24
|
+
name: string;
|
|
25
|
+
createdAt: string;
|
|
26
|
+
updatedAt: string;
|
|
27
|
+
orgId: string | null;
|
|
28
|
+
userId: string | null;
|
|
29
|
+
}
|
|
30
|
+
export interface SqlQueryResult {
|
|
31
|
+
rows: Record<string, unknown>[];
|
|
32
|
+
rowIds: string[];
|
|
33
|
+
count?: number;
|
|
34
|
+
sql?: string;
|
|
35
|
+
}
|
|
36
|
+
export interface SqlActionResult {
|
|
37
|
+
success: boolean;
|
|
38
|
+
id?: string;
|
|
39
|
+
columns?: Array<{
|
|
40
|
+
id: string;
|
|
41
|
+
name: string;
|
|
42
|
+
}>;
|
|
43
|
+
}
|
|
44
|
+
export type SqlResult = SqlQueryResult | SqlActionResult;
|
|
45
|
+
export declare const ctx: {
|
|
46
|
+
createSpreadsheet: (opts: {
|
|
47
|
+
name: string;
|
|
48
|
+
}) => Promise<Spreadsheet>;
|
|
49
|
+
listSpreadsheets: () => Promise<{
|
|
50
|
+
spreadsheets: SpreadsheetListItem[];
|
|
51
|
+
}>;
|
|
52
|
+
deleteSpreadsheet: (spreadsheetId: string) => Promise<{
|
|
53
|
+
success: boolean;
|
|
54
|
+
}>;
|
|
55
|
+
sql: (spreadsheetId: string, sql: string) => Promise<SqlResult>;
|
|
56
|
+
spreadsheet: (spreadsheetId: string) => {
|
|
57
|
+
sql: (sql: string) => Promise<SqlResult>;
|
|
58
|
+
sheet: (sheetName: string) => {
|
|
59
|
+
addRow: (row: Record<string, unknown>) => Promise<SqlResult>;
|
|
60
|
+
addRows: (rows: Record<string, unknown>[]) => Promise<SqlResult>;
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
};
|
package/dist/ctx.js
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Spreadsheet context API for the orangeslice SDK.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* import { services } from "orangeslice";
|
|
7
|
+
* const { ctx } = services;
|
|
8
|
+
*
|
|
9
|
+
* const ss = await ctx.createSpreadsheet({ name: "Leads" });
|
|
10
|
+
* await ctx.sql(ss.id, 'CREATE TABLE contacts (name, email, website)');
|
|
11
|
+
* await ctx.sql(ss.id, "INSERT INTO contacts (name, email) VALUES ('Acme', 'hi@acme.com')");
|
|
12
|
+
* const { rows } = await ctx.sql(ss.id, "SELECT * FROM contacts");
|
|
13
|
+
*
|
|
14
|
+
* // Or bind to a spreadsheet for convenience:
|
|
15
|
+
* const bound = ctx.spreadsheet(ss.id);
|
|
16
|
+
* await bound.sql("SELECT * FROM contacts WHERE name = 'Acme'");
|
|
17
|
+
* await bound.sheet("contacts").addRow({ name: "Corp", email: "corp@example.com" });
|
|
18
|
+
*/
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.ctx = void 0;
|
|
21
|
+
const api_1 = require("./api");
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// SQL builder helpers
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
function escapeValue(val) {
|
|
26
|
+
if (val === null || val === undefined)
|
|
27
|
+
return "NULL";
|
|
28
|
+
if (typeof val === "number") {
|
|
29
|
+
if (!Number.isFinite(val))
|
|
30
|
+
throw new Error(`[orangeslice] Cannot use ${val} as a SQL value`);
|
|
31
|
+
return String(val);
|
|
32
|
+
}
|
|
33
|
+
if (typeof val === "boolean")
|
|
34
|
+
return String(val);
|
|
35
|
+
const str = String(val).replace(/'/g, "''");
|
|
36
|
+
return `'${str}'`;
|
|
37
|
+
}
|
|
38
|
+
function escapeName(name) {
|
|
39
|
+
return `"${name.replace(/"/g, '""')}"`;
|
|
40
|
+
}
|
|
41
|
+
function buildInsertSQL(sheetName, rows) {
|
|
42
|
+
if (rows.length === 0)
|
|
43
|
+
throw new Error("[orangeslice] addRows requires at least one row");
|
|
44
|
+
const allKeys = new Set();
|
|
45
|
+
for (const row of rows) {
|
|
46
|
+
for (const key of Object.keys(row))
|
|
47
|
+
allKeys.add(key);
|
|
48
|
+
}
|
|
49
|
+
const columns = Array.from(allKeys);
|
|
50
|
+
const colList = columns.map(escapeName).join(", ");
|
|
51
|
+
const valueClauses = rows.map((row) => {
|
|
52
|
+
const vals = columns.map((col) => escapeValue(row[col]));
|
|
53
|
+
return `(${vals.join(", ")})`;
|
|
54
|
+
});
|
|
55
|
+
return `INSERT INTO ${escapeName(sheetName)} (${colList}) VALUES ${valueClauses.join(", ")}`;
|
|
56
|
+
}
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
// Validation
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
function assertNotRun(sql) {
|
|
61
|
+
const trimmed = sql.trim().toUpperCase();
|
|
62
|
+
if (trimmed.startsWith("RUN ") || trimmed === "RUN") {
|
|
63
|
+
throw new Error("[orangeslice] RUN commands are not supported via the API");
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
// Bound spreadsheet handle
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
function createSheetHandle(spreadsheetId, sheetName) {
|
|
70
|
+
return {
|
|
71
|
+
addRow: (row) => (0, api_1.post)("/ctx/sql", {
|
|
72
|
+
spreadsheetId,
|
|
73
|
+
sql: buildInsertSQL(sheetName, [row])
|
|
74
|
+
}),
|
|
75
|
+
addRows: (rows) => (0, api_1.post)("/ctx/sql", {
|
|
76
|
+
spreadsheetId,
|
|
77
|
+
sql: buildInsertSQL(sheetName, rows)
|
|
78
|
+
})
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function createSpreadsheetHandle(spreadsheetId) {
|
|
82
|
+
return {
|
|
83
|
+
sql: (sql) => {
|
|
84
|
+
assertNotRun(sql);
|
|
85
|
+
return (0, api_1.post)("/ctx/sql", { spreadsheetId, sql });
|
|
86
|
+
},
|
|
87
|
+
sheet: (sheetName) => createSheetHandle(spreadsheetId, sheetName)
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
// Top-level ctx object
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
exports.ctx = {
|
|
94
|
+
createSpreadsheet: (opts) => (0, api_1.post)("/ctx/spreadsheet/create", opts),
|
|
95
|
+
listSpreadsheets: () => (0, api_1.post)("/ctx/spreadsheet/list", {}),
|
|
96
|
+
deleteSpreadsheet: (spreadsheetId) => (0, api_1.post)("/ctx/spreadsheet/delete", { spreadsheetId }),
|
|
97
|
+
sql: (spreadsheetId, sql) => {
|
|
98
|
+
assertNotRun(sql);
|
|
99
|
+
return (0, api_1.post)("/ctx/sql", { spreadsheetId, sql });
|
|
100
|
+
},
|
|
101
|
+
spreadsheet: (spreadsheetId) => createSpreadsheetHandle(spreadsheetId)
|
|
102
|
+
};
|
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";
|
|
@@ -30,6 +32,25 @@ import { generateObject } from "./generateObject";
|
|
|
30
32
|
import { googleMapsScrape } from "./googleMaps";
|
|
31
33
|
import { webBatchSearch, webSearch } from "./serp";
|
|
32
34
|
export declare const services: {
|
|
35
|
+
ctx: {
|
|
36
|
+
createSpreadsheet: (opts: {
|
|
37
|
+
name: string;
|
|
38
|
+
}) => Promise<import("./ctx").Spreadsheet>;
|
|
39
|
+
listSpreadsheets: () => Promise<{
|
|
40
|
+
spreadsheets: import("./ctx").SpreadsheetListItem[];
|
|
41
|
+
}>;
|
|
42
|
+
deleteSpreadsheet: (spreadsheetId: string) => Promise<{
|
|
43
|
+
success: boolean;
|
|
44
|
+
}>;
|
|
45
|
+
sql: (spreadsheetId: string, sql: string) => Promise<import("./ctx").SqlResult>;
|
|
46
|
+
spreadsheet: (spreadsheetId: string) => {
|
|
47
|
+
sql: (sql: string) => Promise<import("./ctx").SqlResult>;
|
|
48
|
+
sheet: (sheetName: string) => {
|
|
49
|
+
addRow: (row: Record<string, unknown>) => Promise<import("./ctx").SqlResult>;
|
|
50
|
+
addRows: (rows: Record<string, unknown>[]) => Promise<import("./ctx").SqlResult>;
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
};
|
|
33
54
|
crunchbase: {
|
|
34
55
|
search: typeof crunchbaseSearch;
|
|
35
56
|
};
|
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");
|
|
@@ -39,6 +41,7 @@ const apify_2 = require("./apify");
|
|
|
39
41
|
const b2b_2 = require("./b2b");
|
|
40
42
|
const browser_2 = require("./browser");
|
|
41
43
|
const crunchbase_2 = require("./crunchbase");
|
|
44
|
+
const ctx_2 = require("./ctx");
|
|
42
45
|
const expansion_2 = require("./expansion");
|
|
43
46
|
const firecrawl_2 = require("./firecrawl");
|
|
44
47
|
const generateObject_2 = require("./generateObject");
|
|
@@ -46,6 +49,7 @@ const googleMaps_2 = require("./googleMaps");
|
|
|
46
49
|
const predictLeads_2 = require("./predictLeads");
|
|
47
50
|
const serp_2 = require("./serp");
|
|
48
51
|
exports.services = {
|
|
52
|
+
ctx: ctx_2.ctx,
|
|
49
53
|
crunchbase: {
|
|
50
54
|
search: crunchbase_2.crunchbaseSearch
|
|
51
55
|
},
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Spreadsheet management — create spreadsheets, run SQL, add rows
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# ctx — Spreadsheet Context API
|
|
6
|
+
|
|
7
|
+
Manage Orange Slice spreadsheets programmatically. Create spreadsheets, add sheets and columns via SQL, query data, insert rows.
|
|
8
|
+
|
|
9
|
+
## Quick start
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
import { services } from "orangeslice";
|
|
13
|
+
const { ctx } = services;
|
|
14
|
+
|
|
15
|
+
// Create a spreadsheet
|
|
16
|
+
const ss = await ctx.createSpreadsheet({ name: "Leads" });
|
|
17
|
+
|
|
18
|
+
// Create a sheet with columns
|
|
19
|
+
await ctx.sql(ss.id, "CREATE TABLE contacts (name, email, website)");
|
|
20
|
+
|
|
21
|
+
// Insert data
|
|
22
|
+
await ctx.sql(ss.id, "INSERT INTO contacts (name, email) VALUES ('Acme', 'hi@acme.com')");
|
|
23
|
+
|
|
24
|
+
// Query data
|
|
25
|
+
const result = await ctx.sql(ss.id, "SELECT * FROM contacts WHERE name = 'Acme'");
|
|
26
|
+
console.log(result.rows);
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Methods
|
|
30
|
+
|
|
31
|
+
### Top-level
|
|
32
|
+
|
|
33
|
+
- **`ctx.createSpreadsheet({ name })`** — Create a new spreadsheet. The scope (personal vs org) is determined by the API key. Returns `{ id, name }`.
|
|
34
|
+
- **`ctx.listSpreadsheets()`** — List spreadsheets visible to the API key's scope. Returns `{ spreadsheets: [...] }`.
|
|
35
|
+
- **`ctx.deleteSpreadsheet(spreadsheetId)`** — Soft-delete a spreadsheet (must be within the API key's scope).
|
|
36
|
+
- **`ctx.sql(spreadsheetId, sql)`** — Execute EAV-SQL against a spreadsheet within the API key's scope (see SQL reference below).
|
|
37
|
+
|
|
38
|
+
### Bound spreadsheet
|
|
39
|
+
|
|
40
|
+
Call `ctx.spreadsheet(id)` to get a handle bound to a specific spreadsheet:
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
const { ctx } = services;
|
|
44
|
+
const ss = ctx.spreadsheet("uuid-here");
|
|
45
|
+
await ss.sql("SELECT * FROM contacts");
|
|
46
|
+
await ss.sheet("contacts").addRow({ name: "Corp", email: "corp@example.com" });
|
|
47
|
+
await ss.sheet("contacts").addRows([
|
|
48
|
+
{ name: "Foo", email: "foo@example.com" },
|
|
49
|
+
{ name: "Bar", email: "bar@example.com" }
|
|
50
|
+
]);
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
- **`ss.sql(sql)`** — Execute EAV-SQL (same as `ctx.sql` but without needing to pass spreadsheetId).
|
|
54
|
+
- **`ss.sheet(name).addRow(row)`** — Insert a single row into the named sheet.
|
|
55
|
+
- **`ss.sheet(name).addRows(rows)`** — Insert multiple rows.
|
|
56
|
+
|
|
57
|
+
## EAV-SQL Reference
|
|
58
|
+
|
|
59
|
+
The `sql` method supports a subset of SQL mapped to Orange Slice's EAV storage:
|
|
60
|
+
|
|
61
|
+
| Statement | Example | Description |
|
|
62
|
+
| -------------- | ---------------------------------------------------------- | -------------------------------- |
|
|
63
|
+
| `CREATE TABLE` | `CREATE TABLE leads (name, email, website)` | Creates a new sheet with columns |
|
|
64
|
+
| `SELECT` | `SELECT name, email FROM leads WHERE email LIKE '%@acme%'` | Query rows |
|
|
65
|
+
| `INSERT INTO` | `INSERT INTO leads (name) VALUES ('Acme')` | Add rows |
|
|
66
|
+
| `ALTER TABLE` | `ALTER TABLE leads ADD COLUMN phone` | Add/rename/drop columns |
|
|
67
|
+
| `DELETE FROM` | `DELETE FROM leads WHERE email IS NULL` | Delete rows |
|
|
68
|
+
| `DROP TABLE` | `DROP TABLE leads` | Delete a sheet |
|
|
69
|
+
|
|
70
|
+
> **Note:** `RUN` commands are not supported via the API.
|
package/docs/services/index.md
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
- **ctx**: Spreadsheet management — create spreadsheets, run SQL, add sheets/columns/rows programmatically.
|
|
1
2
|
- **ai**: AI helpers (summaries, classifications, scoring).
|
|
2
3
|
- **apify**: Run any of 10,000+ Apify actors for web scraping, social media, e-commerce, and more.
|
|
3
4
|
- **browser**: Kernel browser automation - spin up cloud browsers, execute Playwright code, take screenshots. **Use this for scraping structured lists of repeated data** (e.g., product listings, search results, table rows) where you know the DOM structure. Also ideal for **intercepting network requests** to discover underlying APIs, then paginate those APIs directly in your code (faster & cheaper than clicking through pages). Perfect for JS-heavy sites that don't work with simple HTTP scraping.
|