// https://observablehq.com/@keystroke/obs-run
const { watch, ...args } = getArgs();
if (watch) {
let etag = await getEtag(args);
let worker = startWorker(args);
let updated = new Date();
while (true) {
await delay(new Date() - updated > watch.recent ? watch.slow : watch.fast);
const latest = await getEtag(args);
if (latest && etag !== latest) {
console.log(`$ SIGTERM -> p:${worker.pid}`);
worker.kill("SIGTERM");
worker.close();
worker = startWorker(args);
etag = latest;
updated = new Date();
}
}
}
import(`https://obs.run/${notebook}`);
function getArgs() {
let watch = Deno.args.filter(a => a.startsWith("--watch"))[0]
|| Deno.env.get("WATCH").filter(i => i).map(i => `--watch=${i}`)[0];
let reload = Deno.args.filter(a => a.startsWith("--reload"))[0]
|| [Deno.env.get("RELOAD")].filter(i => i).map(i => i === "*" ? "--reload" : `--reload=${i}`)[0]
|| "--reload=https://api.observablehq.com";
let permissions = Deno.args
.filter(a => a === "-A" || a.startsWith("--"))
.filter(a => a !== watch && a !== reload)
.join(" ")
|| Deno.env.get("PERMISSIONS")
|| "";
const notebook = Deno.args.filter(a => !a.startsWith("-"))[0]
|| Deno.env.get("NOTEBOOK");
if (watch) {
let parts = watch.split("=", 2)[1]?.split(';', 3) || [];
watch = {
slow: Number(parts[0]) || 31000,
fast: Number(parts[1]) || 3000,
recent: Number(parts[2]) || 1000 * 60 * 5,
};
}
if (reload != "--reload" && !reload.includes("https://api.observablehq.com"))
reload += ",https://api.observablehq.com";
if (reload != "--reload" && !reload.includes("https://obs.run"))
reload += ",https://obs.run";
if (permissions)
permissions = permissions.split(" ");
return { watch, reload, permissions, notebook };
}
async function getEtag({ notebook }) {
const url = `https://api.observablehq.com/${notebook}.js?v=3`;
try {
const response = await fetch(url);
if (!response.ok) console.warn(`${response.status} ${url}`, await response.text());
return response.headers.get("etag");
} catch (error) {
console.warn(url, error);
return null;
}
}
function startWorker({ reload, permissions, notebook }) {
const cmd = [
"deno",
"run",
reload,
...permissions,
`https://obs.run/${notebook}`,
];
console.log(`$ ${cmd.join(" ")}`);
return Deno.run({ cmd });
}
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}