UNPKG

skypack

Version:
229 lines 10.1 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.clearCache = exports.SkypackSDK = exports.SKYPACK_ORIGIN = exports.rollupPluginSkypack = void 0; const mkdirp_1 = __importDefault(require("mkdirp")); const cacache_1 = __importDefault(require("cacache")); const path_1 = __importDefault(require("path")); const tar_1 = __importDefault(require("tar")); const fs_1 = __importDefault(require("fs")); const url_1 = __importDefault(require("url")); const got_1 = __importDefault(require("got")); const util_1 = require("./util"); var rollup_plugin_remote_cdn_1 = require("./rollup-plugin-remote-cdn"); Object.defineProperty(exports, "rollupPluginSkypack", { enumerable: true, get: function () { return rollup_plugin_remote_cdn_1.rollupPluginSkypack; } }); exports.SKYPACK_ORIGIN = `https://cdn.skypack.dev`; function parseRawPackageImport(spec) { const impParts = spec.split('/'); if (spec.startsWith('@')) { const [scope, name, ...rest] = impParts; return [`${scope}/${name}`, rest.join('/') || null]; } const [name, ...rest] = impParts; return [name, rest.join('/') || null]; } class SkypackSDK { constructor(options = {}) { this.origin = options.origin || `https://cdn.skypack.dev`; } async generateImportMap(webDependencies, inheritFromImportMap) { const newLockfile = inheritFromImportMap ? { imports: { ...inheritFromImportMap.imports } } : { imports: {} }; await Promise.all(Object.entries(webDependencies).map(async ([packageName, packageSemver]) => { if (packageSemver === null) { delete newLockfile.imports[packageName]; delete newLockfile.imports[packageName + '/']; return; } const lookupResponse = await this.lookupBySpecifier(packageName, packageSemver); if (lookupResponse.error) { throw lookupResponse.error; } if (lookupResponse.pinnedUrl) { let keepGoing = true; const deepPinnedUrlParts = lookupResponse.pinnedUrl.split('/'); // TODO: Get ?meta support to get this info via JSON instead of header manipulation deepPinnedUrlParts.shift(); // remove "" deepPinnedUrlParts.shift(); // remove "pin" while (keepGoing) { const investigate = deepPinnedUrlParts.pop(); if (util_1.HAS_CDN_HASH_REGEX.test(investigate)) { keepGoing = false; deepPinnedUrlParts.push(investigate); } } newLockfile.imports[packageName] = this.origin + '/' + deepPinnedUrlParts.join('/'); newLockfile.imports[packageName + '/'] = this.origin + '/' + deepPinnedUrlParts.join('/') + '/'; } })); const newLockfileSorted = Object.keys(newLockfile.imports).sort((a, b) => { // We want 'xxx/' to come after 'xxx', so we convert it to a space (the character with the highest sort order) // See: http://support.ecisolutions.com/doc-ddms/help/reportsmenu/ascii_sort_order_chart.htm return a.replace(/\/$/, ' ').localeCompare(b.replace(/\/$/, ' ')); }); return { imports: newLockfileSorted.reduce((prev, k) => { prev[k] = newLockfile.imports[k]; return prev; }, {}), }; } async fetch(resourceUrl, userAgent) { var _a; if (!resourceUrl.startsWith(this.origin)) { resourceUrl = this.origin + resourceUrl; } const cachedResult = await cacache_1.default.get(util_1.RESOURCE_CACHE, resourceUrl).catch(() => null); if (cachedResult) { const cachedResultMetadata = cachedResult.metadata; const freshUntil = new Date(cachedResult.metadata.freshUntil); if (freshUntil >= new Date()) { return { isCached: true, isStale: false, body: cachedResult.data, headers: cachedResultMetadata.headers, statusCode: cachedResultMetadata.statusCode, }; } } let freshResult; try { freshResult = await got_1.default(resourceUrl, { headers: { 'user-agent': userAgent || `skypack/v0.0.1` }, throwHttpErrors: false, responseType: 'buffer', }); } catch (err) { if (cachedResult) { const cachedResultMetadata = cachedResult.metadata; return { isCached: true, isStale: true, body: cachedResult.data, headers: cachedResultMetadata.headers, statusCode: cachedResultMetadata.statusCode, }; } throw err; } const cacheUntilMatch = (_a = freshResult.headers['cache-control']) === null || _a === void 0 ? void 0 : _a.match(/max-age=(\d+)/); if (cacheUntilMatch) { var freshUntil = new Date(); freshUntil.setSeconds(freshUntil.getSeconds() + parseInt(cacheUntilMatch[1])); // no need to await, since we `.catch()` to swallow any errors. cacache_1.default .put(util_1.RESOURCE_CACHE, resourceUrl, freshResult.body, { metadata: { headers: freshResult.headers, statusCode: freshResult.statusCode, freshUntil: freshUntil.toUTCString(), }, }) .catch(() => null); } return { body: freshResult.body, headers: freshResult.headers, statusCode: freshResult.statusCode, isCached: false, isStale: false, }; } async buildNewPackage(spec, semverString, userAgent) { const [packageName, packagePath] = parseRawPackageImport(spec); const lookupUrl = `/new/${packageName}` + (semverString ? `@${semverString}` : ``) + (packagePath ? `/${packagePath}` : ``); try { const { statusCode } = await this.fetch(lookupUrl, userAgent); return { error: null, success: statusCode !== 500, }; } catch (err) { return { error: err, success: false }; } } async lookupBySpecifier(spec, semverString, qs, userAgent) { const [packageName, packagePath] = parseRawPackageImport(spec); const lookupUrl = `/${packageName}` + (semverString ? `@${semverString}` : ``) + (packagePath ? `/${packagePath}` : ``) + (qs ? `?${qs}` : ``); try { const { body, statusCode, headers, isCached, isStale } = await this.fetch(lookupUrl, userAgent); if (statusCode !== 200) { return { error: new Error(body.toString()) }; } return { error: null, body, isCached, isStale, importStatus: headers['x-import-status'], importUrl: headers['x-import-url'], pinnedUrl: headers['x-pinned-url'], typesUrl: headers['x-typescript-types'], }; } catch (err) { return { error: err }; } } async installTypes(spec, semverString, dir) { dir = dir || path_1.default.join(process.cwd(), '.types'); const lookupResult = await this.lookupBySpecifier(spec, semverString, 'dts'); if (lookupResult.error) { throw lookupResult.error; } if (!lookupResult.typesUrl) { throw new Error(`Skypack CDN: No types found "${spec}"`); } const typesTarballUrl = lookupResult.typesUrl.replace(/(mode=types.*?)\/.*/, '$1/all.tgz'); await mkdirp_1.default(dir); const tempDir = await cacache_1.default.tmp.mkdir(util_1.RESOURCE_CACHE); let tarballContents; const cachedTarball = await cacache_1.default .get(util_1.RESOURCE_CACHE, typesTarballUrl) .catch(( /* ignore */) => null); if (cachedTarball) { tarballContents = cachedTarball.data; } else { const tarballResponse = await this.fetch(typesTarballUrl); if (tarballResponse.statusCode !== 200) { throw new Error(tarballResponse.body.toString()); } tarballContents = tarballResponse.body; await cacache_1.default.put(util_1.RESOURCE_CACHE, typesTarballUrl, tarballContents); } const typesUrlParts = url_1.default.parse(typesTarballUrl).pathname.split('/'); const typesPackageName = url_1.default.parse(typesTarballUrl).pathname.startsWith('/-/@') ? typesUrlParts[2] + '/' + typesUrlParts[3].split('@')[0] : typesUrlParts[2].split('@')[0]; const typesPackageTarLoc = path_1.default.join(tempDir, `${typesPackageName}.tgz`); if (typesPackageName.includes('/')) { await mkdirp_1.default(path_1.default.dirname(typesPackageTarLoc)); } fs_1.default.writeFileSync(typesPackageTarLoc, tarballContents); const typesPackageLoc = path_1.default.join(dir, typesPackageName); await mkdirp_1.default(typesPackageLoc); await tar_1.default.x({ file: typesPackageTarLoc, cwd: typesPackageLoc, }); } } exports.SkypackSDK = SkypackSDK; async function clearCache() { return cacache_1.default.rm.all(util_1.RESOURCE_CACHE); } exports.clearCache = clearCache; //# sourceMappingURL=index.js.map