@jspm/generator
Version:
Package Import Map Generation Tool
211 lines (209 loc) • 8.81 kB
JavaScript
import { SemverRange } from 'sver';
// @ts-ignore
import { fetch } from '../common/fetch.js';
const cdnUrl = 'https://deno.land/x/';
const stdlibUrl = 'https://deno.land/std';
let denoStdVersion;
export function resolveBuiltin(specifier, env) {
// Bare npm:XXX imports are supported by Deno:
if (env.includes('deno') && specifier.startsWith('npm:')) return specifier;
if (specifier.startsWith('deno:')) {
let name = specifier.slice(5);
if (name.endsWith('.ts')) name = name.slice(0, -3);
let alias = name, subpath = '.';
const slashIndex = name.indexOf('/');
if (slashIndex !== -1) {
alias = name.slice(0, slashIndex);
subpath = `./${name.slice(slashIndex + 1)}`;
}
return {
alias,
subpath,
target: {
pkgTarget: {
registry: 'deno',
name: 'std',
ranges: [
new SemverRange('*')
],
unstable: true
},
installSubpath: `./${slashIndex === -1 ? name : name.slice(0, slashIndex)}`
}
};
}
}
export function pkgToUrl(pkg) {
if (pkg.registry === 'deno') return `${stdlibUrl}@${pkg.version}/`;
if (pkg.registry === 'denoland') return `${cdnUrl}${pkg.name}@${vCache[pkg.name] ? 'v' : ''}${pkg.version}/`;
throw new Error(`Deno provider does not support the ${pkg.registry} registry for package "${pkg.name}" - perhaps you mean to install "denoland:${pkg.name}"?`);
}
export async function getPackageConfig(pkgUrl) {
if (pkgUrl.startsWith('https://deno.land/std@')) {
return {
exports: {
'./archive': './archive/mod.ts',
'./archive/*.ts': './archive/*.ts',
'./archive/*': './archive/*.ts',
'./async': './async/mod.ts',
'./async/*.ts': './async/*.ts',
'./async/*': './async/*.ts',
'./bytes': './bytes/mod.ts',
'./bytes/*.ts': './bytes/*.ts',
'./bytes/*': './bytes/*.ts',
'./collection': './collection/mod.ts',
'./collection/*.ts': './collection/*.ts',
'./collection/*': './collection/*.ts',
'./crypto': './crypto/mod.ts',
'./crypto/*.ts': './crypto/*.ts',
'./crypto/*': './crypto/*.ts',
'./datetime': './datetime/mod.ts',
'./datetime/*.ts': './datetime/*.ts',
'./datetime/*': './datetime/*.ts',
'./dotenv': './dotenv/mod.ts',
'./dotenv/*.ts': './dotenv/*.ts',
'./dotenv/*': './dotenv/*.ts',
'./encoding': './encoding/mod.ts',
'./encoding/*.ts': './encoding/*.ts',
'./encoding/*': './encoding/*.ts',
'./examples': './examples/mod.ts',
'./examples/*.ts': './examples/*.ts',
'./examples/*': './examples/*.ts',
'./flags': './flags/mod.ts',
'./flags/*.ts': './flags/*.ts',
'./flags/*': './flags/*.ts',
'./fmt': './fmt/mod.ts',
'./fmt/*.ts': './fmt/*.ts',
'./fmt/*': './fmt/*.ts',
'./fs': './fs/mod.ts',
'./fs/*.ts': './fs/*.ts',
'./fs/*': './fs/*.ts',
'./hash': './hash/mod.ts',
'./hash/*.ts': './hash/*.ts',
'./hash/*': './hash/*.ts',
'./http': './http/mod.ts',
'./http/*.ts': './http/*.ts',
'./http/*': './http/*.ts',
'./io': './io/mod.ts',
'./io/*.ts': './io/*.ts',
'./io/*': './io/*.ts',
'./log': './log/mod.ts',
'./log/*.ts': './log/*.ts',
'./log/*': './log/*.ts',
'./media_types': './media_types/mod.ts',
'./media_types/*.ts': './media_types/*.ts',
'./media_types/*': './media_types/*.ts',
'./node': './node/mod.ts',
'./node/*.ts': './node/*.ts',
'./node/*': './node/*.ts',
'./path': './path/mod.ts',
'./path/*.ts': './path/*.ts',
'./path/*': './path/*.ts',
'./permissions': './permissions/mod.ts',
'./permissions/*.ts': './permissions/*.ts',
'./permissions/*': './permissions/*.ts',
'./signal': './signal/mod.ts',
'./signal/*.ts': './signal/*.ts',
'./signal/*': './signal/*.ts',
'./streams': './streams/mod.ts',
'./streams/*.ts': './streams/*.ts',
'./streams/*': './streams/*.ts',
'./testing': './testing/mod.ts',
'./testing/*.ts': './testing/*.ts',
'./testing/*': './testing/*.ts',
'./textproto': './textproto/mod.ts',
'./textproto/*.ts': './textproto/*.ts',
'./textproto/*': './textproto/*.ts',
'./uuid': './uuid/mod.ts',
'./uuid/*.ts': './uuid/*.ts',
'./uuid/*': './uuid/*.ts',
'./version': './version.ts',
'./version.ts': './version.ts',
'./wasi': './wasi/mod.ts',
'./wasi/*.ts': './wasi/*.ts',
'./wasi/*': './wasi*.ts'
}
};
}
// If there's a package.json, return that:
const pkgJsonUrl = new URL('package.json', pkgUrl);
const pkgRes = await fetch(pkgJsonUrl.href, this.fetchOpts);
switch(pkgRes.status){
case 200:
case 304:
return await pkgRes.json();
}
return null;
}
const vCache = {};
export function parseUrlPkg(url) {
let subpath = null;
if (url.startsWith(stdlibUrl) && url[stdlibUrl.length] === '@') {
const version = url.slice(stdlibUrl.length + 1, url.indexOf('/', stdlibUrl.length + 1));
subpath = url.slice(stdlibUrl.length + version.length + 2);
if (subpath.endsWith('/mod.ts')) subpath = subpath.slice(0, -7);
else if (subpath.endsWith('.ts')) subpath = subpath.slice(0, -3);
const name = subpath.indexOf('/') === -1 ? subpath : subpath.slice(0, subpath.indexOf('/'));
return {
pkg: {
registry: 'deno',
name: 'std',
version
},
layer: 'default',
subpath: `./${name}${subpath ? `./${subpath}/mod.ts` : ''}`
};
} else if (url.startsWith(cdnUrl)) {
const path = url.slice(cdnUrl.length);
const versionIndex = path.indexOf('@');
if (versionIndex === -1) return;
const sepIndex = path.indexOf('/', versionIndex);
const name = path.slice(0, versionIndex);
const version = path.slice(versionIndex + ((vCache[name] = path[versionIndex + 1] === 'v') ? 2 : 1), sepIndex === -1 ? path.length : sepIndex);
return {
pkg: {
registry: 'denoland',
name,
version
},
subpath: null,
layer: 'default'
};
}
}
export async function resolveLatestTarget(target, _layer, parentUrl) {
let { registry, name, range } = target;
if (denoStdVersion && registry === 'deno') return {
registry,
name,
version: denoStdVersion
};
if (range.isExact) return {
registry,
name,
version: range.version.toString()
};
// convert all Denoland ranges into wildcards
// since we don't have an actual semver lookup at the moment
if (!range.isWildcard) range = new SemverRange(range.version.toString());
const fetchOpts = {
...this.fetchOpts,
headers: Object.assign({}, this.fetchOpts.headers || {}, {
// For some reason, Deno provides different redirect behaviour for the server
// Which requires us to use the text/html accept
accept: typeof document === 'undefined' ? 'text/html' : 'text/javascript'
})
};
// "mod.ts" addition is necessary for the browser otherwise not resolving an exact module gives a CORS error
const fetchUrl = registry === 'denoland' ? cdnUrl + name + '/mod.ts' : stdlibUrl + '/version.ts';
const res = await fetch(fetchUrl, fetchOpts);
if (!res.ok) throw new Error(`Deno: Unable to lookup ${fetchUrl}`);
const { version } = (await parseUrlPkg(res.url)).pkg;
if (registry === 'deno') denoStdVersion = version;
return {
registry,
name,
version
};
}
//# sourceMappingURL=deno.js.map