@shipstatic/types 2.5.0-beta.11 → 2.5.0-beta.13
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 +9 -4
- package/dist/index.d.ts +209 -33
- package/dist/index.js +88 -0
- package/package.json +1 -1
- package/src/index.ts +235 -23
package/README.md
CHANGED
|
@@ -20,13 +20,17 @@ npm install @shipstatic/types
|
|
|
20
20
|
|
|
21
21
|
```typescript
|
|
22
22
|
import type {
|
|
23
|
-
ListResponse,
|
|
24
|
-
Deployment, DeploymentListResponse, DeploymentDeleteResponse,
|
|
25
|
-
Domain, DomainSetResult, DomainListResponse, DnsRecord, DomainDnsResponse, DomainRecordsResponse, DomainValidateResponse, DomainDeleteResponse, DomainVerifyResponse,
|
|
26
|
-
Token, TokenListResponse, TokenCreateResponse, TokenDeleteResponse,
|
|
23
|
+
ListResponse, ListOptions,
|
|
24
|
+
Deployment, DeploymentListResponse, DeploymentDeleteResponse, DeploymentSetOptions,
|
|
25
|
+
Domain, DomainSetResult, DomainSetOptions, DomainListResponse, DnsRecord, DnsLookup, DomainDnsResponse, DomainRecordsResponse, DomainShareResponse, DomainValidateResponse, DomainDeleteResponse, DomainVerifyResponse,
|
|
26
|
+
Token, TokenListResponse, TokenCreateResponse, TokenCreateOptions, TokenDeleteResponse,
|
|
27
27
|
Account, AccountUsage, AccountOverrides, AccountDeleteResponse, AccountKeyResponse,
|
|
28
|
+
LabelsResponse, SetupInstructionsResponse,
|
|
28
29
|
StaticFile
|
|
29
30
|
} from '@shipstatic/types';
|
|
31
|
+
|
|
32
|
+
// Every public path, declared once — the API mounts from it, clients request against it.
|
|
33
|
+
import { API_PATHS } from '@shipstatic/types';
|
|
30
34
|
```
|
|
31
35
|
|
|
32
36
|
A mutation answers with the resource it affected — the entity when it
|
|
@@ -123,6 +127,7 @@ import type {
|
|
|
123
127
|
import {
|
|
124
128
|
validateApiKey,
|
|
125
129
|
validateDeployToken,
|
|
130
|
+
validateIdempotencyKey,
|
|
126
131
|
validateApiUrl,
|
|
127
132
|
isDeployment,
|
|
128
133
|
isBlockedExtension,
|
package/dist/index.d.ts
CHANGED
|
@@ -49,6 +49,62 @@ export interface DeploymentCreateResponse extends Deployment {
|
|
|
49
49
|
/** Claim URL for public deployments. Present when deployed without credentials. */
|
|
50
50
|
readonly claim?: string;
|
|
51
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Every path the public API answers on, declared once.
|
|
54
|
+
*
|
|
55
|
+
* The URL surface was written out in four places — the API's mounts, the
|
|
56
|
+
* SDK's client, the dashboard's client, and the post-deploy smoke — so a
|
|
57
|
+
* rename meant finding all four. The first three now read this table.
|
|
58
|
+
*
|
|
59
|
+
* The smoke (`cloudflare/api/smoke.mjs`) deliberately still spells its own:
|
|
60
|
+
* five of its nine paths are `/admin/*`, which this table excludes by
|
|
61
|
+
* design, and splitting one list between a registry and literals reads worse
|
|
62
|
+
* than keeping it uniform.
|
|
63
|
+
*
|
|
64
|
+
* **What this guarantees, exactly.** Collection paths are mounted from here,
|
|
65
|
+
* so producer and consumer cannot diverge. Item paths are declared here and
|
|
66
|
+
* consumed by clients, but the API spells them relative to their mount
|
|
67
|
+
* (`/:deployment/config`), so the table does not *generate* them — it is
|
|
68
|
+
* held to them by `api/tests/architecture/api-paths.test.ts`, which fails if
|
|
69
|
+
* any entry names a path no route answers. Some entries have no client yet
|
|
70
|
+
* (`DEPLOYMENT_CONFIG`, `DOMAIN_PROPAGATION` — endpoints the SDK
|
|
71
|
+
* deliberately does not reach); the fence is what keeps those honest rather
|
|
72
|
+
* than merely asserted.
|
|
73
|
+
*
|
|
74
|
+
* **The operator surface is deliberately absent.** `/admin/*` paths belong
|
|
75
|
+
* to `web/my`, for the same reason its row types do: this package is
|
|
76
|
+
* published, and the operator surface is not public (see `CLAUDE.md`, "Admin
|
|
77
|
+
* types"). A path here is a promise to every npm consumer; `/admin` is a
|
|
78
|
+
* promise to one dashboard.
|
|
79
|
+
*
|
|
80
|
+
* Item paths are functions rather than templates so the key is interpolated
|
|
81
|
+
* in one place, encoded the same way by every caller.
|
|
82
|
+
*/
|
|
83
|
+
export declare const API_PATHS: {
|
|
84
|
+
readonly DEPLOYMENTS: "/deployments";
|
|
85
|
+
readonly DEPLOYMENT: (deployment: string) => string;
|
|
86
|
+
readonly DEPLOYMENT_CONFIG: (deployment: string) => string;
|
|
87
|
+
readonly DOMAINS: "/domains";
|
|
88
|
+
readonly DOMAIN: (domain: string) => string;
|
|
89
|
+
readonly DOMAIN_VERIFY: (domain: string) => string;
|
|
90
|
+
readonly DOMAIN_DNS: (domain: string) => string;
|
|
91
|
+
readonly DOMAIN_RECORDS: (domain: string) => string;
|
|
92
|
+
readonly DOMAIN_SHARE: (domain: string) => string;
|
|
93
|
+
readonly DOMAIN_PROPAGATION: (domain: string) => string;
|
|
94
|
+
readonly DOMAINS_VALIDATE: "/domains/validate";
|
|
95
|
+
readonly TOKENS: "/tokens";
|
|
96
|
+
readonly TOKEN: (token: string) => string;
|
|
97
|
+
readonly ACCOUNT: "/account";
|
|
98
|
+
readonly ACCOUNT_KEY: "/account/key";
|
|
99
|
+
readonly ACCOUNT_CLAIM: "/account/claim";
|
|
100
|
+
readonly ACTIVITIES: "/activities";
|
|
101
|
+
readonly LABELS: "/labels";
|
|
102
|
+
readonly LIMITS: "/limits";
|
|
103
|
+
readonly PING: "/ping";
|
|
104
|
+
readonly SETUP: "/setup";
|
|
105
|
+
readonly SPA_CHECK: "/spa-check";
|
|
106
|
+
readonly UPLOAD: "/upload";
|
|
107
|
+
};
|
|
52
108
|
/**
|
|
53
109
|
* The half of a list response that is identical on every list.
|
|
54
110
|
*
|
|
@@ -86,12 +142,23 @@ export interface DeploymentListResponse extends ListResponse {
|
|
|
86
142
|
* Where the resource is simply gone, the key alone is the whole answer
|
|
87
143
|
* ({@link DomainDeleteResponse}, {@link TokenDeleteResponse}).
|
|
88
144
|
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
145
|
+
* Put positively: **an acknowledgement is a projection of the resource** —
|
|
146
|
+
* its key, plus its own state field where the state changed. That is the
|
|
147
|
+
* test to apply, and it is sharper than "no constant", which this shape
|
|
148
|
+
* would fail on its own terms: `status` here is the literal `'deleting'` on
|
|
149
|
+
* every success, exactly as fixed as a `changed: true` would be.
|
|
150
|
+
*
|
|
151
|
+
* The difference is not how predictable the value is, it is what the field
|
|
152
|
+
* IS. `status` is the deployment's own field — the same one `GET
|
|
153
|
+
* /deployments/:deployment` returns — so this response is `Deployment`
|
|
154
|
+
* narrowed to two members, and a client renders it with the code it already
|
|
155
|
+
* has. `changed: true`, `queued: true` and `success: true` are not fields of
|
|
156
|
+
* any entity; they exist only to assert that the call worked, which the
|
|
157
|
+
* status code already said. Sync versus accepted is likewise the status
|
|
158
|
+
* code's job — 200 versus 202 — not a boolean's.
|
|
159
|
+
*
|
|
160
|
+
* No prose either (`message`): an acknowledgement is data, and each surface
|
|
161
|
+
* composes its own copy.
|
|
95
162
|
*/
|
|
96
163
|
export interface DeploymentDeleteResponse {
|
|
97
164
|
/** The deployment hostname that was marked for removal */
|
|
@@ -200,13 +267,33 @@ export interface DnsProvider {
|
|
|
200
267
|
/**
|
|
201
268
|
* Response for domain DNS provider lookup
|
|
202
269
|
*/
|
|
270
|
+
/**
|
|
271
|
+
* What a DNS lookup found for a domain. An envelope rather than a bare
|
|
272
|
+
* {@link DnsProvider} because a lookup can succeed and learn more than the
|
|
273
|
+
* provider later; the shape is named so a consumer can hold one.
|
|
274
|
+
*/
|
|
275
|
+
export interface DnsLookup {
|
|
276
|
+
/** The provider serving this domain's DNS, absent when unidentified */
|
|
277
|
+
provider?: DnsProvider;
|
|
278
|
+
}
|
|
203
279
|
export interface DomainDnsResponse {
|
|
204
280
|
/** The domain name */
|
|
205
281
|
domain: string;
|
|
206
282
|
/** DNS provider information, null if not yet looked up */
|
|
207
|
-
dns:
|
|
208
|
-
|
|
209
|
-
|
|
283
|
+
dns: DnsLookup | null;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Response for `GET /domains/:domain/share` — the domain plus the salted
|
|
287
|
+
* hash that lets someone else complete its DNS setup without an account.
|
|
288
|
+
*
|
|
289
|
+
* `/admin/domains/:domain/share` answers the same shape, which is the admin
|
|
290
|
+
* law working: the operator surface is the public grammar with a prefix.
|
|
291
|
+
*/
|
|
292
|
+
export interface DomainShareResponse {
|
|
293
|
+
/** The domain the setup link is for */
|
|
294
|
+
readonly domain: string;
|
|
295
|
+
/** The salted setup hash that authorizes the share */
|
|
296
|
+
readonly hash: string;
|
|
210
297
|
}
|
|
211
298
|
/**
|
|
212
299
|
* Response for domain DNS records
|
|
@@ -219,6 +306,53 @@ export interface DomainRecordsResponse {
|
|
|
219
306
|
/** Required DNS records for configuration */
|
|
220
307
|
records: DnsRecord[];
|
|
221
308
|
}
|
|
309
|
+
/**
|
|
310
|
+
* The envelope an `Idempotency-Key` must fit, and how long a replay lasts.
|
|
311
|
+
*
|
|
312
|
+
* Format lives here rather than on the server alone by the format-vs-policy
|
|
313
|
+
* rule: a client can decide offline whether a key is well-formed, and the
|
|
314
|
+
* API would reject the same value the same way.
|
|
315
|
+
*/
|
|
316
|
+
export declare const IDEMPOTENCY_KEY_CONSTRAINTS: {
|
|
317
|
+
readonly MAX_LENGTH: 256;
|
|
318
|
+
/** How long a stored 201 stays replayable. */
|
|
319
|
+
readonly WINDOW_SECONDS: number;
|
|
320
|
+
};
|
|
321
|
+
/**
|
|
322
|
+
* Validate an idempotency key, returning the trimmed value or `undefined`
|
|
323
|
+
* when none was supplied. Throws {@link ShipError.validation} when the value
|
|
324
|
+
* cannot be sent — the same verdict the API would reach, reached earlier.
|
|
325
|
+
*/
|
|
326
|
+
export declare function validateIdempotencyKey(value: unknown): string | undefined;
|
|
327
|
+
/**
|
|
328
|
+
* Response for `GET /labels` — every label in use across the caller's
|
|
329
|
+
* deployments, domains and tokens, grouped and ordered by last use.
|
|
330
|
+
*
|
|
331
|
+
* The one plural noun outside the list contract, deliberately: labels have
|
|
332
|
+
* no identity, no row and no `created`, so there is nothing for a keyset
|
|
333
|
+
* cursor to resume after, and its consumer is an autocomplete that wants the
|
|
334
|
+
* whole set. Bounded by `PAGINATION.GLOBAL_LIMIT` rather than paginated.
|
|
335
|
+
*/
|
|
336
|
+
export interface LabelsResponse {
|
|
337
|
+
readonly labels: string[];
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Response for `POST /setup` — the DNS instructions for one domain, written
|
|
341
|
+
* for a human to follow at their registrar.
|
|
342
|
+
*
|
|
343
|
+
* `custom` is the provider-specific walkthrough when the provider is known;
|
|
344
|
+
* `generic` always answers, so a caller never has nothing to show.
|
|
345
|
+
*/
|
|
346
|
+
export interface SetupInstructionsResponse {
|
|
347
|
+
/** One-line summary of what to do */
|
|
348
|
+
readonly tldr: string;
|
|
349
|
+
/** Provider-specific instructions, null when the provider is unknown */
|
|
350
|
+
readonly custom: string | null;
|
|
351
|
+
/** Provider-agnostic instructions — always present */
|
|
352
|
+
readonly generic: string;
|
|
353
|
+
/** The identified DNS provider, null when unknown */
|
|
354
|
+
readonly provider: string | null;
|
|
355
|
+
}
|
|
222
356
|
/**
|
|
223
357
|
* Response for domain validation
|
|
224
358
|
*/
|
|
@@ -839,16 +973,22 @@ export interface SPACheckRequest {
|
|
|
839
973
|
/**
|
|
840
974
|
* Response from SPA check endpoint
|
|
841
975
|
*/
|
|
976
|
+
/**
|
|
977
|
+
* Which of the classifier's tiers reached the verdict, and why. Named rather
|
|
978
|
+
* than inline so the API's own `checkSPA` can return `SPACheckResponse`
|
|
979
|
+
* instead of restating its shape.
|
|
980
|
+
*/
|
|
981
|
+
export interface SPACheckDebug {
|
|
982
|
+
/** Which tier made the detection */
|
|
983
|
+
tier: 'exclusions' | 'inclusions' | 'scoring' | 'ai' | 'fallback';
|
|
984
|
+
/** The reason for the detection result */
|
|
985
|
+
reason: string;
|
|
986
|
+
}
|
|
842
987
|
export interface SPACheckResponse {
|
|
843
988
|
/** Whether the project is detected as a Single Page Application */
|
|
844
989
|
isSPA: boolean;
|
|
845
990
|
/** Debugging information about detection */
|
|
846
|
-
debug:
|
|
847
|
-
/** Which tier made the detection: 'exclusions', 'inclusions', 'scoring', 'ai', or 'fallback' */
|
|
848
|
-
tier: 'exclusions' | 'inclusions' | 'scoring' | 'ai' | 'fallback';
|
|
849
|
-
/** The reason for the detection result */
|
|
850
|
-
reason: string;
|
|
851
|
-
};
|
|
991
|
+
debug: SPACheckDebug;
|
|
852
992
|
}
|
|
853
993
|
/**
|
|
854
994
|
* Represents a file that has been processed and is ready for deploy.
|
|
@@ -920,6 +1060,25 @@ export interface DeploymentUploadOptions {
|
|
|
920
1060
|
spa?: boolean;
|
|
921
1061
|
/** @internal reCAPTCHA proof for the anonymous human deploy channel. Only available via /upload endpoint. */
|
|
922
1062
|
captcha?: string;
|
|
1063
|
+
/**
|
|
1064
|
+
* Makes this deploy replayable instead of repeatable.
|
|
1065
|
+
*
|
|
1066
|
+
* A deploy is not naturally idempotent: a client-side timeout on a slow
|
|
1067
|
+
* one leaves the caller unable to tell "it never landed" from "it landed
|
|
1068
|
+
* and the response was lost", and retrying produces a second deployment.
|
|
1069
|
+
* Send the same key on the retry and the platform replays the original
|
|
1070
|
+
* 201 verbatim rather than creating anything
|
|
1071
|
+
* ({@link IDEMPOTENCY_KEY_CONSTRAINTS.WINDOW_SECONDS}).
|
|
1072
|
+
*
|
|
1073
|
+
* **Agents are the audience.** A human notices a duplicate; an automated
|
|
1074
|
+
* retry does not. Pick a key that identifies the ATTEMPT — a run id, a
|
|
1075
|
+
* commit sha, a uuid minted before the first try — never one that varies
|
|
1076
|
+
* per attempt, which would defeat the point.
|
|
1077
|
+
*
|
|
1078
|
+
* The replay is per-caller, and it stores successes only: a failed deploy
|
|
1079
|
+
* retries fresh under the same key.
|
|
1080
|
+
*/
|
|
1081
|
+
idempotencyKey?: string;
|
|
923
1082
|
}
|
|
924
1083
|
/**
|
|
925
1084
|
* Pagination options for every list endpoint. The response's `cursor` feeds
|
|
@@ -943,6 +1102,33 @@ export interface ListOptions {
|
|
|
943
1102
|
/** Opaque cursor from the previous page's response. */
|
|
944
1103
|
cursor?: string;
|
|
945
1104
|
}
|
|
1105
|
+
/**
|
|
1106
|
+
* What a caller may change on an existing deployment.
|
|
1107
|
+
*
|
|
1108
|
+
* Labels and nothing else: a deployment's content is immutable by design, so
|
|
1109
|
+
* this is the whole mutable surface rather than a subset someone chose.
|
|
1110
|
+
*/
|
|
1111
|
+
export interface DeploymentSetOptions {
|
|
1112
|
+
labels: string[];
|
|
1113
|
+
}
|
|
1114
|
+
/**
|
|
1115
|
+
* What `domains.set()` may create or change. Every field is optional because
|
|
1116
|
+
* the call is a natural-key upsert: omitting `deployment` reserves the
|
|
1117
|
+
* domain, naming one links or re-points it, and labels travel either way.
|
|
1118
|
+
*
|
|
1119
|
+
* `deployment` is deliberately not nullable — unlinking is refused (400).
|
|
1120
|
+
* See `npm/ship/CLAUDE.md`, "Domain Write Semantics".
|
|
1121
|
+
*/
|
|
1122
|
+
export interface DomainSetOptions {
|
|
1123
|
+
deployment?: string;
|
|
1124
|
+
labels?: string[];
|
|
1125
|
+
}
|
|
1126
|
+
/** What a caller may set when minting a deploy token. */
|
|
1127
|
+
export interface TokenCreateOptions {
|
|
1128
|
+
/** Seconds until expiry; omit for a token that never expires. */
|
|
1129
|
+
ttl?: number;
|
|
1130
|
+
labels?: string[];
|
|
1131
|
+
}
|
|
946
1132
|
/**
|
|
947
1133
|
* Deployment resource interface - the contract all implementations must follow.
|
|
948
1134
|
*
|
|
@@ -955,30 +1141,22 @@ export interface DeploymentResource<UploadOptions extends DeploymentUploadOption
|
|
|
955
1141
|
upload: (input: DeployInput, options?: UploadOptions) => Promise<DeploymentCreateResponse>;
|
|
956
1142
|
list: (options?: ListOptions) => Promise<DeploymentListResponse>;
|
|
957
1143
|
get: (id: string) => Promise<Deployment>;
|
|
958
|
-
set: (id: string, options:
|
|
959
|
-
|
|
960
|
-
}) => Promise<Deployment>;
|
|
961
|
-
remove: (id: string) => Promise<void>;
|
|
1144
|
+
set: (id: string, options: DeploymentSetOptions) => Promise<Deployment>;
|
|
1145
|
+
remove: (id: string) => Promise<DeploymentDeleteResponse>;
|
|
962
1146
|
}
|
|
963
1147
|
/**
|
|
964
1148
|
* Domain resource interface - the contract all implementations must follow
|
|
965
1149
|
*/
|
|
966
1150
|
export interface DomainResource {
|
|
967
|
-
set: (name: string, options?:
|
|
968
|
-
deployment?: string;
|
|
969
|
-
labels?: string[];
|
|
970
|
-
}) => Promise<DomainSetResult>;
|
|
1151
|
+
set: (name: string, options?: DomainSetOptions) => Promise<DomainSetResult>;
|
|
971
1152
|
list: (options?: ListOptions) => Promise<DomainListResponse>;
|
|
972
1153
|
get: (name: string) => Promise<Domain>;
|
|
973
|
-
remove: (name: string) => Promise<
|
|
1154
|
+
remove: (name: string) => Promise<DomainDeleteResponse>;
|
|
974
1155
|
verify: (name: string) => Promise<DomainVerifyResponse>;
|
|
975
1156
|
validate: (name: string) => Promise<DomainValidateResponse>;
|
|
976
1157
|
dns: (name: string) => Promise<DomainDnsResponse>;
|
|
977
1158
|
records: (name: string) => Promise<DomainRecordsResponse>;
|
|
978
|
-
share: (name: string) => Promise<
|
|
979
|
-
domain: string;
|
|
980
|
-
hash: string;
|
|
981
|
-
}>;
|
|
1159
|
+
share: (name: string) => Promise<DomainShareResponse>;
|
|
982
1160
|
}
|
|
983
1161
|
/**
|
|
984
1162
|
* Account resource interface - the contract all implementations must follow
|
|
@@ -990,12 +1168,10 @@ export interface AccountResource {
|
|
|
990
1168
|
* Token resource interface - the contract all implementations must follow
|
|
991
1169
|
*/
|
|
992
1170
|
export interface TokenResource {
|
|
993
|
-
create: (options?:
|
|
994
|
-
ttl?: number;
|
|
995
|
-
labels?: string[];
|
|
996
|
-
}) => Promise<TokenCreateResponse>;
|
|
1171
|
+
create: (options?: TokenCreateOptions) => Promise<TokenCreateResponse>;
|
|
997
1172
|
list: (options?: ListOptions) => Promise<TokenListResponse>;
|
|
998
|
-
|
|
1173
|
+
get: (token: string) => Promise<Token>;
|
|
1174
|
+
remove: (token: string) => Promise<TokenDeleteResponse>;
|
|
999
1175
|
}
|
|
1000
1176
|
/**
|
|
1001
1177
|
* Billing status response from GET /billing/status
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,62 @@ export const DeploymentStatus = {
|
|
|
14
14
|
FAILED: 'failed',
|
|
15
15
|
DELETING: 'deleting',
|
|
16
16
|
};
|
|
17
|
+
/**
|
|
18
|
+
* Every path the public API answers on, declared once.
|
|
19
|
+
*
|
|
20
|
+
* The URL surface was written out in four places — the API's mounts, the
|
|
21
|
+
* SDK's client, the dashboard's client, and the post-deploy smoke — so a
|
|
22
|
+
* rename meant finding all four. The first three now read this table.
|
|
23
|
+
*
|
|
24
|
+
* The smoke (`cloudflare/api/smoke.mjs`) deliberately still spells its own:
|
|
25
|
+
* five of its nine paths are `/admin/*`, which this table excludes by
|
|
26
|
+
* design, and splitting one list between a registry and literals reads worse
|
|
27
|
+
* than keeping it uniform.
|
|
28
|
+
*
|
|
29
|
+
* **What this guarantees, exactly.** Collection paths are mounted from here,
|
|
30
|
+
* so producer and consumer cannot diverge. Item paths are declared here and
|
|
31
|
+
* consumed by clients, but the API spells them relative to their mount
|
|
32
|
+
* (`/:deployment/config`), so the table does not *generate* them — it is
|
|
33
|
+
* held to them by `api/tests/architecture/api-paths.test.ts`, which fails if
|
|
34
|
+
* any entry names a path no route answers. Some entries have no client yet
|
|
35
|
+
* (`DEPLOYMENT_CONFIG`, `DOMAIN_PROPAGATION` — endpoints the SDK
|
|
36
|
+
* deliberately does not reach); the fence is what keeps those honest rather
|
|
37
|
+
* than merely asserted.
|
|
38
|
+
*
|
|
39
|
+
* **The operator surface is deliberately absent.** `/admin/*` paths belong
|
|
40
|
+
* to `web/my`, for the same reason its row types do: this package is
|
|
41
|
+
* published, and the operator surface is not public (see `CLAUDE.md`, "Admin
|
|
42
|
+
* types"). A path here is a promise to every npm consumer; `/admin` is a
|
|
43
|
+
* promise to one dashboard.
|
|
44
|
+
*
|
|
45
|
+
* Item paths are functions rather than templates so the key is interpolated
|
|
46
|
+
* in one place, encoded the same way by every caller.
|
|
47
|
+
*/
|
|
48
|
+
export const API_PATHS = {
|
|
49
|
+
DEPLOYMENTS: '/deployments',
|
|
50
|
+
DEPLOYMENT: (deployment) => `/deployments/${deployment}`,
|
|
51
|
+
DEPLOYMENT_CONFIG: (deployment) => `/deployments/${deployment}/config`,
|
|
52
|
+
DOMAINS: '/domains',
|
|
53
|
+
DOMAIN: (domain) => `/domains/${domain}`,
|
|
54
|
+
DOMAIN_VERIFY: (domain) => `/domains/${domain}/verify`,
|
|
55
|
+
DOMAIN_DNS: (domain) => `/domains/${domain}/dns`,
|
|
56
|
+
DOMAIN_RECORDS: (domain) => `/domains/${domain}/records`,
|
|
57
|
+
DOMAIN_SHARE: (domain) => `/domains/${domain}/share`,
|
|
58
|
+
DOMAIN_PROPAGATION: (domain) => `/domains/${domain}/propagation`,
|
|
59
|
+
DOMAINS_VALIDATE: '/domains/validate',
|
|
60
|
+
TOKENS: '/tokens',
|
|
61
|
+
TOKEN: (token) => `/tokens/${token}`,
|
|
62
|
+
ACCOUNT: '/account',
|
|
63
|
+
ACCOUNT_KEY: '/account/key',
|
|
64
|
+
ACCOUNT_CLAIM: '/account/claim',
|
|
65
|
+
ACTIVITIES: '/activities',
|
|
66
|
+
LABELS: '/labels',
|
|
67
|
+
LIMITS: '/limits',
|
|
68
|
+
PING: '/ping',
|
|
69
|
+
SETUP: '/setup',
|
|
70
|
+
SPA_CHECK: '/spa-check',
|
|
71
|
+
UPLOAD: '/upload',
|
|
72
|
+
};
|
|
17
73
|
// =============================================================================
|
|
18
74
|
// DOMAIN TYPES
|
|
19
75
|
// =============================================================================
|
|
@@ -31,6 +87,38 @@ export const DomainStatus = {
|
|
|
31
87
|
SUCCESS: 'success',
|
|
32
88
|
PAUSED: 'paused',
|
|
33
89
|
};
|
|
90
|
+
/**
|
|
91
|
+
* The envelope an `Idempotency-Key` must fit, and how long a replay lasts.
|
|
92
|
+
*
|
|
93
|
+
* Format lives here rather than on the server alone by the format-vs-policy
|
|
94
|
+
* rule: a client can decide offline whether a key is well-formed, and the
|
|
95
|
+
* API would reject the same value the same way.
|
|
96
|
+
*/
|
|
97
|
+
export const IDEMPOTENCY_KEY_CONSTRAINTS = {
|
|
98
|
+
MAX_LENGTH: 256,
|
|
99
|
+
/** How long a stored 201 stays replayable. */
|
|
100
|
+
WINDOW_SECONDS: 24 * 60 * 60,
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* Validate an idempotency key, returning the trimmed value or `undefined`
|
|
104
|
+
* when none was supplied. Throws {@link ShipError.validation} when the value
|
|
105
|
+
* cannot be sent — the same verdict the API would reach, reached earlier.
|
|
106
|
+
*/
|
|
107
|
+
export function validateIdempotencyKey(value) {
|
|
108
|
+
if (value === undefined || value === null)
|
|
109
|
+
return undefined;
|
|
110
|
+
if (typeof value !== 'string') {
|
|
111
|
+
throw ShipError.validation('Idempotency key must be a string.');
|
|
112
|
+
}
|
|
113
|
+
const key = value.trim();
|
|
114
|
+
if (!key) {
|
|
115
|
+
throw ShipError.validation('Idempotency key must not be empty.');
|
|
116
|
+
}
|
|
117
|
+
if (key.length > IDEMPOTENCY_KEY_CONSTRAINTS.MAX_LENGTH) {
|
|
118
|
+
throw ShipError.validation(`Idempotency key must be at most ${IDEMPOTENCY_KEY_CONSTRAINTS.MAX_LENGTH} characters.`);
|
|
119
|
+
}
|
|
120
|
+
return key;
|
|
121
|
+
}
|
|
34
122
|
// =============================================================================
|
|
35
123
|
// ACCOUNT TYPES
|
|
36
124
|
// =============================================================================
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -58,6 +58,63 @@ export interface DeploymentCreateResponse extends Deployment {
|
|
|
58
58
|
readonly claim?: string;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Every path the public API answers on, declared once.
|
|
63
|
+
*
|
|
64
|
+
* The URL surface was written out in four places — the API's mounts, the
|
|
65
|
+
* SDK's client, the dashboard's client, and the post-deploy smoke — so a
|
|
66
|
+
* rename meant finding all four. The first three now read this table.
|
|
67
|
+
*
|
|
68
|
+
* The smoke (`cloudflare/api/smoke.mjs`) deliberately still spells its own:
|
|
69
|
+
* five of its nine paths are `/admin/*`, which this table excludes by
|
|
70
|
+
* design, and splitting one list between a registry and literals reads worse
|
|
71
|
+
* than keeping it uniform.
|
|
72
|
+
*
|
|
73
|
+
* **What this guarantees, exactly.** Collection paths are mounted from here,
|
|
74
|
+
* so producer and consumer cannot diverge. Item paths are declared here and
|
|
75
|
+
* consumed by clients, but the API spells them relative to their mount
|
|
76
|
+
* (`/:deployment/config`), so the table does not *generate* them — it is
|
|
77
|
+
* held to them by `api/tests/architecture/api-paths.test.ts`, which fails if
|
|
78
|
+
* any entry names a path no route answers. Some entries have no client yet
|
|
79
|
+
* (`DEPLOYMENT_CONFIG`, `DOMAIN_PROPAGATION` — endpoints the SDK
|
|
80
|
+
* deliberately does not reach); the fence is what keeps those honest rather
|
|
81
|
+
* than merely asserted.
|
|
82
|
+
*
|
|
83
|
+
* **The operator surface is deliberately absent.** `/admin/*` paths belong
|
|
84
|
+
* to `web/my`, for the same reason its row types do: this package is
|
|
85
|
+
* published, and the operator surface is not public (see `CLAUDE.md`, "Admin
|
|
86
|
+
* types"). A path here is a promise to every npm consumer; `/admin` is a
|
|
87
|
+
* promise to one dashboard.
|
|
88
|
+
*
|
|
89
|
+
* Item paths are functions rather than templates so the key is interpolated
|
|
90
|
+
* in one place, encoded the same way by every caller.
|
|
91
|
+
*/
|
|
92
|
+
export const API_PATHS = {
|
|
93
|
+
DEPLOYMENTS: '/deployments',
|
|
94
|
+
DEPLOYMENT: (deployment: string) => `/deployments/${deployment}`,
|
|
95
|
+
DEPLOYMENT_CONFIG: (deployment: string) => `/deployments/${deployment}/config`,
|
|
96
|
+
DOMAINS: '/domains',
|
|
97
|
+
DOMAIN: (domain: string) => `/domains/${domain}`,
|
|
98
|
+
DOMAIN_VERIFY: (domain: string) => `/domains/${domain}/verify`,
|
|
99
|
+
DOMAIN_DNS: (domain: string) => `/domains/${domain}/dns`,
|
|
100
|
+
DOMAIN_RECORDS: (domain: string) => `/domains/${domain}/records`,
|
|
101
|
+
DOMAIN_SHARE: (domain: string) => `/domains/${domain}/share`,
|
|
102
|
+
DOMAIN_PROPAGATION: (domain: string) => `/domains/${domain}/propagation`,
|
|
103
|
+
DOMAINS_VALIDATE: '/domains/validate',
|
|
104
|
+
TOKENS: '/tokens',
|
|
105
|
+
TOKEN: (token: string) => `/tokens/${token}`,
|
|
106
|
+
ACCOUNT: '/account',
|
|
107
|
+
ACCOUNT_KEY: '/account/key',
|
|
108
|
+
ACCOUNT_CLAIM: '/account/claim',
|
|
109
|
+
ACTIVITIES: '/activities',
|
|
110
|
+
LABELS: '/labels',
|
|
111
|
+
LIMITS: '/limits',
|
|
112
|
+
PING: '/ping',
|
|
113
|
+
SETUP: '/setup',
|
|
114
|
+
SPA_CHECK: '/spa-check',
|
|
115
|
+
UPLOAD: '/upload',
|
|
116
|
+
} as const;
|
|
117
|
+
|
|
61
118
|
/**
|
|
62
119
|
* The half of a list response that is identical on every list.
|
|
63
120
|
*
|
|
@@ -97,12 +154,23 @@ export interface DeploymentListResponse extends ListResponse {
|
|
|
97
154
|
* Where the resource is simply gone, the key alone is the whole answer
|
|
98
155
|
* ({@link DomainDeleteResponse}, {@link TokenDeleteResponse}).
|
|
99
156
|
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
157
|
+
* Put positively: **an acknowledgement is a projection of the resource** —
|
|
158
|
+
* its key, plus its own state field where the state changed. That is the
|
|
159
|
+
* test to apply, and it is sharper than "no constant", which this shape
|
|
160
|
+
* would fail on its own terms: `status` here is the literal `'deleting'` on
|
|
161
|
+
* every success, exactly as fixed as a `changed: true` would be.
|
|
162
|
+
*
|
|
163
|
+
* The difference is not how predictable the value is, it is what the field
|
|
164
|
+
* IS. `status` is the deployment's own field — the same one `GET
|
|
165
|
+
* /deployments/:deployment` returns — so this response is `Deployment`
|
|
166
|
+
* narrowed to two members, and a client renders it with the code it already
|
|
167
|
+
* has. `changed: true`, `queued: true` and `success: true` are not fields of
|
|
168
|
+
* any entity; they exist only to assert that the call worked, which the
|
|
169
|
+
* status code already said. Sync versus accepted is likewise the status
|
|
170
|
+
* code's job — 200 versus 202 — not a boolean's.
|
|
171
|
+
*
|
|
172
|
+
* No prose either (`message`): an acknowledgement is data, and each surface
|
|
173
|
+
* composes its own copy.
|
|
106
174
|
*/
|
|
107
175
|
export interface DeploymentDeleteResponse {
|
|
108
176
|
/** The deployment hostname that was marked for removal */
|
|
@@ -226,11 +294,35 @@ export interface DnsProvider {
|
|
|
226
294
|
/**
|
|
227
295
|
* Response for domain DNS provider lookup
|
|
228
296
|
*/
|
|
297
|
+
/**
|
|
298
|
+
* What a DNS lookup found for a domain. An envelope rather than a bare
|
|
299
|
+
* {@link DnsProvider} because a lookup can succeed and learn more than the
|
|
300
|
+
* provider later; the shape is named so a consumer can hold one.
|
|
301
|
+
*/
|
|
302
|
+
export interface DnsLookup {
|
|
303
|
+
/** The provider serving this domain's DNS, absent when unidentified */
|
|
304
|
+
provider?: DnsProvider;
|
|
305
|
+
}
|
|
306
|
+
|
|
229
307
|
export interface DomainDnsResponse {
|
|
230
308
|
/** The domain name */
|
|
231
309
|
domain: string;
|
|
232
310
|
/** DNS provider information, null if not yet looked up */
|
|
233
|
-
dns:
|
|
311
|
+
dns: DnsLookup | null;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Response for `GET /domains/:domain/share` — the domain plus the salted
|
|
316
|
+
* hash that lets someone else complete its DNS setup without an account.
|
|
317
|
+
*
|
|
318
|
+
* `/admin/domains/:domain/share` answers the same shape, which is the admin
|
|
319
|
+
* law working: the operator surface is the public grammar with a prefix.
|
|
320
|
+
*/
|
|
321
|
+
export interface DomainShareResponse {
|
|
322
|
+
/** The domain the setup link is for */
|
|
323
|
+
readonly domain: string;
|
|
324
|
+
/** The salted setup hash that authorizes the share */
|
|
325
|
+
readonly hash: string;
|
|
234
326
|
}
|
|
235
327
|
|
|
236
328
|
/**
|
|
@@ -245,6 +337,72 @@ export interface DomainRecordsResponse {
|
|
|
245
337
|
records: DnsRecord[];
|
|
246
338
|
}
|
|
247
339
|
|
|
340
|
+
/**
|
|
341
|
+
* The envelope an `Idempotency-Key` must fit, and how long a replay lasts.
|
|
342
|
+
*
|
|
343
|
+
* Format lives here rather than on the server alone by the format-vs-policy
|
|
344
|
+
* rule: a client can decide offline whether a key is well-formed, and the
|
|
345
|
+
* API would reject the same value the same way.
|
|
346
|
+
*/
|
|
347
|
+
export const IDEMPOTENCY_KEY_CONSTRAINTS = {
|
|
348
|
+
MAX_LENGTH: 256,
|
|
349
|
+
/** How long a stored 201 stays replayable. */
|
|
350
|
+
WINDOW_SECONDS: 24 * 60 * 60,
|
|
351
|
+
} as const;
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Validate an idempotency key, returning the trimmed value or `undefined`
|
|
355
|
+
* when none was supplied. Throws {@link ShipError.validation} when the value
|
|
356
|
+
* cannot be sent — the same verdict the API would reach, reached earlier.
|
|
357
|
+
*/
|
|
358
|
+
export function validateIdempotencyKey(value: unknown): string | undefined {
|
|
359
|
+
if (value === undefined || value === null) return undefined;
|
|
360
|
+
if (typeof value !== 'string') {
|
|
361
|
+
throw ShipError.validation('Idempotency key must be a string.');
|
|
362
|
+
}
|
|
363
|
+
const key = value.trim();
|
|
364
|
+
if (!key) {
|
|
365
|
+
throw ShipError.validation('Idempotency key must not be empty.');
|
|
366
|
+
}
|
|
367
|
+
if (key.length > IDEMPOTENCY_KEY_CONSTRAINTS.MAX_LENGTH) {
|
|
368
|
+
throw ShipError.validation(
|
|
369
|
+
`Idempotency key must be at most ${IDEMPOTENCY_KEY_CONSTRAINTS.MAX_LENGTH} characters.`,
|
|
370
|
+
);
|
|
371
|
+
}
|
|
372
|
+
return key;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Response for `GET /labels` — every label in use across the caller's
|
|
377
|
+
* deployments, domains and tokens, grouped and ordered by last use.
|
|
378
|
+
*
|
|
379
|
+
* The one plural noun outside the list contract, deliberately: labels have
|
|
380
|
+
* no identity, no row and no `created`, so there is nothing for a keyset
|
|
381
|
+
* cursor to resume after, and its consumer is an autocomplete that wants the
|
|
382
|
+
* whole set. Bounded by `PAGINATION.GLOBAL_LIMIT` rather than paginated.
|
|
383
|
+
*/
|
|
384
|
+
export interface LabelsResponse {
|
|
385
|
+
readonly labels: string[];
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Response for `POST /setup` — the DNS instructions for one domain, written
|
|
390
|
+
* for a human to follow at their registrar.
|
|
391
|
+
*
|
|
392
|
+
* `custom` is the provider-specific walkthrough when the provider is known;
|
|
393
|
+
* `generic` always answers, so a caller never has nothing to show.
|
|
394
|
+
*/
|
|
395
|
+
export interface SetupInstructionsResponse {
|
|
396
|
+
/** One-line summary of what to do */
|
|
397
|
+
readonly tldr: string;
|
|
398
|
+
/** Provider-specific instructions, null when the provider is unknown */
|
|
399
|
+
readonly custom: string | null;
|
|
400
|
+
/** Provider-agnostic instructions — always present */
|
|
401
|
+
readonly generic: string;
|
|
402
|
+
/** The identified DNS provider, null when unknown */
|
|
403
|
+
readonly provider: string | null;
|
|
404
|
+
}
|
|
405
|
+
|
|
248
406
|
/**
|
|
249
407
|
* Response for domain validation
|
|
250
408
|
*/
|
|
@@ -1320,16 +1478,23 @@ export interface SPACheckRequest {
|
|
|
1320
1478
|
/**
|
|
1321
1479
|
* Response from SPA check endpoint
|
|
1322
1480
|
*/
|
|
1481
|
+
/**
|
|
1482
|
+
* Which of the classifier's tiers reached the verdict, and why. Named rather
|
|
1483
|
+
* than inline so the API's own `checkSPA` can return `SPACheckResponse`
|
|
1484
|
+
* instead of restating its shape.
|
|
1485
|
+
*/
|
|
1486
|
+
export interface SPACheckDebug {
|
|
1487
|
+
/** Which tier made the detection */
|
|
1488
|
+
tier: 'exclusions' | 'inclusions' | 'scoring' | 'ai' | 'fallback';
|
|
1489
|
+
/** The reason for the detection result */
|
|
1490
|
+
reason: string;
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1323
1493
|
export interface SPACheckResponse {
|
|
1324
1494
|
/** Whether the project is detected as a Single Page Application */
|
|
1325
1495
|
isSPA: boolean;
|
|
1326
1496
|
/** Debugging information about detection */
|
|
1327
|
-
debug:
|
|
1328
|
-
/** Which tier made the detection: 'exclusions', 'inclusions', 'scoring', 'ai', or 'fallback' */
|
|
1329
|
-
tier: 'exclusions' | 'inclusions' | 'scoring' | 'ai' | 'fallback';
|
|
1330
|
-
/** The reason for the detection result */
|
|
1331
|
-
reason: string;
|
|
1332
|
-
};
|
|
1497
|
+
debug: SPACheckDebug;
|
|
1333
1498
|
}
|
|
1334
1499
|
|
|
1335
1500
|
// =============================================================================
|
|
@@ -1417,6 +1582,25 @@ export interface DeploymentUploadOptions {
|
|
|
1417
1582
|
spa?: boolean;
|
|
1418
1583
|
/** @internal reCAPTCHA proof for the anonymous human deploy channel. Only available via /upload endpoint. */
|
|
1419
1584
|
captcha?: string;
|
|
1585
|
+
/**
|
|
1586
|
+
* Makes this deploy replayable instead of repeatable.
|
|
1587
|
+
*
|
|
1588
|
+
* A deploy is not naturally idempotent: a client-side timeout on a slow
|
|
1589
|
+
* one leaves the caller unable to tell "it never landed" from "it landed
|
|
1590
|
+
* and the response was lost", and retrying produces a second deployment.
|
|
1591
|
+
* Send the same key on the retry and the platform replays the original
|
|
1592
|
+
* 201 verbatim rather than creating anything
|
|
1593
|
+
* ({@link IDEMPOTENCY_KEY_CONSTRAINTS.WINDOW_SECONDS}).
|
|
1594
|
+
*
|
|
1595
|
+
* **Agents are the audience.** A human notices a duplicate; an automated
|
|
1596
|
+
* retry does not. Pick a key that identifies the ATTEMPT — a run id, a
|
|
1597
|
+
* commit sha, a uuid minted before the first try — never one that varies
|
|
1598
|
+
* per attempt, which would defeat the point.
|
|
1599
|
+
*
|
|
1600
|
+
* The replay is per-caller, and it stores successes only: a failed deploy
|
|
1601
|
+
* retries fresh under the same key.
|
|
1602
|
+
*/
|
|
1603
|
+
idempotencyKey?: string;
|
|
1420
1604
|
}
|
|
1421
1605
|
|
|
1422
1606
|
/**
|
|
@@ -1442,6 +1626,36 @@ export interface ListOptions {
|
|
|
1442
1626
|
cursor?: string;
|
|
1443
1627
|
}
|
|
1444
1628
|
|
|
1629
|
+
/**
|
|
1630
|
+
* What a caller may change on an existing deployment.
|
|
1631
|
+
*
|
|
1632
|
+
* Labels and nothing else: a deployment's content is immutable by design, so
|
|
1633
|
+
* this is the whole mutable surface rather than a subset someone chose.
|
|
1634
|
+
*/
|
|
1635
|
+
export interface DeploymentSetOptions {
|
|
1636
|
+
labels: string[];
|
|
1637
|
+
}
|
|
1638
|
+
|
|
1639
|
+
/**
|
|
1640
|
+
* What `domains.set()` may create or change. Every field is optional because
|
|
1641
|
+
* the call is a natural-key upsert: omitting `deployment` reserves the
|
|
1642
|
+
* domain, naming one links or re-points it, and labels travel either way.
|
|
1643
|
+
*
|
|
1644
|
+
* `deployment` is deliberately not nullable — unlinking is refused (400).
|
|
1645
|
+
* See `npm/ship/CLAUDE.md`, "Domain Write Semantics".
|
|
1646
|
+
*/
|
|
1647
|
+
export interface DomainSetOptions {
|
|
1648
|
+
deployment?: string;
|
|
1649
|
+
labels?: string[];
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1652
|
+
/** What a caller may set when minting a deploy token. */
|
|
1653
|
+
export interface TokenCreateOptions {
|
|
1654
|
+
/** Seconds until expiry; omit for a token that never expires. */
|
|
1655
|
+
ttl?: number;
|
|
1656
|
+
labels?: string[];
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1445
1659
|
/**
|
|
1446
1660
|
* Deployment resource interface - the contract all implementations must follow.
|
|
1447
1661
|
*
|
|
@@ -1456,26 +1670,23 @@ export interface DeploymentResource<
|
|
|
1456
1670
|
upload: (input: DeployInput, options?: UploadOptions) => Promise<DeploymentCreateResponse>;
|
|
1457
1671
|
list: (options?: ListOptions) => Promise<DeploymentListResponse>;
|
|
1458
1672
|
get: (id: string) => Promise<Deployment>;
|
|
1459
|
-
set: (id: string, options:
|
|
1460
|
-
remove: (id: string) => Promise<
|
|
1673
|
+
set: (id: string, options: DeploymentSetOptions) => Promise<Deployment>;
|
|
1674
|
+
remove: (id: string) => Promise<DeploymentDeleteResponse>;
|
|
1461
1675
|
}
|
|
1462
1676
|
|
|
1463
1677
|
/**
|
|
1464
1678
|
* Domain resource interface - the contract all implementations must follow
|
|
1465
1679
|
*/
|
|
1466
1680
|
export interface DomainResource {
|
|
1467
|
-
set: (
|
|
1468
|
-
name: string,
|
|
1469
|
-
options?: { deployment?: string; labels?: string[] },
|
|
1470
|
-
) => Promise<DomainSetResult>;
|
|
1681
|
+
set: (name: string, options?: DomainSetOptions) => Promise<DomainSetResult>;
|
|
1471
1682
|
list: (options?: ListOptions) => Promise<DomainListResponse>;
|
|
1472
1683
|
get: (name: string) => Promise<Domain>;
|
|
1473
|
-
remove: (name: string) => Promise<
|
|
1684
|
+
remove: (name: string) => Promise<DomainDeleteResponse>;
|
|
1474
1685
|
verify: (name: string) => Promise<DomainVerifyResponse>;
|
|
1475
1686
|
validate: (name: string) => Promise<DomainValidateResponse>;
|
|
1476
1687
|
dns: (name: string) => Promise<DomainDnsResponse>;
|
|
1477
1688
|
records: (name: string) => Promise<DomainRecordsResponse>;
|
|
1478
|
-
share: (name: string) => Promise<
|
|
1689
|
+
share: (name: string) => Promise<DomainShareResponse>;
|
|
1479
1690
|
}
|
|
1480
1691
|
|
|
1481
1692
|
/**
|
|
@@ -1489,9 +1700,10 @@ export interface AccountResource {
|
|
|
1489
1700
|
* Token resource interface - the contract all implementations must follow
|
|
1490
1701
|
*/
|
|
1491
1702
|
export interface TokenResource {
|
|
1492
|
-
create: (options?:
|
|
1703
|
+
create: (options?: TokenCreateOptions) => Promise<TokenCreateResponse>;
|
|
1493
1704
|
list: (options?: ListOptions) => Promise<TokenListResponse>;
|
|
1494
|
-
|
|
1705
|
+
get: (token: string) => Promise<Token>;
|
|
1706
|
+
remove: (token: string) => Promise<TokenDeleteResponse>;
|
|
1495
1707
|
}
|
|
1496
1708
|
|
|
1497
1709
|
// =============================================================================
|