@teamkeel/functions-runtime 0.429.1 → 0.430.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.cjs CHANGED
@@ -34,6 +34,7 @@ __export(index_exports, {
34
34
  Duration: () => Duration,
35
35
  ErrorPresets: () => ErrorPresets,
36
36
  File: () => File,
37
+ FlowsAPI: () => FlowsAPI,
37
38
  InlineFile: () => InlineFile,
38
39
  KSUID: () => import_ksuid2.default,
39
40
  ModelAPI: () => ModelAPI,
@@ -1081,8 +1082,12 @@ var opMapping = {
1081
1082
  onOrBefore: { op: "<=" },
1082
1083
  after: { op: ">" },
1083
1084
  onOrAfter: { op: ">=" },
1084
- equals: { op: import_kysely4.sql`is not distinct from` },
1085
- notEquals: { op: import_kysely4.sql`is distinct from` },
1085
+ equals: {
1086
+ op: /* @__PURE__ */ __name((v) => v === null || Array.isArray(v) ? import_kysely4.sql`is not distinct from` : "=", "op")
1087
+ },
1088
+ notEquals: {
1089
+ op: /* @__PURE__ */ __name((v) => v === null || Array.isArray(v) ? import_kysely4.sql`is distinct from` : "!=", "op")
1090
+ },
1086
1091
  equalsRelative: {
1087
1092
  op: import_kysely4.sql`BETWEEN`,
1088
1093
  value: /* @__PURE__ */ __name((v) => import_kysely4.sql`${import_kysely4.sql.raw(
@@ -1137,7 +1142,8 @@ function applyWhereConditions(context6, qb, where = {}) {
1137
1142
  }
1138
1143
  const fieldName = `${context6.tableAlias()}.${(0, import_change_case.snakeCase)(key)}`;
1139
1144
  if (Object.prototype.toString.call(v) !== "[object Object]") {
1140
- qb = qb.where(fieldName, import_kysely4.sql`is not distinct from`, import_kysely4.sql`${v}`);
1145
+ const operator = v === null || Array.isArray(v) ? import_kysely4.sql`is not distinct from` : "=";
1146
+ qb = qb.where(fieldName, operator, import_kysely4.sql`${v}`);
1141
1147
  continue;
1142
1148
  }
1143
1149
  for (const op of Object.keys(v)) {
@@ -1154,9 +1160,10 @@ function applyWhereConditions(context6, qb, where = {}) {
1154
1160
  );
1155
1161
  }
1156
1162
  } else {
1163
+ const operator = typeof mapping.op === "function" ? mapping.op(v[op]) : mapping.op;
1157
1164
  qb = qb.where(
1158
1165
  fieldName,
1159
- mapping.op,
1166
+ operator,
1160
1167
  mapping.value ? mapping.value(v[op]) : import_kysely4.sql`${v[op]}`
1161
1168
  );
1162
1169
  }
@@ -2089,6 +2096,294 @@ var TaskAPI = class _TaskAPI {
2089
2096
  }
2090
2097
  };
2091
2098
 
2099
+ // src/FlowsAPI.js
2100
+ var import_jsonwebtoken2 = __toESM(require("jsonwebtoken"), 1);
2101
+ function buildHeaders2(identity, authToken) {
2102
+ const headers = { "Content-Type": "application/json" };
2103
+ if (identity !== null) {
2104
+ const base64pk = process.env.KEEL_PRIVATE_KEY;
2105
+ let privateKey = void 0;
2106
+ if (base64pk) {
2107
+ privateKey = Buffer.from(base64pk, "base64").toString("utf8");
2108
+ }
2109
+ headers["Authorization"] = "Bearer " + import_jsonwebtoken2.default.sign({}, privateKey, {
2110
+ algorithm: privateKey ? "RS256" : "none",
2111
+ expiresIn: 60 * 60 * 24,
2112
+ subject: identity.id,
2113
+ issuer: "https://keel.so"
2114
+ });
2115
+ }
2116
+ if (authToken !== null) {
2117
+ headers["Authorization"] = "Bearer " + authToken;
2118
+ }
2119
+ return headers;
2120
+ }
2121
+ __name(buildHeaders2, "buildHeaders");
2122
+ function getApiUrl2() {
2123
+ const apiUrl = process.env.KEEL_API_URL;
2124
+ if (!apiUrl) {
2125
+ throw new Error("KEEL_API_URL environment variable is not set");
2126
+ }
2127
+ return apiUrl;
2128
+ }
2129
+ __name(getApiUrl2, "getApiUrl");
2130
+ var FlowRun = class _FlowRun {
2131
+ static {
2132
+ __name(this, "FlowRun");
2133
+ }
2134
+ /**
2135
+ * @param {Object} data The flow run data from the API
2136
+ * @param {string} flowName The name of the flow
2137
+ * @param {Object|null} identity Optional identity object for authentication
2138
+ * @param {string|null} authToken Optional auth token for authentication
2139
+ */
2140
+ constructor(data, flowName, identity = null, authToken = null) {
2141
+ this.id = data.id;
2142
+ this.name = data.name;
2143
+ this.status = data.status;
2144
+ this.inputs = data.inputs;
2145
+ this.outputs = data.outputs;
2146
+ this.steps = data.steps;
2147
+ this.pendingStep = data.pendingStep;
2148
+ this.createdAt = data.createdAt ? new Date(data.createdAt) : void 0;
2149
+ this.updatedAt = data.updatedAt ? new Date(data.updatedAt) : void 0;
2150
+ this.completedAt = data.completedAt ? new Date(data.completedAt) : void 0;
2151
+ this._flowName = flowName;
2152
+ this._identity = identity;
2153
+ this._authToken = authToken;
2154
+ }
2155
+ /**
2156
+ * Returns a new FlowRun instance that will use the given identity for authentication.
2157
+ * @param {Object} identity The identity object
2158
+ * @returns {FlowRun} A new FlowRun instance with the identity set
2159
+ */
2160
+ withIdentity(identity) {
2161
+ const data = this._toApiData();
2162
+ return new _FlowRun(data, this._flowName, identity, null);
2163
+ }
2164
+ /**
2165
+ * Returns a new FlowRun instance that will use the given auth token for authentication.
2166
+ * @param {string} token The auth token to use
2167
+ * @returns {FlowRun} A new FlowRun instance with the auth token set
2168
+ */
2169
+ withAuthToken(token) {
2170
+ const data = this._toApiData();
2171
+ return new _FlowRun(data, this._flowName, null, token);
2172
+ }
2173
+ /**
2174
+ * Converts the flow run back to API data format for creating new instances.
2175
+ * @returns {Object} The flow run data in API format
2176
+ */
2177
+ _toApiData() {
2178
+ return {
2179
+ id: this.id,
2180
+ name: this.name,
2181
+ status: this.status,
2182
+ inputs: this.inputs,
2183
+ outputs: this.outputs,
2184
+ steps: this.steps,
2185
+ pendingStep: this.pendingStep,
2186
+ createdAt: this.createdAt?.toISOString(),
2187
+ updatedAt: this.updatedAt?.toISOString(),
2188
+ completedAt: this.completedAt?.toISOString()
2189
+ };
2190
+ }
2191
+ /**
2192
+ * Refreshes the flow run state from the API.
2193
+ * @returns {Promise<FlowRun>} The updated flow run
2194
+ */
2195
+ async refresh() {
2196
+ const name = spanNameForModelAPI(this._flowName, "refresh");
2197
+ return withSpan(name, async () => {
2198
+ const apiUrl = getApiUrl2();
2199
+ const url = `${apiUrl}/flows/json/${this._flowName}/${this.id}`;
2200
+ const response = await fetch(url, {
2201
+ method: "GET",
2202
+ headers: buildHeaders2(this._identity, this._authToken)
2203
+ });
2204
+ if (!response.ok) {
2205
+ const errorBody = await response.json().catch(() => ({}));
2206
+ throw new Error(
2207
+ `Failed to refresh flow run: ${response.status} ${response.statusText} - ${errorBody.message || JSON.stringify(errorBody)}`
2208
+ );
2209
+ }
2210
+ const result = await response.json();
2211
+ return new _FlowRun(
2212
+ result,
2213
+ this._flowName,
2214
+ this._identity,
2215
+ this._authToken
2216
+ );
2217
+ });
2218
+ }
2219
+ /**
2220
+ * Cancels the flow run.
2221
+ * @returns {Promise<FlowRun>} The updated flow run
2222
+ */
2223
+ async cancel() {
2224
+ const name = spanNameForModelAPI(this._flowName, "cancel");
2225
+ return withSpan(name, async () => {
2226
+ const apiUrl = getApiUrl2();
2227
+ const url = `${apiUrl}/flows/json/${this._flowName}/${this.id}/cancel`;
2228
+ const response = await fetch(url, {
2229
+ method: "POST",
2230
+ headers: buildHeaders2(this._identity, this._authToken)
2231
+ });
2232
+ if (!response.ok) {
2233
+ const errorBody = await response.json().catch(() => ({}));
2234
+ throw new Error(
2235
+ `Failed to cancel flow run: ${response.status} ${response.statusText} - ${errorBody.message || JSON.stringify(errorBody)}`
2236
+ );
2237
+ }
2238
+ const result = await response.json();
2239
+ return new _FlowRun(
2240
+ result,
2241
+ this._flowName,
2242
+ this._identity,
2243
+ this._authToken
2244
+ );
2245
+ });
2246
+ }
2247
+ };
2248
+ var FlowsAPI = class _FlowsAPI {
2249
+ static {
2250
+ __name(this, "FlowsAPI");
2251
+ }
2252
+ /**
2253
+ * @param {string} flowName The name of the flow
2254
+ * @param {Object|null} identity Optional identity object for authentication
2255
+ * @param {string|null} authToken Optional auth token for authentication
2256
+ */
2257
+ constructor(flowName, identity = null, authToken = null) {
2258
+ this._flowName = flowName;
2259
+ this._identity = identity;
2260
+ this._authToken = authToken;
2261
+ }
2262
+ /**
2263
+ * Returns a new FlowsAPI instance that will use the given identity for authentication.
2264
+ * @param {Object} identity The identity object
2265
+ * @returns {FlowsAPI} A new FlowsAPI instance with the identity set
2266
+ */
2267
+ withIdentity(identity) {
2268
+ return new _FlowsAPI(this._flowName, identity, null);
2269
+ }
2270
+ /**
2271
+ * Returns a new FlowsAPI instance that will use the given auth token for authentication.
2272
+ * @param {string} token The auth token to use
2273
+ * @returns {FlowsAPI} A new FlowsAPI instance with the auth token set
2274
+ */
2275
+ withAuthToken(token) {
2276
+ return new _FlowsAPI(this._flowName, null, token);
2277
+ }
2278
+ /**
2279
+ * Starts a new flow run with the given inputs.
2280
+ * @param {Object} inputs The flow input data
2281
+ * @returns {Promise<FlowRun>} The created flow run
2282
+ */
2283
+ async start(inputs = {}) {
2284
+ const name = spanNameForModelAPI(this._flowName, "start");
2285
+ return withSpan(name, async () => {
2286
+ const apiUrl = getApiUrl2();
2287
+ const url = `${apiUrl}/flows/json/${this._flowName}`;
2288
+ const response = await fetch(url, {
2289
+ method: "POST",
2290
+ headers: buildHeaders2(this._identity, this._authToken),
2291
+ body: JSON.stringify(inputs)
2292
+ });
2293
+ if (!response.ok) {
2294
+ const errorBody = await response.json().catch(() => ({}));
2295
+ throw new Error(
2296
+ `Failed to start flow: ${response.status} ${response.statusText} - ${errorBody.message || JSON.stringify(errorBody)}`
2297
+ );
2298
+ }
2299
+ const result = await response.json();
2300
+ return new FlowRun(
2301
+ result,
2302
+ this._flowName,
2303
+ this._identity,
2304
+ this._authToken
2305
+ );
2306
+ });
2307
+ }
2308
+ /**
2309
+ * Gets a flow run by ID.
2310
+ * @param {string} runId The flow run ID
2311
+ * @returns {Promise<FlowRun>} The flow run
2312
+ */
2313
+ async get(runId) {
2314
+ const name = spanNameForModelAPI(this._flowName, "get");
2315
+ return withSpan(name, async () => {
2316
+ const apiUrl = getApiUrl2();
2317
+ const url = `${apiUrl}/flows/json/${this._flowName}/${runId}`;
2318
+ const response = await fetch(url, {
2319
+ method: "GET",
2320
+ headers: buildHeaders2(this._identity, this._authToken)
2321
+ });
2322
+ if (!response.ok) {
2323
+ const errorBody = await response.json().catch(() => ({}));
2324
+ throw new Error(
2325
+ `Failed to get flow run: ${response.status} ${response.statusText} - ${errorBody.message || JSON.stringify(errorBody)}`
2326
+ );
2327
+ }
2328
+ const result = await response.json();
2329
+ return new FlowRun(
2330
+ result,
2331
+ this._flowName,
2332
+ this._identity,
2333
+ this._authToken
2334
+ );
2335
+ });
2336
+ }
2337
+ /**
2338
+ * Lists flow runs for this flow.
2339
+ * @param {Object} options Optional pagination options
2340
+ * @param {number} options.limit Maximum number of runs to return
2341
+ * @param {number} options.offset Offset for pagination
2342
+ * @returns {Promise<{results: FlowRun[], pageInfo: Object}>} List of flow runs with pagination info
2343
+ */
2344
+ async list(options = {}) {
2345
+ const name = spanNameForModelAPI(this._flowName, "list");
2346
+ return withSpan(name, async () => {
2347
+ const apiUrl = getApiUrl2();
2348
+ const params = new URLSearchParams();
2349
+ if (options.limit) params.set("limit", options.limit.toString());
2350
+ if (options.offset) params.set("offset", options.offset.toString());
2351
+ const url = `${apiUrl}/flows/json/${this._flowName}${params.toString() ? "?" + params.toString() : ""}`;
2352
+ const response = await fetch(url, {
2353
+ method: "GET",
2354
+ headers: buildHeaders2(this._identity, this._authToken)
2355
+ });
2356
+ if (!response.ok) {
2357
+ const errorBody = await response.json().catch(() => ({}));
2358
+ throw new Error(
2359
+ `Failed to list flow runs: ${response.status} ${response.statusText} - ${errorBody.message || JSON.stringify(errorBody)}`
2360
+ );
2361
+ }
2362
+ const result = await response.json();
2363
+ if (Array.isArray(result)) {
2364
+ return {
2365
+ results: result.map(
2366
+ (run) => new FlowRun(run, this._flowName, this._identity, this._authToken)
2367
+ ),
2368
+ pageInfo: {
2369
+ totalCount: result.length,
2370
+ hasNextPage: false
2371
+ }
2372
+ };
2373
+ }
2374
+ return {
2375
+ results: (result.results || []).map(
2376
+ (run) => new FlowRun(run, this._flowName, this._identity, this._authToken)
2377
+ ),
2378
+ pageInfo: result.pageInfo || {
2379
+ totalCount: (result.results || []).length,
2380
+ hasNextPage: false
2381
+ }
2382
+ };
2383
+ });
2384
+ }
2385
+ };
2386
+
2092
2387
  // src/RequestHeaders.ts
2093
2388
  var RequestHeaders = class {
2094
2389
  /**
@@ -2262,6 +2557,9 @@ __name(tryExecuteFunction, "tryExecuteFunction");
2262
2557
  // src/handleRequest.js
2263
2558
  var opentelemetry2 = __toESM(require("@opentelemetry/api"), 1);
2264
2559
  async function handleRequest(request, config) {
2560
+ if (request.method === "__ping") {
2561
+ return (0, import_json_rpc_22.createJSONRPCSuccessResponse)(request.id, { status: "ok" });
2562
+ }
2265
2563
  const activeContext = opentelemetry2.propagation.extract(
2266
2564
  opentelemetry2.context.active(),
2267
2565
  request.meta?.tracing
@@ -3869,6 +4167,7 @@ __name(ksuid, "ksuid");
3869
4167
  Duration,
3870
4168
  ErrorPresets,
3871
4169
  File,
4170
+ FlowsAPI,
3872
4171
  InlineFile,
3873
4172
  KSUID,
3874
4173
  ModelAPI,