Docs/Skills and code/src/
src/observations.js
import { getDb } from "./db.js";
const db = getDb();
const insertVideoSnapshot = db.prepare(`
INSERT INTO video_metric_snapshots (
video_id, observed_at, source, view_count, view_count_text,
view_count_precision, likes_count, published_at, published_at_text,
published_at_precision, duration_seconds, duration_precision, category, raw_metadata_json
) VALUES (
@video_id, @observed_at, @source, @view_count, @view_count_text,
@view_count_precision, @likes_count, @published_at, @published_at_text,
@published_at_precision, @duration_seconds, @duration_precision, @category, @raw_metadata_json
)
`);
const insertChannelSnapshot = db.prepare(`
INSERT INTO channel_metric_snapshots (
channel_url, observed_at, source, subscriber_count, subscriber_count_text, subscriber_count_precision,
total_view_count, total_view_count_text, total_view_count_precision, video_count, video_count_text, video_count_precision,
joined_date, joined_date_text, country, raw_metadata_json
) VALUES (
@channel_url, @observed_at, @source, @subscriber_count, @subscriber_count_text, @subscriber_count_precision,
@total_view_count, @total_view_count_text, @total_view_count_precision, @video_count, @video_count_text, @video_count_precision,
@joined_date, @joined_date_text, @country, @raw_metadata_json
)
`);
export function recordVideoSnapshot(video, source, observedAt = new Date().toISOString()) {
if (!video?.video_id) return false;
insertVideoSnapshot.run({
video_id: video.video_id,
observed_at: observedAt,
source: source ?? video.metadata_source ?? "unknown",
view_count: video.view_count ?? null,
view_count_text: video.view_count_text ?? null,
view_count_precision: video.view_count_precision ?? "unknown",
likes_count: video.likes_count ?? null,
published_at: video.published_at ?? null,
published_at_text: video.published_at_text ?? null,
published_at_precision: video.published_at_precision ?? "unknown",
duration_seconds: video.duration_seconds ?? null,
duration_precision: video.duration_precision ?? "unknown",
category: video.category ?? null,
raw_metadata_json: video.raw_metadata_json ?? null
});
return true;
}
export function recordChannelSnapshot(channel, source, observedAt = new Date().toISOString()) {
if (!channel?.channel_url) return false;
insertChannelSnapshot.run({
channel_url: channel.channel_url,
observed_at: observedAt,
source: source ?? channel.metadata_source ?? "unknown",
subscriber_count: channel.subscriber_count ?? null,
subscriber_count_text: channel.subscriber_count_text ?? null,
subscriber_count_precision: channel.subscriber_count_precision ?? "unknown",
total_view_count: channel.total_view_count ?? null,
total_view_count_text: channel.total_view_count_text ?? null,
total_view_count_precision: channel.total_view_count_precision ?? "unknown",
video_count: channel.video_count ?? null,
video_count_text: channel.video_count_text ?? null,
video_count_precision: channel.video_count_precision ?? "unknown",
joined_date: channel.joined_date ?? null,
joined_date_text: channel.joined_date_text ?? null,
country: channel.country ?? null,
raw_metadata_json: channel.metadata_raw_json ?? null
});
return true;
}
Shown as it is in the repository at build time (2026-11-03); the home directory appears as <home>. If this page and the file differ, the file is right. Back to the catalogue.