@ttt-productions/media-processing-core 0.8.8 → 0.8.10
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/dist/server/gcs-errors.d.ts +5 -2
- package/dist/server/gcs-errors.d.ts.map +1 -1
- package/dist/server/gcs-errors.js +6 -3
- package/dist/server/gcs-errors.js.map +1 -1
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/staged-object.d.ts +36 -0
- package/dist/server/staged-object.d.ts.map +1 -1
- package/dist/server/staged-object.js +46 -2
- package/dist/server/staged-object.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* True when a
|
|
3
|
-
*
|
|
2
|
+
* True when a storage read or delete failed because the object does not exist, from
|
|
3
|
+
* either backend this package's stores use. The Cloud Storage Admin SDK reports it as a
|
|
4
|
+
* numeric or string `404` code, or only in the message ("No such object"); the R2 store
|
|
5
|
+
* throws an `R2StorageError` whose message carries the S3 `NoSuchKey` error code. Any
|
|
6
|
+
* other failure — an R2 `NoSuchBucket` included — is not an object-not-found.
|
|
4
7
|
*/
|
|
5
8
|
export declare function isObjectNotFoundError(e: unknown): boolean;
|
|
6
9
|
//# sourceMappingURL=gcs-errors.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gcs-errors.d.ts","sourceRoot":"","sources":["../../src/server/gcs-errors.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"gcs-errors.d.ts","sourceRoot":"","sources":["../../src/server/gcs-errors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAGzD"}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* True when a
|
|
3
|
-
*
|
|
2
|
+
* True when a storage read or delete failed because the object does not exist, from
|
|
3
|
+
* either backend this package's stores use. The Cloud Storage Admin SDK reports it as a
|
|
4
|
+
* numeric or string `404` code, or only in the message ("No such object"); the R2 store
|
|
5
|
+
* throws an `R2StorageError` whose message carries the S3 `NoSuchKey` error code. Any
|
|
6
|
+
* other failure — an R2 `NoSuchBucket` included — is not an object-not-found.
|
|
4
7
|
*/
|
|
5
8
|
export function isObjectNotFoundError(e) {
|
|
6
9
|
const err = e;
|
|
7
|
-
return err?.code === 404 || err?.code === "404" || /No such object/i.test(String(err?.message));
|
|
10
|
+
return err?.code === 404 || err?.code === "404" || /No such object|NoSuchKey/i.test(String(err?.message));
|
|
8
11
|
}
|
|
9
12
|
//# sourceMappingURL=gcs-errors.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gcs-errors.js","sourceRoot":"","sources":["../../src/server/gcs-errors.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"gcs-errors.js","sourceRoot":"","sources":["../../src/server/gcs-errors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,CAAU;IAC9C,MAAM,GAAG,GAAG,CAA6D,CAAC;IAC1E,OAAO,GAAG,EAAE,IAAI,KAAK,GAAG,IAAI,GAAG,EAAE,IAAI,KAAK,KAAK,IAAI,2BAA2B,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;AAC5G,CAAC","sourcesContent":["/**\n * True when a storage read or delete failed because the object does not exist, from\n * either backend this package's stores use. The Cloud Storage Admin SDK reports it as a\n * numeric or string `404` code, or only in the message (\"No such object\"); the R2 store\n * throws an `R2StorageError` whose message carries the S3 `NoSuchKey` error code. Any\n * other failure — an R2 `NoSuchBucket` included — is not an object-not-found.\n */\nexport function isObjectNotFoundError(e: unknown): boolean {\n const err = e as { code?: unknown; message?: unknown } | null | undefined;\n return err?.code === 404 || err?.code === \"404\" || /No such object|NoSuchKey/i.test(String(err?.message));\n}\n"]}
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC"}
|
package/dist/server/index.js
CHANGED
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC","sourcesContent":["export * from \"./storage-ops.js\";\nexport * from \"./firebase-media-io.js\";\nexport * from \"./pending-media.js\";\nexport * from \"./staged-object.js\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC","sourcesContent":["export * from \"./storage-ops.js\";\nexport * from \"./firebase-media-io.js\";\nexport * from \"./pending-media.js\";\nexport * from \"./staged-object.js\";\nexport * from \"./gcs-errors.js\";\n"]}
|
|
@@ -18,6 +18,42 @@ export type StagedUploadMetadataRead = {
|
|
|
18
18
|
* failure throws.
|
|
19
19
|
*/
|
|
20
20
|
export declare function readStagedUploadMetadata(bucket: Bucket, storagePath: string): Promise<StagedUploadMetadataRead>;
|
|
21
|
+
/**
|
|
22
|
+
* The staged object's generation from metadata the caller already fetched, as a string
|
|
23
|
+
* (GCS generations exceed 2^53) — the one normalization `readStagedObjectGeneration`
|
|
24
|
+
* applies, for a processor that already holds the object's metadata and must not read
|
|
25
|
+
* it again. `undefined` when the metadata carries no generation (the emulator may not):
|
|
26
|
+
* absent, `null`, or an empty string, which names no generation.
|
|
27
|
+
*/
|
|
28
|
+
export declare function stagedObjectGenerationFromMetadata(metadata: {
|
|
29
|
+
generation?: string | number | null;
|
|
30
|
+
}): string | undefined;
|
|
31
|
+
/** The stored-object metadata field an `UnreadableStorageObjectMetadataError` names. */
|
|
32
|
+
export type StorageObjectMetadataField = "generation" | "size";
|
|
33
|
+
/**
|
|
34
|
+
* A storage object whose metadata has no readable generation or byte size. GCS, the Storage
|
|
35
|
+
* emulator, and a Storage finalize event always carry both, so this is an anomaly to surface,
|
|
36
|
+
* never to paper over with a placeholder. The bucket and key are PROPERTIES, never message
|
|
37
|
+
* text: an escaping error reaches monitoring, and an object key must not.
|
|
38
|
+
*/
|
|
39
|
+
export declare class UnreadableStorageObjectMetadataError extends Error {
|
|
40
|
+
readonly bucket: string;
|
|
41
|
+
readonly key: string;
|
|
42
|
+
readonly field: StorageObjectMetadataField;
|
|
43
|
+
constructor(bucket: string, key: string, field: StorageObjectMetadataField);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The object's generation from metadata the caller already holds, for a site that cannot
|
|
47
|
+
* proceed without it (a hold key, an evidence record, a pinned read). Throws
|
|
48
|
+
* `UnreadableStorageObjectMetadataError` (field `generation`) when the metadata names none —
|
|
49
|
+
* the same normalization as `stagedObjectGenerationFromMetadata`, with no fallback value.
|
|
50
|
+
*/
|
|
51
|
+
export declare function requireStorageObjectGeneration(metadata: {
|
|
52
|
+
generation?: string | number | null;
|
|
53
|
+
}, object: {
|
|
54
|
+
bucket: string;
|
|
55
|
+
key: string;
|
|
56
|
+
}): string;
|
|
21
57
|
export interface ReadStagedObjectGenerationOptions {
|
|
22
58
|
/** Called when the generation cannot be read (the caller logs it); reads then stay unpinned. */
|
|
23
59
|
onReadFailure?: (error: unknown) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"staged-object.d.ts","sourceRoot":"","sources":["../../src/server/staged-object.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE/C,sFAAsF;AACtF,MAAM,WAAW,oBAAoB;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED,MAAM,MAAM,wBAAwB,GAChC;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,oBAAoB,CAAA;CAAE,GAC/C;IAAE,KAAK,EAAE,KAAK,CAAA;CAAE,CAAC;AAErB;;;;GAIG;AACH,wBAAsB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAQrH;AAED,MAAM,WAAW,iCAAiC;IAChD,gGAAgG;IAChG,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC1C;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,0BAA0B,CAC9C,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,OAAO,GAAE,iCAAsC,GAC9C,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,
|
|
1
|
+
{"version":3,"file":"staged-object.d.ts","sourceRoot":"","sources":["../../src/server/staged-object.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE/C,sFAAsF;AACtF,MAAM,WAAW,oBAAoB;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED,MAAM,MAAM,wBAAwB,GAChC;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,oBAAoB,CAAA;CAAE,GAC/C;IAAE,KAAK,EAAE,KAAK,CAAA;CAAE,CAAC;AAErB;;;;GAIG;AACH,wBAAsB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAQrH;AAED;;;;;;GAMG;AACH,wBAAgB,kCAAkC,CAAC,QAAQ,EAAE;IAC3D,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;CACrC,GAAG,MAAM,GAAG,SAAS,CAKrB;AAED,wFAAwF;AACxF,MAAM,MAAM,0BAA0B,GAAG,YAAY,GAAG,MAAM,CAAC;AAE/D;;;;;GAKG;AACH,qBAAa,oCAAqC,SAAQ,KAAK;aAE3C,MAAM,EAAE,MAAM;aACd,GAAG,EAAE,MAAM;aACX,KAAK,EAAE,0BAA0B;gBAFjC,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,0BAA0B;CAKpD;AAED;;;;;GAKG;AACH,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;CAAE,EACjD,MAAM,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACtC,MAAM,CAMR;AAED,MAAM,WAAW,iCAAiC;IAChD,gGAAgG;IAChG,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC1C;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,0BAA0B,CAC9C,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,OAAO,GAAE,iCAAsC,GAC9C,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAS7B;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAEnF"}
|
|
@@ -18,6 +18,51 @@ export async function readStagedUploadMetadata(bucket, storagePath) {
|
|
|
18
18
|
throw e;
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* The staged object's generation from metadata the caller already fetched, as a string
|
|
23
|
+
* (GCS generations exceed 2^53) — the one normalization `readStagedObjectGeneration`
|
|
24
|
+
* applies, for a processor that already holds the object's metadata and must not read
|
|
25
|
+
* it again. `undefined` when the metadata carries no generation (the emulator may not):
|
|
26
|
+
* absent, `null`, or an empty string, which names no generation.
|
|
27
|
+
*/
|
|
28
|
+
export function stagedObjectGenerationFromMetadata(metadata) {
|
|
29
|
+
const { generation } = metadata;
|
|
30
|
+
if (generation === undefined || generation === null)
|
|
31
|
+
return undefined;
|
|
32
|
+
const value = String(generation);
|
|
33
|
+
return value === "" ? undefined : value;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* A storage object whose metadata has no readable generation or byte size. GCS, the Storage
|
|
37
|
+
* emulator, and a Storage finalize event always carry both, so this is an anomaly to surface,
|
|
38
|
+
* never to paper over with a placeholder. The bucket and key are PROPERTIES, never message
|
|
39
|
+
* text: an escaping error reaches monitoring, and an object key must not.
|
|
40
|
+
*/
|
|
41
|
+
export class UnreadableStorageObjectMetadataError extends Error {
|
|
42
|
+
bucket;
|
|
43
|
+
key;
|
|
44
|
+
field;
|
|
45
|
+
constructor(bucket, key, field) {
|
|
46
|
+
super(`storage object metadata has no readable ${field}`);
|
|
47
|
+
this.bucket = bucket;
|
|
48
|
+
this.key = key;
|
|
49
|
+
this.field = field;
|
|
50
|
+
this.name = "UnreadableStorageObjectMetadataError";
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The object's generation from metadata the caller already holds, for a site that cannot
|
|
55
|
+
* proceed without it (a hold key, an evidence record, a pinned read). Throws
|
|
56
|
+
* `UnreadableStorageObjectMetadataError` (field `generation`) when the metadata names none —
|
|
57
|
+
* the same normalization as `stagedObjectGenerationFromMetadata`, with no fallback value.
|
|
58
|
+
*/
|
|
59
|
+
export function requireStorageObjectGeneration(metadata, object) {
|
|
60
|
+
const generation = stagedObjectGenerationFromMetadata(metadata);
|
|
61
|
+
if (generation === undefined) {
|
|
62
|
+
throw new UnreadableStorageObjectMetadataError(object.bucket, object.key, "generation");
|
|
63
|
+
}
|
|
64
|
+
return generation;
|
|
65
|
+
}
|
|
21
66
|
/**
|
|
22
67
|
* The staged object's current generation, as a string (GCS generations exceed 2^53).
|
|
23
68
|
*
|
|
@@ -34,8 +79,7 @@ export async function readStagedObjectGeneration(bucket, storagePath, options =
|
|
|
34
79
|
return undefined;
|
|
35
80
|
try {
|
|
36
81
|
const [metadata] = await bucket.file(storagePath).getMetadata();
|
|
37
|
-
|
|
38
|
-
return generation === undefined || generation === null ? undefined : String(generation);
|
|
82
|
+
return stagedObjectGenerationFromMetadata(metadata);
|
|
39
83
|
}
|
|
40
84
|
catch (e) {
|
|
41
85
|
options.onReadFailure?.(e);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"staged-object.js","sourceRoot":"","sources":["../../src/server/staged-object.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,+EAA+E;AAC/E,oEAAoE;AAEpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAexD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,MAAc,EAAE,WAAmB;IAChF,IAAI,CAAC;QACH,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE,CAAC;QAChE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IACnC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,qBAAqB,CAAC,CAAC,CAAC;YAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;QACtD,MAAM,CAAC,CAAC;IACV,CAAC;AACH,CAAC;
|
|
1
|
+
{"version":3,"file":"staged-object.js","sourceRoot":"","sources":["../../src/server/staged-object.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,+EAA+E;AAC/E,oEAAoE;AAEpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAexD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,MAAc,EAAE,WAAmB;IAChF,IAAI,CAAC;QACH,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE,CAAC;QAChE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IACnC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,qBAAqB,CAAC,CAAC,CAAC;YAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;QACtD,MAAM,CAAC,CAAC;IACV,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,kCAAkC,CAAC,QAElD;IACC,MAAM,EAAE,UAAU,EAAE,GAAG,QAAQ,CAAC;IAChC,IAAI,UAAU,KAAK,SAAS,IAAI,UAAU,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IACtE,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;IACjC,OAAO,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC;AAC1C,CAAC;AAKD;;;;;GAKG;AACH,MAAM,OAAO,oCAAqC,SAAQ,KAAK;IAE3C;IACA;IACA;IAHlB,YACkB,MAAc,EACd,GAAW,EACX,KAAiC;QAEjD,KAAK,CAAC,2CAA2C,KAAK,EAAE,CAAC,CAAC;QAJ1C,WAAM,GAAN,MAAM,CAAQ;QACd,QAAG,GAAH,GAAG,CAAQ;QACX,UAAK,GAAL,KAAK,CAA4B;QAGjD,IAAI,CAAC,IAAI,GAAG,sCAAsC,CAAC;IACrD,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,8BAA8B,CAC5C,QAAiD,EACjD,MAAuC;IAEvC,MAAM,UAAU,GAAG,kCAAkC,CAAC,QAAQ,CAAC,CAAC;IAChE,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,MAAM,IAAI,oCAAoC,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAC1F,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAOD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,MAAc,EACd,WAA+B,EAC/B,UAA6C,EAAE;IAE/C,IAAI,CAAC,WAAW;QAAE,OAAO,SAAS,CAAC;IACnC,IAAI,CAAC;QACH,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE,CAAC;QAChE,OAAO,kCAAkC,CAAC,QAAQ,CAAC,CAAC;IACtD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC;QAC3B,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,MAAc,EAAE,UAA8B;IACzE,OAAO,UAAU,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,UAAU,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;AACzD,CAAC","sourcesContent":["// Admin-SDK reads of a STAGED upload object (the client-written staging copy a\n// processor reads from). The accept-time verdict over the metadata is the pure\n// `verifyStagedUploadMetadata` in `@ttt-productions/media-schemas`.\n\nimport { isObjectNotFoundError } from \"./gcs-errors.js\";\nimport type { Bucket } from \"./storage-ops.js\";\n\n/** The stored-object metadata fields these reads use (the Admin SDK returns more). */\nexport interface StagedObjectMetadata {\n contentType?: string;\n size?: string | number;\n generation?: string | number;\n [field: string]: unknown;\n}\n\nexport type StagedUploadMetadataRead =\n | { found: true; metadata: StagedObjectMetadata }\n | { found: false };\n\n/**\n * Read a staged object's stored metadata (`contentType`, `size`, `generation`, …) for\n * `verifyStagedUploadMetadata`. A missing object is `{ found: false }`; any other read\n * failure throws.\n */\nexport async function readStagedUploadMetadata(bucket: Bucket, storagePath: string): Promise<StagedUploadMetadataRead> {\n try {\n const [metadata] = await bucket.file(storagePath).getMetadata();\n return { found: true, metadata };\n } catch (e) {\n if (isObjectNotFoundError(e)) return { found: false };\n throw e;\n }\n}\n\n/**\n * The staged object's generation from metadata the caller already fetched, as a string\n * (GCS generations exceed 2^53) — the one normalization `readStagedObjectGeneration`\n * applies, for a processor that already holds the object's metadata and must not read\n * it again. `undefined` when the metadata carries no generation (the emulator may not):\n * absent, `null`, or an empty string, which names no generation.\n */\nexport function stagedObjectGenerationFromMetadata(metadata: {\n generation?: string | number | null;\n}): string | undefined {\n const { generation } = metadata;\n if (generation === undefined || generation === null) return undefined;\n const value = String(generation);\n return value === \"\" ? undefined : value;\n}\n\n/** The stored-object metadata field an `UnreadableStorageObjectMetadataError` names. */\nexport type StorageObjectMetadataField = \"generation\" | \"size\";\n\n/**\n * A storage object whose metadata has no readable generation or byte size. GCS, the Storage\n * emulator, and a Storage finalize event always carry both, so this is an anomaly to surface,\n * never to paper over with a placeholder. The bucket and key are PROPERTIES, never message\n * text: an escaping error reaches monitoring, and an object key must not.\n */\nexport class UnreadableStorageObjectMetadataError extends Error {\n constructor(\n public readonly bucket: string,\n public readonly key: string,\n public readonly field: StorageObjectMetadataField,\n ) {\n super(`storage object metadata has no readable ${field}`);\n this.name = \"UnreadableStorageObjectMetadataError\";\n }\n}\n\n/**\n * The object's generation from metadata the caller already holds, for a site that cannot\n * proceed without it (a hold key, an evidence record, a pinned read). Throws\n * `UnreadableStorageObjectMetadataError` (field `generation`) when the metadata names none —\n * the same normalization as `stagedObjectGenerationFromMetadata`, with no fallback value.\n */\nexport function requireStorageObjectGeneration(\n metadata: { generation?: string | number | null },\n object: { bucket: string; key: string },\n): string {\n const generation = stagedObjectGenerationFromMetadata(metadata);\n if (generation === undefined) {\n throw new UnreadableStorageObjectMetadataError(object.bucket, object.key, \"generation\");\n }\n return generation;\n}\n\nexport interface ReadStagedObjectGenerationOptions {\n /** Called when the generation cannot be read (the caller logs it); reads then stay unpinned. */\n onReadFailure?: (error: unknown) => void;\n}\n\n/**\n * The staged object's current generation, as a string (GCS generations exceed 2^53).\n *\n * This is the one value that pins every later read of the staged bytes — the processing\n * download, a moderation scan, a hash — to the SAME immutable object, so \"processed\n * bytes == scanned bytes == hashed bytes\" holds even if the staging path were\n * overwritten (a pinned read resolves exactly the captured generation). Returns\n * `undefined` when no path is given, the object reports no generation (the emulator may\n * not), or the read fails — best effort: callers fall back to unpinned reads, and a\n * create-only staging rule stays the primary defense.\n */\nexport async function readStagedObjectGeneration(\n bucket: Bucket,\n storagePath: string | undefined,\n options: ReadStagedObjectGenerationOptions = {},\n): Promise<string | undefined> {\n if (!storagePath) return undefined;\n try {\n const [metadata] = await bucket.file(storagePath).getMetadata();\n return stagedObjectGenerationFromMetadata(metadata);\n } catch (e) {\n options.onReadFailure?.(e);\n return undefined;\n }\n}\n\n/**\n * A `gs://` URI pinned to a captured generation (`gs://bucket/path#<generation>`), so a\n * service reading by URI (a moderation scan) reads the same bytes the processor did.\n * Without a generation it is the bare URI.\n */\nexport function pinnedGcsUri(gcsUri: string, generation: string | undefined): string {\n return generation ? `${gcsUri}#${generation}` : gcsUri;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttt-productions/media-processing-core",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.10",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/ttt-productions/ttt-packages.git",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"prepublishOnly": "npm run clean && npm run build"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@ttt-productions/media-schemas": "^0.14.
|
|
34
|
+
"@ttt-productions/media-schemas": "^0.14.7",
|
|
35
35
|
"aws4fetch": "^1.0.20",
|
|
36
36
|
"sharp": "^0.35.3",
|
|
37
37
|
"zod": "^4.4.3"
|