feat: integrate learning module
This commit is contained in:
46
scripts/learning-player-artifact.mjs
Normal file
46
scripts/learning-player-artifact.mjs
Normal file
@@ -0,0 +1,46 @@
|
||||
import { createHash } from 'node:crypto';
|
||||
import { readdir, readFile, stat } from 'node:fs/promises';
|
||||
import { resolve } from 'node:path';
|
||||
|
||||
async function hasFiles(directory) {
|
||||
const entries = await readdir(directory, { withFileTypes: true }).catch(() => []);
|
||||
for (const entry of entries) {
|
||||
if (entry.isFile()) return true;
|
||||
if (entry.isDirectory() && await hasFiles(resolve(directory, entry.name))) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export async function validateLearningPlayerArtifact(directory) {
|
||||
const root = resolve(directory);
|
||||
const [artifactText, html] = await Promise.all([
|
||||
readFile(resolve(root, 'artifact.json'), 'utf8'),
|
||||
readFile(resolve(root, 'index.html')),
|
||||
]).catch((error) => {
|
||||
throw new Error(`Invalid learning player artifact at ${root}: ${error.message}`);
|
||||
});
|
||||
const artifact = JSON.parse(artifactText);
|
||||
if (artifact.schemaVersion !== 1
|
||||
|| artifact.entrypoint !== 'index.html'
|
||||
|| typeof artifact.htmlSha256 !== 'string'
|
||||
|| !/^[0-9a-f]{64}$/.test(artifact.htmlSha256)) {
|
||||
throw new Error(`Invalid learning player artifact manifest at ${root}`);
|
||||
}
|
||||
const htmlSha256 = createHash('sha256').update(html).digest('hex');
|
||||
if (htmlSha256 !== artifact.htmlSha256) {
|
||||
throw new Error(`Learning player index hash mismatch at ${root}`);
|
||||
}
|
||||
if (!(await stat(resolve(root, '_next', 'static')).then((entry) => entry.isDirectory()).catch(() => false))
|
||||
|| !await hasFiles(resolve(root, '_next', 'static'))) {
|
||||
throw new Error(`Learning player static assets are missing at ${root}`);
|
||||
}
|
||||
if (!(await stat(resolve(root, 'avatars')).then((entry) => entry.isDirectory()).catch(() => false))
|
||||
|| !await hasFiles(resolve(root, 'avatars'))) {
|
||||
throw new Error(`Learning player avatars are missing at ${root}`);
|
||||
}
|
||||
if (!(await stat(resolve(root, 'public')).then((entry) => entry.isDirectory()).catch(() => false))
|
||||
|| !await hasFiles(resolve(root, 'public'))) {
|
||||
throw new Error(`Learning player public assets are missing at ${root}`);
|
||||
}
|
||||
return { root, artifact, htmlSha256 };
|
||||
}
|
||||
Reference in New Issue
Block a user