@shipstatic/types 2.5.0-beta.19 → 2.5.0-beta.20

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
@@ -12,6 +12,28 @@ export declare const DeploymentStatus: {
12
12
  readonly DELETING: "deleting";
13
13
  };
14
14
  export type DeploymentStatusType = (typeof DeploymentStatus)[keyof typeof DeploymentStatus];
15
+ /**
16
+ * Which client made a deployment — the origin-tracking vocabulary.
17
+ *
18
+ * A closed set with many authors: the CLI, the SDK, the dashboard, both MCP
19
+ * transports, the GitHub Action, the n8n node and the VS Code extension each
20
+ * name themselves here. It lived in the API's config until 2026-08-06, where
21
+ * being server-side made it unenforceable in the one direction that matters —
22
+ * every client wrote a bare string, and a value outside the set was **silently
23
+ * dropped** by the server, so a typo did not fail anywhere. It stopped
24
+ * recording where deploys came from and said nothing.
25
+ */
26
+ export declare const DeploymentVia: {
27
+ readonly WEB: "web";
28
+ readonly SDK: "sdk";
29
+ readonly CLI: "cli";
30
+ readonly MCP: "mcp";
31
+ readonly GIT: "git";
32
+ readonly N8N: "n8n";
33
+ readonly GPT: "gpt";
34
+ readonly VSC: "vsc";
35
+ };
36
+ export type DeploymentViaType = (typeof DeploymentVia)[keyof typeof DeploymentVia];
15
37
  /**
16
38
  * Core deployment object - used in both API responses and SDK
17
39
  */
@@ -32,7 +54,15 @@ export interface Deployment {
32
54
  readonly password: boolean;
33
55
  /** Labels for categorization and filtering (lowercase, alphanumeric with separators). Always present, empty array when none. */
34
56
  labels: string[];
35
- /** The client/tool used to create this deployment (e.g., 'web', 'sdk', 'cli'), null if unknown */
57
+ /**
58
+ * The client/tool that created this deployment, null if unknown.
59
+ *
60
+ * Deliberately wider than {@link DeploymentViaType}: this is stored data,
61
+ * and rows predate the vocabulary being closed. Narrowing the ENTITY would
62
+ * be a claim about every row already in the database; narrowing the
63
+ * REQUEST option ({@link DeploymentUploadOptions.via}) is a claim about
64
+ * what a client may send, which is ours to make.
65
+ */
36
66
  readonly via: string | null;
37
67
  /** Unix timestamp (seconds) when deployment was created */
38
68
  readonly created: number;
@@ -324,10 +354,33 @@ export interface DomainRecordsResponse {
324
354
  * API would reject the same value the same way.
325
355
  */
326
356
  export declare const IDEMPOTENCY_KEY_CONSTRAINTS: {
357
+ /**
358
+ * HTTP header name. Here for the same reason {@link CALLER.HEADER} is: a
359
+ * wire header has two ends, and the package that owns the value's format
360
+ * is the only place both ends can read its name from.
361
+ */
362
+ readonly HEADER: "Idempotency-Key";
327
363
  readonly MAX_LENGTH: 256;
328
364
  /** How long a stored 201 stays replayable. */
329
365
  readonly WINDOW_SECONDS: number;
330
366
  };
367
+ /**
368
+ * Normalize a `via` value from any transport — trimmed, lowercased, and a
369
+ * member of {@link DeploymentVia}, or `undefined`.
370
+ *
371
+ * A format rule by this package's own test: a client can decide offline
372
+ * whether a value is well-formed, and the API reaches the same verdict on the
373
+ * same input. It lived server-side until 2026-08-06, which meant clients could
374
+ * only learn their label was unusable by noticing analytics had gone quiet.
375
+ *
376
+ * **Not knowing your `via` is not an error** — an unrecognized value yields
377
+ * `undefined` rather than throwing, because origin tracking is telemetry and a
378
+ * deploy must never fail over it. A caller that has an honest default should
379
+ * prefer it (`normalizeVia(process.env.SHIP_VIA) ?? DeploymentVia.CLI`): the
380
+ * deploy really did come from the CLI, so recording that beats recording
381
+ * nothing.
382
+ */
383
+ export declare function normalizeVia(value: unknown): DeploymentViaType | undefined;
331
384
  /**
332
385
  * Validate an idempotency key, returning the trimmed value or `undefined`
333
386
  * when none was supplied. Throws {@link ShipError.validation} when the value
@@ -1127,8 +1180,12 @@ export type DeployInput = File[] | string | string[];
1127
1180
  export interface DeploymentUploadOptions {
1128
1181
  /** Optional labels for categorization and filtering */
1129
1182
  labels?: string[];
1130
- /** Client identifier (e.g., 'cli', 'sdk', 'web') */
1131
- via?: string;
1183
+ /**
1184
+ * Which client is making this deploy. Closed, because the server silently
1185
+ * ignores anything outside the set — so an unchecked string turned a typo
1186
+ * into missing analytics rather than an error. See {@link DeploymentVia}.
1187
+ */
1188
+ via?: DeploymentViaType;
1132
1189
  /**
1133
1190
  * Optional password that protects this deployment.
1134
1191
  *
package/dist/index.js CHANGED
@@ -14,6 +14,27 @@ export const DeploymentStatus = {
14
14
  FAILED: 'failed',
15
15
  DELETING: 'deleting',
16
16
  };
17
+ /**
18
+ * Which client made a deployment — the origin-tracking vocabulary.
19
+ *
20
+ * A closed set with many authors: the CLI, the SDK, the dashboard, both MCP
21
+ * transports, the GitHub Action, the n8n node and the VS Code extension each
22
+ * name themselves here. It lived in the API's config until 2026-08-06, where
23
+ * being server-side made it unenforceable in the one direction that matters —
24
+ * every client wrote a bare string, and a value outside the set was **silently
25
+ * dropped** by the server, so a typo did not fail anywhere. It stopped
26
+ * recording where deploys came from and said nothing.
27
+ */
28
+ export const DeploymentVia = {
29
+ WEB: 'web',
30
+ SDK: 'sdk',
31
+ CLI: 'cli',
32
+ MCP: 'mcp',
33
+ GIT: 'git',
34
+ N8N: 'n8n',
35
+ GPT: 'gpt',
36
+ VSC: 'vsc',
37
+ };
17
38
  /**
18
39
  * Every path the public API answers on, declared once.
19
40
  *
@@ -95,10 +116,40 @@ export const DomainStatus = {
95
116
  * API would reject the same value the same way.
96
117
  */
97
118
  export const IDEMPOTENCY_KEY_CONSTRAINTS = {
119
+ /**
120
+ * HTTP header name. Here for the same reason {@link CALLER.HEADER} is: a
121
+ * wire header has two ends, and the package that owns the value's format
122
+ * is the only place both ends can read its name from.
123
+ */
124
+ HEADER: 'Idempotency-Key',
98
125
  MAX_LENGTH: 256,
99
126
  /** How long a stored 201 stays replayable. */
100
127
  WINDOW_SECONDS: 24 * 60 * 60,
101
128
  };
129
+ /**
130
+ * Normalize a `via` value from any transport — trimmed, lowercased, and a
131
+ * member of {@link DeploymentVia}, or `undefined`.
132
+ *
133
+ * A format rule by this package's own test: a client can decide offline
134
+ * whether a value is well-formed, and the API reaches the same verdict on the
135
+ * same input. It lived server-side until 2026-08-06, which meant clients could
136
+ * only learn their label was unusable by noticing analytics had gone quiet.
137
+ *
138
+ * **Not knowing your `via` is not an error** — an unrecognized value yields
139
+ * `undefined` rather than throwing, because origin tracking is telemetry and a
140
+ * deploy must never fail over it. A caller that has an honest default should
141
+ * prefer it (`normalizeVia(process.env.SHIP_VIA) ?? DeploymentVia.CLI`): the
142
+ * deploy really did come from the CLI, so recording that beats recording
143
+ * nothing.
144
+ */
145
+ export function normalizeVia(value) {
146
+ if (!value || typeof value !== 'string')
147
+ return undefined;
148
+ const via = value.trim().toLowerCase();
149
+ return Object.values(DeploymentVia).includes(via)
150
+ ? via
151
+ : undefined;
152
+ }
102
153
  /**
103
154
  * Validate an idempotency key, returning the trimmed value or `undefined`
104
155
  * when none was supplied. Throws {@link ShipError.validation} when the value
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shipstatic/types",
3
- "version": "2.5.0-beta.19",
3
+ "version": "2.5.0-beta.20",
4
4
  "description": "Shared types for ShipStatic platform",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/src/index.ts CHANGED
@@ -19,6 +19,30 @@ export const DeploymentStatus = {
19
19
 
20
20
  export type DeploymentStatusType = (typeof DeploymentStatus)[keyof typeof DeploymentStatus];
21
21
 
22
+ /**
23
+ * Which client made a deployment — the origin-tracking vocabulary.
24
+ *
25
+ * A closed set with many authors: the CLI, the SDK, the dashboard, both MCP
26
+ * transports, the GitHub Action, the n8n node and the VS Code extension each
27
+ * name themselves here. It lived in the API's config until 2026-08-06, where
28
+ * being server-side made it unenforceable in the one direction that matters —
29
+ * every client wrote a bare string, and a value outside the set was **silently
30
+ * dropped** by the server, so a typo did not fail anywhere. It stopped
31
+ * recording where deploys came from and said nothing.
32
+ */
33
+ export const DeploymentVia = {
34
+ WEB: 'web',
35
+ SDK: 'sdk',
36
+ CLI: 'cli',
37
+ MCP: 'mcp',
38
+ GIT: 'git',
39
+ N8N: 'n8n',
40
+ GPT: 'gpt',
41
+ VSC: 'vsc',
42
+ } as const;
43
+
44
+ export type DeploymentViaType = (typeof DeploymentVia)[keyof typeof DeploymentVia];
45
+
22
46
  /**
23
47
  * Core deployment object - used in both API responses and SDK
24
48
  */
@@ -39,7 +63,15 @@ export interface Deployment {
39
63
  readonly password: boolean;
40
64
  /** Labels for categorization and filtering (lowercase, alphanumeric with separators). Always present, empty array when none. */
41
65
  labels: string[];
42
- /** The client/tool used to create this deployment (e.g., 'web', 'sdk', 'cli'), null if unknown */
66
+ /**
67
+ * The client/tool that created this deployment, null if unknown.
68
+ *
69
+ * Deliberately wider than {@link DeploymentViaType}: this is stored data,
70
+ * and rows predate the vocabulary being closed. Narrowing the ENTITY would
71
+ * be a claim about every row already in the database; narrowing the
72
+ * REQUEST option ({@link DeploymentUploadOptions.via}) is a claim about
73
+ * what a client may send, which is ours to make.
74
+ */
43
75
  readonly via: string | null;
44
76
  /** Unix timestamp (seconds) when deployment was created */
45
77
  readonly created: number;
@@ -355,11 +387,41 @@ export interface DomainRecordsResponse {
355
387
  * API would reject the same value the same way.
356
388
  */
357
389
  export const IDEMPOTENCY_KEY_CONSTRAINTS = {
390
+ /**
391
+ * HTTP header name. Here for the same reason {@link CALLER.HEADER} is: a
392
+ * wire header has two ends, and the package that owns the value's format
393
+ * is the only place both ends can read its name from.
394
+ */
395
+ HEADER: 'Idempotency-Key',
358
396
  MAX_LENGTH: 256,
359
397
  /** How long a stored 201 stays replayable. */
360
398
  WINDOW_SECONDS: 24 * 60 * 60,
361
399
  } as const;
362
400
 
401
+ /**
402
+ * Normalize a `via` value from any transport — trimmed, lowercased, and a
403
+ * member of {@link DeploymentVia}, or `undefined`.
404
+ *
405
+ * A format rule by this package's own test: a client can decide offline
406
+ * whether a value is well-formed, and the API reaches the same verdict on the
407
+ * same input. It lived server-side until 2026-08-06, which meant clients could
408
+ * only learn their label was unusable by noticing analytics had gone quiet.
409
+ *
410
+ * **Not knowing your `via` is not an error** — an unrecognized value yields
411
+ * `undefined` rather than throwing, because origin tracking is telemetry and a
412
+ * deploy must never fail over it. A caller that has an honest default should
413
+ * prefer it (`normalizeVia(process.env.SHIP_VIA) ?? DeploymentVia.CLI`): the
414
+ * deploy really did come from the CLI, so recording that beats recording
415
+ * nothing.
416
+ */
417
+ export function normalizeVia(value: unknown): DeploymentViaType | undefined {
418
+ if (!value || typeof value !== 'string') return undefined;
419
+ const via = value.trim().toLowerCase();
420
+ return (Object.values(DeploymentVia) as string[]).includes(via)
421
+ ? (via as DeploymentViaType)
422
+ : undefined;
423
+ }
424
+
363
425
  /**
364
426
  * Validate an idempotency key, returning the trimmed value or `undefined`
365
427
  * when none was supplied. Throws {@link ShipError.validation} when the value
@@ -1811,8 +1873,12 @@ export type DeployInput = File[] | string | string[];
1811
1873
  export interface DeploymentUploadOptions {
1812
1874
  /** Optional labels for categorization and filtering */
1813
1875
  labels?: string[];
1814
- /** Client identifier (e.g., 'cli', 'sdk', 'web') */
1815
- via?: string;
1876
+ /**
1877
+ * Which client is making this deploy. Closed, because the server silently
1878
+ * ignores anything outside the set — so an unchecked string turned a typo
1879
+ * into missing analytics rather than an error. See {@link DeploymentVia}.
1880
+ */
1881
+ via?: DeploymentViaType;
1816
1882
  /**
1817
1883
  * Optional password that protects this deployment.
1818
1884
  *