@myapihq/sdk 1.3.12 → 2.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.
- package/dist/auth.d.ts +58 -0
- package/dist/auth.js +76 -0
- package/dist/client.d.ts +6 -0
- package/dist/client.js +16 -3
- package/dist/config.d.ts +1 -0
- package/dist/config.js +2 -1
- package/dist/container.d.ts +8 -0
- package/dist/container.js +26 -2
- package/dist/crm.d.ts +1 -1
- package/dist/crm.js +4 -1
- package/dist/database.js +4 -1
- package/dist/domain.d.ts +1 -1
- package/dist/email.d.ts +0 -74
- package/dist/email.js +1 -70
- package/dist/function.d.ts +4 -0
- package/dist/function.js +8 -0
- package/dist/funnel.d.ts +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -1
- package/dist/payments.d.ts +1 -0
- package/dist/payments.js +1 -1
- package/dist/queue.d.ts +1 -0
- package/dist/queue.js +5 -0
- package/dist/services.js +15 -6
- package/dist/storage.d.ts +1 -1
- package/dist/types.d.ts +3 -0
- package/dist/webhook.d.ts +4 -0
- package/dist/workflow.d.ts +11 -1
- package/dist/workflow.js +12 -2
- package/package.json +1 -1
- package/src/auth.ts +129 -0
- package/src/client.ts +36 -4
- package/src/config.ts +1 -0
- package/src/container.ts +53 -3
- package/src/crm.ts +7 -3
- package/src/database.ts +5 -2
- package/src/domain.ts +1 -1
- package/src/email.ts +1 -78
- package/src/function.ts +12 -0
- package/src/funnel.ts +1 -1
- package/src/index.ts +1 -0
- package/src/payments.ts +2 -1
- package/src/queue.ts +5 -0
- package/src/services.ts +15 -6
- package/src/storage.ts +2 -0
- package/src/types.ts +3 -1
- package/src/webhook.ts +10 -0
- package/src/workflow.ts +34 -3
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { Exposes } from './exposes';
|
|
2
|
+
export declare const EXPOSES: Exposes;
|
|
3
|
+
export type AuthConnection = 'google' | 'password' | 'magic';
|
|
4
|
+
export interface Tenant {
|
|
5
|
+
tenant_id: string;
|
|
6
|
+
issuer: string;
|
|
7
|
+
login_url: string;
|
|
8
|
+
connections?: AuthConnection[];
|
|
9
|
+
}
|
|
10
|
+
export interface CreateTenantInput {
|
|
11
|
+
connections?: AuthConnection[];
|
|
12
|
+
theme?: unknown;
|
|
13
|
+
}
|
|
14
|
+
export interface AuthClient {
|
|
15
|
+
client_id: string;
|
|
16
|
+
name?: string;
|
|
17
|
+
type: 'spa' | 'web';
|
|
18
|
+
redirect_uris: string[];
|
|
19
|
+
issuer?: string;
|
|
20
|
+
client_secret?: string;
|
|
21
|
+
created_at?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface ListClientsResponse {
|
|
24
|
+
clients: AuthClient[];
|
|
25
|
+
}
|
|
26
|
+
export interface CreateClientInput {
|
|
27
|
+
name: string;
|
|
28
|
+
type: 'spa' | 'web';
|
|
29
|
+
redirect_uris: string[];
|
|
30
|
+
}
|
|
31
|
+
export interface AuthUsage {
|
|
32
|
+
period: string;
|
|
33
|
+
active_users: number;
|
|
34
|
+
price_cents_each: number;
|
|
35
|
+
}
|
|
36
|
+
export interface AuthDomain {
|
|
37
|
+
domain: string;
|
|
38
|
+
status: 'pending' | 'active';
|
|
39
|
+
dns: {
|
|
40
|
+
type: string;
|
|
41
|
+
name: string;
|
|
42
|
+
value: string;
|
|
43
|
+
};
|
|
44
|
+
next?: string;
|
|
45
|
+
issuer?: string;
|
|
46
|
+
login_url?: string;
|
|
47
|
+
}
|
|
48
|
+
export declare function createTenant(apiKey: string, orgId: string, input?: CreateTenantInput): Promise<Tenant>;
|
|
49
|
+
export declare function getTenant(apiKey: string, orgId: string): Promise<Tenant>;
|
|
50
|
+
export declare function createClient(apiKey: string, orgId: string, input: CreateClientInput): Promise<AuthClient>;
|
|
51
|
+
export declare function listClients(apiKey: string, orgId: string): Promise<ListClientsResponse>;
|
|
52
|
+
export declare function getUsage(apiKey: string, orgId: string): Promise<AuthUsage>;
|
|
53
|
+
export declare function registerDomain(apiKey: string, orgId: string, domain: string): Promise<AuthDomain>;
|
|
54
|
+
export declare function getDomain(apiKey: string, orgId: string): Promise<AuthDomain>;
|
|
55
|
+
export declare function deleteDomain(apiKey: string, orgId: string, domain: string): Promise<{
|
|
56
|
+
domain: string;
|
|
57
|
+
status: string;
|
|
58
|
+
}>;
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EXPOSES = void 0;
|
|
4
|
+
exports.createTenant = createTenant;
|
|
5
|
+
exports.getTenant = getTenant;
|
|
6
|
+
exports.createClient = createClient;
|
|
7
|
+
exports.listClients = listClients;
|
|
8
|
+
exports.getUsage = getUsage;
|
|
9
|
+
exports.registerDomain = registerDomain;
|
|
10
|
+
exports.getDomain = getDomain;
|
|
11
|
+
exports.deleteDomain = deleteDomain;
|
|
12
|
+
const client_1 = require("./client");
|
|
13
|
+
const config_1 = require("./config");
|
|
14
|
+
// The end-user auth product (my-auth-api): a managed multi-tenant OIDC
|
|
15
|
+
// Identity Provider for the END USERS of apps built on MyAPI. Distinct from
|
|
16
|
+
// operator/account auth (hq/account/*). Each org gets one auth tenant; OIDC
|
|
17
|
+
// clients (apps) register against it. End users sign in with managed Google,
|
|
18
|
+
// email/password, or magic links (per the tenant's `connections`). Tokens are
|
|
19
|
+
// RS256, verified via the tenant's JWKS.
|
|
20
|
+
//
|
|
21
|
+
// The browser/app-facing OIDC + sign-in flows — discovery, jwks, authorize,
|
|
22
|
+
// token, userinfo, password/magic/google login, verify-email, password reset,
|
|
23
|
+
// the hosted login page — are machine/end-user surfaces consumed by apps, the
|
|
24
|
+
// JS SDK, and browsers, NOT management calls; they are not CLI/SDK verbs. This
|
|
25
|
+
// module covers only the org-scoped MANAGEMENT surface: tenant, clients, MAU
|
|
26
|
+
// usage, and the custom auth domain.
|
|
27
|
+
exports.EXPOSES = [
|
|
28
|
+
'POST /auth/orgs/{org_id}/tenant',
|
|
29
|
+
'GET /auth/orgs/{org_id}/tenant',
|
|
30
|
+
'POST /auth/orgs/{org_id}/clients',
|
|
31
|
+
'GET /auth/orgs/{org_id}/clients',
|
|
32
|
+
'GET /auth/orgs/{org_id}/usage',
|
|
33
|
+
'POST /auth/orgs/{org_id}/domain',
|
|
34
|
+
'GET /auth/orgs/{org_id}/domain',
|
|
35
|
+
'DELETE /auth/orgs/{org_id}/domain',
|
|
36
|
+
];
|
|
37
|
+
// Create (or update) the org's auth tenant. Idempotent. `connections` selects
|
|
38
|
+
// the sign-in methods (subset of google/password/magic; defaults to google);
|
|
39
|
+
// `theme` is opaque JSON for the hosted login page.
|
|
40
|
+
async function createTenant(apiKey, orgId, input = {}) {
|
|
41
|
+
const body = {};
|
|
42
|
+
if (input.connections !== undefined)
|
|
43
|
+
body.connections = input.connections;
|
|
44
|
+
if (input.theme !== undefined)
|
|
45
|
+
body.theme = input.theme;
|
|
46
|
+
return (0, client_1.request)('POST', `${config_1.AUTH_BASE}/auth/orgs/${encodeURIComponent(orgId)}/tenant`, apiKey, body);
|
|
47
|
+
}
|
|
48
|
+
// Fetch the org's auth tenant. Rejects with TENANT_NOT_FOUND if not created.
|
|
49
|
+
async function getTenant(apiKey, orgId) {
|
|
50
|
+
return (0, client_1.request)('GET', `${config_1.AUTH_BASE}/auth/orgs/${encodeURIComponent(orgId)}/tenant`, apiKey);
|
|
51
|
+
}
|
|
52
|
+
// Register an OIDC client (an app) under the org's tenant. Auto-provisions the
|
|
53
|
+
// tenant if absent. For type 'web' the response carries `client_secret` once.
|
|
54
|
+
async function createClient(apiKey, orgId, input) {
|
|
55
|
+
return (0, client_1.request)('POST', `${config_1.AUTH_BASE}/auth/orgs/${encodeURIComponent(orgId)}/clients`, apiKey, input);
|
|
56
|
+
}
|
|
57
|
+
async function listClients(apiKey, orgId) {
|
|
58
|
+
return (0, client_1.request)('GET', `${config_1.AUTH_BASE}/auth/orgs/${encodeURIComponent(orgId)}/clients`, apiKey);
|
|
59
|
+
}
|
|
60
|
+
// Monthly-active-user usage for the current period (auth is billed per MAU).
|
|
61
|
+
async function getUsage(apiKey, orgId) {
|
|
62
|
+
return (0, client_1.request)('GET', `${config_1.AUTH_BASE}/auth/orgs/${encodeURIComponent(orgId)}/usage`, apiKey);
|
|
63
|
+
}
|
|
64
|
+
// Set a custom auth domain (e.g. auth.acme.com). Returns the DNS record to
|
|
65
|
+
// create; TLS provisions automatically and the domain becomes the issuer once
|
|
66
|
+
// active. One custom domain per org.
|
|
67
|
+
async function registerDomain(apiKey, orgId, domain) {
|
|
68
|
+
return (0, client_1.request)('POST', `${config_1.AUTH_BASE}/auth/orgs/${encodeURIComponent(orgId)}/domain`, apiKey, { domain });
|
|
69
|
+
}
|
|
70
|
+
// Fetch the org's custom auth domain. Rejects with NO_DOMAIN if none set.
|
|
71
|
+
async function getDomain(apiKey, orgId) {
|
|
72
|
+
return (0, client_1.request)('GET', `${config_1.AUTH_BASE}/auth/orgs/${encodeURIComponent(orgId)}/domain`, apiKey);
|
|
73
|
+
}
|
|
74
|
+
async function deleteDomain(apiKey, orgId, domain) {
|
|
75
|
+
return (0, client_1.request)('DELETE', `${config_1.AUTH_BASE}/auth/orgs/${encodeURIComponent(orgId)}/domain`, apiKey, { domain });
|
|
76
|
+
}
|
package/dist/client.d.ts
CHANGED
|
@@ -6,3 +6,9 @@ export declare class MyApiError extends Error {
|
|
|
6
6
|
constructor(code: string, status: number, detail?: string | undefined, body?: Record<string, unknown> | undefined);
|
|
7
7
|
}
|
|
8
8
|
export declare function request<T>(method: string, url: string, apiKey?: string, body?: unknown, extraHeaders?: Record<string, string>): Promise<T>;
|
|
9
|
+
export interface Page<T> {
|
|
10
|
+
data: T[];
|
|
11
|
+
next_cursor?: string;
|
|
12
|
+
has_more?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare function requestPage<T>(method: string, url: string, apiKey?: string, body?: unknown, extraHeaders?: Record<string, string>): Promise<Page<T>>;
|
package/dist/client.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MyApiError = void 0;
|
|
4
4
|
exports.request = request;
|
|
5
|
+
exports.requestPage = requestPage;
|
|
5
6
|
class MyApiError extends Error {
|
|
6
7
|
code;
|
|
7
8
|
status;
|
|
@@ -22,7 +23,7 @@ class MyApiError extends Error {
|
|
|
22
23
|
}
|
|
23
24
|
}
|
|
24
25
|
exports.MyApiError = MyApiError;
|
|
25
|
-
async function
|
|
26
|
+
async function requestFull(method, url, apiKey, body, extraHeaders) {
|
|
26
27
|
const headers = {};
|
|
27
28
|
if (apiKey) {
|
|
28
29
|
headers['Authorization'] = `Bearer ${apiKey}`;
|
|
@@ -46,7 +47,7 @@ async function request(method, url, apiKey, body, extraHeaders) {
|
|
|
46
47
|
}
|
|
47
48
|
const response = await fetch(url, options);
|
|
48
49
|
if (response.status === 204) {
|
|
49
|
-
return
|
|
50
|
+
return { success: true, data: null, error: null, meta: {} };
|
|
50
51
|
}
|
|
51
52
|
// Read the body as text first so we can include a snippet in errors when
|
|
52
53
|
// it isn't valid JSON (HTML error pages from edge proxies, plaintext
|
|
@@ -75,5 +76,17 @@ async function request(method, url, apiKey, body, extraHeaders) {
|
|
|
75
76
|
const errBody = typeof err === 'object' ? err : undefined;
|
|
76
77
|
throw new MyApiError(code, response.status, detail, errBody);
|
|
77
78
|
}
|
|
78
|
-
return apiResponse
|
|
79
|
+
return apiResponse;
|
|
80
|
+
}
|
|
81
|
+
// Returns the unwrapped `data` payload — the common case.
|
|
82
|
+
async function request(method, url, apiKey, body, extraHeaders) {
|
|
83
|
+
return (await requestFull(method, url, apiKey, body, extraHeaders)).data;
|
|
84
|
+
}
|
|
85
|
+
// For keyset-paginated endpoints (backend `envelope.WrapPage`): `data` is a
|
|
86
|
+
// bare array and the cursor/has_more live under `meta`. `request` would drop
|
|
87
|
+
// the cursor, so list endpoints with pagination must use this.
|
|
88
|
+
async function requestPage(method, url, apiKey, body, extraHeaders) {
|
|
89
|
+
const r = await requestFull(method, url, apiKey, body, extraHeaders);
|
|
90
|
+
const meta = (r.meta ?? {});
|
|
91
|
+
return { data: (r.data ?? []), next_cursor: meta.next_cursor, has_more: meta.has_more };
|
|
79
92
|
}
|
package/dist/config.d.ts
CHANGED
package/dist/config.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// local dev — `source scripts/local-env.sh` still points everything at
|
|
9
9
|
// localhost:8080 regardless of the prod default.
|
|
10
10
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
-
exports.CRM_BASE = exports.DATABASE_BASE = exports.LLM_BASE = exports.AUDIENCE_BASE = exports.COMPANY_BASE = exports.PEOPLE_BASE = exports.PIXEL_BASE = exports.URL_BASE = exports.STORAGE_BASE = exports.EMAIL_BASE = exports.WORKFLOW_BASE = exports.WEBHOOK_BASE = exports.IMAGE_BASE = exports.TASK_BASE = exports.QUEUE_BASE = exports.GIT_BASE = exports.CONTAINER_BASE = exports.PAYMENTS_BASE = exports.FUNCTION_BASE = exports.FUNNEL_BASE = exports.DOMAIN_BASE = exports.HQ_BASE = void 0;
|
|
11
|
+
exports.AUTH_BASE = exports.CRM_BASE = exports.DATABASE_BASE = exports.LLM_BASE = exports.AUDIENCE_BASE = exports.COMPANY_BASE = exports.PEOPLE_BASE = exports.PIXEL_BASE = exports.URL_BASE = exports.STORAGE_BASE = exports.EMAIL_BASE = exports.WORKFLOW_BASE = exports.WEBHOOK_BASE = exports.IMAGE_BASE = exports.TASK_BASE = exports.QUEUE_BASE = exports.GIT_BASE = exports.CONTAINER_BASE = exports.PAYMENTS_BASE = exports.FUNCTION_BASE = exports.FUNNEL_BASE = exports.DOMAIN_BASE = exports.HQ_BASE = void 0;
|
|
12
12
|
const GATEWAY = 'https://api.myapihq.com';
|
|
13
13
|
exports.HQ_BASE = process.env.MYAPI_HQ_URL ?? process.env.MYAPI_API_BASE ?? GATEWAY;
|
|
14
14
|
exports.DOMAIN_BASE = process.env.MYAPI_DOMAIN_URL ?? 'https://api.mydomainapi.com';
|
|
@@ -37,3 +37,4 @@ exports.AUDIENCE_BASE = process.env.MYAPI_AUDIENCE_URL ?? GATEWAY;
|
|
|
37
37
|
exports.LLM_BASE = process.env.MYAPI_LLM_URL ?? GATEWAY;
|
|
38
38
|
exports.DATABASE_BASE = process.env.MYAPI_DATABASE_URL ?? GATEWAY;
|
|
39
39
|
exports.CRM_BASE = process.env.MYAPI_CRM_URL ?? GATEWAY;
|
|
40
|
+
exports.AUTH_BASE = process.env.MYAPI_AUTH_URL ?? GATEWAY;
|
package/dist/container.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export interface Container {
|
|
|
16
16
|
url?: string;
|
|
17
17
|
custom_domain?: string;
|
|
18
18
|
status: string;
|
|
19
|
+
egress: string;
|
|
19
20
|
created_at: string;
|
|
20
21
|
updated_at: string;
|
|
21
22
|
}
|
|
@@ -47,6 +48,13 @@ export declare function listContainers(apiKey: string, orgId: string): Promise<C
|
|
|
47
48
|
export declare function getContainer(apiKey: string, orgId: string, containerId: string): Promise<Container>;
|
|
48
49
|
export declare function deleteContainer(apiKey: string, orgId: string, containerId: string): Promise<void>;
|
|
49
50
|
export declare function deployContainer(apiKey: string, orgId: string, containerId: string, image: string): Promise<DeployResponse>;
|
|
51
|
+
export interface BuildDeployResponse {
|
|
52
|
+
container_id: string;
|
|
53
|
+
revision_id: string;
|
|
54
|
+
status: string;
|
|
55
|
+
message?: string;
|
|
56
|
+
}
|
|
57
|
+
export declare function deployContainerSource(apiKey: string, orgId: string, containerId: string, tarball: Blob | Buffer, filename?: string): Promise<BuildDeployResponse>;
|
|
50
58
|
export interface LogEntry {
|
|
51
59
|
timestamp: string;
|
|
52
60
|
severity: string;
|
package/dist/container.js
CHANGED
|
@@ -6,6 +6,7 @@ exports.listContainers = listContainers;
|
|
|
6
6
|
exports.getContainer = getContainer;
|
|
7
7
|
exports.deleteContainer = deleteContainer;
|
|
8
8
|
exports.deployContainer = deployContainer;
|
|
9
|
+
exports.deployContainerSource = deployContainerSource;
|
|
9
10
|
exports.getContainerLogs = getContainerLogs;
|
|
10
11
|
exports.bindDomain = bindDomain;
|
|
11
12
|
exports.unbindDomain = unbindDomain;
|
|
@@ -36,11 +37,34 @@ async function getContainer(apiKey, orgId, containerId) {
|
|
|
36
37
|
async function deleteContainer(apiKey, orgId, containerId) {
|
|
37
38
|
return (0, client_1.request)('DELETE', `${config_1.CONTAINER_BASE}/container/orgs/${encodeURIComponent(orgId)}/containers/${encodeURIComponent(containerId)}`, apiKey);
|
|
38
39
|
}
|
|
39
|
-
// deployContainer ships a revision from a pre-built image ref to Cloud Run
|
|
40
|
-
//
|
|
40
|
+
// deployContainer ships a revision from a pre-built image ref to Cloud Run.
|
|
41
|
+
// Synchronous — returns status='active' with a rotated scoped key.
|
|
41
42
|
async function deployContainer(apiKey, orgId, containerId, image) {
|
|
42
43
|
return (0, client_1.request)('POST', `${config_1.CONTAINER_BASE}/container/orgs/${encodeURIComponent(orgId)}/containers/${encodeURIComponent(containerId)}/deploy`, apiKey, { image });
|
|
43
44
|
}
|
|
45
|
+
// deployContainerSource uploads a build-context tarball via multipart `source`
|
|
46
|
+
// (backend deploy.go builds it via Cloud Build → Artifact Registry, then
|
|
47
|
+
// deploys). Asynchronous: returns status='building' to poll. The tarball is
|
|
48
|
+
// capped at 100MB server-side. Mirrors the multipart upload in storage.ts.
|
|
49
|
+
async function deployContainerSource(apiKey, orgId, containerId, tarball, filename = 'source.tar.gz') {
|
|
50
|
+
const formData = new FormData();
|
|
51
|
+
formData.append('source', new Blob([tarball], { type: 'application/gzip' }), filename);
|
|
52
|
+
const response = await fetch(`${config_1.CONTAINER_BASE}/container/orgs/${encodeURIComponent(orgId)}/containers/${encodeURIComponent(containerId)}/deploy`, { method: 'POST', headers: { Authorization: `Bearer ${apiKey}` }, body: formData });
|
|
53
|
+
let result;
|
|
54
|
+
try {
|
|
55
|
+
result = await response.json();
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
throw new client_1.MyApiError('invalid_json_response', response.status);
|
|
59
|
+
}
|
|
60
|
+
if (!response.ok || !result?.success) {
|
|
61
|
+
const err = result?.error;
|
|
62
|
+
const code = typeof err === 'object' ? (err?.code || 'unknown_error') : (err || 'unknown_error');
|
|
63
|
+
const detail = typeof err === 'object' ? err?.message : undefined;
|
|
64
|
+
throw new client_1.MyApiError(code, response.status, detail, typeof err === 'object' ? err : undefined);
|
|
65
|
+
}
|
|
66
|
+
return result.data;
|
|
67
|
+
}
|
|
44
68
|
// getContainerLogs returns recent runtime log entries, newest first.
|
|
45
69
|
// `tail` caps the count (default 100, max 1000 server-side). An
|
|
46
70
|
// undeployed container returns an empty array.
|
package/dist/crm.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { Exposes } from './exposes';
|
|
|
2
2
|
export declare const EXPOSES: Exposes;
|
|
3
3
|
export type LifecycleStage = 'cold' | 'warm' | 'qualified' | 'customer' | 'churned';
|
|
4
4
|
export type ContactSource = 'goldfox' | 'email' | 'pixel' | 'webhook' | 'manual';
|
|
5
|
-
export type EventKind = 'created' | 'promoted' | 'stage_changed' | 'email_sent' | 'email_opened' | 'email_clicked' | 'email_replied' | 'pixel_visit' | 'webhook_received';
|
|
5
|
+
export type EventKind = 'created' | 'promoted' | 'stage_changed' | 'email_sent' | 'email_opened' | 'email_clicked' | 'email_replied' | 'pixel_visit' | 'webhook_received' | 'payment';
|
|
6
6
|
export interface Contact {
|
|
7
7
|
id: string;
|
|
8
8
|
org_id: string;
|
package/dist/crm.js
CHANGED
|
@@ -60,7 +60,10 @@ async function getContactEvents(apiKey, orgId, id, opts = {}) {
|
|
|
60
60
|
qs.append('kind', opts.kind);
|
|
61
61
|
const q = qs.toString();
|
|
62
62
|
const url = `${config_1.CRM_BASE}/crm/orgs/${encodeURIComponent(orgId)}/contacts/${encodeURIComponent(id)}/events${q ? `?${q}` : ''}`;
|
|
63
|
-
|
|
63
|
+
// Paginated (WrapPage): events are the bare `data` array with the cursor
|
|
64
|
+
// under `meta` — use requestPage so `next_cursor` survives.
|
|
65
|
+
const page = await (0, client_1.requestPage)('GET', url, apiKey);
|
|
66
|
+
return { events: page.data, next_cursor: page.next_cursor };
|
|
64
67
|
}
|
|
65
68
|
// ── Companies ─────────────────────────────────────────────────────────────
|
|
66
69
|
async function createCompany(apiKey, orgId, input) {
|
package/dist/database.js
CHANGED
|
@@ -48,7 +48,10 @@ async function listKeys(apiKey, orgId, ns, opts = {}) {
|
|
|
48
48
|
qs.append('values', 'true');
|
|
49
49
|
const q = qs.toString();
|
|
50
50
|
const url = `${config_1.DATABASE_BASE}/database/orgs/${encodeURIComponent(orgId)}/namespaces/${encodeURIComponent(ns)}/keys${q ? `?${q}` : ''}`;
|
|
51
|
-
|
|
51
|
+
// Paginated (WrapPage): keys come back as the bare `data` array with the
|
|
52
|
+
// cursor under `meta` — must use requestPage or the cursor is lost.
|
|
53
|
+
const page = await (0, client_1.requestPage)('GET', url, apiKey);
|
|
54
|
+
return { keys: page.data, next_cursor: page.next_cursor };
|
|
52
55
|
}
|
|
53
56
|
async function getKey(apiKey, orgId, ns, key) {
|
|
54
57
|
return (0, client_1.request)('GET', `${config_1.DATABASE_BASE}/database/orgs/${encodeURIComponent(orgId)}/namespaces/${encodeURIComponent(ns)}/keys/${encodeURIComponent(key)}`, apiKey);
|
package/dist/domain.d.ts
CHANGED
|
@@ -107,7 +107,7 @@ export declare function deleteDnsRecord(apiKey: string, orgId: string, domain: s
|
|
|
107
107
|
export interface EmailInfraResponse {
|
|
108
108
|
domain: string;
|
|
109
109
|
email_infra: 'pending' | 'ready' | 'error';
|
|
110
|
-
|
|
110
|
+
subdomain: string;
|
|
111
111
|
next_step?: string;
|
|
112
112
|
}
|
|
113
113
|
export declare function setupEmailInfra(apiKey: string, orgId: string, domain: string, subdomain?: string): Promise<EmailInfraResponse>;
|
package/dist/email.d.ts
CHANGED
|
@@ -15,45 +15,6 @@ export interface EmailTemplate {
|
|
|
15
15
|
created_at: string;
|
|
16
16
|
updated_at: string;
|
|
17
17
|
}
|
|
18
|
-
export interface WarmupConfig {
|
|
19
|
-
enabled: boolean;
|
|
20
|
-
start: number;
|
|
21
|
-
increment: number;
|
|
22
|
-
max: number;
|
|
23
|
-
}
|
|
24
|
-
export interface Campaign {
|
|
25
|
-
id: string;
|
|
26
|
-
name: string;
|
|
27
|
-
status: string;
|
|
28
|
-
template_id: string;
|
|
29
|
-
from_address: string;
|
|
30
|
-
per_day_limit: number;
|
|
31
|
-
warmup_config?: WarmupConfig;
|
|
32
|
-
created_at: string;
|
|
33
|
-
}
|
|
34
|
-
export interface CampaignStats {
|
|
35
|
-
campaign: Campaign;
|
|
36
|
-
validation: {
|
|
37
|
-
total: number;
|
|
38
|
-
valid: number;
|
|
39
|
-
invalid: number;
|
|
40
|
-
pending: number;
|
|
41
|
-
list_status: string;
|
|
42
|
-
};
|
|
43
|
-
dispatch: {
|
|
44
|
-
sent: number;
|
|
45
|
-
remaining: number;
|
|
46
|
-
sent_this_hour: number;
|
|
47
|
-
hour_limit: number;
|
|
48
|
-
last_dispatch_at: string;
|
|
49
|
-
};
|
|
50
|
-
engagement: {
|
|
51
|
-
sent: number;
|
|
52
|
-
opens: number;
|
|
53
|
-
clicks: number;
|
|
54
|
-
page_visits: number;
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
18
|
export type VerifyVerdict = 'deliverable' | 'undeliverable' | 'unknown';
|
|
58
19
|
export interface VerifyChecks {
|
|
59
20
|
syntax: {
|
|
@@ -191,38 +152,3 @@ export declare function sendTestEmail(apiKey: string, orgId: string, templateId:
|
|
|
191
152
|
}>;
|
|
192
153
|
export declare function listTemplates(apiKey: string, orgId: string): Promise<EmailTemplate[]>;
|
|
193
154
|
export declare function deleteTemplate(apiKey: string, orgId: string, templateId: string): Promise<void>;
|
|
194
|
-
export declare function createCampaign(apiKey: string, orgId: string, payload: {
|
|
195
|
-
name: string;
|
|
196
|
-
template_id: string;
|
|
197
|
-
from_address: string;
|
|
198
|
-
per_day_limit?: number;
|
|
199
|
-
warmup_config?: WarmupConfig | null;
|
|
200
|
-
}): Promise<Campaign>;
|
|
201
|
-
export declare function uploadContactList(apiKey: string, orgId: string, campaignId: string, emails: string[]): Promise<{
|
|
202
|
-
list_id: string;
|
|
203
|
-
total: number;
|
|
204
|
-
status: string;
|
|
205
|
-
}>;
|
|
206
|
-
export declare function uploadContactsFile(apiKey: string, orgId: string, campaignId: string, file: Blob | ArrayBuffer | Uint8Array, filename?: string): Promise<{
|
|
207
|
-
list_id: string;
|
|
208
|
-
total: number;
|
|
209
|
-
status: string;
|
|
210
|
-
}>;
|
|
211
|
-
export declare function getContactUploadStatus(apiKey: string, orgId: string, campaignId: string): Promise<{
|
|
212
|
-
upload_status: 'ready' | 'validating' | 'failed';
|
|
213
|
-
total: number;
|
|
214
|
-
valid_count: number;
|
|
215
|
-
invalid_count: number;
|
|
216
|
-
}>;
|
|
217
|
-
export declare function startCampaign(apiKey: string, orgId: string, campaignId: string): Promise<{
|
|
218
|
-
status: string;
|
|
219
|
-
}>;
|
|
220
|
-
export declare function pauseCampaign(apiKey: string, orgId: string, campaignId: string): Promise<void>;
|
|
221
|
-
export declare function resumeCampaign(apiKey: string, orgId: string, campaignId: string): Promise<void>;
|
|
222
|
-
export declare function getCampaignStats(apiKey: string, orgId: string, campaignId: string): Promise<CampaignStats>;
|
|
223
|
-
export declare function listCampaigns(apiKey: string, orgId: string): Promise<Campaign[]>;
|
|
224
|
-
export declare function getCampaign(apiKey: string, orgId: string, campaignId: string): Promise<Campaign>;
|
|
225
|
-
export declare function updateCampaign(apiKey: string, orgId: string, campaignId: string, payload: {
|
|
226
|
-
name?: string;
|
|
227
|
-
per_day_limit?: number;
|
|
228
|
-
}): Promise<Campaign>;
|
package/dist/email.js
CHANGED
|
@@ -30,17 +30,6 @@ exports.editTemplate = editTemplate;
|
|
|
30
30
|
exports.sendTestEmail = sendTestEmail;
|
|
31
31
|
exports.listTemplates = listTemplates;
|
|
32
32
|
exports.deleteTemplate = deleteTemplate;
|
|
33
|
-
exports.createCampaign = createCampaign;
|
|
34
|
-
exports.uploadContactList = uploadContactList;
|
|
35
|
-
exports.uploadContactsFile = uploadContactsFile;
|
|
36
|
-
exports.getContactUploadStatus = getContactUploadStatus;
|
|
37
|
-
exports.startCampaign = startCampaign;
|
|
38
|
-
exports.pauseCampaign = pauseCampaign;
|
|
39
|
-
exports.resumeCampaign = resumeCampaign;
|
|
40
|
-
exports.getCampaignStats = getCampaignStats;
|
|
41
|
-
exports.listCampaigns = listCampaigns;
|
|
42
|
-
exports.getCampaign = getCampaign;
|
|
43
|
-
exports.updateCampaign = updateCampaign;
|
|
44
33
|
const client_1 = require("./client");
|
|
45
34
|
const config_1 = require("./config");
|
|
46
35
|
exports.EXPOSES = [
|
|
@@ -72,18 +61,6 @@ exports.EXPOSES = [
|
|
|
72
61
|
'POST /email/orgs/{org_id}/templates/{template_id}/send-test',
|
|
73
62
|
'DELETE /email/orgs/{org_id}/templates/{template_id}',
|
|
74
63
|
'GET /email/templates/{template_id}/preview',
|
|
75
|
-
// Campaigns
|
|
76
|
-
'POST /email/orgs/{org_id}/campaigns',
|
|
77
|
-
'GET /email/orgs/{org_id}/campaigns',
|
|
78
|
-
'GET /email/orgs/{org_id}/campaigns/{campaign_id}',
|
|
79
|
-
'PATCH /email/orgs/{org_id}/campaigns/{campaign_id}',
|
|
80
|
-
'POST /email/orgs/{org_id}/campaigns/{campaign_id}/contacts/upload-list',
|
|
81
|
-
'POST /email/orgs/{org_id}/campaigns/{campaign_id}/contacts/upload-file',
|
|
82
|
-
'GET /email/orgs/{org_id}/campaigns/{campaign_id}/contacts/status',
|
|
83
|
-
'POST /email/orgs/{org_id}/campaigns/{campaign_id}/start',
|
|
84
|
-
'POST /email/orgs/{org_id}/campaigns/{campaign_id}/pause',
|
|
85
|
-
'POST /email/orgs/{org_id}/campaigns/{campaign_id}/resume',
|
|
86
|
-
'GET /email/orgs/{org_id}/campaigns/{campaign_id}/stats',
|
|
87
64
|
// Verify
|
|
88
65
|
'POST /email/orgs/{org_id}/verify',
|
|
89
66
|
'POST /email/orgs/{org_id}/verify-bulk',
|
|
@@ -110,8 +87,7 @@ async function createMailbox(apiKey, domain, username, displayName) {
|
|
|
110
87
|
return (0, client_1.request)('POST', `${config_1.EMAIL_BASE}/email/mailboxes/create`, apiKey, { domain, username, display_name: displayName });
|
|
111
88
|
}
|
|
112
89
|
// Backend (2026-06-06): idempotent — 204 whether the mailbox existed or not.
|
|
113
|
-
//
|
|
114
|
-
// this address; pause/delete the campaign first.
|
|
90
|
+
// May return 409 MAILBOX_IN_USE if the address is still referenced server-side.
|
|
115
91
|
async function deleteMailbox(apiKey, address) {
|
|
116
92
|
return (0, client_1.request)('DELETE', `${config_1.EMAIL_BASE}/email/mailboxes/${encodeURIComponent(address)}`, apiKey);
|
|
117
93
|
}
|
|
@@ -207,48 +183,3 @@ async function listTemplates(apiKey, orgId) {
|
|
|
207
183
|
async function deleteTemplate(apiKey, orgId, templateId) {
|
|
208
184
|
return (0, client_1.request)('DELETE', `${config_1.EMAIL_BASE}/email/orgs/${encodeURIComponent(orgId)}/templates/${encodeURIComponent(templateId)}`, apiKey);
|
|
209
185
|
}
|
|
210
|
-
// ── Campaigns (org-scoped) ───────────────────────────────────────────────────
|
|
211
|
-
async function createCampaign(apiKey, orgId, payload) {
|
|
212
|
-
return (0, client_1.request)('POST', `${config_1.EMAIL_BASE}/email/orgs/${encodeURIComponent(orgId)}/campaigns`, apiKey, payload);
|
|
213
|
-
}
|
|
214
|
-
async function uploadContactList(apiKey, orgId, campaignId, emails) {
|
|
215
|
-
return (0, client_1.request)('POST', `${config_1.EMAIL_BASE}/email/orgs/${encodeURIComponent(orgId)}/campaigns/${encodeURIComponent(campaignId)}/contacts/upload-list`, apiKey, { emails });
|
|
216
|
-
}
|
|
217
|
-
async function uploadContactsFile(apiKey, orgId, campaignId, file, filename = 'contacts.csv') {
|
|
218
|
-
const form = new FormData();
|
|
219
|
-
const blob = file instanceof Blob ? file : new Blob([file]);
|
|
220
|
-
form.append('file', blob, filename);
|
|
221
|
-
const res = await fetch(`${config_1.EMAIL_BASE}/email/orgs/${encodeURIComponent(orgId)}/campaigns/${encodeURIComponent(campaignId)}/contacts/upload-file`, {
|
|
222
|
-
method: 'POST',
|
|
223
|
-
headers: { Authorization: `Bearer ${apiKey}` },
|
|
224
|
-
body: form,
|
|
225
|
-
});
|
|
226
|
-
const json = await res.json();
|
|
227
|
-
if (!res.ok || !json.success)
|
|
228
|
-
throw new Error(json.error?.code || json.error || 'upload_failed');
|
|
229
|
-
return json.data;
|
|
230
|
-
}
|
|
231
|
-
async function getContactUploadStatus(apiKey, orgId, campaignId) {
|
|
232
|
-
return (0, client_1.request)('GET', `${config_1.EMAIL_BASE}/email/orgs/${encodeURIComponent(orgId)}/campaigns/${encodeURIComponent(campaignId)}/contacts/status`, apiKey);
|
|
233
|
-
}
|
|
234
|
-
async function startCampaign(apiKey, orgId, campaignId) {
|
|
235
|
-
return (0, client_1.request)('POST', `${config_1.EMAIL_BASE}/email/orgs/${encodeURIComponent(orgId)}/campaigns/${encodeURIComponent(campaignId)}/start`, apiKey);
|
|
236
|
-
}
|
|
237
|
-
async function pauseCampaign(apiKey, orgId, campaignId) {
|
|
238
|
-
return (0, client_1.request)('POST', `${config_1.EMAIL_BASE}/email/orgs/${encodeURIComponent(orgId)}/campaigns/${encodeURIComponent(campaignId)}/pause`, apiKey);
|
|
239
|
-
}
|
|
240
|
-
async function resumeCampaign(apiKey, orgId, campaignId) {
|
|
241
|
-
return (0, client_1.request)('POST', `${config_1.EMAIL_BASE}/email/orgs/${encodeURIComponent(orgId)}/campaigns/${encodeURIComponent(campaignId)}/resume`, apiKey);
|
|
242
|
-
}
|
|
243
|
-
async function getCampaignStats(apiKey, orgId, campaignId) {
|
|
244
|
-
return (0, client_1.request)('GET', `${config_1.EMAIL_BASE}/email/orgs/${encodeURIComponent(orgId)}/campaigns/${encodeURIComponent(campaignId)}/stats`, apiKey);
|
|
245
|
-
}
|
|
246
|
-
async function listCampaigns(apiKey, orgId) {
|
|
247
|
-
return (0, client_1.request)('GET', `${config_1.EMAIL_BASE}/email/orgs/${encodeURIComponent(orgId)}/campaigns`, apiKey);
|
|
248
|
-
}
|
|
249
|
-
async function getCampaign(apiKey, orgId, campaignId) {
|
|
250
|
-
return (0, client_1.request)('GET', `${config_1.EMAIL_BASE}/email/orgs/${encodeURIComponent(orgId)}/campaigns/${encodeURIComponent(campaignId)}`, apiKey);
|
|
251
|
-
}
|
|
252
|
-
async function updateCampaign(apiKey, orgId, campaignId, payload) {
|
|
253
|
-
return (0, client_1.request)('PATCH', `${config_1.EMAIL_BASE}/email/orgs/${encodeURIComponent(orgId)}/campaigns/${encodeURIComponent(campaignId)}`, apiKey, payload);
|
|
254
|
-
}
|
package/dist/function.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export interface CreatePayload {
|
|
|
15
15
|
name: string;
|
|
16
16
|
trigger_type?: TriggerType;
|
|
17
17
|
cron_schedule?: string;
|
|
18
|
+
scopes?: string[];
|
|
18
19
|
}
|
|
19
20
|
export interface CreateResponse {
|
|
20
21
|
function: Fn;
|
|
@@ -40,4 +41,7 @@ export declare function getFunction(apiKey: string, orgId: string, fnId: string)
|
|
|
40
41
|
export declare function deleteFunction(apiKey: string, orgId: string, fnId: string): Promise<void>;
|
|
41
42
|
export declare function uploadBundle(apiKey: string, orgId: string, fnId: string, bundle: Blob | Buffer | string, filename?: string): Promise<DeployResponse>;
|
|
42
43
|
export declare function setFunctionEnv(apiKey: string, orgId: string, fnId: string, name: string, value: string): Promise<void>;
|
|
44
|
+
export declare function setFunctionEnvBulk(apiKey: string, orgId: string, fnId: string, env: Record<string, string>): Promise<{
|
|
45
|
+
set: number;
|
|
46
|
+
}>;
|
|
43
47
|
export declare function listFunctionRuns(apiKey: string, orgId: string, fnId: string): Promise<FunctionRun[]>;
|
package/dist/function.js
CHANGED
|
@@ -7,6 +7,7 @@ exports.getFunction = getFunction;
|
|
|
7
7
|
exports.deleteFunction = deleteFunction;
|
|
8
8
|
exports.uploadBundle = uploadBundle;
|
|
9
9
|
exports.setFunctionEnv = setFunctionEnv;
|
|
10
|
+
exports.setFunctionEnvBulk = setFunctionEnvBulk;
|
|
10
11
|
exports.listFunctionRuns = listFunctionRuns;
|
|
11
12
|
const client_1 = require("./client");
|
|
12
13
|
const config_1 = require("./config");
|
|
@@ -62,6 +63,13 @@ async function uploadBundle(apiKey, orgId, fnId, bundle, filename = 'bundle.js')
|
|
|
62
63
|
async function setFunctionEnv(apiKey, orgId, fnId, name, value) {
|
|
63
64
|
return (0, client_1.request)('POST', `${config_1.FUNCTION_BASE}/function/orgs/${encodeURIComponent(orgId)}/functions/${encodeURIComponent(fnId)}/env`, apiKey, { name, value });
|
|
64
65
|
}
|
|
66
|
+
// setFunctionEnvBulk writes multiple Worker Secrets in one call. The backend
|
|
67
|
+
// (env.go) loops, calling Cloudflare once per secret, and returns `{set:N}`.
|
|
68
|
+
// The single-secret `setFunctionEnv` above stays the canonical one-off path;
|
|
69
|
+
// this is the bulk variant. The function must already be deployed.
|
|
70
|
+
async function setFunctionEnvBulk(apiKey, orgId, fnId, env) {
|
|
71
|
+
return (0, client_1.request)('POST', `${config_1.FUNCTION_BASE}/function/orgs/${encodeURIComponent(orgId)}/functions/${encodeURIComponent(fnId)}/env`, apiKey, { env });
|
|
72
|
+
}
|
|
65
73
|
// listFunctionRuns returns recent invocation records, most recent first
|
|
66
74
|
// (Story 4). Capped at 100 server-side.
|
|
67
75
|
async function listFunctionRuns(apiKey, orgId, fnId) {
|
package/dist/funnel.d.ts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -36,7 +36,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
36
36
|
};
|
|
37
37
|
})();
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.task = exports.queue = exports.git = exports.container = exports.payments = exports.fn = exports.crm = exports.database = exports.llm = exports.audience = exports.company = exports.people = exports.url = exports.workflow = exports.webhook = exports.storage = exports.pixel = exports.image = exports.funnel = exports.email = exports.domain = exports.hq = void 0;
|
|
39
|
+
exports.task = exports.queue = exports.git = exports.container = exports.payments = exports.fn = exports.crm = exports.database = exports.llm = exports.audience = exports.company = exports.people = exports.url = exports.workflow = exports.webhook = exports.storage = exports.pixel = exports.image = exports.funnel = exports.email = exports.domain = exports.auth = exports.hq = void 0;
|
|
40
40
|
__exportStar(require("./types"), exports);
|
|
41
41
|
__exportStar(require("./client"), exports);
|
|
42
42
|
// Note: config constants (STORAGE_BASE etc.) are NOT re-exported from the
|
|
@@ -46,6 +46,7 @@ __exportStar(require("./client"), exports);
|
|
|
46
46
|
// CJS-compiled SDK. If you need a base URL in a downstream package, mirror
|
|
47
47
|
// the constant locally — it's one line and the comment makes it obvious.
|
|
48
48
|
exports.hq = __importStar(require("./hq"));
|
|
49
|
+
exports.auth = __importStar(require("./auth"));
|
|
49
50
|
exports.domain = __importStar(require("./domain"));
|
|
50
51
|
exports.email = __importStar(require("./email"));
|
|
51
52
|
exports.funnel = __importStar(require("./funnel"));
|
package/dist/payments.d.ts
CHANGED
package/dist/payments.js
CHANGED
|
@@ -32,7 +32,7 @@ async function connect(apiKey, orgId, stripeSecretKey, tier = 't0') {
|
|
|
32
32
|
stripe_secret_key: stripeSecretKey,
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
|
-
// getConnect reads the org's connection status.
|
|
35
|
+
// getConnect reads the org's connection status. Returns { connected: false } when no Stripe is linked (no longer a 404).
|
|
36
36
|
// when the org has not connected Stripe.
|
|
37
37
|
async function getConnect(apiKey, orgId) {
|
|
38
38
|
return (0, client_1.request)('GET', `${config_1.PAYMENTS_BASE}/payments/orgs/${encodeURIComponent(orgId)}/connect`, apiKey);
|
package/dist/queue.d.ts
CHANGED
|
@@ -41,6 +41,7 @@ export interface EnqueueOptions {
|
|
|
41
41
|
export declare function createQueue(apiKey: string, orgId: string, opts: CreateQueueOptions): Promise<Queue>;
|
|
42
42
|
export declare function listQueues(apiKey: string, orgId: string): Promise<Queue[]>;
|
|
43
43
|
export declare function getQueue(apiKey: string, orgId: string, name: string): Promise<Queue>;
|
|
44
|
+
export declare function deleteQueue(apiKey: string, orgId: string, name: string): Promise<void>;
|
|
44
45
|
export declare function enqueueJob(apiKey: string, orgId: string, name: string, opts?: EnqueueOptions): Promise<Job>;
|
|
45
46
|
export declare function listJobs(apiKey: string, orgId: string, name: string, opts?: {
|
|
46
47
|
status?: string;
|
package/dist/queue.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.EXPOSES = void 0;
|
|
|
4
4
|
exports.createQueue = createQueue;
|
|
5
5
|
exports.listQueues = listQueues;
|
|
6
6
|
exports.getQueue = getQueue;
|
|
7
|
+
exports.deleteQueue = deleteQueue;
|
|
7
8
|
exports.enqueueJob = enqueueJob;
|
|
8
9
|
exports.listJobs = listJobs;
|
|
9
10
|
exports.getJob = getJob;
|
|
@@ -17,6 +18,7 @@ exports.EXPOSES = [
|
|
|
17
18
|
'POST /queue/orgs/{org_id}/queues',
|
|
18
19
|
'GET /queue/orgs/{org_id}/queues',
|
|
19
20
|
'GET /queue/orgs/{org_id}/queues/{name}',
|
|
21
|
+
'DELETE /queue/orgs/{org_id}/queues/{name}',
|
|
20
22
|
'POST /queue/orgs/{org_id}/queues/{name}/jobs',
|
|
21
23
|
'GET /queue/orgs/{org_id}/queues/{name}/jobs',
|
|
22
24
|
'GET /queue/orgs/{org_id}/jobs/{id}',
|
|
@@ -41,6 +43,9 @@ async function listQueues(apiKey, orgId) {
|
|
|
41
43
|
async function getQueue(apiKey, orgId, name) {
|
|
42
44
|
return (0, client_1.request)('GET', `${queuesBase(orgId)}/${encodeURIComponent(name)}`, apiKey);
|
|
43
45
|
}
|
|
46
|
+
async function deleteQueue(apiKey, orgId, name) {
|
|
47
|
+
return (0, client_1.request)('DELETE', `${queuesBase(orgId)}/${encodeURIComponent(name)}`, apiKey);
|
|
48
|
+
}
|
|
44
49
|
// enqueueJob is idempotent on (queue, dedup_key). A job with unsucceeded
|
|
45
50
|
// depends_on starts blocked.
|
|
46
51
|
async function enqueueJob(apiKey, orgId, name, opts = {}) {
|