deepline 0.0.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/config.ts","../src/errors.ts","../src/http.ts","../src/client.ts"],"sourcesContent":["export { DeeplineClient } from './client.js';\nexport type { PlayStatus } from './client.js';\nexport { DeeplineError, AuthError, RateLimitError, ConfigError } from './errors.js';\nexport { resolveConfig, PROD_URL } from './config.js';\nexport type {\n DeeplineClientOptions,\n ResolvedConfig,\n ToolDefinition,\n ToolExecuteResult,\n PlayRunResult,\n} from './types.js';\n","import { readFileSync, existsSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport type { DeeplineClientOptions, ResolvedConfig } from './types.js';\nimport { ConfigError } from './errors.js';\n\nconst PROD_URL = 'https://code.deepline.com';\nconst DEFAULT_TIMEOUT = 60_000;\nconst DEFAULT_MAX_RETRIES = 3;\n\nfunction baseUrlSlug(baseUrl: string): string {\n let url: URL;\n try {\n url = new URL(baseUrl);\n } catch {\n return 'unknown';\n }\n const host = url.hostname || 'unknown';\n const port = url.port ? parseInt(url.port, 10) : null;\n let slug = host.replace(/[^a-zA-Z0-9]/g, '-');\n if (port && port !== 80 && port !== 443) {\n slug = `${slug}-${port}`;\n }\n return slug.toLowerCase().replace(/^-+|-+$/g, '');\n}\n\nfunction parseEnvFile(filePath: string): Record<string, string> {\n if (!existsSync(filePath)) return {};\n const env: Record<string, string> = {};\n const content = readFileSync(filePath, 'utf-8');\n for (const line of content.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const eqIndex = trimmed.indexOf('=');\n if (eqIndex < 0) continue;\n const key = trimmed.slice(0, eqIndex).trim();\n let value = trimmed.slice(eqIndex + 1).trim();\n // Strip surrounding quotes\n if (\n value.length >= 2 &&\n ((value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\")))\n ) {\n value = value.slice(1, -1);\n }\n if (key && value) {\n env[key] = value;\n }\n }\n return env;\n}\n\nfunction loadCliEnv(baseUrl: string): Record<string, string> {\n const slug = baseUrlSlug(baseUrl);\n const envPath = join(homedir(), '.local', 'deepline', slug, '.env');\n return parseEnvFile(envPath);\n}\n\nfunction isLocalhost(url: string): boolean {\n try {\n const parsed = new URL(url);\n return parsed.hostname === 'localhost' || parsed.hostname === '127.0.0.1';\n } catch {\n return false;\n }\n}\n\nfunction autoDetectBaseUrl(): string {\n // Check env var first\n const envBase = process.env.DEEPLINE_API_BASE_URL?.trim();\n if (envBase) return envBase;\n\n // Check if localhost:3000 is likely (dev mode)\n const localEnvPath = join(homedir(), '.local', 'deepline', 'localhost-3000', '.env');\n if (existsSync(localEnvPath)) {\n return 'http://localhost:3000';\n }\n\n return PROD_URL;\n}\n\nexport function resolveConfig(options?: DeeplineClientOptions): ResolvedConfig {\n // Resolve base URL\n const baseUrl = options?.baseUrl?.trim() || autoDetectBaseUrl();\n\n // Load CLI env file for this host\n const cliEnv = loadCliEnv(baseUrl);\n\n // Resolve API key: option > env var > CLI env file\n const apiKey =\n options?.apiKey?.trim() ||\n process.env.DEEPLINE_API_KEY?.trim() ||\n cliEnv.DEEPLINE_API_KEY ||\n '';\n\n if (!apiKey) {\n throw new ConfigError(\n `No API key found. Set DEEPLINE_API_KEY env var, pass apiKey option, or run: deepline auth register`,\n );\n }\n\n return {\n apiKey,\n baseUrl: baseUrl.replace(/\\/$/, ''),\n timeout: options?.timeout ?? DEFAULT_TIMEOUT,\n maxRetries: options?.maxRetries ?? DEFAULT_MAX_RETRIES,\n };\n}\n\nexport { baseUrlSlug, loadCliEnv, parseEnvFile, autoDetectBaseUrl, PROD_URL };\n","export class DeeplineError extends Error {\n constructor(\n message: string,\n public statusCode?: number,\n public code?: string,\n public details?: Record<string, unknown>,\n ) {\n super(message);\n this.name = 'DeeplineError';\n }\n}\n\nexport class AuthError extends DeeplineError {\n constructor(message = 'Authentication failed. Check your DEEPLINE_API_KEY.') {\n super(message, 401, 'AUTH_ERROR');\n this.name = 'AuthError';\n }\n}\n\nexport class RateLimitError extends DeeplineError {\n public retryAfterMs: number;\n\n constructor(retryAfterMs = 5000, message?: string) {\n super(message ?? `Rate limited. Retry after ${retryAfterMs}ms.`, 429, 'RATE_LIMIT');\n this.name = 'RateLimitError';\n this.retryAfterMs = retryAfterMs;\n }\n}\n\nexport class ConfigError extends DeeplineError {\n constructor(message: string) {\n super(message, undefined, 'CONFIG_ERROR');\n this.name = 'ConfigError';\n }\n}\n","import type { ResolvedConfig } from './types.js';\nimport { AuthError, DeeplineError, RateLimitError } from './errors.js';\n\nconst SDK_VERSION = '0.1.0';\n\ninterface RequestOptions {\n method?: 'GET' | 'POST' | 'PUT' | 'DELETE';\n body?: unknown;\n headers?: Record<string, string>;\n timeout?: number;\n}\n\nexport class HttpClient {\n constructor(private config: ResolvedConfig) {}\n\n async request<T = unknown>(path: string, options?: RequestOptions): Promise<T> {\n const url = `${this.config.baseUrl}${path}`;\n const method = options?.method ?? 'GET';\n\n const headers: Record<string, string> = {\n 'Authorization': `Bearer ${this.config.apiKey}`,\n 'User-Agent': `deepline-ts-sdk/${SDK_VERSION}`,\n ...options?.headers,\n };\n\n if (options?.body !== undefined) {\n headers['Content-Type'] = 'application/json';\n }\n\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {\n if (attempt > 0) {\n const backoffMs = Math.min(1000 * Math.pow(2, attempt - 1), 30_000);\n await sleep(backoffMs);\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(\n () => controller.abort(),\n options?.timeout ?? this.config.timeout,\n );\n\n try {\n const response = await fetch(url, {\n method,\n headers,\n body: options?.body !== undefined ? JSON.stringify(options.body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (response.status === 401 || response.status === 403) {\n throw new AuthError();\n }\n\n if (response.status === 429) {\n const retryAfter = parseRetryAfter(response);\n lastError = new RateLimitError(retryAfter);\n if (attempt < this.config.maxRetries) continue;\n throw lastError;\n }\n\n const body = await response.text();\n let parsed: unknown;\n try {\n parsed = JSON.parse(body);\n } catch {\n parsed = body;\n }\n\n if (!response.ok) {\n const msg =\n typeof parsed === 'object' && parsed && 'error' in parsed\n ? String((parsed as Record<string, unknown>).error)\n : `HTTP ${response.status}`;\n throw new DeeplineError(msg, response.status, 'API_ERROR', {\n response: parsed,\n });\n }\n\n return parsed as T;\n } catch (error) {\n clearTimeout(timeoutId);\n if (error instanceof AuthError || error instanceof DeeplineError) {\n throw error;\n }\n if (error instanceof RateLimitError) {\n lastError = error;\n if (attempt < this.config.maxRetries) continue;\n throw error;\n }\n // Network / timeout errors\n lastError = error instanceof Error ? error : new Error(String(error));\n if (attempt < this.config.maxRetries) continue;\n }\n }\n\n throw lastError ?? new DeeplineError('Request failed after retries');\n }\n\n async get<T = unknown>(path: string): Promise<T> {\n return this.request<T>(path, { method: 'GET' });\n }\n\n async post<T = unknown>(path: string, body: unknown): Promise<T> {\n return this.request<T>(path, { method: 'POST', body });\n }\n}\n\nfunction parseRetryAfter(response: Response): number {\n const header = response.headers.get('retry-after');\n if (header) {\n const seconds = Number(header);\n if (Number.isFinite(seconds) && seconds > 0) {\n return seconds * 1000;\n }\n }\n return 5000;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import { resolveConfig } from './config.js';\nimport { HttpClient } from './http.js';\nimport type { DeeplineClientOptions, ResolvedConfig, PlayRunResult, ToolDefinition } from './types.js';\n\nexport class DeeplineClient {\n private readonly http: HttpClient;\n private readonly config: ResolvedConfig;\n\n constructor(options?: DeeplineClientOptions) {\n this.config = resolveConfig(options);\n this.http = new HttpClient(this.config);\n }\n\n get baseUrl(): string {\n return this.config.baseUrl;\n }\n\n /** List available tools. */\n async listTools(): Promise<ToolDefinition[]> {\n const res = await this.http.get<{ tools: ToolDefinition[] }>('/api/v2/tools');\n return res.tools;\n }\n\n /** Execute a single tool. */\n async executeTool(toolId: string, input: Record<string, unknown>): Promise<unknown> {\n const res = await this.http.post<{ result: unknown }>(\n `/api/v2/integrations/${encodeURIComponent(toolId)}/execute`,\n { payload: input },\n );\n return res.result ?? res;\n }\n\n /**\n * Submit a play for cloud execution.\n * Returns a workflowId. Use pollPlay() to get status.\n */\n async submitPlay(code: string, csvPath: string, name?: string): Promise<{ workflowId: string }> {\n return this.http.post<{ workflowId: string }>('/api/v2/plays/run', {\n code,\n csvPath,\n name,\n });\n }\n\n /** Poll workflow status. */\n async getPlayStatus(workflowId: string): Promise<PlayStatus> {\n return this.http.get<PlayStatus>(`/api/v2/plays/run/${workflowId}`);\n }\n\n /** Cancel a running play. */\n async cancelPlay(workflowId: string): Promise<void> {\n await this.http.request(`/api/v2/plays/run/${workflowId}`, { method: 'DELETE' });\n }\n\n /**\n * Run a play end-to-end: submit, poll until done, return result.\n * onProgress is called on each poll with current status.\n */\n async runPlay(\n code: string,\n csvPath: string,\n name?: string,\n options?: {\n onProgress?: (status: PlayStatus) => void;\n pollIntervalMs?: number;\n signal?: AbortSignal;\n },\n ): Promise<PlayRunResult> {\n const { workflowId } = await this.submitPlay(code, csvPath, name);\n const pollInterval = options?.pollIntervalMs ?? 2000;\n const start = Date.now();\n\n while (true) {\n if (options?.signal?.aborted) {\n await this.cancelPlay(workflowId);\n return {\n success: false,\n workflowId,\n logs: [],\n durationMs: Date.now() - start,\n error: 'Cancelled by user',\n };\n }\n\n const status = await this.getPlayStatus(workflowId);\n options?.onProgress?.(status);\n\n const terminal = ['COMPLETED', 'FAILED', 'CANCELLED', 'TERMINATED', 'TIMED_OUT'];\n if (terminal.includes(status.temporalStatus)) {\n return {\n success: status.temporalStatus === 'COMPLETED',\n workflowId,\n result: status.result,\n logs: status.progress?.logs ?? [],\n durationMs: Date.now() - start,\n error: status.progress?.error ?? (status.temporalStatus !== 'COMPLETED' ? status.temporalStatus : undefined),\n };\n }\n\n await new Promise((resolve) => setTimeout(resolve, pollInterval));\n }\n }\n\n /** Health check. */\n async health(): Promise<{ status: string; version?: string }> {\n return this.http.get<{ status: string; version?: string }>('/api/v2/health');\n }\n}\n\nexport interface PlayStatus {\n workflowId: string;\n temporalStatus: string;\n progress?: {\n status: string;\n totalRows?: number;\n logs: string[];\n error?: string;\n };\n result?: unknown;\n}\n"],"mappings":"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","names":[]}
package/dist/index.mjs ADDED
@@ -0,0 +1,299 @@
1
+ // src/config.ts
2
+ import { readFileSync, existsSync } from "fs";
3
+ import { homedir } from "os";
4
+ import { join } from "path";
5
+
6
+ // src/errors.ts
7
+ var DeeplineError = class extends Error {
8
+ constructor(message, statusCode, code, details) {
9
+ super(message);
10
+ this.statusCode = statusCode;
11
+ this.code = code;
12
+ this.details = details;
13
+ this.name = "DeeplineError";
14
+ }
15
+ statusCode;
16
+ code;
17
+ details;
18
+ };
19
+ var AuthError = class extends DeeplineError {
20
+ constructor(message = "Authentication failed. Check your DEEPLINE_API_KEY.") {
21
+ super(message, 401, "AUTH_ERROR");
22
+ this.name = "AuthError";
23
+ }
24
+ };
25
+ var RateLimitError = class extends DeeplineError {
26
+ retryAfterMs;
27
+ constructor(retryAfterMs = 5e3, message) {
28
+ super(message ?? `Rate limited. Retry after ${retryAfterMs}ms.`, 429, "RATE_LIMIT");
29
+ this.name = "RateLimitError";
30
+ this.retryAfterMs = retryAfterMs;
31
+ }
32
+ };
33
+ var ConfigError = class extends DeeplineError {
34
+ constructor(message) {
35
+ super(message, void 0, "CONFIG_ERROR");
36
+ this.name = "ConfigError";
37
+ }
38
+ };
39
+
40
+ // src/config.ts
41
+ var PROD_URL = "https://code.deepline.com";
42
+ var DEFAULT_TIMEOUT = 6e4;
43
+ var DEFAULT_MAX_RETRIES = 3;
44
+ function baseUrlSlug(baseUrl) {
45
+ let url;
46
+ try {
47
+ url = new URL(baseUrl);
48
+ } catch {
49
+ return "unknown";
50
+ }
51
+ const host = url.hostname || "unknown";
52
+ const port = url.port ? parseInt(url.port, 10) : null;
53
+ let slug = host.replace(/[^a-zA-Z0-9]/g, "-");
54
+ if (port && port !== 80 && port !== 443) {
55
+ slug = `${slug}-${port}`;
56
+ }
57
+ return slug.toLowerCase().replace(/^-+|-+$/g, "");
58
+ }
59
+ function parseEnvFile(filePath) {
60
+ if (!existsSync(filePath)) return {};
61
+ const env = {};
62
+ const content = readFileSync(filePath, "utf-8");
63
+ for (const line of content.split(/\r?\n/)) {
64
+ const trimmed = line.trim();
65
+ if (!trimmed || trimmed.startsWith("#")) continue;
66
+ const eqIndex = trimmed.indexOf("=");
67
+ if (eqIndex < 0) continue;
68
+ const key = trimmed.slice(0, eqIndex).trim();
69
+ let value = trimmed.slice(eqIndex + 1).trim();
70
+ if (value.length >= 2 && (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'"))) {
71
+ value = value.slice(1, -1);
72
+ }
73
+ if (key && value) {
74
+ env[key] = value;
75
+ }
76
+ }
77
+ return env;
78
+ }
79
+ function loadCliEnv(baseUrl) {
80
+ const slug = baseUrlSlug(baseUrl);
81
+ const envPath = join(homedir(), ".local", "deepline", slug, ".env");
82
+ return parseEnvFile(envPath);
83
+ }
84
+ function autoDetectBaseUrl() {
85
+ const envBase = process.env.DEEPLINE_API_BASE_URL?.trim();
86
+ if (envBase) return envBase;
87
+ const localEnvPath = join(homedir(), ".local", "deepline", "localhost-3000", ".env");
88
+ if (existsSync(localEnvPath)) {
89
+ return "http://localhost:3000";
90
+ }
91
+ return PROD_URL;
92
+ }
93
+ function resolveConfig(options) {
94
+ const baseUrl = options?.baseUrl?.trim() || autoDetectBaseUrl();
95
+ const cliEnv = loadCliEnv(baseUrl);
96
+ const apiKey = options?.apiKey?.trim() || process.env.DEEPLINE_API_KEY?.trim() || cliEnv.DEEPLINE_API_KEY || "";
97
+ if (!apiKey) {
98
+ throw new ConfigError(
99
+ `No API key found. Set DEEPLINE_API_KEY env var, pass apiKey option, or run: deepline auth register`
100
+ );
101
+ }
102
+ return {
103
+ apiKey,
104
+ baseUrl: baseUrl.replace(/\/$/, ""),
105
+ timeout: options?.timeout ?? DEFAULT_TIMEOUT,
106
+ maxRetries: options?.maxRetries ?? DEFAULT_MAX_RETRIES
107
+ };
108
+ }
109
+
110
+ // src/http.ts
111
+ var SDK_VERSION = "0.1.0";
112
+ var HttpClient = class {
113
+ constructor(config) {
114
+ this.config = config;
115
+ }
116
+ config;
117
+ async request(path, options) {
118
+ const url = `${this.config.baseUrl}${path}`;
119
+ const method = options?.method ?? "GET";
120
+ const headers = {
121
+ "Authorization": `Bearer ${this.config.apiKey}`,
122
+ "User-Agent": `deepline-ts-sdk/${SDK_VERSION}`,
123
+ ...options?.headers
124
+ };
125
+ if (options?.body !== void 0) {
126
+ headers["Content-Type"] = "application/json";
127
+ }
128
+ let lastError = null;
129
+ for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {
130
+ if (attempt > 0) {
131
+ const backoffMs = Math.min(1e3 * Math.pow(2, attempt - 1), 3e4);
132
+ await sleep(backoffMs);
133
+ }
134
+ const controller = new AbortController();
135
+ const timeoutId = setTimeout(
136
+ () => controller.abort(),
137
+ options?.timeout ?? this.config.timeout
138
+ );
139
+ try {
140
+ const response = await fetch(url, {
141
+ method,
142
+ headers,
143
+ body: options?.body !== void 0 ? JSON.stringify(options.body) : void 0,
144
+ signal: controller.signal
145
+ });
146
+ clearTimeout(timeoutId);
147
+ if (response.status === 401 || response.status === 403) {
148
+ throw new AuthError();
149
+ }
150
+ if (response.status === 429) {
151
+ const retryAfter = parseRetryAfter(response);
152
+ lastError = new RateLimitError(retryAfter);
153
+ if (attempt < this.config.maxRetries) continue;
154
+ throw lastError;
155
+ }
156
+ const body = await response.text();
157
+ let parsed;
158
+ try {
159
+ parsed = JSON.parse(body);
160
+ } catch {
161
+ parsed = body;
162
+ }
163
+ if (!response.ok) {
164
+ const msg = typeof parsed === "object" && parsed && "error" in parsed ? String(parsed.error) : `HTTP ${response.status}`;
165
+ throw new DeeplineError(msg, response.status, "API_ERROR", {
166
+ response: parsed
167
+ });
168
+ }
169
+ return parsed;
170
+ } catch (error) {
171
+ clearTimeout(timeoutId);
172
+ if (error instanceof AuthError || error instanceof DeeplineError) {
173
+ throw error;
174
+ }
175
+ if (error instanceof RateLimitError) {
176
+ lastError = error;
177
+ if (attempt < this.config.maxRetries) continue;
178
+ throw error;
179
+ }
180
+ lastError = error instanceof Error ? error : new Error(String(error));
181
+ if (attempt < this.config.maxRetries) continue;
182
+ }
183
+ }
184
+ throw lastError ?? new DeeplineError("Request failed after retries");
185
+ }
186
+ async get(path) {
187
+ return this.request(path, { method: "GET" });
188
+ }
189
+ async post(path, body) {
190
+ return this.request(path, { method: "POST", body });
191
+ }
192
+ };
193
+ function parseRetryAfter(response) {
194
+ const header = response.headers.get("retry-after");
195
+ if (header) {
196
+ const seconds = Number(header);
197
+ if (Number.isFinite(seconds) && seconds > 0) {
198
+ return seconds * 1e3;
199
+ }
200
+ }
201
+ return 5e3;
202
+ }
203
+ function sleep(ms) {
204
+ return new Promise((resolve) => setTimeout(resolve, ms));
205
+ }
206
+
207
+ // src/client.ts
208
+ var DeeplineClient = class {
209
+ http;
210
+ config;
211
+ constructor(options) {
212
+ this.config = resolveConfig(options);
213
+ this.http = new HttpClient(this.config);
214
+ }
215
+ get baseUrl() {
216
+ return this.config.baseUrl;
217
+ }
218
+ /** List available tools. */
219
+ async listTools() {
220
+ const res = await this.http.get("/api/v2/tools");
221
+ return res.tools;
222
+ }
223
+ /** Execute a single tool. */
224
+ async executeTool(toolId, input) {
225
+ const res = await this.http.post(
226
+ `/api/v2/integrations/${encodeURIComponent(toolId)}/execute`,
227
+ { payload: input }
228
+ );
229
+ return res.result ?? res;
230
+ }
231
+ /**
232
+ * Submit a play for cloud execution.
233
+ * Returns a workflowId. Use pollPlay() to get status.
234
+ */
235
+ async submitPlay(code, csvPath, name) {
236
+ return this.http.post("/api/v2/plays/run", {
237
+ code,
238
+ csvPath,
239
+ name
240
+ });
241
+ }
242
+ /** Poll workflow status. */
243
+ async getPlayStatus(workflowId) {
244
+ return this.http.get(`/api/v2/plays/run/${workflowId}`);
245
+ }
246
+ /** Cancel a running play. */
247
+ async cancelPlay(workflowId) {
248
+ await this.http.request(`/api/v2/plays/run/${workflowId}`, { method: "DELETE" });
249
+ }
250
+ /**
251
+ * Run a play end-to-end: submit, poll until done, return result.
252
+ * onProgress is called on each poll with current status.
253
+ */
254
+ async runPlay(code, csvPath, name, options) {
255
+ const { workflowId } = await this.submitPlay(code, csvPath, name);
256
+ const pollInterval = options?.pollIntervalMs ?? 2e3;
257
+ const start = Date.now();
258
+ while (true) {
259
+ if (options?.signal?.aborted) {
260
+ await this.cancelPlay(workflowId);
261
+ return {
262
+ success: false,
263
+ workflowId,
264
+ logs: [],
265
+ durationMs: Date.now() - start,
266
+ error: "Cancelled by user"
267
+ };
268
+ }
269
+ const status = await this.getPlayStatus(workflowId);
270
+ options?.onProgress?.(status);
271
+ const terminal = ["COMPLETED", "FAILED", "CANCELLED", "TERMINATED", "TIMED_OUT"];
272
+ if (terminal.includes(status.temporalStatus)) {
273
+ return {
274
+ success: status.temporalStatus === "COMPLETED",
275
+ workflowId,
276
+ result: status.result,
277
+ logs: status.progress?.logs ?? [],
278
+ durationMs: Date.now() - start,
279
+ error: status.progress?.error ?? (status.temporalStatus !== "COMPLETED" ? status.temporalStatus : void 0)
280
+ };
281
+ }
282
+ await new Promise((resolve) => setTimeout(resolve, pollInterval));
283
+ }
284
+ }
285
+ /** Health check. */
286
+ async health() {
287
+ return this.http.get("/api/v2/health");
288
+ }
289
+ };
290
+ export {
291
+ AuthError,
292
+ ConfigError,
293
+ DeeplineClient,
294
+ DeeplineError,
295
+ PROD_URL,
296
+ RateLimitError,
297
+ resolveConfig
298
+ };
299
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config.ts","../src/errors.ts","../src/http.ts","../src/client.ts"],"sourcesContent":["import { readFileSync, existsSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport type { DeeplineClientOptions, ResolvedConfig } from './types.js';\nimport { ConfigError } from './errors.js';\n\nconst PROD_URL = 'https://code.deepline.com';\nconst DEFAULT_TIMEOUT = 60_000;\nconst DEFAULT_MAX_RETRIES = 3;\n\nfunction baseUrlSlug(baseUrl: string): string {\n let url: URL;\n try {\n url = new URL(baseUrl);\n } catch {\n return 'unknown';\n }\n const host = url.hostname || 'unknown';\n const port = url.port ? parseInt(url.port, 10) : null;\n let slug = host.replace(/[^a-zA-Z0-9]/g, '-');\n if (port && port !== 80 && port !== 443) {\n slug = `${slug}-${port}`;\n }\n return slug.toLowerCase().replace(/^-+|-+$/g, '');\n}\n\nfunction parseEnvFile(filePath: string): Record<string, string> {\n if (!existsSync(filePath)) return {};\n const env: Record<string, string> = {};\n const content = readFileSync(filePath, 'utf-8');\n for (const line of content.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const eqIndex = trimmed.indexOf('=');\n if (eqIndex < 0) continue;\n const key = trimmed.slice(0, eqIndex).trim();\n let value = trimmed.slice(eqIndex + 1).trim();\n // Strip surrounding quotes\n if (\n value.length >= 2 &&\n ((value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\")))\n ) {\n value = value.slice(1, -1);\n }\n if (key && value) {\n env[key] = value;\n }\n }\n return env;\n}\n\nfunction loadCliEnv(baseUrl: string): Record<string, string> {\n const slug = baseUrlSlug(baseUrl);\n const envPath = join(homedir(), '.local', 'deepline', slug, '.env');\n return parseEnvFile(envPath);\n}\n\nfunction isLocalhost(url: string): boolean {\n try {\n const parsed = new URL(url);\n return parsed.hostname === 'localhost' || parsed.hostname === '127.0.0.1';\n } catch {\n return false;\n }\n}\n\nfunction autoDetectBaseUrl(): string {\n // Check env var first\n const envBase = process.env.DEEPLINE_API_BASE_URL?.trim();\n if (envBase) return envBase;\n\n // Check if localhost:3000 is likely (dev mode)\n const localEnvPath = join(homedir(), '.local', 'deepline', 'localhost-3000', '.env');\n if (existsSync(localEnvPath)) {\n return 'http://localhost:3000';\n }\n\n return PROD_URL;\n}\n\nexport function resolveConfig(options?: DeeplineClientOptions): ResolvedConfig {\n // Resolve base URL\n const baseUrl = options?.baseUrl?.trim() || autoDetectBaseUrl();\n\n // Load CLI env file for this host\n const cliEnv = loadCliEnv(baseUrl);\n\n // Resolve API key: option > env var > CLI env file\n const apiKey =\n options?.apiKey?.trim() ||\n process.env.DEEPLINE_API_KEY?.trim() ||\n cliEnv.DEEPLINE_API_KEY ||\n '';\n\n if (!apiKey) {\n throw new ConfigError(\n `No API key found. Set DEEPLINE_API_KEY env var, pass apiKey option, or run: deepline auth register`,\n );\n }\n\n return {\n apiKey,\n baseUrl: baseUrl.replace(/\\/$/, ''),\n timeout: options?.timeout ?? DEFAULT_TIMEOUT,\n maxRetries: options?.maxRetries ?? DEFAULT_MAX_RETRIES,\n };\n}\n\nexport { baseUrlSlug, loadCliEnv, parseEnvFile, autoDetectBaseUrl, PROD_URL };\n","export class DeeplineError extends Error {\n constructor(\n message: string,\n public statusCode?: number,\n public code?: string,\n public details?: Record<string, unknown>,\n ) {\n super(message);\n this.name = 'DeeplineError';\n }\n}\n\nexport class AuthError extends DeeplineError {\n constructor(message = 'Authentication failed. Check your DEEPLINE_API_KEY.') {\n super(message, 401, 'AUTH_ERROR');\n this.name = 'AuthError';\n }\n}\n\nexport class RateLimitError extends DeeplineError {\n public retryAfterMs: number;\n\n constructor(retryAfterMs = 5000, message?: string) {\n super(message ?? `Rate limited. Retry after ${retryAfterMs}ms.`, 429, 'RATE_LIMIT');\n this.name = 'RateLimitError';\n this.retryAfterMs = retryAfterMs;\n }\n}\n\nexport class ConfigError extends DeeplineError {\n constructor(message: string) {\n super(message, undefined, 'CONFIG_ERROR');\n this.name = 'ConfigError';\n }\n}\n","import type { ResolvedConfig } from './types.js';\nimport { AuthError, DeeplineError, RateLimitError } from './errors.js';\n\nconst SDK_VERSION = '0.1.0';\n\ninterface RequestOptions {\n method?: 'GET' | 'POST' | 'PUT' | 'DELETE';\n body?: unknown;\n headers?: Record<string, string>;\n timeout?: number;\n}\n\nexport class HttpClient {\n constructor(private config: ResolvedConfig) {}\n\n async request<T = unknown>(path: string, options?: RequestOptions): Promise<T> {\n const url = `${this.config.baseUrl}${path}`;\n const method = options?.method ?? 'GET';\n\n const headers: Record<string, string> = {\n 'Authorization': `Bearer ${this.config.apiKey}`,\n 'User-Agent': `deepline-ts-sdk/${SDK_VERSION}`,\n ...options?.headers,\n };\n\n if (options?.body !== undefined) {\n headers['Content-Type'] = 'application/json';\n }\n\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {\n if (attempt > 0) {\n const backoffMs = Math.min(1000 * Math.pow(2, attempt - 1), 30_000);\n await sleep(backoffMs);\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(\n () => controller.abort(),\n options?.timeout ?? this.config.timeout,\n );\n\n try {\n const response = await fetch(url, {\n method,\n headers,\n body: options?.body !== undefined ? JSON.stringify(options.body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (response.status === 401 || response.status === 403) {\n throw new AuthError();\n }\n\n if (response.status === 429) {\n const retryAfter = parseRetryAfter(response);\n lastError = new RateLimitError(retryAfter);\n if (attempt < this.config.maxRetries) continue;\n throw lastError;\n }\n\n const body = await response.text();\n let parsed: unknown;\n try {\n parsed = JSON.parse(body);\n } catch {\n parsed = body;\n }\n\n if (!response.ok) {\n const msg =\n typeof parsed === 'object' && parsed && 'error' in parsed\n ? String((parsed as Record<string, unknown>).error)\n : `HTTP ${response.status}`;\n throw new DeeplineError(msg, response.status, 'API_ERROR', {\n response: parsed,\n });\n }\n\n return parsed as T;\n } catch (error) {\n clearTimeout(timeoutId);\n if (error instanceof AuthError || error instanceof DeeplineError) {\n throw error;\n }\n if (error instanceof RateLimitError) {\n lastError = error;\n if (attempt < this.config.maxRetries) continue;\n throw error;\n }\n // Network / timeout errors\n lastError = error instanceof Error ? error : new Error(String(error));\n if (attempt < this.config.maxRetries) continue;\n }\n }\n\n throw lastError ?? new DeeplineError('Request failed after retries');\n }\n\n async get<T = unknown>(path: string): Promise<T> {\n return this.request<T>(path, { method: 'GET' });\n }\n\n async post<T = unknown>(path: string, body: unknown): Promise<T> {\n return this.request<T>(path, { method: 'POST', body });\n }\n}\n\nfunction parseRetryAfter(response: Response): number {\n const header = response.headers.get('retry-after');\n if (header) {\n const seconds = Number(header);\n if (Number.isFinite(seconds) && seconds > 0) {\n return seconds * 1000;\n }\n }\n return 5000;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import { resolveConfig } from './config.js';\nimport { HttpClient } from './http.js';\nimport type { DeeplineClientOptions, ResolvedConfig, PlayRunResult, ToolDefinition } from './types.js';\n\nexport class DeeplineClient {\n private readonly http: HttpClient;\n private readonly config: ResolvedConfig;\n\n constructor(options?: DeeplineClientOptions) {\n this.config = resolveConfig(options);\n this.http = new HttpClient(this.config);\n }\n\n get baseUrl(): string {\n return this.config.baseUrl;\n }\n\n /** List available tools. */\n async listTools(): Promise<ToolDefinition[]> {\n const res = await this.http.get<{ tools: ToolDefinition[] }>('/api/v2/tools');\n return res.tools;\n }\n\n /** Execute a single tool. */\n async executeTool(toolId: string, input: Record<string, unknown>): Promise<unknown> {\n const res = await this.http.post<{ result: unknown }>(\n `/api/v2/integrations/${encodeURIComponent(toolId)}/execute`,\n { payload: input },\n );\n return res.result ?? res;\n }\n\n /**\n * Submit a play for cloud execution.\n * Returns a workflowId. Use pollPlay() to get status.\n */\n async submitPlay(code: string, csvPath: string, name?: string): Promise<{ workflowId: string }> {\n return this.http.post<{ workflowId: string }>('/api/v2/plays/run', {\n code,\n csvPath,\n name,\n });\n }\n\n /** Poll workflow status. */\n async getPlayStatus(workflowId: string): Promise<PlayStatus> {\n return this.http.get<PlayStatus>(`/api/v2/plays/run/${workflowId}`);\n }\n\n /** Cancel a running play. */\n async cancelPlay(workflowId: string): Promise<void> {\n await this.http.request(`/api/v2/plays/run/${workflowId}`, { method: 'DELETE' });\n }\n\n /**\n * Run a play end-to-end: submit, poll until done, return result.\n * onProgress is called on each poll with current status.\n */\n async runPlay(\n code: string,\n csvPath: string,\n name?: string,\n options?: {\n onProgress?: (status: PlayStatus) => void;\n pollIntervalMs?: number;\n signal?: AbortSignal;\n },\n ): Promise<PlayRunResult> {\n const { workflowId } = await this.submitPlay(code, csvPath, name);\n const pollInterval = options?.pollIntervalMs ?? 2000;\n const start = Date.now();\n\n while (true) {\n if (options?.signal?.aborted) {\n await this.cancelPlay(workflowId);\n return {\n success: false,\n workflowId,\n logs: [],\n durationMs: Date.now() - start,\n error: 'Cancelled by user',\n };\n }\n\n const status = await this.getPlayStatus(workflowId);\n options?.onProgress?.(status);\n\n const terminal = ['COMPLETED', 'FAILED', 'CANCELLED', 'TERMINATED', 'TIMED_OUT'];\n if (terminal.includes(status.temporalStatus)) {\n return {\n success: status.temporalStatus === 'COMPLETED',\n workflowId,\n result: status.result,\n logs: status.progress?.logs ?? [],\n durationMs: Date.now() - start,\n error: status.progress?.error ?? (status.temporalStatus !== 'COMPLETED' ? status.temporalStatus : undefined),\n };\n }\n\n await new Promise((resolve) => setTimeout(resolve, pollInterval));\n }\n }\n\n /** Health check. */\n async health(): Promise<{ status: string; version?: string }> {\n return this.http.get<{ status: string; version?: string }>('/api/v2/health');\n }\n}\n\nexport interface PlayStatus {\n workflowId: string;\n temporalStatus: string;\n progress?: {\n status: string;\n totalRows?: number;\n logs: string[];\n error?: string;\n };\n result?: unknown;\n}\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "deepline",
3
+ "version": "0.0.1",
4
+ "description": "Deepline SDK + CLI — B2B data enrichment powered by durable cloud execution",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/deeplineai/deepline"
9
+ },
10
+ "homepage": "https://code.deepline.com",
11
+ "keywords": [
12
+ "deepline",
13
+ "enrichment",
14
+ "b2b",
15
+ "data",
16
+ "leads",
17
+ "cli",
18
+ "sdk"
19
+ ],
20
+ "main": "./dist/index.cjs",
21
+ "module": "./dist/index.js",
22
+ "types": "./dist/index.d.ts",
23
+ "bin": {
24
+ "deepline": "./dist/cli/index.mjs"
25
+ },
26
+ "exports": {
27
+ ".": {
28
+ "types": "./dist/index.d.ts",
29
+ "import": "./dist/index.js",
30
+ "require": "./dist/index.cjs"
31
+ }
32
+ },
33
+ "files": [
34
+ "dist"
35
+ ],
36
+ "engines": {
37
+ "node": ">=18"
38
+ },
39
+ "scripts": {
40
+ "build": "tsup",
41
+ "dev": "tsup --watch",
42
+ "typecheck": "tsc --noEmit",
43
+ "prepublishOnly": "tsup"
44
+ },
45
+ "dependencies": {
46
+ "csv-parse": "^5.6.0",
47
+ "csv-stringify": "^6.5.0"
48
+ },
49
+ "devDependencies": {
50
+ "tsup": "^8.0.0",
51
+ "typescript": "^5.4.0",
52
+ "@types/node": "^20.0.0"
53
+ }
54
+ }