@dropthis/cli 0.20.0 → 0.22.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.
- package/README.md +55 -0
- package/dist/cli.cjs +211 -51
- package/dist/cli.cjs.map +1 -1
- package/node_modules/@dropthis/node/README.md +20 -2
- package/node_modules/@dropthis/node/dist/{drops-C92Gkuqx.d.cts → drops-DNwOp7g_.d.cts} +89 -5
- package/node_modules/@dropthis/node/dist/{drops-C92Gkuqx.d.ts → drops-DNwOp7g_.d.ts} +89 -5
- package/node_modules/@dropthis/node/dist/edge.cjs +88 -21
- package/node_modules/@dropthis/node/dist/edge.cjs.map +1 -1
- package/node_modules/@dropthis/node/dist/edge.d.cts +1 -1
- package/node_modules/@dropthis/node/dist/edge.d.ts +1 -1
- package/node_modules/@dropthis/node/dist/edge.mjs +88 -21
- package/node_modules/@dropthis/node/dist/edge.mjs.map +1 -1
- package/node_modules/@dropthis/node/dist/index.cjs +88 -21
- package/node_modules/@dropthis/node/dist/index.cjs.map +1 -1
- package/node_modules/@dropthis/node/dist/index.d.cts +2 -2
- package/node_modules/@dropthis/node/dist/index.d.ts +2 -2
- package/node_modules/@dropthis/node/dist/index.mjs +88 -21
- package/node_modules/@dropthis/node/dist/index.mjs.map +1 -1
- package/node_modules/@dropthis/node/package.json +1 -1
- package/package.json +49 -49
|
@@ -185,11 +185,13 @@ The `drops.publish()` and `drops.updateContent()` methods accept:
|
|
|
185
185
|
- **URL object** -- `new URL("https://example.com/page")` (source fetch)
|
|
186
186
|
- **Bytes** -- `new Uint8Array(...)` (raw bytes)
|
|
187
187
|
- **Explicit content** -- `{ kind: "content", content: "...", contentType?: "text/html", path?: "page.html" }`
|
|
188
|
-
- **Source URL** -- `{ kind: "source_url", sourceUrl: "https://example.com/page" }`
|
|
189
|
-
- **File bundle** -- `{ kind: "files", files: [{ path, content
|
|
188
|
+
- **Source URL** -- `{ kind: "source_url", sourceUrl: "https://example.com/page" }` (the server fetches it; an HTML page becomes a site, any other file becomes a single-file drop with a `rawUrl`)
|
|
189
|
+
- **File bundle** -- `{ kind: "files", files: [{ path, content? | contentBase64? | bytes? | sourceUrl?, contentType? }], entry? }`. Give each file its bytes inline (`content`/`contentBase64`/`bytes`) **or** a `sourceUrl` for the server to fetch — never both on one file. Mix them freely in one bundle.
|
|
190
190
|
|
|
191
191
|
Drop **settings** (title, visibility, password, noindex, expiresAt, metadata) go in the second `options` argument, not in the input object.
|
|
192
192
|
|
|
193
|
+
> **A `source_url` to a non-HTML file now becomes a single-file drop.** Point a top-level source URL (`new URL(...)` or `{ kind: "source_url" }`) at an image, PDF, or text file and you get a single-file `file_viewer` drop with `rawUrl` set — the same as publishing those bytes directly. Previously a source URL only worked for HTML pages.
|
|
194
|
+
|
|
193
195
|
All inputs are uploaded through staged presigned URLs — one signed PUT per file, up to 5 files in parallel. The SDK handles this transparently.
|
|
194
196
|
|
|
195
197
|
### Explicit input examples
|
|
@@ -220,6 +222,22 @@ await dropthis.drops.publish(
|
|
|
220
222
|
},
|
|
221
223
|
{ title: "My Site" },
|
|
222
224
|
);
|
|
225
|
+
|
|
226
|
+
// Publish by reference: inline your HTML, let the server fetch the images.
|
|
227
|
+
// Each `sourceUrl` file is fetched server-side (no bytes pass through your
|
|
228
|
+
// process) and lands at its path in the bundle — one self-contained drop.
|
|
229
|
+
await dropthis.drops.publish({
|
|
230
|
+
kind: "files",
|
|
231
|
+
files: [
|
|
232
|
+
{
|
|
233
|
+
path: "index.html",
|
|
234
|
+
content: '<h1>Gallery</h1><img src="hero.png"><img src="logo.svg">',
|
|
235
|
+
},
|
|
236
|
+
{ path: "hero.png", sourceUrl: "https://cdn.example.com/hero.png" },
|
|
237
|
+
{ path: "logo.svg", sourceUrl: "https://cdn.example.com/logo.svg" },
|
|
238
|
+
],
|
|
239
|
+
entry: "index.html",
|
|
240
|
+
});
|
|
223
241
|
```
|
|
224
242
|
|
|
225
243
|
## Prepare (validate without sending)
|
|
@@ -102,7 +102,6 @@ type DropDeploymentResponse = {
|
|
|
102
102
|
dropId: string;
|
|
103
103
|
revision: number;
|
|
104
104
|
status: string;
|
|
105
|
-
storagePrefix: string;
|
|
106
105
|
entry: string | null;
|
|
107
106
|
contentType: string;
|
|
108
107
|
renderMode: string;
|
|
@@ -204,11 +203,33 @@ type ListDropsParams = {
|
|
|
204
203
|
/** Only drops mounted on this custom domain hostname (e.g. "reports.example.com"). */
|
|
205
204
|
domain?: string;
|
|
206
205
|
};
|
|
206
|
+
/**
|
|
207
|
+
* One file in an upload manifest. A discriminated union:
|
|
208
|
+
*
|
|
209
|
+
* - **client-put** — the SDK pushes the bytes through a signed PUT. Requires
|
|
210
|
+
* `contentType` and `sizeBytes`; an optional `checksumSha256` locks the
|
|
211
|
+
* transfer integrity.
|
|
212
|
+
* - **remote** — the server fetches the bytes itself from `sourceUrl` during
|
|
213
|
+
* `POST /uploads/{id}/ingest`. No bytes leave this process, so `sizeBytes`,
|
|
214
|
+
* `contentType`, and `checksumSha256` are all optional (the server infers
|
|
215
|
+
* them on fetch). Carries NO signed PUT target.
|
|
216
|
+
*
|
|
217
|
+
* `sourceUrl` is the discriminant: present ⇒ remote, absent ⇒ client-put. The
|
|
218
|
+
* camelCase `sourceUrl` becomes the wire field `source_url` via the transport's
|
|
219
|
+
* snake_case conversion (exactly like `contentType` → `content_type`).
|
|
220
|
+
*/
|
|
207
221
|
type UploadManifestFile = {
|
|
208
222
|
path: string;
|
|
209
223
|
contentType: string;
|
|
210
224
|
sizeBytes: number;
|
|
211
225
|
checksumSha256?: string | null;
|
|
226
|
+
sourceUrl?: never;
|
|
227
|
+
} | {
|
|
228
|
+
path: string;
|
|
229
|
+
sourceUrl: string;
|
|
230
|
+
contentType?: string;
|
|
231
|
+
sizeBytes?: number;
|
|
232
|
+
checksumSha256?: string | null;
|
|
212
233
|
};
|
|
213
234
|
type CreateUploadSessionRequest = {
|
|
214
235
|
schemaVersion?: 1;
|
|
@@ -315,13 +336,61 @@ type PublishOptions = DropOptions & PrepareOptions & RequestControls;
|
|
|
315
336
|
type UpdateContentOptions = PrepareOptions & RequestControls & {
|
|
316
337
|
/** Entry file for multi-file bundles (default: index.html). */
|
|
317
338
|
entry?: string;
|
|
339
|
+
/**
|
|
340
|
+
* How the supplied files combine with what the drop already serves
|
|
341
|
+
* (partial-by-default, ADR 0065):
|
|
342
|
+
*
|
|
343
|
+
* - `"patch"` (default): the supplied files upsert by path and every
|
|
344
|
+
* unmentioned file is carried forward, so editing one file never drops the
|
|
345
|
+
* rest. Use `deletePaths` to remove files.
|
|
346
|
+
* - `"replace"`: the supplied files become the drop's entire content set —
|
|
347
|
+
* a full swap. Anything not supplied is gone. `deletePaths` is invalid here.
|
|
348
|
+
*
|
|
349
|
+
* Omit to default to `"patch"`.
|
|
350
|
+
*/
|
|
351
|
+
mode?: "patch" | "replace";
|
|
352
|
+
/**
|
|
353
|
+
* Paths to remove from the drop's content (patch-mode only). Each path must
|
|
354
|
+
* exist or the server rejects the update (loud, never a silent no-op). Invalid
|
|
355
|
+
* with `mode: "replace"`. Wire field: `delete_paths`.
|
|
356
|
+
*/
|
|
357
|
+
deletePaths?: string[];
|
|
318
358
|
};
|
|
359
|
+
/**
|
|
360
|
+
* One file in a multi-file `{ kind: "files" }` bundle. Supply the bytes inline
|
|
361
|
+
* exactly one way — `content` (UTF-8 text), `contentBase64`, or `bytes` — OR set
|
|
362
|
+
* `sourceUrl` to a public http(s) URL and let the server fetch that file for you
|
|
363
|
+
* server-side (no bytes pass through your process). A single entry may NOT carry
|
|
364
|
+
* both inline bytes and `sourceUrl`. Mix freely within one bundle: e.g. inline
|
|
365
|
+
* `content` for `index.html` plus a `sourceUrl` for each image referenced by it,
|
|
366
|
+
* yielding one self-contained drop.
|
|
367
|
+
*/
|
|
319
368
|
type PublishFileInput = {
|
|
320
369
|
path: string;
|
|
321
370
|
contentType?: string;
|
|
322
371
|
content?: string;
|
|
323
372
|
contentBase64?: string;
|
|
324
373
|
bytes?: Uint8Array;
|
|
374
|
+
/**
|
|
375
|
+
* Public http(s) URL the server fetches this file's bytes from during publish
|
|
376
|
+
* (publish by reference). Mutually exclusive with `content`/`contentBase64`/`bytes`.
|
|
377
|
+
*/
|
|
378
|
+
sourceUrl?: string;
|
|
379
|
+
/**
|
|
380
|
+
* Declared byte size of the remote file (optional hint for `sourceUrl` files).
|
|
381
|
+
* When provided, the server uses this for upfront quota admission before fetching,
|
|
382
|
+
* so a large file is rejected immediately rather than after the server downloads it.
|
|
383
|
+
* Ignored for inline files (size is computed from the bytes).
|
|
384
|
+
*/
|
|
385
|
+
sizeBytes?: number;
|
|
386
|
+
/**
|
|
387
|
+
* Expected SHA-256 hex digest of the remote file (optional hint for `sourceUrl` files).
|
|
388
|
+
* When provided, the server verifies the fetched content matches this checksum and
|
|
389
|
+
* rejects the publish if it does not, giving you integrity verification without
|
|
390
|
+
* downloading the bytes yourself.
|
|
391
|
+
* Ignored for inline files (checksum is computed by the SDK/server from actual bytes).
|
|
392
|
+
*/
|
|
393
|
+
checksumSha256?: string;
|
|
325
394
|
};
|
|
326
395
|
type PublishInput = string | string[] | URL | Uint8Array | {
|
|
327
396
|
kind: "content";
|
|
@@ -485,17 +554,32 @@ declare class Transport {
|
|
|
485
554
|
}
|
|
486
555
|
|
|
487
556
|
/**
|
|
488
|
-
* A file ready to be staged for upload.
|
|
489
|
-
*
|
|
490
|
-
*
|
|
491
|
-
*
|
|
557
|
+
* A file ready to be staged for upload. Two shapes:
|
|
558
|
+
*
|
|
559
|
+
* - **client-put** — the SDK pushes the bytes. The body is lazy: the orchestrator
|
|
560
|
+
* calls `getBody()` per file when it is ready to push bytes to the signed URL.
|
|
561
|
+
* This keeps the resolution layer pure and lets the filesystem layer (node.ts)
|
|
562
|
+
* defer reads/streams until upload time.
|
|
563
|
+
* - **remote** (`sourceUrl` set, no `getBody`) — the server fetches the bytes from
|
|
564
|
+
* `sourceUrl` during `POST /uploads/{id}/ingest`. No bytes leave this process, so
|
|
565
|
+
* it has no `getBody`, no `sizeBytes`, and consumes no signed PUT target.
|
|
492
566
|
*/
|
|
493
567
|
type PreparedUploadFile = {
|
|
494
568
|
path: string;
|
|
495
569
|
contentType: string;
|
|
496
570
|
sizeBytes: number;
|
|
497
571
|
checksumSha256?: string;
|
|
572
|
+
sourceUrl?: never;
|
|
498
573
|
getBody(): Promise<Uint8Array | Blob | ReadableStream>;
|
|
574
|
+
} | {
|
|
575
|
+
path: string;
|
|
576
|
+
sourceUrl: string;
|
|
577
|
+
contentType?: string;
|
|
578
|
+
/** Optional hint: declared byte size for upfront quota admission (server-side). */
|
|
579
|
+
sizeBytes?: number;
|
|
580
|
+
/** Optional hint: expected SHA-256 hex digest for server-side integrity check. */
|
|
581
|
+
checksumSha256?: string;
|
|
582
|
+
getBody?: never;
|
|
499
583
|
};
|
|
500
584
|
/**
|
|
501
585
|
* Resolves a publish input into a {@link PreparedPublishRequest}. Two implementations exist:
|
|
@@ -102,7 +102,6 @@ type DropDeploymentResponse = {
|
|
|
102
102
|
dropId: string;
|
|
103
103
|
revision: number;
|
|
104
104
|
status: string;
|
|
105
|
-
storagePrefix: string;
|
|
106
105
|
entry: string | null;
|
|
107
106
|
contentType: string;
|
|
108
107
|
renderMode: string;
|
|
@@ -204,11 +203,33 @@ type ListDropsParams = {
|
|
|
204
203
|
/** Only drops mounted on this custom domain hostname (e.g. "reports.example.com"). */
|
|
205
204
|
domain?: string;
|
|
206
205
|
};
|
|
206
|
+
/**
|
|
207
|
+
* One file in an upload manifest. A discriminated union:
|
|
208
|
+
*
|
|
209
|
+
* - **client-put** — the SDK pushes the bytes through a signed PUT. Requires
|
|
210
|
+
* `contentType` and `sizeBytes`; an optional `checksumSha256` locks the
|
|
211
|
+
* transfer integrity.
|
|
212
|
+
* - **remote** — the server fetches the bytes itself from `sourceUrl` during
|
|
213
|
+
* `POST /uploads/{id}/ingest`. No bytes leave this process, so `sizeBytes`,
|
|
214
|
+
* `contentType`, and `checksumSha256` are all optional (the server infers
|
|
215
|
+
* them on fetch). Carries NO signed PUT target.
|
|
216
|
+
*
|
|
217
|
+
* `sourceUrl` is the discriminant: present ⇒ remote, absent ⇒ client-put. The
|
|
218
|
+
* camelCase `sourceUrl` becomes the wire field `source_url` via the transport's
|
|
219
|
+
* snake_case conversion (exactly like `contentType` → `content_type`).
|
|
220
|
+
*/
|
|
207
221
|
type UploadManifestFile = {
|
|
208
222
|
path: string;
|
|
209
223
|
contentType: string;
|
|
210
224
|
sizeBytes: number;
|
|
211
225
|
checksumSha256?: string | null;
|
|
226
|
+
sourceUrl?: never;
|
|
227
|
+
} | {
|
|
228
|
+
path: string;
|
|
229
|
+
sourceUrl: string;
|
|
230
|
+
contentType?: string;
|
|
231
|
+
sizeBytes?: number;
|
|
232
|
+
checksumSha256?: string | null;
|
|
212
233
|
};
|
|
213
234
|
type CreateUploadSessionRequest = {
|
|
214
235
|
schemaVersion?: 1;
|
|
@@ -315,13 +336,61 @@ type PublishOptions = DropOptions & PrepareOptions & RequestControls;
|
|
|
315
336
|
type UpdateContentOptions = PrepareOptions & RequestControls & {
|
|
316
337
|
/** Entry file for multi-file bundles (default: index.html). */
|
|
317
338
|
entry?: string;
|
|
339
|
+
/**
|
|
340
|
+
* How the supplied files combine with what the drop already serves
|
|
341
|
+
* (partial-by-default, ADR 0065):
|
|
342
|
+
*
|
|
343
|
+
* - `"patch"` (default): the supplied files upsert by path and every
|
|
344
|
+
* unmentioned file is carried forward, so editing one file never drops the
|
|
345
|
+
* rest. Use `deletePaths` to remove files.
|
|
346
|
+
* - `"replace"`: the supplied files become the drop's entire content set —
|
|
347
|
+
* a full swap. Anything not supplied is gone. `deletePaths` is invalid here.
|
|
348
|
+
*
|
|
349
|
+
* Omit to default to `"patch"`.
|
|
350
|
+
*/
|
|
351
|
+
mode?: "patch" | "replace";
|
|
352
|
+
/**
|
|
353
|
+
* Paths to remove from the drop's content (patch-mode only). Each path must
|
|
354
|
+
* exist or the server rejects the update (loud, never a silent no-op). Invalid
|
|
355
|
+
* with `mode: "replace"`. Wire field: `delete_paths`.
|
|
356
|
+
*/
|
|
357
|
+
deletePaths?: string[];
|
|
318
358
|
};
|
|
359
|
+
/**
|
|
360
|
+
* One file in a multi-file `{ kind: "files" }` bundle. Supply the bytes inline
|
|
361
|
+
* exactly one way — `content` (UTF-8 text), `contentBase64`, or `bytes` — OR set
|
|
362
|
+
* `sourceUrl` to a public http(s) URL and let the server fetch that file for you
|
|
363
|
+
* server-side (no bytes pass through your process). A single entry may NOT carry
|
|
364
|
+
* both inline bytes and `sourceUrl`. Mix freely within one bundle: e.g. inline
|
|
365
|
+
* `content` for `index.html` plus a `sourceUrl` for each image referenced by it,
|
|
366
|
+
* yielding one self-contained drop.
|
|
367
|
+
*/
|
|
319
368
|
type PublishFileInput = {
|
|
320
369
|
path: string;
|
|
321
370
|
contentType?: string;
|
|
322
371
|
content?: string;
|
|
323
372
|
contentBase64?: string;
|
|
324
373
|
bytes?: Uint8Array;
|
|
374
|
+
/**
|
|
375
|
+
* Public http(s) URL the server fetches this file's bytes from during publish
|
|
376
|
+
* (publish by reference). Mutually exclusive with `content`/`contentBase64`/`bytes`.
|
|
377
|
+
*/
|
|
378
|
+
sourceUrl?: string;
|
|
379
|
+
/**
|
|
380
|
+
* Declared byte size of the remote file (optional hint for `sourceUrl` files).
|
|
381
|
+
* When provided, the server uses this for upfront quota admission before fetching,
|
|
382
|
+
* so a large file is rejected immediately rather than after the server downloads it.
|
|
383
|
+
* Ignored for inline files (size is computed from the bytes).
|
|
384
|
+
*/
|
|
385
|
+
sizeBytes?: number;
|
|
386
|
+
/**
|
|
387
|
+
* Expected SHA-256 hex digest of the remote file (optional hint for `sourceUrl` files).
|
|
388
|
+
* When provided, the server verifies the fetched content matches this checksum and
|
|
389
|
+
* rejects the publish if it does not, giving you integrity verification without
|
|
390
|
+
* downloading the bytes yourself.
|
|
391
|
+
* Ignored for inline files (checksum is computed by the SDK/server from actual bytes).
|
|
392
|
+
*/
|
|
393
|
+
checksumSha256?: string;
|
|
325
394
|
};
|
|
326
395
|
type PublishInput = string | string[] | URL | Uint8Array | {
|
|
327
396
|
kind: "content";
|
|
@@ -485,17 +554,32 @@ declare class Transport {
|
|
|
485
554
|
}
|
|
486
555
|
|
|
487
556
|
/**
|
|
488
|
-
* A file ready to be staged for upload.
|
|
489
|
-
*
|
|
490
|
-
*
|
|
491
|
-
*
|
|
557
|
+
* A file ready to be staged for upload. Two shapes:
|
|
558
|
+
*
|
|
559
|
+
* - **client-put** — the SDK pushes the bytes. The body is lazy: the orchestrator
|
|
560
|
+
* calls `getBody()` per file when it is ready to push bytes to the signed URL.
|
|
561
|
+
* This keeps the resolution layer pure and lets the filesystem layer (node.ts)
|
|
562
|
+
* defer reads/streams until upload time.
|
|
563
|
+
* - **remote** (`sourceUrl` set, no `getBody`) — the server fetches the bytes from
|
|
564
|
+
* `sourceUrl` during `POST /uploads/{id}/ingest`. No bytes leave this process, so
|
|
565
|
+
* it has no `getBody`, no `sizeBytes`, and consumes no signed PUT target.
|
|
492
566
|
*/
|
|
493
567
|
type PreparedUploadFile = {
|
|
494
568
|
path: string;
|
|
495
569
|
contentType: string;
|
|
496
570
|
sizeBytes: number;
|
|
497
571
|
checksumSha256?: string;
|
|
572
|
+
sourceUrl?: never;
|
|
498
573
|
getBody(): Promise<Uint8Array | Blob | ReadableStream>;
|
|
574
|
+
} | {
|
|
575
|
+
path: string;
|
|
576
|
+
sourceUrl: string;
|
|
577
|
+
contentType?: string;
|
|
578
|
+
/** Optional hint: declared byte size for upfront quota admission (server-side). */
|
|
579
|
+
sizeBytes?: number;
|
|
580
|
+
/** Optional hint: expected SHA-256 hex digest for server-side integrity check. */
|
|
581
|
+
checksumSha256?: string;
|
|
582
|
+
getBody?: never;
|
|
499
583
|
};
|
|
500
584
|
/**
|
|
501
585
|
* Resolves a publish input into a {@link PreparedPublishRequest}. Two implementations exist:
|
|
@@ -220,18 +220,34 @@ function updateContentOptions(options) {
|
|
|
220
220
|
if (options.idempotencyKey !== void 0)
|
|
221
221
|
out.idempotencyKey = options.idempotencyKey;
|
|
222
222
|
if (options.ifRevision !== void 0) out.ifRevision = options.ifRevision;
|
|
223
|
+
if (options.mode !== void 0) out.mode = options.mode;
|
|
224
|
+
if (options.deletePaths !== void 0) out.deletePaths = options.deletePaths;
|
|
223
225
|
return out;
|
|
224
226
|
}
|
|
225
227
|
function buildStagedRequest(files, options, entry) {
|
|
226
228
|
assertNonEmptyBundle(files.map((f) => f.path));
|
|
227
229
|
const normalizedPaths = files.map((f) => normalizeManifestPath(f.path));
|
|
228
230
|
assertNoDuplicatePaths(normalizedPaths);
|
|
229
|
-
const manifestFiles = files.map(
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
231
|
+
const manifestFiles = files.map(
|
|
232
|
+
(file) => file.sourceUrl !== void 0 ? (
|
|
233
|
+
// Remote entry: the server fetches the bytes on /ingest. Emit sourceUrl
|
|
234
|
+
// plus optional metadata hints (contentType, sizeBytes, checksumSha256)
|
|
235
|
+
// when the caller declared them. The transport snake_cases all camelCase
|
|
236
|
+
// keys to source_url / content_type / size_bytes / checksum_sha256.
|
|
237
|
+
{
|
|
238
|
+
path: normalizeManifestPath(file.path),
|
|
239
|
+
sourceUrl: file.sourceUrl,
|
|
240
|
+
...file.contentType ? { contentType: file.contentType } : {},
|
|
241
|
+
...file.sizeBytes !== void 0 ? { sizeBytes: file.sizeBytes } : {},
|
|
242
|
+
...file.checksumSha256 ? { checksumSha256: file.checksumSha256 } : {}
|
|
243
|
+
}
|
|
244
|
+
) : {
|
|
245
|
+
path: normalizeManifestPath(file.path),
|
|
246
|
+
contentType: file.contentType,
|
|
247
|
+
sizeBytes: file.sizeBytes,
|
|
248
|
+
...file.checksumSha256 ? { checksumSha256: file.checksumSha256 } : {}
|
|
249
|
+
}
|
|
250
|
+
);
|
|
235
251
|
const resolvedEntry = entry ?? options.entry;
|
|
236
252
|
if (resolvedEntry !== void 0) assertValidManifestPath(resolvedEntry);
|
|
237
253
|
const manifest = {
|
|
@@ -277,9 +293,48 @@ function fileBytes(file) {
|
|
|
277
293
|
"missing_file_bytes",
|
|
278
294
|
`File "${file.path}" is missing content bytes.`,
|
|
279
295
|
file.path,
|
|
280
|
-
"Provide one of content, contentBase64, or bytes."
|
|
296
|
+
"Provide one of content, contentBase64, or bytes, or set sourceUrl."
|
|
281
297
|
);
|
|
282
298
|
}
|
|
299
|
+
function hasInlineBytes(file) {
|
|
300
|
+
return file.content !== void 0 || file.contentBase64 !== void 0 || file.bytes !== void 0;
|
|
301
|
+
}
|
|
302
|
+
function prepareBundleFile(file) {
|
|
303
|
+
assertValidManifestPath(file.path);
|
|
304
|
+
if (file.sourceUrl !== void 0) {
|
|
305
|
+
if (hasInlineBytes(file)) {
|
|
306
|
+
throw new PublishInputError(
|
|
307
|
+
"conflicting_file_source",
|
|
308
|
+
`File "${file.path}" sets both inline content and sourceUrl; pick one.`,
|
|
309
|
+
file.path,
|
|
310
|
+
"Drop sourceUrl to upload bytes, or drop content/contentBase64/bytes to fetch by reference."
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
if (!isHttpUrl(file.sourceUrl)) {
|
|
314
|
+
throw new PublishInputError(
|
|
315
|
+
"invalid_source_url",
|
|
316
|
+
`File "${file.path}" sourceUrl must be an http(s) URL.`,
|
|
317
|
+
file.path,
|
|
318
|
+
"Fetch the bytes first and pass them inline, or use an http(s) URL."
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
return {
|
|
322
|
+
path: file.path,
|
|
323
|
+
sourceUrl: file.sourceUrl,
|
|
324
|
+
...file.contentType ? { contentType: file.contentType } : {},
|
|
325
|
+
...file.sizeBytes !== void 0 ? { sizeBytes: file.sizeBytes } : {},
|
|
326
|
+
...file.checksumSha256 ? { checksumSha256: file.checksumSha256 } : {}
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
const bytes = fileBytes(file);
|
|
330
|
+
const contentType = file.contentType ?? detectBytesContentType(bytes);
|
|
331
|
+
return {
|
|
332
|
+
path: file.path,
|
|
333
|
+
contentType,
|
|
334
|
+
sizeBytes: bytes.byteLength,
|
|
335
|
+
getBody: async () => bytes
|
|
336
|
+
};
|
|
337
|
+
}
|
|
283
338
|
function singleStagedFile(path, contentType, bytes, options) {
|
|
284
339
|
return buildStagedRequest(
|
|
285
340
|
[
|
|
@@ -322,20 +377,17 @@ async function resolveInMemory(input, options = {}) {
|
|
|
322
377
|
if (input.kind === "source_url") {
|
|
323
378
|
return buildSourceRequest(input.sourceUrl, options);
|
|
324
379
|
}
|
|
325
|
-
const files = input.files.map(
|
|
326
|
-
assertValidManifestPath(file.path);
|
|
327
|
-
const bytes = fileBytes(file);
|
|
328
|
-
const contentType = file.contentType ?? detectBytesContentType(bytes);
|
|
329
|
-
return {
|
|
330
|
-
path: file.path,
|
|
331
|
-
contentType,
|
|
332
|
-
sizeBytes: bytes.byteLength,
|
|
333
|
-
getBody: async () => bytes
|
|
334
|
-
};
|
|
335
|
-
});
|
|
380
|
+
const files = input.files.map(prepareBundleFile);
|
|
336
381
|
return buildStagedRequest(files, options, input.entry);
|
|
337
382
|
}
|
|
383
|
+
function partialUpdateBody(options) {
|
|
384
|
+
return {
|
|
385
|
+
...options.mode !== void 0 ? { mode: options.mode } : {},
|
|
386
|
+
...options.deletePaths !== void 0 ? { deletePaths: options.deletePaths } : {}
|
|
387
|
+
};
|
|
388
|
+
}
|
|
338
389
|
var UPLOAD_CONCURRENCY = 5;
|
|
390
|
+
var INGEST_TIMEOUT_MS = 12e4;
|
|
339
391
|
function errorResult(result) {
|
|
340
392
|
if (!result.error) throw new Error("Expected an error result");
|
|
341
393
|
return { data: null, error: result.error, headers: result.headers };
|
|
@@ -391,6 +443,7 @@ async function publishStaged(transport, prepared, finalPath, options = {}) {
|
|
|
391
443
|
if (createResult.error) return errorResult(createResult);
|
|
392
444
|
const jobs = [];
|
|
393
445
|
for (const file of prepared.files) {
|
|
446
|
+
if (file.sourceUrl !== void 0) continue;
|
|
394
447
|
const target = createResult.data.files.find((f) => f.path === file.path);
|
|
395
448
|
if (!target) {
|
|
396
449
|
return createErrorResult(
|
|
@@ -410,6 +463,18 @@ async function publishStaged(transport, prepared, finalPath, options = {}) {
|
|
|
410
463
|
}
|
|
411
464
|
const uploadFailure = await uploadStagedFiles(transport, jobs);
|
|
412
465
|
if (uploadFailure) return uploadFailure;
|
|
466
|
+
const hasRemote = prepared.files.some((f) => f.sourceUrl !== void 0);
|
|
467
|
+
if (hasRemote) {
|
|
468
|
+
const ingestResult = await transport.request(
|
|
469
|
+
"POST",
|
|
470
|
+
`/uploads/${encodeURIComponent(createResult.data.uploadId)}/ingest`,
|
|
471
|
+
{
|
|
472
|
+
idempotencyKey: `${baseKey}:ingest-upload`,
|
|
473
|
+
timeoutMs: INGEST_TIMEOUT_MS
|
|
474
|
+
}
|
|
475
|
+
);
|
|
476
|
+
if (ingestResult.error) return errorResult(ingestResult);
|
|
477
|
+
}
|
|
413
478
|
const completeResult = await transport.request(
|
|
414
479
|
"POST",
|
|
415
480
|
`/uploads/${encodeURIComponent(createResult.data.uploadId)}/complete`,
|
|
@@ -422,7 +487,8 @@ async function publishStaged(transport, prepared, finalPath, options = {}) {
|
|
|
422
487
|
body: {
|
|
423
488
|
uploadId: createResult.data.uploadId,
|
|
424
489
|
...Object.keys(prepared.options).length > 0 ? { options: prepared.options } : {},
|
|
425
|
-
...prepared.metadata ? { metadata: prepared.metadata } : {}
|
|
490
|
+
...prepared.metadata ? { metadata: prepared.metadata } : {},
|
|
491
|
+
...partialUpdateBody(options)
|
|
426
492
|
},
|
|
427
493
|
idempotencyKey: `${baseKey}:publish`
|
|
428
494
|
};
|
|
@@ -436,7 +502,8 @@ async function publishSource(transport, prepared, finalPath, options = {}) {
|
|
|
436
502
|
body: {
|
|
437
503
|
sourceUrl: prepared.sourceUrl,
|
|
438
504
|
...Object.keys(prepared.options).length > 0 ? { options: prepared.options } : {},
|
|
439
|
-
...prepared.metadata ? { metadata: prepared.metadata } : {}
|
|
505
|
+
...prepared.metadata ? { metadata: prepared.metadata } : {},
|
|
506
|
+
...partialUpdateBody(options)
|
|
440
507
|
},
|
|
441
508
|
idempotencyKey: `${baseKey}:publish`,
|
|
442
509
|
...options.ifRevision !== void 0 ? { ifRevision: options.ifRevision } : {}
|
|
@@ -804,7 +871,7 @@ function toSnakeCase(value) {
|
|
|
804
871
|
|
|
805
872
|
// src/transport.ts
|
|
806
873
|
var DEFAULT_BASE_URL = "https://api.dropthis.app";
|
|
807
|
-
var SDK_VERSION = "0.
|
|
874
|
+
var SDK_VERSION = "0.20.0";
|
|
808
875
|
var Transport = class {
|
|
809
876
|
apiKey;
|
|
810
877
|
baseUrl;
|