Initial commit
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
import { readdir, readFile, mkdir, writeFile, stat } from "node:fs/promises";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import path from "node:path";
|
||||
import * as esbuild from "esbuild";
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const ROOT = path.resolve(__dirname, "..");
|
||||
const PRESENCES_DIR = path.join(ROOT, "presences");
|
||||
const SDK_RUNTIME = path.join(ROOT, "scripts", "sdk-runtime.mjs");
|
||||
|
||||
async function listPresences() {
|
||||
const entries = await readdir(PRESENCES_DIR, { withFileTypes: true });
|
||||
return entries.filter((e) => e.isDirectory()).map((e) => e.name);
|
||||
}
|
||||
|
||||
async function readMetadata(presenceDir) {
|
||||
const metaPath = path.join(presenceDir, "metadata.json");
|
||||
const json = JSON.parse(await readFile(metaPath, "utf8"));
|
||||
return json;
|
||||
}
|
||||
|
||||
async function findEntry(presenceDir) {
|
||||
const candidates = ["src/presence.ts", "src/index.ts", "presence.ts", "index.ts"];
|
||||
for (const candidate of candidates) {
|
||||
const full = path.join(presenceDir, candidate);
|
||||
try {
|
||||
await stat(full);
|
||||
return full;
|
||||
} catch {
|
||||
// try next
|
||||
}
|
||||
}
|
||||
throw new Error(`No entry script found in ${presenceDir} (tried ${candidates.join(", ")})`);
|
||||
}
|
||||
|
||||
async function buildPresence(slug) {
|
||||
const presenceDir = path.join(PRESENCES_DIR, slug);
|
||||
const meta = await readMetadata(presenceDir);
|
||||
if (meta.id !== slug) {
|
||||
throw new Error(`metadata.id "${meta.id}" does not match folder name "${slug}"`);
|
||||
}
|
||||
const entry = await findEntry(presenceDir);
|
||||
const distDir = path.join(presenceDir, "dist");
|
||||
await mkdir(distDir, { recursive: true });
|
||||
await esbuild.build({
|
||||
entryPoints: [entry],
|
||||
outfile: path.join(distDir, "presence.js"),
|
||||
bundle: true,
|
||||
platform: "browser",
|
||||
format: "cjs",
|
||||
target: ["chrome120", "firefox115"],
|
||||
minify: true,
|
||||
legalComments: "none",
|
||||
alias: {
|
||||
"@source/presence-sdk": SDK_RUNTIME,
|
||||
},
|
||||
});
|
||||
console.log(`✓ ${slug} v${meta.version}`);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const list = await listPresences();
|
||||
if (list.length === 0) {
|
||||
console.log("No presences found.");
|
||||
return;
|
||||
}
|
||||
for (const slug of list) {
|
||||
await buildPresence(slug);
|
||||
}
|
||||
}
|
||||
|
||||
await main();
|
||||
@@ -0,0 +1,54 @@
|
||||
import { readdir, readFile, writeFile, stat } from "node:fs/promises";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import path from "node:path";
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const ROOT = path.resolve(__dirname, "..");
|
||||
const PRESENCES_DIR = path.join(ROOT, "presences");
|
||||
|
||||
async function listPresences() {
|
||||
const entries = await readdir(PRESENCES_DIR, { withFileTypes: true });
|
||||
return entries.filter((e) => e.isDirectory()).map((e) => e.name);
|
||||
}
|
||||
|
||||
async function readMetadata(presenceDir) {
|
||||
return JSON.parse(await readFile(path.join(presenceDir, "metadata.json"), "utf8"));
|
||||
}
|
||||
|
||||
async function ensureDistExists(presenceDir, slug) {
|
||||
const distFile = path.join(presenceDir, "dist", "presence.js");
|
||||
try {
|
||||
await stat(distFile);
|
||||
} catch {
|
||||
throw new Error(`dist/presence.js missing for ${slug} — run "npm run build" first`);
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const slugs = await listPresences();
|
||||
const entries = [];
|
||||
for (const slug of slugs) {
|
||||
const dir = path.join(PRESENCES_DIR, slug);
|
||||
const meta = await readMetadata(dir);
|
||||
await ensureDistExists(dir, slug);
|
||||
entries.push({
|
||||
id: meta.id,
|
||||
name: meta.name,
|
||||
description: meta.description,
|
||||
version: meta.version,
|
||||
author: meta.author,
|
||||
match: meta.match,
|
||||
...(meta.icon ? { icon: meta.icon } : {}),
|
||||
...(typeof meta.tickInterval === "number" ? { tickInterval: meta.tickInterval } : {}),
|
||||
});
|
||||
}
|
||||
entries.sort((a, b) => a.id.localeCompare(b.id));
|
||||
const index = {
|
||||
generatedAt: new Date().toISOString(),
|
||||
presences: entries,
|
||||
};
|
||||
await writeFile(path.join(ROOT, "index.json"), JSON.stringify(index, null, 2) + "\n");
|
||||
console.log(`Wrote index.json (${entries.length} presence${entries.length === 1 ? "" : "s"})`);
|
||||
}
|
||||
|
||||
await main();
|
||||
@@ -0,0 +1,14 @@
|
||||
// Runtime stand-in for `@source/presence-sdk` when bundling presences.
|
||||
// definePresence is just identity; the extension's content-script runtime
|
||||
// passes a PresenceContext to lifecycle methods, so the package itself only
|
||||
// needs to export constants and a pass-through helper.
|
||||
|
||||
export const ActivityType = Object.freeze({
|
||||
PLAYING: 0,
|
||||
LISTENING: 2,
|
||||
WATCHING: 3,
|
||||
});
|
||||
|
||||
export function definePresence(def) {
|
||||
return def;
|
||||
}
|
||||
Reference in New Issue
Block a user