@oleanderhq/sdk 0.1.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 +89 -0
- package/dist/index.cjs +314 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +343 -0
- package/dist/index.d.ts +343 -0
- package/dist/index.js +275 -0
- package/dist/index.js.map +1 -0
- package/package.json +47 -0
package/README.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# oleander TypeScript SDK
|
|
2
|
+
|
|
3
|
+
Use the [oleander](https://oleander.dev) API from TypeScript: run lake queries, list Spark jobs, and launch Spark jobs. Inputs and responses are validated with [Zod](https://zod.dev).
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @oleanderhq/sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or: `yarn add @oleanderhq/sdk` / `pnpm add @oleanderhq/sdk`
|
|
12
|
+
|
|
13
|
+
## Get your API key
|
|
14
|
+
|
|
15
|
+
Create an API key in [oleander settings](https://oleander.dev/app/settings), or run `oleander configure` if you use the CLI. You can pass the key when creating the client or set the `OLEANDER_API_KEY` environment variable (Node only).
|
|
16
|
+
|
|
17
|
+
## Quick start
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { Oleander } from "@oleanderhq/sdk";
|
|
21
|
+
|
|
22
|
+
const oleander = new Oleander();
|
|
23
|
+
const list = await oleander.listSparkJobs();
|
|
24
|
+
console.log(list.scripts);
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## API
|
|
28
|
+
|
|
29
|
+
### Query (lake)
|
|
30
|
+
|
|
31
|
+
Run a SQL query against the oleander lake. The second parameter is optional; `save` defaults to `false`. Use `save: true` to persist results as a table.
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
const result = await oleander.query(
|
|
35
|
+
"SELECT * FROM public.iris_dataset LIMIT 10",
|
|
36
|
+
);
|
|
37
|
+
console.log(result.results?.columns, result.results?.rows);
|
|
38
|
+
console.log(result.row_count, result.execution_time);
|
|
39
|
+
if (result.saved_table_name) console.log("Saved to:", result.saved_table_name);
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### List Spark jobs
|
|
43
|
+
|
|
44
|
+
Paginated list of your Spark job scripts. Options: `limit` (default 20), `offset` (default 0).
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
const list = await oleander.listSparkJobs();
|
|
48
|
+
console.log(list.scripts, list.hasMore);
|
|
49
|
+
|
|
50
|
+
const next = await oleander.listSparkJobs({ offset: 20 });
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Launch Spark job
|
|
54
|
+
|
|
55
|
+
Submit a Spark job. Required: `namespace`, `name`, `scriptName`. Other options (e.g. `args`, machine types, tags) have defaults.
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
const { runId } = await oleander.submitSparkJob({
|
|
59
|
+
namespace: "my-namespace",
|
|
60
|
+
name: "my-job-name",
|
|
61
|
+
scriptName: "my_script.py",
|
|
62
|
+
});
|
|
63
|
+
console.log("Run ID:", runId);
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Wait for a run to finish
|
|
67
|
+
|
|
68
|
+
Submit and poll until the run completes. Optional: `pollIntervalMs` (default 10000), `timeoutMs` (default 600000).
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
const { runId, state, run } = await oleander.submitSparkJobAndWait({
|
|
72
|
+
namespace: "my-namespace",
|
|
73
|
+
name: "my-job-name",
|
|
74
|
+
scriptName: "my_script.py",
|
|
75
|
+
});
|
|
76
|
+
console.log(runId, state); // COMPLETE | FAIL | ABORT
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Get run status
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
const run = await oleander.getRun(runId);
|
|
83
|
+
console.log(run.state, run.duration);
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Options
|
|
87
|
+
|
|
88
|
+
- **Constructor**: `new Oleander({ apiKey?, baseUrl? })`. Omit `apiKey` to use `OLEANDER_API_KEY`. Set `baseUrl` to use a different endpoint (e.g. `http://localhost:3000`).
|
|
89
|
+
- **Schemas**: The package exports Zod schemas (e.g. `optionsSchema`, `submitOptionsSchema`) if you want to validate config or options yourself.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
Oleander: () => Oleander,
|
|
24
|
+
apiErrorBodySchema: () => apiErrorBodySchema,
|
|
25
|
+
lakeQueryResultSchema: () => lakeQueryResultSchema,
|
|
26
|
+
listSparkJobsOptionsSchema: () => listSparkJobsOptionsSchema,
|
|
27
|
+
listSparkJobsResultSchema: () => listSparkJobsResultSchema,
|
|
28
|
+
optionsSchema: () => optionsSchema,
|
|
29
|
+
queryOptionsSchema: () => queryOptionsSchema,
|
|
30
|
+
runResponseSchema: () => runResponseSchema,
|
|
31
|
+
sparkJobListPageSchema: () => sparkJobListPageSchema,
|
|
32
|
+
sparkJobRunSchema: () => sparkJobRunSchema,
|
|
33
|
+
sparkMachineTypeSchema: () => sparkMachineTypeSchema,
|
|
34
|
+
submitOptionsSchema: () => submitOptionsSchema,
|
|
35
|
+
submitSparkJobAndWaitOptionsSchema: () => submitSparkJobAndWaitOptionsSchema
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(index_exports);
|
|
38
|
+
|
|
39
|
+
// src/schemas.ts
|
|
40
|
+
var import_zod = require("zod");
|
|
41
|
+
var apiErrorBodySchema = import_zod.z.object({
|
|
42
|
+
error: import_zod.z.string().optional(),
|
|
43
|
+
details: import_zod.z.string().optional()
|
|
44
|
+
});
|
|
45
|
+
var DEFAULT_BASE_URL = "https://oleander.dev";
|
|
46
|
+
var optionsSchema = import_zod.z.object({
|
|
47
|
+
apiKey: import_zod.z.string().optional(),
|
|
48
|
+
baseUrl: import_zod.z.string().default(DEFAULT_BASE_URL).transform((v) => v.trim() ? v.trim() : DEFAULT_BASE_URL)
|
|
49
|
+
});
|
|
50
|
+
var queryOptionsSchema = import_zod.z.object({
|
|
51
|
+
save: import_zod.z.boolean().default(false)
|
|
52
|
+
});
|
|
53
|
+
var lakeQueryResultSchema = import_zod.z.object({
|
|
54
|
+
success: import_zod.z.boolean(),
|
|
55
|
+
results: import_zod.z.object({
|
|
56
|
+
columns: import_zod.z.array(import_zod.z.string()),
|
|
57
|
+
column_types: import_zod.z.array(import_zod.z.string()),
|
|
58
|
+
rows: import_zod.z.array(import_zod.z.array(import_zod.z.unknown()))
|
|
59
|
+
}).optional(),
|
|
60
|
+
row_count: import_zod.z.number().optional(),
|
|
61
|
+
execution_time: import_zod.z.string().optional(),
|
|
62
|
+
saved_table_name: import_zod.z.string().optional(),
|
|
63
|
+
error: import_zod.z.string().optional(),
|
|
64
|
+
details: import_zod.z.string().optional(),
|
|
65
|
+
query: import_zod.z.string().optional()
|
|
66
|
+
});
|
|
67
|
+
var sparkJobListPageSchema = import_zod.z.object({
|
|
68
|
+
scripts: import_zod.z.array(import_zod.z.string()),
|
|
69
|
+
continuationToken: import_zod.z.string().optional()
|
|
70
|
+
});
|
|
71
|
+
var listSparkJobsOptionsSchema = import_zod.z.object({
|
|
72
|
+
limit: import_zod.z.number().int().positive().default(20),
|
|
73
|
+
offset: import_zod.z.number().int().nonnegative().default(0)
|
|
74
|
+
});
|
|
75
|
+
var listSparkJobsResultSchema = import_zod.z.object({
|
|
76
|
+
scripts: import_zod.z.array(import_zod.z.string()),
|
|
77
|
+
hasMore: import_zod.z.boolean()
|
|
78
|
+
});
|
|
79
|
+
var sparkMachineTypeSchema = import_zod.z.enum([
|
|
80
|
+
"spark.1.c",
|
|
81
|
+
"spark.2.c",
|
|
82
|
+
"spark.4.c",
|
|
83
|
+
"spark.8.c",
|
|
84
|
+
"spark.16.c",
|
|
85
|
+
"spark.1.b",
|
|
86
|
+
"spark.2.b",
|
|
87
|
+
"spark.4.b",
|
|
88
|
+
"spark.8.b",
|
|
89
|
+
"spark.16.b",
|
|
90
|
+
"spark.1.m",
|
|
91
|
+
"spark.2.m",
|
|
92
|
+
"spark.4.m",
|
|
93
|
+
"spark.8.m",
|
|
94
|
+
"spark.16.m"
|
|
95
|
+
]);
|
|
96
|
+
var submitOptionsSchema = import_zod.z.object({
|
|
97
|
+
namespace: import_zod.z.string().min(1, "namespace is required"),
|
|
98
|
+
name: import_zod.z.string().min(1, "name is required"),
|
|
99
|
+
scriptName: import_zod.z.string().min(1, "scriptName is required"),
|
|
100
|
+
args: import_zod.z.array(import_zod.z.string()).default([]),
|
|
101
|
+
driverMachineType: sparkMachineTypeSchema.default("spark.1.b"),
|
|
102
|
+
executorMachineType: sparkMachineTypeSchema.default("spark.1.b"),
|
|
103
|
+
executorNumbers: import_zod.z.number().int().min(1).max(20).default(2),
|
|
104
|
+
jobTags: import_zod.z.array(import_zod.z.string()).default([]),
|
|
105
|
+
runTags: import_zod.z.array(import_zod.z.string()).default([])
|
|
106
|
+
});
|
|
107
|
+
var submitSparkJobAndWaitOptionsSchema = submitOptionsSchema.extend({
|
|
108
|
+
pollIntervalMs: import_zod.z.number().int().positive().default(1e4),
|
|
109
|
+
timeoutMs: import_zod.z.number().int().positive().default(6e5)
|
|
110
|
+
});
|
|
111
|
+
var sparkJobRunSchema = import_zod.z.object({
|
|
112
|
+
runId: import_zod.z.string()
|
|
113
|
+
});
|
|
114
|
+
var runResponseSchema = import_zod.z.object({
|
|
115
|
+
id: import_zod.z.string(),
|
|
116
|
+
state: import_zod.z.string().nullable(),
|
|
117
|
+
started_at: import_zod.z.string().nullable().optional(),
|
|
118
|
+
queued_at: import_zod.z.string().nullable().optional(),
|
|
119
|
+
scheduled_at: import_zod.z.string().nullable().optional(),
|
|
120
|
+
ended_at: import_zod.z.string().nullable().optional(),
|
|
121
|
+
duration: import_zod.z.number().nullable().optional(),
|
|
122
|
+
error: import_zod.z.unknown().nullable().optional(),
|
|
123
|
+
tags: import_zod.z.array(
|
|
124
|
+
import_zod.z.object({
|
|
125
|
+
key: import_zod.z.string(),
|
|
126
|
+
value: import_zod.z.string(),
|
|
127
|
+
source: import_zod.z.string().nullable().optional()
|
|
128
|
+
})
|
|
129
|
+
),
|
|
130
|
+
job: import_zod.z.object({
|
|
131
|
+
id: import_zod.z.string(),
|
|
132
|
+
name: import_zod.z.string(),
|
|
133
|
+
namespace: import_zod.z.string()
|
|
134
|
+
}),
|
|
135
|
+
pipeline: import_zod.z.object({
|
|
136
|
+
id: import_zod.z.string(),
|
|
137
|
+
name: import_zod.z.string(),
|
|
138
|
+
namespace: import_zod.z.string()
|
|
139
|
+
})
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
// src/client.ts
|
|
143
|
+
function getHeaders(apiKey) {
|
|
144
|
+
return {
|
|
145
|
+
Authorization: `Bearer ${apiKey}`,
|
|
146
|
+
"Content-Type": "application/json"
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
function parseErrorBody(body, status) {
|
|
150
|
+
const parsed = apiErrorBodySchema.safeParse(body);
|
|
151
|
+
if (parsed.success) {
|
|
152
|
+
const { error, details } = parsed.data;
|
|
153
|
+
return error || details || `HTTP ${status}`;
|
|
154
|
+
}
|
|
155
|
+
return `HTTP ${status}`;
|
|
156
|
+
}
|
|
157
|
+
var Oleander = class {
|
|
158
|
+
constructor(options = {}) {
|
|
159
|
+
const parsed = optionsSchema.safeParse(options);
|
|
160
|
+
if (!parsed.success) {
|
|
161
|
+
const first = parsed.error.flatten().formErrors[0] ?? parsed.error.message;
|
|
162
|
+
throw new Error(first);
|
|
163
|
+
}
|
|
164
|
+
const fromOptions = parsed.data.apiKey?.trim();
|
|
165
|
+
const fromEnv = typeof process !== "undefined" && process.env?.OLEANDER_API_KEY;
|
|
166
|
+
const apiKey = fromOptions ?? fromEnv ?? "";
|
|
167
|
+
if (!apiKey) {
|
|
168
|
+
throw new Error(
|
|
169
|
+
"Oleander requires a non-empty apiKey (or set OLEANDER_API_KEY)"
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
this.apiKey = apiKey;
|
|
173
|
+
this.baseUrl = parsed.data.baseUrl.trim().replace(/\/$/, "");
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Execute a lake query (mirrors `oleander query`).
|
|
177
|
+
*/
|
|
178
|
+
async query(sql, options = {}) {
|
|
179
|
+
const query = typeof sql === "string" ? sql.trim() : "";
|
|
180
|
+
if (!query) {
|
|
181
|
+
throw new Error("Query is required");
|
|
182
|
+
}
|
|
183
|
+
const opts = queryOptionsSchema.parse(options);
|
|
184
|
+
const res = await fetch(`${this.baseUrl}/api/v1/warehouse/query`, {
|
|
185
|
+
method: "POST",
|
|
186
|
+
headers: getHeaders(this.apiKey),
|
|
187
|
+
body: JSON.stringify({
|
|
188
|
+
query,
|
|
189
|
+
autoSaveByHash: opts.save
|
|
190
|
+
})
|
|
191
|
+
});
|
|
192
|
+
const raw = await res.json().catch(() => ({}));
|
|
193
|
+
if (!res.ok) {
|
|
194
|
+
throw new Error(parseErrorBody(raw, res.status));
|
|
195
|
+
}
|
|
196
|
+
const result = lakeQueryResultSchema.parse(raw);
|
|
197
|
+
if (!result.success && result.error) {
|
|
198
|
+
throw new Error(result.details || result.error);
|
|
199
|
+
}
|
|
200
|
+
return result;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* List spark jobs (mirrors `oleander spark jobs list`).
|
|
204
|
+
* Uses limit/offset pagination; pages through the API internally.
|
|
205
|
+
*/
|
|
206
|
+
async listSparkJobs(options = {}) {
|
|
207
|
+
const opts = listSparkJobsOptionsSchema.parse(options);
|
|
208
|
+
const { limit, offset } = opts;
|
|
209
|
+
const allScripts = [];
|
|
210
|
+
let continuationToken;
|
|
211
|
+
while (true) {
|
|
212
|
+
const params = continuationToken ? `?${new URLSearchParams({ continuationToken }).toString()}` : "";
|
|
213
|
+
const res = await fetch(`${this.baseUrl}/api/v1/spark/scripts${params}`, {
|
|
214
|
+
method: "GET",
|
|
215
|
+
headers: { Authorization: `Bearer ${this.apiKey}` }
|
|
216
|
+
});
|
|
217
|
+
const raw = await res.json().catch(() => ({}));
|
|
218
|
+
if (!res.ok) {
|
|
219
|
+
throw new Error(parseErrorBody(raw, res.status));
|
|
220
|
+
}
|
|
221
|
+
const page = sparkJobListPageSchema.parse(raw);
|
|
222
|
+
allScripts.push(...page.scripts);
|
|
223
|
+
continuationToken = page.continuationToken;
|
|
224
|
+
if (!continuationToken || allScripts.length >= offset + limit) {
|
|
225
|
+
break;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
const scripts = allScripts.slice(offset, offset + limit);
|
|
229
|
+
const hasMore = !!continuationToken || allScripts.length > offset + limit;
|
|
230
|
+
return { scripts, hasMore };
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Submit a spark job (mirrors `oleander spark jobs submit`).
|
|
234
|
+
* Returns the run ID; use getRun() or submitSparkJobAndWait() to poll status.
|
|
235
|
+
*/
|
|
236
|
+
async submitSparkJob(options) {
|
|
237
|
+
const opts = submitOptionsSchema.parse(options);
|
|
238
|
+
const res = await fetch(`${this.baseUrl}/api/v1/spark/jobs`, {
|
|
239
|
+
method: "POST",
|
|
240
|
+
headers: getHeaders(this.apiKey),
|
|
241
|
+
body: JSON.stringify({
|
|
242
|
+
namespace: opts.namespace.trim(),
|
|
243
|
+
name: opts.name.trim(),
|
|
244
|
+
scriptName: opts.scriptName.trim(),
|
|
245
|
+
arguments: opts.args,
|
|
246
|
+
driverMachineType: opts.driverMachineType,
|
|
247
|
+
executorMachineType: opts.executorMachineType,
|
|
248
|
+
executorNumbers: opts.executorNumbers,
|
|
249
|
+
jobTags: opts.jobTags,
|
|
250
|
+
runTags: opts.runTags
|
|
251
|
+
})
|
|
252
|
+
});
|
|
253
|
+
const raw = await res.json().catch(() => ({}));
|
|
254
|
+
if (!res.ok) {
|
|
255
|
+
throw new Error(parseErrorBody(raw, res.status));
|
|
256
|
+
}
|
|
257
|
+
return sparkJobRunSchema.parse(raw);
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Get run status (used for polling after submit).
|
|
261
|
+
*/
|
|
262
|
+
async getRun(runId) {
|
|
263
|
+
if (!runId || typeof runId !== "string" || !runId.trim()) {
|
|
264
|
+
throw new Error("runId is required");
|
|
265
|
+
}
|
|
266
|
+
const res = await fetch(`${this.baseUrl}/api/v2/runs/${runId}`, {
|
|
267
|
+
method: "GET",
|
|
268
|
+
headers: { Authorization: `Bearer ${this.apiKey}` }
|
|
269
|
+
});
|
|
270
|
+
const raw = await res.json().catch(() => ({}));
|
|
271
|
+
if (!res.ok) {
|
|
272
|
+
throw new Error(parseErrorBody(raw, res.status));
|
|
273
|
+
}
|
|
274
|
+
return runResponseSchema.parse(raw);
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Submit a spark job and wait until the run reaches a terminal state (COMPLETE, FAIL, ABORT).
|
|
278
|
+
*/
|
|
279
|
+
async submitSparkJobAndWait(options) {
|
|
280
|
+
const opts = submitSparkJobAndWaitOptionsSchema.parse(options);
|
|
281
|
+
const { pollIntervalMs, timeoutMs, ...submitOpts } = opts;
|
|
282
|
+
const { runId } = await this.submitSparkJob(submitOpts);
|
|
283
|
+
const started = Date.now();
|
|
284
|
+
while (Date.now() - started < timeoutMs) {
|
|
285
|
+
const run2 = await this.getRun(runId);
|
|
286
|
+
const state = run2.state ?? "";
|
|
287
|
+
if (state === "COMPLETE" || state === "FAIL" || state === "ABORT") {
|
|
288
|
+
return { runId, state, run: run2 };
|
|
289
|
+
}
|
|
290
|
+
await new Promise((r) => setTimeout(r, pollIntervalMs));
|
|
291
|
+
}
|
|
292
|
+
const run = await this.getRun(runId);
|
|
293
|
+
throw new Error(
|
|
294
|
+
`Timeout waiting for run ${runId} (state: ${run.state ?? "unknown"})`
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
299
|
+
0 && (module.exports = {
|
|
300
|
+
Oleander,
|
|
301
|
+
apiErrorBodySchema,
|
|
302
|
+
lakeQueryResultSchema,
|
|
303
|
+
listSparkJobsOptionsSchema,
|
|
304
|
+
listSparkJobsResultSchema,
|
|
305
|
+
optionsSchema,
|
|
306
|
+
queryOptionsSchema,
|
|
307
|
+
runResponseSchema,
|
|
308
|
+
sparkJobListPageSchema,
|
|
309
|
+
sparkJobRunSchema,
|
|
310
|
+
sparkMachineTypeSchema,
|
|
311
|
+
submitOptionsSchema,
|
|
312
|
+
submitSparkJobAndWaitOptionsSchema
|
|
313
|
+
});
|
|
314
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/schemas.ts","../src/client.ts"],"sourcesContent":["export { Oleander } from \"./client.js\";\nexport type { OleanderOptions } from \"./schemas.js\";\nexport type {\n QueryOptions,\n LakeQueryResult,\n ApiErrorBody,\n SparkJobListPage,\n ListSparkJobsOptions,\n ListSparkJobsResult,\n SparkMachineType,\n SparkJobSubmitOptions,\n SubmitSparkJobAndWaitOptions,\n SparkJobRun,\n RunResponse,\n RunState,\n} from \"./schemas.js\";\nexport {\n optionsSchema,\n queryOptionsSchema,\n lakeQueryResultSchema,\n sparkJobListPageSchema,\n listSparkJobsOptionsSchema,\n listSparkJobsResultSchema,\n sparkMachineTypeSchema,\n submitOptionsSchema,\n submitSparkJobAndWaitOptionsSchema,\n sparkJobRunSchema,\n runResponseSchema,\n apiErrorBodySchema,\n} from \"./schemas.js\";\n","import { z } from \"zod\";\n\n/** API error response body */\nexport const apiErrorBodySchema = z.object({\n error: z.string().optional(),\n details: z.string().optional(),\n});\n\nexport type ApiErrorBody = z.infer<typeof apiErrorBodySchema>;\n\nconst DEFAULT_BASE_URL = \"https://oleander.dev\";\n\n/** Constructor options. apiKey can be omitted if OLEANDER_API_KEY env is set. */\nexport const optionsSchema = z.object({\n apiKey: z.string().optional(),\n baseUrl: z\n .string()\n .default(DEFAULT_BASE_URL)\n .transform((v) => (v.trim() ? v.trim() : DEFAULT_BASE_URL)),\n});\n\nexport type OleanderOptions = z.input<typeof optionsSchema>;\n\n/** Lake query options */\nexport const queryOptionsSchema = z.object({\n save: z.boolean().default(false),\n});\n\nexport type QueryOptions = z.input<typeof queryOptionsSchema>;\n\n/** Lake query result (API response) */\nexport const lakeQueryResultSchema = z.object({\n success: z.boolean(),\n results: z\n .object({\n columns: z.array(z.string()),\n column_types: z.array(z.string()),\n rows: z.array(z.array(z.unknown())),\n })\n .optional(),\n row_count: z.number().optional(),\n execution_time: z.string().optional(),\n saved_table_name: z.string().optional(),\n error: z.string().optional(),\n details: z.string().optional(),\n query: z.string().optional(),\n});\n\nexport type LakeQueryResult = z.infer<typeof lakeQueryResultSchema>;\n\n/** API response for one page of spark scripts (S3-style) */\nexport const sparkJobListPageSchema = z.object({\n scripts: z.array(z.string()),\n continuationToken: z.string().optional(),\n});\n\nexport type SparkJobListPage = z.infer<typeof sparkJobListPageSchema>;\n\n/** Options for listSparkJobs (limit/offset pagination) */\nexport const listSparkJobsOptionsSchema = z.object({\n limit: z.number().int().positive().default(20),\n offset: z.number().int().nonnegative().default(0),\n});\n\nexport type ListSparkJobsOptions = z.input<typeof listSparkJobsOptionsSchema>;\n\n/** Result of listSparkJobs with limit/offset */\nexport const listSparkJobsResultSchema = z.object({\n scripts: z.array(z.string()),\n hasMore: z.boolean(),\n});\n\nexport type ListSparkJobsResult = z.infer<typeof listSparkJobsResultSchema>;\n\n/** Spark machine type enum */\nexport const sparkMachineTypeSchema = z.enum([\n \"spark.1.c\",\n \"spark.2.c\",\n \"spark.4.c\",\n \"spark.8.c\",\n \"spark.16.c\",\n \"spark.1.b\",\n \"spark.2.b\",\n \"spark.4.b\",\n \"spark.8.b\",\n \"spark.16.b\",\n \"spark.1.m\",\n \"spark.2.m\",\n \"spark.4.m\",\n \"spark.8.m\",\n \"spark.16.m\",\n]);\n\nexport type SparkMachineType = z.infer<typeof sparkMachineTypeSchema>;\n\n/** Spark job submit options. Optional fields have defaults. */\nexport const submitOptionsSchema = z.object({\n namespace: z.string().min(1, \"namespace is required\"),\n name: z.string().min(1, \"name is required\"),\n scriptName: z.string().min(1, \"scriptName is required\"),\n args: z.array(z.string()).default([]),\n driverMachineType: sparkMachineTypeSchema.default(\"spark.1.b\"),\n executorMachineType: sparkMachineTypeSchema.default(\"spark.1.b\"),\n executorNumbers: z.number().int().min(1).max(20).default(2),\n jobTags: z.array(z.string()).default([]),\n runTags: z.array(z.string()).default([]),\n});\n\nexport type SparkJobSubmitOptions = z.input<typeof submitOptionsSchema>;\n\n/** Options for submitSparkJobAndWait (submit options + optional wait tuning) */\nexport const submitSparkJobAndWaitOptionsSchema = submitOptionsSchema.extend({\n pollIntervalMs: z.number().int().positive().default(10000),\n timeoutMs: z.number().int().positive().default(600000),\n});\n\nexport type SubmitSparkJobAndWaitOptions = z.input<\n typeof submitSparkJobAndWaitOptionsSchema\n>;\n\n/** Spark job submit response */\nexport const sparkJobRunSchema = z.object({\n runId: z.string(),\n});\n\nexport type SparkJobRun = z.infer<typeof sparkJobRunSchema>;\n\n/** Run status (for polling) */\nexport const runResponseSchema = z.object({\n id: z.string(),\n state: z.string().nullable(),\n started_at: z.string().nullable().optional(),\n queued_at: z.string().nullable().optional(),\n scheduled_at: z.string().nullable().optional(),\n ended_at: z.string().nullable().optional(),\n duration: z.number().nullable().optional(),\n error: z.unknown().nullable().optional(),\n tags: z.array(\n z.object({\n key: z.string(),\n value: z.string(),\n source: z.string().nullable().optional(),\n }),\n ),\n job: z.object({\n id: z.string(),\n name: z.string(),\n namespace: z.string(),\n }),\n pipeline: z.object({\n id: z.string(),\n name: z.string(),\n namespace: z.string(),\n }),\n});\n\nexport type RunResponse = z.infer<typeof runResponseSchema>;\n\nexport type RunState = \"COMPLETE\" | \"FAIL\" | \"ABORT\" | string;\n","import {\n optionsSchema,\n queryOptionsSchema,\n lakeQueryResultSchema,\n sparkJobListPageSchema,\n listSparkJobsOptionsSchema,\n submitOptionsSchema,\n submitSparkJobAndWaitOptionsSchema,\n sparkJobRunSchema,\n runResponseSchema,\n apiErrorBodySchema,\n} from \"./schemas.js\";\nimport type {\n OleanderOptions,\n QueryOptions,\n LakeQueryResult,\n ListSparkJobsOptions,\n ListSparkJobsResult,\n SparkJobSubmitOptions,\n SubmitSparkJobAndWaitOptions,\n SparkJobRun,\n RunResponse,\n RunState,\n} from \"./schemas.js\";\n\nfunction getHeaders(apiKey: string): Record<string, string> {\n return {\n Authorization: `Bearer ${apiKey}`,\n \"Content-Type\": \"application/json\",\n };\n}\n\nfunction parseErrorBody(body: unknown, status: number): string {\n const parsed = apiErrorBodySchema.safeParse(body);\n if (parsed.success) {\n const { error, details } = parsed.data;\n return error || details || `HTTP ${status}`;\n }\n return `HTTP ${status}`;\n}\n\n/**\n * oleander API. Mirrors the CLI for query, list spark jobs, and launch spark jobs.\n */\nexport class Oleander {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n\n constructor(options: OleanderOptions = {}) {\n const parsed = optionsSchema.safeParse(options);\n if (!parsed.success) {\n const first =\n parsed.error.flatten().formErrors[0] ?? parsed.error.message;\n throw new Error(first);\n }\n const fromOptions = parsed.data.apiKey?.trim();\n const fromEnv =\n typeof process !== \"undefined\" && process.env?.OLEANDER_API_KEY;\n const apiKey = fromOptions ?? fromEnv ?? \"\";\n if (!apiKey) {\n throw new Error(\n \"Oleander requires a non-empty apiKey (or set OLEANDER_API_KEY)\",\n );\n }\n this.apiKey = apiKey;\n this.baseUrl = parsed.data.baseUrl.trim().replace(/\\/$/, \"\");\n }\n\n /**\n * Execute a lake query (mirrors `oleander query`).\n */\n async query(\n sql: string,\n options: QueryOptions = {},\n ): Promise<LakeQueryResult> {\n const query = typeof sql === \"string\" ? sql.trim() : \"\";\n if (!query) {\n throw new Error(\"Query is required\");\n }\n const opts = queryOptionsSchema.parse(options);\n\n const res = await fetch(`${this.baseUrl}/api/v1/warehouse/query`, {\n method: \"POST\",\n headers: getHeaders(this.apiKey),\n body: JSON.stringify({\n query,\n autoSaveByHash: opts.save,\n }),\n });\n\n const raw = await res.json().catch(() => ({}));\n if (!res.ok) {\n throw new Error(parseErrorBody(raw, res.status));\n }\n\n const result = lakeQueryResultSchema.parse(raw);\n if (!result.success && result.error) {\n throw new Error(result.details || result.error);\n }\n return result;\n }\n\n /**\n * List spark jobs (mirrors `oleander spark jobs list`).\n * Uses limit/offset pagination; pages through the API internally.\n */\n async listSparkJobs(\n options: ListSparkJobsOptions = {},\n ): Promise<ListSparkJobsResult> {\n const opts = listSparkJobsOptionsSchema.parse(options);\n const { limit, offset } = opts;\n\n const allScripts: string[] = [];\n let continuationToken: string | undefined;\n\n while (true) {\n const params = continuationToken\n ? `?${new URLSearchParams({ continuationToken }).toString()}`\n : \"\";\n const res = await fetch(`${this.baseUrl}/api/v1/spark/scripts${params}`, {\n method: \"GET\",\n headers: { Authorization: `Bearer ${this.apiKey}` },\n });\n const raw = await res.json().catch(() => ({}));\n if (!res.ok) {\n throw new Error(parseErrorBody(raw, res.status));\n }\n const page = sparkJobListPageSchema.parse(raw);\n allScripts.push(...page.scripts);\n continuationToken = page.continuationToken;\n if (!continuationToken || allScripts.length >= offset + limit) {\n break;\n }\n }\n\n const scripts = allScripts.slice(offset, offset + limit);\n const hasMore = !!continuationToken || allScripts.length > offset + limit;\n return { scripts, hasMore };\n }\n\n /**\n * Submit a spark job (mirrors `oleander spark jobs submit`).\n * Returns the run ID; use getRun() or submitSparkJobAndWait() to poll status.\n */\n async submitSparkJob(options: SparkJobSubmitOptions): Promise<SparkJobRun> {\n const opts = submitOptionsSchema.parse(options);\n\n const res = await fetch(`${this.baseUrl}/api/v1/spark/jobs`, {\n method: \"POST\",\n headers: getHeaders(this.apiKey),\n body: JSON.stringify({\n namespace: opts.namespace.trim(),\n name: opts.name.trim(),\n scriptName: opts.scriptName.trim(),\n arguments: opts.args,\n driverMachineType: opts.driverMachineType,\n executorMachineType: opts.executorMachineType,\n executorNumbers: opts.executorNumbers,\n jobTags: opts.jobTags,\n runTags: opts.runTags,\n }),\n });\n\n const raw = await res.json().catch(() => ({}));\n if (!res.ok) {\n throw new Error(parseErrorBody(raw, res.status));\n }\n return sparkJobRunSchema.parse(raw);\n }\n\n /**\n * Get run status (used for polling after submit).\n */\n async getRun(runId: string): Promise<RunResponse> {\n if (!runId || typeof runId !== \"string\" || !runId.trim()) {\n throw new Error(\"runId is required\");\n }\n const res = await fetch(`${this.baseUrl}/api/v2/runs/${runId}`, {\n method: \"GET\",\n headers: { Authorization: `Bearer ${this.apiKey}` },\n });\n\n const raw = await res.json().catch(() => ({}));\n if (!res.ok) {\n throw new Error(parseErrorBody(raw, res.status));\n }\n return runResponseSchema.parse(raw);\n }\n\n /**\n * Submit a spark job and wait until the run reaches a terminal state (COMPLETE, FAIL, ABORT).\n */\n async submitSparkJobAndWait(\n options: SubmitSparkJobAndWaitOptions,\n ): Promise<{ runId: string; state: RunState; run: RunResponse }> {\n const opts = submitSparkJobAndWaitOptionsSchema.parse(options);\n const { pollIntervalMs, timeoutMs, ...submitOpts } = opts;\n const { runId } = await this.submitSparkJob(submitOpts);\n const started = Date.now();\n\n while (Date.now() - started < timeoutMs) {\n const run = await this.getRun(runId);\n const state = run.state ?? \"\";\n if (state === \"COMPLETE\" || state === \"FAIL\" || state === \"ABORT\") {\n return { runId, state, run };\n }\n await new Promise((r) => setTimeout(r, pollIntervalMs));\n }\n const run = await this.getRun(runId);\n throw new Error(\n `Timeout waiting for run ${runId} (state: ${run.state ?? \"unknown\"})`,\n );\n }\n}\n"],"mappings":"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","names":["run"]}
|