cvx-kit 0.0.1

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 (135) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +200 -0
  3. package/dist/_virtual/_rolldown/runtime.mjs +1 -0
  4. package/dist/auth.d.mts +353 -0
  5. package/dist/auth.mjs +2 -0
  6. package/dist/auth.mjs.map +1 -0
  7. package/dist/components/approvals/_generated/api.d.mts +47 -0
  8. package/dist/components/approvals/_generated/api.mjs +2 -0
  9. package/dist/components/approvals/_generated/api.mjs.map +1 -0
  10. package/dist/components/approvals/_generated/component.d.mts +297 -0
  11. package/dist/components/approvals/_generated/component.mjs +1 -0
  12. package/dist/components/approvals/_generated/dataModel.d.mts +41 -0
  13. package/dist/components/approvals/_generated/dataModel.mjs +1 -0
  14. package/dist/components/approvals/_generated/server.d.mts +116 -0
  15. package/dist/components/approvals/_generated/server.mjs +2 -0
  16. package/dist/components/approvals/_generated/server.mjs.map +1 -0
  17. package/dist/components/approvals/audit.d.mts +40 -0
  18. package/dist/components/approvals/audit.mjs +2 -0
  19. package/dist/components/approvals/audit.mjs.map +1 -0
  20. package/dist/components/approvals/client.d.mts +98 -0
  21. package/dist/components/approvals/client.mjs +2 -0
  22. package/dist/components/approvals/client.mjs.map +1 -0
  23. package/dist/components/approvals/constants.d.mts +31 -0
  24. package/dist/components/approvals/constants.mjs +2 -0
  25. package/dist/components/approvals/constants.mjs.map +1 -0
  26. package/dist/components/approvals/convex.config.d.mts +5 -0
  27. package/dist/components/approvals/convex.config.mjs +2 -0
  28. package/dist/components/approvals/convex.config.mjs.map +1 -0
  29. package/dist/components/approvals/decisions.d.mts +61 -0
  30. package/dist/components/approvals/decisions.mjs +2 -0
  31. package/dist/components/approvals/decisions.mjs.map +1 -0
  32. package/dist/components/approvals/functions.d.mts +9 -0
  33. package/dist/components/approvals/functions.mjs +2 -0
  34. package/dist/components/approvals/functions.mjs.map +1 -0
  35. package/dist/components/approvals/requests.d.mts +323 -0
  36. package/dist/components/approvals/requests.mjs +2 -0
  37. package/dist/components/approvals/requests.mjs.map +1 -0
  38. package/dist/components/approvals/schema.d.mts +376 -0
  39. package/dist/components/approvals/schema.mjs +2 -0
  40. package/dist/components/approvals/schema.mjs.map +1 -0
  41. package/dist/components/approvals/validators.d.mts +302 -0
  42. package/dist/components/approvals/validators.mjs +2 -0
  43. package/dist/components/approvals/validators.mjs.map +1 -0
  44. package/dist/components/approvals/workflow.d.mts +11 -0
  45. package/dist/components/approvals/workflow.mjs +2 -0
  46. package/dist/components/approvals/workflow.mjs.map +1 -0
  47. package/dist/components/approvals/workflow_steps.d.mts +83 -0
  48. package/dist/components/approvals/workflow_steps.mjs +2 -0
  49. package/dist/components/approvals/workflow_steps.mjs.map +1 -0
  50. package/dist/components/foundation/_generated/api.d.mts +40 -0
  51. package/dist/components/foundation/_generated/api.mjs +2 -0
  52. package/dist/components/foundation/_generated/api.mjs.map +1 -0
  53. package/dist/components/foundation/_generated/component.d.mts +21 -0
  54. package/dist/components/foundation/_generated/component.mjs +1 -0
  55. package/dist/components/foundation/_generated/dataModel.d.mts +41 -0
  56. package/dist/components/foundation/_generated/dataModel.mjs +1 -0
  57. package/dist/components/foundation/_generated/server.d.mts +116 -0
  58. package/dist/components/foundation/_generated/server.mjs +2 -0
  59. package/dist/components/foundation/_generated/server.mjs.map +1 -0
  60. package/dist/components/foundation/client.d.mts +93 -0
  61. package/dist/components/foundation/client.mjs +2 -0
  62. package/dist/components/foundation/client.mjs.map +1 -0
  63. package/dist/components/foundation/convex.config.d.mts +5 -0
  64. package/dist/components/foundation/convex.config.mjs +2 -0
  65. package/dist/components/foundation/convex.config.mjs.map +1 -0
  66. package/dist/components/foundation/functions.d.mts +8 -0
  67. package/dist/components/foundation/functions.mjs +2 -0
  68. package/dist/components/foundation/functions.mjs.map +1 -0
  69. package/dist/components/foundation/modules/command/command.d.mts +47 -0
  70. package/dist/components/foundation/modules/command/command.mjs +2 -0
  71. package/dist/components/foundation/modules/command/command.mjs.map +1 -0
  72. package/dist/components/foundation/modules/observability/observability.d.mts +31 -0
  73. package/dist/components/foundation/modules/observability/observability.mjs +2 -0
  74. package/dist/components/foundation/modules/observability/observability.mjs.map +1 -0
  75. package/dist/components/foundation/modules/query/query.d.mts +24 -0
  76. package/dist/components/foundation/modules/query/query.mjs +2 -0
  77. package/dist/components/foundation/modules/query/query.mjs.map +1 -0
  78. package/dist/components/foundation/result.d.mts +27 -0
  79. package/dist/components/foundation/result.mjs +2 -0
  80. package/dist/components/foundation/result.mjs.map +1 -0
  81. package/dist/components/foundation/schema.d.mts +6 -0
  82. package/dist/components/foundation/schema.mjs +2 -0
  83. package/dist/components/foundation/schema.mjs.map +1 -0
  84. package/dist/components/foundation/telemetry.d.mts +9 -0
  85. package/dist/components/foundation/telemetry.mjs +2 -0
  86. package/dist/components/foundation/telemetry.mjs.map +1 -0
  87. package/dist/errors.d.mts +24 -0
  88. package/dist/errors.mjs +2 -0
  89. package/dist/errors.mjs.map +1 -0
  90. package/dist/index.d.mts +6 -0
  91. package/dist/index.mjs +1 -0
  92. package/dist/triggers.d.mts +27 -0
  93. package/dist/triggers.mjs +2 -0
  94. package/dist/triggers.mjs.map +1 -0
  95. package/dist/zod-table.d.mts +124 -0
  96. package/dist/zod-table.mjs +2 -0
  97. package/dist/zod-table.mjs.map +1 -0
  98. package/package.json +108 -0
  99. package/src/auth.ts +360 -0
  100. package/src/components/approvals/_generated/api.ts +69 -0
  101. package/src/components/approvals/_generated/component.ts +335 -0
  102. package/src/components/approvals/_generated/dataModel.ts +60 -0
  103. package/src/components/approvals/_generated/server.ts +156 -0
  104. package/src/components/approvals/audit.ts +148 -0
  105. package/src/components/approvals/client.ts +321 -0
  106. package/src/components/approvals/constants.ts +51 -0
  107. package/src/components/approvals/convex.config.ts +10 -0
  108. package/src/components/approvals/decisions.ts +376 -0
  109. package/src/components/approvals/functions.ts +27 -0
  110. package/src/components/approvals/requests.ts +240 -0
  111. package/src/components/approvals/schema.ts +23 -0
  112. package/src/components/approvals/validators.ts +272 -0
  113. package/src/components/approvals/workflow.ts +204 -0
  114. package/src/components/approvals/workflow_steps.ts +189 -0
  115. package/src/components/foundation/_generated/api.ts +62 -0
  116. package/src/components/foundation/_generated/component.ts +29 -0
  117. package/src/components/foundation/_generated/dataModel.ts +60 -0
  118. package/src/components/foundation/_generated/server.ts +156 -0
  119. package/src/components/foundation/client.ts +190 -0
  120. package/src/components/foundation/convex.config.ts +3 -0
  121. package/src/components/foundation/functions.ts +10 -0
  122. package/src/components/foundation/modules/command/__tests__/command.test.ts +106 -0
  123. package/src/components/foundation/modules/command/command.ts +154 -0
  124. package/src/components/foundation/modules/observability/__tests__/observability.test.ts +79 -0
  125. package/src/components/foundation/modules/observability/observability.ts +95 -0
  126. package/src/components/foundation/modules/query/__tests__/query.test.ts +25 -0
  127. package/src/components/foundation/modules/query/query.ts +47 -0
  128. package/src/components/foundation/result.ts +77 -0
  129. package/src/components/foundation/schema.ts +4 -0
  130. package/src/components/foundation/telemetry.ts +23 -0
  131. package/src/errors.ts +25 -0
  132. package/src/index.ts +41 -0
  133. package/src/test.ts +36 -0
  134. package/src/triggers.ts +90 -0
  135. package/src/zod-table.ts +197 -0
@@ -0,0 +1,321 @@
1
+ import type {
2
+ FunctionArgs,
3
+ FunctionReference,
4
+ FunctionReturnType,
5
+ GenericDataModel,
6
+ GenericMutationCtx,
7
+ GenericQueryCtx,
8
+ } from 'convex/server'
9
+
10
+ import type { ComponentApi } from './_generated/component'
11
+ import type { ApprovalDecision } from './constants'
12
+ import type {
13
+ ApprovalActor,
14
+ ApprovalMetadata,
15
+ ApprovalWorkflowDescriptor,
16
+ } from './validators'
17
+ import {
18
+ compileApprovalDescriptor,
19
+ type ApprovalActionStep,
20
+ type ApprovalBranchStep,
21
+ type ApprovalDecisionStep,
22
+ type ApprovalDefinition,
23
+ type ApprovalMutationStep,
24
+ type ApprovalNotifyStep,
25
+ type ApprovalWorkflowStep,
26
+ type ApprovalCallbackInput,
27
+ type CreateApprovalHandle,
28
+ } from './workflow_steps'
29
+
30
+ export type ApprovalsOptions = Readonly<{
31
+ createHandle?: CreateApprovalHandle
32
+ }>
33
+
34
+ export type ApprovalStartInput = Readonly<{
35
+ scopeRef: string
36
+ resourceType: string
37
+ resourceRef: string
38
+ requester: ApprovalActor
39
+ metadata?: ApprovalMetadata
40
+ }>
41
+
42
+ export type ApprovalDecisionInput = Readonly<{
43
+ runId: string
44
+ decision: ApprovalDecision
45
+ reason?: string
46
+ }>
47
+
48
+ export type ApprovalEvidenceItem = Readonly<{
49
+ stepKey: string
50
+ actorRef: string
51
+ decision: ApprovalDecision
52
+ reason?: string
53
+ decidedAt: number
54
+ }>
55
+
56
+ export type ApprovalAuditHistoryInput = Readonly<{
57
+ resourceType: string
58
+ resourceRef: string
59
+ limit?: number
60
+ }>
61
+
62
+ export type ApprovalAuditCleanupInput = Readonly<{
63
+ olderThanDays: number
64
+ batchSize: number
65
+ }>
66
+
67
+ export type ApprovalStatus = FunctionReturnType<
68
+ ComponentApi['requests']['status']
69
+ >
70
+
71
+ export class Approvals<Component extends ComponentApi = ComponentApi> {
72
+ private readonly component: Component
73
+ private readonly createHandle: CreateApprovalHandle | undefined
74
+
75
+ constructor(component: Component, options: ApprovalsOptions = {}) {
76
+ this.component = component
77
+ this.createHandle = options.createHandle
78
+ }
79
+
80
+ cleanupAudit<DataModel extends GenericDataModel>(
81
+ ctx: GenericMutationCtx<DataModel>,
82
+ input: ApprovalAuditCleanupInput,
83
+ ): Promise<FunctionReturnType<Component['audit']['cleanup']>> {
84
+ return ctx.runMutation(this.component.audit.cleanup, input)
85
+ }
86
+
87
+ mutation(
88
+ key: string,
89
+ options: Readonly<{
90
+ handler: FunctionReference<
91
+ 'mutation',
92
+ 'internal',
93
+ ApprovalCallbackInput,
94
+ unknown
95
+ >
96
+ retry?: boolean
97
+ }>,
98
+ ): ApprovalMutationStep {
99
+ return Object.freeze({
100
+ kind: 'mutation',
101
+ key,
102
+ handler: options.handler,
103
+ retry: options.retry ?? false,
104
+ })
105
+ }
106
+
107
+ action(
108
+ key: string,
109
+ options: Readonly<{
110
+ handler: FunctionReference<
111
+ 'action',
112
+ 'internal',
113
+ ApprovalCallbackInput,
114
+ unknown
115
+ >
116
+ retry?: boolean
117
+ }>,
118
+ ): ApprovalActionStep {
119
+ return Object.freeze({
120
+ kind: 'action',
121
+ key,
122
+ handler: options.handler,
123
+ retry: options.retry ?? false,
124
+ })
125
+ }
126
+
127
+ notify(
128
+ key: string,
129
+ options: Readonly<{
130
+ handler: FunctionReference<
131
+ 'action',
132
+ 'internal',
133
+ ApprovalCallbackInput,
134
+ unknown
135
+ >
136
+ retry?: boolean
137
+ }>,
138
+ ): ApprovalNotifyStep {
139
+ return Object.freeze({
140
+ kind: 'notify',
141
+ key,
142
+ handler: options.handler,
143
+ retry: options.retry ?? false,
144
+ })
145
+ }
146
+
147
+ decision(
148
+ key: string,
149
+ options: Readonly<{
150
+ decisions: readonly ApprovalDecision[]
151
+ quorum: Readonly<{ kind: 'count'; approvals: number }>
152
+ makerChecker?: boolean
153
+ expiresAfterMs?: number
154
+ }>,
155
+ ): ApprovalDecisionStep {
156
+ return Object.freeze({
157
+ kind: 'decision',
158
+ key,
159
+ decisions: Object.freeze([...options.decisions]),
160
+ quorum: Object.freeze({ ...options.quorum }),
161
+ makerChecker: options.makerChecker ?? false,
162
+ ...(options.expiresAfterMs === undefined
163
+ ? {}
164
+ : { expiresAfterMs: options.expiresAfterMs }),
165
+ })
166
+ }
167
+
168
+ branch(
169
+ key: string,
170
+ options: Readonly<{
171
+ approvedStepKey: string
172
+ rejectedStepKey: string
173
+ }>,
174
+ ): ApprovalBranchStep {
175
+ return Object.freeze({ kind: 'branch', key, ...options })
176
+ }
177
+
178
+ define(
179
+ input: Readonly<{
180
+ name: string
181
+ compatibilityKey?: string
182
+ steps: readonly ApprovalWorkflowStep[]
183
+ }>,
184
+ ): ConfiguredApprovalWorkflow<Component> {
185
+ const definition = freezeDefinition({
186
+ name: input.name,
187
+ compatibilityKey: input.compatibilityKey ?? input.name,
188
+ steps: input.steps,
189
+ })
190
+ return new ConfiguredApprovalWorkflow(
191
+ this.component,
192
+ definition,
193
+ this.createHandle,
194
+ )
195
+ }
196
+ }
197
+
198
+ export class ConfiguredApprovalWorkflow<
199
+ Component extends ComponentApi = ComponentApi,
200
+ > {
201
+ readonly name: string
202
+ readonly compatibilityKey: string
203
+ readonly steps: readonly ApprovalWorkflowStep[]
204
+
205
+ private readonly component: Component
206
+ private readonly definition: ApprovalDefinition
207
+ private readonly createHandle: CreateApprovalHandle | undefined
208
+
209
+ constructor(
210
+ component: Component,
211
+ definition: ApprovalDefinition,
212
+ createHandle?: CreateApprovalHandle,
213
+ ) {
214
+ this.component = component
215
+ this.definition = definition
216
+ this.name = definition.name
217
+ this.compatibilityKey = definition.compatibilityKey
218
+ this.steps = definition.steps
219
+ this.createHandle = createHandle
220
+ Object.freeze(this)
221
+ }
222
+
223
+ descriptor(): Promise<Readonly<ApprovalWorkflowDescriptor>> {
224
+ return compileApprovalDescriptor(this.definition, this.createHandle)
225
+ }
226
+
227
+ async start<DataModel extends GenericDataModel>(
228
+ ctx: GenericMutationCtx<DataModel>,
229
+ input: ApprovalStartInput,
230
+ ): Promise<FunctionReturnType<Component['requests']['start']>> {
231
+ return ctx.runMutation(this.component.requests.start, {
232
+ ...input,
233
+ workflow: await this.descriptor(),
234
+ })
235
+ }
236
+
237
+ decide<DataModel extends GenericDataModel>(
238
+ ctx: GenericMutationCtx<DataModel>,
239
+ input: ApprovalDecisionInput,
240
+ actor: ApprovalActor,
241
+ ): Promise<FunctionReturnType<Component['decisions']['decide']>> {
242
+ return ctx.runMutation(this.component.decisions.decide, {
243
+ ...input,
244
+ actor,
245
+ compatibilityKey: this.compatibilityKey,
246
+ })
247
+ }
248
+
249
+ evidence<DataModel extends GenericDataModel>(
250
+ ctx: GenericQueryCtx<DataModel>,
251
+ runId: string,
252
+ ): Promise<FunctionReturnType<Component['decisions']['list']>> {
253
+ return ctx.runQuery(this.component.decisions.list, { runId })
254
+ }
255
+
256
+ auditHistory<DataModel extends GenericDataModel>(
257
+ ctx: GenericQueryCtx<DataModel>,
258
+ input: ApprovalAuditHistoryInput,
259
+ ): Promise<FunctionReturnType<Component['audit']['history']>> {
260
+ return ctx.runQuery(this.component.audit.history, input)
261
+ }
262
+
263
+ cancel<DataModel extends GenericDataModel>(
264
+ ctx: GenericMutationCtx<DataModel>,
265
+ runId: string,
266
+ actor: ApprovalActor,
267
+ ): Promise<FunctionReturnType<Component['requests']['cancel']>> {
268
+ return ctx.runMutation(this.component.requests.cancel, {
269
+ runId,
270
+ actor,
271
+ compatibilityKey: this.compatibilityKey,
272
+ })
273
+ }
274
+
275
+ status<DataModel extends GenericDataModel>(
276
+ ctx: GenericQueryCtx<DataModel>,
277
+ runId: string,
278
+ ): Promise<ApprovalStatus | null> {
279
+ return ctx.runQuery(this.component.requests.status, {
280
+ runId,
281
+ compatibilityKey: this.compatibilityKey,
282
+ })
283
+ }
284
+
285
+ list<DataModel extends GenericDataModel>(
286
+ ctx: GenericQueryCtx<DataModel>,
287
+ input: FunctionArgs<Component['requests']['list']>,
288
+ ): Promise<FunctionReturnType<Component['requests']['list']>> {
289
+ return ctx.runQuery(this.component.requests.list, input)
290
+ }
291
+
292
+ restart<DataModel extends GenericDataModel>(
293
+ ctx: GenericMutationCtx<DataModel>,
294
+ runId: string,
295
+ ): Promise<FunctionReturnType<Component['requests']['restart']>> {
296
+ return ctx.runMutation(this.component.requests.restart, {
297
+ runId,
298
+ compatibilityKey: this.compatibilityKey,
299
+ })
300
+ }
301
+ }
302
+
303
+ function freezeDefinition(definition: ApprovalDefinition): ApprovalDefinition {
304
+ return Object.freeze({
305
+ ...definition,
306
+ steps: Object.freeze(
307
+ definition.steps.map((step) => {
308
+ if (step.kind === 'decision')
309
+ return Object.freeze({
310
+ ...step,
311
+ decisions: Object.freeze([...step.decisions]),
312
+ quorum: Object.freeze({ ...step.quorum }),
313
+ })
314
+ return Object.freeze({ ...step })
315
+ }),
316
+ ),
317
+ })
318
+ }
319
+
320
+ // Component definition as default export: `import approvals from "cvx-kit/components/approvals"` → app.use(approvals)
321
+ export { default } from "./convex.config"
@@ -0,0 +1,51 @@
1
+ export const APPROVAL_RUN_STATES = [
2
+ 'pending',
3
+ 'approved',
4
+ 'rejected',
5
+ 'expired',
6
+ 'canceled',
7
+ ] as const
8
+
9
+ export const APPROVAL_DECISIONS = ['approved', 'rejected'] as const
10
+
11
+ export const APPROVAL_EXECUTION_STATES = [
12
+ 'inProgress',
13
+ 'completed',
14
+ 'canceled',
15
+ 'failed',
16
+ ] as const
17
+
18
+ export const APPROVAL_STEP_KINDS = [
19
+ 'mutation',
20
+ 'action',
21
+ 'notify',
22
+ 'decision',
23
+ 'branch',
24
+ ] as const
25
+
26
+ export const APPROVAL_QUORUM_KINDS = ['count'] as const
27
+
28
+ export const APPROVAL_CALLBACK_KINDS = ['mutation', 'action'] as const
29
+
30
+ export const APPROVAL_DESCRIPTOR_SCHEMA_VERSION = 1 as const
31
+
32
+ export const APPROVAL_AUDIT_RETENTION_CATEGORY = 'approval-protocol'
33
+ export const MIN_APPROVAL_AUDIT_RETENTION_DAYS = 1
34
+ export const MAX_APPROVAL_AUDIT_RETENTION_DAYS = 3_650
35
+ export const MAX_APPROVAL_AUDIT_CLEANUP_BATCH_SIZE = 100
36
+
37
+ export const MAX_APPROVAL_REFERENCE_LENGTH = 256
38
+ export const MAX_APPROVAL_NAME_LENGTH = 96
39
+ export const MAX_APPROVAL_REASON_LENGTH = 500
40
+ export const MAX_APPROVAL_CAPABILITIES = 32
41
+ export const MAX_APPROVAL_METADATA_ENTRIES = 32
42
+ export const MAX_APPROVAL_METADATA_KEY_LENGTH = 64
43
+ export const MAX_APPROVAL_METADATA_VALUE_LENGTH = 512
44
+ export const MAX_APPROVAL_WORKFLOW_STEPS = 32
45
+ export const MAX_APPROVAL_DECISIONS_PER_STEP = 8
46
+
47
+ export type ApprovalRunState = (typeof APPROVAL_RUN_STATES)[number]
48
+ export type ApprovalDecision = (typeof APPROVAL_DECISIONS)[number]
49
+ export type ApprovalExecutionState = (typeof APPROVAL_EXECUTION_STATES)[number]
50
+ export type ApprovalStepKind = (typeof APPROVAL_STEP_KINDS)[number]
51
+ export type ApprovalCallbackKind = (typeof APPROVAL_CALLBACK_KINDS)[number]
@@ -0,0 +1,10 @@
1
+ import workflow from '@convex-dev/workflow/convex.config'
2
+ import auditLog from 'convex-audit-log/convex.config.js'
3
+ import { defineComponent } from 'convex/server'
4
+
5
+ const approvals = defineComponent('approvals')
6
+
7
+ approvals.use(workflow, { name: 'workflow' })
8
+ approvals.use(auditLog, { name: 'auditLog' })
9
+
10
+ export default approvals