motia 0.15.5-beta.174-093524 → 0.15.5-beta.174-069425

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,13 +1,15 @@
1
+ import { version } from "../../version.mjs";
1
2
  import { constants, mkdirSync, promises, statSync } from "fs";
2
3
  import { globSync } from "glob";
3
4
  import * as path$1 from "path";
4
5
  import { fileURLToPath } from "url";
5
6
 
6
7
  //#region src/create/templates/generate.ts
7
- const replaceTemplateVariables = (content, projectName) => {
8
+ const replaceTemplateVariables = (content, projectName, version$1) => {
8
9
  const replacements = {
9
10
  "{{PROJECT_NAME}}": projectName,
10
- "{{PLUGIN_NAME}}": toPascalCase(projectName)
11
+ "{{PLUGIN_NAME}}": toPascalCase(projectName),
12
+ "{{VERSION}}": version$1 || "latest"
11
13
  };
12
14
  return Object.entries(replacements).reduce((result, [key, value]) => {
13
15
  return result.replace(new RegExp(key, "g"), value);
@@ -91,7 +93,7 @@ const generatePluginTemplate = (templateFolder) => {
91
93
  const sanitizedFileName = fileName.replace(".txt", "");
92
94
  const generateFilePath = path$1.join(rootDir, sanitizedFileName);
93
95
  let content = await promises.readFile(filePath, "utf8");
94
- content = replaceTemplateVariables(content, projectName);
96
+ content = replaceTemplateVariables(content, projectName, version);
95
97
  let fd = null;
96
98
  try {
97
99
  fd = await promises.open(generateFilePath, constants.O_CREAT | constants.O_WRONLY | constants.O_TRUNC, 420);
@@ -1 +1 @@
1
- {"version":3,"file":"generate.mjs","names":["replacements: Record<string, string>","path","fs","fd: fs.FileHandle | null","fd"],"sources":["../../../src/create/templates/generate.ts"],"sourcesContent":["import { constants, promises as fs, mkdirSync, statSync } from 'fs'\nimport { globSync } from 'glob'\nimport * as path from 'path'\nimport { fileURLToPath } from 'url'\nimport type { CliContext } from '../../cloud/config-utils'\n\nexport type Generator = (rootDir: string, context: CliContext) => Promise<void>\n\nconst replaceTemplateVariables = (content: string, projectName: string): string => {\n const replacements: Record<string, string> = {\n '{{PROJECT_NAME}}': projectName,\n '{{PLUGIN_NAME}}': toPascalCase(projectName),\n }\n\n return Object.entries(replacements).reduce((result, [key, value]) => {\n return result.replace(new RegExp(key, 'g'), value)\n }, content)\n}\n\nconst toPascalCase = (str: string): string => {\n // Remove @ and scope if present\n const name = str.replace(/^@[^/]+\\//, '')\n return name\n .split(/[-_]/)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join('')\n}\nconst __dirname = path.dirname(fileURLToPath(import.meta.url))\n\nexport const generateTemplateSteps = (templateFolder: string): Generator => {\n return async (rootDir: string, context: CliContext): Promise<void> => {\n const templatePath = path.join(__dirname, templateFolder)\n const files = globSync('**/*', { absolute: false, cwd: templatePath, dot: true })\n const projectName = path.basename(rootDir)\n\n try {\n for (const fileName of files) {\n const filePath = path.join(templatePath, fileName)\n const targetFilePath = path.join(rootDir, fileName)\n const targetDir = path.dirname(targetFilePath)\n\n mkdirSync(targetDir, { recursive: true })\n\n if (statSync(filePath).isDirectory()) {\n const folderPath = filePath.replace(templatePath, '')\n mkdirSync(path.join(rootDir, folderPath), { recursive: true })\n continue\n }\n\n const sanitizedFileName = fileName === 'requirements.txt' ? fileName : fileName.replace('.txt', '')\n const isWorkbenchConfig = fileName.match('motia-workbench.json')\n const generateFilePath = path.join(rootDir, sanitizedFileName)\n let content = await fs.readFile(filePath, 'utf8')\n\n if (isWorkbenchConfig) {\n try {\n // Use file descriptor to avoid TOCTOU vulnerability\n let fd: fs.FileHandle | null = null\n try {\n // Try to open existing file for reading\n fd = await fs.open(generateFilePath, constants.O_RDONLY)\n const existingWorkbenchConfig = await fd.readFile('utf8')\n const workbenchContent = JSON.parse(content)\n\n content = JSON.stringify([...JSON.parse(existingWorkbenchConfig), ...workbenchContent], null, 2)\n\n context.log('workbench-config-updated', (message) =>\n message.tag('success').append('Workbench config').append('has been updated.'),\n )\n } finally {\n if (fd) await fd.close()\n }\n } catch {\n void 0\n }\n } else {\n content = replaceTemplateVariables(content, projectName)\n }\n\n // Use file descriptor for atomic write operation\n let fd: fs.FileHandle | null = null\n try {\n fd = await fs.open(generateFilePath, constants.O_CREAT | constants.O_WRONLY | constants.O_TRUNC, 0o644)\n await fd.writeFile(content, 'utf8')\n } finally {\n if (fd) await fd.close()\n }\n context.log(sanitizedFileName, (message) => {\n message.tag('success').append('File').append(sanitizedFileName, 'cyan').append('has been created.')\n })\n }\n } catch (error) {\n console.error('Error generating template files:', error)\n }\n }\n}\n\nexport const generatePluginTemplate = (templateFolder: string): Generator => {\n return async (rootDir: string, context: CliContext): Promise<void> => {\n const templatePath = path.join(__dirname, templateFolder)\n const files = globSync('**/*', { absolute: false, cwd: templatePath, dot: true })\n const projectName = path.basename(rootDir)\n\n try {\n for (const fileName of files) {\n const filePath = path.join(templatePath, fileName)\n const targetFilePath = path.join(rootDir, fileName)\n const targetDir = path.dirname(targetFilePath)\n\n mkdirSync(targetDir, { recursive: true })\n\n if (statSync(filePath).isDirectory()) {\n const folderPath = filePath.replace(templatePath, '')\n mkdirSync(path.join(rootDir, folderPath), { recursive: true })\n continue\n }\n\n const sanitizedFileName = fileName.replace('.txt', '')\n const generateFilePath = path.join(rootDir, sanitizedFileName)\n let content = await fs.readFile(filePath, 'utf8')\n\n content = replaceTemplateVariables(content, projectName)\n\n // Use file descriptor for atomic write operation\n let fd: fs.FileHandle | null = null\n try {\n fd = await fs.open(generateFilePath, constants.O_CREAT | constants.O_WRONLY | constants.O_TRUNC, 0o644)\n await fd.writeFile(content, 'utf8')\n } finally {\n if (fd) await fd.close()\n }\n context.log(sanitizedFileName, (message) => {\n message.tag('success').append('File').append(sanitizedFileName, 'cyan').append('has been created.')\n })\n }\n } catch (error) {\n console.error('Error generating template files:', error)\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"generate.mjs","names":["replacements: Record<string, string>","version","path","fs","fd: fs.FileHandle | null","fd"],"sources":["../../../src/create/templates/generate.ts"],"sourcesContent":["import { constants, promises as fs, mkdirSync, statSync } from 'fs'\nimport { globSync } from 'glob'\nimport * as path from 'path'\nimport { fileURLToPath } from 'url'\nimport type { CliContext } from '../../cloud/config-utils'\nimport { version } from '../../version'\n\nexport type Generator = (rootDir: string, context: CliContext) => Promise<void>\n\nconst replaceTemplateVariables = (content: string, projectName: string, version?: string): string => {\n const replacements: Record<string, string> = {\n '{{PROJECT_NAME}}': projectName,\n '{{PLUGIN_NAME}}': toPascalCase(projectName),\n '{{VERSION}}': version || 'latest',\n }\n\n return Object.entries(replacements).reduce((result, [key, value]) => {\n return result.replace(new RegExp(key, 'g'), value)\n }, content)\n}\n\nconst toPascalCase = (str: string): string => {\n // Remove @ and scope if present\n const name = str.replace(/^@[^/]+\\//, '')\n return name\n .split(/[-_]/)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join('')\n}\nconst __dirname = path.dirname(fileURLToPath(import.meta.url))\n\nexport const generateTemplateSteps = (templateFolder: string): Generator => {\n return async (rootDir: string, context: CliContext): Promise<void> => {\n const templatePath = path.join(__dirname, templateFolder)\n const files = globSync('**/*', { absolute: false, cwd: templatePath, dot: true })\n const projectName = path.basename(rootDir)\n\n try {\n for (const fileName of files) {\n const filePath = path.join(templatePath, fileName)\n const targetFilePath = path.join(rootDir, fileName)\n const targetDir = path.dirname(targetFilePath)\n\n mkdirSync(targetDir, { recursive: true })\n\n if (statSync(filePath).isDirectory()) {\n const folderPath = filePath.replace(templatePath, '')\n mkdirSync(path.join(rootDir, folderPath), { recursive: true })\n continue\n }\n\n const sanitizedFileName = fileName === 'requirements.txt' ? fileName : fileName.replace('.txt', '')\n const isWorkbenchConfig = fileName.match('motia-workbench.json')\n const generateFilePath = path.join(rootDir, sanitizedFileName)\n let content = await fs.readFile(filePath, 'utf8')\n\n if (isWorkbenchConfig) {\n try {\n // Use file descriptor to avoid TOCTOU vulnerability\n let fd: fs.FileHandle | null = null\n try {\n // Try to open existing file for reading\n fd = await fs.open(generateFilePath, constants.O_RDONLY)\n const existingWorkbenchConfig = await fd.readFile('utf8')\n const workbenchContent = JSON.parse(content)\n\n content = JSON.stringify([...JSON.parse(existingWorkbenchConfig), ...workbenchContent], null, 2)\n\n context.log('workbench-config-updated', (message) =>\n message.tag('success').append('Workbench config').append('has been updated.'),\n )\n } finally {\n if (fd) await fd.close()\n }\n } catch {\n void 0\n }\n } else {\n content = replaceTemplateVariables(content, projectName)\n }\n\n // Use file descriptor for atomic write operation\n let fd: fs.FileHandle | null = null\n try {\n fd = await fs.open(generateFilePath, constants.O_CREAT | constants.O_WRONLY | constants.O_TRUNC, 0o644)\n await fd.writeFile(content, 'utf8')\n } finally {\n if (fd) await fd.close()\n }\n context.log(sanitizedFileName, (message) => {\n message.tag('success').append('File').append(sanitizedFileName, 'cyan').append('has been created.')\n })\n }\n } catch (error) {\n console.error('Error generating template files:', error)\n }\n }\n}\n\nexport const generatePluginTemplate = (templateFolder: string): Generator => {\n return async (rootDir: string, context: CliContext): Promise<void> => {\n const templatePath = path.join(__dirname, templateFolder)\n const files = globSync('**/*', { absolute: false, cwd: templatePath, dot: true })\n const projectName = path.basename(rootDir)\n\n try {\n for (const fileName of files) {\n const filePath = path.join(templatePath, fileName)\n const targetFilePath = path.join(rootDir, fileName)\n const targetDir = path.dirname(targetFilePath)\n\n mkdirSync(targetDir, { recursive: true })\n\n if (statSync(filePath).isDirectory()) {\n const folderPath = filePath.replace(templatePath, '')\n mkdirSync(path.join(rootDir, folderPath), { recursive: true })\n continue\n }\n\n const sanitizedFileName = fileName.replace('.txt', '')\n const generateFilePath = path.join(rootDir, sanitizedFileName)\n let content = await fs.readFile(filePath, 'utf8')\n\n content = replaceTemplateVariables(content, projectName, version)\n\n // Use file descriptor for atomic write operation\n let fd: fs.FileHandle | null = null\n try {\n fd = await fs.open(generateFilePath, constants.O_CREAT | constants.O_WRONLY | constants.O_TRUNC, 0o644)\n await fd.writeFile(content, 'utf8')\n } finally {\n if (fd) await fd.close()\n }\n context.log(sanitizedFileName, (message) => {\n message.tag('success').append('File').append(sanitizedFileName, 'cyan').append('has been created.')\n })\n }\n } catch (error) {\n console.error('Error generating template files:', error)\n }\n }\n}\n"],"mappings":"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"}
@@ -3,13 +3,15 @@ import { globSync } from 'glob'
3
3
  import * as path from 'path'
4
4
  import { fileURLToPath } from 'url'
5
5
  import type { CliContext } from '../../cloud/config-utils'
6
+ import { version } from '../../version'
6
7
 
7
8
  export type Generator = (rootDir: string, context: CliContext) => Promise<void>
8
9
 
9
- const replaceTemplateVariables = (content: string, projectName: string): string => {
10
+ const replaceTemplateVariables = (content: string, projectName: string, version?: string): string => {
10
11
  const replacements: Record<string, string> = {
11
12
  '{{PROJECT_NAME}}': projectName,
12
13
  '{{PLUGIN_NAME}}': toPascalCase(projectName),
14
+ '{{VERSION}}': version || 'latest',
13
15
  }
14
16
 
15
17
  return Object.entries(replacements).reduce((result, [key, value]) => {
@@ -119,7 +121,7 @@ export const generatePluginTemplate = (templateFolder: string): Generator => {
119
121
  const generateFilePath = path.join(rootDir, sanitizedFileName)
120
122
  let content = await fs.readFile(filePath, 'utf8')
121
123
 
122
- content = replaceTemplateVariables(content, projectName)
124
+ content = replaceTemplateVariables(content, projectName, version)
123
125
 
124
126
  // Use file descriptor for atomic write operation
125
127
  let fd: fs.FileHandle | null = null
@@ -1,4 +1,4 @@
1
- # @motiadev/plugin-example
1
+ # {{PROJECT_NAME}}
2
2
 
3
3
  A minimal example plugin demonstrating the Motia plugin system.
4
4
 
@@ -37,7 +37,7 @@ pnpm run clean
37
37
  To use this plugin in your Motia project, import it in your `motia.config.ts`:
38
38
 
39
39
  ```typescript
40
- import examplePlugin from '@motiadev/plugin-example/plugin'
40
+ import examplePlugin from '{{PROJECT_NAME}}/plugin'
41
41
 
42
42
  export default {
43
43
  plugins: [examplePlugin],
@@ -55,8 +55,8 @@ export default function plugin(_motia: MotiaPluginContext): MotiaPlugin {
55
55
  return {
56
56
  workbench: [
57
57
  {
58
- packageName: '@motiadev/plugin-example',
59
- cssImports: ['@motiadev/plugin-example/dist/index.css'],
58
+ packageName: '{{PROJECT_NAME}}',
59
+ cssImports: ['{{PROJECT_NAME}}/dist/index.css'],
60
60
  label: 'Example',
61
61
  position: 'bottom',
62
62
  componentName: 'ExamplePage',
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "{{PROJECT_NAME}}",
3
- "version": "0.14.0-beta.164",
3
+ "version": "0.1.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -28,8 +28,8 @@
28
28
  "react": "^19.2.0"
29
29
  },
30
30
  "peerDependencies": {
31
- "@motiadev/core": "latest",
32
- "@motiadev/ui": "latest"
31
+ "@motiadev/core": "{{VERSION}}",
32
+ "@motiadev/ui": "{{VERSION}}"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@rollup/plugin-babel": "^6.1.0",
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.15.5-beta.174-093524",
4
+ "version": "0.15.5-beta.174-069425",
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-bullmq-events": "0.15.5-beta.174-093524",
50
- "@motiadev/adapter-redis-cron": "0.15.5-beta.174-093524",
51
- "@motiadev/adapter-redis-streams": "0.15.5-beta.174-093524",
52
- "@motiadev/core": "0.15.5-beta.174-093524",
53
- "@motiadev/adapter-redis-state": "0.15.5-beta.174-093524",
54
- "@motiadev/stream-client-node": "0.15.5-beta.174-093524",
55
- "@motiadev/workbench": "0.15.5-beta.174-093524"
49
+ "@motiadev/adapter-redis-cron": "0.15.5-beta.174-069425",
50
+ "@motiadev/adapter-redis-state": "0.15.5-beta.174-069425",
51
+ "@motiadev/adapter-bullmq-events": "0.15.5-beta.174-069425",
52
+ "@motiadev/adapter-redis-streams": "0.15.5-beta.174-069425",
53
+ "@motiadev/core": "0.15.5-beta.174-069425",
54
+ "@motiadev/workbench": "0.15.5-beta.174-069425",
55
+ "@motiadev/stream-client-node": "0.15.5-beta.174-069425"
56
56
  },
57
57
  "devDependencies": {
58
58
  "@amplitude/analytics-types": "^2.9.2",