### Example Prompt for Momen Frontend Generation Source: https://github.com/privatejiangyaokai/momen-cursor-rules/blob/main/README.md This example prompt demonstrates how to instruct an AI assistant within Cursor to build a frontend application based on your Momen project. It includes specifying the Momen project name or `exId`, outlining basic requirements like e-commerce functionality and authentication, and providing necessary credentials like Stripe publishable keys. ```plaintext My Momen project is: my-ecommerce-app (or exId: abc123xyz) Build an ecommerce website based on the Momen project's backend structure. Use username authentication. + Other misc requirements e.g. Use Stripe publishable key: pk_test_51RQRPTCO2XREqHNZr8Vz0T1CNciMnXCM4I2qxb3ZYOi4GTHtbPnW8OJxGM9GR9L67jEngDUoBTMWOdr9W2AzMoKa00AzoEc7qr ``` -------------------------------- ### Database Insert Data Example (JSON) Source: https://context7.com/privatejiangyaokai/momen-cursor-rules/llms.txt An example JSON object containing the data for inserting a new post. It includes the post's title, content, author ID, cover image ID, and nested data for tags and meta information. ```json { "object": { "title": "Getting Started with Momen BaaS", "content": "This is a comprehensive guide to building applications with Momen as your backend...", "author_account": 1000000000000004, "cover_image_id": 1020000000000097, "post_tags": { "data": [ { "tag_tag": 1 }, { "tag_tag": 5 } ] }, "meta": { "data": { "seo_title": "Momen BaaS Tutorial - Complete Guide", "word_count": 1500 } } } } ``` -------------------------------- ### GraphQL Client Setup with Apollo and WebSocket Source: https://context7.com/privatejiangyaokai/momen-cursor-rules/llms.txt This section details how to configure an Apollo Client instance with WebSocket support for real-time subscriptions, essential for applications requiring live data updates. ```APIDOC ## GraphQL Client Setup with Apollo and WebSocket ### Description Configures Apollo Client with WebSocket support for subscriptions, enabling real-time data updates. ### Method N/A (This is a client-side setup guide) ### Endpoint N/A ### Parameters N/A ### Request Example ```typescript import { ApolloClient, InMemoryCache, HttpLink, split } from '@apollo/client'; import { getMainDefinition } from '@apollo/client/utilities'; import { WebSocketLink } from '@apollo/client/link/ws'; import { SubscriptionClient } from 'subscriptions-transport-ws'; const projectExId = 'your-project-exid'; const httpUrl = `https://villa.momen.app/zero/${projectExId}/api/graphql-v2`; const wssUrl = `wss://villa.momen.app/zero/${projectExId}/api/graphql-subscription`; export const createApolloClient = (token?: string) => { const wsClient = new SubscriptionClient(wssUrl, { reconnect: true, connectionParams: token ? { authToken: token } : {}, }); const wsLink = new WebSocketLink(wsClient); const splitLink = split( ({ query }) => { const definition = getMainDefinition(query); return ( definition.kind === 'OperationDefinition' && definition.operation === 'subscription' ); }, wsLink, new HttpLink({ uri: httpUrl, headers: token ? { Authorization: `Bearer ${token}` } : {}, }) ); return new ApolloClient({ link: splitLink, cache: new InMemoryCache(), }); }; // Usage const client = createApolloClient(userToken); ``` ### Response N/A ### Response Example N/A ``` -------------------------------- ### MDC File Format Example Source: https://github.com/privatejiangyaokai/momen-cursor-rules/blob/main/README.md Demonstrates the structure of a Cursor Rule file in `.mdc` format, which combines Markdown with frontmatter. The frontmatter includes metadata like a description and an `alwaysApply` flag, while the rest of the file contains the rule content in Markdown. This format helps AI understand when and how to apply specific rules. ```markdown --- description: Brief description of the rule alwaysApply: true # or false for contextual rules --- # Rule content in markdown... ``` -------------------------------- ### GraphQL Client Setup with Apollo and WebSocket Source: https://context7.com/privatejiangyaokai/momen-cursor-rules/llms.txt Configures Apollo Client to use both HTTP for queries/mutations and WebSocket for subscriptions. It requires the '@apollo/client' and 'subscriptions-transport-ws' packages. The function takes an optional authentication token and returns an ApolloClient instance ready for Momen BaaS interaction. ```typescript import { ApolloClient, InMemoryCache, HttpLink, split } from '@apollo/client'; import { getMainDefinition } from '@apollo/client/utilities'; import { WebSocketLink } from '@apollo/client/link/ws'; import { SubscriptionClient } from 'subscriptions-transport-ws'; const projectExId = 'your-project-exid'; const httpUrl = `https://villa.momen.app/zero/${projectExId}/api/graphql-v2`; const wssUrl = `wss://villa.momen.app/zero/${projectExId}/api/graphql-subscription`; export const createApolloClient = (token?: string) => { const wsClient = new SubscriptionClient(wssUrl, { reconnect: true, connectionParams: token ? { authToken: token } : {}, }); const wsLink = new WebSocketLink(wsClient); const splitLink = split( ({ query }) => { const definition = getMainDefinition(query); return ( definition.kind === 'OperationDefinition' && definition.operation === 'subscription' ); }, wsLink, new HttpLink({ uri: httpUrl, headers: token ? { Authorization: `Bearer ${token}` } : {}, }) ); return new ApolloClient({ link: splitLink, cache: new InMemoryCache(), }); }; // Usage const client = createApolloClient(userToken); ``` -------------------------------- ### Database Update Data Example (JSON) Source: https://context7.com/privatejiangyaokai/momen-cursor-rules/llms.txt An example JSON object for updating a post. It specifies the 'where' clause to target a post by its ID (167) and provides new values for the 'title' and 'content' fields in the '_set' object. ```json { "where": { "_eq": { "bigint_operand": { "left_operand": { "column": "id" }, "right_operand": { "literal": "167" } } } }, "set": { "title": "Updated: Getting Started with Momen BaaS", "content": "This is the updated comprehensive guide..." } } ``` -------------------------------- ### Database Query Filter Example (JSON) Source: https://context7.com/privatejiangyaokai/momen-cursor-rules/llms.txt An example JSON object representing variables for a GraphQL query. It specifies a limit of 10 posts and complex filtering criteria including title matching, creation date within the last year, and author ID. ```json { "limit": 10, "where": { "_and": [ { "_ilike": { "text_operand": { "left_operand": { "column": "title" }, "right_operand": { "literal": "%Summary%" } } } }, { "_gte": { "timestamptz_operand": { "left_operand": { "column": "created_at" }, "right_operand": { "adjust": { "timestamptz": { "nullary_func": "now" }, "increase": false, "years": { "literal": "1" } } } } } }, { "author": { "_eq": { "bigint_operand": { "left_operand": { "column": "id" }, "right_operand": { "literal": "1000000000000004" } } } } } ] } } ``` -------------------------------- ### Create Google Calendar Event via GraphQL Source: https://context7.com/privatejiangyaokai/momen-cursor-rules/llms.txt This GraphQL mutation defines the structure for creating a new event in a Google Calendar. It requires details such as summary, location, description, start and end times with time zones, attendees, and an authorization token. The response includes the event's ID, link, status, and other details if successful. ```graphql mutation CreateGoogleCalendarEvent( $summary: String! $location: String! $description: String! $startDateTime: String! $startTimeZone: String! $endDateTime: String! $endTimeZone: String! $attendees: [String!]! $authorization: String! ) { operation_lzb3ownk( body: { summary: $summary location: $location description: $description start: { dateTime: $startDateTime timeZone: $startTimeZone } end: { dateTime: $endDateTime timeZone: $endTimeZone } attendees: $attendees } Authorization: $authorization ) { responseCode field_200_json { id htmlLink status summary description start { dateTime timeZone } end { dateTime timeZone } creator { email self } } } } ``` -------------------------------- ### Momen Database GraphQL API Query Example Source: https://github.com/privatejiangyaokai/momen-cursor-rules/blob/main/README.md Illustrates how database tables map to GraphQL types and demonstrates query patterns for fetching data, including handling relationships and applying filters, sorting, and pagination. This rule helps the AI generate accurate GraphQL queries for interacting with the Momen database. ```graphql query GetPostsWithAuthors($limit: Int) { post(limit: $limit, order_by: {created_at: desc}) { id title content author { id name email } } } ``` -------------------------------- ### AI Agent with Structured JSON Output Source: https://context7.com/privatejiangyaokai/momen-cursor-rules/llms.txt This section demonstrates how to configure an AI agent to return type-safe structured JSON data. The example assumes a JSON schema is defined for the desired output. ```APIDOC ## AI Agent with Structured JSON Output ### Description Retrieves structured, type-safe JSON data from an AI agent. The agent is configured with a specific JSON schema for its output. ### Method POST (for mutation) / SUBSCRIBE (for result) ### Endpoint /graphql ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body (for CREATE_AI_CONVERSATION mutation) - **query** (String!) - The GraphQL mutation string. - **variables** (Map!) - **zaiConfigId** (String!) - The ID of the AI agent configuration. - **inputArgs** (Map!) - **prompt** (String!) - The user's prompt. ### Request Example (Initial Conversation Creation) ```json { "query": "mutation CreateAIConversation($inputArgs: Map_String_ObjectScalar!, $zaiConfigId: String!) { fz_zai_create_conversation(inputArgs: $inputArgs, zaiConfigId: $zaiConfigId) }", "variables": { "zaiConfigId": "your_structured_config_id", "inputArgs": { "prompt": "Generate a summary of the latest news and provide a relevant link." } } } ``` ### Response (from LISTEN_AI_RESULT subscription) #### Success Response (200) - **data** (Object) - **fz_zai_listen_conversation_result** (Object) - **conversationId** (Long) - The ID of the conversation. - **status** (String) - The status of the conversation (expected 'COMPLETED'). - **data** (Object) - The structured JSON output from the AI, matching the defined schema. - **httpLink** (String) - A relevant HTTP link. - **reasoning** (String) - The reasoning behind the AI's output. #### Response Example ```json { "data": { "fz_zai_listen_conversation_result": { "conversationId": 987654321, "status": "COMPLETED", "reasoningContent": null, "images": [], "data": { "httpLink": "http://example.com/news/latest", "reasoning": "The AI found the latest news summary and a relevant link." } } } } ``` ``` -------------------------------- ### Momen Backend Architecture GraphQL Endpoints Source: https://github.com/privatejiangyaokai/momen-cursor-rules/blob/main/README.md Defines the core architecture understanding for the Momen backend, including the HTTP and WebSocket endpoints for the GraphQL API. It also covers Apollo Client setup, authentication token handling, and project structure conventions. This rule is always applied to ensure the AI has a foundational understanding of the Momen environment. ```typescript // HTTP endpoint https://villa.momen.app/zero/{projectExId}/api/graphql-v2 // WebSocket endpoint wss://villa.momen.app/zero/{projectExId}/api/graphql-subscription ``` -------------------------------- ### POST /filePresignedUrl Source: https://context7.com/privatejiangyaokai/momen-cursor-rules/llms.txt Generates a pre-signed URL for uploading a binary file with associated metadata. ```APIDOC ## POST /filePresignedUrl ### Description Generates a pre-signed URL for uploading a binary file. This endpoint is used to obtain the necessary URL and headers to perform a direct PUT request to upload the file content to storage. ### Method POST ### Endpoint /filePresignedUrl ### Parameters #### Query Parameters - **md5** (String!) - Required - The MD5 hash of the file in Base64 format. - **format** (MediaFormat!) - Required - The media format of the file (e.g., 'JPEG', 'PNG', 'MP4'). - **name** (String) - Optional - The name of the file. - **suffix** (String) - Optional - The file extension (e.g., 'jpg', 'mp4'). - **sizeBytes** (Int) - Optional - The size of the file in bytes. - **acl** (CannedAccessControlList) - Optional - The access control list for the uploaded file (e.g., 'PRIVATE', 'PUBLIC_READ'). ### Request Example ```json { "query": "mutation GetFileUploadUrl($md5: String!, $format: MediaFormat!, $name: String, $suffix: String, $sizeBytes: Int, $acl: CannedAccessControlList) { filePresignedUrl(md5Base64: $md5, format: $format, name: $name, suffix: $suffix, sizeBytes: $sizeBytes, acl: $acl) { fileId uploadHeaders uploadUrl } }", "variables": { "md5": "your_file_md5_base64", "format": "JPEG", "name": "example.jpg", "suffix": "jpg", "sizeBytes": 1024, "acl": "PRIVATE" } } ``` ### Response #### Success Response (200) - **fileId** (Int) - The unique identifier for the uploaded file. - **uploadHeaders** (Object) - Headers required for the upload request. - **uploadUrl** (String) - The pre-signed URL to which the file should be uploaded. #### Response Example ```json { "data": { "filePresignedUrl": { "fileId": 12345, "uploadHeaders": { "Content-Type": "image/jpeg", "x-amz-acl": "private" }, "uploadUrl": "https://your-storage-url.com/path/to/file?signature=..." } } } ``` ``` -------------------------------- ### POST /videoPresignedUrl Source: https://context7.com/privatejiangyaokai/momen-cursor-rules/llms.txt Generates a pre-signed URL for uploading a video file. ```APIDOC ## POST /videoPresignedUrl ### Description Generates a pre-signed URL specifically for uploading video files. This endpoint is crucial for handling video uploads efficiently by providing a direct upload URL and necessary headers. ### Method POST ### Endpoint /videoPresignedUrl ### Parameters #### Query Parameters - **md5** (String!) - Required - The MD5 hash of the video in Base64 format. - **format** (MediaFormat!) - Required - The video format (e.g., 'MP4', 'MOV'). - **acl** (CannedAccessControlList) - Optional - The access control list for the uploaded video (e.g., 'PUBLIC_READ'). ### Request Example ```json { "query": "mutation GetVideoUploadUrl($md5: String!, $format: MediaFormat!, $acl: CannedAccessControlList) { videoPresignedUrl(videoMd5Base64: $md5, videoFormat: $format, acl: $acl) { videoId uploadUrl uploadHeaders } }", "variables": { "md5": "your_video_md5_base64", "format": "MP4", "acl": "PUBLIC_READ" } } ``` ### Response #### Success Response (200) - **videoId** (Int) - The unique identifier for the uploaded video. - **uploadUrl** (String) - The pre-signed URL for video upload. - **uploadHeaders** (Object) - Headers required for the video upload request. #### Response Example ```json { "data": { "videoPresignedUrl": { "videoId": 67890, "uploadUrl": "https://your-storage-url.com/path/to/video?signature=...", "uploadHeaders": { "Content-Type": "video/mp4" } } } } ``` ``` -------------------------------- ### Generated TypeScript Post Type Source: https://github.com/privatejiangyaokai/momen-cursor-rules/blob/main/README.md An example of a TypeScript type definition for a 'Post' entity, automatically generated by AI from a GraphQL schema. This ensures type safety in frontend applications interacting with the Momen backend. ```typescript type Post = { id: number; title: string; content: string; author: { id: number; name: string; }; }; ``` -------------------------------- ### Copy Momen Cursor Rules to Project Directory Source: https://github.com/privatejiangyaokai/momen-cursor-rules/blob/main/README.md This Bash command copies the entire `.cursor` directory from the cloned Momen Cursor Rules repository into your project's root directory. This action makes the rule files available for AI assistants like Cursor to utilize, enabling them to understand and interact with your Momen backend. ```bash cp -r .cursor /path/to/your/project/ ``` -------------------------------- ### Upload Video using GraphQL and Fetch API Source: https://context7.com/privatejiangyaokai/momen-cursor-rules/llms.txt Handles video uploads by first obtaining a presigned URL via a GraphQL mutation. It calculates the video's MD5 hash and then uses the Fetch API to upload the video data. The function returns the video ID upon successful completion. Dependencies include CryptoJS for MD5 hashing and a GraphQL client. ```typescript const GET_VIDEO_UPLOAD_URL = gql` mutation GetVideoUploadUrl( $md5: String! $format: MediaFormat! $acl: CannedAccessControlList ) { videoPresignedUrl( videoMd5Base64: $md5 videoFormat: $format acl: $acl ) { videoId uploadUrl uploadHeaders } } `; async function uploadVideo(file: File): Promise { const fileBuffer = await file.arrayBuffer(); const wordArray = CryptoJS.lib.WordArray.create(fileBuffer); const md5Base64 = CryptoJS.MD5(wordArray).toString(CryptoJS.enc.Base64); const format = file.name.split('.').pop()?.toUpperCase() || 'MP4'; const { data } = await client.mutate({ mutation: GET_VIDEO_UPLOAD_URL, variables: { md5: md5Base64, format, acl: 'PUBLIC_READ' } }); const { videoId, uploadUrl, uploadHeaders } = data.videoPresignedUrl; const headers: Record = {}; if (uploadHeaders) { Object.entries(uploadHeaders).forEach(([key, value]) => { headers[key] = value as string; }); } await fetch(uploadUrl, { method: 'PUT', body: file, headers }); return videoId; } ``` -------------------------------- ### Clone Momen Cursor Rules Repository Source: https://github.com/privatejiangyaokai/momen-cursor-rules/blob/main/README.md This Bash command clones the Momen Cursor Rules repository from GitHub. After cloning, navigate into the repository directory to copy the rules into your project. This is the initial step to integrate the provided Cursor rules into your development workflow. ```bash git clone https://github.com/privatejiangyaokai/momen-cursor-rules.git cd momen-cursor-rules ``` -------------------------------- ### Configure Momen MCP Server for Cursor Source: https://github.com/privatejiangyaokai/momen-cursor-rules/blob/main/README.md This JSON configuration enables Cursor's Model Context Protocol (MCP) server to automatically fetch your Momen project's latest schema. It specifies the command to run the Momen MCP server and its arguments. This enhances AI's understanding of your project structure but is optional. ```json { "mcpServers": { "momen": { "command": "npx", "args": [ "-y", "momen-mcp@latest" ] } } } ``` -------------------------------- ### Upload File using GraphQL and Fetch API Source: https://context7.com/privatejiangyaokai/momen-cursor-rules/llms.txt Generates a presigned URL for file uploads using a GraphQL mutation, calculates the MD5 hash of the file, and then uploads the file content using the Fetch API. It handles necessary headers and returns the file ID upon successful upload. Dependencies include CryptoJS for MD5 hashing and a GraphQL client. ```typescript const GET_FILE_UPLOAD_URL = gql` mutation GetFileUploadUrl( $md5: String! $format: MediaFormat! $name: String $suffix: String $sizeBytes: Int $acl: CannedAccessControlList ) { filePresignedUrl( md5Base64: $md5 format: $format name: $name suffix: $suffix sizeBytes: $sizeBytes acl: $acl ) { fileId uploadHeaders uploadUrl } } `; async function uploadFile(file: File): Promise { const fileBuffer = await file.arrayBuffer(); const wordArray = CryptoJS.lib.WordArray.create(fileBuffer); const md5Base64 = CryptoJS.MD5(wordArray).toString(CryptoJS.enc.Base64); const extension = file.name.split('.').pop()?.toUpperCase(); const format = extension || 'OTHER'; const { data } = await client.mutate({ mutation: GET_FILE_UPLOAD_URL, variables: { md5: md5Base64, format, name: file.name, suffix: extension?.toLowerCase(), sizeBytes: file.size, acl: 'PRIVATE' } }); const { fileId, uploadUrl, uploadHeaders } = data.filePresignedUrl; const headers: Record = {}; if (uploadHeaders) { Object.entries(uploadHeaders).forEach(([key, value]) => { headers[key] = value as string; }); } await fetch(uploadUrl, { method: 'PUT', body: file, headers }); return fileId; } ``` -------------------------------- ### Binary Asset Upload (Images) API Source: https://context7.com/privatejiangyaokai/momen-cursor-rules/llms.txt This API provides a two-step process for uploading binary assets, specifically images. It involves obtaining a presigned URL for upload and then uploading the file content to that URL. ```APIDOC ## POST /graphql (imagePresignedUrl) ### Description Generates a presigned URL for uploading an image and provides necessary headers. ### Method POST ### Endpoint /graphql ### Parameters #### Query Parameters None #### Request Body - **imgMd5Base64** (String!) - The MD5 hash of the image file in Base64 encoding. - **imageSuffix** (MediaFormat!) - The format/suffix of the image (e.g., 'PNG', 'JPEG'). - **acl** (CannedAccessControlList) - Optional. The access control list for the uploaded image (e.g., 'PRIVATE', 'PUBLIC_READ'). Defaults to 'PRIVATE'. ### Request Example ```json { "query": "mutation GetImageUploadUrl($md5: String!, $suffix: MediaFormat!, $acl: CannedAccessControlList) {\n imagePresignedUrl(imgMd5Base64: $md5, imageSuffix: $suffix, acl: $acl) {\n imageId\n uploadUrl\n uploadHeaders\n }\n}", "variables": { "md5": "your_base64_md5_hash", "suffix": "PNG", "acl": "PRIVATE" } } ``` ### Response #### Success Response (200) - **imageId** (Int) - The unique ID assigned to the image. - **uploadUrl** (String) - The presigned URL to which the image file should be uploaded. - **uploadHeaders** (JSON) - A JSON object containing headers required for the upload request. #### Response Example ```json { "data": { "imagePresignedUrl": { "imageId": 123, "uploadUrl": "https://your-s3-bucket.s3.amazonaws.com/image.png?AWSAccessKeyId=...", "uploadHeaders": { "Content-Type": "image/png", "x-amz-acl": "private" } } } } ``` ## PUT [uploadUrl] ### Description Uploads the image file to the presigned URL obtained from the `imagePresignedUrl` mutation. ### Method PUT ### Endpoint [The `uploadUrl` returned from the `imagePresignedUrl` mutation] ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **file** (File) - The image file to upload. ### Request Example ```bash curl -X PUT "[uploadUrl]" \ -H "Content-Type: image/png" \ -H "x-amz-acl: private" \ --data-binary @/path/to/your/image.png ``` ### Response #### Success Response (200) Typically returns a 200 OK status upon successful upload. No specific JSON response body is usually returned by the presigned URL endpoint itself. ``` -------------------------------- ### Backend Actionflow for Order Creation (TypeScript) Source: https://github.com/privatejiangyaokai/momen-cursor-rules/blob/main/README.md Illustrates the recommended backend approach for handling complex business logic like order creation with inventory checks using Momen's actionflow mechanism. This promotes cleaner frontend code and centralized logic. ```typescript const createOrder = async () => { await invokeActionflow('create_order_with_checks', { product_id: productId, quantity: 1 }); }; ``` -------------------------------- ### User Authentication with Email Verification Source: https://context7.com/privatejiangyaokai/momen-cursor-rules/llms.txt Handles user registration and login flows using Momen's email authentication. It requires the 'graphql' package for gql tag. The flow involves sending a verification code via email for registration, then authenticating with the provided code and password. Login bypasses the verification code step. ```typescript import { gql } from '@apollo/client'; // Step 1: Send verification code for registration const SEND_VERIFICATION = gql` mutation SendVerificationCodeToEmail( $email: String! $verificationEnumType: verificationEnumType! ) { sendVerificationCodeToEmail( email: $email verificationEnumType: $verificationEnumType ) } `; // Step 2: Register with verification code const AUTHENTICATE_EMAIL = gql` mutation AuthenticateWithEmail( $email: String! $password: String! $verificationCode: String $register: Boolean! ) { authenticateWithEmail( email: $email password: $password verificationCode: $verificationCode register: $register ) { account { id permissionRoles } jwt { token } } } `; // Registration flow async function registerUser(email: string, password: string) { try { // Send verification code await client.mutate({ mutation: SEND_VERIFICATION, variables: { email, verificationEnumType: 'SIGN_UP' } }); // User enters code from email const verificationCode = prompt('Enter verification code:'); // Register with code const { data } = await client.mutate({ mutation: AUTHENTICATE_EMAIL, variables: { email, password, verificationCode, register: true } }); const token = data.authenticateWithEmail.jwt.token; localStorage.setItem('authToken', token); return data.authenticateWithEmail.account; } catch (error) { console.error('Registration failed:', error); throw error; } } // Login flow (no verification needed) async function loginUser(email: string, password: string) { const { data } = await client.mutate({ mutation: AUTHENTICATE_EMAIL, variables: { email, password, register: false } }); const token = data.authenticateWithEmail.jwt.token; localStorage.setItem('authToken', token); return data.authenticateWithEmail.account; } ``` -------------------------------- ### Retrieve Post with Media using GraphQL and TypeScript Source: https://context7.com/privatejiangyaokai/momen-cursor-rules/llms.txt This snippet defines a GraphQL query to fetch a post by its ID, including its cover image with specified resize options and attachments. It then uses the `useQuery` hook from Apollo Client to execute the query and display the post content, cover image, and downloadable attachments in a React component. The query utilizes `PUBLIC_READ` and `AUTHENTICATE_READ` ACLs for accessing binary assets. ```typescript const GET_POST_WITH_MEDIA = gql` query GetPostWithMedia($id: bigint!) { post_by_pk(id: $id) { id title content cover_image { id url(acl: PUBLIC_READ, option: { resize: { width: 800, height: 600, mode: FIT } }) external } attachments { file { id name sizeBytes suffix url(acl: AUTHENTICATE_READ, contentType: APPLICATION_FORM_URLENCODED) } } } } `; function PostWithMedia({ postId }: { postId: number }) { const { data, loading } = useQuery(GET_POST_WITH_MEDIA, { variables: { id: postId } }); if (loading) return
Loading...
; const post = data.post_by_pk; return ( ); } ``` -------------------------------- ### Real-Time Subscriptions for Live Updates Source: https://context7.com/privatejiangyaokai/momen-cursor-rules/llms.txt This endpoint provides real-time post notifications using WebSocket subscriptions. ```APIDOC ## Real-Time Subscriptions for Live Updates ### Description WebSocket subscription for real-time post notifications. ### Method SUBSCRIPTION ### Endpoint (WebSocket Endpoint) ### Parameters #### Query Parameters - **authorId** (bigint) - Required - The ID of the author to subscribe to. ### Response #### Success Response (200) - **post** (array) - An array of post objects. - **id** (ID) - The unique identifier for the post. - **title** (String) - The title of the post. - **content** (String) - The content of the post. - **created_at** (DateTime) - The timestamp when the post was created. - **author** (Object) - Information about the post's author. - **name** (String) - The name of the author. - **username** (String) - The username of the author. ### Response Example ```json { "data": { "post": [ { "id": "1", "title": "First Post", "content": "This is the content of the first post.", "created_at": "2023-10-27T10:00:00Z", "author": { "name": "John Doe", "username": "johndoe" } } ] } } ``` ``` -------------------------------- ### Markdown Frontmatter for Cursor Rules Source: https://github.com/privatejiangyaokai/momen-cursor-rules/blob/main/README.md Defines the frontmatter structure for new `.mdc` rule files. It includes a 'description' field for a brief explanation and an 'alwaysApply' boolean to control rule application. This frontmatter is essential for the Cursor AI assistant to understand and apply the rule correctly. ```markdown --- description: Brief description alwaysApply: true/false --- # Rule Content ``` -------------------------------- ### User Authentication with Email Verification Source: https://context7.com/privatejiangyaokai/momen-cursor-rules/llms.txt Provides GraphQL mutations for handling user registration and login flows, including email verification. ```APIDOC ## User Authentication with Email Verification ### Description Handles user registration and login using email and password, incorporating an email verification step for new sign-ups. ### Method N/A (This section provides GraphQL mutations for client-side implementation) ### Endpoint N/A ### Parameters N/A ### Request Example ```typescript import { gql } from '@apollo/client'; // Step 1: Send verification code for registration const SEND_VERIFICATION = gql` mutation SendVerificationCodeToEmail( $email: String! $verificationEnumType: verificationEnumType! ) { sendVerificationCodeToEmail( email: $email verificationEnumType: $verificationEnumType ) } `; // Step 2: Register with verification code const AUTHENTICATE_EMAIL = gql` mutation AuthenticateWithEmail( $email: String! $password: String! $verificationCode: String $register: Boolean! ) { authenticateWithEmail( email: $email password: $password verificationCode: $verificationCode register: $register ) { account { id permissionRoles } jwt { token } } } `; // Registration flow async function registerUser(email: string, password: string) { try { // Send verification code await client.mutate({ mutation: SEND_VERIFICATION, variables: { email, verificationEnumType: 'SIGN_UP' } }); // User enters code from email const verificationCode = prompt('Enter verification code:'); // Register with code const { data } = await client.mutate({ mutation: AUTHENTICATE_EMAIL, variables: { email, password, verificationCode, register: true } }); const token = data.authenticateWithEmail.jwt.token; localStorage.setItem('authToken', token); return data.authenticateWithEmail.account; } catch (error) { console.error('Registration failed:', error); throw error; } } // Login flow (no verification needed) async function loginUser(email: string, password: string) { const { data } = await client.mutate({ mutation: AUTHENTICATE_EMAIL, variables: { email, password, register: false } }); const token = data.authenticateWithEmail.jwt.token; localStorage.setItem('authToken', token); return data.authenticateWithEmail.account; } ``` ### Response #### Success Response (200) - **account** (object) - Contains user account details including ID and permission roles. - **jwt** (object) - Contains the authentication token. - **token** (string) - The JWT token for subsequent authenticated requests. #### Response Example ```json { "data": { "authenticateWithEmail": { "account": { "id": "user-id-123", "permissionRoles": ["user"] }, "jwt": { "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." } } } } ``` ### Error Handling - **400 Bad Request**: Invalid credentials, incorrect verification code, or missing fields. - **401 Unauthorized**: User not authenticated. - **500 Internal Server Error**: Server-side issue. ``` -------------------------------- ### Frontend Order Creation Logic (TypeScript) Source: https://github.com/privatejiangyaokai/momen-cursor-rules/blob/main/README.md Demonstrates a suboptimal frontend approach for creating an order with inventory checks and subsequent actions, highlighting the need for backend offloading. This pattern is discouraged in favor of backend actionflows for complex logic. ```typescript const createOrderWithInventoryCheck = async () => { const inventory = await checkInventory(productId); if (inventory > 0) { const order = await createOrder(...); await reduceInventory(productId); await sendEmail(...); } }; ``` -------------------------------- ### Invoke AI Agent with Streaming Output (TypeScript) Source: https://context7.com/privatejiangyaokai/momen-cursor-rules/llms.txt Initiates an AI conversation with multi-modal inputs (text, images, video) and subscribes to receive streaming text responses. It accumulates response chunks until the 'COMPLETED' status is received. Requires a GraphQL client configured for mutations and subscriptions. ```typescript const CREATE_AI_CONVERSATION = gql` mutation CreateAIConversation( $inputArgs: Map_String_ObjectScalar! $zaiConfigId: String! ) { fz_zai_create_conversation( inputArgs: $inputArgs zaiConfigId: $zaiConfigId ) } `; const LISTEN_AI_RESULT = gql` subscription ListenAIResult($conversationId: Long!) { fz_zai_listen_conversation_result(conversationId: $conversationId) { conversationId status reasoningContent images { id url } data } } `; async function invokeAIAgent( configId: string, textInput: string, imageIds: number[], videoId: number ) { // Create conversation with multi-modal inputs const { data: convData } = await client.mutate({ mutation: CREATE_AI_CONVERSATION, variables: { zaiConfigId: configId, inputArgs: { mh4cjjcf: textInput, // text input mh4cjoof_id: imageIds, // image array (note _id suffix) mgzzufo2_id: videoId // video input (note _id suffix) } } }); const conversationId = convData.fz_zai_create_conversation; // Subscribe to streaming results return new Promise((resolve, reject) => { let fullResponse = ''; const subscription = client.subscribe({ query: LISTEN_AI_RESULT, variables: { conversationId } }).subscribe({ next: ({ data }) => { const result = data.fz_zai_listen_conversation_result; if (result.status === 'STREAMING') { // Accumulate streaming chunks fullResponse += result.data; console.log('Streaming:', result.data); } else if (result.status === 'COMPLETED') { // Final complete response subscription.unsubscribe(); resolve({ text: result.data, images: result.images, reasoning: result.reasoningContent }); } }, error: (err) => { subscription.unsubscribe(); reject(err); } }); }); } ``` -------------------------------- ### Synchronous Actionflow Execution for Order Creation (GraphQL & TypeScript) Source: https://context7.com/privatejiangyaokai/momen-cursor-rules/llms.txt Executes backend workflows synchronously with transactional guarantees using a GraphQL mutation. This function invokes an action flow to create an order and returns the result immediately. It requires a GraphQL client and depends on the `fz_invoke_action_flow` mutation. ```graphql mutation CreateOrder($args: Json!) { fz_invoke_action_flow( actionFlowId: "d3ea4f95-5d34-46e1-b940-91c4028caff5" versionId: 3 args: $args ) } ``` ```typescript async function createOrder(courseId: number, userId: number) { const { data } = await client.mutate({ mutation: CREATE_ORDER, variables: { args: { course_id: courseId, user_id: userId, quantity: 1 } } }); // Synchronous actionflow returns result immediately console.log('Order created:', data.fz_invoke_action_flow); return data.fz_invoke_action_flow; } ``` -------------------------------- ### Stripe One-Time Payment Source: https://context7.com/privatejiangyaokai/momen-cursor-rules/llms.txt This API integrates with Stripe to process one-time credit card payments for orders. ```APIDOC ## POST /api/stripe/payment ### Description Initiates a one-time payment process using Stripe. This endpoint generates a payment client secret required for the client-side Stripe Elements integration. ### Method POST ### Endpoint /api/stripe/payment ### Parameters #### Request Body - **orderId** (long) - Required - The unique identifier for the order to be paid. - **currency** (string) - Required - The currency code for the payment (e.g., 'USD'). - **amount** (BigDecimal) - Required - The amount to be paid, typically in the smallest currency unit (e.g., cents for USD). ### Request Example ```json { "orderId": 12345, "currency": "USD", "amount": 10000 // Represents $100.00 } ``` ### Response #### Success Response (200) - **paymentClientSecret** (string) - The client secret required to confirm the Stripe payment on the client side. - **stripeReadableAmount** (string) - A human-readable representation of the payment amount (e.g., "$100.00"). #### Response Example ```json { "paymentClientSecret": "pi_..._secret_...", "stripeReadableAmount": "$100.00" } ``` ``` -------------------------------- ### Upload Image with Presigned URL (TypeScript) Source: https://context7.com/privatejiangyaokai/momen-cursor-rules/llms.txt This function handles the binary asset upload of images in a two-step process. It first calculates the MD5 hash of the file and determines its format, then requests a presigned URL from the server. Finally, it uploads the file directly to the presigned URL using a PUT request and returns the image ID. Dependencies include CryptoJS for MD5 hashing and a GraphQL client. ```typescript import CryptoJS from 'crypto-js'; const GET_IMAGE_UPLOAD_URL = gql` mutation GetImageUploadUrl( $md5: String! $suffix: MediaFormat! $acl: CannedAccessControlList ) { imagePresignedUrl( imgMd5Base64: $md5 imageSuffix: $suffix acl: $acl ) { imageId uploadUrl uploadHeaders } } `; async function uploadImage(file: File): Promise { // Step 1: Calculate MD5 hash const fileBuffer = await file.arrayBuffer(); const wordArray = CryptoJS.lib.WordArray.create(fileBuffer); const md5Hash = CryptoJS.MD5(wordArray); const md5Base64 = md5Hash.toString(CryptoJS.enc.Base64); // Determine format from file extension const suffix = file.name.split('.').pop()?.toUpperCase() as any; // Step 2: Get presigned URL const { data } = await client.mutate({ mutation: GET_IMAGE_UPLOAD_URL, variables: { md5: md5Base64, suffix: suffix || 'PNG', acl: 'PRIVATE' } }); const { imageId, uploadUrl, uploadHeaders } = data.imagePresignedUrl; // Step 3: Upload file to presigned URL const headers: Record = {}; if (uploadHeaders) { Object.entries(uploadHeaders).forEach(([key, value]) => { headers[key] = value as string; }); } await fetch(uploadUrl, { method: 'PUT', body: file, headers }); // Step 4: Return image ID for use in mutations return imageId; } // Usage: Upload and attach to post async function createPostWithImage(title: string, content: string, imageFile: File) { const imageId = await uploadImage(imageFile); const { data } = await client.mutate({ mutation: INSERT_POST, variables: { object: { title, content, cover_image_id: imageId // Use returned ID } } }); return data.insert_post_one; } ``` -------------------------------- ### Continuing AI Agent Conversations Source: https://context7.com/privatejiangyaokai/momen-cursor-rules/llms.txt This API allows for multi-turn conversations by sending follow-up messages within an existing conversation context. The subscription to listen for results remains the same. ```APIDOC ## POST /graphql (fz_zai_send_ai_message) ### Description Sends a follow-up message in an ongoing AI conversation, maintaining context for multi-turn interactions. ### Method POST ### Endpoint /graphql ### Parameters #### Query Parameters None #### Request Body - **query** (String!) - The GraphQL mutation string for continuing a conversation. - **variables** (Map!) - **conversationId** (Long!) - The ID of the existing conversation. - **text** (String!) - The follow-up message text. ### Request Example ```json { "query": "mutation ContinueConversation($conversationId: Long!, $text: String!) { fz_zai_send_ai_message(conversationId: $conversationId, text: $text) }", "variables": { "conversationId": 123456789, "text": "Can you elaborate on that?" } } ``` ### Response #### Success Response (200) - **data** (Object) - **fz_zai_send_ai_message** (Boolean) - Indicates if the message was successfully sent (typically true). #### Response Example ```json { "data": { "fz_zai_send_ai_message": true } } ``` ### Note: After sending a follow-up message using `fz_zai_send_ai_message`, you should continue to use the `fz_zai_listen_conversation_result` subscription (as described in 'AI Agent Invocation with Streaming Output') to receive the AI's response to the follow-up message. The subscription automatically continues listening to the same `conversationId`. ```