代码之家  ›  专栏  ›  技术社区  ›  ThomasReggi

如何获取下载的deno模块的路径?

  •  0
  • ThomasReggi  · 技术社区  · 2 年前

    给定下载的deno模块,如:

    import x from "https://deno.land/x/reggi@0.0.1/calendar/denodb/fresh/island.ts"
    

    如何查找此特定模块在主机上的位置?

    ➜  deno.land cd x
    cd: no such file or directory: x
    ➜  deno.land pwd
    /Users/thomasreggi/Library/Caches/deno/deps/https/deno.land
    

    这里似乎没有“x”目录

    文件本地存储在哪里? 如何通过代码/api从url创建本地文件路径?

    0 回复  |  直到 2 年前
        1
  •  2
  •   jsejcksn    2 年前

    注意事项:

    • 这个 Linking to Third Party Code 手册中的部分将是关于这个主题的一个很好的入口参考。

    • 以下信息是Deno的最新版本 1.25.1


    Deno有一个 dependency inspector 工具:

    deno info [URL] 将检查ES模块及其所有依赖项。

    此工具将模块的所有依赖项打印到 stdout ,输出包括模块的远程原点及其在本地存储设备上的缓存路径。

    它还有一个(当前不稳定)参数 --json 它将以JSON格式打印依赖项(如果这是您的目标,则更容易通过编程进行解析)。

    你可以 create a subprocess 在使用上述命令和参数的程序中,然后解析其输出,以便以编程方式确定模块的缓存位置。(还要注意,子流程API is changing 以及当前不稳定的API Deno.spawn Deno.spawnChild 将替换 the current one )

    以下是一个依赖项比您问题中的模块少的模块的输出示例:

    % deno info https://deno.land/std@0.154.0/testing/asserts.ts
    local: /Users/deno/.deno/deps/https/deno.land/ce1734220fb8c205d2de1b52a59b20401c59d0707abcc9765dbeb60c25483df9
    type: TypeScript
    dependencies: 3 unique (total 46.65KB)
    
    https://deno.land/std@0.154.0/testing/asserts.ts (23.22KB)
    ├── https://deno.land/std@0.154.0/fmt/colors.ts (11.62KB)
    ├─┬ https://deno.land/std@0.154.0/testing/_diff.ts (11.11KB)
    │ └── https://deno.land/std@0.154.0/fmt/colors.ts *
    └── https://deno.land/std@0.154.0/testing/_format.ts (705B)
    

    使用时的输出 --json 自变量:

    % deno info --json https://deno.land/std@0.154.0/testing/asserts.ts
    {
      "roots": [
        "https://deno.land/std@0.154.0/testing/asserts.ts"
      ],
      "modules": [
        {
          "kind": "esm",
          "local": "/Users/deno/.deno/deps/https/deno.land/02d8068ecd90393c6bf5c8f69b02882b789681b5c638c210545b2d71e604b585",
          "emit": null,
          "map": null,
          "size": 11904,
          "mediaType": "TypeScript",
          "specifier": "https://deno.land/std@0.154.0/fmt/colors.ts"
        },
        {
          "dependencies": [
            {
              "specifier": "../fmt/colors.ts",
              "code": {
                "specifier": "https://deno.land/std@0.154.0/fmt/colors.ts",
                "span": {
                  "start": {
                    "line": 11,
                    "character": 7
                  },
                  "end": {
                    "line": 11,
                    "character": 25
                  }
                }
              }
            }
          ],
          "kind": "esm",
          "local": "/Users/deno/.deno/deps/https/deno.land/62cb97c1d18d022406d28b201c22805c58600e9a6d837b0fc4b71621ed21e30d",
          "emit": null,
          "map": null,
          "size": 11380,
          "mediaType": "TypeScript",
          "specifier": "https://deno.land/std@0.154.0/testing/_diff.ts"
        },
        {
          "kind": "esm",
          "local": "/Users/deno/.deno/deps/https/deno.land/3f50b09108fe404c8274e994b417a0802863842e740c1d7ca43c119c0ee0f14b",
          "emit": null,
          "map": null,
          "size": 705,
          "mediaType": "TypeScript",
          "specifier": "https://deno.land/std@0.154.0/testing/_format.ts"
        },
        {
          "dependencies": [
            {
              "specifier": "../fmt/colors.ts",
              "code": {
                "specifier": "https://deno.land/std@0.154.0/fmt/colors.ts",
                "span": {
                  "start": {
                    "line": 10,
                    "character": 32
                  },
                  "end": {
                    "line": 10,
                    "character": 50
                  }
                }
              }
            },
            {
              "specifier": "./_diff.ts",
              "code": {
                "specifier": "https://deno.land/std@0.154.0/testing/_diff.ts",
                "span": {
                  "start": {
                    "line": 11,
                    "character": 44
                  },
                  "end": {
                    "line": 11,
                    "character": 56
                  }
                }
              }
            },
            {
              "specifier": "./_format.ts",
              "code": {
                "specifier": "https://deno.land/std@0.154.0/testing/_format.ts",
                "span": {
                  "start": {
                    "line": 12,
                    "character": 23
                  },
                  "end": {
                    "line": 12,
                    "character": 37
                  }
                }
              }
            }
          ],
          "kind": "esm",
          "local": "/Users/deno/.deno/deps/https/deno.land/ce1734220fb8c205d2de1b52a59b20401c59d0707abcc9765dbeb60c25483df9",
          "emit": null,
          "map": null,
          "size": 23776,
          "mediaType": "TypeScript",
          "specifier": "https://deno.land/std@0.154.0/testing/asserts.ts"
        }
      ],
      "redirects": {}
    }
    

    但是,如果您的最终目标是将模块(来自远程源)缓存到本地存储设备并从该位置导入,而不是使用Deno的内置缓存,我建议使用内置工具: deno vendor 从…起 its manual page :

    deno vendor <specifiers>... 将指定模块的所有远程依赖项下载到本地 vendor 文件夹


    更新:下面是一个示例脚本,演示了我上面描述的方法:

    so-73596066.ts :

    /// <reference lib="deno.unstable" />
    
    import { assertExists } from "https://deno.land/std@0.154.0/testing/asserts.ts";
    
    /*
    `deno info --json` is unstable, and I didn't find any mention of schema for its
    output in the docs, but here's a (conservative) partial type for the bits
    that are relevant to this example, derived from looking at just a couple
    of outputs from Deno v1.25.1:
    */
    
    type ModuleInfo =
      & Record<"kind" | "local" | "mediaType" | "specifier", string>
      & Record<"emit" | "map", string | null>
      & {
        dependencies?: unknown[];
        size: number;
      };
    
    type DependencyInspectorResult = {
      modules: ModuleInfo[];
      roots: string[];
    };
    
    /**
     * Creates a formatted error message and allows for improved error handling by
     * discriminating error instances
     */
    class ProcessError extends Error {
      override name = "ProcessError";
    
      constructor(status: Deno.ChildStatus, stdErr?: string) {
        let msg = `The process exited with status code ${status.code}`;
        if (stdErr) msg += `. stderr:\n${stdErr}`;
        super(msg);
      }
    }
    
    /**
     * Parses output from `deno info --json`. The resulting command will look like:
     * `deno info --json [...denoInfoArgs] specifier`
     * @param specifier local/remote path/URL
     * @param denoInfoArgs optional, additional arguments to be used with `deno info --json`
     */
    async function getCachedModuleInfo(
      specifier: string | URL,
      denoInfoArgs?: string[],
    ): Promise<ModuleInfo> {
      const decoder = new TextDecoder();
      const specifierStr = String(specifier);
    
      const args = ["info", "--json"];
      if (denoInfoArgs?.length) args.push(...denoInfoArgs);
      args.push(specifierStr);
    
      const { stderr, stdout, ...status } = await Deno.spawn("deno", { args });
    
      if (!status.success) {
        const stdErr = decoder.decode(stderr).trim();
        throw new ProcessError(status, stdErr);
      }
    
      const result = JSON.parse(
        decoder.decode(stdout),
      ) as DependencyInspectorResult;
    
      const moduleInfo = result.modules.find((info) =>
        info.specifier === specifierStr
      );
    
      assertExists(moduleInfo, "Module not found in output");
      return moduleInfo;
    }
    
    /**
     * `console.log` truncates long strings and deep object properties by default.
     * This overrides that behavior.
     */
    function print(value: unknown): void {
      const inspectOpts: Deno.InspectOptions = {
        colors: true,
        depth: Infinity,
        strAbbreviateSize: Infinity,
      };
    
      const formattedOutput = Deno.inspect(value, inspectOpts);
      console.log(formattedOutput);
    }
    
    async function main() {
      const moduleInfo = await getCachedModuleInfo(
        "https://deno.land/std@0.154.0/testing/asserts.ts",
      );
    
      const { local, specifier } = moduleInfo;
      print({ specifier, local });
    }
    
    if (import.meta.main) main();
    
    
    % deno --version
    deno 1.25.1 (release, x86_64-apple-darwin)
    v8 10.6.194.5
    typescript 4.7.4
    
    % deno run --allow-run=deno --unstable so-73596066.ts
    {
      specifier: "https://deno.land/std@0.154.0/testing/asserts.ts",
      local: "/Users/deno/.deno/deps/https/deno.land/ce1734220fb8c205d2de1b52a59b20401c59d0707abcc9765dbeb60c25483df9"
    }
    
    推荐文章