motia 0.0.28 → 0.0.30
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/LICENSE +21 -0
- package/dist/src/builder/build-printer.js +44 -0
- package/dist/src/builder/build.js +170 -0
- package/dist/src/builder/cli-output-manager.js +28 -0
- package/dist/src/builder/python-builder.py +31 -0
- package/dist/src/cli.js +14 -10
- package/dist/src/create/templates/default/steps/api.step.txt +1 -1
- package/dist/src/create/templates/default/steps/one.step.txt +1 -1
- package/dist/src/create-step/templates/cron/template.javascript.txt +1 -1
- package/dist/src/create-step/templates/cron/template.python.txt +1 -1
- package/dist/src/create-step/templates/cron/template.ruby.txt +1 -1
- package/dist/src/create-step/templates/cron/template.type.txt +1 -1
- package/dist/src/create-step/templates/cron/template.typescript.txt +1 -1
- package/dist/src/create-step/templates/event/template.javascript.txt +1 -1
- package/dist/src/create-step/templates/event/template.python.txt +1 -1
- package/dist/src/create-step/templates/event/template.ruby.txt +1 -1
- package/dist/src/create-step/templates/event/template.typescript.txt +1 -1
- package/dist/src/dev/workflow-config-endpoints.js +39 -0
- package/dist/src/dev.js +6 -2
- package/dist/src/generate-locked-data.js +4 -3
- package/package.json +8 -4
- package/scripts/move-python.sh +1 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Motia
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.BuildPrinter = void 0;
|
|
7
|
+
const cli_output_manager_1 = require("./cli-output-manager");
|
|
8
|
+
const colors_1 = __importDefault(require("colors"));
|
|
9
|
+
const printer_1 = require("@motiadev/core/dist/src/printer");
|
|
10
|
+
const building = colors_1.default.yellow('➜ [BUILDING]');
|
|
11
|
+
const built = colors_1.default.green('✓ [BUILT]');
|
|
12
|
+
const failed = colors_1.default.red('✘ [FAILED]');
|
|
13
|
+
const skipped = colors_1.default.gray('- [SKIPPED]');
|
|
14
|
+
class BuildPrinter {
|
|
15
|
+
constructor() {
|
|
16
|
+
this.printer = new printer_1.Printer(process.cwd());
|
|
17
|
+
this.output = new cli_output_manager_1.CLIOutputManager();
|
|
18
|
+
}
|
|
19
|
+
printStepBuilding(step) {
|
|
20
|
+
const stepType = this.printer.getStepType(step);
|
|
21
|
+
const stepPath = this.printer.getStepPath(step);
|
|
22
|
+
const stepTag = this.printer.stepTag;
|
|
23
|
+
this.output.logStep(step.filePath, `${building} ${stepTag} ${stepType} ${stepPath}`);
|
|
24
|
+
}
|
|
25
|
+
printStepBuilt(step) {
|
|
26
|
+
const stepType = this.printer.getStepType(step);
|
|
27
|
+
const stepPath = this.printer.getStepPath(step);
|
|
28
|
+
const stepTag = this.printer.stepTag;
|
|
29
|
+
this.output.updateStep(step.filePath, `${built} ${stepTag} ${stepType} ${stepPath}`);
|
|
30
|
+
}
|
|
31
|
+
printStepFailed(step, error) {
|
|
32
|
+
const stepType = this.printer.getStepType(step);
|
|
33
|
+
const stepPath = this.printer.getStepPath(step);
|
|
34
|
+
const stepTag = this.printer.stepTag;
|
|
35
|
+
this.output.updateStep(step.filePath, `${failed} ${stepTag} ${stepType} ${stepPath} ${error.message}`);
|
|
36
|
+
}
|
|
37
|
+
printStepSkipped(step, reason) {
|
|
38
|
+
const stepType = this.printer.getStepType(step);
|
|
39
|
+
const stepPath = this.printer.getStepPath(step);
|
|
40
|
+
const stepTag = this.printer.stepTag;
|
|
41
|
+
this.output.logStep(step.filePath, `${skipped} ${stepTag} ${stepType} ${stepPath} ${reason}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
exports.BuildPrinter = BuildPrinter;
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.build = void 0;
|
|
40
|
+
const locked_data_1 = require("@motiadev/core/dist/src/locked-data");
|
|
41
|
+
const printer_1 = require("@motiadev/core/dist/src/printer");
|
|
42
|
+
const colors_1 = __importDefault(require("colors"));
|
|
43
|
+
const esbuild = __importStar(require("esbuild"));
|
|
44
|
+
const fs_1 = __importDefault(require("fs"));
|
|
45
|
+
const path_1 = __importDefault(require("path"));
|
|
46
|
+
const generate_locked_data_1 = require("../generate-locked-data");
|
|
47
|
+
const build_printer_1 = require("./build-printer");
|
|
48
|
+
const child_process_1 = require("child_process");
|
|
49
|
+
const archiver_1 = __importDefault(require("archiver"));
|
|
50
|
+
class Builder {
|
|
51
|
+
constructor(projectDir) {
|
|
52
|
+
this.projectDir = projectDir;
|
|
53
|
+
this.distDir = path_1.default.join(projectDir, 'dist');
|
|
54
|
+
this.stepsConfig = {};
|
|
55
|
+
this.printer = new build_printer_1.BuildPrinter();
|
|
56
|
+
}
|
|
57
|
+
registerStep(args) {
|
|
58
|
+
this.stepsConfig[args.bundlePath] = {
|
|
59
|
+
type: args.type,
|
|
60
|
+
entrypointPath: args.entrypointPath,
|
|
61
|
+
config: args.step.config,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const buildPython = async (step, builder) => {
|
|
66
|
+
const archive = (0, archiver_1.default)('zip', { zlib: { level: 9 } });
|
|
67
|
+
const entrypointPath = step.filePath.replace(builder.projectDir, '');
|
|
68
|
+
const bundlePath = path_1.default.join('python', entrypointPath.replace(/(.*)\.py$/, '$1.zip'));
|
|
69
|
+
const outfile = path_1.default.join(builder.distDir, bundlePath);
|
|
70
|
+
return new Promise((resolve, reject) => {
|
|
71
|
+
try {
|
|
72
|
+
// Ensure output directory exists
|
|
73
|
+
fs_1.default.mkdirSync(path_1.default.dirname(outfile), { recursive: true });
|
|
74
|
+
builder.printer.printStepBuilding(step);
|
|
75
|
+
const type = 'python';
|
|
76
|
+
const child = (0, child_process_1.spawn)('python', [path_1.default.join(__dirname, 'python-builder.py'), step.filePath], {
|
|
77
|
+
cwd: builder.projectDir,
|
|
78
|
+
stdio: [undefined, undefined, undefined, 'ipc'],
|
|
79
|
+
});
|
|
80
|
+
builder.registerStep({ entrypointPath, bundlePath, step, type });
|
|
81
|
+
archive.pipe(fs_1.default.createWriteStream(outfile));
|
|
82
|
+
child.on('message', (message) => {
|
|
83
|
+
message.forEach((file) => {
|
|
84
|
+
archive.append(fs_1.default.createReadStream(path_1.default.join(builder.projectDir, file)), { name: file });
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
child.on('close', (code) => {
|
|
88
|
+
if (code !== 0) {
|
|
89
|
+
builder.printer.printStepFailed(step, new Error('Python builder failed'));
|
|
90
|
+
return reject(new Error('Python builder failed'));
|
|
91
|
+
}
|
|
92
|
+
builder.printer.printStepBuilt(step);
|
|
93
|
+
archive.finalize();
|
|
94
|
+
});
|
|
95
|
+
archive.on('close', () => resolve());
|
|
96
|
+
archive.on('error', (err) => reject(err));
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
builder.printer.printStepFailed(step, err);
|
|
100
|
+
reject(err);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
};
|
|
104
|
+
const buildNode = async (step, builder) => {
|
|
105
|
+
const relativeFilePath = step.filePath.replace(builder.projectDir, '');
|
|
106
|
+
const entrypointPath = relativeFilePath.replace(/(.*)\.(ts|js)$/, '$1.js');
|
|
107
|
+
const entrypointMapPath = entrypointPath.replace(/(.*)\.js$/, '$1.js.map');
|
|
108
|
+
const bundlePath = path_1.default.join('node', entrypointPath.replace(/(.*)\.js$/, '$1.zip'));
|
|
109
|
+
const outputJsFile = path_1.default.join(builder.distDir, 'node', entrypointPath);
|
|
110
|
+
const outputMapFile = path_1.default.join(builder.distDir, 'node', entrypointMapPath);
|
|
111
|
+
const type = 'node';
|
|
112
|
+
builder.registerStep({ entrypointPath, bundlePath, step, type });
|
|
113
|
+
builder.printer.printStepBuilding(step);
|
|
114
|
+
try {
|
|
115
|
+
await esbuild.build({
|
|
116
|
+
entryPoints: [step.filePath],
|
|
117
|
+
bundle: true,
|
|
118
|
+
sourcemap: true,
|
|
119
|
+
outfile: outputJsFile,
|
|
120
|
+
platform: 'node',
|
|
121
|
+
});
|
|
122
|
+
await new Promise((resolve, reject) => {
|
|
123
|
+
const archive = (0, archiver_1.default)('zip', { zlib: { level: 9 } });
|
|
124
|
+
archive.pipe(fs_1.default.createWriteStream(path_1.default.join(builder.distDir, bundlePath)));
|
|
125
|
+
archive.append(fs_1.default.createReadStream(outputJsFile), { name: entrypointPath });
|
|
126
|
+
archive.append(fs_1.default.createReadStream(outputMapFile), { name: entrypointMapPath });
|
|
127
|
+
archive.finalize();
|
|
128
|
+
archive.on('close', () => {
|
|
129
|
+
fs_1.default.unlinkSync(outputJsFile);
|
|
130
|
+
fs_1.default.unlinkSync(outputMapFile);
|
|
131
|
+
resolve();
|
|
132
|
+
});
|
|
133
|
+
archive.on('error', (err) => reject(err));
|
|
134
|
+
});
|
|
135
|
+
builder.printer.printStepBuilt(step);
|
|
136
|
+
}
|
|
137
|
+
catch (err) {
|
|
138
|
+
builder.printer.printStepFailed(step, err);
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
const build = async () => {
|
|
142
|
+
const projectDir = process.cwd();
|
|
143
|
+
const builder = new Builder(projectDir);
|
|
144
|
+
const stepsConfigPath = path_1.default.join(projectDir, 'dist', 'motia.steps.json');
|
|
145
|
+
const lockedData = new locked_data_1.LockedData(projectDir);
|
|
146
|
+
const promises = [];
|
|
147
|
+
const distDir = path_1.default.join(projectDir, 'dist');
|
|
148
|
+
lockedData.printer = new printer_1.NoPrinter(projectDir); // let's make it not print anything
|
|
149
|
+
fs_1.default.rmSync(distDir, { recursive: true, force: true });
|
|
150
|
+
fs_1.default.mkdirSync(distDir, { recursive: true });
|
|
151
|
+
lockedData.onStep('step-created', (step) => {
|
|
152
|
+
if (step.config.type === 'noop') {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
else if (step.filePath.endsWith('.ts') || step.filePath.endsWith('.js')) {
|
|
156
|
+
return promises.push(buildNode(step, builder));
|
|
157
|
+
}
|
|
158
|
+
else if (step.filePath.endsWith('.py')) {
|
|
159
|
+
return promises.push(buildPython(step, builder));
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
return builder.printer.printStepSkipped(step, 'File not supported');
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
await (0, generate_locked_data_1.collectFlows)(path_1.default.join(projectDir, 'steps'), lockedData);
|
|
166
|
+
await Promise.all(promises);
|
|
167
|
+
fs_1.default.writeFileSync(stepsConfigPath, JSON.stringify(builder.stepsConfig, null, 2));
|
|
168
|
+
console.log(colors_1.default.green('✓ [SUCCESS] '), 'Build completed');
|
|
169
|
+
};
|
|
170
|
+
exports.build = build;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.CLIOutputManager = void 0;
|
|
7
|
+
const readline_1 = __importDefault(require("readline"));
|
|
8
|
+
class CLIOutputManager {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.lines = new Map(); // Track line positions
|
|
11
|
+
this.lineCount = 0;
|
|
12
|
+
}
|
|
13
|
+
logStep(id, message) {
|
|
14
|
+
this.lines.set(id, this.lineCount);
|
|
15
|
+
process.stdout.write(`${message}\n`);
|
|
16
|
+
this.lineCount++;
|
|
17
|
+
}
|
|
18
|
+
updateStep(id, newMessage) {
|
|
19
|
+
const lineIndex = this.lines.get(id);
|
|
20
|
+
if (lineIndex === undefined)
|
|
21
|
+
return;
|
|
22
|
+
readline_1.default.moveCursor(process.stdout, 0, -(this.lineCount - lineIndex));
|
|
23
|
+
readline_1.default.clearLine(process.stdout, 0);
|
|
24
|
+
process.stdout.write(`${newMessage}\n`);
|
|
25
|
+
readline_1.default.moveCursor(process.stdout, 0, this.lineCount - lineIndex - 1);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.CLIOutputManager = CLIOutputManager;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import json
|
|
4
|
+
import modulegraph.modulegraph
|
|
5
|
+
|
|
6
|
+
NODEIPCFD = int(os.environ["NODE_CHANNEL_FD"])
|
|
7
|
+
|
|
8
|
+
def trace_imports(entry_file):
|
|
9
|
+
module_dir = os.path.dirname(os.path.abspath(entry_file))
|
|
10
|
+
"""Find all imported Python files starting from an entry file."""
|
|
11
|
+
# Add both the module directory and current Python path to search paths
|
|
12
|
+
paths = [module_dir] + sys.path
|
|
13
|
+
graph = modulegraph.modulegraph.ModuleGraph(paths)
|
|
14
|
+
graph.run_script(entry_file)
|
|
15
|
+
|
|
16
|
+
files = set()
|
|
17
|
+
cwd = os.getcwd()
|
|
18
|
+
for mod in graph.nodes():
|
|
19
|
+
if mod.filename and mod.filename.endswith(".py"):
|
|
20
|
+
abs_path = os.path.abspath(mod.filename)
|
|
21
|
+
if abs_path.startswith(cwd):
|
|
22
|
+
rel_path = os.path.relpath(abs_path, cwd)
|
|
23
|
+
files.add(rel_path)
|
|
24
|
+
|
|
25
|
+
return list(files)
|
|
26
|
+
|
|
27
|
+
if __name__ == "__main__":
|
|
28
|
+
entry_file = sys.argv[1] # Get entrypoint from CLI args
|
|
29
|
+
files = trace_imports(entry_file)
|
|
30
|
+
bytes_message = (json.dumps(files) + '\n').encode('utf-8')
|
|
31
|
+
os.write(NODEIPCFD, bytes_message)
|
package/dist/src/cli.js
CHANGED
|
@@ -4,13 +4,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
5
|
};
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
/* eslint-disable @typescript-eslint/no-require-imports */
|
|
7
8
|
const commander_1 = require("commander");
|
|
8
9
|
const path_1 = __importDefault(require("path"));
|
|
9
10
|
const fs_1 = __importDefault(require("fs"));
|
|
10
11
|
const defaultPort = 3000;
|
|
11
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
12
12
|
require('dotenv/config');
|
|
13
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
14
13
|
require('ts-node').register({
|
|
15
14
|
transpileOnly: true,
|
|
16
15
|
compilerOptions: { module: 'commonjs' },
|
|
@@ -21,7 +20,6 @@ commander_1.program
|
|
|
21
20
|
.option('-n, --name <project name>', 'The name for your project, used to create a directory, use ./ or . to create it under the existing directory')
|
|
22
21
|
.option('-t, --template <template name>', 'The motia template name to use for your project')
|
|
23
22
|
.action(async (arg) => {
|
|
24
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
25
23
|
const { create } = require('./create');
|
|
26
24
|
await create({
|
|
27
25
|
projectName: arg.project ?? '.',
|
|
@@ -32,7 +30,6 @@ commander_1.program
|
|
|
32
30
|
.command('templates')
|
|
33
31
|
.description('Prints the list of available templates')
|
|
34
32
|
.action(async () => {
|
|
35
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
36
33
|
const { templates } = require('./create/templates');
|
|
37
34
|
console.log(`📝 Available templates: \n\n ${Object.keys(templates).join('\n')}`);
|
|
38
35
|
});
|
|
@@ -40,6 +37,7 @@ commander_1.program
|
|
|
40
37
|
.command('dev')
|
|
41
38
|
.description('Start the development server')
|
|
42
39
|
.option('-p, --port <port>', 'The port to run the server on', `${defaultPort}`)
|
|
40
|
+
.option('-v, --verbose', 'Enable verbose logging')
|
|
43
41
|
.option('-d, --debug', 'Enable debug logging')
|
|
44
42
|
.action(async (arg) => {
|
|
45
43
|
if (arg.debug) {
|
|
@@ -47,19 +45,25 @@ commander_1.program
|
|
|
47
45
|
process.env.LOG_LEVEL = 'debug';
|
|
48
46
|
}
|
|
49
47
|
const port = arg.port ? parseInt(arg.port) : defaultPort;
|
|
50
|
-
const { dev } = require('./dev');
|
|
51
|
-
await dev(port);
|
|
48
|
+
const { dev } = require('./dev');
|
|
49
|
+
await dev(port, arg.verbose);
|
|
50
|
+
});
|
|
51
|
+
commander_1.program
|
|
52
|
+
.command('build')
|
|
53
|
+
.description('Build the project')
|
|
54
|
+
.action(async () => {
|
|
55
|
+
const { build } = require('./builder/build');
|
|
56
|
+
await build();
|
|
52
57
|
});
|
|
53
58
|
commander_1.program
|
|
54
59
|
.command('get-config')
|
|
55
60
|
.description('Get the generated config for your project')
|
|
56
61
|
.option('-o, --output <port>', 'Path to write the generated config')
|
|
57
62
|
.action(async (arg) => {
|
|
58
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
59
63
|
const { generateLockedData } = require('./src/generate/locked-data');
|
|
60
64
|
const lockedData = await generateLockedData(path_1.default.join(process.cwd()));
|
|
61
65
|
if (arg.output) {
|
|
62
|
-
const fs = require('fs');
|
|
66
|
+
const fs = require('fs');
|
|
63
67
|
fs.writeFileSync(path_1.default.join(arg.output, '.motia.generated.json'), JSON.stringify(lockedData, null, 2));
|
|
64
68
|
console.log(`📄 Wrote locked data to ${arg.output}`);
|
|
65
69
|
return;
|
|
@@ -101,7 +105,7 @@ generate
|
|
|
101
105
|
.description('Create a new step with interactive prompts')
|
|
102
106
|
.option('-d, --dir <step file path>', 'The path relative to the steps directory, used to create the step file')
|
|
103
107
|
.action(async (arg) => {
|
|
104
|
-
const { createStep } = require('./create-step');
|
|
108
|
+
const { createStep } = require('./create-step');
|
|
105
109
|
await createStep({
|
|
106
110
|
stepFilePath: arg.dir,
|
|
107
111
|
});
|
|
@@ -117,7 +121,7 @@ state
|
|
|
117
121
|
console.error('Error: State file not found at', statePath);
|
|
118
122
|
process.exit(1);
|
|
119
123
|
}
|
|
120
|
-
const state = require(statePath);
|
|
124
|
+
const state = require(statePath);
|
|
121
125
|
console.log(JSON.stringify(state, null, 2));
|
|
122
126
|
}
|
|
123
127
|
catch (error) {
|
|
@@ -23,7 +23,7 @@ export const handler: StepHandler<typeof config> = async (input, { traceId, logg
|
|
|
23
23
|
await state.set<any>(traceId, 'test', message)
|
|
24
24
|
|
|
25
25
|
await emit({
|
|
26
|
-
|
|
26
|
+
topic: 'check-state-change',
|
|
27
27
|
data: {key: 'test', expected: message}
|
|
28
28
|
})
|
|
29
29
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.workflowConfigEndpoints = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const workflowConfigEndpoints = (server, baseDir) => {
|
|
10
|
+
const { app } = server;
|
|
11
|
+
app.post('/flows/:id/config', async (req, res) => {
|
|
12
|
+
const { id } = req.params;
|
|
13
|
+
const config = req.body;
|
|
14
|
+
const configDir = path_1.default.join(baseDir, '.motia', 'flow-config');
|
|
15
|
+
const configPath = path_1.default.join(configDir, `${id}.workflow.config.json`);
|
|
16
|
+
try {
|
|
17
|
+
fs_1.default.mkdirSync(configDir, { recursive: true });
|
|
18
|
+
fs_1.default.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
19
|
+
res.status(200).send({ message: 'Workflow config saved' });
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
console.error('Error saving workflow config:', error);
|
|
23
|
+
res.status(500).json({ error: 'Failed to save workflow config' });
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
app.get('/flows/:id/config', async (req, res) => {
|
|
27
|
+
const { id } = req.params;
|
|
28
|
+
const configPath = path_1.default.join(baseDir, '.motia', 'flow-config', `${id}.workflow.config.json`);
|
|
29
|
+
try {
|
|
30
|
+
const config = fs_1.default.existsSync(configPath) ? JSON.parse(fs_1.default.readFileSync(configPath, 'utf8')) : {};
|
|
31
|
+
res.status(200).send(config);
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
console.error('Error reading workflow config:', error);
|
|
35
|
+
res.status(200).send({});
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
exports.workflowConfigEndpoints = workflowConfigEndpoints;
|
package/dist/src/dev.js
CHANGED
|
@@ -4,17 +4,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.dev = void 0;
|
|
7
|
+
// packages/snap/src/dev.ts
|
|
7
8
|
const core_1 = require("@motiadev/core");
|
|
8
9
|
const generate_locked_data_1 = require("./generate-locked-data");
|
|
9
10
|
const path_1 = __importDefault(require("path"));
|
|
10
11
|
const dev_watchers_1 = require("./dev-watchers");
|
|
11
12
|
const state_endpoints_1 = require("./dev/state-endpoints");
|
|
13
|
+
const workflow_config_endpoints_1 = require("./dev/workflow-config-endpoints");
|
|
12
14
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
13
15
|
require('ts-node').register({
|
|
14
16
|
transpileOnly: true,
|
|
15
17
|
compilerOptions: { module: 'commonjs' },
|
|
16
18
|
});
|
|
17
|
-
const dev = async (port) => {
|
|
19
|
+
const dev = async (port, isVerbose) => {
|
|
18
20
|
const baseDir = process.cwd();
|
|
19
21
|
const lockedData = await (0, generate_locked_data_1.generateLockedData)(baseDir);
|
|
20
22
|
const eventManager = (0, core_1.createEventManager)();
|
|
@@ -23,11 +25,13 @@ const dev = async (port) => {
|
|
|
23
25
|
filePath: path_1.default.join(baseDir, '.motia'),
|
|
24
26
|
});
|
|
25
27
|
await state.init();
|
|
26
|
-
const
|
|
28
|
+
const config = { isVerbose };
|
|
29
|
+
const motiaServer = await (0, core_1.createServer)(lockedData, eventManager, state, config);
|
|
27
30
|
const motiaEventManager = (0, core_1.createStepHandlers)(lockedData, eventManager, state);
|
|
28
31
|
const watcher = (0, dev_watchers_1.createDevWatchers)(lockedData, motiaServer, motiaEventManager, motiaServer.cronManager);
|
|
29
32
|
watcher.init();
|
|
30
33
|
(0, state_endpoints_1.stateEndpoints)(motiaServer, state);
|
|
34
|
+
(0, workflow_config_endpoints_1.workflowConfigEndpoints)(motiaServer, baseDir);
|
|
31
35
|
motiaServer.server.listen(port);
|
|
32
36
|
console.log('🚀 Server ready and listening on port', port);
|
|
33
37
|
console.log(`🔗 Open http://localhost:${port}/ to open workbench 🛠️`);
|
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.generateLockedData = void 0;
|
|
6
|
+
exports.generateLockedData = exports.collectFlows = void 0;
|
|
7
7
|
const core_1 = require("@motiadev/core");
|
|
8
8
|
const crypto_1 = require("crypto");
|
|
9
9
|
const fs_1 = __importDefault(require("fs"));
|
|
@@ -16,7 +16,7 @@ const collectFlows = async (baseDir, lockedData) => {
|
|
|
16
16
|
for (const item of folderItems) {
|
|
17
17
|
const filePath = path_1.default.join(baseDir, item.name);
|
|
18
18
|
if (item.isDirectory()) {
|
|
19
|
-
steps = steps.concat(await collectFlows(filePath, lockedData));
|
|
19
|
+
steps = steps.concat(await (0, exports.collectFlows)(filePath, lockedData));
|
|
20
20
|
}
|
|
21
21
|
else if (item.name.match(/\.step\.(ts|js|py|rb)$/)) {
|
|
22
22
|
const config = await (0, core_1.getStepConfig)(filePath);
|
|
@@ -29,6 +29,7 @@ const collectFlows = async (baseDir, lockedData) => {
|
|
|
29
29
|
}
|
|
30
30
|
return steps;
|
|
31
31
|
};
|
|
32
|
+
exports.collectFlows = collectFlows;
|
|
32
33
|
const generateLockedData = async (projectDir) => {
|
|
33
34
|
try {
|
|
34
35
|
/*
|
|
@@ -36,7 +37,7 @@ const generateLockedData = async (projectDir) => {
|
|
|
36
37
|
* but we might want to remove this and scan the entire current directory
|
|
37
38
|
*/
|
|
38
39
|
const lockedData = new core_1.LockedData(projectDir);
|
|
39
|
-
await collectFlows(path_1.default.join(projectDir, 'steps'), lockedData);
|
|
40
|
+
await (0, exports.collectFlows)(path_1.default.join(projectDir, 'steps'), lockedData);
|
|
40
41
|
return lockedData;
|
|
41
42
|
}
|
|
42
43
|
catch (error) {
|
package/package.json
CHANGED
|
@@ -1,23 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "motia",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.30",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"bin": {
|
|
6
6
|
"motia": "dist/src/cli.js"
|
|
7
7
|
},
|
|
8
8
|
"dependencies": {
|
|
9
|
+
"archiver": "^7.0.1",
|
|
9
10
|
"chokidar": "^4.0.3",
|
|
10
11
|
"colors": "^1.4.0",
|
|
11
12
|
"commander": "^13.0.0",
|
|
12
13
|
"dotenv": "^16.4.7",
|
|
14
|
+
"esbuild": "^0.25.0",
|
|
13
15
|
"figlet": "^1.8.0",
|
|
14
16
|
"inquirer": "^12.4.1",
|
|
15
17
|
"ts-node": "^10.9.2",
|
|
16
18
|
"yaml": "^2.7.0",
|
|
17
|
-
"@motiadev/core": "0.0.
|
|
18
|
-
"@motiadev/workbench": "0.0.
|
|
19
|
+
"@motiadev/core": "0.0.30",
|
|
20
|
+
"@motiadev/workbench": "0.0.30"
|
|
19
21
|
},
|
|
20
22
|
"devDependencies": {
|
|
23
|
+
"@types/archiver": "^6.0.3",
|
|
21
24
|
"@types/figlet": "^1.7.0",
|
|
22
25
|
"@types/jest": "^29.5.14",
|
|
23
26
|
"jest": "^29.7.0",
|
|
@@ -26,7 +29,8 @@
|
|
|
26
29
|
},
|
|
27
30
|
"scripts": {
|
|
28
31
|
"move:templates": "sh scripts/move-templates.sh",
|
|
29
|
-
"
|
|
32
|
+
"move:python": "sh scripts/move-python.sh",
|
|
33
|
+
"build": "rm -rf dist && tsc && pnpm run move:templates && pnpm run move:python",
|
|
30
34
|
"lint": "eslint --config ../../eslint.config.js"
|
|
31
35
|
}
|
|
32
36
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
cp src/builder/python-builder.py dist/src/builder/python-builder.py
|