Skip to content
This repository has been archived by the owner on May 27, 2020. It is now read-only.

Commit

Permalink
refactor: add extension support for resolvedModule
Browse files Browse the repository at this point in the history
  • Loading branch information
axetroy committed Apr 7, 2020
1 parent 90f4ad2 commit 5ea1d19
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 7 deletions.
5 changes: 4 additions & 1 deletion core/deno_cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import { getDenoDepsDir } from "./deno";
import { HashMeta } from "./hash_meta";
import { pathExistsSync, isHttpURL, hashURL, normalizeFilepath } from "./util";
import { Logger } from "./logger";
import { Extension } from "./extension";

export interface DenoCacheModule {
filepath: string;
extension: Extension;
url: URL;
resolveModule(moduleName: string): DenoCacheModule | void;
}
Expand Down Expand Up @@ -37,12 +39,13 @@ export class CacheModule implements DenoCacheModule {
return;
}

return new CacheModule(filepath, meta.url, logger);
return new CacheModule(filepath, meta.url, meta.extension, logger);
}

constructor(
public filepath: string,
public url: URL,
public extension: Extension,
private logger?: Logger
) {
filepath = normalizeFilepath(filepath);
Expand Down
12 changes: 12 additions & 0 deletions core/extension.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { getExtensionFromFile } from "./extension";

test("core / extension: getExtensionFromFile", async () => {
expect(getExtensionFromFile("./foo.ts")).toBe(".ts");
expect(getExtensionFromFile("./foo.tsx")).toBe(".tsx");
expect(getExtensionFromFile("./foo.js")).toBe(".js");
expect(getExtensionFromFile("./foo.jsx")).toBe(".jsx");
expect(getExtensionFromFile("./foo.d.ts")).toBe(".d.ts");
expect(getExtensionFromFile("./foo.json")).toBe(".json");
expect(getExtensionFromFile("./foo.wasm")).toBe(".wasm");
expect(getExtensionFromFile("./foo")).toBe("");
});
23 changes: 23 additions & 0 deletions core/extension.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import * as path from "path";

export type Extension =
| ".ts"
| ".tsx"
| ".d.ts"
| ".js"
| ".jsx"
| ".json"
| ".wasm"
| "";

export function getExtensionFromFile(filename: string): Extension {
const extName = path.extname(filename);

if (extName === ".ts") {
if (/\.d\.ts$/.test(filename)) {
return ".d.ts";
}
}

return extName as Extension;
}
6 changes: 6 additions & 0 deletions core/hash_meta.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ test("core / hash_meta", () => {
expect(meta).not.toBe(undefined);
expect(meta.filepath).toEqual(cacheFilepath + ".metadata.json");
expect(meta.type).toEqual(Type.TypeScript);
expect(meta.extension).toEqual(".ts");
expect(meta.url.href).toEqual("https://example.com/demo/mod.ts");
expect(meta.destinationFilepath).toEqual(cacheFilepath);
});
Expand All @@ -42,6 +43,7 @@ test("core / hash_meta with javascript file", () => {
expect(meta).not.toBe(undefined);
expect(meta.filepath).toEqual(cacheFilepath + ".metadata.json");
expect(meta.type).toEqual(Type.JavaScript);
expect(meta.extension).toEqual(".js");
expect(meta.url.href).toEqual("https://example.com/demo.js");
expect(meta.destinationFilepath).toEqual(cacheFilepath);
});
Expand All @@ -59,6 +61,7 @@ test("core / hash_meta with json file", () => {
expect(meta).not.toBe(undefined);
expect(meta.filepath).toEqual(cacheFilepath + ".metadata.json");
expect(meta.type).toEqual(Type.JSON);
expect(meta.extension).toEqual(".json");
expect(meta.url.href).toEqual("https://example.com/demo.json");
expect(meta.destinationFilepath).toEqual(cacheFilepath);
});
Expand All @@ -76,6 +79,7 @@ test("core / hash_meta without extension name", () => {
expect(meta).not.toBe(undefined);
expect(meta.filepath).toEqual(cacheFilepath + ".metadata.json");
expect(meta.type).toEqual(Type.PlainText);
expect(meta.extension).toEqual("");
expect(meta.url.href).toEqual("https://example.com/without-extension-name");
expect(meta.destinationFilepath).toEqual(cacheFilepath);
});
Expand All @@ -93,6 +97,7 @@ test("core / hash_meta if have content-type", () => {
expect(meta).not.toBe(undefined);
expect(meta.filepath).toEqual(cacheFilepath + ".metadata.json");
expect(meta.type).toEqual(Type.JavaScript);
expect(meta.extension).toEqual(".js");
expect(meta.url.href).toEqual("https://example.com/content-type");
expect(meta.destinationFilepath).toEqual(cacheFilepath);
});
Expand All @@ -110,6 +115,7 @@ test("core / hash_meta if have content-type typescript", () => {
expect(meta).not.toBe(undefined);
expect(meta.filepath).toEqual(cacheFilepath + ".metadata.json");
expect(meta.type).toEqual(Type.TypeScript);
expect(meta.extension).toEqual(".ts");
expect(meta.url.href).toEqual("https://example.com/content-type-typescript");
expect(meta.destinationFilepath).toEqual(cacheFilepath);
});
Expand Down
24 changes: 24 additions & 0 deletions core/hash_meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as fs from "fs";
import * as path from "path";

import { pathExistsSync, normalizeFilepath } from "./util";
import { Extension } from "./extension";

type HTTPHeaders = { [key: string]: string };

Expand Down Expand Up @@ -99,6 +100,29 @@ export class HashMeta implements HashMetaInterface {

return Type.PlainText;
}
get extension(): Extension {
const type = this.type;

switch (type) {
case Type.JavaScript:
return ".js";
/* istanbul ignore next */
case Type.JavaScriptReact:
return ".jsx";
case Type.TypeScript:
return ".ts";
/* istanbul ignore next */
case Type.TypeScriptReact:
return ".tsx";
case Type.JSON:
return ".json";
/* istanbul ignore next */
case Type.WebAssembly:
return ".wasm";
}

return "";
}
get destinationFilepath(): string {
return this.filepath.replace(/\.metadata\.json$/, "");
}
Expand Down
11 changes: 11 additions & 0 deletions core/module_resolver.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ test("core / module_resolver: resolve module from Deno cache", () => {
])
).toEqual([
{
extension: ".ts",
origin: "./sub/mod.ts",
filepath: path.join(
path.dirname(cacheFilepath),
Expand All @@ -44,6 +45,7 @@ test("core / module_resolver: resolve module from Deno cache", () => {
),
},
{
extension: ".ts",
origin: "/esm/mod.ts",
filepath: path.join(
path.dirname(cacheFilepath),
Expand All @@ -55,6 +57,7 @@ test("core / module_resolver: resolve module from Deno cache", () => {
),
},
{
extension: ".ts",
origin: "https://example.com/esm/mod.ts",
filepath: path.join(
path.dirname(cacheFilepath),
Expand Down Expand Up @@ -88,16 +91,19 @@ test("core / module_resolver: resolve module from local", () => {
])
).toEqual([
{
extension: ".ts",
origin: "./deno.ts",
filepath: path.join(__dirname, "deno.ts"),
module: path.join(__dirname, "deno.ts").replace(/\.ts$/, ""),
},
{
extension: ".json",
origin: "../package.json",
filepath: path.join(__dirname, "..", "package.json"),
module: path.join(__dirname, "..", "package.json"),
},
{
extension: ".ts",
origin: "https://example.com/esm/mod.ts",
filepath: path.join(
path.dirname(cacheFilepath),
Expand All @@ -109,6 +115,7 @@ test("core / module_resolver: resolve module from local", () => {
),
},
{
extension: ".ts",
origin: "demo/mod.ts",
filepath: path.join(
path.dirname(cacheFilepath),
Expand All @@ -120,6 +127,7 @@ test("core / module_resolver: resolve module from local", () => {
),
},
{
extension: ".ts",
origin: "https://another.example.com/path/mod.ts?foo=bar",
filepath: path.join(
denoDir,
Expand All @@ -139,6 +147,7 @@ test("core / module_resolver: resolve module from local", () => {
undefined,
undefined,
{
extension: ".ts",
origin: "https://example.com/x-typescript-types",
filepath: path.join(
denoDir,
Expand Down Expand Up @@ -172,6 +181,7 @@ test("core / module_resolver: resolve module if redirect", () => {
])
).toEqual([
{
extension: ".ts",
origin: "https://example.com/redirect",
filepath: path.join(
denoDir,
Expand All @@ -189,6 +199,7 @@ test("core / module_resolver: resolve module if redirect", () => {
),
},
{
extension: ".ts",
origin: "https://example.com/redirect_to_absolute",
filepath: path.join(
denoDir,
Expand Down
7 changes: 6 additions & 1 deletion core/module_resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import { ImportMap } from "./import_map";
import { HashMeta } from "./hash_meta";
import { pathExistsSync, isHttpURL, hashURL, normalizeFilepath } from "./util";
import { Logger } from "./logger";
import { Extension, getExtensionFromFile } from "./extension";

export type ResolvedModule = {
origin: string; // the origin resolve module
filepath: string; // full file name path. May be relative or absolute
module: string; // final resolve module. It may not have an extension
extension: Extension;
};

export interface ModuleResolverInterface {
Expand Down Expand Up @@ -125,6 +127,7 @@ export class ModuleResolver implements ModuleResolverInterface {
origin: origin,
filepath: moduleFilepath,
module: moduleFilepath,
extension: meta.extension,
};
}

Expand All @@ -148,7 +151,8 @@ export class ModuleResolver implements ModuleResolverInterface {
return {
origin: originModuleName,
filepath: moduleFilepath,
module: moduleFilepath.replace(/(\.d)?\.(t|j)sx?$/, ""), // "./foo.ts" -> "./foo"
module: moduleFilepath.replace(/(\.d)?\.(t|j)sx?$/, ""), // "./foo.ts" -> "./foo",
extension: getExtensionFromFile(moduleFilepath),
};
}

Expand Down Expand Up @@ -178,6 +182,7 @@ export class ModuleResolver implements ModuleResolverInterface {
origin: moduleName,
filepath: moduleCacheFile.filepath,
module: moduleCacheFile.filepath,
extension: moduleCacheFile.extension,
});
} else {
resolvedModules.push(undefined);
Expand Down
18 changes: 13 additions & 5 deletions typescript-deno-plugin/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ export class DenoPlugin implements ts_module.server.PluginModule {
for (const typeDirectiveName of typeDirectiveNames) {
const [resolvedModule] = resolver.resolveModules([typeDirectiveName]);

// if module found. then return the module file
if (resolvedModule) {
const target: ts_module.ResolvedTypeReferenceDirective = {
primary: false,
Expand All @@ -185,6 +186,7 @@ export class DenoPlugin implements ts_module.server.PluginModule {
continue;
}

// If the module does not exist, then apply the native reference method
const [target] = resolveTypeReferenceDirectives(
[typeDirectiveName],
containingFile,
Expand Down Expand Up @@ -293,8 +295,8 @@ export class DenoPlugin implements ts_module.server.PluginModule {
// text is always unix style
const text = source.text;

const absoluteFilepath = path.posix.resolve(
path.dirname(fileName),
const absoluteFilepath = path.resolve(
normalizeFilepath(path.dirname(fileName)),
normalizeFilepath(text)
);

Expand All @@ -321,7 +323,11 @@ export class DenoPlugin implements ts_module.server.PluginModule {
moduleNames: string[],
containingFile: string,
...rest
): (ts_module.ResolvedModule | undefined)[] => {
): (
| ts_module.ResolvedModule
| ts_module.ResolvedModuleFull
| undefined
)[] => {
if (!this.configurationManager.config.enable) {
return resolveModuleNames(moduleNames, containingFile, ...rest);
}
Expand Down Expand Up @@ -415,11 +421,13 @@ export class DenoPlugin implements ts_module.server.PluginModule {
path.isAbsolute(moduleFilepath) &&
pathExistsSync(moduleFilepath)
) {
return {
extension: this.typescript.Extension.Js,
const result: ts_module.ResolvedModuleFull = {
extension: cacheModule.extension,
isExternalLibraryImport: false,
resolvedFileName: moduleFilepath,
} as ts_module.ResolvedModuleFull;

return result;
}
}
}
Expand Down

0 comments on commit 5ea1d19

Please sign in to comment.