cvx-kit 0.1.7 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/README.md +63 -47
- package/dist/agent-tools.d.mts +5 -5
- package/dist/agent-tools.mjs.map +1 -1
- package/dist/auth.d.mts +39 -289
- package/dist/auth.mjs.map +1 -1
- package/dist/components/approvals/_generated/api.d.mts +3 -4
- package/dist/components/approvals/_generated/api.mjs.map +1 -1
- package/dist/components/approvals/_generated/component.d.mts +1 -2
- package/dist/components/approvals/_generated/dataModel.d.mts +4 -5
- package/dist/components/approvals/_generated/server.d.mts +12 -13
- package/dist/components/approvals/_generated/server.mjs.map +1 -1
- package/dist/components/approvals/audit.d.mts +8 -8
- package/dist/components/approvals/audit.mjs +1 -1
- package/dist/components/approvals/audit.mjs.map +1 -1
- package/dist/components/approvals/client.d.mts +10 -10
- package/dist/components/approvals/client.mjs.map +1 -1
- package/dist/components/approvals/constants.d.mts +30 -30
- package/dist/components/approvals/constants.mjs.map +1 -1
- package/dist/components/approvals/convex.config.mjs.map +1 -1
- package/dist/components/approvals/decisions.d.mts +6 -6
- package/dist/components/approvals/decisions.mjs.map +1 -1
- package/dist/components/approvals/functions.d.mts +3 -3
- package/dist/components/approvals/functions.mjs.map +1 -1
- package/dist/components/approvals/health.d.mts +2 -2
- package/dist/components/approvals/health.mjs.map +1 -1
- package/dist/components/approvals/requests.d.mts +8 -8
- package/dist/components/approvals/requests.mjs.map +1 -1
- package/dist/components/approvals/validators.d.mts +29 -29
- package/dist/components/approvals/validators.mjs +1 -1
- package/dist/components/approvals/validators.mjs.map +1 -1
- package/dist/components/approvals/workflow.d.mts +3 -3
- package/dist/components/approvals/workflow.mjs.map +1 -1
- package/dist/components/approvals/workflow_steps.d.mts +15 -15
- package/dist/components/approvals/workflow_steps.mjs.map +1 -1
- package/dist/components/foundation/_generated/api.d.mts +3 -4
- package/dist/components/foundation/_generated/api.mjs.map +1 -1
- package/dist/components/foundation/_generated/component.d.mts +1 -2
- package/dist/components/foundation/_generated/dataModel.d.mts +4 -5
- package/dist/components/foundation/_generated/server.d.mts +12 -13
- package/dist/components/foundation/_generated/server.mjs.map +1 -1
- package/dist/components/foundation/client.d.mts +21 -13
- package/dist/components/foundation/client.mjs.map +1 -1
- package/dist/components/foundation/convex.config.mjs.map +1 -1
- package/dist/components/foundation/functions.d.mts +2 -2
- package/dist/components/foundation/functions.mjs.map +1 -1
- package/dist/components/foundation/modules/command/command.d.mts +14 -14
- package/dist/components/foundation/modules/command/command.mjs.map +1 -1
- package/dist/components/foundation/modules/command/lifecycle.d.mts +12 -13
- package/dist/components/foundation/modules/command/lifecycle.mjs.map +1 -1
- package/dist/components/foundation/modules/observability/observability.d.mts +4 -4
- package/dist/components/foundation/modules/observability/observability.mjs.map +1 -1
- package/dist/components/foundation/modules/query/query.d.mts +5 -5
- package/dist/components/foundation/modules/query/query.mjs.map +1 -1
- package/dist/components/foundation/operation.d.mts +5 -6
- package/dist/components/foundation/operation.mjs.map +1 -1
- package/dist/components/foundation/result.d.mts +6 -6
- package/dist/components/foundation/result.mjs.map +1 -1
- package/dist/components/foundation/telemetry.d.mts +2 -2
- package/dist/components/foundation/telemetry.mjs.map +1 -1
- package/dist/crud.d.mts +6 -5
- package/dist/crud.mjs.map +1 -1
- package/dist/errors.d.mts +4 -4
- package/dist/errors.mjs.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/middleware.d.mts +2 -3
- package/dist/middleware.mjs.map +1 -1
- package/dist/modules/contracts/contract.d.mts +12 -13
- package/dist/modules/contracts/contract.mjs.map +1 -1
- package/dist/modules/contracts/convex.d.mts +3 -5
- package/dist/modules/contracts/convex.mjs.map +1 -1
- package/dist/modules/contracts/errors.d.mts +8 -9
- package/dist/modules/contracts/errors.mjs +1 -1
- package/dist/modules/contracts/errors.mjs.map +1 -1
- package/dist/modules/contracts/exposure.d.mts +13 -14
- package/dist/modules/contracts/exposure.mjs +1 -1
- package/dist/modules/contracts/exposure.mjs.map +1 -1
- package/dist/modules/contracts/idempotency.d.mts +15 -16
- package/dist/modules/contracts/idempotency.mjs +1 -1
- package/dist/modules/contracts/idempotency.mjs.map +1 -1
- package/dist/modules/contracts/standard.d.mts +2 -3
- package/dist/modules/contracts/standard.mjs.map +1 -1
- package/dist/modules/contracts/workflow.d.mts +26 -27
- package/dist/modules/contracts/workflow.mjs.map +1 -1
- package/dist/modules/effect/api-runtime.d.mts +20 -11
- package/dist/modules/effect/api-runtime.mjs +1 -1
- package/dist/modules/effect/api-runtime.mjs.map +1 -1
- package/dist/modules/effect/api-zod.d.mts +5 -6
- package/dist/modules/effect/api-zod.mjs.map +1 -1
- package/dist/modules/effect/api.d.mts +6 -7
- package/dist/modules/effect/api.mjs.map +1 -1
- package/dist/modules/effect/command.d.mts +10 -7
- package/dist/modules/effect/command.mjs +1 -1
- package/dist/modules/effect/command.mjs.map +1 -1
- package/dist/modules/effect/crud.d.mts +7 -8
- package/dist/modules/effect/crud.mjs.map +1 -1
- package/dist/modules/effect/errors.d.mts +1 -2
- package/dist/modules/effect/errors.mjs.map +1 -1
- package/dist/modules/effect/foundation.d.mts +3 -4
- package/dist/modules/effect/foundation.mjs.map +1 -1
- package/dist/modules/effect/idempotency.d.mts +2 -3
- package/dist/modules/effect/idempotency.mjs.map +1 -1
- package/dist/modules/effect/normalize.d.mts +2 -3
- package/dist/modules/effect/normalize.mjs.map +1 -1
- package/dist/modules/effect/operation.d.mts +17 -18
- package/dist/modules/effect/operation.mjs.map +1 -1
- package/dist/modules/effect/query.d.mts +8 -5
- package/dist/modules/effect/query.mjs +1 -1
- package/dist/modules/effect/query.mjs.map +1 -1
- package/dist/modules/effect/schema.d.mts +8 -9
- package/dist/modules/effect/schema.mjs.map +1 -1
- package/dist/modules/effect/workflow.d.mts +5 -6
- package/dist/modules/effect/workflow.mjs.map +1 -1
- package/dist/oxlint/architecture.d.mts +6 -7
- package/dist/oxlint/architecture.mjs +1 -1
- package/dist/oxlint/architecture.mjs.map +1 -1
- package/dist/oxlint/ast.d.mts +22 -23
- package/dist/oxlint/ast.mjs +1 -1
- package/dist/oxlint/ast.mjs.map +1 -1
- package/dist/oxlint/ownership.d.mts +2 -3
- package/dist/oxlint/ownership.mjs +1 -1
- package/dist/oxlint/ownership.mjs.map +1 -1
- package/dist/oxlint.d.mts +4 -4
- package/dist/oxlint.mjs +1 -1
- package/dist/oxlint.mjs.map +1 -1
- package/dist/state-machine.d.mts +1 -2
- package/dist/state-machine.mjs.map +1 -1
- package/dist/tenancy.d.mts +6 -6
- package/dist/tenancy.mjs.map +1 -1
- package/dist/triggers.d.mts +6 -6
- package/dist/triggers.mjs.map +1 -1
- package/dist/webhooks.d.mts +5 -6
- package/dist/webhooks.mjs.map +1 -1
- package/dist/zod-table.d.mts +10 -10
- package/dist/zod-table.mjs.map +1 -1
- package/docs/architecture.md +3 -3
- package/docs/auth.md +10 -4
- package/docs/command-context.md +150 -0
- package/docs/commands-legacy.md +511 -0
- package/docs/commands.md +113 -451
- package/docs/conventions.md +15 -5
- package/docs/crud.md +4 -0
- package/docs/domain-operations.md +1 -1
- package/docs/effect.md +14 -3
- package/docs/llms.md +69 -45
- package/docs/migration.md +1 -1
- package/docs/oxlint.md +1 -1
- package/docs/upgrading.md +18 -1
- package/docs/zod-table.md +1 -1
- package/package.json +21 -15
- package/scripts/test-packed-auth.mjs +68 -0
- package/scripts/test-packed-effect.mjs +4 -1
- package/scripts/test-packed-ids.mjs +2 -2
- package/dist/node_modules/@standard-schema/spec/dist/index.d.mts +0 -79
package/docs/crud.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# `cvx-kit/crud` — the CRUD command factory
|
|
2
2
|
|
|
3
|
+
> This factory uses the deprecated Promise command facade and remains available
|
|
4
|
+
> for existing consumers. For new Effect commands, use `createEffectCrud` from
|
|
5
|
+
> `cvx-kit/effect`; see [domain integrations](./domain-operations.md).
|
|
6
|
+
|
|
3
7
|
`createCrudCommands` generates the three standard operations every entity
|
|
4
8
|
starts with — create, update, archive — from one zodTable declaration,
|
|
5
9
|
**fully inside the audited command pipeline**: strict command inputs from
|
|
@@ -4,7 +4,7 @@ Declare operations beside their handlers, inject the application's repositories,
|
|
|
4
4
|
|
|
5
5
|
The complete TypeScript module below is mirrored in `test/domain-operation-guide-types.ts` for strict compilation. All TypeScript in this guide belongs to that one module; there are no standalone handler fragments. It uses public `cvx-kit/*` imports, real Convex builders, an injected document repository, and generated references from the native acceptance fixture. Its document schema and generic builders let the example compile independently; an application imports its own `mutation`, `query`, and internal builders from `./_generated/server`. The integrated rename portion imports the exact registry from `test/fixture-effect/convex/integratedRename.ts` and binds its real generated references. The document create/receipt example remains separate.
|
|
6
6
|
|
|
7
|
-
The examples use the
|
|
7
|
+
The examples use the recommended Effect command API even for ordinary handlers. The older `Foundation.Command` facade is deprecated and retained for existing consumers without Effect; use [the migration guide](./commands.md) when moving those domains. Neutral contracts, errors, idempotency, workflow, and tool facades remain available without Effect. Import `cvx-kit/effect` only when the application supplies its Effect peer.
|
|
8
8
|
|
|
9
9
|
## Declare a cohesive domain
|
|
10
10
|
|
package/docs/effect.md
CHANGED
|
@@ -5,7 +5,11 @@ runner. Handlers can return ordinary values, Promises, or Effects. Each
|
|
|
5
5
|
registry returns a lazy Effect from `exec(operation, input, host)`; the API
|
|
6
6
|
adapter provides request services and runs it once.
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
This is the recommended command API. The older `Foundation.Command` facade
|
|
9
|
+
and `exec({ operation, handler })` executor API are deprecated and retained for
|
|
10
|
+
compatibility. Declare handlers inside `command({...})` for new command code.
|
|
11
|
+
|
|
12
|
+
Install Effect explicitly:
|
|
9
13
|
|
|
10
14
|
```sh
|
|
11
15
|
bun add effect@4.0.1
|
|
@@ -377,8 +381,15 @@ registry's lazy Effect to a shared API adapter. A normal async handler works
|
|
|
377
381
|
in the cohesive declaration without a generator; wrap expected Promise failures
|
|
378
382
|
only when you want a typed error channel.
|
|
379
383
|
|
|
380
|
-
The [command
|
|
381
|
-
|
|
384
|
+
The [command guide](./commands.md) documents the current lifecycle and migration
|
|
385
|
+
steps; the [deprecated API reference](./commands-legacy.md) retains old examples.
|
|
386
|
+
The [authentication guide](./auth.md)
|
|
382
387
|
shows how to wrap trusted custom builders with `effectZodApiBuilder`, so auth,
|
|
383
388
|
tenancy, validators, row-level policies, and triggers run through their
|
|
384
389
|
existing builder before Effect request services are provisioned.
|
|
390
|
+
|
|
391
|
+
Optional request context can be added through the existing Effect API adapter's
|
|
392
|
+
`context` callback. Bind selected registries with `commands.withContext(value)`
|
|
393
|
+
and consume `ctx.commands.exec(name, input)` through the application's existing
|
|
394
|
+
function helper names. Keep dependencies local to each feature; explicit execution
|
|
395
|
+
and input-only command handlers remain supported. See [optional context injection](./command-context.md).
|
package/docs/llms.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> Paste this file (installed at `node_modules/cvx-kit/docs/`) into an agent's
|
|
4
4
|
> context when it works on a cvx-kit application. Detailed docs:
|
|
5
5
|
> `architecture.md`, `conventions.md`, `zod-table.md`, `auth.md`,
|
|
6
|
-
> `commands.md`, `triggers.md`, `approvals.md`, `maintainability.md`,
|
|
6
|
+
> `commands.md`, `effect.md`, `domain-operations.md`, `triggers.md`, `approvals.md`, `maintainability.md`,
|
|
7
7
|
> `migration.md` (same directory).
|
|
8
8
|
> Structure, file anatomy, and naming rules → `conventions.md` is
|
|
9
9
|
> authoritative. Restructuring an existing raw project → `migration.md`.
|
|
@@ -22,7 +22,13 @@
|
|
|
22
22
|
cvx-kit is a reusable Convex application kit: zod table boundaries, auth-aware
|
|
23
23
|
function constructors, a trigger registry, an audited command protocol
|
|
24
24
|
(Foundation component), and a declarative approvals component. Peer deps:
|
|
25
|
-
`convex ^1.
|
|
25
|
+
`convex ^1.45.0`, `zod ^4.5.4`; command implementations also install
|
|
26
|
+
`effect >=4.0.1 <5` and import `cvx-kit/effect`.
|
|
27
|
+
|
|
28
|
+
**Command API selection:** use `createEffectFoundation` and declare handlers
|
|
29
|
+
inside `command({...})`. The older `Foundation.Command` Promise facade is
|
|
30
|
+
deprecated. Its compatibility examples live in `commands-legacy.md`; do not
|
|
31
|
+
copy that API into new implementations.
|
|
26
32
|
|
|
27
33
|
## Non-negotiable rules
|
|
28
34
|
|
|
@@ -31,27 +37,27 @@ function constructors, a trigger registry, an audited command protocol
|
|
|
31
37
|
2. **Raw `query`/`mutation`/`action`/`internal*` builders appear only in
|
|
32
38
|
`convex/functions.ts`** (the `createAuthFunctions` call). All other
|
|
33
39
|
functions use `authQuery/authMutation/authAction`, `roleQuery/...`,
|
|
34
|
-
`adminQuery/...` (public) or `systemQuery/systemMutation/systemAction` (internal)
|
|
40
|
+
`adminQuery/...` (public) or `systemQuery/systemMutation/systemAction` (internal),
|
|
41
|
+
wrapped once with `effectZodApiBuilder` when their handlers return Effects.
|
|
35
42
|
This is what guarantees auth, triggers, and bounded reads.
|
|
36
43
|
3. **Every public query returns DTOs** via `<table>.toPublicDto(row)` —
|
|
37
44
|
runtime redaction, not just types.
|
|
38
45
|
4. **Every read is bounded**: `ctx.include(ctx.db.query('t')).matching(...)
|
|
39
46
|
.execute(limit)` with `1 ≤ limit ≤ 100`. `.resolve()` falls back to a full
|
|
40
47
|
table scan — avoid it.
|
|
41
|
-
5. **State changes are commands**:
|
|
42
|
-
`
|
|
43
|
-
`
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
→ operation guard → handler → result parse → aggregates → audit.
|
|
48
|
+
5. **State changes are Effect commands**: declare
|
|
49
|
+
`Command({ context, operations: ({ command }) => ({ ... }), defaults })`.
|
|
50
|
+
Each `command({ input, result, classification, handler, audit })` owns its
|
|
51
|
+
handler; handlers receive `(input, context)`. Execute with
|
|
52
|
+
`commands.exec(operation, input, host)` and return the lazy Effect through a
|
|
53
|
+
shared API builder. Never pass a handler to `exec` or run a nested
|
|
54
|
+
`Effect.runPromise`. Permission uses the injected `checkPermission(host, ...)`;
|
|
55
|
+
guards receive `(context, input)`. Per-operation middleware is one callback,
|
|
56
|
+
`next()` returns an Effect, and `next({ context })` enriches downstream ctx.
|
|
57
|
+
Order: input → context → permission → prepare/replay → middleware → default
|
|
58
|
+
guard → operation guard → handler → result parse → aggregates/audit → completion.
|
|
59
|
+
Audit writes stay in the mutation transaction. Failures must escape the
|
|
60
|
+
mutation for rollback; replay skips middleware, guards, handler, and audit.
|
|
55
61
|
6. **Never write timestamps by hand.** `createdAt`/`updatedAt` are maintained
|
|
56
62
|
by the `timestamps` trigger; `archivedAt` is the app-controlled soft-delete
|
|
57
63
|
marker.
|
|
@@ -74,18 +80,19 @@ function constructors, a trigger registry, an audited command protocol
|
|
|
74
80
|
|
|
75
81
|
| Import | Provides |
|
|
76
82
|
| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
77
|
-
| `cvx-kit` |
|
|
83
|
+
| `cvx-kit` | Non-Effect helpers and component clients; import the optional Effect facade explicitly from `cvx-kit/effect`. |
|
|
78
84
|
| `cvx-kit/zod-table` | `zodTable`, `tenantTable`, `createModule`, `paginated`, `zodVariantTable`, `jsonSafeZid`, `TIMESTAMP_FIELDS` |
|
|
85
|
+
| `cvx-kit/effect` | Recommended command/query API: `createEffectFoundation`, `effectApiBuilder`, `effectZodApiBuilder`, `createEffectCrud`, idempotency/workflow adapters and operation tools. |
|
|
79
86
|
| `cvx-kit/auth` | `createAuthFunctions` (incl. optional `security` RLS config), `createInclude`, `defaultRoleMap` |
|
|
80
87
|
| `cvx-kit/tenancy` | `createTenantRules`, `composeRules`, `requireTenantReference`, `assertTenantOwned`, `TENANT_FIELD` |
|
|
81
|
-
| `cvx-kit/crud` |
|
|
88
|
+
| `cvx-kit/crud` | Compatibility CRUD factory using the deprecated Promise command facade; use `createEffectCrud` from `cvx-kit/effect` for new domains. |
|
|
82
89
|
| `cvx-kit/state-machine` | `createStateMachine` — typed transitions from constants tuples; `assert` drops into command guards |
|
|
83
90
|
| `cvx-kit/middleware` | `rateLimit` — packaged middleware over an injected rate-limiter instance; keyed by `ctx.tenant`, missing key = config error |
|
|
84
91
|
| `cvx-kit/webhooks` | `createWebhookBoundary`, `recordWebhookEvent`, `webhookEventsTable` — raw-body verify, natural-key dedup in the mutation |
|
|
85
92
|
| `cvx-kit/agent-tools` | `createAgentTools` — tool records from table masks; mutation handlers route through command executors |
|
|
86
93
|
| `cvx-kit/triggers` | `createTriggers`, `timestamps`, `appendOnly`, `noDelete`, `tenantOwnership`, `Triggers` |
|
|
87
94
|
| `cvx-kit/errors` | `KitError`, `defaultErrors`, `ErrorFactory` |
|
|
88
|
-
| `cvx-kit/components/foundation` |
|
|
95
|
+
| `cvx-kit/components/foundation` | Component client and types; `Foundation.Command` is deprecated. The component and other capabilities remain available. New command registries use `cvx-kit/effect`. |
|
|
89
96
|
| `cvx-kit/components/approvals` | `Approvals` client; default export = component config for `app.use` |
|
|
90
97
|
| `cvx-kit/test` | `registerFoundation(t)`, `registerApprovals(t)` for convex-test |
|
|
91
98
|
|
|
@@ -110,7 +117,7 @@ appendOnly(triggers, 'history')
|
|
|
110
117
|
// convex/functions.ts
|
|
111
118
|
export const {
|
|
112
119
|
authQuery,
|
|
113
|
-
authMutation,
|
|
120
|
+
authMutation: baseAuthMutation,
|
|
114
121
|
authAction,
|
|
115
122
|
adminQuery,
|
|
116
123
|
adminMutation,
|
|
@@ -141,13 +148,23 @@ export const {
|
|
|
141
148
|
},
|
|
142
149
|
})
|
|
143
150
|
|
|
151
|
+
// convex/functions.ts — wrap configured auth constructors once, after auth/RLS/triggers
|
|
152
|
+
// Import Context from effect and effectZodApiBuilder from cvx-kit/effect.
|
|
153
|
+
// Place this after the registry declaration or import the registry from its module.
|
|
154
|
+
export const authMutation = effectZodApiBuilder(baseAuthMutation, {
|
|
155
|
+
context: (ctx) => ({ commands: commands.withContext(ctx) }),
|
|
156
|
+
})
|
|
157
|
+
|
|
144
158
|
// convex/foundation.ts
|
|
145
|
-
|
|
159
|
+
// Import createEffectFoundation from cvx-kit/effect.
|
|
160
|
+
import type { MutationCtx } from './_generated/server'
|
|
161
|
+
export type CommandHost = MutationCtx & { actor: { userId: string } }
|
|
162
|
+
export const { Command, Query, observability } = createEffectFoundation({
|
|
146
163
|
observability: {
|
|
147
164
|
enabled: () => process.env.OBS === 'true',
|
|
148
165
|
classifyError, // → { outcome: 'denied'|'failed', errorCode }
|
|
149
|
-
writeAudit: (ctx, entry) => writeAuditEntry(ctx, entry),
|
|
150
166
|
},
|
|
167
|
+
writeAudit: (ctx: CommandHost, entry) => writeAuditEntry(ctx, entry),
|
|
151
168
|
})
|
|
152
169
|
|
|
153
170
|
// convex/approvals.ts
|
|
@@ -175,32 +192,33 @@ export const documents = zodTable(
|
|
|
175
192
|
defineSchema({ documents: documents.table.index('by_owner', ['ownerId']) })
|
|
176
193
|
|
|
177
194
|
// domain/documents/commands.ts
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
195
|
+
export const renameInput = documents.commandInput.extend({ id: zid('documents') })
|
|
196
|
+
export const renameResult = z.object({ ok: z.literal(true) }).strict()
|
|
197
|
+
export const commands = Command({
|
|
198
|
+
context: (host: CommandHost) => host,
|
|
199
|
+
operations: ({ command }) => ({
|
|
200
|
+
'documents.rename': command({
|
|
201
|
+
input: renameInput,
|
|
202
|
+
result: renameResult,
|
|
203
|
+
classification: 'business',
|
|
204
|
+
handler: async (input, ctx) => {
|
|
205
|
+
await ctx.db.patch(input.id, { title: input.title })
|
|
206
|
+
return { ok: true as const }
|
|
207
|
+
},
|
|
208
|
+
audit: ({ command }, ctx) => ({
|
|
209
|
+
operation: 'documents.rename',
|
|
210
|
+
actorId: ctx.actor.userId,
|
|
211
|
+
aggregate: { type: 'document', id: command.id },
|
|
212
|
+
}),
|
|
187
213
|
}),
|
|
188
214
|
}),
|
|
189
|
-
} as const
|
|
190
|
-
const commands = new Command<MutationCtx, typeof operations>(operations)
|
|
191
|
-
export const executeRename = commands.exec({
|
|
192
|
-
operation: 'documents.rename',
|
|
193
|
-
handler: async (ctx, cmd) => {
|
|
194
|
-
await ctx.db.patch(cmd.id, { title: cmd.title })
|
|
195
|
-
return { ok: true }
|
|
196
|
-
},
|
|
197
215
|
})
|
|
198
216
|
|
|
199
217
|
// api/documents.ts — thin public adapter
|
|
200
218
|
export const rename = authMutation({
|
|
201
|
-
args:
|
|
202
|
-
returns:
|
|
203
|
-
handler: (ctx,
|
|
219
|
+
args: renameInput,
|
|
220
|
+
returns: renameResult,
|
|
221
|
+
handler: (ctx, input) => ctx.commands.exec('documents.rename', input),
|
|
204
222
|
})
|
|
205
223
|
export const list = authQuery({
|
|
206
224
|
args: { limit: z.number() },
|
|
@@ -261,9 +279,15 @@ points at `runId`.
|
|
|
261
279
|
4. Mis-declared `serverFields` silently make server-owned fields
|
|
262
280
|
client-writable; masks are the security boundary.
|
|
263
281
|
5. `include(...).resolve()` silently falls back to `fullTableScan()`.
|
|
264
|
-
6.
|
|
265
|
-
|
|
282
|
+
6. Command audit actors come from trusted host context, never client input.
|
|
283
|
+
Commands with writes must run through mutation builders with wrapped `ctx.db`.
|
|
266
284
|
7. Changing approval steps without bumping `compatibilityKey` lets old runs
|
|
267
285
|
be driven by an incompatible shape.
|
|
268
286
|
8. When composing ctx manually, spread `wrapDB(ctx)` first — later spreads
|
|
269
287
|
carrying `db` restore the unwrapped database.
|
|
288
|
+
|
|
289
|
+
Optional request context can be added through the existing Effect API adapter's
|
|
290
|
+
`context` callback. Bind selected registries with `commands.withContext(value)`
|
|
291
|
+
and consume `ctx.commands.exec(name, input)` through the application's existing
|
|
292
|
+
function helper names. Keep dependencies local to each feature; explicit execution
|
|
293
|
+
and input-only command handlers remain supported. See [optional context injection](./command-context.md).
|
package/docs/migration.md
CHANGED
|
@@ -25,7 +25,7 @@ convex/
|
|
|
25
25
|
schema.ts # defineSchema(domainTables). Nothing else.
|
|
26
26
|
functions.ts # the single createAuthFunctions(...) call
|
|
27
27
|
triggers.ts # the single trigger registry + helper registrations
|
|
28
|
-
foundation.ts # the single
|
|
28
|
+
foundation.ts # the single createEffectFoundation(...) facade
|
|
29
29
|
<component>.ts # one facade per mounted component (audit.ts, approvals.ts, pool.ts, workflows.ts, ...)
|
|
30
30
|
auth.ts # identity-provider client wiring
|
|
31
31
|
auth.config.ts # Convex auth providers config
|
package/docs/oxlint.md
CHANGED
|
@@ -27,7 +27,7 @@ Loading a plugin does not enable its rules. For example:
|
|
|
27
27
|
|
|
28
28
|
With Vite+, place those fields under `lint` in `vite.config.ts`. The plugin
|
|
29
29
|
exports a default plugin object, named `rules`, and the `RuleName` type. It is
|
|
30
|
-
tested with Oxlint 1.
|
|
30
|
+
tested with Oxlint 1.87.0 and Vite+ 1.1.0.
|
|
31
31
|
|
|
32
32
|
All rules default to `convex/` relative to the linter's working directory.
|
|
33
33
|
For another location, set `convexDir` on **each enabled rule**:
|
package/docs/upgrading.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Upgrading to 0.1.0 — the new way of things
|
|
2
2
|
|
|
3
|
+
## Current dependency requirements
|
|
4
|
+
|
|
5
|
+
Install Convex 1.46 or newer and convex-helpers 0.1.127 or newer (below 0.2.0).
|
|
6
|
+
These minimums match workflow 0.4.10. Regenerate your lockfile after updating.
|
|
7
|
+
Auth declarations retain native Convex context types across package versions;
|
|
8
|
+
the regression fixture also checks Convex 1.45, which is below the current
|
|
9
|
+
full-package dependency minimum.
|
|
10
|
+
|
|
11
|
+
## Current command API — Effect declarations
|
|
12
|
+
|
|
13
|
+
`Foundation.Command` and its separate `exec({ operation, handler })` API are
|
|
14
|
+
deprecated. For new command code, use `createEffectFoundation` from
|
|
15
|
+
`cvx-kit/effect`, declare handlers inside `command({...})`, and return
|
|
16
|
+
`exec(operation, input, host)` through a shared Effect API builder.
|
|
17
|
+
See [commands.md](./commands.md) for migration steps. Existing consumers remain
|
|
18
|
+
compatible; older release sections below describe their historical APIs.
|
|
19
|
+
|
|
3
20
|
## 0.1.6 — stricter architecture checks
|
|
4
21
|
|
|
5
22
|
Enable `project-structure`, `root-wiring-only`, `application-orchestration`,
|
|
@@ -58,7 +75,7 @@ Install `convex-helpers` as a direct peer, using one compatible instance:
|
|
|
58
75
|
bun add cvx-kit@0.1.3 convex-helpers@0.1.124
|
|
59
76
|
```
|
|
60
77
|
|
|
61
|
-
The peer range
|
|
78
|
+
The peer range was `>=0.1.123 <0.2.0`. Remove overrides that force a
|
|
62
79
|
separate helper copy and regenerate the installation without discarding
|
|
63
80
|
unrelated dependency choices. This release is validated with Convex 1.45.0,
|
|
64
81
|
Zod 4.5.4, and convex-test 0.0.56.
|
package/docs/zod-table.md
CHANGED
|
@@ -29,7 +29,7 @@ export const documents = zodTable(
|
|
|
29
29
|
|
|
30
30
|
### Shared ID validation (0.1.3)
|
|
31
31
|
|
|
32
|
-
Install one compatible `convex-helpers` peer (`>=0.1.
|
|
32
|
+
Install one compatible `convex-helpers` peer (`>=0.1.127 <0.2.0`) alongside
|
|
33
33
|
cvx-kit. ID metadata lives in a helper-instance registry: copying schemas
|
|
34
34
|
between separately installed helper instances can silently turn an ID into
|
|
35
35
|
`v.any()`. An exact nested dependency previously caused that failure even
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cvx-kit",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"description": "Reusable Convex application kit: foundation kernels, approvals component, zod table boundaries, WorkOS-backed auth function constructors, and audited command protocol.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"component",
|
|
@@ -133,6 +133,7 @@
|
|
|
133
133
|
"test:package:ids": "bun run build && node scripts/test-packed-ids.mjs",
|
|
134
134
|
"test:package:oxlint": "bun run build && node scripts/test-packed-oxlint.mjs",
|
|
135
135
|
"test:package:effect": "bun run build && node scripts/test-packed-effect.mjs",
|
|
136
|
+
"test:package:auth": "bun run build && node scripts/test-packed-auth.mjs",
|
|
136
137
|
"test:package:smoke:effect": "bun run build && node scripts/smoke-packed-effect.mjs",
|
|
137
138
|
"test:package:smoke:bun": "bun scripts/smoke-packed-components.mjs bun",
|
|
138
139
|
"test:package:smoke:npm": "node scripts/smoke-packed-components.mjs npm",
|
|
@@ -143,28 +144,30 @@
|
|
|
143
144
|
"release:minor": "npm version minor && git push --follow-tags"
|
|
144
145
|
},
|
|
145
146
|
"dependencies": {
|
|
146
|
-
"@convex-dev/workflow": "0.4.
|
|
147
|
-
"@oxlint/plugins": "1.
|
|
147
|
+
"@convex-dev/workflow": "0.4.10",
|
|
148
|
+
"@oxlint/plugins": "1.87.0",
|
|
149
|
+
"@standard-schema/spec": "^1.1.0",
|
|
148
150
|
"convex-audit-log": "^0.2.0",
|
|
149
|
-
"oxc-parser": "0.
|
|
151
|
+
"oxc-parser": "0.153.0",
|
|
150
152
|
"oxc-resolver": "11.24.2"
|
|
151
153
|
},
|
|
152
154
|
"devDependencies": {
|
|
153
155
|
"@edge-runtime/vm": "^5.0.0",
|
|
154
|
-
"@types/node": "^26.6.
|
|
155
|
-
"convex": "1.
|
|
156
|
-
"convex-helpers": "0.1.
|
|
157
|
-
"convex-test": "^0.0.
|
|
158
|
-
"effect": "4.0.
|
|
159
|
-
"oxlint": "1.
|
|
160
|
-
"publint": "^0.3.
|
|
156
|
+
"@types/node": "^26.6.5",
|
|
157
|
+
"convex": "1.46.0",
|
|
158
|
+
"convex-helpers": "0.1.128",
|
|
159
|
+
"convex-test": "^0.0.61",
|
|
160
|
+
"effect": "4.0.2",
|
|
161
|
+
"oxlint": "1.87.0",
|
|
162
|
+
"publint": "^0.3.25",
|
|
161
163
|
"typescript": "7.0.2",
|
|
162
|
-
"vite
|
|
163
|
-
"
|
|
164
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@1.1.0",
|
|
165
|
+
"vite-plus": "1.1.0",
|
|
166
|
+
"zod": "4.6.5"
|
|
164
167
|
},
|
|
165
168
|
"peerDependencies": {
|
|
166
|
-
"convex": "^1.
|
|
167
|
-
"convex-helpers": ">=0.1.
|
|
169
|
+
"convex": "^1.46.0",
|
|
170
|
+
"convex-helpers": ">=0.1.127 <0.2.0",
|
|
168
171
|
"effect": ">=4.0.1 <5",
|
|
169
172
|
"zod": "^4.5.4"
|
|
170
173
|
},
|
|
@@ -173,6 +176,9 @@
|
|
|
173
176
|
"optional": true
|
|
174
177
|
}
|
|
175
178
|
},
|
|
179
|
+
"overrides": {
|
|
180
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@1.1.0"
|
|
181
|
+
},
|
|
176
182
|
"devEngines": {
|
|
177
183
|
"packageManager": {
|
|
178
184
|
"name": "bun",
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process'
|
|
2
|
+
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
|
|
3
|
+
import { tmpdir } from 'node:os'
|
|
4
|
+
import { basename, join, resolve } from 'node:path'
|
|
5
|
+
|
|
6
|
+
const root = resolve(import.meta.dirname, '..')
|
|
7
|
+
const manifest = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8'))
|
|
8
|
+
const temporary = mkdtempSync(join(tmpdir(), 'cvx-kit-auth-'))
|
|
9
|
+
function run(command, args, cwd) {
|
|
10
|
+
try {
|
|
11
|
+
return execFileSync(command, args, { cwd, encoding: 'utf8', stdio: 'pipe' })
|
|
12
|
+
} catch (error) {
|
|
13
|
+
if (!args.includes('install')) {
|
|
14
|
+
process.stderr.write(error.stdout ?? '')
|
|
15
|
+
process.stderr.write(error.stderr ?? '')
|
|
16
|
+
}
|
|
17
|
+
throw new Error(`${command} ${args.join(' ')} failed in ${basename(cwd)}`, {
|
|
18
|
+
cause: error.code,
|
|
19
|
+
})
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
run('bun', ['pm', 'pack', '--ignore-scripts', '--destination', temporary], root)
|
|
24
|
+
const tarball = join(temporary, `${manifest.name}-${manifest.version}.tgz`)
|
|
25
|
+
// 1.45 is a declaration regression target, below the current workflow peer floor.
|
|
26
|
+
for (const convex of ['1.45.0', '1.46.0']) {
|
|
27
|
+
const fixture = mkdtempSync(join(temporary, `convex-${convex}-`))
|
|
28
|
+
writeFileSync(
|
|
29
|
+
join(fixture, 'package.json'),
|
|
30
|
+
JSON.stringify({
|
|
31
|
+
private: true,
|
|
32
|
+
type: 'module',
|
|
33
|
+
dependencies: {
|
|
34
|
+
'cvx-kit': `file:${tarball}`,
|
|
35
|
+
convex,
|
|
36
|
+
'convex-helpers': manifest.devDependencies['convex-helpers'],
|
|
37
|
+
effect: manifest.devDependencies.effect,
|
|
38
|
+
zod: manifest.devDependencies.zod,
|
|
39
|
+
typescript: manifest.devDependencies.typescript,
|
|
40
|
+
'@types/node': manifest.devDependencies['@types/node'],
|
|
41
|
+
},
|
|
42
|
+
}),
|
|
43
|
+
)
|
|
44
|
+
writeFileSync(
|
|
45
|
+
join(fixture, 'auth.ts'),
|
|
46
|
+
readFileSync(join(root, 'test/auth-native-context-types.ts')),
|
|
47
|
+
)
|
|
48
|
+
writeFileSync(
|
|
49
|
+
join(fixture, 'tsconfig.json'),
|
|
50
|
+
JSON.stringify({
|
|
51
|
+
compilerOptions: {
|
|
52
|
+
strict: true,
|
|
53
|
+
noEmit: true,
|
|
54
|
+
skipLibCheck: true,
|
|
55
|
+
target: 'ES2025',
|
|
56
|
+
module: 'ESNext',
|
|
57
|
+
moduleResolution: 'bundler',
|
|
58
|
+
},
|
|
59
|
+
include: ['auth.ts'],
|
|
60
|
+
}),
|
|
61
|
+
)
|
|
62
|
+
run('bun', ['install', '--ignore-scripts'], fixture)
|
|
63
|
+
run('bun', ['x', '--no-install', 'tsc', '--project', 'tsconfig.json'], fixture)
|
|
64
|
+
console.log(`Packed auth native contexts pass on Convex ${convex}`)
|
|
65
|
+
}
|
|
66
|
+
} finally {
|
|
67
|
+
rmSync(temporary, { recursive: true, force: true })
|
|
68
|
+
}
|
|
@@ -15,7 +15,7 @@ const root = resolve(import.meta.dirname, '..')
|
|
|
15
15
|
const manifest = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8'))
|
|
16
16
|
const temporary = mkdtempSync(join(tmpdir(), 'cvx-kit-effect-'))
|
|
17
17
|
const effectVersion = '4.0.1'
|
|
18
|
-
const helpersVersion = '0.1.
|
|
18
|
+
const helpersVersion = '0.1.127'
|
|
19
19
|
const nodeTypesVersion = '26.6.1'
|
|
20
20
|
const domainGuidePath = join(root, 'src/docs/domain-operations.md')
|
|
21
21
|
const domainGuideImports = new Set([
|
|
@@ -26,8 +26,11 @@ const domainGuideImports = new Set([
|
|
|
26
26
|
'./fixture-effect/convex/_generated/dataModel',
|
|
27
27
|
])
|
|
28
28
|
const extraTypeFixtures = [
|
|
29
|
+
join(root, 'README.md'),
|
|
29
30
|
join(root, 'src/docs/effect.md'),
|
|
30
31
|
join(root, 'src/docs/commands.md'),
|
|
32
|
+
join(root, 'src/docs/command-context.md'),
|
|
33
|
+
join(root, 'src/docs/commands-legacy.md'),
|
|
31
34
|
join(root, 'src/docs/auth.md'),
|
|
32
35
|
domainGuidePath,
|
|
33
36
|
...process.argv.slice(2).map((path) => resolve(path)),
|
|
@@ -25,7 +25,7 @@ try {
|
|
|
25
25
|
type: 'module',
|
|
26
26
|
dependencies: {
|
|
27
27
|
'cvx-kit': `file:${join(temporary, `cvx-kit-${manifest.version}.tgz`)}`,
|
|
28
|
-
'convex-helpers': '0.1.
|
|
28
|
+
'convex-helpers': '0.1.127',
|
|
29
29
|
convex: manifest.devDependencies.convex,
|
|
30
30
|
zod: manifest.devDependencies.zod,
|
|
31
31
|
},
|
|
@@ -142,7 +142,7 @@ it('registers concrete and generic backends from the packed package', () => {
|
|
|
142
142
|
fixture,
|
|
143
143
|
)
|
|
144
144
|
console.log(
|
|
145
|
-
`${installer}: packed IDs, table/tool types, registration, and command lifecycle pass with host convex-helpers 0.1.
|
|
145
|
+
`${installer}: packed IDs, table/tool types, registration, and command lifecycle pass with host convex-helpers 0.1.127`,
|
|
146
146
|
)
|
|
147
147
|
}
|
|
148
148
|
} finally {
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
//#region node_modules/@standard-schema/spec/dist/index.d.ts
|
|
2
|
-
/** The Standard Typed interface. This is a base type extended by other specs. */
|
|
3
|
-
interface StandardTypedV1<Input = unknown, Output = Input> {
|
|
4
|
-
/** The Standard properties. */
|
|
5
|
-
readonly "~standard": StandardTypedV1.Props<Input, Output>;
|
|
6
|
-
}
|
|
7
|
-
declare namespace StandardTypedV1 {
|
|
8
|
-
/** The Standard Typed properties interface. */
|
|
9
|
-
interface Props<Input = unknown, Output = Input> {
|
|
10
|
-
/** The version number of the standard. */
|
|
11
|
-
readonly version: 1;
|
|
12
|
-
/** The vendor name of the schema library. */
|
|
13
|
-
readonly vendor: string;
|
|
14
|
-
/** Inferred types associated with the schema. */
|
|
15
|
-
readonly types?: Types<Input, Output> | undefined;
|
|
16
|
-
}
|
|
17
|
-
/** The Standard Typed types interface. */
|
|
18
|
-
interface Types<Input = unknown, Output = Input> {
|
|
19
|
-
/** The input type of the schema. */
|
|
20
|
-
readonly input: Input;
|
|
21
|
-
/** The output type of the schema. */
|
|
22
|
-
readonly output: Output;
|
|
23
|
-
}
|
|
24
|
-
/** Infers the input type of a Standard Typed. */
|
|
25
|
-
type InferInput<Schema extends StandardTypedV1> = NonNullable<Schema["~standard"]["types"]>["input"];
|
|
26
|
-
/** Infers the output type of a Standard Typed. */
|
|
27
|
-
type InferOutput<Schema extends StandardTypedV1> = NonNullable<Schema["~standard"]["types"]>["output"];
|
|
28
|
-
}
|
|
29
|
-
/** The Standard Schema interface. */
|
|
30
|
-
interface StandardSchemaV1<Input = unknown, Output = Input> {
|
|
31
|
-
/** The Standard Schema properties. */
|
|
32
|
-
readonly "~standard": StandardSchemaV1.Props<Input, Output>;
|
|
33
|
-
}
|
|
34
|
-
declare namespace StandardSchemaV1 {
|
|
35
|
-
/** The Standard Schema properties interface. */
|
|
36
|
-
interface Props<Input = unknown, Output = Input> extends StandardTypedV1.Props<Input, Output> {
|
|
37
|
-
/** Validates unknown input values. */
|
|
38
|
-
readonly validate: (value: unknown, options?: StandardSchemaV1.Options | undefined) => Result<Output> | Promise<Result<Output>>;
|
|
39
|
-
}
|
|
40
|
-
/** The result interface of the validate function. */
|
|
41
|
-
type Result<Output> = SuccessResult<Output> | FailureResult;
|
|
42
|
-
/** The result interface if validation succeeds. */
|
|
43
|
-
interface SuccessResult<Output> {
|
|
44
|
-
/** The typed output value. */
|
|
45
|
-
readonly value: Output;
|
|
46
|
-
/** A falsy value for `issues` indicates success. */
|
|
47
|
-
readonly issues?: undefined;
|
|
48
|
-
}
|
|
49
|
-
interface Options {
|
|
50
|
-
/** Explicit support for additional vendor-specific parameters, if needed. */
|
|
51
|
-
readonly libraryOptions?: Record<string, unknown> | undefined;
|
|
52
|
-
}
|
|
53
|
-
/** The result interface if validation fails. */
|
|
54
|
-
interface FailureResult {
|
|
55
|
-
/** The issues of failed validation. */
|
|
56
|
-
readonly issues: ReadonlyArray<Issue>;
|
|
57
|
-
}
|
|
58
|
-
/** The issue interface of the failure output. */
|
|
59
|
-
interface Issue {
|
|
60
|
-
/** The error message of the issue. */
|
|
61
|
-
readonly message: string;
|
|
62
|
-
/** The path of the issue, if any. */
|
|
63
|
-
readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
|
|
64
|
-
}
|
|
65
|
-
/** The path segment interface of the issue. */
|
|
66
|
-
interface PathSegment {
|
|
67
|
-
/** The key representing a path segment. */
|
|
68
|
-
readonly key: PropertyKey;
|
|
69
|
-
}
|
|
70
|
-
/** The Standard types interface. */
|
|
71
|
-
interface Types<Input = unknown, Output = Input> extends StandardTypedV1.Types<Input, Output> {}
|
|
72
|
-
/** Infers the input type of a Standard. */
|
|
73
|
-
type InferInput<Schema extends StandardTypedV1> = StandardTypedV1.InferInput<Schema>;
|
|
74
|
-
/** Infers the output type of a Standard. */
|
|
75
|
-
type InferOutput<Schema extends StandardTypedV1> = StandardTypedV1.InferOutput<Schema>;
|
|
76
|
-
}
|
|
77
|
-
//#endregion
|
|
78
|
-
export { StandardSchemaV1, StandardTypedV1 };
|
|
79
|
-
//# sourceMappingURL=index.d.mts.map
|