@skyphusion-labs/vivijure-core 1.2.13 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,340 @@
1
+ // Host-neutral storage accounting + the R2_STORAGE_QUOTA_BYTES operator knob (core#52).
2
+ //
3
+ // WHY THIS IS IN CORE, not in a panel: the hosted tier meters per-tenant storage, but a tenant studio
4
+ // runs the PUBLISHED release unmodified, so there is no hosted fork to put hosted-only enforcement in.
5
+ // A quota check that exists only for hosted is the named drift tripwire. It lands here as an operator
6
+ // knob shipping to hosted and self-host in the same release; hosted just sets the var per tenant, and a
7
+ // self-hoster gets the identical feature to cap their own R2 bill. Ruled on vivijure-cf#56.
8
+ //
9
+ // SHAPE (mirrors SPEND_DAILY_CEILING, vivijure-cf src/rate-limit.ts):
10
+ // R2_STORAGE_QUOTA_BYTES="<n>" -- unset / 0 / garbage = OFF (absent knob, absent behavior).
11
+ // Set = enforced at submit with an HONEST deny carrying the real
12
+ // numbers (used vs limit), never a silent truncation or a partial
13
+ // render.
14
+ //
15
+ // WHERE THE NUMBER COMES FROM: the host DB, accounted at WRITE TIME (D1 on Workers, SQLite on the Node
16
+ // host). NOT an R2/S3 usage API read -- that is CF-specific, so it breaks the Node/MinIO host, which is
17
+ // a parity break for a parity feature; it is also eventually consistent and would need creds in the
18
+ // render path. The ledger is per object key (storage_usage), so re-writing the SAME key (every film /
19
+ // clip job-doc update does) UPDATES its row rather than double counting, and a delete removes it.
20
+ //
21
+ // ACCOUNTING RULE (one rule, no exceptions): every object write upserts its key at its current size,
22
+ // every delete (user, orphan-GC, panel cleanup) drops the row. Intermediates COUNT while they exist --
23
+ // they occupy bytes while they exist, and the operator is billed for them while they exist.
24
+ //
25
+ // ACCOUNTING NEVER FAILS A WRITE. The meter is a meter, not a gate: if the ledger write throws, the
26
+ // object write still succeeds and the counter drifts LOW with a warning. The gate is at submit. The
27
+ // repair for any drift (a failed ledger write, an R2 lifecycle rule expiring objects out of band, or
28
+ // artifacts that predate this version) is reconcileStorageUsage, which rebuilds the ledger from the
29
+ // object store itself.
30
+ //
31
+ // BACKFILL POSTURE (core#52 sub-question 1): artifact SIZES are not derivable from the DB (renders rows
32
+ // carry keys, never bytes), so there is nothing cheap and honest to sum. The counter therefore starts
33
+ // at 0 on an existing studio (accounting starts at the version that ships this) and the operator runs
34
+ // the reconcile to make the number true. That is stated in the docs and surfaced by the panel usage
35
+ // route, never left as a quietly-wrong number.
36
+ // --------------------------------------------------------------------------- schema
37
+ /** Canonical ledger DDL. Both panel migrations carry this VERBATIM, and each panel has a test asserting
38
+ * its migration file still matches this constant, so the two hosts cannot drift apart. */
39
+ export const STORAGE_USAGE_DDL = `CREATE TABLE IF NOT EXISTS storage_usage (
40
+ object_key TEXT PRIMARY KEY,
41
+ bytes INTEGER NOT NULL,
42
+ updated_at INTEGER NOT NULL
43
+ )`;
44
+ /** Pure: the configured ceiling in bytes, or null when the knob is off (unset / empty / 0 / garbage).
45
+ * Bytes only, deliberately: no "10GB" unit parsing, because a mis-parsed unit is an order-of-magnitude
46
+ * error on somebody's bill. The docs carry the worked examples. */
47
+ export function storageQuotaBytes(env) {
48
+ const raw = env.R2_STORAGE_QUOTA_BYTES;
49
+ if (typeof raw !== "string" || raw.trim() === "")
50
+ return null;
51
+ const n = Number(raw.trim());
52
+ return Number.isInteger(n) && n > 0 ? n : null;
53
+ }
54
+ // --------------------------------------------------------------------------- the ledger
55
+ function nowSeconds() {
56
+ return Math.floor(Date.now() / 1000);
57
+ }
58
+ /** Upsert one object's accounted size. Idempotent per key: a re-put of the same key overwrites its row,
59
+ * so repeated writes to a job doc never inflate the total. */
60
+ export async function recordObjectWrite(db, key, bytes) {
61
+ if (!Number.isFinite(bytes) || bytes < 0) {
62
+ throw new Error(`storage-usage: refusing to record ${bytes} bytes for ${key}`);
63
+ }
64
+ await db
65
+ .prepare(`INSERT INTO storage_usage (object_key, bytes, updated_at) VALUES (?, ?, ?)
66
+ ON CONFLICT(object_key) DO UPDATE SET bytes = excluded.bytes, updated_at = excluded.updated_at`)
67
+ .bind(key, Math.floor(bytes), nowSeconds())
68
+ .run();
69
+ }
70
+ /** Drop one object from the ledger. A key with no row is a no-op (deleting an unaccounted object is
71
+ * normal on a studio whose accounting started mid-life). */
72
+ export async function recordObjectDelete(db, key) {
73
+ await db.prepare("DELETE FROM storage_usage WHERE object_key = ?").bind(key).run();
74
+ }
75
+ /** Accounted bytes AND object count, for enforcement and for the operator usage surface. One SUM over
76
+ * the ledger; called at submit (a rare event) and by the usage route, never on the write path. */
77
+ export async function storageUsage(db) {
78
+ const row = await db
79
+ .prepare("SELECT COALESCE(SUM(bytes), 0) AS total, COUNT(*) AS objects FROM storage_usage")
80
+ .bind()
81
+ .first();
82
+ return {
83
+ usedBytes: typeof row?.total === "number" ? row.total : 0,
84
+ objects: typeof row?.objects === "number" ? row.objects : 0,
85
+ };
86
+ }
87
+ /** Total accounted bytes. */
88
+ export async function storageUsedBytes(db) {
89
+ return (await storageUsage(db)).usedBytes;
90
+ }
91
+ /** Enforce the storage ceiling for one submission. Knob off = a pure no-op that never touches the DB. */
92
+ export async function checkStorageQuota(env) {
93
+ const quotaBytes = storageQuotaBytes(env);
94
+ if (quotaBytes === null)
95
+ return { ok: true, usedBytes: null, quotaBytes: null };
96
+ if (!env.DB) {
97
+ return {
98
+ ok: false,
99
+ status: 503,
100
+ usedBytes: null,
101
+ quotaBytes,
102
+ message: `storage quota is set (${quotaBytes} bytes) but the studio database is unavailable, so storage usage cannot be checked; submissions are blocked (fail-closed posture)`,
103
+ };
104
+ }
105
+ let usedBytes;
106
+ try {
107
+ usedBytes = await storageUsedBytes(env.DB);
108
+ }
109
+ catch (e) {
110
+ return {
111
+ ok: false,
112
+ status: 503,
113
+ usedBytes: null,
114
+ quotaBytes,
115
+ message: `storage quota check failed (${e.message}); submissions are blocked until the database recovers (fail-closed posture)`,
116
+ };
117
+ }
118
+ // >= denies AT the ceiling: a studio exactly at its limit is full, and the next render only ever adds
119
+ // bytes. Denying one submission early is honest; letting one through is not.
120
+ if (usedBytes >= quotaBytes) {
121
+ return {
122
+ ok: false,
123
+ status: 507,
124
+ usedBytes,
125
+ quotaBytes,
126
+ message: `storage quota reached: ${usedBytes} bytes stored of the ${quotaBytes}-byte R2_STORAGE_QUOTA_BYTES ceiling; delete renders or raise the knob`,
127
+ };
128
+ }
129
+ return { ok: true, usedBytes, quotaBytes };
130
+ }
131
+ // --------------------------------------------------------------------------- the submit surface
132
+ // The POST routes that WRITE ARTIFACT BYTES: uploads, GPU submits, and the paid-generation routes whose
133
+ // product is a stored file. Both panels serve this same studio API, so the list lives here once rather
134
+ // than being mirrored (and drifting) in two hosts. Each panel has a test asserting every pattern below
135
+ // still matches one of ITS registered routes.
136
+ //
137
+ // Deliberately NOT here, and why:
138
+ // /api/chat -- its text branch writes nothing; only the image branch stores a small file.
139
+ // Denying text chat because the video bucket is full is over-blocking. The
140
+ // byte-heavy paths are all gated, and a full studio is denied at its next
141
+ // render submit. A documented bound, not an oversight.
142
+ // /api/storyboard/plan | refine | enhance | preflight | render-plan | markers | yaml
143
+ // -- planning routes; they spend AI money (that is SPEND_DAILY_CEILING's job, a
144
+ // different meter) but store no artifact.
145
+ const STORAGE_SUBMIT_PATTERNS = [
146
+ // Operator/user uploads: caller-supplied bytes, the least bounded write there is.
147
+ /^\/api\/upload$/,
148
+ /^\/api\/storyboard\/audio-upload$/,
149
+ /^\/api\/storyboard\/character-ref$/,
150
+ /^\/api\/storyboard\/bundle$/,
151
+ /^\/api\/cast\/import$/,
152
+ /^\/api\/cast\/[^/]+\/portrait$/,
153
+ /^\/api\/cast\/[^/]+\/ref$/,
154
+ /^\/api\/cast\/[^/]+\/source$/,
155
+ // GPU submits: every one of these ends in video / image / LoRA bytes in the bucket.
156
+ /^\/api\/storyboard\/render$/,
157
+ /^\/api\/storyboard\/render\/scatter$/,
158
+ /^\/api\/storyboard\/render-from-keyframes$/,
159
+ /^\/api\/render\/clips$/,
160
+ /^\/api\/render\/film$/,
161
+ /^\/api\/storyboard\/renders\/[^/]+\/regen-shot$/,
162
+ /^\/api\/storyboard\/renders\/[^/]+\/finalize$/,
163
+ /^\/api\/storyboard\/renders\/[^/]+\/animate-cloud$/,
164
+ /^\/api\/storyboard\/renders\/[^/]+\/animate-hybrid$/,
165
+ /^\/api\/storyboard\/renders\/[^/]+\/add-audio$/,
166
+ /^\/api\/storyboard\/renders\/[^/]+\/add-narration$/,
167
+ /^\/api\/cast\/[^/]+\/generate-refs$/,
168
+ /^\/api\/cast\/[^/]+\/train-lora$/,
169
+ /^\/api\/cast\/[^/]+\/train-wan-lora$/,
170
+ // Audio generation: a score bed / music track is a stored artifact.
171
+ /^\/api\/storyboard\/score-bed$/,
172
+ /^\/api\/storyboard\/music-generate$/,
173
+ ];
174
+ /** True for a request whose product is stored bytes, and so must pass the storage ceiling. */
175
+ export function isStorageSubmitRoute(method, pathname) {
176
+ if (method !== "POST")
177
+ return false;
178
+ return STORAGE_SUBMIT_PATTERNS.some((re) => re.test(pathname));
179
+ }
180
+ /** The pattern list, for the panel route-drift tests. */
181
+ export function storageSubmitPatterns() {
182
+ return [...STORAGE_SUBMIT_PATTERNS];
183
+ }
184
+ // --------------------------------------------------------------------------- write metering
185
+ /** Marker so wrapping an already-metered store is a no-op. Symbol.for (not a fresh Symbol) so a double
186
+ * wrap ACROSS module instances (a panel copy plus the core copy) is still detected. A per-request seam
187
+ * that re-wrapped its bucket would otherwise double count every byte. */
188
+ const METERED = Symbol.for("vivijure.storage-metered");
189
+ /** Bytes a put() payload will occupy, or null when it cannot be determined from the value alone. */
190
+ export function putValueByteLength(value) {
191
+ if (typeof value === "string")
192
+ return new TextEncoder().encode(value).byteLength;
193
+ if (value instanceof ArrayBuffer)
194
+ return value.byteLength;
195
+ if (ArrayBuffer.isView(value))
196
+ return value.byteLength;
197
+ if (typeof value === "object" && value !== null && "body" in value) {
198
+ const body = value.body;
199
+ if (ArrayBuffer.isView(body))
200
+ return body.byteLength;
201
+ if (body instanceof ArrayBuffer)
202
+ return body.byteLength;
203
+ }
204
+ return null;
205
+ }
206
+ /** Account one completed write. Never throws: a broken meter must not fail a good write. */
207
+ async function accountWrite(db, target, key, value) {
208
+ try {
209
+ let bytes = putValueByteLength(value);
210
+ if (bytes === null && typeof target.head === "function") {
211
+ // A payload shape we cannot measure locally (a stream, a host-specific body). Ask the store what
212
+ // it actually stored rather than guessing or skipping.
213
+ const head = await target.head(key);
214
+ if (head && typeof head.size === "number")
215
+ bytes = head.size;
216
+ }
217
+ if (bytes === null) {
218
+ console.warn(`storage-usage: could not size ${key}; the counter will read LOW until a reconcile`);
219
+ return;
220
+ }
221
+ await recordObjectWrite(db, key, bytes);
222
+ }
223
+ catch (e) {
224
+ console.warn(`storage-usage: failed to account a write of ${key} (${e.message}); the counter may read LOW until a reconcile`);
225
+ }
226
+ }
227
+ /** Account one completed delete. Never throws (same reason as accountWrite). */
228
+ async function accountDelete(db, key) {
229
+ try {
230
+ for (const k of Array.isArray(key) ? key : [key])
231
+ await recordObjectDelete(db, k);
232
+ }
233
+ catch (e) {
234
+ console.warn(`storage-usage: failed to account a delete of ${String(key)} (${e.message}); the counter may read HIGH until a reconcile`);
235
+ }
236
+ }
237
+ function meterStoreLike(target, db) {
238
+ if (target[METERED])
239
+ return target;
240
+ const proxy = new Proxy(target, {
241
+ get(t, prop) {
242
+ if (prop === METERED)
243
+ return true;
244
+ if (prop === "put") {
245
+ return async (key, value, opts) => {
246
+ const put = Reflect.get(t, "put");
247
+ const result = await put.call(t, key, value, opts);
248
+ await accountWrite(db, t, key, value);
249
+ return result;
250
+ };
251
+ }
252
+ if (prop === "delete") {
253
+ return async (key) => {
254
+ const del = Reflect.get(t, "delete");
255
+ const result = await del.call(t, key);
256
+ await accountDelete(db, key);
257
+ return result;
258
+ };
259
+ }
260
+ const value = Reflect.get(t, prop);
261
+ return typeof value === "function" ? value.bind(t) : value;
262
+ },
263
+ });
264
+ return proxy;
265
+ }
266
+ /** Wrap a Workers-shaped R2 bucket so every put/delete keeps the ledger current. Idempotent: wrapping an
267
+ * already-metered bucket returns it unchanged. Methods this core does not know about pass straight
268
+ * through, so a host binding keeps its full surface. */
269
+ export function meteredR2Bucket(bucket, db) {
270
+ return meterStoreLike(bucket, db);
271
+ }
272
+ /** Platform ICD twin of meteredR2Bucket, for a host whose renders store is an ObjectStore (the Node /
273
+ * MinIO door). Same accounting, same idempotence.
274
+ *
275
+ * Generic in the store type because the wrapper is a pass-through Proxy: a host store that extends
276
+ * ObjectStore (the Node ArtifactStore adds getBytes/getRange) keeps its full surface, and the type says
277
+ * so rather than narrowing the caller down to the ICD subset. */
278
+ export function meteredObjectStore(store, db) {
279
+ return meterStoreLike(store, db);
280
+ }
281
+ const _meteredObjectStorePreservesItsInput = true;
282
+ const _meteredR2BucketPreservesItsInput = true;
283
+ void _meteredObjectStorePreservesItsInput;
284
+ void _meteredR2BucketPreservesItsInput;
285
+ /** True when this store already meters its writes (test + wiring assertions). */
286
+ export function isMeteredStore(store) {
287
+ return store[METERED] === true;
288
+ }
289
+ /** Rebuild the ledger from the object store itself: the repair for accounting drift and the backfill for
290
+ * artifacts that predate accounting. Host-neutral, reading the store through the Platform ICD (list +
291
+ * head), never a CF-specific bucket-usage API.
292
+ *
293
+ * Operator-invokable, never automatic: it is O(objects) list/head calls, so a boot-time sweep would tax
294
+ * every cold start of every studio to fix a number that is usually already right. */
295
+ export async function reconcileStorageUsage(bucket, db, opts) {
296
+ const prefix = opts?.prefix ?? "";
297
+ const chunkSize = opts?.chunkSize ?? 100;
298
+ const sized = [];
299
+ let unsized = 0;
300
+ let cursor;
301
+ do {
302
+ const page = await bucket.list({ prefix, cursor });
303
+ for (const obj of page.objects) {
304
+ let bytes = typeof obj.size === "number" ? obj.size : null;
305
+ if (bytes === null) {
306
+ // A host whose list() omits size (ICD-optional): pay for one HEAD per object rather than
307
+ // reporting a number we did not measure.
308
+ const head = await bucket.head(obj.key);
309
+ bytes = head && typeof head.size === "number" ? head.size : null;
310
+ }
311
+ if (bytes === null)
312
+ unsized += 1;
313
+ sized.push({ key: obj.key, bytes: bytes ?? 0 });
314
+ }
315
+ cursor = page.truncated ? page.cursor : undefined;
316
+ } while (cursor);
317
+ // Replace, do not merge: the store is the authority, so a ledger row for an object that no longer
318
+ // exists (lifecycle-expired, deleted out of band) must disappear rather than survive a reconcile.
319
+ const deleteStmt = prefix
320
+ ? db.prepare("DELETE FROM storage_usage WHERE object_key LIKE ? || '%'").bind(prefix)
321
+ : db.prepare("DELETE FROM storage_usage").bind();
322
+ await deleteStmt.run();
323
+ const now = nowSeconds();
324
+ const insert = db.prepare(`INSERT INTO storage_usage (object_key, bytes, updated_at) VALUES (?, ?, ?)
325
+ ON CONFLICT(object_key) DO UPDATE SET bytes = excluded.bytes, updated_at = excluded.updated_at`);
326
+ for (let i = 0; i < sized.length; i += chunkSize) {
327
+ const chunk = sized.slice(i, i + chunkSize).map((row) => insert.bind(row.key, row.bytes, now));
328
+ if (db.batch)
329
+ await db.batch(chunk);
330
+ else
331
+ for (const stmt of chunk)
332
+ await stmt.run();
333
+ }
334
+ return {
335
+ objects: sized.length,
336
+ bytes: sized.reduce((sum, row) => sum + row.bytes, 0),
337
+ unsized,
338
+ };
339
+ }
340
+ //# sourceMappingURL=storage-quota.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage-quota.js","sourceRoot":"","sources":["../src/storage-quota.ts"],"names":[],"mappings":"AAAA,wFAAwF;AACxF,EAAE;AACF,sGAAsG;AACtG,uGAAuG;AACvG,sGAAsG;AACtG,wGAAwG;AACxG,4FAA4F;AAC5F,EAAE;AACF,sEAAsE;AACtE,+FAA+F;AAC/F,oGAAoG;AACpG,qGAAqG;AACrG,6CAA6C;AAC7C,EAAE;AACF,uGAAuG;AACvG,wGAAwG;AACxG,oGAAoG;AACpG,sGAAsG;AACtG,kGAAkG;AAClG,EAAE;AACF,qGAAqG;AACrG,uGAAuG;AACvG,4FAA4F;AAC5F,EAAE;AACF,oGAAoG;AACpG,oGAAoG;AACpG,qGAAqG;AACrG,oGAAoG;AACpG,uBAAuB;AACvB,EAAE;AACF,wGAAwG;AACxG,sGAAsG;AACtG,sGAAsG;AACtG,oGAAoG;AACpG,+CAA+C;AAK/C,qFAAqF;AAErF;2FAC2F;AAC3F,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;EAI/B,CAAC;AAYH;;oEAEoE;AACpE,MAAM,UAAU,iBAAiB,CAAC,GAAoB;IACpD,MAAM,GAAG,GAAG,GAAG,CAAC,sBAAsB,CAAC;IACvC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAC9D,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7B,OAAO,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACjD,CAAC;AAED,yFAAyF;AAEzF,SAAS,UAAU;IACjB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;AACvC,CAAC;AAED;+DAC+D;AAC/D,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,EAAY,EAAE,GAAW,EAAE,KAAa;IAC9E,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CAAC,qCAAqC,KAAK,cAAc,GAAG,EAAE,CAAC,CAAC;IACjF,CAAC;IACD,MAAM,EAAE;SACL,OAAO,CACN;sGACgG,CACjG;SACA,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;SAC1C,GAAG,EAAE,CAAC;AACX,CAAC;AAED;6DAC6D;AAC7D,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,EAAY,EAAE,GAAW;IAChE,MAAM,EAAE,CAAC,OAAO,CAAC,gDAAgD,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;AACrF,CAAC;AAED;mGACmG;AACnG,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,EAAY;IAC7C,MAAM,GAAG,GAAG,MAAM,EAAE;SACjB,OAAO,CAAC,iFAAiF,CAAC;SAC1F,IAAI,EAAE;SACN,KAAK,EAAoD,CAAC;IAC7D,OAAO;QACL,SAAS,EAAE,OAAO,GAAG,EAAE,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACzD,OAAO,EAAE,OAAO,GAAG,EAAE,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;KAC5D,CAAC;AACJ,CAAC;AAED,6BAA6B;AAC7B,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,EAAY;IACjD,OAAO,CAAC,MAAM,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAC5C,CAAC;AAYD,yGAAyG;AACzG,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,GAAoB;IAC1D,MAAM,UAAU,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;IAC1C,IAAI,UAAU,KAAK,IAAI;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;IAEhF,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,GAAG;YACX,SAAS,EAAE,IAAI;YACf,UAAU;YACV,OAAO,EAAE,yBAAyB,UAAU,mIAAmI;SAChL,CAAC;IACJ,CAAC;IAED,IAAI,SAAiB,CAAC;IACtB,IAAI,CAAC;QACH,SAAS,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,GAAG;YACX,SAAS,EAAE,IAAI;YACf,UAAU;YACV,OAAO,EAAE,+BAAgC,CAAW,CAAC,OAAO,8EAA8E;SAC3I,CAAC;IACJ,CAAC;IAED,sGAAsG;IACtG,6EAA6E;IAC7E,IAAI,SAAS,IAAI,UAAU,EAAE,CAAC;QAC5B,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,GAAG;YACX,SAAS;YACT,UAAU;YACV,OAAO,EAAE,0BAA0B,SAAS,wBAAwB,UAAU,wEAAwE;SACvJ,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC;AAC7C,CAAC;AAED,iGAAiG;AAEjG,wGAAwG;AACxG,uGAAuG;AACvG,uGAAuG;AACvG,8CAA8C;AAC9C,EAAE;AACF,kCAAkC;AAClC,uGAAuG;AACvG,qGAAqG;AACrG,oGAAoG;AACpG,iFAAiF;AACjF,uFAAuF;AACvF,uGAAuG;AACvG,oEAAoE;AACpE,MAAM,uBAAuB,GAAa;IACxC,kFAAkF;IAClF,iBAAiB;IACjB,mCAAmC;IACnC,oCAAoC;IACpC,6BAA6B;IAC7B,uBAAuB;IACvB,gCAAgC;IAChC,2BAA2B;IAC3B,8BAA8B;IAC9B,oFAAoF;IACpF,6BAA6B;IAC7B,sCAAsC;IACtC,4CAA4C;IAC5C,wBAAwB;IACxB,uBAAuB;IACvB,iDAAiD;IACjD,+CAA+C;IAC/C,oDAAoD;IACpD,qDAAqD;IACrD,gDAAgD;IAChD,oDAAoD;IACpD,qCAAqC;IACrC,kCAAkC;IAClC,sCAAsC;IACtC,oEAAoE;IACpE,gCAAgC;IAChC,qCAAqC;CACtC,CAAC;AAEF,8FAA8F;AAC9F,MAAM,UAAU,oBAAoB,CAAC,MAAc,EAAE,QAAgB;IACnE,IAAI,MAAM,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC;IACpC,OAAO,uBAAuB,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;AACjE,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,qBAAqB;IACnC,OAAO,CAAC,GAAG,uBAAuB,CAAC,CAAC;AACtC,CAAC;AAED,6FAA6F;AAE7F;;0EAE0E;AAC1E,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;AAEvD,oGAAoG;AACpG,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC;IACjF,IAAI,KAAK,YAAY,WAAW;QAAE,OAAO,KAAK,CAAC,UAAU,CAAC;IAC1D,IAAI,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,UAAU,CAAC;IACvD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;QACnE,MAAM,IAAI,GAAI,KAA4B,CAAC,IAAI,CAAC;QAChD,IAAI,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC,UAAU,CAAC;QACrD,IAAI,IAAI,YAAY,WAAW;YAAE,OAAO,IAAI,CAAC,UAAU,CAAC;IAC1D,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAMD,4FAA4F;AAC5F,KAAK,UAAU,YAAY,CAAC,EAAY,EAAE,MAAgB,EAAE,GAAW,EAAE,KAAc;IACrF,IAAI,CAAC;QACH,IAAI,KAAK,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;QACtC,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YACxD,iGAAiG;YACjG,uDAAuD;YACvD,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACpC,IAAI,IAAI,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ;gBAAE,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC;QAC/D,CAAC;QACD,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,OAAO,CAAC,IAAI,CAAC,iCAAiC,GAAG,+CAA+C,CAAC,CAAC;YAClG,OAAO;QACT,CAAC;QACD,MAAM,iBAAiB,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IAC1C,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,IAAI,CACV,+CAA+C,GAAG,KAAM,CAAW,CAAC,OAAO,+CAA+C,CAC3H,CAAC;IACJ,CAAC;AACH,CAAC;AAED,gFAAgF;AAChF,KAAK,UAAU,aAAa,CAAC,EAAY,EAAE,GAAsB;IAC/D,IAAI,CAAC;QACH,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;YAAE,MAAM,kBAAkB,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IACpF,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,IAAI,CACV,gDAAgD,MAAM,CAAC,GAAG,CAAC,KAAM,CAAW,CAAC,OAAO,gDAAgD,CACrI,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAmB,MAAS,EAAE,EAAY;IAC/D,IAAK,MAAkC,CAAC,OAAO,CAAC;QAAE,OAAO,MAAM,CAAC;IAChE,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,MAAM,EAAE;QAC9B,GAAG,CAAC,CAAC,EAAE,IAAI;YACT,IAAI,IAAI,KAAK,OAAO;gBAAE,OAAO,IAAI,CAAC;YAClC,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;gBACnB,OAAO,KAAK,EAAE,GAAW,EAAE,KAAc,EAAE,IAAc,EAAoB,EAAE;oBAC7E,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAA6D,CAAC;oBAC9F,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;oBACnD,MAAM,YAAY,CAAC,EAAE,EAAE,CAAa,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;oBAClD,OAAO,MAAM,CAAC;gBAChB,CAAC,CAAC;YACJ,CAAC;YACD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACtB,OAAO,KAAK,EAAE,GAAsB,EAAoB,EAAE;oBACxD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAA+C,CAAC;oBACnF,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;oBACtC,MAAM,aAAa,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;oBAC7B,OAAO,MAAM,CAAC;gBAChB,CAAC,CAAC;YACJ,CAAC;YACD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;YACnC,OAAO,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAC7D,CAAC;KACF,CAAC,CAAC;IACH,OAAO,KAAU,CAAC;AACpB,CAAC;AAED;;yDAEyD;AACzD,MAAM,UAAU,eAAe,CAAqB,MAAS,EAAE,EAAY;IACzE,OAAO,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACpC,CAAC;AAED;;;;;kEAKkE;AAClE,MAAM,UAAU,kBAAkB,CAAwB,KAAQ,EAAE,EAAY;IAC9E,OAAO,cAAc,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACnC,CAAC;AAUD,MAAM,oCAAoC,GAAkD,IAAI,CAAC;AACjG,MAAM,iCAAiC,GAAgD,IAAI,CAAC;AAC5F,KAAK,oCAAoC,CAAC;AAC1C,KAAK,iCAAiC,CAAC;AAEvC,iFAAiF;AACjF,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,OAAQ,KAAiC,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;AAC9D,CAAC;AAkBD;;;;;sFAKsF;AACtF,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,MAAgB,EAChB,EAAY,EACZ,IAA8C;IAE9C,MAAM,MAAM,GAAG,IAAI,EAAE,MAAM,IAAI,EAAE,CAAC;IAClC,MAAM,SAAS,GAAG,IAAI,EAAE,SAAS,IAAI,GAAG,CAAC;IACzC,MAAM,KAAK,GAA0C,EAAE,CAAC;IACxD,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,IAAI,MAA0B,CAAC;IAC/B,GAAG,CAAC;QACF,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACnD,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,OAA2B,EAAE,CAAC;YACnD,IAAI,KAAK,GAAG,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;YAC3D,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBACnB,yFAAyF;gBACzF,yCAAyC;gBACzC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBACxC,KAAK,GAAG,IAAI,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;YACnE,CAAC;YACD,IAAI,KAAK,KAAK,IAAI;gBAAE,OAAO,IAAI,CAAC,CAAC;YACjC,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC;QAClD,CAAC;QACD,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IACpD,CAAC,QAAQ,MAAM,EAAE;IAEjB,kGAAkG;IAClG,kGAAkG;IAClG,MAAM,UAAU,GAAG,MAAM;QACvB,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,0DAA0D,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;QACrF,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC,IAAI,EAAE,CAAC;IACnD,MAAM,UAAU,CAAC,GAAG,EAAE,CAAC;IAEvB,MAAM,GAAG,GAAG,UAAU,EAAE,CAAC;IACzB,MAAM,MAAM,GAAG,EAAE,CAAC,OAAO,CACvB;oGACgG,CACjG,CAAC;IACF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,SAAS,EAAE,CAAC;QACjD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;QAC/F,IAAI,EAAE,CAAC,KAAK;YAAE,MAAM,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;;YAC/B,KAAK,MAAM,IAAI,IAAI,KAAK;gBAAE,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC;IAClD,CAAC;IAED,OAAO;QACL,OAAO,EAAE,KAAK,CAAC,MAAM;QACrB,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;QACrD,OAAO;KACR,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skyphusion-labs/vivijure-core",
3
- "version": "1.2.13",
3
+ "version": "1.3.0",
4
4
  "description": "Shared Vivijure orchestration unifying vivijure-cf and vivijure-local: module registry, film pipeline, Platform ICD.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "type": "module",