@mevdragon/vidfarm-devcli 0.2.14 → 0.3.1

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.
Files changed (204) hide show
  1. package/README.md +11 -4
  2. package/SKILL.director.md +100 -0
  3. package/SKILL.platform.md +66 -6
  4. package/dist/src/cli.js +135 -1527
  5. package/package.json +5 -24
  6. package/.env.example +0 -60
  7. package/auto-create-hyperframe-templates/AUTO_CREATE_HYPERFRAME_TEMPLATES.md +0 -275
  8. package/auto-create-hyperframe-templates/extractor-system-prompt.md +0 -128
  9. package/auto-create-hyperframe-templates/input-manifest.schema.json +0 -56
  10. package/auto-create-hyperframe-templates/lambda-memory-estimator.md +0 -118
  11. package/auto-create-hyperframe-templates/production-graph.schema.json +0 -314
  12. package/auto-create-hyperframe-templates/runbook.md +0 -198
  13. package/auto-create-hyperframe-templates/scripts/create-hyperframe-template.mjs +0 -368
  14. package/auto-create-hyperframe-templates/template-plan.schema.json +0 -311
  15. package/auto-create-hyperframe-templates/template-planner-prompt.md +0 -144
  16. package/auto-create-templates/AUTO_CREATE_TEMPLATES.md +0 -599
  17. package/auto-create-templates/extractor-system-prompt.md +0 -119
  18. package/auto-create-templates/production-graph.schema.json +0 -276
  19. package/auto-create-templates/runbook.md +0 -140
  20. package/auto-create-templates/template-plan.schema.json +0 -301
  21. package/auto-create-templates/template-planner-prompt.md +0 -137
  22. package/dist/src/account-pages-legacy.js +0 -9338
  23. package/dist/src/account-pages-legacy.js.map +0 -1
  24. package/dist/src/account-pages.js +0 -52
  25. package/dist/src/account-pages.js.map +0 -1
  26. package/dist/src/app.js +0 -13711
  27. package/dist/src/app.js.map +0 -1
  28. package/dist/src/cli.js.map +0 -1
  29. package/dist/src/composition-runtime.js +0 -581
  30. package/dist/src/composition-runtime.js.map +0 -1
  31. package/dist/src/config.js +0 -140
  32. package/dist/src/config.js.map +0 -1
  33. package/dist/src/context.js +0 -492
  34. package/dist/src/context.js.map +0 -1
  35. package/dist/src/dev-app-legacy.js +0 -694
  36. package/dist/src/dev-app-legacy.js.map +0 -1
  37. package/dist/src/dev-app.js +0 -6
  38. package/dist/src/dev-app.js.map +0 -1
  39. package/dist/src/dev-serve.js.map +0 -1
  40. package/dist/src/domain.js +0 -2
  41. package/dist/src/domain.js.map +0 -1
  42. package/dist/src/editor-chat-history.js +0 -82
  43. package/dist/src/editor-chat-history.js.map +0 -1
  44. package/dist/src/editor-chat.js +0 -312
  45. package/dist/src/editor-chat.js.map +0 -1
  46. package/dist/src/editor-dark-theme.js +0 -1128
  47. package/dist/src/editor-dark-theme.js.map +0 -1
  48. package/dist/src/frontend/flockposter-cache-store.js +0 -124
  49. package/dist/src/frontend/flockposter-cache-store.js.map +0 -1
  50. package/dist/src/frontend/homepage-client.js +0 -117
  51. package/dist/src/frontend/homepage-client.js.map +0 -1
  52. package/dist/src/frontend/homepage-shared.js +0 -4
  53. package/dist/src/frontend/homepage-shared.js.map +0 -1
  54. package/dist/src/frontend/homepage-store.js +0 -28
  55. package/dist/src/frontend/homepage-store.js.map +0 -1
  56. package/dist/src/frontend/homepage-view.js +0 -260
  57. package/dist/src/frontend/homepage-view.js.map +0 -1
  58. package/dist/src/frontend/page-runtime-client.js +0 -124
  59. package/dist/src/frontend/page-runtime-client.js.map +0 -1
  60. package/dist/src/frontend/page-runtime-store.js +0 -9
  61. package/dist/src/frontend/page-runtime-store.js.map +0 -1
  62. package/dist/src/frontend/sentry.js +0 -42
  63. package/dist/src/frontend/sentry.js.map +0 -1
  64. package/dist/src/frontend/template-editor-chat.js +0 -3760
  65. package/dist/src/frontend/template-editor-chat.js.map +0 -1
  66. package/dist/src/help-page.js +0 -333
  67. package/dist/src/help-page.js.map +0 -1
  68. package/dist/src/homepage.js +0 -919
  69. package/dist/src/homepage.js.map +0 -1
  70. package/dist/src/hyperframes/composition.js +0 -180
  71. package/dist/src/hyperframes/composition.js.map +0 -1
  72. package/dist/src/index.js +0 -16
  73. package/dist/src/index.js.map +0 -1
  74. package/dist/src/instrument.js +0 -30
  75. package/dist/src/instrument.js.map +0 -1
  76. package/dist/src/lib/crypto.js +0 -45
  77. package/dist/src/lib/crypto.js.map +0 -1
  78. package/dist/src/lib/dev-log.js +0 -54
  79. package/dist/src/lib/dev-log.js.map +0 -1
  80. package/dist/src/lib/display-name.js +0 -11
  81. package/dist/src/lib/display-name.js.map +0 -1
  82. package/dist/src/lib/ids.js +0 -24
  83. package/dist/src/lib/ids.js.map +0 -1
  84. package/dist/src/lib/images.js +0 -19
  85. package/dist/src/lib/images.js.map +0 -1
  86. package/dist/src/lib/json.js +0 -15
  87. package/dist/src/lib/json.js.map +0 -1
  88. package/dist/src/lib/template-dna.js +0 -543
  89. package/dist/src/lib/template-dna.js.map +0 -1
  90. package/dist/src/lib/template-paths.js +0 -28
  91. package/dist/src/lib/template-paths.js.map +0 -1
  92. package/dist/src/lib/template-style-options.js +0 -203
  93. package/dist/src/lib/template-style-options.js.map +0 -1
  94. package/dist/src/lib/time.js +0 -7
  95. package/dist/src/lib/time.js.map +0 -1
  96. package/dist/src/lib/video-quality-harness.js +0 -60
  97. package/dist/src/lib/video-quality-harness.js.map +0 -1
  98. package/dist/src/page-runtime.js +0 -2
  99. package/dist/src/page-runtime.js.map +0 -1
  100. package/dist/src/page-shell.js +0 -1315
  101. package/dist/src/page-shell.js.map +0 -1
  102. package/dist/src/primitive-context.js +0 -299
  103. package/dist/src/primitive-context.js.map +0 -1
  104. package/dist/src/primitive-registry.js +0 -2181
  105. package/dist/src/primitive-registry.js.map +0 -1
  106. package/dist/src/primitive-sdk.js +0 -4
  107. package/dist/src/primitive-sdk.js.map +0 -1
  108. package/dist/src/primitives/remotion/html-image.js +0 -30
  109. package/dist/src/primitives/remotion/html-image.js.map +0 -1
  110. package/dist/src/primitives/remotion/media-slideshow.js +0 -60
  111. package/dist/src/primitives/remotion/media-slideshow.js.map +0 -1
  112. package/dist/src/react-page-shell.js +0 -35
  113. package/dist/src/react-page-shell.js.map +0 -1
  114. package/dist/src/ready-post-schedule-component.js +0 -1515
  115. package/dist/src/ready-post-schedule-component.js.map +0 -1
  116. package/dist/src/registry.js +0 -296
  117. package/dist/src/registry.js.map +0 -1
  118. package/dist/src/runtime.js +0 -31
  119. package/dist/src/runtime.js.map +0 -1
  120. package/dist/src/services/api-call-history.js +0 -249
  121. package/dist/src/services/api-call-history.js.map +0 -1
  122. package/dist/src/services/auth.js +0 -152
  123. package/dist/src/services/auth.js.map +0 -1
  124. package/dist/src/services/billing.js +0 -231
  125. package/dist/src/services/billing.js.map +0 -1
  126. package/dist/src/services/chat-threads.js +0 -92
  127. package/dist/src/services/chat-threads.js.map +0 -1
  128. package/dist/src/services/fork-access.js +0 -93
  129. package/dist/src/services/fork-access.js.map +0 -1
  130. package/dist/src/services/fork-manifest.js +0 -43
  131. package/dist/src/services/fork-manifest.js.map +0 -1
  132. package/dist/src/services/ghostcut.js +0 -132
  133. package/dist/src/services/ghostcut.js.map +0 -1
  134. package/dist/src/services/hyperframes.js +0 -1014
  135. package/dist/src/services/hyperframes.js.map +0 -1
  136. package/dist/src/services/job-capacity.js +0 -14
  137. package/dist/src/services/job-capacity.js.map +0 -1
  138. package/dist/src/services/job-logs.js +0 -197
  139. package/dist/src/services/job-logs.js.map +0 -1
  140. package/dist/src/services/jobs.js +0 -136
  141. package/dist/src/services/jobs.js.map +0 -1
  142. package/dist/src/services/media-processing.js +0 -743
  143. package/dist/src/services/media-processing.js.map +0 -1
  144. package/dist/src/services/primitive-media-lambda.js +0 -280
  145. package/dist/src/services/primitive-media-lambda.js.map +0 -1
  146. package/dist/src/services/providers.js +0 -2870
  147. package/dist/src/services/providers.js.map +0 -1
  148. package/dist/src/services/rate-limits.js +0 -237
  149. package/dist/src/services/rate-limits.js.map +0 -1
  150. package/dist/src/services/remotion.js +0 -688
  151. package/dist/src/services/remotion.js.map +0 -1
  152. package/dist/src/services/serverless-auth.js +0 -374
  153. package/dist/src/services/serverless-auth.js.map +0 -1
  154. package/dist/src/services/serverless-jobs.js +0 -1074
  155. package/dist/src/services/serverless-jobs.js.map +0 -1
  156. package/dist/src/services/serverless-provider-keys.js +0 -401
  157. package/dist/src/services/serverless-provider-keys.js.map +0 -1
  158. package/dist/src/services/serverless-records.js +0 -1088
  159. package/dist/src/services/serverless-records.js.map +0 -1
  160. package/dist/src/services/serverless-template-configs.js +0 -67
  161. package/dist/src/services/serverless-template-configs.js.map +0 -1
  162. package/dist/src/services/storage.js +0 -383
  163. package/dist/src/services/storage.js.map +0 -1
  164. package/dist/src/services/template-certification.js +0 -475
  165. package/dist/src/services/template-certification.js.map +0 -1
  166. package/dist/src/services/template-loader.js +0 -99
  167. package/dist/src/services/template-loader.js.map +0 -1
  168. package/dist/src/services/template-runtime-bundles.js +0 -217
  169. package/dist/src/services/template-runtime-bundles.js.map +0 -1
  170. package/dist/src/services/template-sources.js +0 -1017
  171. package/dist/src/services/template-sources.js.map +0 -1
  172. package/dist/src/services/video-normalization.js +0 -2
  173. package/dist/src/services/video-normalization.js.map +0 -1
  174. package/dist/src/services/webhooks.js +0 -62
  175. package/dist/src/services/webhooks.js.map +0 -1
  176. package/dist/src/template-editor-pages.js +0 -2491
  177. package/dist/src/template-editor-pages.js.map +0 -1
  178. package/dist/src/template-editor-shell.js +0 -2702
  179. package/dist/src/template-editor-shell.js.map +0 -1
  180. package/dist/src/template-sdk.js +0 -4
  181. package/dist/src/template-sdk.js.map +0 -1
  182. package/dist/src/worker.js +0 -17
  183. package/dist/src/worker.js.map +0 -1
  184. package/public/assets/homepage-app.js +0 -54
  185. package/public/assets/homepage-client-app.js +0 -80
  186. package/public/assets/page-runtime-client-app.js +0 -94
  187. package/readme.secret.md +0 -89
  188. package/templates/vidfarm_template_0000/README.md +0 -106
  189. package/templates/vidfarm_template_0000/SKILL.md +0 -266
  190. package/templates/vidfarm_template_0000/assets/Abel-Regular.ttf +0 -0
  191. package/templates/vidfarm_template_0000/assets/DMSerifDisplay-Regular.ttf +0 -0
  192. package/templates/vidfarm_template_0000/assets/Montserrat[wght].ttf +0 -0
  193. package/templates/vidfarm_template_0000/assets/SourceCodePro[wght].ttf +0 -0
  194. package/templates/vidfarm_template_0000/assets/TikTokSans-SemiBold.ttf +0 -0
  195. package/templates/vidfarm_template_0000/assets/Yesteryear-Regular.ttf +0 -0
  196. package/templates/vidfarm_template_0000/composition.json +0 -11
  197. package/templates/vidfarm_template_0000/src/lib/images.js +0 -221
  198. package/templates/vidfarm_template_0000/src/remotion/Root.js +0 -33
  199. package/templates/vidfarm_template_0000/src/remotion/index.js +0 -3
  200. package/templates/vidfarm_template_0000/src/sdk.js +0 -3
  201. package/templates/vidfarm_template_0000/src/style-options.js +0 -200
  202. package/templates/vidfarm_template_0000/src/template-dna.js +0 -9
  203. package/templates/vidfarm_template_0000/src/template.js +0 -1566
  204. package/templates/vidfarm_template_0000/template.config.json +0 -21
@@ -1,152 +0,0 @@
1
- import { randomInt } from "node:crypto";
2
- import { config } from "../config.js";
3
- import { encryptString, hashPassword, hashSecret, safeEqualHash, verifyPassword } from "../lib/crypto.js";
4
- import { displayNameFromEmail } from "../lib/display-name.js";
5
- import { createId } from "../lib/ids.js";
6
- import { addSeconds, nowIso } from "../lib/time.js";
7
- import { ServerlessAuthService } from "./serverless-auth.js";
8
- export class AuthService {
9
- serverless = new ServerlessAuthService();
10
- async requestOtp(email) {
11
- const code = `${randomInt(100000, 999999)}`;
12
- await this.serverless.insertOtpChallenge({
13
- id: createId("otp"),
14
- email,
15
- codeHash: hashSecret(code),
16
- expiresAt: addSeconds(new Date(), 600)
17
- });
18
- if (config.RESEND_API_KEY) {
19
- const response = await fetch("https://api.resend.com/emails", {
20
- method: "POST",
21
- headers: {
22
- "Content-Type": "application/json",
23
- Authorization: `Bearer ${config.RESEND_API_KEY}`
24
- },
25
- body: JSON.stringify({
26
- from: config.RESEND_FROM_EMAIL,
27
- to: email,
28
- subject: "Your Vidfarm login code",
29
- text: `Your login code is ${code}. It expires in 10 minutes.`
30
- })
31
- });
32
- if (!response.ok) {
33
- const body = await response.text();
34
- throw new Error(`Unable to send OTP email (${response.status}): ${body || "empty response body"}`);
35
- }
36
- return {
37
- delivery: "email"
38
- };
39
- }
40
- else {
41
- console.log(`[vidfarm] OTP for ${email}: ${code}`);
42
- return {
43
- delivery: "console",
44
- code: config.isProduction ? undefined : code
45
- };
46
- }
47
- }
48
- async verifyOtp(email, code, name) {
49
- const challenge = await this.serverless.findLatestOtpChallenge(email);
50
- if (!challenge) {
51
- throw new Error("No OTP challenge found for that email.");
52
- }
53
- if (challenge.consumed_at) {
54
- throw new Error("OTP challenge already used.");
55
- }
56
- if (new Date(String(challenge.expires_at)).getTime() < Date.now()) {
57
- throw new Error("OTP challenge expired.");
58
- }
59
- if (!safeEqualHash(code, String(challenge.code_hash))) {
60
- throw new Error("Invalid OTP code.");
61
- }
62
- await this.serverless.consumeOtpChallenge(email, String(challenge.id));
63
- const existing = await this.serverless.getCustomerByEmailPublic(email);
64
- const normalizedEmail = email.trim().toLowerCase();
65
- const customer = await this.serverless.upsertCustomer({
66
- id: existing?.id ?? createId("cus"),
67
- email: normalizedEmail,
68
- name: name?.trim() || existing?.name || displayNameFromEmail(normalizedEmail),
69
- defaultWebhookUrl: existing?.defaultWebhookUrl ?? null,
70
- isDeveloper: existing?.isDeveloper || config.adminEmails.includes(normalizedEmail),
71
- isPaidPlan: existing?.isPaidPlan ?? false,
72
- planTier: existing?.planTier ?? "client"
73
- });
74
- const rawApiKey = `vf_${createId("key")}`;
75
- await this.serverless.insertApiKey({
76
- id: createId("api"),
77
- customerId: customer.id,
78
- keyHash: hashSecret(rawApiKey + config.API_KEY_SALT),
79
- rawValue: rawApiKey,
80
- label: `Issued ${nowIso()}`
81
- });
82
- return { customer, apiKey: rawApiKey };
83
- }
84
- authenticate(apiKey) {
85
- throw new Error("Use authenticateAsync; DynamoDB authentication is asynchronous.");
86
- }
87
- async authenticateAsync(apiKey) {
88
- return this.serverless.authenticate(apiKey);
89
- }
90
- async verifyOtpForBrowserLogin(email, code, name) {
91
- const result = await this.verifyOtp(email, code, name);
92
- if (!result.customer.isPaidPlan) {
93
- return {
94
- status: "pricing",
95
- customer: result.customer
96
- };
97
- }
98
- return {
99
- status: "authenticated",
100
- customer: result.customer
101
- };
102
- }
103
- async authenticateWithPassword(email, password) {
104
- const row = await this.serverless.getCustomerAuthByEmail(email);
105
- if (!row || !row.password_hash || !verifyPassword(password, String(row.password_hash))) {
106
- throw new Error("Invalid email or password.");
107
- }
108
- const customer = await this.serverless.getCustomerById(String(row.customer_id ?? row.id));
109
- if (!customer) {
110
- throw new Error("Customer not found.");
111
- }
112
- await this.serverless.updateCustomerPassword(customer.id, String(row.password_hash), encryptString(password, config.ENCRYPTION_SECRET));
113
- if (!customer.isPaidPlan) {
114
- return {
115
- status: "pricing",
116
- customer
117
- };
118
- }
119
- return {
120
- status: "authenticated",
121
- customer
122
- };
123
- }
124
- async createPasswordUser(input) {
125
- const normalizedEmail = input.email.trim().toLowerCase();
126
- const existing = await this.serverless.getCustomerByEmailPublic(normalizedEmail);
127
- return this.serverless.upsertCustomer({
128
- id: existing?.id ?? createId("cus"),
129
- email: normalizedEmail,
130
- name: input.name?.trim() || existing?.name || displayNameFromEmail(normalizedEmail),
131
- defaultWebhookUrl: existing?.defaultWebhookUrl ?? null,
132
- isDeveloper: existing?.isDeveloper || config.adminEmails.includes(normalizedEmail),
133
- isPaidPlan: true,
134
- planTier: input.planTier ?? existing?.planTier ?? "client",
135
- passwordHash: hashPassword(input.password),
136
- encryptedPassword: encryptString(input.password, config.ENCRYPTION_SECRET)
137
- });
138
- }
139
- }
140
- function normalizePlanTier(value) {
141
- if (value === "client" || value === "standalone" || value === "agency") {
142
- return value;
143
- }
144
- if (value === "invisible" || value === "starter") {
145
- return "client";
146
- }
147
- if (value === "standard") {
148
- return "standalone";
149
- }
150
- return "client";
151
- }
152
- //# sourceMappingURL=auth.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/services/auth.ts"],"names":[],"mappings":"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"}
@@ -1,231 +0,0 @@
1
- import { createHash } from "node:crypto";
2
- import { serverlessRecords } from "./serverless-records.js";
3
- import { createId } from "../lib/ids.js";
4
- import { config } from "../config.js";
5
- const BILLING_COST_EVENTS_PATH = "/v1/cost-events";
6
- const BILLING_WALLET_GRANTS_PATH = "/v1/wallet-grants";
7
- const PAID_SIGNUP_BONUS_GRANT_TYPE = "paid_signup_bonus";
8
- const PAID_SIGNUP_BONUS_USD = 5;
9
- export class BillingService {
10
- async getWalletSummary(customerId) {
11
- if (!config.VIDFARM_BILLING_URL || !config.VIDFARM_BILLING_SECRET) {
12
- throw new Error("Billing service is not configured.");
13
- }
14
- const response = await fetch(new URL(`/v1/wallets/${encodeURIComponent(customerId)}`, config.VIDFARM_BILLING_URL), {
15
- headers: {
16
- "x-vidfarm-billing-secret": config.VIDFARM_BILLING_SECRET
17
- }
18
- });
19
- if (!response.ok) {
20
- const body = await response.text().catch(() => "");
21
- throw new Error(`Billing wallet lookup failed (${response.status}): ${body || response.statusText}`);
22
- }
23
- const payload = await response.json();
24
- return {
25
- currency: typeof payload.currency === "string" ? payload.currency : "USD",
26
- balanceUsd: Number(payload.balance_usd ?? 0),
27
- balanceMicrosUsd: Number(payload.balance_micros_usd ?? 0)
28
- };
29
- }
30
- async getJobBillingSummary(input) {
31
- if (!config.VIDFARM_BILLING_URL || !config.VIDFARM_BILLING_SECRET) {
32
- return {
33
- currency: "USD",
34
- eventCount: 0,
35
- totalBaseCostUsd: 0,
36
- totalChargeUsd: 0,
37
- unavailableReason: "Billing service is not configured."
38
- };
39
- }
40
- const url = new URL(`/v1/jobs/${encodeURIComponent(input.jobId)}/billing`, config.VIDFARM_BILLING_URL);
41
- url.searchParams.set("customer_id", input.customerId);
42
- if (input.templateId) {
43
- url.searchParams.set("template_id", input.templateId);
44
- }
45
- const response = await fetch(url, {
46
- headers: {
47
- "x-vidfarm-billing-secret": config.VIDFARM_BILLING_SECRET
48
- }
49
- });
50
- if (!response.ok) {
51
- const body = await response.text().catch(() => "");
52
- throw new Error(`Billing job summary lookup failed (${response.status}): ${body || response.statusText}`);
53
- }
54
- const payload = await response.json();
55
- return {
56
- currency: typeof payload.currency === "string" ? payload.currency : "USD",
57
- eventCount: Number(payload.event_count ?? 0),
58
- totalBaseCostUsd: Number(payload.total_base_cost_usd ?? 0),
59
- totalChargeUsd: Number(payload.total_charge_usd ?? 0),
60
- unavailableReason: null
61
- };
62
- }
63
- async record(input) {
64
- const normalizedCostCenterSlug = resolveCostCenterSlug(input);
65
- const normalizedIdempotencyKey = resolveIdempotencyKey(input, normalizedCostCenterSlug);
66
- const remoteEventCostCenterSlug = normalizedCostCenterSlug ?? null;
67
- if (!remoteEventCostCenterSlug) {
68
- return;
69
- }
70
- if (!config.VIDFARM_BILLING_URL || !config.VIDFARM_BILLING_SECRET) {
71
- throw new Error(`Billing URL/secret missing for cost center ${remoteEventCostCenterSlug}.`);
72
- }
73
- const response = await fetch(new URL(BILLING_COST_EVENTS_PATH, config.VIDFARM_BILLING_URL), {
74
- method: "POST",
75
- headers: {
76
- "content-type": "application/json",
77
- "x-vidfarm-billing-secret": config.VIDFARM_BILLING_SECRET
78
- },
79
- body: JSON.stringify({
80
- idempotency_key: normalizedIdempotencyKey ?? `${remoteEventCostCenterSlug}:${input.jobId}:${input.templateId}:${input.type}`,
81
- customer_id: input.customerId,
82
- job_id: input.jobId,
83
- tracer: input.tracer,
84
- cost_center_slug: remoteEventCostCenterSlug,
85
- base_cost_usd: input.costUsd,
86
- metadata: {
87
- ...input.metadata,
88
- template_id: input.templateId,
89
- local_charge_usd: input.chargeUsd
90
- },
91
- occurred_at_ms: input.occurredAtMs ?? Date.now()
92
- })
93
- });
94
- if (!response.ok) {
95
- const body = await response.text().catch(() => "");
96
- throw new Error(`Billing service rejected cost event (${response.status}): ${body || response.statusText}`);
97
- }
98
- await response.json().catch(() => ({}));
99
- }
100
- async grantPaidSignupBonus(customerId, metadata) {
101
- const customer = await serverlessRecords.getCustomerById(customerId);
102
- if (!customer) {
103
- throw new Error("Customer not found.");
104
- }
105
- if (!customer.isPaidPlan) {
106
- return { granted: false, reason: "customer_not_paid" };
107
- }
108
- if (await serverlessRecords.hasCustomerCreditGrant(customerId, PAID_SIGNUP_BONUS_GRANT_TYPE)) {
109
- return { granted: false, reason: "already_granted" };
110
- }
111
- if (!config.VIDFARM_BILLING_URL || !config.VIDFARM_BILLING_SECRET) {
112
- throw new Error("Billing service is not configured.");
113
- }
114
- const response = await fetch(new URL(BILLING_WALLET_GRANTS_PATH, config.VIDFARM_BILLING_URL), {
115
- method: "POST",
116
- headers: {
117
- "content-type": "application/json",
118
- "x-vidfarm-billing-secret": config.VIDFARM_BILLING_SECRET
119
- },
120
- body: JSON.stringify({
121
- idempotency_key: `${PAID_SIGNUP_BONUS_GRANT_TYPE}:${customerId}`,
122
- customer_id: customerId,
123
- amount_usd: PAID_SIGNUP_BONUS_USD,
124
- grant_type: PAID_SIGNUP_BONUS_GRANT_TYPE,
125
- occurred_at_ms: Date.now(),
126
- metadata: {
127
- ...(metadata ?? {}),
128
- grant_type: PAID_SIGNUP_BONUS_GRANT_TYPE
129
- }
130
- })
131
- });
132
- if (!response.ok) {
133
- const body = await response.text().catch(() => "");
134
- throw new Error(`Billing service rejected signup wallet grant (${response.status}): ${body || response.statusText}`);
135
- }
136
- try {
137
- await serverlessRecords.insertCustomerCreditGrant({
138
- id: createId("grant"),
139
- customerId,
140
- grantType: PAID_SIGNUP_BONUS_GRANT_TYPE,
141
- amountUsd: PAID_SIGNUP_BONUS_USD,
142
- metadata: metadata ?? {}
143
- });
144
- }
145
- catch (error) {
146
- if (!isUniqueConstraintError(error)) {
147
- throw error;
148
- }
149
- }
150
- return {
151
- granted: true,
152
- reason: "granted",
153
- amountUsd: PAID_SIGNUP_BONUS_USD,
154
- grantType: PAID_SIGNUP_BONUS_GRANT_TYPE
155
- };
156
- }
157
- }
158
- function resolveCostCenterSlug(input) {
159
- if (input.costCenterSlug?.trim()) {
160
- const explicitSlug = input.costCenterSlug.trim();
161
- return explicitSlug === "remotion_lambda"
162
- || explicitSlug === "video_normalization"
163
- || explicitSlug === "rapidapi_video_download"
164
- || explicitSlug === "video_download_lambda"
165
- || explicitSlug === "rapidapi_remove_background"
166
- || explicitSlug === "primitive_media_lambda"
167
- || explicitSlug === "job_runner_lambda"
168
- || explicitSlug === "step_functions_standard"
169
- ? explicitSlug
170
- : null;
171
- }
172
- if (input.type === "render" && input.metadata?.mode === "lambda") {
173
- return "remotion_lambda";
174
- }
175
- return null;
176
- }
177
- function resolveIdempotencyKey(input, costCenterSlug) {
178
- if (input.idempotencyKey?.trim()) {
179
- return input.idempotencyKey.trim();
180
- }
181
- const renderId = typeof input.metadata?.render_id === "string"
182
- ? input.metadata.render_id
183
- : typeof input.metadata?.renderId === "string"
184
- ? input.metadata.renderId
185
- : null;
186
- if (costCenterSlug === "remotion_lambda" && renderId) {
187
- return `remotion_lambda:${renderId}`;
188
- }
189
- return buildBillingEventFingerprint(input, costCenterSlug);
190
- }
191
- function buildBillingEventFingerprint(input, costCenterSlug) {
192
- const fingerprintPayload = {
193
- customerId: input.customerId,
194
- jobId: input.jobId,
195
- templateId: input.templateId,
196
- tracer: input.tracer ?? null,
197
- type: input.type,
198
- costCenterSlug,
199
- costUsd: roundUsd(input.costUsd),
200
- chargeUsd: input.chargeUsd == null ? null : roundUsd(input.chargeUsd),
201
- occurredAtMs: input.occurredAtMs ?? null,
202
- metadata: sortJsonValue(input.metadata ?? {})
203
- };
204
- const digest = createHash("sha256")
205
- .update(JSON.stringify(fingerprintPayload))
206
- .digest("hex")
207
- .slice(0, 24);
208
- return `${costCenterSlug ?? input.type}:${input.jobId}:${digest}`;
209
- }
210
- function sortJsonValue(value) {
211
- if (Array.isArray(value)) {
212
- return value.map(sortJsonValue);
213
- }
214
- if (value && typeof value === "object") {
215
- return Object.entries(value)
216
- .sort(([left], [right]) => left.localeCompare(right))
217
- .reduce((acc, [key, nestedValue]) => {
218
- acc[key] = sortJsonValue(nestedValue);
219
- return acc;
220
- }, {});
221
- }
222
- return value;
223
- }
224
- function roundUsd(value) {
225
- return Number(value.toFixed(6));
226
- }
227
- function isUniqueConstraintError(error) {
228
- return Boolean(error instanceof Error && /unique constraint/i.test(error.message));
229
- }
230
- export { PAID_SIGNUP_BONUS_GRANT_TYPE, PAID_SIGNUP_BONUS_USD, resolveCostCenterSlug, resolveIdempotencyKey };
231
- //# sourceMappingURL=billing.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"billing.js","sourceRoot":"","sources":["../../../src/services/billing.ts"],"names":[],"mappings":"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"}
@@ -1,92 +0,0 @@
1
- import { createId } from "../lib/ids.js";
2
- import { nowIso } from "../lib/time.js";
3
- import { serverlessRecords } from "./serverless-records.js";
4
- import { StorageService } from "./storage.js";
5
- const storage = new StorageService();
6
- function normalizeTracerList(values) {
7
- return [...new Set(values.map((value) => value.trim()).filter(Boolean))];
8
- }
9
- function buildThreadStoragePrefix(customerId, templateId, threadId) {
10
- return storage.developerScopedKey(customerId, "chat-threads", templateId, threadId);
11
- }
12
- function buildThreadChunkKey(prefix, createdAt) {
13
- const sortableTime = createdAt.replace(/[^0-9]/g, "");
14
- return `${prefix}/chunks/${sortableTime}-${createId("chunk")}.json`;
15
- }
16
- async function readChunkMessages(key) {
17
- const raw = await storage.readText(key);
18
- if (!raw) {
19
- return [];
20
- }
21
- const parsed = JSON.parse(raw);
22
- return Array.isArray(parsed.messages) ? parsed.messages : [];
23
- }
24
- export const chatThreads = {
25
- async listThreads(input) {
26
- const threads = await serverlessRecords.listChatThreadMetas(input);
27
- if (input.includeMessages === false) {
28
- return threads;
29
- }
30
- const withMessages = await Promise.all(threads.map(async (thread) => ({
31
- ...thread,
32
- messages: await this.loadThreadMessages(thread)
33
- })));
34
- return withMessages;
35
- },
36
- async getThread(input) {
37
- const thread = await serverlessRecords.getChatThreadMeta(input.customerId, input.threadId);
38
- if (!thread) {
39
- return null;
40
- }
41
- return {
42
- ...thread,
43
- messages: await this.loadThreadMessages(thread)
44
- };
45
- },
46
- async appendExchange(input) {
47
- const createdAt = nowIso();
48
- const storagePrefix = buildThreadStoragePrefix(input.customerId, input.templateId, input.threadId);
49
- const chunk = {
50
- version: 1,
51
- threadId: input.threadId,
52
- customerId: input.customerId,
53
- templateId: input.templateId,
54
- createdAt,
55
- messages: input.messages
56
- };
57
- await storage.putJson(buildThreadChunkKey(storagePrefix, createdAt), chunk);
58
- const updated = await serverlessRecords.appendChatThreadMessages({
59
- threadId: input.threadId,
60
- customerId: input.customerId,
61
- title: input.title || "New chat",
62
- templateId: input.templateId,
63
- storagePrefix,
64
- tracers: normalizeTracerList(input.tracers),
65
- messageCountDelta: input.messages.length,
66
- lastMessageAt: createdAt
67
- });
68
- return updated ? this.getThread({ customerId: input.customerId, threadId: updated.id }) : null;
69
- },
70
- async updateThread(input) {
71
- const updated = await serverlessRecords.updateChatThreadState({
72
- ...input,
73
- tracers: input.tracers ? normalizeTracerList(input.tracers) : undefined
74
- });
75
- return updated ? this.getThread({ customerId: input.customerId, threadId: updated.id }) : null;
76
- },
77
- async deleteThread(input) {
78
- const existing = await serverlessRecords.deleteChatThread(input.customerId, input.threadId);
79
- if (!existing) {
80
- return null;
81
- }
82
- const keys = await storage.listKeys(`${existing.storagePrefix}/`);
83
- await Promise.all(keys.map((key) => storage.deleteObject(key)));
84
- return existing;
85
- },
86
- async loadThreadMessages(thread) {
87
- const keys = (await storage.listKeys(`${thread.storagePrefix}/chunks/`)).sort();
88
- const messageGroups = await Promise.all(keys.map((key) => readChunkMessages(key)));
89
- return messageGroups.flat();
90
- }
91
- };
92
- //# sourceMappingURL=chat-threads.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"chat-threads.js","sourceRoot":"","sources":["../../../src/services/chat-threads.ts"],"names":[],"mappings":"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"}
@@ -1,93 +0,0 @@
1
- import { serverlessRecords } from "./serverless-records.js";
2
- export class ForkNotFoundError extends Error {
3
- constructor() { super("Fork not found"); this.name = "ForkNotFoundError"; }
4
- }
5
- export class ForkAccessDeniedError extends Error {
6
- needed;
7
- constructor(needed) {
8
- super(`Missing required capability: ${needed}`);
9
- this.needed = needed;
10
- this.name = "ForkAccessDeniedError";
11
- }
12
- }
13
- const capabilitiesByRole = {
14
- viewer: { canView: true, canEdit: false, canPublish: false },
15
- editor: { canView: true, canEdit: true, canPublish: false },
16
- publisher: { canView: true, canEdit: true, canPublish: true }
17
- };
18
- function ownerCaps() {
19
- return { isOwner: true, canView: true, canEdit: true, canPublish: true, canShare: true, canDelete: true, role: "owner" };
20
- }
21
- function fromRole(role) {
22
- return {
23
- isOwner: false,
24
- ...capabilitiesByRole[role],
25
- canShare: false,
26
- canDelete: false,
27
- role
28
- };
29
- }
30
- function mergeCaps(a, b) {
31
- const stronger = roleStrength(a.role) >= roleStrength(b.role) ? a : b;
32
- return {
33
- isOwner: a.isOwner || b.isOwner,
34
- canView: a.canView || b.canView,
35
- canEdit: a.canEdit || b.canEdit,
36
- canPublish: a.canPublish || b.canPublish,
37
- canShare: a.canShare || b.canShare,
38
- canDelete: a.canDelete || b.canDelete,
39
- role: stronger.role
40
- };
41
- }
42
- function roleStrength(role) {
43
- switch (role) {
44
- case "owner": return 4;
45
- case "publisher": return 3;
46
- case "editor": return 2;
47
- case "viewer": return 1;
48
- default: return 0;
49
- }
50
- }
51
- function isExpired(expiresAt) {
52
- if (!expiresAt)
53
- return false;
54
- return new Date(expiresAt).getTime() < Date.now();
55
- }
56
- export async function resolveForkAccess(input) {
57
- const fork = await serverlessRecords.getCompositionFork(input.forkId);
58
- if (!fork || fork.deletedAt) {
59
- throw new ForkNotFoundError();
60
- }
61
- // Fork content lives under a public-read S3 prefix — any client with the
62
- // fork_id can already fetch composition.html/json/manifest.json directly
63
- // from S3. Reflect that reality in the API so read endpoints don't lie
64
- // about protecting content that isn't actually protected. Edit/publish/
65
- // share/delete stay gated below.
66
- let caps = fromRole("viewer");
67
- if (input.customerId && fork.customerId === input.customerId) {
68
- caps = mergeCaps(caps, ownerCaps());
69
- }
70
- if (input.customerId) {
71
- const allPerms = await serverlessRecords.listForkPermissions(fork.id);
72
- const granted = allPerms.filter((perm) => perm.granteeType === "customer" && perm.granteeId === input.customerId && !isExpired(perm.expiresAt));
73
- for (const perm of granted) {
74
- caps = mergeCaps(caps, fromRole(perm.role));
75
- }
76
- }
77
- if (input.shareToken) {
78
- const link = await serverlessRecords.getForkShareLinkByToken(input.shareToken);
79
- if (link && link.forkId === fork.id && !link.revokedAt && !isExpired(link.expiresAt)) {
80
- caps = mergeCaps(caps, fromRole(link.role));
81
- }
82
- }
83
- return { fork, capabilities: caps };
84
- }
85
- export async function assertForkAccess(input, required) {
86
- const result = await resolveForkAccess(input);
87
- const need = `can${required[0].toUpperCase()}${required.slice(1)}`;
88
- if (!result.capabilities[need]) {
89
- throw new ForkAccessDeniedError(need);
90
- }
91
- return result;
92
- }
93
- //# sourceMappingURL=fork-access.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"fork-access.js","sourceRoot":"","sources":["../../../src/services/fork-access.ts"],"names":[],"mappings":"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"}
@@ -1,43 +0,0 @@
1
- function buildManifest(storage, fork, target) {
2
- const isWorking = target.kind === "working";
3
- const htmlKey = isWorking
4
- ? storage.compositionForkWorkingKey(fork.id, "composition.html")
5
- : storage.compositionForkVersionKey(fork.id, target.version, "composition.html");
6
- const jsonKey = isWorking
7
- ? storage.compositionForkWorkingKey(fork.id, "composition.json")
8
- : storage.compositionForkVersionKey(fork.id, target.version, "composition.json");
9
- const manifestKey = isWorking
10
- ? storage.compositionForkWorkingKey(fork.id, "manifest.json")
11
- : storage.compositionForkVersionKey(fork.id, target.version, "manifest.json");
12
- const parentManifestKey = fork.parentForkId && fork.parentVersion
13
- ? storage.compositionForkVersionKey(fork.parentForkId, fork.parentVersion, "manifest.json")
14
- : null;
15
- return {
16
- fork_id: fork.id,
17
- customer_id: fork.customerId,
18
- is_working: isWorking,
19
- version: isWorking ? null : target.version,
20
- latest_version: fork.latestVersion,
21
- parent_fork_id: fork.parentForkId,
22
- parent_version: fork.parentVersion,
23
- source_slug_id: fork.sourceSlugId,
24
- source_video_id: fork.sourceVideoId,
25
- visibility: fork.visibility,
26
- title: fork.title,
27
- composition_url: storage.getPublicUrl(htmlKey),
28
- composition_json_url: storage.getPublicUrl(jsonKey),
29
- manifest_url: storage.getPublicUrl(manifestKey),
30
- parent_manifest_url: parentManifestKey ? storage.getPublicUrl(parentManifestKey) : null,
31
- created_at: !isWorking && target.kind === "version" && target.createdAt ? target.createdAt : fork.createdAt,
32
- updated_at: fork.updatedAt
33
- };
34
- }
35
- export async function writeForkManifest(storage, fork, target) {
36
- const manifest = buildManifest(storage, fork, target);
37
- const key = target.kind === "working"
38
- ? storage.compositionForkWorkingKey(fork.id, "manifest.json")
39
- : storage.compositionForkVersionKey(fork.id, target.version, "manifest.json");
40
- await storage.putJson(key, manifest);
41
- return manifest;
42
- }
43
- //# sourceMappingURL=fork-manifest.js.map