70 lines
1.8 KiB
TypeScript
70 lines
1.8 KiB
TypeScript
const projectDir = Deno.args[0];
|
|
|
|
if (!projectDir) {
|
|
throw new Error("Usage: deno run --allow-read microapps/validator/validate_microapp_repo.ts <project-dir>");
|
|
}
|
|
|
|
const requiredFiles = new Set([
|
|
"app.config.ts",
|
|
"deno.json",
|
|
"main.ts",
|
|
"pocketbase/client.ts",
|
|
]);
|
|
|
|
const allowedTopLevelEntries = new Set([
|
|
"app.config.ts",
|
|
"deno.json",
|
|
"main.ts",
|
|
"pocketbase",
|
|
]);
|
|
|
|
const rootEntries = new Set<string>();
|
|
|
|
for await (const entry of Deno.readDir(projectDir)) {
|
|
rootEntries.add(entry.name);
|
|
}
|
|
|
|
for (const file of requiredFiles) {
|
|
const path = `${projectDir}/${file}`;
|
|
await Deno.stat(path);
|
|
}
|
|
|
|
for (const entry of rootEntries) {
|
|
if (!allowedTopLevelEntries.has(entry)) {
|
|
throw new Error(`Unexpected top-level entry: ${entry}`);
|
|
}
|
|
}
|
|
|
|
const configModule = await import(`file://${Deno.realPathSync(`${projectDir}/app.config.ts`)}`);
|
|
const config = configModule.default as {
|
|
manifestVersion?: number;
|
|
runtime?: string;
|
|
libraries?: string[];
|
|
permissions?: {
|
|
allowEnv?: string[];
|
|
allowNet?: string[];
|
|
};
|
|
};
|
|
|
|
if (config.manifestVersion !== 1) {
|
|
throw new Error("app.config.ts must export manifestVersion = 1");
|
|
}
|
|
|
|
if (config.runtime !== "deno-gvisor") {
|
|
throw new Error("app.config.ts must declare runtime = 'deno-gvisor'");
|
|
}
|
|
|
|
if (!Array.isArray(config.libraries) || config.libraries.length === 0) {
|
|
throw new Error("app.config.ts must declare at least one approved library");
|
|
}
|
|
|
|
if (!Array.isArray(config.permissions?.allowEnv) || config.permissions.allowEnv.length === 0) {
|
|
throw new Error("app.config.ts must declare allowEnv permissions");
|
|
}
|
|
|
|
if (!Array.isArray(config.permissions?.allowNet) || config.permissions.allowNet.length === 0) {
|
|
throw new Error("app.config.ts must declare allowNet permissions");
|
|
}
|
|
|
|
console.log(`Microapp repo at ${projectDir} matches the enforced template contract.`);
|