motia 0.14.0-beta.165-246284 → 0.14.0-beta.165-076789

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.
Files changed (31) hide show
  1. package/dist/create/index.mjs +1 -1
  2. package/dist/create/index.mjs.map +1 -1
  3. package/dist/create/interactive.mjs +6 -5
  4. package/dist/create/interactive.mjs.map +1 -1
  5. package/dist/create/templates/hello/README.md.txt +1 -2
  6. package/dist/create/templates/hello_js/README.md.txt +1 -2
  7. package/dist/create/templates/hello_js/steps/hello/hello-api.step.js.txt +3 -5
  8. package/dist/create/templates/hello_js/steps/hello/process-greeting.step.js.txt +3 -5
  9. package/dist/create/templates/hello_multilang/README.md.txt +106 -0
  10. package/dist/create/templates/hello_multilang/motia-workbench.json +21 -0
  11. package/dist/create/templates/hello_multilang/motia.config.ts.txt +10 -0
  12. package/dist/create/templates/hello_multilang/requirements.txt +2 -0
  13. package/dist/create/templates/hello_multilang/steps/hello/hello-api.step.ts.txt +46 -0
  14. package/dist/create/templates/hello_multilang/steps/hello/log-greeting.step.js.txt +34 -0
  15. package/dist/create/templates/hello_multilang/steps/hello/process_greeting_step.py.txt +75 -0
  16. package/dist/create/templates/hello_python/README.md.txt +1 -2
  17. package/dist/create/templates/index.mjs +2 -1
  18. package/dist/create/templates/index.mjs.map +1 -1
  19. package/dist/create/templates/index.ts +1 -0
  20. package/dist/create/templates/nodejs/README.md.txt +1 -2
  21. package/dist/create/templates/plugin/README.md.txt +12 -57
  22. package/dist/create/templates/plugin/package.json.txt +24 -32
  23. package/dist/create/templates/plugin/src/components/example-page.tsx.txt +2 -1
  24. package/dist/create/templates/plugin/src/index.ts.txt +2 -0
  25. package/dist/create/templates/plugin/vite.config.ts.txt +30 -0
  26. package/dist/create/templates/python/README.md.txt +1 -2
  27. package/dist/docker/setup.mjs +2 -8
  28. package/dist/docker/setup.mjs.map +1 -1
  29. package/package.json +9 -8
  30. package/dist/create/templates/plugin/tsdown.config.ts.txt +0 -53
  31. package/dist/cursor-rules/dot-files/.aider.conf.yml +0 -32
@@ -150,7 +150,7 @@ const create = async ({ projectName, template, cursorEnabled, context }) => {
150
150
  let packageManager;
151
151
  if (!isPluginTemplate) {
152
152
  packageManager = await installNodeDependencies(rootDir, context);
153
- if (template.includes("python")) await pythonInstall({ baseDir: rootDir });
153
+ if (template.includes("python") || template.includes("multilang")) await pythonInstall({ baseDir: rootDir });
154
154
  await generateTypes(rootDir);
155
155
  } else packageManager = await preparePackageManager(rootDir, context);
156
156
  const projectDirName = path.basename(rootDir);
@@ -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 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 } 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 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 }[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 = ['ts-node@10.9.2', 'typescript@5.7.3', '@types/react@19.1.1'].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) => {\n let packageManager = 'npm'\n const detectedPackageManager = getPackageManager(rootDir)\n\n if (detectedPackageManager !== 'unknown') {\n context.log('package-manager-detected', (message: Message) =>\n message.tag('info').append('Detected package manager').append(detectedPackageManager, 'gray'),\n )\n packageManager = detectedPackageManager\n } else {\n context.log('package-manager-using-default', (message: Message) =>\n message.tag('info').append('Using default 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}\n\nexport const create = async ({ projectName, template, cursorEnabled, context }: 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 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 let packageManager: string\n if (!isPluginTemplate) {\n packageManager = await installNodeDependencies(rootDir, context)\n\n if (template.includes('python')) {\n await pythonInstall({ baseDir: rootDir })\n }\n\n await generateTypes(rootDir)\n } else {\n // For plugin template, just detect the package manager\n packageManager = await preparePackageManager(rootDir, context)\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 context.log('success-signoff', (message) => message.text('Happy coding! 🚀'))\n context.log('success-blank-7', (message) => message.text(''))\n}\n"],"mappings":"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"}
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 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 } 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 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 }[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 = ['ts-node@10.9.2', 'typescript@5.7.3', '@types/react@19.1.1'].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) => {\n let packageManager = 'npm'\n const detectedPackageManager = getPackageManager(rootDir)\n\n if (detectedPackageManager !== 'unknown') {\n context.log('package-manager-detected', (message: Message) =>\n message.tag('info').append('Detected package manager').append(detectedPackageManager, 'gray'),\n )\n packageManager = detectedPackageManager\n } else {\n context.log('package-manager-using-default', (message: Message) =>\n message.tag('info').append('Using default 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}\n\nexport const create = async ({ projectName, template, cursorEnabled, context }: 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 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 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 // For plugin template, just detect the package manager\n packageManager = await preparePackageManager(rootDir, context)\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 context.log('success-signoff', (message) => message.text('Happy coding! 🚀'))\n context.log('success-blank-7', (message) => message.text(''))\n}\n"],"mappings":"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"}
@@ -4,11 +4,12 @@ import inquirer from "inquirer";
4
4
 
5
5
  //#region src/create/interactive.ts
6
6
  const choices = {
7
- "motia-tutorial-typescript": "Tutorial (TypeScript)",
8
- "motia-tutorial-python": "Tutorial (Python)",
9
- "starter-typescript": "Starter (TypeScript)",
10
- "starter-javascript": "Starter (JavaScript)",
11
- "starter-python": "Starter (Python)"
7
+ "motia-tutorial-typescript": "Tutorial (TypeScript only)",
8
+ "motia-tutorial-python": "Tutorial (Python only)",
9
+ "starter-multilang": "Starter (All languages; TS/JS + Python)",
10
+ "starter-python": "Starter (Python only)",
11
+ "starter-typescript": "Starter (TypeScript only)",
12
+ "starter-javascript": "Starter (JavaScript only)"
12
13
  };
13
14
  const createInteractive = async (args, context) => {
14
15
  context.log("welcome", (message) => message.append(`\n🚀 ${pc.bold(args.plugin ? "Welcome to Motia Plugin Creator!" : "Welcome to Motia Project Creator!")}`));
@@ -1 +1 @@
1
- {"version":3,"file":"interactive.mjs","names":["choices: Record<string, string>","questions: QuestionCollection<never>[]","answers: InteractiveAnswers"],"sources":["../../src/create/interactive.ts"],"sourcesContent":["import inquirer, { type QuestionCollection } from 'inquirer'\nimport pc from 'picocolors'\nimport type { CliContext, Message } from '../cloud/config-utils'\nimport { create } from './index'\n\ninterface InteractiveAnswers {\n template: string\n projectName: string\n}\n\nconst choices: Record<string, string> = {\n 'motia-tutorial-typescript': 'Tutorial (TypeScript)',\n 'motia-tutorial-python': 'Tutorial (Python)',\n 'starter-typescript': 'Starter (TypeScript)',\n 'starter-javascript': 'Starter (JavaScript)',\n 'starter-python': 'Starter (Python)',\n}\n\ninterface CreateInteractiveArgs {\n name?: string\n template?: string\n plugin?: boolean\n}\n\nexport const createInteractive = async (args: CreateInteractiveArgs, context: CliContext): Promise<void> => {\n context.log('welcome', (message: Message) =>\n message.append(\n `\\n🚀 ${pc.bold(args.plugin ? 'Welcome to Motia Plugin Creator!' : 'Welcome to Motia Project Creator!')}`,\n ),\n )\n\n const questions: QuestionCollection<never>[] = []\n\n let name = args.name\n let template = args.template\n\n if (args.plugin) {\n if (!args.name) {\n context.log('failed', (message: Message) =>\n message.tag('failed').append(`Project name is required: ${pc.bold('motia create --plugin [project-name]')}\\n`),\n )\n return\n }\n\n return create({\n projectName: args.name,\n template: 'plugin',\n cursorEnabled: false,\n context,\n })\n } else if (!args.template) {\n questions.push({\n type: 'list',\n name: 'template',\n message: 'What template do you want to use? (Use arrow keys)',\n choices: Object.keys(choices).map((key) => ({\n name: choices[key],\n value: key,\n })),\n })\n }\n\n if (!args.name) {\n questions.push({\n type: 'input',\n name: 'projectName',\n message: 'Project name (leave blank to use current folder):',\n validate: (input: string) => {\n if (input && input.trim().length > 0) {\n if (!/^[a-zA-Z0-9][a-zA-Z0-9-_]*$/.test(input.trim())) {\n return 'Project name must start with a letter or number and contain only letters, numbers, hyphens, and underscores'\n }\n }\n return true\n },\n filter: (input: string) => input.trim(),\n })\n }\n\n if (questions.length > 0) {\n const answers: InteractiveAnswers = await inquirer.prompt(questions)\n name = args.name || answers.projectName\n template = args.template || answers.template\n }\n\n context.log('creating', (message: Message) => message.append('\\n🔨 Creating your Motia project...\\n'))\n\n await create({\n projectName: name || '.',\n template: template || 'motia-tutorial-typescript',\n cursorEnabled: true, // Default to true for cursor rules\n context,\n })\n\n process.exit(0)\n}\n"],"mappings":";;;;;AAUA,MAAMA,UAAkC;CACtC,6BAA6B;CAC7B,yBAAyB;CACzB,sBAAsB;CACtB,sBAAsB;CACtB,kBAAkB;CACnB;AAQD,MAAa,oBAAoB,OAAO,MAA6B,YAAuC;AAC1G,SAAQ,IAAI,YAAY,YACtB,QAAQ,OACN,QAAQ,GAAG,KAAK,KAAK,SAAS,qCAAqC,oCAAoC,GACxG,CACF;CAED,MAAMC,YAAyC,EAAE;CAEjD,IAAI,OAAO,KAAK;CAChB,IAAI,WAAW,KAAK;AAEpB,KAAI,KAAK,QAAQ;AACf,MAAI,CAAC,KAAK,MAAM;AACd,WAAQ,IAAI,WAAW,YACrB,QAAQ,IAAI,SAAS,CAAC,OAAO,6BAA6B,GAAG,KAAK,uCAAuC,CAAC,IAAI,CAC/G;AACD;;AAGF,SAAO,OAAO;GACZ,aAAa,KAAK;GAClB,UAAU;GACV,eAAe;GACf;GACD,CAAC;YACO,CAAC,KAAK,SACf,WAAU,KAAK;EACb,MAAM;EACN,MAAM;EACN,SAAS;EACT,SAAS,OAAO,KAAK,QAAQ,CAAC,KAAK,SAAS;GAC1C,MAAM,QAAQ;GACd,OAAO;GACR,EAAE;EACJ,CAAC;AAGJ,KAAI,CAAC,KAAK,KACR,WAAU,KAAK;EACb,MAAM;EACN,MAAM;EACN,SAAS;EACT,WAAW,UAAkB;AAC3B,OAAI,SAAS,MAAM,MAAM,CAAC,SAAS,GACjC;QAAI,CAAC,8BAA8B,KAAK,MAAM,MAAM,CAAC,CACnD,QAAO;;AAGX,UAAO;;EAET,SAAS,UAAkB,MAAM,MAAM;EACxC,CAAC;AAGJ,KAAI,UAAU,SAAS,GAAG;EACxB,MAAMC,UAA8B,MAAM,SAAS,OAAO,UAAU;AACpE,SAAO,KAAK,QAAQ,QAAQ;AAC5B,aAAW,KAAK,YAAY,QAAQ;;AAGtC,SAAQ,IAAI,aAAa,YAAqB,QAAQ,OAAO,wCAAwC,CAAC;AAEtG,OAAM,OAAO;EACX,aAAa,QAAQ;EACrB,UAAU,YAAY;EACtB,eAAe;EACf;EACD,CAAC;AAEF,SAAQ,KAAK,EAAE"}
1
+ {"version":3,"file":"interactive.mjs","names":["choices: Record<string, string>","questions: QuestionCollection<never>[]","answers: InteractiveAnswers"],"sources":["../../src/create/interactive.ts"],"sourcesContent":["import inquirer, { type QuestionCollection } from 'inquirer'\nimport pc from 'picocolors'\nimport type { CliContext, Message } from '../cloud/config-utils'\nimport { create } from './index'\n\ninterface InteractiveAnswers {\n template: string\n projectName: string\n}\n\nconst choices: Record<string, string> = {\n 'motia-tutorial-typescript': 'Tutorial (TypeScript only)',\n 'motia-tutorial-python': 'Tutorial (Python only)',\n 'starter-multilang': 'Starter (All languages; TS/JS + Python)',\n 'starter-python': 'Starter (Python only)',\n 'starter-typescript': 'Starter (TypeScript only)',\n 'starter-javascript': 'Starter (JavaScript only)',\n}\n\ninterface CreateInteractiveArgs {\n name?: string\n template?: string\n plugin?: boolean\n}\n\nexport const createInteractive = async (args: CreateInteractiveArgs, context: CliContext): Promise<void> => {\n context.log('welcome', (message: Message) =>\n message.append(\n `\\n🚀 ${pc.bold(args.plugin ? 'Welcome to Motia Plugin Creator!' : 'Welcome to Motia Project Creator!')}`,\n ),\n )\n\n const questions: QuestionCollection<never>[] = []\n\n let name = args.name\n let template = args.template\n\n if (args.plugin) {\n if (!args.name) {\n context.log('failed', (message: Message) =>\n message.tag('failed').append(`Project name is required: ${pc.bold('motia create --plugin [project-name]')}\\n`),\n )\n return\n }\n\n return create({\n projectName: args.name,\n template: 'plugin',\n cursorEnabled: false,\n context,\n })\n } else if (!args.template) {\n questions.push({\n type: 'list',\n name: 'template',\n message: 'What template do you want to use? (Use arrow keys)',\n choices: Object.keys(choices).map((key) => ({\n name: choices[key],\n value: key,\n })),\n })\n }\n\n if (!args.name) {\n questions.push({\n type: 'input',\n name: 'projectName',\n message: 'Project name (leave blank to use current folder):',\n validate: (input: string) => {\n if (input && input.trim().length > 0) {\n if (!/^[a-zA-Z0-9][a-zA-Z0-9-_]*$/.test(input.trim())) {\n return 'Project name must start with a letter or number and contain only letters, numbers, hyphens, and underscores'\n }\n }\n return true\n },\n filter: (input: string) => input.trim(),\n })\n }\n\n if (questions.length > 0) {\n const answers: InteractiveAnswers = await inquirer.prompt(questions)\n name = args.name || answers.projectName\n template = args.template || answers.template\n }\n\n context.log('creating', (message: Message) => message.append('\\n🔨 Creating your Motia project...\\n'))\n\n await create({\n projectName: name || '.',\n template: template || 'motia-tutorial-typescript',\n cursorEnabled: true, // Default to true for cursor rules\n context,\n })\n\n process.exit(0)\n}\n"],"mappings":";;;;;AAUA,MAAMA,UAAkC;CACtC,6BAA6B;CAC7B,yBAAyB;CACzB,qBAAqB;CACrB,kBAAkB;CAClB,sBAAsB;CACtB,sBAAsB;CACvB;AAQD,MAAa,oBAAoB,OAAO,MAA6B,YAAuC;AAC1G,SAAQ,IAAI,YAAY,YACtB,QAAQ,OACN,QAAQ,GAAG,KAAK,KAAK,SAAS,qCAAqC,oCAAoC,GACxG,CACF;CAED,MAAMC,YAAyC,EAAE;CAEjD,IAAI,OAAO,KAAK;CAChB,IAAI,WAAW,KAAK;AAEpB,KAAI,KAAK,QAAQ;AACf,MAAI,CAAC,KAAK,MAAM;AACd,WAAQ,IAAI,WAAW,YACrB,QAAQ,IAAI,SAAS,CAAC,OAAO,6BAA6B,GAAG,KAAK,uCAAuC,CAAC,IAAI,CAC/G;AACD;;AAGF,SAAO,OAAO;GACZ,aAAa,KAAK;GAClB,UAAU;GACV,eAAe;GACf;GACD,CAAC;YACO,CAAC,KAAK,SACf,WAAU,KAAK;EACb,MAAM;EACN,MAAM;EACN,SAAS;EACT,SAAS,OAAO,KAAK,QAAQ,CAAC,KAAK,SAAS;GAC1C,MAAM,QAAQ;GACd,OAAO;GACR,EAAE;EACJ,CAAC;AAGJ,KAAI,CAAC,KAAK,KACR,WAAU,KAAK;EACb,MAAM;EACN,MAAM;EACN,SAAS;EACT,WAAW,UAAkB;AAC3B,OAAI,SAAS,MAAM,MAAM,CAAC,SAAS,GACjC;QAAI,CAAC,8BAA8B,KAAK,MAAM,MAAM,CAAC,CACnD,QAAO;;AAGX,UAAO;;EAET,SAAS,UAAkB,MAAM,MAAM;EACxC,CAAC;AAGJ,KAAI,UAAU,SAAS,GAAG;EACxB,MAAMC,UAA8B,MAAM,SAAS,OAAO,UAAU;AACpE,SAAO,KAAK,QAAQ,QAAQ;AAC5B,aAAW,KAAK,YAAY,QAAQ;;AAGtC,SAAQ,IAAI,aAAa,YAAqB,QAAQ,OAAO,wCAAwC,CAAC;AAEtG,OAAM,OAAO;EACX,aAAa,QAAQ;EACrB,UAAU,YAAY;EACtB,eAAe;EACf;EACD,CAAC;AAEF,SAAQ,KAAK,EAAE"}
@@ -80,5 +80,4 @@ Steps are auto-discovered from your `steps/` or `src/` directories - no manual r
80
80
  - [Documentation](https://motia.dev/docs) - Complete guides and API reference
81
81
  - [Quick Start Guide](https://motia.dev/docs/getting-started/quick-start) - Detailed getting started tutorial
82
82
  - [Core Concepts](https://motia.dev/docs/concepts/overview) - Learn about Steps and Motia architecture
83
- - [Discord Community](https://discord.gg/motia) - Get help and connect with other developers
84
-
83
+ - [Discord Community](https://discord.gg/motia) - Get help and connect with other developers
@@ -80,5 +80,4 @@ Steps are auto-discovered from your `steps/` or `src/` directories - no manual r
80
80
  - [Documentation](https://motia.dev/docs) - Complete guides and API reference
81
81
  - [Quick Start Guide](https://motia.dev/docs/getting-started/quick-start) - Detailed getting started tutorial
82
82
  - [Core Concepts](https://motia.dev/docs/concepts/overview) - Learn about Steps and Motia architecture
83
- - [Discord Community](https://discord.gg/motia) - Get help and connect with other developers
84
-
83
+ - [Discord Community](https://discord.gg/motia) - Get help and connect with other developers
@@ -1,6 +1,6 @@
1
- const { z } = require('zod');
1
+ import { z } from 'zod';
2
2
 
3
- const config = {
3
+ export const config = {
4
4
  name: 'HelloAPI',
5
5
  type: 'api',
6
6
  path: '/hello',
@@ -17,7 +17,7 @@ const config = {
17
17
  }
18
18
  };
19
19
 
20
- const handler = async (_, { emit, logger }) => {
20
+ export const handler = async (_, { emit, logger }) => {
21
21
  const appName = process.env.APP_NAME || 'Motia App';
22
22
  const timestamp = new Date().toISOString();
23
23
 
@@ -43,5 +43,3 @@ const handler = async (_, { emit, logger }) => {
43
43
  }
44
44
  };
45
45
  };
46
-
47
- module.exports = { config, handler };
@@ -1,4 +1,4 @@
1
- const { z } = require('zod');
1
+ import { z } from 'zod';
2
2
 
3
3
  const inputSchema = z.object({
4
4
  timestamp: z.string(),
@@ -7,7 +7,7 @@ const inputSchema = z.object({
7
7
  requestId: z.string()
8
8
  });
9
9
 
10
- const config = {
10
+ export const config = {
11
11
  name: 'ProcessGreeting',
12
12
  type: 'event',
13
13
  description: 'Processes greeting in the background',
@@ -17,7 +17,7 @@ const config = {
17
17
  input: inputSchema
18
18
  };
19
19
 
20
- const handler = async (input, { logger, state }) => {
20
+ export const handler = async (input, { logger, state }) => {
21
21
  const { timestamp, appName, greetingPrefix, requestId } = input;
22
22
 
23
23
  logger.info('Processing greeting', { requestId, appName });
@@ -38,5 +38,3 @@ const handler = async (input, { logger, state }) => {
38
38
  storedInState: true
39
39
  });
40
40
  };
41
-
42
- module.exports = { config, handler };
@@ -0,0 +1,106 @@
1
+ # {{PROJECT_NAME}}
2
+
3
+ A Motia project created with the **multi-language** starter template (TypeScript + Python).
4
+
5
+ ## What is Motia?
6
+
7
+ Motia is an open-source, unified backend framework that eliminates runtime fragmentation by bringing **APIs, background jobs, queueing, streaming, state, workflows, AI agents, observability, scaling, and deployment** into one unified system using a single core primitive, the **Step**.
8
+
9
+ ## Polyglot Architecture
10
+
11
+ This template demonstrates Motia's polyglot capabilities by combining:
12
+
13
+ - **TypeScript**: API endpoint (`hello-api.step.ts`) - handles HTTP requests
14
+ - **Python**: Event processor (`process_greeting_step.py`) - handles background processing
15
+ - **JavaScript**: Logger (`log-greeting.step.js`) - handles workflow completion
16
+
17
+ This shows how you can use the best language for each task while keeping everything in a single unified system.
18
+
19
+ ## Quick Start
20
+
21
+ ```bash
22
+ # Start the development server
23
+ npm run dev
24
+ # or
25
+ yarn dev
26
+ # or
27
+ pnpm dev
28
+ ```
29
+
30
+ This starts the Motia runtime and the **Workbench** - a powerful UI for developing and debugging your workflows. By default, it's available at [`http://localhost:3000`](http://localhost:3000).
31
+
32
+ ```bash
33
+ # Test your first endpoint
34
+ curl http://localhost:3000/hello
35
+ ```
36
+
37
+ ## How It Works
38
+
39
+ 1. **TypeScript API Step** receives the HTTP request at `/hello`
40
+ 2. It emits a `process-greeting` event with the request data
41
+ 3. **Python Event Step** picks up the event, processes it, and stores the result in state
42
+ 4. Python emits a `greeting-processed` event
43
+ 5. **JavaScript Event Step** logs the completed workflow
44
+
45
+ ## Step Types
46
+
47
+ Every Step has a `type` that defines how it triggers:
48
+
49
+ | Type | When it runs | Use case |
50
+ |------|--------------|----------|
51
+ | **`api`** | HTTP request | REST APIs, webhooks |
52
+ | **`event`** | Event emitted | Background jobs, workflows |
53
+ | **`cron`** | Schedule | Cleanup, reports, reminders |
54
+
55
+ ## Development Commands
56
+
57
+ ```bash
58
+ # Start Workbench and development server
59
+ npm run dev
60
+ # or
61
+ yarn dev
62
+ # or
63
+ pnpm dev
64
+
65
+ # Start production server (without hot reload)
66
+ npm run start
67
+ # or
68
+ yarn start
69
+ # or
70
+ pnpm start
71
+
72
+ # Generate TypeScript types from Step configs
73
+ npm run generate-types
74
+ # or
75
+ yarn generate-types
76
+ # or
77
+ pnpm generate-types
78
+
79
+ # Build project for deployment
80
+ npm run build
81
+ # or
82
+ yarn build
83
+ # or
84
+ pnpm build
85
+ ```
86
+
87
+ ## Project Structure
88
+
89
+ ```
90
+ steps/ # Your Step definitions
91
+ ├── hello/
92
+ │ ├── hello-api.step.ts # TypeScript API endpoint
93
+ │ ├── process_greeting_step.py # Python event processor
94
+ │ └── log-greeting.step.js # JavaScript logger
95
+ motia.config.ts # Motia configuration
96
+ requirements.txt # Python dependencies
97
+ ```
98
+
99
+ Steps are auto-discovered from your `steps/` or `src/` directories - no manual registration required.
100
+
101
+ ## Learn More
102
+
103
+ - [Documentation](https://motia.dev/docs) - Complete guides and API reference
104
+ - [Quick Start Guide](https://motia.dev/docs/getting-started/quick-start) - Detailed getting started tutorial
105
+ - [Core Concepts](https://motia.dev/docs/concepts/overview) - Learn about Steps and Motia architecture
106
+ - [Discord Community](https://discord.gg/motia) - Get help and connect with other developers
@@ -0,0 +1,21 @@
1
+ [
2
+ {
3
+ "id": "hello-world-flow",
4
+ "config": {
5
+ "steps/hello/log-greeting.step.js": {
6
+ "x": 409,
7
+ "y": 44
8
+ },
9
+ "steps/hello/hello-api.step.ts": {
10
+ "x": -409,
11
+ "y": 0,
12
+ "sourceHandlePosition": "right"
13
+ },
14
+ "steps/hello/process_greeting_step.py": {
15
+ "x": 0,
16
+ "y": 34,
17
+ "sourceHandlePosition": "right"
18
+ }
19
+ }
20
+ }
21
+ ]
@@ -0,0 +1,10 @@
1
+ import { config } from '@motiadev/core'
2
+ import endpointPlugin from '@motiadev/plugin-endpoint/plugin'
3
+ import logsPlugin from '@motiadev/plugin-logs/plugin'
4
+ import observabilityPlugin from '@motiadev/plugin-observability/plugin'
5
+ import statesPlugin from '@motiadev/plugin-states/plugin'
6
+ import bullmqPlugin from '@motiadev/plugin-bullmq/plugin'
7
+
8
+ export default config({
9
+ plugins: [observabilityPlugin, statesPlugin, endpointPlugin, logsPlugin, bullmqPlugin],
10
+ })
@@ -0,0 +1,2 @@
1
+ # Optional: Uncomment if you want to use Pydantic for validation
2
+ # pydantic>=2.0.0
@@ -0,0 +1,46 @@
1
+ import type { ApiRouteConfig, Handlers } from 'motia';
2
+ import { z } from 'zod';
3
+
4
+ export const config: ApiRouteConfig = {
5
+ name: 'HelloAPI',
6
+ type: 'api',
7
+ path: '/hello',
8
+ method: 'GET',
9
+ description: 'Receives hello request and emits event for Python processing',
10
+ emits: ['process-greeting'],
11
+ flows: ['hello-world-flow'],
12
+ responseSchema: {
13
+ 200: z.object({
14
+ message: z.string(),
15
+ status: z.string(),
16
+ appName: z.string()
17
+ })
18
+ }
19
+ };
20
+
21
+ export const handler: Handlers['HelloAPI'] = async (_, { emit, logger }) => {
22
+ const appName = process.env.APP_NAME || 'Motia App';
23
+ const timestamp = new Date().toISOString();
24
+
25
+ logger.info('Hello API endpoint called (TypeScript)', { appName, timestamp });
26
+
27
+ // Emit event for background processing in Python
28
+ await emit({
29
+ topic: 'process-greeting',
30
+ data: {
31
+ timestamp,
32
+ appName,
33
+ greetingPrefix: process.env.GREETING_PREFIX || 'Hello',
34
+ requestId: Math.random().toString(36).substring(7)
35
+ }
36
+ });
37
+
38
+ return {
39
+ status: 200,
40
+ body: {
41
+ message: 'Hello request received! Processing in Python...',
42
+ status: 'processing',
43
+ appName
44
+ }
45
+ };
46
+ };
@@ -0,0 +1,34 @@
1
+ import { z } from 'zod';
2
+
3
+ const inputSchema = z.object({
4
+ requestId: z.string(),
5
+ greeting: z.string(),
6
+ processedBy: z.string()
7
+ });
8
+
9
+ export const config = {
10
+ name: 'LogGreeting',
11
+ type: 'event',
12
+ description: 'Logs the processed greeting (JavaScript)',
13
+ subscribes: ['greeting-processed'],
14
+ emits: [],
15
+ flows: ['hello-world-flow'],
16
+ input: inputSchema
17
+ };
18
+
19
+ export const handler = async (input, { logger, state }) => {
20
+ const { requestId, greeting, processedBy } = input;
21
+
22
+ logger.info('Logging greeting (JavaScript)', { requestId, processedBy });
23
+
24
+ // Retrieve the stored greeting from state
25
+ const storedData = await state.get('greetings', requestId);
26
+
27
+ logger.info('Greeting workflow complete (JavaScript)', {
28
+ requestId,
29
+ greeting,
30
+ processedBy,
31
+ storedAt: storedData?.processedAt,
32
+ workflowComplete: true
33
+ });
34
+ };
@@ -0,0 +1,75 @@
1
+ from datetime import datetime
2
+
3
+ # Optional: Using Pydantic for validation (remove if not using Pydantic)
4
+ try:
5
+ from pydantic import BaseModel
6
+
7
+ class GreetingInput(BaseModel):
8
+ timestamp: str
9
+ appName: str
10
+ greetingPrefix: str
11
+ requestId: str
12
+
13
+ # If using Pydantic, we can generate the JSON schema
14
+ input_schema = GreetingInput.model_json_schema()
15
+ except ImportError:
16
+ # Without Pydantic, define JSON schema manually
17
+ input_schema = {
18
+ "type": "object",
19
+ "properties": {
20
+ "timestamp": {"type": "string"},
21
+ "appName": {"type": "string"},
22
+ "greetingPrefix": {"type": "string"},
23
+ "requestId": {"type": "string"}
24
+ },
25
+ "required": ["timestamp", "appName", "greetingPrefix", "requestId"]
26
+ }
27
+
28
+ config = {
29
+ "name": "ProcessGreeting",
30
+ "type": "event",
31
+ "description": "Processes greeting in the background (Python)",
32
+ "subscribes": ["process-greeting"],
33
+ "emits": ["greeting-processed"],
34
+ "flows": ["hello-world-flow"],
35
+ "input": input_schema
36
+ }
37
+
38
+ async def handler(input_data, context):
39
+ # Extract data from input
40
+ timestamp = input_data.get("timestamp")
41
+ app_name = input_data.get("appName")
42
+ greeting_prefix = input_data.get("greetingPrefix")
43
+ request_id = input_data.get("requestId")
44
+
45
+ context.logger.info("Processing greeting (Python)", {
46
+ "request_id": request_id,
47
+ "app_name": app_name
48
+ })
49
+
50
+ greeting = f"{greeting_prefix} {app_name}!"
51
+
52
+ # Store result in state (demonstrates state usage)
53
+ # Note: The state.set method takes (groupId, key, value)
54
+ await context.state.set("greetings", request_id, {
55
+ "greeting": greeting,
56
+ "processedAt": datetime.utcnow().isoformat(),
57
+ "originalTimestamp": timestamp,
58
+ "processedBy": "python"
59
+ })
60
+
61
+ context.logger.info("Greeting processed successfully (Python)", {
62
+ "request_id": request_id,
63
+ "greeting": greeting,
64
+ "stored_in_state": True
65
+ })
66
+
67
+ # Emit event for JavaScript notification step
68
+ await context.emit({
69
+ "topic": "greeting-processed",
70
+ "data": {
71
+ "requestId": request_id,
72
+ "greeting": greeting,
73
+ "processedBy": "python"
74
+ }
75
+ })
@@ -81,5 +81,4 @@ Steps are auto-discovered from your `steps/` or `src/` directories - no manual r
81
81
  - [Documentation](https://motia.dev/docs) - Complete guides and API reference
82
82
  - [Quick Start Guide](https://motia.dev/docs/getting-started/quick-start) - Detailed getting started tutorial
83
83
  - [Core Concepts](https://motia.dev/docs/concepts/overview) - Learn about Steps and Motia architecture
84
- - [Discord Community](https://discord.gg/motia) - Get help and connect with other developers
85
-
84
+ - [Discord Community](https://discord.gg/motia) - Get help and connect with other developers
@@ -7,7 +7,8 @@ const templates = {
7
7
  plugin: generatePluginTemplate("plugin"),
8
8
  "starter-typescript": generateTemplateSteps("hello"),
9
9
  "starter-javascript": generateTemplateSteps("hello_js"),
10
- "starter-python": generateTemplateSteps("hello_python")
10
+ "starter-python": generateTemplateSteps("hello_python"),
11
+ "starter-multilang": generateTemplateSteps("hello_multilang")
11
12
  };
12
13
 
13
14
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["templates: Record<string, Generator>"],"sources":["../../../src/create/templates/index.ts"],"sourcesContent":["import { type Generator, generatePluginTemplate, generateTemplateSteps } from './generate'\n\nexport const templates: Record<string, Generator> = {\n 'motia-tutorial-typescript': generateTemplateSteps('nodejs'),\n 'motia-tutorial-python': generateTemplateSteps('python'),\n plugin: generatePluginTemplate('plugin'),\n 'starter-typescript': generateTemplateSteps('hello'),\n 'starter-javascript': generateTemplateSteps('hello_js'),\n 'starter-python': generateTemplateSteps('hello_python'),\n}\n"],"mappings":";;;AAEA,MAAaA,YAAuC;CAClD,6BAA6B,sBAAsB,SAAS;CAC5D,yBAAyB,sBAAsB,SAAS;CACxD,QAAQ,uBAAuB,SAAS;CACxC,sBAAsB,sBAAsB,QAAQ;CACpD,sBAAsB,sBAAsB,WAAW;CACvD,kBAAkB,sBAAsB,eAAe;CACxD"}
1
+ {"version":3,"file":"index.mjs","names":["templates: Record<string, Generator>"],"sources":["../../../src/create/templates/index.ts"],"sourcesContent":["import { type Generator, generatePluginTemplate, generateTemplateSteps } from './generate'\n\nexport const templates: Record<string, Generator> = {\n 'motia-tutorial-typescript': generateTemplateSteps('nodejs'),\n 'motia-tutorial-python': generateTemplateSteps('python'),\n plugin: generatePluginTemplate('plugin'),\n 'starter-typescript': generateTemplateSteps('hello'),\n 'starter-javascript': generateTemplateSteps('hello_js'),\n 'starter-python': generateTemplateSteps('hello_python'),\n 'starter-multilang': generateTemplateSteps('hello_multilang'),\n}\n"],"mappings":";;;AAEA,MAAaA,YAAuC;CAClD,6BAA6B,sBAAsB,SAAS;CAC5D,yBAAyB,sBAAsB,SAAS;CACxD,QAAQ,uBAAuB,SAAS;CACxC,sBAAsB,sBAAsB,QAAQ;CACpD,sBAAsB,sBAAsB,WAAW;CACvD,kBAAkB,sBAAsB,eAAe;CACvD,qBAAqB,sBAAsB,kBAAkB;CAC9D"}
@@ -7,4 +7,5 @@ export const templates: Record<string, Generator> = {
7
7
  'starter-typescript': generateTemplateSteps('hello'),
8
8
  'starter-javascript': generateTemplateSteps('hello_js'),
9
9
  'starter-python': generateTemplateSteps('hello_python'),
10
+ 'starter-multilang': generateTemplateSteps('hello_multilang'),
10
11
  }
@@ -89,5 +89,4 @@ This project includes an interactive tutorial that will guide you through:
89
89
  - [Documentation](https://motia.dev/docs) - Complete guides and API reference
90
90
  - [Quick Start Guide](https://motia.dev/docs/getting-started/quick-start) - Detailed getting started tutorial
91
91
  - [Core Concepts](https://motia.dev/docs/concepts/overview) - Learn about Steps and Motia architecture
92
- - [Discord Community](https://discord.gg/motia) - Get help and connect with other developers
93
-
92
+ - [Discord Community](https://discord.gg/motia) - Get help and connect with other developers
@@ -1,17 +1,15 @@
1
- # @motiadev/plugin-example
1
+ # {{PROJECT_NAME}}
2
2
 
3
- A minimal example plugin demonstrating the Motia plugin system.
3
+ A minimal plugin demonstrating the Motia plugin system.
4
4
 
5
5
  ## Overview
6
6
 
7
7
  This plugin serves as a reference implementation showing how to create custom workbench plugins for Motia. It demonstrates:
8
8
 
9
9
  - Basic plugin structure and configuration
10
- - Creating custom workbench tabs with position control
11
- - Using Motia's UI component library (`@motiadev/ui`)
12
- - Building with tsdown and TypeScript
13
- - Tailwind CSS v4 styling with PostCSS
14
- - React Compiler optimization via Babel
10
+ - Creating custom workbench tabs
11
+ - Using Motia's UI component library
12
+ - Building with Vite and TypeScript
15
13
 
16
14
  ## Installation
17
15
 
@@ -37,73 +35,30 @@ pnpm run clean
37
35
  To use this plugin in your Motia project, import it in your `motia.config.ts`:
38
36
 
39
37
  ```typescript
40
- import examplePlugin from '@motiadev/plugin-example/plugin'
38
+ import examplePlugin from '{{PROJECT_NAME}}/plugin'
41
39
 
42
40
  export default {
43
41
  plugins: [examplePlugin],
44
42
  }
45
43
  ```
46
44
 
47
- ## Plugin Configuration
48
-
49
- The plugin exports a function that receives the `MotiaPluginContext` and returns a `MotiaPlugin` object:
50
-
51
- ```typescript
52
- import type { MotiaPlugin, MotiaPluginContext } from '@motiadev/core'
53
-
54
- export default function plugin(_motia: MotiaPluginContext): MotiaPlugin {
55
- return {
56
- workbench: [
57
- {
58
- packageName: '@motiadev/plugin-example',
59
- cssImports: ['@motiadev/plugin-example/dist/index.css'],
60
- label: 'Example',
61
- position: 'bottom',
62
- componentName: 'ExamplePage',
63
- labelIcon: 'sparkles',
64
- },
65
- ],
66
- }
67
- }
68
- ```
69
-
70
- ### Workbench Options
71
-
72
- | Option | Description |
73
- | --------------- | ------------------------------------------ |
74
- | `packageName` | The npm package name for dynamic imports |
75
- | `cssImports` | Array of CSS files to load with the plugin |
76
- | `label` | Display name shown in the workbench tab |
77
- | `position` | Tab position: `'top'` or `'bottom'` |
78
- | `componentName` | Name of the exported React component |
79
- | `labelIcon` | Lucide icon name for the tab |
80
-
81
45
  ## Structure
82
46
 
83
47
  ```
84
- plugin-example/
48
+ {{PROJECT_NAME}}/
85
49
  ├── src/
86
50
  │ ├── components/
87
51
  │ │ └── example-page.tsx # Main UI component
88
- │ ├── index.ts # Package entry point (exports components)
52
+ │ ├── index.ts # Package entry point
89
53
  │ ├── plugin.ts # Plugin definition
90
- │ └── styles.css # Tailwind CSS styles
91
- ├── dist/ # Build output
54
+ │ └── styles.css # Tailwind styles
92
55
  ├── package.json
93
56
  ├── tsconfig.json
94
- ├── tsdown.config.ts # Build configuration
95
- ├── postcss.config.js # PostCSS/Tailwind config
57
+ ├── vite.config.ts
96
58
  └── README.md
97
59
  ```
98
60
 
99
- ## Features Demonstrated
100
-
101
- - **Custom Workbench Tab**: Adds an "Example" tab to the bottom panel
102
- - **UI Components**: Uses `Badge` and `Button` from `@motiadev/ui`
103
- - **Icons**: Integrates Lucide React icons
104
- - **Responsive Layout**: Grid-based responsive design with Tailwind CSS
105
- - **Type Safety**: Full TypeScript support with proper type declarations
106
-
107
61
  ## Learn More
108
62
 
109
- For detailed documentation on creating plugins, see the [Plugins Guide](../../packages/docs/content/docs/development-guide/plugins.mdx).
63
+ For detailed documentation on creating plugins, see the [Motia Plugins Guide](https://motia.dev/docs/development-guide/plugins).
64
+
@@ -1,55 +1,47 @@
1
1
  {
2
2
  "name": "{{PROJECT_NAME}}",
3
- "version": "0.14.0-beta.164",
3
+ "version": "0.0.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
7
7
  "exports": {
8
8
  ".": {
9
- "development": "./src/index.ts",
10
- "default": "./dist/index.js"
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js",
11
+ "require": "./dist/index.cjs"
11
12
  },
12
13
  "./plugin": {
13
- "development": "./src/plugin.ts",
14
- "default": "./dist/plugin.js"
14
+ "types": "./dist/plugin.d.ts",
15
+ "import": "./dist/plugin.js",
16
+ "require": "./dist/plugin.cjs"
15
17
  },
16
- "./package.json": "./package.json"
18
+ "./styles.css": "./dist/styles.css"
17
19
  },
18
20
  "files": [
19
21
  "dist"
20
22
  ],
21
23
  "scripts": {
22
- "build": "tsdown",
23
- "dev": "tsdown --watch",
24
+ "build": "vite build",
25
+ "dev": "vite build --watch",
24
26
  "clean": "rm -rf dist"
25
27
  },
26
28
  "dependencies": {
27
- "lucide-react": "^0.555.0",
28
- "react": "^19.2.0"
29
- },
30
- "peerDependencies": {
31
- "@motiadev/core": "workspace:*",
32
- "@motiadev/ui": "workspace:*"
29
+ "lucide-react": "^0.548.0"
33
30
  },
34
31
  "devDependencies": {
35
- "@rollup/plugin-babel": "^6.1.0",
36
- "@tailwindcss/postcss": "^4.1.17",
37
- "rollup-plugin-postcss": "^4.0.2",
38
- "@types/node": "^24.10.1",
39
- "@types/react": "^19.2.7",
40
- "babel-plugin-react-compiler": "^1.0.0",
41
- "publint": "^0.3.15",
42
- "tailwindcss": "^4.1.17",
43
- "tsdown": "^0.16.8",
32
+ "@motiadev/core": "latest",
33
+ "@motiadev/ui": "latest",
34
+ "@tailwindcss/postcss": "^4.1.16",
35
+ "@tailwindcss/vite": "^4.1.16",
36
+ "@types/node": "^24.9.2",
37
+ "@types/react": "^19.2.2",
38
+ "@vitejs/plugin-react": "^5.1.0",
39
+ "postcss": "^8.5.6",
40
+ "react": "^19.2.0",
41
+ "tailwindcss": "^4.1.16",
44
42
  "typescript": "^5.9.3",
45
- "unplugin-unused": "^0.5.6"
46
- },
47
- "module": "./dist/index.js",
48
- "publishConfig": {
49
- "exports": {
50
- ".": "./dist/index.js",
51
- "./plugin": "./dist/plugin.js",
52
- "./package.json": "./package.json"
53
- }
43
+ "vite": "^7.1.12",
44
+ "vite-plugin-dts": "^4.5.4"
54
45
  }
55
46
  }
47
+
@@ -60,4 +60,5 @@ export const ExamplePage: React.FC = () => {
60
60
  </div>
61
61
  </div>
62
62
  )
63
- }
63
+ }
64
+
@@ -1,2 +1,4 @@
1
+ import './styles.css'
2
+
1
3
  export { ExamplePage } from './components/example-page'
2
4
 
@@ -0,0 +1,30 @@
1
+ import tailwindcss from '@tailwindcss/vite'
2
+ import react from '@vitejs/plugin-react'
3
+ import { resolve } from 'path'
4
+ import { defineConfig } from 'vite'
5
+ import dts from 'vite-plugin-dts'
6
+
7
+ export default defineConfig({
8
+ plugins: [react(), tailwindcss(), dts({ insertTypesEntry: true })],
9
+ build: {
10
+ lib: {
11
+ entry: {
12
+ index: resolve(__dirname, 'src/index.ts'),
13
+ plugin: resolve(__dirname, 'src/plugin.ts'),
14
+ },
15
+ name: '{{PLUGIN_NAME}}',
16
+ formats: ['es', 'cjs'],
17
+ fileName: (format, entryName) => `${entryName}.${format === 'es' ? 'js' : 'cjs'}`,
18
+ },
19
+ rollupOptions: {
20
+ external: ['react', 'react-dom', '@motiadev/core', '@motiadev/ui'],
21
+ },
22
+ cssCodeSplit: false,
23
+ },
24
+ resolve: {
25
+ alias: {
26
+ '@': resolve(__dirname, 'src'),
27
+ },
28
+ },
29
+ })
30
+
@@ -90,5 +90,4 @@ This project includes an interactive tutorial that will guide you through:
90
90
  - [Documentation](https://motia.dev/docs) - Complete guides and API reference
91
91
  - [Quick Start Guide](https://motia.dev/docs/getting-started/quick-start) - Detailed getting started tutorial
92
92
  - [Core Concepts](https://motia.dev/docs/concepts/overview) - Learn about Steps and Motia architecture
93
- - [Discord Community](https://discord.gg/motia) - Get help and connect with other developers
94
-
93
+ - [Discord Community](https://discord.gg/motia) - Get help and connect with other developers
@@ -8,12 +8,6 @@ import * as readline$1 from "readline";
8
8
 
9
9
  //#region src/docker/setup.ts
10
10
  const __dirname = path$1.dirname(fileURLToPath(import.meta.url));
11
- const resolveTemplatesDir = () => {
12
- const localTemplates = path$1.join(__dirname, "./templates");
13
- if (fs$1.existsSync(localTemplates)) return localTemplates;
14
- return path$1.join(__dirname, "../../../docker/templates");
15
- };
16
- const templatesDir = resolveTemplatesDir();
17
11
  const updatePackageJson = () => {
18
12
  const packageJsonPath = path$1.join(process.cwd(), "package.json");
19
13
  if (fs$1.existsSync(packageJsonPath)) {
@@ -42,7 +36,7 @@ const createDockerfile = async () => {
42
36
  return;
43
37
  }
44
38
  }
45
- const dockerfileContent = fs$1.readFileSync(path$1.join(templatesDir, "MotiaDockerSample"), "utf-8");
39
+ const dockerfileContent = fs$1.readFileSync(path$1.join(__dirname, "./templates", "MotiaDockerSample"), "utf-8");
46
40
  try {
47
41
  fs$1.writeFileSync(dockerfilePath, dockerfileContent);
48
42
  console.log("Dockerfile generated successfully!");
@@ -54,7 +48,7 @@ const createDockerfile = async () => {
54
48
  const createDockerignore = async () => {
55
49
  identifyUser();
56
50
  trackEvent("docker_setup_command", { project_name: getProjectIdentifier(process.cwd()) });
57
- const dockerignoreContent = fs$1.readFileSync(path$1.join(templatesDir, ".dockerignore.sample"), "utf-8");
51
+ const dockerignoreContent = fs$1.readFileSync(path$1.join(__dirname, "./templates", ".dockerignore.sample"), "utf-8");
58
52
  const dockerignorePath = path$1.join(process.cwd(), ".dockerignore");
59
53
  if (fs$1.existsSync(dockerignorePath)) {
60
54
  console.log(".dockerignore already exists");
@@ -1 +1 @@
1
- {"version":3,"file":"setup.mjs","names":["path","fs","readline"],"sources":["../../src/docker/setup.ts"],"sourcesContent":["import { getProjectIdentifier, trackEvent } from '@motiadev/core'\nimport * as fs from 'fs'\nimport * as path from 'path'\nimport * as readline from 'readline'\nimport { fileURLToPath } from 'url'\nimport { identifyUser } from '../utils/analytics'\nimport { printMotiaDockerIntro } from './utils/print-intro'\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url))\n\nconst resolveTemplatesDir = (): string => {\n const localTemplates = path.join(__dirname, './templates')\n if (fs.existsSync(localTemplates)) {\n return localTemplates\n }\n // Fallback for development: resolve to packages/docker/templates\n return path.join(__dirname, '../../../docker/templates')\n}\n\nconst templatesDir = resolveTemplatesDir()\n\nconst updatePackageJson = (): void => {\n const packageJsonPath = path.join(process.cwd(), 'package.json')\n if (fs.existsSync(packageJsonPath)) {\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'))\n if (!packageJson.scripts) {\n packageJson.scripts = {}\n }\n packageJson.scripts.start = 'motia start'\n fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2))\n console.log('Updated package.json with start script')\n }\n}\n\nconst createDockerfile = async () => {\n const dockerfilePath = path.join(process.cwd(), 'Dockerfile')\n\n if (fs.existsSync(dockerfilePath)) {\n console.log('Dockerfile already exists')\n\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n })\n\n const shouldOverride = await new Promise<boolean>((resolve) => {\n rl.question('Do you want to override the existing Dockerfile? (y/N): ', (answer) => {\n rl.close()\n resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes')\n })\n })\n\n if (!shouldOverride) {\n console.log('Dockerfile generation cancelled')\n return\n }\n }\n\n const dockerfileContent = fs.readFileSync(path.join(templatesDir, 'MotiaDockerSample'), 'utf-8')\n\n try {\n fs.writeFileSync(dockerfilePath, dockerfileContent)\n console.log('Dockerfile generated successfully!')\n } catch (error) {\n console.error('Error generating Dockerfile:', (error as Error).message)\n throw error\n }\n}\n\nconst createDockerignore = async () => {\n identifyUser()\n\n trackEvent('docker_setup_command', {\n project_name: getProjectIdentifier(process.cwd()),\n })\n\n const dockerignoreContent = fs.readFileSync(path.join(templatesDir, '.dockerignore.sample'), 'utf-8')\n\n const dockerignorePath = path.join(process.cwd(), '.dockerignore')\n\n if (fs.existsSync(dockerignorePath)) {\n console.log('.dockerignore already exists')\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n })\n\n const shouldOverride = await new Promise<boolean>((resolve) => {\n rl.question('Do you want to override the existing .dockerignore? (y/N): ', (answer) => {\n rl.close()\n resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes')\n })\n })\n\n if (!shouldOverride) {\n console.log('.dockerignore generation cancelled')\n return\n }\n }\n\n try {\n fs.writeFileSync(dockerignorePath, dockerignoreContent)\n console.log('.dockerignore generated successfully!')\n } catch (error) {\n console.error('Error generating .dockerignore:', (error as Error).message)\n throw error\n }\n}\n\nexport const setup = async (): Promise<void> => {\n printMotiaDockerIntro()\n\n await createDockerfile()\n await createDockerignore()\n updatePackageJson()\n}\n"],"mappings":";;;;;;;;;AAQA,MAAM,YAAYA,OAAK,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC;AAE9D,MAAM,4BAAoC;CACxC,MAAM,iBAAiBA,OAAK,KAAK,WAAW,cAAc;AAC1D,KAAIC,KAAG,WAAW,eAAe,CAC/B,QAAO;AAGT,QAAOD,OAAK,KAAK,WAAW,4BAA4B;;AAG1D,MAAM,eAAe,qBAAqB;AAE1C,MAAM,0BAAgC;CACpC,MAAM,kBAAkBA,OAAK,KAAK,QAAQ,KAAK,EAAE,eAAe;AAChE,KAAIC,KAAG,WAAW,gBAAgB,EAAE;EAClC,MAAM,cAAc,KAAK,MAAMA,KAAG,aAAa,iBAAiB,QAAQ,CAAC;AACzE,MAAI,CAAC,YAAY,QACf,aAAY,UAAU,EAAE;AAE1B,cAAY,QAAQ,QAAQ;AAC5B,OAAG,cAAc,iBAAiB,KAAK,UAAU,aAAa,MAAM,EAAE,CAAC;AACvE,UAAQ,IAAI,yCAAyC;;;AAIzD,MAAM,mBAAmB,YAAY;CACnC,MAAM,iBAAiBD,OAAK,KAAK,QAAQ,KAAK,EAAE,aAAa;AAE7D,KAAIC,KAAG,WAAW,eAAe,EAAE;AACjC,UAAQ,IAAI,4BAA4B;EAExC,MAAM,KAAKC,WAAS,gBAAgB;GAClC,OAAO,QAAQ;GACf,QAAQ,QAAQ;GACjB,CAAC;AASF,MAAI,CAPmB,MAAM,IAAI,SAAkB,YAAY;AAC7D,MAAG,SAAS,6DAA6D,WAAW;AAClF,OAAG,OAAO;AACV,YAAQ,OAAO,aAAa,KAAK,OAAO,OAAO,aAAa,KAAK,MAAM;KACvE;IACF,EAEmB;AACnB,WAAQ,IAAI,kCAAkC;AAC9C;;;CAIJ,MAAM,oBAAoBD,KAAG,aAAaD,OAAK,KAAK,cAAc,oBAAoB,EAAE,QAAQ;AAEhG,KAAI;AACF,OAAG,cAAc,gBAAgB,kBAAkB;AACnD,UAAQ,IAAI,qCAAqC;UAC1C,OAAO;AACd,UAAQ,MAAM,gCAAiC,MAAgB,QAAQ;AACvE,QAAM;;;AAIV,MAAM,qBAAqB,YAAY;AACrC,eAAc;AAEd,YAAW,wBAAwB,EACjC,cAAc,qBAAqB,QAAQ,KAAK,CAAC,EAClD,CAAC;CAEF,MAAM,sBAAsBC,KAAG,aAAaD,OAAK,KAAK,cAAc,uBAAuB,EAAE,QAAQ;CAErG,MAAM,mBAAmBA,OAAK,KAAK,QAAQ,KAAK,EAAE,gBAAgB;AAElE,KAAIC,KAAG,WAAW,iBAAiB,EAAE;AACnC,UAAQ,IAAI,+BAA+B;EAC3C,MAAM,KAAKC,WAAS,gBAAgB;GAClC,OAAO,QAAQ;GACf,QAAQ,QAAQ;GACjB,CAAC;AASF,MAAI,CAPmB,MAAM,IAAI,SAAkB,YAAY;AAC7D,MAAG,SAAS,gEAAgE,WAAW;AACrF,OAAG,OAAO;AACV,YAAQ,OAAO,aAAa,KAAK,OAAO,OAAO,aAAa,KAAK,MAAM;KACvE;IACF,EAEmB;AACnB,WAAQ,IAAI,qCAAqC;AACjD;;;AAIJ,KAAI;AACF,OAAG,cAAc,kBAAkB,oBAAoB;AACvD,UAAQ,IAAI,wCAAwC;UAC7C,OAAO;AACd,UAAQ,MAAM,mCAAoC,MAAgB,QAAQ;AAC1E,QAAM;;;AAIV,MAAa,QAAQ,YAA2B;AAC9C,wBAAuB;AAEvB,OAAM,kBAAkB;AACxB,OAAM,oBAAoB;AAC1B,oBAAmB"}
1
+ {"version":3,"file":"setup.mjs","names":["path","fs","readline"],"sources":["../../src/docker/setup.ts"],"sourcesContent":["import { getProjectIdentifier, trackEvent } from '@motiadev/core'\nimport * as fs from 'fs'\nimport * as path from 'path'\nimport * as readline from 'readline'\nimport { fileURLToPath } from 'url'\nimport { identifyUser } from '../utils/analytics'\nimport { printMotiaDockerIntro } from './utils/print-intro'\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url))\n\nconst updatePackageJson = (): void => {\n const packageJsonPath = path.join(process.cwd(), 'package.json')\n if (fs.existsSync(packageJsonPath)) {\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'))\n if (!packageJson.scripts) {\n packageJson.scripts = {}\n }\n packageJson.scripts.start = 'motia start'\n fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2))\n console.log('Updated package.json with start script')\n }\n}\n\nconst createDockerfile = async () => {\n const dockerfilePath = path.join(process.cwd(), 'Dockerfile')\n\n if (fs.existsSync(dockerfilePath)) {\n console.log('Dockerfile already exists')\n\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n })\n\n const shouldOverride = await new Promise<boolean>((resolve) => {\n rl.question('Do you want to override the existing Dockerfile? (y/N): ', (answer) => {\n rl.close()\n resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes')\n })\n })\n\n if (!shouldOverride) {\n console.log('Dockerfile generation cancelled')\n return\n }\n }\n\n const dockerfileContent = fs.readFileSync(path.join(__dirname, './templates', 'MotiaDockerSample'), 'utf-8')\n\n try {\n fs.writeFileSync(dockerfilePath, dockerfileContent)\n console.log('Dockerfile generated successfully!')\n } catch (error) {\n console.error('Error generating Dockerfile:', (error as Error).message)\n throw error\n }\n}\n\nconst createDockerignore = async () => {\n identifyUser()\n\n trackEvent('docker_setup_command', {\n project_name: getProjectIdentifier(process.cwd()),\n })\n\n const dockerignoreContent = fs.readFileSync(path.join(__dirname, './templates', '.dockerignore.sample'), 'utf-8')\n\n const dockerignorePath = path.join(process.cwd(), '.dockerignore')\n\n if (fs.existsSync(dockerignorePath)) {\n console.log('.dockerignore already exists')\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n })\n\n const shouldOverride = await new Promise<boolean>((resolve) => {\n rl.question('Do you want to override the existing .dockerignore? (y/N): ', (answer) => {\n rl.close()\n resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes')\n })\n })\n\n if (!shouldOverride) {\n console.log('.dockerignore generation cancelled')\n return\n }\n }\n\n try {\n fs.writeFileSync(dockerignorePath, dockerignoreContent)\n console.log('.dockerignore generated successfully!')\n } catch (error) {\n console.error('Error generating .dockerignore:', (error as Error).message)\n throw error\n }\n}\n\nexport const setup = async (): Promise<void> => {\n printMotiaDockerIntro()\n\n await createDockerfile()\n await createDockerignore()\n updatePackageJson()\n}\n"],"mappings":";;;;;;;;;AAQA,MAAM,YAAYA,OAAK,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC;AAE9D,MAAM,0BAAgC;CACpC,MAAM,kBAAkBA,OAAK,KAAK,QAAQ,KAAK,EAAE,eAAe;AAChE,KAAIC,KAAG,WAAW,gBAAgB,EAAE;EAClC,MAAM,cAAc,KAAK,MAAMA,KAAG,aAAa,iBAAiB,QAAQ,CAAC;AACzE,MAAI,CAAC,YAAY,QACf,aAAY,UAAU,EAAE;AAE1B,cAAY,QAAQ,QAAQ;AAC5B,OAAG,cAAc,iBAAiB,KAAK,UAAU,aAAa,MAAM,EAAE,CAAC;AACvE,UAAQ,IAAI,yCAAyC;;;AAIzD,MAAM,mBAAmB,YAAY;CACnC,MAAM,iBAAiBD,OAAK,KAAK,QAAQ,KAAK,EAAE,aAAa;AAE7D,KAAIC,KAAG,WAAW,eAAe,EAAE;AACjC,UAAQ,IAAI,4BAA4B;EAExC,MAAM,KAAKC,WAAS,gBAAgB;GAClC,OAAO,QAAQ;GACf,QAAQ,QAAQ;GACjB,CAAC;AASF,MAAI,CAPmB,MAAM,IAAI,SAAkB,YAAY;AAC7D,MAAG,SAAS,6DAA6D,WAAW;AAClF,OAAG,OAAO;AACV,YAAQ,OAAO,aAAa,KAAK,OAAO,OAAO,aAAa,KAAK,MAAM;KACvE;IACF,EAEmB;AACnB,WAAQ,IAAI,kCAAkC;AAC9C;;;CAIJ,MAAM,oBAAoBD,KAAG,aAAaD,OAAK,KAAK,WAAW,eAAe,oBAAoB,EAAE,QAAQ;AAE5G,KAAI;AACF,OAAG,cAAc,gBAAgB,kBAAkB;AACnD,UAAQ,IAAI,qCAAqC;UAC1C,OAAO;AACd,UAAQ,MAAM,gCAAiC,MAAgB,QAAQ;AACvE,QAAM;;;AAIV,MAAM,qBAAqB,YAAY;AACrC,eAAc;AAEd,YAAW,wBAAwB,EACjC,cAAc,qBAAqB,QAAQ,KAAK,CAAC,EAClD,CAAC;CAEF,MAAM,sBAAsBC,KAAG,aAAaD,OAAK,KAAK,WAAW,eAAe,uBAAuB,EAAE,QAAQ;CAEjH,MAAM,mBAAmBA,OAAK,KAAK,QAAQ,KAAK,EAAE,gBAAgB;AAElE,KAAIC,KAAG,WAAW,iBAAiB,EAAE;AACnC,UAAQ,IAAI,+BAA+B;EAC3C,MAAM,KAAKC,WAAS,gBAAgB;GAClC,OAAO,QAAQ;GACf,QAAQ,QAAQ;GACjB,CAAC;AASF,MAAI,CAPmB,MAAM,IAAI,SAAkB,YAAY;AAC7D,MAAG,SAAS,gEAAgE,WAAW;AACrF,OAAG,OAAO;AACV,YAAQ,OAAO,aAAa,KAAK,OAAO,OAAO,aAAa,KAAK,MAAM;KACvE;IACF,EAEmB;AACnB,WAAQ,IAAI,qCAAqC;AACjD;;;AAIJ,KAAI;AACF,OAAG,cAAc,kBAAkB,oBAAoB;AACvD,UAAQ,IAAI,wCAAwC;UAC7C,OAAO;AACd,UAAQ,MAAM,mCAAoC,MAAgB,QAAQ;AAC1E,QAAM;;;AAIV,MAAa,QAAQ,YAA2B;AAC9C,wBAAuB;AAEvB,OAAM,kBAAkB;AACxB,OAAM,oBAAoB;AAC1B,oBAAmB"}
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.14.0-beta.165-246284",
4
+ "version": "0.14.0-beta.165-076789",
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.12",
49
- "@motiadev/adapter-redis-state": "0.14.0-beta.165-246284",
50
- "@motiadev/adapter-bullmq-events": "0.14.0-beta.165-246284",
51
- "@motiadev/adapter-redis-cron": "0.14.0-beta.165-246284",
52
- "@motiadev/adapter-redis-streams": "0.14.0-beta.165-246284",
53
- "@motiadev/core": "0.14.0-beta.165-246284",
54
- "@motiadev/stream-client-node": "0.14.0-beta.165-246284",
55
- "@motiadev/workbench": "0.14.0-beta.165-246284"
49
+ "@motiadev/adapter-bullmq-events": "0.14.0-beta.165-076789",
50
+ "@motiadev/adapter-redis-streams": "0.14.0-beta.165-076789",
51
+ "@motiadev/adapter-redis-state": "0.14.0-beta.165-076789",
52
+ "@motiadev/stream-client-node": "0.14.0-beta.165-076789",
53
+ "@motiadev/adapter-redis-cron": "0.14.0-beta.165-076789",
54
+ "@motiadev/workbench": "0.14.0-beta.165-076789",
55
+ "@motiadev/core": "0.14.0-beta.165-076789"
56
56
  },
57
57
  "devDependencies": {
58
58
  "@amplitude/analytics-types": "^2.9.2",
@@ -74,6 +74,7 @@
74
74
  "move:python": "sh scripts/move-python.sh",
75
75
  "move:dot-files": "sh scripts/move-dot-files.sh",
76
76
  "build": "tsdown",
77
+ "postbuild": "sh scripts/post-build.sh",
77
78
  "test": "NODE_OPTIONS='--experimental-vm-modules' jest",
78
79
  "lint": "biome check .",
79
80
  "lint:plugins": "eslint --config ../../eslint.config.js"
@@ -1,53 +0,0 @@
1
- import pluginBabel from '@rollup/plugin-babel'
2
- import postcss from 'rollup-plugin-postcss'
3
- import { defineConfig } from 'tsdown'
4
-
5
- export default defineConfig([
6
- // Main JavaScript/TypeScript build
7
- {
8
- entry: {
9
- index: './src/index.ts',
10
- plugin: './src/plugin.ts',
11
- },
12
- format: 'esm',
13
- platform: 'browser',
14
- external: [/^react($|\/)/, 'react/jsx-runtime'],
15
- dts: {
16
- build: true,
17
- },
18
- exports: {
19
- devExports: 'development',
20
- },
21
- clean: true,
22
- publint: true,
23
- unused: true,
24
- outDir: 'dist',
25
- plugins: [
26
- pluginBabel({
27
- babelHelpers: 'bundled',
28
- parserOpts: {
29
- sourceType: 'module',
30
- plugins: ['jsx', 'typescript'],
31
- },
32
- plugins: ['babel-plugin-react-compiler'],
33
- extensions: ['.js', '.jsx', '.ts', '.tsx'],
34
- }),
35
- ],
36
- },
37
- // Separate CSS build
38
- {
39
- entry: {
40
- index: './src/styles.css',
41
- },
42
- format: 'esm',
43
- platform: 'browser',
44
- outDir: 'dist',
45
- clean: false,
46
- plugins: [
47
- postcss({
48
- extract: true,
49
- minimize: process.env.NODE_ENV === 'prod',
50
- }),
51
- ],
52
- },
53
- ])
@@ -1,32 +0,0 @@
1
- # Aider Configuration for Motia Projects
2
- # https://aider.chat/docs/config.html
3
-
4
- # Read AGENTS.md for project overview and guide references
5
- read:
6
- - AGENTS.md
7
- # Uncomment specific guides as needed for more context:
8
- # - .cursor/rules/motia/api-steps.mdc
9
- # - .cursor/rules/motia/event-steps.mdc
10
- # - .cursor/rules/motia/cron-steps.mdc
11
- # - .cursor/rules/motia/state-management.mdc
12
- # - .cursor/rules/motia/middlewares.mdc
13
- # - .cursor/rules/motia/realtime-streaming.mdc
14
- # - .cursor/rules/motia/virtual-steps.mdc
15
- # - .cursor/rules/motia/ui-steps.mdc
16
- # - .cursor/architecture/architecture.mdc
17
- # - .cursor/architecture/error-handling.mdc
18
-
19
- # Note: AGENTS.md references all detailed guides in .cursor/rules/
20
- # The AI will read those guides when needed based on AGENTS.md instructions
21
-
22
- # Auto-commit changes (optional, uncomment to enable)
23
- # auto-commits: true
24
-
25
- # Model selection (uncomment your preferred model)
26
- # model: gpt-4
27
- # model: claude-3-5-sonnet-20241022
28
-
29
- # Additional context files (optional)
30
- # read:
31
- # - config.yml
32
- # - package.json