UNPKG

motoko

Version:

Compile and run Motoko smart contracts in Node.js or the browser.

165 lines 6.11 kB
"use strict"; // Derived from: https://github.com/dfinity/motoko-playground/blob/main/src/workers/file.ts var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.fetchPackage = fetchPackage; exports.installPackages = installPackages; exports.validatePackage = validatePackage; const parse_github_url_1 = __importDefault(require("parse-github-url")); const cross_fetch_1 = __importDefault(require("cross-fetch")); const sanitize_filename_1 = __importDefault(require("sanitize-filename")); function parseGithubPackageInfo(path) { if (!path) { return; } if (typeof path === 'object') { return path; } let result; try { result = (0, parse_github_url_1.default)(path); if (!result) { return; } } catch (err) { // console.warn(err); return; } const { name, filepath, branch, owner } = result; return { name, repo: `https://github.com/${owner}/${name}.git`, version: branch, dir: filepath, branch, // homepage: , }; } async function fetchPackageFiles(info) { const prefix = 'https://github.com/'; const suffix = '.git'; if (!info.repo.startsWith(prefix) || !info.repo.endsWith(suffix)) { return; } const repoPart = info.repo.slice(prefix.length, -suffix.length); const possiblyCDN = !((info.branch && info.branch.length % 2 === 0 && /^[A-F0-9]+$/i.test(info.branch)) || info.branch === 'master' || info.branch === 'main'); if (possiblyCDN) { try { const result = await fetchFromService(info, 'CDN', `https://data.jsdelivr.com/v1/package/gh/${repoPart}@${info.branch}/flat`, `https://cdn.jsdelivr.net/gh/${repoPart}@${info.branch}`, 'files', 'name'); if (result) { return result; } } catch (err) { console.error('[CDN]', err); } } return await fetchFromService(info, 'GitHub', `https://api.github.com/repos/${repoPart}/git/trees/${info.branch}?recursive=1`, `https://raw.githubusercontent.com/${repoPart}/${info.branch}/`, 'tree', 'path', (file) => file.type === 'blob'); } async function fetchFromService(info, serviceName, metaUrl, baseUrl, resultProperty, pathProperty, condition) { const response = await (0, cross_fetch_1.default)(metaUrl); if (!response.ok) { throw Error(response.statusText || `Could not fetch from ${serviceName}: ${info.repo}`); } const json = await response.json(); if (!json.hasOwnProperty(resultProperty)) { throw new Error(`Unexpected response from ${serviceName}`); } // Remove leading and trailing '/' from directory let directory = info.dir ? info.dir.replace(/^\//, '').replace(/\/$/, '') : ''; const files = {}; await Promise.all(json[resultProperty] .filter((file) => { return ((!directory || file[pathProperty].startsWith(file[pathProperty].startsWith('/') ? `/${directory}` : directory)) && (!condition || condition(file)) && /\.mo$/.test(file[pathProperty])); }) .map(async (file) => { const response = await (0, cross_fetch_1.default)(`${baseUrl}${file[pathProperty]}`); if (!response.ok) { throw Error(response.statusText); } const content = await response.text(); let path = file[pathProperty]; if (path.startsWith('/')) { path = path.slice(1); } if (directory) { // Remove directory prefix path = path.slice(directory.length + 1); } files[path] = { content, }; })); return files; } async function fetchPackage(name, info) { if (typeof info === 'string') { info = parseGithubPackageInfo(info); } const files = await fetchPackageFiles(info); if (!files) { return; } return { name, version: info.version, files, }; } async function installPackages(mo, packages) { await Promise.all(Object.entries(packages).map(async ([name, info]) => { const pkg = await fetchPackage(name, info); mo.loadPackage(pkg); return pkg; })); } function validatePackage(pkg) { function showValue(value) { const string = JSON.stringify(value); return string.length > 50 ? string.substring(0, 50) + '...' : string; } function getPackageDisplayName() { return `(${pkg.name} / ${pkg.version})`; } if (typeof pkg !== 'object' || Array.isArray(pkg)) { throw new Error(`Unexpected package: ${showValue(pkg)}`); } if (typeof pkg.name !== 'string' || (0, sanitize_filename_1.default)(pkg.name) !== pkg.name) { throw new Error(`Invalid package name ${getPackageDisplayName()}`); } if (typeof pkg.version !== 'string' || (0, sanitize_filename_1.default)(pkg.version) !== pkg.version) { throw new Error(`Invalid package version ${getPackageDisplayName()}`); } if (typeof pkg.files !== 'object' || Array.isArray(pkg.files)) { throw new Error(`Invalid package files: ${showValue(pkg.files)}`); } Object.entries(pkg.files).forEach(([path, file]) => { if (typeof path !== 'string' || path.split('/').some((p) => (0, sanitize_filename_1.default)(p) !== p)) { throw new Error(`Invalid file path ${getPackageDisplayName()} [${path}]`); } if (typeof file !== 'object' || Array.isArray(file)) { throw new Error(`Invalid file ${getPackageDisplayName()} [${path}]: ${showValue(file)}`); } if (typeof file.content !== 'string') { throw new Error(`Invalid file content ${getPackageDisplayName()} [${path}]: ${showValue(file.content)}`); } }); } //# sourceMappingURL=package.js.map