vidspotai-shared 1.0.113 → 1.0.114
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/globals/types.d.ts +9 -1
- package/lib/globals/types.d.ts.map +1 -1
- package/lib/globals/types.js +9 -0
- package/lib/libs/index.d.ts +1 -0
- package/lib/libs/index.d.ts.map +1 -1
- package/lib/libs/index.js +1 -0
- package/lib/libs/mediaStore.d.ts +3 -31
- package/lib/libs/mediaStore.d.ts.map +1 -1
- package/lib/libs/mediaStore.js +16 -140
- package/lib/libs/storage/GcsBackend.d.ts +9 -0
- package/lib/libs/storage/GcsBackend.d.ts.map +1 -0
- package/lib/libs/storage/GcsBackend.js +42 -0
- package/lib/libs/storage/MediaStorage.d.ts +80 -0
- package/lib/libs/storage/MediaStorage.d.ts.map +1 -0
- package/lib/libs/storage/MediaStorage.js +105 -0
- package/lib/libs/storage/R2Backend.d.ts +23 -0
- package/lib/libs/storage/R2Backend.d.ts.map +1 -0
- package/lib/libs/storage/R2Backend.js +156 -0
- package/lib/libs/storage/StorageBackend.d.ts +41 -0
- package/lib/libs/storage/StorageBackend.d.ts.map +1 -0
- package/lib/libs/storage/StorageBackend.js +2 -0
- package/lib/libs/storage/index.d.ts +5 -0
- package/lib/libs/storage/index.d.ts.map +1 -0
- package/lib/libs/storage/index.js +20 -0
- package/lib/services/agent/tools/generateAvatarVideo.tool.d.ts.map +1 -1
- package/lib/services/agent/tools/generateAvatarVideo.tool.js +3 -5
- package/lib/services/aiGen/providers/alibaba/alibaba.d.ts.map +1 -1
- package/lib/services/aiGen/providers/alibaba/alibaba.js +5 -11
- package/lib/services/aiGen/providers/bytedance/bytedance.service.d.ts.map +1 -1
- package/lib/services/aiGen/providers/bytedance/bytedance.service.js +5 -0
- package/lib/services/aiGen/providers/elevenlabs/elevenlabs.service.d.ts.map +1 -1
- package/lib/services/aiGen/providers/elevenlabs/elevenlabs.service.js +3 -7
- package/lib/services/aiGen/providers/google/google.service.d.ts.map +1 -1
- package/lib/services/aiGen/providers/google/google.service.js +7 -4
- package/lib/services/aiGen/providers/google/googleMusic.d.ts.map +1 -1
- package/lib/services/aiGen/providers/google/googleMusic.js +3 -7
- package/lib/services/aiGen/providers/kling/kling.service.d.ts +16 -7
- package/lib/services/aiGen/providers/kling/kling.service.d.ts.map +1 -1
- package/lib/services/aiGen/providers/kling/kling.service.js +2 -2
- package/lib/services/aiGen/providers/kling/klingImage.service.d.ts.map +1 -1
- package/lib/services/aiGen/providers/kling/klingImage.service.js +3 -5
- package/lib/services/aiGen/providers/kling/klingStatus.d.ts +1 -1
- package/lib/services/aiGen/providers/kling/klingStatus.d.ts.map +1 -1
- package/lib/services/aiGen/providers/kling/klingStatus.js +8 -19
- package/lib/services/aiGen/providers/minimax/minimax.service.d.ts.map +1 -1
- package/lib/services/aiGen/providers/minimax/minimax.service.js +7 -17
- package/lib/services/aiGen/providers/openai/openai.service.d.ts.map +1 -1
- package/lib/services/aiGen/providers/openai/openai.service.js +5 -13
- package/lib/services/aiGen/providers/pixverse/pixverse.service.d.ts.map +1 -1
- package/lib/services/aiGen/providers/pixverse/pixverse.service.js +5 -0
- package/lib/services/aiGen/providers/runway/runway.service.d.ts.map +1 -1
- package/lib/services/aiGen/providers/runway/runway.service.js +5 -10
- package/lib/services/gcp/uploadAudioBuffer.d.ts.map +1 -1
- package/lib/services/gcp/uploadAudioBuffer.js +4 -0
- package/package.json +1 -1
package/lib/globals/types.d.ts
CHANGED
|
@@ -151,7 +151,15 @@ export declare enum ERedisQueues {
|
|
|
151
151
|
* same engine the demo pipeline uses), applies any permitted allow-listed
|
|
152
152
|
* repairs, and writes the report back. See notes/SAAS_DEMO_GENERATOR_PLAN.md §12.
|
|
153
153
|
*/
|
|
154
|
-
VIDEO_QA_JOBS = "video-qa-job-queue"
|
|
154
|
+
VIDEO_QA_JOBS = "video-qa-job-queue",
|
|
155
|
+
/**
|
|
156
|
+
* R2 cutover — mirrors a resumable-upload object (already in GCS, up to
|
|
157
|
+
* 1 GiB) into R2 off the request path. `completeUploadSessionController`
|
|
158
|
+
* can't safely buffer these in a Function's memory itself, so it enqueues
|
|
159
|
+
* here and the worker streams GCS → R2 directly. Best-effort: GCS is
|
|
160
|
+
* already the durable copy either way.
|
|
161
|
+
*/
|
|
162
|
+
MEDIA_MIRROR_JOBS = "media-mirror-job-queue"
|
|
155
163
|
}
|
|
156
164
|
export declare const REDIS_QUEUES: ERedisQueues[];
|
|
157
165
|
/** X8 Social Suite — connected social platforms. Value = stable storage key. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/globals/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,CAAC,MAAM,KAAK,CAAC;AAEpB,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE;QACT,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,cAAc,CAAC;QACrB,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;KACf,EAAE,CAAC;IACJ,MAAM,EAAE,GAAG,EAAE,CAAC;CACf;AAED,oBAAY,eAAe;IACzB,MAAM,WAAW,CAAE,wCAAwC;IAC3D,WAAW,eAAe,CAAE,2DAA2D;IAGvF,SAAS,cAAc,CAAE,8CAA8C;IACvE,MAAM,WAAW,CAAE,+BAA+B;IAClD,mBAAmB,uBAAuB,CAAE,oEAAoE;IAChH,SAAS,cAAc;CACxB;AAED,oBAAY,iBAAiB;IAC3B,WAAW,eAAe,CAAE,qFAAqF;IACjH,SAAS,cAAc,CAAE,2FAA2F;IACpH,OAAO,YAAY,CAAE,kKAAkK;IACvL,MAAM,WAAW,CAAE,kEAAkE;IACrF,SAAS,cAAc,CAAE,sCAAsC;IAC/D;;;;;OAKG;IACH,SAAS,aAAa;IACtB;;;;;;OAMG;IACH,SAAS,cAAc;CACxB;AAMD,oBAAY,YAAY;IACtB,UAAU,oBAAoB;IAC9B,iJAAiJ;IACjJ,eAAe,yBAAyB;IACxC,6FAA6F;IAC7F,WAAW,qBAAqB;IAChC,iFAAiF;IACjF,WAAW,qBAAqB;IAChC,mJAAmJ;IACnJ,UAAU,oBAAoB;IAC9B;;;;;OAKG;IACH,cAAc,wBAAwB;IACtC;;;;OAIG;IACH,gBAAgB,0BAA0B;IAC1C;;;;;;;;OAQG;IACH,eAAe,yBAAyB;IACxC;;;;;;;OAOG;IACH,eAAe,yBAAyB;IACxC;;;;;;;;OAQG;IACH,oBAAoB,8BAA8B;IAClD;;;;;;;;OAQG;IACH,iBAAiB,2BAA2B;IAC5C;;;;;OAKG;IACH,cAAc,wBAAwB;IACtC;;;;;;OAMG;IACH,mBAAmB,6BAA6B;IAChD;;;;OAIG;IACH,mBAAmB,6BAA6B;IAChD;;;;;;;;OAQG;IACH,eAAe,yBAAyB;IACxC;;;;;;OAMG;IACH,yBAAyB,mCAAmC;IAC5D;;;;;;;;OAQG;IACH,aAAa,uBAAuB;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/globals/types.ts"],"names":[],"mappings":"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"}
|
package/lib/globals/types.js
CHANGED
|
@@ -153,6 +153,14 @@ var ERedisQueues;
|
|
|
153
153
|
* repairs, and writes the report back. See notes/SAAS_DEMO_GENERATOR_PLAN.md §12.
|
|
154
154
|
*/
|
|
155
155
|
ERedisQueues["VIDEO_QA_JOBS"] = "video-qa-job-queue";
|
|
156
|
+
/**
|
|
157
|
+
* R2 cutover — mirrors a resumable-upload object (already in GCS, up to
|
|
158
|
+
* 1 GiB) into R2 off the request path. `completeUploadSessionController`
|
|
159
|
+
* can't safely buffer these in a Function's memory itself, so it enqueues
|
|
160
|
+
* here and the worker streams GCS → R2 directly. Best-effort: GCS is
|
|
161
|
+
* already the durable copy either way.
|
|
162
|
+
*/
|
|
163
|
+
ERedisQueues["MEDIA_MIRROR_JOBS"] = "media-mirror-job-queue";
|
|
156
164
|
})(ERedisQueues || (exports.ERedisQueues = ERedisQueues = {}));
|
|
157
165
|
exports.REDIS_QUEUES = [
|
|
158
166
|
ERedisQueues.VIDEO_JOBS,
|
|
@@ -172,6 +180,7 @@ exports.REDIS_QUEUES = [
|
|
|
172
180
|
ERedisQueues.DEMO_VIDEO_JOBS,
|
|
173
181
|
ERedisQueues.OUTREACH_PERSONALIZE_JOBS,
|
|
174
182
|
ERedisQueues.VIDEO_QA_JOBS,
|
|
183
|
+
ERedisQueues.MEDIA_MIRROR_JOBS,
|
|
175
184
|
];
|
|
176
185
|
/** X8 Social Suite — connected social platforms. Value = stable storage key. */
|
|
177
186
|
var ESocialProvider;
|
package/lib/libs/index.d.ts
CHANGED
package/lib/libs/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/libs/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/libs/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC"}
|
package/lib/libs/index.js
CHANGED
|
@@ -16,4 +16,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./firebase"), exports);
|
|
18
18
|
__exportStar(require("./r2KeyMap"), exports);
|
|
19
|
+
__exportStar(require("./storage"), exports);
|
|
19
20
|
__exportStar(require("./mediaStore"), exports);
|
package/lib/libs/mediaStore.d.ts
CHANGED
|
@@ -1,35 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* `putMedia()` is the single write path new media should flow through. It:
|
|
6
|
-
* 1. writes the bytes to GCS (unchanged system-of-record + pipeline source),
|
|
7
|
-
* 2. mirror-writes them to Cloudflare R2 at the clean `toR2Key()` key IF
|
|
8
|
-
* `R2_WRITE_ENABLED=true` (best-effort — a mirror failure never breaks the
|
|
9
|
-
* pipeline; GCS already succeeded), and
|
|
10
|
-
* 3. returns the same far-future GCS signed URL the call sites already use, so
|
|
11
|
-
* stored URLs / Firestore records don't change at all.
|
|
12
|
-
*
|
|
13
|
-
* Delivery then flips to free egress automatically: the `cdn.vidspotai.com`
|
|
14
|
-
* Worker is R2-first, so once an object is in R2 it's served from R2; until then
|
|
15
|
-
* the Worker falls back to GCS. See notes/R2_MEDIA_MIGRATION_PLAN.md (Phase 2).
|
|
16
|
-
*
|
|
17
|
-
* The R2 SDK is imported lazily (dynamic import) so it stays out of the module
|
|
18
|
-
* import graph — the shared package is already heavy at import time and this
|
|
19
|
-
* must not add to Cloud Function cold start (see
|
|
20
|
-
* memory/project_shared_lazy_load.md).
|
|
21
|
-
*/
|
|
22
|
-
/** R2 mirror-writes are opt-in; off = today's GCS-only behavior, exactly. */
|
|
23
|
-
export declare function isR2WriteEnabled(): boolean;
|
|
24
|
-
/**
|
|
25
|
-
* Write media to GCS (+ optional R2 mirror) and return a far-future signed read
|
|
26
|
-
* URL. Drop-in for the ubiquitous
|
|
27
|
-
* `file.save(buffer, { contentType })` + `getSignedUrl({ expires: "03-09-2491" })`
|
|
28
|
-
* pair.
|
|
29
|
-
*
|
|
30
|
-
* @param objectPath canonical GCS object key, e.g. "final_videos/<id>.mp4"
|
|
31
|
-
* @param body the bytes to store
|
|
32
|
-
* @param contentType MIME type, e.g. "video/mp4"
|
|
2
|
+
* @deprecated Use `mediaStorage.put(objectPath, body, contentType)`.
|
|
3
|
+
* Writes media (GCS primary + best-effort R2 mirror when enabled) and returns a
|
|
4
|
+
* far-future signed read URL.
|
|
33
5
|
*/
|
|
34
6
|
export declare function putMedia(objectPath: string, body: Buffer, contentType: string): Promise<string>;
|
|
35
7
|
//# sourceMappingURL=mediaStore.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mediaStore.d.ts","sourceRoot":"","sources":["../../src/libs/mediaStore.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"mediaStore.d.ts","sourceRoot":"","sources":["../../src/libs/mediaStore.ts"],"names":[],"mappings":"AAcA;;;;GAIG;AACH,wBAAgB,QAAQ,CACtB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC,CAEjB"}
|
package/lib/libs/mediaStore.js
CHANGED
|
@@ -1,148 +1,24 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Media store — GCS system-of-record + optional zero-egress R2 mirror.
|
|
4
|
-
* ====================================================================
|
|
5
|
-
*
|
|
6
|
-
* `putMedia()` is the single write path new media should flow through. It:
|
|
7
|
-
* 1. writes the bytes to GCS (unchanged system-of-record + pipeline source),
|
|
8
|
-
* 2. mirror-writes them to Cloudflare R2 at the clean `toR2Key()` key IF
|
|
9
|
-
* `R2_WRITE_ENABLED=true` (best-effort — a mirror failure never breaks the
|
|
10
|
-
* pipeline; GCS already succeeded), and
|
|
11
|
-
* 3. returns the same far-future GCS signed URL the call sites already use, so
|
|
12
|
-
* stored URLs / Firestore records don't change at all.
|
|
13
|
-
*
|
|
14
|
-
* Delivery then flips to free egress automatically: the `cdn.vidspotai.com`
|
|
15
|
-
* Worker is R2-first, so once an object is in R2 it's served from R2; until then
|
|
16
|
-
* the Worker falls back to GCS. See notes/R2_MEDIA_MIGRATION_PLAN.md (Phase 2).
|
|
17
|
-
*
|
|
18
|
-
* The R2 SDK is imported lazily (dynamic import) so it stays out of the module
|
|
19
|
-
* import graph — the shared package is already heavy at import time and this
|
|
20
|
-
* must not add to Cloud Function cold start (see
|
|
21
|
-
* memory/project_shared_lazy_load.md).
|
|
22
|
-
*/
|
|
23
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
24
|
-
if (k2 === undefined) k2 = k;
|
|
25
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
26
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
27
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
28
|
-
}
|
|
29
|
-
Object.defineProperty(o, k2, desc);
|
|
30
|
-
}) : (function(o, m, k, k2) {
|
|
31
|
-
if (k2 === undefined) k2 = k;
|
|
32
|
-
o[k2] = m[k];
|
|
33
|
-
}));
|
|
34
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
35
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
36
|
-
}) : function(o, v) {
|
|
37
|
-
o["default"] = v;
|
|
38
|
-
});
|
|
39
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
40
|
-
var ownKeys = function(o) {
|
|
41
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
42
|
-
var ar = [];
|
|
43
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
44
|
-
return ar;
|
|
45
|
-
};
|
|
46
|
-
return ownKeys(o);
|
|
47
|
-
};
|
|
48
|
-
return function (mod) {
|
|
49
|
-
if (mod && mod.__esModule) return mod;
|
|
50
|
-
var result = {};
|
|
51
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
52
|
-
__setModuleDefault(result, mod);
|
|
53
|
-
return result;
|
|
54
|
-
};
|
|
55
|
-
})();
|
|
56
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
57
|
-
exports.isR2WriteEnabled = isR2WriteEnabled;
|
|
58
3
|
exports.putMedia = putMedia;
|
|
59
|
-
const firebase_1 = require("./firebase");
|
|
60
|
-
const r2KeyMap_1 = require("./r2KeyMap");
|
|
61
|
-
const logger_1 = require("../utils/logger");
|
|
62
|
-
// Far-future expiry — matches the permanent bearer-token URLs used everywhere
|
|
63
|
-
// in the codebase (getSignedUrl expires "03-09-2491").
|
|
64
|
-
const PERMANENT_EXPIRY = "03-09-2491";
|
|
65
|
-
const R2_BUCKET = process.env.R2_BUCKET || "vidspot-media";
|
|
66
|
-
/** R2 mirror-writes are opt-in; off = today's GCS-only behavior, exactly. */
|
|
67
|
-
function isR2WriteEnabled() {
|
|
68
|
-
return process.env.R2_WRITE_ENABLED === "true";
|
|
69
|
-
}
|
|
70
|
-
function r2Config() {
|
|
71
|
-
const accessKeyId = process.env.CLOUDFLARE_R2_ACCESS_KEY_ID || process.env.R2_ACCESS_KEY_ID;
|
|
72
|
-
const secretAccessKey = process.env.CLOUDFLARE_R2_SECRET_ACCESS_KEY ||
|
|
73
|
-
process.env.R2_SECRET_ACCESS_KEY;
|
|
74
|
-
const endpoint = process.env.CLOUDFLARE_R2_S3_ENDPOINT || process.env.R2_S3_ENDPOINT;
|
|
75
|
-
return { accessKeyId, secretAccessKey, endpoint };
|
|
76
|
-
}
|
|
77
|
-
// Lazily-built singleton S3 client (only when the first mirror actually runs).
|
|
78
|
-
let s3Client = null;
|
|
79
|
-
let s3Init = null;
|
|
80
|
-
async function getS3() {
|
|
81
|
-
if (s3Client)
|
|
82
|
-
return s3Client;
|
|
83
|
-
if (s3Init)
|
|
84
|
-
return s3Init;
|
|
85
|
-
s3Init = (async () => {
|
|
86
|
-
const { accessKeyId, secretAccessKey, endpoint } = r2Config();
|
|
87
|
-
if (!accessKeyId || !secretAccessKey || !endpoint) {
|
|
88
|
-
logger_1.logger.warn("mediaStore: R2_WRITE_ENABLED but R2 creds/endpoint missing — skipping mirror");
|
|
89
|
-
return null;
|
|
90
|
-
}
|
|
91
|
-
const { S3Client: Client } = await Promise.resolve().then(() => __importStar(require("@aws-sdk/client-s3")));
|
|
92
|
-
s3Client = new Client({
|
|
93
|
-
region: "auto",
|
|
94
|
-
endpoint,
|
|
95
|
-
credentials: { accessKeyId, secretAccessKey },
|
|
96
|
-
});
|
|
97
|
-
return s3Client;
|
|
98
|
-
})();
|
|
99
|
-
return s3Init;
|
|
100
|
-
}
|
|
101
4
|
/**
|
|
102
|
-
*
|
|
103
|
-
*
|
|
5
|
+
* mediaStore — DEPRECATED compatibility shim.
|
|
6
|
+
* ===========================================
|
|
7
|
+
*
|
|
8
|
+
* The media write path now lives in the `MediaStorage` class
|
|
9
|
+
* (`./storage/MediaStorage.ts`, singleton `mediaStorage`). Everything should
|
|
10
|
+
* call `mediaStorage.put(...)` / `.putFromFile(...)` / `.mirrorBytes(...)`
|
|
11
|
+
* directly so storage is swappable in ONE place.
|
|
12
|
+
*
|
|
13
|
+
* `putMedia()` is kept only as a thin delegate so pre-existing call sites keep
|
|
14
|
+
* working during migration. Prefer `mediaStorage.put`.
|
|
104
15
|
*/
|
|
105
|
-
|
|
106
|
-
try {
|
|
107
|
-
const client = await getS3();
|
|
108
|
-
if (!client)
|
|
109
|
-
return;
|
|
110
|
-
const { PutObjectCommand } = await Promise.resolve().then(() => __importStar(require("@aws-sdk/client-s3")));
|
|
111
|
-
const r2Key = (0, r2KeyMap_1.toR2Key)(objectPath);
|
|
112
|
-
await client.send(new PutObjectCommand({
|
|
113
|
-
Bucket: R2_BUCKET,
|
|
114
|
-
Key: r2Key,
|
|
115
|
-
Body: body,
|
|
116
|
-
ContentType: contentType,
|
|
117
|
-
}));
|
|
118
|
-
logger_1.logger.info("mediaStore: mirrored to R2", { objectPath, r2Key });
|
|
119
|
-
}
|
|
120
|
-
catch (err) {
|
|
121
|
-
logger_1.logger.error("mediaStore: R2 mirror failed (GCS write still stands)", {
|
|
122
|
-
objectPath,
|
|
123
|
-
err: err instanceof Error ? err.stack ?? err.message : String(err),
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
}
|
|
16
|
+
const storage_1 = require("./storage");
|
|
127
17
|
/**
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
* pair.
|
|
132
|
-
*
|
|
133
|
-
* @param objectPath canonical GCS object key, e.g. "final_videos/<id>.mp4"
|
|
134
|
-
* @param body the bytes to store
|
|
135
|
-
* @param contentType MIME type, e.g. "video/mp4"
|
|
18
|
+
* @deprecated Use `mediaStorage.put(objectPath, body, contentType)`.
|
|
19
|
+
* Writes media (GCS primary + best-effort R2 mirror when enabled) and returns a
|
|
20
|
+
* far-future signed read URL.
|
|
136
21
|
*/
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
await file.save(body, { contentType });
|
|
140
|
-
if (isR2WriteEnabled()) {
|
|
141
|
-
await mirrorToR2(objectPath, body, contentType);
|
|
142
|
-
}
|
|
143
|
-
const [signedUrl] = await file.getSignedUrl({
|
|
144
|
-
action: "read",
|
|
145
|
-
expires: PERMANENT_EXPIRY,
|
|
146
|
-
});
|
|
147
|
-
return signedUrl;
|
|
22
|
+
function putMedia(objectPath, body, contentType) {
|
|
23
|
+
return storage_1.mediaStorage.put(objectPath, body, contentType);
|
|
148
24
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { IStorageBackend } from "./StorageBackend";
|
|
2
|
+
export declare class GcsBackend implements IStorageBackend {
|
|
3
|
+
readonly name = "gcs";
|
|
4
|
+
write(key: string, body: Buffer, contentType: string): Promise<void>;
|
|
5
|
+
writeFromFile(key: string, localPath: string, contentType: string): Promise<number>;
|
|
6
|
+
signedReadUrl(key: string): Promise<string>;
|
|
7
|
+
delete(key: string): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=GcsBackend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GcsBackend.d.ts","sourceRoot":"","sources":["../../../src/libs/storage/GcsBackend.ts"],"names":[],"mappings":"AAYA,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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GcsBackend = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Google Cloud Storage backend — today's system-of-record.
|
|
6
|
+
* ========================================================
|
|
7
|
+
*
|
|
8
|
+
* Wraps the Firebase Admin bucket. The canonical object path IS the GCS key
|
|
9
|
+
* (identity mapping). Read URLs are the far-future signed URLs used everywhere
|
|
10
|
+
* in the codebase (`getSignedUrl({ expires: "03-09-2491" })`) — permanent
|
|
11
|
+
* bearer tokens, so stored Firestore URLs never need refreshing.
|
|
12
|
+
*/
|
|
13
|
+
const fs_1 = require("fs");
|
|
14
|
+
const promises_1 = require("stream/promises");
|
|
15
|
+
const firebase_1 = require("../firebase");
|
|
16
|
+
// Far-future expiry — matches the permanent bearer-token URLs used everywhere
|
|
17
|
+
// (getSignedUrl expires "03-09-2491").
|
|
18
|
+
const PERMANENT_EXPIRY = "03-09-2491";
|
|
19
|
+
class GcsBackend {
|
|
20
|
+
constructor() {
|
|
21
|
+
this.name = "gcs";
|
|
22
|
+
}
|
|
23
|
+
async write(key, body, contentType) {
|
|
24
|
+
await (0, firebase_1.getBucket)().file(key).save(body, { contentType });
|
|
25
|
+
}
|
|
26
|
+
async writeFromFile(key, localPath, contentType) {
|
|
27
|
+
const file = (0, firebase_1.getBucket)().file(key);
|
|
28
|
+
await (0, promises_1.pipeline)((0, fs_1.createReadStream)(localPath), file.createWriteStream({ contentType }));
|
|
29
|
+
const [meta] = await file.getMetadata();
|
|
30
|
+
return Number(meta.size);
|
|
31
|
+
}
|
|
32
|
+
async signedReadUrl(key) {
|
|
33
|
+
const [url] = await (0, firebase_1.getBucket)()
|
|
34
|
+
.file(key)
|
|
35
|
+
.getSignedUrl({ action: "read", expires: PERMANENT_EXPIRY });
|
|
36
|
+
return url;
|
|
37
|
+
}
|
|
38
|
+
async delete(key) {
|
|
39
|
+
await (0, firebase_1.getBucket)().file(key).delete({ ignoreNotFound: true });
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.GcsBackend = GcsBackend;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MediaStorage — the single media write/read path for the whole backend.
|
|
3
|
+
* ======================================================================
|
|
4
|
+
*
|
|
5
|
+
* Every media write (final videos, scene clips, posters, images, music/SFX/TTS,
|
|
6
|
+
* uploads, agent edits) goes through the `mediaStorage` singleton instead of
|
|
7
|
+
* touching a bucket directly. That gives us ONE place to change how/where media
|
|
8
|
+
* is stored — swapping backends, or flipping which one is primary, never touches
|
|
9
|
+
* the ~30 call sites.
|
|
10
|
+
*
|
|
11
|
+
* Today's composition:
|
|
12
|
+
* • PRIMARY = GCS (system-of-record + pipeline source; returns the delivery URL)
|
|
13
|
+
* • MIRROR = R2, best-effort, only when `R2_WRITE_ENABLED=true`
|
|
14
|
+
*
|
|
15
|
+
* Delivery flips to free egress automatically: the `cdn.vidspotai.com` Worker is
|
|
16
|
+
* R2-first, so once an object is mirrored it serves from R2; until then the
|
|
17
|
+
* Worker falls back to GCS. See notes/R2_MEDIA_MIGRATION_PLAN.md (Phase 2).
|
|
18
|
+
*
|
|
19
|
+
* FUTURE SWAP (Stage 2 — decommission GCS): make R2 the primary and return its
|
|
20
|
+
* CDN read URL. That is an edit to THIS FILE ONLY — every caller keeps calling
|
|
21
|
+
* `mediaStorage.put(...)` unchanged.
|
|
22
|
+
*/
|
|
23
|
+
import type { Readable } from "stream";
|
|
24
|
+
import type { IStorageBackend } from "./StorageBackend";
|
|
25
|
+
/** R2 mirror-writes are opt-in; off = today's GCS-only behavior, exactly. */
|
|
26
|
+
export declare function isR2WriteEnabled(): boolean;
|
|
27
|
+
export declare class MediaStorage {
|
|
28
|
+
/** Store-of-record + delivery-URL source. */
|
|
29
|
+
private readonly primary;
|
|
30
|
+
/** Zero-egress mirror; written best-effort when enabled. */
|
|
31
|
+
private readonly mirror;
|
|
32
|
+
constructor(primary: IStorageBackend, mirror: IStorageBackend);
|
|
33
|
+
/**
|
|
34
|
+
* Write in-memory bytes and return a durable delivery URL. Drop-in for the
|
|
35
|
+
* ubiquitous `file.save(buf, { contentType })` + `getSignedUrl({ expires })`
|
|
36
|
+
* pair.
|
|
37
|
+
*
|
|
38
|
+
* @param objectPath canonical object key, e.g. "final_videos/<id>.mp4"
|
|
39
|
+
*/
|
|
40
|
+
put(objectPath: string, body: Buffer, contentType: string): Promise<string>;
|
|
41
|
+
/**
|
|
42
|
+
* Stream a local file to the primary (no whole-file buffering) and return the
|
|
43
|
+
* delivery URL plus the stored object size for integrity checks. For large
|
|
44
|
+
* clips whose GCS upload is size-verified by the caller (e.g. the google
|
|
45
|
+
* scene-download moov-atom guard).
|
|
46
|
+
*/
|
|
47
|
+
putFromFile(objectPath: string, localPath: string, contentType: string): Promise<{
|
|
48
|
+
url: string;
|
|
49
|
+
size: number;
|
|
50
|
+
}>;
|
|
51
|
+
/**
|
|
52
|
+
* Best-effort R2 mirror of an object ALREADY written to the primary through a
|
|
53
|
+
* bespoke path (a specialized streaming/integrity write we don't want to route
|
|
54
|
+
* through `put`). No-op when disabled; never throws.
|
|
55
|
+
*/
|
|
56
|
+
mirrorBytes(objectPath: string, body: Buffer, contentType: string): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* Best-effort R2 mirror of a LOCAL FILE already written to the primary through
|
|
59
|
+
* a bespoke streaming/integrity path (e.g. the google scene-download moov-atom
|
|
60
|
+
* guard). Reads the file only when mirroring is enabled; never throws.
|
|
61
|
+
*/
|
|
62
|
+
mirrorFromFile(objectPath: string, localPath: string, contentType: string): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Best-effort R2 mirror of an object ALREADY written to the primary,
|
|
65
|
+
* streamed straight through from an open Readable (e.g. a GCS read stream)
|
|
66
|
+
* without buffering it whole — for objects too large to safely hold in
|
|
67
|
+
* process memory (resumable uploads, up to 1 GiB). No-op when disabled, when
|
|
68
|
+
* the mirror backend doesn't implement streaming writes, or on failure.
|
|
69
|
+
*/
|
|
70
|
+
mirrorFromReadable(objectPath: string, stream: Readable, contentType: string, size: number): Promise<void>;
|
|
71
|
+
/** Delivery URL for an object already stored. */
|
|
72
|
+
signedReadUrl(objectPath: string): Promise<string>;
|
|
73
|
+
/** Delete from both stores (mirror delete best-effort). */
|
|
74
|
+
delete(objectPath: string): Promise<void>;
|
|
75
|
+
/** Run a mirror op, swallowing failures — the primary write already stands. */
|
|
76
|
+
private bestEffortMirror;
|
|
77
|
+
}
|
|
78
|
+
/** App-wide singleton: GCS primary today, R2 mirror when enabled. */
|
|
79
|
+
export declare const mediaStorage: MediaStorage;
|
|
80
|
+
//# sourceMappingURL=MediaStorage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MediaStorage.d.ts","sourceRoot":"","sources":["../../../src/libs/storage/MediaStorage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAGvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGxD,6EAA6E;AAC7E,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C;AAED,qBAAa,YAAY;IACvB,6CAA6C;IAC7C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkB;IAC1C,4DAA4D;IAC5D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;gBAE7B,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,eAAe;IAK7D;;;;;;OAMG;IACG,GAAG,CACP,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC;IAWlB;;;;;OAKG;IACG,WAAW,CACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAYzC;;;;OAIG;IACG,WAAW,CACf,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC;IAQhB;;;;OAIG;IACG,cAAc,CAClB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC;IAQhB;;;;;;OAMG;IACG,kBAAkB,CACtB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,QAAQ,EAChB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC;IAShB,iDAAiD;IACjD,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIlD,2DAA2D;IACrD,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO/C,+EAA+E;YACjE,gBAAgB;CAa/B;AAED,qEAAqE;AACrE,eAAO,MAAM,YAAY,cAAsD,CAAC"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mediaStorage = exports.MediaStorage = void 0;
|
|
4
|
+
exports.isR2WriteEnabled = isR2WriteEnabled;
|
|
5
|
+
const GcsBackend_1 = require("./GcsBackend");
|
|
6
|
+
const R2Backend_1 = require("./R2Backend");
|
|
7
|
+
const logger_1 = require("../../utils/logger");
|
|
8
|
+
/** R2 mirror-writes are opt-in; off = today's GCS-only behavior, exactly. */
|
|
9
|
+
function isR2WriteEnabled() {
|
|
10
|
+
return process.env.R2_WRITE_ENABLED === "true";
|
|
11
|
+
}
|
|
12
|
+
class MediaStorage {
|
|
13
|
+
constructor(primary, mirror) {
|
|
14
|
+
this.primary = primary;
|
|
15
|
+
this.mirror = mirror;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Write in-memory bytes and return a durable delivery URL. Drop-in for the
|
|
19
|
+
* ubiquitous `file.save(buf, { contentType })` + `getSignedUrl({ expires })`
|
|
20
|
+
* pair.
|
|
21
|
+
*
|
|
22
|
+
* @param objectPath canonical object key, e.g. "final_videos/<id>.mp4"
|
|
23
|
+
*/
|
|
24
|
+
async put(objectPath, body, contentType) {
|
|
25
|
+
await this.primary.write(objectPath, body, contentType);
|
|
26
|
+
if (isR2WriteEnabled()) {
|
|
27
|
+
await this.bestEffortMirror(() => this.mirror.write(objectPath, body, contentType), objectPath);
|
|
28
|
+
}
|
|
29
|
+
return this.primary.signedReadUrl(objectPath);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Stream a local file to the primary (no whole-file buffering) and return the
|
|
33
|
+
* delivery URL plus the stored object size for integrity checks. For large
|
|
34
|
+
* clips whose GCS upload is size-verified by the caller (e.g. the google
|
|
35
|
+
* scene-download moov-atom guard).
|
|
36
|
+
*/
|
|
37
|
+
async putFromFile(objectPath, localPath, contentType) {
|
|
38
|
+
const size = await this.primary.writeFromFile(objectPath, localPath, contentType);
|
|
39
|
+
if (isR2WriteEnabled()) {
|
|
40
|
+
await this.bestEffortMirror(() => this.mirror.writeFromFile(objectPath, localPath, contentType), objectPath);
|
|
41
|
+
}
|
|
42
|
+
const url = await this.primary.signedReadUrl(objectPath);
|
|
43
|
+
return { url, size };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Best-effort R2 mirror of an object ALREADY written to the primary through a
|
|
47
|
+
* bespoke path (a specialized streaming/integrity write we don't want to route
|
|
48
|
+
* through `put`). No-op when disabled; never throws.
|
|
49
|
+
*/
|
|
50
|
+
async mirrorBytes(objectPath, body, contentType) {
|
|
51
|
+
if (!isR2WriteEnabled())
|
|
52
|
+
return;
|
|
53
|
+
await this.bestEffortMirror(() => this.mirror.write(objectPath, body, contentType), objectPath);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Best-effort R2 mirror of a LOCAL FILE already written to the primary through
|
|
57
|
+
* a bespoke streaming/integrity path (e.g. the google scene-download moov-atom
|
|
58
|
+
* guard). Reads the file only when mirroring is enabled; never throws.
|
|
59
|
+
*/
|
|
60
|
+
async mirrorFromFile(objectPath, localPath, contentType) {
|
|
61
|
+
if (!isR2WriteEnabled())
|
|
62
|
+
return;
|
|
63
|
+
await this.bestEffortMirror(() => this.mirror.writeFromFile(objectPath, localPath, contentType), objectPath);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Best-effort R2 mirror of an object ALREADY written to the primary,
|
|
67
|
+
* streamed straight through from an open Readable (e.g. a GCS read stream)
|
|
68
|
+
* without buffering it whole — for objects too large to safely hold in
|
|
69
|
+
* process memory (resumable uploads, up to 1 GiB). No-op when disabled, when
|
|
70
|
+
* the mirror backend doesn't implement streaming writes, or on failure.
|
|
71
|
+
*/
|
|
72
|
+
async mirrorFromReadable(objectPath, stream, contentType, size) {
|
|
73
|
+
if (!isR2WriteEnabled())
|
|
74
|
+
return;
|
|
75
|
+
if (!this.mirror.writeFromReadable)
|
|
76
|
+
return;
|
|
77
|
+
await this.bestEffortMirror(() => this.mirror.writeFromReadable(objectPath, stream, contentType, size), objectPath);
|
|
78
|
+
}
|
|
79
|
+
/** Delivery URL for an object already stored. */
|
|
80
|
+
signedReadUrl(objectPath) {
|
|
81
|
+
return this.primary.signedReadUrl(objectPath);
|
|
82
|
+
}
|
|
83
|
+
/** Delete from both stores (mirror delete best-effort). */
|
|
84
|
+
async delete(objectPath) {
|
|
85
|
+
await this.primary.delete(objectPath);
|
|
86
|
+
if (isR2WriteEnabled()) {
|
|
87
|
+
await this.bestEffortMirror(() => this.mirror.delete(objectPath), objectPath);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/** Run a mirror op, swallowing failures — the primary write already stands. */
|
|
91
|
+
async bestEffortMirror(op, objectPath) {
|
|
92
|
+
try {
|
|
93
|
+
await op();
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
logger_1.logger.error("MediaStorage: R2 mirror failed (primary write stands)", {
|
|
97
|
+
objectPath,
|
|
98
|
+
err: err instanceof Error ? err.stack ?? err.message : String(err),
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
exports.MediaStorage = MediaStorage;
|
|
104
|
+
/** App-wide singleton: GCS primary today, R2 mirror when enabled. */
|
|
105
|
+
exports.mediaStorage = new MediaStorage(new GcsBackend_1.GcsBackend(), new R2Backend_1.R2Backend());
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Readable } from "stream";
|
|
2
|
+
import type { IStorageBackend } from "./StorageBackend";
|
|
3
|
+
export declare class R2Backend implements IStorageBackend {
|
|
4
|
+
readonly name = "r2";
|
|
5
|
+
private client;
|
|
6
|
+
private init;
|
|
7
|
+
/** True once creds+endpoint are present; a missing config is logged once. */
|
|
8
|
+
private getClient;
|
|
9
|
+
write(key: string, body: Buffer, contentType: string): Promise<void>;
|
|
10
|
+
writeFromFile(key: string, localPath: string, contentType: string): Promise<number>;
|
|
11
|
+
/**
|
|
12
|
+
* Mirror an object already stored elsewhere (GCS) straight through, without
|
|
13
|
+
* buffering it in process memory — for objects a caller never downloads to
|
|
14
|
+
* a local file (e.g. a resumable-upload completion, which only has a GCS
|
|
15
|
+
* read stream). A single PutObject with an explicit ContentLength handles
|
|
16
|
+
* up to 5GiB without multipart, comfortably covering our upload ceiling.
|
|
17
|
+
*/
|
|
18
|
+
writeFromReadable(key: string, stream: Readable, contentType: string, size: number): Promise<void>;
|
|
19
|
+
/** Delivery URL once R2 is primary: the CDN host + clean key. */
|
|
20
|
+
signedReadUrl(key: string): Promise<string>;
|
|
21
|
+
delete(key: string): Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=R2Backend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"R2Backend.d.ts","sourceRoot":"","sources":["../../../src/libs/storage/R2Backend.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAIvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAyBxD,qBAAa,SAAU,YAAW,eAAe;IAC/C,QAAQ,CAAC,IAAI,QAAQ;IAGrB,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,IAAI,CAAyC;IAErD,6EAA6E;YAC/D,SAAS;IAoBjB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBpE,aAAa,CACjB,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC;IAQlB;;;;;;OAMG;IACG,iBAAiB,CACrB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,QAAQ,EAChB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC;IAiBhB,iEAAiE;IAC3D,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAI3C,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAQzC"}
|