@vxil/cli 0.4.0 → 0.4.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # vxil
1
+ # @vxil/cli
2
2
 
3
- The [Vxil](https://vxil.com) CLI — config-as-code for backend building blocks you enable in one line.
3
+ The [Vxil](https://vxil.com) CLI — config-as-code for backend building blocks you enable in one line. The package is `@vxil/cli` and it installs the `vxil` command — the bare `vxil` name on npm is blocked, so always install the scoped package.
4
4
 
5
5
  ```bash
6
6
  npx @vxil/cli quickstart # create a tenant + scaffold vxil.config.ts
@@ -9,24 +9,46 @@ npx @vxil/cli gen # generate a typed client + MCP manifest for Y
9
9
  npx @vxil/cli functions dev fn # run a tenant function locally against the remote edge
10
10
  npx @vxil/cli listen --forward-to localhost:3000/webhook # forward inbound webhook events to your local server
11
11
  npx @vxil/cli mcp install --client cursor # wire your backend's MCP server into your editor's agent
12
- npx @vxil/cli doctor # sanity-check keys, URLs, reachability
12
+ npx @vxil/cli doctor # keys, URLs, reachability + secrets referenced-vs-stored + per-function hashes
13
+ npx @vxil/cli diff --against staging # CI drift gate vs a named slot: exit 0 no drift · 1 drift · 2 error
13
14
  ```
14
15
 
15
- Config-as-code lives in `vxil.config.ts`, typed via the bundled `vxil/config` subpath:
16
+ Config-as-code lives in `vxil.config.ts`, typed by `@vxil/config` (also bundled as the `@vxil/cli/config` subpath):
16
17
 
17
18
  ```ts
18
19
  import { defineConfig } from '@vxil/config';
19
20
 
20
21
  export default defineConfig({
22
+ // (a) per-feature config — the same typed manifests the server validates
21
23
  features: {
22
- auth: { enabled: true, methods: ['email_otp'] },
23
- cms: { enabled: true, collections: { tasks: { fields: { title: 'text', done: 'boolean' } } } },
24
- notifications: { enabled: true, provider: 'resend' },
24
+ auth: { enabled: true },
25
+ cms: { enabled: true, draftPublish: true },
26
+ notifications: { enabled: true, provider: 'resend', fromEmail: 'noreply@example.app' },
27
+ },
28
+ // (b) CMS schema-as-code — collections + fields, reconciled by `vxil push`
29
+ cms: {
30
+ collections: {
31
+ tasks: {
32
+ fields: {
33
+ title: { type: 'string', required: true, indexSlot: 's1' },
34
+ done: { type: 'bool' },
35
+ },
36
+ },
37
+ },
25
38
  },
26
39
  });
27
40
  ```
28
41
 
29
- Verbs: `init quickstart push pull diff gen secrets env seed export import functions listen mcp cms dev doctor versions rollback link apply migrate try`.
42
+ Verbs: `init templates quickstart try login link plan push pull diff gen doctor architect versions rollback secrets env seed export import functions listen mcp cms dev payments migrate config users send deliveries api`.
43
+
44
+ **Every verb names its target.** `--dev` selects the dev slot, `--target <name>` a named slot bound by `vxil link <slug> --as <name>` (which merges into the existing binding rather than replacing it). The selector is **fail-closed** — an unbound slot exits 1 telling you the fix, and never falls through to another tenant — and every write verb prints a target banner (slug + env, never a key) before it acts.
45
+
46
+ - `vxil plan --explain` — the config plan with every leaf tagged *declared* or *default*.
47
+ - `vxil diff [--against <target>] [--ignore <k,…>]` — the CI drift gate; secrets compared by name only.
48
+ - `vxil doctor` — preflight: secrets referenced-vs-stored (advisory, names only) plus a served / published / local hash verdict per function.
49
+ - `vxil secrets list --all-projects` — the names-and-metadata matrix across every bound project (values never come back).
50
+ - `vxil migrate payments --from-provider stripe|paddle|paypal|revenuecat (--customers <f.csv> | --all) [--dry-run]` — backfill subscriptions through the server sync leg; resumable.
51
+ - `vxil payments simulate --scenario <s> --user <id> [--tier <t>]` — mock/dev projects only: drive a refund pair, cross-platform unlock, renewal, expiry, past-due grace or transfer and check the oracle.
30
52
 
31
53
  `vxil listen --forward-to <url>` polls your tenant's inbound webhook events and re-POSTs each new one to your local server under the exact delivery contract production uses — same body shape, same signed `X-Vxil-Jobs-Signature` header (your real signing secret) — so the handler you test locally is the handler you ship. `--replay-last <n>` re-forwards recent events; `--raw` posts the stored provider payload alone.
32
54
 
@@ -10,7 +10,7 @@ export declare const HOOK_LIMITS: {
10
10
  readonly maxReadHooksPerCollection: 10;
11
11
  };
12
12
  /** The ONLY root variables an expression may reference. `caller` is the VERIFIED
13
- * end-user principal (docs/end-user-principals-design.md §5.6) — read-only and
13
+ * end-user principal (https://vxil.com/docs/guide/09-security-and-multitenancy) — read-only and
14
14
  * populated ONLY on the READ path (runReadHooks); on the write path and in
15
15
  * server-caller mode it is null, exactly like `before` on a create. It carries
16
16
  * `caller.endUserId` (the verified session sub, or null) and `caller.principal`
package/dist/config.d.ts CHANGED
@@ -76,7 +76,7 @@ export type CoversFieldAttrs<Covered extends FieldAttrName> = [
76
76
  export interface CollectionDef {
77
77
  singular?: string;
78
78
  fields: Record<string, FieldDef>;
79
- /** End-user owner-scoping (docs/end-user-principals-design.md §5.1): names an
79
+ /** End-user owner-scoping (https://vxil.com/docs/guide/09-security-and-multitenancy): names an
80
80
  * existing `string` field on this collection that holds the owner (end-user)
81
81
  * id. When set, the cms worker auto-scopes owned reads/writes to the VERIFIED
82
82
  * end-user principal in end-user mode (default-deny) — and is a no-op in
@@ -138,9 +138,9 @@ export interface FunctionDef {
138
138
  * functions:write, secrets:write rejected; payments:write / notifications:send /
139
139
  * users:* allowed as owner-granted business scopes). */
140
140
  scopes?: string[];
141
- /** tenant_secrets refs injected under KEK_FUNCTIONS (productization). */
141
+ /** Names of tenant secrets injected into the function at invoke time. */
142
142
  secrets?: string[];
143
- /** Outbound-Worker host allowlist (deny-by-default egress guard). */
143
+ /** Outbound host allowlist (deny-by-default egress guard). */
144
144
  egressAllow?: string[];
145
145
  limits?: {
146
146
  cpuMs?: number;
@@ -171,7 +171,7 @@ export interface SeedSpec {
171
171
  email?: string;
172
172
  }[];
173
173
  }
174
- /** The released API majors (docs/feature-versioning.md §3), a CLOSED union —
174
+ /** The released API majors (see https://vxil.com/docs/guide/12-going-to-production), a CLOSED union —
175
175
  * `'v1'` is the only released major, so `apiVersion: 'v2'` is a COMPILE error
176
176
  * until a v2 GAs. `defineConfig` also validates it at runtime against
177
177
  * `RELEASED_API_VERSIONS`. */
@@ -183,7 +183,7 @@ export declare const RELEASED_API_VERSIONS: readonly ApiVersion[];
183
183
  export interface VxilConfig {
184
184
  /** target environment label; resolved to a baseUrl by `vxil link` / `--env`. */
185
185
  env?: string;
186
- /** Pin the API major the CLI targets (default `'v1'`, docs/feature-versioning.md).
186
+ /** Pin the API major the CLI targets (default `'v1'`; see https://vxil.com/docs/guide/12-going-to-production).
187
187
  * Path-major, per-platform: a breaking change ships as a new major on a new
188
188
  * path with a ≥6-month deprecation window. `VXIL_API_VERSION` overrides this
189
189
  * for a one-off invocation. */
package/dist/config.js CHANGED
@@ -3,7 +3,7 @@ var RELEASED_API_VERSIONS = ["v1"];
3
3
  function defineConfig(c) {
4
4
  if (c.apiVersion !== void 0 && !RELEASED_API_VERSIONS.includes(c.apiVersion)) {
5
5
  throw new Error(
6
- `vxil.config: apiVersion '${String(c.apiVersion)}' is not a released API major (released: ${RELEASED_API_VERSIONS.map((v) => `'${v}'`).join(", ")}). A new major ships as a new path with its own deprecation window \u2014 see docs/feature-versioning.md.`
6
+ `vxil.config: apiVersion '${String(c.apiVersion)}' is not a released API major (released: ${RELEASED_API_VERSIONS.map((v) => `'${v}'`).join(", ")}). A new major ships as a new path with its own deprecation window \u2014 see https://vxil.com/docs/guide/12-going-to-production.`
7
7
  );
8
8
  }
9
9
  return c;