vidspotai-shared 1.0.122-dev.0 → 1.0.122
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/lib/libs/storage/GcsBackend.d.ts.map +1 -1
- package/lib/libs/storage/GcsBackend.js +12 -2
- package/lib/libs/storage/cdnUrl.d.ts +12 -0
- package/lib/libs/storage/cdnUrl.d.ts.map +1 -1
- package/lib/libs/storage/cdnUrl.js +16 -0
- package/lib/models/assetPool.model.d.ts +49 -0
- package/lib/models/assetPool.model.d.ts.map +1 -1
- package/lib/models/assetPool.model.js +41 -0
- package/lib/services/aiGen/providers/bytedance/bytedance.service.d.ts.map +1 -1
- package/lib/services/aiGen/providers/bytedance/bytedance.service.js +4 -0
- package/lib/services/aiGen/providers/google/google.service.d.ts.map +1 -1
- package/lib/services/aiGen/providers/google/google.service.js +5 -0
- package/lib/services/aiGen/providers/pixverse/pixverse.service.d.ts.map +1 -1
- package/lib/services/aiGen/providers/pixverse/pixverse.service.js +6 -1
- package/lib/services/assetPool/index.d.ts +2 -0
- package/lib/services/assetPool/index.d.ts.map +1 -0
- package/lib/services/assetPool/index.js +17 -0
- package/lib/services/assetPool/snapshots.service.d.ts +58 -0
- package/lib/services/assetPool/snapshots.service.d.ts.map +1 -0
- package/lib/services/assetPool/snapshots.service.js +99 -0
- package/lib/services/gcp/uploadAudioBuffer.d.ts.map +1 -1
- package/lib/services/gcp/uploadAudioBuffer.js +5 -0
- package/lib/services/index.d.ts +1 -0
- package/lib/services/index.d.ts.map +1 -1
- package/lib/services/index.js +1 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GcsBackend.d.ts","sourceRoot":"","sources":["../../../src/libs/storage/GcsBackend.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"GcsBackend.d.ts","sourceRoot":"","sources":["../../../src/libs/storage/GcsBackend.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAMxD,qBAAa,UAAW,YAAW,eAAe;IAChD,QAAQ,CAAC,IAAI,SAAS;IAEhB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpE,aAAa,CACjB,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC;IAOZ,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAO3C,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGzC"}
|
|
@@ -2,8 +2,18 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.GcsBackend = void 0;
|
|
4
4
|
/**
|
|
5
|
-
* Google Cloud Storage backend —
|
|
6
|
-
*
|
|
5
|
+
* Google Cloud Storage backend — dual role since the R2-primary flip
|
|
6
|
+
* (2026-09-22, MediaStorage.ts §Stage 2).
|
|
7
|
+
* =====================================================================
|
|
8
|
+
*
|
|
9
|
+
* For anything written via `MediaStorage.put`/`putFromFile` (the vast
|
|
10
|
+
* majority of media), this class is used ONLY as `urlMinter` — it mints the
|
|
11
|
+
* signed-URL shape below but never actually stores those bytes; R2 is the
|
|
12
|
+
* sole byte store. For a handful of bespoke pipeline paths that still write
|
|
13
|
+
* real bytes here directly (see MediaStorage.ts's class doc and
|
|
14
|
+
* notes/R2_MEDIA_MIGRATION_PLAN.md §10 for the full list + reasoning), this
|
|
15
|
+
* IS the genuine system-of-record and `MediaStorage.mirrorBytes`/etc. make a
|
|
16
|
+
* best-effort R2 copy afterward.
|
|
7
17
|
*
|
|
8
18
|
* Wraps the Firebase Admin bucket. The canonical object path IS the GCS key
|
|
9
19
|
* (identity mapping). Read URLs are the far-future signed URLs used everywhere
|
|
@@ -50,4 +50,16 @@ export declare function toCdnUrl(url: string, opts?: {
|
|
|
50
50
|
* there's no local `fetch()` call to wrap.
|
|
51
51
|
*/
|
|
52
52
|
export declare function fetchOwnMedia(url: string, init?: RequestInit): Promise<Response>;
|
|
53
|
+
/**
|
|
54
|
+
* Permanent public CDN URL for an object `put`/`putFromFile` wrote to R2 —
|
|
55
|
+
* for public content (e.g. the scraped assetPool) that's stored as a final
|
|
56
|
+
* URL rather than rewritten by the frontend's `cdn()` at render time.
|
|
57
|
+
*
|
|
58
|
+
* Always routes through the prod BUCKET token, in every env: the Worker only
|
|
59
|
+
* resolves `/gcs-pub/<that bucket>/`, and R2 keys carry no bucket name, so dev
|
|
60
|
+
* writes land in the same R2 namespace and resolve fine. A dev-bucket-shaped
|
|
61
|
+
* URL (`storage.googleapis.com/vidspot-dev…`) is never rewritten by `cdn()`
|
|
62
|
+
* and 404s against GCS, which no longer holds the bytes.
|
|
63
|
+
*/
|
|
64
|
+
export declare function publicCdnUrl(objectPath: string): string;
|
|
53
65
|
//# sourceMappingURL=cdnUrl.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cdnUrl.d.ts","sourceRoot":"","sources":["../../../src/libs/storage/cdnUrl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAeH,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEnD;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CACtB,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,eAAe,CAAA;CAAE,GACtC,MAAM,CAeR;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAEhF"}
|
|
1
|
+
{"version":3,"file":"cdnUrl.d.ts","sourceRoot":"","sources":["../../../src/libs/storage/cdnUrl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAeH,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEnD;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CACtB,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,eAAe,CAAA;CAAE,GACtC,MAAM,CAeR;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAEhF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAGvD"}
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
16
|
exports.toCdnUrl = toCdnUrl;
|
|
17
17
|
exports.fetchOwnMedia = fetchOwnMedia;
|
|
18
|
+
exports.publicCdnUrl = publicCdnUrl;
|
|
18
19
|
const FIREBASE_STORAGE_HOST = "https://firebasestorage.googleapis.com";
|
|
19
20
|
const GCS_HOST = "https://storage.googleapis.com";
|
|
20
21
|
const BUCKET = "vidspot-firebase.firebasestorage.app";
|
|
@@ -75,3 +76,18 @@ function toCdnUrl(url, opts) {
|
|
|
75
76
|
function fetchOwnMedia(url, init) {
|
|
76
77
|
return fetch(toCdnUrl(url, { visibility: "private" }), init);
|
|
77
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* Permanent public CDN URL for an object `put`/`putFromFile` wrote to R2 —
|
|
81
|
+
* for public content (e.g. the scraped assetPool) that's stored as a final
|
|
82
|
+
* URL rather than rewritten by the frontend's `cdn()` at render time.
|
|
83
|
+
*
|
|
84
|
+
* Always routes through the prod BUCKET token, in every env: the Worker only
|
|
85
|
+
* resolves `/gcs-pub/<that bucket>/`, and R2 keys carry no bucket name, so dev
|
|
86
|
+
* writes land in the same R2 namespace and resolve fine. A dev-bucket-shaped
|
|
87
|
+
* URL (`storage.googleapis.com/vidspot-dev…`) is never rewritten by `cdn()`
|
|
88
|
+
* and 404s against GCS, which no longer holds the bytes.
|
|
89
|
+
*/
|
|
90
|
+
function publicCdnUrl(objectPath) {
|
|
91
|
+
const encoded = objectPath.split("/").map(encodeURIComponent).join("/");
|
|
92
|
+
return `${cdnBase()}/gcs-pub/${BUCKET}/${encoded}`;
|
|
93
|
+
}
|
|
@@ -33,10 +33,26 @@ export interface IAssetPoolModel {
|
|
|
33
33
|
mediaUrl: string;
|
|
34
34
|
/** Poster still for videos (first-frame JPEG); absent for images. */
|
|
35
35
|
posterUrl?: string;
|
|
36
|
+
/**
|
|
37
|
+
* 640px-wide WebP (`pool/thumbs/<sha1>.webp`) for grid cards — the image
|
|
38
|
+
* itself, or a video's first frame. Cards load this directly instead of
|
|
39
|
+
* `mediaUrl`: scraped originals run 3–8MB, and pushing dozens of those
|
|
40
|
+
* through next/image at once overran its 7s upstream fetch timeout, so
|
|
41
|
+
* cards rendered as broken images (2026-09-28).
|
|
42
|
+
*/
|
|
43
|
+
thumbUrl?: string;
|
|
36
44
|
/** R2 object key of `mediaUrl`. */
|
|
37
45
|
r2Key: string;
|
|
38
46
|
prompt?: string;
|
|
39
47
|
model?: string;
|
|
48
|
+
/**
|
|
49
|
+
* One of OUR generation model keys (e.g. "kling-avatar"), set only when the
|
|
50
|
+
* item was made with a model we offer — the curated Content Creator clips.
|
|
51
|
+
* `model` is the scraped label and is never used to preselect a model.
|
|
52
|
+
*/
|
|
53
|
+
modelKey?: string;
|
|
54
|
+
/** Per-doc override of where Recreate opens; see recreateToolOf(). */
|
|
55
|
+
recreateTool?: TAssetPoolRecreateTool;
|
|
40
56
|
/** e.g. "higgsfield.ai" / "imagine.art" / "openart.ai". */
|
|
41
57
|
platform: string;
|
|
42
58
|
/** tmp/gallery/<source> folder + record id — re-run provenance. */
|
|
@@ -45,4 +61,37 @@ export interface IAssetPoolModel {
|
|
|
45
61
|
rank: number;
|
|
46
62
|
createdAt: FieldValue;
|
|
47
63
|
}
|
|
64
|
+
/** The generation tool a pool card's Recreate opens. */
|
|
65
|
+
export type TAssetPoolRecreateTool = "video" | "image" | "avatar";
|
|
66
|
+
/**
|
|
67
|
+
* Where Recreate sends a pool item, decided here so every surface (gallery,
|
|
68
|
+
* Inspirations tabs, Content Library) routes it the same way. `avatar`-tagged
|
|
69
|
+
* items open the Avatar tool (a portrait becomes the face image); everything
|
|
70
|
+
* else — posters, ads and film stills included — opens the tool for its media
|
|
71
|
+
* type. A doc's own `recreateTool` wins when set, then its `modelKey`.
|
|
72
|
+
*/
|
|
73
|
+
export declare function recreateToolOf(a: Pick<IAssetPoolModel, "tags" | "mediaType" | "recreateTool" | "modelKey">): TAssetPoolRecreateTool;
|
|
74
|
+
/** One pool item as `GET /v1/community/pool` returns it (and as the static
|
|
75
|
+
* first-page snapshots store it — both go through toAssetPoolApiItem so the
|
|
76
|
+
* frontend never sees two shapes). */
|
|
77
|
+
export interface IAssetPoolApiItem {
|
|
78
|
+
id: string;
|
|
79
|
+
type: "pool";
|
|
80
|
+
mediaType: IAssetPoolModel["mediaType"];
|
|
81
|
+
mediaUrl: string;
|
|
82
|
+
posterUrl?: string;
|
|
83
|
+
thumbUrl?: string;
|
|
84
|
+
tags: string[];
|
|
85
|
+
orientation: IAssetPoolModel["orientation"];
|
|
86
|
+
width?: number;
|
|
87
|
+
height?: number;
|
|
88
|
+
aspectRatio?: string;
|
|
89
|
+
durationSec?: number;
|
|
90
|
+
prompt?: string;
|
|
91
|
+
model?: string;
|
|
92
|
+
modelKey?: string;
|
|
93
|
+
recreateTool: TAssetPoolRecreateTool;
|
|
94
|
+
platform: string;
|
|
95
|
+
}
|
|
96
|
+
export declare function toAssetPoolApiItem(id: string, a: IAssetPoolModel): IAssetPoolApiItem;
|
|
48
97
|
//# sourceMappingURL=assetPool.model.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assetPool.model.d.ts","sourceRoot":"","sources":["../../src/models/assetPool.model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEtD;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,uHAS1B,CAAC;AACX,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5E;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,SAAS,GAAG,MAAM,CAAC;IAC3B,SAAS,EAAE,OAAO,GAAG,OAAO,CAAC;IAC7B,iEAAiE;IACjE,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,WAAW,EAAE,UAAU,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,UAAU,CAAC;CACvB"}
|
|
1
|
+
{"version":3,"file":"assetPool.model.d.ts","sourceRoot":"","sources":["../../src/models/assetPool.model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEtD;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,uHAS1B,CAAC;AACX,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5E;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,SAAS,GAAG,MAAM,CAAC;IAC3B,SAAS,EAAE,OAAO,GAAG,OAAO,CAAC;IAC7B,iEAAiE;IACjE,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,WAAW,EAAE,UAAU,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,YAAY,CAAC,EAAE,sBAAsB,CAAC;IACtC,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,UAAU,CAAC;CACvB;AAED,wDAAwD;AACxD,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,CAAC;AAElE;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,CAAC,EAAE,IAAI,CAAC,eAAe,EAAE,MAAM,GAAG,WAAW,GAAG,cAAc,GAAG,UAAU,CAAC,GAC3E,sBAAsB,CAOxB;AAED;;uCAEuC;AACvC,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,eAAe,CAAC,WAAW,CAAC,CAAC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,WAAW,EAAE,eAAe,CAAC,aAAa,CAAC,CAAC;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,sBAAsB,CAAC;IACrC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,eAAe,GAAG,iBAAiB,CAoBpF"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ASSET_POOL_SURFACE_TAGS = void 0;
|
|
4
|
+
exports.recreateToolOf = recreateToolOf;
|
|
5
|
+
exports.toAssetPoolApiItem = toAssetPoolApiItem;
|
|
4
6
|
/**
|
|
5
7
|
* Surface tags — which product surface may pull an asset. One asset can serve
|
|
6
8
|
* several (a talking-head clip is both `avatar` and `video-inspiration`).
|
|
@@ -17,3 +19,42 @@ exports.ASSET_POOL_SURFACE_TAGS = [
|
|
|
17
19
|
"film",
|
|
18
20
|
"content-creator",
|
|
19
21
|
];
|
|
22
|
+
/**
|
|
23
|
+
* Where Recreate sends a pool item, decided here so every surface (gallery,
|
|
24
|
+
* Inspirations tabs, Content Library) routes it the same way. `avatar`-tagged
|
|
25
|
+
* items open the Avatar tool (a portrait becomes the face image); everything
|
|
26
|
+
* else — posters, ads and film stills included — opens the tool for its media
|
|
27
|
+
* type. A doc's own `recreateTool` wins when set, then its `modelKey`.
|
|
28
|
+
*/
|
|
29
|
+
function recreateToolOf(a) {
|
|
30
|
+
if (a.recreateTool)
|
|
31
|
+
return a.recreateTool;
|
|
32
|
+
// A known model key is authoritative: a Sora clip that merely shows a
|
|
33
|
+
// person (and so got the descriptive `avatar` tag) still recreates in Video.
|
|
34
|
+
if (a.modelKey)
|
|
35
|
+
return a.modelKey.includes("avatar") ? "avatar" : a.mediaType === "video" ? "video" : "image";
|
|
36
|
+
if (a.tags.includes("avatar"))
|
|
37
|
+
return "avatar";
|
|
38
|
+
return a.mediaType === "video" ? "video" : "image";
|
|
39
|
+
}
|
|
40
|
+
function toAssetPoolApiItem(id, a) {
|
|
41
|
+
return {
|
|
42
|
+
id,
|
|
43
|
+
type: "pool",
|
|
44
|
+
mediaType: a.mediaType,
|
|
45
|
+
mediaUrl: a.mediaUrl,
|
|
46
|
+
posterUrl: a.posterUrl,
|
|
47
|
+
thumbUrl: a.thumbUrl,
|
|
48
|
+
tags: a.tags,
|
|
49
|
+
orientation: a.orientation,
|
|
50
|
+
width: a.width,
|
|
51
|
+
height: a.height,
|
|
52
|
+
aspectRatio: a.aspectRatio,
|
|
53
|
+
durationSec: a.durationSec,
|
|
54
|
+
prompt: a.prompt,
|
|
55
|
+
model: a.model,
|
|
56
|
+
modelKey: a.modelKey,
|
|
57
|
+
recreateTool: recreateToolOf(a),
|
|
58
|
+
platform: a.platform,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bytedance.service.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/bytedance/bytedance.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,UAAU,CAAC;AAWlB,qBAAa,gBAAiB,SAAQ,wBAAwB;IAC5D,OAAO,CAAC,QAAQ,CAAC,OAAO,CACsD;IAI9E,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,WAAW;IAIb,aAAa,CACjB,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,qBAAqB,CAAC;IA2M3B,gBAAgB,CAAC,EACrB,IAAI,EACJ,cAAc,EACd,cAAyB,GAC1B,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"bytedance.service.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/bytedance/bytedance.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,UAAU,CAAC;AAWlB,qBAAa,gBAAiB,SAAQ,wBAAwB;IAC5D,OAAO,CAAC,QAAQ,CAAC,OAAO,CACsD;IAI9E,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,WAAW;IAIb,aAAa,CACjB,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,qBAAqB,CAAC;IA2M3B,gBAAgB,CAAC,EACrB,IAAI,EACJ,cAAc,EACd,cAAyB,GAC1B,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAqIjD,aAAa,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM;CAyEjD"}
|
|
@@ -265,6 +265,10 @@ class ByteDanceService extends baseAiGenProvider_service_1.BaseAiGenProviderServ
|
|
|
265
265
|
}
|
|
266
266
|
const buffer = Buffer.from(await videoResp.arrayBuffer());
|
|
267
267
|
// ---- Upload to Firebase Storage (PUBLIC URL) ----
|
|
268
|
+
// GCS-PRIMARY (not mediaStorage.put): returns a public
|
|
269
|
+
// firebaseStorageDownloadTokens URL (see publicVideoUrl below), a
|
|
270
|
+
// different shape than mediaStorage.put()'s signed-URL minter produces.
|
|
271
|
+
// See notes/R2_MEDIA_MIGRATION_PLAN.md §10.
|
|
268
272
|
const filePath = `${outputFilePath}/${outputFilename}.mp4`;
|
|
269
273
|
const bucket = (0, firebase_1.getBucket)();
|
|
270
274
|
const file = bucket.file(filePath);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"google.service.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/google/google.service.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,UAAU,CAAC;AA+ElB,qBAAa,aAAc,SAAQ,wBAAwB;IAKzD,OAAO,CAAC,EAAE,CAAc;IACxB,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAK;;IAQ/C;;;;;;;;;OASG;IACG,YAAY,CAChB,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAAC,oBAAoB,CAAC;IAoChC;;;;;OAKG;IACH,OAAO,CAAC,eAAe;IAoCvB;;;;OAIG;YACW,kBAAkB;IAsC1B,aAAa,CACjB,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,qBAAqB,CAAC;IAgU3B,gBAAgB,CAAC,EACrB,IAAI,EACJ,cAAc,EACd,cAAyB,GAC1B,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"google.service.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/google/google.service.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,UAAU,CAAC;AA+ElB,qBAAa,aAAc,SAAQ,wBAAwB;IAKzD,OAAO,CAAC,EAAE,CAAc;IACxB,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAK;;IAQ/C;;;;;;;;;OASG;IACG,YAAY,CAChB,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAAC,oBAAoB,CAAC;IAoChC;;;;;OAKG;IACH,OAAO,CAAC,eAAe;IAoCvB;;;;OAIG;YACW,kBAAkB;IAsC1B,aAAa,CACjB,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,qBAAqB,CAAC;IAgU3B,gBAAgB,CAAC,EACrB,IAAI,EACJ,cAAc,EACd,cAAyB,GAC1B,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAwK3C,aAAa,CACjB,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,qBAAqB,CAAC;YAiBnB,cAAc;IAqK5B;;;;;;OAMG;IACH;;;;OAIG;IACG,aAAa,CACjB,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,qBAAqB,CAAC;IAIjC,aAAa,CAAC,EAAE,QAAQ,EAAE,QAAY,EAAE,UAAmB,EAAE,SAAiB,EAAE,SAAa,EAAE,SAAS,EAAE,WAAW,EAAE,EAAE,iBAAiB,GAAG,MAAM;CA8BpJ"}
|
|
@@ -544,6 +544,11 @@ class GoogleService extends baseAiGenProvider_service_1.BaseAiGenProviderService
|
|
|
544
544
|
// we only read a fully-written file, (2) a structural ftyp+moov check, and
|
|
545
545
|
// (3) a stored-vs-local size match after upload. Any failure re-runs the
|
|
546
546
|
// whole download instead of shipping corruption.
|
|
547
|
+
//
|
|
548
|
+
// GCS-PRIMARY (not mediaStorage.put): the size-verified integrity guard
|
|
549
|
+
// above needs GCS's own writeFromFile + getMetadata size readback: R2
|
|
550
|
+
// gets a best-effort mirror via mediaStorage.mirrorFromFile once the
|
|
551
|
+
// GCS copy is confirmed intact. See notes/R2_MEDIA_MIGRATION_PLAN.md §10.
|
|
547
552
|
const MAX_FETCH_ATTEMPTS = 3;
|
|
548
553
|
let uploaded = false;
|
|
549
554
|
for (let attempt = 1; attempt <= MAX_FETCH_ATTEMPTS && !uploaded; attempt++) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pixverse.service.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/pixverse/pixverse.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,UAAU,CAAC;AAgGlB,qBAAa,eAAgB,SAAQ,wBAAwB;IAC3D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkD;IAK1E;;;;;;OAMG;YACW,WAAW;IAkDnB,aAAa,CACjB,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,qBAAqB,CAAC;IAyL3B,gBAAgB,CAAC,EACrB,IAAI,EACJ,cAAc,EACd,cAAyB,GAC1B,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"pixverse.service.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/pixverse/pixverse.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,UAAU,CAAC;AAgGlB,qBAAa,eAAgB,SAAQ,wBAAwB;IAC3D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkD;IAK1E;;;;;;OAMG;YACW,WAAW;IAkDnB,aAAa,CACjB,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,qBAAqB,CAAC;IAyL3B,gBAAgB,CAAC,EACrB,IAAI,EACJ,cAAc,EACd,cAAyB,GAC1B,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAyHjD,aAAa,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM;CAkDjD"}
|
|
@@ -363,7 +363,12 @@ class PixVerseService extends baseAiGenProvider_service_1.BaseAiGenProviderServi
|
|
|
363
363
|
if (durationSec === undefined) {
|
|
364
364
|
logger_1.logger.warn("PixVerse: could not read delivered duration from the downloaded clip — billing will use the requested duration", { task, bytes: buffer.length });
|
|
365
365
|
}
|
|
366
|
-
// ---- Upload to Firebase ----
|
|
366
|
+
// ---- Upload to Firebase (PUBLIC URL) ----
|
|
367
|
+
// GCS-PRIMARY (not mediaStorage.put): returns a public
|
|
368
|
+
// firebaseStorageDownloadTokens URL (see publicVideoUrl below), a
|
|
369
|
+
// different shape than mediaStorage.put()'s signed-URL minter produces
|
|
370
|
+
// — same reason bytedance.service.ts stays off mediaStorage.put() too.
|
|
371
|
+
// See notes/R2_MEDIA_MIGRATION_PLAN.md §10.
|
|
367
372
|
const filePath = `${outputFilePath}/${outputFilename}.mp4`;
|
|
368
373
|
const bucket = (0, firebase_1.getBucket)();
|
|
369
374
|
const file = bucket.file(filePath);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/assetPool/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./snapshots.service"), exports);
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { type IAssetPoolApiItem } from "../../models/assetPool.model";
|
|
2
|
+
/**
|
|
3
|
+
* Static, pre-paginated snapshots of the asset pool — what lets every
|
|
4
|
+
* Inspirations tab / gallery render and infinite-scroll with zero per-visitor
|
|
5
|
+
* API calls or Firestore reads. Scraped content changes rarely, so the whole
|
|
6
|
+
* feed is written out as files once per pool change instead of queried per view.
|
|
7
|
+
*
|
|
8
|
+
* pool/snapshots/<projectId>/current.json ← pointer
|
|
9
|
+
* pool/snapshots/<projectId>/<version>/<tag>.<kind>.<page>.json ← { items }
|
|
10
|
+
*
|
|
11
|
+
* The frontend reads current.json + page 0 of each feed at `next build` (baked
|
|
12
|
+
* into the page — see wt-dev-frontend src/lib/poolSnapshot.ts), then fetches
|
|
13
|
+
* page 1, 2, … straight from the CDN as the user scrolls. Page N holds exactly
|
|
14
|
+
* what `GET /v1/community/pool?tag=&mediaType=` would return for that page
|
|
15
|
+
* (same rank order, same toAssetPoolApiItem shape), so the API stays a
|
|
16
|
+
* drop-in fallback.
|
|
17
|
+
*
|
|
18
|
+
* Every write goes to a fresh `<version>` folder, so page files are immutable
|
|
19
|
+
* — exactly what the CDN Worker's 1-year immutable edge cache on gcs-pub
|
|
20
|
+
* assumes. Only current.json is overwritten; readers cache-bust it with a
|
|
21
|
+
* query param (the Worker's edge cache key includes the query string, its R2
|
|
22
|
+
* lookup ignores it). Old versions are deliberately NOT deleted: an already
|
|
23
|
+
* deployed build keeps paging through the version it was built against until
|
|
24
|
+
* the next deploy. They're tiny (a few MB per version).
|
|
25
|
+
*
|
|
26
|
+
* Keyed by Firebase project because dev and prod share one R2 bucket and R2
|
|
27
|
+
* keys carry no bucket name. Regenerate after anything that changes the pool
|
|
28
|
+
* (the loader does it itself; thumbnail backfill / retag: run
|
|
29
|
+
* scripts/writeAssetPoolSnapshots.ts), then redeploy the frontend to bake it.
|
|
30
|
+
*/
|
|
31
|
+
export declare const ASSET_POOL_SNAPSHOT_PAGE_SIZE = 24;
|
|
32
|
+
export declare const ASSET_POOL_SNAPSHOT_KINDS: readonly ["all", "image", "video"];
|
|
33
|
+
export type TAssetPoolSnapshotKind = (typeof ASSET_POOL_SNAPSHOT_KINDS)[number];
|
|
34
|
+
export interface IAssetPoolSnapshotManifest {
|
|
35
|
+
version: string;
|
|
36
|
+
generatedAt: string;
|
|
37
|
+
pageSize: number;
|
|
38
|
+
/** Keyed `<tag>.<kind>`. Feeds with no items are omitted. */
|
|
39
|
+
feeds: Record<string, {
|
|
40
|
+
pages: number;
|
|
41
|
+
total: number;
|
|
42
|
+
}>;
|
|
43
|
+
}
|
|
44
|
+
export interface IAssetPoolSnapshotPage {
|
|
45
|
+
items: IAssetPoolApiItem[];
|
|
46
|
+
}
|
|
47
|
+
export declare function assetPoolSnapshotRoot(projectId: string): string;
|
|
48
|
+
export declare function assetPoolSnapshotPageKey(projectId: string, version: string, tag: string, kind: TAssetPoolSnapshotKind, page: number): string;
|
|
49
|
+
/**
|
|
50
|
+
* Writes a complete new snapshot version for `projectId` and flips
|
|
51
|
+
* current.json to it last, so a reader never sees a pointer to a half-written
|
|
52
|
+
* version. Returns the manifest and its public URL.
|
|
53
|
+
*/
|
|
54
|
+
export declare function writeAssetPoolSnapshots(projectId: string): Promise<{
|
|
55
|
+
manifest: IAssetPoolSnapshotManifest;
|
|
56
|
+
manifestUrl: string;
|
|
57
|
+
}>;
|
|
58
|
+
//# sourceMappingURL=snapshots.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshots.service.d.ts","sourceRoot":"","sources":["../../../src/services/assetPool/snapshots.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,iBAAiB,EAEvB,MAAM,8BAA8B,CAAC;AAGtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAChD,eAAO,MAAM,yBAAyB,oCAAqC,CAAC;AAC5E,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhF,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACzD;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,iBAAiB,EAAE,CAAC;CAC5B;AAED,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,sBAAsB,EAC5B,IAAI,EAAE,MAAM,GACX,MAAM,CAER;AAQD;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,QAAQ,EAAE,0BAA0B,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CA8CxE"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ASSET_POOL_SNAPSHOT_KINDS = exports.ASSET_POOL_SNAPSHOT_PAGE_SIZE = void 0;
|
|
4
|
+
exports.assetPoolSnapshotRoot = assetPoolSnapshotRoot;
|
|
5
|
+
exports.assetPoolSnapshotPageKey = assetPoolSnapshotPageKey;
|
|
6
|
+
exports.writeAssetPoolSnapshots = writeAssetPoolSnapshots;
|
|
7
|
+
const cdnUrl_1 = require("../../libs/storage/cdnUrl");
|
|
8
|
+
const MediaStorage_1 = require("../../libs/storage/MediaStorage");
|
|
9
|
+
const assetPool_model_1 = require("../../models/assetPool.model");
|
|
10
|
+
const firestore_service_1 = require("../firestore.service");
|
|
11
|
+
/**
|
|
12
|
+
* Static, pre-paginated snapshots of the asset pool — what lets every
|
|
13
|
+
* Inspirations tab / gallery render and infinite-scroll with zero per-visitor
|
|
14
|
+
* API calls or Firestore reads. Scraped content changes rarely, so the whole
|
|
15
|
+
* feed is written out as files once per pool change instead of queried per view.
|
|
16
|
+
*
|
|
17
|
+
* pool/snapshots/<projectId>/current.json ← pointer
|
|
18
|
+
* pool/snapshots/<projectId>/<version>/<tag>.<kind>.<page>.json ← { items }
|
|
19
|
+
*
|
|
20
|
+
* The frontend reads current.json + page 0 of each feed at `next build` (baked
|
|
21
|
+
* into the page — see wt-dev-frontend src/lib/poolSnapshot.ts), then fetches
|
|
22
|
+
* page 1, 2, … straight from the CDN as the user scrolls. Page N holds exactly
|
|
23
|
+
* what `GET /v1/community/pool?tag=&mediaType=` would return for that page
|
|
24
|
+
* (same rank order, same toAssetPoolApiItem shape), so the API stays a
|
|
25
|
+
* drop-in fallback.
|
|
26
|
+
*
|
|
27
|
+
* Every write goes to a fresh `<version>` folder, so page files are immutable
|
|
28
|
+
* — exactly what the CDN Worker's 1-year immutable edge cache on gcs-pub
|
|
29
|
+
* assumes. Only current.json is overwritten; readers cache-bust it with a
|
|
30
|
+
* query param (the Worker's edge cache key includes the query string, its R2
|
|
31
|
+
* lookup ignores it). Old versions are deliberately NOT deleted: an already
|
|
32
|
+
* deployed build keeps paging through the version it was built against until
|
|
33
|
+
* the next deploy. They're tiny (a few MB per version).
|
|
34
|
+
*
|
|
35
|
+
* Keyed by Firebase project because dev and prod share one R2 bucket and R2
|
|
36
|
+
* keys carry no bucket name. Regenerate after anything that changes the pool
|
|
37
|
+
* (the loader does it itself; thumbnail backfill / retag: run
|
|
38
|
+
* scripts/writeAssetPoolSnapshots.ts), then redeploy the frontend to bake it.
|
|
39
|
+
*/
|
|
40
|
+
exports.ASSET_POOL_SNAPSHOT_PAGE_SIZE = 24; // = the frontend feed's PAGE_LIMIT
|
|
41
|
+
exports.ASSET_POOL_SNAPSHOT_KINDS = ["all", "image", "video"];
|
|
42
|
+
function assetPoolSnapshotRoot(projectId) {
|
|
43
|
+
return `pool/snapshots/${projectId}`;
|
|
44
|
+
}
|
|
45
|
+
function assetPoolSnapshotPageKey(projectId, version, tag, kind, page) {
|
|
46
|
+
return `${assetPoolSnapshotRoot(projectId)}/${version}/${tag}.${kind}.${page}.json`;
|
|
47
|
+
}
|
|
48
|
+
const WRITE_CONCURRENCY = 16;
|
|
49
|
+
async function putJson(key, value) {
|
|
50
|
+
await MediaStorage_1.mediaStorage.put(key, Buffer.from(JSON.stringify(value)), "application/json");
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Writes a complete new snapshot version for `projectId` and flips
|
|
54
|
+
* current.json to it last, so a reader never sees a pointer to a half-written
|
|
55
|
+
* version. Returns the manifest and its public URL.
|
|
56
|
+
*/
|
|
57
|
+
async function writeAssetPoolSnapshots(projectId) {
|
|
58
|
+
const generatedAt = new Date().toISOString();
|
|
59
|
+
const version = generatedAt.replace(/[:.]/g, "-");
|
|
60
|
+
const manifest = {
|
|
61
|
+
version,
|
|
62
|
+
generatedAt,
|
|
63
|
+
pageSize: exports.ASSET_POOL_SNAPSHOT_PAGE_SIZE,
|
|
64
|
+
feeds: {},
|
|
65
|
+
};
|
|
66
|
+
const writes = [];
|
|
67
|
+
for (const tag of assetPool_model_1.ASSET_POOL_SURFACE_TAGS) {
|
|
68
|
+
// One read per tag; the per-kind feeds are rank-ordered subsequences of it,
|
|
69
|
+
// identical to what the API's `mediaType ==` + `orderBy rank` query returns.
|
|
70
|
+
const snap = await firestore_service_1.FirestoreService.assetPoolCol.where("tags", "array-contains", tag)
|
|
71
|
+
.orderBy("rank", "asc")
|
|
72
|
+
.get();
|
|
73
|
+
const all = snap.docs.map((d) => (0, assetPool_model_1.toAssetPoolApiItem)(d.id, d.data()));
|
|
74
|
+
for (const kind of exports.ASSET_POOL_SNAPSHOT_KINDS) {
|
|
75
|
+
const items = kind === "all" ? all : all.filter((i) => i.mediaType === kind);
|
|
76
|
+
if (items.length === 0)
|
|
77
|
+
continue;
|
|
78
|
+
const pages = Math.ceil(items.length / exports.ASSET_POOL_SNAPSHOT_PAGE_SIZE);
|
|
79
|
+
manifest.feeds[`${tag}.${kind}`] = { pages, total: items.length };
|
|
80
|
+
for (let p = 0; p < pages; p++) {
|
|
81
|
+
writes.push({
|
|
82
|
+
key: assetPoolSnapshotPageKey(projectId, version, tag, kind, p),
|
|
83
|
+
value: {
|
|
84
|
+
items: items.slice(p * exports.ASSET_POOL_SNAPSHOT_PAGE_SIZE, (p + 1) * exports.ASSET_POOL_SNAPSHOT_PAGE_SIZE),
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
let next = 0;
|
|
91
|
+
await Promise.all(Array.from({ length: WRITE_CONCURRENCY }, async () => {
|
|
92
|
+
for (let w = writes[next++]; w; w = writes[next++]) {
|
|
93
|
+
await putJson(w.key, w.value);
|
|
94
|
+
}
|
|
95
|
+
}));
|
|
96
|
+
const manifestKey = `${assetPoolSnapshotRoot(projectId)}/current.json`;
|
|
97
|
+
await putJson(manifestKey, manifest);
|
|
98
|
+
return { manifest, manifestUrl: (0, cdnUrl_1.publicCdnUrl)(manifestKey) };
|
|
99
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uploadAudioBuffer.d.ts","sourceRoot":"","sources":["../../../src/services/gcp/uploadAudioBuffer.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;GAUG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,WAAW,GAAE,MAAqB,GACjC,OAAO,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"uploadAudioBuffer.d.ts","sourceRoot":"","sources":["../../../src/services/gcp/uploadAudioBuffer.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;GAUG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,WAAW,GAAE,MAAqB,GACjC,OAAO,CAAC,MAAM,CAAC,CAmBjB"}
|
|
@@ -16,6 +16,11 @@ const storage_1 = require("../../libs/storage");
|
|
|
16
16
|
* are exposed today.
|
|
17
17
|
*/
|
|
18
18
|
async function uploadAudioBufferToGcs(buffer, destination, contentType = "audio/mpeg") {
|
|
19
|
+
// GCS-PRIMARY (not mediaStorage.put): returns a public
|
|
20
|
+
// firebaseStorageDownloadTokens URL, a different shape than
|
|
21
|
+
// mediaStorage.put()'s signed-URL minter produces — same reason
|
|
22
|
+
// pixverse/bytedance stay off mediaStorage.put() too. See
|
|
23
|
+
// notes/R2_MEDIA_MIGRATION_PLAN.md §10.
|
|
19
24
|
const bucket = (0, firebase_1.getBucket)();
|
|
20
25
|
const file = bucket.file(destination);
|
|
21
26
|
const downloadToken = (0, node_crypto_1.randomUUID)();
|
package/lib/services/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,OAAO,CAAC;AACtB,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qCAAqC,CAAC;AACpD,cAAc,qBAAqB,CAAC;AACpC,cAAc,OAAO,CAAC;AACtB,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,OAAO,CAAC;AACtB,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,8BAA8B,CAAC;AAC7C,cAAc,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,OAAO,CAAC;AACtB,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qCAAqC,CAAC;AACpD,cAAc,qBAAqB,CAAC;AACpC,cAAc,OAAO,CAAC;AACtB,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,OAAO,CAAC;AACtB,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,8BAA8B,CAAC;AAC7C,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC"}
|
package/lib/services/index.js
CHANGED