@vxil/config 0.1.1 → 0.2.0
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/dist/index.d.ts +43 -3
- package/package.json +7 -3
- package/src/index.ts +44 -3
package/dist/index.d.ts
CHANGED
|
@@ -14,7 +14,39 @@ export interface FieldDef {
|
|
|
14
14
|
relationTo?: string;
|
|
15
15
|
computed?: boolean;
|
|
16
16
|
compute?: unknown;
|
|
17
|
+
/** Claims-table-enforced value uniqueness across live items (cms.md §9.3):
|
|
18
|
+
* a duplicate write is a clean 409 unique_violation. Scalar types only
|
|
19
|
+
* (string/int/float/datetime/relation/file). Carried on collection/field
|
|
20
|
+
* CREATE by `vxil push` and server apply; since 2026-07-17 `vxil push` also
|
|
21
|
+
* RECONCILES it on an existing same-type field (in-place alter via the REST
|
|
22
|
+
* field re-add — packages/cli/src/cms.ts FIELD_ATTRS); attributes push
|
|
23
|
+
* cannot reconcile surface as a visible plan warning, never a silent no-op. */
|
|
24
|
+
unique?: boolean;
|
|
25
|
+
/** Per-relation-field delete behavior (cms.md §11): bounded, atomic fan-out
|
|
26
|
+
* when the referenced item is deleted. Same carriage + reconcile behavior
|
|
27
|
+
* as `unique`. */
|
|
28
|
+
onDelete?: 'cascade' | 'set_null';
|
|
17
29
|
}
|
|
30
|
+
/** The CANONICAL field-attribute name set (config-side spelling), DERIVED from
|
|
31
|
+
* `FieldDef` itself so it can never drift from the authoring type: it is every
|
|
32
|
+
* key of `FieldDef` except `type` (which is required, not an optional carried
|
|
33
|
+
* attribute). This is the compile-time source of truth for the config-carriage
|
|
34
|
+
* completeness ratchet (audit 2026-07-15e #2, roadmap §4.5 P3): the CLI carriage
|
|
35
|
+
* table (`packages/cli/src/cms.ts` FIELD_ATTRS) and the server one
|
|
36
|
+
* (`workers/control-plane/src/handlers/apply.ts` FIELD_ATTR_DELTA) each pin
|
|
37
|
+
* `keyof` coverage against a set that equals this — so a 9th attribute added to
|
|
38
|
+
* `FieldDef` WITHOUT threading it through BOTH push paths is a tsc error naming
|
|
39
|
+
* the uncovered key, not a silent half-carriage. */
|
|
40
|
+
export type FieldAttrName = Exclude<keyof FieldDef, 'type'>;
|
|
41
|
+
/** Compile-time exact-key closure helper: resolves to `Set` iff `Covered`
|
|
42
|
+
* covers EVERY member of `Required` (i.e. `Required` is assignable to
|
|
43
|
+
* `Covered`), else to the specific uncovered key literal(s) — so a `satisfies`
|
|
44
|
+
* against the covered literal union produces a tsc error naming the field the
|
|
45
|
+
* developer forgot to thread through the carriage table. Used by both push
|
|
46
|
+
* paths' carriage tables to gate additions to `FieldAttrName`. */
|
|
47
|
+
export type CoversFieldAttrs<Covered extends FieldAttrName> = [
|
|
48
|
+
FieldAttrName
|
|
49
|
+
] extends [Covered] ? Covered : Exclude<FieldAttrName, Covered>;
|
|
18
50
|
/** A CMS collection-as-code: collection slug → fields. */
|
|
19
51
|
export interface CollectionDef {
|
|
20
52
|
singular?: string;
|
|
@@ -23,9 +55,17 @@ export interface CollectionDef {
|
|
|
23
55
|
* existing `string` field on this collection that holds the owner (end-user)
|
|
24
56
|
* id. When set, the cms worker auto-scopes owned reads/writes to the VERIFIED
|
|
25
57
|
* end-user principal in end-user mode (default-deny) — and is a no-op in
|
|
26
|
-
* server-caller mode.
|
|
27
|
-
* typed worker consults. Omit for shared/reference collections. */
|
|
58
|
+
* server-caller mode. Not a hard-isolation predicate; a single declarative
|
|
59
|
+
* flag the typed worker consults. Omit for shared/reference collections. */
|
|
28
60
|
ownerField?: string;
|
|
61
|
+
/** Public delivery (roadmap §4.4): when true, this collection's PUBLISHED items
|
|
62
|
+
* are servable through the keyless, edge-cached GET /v1/cms/public/:tenantId/
|
|
63
|
+
* :collection lane (no API key). Owner-UNSCOPED (public content, not per-user);
|
|
64
|
+
* the owner_field is stripped from every served row. Default false. Carried by
|
|
65
|
+
* BOTH push paths (the `vxil push` cms reconciler AND control-plane /v1/apply)
|
|
66
|
+
* with a regression test on each — an attribute read by no enforcing path ships
|
|
67
|
+
* inert (the validation.unique / owner_field precedent). */
|
|
68
|
+
public?: boolean;
|
|
29
69
|
}
|
|
30
70
|
/** A function trigger (the §7.3 crossing). cmsHook fires on a CMS write;
|
|
31
71
|
* authHook is the post-signup hook (fires on `auth.user.created`,
|
|
@@ -77,7 +117,7 @@ export interface FunctionDef {
|
|
|
77
117
|
}
|
|
78
118
|
/** A secret REFERENCE (never a value). `vxil secrets set <name>` writes the value. */
|
|
79
119
|
export interface SecretRef {
|
|
80
|
-
/** which feature
|
|
120
|
+
/** which feature the value is encrypted at rest under. */
|
|
81
121
|
feature: string;
|
|
82
122
|
description?: string;
|
|
83
123
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vxil/config",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "defineConfig() — one typed source of truth for a whole vxil backend (features + CMS schema + functions + secret refs + seed). INTERNAL workspace package: bundled into the published `vxil` package's `vxil/config` subpath, not published separately.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://vxil.com",
|
|
@@ -11,14 +11,18 @@
|
|
|
11
11
|
},
|
|
12
12
|
"type": "module",
|
|
13
13
|
"exports": {
|
|
14
|
-
".":
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"import": "./dist/index.js",
|
|
17
|
+
"default": "./dist/index.js"
|
|
18
|
+
}
|
|
15
19
|
},
|
|
16
20
|
"files": [
|
|
17
21
|
"dist",
|
|
18
22
|
"src"
|
|
19
23
|
],
|
|
20
24
|
"dependencies": {
|
|
21
|
-
"@vxil/feature-configs": "0.
|
|
25
|
+
"@vxil/feature-configs": "0.2.0"
|
|
22
26
|
},
|
|
23
27
|
"publishConfig": {
|
|
24
28
|
"access": "public"
|
package/src/index.ts
CHANGED
|
@@ -33,8 +33,41 @@ export interface FieldDef {
|
|
|
33
33
|
relationTo?: string;
|
|
34
34
|
computed?: boolean;
|
|
35
35
|
compute?: unknown;
|
|
36
|
+
/** Claims-table-enforced value uniqueness across live items (cms.md §9.3):
|
|
37
|
+
* a duplicate write is a clean 409 unique_violation. Scalar types only
|
|
38
|
+
* (string/int/float/datetime/relation/file). Carried on collection/field
|
|
39
|
+
* CREATE by `vxil push` and server apply; since 2026-07-17 `vxil push` also
|
|
40
|
+
* RECONCILES it on an existing same-type field (in-place alter via the REST
|
|
41
|
+
* field re-add — packages/cli/src/cms.ts FIELD_ATTRS); attributes push
|
|
42
|
+
* cannot reconcile surface as a visible plan warning, never a silent no-op. */
|
|
43
|
+
unique?: boolean;
|
|
44
|
+
/** Per-relation-field delete behavior (cms.md §11): bounded, atomic fan-out
|
|
45
|
+
* when the referenced item is deleted. Same carriage + reconcile behavior
|
|
46
|
+
* as `unique`. */
|
|
47
|
+
onDelete?: 'cascade' | 'set_null';
|
|
36
48
|
}
|
|
37
49
|
|
|
50
|
+
/** The CANONICAL field-attribute name set (config-side spelling), DERIVED from
|
|
51
|
+
* `FieldDef` itself so it can never drift from the authoring type: it is every
|
|
52
|
+
* key of `FieldDef` except `type` (which is required, not an optional carried
|
|
53
|
+
* attribute). This is the compile-time source of truth for the config-carriage
|
|
54
|
+
* completeness ratchet (audit 2026-07-15e #2, roadmap §4.5 P3): the CLI carriage
|
|
55
|
+
* table (`packages/cli/src/cms.ts` FIELD_ATTRS) and the server one
|
|
56
|
+
* (`workers/control-plane/src/handlers/apply.ts` FIELD_ATTR_DELTA) each pin
|
|
57
|
+
* `keyof` coverage against a set that equals this — so a 9th attribute added to
|
|
58
|
+
* `FieldDef` WITHOUT threading it through BOTH push paths is a tsc error naming
|
|
59
|
+
* the uncovered key, not a silent half-carriage. */
|
|
60
|
+
export type FieldAttrName = Exclude<keyof FieldDef, 'type'>;
|
|
61
|
+
|
|
62
|
+
/** Compile-time exact-key closure helper: resolves to `Set` iff `Covered`
|
|
63
|
+
* covers EVERY member of `Required` (i.e. `Required` is assignable to
|
|
64
|
+
* `Covered`), else to the specific uncovered key literal(s) — so a `satisfies`
|
|
65
|
+
* against the covered literal union produces a tsc error naming the field the
|
|
66
|
+
* developer forgot to thread through the carriage table. Used by both push
|
|
67
|
+
* paths' carriage tables to gate additions to `FieldAttrName`. */
|
|
68
|
+
export type CoversFieldAttrs<Covered extends FieldAttrName> =
|
|
69
|
+
[FieldAttrName] extends [Covered] ? Covered : Exclude<FieldAttrName, Covered>;
|
|
70
|
+
|
|
38
71
|
/** A CMS collection-as-code: collection slug → fields. */
|
|
39
72
|
export interface CollectionDef {
|
|
40
73
|
singular?: string;
|
|
@@ -43,9 +76,17 @@ export interface CollectionDef {
|
|
|
43
76
|
* existing `string` field on this collection that holds the owner (end-user)
|
|
44
77
|
* id. When set, the cms worker auto-scopes owned reads/writes to the VERIFIED
|
|
45
78
|
* end-user principal in end-user mode (default-deny) — and is a no-op in
|
|
46
|
-
* server-caller mode.
|
|
47
|
-
* typed worker consults. Omit for shared/reference collections. */
|
|
79
|
+
* server-caller mode. Not a hard-isolation predicate; a single declarative
|
|
80
|
+
* flag the typed worker consults. Omit for shared/reference collections. */
|
|
48
81
|
ownerField?: string;
|
|
82
|
+
/** Public delivery (roadmap §4.4): when true, this collection's PUBLISHED items
|
|
83
|
+
* are servable through the keyless, edge-cached GET /v1/cms/public/:tenantId/
|
|
84
|
+
* :collection lane (no API key). Owner-UNSCOPED (public content, not per-user);
|
|
85
|
+
* the owner_field is stripped from every served row. Default false. Carried by
|
|
86
|
+
* BOTH push paths (the `vxil push` cms reconciler AND control-plane /v1/apply)
|
|
87
|
+
* with a regression test on each — an attribute read by no enforcing path ships
|
|
88
|
+
* inert (the validation.unique / owner_field precedent). */
|
|
89
|
+
public?: boolean;
|
|
49
90
|
}
|
|
50
91
|
|
|
51
92
|
/** A function trigger (the §7.3 crossing). cmsHook fires on a CMS write;
|
|
@@ -80,7 +121,7 @@ export interface FunctionDef {
|
|
|
80
121
|
|
|
81
122
|
/** A secret REFERENCE (never a value). `vxil secrets set <name>` writes the value. */
|
|
82
123
|
export interface SecretRef {
|
|
83
|
-
/** which feature
|
|
124
|
+
/** which feature the value is encrypted at rest under. */
|
|
84
125
|
feature: string;
|
|
85
126
|
description?: string;
|
|
86
127
|
}
|