motia 0.15.4-beta.169 → 0.15.4-beta.170-579134
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +3 -6
- package/dist/cli.mjs.map +1 -1
- package/dist/create/index.mjs +39 -4
- package/dist/create/index.mjs.map +1 -1
- package/dist/create/interactive.mjs +2 -1
- package/dist/create/interactive.mjs.map +1 -1
- package/dist/dev.mjs +4 -4
- package/dist/dev.mjs.map +1 -1
- package/dist/redis/connection.mjs +56 -0
- package/dist/redis/connection.mjs.map +1 -0
- package/dist/redis/memory-manager.mjs +68 -0
- package/dist/redis/memory-manager.mjs.map +1 -0
- package/dist/redis/utils.mjs +15 -0
- package/dist/redis/utils.mjs.map +1 -0
- package/dist/start.mjs +4 -4
- package/dist/start.mjs.map +1 -1
- package/dist/utils/execute-command.mjs +5 -2
- package/dist/utils/execute-command.mjs.map +1 -1
- package/package.json +8 -8
- package/dist/redis-memory-manager.mjs +0 -109
- package/dist/redis-memory-manager.mjs.map +0 -1
package/dist/cli.mjs
CHANGED
|
@@ -4,7 +4,6 @@ import { wrapAction } from "./utils/analytics.mjs";
|
|
|
4
4
|
import { handler } from "./cloud/config-utils.mjs";
|
|
5
5
|
import "./cloud/index.mjs";
|
|
6
6
|
import { loadMotiaConfig } from "./load-motia-config.mjs";
|
|
7
|
-
import { instanceRedisMemoryServer, stopRedisMemoryServer } from "./redis-memory-manager.mjs";
|
|
8
7
|
import "dotenv/config";
|
|
9
8
|
import { program } from "commander";
|
|
10
9
|
|
|
@@ -15,7 +14,7 @@ program.command("version").description("Display detailed version information").a
|
|
|
15
14
|
console.log(`Motia CLI v${version}`);
|
|
16
15
|
process.exit(0);
|
|
17
16
|
});
|
|
18
|
-
program.command("create [name]").description("Create a new motia project").option("-t, --template <template>", "The template to use for your project").option("-p, --plugin", "Create a plugin project").option("-i, --interactive", "Use interactive prompts to create project").action((projectName, options) => {
|
|
17
|
+
program.command("create [name]").description("Create a new motia project").option("-t, --template <template>", "The template to use for your project").option("-p, --plugin", "Create a plugin project").option("-i, --interactive", "Use interactive prompts to create project").option("--skip-redis", "Skip Redis binary installation and use external Redis").action((projectName, options) => {
|
|
19
18
|
const mergedArgs = {
|
|
20
19
|
...options,
|
|
21
20
|
name: projectName
|
|
@@ -25,7 +24,8 @@ program.command("create [name]").description("Create a new motia project").optio
|
|
|
25
24
|
await createInteractive({
|
|
26
25
|
name: arg.name,
|
|
27
26
|
template: arg.template,
|
|
28
|
-
plugin: !!arg.plugin
|
|
27
|
+
plugin: !!arg.plugin,
|
|
28
|
+
skipRedis: !!arg.skipRedis
|
|
29
29
|
}, context);
|
|
30
30
|
})(mergedArgs);
|
|
31
31
|
});
|
|
@@ -90,16 +90,13 @@ generate.command("openapi").description("Generate OpenAPI spec for your project"
|
|
|
90
90
|
const { MemoryStreamAdapterManager } = await import("@motiadev/core");
|
|
91
91
|
const baseDir = process.cwd();
|
|
92
92
|
const appConfig = await loadMotiaConfig(baseDir);
|
|
93
|
-
const redisClient = await instanceRedisMemoryServer(baseDir, true);
|
|
94
93
|
const apiSteps = (await generateLockedData({
|
|
95
94
|
projectDir: baseDir,
|
|
96
95
|
streamAdapter: new MemoryStreamAdapterManager(),
|
|
97
96
|
streamAuth: appConfig.streamAuth,
|
|
98
|
-
redisClient,
|
|
99
97
|
printerType: "disabled"
|
|
100
98
|
})).apiSteps();
|
|
101
99
|
generateOpenApi(process.cwd(), apiSteps, options.title, options.version, options.output);
|
|
102
|
-
await stopRedisMemoryServer();
|
|
103
100
|
process.exit(0);
|
|
104
101
|
}));
|
|
105
102
|
const docker = program.command("docker").description("Motia docker commands");
|
package/dist/cli.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.mjs","names":["redisClient: RedisClientType"],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport 'dotenv/config'\n\nimport { program } from 'commander'\nimport { type CliContext, handler } from './cloud/config-utils'\nimport './cloud/index'\nimport type { RedisClientType } from 'redis'\nimport { loadMotiaConfig } from './load-motia-config'\nimport { instanceRedisMemoryServer, stopRedisMemoryServer } from './redis-memory-manager'\nimport { wrapAction } from './utils/analytics'\nimport { version } from './version'\n\nconst defaultPort = 3000\nconst defaultHost = '0.0.0.0'\n\nprogram\n .command('version')\n .description('Display detailed version information')\n .action(() => {\n console.log(`Motia CLI v${version}`)\n process.exit(0)\n })\n\nprogram\n .command('create [name]')\n .description('Create a new motia project')\n .option('-t, --template <template>', 'The template to use for your project')\n .option('-p, --plugin', 'Create a plugin project')\n .option('-i, --interactive', 'Use interactive prompts to create project') // it's default\n .action((projectName, options) => {\n const mergedArgs = { ...options, name: projectName }\n return handler(async (arg: any, context: CliContext) => {\n const { createInteractive } = await import('./create/interactive')\n await createInteractive(\n {\n name: arg.name,\n template: arg.template,\n plugin: !!arg.plugin,\n },\n context,\n )\n })(mergedArgs)\n })\n\nprogram\n .command('rules')\n .command('pull')\n .description('Install essential AI development guides (AGENTS.md, CLAUDE.md) and optional Cursor IDE rules')\n .option('-f, --force', 'Overwrite existing files')\n .action(\n handler(async (arg: any, context: CliContext) => {\n const { pullRules } = await import('./create/pull-rules')\n await pullRules({ force: arg.force, rootDir: process.cwd() }, context)\n }),\n )\n\nprogram\n .command('generate-types')\n .description('Generate types.d.ts file for your project')\n .action(\n wrapAction(async () => {\n const { generateTypes } = await import('./generate-types')\n await generateTypes(process.cwd())\n process.exit(0)\n }),\n )\n\nprogram\n .command('install')\n .description('Sets up Python virtual environment and install dependencies')\n .option('-v, --verbose', 'Enable verbose logging')\n .action(\n wrapAction(async (options: any) => {\n const { install } = await import('./install')\n await install({ isVerbose: options.verbose })\n }),\n )\n\nprogram\n .command('dev')\n .description('Start the development server')\n .option('-p, --port <port>', 'The port to run the server on', `${defaultPort}`)\n .option('-H, --host [host]', 'The host address for the server', `${defaultHost}`)\n .option('-v, --disable-verbose', 'Disable verbose logging')\n .option('-d, --debug', 'Enable debug logging')\n .option('-m, --mermaid', 'Enable mermaid diagram generation')\n .option('--motia-dir <path>', 'Path where .motia folder will be created')\n .action(\n wrapAction(async (arg: any) => {\n if (arg.debug) {\n console.log('🔍 Debug logging enabled')\n process.env.LOG_LEVEL = 'debug'\n }\n\n const port = arg.port ? parseInt(arg.port) : defaultPort\n const host = arg.host ? arg.host : defaultHost\n const { dev } = await import('./dev')\n await dev(port, host, arg.disableVerbose, arg.mermaid, arg.motiaDir)\n }),\n )\n\nprogram\n .command('start')\n .description('Start a server to run your Motia project')\n .option('-p, --port <port>', 'The port to run the server on', `${defaultPort}`)\n .option('-H, --host [host]', 'The host address for the server', `${defaultHost}`)\n .option('-v, --disable-verbose', 'Disable verbose logging')\n .option('-d, --debug', 'Enable debug logging')\n .option('--motia-dir <path>', 'Path where .motia folder will be created')\n .action(\n wrapAction(async (arg: any) => {\n if (arg.debug) {\n console.log('🔍 Debug logging enabled')\n process.env.LOG_LEVEL = 'debug'\n }\n\n const port = arg.port ? parseInt(arg.port) : defaultPort\n const host = arg.host ? arg.host : defaultHost\n const { start } = await import('./start')\n await start(port, host, arg.disableVerbose, arg.motiaDir)\n }),\n )\n\nprogram\n .command('emit')\n .description('Emit an event to the Motia server')\n .requiredOption('--topic <topic>', 'Event topic/type to emit')\n .requiredOption('--message <message>', 'Event payload as JSON string')\n .option('-p, --port <number>', 'Port number (default: 3000)')\n .action(\n wrapAction(async (options: any) => {\n const port = options.port || 3000\n const url = `http://localhost:${port}/emit`\n\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n topic: options.topic,\n data: JSON.parse(options.message),\n }),\n })\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`)\n }\n\n const result = await response.json()\n console.log('Event emitted successfully:', result)\n }),\n )\n\nconst generate = program.command('generate').description('Generate motia resources')\n\ngenerate\n .command('step')\n .description('Create a new step with interactive prompts')\n .option('-d, --dir <step file path>', 'The path relative to the steps directory, used to create the step file')\n .action(\n wrapAction(async (arg: any) => {\n const { createStep } = await import('./create-step/index')\n return createStep({\n stepFilePath: arg.dir,\n })\n }),\n )\n\ngenerate\n .command('openapi')\n .description('Generate OpenAPI spec for your project')\n .option('-t, --title <title>', 'Title for the OpenAPI document. Defaults to project name')\n .option('-v, --version <version>', 'Version for the OpenAPI document. Defaults to 1.0.0', '1.0.0')\n .option('-o, --output <output>', 'Output file for the OpenAPI document. Defaults to openapi.json', 'openapi.json')\n .action(\n wrapAction(async (options: any) => {\n const { generateLockedData } = await import('./generate-locked-data')\n const { generateOpenApi } = await import('./openapi/generate')\n const { MemoryStreamAdapterManager } = await import('@motiadev/core')\n\n const baseDir = process.cwd()\n const appConfig = await loadMotiaConfig(baseDir)\n const redisClient: RedisClientType = await instanceRedisMemoryServer(baseDir, true)\n\n const lockedData = await generateLockedData({\n projectDir: baseDir,\n streamAdapter: new MemoryStreamAdapterManager(),\n streamAuth: appConfig.streamAuth,\n redisClient,\n printerType: 'disabled',\n })\n const apiSteps = lockedData.apiSteps()\n\n generateOpenApi(process.cwd(), apiSteps, options.title, options.version, options.output)\n await stopRedisMemoryServer()\n process.exit(0)\n }),\n )\n\nconst docker = program.command('docker').description('Motia docker commands')\n\ndocker\n .command('setup')\n .description('Setup a motia-docker for your project')\n .action(\n wrapAction(async () => {\n const { setup } = await import('./docker/setup')\n await setup()\n process.exit(0)\n }),\n )\n\ndocker\n .command('run')\n .description('Build and run your project in a docker container')\n .option('-p, --port <port>', 'The port to run the server on', `${defaultPort}`)\n .option('-n, --project-name <project name>', 'The name for your project')\n .option('-s, --skip-build', 'Skip docker build')\n .action(\n wrapAction(async (arg: any) => {\n const { run } = await import('./docker/run')\n await run(arg.port, arg.projectName, arg.skipBuild)\n process.exit(0)\n }),\n )\n\ndocker\n .command('build')\n .description('Build your project in a docker container')\n .option('-n, --project-name <project name>', 'The name for your project')\n .action(\n wrapAction(async (arg: any) => {\n const { build } = await import('./docker/build')\n await build(arg.projectName)\n process.exit(0)\n }),\n )\n\nprogram.version(version, '-V, --version', 'Output the current version')\nprogram.parseAsync(process.argv).catch(() => {\n process.exit(1)\n})\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.mjs","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport 'dotenv/config'\n\nimport { program } from 'commander'\nimport { type CliContext, handler } from './cloud/config-utils'\nimport './cloud/index'\nimport { loadMotiaConfig } from './load-motia-config'\nimport { wrapAction } from './utils/analytics'\nimport { version } from './version'\n\nconst defaultPort = 3000\nconst defaultHost = '0.0.0.0'\n\nprogram\n .command('version')\n .description('Display detailed version information')\n .action(() => {\n console.log(`Motia CLI v${version}`)\n process.exit(0)\n })\n\nprogram\n .command('create [name]')\n .description('Create a new motia project')\n .option('-t, --template <template>', 'The template to use for your project')\n .option('-p, --plugin', 'Create a plugin project')\n .option('-i, --interactive', 'Use interactive prompts to create project') // it's default\n .option('--skip-redis', 'Skip Redis binary installation and use external Redis')\n .action((projectName, options) => {\n const mergedArgs = { ...options, name: projectName }\n return handler(async (arg: any, context: CliContext) => {\n const { createInteractive } = await import('./create/interactive')\n await createInteractive(\n {\n name: arg.name,\n template: arg.template,\n plugin: !!arg.plugin,\n skipRedis: !!arg.skipRedis,\n },\n context,\n )\n })(mergedArgs)\n })\n\nprogram\n .command('rules')\n .command('pull')\n .description('Install essential AI development guides (AGENTS.md, CLAUDE.md) and optional Cursor IDE rules')\n .option('-f, --force', 'Overwrite existing files')\n .action(\n handler(async (arg: any, context: CliContext) => {\n const { pullRules } = await import('./create/pull-rules')\n await pullRules({ force: arg.force, rootDir: process.cwd() }, context)\n }),\n )\n\nprogram\n .command('generate-types')\n .description('Generate types.d.ts file for your project')\n .action(\n wrapAction(async () => {\n const { generateTypes } = await import('./generate-types')\n await generateTypes(process.cwd())\n process.exit(0)\n }),\n )\n\nprogram\n .command('install')\n .description('Sets up Python virtual environment and install dependencies')\n .option('-v, --verbose', 'Enable verbose logging')\n .action(\n wrapAction(async (options: any) => {\n const { install } = await import('./install')\n await install({ isVerbose: options.verbose })\n }),\n )\n\nprogram\n .command('dev')\n .description('Start the development server')\n .option('-p, --port <port>', 'The port to run the server on', `${defaultPort}`)\n .option('-H, --host [host]', 'The host address for the server', `${defaultHost}`)\n .option('-v, --disable-verbose', 'Disable verbose logging')\n .option('-d, --debug', 'Enable debug logging')\n .option('-m, --mermaid', 'Enable mermaid diagram generation')\n .option('--motia-dir <path>', 'Path where .motia folder will be created')\n .action(\n wrapAction(async (arg: any) => {\n if (arg.debug) {\n console.log('🔍 Debug logging enabled')\n process.env.LOG_LEVEL = 'debug'\n }\n\n const port = arg.port ? parseInt(arg.port) : defaultPort\n const host = arg.host ? arg.host : defaultHost\n const { dev } = await import('./dev')\n await dev(port, host, arg.disableVerbose, arg.mermaid, arg.motiaDir)\n }),\n )\n\nprogram\n .command('start')\n .description('Start a server to run your Motia project')\n .option('-p, --port <port>', 'The port to run the server on', `${defaultPort}`)\n .option('-H, --host [host]', 'The host address for the server', `${defaultHost}`)\n .option('-v, --disable-verbose', 'Disable verbose logging')\n .option('-d, --debug', 'Enable debug logging')\n .option('--motia-dir <path>', 'Path where .motia folder will be created')\n .action(\n wrapAction(async (arg: any) => {\n if (arg.debug) {\n console.log('🔍 Debug logging enabled')\n process.env.LOG_LEVEL = 'debug'\n }\n\n const port = arg.port ? parseInt(arg.port) : defaultPort\n const host = arg.host ? arg.host : defaultHost\n const { start } = await import('./start')\n await start(port, host, arg.disableVerbose, arg.motiaDir)\n }),\n )\n\nprogram\n .command('emit')\n .description('Emit an event to the Motia server')\n .requiredOption('--topic <topic>', 'Event topic/type to emit')\n .requiredOption('--message <message>', 'Event payload as JSON string')\n .option('-p, --port <number>', 'Port number (default: 3000)')\n .action(\n wrapAction(async (options: any) => {\n const port = options.port || 3000\n const url = `http://localhost:${port}/emit`\n\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n topic: options.topic,\n data: JSON.parse(options.message),\n }),\n })\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`)\n }\n\n const result = await response.json()\n console.log('Event emitted successfully:', result)\n }),\n )\n\nconst generate = program.command('generate').description('Generate motia resources')\n\ngenerate\n .command('step')\n .description('Create a new step with interactive prompts')\n .option('-d, --dir <step file path>', 'The path relative to the steps directory, used to create the step file')\n .action(\n wrapAction(async (arg: any) => {\n const { createStep } = await import('./create-step/index')\n return createStep({\n stepFilePath: arg.dir,\n })\n }),\n )\n\ngenerate\n .command('openapi')\n .description('Generate OpenAPI spec for your project')\n .option('-t, --title <title>', 'Title for the OpenAPI document. Defaults to project name')\n .option('-v, --version <version>', 'Version for the OpenAPI document. Defaults to 1.0.0', '1.0.0')\n .option('-o, --output <output>', 'Output file for the OpenAPI document. Defaults to openapi.json', 'openapi.json')\n .action(\n wrapAction(async (options: any) => {\n const { generateLockedData } = await import('./generate-locked-data')\n const { generateOpenApi } = await import('./openapi/generate')\n const { MemoryStreamAdapterManager } = await import('@motiadev/core')\n\n const baseDir = process.cwd()\n const appConfig = await loadMotiaConfig(baseDir)\n\n const lockedData = await generateLockedData({\n projectDir: baseDir,\n streamAdapter: new MemoryStreamAdapterManager(),\n streamAuth: appConfig.streamAuth,\n printerType: 'disabled',\n })\n const apiSteps = lockedData.apiSteps()\n\n generateOpenApi(process.cwd(), apiSteps, options.title, options.version, options.output)\n process.exit(0)\n }),\n )\n\nconst docker = program.command('docker').description('Motia docker commands')\n\ndocker\n .command('setup')\n .description('Setup a motia-docker for your project')\n .action(\n wrapAction(async () => {\n const { setup } = await import('./docker/setup')\n await setup()\n process.exit(0)\n }),\n )\n\ndocker\n .command('run')\n .description('Build and run your project in a docker container')\n .option('-p, --port <port>', 'The port to run the server on', `${defaultPort}`)\n .option('-n, --project-name <project name>', 'The name for your project')\n .option('-s, --skip-build', 'Skip docker build')\n .action(\n wrapAction(async (arg: any) => {\n const { run } = await import('./docker/run')\n await run(arg.port, arg.projectName, arg.skipBuild)\n process.exit(0)\n }),\n )\n\ndocker\n .command('build')\n .description('Build your project in a docker container')\n .option('-n, --project-name <project name>', 'The name for your project')\n .action(\n wrapAction(async (arg: any) => {\n const { build } = await import('./docker/build')\n await build(arg.projectName)\n process.exit(0)\n }),\n )\n\nprogram.version(version, '-V, --version', 'Output the current version')\nprogram.parseAsync(process.argv).catch(() => {\n process.exit(1)\n})\n"],"mappings":"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"}
|
package/dist/create/index.mjs
CHANGED
|
@@ -12,6 +12,9 @@ import path from "path";
|
|
|
12
12
|
import pc from "picocolors";
|
|
13
13
|
|
|
14
14
|
//#region src/create/index.ts
|
|
15
|
+
const generateRedisConfig = (skipRedis) => {
|
|
16
|
+
return skipRedis ? ` redis: {\n useMemoryServer: false,\n host: '127.0.0.1',\n port: 6379,\n },\n` : ` redis: {\n useMemoryServer: true,\n },\n`;
|
|
17
|
+
};
|
|
15
18
|
const installRequiredDependencies = async (packageManager, rootDir, context) => {
|
|
16
19
|
context.log("installing-dependencies", (message) => message.tag("info").append("Installing dependencies..."));
|
|
17
20
|
const installCommand = {
|
|
@@ -31,8 +34,8 @@ const installRequiredDependencies = async (packageManager, rootDir, context) =>
|
|
|
31
34
|
"@types/react@19.1.1"
|
|
32
35
|
].join(" ");
|
|
33
36
|
try {
|
|
34
|
-
await executeCommand(`${installCommand} ${dependencies}`, rootDir);
|
|
35
|
-
await executeCommand(`${installCommand} -D ${devDependencies}`, rootDir);
|
|
37
|
+
await executeCommand(`${installCommand} ${dependencies}`, rootDir, { env: { REDISMS_DISABLE_POSTINSTALL: "1" } });
|
|
38
|
+
await executeCommand(`${installCommand} -D ${devDependencies}`, rootDir, { env: { REDISMS_DISABLE_POSTINSTALL: "1" } });
|
|
36
39
|
context.log("dependencies-installed", (message) => message.tag("success").append("Dependencies installed"));
|
|
37
40
|
} catch (error) {
|
|
38
41
|
console.error("❌ Failed to install dependencies:", error);
|
|
@@ -55,7 +58,7 @@ const installNodeDependencies = async (rootDir, context) => {
|
|
|
55
58
|
});
|
|
56
59
|
return packageManager;
|
|
57
60
|
};
|
|
58
|
-
const create = async ({ projectName, template, cursorEnabled, context }) => {
|
|
61
|
+
const create = async ({ projectName, template, cursorEnabled, context, skipRedis = false }) => {
|
|
59
62
|
console.log("\n\n\n _____ ______ ______ ______\n /'\\_/`\\/\\ __`\\/\\__ _\\/\\__ _\\ /\\ _ \\\n /\\ \\ \\ \\/\\ \\/_/\\ \\/\\/_/\\ \\/ \\ \\ \\L\\ \\\n \\ \\ \\__\\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ __ \\\n \\ \\ \\_/\\ \\ \\ \\_\\ \\ \\ \\ \\ \\_\\ \\__\\ \\ \\/\\ \\\n \\ \\_\\\\ \\_\\ \\_____\\ \\ \\_\\ /\\_____\\\\ \\_\\ \\_\\\n \\/_/ \\/_/\\/_____/ \\/_/ \\/_____/ \\/_/\\/_/\n \n\n");
|
|
60
63
|
const isCurrentDir = projectName === "." || projectName === "./" || projectName === ".\\";
|
|
61
64
|
const rootDir = isCurrentDir ? process.cwd() : path.join(process.cwd(), projectName);
|
|
@@ -147,6 +150,34 @@ const create = async ({ projectName, template, cursorEnabled, context }) => {
|
|
|
147
150
|
rootDir
|
|
148
151
|
}, context);
|
|
149
152
|
if (template) await setupTemplate(template, rootDir, context);
|
|
153
|
+
if (!isPluginTemplate) {
|
|
154
|
+
const motiaConfigPath = path.join(rootDir, "motia.config.ts");
|
|
155
|
+
const redisConfig = generateRedisConfig(skipRedis);
|
|
156
|
+
if (checkIfFileExists(rootDir, "motia.config.ts")) {
|
|
157
|
+
let configContent = fs.readFileSync(motiaConfigPath, "utf-8");
|
|
158
|
+
if (!configContent.includes("redis:")) {
|
|
159
|
+
if (configContent.includes("export default config({")) configContent = configContent.replace(/export default config\(/, `export default config({\n${redisConfig}`);
|
|
160
|
+
else if (configContent.includes("config({")) configContent = configContent.replace(/config\(/, `config({\n${redisConfig}`);
|
|
161
|
+
else {
|
|
162
|
+
const lines = configContent.split("\n");
|
|
163
|
+
const lastLine = lines[lines.length - 1];
|
|
164
|
+
if (lastLine.trim() === "})" || lastLine.trim() === ")") {
|
|
165
|
+
lines.splice(lines.length - 1, 0, redisConfig.trim());
|
|
166
|
+
configContent = lines.join("\n");
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
fs.writeFileSync(motiaConfigPath, configContent);
|
|
170
|
+
}
|
|
171
|
+
} else {
|
|
172
|
+
const configContent = `import { config } from '@motiadev/core'
|
|
173
|
+
|
|
174
|
+
export default config({
|
|
175
|
+
${redisConfig}})
|
|
176
|
+
`;
|
|
177
|
+
fs.writeFileSync(motiaConfigPath, configContent);
|
|
178
|
+
context.log("motia-config-created", (message) => message.tag("success").append("File").append("motia.config.ts", "cyan").append("has been created."));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
150
181
|
let packageManager;
|
|
151
182
|
if (!isPluginTemplate) {
|
|
152
183
|
packageManager = await installNodeDependencies(rootDir, context);
|
|
@@ -168,8 +199,12 @@ const create = async ({ projectName, template, cursorEnabled, context }) => {
|
|
|
168
199
|
context.log("success-blank-5", (message) => message.text(""));
|
|
169
200
|
context.log("success-docs", (message) => message.text(`Docs: ${pc.cyan("https://www.motia.dev/docs")}`));
|
|
170
201
|
context.log("success-blank-6", (message) => message.text(""));
|
|
202
|
+
if (skipRedis) {
|
|
203
|
+
context.log("redis-skip-warning", (message) => message.tag("warning").append("⚠️ You skipped Redis binary installation. Make sure to provide a Redis connection before running Motia."));
|
|
204
|
+
context.log("success-blank-7", (message) => message.text(""));
|
|
205
|
+
}
|
|
171
206
|
context.log("success-signoff", (message) => message.text("Happy coding! 🚀"));
|
|
172
|
-
context.log("success-blank-
|
|
207
|
+
context.log("success-blank-8", (message) => message.text(""));
|
|
173
208
|
};
|
|
174
209
|
|
|
175
210
|
//#endregion
|
|
@@ -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') || 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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"}
|
|
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 generateRedisConfig = (skipRedis: boolean): string => {\n return skipRedis\n ? ` redis: {\\n useMemoryServer: false,\\n host: '127.0.0.1',\\n port: 6379,\\n },\\n`\n : ` redis: {\\n useMemoryServer: true,\\n },\\n`\n}\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, { env: { REDISMS_DISABLE_POSTINSTALL: '1' } })\n await executeCommand(`${installCommand} -D ${devDependencies}`, rootDir, {\n env: { REDISMS_DISABLE_POSTINSTALL: '1' },\n })\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 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 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) {\n const motiaConfigPath = path.join(rootDir, 'motia.config.ts')\n const redisConfig = generateRedisConfig(skipRedis)\n\n if (checkIfFileExists(rootDir, 'motia.config.ts')) {\n let configContent = fs.readFileSync(motiaConfigPath, 'utf-8')\n if (!configContent.includes('redis:')) {\n if (configContent.includes('export default config({')) {\n configContent = configContent.replace(/export default config\\(/, `export default config({\\n${redisConfig}`)\n } else if (configContent.includes('config({')) {\n configContent = configContent.replace(/config\\(/, `config({\\n${redisConfig}`)\n } else {\n const lines = configContent.split('\\n')\n const lastLine = lines[lines.length - 1]\n if (lastLine.trim() === '})' || lastLine.trim() === ')') {\n lines.splice(lines.length - 1, 0, redisConfig.trim())\n configContent = lines.join('\\n')\n }\n }\n fs.writeFileSync(motiaConfigPath, configContent)\n }\n } else {\n const configContent = `import { config } from '@motiadev/core'\n\nexport default config({\n${redisConfig}})\n`\n fs.writeFileSync(motiaConfigPath, configContent)\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\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 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 +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 only)',\n 'motia-tutorial-python': 'Tutorial (Python only)',\n 'starter-multilang': 'Starter (All languages; TS/JS + Python)',\n 'starter-typescript': 'Starter (TypeScript only)',\n 'starter-javascript': 'Starter (JavaScript only)',\n 'starter-python': 'Starter (Python 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
|
|
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-typescript': 'Starter (TypeScript only)',\n 'starter-javascript': 'Starter (JavaScript only)',\n 'starter-python': 'Starter (Python only)',\n}\n\ninterface CreateInteractiveArgs {\n name?: string\n template?: string\n plugin?: boolean\n skipRedis?: 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,\n context,\n skipRedis: args.skipRedis,\n })\n\n process.exit(0)\n}\n"],"mappings":";;;;;AAUA,MAAMA,UAAkC;CACtC,6BAA6B;CAC7B,yBAAyB;CACzB,qBAAqB;CACrB,sBAAsB;CACtB,sBAAsB;CACtB,kBAAkB;CACnB;AASD,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;EACA,WAAW,KAAK;EACjB,CAAC;AAEF,SAAQ,KAAK,EAAE"}
|
package/dist/dev.mjs
CHANGED
|
@@ -3,12 +3,12 @@ import { generateLockedData, getStepFiles, getStreamFiles } from "./generate-loc
|
|
|
3
3
|
import { version } from "./version.mjs";
|
|
4
4
|
import { identifyUser } from "./utils/analytics.mjs";
|
|
5
5
|
import { loadMotiaConfig } from "./load-motia-config.mjs";
|
|
6
|
-
import { instanceRedisMemoryServer, stopRedisMemoryServer } from "./redis-memory-manager.mjs";
|
|
7
6
|
import { deployEndpoints } from "./cloud/endpoints.mjs";
|
|
8
7
|
import { isTutorialDisabled, workbenchBase } from "./constants.mjs";
|
|
9
8
|
import { createDevWatchers } from "./dev-watchers.mjs";
|
|
10
9
|
import { processPlugins } from "./plugins/process-plugins.mjs";
|
|
11
10
|
import "./plugins/index.mjs";
|
|
11
|
+
import { getRedisClient, stopRedisConnection } from "./redis/connection.mjs";
|
|
12
12
|
import { createMermaidGenerator, createServer, getProjectIdentifier, trackEvent } from "@motiadev/core";
|
|
13
13
|
import { flush } from "@amplitude/analytics-node";
|
|
14
14
|
import { BullMQEventAdapter } from "@motiadev/adapter-bullmq-events";
|
|
@@ -40,7 +40,7 @@ const dev = async (port, hostname, disableVerbose, enableMermaid, motiaFileStora
|
|
|
40
40
|
}
|
|
41
41
|
const motiaFileStoragePath = motiaFileStorageDir || ".motia";
|
|
42
42
|
const appConfig = await loadMotiaConfig(baseDir);
|
|
43
|
-
const redisClient = await
|
|
43
|
+
const redisClient = await getRedisClient(motiaFileStoragePath, appConfig);
|
|
44
44
|
const adapters = {
|
|
45
45
|
eventAdapter: appConfig.adapters?.events || new BullMQEventAdapter({
|
|
46
46
|
connection: {
|
|
@@ -99,7 +99,7 @@ const dev = async (port, hostname, disableVerbose, enableMermaid, motiaFileStora
|
|
|
99
99
|
trackEvent("dev_server_shutdown", { reason: "SIGTERM" });
|
|
100
100
|
motiaServer.server.close();
|
|
101
101
|
await watcher.stop();
|
|
102
|
-
await
|
|
102
|
+
await stopRedisConnection();
|
|
103
103
|
await flush().promise;
|
|
104
104
|
process.exit(0);
|
|
105
105
|
});
|
|
@@ -107,7 +107,7 @@ const dev = async (port, hostname, disableVerbose, enableMermaid, motiaFileStora
|
|
|
107
107
|
trackEvent("dev_server_shutdown", { reason: "SIGINT" });
|
|
108
108
|
motiaServer.server.close();
|
|
109
109
|
await watcher.stop();
|
|
110
|
-
await
|
|
110
|
+
await stopRedisConnection();
|
|
111
111
|
await flush().promise;
|
|
112
112
|
process.exit(0);
|
|
113
113
|
});
|
package/dist/dev.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.mjs","names":["redisClient: RedisClientType","plugins: MotiaPlugin[]"],"sources":["../src/dev.ts"],"sourcesContent":["import { flush } from '@amplitude/analytics-node'\nimport { BullMQEventAdapter } from '@motiadev/adapter-bullmq-events'\nimport { RedisCronAdapter } from '@motiadev/adapter-redis-cron'\nimport { RedisStateAdapter } from '@motiadev/adapter-redis-state'\nimport { RedisStreamAdapterManager } from '@motiadev/adapter-redis-streams'\nimport {\n createMermaidGenerator,\n createServer,\n getProjectIdentifier,\n type MotiaPlugin,\n trackEvent,\n} from '@motiadev/core'\nimport type { RedisClientType } from 'redis'\nimport { deployEndpoints } from './cloud/endpoints'\nimport { isTutorialDisabled, workbenchBase } from './constants'\nimport { createDevWatchers } from './dev-watchers'\nimport { generateLockedData, getStepFiles, getStreamFiles } from './generate-locked-data'\nimport { loadMotiaConfig } from './load-motia-config'\nimport { processPlugins } from './plugins'\nimport {
|
|
1
|
+
{"version":3,"file":"dev.mjs","names":["redisClient: RedisClientType","plugins: MotiaPlugin[]"],"sources":["../src/dev.ts"],"sourcesContent":["import { flush } from '@amplitude/analytics-node'\nimport { BullMQEventAdapter } from '@motiadev/adapter-bullmq-events'\nimport { RedisCronAdapter } from '@motiadev/adapter-redis-cron'\nimport { RedisStateAdapter } from '@motiadev/adapter-redis-state'\nimport { RedisStreamAdapterManager } from '@motiadev/adapter-redis-streams'\nimport {\n createMermaidGenerator,\n createServer,\n getProjectIdentifier,\n type MotiaPlugin,\n trackEvent,\n} from '@motiadev/core'\nimport type { RedisClientType } from 'redis'\nimport { deployEndpoints } from './cloud/endpoints'\nimport { isTutorialDisabled, workbenchBase } from './constants'\nimport { createDevWatchers } from './dev-watchers'\nimport { generateLockedData, getStepFiles, getStreamFiles } from './generate-locked-data'\nimport { loadMotiaConfig } from './load-motia-config'\nimport { processPlugins } from './plugins'\nimport { getRedisClient, stopRedisConnection } from './redis/connection'\nimport { activatePythonVenv } from './utils/activate-python-env'\nimport { identifyUser } from './utils/analytics'\nimport { version } from './version'\n\nexport const dev = async (\n port: number,\n hostname: string,\n disableVerbose: boolean,\n enableMermaid: boolean,\n motiaFileStorageDir?: string,\n): Promise<void> => {\n const baseDir = process.cwd()\n const isVerbose = !disableVerbose\n\n identifyUser()\n\n const stepFiles = [...getStepFiles(baseDir), ...getStreamFiles(baseDir)]\n const hasPythonFiles = stepFiles.some((file) => file.endsWith('.py'))\n\n trackEvent('dev_server_started', {\n port,\n verbose_mode: isVerbose,\n mermaid_enabled: enableMermaid,\n has_python_files: hasPythonFiles,\n total_step_files: stepFiles.length,\n project_name: getProjectIdentifier(baseDir),\n })\n\n if (hasPythonFiles) {\n activatePythonVenv({ baseDir, isVerbose })\n trackEvent('python_environment_activated')\n }\n\n const motiaFileStoragePath = motiaFileStorageDir || '.motia'\n\n const appConfig = await loadMotiaConfig(baseDir)\n\n const redisClient: RedisClientType = await getRedisClient(motiaFileStoragePath, appConfig)\n\n const adapters = {\n eventAdapter:\n appConfig.adapters?.events ||\n new BullMQEventAdapter({\n connection: {\n host: (redisClient.options.socket as { host?: string })?.host || 'localhost',\n port: (redisClient.options.socket as { port?: number })?.port || 6379,\n },\n prefix: 'motia:events',\n }),\n cronAdapter: appConfig.adapters?.cron || new RedisCronAdapter(redisClient),\n streamAdapter: appConfig.adapters?.streams || new RedisStreamAdapterManager(redisClient),\n }\n\n const lockedData = await generateLockedData({\n projectDir: baseDir,\n streamAdapter: adapters.streamAdapter,\n redisClient,\n streamAuth: appConfig.streamAuth,\n })\n\n const state = appConfig.adapters?.state || new RedisStateAdapter(redisClient)\n\n const config = { isVerbose }\n\n const motiaServer = createServer(lockedData, state, config, adapters, appConfig.app)\n const watcher = createDevWatchers(lockedData, motiaServer, motiaServer.motiaEventManager, motiaServer.cronManager)\n const plugins: MotiaPlugin[] = await processPlugins(motiaServer)\n\n // Initialize mermaid generator\n if (enableMermaid) {\n const mermaidGenerator = createMermaidGenerator(baseDir)\n mermaidGenerator.initialize(lockedData)\n trackEvent('mermaid_generator_initialized')\n }\n\n deployEndpoints(motiaServer, lockedData)\n\n motiaServer.app.get('/__motia', (_, res) => {\n const meta = {\n version,\n isDev: true,\n isTutorialDisabled,\n workbenchBase,\n }\n\n res //\n .header('Access-Control-Allow-Origin', '*')\n .header('Access-Control-Allow-Private-Network', 'true')\n .status(200)\n .json(meta)\n })\n\n trackEvent('dev_server_ready', {\n port,\n flows_count: lockedData.flows?.length || 0,\n steps_count: lockedData.activeSteps?.length || 0,\n flows: Object.keys(lockedData.flows || {}),\n steps: lockedData.activeSteps.map((step) => step.config.name),\n streams: Object.keys(lockedData.getStreams() || {}),\n runtime_version: version,\n environment: process.env.NODE_ENV || 'development',\n })\n\n const { applyMiddleware } = await import('@motiadev/workbench/middleware')\n\n await applyMiddleware({\n app: motiaServer.app,\n port,\n workbenchBase,\n plugins: plugins.flatMap((item) => item.workbench),\n })\n\n motiaServer.server.listen(port, hostname)\n console.log('🚀 Server ready and listening on port', port)\n console.log(`🔗 Open http://localhost:${port}${workbenchBase} to open workbench 🛠️`)\n\n process.on('SIGTERM', async () => {\n trackEvent('dev_server_shutdown', { reason: 'SIGTERM' })\n motiaServer.server.close()\n await watcher.stop()\n await stopRedisConnection()\n await flush().promise\n process.exit(0)\n })\n\n process.on('SIGINT', async () => {\n trackEvent('dev_server_shutdown', { reason: 'SIGINT' })\n motiaServer.server.close()\n await watcher.stop()\n await stopRedisConnection()\n await flush().promise\n process.exit(0)\n })\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { RedisMemoryManager } from "./memory-manager.mjs";
|
|
2
|
+
import { isExternalRedisConfig, shouldUseMemoryServer } from "./utils.mjs";
|
|
3
|
+
import { createClient } from "redis";
|
|
4
|
+
|
|
5
|
+
//#region src/redis/connection.ts
|
|
6
|
+
var RedisConnectionManager = class {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.client = null;
|
|
9
|
+
}
|
|
10
|
+
async getConnectionInfo(baseDir, config) {
|
|
11
|
+
if (shouldUseMemoryServer(config)) return await new RedisMemoryManager().startServer(baseDir);
|
|
12
|
+
if (isExternalRedisConfig(config.redis)) return {
|
|
13
|
+
host: config.redis.host,
|
|
14
|
+
port: config.redis.port
|
|
15
|
+
};
|
|
16
|
+
return {
|
|
17
|
+
host: process.env.MOTIA_REDIS_HOST || "127.0.0.1",
|
|
18
|
+
port: parseInt(process.env.MOTIA_REDIS_PORT || "6379")
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
async connect(baseDir, config) {
|
|
22
|
+
if (this.client) return this.client;
|
|
23
|
+
const { host, port } = await this.getConnectionInfo(baseDir, config);
|
|
24
|
+
this.client = createClient({ socket: {
|
|
25
|
+
host,
|
|
26
|
+
port,
|
|
27
|
+
noDelay: true,
|
|
28
|
+
keepAlive: true,
|
|
29
|
+
reconnectStrategy: (retries) => {
|
|
30
|
+
if (retries > 10) return /* @__PURE__ */ new Error("Redis connection retry limit exceeded");
|
|
31
|
+
return Math.min(retries * 100, 3e3);
|
|
32
|
+
},
|
|
33
|
+
connectTimeout: 1e4
|
|
34
|
+
} });
|
|
35
|
+
return this.client;
|
|
36
|
+
}
|
|
37
|
+
async stop() {
|
|
38
|
+
if (this.client) {
|
|
39
|
+
await this.client.quit();
|
|
40
|
+
this.client = null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
isRunning() {
|
|
44
|
+
return !!this.client?.isOpen;
|
|
45
|
+
}
|
|
46
|
+
getClient() {
|
|
47
|
+
return this.client;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
const manager = new RedisConnectionManager();
|
|
51
|
+
const getRedisClient = (baseDir, config) => manager.connect(baseDir, config);
|
|
52
|
+
const stopRedisConnection = () => manager.stop();
|
|
53
|
+
|
|
54
|
+
//#endregion
|
|
55
|
+
export { getRedisClient, stopRedisConnection };
|
|
56
|
+
//# sourceMappingURL=connection.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.mjs","names":[],"sources":["../../src/redis/connection.ts"],"sourcesContent":["import { createClient, type RedisClientType } from 'redis'\nimport type { LoadedMotiaConfig } from '../load-motia-config'\nimport { RedisMemoryManager } from './memory-manager'\nimport type { RedisConnectionInfo } from './types'\nimport { isExternalRedisConfig, shouldUseMemoryServer } from './utils'\n\nexport type { RedisConnectionInfo } from './types'\n\nclass RedisConnectionManager {\n private client: RedisClientType | null = null\n\n private async getConnectionInfo(baseDir: string, config: LoadedMotiaConfig): Promise<RedisConnectionInfo> {\n if (shouldUseMemoryServer(config)) {\n return await new RedisMemoryManager().startServer(baseDir)\n }\n if (isExternalRedisConfig(config.redis)) {\n return { host: config.redis.host, port: config.redis.port }\n }\n return { host: process.env.MOTIA_REDIS_HOST || '127.0.0.1', port: parseInt(process.env.MOTIA_REDIS_PORT || '6379') }\n }\n\n async connect(baseDir: string, config: LoadedMotiaConfig): Promise<RedisClientType> {\n if (this.client) {\n return this.client\n }\n\n const { host, port } = await this.getConnectionInfo(baseDir, config)\n\n this.client = createClient({\n socket: {\n host,\n port,\n noDelay: true,\n keepAlive: true,\n reconnectStrategy: (retries: number) => {\n if (retries > 10) {\n return new Error('Redis connection retry limit exceeded')\n }\n return Math.min(retries * 100, 3000)\n },\n connectTimeout: 10000,\n },\n })\n return this.client\n }\n\n async stop(): Promise<void> {\n if (this.client) {\n await this.client.quit()\n this.client = null\n }\n }\n\n isRunning(): boolean {\n return !!this.client?.isOpen\n }\n\n getClient(): RedisClientType | null {\n return this.client\n }\n}\n\nconst manager = new RedisConnectionManager()\n\nexport const getRedisClient = (baseDir: string, config: LoadedMotiaConfig): Promise<RedisClientType> =>\n manager.connect(baseDir, config)\n\nexport const stopRedisConnection = (): Promise<void> => manager.stop()\n"],"mappings":";;;;;AAQA,IAAM,yBAAN,MAA6B;;gBACc;;CAEzC,MAAc,kBAAkB,SAAiB,QAAyD;AACxG,MAAI,sBAAsB,OAAO,CAC/B,QAAO,MAAM,IAAI,oBAAoB,CAAC,YAAY,QAAQ;AAE5D,MAAI,sBAAsB,OAAO,MAAM,CACrC,QAAO;GAAE,MAAM,OAAO,MAAM;GAAM,MAAM,OAAO,MAAM;GAAM;AAE7D,SAAO;GAAE,MAAM,QAAQ,IAAI,oBAAoB;GAAa,MAAM,SAAS,QAAQ,IAAI,oBAAoB,OAAO;GAAE;;CAGtH,MAAM,QAAQ,SAAiB,QAAqD;AAClF,MAAI,KAAK,OACP,QAAO,KAAK;EAGd,MAAM,EAAE,MAAM,SAAS,MAAM,KAAK,kBAAkB,SAAS,OAAO;AAEpE,OAAK,SAAS,aAAa,EACzB,QAAQ;GACN;GACA;GACA,SAAS;GACT,WAAW;GACX,oBAAoB,YAAoB;AACtC,QAAI,UAAU,GACZ,wBAAO,IAAI,MAAM,wCAAwC;AAE3D,WAAO,KAAK,IAAI,UAAU,KAAK,IAAK;;GAEtC,gBAAgB;GACjB,EACF,CAAC;AACF,SAAO,KAAK;;CAGd,MAAM,OAAsB;AAC1B,MAAI,KAAK,QAAQ;AACf,SAAM,KAAK,OAAO,MAAM;AACxB,QAAK,SAAS;;;CAIlB,YAAqB;AACnB,SAAO,CAAC,CAAC,KAAK,QAAQ;;CAGxB,YAAoC;AAClC,SAAO,KAAK;;;AAIhB,MAAM,UAAU,IAAI,wBAAwB;AAE5C,MAAa,kBAAkB,SAAiB,WAC9C,QAAQ,QAAQ,SAAS,OAAO;AAElC,MAAa,4BAA2C,QAAQ,MAAM"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { mkdirSync } from "fs";
|
|
2
|
+
import { RedisMemoryServer } from "redis-memory-server";
|
|
3
|
+
|
|
4
|
+
//#region src/redis/memory-manager.ts
|
|
5
|
+
var RedisMemoryManager = class {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.server = null;
|
|
8
|
+
this.client = null;
|
|
9
|
+
this.running = false;
|
|
10
|
+
}
|
|
11
|
+
registerCleanupHandlers() {
|
|
12
|
+
process.on("exit", async () => {
|
|
13
|
+
await this.stop();
|
|
14
|
+
});
|
|
15
|
+
process.on("SIGTERM", async () => {
|
|
16
|
+
await this.stop();
|
|
17
|
+
});
|
|
18
|
+
process.on("SIGINT", async () => {
|
|
19
|
+
await this.stop();
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
async startServer(baseDir) {
|
|
23
|
+
if (!this.server) try {
|
|
24
|
+
mkdirSync(baseDir, { recursive: true });
|
|
25
|
+
const instance = { args: [
|
|
26
|
+
"--appendonly",
|
|
27
|
+
"yes",
|
|
28
|
+
"--appendfsync",
|
|
29
|
+
"everysec",
|
|
30
|
+
"--save",
|
|
31
|
+
"\"\"",
|
|
32
|
+
"--dir",
|
|
33
|
+
baseDir
|
|
34
|
+
] };
|
|
35
|
+
if (process.env.MOTIA_REDIS_PORT) instance.port = parseInt(process.env.MOTIA_REDIS_PORT || "6379");
|
|
36
|
+
this.server = new RedisMemoryServer({ instance });
|
|
37
|
+
this.running = true;
|
|
38
|
+
this.registerCleanupHandlers();
|
|
39
|
+
} catch (error) {
|
|
40
|
+
console.error("[Redis Memory Server] Failed to start:", error);
|
|
41
|
+
throw error;
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
host: await this.server.getHost(),
|
|
45
|
+
port: await this.server.getPort()
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
async stop() {
|
|
49
|
+
if (this.server && this.running) try {
|
|
50
|
+
await this.server.stop();
|
|
51
|
+
this.running = false;
|
|
52
|
+
} catch (error) {
|
|
53
|
+
console.error("[Redis Memory Server] Error stopping:", error?.message);
|
|
54
|
+
} finally {
|
|
55
|
+
this.server = null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
isRunning() {
|
|
59
|
+
return this.running;
|
|
60
|
+
}
|
|
61
|
+
getClient() {
|
|
62
|
+
return this.client;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
//#endregion
|
|
67
|
+
export { RedisMemoryManager };
|
|
68
|
+
//# sourceMappingURL=memory-manager.mjs.map
|
|
@@ -0,0 +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 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 this.running = false\n } catch (error: unknown) {\n console.error('[Redis Memory Server] Error stopping:', (error as Error)?.message)\n } finally {\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,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;AACxB,QAAK,UAAU;WACRC,OAAgB;AACvB,WAAQ,MAAM,yCAA0C,OAAiB,QAAQ;YACzE;AACR,QAAK,SAAS;;;CAKpB,YAAqB;AACnB,SAAO,KAAK;;CAGd,YAAoC;AAClC,SAAO,KAAK"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/redis/utils.ts
|
|
2
|
+
const shouldUseMemoryServer = (config) => {
|
|
3
|
+
if (process.env.MOTIA_DISABLE_MEMORY_SERVER === "true") return false;
|
|
4
|
+
if (process.env.MOTIA_REDIS_HOST && process.env.MOTIA_REDIS_HOST !== "127.0.0.1") return false;
|
|
5
|
+
const redisConfig = config.redis;
|
|
6
|
+
if (redisConfig && "useMemoryServer" in redisConfig && redisConfig.useMemoryServer === false) return false;
|
|
7
|
+
return redisConfig?.useMemoryServer !== void 0 ? redisConfig.useMemoryServer === true : true;
|
|
8
|
+
};
|
|
9
|
+
const isExternalRedisConfig = (redisConfig) => {
|
|
10
|
+
return redisConfig !== void 0 && "host" in redisConfig && "port" in redisConfig;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
//#endregion
|
|
14
|
+
export { isExternalRedisConfig, shouldUseMemoryServer };
|
|
15
|
+
//# sourceMappingURL=utils.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.mjs","names":[],"sources":["../../src/redis/utils.ts"],"sourcesContent":["import type { RedisConfig } from '@motiadev/core'\nimport type { LoadedMotiaConfig } from '../load-motia-config'\n\nexport const shouldUseMemoryServer = (config: LoadedMotiaConfig): boolean => {\n if (process.env.MOTIA_DISABLE_MEMORY_SERVER === 'true') {\n return false\n }\n\n if (process.env.MOTIA_REDIS_HOST && process.env.MOTIA_REDIS_HOST !== '127.0.0.1') {\n return false\n }\n\n const redisConfig = config.redis\n if (redisConfig && 'useMemoryServer' in redisConfig && redisConfig.useMemoryServer === false) {\n return false\n }\n\n return redisConfig?.useMemoryServer !== undefined ? redisConfig.useMemoryServer === true : true\n}\n\nexport const isExternalRedisConfig = (\n redisConfig: RedisConfig | undefined,\n): redisConfig is Extract<RedisConfig, { useMemoryServer?: false; host: string; port: number }> => {\n return redisConfig !== undefined && 'host' in redisConfig && 'port' in redisConfig\n}\n"],"mappings":";AAGA,MAAa,yBAAyB,WAAuC;AAC3E,KAAI,QAAQ,IAAI,gCAAgC,OAC9C,QAAO;AAGT,KAAI,QAAQ,IAAI,oBAAoB,QAAQ,IAAI,qBAAqB,YACnE,QAAO;CAGT,MAAM,cAAc,OAAO;AAC3B,KAAI,eAAe,qBAAqB,eAAe,YAAY,oBAAoB,MACrF,QAAO;AAGT,QAAO,aAAa,oBAAoB,SAAY,YAAY,oBAAoB,OAAO;;AAG7F,MAAa,yBACX,gBACiG;AACjG,QAAO,gBAAgB,UAAa,UAAU,eAAe,UAAU"}
|
package/dist/start.mjs
CHANGED
|
@@ -2,10 +2,10 @@ import { activatePythonVenv } from "./utils/activate-python-env.mjs";
|
|
|
2
2
|
import { generateLockedData, getStepFiles, getStreamFiles } from "./generate-locked-data.mjs";
|
|
3
3
|
import { version } from "./version.mjs";
|
|
4
4
|
import { loadMotiaConfig } from "./load-motia-config.mjs";
|
|
5
|
-
import { instanceRedisMemoryServer, stopRedisMemoryServer } from "./redis-memory-manager.mjs";
|
|
6
5
|
import { workbenchBase } from "./constants.mjs";
|
|
7
6
|
import { processPlugins } from "./plugins/process-plugins.mjs";
|
|
8
7
|
import "./plugins/index.mjs";
|
|
8
|
+
import { getRedisClient, stopRedisConnection } from "./redis/connection.mjs";
|
|
9
9
|
import { createServer } from "@motiadev/core";
|
|
10
10
|
import path from "path";
|
|
11
11
|
import { BullMQEventAdapter } from "@motiadev/adapter-bullmq-events";
|
|
@@ -27,7 +27,7 @@ const start = async (port, hostname, disableVerbose, motiaFileStorageDir) => {
|
|
|
27
27
|
const motiaFileStoragePath = motiaFileStorageDir || ".motia";
|
|
28
28
|
const dotMotia = path.join(baseDir, motiaFileStoragePath);
|
|
29
29
|
const appConfig = await loadMotiaConfig(baseDir);
|
|
30
|
-
const redisClient = await
|
|
30
|
+
const redisClient = await getRedisClient(dotMotia, appConfig, true);
|
|
31
31
|
const adapters = {
|
|
32
32
|
eventAdapter: appConfig.adapters?.events || new BullMQEventAdapter({ connection: {
|
|
33
33
|
host: redisClient.options.socket?.host || "localhost",
|
|
@@ -61,12 +61,12 @@ const start = async (port, hostname, disableVerbose, motiaFileStorageDir) => {
|
|
|
61
61
|
console.log(`🔗 Open http://${hostname}:${port}${workbenchBase} to open workbench 🛠️`);
|
|
62
62
|
process.on("SIGTERM", async () => {
|
|
63
63
|
motiaServer.server.close();
|
|
64
|
-
await
|
|
64
|
+
await stopRedisConnection();
|
|
65
65
|
process.exit(0);
|
|
66
66
|
});
|
|
67
67
|
process.on("SIGINT", async () => {
|
|
68
68
|
motiaServer.server.close();
|
|
69
|
-
await
|
|
69
|
+
await stopRedisConnection();
|
|
70
70
|
process.exit(0);
|
|
71
71
|
});
|
|
72
72
|
};
|
package/dist/start.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start.mjs","names":["redisClient: RedisClientType","plugins: MotiaPlugin[]"],"sources":["../src/start.ts"],"sourcesContent":["import { BullMQEventAdapter } from '@motiadev/adapter-bullmq-events'\nimport { RedisCronAdapter } from '@motiadev/adapter-redis-cron'\nimport { RedisStateAdapter } from '@motiadev/adapter-redis-state'\nimport { RedisStreamAdapterManager } from '@motiadev/adapter-redis-streams'\nimport { createServer, type MotiaPlugin } from '@motiadev/core'\nimport path from 'path'\nimport type { RedisClientType } from 'redis'\nimport { workbenchBase } from './constants'\nimport { generateLockedData, getStepFiles, getStreamFiles } from './generate-locked-data'\nimport { loadMotiaConfig } from './load-motia-config'\nimport { processPlugins } from './plugins/index'\nimport {
|
|
1
|
+
{"version":3,"file":"start.mjs","names":["redisClient: RedisClientType","plugins: MotiaPlugin[]"],"sources":["../src/start.ts"],"sourcesContent":["import { BullMQEventAdapter } from '@motiadev/adapter-bullmq-events'\nimport { RedisCronAdapter } from '@motiadev/adapter-redis-cron'\nimport { RedisStateAdapter } from '@motiadev/adapter-redis-state'\nimport { RedisStreamAdapterManager } from '@motiadev/adapter-redis-streams'\nimport { createServer, type MotiaPlugin } from '@motiadev/core'\nimport path from 'path'\nimport type { RedisClientType } from 'redis'\nimport { workbenchBase } from './constants'\nimport { generateLockedData, getStepFiles, getStreamFiles } from './generate-locked-data'\nimport { loadMotiaConfig } from './load-motia-config'\nimport { processPlugins } from './plugins/index'\nimport { getRedisClient, stopRedisConnection } from './redis/connection'\nimport { activatePythonVenv } from './utils/activate-python-env'\nimport { version } from './version'\n\nexport const start = async (\n port: number,\n hostname: string,\n disableVerbose: boolean,\n motiaFileStorageDir?: string,\n): Promise<void> => {\n const baseDir = process.cwd()\n const isVerbose = !disableVerbose\n\n const stepFiles = [...getStepFiles(baseDir), ...getStreamFiles(baseDir)]\n const hasPythonFiles = stepFiles.some((file) => file.endsWith('.py'))\n\n if (hasPythonFiles) {\n console.log('⚙️ Activating Python environment...')\n activatePythonVenv({ baseDir, isVerbose })\n }\n\n const motiaFileStoragePath = motiaFileStorageDir || '.motia'\n\n const dotMotia = path.join(baseDir, motiaFileStoragePath)\n const appConfig = await loadMotiaConfig(baseDir)\n\n const redisClient: RedisClientType = await getRedisClient(dotMotia, appConfig, true)\n\n const adapters = {\n eventAdapter:\n appConfig.adapters?.events ||\n new BullMQEventAdapter({\n connection: {\n host: (redisClient.options.socket as { host?: string })?.host || 'localhost',\n port: (redisClient.options.socket as { port?: number })?.port || 6379,\n },\n }),\n cronAdapter: appConfig.adapters?.cron || new RedisCronAdapter(redisClient),\n streamAdapter: appConfig.adapters?.streams || new RedisStreamAdapterManager(redisClient),\n }\n const lockedData = await generateLockedData({\n projectDir: baseDir,\n streamAdapter: adapters.streamAdapter,\n redisClient,\n streamAuth: appConfig.streamAuth,\n })\n\n const state = appConfig.adapters?.state || new RedisStateAdapter(redisClient)\n\n const config = { isVerbose, isDev: false, version }\n\n const motiaServer = createServer(lockedData, state, config, adapters, appConfig.app)\n const plugins: MotiaPlugin[] = await processPlugins(motiaServer)\n\n if (!process.env.MOTIA_DOCKER_DISABLE_WORKBENCH) {\n const { applyMiddleware } = await import('@motiadev/workbench/middleware')\n await applyMiddleware({\n app: motiaServer.app,\n port,\n workbenchBase,\n plugins: plugins.flatMap((item) => item.workbench),\n })\n }\n\n motiaServer.server.listen(port, hostname)\n console.log('🚀 Server ready and listening on port', port)\n console.log(`🔗 Open http://${hostname}:${port}${workbenchBase} to open workbench 🛠️`)\n\n process.on('SIGTERM', async () => {\n motiaServer.server.close()\n await stopRedisConnection()\n process.exit(0)\n })\n\n process.on('SIGINT', async () => {\n motiaServer.server.close()\n await stopRedisConnection()\n process.exit(0)\n })\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAeA,MAAa,QAAQ,OACnB,MACA,UACA,gBACA,wBACkB;CAClB,MAAM,UAAU,QAAQ,KAAK;CAC7B,MAAM,YAAY,CAAC;AAKnB,KAHkB,CAAC,GAAG,aAAa,QAAQ,EAAE,GAAG,eAAe,QAAQ,CAAC,CACvC,MAAM,SAAS,KAAK,SAAS,MAAM,CAAC,EAEjD;AAClB,UAAQ,IAAI,sCAAsC;AAClD,qBAAmB;GAAE;GAAS;GAAW,CAAC;;CAG5C,MAAM,uBAAuB,uBAAuB;CAEpD,MAAM,WAAW,KAAK,KAAK,SAAS,qBAAqB;CACzD,MAAM,YAAY,MAAM,gBAAgB,QAAQ;CAEhD,MAAMA,cAA+B,MAAM,eAAe,UAAU,WAAW,KAAK;CAEpF,MAAM,WAAW;EACf,cACE,UAAU,UAAU,UACpB,IAAI,mBAAmB,EACrB,YAAY;GACV,MAAO,YAAY,QAAQ,QAA8B,QAAQ;GACjE,MAAO,YAAY,QAAQ,QAA8B,QAAQ;GAClE,EACF,CAAC;EACJ,aAAa,UAAU,UAAU,QAAQ,IAAI,iBAAiB,YAAY;EAC1E,eAAe,UAAU,UAAU,WAAW,IAAI,0BAA0B,YAAY;EACzF;CAYD,MAAM,cAAc,aAXD,MAAM,mBAAmB;EAC1C,YAAY;EACZ,eAAe,SAAS;EACxB;EACA,YAAY,UAAU;EACvB,CAAC,EAEY,UAAU,UAAU,SAAS,IAAI,kBAAkB,YAAY,EAE9D;EAAE;EAAW,OAAO;EAAO;EAAS,EAES,UAAU,UAAU,IAAI;CACpF,MAAMC,UAAyB,MAAM,eAAe,YAAY;AAEhE,KAAI,CAAC,QAAQ,IAAI,gCAAgC;EAC/C,MAAM,EAAE,oBAAoB,MAAM,OAAO;AACzC,QAAM,gBAAgB;GACpB,KAAK,YAAY;GACjB;GACA;GACA,SAAS,QAAQ,SAAS,SAAS,KAAK,UAAU;GACnD,CAAC;;AAGJ,aAAY,OAAO,OAAO,MAAM,SAAS;AACzC,SAAQ,IAAI,yCAAyC,KAAK;AAC1D,SAAQ,IAAI,kBAAkB,SAAS,GAAG,OAAO,cAAc,wBAAwB;AAEvF,SAAQ,GAAG,WAAW,YAAY;AAChC,cAAY,OAAO,OAAO;AAC1B,QAAM,qBAAqB;AAC3B,UAAQ,KAAK,EAAE;GACf;AAEF,SAAQ,GAAG,UAAU,YAAY;AAC/B,cAAY,OAAO,OAAO;AAC1B,QAAM,qBAAqB;AAC3B,UAAQ,KAAK,EAAE;GACf"}
|
|
@@ -2,9 +2,12 @@ import { exec } from "child_process";
|
|
|
2
2
|
|
|
3
3
|
//#region src/utils/execute-command.ts
|
|
4
4
|
const executeCommand = async (command, rootDir, options) => {
|
|
5
|
-
const { silent = false } = options || {};
|
|
5
|
+
const { silent = false, env = {} } = options || {};
|
|
6
6
|
return new Promise((resolve, reject) => {
|
|
7
|
-
exec(command, {
|
|
7
|
+
exec(command, {
|
|
8
|
+
cwd: rootDir,
|
|
9
|
+
env: { ...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":";;;
|
|
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 env?: Record<string, string>\n}\n\nexport const executeCommand = async (\n command: string,\n rootDir: string,\n options?: ExecuteCommandOptions,\n): Promise<string> => {\n const { silent = false, env = {} } = options || {}\n\n return new Promise((resolve, reject) => {\n exec(command, { cwd: rootDir, env: { ...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":";;;AAOA,MAAa,iBAAiB,OAC5B,SACA,SACA,YACoB;CACpB,MAAM,EAAE,SAAS,OAAO,MAAM,EAAE,KAAK,WAAW,EAAE;AAElD,QAAO,IAAI,SAAS,SAAS,WAAW;AACtC,OAAK,SAAS;GAAE,KAAK;GAAS,KAAK,EAAE,GAAG,KAAK;GAAE,GAAG,OAAO,QAAQ,WAAW;AAC1E,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"}
|
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.4-beta.
|
|
4
|
+
"version": "0.15.4-beta.170-579134",
|
|
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.4-beta.
|
|
50
|
-
"@motiadev/adapter-redis-
|
|
51
|
-
"@motiadev/
|
|
52
|
-
"@motiadev/
|
|
53
|
-
"@motiadev/
|
|
54
|
-
"@motiadev/adapter-redis-
|
|
55
|
-
"@motiadev/
|
|
49
|
+
"@motiadev/adapter-bullmq-events": "0.15.4-beta.170-579134",
|
|
50
|
+
"@motiadev/adapter-redis-cron": "0.15.4-beta.170-579134",
|
|
51
|
+
"@motiadev/adapter-redis-state": "0.15.4-beta.170-579134",
|
|
52
|
+
"@motiadev/core": "0.15.4-beta.170-579134",
|
|
53
|
+
"@motiadev/workbench": "0.15.4-beta.170-579134",
|
|
54
|
+
"@motiadev/adapter-redis-streams": "0.15.4-beta.170-579134",
|
|
55
|
+
"@motiadev/stream-client-node": "0.15.4-beta.170-579134"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@amplitude/analytics-types": "^2.9.2",
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { mkdirSync } from "fs";
|
|
2
|
-
import { createClient } from "redis";
|
|
3
|
-
import { RedisMemoryServer } from "redis-memory-server";
|
|
4
|
-
|
|
5
|
-
//#region src/redis-memory-manager.ts
|
|
6
|
-
var RedisMemoryManager = class {
|
|
7
|
-
constructor() {
|
|
8
|
-
this.server = null;
|
|
9
|
-
this.client = null;
|
|
10
|
-
this.running = false;
|
|
11
|
-
this.cleanupHandlersRegistered = false;
|
|
12
|
-
}
|
|
13
|
-
registerCleanupHandlers() {
|
|
14
|
-
if (this.cleanupHandlersRegistered) return;
|
|
15
|
-
process.on("exit", () => {
|
|
16
|
-
if (this.client?.isOpen && this.running) this.client.quit().catch((error) => {
|
|
17
|
-
console.error("[Redis Memory Server] Error closing client on exit:", error);
|
|
18
|
-
});
|
|
19
|
-
if (this.server && this.running) this.server.stop().catch((error) => {
|
|
20
|
-
console.error("[Redis Memory Server] Error stopping on exit:", error);
|
|
21
|
-
});
|
|
22
|
-
});
|
|
23
|
-
process.on("SIGTERM", async () => {
|
|
24
|
-
await this.stop();
|
|
25
|
-
});
|
|
26
|
-
process.on("SIGINT", async () => {
|
|
27
|
-
await this.stop();
|
|
28
|
-
});
|
|
29
|
-
this.cleanupHandlersRegistered = true;
|
|
30
|
-
}
|
|
31
|
-
async start(baseDir, autoStart) {
|
|
32
|
-
if (this.client && this.running) return this.client;
|
|
33
|
-
try {
|
|
34
|
-
mkdirSync(baseDir, { recursive: true });
|
|
35
|
-
const instance = {
|
|
36
|
-
ip: process.env.MOTIA_REDIS_HOST || "127.0.0.1",
|
|
37
|
-
args: [
|
|
38
|
-
"--appendonly",
|
|
39
|
-
"yes",
|
|
40
|
-
"--save",
|
|
41
|
-
"900 1",
|
|
42
|
-
"--save",
|
|
43
|
-
"300 10",
|
|
44
|
-
"--save",
|
|
45
|
-
"60 100",
|
|
46
|
-
"--dir",
|
|
47
|
-
baseDir
|
|
48
|
-
]
|
|
49
|
-
};
|
|
50
|
-
if (process.env.MOTIA_REDIS_PORT) instance.port = parseInt(process.env.MOTIA_REDIS_PORT || "6379");
|
|
51
|
-
this.server = new RedisMemoryServer({
|
|
52
|
-
instance,
|
|
53
|
-
autoStart
|
|
54
|
-
});
|
|
55
|
-
const host = await this.server.getHost();
|
|
56
|
-
const port = await this.server.getPort();
|
|
57
|
-
this.client = createClient({ socket: {
|
|
58
|
-
host,
|
|
59
|
-
port,
|
|
60
|
-
noDelay: true,
|
|
61
|
-
keepAlive: true,
|
|
62
|
-
reconnectStrategy: (retries) => {
|
|
63
|
-
if (retries > 10) return /* @__PURE__ */ new Error("Redis connection retry limit exceeded");
|
|
64
|
-
return Math.min(retries * 100, 3e3);
|
|
65
|
-
},
|
|
66
|
-
connectTimeout: 1e4
|
|
67
|
-
} });
|
|
68
|
-
this.client.on("error", (err) => {
|
|
69
|
-
if (err.message.includes("ECONNRESET") || err.message.includes("ECONNREFUSED")) return;
|
|
70
|
-
console.error("[Redis Memory Server] Client error:", err);
|
|
71
|
-
});
|
|
72
|
-
await this.client.connect();
|
|
73
|
-
this.running = true;
|
|
74
|
-
this.registerCleanupHandlers();
|
|
75
|
-
console.log(`[Redis Memory Server] Started on ${host}:${port}`);
|
|
76
|
-
return this.client;
|
|
77
|
-
} catch (error) {
|
|
78
|
-
console.error("[Redis Memory Server] Failed to start:", error);
|
|
79
|
-
throw error;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
async stop() {
|
|
83
|
-
if (this.client && this.running) try {
|
|
84
|
-
if (this.client.isOpen) await this.client.quit().catch();
|
|
85
|
-
this.client = null;
|
|
86
|
-
} catch (error) {}
|
|
87
|
-
if (this.server && this.running) try {
|
|
88
|
-
await this.server.stop();
|
|
89
|
-
this.running = false;
|
|
90
|
-
} catch (error) {
|
|
91
|
-
console.error("[Redis Memory Server] Error stopping:", error);
|
|
92
|
-
} finally {
|
|
93
|
-
this.server = null;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
isRunning() {
|
|
97
|
-
return this.running;
|
|
98
|
-
}
|
|
99
|
-
getClient() {
|
|
100
|
-
return this.client;
|
|
101
|
-
}
|
|
102
|
-
};
|
|
103
|
-
const manager = new RedisMemoryManager();
|
|
104
|
-
const instanceRedisMemoryServer = (baseDir, autoStart = true) => manager.start(baseDir, autoStart);
|
|
105
|
-
const stopRedisMemoryServer = () => manager.stop();
|
|
106
|
-
|
|
107
|
-
//#endregion
|
|
108
|
-
export { instanceRedisMemoryServer, stopRedisMemoryServer };
|
|
109
|
-
//# sourceMappingURL=redis-memory-manager.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"redis-memory-manager.mjs","names":["instance: RedisMemoryInstancePropT"],"sources":["../src/redis-memory-manager.ts"],"sourcesContent":["import { mkdirSync } from 'fs'\nimport { createClient, type RedisClientType } from 'redis'\nimport { RedisMemoryServer } from 'redis-memory-server'\nimport type { RedisMemoryInstancePropT } from 'redis-memory-server/lib/types'\n\nexport interface RedisConnectionInfo {\n host: string\n port: number\n}\n\nclass RedisMemoryManager {\n private server: RedisMemoryServer | null = null\n private client: RedisClientType | null = null\n private running = false\n private cleanupHandlersRegistered = false\n\n private registerCleanupHandlers(): void {\n if (this.cleanupHandlersRegistered) return\n\n process.on('exit', () => {\n if (this.client?.isOpen && this.running) {\n this.client.quit().catch((error: unknown) => {\n console.error('[Redis Memory Server] Error closing client on exit:', error)\n })\n }\n if (this.server && this.running) {\n this.server.stop().catch((error: unknown) => {\n console.error('[Redis Memory Server] Error stopping on exit:', error)\n })\n }\n })\n\n process.on('SIGTERM', async () => {\n await this.stop()\n })\n\n process.on('SIGINT', async () => {\n await this.stop()\n })\n\n this.cleanupHandlersRegistered = true\n }\n\n async start(baseDir: string, autoStart: boolean): Promise<RedisClientType> {\n if (this.client && this.running) {\n return this.client\n }\n\n try {\n mkdirSync(baseDir, { recursive: true })\n\n const instance: RedisMemoryInstancePropT = {\n ip: process.env.MOTIA_REDIS_HOST || '127.0.0.1',\n args: ['--appendonly', 'yes', '--save', '900 1', '--save', '300 10', '--save', '60 100', '--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({\n instance,\n autoStart,\n })\n\n const host = await this.server.getHost()\n const port = await this.server.getPort()\n\n this.client = createClient({\n socket: {\n host,\n port,\n noDelay: true,\n keepAlive: true,\n reconnectStrategy: (retries: number) => {\n if (retries > 10) {\n return new Error('Redis connection retry limit exceeded')\n }\n return Math.min(retries * 100, 3000)\n },\n connectTimeout: 10000,\n },\n })\n\n this.client.on('error', (err: Error) => {\n if (err.message.includes('ECONNRESET') || err.message.includes('ECONNREFUSED')) {\n return\n }\n console.error('[Redis Memory Server] Client error:', err)\n })\n\n await this.client.connect()\n\n this.running = true\n this.registerCleanupHandlers()\n console.log(`[Redis Memory Server] Started on ${host}:${port}`)\n\n return this.client\n } catch (error) {\n console.error('[Redis Memory Server] Failed to start:', error)\n throw error\n }\n }\n\n async stop(): Promise<void> {\n if (this.client && this.running) {\n try {\n if (this.client.isOpen) {\n await this.client.quit().catch()\n }\n this.client = null\n } catch (error) {}\n }\n\n if (this.server && this.running) {\n try {\n await this.server.stop()\n this.running = false\n } catch (error) {\n console.error('[Redis Memory Server] Error stopping:', error)\n } finally {\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\nconst manager = new RedisMemoryManager()\n\nexport const instanceRedisMemoryServer = (baseDir: string, autoStart: boolean = true): Promise<RedisClientType> =>\n manager.start(baseDir, autoStart)\n\nexport const stopRedisMemoryServer = (): Promise<void> => manager.stop()\n"],"mappings":";;;;;AAUA,IAAM,qBAAN,MAAyB;;gBACoB;gBACF;iBACvB;mCACkB;;CAEpC,AAAQ,0BAAgC;AACtC,MAAI,KAAK,0BAA2B;AAEpC,UAAQ,GAAG,cAAc;AACvB,OAAI,KAAK,QAAQ,UAAU,KAAK,QAC9B,MAAK,OAAO,MAAM,CAAC,OAAO,UAAmB;AAC3C,YAAQ,MAAM,uDAAuD,MAAM;KAC3E;AAEJ,OAAI,KAAK,UAAU,KAAK,QACtB,MAAK,OAAO,MAAM,CAAC,OAAO,UAAmB;AAC3C,YAAQ,MAAM,iDAAiD,MAAM;KACrE;IAEJ;AAEF,UAAQ,GAAG,WAAW,YAAY;AAChC,SAAM,KAAK,MAAM;IACjB;AAEF,UAAQ,GAAG,UAAU,YAAY;AAC/B,SAAM,KAAK,MAAM;IACjB;AAEF,OAAK,4BAA4B;;CAGnC,MAAM,MAAM,SAAiB,WAA8C;AACzE,MAAI,KAAK,UAAU,KAAK,QACtB,QAAO,KAAK;AAGd,MAAI;AACF,aAAU,SAAS,EAAE,WAAW,MAAM,CAAC;GAEvC,MAAMA,WAAqC;IACzC,IAAI,QAAQ,IAAI,oBAAoB;IACpC,MAAM;KAAC;KAAgB;KAAO;KAAU;KAAS;KAAU;KAAU;KAAU;KAAU;KAAS;KAAQ;IAC3G;AAED,OAAI,QAAQ,IAAI,iBACd,UAAS,OAAO,SAAS,QAAQ,IAAI,oBAAoB,OAAO;AAGlE,QAAK,SAAS,IAAI,kBAAkB;IAClC;IACA;IACD,CAAC;GAEF,MAAM,OAAO,MAAM,KAAK,OAAO,SAAS;GACxC,MAAM,OAAO,MAAM,KAAK,OAAO,SAAS;AAExC,QAAK,SAAS,aAAa,EACzB,QAAQ;IACN;IACA;IACA,SAAS;IACT,WAAW;IACX,oBAAoB,YAAoB;AACtC,SAAI,UAAU,GACZ,wBAAO,IAAI,MAAM,wCAAwC;AAE3D,YAAO,KAAK,IAAI,UAAU,KAAK,IAAK;;IAEtC,gBAAgB;IACjB,EACF,CAAC;AAEF,QAAK,OAAO,GAAG,UAAU,QAAe;AACtC,QAAI,IAAI,QAAQ,SAAS,aAAa,IAAI,IAAI,QAAQ,SAAS,eAAe,CAC5E;AAEF,YAAQ,MAAM,uCAAuC,IAAI;KACzD;AAEF,SAAM,KAAK,OAAO,SAAS;AAE3B,QAAK,UAAU;AACf,QAAK,yBAAyB;AAC9B,WAAQ,IAAI,oCAAoC,KAAK,GAAG,OAAO;AAE/D,UAAO,KAAK;WACL,OAAO;AACd,WAAQ,MAAM,0CAA0C,MAAM;AAC9D,SAAM;;;CAIV,MAAM,OAAsB;AAC1B,MAAI,KAAK,UAAU,KAAK,QACtB,KAAI;AACF,OAAI,KAAK,OAAO,OACd,OAAM,KAAK,OAAO,MAAM,CAAC,OAAO;AAElC,QAAK,SAAS;WACP,OAAO;AAGlB,MAAI,KAAK,UAAU,KAAK,QACtB,KAAI;AACF,SAAM,KAAK,OAAO,MAAM;AACxB,QAAK,UAAU;WACR,OAAO;AACd,WAAQ,MAAM,yCAAyC,MAAM;YACrD;AACR,QAAK,SAAS;;;CAKpB,YAAqB;AACnB,SAAO,KAAK;;CAGd,YAAoC;AAClC,SAAO,KAAK;;;AAIhB,MAAM,UAAU,IAAI,oBAAoB;AAExC,MAAa,6BAA6B,SAAiB,YAAqB,SAC9E,QAAQ,MAAM,SAAS,UAAU;AAEnC,MAAa,8BAA6C,QAAQ,MAAM"}
|