mastra 0.10.13-alpha.0 → 0.10.13-alpha.1

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.
@@ -1,21 +1,213 @@
1
- import * as p from '@clack/prompts';
1
+ import { getAnalytics } from './chunk-US7IPLZ2.js';
2
+ import * as p2 from '@clack/prompts';
2
3
  import color2 from 'picocolors';
4
+ import fs from 'fs/promises';
3
5
  import child_process from 'child_process';
4
6
  import util from 'util';
5
- import * as fs3 from 'fs';
6
- import fs3__default, { existsSync } from 'fs';
7
- import fs4 from 'fs/promises';
8
- import path2, { dirname } from 'path';
7
+ import path3, { dirname } from 'path';
8
+ import shellQuote from 'shell-quote';
9
+ import yoctoSpinner from 'yocto-spinner';
10
+ import { PinoLogger } from '@mastra/loggers';
11
+ import * as fs4 from 'fs';
12
+ import fs4__default, { existsSync } from 'fs';
9
13
  import { fileURLToPath } from 'url';
10
14
  import { execa } from 'execa';
11
15
  import fsExtra3, { readJSON, ensureFile, writeJSON } from 'fs-extra/esm';
12
16
  import os from 'os';
13
17
  import prettier from 'prettier';
14
- import shellQuote from 'shell-quote';
15
- import yoctoSpinner from 'yocto-spinner';
16
- import { PinoLogger } from '@mastra/loggers';
17
18
 
18
- // src/commands/create/create.ts
19
+ // src/commands/utils.ts
20
+ function getPackageManager() {
21
+ const userAgent = process.env.npm_config_user_agent || "";
22
+ const execPath = process.env.npm_execpath || "";
23
+ if (userAgent.includes("yarn")) {
24
+ return "yarn";
25
+ }
26
+ if (userAgent.includes("pnpm")) {
27
+ return "pnpm";
28
+ }
29
+ if (userAgent.includes("npm")) {
30
+ return "npm";
31
+ }
32
+ if (execPath.includes("yarn")) {
33
+ return "yarn";
34
+ }
35
+ if (execPath.includes("pnpm")) {
36
+ return "pnpm";
37
+ }
38
+ if (execPath.includes("npm")) {
39
+ return "npm";
40
+ }
41
+ return "npm";
42
+ }
43
+ function getPackageManagerInstallCommand(pm) {
44
+ switch (pm) {
45
+ case "npm":
46
+ return "install";
47
+ case "yarn":
48
+ return "add";
49
+ case "pnpm":
50
+ return "add";
51
+ default:
52
+ return "install";
53
+ }
54
+ }
55
+ var logger = new PinoLogger({
56
+ name: "Mastra CLI",
57
+ level: "info"
58
+ });
59
+
60
+ // src/utils/clone-template.ts
61
+ var exec = util.promisify(child_process.exec);
62
+ async function cloneTemplate(options) {
63
+ const { template, projectName, targetDir } = options;
64
+ const projectPath = targetDir ? path3.resolve(targetDir, projectName) : path3.resolve(projectName);
65
+ const spinner4 = yoctoSpinner({ text: `Cloning template "${template.title}"...` }).start();
66
+ try {
67
+ if (await directoryExists(projectPath)) {
68
+ spinner4.error(`Directory ${projectName} already exists`);
69
+ throw new Error(`Directory ${projectName} already exists`);
70
+ }
71
+ await cloneRepositoryWithoutGit(template.githubUrl, projectPath);
72
+ await updatePackageJson(projectPath, projectName);
73
+ const envExamplePath = path3.join(projectPath, ".env.example");
74
+ if (await fileExists(envExamplePath)) {
75
+ await fs.copyFile(envExamplePath, path3.join(projectPath, ".env"));
76
+ }
77
+ spinner4.success(`Template "${template.title}" cloned successfully to ${projectName}`);
78
+ return projectPath;
79
+ } catch (error) {
80
+ spinner4.error(`Failed to clone template: ${error instanceof Error ? error.message : "Unknown error"}`);
81
+ throw error;
82
+ }
83
+ }
84
+ async function directoryExists(dirPath) {
85
+ try {
86
+ const stat = await fs.stat(dirPath);
87
+ return stat.isDirectory();
88
+ } catch {
89
+ return false;
90
+ }
91
+ }
92
+ async function fileExists(filePath) {
93
+ try {
94
+ const stat = await fs.stat(filePath);
95
+ return stat.isFile();
96
+ } catch {
97
+ return false;
98
+ }
99
+ }
100
+ async function cloneRepositoryWithoutGit(repoUrl, targetPath) {
101
+ await fs.mkdir(targetPath, { recursive: true });
102
+ try {
103
+ const degitRepo = repoUrl.replace("https://github.com/", "");
104
+ const degitCommand = shellQuote.quote(["npx", "degit", degitRepo, targetPath]);
105
+ await exec(degitCommand, {
106
+ cwd: process.cwd()
107
+ });
108
+ } catch {
109
+ try {
110
+ const gitCommand = shellQuote.quote(["git", "clone", repoUrl, targetPath]);
111
+ await exec(gitCommand, {
112
+ cwd: process.cwd()
113
+ });
114
+ const gitDir = path3.join(targetPath, ".git");
115
+ if (await directoryExists(gitDir)) {
116
+ await fs.rm(gitDir, { recursive: true, force: true });
117
+ }
118
+ } catch (gitError) {
119
+ throw new Error(`Failed to clone repository: ${gitError instanceof Error ? gitError.message : "Unknown error"}`);
120
+ }
121
+ }
122
+ }
123
+ async function updatePackageJson(projectPath, projectName) {
124
+ const packageJsonPath = path3.join(projectPath, "package.json");
125
+ try {
126
+ const packageJsonContent = await fs.readFile(packageJsonPath, "utf-8");
127
+ const packageJson = JSON.parse(packageJsonContent);
128
+ packageJson.name = projectName;
129
+ await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2), "utf-8");
130
+ } catch (error) {
131
+ logger.warn(`Could not update package.json: ${error instanceof Error ? error.message : "Unknown error"}`);
132
+ }
133
+ }
134
+ async function installDependencies(projectPath, packageManager) {
135
+ const spinner4 = yoctoSpinner({ text: "Installing dependencies..." }).start();
136
+ try {
137
+ const pm = packageManager || getPackageManager();
138
+ const installCommand = shellQuote.quote([pm, "install"]);
139
+ await exec(installCommand, {
140
+ cwd: projectPath
141
+ });
142
+ spinner4.success("Dependencies installed successfully");
143
+ } catch (error) {
144
+ spinner4.error(`Failed to install dependencies: ${error instanceof Error ? error.message : "Unknown error"}`);
145
+ throw error;
146
+ }
147
+ }
148
+ var TEMPLATES_API_URL = process.env.MASTRA_TEMPLATES_API_URL || "https://mastra.ai/api/templates.json";
149
+ async function loadTemplates() {
150
+ try {
151
+ const response = await fetch(TEMPLATES_API_URL);
152
+ if (!response.ok) {
153
+ throw new Error(`Failed to fetch templates: ${response.statusText}`);
154
+ }
155
+ const templates = await response.json();
156
+ return templates;
157
+ } catch (error) {
158
+ console.error("Error loading templates:", error);
159
+ throw new Error("Failed to load templates. Please check your internet connection and try again.");
160
+ }
161
+ }
162
+ function pluralize(count, singular, plural) {
163
+ return count === 1 ? singular : plural || `${singular}s`;
164
+ }
165
+ async function selectTemplate(templates) {
166
+ const choices = templates.map((template) => {
167
+ const parts = [];
168
+ if (template.agents?.length) {
169
+ parts.push(`${template.agents.length} ${pluralize(template.agents.length, "agent")}`);
170
+ }
171
+ if (template.tools?.length) {
172
+ parts.push(`${template.tools.length} ${pluralize(template.tools.length, "tool")}`);
173
+ }
174
+ if (template.workflows?.length) {
175
+ parts.push(`${template.workflows.length} ${pluralize(template.workflows.length, "workflow")}`);
176
+ }
177
+ if (template.mcp?.length) {
178
+ parts.push(`${template.mcp.length} ${pluralize(template.mcp.length, "MCP server")}`);
179
+ }
180
+ if (template.networks?.length) {
181
+ parts.push(`${template.networks.length} ${pluralize(template.networks.length, "agent network")}`);
182
+ }
183
+ return {
184
+ value: template,
185
+ label: template.title,
186
+ hint: parts.join(", ") || "Template components"
187
+ };
188
+ });
189
+ const selected = await p2.select({
190
+ message: "Select a template:",
191
+ options: choices
192
+ });
193
+ if (p2.isCancel(selected)) {
194
+ return null;
195
+ }
196
+ return selected;
197
+ }
198
+ function findTemplateByName(templates, templateName) {
199
+ let template = templates.find((t) => t.slug === templateName);
200
+ if (template) return template;
201
+ const slugWithPrefix = `template-${templateName}`;
202
+ template = templates.find((t) => t.slug === slugWithPrefix);
203
+ if (template) return template;
204
+ template = templates.find((t) => t.title.toLowerCase() === templateName.toLowerCase());
205
+ if (template) return template;
206
+ return null;
207
+ }
208
+ function getDefaultProjectName(template) {
209
+ return template.slug.replace(/^template-/, "");
210
+ }
19
211
  var DepsService = class {
20
212
  packageManager;
21
213
  constructor() {
@@ -24,11 +216,11 @@ var DepsService = class {
24
216
  findLockFile(dir) {
25
217
  const lockFiles = ["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lock"];
26
218
  for (const file of lockFiles) {
27
- if (fs3__default.existsSync(path2.join(dir, file))) {
219
+ if (fs4__default.existsSync(path3.join(dir, file))) {
28
220
  return file;
29
221
  }
30
222
  }
31
- const parentDir = path2.resolve(dir, "..");
223
+ const parentDir = path3.resolve(dir, "..");
32
224
  if (parentDir !== dir) {
33
225
  return this.findLockFile(parentDir);
34
226
  }
@@ -65,13 +257,13 @@ var DepsService = class {
65
257
  }
66
258
  async checkDependencies(dependencies) {
67
259
  try {
68
- const packageJsonPath = path2.join(process.cwd(), "package.json");
260
+ const packageJsonPath = path3.join(process.cwd(), "package.json");
69
261
  try {
70
- await fs4.access(packageJsonPath);
262
+ await fs.access(packageJsonPath);
71
263
  } catch {
72
264
  return "No package.json file found in the current directory";
73
265
  }
74
- const packageJson = JSON.parse(await fs4.readFile(packageJsonPath, "utf-8"));
266
+ const packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf-8"));
75
267
  for (const dependency of dependencies) {
76
268
  if (!packageJson.dependencies || !packageJson.dependencies[dependency]) {
77
269
  return `Please install ${dependency} before running this command (${this.packageManager} install ${dependency})`;
@@ -85,8 +277,8 @@ var DepsService = class {
85
277
  }
86
278
  async getProjectName() {
87
279
  try {
88
- const packageJsonPath = path2.join(process.cwd(), "package.json");
89
- const packageJson = await fs4.readFile(packageJsonPath, "utf-8");
280
+ const packageJsonPath = path3.join(process.cwd(), "package.json");
281
+ const packageJson = await fs.readFile(packageJsonPath, "utf-8");
90
282
  const pkg = JSON.parse(packageJson);
91
283
  return pkg.name;
92
284
  } catch (err) {
@@ -96,56 +288,19 @@ var DepsService = class {
96
288
  async getPackageVersion() {
97
289
  const __filename = fileURLToPath(import.meta.url);
98
290
  const __dirname = dirname(__filename);
99
- const pkgJsonPath = path2.join(__dirname, "..", "package.json");
291
+ const pkgJsonPath = path3.join(__dirname, "..", "package.json");
100
292
  const content = await fsExtra3.readJSON(pkgJsonPath);
101
293
  return content.version;
102
294
  }
103
295
  async addScriptsToPackageJson(scripts) {
104
- const packageJson = JSON.parse(await fs4.readFile("package.json", "utf-8"));
296
+ const packageJson = JSON.parse(await fs.readFile("package.json", "utf-8"));
105
297
  packageJson.scripts = {
106
298
  ...packageJson.scripts,
107
299
  ...scripts
108
300
  };
109
- await fs4.writeFile("package.json", JSON.stringify(packageJson, null, 2));
301
+ await fs.writeFile("package.json", JSON.stringify(packageJson, null, 2));
110
302
  }
111
303
  };
112
-
113
- // src/commands/utils.ts
114
- function getPackageManager() {
115
- const userAgent = process.env.npm_config_user_agent || "";
116
- const execPath = process.env.npm_execpath || "";
117
- if (userAgent.includes("yarn")) {
118
- return "yarn";
119
- }
120
- if (userAgent.includes("pnpm")) {
121
- return "pnpm";
122
- }
123
- if (userAgent.includes("npm")) {
124
- return "npm";
125
- }
126
- if (execPath.includes("yarn")) {
127
- return "yarn";
128
- }
129
- if (execPath.includes("pnpm")) {
130
- return "pnpm";
131
- }
132
- if (execPath.includes("npm")) {
133
- return "npm";
134
- }
135
- return "npm";
136
- }
137
- function getPackageManagerInstallCommand(pm) {
138
- switch (pm) {
139
- case "npm":
140
- return "install";
141
- case "yarn":
142
- return "add";
143
- case "pnpm":
144
- return "add";
145
- default:
146
- return "install";
147
- }
148
- }
149
304
  var args = ["-y", "@mastra/mcp-docs-server"];
150
305
  var createMcpConfig = (editor) => {
151
306
  if (editor === "vscode") {
@@ -198,19 +353,19 @@ async function writeMergedConfig(configPath, editor) {
198
353
  spaces: 2
199
354
  });
200
355
  }
201
- var windsurfGlobalMCPConfigPath = path2.join(os.homedir(), ".codeium", "windsurf", "mcp_config.json");
202
- var cursorGlobalMCPConfigPath = path2.join(os.homedir(), ".cursor", "mcp.json");
203
- path2.join(process.cwd(), ".vscode", "mcp.json");
204
- var vscodeGlobalMCPConfigPath = path2.join(
356
+ var windsurfGlobalMCPConfigPath = path3.join(os.homedir(), ".codeium", "windsurf", "mcp_config.json");
357
+ var cursorGlobalMCPConfigPath = path3.join(os.homedir(), ".cursor", "mcp.json");
358
+ path3.join(process.cwd(), ".vscode", "mcp.json");
359
+ var vscodeGlobalMCPConfigPath = path3.join(
205
360
  os.homedir(),
206
- process.platform === "win32" ? path2.join("AppData", "Roaming", "Code", "User", "settings.json") : process.platform === "darwin" ? path2.join("Library", "Application Support", "Code", "User", "settings.json") : path2.join(".config", "Code", "User", "settings.json")
361
+ 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")
207
362
  );
208
363
  async function installMastraDocsMCPServer({ editor, directory }) {
209
364
  if (editor === `cursor`) {
210
- await writeMergedConfig(path2.join(directory, ".cursor", "mcp.json"), "cursor");
365
+ await writeMergedConfig(path3.join(directory, ".cursor", "mcp.json"), "cursor");
211
366
  }
212
367
  if (editor === `vscode`) {
213
- await writeMergedConfig(path2.join(directory, ".vscode", "mcp.json"), "vscode");
368
+ await writeMergedConfig(path3.join(directory, ".vscode", "mcp.json"), "vscode");
214
369
  }
215
370
  if (editor === `cursor-global`) {
216
371
  const alreadyInstalled = await globalMCPIsAlreadyInstalled(editor);
@@ -272,7 +427,7 @@ var FileEnvService = class extends EnvService {
272
427
  }
273
428
  readFile(filePath) {
274
429
  return new Promise((resolve, reject) => {
275
- fs3.readFile(filePath, "utf8", (err, data) => {
430
+ fs4.readFile(filePath, "utf8", (err, data) => {
276
431
  if (err) reject(err);
277
432
  else resolve(data);
278
433
  });
@@ -280,7 +435,7 @@ var FileEnvService = class extends EnvService {
280
435
  }
281
436
  writeFile({ filePath, data }) {
282
437
  return new Promise((resolve, reject) => {
283
- fs3.writeFile(filePath, data, "utf8", (err) => {
438
+ fs4.writeFile(filePath, data, "utf8", (err) => {
284
439
  if (err) reject(err);
285
440
  else resolve();
286
441
  });
@@ -335,10 +490,10 @@ var FileService = class {
335
490
  */
336
491
  async copyStarterFile(inputFile, outputFilePath, replaceIfExists) {
337
492
  const __filename = fileURLToPath(import.meta.url);
338
- const __dirname = path2.dirname(__filename);
339
- const filePath = path2.resolve(__dirname, "starter-files", inputFile);
340
- const fileString = fs3__default.readFileSync(filePath, "utf8");
341
- if (fs3__default.existsSync(outputFilePath) && !replaceIfExists) {
493
+ const __dirname = path3.dirname(__filename);
494
+ const filePath = path3.resolve(__dirname, "starter-files", inputFile);
495
+ const fileString = fs4__default.readFileSync(filePath, "utf8");
496
+ if (fs4__default.existsSync(outputFilePath) && !replaceIfExists) {
342
497
  console.log(`${outputFilePath} already exists`);
343
498
  return false;
344
499
  }
@@ -346,14 +501,14 @@ var FileService = class {
346
501
  return true;
347
502
  }
348
503
  async setupEnvFile({ dbUrl }) {
349
- const envPath = path2.join(process.cwd(), ".env.development");
504
+ const envPath = path3.join(process.cwd(), ".env.development");
350
505
  await fsExtra3.ensureFile(envPath);
351
506
  const fileEnvService = new FileEnvService(envPath);
352
507
  await fileEnvService.setEnvValue("DB_URL", dbUrl);
353
508
  }
354
509
  getFirstExistingFile(files) {
355
510
  for (const f of files) {
356
- if (fs3__default.existsSync(f)) {
511
+ if (fs4__default.existsSync(f)) {
357
512
  return f;
358
513
  }
359
514
  }
@@ -363,20 +518,16 @@ var FileService = class {
363
518
  filePath,
364
519
  replacements
365
520
  }) {
366
- let fileContent = fs3__default.readFileSync(filePath, "utf8");
521
+ let fileContent = fs4__default.readFileSync(filePath, "utf8");
367
522
  replacements.forEach(({ search, replace }) => {
368
523
  fileContent = fileContent.replaceAll(search, replace);
369
524
  });
370
- fs3__default.writeFileSync(filePath, fileContent);
525
+ fs4__default.writeFileSync(filePath, fileContent);
371
526
  }
372
527
  };
373
- var logger = new PinoLogger({
374
- name: "Mastra CLI",
375
- level: "info"
376
- });
377
528
 
378
529
  // src/commands/init/utils.ts
379
- var exec = util.promisify(child_process.exec);
530
+ var exec2 = util.promisify(child_process.exec);
380
531
  var getAISDKPackage = (llmProvider) => {
381
532
  switch (llmProvider) {
382
533
  case "openai":
@@ -453,8 +604,8 @@ export const weatherAgent = new Agent({
453
604
  parser: "typescript",
454
605
  singleQuote: true
455
606
  });
456
- await fs4.writeFile(destPath, "");
457
- await fs4.writeFile(destPath, formattedContent);
607
+ await fs.writeFile(destPath, "");
608
+ await fs.writeFile(destPath, formattedContent);
458
609
  }
459
610
  async function writeWorkflowSample(destPath) {
460
611
  const content = `import { createStep, createWorkflow } from '@mastra/core/workflows';
@@ -647,7 +798,7 @@ export { weatherWorkflow };`;
647
798
  semi: true,
648
799
  singleQuote: true
649
800
  });
650
- await fs4.writeFile(destPath, formattedContent);
801
+ await fs.writeFile(destPath, formattedContent);
651
802
  }
652
803
  async function writeToolSample(destPath) {
653
804
  const fileService = new FileService();
@@ -676,15 +827,15 @@ var writeIndexFile = async ({
676
827
  addWorkflow
677
828
  }) => {
678
829
  const indexPath = dirPath + "/index.ts";
679
- const destPath = path2.join(indexPath);
830
+ const destPath = path3.join(indexPath);
680
831
  try {
681
- await fs4.writeFile(destPath, "");
832
+ await fs.writeFile(destPath, "");
682
833
  const filteredExports = [
683
834
  addWorkflow ? `workflows: { weatherWorkflow },` : "",
684
835
  addAgent ? `agents: { weatherAgent },` : ""
685
836
  ].filter(Boolean);
686
837
  if (!addExample) {
687
- await fs4.writeFile(
838
+ await fs.writeFile(
688
839
  destPath,
689
840
  `
690
841
  import { Mastra } from '@mastra/core';
@@ -694,7 +845,7 @@ export const mastra = new Mastra()
694
845
  );
695
846
  return;
696
847
  }
697
- await fs4.writeFile(
848
+ await fs.writeFile(
698
849
  destPath,
699
850
  `
700
851
  import { Mastra } from '@mastra/core/mastra';
@@ -736,16 +887,16 @@ var checkAndInstallCoreDeps = async (addExample) => {
736
887
  var spinner = yoctoSpinner({ text: "Installing Mastra core dependencies\n" });
737
888
  async function installCoreDeps(pkg) {
738
889
  try {
739
- const confirm2 = await p.confirm({
890
+ const confirm2 = await p2.confirm({
740
891
  message: `You do not have the ${pkg} package installed. Would you like to install it?`,
741
892
  initialValue: false
742
893
  });
743
- if (p.isCancel(confirm2)) {
744
- p.cancel("Installation Cancelled");
894
+ if (p2.isCancel(confirm2)) {
895
+ p2.cancel("Installation Cancelled");
745
896
  process.exit(0);
746
897
  }
747
898
  if (!confirm2) {
748
- p.cancel("Installation Cancelled");
899
+ p2.cancel("Installation Cancelled");
749
900
  process.exit(0);
750
901
  }
751
902
  spinner.start();
@@ -782,13 +933,13 @@ var writeAPIKey = async ({
782
933
  const key = await getAPIKey(provider);
783
934
  const escapedKey = shellQuote.quote([key]);
784
935
  const escapedApiKey = shellQuote.quote([apiKey]);
785
- await exec(`echo ${escapedKey}=${escapedApiKey} >> .env`);
936
+ await exec2(`echo ${escapedKey}=${escapedApiKey} >> .env`);
786
937
  };
787
938
  var createMastraDir = async (directory) => {
788
939
  let dir = directory.trim().split("/").filter((item) => item !== "");
789
- const dirPath = path2.join(process.cwd(), ...dir, "mastra");
940
+ const dirPath = path3.join(process.cwd(), ...dir, "mastra");
790
941
  try {
791
- await fs4.access(dirPath);
942
+ await fs.access(dirPath);
792
943
  return { ok: false };
793
944
  } catch {
794
945
  await fsExtra3.ensureDir(dirPath);
@@ -804,15 +955,15 @@ var writeCodeSample = async (dirPath, component, llmProvider, importComponents)
804
955
  }
805
956
  };
806
957
  var interactivePrompt = async () => {
807
- p.intro(color2.inverse(" Mastra Init "));
808
- const mastraProject = await p.group(
958
+ p2.intro(color2.inverse(" Mastra Init "));
959
+ const mastraProject = await p2.group(
809
960
  {
810
- directory: () => p.text({
961
+ directory: () => p2.text({
811
962
  message: "Where should we create the Mastra files? (default: src/)",
812
963
  placeholder: "src/",
813
964
  defaultValue: "src/"
814
965
  }),
815
- llmProvider: () => p.select({
966
+ llmProvider: () => p2.select({
816
967
  message: "Select default provider:",
817
968
  options: [
818
969
  { value: "openai", label: "OpenAI", hint: "recommended" },
@@ -823,7 +974,7 @@ var interactivePrompt = async () => {
823
974
  ]
824
975
  }),
825
976
  llmApiKey: async ({ results: { llmProvider } }) => {
826
- const keyChoice = await p.select({
977
+ const keyChoice = await p2.select({
827
978
  message: `Enter your ${llmProvider} API key?`,
828
979
  options: [
829
980
  { value: "skip", label: "Skip for now", hint: "default" },
@@ -832,7 +983,7 @@ var interactivePrompt = async () => {
832
983
  initialValue: "skip"
833
984
  });
834
985
  if (keyChoice === "enter") {
835
- return p.text({
986
+ return p2.text({
836
987
  message: "Enter your API key:",
837
988
  placeholder: "sk-..."
838
989
  });
@@ -843,7 +994,7 @@ var interactivePrompt = async () => {
843
994
  const windsurfIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`windsurf`);
844
995
  const cursorIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`cursor`);
845
996
  const vscodeIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`vscode`);
846
- const editor = await p.select({
997
+ const editor = await p2.select({
847
998
  message: `Make your AI IDE into a Mastra expert? (installs Mastra docs MCP server)`,
848
999
  options: [
849
1000
  { value: "skip", label: "Skip for now", hint: "default" },
@@ -871,24 +1022,24 @@ var interactivePrompt = async () => {
871
1022
  });
872
1023
  if (editor === `skip`) return void 0;
873
1024
  if (editor === `windsurf` && windsurfIsAlreadyInstalled) {
874
- p.log.message(`
1025
+ p2.log.message(`
875
1026
  Windsurf is already installed, skipping.`);
876
1027
  return void 0;
877
1028
  }
878
1029
  if (editor === `vscode` && vscodeIsAlreadyInstalled) {
879
- p.log.message(`
1030
+ p2.log.message(`
880
1031
  VSCode is already installed, skipping.`);
881
1032
  return void 0;
882
1033
  }
883
1034
  if (editor === `cursor`) {
884
- p.log.message(
1035
+ p2.log.message(
885
1036
  `
886
1037
  Note: you will need to go into Cursor Settings -> MCP Settings and manually enable the installed Mastra MCP server.
887
1038
  `
888
1039
  );
889
1040
  }
890
1041
  if (editor === `cursor-global`) {
891
- const confirm2 = await p.select({
1042
+ const confirm2 = await p2.select({
892
1043
  message: `Global install will add/update ${cursorGlobalMCPConfigPath} and make the Mastra docs MCP server available in all your Cursor projects. Continue?`,
893
1044
  options: [
894
1045
  { value: "yes", label: "Yes, I understand" },
@@ -900,7 +1051,7 @@ Note: you will need to go into Cursor Settings -> MCP Settings and manually enab
900
1051
  }
901
1052
  }
902
1053
  if (editor === `windsurf`) {
903
- const confirm2 = await p.select({
1054
+ const confirm2 = await p2.select({
904
1055
  message: `Windsurf only supports a global MCP config (at ${windsurfGlobalMCPConfigPath}) is it ok to add/update that global config?
905
1056
  This means the Mastra docs MCP server will be available in all your Windsurf projects.`,
906
1057
  options: [
@@ -917,7 +1068,7 @@ This means the Mastra docs MCP server will be available in all your Windsurf pro
917
1068
  },
918
1069
  {
919
1070
  onCancel: () => {
920
- p.cancel("Operation cancelled.");
1071
+ p2.cancel("Operation cancelled.");
921
1072
  process.exit(0);
922
1073
  }
923
1074
  }
@@ -926,7 +1077,7 @@ This means the Mastra docs MCP server will be available in all your Windsurf pro
926
1077
  };
927
1078
  var checkPkgJson = async () => {
928
1079
  const cwd = process.cwd();
929
- const pkgJsonPath = path2.join(cwd, "package.json");
1080
+ const pkgJsonPath = path3.join(cwd, "package.json");
930
1081
  let isPkgJsonPresent = false;
931
1082
  try {
932
1083
  await fsExtra3.readJSON(pkgJsonPath);
@@ -942,8 +1093,8 @@ var checkPkgJson = async () => {
942
1093
  };
943
1094
 
944
1095
  // src/commands/init/init.ts
945
- var s = p.spinner();
946
- var exec2 = util.promisify(child_process.exec);
1096
+ var s = p2.spinner();
1097
+ var exec3 = util.promisify(child_process.exec);
947
1098
  var init = async ({
948
1099
  directory,
949
1100
  addExample = false,
@@ -995,7 +1146,7 @@ var init = async ({
995
1146
  const depsService = new DepsService();
996
1147
  const pm = depsService.packageManager;
997
1148
  const installCommand = getPackageManagerInstallCommand(pm);
998
- await exec2(`${pm} ${installCommand} ${aiSdkPackage}`);
1149
+ await exec3(`${pm} ${installCommand} ${aiSdkPackage}`);
999
1150
  if (configureEditorWithDocsMCP) {
1000
1151
  await installMastraDocsMCPServer({
1001
1152
  editor: configureEditorWithDocsMCP,
@@ -1004,14 +1155,14 @@ var init = async ({
1004
1155
  }
1005
1156
  s.stop();
1006
1157
  if (!llmApiKey) {
1007
- p.note(`
1158
+ p2.note(`
1008
1159
  ${color2.green("Mastra initialized successfully!")}
1009
1160
 
1010
1161
  Add your ${color2.cyan(key)} as an environment variable
1011
1162
  in your ${color2.cyan(".env")} file
1012
1163
  `);
1013
1164
  } else {
1014
- p.note(`
1165
+ p2.note(`
1015
1166
  ${color2.green("Mastra initialized successfully!")}
1016
1167
  `);
1017
1168
  }
@@ -1022,10 +1173,10 @@ var init = async ({
1022
1173
  return { success: false };
1023
1174
  }
1024
1175
  };
1025
- var exec3 = util.promisify(child_process.exec);
1176
+ var exec4 = util.promisify(child_process.exec);
1026
1177
  var execWithTimeout = async (command, timeoutMs) => {
1027
1178
  try {
1028
- const promise = exec3(command, { killSignal: "SIGTERM" });
1179
+ const promise = exec4(command, { killSignal: "SIGTERM" });
1029
1180
  if (!timeoutMs) {
1030
1181
  return await promise;
1031
1182
  }
@@ -1075,21 +1226,21 @@ var createMastraProject = async ({
1075
1226
  createVersionTag,
1076
1227
  timeout
1077
1228
  }) => {
1078
- p.intro(color2.inverse(" Mastra Create "));
1079
- const projectName = name ?? await p.text({
1229
+ p2.intro(color2.inverse(" Mastra Create "));
1230
+ const projectName = name ?? await p2.text({
1080
1231
  message: "What do you want to name your project?",
1081
1232
  placeholder: "my-mastra-app",
1082
1233
  defaultValue: "my-mastra-app"
1083
1234
  });
1084
- if (p.isCancel(projectName)) {
1085
- p.cancel("Operation cancelled");
1235
+ if (p2.isCancel(projectName)) {
1236
+ p2.cancel("Operation cancelled");
1086
1237
  process.exit(0);
1087
1238
  }
1088
- const s2 = p.spinner();
1239
+ const s2 = p2.spinner();
1089
1240
  try {
1090
1241
  s2.start("Creating project");
1091
1242
  try {
1092
- await fs4.mkdir(projectName);
1243
+ await fs.mkdir(projectName);
1093
1244
  } catch (error) {
1094
1245
  if (error instanceof Error && "code" in error && error.code === "EEXIST") {
1095
1246
  s2.stop(`A directory named "${projectName}" already exists. Please choose a different name.`);
@@ -1104,9 +1255,9 @@ var createMastraProject = async ({
1104
1255
  const installCommand = getPackageManagerInstallCommand(pm);
1105
1256
  s2.message("Initializing project structure");
1106
1257
  try {
1107
- await exec3(`npm init -y`);
1108
- await exec3(`npm pkg set type="module"`);
1109
- await exec3(`npm pkg set engines.node=">=20.9.0"`);
1258
+ await exec4(`npm init -y`);
1259
+ await exec4(`npm pkg set type="module"`);
1260
+ await exec4(`npm pkg set engines.node=">=20.9.0"`);
1110
1261
  const depsService = new DepsService();
1111
1262
  await depsService.addScriptsToPackageJson({
1112
1263
  dev: "mastra dev",
@@ -1121,9 +1272,9 @@ var createMastraProject = async ({
1121
1272
  s2.stop("Project structure created");
1122
1273
  s2.start(`Installing ${pm} dependencies`);
1123
1274
  try {
1124
- await exec3(`${pm} ${installCommand} zod@^3`);
1125
- await exec3(`${pm} ${installCommand} typescript @types/node --save-dev`);
1126
- await exec3(`echo '{
1275
+ await exec4(`${pm} ${installCommand} zod@^3`);
1276
+ await exec4(`${pm} ${installCommand} typescript @types/node --save-dev`);
1277
+ await exec4(`echo '{
1127
1278
  "compilerOptions": {
1128
1279
  "target": "ES2022",
1129
1280
  "module": "ES2022",
@@ -1166,31 +1317,35 @@ var createMastraProject = async ({
1166
1317
  s2.stop("Mastra dependencies installed");
1167
1318
  s2.start("Adding .gitignore");
1168
1319
  try {
1169
- await exec3(`echo output.txt >> .gitignore`);
1170
- await exec3(`echo node_modules >> .gitignore`);
1171
- await exec3(`echo dist >> .gitignore`);
1172
- await exec3(`echo .mastra >> .gitignore`);
1173
- await exec3(`echo .env.development >> .gitignore`);
1174
- await exec3(`echo .env >> .gitignore`);
1175
- await exec3(`echo *.db >> .gitignore`);
1176
- await exec3(`echo *.db-* >> .gitignore`);
1320
+ await exec4(`echo output.txt >> .gitignore`);
1321
+ await exec4(`echo node_modules >> .gitignore`);
1322
+ await exec4(`echo dist >> .gitignore`);
1323
+ await exec4(`echo .mastra >> .gitignore`);
1324
+ await exec4(`echo .env.development >> .gitignore`);
1325
+ await exec4(`echo .env >> .gitignore`);
1326
+ await exec4(`echo *.db >> .gitignore`);
1327
+ await exec4(`echo *.db-* >> .gitignore`);
1177
1328
  } catch (error) {
1178
1329
  throw new Error(`Failed to create .gitignore: ${error instanceof Error ? error.message : "Unknown error"}`);
1179
1330
  }
1180
1331
  s2.stop(".gitignore added");
1181
- p.outro("Project created successfully");
1332
+ p2.outro("Project created successfully");
1182
1333
  console.log("");
1183
1334
  return { projectName };
1184
1335
  } catch (error) {
1185
1336
  s2.stop();
1186
1337
  const errorMessage = error instanceof Error ? error.message : "An unexpected error occurred";
1187
- p.cancel(`Project creation failed: ${errorMessage}`);
1338
+ p2.cancel(`Project creation failed: ${errorMessage}`);
1188
1339
  process.exit(1);
1189
1340
  }
1190
1341
  };
1191
1342
 
1192
1343
  // src/commands/create/create.ts
1193
1344
  var create = async (args2) => {
1345
+ if (args2.template !== void 0) {
1346
+ await createFromTemplate(args2);
1347
+ return;
1348
+ }
1194
1349
  const { projectName } = await createMastraProject({
1195
1350
  projectName: args2?.projectName,
1196
1351
  createVersionTag: args2?.createVersionTag,
@@ -1199,6 +1354,13 @@ var create = async (args2) => {
1199
1354
  const directory = args2.directory || "src/";
1200
1355
  if (args2.components === void 0 || args2.llmProvider === void 0 || args2.addExample === void 0) {
1201
1356
  const result = await interactivePrompt();
1357
+ const analytics2 = getAnalytics();
1358
+ if (analytics2 && result?.llmProvider) {
1359
+ analytics2.trackEvent("cli_model_provider_selected", {
1360
+ provider: result.llmProvider,
1361
+ selection_method: "interactive"
1362
+ });
1363
+ }
1202
1364
  await init({
1203
1365
  ...result,
1204
1366
  llmApiKey: result?.llmApiKey,
@@ -1209,6 +1371,13 @@ var create = async (args2) => {
1209
1371
  return;
1210
1372
  }
1211
1373
  const { components = [], llmProvider = "openai", addExample = false, llmApiKey } = args2;
1374
+ const analytics = getAnalytics();
1375
+ if (analytics) {
1376
+ analytics.trackEvent("cli_model_provider_selected", {
1377
+ provider: llmProvider,
1378
+ selection_method: "cli_args"
1379
+ });
1380
+ }
1212
1381
  await init({
1213
1382
  directory,
1214
1383
  components,
@@ -1221,12 +1390,71 @@ var create = async (args2) => {
1221
1390
  };
1222
1391
  var postCreate = ({ projectName }) => {
1223
1392
  const packageManager = getPackageManager();
1224
- p.outro(`
1393
+ p2.outro(`
1225
1394
  ${color2.green("To start your project:")}
1226
1395
 
1227
1396
  ${color2.cyan("cd")} ${projectName}
1228
1397
  ${color2.cyan(`${packageManager} run dev`)}
1229
1398
  `);
1230
1399
  };
1400
+ async function createFromTemplate(args2) {
1401
+ const templates = await loadTemplates();
1402
+ let selectedTemplate;
1403
+ if (args2.template === true) {
1404
+ selectedTemplate = await selectTemplate(templates);
1405
+ if (!selectedTemplate) {
1406
+ p2.log.info("No template selected. Exiting.");
1407
+ return;
1408
+ }
1409
+ } else if (args2.template) {
1410
+ selectedTemplate = findTemplateByName(templates, args2.template);
1411
+ if (!selectedTemplate) {
1412
+ p2.log.error(`Template "${args2.template}" not found. Available templates:`);
1413
+ templates.forEach((t) => p2.log.info(` - ${t.title} (use: ${t.slug.replace("template-", "")})`));
1414
+ throw new Error(`Template "${args2.template}" not found`);
1415
+ }
1416
+ }
1417
+ if (!selectedTemplate) {
1418
+ throw new Error("No template selected");
1419
+ }
1420
+ let projectName = args2.projectName;
1421
+ if (!projectName) {
1422
+ const defaultName = getDefaultProjectName(selectedTemplate);
1423
+ const response = await p2.text({
1424
+ message: "What is your project name?",
1425
+ defaultValue: defaultName,
1426
+ placeholder: defaultName
1427
+ });
1428
+ if (p2.isCancel(response)) {
1429
+ p2.log.info("Project creation cancelled.");
1430
+ return;
1431
+ }
1432
+ projectName = response;
1433
+ }
1434
+ try {
1435
+ const analytics = getAnalytics();
1436
+ if (analytics) {
1437
+ analytics.trackEvent("cli_template_used", {
1438
+ template_slug: selectedTemplate.slug,
1439
+ template_title: selectedTemplate.title
1440
+ });
1441
+ }
1442
+ const projectPath = await cloneTemplate({
1443
+ template: selectedTemplate,
1444
+ projectName
1445
+ });
1446
+ await installDependencies(projectPath);
1447
+ p2.note(`
1448
+ ${color2.green("Mastra template installed!")}
1449
+
1450
+ Add the necessary environment
1451
+ variables in your ${color2.cyan(".env")} file
1452
+ `);
1453
+ postCreate({ projectName });
1454
+ } catch (error) {
1455
+ p2.log.error(`Failed to create project from template: ${error instanceof Error ? error.message : "Unknown error"}`);
1456
+ throw error;
1457
+ }
1458
+ }
1231
1459
 
1232
1460
  export { DepsService, FileService, checkAndInstallCoreDeps, checkPkgJson, create, init, interactivePrompt, logger };