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,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content-addressing hash for asset bytes.
|
|
3
|
+
*
|
|
4
|
+
* Uses **SHA-256**, 8-character hex prefix — the canonical asset-URL hash for
|
|
5
|
+
* this codebase. Distinct from:
|
|
6
|
+
* - `src/hash.ts` (MD5-based) used by publish-rendered sidecars
|
|
7
|
+
* - Full SHA-256 used by history blob storage
|
|
8
|
+
*
|
|
9
|
+
* See design-media-reference.md "Codebase alignment verified → Two hash
|
|
10
|
+
* algorithms coexist" for why asset work standardises on SHA-256 and doesn't
|
|
11
|
+
* extend the legacy MD5 sidecar pattern.
|
|
12
|
+
*
|
|
13
|
+
* The streaming helper (`hashStream`) consumes the passed stream. Callers
|
|
14
|
+
* that need both the hash AND the original bytes must tee the stream first.
|
|
15
|
+
*/
|
|
16
|
+
import { createHash } from 'node:crypto';
|
|
17
|
+
/** Length of the hex prefix embedded in asset URLs. Matches the doc's `{hash8}`. */
|
|
18
|
+
export const ASSET_HASH_LENGTH = 8;
|
|
19
|
+
/** Hash a complete byte buffer — convenience wrapper for tests and small payloads. */
|
|
20
|
+
export function hashBytes(bytes) {
|
|
21
|
+
const full = createHash('sha256').update(bytes).digest('hex');
|
|
22
|
+
return full.slice(0, ASSET_HASH_LENGTH);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Hash a byte stream as it flows through. Consumes the stream. Returns the
|
|
26
|
+
* 8-char hex prefix once the stream ends.
|
|
27
|
+
*
|
|
28
|
+
* For upload pipelines that need to both hash and persist bytes, tee the
|
|
29
|
+
* source stream and pass one branch here, the other to storage.
|
|
30
|
+
*/
|
|
31
|
+
export async function hashStream(stream) {
|
|
32
|
+
const digest = createHash('sha256');
|
|
33
|
+
const reader = stream.getReader();
|
|
34
|
+
while (true) {
|
|
35
|
+
const { value, done } = await reader.read();
|
|
36
|
+
if (done)
|
|
37
|
+
break;
|
|
38
|
+
if (value)
|
|
39
|
+
digest.update(value);
|
|
40
|
+
}
|
|
41
|
+
return digest.digest('hex').slice(0, ASSET_HASH_LENGTH);
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=hash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/assets/hash.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAExC,oFAAoF;AACpF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAA;AAElC,sFAAsF;AACtF,MAAM,UAAU,SAAS,CAAC,KAAiB;IACzC,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IAC7D,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAA;AACzC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAkC;IACjE,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAA;IACnC,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,CAAA;IACjC,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAA;QAC3C,IAAI,IAAI;YAAE,MAAK;QACf,IAAI,KAAK;YAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IACjC,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAA;AACzD,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface ImageDimensions {
|
|
2
|
+
width: number;
|
|
3
|
+
height: number;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Extract dimensions from an image buffer. Returns `null` when sharp
|
|
7
|
+
* can't parse the bytes (unsupported format, corrupt, or non-image MIME
|
|
8
|
+
* that slipped past sniffing).
|
|
9
|
+
*/
|
|
10
|
+
export declare function extractImageDimensions(bytes: Uint8Array): Promise<ImageDimensions | null>;
|
|
11
|
+
//# sourceMappingURL=image-metadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-metadata.d.ts","sourceRoot":"","sources":["../../src/assets/image-metadata.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAQ/F"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image metadata extraction — wraps sharp's `.metadata()` to get width +
|
|
3
|
+
* height from bytes without decoding the full image. Read-only, no transform,
|
|
4
|
+
* no resize.
|
|
5
|
+
*
|
|
6
|
+
* Step 4 will add a sibling transform module (variants via sharp's
|
|
7
|
+
* `.resize()` + `.toFormat()`) that shares the sharp dependency. This file
|
|
8
|
+
* stays focused on "describe the image" — a reason to change independent of
|
|
9
|
+
* variant generation.
|
|
10
|
+
*
|
|
11
|
+
* sharp is an Apache-2.0 Node binding over libvips. See
|
|
12
|
+
* design-media-reference.md → Library and tooling specifics.
|
|
13
|
+
*/
|
|
14
|
+
import sharp from 'sharp';
|
|
15
|
+
/**
|
|
16
|
+
* Extract dimensions from an image buffer. Returns `null` when sharp
|
|
17
|
+
* can't parse the bytes (unsupported format, corrupt, or non-image MIME
|
|
18
|
+
* that slipped past sniffing).
|
|
19
|
+
*/
|
|
20
|
+
export async function extractImageDimensions(bytes) {
|
|
21
|
+
try {
|
|
22
|
+
const meta = await sharp(bytes).metadata();
|
|
23
|
+
if (typeof meta.width !== 'number' || typeof meta.height !== 'number')
|
|
24
|
+
return null;
|
|
25
|
+
return { width: meta.width, height: meta.height };
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=image-metadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-metadata.js","sourceRoot":"","sources":["../../src/assets/image-metadata.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,MAAM,OAAO,CAAA;AAOzB;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,KAAiB;IAC5D,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,CAAA;QAC1C,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAA;QAClF,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAA;IACnD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Locale-bytes override ingest — write per-locale (or per-theme) bytes
|
|
3
|
+
* for an existing asset.
|
|
4
|
+
*
|
|
5
|
+
* Author-facing semantics (design-media.md → locale-specific bytes):
|
|
6
|
+
* "When the active locale is not the default and the author is
|
|
7
|
+
* uploading a file that matches an existing asset's name, the dialog
|
|
8
|
+
* asks: Replace default bytes / Add {locale} bytes override / Cancel."
|
|
9
|
+
*
|
|
10
|
+
* The "Add override" branch lands here. Result on disk:
|
|
11
|
+
* - `{name}.asset.{selector}.json` — locale-bytes manifest with own hash
|
|
12
|
+
* - `{name}-{hash}.{selector}.{ext}` — primary bytes for this locale
|
|
13
|
+
* - `{name}-{hash}.{selector}-{w}w.{ext}` — variant ladder for this locale
|
|
14
|
+
*
|
|
15
|
+
* The default manifest at `{name}.asset.json` is unchanged.
|
|
16
|
+
*
|
|
17
|
+
* Single responsibility: validate the override candidate, hash + extract
|
|
18
|
+
* dimensions + generate variants, write the locale manifest + bytes.
|
|
19
|
+
* Does NOT own:
|
|
20
|
+
* - the route adapter (HTTP layer)
|
|
21
|
+
* - the "default vs override" decision UX (the route knows whether the
|
|
22
|
+
* active locale is non-default)
|
|
23
|
+
* - per-reference content rewrites (locale-bytes don't affect refs)
|
|
24
|
+
*
|
|
25
|
+
* Compatibility rules per design-media.md:
|
|
26
|
+
* - Same kind as default (image override of image, etc.)
|
|
27
|
+
* - `animated` flag must match (out of v1 scope: animated detection
|
|
28
|
+
* deferred — today both default and override are static images)
|
|
29
|
+
* - MIME may differ within the kind category (jpeg default + webp
|
|
30
|
+
* override is allowed; image → video is not)
|
|
31
|
+
* - Dimensions may differ (warning at upload time is a UX concern)
|
|
32
|
+
*
|
|
33
|
+
* History recording mirrors `ingest.ts`: one revision per upload,
|
|
34
|
+
* recorded BEFORE any writes so the recorder's first-time baseline
|
|
35
|
+
* captures pre-op state.
|
|
36
|
+
*/
|
|
37
|
+
import type { ContentRoot } from '../content-root.js';
|
|
38
|
+
import type { HistoryProvider } from '../history.js';
|
|
39
|
+
import type { LocaleBytesOverrideManifest } from '../schema/types.js';
|
|
40
|
+
import type { Selector } from '../schema/dimensions.js';
|
|
41
|
+
import type { StorageProvider } from '../types.js';
|
|
42
|
+
import { type UploadPreprocessor } from './preprocess.js';
|
|
43
|
+
import { type UploadPolicy } from './validate.js';
|
|
44
|
+
export interface IngestLocaleBytesInput {
|
|
45
|
+
/** Storage provider. */
|
|
46
|
+
storage: StorageProvider;
|
|
47
|
+
/** Path prefix for assets (typically `"assets"`). */
|
|
48
|
+
assetsRoot: string;
|
|
49
|
+
/** Existing asset's name. The default manifest must already exist. */
|
|
50
|
+
assetName: string;
|
|
51
|
+
/**
|
|
52
|
+
* Selector for the override (locale + optional theme). Must be
|
|
53
|
+
* non-null — caller decides which dimension(s) to write. The default
|
|
54
|
+
* asset's bytes correspond to selector === null and are untouched.
|
|
55
|
+
*/
|
|
56
|
+
selector: Selector;
|
|
57
|
+
/** The incoming byte stream for the override bytes. */
|
|
58
|
+
bytes: ReadableStream<Uint8Array>;
|
|
59
|
+
/** Per-target upload policy (size cap). */
|
|
60
|
+
policy?: UploadPolicy;
|
|
61
|
+
/** Optional history. When set, one revision is recorded for this upload. */
|
|
62
|
+
history?: HistoryProvider;
|
|
63
|
+
/** Required when `history` is set. */
|
|
64
|
+
contentRoot?: ContentRoot;
|
|
65
|
+
/** Author identifier. */
|
|
66
|
+
author?: string;
|
|
67
|
+
/** Format-specific preprocessors. Defaults to `defaultPreprocessors`. */
|
|
68
|
+
preprocessors?: readonly UploadPreprocessor[];
|
|
69
|
+
}
|
|
70
|
+
export interface IngestLocaleBytesResult {
|
|
71
|
+
/** The new locale-bytes manifest as written. */
|
|
72
|
+
manifest: LocaleBytesOverrideManifest;
|
|
73
|
+
/** Path to the override's primary bytes (for caller logging). */
|
|
74
|
+
bytesPath: string;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Ingest a locale-bytes override for an existing asset. Throws:
|
|
78
|
+
* - `AssetManifestNotFoundError` — default manifest doesn't exist
|
|
79
|
+
* - `AssetValidationError` (subclass) — name/size/MIME failed policy
|
|
80
|
+
* - `AssetKindMismatchError` — MIME category differs from default
|
|
81
|
+
* (image override of pdf is rejected, jpeg override of png is fine)
|
|
82
|
+
* - `AssetVariantGenerationError` — sharp couldn't process the bytes
|
|
83
|
+
* - `AssetStorageError` — underlying storage failed
|
|
84
|
+
*/
|
|
85
|
+
export declare function ingestLocaleBytes(input: IngestLocaleBytesInput): Promise<IngestLocaleBytesResult>;
|
|
86
|
+
//# sourceMappingURL=ingest-locale.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ingest-locale.d.ts","sourceRoot":"","sources":["../../src/assets/ingest-locale.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAEpD,OAAO,KAAK,EAA+B,2BAA2B,EAAE,MAAM,oBAAoB,CAAA;AAClG,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAEvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAalD,OAAO,EAAoB,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAE3E,OAAO,EAAE,KAAK,YAAY,EAAkB,MAAM,eAAe,CAAA;AASjE,MAAM,WAAW,sBAAsB;IACrC,wBAAwB;IACxB,OAAO,EAAE,eAAe,CAAA;IACxB,qDAAqD;IACrD,UAAU,EAAE,MAAM,CAAA;IAClB,sEAAsE;IACtE,SAAS,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,QAAQ,EAAE,QAAQ,CAAA;IAClB,uDAAuD;IACvD,KAAK,EAAE,cAAc,CAAC,UAAU,CAAC,CAAA;IACjC,2CAA2C;IAC3C,MAAM,CAAC,EAAE,YAAY,CAAA;IACrB,4EAA4E;IAC5E,OAAO,CAAC,EAAE,eAAe,CAAA;IACzB,sCAAsC;IACtC,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,yBAAyB;IACzB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,yEAAyE;IACzE,aAAa,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAA;CAC9C;AAED,MAAM,WAAW,uBAAuB;IACtC,gDAAgD;IAChD,QAAQ,EAAE,2BAA2B,CAAA;IACrC,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAuJvG"}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { recordWrite } from '../history-recorder.js';
|
|
2
|
+
import { selectorSuffix } from '../schema/dimensions.js';
|
|
3
|
+
import { rmIgnoreMissing } from '../providers/_rm-ignore-missing.js';
|
|
4
|
+
import { AssetKindMismatchError, AssetMimeMismatchError, AssetStorageError, AssetVariantGenerationError, } from './errors.js';
|
|
5
|
+
import { ASSET_HASH_LENGTH, hashBytes } from './hash.js';
|
|
6
|
+
import { extractImageDimensions } from './image-metadata.js';
|
|
7
|
+
import { mimeCategory } from './kind-compat.js';
|
|
8
|
+
import { assetBytesPath, assetVariantBytesPath, readManifest, writeLocaleManifest } from './manifest.js';
|
|
9
|
+
import { runAnalyzers } from './analyze.js';
|
|
10
|
+
import { runPreprocessors } from './preprocess.js';
|
|
11
|
+
import { sniffMimeFromStream } from './mime-sniff.js';
|
|
12
|
+
import { validateUpload } from './validate.js';
|
|
13
|
+
import { generateVariants } from './variants.js';
|
|
14
|
+
/** Ext-from-MIME for the v1 allowlist (JPEG, PNG). */
|
|
15
|
+
const EXT_BY_MIME = {
|
|
16
|
+
'image/jpeg': 'jpg',
|
|
17
|
+
'image/png': 'png',
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Ingest a locale-bytes override for an existing asset. Throws:
|
|
21
|
+
* - `AssetManifestNotFoundError` — default manifest doesn't exist
|
|
22
|
+
* - `AssetValidationError` (subclass) — name/size/MIME failed policy
|
|
23
|
+
* - `AssetKindMismatchError` — MIME category differs from default
|
|
24
|
+
* (image override of pdf is rejected, jpeg override of png is fine)
|
|
25
|
+
* - `AssetVariantGenerationError` — sharp couldn't process the bytes
|
|
26
|
+
* - `AssetStorageError` — underlying storage failed
|
|
27
|
+
*/
|
|
28
|
+
export async function ingestLocaleBytes(input) {
|
|
29
|
+
// Step 1 — read the default manifest. Throws AssetManifestNotFoundError
|
|
30
|
+
// when the asset doesn't exist; you can't override bytes for an asset
|
|
31
|
+
// that isn't there.
|
|
32
|
+
const defaultManifest = await readManifest(input.storage, input.assetsRoot, input.assetName);
|
|
33
|
+
// Step 2 — collect bytes once.
|
|
34
|
+
const initialBuffer = await collectBytes(input.bytes);
|
|
35
|
+
// Step 3 — sniff MIME and validate.
|
|
36
|
+
const { mime, ext } = await sniffMimeFromStream(byteStreamFrom(initialBuffer));
|
|
37
|
+
validateUpload({ name: input.assetName, claimedSize: initialBuffer.byteLength, sniffedMime: mime }, input.policy);
|
|
38
|
+
const bytesExt = ext ?? EXT_BY_MIME[mime ?? ''] ?? '';
|
|
39
|
+
if (!bytesExt) {
|
|
40
|
+
throw new AssetMimeMismatchError(mime, []);
|
|
41
|
+
}
|
|
42
|
+
// Step 4 — kind/MIME-category compatibility with default. Per design,
|
|
43
|
+
// jpeg → webp is allowed (same `image` category); image → pdf is not.
|
|
44
|
+
// We don't compare `kind` directly because the override doesn't carry
|
|
45
|
+
// its own kind — it inherits from the default.
|
|
46
|
+
const overrideMime = mime ?? 'application/octet-stream';
|
|
47
|
+
const defaultCategory = mimeCategory(defaultManifest.mime);
|
|
48
|
+
const overrideCategory = mimeCategory(overrideMime);
|
|
49
|
+
if (defaultCategory !== overrideCategory) {
|
|
50
|
+
throw new AssetKindMismatchError(defaultManifest.kind, defaultCategory, defaultManifest.kind, overrideCategory);
|
|
51
|
+
}
|
|
52
|
+
// Step 5 — format-specific preprocessing (SVG sanitization, future
|
|
53
|
+
// EXIF/HEIC/etc.). Same interface as default-asset ingest; failures
|
|
54
|
+
// throw AssetPreprocessError (HTTP 400).
|
|
55
|
+
const { bytes: buffer } = await runPreprocessors(initialBuffer, mime, input.preprocessors);
|
|
56
|
+
const size = buffer.byteLength;
|
|
57
|
+
const hash = hashBytes(buffer);
|
|
58
|
+
if (hash.length !== ASSET_HASH_LENGTH) {
|
|
59
|
+
throw new AssetStorageError('write', input.assetName, new Error('unexpected hash length'));
|
|
60
|
+
}
|
|
61
|
+
// Step 6 — image dimensions (per-locale: override may differ from default).
|
|
62
|
+
const dims = overrideMime.startsWith('image/') ? await extractImageDimensions(buffer) : null;
|
|
63
|
+
// Step 7 — generate variants in memory. Skip for vector formats
|
|
64
|
+
// (SVG) and animated images (multi-frame can't ladder-resize
|
|
65
|
+
// correctly). Animated detection uses the analyzer for parity
|
|
66
|
+
// with the default-ingest path; locale manifests don't carry
|
|
67
|
+
// animated fields today, but the variant skip still matters.
|
|
68
|
+
const generatedVariants = [];
|
|
69
|
+
if (overrideMime.startsWith('image/') && overrideMime !== 'image/svg+xml') {
|
|
70
|
+
let isAnimated = false;
|
|
71
|
+
try {
|
|
72
|
+
const analysis = await runAnalyzers({
|
|
73
|
+
bytes: buffer,
|
|
74
|
+
assetName: input.assetName,
|
|
75
|
+
hash,
|
|
76
|
+
ext: bytesExt,
|
|
77
|
+
mime: overrideMime,
|
|
78
|
+
});
|
|
79
|
+
isAnimated = analysis.manifestPatch?.animated === true;
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
// Analyzer failure is non-fatal at this layer — fall back to
|
|
83
|
+
// assuming static + variants. Static analyzer would be the one
|
|
84
|
+
// failing; variant generation will surface its own error if
|
|
85
|
+
// sharp can't process the image.
|
|
86
|
+
}
|
|
87
|
+
if (!isAnimated) {
|
|
88
|
+
try {
|
|
89
|
+
const generated = await generateVariants(buffer);
|
|
90
|
+
generatedVariants.push(...generated);
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
throw new AssetVariantGenerationError(input.assetName, err);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Step 8 — compose paths + manifest in memory.
|
|
98
|
+
const variantManifestEntries = generatedVariants.map(v => ({
|
|
99
|
+
width: v.width,
|
|
100
|
+
path: assetVariantBytesPath(input.assetName, hash, bytesExt, v.width, input.selector),
|
|
101
|
+
size: v.bytes.byteLength,
|
|
102
|
+
}));
|
|
103
|
+
const bytesRel = assetBytesPath(input.assetName, hash, bytesExt, input.selector);
|
|
104
|
+
const bytesAbs = `${input.assetsRoot}/${bytesRel}`;
|
|
105
|
+
const localeManifest = {
|
|
106
|
+
version: 1,
|
|
107
|
+
name: input.assetName,
|
|
108
|
+
hash,
|
|
109
|
+
size,
|
|
110
|
+
mime: overrideMime,
|
|
111
|
+
width: dims?.width ?? null,
|
|
112
|
+
height: dims?.height ?? null,
|
|
113
|
+
variants: variantManifestEntries,
|
|
114
|
+
};
|
|
115
|
+
const localeManifestPath = `${input.assetsRoot}/${input.assetName}.asset${selectorSuffix(input.selector)}.json`;
|
|
116
|
+
// Step 8 — record history BEFORE any writes. Mirrors ingest.ts /
|
|
117
|
+
// replace.ts pattern.
|
|
118
|
+
if (input.history) {
|
|
119
|
+
if (!input.contentRoot) {
|
|
120
|
+
throw new Error('ingestLocaleBytes: history requires contentRoot');
|
|
121
|
+
}
|
|
122
|
+
const items = [
|
|
123
|
+
{ path: localeManifestPath, content: `${JSON.stringify(localeManifest, null, 2)}\n` },
|
|
124
|
+
{ path: bytesAbs, content: buffer },
|
|
125
|
+
...generatedVariants.map(v => ({
|
|
126
|
+
path: `${input.assetsRoot}/${assetVariantBytesPath(input.assetName, hash, bytesExt, v.width, input.selector)}`,
|
|
127
|
+
content: v.bytes,
|
|
128
|
+
})),
|
|
129
|
+
];
|
|
130
|
+
await recordWrite({
|
|
131
|
+
history: input.history,
|
|
132
|
+
contentRoot: input.contentRoot,
|
|
133
|
+
operation: 'save',
|
|
134
|
+
author: input.author,
|
|
135
|
+
items,
|
|
136
|
+
message: `Upload ${input.assetName} override (${selectorSuffix(input.selector).slice(1)})`,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
// Step 9 — write primary bytes.
|
|
140
|
+
try {
|
|
141
|
+
await input.storage.writeStream(bytesAbs, byteStreamFrom(buffer));
|
|
142
|
+
}
|
|
143
|
+
catch (err) {
|
|
144
|
+
throw new AssetStorageError('write', bytesAbs, err);
|
|
145
|
+
}
|
|
146
|
+
// Step 10 — write variants with rollback on failure.
|
|
147
|
+
const writtenVariantPaths = [];
|
|
148
|
+
for (const v of generatedVariants) {
|
|
149
|
+
const variantAbs = `${input.assetsRoot}/${assetVariantBytesPath(input.assetName, hash, bytesExt, v.width, input.selector)}`;
|
|
150
|
+
try {
|
|
151
|
+
await input.storage.writeStream(variantAbs, byteStreamFrom(v.bytes));
|
|
152
|
+
}
|
|
153
|
+
catch (err) {
|
|
154
|
+
await rollback(input.storage, [bytesAbs, ...writtenVariantPaths]);
|
|
155
|
+
throw new AssetStorageError('write', variantAbs, err);
|
|
156
|
+
}
|
|
157
|
+
writtenVariantPaths.push(variantAbs);
|
|
158
|
+
}
|
|
159
|
+
// Step 11 — write the locale manifest last (the visible "this
|
|
160
|
+
// override exists" record).
|
|
161
|
+
try {
|
|
162
|
+
await writeLocaleManifest(input.storage, input.assetsRoot, input.assetName, input.selector, localeManifest);
|
|
163
|
+
}
|
|
164
|
+
catch (err) {
|
|
165
|
+
await rollback(input.storage, [bytesAbs, ...writtenVariantPaths]);
|
|
166
|
+
throw err;
|
|
167
|
+
}
|
|
168
|
+
return { manifest: localeManifest, bytesPath: bytesAbs };
|
|
169
|
+
}
|
|
170
|
+
async function rollback(storage, paths) {
|
|
171
|
+
for (const path of paths) {
|
|
172
|
+
try {
|
|
173
|
+
await rmIgnoreMissing(storage, path);
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
/* best-effort */
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
async function collectBytes(stream) {
|
|
181
|
+
const reader = stream.getReader();
|
|
182
|
+
const parts = [];
|
|
183
|
+
let total = 0;
|
|
184
|
+
while (true) {
|
|
185
|
+
const { value, done } = await reader.read();
|
|
186
|
+
if (done)
|
|
187
|
+
break;
|
|
188
|
+
if (value) {
|
|
189
|
+
parts.push(value);
|
|
190
|
+
total += value.byteLength;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
const out = new Uint8Array(total);
|
|
194
|
+
let offset = 0;
|
|
195
|
+
for (const p of parts) {
|
|
196
|
+
out.set(p, offset);
|
|
197
|
+
offset += p.byteLength;
|
|
198
|
+
}
|
|
199
|
+
return out;
|
|
200
|
+
}
|
|
201
|
+
function byteStreamFrom(bytes) {
|
|
202
|
+
return new ReadableStream({
|
|
203
|
+
start(controller) {
|
|
204
|
+
controller.enqueue(bytes);
|
|
205
|
+
controller.close();
|
|
206
|
+
},
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
//# sourceMappingURL=ingest-locale.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ingest-locale.js","sourceRoot":"","sources":["../../src/assets/ingest-locale.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Asset ingest pipeline — the single entry point for "bytes in → persisted
|
|
3
|
+
* asset out." Composes validation, hashing, MIME sniffing, dimension
|
|
4
|
+
* extraction, byte persistence, and manifest writing.
|
|
5
|
+
*
|
|
6
|
+
* Callers (HTTP upload route, future CLI import, future paste-URL handler):
|
|
7
|
+
* const result = await ingestAsset({ storage, assetsRoot, bytes, requestedName, ... })
|
|
8
|
+
*
|
|
9
|
+
* Inside, the stream is collected into a buffer first — for the v1 slice's
|
|
10
|
+
* 50 MB limit this is the pragmatic choice (validation wants to see all the
|
|
11
|
+
* bytes; hashing + sniffing + dimensions all need to touch them). A future
|
|
12
|
+
* large-video path would need true streaming; calling sites that need that
|
|
13
|
+
* can compose the lower-level primitives (sniffMimeFromStream, hashStream,
|
|
14
|
+
* atomicWriteStream) directly.
|
|
15
|
+
*
|
|
16
|
+
* History atomicity:
|
|
17
|
+
* When `history` is provided, ingest records ONE revision covering the
|
|
18
|
+
* manifest + primary bytes + every variant. Recording happens BEFORE any
|
|
19
|
+
* writes so the recorder's first-time baseline scan captures pre-op
|
|
20
|
+
* state — same pattern as `replace.ts`. If recording succeeds but a
|
|
21
|
+
* subsequent write fails, the revision references blobs we never
|
|
22
|
+
* persisted; that's recoverable (history-restorer degrades gracefully
|
|
23
|
+
* on missing blobs) and rare (writes after a successful record fail
|
|
24
|
+
* only on transient storage errors), and far better than the inverse
|
|
25
|
+
* (writes succeed, recorder captures post-op state, undo is a no-op).
|
|
26
|
+
*/
|
|
27
|
+
import type { ContentRoot } from '../content-root.js';
|
|
28
|
+
import type { HistoryProvider } from '../history.js';
|
|
29
|
+
import type { AssetManifest } from '../schema/types.js';
|
|
30
|
+
import type { StorageProvider } from '../types.js';
|
|
31
|
+
import { type UploadAnalyzer } from './analyze.js';
|
|
32
|
+
import { type UploadPolicy } from './validate.js';
|
|
33
|
+
import { type UploadPreprocessor } from './preprocess.js';
|
|
34
|
+
export interface IngestInput {
|
|
35
|
+
/** The target's storage provider. */
|
|
36
|
+
storage: StorageProvider;
|
|
37
|
+
/** The assets directory prefix (e.g., `"assets"`) relative to storage root. */
|
|
38
|
+
assetsRoot: string;
|
|
39
|
+
/** The incoming byte stream (multipart file body). */
|
|
40
|
+
bytes: ReadableStream<Uint8Array>;
|
|
41
|
+
/** Author-chosen asset name (pre-validation; policy may reject). */
|
|
42
|
+
requestedName: string;
|
|
43
|
+
/** Optional author-supplied alt text. Null means "not set" (warns in the library). */
|
|
44
|
+
alt: string | null;
|
|
45
|
+
/** Author identifier, if available. Empty string when RBAC isn't configured. */
|
|
46
|
+
uploadedBy: string;
|
|
47
|
+
/**
|
|
48
|
+
* Per-target upload policy. When omitted, the default size cap
|
|
49
|
+
* (`DEFAULT_ASSET_MAX_BYTES` from validate.ts) applies. The HTTP
|
|
50
|
+
* route should pass `target.assets` through here so per-target
|
|
51
|
+
* limits are honored.
|
|
52
|
+
*/
|
|
53
|
+
policy?: UploadPolicy;
|
|
54
|
+
/**
|
|
55
|
+
* Optional history provider. When set, ingest records ONE revision
|
|
56
|
+
* covering manifest + primary bytes + variants. Caller must also pass
|
|
57
|
+
* `contentRoot` so the recorder can scan the pre-op baseline on its
|
|
58
|
+
* first call.
|
|
59
|
+
*/
|
|
60
|
+
history?: HistoryProvider;
|
|
61
|
+
/** Required when `history` is set — content root for the baseline scan. */
|
|
62
|
+
contentRoot?: ContentRoot;
|
|
63
|
+
/** Author identifier passed through to the history revision. */
|
|
64
|
+
author?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Format-specific preprocessors to run on the byte buffer before
|
|
67
|
+
* hashing. Defaults to `defaultPreprocessors` (today: SVG
|
|
68
|
+
* sanitization). Tests pass an empty array to bypass; future
|
|
69
|
+
* deployments can register custom preprocessors (HEIC transcode,
|
|
70
|
+
* etc.) without editing this module.
|
|
71
|
+
*/
|
|
72
|
+
preprocessors?: readonly UploadPreprocessor[];
|
|
73
|
+
/**
|
|
74
|
+
* Format-specific analyzers to run on the post-preprocess bytes.
|
|
75
|
+
* Defaults to `defaultAnalyzers` (today: width/height + animated
|
|
76
|
+
* detection + poster extraction for images). Empty array bypasses
|
|
77
|
+
* analysis; custom registries plug in audio metadata, EXIF,
|
|
78
|
+
* PDF page count, etc. without editing this module.
|
|
79
|
+
*/
|
|
80
|
+
analyzers?: readonly UploadAnalyzer[];
|
|
81
|
+
}
|
|
82
|
+
export interface IngestResult {
|
|
83
|
+
manifest: AssetManifest;
|
|
84
|
+
bytesPath: string;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Ingest an asset. On success, bytes are persisted at
|
|
88
|
+
* `{assetsRoot}/{name}-{hash}.{ext}` and the manifest at
|
|
89
|
+
* `{assetsRoot}/{name}.asset.json`.
|
|
90
|
+
*
|
|
91
|
+
* Throws:
|
|
92
|
+
* - `AssetValidationError` — name, size, or MIME failed policy
|
|
93
|
+
* - `AssetStorageError` — storage write failed
|
|
94
|
+
*/
|
|
95
|
+
export declare function ingestAsset(input: IngestInput): Promise<IngestResult>;
|
|
96
|
+
//# sourceMappingURL=ingest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ingest.d.ts","sourceRoot":"","sources":["../../src/assets/ingest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAEpD,OAAO,KAAK,EAAE,aAAa,EAAgB,MAAM,oBAAoB,CAAA;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAElD,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,cAAc,CAAA;AAMhE,OAAO,EAAE,KAAK,YAAY,EAAkB,MAAM,eAAe,CAAA;AACjE,OAAO,EAAoB,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AA2B3E,MAAM,WAAW,WAAW;IAC1B,qCAAqC;IACrC,OAAO,EAAE,eAAe,CAAA;IACxB,+EAA+E;IAC/E,UAAU,EAAE,MAAM,CAAA;IAClB,sDAAsD;IACtD,KAAK,EAAE,cAAc,CAAC,UAAU,CAAC,CAAA;IACjC,oEAAoE;IACpE,aAAa,EAAE,MAAM,CAAA;IACrB,sFAAsF;IACtF,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,gFAAgF;IAChF,UAAU,EAAE,MAAM,CAAA;IAClB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,YAAY,CAAA;IACrB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,eAAe,CAAA;IACzB,2EAA2E;IAC3E,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,gEAAgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAA;IAC7C;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,SAAS,cAAc,EAAE,CAAA;CACtC;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,aAAa,CAAA;IACvB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAmM3E"}
|