@vexcms/core 0.0.19 → 0.1.0-alpha.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.
- package/LICENSE +202 -0
- package/dist/.build +1 -0
- package/dist/access/buildChecks.d.ts +58 -0
- package/dist/access/buildChecks.d.ts.map +1 -0
- package/dist/access/canAccessAdminPanel.d.ts +53 -0
- package/dist/access/canAccessAdminPanel.d.ts.map +1 -0
- package/dist/access/compileConstraints.d.ts +155 -0
- package/dist/access/compileConstraints.d.ts.map +1 -0
- package/dist/access/config.d.ts +62 -0
- package/dist/access/config.d.ts.map +1 -0
- package/dist/access/constants.d.ts +95 -0
- package/dist/access/constants.d.ts.map +1 -0
- package/dist/access/constraintTypes.d.ts +337 -0
- package/dist/access/constraintTypes.d.ts.map +1 -0
- package/dist/access/createAccessQueryBuilder.d.ts +59 -0
- package/dist/access/createAccessQueryBuilder.d.ts.map +1 -0
- package/dist/access/createFilterConstraintBuilder.d.ts +26 -0
- package/dist/access/createFilterConstraintBuilder.d.ts.map +1 -0
- package/dist/access/createIndexConstraintBuilder.d.ts +40 -0
- package/dist/access/createIndexConstraintBuilder.d.ts.map +1 -0
- package/dist/access/hasPermission.d.ts +85 -0
- package/dist/access/hasPermission.d.ts.map +1 -0
- package/dist/access/index.d.ts +13 -0
- package/dist/access/index.d.ts.map +1 -0
- package/dist/access/pickQueryIndex.d.ts +42 -0
- package/dist/access/pickQueryIndex.d.ts.map +1 -0
- package/dist/access/resolveAccessRule.d.ts +85 -0
- package/dist/access/resolveAccessRule.d.ts.map +1 -0
- package/dist/access/types.d.ts +738 -0
- package/dist/access/types.d.ts.map +1 -0
- package/dist/access/validateAccessConstraints.d.ts +57 -0
- package/dist/access/validateAccessConstraints.d.ts.map +1 -0
- package/dist/api/client.d.ts +20 -0
- package/dist/api/client.d.ts.map +1 -0
- package/dist/api/client.js +117 -0
- package/dist/api/client.js.map +1 -0
- package/dist/api/convex.d.ts +296 -0
- package/dist/api/convex.d.ts.map +1 -0
- package/dist/api/create/client.d.ts +50 -0
- package/dist/api/create/client.d.ts.map +1 -0
- package/dist/api/create/server.d.ts +43 -0
- package/dist/api/create/server.d.ts.map +1 -0
- package/dist/api/depth.d.ts +39 -0
- package/dist/api/depth.d.ts.map +1 -0
- package/dist/api/find/client.d.ts +90 -0
- package/dist/api/find/client.d.ts.map +1 -0
- package/dist/api/find/server.d.ts +73 -0
- package/dist/api/find/server.d.ts.map +1 -0
- package/dist/api/get/client.d.ts +56 -0
- package/dist/api/get/client.d.ts.map +1 -0
- package/dist/api/get/server.d.ts +49 -0
- package/dist/api/get/server.d.ts.map +1 -0
- package/dist/api/globals/find.client.d.ts +20 -0
- package/dist/api/globals/find.client.d.ts.map +1 -0
- package/dist/api/globals/find.server.d.ts +29 -0
- package/dist/api/globals/find.server.d.ts.map +1 -0
- package/dist/api/globals/get.client.d.ts +46 -0
- package/dist/api/globals/get.client.d.ts.map +1 -0
- package/dist/api/globals/get.server.d.ts +55 -0
- package/dist/api/globals/get.server.d.ts.map +1 -0
- package/dist/api/globals/types.d.ts +65 -0
- package/dist/api/globals/types.d.ts.map +1 -0
- package/dist/api/globals/upsert.client.d.ts +24 -0
- package/dist/api/globals/upsert.client.d.ts.map +1 -0
- package/dist/api/globals/upsert.server.d.ts +47 -0
- package/dist/api/globals/upsert.server.d.ts.map +1 -0
- package/dist/api/populate.d.ts +23 -0
- package/dist/api/populate.d.ts.map +1 -0
- package/dist/api/remove/client.d.ts +58 -0
- package/dist/api/remove/client.d.ts.map +1 -0
- package/dist/api/remove/server.d.ts +65 -0
- package/dist/api/remove/server.d.ts.map +1 -0
- package/dist/api/search/client.d.ts +58 -0
- package/dist/api/search/client.d.ts.map +1 -0
- package/dist/api/search/server.d.ts +54 -0
- package/dist/api/search/server.d.ts.map +1 -0
- package/dist/api/server.d.ts +370 -0
- package/dist/api/server.d.ts.map +1 -0
- package/dist/api/server.js +33 -0
- package/dist/api/server.js.map +1 -0
- package/dist/api/types.d.ts +525 -0
- package/dist/api/types.d.ts.map +1 -0
- package/dist/api/update/client.d.ts +53 -0
- package/dist/api/update/client.d.ts.map +1 -0
- package/dist/api/update/server.d.ts +47 -0
- package/dist/api/update/server.d.ts.map +1 -0
- package/dist/api/utils.d.ts +57 -0
- package/dist/api/utils.d.ts.map +1 -0
- package/dist/auth/mergeCollections.d.ts +28 -0
- package/dist/auth/mergeCollections.d.ts.map +1 -0
- package/dist/auth/types.d.ts +84 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/chunk-2DU7JDEX.js +1877 -0
- package/dist/chunk-2DU7JDEX.js.map +1 -0
- package/dist/chunk-2IB2DCN7.js +75 -0
- package/dist/chunk-2IB2DCN7.js.map +1 -0
- package/dist/collections/config.d.ts +28 -0
- package/dist/collections/config.d.ts.map +1 -0
- package/dist/collections/constants.d.ts +27 -0
- package/dist/collections/constants.d.ts.map +1 -0
- package/dist/collections/index.d.ts +7 -0
- package/dist/collections/index.d.ts.map +1 -0
- package/dist/collections/indexFields.d.ts +20 -0
- package/dist/collections/indexFields.d.ts.map +1 -0
- package/dist/collections/interfaceGen.d.ts +59 -0
- package/dist/collections/interfaceGen.d.ts.map +1 -0
- package/dist/collections/internal/index.d.ts +2 -0
- package/dist/collections/internal/index.d.ts.map +1 -0
- package/dist/collections/types.d.ts +282 -0
- package/dist/collections/types.d.ts.map +1 -0
- package/dist/collections/utils.d.ts +71 -0
- package/dist/collections/utils.d.ts.map +1 -0
- package/dist/collections/validator.d.ts +73 -0
- package/dist/collections/validator.d.ts.map +1 -0
- package/dist/config/config.d.ts +43 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/index.d.ts +5 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/sanitizeConfig.d.ts +82 -0
- package/dist/config/sanitizeConfig.d.ts.map +1 -0
- package/dist/config/types.d.ts +316 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/fields/array/config.d.ts +57 -0
- package/dist/fields/array/config.d.ts.map +1 -0
- package/dist/fields/array/index.d.ts +5 -0
- package/dist/fields/array/index.d.ts.map +1 -0
- package/dist/fields/array/inputSchema.d.ts +32 -0
- package/dist/fields/array/inputSchema.d.ts.map +1 -0
- package/dist/fields/array/types.d.ts +127 -0
- package/dist/fields/array/types.d.ts.map +1 -0
- package/dist/fields/array/validator.d.ts +30 -0
- package/dist/fields/array/validator.d.ts.map +1 -0
- package/dist/fields/baseTypes.d.ts +251 -0
- package/dist/fields/baseTypes.d.ts.map +1 -0
- package/dist/fields/blocks/config.d.ts +63 -0
- package/dist/fields/blocks/config.d.ts.map +1 -0
- package/dist/fields/blocks/index.d.ts +5 -0
- package/dist/fields/blocks/index.d.ts.map +1 -0
- package/dist/fields/blocks/inputSchema.d.ts +22 -0
- package/dist/fields/blocks/inputSchema.d.ts.map +1 -0
- package/dist/fields/blocks/types.d.ts +253 -0
- package/dist/fields/blocks/types.d.ts.map +1 -0
- package/dist/fields/blocks/validator.d.ts +32 -0
- package/dist/fields/blocks/validator.d.ts.map +1 -0
- package/dist/fields/checkbox/config.d.ts +46 -0
- package/dist/fields/checkbox/config.d.ts.map +1 -0
- package/dist/fields/checkbox/index.d.ts +5 -0
- package/dist/fields/checkbox/index.d.ts.map +1 -0
- package/dist/fields/checkbox/inputSchema.d.ts +27 -0
- package/dist/fields/checkbox/inputSchema.d.ts.map +1 -0
- package/dist/fields/checkbox/types.d.ts +67 -0
- package/dist/fields/checkbox/types.d.ts.map +1 -0
- package/dist/fields/checkbox/validator.d.ts +34 -0
- package/dist/fields/checkbox/validator.d.ts.map +1 -0
- package/dist/fields/color/config.d.ts +49 -0
- package/dist/fields/color/config.d.ts.map +1 -0
- package/dist/fields/color/convert.d.ts +72 -0
- package/dist/fields/color/convert.d.ts.map +1 -0
- package/dist/fields/color/formats.d.ts +38 -0
- package/dist/fields/color/formats.d.ts.map +1 -0
- package/dist/fields/color/index.d.ts +8 -0
- package/dist/fields/color/index.d.ts.map +1 -0
- package/dist/fields/color/inputSchema.d.ts +29 -0
- package/dist/fields/color/inputSchema.d.ts.map +1 -0
- package/dist/fields/color/types.d.ts +100 -0
- package/dist/fields/color/types.d.ts.map +1 -0
- package/dist/fields/color/utils.d.ts +100 -0
- package/dist/fields/color/utils.d.ts.map +1 -0
- package/dist/fields/color/validator.d.ts +27 -0
- package/dist/fields/color/validator.d.ts.map +1 -0
- package/dist/fields/constants.d.ts +108 -0
- package/dist/fields/constants.d.ts.map +1 -0
- package/dist/fields/date/config.d.ts +57 -0
- package/dist/fields/date/config.d.ts.map +1 -0
- package/dist/fields/date/index.d.ts +5 -0
- package/dist/fields/date/index.d.ts.map +1 -0
- package/dist/fields/date/inputSchema.d.ts +29 -0
- package/dist/fields/date/inputSchema.d.ts.map +1 -0
- package/dist/fields/date/types.d.ts +147 -0
- package/dist/fields/date/types.d.ts.map +1 -0
- package/dist/fields/date/validator.d.ts +34 -0
- package/dist/fields/date/validator.d.ts.map +1 -0
- package/dist/fields/group/config.d.ts +47 -0
- package/dist/fields/group/config.d.ts.map +1 -0
- package/dist/fields/group/index.d.ts +5 -0
- package/dist/fields/group/index.d.ts.map +1 -0
- package/dist/fields/group/inputSchema.d.ts +27 -0
- package/dist/fields/group/inputSchema.d.ts.map +1 -0
- package/dist/fields/group/types.d.ts +105 -0
- package/dist/fields/group/types.d.ts.map +1 -0
- package/dist/fields/group/validator.d.ts +41 -0
- package/dist/fields/group/validator.d.ts.map +1 -0
- package/dist/fields/index.d.ts +20 -0
- package/dist/fields/index.d.ts.map +1 -0
- package/dist/fields/inputSchemas/index.d.ts +23 -0
- package/dist/fields/inputSchemas/index.d.ts.map +1 -0
- package/dist/fields/inputSchemas/utils.d.ts +25 -0
- package/dist/fields/inputSchemas/utils.d.ts.map +1 -0
- package/dist/fields/interfaceGen.d.ts +15 -0
- package/dist/fields/interfaceGen.d.ts.map +1 -0
- package/dist/fields/number/config.d.ts +48 -0
- package/dist/fields/number/config.d.ts.map +1 -0
- package/dist/fields/number/index.d.ts +5 -0
- package/dist/fields/number/index.d.ts.map +1 -0
- package/dist/fields/number/inputSchema.d.ts +23 -0
- package/dist/fields/number/inputSchema.d.ts.map +1 -0
- package/dist/fields/number/types.d.ts +100 -0
- package/dist/fields/number/types.d.ts.map +1 -0
- package/dist/fields/number/validator.d.ts +39 -0
- package/dist/fields/number/validator.d.ts.map +1 -0
- package/dist/fields/relationship/config.d.ts +45 -0
- package/dist/fields/relationship/config.d.ts.map +1 -0
- package/dist/fields/relationship/index.d.ts +5 -0
- package/dist/fields/relationship/index.d.ts.map +1 -0
- package/dist/fields/relationship/inputSchema.d.ts +31 -0
- package/dist/fields/relationship/inputSchema.d.ts.map +1 -0
- package/dist/fields/relationship/types.d.ts +126 -0
- package/dist/fields/relationship/types.d.ts.map +1 -0
- package/dist/fields/relationship/validator.d.ts +27 -0
- package/dist/fields/relationship/validator.d.ts.map +1 -0
- package/dist/fields/select/config.d.ts +59 -0
- package/dist/fields/select/config.d.ts.map +1 -0
- package/dist/fields/select/index.d.ts +5 -0
- package/dist/fields/select/index.d.ts.map +1 -0
- package/dist/fields/select/inputSchema.d.ts +28 -0
- package/dist/fields/select/inputSchema.d.ts.map +1 -0
- package/dist/fields/select/types.d.ts +89 -0
- package/dist/fields/select/types.d.ts.map +1 -0
- package/dist/fields/select/validator.d.ts +31 -0
- package/dist/fields/select/validator.d.ts.map +1 -0
- package/dist/fields/text/config.d.ts +48 -0
- package/dist/fields/text/config.d.ts.map +1 -0
- package/dist/fields/text/index.d.ts +5 -0
- package/dist/fields/text/index.d.ts.map +1 -0
- package/dist/fields/text/inputSchema.d.ts +24 -0
- package/dist/fields/text/inputSchema.d.ts.map +1 -0
- package/dist/fields/text/types.d.ts +132 -0
- package/dist/fields/text/types.d.ts.map +1 -0
- package/dist/fields/text/validator.d.ts +39 -0
- package/dist/fields/text/validator.d.ts.map +1 -0
- package/dist/fields/types.d.ts +135 -0
- package/dist/fields/types.d.ts.map +1 -0
- package/dist/fields/upload/config.d.ts +24 -0
- package/dist/fields/upload/config.d.ts.map +1 -0
- package/dist/fields/upload/index.d.ts +5 -0
- package/dist/fields/upload/index.d.ts.map +1 -0
- package/dist/fields/upload/inputSchema.d.ts +17 -0
- package/dist/fields/upload/inputSchema.d.ts.map +1 -0
- package/dist/fields/upload/types.d.ts +78 -0
- package/dist/fields/upload/types.d.ts.map +1 -0
- package/dist/fields/upload/validator.d.ts +16 -0
- package/dist/fields/upload/validator.d.ts.map +1 -0
- package/dist/fields/url/config.d.ts +49 -0
- package/dist/fields/url/config.d.ts.map +1 -0
- package/dist/fields/url/index.d.ts +5 -0
- package/dist/fields/url/index.d.ts.map +1 -0
- package/dist/fields/url/inputSchema.d.ts +31 -0
- package/dist/fields/url/inputSchema.d.ts.map +1 -0
- package/dist/fields/url/types.d.ts +70 -0
- package/dist/fields/url/types.d.ts.map +1 -0
- package/dist/fields/url/validator.d.ts +37 -0
- package/dist/fields/url/validator.d.ts.map +1 -0
- package/dist/fields/utils.d.ts +47 -0
- package/dist/fields/utils.d.ts.map +1 -0
- package/dist/fields/validators/index.d.ts +23 -0
- package/dist/fields/validators/index.d.ts.map +1 -0
- package/dist/fields/validators/utils.d.ts +24 -0
- package/dist/fields/validators/utils.d.ts.map +1 -0
- package/dist/framework.d.ts +227 -0
- package/dist/framework.d.ts.map +1 -0
- package/dist/globals/config/config.d.ts +1 -0
- package/dist/globals/config/config.d.ts.map +1 -0
- package/dist/globals/config/types.d.ts +1 -0
- package/dist/globals/config/types.d.ts.map +1 -0
- package/dist/globals/config.d.ts +47 -0
- package/dist/globals/config.d.ts.map +1 -0
- package/dist/globals/index.d.ts +5 -0
- package/dist/globals/index.d.ts.map +1 -0
- package/dist/globals/interfaceGen.d.ts +33 -0
- package/dist/globals/interfaceGen.d.ts.map +1 -0
- package/dist/globals/types.d.ts +175 -0
- package/dist/globals/types.d.ts.map +1 -0
- package/dist/globals/utils.d.ts +37 -0
- package/dist/globals/utils.d.ts.map +1 -0
- package/dist/index.d.ts +15 -3165
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2101 -3470
- package/dist/index.js.map +1 -1
- package/dist/media/api/index.d.ts +5 -0
- package/dist/media/api/index.d.ts.map +1 -0
- package/dist/media/api/mutations.d.ts +76 -0
- package/dist/media/api/mutations.d.ts.map +1 -0
- package/dist/media/api/queries.d.ts +28 -0
- package/dist/media/api/queries.d.ts.map +1 -0
- package/dist/media/api/server.d.ts +68 -0
- package/dist/media/api/server.d.ts.map +1 -0
- package/dist/media/api/types.d.ts +171 -0
- package/dist/media/api/types.d.ts.map +1 -0
- package/dist/media/config.d.ts +25 -0
- package/dist/media/config.d.ts.map +1 -0
- package/dist/media/index.d.ts +6 -0
- package/dist/media/index.d.ts.map +1 -0
- package/dist/media/types.d.ts +332 -0
- package/dist/media/types.d.ts.map +1 -0
- package/dist/media/utils.d.ts +35 -0
- package/dist/media/utils.d.ts.map +1 -0
- package/dist/media/validators.d.ts +61 -0
- package/dist/media/validators.d.ts.map +1 -0
- package/dist/schema/generateVexSchema.d.ts +36 -0
- package/dist/schema/generateVexSchema.d.ts.map +1 -0
- package/dist/schema/index.d.ts +3 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/migrate.d.ts +73 -0
- package/dist/schema/migrate.d.ts.map +1 -0
- package/dist/types/generateVexTypes.d.ts +41 -0
- package/dist/types/generateVexTypes.d.ts.map +1 -0
- package/dist/types/generated.d.ts +382 -0
- package/dist/types/generated.d.ts.map +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/utils.d.ts +57 -0
- package/dist/utils.d.ts.map +1 -0
- package/package.json +67 -24
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
import type { GenericDocument, IndexRangeBuilder } from "convex/server";
|
|
2
|
+
/**
|
|
3
|
+
* Adds 1 to a number literal via lookup, mirroring Convex's own `PlusOne`
|
|
4
|
+
* (`convex/src/server/index_range_builder.ts`) — advances the field cursor
|
|
5
|
+
* `ConstraintBuilder` tracks. Not exported: only `NextConstraintBuilder`
|
|
6
|
+
* needs it.
|
|
7
|
+
*/
|
|
8
|
+
type PlusOne<N extends number> = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15][N];
|
|
9
|
+
/**
|
|
10
|
+
* Every operator a Convex `IndexRangeBuilder` exposes at its first
|
|
11
|
+
* position, derived from the builder's own type rather than hand-listed —
|
|
12
|
+
* a new upstream method appears here automatically, and a rename fails
|
|
13
|
+
* compilation instead of silently drifting. Convex's private nominal
|
|
14
|
+
* markers never surface in `keyof`, so this resolves to exactly
|
|
15
|
+
* `"eq" | "gt" | "gte" | "lt" | "lte"`.
|
|
16
|
+
*/
|
|
17
|
+
export type IndexOp = Extract<keyof IndexRangeBuilder<GenericDocument, string[], 0>, string>;
|
|
18
|
+
/**
|
|
19
|
+
* Operators available to an unindexed constraint. The index-range operators
|
|
20
|
+
* plus `neq`, which `IndexRangeBuilder` has no equivalent for but
|
|
21
|
+
* `FilterBuilder` does.
|
|
22
|
+
*/
|
|
23
|
+
export type FilterOp = IndexOp | "neq";
|
|
24
|
+
/**
|
|
25
|
+
* `TDoc`'s explicitly declared keys, with any index signature dropped.
|
|
26
|
+
*
|
|
27
|
+
* Generated documents extend `VexDocument` (`api/convex.ts`), which carries
|
|
28
|
+
* `[key: string]: unknown` so a document can hold schema-defined fields the static
|
|
29
|
+
* type does not enumerate. The cost is that `keyof` answers `string` rather than a
|
|
30
|
+
* literal union — which silently removes editor completion for field names and
|
|
31
|
+
* accepts any string as a field. Remapping with `as string extends K ? never : K`
|
|
32
|
+
* discards exactly the signature keys and keeps the declared ones.
|
|
33
|
+
*
|
|
34
|
+
* @typeParam TDoc - Document shape.
|
|
35
|
+
* @internal
|
|
36
|
+
*/
|
|
37
|
+
type DeclaredKeys<TDoc> = {
|
|
38
|
+
[K in keyof TDoc as string extends K ? never : number extends K ? never : K]: TDoc[K];
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* `TDoc` with `VexDocument`'s `[key: string]: unknown` index signature removed.
|
|
42
|
+
*
|
|
43
|
+
* The signature exists so a document can hold schema-defined fields statically, but it
|
|
44
|
+
* also makes EVERY property name readable at type level: `data.tpyo` and
|
|
45
|
+
* `data.neverDeclared` both resolve to `unknown` instead of erroring. That silently
|
|
46
|
+
* defeats the point of typing a permission callback against its resource.
|
|
47
|
+
*
|
|
48
|
+
* Left alone in the pre-generation case (`unknown extends TDoc`), where stripping would
|
|
49
|
+
* turn the document into `{}` and make every real field unreadable.
|
|
50
|
+
*
|
|
51
|
+
* @typeParam TDoc - Document shape, or `unknown` when the registry is unaugmented.
|
|
52
|
+
*/
|
|
53
|
+
export type DeclaredDoc<TDoc> = unknown extends TDoc ? TDoc : DeclaredKeys<TDoc>;
|
|
54
|
+
/**
|
|
55
|
+
* A constrainable field name for `TDoc`: its declared fields, degrading to `string`
|
|
56
|
+
* when the document type is unresolved.
|
|
57
|
+
*
|
|
58
|
+
* Two widenings are deliberately handled differently.
|
|
59
|
+
*
|
|
60
|
+
* Before `vex generate` runs, `DocumentBySlug` falls back to
|
|
61
|
+
* `Record<string, unknown>`, so a resource's document type resolves to `unknown` —
|
|
62
|
+
* and `keyof unknown` is `never`, which would make every field name unwritable.
|
|
63
|
+
* `unknown extends TDoc` is true only for `unknown`/`any`, so this widens exactly
|
|
64
|
+
* in the pre-generation case.
|
|
65
|
+
*
|
|
66
|
+
* After generation the document type is real but still has `VexDocument`'s index
|
|
67
|
+
* signature, so a bare `keyof` would collapse to `string` — no completion, and a
|
|
68
|
+
* misspelled field silently accepted with an `unknown` value. {@link DeclaredKeys}
|
|
69
|
+
* strips it, which is what makes `q.eq("` offer the resource's actual fields and
|
|
70
|
+
* `q.eq("tset", …)` an error.
|
|
71
|
+
*
|
|
72
|
+
* @typeParam TDoc - Document shape, or `unknown` when the registry is unaugmented.
|
|
73
|
+
*/
|
|
74
|
+
export type ConstraintField<TDoc> = unknown extends TDoc ? string : keyof DeclaredKeys<TDoc> & string;
|
|
75
|
+
/**
|
|
76
|
+
* The value type for a constraint on field `F` of `TDoc`: the field's own type,
|
|
77
|
+
* `never` when `F` is not a field of `TDoc`, and `unknown` when `TDoc` itself is
|
|
78
|
+
* unresolved.
|
|
79
|
+
*
|
|
80
|
+
* The third case is what separates "you named a field that does not exist" (a real
|
|
81
|
+
* error, `never`) from "this project has not run `vex generate` yet" (not an error).
|
|
82
|
+
* Without it both collapse to `never` and no constraint can be written at all —
|
|
83
|
+
* including in `packages/core`'s own tests, which run against an unaugmented
|
|
84
|
+
* registry by design.
|
|
85
|
+
*
|
|
86
|
+
* @typeParam TDoc - Document shape, or `unknown` when the registry is unaugmented.
|
|
87
|
+
* @typeParam F - The field name being constrained.
|
|
88
|
+
*/
|
|
89
|
+
export type ConstraintValue<TDoc, F extends string> = unknown extends TDoc ? unknown : F extends keyof TDoc ? TDoc[F] : never;
|
|
90
|
+
/**
|
|
91
|
+
* One node of an unindexed constraint tree: a comparison on a document field,
|
|
92
|
+
* or a boolean combination of nodes.
|
|
93
|
+
*
|
|
94
|
+
* Unlike {@link AccessIndexConstraint} this is recursive, because `FilterBuilder`
|
|
95
|
+
* supports `and` / `or` / `not` and an index range does not.
|
|
96
|
+
*/
|
|
97
|
+
export type AccessFilterConstraint<TDoc> = {
|
|
98
|
+
kind: "compare";
|
|
99
|
+
field: ConstraintField<TDoc>;
|
|
100
|
+
op: FilterOp;
|
|
101
|
+
value: ConstraintValue<TDoc, ConstraintField<TDoc>>;
|
|
102
|
+
} | {
|
|
103
|
+
kind: "and";
|
|
104
|
+
nodes: AccessFilterConstraint<TDoc>[];
|
|
105
|
+
} | {
|
|
106
|
+
kind: "or";
|
|
107
|
+
nodes: AccessFilterConstraint<TDoc>[];
|
|
108
|
+
} | {
|
|
109
|
+
kind: "not";
|
|
110
|
+
node: AccessFilterConstraint<TDoc>;
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* Builder for an unindexed constraint — the `q` a rule receives when it
|
|
114
|
+
* declares no `withIndex` (DD 13).
|
|
115
|
+
*
|
|
116
|
+
* Deliberately enforces neither field order nor operator sequencing: it
|
|
117
|
+
* compiles to `.filter()`, which imposes neither. Every method returns
|
|
118
|
+
* {@link ConstraintResult}, so this shares the indexed builder's nominal
|
|
119
|
+
* terminal and needs no positional tracking or terminal states.
|
|
120
|
+
*
|
|
121
|
+
* @typeParam TDoc - Document shape for the resource this rule governs.
|
|
122
|
+
*/
|
|
123
|
+
export interface FilterConstraintBuilder<TDoc> {
|
|
124
|
+
eq<F extends ConstraintField<TDoc>>(field: F, value: ConstraintValue<TDoc, F>): ConstraintResult;
|
|
125
|
+
neq<F extends ConstraintField<TDoc>>(field: F, value: ConstraintValue<TDoc, F>): ConstraintResult;
|
|
126
|
+
gt<F extends ConstraintField<TDoc>>(field: F, value: ConstraintValue<TDoc, F>): ConstraintResult;
|
|
127
|
+
gte<F extends ConstraintField<TDoc>>(field: F, value: ConstraintValue<TDoc, F>): ConstraintResult;
|
|
128
|
+
lt<F extends ConstraintField<TDoc>>(field: F, value: ConstraintValue<TDoc, F>): ConstraintResult;
|
|
129
|
+
lte<F extends ConstraintField<TDoc>>(field: F, value: ConstraintValue<TDoc, F>): ConstraintResult;
|
|
130
|
+
and(...nodes: ConstraintResult[]): ConstraintResult;
|
|
131
|
+
or(...nodes: ConstraintResult[]): ConstraintResult;
|
|
132
|
+
not(node: ConstraintResult): ConstraintResult;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* One recorded positional constraint: `field` is pinned to a literal, `op`
|
|
136
|
+
* is one of {@link IndexOp}, and `value` is typed from the document shape
|
|
137
|
+
* at that field. This is what a `ConstraintBuilder` chain call records
|
|
138
|
+
* (`createConstraintBuilder`, `access/createConstraintBuilder.ts`), and
|
|
139
|
+
* what a later compiler step reads back to build a `withIndex` range, a
|
|
140
|
+
* `FilterBuilder` expression, or a JS predicate — the same recorded data
|
|
141
|
+
* feeds all three, which is the reason a builder replaces a callback.
|
|
142
|
+
*
|
|
143
|
+
* @typeParam TField - The field name this constraint pins.
|
|
144
|
+
* @typeParam TDoc - The document shape `value`'s type is read from.
|
|
145
|
+
*/
|
|
146
|
+
export type AccessIndexConstraint<TField extends string, TDoc> = {
|
|
147
|
+
field: TField;
|
|
148
|
+
op: IndexOp;
|
|
149
|
+
value: ConstraintValue<TDoc, TField>;
|
|
150
|
+
};
|
|
151
|
+
/**
|
|
152
|
+
* Terminal marker for a completed constraint chain. Nominal — a private,
|
|
153
|
+
* unimplementable member — so a plain object literal can never satisfy it;
|
|
154
|
+
* only a real chain call (`eq`/`gt`/`gte`/`lt`/`lte`) can produce one. Every
|
|
155
|
+
* builder stage extends this, so a chain is already assignable to
|
|
156
|
+
* `ConstraintResult` at the exact point Convex would also accept it as
|
|
157
|
+
* complete.
|
|
158
|
+
*/
|
|
159
|
+
export declare abstract class ConstraintResult {
|
|
160
|
+
private _isConstraintResult;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Upper-bound stage of a constraint chain: only `lt`/`lte` remain. Reached
|
|
164
|
+
* after a lower bound (Convex allows at most one upper bound, on the same
|
|
165
|
+
* field, and nothing after it) or directly from `eq` on the index's last
|
|
166
|
+
* field. Extends {@link ConstraintResult} — a chain that never calls
|
|
167
|
+
* `lt`/`lte` is already a valid, complete result.
|
|
168
|
+
*
|
|
169
|
+
* @typeParam TDoc - Document shape constraint values are typed from.
|
|
170
|
+
* @typeParam TField - The field this stage's bounds pin to.
|
|
171
|
+
* @internal
|
|
172
|
+
*/
|
|
173
|
+
export interface UpperBoundConstraintBuilder<TDoc, TField extends string> extends ConstraintResult {
|
|
174
|
+
lt<F extends TField>(field: F, value: ConstraintValue<TDoc, F>): ConstraintResult;
|
|
175
|
+
lte<F extends TField>(field: F, value: ConstraintValue<TDoc, F>): ConstraintResult;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Lower-bound stage of a constraint chain: `gt`/`gte` are available, each
|
|
179
|
+
* closing off further lower bounds but permitting one optional upper bound
|
|
180
|
+
* via the returned {@link UpperBoundConstraintBuilder}.
|
|
181
|
+
*
|
|
182
|
+
* @typeParam TDoc - Document shape constraint values are typed from.
|
|
183
|
+
* @typeParam TField - The field this stage's bounds pin to.
|
|
184
|
+
* @internal
|
|
185
|
+
*/
|
|
186
|
+
export interface LowerBoundConstraintBuilder<TDoc, TField extends string> extends UpperBoundConstraintBuilder<TDoc, TField> {
|
|
187
|
+
gt<F extends TField>(field: F, value: ConstraintValue<TDoc, F>): UpperBoundConstraintBuilder<TDoc, TField>;
|
|
188
|
+
gte<F extends TField>(field: F, value: ConstraintValue<TDoc, F>): UpperBoundConstraintBuilder<TDoc, TField>;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* After `eq` advances the field cursor to `N + 1`: another {@link
|
|
192
|
+
* ConstraintBuilder} positioned at the next field, or the terminal {@link
|
|
193
|
+
* ConstraintResult} when the index is spent (no more fields to constrain).
|
|
194
|
+
*
|
|
195
|
+
* @typeParam TFields - The index's field tuple, in declaration order.
|
|
196
|
+
* @typeParam TDoc - Document shape constraint values are typed from.
|
|
197
|
+
* @typeParam N - The field cursor position `eq` was just called at.
|
|
198
|
+
* @internal
|
|
199
|
+
*/
|
|
200
|
+
export type NextConstraintBuilder<TFields extends readonly string[], TDoc, N extends number> = PlusOne<N> extends TFields["length"] ? ConstraintResult : ConstraintBuilder<TFields, TDoc, PlusOne<N>>;
|
|
201
|
+
/**
|
|
202
|
+
* Position-tracking constraint builder — the type `createConstraintBuilder`
|
|
203
|
+
* (`access/createConstraintBuilder.ts`) returns, and what a rule's
|
|
204
|
+
* `constraints` callback receives. `eq` pins the field at cursor `N` and
|
|
205
|
+
* advances to `N + 1`; `gt`/`gte`/`lt`/`lte` (inherited from {@link
|
|
206
|
+
* LowerBoundConstraintBuilder}) pin the SAME field and close the chain to
|
|
207
|
+
* further constraints. This encodes Convex's complete index rule: zero or
|
|
208
|
+
* more `eq`, then at most one lower bound, then at most one upper bound,
|
|
209
|
+
* fields strictly in index order with no gaps, each value typed per field —
|
|
210
|
+
* violating any of these is a compile error, never a runtime one.
|
|
211
|
+
*
|
|
212
|
+
* @typeParam TFields - The index's field tuple, in declaration order —
|
|
213
|
+
* typically `IndexFieldsFor<slug, indexName>` (`types/generated.ts`).
|
|
214
|
+
* @typeParam TDoc - Document shape constraint values are typed from.
|
|
215
|
+
* @typeParam N - The current field cursor. Defaults to `0`, the index's
|
|
216
|
+
* first field; only `NextConstraintBuilder` advances it.
|
|
217
|
+
*/
|
|
218
|
+
export interface ConstraintBuilder<TFields extends readonly string[], TDoc, N extends number = 0> extends LowerBoundConstraintBuilder<TDoc, TFields[N] & string> {
|
|
219
|
+
eq<F extends TFields[N] & string>(field: F, value: ConstraintValue<TDoc, F>): NextConstraintBuilder<TFields, TDoc, N>;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Terminal marker for a completed access CONDITION — the value a rule's
|
|
223
|
+
* `constraints` callback returns.
|
|
224
|
+
*
|
|
225
|
+
* Deliberately NOT {@link ConstraintResult}. That one marks a completed
|
|
226
|
+
* *expression* inside one algebra's callback; this marks a completed *condition* on
|
|
227
|
+
* the query as a whole. Keeping them separate is what makes the mistake
|
|
228
|
+
* unrepresentable: `FilterConstraintBuilder.and` takes `ConstraintResult`, so an
|
|
229
|
+
* index condition can never be passed into a boolean combinator. Under a single
|
|
230
|
+
* shared terminal it type-checked and produced a filter node with no `kind`, which
|
|
231
|
+
* the compilers silently turned into `undefined` — a rule that appeared to
|
|
232
|
+
* constrain and did not.
|
|
233
|
+
*
|
|
234
|
+
* Nominal for the same reason as `ConstraintResult`: a plain object literal must
|
|
235
|
+
* not satisfy it, so only a real `q.withIndex(…)` / `q.filter(…)` call can produce
|
|
236
|
+
* one.
|
|
237
|
+
*/
|
|
238
|
+
export declare abstract class AccessConditionResult {
|
|
239
|
+
private _isAccessConditionResult;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* An index-backed condition, which may still add a filter.
|
|
243
|
+
*
|
|
244
|
+
* Returned by {@link AccessQueryBuilder.withIndex}. Already a complete condition on
|
|
245
|
+
* its own — return it directly for index-only narrowing — or continue with
|
|
246
|
+
* `.filter(…)` to add predicates the index range cannot express.
|
|
247
|
+
*
|
|
248
|
+
* @typeParam TDoc - Document shape for the resource this rule governs.
|
|
249
|
+
*/
|
|
250
|
+
export interface IndexedAccessCondition<TDoc> extends AccessConditionResult {
|
|
251
|
+
/**
|
|
252
|
+
* Adds a per-document predicate alongside the index range.
|
|
253
|
+
*
|
|
254
|
+
* Compiles to `.withIndex(name, range).filter(expr)` — Convex's own shape, and
|
|
255
|
+
* the reason both halves can coexist: the range narrows what is READ, the filter
|
|
256
|
+
* rejects rows within it that the range cannot describe (`neq`, `or`, `not`).
|
|
257
|
+
*
|
|
258
|
+
* @param predicate - Builds the expression from the flat filter algebra.
|
|
259
|
+
* @returns The completed condition.
|
|
260
|
+
*/
|
|
261
|
+
filter(predicate: (q: FilterConstraintBuilder<TDoc>) => ConstraintResult): AccessConditionResult;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* The `q` a rule on a NON-query action receives: predicates only.
|
|
265
|
+
*
|
|
266
|
+
* The same authoring shape as {@link AccessQueryBuilder} minus `withIndex`, so a
|
|
267
|
+
* rule reads identically whichever action it guards — `q.filter((f) => …)` either
|
|
268
|
+
* way. A create/update/delete has no query to narrow, so index pushdown is simply
|
|
269
|
+
* absent rather than rejected, and `q.withIndex` fails at the call with a
|
|
270
|
+
* missing-method error rather than as a whole-object shape mismatch (DD 14).
|
|
271
|
+
*
|
|
272
|
+
* @typeParam TDoc - Document shape for the resource this rule governs.
|
|
273
|
+
*/
|
|
274
|
+
export interface AccessPredicateBuilder<TDoc> {
|
|
275
|
+
/**
|
|
276
|
+
* Narrows by predicate.
|
|
277
|
+
*
|
|
278
|
+
* @param predicate - Builds the expression from the flat filter algebra.
|
|
279
|
+
* @returns The completed condition.
|
|
280
|
+
*/
|
|
281
|
+
filter(predicate: (q: FilterConstraintBuilder<TDoc>) => ConstraintResult): AccessConditionResult;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* The `q` a query-shaped rule receives.
|
|
285
|
+
*
|
|
286
|
+
* Mirrors Convex's own query surface, one layer up — each algebra gets its own
|
|
287
|
+
* callback with its own builder, and the two never meet in one expression:
|
|
288
|
+
*
|
|
289
|
+
* ```ts
|
|
290
|
+
* // Convex
|
|
291
|
+
* ctx.db.query("pages")
|
|
292
|
+
* .withIndex("by_author", (q) => q.eq("authorId", u))
|
|
293
|
+
* .filter((q) => q.neq(q.field("archived"), true));
|
|
294
|
+
*
|
|
295
|
+
* // an access rule
|
|
296
|
+
* q.withIndex("by_author", (ix) => ix.eq("authorId", u))
|
|
297
|
+
* .filter((f) => f.neq("archived", true));
|
|
298
|
+
* ```
|
|
299
|
+
*
|
|
300
|
+
* That confinement is load-bearing, not stylistic: `ix` exists only inside the
|
|
301
|
+
* range callback and `f` only inside the predicate callback, so an index expression
|
|
302
|
+
* cannot reach a boolean combinator even by accident.
|
|
303
|
+
*
|
|
304
|
+
* Selecting the index through a METHOD is also what makes positional typing
|
|
305
|
+
* reachable — `N` is the method's own type parameter, so the literal at the call
|
|
306
|
+
* site resolves that index's real field tuple and Convex's field ORDER becomes a
|
|
307
|
+
* compile error. A sibling property cannot be seen by its neighbour's callback
|
|
308
|
+
* type, which is why earlier `{ withIndex, constraints }` shapes could only offer
|
|
309
|
+
* the resource's flat field-key union.
|
|
310
|
+
*
|
|
311
|
+
* Rules on mutation actions receive a bare {@link FilterConstraintBuilder} instead
|
|
312
|
+
* — no query exists to narrow, so `withIndex` is absent rather than rejected.
|
|
313
|
+
*
|
|
314
|
+
* @typeParam TDoc - Document shape for the resource this rule governs.
|
|
315
|
+
* @typeParam TIndexFields - The resource's declared indexes, name → field tuple
|
|
316
|
+
* in declaration order (`IndexFieldsBySlug[slug]`, `types/generated.ts`).
|
|
317
|
+
*/
|
|
318
|
+
export interface AccessQueryBuilder<TDoc, TIndexFields extends Record<string, readonly string[]>> extends AccessPredicateBuilder<TDoc> {
|
|
319
|
+
/**
|
|
320
|
+
* Narrows the query through a declared index.
|
|
321
|
+
*
|
|
322
|
+
* **The range callback is REQUIRED**, unlike Convex's, where it is optional. A
|
|
323
|
+
* range-less `withIndex` excludes no documents — every row has an index entry, so
|
|
324
|
+
* it only re-orders, and the docs are explicit that it scans the whole table.
|
|
325
|
+
* Convex allows it because a caller may legitimately want ordering; an access rule
|
|
326
|
+
* never does, and a range-less one would read as a restriction while being none.
|
|
327
|
+
*
|
|
328
|
+
* @typeParam N - The index name, inferred from the literal passed.
|
|
329
|
+
* @param name - A declared index on this resource.
|
|
330
|
+
* @param range - Builds the range. `ix` is positional: Convex's index rules,
|
|
331
|
+
* field order included, apply inside it.
|
|
332
|
+
* @returns A condition that may be returned as-is or continued with `.filter(…)`.
|
|
333
|
+
*/
|
|
334
|
+
withIndex<N extends keyof TIndexFields & string>(name: N, range: (ix: ConstraintBuilder<TIndexFields[N], TDoc, 0>) => ConstraintResult): IndexedAccessCondition<TDoc>;
|
|
335
|
+
}
|
|
336
|
+
export {};
|
|
337
|
+
//# sourceMappingURL=constraintTypes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constraintTypes.d.ts","sourceRoot":"","sources":["../../src/access/constraintTypes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { AccessConditionResult, AccessFilterConstraint, AccessIndexConstraint, AccessQueryBuilder, IndexedAccessCondition } from "./constraintTypes";
|
|
2
|
+
/**
|
|
3
|
+
* What a rule's `constraints` callback resolved to: the condition on which
|
|
4
|
+
* documents the caller may read.
|
|
5
|
+
*
|
|
6
|
+
* Either half may be present, and **both together is the normal case, not a
|
|
7
|
+
* conflict** — it is exactly `.withIndex(name, range).filter(expr)`, Convex's own
|
|
8
|
+
* shape. The range narrows what is READ; the filter rejects rows within that range
|
|
9
|
+
* which the range cannot describe (`neq`, `or`, `not`).
|
|
10
|
+
*
|
|
11
|
+
* Neither present means the callback returned a condition that excludes nothing.
|
|
12
|
+
* Absence of a condition altogether is `undefined`, not an empty object.
|
|
13
|
+
*
|
|
14
|
+
* @typeParam TDoc - Document shape the values are typed against.
|
|
15
|
+
*/
|
|
16
|
+
export interface AccessCondition<TDoc> {
|
|
17
|
+
/** The index the rule chose, and the range it built on it. */
|
|
18
|
+
index?: {
|
|
19
|
+
/** Declared index name passed to `q.withIndex(…)`. */
|
|
20
|
+
name: string;
|
|
21
|
+
/** The range, in call order. Never empty — the range callback is required. */
|
|
22
|
+
constraints: readonly AccessIndexConstraint<string, TDoc>[];
|
|
23
|
+
};
|
|
24
|
+
/** Root of the predicate tree, when the rule added or used `filter`. */
|
|
25
|
+
filter?: AccessFilterConstraint<TDoc>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Creates the `q` a query-shaped rule receives.
|
|
29
|
+
*
|
|
30
|
+
* Composes the two algebras without letting them mix: `withIndex` runs its range
|
|
31
|
+
* callback against a fresh positional builder and reads the result; `filter` runs
|
|
32
|
+
* its predicate callback against a fresh flat builder. Neither builder escapes its
|
|
33
|
+
* callback, so an index expression can never reach a boolean combinator.
|
|
34
|
+
*
|
|
35
|
+
* **Pure, and only the returned value counts.** Nothing accumulates outside a
|
|
36
|
+
* callback's own return, so a rule that builds a chain and discards it contributes
|
|
37
|
+
* nothing — dead code behaves like dead code.
|
|
38
|
+
*
|
|
39
|
+
* @typeParam TDoc - Document shape constraint values are typed from.
|
|
40
|
+
* @typeParam TIndexFields - The resource's index name → field tuple map.
|
|
41
|
+
* @returns A builder whose `withIndex` / `filter` results carry the condition.
|
|
42
|
+
*/
|
|
43
|
+
export declare function createAccessQueryBuilder<TDoc, TIndexFields extends Record<string, readonly string[]>>(): AccessQueryBuilder<TDoc, TIndexFields>;
|
|
44
|
+
/**
|
|
45
|
+
* Reads the condition a returned terminal carries.
|
|
46
|
+
*
|
|
47
|
+
* The counterpart to the casts above: `AccessConditionResult` is nominal and has no
|
|
48
|
+
* public shape, so only this module can get the condition back out.
|
|
49
|
+
*
|
|
50
|
+
* @typeParam TDoc - Document shape the values are typed against.
|
|
51
|
+
* @param result - The value a rule's `constraints` callback returned.
|
|
52
|
+
* @returns Its condition, or `undefined` when `result` did not come from this
|
|
53
|
+
* module — unreachable through the types, and treated as "no condition" so a rule
|
|
54
|
+
* that reached past them cannot silently widen into an unfiltered read.
|
|
55
|
+
*/
|
|
56
|
+
export declare function readAccessCondition<TDoc>(result: AccessConditionResult): AccessCondition<TDoc> | undefined;
|
|
57
|
+
/** Re-exported so the type name travels with its reader. */
|
|
58
|
+
export type { IndexedAccessCondition };
|
|
59
|
+
//# sourceMappingURL=createAccessQueryBuilder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createAccessQueryBuilder.d.ts","sourceRoot":"","sources":["../../src/access/createAccessQueryBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,EACrB,kBAAkB,EAElB,sBAAsB,EACvB,MAAM,mBAAmB,CAAC;AAI3B;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,eAAe,CAAC,IAAI;IACnC,8DAA8D;IAC9D,KAAK,CAAC,EAAE;QACN,sDAAsD;QACtD,IAAI,EAAE,MAAM,CAAC;QACb,8EAA8E;QAC9E,WAAW,EAAE,SAAS,qBAAqB,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC;KAC7D,CAAC;IACF,wEAAwE;IACxE,MAAM,CAAC,EAAE,sBAAsB,CAAC,IAAI,CAAC,CAAC;CACvC;AAQD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EACJ,YAAY,SAAS,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,KACnD,kBAAkB,CAAC,IAAI,EAAE,YAAY,CAAC,CAyC1C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EACtC,MAAM,EAAE,qBAAqB,GAC5B,eAAe,CAAC,IAAI,CAAC,GAAG,SAAS,CAUnC;AAED,4DAA4D;AAC5D,YAAY,EAAE,sBAAsB,EAAE,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { FilterConstraintBuilder } from "./constraintTypes";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a fresh unindexed constraint builder: the `q` a rule receives when it
|
|
4
|
+
* declares no `withIndex` (DD 13). Comparisons produce a `compare` node;
|
|
5
|
+
* `and`/`or`/`not` wrap the nodes their arguments produced, so a whole
|
|
6
|
+
* expression evaluates bottom-up into one tree.
|
|
7
|
+
*
|
|
8
|
+
* Unlike {@link createIndexConstraintBuilder} this takes **no sink and keeps no
|
|
9
|
+
* state**. The indexed builder records a flat sequence, so someone has to own the
|
|
10
|
+
* list; here the combinators consume values and return values, which means the
|
|
11
|
+
* callback's own return value already *is* the root of the tree. Two calls to this
|
|
12
|
+
* factory cannot interfere because there is nothing to interfere with — every node
|
|
13
|
+
* is freshly allocated and reachable only through what the caller was handed.
|
|
14
|
+
*
|
|
15
|
+
* The framework reads the result by reinterpreting the returned
|
|
16
|
+
* {@link ConstraintResult} as {@link AccessFilterConstraint} — the same erasure this
|
|
17
|
+
* module performs internally on combinator arguments. `ConstraintResult` is nominal
|
|
18
|
+
* precisely so a rule cannot hand back a hand-built object literal; only a real
|
|
19
|
+
* chain call can produce one.
|
|
20
|
+
*
|
|
21
|
+
* @typeParam TDoc - Document shape for the resource this rule governs.
|
|
22
|
+
* @returns A stateless builder. Every call returns an independent object, and
|
|
23
|
+
* nothing is shared between them.
|
|
24
|
+
*/
|
|
25
|
+
export declare function createFilterConstraintBuilder<TDoc>(): FilterConstraintBuilder<TDoc>;
|
|
26
|
+
//# sourceMappingURL=createFilterConstraintBuilder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createFilterConstraintBuilder.d.ts","sourceRoot":"","sources":["../../src/access/createFilterConstraintBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAKV,uBAAuB,EAExB,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,6BAA6B,CAAC,IAAI,KAAK,uBAAuB,CAAC,IAAI,CAAC,CA6DnF"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { AccessIndexConstraint, ConstraintBuilder, ConstraintResult } from "./constraintTypes";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a positional constraint builder — the `ix` a rule receives inside
|
|
4
|
+
* `q.withIndex(name, (ix) => …)`.
|
|
5
|
+
*
|
|
6
|
+
* **Pure.** Every method returns a NEW builder carrying the accumulated list; there
|
|
7
|
+
* is no shared array and no caller-owned sink. That is what makes "only the value
|
|
8
|
+
* the callback RETURNS counts" true rather than aspirational: a chain the rule
|
|
9
|
+
* builds and discards leaves nothing behind, exactly like any other dead expression.
|
|
10
|
+
* The earlier `{ into }` sink made discarded chains apply anyway, which surprised in
|
|
11
|
+
* the one direction that matters — a rule doing more than it appeared to.
|
|
12
|
+
*
|
|
13
|
+
* The TYPE narrows per call — {@link ConstraintBuilder}'s three-interface state
|
|
14
|
+
* machine only exposes the methods still legal at each position. The RUNTIME object
|
|
15
|
+
* does not: each node carries all five methods, cast to the narrowing type on
|
|
16
|
+
* return. Type safety is enforced entirely at the call site, never here.
|
|
17
|
+
*
|
|
18
|
+
* @typeParam TFields - The index's field tuple, in declaration order.
|
|
19
|
+
* @typeParam TDoc - The document shape constraint values are typed from.
|
|
20
|
+
* @returns A builder positioned at field 0, with nothing accumulated.
|
|
21
|
+
*/
|
|
22
|
+
export declare function createIndexConstraintBuilder<TFields extends readonly string[], TDoc>(): ConstraintBuilder<TFields, TDoc>;
|
|
23
|
+
/**
|
|
24
|
+
* Reads the constraints a returned positional chain accumulated.
|
|
25
|
+
*
|
|
26
|
+
* The counterpart to the cast above: `ConstraintResult` is nominal and carries no
|
|
27
|
+
* public shape, so only this module can get the list back out. Called by
|
|
28
|
+
* `createAccessQueryBuilder` on whatever the range callback returned — which is why
|
|
29
|
+
* a discarded chain contributes nothing.
|
|
30
|
+
*
|
|
31
|
+
* @typeParam TDoc - The document shape constraint values are typed from.
|
|
32
|
+
* @param result - The value a range callback returned.
|
|
33
|
+
* @returns Its accumulated constraints, in call order. `[]` when `result` did not
|
|
34
|
+
* come from this module — unreachable through the types, and treated as "no
|
|
35
|
+
* constraints" rather than throwing, since `validateAccessConstraints` owns
|
|
36
|
+
* diagnosing a rule that reached past them.
|
|
37
|
+
* @internal
|
|
38
|
+
*/
|
|
39
|
+
export declare function readIndexConstraints<TDoc>(result: ConstraintResult): readonly AccessIndexConstraint<string, TDoc>[];
|
|
40
|
+
//# sourceMappingURL=createIndexConstraintBuilder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createIndexConstraintBuilder.d.ts","sourceRoot":"","sources":["../../src/access/createIndexConstraintBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,EAEjB,MAAM,mBAAmB,CAAC;AAa3B;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,SAAS,SAAS,MAAM,EAAE,EACjC,IAAI,KACD,iBAAiB,CAAC,OAAO,EAAE,IAAI,CAAC,CA0CpC;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EACvC,MAAM,EAAE,gBAAgB,GACvB,SAAS,qBAAqB,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAGhD"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { PermissionScope } from "./constants";
|
|
2
|
+
import type { PermissionCheck, SubjectEntry, VexAccessConfig } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* Props required for the hasPermission({...}) function
|
|
5
|
+
*
|
|
6
|
+
* @param access - The resolved config from `defineAccess()`. `undefined`
|
|
7
|
+
* disables access control entirely — every check passes.
|
|
8
|
+
* @param user - The authenticated user document. Roles are derived from
|
|
9
|
+
* `user[access.userRolesField]` (`string` or `string[]`); a missing or empty
|
|
10
|
+
* value falls back to access.anonRole
|
|
11
|
+
* @param organization - The organization document forwarded to callbacks.
|
|
12
|
+
* Only surfaces when `access.orgCollectionSlug` is configured.
|
|
13
|
+
* @param resource - Subject name — a resource slug, a built-in subject
|
|
14
|
+
* (e.g. `"adminPanel"`), or a custom resource name.
|
|
15
|
+
* @param action - Action on `resource`, typed per subject.
|
|
16
|
+
* @param data - Document/context forwarded to permission callbacks.
|
|
17
|
+
* @param throwOnDenied - When `true`, throws `VexAccessError` instead of
|
|
18
|
+
* @param scope Which question to answer when a role's check is a callback that
|
|
19
|
+
* needs the document and `data` was not supplied:
|
|
20
|
+
* `"all"` (default) asks "may they do this to every document" and resolves such
|
|
21
|
+
* a check to `false` — fail-closed, never throws; `"any"` asks "may they do this
|
|
22
|
+
* to at least one document" and resolves it to `true` (nav/sidebar/list gating —
|
|
23
|
+
* row-level filtering happens separately in `find`/`get`); `"doc"` demands an
|
|
24
|
+
* exact per-document answer and throws `VexAccessError` when `data` is missing,
|
|
25
|
+
* which is what you want in edit views. Has no effect on static boolean checks,
|
|
26
|
+
* and no effect when `data` is provided (the callback is always run against it).
|
|
27
|
+
* @default "all"
|
|
28
|
+
*/
|
|
29
|
+
export interface HasPermissionProps<TSubjects extends Record<string, SubjectEntry> = Record<string, SubjectEntry>, TSubject extends keyof TSubjects & string = keyof TSubjects & string, TData extends {} = {}> {
|
|
30
|
+
access?: VexAccessConfig<TSubjects>;
|
|
31
|
+
user: Record<string, unknown> | null;
|
|
32
|
+
organization?: Record<string, unknown>;
|
|
33
|
+
resource: TSubject;
|
|
34
|
+
action: TSubjects[TSubject]["action"];
|
|
35
|
+
data?: TData;
|
|
36
|
+
throwOnDenied?: boolean;
|
|
37
|
+
scope?: PermissionScope;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Resolves runtime role-based access for a single subject + action, merging
|
|
41
|
+
* every role the user holds into one decision.
|
|
42
|
+
*
|
|
43
|
+
* This is the single runtime entry point — every server API guard, admin panel
|
|
44
|
+
* gate, and custom-subject check calls it; the resolution helpers below are
|
|
45
|
+
* module-private.
|
|
46
|
+
*
|
|
47
|
+
* Resolution, per role, first hit wins: subject boolean shorthand → explicit
|
|
48
|
+
* action key → subject-level `WILDCARD_KEY` → role-level `WILDCARD_KEY`
|
|
49
|
+
* (undeclared subjects only) → `defaultPermissionMode`. Roles then OR-merge:
|
|
50
|
+
* any role allowing allows.
|
|
51
|
+
*
|
|
52
|
+
* @param props @see {@link HasPermissionProps}
|
|
53
|
+
* @returns `true` when the action is permitted for the caller.
|
|
54
|
+
* @throws {VexAccessError} When `throwOnDenied` is `true` and access is denied —
|
|
55
|
+
* carries `resource` and `action`.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```ts
|
|
59
|
+
* hasPermission({ access, user, resource: "posts", action: "update" }); // boolean
|
|
60
|
+
* hasPermission({ access, user, resource: "posts", action: "delete",
|
|
61
|
+
* data: post, throwOnDenied: true }); // throws VexAccessError on deny
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export declare function hasPermission<TSubjects extends Record<string, SubjectEntry>, TSubject extends keyof TSubjects & string, TData extends {}>(props: HasPermissionProps<TSubjects, TSubject, TData>): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Resolves a single action's check from a per-action map, consulting the
|
|
67
|
+
* action-level wildcard when the explicit action isn't declared.
|
|
68
|
+
*
|
|
69
|
+
* The wildcard precedence lives in exactly one place so `hasPermission`,
|
|
70
|
+
* `resolveAccessIndex`, and any future evaluator (e.g. DB-backed roles) share
|
|
71
|
+
* it. Presence, not truthiness, decides: an explicit `false` still wins over
|
|
72
|
+
* the wildcard.
|
|
73
|
+
*
|
|
74
|
+
* @param props - Input props.
|
|
75
|
+
* @param props.resource - The per-action map declared for one role + resource.
|
|
76
|
+
* @param props.action - The action being resolved.
|
|
77
|
+
* @returns The declared check for `action`, else the wildcard's check, else
|
|
78
|
+
* `undefined` (caller falls through to `defaultPermissionMode`).
|
|
79
|
+
* @internal
|
|
80
|
+
*/
|
|
81
|
+
export declare function resolveActionCheck(props: {
|
|
82
|
+
resource: Record<string, unknown>;
|
|
83
|
+
action: string;
|
|
84
|
+
}): PermissionCheck | undefined;
|
|
85
|
+
//# sourceMappingURL=hasPermission.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hasPermission.d.ts","sourceRoot":"","sources":["../../src/access/hasPermission.ts"],"names":[],"mappings":"AACA,OAAO,EAAuC,eAAe,EAAgB,MAAM,aAAa,CAAC;AAIjG,OAAO,KAAK,EAEV,eAAe,EACf,YAAY,EACZ,eAAe,EAChB,MAAM,SAAS,CAAC;AAEjB;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,WAAW,kBAAkB,CACjC,SAAS,SAAS,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,EAC7E,QAAQ,SAAS,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,SAAS,GAAG,MAAM,EACpE,KAAK,SAAS,EAAE,GAAG,EAAE;IAErB,MAAM,CAAC,EAAE,eAAe,CAAC,SAAS,CAAC,CAAC;IACpC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAC;IACtC,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,KAAK,CAAC,EAAE,eAAe,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,aAAa,CAC3B,SAAS,SAAS,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,EAC9C,QAAQ,SAAS,MAAM,SAAS,GAAG,MAAM,EACzC,KAAK,SAAS,EAAE,EAChB,KAAK,EAAE,kBAAkB,CAAC,SAAS,EAAE,QAAQ,EAAE,KAAK,CAAC,GAAG,OAAO,CAwEhE;AAmMD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IACxC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,eAAe,GAAG,SAAS,CAQ9B"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export * from "./constants";
|
|
2
|
+
export * from "./types";
|
|
3
|
+
export * from "./config";
|
|
4
|
+
export * from "./hasPermission";
|
|
5
|
+
export * from "./canAccessAdminPanel";
|
|
6
|
+
export * from "./resolveAccessRule";
|
|
7
|
+
export * from "./pickQueryIndex";
|
|
8
|
+
export * from "./constraintTypes";
|
|
9
|
+
export * from "./createIndexConstraintBuilder";
|
|
10
|
+
export * from "./createFilterConstraintBuilder";
|
|
11
|
+
export * from "./createAccessQueryBuilder";
|
|
12
|
+
export * from "./buildChecks";
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/access/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iCAAiC,CAAC;AAChD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,eAAe,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { IndexRangeFn, QueryIndex } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Chooses the single index a query will use, arbitrating between an
|
|
4
|
+
* access-contributed index and whatever the caller explicitly requested.
|
|
5
|
+
* Convex permits exactly one `withIndex` per query, so exactly one wins.
|
|
6
|
+
*
|
|
7
|
+
* 1. Caller's index wins the slot when it names a DIFFERENT index — usually a
|
|
8
|
+
* highly selective lookup; the access `filter` still enforces the rule per
|
|
9
|
+
* document (`hasPermission`), so this only ever costs reads, never
|
|
10
|
+
* correctness.
|
|
11
|
+
* 2. Same name ⇒ ranges merge, so the compound constraint (access's prefix AND
|
|
12
|
+
* the caller's continuation) is served by one query, no degradation.
|
|
13
|
+
* 3. Free slot (no caller index) ⇒ the access index claims it — the common
|
|
14
|
+
* list-view case, where the view passes no index of its own.
|
|
15
|
+
*
|
|
16
|
+
* Never authorizes: whichever index wins, the access rule's `filter` runs per
|
|
17
|
+
* document. Arbitration decides how many rows get read, not which are allowed.
|
|
18
|
+
*
|
|
19
|
+
* @param props - Input props.
|
|
20
|
+
* @param props.accessIndex - `resolveAccessIndex`'s result for this query, if any.
|
|
21
|
+
* @param props.callerIndex - The index the caller explicitly requested, if any.
|
|
22
|
+
* Its `range` is optional, mirroring `find`'s `withIndex` arg — a caller may
|
|
23
|
+
* name an index purely to order results.
|
|
24
|
+
* @returns The index to apply, or `undefined` when neither side supplies one
|
|
25
|
+
* (an un-narrowed scan, today's behavior).
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* pickQueryIndex({
|
|
30
|
+
* accessIndex: { name: "by_author", range: (q) => q.eq("authorId", "u1") },
|
|
31
|
+
* });
|
|
32
|
+
* // → { name: "by_author", range: … } (free slot)
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare function pickQueryIndex(props: {
|
|
36
|
+
accessIndex?: QueryIndex;
|
|
37
|
+
callerIndex?: {
|
|
38
|
+
name: string;
|
|
39
|
+
range?: IndexRangeFn;
|
|
40
|
+
};
|
|
41
|
+
}): QueryIndex | undefined;
|
|
42
|
+
//# sourceMappingURL=pickQueryIndex.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pickQueryIndex.d.ts","sourceRoot":"","sources":["../../src/access/pickQueryIndex.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAwExD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE;IACpC,WAAW,CAAC,EAAE,UAAU,CAAC;IACzB,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,YAAY,CAAA;KAAE,CAAC;CACtD,GAAG,UAAU,GAAG,SAAS,CA4BzB"}
|