motia 0.17.10-beta.192 → 0.17.11-beta.193

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.
@@ -0,0 +1,7 @@
1
+ import { createRequire } from "node:module";
2
+
3
+ //#region rolldown:runtime
4
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
5
+
6
+ //#endregion
7
+ export { __require };
@@ -1,5 +1,6 @@
1
1
  import { version } from "../version.mjs";
2
2
  import { executeCommand } from "../utils/execute-command.mjs";
3
+ import { getInstallCommands, getInstallSaveCommands } from "../utils/build-npm-command.mjs";
3
4
  import { checkIfDirectoryExists, checkIfFileExists } from "./utils.mjs";
4
5
  import { getPackageManager, getPackageManagerFromEnv } from "../utils/get-package-manager.mjs";
5
6
  import { generateTypes } from "../generate-types.mjs";
@@ -16,12 +17,7 @@ import { fileURLToPath } from "url";
16
17
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
17
18
  const installRequiredDependencies = async (packageManager, rootDir, context) => {
18
19
  context.log("installing-dependencies", (message) => message.tag("info").append("Installing dependencies..."));
19
- const installCommand = {
20
- npm: "npm install --save",
21
- yarn: "yarn add",
22
- pnpm: "pnpm add",
23
- bun: "bun add"
24
- }[packageManager];
20
+ const installCommand = getInstallSaveCommands(rootDir)[packageManager];
25
21
  const dependencies = [
26
22
  `motia@${version}`,
27
23
  "zod@4.1.12",
@@ -166,12 +162,8 @@ const create = async ({ projectName, template, cursorEnabled, context, skipRedis
166
162
  } else {
167
163
  packageManager = await preparePackageManager(rootDir, context, true);
168
164
  context.log("installing-plugin-dependencies", (message) => message.tag("info").append("Installing plugin dependencies..."));
169
- const installCommand = {
170
- npm: "npm install",
171
- yarn: "yarn",
172
- pnpm: "pnpm install",
173
- bun: "bun install"
174
- }[packageManager];
165
+ const installCommands = { ...getInstallCommands(rootDir) };
166
+ const installCommand = installCommands[packageManager] || installCommands["npm"];
175
167
  try {
176
168
  await executeCommand(installCommand, rootDir);
177
169
  context.log("plugin-dependencies-installed", (message) => message.tag("success").append("Plugin dependencies installed"));
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["packageManager: string"],"sources":["../../src/create/index.ts"],"sourcesContent":["import fs from 'fs'\nimport path from 'path'\nimport pc from 'picocolors'\nimport { fileURLToPath } from 'url'\nimport type { CliContext, Message } from '../cloud/config-utils'\nimport { generateTypes } from '../generate-types'\nimport { pythonInstall } from '../install'\nimport { pluginDependencies } from '../plugins/plugin-dependencies'\nimport { executeCommand } from '../utils/execute-command'\nimport { getPackageManager, getPackageManagerFromEnv } from '../utils/get-package-manager'\nimport { version } from '../version'\nimport { pullRules } from './pull-rules'\nimport { setupTemplate } from './setup-template'\nimport { checkIfDirectoryExists, checkIfFileExists } from './utils'\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url))\n\nconst installRequiredDependencies = async (packageManager: string, rootDir: string, context: CliContext) => {\n context.log('installing-dependencies', (message: Message) => message.tag('info').append('Installing dependencies...'))\n\n const installCommand = {\n npm: 'npm install --save',\n yarn: 'yarn add',\n pnpm: 'pnpm add',\n bun: 'bun add',\n }[packageManager]\n\n const dependencies = [\n `motia@${version}`,\n 'zod@4.1.12',\n `@motiadev/adapter-bullmq-events@${version}`,\n ...pluginDependencies.map((dep: string) => `${dep}@${version}`),\n ].join(' ')\n\n const devDependencies = [\n 'ts-node@10.9.2',\n 'typescript@5.7.3',\n '@types/react@19.1.1',\n `@motiadev/workbench@${version}`,\n ].join(' ')\n\n try {\n await executeCommand(`${installCommand} ${dependencies}`, rootDir)\n await executeCommand(`${installCommand} -D ${devDependencies}`, rootDir)\n\n context.log('dependencies-installed', (message: Message) => message.tag('success').append('Dependencies installed'))\n } catch (error) {\n console.error('❌ Failed to install dependencies:', error)\n }\n}\n\nconst preparePackageManager = async (rootDir: string, context: CliContext, detectFromParent = false) => {\n const detectionDir = detectFromParent ? process.cwd() : rootDir\n const envPackageManager = getPackageManagerFromEnv()\n const packageManager = getPackageManager(detectionDir)\n\n const isFallback =\n !envPackageManager && packageManager === 'npm' && !checkIfFileExists(detectionDir, 'package-lock.json')\n\n if (isFallback) {\n context.log('package-manager-using-default', (message: Message) =>\n message.tag('info').append('Using default package manager').append(packageManager, 'gray'),\n )\n } else {\n context.log('package-manager-detected', (message: Message) =>\n message.tag('info').append('Detected package manager').append(packageManager, 'gray'),\n )\n }\n\n return packageManager\n}\n\nconst installNodeDependencies = async (rootDir: string, context: CliContext) => {\n const packageManager = await preparePackageManager(rootDir, context)\n\n await installRequiredDependencies(packageManager, rootDir, context).catch((error: unknown) => {\n context.log('failed-to-install-dependencies', (message: Message) =>\n message.tag('failed').append('Failed to install dependencies'),\n )\n console.error(error)\n })\n\n return packageManager\n}\n\ntype Args = {\n projectName: string\n template: string\n cursorEnabled: boolean\n context: CliContext\n skipTutorialTemplates?: boolean\n skipRedis?: boolean\n}\n\nexport const create = async ({\n projectName,\n template,\n cursorEnabled,\n context,\n skipRedis = false,\n}: Args): Promise<void> => {\n console.log(\n '\\n\\n' +\n `\n _____ ______ ______ ______\n /'\\\\_/\\`\\\\/\\\\ __\\`\\\\/\\\\__ _\\\\/\\\\__ _\\\\ /\\\\ _ \\\\\n /\\\\ \\\\ \\\\ \\\\/\\\\ \\\\/_/\\\\ \\\\/\\\\/_/\\\\ \\\\/ \\\\ \\\\ \\\\L\\\\ \\\\\n \\\\ \\\\ \\\\__\\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ __ \\\\\n \\\\ \\\\ \\\\_/\\\\ \\\\ \\\\ \\\\_\\\\ \\\\ \\\\ \\\\ \\\\ \\\\_\\\\ \\\\__\\\\ \\\\ \\\\/\\\\ \\\\\n \\\\ \\\\_\\\\\\\\ \\\\_\\\\ \\\\_____\\\\ \\\\ \\\\_\\\\ /\\\\_____\\\\\\\\ \\\\_\\\\ \\\\_\\\\\n \\\\/_/ \\\\/_/\\\\/_____/ \\\\/_/ \\\\/_____/ \\\\/_/\\\\/_/\n ` +\n '\\n\\n',\n )\n\n const isCurrentDir = projectName === '.' || projectName === './' || projectName === '.\\\\'\n const rootDir = isCurrentDir ? process.cwd() : path.join(process.cwd(), projectName)\n const isPluginTemplate = template === 'plugin'\n\n process.env.REDISMS_DISABLE_POSTINSTALL = '1'\n if (!isCurrentDir && !checkIfDirectoryExists(rootDir)) {\n fs.mkdirSync(path.join(rootDir))\n context.log('directory-created', (message: Message) =>\n message.tag('success').append('Directory created ').append(projectName, 'gray'),\n )\n } else {\n context.log('directory-using', (message: Message) => message.tag('info').append('Using current directory'))\n }\n\n // Plugin template handles package.json differently (via template)\n if (!isPluginTemplate && !checkIfFileExists(rootDir, 'package.json')) {\n const finalProjectName =\n !projectName || projectName === '.' || projectName === './' || projectName === '.\\\\'\n ? path.basename(process.cwd())\n : projectName.trim()\n\n const packageJsonContent = {\n name: finalProjectName,\n description: '',\n type: 'module',\n scripts: {\n postinstall: 'motia install',\n dev: 'motia dev',\n start: 'motia start',\n 'generate-types': 'motia generate-types',\n build: 'motia build',\n clean: 'rm -rf dist node_modules python_modules .motia .mermaid',\n //'generate:config': 'motia get-config --output ./', TODO: doesnt work at the moment\n },\n keywords: ['motia'],\n }\n\n fs.writeFileSync(path.join(rootDir, 'package.json'), JSON.stringify(packageJsonContent, null, 2))\n\n context.log('package-json-created', (message: Message) =>\n message.tag('success').append('File').append('package.json', 'cyan').append('has been created.'),\n )\n } else if (!isPluginTemplate) {\n const packageJsonPath = path.join(rootDir, 'package.json')\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'))\n\n if (!packageJson.scripts) {\n packageJson.scripts = {}\n }\n\n if (!packageJson.scripts.dev) {\n packageJson.scripts.dev = 'motia dev'\n } else {\n packageJson.scripts.olddev = packageJson.scripts.dev\n packageJson.scripts.dev = 'motia dev'\n context.log('dev-command-already-exists', (message: Message) =>\n message.tag('warning').append('dev command already exists in package.json'),\n )\n }\n\n fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2))\n context.log('dev-command-updated', (message: Message) =>\n message\n .tag('success')\n .append('Updated')\n .append('dev', 'gray')\n .append('command to')\n .append('package.json', 'gray'),\n )\n }\n\n // Plugin template handles tsconfig.json via template\n if (!isPluginTemplate && !checkIfFileExists(rootDir, 'tsconfig.json')) {\n const tsconfigContent = {\n compilerOptions: {\n target: 'ES2020',\n module: 'ESNext',\n moduleResolution: 'bundler',\n allowImportingTsExtensions: true,\n noEmit: true,\n esModuleInterop: true,\n strict: true,\n skipLibCheck: true,\n forceConsistentCasingInFileNames: true,\n resolveJsonModule: true,\n allowJs: true,\n outDir: 'dist',\n rootDir: '.',\n baseUrl: '.',\n jsx: 'react-jsx',\n },\n include: ['**/*.ts', 'motia.config.ts', '**/*.tsx', 'types.d.ts', '**/*.jsx'],\n exclude: ['node_modules', 'dist', 'tests'],\n }\n\n fs.writeFileSync(path.join(rootDir, 'tsconfig.json'), JSON.stringify(tsconfigContent, null, 2))\n context.log('tsconfig-json-created', (message: Message) =>\n message.tag('success').append('File').append('tsconfig.json', 'cyan').append('has been created.'),\n )\n }\n\n // Plugin template handles .gitignore via template\n if (!isPluginTemplate && !checkIfFileExists(rootDir, '.gitignore')) {\n const gitignoreContent = [\n 'node_modules',\n 'python_modules',\n '.venv',\n 'venv',\n '.motia',\n '.mermaid',\n 'dist',\n '*.pyc',\n ].join('\\n')\n\n fs.writeFileSync(path.join(rootDir, '.gitignore'), gitignoreContent)\n context.log('gitignore-created', (message: Message) =>\n message.tag('success').append('File').append('.gitignore', 'cyan').append('has been created.'),\n )\n }\n\n // Skip cursor rules for plugin template\n if (!isPluginTemplate && cursorEnabled) {\n await pullRules({ force: true, rootDir }, context)\n }\n\n if (template) {\n await setupTemplate(template, rootDir, context)\n }\n\n if (!isPluginTemplate && skipRedis) {\n const motiaConfigPath = path.join(rootDir, 'motia.config.ts')\n\n const templatePath = path.join(__dirname, 'templates/motia.config.external-redis.ts.txt')\n const templateContent = fs.readFileSync(templatePath, 'utf-8')\n fs.writeFileSync(motiaConfigPath, templateContent)\n context.log('motia-config-created', (message: Message) =>\n message.tag('success').append('File').append('motia.config.ts', 'cyan').append('has been created.'),\n )\n }\n\n let packageManager: string\n if (!isPluginTemplate) {\n packageManager = await installNodeDependencies(rootDir, context)\n\n if (template.includes('python') || template.includes('multilang')) {\n await pythonInstall({ baseDir: rootDir })\n }\n\n await generateTypes(rootDir)\n } else {\n packageManager = await preparePackageManager(rootDir, context, true)\n\n context.log('installing-plugin-dependencies', (message: Message) =>\n message.tag('info').append('Installing plugin dependencies...'),\n )\n\n const installCommand = {\n npm: 'npm install',\n yarn: 'yarn',\n pnpm: 'pnpm install',\n bun: 'bun install',\n }[packageManager]\n\n try {\n await executeCommand(installCommand!, rootDir)\n context.log('plugin-dependencies-installed', (message: Message) =>\n message.tag('success').append('Plugin dependencies installed'),\n )\n } catch (error) {\n context.log('failed-to-install-plugin-dependencies', (message: Message) =>\n message.tag('failed').append('Failed to install plugin dependencies'),\n )\n console.error(error)\n }\n }\n\n const projectDirName = path.basename(rootDir)\n const devCommand = `${packageManager} run dev`\n const port = 3000\n const cdCommand = isCurrentDir ? '' : `${pc.cyan(`cd ${projectDirName}`)}\\n `\n\n context.log('success-blank', (message) => message.text(''))\n context.log('success-header', (message) =>\n message.text(`${pc.green('✨')} ${pc.bold('All set! Your project is ready to go.')}`),\n )\n context.log('success-blank-2', (message) => message.text(''))\n context.log('success-get-started', (message) => message.text('Get started:'))\n context.log('success-blank-3', (message) => message.text(''))\n context.log('success-commands', (message) => message.text(` ${cdCommand}${pc.cyan(devCommand)}`))\n context.log('success-blank-4', (message) => message.text(''))\n context.log('success-open', (message) => message.text(`Then open ${pc.cyan(`http://localhost:${port}`)}`))\n context.log('success-blank-5', (message: Message) => message.text(''))\n context.log('success-docs', (message) => message.text(`Docs: ${pc.cyan('https://www.motia.dev/docs')}`))\n context.log('success-blank-6', (message) => message.text(''))\n if (skipRedis) {\n context.log('redis-skip-warning', (message: Message) =>\n message\n .tag('warning')\n .append(\n '⚠️ You skipped Redis binary installation. Make sure to provide a Redis connection before running Motia.',\n ),\n )\n context.log('success-blank-7', (message) => message.text(''))\n }\n context.log('success-signoff', (message) => message.text('Happy coding! 🚀'))\n context.log('success-blank-8', (message) => message.text(''))\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["packageManager: string","installCommands: Record<string, string>"],"sources":["../../src/create/index.ts"],"sourcesContent":["import fs from 'fs'\nimport path from 'path'\nimport pc from 'picocolors'\nimport { fileURLToPath } from 'url'\nimport type { CliContext, Message } from '../cloud/config-utils'\nimport { generateTypes } from '../generate-types'\nimport { pythonInstall } from '../install'\nimport { pluginDependencies } from '../plugins/plugin-dependencies'\nimport { getInstallCommands, getInstallSaveCommands } from '../utils/build-npm-command'\nimport { executeCommand } from '../utils/execute-command'\nimport { getPackageManager, getPackageManagerFromEnv } from '../utils/get-package-manager'\nimport { version } from '../version'\nimport { pullRules } from './pull-rules'\nimport { setupTemplate } from './setup-template'\nimport { checkIfDirectoryExists, checkIfFileExists } from './utils'\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url))\n\nconst installRequiredDependencies = async (packageManager: string, rootDir: string, context: CliContext) => {\n context.log('installing-dependencies', (message: Message) => message.tag('info').append('Installing dependencies...'))\n\n const installCommand = getInstallSaveCommands(rootDir)[packageManager]\n\n const dependencies = [\n `motia@${version}`,\n 'zod@4.1.12',\n `@motiadev/adapter-bullmq-events@${version}`,\n ...pluginDependencies.map((dep: string) => `${dep}@${version}`),\n ].join(' ')\n\n const devDependencies = [\n 'ts-node@10.9.2',\n 'typescript@5.7.3',\n '@types/react@19.1.1',\n `@motiadev/workbench@${version}`,\n ].join(' ')\n\n try {\n await executeCommand(`${installCommand} ${dependencies}`, rootDir)\n await executeCommand(`${installCommand} -D ${devDependencies}`, rootDir)\n\n context.log('dependencies-installed', (message: Message) => message.tag('success').append('Dependencies installed'))\n } catch (error) {\n console.error('❌ Failed to install dependencies:', error)\n }\n}\n\nconst preparePackageManager = async (rootDir: string, context: CliContext, detectFromParent = false) => {\n const detectionDir = detectFromParent ? process.cwd() : rootDir\n const envPackageManager = getPackageManagerFromEnv()\n const packageManager = getPackageManager(detectionDir)\n\n const isFallback =\n !envPackageManager && packageManager === 'npm' && !checkIfFileExists(detectionDir, 'package-lock.json')\n\n if (isFallback) {\n context.log('package-manager-using-default', (message: Message) =>\n message.tag('info').append('Using default package manager').append(packageManager, 'gray'),\n )\n } else {\n context.log('package-manager-detected', (message: Message) =>\n message.tag('info').append('Detected package manager').append(packageManager, 'gray'),\n )\n }\n\n return packageManager\n}\n\nconst installNodeDependencies = async (rootDir: string, context: CliContext) => {\n const packageManager = await preparePackageManager(rootDir, context)\n\n await installRequiredDependencies(packageManager, rootDir, context).catch((error: unknown) => {\n context.log('failed-to-install-dependencies', (message: Message) =>\n message.tag('failed').append('Failed to install dependencies'),\n )\n console.error(error)\n })\n\n return packageManager\n}\n\ntype Args = {\n projectName: string\n template: string\n cursorEnabled: boolean\n context: CliContext\n skipTutorialTemplates?: boolean\n skipRedis?: boolean\n}\n\nexport const create = async ({\n projectName,\n template,\n cursorEnabled,\n context,\n skipRedis = false,\n}: Args): Promise<void> => {\n console.log(\n '\\n\\n' +\n `\n _____ ______ ______ ______\n /'\\\\_/\\`\\\\/\\\\ __\\`\\\\/\\\\__ _\\\\/\\\\__ _\\\\ /\\\\ _ \\\\\n /\\\\ \\\\ \\\\ \\\\/\\\\ \\\\/_/\\\\ \\\\/\\\\/_/\\\\ \\\\/ \\\\ \\\\ \\\\L\\\\ \\\\\n \\\\ \\\\ \\\\__\\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ __ \\\\\n \\\\ \\\\ \\\\_/\\\\ \\\\ \\\\ \\\\_\\\\ \\\\ \\\\ \\\\ \\\\ \\\\_\\\\ \\\\__\\\\ \\\\ \\\\/\\\\ \\\\\n \\\\ \\\\_\\\\\\\\ \\\\_\\\\ \\\\_____\\\\ \\\\ \\\\_\\\\ /\\\\_____\\\\\\\\ \\\\_\\\\ \\\\_\\\\\n \\\\/_/ \\\\/_/\\\\/_____/ \\\\/_/ \\\\/_____/ \\\\/_/\\\\/_/\n ` +\n '\\n\\n',\n )\n\n const isCurrentDir = projectName === '.' || projectName === './' || projectName === '.\\\\'\n const rootDir = isCurrentDir ? process.cwd() : path.join(process.cwd(), projectName)\n const isPluginTemplate = template === 'plugin'\n\n process.env.REDISMS_DISABLE_POSTINSTALL = '1'\n if (!isCurrentDir && !checkIfDirectoryExists(rootDir)) {\n fs.mkdirSync(path.join(rootDir))\n context.log('directory-created', (message: Message) =>\n message.tag('success').append('Directory created ').append(projectName, 'gray'),\n )\n } else {\n context.log('directory-using', (message: Message) => message.tag('info').append('Using current directory'))\n }\n\n // Plugin template handles package.json differently (via template)\n if (!isPluginTemplate && !checkIfFileExists(rootDir, 'package.json')) {\n const finalProjectName =\n !projectName || projectName === '.' || projectName === './' || projectName === '.\\\\'\n ? path.basename(process.cwd())\n : projectName.trim()\n\n const packageJsonContent = {\n name: finalProjectName,\n description: '',\n type: 'module',\n scripts: {\n postinstall: 'motia install',\n dev: 'motia dev',\n start: 'motia start',\n 'generate-types': 'motia generate-types',\n build: 'motia build',\n clean: 'rm -rf dist node_modules python_modules .motia .mermaid',\n //'generate:config': 'motia get-config --output ./', TODO: doesnt work at the moment\n },\n keywords: ['motia'],\n }\n\n fs.writeFileSync(path.join(rootDir, 'package.json'), JSON.stringify(packageJsonContent, null, 2))\n\n context.log('package-json-created', (message: Message) =>\n message.tag('success').append('File').append('package.json', 'cyan').append('has been created.'),\n )\n } else if (!isPluginTemplate) {\n const packageJsonPath = path.join(rootDir, 'package.json')\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'))\n\n if (!packageJson.scripts) {\n packageJson.scripts = {}\n }\n\n if (!packageJson.scripts.dev) {\n packageJson.scripts.dev = 'motia dev'\n } else {\n packageJson.scripts.olddev = packageJson.scripts.dev\n packageJson.scripts.dev = 'motia dev'\n context.log('dev-command-already-exists', (message: Message) =>\n message.tag('warning').append('dev command already exists in package.json'),\n )\n }\n\n fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2))\n context.log('dev-command-updated', (message: Message) =>\n message\n .tag('success')\n .append('Updated')\n .append('dev', 'gray')\n .append('command to')\n .append('package.json', 'gray'),\n )\n }\n\n // Plugin template handles tsconfig.json via template\n if (!isPluginTemplate && !checkIfFileExists(rootDir, 'tsconfig.json')) {\n const tsconfigContent = {\n compilerOptions: {\n target: 'ES2020',\n module: 'ESNext',\n moduleResolution: 'bundler',\n allowImportingTsExtensions: true,\n noEmit: true,\n esModuleInterop: true,\n strict: true,\n skipLibCheck: true,\n forceConsistentCasingInFileNames: true,\n resolveJsonModule: true,\n allowJs: true,\n outDir: 'dist',\n rootDir: '.',\n baseUrl: '.',\n jsx: 'react-jsx',\n },\n include: ['**/*.ts', 'motia.config.ts', '**/*.tsx', 'types.d.ts', '**/*.jsx'],\n exclude: ['node_modules', 'dist', 'tests'],\n }\n\n fs.writeFileSync(path.join(rootDir, 'tsconfig.json'), JSON.stringify(tsconfigContent, null, 2))\n context.log('tsconfig-json-created', (message: Message) =>\n message.tag('success').append('File').append('tsconfig.json', 'cyan').append('has been created.'),\n )\n }\n\n // Plugin template handles .gitignore via template\n if (!isPluginTemplate && !checkIfFileExists(rootDir, '.gitignore')) {\n const gitignoreContent = [\n 'node_modules',\n 'python_modules',\n '.venv',\n 'venv',\n '.motia',\n '.mermaid',\n 'dist',\n '*.pyc',\n ].join('\\n')\n\n fs.writeFileSync(path.join(rootDir, '.gitignore'), gitignoreContent)\n context.log('gitignore-created', (message: Message) =>\n message.tag('success').append('File').append('.gitignore', 'cyan').append('has been created.'),\n )\n }\n\n // Skip cursor rules for plugin template\n if (!isPluginTemplate && cursorEnabled) {\n await pullRules({ force: true, rootDir }, context)\n }\n\n if (template) {\n await setupTemplate(template, rootDir, context)\n }\n\n if (!isPluginTemplate && skipRedis) {\n const motiaConfigPath = path.join(rootDir, 'motia.config.ts')\n\n const templatePath = path.join(__dirname, 'templates/motia.config.external-redis.ts.txt')\n const templateContent = fs.readFileSync(templatePath, 'utf-8')\n fs.writeFileSync(motiaConfigPath, templateContent)\n context.log('motia-config-created', (message: Message) =>\n message.tag('success').append('File').append('motia.config.ts', 'cyan').append('has been created.'),\n )\n }\n\n let packageManager: string\n if (!isPluginTemplate) {\n packageManager = await installNodeDependencies(rootDir, context)\n\n if (template.includes('python') || template.includes('multilang')) {\n await pythonInstall({ baseDir: rootDir })\n }\n\n await generateTypes(rootDir)\n } else {\n packageManager = await preparePackageManager(rootDir, context, true)\n\n context.log('installing-plugin-dependencies', (message: Message) =>\n message.tag('info').append('Installing plugin dependencies...'),\n )\n\n const installCommands: Record<string, string> = {\n ...getInstallCommands(rootDir),\n }\n const installCommand = installCommands[packageManager] || installCommands['npm']\n\n try {\n await executeCommand(installCommand, rootDir)\n context.log('plugin-dependencies-installed', (message: Message) =>\n message.tag('success').append('Plugin dependencies installed'),\n )\n } catch (error) {\n context.log('failed-to-install-plugin-dependencies', (message: Message) =>\n message.tag('failed').append('Failed to install plugin dependencies'),\n )\n console.error(error)\n }\n }\n\n const projectDirName = path.basename(rootDir)\n const devCommand = `${packageManager} run dev`\n const port = 3000\n const cdCommand = isCurrentDir ? '' : `${pc.cyan(`cd ${projectDirName}`)}\\n `\n\n context.log('success-blank', (message) => message.text(''))\n context.log('success-header', (message) =>\n message.text(`${pc.green('✨')} ${pc.bold('All set! Your project is ready to go.')}`),\n )\n context.log('success-blank-2', (message) => message.text(''))\n context.log('success-get-started', (message) => message.text('Get started:'))\n context.log('success-blank-3', (message) => message.text(''))\n context.log('success-commands', (message) => message.text(` ${cdCommand}${pc.cyan(devCommand)}`))\n context.log('success-blank-4', (message) => message.text(''))\n context.log('success-open', (message) => message.text(`Then open ${pc.cyan(`http://localhost:${port}`)}`))\n context.log('success-blank-5', (message: Message) => message.text(''))\n context.log('success-docs', (message) => message.text(`Docs: ${pc.cyan('https://www.motia.dev/docs')}`))\n context.log('success-blank-6', (message) => message.text(''))\n if (skipRedis) {\n context.log('redis-skip-warning', (message: Message) =>\n message\n .tag('warning')\n .append(\n '⚠️ You skipped Redis binary installation. Make sure to provide a Redis connection before running Motia.',\n ),\n )\n context.log('success-blank-7', (message) => message.text(''))\n }\n context.log('success-signoff', (message) => message.text('Happy coding! 🚀'))\n context.log('success-blank-8', (message) => message.text(''))\n}\n"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { copyWithWSLCompat } from "./utils.mjs";
1
2
  import fs from "fs";
2
3
  import path from "path";
3
4
  import { fileURLToPath } from "url";
@@ -11,13 +12,14 @@ const pullRules = async (args, context) => {
11
12
  const targetFile = path.join(args.rootDir, file);
12
13
  const isFolder = fs.statSync(path.join(cursorTemplateDir, file)).isDirectory();
13
14
  const type = isFolder ? "Folder" : "File";
14
- if (args.force || !fs.existsSync(targetFile)) {
15
- fs.cpSync(path.join(cursorTemplateDir, file), targetFile, {
16
- recursive: isFolder,
17
- force: true
18
- });
15
+ if (args.force || !fs.existsSync(targetFile)) try {
16
+ copyWithWSLCompat(path.join(cursorTemplateDir, file), targetFile, isFolder);
19
17
  context.log(`${file}-created`, (message) => message.tag("success").append(type).append(file, "cyan").append("has been created."));
20
- } else context.log(`${file}-skipped`, (message) => message.tag("warning").append(type).append(file, "cyan").append("already exists, skipping..."));
18
+ } catch (error) {
19
+ context.log(`${file}-error`, (message) => message.tag("error").append("Failed to create").append(type, "yellow").append(file, "cyan").append(`: ${error.message}`));
20
+ throw error;
21
+ }
22
+ else context.log(`${file}-skipped`, (message) => message.tag("warning").append(type).append(file, "cyan").append("already exists, skipping..."));
21
23
  }
22
24
  };
23
25
 
@@ -1 +1 @@
1
- {"version":3,"file":"pull-rules.mjs","names":[],"sources":["../../src/create/pull-rules.ts"],"sourcesContent":["import fs from 'fs'\nimport path from 'path'\nimport { fileURLToPath } from 'url'\nimport type { CliContext, Message } from '../cloud/config-utils'\n\ntype PullRulesArgs = {\n rootDir: string\n force?: boolean\n}\n\nexport const pullRules = async (args: PullRulesArgs, context: CliContext) => {\n const __dirname = path.dirname(fileURLToPath(import.meta.url))\n const cursorTemplateDir = path.join(__dirname, '..', 'cursor-rules', 'dot-files')\n const files = fs.readdirSync(cursorTemplateDir)\n\n for (const file of files) {\n const targetFile = path.join(args.rootDir, file)\n const isFolder = fs.statSync(path.join(cursorTemplateDir, file)).isDirectory()\n const type = isFolder ? 'Folder' : 'File'\n\n if (args.force || !fs.existsSync(targetFile)) {\n fs.cpSync(path.join(cursorTemplateDir, file), targetFile, {\n recursive: isFolder,\n force: true,\n })\n\n context.log(`${file}-created`, (message: Message) =>\n message.tag('success').append(type).append(file, 'cyan').append('has been created.'),\n )\n } else {\n context.log(`${file}-skipped`, (message: Message) =>\n message.tag('warning').append(type).append(file, 'cyan').append('already exists, skipping...'),\n )\n }\n }\n}\n"],"mappings":";;;;;AAUA,MAAa,YAAY,OAAO,MAAqB,YAAwB;CAC3E,MAAM,YAAY,KAAK,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC;CAC9D,MAAM,oBAAoB,KAAK,KAAK,WAAW,MAAM,gBAAgB,YAAY;CACjF,MAAM,QAAQ,GAAG,YAAY,kBAAkB;AAE/C,MAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,aAAa,KAAK,KAAK,KAAK,SAAS,KAAK;EAChD,MAAM,WAAW,GAAG,SAAS,KAAK,KAAK,mBAAmB,KAAK,CAAC,CAAC,aAAa;EAC9E,MAAM,OAAO,WAAW,WAAW;AAEnC,MAAI,KAAK,SAAS,CAAC,GAAG,WAAW,WAAW,EAAE;AAC5C,MAAG,OAAO,KAAK,KAAK,mBAAmB,KAAK,EAAE,YAAY;IACxD,WAAW;IACX,OAAO;IACR,CAAC;AAEF,WAAQ,IAAI,GAAG,KAAK,YAAY,YAC9B,QAAQ,IAAI,UAAU,CAAC,OAAO,KAAK,CAAC,OAAO,MAAM,OAAO,CAAC,OAAO,oBAAoB,CACrF;QAED,SAAQ,IAAI,GAAG,KAAK,YAAY,YAC9B,QAAQ,IAAI,UAAU,CAAC,OAAO,KAAK,CAAC,OAAO,MAAM,OAAO,CAAC,OAAO,8BAA8B,CAC/F"}
1
+ {"version":3,"file":"pull-rules.mjs","names":["error: any"],"sources":["../../src/create/pull-rules.ts"],"sourcesContent":["import fs from 'fs'\nimport path from 'path'\nimport { fileURLToPath } from 'url'\nimport type { CliContext, Message } from '../cloud/config-utils'\nimport { copyWithWSLCompat } from './utils'\n\ntype PullRulesArgs = {\n rootDir: string\n force?: boolean\n}\n\nexport const pullRules = async (args: PullRulesArgs, context: CliContext) => {\n const __dirname = path.dirname(fileURLToPath(import.meta.url))\n const cursorTemplateDir = path.join(__dirname, '..', 'cursor-rules', 'dot-files')\n const files = fs.readdirSync(cursorTemplateDir)\n\n for (const file of files) {\n const targetFile = path.join(args.rootDir, file)\n const isFolder = fs.statSync(path.join(cursorTemplateDir, file)).isDirectory()\n const type = isFolder ? 'Folder' : 'File'\n\n if (args.force || !fs.existsSync(targetFile)) {\n try {\n copyWithWSLCompat(path.join(cursorTemplateDir, file), targetFile, isFolder)\n context.log(`${file}-created`, (message: Message) =>\n message.tag('success').append(type).append(file, 'cyan').append('has been created.'),\n )\n } catch (error: any) {\n context.log(`${file}-error`, (message: Message) =>\n message\n .tag('error')\n .append('Failed to create')\n .append(type, 'yellow')\n .append(file, 'cyan')\n .append(`: ${error.message}`),\n )\n throw error\n }\n } else {\n context.log(`${file}-skipped`, (message: Message) =>\n message.tag('warning').append(type).append(file, 'cyan').append('already exists, skipping...'),\n )\n }\n }\n}\n"],"mappings":";;;;;;AAWA,MAAa,YAAY,OAAO,MAAqB,YAAwB;CAC3E,MAAM,YAAY,KAAK,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC;CAC9D,MAAM,oBAAoB,KAAK,KAAK,WAAW,MAAM,gBAAgB,YAAY;CACjF,MAAM,QAAQ,GAAG,YAAY,kBAAkB;AAE/C,MAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,aAAa,KAAK,KAAK,KAAK,SAAS,KAAK;EAChD,MAAM,WAAW,GAAG,SAAS,KAAK,KAAK,mBAAmB,KAAK,CAAC,CAAC,aAAa;EAC9E,MAAM,OAAO,WAAW,WAAW;AAEnC,MAAI,KAAK,SAAS,CAAC,GAAG,WAAW,WAAW,CAC1C,KAAI;AACF,qBAAkB,KAAK,KAAK,mBAAmB,KAAK,EAAE,YAAY,SAAS;AAC3E,WAAQ,IAAI,GAAG,KAAK,YAAY,YAC9B,QAAQ,IAAI,UAAU,CAAC,OAAO,KAAK,CAAC,OAAO,MAAM,OAAO,CAAC,OAAO,oBAAoB,CACrF;WACMA,OAAY;AACnB,WAAQ,IAAI,GAAG,KAAK,UAAU,YAC5B,QACG,IAAI,QAAQ,CACZ,OAAO,mBAAmB,CAC1B,OAAO,MAAM,SAAS,CACtB,OAAO,MAAM,OAAO,CACpB,OAAO,KAAK,MAAM,UAAU,CAChC;AACD,SAAM;;MAGR,SAAQ,IAAI,GAAG,KAAK,YAAY,YAC9B,QAAQ,IAAI,UAAU,CAAC,OAAO,KAAK,CAAC,OAAO,MAAM,OAAO,CAAC,OAAO,8BAA8B,CAC/F"}
@@ -1,2 +1 @@
1
- # Optional: Uncomment if you want to use Pydantic for validation
2
- # pydantic>=2.0.0
1
+ pydantic>=2.6.1
@@ -1,2 +1 @@
1
- # Optional: Uncomment if you want to use Pydantic for validation
2
- # pydantic>=2.0.0
1
+ pydantic>=2.6.1
@@ -12,7 +12,51 @@ const checkIfDirectoryExists = (dir) => {
12
12
  return false;
13
13
  }
14
14
  };
15
+ /**
16
+ * Recursively copies a directory using read/write operations.
17
+ * This is a fallback method for WSL/Windows compatibility.
18
+ */
19
+ function copyDirectoryRecursive(src, dest) {
20
+ fs.mkdirSync(dest, { recursive: true });
21
+ const entries = fs.readdirSync(src, { withFileTypes: true });
22
+ for (const entry of entries) {
23
+ const srcPath = path.join(src, entry.name);
24
+ const destPath = path.join(dest, entry.name);
25
+ if (entry.isDirectory()) copyDirectoryRecursive(srcPath, destPath);
26
+ else {
27
+ const content = fs.readFileSync(srcPath);
28
+ fs.writeFileSync(destPath, content);
29
+ }
30
+ }
31
+ }
32
+ /**
33
+ * Copies a file or directory with WSL/Windows compatibility.
34
+ * Attempts to use fs.cpSync first for better performance, but falls back
35
+ * to manual read/write operations if permission errors occur (common in WSL).
36
+ *
37
+ * @param src - Source file or directory path
38
+ * @param dest - Destination file or directory path
39
+ * @param isDirectory - Whether the source is a directory
40
+ * @throws Error if copy fails after all fallback attempts
41
+ */
42
+ function copyWithWSLCompat(src, dest, isDirectory) {
43
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
44
+ try {
45
+ fs.cpSync(src, dest, {
46
+ recursive: isDirectory,
47
+ force: true
48
+ });
49
+ } catch (error) {
50
+ const code = typeof error === "object" && error !== null && "code" in error ? error.code : void 0;
51
+ if (code === "EPERM" || code === "EACCES") if (isDirectory) copyDirectoryRecursive(src, dest);
52
+ else {
53
+ const content = fs.readFileSync(src);
54
+ fs.writeFileSync(dest, content);
55
+ }
56
+ else throw error;
57
+ }
58
+ }
15
59
 
16
60
  //#endregion
17
- export { checkIfDirectoryExists, checkIfFileExists };
61
+ export { checkIfDirectoryExists, checkIfFileExists, copyWithWSLCompat };
18
62
  //# sourceMappingURL=utils.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.mjs","names":[],"sources":["../../src/create/utils.ts"],"sourcesContent":["import fs from 'fs'\nimport path from 'path'\n\nexport const checkIfFileExists = (dir: string, fileName: string): boolean => {\n return fs.existsSync(path.join(dir, fileName))\n}\n\nexport const checkIfDirectoryExists = (dir: string): boolean => {\n try {\n return fs.statSync(dir).isDirectory()\n } catch {\n return false\n }\n}\n"],"mappings":";;;;AAGA,MAAa,qBAAqB,KAAa,aAA8B;AAC3E,QAAO,GAAG,WAAW,KAAK,KAAK,KAAK,SAAS,CAAC;;AAGhD,MAAa,0BAA0B,QAAyB;AAC9D,KAAI;AACF,SAAO,GAAG,SAAS,IAAI,CAAC,aAAa;SAC/B;AACN,SAAO"}
1
+ {"version":3,"file":"utils.mjs","names":["error: unknown"],"sources":["../../src/create/utils.ts"],"sourcesContent":["import fs from 'fs'\nimport path from 'path'\n\nexport const checkIfFileExists = (dir: string, fileName: string): boolean => {\n return fs.existsSync(path.join(dir, fileName))\n}\n\nexport const checkIfDirectoryExists = (dir: string): boolean => {\n try {\n return fs.statSync(dir).isDirectory()\n } catch {\n return false\n }\n}\n\n/**\n * Recursively copies a directory using read/write operations.\n * This is a fallback method for WSL/Windows compatibility.\n */\nfunction copyDirectoryRecursive(src: string, dest: string): void {\n fs.mkdirSync(dest, { recursive: true })\n const entries = fs.readdirSync(src, { withFileTypes: true })\n\n for (const entry of entries) {\n const srcPath = path.join(src, entry.name)\n const destPath = path.join(dest, entry.name)\n\n if (entry.isDirectory()) {\n copyDirectoryRecursive(srcPath, destPath)\n } else {\n // For files, read and write manually\n const content = fs.readFileSync(srcPath)\n fs.writeFileSync(destPath, content)\n }\n }\n}\n\n/**\n * Copies a file or directory with WSL/Windows compatibility.\n * Attempts to use fs.cpSync first for better performance, but falls back\n * to manual read/write operations if permission errors occur (common in WSL).\n *\n * @param src - Source file or directory path\n * @param dest - Destination file or directory path\n * @param isDirectory - Whether the source is a directory\n * @throws Error if copy fails after all fallback attempts\n */\nexport function copyWithWSLCompat(src: string, dest: string, isDirectory: boolean): void {\n // Ensure the destination *parent* directory exists.\n // - For directory copies, fs.cpSync/copyDirectoryRecursive will create `dest` as needed.\n // - For file copies, we only need the parent directory.\n fs.mkdirSync(path.dirname(dest), { recursive: true })\n\n try {\n // Try the standard cpSync first (faster and works in most cases)\n fs.cpSync(src, dest, {\n recursive: isDirectory,\n force: true,\n })\n } catch (error: unknown) {\n // If we get permission errors (common in WSL when writing to Windows paths),\n // fall back to manual copy using read/write operations\n const code =\n typeof error === 'object' && error !== null && 'code' in error ? (error as NodeJS.ErrnoException).code : undefined\n\n if (code === 'EPERM' || code === 'EACCES') {\n if (isDirectory) {\n copyDirectoryRecursive(src, dest)\n } else {\n // For files, read and write manually\n const content = fs.readFileSync(src)\n fs.writeFileSync(dest, content)\n }\n } else {\n // Re-throw other errors\n throw error\n }\n }\n}\n"],"mappings":";;;;AAGA,MAAa,qBAAqB,KAAa,aAA8B;AAC3E,QAAO,GAAG,WAAW,KAAK,KAAK,KAAK,SAAS,CAAC;;AAGhD,MAAa,0BAA0B,QAAyB;AAC9D,KAAI;AACF,SAAO,GAAG,SAAS,IAAI,CAAC,aAAa;SAC/B;AACN,SAAO;;;;;;;AAQX,SAAS,uBAAuB,KAAa,MAAoB;AAC/D,IAAG,UAAU,MAAM,EAAE,WAAW,MAAM,CAAC;CACvC,MAAM,UAAU,GAAG,YAAY,KAAK,EAAE,eAAe,MAAM,CAAC;AAE5D,MAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,UAAU,KAAK,KAAK,KAAK,MAAM,KAAK;EAC1C,MAAM,WAAW,KAAK,KAAK,MAAM,MAAM,KAAK;AAE5C,MAAI,MAAM,aAAa,CACrB,wBAAuB,SAAS,SAAS;OACpC;GAEL,MAAM,UAAU,GAAG,aAAa,QAAQ;AACxC,MAAG,cAAc,UAAU,QAAQ;;;;;;;;;;;;;;AAezC,SAAgB,kBAAkB,KAAa,MAAc,aAA4B;AAIvF,IAAG,UAAU,KAAK,QAAQ,KAAK,EAAE,EAAE,WAAW,MAAM,CAAC;AAErD,KAAI;AAEF,KAAG,OAAO,KAAK,MAAM;GACnB,WAAW;GACX,OAAO;GACR,CAAC;UACKA,OAAgB;EAGvB,MAAM,OACJ,OAAO,UAAU,YAAY,UAAU,QAAQ,UAAU,QAAS,MAAgC,OAAO;AAE3G,MAAI,SAAS,WAAW,SAAS,SAC/B,KAAI,YACF,wBAAuB,KAAK,KAAK;OAC5B;GAEL,MAAM,UAAU,GAAG,aAAa,IAAI;AACpC,MAAG,cAAc,MAAM,QAAQ;;MAIjC,OAAM"}
@@ -1,5 +1,6 @@
1
1
  import { version } from "../version.mjs";
2
2
  import { executeCommand } from "../utils/execute-command.mjs";
3
+ import { getInstallCommands } from "../utils/build-npm-command.mjs";
3
4
  import { getPackageManager } from "../utils/get-package-manager.mjs";
4
5
  import { pluginDependencies } from "./plugin-dependencies.mjs";
5
6
  import fs from "node:fs";
@@ -35,11 +36,8 @@ const installPluginDependencies = async (baseDir, printer) => {
35
36
  packageManager = "npm";
36
37
  }
37
38
  printer.printPluginLog(`Installing dependencies using ${packageManager}...`);
38
- const installCommand = {
39
- npm: "npm install",
40
- yarn: "yarn install",
41
- pnpm: "pnpm install"
42
- }[packageManager] || "npm install";
39
+ const installCommands = getInstallCommands(baseDir);
40
+ const installCommand = installCommands[packageManager] || installCommands["npm"];
43
41
  try {
44
42
  await executeCommand(installCommand, baseDir, { silent: false });
45
43
  printer.printPluginLog("Plugin dependencies installed successfully");
@@ -1 +1 @@
1
- {"version":3,"file":"install-plugin-dependencies.mjs","names":["missingDependencies: string[]"],"sources":["../../src/plugins/install-plugin-dependencies.ts"],"sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\nimport type { Printer } from '@motiadev/core'\nimport { executeCommand } from '../utils/execute-command'\nimport { getPackageManager } from '../utils/get-package-manager'\nimport { version } from '../version'\nimport { pluginDependencies } from './plugin-dependencies'\n\nexport const installPluginDependencies = async (baseDir: string, printer: Printer): Promise<void> => {\n const packageJsonPath = path.join(baseDir, 'package.json')\n\n if (!fs.existsSync(packageJsonPath)) {\n printer.printPluginWarn('No package.json found, skipping plugin dependency installation')\n return\n }\n\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'))\n\n if (!packageJson.dependencies) {\n packageJson.dependencies = {}\n }\n\n const missingDependencies: string[] = []\n\n for (const dep of pluginDependencies) {\n if (packageJson.devDependencies?.[dep]) {\n delete packageJson.devDependencies[dep]\n }\n\n if (!packageJson.dependencies[dep]) {\n packageJson.dependencies[dep] = version\n missingDependencies.push(dep)\n }\n }\n\n if (missingDependencies.length === 0) {\n printer.printPluginLog('All plugin dependencies already installed')\n return\n }\n\n printer.printPluginLog(`Adding missing plugin dependencies: ${missingDependencies.join(', ')}`)\n\n fs.writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\\n`)\n printer.printPluginLog('Updated package.json with plugin dependencies')\n\n let packageManager = getPackageManager(baseDir)\n if (packageManager === 'unknown') {\n printer.printPluginError('No package manager found, using npm as default')\n packageManager = 'npm'\n }\n printer.printPluginLog(`Installing dependencies using ${packageManager}...`)\n\n const installCommands: Record<string, string> = {\n npm: 'npm install',\n yarn: 'yarn install',\n pnpm: 'pnpm install',\n }\n\n const installCommand = installCommands[packageManager] || 'npm install'\n\n try {\n await executeCommand(installCommand, baseDir, { silent: false })\n printer.printPluginLog('Plugin dependencies installed successfully')\n } catch (error) {\n printer.printPluginError('Failed to install plugin dependencies:', error)\n printer.printPluginWarn(`Please run '${installCommand}' manually to install the dependencies`)\n }\n}\n"],"mappings":";;;;;;;;AAQA,MAAa,4BAA4B,OAAO,SAAiB,YAAoC;CACnG,MAAM,kBAAkB,KAAK,KAAK,SAAS,eAAe;AAE1D,KAAI,CAAC,GAAG,WAAW,gBAAgB,EAAE;AACnC,UAAQ,gBAAgB,iEAAiE;AACzF;;CAGF,MAAM,cAAc,KAAK,MAAM,GAAG,aAAa,iBAAiB,QAAQ,CAAC;AAEzE,KAAI,CAAC,YAAY,aACf,aAAY,eAAe,EAAE;CAG/B,MAAMA,sBAAgC,EAAE;AAExC,MAAK,MAAM,OAAO,oBAAoB;AACpC,MAAI,YAAY,kBAAkB,KAChC,QAAO,YAAY,gBAAgB;AAGrC,MAAI,CAAC,YAAY,aAAa,MAAM;AAClC,eAAY,aAAa,OAAO;AAChC,uBAAoB,KAAK,IAAI;;;AAIjC,KAAI,oBAAoB,WAAW,GAAG;AACpC,UAAQ,eAAe,4CAA4C;AACnE;;AAGF,SAAQ,eAAe,uCAAuC,oBAAoB,KAAK,KAAK,GAAG;AAE/F,IAAG,cAAc,iBAAiB,GAAG,KAAK,UAAU,aAAa,MAAM,EAAE,CAAC,IAAI;AAC9E,SAAQ,eAAe,gDAAgD;CAEvE,IAAI,iBAAiB,kBAAkB,QAAQ;AAC/C,KAAI,mBAAmB,WAAW;AAChC,UAAQ,iBAAiB,iDAAiD;AAC1E,mBAAiB;;AAEnB,SAAQ,eAAe,iCAAiC,eAAe,KAAK;CAQ5E,MAAM,iBAN0C;EAC9C,KAAK;EACL,MAAM;EACN,MAAM;EACP,CAEsC,mBAAmB;AAE1D,KAAI;AACF,QAAM,eAAe,gBAAgB,SAAS,EAAE,QAAQ,OAAO,CAAC;AAChE,UAAQ,eAAe,6CAA6C;UAC7D,OAAO;AACd,UAAQ,iBAAiB,0CAA0C,MAAM;AACzE,UAAQ,gBAAgB,eAAe,eAAe,wCAAwC"}
1
+ {"version":3,"file":"install-plugin-dependencies.mjs","names":["missingDependencies: string[]"],"sources":["../../src/plugins/install-plugin-dependencies.ts"],"sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\nimport type { Printer } from '@motiadev/core'\nimport { getInstallCommands } from '../utils/build-npm-command'\nimport { executeCommand } from '../utils/execute-command'\nimport { getPackageManager } from '../utils/get-package-manager'\nimport { version } from '../version'\nimport { pluginDependencies } from './plugin-dependencies'\n\nexport const installPluginDependencies = async (baseDir: string, printer: Printer): Promise<void> => {\n const packageJsonPath = path.join(baseDir, 'package.json')\n\n if (!fs.existsSync(packageJsonPath)) {\n printer.printPluginWarn('No package.json found, skipping plugin dependency installation')\n return\n }\n\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'))\n\n if (!packageJson.dependencies) {\n packageJson.dependencies = {}\n }\n\n const missingDependencies: string[] = []\n\n for (const dep of pluginDependencies) {\n if (packageJson.devDependencies?.[dep]) {\n delete packageJson.devDependencies[dep]\n }\n\n if (!packageJson.dependencies[dep]) {\n packageJson.dependencies[dep] = version\n missingDependencies.push(dep)\n }\n }\n\n if (missingDependencies.length === 0) {\n printer.printPluginLog('All plugin dependencies already installed')\n return\n }\n\n printer.printPluginLog(`Adding missing plugin dependencies: ${missingDependencies.join(', ')}`)\n\n fs.writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\\n`)\n printer.printPluginLog('Updated package.json with plugin dependencies')\n\n let packageManager = getPackageManager(baseDir)\n if (packageManager === 'unknown') {\n printer.printPluginError('No package manager found, using npm as default')\n packageManager = 'npm'\n }\n printer.printPluginLog(`Installing dependencies using ${packageManager}...`)\n\n const installCommands = getInstallCommands(baseDir)\n const installCommand = installCommands[packageManager] || installCommands['npm']\n\n try {\n await executeCommand(installCommand, baseDir, { silent: false })\n printer.printPluginLog('Plugin dependencies installed successfully')\n } catch (error) {\n printer.printPluginError('Failed to install plugin dependencies:', error)\n printer.printPluginWarn(`Please run '${installCommand}' manually to install the dependencies`)\n }\n}\n"],"mappings":";;;;;;;;;AASA,MAAa,4BAA4B,OAAO,SAAiB,YAAoC;CACnG,MAAM,kBAAkB,KAAK,KAAK,SAAS,eAAe;AAE1D,KAAI,CAAC,GAAG,WAAW,gBAAgB,EAAE;AACnC,UAAQ,gBAAgB,iEAAiE;AACzF;;CAGF,MAAM,cAAc,KAAK,MAAM,GAAG,aAAa,iBAAiB,QAAQ,CAAC;AAEzE,KAAI,CAAC,YAAY,aACf,aAAY,eAAe,EAAE;CAG/B,MAAMA,sBAAgC,EAAE;AAExC,MAAK,MAAM,OAAO,oBAAoB;AACpC,MAAI,YAAY,kBAAkB,KAChC,QAAO,YAAY,gBAAgB;AAGrC,MAAI,CAAC,YAAY,aAAa,MAAM;AAClC,eAAY,aAAa,OAAO;AAChC,uBAAoB,KAAK,IAAI;;;AAIjC,KAAI,oBAAoB,WAAW,GAAG;AACpC,UAAQ,eAAe,4CAA4C;AACnE;;AAGF,SAAQ,eAAe,uCAAuC,oBAAoB,KAAK,KAAK,GAAG;AAE/F,IAAG,cAAc,iBAAiB,GAAG,KAAK,UAAU,aAAa,MAAM,EAAE,CAAC,IAAI;AAC9E,SAAQ,eAAe,gDAAgD;CAEvE,IAAI,iBAAiB,kBAAkB,QAAQ;AAC/C,KAAI,mBAAmB,WAAW;AAChC,UAAQ,iBAAiB,iDAAiD;AAC1E,mBAAiB;;AAEnB,SAAQ,eAAe,iCAAiC,eAAe,KAAK;CAE5E,MAAM,kBAAkB,mBAAmB,QAAQ;CACnD,MAAM,iBAAiB,gBAAgB,mBAAmB,gBAAgB;AAE1E,KAAI;AACF,QAAM,eAAe,gBAAgB,SAAS,EAAE,QAAQ,OAAO,CAAC;AAChE,UAAQ,eAAe,6CAA6C;UAC7D,OAAO;AACd,UAAQ,iBAAiB,0CAA0C,MAAM;AACzE,UAAQ,gBAAgB,eAAe,eAAe,wCAAwC"}
@@ -1,3 +1,5 @@
1
+ import { internalLogger } from "../utils/internal-logger.mjs";
2
+ import { ensureBuildTools } from "../utils/check-build-tools.mjs";
1
3
  import { mkdirSync } from "fs";
2
4
  import { RedisMemoryServer } from "redis-memory-server";
3
5
 
@@ -21,6 +23,7 @@ var RedisMemoryManager = class {
21
23
  }
22
24
  async startServer(baseDir) {
23
25
  if (!this.server) try {
26
+ await ensureBuildTools();
24
27
  mkdirSync(baseDir, { recursive: true });
25
28
  const instance = { args: [
26
29
  "--appendonly",
@@ -34,23 +37,52 @@ var RedisMemoryManager = class {
34
37
  ] };
35
38
  if (process.env.MOTIA_REDIS_PORT) instance.port = parseInt(process.env.MOTIA_REDIS_PORT || "6379");
36
39
  this.server = new RedisMemoryServer({ instance });
37
- console.log("Redis Memory Server started");
38
- this.running = true;
39
40
  this.registerCleanupHandlers();
40
41
  } catch (error) {
41
- console.error("[Redis Memory Server] Failed to start:", error);
42
+ internalLogger.error("Failed to initialize Redis Memory Server");
43
+ if (error instanceof Error) {
44
+ console.error(error.message);
45
+ if (process.env.LOG_LEVEL === "debug" && error.stack) {
46
+ console.error("\nStack trace:");
47
+ console.error(error.stack);
48
+ }
49
+ }
50
+ throw error;
51
+ }
52
+ try {
53
+ const host = await this.server.getHost();
54
+ const port = await this.server.getPort();
55
+ this.running = true;
56
+ internalLogger.info("Redis Memory Server started", `${host}:${port}`);
57
+ return {
58
+ host,
59
+ port
60
+ };
61
+ } catch (error) {
62
+ internalLogger.error("Failed to start Redis Memory Server");
63
+ if (error instanceof Error) {
64
+ console.error(error.message);
65
+ if (error.message.includes("make") || error.message.includes("compile")) {
66
+ console.error("\nThis error typically occurs when build tools are missing.");
67
+ console.error("Please ensure you have \"make\" and a C compiler installed.");
68
+ }
69
+ if (process.env.LOG_LEVEL === "debug" && error.stack) {
70
+ console.error("\nStack trace:");
71
+ console.error(error.stack);
72
+ }
73
+ }
74
+ console.error("\nAlternative: Use an external Redis server");
75
+ console.error(" Set MOTIA_DISABLE_MEMORY_SERVER=true");
76
+ console.error(" Set MOTIA_REDIS_HOST=<your-redis-host>");
77
+ console.error(" Set MOTIA_REDIS_PORT=<your-redis-port> (default: 6379)");
42
78
  throw error;
43
79
  }
44
- return {
45
- host: await this.server.getHost(),
46
- port: await this.server.getPort()
47
- };
48
80
  }
49
81
  async stop() {
50
82
  if (this.server && this.running) try {
51
83
  await this.server.stop();
52
84
  } catch (error) {
53
- console.error("[Redis Memory Server] Error stopping:", error?.message);
85
+ internalLogger.error("Error stopping Redis Memory Server", error?.message);
54
86
  } finally {
55
87
  this.running = false;
56
88
  this.server = null;
@@ -1 +1 @@
1
- {"version":3,"file":"memory-manager.mjs","names":["instance: RedisMemoryInstancePropT","error: unknown"],"sources":["../../src/redis/memory-manager.ts"],"sourcesContent":["import { mkdirSync } from 'fs'\nimport type { RedisClientType } from 'redis'\nimport { RedisMemoryServer } from 'redis-memory-server'\nimport type { RedisMemoryInstancePropT } from 'redis-memory-server/lib/types'\nimport type { RedisConnectionInfo } from './types'\n\nexport class RedisMemoryManager {\n private server: RedisMemoryServer | null = null\n private client: RedisClientType | null = null\n private running = false\n\n private registerCleanupHandlers(): void {\n process.on('exit', async () => {\n await this.stop()\n })\n process.on('SIGTERM', async () => {\n await this.stop()\n })\n\n process.on('SIGINT', async () => {\n await this.stop()\n })\n }\n\n async startServer(baseDir: string): Promise<RedisConnectionInfo> {\n if (!this.server) {\n try {\n mkdirSync(baseDir, { recursive: true })\n\n const instance: RedisMemoryInstancePropT = {\n args: ['--appendonly', 'yes', '--appendfsync', 'everysec', '--save', '\"\"', '--dir', baseDir],\n }\n\n if (process.env.MOTIA_REDIS_PORT) {\n instance.port = parseInt(process.env.MOTIA_REDIS_PORT || '6379')\n }\n\n this.server = new RedisMemoryServer({ instance })\n console.log('Redis Memory Server started')\n this.running = true\n this.registerCleanupHandlers()\n } catch (error) {\n console.error('[Redis Memory Server] Failed to start:', error)\n throw error\n }\n }\n\n const host = await this.server.getHost()\n const port = await this.server.getPort()\n\n return { host, port }\n }\n\n async stop(): Promise<void> {\n if (this.server && this.running) {\n try {\n await this.server.stop()\n } catch (error: unknown) {\n console.error('[Redis Memory Server] Error stopping:', (error as Error)?.message)\n } finally {\n this.running = false\n this.server = null\n }\n }\n }\n\n isRunning(): boolean {\n return this.running\n }\n\n getClient(): RedisClientType | null {\n return this.client\n }\n}\n"],"mappings":";;;;AAMA,IAAa,qBAAb,MAAgC;;gBACa;gBACF;iBACvB;;CAElB,AAAQ,0BAAgC;AACtC,UAAQ,GAAG,QAAQ,YAAY;AAC7B,SAAM,KAAK,MAAM;IACjB;AACF,UAAQ,GAAG,WAAW,YAAY;AAChC,SAAM,KAAK,MAAM;IACjB;AAEF,UAAQ,GAAG,UAAU,YAAY;AAC/B,SAAM,KAAK,MAAM;IACjB;;CAGJ,MAAM,YAAY,SAA+C;AAC/D,MAAI,CAAC,KAAK,OACR,KAAI;AACF,aAAU,SAAS,EAAE,WAAW,MAAM,CAAC;GAEvC,MAAMA,WAAqC,EACzC,MAAM;IAAC;IAAgB;IAAO;IAAiB;IAAY;IAAU;IAAM;IAAS;IAAQ,EAC7F;AAED,OAAI,QAAQ,IAAI,iBACd,UAAS,OAAO,SAAS,QAAQ,IAAI,oBAAoB,OAAO;AAGlE,QAAK,SAAS,IAAI,kBAAkB,EAAE,UAAU,CAAC;AACjD,WAAQ,IAAI,8BAA8B;AAC1C,QAAK,UAAU;AACf,QAAK,yBAAyB;WACvB,OAAO;AACd,WAAQ,MAAM,0CAA0C,MAAM;AAC9D,SAAM;;AAOV,SAAO;GAAE,MAHI,MAAM,KAAK,OAAO,SAAS;GAGzB,MAFF,MAAM,KAAK,OAAO,SAAS;GAEnB;;CAGvB,MAAM,OAAsB;AAC1B,MAAI,KAAK,UAAU,KAAK,QACtB,KAAI;AACF,SAAM,KAAK,OAAO,MAAM;WACjBC,OAAgB;AACvB,WAAQ,MAAM,yCAA0C,OAAiB,QAAQ;YACzE;AACR,QAAK,UAAU;AACf,QAAK,SAAS;;;CAKpB,YAAqB;AACnB,SAAO,KAAK;;CAGd,YAAoC;AAClC,SAAO,KAAK"}
1
+ {"version":3,"file":"memory-manager.mjs","names":["instance: RedisMemoryInstancePropT","error: unknown"],"sources":["../../src/redis/memory-manager.ts"],"sourcesContent":["import { mkdirSync } from 'fs'\nimport type { RedisClientType } from 'redis'\nimport { RedisMemoryServer } from 'redis-memory-server'\nimport type { RedisMemoryInstancePropT } from 'redis-memory-server/lib/types'\nimport { ensureBuildTools } from '../utils/check-build-tools'\nimport { internalLogger } from '../utils/internal-logger'\nimport type { RedisConnectionInfo } from './types'\n\nexport class RedisMemoryManager {\n private server: RedisMemoryServer | null = null\n private client: RedisClientType | null = null\n private running = false\n\n private registerCleanupHandlers(): void {\n process.on('exit', async () => {\n await this.stop()\n })\n process.on('SIGTERM', async () => {\n await this.stop()\n })\n\n process.on('SIGINT', async () => {\n await this.stop()\n })\n }\n\n async startServer(baseDir: string): Promise<RedisConnectionInfo> {\n if (!this.server) {\n try {\n // Check for required build tools before attempting to start\n await ensureBuildTools()\n\n mkdirSync(baseDir, { recursive: true })\n\n const instance: RedisMemoryInstancePropT = {\n args: ['--appendonly', 'yes', '--appendfsync', 'everysec', '--save', '\"\"', '--dir', baseDir],\n }\n\n if (process.env.MOTIA_REDIS_PORT) {\n instance.port = parseInt(process.env.MOTIA_REDIS_PORT || '6379')\n }\n\n this.server = new RedisMemoryServer({ instance })\n this.registerCleanupHandlers()\n } catch (error) {\n internalLogger.error('Failed to initialize Redis Memory Server')\n if (error instanceof Error) {\n console.error(error.message)\n if (process.env.LOG_LEVEL === 'debug' && error.stack) {\n console.error('\\nStack trace:')\n console.error(error.stack)\n }\n }\n throw error\n }\n }\n\n try {\n const host = await this.server.getHost()\n const port = await this.server.getPort()\n\n this.running = true\n internalLogger.info('Redis Memory Server started', `${host}:${port}`)\n\n return { host, port }\n } catch (error) {\n internalLogger.error('Failed to start Redis Memory Server')\n\n if (error instanceof Error) {\n console.error(error.message)\n\n // Provide helpful suggestions based on common error patterns\n if (error.message.includes('make') || error.message.includes('compile')) {\n console.error('\\nThis error typically occurs when build tools are missing.')\n console.error('Please ensure you have \"make\" and a C compiler installed.')\n }\n\n if (process.env.LOG_LEVEL === 'debug' && error.stack) {\n console.error('\\nStack trace:')\n console.error(error.stack)\n }\n }\n\n console.error('\\nAlternative: Use an external Redis server')\n console.error(' Set MOTIA_DISABLE_MEMORY_SERVER=true')\n console.error(' Set MOTIA_REDIS_HOST=<your-redis-host>')\n console.error(' Set MOTIA_REDIS_PORT=<your-redis-port> (default: 6379)')\n\n throw error\n }\n }\n\n async stop(): Promise<void> {\n if (this.server && this.running) {\n try {\n await this.server.stop()\n } catch (error: unknown) {\n internalLogger.error('Error stopping Redis Memory Server', (error as Error)?.message)\n } finally {\n this.running = false\n this.server = null\n }\n }\n }\n\n isRunning(): boolean {\n return this.running\n }\n\n getClient(): RedisClientType | null {\n return this.client\n }\n}\n"],"mappings":";;;;;;AAQA,IAAa,qBAAb,MAAgC;;gBACa;gBACF;iBACvB;;CAElB,AAAQ,0BAAgC;AACtC,UAAQ,GAAG,QAAQ,YAAY;AAC7B,SAAM,KAAK,MAAM;IACjB;AACF,UAAQ,GAAG,WAAW,YAAY;AAChC,SAAM,KAAK,MAAM;IACjB;AAEF,UAAQ,GAAG,UAAU,YAAY;AAC/B,SAAM,KAAK,MAAM;IACjB;;CAGJ,MAAM,YAAY,SAA+C;AAC/D,MAAI,CAAC,KAAK,OACR,KAAI;AAEF,SAAM,kBAAkB;AAExB,aAAU,SAAS,EAAE,WAAW,MAAM,CAAC;GAEvC,MAAMA,WAAqC,EACzC,MAAM;IAAC;IAAgB;IAAO;IAAiB;IAAY;IAAU;IAAM;IAAS;IAAQ,EAC7F;AAED,OAAI,QAAQ,IAAI,iBACd,UAAS,OAAO,SAAS,QAAQ,IAAI,oBAAoB,OAAO;AAGlE,QAAK,SAAS,IAAI,kBAAkB,EAAE,UAAU,CAAC;AACjD,QAAK,yBAAyB;WACvB,OAAO;AACd,kBAAe,MAAM,2CAA2C;AAChE,OAAI,iBAAiB,OAAO;AAC1B,YAAQ,MAAM,MAAM,QAAQ;AAC5B,QAAI,QAAQ,IAAI,cAAc,WAAW,MAAM,OAAO;AACpD,aAAQ,MAAM,iBAAiB;AAC/B,aAAQ,MAAM,MAAM,MAAM;;;AAG9B,SAAM;;AAIV,MAAI;GACF,MAAM,OAAO,MAAM,KAAK,OAAO,SAAS;GACxC,MAAM,OAAO,MAAM,KAAK,OAAO,SAAS;AAExC,QAAK,UAAU;AACf,kBAAe,KAAK,+BAA+B,GAAG,KAAK,GAAG,OAAO;AAErE,UAAO;IAAE;IAAM;IAAM;WACd,OAAO;AACd,kBAAe,MAAM,sCAAsC;AAE3D,OAAI,iBAAiB,OAAO;AAC1B,YAAQ,MAAM,MAAM,QAAQ;AAG5B,QAAI,MAAM,QAAQ,SAAS,OAAO,IAAI,MAAM,QAAQ,SAAS,UAAU,EAAE;AACvE,aAAQ,MAAM,8DAA8D;AAC5E,aAAQ,MAAM,8DAA4D;;AAG5E,QAAI,QAAQ,IAAI,cAAc,WAAW,MAAM,OAAO;AACpD,aAAQ,MAAM,iBAAiB;AAC/B,aAAQ,MAAM,MAAM,MAAM;;;AAI9B,WAAQ,MAAM,8CAA8C;AAC5D,WAAQ,MAAM,yCAAyC;AACvD,WAAQ,MAAM,2CAA2C;AACzD,WAAQ,MAAM,2DAA2D;AAEzE,SAAM;;;CAIV,MAAM,OAAsB;AAC1B,MAAI,KAAK,UAAU,KAAK,QACtB,KAAI;AACF,SAAM,KAAK,OAAO,MAAM;WACjBC,OAAgB;AACvB,kBAAe,MAAM,sCAAuC,OAAiB,QAAQ;YAC7E;AACR,QAAK,UAAU;AACf,QAAK,SAAS;;;CAKpB,YAAqB;AACnB,SAAO,KAAK;;CAGd,YAAoC;AAClC,SAAO,KAAK"}
@@ -5,6 +5,7 @@ import path from "path";
5
5
  //#region src/utils/activate-python-env.ts
6
6
  const getSitePackagesPath = ({ baseDir, pythonVersion = "3.13" }) => {
7
7
  const venvPath = path.join(baseDir, "python_modules");
8
+ if (process.platform === "win32") return path.join(venvPath, "Lib", "site-packages");
8
9
  const actualPythonVersionPath = findPythonSitePackagesDir(path.join(venvPath, "lib"), pythonVersion);
9
10
  return path.join(venvPath, "lib", actualPythonVersionPath, "site-packages");
10
11
  };
@@ -1 +1 @@
1
- {"version":3,"file":"activate-python-env.mjs","names":["path"],"sources":["../../src/utils/activate-python-env.ts"],"sourcesContent":["import fs from 'fs'\nimport path from 'path'\nimport { internalLogger } from './internal-logger'\nimport { findPythonSitePackagesDir } from './python-version-utils'\n\ninterface VenvConfig {\n baseDir: string\n isVerbose?: boolean\n pythonVersion?: string\n}\n\nexport const getSitePackagesPath = ({ baseDir, pythonVersion = '3.13' }: VenvConfig): string => {\n const venvPath = path.join(baseDir, 'python_modules')\n const libPath = path.join(venvPath, 'lib')\n const actualPythonVersionPath = findPythonSitePackagesDir(libPath, pythonVersion)\n return path.join(venvPath, 'lib', actualPythonVersionPath, 'site-packages')\n}\n\nexport const activatePythonVenv = ({ baseDir, isVerbose = false, pythonVersion = '3.13' }: VenvConfig): void => {\n internalLogger.info('Activating Python environment')\n\n // Set the virtual environment path\n const venvPath = path.join(baseDir, 'python_modules')\n const venvBinPath = path.join(venvPath, process.platform === 'win32' ? 'Scripts' : 'bin')\n\n // Find the Python version directory using the utility function\n const sitePackagesPath = getSitePackagesPath({ baseDir, pythonVersion })\n\n // Add virtual environment to PATH\n process.env.PATH = `${venvBinPath}${path.delimiter}${process.env.PATH}`\n // Set VIRTUAL_ENV environment variable\n process.env.VIRTUAL_ENV = venvPath\n // Set PYTHON_SITE_PACKAGES with the site-packages path\n process.env.PYTHON_SITE_PACKAGES = sitePackagesPath\n // Remove PYTHONHOME if it exists as it can interfere with venv\n delete process.env.PYTHONHOME\n\n // Log Python environment information if verbose mode is enabled\n if (isVerbose) {\n const pythonPath =\n process.platform === 'win32' ? path.join(venvBinPath, 'python.exe') : path.join(venvBinPath, 'python')\n\n const relativePath = (path: string) => path.replace(baseDir, '<projectDir>')\n\n internalLogger.info('Using Python', relativePath(pythonPath))\n internalLogger.info('Site-packages path', relativePath(sitePackagesPath))\n }\n}\n"],"mappings":";;;;;AAWA,MAAa,uBAAuB,EAAE,SAAS,gBAAgB,aAAiC;CAC9F,MAAM,WAAW,KAAK,KAAK,SAAS,iBAAiB;CAErD,MAAM,0BAA0B,0BADhB,KAAK,KAAK,UAAU,MAAM,EACyB,cAAc;AACjF,QAAO,KAAK,KAAK,UAAU,OAAO,yBAAyB,gBAAgB;;AAG7E,MAAa,sBAAsB,EAAE,SAAS,YAAY,OAAO,gBAAgB,aAA+B;AAC9G,gBAAe,KAAK,gCAAgC;CAGpD,MAAM,WAAW,KAAK,KAAK,SAAS,iBAAiB;CACrD,MAAM,cAAc,KAAK,KAAK,UAAU,QAAQ,aAAa,UAAU,YAAY,MAAM;CAGzF,MAAM,mBAAmB,oBAAoB;EAAE;EAAS;EAAe,CAAC;AAGxE,SAAQ,IAAI,OAAO,GAAG,cAAc,KAAK,YAAY,QAAQ,IAAI;AAEjE,SAAQ,IAAI,cAAc;AAE1B,SAAQ,IAAI,uBAAuB;AAEnC,QAAO,QAAQ,IAAI;AAGnB,KAAI,WAAW;EACb,MAAM,aACJ,QAAQ,aAAa,UAAU,KAAK,KAAK,aAAa,aAAa,GAAG,KAAK,KAAK,aAAa,SAAS;EAExG,MAAM,gBAAgB,WAAiBA,OAAK,QAAQ,SAAS,eAAe;AAE5E,iBAAe,KAAK,gBAAgB,aAAa,WAAW,CAAC;AAC7D,iBAAe,KAAK,sBAAsB,aAAa,iBAAiB,CAAC"}
1
+ {"version":3,"file":"activate-python-env.mjs","names":["path"],"sources":["../../src/utils/activate-python-env.ts"],"sourcesContent":["import fs from 'fs'\nimport path from 'path'\nimport { internalLogger } from './internal-logger'\nimport { findPythonSitePackagesDir } from './python-version-utils'\n\ninterface VenvConfig {\n baseDir: string\n isVerbose?: boolean\n pythonVersion?: string\n}\n\nexport const getSitePackagesPath = ({ baseDir, pythonVersion = '3.13' }: VenvConfig): string => {\n const venvPath = path.join(baseDir, 'python_modules')\n\n // Windows virtualenv layout uses \"Lib/site-packages\"\n if (process.platform === 'win32') {\n return path.join(venvPath, 'Lib', 'site-packages')\n }\n\n // Unix-like layout uses \"lib/python3.x/site-packages\"\n const libPath = path.join(venvPath, 'lib')\n const actualPythonVersionPath = findPythonSitePackagesDir(libPath, pythonVersion)\n return path.join(venvPath, 'lib', actualPythonVersionPath, 'site-packages')\n}\n\nexport const activatePythonVenv = ({ baseDir, isVerbose = false, pythonVersion = '3.13' }: VenvConfig): void => {\n internalLogger.info('Activating Python environment')\n\n // Set the virtual environment path\n const venvPath = path.join(baseDir, 'python_modules')\n const venvBinPath = path.join(venvPath, process.platform === 'win32' ? 'Scripts' : 'bin')\n\n // Find the Python version directory using the utility function\n const sitePackagesPath = getSitePackagesPath({ baseDir, pythonVersion })\n\n // Add virtual environment to PATH\n process.env.PATH = `${venvBinPath}${path.delimiter}${process.env.PATH}`\n // Set VIRTUAL_ENV environment variable\n process.env.VIRTUAL_ENV = venvPath\n // Set PYTHON_SITE_PACKAGES with the site-packages path\n process.env.PYTHON_SITE_PACKAGES = sitePackagesPath\n // Remove PYTHONHOME if it exists as it can interfere with venv\n delete process.env.PYTHONHOME\n\n // Log Python environment information if verbose mode is enabled\n if (isVerbose) {\n const pythonPath =\n process.platform === 'win32' ? path.join(venvBinPath, 'python.exe') : path.join(venvBinPath, 'python')\n\n const relativePath = (path: string) => path.replace(baseDir, '<projectDir>')\n\n internalLogger.info('Using Python', relativePath(pythonPath))\n internalLogger.info('Site-packages path', relativePath(sitePackagesPath))\n }\n}\n"],"mappings":";;;;;AAWA,MAAa,uBAAuB,EAAE,SAAS,gBAAgB,aAAiC;CAC9F,MAAM,WAAW,KAAK,KAAK,SAAS,iBAAiB;AAGrD,KAAI,QAAQ,aAAa,QACvB,QAAO,KAAK,KAAK,UAAU,OAAO,gBAAgB;CAKpD,MAAM,0BAA0B,0BADhB,KAAK,KAAK,UAAU,MAAM,EACyB,cAAc;AACjF,QAAO,KAAK,KAAK,UAAU,OAAO,yBAAyB,gBAAgB;;AAG7E,MAAa,sBAAsB,EAAE,SAAS,YAAY,OAAO,gBAAgB,aAA+B;AAC9G,gBAAe,KAAK,gCAAgC;CAGpD,MAAM,WAAW,KAAK,KAAK,SAAS,iBAAiB;CACrD,MAAM,cAAc,KAAK,KAAK,UAAU,QAAQ,aAAa,UAAU,YAAY,MAAM;CAGzF,MAAM,mBAAmB,oBAAoB;EAAE;EAAS;EAAe,CAAC;AAGxE,SAAQ,IAAI,OAAO,GAAG,cAAc,KAAK,YAAY,QAAQ,IAAI;AAEjE,SAAQ,IAAI,cAAc;AAE1B,SAAQ,IAAI,uBAAuB;AAEnC,QAAO,QAAQ,IAAI;AAGnB,KAAI,WAAW;EACb,MAAM,aACJ,QAAQ,aAAa,UAAU,KAAK,KAAK,aAAa,aAAa,GAAG,KAAK,KAAK,aAAa,SAAS;EAExG,MAAM,gBAAgB,WAAiBA,OAAK,QAAQ,SAAS,eAAe;AAE5E,iBAAe,KAAK,gBAAgB,aAAa,WAAW,CAAC;AAC7D,iBAAe,KAAK,sBAAsB,aAAa,iBAAiB,CAAC"}
@@ -0,0 +1,51 @@
1
+ import { shouldUseNoBinLinks } from "./detect-wsl.mjs";
2
+
3
+ //#region src/utils/build-npm-command.ts
4
+ /**
5
+ * Build an npm install command with appropriate flags for the environment.
6
+ * Adds --no-bin-links when running in WSL2 on Windows filesystem to prevent
7
+ * EPERM errors during npm install.
8
+ *
9
+ * @param baseCommand - The base npm command (e.g., 'npm install --save' or 'npm install')
10
+ * @param targetPath - The path where the command will be executed
11
+ * @returns The command with appropriate flags added
12
+ */
13
+ function buildNpmCommand(baseCommand, targetPath) {
14
+ if (!baseCommand.startsWith("npm ")) return baseCommand;
15
+ if (shouldUseNoBinLinks(targetPath)) {
16
+ if (baseCommand.includes("npm install")) return baseCommand.replace("npm install", "npm install --no-bin-links");
17
+ }
18
+ return baseCommand;
19
+ }
20
+ /**
21
+ * Get install commands for all package managers, with WSL2 compatibility for npm.
22
+ *
23
+ * @param targetPath - The path where the command will be executed
24
+ * @returns Record of package manager to install command
25
+ */
26
+ function getInstallCommands(targetPath) {
27
+ return {
28
+ npm: buildNpmCommand("npm install", targetPath),
29
+ yarn: "yarn install",
30
+ pnpm: "pnpm install",
31
+ bun: "bun install"
32
+ };
33
+ }
34
+ /**
35
+ * Get install commands with --save flag for all package managers, with WSL2 compatibility for npm.
36
+ *
37
+ * @param targetPath - The path where the command will be executed
38
+ * @returns Record of package manager to install command
39
+ */
40
+ function getInstallSaveCommands(targetPath) {
41
+ return {
42
+ npm: buildNpmCommand("npm install --save", targetPath),
43
+ yarn: "yarn add",
44
+ pnpm: "pnpm add",
45
+ bun: "bun add"
46
+ };
47
+ }
48
+
49
+ //#endregion
50
+ export { getInstallCommands, getInstallSaveCommands };
51
+ //# sourceMappingURL=build-npm-command.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-npm-command.mjs","names":[],"sources":["../../src/utils/build-npm-command.ts"],"sourcesContent":["import { shouldUseNoBinLinks } from './detect-wsl'\n\n/**\n * Build an npm install command with appropriate flags for the environment.\n * Adds --no-bin-links when running in WSL2 on Windows filesystem to prevent\n * EPERM errors during npm install.\n *\n * @param baseCommand - The base npm command (e.g., 'npm install --save' or 'npm install')\n * @param targetPath - The path where the command will be executed\n * @returns The command with appropriate flags added\n */\nexport function buildNpmCommand(baseCommand: string, targetPath: string): string {\n // Only modify npm commands\n if (!baseCommand.startsWith('npm ')) {\n return baseCommand\n }\n\n // Add --no-bin-links if needed for WSL2 on Windows filesystem\n if (shouldUseNoBinLinks(targetPath)) {\n // Insert --no-bin-links after 'npm install' but before any other flags\n // Handle both 'npm install' and 'npm install --save' patterns\n if (baseCommand.includes('npm install')) {\n return baseCommand.replace('npm install', 'npm install --no-bin-links')\n }\n }\n\n return baseCommand\n}\n\n/**\n * Get install commands for all package managers, with WSL2 compatibility for npm.\n *\n * @param targetPath - The path where the command will be executed\n * @returns Record of package manager to install command\n */\nexport function getInstallCommands(targetPath: string): Record<string, string> {\n return {\n npm: buildNpmCommand('npm install', targetPath),\n yarn: 'yarn install',\n pnpm: 'pnpm install',\n bun: 'bun install',\n }\n}\n\n/**\n * Get install commands with --save flag for all package managers, with WSL2 compatibility for npm.\n *\n * @param targetPath - The path where the command will be executed\n * @returns Record of package manager to install command\n */\nexport function getInstallSaveCommands(targetPath: string): Record<string, string> {\n return {\n npm: buildNpmCommand('npm install --save', targetPath),\n yarn: 'yarn add',\n pnpm: 'pnpm add',\n bun: 'bun add',\n }\n}\n"],"mappings":";;;;;;;;;;;;AAWA,SAAgB,gBAAgB,aAAqB,YAA4B;AAE/E,KAAI,CAAC,YAAY,WAAW,OAAO,CACjC,QAAO;AAIT,KAAI,oBAAoB,WAAW,EAGjC;MAAI,YAAY,SAAS,cAAc,CACrC,QAAO,YAAY,QAAQ,eAAe,6BAA6B;;AAI3E,QAAO;;;;;;;;AAST,SAAgB,mBAAmB,YAA4C;AAC7E,QAAO;EACL,KAAK,gBAAgB,eAAe,WAAW;EAC/C,MAAM;EACN,MAAM;EACN,KAAK;EACN;;;;;;;;AASH,SAAgB,uBAAuB,YAA4C;AACjF,QAAO;EACL,KAAK,gBAAgB,sBAAsB,WAAW;EACtD,MAAM;EACN,MAAM;EACN,KAAK;EACN"}
@@ -0,0 +1,97 @@
1
+ import os from "os";
2
+ import { spawn } from "child_process";
3
+
4
+ //#region src/utils/check-build-tools.ts
5
+ const checkCommand = async (command, args) => {
6
+ return new Promise((resolve) => {
7
+ const child = spawn(command, args, {
8
+ stdio: "pipe",
9
+ shell: process.platform === "win32"
10
+ });
11
+ child.on("close", (code) => resolve(code === 0));
12
+ child.on("error", () => resolve(false));
13
+ });
14
+ };
15
+ const getPlatform = () => {
16
+ const platform = os.platform();
17
+ if (platform === "linux" || platform === "darwin" || platform === "win32") return platform;
18
+ return "unknown";
19
+ };
20
+ const getInstallInstructions = (missingTools, platform) => {
21
+ const toolsList = missingTools.join(", ");
22
+ switch (platform) {
23
+ case "linux": return `Missing build tools: ${toolsList}\n\nTo install on Ubuntu/Debian:
24
+ sudo apt-get update && sudo apt-get install build-essential pkg-config
25
+
26
+ To install on Fedora/RHEL:
27
+ sudo dnf install gcc gcc-c++ make pkg-config gawk jemalloc-devel
28
+
29
+ To install on Arch Linux:
30
+ sudo pacman -S base-devel pkg-config`;
31
+ case "darwin": return `Missing build tools: ${toolsList}\n\nTo install on macOS:
32
+ xcode-select --install
33
+
34
+ Or using Homebrew:
35
+ brew install make gcc pkg-config`;
36
+ case "win32": return `Missing build tools: ${toolsList}\n\nThe Redis Memory Server requires build tools to compile Redis.
37
+ On Windows, we recommend using an external Redis instance instead.
38
+
39
+ Option 1: Use an external Redis server
40
+ Set MOTIA_DISABLE_MEMORY_SERVER=true and configure MOTIA_REDIS_HOST
41
+
42
+ Option 2: Install Visual Studio Build Tools
43
+ Download from: https://visualstudio.microsoft.com/visual-cpp-build-tools/
44
+ Select "Desktop development with C++" workload
45
+
46
+ Option 3: Use WSL (Windows Subsystem for Linux)
47
+ Run your project inside WSL with Linux build tools installed`;
48
+ default: return `Missing build tools: ${toolsList}\n\nPlease install make and a C compiler (gcc or clang) for your platform.
49
+ Alternatively, use an external Redis server by setting:
50
+ MOTIA_DISABLE_MEMORY_SERVER=true
51
+ MOTIA_REDIS_HOST=<your-redis-host>`;
52
+ }
53
+ };
54
+ /**
55
+ * Check if required build tools are available for compiling Redis.
56
+ * The redis-memory-server package needs to compile Redis from source,
57
+ * which requires make and a C compiler.
58
+ */
59
+ const checkBuildTools = async () => {
60
+ const platform = getPlatform();
61
+ const missingTools = [];
62
+ if (platform === "win32") {
63
+ const hasNmake = await checkCommand("where", ["nmake"]);
64
+ const hasMake = await checkCommand("where", ["make"]);
65
+ if (!hasNmake && !hasMake) missingTools.push("make (or nmake)");
66
+ const hasCl = await checkCommand("where", ["cl"]);
67
+ const hasGcc = await checkCommand("where", ["gcc"]);
68
+ if (!hasCl && !hasGcc) missingTools.push("C compiler (cl.exe or gcc)");
69
+ } else {
70
+ if (!await checkCommand("make", ["--version"])) missingTools.push("make");
71
+ const hasGcc = await checkCommand("gcc", ["--version"]);
72
+ const hasCc = await checkCommand("cc", ["--version"]);
73
+ if (!hasGcc && !hasCc) missingTools.push("gcc (or cc)");
74
+ }
75
+ if (missingTools.length > 0) return {
76
+ success: false,
77
+ missingTools,
78
+ installInstructions: getInstallInstructions(missingTools, platform)
79
+ };
80
+ return {
81
+ success: true,
82
+ missingTools: [],
83
+ installInstructions: ""
84
+ };
85
+ };
86
+ /**
87
+ * Throws an error if required build tools are missing.
88
+ * Use this before attempting to start the Redis Memory Server.
89
+ */
90
+ const ensureBuildTools = async () => {
91
+ const result = await checkBuildTools();
92
+ if (!result.success) throw new Error("Redis Memory Server requires build tools to compile Redis.\n\n" + result.installInstructions);
93
+ };
94
+
95
+ //#endregion
96
+ export { ensureBuildTools };
97
+ //# sourceMappingURL=check-build-tools.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-build-tools.mjs","names":["missingTools: string[]"],"sources":["../../src/utils/check-build-tools.ts"],"sourcesContent":["import { spawn } from 'child_process'\nimport os from 'os'\n\nexport interface BuildToolsCheckResult {\n success: boolean\n missingTools: string[]\n installInstructions: string\n}\n\nconst checkCommand = async (command: string, args: string[]): Promise<boolean> => {\n return new Promise((resolve) => {\n const child = spawn(command, args, { stdio: 'pipe', shell: process.platform === 'win32' })\n child.on('close', (code) => resolve(code === 0))\n child.on('error', () => resolve(false))\n })\n}\n\nconst getPlatform = (): 'linux' | 'darwin' | 'win32' | 'unknown' => {\n const platform = os.platform()\n if (platform === 'linux' || platform === 'darwin' || platform === 'win32') {\n return platform\n }\n return 'unknown'\n}\n\nconst getInstallInstructions = (missingTools: string[], platform: string): string => {\n const toolsList = missingTools.join(', ')\n\n switch (platform) {\n case 'linux':\n return (\n `Missing build tools: ${toolsList}\\n\\n` +\n 'To install on Ubuntu/Debian:\\n' +\n ' sudo apt-get update && sudo apt-get install build-essential pkg-config\\n\\n' +\n 'To install on Fedora/RHEL:\\n' +\n ' sudo dnf install gcc gcc-c++ make pkg-config gawk jemalloc-devel\\n\\n' +\n 'To install on Arch Linux:\\n' +\n ' sudo pacman -S base-devel pkg-config'\n )\n case 'darwin':\n return (\n `Missing build tools: ${toolsList}\\n\\n` +\n 'To install on macOS:\\n' +\n ' xcode-select --install\\n\\n' +\n 'Or using Homebrew:\\n' +\n ' brew install make gcc pkg-config'\n )\n case 'win32':\n return (\n `Missing build tools: ${toolsList}\\n\\n` +\n 'The Redis Memory Server requires build tools to compile Redis.\\n' +\n 'On Windows, we recommend using an external Redis instance instead.\\n\\n' +\n 'Option 1: Use an external Redis server\\n' +\n ' Set MOTIA_DISABLE_MEMORY_SERVER=true and configure MOTIA_REDIS_HOST\\n\\n' +\n 'Option 2: Install Visual Studio Build Tools\\n' +\n ' Download from: https://visualstudio.microsoft.com/visual-cpp-build-tools/\\n' +\n ' Select \"Desktop development with C++\" workload\\n\\n' +\n 'Option 3: Use WSL (Windows Subsystem for Linux)\\n' +\n ' Run your project inside WSL with Linux build tools installed'\n )\n default:\n return (\n `Missing build tools: ${toolsList}\\n\\n` +\n 'Please install make and a C compiler (gcc or clang) for your platform.\\n' +\n 'Alternatively, use an external Redis server by setting:\\n' +\n ' MOTIA_DISABLE_MEMORY_SERVER=true\\n' +\n ' MOTIA_REDIS_HOST=<your-redis-host>'\n )\n }\n}\n\n/**\n * Check if required build tools are available for compiling Redis.\n * The redis-memory-server package needs to compile Redis from source,\n * which requires make and a C compiler.\n */\nexport const checkBuildTools = async (): Promise<BuildToolsCheckResult> => {\n const platform = getPlatform()\n const missingTools: string[] = []\n\n // On Windows, build tools work differently\n if (platform === 'win32') {\n // Check for nmake (Visual Studio) or make (MinGW/MSYS)\n const hasNmake = await checkCommand('where', ['nmake'])\n const hasMake = await checkCommand('where', ['make'])\n\n if (!hasNmake && !hasMake) {\n missingTools.push('make (or nmake)')\n }\n\n // Check for cl.exe (Visual Studio) or gcc (MinGW)\n const hasCl = await checkCommand('where', ['cl'])\n const hasGcc = await checkCommand('where', ['gcc'])\n\n if (!hasCl && !hasGcc) {\n missingTools.push('C compiler (cl.exe or gcc)')\n }\n } else {\n // Unix-like systems (Linux, macOS)\n const hasMake = await checkCommand('make', ['--version'])\n if (!hasMake) {\n missingTools.push('make')\n }\n\n // Check for gcc or cc (clang on macOS)\n const hasGcc = await checkCommand('gcc', ['--version'])\n const hasCc = await checkCommand('cc', ['--version'])\n\n if (!hasGcc && !hasCc) {\n missingTools.push('gcc (or cc)')\n }\n }\n\n if (missingTools.length > 0) {\n return {\n success: false,\n missingTools,\n installInstructions: getInstallInstructions(missingTools, platform),\n }\n }\n\n return {\n success: true,\n missingTools: [],\n installInstructions: '',\n }\n}\n\n/**\n * Throws an error if required build tools are missing.\n * Use this before attempting to start the Redis Memory Server.\n */\nexport const ensureBuildTools = async (): Promise<void> => {\n const result = await checkBuildTools()\n\n if (!result.success) {\n throw new Error('Redis Memory Server requires build tools to compile Redis.\\n\\n' + result.installInstructions)\n }\n}\n"],"mappings":";;;;AASA,MAAM,eAAe,OAAO,SAAiB,SAAqC;AAChF,QAAO,IAAI,SAAS,YAAY;EAC9B,MAAM,QAAQ,MAAM,SAAS,MAAM;GAAE,OAAO;GAAQ,OAAO,QAAQ,aAAa;GAAS,CAAC;AAC1F,QAAM,GAAG,UAAU,SAAS,QAAQ,SAAS,EAAE,CAAC;AAChD,QAAM,GAAG,eAAe,QAAQ,MAAM,CAAC;GACvC;;AAGJ,MAAM,oBAA8D;CAClE,MAAM,WAAW,GAAG,UAAU;AAC9B,KAAI,aAAa,WAAW,aAAa,YAAY,aAAa,QAChE,QAAO;AAET,QAAO;;AAGT,MAAM,0BAA0B,cAAwB,aAA6B;CACnF,MAAM,YAAY,aAAa,KAAK,KAAK;AAEzC,SAAQ,UAAR;EACE,KAAK,QACH,QACE,wBAAwB,UAAU;;;;;;;;EAQtC,KAAK,SACH,QACE,wBAAwB,UAAU;;;;;EAMtC,KAAK,QACH,QACE,wBAAwB,UAAU;;;;;;;;;;;;EAWtC,QACE,QACE,wBAAwB,UAAU;;;;;;;;;;;AAc1C,MAAa,kBAAkB,YAA4C;CACzE,MAAM,WAAW,aAAa;CAC9B,MAAMA,eAAyB,EAAE;AAGjC,KAAI,aAAa,SAAS;EAExB,MAAM,WAAW,MAAM,aAAa,SAAS,CAAC,QAAQ,CAAC;EACvD,MAAM,UAAU,MAAM,aAAa,SAAS,CAAC,OAAO,CAAC;AAErD,MAAI,CAAC,YAAY,CAAC,QAChB,cAAa,KAAK,kBAAkB;EAItC,MAAM,QAAQ,MAAM,aAAa,SAAS,CAAC,KAAK,CAAC;EACjD,MAAM,SAAS,MAAM,aAAa,SAAS,CAAC,MAAM,CAAC;AAEnD,MAAI,CAAC,SAAS,CAAC,OACb,cAAa,KAAK,6BAA6B;QAE5C;AAGL,MAAI,CADY,MAAM,aAAa,QAAQ,CAAC,YAAY,CAAC,CAEvD,cAAa,KAAK,OAAO;EAI3B,MAAM,SAAS,MAAM,aAAa,OAAO,CAAC,YAAY,CAAC;EACvD,MAAM,QAAQ,MAAM,aAAa,MAAM,CAAC,YAAY,CAAC;AAErD,MAAI,CAAC,UAAU,CAAC,MACd,cAAa,KAAK,cAAc;;AAIpC,KAAI,aAAa,SAAS,EACxB,QAAO;EACL,SAAS;EACT;EACA,qBAAqB,uBAAuB,cAAc,SAAS;EACpE;AAGH,QAAO;EACL,SAAS;EACT,cAAc,EAAE;EAChB,qBAAqB;EACtB;;;;;;AAOH,MAAa,mBAAmB,YAA2B;CACzD,MAAM,SAAS,MAAM,iBAAiB;AAEtC,KAAI,CAAC,OAAO,QACV,OAAM,IAAI,MAAM,mEAAmE,OAAO,oBAAoB"}
@@ -0,0 +1,39 @@
1
+ import { __require } from "../_virtual/rolldown_runtime.mjs";
2
+
3
+ //#region src/utils/detect-wsl.ts
4
+ /**
5
+ * Detects if we're running in WSL2 with a Windows filesystem path.
6
+ * This is used to determine if we need to add --no-bin-links to npm commands
7
+ * to avoid EPERM errors when npm tries to chmod files on Windows filesystem.
8
+ */
9
+ /**
10
+ * Check if the current environment is WSL (Windows Subsystem for Linux)
11
+ */
12
+ function isWsl() {
13
+ if (process.env.WSL_DISTRO_NAME || process.env.WSLENV) return true;
14
+ if (process.platform !== "linux") return false;
15
+ try {
16
+ const release = __require("os").release().toLowerCase();
17
+ return release.includes("microsoft") || release.includes("wsl");
18
+ } catch {
19
+ return false;
20
+ }
21
+ }
22
+ /**
23
+ * Check if a path is on the Windows filesystem (mounted via /mnt/)
24
+ */
25
+ function isWindowsFilesystemPath(targetPath) {
26
+ return targetPath.startsWith("/mnt/");
27
+ }
28
+ /**
29
+ * Determines if --no-bin-links should be used for npm commands.
30
+ * This is needed when running in WSL2 on Windows filesystem to avoid
31
+ * EPERM errors during npm install.
32
+ */
33
+ function shouldUseNoBinLinks(targetPath) {
34
+ return isWsl() && isWindowsFilesystemPath(targetPath);
35
+ }
36
+
37
+ //#endregion
38
+ export { shouldUseNoBinLinks };
39
+ //# sourceMappingURL=detect-wsl.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect-wsl.mjs","names":[],"sources":["../../src/utils/detect-wsl.ts"],"sourcesContent":["/**\n * Detects if we're running in WSL2 with a Windows filesystem path.\n * This is used to determine if we need to add --no-bin-links to npm commands\n * to avoid EPERM errors when npm tries to chmod files on Windows filesystem.\n */\n\n/**\n * Check if the current environment is WSL (Windows Subsystem for Linux)\n */\nexport function isWsl(): boolean {\n // Check for WSL-specific environment variables\n if (process.env.WSL_DISTRO_NAME || process.env.WSLENV) {\n return true\n }\n\n // Check if running on Linux (WSL reports as Linux)\n if (process.platform !== 'linux') {\n return false\n }\n\n // Additional check: look for WSL in the kernel version\n try {\n const os = require('os')\n const release = os.release().toLowerCase()\n return release.includes('microsoft') || release.includes('wsl')\n } catch {\n return false\n }\n}\n\n/**\n * Check if a path is on the Windows filesystem (mounted via /mnt/)\n */\nexport function isWindowsFilesystemPath(targetPath: string): boolean {\n // Windows drives are mounted at /mnt/c/, /mnt/d/, etc. in WSL\n return targetPath.startsWith('/mnt/')\n}\n\n/**\n * Determines if --no-bin-links should be used for npm commands.\n * This is needed when running in WSL2 on Windows filesystem to avoid\n * EPERM errors during npm install.\n */\nexport function shouldUseNoBinLinks(targetPath: string): boolean {\n return isWsl() && isWindowsFilesystemPath(targetPath)\n}\n"],"mappings":";;;;;;;;;;;AASA,SAAgB,QAAiB;AAE/B,KAAI,QAAQ,IAAI,mBAAmB,QAAQ,IAAI,OAC7C,QAAO;AAIT,KAAI,QAAQ,aAAa,QACvB,QAAO;AAIT,KAAI;EAEF,MAAM,oBADa,KAAK,CACL,SAAS,CAAC,aAAa;AAC1C,SAAO,QAAQ,SAAS,YAAY,IAAI,QAAQ,SAAS,MAAM;SACzD;AACN,SAAO;;;;;;AAOX,SAAgB,wBAAwB,YAA6B;AAEnE,QAAO,WAAW,WAAW,QAAQ;;;;;;;AAQvC,SAAgB,oBAAoB,YAA6B;AAC/D,QAAO,OAAO,IAAI,wBAAwB,WAAW"}
@@ -4,7 +4,10 @@ import { exec } from "child_process";
4
4
  const executeCommand = async (command, rootDir, options) => {
5
5
  const { silent = false } = options || {};
6
6
  return new Promise((resolve, reject) => {
7
- exec(command, { cwd: rootDir }, (error, stdout, stderr) => {
7
+ exec(command, {
8
+ cwd: rootDir,
9
+ env: process.env
10
+ }, (error, stdout, stderr) => {
8
11
  if (error) {
9
12
  if (!silent) console.error(`exec error: ${error}`);
10
13
  reject(error);
@@ -1 +1 @@
1
- {"version":3,"file":"execute-command.mjs","names":[],"sources":["../../src/utils/execute-command.ts"],"sourcesContent":["import { exec } from 'child_process'\n\ninterface ExecuteCommandOptions {\n silent?: boolean\n}\n\nexport const executeCommand = async (\n command: string,\n rootDir: string,\n options?: ExecuteCommandOptions,\n): Promise<string> => {\n const { silent = false } = options || {}\n\n return new Promise((resolve, reject) => {\n exec(command, { cwd: rootDir }, (error, stdout, stderr) => {\n if (error) {\n if (!silent) {\n console.error(`exec error: ${error}`)\n }\n reject(error)\n return\n }\n\n if (!silent) {\n if (stdout) console.log(stdout.toString())\n if (stderr) console.error(stderr.toString())\n }\n\n resolve(stdout.toString())\n })\n })\n}\n"],"mappings":";;;AAMA,MAAa,iBAAiB,OAC5B,SACA,SACA,YACoB;CACpB,MAAM,EAAE,SAAS,UAAU,WAAW,EAAE;AAExC,QAAO,IAAI,SAAS,SAAS,WAAW;AACtC,OAAK,SAAS,EAAE,KAAK,SAAS,GAAG,OAAO,QAAQ,WAAW;AACzD,OAAI,OAAO;AACT,QAAI,CAAC,OACH,SAAQ,MAAM,eAAe,QAAQ;AAEvC,WAAO,MAAM;AACb;;AAGF,OAAI,CAAC,QAAQ;AACX,QAAI,OAAQ,SAAQ,IAAI,OAAO,UAAU,CAAC;AAC1C,QAAI,OAAQ,SAAQ,MAAM,OAAO,UAAU,CAAC;;AAG9C,WAAQ,OAAO,UAAU,CAAC;IAC1B;GACF"}
1
+ {"version":3,"file":"execute-command.mjs","names":[],"sources":["../../src/utils/execute-command.ts"],"sourcesContent":["import { exec } from 'child_process'\n\ninterface ExecuteCommandOptions {\n silent?: boolean\n}\n\nexport const executeCommand = async (\n command: string,\n rootDir: string,\n options?: ExecuteCommandOptions,\n): Promise<string> => {\n const { silent = false } = options || {}\n\n return new Promise((resolve, reject) => {\n exec(command, { cwd: rootDir, env: process.env }, (error, stdout, stderr) => {\n if (error) {\n if (!silent) {\n console.error(`exec error: ${error}`)\n }\n reject(error)\n return\n }\n\n if (!silent) {\n if (stdout) console.log(stdout.toString())\n if (stderr) console.error(stderr.toString())\n }\n\n resolve(stdout.toString())\n })\n })\n}\n"],"mappings":";;;AAMA,MAAa,iBAAiB,OAC5B,SACA,SACA,YACoB;CACpB,MAAM,EAAE,SAAS,UAAU,WAAW,EAAE;AAExC,QAAO,IAAI,SAAS,SAAS,WAAW;AACtC,OAAK,SAAS;GAAE,KAAK;GAAS,KAAK,QAAQ;GAAK,GAAG,OAAO,QAAQ,WAAW;AAC3E,OAAI,OAAO;AACT,QAAI,CAAC,OACH,SAAQ,MAAM,eAAe,QAAQ;AAEvC,WAAO,MAAM;AACb;;AAGF,OAAI,CAAC,QAAQ;AACX,QAAI,OAAQ,SAAQ,IAAI,OAAO,UAAU,CAAC;AAC1C,QAAI,OAAQ,SAAQ,MAAM,OAAO,UAAU,CAAC;;AAG9C,WAAQ,OAAO,UAAU,CAAC;IAC1B;GACF"}
@@ -1,5 +1,6 @@
1
1
  import { internalLogger } from "./internal-logger.mjs";
2
2
  import { getPythonCommand } from "./python-version-utils.mjs";
3
+ import { getInstallCommands } from "./build-npm-command.mjs";
3
4
  import { getPackageManager } from "./get-package-manager.mjs";
4
5
  import fs from "fs";
5
6
  import path from "path";
@@ -7,12 +8,9 @@ import pc from "picocolors";
7
8
 
8
9
  //#region src/utils/validate-python-environment.ts
9
10
  function getInstallCommand(baseDir) {
10
- switch (getPackageManager(baseDir)) {
11
- case "yarn": return "yarn install";
12
- case "pnpm": return "pnpm install";
13
- case "npm":
14
- default: return "npm install";
15
- }
11
+ const pm = getPackageManager(baseDir);
12
+ const installCommands = getInstallCommands(baseDir);
13
+ return installCommands[pm] || installCommands["npm"];
16
14
  }
17
15
  async function validatePythonEnvironment({ baseDir, hasPythonFiles, pythonVersion = "3.13" }) {
18
16
  if (!hasPythonFiles) return {
@@ -41,17 +39,18 @@ async function validatePythonEnvironment({ baseDir, hasPythonFiles, pythonVersio
41
39
  hasPythonFiles: true
42
40
  };
43
41
  }
44
- const libPath = path.join(venvPath, "lib");
42
+ const libDirName = process.platform === "win32" ? "Lib" : "lib";
43
+ const libPath = path.join(venvPath, libDirName);
45
44
  if (!fs.existsSync(libPath)) {
46
45
  internalLogger.error("Python environment is incomplete");
47
- internalLogger.info("The python_modules directory exists but appears to be corrupted");
46
+ internalLogger.info(`The python_modules/${libDirName} directory was not found`);
48
47
  internalLogger.info(`Run ${pc.cyan(installCmd)} to recreate your Python environment`);
49
48
  return {
50
49
  success: false,
51
50
  hasPythonFiles: true
52
51
  };
53
52
  }
54
- try {
53
+ if (process.platform !== "win32") try {
55
54
  if (fs.readdirSync(libPath).filter((item) => item.startsWith("python3")).length === 0) {
56
55
  internalLogger.error("Python environment is incomplete");
57
56
  internalLogger.info("The python_modules/lib directory exists but contains no Python version directories");
@@ -1 +1 @@
1
- {"version":3,"file":"validate-python-environment.mjs","names":["error: any"],"sources":["../../src/utils/validate-python-environment.ts"],"sourcesContent":["import fs from 'fs'\nimport path from 'path'\nimport pc from 'picocolors'\nimport { getPackageManager } from './get-package-manager'\nimport { internalLogger } from './internal-logger'\nimport { getPythonCommand } from './python-version-utils'\n\nexport interface ValidationResult {\n success: boolean\n hasPythonFiles: boolean\n}\n\ninterface ValidateConfig {\n baseDir: string\n hasPythonFiles: boolean\n pythonVersion?: string\n}\n\nexport function getInstallCommand(baseDir: string): string {\n const pm = getPackageManager(baseDir)\n switch (pm) {\n case 'yarn':\n return 'yarn install'\n case 'pnpm':\n return 'pnpm install'\n case 'npm':\n default:\n return 'npm install'\n }\n}\n\nexport async function validatePythonEnvironment({\n baseDir,\n hasPythonFiles,\n pythonVersion = '3.13',\n}: ValidateConfig): Promise<ValidationResult> {\n if (!hasPythonFiles) {\n return { success: true, hasPythonFiles: false }\n }\n\n const installCmd = getInstallCommand(baseDir)\n\n try {\n await getPythonCommand(pythonVersion, baseDir)\n } catch {\n internalLogger.error('Python is not installed')\n internalLogger.info('Python files were detected in your project but Python 3 is not available')\n internalLogger.info('Please install Python 3.10 or higher: https://www.python.org/downloads/')\n return { success: false, hasPythonFiles: true }\n }\n\n const venvPath = path.join(baseDir, 'python_modules')\n if (!fs.existsSync(venvPath)) {\n internalLogger.error('Python environment not configured')\n internalLogger.info('The python_modules directory was not found')\n internalLogger.info(`Run ${pc.cyan(installCmd)} to set up your Python environment`)\n return { success: false, hasPythonFiles: true }\n }\n\n const libPath = path.join(venvPath, 'lib')\n if (!fs.existsSync(libPath)) {\n internalLogger.error('Python environment is incomplete')\n internalLogger.info('The python_modules directory exists but appears to be corrupted')\n internalLogger.info(`Run ${pc.cyan(installCmd)} to recreate your Python environment`)\n return { success: false, hasPythonFiles: true }\n }\n\n try {\n const libContents = fs.readdirSync(libPath)\n const pythonDirs = libContents.filter((item) => item.startsWith('python3'))\n\n if (pythonDirs.length === 0) {\n internalLogger.error('Python environment is incomplete')\n internalLogger.info('The python_modules/lib directory exists but contains no Python version directories')\n internalLogger.info(`Run ${pc.cyan(installCmd)} to recreate your Python environment`)\n return { success: false, hasPythonFiles: true }\n }\n } catch (error: any) {\n internalLogger.error('Python environment is incomplete')\n internalLogger.info('The python_modules/lib directory cannot be read')\n internalLogger.info(`Run ${pc.cyan(installCmd)} to recreate your Python environment`)\n return { success: false, hasPythonFiles: true }\n }\n\n return { success: true, hasPythonFiles: true }\n}\n"],"mappings":";;;;;;;;AAkBA,SAAgB,kBAAkB,SAAyB;AAEzD,SADW,kBAAkB,QAAQ,EACrC;EACE,KAAK,OACH,QAAO;EACT,KAAK,OACH,QAAO;EACT,KAAK;EACL,QACE,QAAO;;;AAIb,eAAsB,0BAA0B,EAC9C,SACA,gBACA,gBAAgB,UAC4B;AAC5C,KAAI,CAAC,eACH,QAAO;EAAE,SAAS;EAAM,gBAAgB;EAAO;CAGjD,MAAM,aAAa,kBAAkB,QAAQ;AAE7C,KAAI;AACF,QAAM,iBAAiB,eAAe,QAAQ;SACxC;AACN,iBAAe,MAAM,0BAA0B;AAC/C,iBAAe,KAAK,2EAA2E;AAC/F,iBAAe,KAAK,0EAA0E;AAC9F,SAAO;GAAE,SAAS;GAAO,gBAAgB;GAAM;;CAGjD,MAAM,WAAW,KAAK,KAAK,SAAS,iBAAiB;AACrD,KAAI,CAAC,GAAG,WAAW,SAAS,EAAE;AAC5B,iBAAe,MAAM,oCAAoC;AACzD,iBAAe,KAAK,6CAA6C;AACjE,iBAAe,KAAK,OAAO,GAAG,KAAK,WAAW,CAAC,oCAAoC;AACnF,SAAO;GAAE,SAAS;GAAO,gBAAgB;GAAM;;CAGjD,MAAM,UAAU,KAAK,KAAK,UAAU,MAAM;AAC1C,KAAI,CAAC,GAAG,WAAW,QAAQ,EAAE;AAC3B,iBAAe,MAAM,mCAAmC;AACxD,iBAAe,KAAK,kEAAkE;AACtF,iBAAe,KAAK,OAAO,GAAG,KAAK,WAAW,CAAC,sCAAsC;AACrF,SAAO;GAAE,SAAS;GAAO,gBAAgB;GAAM;;AAGjD,KAAI;AAIF,MAHoB,GAAG,YAAY,QAAQ,CACZ,QAAQ,SAAS,KAAK,WAAW,UAAU,CAAC,CAE5D,WAAW,GAAG;AAC3B,kBAAe,MAAM,mCAAmC;AACxD,kBAAe,KAAK,qFAAqF;AACzG,kBAAe,KAAK,OAAO,GAAG,KAAK,WAAW,CAAC,sCAAsC;AACrF,UAAO;IAAE,SAAS;IAAO,gBAAgB;IAAM;;UAE1CA,OAAY;AACnB,iBAAe,MAAM,mCAAmC;AACxD,iBAAe,KAAK,kDAAkD;AACtE,iBAAe,KAAK,OAAO,GAAG,KAAK,WAAW,CAAC,sCAAsC;AACrF,SAAO;GAAE,SAAS;GAAO,gBAAgB;GAAM;;AAGjD,QAAO;EAAE,SAAS;EAAM,gBAAgB;EAAM"}
1
+ {"version":3,"file":"validate-python-environment.mjs","names":["error: any"],"sources":["../../src/utils/validate-python-environment.ts"],"sourcesContent":["import fs from 'fs'\nimport path from 'path'\nimport pc from 'picocolors'\nimport { getInstallCommands } from './build-npm-command'\nimport { getPackageManager } from './get-package-manager'\nimport { internalLogger } from './internal-logger'\nimport { getPythonCommand } from './python-version-utils'\n\nexport interface ValidationResult {\n success: boolean\n hasPythonFiles: boolean\n}\n\ninterface ValidateConfig {\n baseDir: string\n hasPythonFiles: boolean\n pythonVersion?: string\n}\n\nexport function getInstallCommand(baseDir: string): string {\n const pm = getPackageManager(baseDir)\n const installCommands = getInstallCommands(baseDir)\n return installCommands[pm] || installCommands['npm']\n}\n\nexport async function validatePythonEnvironment({\n baseDir,\n hasPythonFiles,\n pythonVersion = '3.13',\n}: ValidateConfig): Promise<ValidationResult> {\n if (!hasPythonFiles) {\n return { success: true, hasPythonFiles: false }\n }\n\n const installCmd = getInstallCommand(baseDir)\n\n try {\n await getPythonCommand(pythonVersion, baseDir)\n } catch {\n internalLogger.error('Python is not installed')\n internalLogger.info('Python files were detected in your project but Python 3 is not available')\n internalLogger.info('Please install Python 3.10 or higher: https://www.python.org/downloads/')\n return { success: false, hasPythonFiles: true }\n }\n\n const venvPath = path.join(baseDir, 'python_modules')\n if (!fs.existsSync(venvPath)) {\n internalLogger.error('Python environment not configured')\n internalLogger.info('The python_modules directory was not found')\n internalLogger.info(`Run ${pc.cyan(installCmd)} to set up your Python environment`)\n return { success: false, hasPythonFiles: true }\n }\n\n const libDirName = process.platform === 'win32' ? 'Lib' : 'lib'\n const libPath = path.join(venvPath, libDirName)\n if (!fs.existsSync(libPath)) {\n internalLogger.error('Python environment is incomplete')\n internalLogger.info(`The python_modules/${libDirName} directory was not found`)\n internalLogger.info(`Run ${pc.cyan(installCmd)} to recreate your Python environment`)\n return { success: false, hasPythonFiles: true }\n }\n\n if (process.platform !== 'win32') {\n try {\n const libContents = fs.readdirSync(libPath)\n const pythonDirs = libContents.filter((item) => item.startsWith('python3'))\n\n if (pythonDirs.length === 0) {\n internalLogger.error('Python environment is incomplete')\n internalLogger.info('The python_modules/lib directory exists but contains no Python version directories')\n internalLogger.info(`Run ${pc.cyan(installCmd)} to recreate your Python environment`)\n return { success: false, hasPythonFiles: true }\n }\n } catch (error: any) {\n internalLogger.error('Python environment is incomplete')\n internalLogger.info('The python_modules/lib directory cannot be read')\n internalLogger.info(`Run ${pc.cyan(installCmd)} to recreate your Python environment`)\n return { success: false, hasPythonFiles: true }\n }\n }\n\n return { success: true, hasPythonFiles: true }\n}\n"],"mappings":";;;;;;;;;AAmBA,SAAgB,kBAAkB,SAAyB;CACzD,MAAM,KAAK,kBAAkB,QAAQ;CACrC,MAAM,kBAAkB,mBAAmB,QAAQ;AACnD,QAAO,gBAAgB,OAAO,gBAAgB;;AAGhD,eAAsB,0BAA0B,EAC9C,SACA,gBACA,gBAAgB,UAC4B;AAC5C,KAAI,CAAC,eACH,QAAO;EAAE,SAAS;EAAM,gBAAgB;EAAO;CAGjD,MAAM,aAAa,kBAAkB,QAAQ;AAE7C,KAAI;AACF,QAAM,iBAAiB,eAAe,QAAQ;SACxC;AACN,iBAAe,MAAM,0BAA0B;AAC/C,iBAAe,KAAK,2EAA2E;AAC/F,iBAAe,KAAK,0EAA0E;AAC9F,SAAO;GAAE,SAAS;GAAO,gBAAgB;GAAM;;CAGjD,MAAM,WAAW,KAAK,KAAK,SAAS,iBAAiB;AACrD,KAAI,CAAC,GAAG,WAAW,SAAS,EAAE;AAC5B,iBAAe,MAAM,oCAAoC;AACzD,iBAAe,KAAK,6CAA6C;AACjE,iBAAe,KAAK,OAAO,GAAG,KAAK,WAAW,CAAC,oCAAoC;AACnF,SAAO;GAAE,SAAS;GAAO,gBAAgB;GAAM;;CAGjD,MAAM,aAAa,QAAQ,aAAa,UAAU,QAAQ;CAC1D,MAAM,UAAU,KAAK,KAAK,UAAU,WAAW;AAC/C,KAAI,CAAC,GAAG,WAAW,QAAQ,EAAE;AAC3B,iBAAe,MAAM,mCAAmC;AACxD,iBAAe,KAAK,sBAAsB,WAAW,0BAA0B;AAC/E,iBAAe,KAAK,OAAO,GAAG,KAAK,WAAW,CAAC,sCAAsC;AACrF,SAAO;GAAE,SAAS;GAAO,gBAAgB;GAAM;;AAGjD,KAAI,QAAQ,aAAa,QACvB,KAAI;AAIF,MAHoB,GAAG,YAAY,QAAQ,CACZ,QAAQ,SAAS,KAAK,WAAW,UAAU,CAAC,CAE5D,WAAW,GAAG;AAC3B,kBAAe,MAAM,mCAAmC;AACxD,kBAAe,KAAK,qFAAqF;AACzG,kBAAe,KAAK,OAAO,GAAG,KAAK,WAAW,CAAC,sCAAsC;AACrF,UAAO;IAAE,SAAS;IAAO,gBAAgB;IAAM;;UAE1CA,OAAY;AACnB,iBAAe,MAAM,mCAAmC;AACxD,iBAAe,KAAK,kDAAkD;AACtE,iBAAe,KAAK,OAAO,GAAG,KAAK,WAAW,CAAC,sCAAsC;AACrF,SAAO;GAAE,SAAS;GAAO,gBAAgB;GAAM;;AAInD,QAAO;EAAE,SAAS;EAAM,gBAAgB;EAAM"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "motia",
3
3
  "description": "Build production-grade backends with a single primitive. APIs, background jobs, Queues, Workflows, and AI agents - unified in one system with built-in State management, Streaming, and Observability.",
4
- "version": "0.17.10-beta.192",
4
+ "version": "0.17.11-beta.193",
5
5
  "license": "Elastic-2.0",
6
6
  "type": "module",
7
7
  "repository": {
@@ -46,13 +46,13 @@
46
46
  "table": "^6.9.0",
47
47
  "ts-node": "^10.9.2",
48
48
  "zod": "^4.1.13",
49
- "@motiadev/adapter-bullmq-events": "0.17.10-beta.192",
50
- "@motiadev/adapter-redis-cron": "0.17.10-beta.192",
51
- "@motiadev/stream-client-node": "0.17.10-beta.192",
52
- "@motiadev/core": "0.17.10-beta.192",
53
- "@motiadev/workbench": "0.17.10-beta.192",
54
- "@motiadev/adapter-redis-state": "0.17.10-beta.192",
55
- "@motiadev/adapter-redis-streams": "0.17.10-beta.192"
49
+ "@motiadev/adapter-bullmq-events": "0.17.11-beta.193",
50
+ "@motiadev/adapter-redis-streams": "0.17.11-beta.193",
51
+ "@motiadev/adapter-redis-cron": "0.17.11-beta.193",
52
+ "@motiadev/adapter-redis-state": "0.17.11-beta.193",
53
+ "@motiadev/core": "0.17.11-beta.193",
54
+ "@motiadev/stream-client-node": "0.17.11-beta.193",
55
+ "@motiadev/workbench": "0.17.11-beta.193"
56
56
  },
57
57
  "devDependencies": {
58
58
  "@amplitude/analytics-types": "^2.9.2",