create-mastra 0.10.13-alpha.1 → 0.10.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +112 -17
- package/dist/index.js.map +1 -1
- package/dist/templates/dev.entry.js +7 -2
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1216,10 +1216,10 @@ var exec = util.promisify(child_process.exec);
|
|
|
1216
1216
|
async function cloneTemplate(options) {
|
|
1217
1217
|
const { template, projectName, targetDir } = options;
|
|
1218
1218
|
const projectPath = targetDir ? path3.resolve(targetDir, projectName) : path3.resolve(projectName);
|
|
1219
|
-
const
|
|
1219
|
+
const spinner5 = yoctoSpinner({ text: `Cloning template "${template.title}"...` }).start();
|
|
1220
1220
|
try {
|
|
1221
1221
|
if (await directoryExists(projectPath)) {
|
|
1222
|
-
|
|
1222
|
+
spinner5.error(`Directory ${projectName} already exists`);
|
|
1223
1223
|
throw new Error(`Directory ${projectName} already exists`);
|
|
1224
1224
|
}
|
|
1225
1225
|
await cloneRepositoryWithoutGit(template.githubUrl, projectPath);
|
|
@@ -1228,10 +1228,10 @@ async function cloneTemplate(options) {
|
|
|
1228
1228
|
if (await fileExists(envExamplePath)) {
|
|
1229
1229
|
await fs.copyFile(envExamplePath, path3.join(projectPath, ".env"));
|
|
1230
1230
|
}
|
|
1231
|
-
|
|
1231
|
+
spinner5.success(`Template "${template.title}" cloned successfully to ${projectName}`);
|
|
1232
1232
|
return projectPath;
|
|
1233
1233
|
} catch (error) {
|
|
1234
|
-
|
|
1234
|
+
spinner5.error(`Failed to clone template: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
1235
1235
|
throw error;
|
|
1236
1236
|
}
|
|
1237
1237
|
}
|
|
@@ -1286,16 +1286,16 @@ async function updatePackageJson(projectPath, projectName) {
|
|
|
1286
1286
|
}
|
|
1287
1287
|
}
|
|
1288
1288
|
async function installDependencies(projectPath, packageManager) {
|
|
1289
|
-
const
|
|
1289
|
+
const spinner5 = yoctoSpinner({ text: "Installing dependencies..." }).start();
|
|
1290
1290
|
try {
|
|
1291
1291
|
const pm = packageManager || getPackageManager();
|
|
1292
1292
|
const installCommand = shellQuote.quote([pm, "install"]);
|
|
1293
1293
|
await exec(installCommand, {
|
|
1294
1294
|
cwd: projectPath
|
|
1295
1295
|
});
|
|
1296
|
-
|
|
1296
|
+
spinner5.success("Dependencies installed successfully");
|
|
1297
1297
|
} catch (error) {
|
|
1298
|
-
|
|
1298
|
+
spinner5.error(`Failed to install dependencies: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
1299
1299
|
throw error;
|
|
1300
1300
|
}
|
|
1301
1301
|
}
|
|
@@ -2474,21 +2474,116 @@ var postCreate = ({ projectName }) => {
|
|
|
2474
2474
|
${color2.cyan(`${packageManager} run dev`)}
|
|
2475
2475
|
`);
|
|
2476
2476
|
};
|
|
2477
|
+
function isGitHubUrl(url) {
|
|
2478
|
+
try {
|
|
2479
|
+
const parsedUrl = new URL(url);
|
|
2480
|
+
return parsedUrl.hostname === "github.com" && parsedUrl.pathname.split("/").length >= 3;
|
|
2481
|
+
} catch {
|
|
2482
|
+
return false;
|
|
2483
|
+
}
|
|
2484
|
+
}
|
|
2485
|
+
async function validateGitHubProject(githubUrl) {
|
|
2486
|
+
const errors = [];
|
|
2487
|
+
try {
|
|
2488
|
+
const urlParts = new URL(githubUrl).pathname.split("/").filter(Boolean);
|
|
2489
|
+
const owner = urlParts[0];
|
|
2490
|
+
const repo = urlParts[1]?.replace(".git", "");
|
|
2491
|
+
if (!owner || !repo) {
|
|
2492
|
+
throw new Error("Invalid GitHub URL format");
|
|
2493
|
+
}
|
|
2494
|
+
const branches = ["main", "master"];
|
|
2495
|
+
let packageJsonContent = null;
|
|
2496
|
+
let indexContent = null;
|
|
2497
|
+
for (const branch of branches) {
|
|
2498
|
+
try {
|
|
2499
|
+
const packageJsonUrl = `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/package.json`;
|
|
2500
|
+
const packageJsonResponse = await fetch(packageJsonUrl);
|
|
2501
|
+
if (packageJsonResponse.ok) {
|
|
2502
|
+
packageJsonContent = await packageJsonResponse.text();
|
|
2503
|
+
const indexUrl = `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/src/mastra/index.ts`;
|
|
2504
|
+
const indexResponse = await fetch(indexUrl);
|
|
2505
|
+
if (indexResponse.ok) {
|
|
2506
|
+
indexContent = await indexResponse.text();
|
|
2507
|
+
}
|
|
2508
|
+
break;
|
|
2509
|
+
}
|
|
2510
|
+
} catch {
|
|
2511
|
+
}
|
|
2512
|
+
}
|
|
2513
|
+
if (!packageJsonContent) {
|
|
2514
|
+
errors.push("Could not fetch package.json from repository");
|
|
2515
|
+
return { isValid: false, errors };
|
|
2516
|
+
}
|
|
2517
|
+
try {
|
|
2518
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
2519
|
+
const hasMastraCore = packageJson.dependencies?.["@mastra/core"] || packageJson.devDependencies?.["@mastra/core"] || packageJson.peerDependencies?.["@mastra/core"];
|
|
2520
|
+
if (!hasMastraCore) {
|
|
2521
|
+
errors.push("Missing @mastra/core dependency in package.json");
|
|
2522
|
+
}
|
|
2523
|
+
} catch {
|
|
2524
|
+
errors.push("Invalid package.json format");
|
|
2525
|
+
}
|
|
2526
|
+
if (!indexContent) {
|
|
2527
|
+
errors.push("Missing src/mastra/index.ts file");
|
|
2528
|
+
} else {
|
|
2529
|
+
const hasMastraExport = indexContent.includes("export") && (indexContent.includes("new Mastra") || indexContent.includes("Mastra("));
|
|
2530
|
+
if (!hasMastraExport) {
|
|
2531
|
+
errors.push("src/mastra/index.ts does not export a Mastra instance");
|
|
2532
|
+
}
|
|
2533
|
+
}
|
|
2534
|
+
return { isValid: errors.length === 0, errors };
|
|
2535
|
+
} catch (error) {
|
|
2536
|
+
errors.push(`Failed to validate GitHub repository: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2537
|
+
return { isValid: false, errors };
|
|
2538
|
+
}
|
|
2539
|
+
}
|
|
2540
|
+
async function createFromGitHubUrl(url) {
|
|
2541
|
+
const urlParts = new URL(url).pathname.split("/").filter(Boolean);
|
|
2542
|
+
const owner = urlParts[0] || "unknown";
|
|
2543
|
+
const repo = urlParts[1] || "unknown";
|
|
2544
|
+
return {
|
|
2545
|
+
githubUrl: url,
|
|
2546
|
+
title: `${owner}/${repo}`,
|
|
2547
|
+
slug: repo,
|
|
2548
|
+
agents: [],
|
|
2549
|
+
mcp: [],
|
|
2550
|
+
tools: [],
|
|
2551
|
+
networks: [],
|
|
2552
|
+
workflows: []
|
|
2553
|
+
};
|
|
2554
|
+
}
|
|
2477
2555
|
async function createFromTemplate(args2) {
|
|
2478
|
-
const templates = await loadTemplates();
|
|
2479
2556
|
let selectedTemplate;
|
|
2480
2557
|
if (args2.template === true) {
|
|
2481
|
-
|
|
2482
|
-
|
|
2558
|
+
const templates = await loadTemplates();
|
|
2559
|
+
const selected = await selectTemplate(templates);
|
|
2560
|
+
if (!selected) {
|
|
2483
2561
|
M.info("No template selected. Exiting.");
|
|
2484
2562
|
return;
|
|
2485
2563
|
}
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
if (
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2564
|
+
selectedTemplate = selected;
|
|
2565
|
+
} else if (args2.template && typeof args2.template === "string") {
|
|
2566
|
+
if (isGitHubUrl(args2.template)) {
|
|
2567
|
+
const spinner5 = Y();
|
|
2568
|
+
spinner5.start("Validating GitHub repository...");
|
|
2569
|
+
const validation = await validateGitHubProject(args2.template);
|
|
2570
|
+
if (!validation.isValid) {
|
|
2571
|
+
spinner5.stop("Validation failed");
|
|
2572
|
+
M.error("This does not appear to be a valid Mastra project:");
|
|
2573
|
+
validation.errors.forEach((error) => M.error(` - ${error}`));
|
|
2574
|
+
throw new Error("Invalid Mastra project");
|
|
2575
|
+
}
|
|
2576
|
+
spinner5.stop("Valid Mastra project \u2713");
|
|
2577
|
+
selectedTemplate = await createFromGitHubUrl(args2.template);
|
|
2578
|
+
} else {
|
|
2579
|
+
const templates = await loadTemplates();
|
|
2580
|
+
const found = findTemplateByName(templates, args2.template);
|
|
2581
|
+
if (!found) {
|
|
2582
|
+
M.error(`Template "${args2.template}" not found. Available templates:`);
|
|
2583
|
+
templates.forEach((t) => M.info(` - ${t.title} (use: ${t.slug.replace("template-", "")})`));
|
|
2584
|
+
throw new Error(`Template "${args2.template}" not found`);
|
|
2585
|
+
}
|
|
2586
|
+
selectedTemplate = found;
|
|
2492
2587
|
}
|
|
2493
2588
|
}
|
|
2494
2589
|
if (!selectedTemplate) {
|
|
@@ -2572,7 +2667,7 @@ program.name("create-mastra").description("Create a new Mastra project").argumen
|
|
|
2572
2667
|
"Project name that will be used in package.json and as the project directory name."
|
|
2573
2668
|
).option("--default", "Quick start with defaults(src, OpenAI, examples)").option("-c, --components <components>", "Comma-separated list of components (agents, tools, workflows)").option("-l, --llm <model-provider>", "Default model provider (openai, anthropic, groq, google, or cerebras)").option("-k, --llm-api-key <api-key>", "API key for the model provider").option("-e, --example", "Include example code").option("-n, --no-example", "Do not include example code").option("-t, --timeout [timeout]", "Configurable timeout for package installation, defaults to 60000 ms").option("-d, --dir <directory>", "Target directory for Mastra source code (default: src/)").option("-m, --mcp <mcp>", "MCP Server for code editor (cursor, cursor-global, windsurf, vscode)").option(
|
|
2574
2669
|
"--template [template-name]",
|
|
2575
|
-
"Create project from a template (use template name or leave blank to select from list)"
|
|
2670
|
+
"Create project from a template (use template name, public GitHub URL, or leave blank to select from list)"
|
|
2576
2671
|
).action(async (projectNameArg, args) => {
|
|
2577
2672
|
const projectName = projectNameArg || args.projectName;
|
|
2578
2673
|
const timeout = args?.timeout ? args?.timeout === true ? 6e4 : parseInt(args?.timeout, 10) : void 0;
|