@dropthis/cli 0.4.0 → 0.5.0

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.
@@ -1,290 +1,5 @@
1
- type DropthisClientOptions = {
2
- apiKey?: string;
3
- baseUrl?: string;
4
- timeoutMs?: number;
5
- fetch?: typeof globalThis.fetch;
6
- };
7
- type RequestOptions = {
8
- authenticated?: boolean;
9
- idempotencyKey?: string;
10
- ifRevision?: number;
11
- timeoutMs?: number;
12
- };
13
- type DropthisErrorResponse = {
14
- code: string;
15
- message: string;
16
- statusCode: number | null;
17
- type?: string;
18
- detail?: unknown;
19
- param?: string | null;
20
- currentRevision?: number;
21
- requestId?: string | null;
22
- suggestion?: string | null;
23
- retryable?: boolean | null;
24
- };
25
- type DropthisResult<T> = {
26
- data: T;
27
- error: null;
28
- headers: Record<string, string>;
29
- } | {
30
- data: null;
31
- error: DropthisErrorResponse;
32
- headers: Record<string, string>;
33
- };
34
- type ActionResolve = {
35
- method: string;
36
- url?: string | null;
37
- endpoint?: string | null;
38
- };
39
- type DropAction = {
40
- code: string;
41
- kind: "api" | "human";
42
- priority: "required" | "suggested";
43
- message: string;
44
- resolve?: ActionResolve | null;
45
- };
46
- type TierInfo = {
47
- name: string;
48
- maxSizeBytes: number;
49
- ttlDays: number | null;
50
- persistent: boolean;
51
- badge: boolean;
52
- };
53
- type Limitations = {
54
- actions: DropAction[];
55
- };
56
- type DropResponse = {
57
- id: string;
58
- slug: string;
59
- url: string;
60
- canonicalHost: string;
61
- deploymentId: string | null;
62
- title: string;
63
- contentType: string;
64
- visibility: string;
65
- status: string;
66
- revision: number;
67
- contentRevision: number;
68
- accessRevision: number;
69
- sizeBytes: number;
70
- renderMode: string;
71
- warnings: Array<Record<string, unknown>>;
72
- createdAt: string;
73
- expiresAt: string | null;
74
- object: string;
75
- accessible: boolean;
76
- persistent: boolean;
77
- badgeApplied: boolean;
78
- tier: TierInfo;
79
- limitations: Limitations;
80
- };
81
- type DropDeploymentResponse = {
82
- id: string;
83
- dropId: string;
84
- revision: number;
85
- status: string;
86
- storagePrefix: string;
87
- entry: string | null;
88
- contentType: string;
89
- renderMode: string;
90
- files: Array<Record<string, unknown>>;
91
- warnings: Array<Record<string, unknown>>;
92
- sizeBytes: number;
93
- classificationVersion: number;
94
- classificationReason: string;
95
- errorCode: string | null;
96
- errorMessage: string | null;
97
- createdAt: string;
98
- readyAt: string | null;
99
- publishedAt: string | null;
100
- };
101
- type ListDeploymentsParams = {
102
- cursor?: string | null;
103
- limit?: number;
104
- };
105
- type ListDeploymentsResponse = {
106
- deployments: DropDeploymentResponse[];
107
- nextCursor: string | null;
108
- };
109
- type ListPage<T> = {
110
- object: "list";
111
- data: T[];
112
- hasMore: boolean;
113
- nextCursor: string | null;
114
- autoPagingToArray(options?: {
115
- limit?: number;
116
- }): Promise<T[]>;
117
- [Symbol.asyncIterator](): AsyncIterableIterator<T>;
118
- };
119
- type Action = {
120
- code: string;
121
- kind: string;
122
- method?: string | null;
123
- endpoint?: string | null;
124
- message: string;
125
- };
126
- type EmailOtpResponse = {
127
- ok: true;
128
- expiresIn: number;
129
- nextAction?: Action | null;
130
- };
131
- type SessionResponse = {
132
- object: "session";
133
- token: string;
134
- accountId: string;
135
- isNewAccount: boolean;
136
- expiresIn: number;
137
- };
138
- type ApiKeyResponse = {
139
- object: "api_key";
140
- id: string;
141
- keyLast4: string;
142
- label: string;
143
- createdAt: string;
144
- };
145
- type ApiKeyCreatedResponse = ApiKeyResponse & {
146
- key: string;
147
- accountId?: string | null;
148
- isNewAccount?: boolean;
149
- };
150
- type AccountResponse = {
151
- id: string;
152
- email: string;
153
- displayName: string | null;
154
- plan: string;
155
- status: string;
156
- createdAt: string;
157
- };
158
- type ListDropsParams = {
159
- cursor?: string | null;
160
- limit?: number;
161
- };
162
- type UploadManifestFile = {
163
- path: string;
164
- contentType: string;
165
- sizeBytes: number;
166
- checksumSha256?: string | null;
167
- };
168
- type CreateUploadSessionRequest = {
169
- schemaVersion?: 1;
170
- files: UploadManifestFile[];
171
- entry?: string | null;
172
- };
173
- type UploadTarget = {
174
- strategy: "single_put" | "multipart";
175
- url: string;
176
- headers: Record<string, string>;
177
- expiresAt: string;
178
- partSize?: number;
179
- partCount?: number;
180
- };
181
- type CreateUploadSessionFileResponse = {
182
- fileId: string;
183
- path: string;
184
- objectKey: string;
185
- upload: UploadTarget;
186
- };
187
- type UploadSessionFileResponse = {
188
- fileId: string;
189
- path: string;
190
- contentType: string;
191
- sizeBytes: number;
192
- objectKey: string;
193
- verified: boolean;
194
- };
195
- type UploadSessionResponse = {
196
- uploadId: string;
197
- status: string;
198
- expiresAt: string;
199
- entry?: string | null;
200
- files: UploadSessionFileResponse[];
201
- nextAction?: Action | null;
202
- };
203
- type CreateUploadSessionResponse = {
204
- uploadId: string;
205
- expiresAt: string;
206
- files: CreateUploadSessionFileResponse[];
207
- nextAction?: Action | null;
208
- };
209
- type CreateUploadPartTargetsRequest = {
210
- fileId: string;
211
- partNumbers: number[];
212
- };
213
- type UploadPartTarget = {
214
- partNumber: number;
215
- url: string;
216
- headers: Record<string, string>;
217
- expiresAt: string;
218
- };
219
- type CreateUploadPartTargetsResponse = {
220
- fileId: string;
221
- urlExpiresAt?: string | null;
222
- parts: UploadPartTarget[];
223
- };
224
- type CompleteUploadSessionRequest = {
225
- files?: Record<string, {
226
- parts?: Array<{
227
- partNumber: number;
228
- etag: string;
229
- }> | null;
230
- }>;
231
- };
232
- type DropOptions = {
233
- /** Change the vanity slug (update only). */
234
- slug?: string;
235
- /** Drop title. */
236
- title?: string;
237
- /** public (default) or unlisted. */
238
- visibility?: "public" | "unlisted";
239
- /** Require password to view. Pass `null` to remove password protection. */
240
- password?: string | null;
241
- /** Prevent search-engine indexing. Pass `null` to allow indexing (default). */
242
- noindex?: boolean | null;
243
- /** Auto-delete after this ISO 8601 date. Pass `null` to clear. */
244
- expiresAt?: string | Date | null;
245
- /** Entry file for multi-file bundles (default: index.html). */
246
- entry?: string;
247
- /** Attach JSON key-value pairs, e.g. `{ source: "ci" }`. */
248
- metadata?: Record<string, unknown>;
249
- };
250
- type PrepareOptions = {
251
- /** Glob patterns to ignore when publishing directories. */
252
- ignore?: string[];
253
- /** Disable default ignore patterns. */
254
- ignoreDefaults?: boolean;
255
- /** Override MIME type (auto-detected from extension). */
256
- contentType?: string;
257
- /** Set filename when publishing from stdin or bytes. */
258
- path?: string;
259
- };
260
- type RequestControls = {
261
- /** Prevent duplicate publishes on retry (auto-generated by CLI). */
262
- idempotencyKey?: string;
263
- /** Fail if current revision doesn't match -- optimistic lock (update only). */
264
- ifRevision?: number;
265
- };
266
- type PublishOptions = DropOptions & PrepareOptions & RequestControls;
267
- type ExplicitPublishInput = {
268
- content: string;
269
- contentType?: string;
270
- title?: string;
271
- visibility?: "public" | "unlisted";
272
- metadata?: Record<string, unknown>;
273
- entry?: string;
274
- } | {
275
- files: Array<{
276
- path: string;
277
- content?: string;
278
- contentBase64?: string;
279
- bytes?: Uint8Array;
280
- contentType: string;
281
- }>;
282
- title?: string;
283
- visibility?: "public" | "unlisted";
284
- metadata?: Record<string, unknown>;
285
- entry?: string;
286
- };
287
- type PublishInput = string | Uint8Array | ExplicitPublishInput;
1
+ import { e as CreateUploadSessionRequest, v as Transport, o as DropthisResult, E as EmailOtpResponse, S as SessionResponse, f as CreateUploadSessionResponse, y as UploadSessionResponse, c as CreateUploadPartTargetsRequest, d as CreateUploadPartTargetsResponse, C as CompleteUploadSessionRequest, m as DropthisClientOptions, b as ApiKeysResource, A as AccountResource, l as DropsResource, D as DeploymentsResource, s as PublishInput, t as PublishOptions, k as DropResponse, j as DropOptions, R as RequestControls, u as RequestOptions } from './drops-fK63OCk6.js';
2
+ export { a as ActionResolve, g as CursorPage, h as DropAction, i as DropDeploymentResponse, n as DropthisErrorResponse, L as Limitations, p as ListDeploymentsParams, q as ListDeploymentsResponse, r as ListPage, P as PrepareOptions, T as TierInfo, U as UploadManifestFile, w as UploadPartTarget, x as UploadSessionFileResponse, z as UploadTarget } from './drops-fK63OCk6.js';
288
3
 
289
4
  type PreparedUploadFile = {
290
5
  path: string;
@@ -305,50 +20,13 @@ type PreparedPublishRequest = {
305
20
  files: PreparedUploadFile[];
306
21
  options: Record<string, unknown>;
307
22
  metadata?: Record<string, unknown>;
23
+ } | {
24
+ kind: "source";
25
+ sourceUrl: string;
26
+ options: Record<string, unknown>;
27
+ metadata?: Record<string, unknown>;
308
28
  };
309
29
 
310
- declare class Transport {
311
- readonly apiKey: string | undefined;
312
- readonly baseUrl: string;
313
- readonly timeoutMs: number;
314
- readonly fetchImpl: typeof globalThis.fetch;
315
- constructor(options?: DropthisClientOptions | string);
316
- multipart<T>(method: string, path: string, form: FormData, options?: RequestOptions): Promise<DropthisResult<T>>;
317
- putSignedUrl(url: string, body: Uint8Array | Blob | ReadableStream, headers: Record<string, string>): Promise<DropthisResult<{
318
- etag: string | null;
319
- }>>;
320
- request<T>(method: string, path: string, options?: RequestOptions & {
321
- body?: unknown;
322
- bodyCase?: "snake" | "raw";
323
- params?: Record<string, string | number | boolean | null | undefined>;
324
- }): Promise<DropthisResult<T>>;
325
- }
326
-
327
- declare class AccountResource {
328
- private readonly transport;
329
- constructor(transport: Transport);
330
- get(): Promise<DropthisResult<AccountResponse>>;
331
- update(input: {
332
- displayName: string | null;
333
- }): Promise<DropthisResult<AccountResponse>>;
334
- delete(): Promise<DropthisResult<null>>;
335
- }
336
-
337
- declare class ApiKeysResource {
338
- private readonly transport;
339
- constructor(transport: Transport);
340
- list(): Promise<DropthisResult<{
341
- object: "list";
342
- data: ApiKeyResponse[];
343
- }>>;
344
- create(input: {
345
- label: string;
346
- }): Promise<DropthisResult<ApiKeyCreatedResponse>>;
347
- delete(keyId: string): Promise<DropthisResult<{
348
- ok: true;
349
- }>>;
350
- }
351
-
352
30
  declare class AuthResource {
353
31
  private readonly transport;
354
32
  constructor(transport: Transport);
@@ -364,54 +42,6 @@ declare class AuthResource {
364
42
  }>>;
365
43
  }
366
44
 
367
- declare class DeploymentsResource {
368
- private readonly transport;
369
- constructor(transport: Transport);
370
- create(dropId: string, body: Record<string, unknown>, options?: {
371
- idempotencyKey?: string;
372
- ifRevision?: number;
373
- }): Promise<DropthisResult<DropResponse>>;
374
- createRaw(dropId: string, body: unknown, options?: {
375
- idempotencyKey?: string;
376
- ifRevision?: number;
377
- }): Promise<DropthisResult<DropResponse>>;
378
- list(dropId: string, params?: ListDeploymentsParams): Promise<DropthisResult<ListDeploymentsResponse>>;
379
- get(dropId: string, deploymentId: string): Promise<DropthisResult<DropDeploymentResponse>>;
380
- }
381
-
382
- declare class CursorPage<T> implements ListPage<T> {
383
- readonly object: "list";
384
- readonly data: T[];
385
- readonly hasMore: boolean;
386
- readonly nextCursor: string | null;
387
- private readonly fetchNextPage;
388
- constructor(input: {
389
- data: T[];
390
- hasMore: boolean;
391
- nextCursor: string | null;
392
- fetchNextPage?: (() => Promise<DropthisResult<CursorPage<T>>>) | undefined;
393
- });
394
- autoPagingToArray(options?: {
395
- limit?: number;
396
- }): Promise<T[]>;
397
- [Symbol.asyncIterator](): AsyncIterableIterator<T>;
398
- }
399
-
400
- declare class DropsResource {
401
- private readonly transport;
402
- constructor(transport: Transport);
403
- create(body: unknown, options?: {
404
- idempotencyKey?: string;
405
- }): Promise<DropthisResult<DropResponse>>;
406
- createRaw(body: unknown, options?: {
407
- idempotencyKey?: string;
408
- }): Promise<DropthisResult<DropResponse>>;
409
- list(params?: ListDropsParams): Promise<DropthisResult<CursorPage<DropResponse>>>;
410
- get(dropId: string): Promise<DropthisResult<DropResponse>>;
411
- update(dropId: string, options?: DropOptions & RequestControls): Promise<DropthisResult<DropResponse>>;
412
- delete(dropId: string): Promise<DropthisResult<null>>;
413
- }
414
-
415
45
  declare class UploadsResource {
416
46
  private readonly transport;
417
47
  constructor(transport: Transport);
@@ -444,6 +74,7 @@ declare class Dropthis {
444
74
  prepare(input: PublishInput, options?: PublishOptions): Promise<PreparedPublishRequest>;
445
75
  publish(input: PublishInput, options?: PublishOptions): Promise<DropthisResult<DropResponse>>;
446
76
  deploy(dropId: string, input: PublishInput, options?: PublishOptions): Promise<DropthisResult<DropResponse>>;
77
+ private publishSource;
447
78
  update(dropId: string, options?: DropOptions & RequestControls): Promise<DropthisResult<DropResponse>>;
448
79
  request<T>(method: string, path: string, options?: RequestOptions & {
449
80
  body?: unknown;
@@ -466,4 +97,4 @@ declare function createErrorResult<T>(code: string, message: string, statusCode:
466
97
  retryable?: boolean | null;
467
98
  }): DropthisResult<T>;
468
99
 
469
- export { type ActionResolve, type CompleteUploadSessionRequest, type CreateUploadPartTargetsRequest, type CreateUploadPartTargetsResponse, type CreateUploadSessionRequest, type CreateUploadSessionResponse, CursorPage, DeploymentsResource, type DropAction, type DropDeploymentResponse, type DropOptions, type DropResponse, Dropthis, type DropthisClientOptions, type DropthisErrorResponse, type DropthisResult, type Limitations, type ListDeploymentsParams, type ListDeploymentsResponse, type ListPage, type PrepareOptions, type PreparedPublishRequest, type PreparedUploadFile, type PublishOptions, type RequestControls, type RequestOptions, type TierInfo, type UploadManifestFile, type UploadPartTarget, type UploadSessionFileResponse, type UploadSessionResponse, type UploadTarget, UploadsResource, createErrorResult, redactSecrets };
100
+ export { CompleteUploadSessionRequest, CreateUploadPartTargetsRequest, CreateUploadPartTargetsResponse, CreateUploadSessionRequest, CreateUploadSessionResponse, DeploymentsResource, DropOptions, DropResponse, Dropthis, DropthisClientOptions, DropthisResult, type PreparedPublishRequest, type PreparedUploadFile, PublishOptions, RequestControls, RequestOptions, UploadSessionResponse, UploadsResource, createErrorResult, redactSecrets };
@@ -1,3 +1,27 @@
1
+ // src/errors.ts
2
+ var API_KEY_RE = /sk_[A-Za-z0-9_-]+/g;
3
+ function redactSecrets(message) {
4
+ return message.replace(API_KEY_RE, "sk_[redacted]");
5
+ }
6
+ function createErrorResult(code, message, statusCode, extra = {}) {
7
+ return {
8
+ data: null,
9
+ error: {
10
+ code,
11
+ message: redactSecrets(message),
12
+ statusCode,
13
+ ...extra.type ? { type: extra.type } : {},
14
+ ...extra.detail !== void 0 ? { detail: extra.detail } : {},
15
+ ...extra.param !== void 0 ? { param: extra.param } : {},
16
+ ...extra.currentRevision !== void 0 ? { currentRevision: extra.currentRevision } : {},
17
+ ...extra.requestId !== void 0 ? { requestId: extra.requestId } : {},
18
+ ...extra.suggestion !== void 0 ? { suggestion: extra.suggestion } : {},
19
+ ...extra.retryable !== void 0 ? { retryable: extra.retryable } : {}
20
+ },
21
+ headers: extra.headers ?? {}
22
+ };
23
+ }
24
+
1
25
  // src/publish/prepare.ts
2
26
  import { stat as stat2 } from "fs/promises";
3
27
  import { basename as basename2 } from "path";
@@ -113,9 +137,7 @@ async function detectPathContentType(path) {
113
137
  var SINGLE_PUT_CHECKSUM_THRESHOLD_BYTES = 10 * 1024 * 1024;
114
138
  async function preparePublishRequest(input, options = {}) {
115
139
  if (input instanceof URL) {
116
- throw new Error(
117
- "URL inputs are not supported. Fetch the content first, then pass it as a string or file."
118
- );
140
+ return sourceRequest(input.toString(), options);
119
141
  }
120
142
  if (typeof input === "string") {
121
143
  const local = await localKind(input);
@@ -126,10 +148,7 @@ async function preparePublishRequest(input, options = {}) {
126
148
  return folderStaged(input, options);
127
149
  }
128
150
  const detection = detectStringInput(input);
129
- if (detection.mode === "sourceUrl")
130
- throw new Error(
131
- "URL inputs are not supported. Fetch the content first, then pass it as a string or file."
132
- );
151
+ if (detection.mode === "sourceUrl") return sourceRequest(input, options);
133
152
  return stringContent(input, options, detection.contentType);
134
153
  }
135
154
  if (input instanceof Uint8Array || Buffer.isBuffer(input)) {
@@ -230,6 +249,20 @@ async function stagedRequest(files, options) {
230
249
  if (options.metadata) prepared.metadata = options.metadata;
231
250
  return prepared;
232
251
  }
252
+ function sourceRequest(sourceUrl, options) {
253
+ if (!isHttpUrl(sourceUrl)) {
254
+ throw new Error(
255
+ "source_url must be an http(s) URL. Fetch the content first, then pass it as a string or file."
256
+ );
257
+ }
258
+ const prepared = {
259
+ kind: "source",
260
+ sourceUrl,
261
+ options: optionsBody(options)
262
+ };
263
+ if (options.metadata) prepared.metadata = options.metadata;
264
+ return prepared;
265
+ }
233
266
  async function explicitInput(input, options) {
234
267
  if ("content" in input)
235
268
  return stringContent(
@@ -238,12 +271,10 @@ async function explicitInput(input, options) {
238
271
  input.contentType ?? options.contentType ?? "text/html"
239
272
  );
240
273
  if ("sourceUrl" in input)
241
- throw new Error(
242
- "sourceUrl inputs are not supported. Fetch the content first, then pass it as a string or file."
243
- );
274
+ return sourceRequest(input.sourceUrl, { ...options, ...input });
244
275
  if ("sourceUrls" in input)
245
276
  throw new Error(
246
- "sourceUrls inputs are not supported. Fetch the content first, then pass it as a string or file."
277
+ "sourceUrls inputs are not supported in v1. Publish a single source_url, or fetch the content first."
247
278
  );
248
279
  return stagedRequest(
249
280
  input.files.map((file) => {
@@ -306,30 +337,6 @@ function optionsBody(options) {
306
337
  import { randomUUID } from "crypto";
307
338
  import { readFile as readFile2 } from "fs/promises";
308
339
 
309
- // src/errors.ts
310
- var API_KEY_RE = /sk_[A-Za-z0-9_-]+/g;
311
- function redactSecrets(message) {
312
- return message.replace(API_KEY_RE, "sk_[redacted]");
313
- }
314
- function createErrorResult(code, message, statusCode, extra = {}) {
315
- return {
316
- data: null,
317
- error: {
318
- code,
319
- message: redactSecrets(message),
320
- statusCode,
321
- ...extra.type ? { type: extra.type } : {},
322
- ...extra.detail !== void 0 ? { detail: extra.detail } : {},
323
- ...extra.param !== void 0 ? { param: extra.param } : {},
324
- ...extra.currentRevision !== void 0 ? { currentRevision: extra.currentRevision } : {},
325
- ...extra.requestId !== void 0 ? { requestId: extra.requestId } : {},
326
- ...extra.suggestion !== void 0 ? { suggestion: extra.suggestion } : {},
327
- ...extra.retryable !== void 0 ? { retryable: extra.retryable } : {}
328
- },
329
- headers: extra.headers ?? {}
330
- };
331
- }
332
-
333
340
  // src/publish/multipart.ts
334
341
  var MAX_PART_TARGETS_PER_REQUEST = 100;
335
342
  async function uploadMultipartFile(transport, uploadId, fileId, bytes, partSize) {
@@ -751,7 +758,7 @@ function toSnakeCase(value) {
751
758
 
752
759
  // src/transport.ts
753
760
  var DEFAULT_BASE_URL = "https://api.dropthis.app";
754
- var SDK_VERSION = "0.3.0";
761
+ var SDK_VERSION = "0.5.0";
755
762
  var Transport = class {
756
763
  apiKey;
757
764
  baseUrl;
@@ -759,7 +766,7 @@ var Transport = class {
759
766
  fetchImpl;
760
767
  constructor(options = {}) {
761
768
  const resolved = typeof options === "string" ? { apiKey: options } : options;
762
- this.apiKey = resolved.apiKey ?? process.env.DROPTHIS_API_KEY;
769
+ this.apiKey = resolved.apiKey ?? (typeof process !== "undefined" ? process.env?.DROPTHIS_API_KEY : void 0);
763
770
  this.baseUrl = (resolved.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
764
771
  this.timeoutMs = resolved.timeoutMs ?? 3e4;
765
772
  this.fetchImpl = resolved.fetch ?? globalThis.fetch;
@@ -958,13 +965,33 @@ var Dropthis = class {
958
965
  }
959
966
  async publish(input, options = {}) {
960
967
  const prepared = await preparePublishRequest(input, options);
968
+ if (prepared.kind === "source")
969
+ return this.publishSource(prepared, "/drops", options);
961
970
  return publishStaged(this.transport, prepared, "/drops", options);
962
971
  }
963
972
  async deploy(dropId, input, options = {}) {
964
973
  const prepared = await preparePublishRequest(input, options);
965
974
  const path = `/drops/${encodeURIComponent(dropId)}/deployments`;
975
+ if (prepared.kind === "source")
976
+ return createErrorResult(
977
+ "source_url_unsupported_for_deployment",
978
+ "Publishing a deployment from a source_url is not supported yet. Fetch the content first, then pass it as a string or file.",
979
+ null
980
+ );
966
981
  return publishStaged(this.transport, prepared, path, options);
967
982
  }
983
+ publishSource(prepared, path, options) {
984
+ const body = {
985
+ sourceUrl: prepared.sourceUrl,
986
+ options: prepared.options
987
+ };
988
+ if (prepared.metadata) body.metadata = prepared.metadata;
989
+ const baseKey = options.idempotencyKey ?? `sdk-${crypto.randomUUID()}`;
990
+ return this.transport.request("POST", path, {
991
+ body,
992
+ idempotencyKey: `${baseKey}:publish`
993
+ });
994
+ }
968
995
  async update(dropId, options = {}) {
969
996
  return this.drops.update(dropId, options);
970
997
  }