gazetta 0.6.0 → 0.7.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/admin-dist/assets/index-BO9-CXmW.css +1 -0
- package/admin-dist/assets/index-Ufu8zZH_.js +668 -0
- package/admin-dist/index.html +2 -2
- package/dist/admin-api/error-response.d.ts +21 -0
- package/dist/admin-api/error-response.d.ts.map +1 -0
- package/dist/admin-api/error-response.js +12 -0
- package/dist/admin-api/error-response.js.map +1 -0
- package/dist/admin-api/index.d.ts +0 -2
- package/dist/admin-api/index.d.ts.map +1 -1
- package/dist/admin-api/index.js +4 -24
- package/dist/admin-api/index.js.map +1 -1
- package/dist/admin-api/routes/assets.d.ts +16 -0
- package/dist/admin-api/routes/assets.d.ts.map +1 -0
- package/dist/admin-api/routes/assets.js +433 -0
- package/dist/admin-api/routes/assets.js.map +1 -0
- package/dist/admin-api/routes/fragments.d.ts.map +1 -1
- package/dist/admin-api/routes/fragments.js +30 -4
- package/dist/admin-api/routes/fragments.js.map +1 -1
- package/dist/admin-api/routes/pages.d.ts.map +1 -1
- package/dist/admin-api/routes/pages.js +37 -4
- package/dist/admin-api/routes/pages.js.map +1 -1
- package/dist/admin-api/routes/publish.d.ts.map +1 -1
- package/dist/admin-api/routes/publish.js +68 -35
- package/dist/admin-api/routes/publish.js.map +1 -1
- package/dist/admin-api/schemas/assets.d.ts +48 -0
- package/dist/admin-api/schemas/assets.d.ts.map +1 -0
- package/dist/admin-api/schemas/assets.js +44 -0
- package/dist/admin-api/schemas/assets.js.map +1 -0
- package/dist/admin-api/schemas/index.d.ts +2 -0
- package/dist/admin-api/schemas/index.d.ts.map +1 -1
- package/dist/admin-api/schemas/index.js +2 -0
- package/dist/admin-api/schemas/index.js.map +1 -1
- package/dist/admin-api/source-context.d.ts +0 -7
- package/dist/admin-api/source-context.d.ts.map +1 -1
- package/dist/admin-api/source-context.js +0 -3
- package/dist/admin-api/source-context.js.map +1 -1
- package/dist/assets/analyze-audio.d.ts +3 -0
- package/dist/assets/analyze-audio.d.ts.map +1 -0
- package/dist/assets/analyze-audio.js +80 -0
- package/dist/assets/analyze-audio.js.map +1 -0
- package/dist/assets/analyze-image.d.ts +19 -0
- package/dist/assets/analyze-image.d.ts.map +1 -0
- package/dist/assets/analyze-image.js +123 -0
- package/dist/assets/analyze-image.js.map +1 -0
- package/dist/assets/analyze.d.ts +94 -0
- package/dist/assets/analyze.d.ts.map +1 -0
- package/dist/assets/analyze.js +45 -0
- package/dist/assets/analyze.js.map +1 -0
- package/dist/assets/asset-deps.d.ts +30 -0
- package/dist/assets/asset-deps.d.ts.map +1 -0
- package/dist/assets/asset-deps.js +42 -0
- package/dist/assets/asset-deps.js.map +1 -0
- package/dist/assets/asset-paths.d.ts +155 -0
- package/dist/assets/asset-paths.d.ts.map +1 -0
- package/dist/assets/asset-paths.js +197 -0
- package/dist/assets/asset-paths.js.map +1 -0
- package/dist/assets/delete.d.ts +75 -0
- package/dist/assets/delete.d.ts.map +1 -0
- package/dist/assets/delete.js +82 -0
- package/dist/assets/delete.js.map +1 -0
- package/dist/assets/errors.d.ts +241 -0
- package/dist/assets/errors.d.ts.map +1 -0
- package/dist/assets/errors.js +300 -0
- package/dist/assets/errors.js.map +1 -0
- package/dist/assets/find-refs.d.ts +37 -0
- package/dist/assets/find-refs.d.ts.map +1 -0
- package/dist/assets/find-refs.js +35 -0
- package/dist/assets/find-refs.js.map +1 -0
- package/dist/assets/hash.d.ts +13 -0
- package/dist/assets/hash.d.ts.map +1 -0
- package/dist/assets/hash.js +43 -0
- package/dist/assets/hash.js.map +1 -0
- package/dist/assets/image-metadata.d.ts +11 -0
- package/dist/assets/image-metadata.d.ts.map +1 -0
- package/dist/assets/image-metadata.js +31 -0
- package/dist/assets/image-metadata.js.map +1 -0
- package/dist/assets/ingest-locale.d.ts +86 -0
- package/dist/assets/ingest-locale.d.ts.map +1 -0
- package/dist/assets/ingest-locale.js +209 -0
- package/dist/assets/ingest-locale.js.map +1 -0
- package/dist/assets/ingest.d.ts +96 -0
- package/dist/assets/ingest.d.ts.map +1 -0
- package/dist/assets/ingest.js +308 -0
- package/dist/assets/ingest.js.map +1 -0
- package/dist/assets/kind-compat.d.ts +34 -0
- package/dist/assets/kind-compat.d.ts.map +1 -0
- package/dist/assets/kind-compat.js +33 -0
- package/dist/assets/kind-compat.js.map +1 -0
- package/dist/assets/list.d.ts +46 -0
- package/dist/assets/list.d.ts.map +1 -0
- package/dist/assets/list.js +102 -0
- package/dist/assets/list.js.map +1 -0
- package/dist/assets/manifest-default.d.ts +56 -0
- package/dist/assets/manifest-default.d.ts.map +1 -0
- package/dist/assets/manifest-default.js +120 -0
- package/dist/assets/manifest-default.js.map +1 -0
- package/dist/assets/manifest-filename.d.ts +52 -0
- package/dist/assets/manifest-filename.d.ts.map +1 -0
- package/dist/assets/manifest-filename.js +104 -0
- package/dist/assets/manifest-filename.js.map +1 -0
- package/dist/assets/manifest-locale.d.ts +60 -0
- package/dist/assets/manifest-locale.d.ts.map +1 -0
- package/dist/assets/manifest-locale.js +206 -0
- package/dist/assets/manifest-locale.js.map +1 -0
- package/dist/assets/manifest-merge.d.ts +66 -0
- package/dist/assets/manifest-merge.d.ts.map +1 -0
- package/dist/assets/manifest-merge.js +82 -0
- package/dist/assets/manifest-merge.js.map +1 -0
- package/dist/assets/manifest.d.ts +83 -0
- package/dist/assets/manifest.d.ts.map +1 -0
- package/dist/assets/manifest.js +93 -0
- package/dist/assets/manifest.js.map +1 -0
- package/dist/assets/mime-sniff.d.ts +18 -0
- package/dist/assets/mime-sniff.d.ts.map +1 -0
- package/dist/assets/mime-sniff.js +84 -0
- package/dist/assets/mime-sniff.js.map +1 -0
- package/dist/assets/preprocess-svg.d.ts +3 -0
- package/dist/assets/preprocess-svg.d.ts.map +1 -0
- package/dist/assets/preprocess-svg.js +49 -0
- package/dist/assets/preprocess-svg.js.map +1 -0
- package/dist/assets/preprocess.d.ts +62 -0
- package/dist/assets/preprocess.d.ts.map +1 -0
- package/dist/assets/preprocess.js +86 -0
- package/dist/assets/preprocess.js.map +1 -0
- package/dist/assets/publish-plan.d.ts +41 -0
- package/dist/assets/publish-plan.d.ts.map +1 -0
- package/dist/assets/publish-plan.js +49 -0
- package/dist/assets/publish-plan.js.map +1 -0
- package/dist/assets/publish.d.ts +33 -0
- package/dist/assets/publish.d.ts.map +1 -0
- package/dist/assets/publish.js +81 -0
- package/dist/assets/publish.js.map +1 -0
- package/dist/assets/refs.d.ts +37 -0
- package/dist/assets/refs.d.ts.map +1 -0
- package/dist/assets/refs.js +33 -0
- package/dist/assets/refs.js.map +1 -0
- package/dist/assets/remove-override.d.ts +42 -0
- package/dist/assets/remove-override.d.ts.map +1 -0
- package/dist/assets/remove-override.js +53 -0
- package/dist/assets/remove-override.js.map +1 -0
- package/dist/assets/rename.d.ts +43 -0
- package/dist/assets/rename.d.ts.map +1 -0
- package/dist/assets/rename.js +271 -0
- package/dist/assets/rename.js.map +1 -0
- package/dist/assets/replace.d.ts +37 -0
- package/dist/assets/replace.d.ts.map +1 -0
- package/dist/assets/replace.js +195 -0
- package/dist/assets/replace.js.map +1 -0
- package/dist/assets/resolve.d.ts +141 -0
- package/dist/assets/resolve.d.ts.map +1 -0
- package/dist/assets/resolve.js +381 -0
- package/dist/assets/resolve.js.map +1 -0
- package/dist/assets/rewrite-manifest-asset-ref.d.ts +44 -0
- package/dist/assets/rewrite-manifest-asset-ref.d.ts.map +1 -0
- package/dist/assets/rewrite-manifest-asset-ref.js +51 -0
- package/dist/assets/rewrite-manifest-asset-ref.js.map +1 -0
- package/dist/assets/scan-manifest-for-asset.d.ts +63 -0
- package/dist/assets/scan-manifest-for-asset.d.ts.map +1 -0
- package/dist/assets/scan-manifest-for-asset.js +105 -0
- package/dist/assets/scan-manifest-for-asset.js.map +1 -0
- package/dist/assets/serve-route.d.ts +45 -0
- package/dist/assets/serve-route.d.ts.map +1 -0
- package/dist/assets/serve-route.js +123 -0
- package/dist/assets/serve-route.js.map +1 -0
- package/dist/assets/svg-sanitize.d.ts +38 -0
- package/dist/assets/svg-sanitize.d.ts.map +1 -0
- package/dist/assets/svg-sanitize.js +209 -0
- package/dist/assets/svg-sanitize.js.map +1 -0
- package/dist/assets/update-metadata.d.ts +61 -0
- package/dist/assets/update-metadata.d.ts.map +1 -0
- package/dist/assets/update-metadata.js +82 -0
- package/dist/assets/update-metadata.js.map +1 -0
- package/dist/assets/url.d.ts +82 -0
- package/dist/assets/url.d.ts.map +1 -0
- package/dist/assets/url.js +103 -0
- package/dist/assets/url.js.map +1 -0
- package/dist/assets/validate.d.ts +74 -0
- package/dist/assets/validate.d.ts.map +1 -0
- package/dist/assets/validate.js +136 -0
- package/dist/assets/validate.js.map +1 -0
- package/dist/assets/variants.d.ts +23 -0
- package/dist/assets/variants.d.ts.map +1 -0
- package/dist/assets/variants.js +74 -0
- package/dist/assets/variants.js.map +1 -0
- package/dist/cli/assets-cli.d.ts +58 -0
- package/dist/cli/assets-cli.d.ts.map +1 -0
- package/dist/cli/assets-cli.js +233 -0
- package/dist/cli/assets-cli.js.map +1 -0
- package/dist/cli/assets-display.d.ts +112 -0
- package/dist/cli/assets-display.d.ts.map +1 -0
- package/dist/cli/assets-display.js +106 -0
- package/dist/cli/assets-display.js.map +1 -0
- package/dist/cli/bootstrap.d.ts +0 -2
- package/dist/cli/bootstrap.d.ts.map +1 -1
- package/dist/cli/bootstrap.js +0 -1
- package/dist/cli/bootstrap.js.map +1 -1
- package/dist/cli/index.js +64 -18
- package/dist/cli/index.js.map +1 -1
- package/dist/compare.d.ts.map +1 -1
- package/dist/compare.js +15 -12
- package/dist/compare.js.map +1 -1
- package/dist/dep-sidecars.d.ts +127 -0
- package/dist/dep-sidecars.d.ts.map +1 -0
- package/dist/dep-sidecars.js +122 -0
- package/dist/dep-sidecars.js.map +1 -0
- package/dist/editor/AssetEmbeddedWidget.d.ts +3 -0
- package/dist/editor/AssetEmbeddedWidget.d.ts.map +1 -0
- package/dist/editor/AssetEmbeddedWidget.js +146 -0
- package/dist/editor/AssetEmbeddedWidget.js.map +1 -0
- package/dist/editor/mount.d.ts +12 -1
- package/dist/editor/mount.d.ts.map +1 -1
- package/dist/editor/mount.js +36 -5
- package/dist/editor/mount.js.map +1 -1
- package/dist/format.d.ts +44 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +65 -0
- package/dist/format.js.map +1 -0
- package/dist/fragment-deps.d.ts +24 -0
- package/dist/fragment-deps.d.ts.map +1 -0
- package/dist/fragment-deps.js +20 -0
- package/dist/fragment-deps.js.map +1 -0
- package/dist/hash.d.ts +0 -6
- package/dist/hash.d.ts.map +1 -1
- package/dist/hash.js +0 -18
- package/dist/hash.js.map +1 -1
- package/dist/history-provider.d.ts.map +1 -1
- package/dist/history-provider.js +30 -8
- package/dist/history-provider.js.map +1 -1
- package/dist/history-recorder.d.ts +7 -3
- package/dist/history-recorder.d.ts.map +1 -1
- package/dist/history-recorder.js +9 -1
- package/dist/history-recorder.js.map +1 -1
- package/dist/history-restorer.d.ts.map +1 -1
- package/dist/history-restorer.js +34 -2
- package/dist/history-restorer.js.map +1 -1
- package/dist/history.d.ts +26 -8
- package/dist/history.d.ts.map +1 -1
- package/dist/index.d.ts +2 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -2
- package/dist/index.js.map +1 -1
- package/dist/locale.d.ts +20 -0
- package/dist/locale.d.ts.map +1 -1
- package/dist/locale.js +38 -0
- package/dist/locale.js.map +1 -1
- package/dist/providers/_atomic-write.d.ts +9 -0
- package/dist/providers/_atomic-write.d.ts.map +1 -0
- package/dist/providers/_atomic-write.js +72 -0
- package/dist/providers/_atomic-write.js.map +1 -0
- package/dist/providers/_rm-ignore-missing.d.ts +31 -0
- package/dist/providers/_rm-ignore-missing.d.ts.map +1 -0
- package/dist/providers/_rm-ignore-missing.js +12 -0
- package/dist/providers/_rm-ignore-missing.js.map +1 -0
- package/dist/providers/_stream-interop.d.ts +23 -0
- package/dist/providers/_stream-interop.d.ts.map +1 -0
- package/dist/providers/_stream-interop.js +21 -0
- package/dist/providers/_stream-interop.js.map +1 -0
- package/dist/providers/azure-blob.d.ts.map +1 -1
- package/dist/providers/azure-blob.js +60 -0
- package/dist/providers/azure-blob.js.map +1 -1
- package/dist/providers/filesystem.d.ts +4 -0
- package/dist/providers/filesystem.d.ts.map +1 -1
- package/dist/providers/filesystem.js +63 -2
- package/dist/providers/filesystem.js.map +1 -1
- package/dist/providers/s3.d.ts.map +1 -1
- package/dist/providers/s3.js +84 -1
- package/dist/providers/s3.js.map +1 -1
- package/dist/publish-rendered.d.ts +37 -17
- package/dist/publish-rendered.d.ts.map +1 -1
- package/dist/publish-rendered.js +71 -67
- package/dist/publish-rendered.js.map +1 -1
- package/dist/publish.d.ts +13 -12
- package/dist/publish.d.ts.map +1 -1
- package/dist/publish.js +23 -47
- package/dist/publish.js.map +1 -1
- package/dist/resolver.d.ts +12 -2
- package/dist/resolver.d.ts.map +1 -1
- package/dist/resolver.js +54 -9
- package/dist/resolver.js.map +1 -1
- package/dist/schema/dimensions.d.ts +78 -0
- package/dist/schema/dimensions.d.ts.map +1 -0
- package/dist/schema/dimensions.js +97 -0
- package/dist/schema/dimensions.js.map +1 -0
- package/dist/schema/helpers.d.ts +108 -0
- package/dist/schema/helpers.d.ts.map +1 -0
- package/dist/schema/helpers.js +133 -0
- package/dist/schema/helpers.js.map +1 -0
- package/dist/schema/index.d.ts +27 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +25 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/types.d.ts +390 -0
- package/dist/schema/types.d.ts.map +1 -0
- package/dist/schema/types.js +25 -0
- package/dist/schema/types.js.map +1 -0
- package/dist/selector-chain.d.ts +63 -0
- package/dist/selector-chain.d.ts.map +1 -0
- package/dist/selector-chain.js +58 -0
- package/dist/selector-chain.js.map +1 -0
- package/dist/sidecars.d.ts +19 -18
- package/dist/sidecars.d.ts.map +1 -1
- package/dist/sidecars.js +70 -62
- package/dist/sidecars.js.map +1 -1
- package/dist/targets.d.ts.map +1 -1
- package/dist/targets.js +15 -37
- package/dist/targets.js.map +1 -1
- package/dist/themes.d.ts +69 -0
- package/dist/themes.d.ts.map +1 -0
- package/dist/themes.js +85 -0
- package/dist/themes.js.map +1 -0
- package/dist/transforms/adapter.d.ts +115 -0
- package/dist/transforms/adapter.d.ts.map +1 -0
- package/dist/transforms/adapter.js +2 -0
- package/dist/transforms/adapter.js.map +1 -0
- package/dist/transforms/cloudflare.d.ts +17 -0
- package/dist/transforms/cloudflare.d.ts.map +1 -0
- package/dist/transforms/cloudflare.js +110 -0
- package/dist/transforms/cloudflare.js.map +1 -0
- package/dist/transforms/index.d.ts +24 -0
- package/dist/transforms/index.d.ts.map +1 -0
- package/dist/transforms/index.js +30 -0
- package/dist/transforms/index.js.map +1 -0
- package/dist/transforms/sharp.d.ts +3 -0
- package/dist/transforms/sharp.d.ts.map +1 -0
- package/dist/transforms/sharp.js +43 -0
- package/dist/transforms/sharp.js.map +1 -0
- package/dist/types.d.ts +125 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +20 -1
- package/admin-dist/assets/index-B6pVot0Y.css +0 -1
- package/admin-dist/assets/index-DniLwxJA.js +0 -609
- package/dist/providers/r2.d.ts +0 -8
- package/dist/providers/r2.d.ts.map +0 -1
- package/dist/providers/r2.js +0 -86
- package/dist/providers/r2.js.map +0 -1
- package/dist/source-sidecars.d.ts +0 -32
- package/dist/source-sidecars.d.ts.map +0 -1
- package/dist/source-sidecars.js +0 -98
- package/dist/source-sidecars.js.map +0 -1
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed errors for the asset domain.
|
|
3
|
+
*
|
|
4
|
+
* Every asset-domain failure is one of these classes — never a plain
|
|
5
|
+
* `new Error('not implemented')`. Callers pattern-match on the class to
|
|
6
|
+
* decide what to do (HTTP status, CLI exit code, retry policy, user
|
|
7
|
+
* message). Subclassing keeps the public error taxonomy small and stable.
|
|
8
|
+
*
|
|
9
|
+
* The `code` property is the machine-readable identifier. Messages are
|
|
10
|
+
* human-readable and may include path/name details; tests should match
|
|
11
|
+
* on `code`, not on message text.
|
|
12
|
+
*/
|
|
13
|
+
export type AssetErrorCode = 'ASSET_VALIDATION_FAILED' | 'ASSET_MIME_MISMATCH' | 'ASSET_SIZE_EXCEEDED' | 'ASSET_NAME_INVALID' | 'ASSET_NAME_RESERVED' | 'ASSET_PATH_TRAVERSAL' | 'ASSET_STORAGE_FAILURE' | 'ASSET_MANIFEST_CORRUPT' | 'ASSET_MANIFEST_NOT_FOUND' | 'ASSET_IN_USE' | 'ASSET_MIME_UNSUPPORTED' | 'ASSET_KIND_MISMATCH' | 'ASSET_NAME_COLLISION' | 'ASSET_VARIANT_GENERATION_FAILED' | 'ASSET_PREPROCESS_FAILED';
|
|
14
|
+
/**
|
|
15
|
+
* `AssetRef` is owned by `./refs.ts` (single source of truth, Zod
|
|
16
|
+
* schema + inferred type). Re-exported here for the error class that
|
|
17
|
+
* carries refs as structured data. Other consumers import from `./refs`
|
|
18
|
+
* directly.
|
|
19
|
+
*/
|
|
20
|
+
export type { AssetRef } from './refs.js';
|
|
21
|
+
import type { AssetRef } from './refs.js';
|
|
22
|
+
/**
|
|
23
|
+
* Every asset error maps to exactly one HTTP status. Declaring it on the
|
|
24
|
+
* class — not in every route handler — means adding a new error subclass
|
|
25
|
+
* requires no route-handler changes (OCP). Kept as a type union rather
|
|
26
|
+
* than `number` so that a typo at the class level fails to compile.
|
|
27
|
+
*/
|
|
28
|
+
export type AssetErrorHttpStatus = 400 | 404 | 409 | 500;
|
|
29
|
+
/**
|
|
30
|
+
* JSON body shape for `AssetError.toResponseBody()`. Every response body
|
|
31
|
+
* has at least `{ code, message }`; structured subclasses (AssetInUseError,
|
|
32
|
+
* AssetValidationError) override `toResponseBody()` to attach extra fields.
|
|
33
|
+
*
|
|
34
|
+
* The admin client's Zod schemas (`admin-api/schemas/assets.ts`) parse the
|
|
35
|
+
* body into typed responses; drift between server serialization and client
|
|
36
|
+
* parsing is a compile-time error.
|
|
37
|
+
*/
|
|
38
|
+
export interface AssetErrorResponseBody {
|
|
39
|
+
readonly code: AssetErrorCode;
|
|
40
|
+
readonly message: string;
|
|
41
|
+
readonly [extra: string]: unknown;
|
|
42
|
+
}
|
|
43
|
+
export declare abstract class AssetError extends Error {
|
|
44
|
+
abstract readonly code: AssetErrorCode;
|
|
45
|
+
/** HTTP status this error maps to at the transport boundary. */
|
|
46
|
+
abstract readonly httpStatus: AssetErrorHttpStatus;
|
|
47
|
+
constructor(message: string);
|
|
48
|
+
/**
|
|
49
|
+
* Serialize this error to a JSON response body. Default shape is
|
|
50
|
+
* `{ code, message }`; subclasses override to add structured data.
|
|
51
|
+
* Transport-boundary polymorphism — no `instanceof` chain needed at
|
|
52
|
+
* the route mapper.
|
|
53
|
+
*/
|
|
54
|
+
toResponseBody(): AssetErrorResponseBody;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Upload-validation failure hierarchy.
|
|
58
|
+
*
|
|
59
|
+
* Each concrete reason a candidate can be rejected is its own class. No
|
|
60
|
+
* god-class taking a polymorphic `code` argument — the class itself is
|
|
61
|
+
* the reason. Benefits (SOLID):
|
|
62
|
+
*
|
|
63
|
+
* - SRP: each class has one reason to change.
|
|
64
|
+
* - OCP: adding a new validation reason = new class, no edits to
|
|
65
|
+
* existing ones; the httpStatus (400) is inherited.
|
|
66
|
+
* - LSP: every subclass fully honors `AssetValidationError` — an
|
|
67
|
+
* `instanceof AssetValidationError` check still groups them.
|
|
68
|
+
* - ISP: callers that only care about "was this input-invalid?" match
|
|
69
|
+
* the base class; callers that branch on specific reasons use the
|
|
70
|
+
* concrete subclass.
|
|
71
|
+
*
|
|
72
|
+
* The `AssetValidationError` base stays as the umbrella for callers that
|
|
73
|
+
* treat all input-validation failures uniformly (HTTP always maps to 400).
|
|
74
|
+
*/
|
|
75
|
+
export declare abstract class AssetValidationError extends AssetError {
|
|
76
|
+
readonly httpStatus: 400;
|
|
77
|
+
}
|
|
78
|
+
/** Asset name failed character / length rules. */
|
|
79
|
+
export declare class AssetNameInvalidError extends AssetValidationError {
|
|
80
|
+
readonly name: string;
|
|
81
|
+
readonly code: "ASSET_NAME_INVALID";
|
|
82
|
+
constructor(name: string, message: string);
|
|
83
|
+
}
|
|
84
|
+
/** Asset name attempted path traversal (`..`, leading `/`, backslash). */
|
|
85
|
+
export declare class AssetPathTraversalError extends AssetValidationError {
|
|
86
|
+
readonly name: string;
|
|
87
|
+
readonly code: "ASSET_PATH_TRAVERSAL";
|
|
88
|
+
constructor(name: string);
|
|
89
|
+
}
|
|
90
|
+
/** Asset name collides with a reserved prefix or suffix. */
|
|
91
|
+
export declare class AssetNameReservedError extends AssetValidationError {
|
|
92
|
+
readonly name: string;
|
|
93
|
+
readonly reservedToken: string;
|
|
94
|
+
readonly position: 'prefix' | 'suffix';
|
|
95
|
+
readonly code: "ASSET_NAME_RESERVED";
|
|
96
|
+
constructor(name: string, reservedToken: string, position: 'prefix' | 'suffix');
|
|
97
|
+
}
|
|
98
|
+
/** Asset bytes exceed the configured size limit, or claimed size is zero. */
|
|
99
|
+
export declare class AssetSizeExceededError extends AssetValidationError {
|
|
100
|
+
readonly claimedSize: number;
|
|
101
|
+
readonly maxBytes: number;
|
|
102
|
+
readonly code: "ASSET_SIZE_EXCEEDED";
|
|
103
|
+
constructor(claimedSize: number, maxBytes: number);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Sniffed MIME is absent or not in the allowlist. The class owns its own
|
|
107
|
+
* message construction — no caller passes a pre-baked string. Two distinct
|
|
108
|
+
* failure reasons share the same `code` because they're the same error
|
|
109
|
+
* semantically ("the MIME isn't usable"): distinguishable by inspecting
|
|
110
|
+
* `sniffedMime === null` vs set.
|
|
111
|
+
*/
|
|
112
|
+
export declare class AssetMimeMismatchError extends AssetValidationError {
|
|
113
|
+
readonly sniffedMime: string | null;
|
|
114
|
+
readonly allowedMimes: readonly string[];
|
|
115
|
+
readonly code: "ASSET_MIME_MISMATCH";
|
|
116
|
+
constructor(sniffedMime: string | null, allowedMimes: readonly string[]);
|
|
117
|
+
}
|
|
118
|
+
/** Wraps an underlying storage-layer failure during an asset operation. */
|
|
119
|
+
export declare class AssetStorageError extends AssetError {
|
|
120
|
+
readonly operation: 'read' | 'write' | 'delete' | 'stat';
|
|
121
|
+
readonly path: string;
|
|
122
|
+
readonly code: "ASSET_STORAGE_FAILURE";
|
|
123
|
+
readonly httpStatus: 500;
|
|
124
|
+
constructor(operation: 'read' | 'write' | 'delete' | 'stat', path: string, cause: unknown);
|
|
125
|
+
}
|
|
126
|
+
/** Manifest JSON couldn't be parsed. */
|
|
127
|
+
export declare class AssetManifestCorruptError extends AssetError {
|
|
128
|
+
readonly code: "ASSET_MANIFEST_CORRUPT";
|
|
129
|
+
readonly httpStatus: 500;
|
|
130
|
+
constructor(path: string, cause: unknown);
|
|
131
|
+
}
|
|
132
|
+
/** Manifest file missing — asset name doesn't exist on this target. */
|
|
133
|
+
export declare class AssetManifestNotFoundError extends AssetError {
|
|
134
|
+
readonly code: "ASSET_MANIFEST_NOT_FOUND";
|
|
135
|
+
readonly httpStatus: 404;
|
|
136
|
+
constructor(name: string);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Delete was attempted on an asset that pages or fragments still reference.
|
|
140
|
+
* The design doc's delete-blocked contract: surface the usage list so the
|
|
141
|
+
* author can rewrite refs or pick a replacement. `refs` is attached as
|
|
142
|
+
* structured data — HTTP layer serializes it into the 409 response body.
|
|
143
|
+
*/
|
|
144
|
+
export declare class AssetInUseError extends AssetError {
|
|
145
|
+
readonly assetName: string;
|
|
146
|
+
readonly refs: readonly AssetRef[];
|
|
147
|
+
readonly code: "ASSET_IN_USE";
|
|
148
|
+
readonly httpStatus: 409;
|
|
149
|
+
constructor(assetName: string, refs: readonly AssetRef[]);
|
|
150
|
+
toResponseBody(): AssetErrorResponseBody;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Manifest MIME has no known extension mapping, so path enumeration
|
|
154
|
+
* can't be completed. Operations that need the full path set (delete,
|
|
155
|
+
* rename, GC) can't proceed. Distinct from validation failure (the
|
|
156
|
+
* manifest is fine — we just don't know how to lay out bytes for this
|
|
157
|
+
* MIME) and from storage failure (nothing failed I/O).
|
|
158
|
+
*
|
|
159
|
+
* In practice, reaching this means a new kind was added without
|
|
160
|
+
* extending `url.ts#extFromMime` — the type points at exactly what
|
|
161
|
+
* needs a fix.
|
|
162
|
+
*/
|
|
163
|
+
export declare class AssetMimeUnsupportedError extends AssetError {
|
|
164
|
+
readonly mime: string;
|
|
165
|
+
readonly assetName: string;
|
|
166
|
+
readonly code: "ASSET_MIME_UNSUPPORTED";
|
|
167
|
+
readonly httpStatus: 500;
|
|
168
|
+
constructor(mime: string, assetName: string);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Responsive-variant generation failed during upload ingest. The original
|
|
172
|
+
* bytes passed MIME sniffing and dimension extraction but sharp could not
|
|
173
|
+
* resize them — usually means truncation, corruption, or a decompression-
|
|
174
|
+
* bomb that sharp declined to decode. The ingest pipeline rolls back the
|
|
175
|
+
* main-bytes write on this error so the upload fails atomically. HTTP
|
|
176
|
+
* 400 (client-correctable: re-upload a non-broken image).
|
|
177
|
+
*
|
|
178
|
+
* Distinct from `AssetMimeMismatchError` (MIME-sniff rejection) because
|
|
179
|
+
* the file may be a legitimate JPEG/PNG on paper — we only discovered
|
|
180
|
+
* the problem once sharp tried to do real work with the pixels.
|
|
181
|
+
*/
|
|
182
|
+
export declare class AssetVariantGenerationError extends AssetError {
|
|
183
|
+
readonly assetName: string;
|
|
184
|
+
readonly code: "ASSET_VARIANT_GENERATION_FAILED";
|
|
185
|
+
readonly httpStatus: 400;
|
|
186
|
+
constructor(assetName: string, cause: unknown);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Format-specific preprocessing failed during ingest. Today: SVG
|
|
190
|
+
* sanitization (DOMPurify rejected the input as malformed XML or it
|
|
191
|
+
* carried oversized embedded base64). Future: HEIC→JPEG transcode,
|
|
192
|
+
* EXIF-orientation flatten, animated-GIF frame extraction.
|
|
193
|
+
*
|
|
194
|
+
* 400 because the input is the problem (client-correctable). The
|
|
195
|
+
* specific reason is on `reason` so route handlers / clients can
|
|
196
|
+
* branch on it. `format` (the MIME) lets clients show the right
|
|
197
|
+
* remediation copy.
|
|
198
|
+
*/
|
|
199
|
+
export declare class AssetPreprocessError extends AssetError {
|
|
200
|
+
readonly format: string;
|
|
201
|
+
readonly reason: string;
|
|
202
|
+
readonly code: "ASSET_PREPROCESS_FAILED";
|
|
203
|
+
readonly httpStatus: 400;
|
|
204
|
+
constructor(format: string, reason: string, cause?: unknown);
|
|
205
|
+
toResponseBody(): AssetErrorResponseBody;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Rename was attempted to a name that's already taken by another asset.
|
|
209
|
+
* Per design-media.md → Rename: copying onto an existing asset would
|
|
210
|
+
* silently merge two distinct assets into one — the operation refuses
|
|
211
|
+
* instead. Authors who genuinely want to merge use replace-and-delete
|
|
212
|
+
* (different verb, explicit kind-compat check). HTTP 409.
|
|
213
|
+
*/
|
|
214
|
+
export declare class AssetNameCollisionError extends AssetError {
|
|
215
|
+
readonly newName: string;
|
|
216
|
+
readonly code: "ASSET_NAME_COLLISION";
|
|
217
|
+
readonly httpStatus: 409;
|
|
218
|
+
constructor(newName: string);
|
|
219
|
+
toResponseBody(): AssetErrorResponseBody;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Replace was attempted between two assets whose kinds (or within
|
|
223
|
+
* `embedded`, MIME categories) don't match. Per design-media.md →
|
|
224
|
+
* Delete semantics: "same kind (embedded ↔ embedded, downloadable ↔
|
|
225
|
+
* downloadable). Within embedded, cross-subtype is blocked
|
|
226
|
+
* (image ≠ video)."
|
|
227
|
+
*
|
|
228
|
+
* Carries structured fields so the UI can render a specific message
|
|
229
|
+
* ("image → video not allowed") without parsing the human message.
|
|
230
|
+
*/
|
|
231
|
+
export declare class AssetKindMismatchError extends AssetError {
|
|
232
|
+
readonly oldKind: string;
|
|
233
|
+
readonly oldMimeCategory: string;
|
|
234
|
+
readonly newKind: string;
|
|
235
|
+
readonly newMimeCategory: string;
|
|
236
|
+
readonly code: "ASSET_KIND_MISMATCH";
|
|
237
|
+
readonly httpStatus: 409;
|
|
238
|
+
constructor(oldKind: string, oldMimeCategory: string, newKind: string, newMimeCategory: string);
|
|
239
|
+
toResponseBody(): AssetErrorResponseBody;
|
|
240
|
+
}
|
|
241
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/assets/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed errors for the asset domain.
|
|
3
|
+
*
|
|
4
|
+
* Every asset-domain failure is one of these classes — never a plain
|
|
5
|
+
* `new Error('not implemented')`. Callers pattern-match on the class to
|
|
6
|
+
* decide what to do (HTTP status, CLI exit code, retry policy, user
|
|
7
|
+
* message). Subclassing keeps the public error taxonomy small and stable.
|
|
8
|
+
*
|
|
9
|
+
* The `code` property is the machine-readable identifier. Messages are
|
|
10
|
+
* human-readable and may include path/name details; tests should match
|
|
11
|
+
* on `code`, not on message text.
|
|
12
|
+
*/
|
|
13
|
+
export class AssetError extends Error {
|
|
14
|
+
constructor(message) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.name = this.constructor.name;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Serialize this error to a JSON response body. Default shape is
|
|
20
|
+
* `{ code, message }`; subclasses override to add structured data.
|
|
21
|
+
* Transport-boundary polymorphism — no `instanceof` chain needed at
|
|
22
|
+
* the route mapper.
|
|
23
|
+
*/
|
|
24
|
+
toResponseBody() {
|
|
25
|
+
return { code: this.code, message: this.message };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Upload-validation failure hierarchy.
|
|
30
|
+
*
|
|
31
|
+
* Each concrete reason a candidate can be rejected is its own class. No
|
|
32
|
+
* god-class taking a polymorphic `code` argument — the class itself is
|
|
33
|
+
* the reason. Benefits (SOLID):
|
|
34
|
+
*
|
|
35
|
+
* - SRP: each class has one reason to change.
|
|
36
|
+
* - OCP: adding a new validation reason = new class, no edits to
|
|
37
|
+
* existing ones; the httpStatus (400) is inherited.
|
|
38
|
+
* - LSP: every subclass fully honors `AssetValidationError` — an
|
|
39
|
+
* `instanceof AssetValidationError` check still groups them.
|
|
40
|
+
* - ISP: callers that only care about "was this input-invalid?" match
|
|
41
|
+
* the base class; callers that branch on specific reasons use the
|
|
42
|
+
* concrete subclass.
|
|
43
|
+
*
|
|
44
|
+
* The `AssetValidationError` base stays as the umbrella for callers that
|
|
45
|
+
* treat all input-validation failures uniformly (HTTP always maps to 400).
|
|
46
|
+
*/
|
|
47
|
+
export class AssetValidationError extends AssetError {
|
|
48
|
+
httpStatus = 400;
|
|
49
|
+
}
|
|
50
|
+
/** Asset name failed character / length rules. */
|
|
51
|
+
export class AssetNameInvalidError extends AssetValidationError {
|
|
52
|
+
name;
|
|
53
|
+
code = 'ASSET_NAME_INVALID';
|
|
54
|
+
constructor(name, message) {
|
|
55
|
+
super(message);
|
|
56
|
+
this.name = name;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** Asset name attempted path traversal (`..`, leading `/`, backslash). */
|
|
60
|
+
export class AssetPathTraversalError extends AssetValidationError {
|
|
61
|
+
name;
|
|
62
|
+
code = 'ASSET_PATH_TRAVERSAL';
|
|
63
|
+
constructor(name) {
|
|
64
|
+
super(`Asset name contains path traversal: ${name}`);
|
|
65
|
+
this.name = name;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/** Asset name collides with a reserved prefix or suffix. */
|
|
69
|
+
export class AssetNameReservedError extends AssetValidationError {
|
|
70
|
+
name;
|
|
71
|
+
reservedToken;
|
|
72
|
+
position;
|
|
73
|
+
code = 'ASSET_NAME_RESERVED';
|
|
74
|
+
constructor(name, reservedToken, position) {
|
|
75
|
+
super(`Asset name reserved (${position} "${reservedToken}"): ${name}`);
|
|
76
|
+
this.name = name;
|
|
77
|
+
this.reservedToken = reservedToken;
|
|
78
|
+
this.position = position;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/** Asset bytes exceed the configured size limit, or claimed size is zero. */
|
|
82
|
+
export class AssetSizeExceededError extends AssetValidationError {
|
|
83
|
+
claimedSize;
|
|
84
|
+
maxBytes;
|
|
85
|
+
code = 'ASSET_SIZE_EXCEEDED';
|
|
86
|
+
constructor(claimedSize, maxBytes) {
|
|
87
|
+
super(claimedSize <= 0
|
|
88
|
+
? 'Asset size must be greater than 0'
|
|
89
|
+
: `Asset exceeds size limit (${claimedSize} bytes > ${maxBytes} bytes)`);
|
|
90
|
+
this.claimedSize = claimedSize;
|
|
91
|
+
this.maxBytes = maxBytes;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Sniffed MIME is absent or not in the allowlist. The class owns its own
|
|
96
|
+
* message construction — no caller passes a pre-baked string. Two distinct
|
|
97
|
+
* failure reasons share the same `code` because they're the same error
|
|
98
|
+
* semantically ("the MIME isn't usable"): distinguishable by inspecting
|
|
99
|
+
* `sniffedMime === null` vs set.
|
|
100
|
+
*/
|
|
101
|
+
export class AssetMimeMismatchError extends AssetValidationError {
|
|
102
|
+
sniffedMime;
|
|
103
|
+
allowedMimes;
|
|
104
|
+
code = 'ASSET_MIME_MISMATCH';
|
|
105
|
+
constructor(sniffedMime, allowedMimes) {
|
|
106
|
+
super(buildMimeMismatchMessage(sniffedMime, allowedMimes));
|
|
107
|
+
this.sniffedMime = sniffedMime;
|
|
108
|
+
this.allowedMimes = allowedMimes;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
function buildMimeMismatchMessage(sniffedMime, allowedMimes) {
|
|
112
|
+
const allowed = allowedMimes.length > 0 ? ` (allowed: ${allowedMimes.join(', ')})` : '';
|
|
113
|
+
if (sniffedMime === null)
|
|
114
|
+
return `Could not detect MIME type from bytes${allowed}`;
|
|
115
|
+
return `MIME "${sniffedMime}" not allowed${allowed}`;
|
|
116
|
+
}
|
|
117
|
+
/** Wraps an underlying storage-layer failure during an asset operation. */
|
|
118
|
+
export class AssetStorageError extends AssetError {
|
|
119
|
+
operation;
|
|
120
|
+
path;
|
|
121
|
+
code = 'ASSET_STORAGE_FAILURE';
|
|
122
|
+
httpStatus = 500;
|
|
123
|
+
constructor(operation, path, cause) {
|
|
124
|
+
super(`Storage ${operation} failed for ${path}: ${cause?.message ?? cause}`);
|
|
125
|
+
this.operation = operation;
|
|
126
|
+
this.path = path;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/** Manifest JSON couldn't be parsed. */
|
|
130
|
+
export class AssetManifestCorruptError extends AssetError {
|
|
131
|
+
code = 'ASSET_MANIFEST_CORRUPT';
|
|
132
|
+
httpStatus = 500;
|
|
133
|
+
constructor(path, cause) {
|
|
134
|
+
super(`Asset manifest corrupt at ${path}: ${cause?.message ?? cause}`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/** Manifest file missing — asset name doesn't exist on this target. */
|
|
138
|
+
export class AssetManifestNotFoundError extends AssetError {
|
|
139
|
+
code = 'ASSET_MANIFEST_NOT_FOUND';
|
|
140
|
+
httpStatus = 404;
|
|
141
|
+
constructor(name) {
|
|
142
|
+
super(`Asset not found: ${name}`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Delete was attempted on an asset that pages or fragments still reference.
|
|
147
|
+
* The design doc's delete-blocked contract: surface the usage list so the
|
|
148
|
+
* author can rewrite refs or pick a replacement. `refs` is attached as
|
|
149
|
+
* structured data — HTTP layer serializes it into the 409 response body.
|
|
150
|
+
*/
|
|
151
|
+
export class AssetInUseError extends AssetError {
|
|
152
|
+
assetName;
|
|
153
|
+
refs;
|
|
154
|
+
code = 'ASSET_IN_USE';
|
|
155
|
+
httpStatus = 409;
|
|
156
|
+
constructor(assetName, refs) {
|
|
157
|
+
super(`Asset "${assetName}" is still referenced by ${refs.length} item(s)`);
|
|
158
|
+
this.assetName = assetName;
|
|
159
|
+
this.refs = refs;
|
|
160
|
+
}
|
|
161
|
+
toResponseBody() {
|
|
162
|
+
// Spread the base `{ code, message }` so future base-class fields
|
|
163
|
+
// (e.g. a request id) flow through automatically.
|
|
164
|
+
return {
|
|
165
|
+
...super.toResponseBody(),
|
|
166
|
+
assetName: this.assetName,
|
|
167
|
+
refs: this.refs,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Manifest MIME has no known extension mapping, so path enumeration
|
|
173
|
+
* can't be completed. Operations that need the full path set (delete,
|
|
174
|
+
* rename, GC) can't proceed. Distinct from validation failure (the
|
|
175
|
+
* manifest is fine — we just don't know how to lay out bytes for this
|
|
176
|
+
* MIME) and from storage failure (nothing failed I/O).
|
|
177
|
+
*
|
|
178
|
+
* In practice, reaching this means a new kind was added without
|
|
179
|
+
* extending `url.ts#extFromMime` — the type points at exactly what
|
|
180
|
+
* needs a fix.
|
|
181
|
+
*/
|
|
182
|
+
export class AssetMimeUnsupportedError extends AssetError {
|
|
183
|
+
mime;
|
|
184
|
+
assetName;
|
|
185
|
+
code = 'ASSET_MIME_UNSUPPORTED';
|
|
186
|
+
httpStatus = 500;
|
|
187
|
+
constructor(mime, assetName) {
|
|
188
|
+
super(`MIME "${mime}" has no extension mapping (asset "${assetName}")`);
|
|
189
|
+
this.mime = mime;
|
|
190
|
+
this.assetName = assetName;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Responsive-variant generation failed during upload ingest. The original
|
|
195
|
+
* bytes passed MIME sniffing and dimension extraction but sharp could not
|
|
196
|
+
* resize them — usually means truncation, corruption, or a decompression-
|
|
197
|
+
* bomb that sharp declined to decode. The ingest pipeline rolls back the
|
|
198
|
+
* main-bytes write on this error so the upload fails atomically. HTTP
|
|
199
|
+
* 400 (client-correctable: re-upload a non-broken image).
|
|
200
|
+
*
|
|
201
|
+
* Distinct from `AssetMimeMismatchError` (MIME-sniff rejection) because
|
|
202
|
+
* the file may be a legitimate JPEG/PNG on paper — we only discovered
|
|
203
|
+
* the problem once sharp tried to do real work with the pixels.
|
|
204
|
+
*/
|
|
205
|
+
export class AssetVariantGenerationError extends AssetError {
|
|
206
|
+
assetName;
|
|
207
|
+
code = 'ASSET_VARIANT_GENERATION_FAILED';
|
|
208
|
+
httpStatus = 400;
|
|
209
|
+
constructor(assetName, cause) {
|
|
210
|
+
super(`Could not generate responsive variants for "${assetName}": ${cause?.message ?? cause}`);
|
|
211
|
+
this.assetName = assetName;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Format-specific preprocessing failed during ingest. Today: SVG
|
|
216
|
+
* sanitization (DOMPurify rejected the input as malformed XML or it
|
|
217
|
+
* carried oversized embedded base64). Future: HEIC→JPEG transcode,
|
|
218
|
+
* EXIF-orientation flatten, animated-GIF frame extraction.
|
|
219
|
+
*
|
|
220
|
+
* 400 because the input is the problem (client-correctable). The
|
|
221
|
+
* specific reason is on `reason` so route handlers / clients can
|
|
222
|
+
* branch on it. `format` (the MIME) lets clients show the right
|
|
223
|
+
* remediation copy.
|
|
224
|
+
*/
|
|
225
|
+
export class AssetPreprocessError extends AssetError {
|
|
226
|
+
format;
|
|
227
|
+
reason;
|
|
228
|
+
code = 'ASSET_PREPROCESS_FAILED';
|
|
229
|
+
httpStatus = 400;
|
|
230
|
+
constructor(format, reason, cause) {
|
|
231
|
+
const detail = cause instanceof Error ? `: ${cause.message}` : '';
|
|
232
|
+
super(`Preprocessing ${format} failed (${reason})${detail}`);
|
|
233
|
+
this.format = format;
|
|
234
|
+
this.reason = reason;
|
|
235
|
+
}
|
|
236
|
+
toResponseBody() {
|
|
237
|
+
return {
|
|
238
|
+
...super.toResponseBody(),
|
|
239
|
+
format: this.format,
|
|
240
|
+
reason: this.reason,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Rename was attempted to a name that's already taken by another asset.
|
|
246
|
+
* Per design-media.md → Rename: copying onto an existing asset would
|
|
247
|
+
* silently merge two distinct assets into one — the operation refuses
|
|
248
|
+
* instead. Authors who genuinely want to merge use replace-and-delete
|
|
249
|
+
* (different verb, explicit kind-compat check). HTTP 409.
|
|
250
|
+
*/
|
|
251
|
+
export class AssetNameCollisionError extends AssetError {
|
|
252
|
+
newName;
|
|
253
|
+
code = 'ASSET_NAME_COLLISION';
|
|
254
|
+
httpStatus = 409;
|
|
255
|
+
constructor(newName) {
|
|
256
|
+
super(`Asset name already in use: ${newName}`);
|
|
257
|
+
this.newName = newName;
|
|
258
|
+
}
|
|
259
|
+
toResponseBody() {
|
|
260
|
+
return {
|
|
261
|
+
...super.toResponseBody(),
|
|
262
|
+
newName: this.newName,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Replace was attempted between two assets whose kinds (or within
|
|
268
|
+
* `embedded`, MIME categories) don't match. Per design-media.md →
|
|
269
|
+
* Delete semantics: "same kind (embedded ↔ embedded, downloadable ↔
|
|
270
|
+
* downloadable). Within embedded, cross-subtype is blocked
|
|
271
|
+
* (image ≠ video)."
|
|
272
|
+
*
|
|
273
|
+
* Carries structured fields so the UI can render a specific message
|
|
274
|
+
* ("image → video not allowed") without parsing the human message.
|
|
275
|
+
*/
|
|
276
|
+
export class AssetKindMismatchError extends AssetError {
|
|
277
|
+
oldKind;
|
|
278
|
+
oldMimeCategory;
|
|
279
|
+
newKind;
|
|
280
|
+
newMimeCategory;
|
|
281
|
+
code = 'ASSET_KIND_MISMATCH';
|
|
282
|
+
httpStatus = 409;
|
|
283
|
+
constructor(oldKind, oldMimeCategory, newKind, newMimeCategory) {
|
|
284
|
+
super(`Replacement asset kind/category mismatch: old=${oldKind}/${oldMimeCategory}, new=${newKind}/${newMimeCategory}`);
|
|
285
|
+
this.oldKind = oldKind;
|
|
286
|
+
this.oldMimeCategory = oldMimeCategory;
|
|
287
|
+
this.newKind = newKind;
|
|
288
|
+
this.newMimeCategory = newMimeCategory;
|
|
289
|
+
}
|
|
290
|
+
toResponseBody() {
|
|
291
|
+
return {
|
|
292
|
+
...super.toResponseBody(),
|
|
293
|
+
oldKind: this.oldKind,
|
|
294
|
+
oldMimeCategory: this.oldMimeCategory,
|
|
295
|
+
newKind: this.newKind,
|
|
296
|
+
newMimeCategory: this.newMimeCategory,
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/assets/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAoDH,MAAM,OAAgB,UAAW,SAAQ,KAAK;IAK5C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAA;IACnC,CAAC;IAED;;;;;OAKG;IACH,cAAc;QACZ,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAA;IACnD,CAAC;CACF;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,OAAgB,oBAAqB,SAAQ,UAAU;IAClD,UAAU,GAAG,GAAY,CAAA;CACnC;AAED,kDAAkD;AAClD,MAAM,OAAO,qBAAsB,SAAQ,oBAAoB;IAG3C;IAFT,IAAI,GAAG,oBAA6B,CAAA;IAC7C,YACkB,IAAY,EAC5B,OAAe;QAEf,KAAK,CAAC,OAAO,CAAC,CAAA;QAHE,SAAI,GAAJ,IAAI,CAAQ;IAI9B,CAAC;CACF;AAED,0EAA0E;AAC1E,MAAM,OAAO,uBAAwB,SAAQ,oBAAoB;IAEnC;IADnB,IAAI,GAAG,sBAA+B,CAAA;IAC/C,YAA4B,IAAY;QACtC,KAAK,CAAC,uCAAuC,IAAI,EAAE,CAAC,CAAA;QAD1B,SAAI,GAAJ,IAAI,CAAQ;IAExC,CAAC;CACF;AAED,4DAA4D;AAC5D,MAAM,OAAO,sBAAuB,SAAQ,oBAAoB;IAG5C;IACA;IACA;IAJT,IAAI,GAAG,qBAA8B,CAAA;IAC9C,YACkB,IAAY,EACZ,aAAqB,EACrB,QAA6B;QAE7C,KAAK,CAAC,wBAAwB,QAAQ,KAAK,aAAa,OAAO,IAAI,EAAE,CAAC,CAAA;QAJtD,SAAI,GAAJ,IAAI,CAAQ;QACZ,kBAAa,GAAb,aAAa,CAAQ;QACrB,aAAQ,GAAR,QAAQ,CAAqB;IAG/C,CAAC;CACF;AAED,6EAA6E;AAC7E,MAAM,OAAO,sBAAuB,SAAQ,oBAAoB;IAG5C;IACA;IAHT,IAAI,GAAG,qBAA8B,CAAA;IAC9C,YACkB,WAAmB,EACnB,QAAgB;QAEhC,KAAK,CACH,WAAW,IAAI,CAAC;YACd,CAAC,CAAC,mCAAmC;YACrC,CAAC,CAAC,6BAA6B,WAAW,YAAY,QAAQ,SAAS,CAC1E,CAAA;QAPe,gBAAW,GAAX,WAAW,CAAQ;QACnB,aAAQ,GAAR,QAAQ,CAAQ;IAOlC,CAAC;CACF;AAED;;;;;;GAMG;AACH,MAAM,OAAO,sBAAuB,SAAQ,oBAAoB;IAG5C;IACA;IAHT,IAAI,GAAG,qBAA8B,CAAA;IAC9C,YACkB,WAA0B,EAC1B,YAA+B;QAE/C,KAAK,CAAC,wBAAwB,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC,CAAA;QAH1C,gBAAW,GAAX,WAAW,CAAe;QAC1B,iBAAY,GAAZ,YAAY,CAAmB;IAGjD,CAAC;CACF;AAED,SAAS,wBAAwB,CAAC,WAA0B,EAAE,YAA+B;IAC3F,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,cAAc,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAA;IACvF,IAAI,WAAW,KAAK,IAAI;QAAE,OAAO,wCAAwC,OAAO,EAAE,CAAA;IAClF,OAAO,SAAS,WAAW,gBAAgB,OAAO,EAAE,CAAA;AACtD,CAAC;AAED,2EAA2E;AAC3E,MAAM,OAAO,iBAAkB,SAAQ,UAAU;IAI7B;IACA;IAJT,IAAI,GAAG,uBAAgC,CAAA;IACvC,UAAU,GAAG,GAAY,CAAA;IAClC,YACkB,SAA+C,EAC/C,IAAY,EAC5B,KAAc;QAEd,KAAK,CAAC,WAAW,SAAS,eAAe,IAAI,KAAM,KAAe,EAAE,OAAO,IAAI,KAAK,EAAE,CAAC,CAAA;QAJvE,cAAS,GAAT,SAAS,CAAsC;QAC/C,SAAI,GAAJ,IAAI,CAAQ;IAI9B,CAAC;CACF;AAED,wCAAwC;AACxC,MAAM,OAAO,yBAA0B,SAAQ,UAAU;IAC9C,IAAI,GAAG,wBAAiC,CAAA;IACxC,UAAU,GAAG,GAAY,CAAA;IAClC,YAAY,IAAY,EAAE,KAAc;QACtC,KAAK,CAAC,6BAA6B,IAAI,KAAM,KAAe,EAAE,OAAO,IAAI,KAAK,EAAE,CAAC,CAAA;IACnF,CAAC;CACF;AAED,uEAAuE;AACvE,MAAM,OAAO,0BAA2B,SAAQ,UAAU;IAC/C,IAAI,GAAG,0BAAmC,CAAA;IAC1C,UAAU,GAAG,GAAY,CAAA;IAClC,YAAY,IAAY;QACtB,KAAK,CAAC,oBAAoB,IAAI,EAAE,CAAC,CAAA;IACnC,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,OAAO,eAAgB,SAAQ,UAAU;IAI3B;IACA;IAJT,IAAI,GAAG,cAAuB,CAAA;IAC9B,UAAU,GAAG,GAAY,CAAA;IAClC,YACkB,SAAiB,EACjB,IAAyB;QAEzC,KAAK,CAAC,UAAU,SAAS,4BAA4B,IAAI,CAAC,MAAM,UAAU,CAAC,CAAA;QAH3D,cAAS,GAAT,SAAS,CAAQ;QACjB,SAAI,GAAJ,IAAI,CAAqB;IAG3C,CAAC;IAEQ,cAAc;QACrB,kEAAkE;QAClE,kDAAkD;QAClD,OAAO;YACL,GAAG,KAAK,CAAC,cAAc,EAAE;YACzB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB,CAAA;IACH,CAAC;CACF;AAED;;;;;;;;;;GAUG;AACH,MAAM,OAAO,yBAA0B,SAAQ,UAAU;IAIrC;IACA;IAJT,IAAI,GAAG,wBAAiC,CAAA;IACxC,UAAU,GAAG,GAAY,CAAA;IAClC,YACkB,IAAY,EACZ,SAAiB;QAEjC,KAAK,CAAC,SAAS,IAAI,sCAAsC,SAAS,IAAI,CAAC,CAAA;QAHvD,SAAI,GAAJ,IAAI,CAAQ;QACZ,cAAS,GAAT,SAAS,CAAQ;IAGnC,CAAC;CACF;AAED;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,2BAA4B,SAAQ,UAAU;IAIvC;IAHT,IAAI,GAAG,iCAA0C,CAAA;IACjD,UAAU,GAAG,GAAY,CAAA;IAClC,YACkB,SAAiB,EACjC,KAAc;QAEd,KAAK,CAAC,+CAA+C,SAAS,MAAO,KAAe,EAAE,OAAO,IAAI,KAAK,EAAE,CAAC,CAAA;QAHzF,cAAS,GAAT,SAAS,CAAQ;IAInC,CAAC;CACF;AAED;;;;;;;;;;GAUG;AACH,MAAM,OAAO,oBAAqB,SAAQ,UAAU;IAIhC;IACA;IAJT,IAAI,GAAG,yBAAkC,CAAA;IACzC,UAAU,GAAG,GAAY,CAAA;IAClC,YACkB,MAAc,EACd,MAAc,EAC9B,KAAe;QAEf,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;QACjE,KAAK,CAAC,iBAAiB,MAAM,YAAY,MAAM,IAAI,MAAM,EAAE,CAAC,CAAA;QAL5C,WAAM,GAAN,MAAM,CAAQ;QACd,WAAM,GAAN,MAAM,CAAQ;IAKhC,CAAC;IAEQ,cAAc;QACrB,OAAO;YACL,GAAG,KAAK,CAAC,cAAc,EAAE;YACzB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAA;IACH,CAAC;CACF;AAED;;;;;;GAMG;AACH,MAAM,OAAO,uBAAwB,SAAQ,UAAU;IAGzB;IAFnB,IAAI,GAAG,sBAA+B,CAAA;IACtC,UAAU,GAAG,GAAY,CAAA;IAClC,YAA4B,OAAe;QACzC,KAAK,CAAC,8BAA8B,OAAO,EAAE,CAAC,CAAA;QADpB,YAAO,GAAP,OAAO,CAAQ;IAE3C,CAAC;IAEQ,cAAc;QACrB,OAAO;YACL,GAAG,KAAK,CAAC,cAAc,EAAE;YACzB,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAA;IACH,CAAC;CACF;AAED;;;;;;;;;GASG;AACH,MAAM,OAAO,sBAAuB,SAAQ,UAAU;IAIlC;IACA;IACA;IACA;IANT,IAAI,GAAG,qBAA8B,CAAA;IACrC,UAAU,GAAG,GAAY,CAAA;IAClC,YACkB,OAAe,EACf,eAAuB,EACvB,OAAe,EACf,eAAuB;QAEvC,KAAK,CACH,iDAAiD,OAAO,IAAI,eAAe,SAAS,OAAO,IAAI,eAAe,EAAE,CACjH,CAAA;QAPe,YAAO,GAAP,OAAO,CAAQ;QACf,oBAAe,GAAf,eAAe,CAAQ;QACvB,YAAO,GAAP,OAAO,CAAQ;QACf,oBAAe,GAAf,eAAe,CAAQ;IAKzC,CAAC;IAEQ,cAAc;QACrB,OAAO;YACL,GAAG,KAAK,CAAC,cAAc,EAAE;YACzB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,eAAe,EAAE,IAAI,CAAC,eAAe;SACtC,CAAA;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Find every reference to a given asset across a site's pages and
|
|
3
|
+
* fragments (including locale variants).
|
|
4
|
+
*
|
|
5
|
+
* Single responsibility: site-wide orchestration. Loads the site,
|
|
6
|
+
* iterates every manifest, delegates the per-manifest walk to
|
|
7
|
+
* `scan-manifest-for-asset.ts`, concatenates results.
|
|
8
|
+
*
|
|
9
|
+
* Scan-on-demand model (v1 simplification):
|
|
10
|
+
* - The design doc calls for an incremental `.refs/` index written on
|
|
11
|
+
* every save. That's a separate feature — its writer will import
|
|
12
|
+
* `scanManifestForAsset` directly (single-manifest granularity) and
|
|
13
|
+
* update the sidecar files, rather than calling this function.
|
|
14
|
+
* - For v1, delete-check and usage-panel reads use this full scan. O(site
|
|
15
|
+
* content size) per call, fine up to a few thousand pages.
|
|
16
|
+
*/
|
|
17
|
+
import type { SiteManifest, StorageProvider } from '../types.js';
|
|
18
|
+
import type { AssetRef } from './refs.js';
|
|
19
|
+
export interface FindRefsInput {
|
|
20
|
+
storage: StorageProvider;
|
|
21
|
+
/** Path prefix applied to storage operations (content root). */
|
|
22
|
+
siteDir: string;
|
|
23
|
+
/** The asset name to find references to. */
|
|
24
|
+
assetName: string;
|
|
25
|
+
/**
|
|
26
|
+
* Optional project-level site manifest. Passed through to `loadSite` so
|
|
27
|
+
* scans work in contexts where the target doesn't have its own site.yaml.
|
|
28
|
+
*/
|
|
29
|
+
manifest?: SiteManifest;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Find every page or fragment manifest that references `assetName`. One
|
|
33
|
+
* entry per match — a manifest that references the asset twice produces
|
|
34
|
+
* two entries with different `componentPath` values.
|
|
35
|
+
*/
|
|
36
|
+
export declare function findAssetRefs(input: FindRefsInput): Promise<AssetRef[]>;
|
|
37
|
+
//# sourceMappingURL=find-refs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find-refs.d.ts","sourceRoot":"","sources":["../../src/assets/find-refs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAIhE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAEzC,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,eAAe,CAAA;IACxB,gEAAgE;IAChE,OAAO,EAAE,MAAM,CAAA;IACf,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAA;IACjB;;;OAGG;IACH,QAAQ,CAAC,EAAE,YAAY,CAAA;CACxB;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CA6B7E"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { createContentRoot } from '../content-root.js';
|
|
2
|
+
import { allFragmentEntries, allPageEntries, loadSite } from '../site-loader.js';
|
|
3
|
+
import { scanManifestForAsset } from './scan-manifest-for-asset.js';
|
|
4
|
+
/**
|
|
5
|
+
* Find every page or fragment manifest that references `assetName`. One
|
|
6
|
+
* entry per match — a manifest that references the asset twice produces
|
|
7
|
+
* two entries with different `componentPath` values.
|
|
8
|
+
*/
|
|
9
|
+
export async function findAssetRefs(input) {
|
|
10
|
+
const contentRoot = createContentRoot(input.storage, input.siteDir);
|
|
11
|
+
const site = await loadSite({ contentRoot, manifest: input.manifest });
|
|
12
|
+
const refs = [];
|
|
13
|
+
for (const { name, page, locale } of allPageEntries(site)) {
|
|
14
|
+
refs.push(...scanManifestForAsset({
|
|
15
|
+
manifest: page,
|
|
16
|
+
manifestPath: localeManifestPath('pages', name, 'page', locale),
|
|
17
|
+
source: 'page',
|
|
18
|
+
assetName: input.assetName,
|
|
19
|
+
}));
|
|
20
|
+
}
|
|
21
|
+
for (const { name, fragment, locale } of allFragmentEntries(site)) {
|
|
22
|
+
refs.push(...scanManifestForAsset({
|
|
23
|
+
manifest: fragment,
|
|
24
|
+
manifestPath: localeManifestPath('fragments', name, 'fragment', locale),
|
|
25
|
+
source: 'fragment',
|
|
26
|
+
assetName: input.assetName,
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
return refs;
|
|
30
|
+
}
|
|
31
|
+
function localeManifestPath(root, itemName, baseName, locale) {
|
|
32
|
+
const file = locale ? `${baseName}.${locale}.json` : `${baseName}.json`;
|
|
33
|
+
return `${root}/${itemName}/${file}`;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=find-refs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find-refs.js","sourceRoot":"","sources":["../../src/assets/find-refs.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAChF,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAA;AAgBnE;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAAoB;IACtD,MAAM,WAAW,GAAG,iBAAiB,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;IACnE,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAA;IAEtE,MAAM,IAAI,GAAe,EAAE,CAAA;IAE3B,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1D,IAAI,CAAC,IAAI,CACP,GAAG,oBAAoB,CAAC;YACtB,QAAQ,EAAE,IAAI;YACd,YAAY,EAAE,kBAAkB,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC;YAC/D,MAAM,EAAE,MAAM;YACd,SAAS,EAAE,KAAK,CAAC,SAAS;SAC3B,CAAC,CACH,CAAA;IACH,CAAC;IAED,KAAK,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;QAClE,IAAI,CAAC,IAAI,CACP,GAAG,oBAAoB,CAAC;YACtB,QAAQ,EAAE,QAAQ;YAClB,YAAY,EAAE,kBAAkB,CAAC,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC;YACvE,MAAM,EAAE,UAAU;YAClB,SAAS,EAAE,KAAK,CAAC,SAAS;SAC3B,CAAC,CACH,CAAA;IACH,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC;AAED,SAAS,kBAAkB,CACzB,IAA2B,EAC3B,QAAgB,EAChB,QAA6B,EAC7B,MAA0B;IAE1B,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,QAAQ,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,QAAQ,OAAO,CAAA;IACvE,OAAO,GAAG,IAAI,IAAI,QAAQ,IAAI,IAAI,EAAE,CAAA;AACtC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Length of the hex prefix embedded in asset URLs. Matches the doc's `{hash8}`. */
|
|
2
|
+
export declare const ASSET_HASH_LENGTH = 8;
|
|
3
|
+
/** Hash a complete byte buffer — convenience wrapper for tests and small payloads. */
|
|
4
|
+
export declare function hashBytes(bytes: Uint8Array): string;
|
|
5
|
+
/**
|
|
6
|
+
* Hash a byte stream as it flows through. Consumes the stream. Returns the
|
|
7
|
+
* 8-char hex prefix once the stream ends.
|
|
8
|
+
*
|
|
9
|
+
* For upload pipelines that need to both hash and persist bytes, tee the
|
|
10
|
+
* source stream and pass one branch here, the other to storage.
|
|
11
|
+
*/
|
|
12
|
+
export declare function hashStream(stream: ReadableStream<Uint8Array>): Promise<string>;
|
|
13
|
+
//# sourceMappingURL=hash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/assets/hash.ts"],"names":[],"mappings":"AAiBA,oFAAoF;AACpF,eAAO,MAAM,iBAAiB,IAAI,CAAA;AAElC,sFAAsF;AACtF,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAGnD;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAAC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CASpF"}
|