@spooled/sdk 1.1.0 → 1.2.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/dist/{index-D_MpLQYY.d.cts → index-BzfyWvfc.d.cts} +105 -72
- package/dist/{index-D_MpLQYY.d.ts → index-BzfyWvfc.d.ts} +105 -72
- package/dist/index.cjs +179 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +179 -31
- package/dist/index.js.map +1 -1
- package/dist/worker/index.cjs +1 -1
- package/dist/worker/index.cjs.map +1 -1
- package/dist/worker/index.d.cts +1 -1
- package/dist/worker/index.d.ts +1 -1
- package/dist/worker/index.js +1 -1
- package/dist/worker/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -50,10 +50,10 @@ var DEFAULT_CONFIG = {
|
|
|
50
50
|
successThreshold: 3,
|
|
51
51
|
timeout: 3e4
|
|
52
52
|
},
|
|
53
|
-
userAgent: "@spooled/sdk-nodejs/1.
|
|
53
|
+
userAgent: "@spooled/sdk-nodejs/1.2.0",
|
|
54
54
|
autoRefreshToken: true
|
|
55
55
|
};
|
|
56
|
-
var SDK_VERSION = "1.
|
|
56
|
+
var SDK_VERSION = "1.2.0";
|
|
57
57
|
var API_VERSION = "v1";
|
|
58
58
|
var API_BASE_PATH = `/api/${API_VERSION}`;
|
|
59
59
|
function normalizeCredential(value) {
|
|
@@ -1079,21 +1079,28 @@ var AuthResource = class {
|
|
|
1079
1079
|
}
|
|
1080
1080
|
/**
|
|
1081
1081
|
* Validate a token
|
|
1082
|
+
*
|
|
1083
|
+
* POST /auth/validate is `{ valid, error?, claims? }`. Claims use `org_id`
|
|
1084
|
+
* (camelCased `orgId`), not `organizationId`. Invalid tokens send `error`,
|
|
1085
|
+
* not `message`.
|
|
1082
1086
|
*/
|
|
1083
1087
|
async validate(params) {
|
|
1084
|
-
|
|
1088
|
+
const raw = await this.http.post(
|
|
1089
|
+
"/auth/validate",
|
|
1090
|
+
params
|
|
1091
|
+
);
|
|
1092
|
+
return mapValidate(raw);
|
|
1085
1093
|
}
|
|
1086
1094
|
/**
|
|
1087
|
-
* Start email-based login flow (sends
|
|
1095
|
+
* Start email-based login flow (sends a 6-digit code)
|
|
1088
1096
|
*/
|
|
1089
1097
|
async startEmailLogin(email) {
|
|
1090
|
-
return this.http.post(
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
);
|
|
1098
|
+
return this.http.post("/auth/email/start", {
|
|
1099
|
+
email
|
|
1100
|
+
});
|
|
1094
1101
|
}
|
|
1095
1102
|
/**
|
|
1096
|
-
* Check
|
|
1103
|
+
* Check whether an email is registered (GET /auth/check-email)
|
|
1097
1104
|
*/
|
|
1098
1105
|
async checkEmail(email) {
|
|
1099
1106
|
return this.http.get("/auth/check-email", {
|
|
@@ -1101,6 +1108,23 @@ var AuthResource = class {
|
|
|
1101
1108
|
});
|
|
1102
1109
|
}
|
|
1103
1110
|
};
|
|
1111
|
+
function mapValidate(raw) {
|
|
1112
|
+
const claims = raw.claims;
|
|
1113
|
+
const organizationId = claims?.organizationId ?? claims?.orgId;
|
|
1114
|
+
return {
|
|
1115
|
+
valid: raw.valid,
|
|
1116
|
+
message: raw.message ?? raw.error,
|
|
1117
|
+
error: raw.error ?? raw.message,
|
|
1118
|
+
claims: claims ? {
|
|
1119
|
+
organizationId: organizationId ?? "",
|
|
1120
|
+
orgId: claims.orgId ?? organizationId,
|
|
1121
|
+
apiKeyId: claims.apiKeyId ?? "",
|
|
1122
|
+
queues: claims.queues ?? [],
|
|
1123
|
+
exp: claims.exp ?? 0,
|
|
1124
|
+
iat: claims.iat ?? 0
|
|
1125
|
+
} : void 0
|
|
1126
|
+
};
|
|
1127
|
+
}
|
|
1104
1128
|
|
|
1105
1129
|
// src/resources/jobs.ts
|
|
1106
1130
|
var JobsResource = class {
|
|
@@ -1131,15 +1155,20 @@ var JobsResource = class {
|
|
|
1131
1155
|
* List jobs with optional filtering
|
|
1132
1156
|
*/
|
|
1133
1157
|
async list(params) {
|
|
1134
|
-
|
|
1158
|
+
const rows = await this.http.get("/jobs", {
|
|
1135
1159
|
params
|
|
1136
1160
|
});
|
|
1161
|
+
return rows.map((row) => ({
|
|
1162
|
+
...row,
|
|
1163
|
+
jobType: row.jobType ?? jobTypeFromPayload(row)
|
|
1164
|
+
}));
|
|
1137
1165
|
}
|
|
1138
1166
|
/**
|
|
1139
1167
|
* Get a job by ID
|
|
1140
1168
|
*/
|
|
1141
1169
|
async get(id) {
|
|
1142
|
-
|
|
1170
|
+
const job = await this.http.get(`/jobs/${id}`);
|
|
1171
|
+
return withJobType(job);
|
|
1143
1172
|
}
|
|
1144
1173
|
/**
|
|
1145
1174
|
* Cancel a pending or scheduled job
|
|
@@ -1151,7 +1180,8 @@ var JobsResource = class {
|
|
|
1151
1180
|
* Retry a failed or dead-lettered job
|
|
1152
1181
|
*/
|
|
1153
1182
|
async retry(id) {
|
|
1154
|
-
|
|
1183
|
+
const job = await this.http.post(`/jobs/${id}/retry`);
|
|
1184
|
+
return withJobType(job);
|
|
1155
1185
|
}
|
|
1156
1186
|
/**
|
|
1157
1187
|
* Boost job priority
|
|
@@ -1220,9 +1250,13 @@ var JobsResource = class {
|
|
|
1220
1250
|
}
|
|
1221
1251
|
// DLQ operations (private implementations)
|
|
1222
1252
|
async listDlq(params) {
|
|
1223
|
-
|
|
1253
|
+
const rows = await this.http.get("/jobs/dlq", {
|
|
1224
1254
|
params
|
|
1225
1255
|
});
|
|
1256
|
+
return rows.map((row) => ({
|
|
1257
|
+
...row,
|
|
1258
|
+
jobType: row.jobType ?? jobTypeFromPayload(row)
|
|
1259
|
+
}));
|
|
1226
1260
|
}
|
|
1227
1261
|
async retryDlq(params) {
|
|
1228
1262
|
return this.http.post("/jobs/dlq/retry", params);
|
|
@@ -1231,6 +1265,28 @@ var JobsResource = class {
|
|
|
1231
1265
|
return this.http.post("/jobs/dlq/purge", params);
|
|
1232
1266
|
}
|
|
1233
1267
|
};
|
|
1268
|
+
function withJobType(job) {
|
|
1269
|
+
return {
|
|
1270
|
+
...job,
|
|
1271
|
+
jobType: job.jobType ?? jobTypeFromPayload(job) ?? void 0
|
|
1272
|
+
};
|
|
1273
|
+
}
|
|
1274
|
+
function jobTypeFromPayload(row) {
|
|
1275
|
+
if (typeof row.jobType === "string" && row.jobType !== "") {
|
|
1276
|
+
return row.jobType;
|
|
1277
|
+
}
|
|
1278
|
+
const payload = row.payload;
|
|
1279
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
1280
|
+
return void 0;
|
|
1281
|
+
}
|
|
1282
|
+
const rec = payload;
|
|
1283
|
+
for (const value of [rec.jobType, rec.job_type]) {
|
|
1284
|
+
if (typeof value === "string" && value !== "") {
|
|
1285
|
+
return value;
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
return void 0;
|
|
1289
|
+
}
|
|
1234
1290
|
|
|
1235
1291
|
// src/resources/queues.ts
|
|
1236
1292
|
var QueuesResource = class {
|
|
@@ -1425,7 +1481,8 @@ var WorkflowsResource = class {
|
|
|
1425
1481
|
* Get a workflow by ID
|
|
1426
1482
|
*/
|
|
1427
1483
|
async get(id) {
|
|
1428
|
-
|
|
1484
|
+
const raw = await this.http.get(`/workflows/${id}`);
|
|
1485
|
+
return mapWorkflowGetResponse(raw);
|
|
1429
1486
|
}
|
|
1430
1487
|
/**
|
|
1431
1488
|
* Cancel a workflow
|
|
@@ -1443,27 +1500,104 @@ var WorkflowsResource = class {
|
|
|
1443
1500
|
return this.http.post(`/workflows/${id}/retry`);
|
|
1444
1501
|
}
|
|
1445
1502
|
// Workflow job operations (private implementations)
|
|
1503
|
+
//
|
|
1504
|
+
// The backend has no /workflows/{id}/jobs routes. Job rows and dependency
|
|
1505
|
+
// edges are on GET /workflows/{id} (WorkflowDetailResponse).
|
|
1446
1506
|
async listWorkflowJobs(workflowId) {
|
|
1447
|
-
|
|
1507
|
+
const detail = await this.http.get(
|
|
1508
|
+
`/workflows/${workflowId}`
|
|
1509
|
+
);
|
|
1510
|
+
return mapWorkflowDetailJobs(detail);
|
|
1448
1511
|
}
|
|
1449
1512
|
async getWorkflowJob(workflowId, jobId) {
|
|
1450
|
-
|
|
1513
|
+
const jobs = await this.listWorkflowJobs(workflowId);
|
|
1514
|
+
const job = jobs.find((item) => item.id === jobId);
|
|
1515
|
+
if (!job) {
|
|
1516
|
+
throw new NotFoundError(
|
|
1517
|
+
`Job ${jobId} not found in workflow ${workflowId}`
|
|
1518
|
+
);
|
|
1519
|
+
}
|
|
1520
|
+
return job;
|
|
1451
1521
|
}
|
|
1452
1522
|
async getWorkflowJobsStatus(workflowId) {
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1523
|
+
const jobs = await this.listWorkflowJobs(workflowId);
|
|
1524
|
+
return jobs.map((job) => ({
|
|
1525
|
+
jobId: job.id,
|
|
1526
|
+
key: job.key,
|
|
1527
|
+
status: job.status
|
|
1528
|
+
}));
|
|
1456
1529
|
}
|
|
1457
1530
|
async getJobDependencies(jobId) {
|
|
1458
1531
|
return this.http.get(`/jobs/${jobId}/dependencies`);
|
|
1459
1532
|
}
|
|
1460
1533
|
async addJobDependencies(jobId, params) {
|
|
1461
|
-
|
|
1534
|
+
const dependsOn = params.dependsOn ?? params.dependsOnJobIds ?? [];
|
|
1535
|
+
const mode = params.dependencyMode ?? (params.dependencyType === "any" || params.dependencyType === "all" ? params.dependencyType : void 0);
|
|
1536
|
+
const raw = await this.http.post(
|
|
1462
1537
|
`/jobs/${jobId}/dependencies`,
|
|
1463
|
-
|
|
1538
|
+
{
|
|
1539
|
+
depends_on: dependsOn,
|
|
1540
|
+
...mode ? { dependency_mode: mode } : {}
|
|
1541
|
+
},
|
|
1542
|
+
{ skipRequestConversion: true }
|
|
1464
1543
|
);
|
|
1544
|
+
return {
|
|
1545
|
+
added: raw.dependenciesAdded ?? 0,
|
|
1546
|
+
dependenciesMet: raw.dependenciesMet ?? false,
|
|
1547
|
+
dependencies: []
|
|
1548
|
+
};
|
|
1465
1549
|
}
|
|
1466
1550
|
};
|
|
1551
|
+
function mapWorkflowGetResponse(raw) {
|
|
1552
|
+
const totalJobs = raw.totalJobs ?? raw.progress?.total ?? 0;
|
|
1553
|
+
const completedJobs = raw.completedJobs ?? raw.progress?.completed ?? 0;
|
|
1554
|
+
const failedJobs = raw.failedJobs ?? raw.progress?.failed ?? 0;
|
|
1555
|
+
const progressPercent = raw.progressPercent ?? (totalJobs > 0 ? completedJobs / totalJobs * 100 : 0);
|
|
1556
|
+
return {
|
|
1557
|
+
id: String(raw.id ?? ""),
|
|
1558
|
+
name: String(raw.name ?? ""),
|
|
1559
|
+
status: raw.status ?? "pending",
|
|
1560
|
+
totalJobs,
|
|
1561
|
+
completedJobs,
|
|
1562
|
+
failedJobs,
|
|
1563
|
+
progressPercent,
|
|
1564
|
+
createdAt: String(raw.createdAt ?? ""),
|
|
1565
|
+
completedAt: raw.completedAt
|
|
1566
|
+
};
|
|
1567
|
+
}
|
|
1568
|
+
function mapWorkflowDetailJobs(detail) {
|
|
1569
|
+
const workflowId = String(detail.id ?? "");
|
|
1570
|
+
const deps = detail.dependencies ?? [];
|
|
1571
|
+
return (detail.jobs ?? []).map((job) => {
|
|
1572
|
+
const id = String(job.id ?? "");
|
|
1573
|
+
const timeoutMs = typeof job.timeoutMs === "number" ? job.timeoutMs : void 0;
|
|
1574
|
+
const errorObj = job.error;
|
|
1575
|
+
let error;
|
|
1576
|
+
if (typeof errorObj === "string") {
|
|
1577
|
+
error = errorObj;
|
|
1578
|
+
} else if (errorObj && typeof errorObj === "object" && "message" in errorObj) {
|
|
1579
|
+
error = String(errorObj.message);
|
|
1580
|
+
}
|
|
1581
|
+
return {
|
|
1582
|
+
id,
|
|
1583
|
+
workflowId: String(job.workflowId ?? workflowId),
|
|
1584
|
+
key: String(job.key ?? ""),
|
|
1585
|
+
queueName: String(job.queueName ?? job.queue ?? ""),
|
|
1586
|
+
status: job.status,
|
|
1587
|
+
payload: job.payload ?? {},
|
|
1588
|
+
result: job.result ?? void 0,
|
|
1589
|
+
error,
|
|
1590
|
+
dependsOn: deps.filter((dep) => dep.childJobId === id).map((dep) => String(dep.parentJobId ?? "")),
|
|
1591
|
+
priority: Number(job.priority ?? 0),
|
|
1592
|
+
maxRetries: Number(job.maxRetries ?? 0),
|
|
1593
|
+
attempt: Number(job.attempt ?? 0),
|
|
1594
|
+
timeoutSeconds: timeoutMs != null ? Math.max(1, Math.floor(timeoutMs / 1e3)) : void 0,
|
|
1595
|
+
createdAt: String(job.createdAt ?? ""),
|
|
1596
|
+
startedAt: job.startedAt ?? void 0,
|
|
1597
|
+
completedAt: job.completedAt ?? void 0
|
|
1598
|
+
};
|
|
1599
|
+
});
|
|
1600
|
+
}
|
|
1467
1601
|
|
|
1468
1602
|
// src/resources/webhooks.ts
|
|
1469
1603
|
var WebhooksResource = class {
|
|
@@ -1632,8 +1766,8 @@ var OrganizationsResource = class {
|
|
|
1632
1766
|
*
|
|
1633
1767
|
* @example
|
|
1634
1768
|
* ```typescript
|
|
1635
|
-
* const {
|
|
1636
|
-
* console.log('Webhook token:',
|
|
1769
|
+
* const { webhookToken, webhookUrl } = await client.organizations.getWebhookToken();
|
|
1770
|
+
* console.log('Webhook token:', webhookToken);
|
|
1637
1771
|
* ```
|
|
1638
1772
|
*/
|
|
1639
1773
|
async getWebhookToken() {
|
|
@@ -1647,7 +1781,7 @@ var OrganizationsResource = class {
|
|
|
1647
1781
|
*
|
|
1648
1782
|
* @example
|
|
1649
1783
|
* ```typescript
|
|
1650
|
-
* const {
|
|
1784
|
+
* const { webhookToken: newToken } = await client.organizations.regenerateWebhookToken();
|
|
1651
1785
|
* console.log('New webhook token:', newToken);
|
|
1652
1786
|
* ```
|
|
1653
1787
|
*/
|
|
@@ -1659,8 +1793,9 @@ var OrganizationsResource = class {
|
|
|
1659
1793
|
/**
|
|
1660
1794
|
* Clear/delete the webhook token for the current organization.
|
|
1661
1795
|
*
|
|
1662
|
-
*
|
|
1663
|
-
*
|
|
1796
|
+
* POST /organizations/webhook-token/clear requires `{ confirm: true }`.
|
|
1797
|
+
* An empty body 422s. The API currently rejects the operation and tells
|
|
1798
|
+
* callers to use regenerateWebhookToken() instead.
|
|
1664
1799
|
*
|
|
1665
1800
|
* @example
|
|
1666
1801
|
* ```typescript
|
|
@@ -1668,7 +1803,9 @@ var OrganizationsResource = class {
|
|
|
1668
1803
|
* ```
|
|
1669
1804
|
*/
|
|
1670
1805
|
async clearWebhookToken() {
|
|
1671
|
-
await this.http.post("/organizations/webhook-token/clear"
|
|
1806
|
+
await this.http.post("/organizations/webhook-token/clear", {
|
|
1807
|
+
confirm: true
|
|
1808
|
+
});
|
|
1672
1809
|
}
|
|
1673
1810
|
};
|
|
1674
1811
|
|
|
@@ -1965,16 +2102,27 @@ var WebhookIngestionResource = class {
|
|
|
1965
2102
|
/**
|
|
1966
2103
|
* Ingest a custom webhook.
|
|
1967
2104
|
*
|
|
1968
|
-
* POST /api/v1/webhooks/{org_id}/custom
|
|
2105
|
+
* POST /api/v1/webhooks/{org_id}/custom returns `{ jobId, queueName, status }`.
|
|
2106
|
+
* An older empty 200 maps to an empty object rather than throwing.
|
|
1969
2107
|
*/
|
|
1970
2108
|
async custom(orgId, params, opts) {
|
|
1971
2109
|
const headers = {
|
|
1972
2110
|
...opts?.webhookToken ? { "X-Webhook-Token": opts.webhookToken } : {},
|
|
1973
2111
|
...opts?.forwardedProto ? { "X-Forwarded-Proto": opts.forwardedProto } : {}
|
|
1974
2112
|
};
|
|
1975
|
-
await this.http.post(
|
|
1976
|
-
|
|
1977
|
-
|
|
2113
|
+
const raw = await this.http.post(
|
|
2114
|
+
`/webhooks/${orgId}/custom`,
|
|
2115
|
+
params,
|
|
2116
|
+
{ headers }
|
|
2117
|
+
);
|
|
2118
|
+
if (!raw || typeof raw === "string") {
|
|
2119
|
+
return {};
|
|
2120
|
+
}
|
|
2121
|
+
return {
|
|
2122
|
+
jobId: raw.jobId,
|
|
2123
|
+
queueName: raw.queueName,
|
|
2124
|
+
status: raw.status
|
|
2125
|
+
};
|
|
1978
2126
|
}
|
|
1979
2127
|
};
|
|
1980
2128
|
|