@teamkeel/functions-runtime 0.453.0 → 0.454.3

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
@@ -47,6 +47,7 @@ __export(index_exports, {
47
47
  RetryConstant: () => RetryConstant,
48
48
  STEP_STATUS: () => STEP_STATUS,
49
49
  STEP_TYPE: () => STEP_TYPE,
50
+ Signature: () => Signature,
50
51
  TaskAPI: () => TaskAPI,
51
52
  checkBuiltInPermissions: () => checkBuiltInPermissions,
52
53
  createFlowContext: () => createFlowContext,
@@ -587,9 +588,9 @@ var InstrumentedClient = class extends import_pg.Client {
587
588
  }
588
589
  async query(...args) {
589
590
  const _super = super.query.bind(this);
590
- const sql5 = args[0];
591
+ const sql4 = args[0];
591
592
  let sqlAttribute = false;
592
- let spanName = txStatements[sql5.toLowerCase()];
593
+ let spanName = txStatements[sql4.toLowerCase()];
593
594
  if (!spanName) {
594
595
  spanName = "Database Query";
595
596
  sqlAttribute = true;
@@ -657,9 +658,9 @@ function getDialect(connString) {
657
658
  pool.on("connect", (client) => {
658
659
  const originalQuery = client.query;
659
660
  client.query = function(...args) {
660
- const sql5 = args[0];
661
+ const sql4 = args[0];
661
662
  let sqlAttribute = false;
662
- let spanName = txStatements[sql5.toLowerCase()];
663
+ let spanName = txStatements[sql4.toLowerCase()];
663
664
  if (!spanName) {
664
665
  spanName = "Database Query";
665
666
  sqlAttribute = true;
@@ -1150,23 +1151,23 @@ var TimePeriod = class _TimePeriod {
1150
1151
  return new _TimePeriod(period, value, offset, complete2);
1151
1152
  }
1152
1153
  periodStartSQL() {
1153
- let sql5 = "NOW()";
1154
+ let sql4 = "NOW()";
1154
1155
  if (this.offset !== 0) {
1155
- sql5 = `${sql5} + INTERVAL '${this.offset} ${this.period}'`;
1156
+ sql4 = `${sql4} + INTERVAL '${this.offset} ${this.period}'`;
1156
1157
  }
1157
1158
  if (this.complete) {
1158
- sql5 = `DATE_TRUNC('${this.period}', ${sql5})`;
1159
+ sql4 = `DATE_TRUNC('${this.period}', ${sql4})`;
1159
1160
  } else {
1160
- sql5 = `(${sql5})`;
1161
+ sql4 = `(${sql4})`;
1161
1162
  }
1162
- return sql5;
1163
+ return sql4;
1163
1164
  }
1164
1165
  periodEndSQL() {
1165
- let sql5 = this.periodStartSQL();
1166
+ let sql4 = this.periodStartSQL();
1166
1167
  if (this.value != 0) {
1167
- sql5 = `(${sql5} + INTERVAL '${this.value} ${this.period}')`;
1168
+ sql4 = `(${sql4} + INTERVAL '${this.value} ${this.period}')`;
1168
1169
  }
1169
- return sql5;
1170
+ return sql4;
1170
1171
  }
1171
1172
  };
1172
1173
 
@@ -3319,28 +3320,46 @@ var import_json_rpc_26 = require("json-rpc-2.0");
3319
3320
  var opentelemetry6 = __toESM(require("@opentelemetry/api"), 1);
3320
3321
 
3321
3322
  // src/tryExecuteFlow.js
3322
- var import_kysely6 = require("kysely");
3323
3323
  function tryExecuteFlow(db, request, cb) {
3324
- return withDatabase(db, false, async ({ sDb }) => {
3325
- const runId = request?.meta?.runId;
3326
- if (runId && sDb) {
3327
- await import_kysely6.sql`SELECT pg_advisory_lock(hashtextextended(${runId}, 0))`.execute(
3328
- sDb
3329
- );
3330
- }
3331
- try {
3332
- return await withAuditContext(request, async () => {
3333
- return cb();
3334
- });
3335
- } finally {
3336
- if (runId && sDb) {
3337
- await import_kysely6.sql`SELECT pg_advisory_unlock(hashtextextended(${runId}, 0))`.execute(sDb).catch(() => void 0);
3338
- }
3339
- }
3324
+ return withDatabase(db, false, async () => {
3325
+ return withAuditContext(request, async () => {
3326
+ return cb();
3327
+ });
3340
3328
  });
3341
3329
  }
3342
3330
  __name(tryExecuteFlow, "tryExecuteFlow");
3343
3331
 
3332
+ // src/flows/ui/elements/input/signature.ts
3333
+ var Signature = class {
3334
+ static {
3335
+ __name(this, "Signature");
3336
+ }
3337
+ constructor(data) {
3338
+ this.svg = data.svg;
3339
+ this.signedAt = data.signedAt;
3340
+ }
3341
+ async toPngDataURL() {
3342
+ const sharp = (await import("sharp")).default;
3343
+ const png = await sharp(Buffer.from(this.svg), { density: 300 }).png().toBuffer();
3344
+ return `data:image/png;base64,${png.toString("base64")}`;
3345
+ }
3346
+ };
3347
+ var signatureInput = /* @__PURE__ */ __name((name, options) => {
3348
+ return {
3349
+ __type: "input",
3350
+ uiConfig: {
3351
+ __type: "ui.input.signature",
3352
+ name,
3353
+ label: options?.label || name,
3354
+ optional: options?.optional || false,
3355
+ disabled: options?.disabled || false,
3356
+ helpText: options?.helpText
3357
+ },
3358
+ validate: options?.validate,
3359
+ getData: /* @__PURE__ */ __name((x) => new Signature(x), "getData")
3360
+ };
3361
+ }, "signatureInput");
3362
+
3344
3363
  // src/flows/ui/elements/input/text.ts
3345
3364
  var textInput = /* @__PURE__ */ __name((name, options) => {
3346
3365
  return {
@@ -3472,6 +3491,28 @@ var selectOne = /* @__PURE__ */ __name((name, options) => {
3472
3491
  }, "selectOne");
3473
3492
 
3474
3493
  // src/flows/ui/page.ts
3494
+ async function applyElementGetData(content, data) {
3495
+ if (!data || typeof data !== "object" || !Array.isArray(content)) return data;
3496
+ for (const c of content) {
3497
+ const resolved = await c;
3498
+ if (!resolved || !("__type" in resolved)) continue;
3499
+ const name = resolved.uiConfig?.name;
3500
+ if (!name || !(name in data)) continue;
3501
+ if (resolved.__type === "input" && typeof resolved.getData === "function") {
3502
+ data[name] = resolved.getData(data[name]);
3503
+ } else if (resolved.__type === "iterator") {
3504
+ const rows = data[name];
3505
+ const inner = resolved.uiConfig?.content;
3506
+ if (Array.isArray(rows) && Array.isArray(inner)) {
3507
+ for (let i = 0; i < rows.length; i++) {
3508
+ rows[i] = await applyElementGetData(inner, rows[i]);
3509
+ }
3510
+ }
3511
+ }
3512
+ }
3513
+ return data;
3514
+ }
3515
+ __name(applyElementGetData, "applyElementGetData");
3475
3516
  async function callbackFn(elements, elementName, callbackName, data) {
3476
3517
  const element = elements.find(
3477
3518
  (el) => el.uiConfig && el.uiConfig.name === elementName
@@ -4009,23 +4050,6 @@ var imageCapture = /* @__PURE__ */ __name((name, options) => {
4009
4050
  };
4010
4051
  }, "imageCapture");
4011
4052
 
4012
- // src/flows/ui/elements/input/signature.ts
4013
- var signatureInput = /* @__PURE__ */ __name((name, options) => {
4014
- return {
4015
- __type: "input",
4016
- uiConfig: {
4017
- __type: "ui.input.signature",
4018
- name,
4019
- label: options?.label || name,
4020
- optional: options?.optional || false,
4021
- disabled: options?.disabled || false,
4022
- helpText: options?.helpText
4023
- },
4024
- validate: options?.validate,
4025
- getData: /* @__PURE__ */ __name((x) => x, "getData")
4026
- };
4027
- }, "signatureInput");
4028
-
4029
4053
  // src/flows/ui/elements/iterator.ts
4030
4054
  var iterator = /* @__PURE__ */ __name((name, options) => {
4031
4055
  return {
@@ -4364,25 +4388,35 @@ function createFlowContext(runId, data, action, callback, element, spanId, ctx)
4364
4388
  throw new Error(`Duplicate step name: ${name}`);
4365
4389
  }
4366
4390
  usedNames.add(name);
4367
- let step = await db.selectFrom("keel.flow_step").where("run_id", "=", runId).where("name", "=", name).selectAll().executeTakeFirst();
4391
+ const { step, inserted } = await db.transaction().execute(async (trx) => {
4392
+ await trx.selectFrom("keel.flow_run").select("id").where("id", "=", runId).forUpdate().executeTakeFirst();
4393
+ const existing = await trx.selectFrom("keel.flow_step").where("run_id", "=", runId).where("name", "=", name).selectAll().executeTakeFirst();
4394
+ if (existing) {
4395
+ return { step: existing, inserted: false };
4396
+ }
4397
+ const created = await trx.insertInto("keel.flow_step").values({
4398
+ run_id: runId,
4399
+ name,
4400
+ stage: options.stage,
4401
+ status: "PENDING" /* PENDING */,
4402
+ type: "UI" /* UI */,
4403
+ startTime: /* @__PURE__ */ new Date()
4404
+ }).returningAll().executeTakeFirstOrThrow();
4405
+ return { step: created, inserted: true };
4406
+ });
4368
4407
  if (step && step.status === "COMPLETED" /* COMPLETED */) {
4369
4408
  span.setAttribute(KEEL_INTERNAL_ATTR, KEEL_INTERNAL_CHILDREN);
4370
4409
  span.setAttribute("step.status", "COMPLETED" /* COMPLETED */);
4371
- const parsedData2 = transformRichDataTypes(step.value);
4410
+ const parsedData2 = await applyElementGetData(
4411
+ options.content,
4412
+ transformRichDataTypes(step.value)
4413
+ );
4372
4414
  if (step.action) {
4373
4415
  return { data: parsedData2, action: step.action };
4374
4416
  }
4375
4417
  return parsedData2;
4376
4418
  }
4377
- if (!step) {
4378
- step = await db.insertInto("keel.flow_step").values({
4379
- run_id: runId,
4380
- name,
4381
- stage: options.stage,
4382
- status: "PENDING" /* PENDING */,
4383
- type: "UI" /* UI */,
4384
- startTime: /* @__PURE__ */ new Date()
4385
- }).returningAll().executeTakeFirst();
4419
+ if (inserted) {
4386
4420
  span.setAttribute("rendered", true);
4387
4421
  span.setAttribute("step.status", "PENDING" /* PENDING */);
4388
4422
  throw new UIRenderDisrupt(
@@ -4445,7 +4479,10 @@ function createFlowContext(runId, data, action, callback, element, spanId, ctx)
4445
4479
  endTime: /* @__PURE__ */ new Date()
4446
4480
  }).where("id", "=", step.id).returningAll().executeTakeFirst();
4447
4481
  span.setAttribute("step.status", "COMPLETED" /* COMPLETED */);
4448
- const parsedData = transformRichDataTypes(data);
4482
+ const parsedData = await applyElementGetData(
4483
+ options.content,
4484
+ transformRichDataTypes(data)
4485
+ );
4449
4486
  if (action) {
4450
4487
  return { data: parsedData, action };
4451
4488
  }
@@ -4718,6 +4755,7 @@ __name(ksuid, "ksuid");
4718
4755
  RetryConstant,
4719
4756
  STEP_STATUS,
4720
4757
  STEP_TYPE,
4758
+ Signature,
4721
4759
  TaskAPI,
4722
4760
  checkBuiltInPermissions,
4723
4761
  createFlowContext,