Skip to content

Commit

Permalink
resolving simple imported package based on node resolution
Browse files Browse the repository at this point in the history
  • Loading branch information
azizghuloum committed Dec 23, 2024
1 parent 5d7b316 commit 3763e6f
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 13 deletions.
70 changes: 57 additions & 13 deletions src/library-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ class RtsModule implements imported_module {
import_path: string,
loc: Loc,
): Promise<imported_module> {
const mod = this.library_manager.do_import(import_path, this.path);
const mod = await this.library_manager.do_import(import_path, this.path);
if (this.imported_modules.includes(mod)) return mod;
const self = this;
function check(mod: imported_module) {
Expand All @@ -405,15 +405,19 @@ class RtsModule implements imported_module {
}
}

type package_props = { types_file?: string };

class Package {
name: string;
version: string;
dir: string;
props: package_props;

constructor(name: string, version: string, dir: string) {
constructor(name: string, version: string, dir: string, props?: package_props) {
this.name = name;
this.version = version;
this.dir = dir;
this.props = props ?? {};
}
}

Expand Down Expand Up @@ -444,7 +448,15 @@ export class LibraryManager {
private get_or_create_module(path: string) {
const existing = this.modules[path];
if (existing) return existing;
const mod = new RtsModule(path, this, this.libs, this.global_unit, this.global_context);
const mod = (() => {
if (path.endsWith(".rts")) {
return new RtsModule(path, this, this.libs, this.global_unit, this.global_context);
} else if (path.endsWith(".d.ts")) {
throw new Error(`TODO import .d.ts ${path}`);
} else {
throw new Error(`don't know how to import ${path}`);
}
})();
this.modules[path] = mod;
const watcher = this.host.watchFile(path, (p) => {
if (p !== path) return;
Expand All @@ -465,41 +477,73 @@ export class LibraryManager {

async findPackage(path: string): Promise<[Package, string]> {
const base = basename(path);
const dir = dirname(path);
const existing = this.packages[dir];
const pkg_dir = dirname(path);
const existing = this.packages[pkg_dir];
if (existing) return [existing, base];
const pkg_path = join(dir, "package.json");
const pkg_path = join(pkg_dir, "package.json");
try {
const content = await fs.readFile(pkg_path, { encoding: "utf8" });
const json = JSON.parse(content);
const { name, version } = json;
assert(typeof name === "string");
assert(typeof version === "string");
return [(this.packages[dir] ??= new Package(name, version, dir)), base];
return [(this.packages[pkg_dir] ??= new Package(name, version, pkg_dir)), base];
} catch (err: any) {
if (err?.code === "ENOENT") {
const [pkg, pkg_base] = await this.findPackage(dir);
const [pkg, pkg_base] = await this.findPackage(pkg_dir);
return [pkg, join(pkg_base, base)];
} else {
throw err;
}
}
}

do_import(import_path: string, importer_path: string) {
async resolve_node_module_package(pkg_name: string, dir: string): Promise<Package> {
const pkg_dir = `${dir}/node_modules/${pkg_name}`;
const existing = this.packages[pkg_dir];
if (existing) return existing;
const pkg_path = join(pkg_dir, "package.json");
try {
const content = await fs.readFile(pkg_path, { encoding: "utf8" });
const json = JSON.parse(content);
const { name, version, types } = json;
assert(name === pkg_name);
assert(typeof version === "string");
assert(typeof types === "string");
return (this.packages[pkg_dir] ??= new Package(pkg_name, version, pkg_dir, {
types_file: types,
}));
} catch (err: any) {
if (err?.code === "ENOENT") {
return this.resolve_node_module_package(pkg_name, dirname(dir));
} else {
throw err;
}
}
}

async do_import(import_path: string, importer_path: string) {
function is_relative(path: string): boolean {
return path.startsWith("./") || path.startsWith("../");
}
function join_relative(import_path: string, importer_path: string): string {
const path = dirname(importer_path) + "/" + import_path;
return normalize(path);
}
function find_absolute_path(_import_path: string): string {
throw new Error("TODO find_absolute_path");
}
const find_absolute_path = async (import_path: string) => {
const b = basename(import_path);
if (b === import_path) {
const pkg = await this.resolve_node_module_package(b, dirname(importer_path));
assert(pkg.props.types_file !== undefined, `no types_file found in ${pkg.name}`);
const types_path = join(pkg.dir, pkg.props.types_file);
return types_path;
} else {
throw new Error(`TODO nested import of ${b} from ${dirname(import_path)}`);
}
};
const actual_path = is_relative(import_path)
? join_relative(import_path, importer_path)
: find_absolute_path(import_path);
: await find_absolute_path(import_path);
const mod = this.get_or_create_module(actual_path);
return mod;
}
Expand Down
1 change: 1 addition & 0 deletions test-project/main.rts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { x, t, fref } from "./mod.rts";
import { expect, test, suite } from "vitest";
const y: t = x + fref;
console.log(y);

0 comments on commit 3763e6f

Please sign in to comment.