Skip to content

Commit 93fc751

Browse files
authored
feat: enhance core functionality with new MotiaPluginContext and API endpoints integration (#837)
1 parent 74e97e6 commit 93fc751

File tree

12 files changed

+135
-137
lines changed

12 files changed

+135
-137
lines changed

packages/core/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ export { StateAdapter } from './src/state/state-adapter'
1212
export { createMermaidGenerator } from './src/mermaid-generator'
1313
export { StreamConfig, MotiaStream } from './src/types-stream'
1414
export { getProjectIdentifier, getUserIdentifier, isAnalyticsEnabled, trackEvent } from './src/analytics/utils'
15-
export { Motia } from './src/motia'
15+
export { Motia, MotiaPluginContext } from './src/motia'
1616
export { NoPrinter, Printer } from './src/printer'
1717
export { NoTracer } from './src/observability/no-tracer'
1818
export { config } from './src/config'
19+
export * from './src/types/schema.types'
20+
export { StreamAdapter } from './src/streams/adapters/stream-adapter'

packages/core/src/endpoints/api-endpoints.ts

Lines changed: 0 additions & 97 deletions
This file was deleted.

packages/core/src/motia.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import { Printer } from './printer'
2-
import { TracerFactory } from './observability'
3-
import { EventManager, InternalStateManager } from './types'
1+
import type { Express } from 'express'
42
import { LockedData } from './locked-data'
53
import { LoggerFactory } from './logger-factory'
6-
import type { Express } from 'express'
4+
import { TracerFactory } from './observability'
5+
import { Printer } from './printer'
76
import { StateAdapter } from './state/state-adapter'
7+
import { EventManager, InternalStateManager } from './types'
88

99
export type Motia = {
1010
loggerFactory: LoggerFactory
@@ -17,3 +17,9 @@ export type Motia = {
1717
app: Express
1818
stateAdapter: StateAdapter
1919
}
20+
21+
export type MotiaPluginContext = {
22+
app: Express
23+
state: StateAdapter
24+
lockedData: LockedData
25+
}

packages/core/src/server.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { trackEvent } from './analytics/utils'
66
import { callStepFile } from './call-step-file'
77
import { CronManager, setupCronHandlers } from './cron-handler'
88
import { analyticsEndpoint } from './endpoints/analytics-endpoint'
9-
import { apiEndpoints } from './endpoints/api-endpoints'
109
import { flowsConfigEndpoint } from './endpoints/flows-config-endpoint'
1110
import { flowsEndpoint } from './endpoints/flows-endpoint'
1211
import { stepEndpoint } from './endpoints/step-endpoint'
@@ -285,7 +284,6 @@ export const createServer = (
285284

286285
app.use(router)
287286

288-
apiEndpoints(lockedData)
289287
flowsEndpoint(lockedData)
290288
flowsConfigEndpoint(app, process.cwd(), lockedData)
291289
analyticsEndpoint(app, process.cwd())
Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,4 @@
1-
import { Motia } from '../motia'
2-
3-
export type Runtime = {
4-
steps: string
5-
streams: string
6-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
7-
runtime: any
8-
}
1+
import { MotiaPluginContext } from '../motia'
92

103
export type WorkbenchPlugin = {
114
packageName: string
@@ -22,9 +15,8 @@ export type MotiaPlugin = {
2215
workbench: WorkbenchPlugin[]
2316
}
2417

25-
export type MotiaPluginBuilder = (motia: Motia) => MotiaPlugin
18+
export type MotiaPluginBuilder = (motia: MotiaPluginContext) => MotiaPlugin
2619

2720
export type Config = {
28-
runtimes?: Runtime[]
2921
plugins?: MotiaPluginBuilder[]
3022
}

packages/core/tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
"rootDir": ".",
1414
"baseUrl": ".",
1515
"declaration": true,
16-
"jsx": "react-jsx",
16+
"declarationMap": true,
17+
"jsx": "react-jsx"
1718
},
1819
"include": ["**/*.ts", "**/*.js"],
1920
"exclude": ["node_modules", "dist"]

packages/snap/src/generate-plugins.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Config, Motia, MotiaPlugin } from '@motiadev/core'
1+
import { Config, Motia, MotiaPlugin, MotiaPluginContext } from '@motiadev/core'
22
import fs from 'fs'
33
import { globSync } from 'glob'
44
import path from 'path'
@@ -18,8 +18,14 @@ export const generatePlugins = async (motia: Motia): Promise<MotiaPlugin[]> => {
1818
configFiles = globSync('motia.config.{ts,js}', { absolute: true, cwd: baseDir })
1919
}
2020

21+
const context: MotiaPluginContext = {
22+
app: motia.app,
23+
state: motia.stateAdapter,
24+
lockedData: motia.lockedData,
25+
}
26+
2127
const appConfig: Config = (await import(configFiles[0])).default
22-
const plugins = appConfig.plugins?.flatMap((item) => item(motia)) || []
28+
const plugins = appConfig.plugins?.flatMap((item) => item(context)) || []
2329

2430
return plugins
2531
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { ApiRouteConfig, ApiRouteMethod, JsonSchema, LockedData, QueryParam, Step, StreamAdapter } from '@motiadev/core'
2+
3+
type ApiEndpoint = {
4+
id: string
5+
method: ApiRouteMethod
6+
path: string
7+
description?: string
8+
queryParams?: QueryParam[]
9+
responseSchema?: JsonSchema
10+
bodySchema?: JsonSchema
11+
flows?: string[]
12+
}
13+
14+
export const mapEndpoint = (step: Step<ApiRouteConfig>): ApiEndpoint => {
15+
return {
16+
id: step.filePath,
17+
method: step.config.method,
18+
path: step.config.path,
19+
description: step.config.description,
20+
queryParams: step.config.queryParams,
21+
responseSchema: step.config.responseSchema as never as JsonSchema,
22+
bodySchema: step.config.bodySchema as never as JsonSchema,
23+
flows: step.config.flows,
24+
}
25+
}
26+
27+
export class EndpointsStream extends StreamAdapter<ApiEndpoint> {
28+
constructor(private readonly lockedData: LockedData) {
29+
super()
30+
}
31+
32+
async get(_groupId: string, id: string): Promise<ApiEndpoint | null> {
33+
const endpoint = this.lockedData.apiSteps().find((step) => step.filePath === id)
34+
return endpoint ? mapEndpoint(endpoint) : null
35+
}
36+
37+
async delete(id: string): Promise<ApiEndpoint> {
38+
return { id } as never
39+
}
40+
41+
async set(_: string, __: string, data: ApiEndpoint): Promise<ApiEndpoint> {
42+
return data
43+
}
44+
45+
async getGroup(): Promise<ApiEndpoint[]> {
46+
return this.lockedData.apiSteps().map(mapEndpoint)
47+
}
48+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { MotiaPlugin, MotiaPluginContext, Step, isApiStep } from '@motiadev/core'
2+
import { EndpointsStream, mapEndpoint } from './endpoints-stream'
3+
4+
export function plugin({ lockedData }: MotiaPluginContext): MotiaPlugin {
5+
const stream = lockedData.createStream({
6+
filePath: '__motia.api-endpoints.ts',
7+
hidden: true,
8+
config: {
9+
name: '__motia.api-endpoints',
10+
baseConfig: { storageType: 'custom', factory: () => new EndpointsStream(lockedData) },
11+
schema: null as never,
12+
},
13+
})()
14+
15+
const apiStepCreated = (step: Step) => {
16+
if (isApiStep(step)) {
17+
stream.set('default', step.filePath, {
18+
id: step.filePath,
19+
method: step.config.method,
20+
path: step.config.path,
21+
description: step.config.description,
22+
queryParams: step.config.queryParams,
23+
})
24+
}
25+
}
26+
27+
const apiStepUpdated = (step: Step) => {
28+
if (isApiStep(step)) {
29+
stream.set('default', step.filePath, mapEndpoint(step))
30+
}
31+
}
32+
33+
const apiStepRemoved = (step: Step) => {
34+
if (isApiStep(step)) {
35+
stream.delete('default', step.filePath)
36+
}
37+
}
38+
39+
lockedData.onStep('step-created', apiStepCreated)
40+
lockedData.onStep('step-updated', apiStepUpdated)
41+
lockedData.onStep('step-removed', apiStepRemoved)
42+
43+
return {
44+
workbench: [
45+
{
46+
packageName: '@motiadev/plugin-endpoint',
47+
cssImports: ['@motiadev/plugin-endpoint/dist/plugin-endpoint.css'],
48+
label: 'Endpoints',
49+
position: 'top',
50+
componentName: 'EndpointsPage',
51+
labelIcon: 'link-2',
52+
},
53+
],
54+
}
55+
}
Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,3 @@
1-
import { Motia, MotiaPlugin } from '@motiadev/core'
1+
import { plugin } from './api'
22

3-
export default function plugin(motia: Motia): MotiaPlugin {
4-
return {
5-
workbench: [
6-
{
7-
packageName: '@motiadev/plugin-endpoint',
8-
cssImports: ['@motiadev/plugin-endpoint/dist/plugin-endpoint.css'],
9-
label: 'Endpoints',
10-
position: 'top',
11-
componentName: 'EndpointsPage',
12-
labelIcon: 'link-2',
13-
},
14-
],
15-
}
16-
}
3+
export default plugin

0 commit comments

Comments
 (0)