@vxil/cli 0.27.0 → 0.29.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/_vxil-feature-configs-readmodels.d.ts +30 -0
- package/dist/_vxil-feature-configs.d.ts +19 -2
- package/dist/config.d.ts +22 -2
- package/dist/vxil-main.js +459 -70
- package/package.json +3 -3
|
@@ -52,6 +52,26 @@ export declare function isOrgChannelTemplate(channel: string): boolean;
|
|
|
52
52
|
* `org:<id>`). Null (publish nothing) for a non-template or an org id that is
|
|
53
53
|
* not a string matching ORG_CHANNEL_ID_RE — fail closed. */
|
|
54
54
|
export declare function resolveOrgChannel(template: string, orgId: unknown): string | null;
|
|
55
|
+
/** MX-1022-CDC-OWNER-CHANNEL: the owner template token — one WHOLE segment of a
|
|
56
|
+
* cdc `channel` on an owner-scoped (ownerField) collection. Each row publishes
|
|
57
|
+
* to its owner's private channel `user:<owner>:<rest>` (realtime-v1
|
|
58
|
+
* userChannelDenied binds an end-user token for a `user:` channel to its
|
|
59
|
+
* verified id). Never combined with `{org}` in one channel. */
|
|
60
|
+
export declare const CDC_OWNER_TOKEN = "{owner}";
|
|
61
|
+
/** Every resolved owner channel starts with this prefix (realtime-v1
|
|
62
|
+
* token.ts USER_CHANNEL_PREFIX; the `cdc-gated-fields` gate pins both equal). */
|
|
63
|
+
export declare const USER_CHANNEL_PREFIX = "user:";
|
|
64
|
+
/** An owner id that may enter a channel name: no ':' / '@' (realtime refuses
|
|
65
|
+
* such ids every `user:` channel anyway), ≤ 128 chars. */
|
|
66
|
+
export declare const OWNER_CHANNEL_ID_RE: RegExp;
|
|
67
|
+
/** Is `channel` an owner template — exactly one segment equal to `{owner}`,
|
|
68
|
+
* every other segment a non-empty channel-alphabet run, ≤ 128 chars? */
|
|
69
|
+
export declare function isOwnerChannelTemplate(channel: string): boolean;
|
|
70
|
+
/** Resolve an owner template for one row: drop the `{owner}` segment and prefix
|
|
71
|
+
* `user:<id>:` (`meals:{owner}` → `user:<id>:meals`). Null (publish nothing)
|
|
72
|
+
* for a non-template, an owner id that is not a string matching
|
|
73
|
+
* OWNER_CHANNEL_ID_RE, or a result past realtime's 200-char cap — fail closed. */
|
|
74
|
+
export declare function resolveOwnerChannel(template: string, ownerId: unknown): string | null;
|
|
55
75
|
/** Cross-field rule for CmsConfig.cdc (called from validateFeatureConfig). */
|
|
56
76
|
export declare function validateCdcConfig(cdc: Record<string, CdcRuleLike> | undefined): string[];
|
|
57
77
|
/** What a payload:'full' change-data rule must know about its target
|
|
@@ -90,4 +110,14 @@ export declare function cdcFullFramesOverGatedCollections(cdc: unknown, collecti
|
|
|
90
110
|
* Pure; one problem line per offending ENABLED rule.
|
|
91
111
|
*/
|
|
92
112
|
export declare function cdcFixedChannelsOverOrgCollections(cdc: unknown, collections: Record<string, CdcCollectionGates>): string[];
|
|
113
|
+
/**
|
|
114
|
+
* MX-1022-CDC-OWNER-CHANNEL: an `{owner}` rule is valid only on an owner-scoped
|
|
115
|
+
* collection (a live `ownerField`) that is NOT a workspace collection: a
|
|
116
|
+
* `user:` channel skips realtime's active-org check, so a member removed from a
|
|
117
|
+
* workspace who still owns rows there would keep receiving them — `{org}`
|
|
118
|
+
* serves workspace collections. The cms runtime floor (cdc.ts cdcChannelFor)
|
|
119
|
+
* publishes nothing for such a rule at every door that cannot check. Pure; one
|
|
120
|
+
* problem line per offending ENABLED rule (an unknown collection is skipped).
|
|
121
|
+
*/
|
|
122
|
+
export declare function cdcOwnerRulesOverNonOwnerCollections(cdc: unknown, collections: Record<string, CdcCollectionGates>): string[];
|
|
93
123
|
export {};
|
|
@@ -313,6 +313,7 @@ export declare const AuthConfigSchema: import("@sinclair/typebox").TObject<{
|
|
|
313
313
|
resendCooldownSec: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TInteger>;
|
|
314
314
|
}>>;
|
|
315
315
|
registryAdopt: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
|
|
316
|
+
userIdFormat: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"ulid">, import("@sinclair/typebox").TLiteral<"uuid">]>>;
|
|
316
317
|
otp: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
|
|
317
318
|
enabled: import("@sinclair/typebox").TBoolean;
|
|
318
319
|
codeTtlMinutes: import("@sinclair/typebox").TInteger;
|
|
@@ -710,6 +711,7 @@ export declare const AiConfigSchema: import("@sinclair/typebox").TObject<{
|
|
|
710
711
|
system: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
711
712
|
schema: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TUnknown>>;
|
|
712
713
|
}>>>;
|
|
714
|
+
testMarkers: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
|
|
713
715
|
}>;
|
|
714
716
|
export type AiConfig = Static<typeof AiConfigSchema>;
|
|
715
717
|
export declare const RagConfigSchema: import("@sinclair/typebox").TObject<{
|
|
@@ -805,6 +807,13 @@ export declare const PaymentsConfigSchema: import("@sinclair/typebox").TObject<{
|
|
|
805
807
|
deferDowngrades: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
|
|
806
808
|
subPeriodGrants: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
|
|
807
809
|
}>>;
|
|
810
|
+
refunds: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
|
|
811
|
+
cancelAtProvider: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"off">, import("@sinclair/typebox").TLiteral<"period_end">, import("@sinclair/typebox").TLiteral<"immediately">]>>;
|
|
812
|
+
}>>;
|
|
813
|
+
disputes: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
|
|
814
|
+
cancelAtProvider: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"off">, import("@sinclair/typebox").TLiteral<"period_end">]>>;
|
|
815
|
+
}>>;
|
|
816
|
+
shadow: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
|
|
808
817
|
}>;
|
|
809
818
|
export type PaymentsConfig = Static<typeof PaymentsConfigSchema>;
|
|
810
819
|
export declare const FunctionsConfigSchema: import("@sinclair/typebox").TObject<{
|
|
@@ -916,12 +925,12 @@ export type AuthHookEvent = (typeof AUTH_HOOK_EVENTS)[number];
|
|
|
916
925
|
/** The events a `cmsHook` function binding may name — the closed union
|
|
917
926
|
* `packages/config` types on the `cmsHook` trigger, and the keys of the
|
|
918
927
|
* functions-v1 receiver's CMS_HOOK_EVENTS_FOR (beforeCreate → created,
|
|
919
|
-
* beforeUpdate → updated, beforeWrite → both, afterPublish → published). Omitted = beforeWrite. Anything
|
|
928
|
+
* beforeUpdate → updated, beforeWrite → both, afterPublish → published, afterDelete → deleted). Omitted = beforeWrite. Anything
|
|
920
929
|
* else is refused at config write (E-CMSHOOK, 2026-10-01): an unknown name used
|
|
921
930
|
* to fall back to beforeWrite at delivery, so a typo like 'afterCreate' or
|
|
922
931
|
* 'beforeDelete' silently subscribed the function to creates AND updates.
|
|
923
932
|
* A CI gate pins every copy to this list. */
|
|
924
|
-
export declare const CMS_HOOK_EVENTS: readonly ["beforeCreate", "beforeUpdate", "beforeWrite", "afterPublish"];
|
|
933
|
+
export declare const CMS_HOOK_EVENTS: readonly ["beforeCreate", "beforeUpdate", "beforeWrite", "afterPublish", "afterDelete"];
|
|
925
934
|
export type CmsHookEvent = (typeof CMS_HOOK_EVENTS)[number];
|
|
926
935
|
/** The ONE refusal text for an unknown cmsHook binding event (the config
|
|
927
936
|
* validator and the deploy route's early 422 both use it). */
|
|
@@ -1014,3 +1023,11 @@ export declare function isDeclaredRetainDays(v: unknown): v is number | null | u
|
|
|
1014
1023
|
* collection that change applies only under allow-destructive; lengthening
|
|
1015
1024
|
* or clearing keeps more and always applies. */
|
|
1016
1025
|
export declare function retainDaysShortens(declared: number | null, remote: number | null): boolean;
|
|
1026
|
+
/** = cms-v1 core.ts DELETED_RETAIN_DAYS_MAX (a parity test pins the two). */
|
|
1027
|
+
export declare const CMS_DELETED_RETAIN_DAYS_MAX = 29;
|
|
1028
|
+
export declare function isDeclaredDeletedRetainDays(v: unknown): v is number | null | undefined;
|
|
1029
|
+
export declare function isDeclaredOnOwnerErase(v: unknown): v is 'delete' | 'keep' | undefined;
|
|
1030
|
+
/** Does moving from `remote` to `declared` make an erase delete MORE (turning
|
|
1031
|
+
* 'delete' on)? On an existing collection that applies only under
|
|
1032
|
+
* allow-destructive; turning it off always applies. */
|
|
1033
|
+
export declare function onOwnerEraseWidens(declared: 'delete' | 'keep', remote: 'delete' | 'keep'): boolean;
|
package/dist/config.d.ts
CHANGED
|
@@ -140,6 +140,24 @@ export interface CollectionDef {
|
|
|
140
140
|
* shortening it needs `vxil push --allow-destructive` (lengthening or
|
|
141
141
|
* `null` always applies). Carried by BOTH push paths. */
|
|
142
142
|
retainDays?: number | null;
|
|
143
|
+
/** Recovery window for DELETED items, in days (guide ch. 4): a soft-deleted
|
|
144
|
+
* item stays restorable this long before the nightly cleanup purges it for
|
|
145
|
+
* good. An integer 0..29 (0 = purged at the next nightly run, ≤ 24 h), or
|
|
146
|
+
* `null` for the platform default of 30 days. ABSENT = not managed by
|
|
147
|
+
* config. Shortening it on an existing collection needs
|
|
148
|
+
* `vxil push --allow-destructive`. Carried by BOTH push paths. */
|
|
149
|
+
deletedRetainDays?: number | null;
|
|
150
|
+
/** What a GDPR erase of a user does to the items they OWN here (guide ch. 9;
|
|
151
|
+
* needs `ownerField` — "owner" is whoever that field names):
|
|
152
|
+
* 'keep' (default) — the items stay; the owner id resolves to the
|
|
153
|
+
* erased tombstone user;
|
|
154
|
+
* 'delete' — the erase hard-deletes them (live and deleted, unique values
|
|
155
|
+
* freed) in the same transaction. Relations elsewhere are not
|
|
156
|
+
* cascaded (they keep a dangling id).
|
|
157
|
+
* ABSENT = not managed by config. Turning 'delete' on for an existing
|
|
158
|
+
* collection needs `vxil push --allow-destructive`. Carried by BOTH push
|
|
159
|
+
* paths. */
|
|
160
|
+
onOwnerErase?: 'delete' | 'keep';
|
|
143
161
|
/** Per-record action buttons (guide ch. 4): `[{ key, label, fn }]`, stored on
|
|
144
162
|
* the collection (model data, not a config leaf). The dashboard renders one
|
|
145
163
|
* button per action on each record row; `POST /v1/cms/items/:coll/:id/actions/
|
|
@@ -303,12 +321,14 @@ export type FunctionTrigger =
|
|
|
303
321
|
* `beforeUpdate` → updated only, `beforeWrite` → created|updated,
|
|
304
322
|
* `afterPublish` → published (a draft→published transition is its own event,
|
|
305
323
|
* not an update); a write to another collection never wakes the function.
|
|
306
|
-
*
|
|
324
|
+
* `afterDelete` → deleted (one event per deleted root row — cascaded children
|
|
325
|
+
* and GDPR erase emit none; the payload carries `id`, `owner` (+ `org`), never
|
|
326
|
+
* the row body). Bulk-summary events are not delivered to a cmsHook binding. `event`
|
|
307
327
|
* defaults to `beforeWrite`. */
|
|
308
328
|
| {
|
|
309
329
|
kind: 'cmsHook';
|
|
310
330
|
collection: string;
|
|
311
|
-
event?: 'beforeCreate' | 'beforeUpdate' | 'beforeWrite' | 'afterPublish';
|
|
331
|
+
event?: 'beforeCreate' | 'beforeUpdate' | 'beforeWrite' | 'afterPublish' | 'afterDelete';
|
|
312
332
|
retry?: FunctionTriggerRetry;
|
|
313
333
|
} | {
|
|
314
334
|
kind: 'authHook';
|