@motiadev/core 0.2.1-beta.65-2533 → 0.2.1-beta.67
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/index.d.ts +1 -0
- package/dist/index.js +6 -1
- package/dist/src/analytics/utils.d.ts +5 -0
- package/dist/src/analytics/utils.js +50 -0
- package/dist/src/analytics-endpoint.d.ts +2 -0
- package/dist/src/analytics-endpoint.js +30 -0
- package/dist/src/call-step-file.js +15 -0
- package/dist/src/server.js +8 -0
- package/dist/src/state/adapters/default-state-adapter.d.ts +2 -2
- package/dist/src/state/adapters/default-state-adapter.js +16 -4
- package/package.json +2 -1
package/dist/index.d.ts
CHANGED
|
@@ -12,3 +12,4 @@ export { StateAdapter } from './src/state/state-adapter';
|
|
|
12
12
|
export { createMermaidGenerator } from './src/mermaid-generator';
|
|
13
13
|
export { StateStream } from './src/state-stream';
|
|
14
14
|
export { StateStreamConfig, IStateStream } from './src/types-stream';
|
|
15
|
+
export { getProjectIdentifier, getUserIdentifier, isAnalyticsEnabled, trackEvent } from './src/analytics/utils';
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.StateStream = exports.createMermaidGenerator = exports.getStreamConfig = exports.getStepConfig = exports.LockedData = exports.isNoopStep = exports.isEventStep = exports.isCronStep = exports.isApiStep = exports.setupCronHandlers = exports.createStateAdapter = exports.Logger = exports.globalLogger = exports.createEventManager = exports.createStepHandlers = exports.createServer = void 0;
|
|
17
|
+
exports.trackEvent = exports.isAnalyticsEnabled = exports.getUserIdentifier = exports.getProjectIdentifier = exports.StateStream = exports.createMermaidGenerator = exports.getStreamConfig = exports.getStepConfig = exports.LockedData = exports.isNoopStep = exports.isEventStep = exports.isCronStep = exports.isApiStep = exports.setupCronHandlers = exports.createStateAdapter = exports.Logger = exports.globalLogger = exports.createEventManager = exports.createStepHandlers = exports.createServer = void 0;
|
|
18
18
|
__exportStar(require("./src/types"), exports);
|
|
19
19
|
var server_1 = require("./src/server");
|
|
20
20
|
Object.defineProperty(exports, "createServer", { enumerable: true, get: function () { return server_1.createServer; } });
|
|
@@ -43,3 +43,8 @@ var mermaid_generator_1 = require("./src/mermaid-generator");
|
|
|
43
43
|
Object.defineProperty(exports, "createMermaidGenerator", { enumerable: true, get: function () { return mermaid_generator_1.createMermaidGenerator; } });
|
|
44
44
|
var state_stream_1 = require("./src/state-stream");
|
|
45
45
|
Object.defineProperty(exports, "StateStream", { enumerable: true, get: function () { return state_stream_1.StateStream; } });
|
|
46
|
+
var utils_1 = require("./src/analytics/utils");
|
|
47
|
+
Object.defineProperty(exports, "getProjectIdentifier", { enumerable: true, get: function () { return utils_1.getProjectIdentifier; } });
|
|
48
|
+
Object.defineProperty(exports, "getUserIdentifier", { enumerable: true, get: function () { return utils_1.getUserIdentifier; } });
|
|
49
|
+
Object.defineProperty(exports, "isAnalyticsEnabled", { enumerable: true, get: function () { return utils_1.isAnalyticsEnabled; } });
|
|
50
|
+
Object.defineProperty(exports, "trackEvent", { enumerable: true, get: function () { return utils_1.trackEvent; } });
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const getProjectName: (baseDir: string) => string;
|
|
2
|
+
export declare const getUserIdentifier: () => string;
|
|
3
|
+
export declare const getProjectIdentifier: (baseDir: string) => string;
|
|
4
|
+
export declare const isAnalyticsEnabled: () => boolean;
|
|
5
|
+
export declare const trackEvent: (eventName: string, properties?: Record<string, any>) => void;
|
|
@@ -0,0 +1,50 @@
|
|
|
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.trackEvent = exports.isAnalyticsEnabled = exports.getProjectIdentifier = exports.getUserIdentifier = exports.getProjectName = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const os_1 = __importDefault(require("os"));
|
|
10
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
11
|
+
const analytics_node_1 = require("@amplitude/analytics-node");
|
|
12
|
+
const getProjectName = (baseDir) => {
|
|
13
|
+
const packageJsonPath = path_1.default.join(baseDir, 'package.json');
|
|
14
|
+
if (fs_1.default.existsSync(packageJsonPath)) {
|
|
15
|
+
const packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath, 'utf8'));
|
|
16
|
+
return packageJson.name || path_1.default.basename(baseDir);
|
|
17
|
+
}
|
|
18
|
+
return 'unknown';
|
|
19
|
+
};
|
|
20
|
+
exports.getProjectName = getProjectName;
|
|
21
|
+
const getUserIdentifier = () => {
|
|
22
|
+
const userInfo = `${os_1.default.userInfo().username}${os_1.default.hostname()}`;
|
|
23
|
+
return crypto_1.default.createHash('sha256').update(userInfo).digest('hex').substring(0, 16);
|
|
24
|
+
};
|
|
25
|
+
exports.getUserIdentifier = getUserIdentifier;
|
|
26
|
+
const getProjectIdentifier = (baseDir) => {
|
|
27
|
+
try {
|
|
28
|
+
return crypto_1.default.createHash('sha256').update((0, exports.getProjectName)(baseDir)).digest('hex').substring(0, 16);
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
return 'unknown';
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
exports.getProjectIdentifier = getProjectIdentifier;
|
|
35
|
+
const isAnalyticsEnabled = () => {
|
|
36
|
+
return process.env.MOTIA_ANALYTICS_DISABLED !== 'true';
|
|
37
|
+
};
|
|
38
|
+
exports.isAnalyticsEnabled = isAnalyticsEnabled;
|
|
39
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
40
|
+
const trackEvent = (eventName, properties = {}) => {
|
|
41
|
+
try {
|
|
42
|
+
(0, analytics_node_1.track)(eventName, properties, {
|
|
43
|
+
user_id: (0, exports.getUserIdentifier)() || 'unknown',
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
// Silently fail to not disrupt dev server
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
exports.trackEvent = trackEvent;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.analyticsEndpoint = void 0;
|
|
4
|
+
const utils_1 = require("./analytics/utils");
|
|
5
|
+
const analyticsEndpoint = (app, baseDir) => {
|
|
6
|
+
app.get('/motia/analytics/user', (req, res) => {
|
|
7
|
+
const analyticsEnabled = (0, utils_1.isAnalyticsEnabled)();
|
|
8
|
+
if (!analyticsEnabled) {
|
|
9
|
+
res.json({
|
|
10
|
+
userId: null,
|
|
11
|
+
projectId: null,
|
|
12
|
+
motiaVersion: null,
|
|
13
|
+
analyticsEnabled: false,
|
|
14
|
+
});
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
res.json({
|
|
18
|
+
userId: (0, utils_1.getUserIdentifier)(),
|
|
19
|
+
projectId: (0, utils_1.getProjectIdentifier)(baseDir),
|
|
20
|
+
motiaVersion: process.env.npm_package_dependencies_motia || 'unknown',
|
|
21
|
+
analyticsEnabled: true,
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
app.get('/motia/analytics/status', (req, res) => {
|
|
25
|
+
res.json({
|
|
26
|
+
analyticsEnabled: (0, utils_1.isAnalyticsEnabled)(),
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
exports.analyticsEndpoint = analyticsEndpoint;
|
|
@@ -7,6 +7,7 @@ exports.callStepFile = void 0;
|
|
|
7
7
|
const path_1 = __importDefault(require("path"));
|
|
8
8
|
const utils_1 = require("./utils");
|
|
9
9
|
const process_manager_1 = require("./process-communication/process-manager");
|
|
10
|
+
const utils_2 = require("./analytics/utils");
|
|
10
11
|
const getLanguageBasedRunner = (stepFilePath = '') => {
|
|
11
12
|
const isPython = stepFilePath.endsWith('.py');
|
|
12
13
|
const isRuby = stepFilePath.endsWith('.rb');
|
|
@@ -46,6 +47,7 @@ const callStepFile = (options) => {
|
|
|
46
47
|
logger,
|
|
47
48
|
context: 'StepExecution',
|
|
48
49
|
});
|
|
50
|
+
(0, utils_2.trackEvent)('step_execution_started', { language: command, type: step.config.type, streams: streams.length });
|
|
49
51
|
processManager
|
|
50
52
|
.spawn()
|
|
51
53
|
.then(() => {
|
|
@@ -88,6 +90,7 @@ const callStepFile = (options) => {
|
|
|
88
90
|
processManager.onProcessClose((code) => {
|
|
89
91
|
processManager.close();
|
|
90
92
|
if (code !== 0 && code !== null) {
|
|
93
|
+
(0, utils_2.trackEvent)('step_execution_error', { stepName: step.config.name, traceId, code });
|
|
91
94
|
reject(`Process exited with code ${code}`);
|
|
92
95
|
}
|
|
93
96
|
else {
|
|
@@ -98,6 +101,12 @@ const callStepFile = (options) => {
|
|
|
98
101
|
processManager.onProcessError((error) => {
|
|
99
102
|
processManager.close();
|
|
100
103
|
if (error.code === 'ENOENT') {
|
|
104
|
+
(0, utils_2.trackEvent)('step_execution_error', {
|
|
105
|
+
stepName: step.config.name,
|
|
106
|
+
traceId,
|
|
107
|
+
code: error.code,
|
|
108
|
+
message: error.message,
|
|
109
|
+
});
|
|
101
110
|
reject(`Executable ${command} not found`);
|
|
102
111
|
}
|
|
103
112
|
else {
|
|
@@ -106,6 +115,12 @@ const callStepFile = (options) => {
|
|
|
106
115
|
});
|
|
107
116
|
})
|
|
108
117
|
.catch((error) => {
|
|
118
|
+
(0, utils_2.trackEvent)('step_execution_error', {
|
|
119
|
+
stepName: step.config.name,
|
|
120
|
+
traceId,
|
|
121
|
+
code: error.code,
|
|
122
|
+
message: error.message,
|
|
123
|
+
});
|
|
109
124
|
reject(`Failed to spawn process: ${error}`);
|
|
110
125
|
});
|
|
111
126
|
});
|
package/dist/src/server.js
CHANGED
|
@@ -20,6 +20,8 @@ const flows_config_endpoint_1 = require("./flows-config-endpoint");
|
|
|
20
20
|
const api_endpoints_1 = require("./streams/api-endpoints");
|
|
21
21
|
const socket_server_1 = require("./socket-server");
|
|
22
22
|
const logs_stream_1 = require("./streams/logs-stream");
|
|
23
|
+
const analytics_endpoint_1 = require("./analytics-endpoint");
|
|
24
|
+
const utils_1 = require("./analytics/utils");
|
|
23
25
|
const createServer = async (lockedData, eventManager, state, config) => {
|
|
24
26
|
const printer = lockedData.printer;
|
|
25
27
|
const app = (0, express_1.default)();
|
|
@@ -135,6 +137,11 @@ const createServer = async (lockedData, eventManager, state, config) => {
|
|
|
135
137
|
res.json(result.body);
|
|
136
138
|
}
|
|
137
139
|
catch (error) {
|
|
140
|
+
(0, utils_1.trackEvent)('api_call_error', {
|
|
141
|
+
stepName,
|
|
142
|
+
traceId,
|
|
143
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
144
|
+
});
|
|
138
145
|
logger.error('[API] Internal server error', { error });
|
|
139
146
|
console.log(error);
|
|
140
147
|
res.status(500).json({ error: 'Internal server error' });
|
|
@@ -182,6 +189,7 @@ const createServer = async (lockedData, eventManager, state, config) => {
|
|
|
182
189
|
(0, api_endpoints_1.apiEndpoints)(lockedData);
|
|
183
190
|
(0, flows_endpoint_1.flowsEndpoint)(lockedData, app);
|
|
184
191
|
(0, flows_config_endpoint_1.flowsConfigEndpoint)(app, process.cwd());
|
|
192
|
+
(0, analytics_endpoint_1.analyticsEndpoint)(app, process.cwd());
|
|
185
193
|
server.on('error', (error) => {
|
|
186
194
|
console.error('Server error:', error);
|
|
187
195
|
});
|
|
@@ -4,9 +4,9 @@ export type FileAdapterConfig = {
|
|
|
4
4
|
filePath: string;
|
|
5
5
|
};
|
|
6
6
|
export declare class FileStateAdapter implements StateAdapter {
|
|
7
|
-
private filePath;
|
|
7
|
+
private readonly filePath;
|
|
8
8
|
constructor(config: FileAdapterConfig);
|
|
9
|
-
init():
|
|
9
|
+
init(): void;
|
|
10
10
|
getGroup<T>(groupId: string): Promise<T[]>;
|
|
11
11
|
get<T>(traceId: string, key: string): Promise<T | null>;
|
|
12
12
|
set<T>(traceId: string, key: string, value: T): Promise<T>;
|
|
@@ -43,7 +43,7 @@ class FileStateAdapter {
|
|
|
43
43
|
constructor(config) {
|
|
44
44
|
this.filePath = path.join(config.filePath, 'motia.state.json');
|
|
45
45
|
}
|
|
46
|
-
|
|
46
|
+
init() {
|
|
47
47
|
const dir = this.filePath.replace('motia.state.json', '');
|
|
48
48
|
try {
|
|
49
49
|
fs_1.default.realpathSync(dir);
|
|
@@ -115,11 +115,23 @@ class FileStateAdapter {
|
|
|
115
115
|
return `${traceId}:${key}`;
|
|
116
116
|
}
|
|
117
117
|
_readFile() {
|
|
118
|
-
|
|
119
|
-
|
|
118
|
+
try {
|
|
119
|
+
const content = fs_1.default.readFileSync(this.filePath, 'utf-8');
|
|
120
|
+
return JSON.parse(content);
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
this.init();
|
|
124
|
+
return {};
|
|
125
|
+
}
|
|
120
126
|
}
|
|
121
127
|
_writeFile(data) {
|
|
122
|
-
|
|
128
|
+
try {
|
|
129
|
+
fs_1.default.writeFileSync(this.filePath, JSON.stringify(data, null, 2), 'utf-8');
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
this.init();
|
|
133
|
+
fs_1.default.writeFileSync(this.filePath, JSON.stringify(data, null, 2), 'utf-8');
|
|
134
|
+
}
|
|
123
135
|
}
|
|
124
136
|
}
|
|
125
137
|
exports.FileStateAdapter = FileStateAdapter;
|
package/package.json
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
"name": "@motiadev/core",
|
|
3
3
|
"description": "Core functionality for the Motia framework, providing the foundation for building event-driven workflows.",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
|
-
"version": "0.2.1-beta.
|
|
5
|
+
"version": "0.2.1-beta.67",
|
|
6
6
|
"dependencies": {
|
|
7
|
+
"@amplitude/analytics-node": "^1.3.8",
|
|
7
8
|
"body-parser": "^1.20.3",
|
|
8
9
|
"colors": "^1.4.0",
|
|
9
10
|
"cors": "^2.8.5",
|