gencow 0.1.144 → 0.1.145

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/core/index.js CHANGED
@@ -2207,10 +2207,17 @@ function createScheduler(options) {
2207
2207
  }
2208
2208
 
2209
2209
  // ../core/src/workflow.ts
2210
- import { sql as sql2 } from "drizzle-orm";
2210
+ import { sql as sql3 } from "drizzle-orm";
2211
2211
 
2212
- // ../core/src/workflows-api.ts
2212
+ // ../core/src/workflow-json.ts
2213
2213
  import { sql } from "drizzle-orm";
2214
+ function workflowJsonb(value) {
2215
+ const json = JSON.stringify(value ?? {});
2216
+ return sql`${json}::text::jsonb`;
2217
+ }
2218
+
2219
+ // ../core/src/workflows-api.ts
2220
+ import { sql as sql2 } from "drizzle-orm";
2214
2221
 
2215
2222
  // ../core/src/v.ts
2216
2223
  var GencowValidationError = class extends Error {
@@ -2419,7 +2426,7 @@ function toWorkflowStatusFilter(status) {
2419
2426
  async function ensureWorkflowRealtimeToken(db, workflowId, currentToken) {
2420
2427
  if (currentToken && currentToken.trim() !== "") return currentToken;
2421
2428
  const nextToken = createWorkflowRealtimeToken();
2422
- const updateResult = await db.execute(sql`
2429
+ const updateResult = await db.execute(sql2`
2423
2430
  UPDATE _gencow_workflows
2424
2431
  SET realtime_token = ${nextToken}
2425
2432
  WHERE id = ${workflowId}
@@ -2428,7 +2435,7 @@ async function ensureWorkflowRealtimeToken(db, workflowId, currentToken) {
2428
2435
  `);
2429
2436
  const updatedToken = rowsFromResult(updateResult)[0]?.realtime_token ?? null;
2430
2437
  if (updatedToken && updatedToken.trim() !== "") return updatedToken;
2431
- const rereadResult = await db.execute(sql`
2438
+ const rereadResult = await db.execute(sql2`
2432
2439
  SELECT realtime_token
2433
2440
  FROM _gencow_workflows
2434
2441
  WHERE id = ${workflowId}
@@ -2438,7 +2445,7 @@ async function ensureWorkflowRealtimeToken(db, workflowId, currentToken) {
2438
2445
  return rereadToken && rereadToken.trim() !== "" ? rereadToken : null;
2439
2446
  }
2440
2447
  async function loadWorkflowSignalTarget(db, workflowId) {
2441
- const result = await db.execute(sql`
2448
+ const result = await db.execute(sql2`
2442
2449
  SELECT
2443
2450
  id,
2444
2451
  name,
@@ -2460,7 +2467,7 @@ function isMissingWorkflowV2SignalSchemaError(error) {
2460
2467
  }
2461
2468
  async function tryRecordWorkflowV2Signal(options) {
2462
2469
  try {
2463
- await options.db.execute(sql`
2470
+ await options.db.execute(sql2`
2464
2471
  WITH inserted AS (
2465
2472
  INSERT INTO _gencow_workflow_signals_v2 (
2466
2473
  id,
@@ -2473,7 +2480,7 @@ async function tryRecordWorkflowV2Signal(options) {
2473
2480
  ${crypto.randomUUID()},
2474
2481
  ${options.workflowId},
2475
2482
  ${options.event},
2476
- ${JSON.stringify(options.payload)}::jsonb,
2483
+ ${workflowJsonb(options.payload)},
2477
2484
  ${crypto.randomUUID()}
2478
2485
  )
2479
2486
  RETURNING run_id
@@ -2499,7 +2506,7 @@ async function tryRecordWorkflowV2Signal(options) {
2499
2506
  }
2500
2507
  }
2501
2508
  async function loadWorkflowSnapshot(db, workflowId, options) {
2502
- const workflowResult = await db.execute(sql`
2509
+ const workflowResult = await db.execute(sql2`
2503
2510
  SELECT
2504
2511
  id,
2505
2512
  name,
@@ -2529,7 +2536,7 @@ async function loadWorkflowSnapshot(db, workflowId, options) {
2529
2536
  }
2530
2537
  const realtimeToken = await ensureWorkflowRealtimeToken(db, workflowId, row.realtime_token);
2531
2538
  if (!realtimeToken) return null;
2532
- const stepsResult = await db.execute(sql`
2539
+ const stepsResult = await db.execute(sql2`
2533
2540
  SELECT
2534
2541
  step_name,
2535
2542
  status,
@@ -2594,7 +2601,7 @@ function registerWorkflowsApi() {
2594
2601
  };
2595
2602
  }
2596
2603
  const persistedPayload = serializeWorkflowValue(args.payload);
2597
- await ctx.unsafeDb.execute(sql`
2604
+ await ctx.unsafeDb.execute(sql2`
2598
2605
  INSERT INTO _gencow_workflow_events (
2599
2606
  id,
2600
2607
  workflow_id,
@@ -2605,7 +2612,7 @@ function registerWorkflowsApi() {
2605
2612
  ${crypto.randomUUID()},
2606
2613
  ${workflow2.id},
2607
2614
  ${normalizedEvent},
2608
- ${JSON.stringify(persistedPayload)}::jsonb
2615
+ ${workflowJsonb(persistedPayload)}
2609
2616
  )
2610
2617
  `);
2611
2618
  await tryRecordWorkflowV2Signal({
@@ -2642,7 +2649,7 @@ function registerWorkflowsApi() {
2642
2649
  const limit = normalizeListLimit(args.limit);
2643
2650
  const requestedStatus = normalizeDerivedStatus(args.status);
2644
2651
  const status = toWorkflowStatusFilter(requestedStatus);
2645
- const result = status == null ? await ctx.unsafeDb.execute(sql`
2652
+ const result = status == null ? await ctx.unsafeDb.execute(sql2`
2646
2653
  SELECT
2647
2654
  id,
2648
2655
  name,
@@ -2663,7 +2670,7 @@ function registerWorkflowsApi() {
2663
2670
  WHERE user_id = ${userId}
2664
2671
  ORDER BY started_at DESC
2665
2672
  LIMIT ${limit}
2666
- `) : await ctx.unsafeDb.execute(sql`
2673
+ `) : await ctx.unsafeDb.execute(sql2`
2667
2674
  SELECT
2668
2675
  id,
2669
2676
  name,
@@ -2769,61 +2776,60 @@ function isMissingWorkflowV2SchemaError(error) {
2769
2776
  const message = error instanceof Error ? error.message : String(error);
2770
2777
  return code === "42P01" || code === "42703" || causeCode === "42P01" || causeCode === "42703" || message.includes('relation "_gencow_workflow_runs_v2" does not exist') || message.includes("relation _gencow_workflow_runs_v2 does not exist") || message.includes('relation "_gencow_workflow_outbox_v2" does not exist') || message.includes("relation _gencow_workflow_outbox_v2 does not exist") || message.includes('column "max_active_duration_ms"') || message.includes('column "retry_count"') || message.includes('column "user_id"');
2771
2778
  }
2772
- async function tryInsertWorkflowV2WakeOutbox(db, workflowId) {
2773
- try {
2774
- await db.execute(sql2`
2775
- INSERT INTO _gencow_workflow_outbox_v2 (
2776
- id,
2777
- run_id,
2778
- kind,
2779
- available_at,
2780
- status
2781
- )
2782
- VALUES (
2783
- ${`start:${workflowId}`},
2784
- ${workflowId},
2785
- 'wake_run',
2786
- NOW(),
2787
- 'pending'
2788
- )
2789
- ON CONFLICT (id) DO NOTHING
2790
- `);
2791
- } catch (error) {
2792
- if (!isMissingWorkflowV2SchemaError(error)) throw error;
2793
- }
2794
- }
2795
2779
  async function tryInsertWorkflowV2Run(options) {
2796
2780
  try {
2797
- await options.db.execute(sql2`
2798
- INSERT INTO _gencow_workflow_runs_v2 (
2799
- id,
2800
- workflow_name,
2801
- workflow_version,
2802
- args_json,
2803
- user_id,
2804
- max_active_duration_ms,
2805
- lifecycle_deadline_at,
2806
- retry_count,
2807
- max_retries,
2808
- max_attempts
2809
- )
2810
- VALUES (
2811
- ${options.workflowId},
2812
- ${options.workflowName},
2813
- ${options.workflowVersion ?? null},
2814
- ${JSON.stringify(options.args)}::jsonb,
2815
- ${options.userId},
2816
- ${options.maxActiveDurationMs},
2817
- CASE
2818
- WHEN ${options.lifecycleTimeoutMs}::bigint IS NULL THEN NULL
2819
- ELSE NOW() + (${options.lifecycleTimeoutMs}::bigint * INTERVAL '1 millisecond')
2820
- END,
2821
- 0,
2822
- ${options.maxRetries},
2823
- ${options.maxRetries + 1}
2781
+ await options.db.execute(sql3`
2782
+ WITH inserted_run AS (
2783
+ INSERT INTO _gencow_workflow_runs_v2 (
2784
+ id,
2785
+ workflow_name,
2786
+ workflow_version,
2787
+ args_json,
2788
+ user_id,
2789
+ max_active_duration_ms,
2790
+ lifecycle_deadline_at,
2791
+ retry_count,
2792
+ max_retries,
2793
+ max_attempts
2794
+ )
2795
+ VALUES (
2796
+ ${options.workflowId},
2797
+ ${options.workflowName},
2798
+ ${options.workflowVersion ?? null},
2799
+ ${workflowJsonb(options.args)},
2800
+ ${options.userId},
2801
+ ${options.maxActiveDurationMs},
2802
+ CASE
2803
+ WHEN ${options.lifecycleTimeoutMs}::bigint IS NULL THEN NULL
2804
+ ELSE NOW() + (${options.lifecycleTimeoutMs}::bigint * INTERVAL '1 millisecond')
2805
+ END,
2806
+ 0,
2807
+ ${options.maxRetries},
2808
+ ${options.maxRetries + 1}
2809
+ )
2810
+ RETURNING id
2811
+ ),
2812
+ inserted_outbox AS (
2813
+ INSERT INTO _gencow_workflow_outbox_v2 (
2814
+ id,
2815
+ run_id,
2816
+ kind,
2817
+ available_at,
2818
+ status
2819
+ )
2820
+ SELECT
2821
+ 'start:' || inserted_run.id,
2822
+ inserted_run.id,
2823
+ 'wake_run',
2824
+ NOW(),
2825
+ 'pending'
2826
+ FROM inserted_run
2827
+ ON CONFLICT (id) DO NOTHING
2828
+ RETURNING id
2824
2829
  )
2830
+ SELECT id
2831
+ FROM inserted_run
2825
2832
  `);
2826
- await tryInsertWorkflowV2WakeOutbox(options.db, options.workflowId);
2827
2833
  return true;
2828
2834
  } catch (error) {
2829
2835
  if (isMissingWorkflowV2SchemaError(error)) return false;
@@ -2832,7 +2838,7 @@ async function tryInsertWorkflowV2Run(options) {
2832
2838
  }
2833
2839
  async function tryDeleteWorkflowV2Run(db, workflowId) {
2834
2840
  try {
2835
- await db.execute(sql2`
2841
+ await db.execute(sql3`
2836
2842
  DELETE FROM _gencow_workflow_runs_v2
2837
2843
  WHERE id = ${workflowId}
2838
2844
  `);
@@ -2888,7 +2894,7 @@ function workflow(name, options) {
2888
2894
  const ownerId = ctx.auth.getUserIdentity()?.id ?? null;
2889
2895
  const persistedArgs = serializeWorkflowValue(args ?? {});
2890
2896
  const realtimeToken = createWorkflowRealtimeToken();
2891
- await ctx.unsafeDb.execute(sql2`
2897
+ await ctx.unsafeDb.execute(sql3`
2892
2898
  INSERT INTO _gencow_workflows (
2893
2899
  id,
2894
2900
  name,
@@ -2903,7 +2909,7 @@ function workflow(name, options) {
2903
2909
  VALUES (
2904
2910
  ${workflowId},
2905
2911
  ${name},
2906
- ${JSON.stringify(persistedArgs)}::jsonb,
2912
+ ${workflowJsonb(persistedArgs)},
2907
2913
  ${realtimeToken},
2908
2914
  'pending',
2909
2915
  0,
@@ -2933,7 +2939,7 @@ function workflow(name, options) {
2933
2939
  scheduledJobId
2934
2940
  };
2935
2941
  } catch (error) {
2936
- await ctx.unsafeDb.execute(sql2`
2942
+ await ctx.unsafeDb.execute(sql3`
2937
2943
  DELETE FROM _gencow_workflows
2938
2944
  WHERE id = ${workflowId}
2939
2945
  `);
@@ -3097,7 +3103,7 @@ function defineConfig(config) {
3097
3103
  }
3098
3104
 
3099
3105
  // ../core/src/rls.ts
3100
- import { sql as sql3 } from "drizzle-orm";
3106
+ import { sql as sql4 } from "drizzle-orm";
3101
3107
  import { pgPolicy } from "drizzle-orm/pg-core";
3102
3108
  var _ownerRlsRegistry = /* @__PURE__ */ new WeakMap();
3103
3109
  function getOwnerRlsMeta(table) {
@@ -3113,13 +3119,13 @@ function ownerRls(userIdColumn, options) {
3113
3119
  "[ownerRls] userIdColumn must have a .name property. Ensure you pass a valid Drizzle column reference (e.g. t.userId)."
3114
3120
  );
3115
3121
  }
3116
- const isOwner = sql3`${userIdColumn} = current_setting('app.current_user_id', true)`;
3122
+ const isOwner = sql4`${userIdColumn} = current_setting('app.current_user_id', true)`;
3117
3123
  const meta = {
3118
3124
  columnName: colName,
3119
3125
  readPublic: options?.read === "public"
3120
3126
  };
3121
3127
  const policies = [
3122
- pgPolicy("rls-select", { for: "select", using: options?.read === "public" ? sql3`true` : isOwner }),
3128
+ pgPolicy("rls-select", { for: "select", using: options?.read === "public" ? sql4`true` : isOwner }),
3123
3129
  pgPolicy("rls-insert", { for: "insert", withCheck: isOwner }),
3124
3130
  pgPolicy("rls-update", { for: "update", using: isOwner, withCheck: isOwner }),
3125
3131
  pgPolicy("rls-delete", { for: "delete", using: isOwner })
@@ -3129,7 +3135,7 @@ function ownerRls(userIdColumn, options) {
3129
3135
 
3130
3136
  // ../core/src/rls-db.ts
3131
3137
  import { AsyncLocalStorage } from "node:async_hooks";
3132
- import { sql as sql4 } from "drizzle-orm";
3138
+ import { sql as sql5 } from "drizzle-orm";
3133
3139
  var gucNameRe = /^app\.[a-z][a-z0-9_]*(?:\.[a-z][a-z0-9_]*)*$/;
3134
3140
  var RESERVED_VARS_KEYS = /* @__PURE__ */ new Set(["app.current_user_id", "app.current_user_role", "app.tenant_id"]);
3135
3141
  function assertSafeGucName(key) {
@@ -3189,7 +3195,7 @@ async function applyRlsSessionVars(client, rls) {
3189
3195
  await forEachSetConfig(rls, (name, value) => execSetConfig(client, name, value));
3190
3196
  }
3191
3197
  async function injectRlsVarsOnTx(tx, rls) {
3192
- await forEachSetConfig(rls, (name, value) => tx.execute(sql4`SELECT set_config(${name}, ${value}, true)`));
3198
+ await forEachSetConfig(rls, (name, value) => tx.execute(sql5`SELECT set_config(${name}, ${value}, true)`));
3193
3199
  }
3194
3200
  async function withRlsLeasedConnection(leased, rls, fn) {
3195
3201
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gencow",
3
- "version": "0.1.144",
3
+ "version": "0.1.145",
4
4
  "description": "Gencow — AI Backend Engine",
5
5
  "type": "module",
6
6
  "bin": {