Modules
ESM export
Many modules use conditionally loaded functions inside a synchronous context. Only require supports loading packages or files (cjs) without using an async/await chain all the way to the top-level (e.g. squared-express). NodeJS/NPM packages themselves rarely use top-level await and can load ESM packages synchronously with require as of these versions:
24+
22.12
20.19
E-mc will detect default exports in these versions:
14+ [1]
13.10
12.16
There is not much difference between a “.cjs” and a “.mjs” file except TypeScript 6/7 no longer supports CommonJS.
import type * as terser from "terser";
import util from "@e-mc/document/util";
export default async function transform(context: typeof terser, value: string, options: terser.MinifyOptions) {
options.plugins = util.loadPlugins(options.plugins);
return (await context.minify(value, options)).code;
}
import type * as terser from "terser";
import util = require("@e-mc/document/util");
export = async function transform(context: typeof terser, value: string, options: terser.MinifyOptions) {
options.plugins = util.loadPlugins(options.plugins);
return (await context.minify(value, options)).code;
}
Note
E-mc is shipped only as CJS modules until 1.0.0. The source repository module system did change from “commonjs” to “preserve” in E-mc 0.14. [2]
Private members
Symbols for semi-privacy were replaced with JavaScript private properties [3] in E-mc 0.12.
const kConfig = Symbol('config');
class Host {
private readonly [kConfig]: Readonly<HostInitConfig>;
constructor(config: HostInitConfig) {
if (config.username) {
HOST_USERNAME.set(this, config.username);
}
this[kConfig] = Object.freeze({ ...config });
}
}
class Host {
readonly #config: Readonly<HostInitConfig>;
constructor(config: HostInitConfig) {
if (config.username) {
const cipher = HOST.CIPHER;
this.#username = cipher ? decryptUTF8(cipher.algorithm, cipher.key, cipher.iv, config.username) || '' : config.username;
}
this.#config = Object.freeze({ ...config });
}
}
The username property in particular requires pre-encryption [4] using the encryptUTF8 method exported from the Types package.
ESM imports
The default convention for all packages was removed in E-mc 0.9. It is auto-generated by the TSC compiler and is not necessary for out-of-source tree usage.
import Module from "@e-mc/module"; // OK
const Module = require("@e-mc/module"); // OK
let Module;
import("@e-mc/module").then(res => Module = res.default); // OK
Module.default.isPath("/path/file"); // OK
Module.isPath("/path/file"); // OK
import Module from "@e-mc/module"; // OK
const Module = require("@e-mc/module"); // OK
let Module;
import("@e-mc/module").then(res => Module = res.default); // OK
Module.default.isPath("/path/file"); // FAIL
Module.isPath("/path/file"); // OK
Besides static methods there is an additional utility library within these modules: