motia 0.7.2-beta.135-685562 → 0.7.2-beta.135-014583
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/cjs/create/templates/generate.js +2 -2
- package/dist/cjs/create/templates/generate.ts +2 -2
- package/dist/cjs/create/templates/nodejs/.cursor/architecture/database/database-migration.mdc +49 -0
- package/dist/cjs/create/templates/nodejs/.cursor/architecture/database/database.mdc +83 -0
- package/dist/cjs/create/templates/nodejs/src/services/pet-store/create-order.ts.txt +15 -0
- package/dist/cjs/create/templates/nodejs/src/services/pet-store/create-pet.ts.txt +14 -0
- package/dist/cjs/create/templates/nodejs/src/services/pet-store/index.ts.txt +9 -0
- package/dist/{esm/create/templates/nodejs/steps → cjs/create/templates/nodejs/steps/petstore}/api.step.ts-features.json.txt +9 -9
- package/dist/{esm/create/templates/nodejs/steps → cjs/create/templates/nodejs/steps/petstore}/api.step.ts.txt +1 -2
- package/dist/{esm/create/templates/nodejs/steps → cjs/create/templates/nodejs/steps/petstore}/process-food-order.step.ts.txt +1 -1
- package/dist/cjs/cursor-rules/dot-files/.cursor/architecture/architecture.mdc +96 -0
- package/dist/cjs/cursor-rules/dot-files/.cursor/architecture/error-handling.mdc +122 -0
- package/dist/cjs/cursor-rules/dot-files/.cursor/index.mdc +26 -0
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/motia/api-steps.mdc +317 -0
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/motia/cron-steps.mdc +144 -0
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/motia/event-steps.mdc +157 -0
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/motia/middlewares.mdc +122 -0
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/motia/realtime-streaming.mdc +231 -0
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/motia/state-management.mdc +73 -0
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/motia/ui-steps.mdc +76 -0
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/motia/virtual-steps.mdc +172 -0
- package/dist/esm/create/templates/generate.js +2 -2
- package/dist/esm/create/templates/generate.ts +2 -2
- package/dist/esm/create/templates/nodejs/.cursor/architecture/database/database-migration.mdc +49 -0
- package/dist/esm/create/templates/nodejs/.cursor/architecture/database/database.mdc +83 -0
- package/dist/esm/create/templates/nodejs/src/services/pet-store/create-order.ts.txt +15 -0
- package/dist/esm/create/templates/nodejs/src/services/pet-store/create-pet.ts.txt +14 -0
- package/dist/esm/create/templates/nodejs/src/services/pet-store/index.ts.txt +9 -0
- package/dist/{cjs/create/templates/nodejs/steps → esm/create/templates/nodejs/steps/petstore}/api.step.ts-features.json.txt +9 -9
- package/dist/{cjs/create/templates/nodejs/steps → esm/create/templates/nodejs/steps/petstore}/api.step.ts.txt +1 -2
- package/dist/{cjs/create/templates/nodejs/steps → esm/create/templates/nodejs/steps/petstore}/process-food-order.step.ts.txt +1 -1
- package/dist/esm/cursor-rules/dot-files/.cursor/architecture/architecture.mdc +96 -0
- package/dist/esm/cursor-rules/dot-files/.cursor/architecture/error-handling.mdc +122 -0
- package/dist/esm/cursor-rules/dot-files/.cursor/index.mdc +26 -0
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/motia/api-steps.mdc +317 -0
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/motia/cron-steps.mdc +144 -0
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/motia/event-steps.mdc +157 -0
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/motia/middlewares.mdc +122 -0
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/motia/realtime-streaming.mdc +231 -0
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/motia/state-management.mdc +73 -0
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/motia/ui-steps.mdc +76 -0
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/motia/virtual-steps.mdc +172 -0
- package/package.json +4 -4
- package/dist/cjs/create/templates/nodejs/services/pet-store.ts.txt +0 -29
- package/dist/cjs/cursor-rules/dot-files/.claude/CLAUDE.md +0 -467
- package/dist/cjs/cursor-rules/dot-files/.claude/README.md +0 -97
- package/dist/cjs/cursor-rules/dot-files/.claude/agents/code-reviewer.md +0 -153
- package/dist/cjs/cursor-rules/dot-files/.claude/agents/debugger.md +0 -259
- package/dist/cjs/cursor-rules/dot-files/.claude/agents/test-runner.md +0 -268
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/add-authentication.md +0 -491
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/ai-ml-patterns.md +0 -748
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/authentication.md +0 -515
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/backend-types.md +0 -719
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/build-api.md +0 -407
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/claude-workflows.md +0 -1032
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/complete-backend.md +0 -345
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/create-api.md +0 -96
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/data-processing.md +0 -977
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/integrate-ai.md +0 -852
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/javascript-patterns.md +0 -678
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/multi-language-workflow.md +0 -756
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/multi-language.md +0 -141
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/process-background-jobs.md +0 -587
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/process-events.md +0 -89
- package/dist/cjs/cursor-rules/dot-files/.claude/hooks/pre-commit.sh +0 -84
- package/dist/cjs/cursor-rules/dot-files/.claude/settings.json +0 -37
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/ai-agent-patterns.mdc +0 -725
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/api-design-patterns.mdc +0 -740
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/api-steps.mdc +0 -230
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/architecture.mdc +0 -189
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/authentication-patterns.mdc +0 -620
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/background-job-patterns.mdc +0 -628
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/complete-application-patterns.mdc +0 -433
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/complete-backend-generator.mdc +0 -415
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/cron-steps.mdc +0 -257
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/event-steps.mdc +0 -504
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/instructions.mdc +0 -15
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/multi-language-workflows.mdc +0 -1059
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/noop-steps.mdc +0 -57
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/production-deployment.mdc +0 -668
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/realtime-streaming.mdc +0 -656
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/state-management.mdc +0 -371
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/steps.mdc +0 -373
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/testing.mdc +0 -329
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/typescript.mdc +0 -409
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/ui-steps.mdc +0 -429
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/workflow-patterns.mdc +0 -938
- package/dist/cjs/cursor-rules/dot-files/AGENTS.md +0 -397
- package/dist/cjs/cursor-rules/dot-files/README.md +0 -58
- package/dist/esm/create/templates/nodejs/services/pet-store.ts.txt +0 -29
- package/dist/esm/cursor-rules/dot-files/.claude/CLAUDE.md +0 -467
- package/dist/esm/cursor-rules/dot-files/.claude/README.md +0 -97
- package/dist/esm/cursor-rules/dot-files/.claude/agents/code-reviewer.md +0 -153
- package/dist/esm/cursor-rules/dot-files/.claude/agents/debugger.md +0 -259
- package/dist/esm/cursor-rules/dot-files/.claude/agents/test-runner.md +0 -268
- package/dist/esm/cursor-rules/dot-files/.claude/commands/add-authentication.md +0 -491
- package/dist/esm/cursor-rules/dot-files/.claude/commands/ai-ml-patterns.md +0 -748
- package/dist/esm/cursor-rules/dot-files/.claude/commands/authentication.md +0 -515
- package/dist/esm/cursor-rules/dot-files/.claude/commands/backend-types.md +0 -719
- package/dist/esm/cursor-rules/dot-files/.claude/commands/build-api.md +0 -407
- package/dist/esm/cursor-rules/dot-files/.claude/commands/claude-workflows.md +0 -1032
- package/dist/esm/cursor-rules/dot-files/.claude/commands/complete-backend.md +0 -345
- package/dist/esm/cursor-rules/dot-files/.claude/commands/create-api.md +0 -96
- package/dist/esm/cursor-rules/dot-files/.claude/commands/data-processing.md +0 -977
- package/dist/esm/cursor-rules/dot-files/.claude/commands/integrate-ai.md +0 -852
- package/dist/esm/cursor-rules/dot-files/.claude/commands/javascript-patterns.md +0 -678
- package/dist/esm/cursor-rules/dot-files/.claude/commands/multi-language-workflow.md +0 -756
- package/dist/esm/cursor-rules/dot-files/.claude/commands/multi-language.md +0 -141
- package/dist/esm/cursor-rules/dot-files/.claude/commands/process-background-jobs.md +0 -587
- package/dist/esm/cursor-rules/dot-files/.claude/commands/process-events.md +0 -89
- package/dist/esm/cursor-rules/dot-files/.claude/hooks/pre-commit.sh +0 -84
- package/dist/esm/cursor-rules/dot-files/.claude/settings.json +0 -37
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/ai-agent-patterns.mdc +0 -725
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/api-design-patterns.mdc +0 -740
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/api-steps.mdc +0 -230
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/architecture.mdc +0 -189
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/authentication-patterns.mdc +0 -620
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/background-job-patterns.mdc +0 -628
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/complete-application-patterns.mdc +0 -433
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/complete-backend-generator.mdc +0 -415
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/cron-steps.mdc +0 -257
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/event-steps.mdc +0 -504
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/instructions.mdc +0 -15
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/multi-language-workflows.mdc +0 -1059
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/noop-steps.mdc +0 -57
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/production-deployment.mdc +0 -668
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/realtime-streaming.mdc +0 -656
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/state-management.mdc +0 -371
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/steps.mdc +0 -373
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/testing.mdc +0 -329
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/typescript.mdc +0 -409
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/ui-steps.mdc +0 -429
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/workflow-patterns.mdc +0 -938
- package/dist/esm/cursor-rules/dot-files/AGENTS.md +0 -397
- package/dist/esm/cursor-rules/dot-files/README.md +0 -58
- /package/dist/cjs/create/templates/nodejs/{services → src/services/pet-store}/types.ts.txt +0 -0
- /package/dist/cjs/create/templates/nodejs/steps/{notification.step.ts.txt → petstore/notification.step.ts.txt} +0 -0
- /package/dist/cjs/create/templates/nodejs/steps/{process-food-order.step.ts-features.json.txt → petstore/process-food-order.step.ts-features.json.txt} +0 -0
- /package/dist/cjs/create/templates/nodejs/steps/{state-audit-cron.step.ts-features.json.txt → petstore/state-audit-cron.step.ts-features.json.txt} +0 -0
- /package/dist/cjs/create/templates/nodejs/steps/{state-audit-cron.step.ts.txt → petstore/state-audit-cron.step.ts.txt} +0 -0
- /package/dist/esm/create/templates/nodejs/{services → src/services/pet-store}/types.ts.txt +0 -0
- /package/dist/esm/create/templates/nodejs/steps/{notification.step.ts.txt → petstore/notification.step.ts.txt} +0 -0
- /package/dist/esm/create/templates/nodejs/steps/{process-food-order.step.ts-features.json.txt → petstore/process-food-order.step.ts-features.json.txt} +0 -0
- /package/dist/esm/create/templates/nodejs/steps/{state-audit-cron.step.ts-features.json.txt → petstore/state-audit-cron.step.ts-features.json.txt} +0 -0
- /package/dist/esm/create/templates/nodejs/steps/{state-audit-cron.step.ts.txt → petstore/state-audit-cron.step.ts.txt} +0 -0
|
@@ -40,7 +40,7 @@ const glob_1 = require("glob");
|
|
|
40
40
|
const generateTemplateSteps = (templateFolder) => {
|
|
41
41
|
return async (rootDir, context) => {
|
|
42
42
|
const templatePath = path.join(__dirname, templateFolder);
|
|
43
|
-
const files = (0, glob_1.globSync)('**/*', { absolute: false, cwd: templatePath });
|
|
43
|
+
const files = (0, glob_1.globSync)('**/*', { absolute: false, cwd: templatePath, dot: true });
|
|
44
44
|
try {
|
|
45
45
|
for (const fileName of files) {
|
|
46
46
|
const filePath = path.join(templatePath, fileName);
|
|
@@ -54,7 +54,7 @@ const generateTemplateSteps = (templateFolder) => {
|
|
|
54
54
|
(0, fs_1.mkdirSync)(targetDir, { recursive: true });
|
|
55
55
|
}
|
|
56
56
|
if ((0, fs_1.statSync)(filePath).isDirectory()) {
|
|
57
|
-
const folderPath =
|
|
57
|
+
const folderPath = filePath.replace(templatePath, '');
|
|
58
58
|
(0, fs_1.mkdirSync)(path.join(rootDir, folderPath), { recursive: true });
|
|
59
59
|
continue;
|
|
60
60
|
}
|
|
@@ -8,7 +8,7 @@ export type Generator = (rootDir: string, context: CliContext) => Promise<void>
|
|
|
8
8
|
export const generateTemplateSteps = (templateFolder: string): Generator => {
|
|
9
9
|
return async (rootDir: string, context: CliContext): Promise<void> => {
|
|
10
10
|
const templatePath = path.join(__dirname, templateFolder)
|
|
11
|
-
const files = globSync('**/*', { absolute: false, cwd: templatePath })
|
|
11
|
+
const files = globSync('**/*', { absolute: false, cwd: templatePath, dot: true })
|
|
12
12
|
|
|
13
13
|
try {
|
|
14
14
|
for (const fileName of files) {
|
|
@@ -24,7 +24,7 @@ export const generateTemplateSteps = (templateFolder: string): Generator => {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
if (statSync(filePath).isDirectory()) {
|
|
27
|
-
const folderPath =
|
|
27
|
+
const folderPath = filePath.replace(templatePath, '')
|
|
28
28
|
mkdirSync(path.join(rootDir, folderPath), { recursive: true })
|
|
29
29
|
continue
|
|
30
30
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: How to configure database migrations in the project
|
|
3
|
+
globs:
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
# Configuring database migrations
|
|
7
|
+
|
|
8
|
+
When configuring database in the project, create a `knexfile.ts` file in the root of the project.
|
|
9
|
+
|
|
10
|
+
```typescript
|
|
11
|
+
import type { Knex } from 'knex'
|
|
12
|
+
import * as dotenv from 'dotenv'
|
|
13
|
+
|
|
14
|
+
dotenv.config({ path: '.env' })
|
|
15
|
+
|
|
16
|
+
const config: Knex.Config = {
|
|
17
|
+
client: 'postgresql',
|
|
18
|
+
connection: {
|
|
19
|
+
host: process.env.DB_HOST,
|
|
20
|
+
port: process.env.DB_PORT,
|
|
21
|
+
database: process.env.DB_NAME,
|
|
22
|
+
user: process.env.DB_USER,
|
|
23
|
+
password: process.env.DB_PASS,
|
|
24
|
+
},
|
|
25
|
+
pool: {
|
|
26
|
+
min: 2,
|
|
27
|
+
max: 10,
|
|
28
|
+
},
|
|
29
|
+
migrations: {
|
|
30
|
+
tableName: 'knex_migrations',
|
|
31
|
+
},
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default config
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Creating a new migration
|
|
38
|
+
|
|
39
|
+
Prefix should be timestamp in milliseconds.
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm run migrate:make 1727115600000_create_users_table
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Running migrations
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm run migrate:latest
|
|
49
|
+
```
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Database connections and queries
|
|
3
|
+
globs: src/repositories/**/*.ts
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
# Database Guide
|
|
7
|
+
|
|
8
|
+
- Prefer knex to interact with the database
|
|
9
|
+
- http://npmjs.com/package/knex
|
|
10
|
+
- Use knex migrations to manage database schema changes
|
|
11
|
+
- Do NOT create DB calls directly in steps or services, ALWAYS create a repository file to handle the database calls. Follow DDD principles.
|
|
12
|
+
|
|
13
|
+
## Add commands to package.json
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"scripts": {
|
|
18
|
+
"migrate:up": "knex migrate:latest",
|
|
19
|
+
"migrate:down": "knex migrate:rollback",
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Creating base database connection
|
|
25
|
+
|
|
26
|
+
- When SQL database is used, create a database connection file in the `src/repositories/database.ts` file.
|
|
27
|
+
- All columns in code are cammelCase, however, in the database and in the migration, we use snake_case.
|
|
28
|
+
- Avoid numeric incremental IDs, use UUIDs instead. Make sure to add foreign key with cascade delete when applicable.
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import knex, { Knex } from 'knex'
|
|
32
|
+
/**
|
|
33
|
+
* Create these functions to convert between camelCase and snake_case.
|
|
34
|
+
* This is important to keep the consistency of the data.
|
|
35
|
+
*/
|
|
36
|
+
import { camelToSnake, snakeToCamelObject } from '../utils/case-conversion'
|
|
37
|
+
|
|
38
|
+
const isProduction = process.env.NODE_ENV === 'production'
|
|
39
|
+
const isDevelopment = process.env.NODE_ENV === 'development'
|
|
40
|
+
|
|
41
|
+
// Knex configuration
|
|
42
|
+
const knexConfig: Knex.Config = {
|
|
43
|
+
client: 'pg',
|
|
44
|
+
connection: {
|
|
45
|
+
host: process.env.DB_HOST,
|
|
46
|
+
port: process.env.DB_PORT,
|
|
47
|
+
user: process.env.DB_USER,
|
|
48
|
+
password: process.env.DB_PASSWORD,
|
|
49
|
+
database: process.env.DB_NAME,
|
|
50
|
+
ssl: process.env.DB_SSL ? {
|
|
51
|
+
/** In development, we might use self-signed certs */
|
|
52
|
+
rejectUnauthorized: isProduction,
|
|
53
|
+
/** Add CA certificate if needed */
|
|
54
|
+
ca: undefined,
|
|
55
|
+
} : false,
|
|
56
|
+
},
|
|
57
|
+
pool: {
|
|
58
|
+
min: 2,
|
|
59
|
+
max: 10,
|
|
60
|
+
idleTimeoutMillis: 30000,
|
|
61
|
+
},
|
|
62
|
+
debug: isDevelopment,
|
|
63
|
+
wrapIdentifier: (value, origImpl) => origImpl(camelToSnake(value)),
|
|
64
|
+
postProcessResponse: result =>
|
|
65
|
+
Array.isArray(result)
|
|
66
|
+
? result.map(row => snakeToCamelObject(row))
|
|
67
|
+
: snakeToCamelObject(result),
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Create a singleton instance
|
|
71
|
+
let db: Knex | null = null
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Get the database instance
|
|
75
|
+
* @returns Knex instance
|
|
76
|
+
*/
|
|
77
|
+
export const getDb = (): Knex => {
|
|
78
|
+
if (!db) {
|
|
79
|
+
db = knex(knexConfig)
|
|
80
|
+
}
|
|
81
|
+
return db
|
|
82
|
+
}
|
|
83
|
+
```
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Order } from './types'
|
|
2
|
+
|
|
3
|
+
export const createOrder = async (order: Omit<Order, 'id'>): Promise<Order> => {
|
|
4
|
+
const response = await fetch('https://petstore.swagger.io/v2/store/order', {
|
|
5
|
+
method: 'POST',
|
|
6
|
+
body: JSON.stringify({
|
|
7
|
+
quantity: order?.quantity ?? 1,
|
|
8
|
+
petId: 1,
|
|
9
|
+
shipDate: order?.shipDate ?? new Date().toISOString(),
|
|
10
|
+
status: order?.status ?? 'placed',
|
|
11
|
+
}),
|
|
12
|
+
headers: { 'Content-Type': 'application/json' },
|
|
13
|
+
})
|
|
14
|
+
return response.json()
|
|
15
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Pet } from './types'
|
|
2
|
+
|
|
3
|
+
export const createPet = async (pet: Omit<Pet, 'id'>): Promise<Pet> => {
|
|
4
|
+
const response = await fetch('https://petstore.swagger.io/v2/pet', {
|
|
5
|
+
method: 'POST',
|
|
6
|
+
body: JSON.stringify({
|
|
7
|
+
name: pet?.name ?? '',
|
|
8
|
+
photoUrls: [pet?.photoUrl ?? ''],
|
|
9
|
+
status: 'available',
|
|
10
|
+
}),
|
|
11
|
+
headers: { 'Content-Type': 'application/json' },
|
|
12
|
+
})
|
|
13
|
+
return response.json()
|
|
14
|
+
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"title": "Step Configuration",
|
|
5
5
|
"description": "All steps should have a defined configuration, this is how you define the step's behavior and how it will be triggered.",
|
|
6
6
|
"lines": [
|
|
7
|
-
"
|
|
7
|
+
"5-29"
|
|
8
8
|
]
|
|
9
9
|
},
|
|
10
10
|
{
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"title": "API Step",
|
|
13
13
|
"description": "Definition of an API endpoint",
|
|
14
14
|
"lines": [
|
|
15
|
-
"12
|
|
15
|
+
"11-12"
|
|
16
16
|
]
|
|
17
17
|
},
|
|
18
18
|
{
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"title": "Request body",
|
|
21
21
|
"description": "Definition of the expected request body. Motia will automatically generate types based on this schema.",
|
|
22
22
|
"lines": [
|
|
23
|
-
"
|
|
23
|
+
"13-24"
|
|
24
24
|
]
|
|
25
25
|
},
|
|
26
26
|
{
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"title": "Response Payload",
|
|
29
29
|
"description": "Definition of the expected response payload, Motia will generate the types automatically based on this schema. This is also important to create the Open API spec later.",
|
|
30
30
|
"lines": [
|
|
31
|
-
"
|
|
31
|
+
"25-27"
|
|
32
32
|
]
|
|
33
33
|
},
|
|
34
34
|
{
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
"title": "Emits",
|
|
37
37
|
"description": "We can define the events that this step will emit, this is how we can trigger other Motia Steps.",
|
|
38
38
|
"lines": [
|
|
39
|
-
"
|
|
40
|
-
"
|
|
39
|
+
"28",
|
|
40
|
+
"38-45"
|
|
41
41
|
]
|
|
42
42
|
},
|
|
43
43
|
{
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"title": "Handler",
|
|
46
46
|
"description": "The handler is the function that will be executed when the step is triggered. This one receives the request body and emits events.",
|
|
47
47
|
"lines": [
|
|
48
|
-
"
|
|
48
|
+
"31-49"
|
|
49
49
|
]
|
|
50
50
|
},
|
|
51
51
|
{
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"title": "Logger",
|
|
54
54
|
"description": "The logger is a utility that allows you to log messages to the console. It is available in the handler function. We encourage you to use it instead of console.log. It will automatically be tied to the trace id of the request.",
|
|
55
55
|
"lines": [
|
|
56
|
-
"
|
|
56
|
+
"32"
|
|
57
57
|
]
|
|
58
58
|
},
|
|
59
59
|
{
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"title": "HTTP Response",
|
|
62
62
|
"description": "The handler can return a response to the client. This is how we can return a response to the client. It must comply with the responseSchema defined in the step configuration.",
|
|
63
63
|
"lines": [
|
|
64
|
-
"
|
|
64
|
+
"48"
|
|
65
65
|
]
|
|
66
66
|
}
|
|
67
67
|
]
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ApiRouteConfig, Handlers } from 'motia'
|
|
2
2
|
import { z } from 'zod'
|
|
3
|
-
import { petStoreService } from '
|
|
4
|
-
import { petSchema } from '../services/types'
|
|
3
|
+
import { petStoreService, petSchema } from '../../src/services/pet-store'
|
|
5
4
|
|
|
6
5
|
export const config: ApiRouteConfig = {
|
|
7
6
|
type: 'api',
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: How to structure your Motia project
|
|
3
|
+
globs:
|
|
4
|
+
alwaysApply: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Architecture Guide
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
This guide covers the architecture of a Motia project.
|
|
12
|
+
|
|
13
|
+
## File Structure
|
|
14
|
+
|
|
15
|
+
All step files should be underneath the `steps/` folder.
|
|
16
|
+
|
|
17
|
+
Underneath the `steps/` folder, create subfolders for Flows. Flows are used to group steps together.
|
|
18
|
+
|
|
19
|
+
## Step Naming Conventions
|
|
20
|
+
|
|
21
|
+
### Typescript
|
|
22
|
+
|
|
23
|
+
- Use kebab-case for filenames: `resource-processing.step.ts`
|
|
24
|
+
- Include `.step` before language extension
|
|
25
|
+
|
|
26
|
+
### Python
|
|
27
|
+
|
|
28
|
+
- Use snake_case for filenames: `data_processor_step.py`
|
|
29
|
+
- Include `_step` before language extension
|
|
30
|
+
|
|
31
|
+
### Global
|
|
32
|
+
|
|
33
|
+
- Match handler names to config names
|
|
34
|
+
- Use descriptive, action-oriented names
|
|
35
|
+
|
|
36
|
+
## Code Style Guidelines
|
|
37
|
+
|
|
38
|
+
- **JavaScript**: Use modern ES6+ features, async/await, proper error handling
|
|
39
|
+
- **TypeScript**: Make sure you use the correct Handlers type that is auto generated on the `types.d.ts` file.
|
|
40
|
+
|
|
41
|
+
## Defining Middlewares
|
|
42
|
+
|
|
43
|
+
Middleware is a powerful feature in Motia to help adding common validation, error
|
|
44
|
+
handling and other common logic to your steps.
|
|
45
|
+
|
|
46
|
+
- Make sure to add all the middlewares in a single folder, called `middlewares/`.
|
|
47
|
+
- Create a comprehensive file name for the middleware, like `auth.middleware.ts`.
|
|
48
|
+
- Follow SOLID principles with separation of concerns in middlewares, create a middleware for each responsibility.
|
|
49
|
+
- Use core middleware to handle ZodError gracefully (see [Error Handling Guide](./error-handling.mdc))
|
|
50
|
+
- Rate limiting and CORS are not needed to be handled in middleware since they're an infrastructure concern.
|
|
51
|
+
|
|
52
|
+
## Domain Driven Design
|
|
53
|
+
|
|
54
|
+
Make sure you follow Domain Driven Design principles in your project.
|
|
55
|
+
|
|
56
|
+
- Create `/src/services` folder to store your services, this is where it holds business logic.
|
|
57
|
+
- Create `/src/repositories` folder to store your repositories, this is where it holds data access logic.
|
|
58
|
+
- Create `/src/utils` folder to store your utility functions.
|
|
59
|
+
- Models and DTOs are not quite necessary, we can rely on zod to create the models and DTOs from the steps.
|
|
60
|
+
- Controller layer is the Steps, it should have mostly logic around validation and calling services.
|
|
61
|
+
- Avoid having Service methods with just a call to the Repository, it should have some logic around it, if it doesn't have, then Steps can have access to repositories directly.
|
|
62
|
+
|
|
63
|
+
### Services
|
|
64
|
+
|
|
65
|
+
Defining services can be done in the following way:
|
|
66
|
+
|
|
67
|
+
- Create a folder underneath `/src/services/` folder, like `/src/services/auth/`.
|
|
68
|
+
- Create a file inside the folder called `index.ts`.
|
|
69
|
+
- Inside `index.ts`, export a constant with the name of the service, with the methods as properties.
|
|
70
|
+
- Methods should be defined as separate files, use export named functions.
|
|
71
|
+
- Use the service in the Steps.
|
|
72
|
+
|
|
73
|
+
#### Example
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
/**
|
|
77
|
+
* Business logic for authentication defined in a separate file in the same folder.
|
|
78
|
+
*/
|
|
79
|
+
import { login } from './login'
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Constant with the name of the service, with the methods as properties.
|
|
83
|
+
*/
|
|
84
|
+
export const authService = {
|
|
85
|
+
login
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Logging and observability
|
|
90
|
+
|
|
91
|
+
- Make sure to use the Logger from Motia (from context object) to log messages.
|
|
92
|
+
- Make sure to have visibility of what is going on in a request
|
|
93
|
+
- Before throwing errors, make sure to log the issue, identify if issue is a validation blocker, then log with `logger.warn`, if it's something that is not supposed to happen, then log with `logger.error`.
|
|
94
|
+
- Make sure to add context to the logs to help identify any potential issues.
|
|
95
|
+
|
|
96
|
+
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: How to handle errors in a Motia project
|
|
3
|
+
globs:
|
|
4
|
+
alwaysApply: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Error Handling Guide
|
|
8
|
+
|
|
9
|
+
Errors happen, but we need to handle them gracefully. Make sure you create a custom error class for your project, underneath `/src/errors/` folder.
|
|
10
|
+
|
|
11
|
+
## Good practices
|
|
12
|
+
|
|
13
|
+
- Use Custom error to return errors to the client.
|
|
14
|
+
- Anything that is not the error class, should be logged with `logger.error`. And root cause should be omitted to the client.
|
|
15
|
+
|
|
16
|
+
## Create a custom Error class
|
|
17
|
+
|
|
18
|
+
Name: `/src/errors/base.error.ts`
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
export class BaseError extends Error {
|
|
22
|
+
public readonly status: number
|
|
23
|
+
public readonly code: string
|
|
24
|
+
public readonly metadata: Record<string, any>
|
|
25
|
+
|
|
26
|
+
constructor(
|
|
27
|
+
message: string,
|
|
28
|
+
status: number = 500,
|
|
29
|
+
code: string = 'INTERNAL_SERVER_ERROR',
|
|
30
|
+
metadata: Record<string, any> = {}
|
|
31
|
+
) {
|
|
32
|
+
super(message)
|
|
33
|
+
this.name = this.constructor.name
|
|
34
|
+
this.status = status
|
|
35
|
+
this.code = code
|
|
36
|
+
this.metadata = metadata
|
|
37
|
+
|
|
38
|
+
// Maintains proper stack trace for where our error was thrown
|
|
39
|
+
Error.captureStackTrace(this, this.constructor)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
toJSON() {
|
|
43
|
+
return {
|
|
44
|
+
error: {
|
|
45
|
+
name: this.name,
|
|
46
|
+
message: this.message,
|
|
47
|
+
code: this.code,
|
|
48
|
+
status: this.status,
|
|
49
|
+
...(Object.keys(this.metadata).length > 0 && { metadata: this.metadata }),
|
|
50
|
+
},
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Then create sub class for specific errors that are commonly thrown in your project.
|
|
57
|
+
|
|
58
|
+
Name: `/src/errors/not-found.error.ts`
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
import { BaseError } from './base.error'
|
|
62
|
+
|
|
63
|
+
export class NotFoundError extends BaseError {
|
|
64
|
+
constructor(message: string = 'Not Found', metadata: Record<string, any> = {}) {
|
|
65
|
+
super(message, 404, 'NOT_FOUND', metadata)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Core Middleware
|
|
71
|
+
|
|
72
|
+
Make sure you create a core middleware that will be added to ALL API Steps.
|
|
73
|
+
|
|
74
|
+
File: `/src/middlewares/core.middleware.ts`
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
import { ApiMiddleware } from 'motia'
|
|
78
|
+
import { ZodError } from 'zod'
|
|
79
|
+
import { BaseError } from '../errors/base.error'
|
|
80
|
+
|
|
81
|
+
export const coreMiddleware: ApiMiddleware = async (req, ctx, next) => {
|
|
82
|
+
const logger = ctx.logger
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
return await next()
|
|
86
|
+
} catch (error: any) {
|
|
87
|
+
if (error instanceof ZodError) {
|
|
88
|
+
logger.error('Validation error', {
|
|
89
|
+
error,
|
|
90
|
+
stack: error.stack,
|
|
91
|
+
errors: error.errors,
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
status: 400,
|
|
96
|
+
body: {
|
|
97
|
+
error: 'Invalid request body',
|
|
98
|
+
data: error.errors,
|
|
99
|
+
},
|
|
100
|
+
}
|
|
101
|
+
} else if (error instanceof BaseError) {
|
|
102
|
+
logger.error('BaseError', {
|
|
103
|
+
status: error.status,
|
|
104
|
+
code: error.code,
|
|
105
|
+
metadata: error.metadata,
|
|
106
|
+
name: error.name,
|
|
107
|
+
message: error.message,
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
return { status: error.status, body: error.toJSON() }
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
logger.error('Error while performing request', {
|
|
114
|
+
error,
|
|
115
|
+
body: req.body,
|
|
116
|
+
stack: error.stack,
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
return { status: 500, body: { error: 'Internal Server Error' } }
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Rules for the project
|
|
3
|
+
globs:
|
|
4
|
+
alwaysApply: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Adding migration
|
|
8
|
+
|
|
9
|
+
Make sure to use [migration guide](./architecture/database/database-migration.mdc) to create a new migration.
|
|
10
|
+
|
|
11
|
+
## Database integration
|
|
12
|
+
|
|
13
|
+
Whenever database is used, please use [database guide](./architecture/database/database.mdc) to create a database connection and methods.
|
|
14
|
+
|
|
15
|
+
## Real time events
|
|
16
|
+
|
|
17
|
+
Make sure to use [real time events guide](./rules/motia/realtime-streaming.mdc) to create a new real time event.
|
|
18
|
+
|
|
19
|
+
## State/Cache management
|
|
20
|
+
|
|
21
|
+
Make sure to use [state management guide](./rules/motia/state-management.mdc) to create a new state management.
|
|
22
|
+
|
|
23
|
+
## Authentication
|
|
24
|
+
|
|
25
|
+
If ever need to add authentication, make sure to use middleware to authenticate the request.
|
|
26
|
+
Make sure to use [middlewares](./rules/motia/middlewares.mdc) to validate the requests.
|