@proofkit/typegen
Version:
`@proofkit/typegen` is a tool for generating TypeScript types from FileMaker database schemas, making it easier to work with FileMaker data in modern TypeScript projects.
191 lines (190 loc) • 5.66 kB
JavaScript
import { program } from "@commander-js/extra-typings";
import chalk from "chalk";
import fs from "fs-extra";
import path from "path";
import { confirm } from "@clack/prompts";
import { parse } from "jsonc-parser";
import { config } from "dotenv";
import { fileURLToPath } from "url";
import { typegenConfig } from "./types.js";
import { generateTypedClients } from "./typegen.js";
const defaultConfigPaths = [
"proofkit-typegen.config.jsonc",
"proofkit-typegen.config.json"
];
const oldConfigPaths = ["fmschema.config.mjs", "fmschema.config.js"];
function init({ configLocation }) {
console.log();
if (fs.existsSync(configLocation)) {
console.log(
chalk.yellow(`⚠️ ${path.basename(configLocation)} already exists`)
);
} else {
const stubFile = fs.readFileSync(
path.resolve(
typeof __dirname !== "undefined" ? __dirname : path.dirname(fileURLToPath(import.meta.url)),
"../../stubs/proofkit-typegen.config.jsonc"
),
"utf8"
);
fs.writeFileSync(configLocation, stubFile, "utf8");
console.log(`✅ Created config file: ${path.basename(configLocation)}`);
}
}
async function runCodegen({
configLocation,
resetOverrides = false
}) {
if (!fs.existsSync(configLocation)) {
let hasOldConfig = false;
for (const oldConfigPath of oldConfigPaths) {
if (fs.existsSync(oldConfigPath)) {
hasOldConfig = true;
break;
}
}
if (hasOldConfig) {
console.log(
chalk.yellow(
"⚠️ You have an old config file from the @proofgeist/fmdapi package. Please upgrade to @proofkit/typegen by running `npx @proofgeist/fmdapi@latest upgrade`"
)
);
process.exit(1);
} else {
console.error(
chalk.red(
`Could not find ${path.basename(
configLocation
)} at the root of your project.`
)
);
console.log();
const runInitNow = await confirm({
message: "Would you like to initialize a new config file?",
initialValue: true,
active: "Yes",
inactive: "No"
});
if (runInitNow) {
init({ configLocation });
process.exit(0);
}
process.exit(1);
}
}
await fs.access(configLocation, fs.constants.R_OK).catch(() => {
console.error(
chalk.red(
`You do not have read access to ${path.basename(
configLocation
)} at the root of your project.`
)
);
return process.exit(1);
});
console.log(`🔍 Reading config from ${configLocation}`);
const configRaw = fs.readFileSync(configLocation, "utf8");
const configParsed = typegenConfig.safeParse(parse(configRaw));
if (!configParsed.success) {
console.error(
chalk.red(
`Error reading the config object from ${path.basename(
configLocation
)}.`
)
);
console.error(configParsed.error);
return process.exit(1);
}
const result = await generateTypedClients(configParsed.data.config, {
resetOverrides
}).catch((err) => {
console.error(err);
return process.exit(1);
});
if (result) {
if (result.totalCount === 0) ;
else if (result.totalCount === result.successCount) {
console.log(
`✅ Generated ${result.successCount} layout${result.successCount === 1 ? "" : "s"}`
);
} else if (result.errorCount === result.totalCount) {
console.log(`❌ Failed to generate any layouts`);
} else {
console.log(
`⚠️ Generated ${result.successCount} of ${result.totalCount} layouts`
);
}
}
}
program.command("generate", { isDefault: true }).option("--config <filename>", "optional config file name").option("--env-path <path>", "optional path to your .env file").option(
"--reset-overrides",
"Recreate the overrides file(s), even if they already exist. Most useful when upgrading from @proofgeist/fmdapi",
false
).option(
"--skip-env-check",
"Ignore loading environment variables from a file.",
false
).action(async (options) => {
const configPath = getConfigPath(options.config);
const configLocation = path.toNamespacedPath(
path.resolve(configPath ?? defaultConfigPaths[0] ?? "")
);
if (!options.skipEnvCheck) {
parseEnvs(options.envPath);
}
await runCodegen({
configLocation,
resetOverrides: options.resetOverrides
});
});
program.command("init").option("--config <filename>", "optional config file name").action(async (options) => {
const configLocation = path.toNamespacedPath(
path.resolve(options.config ?? defaultConfigPaths[0] ?? "")
);
console.log(configLocation);
init({ configLocation });
});
program.parse();
function parseEnvs(envPath) {
let actualEnvPath = envPath;
if (!actualEnvPath || !fs.existsSync(actualEnvPath)) {
const possiblePaths = [".env.local", ".env"];
for (const path2 of possiblePaths) {
if (fs.existsSync(path2)) {
actualEnvPath = path2;
break;
}
}
}
const envRes = config({ path: actualEnvPath });
if (envRes.error) {
console.log(
chalk.red(
`Could not resolve your environment variables.
${envRes.error.message}
`
)
);
throw new Error("Could not resolve your environment variables.");
}
}
function getConfigPath(configPath) {
if (configPath) {
try {
fs.accessSync(configPath, fs.constants.F_OK);
return configPath;
} catch (e) {
}
}
for (const path2 of defaultConfigPaths) {
try {
fs.accessSync(path2, fs.constants.F_OK);
return path2;
} catch (e) {
}
}
return null;
}
//# sourceMappingURL=cli.js.map