UNPKG

telefunc

Version:

Remote functions. Instead of API.

110 lines (109 loc) 4.12 kB
export { isImportPathNpmPackage }; export { isImportPathNpmPackageOrPathAlias }; export { assertIsImportPathNpmPackage }; export { isPathAliasRecommended }; export { getNpmPackageName }; /* Currently not used export { isNpmPackageName } export { getNpmPackageImportPath } */ // For ./isNpmPackage.spec.ts export { parseNpmPackage }; export { isDistinguishable }; import { assert } from './assert.js'; import { assertIsNotBrowser } from './assertIsNotBrowser.js'; assertIsNotBrowser(); function isImportPathNpmPackage(str, { cannotBePathAlias }) { assert(cannotBePathAlias); return isImportPathNpmPackageOrPathAlias(str); } // We cannot distinguish path aliases that look like npm package imports function isImportPathNpmPackageOrPathAlias(str) { const res = parseNpmPackage(str); return res !== null; } function assertIsImportPathNpmPackage(str) { assert(isImportPathNpmPackage(str, { // If `str` is a path alias that looks like an npm package => assertIsImportPathNpmPackage() is erroneous but that's okay because the assertion will eventually fail for some other user using a disambiguated path alias. cannotBePathAlias: true, }), str); } function isNpmPackageName(str) { const res = parseNpmPackage(str); return res !== null && res.importPath === null; } function getNpmPackageName(str) { const res = parseNpmPackage(str); if (!res) return null; return res.pkgName; } function getNpmPackageImportPath(str) { const res = parseNpmPackage(str); if (!res) return null; return res.importPath; } function isPathAliasRecommended(alias) { // Cannot be distinguished from npm package names if (!isDistinguishable(alias)) return false; // Ensure path alias starts with a special character. // - In principle, we could allow path aliases that don't start with special character as long as they can be distinguished from npm package names. // - But we still enforce path aliases to start with a special character because it's a much simpler rule to follow. if (alias.startsWith('@/')) return true; // Needed by contra.com and https://github.com/vikejs/vike/issues/1567#issuecomment-3076374243 const firstLetter = alias[0]; assert(firstLetter); if (firstLetter === '@' || /[0-9a-z]/.test(firstLetter.toLowerCase())) return false; return true; } function isDistinguishable(alias) { return (parseNpmPackage(alias) === null && parseNpmPackage(`${alias}fake-path`) === null && parseNpmPackage(`${alias}/fake-path`) === null && parseNpmPackage(`${alias}fake/deep/path`) === null && parseNpmPackage(`${alias}/fake/deep/path`) === null && // See note about '-' in ./isNpmPackageName.spec.ts // ```ts // expect(parseNpmPackage('-')).toBe(null) // actually wrong: https://www.npmjs.com/package/- // ``` !alias.startsWith('-')); } // The logic down below is wrong, for example: // - https://www.npmjs.com/package/- // The correct logic is complex, see https://github.com/npm/validate-npm-package-name // We don't need to be accurate: are there npm packages with weird names that are actually being used? function parseNpmPackage(str) { if (!str) return null; let scope = null; if (str.startsWith('@')) { if (!str.includes('/')) return null; const [scope_, ...rest] = str.split('/'); scope = scope_; str = rest.join('/'); if (!str) return null; if (scope === '@' || invalid(scope.slice(1))) return null; } const [name, ...importPathParts] = str.split('/'); if (!name || invalid(name)) return null; const importPath = importPathParts.length === 0 ? null : importPathParts.join('/'); return { pkgName: scope ? `${scope}/${name}` : name, importPath, }; } function invalid(s) { const firstLetter = s[0]; if (!firstLetter || !/[a-z0-9]/.test(firstLetter)) return true; if (/[^a-z0-9_\-\.]/.test(s)) return true; return false; }