128 lines
3.8 KiB
TypeScript
128 lines
3.8 KiB
TypeScript
const fs = require("fs");
|
|
const path = require("path");
|
|
let isInWatchMode = false;
|
|
if (process.argv[2] === "--watch") {
|
|
isInWatchMode = true;
|
|
}
|
|
const chokidar = require("chokidar");
|
|
const { debounce } = require("lodash");
|
|
const APP_STORE_PATH = path.join(__dirname, "..", "..", "app-store");
|
|
function getAppName(candidatePath) {
|
|
function isValidAppName(candidatePath) {
|
|
if (!candidatePath.startsWith("_") && !candidatePath.includes("/") && !candidatePath.includes("\\")) {
|
|
return candidatePath;
|
|
}
|
|
}
|
|
|
|
if (isValidAppName(candidatePath)) {
|
|
// Already a dirname of an app
|
|
return candidatePath;
|
|
}
|
|
// Get dirname of app from full path
|
|
const dirName = path.relative(APP_STORE_PATH, candidatePath);
|
|
return isValidAppName(dirName) ? dirName : null;
|
|
}
|
|
|
|
function generateFiles() {
|
|
const browserOutput = [`import dynamic from "next/dynamic"`];
|
|
const serverOutput = [];
|
|
const appDirs = [];
|
|
|
|
fs.readdirSync(`${APP_STORE_PATH}`).forEach(function (dir) {
|
|
if (fs.statSync(`${APP_STORE_PATH}/${dir}`).isDirectory()) {
|
|
if (!getAppName(dir)) {
|
|
return;
|
|
}
|
|
appDirs.push(dir);
|
|
}
|
|
});
|
|
|
|
function forEachAppDir(callback) {
|
|
for (let i = 0; i < appDirs.length; i++) {
|
|
callback(appDirs[i]);
|
|
}
|
|
}
|
|
|
|
function getObjectExporter(objectName, { fileToBeImported, importBuilder, entryBuilder }) {
|
|
const output = [];
|
|
forEachAppDir((appName) => {
|
|
if (fs.existsSync(path.join(APP_STORE_PATH, appName, fileToBeImported))) {
|
|
output.push(importBuilder(appName));
|
|
}
|
|
});
|
|
|
|
output.push(`export const ${objectName} = {`);
|
|
|
|
forEachAppDir((dirName) => {
|
|
if (fs.existsSync(path.join(APP_STORE_PATH, dirName, fileToBeImported))) {
|
|
output.push(entryBuilder(dirName));
|
|
}
|
|
});
|
|
|
|
output.push(`};`);
|
|
return output;
|
|
}
|
|
|
|
serverOutput.push(
|
|
...getObjectExporter("apiHandlers", {
|
|
fileToBeImported: "api/index.ts",
|
|
importBuilder: (appName) => `const ${appName}_api = import("./${appName}/api");`,
|
|
entryBuilder: (appName) => `${appName}:${appName}_api,`,
|
|
})
|
|
);
|
|
|
|
browserOutput.push(
|
|
...getObjectExporter("appStoreMetadata", {
|
|
fileToBeImported: "_metadata.ts",
|
|
importBuilder: (appName) => `import { metadata as ${appName}_meta } from "./${appName}/_metadata";`,
|
|
entryBuilder: (appName) => `${appName}:${appName}_meta,`,
|
|
})
|
|
);
|
|
|
|
browserOutput.push(
|
|
...getObjectExporter("InstallAppButtonMap", {
|
|
fileToBeImported: "components/InstallAppButton.tsx",
|
|
importBuilder: (appName) =>
|
|
`const ${appName}_installAppButton = dynamic(() =>import("./${appName}/components/InstallAppButton"));`,
|
|
entryBuilder: (appName) => `${appName}:${appName}_installAppButton,`,
|
|
})
|
|
);
|
|
const banner = `/**
|
|
This file is autogenerated using the command \`yarn app-store:build --watch\`.
|
|
Don't modify this file manually.
|
|
**/
|
|
`;
|
|
fs.writeFileSync(`${APP_STORE_PATH}/apps.server.generated.ts`, `${banner}${serverOutput.join("\n")}`);
|
|
fs.writeFileSync(`${APP_STORE_PATH}/apps.browser.generated.tsx`, `${banner}${browserOutput.join("\n")}`);
|
|
console.log("Generated `apps.server.generated.ts` and `apps.browser.generated.tsx`");
|
|
}
|
|
|
|
const debouncedGenerateFiles = debounce(generateFiles);
|
|
|
|
if (isInWatchMode) {
|
|
chokidar
|
|
.watch(APP_STORE_PATH)
|
|
.on("addDir", (dirPath) => {
|
|
const appName = getAppName(dirPath);
|
|
if (appName) {
|
|
console.log(`Added ${appName}`);
|
|
debouncedGenerateFiles();
|
|
}
|
|
})
|
|
.on("change", (filePath) => {
|
|
if (filePath.endsWith("config.json")) {
|
|
console.log("Config file changed");
|
|
debouncedGenerateFiles();
|
|
}
|
|
})
|
|
.on("unlinkDir", (dirPath) => {
|
|
const appName = getAppName(dirPath);
|
|
if (appName) {
|
|
console.log(`Removed ${appName}`);
|
|
debouncedGenerateFiles();
|
|
}
|
|
});
|
|
} else {
|
|
generateFiles();
|
|
}
|