@weborigami/origami 0.5.5 → 0.5.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/main.js +2 -26
  2. package/package.json +4 -5
  3. package/src/cli/cli.js +10 -8
  4. package/src/common/documentObject.js +1 -1
  5. package/src/common/utilities.d.ts +0 -1
  6. package/src/common/utilities.js +1 -19
  7. package/src/dev/ExplorableSiteTransform.js +2 -2
  8. package/src/dev/OriCommandTransform.js +25 -7
  9. package/src/dev/explore.js +17 -40
  10. package/src/dev/help.yaml +4 -1
  11. package/src/dev/log.js +1 -1
  12. package/src/dev/svg.js +5 -5
  13. package/src/initializeBuiltins.js +23 -0
  14. package/src/origami/fetch.js +4 -8
  15. package/src/origami/indexPage.js +4 -4
  16. package/src/origami/inline.js +3 -4
  17. package/src/origami/jsonParse.js +1 -1
  18. package/src/origami/mdHtml.js +3 -7
  19. package/src/origami/mdOutline.js +3 -3
  20. package/src/origami/ori.js +16 -24
  21. package/src/origami/origami.js +0 -2
  22. package/src/origami/sitemap.js +2 -2
  23. package/src/origami/static.js +2 -2
  24. package/src/origami/string.js +1 -10
  25. package/src/origami/yaml.js +1 -5
  26. package/src/origami/yamlParse.js +1 -1
  27. package/src/server/constructResponse.js +1 -1
  28. package/src/server/server.js +6 -26
  29. package/src/builtinsProgram.js +0 -56
  30. package/src/builtinsShell.js +0 -18
  31. package/src/cli/getConfig.js +0 -11
  32. package/src/common/constructHref.js +0 -20
  33. package/src/common/constructSiteTree.js +0 -34
  34. package/src/common/fetchAndHandleExtension.js +0 -27
  35. package/src/handlers/css.handler.js +0 -7
  36. package/src/handlers/csv.handler.js +0 -129
  37. package/src/handlers/handlerBuiltins.js +0 -27
  38. package/src/handlers/handlers.js +0 -33
  39. package/src/handlers/htm.handler.js +0 -2
  40. package/src/handlers/html.handler.js +0 -7
  41. package/src/handlers/jpeg.handler.js +0 -62
  42. package/src/handlers/jpg.handler.js +0 -2
  43. package/src/handlers/js.handler.js +0 -20
  44. package/src/handlers/json.handler.js +0 -27
  45. package/src/handlers/md.handler.js +0 -7
  46. package/src/handlers/mjs.handler.js +0 -2
  47. package/src/handlers/ori.handler.js +0 -55
  48. package/src/handlers/oridocument.handler.js +0 -78
  49. package/src/handlers/parseFrontMatter.js +0 -16
  50. package/src/handlers/processUnpackedContent.js +0 -35
  51. package/src/handlers/ts.handler.js +0 -1
  52. package/src/handlers/txt.handler.js +0 -91
  53. package/src/handlers/wasm.handler.js +0 -17
  54. package/src/handlers/xhtml.handler.js +0 -2
  55. package/src/handlers/yaml.handler.js +0 -36
  56. package/src/handlers/yml.handler.js +0 -2
  57. package/src/origami/config.js +0 -18
  58. package/src/origami/project.js +0 -111
  59. package/src/protocols/explore.js +0 -17
  60. package/src/protocols/files.js +0 -31
  61. package/src/protocols/http.js +0 -18
  62. package/src/protocols/https.js +0 -18
  63. package/src/protocols/httpstree.js +0 -17
  64. package/src/protocols/httptree.js +0 -17
  65. package/src/protocols/node.js +0 -13
  66. package/src/protocols/package.js +0 -70
@@ -1,78 +0,0 @@
1
- import { extension, getParent, trailingSlash } from "@weborigami/async-tree";
2
- import { compile } from "@weborigami/language";
3
- import builtinsProgram from "../builtinsProgram.js";
4
- import getConfig from "../cli/getConfig.js";
5
- import { toString } from "../common/utilities.js";
6
- import processUnpackedContent from "./processUnpackedContent.js";
7
-
8
- /**
9
- * An Origami template document: a plain text file that contains Origami
10
- * expressions.
11
- */
12
- export default {
13
- mediaType: "text/plain",
14
-
15
- /** @type {import("@weborigami/async-tree").UnpackFunction} */
16
- async unpack(packed, options = {}) {
17
- const parent = getParent(packed, options);
18
-
19
- // Unpack as a text document
20
- const text = toString(packed);
21
-
22
- // See if we can construct a URL to use in error messages
23
- const key = options.key;
24
- let url;
25
- if (key && /** @type {any} */ (parent)?.url) {
26
- let parentHref = /** @type {any} */ (parent).url.href;
27
- if (!parentHref.endsWith("/")) {
28
- parentHref += "/";
29
- }
30
- url = new URL(key, parentHref);
31
- }
32
-
33
- // Compile the text as an Origami template document
34
- const source = {
35
- name: key,
36
- text,
37
- url,
38
- };
39
-
40
- const config = getConfig(parent) ?? {};
41
- const globals = {
42
- ...(options.globals ?? builtinsProgram()),
43
- ...config,
44
- };
45
-
46
- const defineFn = compile.templateDocument(source, {
47
- front: options.front,
48
- globals,
49
- mode: "program",
50
- });
51
-
52
- // Invoke the definition to get back the template function
53
- const result = await defineFn.call(parent);
54
-
55
- const resultExtension = key ? extension.extname(key) : null;
56
- if (resultExtension && Object.isExtensible(result)) {
57
- // Add sidecar function so this template can be used in a map.
58
- result.key = addExtension(resultExtension);
59
- }
60
-
61
- return processUnpackedContent(result, parent);
62
- },
63
- };
64
-
65
- // Return a function that adds the given extension
66
- function addExtension(resultExtension) {
67
- return (sourceValue, sourceKey) => {
68
- if (sourceKey === undefined) {
69
- return undefined;
70
- }
71
- const normalizedKey = trailingSlash.remove(sourceKey);
72
- const sourceExtension = extension.extname(normalizedKey);
73
- const resultKey = sourceExtension
74
- ? extension.replace(normalizedKey, sourceExtension, resultExtension)
75
- : normalizedKey + resultExtension;
76
- return resultKey;
77
- };
78
- }
@@ -1,16 +0,0 @@
1
- import { isOrigamiFrontMatter } from "@weborigami/language";
2
-
3
- export default function parseFrontMatter(text) {
4
- const regex =
5
- /^(---\r?\n(?<frontText>[\s\S]*?\r?\n?)---\r?\n)(?<body>[\s\S]*$)/;
6
- const match = regex.exec(text);
7
- if (!match?.groups) {
8
- return null;
9
- }
10
- const isOrigami = isOrigamiFrontMatter(match.groups.frontText);
11
- return {
12
- body: match.groups.body,
13
- frontText: match.groups.frontText,
14
- isOrigami,
15
- };
16
- }
@@ -1,35 +0,0 @@
1
- import { symbols, Tree } from "@weborigami/async-tree";
2
-
3
- /**
4
- * Perform any necessary post-processing on the unpacked content of a file. This
5
- * lets treat the contents of various file types consistently.
6
- *
7
- * @typedef {import("@weborigami/types").AsyncTree} AsyncTree
8
- *
9
- * @param {any} content
10
- * @param {AsyncTree|null} parent
11
- * @returns
12
- */
13
- export default function processUnpackedContent(content, parent) {
14
- if (typeof content === "function") {
15
- // Bind the function to the parent as the `this` context.
16
- const result = content.bind(parent);
17
- // Copy over any properties that were attached to the function
18
- Object.assign(result, content);
19
- return result;
20
- } else if (Tree.isAsyncTree(content) && !content.parent) {
21
- const result = Object.create(content);
22
- result.parent = parent;
23
- return result;
24
- } else if (Object.isExtensible(content) && !content[symbols.parent]) {
25
- Object.defineProperty(content, symbols.parent, {
26
- configurable: true,
27
- enumerable: false,
28
- value: parent,
29
- writable: true,
30
- });
31
- return content;
32
- } else {
33
- return content;
34
- }
35
- }
@@ -1 +0,0 @@
1
- export { jsHandler as default } from "./handlers.js";
@@ -1,91 +0,0 @@
1
- import { isPacked, symbols } from "@weborigami/async-tree";
2
- import { compile } from "@weborigami/language";
3
- import { parseYaml, toYaml } from "../common/serialize.js";
4
- import { toString } from "../common/utilities.js";
5
- import parseFrontMatter from "./parseFrontMatter.js";
6
-
7
- /**
8
- * A text file with possible front matter
9
- *
10
- * The unpacking process will parse out any YAML or JSON front matter and attach
11
- * it to the document as data. The first line of the text must be "---",
12
- * followed by a block of JSON or YAML, followed by another line of "---". Any
13
- * lines following will be treated as the document text.
14
- *
15
- * If there is no front matter, the document will be treated as plain text and
16
- * returned as a String object.
17
- *
18
- * If there is front matter, any Origami expressions in the front matter will be
19
- * evaluated. The result will be a plain JavaScript object with the evaluated
20
- * data and a `_body` property containing the document text.
21
- */
22
- export default {
23
- mediaType: "text/plain",
24
-
25
- /**
26
- * If the input is already in some packed format, it will be returned as is.
27
- *
28
- * Otherwise, the properties of the object will be formatted as YAML. If the
29
- * object has a `_body` property, that will be used as the body of the text
30
- * document; otherwise, an empty string will be used.
31
- *
32
- * @param {any} object
33
- * @returns {Promise<import("@weborigami/async-tree").Packed>}
34
- */
35
- async pack(object) {
36
- if (isPacked(object)) {
37
- return object;
38
- } else if (!object || typeof object !== "object") {
39
- throw new TypeError("The input to pack must be a JavaScript object.");
40
- }
41
-
42
- const text = object._body ?? "";
43
-
44
- /** @type {any} */
45
- const dataWithoutText = Object.assign({}, object);
46
- delete dataWithoutText._body;
47
- if (Object.keys(dataWithoutText).length > 0) {
48
- const frontMatter = (await toYaml(dataWithoutText)).trimEnd();
49
- return `---\n${frontMatter}\n---\n${text}`;
50
- } else {
51
- return text;
52
- }
53
- },
54
-
55
- /** @type {import("@weborigami/async-tree").UnpackFunction} */
56
- async unpack(packed, options = {}) {
57
- const parent = options.parent ?? null;
58
- const text = toString(packed);
59
- if (text === null) {
60
- throw new Error("Tried to treat a file as text but it wasn't text.");
61
- }
62
-
63
- const parsed = parseFrontMatter(text);
64
- let unpacked;
65
- if (parsed) {
66
- // Document object with front matter
67
- const { body, frontText, isOrigami } = parsed;
68
- let frontData;
69
- if (isOrigami) {
70
- const compiled = compile.expression(frontText.trim());
71
- frontData = await compiled.call(parent);
72
- } else {
73
- frontData = parseYaml(frontText);
74
- }
75
- unpacked = { ...frontData };
76
- Object.defineProperty(unpacked, "_body", {
77
- configurable: true,
78
- enumerable: true,
79
- value: body,
80
- writable: true,
81
- });
82
- } else {
83
- // Plain text
84
- unpacked = new String(text);
85
- }
86
-
87
- unpacked[symbols.parent] = parent;
88
-
89
- return unpacked;
90
- },
91
- };
@@ -1,17 +0,0 @@
1
- import processUnpackedContent from "./processUnpackedContent.js";
2
-
3
- /**
4
- * A WebAssembly module
5
- *
6
- * Unpacking a WebAssembly module returns its exports.
7
- */
8
- export default {
9
- mediaType: "application/wasm",
10
-
11
- /** @type {import("@weborigami/async-tree").UnpackFunction} */
12
- async unpack(packed, options = {}) {
13
- const wasmModule = await WebAssembly.instantiate(packed);
14
- // @ts-ignore TypeScript thinks wasmModule is already an Instance.
15
- return processUnpackedContent(wasmModule.instance.exports, options.parent);
16
- },
17
- };
@@ -1,2 +0,0 @@
1
- // .xhtml is a synonynm for .html
2
- export { htmlHandler as default } from "./handlers.js";
@@ -1,36 +0,0 @@
1
- import { symbols } from "@weborigami/async-tree";
2
- import * as YAMLModule from "yaml";
3
- import { parseYaml } from "../common/serialize.js";
4
- import * as utilities from "../common/utilities.js";
5
- import processUnpackedContent from "./processUnpackedContent.js";
6
-
7
- // See notes at serialize.js
8
- // @ts-ignore
9
- const YAML = YAMLModule.default ?? YAMLModule.YAML;
10
-
11
- /**
12
- * A YAML file
13
- *
14
- * Unpacking a YAML file returns the parsed data.
15
- *
16
- */
17
- export default {
18
- mediaType: "application/yaml",
19
-
20
- /** @type {import("@weborigami/async-tree").UnpackFunction} */
21
- unpack(packed, options = {}) {
22
- const parent = options.parent ?? null;
23
- const yaml = utilities.toString(packed);
24
- if (!yaml) {
25
- throw new Error("Tried to parse something as YAML but it wasn't text.");
26
- }
27
- const data = parseYaml(yaml);
28
- if (data && typeof data === "object" && Object.isExtensible(data)) {
29
- Object.defineProperty(data, symbols.deep, {
30
- enumerable: false,
31
- value: true,
32
- });
33
- }
34
- return processUnpackedContent(data, parent);
35
- },
36
- };
@@ -1,2 +0,0 @@
1
- // .yml is a synonym for .yaml
2
- export { yamlHandler as default } from "./handlers.js";
@@ -1,18 +0,0 @@
1
- import project from "./project.js";
2
-
3
- /**
4
- * Return the configuration for the current project.
5
- *
6
- * The configuration is the project's config.ori file (if defined in the project
7
- * root) plus the Origami builtins.
8
- *
9
- * @typedef {import("@weborigami/types").AsyncTree} AsyncTree
10
- *
11
- * @this {AsyncTree|null}
12
- * @param {any} [key]
13
- */
14
- export default async function config(key) {
15
- const projectTree = await project.call(this);
16
- const projectConfig = projectTree.config;
17
- return key === undefined ? projectConfig : projectConfig[key];
18
- }
@@ -1,111 +0,0 @@
1
- /** @typedef {import("@weborigami/types").AsyncTree} AsyncTree */
2
- import { OrigamiFiles } from "@weborigami/language";
3
- import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
4
- import handlerBuiltins from "../handlers/handlerBuiltins.js";
5
- import { oriHandler } from "../handlers/handlers.js";
6
-
7
- const configFileName = "config.ori";
8
-
9
- /**
10
- * Return an object for the current project including
11
- *
12
- * `config`: the evaluated config.ori file
13
- * `root`: the project's root folder
14
- *
15
- * This searches the current directory and its ancestors for an Origami file
16
- * called `config.ori`. If an Origami configuration file is found, the
17
- * containing folder is considered to be the project root. This returns a tree
18
- * for that folder, with the exported configuration as the context for that
19
- * folder — that is, the tree exported by the configuration will be the scope.
20
- *
21
- * If no Origami configuration file is found, the current folder will be
22
- * returned as a tree, with the builtins as its parent.
23
- *
24
- * @this {AsyncTree|null}
25
- */
26
- export default async function project() {
27
- assertTreeIsDefined(this, "project");
28
-
29
- const dirname = process.cwd();
30
- const currentTree = new OrigamiFiles(dirname);
31
- let config;
32
-
33
- // Search up the tree for the configuration file or package.json to determine
34
- // the project root.
35
- let root;
36
- const foundConfig = await findAncestorFile(currentTree, configFileName);
37
- if (foundConfig) {
38
- root = foundConfig.container;
39
- // Attach standard extension handlers so config can use them
40
- root.handlers = handlerBuiltins();
41
- // Unpack Origami configuration file
42
- const buffer = foundConfig.value;
43
- config = await oriHandler.unpack(buffer, {
44
- key: configFileName,
45
- parent: root,
46
- });
47
- root.config = config;
48
- } else {
49
- // No Origami configuration file, look for package.json
50
- const foundPackageJson = await findAncestorFile(
51
- currentTree,
52
- "package.json"
53
- );
54
- if (foundPackageJson) {
55
- // Found package.json; use its parent as the project root
56
- root = foundPackageJson.container;
57
- } else {
58
- // No package.json found; use the current directory as root
59
- root = currentTree;
60
- }
61
- }
62
-
63
- // Merge config if present into handlers
64
- root.handlers = config
65
- ? {
66
- ...handlerBuiltins(),
67
- ...configHandlers(config),
68
- }
69
- : handlerBuiltins();
70
-
71
- return root;
72
- }
73
-
74
- // Find the first ancestor of the given folder that contains a file with the
75
- // given name. Return the container and the file contents.
76
- async function findAncestorFile(start, fileName) {
77
- let container = start;
78
- while (container) {
79
- const value = await container.get(fileName);
80
- if (value) {
81
- // Found the desired file
82
- return {
83
- container,
84
- value,
85
- };
86
- }
87
- // Not found; try the parent
88
- const parent = await container.get("..");
89
- if (
90
- !parent ||
91
- (parent.path && container.path && parent.path === container.path)
92
- ) {
93
- break;
94
- }
95
- container = parent;
96
- }
97
-
98
- // Not found
99
- return null;
100
- }
101
-
102
- // Return an object with all `.handler` keys from the config
103
- function configHandlers(config) {
104
- const handlers = {};
105
- for (const key in config) {
106
- if (key.endsWith(".handler")) {
107
- handlers[key] = config[key];
108
- }
109
- }
110
- return handlers;
111
- }
@@ -1,17 +0,0 @@
1
- import { ExplorableSiteTree } from "@weborigami/async-tree";
2
- import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
3
- import constructSiteTree from "../common/constructSiteTree.js";
4
-
5
- /**
6
- * A site tree with JSON Keys via HTTPS.
7
- *
8
- * @typedef {import("@weborigami/types").AsyncTree} AsyncTree
9
- *
10
- * @this {AsyncTree|null}
11
- * @param {string} host
12
- * @param {...string} keys
13
- */
14
- export default function explore(host, ...keys) {
15
- assertTreeIsDefined(this, "explore");
16
- return constructSiteTree("https:", ExplorableSiteTree, this, host, ...keys);
17
- }
@@ -1,31 +0,0 @@
1
- import { OrigamiFiles, getHandlers } from "@weborigami/language";
2
- import os from "node:os";
3
- import path from "node:path";
4
- import process from "node:process";
5
- import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
6
-
7
- /**
8
- * @typedef {import("@weborigami/types").AsyncTree} AsyncTree
9
- *
10
- * @this {AsyncTree|null}
11
- * @param {string[]} keys
12
- */
13
- export default async function files(...keys) {
14
- assertTreeIsDefined(this, "files");
15
-
16
- // If path begins with `~`, treat it relative to the home directory.
17
- // Otherwise, treat it relative to the current working directory.
18
- let relativePath = keys.join(path.sep);
19
- let basePath;
20
- if (relativePath.startsWith("~")) {
21
- basePath = os.homedir();
22
- relativePath = relativePath.slice(2);
23
- } else {
24
- basePath = process.cwd();
25
- }
26
- const resolved = path.resolve(basePath, relativePath);
27
-
28
- const result = new OrigamiFiles(resolved);
29
- /** @type {any} */ (result).handlers = getHandlers(this);
30
- return result;
31
- }
@@ -1,18 +0,0 @@
1
- import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
2
- import constructHref from "../common/constructHref.js";
3
- import fetchAndHandleExtension from "../common/fetchAndHandleExtension.js";
4
-
5
- /**
6
- * Retrieve the indicated web resource via HTTP.
7
- *
8
- * @typedef {import("@weborigami/types").AsyncTree} AsyncTree
9
- *
10
- * @this {AsyncTree|null}
11
- * @param {string} host
12
- * @param {...string} keys
13
- */
14
- export default async function http(host, ...keys) {
15
- assertTreeIsDefined(this, "http");
16
- const href = constructHref("http:", host, ...keys);
17
- return fetchAndHandleExtension.call(this, href);
18
- }
@@ -1,18 +0,0 @@
1
- import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
2
- import constructHref from "../common/constructHref.js";
3
- import fetchAndHandleExtension from "../common/fetchAndHandleExtension.js";
4
-
5
- /**
6
- * Retrieve the indicated web resource via HTTPS.
7
- *
8
- * @typedef {import("@weborigami/types").AsyncTree} AsyncTree
9
- *
10
- * @this {AsyncTree|null}
11
- * @param {string} host
12
- * @param {...string} keys
13
- */
14
- export default async function https(host, ...keys) {
15
- assertTreeIsDefined(this, "https");
16
- const href = constructHref("https:", host, ...keys);
17
- return fetchAndHandleExtension.call(this, href);
18
- }
@@ -1,17 +0,0 @@
1
- import { SiteTree } from "@weborigami/async-tree";
2
- import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
3
- import constructSiteTree from "../common/constructSiteTree.js";
4
-
5
- /**
6
- * Return a website tree via HTTPS.
7
- *
8
- * @typedef {import("@weborigami/types").AsyncTree} AsyncTree
9
- *
10
- * @this {AsyncTree|null}
11
- * @param {string} host
12
- * @param {...string} keys
13
- */
14
- export default function httpstree(host, ...keys) {
15
- assertTreeIsDefined(this, "treehttps");
16
- return constructSiteTree("https:", SiteTree, this, host, ...keys);
17
- }
@@ -1,17 +0,0 @@
1
- import { SiteTree } from "@weborigami/async-tree";
2
- import assertTreeIsDefined from "../common/assertTreeIsDefined.js";
3
- import constructSiteTree from "../common/constructSiteTree.js";
4
-
5
- /**
6
- * Return a website tree via HTTP.
7
- *
8
- * @typedef {import("@weborigami/types").AsyncTree} AsyncTree
9
- *
10
- * @this {AsyncTree|null}
11
- * @param {string} host
12
- * @param {...string} keys
13
- */
14
- export default function httptree(host, ...keys) {
15
- assertTreeIsDefined(this, "httptree");
16
- return constructSiteTree("http:", SiteTree, this, host, ...keys);
17
- }
@@ -1,13 +0,0 @@
1
- import { trailingSlash, Tree } from "@weborigami/async-tree";
2
-
3
- /**
4
- * The node: protocol does a dynamic import from the `node:` namespace.
5
- *
6
- * @param {string[]} keys
7
- */
8
- export default async function node(...keys) {
9
- const key = keys.shift();
10
- const normalized = trailingSlash.remove(key);
11
- const module = await import(`node:${normalized}`);
12
- return keys.length > 0 ? Tree.traverse(module, ...keys) : module;
13
- }
@@ -1,70 +0,0 @@
1
- import { Tree, keysFromPath } from "@weborigami/async-tree";
2
- import project from "../origami/project.js";
3
-
4
- /**
5
- * @this {import("@weborigami/types").AsyncTree|null}
6
- * @param {string[]} keys
7
- */
8
- export default async function packageNamespace(...keys) {
9
- const parent = this ?? (await project.call(null));
10
-
11
- let name = keys.shift();
12
- let organization;
13
- if (name?.startsWith("@")) {
14
- // First key is an npm organization
15
- organization = name;
16
- if (keys.length === 0) {
17
- // Return a function that will process the next key
18
- return async (name, ...keys) =>
19
- getPackage(parent, organization, name, keys);
20
- }
21
- name = keys.shift();
22
- }
23
-
24
- return getPackage(parent, organization, name, keys);
25
- }
26
-
27
- async function getPackage(parent, organization, name, keys) {
28
- const packagePath = ["node_modules"];
29
- if (organization) {
30
- packagePath.push(organization);
31
- }
32
- packagePath.push(name);
33
-
34
- const parentScope = await Tree.scope(parent);
35
- const packageRoot = await Tree.traverse(
36
- // @ts-ignore
37
- parentScope,
38
- ...packagePath
39
- );
40
-
41
- if (!packageRoot) {
42
- throw new Error(`Can't find ${packagePath.join("/")}`);
43
- }
44
-
45
- const mainPath = await Tree.traverse(packageRoot, "package.json", "main");
46
- if (!mainPath) {
47
- throw new Error(
48
- `node_modules/${keys.join(
49
- "/"
50
- )} doesn't contain a package.json with a "main" entry.`
51
- );
52
- }
53
-
54
- const mainKeys = keysFromPath(mainPath);
55
- const mainContainerKeys = mainKeys.slice(0, -1);
56
- const mainFileName = mainKeys[mainKeys.length - 1];
57
- const mainContainer = await Tree.traverse(packageRoot, ...mainContainerKeys);
58
- const packageExports = await mainContainer.import(mainFileName);
59
-
60
- const result =
61
- keys.length > 0
62
- ? await Tree.traverse(packageExports, ...keys)
63
- : packageExports;
64
-
65
- if (Tree.isAsyncTree(result)) {
66
- result.parent = parent;
67
- }
68
-
69
- return result;
70
- }