feat(compartment-mapper): Add Node.js power adapter
MODIFY
packages/compartment-mapper/NEWS.md
packages/compartment-mapper/NEWS.md
User-visible changes to the compartment mapper:
+# Next release
+
+- Adds an `"@endo/compartment-mapper/node-powers.js"` entry point utility
+ module that exports `makeNodeReadPowers` and `makeNodeWritePowers` that adapt
+ the Node.js `fs` module to the promise and URL oriented interfaces expected
+ by compartment mapper functions.
+
# 0.3.0 (2021-06-01)
- Reenables CommonJS support with a fast lexer and without a dependency on

ADD
packages/compartment-mapper/node-powers.js
+export { makeNodeReadPowers, makeNodeWritePowers } from './src/node-powers.js';

MODIFY
packages/compartment-mapper/package.json
packages/compartment-mapper/package.json
"./archive.js": "./archive.js",
"./import-archive.js": "./import-archive.js",
"./bundle.js": "./bundle.js",
+ "./node-powers.js": "./node-powers.js",
"./package.json": "./package.json"
},
"scripts": {

ADD
packages/compartment-mapper/src/node-powers.js
+// @ts-check
+
+/**
+ * @param {typeof import('fs')} fs
+ * @returns {ReadPowers}
+ */
+export const makeNodeReadPowers = fs => {
+ /**
+ * @param {string} location
+ */
+ const read = async location =>
+ fs.promises.readFile(new URL(location).pathname);
+
+ /**
+ * @param {string} location
+ */
+ const canonical = async location => {
+ try {
+ if (location.endsWith('/')) {
+ const realPath = await fs.promises.realpath(
+ new URL(location).pathname.replace(/\/$/, ''),
+ );
+ return new URL(`${realPath}/`, location).toString();
+ } else {
+ const realPath = await fs.promises.realpath(new URL(location).pathname);
+ return new URL(realPath, location).toString();
+ }
+ } catch {
+ return location;
+ }
+ };
+
+ return { read, canonical };
+};
+
+/**
+ * @param {typeof import('fs')} fs
+ * @returns {WritePowers}
+ */
+export const makeNodeWritePowers = fs => {
+ /**
+ * @param {string} location
+ * @param {Uint8Array} data
+ */
+ const write = async (location, data) =>
+ fs.promises.writeFile(new URL(location).pathname, data);
+
+ return { write };
+};

MODIFY
packages/compartment-mapper/src/types.js
packages/compartment-mapper/src/types.js
* @returns {Promise<Uint8Array>} bytes
*/
+/**
+ * @callback CanonicalFn
+ * @param {string} location
+ * @returns {Promise<string>} canonical location
+ */
+
/**
* @typedef {Object} Application
* @property {ExecuteFn} import
* @returns {Promise<Uint8Array>}
*/
+/**
+ * @typedef {Object} ReadPowers
+ * @property {ReadFn} read
+ * @property {CanonicalFn} canonical
+ */
+
+/**
+ * @typedef {Object} WritePowers
+ * @property {WriteFn} write
+ */
+
// /////////////////////////////////////////////////////////////////////////////
// Shared machinery for assembling applications:

feat(compartment-mapper): Add Node.js power adapter