diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 55e198e52a..6546dfa583 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1989,7 +1989,7 @@ importers: version: 3.13.12(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@uiw/codemirror-extensions-basic-setup': specifier: ^4.25.1 - version: 4.25.1(@codemirror/autocomplete@6.19.0)(@codemirror/commands@6.9.0)(@codemirror/language@6.11.3)(@codemirror/lint@6.9.0)(@codemirror/search@6.5.11)(@codemirror/state@6.5.2)(@codemirror/view@6.38.2) + version: 4.25.1(@codemirror/autocomplete@6.19.0)(@codemirror/commands@6.8.1)(@codemirror/language@6.11.3)(@codemirror/lint@6.9.0)(@codemirror/search@6.5.11)(@codemirror/state@6.5.2)(@codemirror/view@6.38.2) '@uiw/codemirror-theme-github': specifier: ^4.25.1 version: 4.25.1(@codemirror/language@6.11.3)(@codemirror/state@6.5.2)(@codemirror/view@6.38.2) @@ -2397,6 +2397,9 @@ importers: ws: specifier: ^8.18.1 version: 8.18.3 + zod-to-json-schema: + specifier: ^3.24.6 + version: 3.24.6(zod@3.25.76) rivetkit-typescript/packages/sql-loader: devDependencies: @@ -2463,13 +2466,13 @@ importers: version: 6.0.1 '@mdx-js/loader': specifier: ^3.1.1 - version: 3.1.1(webpack@5.101.3(esbuild@0.25.9)) + version: 3.1.1(webpack@5.101.3) '@mdx-js/react': specifier: ^3.1.1 version: 3.1.1(@types/react@19.2.2)(react@19.1.1) '@next/mdx': specifier: ^15.5.2 - version: 15.5.2(@mdx-js/loader@3.1.1(webpack@5.101.3(esbuild@0.25.9)))(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@19.1.1)) + version: 15.5.2(@mdx-js/loader@3.1.1(webpack@5.101.3))(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@19.1.1)) '@next/third-parties': specifier: latest version: 16.0.1(next@15.5.2(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(sass@1.93.2))(react@19.1.1) @@ -2659,7 +2662,7 @@ importers: version: 13.0.2(eslint@8.26.0)(typescript@5.9.2) file-loader: specifier: ^6.2.0 - version: 6.2.0(webpack@5.101.3(esbuild@0.25.9)) + version: 6.2.0(webpack@5.101.3) prettier: specifier: ^2.8.8 version: 2.8.8 @@ -16169,12 +16172,12 @@ snapshots: '@marijn/find-cluster-break@1.0.2': {} - '@mdx-js/loader@3.1.1(webpack@5.101.3(esbuild@0.25.9))': + '@mdx-js/loader@3.1.1(webpack@5.101.3)': dependencies: '@mdx-js/mdx': 3.1.1 source-map: 0.7.6 optionalDependencies: - webpack: 5.101.3(esbuild@0.25.9) + webpack: 5.101.3 transitivePeerDependencies: - supports-color @@ -16352,11 +16355,11 @@ snapshots: dependencies: glob: 7.1.7 - '@next/mdx@15.5.2(@mdx-js/loader@3.1.1(webpack@5.101.3(esbuild@0.25.9)))(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@19.1.1))': + '@next/mdx@15.5.2(@mdx-js/loader@3.1.1(webpack@5.101.3))(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@19.1.1))': dependencies: source-map: 0.7.6 optionalDependencies: - '@mdx-js/loader': 3.1.1(webpack@5.101.3(esbuild@0.25.9)) + '@mdx-js/loader': 3.1.1(webpack@5.101.3) '@mdx-js/react': 3.1.1(@types/react@19.2.2)(react@19.1.1) '@next/swc-darwin-arm64@15.4.5': @@ -18565,16 +18568,6 @@ snapshots: '@codemirror/state': 6.5.2 '@codemirror/view': 6.38.2 - '@uiw/codemirror-extensions-basic-setup@4.25.1(@codemirror/autocomplete@6.19.0)(@codemirror/commands@6.9.0)(@codemirror/language@6.11.3)(@codemirror/lint@6.9.0)(@codemirror/search@6.5.11)(@codemirror/state@6.5.2)(@codemirror/view@6.38.2)': - dependencies: - '@codemirror/autocomplete': 6.19.0 - '@codemirror/commands': 6.9.0 - '@codemirror/language': 6.11.3 - '@codemirror/lint': 6.9.0 - '@codemirror/search': 6.5.11 - '@codemirror/state': 6.5.2 - '@codemirror/view': 6.38.2 - '@uiw/codemirror-theme-github@4.25.1(@codemirror/language@6.11.3)(@codemirror/state@6.5.2)(@codemirror/view@6.38.2)': dependencies: '@uiw/codemirror-themes': 4.25.1(@codemirror/language@6.11.3)(@codemirror/state@6.5.2)(@codemirror/view@6.38.2) @@ -20630,7 +20623,7 @@ snapshots: eslint: 8.26.0 eslint-import-resolver-node: 0.3.9 eslint-import-resolver-typescript: 2.7.1(eslint-plugin-import@2.32.0(eslint@8.26.0))(eslint@8.26.0) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@5.62.0(eslint@8.26.0)(typescript@5.9.2))(eslint-import-resolver-typescript@2.7.1(eslint-plugin-import@2.32.0(eslint@8.26.0))(eslint@8.26.0))(eslint@8.26.0) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@5.62.0(eslint@8.26.0)(typescript@5.9.2))(eslint-import-resolver-typescript@2.7.1)(eslint@8.26.0) eslint-plugin-jsx-a11y: 6.10.2(eslint@8.26.0) eslint-plugin-react: 7.37.5(eslint@8.26.0) eslint-plugin-react-hooks: 4.6.2(eslint@8.26.0) @@ -20652,7 +20645,7 @@ snapshots: dependencies: debug: 4.4.1 eslint: 8.26.0 - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@5.62.0(eslint@8.26.0)(typescript@5.9.2))(eslint-import-resolver-typescript@2.7.1(eslint-plugin-import@2.32.0(eslint@8.26.0))(eslint@8.26.0))(eslint@8.26.0) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@5.62.0(eslint@8.26.0)(typescript@5.9.2))(eslint-import-resolver-typescript@2.7.1)(eslint@8.26.0) glob: 7.2.3 is-glob: 4.0.3 resolve: 1.22.10 @@ -20671,7 +20664,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@5.62.0(eslint@8.26.0)(typescript@5.9.2))(eslint-import-resolver-typescript@2.7.1(eslint-plugin-import@2.32.0(eslint@8.26.0))(eslint@8.26.0))(eslint@8.26.0): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@5.62.0(eslint@8.26.0)(typescript@5.9.2))(eslint-import-resolver-typescript@2.7.1)(eslint@8.26.0): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -21170,11 +21163,11 @@ snapshots: dependencies: flat-cache: 3.2.0 - file-loader@6.2.0(webpack@5.101.3(esbuild@0.25.9)): + file-loader@6.2.0(webpack@5.101.3): dependencies: loader-utils: 2.0.4 schema-utils: 3.3.0 - webpack: 5.101.3(esbuild@0.25.9) + webpack: 5.101.3 file-saver@2.0.5: {} @@ -25686,6 +25679,16 @@ snapshots: webpack: 5.101.3(esbuild@0.25.9) optionalDependencies: esbuild: 0.25.9 + optional: true + + terser-webpack-plugin@5.3.14(webpack@5.101.3): + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + jest-worker: 27.5.1 + schema-utils: 4.3.3 + serialize-javascript: 6.0.2 + terser: 5.44.0 + webpack: 5.101.3 terser@5.44.0: dependencies: @@ -26798,6 +26801,38 @@ snapshots: webpack-virtual-modules@0.6.2: {} + webpack@5.101.3: + dependencies: + '@types/eslint-scope': 3.7.7 + '@types/estree': 1.0.8 + '@types/json-schema': 7.0.15 + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/wasm-edit': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + acorn: 8.15.0 + acorn-import-phases: 1.0.4(acorn@8.15.0) + browserslist: 4.26.3 + chrome-trace-event: 1.0.4 + enhanced-resolve: 5.18.3 + es-module-lexer: 1.7.0 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.1 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 4.3.3 + tapable: 2.3.0 + terser-webpack-plugin: 5.3.14(webpack@5.101.3) + watchpack: 2.4.4 + webpack-sources: 3.3.3 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + webpack@5.101.3(esbuild@0.25.9): dependencies: '@types/eslint-scope': 3.7.7 @@ -26829,6 +26864,7 @@ snapshots: - '@swc/core' - esbuild - uglify-js + optional: true whatwg-fetch@3.6.20: {} diff --git a/rivetkit-asyncapi/asyncapi.json b/rivetkit-asyncapi/asyncapi.json new file mode 100644 index 0000000000..0d9c7c7f98 --- /dev/null +++ b/rivetkit-asyncapi/asyncapi.json @@ -0,0 +1,436 @@ +{ + "asyncapi": "3.0.0", + "info": { + "title": "RivetKit WebSocket Protocol", + "version": "2.0.24-rc.1", + "description": "WebSocket protocol for bidirectional communication between RivetKit clients and actors" + }, + "channels": { + "/gateway/{actorId}/connect": { + "address": "/gateway/{actorId}/connect", + "parameters": { + "actorId": { + "description": "The unique identifier for the actor instance" + } + }, + "messages": { + "toClient": { + "$ref": "#/components/messages/ToClient" + }, + "toServer": { + "$ref": "#/components/messages/ToServer" + } + } + } + }, + "operations": { + "sendToClient": { + "action": "send", + "channel": { + "$ref": "#/channels/~1gateway~1{actorId}~1connect" + }, + "messages": [ + { + "$ref": "#/channels/~1gateway~1{actorId}~1connect/messages/toClient" + } + ], + "summary": "Send messages from server to client", + "description": "Messages sent from the RivetKit actor to connected clients" + }, + "receiveFromClient": { + "action": "receive", + "channel": { + "$ref": "#/channels/~1gateway~1{actorId}~1connect" + }, + "messages": [ + { + "$ref": "#/channels/~1gateway~1{actorId}~1connect/messages/toServer" + } + ], + "summary": "Receive messages from client", + "description": "Messages received by the RivetKit actor from connected clients" + } + }, + "components": { + "messages": { + "ToClient": { + "name": "ToClient", + "title": "Message To Client", + "summary": "A message sent from the server to the client", + "contentType": "application/json", + "payload": { + "type": "object", + "properties": { + "body": { + "anyOf": [ + { + "type": "object", + "properties": { + "tag": { + "type": "string", + "const": "Init" + }, + "val": { + "type": "object", + "properties": { + "actorId": { + "type": "string" + }, + "connectionId": { + "type": "string" + } + }, + "required": [ + "actorId", + "connectionId" + ], + "additionalProperties": false + } + }, + "required": ["tag", "val"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "tag": { + "type": "string", + "const": "Error" + }, + "val": { + "type": "object", + "properties": { + "group": { + "type": "string" + }, + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "metadata": {}, + "actionId": { + "type": ["integer", "null"] + } + }, + "required": [ + "group", + "code", + "message", + "actionId" + ], + "additionalProperties": false + } + }, + "required": ["tag", "val"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "tag": { + "type": "string", + "const": "ActionResponse" + }, + "val": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "output": {} + }, + "required": ["id"], + "additionalProperties": false + } + }, + "required": ["tag", "val"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "tag": { + "type": "string", + "const": "Event" + }, + "val": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "args": {} + }, + "required": ["name"], + "additionalProperties": false + } + }, + "required": ["tag", "val"], + "additionalProperties": false + } + ] + } + }, + "required": ["body"], + "additionalProperties": false + }, + "examples": [ + { + "name": "Init message", + "summary": "Initial connection message", + "payload": { + "body": { + "tag": "Init", + "val": { + "actorId": "actor_123", + "connectionId": "conn_456" + } + } + } + }, + { + "name": "Error message", + "summary": "Error response", + "payload": { + "body": { + "tag": "Error", + "val": { + "group": "auth", + "code": "unauthorized", + "message": "Authentication failed", + "actionId": null + } + } + } + }, + { + "name": "Action response", + "summary": "Response to an action request", + "payload": { + "body": { + "tag": "ActionResponse", + "val": { + "id": "123", + "output": { + "result": "success" + } + } + } + } + }, + { + "name": "Event", + "summary": "Event broadcast to subscribed clients", + "payload": { + "body": { + "tag": "Event", + "val": { + "name": "stateChanged", + "args": { + "newState": "active" + } + } + } + } + } + ] + }, + "ToServer": { + "name": "ToServer", + "title": "Message To Server", + "summary": "A message sent from the client to the server", + "contentType": "application/json", + "payload": { + "type": "object", + "properties": { + "body": { + "anyOf": [ + { + "type": "object", + "properties": { + "tag": { + "type": "string", + "const": "ActionRequest" + }, + "val": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + }, + "args": {} + }, + "required": ["id", "name"], + "additionalProperties": false + } + }, + "required": ["tag", "val"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "tag": { + "type": "string", + "const": "SubscriptionRequest" + }, + "val": { + "type": "object", + "properties": { + "eventName": { + "type": "string" + }, + "subscribe": { + "type": "boolean" + } + }, + "required": [ + "eventName", + "subscribe" + ], + "additionalProperties": false + } + }, + "required": ["tag", "val"], + "additionalProperties": false + } + ] + } + }, + "required": ["body"], + "additionalProperties": false + }, + "examples": [ + { + "name": "Action request", + "summary": "Request to execute an action", + "payload": { + "body": { + "tag": "ActionRequest", + "val": { + "id": "123", + "name": "updateState", + "args": { + "key": "value" + } + } + } + } + }, + { + "name": "Subscription request", + "summary": "Request to subscribe/unsubscribe from an event", + "payload": { + "body": { + "tag": "SubscriptionRequest", + "val": { + "eventName": "stateChanged", + "subscribe": true + } + } + } + } + ] + } + }, + "schemas": { + "Init": { + "type": "object", + "properties": { + "actorId": { + "type": "string" + }, + "connectionId": { + "type": "string" + } + }, + "required": ["actorId", "connectionId"], + "additionalProperties": false, + "description": "Initial connection message sent from server to client" + }, + "Error": { + "type": "object", + "properties": { + "group": { + "type": "string" + }, + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "metadata": {}, + "actionId": { + "type": ["integer", "null"] + } + }, + "required": ["group", "code", "message", "actionId"], + "additionalProperties": false, + "description": "Error message sent from server to client" + }, + "ActionResponse": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "output": {} + }, + "required": ["id"], + "additionalProperties": false, + "description": "Response to an action request" + }, + "Event": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "args": {} + }, + "required": ["name"], + "additionalProperties": false, + "description": "Event broadcast to subscribed clients" + }, + "ActionRequest": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + }, + "args": {} + }, + "required": ["id", "name"], + "additionalProperties": false, + "description": "Request to execute an action on the actor" + }, + "SubscriptionRequest": { + "type": "object", + "properties": { + "eventName": { + "type": "string" + }, + "subscribe": { + "type": "boolean" + } + }, + "required": ["eventName", "subscribe"], + "additionalProperties": false, + "description": "Request to subscribe or unsubscribe from an event" + } + } + } +} diff --git a/rivetkit-typescript/packages/rivetkit/package.json b/rivetkit-typescript/packages/rivetkit/package.json index d9548edc7e..8dd09f52bd 100644 --- a/rivetkit-typescript/packages/rivetkit/package.json +++ b/rivetkit-typescript/packages/rivetkit/package.json @@ -157,7 +157,8 @@ "check-types": "tsc --noEmit", "test": "vitest run", "test:watch": "vitest", - "dump-openapi": "tsx scripts/dump-openapi.ts" + "dump-openapi": "tsx scripts/dump-openapi.ts", + "dump-asyncapi": "tsx scripts/dump-asyncapi.ts" }, "dependencies": { "@bare-ts/lib": "~0.3.0", @@ -190,7 +191,8 @@ "tsx": "^4.19.4", "typescript": "^5.7.3", "vitest": "^3.1.1", - "ws": "^8.18.1" + "ws": "^8.18.1", + "zod-to-json-schema": "^3.24.6" }, "peerDependencies": { "@hono/node-server": "^1.14.0", diff --git a/rivetkit-typescript/packages/rivetkit/scripts/dump-asyncapi.ts b/rivetkit-typescript/packages/rivetkit/scripts/dump-asyncapi.ts new file mode 100644 index 0000000000..8087cf453c --- /dev/null +++ b/rivetkit-typescript/packages/rivetkit/scripts/dump-asyncapi.ts @@ -0,0 +1,327 @@ +import * as fs from "node:fs/promises"; +import { resolve } from "node:path"; +import { zodToJsonSchema } from "zod-to-json-schema"; +import { + ActionRequestSchema, + ActionResponseSchema, + ErrorSchema, + EventSchema, + InitSchema, + SubscriptionRequestSchema, + ToClientSchema, + ToServerSchema, +} from "@/schemas/client-protocol-zod/mod"; +import { VERSION } from "@/utils"; + +// Helper function to fix $ref paths from #/definitions to #/components/schemas +function fixRefs(obj: any): any { + if (Array.isArray(obj)) { + return obj.map(fixRefs); + } + if (obj && typeof obj === "object") { + const newObj: any = {}; + for (const [key, value] of Object.entries(obj)) { + if ( + key === "$ref" && + typeof value === "string" && + value.startsWith("#/definitions/") + ) { + newObj[key] = value.replace( + "#/definitions/", + "#/components/schemas/", + ); + } else if (key === "definitions") { + } else { + newObj[key] = fixRefs(value); + } + } + return newObj; + } + return obj; +} + +// Helper function to extract and flatten definitions into schemas +function extractSchemas(jsonSchema: any): Record { + const schemas: Record = {}; + + if (jsonSchema.definitions) { + for (const [name, schema] of Object.entries(jsonSchema.definitions)) { + schemas[name] = fixRefs(schema); + } + } + + return schemas; +} + +// Helper function to get schema without definitions wrapper +function getSchemaWithoutDefinitions(jsonSchema: any): any { + const result = { ...jsonSchema }; + delete result.$schema; + delete result.definitions; + + // If there's a $ref to definitions, replace it with the actual schema + if (result.$ref && result.$ref.startsWith("#/definitions/")) { + const defName = result.$ref.replace("#/definitions/", ""); + if (jsonSchema.definitions && jsonSchema.definitions[defName]) { + return fixRefs(jsonSchema.definitions[defName]); + } + } + + return fixRefs(result); +} + +function main() { + // Convert Zod schemas to JSON schemas + const toClientJsonSchema = zodToJsonSchema(ToClientSchema, { + name: "ToClient", + $refStrategy: "none", + }); + + const toServerJsonSchema = zodToJsonSchema(ToServerSchema, { + name: "ToServer", + $refStrategy: "none", + }); + + // Convert individual message schemas + const initJsonSchema = zodToJsonSchema(InitSchema, { + name: "Init", + $refStrategy: "none", + }); + + const errorJsonSchema = zodToJsonSchema(ErrorSchema, { + name: "Error", + $refStrategy: "none", + }); + + const actionResponseJsonSchema = zodToJsonSchema(ActionResponseSchema, { + name: "ActionResponse", + $refStrategy: "none", + }); + + const eventJsonSchema = zodToJsonSchema(EventSchema, { + name: "Event", + $refStrategy: "none", + }); + + const actionRequestJsonSchema = zodToJsonSchema(ActionRequestSchema, { + name: "ActionRequest", + $refStrategy: "none", + }); + + const subscriptionRequestJsonSchema = zodToJsonSchema( + SubscriptionRequestSchema, + { + name: "SubscriptionRequest", + $refStrategy: "none", + }, + ); + + // Build AsyncAPI v3.0.0 specification + const asyncApiSpec = { + asyncapi: "3.0.0", + info: { + title: "RivetKit WebSocket Protocol", + version: VERSION, + description: + "WebSocket protocol for bidirectional communication between RivetKit clients and actors", + }, + channels: { + "/gateway/{actorId}/connect": { + address: "/gateway/{actorId}/connect", + parameters: { + actorId: { + description: + "The unique identifier for the actor instance", + }, + }, + messages: { + toClient: { + $ref: "#/components/messages/ToClient", + }, + toServer: { + $ref: "#/components/messages/ToServer", + }, + }, + }, + }, + operations: { + sendToClient: { + action: "send", + channel: { + $ref: "#/channels/~1gateway~1{actorId}~1connect", + }, + messages: [ + { + $ref: "#/channels/~1gateway~1{actorId}~1connect/messages/toClient", + }, + ], + summary: "Send messages from server to client", + description: + "Messages sent from the RivetKit actor to connected clients", + }, + receiveFromClient: { + action: "receive", + channel: { + $ref: "#/channels/~1gateway~1{actorId}~1connect", + }, + messages: [ + { + $ref: "#/channels/~1gateway~1{actorId}~1connect/messages/toServer", + }, + ], + summary: "Receive messages from client", + description: + "Messages received by the RivetKit actor from connected clients", + }, + }, + components: { + messages: { + ToClient: { + name: "ToClient", + title: "Message To Client", + summary: "A message sent from the server to the client", + contentType: "application/json", + payload: getSchemaWithoutDefinitions(toClientJsonSchema), + examples: [ + { + name: "Init message", + summary: "Initial connection message", + payload: { + body: { + tag: "Init", + val: { + actorId: "actor_123", + connectionId: "conn_456", + }, + }, + }, + }, + { + name: "Error message", + summary: "Error response", + payload: { + body: { + tag: "Error", + val: { + group: "auth", + code: "unauthorized", + message: "Authentication failed", + actionId: null, + }, + }, + }, + }, + { + name: "Action response", + summary: "Response to an action request", + payload: { + body: { + tag: "ActionResponse", + val: { + id: "123", + output: { result: "success" }, + }, + }, + }, + }, + { + name: "Event", + summary: "Event broadcast to subscribed clients", + payload: { + body: { + tag: "Event", + val: { + name: "stateChanged", + args: { newState: "active" }, + }, + }, + }, + }, + ], + }, + ToServer: { + name: "ToServer", + title: "Message To Server", + summary: "A message sent from the client to the server", + contentType: "application/json", + payload: getSchemaWithoutDefinitions(toServerJsonSchema), + examples: [ + { + name: "Action request", + summary: "Request to execute an action", + payload: { + body: { + tag: "ActionRequest", + val: { + id: "123", + name: "updateState", + args: { key: "value" }, + }, + }, + }, + }, + { + name: "Subscription request", + summary: + "Request to subscribe/unsubscribe from an event", + payload: { + body: { + tag: "SubscriptionRequest", + val: { + eventName: "stateChanged", + subscribe: true, + }, + }, + }, + }, + ], + }, + }, + schemas: { + Init: { + ...getSchemaWithoutDefinitions(initJsonSchema), + description: + "Initial connection message sent from server to client", + }, + Error: { + ...getSchemaWithoutDefinitions(errorJsonSchema), + description: "Error message sent from server to client", + }, + ActionResponse: { + ...getSchemaWithoutDefinitions(actionResponseJsonSchema), + description: "Response to an action request", + }, + Event: { + ...getSchemaWithoutDefinitions(eventJsonSchema), + description: "Event broadcast to subscribed clients", + }, + ActionRequest: { + ...getSchemaWithoutDefinitions(actionRequestJsonSchema), + description: "Request to execute an action on the actor", + }, + SubscriptionRequest: { + ...getSchemaWithoutDefinitions( + subscriptionRequestJsonSchema, + ), + description: + "Request to subscribe or unsubscribe from an event", + }, + }, + }, + }; + + const outputPath = resolve( + import.meta.dirname, + "..", + "..", + "..", + "..", + "rivetkit-asyncapi", + "asyncapi.json", + ); + + fs.writeFile(outputPath, JSON.stringify(asyncApiSpec, null, 2)); + console.log("Dumped AsyncAPI spec to", outputPath); +} + +main(); diff --git a/rivetkit-typescript/packages/rivetkit/turbo.json b/rivetkit-typescript/packages/rivetkit/turbo.json index 1ffa803044..d72ae8ba2e 100644 --- a/rivetkit-typescript/packages/rivetkit/turbo.json +++ b/rivetkit-typescript/packages/rivetkit/turbo.json @@ -9,13 +9,25 @@ ], "dependsOn": ["build:schema"] }, + "dump-asyncapi": { + "inputs": [ + "package.json", + "packages/rivetkit/src/manager/router.ts" + ], + "dependsOn": ["build:schema"] + }, "build:schema": { "dependsOn": ["^build"], "inputs": ["schemas/**/*.bare"], "outputs": ["dist/schemas/**/*.ts"] }, "build": { - "dependsOn": ["^build", "dump-openapi", "build:schema"], + "dependsOn": [ + "^build", + "dump-openapi", + "dump-asyncapi", + "build:schema" + ], "inputs": [ "src/**", "tsconfig.json",