@mevdragon/vidfarm-devcli 0.2.7 → 0.2.8
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/GETTING_STARTED.developers.md +14 -18
- package/README.md +19 -5
- package/SKILL.developer.md +140 -11
- package/dist/src/account-pages.js +1 -1
- package/dist/src/app.js +305 -9
- package/dist/src/cli.js +142 -6
- package/dist/src/config.js +2 -5
- package/dist/src/context.js +16 -0
- package/dist/src/db.js +33 -2
- package/dist/src/homepage.js +33 -1
- package/dist/src/lib/template-paths.js +10 -4
- package/dist/src/registry.js +9 -2
- package/dist/src/services/auth.js +2 -6
- package/dist/src/services/job-logs.js +4 -4
- package/dist/src/services/providers.js +470 -0
- package/dist/src/services/storage.js +13 -0
- package/dist/src/services/template-certification.js +16 -2
- package/dist/src/services/template-loader.js +17 -1
- package/dist/src/services/template-sources.js +249 -5
- package/{templates/template_0000 → dist/templates/vidfarm_template_0000}/src/remotion/Root.js +1 -0
- package/dist/templates/{template_0000 → vidfarm_template_0000}/src/template.js +9 -3
- package/package.json +4 -3
- package/templates/{template_0000 → vidfarm_template_0000}/README.md +23 -0
- package/templates/{template_0000 → vidfarm_template_0000}/package.json +0 -1
- package/templates/{template_0000 → vidfarm_template_0000}/src/sdk.ts +18 -0
- package/templates/{template_0000 → vidfarm_template_0000}/src/template.js +9 -3
- package/templates/{template_0000 → vidfarm_template_0000}/src/template.ts +10 -3
- package/templates/vidfarm_template_0000/tmp/solobacterium-moorei-slideshow.request.json +31 -0
- /package/dist/templates/{template_0000 → vidfarm_template_0000}/src/lib/images.js +0 -0
- /package/dist/templates/{template_0000 → vidfarm_template_0000}/src/remotion/index.js +0 -0
- /package/dist/templates/{template_0000 → vidfarm_template_0000}/src/sdk.js +0 -0
- /package/dist/templates/{template_0000 → vidfarm_template_0000}/src/style-options.js +0 -0
- /package/dist/templates/{template_0000 → vidfarm_template_0000}/src/template-dna.js +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/SKILL.md +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/assets/Abel-Regular.ttf +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/assets/DMSerifDisplay-Regular.ttf +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/assets/Montserrat[wght].ttf +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/assets/SourceCodePro[wght].ttf +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/assets/TikTokSans-SemiBold.ttf +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/assets/Yesteryear-Regular.ttf +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/composition.json +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/research/preview/.gitkeep +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/research/source_notes.md +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/src/lib/images.js +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/src/lib/images.ts +0 -0
- /package/{dist/templates/template_0000 → templates/vidfarm_template_0000}/src/remotion/Root.js +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/src/remotion/Root.tsx +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/src/remotion/index.js +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/src/remotion/index.tsx +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/src/sdk.js +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/src/style-options.js +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/src/style-options.ts +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/src/template-dna.js +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/src/template-dna.ts +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/template.config.json +0 -0
- /package/templates/{template_0000 → vidfarm_template_0000}/tsconfig.json +0 -0
package/dist/src/db.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import Database from "better-sqlite3";
|
|
2
2
|
import { config } from "./config.js";
|
|
3
|
+
import { createId } from "./lib/ids.js";
|
|
3
4
|
import { parseJson, stringifyJson } from "./lib/json.js";
|
|
4
5
|
import { nowIso } from "./lib/time.js";
|
|
5
6
|
const db = new Database(config.VIDFARM_DB_PATH);
|
|
@@ -192,6 +193,8 @@ create table if not exists template_releases (
|
|
|
192
193
|
checkout_path text not null,
|
|
193
194
|
skill_path text not null,
|
|
194
195
|
module_path text not null,
|
|
196
|
+
artifact_manifest_key text,
|
|
197
|
+
artifact_key text,
|
|
195
198
|
status text not null,
|
|
196
199
|
certification_report_json text,
|
|
197
200
|
activated_at text,
|
|
@@ -245,6 +248,13 @@ db.exec(`
|
|
|
245
248
|
set status = 'pending_approval'
|
|
246
249
|
where status = 'certified';
|
|
247
250
|
`);
|
|
251
|
+
const templateReleaseColumns = db.prepare(`pragma table_info(template_releases)`).all();
|
|
252
|
+
if (!templateReleaseColumns.some((column) => column.name === "artifact_manifest_key")) {
|
|
253
|
+
db.exec(`alter table template_releases add column artifact_manifest_key text;`);
|
|
254
|
+
}
|
|
255
|
+
if (!templateReleaseColumns.some((column) => column.name === "artifact_key")) {
|
|
256
|
+
db.exec(`alter table template_releases add column artifact_key text;`);
|
|
257
|
+
}
|
|
248
258
|
db.exec(`drop index if exists idx_job_events_job_time;`);
|
|
249
259
|
db.exec(`drop table if exists job_events;`);
|
|
250
260
|
function mapJob(row) {
|
|
@@ -298,6 +308,8 @@ function mapTemplateRelease(row) {
|
|
|
298
308
|
checkoutPath: String(row.checkout_path),
|
|
299
309
|
skillPath: String(row.skill_path),
|
|
300
310
|
modulePath: String(row.module_path),
|
|
311
|
+
artifactManifestKey: row.artifact_manifest_key ? String(row.artifact_manifest_key) : null,
|
|
312
|
+
artifactKey: row.artifact_key ? String(row.artifact_key) : null,
|
|
301
313
|
status: row.status,
|
|
302
314
|
certificationReport: parseJson(row.certification_report_json, null),
|
|
303
315
|
activatedAt: row.activated_at ? String(row.activated_at) : null,
|
|
@@ -400,6 +412,21 @@ export const database = {
|
|
|
400
412
|
where id = ?
|
|
401
413
|
`).run(isPaidPlan ? 1 : 0, nowIso(), customerId);
|
|
402
414
|
},
|
|
415
|
+
setCustomerAccessByEmail(input) {
|
|
416
|
+
const normalizedEmail = input.email.trim().toLowerCase();
|
|
417
|
+
const existing = this.getCustomerByEmail(normalizedEmail);
|
|
418
|
+
return this.upsertCustomer({
|
|
419
|
+
id: existing?.id ?? createId("cus"),
|
|
420
|
+
email: normalizedEmail,
|
|
421
|
+
name: input.name === undefined ? (existing?.name ?? null) : input.name,
|
|
422
|
+
defaultWebhookUrl: existing?.defaultWebhookUrl ?? null,
|
|
423
|
+
isDeveloper: input.isDeveloper === undefined ? (existing?.isDeveloper ?? false) : input.isDeveloper,
|
|
424
|
+
isPaidPlan: input.isPaidPlan === undefined ? (existing?.isPaidPlan ?? false) : input.isPaidPlan,
|
|
425
|
+
about: existing?.about ?? null,
|
|
426
|
+
groupchatUrl: existing?.groupchatUrl ?? null,
|
|
427
|
+
flockposterApiKey: existing?.flockposterApiKey ?? null
|
|
428
|
+
});
|
|
429
|
+
},
|
|
403
430
|
updateCustomerProfile(input) {
|
|
404
431
|
db.prepare(`
|
|
405
432
|
update customers
|
|
@@ -915,16 +942,18 @@ export const database = {
|
|
|
915
942
|
const timestamp = nowIso();
|
|
916
943
|
db.prepare(`
|
|
917
944
|
insert into template_releases (
|
|
918
|
-
id, source_id, template_id, branch, commit_sha, checkout_path, skill_path, module_path, status,
|
|
945
|
+
id, source_id, template_id, branch, commit_sha, checkout_path, skill_path, module_path, artifact_manifest_key, artifact_key, status,
|
|
919
946
|
certification_report_json, activated_at, created_at, updated_at
|
|
920
947
|
) values (
|
|
921
|
-
@id, @source_id, @template_id, @branch, @commit_sha, @checkout_path, @skill_path, @module_path, @status,
|
|
948
|
+
@id, @source_id, @template_id, @branch, @commit_sha, @checkout_path, @skill_path, @module_path, @artifact_manifest_key, @artifact_key, @status,
|
|
922
949
|
@certification_report_json, @activated_at, @created_at, @updated_at
|
|
923
950
|
)
|
|
924
951
|
on conflict(source_id, commit_sha) do update set
|
|
925
952
|
checkout_path = excluded.checkout_path,
|
|
926
953
|
skill_path = excluded.skill_path,
|
|
927
954
|
module_path = excluded.module_path,
|
|
955
|
+
artifact_manifest_key = excluded.artifact_manifest_key,
|
|
956
|
+
artifact_key = excluded.artifact_key,
|
|
928
957
|
status = excluded.status,
|
|
929
958
|
certification_report_json = excluded.certification_report_json,
|
|
930
959
|
activated_at = excluded.activated_at,
|
|
@@ -938,6 +967,8 @@ export const database = {
|
|
|
938
967
|
checkout_path: record.checkoutPath,
|
|
939
968
|
skill_path: record.skillPath,
|
|
940
969
|
module_path: record.modulePath,
|
|
970
|
+
artifact_manifest_key: record.artifactManifestKey ?? null,
|
|
971
|
+
artifact_key: record.artifactKey ?? null,
|
|
941
972
|
status: record.status,
|
|
942
973
|
certification_report_json: stringifyJson(record.certificationReport ?? null),
|
|
943
974
|
activated_at: record.activatedAt ?? null,
|
package/dist/src/homepage.js
CHANGED
|
@@ -35,7 +35,7 @@ export function renderHomepage(input) {
|
|
|
35
35
|
const search = `${template.templateId} ${template.title} ${template.slugId}`.toLowerCase();
|
|
36
36
|
const media = template.previewUrl
|
|
37
37
|
? isVideoPreview(template.previewUrl)
|
|
38
|
-
? `<video class="preview" src="${escapeHtml(template.previewUrl)}" preload="
|
|
38
|
+
? `<video class="preview" data-lazy-video data-src="${escapeHtml(template.previewUrl)}" preload="metadata" muted playsinline controls></video>`
|
|
39
39
|
: `<img class="preview" src="${escapeHtml(template.previewUrl)}" alt="${escapeHtml(template.title)} preview" loading="lazy" decoding="async" />`
|
|
40
40
|
: `<div class="preview preview-empty">No preview</div>`;
|
|
41
41
|
return `
|
|
@@ -393,6 +393,7 @@ export function renderHomepage(input) {
|
|
|
393
393
|
const rows = Array.from(document.querySelectorAll(".row"));
|
|
394
394
|
const count = document.getElementById("count");
|
|
395
395
|
const emptyState = document.getElementById("empty-state");
|
|
396
|
+
const lazyVideos = Array.from(document.querySelectorAll("[data-lazy-video]"));
|
|
396
397
|
|
|
397
398
|
const updateFilter = () => {
|
|
398
399
|
const query = (searchInput.value || "").trim().toLowerCase();
|
|
@@ -411,6 +412,37 @@ export function renderHomepage(input) {
|
|
|
411
412
|
|
|
412
413
|
searchInput.addEventListener("input", updateFilter);
|
|
413
414
|
|
|
415
|
+
const loadVideo = (video) => {
|
|
416
|
+
const src = video.getAttribute("data-src");
|
|
417
|
+
if (!src || video.getAttribute("src")) {
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
video.setAttribute("src", src);
|
|
421
|
+
video.load();
|
|
422
|
+
};
|
|
423
|
+
|
|
424
|
+
if ("IntersectionObserver" in window) {
|
|
425
|
+
const observer = new IntersectionObserver((entries) => {
|
|
426
|
+
for (const entry of entries) {
|
|
427
|
+
if (!entry.isIntersecting) {
|
|
428
|
+
continue;
|
|
429
|
+
}
|
|
430
|
+
loadVideo(entry.target);
|
|
431
|
+
observer.unobserve(entry.target);
|
|
432
|
+
}
|
|
433
|
+
}, {
|
|
434
|
+
rootMargin: "240px 0px"
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
for (const video of lazyVideos) {
|
|
438
|
+
observer.observe(video);
|
|
439
|
+
}
|
|
440
|
+
} else {
|
|
441
|
+
for (const video of lazyVideos) {
|
|
442
|
+
loadVideo(video);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
414
446
|
for (const button of document.querySelectorAll("[data-copy-text]")) {
|
|
415
447
|
button.addEventListener("click", async () => {
|
|
416
448
|
const text = button.getAttribute("data-copy-text") || "";
|
|
@@ -1,21 +1,27 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
export const TEMPLATE_FOLDER_PREFIX = "vidfarm_template_";
|
|
3
|
+
export const LEGACY_TEMPLATE_FOLDER_PREFIX = "template_";
|
|
3
4
|
export function assertTemplateFolderNameHasPrefix(folderName) {
|
|
4
|
-
if (!folderName.startsWith(TEMPLATE_FOLDER_PREFIX)) {
|
|
5
|
-
throw new Error(`Template folder name must start with ${TEMPLATE_FOLDER_PREFIX}. Received: ${folderName}`);
|
|
5
|
+
if (!folderName.startsWith(TEMPLATE_FOLDER_PREFIX) && !folderName.startsWith(LEGACY_TEMPLATE_FOLDER_PREFIX)) {
|
|
6
|
+
throw new Error(`Template folder name must start with ${TEMPLATE_FOLDER_PREFIX} or ${LEGACY_TEMPLATE_FOLDER_PREFIX}. Received: ${folderName}`);
|
|
6
7
|
}
|
|
7
8
|
}
|
|
8
9
|
export function deriveTemplateRootDirFromModulePath(templateModulePath) {
|
|
9
10
|
const normalizedModulePath = templateModulePath.replace(/\\/g, "/");
|
|
10
11
|
const templateSourceDir = path.posix.dirname(normalizedModulePath);
|
|
11
12
|
const templateRootDir = path.posix.dirname(templateSourceDir);
|
|
13
|
+
const sourceDirName = path.posix.basename(templateSourceDir);
|
|
14
|
+
if (sourceDirName !== "src") {
|
|
15
|
+
throw new Error("template_module_path must point at a TypeScript entrypoint inside a src/ folder, such as src/template.ts or templates/vidfarm_template_example/src/template.ts.");
|
|
16
|
+
}
|
|
12
17
|
if (templateRootDir === "." || templateRootDir === "") {
|
|
13
|
-
|
|
18
|
+
return "";
|
|
14
19
|
}
|
|
15
20
|
const folderName = path.posix.basename(templateRootDir);
|
|
16
21
|
assertTemplateFolderNameHasPrefix(folderName);
|
|
17
22
|
return templateRootDir;
|
|
18
23
|
}
|
|
19
24
|
export function defaultSkillPathForTemplateModule(templateModulePath) {
|
|
20
|
-
|
|
25
|
+
const templateRootDir = deriveTemplateRootDirFromModulePath(templateModulePath);
|
|
26
|
+
return templateRootDir ? path.posix.join(templateRootDir, "SKILL.md") : "SKILL.md";
|
|
21
27
|
}
|
package/dist/src/registry.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { database } from "./db.js";
|
|
2
|
-
import { template0000Definition } from "../templates/
|
|
2
|
+
import { template0000Definition } from "../templates/vidfarm_template_0000/src/template.js";
|
|
3
3
|
import { loadTemplateFromModule } from "./services/template-loader.js";
|
|
4
4
|
import { TemplateCertificationService } from "./services/template-certification.js";
|
|
5
5
|
class TemplateRegistry {
|
|
@@ -42,7 +42,14 @@ class TemplateRegistry {
|
|
|
42
42
|
return this.initPromise;
|
|
43
43
|
}
|
|
44
44
|
list() {
|
|
45
|
-
|
|
45
|
+
const merged = new Map();
|
|
46
|
+
for (const template of this.localTemplates.values()) {
|
|
47
|
+
merged.set(template.id, template);
|
|
48
|
+
}
|
|
49
|
+
for (const template of this.runtimeTemplates.values()) {
|
|
50
|
+
merged.set(template.id, template);
|
|
51
|
+
}
|
|
52
|
+
return [...merged.values()].sort((a, b) => a.id.localeCompare(b.id));
|
|
46
53
|
}
|
|
47
54
|
get(templateId) {
|
|
48
55
|
return this.findTemplate(templateId, this.runtimeTemplates) ?? this.findTemplate(templateId, this.localTemplates);
|
|
@@ -54,9 +54,7 @@ export class AuthService {
|
|
|
54
54
|
email,
|
|
55
55
|
name: name ?? existing?.name ?? null,
|
|
56
56
|
defaultWebhookUrl: existing?.defaultWebhookUrl ?? null,
|
|
57
|
-
isDeveloper: existing?.isDeveloper
|
|
58
|
-
|| config.adminEmails.includes(normalizedEmail)
|
|
59
|
-
|| config.developerEmails.includes(normalizedEmail),
|
|
57
|
+
isDeveloper: existing?.isDeveloper || config.adminEmails.includes(normalizedEmail),
|
|
60
58
|
isPaidPlan: existing?.isPaidPlan ?? false
|
|
61
59
|
});
|
|
62
60
|
const rawApiKey = `vf_${createId("key")}`;
|
|
@@ -134,9 +132,7 @@ export class AuthService {
|
|
|
134
132
|
email: normalizedEmail,
|
|
135
133
|
name: input.name ?? existing?.name ?? null,
|
|
136
134
|
defaultWebhookUrl: existing?.defaultWebhookUrl ?? null,
|
|
137
|
-
isDeveloper: existing?.isDeveloper
|
|
138
|
-
|| config.adminEmails.includes(normalizedEmail)
|
|
139
|
-
|| config.developerEmails.includes(normalizedEmail),
|
|
135
|
+
isDeveloper: existing?.isDeveloper || config.adminEmails.includes(normalizedEmail),
|
|
140
136
|
isPaidPlan: true,
|
|
141
137
|
passwordHash: hashPassword(input.password)
|
|
142
138
|
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { StorageService } from "./storage.js";
|
|
2
2
|
const JOB_LOG_PREFIX = "job-logs";
|
|
3
|
-
const JOB_LOG_CHUNK_INTERVAL_MS =
|
|
3
|
+
const JOB_LOG_CHUNK_INTERVAL_MS = 60000;
|
|
4
4
|
const JOB_LOG_CHUNK_MAX_BYTES = 1024 * 1024;
|
|
5
|
-
const JOB_LOG_FLUSH_INTERVAL_MS =
|
|
5
|
+
const JOB_LOG_FLUSH_INTERVAL_MS = 5000;
|
|
6
6
|
export class JobLogStore {
|
|
7
7
|
storage = new StorageService();
|
|
8
8
|
activeChunks = new Map();
|
|
@@ -81,7 +81,7 @@ export class JobLogStore {
|
|
|
81
81
|
const minMs = Math.min(startMs, endMs);
|
|
82
82
|
const maxMs = Math.max(startMs, endMs);
|
|
83
83
|
const minuteStarts = [];
|
|
84
|
-
for (let cursor = minMs; cursor <= maxMs; cursor +=
|
|
84
|
+
for (let cursor = minMs; cursor <= maxMs; cursor += 60000) {
|
|
85
85
|
minuteStarts.push(cursor);
|
|
86
86
|
}
|
|
87
87
|
return minuteStarts;
|
|
@@ -155,7 +155,7 @@ function serializedEventSize(event) {
|
|
|
155
155
|
return Buffer.byteLength(`${JSON.stringify(event)}\n`, "utf8");
|
|
156
156
|
}
|
|
157
157
|
function floorToMinute(timestampMs) {
|
|
158
|
-
return Math.floor(timestampMs /
|
|
158
|
+
return Math.floor(timestampMs / 60000) * 60000;
|
|
159
159
|
}
|
|
160
160
|
function parseChunk(content) {
|
|
161
161
|
if (!content) {
|