create-mastra 0.10.12-alpha.0 → 0.10.12-alpha.2
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 +343 -110
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#! /usr/bin/env node
|
|
2
2
|
import { Command } from 'commander';
|
|
3
3
|
import { randomUUID } from 'node:crypto';
|
|
4
|
-
import * as
|
|
5
|
-
import
|
|
4
|
+
import * as fs4__default from 'node:fs';
|
|
5
|
+
import fs4__default__default, { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
6
6
|
import os from 'node:os';
|
|
7
|
-
import
|
|
7
|
+
import path3, { dirname } from 'node:path';
|
|
8
8
|
import { fileURLToPath } from 'node:url';
|
|
9
9
|
import { PostHog } from 'posthog-node';
|
|
10
10
|
import util, { stripVTControlCharacters } from 'node:util';
|
|
@@ -12,18 +12,22 @@ import y$1, { stdout, stdin } from 'node:process';
|
|
|
12
12
|
import * as g from 'node:readline';
|
|
13
13
|
import g__default from 'node:readline';
|
|
14
14
|
import { Writable } from 'node:stream';
|
|
15
|
+
import fs from 'node:fs/promises';
|
|
15
16
|
import child_process from 'node:child_process';
|
|
16
|
-
import fs4 from 'node:fs/promises';
|
|
17
|
-
import { execa } from 'execa';
|
|
18
|
-
import fsExtra3, { readJSON, ensureFile, writeJSON } from 'fs-extra/esm';
|
|
19
|
-
import prettier from 'prettier';
|
|
20
17
|
import tty from 'node:tty';
|
|
21
18
|
import pino from 'pino';
|
|
22
19
|
import pretty from 'pino-pretty';
|
|
20
|
+
import { execa } from 'execa';
|
|
21
|
+
import fsExtra3, { readJSON, ensureFile, writeJSON } from 'fs-extra/esm';
|
|
22
|
+
import prettier from 'prettier';
|
|
23
23
|
import fsExtra from 'fs-extra';
|
|
24
24
|
|
|
25
25
|
var __filename = fileURLToPath(import.meta.url);
|
|
26
|
-
var __dirname =
|
|
26
|
+
var __dirname = path3.dirname(__filename);
|
|
27
|
+
var analyticsInstance = null;
|
|
28
|
+
function getAnalytics() {
|
|
29
|
+
return analyticsInstance;
|
|
30
|
+
}
|
|
27
31
|
var PosthogAnalytics = class {
|
|
28
32
|
sessionId;
|
|
29
33
|
client;
|
|
@@ -35,7 +39,7 @@ var PosthogAnalytics = class {
|
|
|
35
39
|
host = "https://app.posthog.com"
|
|
36
40
|
}) {
|
|
37
41
|
this.version = version;
|
|
38
|
-
const cliConfigPath =
|
|
42
|
+
const cliConfigPath = path3.join(__dirname, "mastra-cli.json");
|
|
39
43
|
if (existsSync(cliConfigPath)) {
|
|
40
44
|
try {
|
|
41
45
|
const { distinctId, sessionId } = JSON.parse(readFileSync(cliConfigPath, "utf-8"));
|
|
@@ -63,7 +67,7 @@ var PosthogAnalytics = class {
|
|
|
63
67
|
}
|
|
64
68
|
writeCliConfig({ distinctId, sessionId }) {
|
|
65
69
|
try {
|
|
66
|
-
writeFileSync(
|
|
70
|
+
writeFileSync(path3.join(__dirname, "mastra-cli.json"), JSON.stringify({ distinctId, sessionId }));
|
|
67
71
|
} catch {
|
|
68
72
|
}
|
|
69
73
|
}
|
|
@@ -113,6 +117,22 @@ var PosthogAnalytics = class {
|
|
|
113
117
|
}
|
|
114
118
|
});
|
|
115
119
|
}
|
|
120
|
+
trackEvent(eventName, properties) {
|
|
121
|
+
try {
|
|
122
|
+
if (!this.client) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
this.client.capture({
|
|
126
|
+
distinctId: this.distinctId,
|
|
127
|
+
event: eventName,
|
|
128
|
+
properties: {
|
|
129
|
+
...this.getSystemProperties(),
|
|
130
|
+
...properties
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
} catch {
|
|
134
|
+
}
|
|
135
|
+
}
|
|
116
136
|
trackCommand(options) {
|
|
117
137
|
try {
|
|
118
138
|
if (!this.client) {
|
|
@@ -1153,6 +1173,195 @@ var PinoLogger = class extends MastraLogger {
|
|
|
1153
1173
|
}
|
|
1154
1174
|
};
|
|
1155
1175
|
|
|
1176
|
+
function getPackageManager() {
|
|
1177
|
+
const userAgent = process.env.npm_config_user_agent || "";
|
|
1178
|
+
const execPath = process.env.npm_execpath || "";
|
|
1179
|
+
if (userAgent.includes("yarn")) {
|
|
1180
|
+
return "yarn";
|
|
1181
|
+
}
|
|
1182
|
+
if (userAgent.includes("pnpm")) {
|
|
1183
|
+
return "pnpm";
|
|
1184
|
+
}
|
|
1185
|
+
if (userAgent.includes("npm")) {
|
|
1186
|
+
return "npm";
|
|
1187
|
+
}
|
|
1188
|
+
if (execPath.includes("yarn")) {
|
|
1189
|
+
return "yarn";
|
|
1190
|
+
}
|
|
1191
|
+
if (execPath.includes("pnpm")) {
|
|
1192
|
+
return "pnpm";
|
|
1193
|
+
}
|
|
1194
|
+
if (execPath.includes("npm")) {
|
|
1195
|
+
return "npm";
|
|
1196
|
+
}
|
|
1197
|
+
return "npm";
|
|
1198
|
+
}
|
|
1199
|
+
function getPackageManagerInstallCommand(pm) {
|
|
1200
|
+
switch (pm) {
|
|
1201
|
+
case "npm":
|
|
1202
|
+
return "install";
|
|
1203
|
+
case "yarn":
|
|
1204
|
+
return "add";
|
|
1205
|
+
case "pnpm":
|
|
1206
|
+
return "add";
|
|
1207
|
+
default:
|
|
1208
|
+
return "install";
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
var logger = new PinoLogger({
|
|
1212
|
+
name: "Mastra CLI",
|
|
1213
|
+
level: "info"
|
|
1214
|
+
});
|
|
1215
|
+
var exec = util.promisify(child_process.exec);
|
|
1216
|
+
async function cloneTemplate(options) {
|
|
1217
|
+
const { template, projectName, targetDir } = options;
|
|
1218
|
+
const projectPath = targetDir ? path3.resolve(targetDir, projectName) : path3.resolve(projectName);
|
|
1219
|
+
const spinner4 = yoctoSpinner({ text: `Cloning template "${template.title}"...` }).start();
|
|
1220
|
+
try {
|
|
1221
|
+
if (await directoryExists(projectPath)) {
|
|
1222
|
+
spinner4.error(`Directory ${projectName} already exists`);
|
|
1223
|
+
throw new Error(`Directory ${projectName} already exists`);
|
|
1224
|
+
}
|
|
1225
|
+
await cloneRepositoryWithoutGit(template.githubUrl, projectPath);
|
|
1226
|
+
await updatePackageJson(projectPath, projectName);
|
|
1227
|
+
const envExamplePath = path3.join(projectPath, ".env.example");
|
|
1228
|
+
if (await fileExists(envExamplePath)) {
|
|
1229
|
+
await fs.copyFile(envExamplePath, path3.join(projectPath, ".env"));
|
|
1230
|
+
}
|
|
1231
|
+
spinner4.success(`Template "${template.title}" cloned successfully to ${projectName}`);
|
|
1232
|
+
return projectPath;
|
|
1233
|
+
} catch (error) {
|
|
1234
|
+
spinner4.error(`Failed to clone template: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
1235
|
+
throw error;
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
async function directoryExists(dirPath) {
|
|
1239
|
+
try {
|
|
1240
|
+
const stat = await fs.stat(dirPath);
|
|
1241
|
+
return stat.isDirectory();
|
|
1242
|
+
} catch {
|
|
1243
|
+
return false;
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
async function fileExists(filePath) {
|
|
1247
|
+
try {
|
|
1248
|
+
const stat = await fs.stat(filePath);
|
|
1249
|
+
return stat.isFile();
|
|
1250
|
+
} catch {
|
|
1251
|
+
return false;
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
async function cloneRepositoryWithoutGit(repoUrl, targetPath) {
|
|
1255
|
+
await fs.mkdir(targetPath, { recursive: true });
|
|
1256
|
+
try {
|
|
1257
|
+
const degitRepo = repoUrl.replace("https://github.com/", "");
|
|
1258
|
+
const degitCommand = shellQuote.quote(["npx", "degit", degitRepo, targetPath]);
|
|
1259
|
+
await exec(degitCommand, {
|
|
1260
|
+
cwd: process.cwd()
|
|
1261
|
+
});
|
|
1262
|
+
} catch {
|
|
1263
|
+
try {
|
|
1264
|
+
const gitCommand = shellQuote.quote(["git", "clone", repoUrl, targetPath]);
|
|
1265
|
+
await exec(gitCommand, {
|
|
1266
|
+
cwd: process.cwd()
|
|
1267
|
+
});
|
|
1268
|
+
const gitDir = path3.join(targetPath, ".git");
|
|
1269
|
+
if (await directoryExists(gitDir)) {
|
|
1270
|
+
await fs.rm(gitDir, { recursive: true, force: true });
|
|
1271
|
+
}
|
|
1272
|
+
} catch (gitError) {
|
|
1273
|
+
throw new Error(`Failed to clone repository: ${gitError instanceof Error ? gitError.message : "Unknown error"}`);
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
async function updatePackageJson(projectPath, projectName) {
|
|
1278
|
+
const packageJsonPath = path3.join(projectPath, "package.json");
|
|
1279
|
+
try {
|
|
1280
|
+
const packageJsonContent = await fs.readFile(packageJsonPath, "utf-8");
|
|
1281
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
1282
|
+
packageJson.name = projectName;
|
|
1283
|
+
await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2), "utf-8");
|
|
1284
|
+
} catch (error) {
|
|
1285
|
+
logger.warn(`Could not update package.json: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
async function installDependencies(projectPath, packageManager) {
|
|
1289
|
+
const spinner4 = yoctoSpinner({ text: "Installing dependencies..." }).start();
|
|
1290
|
+
try {
|
|
1291
|
+
const pm = packageManager || getPackageManager();
|
|
1292
|
+
const installCommand = shellQuote.quote([pm, "install"]);
|
|
1293
|
+
await exec(installCommand, {
|
|
1294
|
+
cwd: projectPath
|
|
1295
|
+
});
|
|
1296
|
+
spinner4.success("Dependencies installed successfully");
|
|
1297
|
+
} catch (error) {
|
|
1298
|
+
spinner4.error(`Failed to install dependencies: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
1299
|
+
throw error;
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
var TEMPLATES_API_URL = process.env.MASTRA_TEMPLATES_API_URL || "https://mastra.ai/api/templates.json";
|
|
1303
|
+
async function loadTemplates() {
|
|
1304
|
+
try {
|
|
1305
|
+
const response = await fetch(TEMPLATES_API_URL);
|
|
1306
|
+
if (!response.ok) {
|
|
1307
|
+
throw new Error(`Failed to fetch templates: ${response.statusText}`);
|
|
1308
|
+
}
|
|
1309
|
+
const templates = await response.json();
|
|
1310
|
+
return templates;
|
|
1311
|
+
} catch (error) {
|
|
1312
|
+
console.error("Error loading templates:", error);
|
|
1313
|
+
throw new Error("Failed to load templates. Please check your internet connection and try again.");
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1316
|
+
function pluralize(count, singular, plural) {
|
|
1317
|
+
return count === 1 ? singular : plural || `${singular}s`;
|
|
1318
|
+
}
|
|
1319
|
+
async function selectTemplate(templates) {
|
|
1320
|
+
const choices = templates.map((template) => {
|
|
1321
|
+
const parts = [];
|
|
1322
|
+
if (template.agents?.length) {
|
|
1323
|
+
parts.push(`${template.agents.length} ${pluralize(template.agents.length, "agent")}`);
|
|
1324
|
+
}
|
|
1325
|
+
if (template.tools?.length) {
|
|
1326
|
+
parts.push(`${template.tools.length} ${pluralize(template.tools.length, "tool")}`);
|
|
1327
|
+
}
|
|
1328
|
+
if (template.workflows?.length) {
|
|
1329
|
+
parts.push(`${template.workflows.length} ${pluralize(template.workflows.length, "workflow")}`);
|
|
1330
|
+
}
|
|
1331
|
+
if (template.mcp?.length) {
|
|
1332
|
+
parts.push(`${template.mcp.length} ${pluralize(template.mcp.length, "MCP server")}`);
|
|
1333
|
+
}
|
|
1334
|
+
if (template.networks?.length) {
|
|
1335
|
+
parts.push(`${template.networks.length} ${pluralize(template.networks.length, "agent network")}`);
|
|
1336
|
+
}
|
|
1337
|
+
return {
|
|
1338
|
+
value: template,
|
|
1339
|
+
label: template.title,
|
|
1340
|
+
hint: parts.join(", ") || "Template components"
|
|
1341
|
+
};
|
|
1342
|
+
});
|
|
1343
|
+
const selected = await ve({
|
|
1344
|
+
message: "Select a template:",
|
|
1345
|
+
options: choices
|
|
1346
|
+
});
|
|
1347
|
+
if (pD(selected)) {
|
|
1348
|
+
return null;
|
|
1349
|
+
}
|
|
1350
|
+
return selected;
|
|
1351
|
+
}
|
|
1352
|
+
function findTemplateByName(templates, templateName) {
|
|
1353
|
+
let template = templates.find((t) => t.slug === templateName);
|
|
1354
|
+
if (template) return template;
|
|
1355
|
+
const slugWithPrefix = `template-${templateName}`;
|
|
1356
|
+
template = templates.find((t) => t.slug === slugWithPrefix);
|
|
1357
|
+
if (template) return template;
|
|
1358
|
+
template = templates.find((t) => t.title.toLowerCase() === templateName.toLowerCase());
|
|
1359
|
+
if (template) return template;
|
|
1360
|
+
return null;
|
|
1361
|
+
}
|
|
1362
|
+
function getDefaultProjectName(template) {
|
|
1363
|
+
return template.slug.replace(/^template-/, "");
|
|
1364
|
+
}
|
|
1156
1365
|
var DepsService = class {
|
|
1157
1366
|
packageManager;
|
|
1158
1367
|
constructor() {
|
|
@@ -1161,11 +1370,11 @@ var DepsService = class {
|
|
|
1161
1370
|
findLockFile(dir) {
|
|
1162
1371
|
const lockFiles = ["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lock"];
|
|
1163
1372
|
for (const file of lockFiles) {
|
|
1164
|
-
if (
|
|
1373
|
+
if (fs4__default__default.existsSync(path3.join(dir, file))) {
|
|
1165
1374
|
return file;
|
|
1166
1375
|
}
|
|
1167
1376
|
}
|
|
1168
|
-
const parentDir =
|
|
1377
|
+
const parentDir = path3.resolve(dir, "..");
|
|
1169
1378
|
if (parentDir !== dir) {
|
|
1170
1379
|
return this.findLockFile(parentDir);
|
|
1171
1380
|
}
|
|
@@ -1202,13 +1411,13 @@ var DepsService = class {
|
|
|
1202
1411
|
}
|
|
1203
1412
|
async checkDependencies(dependencies) {
|
|
1204
1413
|
try {
|
|
1205
|
-
const packageJsonPath =
|
|
1414
|
+
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
1206
1415
|
try {
|
|
1207
|
-
await
|
|
1416
|
+
await fs.access(packageJsonPath);
|
|
1208
1417
|
} catch {
|
|
1209
1418
|
return "No package.json file found in the current directory";
|
|
1210
1419
|
}
|
|
1211
|
-
const packageJson = JSON.parse(await
|
|
1420
|
+
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf-8"));
|
|
1212
1421
|
for (const dependency of dependencies) {
|
|
1213
1422
|
if (!packageJson.dependencies || !packageJson.dependencies[dependency]) {
|
|
1214
1423
|
return `Please install ${dependency} before running this command (${this.packageManager} install ${dependency})`;
|
|
@@ -1222,8 +1431,8 @@ var DepsService = class {
|
|
|
1222
1431
|
}
|
|
1223
1432
|
async getProjectName() {
|
|
1224
1433
|
try {
|
|
1225
|
-
const packageJsonPath =
|
|
1226
|
-
const packageJson = await
|
|
1434
|
+
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
1435
|
+
const packageJson = await fs.readFile(packageJsonPath, "utf-8");
|
|
1227
1436
|
const pkg = JSON.parse(packageJson);
|
|
1228
1437
|
return pkg.name;
|
|
1229
1438
|
} catch (err) {
|
|
@@ -1233,54 +1442,19 @@ var DepsService = class {
|
|
|
1233
1442
|
async getPackageVersion() {
|
|
1234
1443
|
const __filename = fileURLToPath(import.meta.url);
|
|
1235
1444
|
const __dirname = dirname(__filename);
|
|
1236
|
-
const pkgJsonPath =
|
|
1445
|
+
const pkgJsonPath = path3.join(__dirname, "..", "package.json");
|
|
1237
1446
|
const content = await fsExtra3.readJSON(pkgJsonPath);
|
|
1238
1447
|
return content.version;
|
|
1239
1448
|
}
|
|
1240
1449
|
async addScriptsToPackageJson(scripts) {
|
|
1241
|
-
const packageJson = JSON.parse(await
|
|
1450
|
+
const packageJson = JSON.parse(await fs.readFile("package.json", "utf-8"));
|
|
1242
1451
|
packageJson.scripts = {
|
|
1243
1452
|
...packageJson.scripts,
|
|
1244
1453
|
...scripts
|
|
1245
1454
|
};
|
|
1246
|
-
await
|
|
1455
|
+
await fs.writeFile("package.json", JSON.stringify(packageJson, null, 2));
|
|
1247
1456
|
}
|
|
1248
1457
|
};
|
|
1249
|
-
function getPackageManager() {
|
|
1250
|
-
const userAgent = process.env.npm_config_user_agent || "";
|
|
1251
|
-
const execPath = process.env.npm_execpath || "";
|
|
1252
|
-
if (userAgent.includes("yarn")) {
|
|
1253
|
-
return "yarn";
|
|
1254
|
-
}
|
|
1255
|
-
if (userAgent.includes("pnpm")) {
|
|
1256
|
-
return "pnpm";
|
|
1257
|
-
}
|
|
1258
|
-
if (userAgent.includes("npm")) {
|
|
1259
|
-
return "npm";
|
|
1260
|
-
}
|
|
1261
|
-
if (execPath.includes("yarn")) {
|
|
1262
|
-
return "yarn";
|
|
1263
|
-
}
|
|
1264
|
-
if (execPath.includes("pnpm")) {
|
|
1265
|
-
return "pnpm";
|
|
1266
|
-
}
|
|
1267
|
-
if (execPath.includes("npm")) {
|
|
1268
|
-
return "npm";
|
|
1269
|
-
}
|
|
1270
|
-
return "npm";
|
|
1271
|
-
}
|
|
1272
|
-
function getPackageManagerInstallCommand(pm) {
|
|
1273
|
-
switch (pm) {
|
|
1274
|
-
case "npm":
|
|
1275
|
-
return "install";
|
|
1276
|
-
case "yarn":
|
|
1277
|
-
return "add";
|
|
1278
|
-
case "pnpm":
|
|
1279
|
-
return "add";
|
|
1280
|
-
default:
|
|
1281
|
-
return "install";
|
|
1282
|
-
}
|
|
1283
|
-
}
|
|
1284
1458
|
var args = ["-y", "@mastra/mcp-docs-server"];
|
|
1285
1459
|
var createMcpConfig = (editor) => {
|
|
1286
1460
|
if (editor === "vscode") {
|
|
@@ -1333,19 +1507,19 @@ async function writeMergedConfig(configPath, editor) {
|
|
|
1333
1507
|
spaces: 2
|
|
1334
1508
|
});
|
|
1335
1509
|
}
|
|
1336
|
-
var windsurfGlobalMCPConfigPath =
|
|
1337
|
-
var cursorGlobalMCPConfigPath =
|
|
1338
|
-
|
|
1339
|
-
var vscodeGlobalMCPConfigPath =
|
|
1510
|
+
var windsurfGlobalMCPConfigPath = path3.join(os.homedir(), ".codeium", "windsurf", "mcp_config.json");
|
|
1511
|
+
var cursorGlobalMCPConfigPath = path3.join(os.homedir(), ".cursor", "mcp.json");
|
|
1512
|
+
path3.join(process.cwd(), ".vscode", "mcp.json");
|
|
1513
|
+
var vscodeGlobalMCPConfigPath = path3.join(
|
|
1340
1514
|
os.homedir(),
|
|
1341
|
-
process.platform === "win32" ?
|
|
1515
|
+
process.platform === "win32" ? path3.join("AppData", "Roaming", "Code", "User", "settings.json") : process.platform === "darwin" ? path3.join("Library", "Application Support", "Code", "User", "settings.json") : path3.join(".config", "Code", "User", "settings.json")
|
|
1342
1516
|
);
|
|
1343
1517
|
async function installMastraDocsMCPServer({ editor, directory }) {
|
|
1344
1518
|
if (editor === `cursor`) {
|
|
1345
|
-
await writeMergedConfig(
|
|
1519
|
+
await writeMergedConfig(path3.join(directory, ".cursor", "mcp.json"), "cursor");
|
|
1346
1520
|
}
|
|
1347
1521
|
if (editor === `vscode`) {
|
|
1348
|
-
await writeMergedConfig(
|
|
1522
|
+
await writeMergedConfig(path3.join(directory, ".vscode", "mcp.json"), "vscode");
|
|
1349
1523
|
}
|
|
1350
1524
|
if (editor === `cursor-global`) {
|
|
1351
1525
|
const alreadyInstalled = await globalMCPIsAlreadyInstalled(editor);
|
|
@@ -1403,7 +1577,7 @@ var FileEnvService = class extends EnvService {
|
|
|
1403
1577
|
}
|
|
1404
1578
|
readFile(filePath) {
|
|
1405
1579
|
return new Promise((resolve, reject) => {
|
|
1406
|
-
|
|
1580
|
+
fs4__default.readFile(filePath, "utf8", (err, data) => {
|
|
1407
1581
|
if (err) reject(err);
|
|
1408
1582
|
else resolve(data);
|
|
1409
1583
|
});
|
|
@@ -1411,7 +1585,7 @@ var FileEnvService = class extends EnvService {
|
|
|
1411
1585
|
}
|
|
1412
1586
|
writeFile({ filePath, data }) {
|
|
1413
1587
|
return new Promise((resolve, reject) => {
|
|
1414
|
-
|
|
1588
|
+
fs4__default.writeFile(filePath, data, "utf8", (err) => {
|
|
1415
1589
|
if (err) reject(err);
|
|
1416
1590
|
else resolve();
|
|
1417
1591
|
});
|
|
@@ -1464,10 +1638,10 @@ var FileService = class {
|
|
|
1464
1638
|
*/
|
|
1465
1639
|
async copyStarterFile(inputFile, outputFilePath, replaceIfExists) {
|
|
1466
1640
|
const __filename = fileURLToPath(import.meta.url);
|
|
1467
|
-
const __dirname =
|
|
1468
|
-
const filePath =
|
|
1469
|
-
const fileString =
|
|
1470
|
-
if (
|
|
1641
|
+
const __dirname = path3.dirname(__filename);
|
|
1642
|
+
const filePath = path3.resolve(__dirname, "starter-files", inputFile);
|
|
1643
|
+
const fileString = fs4__default__default.readFileSync(filePath, "utf8");
|
|
1644
|
+
if (fs4__default__default.existsSync(outputFilePath) && !replaceIfExists) {
|
|
1471
1645
|
console.log(`${outputFilePath} already exists`);
|
|
1472
1646
|
return false;
|
|
1473
1647
|
}
|
|
@@ -1475,14 +1649,14 @@ var FileService = class {
|
|
|
1475
1649
|
return true;
|
|
1476
1650
|
}
|
|
1477
1651
|
async setupEnvFile({ dbUrl }) {
|
|
1478
|
-
const envPath =
|
|
1652
|
+
const envPath = path3.join(process.cwd(), ".env.development");
|
|
1479
1653
|
await fsExtra3.ensureFile(envPath);
|
|
1480
1654
|
const fileEnvService = new FileEnvService(envPath);
|
|
1481
1655
|
await fileEnvService.setEnvValue("DB_URL", dbUrl);
|
|
1482
1656
|
}
|
|
1483
1657
|
getFirstExistingFile(files) {
|
|
1484
1658
|
for (const f of files) {
|
|
1485
|
-
if (
|
|
1659
|
+
if (fs4__default__default.existsSync(f)) {
|
|
1486
1660
|
return f;
|
|
1487
1661
|
}
|
|
1488
1662
|
}
|
|
@@ -1492,18 +1666,14 @@ var FileService = class {
|
|
|
1492
1666
|
filePath,
|
|
1493
1667
|
replacements
|
|
1494
1668
|
}) {
|
|
1495
|
-
let fileContent =
|
|
1669
|
+
let fileContent = fs4__default__default.readFileSync(filePath, "utf8");
|
|
1496
1670
|
replacements.forEach(({ search, replace }) => {
|
|
1497
1671
|
fileContent = fileContent.replaceAll(search, replace);
|
|
1498
1672
|
});
|
|
1499
|
-
|
|
1673
|
+
fs4__default__default.writeFileSync(filePath, fileContent);
|
|
1500
1674
|
}
|
|
1501
1675
|
};
|
|
1502
|
-
|
|
1503
|
-
name: "Mastra CLI",
|
|
1504
|
-
level: "info"
|
|
1505
|
-
});
|
|
1506
|
-
var exec = util.promisify(child_process.exec);
|
|
1676
|
+
var exec2 = util.promisify(child_process.exec);
|
|
1507
1677
|
var getAISDKPackage = (llmProvider) => {
|
|
1508
1678
|
switch (llmProvider) {
|
|
1509
1679
|
case "openai":
|
|
@@ -1580,8 +1750,8 @@ export const weatherAgent = new Agent({
|
|
|
1580
1750
|
parser: "typescript",
|
|
1581
1751
|
singleQuote: true
|
|
1582
1752
|
});
|
|
1583
|
-
await
|
|
1584
|
-
await
|
|
1753
|
+
await fs.writeFile(destPath, "");
|
|
1754
|
+
await fs.writeFile(destPath, formattedContent);
|
|
1585
1755
|
}
|
|
1586
1756
|
async function writeWorkflowSample(destPath) {
|
|
1587
1757
|
const content = `import { createStep, createWorkflow } from '@mastra/core/workflows';
|
|
@@ -1774,7 +1944,7 @@ export { weatherWorkflow };`;
|
|
|
1774
1944
|
semi: true,
|
|
1775
1945
|
singleQuote: true
|
|
1776
1946
|
});
|
|
1777
|
-
await
|
|
1947
|
+
await fs.writeFile(destPath, formattedContent);
|
|
1778
1948
|
}
|
|
1779
1949
|
async function writeToolSample(destPath) {
|
|
1780
1950
|
const fileService = new FileService();
|
|
@@ -1803,15 +1973,15 @@ var writeIndexFile = async ({
|
|
|
1803
1973
|
addWorkflow
|
|
1804
1974
|
}) => {
|
|
1805
1975
|
const indexPath = dirPath + "/index.ts";
|
|
1806
|
-
const destPath =
|
|
1976
|
+
const destPath = path3.join(indexPath);
|
|
1807
1977
|
try {
|
|
1808
|
-
await
|
|
1978
|
+
await fs.writeFile(destPath, "");
|
|
1809
1979
|
const filteredExports = [
|
|
1810
1980
|
addWorkflow ? `workflows: { weatherWorkflow },` : "",
|
|
1811
1981
|
addAgent ? `agents: { weatherAgent },` : ""
|
|
1812
1982
|
].filter(Boolean);
|
|
1813
1983
|
if (!addExample) {
|
|
1814
|
-
await
|
|
1984
|
+
await fs.writeFile(
|
|
1815
1985
|
destPath,
|
|
1816
1986
|
`
|
|
1817
1987
|
import { Mastra } from '@mastra/core';
|
|
@@ -1821,7 +1991,7 @@ export const mastra = new Mastra()
|
|
|
1821
1991
|
);
|
|
1822
1992
|
return;
|
|
1823
1993
|
}
|
|
1824
|
-
await
|
|
1994
|
+
await fs.writeFile(
|
|
1825
1995
|
destPath,
|
|
1826
1996
|
`
|
|
1827
1997
|
import { Mastra } from '@mastra/core/mastra';
|
|
@@ -1874,13 +2044,13 @@ var writeAPIKey = async ({
|
|
|
1874
2044
|
const key = await getAPIKey(provider);
|
|
1875
2045
|
const escapedKey = shellQuote.quote([key]);
|
|
1876
2046
|
const escapedApiKey = shellQuote.quote([apiKey]);
|
|
1877
|
-
await
|
|
2047
|
+
await exec2(`echo ${escapedKey}=${escapedApiKey} >> .env`);
|
|
1878
2048
|
};
|
|
1879
2049
|
var createMastraDir = async (directory) => {
|
|
1880
2050
|
let dir = directory.trim().split("/").filter((item) => item !== "");
|
|
1881
|
-
const dirPath =
|
|
2051
|
+
const dirPath = path3.join(process.cwd(), ...dir, "mastra");
|
|
1882
2052
|
try {
|
|
1883
|
-
await
|
|
2053
|
+
await fs.access(dirPath);
|
|
1884
2054
|
return { ok: false };
|
|
1885
2055
|
} catch {
|
|
1886
2056
|
await fsExtra3.ensureDir(dirPath);
|
|
@@ -2017,7 +2187,7 @@ This means the Mastra docs MCP server will be available in all your Windsurf pro
|
|
|
2017
2187
|
return mastraProject;
|
|
2018
2188
|
};
|
|
2019
2189
|
var s = Y();
|
|
2020
|
-
var
|
|
2190
|
+
var exec3 = util.promisify(child_process.exec);
|
|
2021
2191
|
var init = async ({
|
|
2022
2192
|
directory,
|
|
2023
2193
|
addExample = false,
|
|
@@ -2069,7 +2239,7 @@ var init = async ({
|
|
|
2069
2239
|
const depsService = new DepsService();
|
|
2070
2240
|
const pm = depsService.packageManager;
|
|
2071
2241
|
const installCommand = getPackageManagerInstallCommand(pm);
|
|
2072
|
-
await
|
|
2242
|
+
await exec3(`${pm} ${installCommand} ${aiSdkPackage}`);
|
|
2073
2243
|
if (configureEditorWithDocsMCP) {
|
|
2074
2244
|
await installMastraDocsMCPServer({
|
|
2075
2245
|
editor: configureEditorWithDocsMCP,
|
|
@@ -2096,10 +2266,10 @@ var init = async ({
|
|
|
2096
2266
|
return { success: false };
|
|
2097
2267
|
}
|
|
2098
2268
|
};
|
|
2099
|
-
var
|
|
2269
|
+
var exec4 = util.promisify(child_process.exec);
|
|
2100
2270
|
var execWithTimeout = async (command, timeoutMs) => {
|
|
2101
2271
|
try {
|
|
2102
|
-
const promise =
|
|
2272
|
+
const promise = exec4(command, { killSignal: "SIGTERM" });
|
|
2103
2273
|
if (!timeoutMs) {
|
|
2104
2274
|
return await promise;
|
|
2105
2275
|
}
|
|
@@ -2163,7 +2333,7 @@ var createMastraProject = async ({
|
|
|
2163
2333
|
try {
|
|
2164
2334
|
s2.start("Creating project");
|
|
2165
2335
|
try {
|
|
2166
|
-
await
|
|
2336
|
+
await fs.mkdir(projectName);
|
|
2167
2337
|
} catch (error) {
|
|
2168
2338
|
if (error instanceof Error && "code" in error && error.code === "EEXIST") {
|
|
2169
2339
|
s2.stop(`A directory named "${projectName}" already exists. Please choose a different name.`);
|
|
@@ -2178,9 +2348,9 @@ var createMastraProject = async ({
|
|
|
2178
2348
|
const installCommand = getPackageManagerInstallCommand(pm);
|
|
2179
2349
|
s2.message("Initializing project structure");
|
|
2180
2350
|
try {
|
|
2181
|
-
await
|
|
2182
|
-
await
|
|
2183
|
-
await
|
|
2351
|
+
await exec4(`npm init -y`);
|
|
2352
|
+
await exec4(`npm pkg set type="module"`);
|
|
2353
|
+
await exec4(`npm pkg set engines.node=">=20.9.0"`);
|
|
2184
2354
|
const depsService = new DepsService();
|
|
2185
2355
|
await depsService.addScriptsToPackageJson({
|
|
2186
2356
|
dev: "mastra dev",
|
|
@@ -2195,9 +2365,9 @@ var createMastraProject = async ({
|
|
|
2195
2365
|
s2.stop("Project structure created");
|
|
2196
2366
|
s2.start(`Installing ${pm} dependencies`);
|
|
2197
2367
|
try {
|
|
2198
|
-
await
|
|
2199
|
-
await
|
|
2200
|
-
await
|
|
2368
|
+
await exec4(`${pm} ${installCommand} zod@^3`);
|
|
2369
|
+
await exec4(`${pm} ${installCommand} typescript @types/node --save-dev`);
|
|
2370
|
+
await exec4(`echo '{
|
|
2201
2371
|
"compilerOptions": {
|
|
2202
2372
|
"target": "ES2022",
|
|
2203
2373
|
"module": "ES2022",
|
|
@@ -2240,14 +2410,14 @@ var createMastraProject = async ({
|
|
|
2240
2410
|
s2.stop("Mastra dependencies installed");
|
|
2241
2411
|
s2.start("Adding .gitignore");
|
|
2242
2412
|
try {
|
|
2243
|
-
await
|
|
2244
|
-
await
|
|
2245
|
-
await
|
|
2246
|
-
await
|
|
2247
|
-
await
|
|
2248
|
-
await
|
|
2249
|
-
await
|
|
2250
|
-
await
|
|
2413
|
+
await exec4(`echo output.txt >> .gitignore`);
|
|
2414
|
+
await exec4(`echo node_modules >> .gitignore`);
|
|
2415
|
+
await exec4(`echo dist >> .gitignore`);
|
|
2416
|
+
await exec4(`echo .mastra >> .gitignore`);
|
|
2417
|
+
await exec4(`echo .env.development >> .gitignore`);
|
|
2418
|
+
await exec4(`echo .env >> .gitignore`);
|
|
2419
|
+
await exec4(`echo *.db >> .gitignore`);
|
|
2420
|
+
await exec4(`echo *.db-* >> .gitignore`);
|
|
2251
2421
|
} catch (error) {
|
|
2252
2422
|
throw new Error(`Failed to create .gitignore: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2253
2423
|
}
|
|
@@ -2263,6 +2433,10 @@ var createMastraProject = async ({
|
|
|
2263
2433
|
}
|
|
2264
2434
|
};
|
|
2265
2435
|
var create = async (args2) => {
|
|
2436
|
+
if (args2.template !== void 0) {
|
|
2437
|
+
await createFromTemplate(args2);
|
|
2438
|
+
return;
|
|
2439
|
+
}
|
|
2266
2440
|
const { projectName } = await createMastraProject({
|
|
2267
2441
|
projectName: args2?.projectName,
|
|
2268
2442
|
createVersionTag: args2?.createVersionTag,
|
|
@@ -2300,11 +2474,65 @@ var postCreate = ({ projectName }) => {
|
|
|
2300
2474
|
${color2.cyan(`${packageManager} run dev`)}
|
|
2301
2475
|
`);
|
|
2302
2476
|
};
|
|
2477
|
+
async function createFromTemplate(args2) {
|
|
2478
|
+
const templates = await loadTemplates();
|
|
2479
|
+
let selectedTemplate;
|
|
2480
|
+
if (args2.template === true) {
|
|
2481
|
+
selectedTemplate = await selectTemplate(templates);
|
|
2482
|
+
if (!selectedTemplate) {
|
|
2483
|
+
M.info("No template selected. Exiting.");
|
|
2484
|
+
return;
|
|
2485
|
+
}
|
|
2486
|
+
} else if (args2.template) {
|
|
2487
|
+
selectedTemplate = findTemplateByName(templates, args2.template);
|
|
2488
|
+
if (!selectedTemplate) {
|
|
2489
|
+
M.error(`Template "${args2.template}" not found. Available templates:`);
|
|
2490
|
+
templates.forEach((t) => M.info(` - ${t.title} (use: ${t.slug.replace("template-", "")})`));
|
|
2491
|
+
throw new Error(`Template "${args2.template}" not found`);
|
|
2492
|
+
}
|
|
2493
|
+
}
|
|
2494
|
+
if (!selectedTemplate) {
|
|
2495
|
+
throw new Error("No template selected");
|
|
2496
|
+
}
|
|
2497
|
+
let projectName = args2.projectName;
|
|
2498
|
+
if (!projectName) {
|
|
2499
|
+
const defaultName = getDefaultProjectName(selectedTemplate);
|
|
2500
|
+
const response = await he({
|
|
2501
|
+
message: "What is your project name?",
|
|
2502
|
+
defaultValue: defaultName,
|
|
2503
|
+
placeholder: defaultName
|
|
2504
|
+
});
|
|
2505
|
+
if (pD(response)) {
|
|
2506
|
+
M.info("Project creation cancelled.");
|
|
2507
|
+
return;
|
|
2508
|
+
}
|
|
2509
|
+
projectName = response;
|
|
2510
|
+
}
|
|
2511
|
+
try {
|
|
2512
|
+
const analytics = getAnalytics();
|
|
2513
|
+
if (analytics) ;
|
|
2514
|
+
const projectPath = await cloneTemplate({
|
|
2515
|
+
template: selectedTemplate,
|
|
2516
|
+
projectName
|
|
2517
|
+
});
|
|
2518
|
+
await installDependencies(projectPath);
|
|
2519
|
+
Me(`
|
|
2520
|
+
${color2.green("Mastra template installed!")}
|
|
2521
|
+
|
|
2522
|
+
Add the necessary environment
|
|
2523
|
+
variables in your ${color2.cyan(".env")} file
|
|
2524
|
+
`);
|
|
2525
|
+
postCreate({ projectName });
|
|
2526
|
+
} catch (error) {
|
|
2527
|
+
M.error(`Failed to create project from template: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2528
|
+
throw error;
|
|
2529
|
+
}
|
|
2530
|
+
}
|
|
2303
2531
|
|
|
2304
2532
|
async function getPackageVersion() {
|
|
2305
2533
|
const __filename = fileURLToPath(import.meta.url);
|
|
2306
2534
|
const __dirname = dirname(__filename);
|
|
2307
|
-
const pkgJsonPath =
|
|
2535
|
+
const pkgJsonPath = path3.join(__dirname, "..", "package.json");
|
|
2308
2536
|
const content = await fsExtra.readJSON(pkgJsonPath);
|
|
2309
2537
|
return content.version;
|
|
2310
2538
|
}
|
|
@@ -2342,7 +2570,10 @@ program.version(`${version}`, "-v, --version").description(`create-mastra ${vers
|
|
|
2342
2570
|
program.name("create-mastra").description("Create a new Mastra project").argument("[project-name]", "Directory name of the project").option(
|
|
2343
2571
|
"-p, --project-name <string>",
|
|
2344
2572
|
"Project name that will be used in package.json and as the project directory name."
|
|
2345
|
-
).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)").
|
|
2573
|
+
).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
|
+
"--template [template-name]",
|
|
2575
|
+
"Create project from a template (use template name or leave blank to select from list)"
|
|
2576
|
+
).action(async (projectNameArg, args) => {
|
|
2346
2577
|
const projectName = projectNameArg || args.projectName;
|
|
2347
2578
|
const timeout = args?.timeout ? args?.timeout === true ? 6e4 : parseInt(args?.timeout, 10) : void 0;
|
|
2348
2579
|
if (args.default) {
|
|
@@ -2353,7 +2584,8 @@ program.name("create-mastra").description("Create a new Mastra project").argumen
|
|
|
2353
2584
|
createVersionTag,
|
|
2354
2585
|
timeout,
|
|
2355
2586
|
mcpServer: args.mcp,
|
|
2356
|
-
directory: "src/"
|
|
2587
|
+
directory: "src/",
|
|
2588
|
+
template: args.template
|
|
2357
2589
|
});
|
|
2358
2590
|
return;
|
|
2359
2591
|
}
|
|
@@ -2366,7 +2598,8 @@ program.name("create-mastra").description("Create a new Mastra project").argumen
|
|
|
2366
2598
|
timeout,
|
|
2367
2599
|
projectName,
|
|
2368
2600
|
directory: args.dir,
|
|
2369
|
-
mcpServer: args.mcp
|
|
2601
|
+
mcpServer: args.mcp,
|
|
2602
|
+
template: args.template
|
|
2370
2603
|
});
|
|
2371
2604
|
});
|
|
2372
2605
|
program.parse(process.argv);
|