Files
config-plugins/scripts/generate-plugin.ts
T
2022-01-13 14:38:00 -07:00

174 lines
4.5 KiB
TypeScript

#!/usr/bin/env ts-node
import assert from "assert";
import * as fs from "fs";
import * as path from "path";
import prompts from "prompts";
// @ts-ignore
import replaceAll from "string.prototype.replaceall";
import * as PackageManager from "@expo/package-manager";
const packagesDir = path.join(__dirname, "../packages");
const templateDir = path.join(__dirname, "./template");
// Style like DT: @foo/bar -> foo__bar
function convertOrgName(name: string) {
const match = name.match(/^@(\w+)\/(\w+)/gi);
if (match?.length === 3) {
return [match[1], match[2]].join("__");
}
return name;
}
(async () => {
const { name } = await prompts({
initial: process.argv[2],
type: "text",
name: "name",
message: "Package to extend, ex: react-native-reanimated",
validate: (value) =>
/^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(value),
});
assert(name, "name must be defined");
const pluginName = convertOrgName(name);
const packageName = `@config-plugins/${pluginName}`;
console.log(`Using name: ${packageName}`);
const outputDir = path.join(packagesDir, pluginName);
// assert(!fs.existsSync(outputDir), `package already exists at: ${outputDir}`);
if (fs.existsSync(outputDir)) {
if (
(
await prompts({
type: "confirm",
message: "overwrite existing module?",
initial: true,
name: "value",
})
).value
) {
// Nuke
fs.rmSync(outputDir, { recursive: true });
} else {
return;
}
}
const moduleName = camelize(["with", name].join("-"));
const settings: Props = {
MODULE_NAME: moduleName,
CONFIG_PLUGIN: pluginName,
SDK_VERSION: "42",
NPM_MODULE: name,
};
console.log(`Module name: ${moduleName}`);
fs.mkdirSync(outputDir, { recursive: true });
fs.writeFileSync(
path.join(outputDir, "package.json"),
JSON.stringify(getPackageJson(settings), null, 2)
);
fs.copyFileSync(
path.join(templateDir, "tsconfig.json"),
path.join(outputDir, "tsconfig.json")
);
const srcFolder = path.join(outputDir, "src");
fs.mkdirSync(srcFolder, { recursive: true });
fs.writeFileSync(
path.join(srcFolder, `${moduleName}.ts`),
createTemplatePlugin(settings)
);
fs.writeFileSync(
path.join(outputDir, `README.md`),
createTemplateREADME(settings)
);
fs.writeFileSync(
path.join(outputDir, "app.plugin.js"),
`module.exports = require("./build/${moduleName}");`
);
const manager = new PackageManager.YarnPackageManager({
cwd: outputDir,
silent: false,
});
await manager.installAsync();
})();
function camelize(str: string) {
const arr = str.split("-");
const capital = arr.map((item, index) =>
index
? item.charAt(0).toUpperCase() + item.slice(1).toLowerCase()
: item.toLowerCase()
);
return capital.join("");
}
type Props = {
NPM_MODULE: string;
SDK_VERSION: string;
MODULE_NAME: string;
CONFIG_PLUGIN: string;
};
function createTemplatePlugin({
MODULE_NAME,
SDK_VERSION,
CONFIG_PLUGIN,
NPM_MODULE,
}: Props) {
let template = fs.readFileSync(path.join(templateDir, "index.ts"), "utf8");
template = replaceAll(template, /%NPM_MODULE%/g, NPM_MODULE);
template = replaceAll(template, /%CONFIG_PLUGIN%/g, CONFIG_PLUGIN);
template = replaceAll(template, /_MODULE_NAME_/g, MODULE_NAME);
template = replaceAll(template, /%SDK_VERSION%/g, SDK_VERSION);
return template;
}
function createTemplateREADME({
MODULE_NAME,
SDK_VERSION,
CONFIG_PLUGIN,
NPM_MODULE,
}: Props) {
let template = fs.readFileSync(path.join(templateDir, "README.md"), "utf8");
template = replaceAll(template, /%NPM_MODULE%/g, NPM_MODULE);
template = replaceAll(template, /%CONFIG_PLUGIN%/g, CONFIG_PLUGIN);
template = replaceAll(template, /%MODULE_NAME%/g, MODULE_NAME);
template = replaceAll(template, /%SDK_VERSION%/g, SDK_VERSION);
return template;
}
function getPackageJson({
MODULE_NAME,
SDK_VERSION,
CONFIG_PLUGIN,
NPM_MODULE,
}: Props) {
const templatePackageJson = JSON.parse(
fs.readFileSync(path.join(templateDir, "package.json"), "utf8")
);
templatePackageJson.name = `@config-plugins/${CONFIG_PLUGIN}`;
templatePackageJson.repository.directory = `packages/${CONFIG_PLUGIN}`;
templatePackageJson.description = `Config plugin for ${NPM_MODULE} package`;
templatePackageJson.main = `build/${MODULE_NAME}.js`;
templatePackageJson.types = `build/${MODULE_NAME}.d.ts`;
templatePackageJson.keywords.push(NPM_MODULE, `expo-${SDK_VERSION}`);
return templatePackageJson;
}