@shipstatic/types 2.5.0-beta.21 → 2.5.0-beta.22

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 CHANGED
@@ -79,97 +79,6 @@ export interface DeploymentCreateResponse extends Deployment {
79
79
  /** Claim URL for public deployments. Present when deployed without credentials. */
80
80
  readonly claim?: string;
81
81
  }
82
- /**
83
- * Every path the public API answers on, declared once.
84
- *
85
- * The URL surface was written out in four places — the API's mounts, the
86
- * SDK's client, the dashboard's client, and the post-deploy smoke — so a
87
- * rename meant finding all four. The first three now read this table.
88
- *
89
- * The smoke (`cloudflare/api/smoke.mjs`) deliberately still spells its own:
90
- * five of its nine paths are `/admin/*`, which this table excludes by
91
- * design, and splitting one list between a registry and literals reads worse
92
- * than keeping it uniform.
93
- *
94
- * **What this guarantees, exactly.** Collection paths are mounted from here,
95
- * so producer and consumer cannot diverge. Item paths are declared here and
96
- * consumed by clients, but the API spells them relative to their mount
97
- * (`/:deployment/config`), so the table does not *generate* them — it is
98
- * held to them by `api/tests/architecture/api-paths.test.ts`, which fails if
99
- * any entry names a path no route answers. Some entries have no client yet
100
- * (`DEPLOYMENT_CONFIG`, `DOMAIN_PROPAGATION` — endpoints the SDK
101
- * deliberately does not reach); the fence is what keeps those honest rather
102
- * than merely asserted.
103
- *
104
- * **The operator surface is deliberately absent.** `/admin/*` paths belong
105
- * to `web/my`, for the same reason its row types do: this package is
106
- * published, and the operator surface is not public (see `CLAUDE.md`, "Admin
107
- * types"). A path here is a promise to every npm consumer; `/admin` is a
108
- * promise to one dashboard.
109
- *
110
- * Item paths are functions rather than templates so the key is interpolated
111
- * in one place, encoded the same way by every caller.
112
- */
113
- export declare const API_PATHS: {
114
- readonly DEPLOYMENTS: "/deployments";
115
- readonly DEPLOYMENT: (deployment: string) => string;
116
- readonly DEPLOYMENT_CONFIG: (deployment: string) => string;
117
- readonly DOMAINS: "/domains";
118
- readonly DOMAIN: (domain: string) => string;
119
- readonly DOMAIN_VERIFY: (domain: string) => string;
120
- readonly DOMAIN_DNS: (domain: string) => string;
121
- readonly DOMAIN_RECORDS: (domain: string) => string;
122
- readonly DOMAIN_SHARE: (domain: string) => string;
123
- readonly DOMAIN_PROPAGATION: (domain: string) => string;
124
- readonly DOMAINS_VALIDATE: "/domains/validate";
125
- readonly TOKENS: "/tokens";
126
- readonly TOKEN: (token: string) => string;
127
- readonly ACCOUNT: "/account";
128
- readonly ACCOUNT_KEY: "/account/key";
129
- readonly ACCOUNT_CLAIM: "/account/claim";
130
- readonly ACTIVITIES: "/activities";
131
- readonly LABELS: "/labels";
132
- readonly LIMITS: "/limits";
133
- readonly PING: "/ping";
134
- readonly SETUP: "/setup";
135
- readonly SPA_CHECK: "/spa-check";
136
- readonly UPLOAD: "/upload";
137
- };
138
- /**
139
- * The deploy request's multipart field names — the other half of the wire
140
- * surface beside {@link API_PATHS}. `POST /deployments` (and the first-party
141
- * `/upload`) is multipart/form-data, and these are the names the API reads.
142
- *
143
- * Declared once because the body has three independent WRITERS — the SDK's
144
- * Node and browser body builders, and the n8n community node's hand-rolled
145
- * client (which cannot import this under n8n Cloud's zero-dependency rule,
146
- * and fences its restated copy instead) — and until this export every writer
147
- * restated the strings the API parses, with nothing comparing them.
148
- *
149
- * `FILES` carries one entry per file (the API reads it with `getAll`); every
150
- * other field is single. The `@internal` flags are serialized as the literal
151
- * string `'true'` and belong to first-party surfaces only.
152
- */
153
- export declare const DEPLOY_FIELDS: {
154
- /** One entry per file — read with `getAll`. */
155
- readonly FILES: "files[]";
156
- /** JSON array of MD5 hex digests, index-aligned with `FILES`. */
157
- readonly CHECKSUMS: "checksums";
158
- /** JSON array of label strings. */
159
- readonly LABELS: "labels";
160
- /** The deploying surface's {@link DeploymentVia} member. */
161
- readonly VIA: "via";
162
- /** Plaintext password — the API hashes it server-side. */
163
- readonly PASSWORD: "password";
164
- /** @internal Server-processing flag — first-party `/upload` only. */
165
- readonly BUILD: "build";
166
- /** @internal Server-processing flag — first-party `/upload` only. */
167
- readonly PRERENDER: "prerender";
168
- /** @internal Server-processing flag — first-party `/upload` only. */
169
- readonly SPA: "spa";
170
- /** @internal reCAPTCHA proof — `web/www`'s public uploader only. */
171
- readonly CAPTCHA: "captcha";
172
- };
173
82
  /**
174
83
  * The half of a list response that is identical on every list.
175
84
  *
@@ -188,6 +97,28 @@ export interface ListResponse {
188
97
  /** Opaque cursor from this page; `null` on the last page. */
189
98
  cursor: string | null;
190
99
  }
100
+ /**
101
+ * Pagination options for every list endpoint. The response's `cursor` feeds
102
+ * the next request; a `null` cursor means the last page. Omitting both
103
+ * returns the server's default first page.
104
+ *
105
+ * A list answers `{ <collection>, cursor }` and nothing else — `cursor`
106
+ * carries the entire has-more signal, so no redundant boolean, and no
107
+ * `total`. **A count is an aggregate over a collection, not a property of a
108
+ * page:** including one makes every read pay for a full scan it did not ask
109
+ * for, which is precisely the cost keyset pagination exists to avoid.
110
+ *
111
+ * Counts therefore live on the summary resource that owns them —
112
+ * `GET /account` (`usage`) for a caller's own totals, `GET /admin/stats` for
113
+ * platform-wide ones. Ask for a count when you want a count; ask for a page
114
+ * when you want a page.
115
+ */
116
+ export interface ListOptions {
117
+ /** Maximum number of items to return in one page. */
118
+ limit?: number;
119
+ /** Opaque cursor from the previous page's response. */
120
+ cursor?: string;
121
+ }
191
122
  /**
192
123
  * Response for listing deployments
193
124
  */
@@ -658,6 +589,97 @@ export interface AccountOverrides {
658
589
  /** Override for maximum total deployment size in bytes */
659
590
  totalSize?: number;
660
591
  }
592
+ /**
593
+ * Every path the public API answers on, declared once.
594
+ *
595
+ * The URL surface was written out in four places — the API's mounts, the
596
+ * SDK's client, the dashboard's client, and the post-deploy smoke — so a
597
+ * rename meant finding all four. The first three now read this table.
598
+ *
599
+ * The smoke (`cloudflare/api/smoke.mjs`) deliberately still spells its own:
600
+ * five of its nine paths are `/admin/*`, which this table excludes by
601
+ * design, and splitting one list between a registry and literals reads worse
602
+ * than keeping it uniform.
603
+ *
604
+ * **What this guarantees, exactly.** Collection paths are mounted from here,
605
+ * so producer and consumer cannot diverge. Item paths are declared here and
606
+ * consumed by clients, but the API spells them relative to their mount
607
+ * (`/:deployment/config`), so the table does not *generate* them — it is
608
+ * held to them by `api/tests/architecture/api-paths.test.ts`, which fails if
609
+ * any entry names a path no route answers. Some entries have no client yet
610
+ * (`DEPLOYMENT_CONFIG`, `DOMAIN_PROPAGATION` — endpoints the SDK
611
+ * deliberately does not reach); the fence is what keeps those honest rather
612
+ * than merely asserted.
613
+ *
614
+ * **The operator surface is deliberately absent.** `/admin/*` paths belong
615
+ * to `web/my`, for the same reason its row types do: this package is
616
+ * published, and the operator surface is not public (see `CLAUDE.md`, "Admin
617
+ * types"). A path here is a promise to every npm consumer; `/admin` is a
618
+ * promise to one dashboard.
619
+ *
620
+ * Item paths are functions rather than templates so the key is interpolated
621
+ * in one place, encoded the same way by every caller.
622
+ */
623
+ export declare const API_PATHS: {
624
+ readonly DEPLOYMENTS: "/deployments";
625
+ readonly DEPLOYMENT: (deployment: string) => string;
626
+ readonly DEPLOYMENT_CONFIG: (deployment: string) => string;
627
+ readonly DOMAINS: "/domains";
628
+ readonly DOMAIN: (domain: string) => string;
629
+ readonly DOMAIN_VERIFY: (domain: string) => string;
630
+ readonly DOMAIN_DNS: (domain: string) => string;
631
+ readonly DOMAIN_RECORDS: (domain: string) => string;
632
+ readonly DOMAIN_SHARE: (domain: string) => string;
633
+ readonly DOMAIN_PROPAGATION: (domain: string) => string;
634
+ readonly DOMAINS_VALIDATE: "/domains/validate";
635
+ readonly TOKENS: "/tokens";
636
+ readonly TOKEN: (token: string) => string;
637
+ readonly ACCOUNT: "/account";
638
+ readonly ACCOUNT_KEY: "/account/key";
639
+ readonly ACCOUNT_CLAIM: "/account/claim";
640
+ readonly ACTIVITIES: "/activities";
641
+ readonly LABELS: "/labels";
642
+ readonly LIMITS: "/limits";
643
+ readonly PING: "/ping";
644
+ readonly SETUP: "/setup";
645
+ readonly SPA_CHECK: "/spa-check";
646
+ readonly UPLOAD: "/upload";
647
+ };
648
+ /**
649
+ * The deploy request's multipart field names — the other half of the wire
650
+ * surface beside {@link API_PATHS}. `POST /deployments` (and the first-party
651
+ * `/upload`) is multipart/form-data, and these are the names the API reads.
652
+ *
653
+ * Declared once because the body has three independent WRITERS — the SDK's
654
+ * Node and browser body builders, and the n8n community node's hand-rolled
655
+ * client (which cannot import this under n8n Cloud's zero-dependency rule,
656
+ * and fences its restated copy instead) — and until this export every writer
657
+ * restated the strings the API parses, with nothing comparing them.
658
+ *
659
+ * `FILES` carries one entry per file (the API reads it with `getAll`); every
660
+ * other field is single. The `@internal` flags are serialized as the literal
661
+ * string `'true'` and belong to first-party surfaces only.
662
+ */
663
+ export declare const DEPLOY_FIELDS: {
664
+ /** One entry per file — read with `getAll`. */
665
+ readonly FILES: "files[]";
666
+ /** JSON array of MD5 hex digests, index-aligned with `FILES`. */
667
+ readonly CHECKSUMS: "checksums";
668
+ /** JSON array of label strings. */
669
+ readonly LABELS: "labels";
670
+ /** The deploying surface's {@link DeploymentVia} member. */
671
+ readonly VIA: "via";
672
+ /** Plaintext password — the API hashes it server-side. */
673
+ readonly PASSWORD: "password";
674
+ /** @internal Server-processing flag — first-party `/upload` only. */
675
+ readonly BUILD: "build";
676
+ /** @internal Server-processing flag — first-party `/upload` only. */
677
+ readonly PRERENDER: "prerender";
678
+ /** @internal Server-processing flag — first-party `/upload` only. */
679
+ readonly SPA: "spa";
680
+ /** @internal reCAPTCHA proof — `web/www`'s public uploader only. */
681
+ readonly CAPTCHA: "captcha";
682
+ };
661
683
  /**
662
684
  * All possible error types in the ShipStatic platform.
663
685
  *
@@ -1309,28 +1331,6 @@ export interface DeploymentUploadOptions {
1309
1331
  */
1310
1332
  idempotencyKey?: string;
1311
1333
  }
1312
- /**
1313
- * Pagination options for every list endpoint. The response's `cursor` feeds
1314
- * the next request; a `null` cursor means the last page. Omitting both
1315
- * returns the server's default first page.
1316
- *
1317
- * A list answers `{ <collection>, cursor }` and nothing else — `cursor`
1318
- * carries the entire has-more signal, so no redundant boolean, and no
1319
- * `total`. **A count is an aggregate over a collection, not a property of a
1320
- * page:** including one makes every read pay for a full scan it did not ask
1321
- * for, which is precisely the cost keyset pagination exists to avoid.
1322
- *
1323
- * Counts therefore live on the summary resource that owns them —
1324
- * `GET /account` (`usage`) for a caller's own totals, `GET /admin/stats` for
1325
- * platform-wide ones. Ask for a count when you want a count; ask for a page
1326
- * when you want a page.
1327
- */
1328
- export interface ListOptions {
1329
- /** Maximum number of items to return in one page. */
1330
- limit?: number;
1331
- /** Opaque cursor from the previous page's response. */
1332
- cursor?: string;
1333
- }
1334
1334
  /**
1335
1335
  * What a caller may change on an existing deployment.
1336
1336
  *
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@
3
3
  * This package is the single source of truth for all shared data structures.
4
4
  */
5
5
  // =============================================================================
6
- // I. CORE ENTITIES
6
+ // DEPLOYMENT TYPES
7
7
  // =============================================================================
8
8
  /**
9
9
  * Deployment status constants
@@ -35,97 +35,6 @@ export const DeploymentVia = {
35
35
  GPT: 'gpt',
36
36
  VSC: 'vsc',
37
37
  };
38
- /**
39
- * Every path the public API answers on, declared once.
40
- *
41
- * The URL surface was written out in four places — the API's mounts, the
42
- * SDK's client, the dashboard's client, and the post-deploy smoke — so a
43
- * rename meant finding all four. The first three now read this table.
44
- *
45
- * The smoke (`cloudflare/api/smoke.mjs`) deliberately still spells its own:
46
- * five of its nine paths are `/admin/*`, which this table excludes by
47
- * design, and splitting one list between a registry and literals reads worse
48
- * than keeping it uniform.
49
- *
50
- * **What this guarantees, exactly.** Collection paths are mounted from here,
51
- * so producer and consumer cannot diverge. Item paths are declared here and
52
- * consumed by clients, but the API spells them relative to their mount
53
- * (`/:deployment/config`), so the table does not *generate* them — it is
54
- * held to them by `api/tests/architecture/api-paths.test.ts`, which fails if
55
- * any entry names a path no route answers. Some entries have no client yet
56
- * (`DEPLOYMENT_CONFIG`, `DOMAIN_PROPAGATION` — endpoints the SDK
57
- * deliberately does not reach); the fence is what keeps those honest rather
58
- * than merely asserted.
59
- *
60
- * **The operator surface is deliberately absent.** `/admin/*` paths belong
61
- * to `web/my`, for the same reason its row types do: this package is
62
- * published, and the operator surface is not public (see `CLAUDE.md`, "Admin
63
- * types"). A path here is a promise to every npm consumer; `/admin` is a
64
- * promise to one dashboard.
65
- *
66
- * Item paths are functions rather than templates so the key is interpolated
67
- * in one place, encoded the same way by every caller.
68
- */
69
- export const API_PATHS = {
70
- DEPLOYMENTS: '/deployments',
71
- DEPLOYMENT: (deployment) => `/deployments/${deployment}`,
72
- DEPLOYMENT_CONFIG: (deployment) => `/deployments/${deployment}/config`,
73
- DOMAINS: '/domains',
74
- DOMAIN: (domain) => `/domains/${domain}`,
75
- DOMAIN_VERIFY: (domain) => `/domains/${domain}/verify`,
76
- DOMAIN_DNS: (domain) => `/domains/${domain}/dns`,
77
- DOMAIN_RECORDS: (domain) => `/domains/${domain}/records`,
78
- DOMAIN_SHARE: (domain) => `/domains/${domain}/share`,
79
- DOMAIN_PROPAGATION: (domain) => `/domains/${domain}/propagation`,
80
- DOMAINS_VALIDATE: '/domains/validate',
81
- TOKENS: '/tokens',
82
- TOKEN: (token) => `/tokens/${token}`,
83
- ACCOUNT: '/account',
84
- ACCOUNT_KEY: '/account/key',
85
- ACCOUNT_CLAIM: '/account/claim',
86
- ACTIVITIES: '/activities',
87
- LABELS: '/labels',
88
- LIMITS: '/limits',
89
- PING: '/ping',
90
- SETUP: '/setup',
91
- SPA_CHECK: '/spa-check',
92
- UPLOAD: '/upload',
93
- };
94
- /**
95
- * The deploy request's multipart field names — the other half of the wire
96
- * surface beside {@link API_PATHS}. `POST /deployments` (and the first-party
97
- * `/upload`) is multipart/form-data, and these are the names the API reads.
98
- *
99
- * Declared once because the body has three independent WRITERS — the SDK's
100
- * Node and browser body builders, and the n8n community node's hand-rolled
101
- * client (which cannot import this under n8n Cloud's zero-dependency rule,
102
- * and fences its restated copy instead) — and until this export every writer
103
- * restated the strings the API parses, with nothing comparing them.
104
- *
105
- * `FILES` carries one entry per file (the API reads it with `getAll`); every
106
- * other field is single. The `@internal` flags are serialized as the literal
107
- * string `'true'` and belong to first-party surfaces only.
108
- */
109
- export const DEPLOY_FIELDS = {
110
- /** One entry per file — read with `getAll`. */
111
- FILES: 'files[]',
112
- /** JSON array of MD5 hex digests, index-aligned with `FILES`. */
113
- CHECKSUMS: 'checksums',
114
- /** JSON array of label strings. */
115
- LABELS: 'labels',
116
- /** The deploying surface's {@link DeploymentVia} member. */
117
- VIA: 'via',
118
- /** Plaintext password — the API hashes it server-side. */
119
- PASSWORD: 'password',
120
- /** @internal Server-processing flag — first-party `/upload` only. */
121
- BUILD: 'build',
122
- /** @internal Server-processing flag — first-party `/upload` only. */
123
- PRERENDER: 'prerender',
124
- /** @internal Server-processing flag — first-party `/upload` only. */
125
- SPA: 'spa',
126
- /** @internal reCAPTCHA proof — `web/www`'s public uploader only. */
127
- CAPTCHA: 'captcha',
128
- };
129
38
  // =============================================================================
130
39
  // DOMAIN TYPES
131
40
  // =============================================================================
@@ -221,6 +130,100 @@ export const AccountPlan = {
221
130
  TERMINATED: 'terminated',
222
131
  };
223
132
  // =============================================================================
133
+ // WIRE SURFACE
134
+ // =============================================================================
135
+ /**
136
+ * Every path the public API answers on, declared once.
137
+ *
138
+ * The URL surface was written out in four places — the API's mounts, the
139
+ * SDK's client, the dashboard's client, and the post-deploy smoke — so a
140
+ * rename meant finding all four. The first three now read this table.
141
+ *
142
+ * The smoke (`cloudflare/api/smoke.mjs`) deliberately still spells its own:
143
+ * five of its nine paths are `/admin/*`, which this table excludes by
144
+ * design, and splitting one list between a registry and literals reads worse
145
+ * than keeping it uniform.
146
+ *
147
+ * **What this guarantees, exactly.** Collection paths are mounted from here,
148
+ * so producer and consumer cannot diverge. Item paths are declared here and
149
+ * consumed by clients, but the API spells them relative to their mount
150
+ * (`/:deployment/config`), so the table does not *generate* them — it is
151
+ * held to them by `api/tests/architecture/api-paths.test.ts`, which fails if
152
+ * any entry names a path no route answers. Some entries have no client yet
153
+ * (`DEPLOYMENT_CONFIG`, `DOMAIN_PROPAGATION` — endpoints the SDK
154
+ * deliberately does not reach); the fence is what keeps those honest rather
155
+ * than merely asserted.
156
+ *
157
+ * **The operator surface is deliberately absent.** `/admin/*` paths belong
158
+ * to `web/my`, for the same reason its row types do: this package is
159
+ * published, and the operator surface is not public (see `CLAUDE.md`, "Admin
160
+ * types"). A path here is a promise to every npm consumer; `/admin` is a
161
+ * promise to one dashboard.
162
+ *
163
+ * Item paths are functions rather than templates so the key is interpolated
164
+ * in one place, encoded the same way by every caller.
165
+ */
166
+ export const API_PATHS = {
167
+ DEPLOYMENTS: '/deployments',
168
+ DEPLOYMENT: (deployment) => `/deployments/${deployment}`,
169
+ DEPLOYMENT_CONFIG: (deployment) => `/deployments/${deployment}/config`,
170
+ DOMAINS: '/domains',
171
+ DOMAIN: (domain) => `/domains/${domain}`,
172
+ DOMAIN_VERIFY: (domain) => `/domains/${domain}/verify`,
173
+ DOMAIN_DNS: (domain) => `/domains/${domain}/dns`,
174
+ DOMAIN_RECORDS: (domain) => `/domains/${domain}/records`,
175
+ DOMAIN_SHARE: (domain) => `/domains/${domain}/share`,
176
+ DOMAIN_PROPAGATION: (domain) => `/domains/${domain}/propagation`,
177
+ DOMAINS_VALIDATE: '/domains/validate',
178
+ TOKENS: '/tokens',
179
+ TOKEN: (token) => `/tokens/${token}`,
180
+ ACCOUNT: '/account',
181
+ ACCOUNT_KEY: '/account/key',
182
+ ACCOUNT_CLAIM: '/account/claim',
183
+ ACTIVITIES: '/activities',
184
+ LABELS: '/labels',
185
+ LIMITS: '/limits',
186
+ PING: '/ping',
187
+ SETUP: '/setup',
188
+ SPA_CHECK: '/spa-check',
189
+ UPLOAD: '/upload',
190
+ };
191
+ /**
192
+ * The deploy request's multipart field names — the other half of the wire
193
+ * surface beside {@link API_PATHS}. `POST /deployments` (and the first-party
194
+ * `/upload`) is multipart/form-data, and these are the names the API reads.
195
+ *
196
+ * Declared once because the body has three independent WRITERS — the SDK's
197
+ * Node and browser body builders, and the n8n community node's hand-rolled
198
+ * client (which cannot import this under n8n Cloud's zero-dependency rule,
199
+ * and fences its restated copy instead) — and until this export every writer
200
+ * restated the strings the API parses, with nothing comparing them.
201
+ *
202
+ * `FILES` carries one entry per file (the API reads it with `getAll`); every
203
+ * other field is single. The `@internal` flags are serialized as the literal
204
+ * string `'true'` and belong to first-party surfaces only.
205
+ */
206
+ export const DEPLOY_FIELDS = {
207
+ /** One entry per file — read with `getAll`. */
208
+ FILES: 'files[]',
209
+ /** JSON array of MD5 hex digests, index-aligned with `FILES`. */
210
+ CHECKSUMS: 'checksums',
211
+ /** JSON array of label strings. */
212
+ LABELS: 'labels',
213
+ /** The deploying surface's {@link DeploymentVia} member. */
214
+ VIA: 'via',
215
+ /** Plaintext password — the API hashes it server-side. */
216
+ PASSWORD: 'password',
217
+ /** @internal Server-processing flag — first-party `/upload` only. */
218
+ BUILD: 'build',
219
+ /** @internal Server-processing flag — first-party `/upload` only. */
220
+ PRERENDER: 'prerender',
221
+ /** @internal Server-processing flag — first-party `/upload` only. */
222
+ SPA: 'spa',
223
+ /** @internal reCAPTCHA proof — `web/www`'s public uploader only. */
224
+ CAPTCHA: 'captcha',
225
+ };
226
+ // =============================================================================
224
227
  // ERROR SYSTEM
225
228
  // =============================================================================
226
229
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shipstatic/types",
3
- "version": "2.5.0-beta.21",
3
+ "version": "2.5.0-beta.22",
4
4
  "description": "Shared types for ShipStatic platform",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/src/index.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  // =============================================================================
7
- // I. CORE ENTITIES
7
+ // DEPLOYMENT TYPES
8
8
  // =============================================================================
9
9
 
10
10
  /**
@@ -90,99 +90,6 @@ export interface DeploymentCreateResponse extends Deployment {
90
90
  readonly claim?: string;
91
91
  }
92
92
 
93
- /**
94
- * Every path the public API answers on, declared once.
95
- *
96
- * The URL surface was written out in four places — the API's mounts, the
97
- * SDK's client, the dashboard's client, and the post-deploy smoke — so a
98
- * rename meant finding all four. The first three now read this table.
99
- *
100
- * The smoke (`cloudflare/api/smoke.mjs`) deliberately still spells its own:
101
- * five of its nine paths are `/admin/*`, which this table excludes by
102
- * design, and splitting one list between a registry and literals reads worse
103
- * than keeping it uniform.
104
- *
105
- * **What this guarantees, exactly.** Collection paths are mounted from here,
106
- * so producer and consumer cannot diverge. Item paths are declared here and
107
- * consumed by clients, but the API spells them relative to their mount
108
- * (`/:deployment/config`), so the table does not *generate* them — it is
109
- * held to them by `api/tests/architecture/api-paths.test.ts`, which fails if
110
- * any entry names a path no route answers. Some entries have no client yet
111
- * (`DEPLOYMENT_CONFIG`, `DOMAIN_PROPAGATION` — endpoints the SDK
112
- * deliberately does not reach); the fence is what keeps those honest rather
113
- * than merely asserted.
114
- *
115
- * **The operator surface is deliberately absent.** `/admin/*` paths belong
116
- * to `web/my`, for the same reason its row types do: this package is
117
- * published, and the operator surface is not public (see `CLAUDE.md`, "Admin
118
- * types"). A path here is a promise to every npm consumer; `/admin` is a
119
- * promise to one dashboard.
120
- *
121
- * Item paths are functions rather than templates so the key is interpolated
122
- * in one place, encoded the same way by every caller.
123
- */
124
- export const API_PATHS = {
125
- DEPLOYMENTS: '/deployments',
126
- DEPLOYMENT: (deployment: string) => `/deployments/${deployment}`,
127
- DEPLOYMENT_CONFIG: (deployment: string) => `/deployments/${deployment}/config`,
128
- DOMAINS: '/domains',
129
- DOMAIN: (domain: string) => `/domains/${domain}`,
130
- DOMAIN_VERIFY: (domain: string) => `/domains/${domain}/verify`,
131
- DOMAIN_DNS: (domain: string) => `/domains/${domain}/dns`,
132
- DOMAIN_RECORDS: (domain: string) => `/domains/${domain}/records`,
133
- DOMAIN_SHARE: (domain: string) => `/domains/${domain}/share`,
134
- DOMAIN_PROPAGATION: (domain: string) => `/domains/${domain}/propagation`,
135
- DOMAINS_VALIDATE: '/domains/validate',
136
- TOKENS: '/tokens',
137
- TOKEN: (token: string) => `/tokens/${token}`,
138
- ACCOUNT: '/account',
139
- ACCOUNT_KEY: '/account/key',
140
- ACCOUNT_CLAIM: '/account/claim',
141
- ACTIVITIES: '/activities',
142
- LABELS: '/labels',
143
- LIMITS: '/limits',
144
- PING: '/ping',
145
- SETUP: '/setup',
146
- SPA_CHECK: '/spa-check',
147
- UPLOAD: '/upload',
148
- } as const;
149
-
150
- /**
151
- * The deploy request's multipart field names — the other half of the wire
152
- * surface beside {@link API_PATHS}. `POST /deployments` (and the first-party
153
- * `/upload`) is multipart/form-data, and these are the names the API reads.
154
- *
155
- * Declared once because the body has three independent WRITERS — the SDK's
156
- * Node and browser body builders, and the n8n community node's hand-rolled
157
- * client (which cannot import this under n8n Cloud's zero-dependency rule,
158
- * and fences its restated copy instead) — and until this export every writer
159
- * restated the strings the API parses, with nothing comparing them.
160
- *
161
- * `FILES` carries one entry per file (the API reads it with `getAll`); every
162
- * other field is single. The `@internal` flags are serialized as the literal
163
- * string `'true'` and belong to first-party surfaces only.
164
- */
165
- export const DEPLOY_FIELDS = {
166
- /** One entry per file — read with `getAll`. */
167
- FILES: 'files[]',
168
- /** JSON array of MD5 hex digests, index-aligned with `FILES`. */
169
- CHECKSUMS: 'checksums',
170
- /** JSON array of label strings. */
171
- LABELS: 'labels',
172
- /** The deploying surface's {@link DeploymentVia} member. */
173
- VIA: 'via',
174
- /** Plaintext password — the API hashes it server-side. */
175
- PASSWORD: 'password',
176
- /** @internal Server-processing flag — first-party `/upload` only. */
177
- BUILD: 'build',
178
- /** @internal Server-processing flag — first-party `/upload` only. */
179
- PRERENDER: 'prerender',
180
- /** @internal Server-processing flag — first-party `/upload` only. */
181
- SPA: 'spa',
182
- /** @internal reCAPTCHA proof — `web/www`'s public uploader only. */
183
- CAPTCHA: 'captcha',
184
- } as const;
185
-
186
93
  /**
187
94
  * The half of a list response that is identical on every list.
188
95
  *
@@ -202,6 +109,29 @@ export interface ListResponse {
202
109
  cursor: string | null;
203
110
  }
204
111
 
112
+ /**
113
+ * Pagination options for every list endpoint. The response's `cursor` feeds
114
+ * the next request; a `null` cursor means the last page. Omitting both
115
+ * returns the server's default first page.
116
+ *
117
+ * A list answers `{ <collection>, cursor }` and nothing else — `cursor`
118
+ * carries the entire has-more signal, so no redundant boolean, and no
119
+ * `total`. **A count is an aggregate over a collection, not a property of a
120
+ * page:** including one makes every read pay for a full scan it did not ask
121
+ * for, which is precisely the cost keyset pagination exists to avoid.
122
+ *
123
+ * Counts therefore live on the summary resource that owns them —
124
+ * `GET /account` (`usage`) for a caller's own totals, `GET /admin/stats` for
125
+ * platform-wide ones. Ask for a count when you want a count; ask for a page
126
+ * when you want a page.
127
+ */
128
+ export interface ListOptions {
129
+ /** Maximum number of items to return in one page. */
130
+ limit?: number;
131
+ /** Opaque cursor from the previous page's response. */
132
+ cursor?: string;
133
+ }
134
+
205
135
  /**
206
136
  * Response for listing deployments
207
137
  */
@@ -739,6 +669,103 @@ export interface AccountOverrides {
739
669
  totalSize?: number;
740
670
  }
741
671
 
672
+ // =============================================================================
673
+ // WIRE SURFACE
674
+ // =============================================================================
675
+
676
+ /**
677
+ * Every path the public API answers on, declared once.
678
+ *
679
+ * The URL surface was written out in four places — the API's mounts, the
680
+ * SDK's client, the dashboard's client, and the post-deploy smoke — so a
681
+ * rename meant finding all four. The first three now read this table.
682
+ *
683
+ * The smoke (`cloudflare/api/smoke.mjs`) deliberately still spells its own:
684
+ * five of its nine paths are `/admin/*`, which this table excludes by
685
+ * design, and splitting one list between a registry and literals reads worse
686
+ * than keeping it uniform.
687
+ *
688
+ * **What this guarantees, exactly.** Collection paths are mounted from here,
689
+ * so producer and consumer cannot diverge. Item paths are declared here and
690
+ * consumed by clients, but the API spells them relative to their mount
691
+ * (`/:deployment/config`), so the table does not *generate* them — it is
692
+ * held to them by `api/tests/architecture/api-paths.test.ts`, which fails if
693
+ * any entry names a path no route answers. Some entries have no client yet
694
+ * (`DEPLOYMENT_CONFIG`, `DOMAIN_PROPAGATION` — endpoints the SDK
695
+ * deliberately does not reach); the fence is what keeps those honest rather
696
+ * than merely asserted.
697
+ *
698
+ * **The operator surface is deliberately absent.** `/admin/*` paths belong
699
+ * to `web/my`, for the same reason its row types do: this package is
700
+ * published, and the operator surface is not public (see `CLAUDE.md`, "Admin
701
+ * types"). A path here is a promise to every npm consumer; `/admin` is a
702
+ * promise to one dashboard.
703
+ *
704
+ * Item paths are functions rather than templates so the key is interpolated
705
+ * in one place, encoded the same way by every caller.
706
+ */
707
+ export const API_PATHS = {
708
+ DEPLOYMENTS: '/deployments',
709
+ DEPLOYMENT: (deployment: string) => `/deployments/${deployment}`,
710
+ DEPLOYMENT_CONFIG: (deployment: string) => `/deployments/${deployment}/config`,
711
+ DOMAINS: '/domains',
712
+ DOMAIN: (domain: string) => `/domains/${domain}`,
713
+ DOMAIN_VERIFY: (domain: string) => `/domains/${domain}/verify`,
714
+ DOMAIN_DNS: (domain: string) => `/domains/${domain}/dns`,
715
+ DOMAIN_RECORDS: (domain: string) => `/domains/${domain}/records`,
716
+ DOMAIN_SHARE: (domain: string) => `/domains/${domain}/share`,
717
+ DOMAIN_PROPAGATION: (domain: string) => `/domains/${domain}/propagation`,
718
+ DOMAINS_VALIDATE: '/domains/validate',
719
+ TOKENS: '/tokens',
720
+ TOKEN: (token: string) => `/tokens/${token}`,
721
+ ACCOUNT: '/account',
722
+ ACCOUNT_KEY: '/account/key',
723
+ ACCOUNT_CLAIM: '/account/claim',
724
+ ACTIVITIES: '/activities',
725
+ LABELS: '/labels',
726
+ LIMITS: '/limits',
727
+ PING: '/ping',
728
+ SETUP: '/setup',
729
+ SPA_CHECK: '/spa-check',
730
+ UPLOAD: '/upload',
731
+ } as const;
732
+
733
+ /**
734
+ * The deploy request's multipart field names — the other half of the wire
735
+ * surface beside {@link API_PATHS}. `POST /deployments` (and the first-party
736
+ * `/upload`) is multipart/form-data, and these are the names the API reads.
737
+ *
738
+ * Declared once because the body has three independent WRITERS — the SDK's
739
+ * Node and browser body builders, and the n8n community node's hand-rolled
740
+ * client (which cannot import this under n8n Cloud's zero-dependency rule,
741
+ * and fences its restated copy instead) — and until this export every writer
742
+ * restated the strings the API parses, with nothing comparing them.
743
+ *
744
+ * `FILES` carries one entry per file (the API reads it with `getAll`); every
745
+ * other field is single. The `@internal` flags are serialized as the literal
746
+ * string `'true'` and belong to first-party surfaces only.
747
+ */
748
+ export const DEPLOY_FIELDS = {
749
+ /** One entry per file — read with `getAll`. */
750
+ FILES: 'files[]',
751
+ /** JSON array of MD5 hex digests, index-aligned with `FILES`. */
752
+ CHECKSUMS: 'checksums',
753
+ /** JSON array of label strings. */
754
+ LABELS: 'labels',
755
+ /** The deploying surface's {@link DeploymentVia} member. */
756
+ VIA: 'via',
757
+ /** Plaintext password — the API hashes it server-side. */
758
+ PASSWORD: 'password',
759
+ /** @internal Server-processing flag — first-party `/upload` only. */
760
+ BUILD: 'build',
761
+ /** @internal Server-processing flag — first-party `/upload` only. */
762
+ PRERENDER: 'prerender',
763
+ /** @internal Server-processing flag — first-party `/upload` only. */
764
+ SPA: 'spa',
765
+ /** @internal reCAPTCHA proof — `web/www`'s public uploader only. */
766
+ CAPTCHA: 'captcha',
767
+ } as const;
768
+
742
769
  // =============================================================================
743
770
  // ERROR SYSTEM
744
771
  // =============================================================================
@@ -1179,7 +1206,7 @@ export function isShipError(error: unknown): error is ShipError {
1179
1206
  }
1180
1207
 
1181
1208
  // =============================================================================
1182
- // CONFIG TYPES
1209
+ // PLATFORM LIMITS
1183
1210
  // =============================================================================
1184
1211
 
1185
1212
  /**
@@ -2007,29 +2034,6 @@ export interface DeploymentUploadOptions {
2007
2034
  idempotencyKey?: string;
2008
2035
  }
2009
2036
 
2010
- /**
2011
- * Pagination options for every list endpoint. The response's `cursor` feeds
2012
- * the next request; a `null` cursor means the last page. Omitting both
2013
- * returns the server's default first page.
2014
- *
2015
- * A list answers `{ <collection>, cursor }` and nothing else — `cursor`
2016
- * carries the entire has-more signal, so no redundant boolean, and no
2017
- * `total`. **A count is an aggregate over a collection, not a property of a
2018
- * page:** including one makes every read pay for a full scan it did not ask
2019
- * for, which is precisely the cost keyset pagination exists to avoid.
2020
- *
2021
- * Counts therefore live on the summary resource that owns them —
2022
- * `GET /account` (`usage`) for a caller's own totals, `GET /admin/stats` for
2023
- * platform-wide ones. Ask for a count when you want a count; ask for a page
2024
- * when you want a page.
2025
- */
2026
- export interface ListOptions {
2027
- /** Maximum number of items to return in one page. */
2028
- limit?: number;
2029
- /** Opaque cursor from the previous page's response. */
2030
- cursor?: string;
2031
- }
2032
-
2033
2037
  /**
2034
2038
  * What a caller may change on an existing deployment.
2035
2039
  *