gencow 0.1.143 → 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
@@ -1374,6 +1374,11 @@ var require_node_cron = __commonJS({
1374
1374
  }
1375
1375
  });
1376
1376
 
1377
+ // ../core/src/context.ts
1378
+ function defineApi(api) {
1379
+ return api;
1380
+ }
1381
+
1377
1382
  // ../core/src/document-types.ts
1378
1383
  function normalizeCachePart(value) {
1379
1384
  return value.trim() || "unknown";
@@ -1841,6 +1846,166 @@ function getRegisteredMutations() {
1841
1846
  return [...mutationRegistry];
1842
1847
  }
1843
1848
 
1849
+ // ../core/src/procedure.ts
1850
+ function hasStandardSchema(schema) {
1851
+ return !!schema && typeof schema === "object" && "~standard" in schema && !!schema["~standard"] && typeof schema["~standard"].validate === "function";
1852
+ }
1853
+ async function validateWithSchema(schema, value) {
1854
+ if (!schema) return value;
1855
+ if (hasStandardSchema(schema)) {
1856
+ const result = await schema["~standard"].validate(value);
1857
+ if ("issues" in result && result.issues.length > 0) {
1858
+ throw new Error(result.issues[0]?.message ?? "Validation failed");
1859
+ }
1860
+ if ("value" in result) {
1861
+ return result.value;
1862
+ }
1863
+ throw new Error("Validation failed");
1864
+ }
1865
+ throw new Error("procQuery/procMutation only supports Standard Schema v1 validators");
1866
+ }
1867
+ function composeMiddlewares(middlewares, handler, inputSchema, outputSchema, inputValidationIndex, outputValidationIndex) {
1868
+ return async (initialContext, initialInput) => {
1869
+ let idx = -1;
1870
+ const boundedInputValidationIndex = Math.min(Math.max(0, inputValidationIndex), middlewares.length);
1871
+ const boundedOutputValidationIndex = Math.min(Math.max(0, outputValidationIndex), middlewares.length);
1872
+ const run = async (currentIdx, context, input) => {
1873
+ if (currentIdx <= idx) {
1874
+ throw new Error("next() called multiple times in the same middleware");
1875
+ }
1876
+ idx = currentIdx;
1877
+ let currentInput = input;
1878
+ if (currentIdx === boundedInputValidationIndex) {
1879
+ currentInput = await validateWithSchema(inputSchema, currentInput);
1880
+ }
1881
+ if (currentIdx === middlewares.length) {
1882
+ const output2 = await handler({ context, input: currentInput });
1883
+ if (currentIdx === boundedOutputValidationIndex) {
1884
+ return await validateWithSchema(outputSchema, output2);
1885
+ }
1886
+ return output2;
1887
+ }
1888
+ const middleware = middlewares[currentIdx];
1889
+ const output = await middleware({
1890
+ context,
1891
+ input: currentInput,
1892
+ next: async (overrides) => {
1893
+ return await run(
1894
+ currentIdx + 1,
1895
+ overrides?.context ?? context,
1896
+ overrides?.input ?? currentInput
1897
+ );
1898
+ }
1899
+ });
1900
+ if (currentIdx === boundedOutputValidationIndex) {
1901
+ return await validateWithSchema(outputSchema, output);
1902
+ }
1903
+ return output;
1904
+ };
1905
+ return await run(0, initialContext, initialInput);
1906
+ };
1907
+ }
1908
+ var GencowProcedureBuilderImpl = class _GencowProcedureBuilderImpl {
1909
+ constructor(kind, procedureName, middlewares = [], inputSchema, outputSchema, inputValidationIndex = -1, outputValidationIndex = -1, isPublic = false) {
1910
+ this.kind = kind;
1911
+ this.procedureName = procedureName;
1912
+ this.middlewares = middlewares;
1913
+ this.inputSchema = inputSchema;
1914
+ this.outputSchema = outputSchema;
1915
+ this.inputValidationIndex = inputValidationIndex;
1916
+ this.outputValidationIndex = outputValidationIndex;
1917
+ this.isPublic = isPublic;
1918
+ }
1919
+ name(name) {
1920
+ return new _GencowProcedureBuilderImpl(
1921
+ this.kind,
1922
+ name,
1923
+ this.middlewares,
1924
+ this.inputSchema,
1925
+ this.outputSchema,
1926
+ this.inputValidationIndex,
1927
+ this.outputValidationIndex,
1928
+ this.isPublic
1929
+ );
1930
+ }
1931
+ allowPublic() {
1932
+ return new _GencowProcedureBuilderImpl(
1933
+ this.kind,
1934
+ this.procedureName,
1935
+ this.middlewares,
1936
+ this.inputSchema,
1937
+ this.outputSchema,
1938
+ this.inputValidationIndex,
1939
+ this.outputValidationIndex,
1940
+ true
1941
+ );
1942
+ }
1943
+ use(middleware) {
1944
+ return new _GencowProcedureBuilderImpl(
1945
+ this.kind,
1946
+ this.procedureName,
1947
+ [...this.middlewares, middleware],
1948
+ this.inputSchema,
1949
+ this.outputSchema,
1950
+ this.inputValidationIndex,
1951
+ this.outputValidationIndex,
1952
+ this.isPublic
1953
+ );
1954
+ }
1955
+ input(schema) {
1956
+ const nextInputValidationIndex = this.middlewares.length < 0 ? 0 : this.middlewares.length;
1957
+ return new _GencowProcedureBuilderImpl(
1958
+ this.kind,
1959
+ this.procedureName,
1960
+ this.middlewares,
1961
+ schema,
1962
+ this.outputSchema,
1963
+ nextInputValidationIndex,
1964
+ this.outputValidationIndex,
1965
+ this.isPublic
1966
+ );
1967
+ }
1968
+ output(schema) {
1969
+ const nextOutputValidationIndex = this.middlewares.length < 0 ? 0 : this.middlewares.length;
1970
+ return new _GencowProcedureBuilderImpl(
1971
+ this.kind,
1972
+ this.procedureName,
1973
+ this.middlewares,
1974
+ this.inputSchema,
1975
+ schema,
1976
+ this.inputValidationIndex,
1977
+ nextOutputValidationIndex,
1978
+ this.isPublic
1979
+ );
1980
+ }
1981
+ handler(handler) {
1982
+ if (!this.procedureName) {
1983
+ throw new Error("Procedure name is required. Call .name(...) before .handler(...)");
1984
+ }
1985
+ const run = composeMiddlewares(
1986
+ this.middlewares,
1987
+ handler,
1988
+ this.inputSchema,
1989
+ this.outputSchema,
1990
+ this.inputValidationIndex,
1991
+ this.outputValidationIndex
1992
+ );
1993
+ return {
1994
+ kind: this.kind,
1995
+ name: this.procedureName,
1996
+ isPublic: this.isPublic,
1997
+ middlewares: [...this.middlewares],
1998
+ inputSchema: this.inputSchema,
1999
+ outputSchema: this.outputSchema,
2000
+ inputValidationIndex: this.inputValidationIndex,
2001
+ outputValidationIndex: this.outputValidationIndex,
2002
+ handler: run
2003
+ };
2004
+ }
2005
+ };
2006
+ var procQuery = new GencowProcedureBuilderImpl("query");
2007
+ var procMutation = new GencowProcedureBuilderImpl("mutation");
2008
+
1844
2009
  // ../core/src/http-action.ts
1845
2010
  if (!globalThis.__gencow_httpActionRegistry) globalThis.__gencow_httpActionRegistry = [];
1846
2011
  var httpActionRegistry = globalThis.__gencow_httpActionRegistry;
@@ -2042,10 +2207,17 @@ function createScheduler(options) {
2042
2207
  }
2043
2208
 
2044
2209
  // ../core/src/workflow.ts
2045
- import { sql as sql2 } from "drizzle-orm";
2210
+ import { sql as sql3 } from "drizzle-orm";
2046
2211
 
2047
- // ../core/src/workflows-api.ts
2212
+ // ../core/src/workflow-json.ts
2048
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";
2049
2221
 
2050
2222
  // ../core/src/v.ts
2051
2223
  var GencowValidationError = class extends Error {
@@ -2203,6 +2375,7 @@ function mapWorkflowSummary(row) {
2203
2375
  derivedStatus: deriveWorkflowStatus(row.status, row.current_step),
2204
2376
  currentStep: row.current_step,
2205
2377
  error: row.error,
2378
+ errorCode: row.error_code,
2206
2379
  retryCount: row.retry_count,
2207
2380
  maxRetries: row.max_retries,
2208
2381
  maxDurationMs: Number(row.max_duration_ms),
@@ -2253,7 +2426,7 @@ function toWorkflowStatusFilter(status) {
2253
2426
  async function ensureWorkflowRealtimeToken(db, workflowId, currentToken) {
2254
2427
  if (currentToken && currentToken.trim() !== "") return currentToken;
2255
2428
  const nextToken = createWorkflowRealtimeToken();
2256
- const updateResult = await db.execute(sql`
2429
+ const updateResult = await db.execute(sql2`
2257
2430
  UPDATE _gencow_workflows
2258
2431
  SET realtime_token = ${nextToken}
2259
2432
  WHERE id = ${workflowId}
@@ -2262,7 +2435,7 @@ async function ensureWorkflowRealtimeToken(db, workflowId, currentToken) {
2262
2435
  `);
2263
2436
  const updatedToken = rowsFromResult(updateResult)[0]?.realtime_token ?? null;
2264
2437
  if (updatedToken && updatedToken.trim() !== "") return updatedToken;
2265
- const rereadResult = await db.execute(sql`
2438
+ const rereadResult = await db.execute(sql2`
2266
2439
  SELECT realtime_token
2267
2440
  FROM _gencow_workflows
2268
2441
  WHERE id = ${workflowId}
@@ -2272,7 +2445,7 @@ async function ensureWorkflowRealtimeToken(db, workflowId, currentToken) {
2272
2445
  return rereadToken && rereadToken.trim() !== "" ? rereadToken : null;
2273
2446
  }
2274
2447
  async function loadWorkflowSignalTarget(db, workflowId) {
2275
- const result = await db.execute(sql`
2448
+ const result = await db.execute(sql2`
2276
2449
  SELECT
2277
2450
  id,
2278
2451
  name,
@@ -2282,11 +2455,58 @@ async function loadWorkflowSignalTarget(db, workflowId) {
2282
2455
  FROM _gencow_workflows
2283
2456
  WHERE id = ${workflowId}
2284
2457
  LIMIT 1
2285
- `);
2458
+ `);
2286
2459
  return rowsFromResult(result)[0] ?? null;
2287
2460
  }
2461
+ function isMissingWorkflowV2SignalSchemaError(error) {
2462
+ const code = error && typeof error === "object" && "code" in error ? String(error.code) : "";
2463
+ const cause = error && typeof error === "object" && "cause" in error ? error.cause : null;
2464
+ const causeCode = cause && typeof cause === "object" && "code" in cause ? String(cause.code) : "";
2465
+ const message = error instanceof Error ? error.message : String(error);
2466
+ return code === "42P01" || code === "42703" || causeCode === "42P01" || causeCode === "42703" || (code === "23503" || causeCode === "23503") && message.includes("_gencow_workflow_signals_v2") || message.includes('relation "_gencow_workflow_signals_v2" does not exist') || message.includes("relation _gencow_workflow_signals_v2 does not exist") || message.includes('relation "_gencow_workflow_runs_v2" does not exist') || message.includes("relation _gencow_workflow_runs_v2 does not exist");
2467
+ }
2468
+ async function tryRecordWorkflowV2Signal(options) {
2469
+ try {
2470
+ await options.db.execute(sql2`
2471
+ WITH inserted AS (
2472
+ INSERT INTO _gencow_workflow_signals_v2 (
2473
+ id,
2474
+ run_id,
2475
+ event_name,
2476
+ payload_json,
2477
+ idempotency_key
2478
+ )
2479
+ VALUES (
2480
+ ${crypto.randomUUID()},
2481
+ ${options.workflowId},
2482
+ ${options.event},
2483
+ ${workflowJsonb(options.payload)},
2484
+ ${crypto.randomUUID()}
2485
+ )
2486
+ RETURNING run_id
2487
+ )
2488
+ UPDATE _gencow_workflow_runs_v2 run
2489
+ SET
2490
+ status = 'queued',
2491
+ runnable_at = NOW(),
2492
+ lease_owner = NULL,
2493
+ lease_expires_at = NULL,
2494
+ heartbeat_at = NULL,
2495
+ updated_at = NOW()
2496
+ FROM inserted
2497
+ WHERE run.id = inserted.run_id
2498
+ AND run.status = 'waiting'
2499
+ AND run.completed_at IS NULL
2500
+ AND run.cancel_requested_at IS NULL
2501
+ `);
2502
+ return true;
2503
+ } catch (error) {
2504
+ if (isMissingWorkflowV2SignalSchemaError(error)) return false;
2505
+ throw error;
2506
+ }
2507
+ }
2288
2508
  async function loadWorkflowSnapshot(db, workflowId, options) {
2289
- const workflowResult = await db.execute(sql`
2509
+ const workflowResult = await db.execute(sql2`
2290
2510
  SELECT
2291
2511
  id,
2292
2512
  name,
@@ -2295,6 +2515,7 @@ async function loadWorkflowSnapshot(db, workflowId, options) {
2295
2515
  current_step,
2296
2516
  result,
2297
2517
  error,
2518
+ error_code,
2298
2519
  retry_count,
2299
2520
  max_retries,
2300
2521
  max_duration_ms,
@@ -2315,7 +2536,7 @@ async function loadWorkflowSnapshot(db, workflowId, options) {
2315
2536
  }
2316
2537
  const realtimeToken = await ensureWorkflowRealtimeToken(db, workflowId, row.realtime_token);
2317
2538
  if (!realtimeToken) return null;
2318
- const stepsResult = await db.execute(sql`
2539
+ const stepsResult = await db.execute(sql2`
2319
2540
  SELECT
2320
2541
  step_name,
2321
2542
  status,
@@ -2380,7 +2601,7 @@ function registerWorkflowsApi() {
2380
2601
  };
2381
2602
  }
2382
2603
  const persistedPayload = serializeWorkflowValue(args.payload);
2383
- await ctx.unsafeDb.execute(sql`
2604
+ await ctx.unsafeDb.execute(sql2`
2384
2605
  INSERT INTO _gencow_workflow_events (
2385
2606
  id,
2386
2607
  workflow_id,
@@ -2391,9 +2612,15 @@ function registerWorkflowsApi() {
2391
2612
  ${crypto.randomUUID()},
2392
2613
  ${workflow2.id},
2393
2614
  ${normalizedEvent},
2394
- ${JSON.stringify(persistedPayload)}::jsonb
2615
+ ${workflowJsonb(persistedPayload)}
2395
2616
  )
2396
2617
  `);
2618
+ await tryRecordWorkflowV2Signal({
2619
+ db: ctx.unsafeDb,
2620
+ workflowId: workflow2.id,
2621
+ event: normalizedEvent,
2622
+ payload: persistedPayload
2623
+ });
2397
2624
  let scheduledJobId = null;
2398
2625
  if (workflow2.status === "pending" && workflow2.current_step?.startsWith("wait:")) {
2399
2626
  try {
@@ -2422,7 +2649,7 @@ function registerWorkflowsApi() {
2422
2649
  const limit = normalizeListLimit(args.limit);
2423
2650
  const requestedStatus = normalizeDerivedStatus(args.status);
2424
2651
  const status = toWorkflowStatusFilter(requestedStatus);
2425
- const result = status == null ? await ctx.unsafeDb.execute(sql`
2652
+ const result = status == null ? await ctx.unsafeDb.execute(sql2`
2426
2653
  SELECT
2427
2654
  id,
2428
2655
  name,
@@ -2431,6 +2658,7 @@ function registerWorkflowsApi() {
2431
2658
  current_step,
2432
2659
  result,
2433
2660
  error,
2661
+ error_code,
2434
2662
  retry_count,
2435
2663
  max_retries,
2436
2664
  max_duration_ms,
@@ -2442,7 +2670,7 @@ function registerWorkflowsApi() {
2442
2670
  WHERE user_id = ${userId}
2443
2671
  ORDER BY started_at DESC
2444
2672
  LIMIT ${limit}
2445
- `) : await ctx.unsafeDb.execute(sql`
2673
+ `) : await ctx.unsafeDb.execute(sql2`
2446
2674
  SELECT
2447
2675
  id,
2448
2676
  name,
@@ -2451,6 +2679,7 @@ function registerWorkflowsApi() {
2451
2679
  current_step,
2452
2680
  result,
2453
2681
  error,
2682
+ error_code,
2454
2683
  retry_count,
2455
2684
  max_retries,
2456
2685
  max_duration_ms,
@@ -2526,9 +2755,96 @@ function parseWorkflowDurationMs(raw, label = "workflow duration") {
2526
2755
  }
2527
2756
  return parseDurationString(raw, label);
2528
2757
  }
2529
- function normalizeMaxDurationMs(maxDuration) {
2758
+ function normalizeMaxDurationMs(maxDuration, label = "workflow() maxDuration") {
2530
2759
  if (maxDuration == null) return DEFAULT_WORKFLOW_MAX_DURATION_MS;
2531
- return parseWorkflowDurationMs(maxDuration, "workflow() maxDuration");
2760
+ return parseWorkflowDurationMs(maxDuration, label);
2761
+ }
2762
+ function normalizeOptionalDurationMs(duration, label) {
2763
+ return duration == null ? null : parseWorkflowDurationMs(duration, label);
2764
+ }
2765
+ function normalizeConcurrency(concurrency) {
2766
+ if (concurrency == null) return null;
2767
+ if (!Number.isFinite(concurrency) || concurrency <= 0) {
2768
+ throw new Error(`workflow() concurrency must be a positive finite number, got "${concurrency}"`);
2769
+ }
2770
+ return Math.floor(concurrency);
2771
+ }
2772
+ function isMissingWorkflowV2SchemaError(error) {
2773
+ const code = error && typeof error === "object" && "code" in error ? String(error.code) : "";
2774
+ const cause = error && typeof error === "object" && "cause" in error ? error.cause : null;
2775
+ const causeCode = cause && typeof cause === "object" && "code" in cause ? String(cause.code) : "";
2776
+ const message = error instanceof Error ? error.message : String(error);
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"');
2778
+ }
2779
+ async function tryInsertWorkflowV2Run(options) {
2780
+ try {
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
2829
+ )
2830
+ SELECT id
2831
+ FROM inserted_run
2832
+ `);
2833
+ return true;
2834
+ } catch (error) {
2835
+ if (isMissingWorkflowV2SchemaError(error)) return false;
2836
+ throw error;
2837
+ }
2838
+ }
2839
+ async function tryDeleteWorkflowV2Run(db, workflowId) {
2840
+ try {
2841
+ await db.execute(sql3`
2842
+ DELETE FROM _gencow_workflow_runs_v2
2843
+ WHERE id = ${workflowId}
2844
+ `);
2845
+ } catch (error) {
2846
+ if (!isMissingWorkflowV2SchemaError(error)) throw error;
2847
+ }
2532
2848
  }
2533
2849
  function getWorkflowResumeActionName(name) {
2534
2850
  return `${WORKFLOW_RESUME_ACTION_PREFIX}.${name}`;
@@ -2547,13 +2863,24 @@ function getRegisteredWorkflows() {
2547
2863
  }
2548
2864
  function workflow(name, options) {
2549
2865
  registerWorkflowsApi();
2550
- const maxDurationMs = normalizeMaxDurationMs(options.maxDuration);
2866
+ const maxActiveDurationMs = normalizeMaxDurationMs(
2867
+ options.maxActiveDuration ?? options.maxDuration,
2868
+ options.maxActiveDuration == null ? "workflow() maxDuration" : "workflow() maxActiveDuration"
2869
+ );
2870
+ const lifecycleTimeoutMs = normalizeOptionalDurationMs(
2871
+ options.lifecycleTimeout,
2872
+ "workflow() lifecycleTimeout"
2873
+ );
2551
2874
  const maxRetries = clampRetries(options.retries);
2552
2875
  const def = {
2553
2876
  name,
2554
2877
  argsSchema: options.args,
2555
2878
  isPublic: options.public === true,
2556
- maxDurationMs,
2879
+ version: options.version,
2880
+ maxDurationMs: maxActiveDurationMs,
2881
+ maxActiveDurationMs,
2882
+ lifecycleTimeoutMs,
2883
+ concurrency: normalizeConcurrency(options.concurrency),
2557
2884
  maxRetries,
2558
2885
  handler: options.handler
2559
2886
  };
@@ -2567,7 +2894,7 @@ function workflow(name, options) {
2567
2894
  const ownerId = ctx.auth.getUserIdentity()?.id ?? null;
2568
2895
  const persistedArgs = serializeWorkflowValue(args ?? {});
2569
2896
  const realtimeToken = createWorkflowRealtimeToken();
2570
- await ctx.unsafeDb.execute(sql2`
2897
+ await ctx.unsafeDb.execute(sql3`
2571
2898
  INSERT INTO _gencow_workflows (
2572
2899
  id,
2573
2900
  name,
@@ -2582,16 +2909,28 @@ function workflow(name, options) {
2582
2909
  VALUES (
2583
2910
  ${workflowId},
2584
2911
  ${name},
2585
- ${JSON.stringify(persistedArgs)}::jsonb,
2586
- ${realtimeToken},
2587
- 'pending',
2588
- 0,
2589
- ${maxRetries},
2590
- ${maxDurationMs},
2591
- ${ownerId}
2912
+ ${workflowJsonb(persistedArgs)},
2913
+ ${realtimeToken},
2914
+ 'pending',
2915
+ 0,
2916
+ ${maxRetries},
2917
+ ${maxActiveDurationMs},
2918
+ ${ownerId}
2592
2919
  )
2593
2920
  `);
2921
+ let insertedWorkflowV2 = false;
2594
2922
  try {
2923
+ insertedWorkflowV2 = await tryInsertWorkflowV2Run({
2924
+ db: ctx.unsafeDb,
2925
+ workflowId,
2926
+ workflowName: name,
2927
+ workflowVersion: options.version ?? null,
2928
+ args: persistedArgs,
2929
+ userId: ownerId,
2930
+ maxActiveDurationMs,
2931
+ lifecycleTimeoutMs,
2932
+ maxRetries
2933
+ });
2595
2934
  const scheduledJobId = ctx.scheduler.runAfter(0, resumeAction, { workflowId });
2596
2935
  return {
2597
2936
  id: workflowId,
@@ -2600,10 +2939,13 @@ function workflow(name, options) {
2600
2939
  scheduledJobId
2601
2940
  };
2602
2941
  } catch (error) {
2603
- await ctx.unsafeDb.execute(sql2`
2942
+ await ctx.unsafeDb.execute(sql3`
2604
2943
  DELETE FROM _gencow_workflows
2605
2944
  WHERE id = ${workflowId}
2606
2945
  `);
2946
+ if (insertedWorkflowV2) {
2947
+ await tryDeleteWorkflowV2Run(ctx.unsafeDb, workflowId);
2948
+ }
2607
2949
  throw error;
2608
2950
  }
2609
2951
  }
@@ -2761,7 +3103,7 @@ function defineConfig(config) {
2761
3103
  }
2762
3104
 
2763
3105
  // ../core/src/rls.ts
2764
- import { sql as sql3 } from "drizzle-orm";
3106
+ import { sql as sql4 } from "drizzle-orm";
2765
3107
  import { pgPolicy } from "drizzle-orm/pg-core";
2766
3108
  var _ownerRlsRegistry = /* @__PURE__ */ new WeakMap();
2767
3109
  function getOwnerRlsMeta(table) {
@@ -2777,13 +3119,13 @@ function ownerRls(userIdColumn, options) {
2777
3119
  "[ownerRls] userIdColumn must have a .name property. Ensure you pass a valid Drizzle column reference (e.g. t.userId)."
2778
3120
  );
2779
3121
  }
2780
- const isOwner = sql3`${userIdColumn} = current_setting('app.current_user_id', true)`;
3122
+ const isOwner = sql4`${userIdColumn} = current_setting('app.current_user_id', true)`;
2781
3123
  const meta = {
2782
3124
  columnName: colName,
2783
3125
  readPublic: options?.read === "public"
2784
3126
  };
2785
3127
  const policies = [
2786
- 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 }),
2787
3129
  pgPolicy("rls-insert", { for: "insert", withCheck: isOwner }),
2788
3130
  pgPolicy("rls-update", { for: "update", using: isOwner, withCheck: isOwner }),
2789
3131
  pgPolicy("rls-delete", { for: "delete", using: isOwner })
@@ -2793,7 +3135,7 @@ function ownerRls(userIdColumn, options) {
2793
3135
 
2794
3136
  // ../core/src/rls-db.ts
2795
3137
  import { AsyncLocalStorage } from "node:async_hooks";
2796
- import { sql as sql4 } from "drizzle-orm";
3138
+ import { sql as sql5 } from "drizzle-orm";
2797
3139
  var gucNameRe = /^app\.[a-z][a-z0-9_]*(?:\.[a-z][a-z0-9_]*)*$/;
2798
3140
  var RESERVED_VARS_KEYS = /* @__PURE__ */ new Set(["app.current_user_id", "app.current_user_role", "app.tenant_id"]);
2799
3141
  function assertSafeGucName(key) {
@@ -2853,7 +3195,7 @@ async function applyRlsSessionVars(client, rls) {
2853
3195
  await forEachSetConfig(rls, (name, value) => execSetConfig(client, name, value));
2854
3196
  }
2855
3197
  async function injectRlsVarsOnTx(tx, rls) {
2856
- 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)`));
2857
3199
  }
2858
3200
  async function withRlsLeasedConnection(leased, rls, fn) {
2859
3201
  try {
@@ -3393,6 +3735,7 @@ export {
3393
3735
  createWorkflowRealtimeToken,
3394
3736
  cronJobs,
3395
3737
  crud,
3738
+ defineApi,
3396
3739
  defineAuth,
3397
3740
  defineConfig,
3398
3741
  deregisterClient,
@@ -3424,6 +3767,8 @@ export {
3424
3767
  parseArgs,
3425
3768
  parseFilterNode,
3426
3769
  parseWorkflowDurationMs,
3770
+ procMutation,
3771
+ procQuery,
3427
3772
  query,
3428
3773
  ragChunks,
3429
3774
  ragCorpora,