@vxil/config 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +44 -25
- package/package.json +2 -2
- package/src/deepPartial.test.ts +24 -0
- package/src/index.ts +45 -24
package/dist/index.d.ts
CHANGED
|
@@ -120,15 +120,25 @@ export type FunctionTrigger = {
|
|
|
120
120
|
source: string;
|
|
121
121
|
}
|
|
122
122
|
/** `webhook`: the function is woken by a webhook_subscription fan-out whose
|
|
123
|
-
* target_url is `<edge>/v1/internal/fn/trigger/<name>?tenant=<id>`.
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
* function
|
|
127
|
-
*
|
|
123
|
+
* target_url is `<edge>/v1/internal/fn/trigger/<name>?tenant=<id>`. That
|
|
124
|
+
* subscription is AUTO-WIRED on deploy (2026-09-19): the platform reconciles
|
|
125
|
+
* one per function declaring this binding, with `event_prefixes` = the
|
|
126
|
+
* function's `source` values — a hand-made one equal in target + prefixes is
|
|
127
|
+
* adopted. `source` is an event-name PREFIX (e.g. 'payments.') or a full event
|
|
128
|
+
* name — lowercase dotted segments, ≤64 chars, validated at deploy — and is
|
|
129
|
+
* also enforced at delivery: a non-matching event is ACK-200 skipped.
|
|
130
|
+
* Declaring the binding is what opts the function into event delivery; a
|
|
131
|
+
* receiver that declares only `cron` keeps the older cron+{} wake. */
|
|
128
132
|
| {
|
|
129
133
|
kind: 'webhook';
|
|
130
134
|
source: string;
|
|
131
|
-
}
|
|
135
|
+
}
|
|
136
|
+
/** `cmsHook`: fires after a CMS write in `collection`. The platform filters
|
|
137
|
+
* deliveries on the binding (2026-09-19): `beforeCreate` → created only,
|
|
138
|
+
* `beforeUpdate` → updated only, `beforeWrite` → created|updated; a write to
|
|
139
|
+
* another collection never wakes the function. Deleted/bulk events are not
|
|
140
|
+
* delivered to a cmsHook binding. */
|
|
141
|
+
| {
|
|
132
142
|
kind: 'cmsHook';
|
|
133
143
|
collection: string;
|
|
134
144
|
event: 'beforeCreate' | 'beforeUpdate' | 'beforeWrite';
|
|
@@ -211,6 +221,15 @@ export type ApiVersion = 'v1';
|
|
|
211
221
|
* only by a real v2. */
|
|
212
222
|
export declare const RELEASED_API_VERSIONS: readonly ApiVersion[];
|
|
213
223
|
/** The whole vxil backend, declared in one typed, version-controlled file. */
|
|
224
|
+
/** Recursive partial: a `vxil.config.ts` may write any SUBSET of a nested bag
|
|
225
|
+
* (`auth: { otp: { enabled: true } }`) — the server applies the defaults for
|
|
226
|
+
* the rest (Value.Default). A shallow `Partial` made `tsc` reject every
|
|
227
|
+
* partially-written nested bag, including the guide's own skeleton
|
|
228
|
+
* (found by the 2026-09-19 cvskit dry-run). Arrays and primitives are kept
|
|
229
|
+
* as-is; only plain object bags recurse. */
|
|
230
|
+
export type DeepPartial<T> = T extends readonly unknown[] ? T : T extends object ? {
|
|
231
|
+
[K in keyof T]?: DeepPartial<T[K]>;
|
|
232
|
+
} : T;
|
|
214
233
|
export interface VxilConfig {
|
|
215
234
|
/** target environment label; resolved to a baseUrl by `vxil link` / `--env`. */
|
|
216
235
|
env?: string;
|
|
@@ -223,25 +242,25 @@ export interface VxilConfig {
|
|
|
223
242
|
* same Value.Default/Clean pipeline the server uses. Keys match FEATURE_SCHEMAS
|
|
224
243
|
* exactly (note the hyphenated ids). */
|
|
225
244
|
features?: {
|
|
226
|
-
notifications?:
|
|
227
|
-
jobs?:
|
|
228
|
-
auth?:
|
|
229
|
-
'rate-limits'?:
|
|
230
|
-
files?:
|
|
231
|
-
webhooks?:
|
|
232
|
-
comments?:
|
|
233
|
-
cms?:
|
|
234
|
-
mcp?:
|
|
235
|
-
realtime?:
|
|
236
|
-
presence?:
|
|
237
|
-
orgs?:
|
|
238
|
-
'activity-feed'?:
|
|
239
|
-
'vector-search'?:
|
|
240
|
-
ai?:
|
|
241
|
-
rag?:
|
|
242
|
-
payments?:
|
|
243
|
-
functions?:
|
|
244
|
-
copilot?:
|
|
245
|
+
notifications?: DeepPartial<NotificationsConfig>;
|
|
246
|
+
jobs?: DeepPartial<JobsConfig>;
|
|
247
|
+
auth?: DeepPartial<AuthConfig>;
|
|
248
|
+
'rate-limits'?: DeepPartial<RateLimitsConfig>;
|
|
249
|
+
files?: DeepPartial<FilesConfig>;
|
|
250
|
+
webhooks?: DeepPartial<WebhooksConfig>;
|
|
251
|
+
comments?: DeepPartial<CommentsConfig>;
|
|
252
|
+
cms?: DeepPartial<CmsConfig>;
|
|
253
|
+
mcp?: DeepPartial<McpConfig>;
|
|
254
|
+
realtime?: DeepPartial<RealtimeConfig>;
|
|
255
|
+
presence?: DeepPartial<PresenceConfig>;
|
|
256
|
+
orgs?: DeepPartial<OrgsConfig>;
|
|
257
|
+
'activity-feed'?: DeepPartial<ActivityFeedConfig>;
|
|
258
|
+
'vector-search'?: DeepPartial<VectorSearchConfig>;
|
|
259
|
+
ai?: DeepPartial<AiConfig>;
|
|
260
|
+
rag?: DeepPartial<RagConfig>;
|
|
261
|
+
payments?: DeepPartial<PaymentsConfig>;
|
|
262
|
+
functions?: DeepPartial<FunctionsConfig>;
|
|
263
|
+
copilot?: DeepPartial<CopilotConfig>;
|
|
245
264
|
};
|
|
246
265
|
/** (b) CMS SCHEMA-AS-CODE — collections + fields. `push` reconciles them
|
|
247
266
|
* additively against GET /v1/cms/collections (no destructive drops without
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vxil/config",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Typed vxil.config.ts authoring for the vxil backend platform — defineConfig, feature and cms field definitions (published for @vxil/cli).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://vxil.com",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"src"
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@vxil/feature-configs": "0.4.
|
|
25
|
+
"@vxil/feature-configs": "0.4.1"
|
|
26
26
|
},
|
|
27
27
|
"publishConfig": {
|
|
28
28
|
"access": "public"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// A `vxil.config.ts` may write any SUBSET of a nested feature bag; the server
|
|
2
|
+
// defaults the rest. This file is COMPILED by the package typecheck, so a
|
|
3
|
+
// regression to a shallow Partial fails `tsc`, not just a runtime assertion
|
|
4
|
+
// (the 2026-09-19 cvskit dry-run found the guide's own skeleton red under tsc).
|
|
5
|
+
import { describe, expect, it } from 'vitest';
|
|
6
|
+
import type { DeepPartial, VxilConfig } from './index.js';
|
|
7
|
+
|
|
8
|
+
const partial: VxilConfig = {
|
|
9
|
+
features: {
|
|
10
|
+
auth: { otp: { enabled: true }, anonymous: { enabled: true } },
|
|
11
|
+
files: { ttl: { enabled: true, defaultExpiresInSeconds: 2592000 } },
|
|
12
|
+
ai: { defaults: { model: 'x' } },
|
|
13
|
+
cms: { limits: { maxItemsPerCollection: 5 } },
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
describe('DeepPartial', () => {
|
|
18
|
+
it('accepts partially-written nested bags (compile-time) and leaves arrays alone', () => {
|
|
19
|
+
type T = DeepPartial<{ a: { b: number; c: string }; list: string[] }>;
|
|
20
|
+
const v: T = { a: { b: 1 }, list: ['x'] };
|
|
21
|
+
expect(v.a?.b).toBe(1);
|
|
22
|
+
expect(partial.features?.auth?.otp?.enabled).toBe(true);
|
|
23
|
+
});
|
|
24
|
+
});
|
package/src/index.ts
CHANGED
|
@@ -138,12 +138,21 @@ export type FunctionTrigger =
|
|
|
138
138
|
| { kind: 'cron'; schedule: string }
|
|
139
139
|
| { kind: 'queue'; source: string }
|
|
140
140
|
/** `webhook`: the function is woken by a webhook_subscription fan-out whose
|
|
141
|
-
* target_url is `<edge>/v1/internal/fn/trigger/<name>?tenant=<id>`.
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
* function
|
|
145
|
-
*
|
|
141
|
+
* target_url is `<edge>/v1/internal/fn/trigger/<name>?tenant=<id>`. That
|
|
142
|
+
* subscription is AUTO-WIRED on deploy (2026-09-19): the platform reconciles
|
|
143
|
+
* one per function declaring this binding, with `event_prefixes` = the
|
|
144
|
+
* function's `source` values — a hand-made one equal in target + prefixes is
|
|
145
|
+
* adopted. `source` is an event-name PREFIX (e.g. 'payments.') or a full event
|
|
146
|
+
* name — lowercase dotted segments, ≤64 chars, validated at deploy — and is
|
|
147
|
+
* also enforced at delivery: a non-matching event is ACK-200 skipped.
|
|
148
|
+
* Declaring the binding is what opts the function into event delivery; a
|
|
149
|
+
* receiver that declares only `cron` keeps the older cron+{} wake. */
|
|
146
150
|
| { kind: 'webhook'; source: string }
|
|
151
|
+
/** `cmsHook`: fires after a CMS write in `collection`. The platform filters
|
|
152
|
+
* deliveries on the binding (2026-09-19): `beforeCreate` → created only,
|
|
153
|
+
* `beforeUpdate` → updated only, `beforeWrite` → created|updated; a write to
|
|
154
|
+
* another collection never wakes the function. Deleted/bulk events are not
|
|
155
|
+
* delivered to a cmsHook binding. */
|
|
147
156
|
| { kind: 'cmsHook'; collection: string; event: 'beforeCreate' | 'beforeUpdate' | 'beforeWrite' }
|
|
148
157
|
| { kind: 'authHook'; event?: AuthHookEvent };
|
|
149
158
|
|
|
@@ -218,6 +227,18 @@ export type ApiVersion = 'v1';
|
|
|
218
227
|
export const RELEASED_API_VERSIONS: readonly ApiVersion[] = ['v1'];
|
|
219
228
|
|
|
220
229
|
/** The whole vxil backend, declared in one typed, version-controlled file. */
|
|
230
|
+
/** Recursive partial: a `vxil.config.ts` may write any SUBSET of a nested bag
|
|
231
|
+
* (`auth: { otp: { enabled: true } }`) — the server applies the defaults for
|
|
232
|
+
* the rest (Value.Default). A shallow `Partial` made `tsc` reject every
|
|
233
|
+
* partially-written nested bag, including the guide's own skeleton
|
|
234
|
+
* (found by the 2026-09-19 cvskit dry-run). Arrays and primitives are kept
|
|
235
|
+
* as-is; only plain object bags recurse. */
|
|
236
|
+
export type DeepPartial<T> = T extends readonly unknown[]
|
|
237
|
+
? T
|
|
238
|
+
: T extends object
|
|
239
|
+
? { [K in keyof T]?: DeepPartial<T[K]> }
|
|
240
|
+
: T;
|
|
241
|
+
|
|
221
242
|
export interface VxilConfig {
|
|
222
243
|
/** target environment label; resolved to a baseUrl by `vxil link` / `--env`. */
|
|
223
244
|
env?: string;
|
|
@@ -232,25 +253,25 @@ export interface VxilConfig {
|
|
|
232
253
|
* same Value.Default/Clean pipeline the server uses. Keys match FEATURE_SCHEMAS
|
|
233
254
|
* exactly (note the hyphenated ids). */
|
|
234
255
|
features?: {
|
|
235
|
-
notifications?:
|
|
236
|
-
jobs?:
|
|
237
|
-
auth?:
|
|
238
|
-
'rate-limits'?:
|
|
239
|
-
files?:
|
|
240
|
-
webhooks?:
|
|
241
|
-
comments?:
|
|
242
|
-
cms?:
|
|
243
|
-
mcp?:
|
|
244
|
-
realtime?:
|
|
245
|
-
presence?:
|
|
246
|
-
orgs?:
|
|
247
|
-
'activity-feed'?:
|
|
248
|
-
'vector-search'?:
|
|
249
|
-
ai?:
|
|
250
|
-
rag?:
|
|
251
|
-
payments?:
|
|
252
|
-
functions?:
|
|
253
|
-
copilot?:
|
|
256
|
+
notifications?: DeepPartial<NotificationsConfig>;
|
|
257
|
+
jobs?: DeepPartial<JobsConfig>;
|
|
258
|
+
auth?: DeepPartial<AuthConfig>;
|
|
259
|
+
'rate-limits'?: DeepPartial<RateLimitsConfig>;
|
|
260
|
+
files?: DeepPartial<FilesConfig>;
|
|
261
|
+
webhooks?: DeepPartial<WebhooksConfig>;
|
|
262
|
+
comments?: DeepPartial<CommentsConfig>;
|
|
263
|
+
cms?: DeepPartial<CmsConfig>;
|
|
264
|
+
mcp?: DeepPartial<McpConfig>;
|
|
265
|
+
realtime?: DeepPartial<RealtimeConfig>;
|
|
266
|
+
presence?: DeepPartial<PresenceConfig>;
|
|
267
|
+
orgs?: DeepPartial<OrgsConfig>;
|
|
268
|
+
'activity-feed'?: DeepPartial<ActivityFeedConfig>;
|
|
269
|
+
'vector-search'?: DeepPartial<VectorSearchConfig>;
|
|
270
|
+
ai?: DeepPartial<AiConfig>;
|
|
271
|
+
rag?: DeepPartial<RagConfig>;
|
|
272
|
+
payments?: DeepPartial<PaymentsConfig>;
|
|
273
|
+
functions?: DeepPartial<FunctionsConfig>;
|
|
274
|
+
copilot?: DeepPartial<CopilotConfig>;
|
|
254
275
|
};
|
|
255
276
|
|
|
256
277
|
/** (b) CMS SCHEMA-AS-CODE — collections + fields. `push` reconciles them
|