Skip to content

Commit

Permalink
feat: improved entry point resolving
Browse files Browse the repository at this point in the history
  • Loading branch information
hansSchall committed Sep 7, 2024
1 parent 44a6c0a commit 98f2af7
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 52 deletions.
31 changes: 5 additions & 26 deletions mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import type { Plugin } from "vite";
import type { Opt } from "./src/options.ts";
import { ModuleGraph } from "./src/graph.ts";
import { join, toFileUrl } from "@std/path";
import { decodeSpec, encodeSpec, resolve } from "./src/resolve.ts";
import { resolve_undeclared_npm } from "./src/undeclared_npm.ts";

Expand Down Expand Up @@ -87,6 +86,7 @@ export function pluginDeno(options: PluginDenoOptions): Plugin {
o.exclude.push(/\/@id/);
o.exclude.push(/\/@vite\//);
o.exclude.push(/@vite\//);
o.exclude.push("<stdin>");

const graph = new ModuleGraph(o);

Expand All @@ -112,6 +112,10 @@ export function pluginDeno(options: PluginDenoOptions): Plugin {
id = decodeSpec(id);
referrer = referrer && decodeSpec(referrer);

if (id.endsWith(".html")) {
return null;
}

for (const exclude of o.exclude) {
if (exclude instanceof RegExp) {
if (exclude.test(id)) {
Expand All @@ -126,31 +130,6 @@ export function pluginDeno(options: PluginDenoOptions): Plugin {
}
}

if (referrer) {
try {
await Deno.stat(`${referrer}`);
referrer = toFileUrl(referrer).href;
} catch (_err) {
//
}
} else {
try {
await Deno.stat(`./${id}`);
id = toFileUrl(join(Deno.cwd(), id)).href;
} catch (_err) {
//
}
}

if (id.startsWith("/")) {
try {
await Deno.stat(`.${id}`);
} catch (_err) {
return null;
}
id = toFileUrl(`${Deno.cwd()}${id}`).href;
}

const resolved = await resolve(o, graph, id, referrer);

return encodeSpec(resolved);
Expand Down
27 changes: 21 additions & 6 deletions src/graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,9 @@ export class GraphModule {
for (const $ of def.dependencies) {
if ($.code) {
graph.get_module(parseModuleSpecifier($.code.specifier), false).then((mod) => {
this.esm_dependencies.set($.specifier, mod);
if (mod) {
this.esm_dependencies.set($.specifier, mod);
}
});
}
}
Expand All @@ -139,7 +141,7 @@ export class GraphModule {
} else if (this.def.kind === npmDataKind) {
return await getNPMData(this.def.specifier);
}
throw new Error(`module type unsupported`);
throw new Error(`module type ${this.def.kind} unsupported`);
}

async load(): Promise<string> {
Expand Down Expand Up @@ -190,6 +192,7 @@ export class ModuleGraph {
readonly npm_package_versions = new Map<string, Set<string>>();

async call_deno(root: string) {
console.log(`deno info ${root}`);
const args = ["info", "--json"];
if (this.o.deno_json) {
args.push("--config", this.o.deno_json);
Expand Down Expand Up @@ -271,14 +274,23 @@ export class ModuleGraph {
this.#redirects.set(parseModuleSpecifier(redirect).href, redirects[redirect]);
}

// remove self-redirects
for (const [k, v] of this.#redirects) {
if (k === v.href) {
this.#redirects.delete(k);
}
}

await Promise.all(waitNPM);

for (const [_id, pkg] of this.npm_packages) {
pkg.link();
}

for (const mod of modules) {
new GraphModule(mod, this);
if (mod.kind === "esm") {
new GraphModule(mod, this);
}
}
}

Expand All @@ -289,8 +301,9 @@ export class ModuleGraph {
this.#pending = null;
}

async get_module(specifier: ModuleSpecifier, may_fetch: boolean = true): Promise<GraphModule> {
async get_module(specifier: ModuleSpecifier, may_fetch: boolean = true): Promise<GraphModule | null> {
if (this.#redirects.has(specifier.href)) {
// console.log(`redirecting ${specifier}`);
return await this.get_module(this.#redirects.get(specifier.href)!, may_fetch);
}
if (this.modules.has(specifier.href)) {
Expand Down Expand Up @@ -360,8 +373,10 @@ export class ModuleGraph {
await this.update_info(specifier);
return await this.get_module(specifier, false);
} else {
console.log(`Specifier ${specifier} could not be resolved`);
throw new Error(`Specifier ${specifier} could not be resolved`);
// console.log(`Specifier ${specifier} could not be resolved`);
// throw new Error(`Specifier ${specifier} could not be resolved`);

return null;
}
}

Expand Down
82 changes: 62 additions & 20 deletions src/resolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,44 @@
* USA or see <https://www.gnu.org/licenses/>.
*/

import { fromFileUrl } from "@std/path";
import { fromFileUrl, isAbsolute, join, toFileUrl } from "@std/path";
import type { ModuleGraph } from "./graph.ts";
import { type ModuleSpecifier, parseModuleSpecifier, parseNPMImport } from "./specifier.ts";
import type { Opt } from "./options.ts";

async function exists(path: string): Promise<boolean> {
try {
await Deno.stat(path);
return true;
} catch (_) {
return false;
}
}

export async function resolve(o: Opt, graph: ModuleGraph, id: string, referrer?: string, may_fetch: boolean = true) {
// console.log(`%c[RESOLVE] ${id}`, "color:#ff0");
if (o.extra_import_map.has(id)) {
return await resolve(o, graph, await o.extra_import_map.get(id)!, referrer, may_fetch);
}

const referrer_mod = graph.get_resolved(referrer!);
if (referrer === undefined) {
// local entrypoint
id = join(Deno.cwd(), id);
}

let referrer_mod = referrer ? graph.get_resolved(referrer) : null;

if (
referrer && !referrer_mod && isAbsolute(referrer) && !referrer.includes(`registry.npmjs.org`) &&
await exists(referrer)
) {
referrer_mod = await graph.get_module(toFileUrl(referrer) as ModuleSpecifier);
}

if (referrer_mod) {
// console.log(`%c[REFERRER] ${referrer_mod.specifier.href}`, "color: gray");
const ref = await referrer_mod.resolve_import(id);
if (ref) {
// console.log(`%c[RESOLVED] ${ref.specifier.href}`, "color:#ff0");
return ref.specifier;
} else if (!id.startsWith("npm")) {
if (may_fetch) {
Expand All @@ -49,28 +70,49 @@ export async function resolve(o: Opt, graph: ModuleGraph, id: string, referrer?:
}
}

if (isAbsolute(id)) {
if (await exists(id)) {
const mod = await graph.get_module(toFileUrl(id) as ModuleSpecifier);

if (mod) {
// console.log(`%c[RESOLVED ABS] ${mod.specifier.href}`, "color:blue");

return mod.specifier;
}
} else {
const project_abs = join(Deno.cwd(), id);
if (await exists(project_abs)) {
const mod = await graph.get_module(toFileUrl(project_abs) as ModuleSpecifier);

if (mod) {
// console.log(`%c[RESOLVED ABS] ${mod.specifier.href}`, "color:blue");

return mod.specifier;
}
}
}
}
if (URL.canParse(id)) {
const mod = await graph.get_module(parseModuleSpecifier(id));
if (mod) {
return mod.specifier;
}
}

// console.log(`%c[RESOLVED ENTRY] ${mod.specifier.href}`, "color:blue");

return mod.specifier;
} else {
const maybe_npm = parseNPMImport(id);
if (maybe_npm) {
if (graph.npm_package_versions.has(maybe_npm.name)) {
const versions = graph.npm_package_versions.get(maybe_npm.name)!;
throw new Error(`cannot resolve ${id} from ${referrer}
${maybe_npm.name} has been recognized as an NPM package, if it is an injected import you may want to add "${maybe_npm.name}" to undeclared_npm_imports or one of the following entries to extra_import_map:
${
[...versions.values()].map((version) =>
`"${id}" => "npm:${maybe_npm.name}@${version}${maybe_npm.path ? `/${maybe_npm.path}` : ""}"`
).join("\n")
}`);
}
const npm = parseNPMImport(id);
if (npm) {
if (graph.npm_package_versions.has(npm.name)) {
const versions = graph.npm_package_versions.get(npm.name)!;
throw new Error(`cannot resolve ${id} from ${referrer}
${npm.name} has been recognized as an NPM package, if it is an injected import you may want to add "${npm.name}" to undeclared_npm_imports or one of the following entries to extra_import_map:
${
[...versions.values()].map((version) =>
`"${id}" => "npm:${npm.name}@${version}${npm.path ? `/${npm.path}` : ""}"`
).join("\n")
}`);
}
throw new Error(`cannot resolve ${id} from ${referrer}`);
}
throw new Error(`cannot resolve ${id} from ${referrer}`);
}

const fs_remap = new Map<string, ModuleSpecifier>();
Expand Down

0 comments on commit 98f2af7

Please sign in to comment.