parcel-plugin-codegen
Version:
A plugin for Parcel (v1) to generate useful modules at bundle-time.
111 lines (108 loc) • 4 kB
JavaScript
// src/CodeGenAsset.ts
var import_parcel_bundler = require("parcel-bundler");
var import_fs = require("fs");
var import_path2 = require("path");
// ../codegen-lib/lib/esm/index.mjs
var import_path = require("path");
var import_promises = require("fs/promises");
var import_module = require("module");
function reloadGenerator(requireModule, name) {
const path = requireModule.resolve(name);
delete requireModule.cache[path];
return requireModule(name);
}
function noop() {
}
async function dynamicCodegenImport(file) {
const dir = (0, import_path.dirname)(file);
const text = await (0, import_promises.readFile)(file, "utf8");
const code = replaceRelativeImports(text, dir);
const content = Buffer.from(code).toString("base64");
const url = `data:text/javascript;base64,${content}`;
return await import(url);
}
function replaceRelativeImports(content, absoluteBase) {
const regex = /import\s+([^'"]+)\s+from\s+(['"])\.\/([^'"]+)\2/g;
return content.replace(regex, (_, imports, quote, relativePath) => {
const absolutePath = `${absoluteBase}/${relativePath}`;
return `import ${imports} from ${quote}file://${absolutePath}${quote}`;
});
}
function createCodegenHost(fileOrDirName) {
const requireModule = (0, import_module.createRequire)(fileOrDirName);
const host = {
load(name, type) {
switch (type) {
case "cjs":
return Promise.resolve(reloadGenerator(requireModule, name));
case "esm":
return dynamicCodegenImport(name).then((result) => result.default || result);
case "auto":
default:
if (name.endsWith(".mjs.codegen") || name.endsWith(".esm.codegen") || name.endsWith(".module.codegen") || name.endsWith(".m.codegen")) {
return host.load(name, "esm");
}
return host.load(name, "cjs");
}
},
async generate(details) {
const { name, type = "auto", options = {}, addDependency = noop } = details;
if (typeof name !== "string") {
throw new Error(`You need to pass in a string for "name". Received: "${name}".`);
}
const generator = await host.load(name, type);
if (typeof generator !== "function") {
throw new Error(`The codegen module "${name}" does not export a function and is invalid.`);
}
const result = await generator.call({
name,
options,
addDependency
});
if (typeof result === "string") {
const type2 = typeof generator.type === "string" ? generator.type : "js";
return {
type: type2,
value: result
};
}
if (result && typeof result === "object" && typeof result.value === "string" && typeof result.type === "string") {
return result;
}
throw new Error(
`The codegen module "${name}" did not generate a valid result (string or object). It returned: "${result}".`
);
}
};
return host;
}
// src/CodeGenAsset.ts
var codegen = createCodegenHost(process.cwd());
var CodeGenAsset = class extends import_parcel_bundler.Asset {
constructor(name, options) {
super(name, options);
this.name = name;
this.options = options;
}
getFiles(dir, filter) {
const files = (0, import_fs.readdirSync)(dir).map((m) => (0, import_path2.resolve)(dir, m)).filter((m) => typeof filter !== "function" || filter(m));
files.forEach((file) => this.addDependency(file, { includedInParent: true }));
return files;
}
load() {
}
async generate() {
const value = await codegen.generate({
// Parcel v1 only supports CJS - otherwise throws an exception:
// "A dynamic import callback was not specified.", see:
// https://github.com/parcel-bundler/parcel/issues/8987
// (Parcel v2, but the issue exists since v1 and has only been fixed in v2)
type: "cjs",
name: this.name,
options: this.options
});
return [value];
}
};
module.exports = CodeGenAsset;
//# sourceMappingURL=CodeGenAsset.js.map