@microfox/cli
Version:
Universal CLI tool for creating modern TypeScript packages with npm availability checking
312 lines (308 loc) • 13.7 kB
JavaScript
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/commands/kickstart.ts
var kickstart_exports = {};
__export(kickstart_exports, {
kickstartCommand: () => kickstartCommand
});
module.exports = __toCommonJS(kickstart_exports);
var import_fs = __toESM(require("fs"));
var import_path = __toESM(require("path"));
var import_chalk = __toESM(require("chalk"));
var import_readline_sync = __toESM(require("readline-sync"));
var import_inquirer = __toESM(require("inquirer"));
// src/utils/getProjectRoot.ts
var getWorkingDirectory = () => {
return process.cwd();
};
// src/utils/npmChecker.ts
async function isPackageNameAvailable(packageName) {
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5e3);
const response = await fetch(`https://registry.npmjs.org/${packageName}`, {
signal: controller.signal
});
clearTimeout(timeoutId);
if (response.ok) {
return false;
}
if (response.status === 404) {
return true;
}
console.warn(
`Warning: Unexpected status ${response.status} when checking npm availability for ${packageName}. Proceeding with caution.`
);
return false;
} catch (error) {
if (error.name === "AbortError") {
console.warn(
`Warning: Timeout when checking npm availability for ${packageName}. Proceeding with caution.`
);
} else {
console.warn(
`Warning: Could not check npm availability for ${packageName}. Proceeding with caution.`
);
}
return false;
}
}
async function checkPackageNameAndPrompt(packageName) {
const readlineSync2 = require("readline-sync");
let currentName = (packageName == null ? void 0 : packageName.startsWith("@microfox/")) ? packageName : `@microfox/${packageName}`;
while (true) {
console.log(`\u{1F50D} Checking npm availability for "${currentName}"...`);
const isAvailable = await isPackageNameAvailable(currentName);
if (isAvailable) {
console.log(`\u2705 Package name "${currentName}" is available on npm!`);
return currentName;
} else {
console.log(`\u274C Package name "${currentName}" is already taken on npm.`);
const newName = readlineSync2.question(
"Please enter a new package name: "
);
if (!newName || newName.trim() === "") {
console.log("\u274C Invalid package name. Please try again.");
continue;
}
currentName = newName.trim();
}
}
}
// src/commands/kickstart.ts
async function createAgentProject(agentName) {
const workingDir = getWorkingDirectory();
const agentDir = import_path.default.join(workingDir, agentName);
if (import_fs.default.existsSync(agentDir)) {
throw new Error(`Directory already exists at ${agentDir}`);
}
console.log(
import_chalk.default.blue(
`\u{1F680} Creating agent ${import_chalk.default.bold(agentName)} at ${agentDir}
`
)
);
import_fs.default.mkdirSync(agentDir, { recursive: true });
const templatePath = import_path.default.resolve(__dirname, "agent-template.txt");
const templateContent = import_fs.default.readFileSync(templatePath, "utf-8");
const fileSections = templateContent.split("--- filename: ").slice(1);
for (const section of fileSections) {
const lines = section.split("\n");
const filePath = lines.shift().trim();
const content = lines.join("\n").replace(/<%= agentName %>/g, agentName);
const destPath = import_path.default.join(agentDir, filePath);
const destDir = import_path.default.dirname(destPath);
if (!import_fs.default.existsSync(destDir)) {
import_fs.default.mkdirSync(destDir, { recursive: true });
}
import_fs.default.writeFileSync(destPath, content);
console.log(import_chalk.default.green(`\u2705 Created ${filePath}`));
}
}
async function createPackageProject(packageName) {
const simpleName = packageName.includes("/") ? packageName.split("/")[1] : packageName;
const titleName = simpleName.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
const description = `A TypeScript SDK for ${titleName}.`;
const className = simpleName.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("") + "Sdk";
const workingDir = getWorkingDirectory();
const packageDir = import_path.default.join(workingDir, simpleName);
if (import_fs.default.existsSync(packageDir)) {
throw new Error(`Directory already exists at ${packageDir}`);
}
console.log(
import_chalk.default.blue(
`\u{1F680} Creating package ${import_chalk.default.bold(packageName)} at ${packageDir}
`
)
);
import_fs.default.mkdirSync(packageDir, { recursive: true });
const templatePath = import_path.default.resolve(__dirname, "package-template.txt");
const templateContent = import_fs.default.readFileSync(templatePath, "utf-8");
const fileSections = templateContent.split("--- filename: ").slice(1);
for (const section of fileSections) {
const lines = section.split("\n");
const filePath = lines.shift().trim().replace(/<%= simpleName %>/g, simpleName);
let content = lines.join("\n");
content = content.replace(/<%= packageName %>/g, packageName);
content = content.replace(/<%= simpleName %>/g, simpleName);
content = content.replace(/<%= titleName %>/g, titleName);
content = content.replace(/<%= description %>/g, description);
content = content.replace(/<%= className %>/g, className);
const destPath = import_path.default.join(packageDir, filePath);
const destDir = import_path.default.dirname(destPath);
if (!import_fs.default.existsSync(destDir)) {
import_fs.default.mkdirSync(destDir, { recursive: true });
}
import_fs.default.writeFileSync(destPath, content);
console.log(import_chalk.default.green(`\u2705 Created ${filePath}`));
}
const docsDir = import_path.default.join(packageDir, "docs");
const docsConstructors = import_path.default.join(docsDir, "constructors");
const docsFunctions = import_path.default.join(docsDir, "functions");
import_fs.default.mkdirSync(docsDir, { recursive: true });
import_fs.default.mkdirSync(docsConstructors, { recursive: true });
import_fs.default.mkdirSync(docsFunctions, { recursive: true });
}
async function createBackgroundAgentProject(agentName) {
const workingDir = getWorkingDirectory();
const agentDir = import_path.default.join(workingDir, agentName);
if (import_fs.default.existsSync(agentDir)) {
throw new Error(`Directory already exists at ${agentDir}`);
}
console.log(
import_chalk.default.blue(
`\u{1F680} Creating background agent ${import_chalk.default.bold(agentName)} at ${agentDir}
`
)
);
import_fs.default.mkdirSync(agentDir, { recursive: true });
const templateDir = import_path.default.resolve(__dirname, "background-agent");
const copyTemplates = (src, dest) => {
const entries = import_fs.default.readdirSync(src, { withFileTypes: true });
for (const entry of entries) {
const srcPath = import_path.default.join(src, entry.name);
const destPath = import_path.default.join(dest, entry.name.replace(/\.txt$/, ""));
if (entry.isDirectory()) {
import_fs.default.mkdirSync(destPath, { recursive: true });
copyTemplates(srcPath, destPath);
} else if (entry.name.endsWith(".txt")) {
const templateContent = import_fs.default.readFileSync(srcPath, "utf-8");
const content = templateContent.replace(/<%= agentName %>/g, agentName);
import_fs.default.writeFileSync(destPath, content);
console.log(import_chalk.default.green(`\u2705 Created ${import_path.default.relative(agentDir, destPath)}`));
}
}
};
copyTemplates(templateDir, agentDir);
}
async function kickstartCommand() {
console.log(import_chalk.default.cyan("\u{1F680} Let's kickstart your new project!\n"));
const { boilerplateType } = await import_inquirer.default.prompt([
{
type: "list",
name: "boilerplateType",
message: "Select boilerplate type:",
choices: ["package", "agent"]
}
]);
if (!boilerplateType) {
console.log(import_chalk.default.yellow("Operation cancelled."));
return;
}
if (boilerplateType === "agent") {
const { agentType } = await import_inquirer.default.prompt([
{
type: "list",
name: "agentType",
message: "Select agent type:",
choices: ["plain", "background"]
}
]);
if (agentType === "plain") {
const agentName = import_readline_sync.default.question(
import_chalk.default.yellow("\u{1F4E6} Enter agent name: ")
);
if (!agentName.trim()) {
throw new Error("Agent name cannot be empty");
}
await createAgentProject(agentName.trim());
console.log(
import_chalk.default.green(
`
\u{1F389} Successfully created agent ${import_chalk.default.bold(agentName)}!`
)
);
console.log(import_chalk.default.gray(`\u{1F4CD} Located at ${import_path.default.join(getWorkingDirectory(), agentName)}`));
console.log(import_chalk.default.yellow("\n\u{1F4A1} Next steps:"));
console.log(import_chalk.default.yellow(` 1. cd ${agentName}`));
console.log(import_chalk.default.yellow(" 2. npm install"));
console.log(import_chalk.default.yellow(" 3. Configure your env.json"));
console.log(import_chalk.default.yellow(" 4. npm run dev"));
console.log(import_chalk.default.yellow(" 5. Start developing your agent!"));
} else if (agentType === "background") {
const agentName = import_readline_sync.default.question(
import_chalk.default.yellow("\u{1F4E6} Enter agent name: ")
);
if (!agentName.trim()) {
throw new Error("Agent name cannot be empty");
}
await createBackgroundAgentProject(agentName.trim());
console.log(
import_chalk.default.green(
`
\u{1F389} Successfully created background agent ${import_chalk.default.bold(agentName)}!`
)
);
console.log(import_chalk.default.gray(`\u{1F4CD} Located at ${import_path.default.join(getWorkingDirectory(), agentName)}`));
console.log(import_chalk.default.yellow("\n\u{1F4A1} Next steps:"));
console.log(import_chalk.default.yellow(` 1. cd ${agentName}`));
console.log(import_chalk.default.yellow(" 2. npm install"));
console.log(import_chalk.default.yellow(" 3. Configure your env.json"));
console.log(import_chalk.default.yellow(" 4. npm run dev"));
console.log(import_chalk.default.yellow(" 5. Start developing your agent!"));
}
} else if (boilerplateType === "package") {
const packageName = import_readline_sync.default.question(
import_chalk.default.yellow("\u{1F4E6} Enter package name: ")
);
if (!packageName.trim()) {
throw new Error("Package name cannot be empty");
}
const finalPackageName = await checkPackageNameAndPrompt(`@microfox/${packageName.trim()}`);
await createPackageProject(finalPackageName);
const simpleName = finalPackageName.includes("/") ? finalPackageName.split("/")[1] : finalPackageName;
console.log(
import_chalk.default.green(
`
\u{1F389} Successfully created package ${import_chalk.default.bold(finalPackageName)}!`
)
);
console.log(import_chalk.default.gray(`\u{1F4CD} Located at ${import_path.default.join(getWorkingDirectory(), simpleName)}`));
console.log(import_chalk.default.yellow("\n\u{1F4A1} Next steps:"));
console.log(import_chalk.default.yellow(` 1. cd ${simpleName}`));
console.log(import_chalk.default.yellow(" 2. npm install"));
console.log(import_chalk.default.yellow(" 3. npm run build"));
console.log(import_chalk.default.yellow(" 4. npm test"));
console.log(import_chalk.default.yellow(" 5. Start developing your SDK!"));
console.log(
import_chalk.default.gray(
`
\u{1F4DA} Your package is ready to be published to npm as "${finalPackageName}"`
)
);
} else {
console.log(import_chalk.default.red('Invalid boilerplate type selected. Please choose "package" or "agent".'));
}
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
kickstartCommand
});
//# sourceMappingURL=kickstart.js.map