vidspotai-shared 1.0.104 → 1.0.106
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 +3 -1
- package/lib/globals/types.d.ts.map +1 -1
- package/lib/globals/types.js +8 -0
- package/lib/models/index.d.ts +1 -0
- package/lib/models/index.d.ts.map +1 -1
- package/lib/models/index.js +1 -0
- package/lib/models/organization.model.d.ts +69 -0
- package/lib/models/organization.model.d.ts.map +1 -0
- package/lib/models/organization.model.js +6 -0
- package/lib/models/user.model.d.ts +8 -0
- package/lib/models/user.model.d.ts.map +1 -1
- package/lib/services/aiGen/providers/bytedance/bytedance.service.d.ts.map +1 -1
- package/lib/services/aiGen/providers/bytedance/bytedance.service.js +7 -1
- package/lib/services/bullmq.service.d.ts +7 -0
- package/lib/services/bullmq.service.d.ts.map +1 -1
- package/lib/services/bullmq.service.js +9 -0
- package/lib/services/credit.service.d.ts.map +1 -1
- package/lib/services/credit.service.js +101 -1
- package/lib/services/email/index.d.ts +3 -0
- package/lib/services/email/index.d.ts.map +1 -0
- package/lib/services/email/index.js +18 -0
- package/lib/services/email/orgInvite.d.ts +25 -0
- package/lib/services/email/orgInvite.d.ts.map +1 -0
- package/lib/services/email/orgInvite.js +113 -0
- package/lib/services/email/resendClient.d.ts +12 -0
- package/lib/services/email/resendClient.d.ts.map +1 -0
- package/lib/services/email/resendClient.js +39 -0
- package/lib/services/firestore.service.d.ts +5 -0
- package/lib/services/firestore.service.d.ts.map +1 -1
- package/lib/services/firestore.service.js +13 -0
- package/lib/services/index.d.ts +2 -0
- package/lib/services/index.d.ts.map +1 -1
- package/lib/services/index.js +2 -0
- package/lib/services/organizationCredit.service.d.ts +36 -0
- package/lib/services/organizationCredit.service.d.ts.map +1 -0
- package/lib/services/organizationCredit.service.js +105 -0
- package/lib/services/translation/translation.service.d.ts.map +1 -1
- package/lib/services/translation/translation.service.js +23 -9
- package/package.json +2 -1
package/lib/globals/types.d.ts
CHANGED
|
@@ -397,7 +397,9 @@ export declare enum ERROR_CODE {
|
|
|
397
397
|
SERVICE_UNAVAILABLE = "SERVICE_UNAVAILABLE",
|
|
398
398
|
UNSUPPORTED_PARAMS = "UNSUPPORTED_PARAMS",
|
|
399
399
|
SOCIAL_NOT_ENTITLED = "SOCIAL_NOT_ENTITLED",
|
|
400
|
-
SOCIAL_ACCOUNT_LIMIT = "SOCIAL_ACCOUNT_LIMIT"
|
|
400
|
+
SOCIAL_ACCOUNT_LIMIT = "SOCIAL_ACCOUNT_LIMIT",
|
|
401
|
+
ORG_INSUFFICIENT_CREDITS = "ORG_INSUFFICIENT_CREDITS",
|
|
402
|
+
ORG_MEMBER_ALLOCATION_EXCEEDED = "ORG_MEMBER_ALLOCATION_EXCEEDED"
|
|
401
403
|
}
|
|
402
404
|
export declare enum ELANGUAGE_CODE {
|
|
403
405
|
af = "af",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/globals/types.ts"],"names":[],"mappings":"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
|
|
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
|
@@ -445,6 +445,14 @@ var ERROR_CODE;
|
|
|
445
445
|
ERROR_CODE["SOCIAL_NOT_ENTITLED"] = "SOCIAL_NOT_ENTITLED";
|
|
446
446
|
// X8 Social Suite — the user is at their plan's connected-account limit.
|
|
447
447
|
ERROR_CODE["SOCIAL_ACCOUNT_LIMIT"] = "SOCIAL_ACCOUNT_LIMIT";
|
|
448
|
+
// Enterprise Organizations — the member's org pool doesn't have enough
|
|
449
|
+
// credits remaining. Distinct from INSUFFICIENT_CREDITS so the frontend can
|
|
450
|
+
// point the user at their org admin instead of a personal upgrade CTA.
|
|
451
|
+
ERROR_CODE["ORG_INSUFFICIENT_CREDITS"] = "ORG_INSUFFICIENT_CREDITS";
|
|
452
|
+
// Enterprise Organizations — the org is in "allocated" credit mode and this
|
|
453
|
+
// member has hit their monthly draw cap, even though the org pool itself
|
|
454
|
+
// still has room.
|
|
455
|
+
ERROR_CODE["ORG_MEMBER_ALLOCATION_EXCEEDED"] = "ORG_MEMBER_ALLOCATION_EXCEEDED";
|
|
448
456
|
})(ERROR_CODE || (exports.ERROR_CODE = ERROR_CODE = {}));
|
|
449
457
|
var ELANGUAGE_CODE;
|
|
450
458
|
(function (ELANGUAGE_CODE) {
|
package/lib/models/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/models/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/models/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC"}
|
package/lib/models/index.js
CHANGED
|
@@ -31,3 +31,4 @@ __exportStar(require("./githubConnection.model"), exports);
|
|
|
31
31
|
__exportStar(require("./productConnection.model"), exports);
|
|
32
32
|
__exportStar(require("./outreach.model"), exports);
|
|
33
33
|
__exportStar(require("./videoQaJob.model"), exports);
|
|
34
|
+
__exportStar(require("./organization.model"), exports);
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { FieldValue } from "firebase-admin/firestore";
|
|
2
|
+
/**
|
|
3
|
+
* Enterprise: Organizations & Team Members.
|
|
4
|
+
*
|
|
5
|
+
* MVP shape: a user belongs to at most one organization at a time
|
|
6
|
+
* (`IUserModel.organizationId`). The org owns a pooled credit balance funded
|
|
7
|
+
* by the owner transferring credits out of their own personal balance (no new
|
|
8
|
+
* Stripe/seat billing — see notes/ or the plan this shipped under). When
|
|
9
|
+
* `creditMode` is "allocated", each member additionally has a monthly draw
|
|
10
|
+
* cap (`IOrganizationMemberModel.monthlyAllocation`) carved out of the pool;
|
|
11
|
+
* in "shared" mode any member can spend from the full pool.
|
|
12
|
+
*/
|
|
13
|
+
export interface IOrganizationModel {
|
|
14
|
+
id: string;
|
|
15
|
+
name: string;
|
|
16
|
+
ownerId: string;
|
|
17
|
+
creditMode: "shared" | "allocated";
|
|
18
|
+
credits: {
|
|
19
|
+
total: number;
|
|
20
|
+
consumed: number;
|
|
21
|
+
};
|
|
22
|
+
createdAt: FieldValue;
|
|
23
|
+
updatedAt: FieldValue;
|
|
24
|
+
}
|
|
25
|
+
export type TOrgRole = "owner" | "admin" | "member";
|
|
26
|
+
/** Doc id = `${orgId}__${uid}` — mirrors IProductConnectionModel's composite-id convention. */
|
|
27
|
+
export interface IOrganizationMemberModel {
|
|
28
|
+
id: string;
|
|
29
|
+
orgId: string;
|
|
30
|
+
uid: string;
|
|
31
|
+
email: string;
|
|
32
|
+
role: TOrgRole;
|
|
33
|
+
/** Only meaningful when the org's creditMode is "allocated". */
|
|
34
|
+
monthlyAllocation?: {
|
|
35
|
+
total: number;
|
|
36
|
+
consumed: number;
|
|
37
|
+
/** Epoch ms of the next monthly reset. */
|
|
38
|
+
resetAt: number;
|
|
39
|
+
};
|
|
40
|
+
joinedAt: FieldValue;
|
|
41
|
+
}
|
|
42
|
+
export declare function organizationMemberDocId(orgId: string, uid: string): string;
|
|
43
|
+
export type TOrgInviteStatus = "pending" | "accepted" | "revoked" | "expired";
|
|
44
|
+
/** Doc id = the invite token itself (opaque, unguessable — acts as the credential). */
|
|
45
|
+
export interface IOrganizationInviteModel {
|
|
46
|
+
token: string;
|
|
47
|
+
orgId: string;
|
|
48
|
+
email: string;
|
|
49
|
+
role: TOrgRole;
|
|
50
|
+
invitedByUid: string;
|
|
51
|
+
status: TOrgInviteStatus;
|
|
52
|
+
createdAt: FieldValue;
|
|
53
|
+
expiresAt: number;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Append-only accountability trail for org pooled-credit movement. Personal
|
|
57
|
+
* credits have no ledger today (just a running counter) — a *shared* pool
|
|
58
|
+
* needs one from day one so an owner can see who spent what.
|
|
59
|
+
*/
|
|
60
|
+
export interface IOrganizationCreditLedgerEntry {
|
|
61
|
+
id: string;
|
|
62
|
+
orgId: string;
|
|
63
|
+
actorUid: string;
|
|
64
|
+
delta: number;
|
|
65
|
+
reason: "transfer_in" | "consume" | "refund" | "admin_adjust";
|
|
66
|
+
balanceAfter: number;
|
|
67
|
+
createdAt: FieldValue;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=organization.model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"organization.model.d.ts","sourceRoot":"","sources":["../../src/models/organization.model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEtD;;;;;;;;;;GAUG;AACH,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,QAAQ,GAAG,WAAW,CAAC;IACnC,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,SAAS,EAAE,UAAU,CAAC;IACtB,SAAS,EAAE,UAAU,CAAC;CACvB;AAED,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEpD,+FAA+F;AAC/F,MAAM,WAAW,wBAAwB;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;IACf,gEAAgE;IAChE,iBAAiB,CAAC,EAAE;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,0CAA0C;QAC1C,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,QAAQ,EAAE,UAAU,CAAC;CACtB;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAE1E;AAED,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,CAAC;AAE9E,uFAAuF;AACvF,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,gBAAgB,CAAC;IACzB,SAAS,EAAE,UAAU,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,8BAA8B;IAC7C,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,aAAa,GAAG,SAAS,GAAG,QAAQ,GAAG,cAAc,CAAC;IAC9D,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,UAAU,CAAC;CACvB"}
|
|
@@ -33,6 +33,14 @@ export interface IUserModel {
|
|
|
33
33
|
* per refresh cycle so we don't spam users who hover near the threshold.
|
|
34
34
|
*/
|
|
35
35
|
lastCreditsLowNotifiedAt?: FieldValue;
|
|
36
|
+
/**
|
|
37
|
+
* Enterprise Organizations — set when the user creates/joins an org, cleared
|
|
38
|
+
* when they leave. MVP: a user belongs to at most one org at a time. When
|
|
39
|
+
* present, `CreditService.consumeCredits`/`refundCredits` transparently
|
|
40
|
+
* redirect to the org's pooled balance instead of this user's personal
|
|
41
|
+
* `credits` field — see organization.model.ts.
|
|
42
|
+
*/
|
|
43
|
+
organizationId?: string;
|
|
36
44
|
}
|
|
37
45
|
export interface IUserCredts {
|
|
38
46
|
total: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user.model.d.ts","sourceRoot":"","sources":["../../src/models/user.model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EACL,SAAS,EACT,kBAAkB,EAElB,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,EACxB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,YAAY,CAAC;IACtC,SAAS,EAAE,UAAU,CAAC;IACtB,SAAS,EAAE,UAAU,CAAC;IACtB,QAAQ,EAAE,YAAY,GAAG,UAAU,GAAG,WAAW,GAAG,MAAM,CAAC;IAC3D,aAAa,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,YAAY,CAAC,EAAE,iBAAiB,CAAC;IACjC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE;QAEf,SAAS,EAAE,MAAM,CAAC;QAClB,aAAa,EAAE,YAAY,GAAG,WAAW,GAAG,QAAQ,CAAC;QACrD,aAAa,EAAE,IAAI,CAAC;KACrB,CAAC;IACF,QAAQ,CAAC,EAAE;QACT,SAAS,CAAC,EAAE,UAAU,CAAC;QACvB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;IACF;;;;OAIG;IACH,uBAAuB,CAAC,EAAE,uBAAuB,CAAC;IAClD;;;OAGG;IACH,wBAAwB,CAAC,EAAE,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"user.model.d.ts","sourceRoot":"","sources":["../../src/models/user.model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EACL,SAAS,EACT,kBAAkB,EAElB,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,EACxB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,YAAY,CAAC;IACtC,SAAS,EAAE,UAAU,CAAC;IACtB,SAAS,EAAE,UAAU,CAAC;IACtB,QAAQ,EAAE,YAAY,GAAG,UAAU,GAAG,WAAW,GAAG,MAAM,CAAC;IAC3D,aAAa,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,YAAY,CAAC,EAAE,iBAAiB,CAAC;IACjC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE;QAEf,SAAS,EAAE,MAAM,CAAC;QAClB,aAAa,EAAE,YAAY,GAAG,WAAW,GAAG,QAAQ,CAAC;QACrD,aAAa,EAAE,IAAI,CAAC;KACrB,CAAC;IACF,QAAQ,CAAC,EAAE;QACT,SAAS,CAAC,EAAE,UAAU,CAAC;QACvB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;IACF;;;;OAIG;IACH,uBAAuB,CAAC,EAAE,uBAAuB,CAAC;IAClD;;;OAGG;IACH,wBAAwB,CAAC,EAAE,UAAU,CAAC;IACtC;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,oBAAoB,CAAC;IAE7B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IAC/B,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAOrC"}
|
|
@@ -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;AAUlB,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;
|
|
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;AAUlB,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;IA4HjD,aAAa,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM;CAyEjD"}
|
|
@@ -94,12 +94,18 @@ class ByteDanceService extends baseAiGenProvider_service_1.BaseAiGenProviderServ
|
|
|
94
94
|
model: modelId,
|
|
95
95
|
content,
|
|
96
96
|
generate_audio: params.audio || false,
|
|
97
|
-
ratio: params.aspectRatio, // e.g. 16:9
|
|
98
97
|
resolution: params.resolution, // e.g. 720p
|
|
99
98
|
duration: params.duration, // seconds
|
|
100
99
|
watermark: false,
|
|
101
100
|
execution_expires_after: 172800, // 48h
|
|
102
101
|
};
|
|
102
|
+
// For first-frame / first-last-frame generation (an input image present),
|
|
103
|
+
// ByteDance derives the output ratio from the image itself and rejects an
|
|
104
|
+
// explicit `ratio` (InvalidParameter.TaskTypeConstraint, prod 2026-08-11).
|
|
105
|
+
// Only pure text-to-video sends the requested aspect ratio.
|
|
106
|
+
if (!params.inputImageUrl) {
|
|
107
|
+
body.ratio = params.aspectRatio; // e.g. 16:9
|
|
108
|
+
}
|
|
103
109
|
if (!this.isSeedance2(params.modelKey)) {
|
|
104
110
|
body.service_tier = "default";
|
|
105
111
|
}
|
|
@@ -40,6 +40,13 @@ declare class BullMQService {
|
|
|
40
40
|
* for the connection it blocks on.
|
|
41
41
|
*/
|
|
42
42
|
private getConnection;
|
|
43
|
+
/**
|
|
44
|
+
* Lightweight Redis reachability probe. Callers must race this against their
|
|
45
|
+
* own timeout — ioredis (offline queueing + infinite retryStrategy, see
|
|
46
|
+
* redisOptions.ts) will otherwise let this hang indefinitely against a dead
|
|
47
|
+
* Redis instead of rejecting.
|
|
48
|
+
*/
|
|
49
|
+
pingRedis(): Promise<void>;
|
|
43
50
|
/** Initialize BullMQ service (like your initRedis) */
|
|
44
51
|
init(): Promise<void>;
|
|
45
52
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bullmq.service.d.ts","sourceRoot":"","sources":["../../src/services/bullmq.service.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"bullmq.service.d.ts","sourceRoot":"","sources":["../../src/services/bullmq.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -65,6 +65,15 @@ class BullMQService {
|
|
|
65
65
|
(0, redisOptions_1.attachRedisListeners)(this.connection, "BullMQ");
|
|
66
66
|
return this.connection;
|
|
67
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Lightweight Redis reachability probe. Callers must race this against their
|
|
70
|
+
* own timeout — ioredis (offline queueing + infinite retryStrategy, see
|
|
71
|
+
* redisOptions.ts) will otherwise let this hang indefinitely against a dead
|
|
72
|
+
* Redis instead of rejecting.
|
|
73
|
+
*/
|
|
74
|
+
async pingRedis() {
|
|
75
|
+
await this.getConnection().ping();
|
|
76
|
+
}
|
|
68
77
|
/** Initialize BullMQ service (like your initRedis) */
|
|
69
78
|
async init() {
|
|
70
79
|
if (this.initialized)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credit.service.d.ts","sourceRoot":"","sources":["../../src/services/credit.service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"credit.service.d.ts","sourceRoot":"","sources":["../../src/services/credit.service.ts"],"names":[],"mappings":"AAcA,qBAAa,aAAa;WACX,cAAc,CACzB,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,IAAI,CAAC;WAwHH,aAAa,CACxB,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC;CA0EjB"}
|
|
@@ -5,6 +5,7 @@ const firestore_1 = require("firebase-admin/firestore");
|
|
|
5
5
|
const types_1 = require("../globals/types");
|
|
6
6
|
const firebase_1 = require("../libs/firebase");
|
|
7
7
|
const logger_1 = require("../utils/logger");
|
|
8
|
+
const organization_model_1 = require("../models/organization.model");
|
|
8
9
|
const firestore_service_1 = require("./firestore.service");
|
|
9
10
|
const notification_service_1 = require("./notification.service");
|
|
10
11
|
// Once balance drops below this fraction of total, fire CREDITS_LOW. The
|
|
@@ -25,6 +26,57 @@ class CreditService {
|
|
|
25
26
|
throw new Error("USER_NOT_FOUND");
|
|
26
27
|
}
|
|
27
28
|
const data = snap.data();
|
|
29
|
+
// Enterprise Organizations: a member spends from their org's pooled
|
|
30
|
+
// balance instead of their own — transparent to every call site (~30+
|
|
31
|
+
// across controllers/queue-workers/mcp-server all just call
|
|
32
|
+
// consumeCredits(userId, n)). Must live in THIS transaction — Firestore
|
|
33
|
+
// doesn't support nested transactions, so this can't call out to
|
|
34
|
+
// OrganizationCreditService, which owns the separate (non-nested)
|
|
35
|
+
// owner-tops-up-pool transaction.
|
|
36
|
+
const orgId = data.organizationId;
|
|
37
|
+
if (orgId) {
|
|
38
|
+
const orgRef = firestore_service_1.FirestoreService.organizationsCol.doc(orgId);
|
|
39
|
+
const memberRef = firestore_service_1.FirestoreService.organizationMembersCol.doc((0, organization_model_1.organizationMemberDocId)(orgId, userId));
|
|
40
|
+
const [orgSnap, memberSnap] = await Promise.all([
|
|
41
|
+
tx.get(orgRef),
|
|
42
|
+
tx.get(memberRef),
|
|
43
|
+
]);
|
|
44
|
+
if (!orgSnap.exists)
|
|
45
|
+
throw new Error("ORG_NOT_FOUND");
|
|
46
|
+
if (!memberSnap.exists)
|
|
47
|
+
throw new Error("ORG_MEMBER_NOT_FOUND");
|
|
48
|
+
const orgData = orgSnap.data();
|
|
49
|
+
const orgConsumed = orgData?.credits?.consumed ?? 0;
|
|
50
|
+
const orgTotal = orgData?.credits?.total ?? 0;
|
|
51
|
+
if (orgConsumed + creditsToConsume > orgTotal) {
|
|
52
|
+
throw new Error("ORG_INSUFFICIENT_CREDITS");
|
|
53
|
+
}
|
|
54
|
+
const allocation = memberSnap.data()?.monthlyAllocation;
|
|
55
|
+
if (orgData?.creditMode === "allocated" && allocation) {
|
|
56
|
+
const memberConsumed = allocation.consumed ?? 0;
|
|
57
|
+
if (memberConsumed + creditsToConsume > allocation.total) {
|
|
58
|
+
throw new Error("ORG_MEMBER_ALLOCATION_EXCEEDED");
|
|
59
|
+
}
|
|
60
|
+
tx.update(memberRef, {
|
|
61
|
+
"monthlyAllocation.consumed": memberConsumed + creditsToConsume,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
const newOrgConsumed = orgConsumed + creditsToConsume;
|
|
65
|
+
tx.update(orgRef, { "credits.consumed": newOrgConsumed });
|
|
66
|
+
const ledgerRef = firestore_service_1.FirestoreService.organizationCreditLedgerCol.doc();
|
|
67
|
+
tx.set(ledgerRef, {
|
|
68
|
+
id: ledgerRef.id,
|
|
69
|
+
orgId,
|
|
70
|
+
actorUid: userId,
|
|
71
|
+
delta: -creditsToConsume,
|
|
72
|
+
reason: "consume",
|
|
73
|
+
balanceAfter: orgTotal - newOrgConsumed,
|
|
74
|
+
createdAt: firestore_1.FieldValue.serverTimestamp(),
|
|
75
|
+
});
|
|
76
|
+
// Signal the org path to the caller so the personal CREDITS_LOW flow
|
|
77
|
+
// below is skipped — org-pool-low notifications are a fast-follow.
|
|
78
|
+
return { orgSpend: true, total: 0, newRemaining: 0, lastNotifiedMs: 0 };
|
|
79
|
+
}
|
|
28
80
|
const consumed = data.credits?.consumed ?? 0;
|
|
29
81
|
const total = data.credits?.total ?? 0;
|
|
30
82
|
if (consumed + creditsToConsume > total) {
|
|
@@ -35,8 +87,10 @@ class CreditService {
|
|
|
35
87
|
});
|
|
36
88
|
const newRemaining = total - (consumed + creditsToConsume);
|
|
37
89
|
const lastNotifiedMs = data.lastCreditsLowNotifiedAt?.toMillis?.() ?? 0;
|
|
38
|
-
return { total, newRemaining, lastNotifiedMs };
|
|
90
|
+
return { orgSpend: false, total, newRemaining, lastNotifiedMs };
|
|
39
91
|
});
|
|
92
|
+
if (postState.orgSpend)
|
|
93
|
+
return;
|
|
40
94
|
const { total, newRemaining, lastNotifiedMs } = postState;
|
|
41
95
|
if (total > 0 && newRemaining < total * CREDITS_LOW_THRESHOLD) {
|
|
42
96
|
const sinceLast = Date.now() - lastNotifiedMs;
|
|
@@ -72,6 +126,52 @@ class CreditService {
|
|
|
72
126
|
if (!snap.exists) {
|
|
73
127
|
throw new Error("USER_NOT_FOUND");
|
|
74
128
|
}
|
|
129
|
+
// Mirrors consumeCredits' org redirect. Known MVP edge case: this
|
|
130
|
+
// refunds to whatever pool the user CURRENTLY belongs to, not
|
|
131
|
+
// necessarily the one that was actually charged — if a member leaves
|
|
132
|
+
// (or joins) an org in the window between a job's upfront charge and
|
|
133
|
+
// its completion/refund, the refund lands on the wrong pool. Jobs
|
|
134
|
+
// resolve on the order of minutes, so this is accepted as low-risk for
|
|
135
|
+
// MVP rather than threading a `spentFrom` tag through every job type.
|
|
136
|
+
const orgId = snap.data()?.organizationId;
|
|
137
|
+
if (orgId) {
|
|
138
|
+
const orgRef = firestore_service_1.FirestoreService.organizationsCol.doc(orgId);
|
|
139
|
+
const memberRef = firestore_service_1.FirestoreService.organizationMembersCol.doc((0, organization_model_1.organizationMemberDocId)(orgId, userId));
|
|
140
|
+
const [orgSnap, memberSnap] = await Promise.all([
|
|
141
|
+
tx.get(orgRef),
|
|
142
|
+
tx.get(memberRef),
|
|
143
|
+
]);
|
|
144
|
+
// Org/membership may have been deleted since the charge — swallow
|
|
145
|
+
// like the personal path's own "can't go below 0" clamp; there's
|
|
146
|
+
// nowhere left to refund to.
|
|
147
|
+
if (!orgSnap.exists)
|
|
148
|
+
return;
|
|
149
|
+
const orgData = orgSnap.data();
|
|
150
|
+
const orgConsumed = orgData?.credits?.consumed ?? 0;
|
|
151
|
+
const orgTotal = orgData?.credits?.total ?? 0;
|
|
152
|
+
const newOrgConsumed = Math.max(0, orgConsumed - creditsToRefund);
|
|
153
|
+
tx.update(orgRef, { "credits.consumed": newOrgConsumed });
|
|
154
|
+
const allocation = memberSnap.exists
|
|
155
|
+
? memberSnap.data()?.monthlyAllocation
|
|
156
|
+
: undefined;
|
|
157
|
+
if (orgData?.creditMode === "allocated" && allocation && memberSnap.exists) {
|
|
158
|
+
const newMemberConsumed = Math.max(0, (allocation.consumed ?? 0) - creditsToRefund);
|
|
159
|
+
tx.update(memberRef, {
|
|
160
|
+
"monthlyAllocation.consumed": newMemberConsumed,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
const ledgerRef = firestore_service_1.FirestoreService.organizationCreditLedgerCol.doc();
|
|
164
|
+
tx.set(ledgerRef, {
|
|
165
|
+
id: ledgerRef.id,
|
|
166
|
+
orgId,
|
|
167
|
+
actorUid: userId,
|
|
168
|
+
delta: creditsToRefund,
|
|
169
|
+
reason: "refund",
|
|
170
|
+
balanceAfter: orgTotal - newOrgConsumed,
|
|
171
|
+
createdAt: firestore_1.FieldValue.serverTimestamp(),
|
|
172
|
+
});
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
75
175
|
const consumed = snap.data()?.credits?.consumed ?? 0;
|
|
76
176
|
// Never let consumed go below 0
|
|
77
177
|
const newConsumed = Math.max(0, consumed - creditsToRefund);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/email/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
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("./resendClient"), exports);
|
|
18
|
+
__exportStar(require("./orgInvite"), exports);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { TOrgRole } from "../../models/organization.model";
|
|
2
|
+
export interface SendOrgInviteEmailInput {
|
|
3
|
+
/** Invitee's email address. */
|
|
4
|
+
to: string;
|
|
5
|
+
orgName: string;
|
|
6
|
+
/** Display name (or email, if no name set) of the org member sending the invite. */
|
|
7
|
+
inviterName: string;
|
|
8
|
+
role: TOrgRole;
|
|
9
|
+
/** Full accept-invite URL, e.g. `${FRONTEND_URL}/invite/${token}`. */
|
|
10
|
+
acceptUrl: string;
|
|
11
|
+
}
|
|
12
|
+
export interface SendOrgInviteEmailResult {
|
|
13
|
+
/** Resend message id. */
|
|
14
|
+
id: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Sends the org-invite email via Resend. Throws on misconfiguration or a
|
|
18
|
+
* Resend-reported failure — this is intentional: callers that want
|
|
19
|
+
* best-effort semantics (the invite doc + copyable link are already the
|
|
20
|
+
* source of truth) should call this WITHOUT awaiting and chain `.catch()` to
|
|
21
|
+
* log rather than fail the parent request. See
|
|
22
|
+
* `organization.controller.ts#createInvite`.
|
|
23
|
+
*/
|
|
24
|
+
export declare function sendOrgInviteEmail(input: SendOrgInviteEmailInput): Promise<SendOrgInviteEmailResult>;
|
|
25
|
+
//# sourceMappingURL=orgInvite.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orgInvite.d.ts","sourceRoot":"","sources":["../../../src/services/email/orgInvite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAM3D,MAAM,WAAW,uBAAuB;IACtC,+BAA+B;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,oFAAoF;IACpF,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,QAAQ,CAAC;IACf,sEAAsE;IACtE,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,wBAAwB;IACvC,yBAAyB;IACzB,EAAE,EAAE,MAAM,CAAC;CACZ;AAiFD;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,uBAAuB,GAC7B,OAAO,CAAC,wBAAwB,CAAC,CA2BnC"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sendOrgInviteEmail = sendOrgInviteEmail;
|
|
4
|
+
const logger_1 = require("../../utils/logger");
|
|
5
|
+
const resendClient_1 = require("./resendClient");
|
|
6
|
+
const log = (0, logger_1.createLogger)("email:orgInvite");
|
|
7
|
+
const ROLE_LABEL = {
|
|
8
|
+
owner: "Owner",
|
|
9
|
+
admin: "Admin",
|
|
10
|
+
member: "Member",
|
|
11
|
+
};
|
|
12
|
+
/** Minimal HTML-escaping for the handful of user-controlled strings we interpolate. */
|
|
13
|
+
function esc(s) {
|
|
14
|
+
return s
|
|
15
|
+
.replace(/&/g, "&")
|
|
16
|
+
.replace(/</g, "<")
|
|
17
|
+
.replace(/>/g, ">")
|
|
18
|
+
.replace(/"/g, """)
|
|
19
|
+
.replace(/'/g, "'");
|
|
20
|
+
}
|
|
21
|
+
function renderHtml(input) {
|
|
22
|
+
const orgName = esc(input.orgName);
|
|
23
|
+
const inviterName = esc(input.inviterName);
|
|
24
|
+
const roleLabel = ROLE_LABEL[input.role] ?? input.role;
|
|
25
|
+
const acceptUrl = esc(input.acceptUrl);
|
|
26
|
+
// Inline styles only — email clients don't reliably support external/embedded CSS.
|
|
27
|
+
return `<!doctype html>
|
|
28
|
+
<html>
|
|
29
|
+
<body style="margin:0;padding:0;background-color:#f4f4f7;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;">
|
|
30
|
+
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background-color:#f4f4f7;padding:32px 16px;">
|
|
31
|
+
<tr>
|
|
32
|
+
<td align="center">
|
|
33
|
+
<table role="presentation" width="480" cellpadding="0" cellspacing="0" style="max-width:480px;width:100%;background-color:#ffffff;border-radius:12px;overflow:hidden;border:1px solid #e5e5ea;">
|
|
34
|
+
<tr>
|
|
35
|
+
<td style="padding:32px 32px 24px 32px;text-align:center;">
|
|
36
|
+
<div style="font-size:20px;font-weight:700;color:#111114;">VidSpotAI</div>
|
|
37
|
+
</td>
|
|
38
|
+
</tr>
|
|
39
|
+
<tr>
|
|
40
|
+
<td style="padding:0 32px 8px 32px;">
|
|
41
|
+
<h1 style="margin:0 0 16px 0;font-size:18px;line-height:1.4;color:#111114;">
|
|
42
|
+
${inviterName} invited you to join <strong>${orgName}</strong>
|
|
43
|
+
</h1>
|
|
44
|
+
<p style="margin:0 0 24px 0;font-size:14px;line-height:1.6;color:#52525b;">
|
|
45
|
+
You've been invited to join the <strong>${orgName}</strong> team on VidSpotAI as
|
|
46
|
+
a <strong>${esc(roleLabel)}</strong>. Accept the invite to start collaborating
|
|
47
|
+
on AI-generated video projects together.
|
|
48
|
+
</p>
|
|
49
|
+
</td>
|
|
50
|
+
</tr>
|
|
51
|
+
<tr>
|
|
52
|
+
<td style="padding:0 32px 32px 32px;text-align:center;">
|
|
53
|
+
<a href="${acceptUrl}"
|
|
54
|
+
style="display:inline-block;background:linear-gradient(90deg,#6366f1,#a855f7,#ec4899);color:#ffffff;text-decoration:none;font-size:14px;font-weight:600;padding:12px 28px;border-radius:8px;">
|
|
55
|
+
Accept invite
|
|
56
|
+
</a>
|
|
57
|
+
</td>
|
|
58
|
+
</tr>
|
|
59
|
+
<tr>
|
|
60
|
+
<td style="padding:0 32px 32px 32px;">
|
|
61
|
+
<p style="margin:0;font-size:12px;line-height:1.6;color:#a1a1aa;">
|
|
62
|
+
If the button doesn't work, copy and paste this link into your browser:<br />
|
|
63
|
+
<a href="${acceptUrl}" style="color:#6366f1;word-break:break-all;">${acceptUrl}</a>
|
|
64
|
+
</p>
|
|
65
|
+
</td>
|
|
66
|
+
</tr>
|
|
67
|
+
<tr>
|
|
68
|
+
<td style="padding:20px 32px;background-color:#fafafa;border-top:1px solid #e5e5ea;">
|
|
69
|
+
<p style="margin:0;font-size:11px;line-height:1.5;color:#a1a1aa;">
|
|
70
|
+
This invite expires in 14 days. If you weren't expecting this, you can safely
|
|
71
|
+
ignore this email.
|
|
72
|
+
</p>
|
|
73
|
+
</td>
|
|
74
|
+
</tr>
|
|
75
|
+
</table>
|
|
76
|
+
</td>
|
|
77
|
+
</tr>
|
|
78
|
+
</table>
|
|
79
|
+
</body>
|
|
80
|
+
</html>`;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Sends the org-invite email via Resend. Throws on misconfiguration or a
|
|
84
|
+
* Resend-reported failure — this is intentional: callers that want
|
|
85
|
+
* best-effort semantics (the invite doc + copyable link are already the
|
|
86
|
+
* source of truth) should call this WITHOUT awaiting and chain `.catch()` to
|
|
87
|
+
* log rather than fail the parent request. See
|
|
88
|
+
* `organization.controller.ts#createInvite`.
|
|
89
|
+
*/
|
|
90
|
+
async function sendOrgInviteEmail(input) {
|
|
91
|
+
if (!(0, resendClient_1.isResendConfigured)()) {
|
|
92
|
+
throw new Error("sendOrgInviteEmail: RESEND_API_KEY not set");
|
|
93
|
+
}
|
|
94
|
+
const resend = (0, resendClient_1.getResendClient)();
|
|
95
|
+
const subject = `${input.inviterName} invited you to join ${input.orgName} on VidSpotAI`;
|
|
96
|
+
const { data, error } = await resend.emails.send({
|
|
97
|
+
from: resendClient_1.EMAIL_FROM,
|
|
98
|
+
to: input.to,
|
|
99
|
+
subject,
|
|
100
|
+
html: renderHtml(input),
|
|
101
|
+
});
|
|
102
|
+
if (error || !data?.id) {
|
|
103
|
+
const detail = error?.message ?? "no message id returned";
|
|
104
|
+
throw new Error(`sendOrgInviteEmail: Resend send failed — ${detail}`);
|
|
105
|
+
}
|
|
106
|
+
log.info("sendOrgInviteEmail sent", {
|
|
107
|
+
to: input.to,
|
|
108
|
+
orgName: input.orgName,
|
|
109
|
+
role: input.role,
|
|
110
|
+
id: data.id,
|
|
111
|
+
});
|
|
112
|
+
return { id: data.id };
|
|
113
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Resend } from "resend";
|
|
2
|
+
/** True once RESEND_API_KEY is configured. Gate email-sending on this. */
|
|
3
|
+
export declare function isResendConfigured(): boolean;
|
|
4
|
+
/** Lazily-constructed singleton Resend client. Throws if not configured. */
|
|
5
|
+
export declare function getResendClient(): Resend;
|
|
6
|
+
/**
|
|
7
|
+
* Verified sending domain (DKIM/SPF confirmed in Resend for vidspotai.com).
|
|
8
|
+
* Keep the display name generic — individual senders can override the
|
|
9
|
+
* subject/body per email type.
|
|
10
|
+
*/
|
|
11
|
+
export declare const EMAIL_FROM = "VidSpotAI <noreply@vidspotai.com>";
|
|
12
|
+
//# sourceMappingURL=resendClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resendClient.d.ts","sourceRoot":"","sources":["../../../src/services/email/resendClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAgBhC,0EAA0E;AAC1E,wBAAgB,kBAAkB,IAAI,OAAO,CAE5C;AAED,4EAA4E;AAC5E,wBAAgB,eAAe,IAAI,MAAM,CASxC;AAED;;;;GAIG;AACH,eAAO,MAAM,UAAU,sCAAsC,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EMAIL_FROM = void 0;
|
|
4
|
+
exports.isResendConfigured = isResendConfigured;
|
|
5
|
+
exports.getResendClient = getResendClient;
|
|
6
|
+
const resend_1 = require("resend");
|
|
7
|
+
/**
|
|
8
|
+
* Thin Resend client wrapper. Mirrors the other single-provider wrappers in
|
|
9
|
+
* this codebase (e.g. `services/demo/githubOAuth.ts`): a lazy singleton keyed
|
|
10
|
+
* off an env var, a `isXConfigured()` gate the caller can check before doing
|
|
11
|
+
* real work, and a getter that throws a descriptive error instead of letting
|
|
12
|
+
* the SDK fail on `undefined`.
|
|
13
|
+
*
|
|
14
|
+
* Env:
|
|
15
|
+
* RESEND_API_KEY — Resend API key (Doppler `vidspotai-backend` / `dev`
|
|
16
|
+
* config only for now; NOT set in `prd`).
|
|
17
|
+
*/
|
|
18
|
+
let client = null;
|
|
19
|
+
/** True once RESEND_API_KEY is configured. Gate email-sending on this. */
|
|
20
|
+
function isResendConfigured() {
|
|
21
|
+
return Boolean(process.env.RESEND_API_KEY);
|
|
22
|
+
}
|
|
23
|
+
/** Lazily-constructed singleton Resend client. Throws if not configured. */
|
|
24
|
+
function getResendClient() {
|
|
25
|
+
const apiKey = process.env.RESEND_API_KEY;
|
|
26
|
+
if (!apiKey) {
|
|
27
|
+
throw new Error("resend: RESEND_API_KEY not set");
|
|
28
|
+
}
|
|
29
|
+
if (!client) {
|
|
30
|
+
client = new resend_1.Resend(apiKey);
|
|
31
|
+
}
|
|
32
|
+
return client;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Verified sending domain (DKIM/SPF confirmed in Resend for vidspotai.com).
|
|
36
|
+
* Keep the display name generic — individual senders can override the
|
|
37
|
+
* subject/body per email type.
|
|
38
|
+
*/
|
|
39
|
+
exports.EMAIL_FROM = "VidSpotAI <noreply@vidspotai.com>";
|
|
@@ -17,6 +17,7 @@ import { IVideoQaJobModel } from "../models/videoQaJob.model";
|
|
|
17
17
|
import { IGithubConnectionModel } from "../models/githubConnection.model";
|
|
18
18
|
import { IProductConnectionModel } from "../models/productConnection.model";
|
|
19
19
|
import { IOutreachCampaignModel, IOutreachRecipientModel, IOutreachTemplateModel, IPersonalizedVideoModel, IVideoViewModel } from "../models/outreach.model";
|
|
20
|
+
import { IOrganizationCreditLedgerEntry, IOrganizationInviteModel, IOrganizationMemberModel, IOrganizationModel } from "../models/organization.model";
|
|
20
21
|
/**
|
|
21
22
|
* FirestoreService
|
|
22
23
|
* ----------------
|
|
@@ -80,6 +81,10 @@ export declare class FirestoreService {
|
|
|
80
81
|
static outreachCampaignsCol: CollectionReference<IOutreachCampaignModel, DocumentData>;
|
|
81
82
|
static outreachRecipientsCol: CollectionReference<IOutreachRecipientModel, DocumentData>;
|
|
82
83
|
static videoViewsCol: CollectionReference<IVideoViewModel, DocumentData>;
|
|
84
|
+
static organizationsCol: CollectionReference<IOrganizationModel, DocumentData>;
|
|
85
|
+
static organizationMembersCol: CollectionReference<IOrganizationMemberModel, DocumentData>;
|
|
86
|
+
static organizationInvitesCol: CollectionReference<IOrganizationInviteModel, DocumentData>;
|
|
87
|
+
static organizationCreditLedgerCol: CollectionReference<IOrganizationCreditLedgerEntry, DocumentData>;
|
|
83
88
|
/**
|
|
84
89
|
* Sentinel for `.update()` that removes a field from a doc (wraps
|
|
85
90
|
* `FieldValue.delete()`). Use to clear a transient field — e.g. plan-B's
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"firestore.service.d.ts","sourceRoot":"","sources":["../../src/services/firestore.service.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EAEZ,gBAAgB,EAEhB,aAAa,EACd,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,iBAAiB,EAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhD,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,qBAAqB,EACrB,gBAAgB,EACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AAC5E,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,sBAAsB,EACtB,uBAAuB,EACvB,eAAe,EAChB,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"firestore.service.d.ts","sourceRoot":"","sources":["../../src/services/firestore.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -217,3 +217,16 @@ FirestoreService.outreachRecipientsCol = firebase_1.firestore
|
|
|
217
217
|
FirestoreService.videoViewsCol = firebase_1.firestore
|
|
218
218
|
.collection("videoViews")
|
|
219
219
|
.withConverter(collectionConverter());
|
|
220
|
+
// Enterprise: Organizations & Team Members
|
|
221
|
+
FirestoreService.organizationsCol = firebase_1.firestore
|
|
222
|
+
.collection("organizations")
|
|
223
|
+
.withConverter(collectionConverter());
|
|
224
|
+
FirestoreService.organizationMembersCol = firebase_1.firestore
|
|
225
|
+
.collection("organizationMembers")
|
|
226
|
+
.withConverter(collectionConverter());
|
|
227
|
+
FirestoreService.organizationInvitesCol = firebase_1.firestore
|
|
228
|
+
.collection("organizationInvites")
|
|
229
|
+
.withConverter(collectionConverter());
|
|
230
|
+
FirestoreService.organizationCreditLedgerCol = firebase_1.firestore
|
|
231
|
+
.collection("organizationCreditLedger")
|
|
232
|
+
.withConverter(collectionConverter());
|
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,OAAO,CAAC;AACtB,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,OAAO,CAAC;AACtB,cAAc,eAAe,CAAC;AAC9B,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"}
|
|
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,OAAO,CAAC;AACtB,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,OAAO,CAAC;AACtB,cAAc,eAAe,CAAC;AAC9B,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"}
|
package/lib/services/index.js
CHANGED
|
@@ -51,3 +51,5 @@ __exportStar(require("./socialAI"), exports);
|
|
|
51
51
|
__exportStar(require("./socialInsights"), exports);
|
|
52
52
|
__exportStar(require("./socialAccounts"), exports);
|
|
53
53
|
__exportStar(require("./freePlan"), exports);
|
|
54
|
+
__exportStar(require("./organizationCredit.service"), exports);
|
|
55
|
+
__exportStar(require("./email"), exports);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enterprise: Organizations & Team Members — credit-pool funding.
|
|
3
|
+
*
|
|
4
|
+
* Day-to-day spend/refund against the pool happens transparently inside
|
|
5
|
+
* `CreditService.consumeCredits`/`refundCredits` (redirected there when the
|
|
6
|
+
* acting user has `organizationId` set, within the SAME transaction as the
|
|
7
|
+
* personal-credit path would have used — Firestore transactions can't nest,
|
|
8
|
+
* so that logic lives inline in credit.service.ts rather than calling out to
|
|
9
|
+
* this file). This service covers the one op that's genuinely distinct: the
|
|
10
|
+
* owner moving credits FROM their own personal balance INTO the org pool.
|
|
11
|
+
* No new Stripe/seat billing — the pool is funded entirely this way for MVP.
|
|
12
|
+
*/
|
|
13
|
+
export declare class OrganizationCreditService {
|
|
14
|
+
/**
|
|
15
|
+
* Owner-only. Reads owner's user doc + the org doc, then in the same
|
|
16
|
+
* transaction: increments the owner's personal `credits.consumed` (spends
|
|
17
|
+
* `amount` of their own remaining balance) and increments the org's
|
|
18
|
+
* `credits.total` (tops up the pool) by the same amount. Throws
|
|
19
|
+
* "INSUFFICIENT_CREDITS" if the owner doesn't have `amount` remaining —
|
|
20
|
+
* reusing the existing personal error code since this is, from the owner's
|
|
21
|
+
* point of view, spending their own balance.
|
|
22
|
+
*/
|
|
23
|
+
static transferToOrgPool(orgId: string, ownerUid: string, amount: number): Promise<{
|
|
24
|
+
orgTotal: number;
|
|
25
|
+
orgRemaining: number;
|
|
26
|
+
}>;
|
|
27
|
+
/**
|
|
28
|
+
* Owner/admin-set monthly draw cap for a member (only meaningful once the
|
|
29
|
+
* org's creditMode is "allocated"). Setting `monthlyTotal` to undefined
|
|
30
|
+
* clears the member's allocation (falls back to full-pool access if the org
|
|
31
|
+
* later flips back to "shared", or is simply uncapped within "allocated"
|
|
32
|
+
* mode until set again).
|
|
33
|
+
*/
|
|
34
|
+
static setMemberAllocation(orgId: string, memberUid: string, monthlyTotal: number | undefined): Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=organizationCredit.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"organizationCredit.service.d.ts","sourceRoot":"","sources":["../../src/services/organizationCredit.service.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;GAWG;AACH,qBAAa,yBAAyB;IACpC;;;;;;;;OAQG;WACU,iBAAiB,CAC5B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;IAqDtD;;;;;;OAMG;WACU,mBAAmB,CAC9B,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GAAG,SAAS,GAC/B,OAAO,CAAC,IAAI,CAAC;CA0BjB"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OrganizationCreditService = void 0;
|
|
4
|
+
const firestore_1 = require("firebase-admin/firestore");
|
|
5
|
+
const firebase_1 = require("../libs/firebase");
|
|
6
|
+
const organization_model_1 = require("../models/organization.model");
|
|
7
|
+
const firestore_service_1 = require("./firestore.service");
|
|
8
|
+
/**
|
|
9
|
+
* Enterprise: Organizations & Team Members — credit-pool funding.
|
|
10
|
+
*
|
|
11
|
+
* Day-to-day spend/refund against the pool happens transparently inside
|
|
12
|
+
* `CreditService.consumeCredits`/`refundCredits` (redirected there when the
|
|
13
|
+
* acting user has `organizationId` set, within the SAME transaction as the
|
|
14
|
+
* personal-credit path would have used — Firestore transactions can't nest,
|
|
15
|
+
* so that logic lives inline in credit.service.ts rather than calling out to
|
|
16
|
+
* this file). This service covers the one op that's genuinely distinct: the
|
|
17
|
+
* owner moving credits FROM their own personal balance INTO the org pool.
|
|
18
|
+
* No new Stripe/seat billing — the pool is funded entirely this way for MVP.
|
|
19
|
+
*/
|
|
20
|
+
class OrganizationCreditService {
|
|
21
|
+
/**
|
|
22
|
+
* Owner-only. Reads owner's user doc + the org doc, then in the same
|
|
23
|
+
* transaction: increments the owner's personal `credits.consumed` (spends
|
|
24
|
+
* `amount` of their own remaining balance) and increments the org's
|
|
25
|
+
* `credits.total` (tops up the pool) by the same amount. Throws
|
|
26
|
+
* "INSUFFICIENT_CREDITS" if the owner doesn't have `amount` remaining —
|
|
27
|
+
* reusing the existing personal error code since this is, from the owner's
|
|
28
|
+
* point of view, spending their own balance.
|
|
29
|
+
*/
|
|
30
|
+
static async transferToOrgPool(orgId, ownerUid, amount) {
|
|
31
|
+
if (!Number.isFinite(amount) || amount <= 0) {
|
|
32
|
+
throw new Error("INVALID_AMOUNT");
|
|
33
|
+
}
|
|
34
|
+
return firebase_1.firestore.runTransaction(async (tx) => {
|
|
35
|
+
const userRef = firestore_service_1.FirestoreService.usersCol.doc(ownerUid);
|
|
36
|
+
const orgRef = firestore_service_1.FirestoreService.organizationsCol.doc(orgId);
|
|
37
|
+
// All reads before any writes (Firestore transaction requirement).
|
|
38
|
+
const [userSnap, orgSnap] = await Promise.all([
|
|
39
|
+
tx.get(userRef),
|
|
40
|
+
tx.get(orgRef),
|
|
41
|
+
]);
|
|
42
|
+
if (!userSnap.exists)
|
|
43
|
+
throw new Error("USER_NOT_FOUND");
|
|
44
|
+
if (!orgSnap.exists)
|
|
45
|
+
throw new Error("ORG_NOT_FOUND");
|
|
46
|
+
const userData = userSnap.data();
|
|
47
|
+
const orgData = orgSnap.data();
|
|
48
|
+
if (orgData?.ownerId !== ownerUid) {
|
|
49
|
+
throw new Error("ORG_NOT_OWNER");
|
|
50
|
+
}
|
|
51
|
+
const userConsumed = userData?.credits?.consumed ?? 0;
|
|
52
|
+
const userTotal = userData?.credits?.total ?? 0;
|
|
53
|
+
if (userConsumed + amount > userTotal) {
|
|
54
|
+
throw new Error("INSUFFICIENT_CREDITS");
|
|
55
|
+
}
|
|
56
|
+
const orgConsumed = orgData?.credits?.consumed ?? 0;
|
|
57
|
+
const orgTotal = orgData?.credits?.total ?? 0;
|
|
58
|
+
const newOrgTotal = orgTotal + amount;
|
|
59
|
+
tx.update(userRef, { "credits.consumed": userConsumed + amount });
|
|
60
|
+
tx.update(orgRef, { "credits.total": newOrgTotal });
|
|
61
|
+
const ledgerRef = firestore_service_1.FirestoreService.organizationCreditLedgerCol.doc();
|
|
62
|
+
tx.set(ledgerRef, {
|
|
63
|
+
id: ledgerRef.id,
|
|
64
|
+
orgId,
|
|
65
|
+
actorUid: ownerUid,
|
|
66
|
+
delta: amount,
|
|
67
|
+
reason: "transfer_in",
|
|
68
|
+
balanceAfter: newOrgTotal - orgConsumed,
|
|
69
|
+
createdAt: firestore_1.FieldValue.serverTimestamp(),
|
|
70
|
+
});
|
|
71
|
+
return { orgTotal: newOrgTotal, orgRemaining: newOrgTotal - orgConsumed };
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Owner/admin-set monthly draw cap for a member (only meaningful once the
|
|
76
|
+
* org's creditMode is "allocated"). Setting `monthlyTotal` to undefined
|
|
77
|
+
* clears the member's allocation (falls back to full-pool access if the org
|
|
78
|
+
* later flips back to "shared", or is simply uncapped within "allocated"
|
|
79
|
+
* mode until set again).
|
|
80
|
+
*/
|
|
81
|
+
static async setMemberAllocation(orgId, memberUid, monthlyTotal) {
|
|
82
|
+
const memberRef = firestore_service_1.FirestoreService.organizationMembersCol.doc((0, organization_model_1.organizationMemberDocId)(orgId, memberUid));
|
|
83
|
+
const snap = await memberRef.get();
|
|
84
|
+
if (!snap.exists)
|
|
85
|
+
throw new Error("ORG_MEMBER_NOT_FOUND");
|
|
86
|
+
if (monthlyTotal === undefined) {
|
|
87
|
+
await memberRef.update({
|
|
88
|
+
monthlyAllocation: firestore_service_1.FirestoreService.deleteField(),
|
|
89
|
+
});
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (!Number.isFinite(monthlyTotal) || monthlyTotal < 0) {
|
|
93
|
+
throw new Error("INVALID_AMOUNT");
|
|
94
|
+
}
|
|
95
|
+
const existing = snap.data()?.monthlyAllocation;
|
|
96
|
+
await memberRef.update({
|
|
97
|
+
monthlyAllocation: {
|
|
98
|
+
total: monthlyTotal,
|
|
99
|
+
consumed: existing?.consumed ?? 0,
|
|
100
|
+
resetAt: existing?.resetAt ?? Date.now() + 30 * 24 * 60 * 60 * 1000,
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
exports.OrganizationCreditService = OrganizationCreditService;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translation.service.d.ts","sourceRoot":"","sources":["../../../src/services/translation/translation.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGlE;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,eAAO,MAAM,kBAAkB,uBAAuB,CAAC;AAqGvD;;;;GAIG;AACH,iBAAe,SAAS,CACtB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,cAAc,EACpB,EAAE,GAAE,cAAkC,EACtC,OAAO,GAAE,IAAI,GAAG,IAAW,GAC1B,OAAO,CAAC,MAAM,CAAC,CAsCjB;
|
|
1
|
+
{"version":3,"file":"translation.service.d.ts","sourceRoot":"","sources":["../../../src/services/translation/translation.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGlE;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,eAAO,MAAM,kBAAkB,uBAAuB,CAAC;AAqGvD;;;;GAIG;AACH,iBAAe,SAAS,CACtB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,cAAc,EACpB,EAAE,GAAE,cAAkC,EACtC,OAAO,GAAE,IAAI,GAAG,IAAW,GAC1B,OAAO,CAAC,MAAM,CAAC,CAsCjB;AAiDD;;;;;;;;;;;;;;GAcG;AACH,iBAAe,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CA8ChE;AAOD,eAAO,MAAM,kBAAkB;;;CAG9B,CAAC;AAGF,qDAAqD;AACrD,eAAO,MAAM,qBAAqB,kBAAY,CAAC;AAC/C,0DAA0D;AAC1D,eAAO,MAAM,UAAU,uBAAiB,CAAC"}
|
|
@@ -199,15 +199,29 @@ async function callLlmDetect(text) {
|
|
|
199
199
|
"code of the language the user's text is written in — two lowercase " +
|
|
200
200
|
'letters, nothing else (e.g. "es", "ja", "ar"). Use "zh-cn" or "zh-tw" ' +
|
|
201
201
|
"for Chinese. No punctuation, no explanation.";
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
202
|
+
// Bounded the same way as callLlmTranslate (see comment above it): this is
|
|
203
|
+
// called synchronously from POST /v1/video/generate before the BullMQ
|
|
204
|
+
// enqueue, so an unbounded generateText here stalls the HTTP request all
|
|
205
|
+
// the way to the Cloud Run 300s ceiling instead of failing over to the
|
|
206
|
+
// "default to en" path below.
|
|
207
|
+
let timer;
|
|
208
|
+
const { text: out } = await Promise.race([
|
|
209
|
+
service.generateText({
|
|
210
|
+
// Only the opening slice matters for identification, and capping it
|
|
211
|
+
// keeps this cheap when a long-form brief triggers the fallback.
|
|
212
|
+
input: [
|
|
213
|
+
{ role: "system", content: system },
|
|
214
|
+
{ role: "user", content: text.slice(0, 1000) },
|
|
215
|
+
],
|
|
216
|
+
modelKey: FALLBACK_MODEL,
|
|
217
|
+
options: { temperature: 0 },
|
|
218
|
+
}),
|
|
219
|
+
new Promise((_, reject) => {
|
|
220
|
+
timer = setTimeout(() => reject(new Error(`LLM detect timed out after ${FALLBACK_TIMEOUT_MS}ms`)), FALLBACK_TIMEOUT_MS);
|
|
221
|
+
}),
|
|
222
|
+
]).finally(() => {
|
|
223
|
+
if (timer)
|
|
224
|
+
clearTimeout(timer);
|
|
211
225
|
});
|
|
212
226
|
const code = (out ?? "").trim().toLowerCase().replace(/[^a-z-]/g, "");
|
|
213
227
|
if (!/^[a-z]{2}(-[a-z]{2})?$/.test(code)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vidspotai-shared",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.106",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"types": "lib/index.d.ts",
|
|
6
6
|
"exports": {
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"jsonwebtoken": "^9.0.2",
|
|
31
31
|
"logform": "^2.7.0",
|
|
32
32
|
"openai": "^6.1.0",
|
|
33
|
+
"resend": "^6.19.0",
|
|
33
34
|
"winston": "^3.19.0",
|
|
34
35
|
"winston-loki": "^6.1.3",
|
|
35
36
|
"winston-slack-webhook-transport": "^2.3.6",
|