cvx-kit 0.1.0 → 0.1.2

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.
Files changed (45) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/README.md +6 -0
  3. package/dist/auth.d.mts +16 -0
  4. package/dist/auth.mjs +1 -1
  5. package/dist/auth.mjs.map +1 -1
  6. package/dist/components/approvals/_generated/api.d.mts +2 -0
  7. package/dist/components/approvals/_generated/api.mjs.map +1 -1
  8. package/dist/components/approvals/_generated/component.d.mts +7 -0
  9. package/dist/components/approvals/_generated/dataModel.d.mts +1 -1
  10. package/dist/components/approvals/audit.mjs +1 -1
  11. package/dist/components/approvals/client.d.mts +4 -4
  12. package/dist/components/approvals/client.mjs +1 -1
  13. package/dist/components/approvals/client.mjs.map +1 -1
  14. package/dist/components/approvals/constants.d.mts +8 -2
  15. package/dist/components/approvals/constants.mjs +1 -1
  16. package/dist/components/approvals/constants.mjs.map +1 -1
  17. package/dist/components/approvals/decisions.mjs +1 -1
  18. package/dist/components/approvals/decisions.mjs.map +1 -1
  19. package/dist/components/approvals/health.d.mts +15 -0
  20. package/dist/components/approvals/health.mjs +2 -0
  21. package/dist/components/approvals/health.mjs.map +1 -0
  22. package/dist/components/approvals/requests.mjs +1 -1
  23. package/dist/components/approvals/requests.mjs.map +1 -1
  24. package/dist/components/approvals/schema.js +1 -0
  25. package/dist/components/approvals/validators.d.mts +119 -2
  26. package/dist/components/approvals/validators.mjs +1 -1
  27. package/dist/components/approvals/validators.mjs.map +1 -1
  28. package/dist/components/approvals/workflow_steps.d.mts +2 -25
  29. package/dist/components/approvals/workflow_steps.mjs.map +1 -1
  30. package/dist/components/foundation/_generated/dataModel.d.mts +1 -1
  31. package/dist/components/foundation/{schema.mjs → schema.js} +0 -1
  32. package/docs/approvals.md +50 -2
  33. package/docs/auth.md +49 -0
  34. package/docs/llms.md +1 -0
  35. package/docs/plans/2026-08-21-0930-feat-resolve-organization-hook-plan.md +178 -0
  36. package/docs/upgrading.md +23 -0
  37. package/package.json +5 -2
  38. package/scripts/convex-config-bridge.mjs +41 -3
  39. package/scripts/smoke-packed-components.mjs +374 -0
  40. package/src/test.ts +2 -2
  41. package/dist/components/approvals/schema.mjs +0 -2
  42. package/dist/components/approvals/schema.mjs.map +0 -1
  43. package/dist/components/foundation/schema.mjs.map +0 -1
  44. /package/dist/components/approvals/{schema.d.mts → schema.d.ts} +0 -0
  45. /package/dist/components/foundation/{schema.d.mts → schema.d.ts} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"decisions.mjs","names":[],"sources":["../../../src/components/approvals/decisions.ts"],"sourcesContent":["import { WorkflowManager, type WorkflowId } from '@convex-dev/workflow'\nimport { zodToConvex } from 'convex-helpers/server/zod4'\nimport { v } from 'convex/values'\n\nimport { components, internal } from './_generated/api'\nimport {\n\tinternalMutation,\n\tinternalQuery,\n\tmutation,\n\tquery,\n\ttype QueryCtx,\n} from './_generated/server'\nimport { logApprovalTransition } from './audit'\nimport {\n\tAPPROVAL_DECISIONS,\n\tAPPROVAL_RUN_STATES,\n\ttype ApprovalRunState,\n} from './constants'\nimport { canTransitionApprovalRun, classifyPendingRunAt } from './functions'\nimport { approvalActor, approvalDecision, approvalReason } from './validators'\nimport {\n\tapprovalDecisionEventName,\n\tevaluateDecisionOutcome,\n} from './workflow_steps'\n\nexport const decide = mutation({\n\targs: {\n\t\trunId: v.id('approvalRuns'),\n\t\tdecision: zodToConvex(approvalDecision),\n\t\treason: v.optional(zodToConvex(approvalReason)),\n\t\tactor: zodToConvex(approvalActor),\n\t\tcompatibilityKey: v.string(),\n\t},\n\treturns: v.object({\n\t\tstate: v.union(\n\t\t\tv.literal(APPROVAL_RUN_STATES[0]),\n\t\t\tv.literal(APPROVAL_RUN_STATES[1]),\n\t\t\tv.literal(APPROVAL_RUN_STATES[2]),\n\t\t\tv.literal(APPROVAL_RUN_STATES[3]),\n\t\t\tv.literal(APPROVAL_RUN_STATES[4]),\n\t\t),\n\t}),\n\thandler: async (ctx, input) => {\n\t\tconst run = await ctx.db.get(input.runId)\n\t\tif (!run) throw new Error('Approval request not found')\n\t\tassertCompatible(run.workflow.compatibilityKey, input.compatibilityKey)\n\t\tconst step = run.workflow.steps.find(\n\t\t\t(candidate) =>\n\t\t\t\tcandidate.kind === 'decision' && candidate.key === run.currentStepKey,\n\t\t)\n\t\tif (!step || step.kind !== 'decision')\n\t\t\tthrow new Error('Approval request is not waiting for a decision')\n\n\t\tconst prior = await ctx.db\n\t\t\t.query('approvalDecisions')\n\t\t\t.withIndex('by_runId_and_stepKey_and_actor_actorRef', (query) =>\n\t\t\t\tquery\n\t\t\t\t\t.eq('runId', run._id)\n\t\t\t\t\t.eq('stepKey', step.key)\n\t\t\t\t\t.eq('actor.actorRef', input.actor.actorRef),\n\t\t\t)\n\t\t\t.unique()\n\t\tif (prior) {\n\t\t\tif (prior.decision !== input.decision)\n\t\t\t\tthrow new Error('Actor already submitted a contradictory decision')\n\t\t\treturn {\n\t\t\t\tstate: run.state as 'pending' | 'approved' | 'rejected' | 'expired',\n\t\t\t}\n\t\t}\n\t\tif (run.state !== 'pending')\n\t\t\tthrow new Error(`Approval request is already ${run.state}`)\n\t\tif (\n\t\t\trun.expiresAt !== undefined &&\n\t\t\tclassifyPendingRunAt(Date.now(), run.expiresAt) === 'expired'\n\t\t)\n\t\t\treturn claimExpiry(ctx, run, step.key)\n\t\tif (!step.decisions.includes(input.decision))\n\t\t\tthrow new Error('Decision is not allowed by this workflow step')\n\t\tif (step.makerChecker && input.actor.actorRef === run.requester.actorRef)\n\t\t\tthrow new Error('Requester cannot decide this approval step')\n\n\t\tconst decidedAt = Date.now()\n\t\tawait ctx.db.insert('approvalDecisions', {\n\t\t\trunId: run._id,\n\t\t\tstepKey: step.key,\n\t\t\tactor: input.actor,\n\t\t\tdecision: input.decision,\n\t\t\t...(input.reason === undefined ? {} : { reason: input.reason }),\n\t\t\tdecidedAt,\n\t\t})\n\t\tconst evidence = await ctx.db\n\t\t\t.query('approvalDecisions')\n\t\t\t.withIndex('by_runId_and_stepKey_and_decidedAt', (query) =>\n\t\t\t\tquery.eq('runId', run._id).eq('stepKey', step.key),\n\t\t\t)\n\t\t\t.collect()\n\t\tconst outcome = evaluateDecisionOutcome(\n\t\t\tevidence.map((item) => ({\n\t\t\t\tactorRef: item.actor.actorRef,\n\t\t\t\tdecision: item.decision,\n\t\t\t})),\n\t\t\tstep.quorum.approvals,\n\t\t)\n\t\tawait logApprovalTransition(ctx, {\n\t\t\taction: `approval.decision.${input.decision}`,\n\t\t\tactorRef: input.actor.actorRef,\n\t\t\trunId: run._id,\n\t\t\tresourceType: run.resourceType,\n\t\t\tresourceRef: run.resourceRef,\n\t\t\ttransition: `${step.key}:${input.actor.actorRef}:${input.decision}`,\n\t\t})\n\t\tif (!outcome) return { state: 'pending' as const }\n\t\tconst terminal = isTerminalDecision(run, step.key, outcome)\n\t\tawait finishDecision(ctx, run, step.key, outcome, terminal, {\n\t\t\tactorRef: input.actor.actorRef,\n\t\t\tdecision: input.decision,\n\t\t\t...(input.reason === undefined ? {} : { reason: input.reason }),\n\t\t\tdecidedAt,\n\t\t})\n\t\treturn terminal ? { state: outcome } : { state: 'pending' as const }\n\t},\n})\n\nexport const list = query({\n\targs: { runId: v.id('approvalRuns') },\n\treturns: v.array(\n\t\tv.object({\n\t\t\tstepKey: v.string(),\n\t\t\tactorRef: v.string(),\n\t\t\tdecision: zodToConvex(approvalDecision),\n\t\t\treason: v.optional(zodToConvex(approvalReason)),\n\t\t\tdecidedAt: v.number(),\n\t\t}),\n\t),\n\thandler: (ctx, input) => listDecisionEvidence(ctx, input.runId),\n})\n\nexport const listForWorkflow = internalQuery({\n\targs: { runId: v.id('approvalRuns'), stepKey: v.string() },\n\treturns: v.array(\n\t\tv.object({\n\t\t\tstepKey: v.string(),\n\t\t\tactorRef: v.string(),\n\t\t\tdecision: zodToConvex(approvalDecision),\n\t\t\treason: v.optional(zodToConvex(approvalReason)),\n\t\t\tdecidedAt: v.number(),\n\t\t}),\n\t),\n\thandler: (ctx, input) =>\n\t\tlistDecisionEvidenceForStep(ctx, input.runId, input.stepKey),\n})\n\nexport const enter = internalMutation({\n\targs: {\n\t\trunId: v.id('approvalRuns'),\n\t\tstepKey: v.string(),\n\t\tworkflowId: v.string(),\n\t\texpiresAfterMs: v.optional(v.number()),\n\t},\n\treturns: v.object({\n\t\tstate: v.union(\n\t\t\tv.literal(APPROVAL_RUN_STATES[0]),\n\t\t\tv.literal(APPROVAL_RUN_STATES[1]),\n\t\t\tv.literal(APPROVAL_RUN_STATES[2]),\n\t\t\tv.literal(APPROVAL_RUN_STATES[3]),\n\t\t\tv.literal(APPROVAL_RUN_STATES[4]),\n\t\t),\n\t\texpiresAt: v.optional(v.number()),\n\t}),\n\thandler: async (ctx, input) => {\n\t\tconst run = await ctx.db.get(input.runId)\n\t\tif (!run) throw new Error('Approval request not found')\n\t\tif (run.workflowId !== input.workflowId)\n\t\t\tthrow new Error('Approval workflow linkage is incomplete')\n\t\tif (run.state !== 'pending')\n\t\t\treturn {\n\t\t\t\tstate: run.state as ApprovalRunState,\n\t\t\t\texpiresAt: run.expiresAt,\n\t\t\t}\n\t\tconst configuredExpiresAt = Number(run.metadata?.approvalExpiresAt)\n\t\tconst expiresAt = Number.isFinite(configuredExpiresAt)\n\t\t\t? configuredExpiresAt\n\t\t\t: input.expiresAfterMs === undefined\n\t\t\t\t? undefined\n\t\t\t\t: Date.now() + input.expiresAfterMs\n\t\tawait ctx.db.patch(run._id, {\n\t\t\tcurrentStepKey: input.stepKey,\n\t\t\texpiresAt,\n\t\t\tupdatedAt: Date.now(),\n\t\t})\n\t\tawait logApprovalTransition(ctx, {\n\t\t\taction: 'approval.waiting',\n\t\t\trunId: run._id,\n\t\t\tresourceType: run.resourceType,\n\t\t\tresourceRef: run.resourceRef,\n\t\t\ttransition: `${input.stepKey}:waiting`,\n\t\t})\n\t\tif (expiresAt !== undefined)\n\t\t\tawait ctx.scheduler.runAt(expiresAt, internal.decisions.expire, {\n\t\t\t\trunId: run._id,\n\t\t\t\tstepKey: input.stepKey,\n\t\t\t})\n\t\treturn {\n\t\t\tstate: 'pending' as const,\n\t\t\t...(expiresAt === undefined ? {} : { expiresAt }),\n\t\t}\n\t},\n})\n\nexport const expire = internalMutation({\n\targs: { runId: v.id('approvalRuns'), stepKey: v.string() },\n\treturns: v.object({\n\t\tstate: v.union(\n\t\t\tv.literal('missing'),\n\t\t\tv.literal(APPROVAL_RUN_STATES[0]),\n\t\t\tv.literal(APPROVAL_RUN_STATES[1]),\n\t\t\tv.literal(APPROVAL_RUN_STATES[2]),\n\t\t\tv.literal(APPROVAL_RUN_STATES[3]),\n\t\t\tv.literal(APPROVAL_RUN_STATES[4]),\n\t\t),\n\t}),\n\thandler: async (ctx, input) => {\n\t\tconst run = await ctx.db.get(input.runId)\n\t\tif (!run) return { state: 'missing' as const }\n\t\tif (\n\t\t\trun.state !== 'pending' ||\n\t\t\trun.currentStepKey !== input.stepKey ||\n\t\t\trun.expiresAt === undefined ||\n\t\t\tclassifyPendingRunAt(Date.now(), run.expiresAt) === 'pending'\n\t\t)\n\t\t\treturn { state: run.state as ApprovalRunState }\n\t\treturn claimExpiry(ctx, run, input.stepKey)\n\t},\n})\n\nconst approvalWorkflow = new WorkflowManager(components.workflow)\n\nasync function claimExpiry(\n\tctx: import('./_generated/server').MutationCtx,\n\trun: import('./_generated/dataModel').Doc<'approvalRuns'>,\n\tstepKey: string,\n): Promise<{ state: 'expired' }> {\n\tif (!canTransitionApprovalRun(run.state, 'expired'))\n\t\tthrow new Error(`Approval request cannot transition from ${run.state}`)\n\tconst now = Date.now()\n\tawait ctx.db.patch(run._id, {\n\t\tstate: 'expired',\n\t\texpiresAt: undefined,\n\t\tupdatedAt: now,\n\t\tterminalAt: now,\n\t})\n\tawait logApprovalTransition(ctx, {\n\t\taction: 'approval.expired',\n\t\trunId: run._id,\n\t\tresourceType: run.resourceType,\n\t\tresourceRef: run.resourceRef,\n\t\ttransition: `${stepKey}:expired`,\n\t})\n\tif (!run.workflowId) throw new Error('Approval workflow is not linked')\n\tawait approvalWorkflow.sendEvent(ctx, {\n\t\tworkflowId: run.workflowId as WorkflowId,\n\t\tname: approvalDecisionEventName(run._id, stepKey),\n\t\tvalidator: v.object({ outcome: v.literal(APPROVAL_RUN_STATES[3]) }),\n\t\tvalue: { outcome: 'expired' },\n\t})\n\treturn { state: 'expired' }\n}\n\nasync function finishDecision(\n\tctx: import('./_generated/server').MutationCtx,\n\trun: import('./_generated/dataModel').Doc<'approvalRuns'>,\n\tstepKey: string,\n\toutcome: 'approved' | 'rejected',\n\tterminal: boolean,\n\tterminalEvidence: {\n\t\tactorRef: string\n\t\tdecision: 'approved' | 'rejected'\n\t\treason?: string\n\t\tdecidedAt: number\n\t},\n): Promise<void> {\n\tif (terminal) {\n\t\tif (!canTransitionApprovalRun(run.state, outcome))\n\t\t\tthrow new Error(`Approval request cannot transition from ${run.state}`)\n\t\tconst now = Date.now()\n\t\tawait ctx.db.patch(run._id, {\n\t\t\tstate: outcome,\n\t\t\texpiresAt: undefined,\n\t\t\tupdatedAt: now,\n\t\t\tterminalAt: now,\n\t\t})\n\t\tawait logApprovalTransition(ctx, {\n\t\t\taction: `approval.${outcome}`,\n\t\t\trunId: run._id,\n\t\t\tresourceType: run.resourceType,\n\t\t\tresourceRef: run.resourceRef,\n\t\t\ttransition: `${stepKey}:terminal:${outcome}`,\n\t\t})\n\t}\n\tif (!run.workflowId) throw new Error('Approval workflow is not linked')\n\tawait approvalWorkflow.sendEvent(ctx, {\n\t\tworkflowId: run.workflowId as WorkflowId,\n\t\tname: approvalDecisionEventName(run._id, stepKey),\n\t\tvalidator: v.object({\n\t\t\toutcome: v.union(\n\t\t\t\tv.literal(APPROVAL_DECISIONS[0]),\n\t\t\t\tv.literal(APPROVAL_DECISIONS[1]),\n\t\t\t),\n\t\t\tterminalEvidence: v.object({\n\t\t\t\tactorRef: v.string(),\n\t\t\t\tdecision: zodToConvex(approvalDecision),\n\t\t\t\treason: v.optional(zodToConvex(approvalReason)),\n\t\t\t\tdecidedAt: v.number(),\n\t\t\t}),\n\t\t}),\n\t\tvalue: { outcome, terminalEvidence },\n\t})\n}\n\nfunction assertCompatible(actual: string, expected: string): void {\n\tif (actual !== expected)\n\t\tthrow new Error(\n\t\t\t`Approval workflow compatibility mismatch: expected ${expected}, received ${actual}`,\n\t\t)\n}\n\nasync function listDecisionEvidence(\n\tctx: QueryCtx,\n\trunId: import('./_generated/dataModel').Id<'approvalRuns'>,\n) {\n\tconst decisions = await ctx.db\n\t\t.query('approvalDecisions')\n\t\t.withIndex('by_runId_and_decidedAt', (query) => query.eq('runId', runId))\n\t\t.collect()\n\treturn decisions.map((decision) => ({\n\t\tstepKey: decision.stepKey,\n\t\tactorRef: decision.actor.actorRef,\n\t\tdecision: decision.decision,\n\t\t...(decision.reason === undefined ? {} : { reason: decision.reason }),\n\t\tdecidedAt: decision.decidedAt,\n\t}))\n}\n\nasync function listDecisionEvidenceForStep(\n\tctx: QueryCtx,\n\trunId: import('./_generated/dataModel').Id<'approvalRuns'>,\n\tstepKey: string,\n) {\n\tconst decisions = await ctx.db\n\t\t.query('approvalDecisions')\n\t\t.withIndex('by_runId_and_stepKey_and_decidedAt', (query) =>\n\t\t\tquery.eq('runId', runId).eq('stepKey', stepKey),\n\t\t)\n\t\t.collect()\n\treturn decisions.map((decision) => ({\n\t\tstepKey: decision.stepKey,\n\t\tactorRef: decision.actor.actorRef,\n\t\tdecision: decision.decision,\n\t\t...(decision.reason === undefined ? {} : { reason: decision.reason }),\n\t\tdecidedAt: decision.decidedAt,\n\t}))\n}\n\nfunction isTerminalDecision(\n\trun: import('./_generated/dataModel').Doc<'approvalRuns'>,\n\tstepKey: string,\n\toutcome: 'approved' | 'rejected',\n): boolean {\n\tif (outcome === 'rejected') return true\n\tconst currentIndex = run.workflow.steps.findIndex(\n\t\t(step) => step.kind === 'decision' && step.key === stepKey,\n\t)\n\treturn !run.workflow.steps\n\t\t.slice(currentIndex + 1)\n\t\t.some((step) => step.kind === 'decision')\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"decisions.mjs","names":[],"sources":["../../../src/components/approvals/decisions.ts"],"sourcesContent":["import { WorkflowManager, type WorkflowId } from '@convex-dev/workflow'\nimport { zodToConvex } from 'convex-helpers/server/zod4'\nimport { v } from 'convex/values'\n\nimport { components, internal } from './_generated/api'\nimport {\n\tinternalMutation,\n\tinternalQuery,\n\tmutation,\n\tquery,\n\ttype QueryCtx,\n} from './_generated/server'\nimport { logApprovalTransition } from './audit'\nimport {\n\tAPPROVAL_ACTOR_DECISION_INDEX,\n\tAPPROVAL_DECISION_HISTORY_INDEX,\n\tAPPROVAL_DECISIONS,\n\tAPPROVAL_RUN_STATES,\n\ttype ApprovalRunState,\n} from './constants'\nimport { canTransitionApprovalRun, classifyPendingRunAt } from './functions'\nimport { approvalActor, approvalDecision, approvalReason } from './validators'\nimport {\n\tapprovalDecisionEventName,\n\tevaluateDecisionOutcome,\n} from './workflow_steps'\n\nexport const decide = mutation({\n\targs: {\n\t\trunId: v.id('approvalRuns'),\n\t\tdecision: zodToConvex(approvalDecision),\n\t\treason: v.optional(zodToConvex(approvalReason)),\n\t\tactor: zodToConvex(approvalActor),\n\t\tcompatibilityKey: v.string(),\n\t},\n\treturns: v.object({\n\t\tstate: v.union(\n\t\t\tv.literal(APPROVAL_RUN_STATES[0]),\n\t\t\tv.literal(APPROVAL_RUN_STATES[1]),\n\t\t\tv.literal(APPROVAL_RUN_STATES[2]),\n\t\t\tv.literal(APPROVAL_RUN_STATES[3]),\n\t\t\tv.literal(APPROVAL_RUN_STATES[4]),\n\t\t),\n\t}),\n\thandler: async (ctx, input) => {\n\t\tconst run = await ctx.db.get(input.runId)\n\t\tif (!run) throw new Error('Approval request not found')\n\t\tassertCompatible(run.workflow.compatibilityKey, input.compatibilityKey)\n\t\tconst step = run.workflow.steps.find(\n\t\t\t(candidate) =>\n\t\t\t\tcandidate.kind === 'decision' && candidate.key === run.currentStepKey,\n\t\t)\n\t\tif (!step || step.kind !== 'decision')\n\t\t\tthrow new Error('Approval request is not waiting for a decision')\n\n\t\tconst prior = await ctx.db\n\t\t\t.query('approvalDecisions')\n\t\t\t.withIndex(APPROVAL_ACTOR_DECISION_INDEX, (query) =>\n\t\t\t\tquery\n\t\t\t\t\t.eq('runId', run._id)\n\t\t\t\t\t.eq('stepKey', step.key)\n\t\t\t\t\t.eq('actor.actorRef', input.actor.actorRef),\n\t\t\t)\n\t\t\t.unique()\n\t\tif (prior) {\n\t\t\tif (prior.decision !== input.decision)\n\t\t\t\tthrow new Error('Actor already submitted a contradictory decision')\n\t\t\treturn {\n\t\t\t\tstate: run.state as 'pending' | 'approved' | 'rejected' | 'expired',\n\t\t\t}\n\t\t}\n\t\tif (run.state !== 'pending')\n\t\t\tthrow new Error(`Approval request is already ${run.state}`)\n\t\tif (\n\t\t\trun.expiresAt !== undefined &&\n\t\t\tclassifyPendingRunAt(Date.now(), run.expiresAt) === 'expired'\n\t\t)\n\t\t\treturn claimExpiry(ctx, run, step.key)\n\t\tif (!step.decisions.includes(input.decision))\n\t\t\tthrow new Error('Decision is not allowed by this workflow step')\n\t\tif (step.makerChecker && input.actor.actorRef === run.requester.actorRef)\n\t\t\tthrow new Error('Requester cannot decide this approval step')\n\n\t\tconst decidedAt = Date.now()\n\t\tawait ctx.db.insert('approvalDecisions', {\n\t\t\trunId: run._id,\n\t\t\tstepKey: step.key,\n\t\t\tactor: input.actor,\n\t\t\tdecision: input.decision,\n\t\t\t...(input.reason === undefined ? {} : { reason: input.reason }),\n\t\t\tdecidedAt,\n\t\t})\n\t\tconst evidence = await ctx.db\n\t\t\t.query('approvalDecisions')\n\t\t\t.withIndex('by_runId_and_stepKey_and_decidedAt', (query) =>\n\t\t\t\tquery.eq('runId', run._id).eq('stepKey', step.key),\n\t\t\t)\n\t\t\t.collect()\n\t\tconst outcome = evaluateDecisionOutcome(\n\t\t\tevidence.map((item) => ({\n\t\t\t\tactorRef: item.actor.actorRef,\n\t\t\t\tdecision: item.decision,\n\t\t\t})),\n\t\t\tstep.quorum.approvals,\n\t\t)\n\t\tawait logApprovalTransition(ctx, {\n\t\t\taction: `approval.decision.${input.decision}`,\n\t\t\tactorRef: input.actor.actorRef,\n\t\t\trunId: run._id,\n\t\t\tresourceType: run.resourceType,\n\t\t\tresourceRef: run.resourceRef,\n\t\t\ttransition: `${step.key}:${input.actor.actorRef}:${input.decision}`,\n\t\t})\n\t\tif (!outcome) return { state: 'pending' as const }\n\t\tconst terminal = isTerminalDecision(run, step.key, outcome)\n\t\tawait finishDecision(ctx, run, step.key, outcome, terminal, {\n\t\t\tactorRef: input.actor.actorRef,\n\t\t\tdecision: input.decision,\n\t\t\t...(input.reason === undefined ? {} : { reason: input.reason }),\n\t\t\tdecidedAt,\n\t\t})\n\t\treturn terminal ? { state: outcome } : { state: 'pending' as const }\n\t},\n})\n\nexport const list = query({\n\targs: { runId: v.id('approvalRuns') },\n\treturns: v.array(\n\t\tv.object({\n\t\t\tstepKey: v.string(),\n\t\t\tactorRef: v.string(),\n\t\t\tdecision: zodToConvex(approvalDecision),\n\t\t\treason: v.optional(zodToConvex(approvalReason)),\n\t\t\tdecidedAt: v.number(),\n\t\t}),\n\t),\n\thandler: (ctx, input) => listDecisionEvidence(ctx, input.runId),\n})\n\nexport const listForWorkflow = internalQuery({\n\targs: { runId: v.id('approvalRuns'), stepKey: v.string() },\n\treturns: v.array(\n\t\tv.object({\n\t\t\tstepKey: v.string(),\n\t\t\tactorRef: v.string(),\n\t\t\tdecision: zodToConvex(approvalDecision),\n\t\t\treason: v.optional(zodToConvex(approvalReason)),\n\t\t\tdecidedAt: v.number(),\n\t\t}),\n\t),\n\thandler: (ctx, input) =>\n\t\tlistDecisionEvidenceForStep(ctx, input.runId, input.stepKey),\n})\n\nexport const enter = internalMutation({\n\targs: {\n\t\trunId: v.id('approvalRuns'),\n\t\tstepKey: v.string(),\n\t\tworkflowId: v.string(),\n\t\texpiresAfterMs: v.optional(v.number()),\n\t},\n\treturns: v.object({\n\t\tstate: v.union(\n\t\t\tv.literal(APPROVAL_RUN_STATES[0]),\n\t\t\tv.literal(APPROVAL_RUN_STATES[1]),\n\t\t\tv.literal(APPROVAL_RUN_STATES[2]),\n\t\t\tv.literal(APPROVAL_RUN_STATES[3]),\n\t\t\tv.literal(APPROVAL_RUN_STATES[4]),\n\t\t),\n\t\texpiresAt: v.optional(v.number()),\n\t}),\n\thandler: async (ctx, input) => {\n\t\tconst run = await ctx.db.get(input.runId)\n\t\tif (!run) throw new Error('Approval request not found')\n\t\tif (run.workflowId !== input.workflowId)\n\t\t\tthrow new Error('Approval workflow linkage is incomplete')\n\t\tif (run.state !== 'pending')\n\t\t\treturn {\n\t\t\t\tstate: run.state as ApprovalRunState,\n\t\t\t\texpiresAt: run.expiresAt,\n\t\t\t}\n\t\tconst configuredExpiresAt = Number(run.metadata?.approvalExpiresAt)\n\t\tconst expiresAt = Number.isFinite(configuredExpiresAt)\n\t\t\t? configuredExpiresAt\n\t\t\t: input.expiresAfterMs === undefined\n\t\t\t\t? undefined\n\t\t\t\t: Date.now() + input.expiresAfterMs\n\t\tawait ctx.db.patch(run._id, {\n\t\t\tcurrentStepKey: input.stepKey,\n\t\t\texpiresAt,\n\t\t\tupdatedAt: Date.now(),\n\t\t})\n\t\tawait logApprovalTransition(ctx, {\n\t\t\taction: 'approval.waiting',\n\t\t\trunId: run._id,\n\t\t\tresourceType: run.resourceType,\n\t\t\tresourceRef: run.resourceRef,\n\t\t\ttransition: `${input.stepKey}:waiting`,\n\t\t})\n\t\tif (expiresAt !== undefined)\n\t\t\tawait ctx.scheduler.runAt(expiresAt, internal.decisions.expire, {\n\t\t\t\trunId: run._id,\n\t\t\t\tstepKey: input.stepKey,\n\t\t\t})\n\t\treturn {\n\t\t\tstate: 'pending' as const,\n\t\t\t...(expiresAt === undefined ? {} : { expiresAt }),\n\t\t}\n\t},\n})\n\nexport const expire = internalMutation({\n\targs: { runId: v.id('approvalRuns'), stepKey: v.string() },\n\treturns: v.object({\n\t\tstate: v.union(\n\t\t\tv.literal('missing'),\n\t\t\tv.literal(APPROVAL_RUN_STATES[0]),\n\t\t\tv.literal(APPROVAL_RUN_STATES[1]),\n\t\t\tv.literal(APPROVAL_RUN_STATES[2]),\n\t\t\tv.literal(APPROVAL_RUN_STATES[3]),\n\t\t\tv.literal(APPROVAL_RUN_STATES[4]),\n\t\t),\n\t}),\n\thandler: async (ctx, input) => {\n\t\tconst run = await ctx.db.get(input.runId)\n\t\tif (!run) return { state: 'missing' as const }\n\t\tif (\n\t\t\trun.state !== 'pending' ||\n\t\t\trun.currentStepKey !== input.stepKey ||\n\t\t\trun.expiresAt === undefined ||\n\t\t\tclassifyPendingRunAt(Date.now(), run.expiresAt) === 'pending'\n\t\t)\n\t\t\treturn { state: run.state as ApprovalRunState }\n\t\treturn claimExpiry(ctx, run, input.stepKey)\n\t},\n})\n\nconst approvalWorkflow = new WorkflowManager(components.workflow)\n\nasync function claimExpiry(\n\tctx: import('./_generated/server').MutationCtx,\n\trun: import('./_generated/dataModel').Doc<'approvalRuns'>,\n\tstepKey: string,\n): Promise<{ state: 'expired' }> {\n\tif (!canTransitionApprovalRun(run.state, 'expired'))\n\t\tthrow new Error(`Approval request cannot transition from ${run.state}`)\n\tconst now = Date.now()\n\tawait ctx.db.patch(run._id, {\n\t\tstate: 'expired',\n\t\texpiresAt: undefined,\n\t\tupdatedAt: now,\n\t\tterminalAt: now,\n\t})\n\tawait logApprovalTransition(ctx, {\n\t\taction: 'approval.expired',\n\t\trunId: run._id,\n\t\tresourceType: run.resourceType,\n\t\tresourceRef: run.resourceRef,\n\t\ttransition: `${stepKey}:expired`,\n\t})\n\tif (!run.workflowId) throw new Error('Approval workflow is not linked')\n\tawait approvalWorkflow.sendEvent(ctx, {\n\t\tworkflowId: run.workflowId as WorkflowId,\n\t\tname: approvalDecisionEventName(run._id, stepKey),\n\t\tvalidator: v.object({ outcome: v.literal(APPROVAL_RUN_STATES[3]) }),\n\t\tvalue: { outcome: 'expired' },\n\t})\n\treturn { state: 'expired' }\n}\n\nasync function finishDecision(\n\tctx: import('./_generated/server').MutationCtx,\n\trun: import('./_generated/dataModel').Doc<'approvalRuns'>,\n\tstepKey: string,\n\toutcome: 'approved' | 'rejected',\n\tterminal: boolean,\n\tterminalEvidence: {\n\t\tactorRef: string\n\t\tdecision: 'approved' | 'rejected'\n\t\treason?: string\n\t\tdecidedAt: number\n\t},\n): Promise<void> {\n\tif (terminal) {\n\t\tif (!canTransitionApprovalRun(run.state, outcome))\n\t\t\tthrow new Error(`Approval request cannot transition from ${run.state}`)\n\t\tconst now = Date.now()\n\t\tawait ctx.db.patch(run._id, {\n\t\t\tstate: outcome,\n\t\t\texpiresAt: undefined,\n\t\t\tupdatedAt: now,\n\t\t\tterminalAt: now,\n\t\t})\n\t\tawait logApprovalTransition(ctx, {\n\t\t\taction: `approval.${outcome}`,\n\t\t\trunId: run._id,\n\t\t\tresourceType: run.resourceType,\n\t\t\tresourceRef: run.resourceRef,\n\t\t\ttransition: `${stepKey}:terminal:${outcome}`,\n\t\t})\n\t}\n\tif (!run.workflowId) throw new Error('Approval workflow is not linked')\n\tawait approvalWorkflow.sendEvent(ctx, {\n\t\tworkflowId: run.workflowId as WorkflowId,\n\t\tname: approvalDecisionEventName(run._id, stepKey),\n\t\tvalidator: v.object({\n\t\t\toutcome: v.union(\n\t\t\t\tv.literal(APPROVAL_DECISIONS[0]),\n\t\t\t\tv.literal(APPROVAL_DECISIONS[1]),\n\t\t\t),\n\t\t\tterminalEvidence: v.object({\n\t\t\t\tactorRef: v.string(),\n\t\t\t\tdecision: zodToConvex(approvalDecision),\n\t\t\t\treason: v.optional(zodToConvex(approvalReason)),\n\t\t\t\tdecidedAt: v.number(),\n\t\t\t}),\n\t\t}),\n\t\tvalue: { outcome, terminalEvidence },\n\t})\n}\n\nfunction assertCompatible(actual: string, expected: string): void {\n\tif (actual !== expected)\n\t\tthrow new Error(\n\t\t\t`Approval workflow compatibility mismatch: expected ${expected}, received ${actual}`,\n\t\t)\n}\n\nasync function listDecisionEvidence(\n\tctx: QueryCtx,\n\trunId: import('./_generated/dataModel').Id<'approvalRuns'>,\n) {\n\tconst decisions = await ctx.db\n\t\t.query('approvalDecisions')\n\t\t.withIndex(APPROVAL_DECISION_HISTORY_INDEX, (query) =>\n\t\t\tquery.eq('runId', runId),\n\t\t)\n\t\t.collect()\n\treturn decisions.map((decision) => ({\n\t\tstepKey: decision.stepKey,\n\t\tactorRef: decision.actor.actorRef,\n\t\tdecision: decision.decision,\n\t\t...(decision.reason === undefined ? {} : { reason: decision.reason }),\n\t\tdecidedAt: decision.decidedAt,\n\t}))\n}\n\nasync function listDecisionEvidenceForStep(\n\tctx: QueryCtx,\n\trunId: import('./_generated/dataModel').Id<'approvalRuns'>,\n\tstepKey: string,\n) {\n\tconst decisions = await ctx.db\n\t\t.query('approvalDecisions')\n\t\t.withIndex('by_runId_and_stepKey_and_decidedAt', (query) =>\n\t\t\tquery.eq('runId', runId).eq('stepKey', stepKey),\n\t\t)\n\t\t.collect()\n\treturn decisions.map((decision) => ({\n\t\tstepKey: decision.stepKey,\n\t\tactorRef: decision.actor.actorRef,\n\t\tdecision: decision.decision,\n\t\t...(decision.reason === undefined ? {} : { reason: decision.reason }),\n\t\tdecidedAt: decision.decidedAt,\n\t}))\n}\n\nfunction isTerminalDecision(\n\trun: import('./_generated/dataModel').Doc<'approvalRuns'>,\n\tstepKey: string,\n\toutcome: 'approved' | 'rejected',\n): boolean {\n\tif (outcome === 'rejected') return true\n\tconst currentIndex = run.workflow.steps.findIndex(\n\t\t(step) => step.kind === 'decision' && step.key === stepKey,\n\t)\n\treturn !run.workflow.steps\n\t\t.slice(currentIndex + 1)\n\t\t.some((step) => step.kind === 'decision')\n}\n"],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ declare namespace health_d_exports {
2
+ export { check };
3
+ }
4
+ /**
5
+ * Verifies that the package's component schema and required decision indexes
6
+ * were deployed. A missing schema fails with a cvx-kit-specific diagnostic.
7
+ */
8
+ declare const check: import("convex/server").RegisteredQuery<"public", {}, Promise<{
9
+ status: 'ready';
10
+ schemaVersion: 1;
11
+ requiredIndexes: ("by_runId_and_decidedAt" | "by_runId_and_stepKey_and_actor_actorRef")[];
12
+ }>>;
13
+ //#endregion
14
+ export { check, health_d_exports };
15
+ //# sourceMappingURL=health.d.mts.map
@@ -0,0 +1,2 @@
1
+ import{query as e}from"./_generated/server.mjs";import{APPROVAL_REQUIRED_DECISION_INDEXES as t}from"./constants.mjs";import{v as n}from"convex/values";const r=e({args:{},returns:n.object({status:n.literal(`ready`),schemaVersion:n.literal(1),requiredIndexes:n.array(n.string())}),handler:async e=>{try{for(let n of t)await e.db.query(`approvalDecisions`).withIndex(n).take(1)}catch(e){throw Error(`cvx-kit approvals schema v1 is not installed with its required indexes. Remove consumer patches, reinstall cvx-kit, and deploy again. Cause: ${e instanceof Error?e.message:String(e)}`)}return{status:`ready`,schemaVersion:1,requiredIndexes:[...t]}}});export{r as check};
2
+ //# sourceMappingURL=health.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.mjs","names":[],"sources":["../../../src/components/approvals/health.ts"],"sourcesContent":["import { v } from 'convex/values'\n\nimport { query } from './_generated/server'\nimport {\n\tAPPROVAL_COMPONENT_SCHEMA_VERSION,\n\tAPPROVAL_REQUIRED_DECISION_INDEXES,\n} from './constants'\n\n/**\n * Verifies that the package's component schema and required decision indexes\n * were deployed. A missing schema fails with a cvx-kit-specific diagnostic.\n */\nexport const check = query({\n\targs: {},\n\treturns: v.object({\n\t\tstatus: v.literal('ready'),\n\t\tschemaVersion: v.literal(APPROVAL_COMPONENT_SCHEMA_VERSION),\n\t\trequiredIndexes: v.array(v.string()),\n\t}),\n\thandler: async (ctx) => {\n\t\ttry {\n\t\t\tfor (const index of APPROVAL_REQUIRED_DECISION_INDEXES) {\n\t\t\t\tawait ctx.db.query('approvalDecisions').withIndex(index).take(1)\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthrow new Error(\n\t\t\t\t`cvx-kit approvals schema v${APPROVAL_COMPONENT_SCHEMA_VERSION} is not installed with its required indexes. Remove consumer patches, reinstall cvx-kit, and deploy again. Cause: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t)\n\t\t}\n\n\t\treturn {\n\t\t\tstatus: 'ready' as const,\n\t\t\tschemaVersion: APPROVAL_COMPONENT_SCHEMA_VERSION,\n\t\t\trequiredIndexes: [...APPROVAL_REQUIRED_DECISION_INDEXES],\n\t\t}\n\t},\n})\n"],"mappings":"uJAYA,MAAa,EAAQ,EAAM,CAC1B,KAAM,CAAC,EACP,QAAS,EAAE,OAAO,CACjB,OAAQ,EAAE,QAAQ,OAAO,EACzB,cAAe,EAAE,QAAA,CAAyC,EAC1D,gBAAiB,EAAE,MAAM,EAAE,OAAO,CAAC,CACpC,CAAC,EACD,QAAS,KAAO,IAAQ,CACvB,GAAI,CACH,IAAK,IAAM,KAAS,EACnB,MAAM,EAAI,GAAG,MAAM,mBAAmB,CAAC,CAAC,UAAU,CAAK,CAAC,CAAC,KAAK,CAAC,CAEjE,OAAS,EAAO,CACf,MAAU,MACT,gJAAmL,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,GACzO,CACD,CAEA,MAAO,CACN,OAAQ,QACR,cAAA,EACA,gBAAiB,CAAC,GAAG,CAAkC,CACxD,CACD,CACD,CAAC"}
@@ -1,2 +1,2 @@
1
- import{components as e,internal as t}from"./_generated/api.mjs";import{internalMutation as n,internalQuery as r,mutation as i,query as a}from"./_generated/server.mjs";import{APPROVAL_EXECUTION_STATES as o,APPROVAL_RUN_STATES as s}from"./constants.mjs";import{logApprovalTransition as c}from"./audit.mjs";import{approvalActor as l,approvalMetadata as u,approvalName as d,approvalReference as f,approvalRunDocument as p,approvalRunState as m,approvalWorkflowDescriptor as h}from"./validators.mjs";import{canTransitionApprovalRun as g}from"./functions.mjs";import{zodToConvex as _}from"convex-helpers/server/zod4";import{paginationOptsValidator as v,paginationResultValidator as y}from"convex/server";import{v as b}from"convex/values";import{WorkflowManager as x}from"@convex-dev/workflow";const S=i({args:{scopeRef:_(f),resourceType:_(f),resourceRef:_(f),requester:_(l),metadata:b.optional(_(u)),workflow:_(h)},returns:b.object({runId:b.id(`approvalRuns`)}),handler:async(e,n)=>{let r=Date.now(),i=await e.db.insert(`approvalRuns`,{...n,state:`pending`,createdAt:r,updatedAt:r}),a=await k.start(e,t.workflow.run,{runId:i},{startAsync:!0});return await e.db.patch(i,{workflowId:a,updatedAt:Date.now()}),await c(e,{action:`approval.requested`,actorRef:n.requester.actorRef,runId:i,resourceType:n.resourceType,resourceRef:n.resourceRef,transition:`requested`}),{runId:i}}}),C=i({args:{runId:b.id(`approvalRuns`),actor:_(l),compatibilityKey:b.string()},returns:b.object({state:b.literal(s[4])}),handler:async(e,t)=>{let n=await e.db.get(t.runId);if(!n)throw Error(`Approval request not found`);if(P(n.workflow.compatibilityKey,t.compatibilityKey),n.state!==`pending`){if(n.state===`canceled`)return{state:`canceled`};throw Error(`Approval request is already ${n.state}`)}if(!n.workflowId)throw Error(`Approval workflow is not linked`);if(await k.cancel(e,n.workflowId),!g(n.state,`canceled`))throw Error(`Approval request cannot transition from ${n.state}`);let r=Date.now();return await e.db.patch(n._id,{state:`canceled`,expiresAt:void 0,updatedAt:r,terminalAt:r}),await c(e,{action:`approval.canceled`,actorRef:t.actor.actorRef,runId:n._id,resourceType:n.resourceType,resourceRef:n.resourceRef,transition:`canceled`}),{state:`canceled`}}}),w=i({args:{runId:b.id(`approvalRuns`),compatibilityKey:b.string()},returns:b.null(),handler:async(e,t)=>{let n=await e.db.get(t.runId);if(!n)throw Error(`Approval request not found`);if(P(n.workflow.compatibilityKey,t.compatibilityKey),!n.workflowId)throw Error(`Approval workflow is not linked`);if(!n.executionFailedStepKey)throw Error(`Approval workflow has no failed step to restart`);return await k.restart(e,n.workflowId,{from:n.executionFailedStepKey,startAsync:!0}),null}}),T=a({args:{runId:b.id(`approvalRuns`),compatibilityKey:b.string()},returns:b.union(b.null(),N()),handler:async(e,t)=>{let n=await e.db.get(t.runId);return n?(P(n.workflow.compatibilityKey,t.compatibilityKey),{run:n,execution:A(n.workflowId?await k.status(e,n.workflowId):null)}):null}}),E=a({args:{scopeRef:_(f),state:b.optional(_(m)),paginationOpts:v},returns:y(j()),handler:(e,t)=>e.db.query(`approvalRuns`).withIndex(`by_scopeRef_and_state`,e=>t.state===void 0?e.eq(`scopeRef`,t.scopeRef):e.eq(`scopeRef`,t.scopeRef).eq(`state`,t.state)).order(`desc`).paginate(t.paginationOpts)}),D=r({args:{runId:b.id(`approvalRuns`)},returns:b.union(b.null(),j()),handler:(e,t)=>e.db.get(t.runId)}),O=n({args:{runId:b.id(`approvalRuns`),outcome:b.union(b.literal(o[1]),b.literal(o[3])),failedStepKey:b.optional(_(d))},returns:b.null(),handler:async(e,t)=>{let n=await e.db.get(t.runId);if(!n)throw Error(`Approval request not found`);return await e.db.patch(n._id,{executionFailedStepKey:t.outcome===`failed`?t.failedStepKey:void 0,updatedAt:Date.now()}),await c(e,{action:`approval.execution.${t.outcome}`,runId:n._id,resourceType:n.resourceType,resourceRef:n.resourceRef,transition:`execution:${t.outcome}`,severity:t.outcome===`failed`?`error`:`info`}),null}}),k=new x(e.workflow);function A(e){if(!e)return null;switch(e.type){case`failed`:return{type:`failed`,error:e.error};case`inProgress`:case`completed`:case`canceled`:return{type:e.type}}}function j(){return b.object({_id:b.id(`approvalRuns`),_creationTime:b.number(),..._(p).fields})}function M(){return b.union(b.object({type:b.literal(o[0])}),b.object({type:b.literal(o[1])}),b.object({type:b.literal(o[2])}),b.object({type:b.literal(o[3]),error:b.string()}))}function N(){return b.object({run:j(),execution:b.union(b.null(),M())})}function P(e,t){if(e!==t)throw Error(`Approval workflow compatibility mismatch: expected ${t}, received ${e}`)}export{C as cancel,D as getForWorkflow,E as list,O as recordExecutionTerminal,w as restart,S as start,T as status};
1
+ import{components as e,internal as t}from"./_generated/api.mjs";import{internalMutation as n,internalQuery as r,mutation as i,query as a}from"./_generated/server.mjs";import{APPROVAL_EXECUTION_STATES as o,APPROVAL_RUN_STATES as s}from"./constants.mjs";import{logApprovalTransition as c}from"./audit.mjs";import{approvalActor as l,approvalMetadata as u,approvalName as d,approvalReference as f,approvalRunDocument as p,approvalRunState as m,approvalWorkflowDescriptor as h}from"./validators.mjs";import{canTransitionApprovalRun as g}from"./functions.mjs";import _ from"./schema.js";import{zodToConvex as v}from"convex-helpers/server/zod4";import{paginationOptsValidator as y,paginationResultValidator as b}from"convex/server";import{v as x}from"convex/values";import{WorkflowManager as S}from"@convex-dev/workflow";import{paginator as C}from"convex-helpers/server/pagination";const w=i({args:{scopeRef:v(f),resourceType:v(f),resourceRef:v(f),requester:v(l),metadata:x.optional(v(u)),workflow:v(h)},returns:x.object({runId:x.id(`approvalRuns`)}),handler:async(e,n)=>{let r=Date.now(),i=await e.db.insert(`approvalRuns`,{...n,state:`pending`,createdAt:r,updatedAt:r}),a=await j.start(e,t.workflow.run,{runId:i},{startAsync:!0});return await e.db.patch(i,{workflowId:a,updatedAt:Date.now()}),await c(e,{action:`approval.requested`,actorRef:n.requester.actorRef,runId:i,resourceType:n.resourceType,resourceRef:n.resourceRef,transition:`requested`}),{runId:i}}}),T=i({args:{runId:x.id(`approvalRuns`),actor:v(l),compatibilityKey:x.string()},returns:x.object({state:x.literal(s[4])}),handler:async(e,t)=>{let n=await e.db.get(t.runId);if(!n)throw Error(`Approval request not found`);if(I(n.workflow.compatibilityKey,t.compatibilityKey),n.state!==`pending`){if(n.state===`canceled`)return{state:`canceled`};throw Error(`Approval request is already ${n.state}`)}if(!n.workflowId)throw Error(`Approval workflow is not linked`);if(await j.cancel(e,n.workflowId),!g(n.state,`canceled`))throw Error(`Approval request cannot transition from ${n.state}`);let r=Date.now();return await e.db.patch(n._id,{state:`canceled`,expiresAt:void 0,updatedAt:r,terminalAt:r}),await c(e,{action:`approval.canceled`,actorRef:t.actor.actorRef,runId:n._id,resourceType:n.resourceType,resourceRef:n.resourceRef,transition:`canceled`}),{state:`canceled`}}}),E=i({args:{runId:x.id(`approvalRuns`),compatibilityKey:x.string()},returns:x.null(),handler:async(e,t)=>{let n=await e.db.get(t.runId);if(!n)throw Error(`Approval request not found`);if(I(n.workflow.compatibilityKey,t.compatibilityKey),!n.workflowId)throw Error(`Approval workflow is not linked`);if(!n.executionFailedStepKey)throw Error(`Approval workflow has no failed step to restart`);return await j.restart(e,n.workflowId,{from:n.executionFailedStepKey,startAsync:!0}),null}}),D=a({args:{runId:x.id(`approvalRuns`),compatibilityKey:x.string()},returns:x.union(x.null(),F()),handler:async(e,t)=>{let n=await e.db.get(t.runId);return n?(I(n.workflow.compatibilityKey,t.compatibilityKey),{run:n,execution:M(n.workflowId?await j.status(e,n.workflowId):null)}):null}}),O=a({args:{scopeRef:v(f),state:x.optional(v(m)),paginationOpts:y},returns:b(N()),handler:(e,t)=>C(e.db,_).query(`approvalRuns`).withIndex(`by_scopeRef_and_state`,e=>t.state===void 0?e.eq(`scopeRef`,t.scopeRef):e.eq(`scopeRef`,t.scopeRef).eq(`state`,t.state)).order(`desc`).paginate(t.paginationOpts)}),k=r({args:{runId:x.id(`approvalRuns`)},returns:x.union(x.null(),N()),handler:(e,t)=>e.db.get(t.runId)}),A=n({args:{runId:x.id(`approvalRuns`),outcome:x.union(x.literal(o[1]),x.literal(o[3])),failedStepKey:x.optional(v(d))},returns:x.null(),handler:async(e,t)=>{let n=await e.db.get(t.runId);if(!n)throw Error(`Approval request not found`);return await e.db.patch(n._id,{executionFailedStepKey:t.outcome===`failed`?t.failedStepKey:void 0,updatedAt:Date.now()}),await c(e,{action:`approval.execution.${t.outcome}`,runId:n._id,resourceType:n.resourceType,resourceRef:n.resourceRef,transition:`execution:${t.outcome}`,severity:t.outcome===`failed`?`error`:`info`}),null}}),j=new S(e.workflow);function M(e){if(!e)return null;switch(e.type){case`failed`:return{type:`failed`,error:e.error};case`inProgress`:case`completed`:case`canceled`:return{type:e.type}}}function N(){return x.object({_id:x.id(`approvalRuns`),_creationTime:x.number(),...v(p).fields})}function P(){return x.union(x.object({type:x.literal(o[0])}),x.object({type:x.literal(o[1])}),x.object({type:x.literal(o[2])}),x.object({type:x.literal(o[3]),error:x.string()}))}function F(){return x.object({run:N(),execution:x.union(x.null(),P())})}function I(e,t){if(e!==t)throw Error(`Approval workflow compatibility mismatch: expected ${t}, received ${e}`)}export{T as cancel,k as getForWorkflow,O as list,A as recordExecutionTerminal,E as restart,w as start,D as status};
2
2
  //# sourceMappingURL=requests.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"requests.mjs","names":[],"sources":["../../../src/components/approvals/requests.ts"],"sourcesContent":["import { WorkflowManager, type WorkflowId } from '@convex-dev/workflow'\nimport { zodToConvex } from 'convex-helpers/server/zod4'\nimport {\n\tpaginationOptsValidator,\n\tpaginationResultValidator,\n} from 'convex/server'\nimport { v } from 'convex/values'\n\nimport { components, internal } from './_generated/api'\nimport {\n\tinternalMutation,\n\tinternalQuery,\n\tmutation,\n\tquery,\n} from './_generated/server'\nimport { logApprovalTransition } from './audit'\nimport { APPROVAL_EXECUTION_STATES, APPROVAL_RUN_STATES } from './constants'\nimport { canTransitionApprovalRun } from './functions'\nimport {\n\tapprovalActor,\n\tapprovalMetadata,\n\tapprovalName,\n\tapprovalReference,\n\tapprovalRunDocument,\n\tapprovalRunState,\n\tapprovalWorkflowDescriptor,\n} from './validators'\n\nexport const start = mutation({\n\targs: {\n\t\tscopeRef: zodToConvex(approvalReference),\n\t\tresourceType: zodToConvex(approvalReference),\n\t\tresourceRef: zodToConvex(approvalReference),\n\t\trequester: zodToConvex(approvalActor),\n\t\tmetadata: v.optional(zodToConvex(approvalMetadata)),\n\t\tworkflow: zodToConvex(approvalWorkflowDescriptor),\n\t},\n\treturns: v.object({ runId: v.id('approvalRuns') }),\n\thandler: async (ctx, input) => {\n\t\tconst now = Date.now()\n\t\tconst runId = await ctx.db.insert('approvalRuns', {\n\t\t\t...input,\n\t\t\tstate: 'pending',\n\t\t\tcreatedAt: now,\n\t\t\tupdatedAt: now,\n\t\t})\n\t\tconst workflowId: WorkflowId = await approvalWorkflow.start(\n\t\t\tctx,\n\t\t\tinternal.workflow.run,\n\t\t\t{ runId },\n\t\t\t{ startAsync: true },\n\t\t)\n\t\tawait ctx.db.patch(runId, { workflowId, updatedAt: Date.now() })\n\t\tawait logApprovalTransition(ctx, {\n\t\t\taction: 'approval.requested',\n\t\t\tactorRef: input.requester.actorRef,\n\t\t\trunId,\n\t\t\tresourceType: input.resourceType,\n\t\t\tresourceRef: input.resourceRef,\n\t\t\ttransition: 'requested',\n\t\t})\n\t\treturn { runId }\n\t},\n})\n\nexport const cancel = mutation({\n\targs: {\n\t\trunId: v.id('approvalRuns'),\n\t\tactor: zodToConvex(approvalActor),\n\t\tcompatibilityKey: v.string(),\n\t},\n\treturns: v.object({ state: v.literal(APPROVAL_RUN_STATES[4]) }),\n\thandler: async (ctx, input) => {\n\t\tconst run = await ctx.db.get(input.runId)\n\t\tif (!run) throw new Error('Approval request not found')\n\t\tassertCompatible(run.workflow.compatibilityKey, input.compatibilityKey)\n\t\tif (run.state !== 'pending') {\n\t\t\tif (run.state === 'canceled') return { state: 'canceled' as const }\n\t\t\tthrow new Error(`Approval request is already ${run.state}`)\n\t\t}\n\t\tif (!run.workflowId) throw new Error('Approval workflow is not linked')\n\t\tawait approvalWorkflow.cancel(ctx, run.workflowId as WorkflowId)\n\t\tif (!canTransitionApprovalRun(run.state, 'canceled'))\n\t\t\tthrow new Error(`Approval request cannot transition from ${run.state}`)\n\t\tconst now = Date.now()\n\t\tawait ctx.db.patch(run._id, {\n\t\t\tstate: 'canceled',\n\t\t\texpiresAt: undefined,\n\t\t\tupdatedAt: now,\n\t\t\tterminalAt: now,\n\t\t})\n\t\tawait logApprovalTransition(ctx, {\n\t\t\taction: 'approval.canceled',\n\t\t\tactorRef: input.actor.actorRef,\n\t\t\trunId: run._id,\n\t\t\tresourceType: run.resourceType,\n\t\t\tresourceRef: run.resourceRef,\n\t\t\ttransition: 'canceled',\n\t\t})\n\t\treturn { state: 'canceled' as const }\n\t},\n})\n\nexport const restart = mutation({\n\targs: { runId: v.id('approvalRuns'), compatibilityKey: v.string() },\n\treturns: v.null(),\n\thandler: async (ctx, input) => {\n\t\tconst run = await ctx.db.get(input.runId)\n\t\tif (!run) throw new Error('Approval request not found')\n\t\tassertCompatible(run.workflow.compatibilityKey, input.compatibilityKey)\n\t\tif (!run.workflowId) throw new Error('Approval workflow is not linked')\n\t\tif (!run.executionFailedStepKey)\n\t\t\tthrow new Error('Approval workflow has no failed step to restart')\n\t\tawait approvalWorkflow.restart(ctx, run.workflowId as WorkflowId, {\n\t\t\tfrom: run.executionFailedStepKey,\n\t\t\tstartAsync: true,\n\t\t})\n\t\treturn null\n\t},\n})\n\nexport const status = query({\n\targs: { runId: v.id('approvalRuns'), compatibilityKey: v.string() },\n\treturns: v.union(v.null(), approvalStatusValidator()),\n\thandler: async (ctx, input) => {\n\t\tconst run = await ctx.db.get(input.runId)\n\t\tif (!run) return null\n\t\tassertCompatible(run.workflow.compatibilityKey, input.compatibilityKey)\n\t\tconst workflowStatus = run.workflowId\n\t\t\t? await approvalWorkflow.status(ctx, run.workflowId as WorkflowId)\n\t\t\t: null\n\t\tconst execution = normalizeWorkflowStatus(workflowStatus)\n\t\treturn { run, execution }\n\t},\n})\n\nexport const list = query({\n\targs: {\n\t\tscopeRef: zodToConvex(approvalReference),\n\t\tstate: v.optional(zodToConvex(approvalRunState)),\n\t\tpaginationOpts: paginationOptsValidator,\n\t},\n\treturns: paginationResultValidator(approvalRunValidator()),\n\thandler: (ctx, input) =>\n\t\tctx.db\n\t\t\t.query('approvalRuns')\n\t\t\t.withIndex('by_scopeRef_and_state', (query) =>\n\t\t\t\tinput.state === undefined\n\t\t\t\t\t? query.eq('scopeRef', input.scopeRef)\n\t\t\t\t\t: query.eq('scopeRef', input.scopeRef).eq('state', input.state),\n\t\t\t)\n\t\t\t.order('desc')\n\t\t\t.paginate(input.paginationOpts),\n})\n\nexport const getForWorkflow = internalQuery({\n\targs: { runId: v.id('approvalRuns') },\n\treturns: v.union(v.null(), approvalRunValidator()),\n\thandler: (ctx, input) => ctx.db.get(input.runId),\n})\n\nexport const recordExecutionTerminal = internalMutation({\n\targs: {\n\t\trunId: v.id('approvalRuns'),\n\t\toutcome: v.union(\n\t\t\tv.literal(APPROVAL_EXECUTION_STATES[1]),\n\t\t\tv.literal(APPROVAL_EXECUTION_STATES[3]),\n\t\t),\n\t\tfailedStepKey: v.optional(zodToConvex(approvalName)),\n\t},\n\treturns: v.null(),\n\thandler: async (ctx, input) => {\n\t\tconst run = await ctx.db.get(input.runId)\n\t\tif (!run) throw new Error('Approval request not found')\n\t\tawait ctx.db.patch(run._id, {\n\t\t\texecutionFailedStepKey:\n\t\t\t\tinput.outcome === 'failed' ? input.failedStepKey : undefined,\n\t\t\tupdatedAt: Date.now(),\n\t\t})\n\t\tawait logApprovalTransition(ctx, {\n\t\t\taction: `approval.execution.${input.outcome}`,\n\t\t\trunId: run._id,\n\t\t\tresourceType: run.resourceType,\n\t\t\tresourceRef: run.resourceRef,\n\t\t\ttransition: `execution:${input.outcome}`,\n\t\t\tseverity: input.outcome === 'failed' ? 'error' : 'info',\n\t\t})\n\t\treturn null\n\t},\n})\n\nconst approvalWorkflow = new WorkflowManager(components.workflow)\n\nfunction normalizeWorkflowStatus(\n\tstatus: Awaited<ReturnType<typeof approvalWorkflow.status>> | null,\n) {\n\tif (!status) return null\n\tswitch (status.type) {\n\t\tcase 'failed':\n\t\t\treturn { type: 'failed' as const, error: status.error }\n\t\tcase 'inProgress':\n\t\tcase 'completed':\n\t\tcase 'canceled':\n\t\t\treturn { type: status.type }\n\t}\n}\n\nfunction approvalRunValidator() {\n\treturn v.object({\n\t\t_id: v.id('approvalRuns'),\n\t\t_creationTime: v.number(),\n\t\t...zodToConvex(approvalRunDocument).fields,\n\t})\n}\n\nfunction workflowStatusValidator() {\n\treturn v.union(\n\t\tv.object({ type: v.literal(APPROVAL_EXECUTION_STATES[0]) }),\n\t\tv.object({ type: v.literal(APPROVAL_EXECUTION_STATES[1]) }),\n\t\tv.object({ type: v.literal(APPROVAL_EXECUTION_STATES[2]) }),\n\t\tv.object({\n\t\t\ttype: v.literal(APPROVAL_EXECUTION_STATES[3]),\n\t\t\terror: v.string(),\n\t\t}),\n\t)\n}\n\nfunction approvalStatusValidator() {\n\treturn v.object({\n\t\trun: approvalRunValidator(),\n\t\texecution: v.union(v.null(), workflowStatusValidator()),\n\t})\n}\n\nfunction assertCompatible(actual: string, expected: string): void {\n\tif (actual !== expected)\n\t\tthrow new Error(\n\t\t\t`Approval workflow compatibility mismatch: expected ${expected}, received ${actual}`,\n\t\t)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"requests.mjs","names":["schema"],"sources":["../../../src/components/approvals/requests.ts"],"sourcesContent":["import { WorkflowManager, type WorkflowId } from '@convex-dev/workflow'\nimport { zodToConvex } from 'convex-helpers/server/zod4'\nimport { paginator } from 'convex-helpers/server/pagination'\nimport {\n\tpaginationOptsValidator,\n\tpaginationResultValidator,\n} from 'convex/server'\nimport { v } from 'convex/values'\n\nimport { components, internal } from './_generated/api'\nimport {\n\tinternalMutation,\n\tinternalQuery,\n\tmutation,\n\tquery,\n} from './_generated/server'\nimport { logApprovalTransition } from './audit'\nimport schema from './schema'\nimport { APPROVAL_EXECUTION_STATES, APPROVAL_RUN_STATES } from './constants'\nimport { canTransitionApprovalRun } from './functions'\nimport {\n\tapprovalActor,\n\tapprovalMetadata,\n\tapprovalName,\n\tapprovalReference,\n\tapprovalRunDocument,\n\tapprovalRunState,\n\tapprovalWorkflowDescriptor,\n} from './validators'\n\nexport const start = mutation({\n\targs: {\n\t\tscopeRef: zodToConvex(approvalReference),\n\t\tresourceType: zodToConvex(approvalReference),\n\t\tresourceRef: zodToConvex(approvalReference),\n\t\trequester: zodToConvex(approvalActor),\n\t\tmetadata: v.optional(zodToConvex(approvalMetadata)),\n\t\tworkflow: zodToConvex(approvalWorkflowDescriptor),\n\t},\n\treturns: v.object({ runId: v.id('approvalRuns') }),\n\thandler: async (ctx, input) => {\n\t\tconst now = Date.now()\n\t\tconst runId = await ctx.db.insert('approvalRuns', {\n\t\t\t...input,\n\t\t\tstate: 'pending',\n\t\t\tcreatedAt: now,\n\t\t\tupdatedAt: now,\n\t\t})\n\t\tconst workflowId: WorkflowId = await approvalWorkflow.start(\n\t\t\tctx,\n\t\t\tinternal.workflow.run,\n\t\t\t{ runId },\n\t\t\t{ startAsync: true },\n\t\t)\n\t\tawait ctx.db.patch(runId, { workflowId, updatedAt: Date.now() })\n\t\tawait logApprovalTransition(ctx, {\n\t\t\taction: 'approval.requested',\n\t\t\tactorRef: input.requester.actorRef,\n\t\t\trunId,\n\t\t\tresourceType: input.resourceType,\n\t\t\tresourceRef: input.resourceRef,\n\t\t\ttransition: 'requested',\n\t\t})\n\t\treturn { runId }\n\t},\n})\n\nexport const cancel = mutation({\n\targs: {\n\t\trunId: v.id('approvalRuns'),\n\t\tactor: zodToConvex(approvalActor),\n\t\tcompatibilityKey: v.string(),\n\t},\n\treturns: v.object({ state: v.literal(APPROVAL_RUN_STATES[4]) }),\n\thandler: async (ctx, input) => {\n\t\tconst run = await ctx.db.get(input.runId)\n\t\tif (!run) throw new Error('Approval request not found')\n\t\tassertCompatible(run.workflow.compatibilityKey, input.compatibilityKey)\n\t\tif (run.state !== 'pending') {\n\t\t\tif (run.state === 'canceled') return { state: 'canceled' as const }\n\t\t\tthrow new Error(`Approval request is already ${run.state}`)\n\t\t}\n\t\tif (!run.workflowId) throw new Error('Approval workflow is not linked')\n\t\tawait approvalWorkflow.cancel(ctx, run.workflowId as WorkflowId)\n\t\tif (!canTransitionApprovalRun(run.state, 'canceled'))\n\t\t\tthrow new Error(`Approval request cannot transition from ${run.state}`)\n\t\tconst now = Date.now()\n\t\tawait ctx.db.patch(run._id, {\n\t\t\tstate: 'canceled',\n\t\t\texpiresAt: undefined,\n\t\t\tupdatedAt: now,\n\t\t\tterminalAt: now,\n\t\t})\n\t\tawait logApprovalTransition(ctx, {\n\t\t\taction: 'approval.canceled',\n\t\t\tactorRef: input.actor.actorRef,\n\t\t\trunId: run._id,\n\t\t\tresourceType: run.resourceType,\n\t\t\tresourceRef: run.resourceRef,\n\t\t\ttransition: 'canceled',\n\t\t})\n\t\treturn { state: 'canceled' as const }\n\t},\n})\n\nexport const restart = mutation({\n\targs: { runId: v.id('approvalRuns'), compatibilityKey: v.string() },\n\treturns: v.null(),\n\thandler: async (ctx, input) => {\n\t\tconst run = await ctx.db.get(input.runId)\n\t\tif (!run) throw new Error('Approval request not found')\n\t\tassertCompatible(run.workflow.compatibilityKey, input.compatibilityKey)\n\t\tif (!run.workflowId) throw new Error('Approval workflow is not linked')\n\t\tif (!run.executionFailedStepKey)\n\t\t\tthrow new Error('Approval workflow has no failed step to restart')\n\t\tawait approvalWorkflow.restart(ctx, run.workflowId as WorkflowId, {\n\t\t\tfrom: run.executionFailedStepKey,\n\t\t\tstartAsync: true,\n\t\t})\n\t\treturn null\n\t},\n})\n\nexport const status = query({\n\targs: { runId: v.id('approvalRuns'), compatibilityKey: v.string() },\n\treturns: v.union(v.null(), approvalStatusValidator()),\n\thandler: async (ctx, input) => {\n\t\tconst run = await ctx.db.get(input.runId)\n\t\tif (!run) return null\n\t\tassertCompatible(run.workflow.compatibilityKey, input.compatibilityKey)\n\t\tconst workflowStatus = run.workflowId\n\t\t\t? await approvalWorkflow.status(ctx, run.workflowId as WorkflowId)\n\t\t\t: null\n\t\tconst execution = normalizeWorkflowStatus(workflowStatus)\n\t\treturn { run, execution }\n\t},\n})\n\nexport const list = query({\n\targs: {\n\t\tscopeRef: zodToConvex(approvalReference),\n\t\tstate: v.optional(zodToConvex(approvalRunState)),\n\t\tpaginationOpts: paginationOptsValidator,\n\t},\n\treturns: paginationResultValidator(approvalRunValidator()),\n\thandler: (ctx, input) =>\n\t\tpaginator(ctx.db, schema)\n\t\t\t.query('approvalRuns')\n\t\t\t.withIndex('by_scopeRef_and_state', (query) =>\n\t\t\t\tinput.state === undefined\n\t\t\t\t\t? query.eq('scopeRef', input.scopeRef)\n\t\t\t\t\t: query.eq('scopeRef', input.scopeRef).eq('state', input.state),\n\t\t\t)\n\t\t\t.order('desc')\n\t\t\t.paginate(input.paginationOpts),\n})\n\nexport const getForWorkflow = internalQuery({\n\targs: { runId: v.id('approvalRuns') },\n\treturns: v.union(v.null(), approvalRunValidator()),\n\thandler: (ctx, input) => ctx.db.get(input.runId),\n})\n\nexport const recordExecutionTerminal = internalMutation({\n\targs: {\n\t\trunId: v.id('approvalRuns'),\n\t\toutcome: v.union(\n\t\t\tv.literal(APPROVAL_EXECUTION_STATES[1]),\n\t\t\tv.literal(APPROVAL_EXECUTION_STATES[3]),\n\t\t),\n\t\tfailedStepKey: v.optional(zodToConvex(approvalName)),\n\t},\n\treturns: v.null(),\n\thandler: async (ctx, input) => {\n\t\tconst run = await ctx.db.get(input.runId)\n\t\tif (!run) throw new Error('Approval request not found')\n\t\tawait ctx.db.patch(run._id, {\n\t\t\texecutionFailedStepKey:\n\t\t\t\tinput.outcome === 'failed' ? input.failedStepKey : undefined,\n\t\t\tupdatedAt: Date.now(),\n\t\t})\n\t\tawait logApprovalTransition(ctx, {\n\t\t\taction: `approval.execution.${input.outcome}`,\n\t\t\trunId: run._id,\n\t\t\tresourceType: run.resourceType,\n\t\t\tresourceRef: run.resourceRef,\n\t\t\ttransition: `execution:${input.outcome}`,\n\t\t\tseverity: input.outcome === 'failed' ? 'error' : 'info',\n\t\t})\n\t\treturn null\n\t},\n})\n\nconst approvalWorkflow = new WorkflowManager(components.workflow)\n\nfunction normalizeWorkflowStatus(\n\tstatus: Awaited<ReturnType<typeof approvalWorkflow.status>> | null,\n) {\n\tif (!status) return null\n\tswitch (status.type) {\n\t\tcase 'failed':\n\t\t\treturn { type: 'failed' as const, error: status.error }\n\t\tcase 'inProgress':\n\t\tcase 'completed':\n\t\tcase 'canceled':\n\t\t\treturn { type: status.type }\n\t}\n}\n\nfunction approvalRunValidator() {\n\treturn v.object({\n\t\t_id: v.id('approvalRuns'),\n\t\t_creationTime: v.number(),\n\t\t...zodToConvex(approvalRunDocument).fields,\n\t})\n}\n\nfunction workflowStatusValidator() {\n\treturn v.union(\n\t\tv.object({ type: v.literal(APPROVAL_EXECUTION_STATES[0]) }),\n\t\tv.object({ type: v.literal(APPROVAL_EXECUTION_STATES[1]) }),\n\t\tv.object({ type: v.literal(APPROVAL_EXECUTION_STATES[2]) }),\n\t\tv.object({\n\t\t\ttype: v.literal(APPROVAL_EXECUTION_STATES[3]),\n\t\t\terror: v.string(),\n\t\t}),\n\t)\n}\n\nfunction approvalStatusValidator() {\n\treturn v.object({\n\t\trun: approvalRunValidator(),\n\t\texecution: v.union(v.null(), workflowStatusValidator()),\n\t})\n}\n\nfunction assertCompatible(actual: string, expected: string): void {\n\tif (actual !== expected)\n\t\tthrow new Error(\n\t\t\t`Approval workflow compatibility mismatch: expected ${expected}, received ${actual}`,\n\t\t)\n}\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ import{APPROVAL_ACTOR_DECISION_INDEX as e,APPROVAL_DECISION_HISTORY_INDEX as t}from"./constants.mjs";import{approvalDecisionDocument as n,approvalRunDocument as r}from"./validators.mjs";import{zodToConvex as i}from"convex-helpers/server/zod4";import{defineSchema as a,defineTable as o}from"convex/server";var s=a({approvalRuns:o(i(r)).index(`by_resourceType_and_resourceRef`,[`resourceType`,`resourceRef`]).index(`by_scopeRef_and_state`,[`scopeRef`,`state`]).index(`by_state_and_expiresAt`,[`state`,`expiresAt`]),approvalDecisions:o(i(n)).index(e,[`runId`,`stepKey`,`actor.actorRef`]).index(`by_runId_and_stepKey_and_decidedAt`,[`runId`,`stepKey`,`decidedAt`]).index(t,[`runId`,`decidedAt`])});export{s as default};
@@ -1,6 +1,6 @@
1
1
  import { z } from "zod";
2
2
  declare namespace validators_d_exports {
3
- export { ApprovalActor, ApprovalMetadata, ApprovalWorkflowDescriptor, approvalActionCallback, approvalActor, approvalBranchStep, approvalCallback, approvalCallbackKind, approvalCallbackStep, approvalDecision, approvalDecisionDocument, approvalDecisionStep, approvalMetadata, approvalMutationCallback, approvalName, approvalNotifyStep, approvalQuorum, approvalQuorumKind, approvalReason, approvalReference, approvalRunDocument, approvalRunState, approvalStepKind, approvalWorkflowDescriptor, approvalWorkflowStep };
3
+ export { ApprovalActor, ApprovalCallbackInput, ApprovalMetadata, ApprovalWorkflowDescriptor, approvalActionCallback, approvalActor, approvalBranchStep, approvalCallback, approvalCallbackArgs, approvalCallbackInput, approvalCallbackKind, approvalCallbackStep, approvalDecision, approvalDecisionDocument, approvalDecisionStep, approvalMetadata, approvalMutationCallback, approvalName, approvalNotifyStep, approvalQuorum, approvalQuorumKind, approvalReason, approvalReference, approvalRunDocument, approvalRunState, approvalStepKind, approvalWorkflowDescriptor, approvalWorkflowStep };
4
4
  }
5
5
  declare const approvalRunState: z.ZodEnum<{
6
6
  approved: "approved";
@@ -31,6 +31,122 @@ declare const approvalReference: z.ZodString;
31
31
  declare const approvalName: z.ZodString;
32
32
  declare const approvalReason: z.ZodString;
33
33
  declare const approvalMetadata: z.ZodRecord<z.ZodString, z.ZodString>;
34
+ declare const approvalCallbackInput: z.ZodObject<{
35
+ runId: z.ZodString;
36
+ scopeRef: z.ZodString;
37
+ resourceType: z.ZodString;
38
+ resourceRef: z.ZodString;
39
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
40
+ decision: z.ZodOptional<z.ZodObject<{
41
+ stepKey: z.ZodString;
42
+ outcome: z.ZodUnion<readonly [z.ZodEnum<{
43
+ approved: "approved";
44
+ rejected: "rejected";
45
+ }>, z.ZodLiteral<"expired">]>;
46
+ evidence: z.ZodArray<z.ZodObject<{
47
+ stepKey: z.ZodString;
48
+ actorRef: z.ZodString;
49
+ decision: z.ZodEnum<{
50
+ approved: "approved";
51
+ rejected: "rejected";
52
+ }>;
53
+ reason: z.ZodOptional<z.ZodString>;
54
+ decidedAt: z.ZodNumber;
55
+ }, z.core.$strict>>;
56
+ terminalEvidence: z.ZodOptional<z.ZodObject<{
57
+ actorRef: z.ZodString;
58
+ decision: z.ZodEnum<{
59
+ approved: "approved";
60
+ rejected: "rejected";
61
+ }>;
62
+ reason: z.ZodOptional<z.ZodString>;
63
+ decidedAt: z.ZodNumber;
64
+ }, z.core.$strict>>;
65
+ }, z.core.$strict>>;
66
+ }, z.core.$strict>;
67
+ /** Convex argument validator for approval mutation, action, and notify callbacks. */
68
+ declare const approvalCallbackArgs: import("convex/values").VObject<{
69
+ runId: string;
70
+ scopeRef: string;
71
+ resourceType: string;
72
+ resourceRef: string;
73
+ metadata?: {
74
+ [x: string]: string;
75
+ } | undefined;
76
+ decision?: {
77
+ stepKey: string;
78
+ outcome: "approved" | "expired" | "rejected";
79
+ evidence: {
80
+ stepKey: string;
81
+ actorRef: string;
82
+ decision: "approved" | "rejected";
83
+ reason?: string | undefined;
84
+ decidedAt: number;
85
+ }[];
86
+ terminalEvidence?: {
87
+ actorRef: string;
88
+ decision: "approved" | "rejected";
89
+ reason?: string | undefined;
90
+ decidedAt: number;
91
+ } | undefined;
92
+ } | undefined;
93
+ }, {
94
+ runId: import("convex/values").VString<string, "required">;
95
+ scopeRef: import("convex/values").VString<string, "required">;
96
+ resourceType: import("convex/values").VString<string, "required">;
97
+ resourceRef: import("convex/values").VString<string, "required">;
98
+ metadata: import("convex/values").VRecord<Record<string, string> | undefined, import("convex/values").VString<string, "required">, import("convex/values").VString<string, "required">, "optional", string>;
99
+ decision: import("convex/values").VObject<{
100
+ stepKey: string;
101
+ outcome: "approved" | "expired" | "rejected";
102
+ evidence: {
103
+ stepKey: string;
104
+ actorRef: string;
105
+ decision: "approved" | "rejected";
106
+ reason?: string | undefined;
107
+ decidedAt: number;
108
+ }[];
109
+ terminalEvidence?: {
110
+ actorRef: string;
111
+ decision: "approved" | "rejected";
112
+ reason?: string | undefined;
113
+ decidedAt: number;
114
+ } | undefined;
115
+ } | undefined, {
116
+ stepKey: import("convex/values").VString<string, "required">;
117
+ outcome: import("convex/values").VUnion<"approved" | "expired" | "rejected", [import("convex/values").VUnion<"approved" | "rejected", (import("convex/values").VLiteral<"approved", "required"> | import("convex/values").VLiteral<"rejected", "required">)[], "required", never>, import("convex/values").VLiteral<"expired", "required">], "required", never>;
118
+ evidence: import("convex/values").VArray<{
119
+ stepKey: string;
120
+ actorRef: string;
121
+ decision: "approved" | "rejected";
122
+ reason?: string | undefined;
123
+ decidedAt: number;
124
+ }[], import("convex/values").VObject<{
125
+ stepKey: string;
126
+ actorRef: string;
127
+ decision: "approved" | "rejected";
128
+ reason?: string | undefined;
129
+ decidedAt: number;
130
+ }, {
131
+ stepKey: import("convex/values").VString<string, "required">;
132
+ actorRef: import("convex/values").VString<string, "required">;
133
+ decision: import("convex/values").VUnion<"approved" | "rejected", (import("convex/values").VLiteral<"approved", "required"> | import("convex/values").VLiteral<"rejected", "required">)[], "required", never>;
134
+ reason: import("convex/values").VString<string | undefined, "optional">;
135
+ decidedAt: import("convex/values").VFloat64<number, "required">;
136
+ }, "required", "actorRef" | "decidedAt" | "decision" | "reason" | "stepKey">, "required">;
137
+ terminalEvidence: import("convex/values").VObject<{
138
+ actorRef: string;
139
+ decision: "approved" | "rejected";
140
+ reason?: string | undefined;
141
+ decidedAt: number;
142
+ } | undefined, {
143
+ actorRef: import("convex/values").VString<string, "required">;
144
+ decision: import("convex/values").VUnion<"approved" | "rejected", (import("convex/values").VLiteral<"approved", "required"> | import("convex/values").VLiteral<"rejected", "required">)[], "required", never>;
145
+ reason: import("convex/values").VString<string | undefined, "optional">;
146
+ decidedAt: import("convex/values").VFloat64<number, "required">;
147
+ }, "optional", "actorRef" | "decidedAt" | "decision" | "reason">;
148
+ }, "optional", "evidence" | "outcome" | "stepKey" | "terminalEvidence" | "terminalEvidence.actorRef" | "terminalEvidence.decidedAt" | "terminalEvidence.decision" | "terminalEvidence.reason">;
149
+ }, "required", "decision" | "decision.evidence" | "decision.outcome" | "decision.stepKey" | "decision.terminalEvidence" | "decision.terminalEvidence.actorRef" | "decision.terminalEvidence.decidedAt" | "decision.terminalEvidence.decision" | "decision.terminalEvidence.reason" | "metadata" | "resourceRef" | "resourceType" | "runId" | "scopeRef" | `metadata.${string}`>;
34
150
  declare const approvalActor: z.ZodObject<{
35
151
  actorRef: z.ZodString;
36
152
  capabilities: z.ZodArray<z.ZodString>;
@@ -297,6 +413,7 @@ declare const approvalDecisionDocument: z.ZodObject<{
297
413
  type ApprovalWorkflowDescriptor = z.infer<typeof approvalWorkflowDescriptor>;
298
414
  type ApprovalActor = z.infer<typeof approvalActor>;
299
415
  type ApprovalMetadata = z.infer<typeof approvalMetadata>;
416
+ type ApprovalCallbackInput = Readonly<z.infer<typeof approvalCallbackInput>>;
300
417
  //#endregion
301
- export { ApprovalActor, ApprovalMetadata, ApprovalWorkflowDescriptor, approvalActionCallback, approvalActor, approvalBranchStep, approvalCallback, approvalCallbackKind, approvalCallbackStep, approvalDecision, approvalDecisionDocument, approvalDecisionStep, approvalMetadata, approvalMutationCallback, approvalName, approvalNotifyStep, approvalQuorum, approvalQuorumKind, approvalReason, approvalReference, approvalRunDocument, approvalRunState, approvalStepKind, approvalWorkflowDescriptor, approvalWorkflowStep, validators_d_exports };
418
+ export { ApprovalActor, ApprovalCallbackInput, ApprovalMetadata, ApprovalWorkflowDescriptor, approvalActionCallback, approvalActor, approvalBranchStep, approvalCallback, approvalCallbackArgs, approvalCallbackInput, approvalCallbackKind, approvalCallbackStep, approvalDecision, approvalDecisionDocument, approvalDecisionStep, approvalMetadata, approvalMutationCallback, approvalName, approvalNotifyStep, approvalQuorum, approvalQuorumKind, approvalReason, approvalReference, approvalRunDocument, approvalRunState, approvalStepKind, approvalWorkflowDescriptor, approvalWorkflowStep, validators_d_exports };
302
419
  //# sourceMappingURL=validators.d.mts.map
@@ -1,2 +1,2 @@
1
- import{APPROVAL_CALLBACK_KINDS as e,APPROVAL_DECISIONS as t,APPROVAL_QUORUM_KINDS as n,APPROVAL_RUN_STATES as r,APPROVAL_STEP_KINDS as i}from"./constants.mjs";import{zid as a}from"convex-helpers/server/zod4";import{z as o}from"zod";const s=o.enum(r),c=o.enum(t),l=o.enum(i),u=o.enum(e),d=o.enum(n),f=o.string().trim().min(1).max(256),p=o.string().trim().min(1).max(96).regex(/^[A-Za-z][A-Za-z0-9._-]*$/),m=o.string().trim().min(1).max(500),h=o.record(o.string().min(1).max(64).regex(/^(?![$_])[\x20-\x7E]+$/),o.string().max(512)).refine(e=>Object.keys(e).length<=32,`Metadata may contain at most 32 entries`),g=o.object({actorRef:f,capabilities:o.array(p).max(32),metadata:h.optional()}).strict(),_=o.object({kind:o.literal(`mutation`),handle:f,retry:o.boolean()}).strict(),v=o.object({kind:o.literal(`action`),handle:f,retry:o.boolean()}).strict(),y=o.discriminatedUnion(`kind`,[_,v]),b=o.object({kind:d,approvals:o.number().int().positive().max(8)}).strict(),x=o.discriminatedUnion(`kind`,[o.object({kind:o.literal(`mutation`),key:p,callback:_}).strict(),o.object({kind:o.literal(`action`),key:p,callback:v}).strict()]),S=o.object({kind:o.literal(`notify`),key:p,callback:v}).strict(),C=o.object({kind:o.literal(`decision`),key:p,decisions:o.array(c).min(1).max(8),quorum:b,makerChecker:o.boolean(),expiresAfterMs:o.number().int().positive().optional()}).strict(),w=o.object({kind:o.literal(`branch`),key:p,approvedStepKey:p,rejectedStepKey:p}).strict(),T=o.discriminatedUnion(`kind`,[x,S,C,w]),E=o.object({schemaVersion:o.literal(1),compatibilityKey:p,name:p,steps:o.array(T).min(1).max(32)}).strict().superRefine((e,t)=>{let n=new Set,r=new Map(e.steps.map(e=>[e.key,e])),i=new Map;for(let[r,i]of e.steps.entries())n.has(i.key)&&t.addIssue({code:`custom`,message:`Duplicate workflow step key: ${i.key}`,path:[`steps`,r,`key`]}),n.add(i.key),i.kind===`decision`&&new Set(i.decisions).size!==i.decisions.length&&t.addIssue({code:`custom`,message:`Duplicate decision value in step: ${i.key}`,path:[`steps`,r,`decisions`]});for(let[n,a]of e.steps.entries())if(a.kind===`branch`){e.steps[n-1]?.kind!==`decision`&&t.addIssue({code:`custom`,message:`Branch must immediately follow a decision: ${a.key}`,path:[`steps`,n]});for(let o of[a.approvedStepKey,a.rejectedStepKey]){let a=r.get(o),s=e.steps.findIndex(e=>e.key===o);a?a.kind!==`mutation`&&a.kind!==`action`&&a.kind!==`notify`?t.addIssue({code:`custom`,message:`Branch target must be a callback step: ${o}`,path:[`steps`,n]}):s<=n&&t.addIssue({code:`custom`,message:`Branch target must be declared after its branch: ${o}`,path:[`steps`,n]}):t.addIssue({code:`custom`,message:`Unknown branch target: ${o}`,path:[`steps`,n]}),i.set(o,(i.get(o)??0)+1)}}for(let[e,n]of i)n!==1&&t.addIssue({code:`custom`,message:`Branch callback must belong to exactly one branch: ${e}`,path:[`steps`]})}),D=o.object({scopeRef:f,resourceType:p,resourceRef:f,requester:g,metadata:h.optional(),workflow:E,state:s,currentStepKey:p.optional(),executionFailedStepKey:p.optional(),expiresAt:o.number().optional(),workflowId:f.optional(),createdAt:o.number(),updatedAt:o.number(),terminalAt:o.number().optional()}).strict(),O=o.object({runId:a(`approvalRuns`),stepKey:p,actor:g,decision:c,reason:m.optional(),decidedAt:o.number()}).strict();export{v as approvalActionCallback,g as approvalActor,w as approvalBranchStep,y as approvalCallback,u as approvalCallbackKind,x as approvalCallbackStep,c as approvalDecision,O as approvalDecisionDocument,C as approvalDecisionStep,h as approvalMetadata,_ as approvalMutationCallback,p as approvalName,S as approvalNotifyStep,b as approvalQuorum,d as approvalQuorumKind,m as approvalReason,f as approvalReference,D as approvalRunDocument,s as approvalRunState,l as approvalStepKind,E as approvalWorkflowDescriptor,T as approvalWorkflowStep};
1
+ import{APPROVAL_CALLBACK_KINDS as e,APPROVAL_DECISIONS as t,APPROVAL_QUORUM_KINDS as n,APPROVAL_RUN_STATES as r,APPROVAL_STEP_KINDS as i}from"./constants.mjs";import{zid as a,zodToConvex as o}from"convex-helpers/server/zod4";import{z as s}from"zod";const c=s.enum(r),l=s.enum(t),u=s.enum(i),d=s.enum(e),f=s.enum(n),p=s.string().trim().min(1).max(256),m=s.string().trim().min(1).max(96).regex(/^[A-Za-z][A-Za-z0-9._-]*$/),h=s.string().trim().min(1).max(500),g=s.record(s.string().min(1).max(64).regex(/^(?![$_])[\x20-\x7E]+$/),s.string().max(512)).refine(e=>Object.keys(e).length<=32,`Metadata may contain at most 32 entries`),_=s.object({stepKey:m,actorRef:p,decision:l,reason:h.optional(),decidedAt:s.number()}).strict(),v=_.omit({stepKey:!0}),y=s.object({runId:p,scopeRef:p,resourceType:m,resourceRef:p,metadata:g.optional(),decision:s.object({stepKey:m,outcome:s.union([l,s.literal(`expired`)]),evidence:s.array(_),terminalEvidence:v.optional()}).strict().optional()}).strict(),b=o(y),x=s.object({actorRef:p,capabilities:s.array(m).max(32),metadata:g.optional()}).strict(),S=s.object({kind:s.literal(`mutation`),handle:p,retry:s.boolean()}).strict(),C=s.object({kind:s.literal(`action`),handle:p,retry:s.boolean()}).strict(),w=s.discriminatedUnion(`kind`,[S,C]),T=s.object({kind:f,approvals:s.number().int().positive().max(8)}).strict(),E=s.discriminatedUnion(`kind`,[s.object({kind:s.literal(`mutation`),key:m,callback:S}).strict(),s.object({kind:s.literal(`action`),key:m,callback:C}).strict()]),D=s.object({kind:s.literal(`notify`),key:m,callback:C}).strict(),O=s.object({kind:s.literal(`decision`),key:m,decisions:s.array(l).min(1).max(8),quorum:T,makerChecker:s.boolean(),expiresAfterMs:s.number().int().positive().optional()}).strict(),k=s.object({kind:s.literal(`branch`),key:m,approvedStepKey:m,rejectedStepKey:m}).strict(),A=s.discriminatedUnion(`kind`,[E,D,O,k]),j=s.object({schemaVersion:s.literal(1),compatibilityKey:m,name:m,steps:s.array(A).min(1).max(32)}).strict().superRefine((e,t)=>{let n=new Set,r=new Map(e.steps.map(e=>[e.key,e])),i=new Map;for(let[r,i]of e.steps.entries())n.has(i.key)&&t.addIssue({code:`custom`,message:`Duplicate workflow step key: ${i.key}`,path:[`steps`,r,`key`]}),n.add(i.key),i.kind===`decision`&&new Set(i.decisions).size!==i.decisions.length&&t.addIssue({code:`custom`,message:`Duplicate decision value in step: ${i.key}`,path:[`steps`,r,`decisions`]});for(let[n,a]of e.steps.entries())if(a.kind===`branch`){e.steps[n-1]?.kind!==`decision`&&t.addIssue({code:`custom`,message:`Branch must immediately follow a decision: ${a.key}`,path:[`steps`,n]});for(let o of[a.approvedStepKey,a.rejectedStepKey]){let a=r.get(o),s=e.steps.findIndex(e=>e.key===o);a?a.kind!==`mutation`&&a.kind!==`action`&&a.kind!==`notify`?t.addIssue({code:`custom`,message:`Branch target must be a callback step: ${o}`,path:[`steps`,n]}):s<=n&&t.addIssue({code:`custom`,message:`Branch target must be declared after its branch: ${o}`,path:[`steps`,n]}):t.addIssue({code:`custom`,message:`Unknown branch target: ${o}`,path:[`steps`,n]}),i.set(o,(i.get(o)??0)+1)}}for(let[e,n]of i)n!==1&&t.addIssue({code:`custom`,message:`Branch callback must belong to exactly one branch: ${e}`,path:[`steps`]})}),M=s.object({scopeRef:p,resourceType:m,resourceRef:p,requester:x,metadata:g.optional(),workflow:j,state:c,currentStepKey:m.optional(),executionFailedStepKey:m.optional(),expiresAt:s.number().optional(),workflowId:p.optional(),createdAt:s.number(),updatedAt:s.number(),terminalAt:s.number().optional()}).strict(),N=s.object({runId:a(`approvalRuns`),stepKey:m,actor:x,decision:l,reason:h.optional(),decidedAt:s.number()}).strict();export{C as approvalActionCallback,x as approvalActor,k as approvalBranchStep,w as approvalCallback,b as approvalCallbackArgs,y as approvalCallbackInput,d as approvalCallbackKind,E as approvalCallbackStep,l as approvalDecision,N as approvalDecisionDocument,O as approvalDecisionStep,g as approvalMetadata,S as approvalMutationCallback,m as approvalName,D as approvalNotifyStep,T as approvalQuorum,f as approvalQuorumKind,h as approvalReason,p as approvalReference,M as approvalRunDocument,c as approvalRunState,u as approvalStepKind,j as approvalWorkflowDescriptor,A as approvalWorkflowStep};
2
2
  //# sourceMappingURL=validators.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"validators.mjs","names":[],"sources":["../../../src/components/approvals/validators.ts"],"sourcesContent":["import { zid } from 'convex-helpers/server/zod4'\nimport { z } from 'zod'\n\nimport {\n\tAPPROVAL_CALLBACK_KINDS,\n\tAPPROVAL_DECISIONS,\n\tAPPROVAL_DESCRIPTOR_SCHEMA_VERSION,\n\tAPPROVAL_QUORUM_KINDS,\n\tAPPROVAL_RUN_STATES,\n\tAPPROVAL_STEP_KINDS,\n\tMAX_APPROVAL_CAPABILITIES,\n\tMAX_APPROVAL_DECISIONS_PER_STEP,\n\tMAX_APPROVAL_METADATA_ENTRIES,\n\tMAX_APPROVAL_METADATA_KEY_LENGTH,\n\tMAX_APPROVAL_METADATA_VALUE_LENGTH,\n\tMAX_APPROVAL_NAME_LENGTH,\n\tMAX_APPROVAL_REASON_LENGTH,\n\tMAX_APPROVAL_REFERENCE_LENGTH,\n\tMAX_APPROVAL_WORKFLOW_STEPS,\n} from './constants'\n\nexport const approvalRunState = z.enum(APPROVAL_RUN_STATES)\nexport const approvalDecision = z.enum(APPROVAL_DECISIONS)\nexport const approvalStepKind = z.enum(APPROVAL_STEP_KINDS)\nexport const approvalCallbackKind = z.enum(APPROVAL_CALLBACK_KINDS)\nexport const approvalQuorumKind = z.enum(APPROVAL_QUORUM_KINDS)\n\nexport const approvalReference = z\n\t.string()\n\t.trim()\n\t.min(1)\n\t.max(MAX_APPROVAL_REFERENCE_LENGTH)\n\nexport const approvalName = z\n\t.string()\n\t.trim()\n\t.min(1)\n\t.max(MAX_APPROVAL_NAME_LENGTH)\n\t.regex(/^[A-Za-z][A-Za-z0-9._-]*$/)\n\nexport const approvalReason = z\n\t.string()\n\t.trim()\n\t.min(1)\n\t.max(MAX_APPROVAL_REASON_LENGTH)\n\nexport const approvalMetadata = z\n\t.record(\n\t\tz\n\t\t\t.string()\n\t\t\t.min(1)\n\t\t\t.max(MAX_APPROVAL_METADATA_KEY_LENGTH)\n\t\t\t.regex(/^(?![$_])[\\x20-\\x7E]+$/),\n\t\tz.string().max(MAX_APPROVAL_METADATA_VALUE_LENGTH),\n\t)\n\t.refine(\n\t\t(value) => Object.keys(value).length <= MAX_APPROVAL_METADATA_ENTRIES,\n\t\t`Metadata may contain at most ${MAX_APPROVAL_METADATA_ENTRIES} entries`,\n\t)\n\nexport const approvalActor = z\n\t.object({\n\t\tactorRef: approvalReference,\n\t\tcapabilities: z.array(approvalName).max(MAX_APPROVAL_CAPABILITIES),\n\t\tmetadata: approvalMetadata.optional(),\n\t})\n\t.strict()\n\nexport const approvalMutationCallback = z\n\t.object({\n\t\tkind: z.literal('mutation'),\n\t\thandle: approvalReference,\n\t\tretry: z.boolean(),\n\t})\n\t.strict()\n\nexport const approvalActionCallback = z\n\t.object({\n\t\tkind: z.literal('action'),\n\t\thandle: approvalReference,\n\t\tretry: z.boolean(),\n\t})\n\t.strict()\n\nexport const approvalCallback = z.discriminatedUnion('kind', [\n\tapprovalMutationCallback,\n\tapprovalActionCallback,\n])\n\nexport const approvalQuorum = z\n\t.object({\n\t\tkind: approvalQuorumKind,\n\t\tapprovals: z.number().int().positive().max(MAX_APPROVAL_DECISIONS_PER_STEP),\n\t})\n\t.strict()\n\nexport const approvalCallbackStep = z.discriminatedUnion('kind', [\n\tz\n\t\t.object({\n\t\t\tkind: z.literal('mutation'),\n\t\t\tkey: approvalName,\n\t\t\tcallback: approvalMutationCallback,\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\tkind: z.literal('action'),\n\t\t\tkey: approvalName,\n\t\t\tcallback: approvalActionCallback,\n\t\t})\n\t\t.strict(),\n])\n\nexport const approvalNotifyStep = z\n\t.object({\n\t\tkind: z.literal('notify'),\n\t\tkey: approvalName,\n\t\tcallback: approvalActionCallback,\n\t})\n\t.strict()\n\nexport const approvalDecisionStep = z\n\t.object({\n\t\tkind: z.literal('decision'),\n\t\tkey: approvalName,\n\t\tdecisions: z\n\t\t\t.array(approvalDecision)\n\t\t\t.min(1)\n\t\t\t.max(MAX_APPROVAL_DECISIONS_PER_STEP),\n\t\tquorum: approvalQuorum,\n\t\tmakerChecker: z.boolean(),\n\t\texpiresAfterMs: z.number().int().positive().optional(),\n\t})\n\t.strict()\n\nexport const approvalBranchStep = z\n\t.object({\n\t\tkind: z.literal('branch'),\n\t\tkey: approvalName,\n\t\tapprovedStepKey: approvalName,\n\t\trejectedStepKey: approvalName,\n\t})\n\t.strict()\n\nexport const approvalWorkflowStep = z.discriminatedUnion('kind', [\n\tapprovalCallbackStep,\n\tapprovalNotifyStep,\n\tapprovalDecisionStep,\n\tapprovalBranchStep,\n])\n\nexport const approvalWorkflowDescriptor = z\n\t.object({\n\t\tschemaVersion: z.literal(APPROVAL_DESCRIPTOR_SCHEMA_VERSION),\n\t\tcompatibilityKey: approvalName,\n\t\tname: approvalName,\n\t\tsteps: z\n\t\t\t.array(approvalWorkflowStep)\n\t\t\t.min(1)\n\t\t\t.max(MAX_APPROVAL_WORKFLOW_STEPS),\n\t})\n\t.strict()\n\t.superRefine((descriptor, context) => {\n\t\tconst keys = new Set<string>()\n\t\tconst stepsByKey = new Map(\n\t\t\tdescriptor.steps.map((step) => [step.key, step] as const),\n\t\t)\n\t\tconst branchTargetOwners = new Map<string, number>()\n\t\tfor (const [index, step] of descriptor.steps.entries()) {\n\t\t\tif (keys.has(step.key))\n\t\t\t\tcontext.addIssue({\n\t\t\t\t\tcode: 'custom',\n\t\t\t\t\tmessage: `Duplicate workflow step key: ${step.key}`,\n\t\t\t\t\tpath: ['steps', index, 'key'],\n\t\t\t\t})\n\t\t\tkeys.add(step.key)\n\t\t\tif (\n\t\t\t\tstep.kind === 'decision' &&\n\t\t\t\tnew Set(step.decisions).size !== step.decisions.length\n\t\t\t)\n\t\t\t\tcontext.addIssue({\n\t\t\t\t\tcode: 'custom',\n\t\t\t\t\tmessage: `Duplicate decision value in step: ${step.key}`,\n\t\t\t\t\tpath: ['steps', index, 'decisions'],\n\t\t\t\t})\n\t\t}\n\t\tfor (const [index, step] of descriptor.steps.entries()) {\n\t\t\tif (step.kind !== 'branch') continue\n\t\t\tif (descriptor.steps[index - 1]?.kind !== 'decision')\n\t\t\t\tcontext.addIssue({\n\t\t\t\t\tcode: 'custom',\n\t\t\t\t\tmessage: `Branch must immediately follow a decision: ${step.key}`,\n\t\t\t\t\tpath: ['steps', index],\n\t\t\t\t})\n\t\t\tfor (const target of [step.approvedStepKey, step.rejectedStepKey]) {\n\t\t\t\tconst targetStep = stepsByKey.get(target)\n\t\t\t\tconst targetIndex = descriptor.steps.findIndex(\n\t\t\t\t\t(candidate) => candidate.key === target,\n\t\t\t\t)\n\t\t\t\tif (!targetStep)\n\t\t\t\t\tcontext.addIssue({\n\t\t\t\t\t\tcode: 'custom',\n\t\t\t\t\t\tmessage: `Unknown branch target: ${target}`,\n\t\t\t\t\t\tpath: ['steps', index],\n\t\t\t\t\t})\n\t\t\t\telse if (\n\t\t\t\t\ttargetStep.kind !== 'mutation' &&\n\t\t\t\t\ttargetStep.kind !== 'action' &&\n\t\t\t\t\ttargetStep.kind !== 'notify'\n\t\t\t\t)\n\t\t\t\t\tcontext.addIssue({\n\t\t\t\t\t\tcode: 'custom',\n\t\t\t\t\t\tmessage: `Branch target must be a callback step: ${target}`,\n\t\t\t\t\t\tpath: ['steps', index],\n\t\t\t\t\t})\n\t\t\t\telse if (targetIndex <= index)\n\t\t\t\t\tcontext.addIssue({\n\t\t\t\t\t\tcode: 'custom',\n\t\t\t\t\t\tmessage: `Branch target must be declared after its branch: ${target}`,\n\t\t\t\t\t\tpath: ['steps', index],\n\t\t\t\t\t})\n\t\t\t\tbranchTargetOwners.set(\n\t\t\t\t\ttarget,\n\t\t\t\t\t(branchTargetOwners.get(target) ?? 0) + 1,\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t\tfor (const [target, owners] of branchTargetOwners) {\n\t\t\tif (owners !== 1)\n\t\t\t\tcontext.addIssue({\n\t\t\t\t\tcode: 'custom',\n\t\t\t\t\tmessage: `Branch callback must belong to exactly one branch: ${target}`,\n\t\t\t\t\tpath: ['steps'],\n\t\t\t\t})\n\t\t}\n\t})\n\nexport const approvalRunDocument = z\n\t.object({\n\t\tscopeRef: approvalReference,\n\t\tresourceType: approvalName,\n\t\tresourceRef: approvalReference,\n\t\trequester: approvalActor,\n\t\tmetadata: approvalMetadata.optional(),\n\t\tworkflow: approvalWorkflowDescriptor,\n\t\tstate: approvalRunState,\n\t\tcurrentStepKey: approvalName.optional(),\n\t\texecutionFailedStepKey: approvalName.optional(),\n\t\texpiresAt: z.number().optional(),\n\t\tworkflowId: approvalReference.optional(),\n\t\tcreatedAt: z.number(),\n\t\tupdatedAt: z.number(),\n\t\tterminalAt: z.number().optional(),\n\t})\n\t.strict()\n\nexport const approvalDecisionDocument = z\n\t.object({\n\t\trunId: zid('approvalRuns'),\n\t\tstepKey: approvalName,\n\t\tactor: approvalActor,\n\t\tdecision: approvalDecision,\n\t\treason: approvalReason.optional(),\n\t\tdecidedAt: z.number(),\n\t})\n\t.strict()\n\nexport type ApprovalWorkflowDescriptor = z.infer<\n\ttypeof approvalWorkflowDescriptor\n>\nexport type ApprovalActor = z.infer<typeof approvalActor>\nexport type ApprovalMetadata = z.infer<typeof approvalMetadata>\n"],"mappings":"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"}
1
+ {"version":3,"file":"validators.mjs","names":[],"sources":["../../../src/components/approvals/validators.ts"],"sourcesContent":["import { zid, zodToConvex } from 'convex-helpers/server/zod4'\nimport { z } from 'zod'\n\nimport {\n\tAPPROVAL_CALLBACK_KINDS,\n\tAPPROVAL_DECISIONS,\n\tAPPROVAL_DESCRIPTOR_SCHEMA_VERSION,\n\tAPPROVAL_QUORUM_KINDS,\n\tAPPROVAL_RUN_STATES,\n\tAPPROVAL_STEP_KINDS,\n\tMAX_APPROVAL_CAPABILITIES,\n\tMAX_APPROVAL_DECISIONS_PER_STEP,\n\tMAX_APPROVAL_METADATA_ENTRIES,\n\tMAX_APPROVAL_METADATA_KEY_LENGTH,\n\tMAX_APPROVAL_METADATA_VALUE_LENGTH,\n\tMAX_APPROVAL_NAME_LENGTH,\n\tMAX_APPROVAL_REASON_LENGTH,\n\tMAX_APPROVAL_REFERENCE_LENGTH,\n\tMAX_APPROVAL_WORKFLOW_STEPS,\n} from './constants'\n\nexport const approvalRunState = z.enum(APPROVAL_RUN_STATES)\nexport const approvalDecision = z.enum(APPROVAL_DECISIONS)\nexport const approvalStepKind = z.enum(APPROVAL_STEP_KINDS)\nexport const approvalCallbackKind = z.enum(APPROVAL_CALLBACK_KINDS)\nexport const approvalQuorumKind = z.enum(APPROVAL_QUORUM_KINDS)\n\nexport const approvalReference = z\n\t.string()\n\t.trim()\n\t.min(1)\n\t.max(MAX_APPROVAL_REFERENCE_LENGTH)\n\nexport const approvalName = z\n\t.string()\n\t.trim()\n\t.min(1)\n\t.max(MAX_APPROVAL_NAME_LENGTH)\n\t.regex(/^[A-Za-z][A-Za-z0-9._-]*$/)\n\nexport const approvalReason = z\n\t.string()\n\t.trim()\n\t.min(1)\n\t.max(MAX_APPROVAL_REASON_LENGTH)\n\nexport const approvalMetadata = z\n\t.record(\n\t\tz\n\t\t\t.string()\n\t\t\t.min(1)\n\t\t\t.max(MAX_APPROVAL_METADATA_KEY_LENGTH)\n\t\t\t.regex(/^(?![$_])[\\x20-\\x7E]+$/),\n\t\tz.string().max(MAX_APPROVAL_METADATA_VALUE_LENGTH),\n\t)\n\t.refine(\n\t\t(value) => Object.keys(value).length <= MAX_APPROVAL_METADATA_ENTRIES,\n\t\t`Metadata may contain at most ${MAX_APPROVAL_METADATA_ENTRIES} entries`,\n\t)\n\nconst approvalCallbackEvidence = z\n\t.object({\n\t\tstepKey: approvalName,\n\t\tactorRef: approvalReference,\n\t\tdecision: approvalDecision,\n\t\treason: approvalReason.optional(),\n\t\tdecidedAt: z.number(),\n\t})\n\t.strict()\n\nconst approvalCallbackTerminalEvidence = approvalCallbackEvidence.omit({\n\tstepKey: true,\n})\n\nexport const approvalCallbackInput = z\n\t.object({\n\t\trunId: approvalReference,\n\t\tscopeRef: approvalReference,\n\t\tresourceType: approvalName,\n\t\tresourceRef: approvalReference,\n\t\tmetadata: approvalMetadata.optional(),\n\t\tdecision: z\n\t\t\t.object({\n\t\t\t\tstepKey: approvalName,\n\t\t\t\toutcome: z.union([approvalDecision, z.literal('expired')]),\n\t\t\t\tevidence: z.array(approvalCallbackEvidence),\n\t\t\t\tterminalEvidence: approvalCallbackTerminalEvidence.optional(),\n\t\t\t})\n\t\t\t.strict()\n\t\t\t.optional(),\n\t})\n\t.strict()\n\n/** Convex argument validator for approval mutation, action, and notify callbacks. */\nexport const approvalCallbackArgs = zodToConvex(approvalCallbackInput)\n\nexport const approvalActor = z\n\t.object({\n\t\tactorRef: approvalReference,\n\t\tcapabilities: z.array(approvalName).max(MAX_APPROVAL_CAPABILITIES),\n\t\tmetadata: approvalMetadata.optional(),\n\t})\n\t.strict()\n\nexport const approvalMutationCallback = z\n\t.object({\n\t\tkind: z.literal('mutation'),\n\t\thandle: approvalReference,\n\t\tretry: z.boolean(),\n\t})\n\t.strict()\n\nexport const approvalActionCallback = z\n\t.object({\n\t\tkind: z.literal('action'),\n\t\thandle: approvalReference,\n\t\tretry: z.boolean(),\n\t})\n\t.strict()\n\nexport const approvalCallback = z.discriminatedUnion('kind', [\n\tapprovalMutationCallback,\n\tapprovalActionCallback,\n])\n\nexport const approvalQuorum = z\n\t.object({\n\t\tkind: approvalQuorumKind,\n\t\tapprovals: z.number().int().positive().max(MAX_APPROVAL_DECISIONS_PER_STEP),\n\t})\n\t.strict()\n\nexport const approvalCallbackStep = z.discriminatedUnion('kind', [\n\tz\n\t\t.object({\n\t\t\tkind: z.literal('mutation'),\n\t\t\tkey: approvalName,\n\t\t\tcallback: approvalMutationCallback,\n\t\t})\n\t\t.strict(),\n\tz\n\t\t.object({\n\t\t\tkind: z.literal('action'),\n\t\t\tkey: approvalName,\n\t\t\tcallback: approvalActionCallback,\n\t\t})\n\t\t.strict(),\n])\n\nexport const approvalNotifyStep = z\n\t.object({\n\t\tkind: z.literal('notify'),\n\t\tkey: approvalName,\n\t\tcallback: approvalActionCallback,\n\t})\n\t.strict()\n\nexport const approvalDecisionStep = z\n\t.object({\n\t\tkind: z.literal('decision'),\n\t\tkey: approvalName,\n\t\tdecisions: z\n\t\t\t.array(approvalDecision)\n\t\t\t.min(1)\n\t\t\t.max(MAX_APPROVAL_DECISIONS_PER_STEP),\n\t\tquorum: approvalQuorum,\n\t\tmakerChecker: z.boolean(),\n\t\texpiresAfterMs: z.number().int().positive().optional(),\n\t})\n\t.strict()\n\nexport const approvalBranchStep = z\n\t.object({\n\t\tkind: z.literal('branch'),\n\t\tkey: approvalName,\n\t\tapprovedStepKey: approvalName,\n\t\trejectedStepKey: approvalName,\n\t})\n\t.strict()\n\nexport const approvalWorkflowStep = z.discriminatedUnion('kind', [\n\tapprovalCallbackStep,\n\tapprovalNotifyStep,\n\tapprovalDecisionStep,\n\tapprovalBranchStep,\n])\n\nexport const approvalWorkflowDescriptor = z\n\t.object({\n\t\tschemaVersion: z.literal(APPROVAL_DESCRIPTOR_SCHEMA_VERSION),\n\t\tcompatibilityKey: approvalName,\n\t\tname: approvalName,\n\t\tsteps: z\n\t\t\t.array(approvalWorkflowStep)\n\t\t\t.min(1)\n\t\t\t.max(MAX_APPROVAL_WORKFLOW_STEPS),\n\t})\n\t.strict()\n\t.superRefine((descriptor, context) => {\n\t\tconst keys = new Set<string>()\n\t\tconst stepsByKey = new Map(\n\t\t\tdescriptor.steps.map((step) => [step.key, step] as const),\n\t\t)\n\t\tconst branchTargetOwners = new Map<string, number>()\n\t\tfor (const [index, step] of descriptor.steps.entries()) {\n\t\t\tif (keys.has(step.key))\n\t\t\t\tcontext.addIssue({\n\t\t\t\t\tcode: 'custom',\n\t\t\t\t\tmessage: `Duplicate workflow step key: ${step.key}`,\n\t\t\t\t\tpath: ['steps', index, 'key'],\n\t\t\t\t})\n\t\t\tkeys.add(step.key)\n\t\t\tif (\n\t\t\t\tstep.kind === 'decision' &&\n\t\t\t\tnew Set(step.decisions).size !== step.decisions.length\n\t\t\t)\n\t\t\t\tcontext.addIssue({\n\t\t\t\t\tcode: 'custom',\n\t\t\t\t\tmessage: `Duplicate decision value in step: ${step.key}`,\n\t\t\t\t\tpath: ['steps', index, 'decisions'],\n\t\t\t\t})\n\t\t}\n\t\tfor (const [index, step] of descriptor.steps.entries()) {\n\t\t\tif (step.kind !== 'branch') continue\n\t\t\tif (descriptor.steps[index - 1]?.kind !== 'decision')\n\t\t\t\tcontext.addIssue({\n\t\t\t\t\tcode: 'custom',\n\t\t\t\t\tmessage: `Branch must immediately follow a decision: ${step.key}`,\n\t\t\t\t\tpath: ['steps', index],\n\t\t\t\t})\n\t\t\tfor (const target of [step.approvedStepKey, step.rejectedStepKey]) {\n\t\t\t\tconst targetStep = stepsByKey.get(target)\n\t\t\t\tconst targetIndex = descriptor.steps.findIndex(\n\t\t\t\t\t(candidate) => candidate.key === target,\n\t\t\t\t)\n\t\t\t\tif (!targetStep)\n\t\t\t\t\tcontext.addIssue({\n\t\t\t\t\t\tcode: 'custom',\n\t\t\t\t\t\tmessage: `Unknown branch target: ${target}`,\n\t\t\t\t\t\tpath: ['steps', index],\n\t\t\t\t\t})\n\t\t\t\telse if (\n\t\t\t\t\ttargetStep.kind !== 'mutation' &&\n\t\t\t\t\ttargetStep.kind !== 'action' &&\n\t\t\t\t\ttargetStep.kind !== 'notify'\n\t\t\t\t)\n\t\t\t\t\tcontext.addIssue({\n\t\t\t\t\t\tcode: 'custom',\n\t\t\t\t\t\tmessage: `Branch target must be a callback step: ${target}`,\n\t\t\t\t\t\tpath: ['steps', index],\n\t\t\t\t\t})\n\t\t\t\telse if (targetIndex <= index)\n\t\t\t\t\tcontext.addIssue({\n\t\t\t\t\t\tcode: 'custom',\n\t\t\t\t\t\tmessage: `Branch target must be declared after its branch: ${target}`,\n\t\t\t\t\t\tpath: ['steps', index],\n\t\t\t\t\t})\n\t\t\t\tbranchTargetOwners.set(\n\t\t\t\t\ttarget,\n\t\t\t\t\t(branchTargetOwners.get(target) ?? 0) + 1,\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t\tfor (const [target, owners] of branchTargetOwners) {\n\t\t\tif (owners !== 1)\n\t\t\t\tcontext.addIssue({\n\t\t\t\t\tcode: 'custom',\n\t\t\t\t\tmessage: `Branch callback must belong to exactly one branch: ${target}`,\n\t\t\t\t\tpath: ['steps'],\n\t\t\t\t})\n\t\t}\n\t})\n\nexport const approvalRunDocument = z\n\t.object({\n\t\tscopeRef: approvalReference,\n\t\tresourceType: approvalName,\n\t\tresourceRef: approvalReference,\n\t\trequester: approvalActor,\n\t\tmetadata: approvalMetadata.optional(),\n\t\tworkflow: approvalWorkflowDescriptor,\n\t\tstate: approvalRunState,\n\t\tcurrentStepKey: approvalName.optional(),\n\t\texecutionFailedStepKey: approvalName.optional(),\n\t\texpiresAt: z.number().optional(),\n\t\tworkflowId: approvalReference.optional(),\n\t\tcreatedAt: z.number(),\n\t\tupdatedAt: z.number(),\n\t\tterminalAt: z.number().optional(),\n\t})\n\t.strict()\n\nexport const approvalDecisionDocument = z\n\t.object({\n\t\trunId: zid('approvalRuns'),\n\t\tstepKey: approvalName,\n\t\tactor: approvalActor,\n\t\tdecision: approvalDecision,\n\t\treason: approvalReason.optional(),\n\t\tdecidedAt: z.number(),\n\t})\n\t.strict()\n\nexport type ApprovalWorkflowDescriptor = z.infer<\n\ttypeof approvalWorkflowDescriptor\n>\nexport type ApprovalActor = z.infer<typeof approvalActor>\nexport type ApprovalMetadata = z.infer<typeof approvalMetadata>\nexport type ApprovalCallbackInput = Readonly<\n\tz.infer<typeof approvalCallbackInput>\n>\n"],"mappings":"yPAqBA,MAAa,EAAmB,EAAE,KAAK,CAAmB,EAC7C,EAAmB,EAAE,KAAK,CAAkB,EAC5C,EAAmB,EAAE,KAAK,CAAmB,EAC7C,EAAuB,EAAE,KAAK,CAAuB,EACrD,EAAqB,EAAE,KAAK,CAAqB,EAEjD,EAAoB,EAC/B,OAAO,CAAC,CACR,KAAK,CAAC,CACN,IAAI,CAAC,CAAC,CACN,IAAA,GAAiC,EAEtB,EAAe,EAC1B,OAAO,CAAC,CACR,KAAK,CAAC,CACN,IAAI,CAAC,CAAC,CACN,IAAA,EAA4B,CAAC,CAC7B,MAAM,2BAA2B,EAEtB,EAAiB,EAC5B,OAAO,CAAC,CACR,KAAK,CAAC,CACN,IAAI,CAAC,CAAC,CACN,IAAA,GAA8B,EAEnB,EAAmB,EAC9B,OACA,EACE,OAAO,CAAC,CACR,IAAI,CAAC,CAAC,CACN,IAAA,EAAoC,CAAC,CACrC,MAAM,wBAAwB,EAChC,EAAE,OAAO,CAAC,CAAC,IAAA,GAAsC,CAClD,CAAC,CACA,OACC,GAAU,OAAO,KAAK,CAAK,CAAC,CAAC,QAAA,GAC9B,yCACD,EAEK,EAA2B,EAC/B,OAAO,CACP,QAAS,EACT,SAAU,EACV,SAAU,EACV,OAAQ,EAAe,SAAS,EAChC,UAAW,EAAE,OAAO,CACrB,CAAC,CAAC,CACD,OAAO,EAEH,EAAmC,EAAyB,KAAK,CACtE,QAAS,EACV,CAAC,EAEY,EAAwB,EACnC,OAAO,CACP,MAAO,EACP,SAAU,EACV,aAAc,EACd,YAAa,EACb,SAAU,EAAiB,SAAS,EACpC,SAAU,EACR,OAAO,CACP,QAAS,EACT,QAAS,EAAE,MAAM,CAAC,EAAkB,EAAE,QAAQ,SAAS,CAAC,CAAC,EACzD,SAAU,EAAE,MAAM,CAAwB,EAC1C,iBAAkB,EAAiC,SAAS,CAC7D,CAAC,CAAC,CACD,OAAO,CAAC,CACR,SAAS,CACZ,CAAC,CAAC,CACD,OAAO,EAGI,EAAuB,EAAY,CAAqB,EAExD,EAAgB,EAC3B,OAAO,CACP,SAAU,EACV,aAAc,EAAE,MAAM,CAAY,CAAC,CAAC,IAAA,EAA6B,EACjE,SAAU,EAAiB,SAAS,CACrC,CAAC,CAAC,CACD,OAAO,EAEI,EAA2B,EACtC,OAAO,CACP,KAAM,EAAE,QAAQ,UAAU,EAC1B,OAAQ,EACR,MAAO,EAAE,QAAQ,CAClB,CAAC,CAAC,CACD,OAAO,EAEI,EAAyB,EACpC,OAAO,CACP,KAAM,EAAE,QAAQ,QAAQ,EACxB,OAAQ,EACR,MAAO,EAAE,QAAQ,CAClB,CAAC,CAAC,CACD,OAAO,EAEI,EAAmB,EAAE,mBAAmB,OAAQ,CAC5D,EACA,CACD,CAAC,EAEY,EAAiB,EAC5B,OAAO,CACP,KAAM,EACN,UAAW,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,IAAA,CAAmC,CAC3E,CAAC,CAAC,CACD,OAAO,EAEI,EAAuB,EAAE,mBAAmB,OAAQ,CAChE,EACE,OAAO,CACP,KAAM,EAAE,QAAQ,UAAU,EAC1B,IAAK,EACL,SAAU,CACX,CAAC,CAAC,CACD,OAAO,EACT,EACE,OAAO,CACP,KAAM,EAAE,QAAQ,QAAQ,EACxB,IAAK,EACL,SAAU,CACX,CAAC,CAAC,CACD,OAAO,CACV,CAAC,EAEY,EAAqB,EAChC,OAAO,CACP,KAAM,EAAE,QAAQ,QAAQ,EACxB,IAAK,EACL,SAAU,CACX,CAAC,CAAC,CACD,OAAO,EAEI,EAAuB,EAClC,OAAO,CACP,KAAM,EAAE,QAAQ,UAAU,EAC1B,IAAK,EACL,UAAW,EACT,MAAM,CAAgB,CAAC,CACvB,IAAI,CAAC,CAAC,CACN,IAAA,CAAmC,EACrC,OAAQ,EACR,aAAc,EAAE,QAAQ,EACxB,eAAgB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,CACtD,CAAC,CAAC,CACD,OAAO,EAEI,EAAqB,EAChC,OAAO,CACP,KAAM,EAAE,QAAQ,QAAQ,EACxB,IAAK,EACL,gBAAiB,EACjB,gBAAiB,CAClB,CAAC,CAAC,CACD,OAAO,EAEI,EAAuB,EAAE,mBAAmB,OAAQ,CAChE,EACA,EACA,EACA,CACD,CAAC,EAEY,EAA6B,EACxC,OAAO,CACP,cAAe,EAAE,QAAA,CAA0C,EAC3D,iBAAkB,EAClB,KAAM,EACN,MAAO,EACL,MAAM,CAAoB,CAAC,CAC3B,IAAI,CAAC,CAAC,CACN,IAAA,EAA+B,CAClC,CAAC,CAAC,CACD,OAAO,CAAC,CACR,aAAa,EAAY,IAAY,CACrC,IAAM,EAAO,IAAI,IACX,EAAa,IAAI,IACtB,EAAW,MAAM,IAAK,GAAS,CAAC,EAAK,IAAK,CAAI,CAAU,CACzD,EACM,EAAqB,IAAI,IAC/B,IAAK,GAAM,CAAC,EAAO,KAAS,EAAW,MAAM,QAAQ,EAChD,EAAK,IAAI,EAAK,GAAG,GACpB,EAAQ,SAAS,CAChB,KAAM,SACN,QAAS,gCAAgC,EAAK,MAC9C,KAAM,CAAC,QAAS,EAAO,KAAK,CAC7B,CAAC,EACF,EAAK,IAAI,EAAK,GAAG,EAEhB,EAAK,OAAS,YACd,IAAI,IAAI,EAAK,SAAS,CAAC,CAAC,OAAS,EAAK,UAAU,QAEhD,EAAQ,SAAS,CAChB,KAAM,SACN,QAAS,qCAAqC,EAAK,MACnD,KAAM,CAAC,QAAS,EAAO,WAAW,CACnC,CAAC,EAEH,IAAK,GAAM,CAAC,EAAO,KAAS,EAAW,MAAM,QAAQ,EAChD,KAAK,OAAS,SAClB,CAAI,EAAW,MAAM,EAAQ,EAAE,EAAE,OAAS,YACzC,EAAQ,SAAS,CAChB,KAAM,SACN,QAAS,8CAA8C,EAAK,MAC5D,KAAM,CAAC,QAAS,CAAK,CACtB,CAAC,EACF,IAAK,IAAM,IAAU,CAAC,EAAK,gBAAiB,EAAK,eAAe,EAAG,CAClE,IAAM,EAAa,EAAW,IAAI,CAAM,EAClC,EAAc,EAAW,MAAM,UACnC,GAAc,EAAU,MAAQ,CAClC,EACK,EAOJ,EAAW,OAAS,YACpB,EAAW,OAAS,UACpB,EAAW,OAAS,SAEpB,EAAQ,SAAS,CAChB,KAAM,SACN,QAAS,0CAA0C,IACnD,KAAM,CAAC,QAAS,CAAK,CACtB,CAAC,EACO,GAAe,GACvB,EAAQ,SAAS,CAChB,KAAM,SACN,QAAS,oDAAoD,IAC7D,KAAM,CAAC,QAAS,CAAK,CACtB,CAAC,EApBD,EAAQ,SAAS,CAChB,KAAM,SACN,QAAS,0BAA0B,IACnC,KAAM,CAAC,QAAS,CAAK,CACtB,CAAC,EAiBF,EAAmB,IAClB,GACC,EAAmB,IAAI,CAAM,GAAK,GAAK,CACzC,CACD,CAhCE,CAkCH,IAAK,GAAM,CAAC,EAAQ,KAAW,EAC1B,IAAW,GACd,EAAQ,SAAS,CAChB,KAAM,SACN,QAAS,sDAAsD,IAC/D,KAAM,CAAC,OAAO,CACf,CAAC,CAEJ,CAAC,EAEW,EAAsB,EACjC,OAAO,CACP,SAAU,EACV,aAAc,EACd,YAAa,EACb,UAAW,EACX,SAAU,EAAiB,SAAS,EACpC,SAAU,EACV,MAAO,EACP,eAAgB,EAAa,SAAS,EACtC,uBAAwB,EAAa,SAAS,EAC9C,UAAW,EAAE,OAAO,CAAC,CAAC,SAAS,EAC/B,WAAY,EAAkB,SAAS,EACvC,UAAW,EAAE,OAAO,EACpB,UAAW,EAAE,OAAO,EACpB,WAAY,EAAE,OAAO,CAAC,CAAC,SAAS,CACjC,CAAC,CAAC,CACD,OAAO,EAEI,EAA2B,EACtC,OAAO,CACP,MAAO,EAAI,cAAc,EACzB,QAAS,EACT,MAAO,EACP,SAAU,EACV,OAAQ,EAAe,SAAS,EAChC,UAAW,EAAE,OAAO,CACrB,CAAC,CAAC,CACD,OAAO"}
@@ -1,5 +1,5 @@
1
1
  import { ApprovalDecision } from "./constants.mjs";
2
- import { ApprovalWorkflowDescriptor } from "./validators.mjs";
2
+ import { ApprovalCallbackInput, ApprovalWorkflowDescriptor } from "./validators.mjs";
3
3
  import { FunctionReference, FunctionType } from "convex/server";
4
4
  declare namespace workflow_steps_d_exports {
5
5
  export { ApprovalActionStep, ApprovalBranchStep, ApprovalCallbackInput, ApprovalDecisionEvidence, ApprovalDecisionStep, ApprovalDefinition, ApprovalMutationStep, ApprovalNotifyStep, ApprovalWorkflowStep, CreateApprovalHandle, approvalDecisionEventName, callbackReference, compileApprovalDescriptor, evaluateDecisionOutcome, resolveWorkflowStepIndex };
@@ -50,34 +50,11 @@ type ApprovalDecisionEvidence = Readonly<{
50
50
  actorRef: string;
51
51
  decision: ApprovalDecision;
52
52
  }>;
53
- type ApprovalCallbackInput = Readonly<{
54
- runId: string;
55
- scopeRef: string;
56
- resourceType: string;
57
- resourceRef: string;
58
- metadata?: Readonly<Record<string, string>>;
59
- decision?: Readonly<{
60
- stepKey: string;
61
- outcome: ApprovalDecision | 'expired';
62
- evidence: readonly Readonly<{
63
- actorRef: string;
64
- decision: ApprovalDecision;
65
- reason?: string;
66
- decidedAt: number;
67
- }>[];
68
- terminalEvidence?: Readonly<{
69
- actorRef: string;
70
- decision: ApprovalDecision;
71
- reason?: string;
72
- decidedAt: number;
73
- }>;
74
- }>;
75
- }>;
76
53
  declare function approvalDecisionEventName(runId: string, stepKey: string): string;
77
54
  declare function evaluateDecisionOutcome(decisions: readonly ApprovalDecisionEvidence[], approvalsRequired: number): ApprovalDecision | null;
78
55
  declare function resolveWorkflowStepIndex(stepKeys: readonly string[], targetKey: string): number;
79
56
  declare function callbackReference<Type extends FunctionType>(handle: string): FunctionReference<Type, 'internal', ApprovalCallbackInput, unknown>;
80
57
  declare function compileApprovalDescriptor(definition: ApprovalDefinition, createHandle?: CreateApprovalHandle): Promise<Readonly<ApprovalWorkflowDescriptor>>;
81
58
  //#endregion
82
- export { ApprovalActionStep, ApprovalBranchStep, ApprovalCallbackInput, ApprovalDecisionEvidence, ApprovalDecisionStep, ApprovalDefinition, ApprovalMutationStep, ApprovalNotifyStep, ApprovalWorkflowStep, CreateApprovalHandle, approvalDecisionEventName, callbackReference, compileApprovalDescriptor, evaluateDecisionOutcome, resolveWorkflowStepIndex, workflow_steps_d_exports };
59
+ export { ApprovalActionStep, ApprovalBranchStep, type ApprovalCallbackInput, ApprovalDecisionEvidence, ApprovalDecisionStep, ApprovalDefinition, ApprovalMutationStep, ApprovalNotifyStep, ApprovalWorkflowStep, CreateApprovalHandle, approvalDecisionEventName, callbackReference, compileApprovalDescriptor, evaluateDecisionOutcome, resolveWorkflowStepIndex, workflow_steps_d_exports };
83
60
  //# sourceMappingURL=workflow_steps.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"workflow_steps.mjs","names":[],"sources":["../../../src/components/approvals/workflow_steps.ts"],"sourcesContent":["import {\n\tcreateFunctionHandle,\n\ttype FunctionReference,\n\ttype FunctionType,\n} from 'convex/server'\n\nimport type { ApprovalDecision } from './constants'\nimport {\n\tapprovalWorkflowDescriptor,\n\ttype ApprovalWorkflowDescriptor,\n} from './validators'\n\nexport type ApprovalMutationStep = Readonly<{\n\tkind: 'mutation'\n\tkey: string\n\thandler: FunctionReference<'mutation', 'internal'>\n\tretry: boolean\n}>\n\nexport type ApprovalActionStep = Readonly<{\n\tkind: 'action'\n\tkey: string\n\thandler: FunctionReference<'action', 'internal'>\n\tretry: boolean\n}>\n\nexport type ApprovalNotifyStep = Readonly<{\n\tkind: 'notify'\n\tkey: string\n\thandler: FunctionReference<'action', 'internal'>\n\tretry: boolean\n}>\n\nexport type ApprovalDecisionStep = Readonly<{\n\tkind: 'decision'\n\tkey: string\n\tdecisions: readonly ApprovalDecision[]\n\tquorum: Readonly<{ kind: 'count'; approvals: number }>\n\tmakerChecker: boolean\n\texpiresAfterMs?: number\n}>\n\nexport type ApprovalBranchStep = Readonly<{\n\tkind: 'branch'\n\tkey: string\n\tapprovedStepKey: string\n\trejectedStepKey: string\n}>\n\nexport type ApprovalWorkflowStep =\n\t| ApprovalMutationStep\n\t| ApprovalActionStep\n\t| ApprovalNotifyStep\n\t| ApprovalDecisionStep\n\t| ApprovalBranchStep\n\nexport type ApprovalDefinition = Readonly<{\n\tname: string\n\tcompatibilityKey: string\n\tsteps: readonly ApprovalWorkflowStep[]\n}>\n\nexport type CreateApprovalHandle = (\n\treference: FunctionReference<'mutation' | 'action', 'internal'>,\n) => Promise<string>\n\nexport type ApprovalDecisionEvidence = Readonly<{\n\tactorRef: string\n\tdecision: ApprovalDecision\n}>\n\nexport type ApprovalCallbackInput = Readonly<{\n\trunId: string\n\tscopeRef: string\n\tresourceType: string\n\tresourceRef: string\n\tmetadata?: Readonly<Record<string, string>>\n\tdecision?: Readonly<{\n\t\tstepKey: string\n\t\toutcome: ApprovalDecision | 'expired'\n\t\tevidence: readonly Readonly<{\n\t\t\tactorRef: string\n\t\t\tdecision: ApprovalDecision\n\t\t\treason?: string\n\t\t\tdecidedAt: number\n\t\t}>[]\n\t\tterminalEvidence?: Readonly<{\n\t\t\tactorRef: string\n\t\t\tdecision: ApprovalDecision\n\t\t\treason?: string\n\t\t\tdecidedAt: number\n\t\t}>\n\t}>\n}>\n\nexport function approvalDecisionEventName(\n\trunId: string,\n\tstepKey: string,\n): string {\n\treturn `approval:${runId}:${stepKey}`\n}\n\nexport function evaluateDecisionOutcome(\n\tdecisions: readonly ApprovalDecisionEvidence[],\n\tapprovalsRequired: number,\n): ApprovalDecision | null {\n\tif (decisions.some((decision) => decision.decision === 'rejected'))\n\t\treturn 'rejected'\n\treturn decisions.filter((decision) => decision.decision === 'approved')\n\t\t.length >= approvalsRequired\n\t\t? 'approved'\n\t\t: null\n}\n\nexport function resolveWorkflowStepIndex(\n\tstepKeys: readonly string[],\n\ttargetKey: string,\n): number {\n\tconst index = stepKeys.indexOf(targetKey)\n\tif (index === -1)\n\t\tthrow new Error(`Unknown approval workflow step: ${targetKey}`)\n\treturn index\n}\n\nexport function callbackReference<Type extends FunctionType>(\n\thandle: string,\n): FunctionReference<Type, 'internal', ApprovalCallbackInput, unknown> {\n\treturn handle as unknown as FunctionReference<\n\t\tType,\n\t\t'internal',\n\t\tApprovalCallbackInput,\n\t\tunknown\n\t>\n}\n\nexport async function compileApprovalDescriptor(\n\tdefinition: ApprovalDefinition,\n\tcreateHandle: CreateApprovalHandle = createFunctionHandle,\n): Promise<Readonly<ApprovalWorkflowDescriptor>> {\n\tconst steps = await Promise.all(\n\t\tdefinition.steps.map(async (step) => {\n\t\t\tif (step.kind === 'mutation' || step.kind === 'action') {\n\t\t\t\treturn {\n\t\t\t\t\tkind: step.kind,\n\t\t\t\t\tkey: step.key,\n\t\t\t\t\tcallback: {\n\t\t\t\t\t\tkind: step.kind,\n\t\t\t\t\t\thandle: await createHandle(step.handler),\n\t\t\t\t\t\tretry: step.retry,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (step.kind === 'notify') {\n\t\t\t\treturn {\n\t\t\t\t\tkind: step.kind,\n\t\t\t\t\tkey: step.key,\n\t\t\t\t\tcallback: {\n\t\t\t\t\t\tkind: 'action' as const,\n\t\t\t\t\t\thandle: await createHandle(step.handler),\n\t\t\t\t\t\tretry: step.retry,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (step.kind === 'decision') {\n\t\t\t\treturn {\n\t\t\t\t\t...step,\n\t\t\t\t\tdecisions: [...step.decisions],\n\t\t\t\t\tquorum: { ...step.quorum },\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { ...step }\n\t\t}),\n\t)\n\tconst descriptor = approvalWorkflowDescriptor.parse({\n\t\tschemaVersion: 1,\n\t\tcompatibilityKey: definition.compatibilityKey,\n\t\tname: definition.name,\n\t\tsteps,\n\t})\n\treturn deepFreeze(descriptor)\n}\n\nfunction deepFreeze<Value>(value: Value): Readonly<Value> {\n\tif (value && typeof value === 'object') {\n\t\tObject.freeze(value)\n\t\tfor (const nested of Object.values(value)) deepFreeze(nested)\n\t}\n\treturn value\n}\n"],"mappings":"mHA+FA,SAAgB,EACf,EACA,EACS,CACT,MAAO,YAAY,EAAM,GAAG,GAC7B,CAEA,SAAgB,EACf,EACA,EAC0B,CAG1B,OAFI,EAAU,KAAM,GAAa,EAAS,WAAa,UAAU,EACzD,WACD,EAAU,OAAQ,GAAa,EAAS,WAAa,UAAU,CAAC,CACrE,QAAU,EACT,WACA,IACJ,CAEA,SAAgB,EACf,EACA,EACS,CACT,IAAM,EAAQ,EAAS,QAAQ,CAAS,EACxC,GAAI,IAAU,GACb,MAAU,MAAM,mCAAmC,GAAW,EAC/D,OAAO,CACR,CAEA,SAAgB,EACf,EACsE,CACtE,OAAO,CAMR,CAEA,eAAsB,EACrB,EACA,EAAqC,EACW,CAChD,IAAM,EAAQ,MAAM,QAAQ,IAC3B,EAAW,MAAM,IAAI,KAAO,IACvB,EAAK,OAAS,YAAc,EAAK,OAAS,SACtC,CACN,KAAM,EAAK,KACX,IAAK,EAAK,IACV,SAAU,CACT,KAAM,EAAK,KACX,OAAQ,MAAM,EAAa,EAAK,OAAO,EACvC,MAAO,EAAK,KACb,CACD,EAEG,EAAK,OAAS,SACV,CACN,KAAM,EAAK,KACX,IAAK,EAAK,IACV,SAAU,CACT,KAAM,SACN,OAAQ,MAAM,EAAa,EAAK,OAAO,EACvC,MAAO,EAAK,KACb,CACD,EAEG,EAAK,OAAS,WACV,CACN,GAAG,EACH,UAAW,CAAC,GAAG,EAAK,SAAS,EAC7B,OAAQ,CAAE,GAAG,EAAK,MAAO,CAC1B,EAEM,CAAE,GAAG,CAAK,CACjB,CACF,EAOA,OAAO,EANY,EAA2B,MAAM,CACnD,cAAe,EACf,iBAAkB,EAAW,iBAC7B,KAAM,EAAW,KACjB,OACD,CAC2B,CAAC,CAC7B,CAEA,SAAS,EAAkB,EAA+B,CACzD,GAAI,GAAS,OAAO,GAAU,SAAU,CACvC,OAAO,OAAO,CAAK,EACnB,IAAK,IAAM,KAAU,OAAO,OAAO,CAAK,EAAG,EAAW,CAAM,CAC7D,CACA,OAAO,CACR"}
1
+ {"version":3,"file":"workflow_steps.mjs","names":[],"sources":["../../../src/components/approvals/workflow_steps.ts"],"sourcesContent":["import {\n\tcreateFunctionHandle,\n\ttype FunctionReference,\n\ttype FunctionType,\n} from 'convex/server'\n\nimport type { ApprovalDecision } from './constants'\nimport {\n\tapprovalWorkflowDescriptor,\n\ttype ApprovalCallbackInput,\n\ttype ApprovalWorkflowDescriptor,\n} from './validators'\n\nexport type { ApprovalCallbackInput } from './validators'\n\nexport type ApprovalMutationStep = Readonly<{\n\tkind: 'mutation'\n\tkey: string\n\thandler: FunctionReference<'mutation', 'internal'>\n\tretry: boolean\n}>\n\nexport type ApprovalActionStep = Readonly<{\n\tkind: 'action'\n\tkey: string\n\thandler: FunctionReference<'action', 'internal'>\n\tretry: boolean\n}>\n\nexport type ApprovalNotifyStep = Readonly<{\n\tkind: 'notify'\n\tkey: string\n\thandler: FunctionReference<'action', 'internal'>\n\tretry: boolean\n}>\n\nexport type ApprovalDecisionStep = Readonly<{\n\tkind: 'decision'\n\tkey: string\n\tdecisions: readonly ApprovalDecision[]\n\tquorum: Readonly<{ kind: 'count'; approvals: number }>\n\tmakerChecker: boolean\n\texpiresAfterMs?: number\n}>\n\nexport type ApprovalBranchStep = Readonly<{\n\tkind: 'branch'\n\tkey: string\n\tapprovedStepKey: string\n\trejectedStepKey: string\n}>\n\nexport type ApprovalWorkflowStep =\n\t| ApprovalMutationStep\n\t| ApprovalActionStep\n\t| ApprovalNotifyStep\n\t| ApprovalDecisionStep\n\t| ApprovalBranchStep\n\nexport type ApprovalDefinition = Readonly<{\n\tname: string\n\tcompatibilityKey: string\n\tsteps: readonly ApprovalWorkflowStep[]\n}>\n\nexport type CreateApprovalHandle = (\n\treference: FunctionReference<'mutation' | 'action', 'internal'>,\n) => Promise<string>\n\nexport type ApprovalDecisionEvidence = Readonly<{\n\tactorRef: string\n\tdecision: ApprovalDecision\n}>\n\nexport function approvalDecisionEventName(\n\trunId: string,\n\tstepKey: string,\n): string {\n\treturn `approval:${runId}:${stepKey}`\n}\n\nexport function evaluateDecisionOutcome(\n\tdecisions: readonly ApprovalDecisionEvidence[],\n\tapprovalsRequired: number,\n): ApprovalDecision | null {\n\tif (decisions.some((decision) => decision.decision === 'rejected'))\n\t\treturn 'rejected'\n\treturn decisions.filter((decision) => decision.decision === 'approved')\n\t\t.length >= approvalsRequired\n\t\t? 'approved'\n\t\t: null\n}\n\nexport function resolveWorkflowStepIndex(\n\tstepKeys: readonly string[],\n\ttargetKey: string,\n): number {\n\tconst index = stepKeys.indexOf(targetKey)\n\tif (index === -1)\n\t\tthrow new Error(`Unknown approval workflow step: ${targetKey}`)\n\treturn index\n}\n\nexport function callbackReference<Type extends FunctionType>(\n\thandle: string,\n): FunctionReference<Type, 'internal', ApprovalCallbackInput, unknown> {\n\treturn handle as unknown as FunctionReference<\n\t\tType,\n\t\t'internal',\n\t\tApprovalCallbackInput,\n\t\tunknown\n\t>\n}\n\nexport async function compileApprovalDescriptor(\n\tdefinition: ApprovalDefinition,\n\tcreateHandle: CreateApprovalHandle = createFunctionHandle,\n): Promise<Readonly<ApprovalWorkflowDescriptor>> {\n\tconst steps = await Promise.all(\n\t\tdefinition.steps.map(async (step) => {\n\t\t\tif (step.kind === 'mutation' || step.kind === 'action') {\n\t\t\t\treturn {\n\t\t\t\t\tkind: step.kind,\n\t\t\t\t\tkey: step.key,\n\t\t\t\t\tcallback: {\n\t\t\t\t\t\tkind: step.kind,\n\t\t\t\t\t\thandle: await createHandle(step.handler),\n\t\t\t\t\t\tretry: step.retry,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (step.kind === 'notify') {\n\t\t\t\treturn {\n\t\t\t\t\tkind: step.kind,\n\t\t\t\t\tkey: step.key,\n\t\t\t\t\tcallback: {\n\t\t\t\t\t\tkind: 'action' as const,\n\t\t\t\t\t\thandle: await createHandle(step.handler),\n\t\t\t\t\t\tretry: step.retry,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (step.kind === 'decision') {\n\t\t\t\treturn {\n\t\t\t\t\t...step,\n\t\t\t\t\tdecisions: [...step.decisions],\n\t\t\t\t\tquorum: { ...step.quorum },\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { ...step }\n\t\t}),\n\t)\n\tconst descriptor = approvalWorkflowDescriptor.parse({\n\t\tschemaVersion: 1,\n\t\tcompatibilityKey: definition.compatibilityKey,\n\t\tname: definition.name,\n\t\tsteps,\n\t})\n\treturn deepFreeze(descriptor)\n}\n\nfunction deepFreeze<Value>(value: Value): Readonly<Value> {\n\tif (value && typeof value === 'object') {\n\t\tObject.freeze(value)\n\t\tfor (const nested of Object.values(value)) deepFreeze(nested)\n\t}\n\treturn value\n}\n"],"mappings":"mHA0EA,SAAgB,EACf,EACA,EACS,CACT,MAAO,YAAY,EAAM,GAAG,GAC7B,CAEA,SAAgB,EACf,EACA,EAC0B,CAG1B,OAFI,EAAU,KAAM,GAAa,EAAS,WAAa,UAAU,EACzD,WACD,EAAU,OAAQ,GAAa,EAAS,WAAa,UAAU,CAAC,CACrE,QAAU,EACT,WACA,IACJ,CAEA,SAAgB,EACf,EACA,EACS,CACT,IAAM,EAAQ,EAAS,QAAQ,CAAS,EACxC,GAAI,IAAU,GACb,MAAU,MAAM,mCAAmC,GAAW,EAC/D,OAAO,CACR,CAEA,SAAgB,EACf,EACsE,CACtE,OAAO,CAMR,CAEA,eAAsB,EACrB,EACA,EAAqC,EACW,CAChD,IAAM,EAAQ,MAAM,QAAQ,IAC3B,EAAW,MAAM,IAAI,KAAO,IACvB,EAAK,OAAS,YAAc,EAAK,OAAS,SACtC,CACN,KAAM,EAAK,KACX,IAAK,EAAK,IACV,SAAU,CACT,KAAM,EAAK,KACX,OAAQ,MAAM,EAAa,EAAK,OAAO,EACvC,MAAO,EAAK,KACb,CACD,EAEG,EAAK,OAAS,SACV,CACN,KAAM,EAAK,KACX,IAAK,EAAK,IACV,SAAU,CACT,KAAM,SACN,OAAQ,MAAM,EAAa,EAAK,OAAO,EACvC,MAAO,EAAK,KACb,CACD,EAEG,EAAK,OAAS,WACV,CACN,GAAG,EACH,UAAW,CAAC,GAAG,EAAK,SAAS,EAC7B,OAAQ,CAAE,GAAG,EAAK,MAAO,CAC1B,EAEM,CAAE,GAAG,CAAK,CACjB,CACF,EAOA,OAAO,EANY,EAA2B,MAAM,CACnD,cAAe,EACf,iBAAkB,EAAW,iBAC7B,KAAM,EAAW,KACjB,OACD,CAC2B,CAAC,CAC7B,CAEA,SAAS,EAAkB,EAA+B,CACzD,GAAI,GAAS,OAAO,GAAU,SAAU,CACvC,OAAO,OAAO,CAAK,EACnB,IAAK,IAAM,KAAU,OAAO,OAAO,CAAK,EAAG,EAAW,CAAM,CAC7D,CACA,OAAO,CACR"}
@@ -1,4 +1,4 @@
1
- import _default from "../schema.mjs";
1
+ import _default from "../schema.js";
2
2
  import { DataModelFromSchemaDefinition, DocumentByName, SystemTableNames, TableNamesInDataModel } from "convex/server";
3
3
  import { GenericId } from "convex/values";
4
4
  //#region src/components/foundation/_generated/dataModel.d.ts
@@ -1,2 +1 @@
1
1
  import{defineSchema as e}from"convex/server";var t=e({});export{t as default};
2
- //# sourceMappingURL=schema.mjs.map