# generateText Source: https://docs.modelence.com/api-reference/@modelence/ai/functions/generateText [API Reference](/api-reference/@modelence/ai/functions/../../../index) / [@modelence/ai](/api-reference/@modelence/ai/functions/../index) / generateText > **generateText**(`options`): `Promise`\<`GenerateTextResult`\<`ToolSet`, `Output`\<`any`, `any`, `any`>>> Defined in: [index.ts:77](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/ai/src/index.ts#L77) Generates text using AI models with built-in Modelence configuration and telemetry. This is a wrapper around the AI SDK's generateText function that automatically configures providers using Modelence's server-side configuration system. ## Example ```typescript theme={null} import { generateText } from '@modelence/ai'; const response = await generateText({ provider: 'anthropic', model: 'claude-sonnet-4-6', messages: [ { role: 'user', content: 'Write a haiku about programming' } ], temperature: 0.7 }); console.log(response.text); ``` ## Parameters | Parameter | Type | Description | | --------- | --------------------------------------------------------------------------------------------------- | ----------------------------------------- | | `options` | [`GenerateTextOptions`](/api-reference/@modelence/ai/functions/../type-aliases/GenerateTextOptions) | Configuration options for text generation | ## Returns `Promise`\<`GenerateTextResult`\<`ToolSet`, `Output`\<`any`, `any`, `any`>>> A promise that resolves to the generated text result # @modelence/ai Source: https://docs.modelence.com/api-reference/@modelence/ai/index [API Reference](/api-reference/@modelence/ai/../../index) / @modelence/ai ## Type Aliases * [GenerateTextOptions](/api-reference/@modelence/ai/type-aliases/GenerateTextOptions) ## Functions * [generateText](/api-reference/@modelence/ai/functions/generateText) # GenerateTextOptions Source: https://docs.modelence.com/api-reference/@modelence/ai/type-aliases/GenerateTextOptions [API Reference](/api-reference/@modelence/ai/type-aliases/../../../index) / [@modelence/ai](/api-reference/@modelence/ai/type-aliases/../index) / GenerateTextOptions > **GenerateTextOptions** = `ModelenceGenerateTextOptions`\<`OriginalGenerateTextParams`> Defined in: [index.ts:28](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/ai/src/index.ts#L28) Options for the Modelence generateText function. This type extends all the standard AI SDK generateText options, but replaces the model parameter with separate provider and model parameters. # @modelence/auth-ui Source: https://docs.modelence.com/api-reference/@modelence/auth-ui/index [API Reference](/api-reference/@modelence/auth-ui/../../index) / @modelence/auth-ui # @modelence/auth-ui Authentication UI components for Modelence. ## Installation ```sh theme={null} npm install @modelence/auth-ui ``` ## Setup Add this package to your `tailwind.config.js` content paths: ```js theme={null} /** @type {import('tailwindcss').Config} */ module.exports = { content: [ ..., "./node_modules/@modelence/auth-ui/dist/**/*.{js,ts,jsx,tsx}", ], theme: { extend: {}, }, plugins: [], } ``` That's it! The components use standard Tailwind classes and will work with your existing Tailwind setup. ## Usage ```tsx theme={null} import { LoginForm } from '@modelence/auth-ui'; function AuthPage() { return ( ( {children} )} /> ); } ``` ## Customization You can customize the appearance using className props: ```tsx theme={null} ( {children} )} /> ``` ## Framework Support This library is framework-agnostic but includes special support for navigation: ### Next.js ```tsx theme={null} import Link from 'next/link'; import { LoginForm } from '@modelence/auth-ui'; ( {children} )} /> ``` ### React Router ```tsx theme={null} import { Link } from 'react-router-dom'; import { LoginForm } from '@modelence/auth-ui'; ( {children} )} /> ``` ## Development To build the package: ```sh theme={null} npm run build ``` To watch for changes during development: ```sh theme={null} npm run dev ``` # sendEmail Source: https://docs.modelence.com/api-reference/@modelence/aws-ses/functions/sendEmail [API Reference](/api-reference/@modelence/aws-ses/functions/../../../index) / [@modelence/aws-ses](/api-reference/@modelence/aws-ses/functions/../index) / sendEmail > **sendEmail**(`payload`): `Promise`\<`void`> Defined in: [index.ts:83](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/aws-ses/src/index.ts#L83) Sends an email via Resend. ## Example ```ts theme={null} import { sendEmail } from '@modelence/aws-ses'; sendEmail({ from: 'test@example.com', to: 'test@example.com', subject: 'Test Email', html: '

Hello World

' }) ``` ## Parameters | Parameter | Type | Description | | --------- | ------------------------------------------------------------------------------------------ | ------------------------- | | `payload` | [`EmailPayload`](/api-reference/@modelence/aws-ses/functions/../type-aliases/EmailPayload) | The email payload object. | ## Returns `Promise`\<`void`> # @modelence/aws-ses Source: https://docs.modelence.com/api-reference/@modelence/aws-ses/index [API Reference](/api-reference/@modelence/aws-ses/../../index) / @modelence/aws-ses ## Type Aliases * [EmailAttachment](/api-reference/@modelence/aws-ses/type-aliases/EmailAttachment) * [EmailPayload](/api-reference/@modelence/aws-ses/type-aliases/EmailPayload) ## Variables * [default](/api-reference/@modelence/aws-ses/variables/default) ## Functions * [sendEmail](/api-reference/@modelence/aws-ses/functions/sendEmail) # EmailAttachment Source: https://docs.modelence.com/api-reference/@modelence/aws-ses/type-aliases/EmailAttachment [API Reference](/api-reference/@modelence/aws-ses/type-aliases/../../../index) / [@modelence/aws-ses](/api-reference/@modelence/aws-ses/type-aliases/../index) / EmailAttachment > **EmailAttachment** = `object` Defined in: [index.ts:10](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/aws-ses/src/index.ts#L10) ## Properties | Property | Type | Defined in | | ------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | | `content` | `Buffer` \| `string` | [index.ts:12](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/aws-ses/src/index.ts#L12) | | `contentType` | `string` | [index.ts:13](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/aws-ses/src/index.ts#L13) | | `filename` | `string` | [index.ts:11](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/aws-ses/src/index.ts#L11) | # EmailPayload Source: https://docs.modelence.com/api-reference/@modelence/aws-ses/type-aliases/EmailPayload [API Reference](/api-reference/@modelence/aws-ses/type-aliases/../../../index) / [@modelence/aws-ses](/api-reference/@modelence/aws-ses/type-aliases/../index) / EmailPayload > **EmailPayload** = `object` & \{ `html`: `string`; } | \{ `text`: `string`; } Defined in: [index.ts:16](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/aws-ses/src/index.ts#L16) ## Type declaration | Name | Type | Defined in | | -------------- | -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | | `attachments?` | [`EmailAttachment`](/api-reference/@modelence/aws-ses/type-aliases/EmailAttachment)\[] | [index.ts:26](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/aws-ses/src/index.ts#L26) | | `bcc?` | `string` \| `string`\[] | [index.ts:23](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/aws-ses/src/index.ts#L23) | | `cc?` | `string` \| `string`\[] | [index.ts:22](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/aws-ses/src/index.ts#L22) | | `from` | `string` | [index.ts:17](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/aws-ses/src/index.ts#L17) | | `headers?` | `Record`\<`string`, `string`> | [index.ts:25](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/aws-ses/src/index.ts#L25) | | `html?` | `string` | [index.ts:20](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/aws-ses/src/index.ts#L20) | | `replyTo?` | `string` \| `string`\[] | [index.ts:24](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/aws-ses/src/index.ts#L24) | | `subject` | `string` | [index.ts:19](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/aws-ses/src/index.ts#L19) | | `text?` | `string` | [index.ts:21](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/aws-ses/src/index.ts#L21) | | `to` | `string` \| `string`\[] | [index.ts:18](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/aws-ses/src/index.ts#L18) | # default Source: https://docs.modelence.com/api-reference/@modelence/aws-ses/variables/default [API Reference](/api-reference/@modelence/aws-ses/variables/../../../index) / [@modelence/aws-ses](/api-reference/@modelence/aws-ses/variables/../index) / default > **default**: `EmailProvider` Defined in: [index.ts:119](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/aws-ses/src/index.ts#L119) # NextServer Source: https://docs.modelence.com/api-reference/@modelence/next/classes/NextServer [API Reference](/api-reference/@modelence/next/classes/../../../index) / [@modelence/next](/api-reference/@modelence/next/classes/../index) / NextServer Defined in: [index.ts:11](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/next/src/index.ts#L11) Next.js server implementation for Modelence applications. This class wraps Next.js to provide a compatible server interface for the Modelence framework. ## Implements * `AppServer` ## Constructors ### Constructor > **new NextServer**(): `NextServer` #### Returns `NextServer` ## Methods ### handler() > **handler**(`req`, `res`): `void` Defined in: [index.ts:30](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/next/src/index.ts#L30) Handle incoming HTTP requests using Next.js. #### Parameters | Parameter | Type | Description | | --------- | ---------- | ----------------------- | | `req` | `Request` | Express request object | | `res` | `Response` | Express response object | #### Returns `void` #### Implementation of `AppServer.handler` *** ### init() > **init**(): `Promise`\<`void`> Defined in: [index.ts:17](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/next/src/index.ts#L17) Initialize the Next.js application and prepare the request handler. #### Returns `Promise`\<`void`> #### Implementation of `AppServer.init` # @modelence/next Source: https://docs.modelence.com/api-reference/@modelence/next/index [API Reference](/api-reference/@modelence/next/../../index) / @modelence/next ## Classes * [NextServer](/api-reference/@modelence/next/classes/NextServer) ## Variables * [nextServer](/api-reference/@modelence/next/variables/nextServer) # nextServer Source: https://docs.modelence.com/api-reference/@modelence/next/variables/nextServer [API Reference](/api-reference/@modelence/next/variables/../../../index) / [@modelence/next](/api-reference/@modelence/next/variables/../index) / nextServer > `const` **nextServer**: [`NextServer`](/api-reference/@modelence/next/variables/../classes/NextServer) Defined in: [index.ts:54](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/next/src/index.ts#L54) Pre-configured Next.js server instance for Modelence applications. Use this instance in your Modelence server configuration: ## Example ```typescript theme={null} import { startApp } from 'modelence/server'; import { nextServer } from '@modelence/next'; startApp({ server: nextServer }); ``` # ModelenceQueryClient Source: https://docs.modelence.com/api-reference/@modelence/react-query/classes/ModelenceQueryClient [API Reference](/api-reference/@modelence/react-query/classes/../../../index) / [@modelence/react-query](/api-reference/@modelence/react-query/classes/../index) / ModelenceQueryClient Defined in: [index.ts:39](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/react-query/src/index.ts#L39) Client for managing Modelence live queries with TanStack Query. Create one instance and connect it to your QueryClient. ## Example ```tsx theme={null} import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { ModelenceQueryClient } from '@modelence/react-query'; const queryClient = new QueryClient(); new ModelenceQueryClient().connect(queryClient); function App() { return ( ); } ``` ## Constructors ### Constructor > **new ModelenceQueryClient**(): `ModelenceQueryClient` #### Returns `ModelenceQueryClient` ## Methods ### connect() > **connect**(`queryClient`): `void` Defined in: [index.ts:44](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/react-query/src/index.ts#L44) Connects to a TanStack Query QueryClient. This enables live query subscriptions and cache updates. #### Parameters | Parameter | Type | | ------------- | ------------- | | `queryClient` | `QueryClient` | #### Returns `void` # createQueryKey Source: https://docs.modelence.com/api-reference/@modelence/react-query/functions/createQueryKey [API Reference](/api-reference/@modelence/react-query/functions/../../../index) / [@modelence/react-query](/api-reference/@modelence/react-query/functions/../index) / createQueryKey > **createQueryKey**\<`T`, `U`>(`methodName`, `args`): [`ModelenceQueryKey`](/api-reference/@modelence/react-query/functions/../type-aliases/ModelenceQueryKey)\<`T`, `U`> Defined in: [index.ts:279](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/react-query/src/index.ts#L279) Utility function to create query keys for manual cache operations ## Example ```tsx theme={null} import { useQueryClient } from '@tanstack/react-query'; import { createQueryKey } from '@modelence/react-query'; function TodoActions() { const queryClient = useQueryClient(); const refreshTodos = () => { queryClient.invalidateQueries({ queryKey: createQueryKey('todo.getAll', { limit: 10 }) }); }; } ``` ## Type Parameters | Type Parameter | Default type | | ---------------------- | ------------ | | `T` *extends* `string` | - | | `U` *extends* `Args` | `Args` | ## Parameters | Parameter | Type | Description | | ------------ | ---- | --------------- | | `methodName` | `T` | The method name | | `args` | `U` | The arguments | ## Returns [`ModelenceQueryKey`](/api-reference/@modelence/react-query/functions/../type-aliases/ModelenceQueryKey)\<`T`, `U`> Typed query key # modelenceLiveQuery Source: https://docs.modelence.com/api-reference/@modelence/react-query/functions/modelenceLiveQuery [API Reference](/api-reference/@modelence/react-query/functions/../../../index) / [@modelence/react-query](/api-reference/@modelence/react-query/functions/../index) / modelenceLiveQuery > **modelenceLiveQuery**\<`T`>(`methodName`, `args`): `object` Defined in: [index.ts:146](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/react-query/src/index.ts#L146) Creates query options for live queries with TanStack Query's useQuery hook. Data will be updated in real-time when underlying data changes. Requires ModelenceQueryClient to be connected to your QueryClient. ## Example ```tsx theme={null} import { useQuery } from '@tanstack/react-query'; import { modelenceLiveQuery } from '@modelence/react-query'; function TodoList() { // Subscribe to live updates - data refreshes automatically when todos change const { data: todos } = useQuery(modelenceLiveQuery('todo.getAll', { userId })); return (
    {todos?.map(todo =>
  • {todo.title}
  • )}
); } ``` ## Type Parameters | Type Parameter | Default type | Description | | -------------- | ------------ | ------------------------------------- | | `T` | `unknown` | The expected return type of the query | ## Parameters | Parameter | Type | Description | | ------------ | -------- | ---------------------------------------- | | `methodName` | `string` | The name of the method to query | | `args` | `Args` | Optional arguments to pass to the method | ## Returns `object` Query options object for TanStack Query's useQuery | Name | Type | Default value | Defined in | | ---------------------- | -------------------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | | `gcTime` | `number` | `0` | [index.ts:207](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/react-query/src/index.ts#L207) | | `queryFn()` | () => `Promise`\<`T`> | - | [index.ts:155](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/react-query/src/index.ts#L155) | | `queryKey` | readonly \[`"live"`, `string`, `Args`] | - | [index.ts:154](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/react-query/src/index.ts#L154) | | `refetchOnMount` | `boolean` | `false` | [index.ts:205](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/react-query/src/index.ts#L205) | | `refetchOnReconnect` | `boolean` | `false` | [index.ts:206](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/react-query/src/index.ts#L206) | | `refetchOnWindowFocus` | `boolean` | `false` | [index.ts:204](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/react-query/src/index.ts#L204) | | `staleTime` | `number` | `Infinity` | [index.ts:203](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/react-query/src/index.ts#L203) | # modelenceMutation Source: https://docs.modelence.com/api-reference/@modelence/react-query/functions/modelenceMutation [API Reference](/api-reference/@modelence/react-query/functions/../../../index) / [@modelence/react-query](/api-reference/@modelence/react-query/functions/../index) / modelenceMutation > **modelenceMutation**\<`T`>(`methodName`, `defaultArgs`): `object` Defined in: [index.ts:242](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/react-query/src/index.ts#L242) Creates mutation options for use with TanStack Query's useMutation hook. ## Example ```tsx theme={null} import { useMutation, useQueryClient } from '@tanstack/react-query'; import { modelenceMutation } from '@modelence/react-query'; function MyComponent() { const queryClient = useQueryClient(); // Basic usage const { mutate } = useMutation(modelenceMutation('todos.create')); // With additional options const { mutate: updateTodo } = useMutation({ ...modelenceMutation('todos.update'), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['todos.getAll'] }); }, }); return ; } ``` ## Type Parameters | Type Parameter | Default type | Description | | -------------- | ------------ | ---------------------------------------- | | `T` | `unknown` | The expected return type of the mutation | ## Parameters | Parameter | Type | Description | | ------------- | -------- | ----------------------------------------------------------- | | `methodName` | `string` | The name of the method to mutate | | `defaultArgs` | `Args` | Optional default arguments to merge with mutation variables | ## Returns `object` Mutation options object for TanStack Query's useMutation | Name | Type | Defined in | | -------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | | `mutationFn()` | (`variables`) => `Promise`\<`T`> | [index.ts:247](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/react-query/src/index.ts#L247) | # modelenceQuery Source: https://docs.modelence.com/api-reference/@modelence/react-query/functions/modelenceQuery [API Reference](/api-reference/@modelence/react-query/functions/../../../index) / [@modelence/react-query](/api-reference/@modelence/react-query/functions/../index) / modelenceQuery > **modelenceQuery**\<`T`>(`methodName`, `args`): `object` Defined in: [index.ts:108](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/react-query/src/index.ts#L108) Creates query options for use with TanStack Query's useQuery hook. ## Example ```tsx theme={null} import { useQuery } from '@tanstack/react-query'; import { modelenceQuery } from '@modelence/react-query'; function MyComponent() { // Basic usage const { data } = useQuery(modelenceQuery('todo.getAll')); // With additional options const { data: todo } = useQuery({ ...modelenceQuery('todo.getById', { id: '123' }), enabled: !!id, staleTime: 5 * 60 * 1000, }); return
{data?.name}
; } ``` ## Type Parameters | Type Parameter | Default type | Description | | -------------- | ------------ | ------------------------------------- | | `T` | `unknown` | The expected return type of the query | ## Parameters | Parameter | Type | Description | | ------------ | -------- | ---------------------------------------- | | `methodName` | `string` | The name of the method to query | | `args` | `Args` | Optional arguments to pass to the method | ## Returns `object` Query options object for TanStack Query's useQuery | Name | Type | Defined in | | ----------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | | `queryFn()` | () => `Promise`\<`T`> | [index.ts:114](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/react-query/src/index.ts#L114) | | `queryKey` | (`string` \| `Args`)\[] | [index.ts:113](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/react-query/src/index.ts#L113) | # @modelence/react-query Source: https://docs.modelence.com/api-reference/@modelence/react-query/index [API Reference](/api-reference/@modelence/react-query/../../index) / @modelence/react-query ## Classes * [ModelenceQueryClient](/api-reference/@modelence/react-query/classes/ModelenceQueryClient) ## Type Aliases * [ModelenceQueryKey](/api-reference/@modelence/react-query/type-aliases/ModelenceQueryKey) ## Functions * [createQueryKey](/api-reference/@modelence/react-query/functions/createQueryKey) * [modelenceLiveQuery](/api-reference/@modelence/react-query/functions/modelenceLiveQuery) * [modelenceMutation](/api-reference/@modelence/react-query/functions/modelenceMutation) * [modelenceQuery](/api-reference/@modelence/react-query/functions/modelenceQuery) # ModelenceQueryKey Source: https://docs.modelence.com/api-reference/@modelence/react-query/type-aliases/ModelenceQueryKey [API Reference](/api-reference/@modelence/react-query/type-aliases/../../../index) / [@modelence/react-query](/api-reference/@modelence/react-query/type-aliases/../index) / ModelenceQueryKey > **ModelenceQueryKey**\<`T`, `U`> = readonly \[`T`, `U`] Defined in: [index.ts:254](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/react-query/src/index.ts#L254) Type helper for creating properly typed query keys ## Type Parameters | Type Parameter | Default type | | ---------------------- | ------------ | | `T` *extends* `string` | - | | `U` *extends* `Args` | `Args` | # sendEmail Source: https://docs.modelence.com/api-reference/@modelence/resend/functions/sendEmail [API Reference](/api-reference/@modelence/resend/functions/../../../index) / [@modelence/resend](/api-reference/@modelence/resend/functions/../index) / sendEmail > **sendEmail**(`payload`): `Promise`\<`void`> Defined in: [index.ts:57](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/resend/src/index.ts#L57) Sends an email via Resend. ## Example ```ts theme={null} import { sendEmail } from '@modelence/aws-ses'; sendEmail({ from: 'test@example.com', to: 'test@example.com', subject: 'Test Email', html: '

Hello World

' }) ``` ## Parameters | Parameter | Type | Description | | --------- | ----------------------------------------------------------------------------------------- | ------------------------- | | `payload` | [`EmailPayload`](/api-reference/@modelence/resend/functions/../type-aliases/EmailPayload) | The email payload object. | ## Returns `Promise`\<`void`> # @modelence/resend Source: https://docs.modelence.com/api-reference/@modelence/resend/index [API Reference](/api-reference/@modelence/resend/../../index) / @modelence/resend ## Type Aliases * [EmailAttachment](/api-reference/@modelence/resend/type-aliases/EmailAttachment) * [EmailPayload](/api-reference/@modelence/resend/type-aliases/EmailPayload) ## Variables * [default](/api-reference/@modelence/resend/variables/default) ## Functions * [sendEmail](/api-reference/@modelence/resend/functions/sendEmail) # EmailAttachment Source: https://docs.modelence.com/api-reference/@modelence/resend/type-aliases/EmailAttachment [API Reference](/api-reference/@modelence/resend/type-aliases/../../../index) / [@modelence/resend](/api-reference/@modelence/resend/type-aliases/../index) / EmailAttachment > **EmailAttachment** = `object` Defined in: [index.ts:6](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/resend/src/index.ts#L6) ## Properties | Property | Type | Defined in | | ------------------- | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | |
`content` | `Buffer` \| `string` | [index.ts:8](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/resend/src/index.ts#L8) | | `contentType` | `string` | [index.ts:9](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/resend/src/index.ts#L9) | | `filename` | `string` | [index.ts:7](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/resend/src/index.ts#L7) | # EmailPayload Source: https://docs.modelence.com/api-reference/@modelence/resend/type-aliases/EmailPayload [API Reference](/api-reference/@modelence/resend/type-aliases/../../../index) / [@modelence/resend](/api-reference/@modelence/resend/type-aliases/../index) / EmailPayload > **EmailPayload** = `object` & \{ `html`: `string`; } | \{ `text`: `string`; } Defined in: [index.ts:12](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/resend/src/index.ts#L12) ## Type declaration | Name | Type | Defined in | | -------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | | `attachments?` | [`EmailAttachment`](/api-reference/@modelence/resend/type-aliases/EmailAttachment)\[] | [index.ts:22](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/resend/src/index.ts#L22) | | `bcc?` | `string` \| `string`\[] | [index.ts:19](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/resend/src/index.ts#L19) | | `cc?` | `string` \| `string`\[] | [index.ts:18](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/resend/src/index.ts#L18) | | `from` | `string` | [index.ts:13](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/resend/src/index.ts#L13) | | `headers?` | `Record`\<`string`, `string`> | [index.ts:21](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/resend/src/index.ts#L21) | | `html?` | `string` | [index.ts:16](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/resend/src/index.ts#L16) | | `replyTo?` | `string` \| `string`\[] | [index.ts:20](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/resend/src/index.ts#L20) | | `subject` | `string` | [index.ts:15](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/resend/src/index.ts#L15) | | `text?` | `string` | [index.ts:17](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/resend/src/index.ts#L17) | | `to` | `string` \| `string`\[] | [index.ts:14](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/resend/src/index.ts#L14) | # default Source: https://docs.modelence.com/api-reference/@modelence/resend/variables/default [API Reference](/api-reference/@modelence/resend/variables/../../../index) / [@modelence/resend](/api-reference/@modelence/resend/variables/../index) / default > **default**: `EmailProvider` Defined in: [index.ts:98](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/resend/src/index.ts#L98) # sendEmail Source: https://docs.modelence.com/api-reference/@modelence/smtp/functions/sendEmail [API Reference](/api-reference/@modelence/smtp/functions/../../../index) / [@modelence/smtp](/api-reference/@modelence/smtp/functions/../index) / sendEmail > **sendEmail**(`payload`): `Promise`\<`void`> Defined in: [index.ts:70](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/smtp/src/index.ts#L70) Sends an email via Resend. ## Example ```ts theme={null} import { sendEmail } from '@modelence/aws-ses'; sendEmail({ from: 'test@example.com', to: 'test@example.com', subject: 'Test Email', html: '

Hello World

' }) ``` ## Parameters | Parameter | Type | Description | | --------- | --------------------------------------------------------------------------------------- | ------------------------- | | `payload` | [`EmailPayload`](/api-reference/@modelence/smtp/functions/../type-aliases/EmailPayload) | The email payload object. | ## Returns `Promise`\<`void`> # @modelence/smtp Source: https://docs.modelence.com/api-reference/@modelence/smtp/index [API Reference](/api-reference/@modelence/smtp/../../index) / @modelence/smtp ## Type Aliases * [EmailAttachment](/api-reference/@modelence/smtp/type-aliases/EmailAttachment) * [EmailPayload](/api-reference/@modelence/smtp/type-aliases/EmailPayload) ## Variables * [default](/api-reference/@modelence/smtp/variables/default) ## Functions * [sendEmail](/api-reference/@modelence/smtp/functions/sendEmail) # EmailAttachment Source: https://docs.modelence.com/api-reference/@modelence/smtp/type-aliases/EmailAttachment [API Reference](/api-reference/@modelence/smtp/type-aliases/../../../index) / [@modelence/smtp](/api-reference/@modelence/smtp/type-aliases/../index) / EmailAttachment > **EmailAttachment** = `object` Defined in: [index.ts:7](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/smtp/src/index.ts#L7) ## Properties | Property | Type | Defined in | | ------------------- | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | |
`content` | `Buffer` \| `string` | [index.ts:9](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/smtp/src/index.ts#L9) | | `contentType` | `string` | [index.ts:10](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/smtp/src/index.ts#L10) | | `filename` | `string` | [index.ts:8](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/smtp/src/index.ts#L8) | # EmailPayload Source: https://docs.modelence.com/api-reference/@modelence/smtp/type-aliases/EmailPayload [API Reference](/api-reference/@modelence/smtp/type-aliases/../../../index) / [@modelence/smtp](/api-reference/@modelence/smtp/type-aliases/../index) / EmailPayload > **EmailPayload** = `object` & \{ `html`: `string`; } | \{ `text`: `string`; } Defined in: [index.ts:13](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/smtp/src/index.ts#L13) ## Type declaration | Name | Type | Defined in | | -------------- | ----------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | | `attachments?` | [`EmailAttachment`](/api-reference/@modelence/smtp/type-aliases/EmailAttachment)\[] | [index.ts:23](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/smtp/src/index.ts#L23) | | `bcc?` | `string` \| `string`\[] | [index.ts:20](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/smtp/src/index.ts#L20) | | `cc?` | `string` \| `string`\[] | [index.ts:19](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/smtp/src/index.ts#L19) | | `from` | `string` | [index.ts:14](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/smtp/src/index.ts#L14) | | `headers?` | `Record`\<`string`, `string`> | [index.ts:22](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/smtp/src/index.ts#L22) | | `html?` | `string` | [index.ts:17](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/smtp/src/index.ts#L17) | | `replyTo?` | `string` \| `string`\[] | [index.ts:21](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/smtp/src/index.ts#L21) | | `subject` | `string` | [index.ts:16](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/smtp/src/index.ts#L16) | | `text?` | `string` | [index.ts:18](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/smtp/src/index.ts#L18) | | `to` | `string` \| `string`\[] | [index.ts:15](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/smtp/src/index.ts#L15) | # default Source: https://docs.modelence.com/api-reference/@modelence/smtp/variables/default [API Reference](/api-reference/@modelence/smtp/variables/../../../index) / [@modelence/smtp](/api-reference/@modelence/smtp/variables/../index) / default > **default**: `EmailProvider` Defined in: [index.ts:100](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/smtp/src/index.ts#L100) # ClientChannel Source: https://docs.modelence.com/api-reference/modelence/client/classes/ClientChannel [API Reference](/api-reference/modelence/client/classes/../../../index) / [modelence](/api-reference/modelence/client/classes/../../index) / [client](/api-reference/modelence/client/classes/../index) / ClientChannel Defined in: [packages/modelence/src/websocket/clientChannel.ts:3](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/websocket/clientChannel.ts#L3) ## Type Parameters | Type Parameter | Default type | | -------------- | ------------ | | `T` | `unknown` | ## Constructors ### Constructor > **new ClientChannel**\<`T`>(`category`, `onMessage`): `ClientChannel`\<`T`> Defined in: [packages/modelence/src/websocket/clientChannel.ts:7](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/websocket/clientChannel.ts#L7) #### Parameters | Parameter | Type | | ----------- | ------------------ | | `category` | `string` | | `onMessage` | (`data`) => `void` | #### Returns `ClientChannel`\<`T`> ## Properties | Property | Modifier | Type | Defined in | | ---------------- | ---------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `category` | `readonly` | `string` | [packages/modelence/src/websocket/clientChannel.ts:4](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/websocket/clientChannel.ts#L4) | ## Methods ### init() > **init**(): `void` Defined in: [packages/modelence/src/websocket/clientChannel.ts:12](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/websocket/clientChannel.ts#L12) #### Returns `void` *** ### joinChannel() > **joinChannel**(`id`): `void` Defined in: [packages/modelence/src/websocket/clientChannel.ts:19](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/websocket/clientChannel.ts#L19) #### Parameters | Parameter | Type | | --------- | -------- | | `id` | `string` | #### Returns `void` *** ### leaveChannel() > **leaveChannel**(`id`): `void` Defined in: [packages/modelence/src/websocket/clientChannel.ts:26](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/websocket/clientChannel.ts#L26) #### Parameters | Parameter | Type | | --------- | -------- | | `id` | `string` | #### Returns `void` # MethodError Source: https://docs.modelence.com/api-reference/modelence/client/classes/MethodError [API Reference](/api-reference/modelence/client/classes/../../../index) / [modelence](/api-reference/modelence/client/classes/../../index) / [client](/api-reference/modelence/client/classes/../index) / MethodError Defined in: [packages/modelence/src/client/method.ts:15](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/method.ts#L15) ## Extends * `Error` ## Constructors ### Constructor > **new MethodError**(`message`, `status`, `code?`): `MethodError` Defined in: [packages/modelence/src/client/method.ts:25](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/method.ts#L25) #### Parameters | Parameter | Type | | --------- | -------- | | `message` | `string` | | `status` | `number` | | `code?` | `string` | #### Returns `MethodError` #### Overrides `Error.constructor` ## Properties | Property | Type | Description | Defined in | | -------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `code?` | `string` | Machine-readable error code set by the server (when available), so callers can branch on the error kind without matching the human-readable message. For example, a login attempt with an unverified email yields `code === 'EMAIL_NOT_VERIFIED'`. | [packages/modelence/src/client/method.ts:23](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/method.ts#L23) | | `status` | `number` | - | [packages/modelence/src/client/method.ts:16](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/method.ts#L16) | # ModelenceQueryClient Source: https://docs.modelence.com/api-reference/modelence/client/classes/ModelenceQueryClient [API Reference](/api-reference/modelence/client/classes/../../../index) / [modelence](/api-reference/modelence/client/classes/../../index) / [client](/api-reference/modelence/client/classes/../index) / ModelenceQueryClient Defined in: [packages/modelence/src/client/query.ts:80](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/query.ts#L80) ## Deprecated Use `connectModelenceQueryClient(queryClient)` instead. ## Constructors ### Constructor > **new ModelenceQueryClient**(): `ModelenceQueryClient` #### Returns `ModelenceQueryClient` ## Methods ### ~~connect()~~ > **connect**(`queryClient`): `void` Defined in: [packages/modelence/src/client/query.ts:81](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/query.ts#L81) #### Parameters | Parameter | Type | | ------------- | ------------- | | `queryClient` | `QueryClient` | #### Returns `void` # ModelenceQueryProvider Source: https://docs.modelence.com/api-reference/modelence/client/functions/ModelenceQueryProvider [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / ModelenceQueryProvider > **ModelenceQueryProvider**(`__namedParameters`): `Element` Defined in: [packages/modelence/src/client/queryProvider.tsx:38](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/queryProvider.tsx#L38) ## Parameters | Parameter | Type | | ------------------- | ----------------------------- | | `__namedParameters` | `ModelenceQueryProviderProps` | ## Returns `Element` # callMethod Source: https://docs.modelence.com/api-reference/modelence/client/functions/callMethod [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / callMethod > **callMethod**\<`T`>(`methodName`, `args?`, `options?`): `Promise`\<`T`> Defined in: [packages/modelence/src/client/method.ts:103](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/method.ts#L103) Calls a server-side method (query or mutation) defined on a Modelence module. Both `args` and `options` are optional. Use the type parameter `T` to type the return value. ## Example ```typescript theme={null} import { callMethod } from 'modelence/client'; // No arguments const todos = await callMethod('todo.getAll'); // With arguments const todo = await callMethod('todo.getOne', { id: '123' }); // With a custom error handler const created = await callMethod( 'todo.create', { title: 'Buy groceries' }, { errorHandler: (error, methodName) => console.error(methodName, error) } ); ``` ## Type Parameters | Type Parameter | Default type | | -------------- | ------------ | | `T` | `unknown` | ## Parameters | Parameter | Type | Description | | ------------ | -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | | `methodName` | `string` | Fully qualified method name, e.g. `'todo.getAll'`. | | `args?` | [`MethodArgs`](/api-reference/modelence/client/functions/../type-aliases/MethodArgs) | Arguments passed to the server-side method. Defaults to `{}`. | | `options?` | [`CallMethodOptions`](/api-reference/modelence/client/functions/../type-aliases/CallMethodOptions) | Call-site options such as a custom [CallMethodOptions.errorHandler](../type-aliases/CallMethodOptions#errorhandler). Defaults to `{}`. | ## Returns `Promise`\<`T`> A promise that resolves to the method's return value. # configureClient Source: https://docs.modelence.com/api-reference/modelence/client/functions/configureClient [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / configureClient > **configureClient**(`userConfig`): `void` Defined in: [packages/modelence/src/client/clientConfig.ts:58](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/clientConfig.ts#L58) Configure the Modelence client for non-browser environments like React Native. When configured, the client uses the provided functions for auth-token storage, client-info collection, and URL resolution instead of the default browser APIs (localStorage, window\.screen, relative URLs). ## Example ```ts theme={null} import { configureClient } from 'modelence/client'; import { Linking } from 'react-native'; let authToken: string | undefined; configureClient({ baseUrl: 'https://myapp.com', getAuthToken: () => authToken, setAuthToken: (token) => { authToken = token ?? undefined; }, getClientInfo: () => ({ screenWidth: Dimensions.get('screen').width, screenHeight: Dimensions.get('screen').height, windowWidth: Dimensions.get('window').width, windowHeight: Dimensions.get('window').height, pixelRatio: PixelRatio.get(), orientation: null, }), openUrl: (url) => Linking.openURL(url), }); ``` ## Parameters | Parameter | Type | | ------------ | -------------------------------------------------------------------------------------- | | `userConfig` | [`ClientConfig`](/api-reference/modelence/client/functions/../interfaces/ClientConfig) | ## Returns `void` # connectModelenceQueryClient Source: https://docs.modelence.com/api-reference/modelence/client/functions/connectModelenceQueryClient [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / connectModelenceQueryClient > **connectModelenceQueryClient**(`queryClient`): `void` Defined in: [packages/modelence/src/client/query.ts:31](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/query.ts#L31) Connects a `QueryClient` to Modelence's live-query layer. Auto-called by ``; only call manually if you mount your own ``. Note: WebSocket setup is deferred until the first `modelenceLiveQuery` call, so apps that only use `modelenceQuery`/`modelenceMutation` never open a socket. ## Parameters | Parameter | Type | | ------------- | ------------- | | `queryClient` | `QueryClient` | ## Returns `void` # createClientModule Source: https://docs.modelence.com/api-reference/modelence/client/functions/createClientModule [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / createClientModule > **createClientModule**\<`TModule`>(`moduleName`): `object` Defined in: [packages/modelence/src/client/module.ts:88](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/module.ts#L88) Creates a typed client accessor for a module's public configs, queries, and mutations. Use `import type` to reference the module so no server code is bundled on the client. Arg and return types for queries and mutations are inferred automatically from the server-side handler signatures. ## Example ```ts theme={null} // src/client/payments.ts import type paymentsModule from '../server/payments'; import { createClientModule } from 'modelence/client'; export const payments = createClientModule('payments'); ``` ```ts theme={null} // src/components/Checkout.tsx import { useQuery, useMutation } from '@tanstack/react-query'; import { payments } from '../client/payments'; // Typed config — public keys only, private and secret keys excluded: const currency = payments.getConfig('currency'); // string | undefined // Typed query — pass directly to useQuery: const { data: products } = useQuery(payments.query('getProducts', { page: 1 })); // Typed mutation — pass directly to useMutation: const { mutate: charge } = useMutation(payments.mutation('charge')); charge({ amount: 100 }); // args typed from handler signature ``` ## Type Parameters | Type Parameter | | ------------------------------- | | `TModule` *extends* `AnyModule` | ## Parameters | Parameter | Type | Description | | ------------ | -------- | ------------------------------------------------------- | | `moduleName` | `string` | The module's name as passed to `new Module(name, ...)`. | ## Returns | Name | Type | Description | Defined in | | ----------------- | ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `getConfig()` | (`key`) => `undefined` \| `PublicKeyOf`\<`TModule`\[`"configSchema"`]>\[`K`] | - | [packages/modelence/src/client/module.ts:90](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/module.ts#L90) | | `infiniteQuery()` | (`name`, `getArgs`) => `object` | Returns options for `useInfiniteQuery`. The `getArgs` callback receives the current `pageParam` and returns the args to pass to the query handler. Spread the result into `useInfiniteQuery` alongside `getNextPageParam`. Annotate the `pageParam` type in the callback so TypeScript can infer the page param type — no manual generic needed on `useInfiniteQuery`. | [packages/modelence/src/client/module.ts:134](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/module.ts#L134) | | `mutation()` | (`name`) => `object` | - | [packages/modelence/src/client/module.ts:114](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/module.ts#L114) | | `query()` | (`name`, ...`rest`) => `object` | - | [packages/modelence/src/client/module.ts:97](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/module.ts#L97) | # createQueryKey Source: https://docs.modelence.com/api-reference/modelence/client/functions/createQueryKey [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / createQueryKey > **createQueryKey**\<`T`, `U`>(`methodName`, `args`): [`ModelenceQueryKey`](/api-reference/modelence/client/functions/../type-aliases/ModelenceQueryKey)\<`T`, `U`> Defined in: [packages/modelence/src/client/query.ts:191](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/query.ts#L191) Builds a query key matching `modelenceQuery(...)` for cache operations. ## Type Parameters | Type Parameter | Default type | | ---------------------- | ------------ | | `T` *extends* `string` | - | | `U` *extends* `Args` | `Args` | ## Parameters | Parameter | Type | | ------------ | ---- | | `methodName` | `T` | | `args` | `U` | ## Returns [`ModelenceQueryKey`](/api-reference/modelence/client/functions/../type-aliases/ModelenceQueryKey)\<`T`, `U`> # disconnectModelenceQueryClient Source: https://docs.modelence.com/api-reference/modelence/client/functions/disconnectModelenceQueryClient [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / disconnectModelenceQueryClient > **disconnectModelenceQueryClient**(): `void` Defined in: [packages/modelence/src/client/query.ts:68](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/query.ts#L68) ## Returns `void` # getConfig Source: https://docs.modelence.com/api-reference/modelence/client/functions/getConfig [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / getConfig > **getConfig**(`key`): `undefined` | `string` | `number` | `boolean` Defined in: [packages/modelence/src/config/client.ts:19](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/config/client.ts#L19) ## Parameters | Parameter | Type | | --------- | -------- | | `key` | `string` | ## Returns `undefined` | `string` | `number` | `boolean` ## Sidebar Title getConfig (client) # getLocalStorageSession Source: https://docs.modelence.com/api-reference/modelence/client/functions/getLocalStorageSession [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / getLocalStorageSession > **getLocalStorageSession**(): `any` Defined in: [packages/modelence/src/client/localStorage.ts:7](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/localStorage.ts#L7) ## Returns `any` # getWebsocketClientProvider Source: https://docs.modelence.com/api-reference/modelence/client/functions/getWebsocketClientProvider [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / getWebsocketClientProvider > **getWebsocketClientProvider**(): `null` | [`WebsocketClientProvider`](/api-reference/modelence/client/functions/../../index/interfaces/WebsocketClientProvider) Defined in: [packages/modelence/src/websocket/client.ts:13](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/websocket/client.ts#L13) ## Returns `null` | [`WebsocketClientProvider`](/api-reference/modelence/client/functions/../../index/interfaces/WebsocketClientProvider) # linkOAuthProvider Source: https://docs.modelence.com/api-reference/modelence/client/functions/linkOAuthProvider [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / linkOAuthProvider > **linkOAuthProvider**(`options`): `Promise`\<`void`> Defined in: [packages/modelence/src/auth/client/index.ts:278](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/client/index.ts#L278) Link an OAuth provider to the currently signed-in user's account. Redirects the browser to the OAuth provider's authorization page. The provider will redirect back and the account will be linked. ## Example ```ts theme={null} linkOAuthProvider({ provider: 'google' }); ``` ## Parameters | Parameter | Type | Description | | ------------------ | ------------------------------------------ | -------------------------------------------------- | | `options` | \{ `provider`: `"google"` \| `"github"`; } | - | | `options.provider` | `"google"` \| `"github"` | The OAuth provider to link ('google' or 'github'). | ## Returns `Promise`\<`void`> # loginWithMagicLink Source: https://docs.modelence.com/api-reference/modelence/client/functions/loginWithMagicLink [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / loginWithMagicLink > **loginWithMagicLink**(): `Promise`\<`null` | `User`> Defined in: [packages/modelence/src/auth/client/index.ts:207](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/client/index.ts#L207) Complete a magic link sign-in. Call this from the page the magic link landing route redirects to. The token is exchanged server-side via an httpOnly cookie, so no arguments are needed. Signs the user in — creating the account first when the email is not registered yet and the server enables `auth.magicLink.allowSignup` — and returns the logged-in user. ## Example ```ts theme={null} const user = await loginWithMagicLink(); ``` ## Returns `Promise`\<`null` | `User`> # loginWithOneTimeCode Source: https://docs.modelence.com/api-reference/modelence/client/functions/loginWithOneTimeCode [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / loginWithOneTimeCode > **loginWithOneTimeCode**(`options`): `Promise`\<`null` | `User`> Defined in: [packages/modelence/src/auth/client/index.ts:235](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/client/index.ts#L235) Complete a magic link sign-in by typing the one-time code from the email. Alternative to `loginWithMagicLink()` for contexts where clicking the link can't reach the app — native apps without deep links, or when the email is read on a different device. Signs the user in — creating the account first when the email is not registered yet and the server enables `auth.magicLink.allowSignup` — and returns the logged-in user. ## Example ```ts theme={null} const user = await loginWithOneTimeCode({ email: 'user@example.com', code: '482193' }); ``` ## Parameters | Parameter | Type | Description | | --------------- | ----------------------------------------- | ------------------------------------- | | `options` | \{ `code`: `string`; `email`: `string`; } | - | | `options.code` | `string` | The one-time code from the email. | | `options.email` | `string` | The email the magic link was sent to. | ## Returns `Promise`\<`null` | `User`> # loginWithPassword Source: https://docs.modelence.com/api-reference/modelence/client/functions/loginWithPassword [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / loginWithPassword > **loginWithPassword**(`options`): `Promise`\<`null` | `User`> Defined in: [packages/modelence/src/auth/client/index.ts:72](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/client/index.ts#L72) Login a user with an email and password. ## Example ```ts theme={null} await loginWithPassword({ email: 'test@example.com', password: '12345678' }); ``` ## Parameters | Parameter | Type | Description | | ------------------ | --------------------------------------------- | ------------------------- | | `options` | \{ `email`: `string`; `password`: `string`; } | - | | `options.email` | `string` | The email of the user. | | `options.password` | `string` | The password of the user. | ## Returns `Promise`\<`null` | `User`> # logout Source: https://docs.modelence.com/api-reference/modelence/client/functions/logout [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / logout > **logout**(): `Promise`\<`void`> Defined in: [packages/modelence/src/auth/client/index.ts:152](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/client/index.ts#L152) Logout the current user. ## Returns `Promise`\<`void`> # modelenceLiveQuery Source: https://docs.modelence.com/api-reference/modelence/client/functions/modelenceLiveQuery [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / modelenceLiveQuery > **modelenceLiveQuery**\<`T`>(`methodName`, `args`): `object` Defined in: [packages/modelence/src/client/query.ts:104](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/query.ts#L104) Live query — data updates in real time as the underlying collection changes. Requires a `QueryClient` connected via `` or `connectModelenceQueryClient(...)`. ## Type Parameters | Type Parameter | Default type | | -------------- | ------------ | | `T` | `unknown` | ## Parameters | Parameter | Type | | ------------ | -------- | | `methodName` | `string` | | `args` | `Args` | ## Returns `object` | Name | Type | Default value | Defined in | | ---------------------- | -------------------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `gcTime` | `number` | `0` | [packages/modelence/src/client/query.ts:177](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/query.ts#L177) | | `queryFn()` | () => `Promise`\<`T`> | - | [packages/modelence/src/client/query.ts:110](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/query.ts#L110) | | `queryKey` | readonly \[`"live"`, `string`, `Args`] | - | [packages/modelence/src/client/query.ts:109](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/query.ts#L109) | | `refetchOnMount` | `boolean` | `false` | [packages/modelence/src/client/query.ts:175](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/query.ts#L175) | | `refetchOnReconnect` | `boolean` | `false` | [packages/modelence/src/client/query.ts:176](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/query.ts#L176) | | `refetchOnWindowFocus` | `boolean` | `false` | [packages/modelence/src/client/query.ts:174](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/query.ts#L174) | | `staleTime` | `number` | `Infinity` | [packages/modelence/src/client/query.ts:173](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/query.ts#L173) | # modelenceMutation Source: https://docs.modelence.com/api-reference/modelence/client/functions/modelenceMutation [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / modelenceMutation > **modelenceMutation**\<`T`>(`methodName`, `defaultArgs`): `object` Defined in: [packages/modelence/src/client/query.ts:181](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/query.ts#L181) ## Type Parameters | Type Parameter | Default type | | -------------- | ------------ | | `T` | `unknown` | ## Parameters | Parameter | Type | | ------------- | -------- | | `methodName` | `string` | | `defaultArgs` | `Args` | ## Returns `object` | Name | Type | Defined in | | -------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `mutationFn()` | (`variables`) => `Promise`\<`T`> | [packages/modelence/src/client/query.ts:183](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/query.ts#L183) | # modelenceQuery Source: https://docs.modelence.com/api-reference/modelence/client/functions/modelenceQuery [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / modelenceQuery > **modelenceQuery**\<`T`>(`methodName`, `args`): `object` Defined in: [packages/modelence/src/client/query.ts:92](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/query.ts#L92) ## Example ```tsx theme={null} const { data } = useQuery(modelenceQuery('todo.getAll')); ``` ## Type Parameters | Type Parameter | Default type | | -------------- | ------------ | | `T` | `unknown` | ## Parameters | Parameter | Type | | ------------ | -------- | | `methodName` | `string` | | `args` | `Args` | ## Returns `object` | Name | Type | Defined in | | ----------- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `queryFn()` | () => `Promise`\<`T`> | [packages/modelence/src/client/query.ts:95](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/query.ts#L95) | | `queryKey` | (`string` \| `Args`)\[] | [packages/modelence/src/client/query.ts:94](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/query.ts#L94) | # renderApp Source: https://docs.modelence.com/api-reference/modelence/client/functions/renderApp [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / renderApp > **renderApp**(`options`): `void` Defined in: [packages/modelence/src/client/renderApp.tsx:71](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/renderApp.tsx#L71) ## Parameters | Parameter | Type | | --------- | ------------------ | | `options` | `RenderAppOptions` | ## Returns `void` # resendEmailVerification Source: https://docs.modelence.com/api-reference/modelence/client/functions/resendEmailVerification [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / resendEmailVerification > **resendEmailVerification**(`options`): `Promise`\<`void`> Defined in: [packages/modelence/src/auth/client/index.ts:143](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/client/index.ts#L143) Resend the verification email for a given email address. The email is only sent if the address is registered and not yet verified. A generic response is always returned to avoid leaking account information. ## Example ```ts theme={null} await resendEmailVerification({ email: 'user@example.com' }); ``` ## Parameters | Parameter | Type | Description | | --------------- | ----------------------- | -------------------------------------------- | | `options` | \{ `email`: `string`; } | - | | `options.email` | `string` | The email address to resend verification to. | ## Returns `Promise`\<`void`> # resetPassword Source: https://docs.modelence.com/api-reference/modelence/client/functions/resetPassword [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / resetPassword > **resetPassword**(`options`): `Promise`\<`void`> Defined in: [packages/modelence/src/auth/client/index.ts:259](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/client/index.ts#L259) Reset password. The token is normally exchanged server-side via an httpOnly cookie, so the client only submits the new password. Pass `token` only for legacy flows that still carry it client-side (deprecated). ## Parameters | Parameter | Type | Description | | ------------------ | ---------------------------------------------- | ------------------------------------------------------------------- | | `options` | \{ `password`: `string`; `token?`: `string`; } | - | | `options.password` | `string` | The new password. | | `options.token?` | `string` | Reset token (optional; read from the httpOnly cookie when omitted). | ## Returns `Promise`\<`void`> # sendMagicLink Source: https://docs.modelence.com/api-reference/modelence/client/functions/sendMagicLink [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / sendMagicLink > **sendMagicLink**(`options`): `Promise`\<`void`> Defined in: [packages/modelence/src/auth/client/index.ts:186](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/client/index.ts#L186) Send a magic sign-in link to the given email address. Clicking the emailed link signs the user in. When the server enables `auth.magicLink.allowSignup`, this also works for new users — the account is created when the link is used; otherwise unknown emails receive no email. A generic response is always returned to avoid leaking account information. ## Example ```ts theme={null} await sendMagicLink({ email: 'user@example.com' }); ``` ## Parameters | Parameter | Type | Description | | --------------- | ----------------------- | -------------------------------------------- | | `options` | \{ `email`: `string`; } | - | | `options.email` | `string` | The email address to send the magic link to. | ## Returns `Promise`\<`void`> # sendResetPasswordToken Source: https://docs.modelence.com/api-reference/modelence/client/functions/sendResetPasswordToken [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / sendResetPasswordToken > **sendResetPasswordToken**(`options`): `Promise`\<`void`> Defined in: [packages/modelence/src/auth/client/index.ts:165](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/client/index.ts#L165) Send reset password token. ## Parameters | Parameter | Type | Description | | --------------- | ----------------------- | ---------------------- | | `options` | \{ `email`: `string`; } | - | | `options.email` | `string` | The email of the user. | ## Returns `Promise`\<`void`> # setWebsocketClientProvider Source: https://docs.modelence.com/api-reference/modelence/client/functions/setWebsocketClientProvider [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / setWebsocketClientProvider > **setWebsocketClientProvider**(`provider`): `void` Defined in: [packages/modelence/src/websocket/client.ts:9](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/websocket/client.ts#L9) ## Parameters | Parameter | Type | | ---------- | ------------------------------------------------------------------------------------------------------------------------------- | | `provider` | `null` \| [`WebsocketClientProvider`](/api-reference/modelence/client/functions/../../index/interfaces/WebsocketClientProvider) | ## Returns `void` # signupWithPassword Source: https://docs.modelence.com/api-reference/modelence/client/functions/signupWithPassword [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / signupWithPassword > **signupWithPassword**(`options`): `Promise`\<`void`> Defined in: [packages/modelence/src/auth/client/index.ts:43](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/client/index.ts#L43) Sign up a new user with an email and password. ## Example ```ts theme={null} await signupWithPassword({ email: 'test@example.com', password: '12345678' }); await signupWithPassword({ email: 'test@example.com', password: '12345678', handle: 'myhandle', firstName: 'John' }); ``` ## Parameters | Parameter | Type | Description | | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ | | `options` | \{ `avatarUrl?`: `string`; `email`: `string`; `firstName?`: `string`; `handle?`: `string`; `lastName?`: `string`; `password`: `string`; } | - | | `options.avatarUrl?` | `string` | Optional avatar URL. | | `options.email` | `string` | The email of the user. | | `options.firstName?` | `string` | Optional first name. | | `options.handle?` | `string` | Optional custom handle. If omitted, one is derived from the email. | | `options.lastName?` | `string` | Optional last name. | | `options.password` | `string` | The password of the user. | ## Returns `Promise`\<`void`> # startWebsockets Source: https://docs.modelence.com/api-reference/modelence/client/functions/startWebsockets [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / startWebsockets > **startWebsockets**(`props?`): `void` Defined in: [packages/modelence/src/websocket/client.ts:17](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/websocket/client.ts#L17) ## Parameters | Parameter | Type | | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `props?` | \{ `channels?`: [`ClientChannel`](/api-reference/modelence/client/functions/../classes/ClientChannel)\<`unknown`>\[]; `provider?`: [`WebsocketClientProvider`](/api-reference/modelence/client/functions/../../index/interfaces/WebsocketClientProvider); } | | `props.channels?` | [`ClientChannel`](/api-reference/modelence/client/functions/../classes/ClientChannel)\<`unknown`>\[] | | `props.provider?` | [`WebsocketClientProvider`](/api-reference/modelence/client/functions/../../index/interfaces/WebsocketClientProvider) | ## Returns `void` # subscribeLiveQuery Source: https://docs.modelence.com/api-reference/modelence/client/functions/subscribeLiveQuery [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / subscribeLiveQuery > **subscribeLiveQuery**\<`T`>(`method`, `args`, `onData`, `onError?`): () => `void` Defined in: [packages/modelence/src/websocket/socketio/client.ts:112](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/websocket/socketio/client.ts#L112) ## Type Parameters | Type Parameter | Default type | | -------------- | ------------ | | `T` | `unknown` | ## Parameters | Parameter | Type | | ---------- | ------------------------------ | | `method` | `string` | | `args` | `Record`\<`string`, `unknown`> | | `onData` | (`data`) => `void` | | `onError?` | (`error`) => `void` | ## Returns > (): `void` ### Returns `void` # unlinkOAuthProvider Source: https://docs.modelence.com/api-reference/modelence/client/functions/unlinkOAuthProvider [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / unlinkOAuthProvider > **unlinkOAuthProvider**(`options`): `Promise`\<`void`> Defined in: [packages/modelence/src/auth/client/index.ts:328](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/client/index.ts#L328) Unlink an OAuth provider from the currently signed-in user's account. ## Example ```ts theme={null} await unlinkOAuthProvider({ provider: 'github' }); ``` ## Parameters | Parameter | Type | Description | | ------------------ | ------------------------------------------ | ---------------------------------------------------- | | `options` | \{ `provider`: `"google"` \| `"github"`; } | - | | `options.provider` | `"google"` \| `"github"` | The OAuth provider to unlink ('google' or 'github'). | ## Returns `Promise`\<`void`> # updateProfile Source: https://docs.modelence.com/api-reference/modelence/client/functions/updateProfile [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / updateProfile > **updateProfile**(`options`): `Promise`\<`null` | `User`> Defined in: [packages/modelence/src/auth/client/index.ts:101](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/client/index.ts#L101) Update the current user's profile. ## Example ```ts theme={null} await updateProfile({ firstName: 'Atul', lastName: 'Yadav', avatarUrl: 'https://example.com/avatar.jpg', handle: 'atulyadav' }); ``` ## Parameters | Parameter | Type | Description | | -------------------- | ------------------------------------------------------------------------------------------------ | --------------------------- | | `options` | \{ `avatarUrl?`: `string`; `firstName?`: `string`; `handle?`: `string`; `lastName?`: `string`; } | - | | `options.avatarUrl?` | `string` | The avatar URL of the user. | | `options.firstName?` | `string` | The first name of the user. | | `options.handle?` | `string` | The handle of the user. | | `options.lastName?` | `string` | The last name of the user. | ## Returns `Promise`\<`null` | `User`> # useSession Source: https://docs.modelence.com/api-reference/modelence/client/functions/useSession [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / useSession > **useSession**(): `object` Defined in: [packages/modelence/src/client/session.ts:222](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/session.ts#L222) `useSession` is a hook that returns the current user, and in the future will also return other details about the current session. ## Example ```ts theme={null} import { useSession } from 'modelence/client'; function MyComponent() { const { user } = useSession(); return
{user?.handle}
; } ``` ## Returns `object` | Name | Type | Defined in | | ------ | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `user` | `null` \| `User` | [packages/modelence/src/client/session.ts:224](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/session.ts#L224) | # verifyEmail Source: https://docs.modelence.com/api-reference/modelence/client/functions/verifyEmail [API Reference](/api-reference/modelence/client/functions/../../../index) / [modelence](/api-reference/modelence/client/functions/../../index) / [client](/api-reference/modelence/client/functions/../index) / verifyEmail > **verifyEmail**(`options`): `Promise`\<`void`> Defined in: [packages/modelence/src/auth/client/index.ts:127](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/client/index.ts#L127) Verify user's email with a verification token. ## Example ```ts theme={null} await verifyEmail({ token: 'verification-token' }); ``` ## Parameters | Parameter | Type | Description | | --------------- | ----------------------- | ----------------------------- | | `options` | \{ `token`: `string`; } | - | | `options.token` | `string` | The email verification token. | ## Returns `Promise`\<`void`> # client Source: https://docs.modelence.com/api-reference/modelence/client/index [API Reference](/api-reference/modelence/client/../../index) / [modelence](/api-reference/modelence/client/../index) / client ## Classes * [ClientChannel](/api-reference/modelence/client/classes/ClientChannel) * [MethodError](/api-reference/modelence/client/classes/MethodError) * [~~ModelenceQueryClient~~](/api-reference/modelence/client/classes/ModelenceQueryClient) ## Interfaces * [ClientConfig](/api-reference/modelence/client/interfaces/ClientConfig) ## Type Aliases * [CallMethodOptions](/api-reference/modelence/client/type-aliases/CallMethodOptions) * [MethodArgs](/api-reference/modelence/client/type-aliases/MethodArgs) * [ModelenceQueryKey](/api-reference/modelence/client/type-aliases/ModelenceQueryKey) * [UserInfo](/api-reference/modelence/client/type-aliases/UserInfo) ## Variables * [AppProvider](/api-reference/modelence/client/variables/AppProvider) * [systemConfig](/api-reference/modelence/client/variables/systemConfig) ## Functions * [callMethod](/api-reference/modelence/client/functions/callMethod) * [configureClient](/api-reference/modelence/client/functions/configureClient) * [connectModelenceQueryClient](/api-reference/modelence/client/functions/connectModelenceQueryClient) * [createClientModule](/api-reference/modelence/client/functions/createClientModule) * [createQueryKey](/api-reference/modelence/client/functions/createQueryKey) * [disconnectModelenceQueryClient](/api-reference/modelence/client/functions/disconnectModelenceQueryClient) * [getConfig](/api-reference/modelence/client/functions/getConfig) * [getLocalStorageSession](/api-reference/modelence/client/functions/getLocalStorageSession) * [getWebsocketClientProvider](/api-reference/modelence/client/functions/getWebsocketClientProvider) * [linkOAuthProvider](/api-reference/modelence/client/functions/linkOAuthProvider) * [loginWithMagicLink](/api-reference/modelence/client/functions/loginWithMagicLink) * [loginWithOneTimeCode](/api-reference/modelence/client/functions/loginWithOneTimeCode) * [loginWithPassword](/api-reference/modelence/client/functions/loginWithPassword) * [logout](/api-reference/modelence/client/functions/logout) * [modelenceLiveQuery](/api-reference/modelence/client/functions/modelenceLiveQuery) * [modelenceMutation](/api-reference/modelence/client/functions/modelenceMutation) * [modelenceQuery](/api-reference/modelence/client/functions/modelenceQuery) * [ModelenceQueryProvider](/api-reference/modelence/client/functions/ModelenceQueryProvider) * [renderApp](/api-reference/modelence/client/functions/renderApp) * [resendEmailVerification](/api-reference/modelence/client/functions/resendEmailVerification) * [resetPassword](/api-reference/modelence/client/functions/resetPassword) * [sendMagicLink](/api-reference/modelence/client/functions/sendMagicLink) * [sendResetPasswordToken](/api-reference/modelence/client/functions/sendResetPasswordToken) * [setWebsocketClientProvider](/api-reference/modelence/client/functions/setWebsocketClientProvider) * [signupWithPassword](/api-reference/modelence/client/functions/signupWithPassword) * [startWebsockets](/api-reference/modelence/client/functions/startWebsockets) * [subscribeLiveQuery](/api-reference/modelence/client/functions/subscribeLiveQuery) * [unlinkOAuthProvider](/api-reference/modelence/client/functions/unlinkOAuthProvider) * [updateProfile](/api-reference/modelence/client/functions/updateProfile) * [useSession](/api-reference/modelence/client/functions/useSession) * [verifyEmail](/api-reference/modelence/client/functions/verifyEmail) ## References ### ValueType Re-exports [ValueType](/api-reference/modelence/client/../server/type-aliases/ValueType) # ClientConfig Source: https://docs.modelence.com/api-reference/modelence/client/interfaces/ClientConfig [API Reference](/api-reference/modelence/client/interfaces/../../../index) / [modelence](/api-reference/modelence/client/interfaces/../../index) / [client](/api-reference/modelence/client/interfaces/../index) / ClientConfig Defined in: [packages/modelence/src/client/clientConfig.ts:3](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/clientConfig.ts#L3) ## Properties | Property | Type | Description | Defined in | | --------------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | |
`baseUrl` | `string` | - | [packages/modelence/src/client/clientConfig.ts:4](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/clientConfig.ts#L4) | | `credentials?` | `RequestCredentials` | Credentials mode for method-call requests. Defaults to `'include'`, which browser apps need for the cookie-based flows (password reset, magic link). Clients configured with token-in-body auth (React Native / Expo) never use cookies, so set `'omit'` there — on Expo Web a credentialed cross-origin request is otherwise blocked by any server answering `Access-Control-Allow-Origin: *`, surfacing as "TypeError: Failed to fetch". | [packages/modelence/src/client/clientConfig.ts:23](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/clientConfig.ts#L23) | | `getAuthToken` | () => `undefined` \| `string` | - | [packages/modelence/src/client/clientConfig.ts:5](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/clientConfig.ts#L5) | | `getClientInfo` | () => `ClientInfo` | - | [packages/modelence/src/client/clientConfig.ts:7](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/clientConfig.ts#L7) | | `openUrl?` | (`url`) => `void` | Opens a URL for OAuth redirects. React Native must use `(url) => Linking.openURL(url)` — WebView is not supported. Defaults to `window.location.href` when not provided. | [packages/modelence/src/client/clientConfig.ts:13](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/clientConfig.ts#L13) | | `setAuthToken` | (`token`) => `void` | - | [packages/modelence/src/client/clientConfig.ts:6](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/clientConfig.ts#L6) | # CallMethodOptions Source: https://docs.modelence.com/api-reference/modelence/client/type-aliases/CallMethodOptions [API Reference](/api-reference/modelence/client/type-aliases/../../../index) / [modelence](/api-reference/modelence/client/type-aliases/../../index) / [client](/api-reference/modelence/client/type-aliases/../index) / CallMethodOptions > **CallMethodOptions** = `object` Defined in: [packages/modelence/src/client/method.ts:35](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/method.ts#L35) ## Properties | Property | Type | Defined in | | --------------------- | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `errorHandler?` | (`error`, `methodName`) => `void` | [packages/modelence/src/client/method.ts:36](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/method.ts#L36) | # MethodArgs Source: https://docs.modelence.com/api-reference/modelence/client/type-aliases/MethodArgs [API Reference](/api-reference/modelence/client/type-aliases/../../../index) / [modelence](/api-reference/modelence/client/type-aliases/../../index) / [client](/api-reference/modelence/client/type-aliases/../index) / MethodArgs > **MethodArgs** = `Record`\<`string`, `unknown`> Defined in: [packages/modelence/src/client/method.ts:33](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/method.ts#L33) # ModelenceQueryKey Source: https://docs.modelence.com/api-reference/modelence/client/type-aliases/ModelenceQueryKey [API Reference](/api-reference/modelence/client/type-aliases/../../../index) / [modelence](/api-reference/modelence/client/type-aliases/../../index) / [client](/api-reference/modelence/client/type-aliases/../index) / ModelenceQueryKey > **ModelenceQueryKey**\<`T`, `U`> = readonly \[`T`, `U`] Defined in: [packages/modelence/src/client/query.ts:188](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/query.ts#L188) ## Type Parameters | Type Parameter | Default type | | ---------------------- | ------------ | | `T` *extends* `string` | - | | `U` *extends* `Args` | `Args` | # UserInfo Source: https://docs.modelence.com/api-reference/modelence/client/type-aliases/UserInfo [API Reference](/api-reference/modelence/client/type-aliases/../../../index) / [modelence](/api-reference/modelence/client/type-aliases/../../index) / [client](/api-reference/modelence/client/type-aliases/../index) / UserInfo > **UserInfo** = `object` Defined in: [packages/modelence/src/auth/client/index.ts:8](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/client/index.ts#L8) ## Properties | Property | Type | Defined in | | ------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `avatarUrl?` | `string` | [packages/modelence/src/auth/client/index.ts:16](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/client/index.ts#L16) | | `firstName?` | `string` | [packages/modelence/src/auth/client/index.ts:14](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/client/index.ts#L14) | | `handle` | `string` | [packages/modelence/src/auth/client/index.ts:10](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/client/index.ts#L10) | | `hasRole` | (`role`) => `boolean` | [packages/modelence/src/auth/client/index.ts:12](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/client/index.ts#L12) | | `id` | `string` | [packages/modelence/src/auth/client/index.ts:9](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/client/index.ts#L9) | | `lastName?` | `string` | [packages/modelence/src/auth/client/index.ts:15](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/client/index.ts#L15) | | `requireRole` | (`role`) => `void` | [packages/modelence/src/auth/client/index.ts:13](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/client/index.ts#L13) | | `roles` | `string`\[] | [packages/modelence/src/auth/client/index.ts:11](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/client/index.ts#L11) | # AppProvider Source: https://docs.modelence.com/api-reference/modelence/client/variables/AppProvider [API Reference](/api-reference/modelence/client/variables/../../../index) / [modelence](/api-reference/modelence/client/variables/../../index) / [client](/api-reference/modelence/client/variables/../index) / AppProvider > `const` **AppProvider**: `any` Defined in: [packages/modelence/src/client.ts:11](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client.ts#L11) # systemConfig Source: https://docs.modelence.com/api-reference/modelence/client/variables/systemConfig [API Reference](/api-reference/modelence/client/variables/../../../index) / [modelence](/api-reference/modelence/client/variables/../../index) / [client](/api-reference/modelence/client/variables/../index) / systemConfig > `const` **systemConfig**: `object` Defined in: [packages/modelence/src/system/client.ts:4](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/system/client.ts#L4) ## Type declaration | Name | Type | Description | Defined in | | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `getConfig()` | (`key`) => `undefined` \| `PublicKeyOf`\<\{ `env.type`: \{ `default`: `string`; `isPublic`: `true`; `type`: `"string"`; }; `mongodbPoolSize`: \{ `default`: `number`; `isPublic`: `false`; `type`: `"number"`; }; `mongodbUri`: \{ `default`: `string`; `isPublic`: `false`; `type`: `"secret"`; }; `multiInstance`: \{ `default`: `false`; `isPublic`: `false`; `type`: `"boolean"`; }; `site.url`: \{ `default`: `string`; `isPublic`: `true`; `type`: `"string"`; }; }>\[`K`] | - | [packages/modelence/src/client/module.ts:90](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/module.ts#L90) | | `infiniteQuery()` | (`name`, `getArgs`) => `object` | Returns options for `useInfiniteQuery`. The `getArgs` callback receives the current `pageParam` and returns the args to pass to the query handler. Spread the result into `useInfiniteQuery` alongside `getNextPageParam`. Annotate the `pageParam` type in the callback so TypeScript can infer the page param type — no manual generic needed on `useInfiniteQuery`. | [packages/modelence/src/client/module.ts:134](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/module.ts#L134) | | `mutation()` | (`name`) => `object` | - | [packages/modelence/src/client/module.ts:114](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/module.ts#L114) | | `query()` | (`name`, ...`rest`) => `object` | - | [packages/modelence/src/client/module.ts:97](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/client/module.ts#L97) | # modelence Source: https://docs.modelence.com/api-reference/modelence/index [API Reference](/api-reference/modelence/../index) / modelence ## Modules * [client](/api-reference/modelence/client/index) * [index](/api-reference/modelence/index/index) * [server](/api-reference/modelence/server/index) # AuthError Source: https://docs.modelence.com/api-reference/modelence/index/classes/AuthError [API Reference](/api-reference/modelence/index/classes/../../../index) / [modelence](/api-reference/modelence/index/classes/../../index) / [index](/api-reference/modelence/index/classes/../index) / AuthError Defined in: [packages/modelence/src/error.ts:10](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/error.ts#L10) ## Extends * [`ModelenceError`](/api-reference/modelence/index/classes/ModelenceError) ## Constructors ### Constructor > **new AuthError**(`message`, `code?`): `AuthError` Defined in: [packages/modelence/src/error.ts:13](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/error.ts#L13) #### Parameters | Parameter | Type | | --------- | -------- | | `message` | `string` | | `code?` | `string` | #### Returns `AuthError` #### Overrides [`ModelenceError`](/api-reference/modelence/index/classes/ModelenceError).[`constructor`](ModelenceError#constructor) ## Properties | Property | Type | Default value | Description | Overrides | Inherited from | Defined in | | -------------- | -------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `code?` | `string` | `undefined` | Optional machine-readable error code so clients can branch on the kind of error without string-matching `message` (which may be reworded or localized). | - | [`ModelenceError`](/api-reference/modelence/index/classes/ModelenceError).[`code`](ModelenceError#code) | [packages/modelence/src/error.ts:7](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/error.ts#L7) | | `status` | `number` | `401` | - | [`ModelenceError`](/api-reference/modelence/index/classes/ModelenceError).[`status`](ModelenceError#status) | - | [packages/modelence/src/error.ts:11](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/error.ts#L11) | # ModelenceError Source: https://docs.modelence.com/api-reference/modelence/index/classes/ModelenceError [API Reference](/api-reference/modelence/index/classes/../../../index) / [modelence](/api-reference/modelence/index/classes/../../index) / [index](/api-reference/modelence/index/classes/../index) / ModelenceError Defined in: [packages/modelence/src/error.ts:1](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/error.ts#L1) ## Extends * `Error` ## Extended by * [`AuthError`](/api-reference/modelence/index/classes/AuthError) * [`ValidationError`](/api-reference/modelence/index/classes/ValidationError) * [`RateLimitError`](/api-reference/modelence/index/classes/RateLimitError) ## Constructors ### Constructor > **new ModelenceError**(`message?`): `ModelenceError` Defined in: docs/gen/node\_modules/typescript/lib/lib.es5.d.ts:1082 #### Parameters | Parameter | Type | | ---------- | -------- | | `message?` | `string` | #### Returns `ModelenceError` #### Inherited from `Error.constructor` ## Properties | Property | Modifier | Type | Description | Defined in | | -------------- | ---------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `code?` | `public` | `string` | Optional machine-readable error code so clients can branch on the kind of error without string-matching `message` (which may be reworded or localized). | [packages/modelence/src/error.ts:7](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/error.ts#L7) | | `status` | `abstract` | `number` | - | [packages/modelence/src/error.ts:2](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/error.ts#L2) | # RateLimitError Source: https://docs.modelence.com/api-reference/modelence/index/classes/RateLimitError [API Reference](/api-reference/modelence/index/classes/../../../index) / [modelence](/api-reference/modelence/index/classes/../../index) / [index](/api-reference/modelence/index/classes/../index) / RateLimitError Defined in: [packages/modelence/src/error.ts:30](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/error.ts#L30) ## Extends * [`ModelenceError`](/api-reference/modelence/index/classes/ModelenceError) ## Constructors ### Constructor > **new RateLimitError**(`message`): `RateLimitError` Defined in: [packages/modelence/src/error.ts:33](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/error.ts#L33) #### Parameters | Parameter | Type | | --------- | -------- | | `message` | `string` | #### Returns `RateLimitError` #### Overrides [`ModelenceError`](/api-reference/modelence/index/classes/ModelenceError).[`constructor`](ModelenceError#constructor) ## Properties | Property | Type | Default value | Description | Overrides | Inherited from | Defined in | | -------------- | -------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `code?` | `string` | `undefined` | Optional machine-readable error code so clients can branch on the kind of error without string-matching `message` (which may be reworded or localized). | - | [`ModelenceError`](/api-reference/modelence/index/classes/ModelenceError).[`code`](ModelenceError#code) | [packages/modelence/src/error.ts:7](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/error.ts#L7) | | `status` | `number` | `429` | - | [`ModelenceError`](/api-reference/modelence/index/classes/ModelenceError).[`status`](ModelenceError#status) | - | [packages/modelence/src/error.ts:31](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/error.ts#L31) | # ValidationError Source: https://docs.modelence.com/api-reference/modelence/index/classes/ValidationError [API Reference](/api-reference/modelence/index/classes/../../../index) / [modelence](/api-reference/modelence/index/classes/../../index) / [index](/api-reference/modelence/index/classes/../index) / ValidationError Defined in: [packages/modelence/src/error.ts:20](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/error.ts#L20) ## Extends * [`ModelenceError`](/api-reference/modelence/index/classes/ModelenceError) ## Constructors ### Constructor > **new ValidationError**(`message`, `code?`): `ValidationError` Defined in: [packages/modelence/src/error.ts:23](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/error.ts#L23) #### Parameters | Parameter | Type | | --------- | -------- | | `message` | `string` | | `code?` | `string` | #### Returns `ValidationError` #### Overrides [`ModelenceError`](/api-reference/modelence/index/classes/ModelenceError).[`constructor`](ModelenceError#constructor) ## Properties | Property | Type | Default value | Description | Overrides | Inherited from | Defined in | | -------------- | -------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `code?` | `string` | `undefined` | Optional machine-readable error code so clients can branch on the kind of error without string-matching `message` (which may be reworded or localized). | - | [`ModelenceError`](/api-reference/modelence/index/classes/ModelenceError).[`code`](ModelenceError#code) | [packages/modelence/src/error.ts:7](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/error.ts#L7) | | `status` | `number` | `400` | - | [`ModelenceError`](/api-reference/modelence/index/classes/ModelenceError).[`status`](ModelenceError#status) | - | [packages/modelence/src/error.ts:21](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/error.ts#L21) | # index Source: https://docs.modelence.com/api-reference/modelence/index/index [API Reference](/api-reference/modelence/index/../../index) / [modelence](/api-reference/modelence/index/../index) / index ## Classes * [AuthError](/api-reference/modelence/index/classes/AuthError) * [ModelenceError](/api-reference/modelence/index/classes/ModelenceError) * [RateLimitError](/api-reference/modelence/index/classes/RateLimitError) * [ValidationError](/api-reference/modelence/index/classes/ValidationError) ## Interfaces * [ModelenceConfig](/api-reference/modelence/index/interfaces/ModelenceConfig) * [WebsocketClientProvider](/api-reference/modelence/index/interfaces/WebsocketClientProvider) * [WebsocketServerProvider](/api-reference/modelence/index/interfaces/WebsocketServerProvider) ## Type Aliases * [ConfigSchema](/api-reference/modelence/index/type-aliases/ConfigSchema) ## Variables * [time](/api-reference/modelence/index/variables/time) # ModelenceConfig Source: https://docs.modelence.com/api-reference/modelence/index/interfaces/ModelenceConfig [API Reference](/api-reference/modelence/index/interfaces/../../../index) / [modelence](/api-reference/modelence/index/interfaces/../../index) / [index](/api-reference/modelence/index/interfaces/../index) / ModelenceConfig Defined in: [packages/modelence/src/types/index.ts:4](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/types/index.ts#L4) ## Properties | Property | Type | Defined in | | ------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `postBuildCommand?` | `string` | [packages/modelence/src/types/index.ts:7](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/types/index.ts#L7) | | `serverDir` | `string` | [packages/modelence/src/types/index.ts:5](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/types/index.ts#L5) | | `serverEntry` | `string` | [packages/modelence/src/types/index.ts:6](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/types/index.ts#L6) | # WebsocketClientProvider Source: https://docs.modelence.com/api-reference/modelence/index/interfaces/WebsocketClientProvider [API Reference](/api-reference/modelence/index/interfaces/../../../index) / [modelence](/api-reference/modelence/index/interfaces/../../index) / [index](/api-reference/modelence/index/interfaces/../index) / WebsocketClientProvider Defined in: [packages/modelence/src/websocket/types.ts:10](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/websocket/types.ts#L10) ## Methods ### emit() > **emit**(`props`): `void` Defined in: [packages/modelence/src/websocket/types.ts:15](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/websocket/types.ts#L15) #### Parameters | Parameter | Type | | ----------------- | ----------------------------------------------------------------- | | `props` | \{ `category`: `string`; `eventName`: `string`; `id`: `string`; } | | `props.category` | `string` | | `props.eventName` | `string` | | `props.id` | `string` | #### Returns `void` *** ### init() > **init**(`props`): `void` Defined in: [packages/modelence/src/websocket/types.ts:11](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/websocket/types.ts#L11) #### Parameters | Parameter | Type | | ----------------- | --------------------------------------------------------------------------------------------------------------------------------- | | `props` | \{ `channels?`: [`ClientChannel`](/api-reference/modelence/index/interfaces/../../client/classes/ClientChannel)\<`unknown`>\[]; } | | `props.channels?` | [`ClientChannel`](/api-reference/modelence/index/interfaces/../../client/classes/ClientChannel)\<`unknown`>\[] | #### Returns `void` *** ### joinChannel() > **joinChannel**(`props`): `void` Defined in: [packages/modelence/src/websocket/types.ts:16](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/websocket/types.ts#L16) #### Parameters | Parameter | Type | | ---------------- | ------------------------------------------ | | `props` | \{ `category`: `string`; `id`: `string`; } | | `props.category` | `string` | | `props.id` | `string` | #### Returns `void` *** ### leaveChannel() > **leaveChannel**(`props`): `void` Defined in: [packages/modelence/src/websocket/types.ts:17](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/websocket/types.ts#L17) #### Parameters | Parameter | Type | | ---------------- | ------------------------------------------ | | `props` | \{ `category`: `string`; `id`: `string`; } | | `props.category` | `string` | | `props.id` | `string` | #### Returns `void` *** ### off() > **off**\<`T`>(`props`): `void` Defined in: [packages/modelence/src/websocket/types.ts:14](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/websocket/types.ts#L14) #### Type Parameters | Type Parameter | | -------------- | | `T` | #### Parameters | Parameter | Type | | ---------------- | ---------------------------------------------------------- | | `props` | \{ `category`: `string`; `listener`: (`data`) => `void`; } | | `props.category` | `string` | | `props.listener` | (`data`) => `void` | #### Returns `void` *** ### on() > **on**\<`T`>(`props`): `void` Defined in: [packages/modelence/src/websocket/types.ts:12](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/websocket/types.ts#L12) #### Type Parameters | Type Parameter | | -------------- | | `T` | #### Parameters | Parameter | Type | | ---------------- | ---------------------------------------------------------- | | `props` | \{ `category`: `string`; `listener`: (`data`) => `void`; } | | `props.category` | `string` | | `props.listener` | (`data`) => `void` | #### Returns `void` *** ### once() > **once**\<`T`>(`props`): `void` Defined in: [packages/modelence/src/websocket/types.ts:13](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/websocket/types.ts#L13) #### Type Parameters | Type Parameter | | -------------- | | `T` | #### Parameters | Parameter | Type | | ---------------- | ---------------------------------------------------------- | | `props` | \{ `category`: `string`; `listener`: (`data`) => `void`; } | | `props.category` | `string` | | `props.listener` | (`data`) => `void` | #### Returns `void` # WebsocketServerProvider Source: https://docs.modelence.com/api-reference/modelence/index/interfaces/WebsocketServerProvider [API Reference](/api-reference/modelence/index/interfaces/../../../index) / [modelence](/api-reference/modelence/index/interfaces/../../index) / [index](/api-reference/modelence/index/interfaces/../index) / WebsocketServerProvider Defined in: [packages/modelence/src/websocket/types.ts:5](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/websocket/types.ts#L5) ## Methods ### broadcast() > **broadcast**\<`T`>(`props`): `void` Defined in: [packages/modelence/src/websocket/types.ts:7](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/websocket/types.ts#L7) #### Type Parameters | Type Parameter | | -------------- | | `T` | #### Parameters | Parameter | Type | | ---------------- | ------------------------------------------------------- | | `props` | \{ `category`: `string`; `data`: `T`; `id`: `string`; } | | `props.category` | `string` | | `props.data` | `T` | | `props.id` | `string` | #### Returns `void` *** ### init() > **init**(`props`): `Promise`\<`void`> Defined in: [packages/modelence/src/websocket/types.ts:6](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/websocket/types.ts#L6) #### Parameters | Parameter | Type | | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- | | `props` | \{ `channels`: [`ServerChannel`](/api-reference/modelence/index/interfaces/../../server/classes/ServerChannel)\<`unknown`>\[]; `httpServer`: `Server`; } | | `props.channels` | [`ServerChannel`](/api-reference/modelence/index/interfaces/../../server/classes/ServerChannel)\<`unknown`>\[] | | `props.httpServer` | `Server` | #### Returns `Promise`\<`void`> # ConfigSchema Source: https://docs.modelence.com/api-reference/modelence/index/type-aliases/ConfigSchema [API Reference](/api-reference/modelence/index/type-aliases/../../../index) / [modelence](/api-reference/modelence/index/type-aliases/../../index) / [index](/api-reference/modelence/index/type-aliases/../index) / ConfigSchema > **ConfigSchema** = `object` Defined in: [packages/modelence/src/config/types.ts:81](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/config/types.ts#L81) Defines the configuration schema for a module. Each key becomes a namespaced config value accessible via `getConfig('moduleName.key')`. ## Example ```ts theme={null} import { Module } from 'modelence/server'; export default new Module('payments', { configSchema: { apiKey: { type: 'secret', default: '', isPublic: false, }, currency: { type: 'string', default: 'USD', isPublic: true, }, }, }); ``` ## Index Signature \[`key`: `string`]: `ConfigParams`\<[`ConfigType`](/api-reference/modelence/index/type-aliases/../../server/type-aliases/ConfigType), `boolean`> # time Source: https://docs.modelence.com/api-reference/modelence/index/variables/time [API Reference](/api-reference/modelence/index/variables/../../../index) / [modelence](/api-reference/modelence/index/variables/../../index) / [index](/api-reference/modelence/index/variables/../index) / time > `const` **time**: `object` Defined in: [packages/modelence/src/time.ts:7](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/time.ts#L7) ## Type declaration | Name | Type | Defined in | | ----------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `days()` | (`x`) => `number` | [packages/modelence/src/time.ts:11](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/time.ts#L11) | | `hours()` | (`x`) => `number` | [packages/modelence/src/time.ts:10](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/time.ts#L10) | | `minutes()` | (`x`) => `number` | [packages/modelence/src/time.ts:9](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/time.ts#L9) | | `seconds()` | (`x`) => `number` | [packages/modelence/src/time.ts:8](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/time.ts#L8) | | `weeks()` | (`x`) => `number` | [packages/modelence/src/time.ts:12](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/time.ts#L12) | # LiveData Source: https://docs.modelence.com/api-reference/modelence/server/classes/LiveData [API Reference](/api-reference/modelence/server/classes/../../../index) / [modelence](/api-reference/modelence/server/classes/../../index) / [server](/api-reference/modelence/server/classes/../index) / LiveData Defined in: [packages/modelence/src/live-query/context.ts:65](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/live-query/context.ts#L65) LiveData object returned by live query handlers. ## Example ```typescript theme={null} import { LiveData } from 'modelence/server'; ... getTodos({ userId }, context) { return new LiveData({ fetch: async () => await dbTodos.fetch({ userId }), watch: ({ publish }) => { // Subscribe to changes and call publish when data changes listener.onChange(publish); return () => { // Cleanup function to unsubscribe from changes }; } }); } ``` ## Type Parameters | Type Parameter | Default type | | -------------- | ------------ | | `T` | `unknown` | ## Constructors ### Constructor > **new LiveData**\<`T`>(`config`): `LiveData`\<`T`> Defined in: [packages/modelence/src/live-query/context.ts:69](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/live-query/context.ts#L69) #### Parameters | Parameter | Type | | --------- | ---------------------------------------------------------------------------------------------- | | `config` | [`LiveDataConfig`](/api-reference/modelence/server/classes/../interfaces/LiveDataConfig)\<`T`> | #### Returns `LiveData`\<`T`> ## Properties | Property | Modifier | Type | Defined in | | ------------- | ---------- | ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `fetch` | `readonly` | () => `T` \| `Promise`\<`T`> | [packages/modelence/src/live-query/context.ts:66](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/live-query/context.ts#L66) | | `watch` | `readonly` | [`LiveQueryWatch`](/api-reference/modelence/server/classes/../type-aliases/LiveQueryWatch) | [packages/modelence/src/live-query/context.ts:67](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/live-query/context.ts#L67) | # Module Source: https://docs.modelence.com/api-reference/modelence/server/classes/Module [API Reference](/api-reference/modelence/server/classes/../../../index) / [modelence](/api-reference/modelence/server/classes/../../index) / [server](/api-reference/modelence/server/classes/../index) / Module Defined in: [packages/modelence/src/app/module.ts:43](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/module.ts#L43) The Module class is a core building block of a Modelence application that encapsulates related functionality. Modules can contain stores, queries, mutations, routes, cron jobs and configurations. ## Example ```ts theme={null} const todoModule = new Module('todo', { stores: [dbTodos], queries: { async getAll() { // Fetch and return all Todo items } }, mutations: { async create({ title }, { user }) { // Create a new Todo item } } }); ``` ## Type Parameters | Type Parameter | Default type | | ------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | | `TName` *extends* `string` | `string` | | `TSchema` *extends* `Record`\<`string`, `ConfigParams`> | [`ConfigSchema`](/api-reference/modelence/server/classes/../../index/type-aliases/ConfigSchema) | | `TQueries` *extends* `Queries` | `Queries` | | `TMutations` *extends* `Mutations` | `Mutations` | ## Constructors ### Constructor > **new Module**\<`TName`, `TSchema`, `TQueries`, `TMutations`>(`name`, `options`): `Module`\<`TName`, `TSchema`, `TQueries`, `TMutations`> Defined in: [packages/modelence/src/app/module.ts:85](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/module.ts#L85) Creates a new Module instance #### Parameters | Parameter | Type | Description | | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | `name` | `TName` | The unique name of the module. This name is used to namespace queries, mutations, cron jobs and configuration values with a prefix (e.g. "todo.create") | | `options` | \{ `channels?`: [`ServerChannel`](/api-reference/modelence/server/classes/ServerChannel)\<`unknown`>\[]; `configSchema?`: `TSchema`; `cronJobs?`: `Record`\<`string`, [`CronJobInputParams`](/api-reference/modelence/server/classes/../type-aliases/CronJobInputParams)>; `mutations?`: `TMutations`; `queries?`: `TQueries`; `rateLimits?`: [`RateLimitRule`](/api-reference/modelence/server/classes/../type-aliases/RateLimitRule)\[]; `routes?`: [`RouteDefinition`](/api-reference/modelence/server/classes/../type-aliases/RouteDefinition)\[]; `stores?`: [`Store`](/api-reference/modelence/server/classes/Store)\<`any`, `any`>\[]; } | Module configuration options | | `options.channels?` | [`ServerChannel`](/api-reference/modelence/server/classes/ServerChannel)\<`unknown`>\[] | - | | `options.configSchema?` | `TSchema` | - | | `options.cronJobs?` | `Record`\<`string`, [`CronJobInputParams`](/api-reference/modelence/server/classes/../type-aliases/CronJobInputParams)> | - | | `options.mutations?` | `TMutations` | - | | `options.queries?` | `TQueries` | - | | `options.rateLimits?` | [`RateLimitRule`](/api-reference/modelence/server/classes/../type-aliases/RateLimitRule)\[] | - | | `options.routes?` | [`RouteDefinition`](/api-reference/modelence/server/classes/../type-aliases/RouteDefinition)\[] | - | | `options.stores?` | [`Store`](/api-reference/modelence/server/classes/Store)\<`any`, `any`>\[] | - | #### Returns `Module`\<`TName`, `TSchema`, `TQueries`, `TMutations`> ## Methods ### getConfig() > **getConfig**\<`K`>(`key`): [`ValueType`](/api-reference/modelence/server/classes/../type-aliases/ValueType)\<`TSchema`\[`K`]\[`"type"`]> Defined in: [packages/modelence/src/app/module.ts:139](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/module.ts#L139) Retrieves a typed configuration value for this module. The return type is inferred from the schema — no casts needed. #### Example ```ts theme={null} const myModule = new Module('payments', { configSchema: { apiKey: { type: 'secret', default: '', isPublic: false }, maxRetries: { type: 'number', default: 3, isPublic: false }, }, mutations: { async charge({ amount }) { const apiKey = myModule.getConfig('apiKey'); // string const maxRetries = myModule.getConfig('maxRetries'); // number }, }, }); ``` #### Type Parameters | Type Parameter | | ---------------------- | | `K` *extends* `string` | #### Parameters | Parameter | Type | | --------- | ---- | | `key` | `K` | #### Returns [`ValueType`](/api-reference/modelence/server/classes/../type-aliases/ValueType)\<`TSchema`\[`K`]\[`"type"`]> # ServerChannel Source: https://docs.modelence.com/api-reference/modelence/server/classes/ServerChannel [API Reference](/api-reference/modelence/server/classes/../../../index) / [modelence](/api-reference/modelence/server/classes/../../index) / [server](/api-reference/modelence/server/classes/../index) / ServerChannel Defined in: [packages/modelence/src/websocket/serverChannel.ts:11](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/websocket/serverChannel.ts#L11) ## Type Parameters | Type Parameter | Default type | | -------------- | ------------ | | `T` | `unknown` | ## Constructors ### Constructor > **new ServerChannel**\<`T`>(`category`, `canAccessChannel?`): `ServerChannel`\<`T`> Defined in: [packages/modelence/src/websocket/serverChannel.ts:15](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/websocket/serverChannel.ts#L15) #### Parameters | Parameter | Type | | ------------------- | ------------------ | | `category` | `string` | | `canAccessChannel?` | `canAccessChannel` | #### Returns `ServerChannel`\<`T`> ## Properties | Property | Modifier | Type | Defined in | | ------------------------ | ---------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `canAccessChannel` | `readonly` | `null` \| `canAccessChannel` | [packages/modelence/src/websocket/serverChannel.ts:13](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/websocket/serverChannel.ts#L13) | | `category` | `readonly` | `string` | [packages/modelence/src/websocket/serverChannel.ts:12](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/websocket/serverChannel.ts#L12) | ## Methods ### broadcast() > **broadcast**(`id`, `data`): `void` Defined in: [packages/modelence/src/websocket/serverChannel.ts:20](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/websocket/serverChannel.ts#L20) #### Parameters | Parameter | Type | | --------- | -------- | | `id` | `string` | | `data` | `T` | #### Returns `void` # Store Source: https://docs.modelence.com/api-reference/modelence/server/classes/Store [API Reference](/api-reference/modelence/server/classes/../../../index) / [modelence](/api-reference/modelence/server/classes/../../index) / [server](/api-reference/modelence/server/classes/../index) / Store Defined in: [packages/modelence/src/data/store.ts:382](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L382) The Store class provides a type-safe interface for MongoDB collections with built-in schema validation and helper methods. ## Example ```ts theme={null} const dbTodos = new Store('todos', { schema: { title: schema.string(), completed: schema.boolean(), dueDate: schema.date().optional(), userId: schema.userId(), }, methods: { isOverdue() { return this.dueDate < new Date(); } } }); ``` ## Type Parameters | Type Parameter | Description | | ---------------------------------------------------------------------- | ---------------------------------------------- | | `TSchema` *extends* `ModelSchema` | The document schema type | | `TMethods` *extends* `Record`\<`string`, (`this`, ...`args`) => `any`> | Custom methods that will be added to documents | ## Constructors ### Constructor > **new Store**\<`TSchema`, `TMethods`>(`name`, `options`): `Store`\<`TSchema`, `TMethods`> Defined in: [packages/modelence/src/data/store.ts:418](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L418) Creates a new Store instance #### Parameters | Parameter | Type | Description | | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | | `name` | `string` | The collection name in MongoDB | | `options` | \{ `indexCreationMode?`: `IndexCreationMode`; `indexes`: `IndexDescription`\[]; `methods?`: `TMethods`; `schema`: `TSchema`; `searchIndexes?`: `SearchIndexDescription`\[]; } | Store configuration (schema, indexes, methods, search indexes, and optional index creation mode) | | `options.indexCreationMode?` | `IndexCreationMode` | Whether index creation should block startup or run in background (default: 'background') | | `options.indexes` | `IndexDescription`\[] | MongoDB indexes to create | | `options.methods?` | `TMethods` | Custom methods to add to documents | | `options.schema` | `TSchema` | Document schema using Modelence schema types | | `options.searchIndexes?` | `SearchIndexDescription`\[] | MongoDB Atlas Search | #### Returns `Store`\<`TSchema`, `TMethods`> ## Properties | Property | Modifier | Type | Defined in | | ----------- | ---------- | --------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `Doc` | `readonly` | `EnhancedOmit`\<`InferDocumentType`\<`TSchema`>, `"_id"`> & `object` & `TMethods` | [packages/modelence/src/data/store.ts:397](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L397) | ## Methods ### aggregate() > **aggregate**(`pipeline`, `options?`): `AggregationCursor`\<`Document`> Defined in: [packages/modelence/src/data/store.ts:1250](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L1250) Aggregates documents using MongoDB's aggregation framework #### Parameters | Parameter | Type | Description | | ---------- | ------------------ | ------------------------ | | `pipeline` | `Document`\[] | The aggregation pipeline | | `options?` | `AggregateOptions` | Optional options | #### Returns `AggregationCursor`\<`Document`> The aggregation cursor *** ### bulkWrite() > **bulkWrite**(`operations`): `Promise`\<`BulkWriteResult`> Defined in: [packages/modelence/src/data/store.ts:1260](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L1260) Performs a bulk write operation on the collection #### Parameters | Parameter | Type | Description | | ------------ | ------------------------------------------------------------ | ------------------------- | | `operations` | `AnyBulkWriteOperation`\<`InferDocumentType`\<`TSchema`>>\[] | The operations to perform | #### Returns `Promise`\<`BulkWriteResult`> The result of the bulk write operation *** ### countDocuments() > **countDocuments**(`query`): `Promise`\<`number`> Defined in: [packages/modelence/src/data/store.ts:894](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L894) Counts the number of documents that match a query #### Parameters | Parameter | Type | Description | | --------- | ----------------------------------------------- | ----------------------------- | | `query` | `TypedFilter`\<`InferDocumentType`\<`TSchema`>> | The query to filter documents | #### Returns `Promise`\<`number`> The number of documents that match the query *** ### create() > **create**(`document`, `options?`): `Promise`\<`EnhancedOmit`\<`InferDocumentType`\<`TSchema`>, `"_id"`> & `object` & `TMethods`> Defined in: [packages/modelence/src/data/store.ts:963](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L963) Inserts a single document and returns the inserted document with its generated `_id` and any helper methods applied. Unlike [insertOne](/api-reference/modelence/server/classes/Store#insertone), which only returns the insert result metadata, this method returns the full inserted document — useful when you need to immediately use the newly created record (e.g. returning it from an API handler). #### Example ```ts theme={null} const todo = await dbTodos.create({ title: 'Buy milk', completed: false }); console.log(todo._id); // ObjectId console.log(todo.title); // 'Buy milk' ``` #### Parameters | Parameter | Type | Description | | ------------------ | ------------------------------------------------------------ | ---------------------- | | `document` | `OptionalUnlessRequiredId`\<`InferDocumentType`\<`TSchema`>> | The document to insert | | `options?` | \{ `session?`: `ClientSession`; } | - | | `options.session?` | `ClientSession` | - | #### Returns `Promise`\<`EnhancedOmit`\<`InferDocumentType`\<`TSchema`>, `"_id"`> & `object` & `TMethods`> The inserted document with `_id` populated and methods applied *** ### deleteMany() > **deleteMany**(`selector`, `options?`): `Promise`\<`DeleteResult`> Defined in: [packages/modelence/src/data/store.ts:1079](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L1079) Deletes multiple documents #### Parameters | Parameter | Type | Description | | ------------------ | ----------------------------------------------- | -------------------------------------------- | | `selector` | `TypedFilter`\<`InferDocumentType`\<`TSchema`>> | The selector to find the documents to delete | | `options?` | \{ `session?`: `ClientSession`; } | - | | `options.session?` | `ClientSession` | - | #### Returns `Promise`\<`DeleteResult`> The result of the delete operation *** ### deleteOne() > **deleteOne**(`selector`, `options?`): `Promise`\<`DeleteResult`> Defined in: [packages/modelence/src/data/store.ts:1066](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L1066) Deletes a single document #### Parameters | Parameter | Type | Description | | ------------------ | ------------------------------------------------------------------------- | ------------------------------------------- | | `selector` | `string` \| `ObjectId` \| `TypedFilter`\<`InferDocumentType`\<`TSchema`>> | The selector to find the document to delete | | `options?` | \{ `session?`: `ClientSession`; } | - | | `options.session?` | `ClientSession` | - | #### Returns `Promise`\<`DeleteResult`> The result of the delete operation *** ### distinct() > **distinct**\<`K`>(`key`, `filter?`, `options?`): `Promise`\<`Flatten`\<`WithId`\<`InferDocumentType`\<`TSchema`>>\[`K`]>\[]> Defined in: [packages/modelence/src/data/store.ts:1221](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L1221) Returns an array of distinct values for a field across the collection #### Type Parameters | Type Parameter | | ---------------------- | | `K` *extends* `string` | #### Parameters | Parameter | Type | Description | | ---------- | ----------------------------------------------- | -------------------------------------------------------- | | `key` | `K` | The field name (supports dot notation for nested fields) | | `filter?` | `TypedFilter`\<`InferDocumentType`\<`TSchema`>> | Optional filter to narrow the documents | | `options?` | `DistinctOptions` | Optional distinct options | #### Returns `Promise`\<`Flatten`\<`WithId`\<`InferDocumentType`\<`TSchema`>>\[`K`]>\[]> An array of distinct values *** ### extend() > **extend**\<`TExtendedSchema`, `TExtendedMethods`>(`config`): `Store`\<`TSchema` & `TExtendedSchema`, `PreserveMethodsForExtendedSchema`\<`TMethods`, `TSchema` & `TExtendedSchema`> & `TExtendedMethods`> Defined in: [packages/modelence/src/data/store.ts:521](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L521) Extends the store with additional schema fields, indexes, methods, and search indexes. Returns a new Store instance with the extended schema and updated types. Methods from the original store are preserved with updated type signatures. #### Example ```ts theme={null} // Extend the users collection export const dbUsers = baseUsersCollection.extend({ schema: { firstName: schema.string(), lastName: schema.string(), companyId: schema.objectId().optional(), }, indexes: [ { key: { companyId: 1 } }, { key: { lastName: 1, firstName: 1 } }, ], methods: { getFullName() { return `${this.firstName} ${this.lastName}`; } } }); // Now fully typed with new fields const user = await dbUsers.findOne({ firstName: 'John' }); console.log(user?.getFullName()); ``` #### Type Parameters | Type Parameter | Default type | | ------------------------------------------------------------ | ---------------------------- | | `TExtendedSchema` *extends* `ModelSchema` | - | | `TExtendedMethods` *extends* `Record`\<`string`, `Function`> | `Record`\<`string`, `never`> | #### Parameters | Parameter | Type | Description | | --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | | `config` | \{ `indexCreationMode?`: `IndexCreationMode`; `indexes?`: `IndexDescription`\[]; `methods?`: `TExtendedMethods`; `schema?`: `TExtendedSchema`; `searchIndexes?`: `SearchIndexDescription`\[]; } | Additional schema fields, indexes, methods, search indexes, and optional index creation mode to add | | `config.indexCreationMode?` | `IndexCreationMode` | Whether index creation should block startup or run in background | | `config.indexes?` | `IndexDescription`\[] | - | | `config.methods?` | `TExtendedMethods` | - | | `config.schema?` | `TExtendedSchema` | - | | `config.searchIndexes?` | `SearchIndexDescription`\[] | - | #### Returns `Store`\<`TSchema` & `TExtendedSchema`, `PreserveMethodsForExtendedSchema`\<`TMethods`, `TSchema` & `TExtendedSchema`> & `TExtendedMethods`> A new Store instance with the extended schema *** ### fetch() > **fetch**(`query`, `options?`): `Promise`\<`EnhancedOmit`\<`InferDocumentType`\<`TSchema`>, `"_id"`> & `object` & `TMethods`\[]> Defined in: [packages/modelence/src/data/store.ts:924](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L924) Fetches multiple documents, equivalent to Node.js MongoDB driver's `find` and `toArray` methods combined. #### Example ```ts theme={null} // Include only selected fields const docs = await store.fetch( { userId: user.id }, { projection: { framework: 1, title: 1 }, sort: { createdAt: -1 }, limit: 50 } ); // Exclude large fields when not needed const chunks = await store.fetch( { documentId }, { projection: { embedding: 0 } } ); ``` #### Parameters | Parameter | Type | Description | | ---------- | ------------------------------------------------ | ----------------------------- | | `query` | `TypedFilter`\<`InferDocumentType`\<`TSchema`>> | The query to filter documents | | `options?` | `FetchOptions`\<`InferDocumentType`\<`TSchema`>> | Optional fetch options | #### Returns `Promise`\<`EnhancedOmit`\<`InferDocumentType`\<`TSchema`>, `"_id"`> & `object` & `TMethods`\[]> The documents *** ### findById() > **findById**(`id`): `Promise`\<`null` | `EnhancedOmit`\<`InferDocumentType`\<`TSchema`>, `"_id"`> & `object` & `TMethods`> Defined in: [packages/modelence/src/data/store.ts:866](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L866) Fetches a single document by its ID #### Parameters | Parameter | Type | Description | | --------- | ---------------------- | ------------------------------ | | `id` | `string` \| `ObjectId` | The ID of the document to find | #### Returns `Promise`\<`null` | `EnhancedOmit`\<`InferDocumentType`\<`TSchema`>, `"_id"`> & `object` & `TMethods`> The document, or null if not found *** ### findOne() > **findOne**(`query`, `options?`): `Promise`\<`null` | `EnhancedOmit`\<`InferDocumentType`\<`TSchema`>, `"_id"`> & `object` & `TMethods`> Defined in: [packages/modelence/src/data/store.ts:823](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L823) Finds a single document matching the query #### Example ```ts theme={null} // ✅ Valid queries: await store.findOne({ name: 'John' }) await store.findOne({ age: { $gt: 18 } }) await store.findOne({ _id: new ObjectId('...') }) await store.findOne({ tags: { $in: ['typescript', 'mongodb'] } }) await store.findOne({ $or: [{ name: 'John' }, { name: 'Jane' }] }) await store.findOne({ 'emails.address': 'test@example.com' }) // dot notation // ❌ TypeScript error - 'id' is not in schema: await store.findOne({ id: '123' }) ``` #### Parameters | Parameter | Type | Description | | ---------- | ----------------------------------------------- | -------------------------------------------------------------------------------------------- | | `query` | `TypedFilter`\<`InferDocumentType`\<`TSchema`>> | Type-safe query filter. Only schema fields, MongoDB operators, and dot notation are allowed. | | `options?` | `FindOptions`\<`Document`> | Find options | #### Returns `Promise`\<`null` | `EnhancedOmit`\<`InferDocumentType`\<`TSchema`>, `"_id"`> & `object` & `TMethods`> The document, or null if not found *** ### findOneAndDelete() > **findOneAndDelete**(`selector`, `options?`): `Promise`\<`null` | `EnhancedOmit`\<`InferDocumentType`\<`TSchema`>, `"_id"`> & `object` & `TMethods`> Defined in: [packages/modelence/src/data/store.ts:1160](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L1160) Atomically finds a document and deletes it, returning the deleted document #### Parameters | Parameter | Type | Description | | ---------- | ------------------------------------------------------------------------- | ----------------------------------------------- | | `selector` | `string` \| `ObjectId` \| `TypedFilter`\<`InferDocumentType`\<`TSchema`>> | The selector to find the document | | `options?` | `Omit`\<`FindOneAndDeleteOptions`, `"includeResultMetadata"`> | Options including `session`, `projection`, etc. | #### Returns `Promise`\<`null` | `EnhancedOmit`\<`InferDocumentType`\<`TSchema`>, `"_id"`> & `object` & `TMethods`> The deleted document, or null if not found *** ### findOneAndReplace() > **findOneAndReplace**(`selector`, `replacement`, `options?`): `Promise`\<`null` | `EnhancedOmit`\<`InferDocumentType`\<`TSchema`>, `"_id"`> & `object` & `TMethods`> Defined in: [packages/modelence/src/data/store.ts:1179](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L1179) Atomically finds a document and replaces it, returning the document #### Parameters | Parameter | Type | Description | | ------------- | ------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | | `selector` | `string` \| `ObjectId` \| `TypedFilter`\<`InferDocumentType`\<`TSchema`>> | The selector to find the document | | `replacement` | `WithoutId`\<`this`\[`"_type"`]> | The replacement document | | `options?` | `Omit`\<`FindOneAndReplaceOptions`, `"includeResultMetadata"`> | Options including `returnDocument` ('before' or 'after'), `upsert`, `session`, etc. | #### Returns `Promise`\<`null` | `EnhancedOmit`\<`InferDocumentType`\<`TSchema`>, `"_id"`> & `object` & `TMethods`> The document (before or after replacement, depending on options), or null if not found *** ### findOneAndUpdate() > **findOneAndUpdate**(`selector`, `update`, `options?`): `Promise`\<`null` | `EnhancedOmit`\<`InferDocumentType`\<`TSchema`>, `"_id"`> & `object` & `TMethods`> Defined in: [packages/modelence/src/data/store.ts:1094](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L1094) Atomically finds a document and updates it, returning the document #### Parameters | Parameter | Type | Description | | ---------- | ------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | | `selector` | `string` \| `ObjectId` \| `TypedFilter`\<`InferDocumentType`\<`TSchema`>> | The selector to find the document | | `update` | `UpdateFilter`\<`InferDocumentType`\<`TSchema`>> | The update to apply | | `options?` | `Omit`\<`FindOneAndUpdateOptions`, `"includeResultMetadata"`> | Options including `returnDocument` ('before' or 'after'), `upsert`, `session`, etc. | #### Returns `Promise`\<`null` | `EnhancedOmit`\<`InferDocumentType`\<`TSchema`>, `"_id"`> & `object` & `TMethods`> The document (before or after update, depending on options), or null if not found *** ### findOneAndUpsert() > **findOneAndUpsert**(`selector`, `update`, `options?`): `Promise`\<`UpsertResult`\<`EnhancedOmit`\<`InferDocumentType`\<`TSchema`>, `"_id"`> & `object` & `TMethods`>> Defined in: [packages/modelence/src/data/store.ts:1133](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L1133) Atomic find-or-create: runs `findOneAndUpdate` with `upsert` and reports, as `isNew`, whether the returned document was newly inserted. The plain [findOneAndUpdate](/api-reference/modelence/server/classes/Store#findoneandupdate) deliberately hides result metadata and returns only the document, so it can't distinguish an insert from a match. This method surfaces the driver's `lastErrorObject.upserted` flag as `isNew`, so callers can branch on create-vs-match without a separate pre-existence read that would race with concurrent upserts. `upsert` defaults to `true` but is overridable — pass `upsert: false` to make this a pure find-and-report (unknown selector → `{ doc: null, isNew: false }`). `returnDocument` is always `'after'` and cannot be overridden. #### Example ```ts theme={null} const { doc, isNew } = await dbUsers.findOneAndUpsert( { email }, { $setOnInsert: { email, createdAt: new Date() } } ); if (isNew) onSignup(doc); else onLogin(doc); ``` #### Parameters | Parameter | Type | | ---------- | ----------------------------------------------------------------------------------- | | `selector` | `string` \| `ObjectId` \| `TypedFilter`\<`InferDocumentType`\<`TSchema`>> | | `update` | `UpdateFilter`\<`InferDocumentType`\<`TSchema`>> | | `options?` | `Omit`\<`FindOneAndUpdateOptions`, `"includeResultMetadata"` \| `"returnDocument"`> | #### Returns `Promise`\<`UpsertResult`\<`EnhancedOmit`\<`InferDocumentType`\<`TSchema`>, `"_id"`> & `object` & `TMethods`>> `{ doc, isNew }` — `doc` is null only when `upsert: false` and nothing matched; `isNew` is `true` exactly when this call inserted the doc. *** ### getDatabase() > **getDatabase**(): `Db` Defined in: [packages/modelence/src/data/store.ts:1269](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L1269) Returns the raw MongoDB database instance for advanced operations #### Returns `Db` The MongoDB database instance #### Throws Error if the store is not provisioned *** ### getIndexCreationMode() > **getIndexCreationMode**(): `IndexCreationMode` Defined in: [packages/modelence/src/data/store.ts:446](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L446) #### Returns `IndexCreationMode` *** ### getName() > **getName**(): `string` Defined in: [packages/modelence/src/data/store.ts:442](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L442) #### Returns `string` *** ### insertMany() > **insertMany**(`documents`, `options?`): `Promise`\<`InsertManyResult`\<`Document`>> Defined in: [packages/modelence/src/data/store.ts:983](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L983) Inserts multiple documents #### Parameters | Parameter | Type | Description | | ------------------ | --------------------------------------------------------------- | ----------------------- | | `documents` | `OptionalUnlessRequiredId`\<`InferDocumentType`\<`TSchema`>>\[] | The documents to insert | | `options?` | \{ `session?`: `ClientSession`; } | - | | `options.session?` | `ClientSession` | - | #### Returns `Promise`\<`InsertManyResult`\<`Document`>> The result of the insert operation *** ### insertOne() > **insertOne**(`document`, `options?`): `Promise`\<`InsertOneResult`\<`Document`>> Defined in: [packages/modelence/src/data/store.ts:938](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L938) Inserts a single document #### Parameters | Parameter | Type | Description | | ------------------ | ------------------------------------------------------------ | ---------------------- | | `document` | `OptionalUnlessRequiredId`\<`InferDocumentType`\<`TSchema`>> | The document to insert | | `options?` | \{ `session?`: `ClientSession`; } | - | | `options.session?` | `ClientSession` | - | #### Returns `Promise`\<`InsertOneResult`\<`Document`>> The result of the insert operation *** ### rawCollection() > **rawCollection**(): `Collection`\<`InferDocumentType`\<`TSchema`>> Defined in: [packages/modelence/src/data/store.ts:1278](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L1278) Returns the raw MongoDB collection instance for advanced operations #### Returns `Collection`\<`InferDocumentType`\<`TSchema`>> The MongoDB collection instance #### Throws Error if the store is not provisioned *** ### renameFrom() > **renameFrom**(`oldName`, `options?`): `Promise`\<`void`> Defined in: [packages/modelence/src/data/store.ts:1287](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L1287) Renames an existing collection to this store's name, used for migrations #### Parameters | Parameter | Type | Description | | ------------------ | --------------------------------- | ----------------------------------- | | `oldName` | `string` | The previous name of the collection | | `options?` | \{ `session?`: `ClientSession`; } | - | | `options.session?` | `ClientSession` | - | #### Returns `Promise`\<`void`> #### Throws Error if the old collection doesn't exist or if this store's collection already exists *** ### replaceOne() > **replaceOne**(`selector`, `replacement`, `options?`): `Promise`\<`UpdateResult`\<`Document`>> Defined in: [packages/modelence/src/data/store.ts:1200](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L1200) Replaces a single document #### Parameters | Parameter | Type | Description | | ------------- | ------------------------------------------------------------------------- | ------------------------------------------------------------ | | `selector` | `string` \| `ObjectId` \| `TypedFilter`\<`InferDocumentType`\<`TSchema`>> | The selector to find the document to replace | | `replacement` | `WithoutId`\<`this`\[`"_type"`]> | The replacement document (must not contain update operators) | | `options?` | `ReplaceOptions` | Options including `upsert`, `session`, etc. | #### Returns `Promise`\<`UpdateResult`\<`Document`>> The result of the replace operation *** ### requireById() > **requireById**(`id`, `errorHandler?`): `Promise`\<`EnhancedOmit`\<`InferDocumentType`\<`TSchema`>, `"_id"`> & `object` & `TMethods`> Defined in: [packages/modelence/src/data/store.ts:878](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L878) Fetches a single document by its ID, or throws an error if not found #### Parameters | Parameter | Type | Description | | --------------- | ---------------------- | ---------------------------------------------------------------------------- | | `id` | `string` \| `ObjectId` | The ID of the document to find | | `errorHandler?` | () => `Error` | Optional error handler to return a custom error if the document is not found | #### Returns `Promise`\<`EnhancedOmit`\<`InferDocumentType`\<`TSchema`>, `"_id"`> & `object` & `TMethods`> The document *** ### requireOne() > **requireOne**(`query`, `options?`, `errorHandler?`): `Promise`\<`EnhancedOmit`\<`InferDocumentType`\<`TSchema`>, `"_id"`> & `object` & `TMethods`> Defined in: [packages/modelence/src/data/store.ts:831](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L831) #### Parameters | Parameter | Type | | --------------- | ----------------------------------------------- | | `query` | `TypedFilter`\<`InferDocumentType`\<`TSchema`>> | | `options?` | `FindOptions`\<`Document`> | | `errorHandler?` | () => `Error` | #### Returns `Promise`\<`EnhancedOmit`\<`InferDocumentType`\<`TSchema`>, `"_id"`> & `object` & `TMethods`> *** ### updateMany() > **updateMany**(`selector`, `update`, `options?`): `Promise`\<`UpdateResult`\<`Document`>> Defined in: [packages/modelence/src/data/store.ts:1030](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L1030) Updates multiple documents #### Parameters | Parameter | Type | Description | | ------------------ | ------------------------------------------------ | ---------------------------------------------- | | `selector` | `TypedFilter`\<`InferDocumentType`\<`TSchema`>> | The selector to find the documents to update | | `update` | `UpdateFilter`\<`InferDocumentType`\<`TSchema`>> | The MongoDB modifier to apply to the documents | | `options?` | \{ `session?`: `ClientSession`; } | - | | `options.session?` | `ClientSession` | - | #### Returns `Promise`\<`UpdateResult`\<`Document`>> The result of the update operation *** ### updateOne() > **updateOne**(`selector`, `update`, `options?`): `Promise`\<`UpdateResult`\<`Document`>> Defined in: [packages/modelence/src/data/store.ts:997](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L997) Updates a single document #### Parameters | Parameter | Type | Description | | -------------------- | ------------------------------------------------------------------------- | ------------------------------------------- | | `selector` | `string` \| `ObjectId` \| `TypedFilter`\<`InferDocumentType`\<`TSchema`>> | The selector to find the document to update | | `update` | `UpdateFilter`\<`InferDocumentType`\<`TSchema`>> | The update to apply to the document | | `options?` | \{ `collation?`: `CollationOptions`; `session?`: `ClientSession`; } | - | | `options.collation?` | `CollationOptions` | - | | `options.session?` | `ClientSession` | - | #### Returns `Promise`\<`UpdateResult`\<`Document`>> The result of the update operation *** ### upsertMany() > **upsertMany**(`selector`, `update`, `options?`): `Promise`\<`UpdateResult`\<`Document`>> Defined in: [packages/modelence/src/data/store.ts:1049](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L1049) Updates multiple documents, or inserts them if they don't exist #### Parameters | Parameter | Type | Description | | ------------------ | ------------------------------------------------ | ---------------------------------------------- | | `selector` | `TypedFilter`\<`InferDocumentType`\<`TSchema`>> | The selector to find the documents to update | | `update` | `UpdateFilter`\<`InferDocumentType`\<`TSchema`>> | The MongoDB modifier to apply to the documents | | `options?` | \{ `session?`: `ClientSession`; } | - | | `options.session?` | `ClientSession` | - | #### Returns `Promise`\<`UpdateResult`\<`Document`>> The result of the update operation *** ### upsertOne() > **upsertOne**(`selector`, `update`, `options?`): `Promise`\<`UpdateResult`\<`Document`>> Defined in: [packages/modelence/src/data/store.ts:1012](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L1012) Updates a single document, or inserts it if it doesn't exist #### Parameters | Parameter | Type | Description | | ------------------ | ------------------------------------------------------------------------- | --------------------------------------------- | | `selector` | `string` \| `ObjectId` \| `TypedFilter`\<`InferDocumentType`\<`TSchema`>> | The selector to find the document to update | | `update` | `UpdateFilter`\<`InferDocumentType`\<`TSchema`>> | The MongoDB modifier to apply to the document | | `options?` | \{ `session?`: `ClientSession`; } | - | | `options.session?` | `ClientSession` | - | #### Returns `Promise`\<`UpdateResult`\<`Document`>> The result of the update operation *** ### vectorSearch() > **vectorSearch**(`params`): `Promise`\<`AggregationCursor`\<`Document`>> Defined in: [packages/modelence/src/data/store.ts:1332](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L1332) Performs a vector similarity search using MongoDB Atlas Vector Search #### Example ```ts theme={null} const results = await store.vectorSearch({ field: 'embedding', embedding: [0.1, 0.2, 0.3, ...], numCandidates: 100, limit: 10, projection: { title: 1, description: 1 } }); ``` #### Parameters | Parameter | Type | Description | | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ | | `params` | \{ `embedding`: `number`\[]; `field`: `string`; `indexName?`: `string`; `limit?`: `number`; `numCandidates?`: `number`; `projection?`: `Document`; } | Vector search parameters | | `params.embedding` | `number`\[] | The query vector to search for | | `params.field` | `string` | The field name containing the vector embeddings | | `params.indexName?` | `string` | Name of index (default: field + VectorSearch) | | `params.limit?` | `number` | Maximum number of results to return (default: 10) | | `params.numCandidates?` | `number` | Number of nearest neighbors to consider (default: 100) | | `params.projection?` | `Document` | Additional fields to include in the results | #### Returns `Promise`\<`AggregationCursor`\<`Document`>> An aggregation cursor with search results and scores *** ### watch() > **watch**(`pipeline?`, `options?`): `ChangeStream` Defined in: [packages/modelence/src/data/store.ts:1239](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L1239) Opens a change stream on the collection to watch for real-time changes #### Parameters | Parameter | Type | Description | | ----------- | --------------------- | --------------------------------------------------------------- | | `pipeline?` | `Document`\[] | Optional aggregation pipeline to filter/transform change events | | `options?` | `ChangeStreamOptions` | Optional change stream options | #### Returns `ChangeStream` A ChangeStream instance *** ### vectorIndex() > `static` **vectorIndex**(`params`): `object` Defined in: [packages/modelence/src/data/store.ts:1395](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L1395) Creates a MongoDB Atlas Vector Search index definition #### Example ```ts theme={null} const store = new Store('documents', { schema: { title: schema.string(), embedding: schema.array(schema.number()), }, indexes: [], searchIndexes: [ Store.vectorIndex({ field: 'embedding', dimensions: 1536, similarity: 'cosine' }) ] }); ``` #### Parameters | Parameter | Type | Description | | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- | | `params` | \{ `dimensions`: `number`; `field`: `string`; `indexName?`: `string`; `similarity?`: `"cosine"` \| `"euclidean"` \| `"dotProduct"`; } | Vector index parameters | | `params.dimensions` | `number` | The number of dimensions in the vector embeddings | | `params.field` | `string` | The field name to create the vector index on | | `params.indexName?` | `string` | Name of index (default: field + VectorSearch) | | `params.similarity?` | `"cosine"` \| `"euclidean"` \| `"dotProduct"` | The similarity metric to use (default: 'cosine') | #### Returns `object` A search index description object | Name | Type | Default value | Defined in | | ------------------- | ----------- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `definition` | `object` | - | [packages/modelence/src/data/store.ts:1409](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L1409) | | `definition.fields` | `object`\[] | - | [packages/modelence/src/data/store.ts:1410](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L1410) | | `name` | `string` | - | [packages/modelence/src/data/store.ts:1408](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L1408) | | `type` | `string` | `'vectorSearch'` | [packages/modelence/src/data/store.ts:1407](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/store.ts#L1407) | # authenticate Source: https://docs.modelence.com/api-reference/modelence/server/functions/authenticate [API Reference](/api-reference/modelence/server/functions/../../../index) / [modelence](/api-reference/modelence/server/functions/../../index) / [server](/api-reference/modelence/server/functions/../index) / authenticate > **authenticate**(`authToken`): `Promise`\<\{ `roles`: `string`\[]; `session`: `Session`; `user`: `null` | [`UserInfo`](/api-reference/modelence/server/functions/../type-aliases/UserInfo); }> Defined in: [packages/modelence/src/auth/index.ts:8](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/index.ts#L8) ## Parameters | Parameter | Type | | ----------- | ------------------ | | `authToken` | `null` \| `string` | ## Returns `Promise`\<\{ `roles`: `string`\[]; `session`: `Session`; `user`: `null` | [`UserInfo`](/api-reference/modelence/server/functions/../type-aliases/UserInfo); }> # clearSessionUser Source: https://docs.modelence.com/api-reference/modelence/server/functions/clearSessionUser [API Reference](/api-reference/modelence/server/functions/../../../index) / [modelence](/api-reference/modelence/server/functions/../../index) / [server](/api-reference/modelence/server/functions/../index) / clearSessionUser > **clearSessionUser**(`authToken`): `Promise`\<`void`> Defined in: [packages/modelence/src/auth/session.ts:94](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/session.ts#L94) ## Parameters | Parameter | Type | | ----------- | -------- | | `authToken` | `string` | ## Returns `Promise`\<`void`> # consumeRateLimit Source: https://docs.modelence.com/api-reference/modelence/server/functions/consumeRateLimit [API Reference](/api-reference/modelence/server/functions/../../../index) / [modelence](/api-reference/modelence/server/functions/../../index) / [server](/api-reference/modelence/server/functions/../index) / consumeRateLimit > **consumeRateLimit**(`options`): `Promise`\<`void`> Defined in: [packages/modelence/src/rate-limit/rules.ts:30](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/rate-limit/rules.ts#L30) This function will check all rate limit rules on the specified bucket and type, throw an error if any of them are exceeded and increase the count of the rate limit record. ## Example ```ts theme={null} await consumeRateLimit({ bucket: 'api', type: 'ip', value: '127.0.0.1' }); ``` ## Parameters | Parameter | Type | Description | | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | | `options` | \{ `bucket`: `string`; `message?`: `string`; `type`: [`RateLimitType`](/api-reference/modelence/server/functions/../type-aliases/RateLimitType); `value`: `string`; } | - | | `options.bucket` | `string` | The bucket for the rate limit. | | `options.message?` | `string` | Optional custom error message when the rate limit is exceeded. | | `options.type` | [`RateLimitType`](/api-reference/modelence/server/functions/../type-aliases/RateLimitType) | The type of the rate limit. | | `options.value` | `string` | The value for the rate limit. | ## Returns `Promise`\<`void`> # createQuery Source: https://docs.modelence.com/api-reference/modelence/server/functions/createQuery [API Reference](/api-reference/modelence/server/functions/../../../index) / [modelence](/api-reference/modelence/server/functions/../../index) / [server](/api-reference/modelence/server/functions/../index) / createQuery > **createQuery**\<`T`>(`name`, `methodDef`): `void` Defined in: [packages/modelence/src/methods/index.ts:9](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/methods/index.ts#L9) ## Type Parameters | Type Parameter | | -------------------------- | | `T` *extends* `unknown`\[] | ## Parameters | Parameter | Type | | ----------- | ------------------------ | | `name` | `string` | | `methodDef` | `MethodDefinition`\<`T`> | ## Returns `void` # createSession Source: https://docs.modelence.com/api-reference/modelence/server/functions/createSession [API Reference](/api-reference/modelence/server/functions/../../../index) / [modelence](/api-reference/modelence/server/functions/../../index) / [server](/api-reference/modelence/server/functions/../index) / createSession > **createSession**(`userId`): `Promise`\<`Session`> Defined in: [packages/modelence/src/auth/session.ts:107](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/session.ts#L107) ## Parameters | Parameter | Type | Default value | | --------- | -------------------- | ------------- | | `userId` | `null` \| `ObjectId` | `null` | ## Returns `Promise`\<`Session`> # deleteFile Source: https://docs.modelence.com/api-reference/modelence/server/functions/deleteFile [API Reference](/api-reference/modelence/server/functions/../../../index) / [modelence](/api-reference/modelence/server/functions/../../index) / [server](/api-reference/modelence/server/functions/../index) / deleteFile > **deleteFile**(`filePath`): `Promise`\<`void`> Defined in: [packages/modelence/src/files/index.ts:30](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/files/index.ts#L30) ## Parameters | Parameter | Type | | ---------- | -------- | | `filePath` | `string` | ## Returns `Promise`\<`void`> # deleteUser Source: https://docs.modelence.com/api-reference/modelence/server/functions/deleteUser [API Reference](/api-reference/modelence/server/functions/../../../index) / [modelence](/api-reference/modelence/server/functions/../../index) / [server](/api-reference/modelence/server/functions/../index) / deleteUser > **deleteUser**(`userId`): `Promise`\<`void`> Defined in: [packages/modelence/src/auth/deleteUser.ts:50](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/deleteUser.ts#L50) ## Parameters | Parameter | Type | | --------- | ---------- | | `userId` | `ObjectId` | ## Returns `Promise`\<`void`> # disableUser Source: https://docs.modelence.com/api-reference/modelence/server/functions/disableUser [API Reference](/api-reference/modelence/server/functions/../../../index) / [modelence](/api-reference/modelence/server/functions/../../index) / [server](/api-reference/modelence/server/functions/../index) / disableUser > **disableUser**(`userId`): `Promise`\<`void`> Defined in: [packages/modelence/src/auth/deleteUser.ts:39](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/deleteUser.ts#L39) ## Parameters | Parameter | Type | | --------- | ---------- | | `userId` | `ObjectId` | ## Returns `Promise`\<`void`> # downloadFile Source: https://docs.modelence.com/api-reference/modelence/server/functions/downloadFile [API Reference](/api-reference/modelence/server/functions/../../../index) / [modelence](/api-reference/modelence/server/functions/../../index) / [server](/api-reference/modelence/server/functions/../index) / downloadFile > **downloadFile**(`filePath`): `Promise`\<`DownloadFileResult`> Defined in: [packages/modelence/src/files/index.ts:34](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/files/index.ts#L34) ## Parameters | Parameter | Type | | ---------- | -------- | | `filePath` | `string` | ## Returns `Promise`\<`DownloadFileResult`> # getConfig Source: https://docs.modelence.com/api-reference/modelence/server/functions/getConfig [API Reference](/api-reference/modelence/server/functions/../../../index) / [modelence](/api-reference/modelence/server/functions/../../index) / [server](/api-reference/modelence/server/functions/../index) / getConfig > **getConfig**(`key`): `undefined` | `string` | `number` | `boolean` Defined in: [packages/modelence/src/config/server.ts:43](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/config/server.ts#L43) ## Parameters | Parameter | Type | Description | | --------- | -------- | --------------------------------- | | `key` | `string` | The configuration key to retrieve | ## Returns `undefined` | `string` | `number` | `boolean` The configuration value (string, number, or boolean) ## Sidebar Title getConfig (server) ## Examples ```ts theme={null} import { getConfig } from 'modelence/server'; // Get the site URL const siteUrl = getConfig('_system.site.url'); ``` Set via environment variable: ```bash theme={null} MODELENCE_SITE_URL=https://myapp.com ``` ```ts theme={null} import { getConfig } from 'modelence/server'; // Get the current environment (e.g., 'development', 'staging', 'production') const env = getConfig('_system.env'); if (env === 'production') { // Enable production features } ``` Set via environment variable: ```bash theme={null} MODELENCE_SITE_ENV=production ``` # getFileUrl Source: https://docs.modelence.com/api-reference/modelence/server/functions/getFileUrl [API Reference](/api-reference/modelence/server/functions/../../../index) / [modelence](/api-reference/modelence/server/functions/../../index) / [server](/api-reference/modelence/server/functions/../index) / getFileUrl > **getFileUrl**(`filePath`): `Promise`\<`GetFileUrlResult`> Defined in: [packages/modelence/src/files/index.ts:38](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/files/index.ts#L38) ## Parameters | Parameter | Type | | ---------- | -------- | | `filePath` | `string` | ## Returns `Promise`\<`GetFileUrlResult`> # getUploadUrl Source: https://docs.modelence.com/api-reference/modelence/server/functions/getUploadUrl [API Reference](/api-reference/modelence/server/functions/../../../index) / [modelence](/api-reference/modelence/server/functions/../../index) / [server](/api-reference/modelence/server/functions/../index) / getUploadUrl > **getUploadUrl**(`__namedParameters`): `Promise`\<`GetUploadUrlResult`> Defined in: [packages/modelence/src/files/index.ts:14](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/files/index.ts#L14) ## Parameters | Parameter | Type | | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `__namedParameters` | \{ `contentType`: `string`; `filePath`: `string`; `visibility`: [`FileVisibility`](/api-reference/modelence/server/functions/../type-aliases/FileVisibility); } | | `__namedParameters.contentType` | `string` | | `__namedParameters.filePath` | `string` | | `__namedParameters.visibility` | [`FileVisibility`](/api-reference/modelence/server/functions/../type-aliases/FileVisibility) | ## Returns `Promise`\<`GetUploadUrlResult`> # invalidateAllUserSessions Source: https://docs.modelence.com/api-reference/modelence/server/functions/invalidateAllUserSessions [API Reference](/api-reference/modelence/server/functions/../../../index) / [modelence](/api-reference/modelence/server/functions/../../index) / [server](/api-reference/modelence/server/functions/../index) / invalidateAllUserSessions > **invalidateAllUserSessions**(`userId`): `Promise`\<`void`> Defined in: [packages/modelence/src/auth/session.ts:103](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/session.ts#L103) ## Parameters | Parameter | Type | | --------- | ---------- | | `userId` | `ObjectId` | ## Returns `Promise`\<`void`> # obtainSession Source: https://docs.modelence.com/api-reference/modelence/server/functions/obtainSession [API Reference](/api-reference/modelence/server/functions/../../../index) / [modelence](/api-reference/modelence/server/functions/../../index) / [server](/api-reference/modelence/server/functions/../index) / obtainSession > **obtainSession**(`authToken`): `Promise`\<`Session`> Defined in: [packages/modelence/src/auth/session.ts:54](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/session.ts#L54) ## Parameters | Parameter | Type | | ----------- | ------------------ | | `authToken` | `null` \| `string` | ## Returns `Promise`\<`Session`> # sendEmail Source: https://docs.modelence.com/api-reference/modelence/server/functions/sendEmail [API Reference](/api-reference/modelence/server/functions/../../../index) / [modelence](/api-reference/modelence/server/functions/../../index) / [server](/api-reference/modelence/server/functions/../index) / sendEmail > **sendEmail**(`payload`): `undefined` | `Promise`\<`void`> Defined in: [packages/modelence/src/app/email.ts:4](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/email.ts#L4) ## Parameters | Parameter | Type | | --------- | -------------- | | `payload` | `EmailPayload` | ## Returns `undefined` | `Promise`\<`void`> # setAuthTokenCookie Source: https://docs.modelence.com/api-reference/modelence/server/functions/setAuthTokenCookie [API Reference](/api-reference/modelence/server/functions/../../../index) / [modelence](/api-reference/modelence/server/functions/../../index) / [server](/api-reference/modelence/server/functions/../index) / setAuthTokenCookie > **setAuthTokenCookie**(`res`, `authToken`): `void` Defined in: [packages/modelence/src/auth/session.ts:143](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/session.ts#L143) ## Parameters | Parameter | Type | | ----------- | ---------- | | `res` | `Response` | | `authToken` | `string` | ## Returns `void` # setSessionUser Source: https://docs.modelence.com/api-reference/modelence/server/functions/setSessionUser [API Reference](/api-reference/modelence/server/functions/../../../index) / [modelence](/api-reference/modelence/server/functions/../../index) / [server](/api-reference/modelence/server/functions/../index) / setSessionUser > **setSessionUser**(`authToken`, `userId`): `Promise`\<`void`> Defined in: [packages/modelence/src/auth/session.ts:85](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/session.ts#L85) ## Parameters | Parameter | Type | | ----------- | ---------- | | `authToken` | `string` | | `userId` | `ObjectId` | ## Returns `Promise`\<`void`> # startApp Source: https://docs.modelence.com/api-reference/modelence/server/functions/startApp [API Reference](/api-reference/modelence/server/functions/../../../index) / [modelence](/api-reference/modelence/server/functions/../../index) / [server](/api-reference/modelence/server/functions/../index) / startApp > **startApp**(`__namedParameters`): `Promise`\<`void`> Defined in: [packages/modelence/src/app/index.ts:77](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/index.ts#L77) ## Parameters | Parameter | Type | | ------------------- | ------------------------------------------------------------------------------------ | | `__namedParameters` | [`AppOptions`](/api-reference/modelence/server/functions/../type-aliases/AppOptions) | ## Returns `Promise`\<`void`> # server Source: https://docs.modelence.com/api-reference/modelence/server/index [API Reference](/api-reference/modelence/server/../../index) / [modelence](/api-reference/modelence/server/../index) / server ## Module * [Module](/api-reference/modelence/server/classes/Module) ## Other ### ConfigSchema Re-exports [ConfigSchema](/api-reference/modelence/server/../index/type-aliases/ConfigSchema) ## Rate Limits * [consumeRateLimit](/api-reference/modelence/server/functions/consumeRateLimit) ## Store * [Store](/api-reference/modelence/server/classes/Store) # LiveDataConfig Source: https://docs.modelence.com/api-reference/modelence/server/interfaces/LiveDataConfig [API Reference](/api-reference/modelence/server/interfaces/../../../index) / [modelence](/api-reference/modelence/server/interfaces/../../index) / [server](/api-reference/modelence/server/interfaces/../index) / LiveDataConfig Defined in: [packages/modelence/src/live-query/context.ts:30](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/live-query/context.ts#L30) Configuration for creating LiveData. ## Type Parameters | Type Parameter | Default type | | -------------- | ------------ | | `T` | `unknown` | ## Properties | Property | Type | Description | Defined in | | ------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `fetch` | () => `T` \| `Promise`\<`T`> | Fetches the current data. Called initially and whenever watch triggers publish. | [packages/modelence/src/live-query/context.ts:34](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/live-query/context.ts#L34) | | `watch` | [`LiveQueryWatch`](/api-reference/modelence/server/interfaces/../type-aliases/LiveQueryWatch) | Sets up watching for changes. Receives publish callback and returns cleanup. | [packages/modelence/src/live-query/context.ts:38](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/live-query/context.ts#L38) | # schema Source: https://docs.modelence.com/api-reference/modelence/server/namespaces/schema/index [API Reference](/api-reference/modelence/server/namespaces/schema/../../../../index) / [modelence](/api-reference/modelence/server/namespaces/schema/../../../index) / [server](/api-reference/modelence/server/namespaces/schema/../../index) / schema ## Type Aliases * [infer](/api-reference/modelence/server/namespaces/schema/type-aliases/infer) # infer Source: https://docs.modelence.com/api-reference/modelence/server/namespaces/schema/type-aliases/infer [API Reference](/api-reference/modelence/server/namespaces/schema/type-aliases/../../../../../index) / [modelence](/api-reference/modelence/server/namespaces/schema/type-aliases/../../../../index) / [server](/api-reference/modelence/server/namespaces/schema/type-aliases/../../../index) / [schema](/api-reference/modelence/server/namespaces/schema/type-aliases/../index) / infer > **infer**\<`T`> = `InferDocumentType`\<`T`> Defined in: [packages/modelence/src/data/types.ts:74](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/types.ts#L74) ## Type Parameters | Type Parameter | | ------------------------------------ | | `T` *extends* `SchemaTypeDefinition` | # AppOptions Source: https://docs.modelence.com/api-reference/modelence/server/type-aliases/AppOptions [API Reference](/api-reference/modelence/server/type-aliases/../../../index) / [modelence](/api-reference/modelence/server/type-aliases/../../index) / [server](/api-reference/modelence/server/type-aliases/../index) / AppOptions > **AppOptions** = `object` Defined in: [packages/modelence/src/app/index.ts:46](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/index.ts#L46) ## Properties | Property | Type | Description | Defined in | | ------------------- | ---------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `auth?` | [`AuthConfig`](/api-reference/modelence/server/type-aliases/AuthConfig) | - | [packages/modelence/src/app/index.ts:50](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/index.ts#L50) | | `email?` | `EmailConfig` | - | [packages/modelence/src/app/index.ts:49](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/index.ts#L49) | | `migrations?` | `MigrationScript`\[] | - | [packages/modelence/src/app/index.ts:71](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/index.ts#L71) | | `modules?` | [`Module`](/api-reference/modelence/server/type-aliases/../classes/Module)\[] | - | [packages/modelence/src/app/index.ts:47](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/index.ts#L47) | | `roles?` | `Record`\<`string`, [`RoleDefinition`](/api-reference/modelence/server/type-aliases/RoleDefinition)> | Custom role definitions keyed by role name. Defined roles are synced to the Modelence Cloud dashboard for user management. See [RoleDefinition](/api-reference/modelence/server/type-aliases/RoleDefinition). **Example** `startApp({ roles: { admin: { description: 'Full access to all features' }, editor: { description: 'Can edit content' }, viewer: {}, }, });` | [packages/modelence/src/app/index.ts:68](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/index.ts#L68) | | `security?` | [`SecurityConfig`](/api-reference/modelence/server/type-aliases/SecurityConfig) | Security settings such as clickjacking protection. See [SecurityConfig](/api-reference/modelence/server/type-aliases/SecurityConfig). | [packages/modelence/src/app/index.ts:52](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/index.ts#L52) | | `server?` | `AppServer` | - | [packages/modelence/src/app/index.ts:48](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/index.ts#L48) | | `ssr?` | `boolean` | Enable server-side rendering of the user's React tree. | [packages/modelence/src/app/index.ts:74](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/index.ts#L74) | | `websocket?` | `WebsocketConfig` | - | [packages/modelence/src/app/index.ts:72](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/index.ts#L72) | # AuthConfig Source: https://docs.modelence.com/api-reference/modelence/server/type-aliases/AuthConfig [API Reference](/api-reference/modelence/server/type-aliases/../../../index) / [modelence](/api-reference/modelence/server/type-aliases/../../index) / [server](/api-reference/modelence/server/type-aliases/../index) / AuthConfig > **AuthConfig** = `object` Defined in: [packages/modelence/src/app/authConfig.ts:164](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L164) Authentication configuration for the application ## Example ```typescript theme={null} import { startApp } from 'modelence/server'; import { time } from 'modelence'; startApp({ auth: { validateSignup: ({ email, firstName, lastName, password, handle, avatarUrl }) => { // Validating the signup data if (!email || !password) { throw new Error('Email and password are required'); } }, onAfterLogin: ({ user }) => { console.log('User logged in:', user.name); // Redirect to dashboard }, onLoginError: ({ error }) => { console.error('Login failed:', error.message); // Show error toast }, onAfterSignup: ({ user }) => { console.log('User signed up:', user.email); // Send welcome email }, onSignupError: ({ error }) => { console.error('Signup failed:', error.message); }, generateHandle: ({ email }) => { console.log('Generating handle for:', email); // Generate handle return 'user123'; }, } }); ``` ## Properties | Property | Type | Description | Defined in | | --------------------------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `allowDisposableEmails?` | `boolean` | When `true`, the built-in disposable-email check is skipped during signup. Defaults to `false` (built-in check enforced). Set this to `true` when you want to enforce your own domain-policy logic via [onBeforeSignup](/api-reference/modelence/server/type-aliases/AuthConfig#onbeforesignup) — for example, a service that classifies domains as public/disposable/custom with its own data sources and cache. Skipping the built-in check without registering an `onBeforeSignup` hook means disposable emails will be allowed to sign up. | [packages/modelence/src/app/authConfig.ts:329](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L329) | | `errorComponent?` | (`props`) => `string` \| `null` \| `undefined` | Customizes how OAuth authentication errors are rendered. By default, OAuth errors are returned as JSON; providing this returns a custom HTML response instead, which is useful when the OAuth flow runs in a browser context. Receives `{ error, statusCode }` and returns an HTML string (or `null`/`undefined` to fall back to the default JSON response). Always escape interpolated values to prevent XSS. | [packages/modelence/src/app/authConfig.ts:307](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L307) | | `generateHandle?` | (`props`) => `Promise`\<`string`> \| `string` | Custom handle generator. If provided, overrides the default behavior (which derives the handle from the email local-part). Receives `{ email, firstName?, lastName? }` and returns the desired handle synchronously or as a `Promise`. If the returned handle collides with an existing one, Modelence appends a numeric suffix automatically. | [packages/modelence/src/app/authConfig.ts:257](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L257) | | ~~`login?`~~ | [`AuthOption`](/api-reference/modelence/server/type-aliases/AuthOption) | **Deprecated** Use [AuthConfig.onAfterLogin](/api-reference/modelence/server/type-aliases/AuthConfig#onafterlogin) and [AuthConfig.onLoginError](/api-reference/modelence/server/type-aliases/AuthConfig#onloginerror) instead. | [packages/modelence/src/app/authConfig.ts:260](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L260) | | `magicLink?` | `object` | Enables passwordless magic link authentication. Disabled by default. Requires an email provider and delivery settings under the `email` option (see `EmailConfig.magicLink`). **Example** `startApp({ auth: { magicLink: { enabled: true, allowSignup: true }, }, });` | [packages/modelence/src/app/authConfig.ts:279](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L279) | | `magicLink.allowSignup?` | `boolean` | Allows a magic link (or its one-time code) to create an account when the email has no existing one — combined sign-in/sign-up, like OAuth. Disabled by default: unknown emails get the same generic "link sent" response but no email, and no account is ever auto-created. | [packages/modelence/src/app/authConfig.ts:287](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L287) | | `magicLink.enabled?` | `boolean` | - | [packages/modelence/src/app/authConfig.ts:280](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L280) | | `oauthAccountLinking?` | `"auto"` \| `"manual"` | Controls how OAuth providers handle existing accounts with matching email. - 'manual' (default): Returns an error when an OAuth login matches an existing email. - 'auto': Automatically links the OAuth provider to the existing account if the provider email is verified. | [packages/modelence/src/app/authConfig.ts:296](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L296) | | `onAfterEmailVerification?` | (`props`) => `void` | Fires after a user's email is successfully verified (via the verification link or implicitly via password reset). Receives `{ provider, user, session, connectionInfo }`. | [packages/modelence/src/app/authConfig.ts:229](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L229) | | `onAfterLogin?` | (`props`) => `void` | Fires after a successful login (email/password or OAuth) once the session has been linked to the user. Receives `{ provider, user, session, connectionInfo }`. Use for analytics, audit logging, or post-login side effects. | [packages/modelence/src/app/authConfig.ts:188](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L188) | | `onAfterOAuthLink?` | (`props`) => `void` | Fires after an OAuth provider is linked to an existing account (either automatically when `oauthAccountLinking: 'auto'` or via an explicit link flow). Receives `{ provider, user, session, connectionInfo }`. | [packages/modelence/src/app/authConfig.ts:242](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L242) | | `onAfterSignup?` | (`props`) => `void` | Fires after a successful signup once the user record is created and the session is linked. Receives `{ provider, user, session, connectionInfo }`. Common uses: send welcome email, create default workspace, track activation. | [packages/modelence/src/app/authConfig.ts:216](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L216) | | `onBeforeSignup?` | (`props`) => `void` \| `Promise`\<`void`> | Hook fired after validation and the built-in disposable-email check, but before the new user document is inserted. Throwing aborts the signup — the thrown error is re-thrown to the caller and `onSignupError` fires. Use this to plug in a custom domain-policy check (e.g. a tenant-specific email-domain verification service) without having to disable the built-in disposable-email check. Invoked for `'email'` and `'magicLink'` provider signups. OAuth signups are not gated because OAuth providers (Google, GitHub, etc.) do not issue disposable accounts. | [packages/modelence/src/app/authConfig.ts:209](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L209) | | `onEmailVerificationError?` | (`props`) => `void` | Fires when email verification fails (invalid or expired token). Receives `{ provider, error, session, connectionInfo }`. | [packages/modelence/src/app/authConfig.ts:235](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L235) | | `onLoginError?` | (`props`) => `void` | Fires when a login attempt fails. Receives `{ provider, error, session, connectionInfo }`. Use for failure analytics or alerting — does NOT change the response sent to the client. | [packages/modelence/src/app/authConfig.ts:194](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L194) | | `onOAuthLinkError?` | (`props`) => `void` | Fires when OAuth account linking fails. Receives `{ provider, error, session, connectionInfo }`. | [packages/modelence/src/app/authConfig.ts:248](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L248) | | `onSignupError?` | (`props`) => `void` | Fires when a signup attempt fails (validation, duplicate email, etc.). Receives `{ provider, error, session, connectionInfo }`. Use for failure analytics — does NOT change the response sent to the client. | [packages/modelence/src/app/authConfig.ts:223](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L223) | | `rateLimits?` | [`AuthRateLimitsConfig`](/api-reference/modelence/server/type-aliases/AuthRateLimitsConfig) | Overrides the built-in rate limits for authentication endpoints. Each rule you provide is merged into the defaults by `(bucket, type, window)`: matching tuples replace the default `limit`, new tuples are added, and unspecified defaults are preserved. See [AuthRateLimitsConfig](/api-reference/modelence/server/type-aliases/AuthRateLimitsConfig) for full semantics and examples. | [packages/modelence/src/app/authConfig.ts:316](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L316) | | ~~`signup?`~~ | [`AuthOption`](/api-reference/modelence/server/type-aliases/AuthOption) | **Deprecated** Use [AuthConfig.onAfterSignup](/api-reference/modelence/server/type-aliases/AuthConfig#onaftersignup) and [AuthConfig.onSignupError](/api-reference/modelence/server/type-aliases/AuthConfig#onsignuperror) instead. | [packages/modelence/src/app/authConfig.ts:262](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L262) | | `validateProfileUpdate?` | (`props`) => `void` \| `Promise`\<`void`> | Pre-update validation hook. Runs before a user's profile fields (`firstName`, `lastName`, `avatarUrl`, `handle`) are written. Throw to reject the update — the thrown message is surfaced to the client. May be async. | [packages/modelence/src/app/authConfig.ts:181](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L181) | | `validateSignup?` | (`props`) => `void` \| `Promise`\<`void`> | Pre-signup validation hook. Runs before a new user is created during email/password signup, after format checks but before duplicate detection. Throw to reject the signup — the thrown message is surfaced to the client. Receives the raw signup payload (`email`, `password`, and optional `firstName`, `lastName`, `avatarUrl`, `handle`). May be async. | [packages/modelence/src/app/authConfig.ts:173](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L173) | # AuthOption Source: https://docs.modelence.com/api-reference/modelence/server/type-aliases/AuthOption [API Reference](/api-reference/modelence/server/type-aliases/../../../index) / [modelence](/api-reference/modelence/server/type-aliases/../../index) / [server](/api-reference/modelence/server/type-aliases/../index) / AuthOption > **AuthOption** = `object` Defined in: [packages/modelence/src/app/authConfig.ts:117](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L117) Callback options for authentication operations ## Properties | Property | Type | Description | Defined in | | ------------------ | ------------------- | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `onError?` | (`error`) => `void` | Callback executed when authentication fails | [packages/modelence/src/app/authConfig.ts:121](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L121) | | `onSuccess?` | (`user`) => `void` | Callback executed when authentication succeeds | [packages/modelence/src/app/authConfig.ts:119](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L119) | # AuthRateLimitOverride Source: https://docs.modelence.com/api-reference/modelence/server/type-aliases/AuthRateLimitOverride [API Reference](/api-reference/modelence/server/type-aliases/../../../index) / [modelence](/api-reference/modelence/server/type-aliases/../../index) / [server](/api-reference/modelence/server/type-aliases/../index) / AuthRateLimitOverride > **AuthRateLimitOverride** = `object` Defined in: [packages/modelence/src/app/authConfig.ts:21](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L21) A single rate-limit rule for an authentication bucket. The `bucket` is implied by which auth action you're configuring (e.g. `signup`), so callers only specify the actor type, window size, and limit. ## Example ```typescript theme={null} import { time } from 'modelence'; const rule: AuthRateLimitOverride = { type: 'ip', window: time.minutes(15), limit: 10, }; ``` ## Properties | Property | Type | Description | Defined in | | -------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `limit` | `number` | Maximum allowed hits within the window. | [packages/modelence/src/app/authConfig.ts:27](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L27) | | `type` | [`RateLimitType`](/api-reference/modelence/server/type-aliases/RateLimitType) | Identifier type of the actor this rule applies to. | [packages/modelence/src/app/authConfig.ts:23](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L23) | | `window` | `number` | Time window size in milliseconds. Use `time.minutes(15)` etc. | [packages/modelence/src/app/authConfig.ts:25](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L25) | # AuthRateLimitsConfig Source: https://docs.modelence.com/api-reference/modelence/server/type-aliases/AuthRateLimitsConfig [API Reference](/api-reference/modelence/server/type-aliases/../../../index) / [modelence](/api-reference/modelence/server/type-aliases/../../index) / [server](/api-reference/modelence/server/type-aliases/../index) / AuthRateLimitsConfig > **AuthRateLimitsConfig** = `object` Defined in: [packages/modelence/src/app/authConfig.ts:73](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L73) Per-action rate limit overrides for authentication endpoints. Each bucket accepts an array of rules that are merged into the built-in defaults by `(type, window)` tuple: * A rule whose `(type, window)` matches a default replaces that default's `limit`. * A rule whose `(type, window)` does not match any default is added as an extra rule for the bucket. * Defaults whose `(type, window)` is not overridden are kept. This means you can tighten a single window without accidentally dropping the other built-in protections for that bucket. ## Examples ```typescript theme={null} import { startApp } from 'modelence/server'; import { time } from 'modelence'; startApp({ auth: { rateLimits: { signup: [ { type: 'ip', window: time.minutes(15), limit: 5 }, ], }, }, }); ``` ```typescript theme={null} startApp({ auth: { rateLimits: { signup: [ { type: 'ip', window: time.minutes(1), limit: 2 }, ], }, }, }); ``` ## Properties | Property | Type | Description | Defined in | | ---------------------- | ------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `magicLink?` | [`AuthRateLimitOverride`](/api-reference/modelence/server/type-aliases/AuthRateLimitOverride)\[] | Rate limits for magic link requests. | [packages/modelence/src/app/authConfig.ts:85](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L85) | | `oneTimeCode?` | [`AuthRateLimitOverride`](/api-reference/modelence/server/type-aliases/AuthRateLimitOverride)\[] | Rate limits for one-time code sign-in attempts. | [packages/modelence/src/app/authConfig.ts:87](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L87) | | `passwordReset?` | [`AuthRateLimitOverride`](/api-reference/modelence/server/type-aliases/AuthRateLimitOverride)\[] | Rate limits for password reset requests. | [packages/modelence/src/app/authConfig.ts:83](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L83) | | `signin?` | [`AuthRateLimitOverride`](/api-reference/modelence/server/type-aliases/AuthRateLimitOverride)\[] | Per-IP limits for login attempts. | [packages/modelence/src/app/authConfig.ts:79](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L79) | | `signup?` | [`AuthRateLimitOverride`](/api-reference/modelence/server/type-aliases/AuthRateLimitOverride)\[] | Per-IP limits for the signup endpoint (successful signups only). | [packages/modelence/src/app/authConfig.ts:75](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L75) | | `signupAttempt?` | [`AuthRateLimitOverride`](/api-reference/modelence/server/type-aliases/AuthRateLimitOverride)\[] | Per-IP limits for signup attempts (checked before duplicate detection). | [packages/modelence/src/app/authConfig.ts:77](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L77) | | `verification?` | [`AuthRateLimitOverride`](/api-reference/modelence/server/type-aliases/AuthRateLimitOverride)\[] | Per-user limits for email verification requests. | [packages/modelence/src/app/authConfig.ts:81](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/authConfig.ts#L81) | # CloudBackendConnectResponse Source: https://docs.modelence.com/api-reference/modelence/server/type-aliases/CloudBackendConnectResponse [API Reference](/api-reference/modelence/server/type-aliases/../../../index) / [modelence](/api-reference/modelence/server/type-aliases/../../index) / [server](/api-reference/modelence/server/type-aliases/../index) / CloudBackendConnectResponse > **CloudBackendConnectResponse** = `CloudBackendConnectOkResponse` | `CloudBackendConnectErrorResponse` Defined in: [packages/modelence/src/app/backendApi.ts:26](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/backendApi.ts#L26) # ConfigType Source: https://docs.modelence.com/api-reference/modelence/server/type-aliases/ConfigType [API Reference](/api-reference/modelence/server/type-aliases/../../../index) / [modelence](/api-reference/modelence/server/type-aliases/../../index) / [server](/api-reference/modelence/server/type-aliases/../index) / ConfigType > **ConfigType** = `"text"` | `"string"` | `"number"` | `"boolean"` | `"secret"` Defined in: [packages/modelence/src/config/types.ts:10](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/config/types.ts#L10) The available types for module configuration values. * `'string'` — A short text value (single line) * `'text'` — A longer text value (multi-line) * `'number'` — A numeric value * `'boolean'` — A true/false toggle * `'secret'` — A sensitive string value (e.g. API keys, tokens). Masked in the Cloud dashboard and cannot be marked as `isPublic`. # CronJobInputParams Source: https://docs.modelence.com/api-reference/modelence/server/type-aliases/CronJobInputParams [API Reference](/api-reference/modelence/server/type-aliases/../../../index) / [modelence](/api-reference/modelence/server/type-aliases/../../index) / [server](/api-reference/modelence/server/type-aliases/../index) / CronJobInputParams > **CronJobInputParams** = `object` Defined in: [packages/modelence/src/cron/types.ts:18](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/cron/types.ts#L18) ## Properties | Property | Type | Defined in | | -------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `description?` | `string` | [packages/modelence/src/cron/types.ts:19](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/cron/types.ts#L19) | | `handler` | `CronJobHandler` | [packages/modelence/src/cron/types.ts:22](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/cron/types.ts#L22) | | `interval` | `number` | [packages/modelence/src/cron/types.ts:20](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/cron/types.ts#L20) | | `timeout?` | `number` | [packages/modelence/src/cron/types.ts:21](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/cron/types.ts#L21) | # FileVisibility Source: https://docs.modelence.com/api-reference/modelence/server/type-aliases/FileVisibility [API Reference](/api-reference/modelence/server/type-aliases/../../../index) / [modelence](/api-reference/modelence/server/type-aliases/../../index) / [server](/api-reference/modelence/server/type-aliases/../index) / FileVisibility > **FileVisibility** = `"public"` | `"private"` Defined in: [packages/modelence/src/files/types.ts:1](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/files/types.ts#L1) # HttpMethod Source: https://docs.modelence.com/api-reference/modelence/server/type-aliases/HttpMethod [API Reference](/api-reference/modelence/server/type-aliases/../../../index) / [modelence](/api-reference/modelence/server/type-aliases/../../index) / [server](/api-reference/modelence/server/type-aliases/../index) / HttpMethod > **HttpMethod** = `"get"` | `"post"` | `"put"` | `"delete"` | `"patch"` | `"options"` | `"head"` | `"all"` | `"use"` Defined in: [packages/modelence/src/routes/types.ts:4](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/routes/types.ts#L4) # LiveQueryCleanup Source: https://docs.modelence.com/api-reference/modelence/server/type-aliases/LiveQueryCleanup [API Reference](/api-reference/modelence/server/type-aliases/../../../index) / [modelence](/api-reference/modelence/server/type-aliases/../../index) / [server](/api-reference/modelence/server/type-aliases/../index) / LiveQueryCleanup > **LiveQueryCleanup** = () => `void` Defined in: [packages/modelence/src/live-query/context.ts:11](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/live-query/context.ts#L11) Cleanup function returned by watch handlers. Called when the client unsubscribes. ## Returns `void` # LiveQueryPublish Source: https://docs.modelence.com/api-reference/modelence/server/type-aliases/LiveQueryPublish [API Reference](/api-reference/modelence/server/type-aliases/../../../index) / [modelence](/api-reference/modelence/server/type-aliases/../../index) / [server](/api-reference/modelence/server/type-aliases/../index) / LiveQueryPublish > **LiveQueryPublish** = () => `void` Defined in: [packages/modelence/src/live-query/context.ts:5](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/live-query/context.ts#L5) Publish function provided to watch handlers. Call this to trigger a re-fetch and send updated data to the client. ## Returns `void` # LiveQueryWatch Source: https://docs.modelence.com/api-reference/modelence/server/type-aliases/LiveQueryWatch [API Reference](/api-reference/modelence/server/type-aliases/../../../index) / [modelence](/api-reference/modelence/server/type-aliases/../../index) / [server](/api-reference/modelence/server/type-aliases/../index) / LiveQueryWatch > **LiveQueryWatch** = (`context`) => [`LiveQueryCleanup`](/api-reference/modelence/server/type-aliases/LiveQueryCleanup) | `void` Defined in: [packages/modelence/src/live-query/context.ts:25](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/live-query/context.ts#L25) Watch function that sets up real-time monitoring. Receives a context with publish callback to trigger re-fetches. Returns a cleanup function. ## Parameters | Parameter | Type | | --------- | -------------- | | `context` | `WatchContext` | ## Returns [`LiveQueryCleanup`](/api-reference/modelence/server/type-aliases/LiveQueryCleanup) | `void` # RateLimitRule Source: https://docs.modelence.com/api-reference/modelence/server/type-aliases/RateLimitRule [API Reference](/api-reference/modelence/server/type-aliases/../../../index) / [modelence](/api-reference/modelence/server/type-aliases/../../index) / [server](/api-reference/modelence/server/type-aliases/../index) / RateLimitRule > **RateLimitRule** = `object` Defined in: [packages/modelence/src/rate-limit/types.ts:3](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/rate-limit/types.ts#L3) ## Properties | Property | Type | Description | Defined in | | -------------- | ----------------------------------------------------------------------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `bucket` | `string` | Logical action being limited, e.g. "signup" | [packages/modelence/src/rate-limit/types.ts:5](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/rate-limit/types.ts#L5) | | `limit` | `number` | Maximum allowed hits within the window | [packages/modelence/src/rate-limit/types.ts:14](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/rate-limit/types.ts#L14) | | `type` | [`RateLimitType`](/api-reference/modelence/server/type-aliases/RateLimitType) | Identifier type of the actor this rule applies to | [packages/modelence/src/rate-limit/types.ts:8](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/rate-limit/types.ts#L8) | | `window` | `number` | Time window size in milliseconds | [packages/modelence/src/rate-limit/types.ts:11](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/rate-limit/types.ts#L11) | # RateLimitType Source: https://docs.modelence.com/api-reference/modelence/server/type-aliases/RateLimitType [API Reference](/api-reference/modelence/server/type-aliases/../../../index) / [modelence](/api-reference/modelence/server/type-aliases/../../index) / [server](/api-reference/modelence/server/type-aliases/../index) / RateLimitType > **RateLimitType** = `"ip"` | `"user"` | `"email"` Defined in: [packages/modelence/src/rate-limit/types.ts:1](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/rate-limit/types.ts#L1) # RoleDefinition Source: https://docs.modelence.com/api-reference/modelence/server/type-aliases/RoleDefinition [API Reference](/api-reference/modelence/server/type-aliases/../../../index) / [modelence](/api-reference/modelence/server/type-aliases/../../index) / [server](/api-reference/modelence/server/type-aliases/../index) / RoleDefinition > **RoleDefinition** = `object` Defined in: [packages/modelence/src/auth/types.ts:88](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/types.ts#L88) Defines a role that can be assigned to users. Roles are registered via the `roles` option in [AppOptions](/api-reference/modelence/server/type-aliases/AppOptions) and are synced to the Modelence Cloud dashboard for user management. ## Example ```typescript theme={null} import { startApp } from 'modelence/server'; startApp({ roles: { admin: { description: 'Full access to all features' }, editor: { description: 'Can edit content' }, viewer: {}, }, }); ``` ## Properties | Property | Type | Description | Defined in | | -------------------- | -------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `description?` | `string` | Human-readable description of the role, shown in the Modelence Cloud dashboard. | [packages/modelence/src/auth/types.ts:90](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/types.ts#L90) | # RouteDefinition Source: https://docs.modelence.com/api-reference/modelence/server/type-aliases/RouteDefinition [API Reference](/api-reference/modelence/server/type-aliases/../../../index) / [modelence](/api-reference/modelence/server/type-aliases/../../index) / [server](/api-reference/modelence/server/type-aliases/../index) / RouteDefinition > **RouteDefinition** = `object` Defined in: [packages/modelence/src/routes/types.ts:68](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/routes/types.ts#L68) ## Properties | Property | Type | Defined in | | --------------------- | --------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `body?` | `BodyConfig` | [packages/modelence/src/routes/types.ts:72](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/routes/types.ts#L72) | | `errorHandler?` | [`RouteHandler`](/api-reference/modelence/server/type-aliases/RouteHandler) | [packages/modelence/src/routes/types.ts:71](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/routes/types.ts#L71) | | `handlers` | `RouteHandlers` | [packages/modelence/src/routes/types.ts:70](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/routes/types.ts#L70) | | `path` | `string` | [packages/modelence/src/routes/types.ts:69](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/routes/types.ts#L69) | # RouteHandler Source: https://docs.modelence.com/api-reference/modelence/server/type-aliases/RouteHandler [API Reference](/api-reference/modelence/server/type-aliases/../../../index) / [modelence](/api-reference/modelence/server/type-aliases/../../index) / [server](/api-reference/modelence/server/type-aliases/../index) / RouteHandler > **RouteHandler**\<`T`> = (`params`, `context`) => `Promise`\<[`RouteResponse`](/api-reference/modelence/server/type-aliases/RouteResponse)\<`T`>> | [`RouteResponse`](/api-reference/modelence/server/type-aliases/RouteResponse)\<`T`> Defined in: [packages/modelence/src/routes/types.ts:39](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/routes/types.ts#L39) ## Type Parameters | Type Parameter | Default type | | -------------- | ------------ | | `T` | `unknown` | ## Parameters | Parameter | Type | | --------- | ------------------------------------------------------------------------- | | `params` | [`RouteParams`](/api-reference/modelence/server/type-aliases/RouteParams) | | `context` | `Pick`\<`Context`, `"session"` \| `"user"`> | ## Returns `Promise`\<[`RouteResponse`](/api-reference/modelence/server/type-aliases/RouteResponse)\<`T`>> | [`RouteResponse`](/api-reference/modelence/server/type-aliases/RouteResponse)\<`T`> # RouteParams Source: https://docs.modelence.com/api-reference/modelence/server/type-aliases/RouteParams [API Reference](/api-reference/modelence/server/type-aliases/../../../index) / [modelence](/api-reference/modelence/server/type-aliases/../../index) / [server](/api-reference/modelence/server/type-aliases/../index) / RouteParams > **RouteParams**\<`T`> = `object` Defined in: [packages/modelence/src/routes/types.ts:15](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/routes/types.ts#L15) ## Type Parameters | Type Parameter | Default type | | -------------- | ------------ | | `T` | `unknown` | ## Properties | Property | Type | Defined in | | ---------------- | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `body` | `T` | [packages/modelence/src/routes/types.ts:17](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/routes/types.ts#L17) | | `cookies` | `Record`\<`string`, `string`> | [packages/modelence/src/routes/types.ts:20](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/routes/types.ts#L20) | | `headers` | `Record`\<`string`, `string`> | [packages/modelence/src/routes/types.ts:19](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/routes/types.ts#L19) | | `next` | `NextFunction` | [packages/modelence/src/routes/types.ts:24](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/routes/types.ts#L24) | | `params` | `Record`\<`string`, `string`> | [packages/modelence/src/routes/types.ts:18](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/routes/types.ts#L18) | | `query` | `Record`\<`string`, `string`> | [packages/modelence/src/routes/types.ts:16](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/routes/types.ts#L16) | | `rawBody?` | `Buffer` | [packages/modelence/src/routes/types.ts:21](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/routes/types.ts#L21) | | `req` | `Request` | [packages/modelence/src/routes/types.ts:22](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/routes/types.ts#L22) | | `res` | `Response` | [packages/modelence/src/routes/types.ts:23](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/routes/types.ts#L23) | # RouteResponse Source: https://docs.modelence.com/api-reference/modelence/server/type-aliases/RouteResponse [API Reference](/api-reference/modelence/server/type-aliases/../../../index) / [modelence](/api-reference/modelence/server/type-aliases/../../index) / [server](/api-reference/modelence/server/type-aliases/../index) / RouteResponse > **RouteResponse**\<`T`> = \{ `contentType?`: `string`; `data?`: `T`; `headers?`: `Record`\<`string`, `string`>; `redirect?`: `string`; `status?`: `number`; } | `null` Defined in: [packages/modelence/src/routes/types.ts:27](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/routes/types.ts#L27) ## Type Parameters | Type Parameter | Default type | | -------------- | ------------ | | `T` | `unknown` | ## Type declaration \{ `contentType?`: `string`; `data?`: `T`; `headers?`: `Record`\<`string`, `string`>; `redirect?`: `string`; `status?`: `number`; } | Name | Type | Description | Defined in | | -------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `contentType?` | `string` | Sets the response Content-Type before sending `data`. A Content-Type supplied through `headers` takes precedence when both options are provided. | [packages/modelence/src/routes/types.ts:35](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/routes/types.ts#L35) | | `data?` | `T` | - | [packages/modelence/src/routes/types.ts:28](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/routes/types.ts#L28) | | `headers?` | `Record`\<`string`, `string`> | - | [packages/modelence/src/routes/types.ts:30](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/routes/types.ts#L30) | | `redirect?` | `string` | - | [packages/modelence/src/routes/types.ts:36](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/routes/types.ts#L36) | | `status?` | `number` | - | [packages/modelence/src/routes/types.ts:29](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/routes/types.ts#L29) | `null` # SecurityConfig Source: https://docs.modelence.com/api-reference/modelence/server/type-aliases/SecurityConfig [API Reference](/api-reference/modelence/server/type-aliases/../../../index) / [modelence](/api-reference/modelence/server/type-aliases/../../index) / [server](/api-reference/modelence/server/type-aliases/../index) / SecurityConfig > **SecurityConfig** = `object` Defined in: [packages/modelence/src/app/securityConfig.ts:20](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/securityConfig.ts#L20) Security configuration for the application By default, the app is protected against clickjacking by setting `Content-Security-Policy: frame-ancestors 'self'` and `X-Frame-Options: SAMEORIGIN` on all responses, preventing the app from being embedded in iframes on other domains. ## Example ```typescript theme={null} import { startApp } from 'modelence/server'; // Allow embedding in iframes on specific domains startApp({ security: { frameAncestors: ['https://modelence.com', 'https://app.example.com'], }, }); ``` ## Properties | Property | Type | Description | Defined in | | ----------------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `frameAncestors?` | `string`\[] | Additional origins allowed to embed this app in an iframe. The app's own origin (`'self'`) is always included automatically. When not set, only same-origin framing is allowed. When set, `X-Frame-Options` is omitted since it cannot express multiple origins. | [packages/modelence/src/app/securityConfig.ts:28](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/app/securityConfig.ts#L28) | # UserInfo Source: https://docs.modelence.com/api-reference/modelence/server/type-aliases/UserInfo [API Reference](/api-reference/modelence/server/type-aliases/../../../index) / [modelence](/api-reference/modelence/server/type-aliases/../../index) / [server](/api-reference/modelence/server/type-aliases/../index) / UserInfo > **UserInfo** = `object` Defined in: [packages/modelence/src/auth/types.ts:41](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/types.ts#L41) ## Properties | Property | Type | Description | Defined in | | ------------------- | --------------------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `avatarUrl?` | `string` | - | [packages/modelence/src/auth/types.ts:54](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/types.ts#L54) | | `firstName?` | `string` | - | [packages/modelence/src/auth/types.ts:52](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/types.ts#L52) | | `handle` | `string` | The user's display handle. | [packages/modelence/src/auth/types.ts:45](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/types.ts#L45) | | `hasRole` | (`role`) => `boolean` | Returns `true` if the user has the given role. | [packages/modelence/src/auth/types.ts:49](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/types.ts#L49) | | `id` | `string` | The user's unique identifier. | [packages/modelence/src/auth/types.ts:43](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/types.ts#L43) | | `lastName?` | `string` | - | [packages/modelence/src/auth/types.ts:53](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/types.ts#L53) | | `requireRole` | (`role`) => `void` | Throws an error if the user does not have the given role. | [packages/modelence/src/auth/types.ts:51](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/types.ts#L51) | | `roles` | `string`\[] | The role strings assigned to this user in the database. | [packages/modelence/src/auth/types.ts:47](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/types.ts#L47) | # ValueType Source: https://docs.modelence.com/api-reference/modelence/server/type-aliases/ValueType [API Reference](/api-reference/modelence/server/type-aliases/../../../index) / [modelence](/api-reference/modelence/server/type-aliases/../../index) / [server](/api-reference/modelence/server/type-aliases/../index) / ValueType > **ValueType**\<`T`> = `T` *extends* `"number"` ? `number` : `T` *extends* `"string"` ? `string` : `T` *extends* `"text"` ? `string` : `T` *extends* `"boolean"` ? `boolean` : `T` *extends* `"secret"` ? `string` : `never` Defined in: [packages/modelence/src/config/types.ts:14](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/config/types.ts#L14) ## Type Parameters | Type Parameter | Default type | | ------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- | | `T` *extends* [`ConfigType`](/api-reference/modelence/server/type-aliases/ConfigType) | [`ConfigType`](/api-reference/modelence/server/type-aliases/ConfigType) | # dbSessions Source: https://docs.modelence.com/api-reference/modelence/server/variables/dbSessions [API Reference](/api-reference/modelence/server/variables/../../../index) / [modelence](/api-reference/modelence/server/variables/../../index) / [server](/api-reference/modelence/server/variables/../index) / dbSessions > `const` **dbSessions**: [`Store`](/api-reference/modelence/server/variables/../classes/Store)\<\{ `authToken`: `ZodString`; `createdAt`: `ZodDate`; `expiresAt`: `ZodDate`; `userId`: `ZodNullable`\<`ZodType`\<`ObjectId`, `ZodTypeDef`, `ObjectId`>>; }, `Record`\<`string`, (`this`, ...`args`) => `any`>> Defined in: [packages/modelence/src/auth/session.ts:40](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/session.ts#L40) # dbUsers Source: https://docs.modelence.com/api-reference/modelence/server/variables/dbUsers [API Reference](/api-reference/modelence/server/variables/../../../index) / [modelence](/api-reference/modelence/server/variables/../../index) / [server](/api-reference/modelence/server/variables/../index) / dbUsers > `const` **dbUsers**: [`Store`](/api-reference/modelence/server/variables/../classes/Store)\<\{ `authMethods`: `ZodObject`\<\{ `github`: `ZodOptional`\<`ZodObject`\<\{ `id`: `ZodString`; }, `"strip"`, `ZodTypeAny`, \{ `id`: `string`; }, \{ `id`: `string`; }>>; `google`: `ZodOptional`\<`ZodObject`\<\{ `id`: `ZodString`; }, `"strip"`, `ZodTypeAny`, \{ `id`: `string`; }, \{ `id`: `string`; }>>; `password`: `ZodOptional`\<`ZodObject`\<\{ `hash`: `ZodString`; }, `"strip"`, `ZodTypeAny`, \{ `hash`: `string`; }, \{ `hash`: `string`; }>>; }, `"strip"`, `ZodTypeAny`, \{ `github?`: \{ `id`: `string`; }; `google?`: \{ `id`: `string`; }; `password?`: \{ `hash`: `string`; }; }, \{ `github?`: \{ `id`: `string`; }; `google?`: \{ `id`: `string`; }; `password?`: \{ `hash`: `string`; }; }>; `avatarUrl`: `ZodOptional`\<`ZodString`>; `createdAt`: `ZodDate`; `deletedAt`: `ZodOptional`\<`ZodDate`>; `disabledAt`: `ZodOptional`\<`ZodDate`>; `emails`: `ZodOptional`\<`ZodArray`\<`ZodObject`\<\{ `address`: `ZodString`; `verified`: `ZodBoolean`; }, `"strip"`, `ZodTypeAny`, \{ `address`: `string`; `verified`: `boolean`; }, \{ `address`: `string`; `verified`: `boolean`; }>, `"many"`>>; `firstName`: `ZodOptional`\<`ZodString`>; `handle`: `ZodString`; `lastName`: `ZodOptional`\<`ZodString`>; `roles`: `ZodOptional`\<`ZodArray`\<`ZodString`, `"many"`>>; `status`: `ZodOptional`\<`ZodEnum`\<\[`"active"`, `"disabled"`, `"deleted"`]>>; }, `Record`\<`string`, (`this`, ...`args`) => `any`>> Defined in: [packages/modelence/src/auth/db.ts:18](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/auth/db.ts#L18) Database collection for storing user accounts with authentication methods and profile information. This is where **signupWithPassword** automatically creates new users. ## Example ```typescript theme={null} // Find user by email const user = await dbUsers.findOne( { 'emails.address': 'john@example.com' } ); ``` # schema Source: https://docs.modelence.com/api-reference/modelence/server/variables/schema [API Reference](/api-reference/modelence/server/variables/../../../index) / [modelence](/api-reference/modelence/server/variables/../../index) / [server](/api-reference/modelence/server/variables/../index) / schema > `const` **schema**: `object` Defined in: [packages/modelence/src/data/types.ts:31](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/types.ts#L31) ## Type declaration | Name | Type | Default value | Defined in | | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `array()` | \<`El`>(`schema`, `params?`) => `ZodArray`\<`El`> | `schemaArray` | [packages/modelence/src/data/types.ts:36](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/types.ts#L36) | | `boolean()` | (`params?`) => `ZodBoolean` | `schemaBoolean` | [packages/modelence/src/data/types.ts:35](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/types.ts#L35) | | `date()` | (`params?`) => `ZodDate` | `schemaDate` | [packages/modelence/src/data/types.ts:34](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/types.ts#L34) | | `enum()` | \{\<`U`, `T`>(`values`, `params?`): `ZodEnum`\<`Writeable`\<`T`>>; \<`U`, `T`>(`values`, `params?`): `ZodEnum`\<`T`>; } | `schemaEnum` | [packages/modelence/src/data/types.ts:38](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/types.ts#L38) | | `number()` | (`params?`) => `ZodNumber` | `schemaNumber` | [packages/modelence/src/data/types.ts:33](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/types.ts#L33) | | `object()` | \<`Shape`>(`shape`, `params?`) => `ZodObject`\<`Shape`, `"strip"`, `ZodTypeAny`, \{ \[k in string \| number \| symbol]: addQuestionMarks\, any>\[k] }, \{ \[k in string \| number \| symbol]: baseObjectInputType\\[k] }> | `schemaObject` | [packages/modelence/src/data/types.ts:37](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/types.ts#L37) | | `string()` | (`params?`) => `ZodString` | `schemaString` | [packages/modelence/src/data/types.ts:32](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/types.ts#L32) | | `union()` | \<`Options`>(`types`, `params?`) => `ZodUnion`\<`Options`> | - | [packages/modelence/src/data/types.ts:53](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/types.ts#L53) | | `embedding()` | () => `ZodArray`\<`ZodNumber`> | - | [packages/modelence/src/data/types.ts:39](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/types.ts#L39) | | `infer()` | (`_schema`) => `InferDocumentType`\<`T`> | - | [packages/modelence/src/data/types.ts:54](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/types.ts#L54) | | `objectId()` | () => `ZodType`\<`ObjectId`> | - | [packages/modelence/src/data/types.ts:42](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/types.ts#L42) | | `ref()` | (`_collection`) => `ZodType`\<`ObjectId`> | - | [packages/modelence/src/data/types.ts:48](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/types.ts#L48) | | `userId()` | () => `ZodType`\<`ObjectId`> | - | [packages/modelence/src/data/types.ts:45](https://github.com/modelence/modelence/blob/0e072e44dd157ae8712ae82111cf4aa756460eba/packages/modelence/src/data/types.ts#L45) | # Email Verification Source: https://docs.modelence.com/authentication/email-verification Email verification adds an extra layer of security by ensuring users own the email address they register with. > The email delivery setup below (provider, sender, template, redirect URL) is configured under the **`email:`** key of `startApp`. To run code when verification succeeds or fails, register the `onAfterEmailVerification` / `onEmailVerificationError` callbacks under **`auth:`** — see [Auth Hooks](/authentication/hooks). ## Enabling Email Verification First, configure your email provider (see [Email Configuration](/email)): ```typescript theme={null} import { startApp } from 'modelence/server'; import resendProvider from '@modelence/resend'; startApp({ email: { provider: resendProvider, from: 'noreply@yourdomain.com', verification: { subject: 'Verify your email', redirectUrl: 'https://yourdomain.com/email-verified', }, }, }); ``` ## How It Works 1. When a user signs up, a verification token is generated and stored 2. An email with a verification link is sent to the user's email address 3. The link contains the token: `https://yourapp.com/api/_internal/auth/verify-email?token=...` 4. When clicked, the token is validated and the user's email is marked as verified 5. The user is redirected to your configured `redirectUrl` ## Custom Verification Templates You can customize the verification email template: ```typescript theme={null} startApp({ email: { provider: resendProvider, from: 'noreply@yourdomain.com', verification: { subject: 'Welcome! Please verify your email', template: ({ name, email, verificationUrl }) => `

Welcome to Our App!

Hi ${name || 'there'},

Please click the button below to verify your email address:

Verify Email

Or copy and paste this link: ${verificationUrl}

`, redirectUrl: 'https://yourdomain.com/email-verified', }, }, }); ``` ## Manual Verification You can also manually complete email verification from the client using a verification token: ```typescript theme={null} import { verifyEmail } from 'modelence/client'; async function handleVerification(token: string) { try { await verifyEmail({ token }); console.log('Email verified successfully!'); } catch (error) { console.error('Verification failed:', error.message); } } ``` ## Automatic Verification via Password Reset If a user resets their password and their email was not yet verified, the email is automatically marked as verified upon a successful password reset. Since the user must receive the reset email to complete the flow, this proves ownership of the address. See [Password Reset](/authentication/password-reset) for setup details. ## Resending Verification Email If the user did not receive the original verification email, you can resend it. The email is only sent when the address is registered and not yet verified — a generic response is always returned regardless, to avoid leaking account information. This endpoint enforces the following limits via the `verification` rate limit bucket: * **1 per 60 seconds** — per user, a new verification email cannot be sent until 60 seconds have passed since the previous one. * **10 per day** — per user, a maximum of 10 verification emails can be sent within a 24-hour window. * **IP-based rate limiting** — repeated calls from the same IP are also rate-limited. ```typescript theme={null} import { resendEmailVerification } from 'modelence/client'; async function handleResend(email: string) { try { await resendEmailVerification({ email }); console.log('Verification email sent'); } catch (error) { console.error('Error:', error.message); } } ``` # GitHub Sign-In Source: https://docs.modelence.com/authentication/github-sign-in Modelence supports OAuth authentication with GitHub, allowing users to sign in with their GitHub accounts. ## Prerequisites Before implementing GitHub Sign-In, you need to: 1. Have a GitHub account 2. Register a new OAuth application on GitHub 3. Obtain OAuth credentials (Client ID and Client Secret) 4. Configure authorization callback URLs ## GitHub OAuth App Setup 1. **Create an OAuth App** * Go to [GitHub Developer Settings](https://github.com/settings/developers) * Click "OAuth Apps" in the left sidebar * Click "New OAuth App" 2. **Configure Application Details** * **Application name**: Enter your application's name * **Homepage URL**: * For local development: `http://localhost:3000` * For production: `https://yourdomain.com` * **Application description**: (Optional) Describe your application * **Authorization callback URL**: This is critical for OAuth to work * For local development: `http://localhost:3000/api/_internal/auth/github/callback` * For production: `https://yourdomain.com/api/_internal/auth/github/callback` 3. **Register Application** * Click "Register application" 4. **Generate Client Secret** * After registration, you'll see your **Client ID** * Click "Generate a new client secret" * Copy and save the **Client Secret** immediately (it won't be shown again) 5. **Save Credentials** * Store your **Client ID** and **Client Secret** securely * Use environment variables or Modelence Cloud config * Never commit these credentials to version control ## Server-Side Configuration GitHub Sign-In is built into Modelence and requires no additional packages. ### Option 1: Modelence Cloud (Recommended) The preferred way to configure GitHub authentication is through [Modelence Cloud](https://cloud.modelence.com/): 1. Go to [https://cloud.modelence.com/](https://cloud.modelence.com/) 2. Navigate to your project 3. Go to **Users → Auth Providers → GitHub** 4. Enable GitHub authentication 5. Enter your **Client ID** and **Client Secret** from GitHub 6. Save the configuration This approach allows you to manage your configuration centrally through an intuitive UI and keeps sensitive credentials secure. ### Option 2: Environment Variables Alternatively, you can use environment variables. Create a `.env` file in your project root: ```bash theme={null} MODELENCE_AUTH_GITHUB_ENABLED=true MODELENCE_AUTH_GITHUB_CLIENT_ID=your-github-client-id MODELENCE_AUTH_GITHUB_CLIENT_SECRET=your-github-client-secret MODELENCE_AUTH_GITHUB_CLIENT_SCOPES=user:email,read:user ``` **Optional Configuration:** * `MODELENCE_AUTH_GITHUB_CLIENT_SCOPES`: Comma-separated list of OAuth scopes to request from GitHub. Defaults to `user:email` if not specified. Make sure to add `.env` to your `.gitignore` file to keep credentials secure. The GitHub authentication is automatically enabled when these configurations are set. No additional server code is needed. ## Client-Side Implementation To initiate GitHub Sign-In, redirect the user to the GitHub authentication endpoint: ```typescript theme={null} function handleGitHubSignIn() { // Redirect to GitHub OAuth flow window.location.href = '/api/_internal/auth/github'; } ``` ## UI Integration Add a GitHub Sign-In button to your UI: ```typescript theme={null} function LoginForm() { return (

Sign In

); } ``` ## How GitHub Sign-In Works 1. **Initiation** - User clicks "Sign in with GitHub" button 2. **Redirect** - User is redirected to GitHub's OAuth authorization page 3. **Authorization** - User grants permission to your app 4. **Callback** - GitHub redirects back to your app with an authorization code 5. **Token Exchange** - Your server exchanges the code for an access token and user information 6. **User Creation/Login** - If user doesn't exist, a new account is created; otherwise, user is logged in 7. **Session Creation** - A session is established and the user is authenticated ## User Data Handling When a user signs in with GitHub, Modelence automatically: * Creates a user account if one doesn't exist * Links the GitHub account to the user profile * Retrieves profile information (first name, last name, username, email, avatar URL) * Marks the email as verified if GitHub has verified it * **Backfills missing profile fields** — If an existing user is missing `firstName`, `lastName`, or `avatarUrl`, these fields are automatically populated from their GitHub profile on login The user object will contain: ```typescript theme={null} { email: string; // GitHub account email handle: string; // Generated from GitHub username or email emailVerified: boolean; // true if GitHub email is verified githubId: string; // GitHub user ID firstName?: string; // First name from GitHub lastName?: string; // Last name avatarUrl?: string; // Avatar URL from GitHub } ``` ## Requesting Additional Scopes By default, Modelence requests basic profile information (`user:email` scope). If you need additional data from GitHub, you can configure additional scopes using the `MODELENCE_AUTH_GITHUB_CLIENT_SCOPES` environment variable or through Modelence Cloud. ### Configuring Scopes **Via Environment Variables:** ```bash theme={null} # Request multiple scopes (comma-separated) MODELENCE_AUTH_GITHUB_CLIENT_SCOPES=user:email,read:user,repo ``` **Via Modelence Cloud:** 1. Go to [cloud.modelence.com](https://cloud.modelence.com) 2. Navigate to **Authentication → Providers → GitHub** 3. Add the desired scopes in the scopes configuration field ### Common GitHub Scopes * `user:email` - Access to user's email addresses (default, required for authentication) * `read:user` - Read access to user profile data * `user` - Full access to user profile data (includes read and write) * `repo` - Access to public and private repositories * `public_repo` - Access to public repositories only * `gist` - Access to gists * `read:org` - Read-only access to organization membership For a complete list of available scopes, see the [GitHub OAuth scopes documentation](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/scopes-for-oauth-apps). **Note:** Only request the scopes your application actually needs. Users are more likely to authorize your app if it requests minimal permissions. ## Combining with Email/Password Authentication Users can have both GitHub and email/password authentication on the same account: ```typescript theme={null} import { loginWithPassword, logout } from 'modelence/client'; import { useState } from 'react'; function LoginOptions() { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); return (

Sign In

{/* GitHub Sign-In */}
or
{/* Email/Password Sign-In */}
{ e.preventDefault(); await loginWithPassword({ email, password }); }}> setEmail(e.target.value)} placeholder="Email" /> setPassword(e.target.value)} placeholder="Password" />
); } ``` ## Troubleshooting **Authorization callback URL mismatch** * Ensure the callback URL in your GitHub OAuth App settings exactly matches your application URL * Check for trailing slashes and http vs https * Common format: `https://yourdomain.com/api/_internal/auth/github/callback` * You can only register one callback URL per OAuth App **Application suspended error** * Check your GitHub app settings to ensure it hasn't been suspended * Verify your account is in good standing **Invalid client credentials** * Verify your Client ID and Client Secret are correct * Check that environment variables are properly loaded * Ensure you copied the Client Secret correctly (it's only shown once) * Make sure credentials are from the correct GitHub OAuth App **No email address returned** * Some GitHub users have private email addresses * Users must have at least one public email or primary email set * You may need to handle cases where email is not provided * Consider prompting users to provide an email if not available from GitHub **Rate limiting errors** * GitHub enforces rate limits on OAuth endpoints * If developing locally, avoid making too many authentication requests in quick succession * Production apps typically don't hit these limits under normal usage # Google Sign-In Source: https://docs.modelence.com/authentication/google-sign-in Modelence supports OAuth authentication with Google, allowing users to sign in with their Google accounts. ## Prerequisites Before implementing Google Sign-In, you need to: 1. Create a project in the [Google Cloud Console](https://console.cloud.google.com/) 2. Configure the OAuth consent screen 3. Create OAuth 2.0 credentials (Client ID and Client Secret) 4. Configure authorized redirect URIs ## Google Cloud Console Setup 1. **Create a Project** * Go to [Google Cloud Console](https://console.cloud.google.com/) * Click "Select a project" → "New Project" * Name your project and click "Create" 2. **Configure OAuth Consent Screen** * Go to "APIs & Services" → "OAuth consent screen" * Choose user type (External for most applications) * Fill in the required fields: * App name * User support email * Developer contact information * Click "Save and Continue" * Add scopes if needed (profile and email are included by default) * Click "Save and Continue" 3. **Create OAuth Credentials** * Go to "APIs & Services" → "Credentials" * Click "Create Credentials" → "OAuth client ID" * Select "Web application" as the application type * Add a name for your OAuth client 4. **Configure Redirect URIs** * Under "Authorized JavaScript origins", add: * `http://localhost:3000` (for local development) * `https://yourdomain.com` (for production) * Under "Authorized redirect URIs", add: * `http://localhost:3000/api/_internal/auth/google/callback` (for local development) * `https://yourdomain.com/api/_internal/auth/google/callback` (for production) * Click "Create" 5. **Save Credentials** * Copy your **Client ID** and **Client Secret** * Store them securely (use environment variables or Modelence Cloud config) ## Server-Side Configuration Google Sign-In is built into Modelence and requires no additional packages. ### Option 1: Modelence Cloud (Recommended) The preferred way to configure Google authentication is through [Modelence Cloud](https://cloud.modelence.com/): 1. Go to [https://cloud.modelence.com/](https://cloud.modelence.com/) 2. Navigate to your project 3. Go to **Users → Auth Providers → Google** 4. Enable Google authentication 5. Enter your **Client ID** and **Client Secret** from Google Cloud Console 6. Save the configuration This approach allows you to manage your configuration centrally through an intuitive UI and keeps sensitive credentials secure. ### Option 2: Environment Variables Alternatively, you can use environment variables. Create a `.env` file in your project root: ```bash theme={null} MODELENCE_AUTH_GOOGLE_ENABLED=true MODELENCE_AUTH_GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com MODELENCE_AUTH_GOOGLE_CLIENT_SECRET=your-client-secret ``` Make sure to add `.env` to your `.gitignore` file to keep credentials secure. The Google authentication is automatically enabled when these configurations are set. No additional server code is needed. ## Client-Side Implementation To initiate Google Sign-In, redirect the user to the Google authentication endpoint: ```typescript theme={null} function handleGoogleSignIn() { // Redirect to Google OAuth flow window.location.href = '/api/_internal/auth/google'; } ``` ## UI Integration Add a Google Sign-In button to your UI: ```typescript theme={null} function LoginForm() { return (

Sign In

); } ``` ## How Google Sign-In Works 1. **Initiation** - User clicks "Sign in with Google" button 2. **Redirect** - User is redirected to Google's OAuth consent screen 3. **Authorization** - User grants permission to your app 4. **Callback** - Google redirects back to your app with an authorization code 5. **Token Exchange** - Your server exchanges the code for user information 6. **User Creation/Login** - If user doesn't exist, a new account is created; otherwise, user is logged in 7. **Session Creation** - A session is established and the user is authenticated ## User Data Handling When a user signs in with Google, Modelence automatically: * Creates a user account if one doesn't exist * Links the Google account to the user profile * Retrieves profile information (first name, last name, email, avatar URL) * Marks the email as verified (since Google has verified it) * **Backfills missing profile fields** — If an existing user is missing `firstName`, `lastName`, or `avatarUrl`, these fields are automatically populated from their Google profile on login The user object will contain: ```typescript theme={null} { email: string; // Google account email handle: string; // Generated from email or name emailVerified: true; // Always true for Google sign-in googleId: string; // Google user ID firstName?: string; // First name from Google lastName?: string; // Last name from Google avatarUrl?: string; // Avatar URL from Google } ``` ## Combining with Email/Password Authentication Users can have both Google and email/password authentication on the same account: ```typescript theme={null} import { loginWithPassword, logout } from 'modelence/client'; import { useState } from 'react'; function LoginOptions() { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); return (

Sign In

{/* Google Sign-In */}
or
{/* Email/Password Sign-In */}
{ e.preventDefault(); await loginWithPassword({ email, password }); }}> setEmail(e.target.value)} placeholder="Email" /> setPassword(e.target.value)} placeholder="Password" />
); } ``` ## Troubleshooting **Redirect URI Mismatch Error** * Ensure the redirect URI in Google Cloud Console exactly matches your application URL * Check for trailing slashes and http vs https * Common format: `https://yourdomain.com/api/_internal/auth/google/callback` **Invalid Client Error** * Verify your Client ID and Client Secret are correct * Check that environment variables are properly loaded * Ensure credentials are from the correct Google Cloud project **Access Blocked: Authorization Error** * Make sure Google+ API is enabled in your project * Verify your OAuth consent screen is configured * Check that your domain is authorized # Auth Hooks Source: https://docs.modelence.com/authentication/hooks The [AuthConfig](/api-reference/modelence/server/type-aliases/AuthConfig) type provides hooks for authentication events. Configure these in your `startApp` call under the **`auth:`** key. ## Validation Hooks ### `validateSignup` Called before a new user is created during email/password signup. Use this to enforce custom validation rules on signup data. Throw an error to reject the signup. ```typescript theme={null} import { startApp } from 'modelence/server'; startApp({ auth: { validateSignup: ({ email, firstName, lastName, password, handle, avatarUrl }) => { // Custom validation logic if (password.length < 12) { throw new Error('Password must be at least 12 characters'); } if (!firstName) { throw new Error('First name is required'); } }, }, }); ``` **Props:** | Property | Type | | ----------- | --------------------- | | `email` | `string` | | `password` | `string` | | `firstName` | `string \| undefined` | | `lastName` | `string \| undefined` | | `avatarUrl` | `string \| undefined` | | `handle` | `string \| undefined` | **Returns:** `void | Promise` ### `onBeforeSignup` Available since `modelence@0.17.0`. Called after `validateSignup` and the built-in disposable-email check, but before the user document is inserted. Use this to plug in a custom domain-policy check (e.g. a tenant-specific email-domain verification service) without disabling the built-in disposable-email check. Throw an error to reject the signup — the thrown error is re-thrown to the caller and `onSignupError` fires. Invoked for `'email'` and `'magicLink'` provider signups. OAuth signups are not gated because OAuth providers (Google, GitHub, etc.) do not issue disposable accounts. ```typescript theme={null} import { startApp } from 'modelence/server'; startApp({ auth: { onBeforeSignup: async ({ email, firstName, lastName, handle, provider, connectionInfo }) => { const domain = email.split('@')[1]; const allowed = await isAllowedDomain(domain); if (!allowed) { throw new Error(`Signups from ${domain} are not allowed`); } }, }, }); ``` To replace the built-in disposable-email check entirely with your own logic, set `allowDisposableEmails: true` (also available since `modelence@0.17.0`) and enforce your policy in `onBeforeSignup`. ```typescript theme={null} startApp({ auth: { allowDisposableEmails: true, onBeforeSignup: async ({ email }) => { const verdict = await classifyEmailDomain(email); if (verdict === 'disposable') { throw new Error('Disposable email addresses are not allowed'); } }, }, }); ``` **Props:** | Property | Type | | ---------------- | ----------------------------- | | `email` | `string` | | `firstName` | `string \| undefined` | | `lastName` | `string \| undefined` | | `handle` | `string \| undefined` | | `provider` | `'email' \| 'magicLink'` | | `connectionInfo` | `ConnectionInfo \| undefined` | **Returns:** `void | Promise` ### `validateProfileUpdate` Called before a user's profile is updated. Use this to enforce custom validation rules on profile updates. Throw an error to reject the update. ```typescript theme={null} startApp({ auth: { validateProfileUpdate: ({ firstName, lastName, avatarUrl, handle }) => { if (handle && handle.length < 3) { throw new Error('Handle must be at least 3 characters'); } }, }, }); ``` **Props:** | Property | Type | | ----------- | --------------------- | | `firstName` | `string \| undefined` | | `lastName` | `string \| undefined` | | `avatarUrl` | `string \| undefined` | | `handle` | `string \| undefined` | **Returns:** `void | Promise` ## Custom Handle Generation ### `generateHandle` By default, handles are derived from the user's email address. This hook lets you generate custom handles based on the user's email and profile information. ```typescript theme={null} startApp({ auth: { generateHandle: ({ email, firstName, lastName }) => { // Generate a custom handle if (firstName && lastName) { return `${firstName.toLowerCase()}-${lastName.toLowerCase()}`; } return email.split('@')[0]; }, }, }); ``` **Props:** | Property | Type | | ----------- | --------------------- | | `email` | `string` | | `firstName` | `string \| undefined` | | `lastName` | `string \| undefined` | **Returns:** `string | Promise` — The generated handle. If the handle conflicts with an existing one, Modelence will automatically append a numeric suffix. ## Auth Events ```typescript theme={null} startApp({ auth: { onAfterLogin: ({ user, provider, session, connectionInfo }) => { // Called after successful login console.log(`${user.handle} logged in via ${provider} from ${connectionInfo.ip}`); }, onLoginError: ({ error, provider, session, connectionInfo }) => { // Called when login fails console.error('Login error:', error.message); }, onAfterSignup: ({ user, provider, session, connectionInfo }) => { // Called after successful signup // Perfect place to send welcome emails or analytics }, onSignupError: ({ error, provider, session, connectionInfo }) => { // Called when signup fails console.error('Signup error:', error.message); }, onAfterEmailVerification: ({ user, session, connectionInfo }) => { // Called after successful email verification }, onEmailVerificationError: ({ error, session, connectionInfo }) => { // Called when email verification fails }, }, }); ``` ## Error Rendering ### `errorComponent` Use `errorComponent` to customize how OAuth authentication errors are rendered. By default, OAuth errors are returned as JSON. Providing `errorComponent` allows you to return a custom HTML response instead. This is useful when OAuth flows are triggered in a browser context. ```typescript theme={null} startApp({ auth: { errorComponent: ({ error, statusCode }) => { // Safely escape the error string to prevent XSS vulnerabilities const escapeHtml = (str: string | number) => String(str).replace(/[&<>"']/g, m => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' })[m as any] || m); return `

Error ${escapeHtml(statusCode)}

${escapeHtml(error)}

`; }, }, }); ``` ## Full Example ```typescript theme={null} import { startApp } from 'modelence/server'; startApp({ auth: { validateSignup: ({ email, password, firstName }) => { if (!firstName) { throw new Error('First name is required'); } }, validateProfileUpdate: ({ handle }) => { if (handle && !/^[a-z0-9-]+$/.test(handle)) { throw new Error('Handle can only contain lowercase letters, numbers, and hyphens'); } }, onBeforeSignup: async ({ email }) => { const domain = email.split('@')[1]; if (domain === 'blocked.example') { throw new Error(`Signups from ${domain} are not allowed`); } }, generateHandle: ({ email, firstName, lastName }) => { if (firstName && lastName) { return `${firstName}-${lastName}`.toLowerCase(); } return email.split('@')[0]; }, errorComponent: ({ error, statusCode }) => { const escapeHtml = (str: string | number) => String(str).replace(/[&<>"']/g, m => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' })[m as any] || m); return `

Error ${escapeHtml(statusCode)}

${escapeHtml(error)}

`; }, onAfterSignup: ({ user }) => { console.log('Welcome!', user.handle); }, onAfterLogin: ({ user, provider }) => { console.log(`${user.handle} logged in via ${provider}`); }, }, }); ``` # Auth Overview Source: https://docs.modelence.com/authentication/index Modelence provides a comprehensive built-in authentication system with support for email/password authentication, email verification, password reset, and session management. This guide explains how authentication works in Modelence and how to implement it in your application. ## Overview Modelence authentication includes: * **Email/Password Authentication** - User signup and login with email and password * **Session Management** - Secure session handling with automatic token rotation * **[User Management](/authentication/user-management)** - User profile and role management * **[Email Verification](/authentication/email-verification)** - Optional email verification for new signups * **[Password Reset](/authentication/password-reset)** - Secure password reset flow with email tokens * **[Hooks](/authentication/hooks)** - Add custom handlers and error rendering components for your authentication flow * **[Rate Limiting](/authentication/rate-limiting)** - Built-in protection against brute force attacks * **[Google Sign-In](/authentication/google-sign-in)** - OAuth authentication with Google accounts * **[GitHub Sign-In](/authentication/github-sign-in)** - OAuth authentication with GitHub accounts ## Where to configure what Modelence splits authentication configuration across two top-level keys in `startApp`: * **`auth: { ... }`** — authentication *lifecycle*: validation hooks (`validateSignup`, `validateProfileUpdate`), event callbacks (`onAfterLogin`, `onAfterSignup`, `onAfterEmailVerification`, …), `generateHandle`, OAuth linking behavior, and `rateLimits`. See [AuthConfig](/api-reference/modelence/server/type-aliases/AuthConfig) and [Hooks](/authentication/hooks). * **`email: { ... }`** — email *delivery*: the email provider, sender address, and per-flow templates/subjects/redirect URLs for `verification` and `passwordReset`. See [Email Configuration](/email). The two are complementary: `email:` controls whether and how the verification/reset email is delivered; `auth:` controls what happens when the user clicks the link (and the rest of the auth lifecycle). ## How Authentication Works ### Session Management When a user visits your application, Modelence automatically creates a session: 1. **Session Creation** - A secure session token is generated using cryptographically random bytes 2. **Token Storage** - The session token is stored in the database and sent to the client 3. **Automatic Expiration** - Sessions expire after 7 days of inactivity 4. **Heartbeat Updates** - Active sessions are automatically renewed through periodic heartbeat requests Sessions are stored in the `_modelenceSessions` collection and tracked with the following properties: ```typescript theme={null} { authToken: string; // Secure random token createdAt: Date; // Session creation timestamp expiresAt: Date; // Automatic expiration date userId: ObjectId | null; // Associated user (null for guest sessions) } ``` ### User Authentication Flow #### Signup Process When a user signs up with email and password: 1. **Validation** - Email format and password strength are validated 2. **Duplicate Check** - System checks if email already exists 3. **Validate Signup** (Optional) - If provided, validates signup using `validateSignup` hook 4. **Password Hashing** - Password is securely hashed using bcrypt (never stored in plain text) 5. **User Creation** - User record is created in the `_modelenceUsers` collection 6. **Session Linking** - The session is linked to the new user 7. **Email Verification** (Optional) - If enabled, a verification email is sent #### Login Process When a user logs in: 1. **Credential Verification** - Email and password are validated against stored credentials 2. **Session Update** - Current session is linked to the authenticated user 3. **User Data** - User information is returned to the client 4. **State Update** - Client-side session state is updated ### OAuth Account Linking When a user signs in with an OAuth provider (Google or GitHub) using an email that already matches an existing email/password account, behavior is controlled by the [`oauthAccountLinking`](/api-reference/modelence/server/type-aliases/AuthConfig#oauthaccountlinking) auth config option: * **`'manual'`** (default) - The OAuth sign-in is rejected with an error: *"User with this email already exists. Please log in instead."* The user must log in with their existing password first and link the provider deliberately. * **`'auto'`** - The OAuth provider is automatically linked to the existing account, but only when **both** the OAuth-provided email is verified by the provider **and** the matching email on the existing account is also marked verified locally. This dual-verification requirement prevents pre-registration account takeover (e.g., someone registering a password account against an email they don't own, then waiting for the real owner to sign in via OAuth). When auto-linking succeeds, missing `firstName`, `lastName`, and `avatarUrl` fields are backfilled from the provider profile. If either email is unverified — even in `'auto'` mode — the sign-in is rejected with the same error. Once an OAuth provider is linked, subsequent sign-ins with the same provider look up the user directly by the provider's user ID, regardless of email. ## Basic Implementation ### Client-Side Usage #### Signup ```typescript theme={null} import { signupWithPassword } from 'modelence/client'; async function handleSignup(email: string, password: string) { try { await signupWithPassword({ email, password }); // User is now signed up // If email verification is disabled, user is automatically logged in } catch (error) { console.error('Signup failed:', error.message); } } // You can also pass optional profile fields during signup await signupWithPassword({ email: 'test@example.com', password: 'securepassword', firstName: 'John', lastName: 'Doe', avatarUrl: 'https://example.com/avatar.jpg', handle: 'johndoe', }); ``` #### Login ```typescript theme={null} import { loginWithPassword } from 'modelence/client'; async function handleLogin(email: string, password: string) { try { const user = await loginWithPassword({ email, password }); console.log('Logged in as:', user.handle); } catch (error) { console.error('Login failed:', error.message); } } ``` #### Logout ```typescript theme={null} import { logout } from 'modelence/client'; async function handleLogout() { await logout(); // User is now logged out } ``` #### Update Profile ```typescript theme={null} import { updateProfile } from 'modelence/client'; async function handleUpdateProfile() { try { const user = await updateProfile({ firstName: 'John', lastName: 'Doe', avatarUrl: 'https://example.com/avatar.jpg', handle: 'johndoe', }); console.log('Profile updated:', user.handle); } catch (error) { console.error('Update failed:', error.message); } } ``` All fields are optional — pass only the ones you want to update. Modelence automatically updates the user in `useSession()`. #### Accessing Current User ```typescript theme={null} import { useSession } from 'modelence/client'; function MyComponent() { const { user } = useSession(); if (!user) { return
Please log in
; } return
Welcome, {user.handle}!
; } ``` ## API Reference ### Client Functions * [signupWithPassword](/api-reference/modelence/client/functions/signupWithPassword) - Sign up with email and password * [loginWithPassword](/api-reference/modelence/client/functions/loginWithPassword) - Log in with email and password * [logout](/api-reference/modelence/client/functions/logout) - Log out current user * [useSession](/api-reference/modelence/client/functions/useSession) - Access current user session * [verifyEmail](/api-reference/modelence/client/functions/verifyEmail) - Verify email with token * [sendResetPasswordToken](/api-reference/modelence/client/functions/sendResetPasswordToken) - Request password reset * [resetPassword](/api-reference/modelence/client/functions/resetPassword) - Set a new password (token is exchanged server-side via cookie) ### Server Types * [AuthConfig](/api-reference/modelence/server/type-aliases/AuthConfig) - Authentication configuration * [UserInfo](/api-reference/modelence/server/type-aliases/UserInfo) - User information type * [dbUsers](/api-reference/modelence/server/variables/dbUsers) - User database collection ### Error Types * [AuthError](/api-reference/modelence/index/classes/AuthError) - Authentication errors * [ValidationError](/api-reference/modelence/index/classes/ValidationError) - Validation errors * [RateLimitError](/api-reference/modelence/index/classes/RateLimitError) - Rate limit errors # Magic Link Source: https://docs.modelence.com/authentication/magic-link Modelence supports passwordless authentication with magic links: the user enters their email address and receives an email with a single-use sign-in **link** and a matching **one-time code**. Clicking the link signs them in; typing the code does the same — useful on mobile apps or when the email is read on a different device. Magic link sign-in and sign-up are available since `modelence@0.22.0`. Magic link can also work as a combined sign-in and sign-up: with the `allowSignup` option enabled, an account is created automatically when the link or code is used for an email that is not registered yet — just like OAuth sign-in. This is disabled by default (see [Sign-Up Behavior](#sign-up-behavior)). > The magic link email delivery setup below (provider, sender, template, redirect URL) is configured under the **`email:`** key of `startApp`. To run code on related auth events, register callbacks under **`auth:`** — see [Auth Hooks](/authentication/hooks). ## Configuration Magic link authentication is disabled by default. Enable it under the `auth:` key of `startApp` and configure the email delivery under the `email:` key: ```typescript theme={null} import { startApp } from 'modelence/server'; import resendProvider from '@modelence/resend'; startApp({ auth: { magicLink: { enabled: true, // Optional: also create accounts for unknown emails (default: false) allowSignup: true, }, }, email: { provider: resendProvider, from: 'noreply@yourdomain.com', magicLink: { subject: 'Your sign-in link', redirectUrl: 'https://yourdomain.com/auth/magic-link', }, }, }); ``` `redirectUrl` is the page in your app that completes the sign-in. Modelence redirects here **after** validating the token and storing it in an `httpOnly` cookie, so this URL never carries the token. This is also where you call [`loginWithMagicLink()`](#complete-the-sign-in). ## How It Works 1. User requests a magic link by providing their email 2. A secure single-use link token and a 6-digit one-time code are generated, hashed, and stored in the database (only the hashes are stored, never the raw values). Both expire after 15 minutes, and using either one invalidates both 3. An email with the sign-in link and the code is sent to the address. The response is always the same generic message, so it never reveals whether an email is registered (with `allowSignup` disabled, unknown emails get the same response but no email is sent) 4. The link points at a Modelence server route, **not** your SPA page. That route validates the token, stores it in a short-lived `httpOnly` cookie, and redirects to your configured `redirectUrl` **without the token in the URL**. The token is **not** consumed at this step, so email security scanners that prefetch links cannot burn it 5. On that page, you call `loginWithMagicLink()` — the token is read server-side from the cookie, atomically consumed (single-use), and the user is signed in. Alternatively, the user types the code anywhere and you call `loginWithOneTimeCode({ email, code })` 6. If no account exists for the email and `allowSignup` is enabled, one is created first (see [Sign-Up Behavior](#sign-up-behavior)) 7. The email address is marked as verified — using the emailed link or code proves ownership The magic link token never reaches your client code or appears in a browser URL — it is exchanged server-side through an `httpOnly` cookie, the same pattern used by [password reset](/authentication/password-reset). This closes the window where a token could leak via the address bar, browser history, or the `Referer` header. ### Base URL requirement The magic link is built from your site's base URL, so you must set it via the `_system.site.url` config (or the `MODELENCE_SITE_URL` environment variable). If it isn't set, sending a magic link fails with a clear error rather than emailing a broken link. ### Sender address requirement `email.from` must be set to an address on your own domain. There is no default sender — if it isn't configured, sending a magic link fails with a clear error rather than sending from an address your email provider can't authenticate (SPF/DKIM). ## Client Implementation ### Request a Magic Link ```typescript theme={null} import { sendMagicLink } from 'modelence/client'; async function handleMagicLinkRequest(email: string) { try { await sendMagicLink({ email }); console.log('Check your email for a sign-in link'); } catch (error) { console.error('Error:', error.message); } } ``` A typical email form: ```tsx theme={null} import { useState } from 'react'; import { sendMagicLink } from 'modelence/client'; function MagicLinkForm() { const [isSent, setIsSent] = useState(false); if (isSent) { return

Check your email — we've sent you a sign-in link.

; } return (
{ event.preventDefault(); const email = new FormData(event.currentTarget).get('email') as string; await sendMagicLink({ email }); setIsSent(true); }} >
); } ``` ### Complete the Sign-In The user lands on your `redirectUrl` page after clicking the email link. The token is already held in an `httpOnly` cookie, so no arguments are needed: ```tsx theme={null} import { useEffect, useRef, useState } from 'react'; import { loginWithMagicLink } from 'modelence/client'; function MagicLinkLoginPage() { const [error, setError] = useState(null); const startedRef = useRef(false); useEffect(() => { // Guard against double-invocation (React StrictMode) — the token is // single-use, so the mutation must only run once. if (startedRef.current) return; startedRef.current = true; // The landing route redirects here with ?status=error when the link is // invalid or expired. const params = new URLSearchParams(window.location.search); if (params.get('status') === 'error') { setError(params.get('message') ?? 'This sign-in link is invalid or has expired.'); return; } loginWithMagicLink() .then(() => { window.location.href = '/'; }) .catch((err) => setError(err.message)); }, []); if (error) { return

{error}

; } return

Signing you in…

; } ``` ### Sign In with the One-Time Code The same email carries a 6-digit code, so users can complete the sign-in without clicking the link — the natural path for native apps (Expo / React Native) where deep links aren't set up, or when the email is opened on a different device than the one signing in: ```tsx theme={null} import { useState } from 'react'; import { loginWithOneTimeCode } from 'modelence/client'; function OneTimeCodeForm({ email }: { email: string }) { const [error, setError] = useState(null); return (
{ event.preventDefault(); const code = new FormData(event.currentTarget).get('code') as string; try { await loginWithOneTimeCode({ email, code }); // Signed in — navigate to your app's home screen } catch (err) { setError((err as Error).message); } }} > {error &&

{error}

}
); } ``` Whitespace and dashes in the typed code are ignored, so `482 193` and `482-193` both work. Each code tolerates only a few wrong guesses before it is invalidated, and using the code invalidates the link (and vice versa). ## Sign-Up Behavior Automatic account creation is a separate opt-in from enabling magic links, and it is **disabled by default**: unknown emails receive no email (the response stays the same generic message), and a link or code can never create an account. Enable it with `allowSignup`: ```typescript theme={null} startApp({ auth: { magicLink: { enabled: true, allowSignup: true, }, }, }); ``` With `allowSignup` enabled, when a magic link is used for an email with no existing account, Modelence creates one automatically: * The account is created with the email already marked as **verified** * The handle is derived from the email local-part (or via your [`generateHandle`](/authentication/hooks) hook) * The [`onBeforeSignup`](/authentication/hooks) hook runs first and can reject the signup by throwing; [`onAfterSignup`](/authentication/hooks) fires after the account is created * No password is set — the user can keep signing in with magic links, add a password later via password reset, or link an OAuth provider For existing accounts, magic link works regardless of how the account was originally created (password or OAuth) — [`onAfterLogin`](/authentication/hooks) fires as usual. All magic link hook invocations use `provider: 'magicLink'`. ## Custom Email Template The template receives both credentials — `magicLinkUrl` (the clickable link) and `code` (the typed one-time code) — so you can render either or both: ```typescript theme={null} startApp({ email: { provider: resendProvider, from: 'noreply@yourdomain.com', magicLink: { subject: 'Sign in to YourApp', template: ({ name, email, magicLinkUrl, code }) => `

Sign in to YourApp

Hi ${name || 'there'},

Click the button below to sign in as ${email}:

Sign In

Or enter this code in the app:

${code}

The link and code can only be used once and will expire in 15 minutes.

If you didn't request this, you can safely ignore this email.

`, redirectUrl: 'https://yourdomain.com/auth/magic-link', }, }, }); ``` ## Security * **Single-use, short-lived credentials** — the link and code work exactly once (using either invalidates both) and expire after 15 minutes * **Hashed at rest** — only SHA-256 hashes are stored, so a database leak does not expose usable links * **Scanner-safe** — the emailed link only stashes the token in a cookie; it is consumed by the follow-up client call, so corporate email scanners that prefetch links do not invalidate them * **Guess-resistant codes** — each code allows only a handful of wrong guesses before it is invalidated, and code attempts are separately rate limited per IP and per email * **No enumeration** — requesting a link always returns the same generic response, whether or not the email is registered; a wrong code returns the same error as an unknown email * **Rate limited** — magic link requests and code attempts are limited per IP and per email address; see [Rate Limiting](/authentication/rate-limiting) to customize the `magicLink` and `oneTimeCode` buckets # Password Reset Source: https://docs.modelence.com/authentication/password-reset Modelence provides a secure password reset flow with email tokens. > The reset email delivery setup below (provider, sender, template, redirect URL) is configured under the **`email:`** key of `startApp`. To run code on related auth events, register callbacks under **`auth:`** — see [Auth Hooks](/authentication/hooks). ## Configuration Configure password reset emails in your server setup: ```typescript theme={null} import { startApp } from 'modelence/server'; import resendProvider from '@modelence/resend'; startApp({ email: { provider: resendProvider, from: 'noreply@yourdomain.com', passwordReset: { subject: 'Reset your password', redirectUrl: 'https://yourdomain.com/reset-password', }, }, }); ``` `redirectUrl` is the page in your app where the user enters their new password. Modelence redirects here **after** validating the token and storing it in an `httpOnly` cookie, so this URL never carries the token. This is also where you call [`resetPassword({ password })`](#reset-password). ## How It Works 1. User requests a password reset by providing their email 2. A secure reset token is generated, hashed, and stored in the database (only the hash is stored, never the raw token) 3. An email with a reset link is sent to the user 4. The link points at a Modelence server route, **not** your SPA page. That route validates the token, stores it in a short-lived `httpOnly` cookie, and redirects to your configured `redirectUrl` **without the token in the URL** 5. On that page, the user enters their new password and you call `resetPassword({ password })` — the token is read server-side from the cookie, so it never reaches client JavaScript 6. Password is updated and the token is invalidated (single-use) 7. If the user's email was not yet verified, it is automatically marked as verified Since the user must receive the reset email to complete the flow, a successful password reset proves ownership of the email address. This is a **set-or-reset** flow. It works for accounts that have no password yet — for example those created via [magic link](/authentication/magic-link) or OAuth — letting the user add a local password. Completing it sets the password whether or not one existed before. The reset token never reaches your client code or appears in a browser URL — it is exchanged server-side through an `httpOnly` cookie. This closes the window where a token could leak via the address bar, browser history, or the `Referer` header. The token cookie is sent with credentialed requests, so it works even when your SPA and Modelence API are on different origins. For that cross-origin case, the API must respond with `Access-Control-Allow-Credentials: true` and a specific (non-wildcard) allowed origin, otherwise the browser drops the cookie and the reset fails. ### Base URL requirement The reset email link is built from your site's base URL, so you must set it via the `_system.site.url` config (or the `MODELENCE_SITE_URL` environment variable). If it isn't set, sending a reset token fails with a clear error rather than emailing a broken link. ## Client Implementation ### Request Password Reset ```typescript theme={null} import { sendResetPasswordToken } from 'modelence/client'; async function handleForgotPassword(email: string) { try { await sendResetPasswordToken({ email }); console.log('Password reset email sent'); } catch (error) { console.error('Error:', error.message); } } ``` ### Reset Password The user lands on your `redirectUrl` page after clicking the email link. The token is already held in an `httpOnly` cookie, so you only collect the new password — don't pass a token: ```typescript theme={null} import { resetPassword } from 'modelence/client'; async function handleResetPassword(newPassword: string) { try { await resetPassword({ password: newPassword }); console.log('Password reset successful'); } catch (error) { console.error('Reset failed:', error.message); } } ``` Passing a `token` to `resetPassword({ token, password })` is **deprecated**. It exists only for legacy flows that still carry the token client-side and will be removed. New apps should rely on the server-side cookie exchange and submit just the password. ## Custom Reset Email Template ```typescript theme={null} startApp({ email: { provider: resendProvider, from: 'noreply@yourdomain.com', passwordReset: { subject: 'Reset Your Password', template: ({ name, email, resetUrl }) => `

Password Reset Request

Hi ${name || 'there'},

We received a request to reset your password. Click the button below to proceed:

Reset Password

If you didn't request this, you can safely ignore this email.

This link will expire in 1 hour.

`, redirectUrl: 'https://yourdomain.com/reset-password', }, }, }); ``` # Auth Rate Limiting Source: https://docs.modelence.com/authentication/rate-limiting Modelence includes built-in rate limiting on all authentication endpoints to protect against brute force attacks and abuse. ## Default Rate Limits * **Signup**: 20 attempts per 15 minutes, 200 per day (per IP) * **Login**: 50 attempts per 15 minutes, 500 per day (per IP) * **Email Verification**: 1 per 60 seconds, 10 per day (per user) * **Password Reset**: 10 per 15 minutes, 100 per day (per IP); 5 per hour, 10 per day (per email) * **Magic Link**: 10 per 15 minutes, 100 per day (per IP); 5 per hour, 10 per day (per email) * **One-Time Code**: 20 per 15 minutes, 100 per day (per IP); 10 per hour, 20 per day (per email) These limits are automatically enforced and will throw a [RateLimitError](/api-reference/modelence/index/classes/RateLimitError) when exceeded. ## Handling Rate Limit Errors ```typescript theme={null} import { loginWithPassword } from 'modelence/client'; import { RateLimitError } from 'modelence'; async function handleLogin(email: string, password: string) { try { await loginWithPassword({ email, password }); } catch (error) { if (error instanceof RateLimitError) { console.error('Too many attempts. Please try again later.'); } else { console.error('Login failed:', error.message); } } } ``` ## Disposable Email Detection Aside from rate limiting, Modelence also includes automatic protection against 100k+ disposable email services, and keeps a periodically updated dataset of all disposable email providers. *** For defining custom rate limits on your own modules, see [Custom Rate Limiting](/rate-limiting). # User Management Source: https://docs.modelence.com/authentication/user-management Modelence stores user data in the `dbUsers` collection, which you can query and update directly from your server-side code. ## Finding Users ```typescript theme={null} import { dbUsers, ObjectId } from 'modelence/server'; // Find user by ID const user = await dbUsers.findById(userId); // Find user by email const user = await dbUsers.findOne({ 'emails.address': 'john@example.com' }); // Find all users with a specific role const admins = await dbUsers.fetch({ roles: 'admin' }); ``` ## Accessing the current user in method calls Use the `user` object from the context in your query/mutation handler to access the currently authenticated user: ```typescript theme={null} import { Module } from 'modelence/server'; export default new Module('profile', { queries: { getMyProfile: async (args, { user }) => { if (!user) { return null; } return { id: user.id, handle: user.handle, roles: user.roles, }; } } }); ``` ## Disabling & Deleting Users Modelence provides helper functions for safely disabling or deleting users: ```typescript theme={null} import { disableUser, deleteUser, ObjectId } from 'modelence/server'; // Set user's status to `disabled` and clears all sessions (preserves data, prevents login) await disableUser(new ObjectId(userId)); // Delete a user (anonymizes data, clears all login methods) await deleteUser(new ObjectId(userId)); ``` # Configuration Source: https://docs.modelence.com/configuration Define typed configuration schemas and access them with Module.getConfig and createClientModule(...).getConfig. Available since modelence@0.15.0. Modelence modules support a `configSchema` that lets you define typed, named configuration values. These values can be managed through Modelence Cloud and accessed at runtime via typed accessors. This is the recommended way to store settings like API keys, feature toggles, default values, and any other configuration your module needs — without hardcoding them or relying solely on environment variables. ## Version Requirements Configuration accessors in this guide require: * `Module.getConfig()` - available since `modelence@0.15.0` * `createClientModule(...).getConfig()` - available since `modelence@0.15.0` ## Defining a Config Schema Add a `configSchema` to your module definition. Each key becomes a configuration value namespaced under the module name: ```typescript title="src/server/payments/index.ts" theme={null} import { Module } from 'modelence/server'; export default new Module('payments', { configSchema: { apiKey: { type: 'secret', default: '', isPublic: false, }, currency: { type: 'string', default: 'USD', isPublic: true, }, maxRetries: { type: 'number', default: 3, isPublic: false, }, }, }); ``` Each config field requires three properties: | Property | Type | Description | | ---------- | ---------------- | ------------------------------------------------------- | | `type` | `ConfigType` | The data type — see [Config Types](#config-types) below | | `default` | *(matches type)* | Default value used when no value has been set | | `isPublic` | `boolean` | Whether this value is accessible on the client | ## Config Types The `type` field accepts one of five values: | Type | Value Type | Description | | ----------- | ---------- | ---------------------------------------------------------------------------------------------------- | | `'string'` | `string` | A short text value (single line) | | `'text'` | `string` | A longer text value (multi-line, rendered as a textarea in Cloud) | | `'number'` | `number` | A numeric value | | `'boolean'` | `boolean` | A true/false toggle | | `'secret'` | `string` | A sensitive value like an API key or token. Masked in the Cloud dashboard. **Cannot be `isPublic`.** | Config values with `type: 'secret'` cannot have `isPublic: true`. Modelence will throw an error at startup if this rule is violated. ## Reading Config Values ### Server-side Call `getConfig` directly on the module instance. The return type is inferred automatically from the schema — no casts needed: `Module.getConfig()` is available since `modelence@0.15.0`. ```typescript title="src/server/payments/index.ts" theme={null} import { Module } from 'modelence/server'; const paymentsModule = new Module('payments', { configSchema: { apiKey: { type: 'secret', default: '', isPublic: false }, maxRetries: { type: 'number', default: 3, isPublic: false }, }, mutations: { async charge({ amount }) { const apiKey = paymentsModule.getConfig('apiKey'); // string const retries = paymentsModule.getConfig('maxRetries'); // number // ... }, }, }); export default paymentsModule; ``` ### Client-side Use `createClientModule` to create a typed accessor for a module's public config values. Pass the module type via `import type` — no server code is bundled on the client. `createClientModule(...).getConfig()` is available since `modelence@0.15.0`. ```typescript title="src/client/payments.ts" theme={null} import type paymentsModule from '../server/payments'; import { createClientModule } from 'modelence/client'; export const payments = createClientModule('payments'); ``` ```typescript title="src/components/Checkout.tsx" theme={null} import { payments } from '../client/payments'; function Checkout() { const currency = payments.getConfig('currency'); // string | undefined return
Currency: {currency}
; } ``` Only values marked `isPublic: true` are available on the client. Private and `secret` values are **not** sent to the client and will not appear as valid keys. For typed query and mutation wrappers, see: * [Queries](/core-concepts/queries) * [Mutations](/core-concepts/mutations) ## Managing Values in Modelence Cloud Once your module defines a `configSchema`, the configuration fields appear automatically in the Modelence Cloud dashboard: 1. Go to [cloud.modelence.com](https://cloud.modelence.com) 2. Select your environment 3. Open the **Application** tab 4. Find your module's configuration section 5. Set values and save Changes sync to your running application automatically (within \~10 seconds). Config values set in Modelence Cloud take precedence over defaults defined in your code. Environment variables take precedence over both. ## Examples ### Storing a third-party API key ```typescript title="src/server/ai/index.ts" theme={null} import { Module } from 'modelence/server'; const aiModule = new Module('ai', { configSchema: { apiKey: { type: 'secret', default: '', isPublic: false, }, model: { type: 'string', default: 'gpt-4o', isPublic: false, }, }, mutations: { async generateResponse({ prompt }: { prompt: string }) { const apiKey = aiModule.getConfig('apiKey'); // string const model = aiModule.getConfig('model'); // string if (!apiKey) { throw new Error('AI API key not configured'); } const response = await fetch('https://api.openai.com/v1/chat/completions', { method: 'POST', headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ model, messages: [{ role: 'user', content: prompt }], }), }); return response.json(); }, }, }); export default aiModule; ``` ### Feature toggle with a boolean config ```typescript title="src/server/notifications/index.ts" theme={null} import { Module } from 'modelence/server'; const notificationsModule = new Module('notifications', { configSchema: { emailEnabled: { type: 'boolean', default: true, isPublic: false, }, footer: { type: 'text', default: 'You are receiving this because you signed up for our service.', isPublic: false, }, }, mutations: { async sendNotification({ userId, message }: { userId: string; message: string }) { const emailEnabled = notificationsModule.getConfig('emailEnabled'); // boolean if (!emailEnabled) { return { skipped: true }; } const footer = notificationsModule.getConfig('footer'); // string // Send email with message + footer... }, }, }); export default notificationsModule; ``` ### Exposing config to the client ```typescript title="src/server/app/index.ts" theme={null} import { Module } from 'modelence/server'; export default new Module('app', { configSchema: { appName: { type: 'string', default: 'My App', isPublic: true, }, maintenanceMode: { type: 'boolean', default: false, isPublic: true, }, }, }); ``` ```typescript title="src/client/app.ts" theme={null} import type appModule from '../server/app'; import { createClientModule } from 'modelence/client'; export const app = createClientModule('app'); ``` ```typescript title="src/components/Header.tsx" theme={null} import { app } from '../client/app'; function Header() { const appName = app.getConfig('appName'); // string | undefined const maintenance = app.getConfig('maintenanceMode'); // boolean | undefined if (maintenance) { return
We are currently undergoing maintenance. Please check back soon.
; } return

{appName}

; } ``` ## Type Reference See the full API reference for config types: * [`ConfigSchema`](/api-reference/modelence/index/type-aliases/ConfigSchema) — The schema object passed to a module * [`ConfigType`](/api-reference/modelence/server/type-aliases/ConfigType) — The union of allowed type values * [`getConfig` (server)](/api-reference/modelence/server/functions/getConfig) — Read config on the server (untyped, for dynamic keys) * [`getConfig` (client)](/api-reference/modelence/client/functions/getConfig) — Read config on the client (untyped, for dynamic keys) # Environment & Setup Source: https://docs.modelence.com/core-concepts/environment-and-setup Modelence provides flexible configuration options for your application. You can configure your app through the `startApp()` function, environment variables, and Modelence Cloud settings. ## Configuration Methods There are three ways to configure your Modelence application, listed in order of precedence: 1. **Environment Variables** - Highest priority, overrides everything 2. **Modelence Cloud** - Synced configuration from cloud.modelence.com 3. **startApp() Options** - Direct code configuration, lowest priority Environment variables always take precedence, allowing you to override any configuration when deploying to different environments. ## Basic Configuration with startApp() The `startApp()` function is your application's entry point where you configure core settings: ```typescript title="src/server/app.ts" theme={null} import { startApp } from 'modelence/server'; import todoModule from './todo'; import userModule from './users'; startApp({ // Register your modules modules: [todoModule, userModule], // Email configuration email: { provider: resendProvider, from: 'noreply@yourapp.com' } }); ``` ## Environment Variables Environment variables provide a way to configure your application without hardcoding values. They override all other configuration methods. ### Core Environment Variables ```env title=".modelence.env" theme={null} # MongoDB connection string MONGODB_URI="mongodb+srv://user:pass@cluster.mongodb.net/myapp" # Server configuration PORT=3000 MODELENCE_SITE_URL=http://localhost ``` ### All Environment Variables Every `MODELENCE_*` variable (plus the few non-prefixed ones) that the framework or first-party packages read. Anything not listed here is application-specific and should go through `defineConfigs` / `getConfig` instead. #### Core | Variable | Type | Default | Consumed by | | -------------------------- | -------------------------------------- | -------------------- | ------------------------------------------------------------------------- | | `MONGODB_URI` | string | — | `packages/modelence` (database connection) | | `MONGODB_POOL_SIZE` | number | driver default | `packages/modelence` (pool size override) | | `MODELENCE_SITE_URL` | string | — | `packages/modelence` (public site URL, used by auth callbacks and emails) | | `PORT` | number | `3000` | `packages/modelence/app/server.ts` | | `MODELENCE_PORT` | number | falls back to `PORT` | `packages/modelence/app/server.ts` | | `NODE_ENV` | `development` \| `production` | `development` | Build pipeline, cookie `secure` flag, Vite dev server | | `MODELENCE_LOG_LEVEL` | `debug` \| `info` \| `warn` \| `error` | `info` | `packages/modelence/telemetry` | | `MODELENCE_ENV_TYPE` | string | — | `packages/modelence/config` (`_system.env.type`) | | `MODELENCE_MULTI_INSTANCE` | boolean | `false` | `packages/modelence/config` (`_system.multiInstance`) | #### Modelence Cloud | Variable | Type | Default | Consumed by | | ---------------------------- | ------- | ----------------------------- | ------------------------------------------------------------------------------------- | | `MODELENCE_SERVICE_ENDPOINT` | string | `https://cloud.modelence.com` | `packages/modelence/app` (cloud API endpoint) | | `MODELENCE_SERVICE_TOKEN` | string | — | `packages/modelence/app/backendApi.ts` (cloud auth token, written by `setup --token`) | | `MODELENCE_CONTAINER_ID` | string | — | `packages/modelence/app/backendApi.ts` (assigned per running container) | | `MODELENCE_ENVIRONMENT_ID` | string | — | `packages/modelence/app` (cloud environment binding) | | `MODELENCE_TRACKING_ENABLED` | boolean | `true` | `packages/modelence/app` (set to `false` to opt out of tracking) | #### Authentication (OAuth providers) | Variable | Type | Default | Consumed by | | ------------------------------------- | ------------------------ | ---------------------- | --------------------------------------------- | | `MODELENCE_AUTH_GOOGLE_ENABLED` | boolean | `false` | `packages/modelence/auth/providers/google.ts` | | `MODELENCE_AUTH_GOOGLE_CLIENT_ID` | string | — | `packages/modelence/auth/providers/google.ts` | | `MODELENCE_AUTH_GOOGLE_CLIENT_SECRET` | string | — | `packages/modelence/auth/providers/google.ts` | | `MODELENCE_AUTH_GITHUB_ENABLED` | boolean | `false` | `packages/modelence/auth/providers/github.ts` | | `MODELENCE_AUTH_GITHUB_CLIENT_ID` | string | — | `packages/modelence/auth/providers/github.ts` | | `MODELENCE_AUTH_GITHUB_CLIENT_SECRET` | string | — | `packages/modelence/auth/providers/github.ts` | | `MODELENCE_AUTH_GITHUB_CLIENT_SCOPES` | string (comma-separated) | `read:user,user:email` | `packages/modelence/auth/providers/github.ts` | #### Email providers | Variable | Type | Default | Consumed by | | ------------------------------------------- | ------ | ------- | -------------------- | | `MODELENCE_EMAIL_RESEND_API_KEY` | string | — | `@modelence/resend` | | `MODELENCE_EMAIL_AWS_SES_REGION` | string | — | `@modelence/aws-ses` | | `MODELENCE_EMAIL_AWS_SES_ACCESS_KEY_ID` | string | — | `@modelence/aws-ses` | | `MODELENCE_EMAIL_AWS_SES_SECRET_ACCESS_KEY` | string | — | `@modelence/aws-ses` | | `MODELENCE_EMAIL_SMTP_HOST` | string | — | `@modelence/smtp` | | `MODELENCE_EMAIL_SMTP_PORT` | number | — | `@modelence/smtp` | | `MODELENCE_EMAIL_SMTP_USER` | string | — | `@modelence/smtp` | | `MODELENCE_EMAIL_SMTP_PASS` | string | — | `@modelence/smtp` | Any variable not listed here is application-specific. Define it through your modules' `configSchema` so Modelence Cloud can manage it and `getConfig()` can read it type-safely. ## Modelence Cloud Configuration When connected to Modelence Cloud, you can manage configuration through the cloud dashboard at [cloud.modelence.com](https://cloud.modelence.com): 1. Navigate to your application 2. Select your environment 3. Open the **Application** tab 4. Configure settings like: * Email providers * Environment variables * Database connections * Custom configuration Changes made in the cloud dashboard are automatically synced to your application when it starts. ### Connecting to Modelence Cloud ```bash theme={null} npx modelence@latest setup --token ``` This command creates a `.modelence.env` file with your cloud connection token. See the [Setup documentation](/setup) for detailed instructions on connecting to Modelence Cloud. ## Next Steps Configure authentication and user management Set up email providers for transactional emails Define user roles and permissions Enable real-time communication # Migrations Source: https://docs.modelence.com/core-concepts/migrations Migrations let you run one-time tasks safely on application startup — such as evolving database schemas, backfilling data, or initializing external services like Stripe plans. ## Defining Migrations Pass a `migrations` array to `startApp()`. Each migration has: * `version` - Unique numeric version * `description` - Human-readable summary * `handler` - Async function that performs the task Define each migration handler in its own file under a `migrations/` directory, then wire up versions and descriptions in the index file: ```typescript title="src/server/migrations/backfill-todo-status.ts" theme={null} import { dbTodos } from '../todo/db'; export async function backfillTodoStatus() { await dbTodos.updateMany( { status: { $exists: false } }, { $set: { status: 'open' } } ); return 'Backfilled todos without status'; } ``` ```typescript title="src/server/migrations/index.ts" theme={null} import { backfillTodoStatus } from './backfill-todo-status'; export const migrations = [ { version: 1, description: 'Backfill status field on existing todos', handler: backfillTodoStatus, }, ]; ``` ```typescript title="src/server/app.ts" theme={null} import { startApp } from 'modelence/server'; import todoModule from './todo'; import { migrations } from './migrations'; startApp({ modules: [todoModule], migrations, }); ``` ## How Migrations Run On application startup, Modelence will: 1. Acquire a distributed `migrations` lock. If another instance already owns it, this instance skips running migrations. 2. Read existing migration versions from the `_modelenceMigrations` collection. 3. Run only pending migration versions from your `migrations` array. 4. Write a record to `_modelenceMigrations` with: * `version` * `status` (`completed` or `failed`) * `description` * `output` (handler result or error message) * `appliedAt` 5. Release the lock. Migrations run in the order they appear in your `migrations` array, so keep that array intentionally ordered and use unique versions. Store indexes run before migrations with this startup behavior: * Stores using `indexCreationMode: 'blocking'` are awaited before migrations begin. Use this for small collections with critical index dependencies (e.g. unique indexes that a migration relies on). * Stores using `indexCreationMode: 'background'` may still be creating indexes while migrations run. Prefer this for large collections to avoid blocking app startup. See [Indexes: Index Creation Mode](/indexes#index-creation-mode) for configuration details. ## Migrations and Cron Jobs Migration execution is scheduled asynchronously at startup, and cron jobs are started right after. This means migration handlers and cron handlers can run in parallel, so design both to be safe under race conditions. Recommended approach: * Make migration handlers idempotent (safe to run once or be retried manually). * Use conditional updates (for example, update only documents missing the new field). * Keep cron handlers compatible with both pre-migration and post-migration data during rollout windows. * If a cron job strictly depends on a migration, add an explicit readiness guard in the cron handler. Example of a race-safe migration pattern: ```typescript theme={null} await dbTodos.updateMany( { status: { $exists: false } }, { $set: { status: 'open' } } ); ``` ## Failure Behavior Failed migrations are recorded with `status: 'failed'`. Since version tracking is version-based, a failed version is still considered already seen on future starts — it will **not** be retried automatically on the next boot. If you need to rerun logic, prefer creating a new migration version. Edit a previous version's handler only if the migration has never run successfully in any environment. ### No Built-in Rollback Modelence migrations are forward-only. There is no `down` handler, no auto-revert on failure, and no CLI command to roll back. Failed handlers do **not** un-do partial writes — design each handler to be idempotent so a rerun (after manual cleanup) converges on the desired state. Practical guidance: * Use conditional updates (e.g. `{ field: { $exists: false } }`) so partial progress is safe to resume. * Avoid destructive operations (drops, deletes) inside the same migration that performs the new write. Split them into separate versions and only run the destructive step after verifying the prior version succeeded everywhere. * Wrap multi-document changes in your own checkpoint logic if you need to resume after a crash mid-handler — the runner itself records only the final outcome per version. ### Manual Cleanup of `_modelenceMigrations` To force a version to rerun, delete (or update) its document in the `_modelenceMigrations` collection before restarting the app. Each document has the shape: ```typescript theme={null} { version: number; // unique status: 'completed' | 'failed'; description?: string; output?: string; // handler return value or error message (max ~15MB) appliedAt: Date; } ``` To rerun a failed `version: 7` migration: ```javascript theme={null} // mongo shell or Compass db._modelenceMigrations.deleteOne({ version: 7 }); ``` On the next startup the runner sees no record for version 7 and re-executes the handler. Do this only when you are sure the prior partial run is safe to re-apply, or you have manually undone its effects first. ### CLI Surface Migrations are run **only at application startup**. There is currently no `modelence migrate` CLI command, no dry-run mode, and no way to invoke a single migration handler out-of-band. To run or re-run migrations you must (re)start the app — typically by deploying a new version that includes the new entries in your `migrations` array. # Modules Source: https://docs.modelence.com/core-concepts/modules Organize your backend into self-contained units with queries, mutations, stores, and configuration Modules are the fundamental building blocks of a Modelence application. They help you organize your backend functionality into cohesive, self-contained units that encapsulate queries, mutations, stores, and configuration. ## What is a Module? A Module in Modelence is similar to a feature module in other frameworks. It groups related functionality together, making your codebase more maintainable and easier to reason about. ```typescript theme={null} import { Module } from 'modelence/server'; export default new Module('todo', { // Module configuration goes here }); ``` ## Module Structure A typical module includes: * **Stores** - MongoDB collection definitions * **Queries** - Read operations that fetch data * **Mutations** - Write operations that modify data * **Configuration** - Module-specific settings * **Cron Jobs** - Scheduled tasks (optional) Data migrations are configured at the `startApp()` level (not inside individual modules). See the [Migrations documentation](/core-concepts/migrations). ## Stores Stores define your MongoDB collections with schemas, indexes, and custom methods. Including stores in your module ensures they're automatically provisioned when the server starts. ```typescript theme={null} import { Store, schema } from 'modelence/server'; export const dbTodos = new Store('todos', { schema: { title: schema.string(), isCompleted: schema.boolean(), userId: schema.userId(), createdAt: schema.date() }, indexes: [ { key: { userId: 1 } } ] }); export default new Module('todo', { // Register the store with the module stores: [dbTodos], queries: { async getAll({}, { user }) { return await dbTodos.fetch({ userId: user.id }); } } }); ``` Learn more about working with Stores in the [Stores documentation](/stores). ## Authentication & Authorization You can restrict access to queries and mutations using authentication requirements: ```typescript theme={null} export default new Module('todo', { queries: { getAll: { // Require authentication for this query auth: true, async handler({}, { user }) { // user is guaranteed to exist here return await dbTodos.fetch({ userId: user.id }); } }, getPublic: { // No authentication required auth: false, async handler() { return await dbTodos.fetch({ isPublic: true }); } } }, mutations: { adminDelete: { // Custom authorization check auth: true, authorize: ({ user }) => { if (!user.roles?.includes('admin')) { throw new Error('Admin access required'); } }, async handler({ id }) { return await dbTodos.deleteOne({ _id: new ObjectId(id) }); } } } }); ``` ## Queries Queries are read operations that fetch data without modifying state. For full query patterns, including client usage with `callMethod`, `modelenceQuery`, and typed client modules, see [Queries](/core-concepts/queries). ## Mutations Mutations are write operations that create, update, or delete data. For full mutation patterns, including client usage with `callMethod`, `modelenceMutation`, and typed client modules, see [Mutations](/core-concepts/mutations). ## Rate Limiting Protect your queries and mutations from abuse by declaring rate limit rules on the module and consuming them inside handlers: ```typescript theme={null} import { Module, consumeRateLimit } from 'modelence/server'; import { time } from 'modelence/server'; export default new Module('todo', { rateLimits: [ { bucket: 'todoCreate', type: 'ip', window: time.minutes(1), limit: 10 }, ], mutations: { async create({ title }, { user, connectionInfo }) { await consumeRateLimit({ bucket: 'todoCreate', type: 'ip', value: connectionInfo.ip, message: 'Too many todos created. Please slow down.', }); const { insertedId } = await dbTodos.insertOne({ title, userId: user.id, isCompleted: false, createdAt: new Date() }); return insertedId; } } }); ``` Learn more about rate limiting in the [Custom Rate Limiting documentation](/rate-limiting). ## Best Practices ### 1. Keep Modules Focused Each module should represent a single domain or feature: ```typescript theme={null} // Good: Focused todo module export default new Module('todo', { // Only todo-related functionality }); // Good: Separate user module export default new Module('users', { // Only user-related functionality }); ``` ### 2. Use Clear Naming Name your queries and mutations descriptively: ```typescript theme={null} // Good queries: { getAll() { }, getByStatus({ status }) { }, getOverdue() { } } // Avoid queries: { get() { }, // Too generic fetchData() { }, // Unclear what data q1() { } // Meaningless name } ``` ### 3. Handle Errors Gracefully Always handle potential errors and provide meaningful messages: ```typescript theme={null} mutations: { async delete({ id }, { user }) { const todo = await dbTodos.findById(id); if (!todo) { throw new Error('Todo not found'); } if (todo.userId !== user.id) { throw new Error('Not authorized to delete this todo'); } return await dbTodos.deleteOne({ _id: new ObjectId(id) }); } } ``` ### 4. Keep Business Logic in Modules Don't put business logic directly in your database stores. Keep it in your module methods: ```typescript theme={null} // Good: Business logic in module export default new Module('todo', { mutations: { async complete({ id }, { user }) { const todo = await dbTodos.findById(id); // Business logic if (todo.isCompleted) { throw new Error('Todo is already completed'); } await dbTodos.updateOne(id, { $set: { isCompleted: true, completedAt: new Date() } }); // Trigger side effects await callMethod('notifications.send', { userId: user.id, message: 'Todo completed!' }); } } }); ``` ### 5. Use TypeScript Types Leverage TypeScript for type safety across your modules: ```typescript theme={null} import { schema } from 'modelence/server'; type TodoPriority = 'low' | 'medium' | 'high'; export default new Module('todo', { mutations: { create: { input: { title: schema.string(), priority: schema.enum(['low', 'medium', 'high']) }, async handler(input, { user }) { // input is fully typed const { insertedId } = await dbTodos.insertOne({ ...input, userId: user.id, createdAt: new Date() }); return insertedId; } } } }); ``` ## Next Steps Learn how to define and call query methods Learn how to define and call mutation methods Learn how migration scripts run and how to handle cron race conditions Learn about configuration options Deep dive into working with MongoDB stores # Mutations Source: https://docs.modelence.com/core-concepts/mutations Define mutation methods and call them from the client with callMethod, modelenceMutation, or createClientModule. Typed client modules are available since modelence@0.15.0. Mutations are write operations that create, update, or delete data. They are similar to `POST`, `PUT`, and `DELETE` endpoints in REST. ## Version Requirements Typed client modules for mutations require: * `createClientModule(...).mutation()` - available since `modelence@0.15.0` ## Defining Mutations Define mutations inside a module's `mutations` object: ```typescript theme={null} import { Module, ObjectId } from 'modelence/server'; import { dbTodos } from './db'; export default new Module('todo', { mutations: { // Create a new todo async create({ title, dueDate }, { user }) { const { insertedId } = await dbTodos.insertOne({ title, dueDate, userId: user.id, isCompleted: false, createdAt: new Date(), }); return insertedId; }, // Update a todo async update({ id, title, isCompleted }) { return await dbTodos.updateOne( id, { $set: { title, isCompleted } } ); }, // Delete a todo async delete({ id }) { return await dbTodos.deleteOne({ _id: new ObjectId(id) }); }, }, }); ``` ## Calling Mutations from the Client ### `callMethod` ```typescript theme={null} import { callMethod } from 'modelence/client'; const todoId = await callMethod('todo.create', { title: 'Buy groceries', dueDate: new Date('2024-12-31'), }); ``` ### `modelenceMutation` (TanStack Query) ```typescript theme={null} import { useMutation, useQueryClient } from '@tanstack/react-query'; import { modelenceMutation } from 'modelence/client'; function CreateTodo() { const queryClient = useQueryClient(); const { mutate: createTodo } = useMutation({ ...modelenceMutation('todo.create'), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['todo.getAll'] }); }, }); const handleSubmit = () => { createTodo({ title: 'New todo', dueDate: new Date() }); }; return ; } ``` ### `createClientModule(...).mutation()` (typed client modules) `createClientModule(...).mutation()` is available since `modelence@0.15.0`. ```typescript title="src/server/admin/index.ts" theme={null} import { Module } from 'modelence/server'; export default new Module('admin', { mutations: { async inviteUser({ email }: { email: string }) { // returns { success: boolean } }, }, }); ``` ```typescript title="src/client/admin.ts" theme={null} import type adminModule from '../server/admin'; import { createClientModule } from 'modelence/client'; export const admin = createClientModule('admin'); ``` ```typescript title="src/components/AdminPanel.tsx" theme={null} import { useMutation } from '@tanstack/react-query'; import { admin } from '../client/admin'; function AdminPanel() { const { mutate: invite } = useMutation(admin.mutation('inviteUser')); return ; } ``` ## Related * [Queries](/core-concepts/queries) * [Modules](/core-concepts/modules) # Project Structure Source: https://docs.modelence.com/core-concepts/project-structure A Modelence project follows a well-organized structure that clearly separates client and server code, making it easy to build full-stack applications with TypeScript. ## Directory Overview When you create a new Modelence project, you'll see the following structure: ``` my-app/ ├── src/ │ ├── client/ # Frontend code │ ├── server/ # Backend code │ └── shared/ # (Optional) Shared code ├── assets/ # Static assets (images, fonts) ├── .modelence.env # Generated by `npx modelence setup` (cloud connection) ├── package.json # Project dependencies └── tsconfig.json # TypeScript configuration ``` ## Client Directory The `src/client` directory contains all your frontend React application code. ### Key Files * **`index.html`** - The main HTML template for your application. You typically don't need to modify this file unless you want to add meta tags, external scripts, or customize the root template. * **`index.tsx`** - The React application entry point. This is where you initialize your client-side app using `renderApp()` and configure providers. ```typescript theme={null} import { renderApp } from 'modelence/client'; import routes from './routes'; import './index.css'; renderApp({ routes, }); ``` * **`index.css`** - Global CSS styles for your application. This file typically includes Tailwind CSS imports and any global style customizations. * **`routes.ts`** - Client-side routing configuration that maps URL paths to React components. ```typescript theme={null} import { createBrowserRouter } from 'react-router-dom'; import Home from './pages/Home'; import About from './pages/About'; export default createBrowserRouter([ { path: '/', element: }, { path: '/about', element: }, ]); ``` ### Organizing Client Code Within the `client` directory, you can organize your code into subdirectories: ``` src/client/ ├── components/ # Reusable React components ├── pages/ # Page-level components ├── hooks/ # Custom React hooks └── utils/ # Client-side utilities ``` ## Server Directory The `src/server` directory contains all your backend code, including API logic, database models, and business logic. ### Key Files * **`app.ts`** - The server entry point where you configure and start your Modelence application. ```typescript theme={null} import { startApp } from 'modelence/server'; import todoModule from './todo'; startApp({ modules: [todoModule], }); ``` ### Organizing Server Code by Modules The recommended approach is to organize server code into **modules** - self-contained units of functionality: ``` src/server/ ├── migrations/ # (Optional) App migration scripts │ ├── index.ts # Exports the ordered migrations array │ └── ... # One file per migration handler ├── todo/ │ ├── index.ts # Module definition │ ├── db.ts # Database stores │ └── utils.ts # Module utilities ├── users/ │ ├── index.ts │ └── db.ts └── app.ts # Main server file ``` Each module typically contains: * **Module definition** - Queries, mutations, and configuration * **Database stores** - MongoDB collection definitions * **Business logic** - Domain-specific utilities and helpers For data evolution over time, keep app-level migration scripts under `src/server/migrations/` — one file per handler, with `index.ts` exporting the ordered array passed to `startApp({ migrations })`. See [Migrations](/core-concepts/migrations) for the full layout. Grouping code by modules (domains/features) rather than by type (controllers, models, etc.) makes your codebase more maintainable and easier to understand as it grows. ## Shared Code You can create a `src/shared` directory (or any other name) for code that needs to be used by both client and server: ``` src/ ├── client/ ├── server/ └── shared/ ├── types.ts # Shared TypeScript types ├── constants.ts # Shared constants └── utils.ts # Shared utilities ``` Be careful when importing server code into client code or vice versa. ## Configuration Files ### .modelence.env Environment-specific configuration for your application. This file should never be committed to version control. ```env theme={null} # MongoDB connection MONGODB_URI="mongodb+srv://..." # Other configuration PORT=3000 ``` Always add `.modelence.env` to your `.gitignore` file to prevent committing sensitive credentials. ### package.json Standard Node.js package configuration. Modelence projects include these key scripts: ```json theme={null} { "scripts": { "dev": "modelence dev", "build": "modelence build", "start": "node dist/server/app.js" } } ``` ### tsconfig.json TypeScript configuration for your project. Modelence sets up appropriate defaults for both client and server code with path aliases and module resolution. ## Build Output When you build your application with `npm run build`, Modelence generates a `dist` directory: ``` dist/ ├── client/ # Built frontend assets │ ├── index.html │ ├── assets/ │ └── ... └── server/ # Compiled server code └── app.js ``` The built application is ready for deployment to any Node.js hosting platform. ## Next Steps Learn how to organize your application logic into modules Understand how to configure your Modelence application # Queries Source: https://docs.modelence.com/core-concepts/queries Define query methods and call them from the client with callMethod, modelenceQuery, or createClientModule. Typed client modules are available since modelence@0.15.0. Queries are read operations that retrieve data without modifying state. They are similar to `GET` endpoints in REST. ## Version Requirements Typed client modules for queries require: * `createClientModule(...).query()` - available since `modelence@0.15.0` ## Defining Queries Define queries inside a module's `queries` object: ```typescript theme={null} import { Module } from 'modelence/server'; import { dbTodos } from './db'; export default new Module('todo', { queries: { // Get a single todo by ID async getOne({ id }) { return await dbTodos.findById(id); }, // Get all todos for the current user async getAll({}, { user }) { return await dbTodos.fetch({ userId: user.id }); }, // Get todos with filtering async getCompleted({}, { user }) { return await dbTodos.fetch({ userId: user.id, isCompleted: true, }); }, }, }); ``` ## Query Parameters Queries receive two arguments: 1. **Input parameters** - data passed from the client. 2. **Context** - server-side context including: * `user` - current authenticated user (if logged in) * `req` - Express request object * `res` - Express response object ## Calling Queries from the Client ### `callMethod` ```typescript theme={null} import { callMethod } from 'modelence/client'; const todos = await callMethod('todo.getAll'); const todo = await callMethod('todo.getOne', { id: '123' }); ``` ### `modelenceQuery` (TanStack Query) ```typescript theme={null} import { useQuery } from '@tanstack/react-query'; import { modelenceQuery } from 'modelence/client'; function TodoList() { const { data: todos } = useQuery(modelenceQuery('todo.getAll')); return
{/* render todos */}
; } ``` Since `modelence@0.15.0`, the query helpers (`modelenceQuery`, `modelenceLiveQuery`, `modelenceMutation`, `createQueryKey`) are available directly from `modelence/client` — this is the recommended import. The `@modelence/react-query` package still exports the same helpers and continues to work, but new code should import from `modelence/client`. See [Migrating from @modelence/react-query](/live-queries#migrating-from-modelence-react-query). ### `createClientModule(...).query()` (typed client modules) `createClientModule(...).query()` is available since `modelence@0.15.0`. ```typescript title="src/server/admin/index.ts" theme={null} import { Module } from 'modelence/server'; export default new Module('admin', { queries: { async getUsers({ page }: { page: number }) { // returns User[] }, }, }); ``` ```typescript title="src/client/admin.ts" theme={null} import type adminModule from '../server/admin'; import { createClientModule } from 'modelence/client'; export const admin = createClientModule('admin'); ``` ```typescript title="src/components/AdminPanel.tsx" theme={null} import { useQuery } from '@tanstack/react-query'; import { admin } from '../client/admin'; function AdminPanel() { const { data: users } = useQuery(admin.query('getUsers', { page: 1 })); return
{/* render users */}
; } ``` ## Related * [Mutations](/core-concepts/mutations) * [Modules](/core-concepts/modules) # MongoDB Data API Source: https://docs.modelence.com/data-api REST API for MongoDB operations with Modelence **Quick Start Tutorial**: [Migrate your MongoDB Data API in 30 minutes](https://medium.com/modelence/migrate-your-mongodb-data-api-in-30-minutes-c1d8d5959728) - A step-by-step guide to get started with Modelence Data API. ## What is MongoDB Data API An open-source API to read, write, and aggregate data in MongoDB. The application can be deployed to Modelence Cloud or to any other cloud provider. * **CRUD Operations**: Insert, find, update, and delete documents * **Advanced Querying**: Aggregation pipelines and complex queries * **Database Management**: Collection and index management * **Authentication**: API key-based security * **MongoDB Operations**: Direct access to MongoDB features ## Project Setup ### 1. Create a new application ```bash theme={null} npx create-modelence-app@latest data-api --template data-api ``` ### 2. Connect to Modelence Cloud 1. Open [cloud.modelence.com](https://cloud.modelence.com/) create 2. Create a new application and a local environment 3. Click on Setting → Set up 4. Follow the steps described in the modal ### 3. Start the Development Server ```bash theme={null} npm run dev ``` Your Data API will be available at `http://localhost:3000` ### 4. Deploy to Modelence Cloud To deploy your Data API to cloud: 1. **Create a Cloud Environment**: In your Modelence Cloud dashboard, navigate to your application and create a new environment, selecting **cloud** as the environment type. 2. **Get the Deployment Command**: Go to your cloud environment's settings page and copy the deployment command: ```bash theme={null} npx modelence@latest deploy --app --env ``` 3. **Deploy**: Run the deployment command in your project directory. The deployment process will: * Build your application * Upload it to Modelence Cloud * Provision resources including MongoDB database and server infrastructure * Launch your application Once deployment completes, your environment status will become `active` and you'll receive a URL to access your deployed Data API. ## Core Components ### DB Access MongoDB is configured when you create an environment. During environment creation, you can choose to: * Create a new MongoDB database, or * Connect to an existing MongoDB instance ### Authentication The Data API supports two authentication methods: #### 1. Direct API Key Authentication Set the api key as the value of `dataApi.apiKey` in Modelence Cloud from the Application page. (Alternatively you can use the `DATA_API_KEY` environment variable). Use the `apiKey` header in your requests: ```bash theme={null} apiKey: your-secure-api-key-here ``` #### 2. Bearer Token Authentication Alternatively, you can use Bearer token authentication by first obtaining an access token from the login endpoint: **Login Endpoint**: `POST /auth/providers/api-key/login` **Request**: ```json theme={null} { "key": "your-api-key" } ``` **Response**: ```json theme={null} { "access_token": "eyJhbGc...", "refresh_token": "eyJhbGc...", "token_type": "Bearer", "expires_in": 1800 } ``` Then use the access token in the `Authorization` header: ```bash theme={null} Authorization: Bearer eyJhbGc... ``` Access tokens expire after 30 minutes. Use the refresh token to obtain a new access token without re-authenticating. ### Available Endpoints The API provides comprehensive MongoDB operations with full request/response specifications: ## API Operations Reference ### 1. Find One Document (`POST /data/v1/action/findOne`) **Purpose**: Retrieve a single document from a collection **Request Fields**: ```json theme={null} { "collection": "string", // Required: Collection name "database": "string", // Optional: Database name (uses default if not specified) "filter": {}, // Optional: Query filter object "projection": {} // Optional: Fields to include/exclude } ``` **Example Request**: ```json theme={null} { "collection": "users", "filter": { "email": "user@example.com" }, "projection": { "name": 1, "email": 1, "_id": 0 } } ``` **Response**: ```json theme={null} { "document": { "name": "John Doe", "email": "user@example.com" } } ``` ### 2. Find Multiple Documents (`POST /data/v1/action/find`) **Purpose**: Retrieve multiple documents from a collection **Request Fields**: ```json theme={null} { "collection": "string", // Required: Collection name "database": "string", // Optional: Database name "filter": {}, // Optional: Query filter object "projection": {}, // Optional: Fields to include/exclude "sort": {}, // Optional: Sort specification "limit": 0, // Optional: Maximum number of documents "skip": 0 // Optional: Number of documents to skip } ``` **Example Request**: ```json theme={null} { "collection": "products", "filter": { "category": "electronics", "price": { "$lt": 500 } }, "projection": { "name": 1, "price": 1, "category": 1 }, "sort": { "price": 1 }, "limit": 10, "skip": 0 } ``` **Response**: ```json theme={null} { "documents": [ { "name": "Wireless Mouse", "price": 29.99, "category": "electronics" }, { "name": "USB Cable", "price": 9.99, "category": "electronics" } ] } ``` ### 3. Insert One Document (`POST /data/v1/action/insertOne`) **Purpose**: Insert a single document into a collection **Request Fields**: ```json theme={null} { "collection": "string", // Required: Collection name "database": "string", // Optional: Database name "document": {} // Required: Document to insert } ``` **Example Request**: ```json theme={null} { "collection": "users", "document": { "name": "John Doe", "email": "john@example.com", "age": 30, "createdAt": "2024-01-01T00:00:00Z" } } ``` **Response**: ```json theme={null} { "insertedId": "507f1f77bcf86cd799439011" } ``` ### 4. Insert Multiple Documents (`POST /data/v1/action/insertMany`) **Purpose**: Insert multiple documents into a collection **Request Fields**: ```json theme={null} { "collection": "string", // Required: Collection name "database": "string", // Optional: Database name "documents": [] // Required: Array of documents to insert } ``` **Example Request**: ```json theme={null} { "collection": "orders", "documents": [ { "orderId": "ORD001", "customerId": "CUST123", "total": 99.99, "status": "pending" }, { "orderId": "ORD002", "customerId": "CUST456", "total": 149.99, "status": "completed" } ] } ``` **Response**: ```json theme={null} { "insertedIds": [ "507f1f77bcf86cd799439011", "507f1f77bcf86cd799439012" ] } ``` ### 5. Update One Document (`POST /data/v1/action/updateOne`) **Purpose**: Update a single document in a collection **Request Fields**: ```json theme={null} { "collection": "string", // Required: Collection name "database": "string", // Optional: Database name "filter": {}, // Required: Query filter to match document "update": {}, // Required: Update operations "upsert": false // Optional: Create document if not found } ``` **Example Request**: ```json theme={null} { "collection": "users", "filter": { "email": "john@example.com" }, "update": { "$set": { "lastLogin": "2024-01-15T10:30:00Z" }, "$inc": { "loginCount": 1 } }, "upsert": false } ``` **Response**: ```json theme={null} { "matchedCount": 1, "modifiedCount": 1 } ``` ### 6. Update Multiple Documents (`POST /data/v1/action/updateMany`) **Purpose**: Update multiple documents in a collection **Request Fields**: ```json theme={null} { "collection": "string", // Required: Collection name "database": "string", // Optional: Database name "filter": {}, // Required: Query filter to match documents "update": {}, // Required: Update operations "upsert": false // Optional: Create documents if not found } ``` **Example Request**: ```json theme={null} { "collection": "products", "filter": { "category": "electronics" }, "update": { "$mul": { "price": 0.9 } }, "upsert": false } ``` **Response**: ```json theme={null} { "matchedCount": 25, "modifiedCount": 25 } ``` ### 7. Replace One Document (`POST /data/v1/action/replaceOne`) **Purpose**: Replace an entire document in a collection **Request Fields**: ```json theme={null} { "collection": "string", // Required: Collection name "database": "string", // Optional: Database name "filter": {}, // Required: Query filter to match document "replacement": {}, // Required: New document to replace with "upsert": false // Optional: Create document if not found } ``` **Example Request**: ```json theme={null} { "collection": "users", "filter": { "_id": { "$oid": "507f1f77bcf86cd799439011" } }, "replacement": { "name": "Jane Smith", "email": "jane@example.com", "age": 25, "department": "Engineering" }, "upsert": false } ``` **Response**: ```json theme={null} { "matchedCount": 1, "modifiedCount": 1 } ``` ### 8. Delete One Document (`POST /data/v1/action/deleteOne`) **Purpose**: Delete a single document from a collection **Request Fields**: ```json theme={null} { "collection": "string", // Required: Collection name "database": "string", // Optional: Database name "filter": {} // Required: Query filter to match document } ``` **Example Request**: ```json theme={null} { "collection": "users", "filter": { "email": "inactive@example.com" } } ``` **Response**: ```json theme={null} { "deletedCount": 1 } ``` ### 9. Delete Multiple Documents (`POST /data/v1/action/deleteMany`) **Purpose**: Delete multiple documents from a collection **Request Fields**: ```json theme={null} { "collection": "string", // Required: Collection name "database": "string", // Optional: Database name "filter": {} // Required: Query filter to match documents } ``` **Example Request**: ```json theme={null} { "collection": "logs", "filter": { "timestamp": { "$lt": "2024-01-01T00:00:00Z" } } } ``` **Response**: ```json theme={null} { "deletedCount": 1523 } ``` ### 10. Aggregate (`POST /data/v1/action/aggregate`) **Purpose**: Perform aggregation operations on a collection **Request Fields**: ```json theme={null} { "collection": "string", // Required: Collection name "database": "string", // Optional: Database name "pipeline": [] // Required: Aggregation pipeline stages } ``` **Example Request**: ```json theme={null} { "collection": "orders", "pipeline": [ { "$match": { "status": "completed" } }, { "$group": { "_id": "$customerId", "totalSpent": { "$sum": "$total" }, "orderCount": { "$sum": 1 } } }, { "$sort": { "totalSpent": -1 } }, { "$limit": 10 } ] } ``` **Response**: ```json theme={null} { "documents": [ { "_id": "CUST123", "totalSpent": 1299.97, "orderCount": 13 }, { "_id": "CUST456", "totalSpent": 899.95, "orderCount": 6 } ] } ``` ### 11. Count Documents (`POST /data/v1/action/countDocuments`) **Purpose**: Count the number of documents matching a filter **Request Fields**: ```json theme={null} { "dataSource": "string", // Required: Data source identifier "collection": "string", // Required: Collection name "database": "string", // Required: Database name "filter": {} // Optional: Query filter object } ``` **Example Request**: ```json theme={null} { "dataSource": "main", "database": "mydb", "collection": "users", "filter": { "status": "active" } } ``` **Response**: ```json theme={null} { "count": 1523 } ``` ### 12. Estimated Document Count (`POST /data/v1/action/estimatedDocumentCount`) **Purpose**: Get an estimated count of all documents in a collection (faster but less accurate than countDocuments) **Request Fields**: ```json theme={null} { "dataSource": "string", // Required: Data source identifier "collection": "string", // Required: Collection name "database": "string" // Required: Database name } ``` **Example Request**: ```json theme={null} { "dataSource": "main", "database": "mydb", "collection": "users" } ``` **Response**: ```json theme={null} { "count": 15432 } ``` ### 13. Distinct (`POST /data/v1/action/distinct`) **Purpose**: Get distinct values for a specific field across documents **Request Fields**: ```json theme={null} { "dataSource": "string", // Required: Data source identifier "collection": "string", // Required: Collection name "database": "string", // Required: Database name "key": "string", // Required: Field name to get distinct values for "filter": {} // Optional: Query filter object } ``` **Example Request**: ```json theme={null} { "dataSource": "main", "database": "mydb", "collection": "orders", "key": "status", "filter": { "year": 2024 } } ``` **Response**: ```json theme={null} { "values": ["pending", "completed", "cancelled", "refunded"] } ``` ### 14. Find One and Update (`POST /data/v1/action/findOneAndUpdate`) **Purpose**: Find a single document and update it atomically, returning either the original or updated document **Request Fields**: ```json theme={null} { "dataSource": "string", // Required: Data source identifier "collection": "string", // Required: Collection name "database": "string", // Required: Database name "filter": {}, // Required: Query filter to match document "update": {}, // Required: Update operations (must contain update operators) "projection": {}, // Optional: Fields to include/exclude in returned document "sort": {}, // Optional: Sort specification if multiple documents match "upsert": false, // Optional: Create document if not found "returnNewDocument": true // Optional: Return updated document (true) or original (false) } ``` **Example Request**: ```json theme={null} { "dataSource": "main", "database": "mydb", "collection": "inventory", "filter": { "sku": "ABC123" }, "update": { "$inc": { "quantity": -1 }, "$set": { "lastModified": "2024-01-15T10:30:00Z" } }, "returnNewDocument": true } ``` **Response**: ```json theme={null} { "document": { "_id": "507f1f77bcf86cd799439011", "sku": "ABC123", "quantity": 49, "lastModified": "2024-01-15T10:30:00Z" } } ``` ### 15. Find One and Replace (`POST /data/v1/action/findOneAndReplace`) **Purpose**: Find a single document and replace it entirely, returning either the original or replacement document **Request Fields**: ```json theme={null} { "dataSource": "string", // Required: Data source identifier "collection": "string", // Required: Collection name "database": "string", // Required: Database name "filter": {}, // Required: Query filter to match document "replacement": {}, // Required: New document (cannot contain update operators) "projection": {}, // Optional: Fields to include/exclude in returned document "sort": {}, // Optional: Sort specification if multiple documents match "upsert": false, // Optional: Create document if not found "returnNewDocument": true // Optional: Return replacement document (true) or original (false) } ``` **Example Request**: ```json theme={null} { "dataSource": "main", "database": "mydb", "collection": "profiles", "filter": { "userId": "user123" }, "replacement": { "userId": "user123", "name": "Jane Doe", "email": "jane.doe@example.com", "preferences": { "theme": "dark", "notifications": true } }, "returnNewDocument": true } ``` **Response**: ```json theme={null} { "document": { "_id": "507f1f77bcf86cd799439011", "userId": "user123", "name": "Jane Doe", "email": "jane.doe@example.com", "preferences": { "theme": "dark", "notifications": true } } } ``` ### 16. Find One and Delete (`POST /data/v1/action/findOneAndDelete`) **Purpose**: Find a single document and delete it atomically, returning the deleted document **Request Fields**: ```json theme={null} { "dataSource": "string", // Required: Data source identifier "collection": "string", // Required: Collection name "database": "string", // Required: Database name "filter": {}, // Required: Query filter to match document "projection": {}, // Optional: Fields to include/exclude in returned document "sort": {} // Optional: Sort specification if multiple documents match } ``` **Example Request**: ```json theme={null} { "dataSource": "main", "database": "mydb", "collection": "sessions", "filter": { "sessionId": "sess_abc123" }, "projection": { "userId": 1, "expiredAt": 1 } } ``` **Response**: ```json theme={null} { "document": { "_id": "507f1f77bcf86cd799439011", "userId": "user456", "expiredAt": "2024-01-15T10:30:00Z" } } ``` ### 17. Bulk Write (`POST /data/v1/action/bulkWrite`) **Purpose**: Perform multiple write operations (insert, update, replace, delete) in a single request **Request Fields**: ```json theme={null} { "dataSource": "string", // Required: Data source identifier "collection": "string", // Required: Collection name "database": "string", // Required: Database name "operations": [], // Required: Array of write operations "ordered": true // Optional: Execute operations in order (default true) } ``` **Operation Types**: * `insertOne`: `{ "insertOne": { "document": {...} } }` * `updateOne`: `{ "updateOne": { "filter": {...}, "update": {...}, "upsert": false } }` * `updateMany`: `{ "updateMany": { "filter": {...}, "update": {...}, "upsert": false } }` * `replaceOne`: `{ "replaceOne": { "filter": {...}, "replacement": {...}, "upsert": false } }` * `deleteOne`: `{ "deleteOne": { "filter": {...} } }` * `deleteMany`: `{ "deleteMany": { "filter": {...} } }` **Example Request**: ```json theme={null} { "dataSource": "main", "database": "mydb", "collection": "products", "operations": [ { "insertOne": { "document": { "name": "New Product", "price": 99.99 } } }, { "updateMany": { "filter": { "category": "electronics" }, "update": { "$mul": { "price": 0.9 } } } }, { "deleteOne": { "filter": { "discontinued": true } } } ], "ordered": true } ``` **Response**: ```json theme={null} { "insertedCount": 1, "matchedCount": 15, "modifiedCount": 15, "deletedCount": 1, "upsertedCount": 0, "upsertedIds": {} } ``` ### 18. Create Index (`POST /data/v1/action/createIndex`) **Purpose**: Create an index on a collection to improve query performance **Request Fields**: ```json theme={null} { "dataSource": "string", // Required: Data source identifier "collection": "string", // Required: Collection name "database": "string", // Required: Database name "keys": {}, // Required: Index specification (field: 1 or -1) "options": {} // Optional: Index options (name, unique, sparse, etc.) } ``` **Example Request**: ```json theme={null} { "dataSource": "main", "database": "mydb", "collection": "users", "keys": { "email": 1 }, "options": { "name": "email_index", "unique": true, "sparse": false } } ``` **Response**: ```json theme={null} { "createdCollectionAutomatically": false, "numIndexesBefore": 1, "numIndexesAfter": 2, "ok": 1 } ``` ### 19. Drop Index (`POST /data/v1/action/dropIndex`) **Purpose**: Remove an index from a collection **Request Fields**: ```json theme={null} { "dataSource": "string", // Required: Data source identifier "collection": "string", // Required: Collection name "database": "string", // Required: Database name "name": "string" // Required: Index name to drop } ``` **Example Request**: ```json theme={null} { "dataSource": "main", "database": "mydb", "collection": "users", "name": "email_index" } ``` **Response**: ```json theme={null} { "nIndexesWas": 2, "ok": 1 } ``` ### 20. List Indexes (`POST /data/v1/action/listIndexes`) **Purpose**: List all indexes on a collection **Request Fields**: ```json theme={null} { "dataSource": "string", // Required: Data source identifier "collection": "string", // Required: Collection name "database": "string" // Required: Database name } ``` **Example Request**: ```json theme={null} { "dataSource": "main", "database": "mydb", "collection": "users" } ``` **Response**: ```json theme={null} { "indexes": [ { "v": 2, "key": { "_id": 1 }, "name": "_id_" }, { "v": 2, "key": { "email": 1 }, "name": "email_index", "unique": true } ] } ``` ### 21. List Collections (`POST /data/v1/action/listCollections`) **Purpose**: List all collections in a database **Request Fields**: ```json theme={null} { "dataSource": "string", // Required: Data source identifier "database": "string" // Required: Database name } ``` **Example Request**: ```json theme={null} { "dataSource": "main", "database": "mydb" } ``` **Response**: ```json theme={null} { "collections": [ { "name": "users", "type": "collection" }, { "name": "products", "type": "collection" }, { "name": "orders", "type": "collection" } ] } ``` ### 22. Create Collection (`POST /data/v1/action/createCollection`) **Purpose**: Create a new collection in a database **Request Fields**: ```json theme={null} { "dataSource": "string", // Required: Data source identifier "database": "string", // Required: Database name "collection": "string" // Required: Collection name to create } ``` **Example Request**: ```json theme={null} { "dataSource": "main", "database": "mydb", "collection": "analytics" } ``` **Response**: ```json theme={null} { "ok": 1 } ``` ### 23. Drop Collection (`POST /data/v1/action/dropCollection`) **Purpose**: Delete a collection and all its documents **Request Fields**: ```json theme={null} { "dataSource": "string", // Required: Data source identifier "database": "string", // Required: Database name "collection": "string" // Required: Collection name to drop } ``` **Example Request**: ```json theme={null} { "dataSource": "main", "database": "mydb", "collection": "temp_data" } ``` **Response**: ```json theme={null} { "ok": 1 } ``` ### 24. List Databases (`POST /data/v1/action/listDatabases`) **Purpose**: List all available databases **Request Fields**: ```json theme={null} { "dataSource": "string" // Required: Data source identifier } ``` **Example Request**: ```json theme={null} { "dataSource": "main" } ``` **Response**: ```json theme={null} { "databases": [ { "name": "admin", "sizeOnDisk": 32768, "empty": false }, { "name": "mydb", "sizeOnDisk": 8192000, "empty": false }, { "name": "test", "sizeOnDisk": 32768, "empty": true } ], "totalSize": 8256736, "ok": 1 } ``` ### 25. Run Command (`POST /data/v1/action/runCommand`) **Purpose**: Execute arbitrary database commands **Request Fields**: ```json theme={null} { "dataSource": "string", // Required: Data source identifier "database": "string", // Required: Database name "command": {} // Required: Command object } ``` **Example Request**: ```json theme={null} { "dataSource": "main", "database": "mydb", "command": { "dbStats": 1, "scale": 1024 } } ``` **Response**: ```json theme={null} { "result": { "db": "mydb", "collections": 5, "views": 0, "objects": 1523, "avgObjSize": 512, "dataSize": 780288, "storageSize": 1024000, "ok": 1 } } ``` ## Quick cURL Examples ```bash theme={null} # Insert a document curl -X POST http://localhost:3000/data/v1/action/insertOne \ -H "Content-Type: application/json" \ -H "apiKey: your-api-key" \ -d '{"dataSource": "main", "database": "mydb", "collection": "users", "document": {"name": "John Doe"}}' # Find documents curl -X POST http://localhost:3000/data/v1/action/find \ -H "Content-Type: application/json" \ -H "apiKey: your-api-key" \ -d '{"dataSource": "main", "database": "mydb", "collection": "users", "filter": {"name": "John Doe"}}' # Update a document curl -X POST http://localhost:3000/data/v1/action/updateOne \ -H "Content-Type: application/json" \ -H "apiKey: your-api-key" \ -d '{"dataSource": "main", "database": "mydb", "collection": "users", "filter": {"name": "John Doe"}, "update": {"$set": {"active": true}}}' # Count documents curl -X POST http://localhost:3000/data/v1/action/countDocuments \ -H "Content-Type: application/json" \ -H "apiKey: your-api-key" \ -d '{"dataSource": "main", "database": "mydb", "collection": "users", "filter": {"status": "active"}}' # Aggregate data curl -X POST http://localhost:3000/data/v1/action/aggregate \ -H "Content-Type: application/json" \ -H "apiKey: your-api-key" \ -d '{"dataSource": "main", "database": "mydb", "collection": "orders", "pipeline": [{"$match": {"status": "completed"}}, {"$group": {"_id": "$customerId", "total": {"$sum": "$amount"}}}]}' ``` ## Security Considerations * **API Key Authentication**: All endpoints require a valid API key * **Input Validation**: Requests are validated before processing * **Error Handling**: Proper error responses without exposing sensitive information * **Rate Limiting**: Consider implementing rate limiting for production use ## Use Cases The Data API is ideal for: * **Admin Dashboards**: Building administrative interfaces for data management * **Data Integration**: Connecting external systems to your MongoDB database * **Rapid Prototyping**: Quickly testing database operations and queries * **Analytics Tools**: Building custom analytics and reporting tools * **Mobile Apps**: Providing backend API for mobile applications ## Complete Example Want to see the full working code? Check it out on GitHub: See the complete source code for this example on GitHub, including all endpoints and configuration. ## Next Steps * Explore the [Store API Reference](/api-reference/modelence/server/classes/Store) for advanced MongoDB operations * Learn about [Authentication](/authentication) for more secure authentication methods * Check out the [Modules Guide](/core-concepts/modules) to understand how to organize your application # Built-in Email Source: https://docs.modelence.com/email/index Send transactional emails out of the box with no provider setup Modelence sends transactional emails — verification, password reset, and any custom emails you trigger via `sendEmail` — through a built-in managed email provider. No provider setup, no API keys, no SMTP credentials. Apps connected to Modelence Cloud get email working immediately. If you outgrow the managed provider or need custom domains, attachments, or full deliverability control, you can swap in a [custom provider](/email/providers) (Resend, Amazon SES, or SMTP) at any time. ## Built-in Managed Email (Default) Built-in managed email requires **`modelence` v0.18.0 or newer**. Earlier versions still require you to configure a provider explicitly. Update with `npm install modelence@latest`. When your app is connected to Modelence Cloud, the managed email provider is enabled automatically. You don't need to install any package, configure credentials, or pass a `provider` to `startApp`. ### Minimum setup ```typescript theme={null} import { startApp } from 'modelence/server'; startApp({ // ... your other app configuration email: { verification: { subject: 'Verify your email', redirectUrl: 'https://yourdomain.com/email-verified', }, passwordReset: { subject: 'Reset your password', redirectUrl: 'https://yourdomain.com/password-reset-success', }, }, }); ``` That's it. Verification and password reset emails go out automatically. You can also call `sendEmail` for custom transactional messages (see [Sending Custom Emails](#sending-custom-emails)). ### How it works * Outbound mail is relayed through Modelence Cloud (`/api/email/send`), which sends via Resend on a Modelence-owned domain. * You can still pass `from: '"Your App" '` to set a friendly **name**; the address part is replaced by the managed sender. The `replyTo` field works normally so users can still reply to your support inbox. * Local development (no Modelence Cloud connection) falls back to the legacy "no provider configured" behavior so misconfigurations fail loudly during development. ### Limitations in v1 The managed provider focuses on the common transactional case. It does **not** support: * `cc` / `bcc` recipients * File attachments * Custom email headers * Custom sender domains If you call `sendEmail` with any of these, Modelence throws a clear error. Use a [custom provider](/email/providers) when you need them. ## Custom Email Templates You can customize the HTML for verification and password reset emails. Templates work the same whether you use the built-in provider or a custom one: ```typescript theme={null} startApp({ // ... your other app configuration email: { verification: { subject: 'Welcome! Please verify your email', template: ({ name, email, verificationUrl }) => `

Welcome ${name}!

Please click the link below to verify your email address:

Verify Email `, redirectUrl: 'https://yourdomain.com/email-verified', }, passwordReset: { subject: 'Reset Your Password', template: ({ name, email, resetUrl }) => `

Hello ${name}

Click the link below to reset your password:

Reset Password

If you didn't request this, please ignore this email.

`, redirectUrl: 'https://yourdomain.com/password-reset-success', }, }, }); ``` ## Sending Custom Emails Use `sendEmail` to send arbitrary transactional emails — order confirmations, invites, notifications, anything you trigger from your own code. It routes through whichever provider is active (managed or custom), so the call site stays the same. ### Basic example ```typescript theme={null} import { sendEmail } from 'modelence/server'; await sendEmail({ to: 'user@example.com', subject: 'Welcome to Acme', html: '

Welcome!

Thanks for signing up.

', }); ``` ### Calling `sendEmail` from a mutation A typical use case — sending a notification when a user completes an action: ```typescript theme={null} import { Module, sendEmail } from 'modelence/server'; import { z } from 'zod'; export default new Module('orders', { mutations: { async create(args, { user }) { const { items } = z.object({ items: z.array(z.string()) }).parse(args); const order = await dbOrders.insertOne({ userId: user.id, items, createdAt: new Date(), }); await sendEmail({ to: user.emails[0].address, subject: `Order #${order.insertedId} confirmed`, html: `

Thanks for your order!

We received your order with ${items.length} item(s).

`, }); return { orderId: order.insertedId }; }, }, }); ``` ### Plain-text and multipart emails Provide `text` for clients that don't render HTML, or both `html` and `text` for a multipart message: ```typescript theme={null} await sendEmail({ to: 'user@example.com', subject: 'Your weekly digest', text: 'You have 3 new notifications. Visit https://yourdomain.com to view.', html: '

You have 3 new notifications.

', }); ``` ### Sending to multiple recipients ```typescript theme={null} await sendEmail({ to: ['alice@example.com', 'bob@example.com'], replyTo: 'support@yourdomain.com', subject: 'Team update', html: '

Here is this week\'s update.

', }); ``` ### Email Payload Options ```typescript theme={null} { from?: string; // Sender address (managed provider uses the name only) to: string | string[]; // Recipient(s) subject: string; // Email subject html?: string; // HTML content text?: string; // Plain text content cc?: string | string[]; // CC recipients (custom provider only) bcc?: string | string[]; // BCC recipients (custom provider only) replyTo?: string | string[]; // Reply-to address(es) headers?: Record; // Custom headers (custom provider only) attachments?: EmailAttachment[]; // File attachments (custom provider only) } ``` You must provide either `html` or `text` (or both). Fields marked **custom provider only** are rejected by the built-in managed provider — see [Custom Email Providers](/email/providers) if you need them. ## Troubleshooting ### Error: "Modelence managed email does not support cc, bcc, attachments, or custom headers" The built-in managed provider does not support these fields in v1. Either remove them from your `sendEmail` call, or configure a [custom provider](/email/providers) (Resend, SES, or SMTP). ### Error: "Email provider is not configured" You're running locally without a Modelence Cloud connection and haven't set a `provider`. Either: * Connect your app to Modelence Cloud to use the managed provider, or * Configure a [custom provider](/email/providers). ## Next Steps * Use a [custom email provider](/email/providers) for attachments, custom domains, or specific vendor requirements * Learn about [Authentication](/authentication) to understand how email verification works * Explore [User Management](/authentication/user-management) features * Review the [API Reference](/api-reference) for more details on email functions # Custom Email Providers Source: https://docs.modelence.com/email/providers Use Resend, Amazon SES, or SMTP instead of the built-in managed email provider By default, Modelence sends transactional email through its [built-in managed provider](/email) — no setup required. Configure a custom provider only when you need: * A custom sender domain / full DKIM control * Attachments, `cc` / `bcc`, or custom email headers * A specific deliverability vendor (Resend, SES in your own AWS account, your own SMTP relay) Setting `email.provider` on `startApp` overrides the managed provider. If you omit `provider`, Modelence keeps using the managed email service. ## Supported Providers * **[Resend](/api-reference/@modelence/resend/index)** — modern email API service * **[Amazon SES](/api-reference/@modelence/aws-ses/index)** — AWS Simple Email Service * **[SMTP](/api-reference/@modelence/smtp/index)** — any SMTP-compatible email service ## 1. Install a provider package ```bash theme={null} # For Resend npm install @modelence/resend # For Amazon SES npm install @modelence/aws-ses # For SMTP npm install @modelence/smtp ``` ## 2. Configure credentials ### Option A: Cloud Configuration (Recommended) 1. Go to [cloud.modelence.com](https://cloud.modelence.com) 2. Choose your environment 3. Open the **Application** tab 4. Select the **Email** configuration section 5. Choose your provider and enter the required credentials: **For Resend:** * API Key (get it from [resend.com/api-keys](https://resend.com/api-keys)) **For Amazon SES:** * Region (e.g., `us-east-1`) * Access Key ID * Secret Access Key See [AWS SES documentation](https://docs.aws.amazon.com/ses/) for obtaining credentials. **For SMTP:** * Host (e.g., `smtp.gmail.com`) * Port (usually `465` for secure connections) * Username * Password The cloud configuration syncs to your app automatically. ### Option B: Local Environment Variables Useful for local development: **For Resend:** ```bash theme={null} MODELENCE_EMAIL_RESEND_API_KEY=your_resend_api_key ``` **For Amazon SES:** ```bash theme={null} MODELENCE_EMAIL_AWS_SES_REGION=us-east-1 MODELENCE_EMAIL_AWS_SES_ACCESS_KEY_ID=your_access_key_id MODELENCE_EMAIL_AWS_SES_SECRET_ACCESS_KEY=your_secret_access_key ``` **For SMTP:** ```bash theme={null} MODELENCE_EMAIL_SMTP_HOST=smtp.example.com MODELENCE_EMAIL_SMTP_PORT=465 MODELENCE_EMAIL_SMTP_USER=your_smtp_username MODELENCE_EMAIL_SMTP_PASS=your_smtp_password ``` Cloud configuration takes precedence over local environment variables. ## 3. Pass the provider to `startApp` ```typescript theme={null} import { startApp } from 'modelence/server'; import resendProvider from '@modelence/resend'; // or import awsSesProvider from '@modelence/aws-ses'; // or import smtpProvider from '@modelence/smtp'; startApp({ // ... your other app configuration email: { provider: resendProvider, from: 'noreply@yourdomain.com', verification: { subject: 'Verify your email', redirectUrl: 'https://yourdomain.com/email-verified', }, passwordReset: { subject: 'Reset your password', redirectUrl: 'https://yourdomain.com/password-reset-success', }, }, }); ``` With a custom provider, the full [email payload](/email#email-payload-options) is supported — including `cc`, `bcc`, custom headers, and attachments: ```typescript theme={null} await sendEmail({ from: 'noreply@yourdomain.com', to: 'user@example.com', subject: 'Invoice', html: '

Your Invoice

', attachments: [ { filename: 'invoice.pdf', content: pdfBuffer, contentType: 'application/pdf', }, ], }); ``` ## Troubleshooting ### SMTP connection issues * Verify your SMTP credentials are correct * Check that the port is correct (usually 465 for secure connections) * Ensure your firewall allows outbound connections on the SMTP port * Some email providers require you to enable "less secure app access" or create an app-specific password ### AWS SES sending limits If you're in the AWS SES sandbox: * You can only send emails to verified email addresses * Request production access to send to any email address * Verify your sending domain or individual email addresses in the AWS Console ### Error: "Email provider is not configured" You're running locally without a Modelence Cloud connection and haven't set `email.provider`. Either: * Connect your app to Modelence Cloud to use the [built-in managed provider](/email), or * Configure a provider via `startApp({ email: { provider, ... } })`. # Files Source: https://docs.modelence.com/files Upload and manage files with Modelence Cloud storage Modelence provides built-in file storage through Modelence Cloud. Files are organized by visibility — either `public` (accessible via a permanent URL) or `private` (accessible only via a time-limited signed URL). **File operations are server-only.** `getUploadUrl`, `getFileUrl`, `downloadFile`, and `deleteFile` are imported from `modelence/server` and can only be called from your server-side code (queries, mutations, cron jobs). They are **not** callable directly from the browser. This is deliberate. Each operation issues a signed URL or performs a delete against Modelence Cloud using your app's credentials, for whatever `filePath` it is given. The framework has no way to know which user owns which file, so exposing these to the client would let any caller act on any path. **You** decide who can touch which file by wrapping these calls in your own queries/mutations and enforcing ownership there — see [Exposing file operations to the client](#exposing-file-operations-to-the-client). ## Uploading a File `getUploadUrl` returns a presigned URL and form fields. POST these together as `FormData` to upload the file directly to storage: ```ts theme={null} import { getUploadUrl } from 'modelence/server'; import fs from 'fs/promises'; const { url, fields, filePath } = await getUploadUrl({ filePath: 'photo.png', contentType: 'image/png', visibility: 'public', }); const data = await fs.readFile('./photo.png'); const formData = new FormData(); for (const [key, value] of Object.entries(fields)) { formData.append(key, value); } formData.append('file', new Blob([data], { type: 'image/png' })); await fetch(url, { method: 'POST', body: formData }); console.log(filePath); // e.g. 'public/photo.png' ``` The `visibility` field controls access: * `"public"` — the file is accessible via a permanent URL * `"private"` — the file requires a signed URL to access ## Getting a File URL Returns a URL for displaying or linking to a file. For public files this is a permanent URL; for private files it is a time-limited presigned URL. ```ts theme={null} import { getFileUrl } from 'modelence/server'; const { url } = await getFileUrl('public/photo.png'); console.log(url); // Permanent public URL const { url: privateUrl } = await getFileUrl('private/report.pdf'); console.log(privateUrl); // Time-limited presigned URL ``` ## Downloading a File Returns a presigned download URL for a private file. ```ts theme={null} import { downloadFile } from 'modelence/server'; const { downloadUrl } = await downloadFile('private/report.pdf'); // Redirect the user to downloadUrl or fetch it server-side ``` ## Deleting a File ```ts theme={null} import { deleteFile } from 'modelence/server'; await deleteFile('public/photo.png'); await deleteFile('private/report.pdf'); ``` ## File Paths File paths always include the visibility prefix: `public/` or `private/`. The upload functions return the full `filePath` (including prefix) in their result, which you can store and pass to the other functions. ```ts theme={null} import { getUploadUrl } from 'modelence/server'; const { filePath } = await getUploadUrl({ filePath: 'avatars/user-123.png', contentType: 'image/png', visibility: 'private', }); // filePath === 'private/avatars/user-123.png' const { url } = await getFileUrl(filePath); ``` ## Exposing file operations to the client Because the file functions are server-only, the browser reaches them through **your own** queries and mutations. This is where you enforce authorization: never accept a raw client-supplied `filePath` and forward it blindly — derive the path from your own data and verify the current user is allowed to act on it. The pattern below stores file ownership in a Store and checks it on every operation. Uploading returns the presigned URL to the client, which performs the actual upload directly to storage. ```ts theme={null} import { Module, Store, schema, getUploadUrl, getFileUrl, deleteFile } from 'modelence/server'; import { ObjectId } from 'mongodb'; const dbDocuments = new Store('documents', { schema: { userId: schema.userId(), filePath: schema.string(), createdAt: schema.date(), }, }); export default new Module('documents', { stores: [dbDocuments], queries: { // Hand out a time-limited URL only for a document the caller owns. async getUrl({ documentId }, { user }) { if (!user) { throw new Error('Authentication required'); } const doc = await dbDocuments.requireOne({ _id: new ObjectId(documentId as string), userId: new ObjectId(user.id), }); return getFileUrl(doc.filePath); }, }, mutations: { // Issue an upload URL for a path scoped to the caller, then record ownership. async requestUpload({ contentType }, { user }) { if (!user) { throw new Error('Authentication required'); } const filePath = `private/users/${user.id}/${new ObjectId().toString()}`; const upload = await getUploadUrl({ filePath, contentType: contentType as string, visibility: 'private', }); await dbDocuments.insertOne({ userId: new ObjectId(user.id), filePath, createdAt: new Date(), }); return upload; // { url, fields, filePath } — the client POSTs the file to `url` }, // Only the owner can delete. async remove({ documentId }, { user }) { if (!user) { throw new Error('Authentication required'); } const doc = await dbDocuments.requireOne({ _id: new ObjectId(documentId as string), userId: new ObjectId(user.id), }); await deleteFile(doc.filePath); await dbDocuments.deleteOne({ _id: doc._id }); }, }, }); ``` The client then calls your guarded methods — e.g. `callMethod('documents.requestUpload', { contentType })` — instead of the file functions directly. Public assets that are safe for anyone to read can be served straight from their permanent `public/...` URL without a query. # Introduction Source: https://docs.modelence.com/index Modelence is a production-ready platform for building and deploying full-stack web applications. You can create a complete app - frontend, backend, database, and hosting - by describing what you want in plain English. Under the hood, Modelence generates structured, readable TypeScript + React + MongoDB code on an open-source framework, so you always have full access to your codebase. ## Get Started The fastest way to create an app is through the **App Builder**: 1. Go to [cloud.modelence.com](https://cloud.modelence.com) 2. Describe the app you want to build 3. Submit your prompt - the App Builder will generate and deploy your app That's it. No setup, no CLI, no configuration required. Create an app by describing what you want in plain English Set up a local project with the CLI for hands-on development Learn about the Modelence framework and project structure Full API reference for the Modelence framework # Indexes Source: https://docs.modelence.com/indexes Configure MongoDB and Atlas Search indexes for your stores Modelence lets you configure indexes directly on each `Store`. Use: * `indexes` for regular MongoDB indexes (performance and constraints) * `searchIndexes` for MongoDB Atlas Search * `indexCreationMode` to control startup behavior ## MongoDB Indexes Configure indexes to improve query performance: ```typescript theme={null} export const dbPosts = new Store('posts', { schema: { title: schema.string(), authorId: schema.userId(), publishedAt: schema.date(), status: schema.string(), }, indexes: [ // Single field index { key: { authorId: 1 } }, // Compound index { key: { status: 1, publishedAt: -1 } }, // Named index { key: { title: 'text' }, name: 'title_text_index' }, // Unique index { key: { slug: 1 }, unique: true } ] }); ``` Modelence automatically creates these indexes when the application starts. Starting from `modelence@0.12.0`, Modelence manages framework-created indexes using this strategy. Modelence manages framework-created indexes with a `_modelence_` name prefix. If you provide `name`, Modelence still prefixes it automatically. During startup reconciliation, Modelence will create missing managed indexes, drop outdated managed indexes, and recreate changed ones. Manual indexes that do not use the `_modelence_` prefix are preserved unless they conflict with code-defined index keys. ### Common Index Options `indexes` accepts MongoDB index options like `unique`, `sparse`, `expireAfterSeconds`, and `partialFilterExpression`: ```typescript theme={null} indexes: [ { key: { email: 1 }, unique: true }, { key: { deletedAt: 1 }, sparse: true }, { key: { expiresAt: 1 }, expireAfterSeconds: 0 }, // TTL { key: { status: 1 }, partialFilterExpression: { status: { $exists: true } } }, ] ``` ## Index Creation Mode By default, store indexes are created in the background during startup.\ Set `indexCreationMode: 'blocking'` for indexes that must be created before startup continues. ```typescript theme={null} export const locksCollection = new Store('_modelenceLocks', { schema: { resource: schema.string(), instanceId: schema.string(), acquiredAt: schema.date(), }, indexes: [ { key: { resource: 1 }, unique: true }, { key: { resource: 1, acquiredAt: 1 } }, ], indexCreationMode: 'blocking', }); ``` Startup ordering: 1. `blocking` indexes are awaited before migrations begin. 2. Migrations are then started. 3. `background` indexes may continue running in parallel with migrations. In multi-instance deployments, index creation is coordinated through a distributed `indexes` lock so only one instance performs reconciliation at a time. If index creation fails for a store, startup continues and a warning is logged. See [Migrations](/core-concepts/migrations) for startup and race-condition guidance with cron jobs. ## MongoDB Atlas Search Indexes For advanced full-text search capabilities using MongoDB Atlas Search, configure search indexes: ```typescript theme={null} export const dbArticles = new Store('articles', { schema: { title: schema.string(), content: schema.string(), tags: schema.array(schema.string()), category: schema.string(), authorId: schema.userId(), }, indexes: [ { key: { authorId: 1 } }, ], searchIndexes: [ { name: 'article_search', definition: { mappings: { dynamic: false, fields: { title: { type: 'string', analyzer: 'lucene.standard' }, content: { type: 'string', analyzer: 'lucene.standard' }, tags: { type: 'string', analyzer: 'lucene.keyword' }, category: { type: 'string', analyzer: 'lucene.keyword' } } } } } ] }); ``` ### Using Search Indexes Once configured, use the search indexes with MongoDB's aggregation pipeline: ```typescript theme={null} // Full-text search across title and content const results = await dbArticles.aggregate([ { $search: { index: 'article_search', text: { query: 'machine learning', path: ['title', 'content'] } } }, { $limit: 10 } ]).toArray(); // Search with filters const filteredResults = await dbArticles.aggregate([ { $search: { index: 'article_search', compound: { must: [ { text: { query: 'tutorial', path: 'title' } } ], filter: [ { text: { query: 'javascript', path: 'category' } } ] } } } ]).toArray(); ``` Search indexes require MongoDB Atlas. They are automatically created when your application starts, similar to regular indexes. ## Vector Search Indexes For Atlas Vector Search, you can define a vector index in `searchIndexes`: ```typescript theme={null} export const dbDocuments = new Store('documents', { schema: { title: schema.string(), embedding: schema.array(schema.number()), }, indexes: [], searchIndexes: [ Store.vectorIndex({ field: 'embedding', dimensions: 1536, similarity: 'cosine', }), ], }); ``` See [Voyage AI Tutorial](/voyage-ai) for an end-to-end vector search example. # Live Queries Source: https://docs.modelence.com/live-queries Real-time data synchronization with automatic updates using LiveData and TanStack Query. Available since modelence@0.15.1 and @modelence/react-query@1.2.1. Live Queries in Modelence provide real-time data synchronization between your server and client. When underlying data changes, connected clients automatically receive updated data without manual polling or refetching. ## Version Requirements Live Queries are available with the following minimum package versions: * `modelence >= 0.15.1` (requires `Store.watch()`, introduced in `0.15.1`) * `@modelence/react-query >= 1.2.1` ## Overview The live query system consists of three parts: 1. **Server-side `LiveData`** - Defines how to fetch data and watch for changes 2. **`ModelenceQueryProvider`** (or `connectModelenceQueryClient`) - Connects Modelence's live query system to TanStack Query 3. **`modelenceLiveQuery`** - Creates live query options for `useQuery` ## Client Setup ### 1. Provide a connected QueryClient `modelenceLiveQuery` needs a TanStack Query `QueryClient` connected to Modelence's live-query layer. The simplest way is to let `renderApp` handle it: if you don't mount your own provider, `renderApp` automatically wraps your app in `ModelenceQueryProvider`, which creates a `QueryClient` and connects it for you. ```tsx theme={null} // src/client/index.tsx import { renderApp } from 'modelence/client'; import routes from './routes'; renderApp({ loadingElement:
Loading…
, routesElement: routes, }); // No provider wiring needed — renderApp injects ModelenceQueryProvider. ``` If you need your own `QueryClient` (for example, to configure defaults or share it with other libraries), connect it yourself with `connectModelenceQueryClient` and mount your own `QueryClientProvider`. `renderApp` detects the already-connected client and will not inject a second provider. ```tsx theme={null} // src/client/index.tsx import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { connectModelenceQueryClient, renderApp } from 'modelence/client'; import routes from './routes'; const queryClient = new QueryClient(); connectModelenceQueryClient(queryClient); renderApp({ loadingElement:
Loading…
, routesElement: ( {routes} ), }); ``` If you mount your own `QueryClientProvider` but never call `connectModelenceQueryClient(queryClient)`, `modelenceLiveQuery` throws: `Modelence: connect a QueryClient before using modelenceLiveQuery(). Mount or call connectModelenceQueryClient().` ### 2. Use modelenceLiveQuery in Components Use `modelenceLiveQuery` with TanStack Query's `useQuery` hook. It works just like `modelenceQuery`, but data updates automatically when the server detects changes: ```tsx theme={null} import { useQuery } from '@tanstack/react-query'; import { modelenceLiveQuery } from 'modelence/client'; function TodoList({ userId }: { userId: string }) { const { data: todos, isLoading } = useQuery( modelenceLiveQuery('todo.getAll', { userId }) ); if (isLoading) return
Loading...
; return (
    {todos?.map(todo => (
  • {todo.title}
  • ))}
); } ``` ## Server Setup ### Returning LiveData from Query Handlers Live query handlers **must** return a `LiveData` object, not plain data. `LiveData` tells Modelence how to fetch the data and how to watch for changes. ```typescript theme={null} import { Module, LiveData } from 'modelence/server'; import { dbTodos } from './db'; export default new Module('todo', { stores: [dbTodos], queries: { // Standard query - returns data directly getById: async ({ id }) => { return await dbTodos.findById(id); }, // Live query - returns LiveData getAll: async ({ userId }) => { return new LiveData({ fetch: async () => await dbTodos.fetch({ userId }), watch: ({ publish }) => { const changeStream = dbTodos.watch(); changeStream.on('change', () => publish()); return () => changeStream.close(); }, }); }, }, }); ``` If a live query handler returns plain data instead of a `LiveData` object, the server will throw: `Live query handler for 'X' must return a LiveData object with fetch and watch functions.` ### LiveData Configuration `LiveData` accepts two functions: | Property | Type | Description | | -------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | | `fetch` | `() => Promise \| T` | Fetches the current data. Called on initial subscription and whenever `publish()` is called. | | `watch` | `({ publish }) => (() => void) \| void` | Sets up real-time monitoring. Call `publish()` to trigger a re-fetch. Return a cleanup function to unsubscribe when the client disconnects. | ### Using MongoDB Change Streams The most common pattern for the `watch` function is MongoDB change streams, which notify you when documents in a collection are inserted, updated, or deleted: ```typescript theme={null} import { LiveData } from 'modelence/server'; import { dbTodos } from './db'; // Watch all changes to a collection queries: { getAll: async ({ userId }) => { return new LiveData({ fetch: async () => await dbTodos.fetch({ userId }), watch: ({ publish }) => { const changeStream = dbTodos.watch(); changeStream.on('change', () => publish()); return () => changeStream.close(); }, }); }, } ``` You can also use a [pipeline](https://www.mongodb.com/docs/manual/changeStreams/#modify-change-stream-output) to filter which changes trigger updates: ```typescript theme={null} // Only watch for changes to a specific user's todos queries: { getAll: async ({ userId }) => { return new LiveData({ fetch: async () => await dbTodos.fetch({ userId }), watch: ({ publish }) => { const pipeline = [ { $match: { 'fullDocument.userId': userId } }, ]; const changeStream = dbTodos.watch(pipeline); changeStream.on('change', () => publish()); return () => changeStream.close(); }, }); }, } ``` MongoDB change streams require a **replica set** or **sharded cluster**. If you're using MongoDB Atlas, this is enabled by default. For local development, you need to configure a replica set. ## Complete Example Here's a full example of a live todo list: ### Server ```typescript theme={null} // src/server/db.ts import { Store, schema } from 'modelence/server'; export const dbTodos = new Store('todos', { schema: { title: schema.string(), isCompleted: schema.boolean(), userId: schema.userId(), createdAt: schema.date(), }, indexes: [ { key: { userId: 1 } }, ], }); ``` ```typescript theme={null} // src/server/module.ts import { Module, LiveData } from 'modelence/server'; import { z } from 'zod'; import { dbTodos } from './db'; export default new Module('todo', { stores: [dbTodos], queries: { getAll: async ({ userId }) => { return new LiveData({ fetch: async () => await dbTodos.fetch( { userId }, { sort: { createdAt: -1 } } ), watch: ({ publish }) => { const changeStream = dbTodos.watch(); changeStream.on('change', () => publish()); return () => changeStream.close(); }, }); }, }, mutations: { create: async (args, { user }) => { const { title } = z.object({ title: z.string() }).parse(args); await dbTodos.insertOne({ title, isCompleted: false, userId: user.id, createdAt: new Date(), }); }, toggleComplete: async (args) => { const { id, isCompleted } = z.object({ id: z.string(), isCompleted: z.boolean(), }).parse(args); await dbTodos.updateOne(id, { $set: { isCompleted } }); }, }, }); ``` ### Client ```tsx theme={null} // src/client/index.tsx import { renderApp } from 'modelence/client'; import TodoList from './pages/TodoList'; // renderApp injects ModelenceQueryProvider automatically — no manual wiring. renderApp({ loadingElement:
Loading…
, routesElement: , }); ``` ```tsx theme={null} // src/client/pages/TodoList.tsx import { useQuery, useMutation } from '@tanstack/react-query'; import { modelenceLiveQuery, modelenceMutation } from 'modelence/client'; import { useSession } from 'modelence/client'; export default function TodoList() { const { user } = useSession(); // Live query - automatically updates when todos change const { data: todos, isLoading } = useQuery( modelenceLiveQuery('todo.getAll', { userId: user?.id }) ); const { mutate: createTodo } = useMutation( modelenceMutation('todo.create') ); const { mutate: toggleComplete } = useMutation( modelenceMutation('todo.toggleComplete') ); if (isLoading) return
Loading...
; return (
    {todos?.map(todo => (
  • toggleComplete({ id: todo._id, isCompleted: !todo.isCompleted, })} /> {todo.title}
  • ))}
); } ``` With this setup, when any client creates or updates a todo, all connected clients see the changes immediately. ## Live Queries vs WebSockets | Feature | Live Queries | WebSockets | | -------------- | --------------------------------------- | ------------------------------------------ | | **Use case** | Automatic data sync with TanStack Query | Custom real-time messaging | | **Data flow** | Server watches data, pushes updates | Bidirectional messaging | | **Client API** | `useQuery(modelenceLiveQuery(...))` | `ClientChannel` + `joinChannel` | | **Server API** | `LiveData` with `fetch` + `watch` | `ServerChannel` + `broadcast` | | **Best for** | Lists, dashboards, any data-driven UI | Chat, notifications, collaborative editing | Live queries are built on top of WebSockets internally, but provide a higher-level abstraction for the common pattern of keeping query data in sync. ## Common Pitfalls ### Missing QueryClient connection If you see `Modelence: connect a QueryClient before using modelenceLiveQuery()`, you mounted your own `QueryClientProvider` without connecting it. Either drop your custom provider and let `renderApp` inject `ModelenceQueryProvider`, or connect your client explicitly: ```tsx theme={null} import { connectModelenceQueryClient } from 'modelence/client'; const queryClient = new QueryClient(); connectModelenceQueryClient(queryClient); ``` ### Returning plain data instead of LiveData If you see `Live query handler for 'X' must return a LiveData object`, your query handler is returning data directly. Wrap it in `LiveData`: ```typescript theme={null} // Wrong getAll: async () => { return await dbItems.fetch({}); }, // Correct getAll: async () => { return new LiveData({ fetch: async () => await dbItems.fetch({}), watch: ({ publish }) => { const changeStream = dbItems.watch(); changeStream.on('change', () => publish()); return () => changeStream.close(); }, }); }, ``` ### Forgetting to close change streams Always return a cleanup function from `watch` to close change streams. Without this, streams accumulate and may exhaust database connections: ```typescript theme={null} watch: ({ publish }) => { const changeStream = dbTodos.watch(); changeStream.on('change', () => publish()); return () => changeStream.close(); // Don't forget this! }, ``` ## Migrating from @modelence/react-query Since `modelence@0.15.0`, the query helpers live in `modelence/client`, and `renderApp` connects a `QueryClient` for you. Existing apps using `@modelence/react-query` keep working — this migration is optional — but new code should use the core imports. **1. Swap the import source.** The helpers are drop-in identical: ```diff theme={null} - import { modelenceQuery, modelenceLiveQuery, modelenceMutation } from '@modelence/react-query'; + import { modelenceQuery, modelenceLiveQuery, modelenceMutation } from 'modelence/client'; ``` **2. Drop the manual provider wiring (optional).** If you connected the client only to satisfy live queries, you can let `renderApp` inject `ModelenceQueryProvider` and remove the boilerplate: ```diff theme={null} - import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; - import { ModelenceQueryClient } from '@modelence/react-query'; import { renderApp } from 'modelence/client'; - const queryClient = new QueryClient(); - new ModelenceQueryClient().connect(queryClient); renderApp({ - routesElement: ( - {routes} - ), + loadingElement:
Loading…
, + routesElement: routes, }); ``` If you still need your own `QueryClient`, replace `new ModelenceQueryClient().connect(queryClient)` with `connectModelenceQueryClient(queryClient)` (the `ModelenceQueryClient` class is deprecated but still exported for compatibility). ## API Reference * [modelenceQuery](/api-reference/modelence/client/functions/modelenceQuery) - Standard (non-live) query helper * [modelenceLiveQuery](/api-reference/modelence/client/functions/modelenceLiveQuery) - Live query helper * [ModelenceQueryProvider](/api-reference/modelence/client/functions/ModelenceQueryProvider) - Auto-connecting provider * [Store](/api-reference/modelence/server/classes/Store) - Database store with `watch()` support # Quick Start Source: https://docs.modelence.com/quickstart ## Build with the App Builder The fastest way to create a Modelence app - no local setup needed. Open [cloud.modelence.com](https://cloud.modelence.com) and sign up for a free account. Describe what you want to build in the prompt field. For example: > "A task management app with user accounts, project boards, and due date reminders" The App Builder will generate your full application - frontend, backend, database, and hosting - in minutes. Once your app is generated, you can continue chatting with the App Builder to refine it. Ask it to add features, change the design, fix issues, or adjust functionality. Once ready, click `Publish`, and your app is automatically deployed to a live URL on Modelence Cloud. You can share it immediately or connect a custom domain. Every app built with the App Builder generates a clean, readable TypeScript + React + MongoDB codebase. You can view, edit, and download the source code at any time. *** ## Developer Quick Start (CLI) If you prefer working locally with your own editor and terminal, you can scaffold a project with the Modelence CLI. ### Prerequisites [Node.js](https://nodejs.org/en/download/) version 18.0 or above * When installing Node.js, make sure to check all checkboxes related to dependencies * Node.js installation includes NPM (Node Package Manager) which is required * You can verify your installation by running: ```bash theme={null} node --version npm --version ``` If you see version numbers displayed for both commands, you're ready to start building with Modelence! ### Creating a new project You can create a new Modelence project using the `create-modelence-app` command. ```bash theme={null} npx create-modelence-app@latest my-app ``` This command will create a new directory named `my-app` with the necessary files and folders for your project. ### Project structure For a detailed breakdown of the project structure, see [Project Structure](/core-concepts/project-structure). ### Start your application Navigate to your project directory and install the required packages: ```bash theme={null} cd my-app npm install ``` Start the development server: ```bash theme={null} npm run dev ``` The `npm run dev` command builds your website locally and serves it through a Vite development server, ready for you to view at [http://localhost:3000/](http://localhost:3000/) (or the port you specified in the `.env` file). If everything is set up correctly, you should see the Modelence new project home page in your browser. ### Next steps Once your local project is running, you can [connect it to Modelence Cloud](/setup) for hosting, database provisioning, and monitoring. # Custom Rate Limiting Source: https://docs.modelence.com/rate-limiting Modelence provides a built-in rate limiting system you can use to protect any mutation or query from abuse. Authentication endpoints come with [their own default limits](/authentication/rate-limiting). ## Defining Rate Limits You can define your own rate limits by adding a `rateLimits` array to a [Module](/api-reference/modelence/server/classes/Module). Each rule specifies a bucket name, the type of actor being limited (`ip` or `user`), a time window, and a maximum number of allowed calls within that window. ```typescript theme={null} import { Module } from 'modelence/server'; import { time } from 'modelence'; const myModule = new Module('myFeature', { rateLimits: [ { bucket: 'myAction', type: 'ip', window: time.minutes(15), // 15-minute window limit: 10, // max 10 calls per window }, ], // ... }); ``` Multiple rules can share the same bucket to enforce more than one window. All rules on a bucket are checked — if any one is exceeded, the call is rejected: ```typescript theme={null} rateLimits: [ { bucket: 'myAction', type: 'ip', window: time.minutes(1), limit: 3 }, // 3 per minute { bucket: 'myAction', type: 'ip', window: time.hours(1), limit: 20 }, // 20 per hour { bucket: 'myAction', type: 'ip', window: time.days(1), limit: 100 }, // 100 per day ], ``` ### Consuming a Rate Limit Call [`consumeRateLimit`](/api-reference/modelence/server/functions/consumeRateLimit) inside a mutation or query handler to check and increment the rate limit counter. It throws a [RateLimitError](/api-reference/modelence/index/classes/RateLimitError) automatically when any matching rule is exceeded: ```typescript theme={null} import { consumeRateLimit } from 'modelence/server'; // Inside a mutation handler: async function handleMyAction(args, { connectionInfo }) { await consumeRateLimit({ bucket: 'myAction', type: 'ip', value: connectionInfo.ip, }); // ... proceed with the action } ``` An optional `message` parameter lets you provide a user-facing error message instead of the default: ```typescript theme={null} await consumeRateLimit({ bucket: 'myAction', type: 'ip', value: connectionInfo.ip, message: 'Too many requests. Please wait a moment and try again.', }); ``` # React Native Source: https://docs.modelence.com/react-native React Native support is available from **modelence v0.19.0**. Modelence's client library works in React Native. Because React Native lacks browser APIs like `localStorage` and `window`, you configure the client with `configureClient` so the SDK knows how to store auth tokens, read device dimensions, and resolve server URLs. ## Setup Add Modelence to your React Native project: ```bash theme={null} npm install modelence ``` You'll also need `@react-native-async-storage/async-storage` (or any other persistent key-value store) to persist the auth token across app restarts. ```bash theme={null} npm install @react-native-async-storage/async-storage ``` Call `configureClient` once, before your app mounts — for example at the top of your entry file (`App.tsx` or `index.ts`). ```typescript theme={null} import { configureClient } from 'modelence/client'; import AsyncStorage from '@react-native-async-storage/async-storage'; import { Dimensions, Linking, PixelRatio } from 'react-native'; const AUTH_TOKEN_KEY = 'modelence_auth_token'; // getAuthToken is called synchronously on every request, so we keep the // token in memory and mirror writes to AsyncStorage for persistence across // app restarts. Load the persisted value before mounting your app (see // the loadAuthToken helper below). let authToken: string | undefined; export async function loadAuthToken() { authToken = (await AsyncStorage.getItem(AUTH_TOKEN_KEY)) ?? undefined; } configureClient({ baseUrl: 'https://your-modelence-app.com', getAuthToken: () => authToken, setAuthToken: (token) => { authToken = token ?? undefined; if (token === null) { AsyncStorage.removeItem(AUTH_TOKEN_KEY); } else { AsyncStorage.setItem(AUTH_TOKEN_KEY, token); } }, getClientInfo: () => { const screen = Dimensions.get('screen'); const window = Dimensions.get('window'); return { screenWidth: screen.width, screenHeight: screen.height, windowWidth: window.width, windowHeight: window.height, pixelRatio: PixelRatio.get(), orientation: screen.width > screen.height ? 'landscape' : 'portrait', }; }, // Used for OAuth redirects — opens the URL in the device browser openUrl: (url) => Linking.openURL(url), }); ``` Load the persisted auth token before mounting your app, then wrap your root component with `AppProvider`: ```tsx theme={null} import { AppProvider } from 'modelence/client'; import { loadAuthToken } from './modelenceConfig'; // the file from the previous step import { useEffect, useState } from 'react'; export default function App() { const [ready, setReady] = useState(false); useEffect(() => { loadAuthToken().then(() => setReady(true)); }, []); if (!ready) return null; return ( ); } ``` ## ClientConfig reference | Field | Type | Description | | --------------- | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `baseUrl` | `string` | Absolute URL of your Modelence server, e.g. `https://myapp.com`. All API and WebSocket connections are made relative to this URL. | | `getAuthToken` | `() => string \| undefined` | Returns the stored auth token synchronously. Called before every request — must not return a `Promise`. | | `setAuthToken` | `(token: string \| null) => void` | Persists or clears the auth token synchronously. Called after login and logout. Async side-effects (e.g. writing to `AsyncStorage`) are fine as long as the function itself is not `async`. | | `getClientInfo` | `() => ClientInfo` | Returns device screen dimensions and pixel ratio. Used for telemetry. | | `openUrl` | `(url: string) => void` | *(Optional)* Opens a URL externally. Defaults to `window.location.href` assignment in browsers. Pass `Linking.openURL` for React Native OAuth redirects. | ## Using authentication Auth functions work the same way as on the web: ```typescript theme={null} import { loginWithPassword, logout, useSession } from 'modelence/client'; // Login await loginWithPassword({ email: 'user@example.com', password: 'secret' }); // Access current user function ProfileScreen() { const { user } = useSession(); if (!user) return Not logged in; return Hello, {user.handle}; } // Logout await logout(); // clears the stored token via setAuthToken(null) ``` ## Calling methods `callMethod` works without any changes — it automatically prepends `baseUrl` to every request: ```typescript theme={null} import { callMethod } from 'modelence/client'; const result = await callMethod('myModule.getData', { id: '123' }); ``` ## Live queries and WebSockets Live queries connect over WebSocket to `baseUrl`. No additional configuration is needed beyond `configureClient`: ```typescript theme={null} import { useQuery } from 'modelence/client'; import { myModule } from './modules/myModule'; function ItemList() { const items = useQuery(myModule.queries.listItems); return items?.map(item => {item.name}); } ``` ## OAuth sign-in For Google or GitHub sign-in, Modelence opens an OAuth URL in the browser. On React Native, provide `openUrl` in `configureClient` so the SDK can hand off to the device browser via `Linking.openURL`: ```typescript theme={null} import { linkOAuthProvider } from 'modelence/client'; import { Linking } from 'react-native'; configureClient({ // ... openUrl: (url) => Linking.openURL(url), }); // Trigger OAuth linking await linkOAuthProvider({ provider: 'google' }); ``` After the OAuth flow completes, the provider redirects back to your app via a deep link. Configure your deep link scheme to call `loginWithOAuth` with the returned token. ## Notes * **No `AppProvider` required for auth-only usage.** You can call `loginWithPassword`, `callMethod`, etc. without `AppProvider`. The provider is needed only if you use React hooks like `useSession` or `useQuery`. * **Token persistence is your responsibility.** Modelence calls `setAuthToken` and `getAuthToken` but does not bundle a storage library. Use `AsyncStorage`, `expo-secure-store`, or any store that fits your security requirements. * **`orientation` in `ClientInfo` is optional.** Pass `null` if your app does not track orientation. # Roles Source: https://docs.modelence.com/roles Define custom roles and manage user access Modelence provides built-in support for user roles. You can define roles in `startApp`, assign them to users, and check them on both the server and client. ## Defining Roles Register the roles your app uses in your `startApp` call: ```typescript theme={null} import { startApp } from 'modelence/server'; startApp({ roles: { admin: { description: 'Full access to all features' }, editor: { description: 'Can edit content' }, viewer: {}, }, }); ``` Each role has an optional `description` that is shown in the Modelence Cloud dashboard. Roles defined in `startApp` are synced to Modelence Cloud so you can assign them to users directly from the dashboard. ## Checking Roles in Handlers Use `user.requireRole` to throw an error if the user lacks a role, or `user.hasRole` for manual checking: ```typescript theme={null} import { Module } from 'modelence/server'; import { AuthError } from 'modelence'; export default new Module('myModule', { mutations: { adminAction: { handler: async (args, { user }) => { if (!user) { throw new AuthError('Not authenticated'); } // Throws if the user doesn't have the "admin" role user.requireRole('admin'); // Admin-only logic here } }, anotherAdminAction: { handler: async (args, { user }) => { if (!user) { throw new AuthError('Not authenticated'); } // Check without throwing for custom error handling if (!user.hasRole('admin')) { throw new Error('Admin access required'); } // Admin-only logic here } } } }); ``` ## Assigning Roles The recommended way to assign roles is through the Modelence Cloud user management dashboard. If that is not available, you can update roles directly via the `dbUsers` collection: ```typescript theme={null} import { dbUsers, ObjectId } from 'modelence/server'; // Add a role await dbUsers.updateOne( { _id: new ObjectId(userId) }, { $addToSet: { roles: 'admin' } } ); // Add multiple roles await dbUsers.updateOne( { _id: new ObjectId(userId) }, { $addToSet: { roles: { $each: ['editor', 'viewer'] } } } ); // Remove a role await dbUsers.updateOne( { _id: new ObjectId(userId) }, { $pull: { roles: 'admin' } } ); ``` ## Frontend Usage Use `useSession` to check roles on the client and conditionally render UI: ```typescript theme={null} import { useSession } from 'modelence/client'; function AdminPanel() { const { user } = useSession(); if (!user?.hasRole('admin')) { return
Access denied
; } return
Admin content
; } ``` ```typescript theme={null} import { useSession } from 'modelence/client'; function Navigation() { const { user } = useSession(); return ( ); } ``` ## API Reference **`startApp` options:** * `roles` — `Record` — role definitions keyed by name **`RoleDefinition`:** * `description?: string` — optional human-readable description shown in the Modelence Cloud dashboard **User methods:** * `user.roles: string[]` — the roles assigned to the user * `user.hasRole(role: string): boolean` — check if user has a specific role * `user.requireRole(role: string): void` — throw error if user doesn't have role # Setup Source: https://docs.modelence.com/setup You can either continue using your Modelence project as it is, or connect it to Modelence Cloud. We've built **Modelence Cloud** to seamlessly host and monitor Modelence applications, and it's designed for both scalable production apps as well as local development environments. By connecting your local project, you can use a free remote MongoDB database without having to set up your own, and you will also get access to logs, metrics and performance insights of your locally running application. If you want to skip this for now, feel free to ignore the "Connecting to Modelence Cloud" section below and continue with the MongoDB setup section. ## Connecting to Modelence Cloud First, you need to create a free Modelence account by going to [Modelence Cloud](https://cloud.modelence.com). After you've logged in, create a new application and name it after your project. After you've created an application, create a new environment. There are 2 types of environments: **cloud** and **local**. The cloud environment will provision and deploy your application to Modelence Cloud servers, while the local environment will only provision a remote MongoDB database for your local development. You can also connect to an external MongoDB database instead of using Modelence's provisioned database. See the "Setting up MongoDB" section below for more details. After you've created a new environment, open its Settings page and click on `Setup Local Environment` button. It will open a modal with 2 steps. The first step creates a project (it's optional) by running the following command. ```bash theme={null} npx create-modelence-app@latest testenv --template ai-chat ``` The second command should be executed in the project directory and it connects the project to Modelence Cloud. Here is how the command looks like: ```bash theme={null} npx modelence@latest setup --token ``` It will automatically create a `.modelence.env` file with the necessary environment variables. Run the following command in the project directory `npm run dev` to start the development server. Now, if everything is set up correctly, you should see your environment status go from `inactive` to `active` in the Modelence Cloud dashboard. ## Deploy to Modelence Cloud To deploy your Modelence application to the cloud, follow these steps: In your Modelence Cloud dashboard, navigate to your application and create a new environment. This time, select **cloud** as the environment type instead of local. Cloud environments will provision infrastructure and deploy your application to Modelence Cloud servers. After creating the cloud environment, navigate to its Settings page. You'll find deployment configuration and commands here. If you don't have an existing project, you can create one using the command from Step 1 in the settings modal: ```bash theme={null} npx create-modelence-app@latest my-app --template ai-chat ``` Replace `my-app` with your preferred project name and choose the template that fits your needs. Copy the deployment command from Step 2 in the settings page. The command will look like this: ```bash theme={null} npx modelence@latest deploy --app --env ``` Run this command in your project directory to deploy your application to Modelence Cloud. The deployment process will: * Build your application * Upload it to Modelence Cloud * Provision necessary resources (MongoDB database, server infrastructure) * Start your application Once deployment completes, your environment status will change to `active` and you'll receive a URL to access your deployed application. Cloud deployments include automatic scaling, monitoring, and a production-ready MongoDB database. You can view logs, metrics, and manage your deployment from the Modelence Cloud dashboard. ## Setting up MongoDB If you've connected your local project to Modelence Cloud, as described in the section above, **no more setup is needed** - you are automatically set up with a MongoDB database that is included with your remote environment and can skip this section. If you skipped the Modelence Cloud setup, the easiest way to set up MongoDB is to use the [MongoDB Atlas](https://www.mongodb.com/atlas) free tier. While you can set up your own local MongoDB instance, we recommend Atlas because it eliminates the need for local installation and provides cloud storage for your development data, protecting it from local environment issues or data loss. ### Setting up MongoDB with Atlas * Go to [MongoDB Atlas](https://www.mongodb.com/atlas) * Sign up for a new account or log in if you already have one For more detailed instructions, you can refer to the [MongoDB Atlas documentation](https://www.mongodb.com/docs/guides/atlas/cluster/) * Click "Build a Database" * Choose the "FREE" tier (labeled as "Shared" or "M0") * Select your preferred cloud provider and region * Click "Create" to deploy your cluster (this may take a few minutes) * In the Security Quickstart page, select "Username and Password" authentication * Enter a username in the first text field * For the password, either: * Enter your own secure password, or * Click "Autogenerate Secure Password" to let Atlas create one * Click "Create User" For more detailed instructions, you can refer to the [MongoDB user setup guide](https://www.mongodb.com/docs/guides/atlas/db-user/) * In the Security Quickstart page, select "My Local Environment" * In the "Add entries to your IP Access List" section, you can either: * Click "Add My Current IP Address" to add your current IP * For development, click "Allow Access from Anywhere" (0.0.0.0/0) * Click "Finish and Close" For more detailed instructions, you can refer to the [MongoDB network access guide](https://www.mongodb.com/docs/guides/atlas/network-connections/) * Return to the "Database" page * Click "Connect" on your cluster * Select "Drivers" under "Connect Your Application" * Choose the latest Node.js version and copy the connection string * Replace the `` and `` in the string with your database user's username and password * Add your desired database name to the connection string (otherwise it will default to `test`), so it looks like this: ``` mongodb+srv://:@.mongodb.net/?retryWrites=true&w=majority ``` For more detailed instructions, you can refer to the [MongoDB connection string guide](https://www.mongodb.com/docs/guides/atlas/connection-string/) Do not load sample data into your newly created database if prompted - Modelence already provisions what you need and will work perfectly with an empty database on the first run. ### Configure Environment Variables Without the Modelence Cloud setup, you need to manually add your database configuration. Once you have your connection string, you'll need to add it to your Modelence environment variables. Create a `.modelence.env` file in your project root (if it doesn't exist already) and add: ```env theme={null} MONGODB_URI="" ``` Make sure that your `.modelence.env` file is added to your `.gitignore` to keep your credentials secure. ## Next Steps Check out an example Todo app # Server-Side Rendering Source: https://docs.modelence.com/ssr Render your React tree on the server for faster first paint and hydrate on the client. Available since modelence@0.15.0. Server-side rendering (SSR) renders your React application to HTML on the server, sends that HTML to the browser, and then hydrates it on the client. This improves first-paint performance and lets crawlers see fully rendered markup. SSR in Modelence is **opt-in**. Existing client-only apps keep working unchanged — you only get SSR after you explicitly enable it. ## Enabling SSR Set `ssr: true` in `startApp`: ```typescript title="src/server/app.ts" theme={null} import { startApp } from 'modelence/server'; import todoModule from './todo'; startApp({ modules: [todoModule], ssr: true, }); ``` That's the only required change. The Modelence build always emits SSR artifacts, so there is no separate build flag — `startApp({ ssr: true })` decides whether they are used at runtime. When `ssr` is omitted or `false`, Modelence renders on the client only, exactly as before. Nothing about your existing app changes until you opt in. ## Routing with SSR For the server and client to resolve the same route, a location-driven router must be told which URL to render. Pass a `router` function to `renderApp`. Modelence calls it with the current `location` on the server and again on the client during hydration, so both produce the same tree: ```tsx title="src/client/index.tsx" theme={null} import { renderApp } from 'modelence/client'; import { StaticRouter } from 'react-router-dom/server'; import { BrowserRouter } from 'react-router-dom'; import routes from './routes'; renderApp({ loadingElement:
Loading…
, routesElement: routes, router: ({ children, location }) => typeof window === 'undefined' ? {children} : {children}, }); ``` The `location` passed to the router is `path + search` (the hash is never sent to the server), matching what the browser sees on hydration. This avoids hydration mismatches. Without a `router`, a location-driven router (like React Router) will render its default route on the server and a different route on the client, producing a hydration mismatch. Only pass `router` when your routing depends on the current URL. ## Data fetching and hydration * **Session** is rendered on the server and hydrated on the client, so `useSession()` returns the correct value on the very first render with no flash of logged-out UI. * **Queries** (`modelenceQuery`) run on the server and their results are serialized into the HTML, so cached data is available immediately after hydration. * **Live queries** (`modelenceLiveQuery`) are WebSocket subscriptions with no server snapshot — they stay pending during SSR and connect after hydration on the client. See [Queries](/core-concepts/queries) and [Live Queries](/live-queries) for how to call methods from the client. ## Related * [Queries](/core-concepts/queries) * [Live Queries](/live-queries) * [Project Structure](/core-concepts/project-structure) # Stores Source: https://docs.modelence.com/stores MongoDB collections with TypeScript schemas and helper methods Stores in Modelence provide a type-safe interface for MongoDB collections with built-in schema validation, custom methods, and indexing support. ## Overview A Store represents a MongoDB collection with: * **Type-safe schemas** using Modelence schema types (based on Zod) * **Custom document methods** for business logic * **MongoDB indexes** for query performance * **Search indexes** for MongoDB Atlas Search * **CRUD operations** with full TypeScript support ## Creating a Store Define a Store by specifying a collection name and configuration: ```typescript theme={null} import { Store, schema } from 'modelence/server'; export const dbTodos = new Store('todos', { schema: { title: schema.string(), isCompleted: schema.boolean(), dueDate: schema.date().optional(), userId: schema.userId(), createdAt: schema.date(), }, indexes: [ { key: { userId: 1 } }, { key: { dueDate: 1 } }, ], methods: { isOverdue() { return this.dueDate ? this.dueDate < new Date() : false; } } }); ``` ## Schema Definition Modelence schemas are based on and closely resemble Zod types. Available schema types include: ```typescript theme={null} { // Primitive types name: schema.string(), age: schema.number(), isActive: schema.boolean(), createdAt: schema.date(), // Optional fields description: schema.string().optional(), // Arrays tags: schema.array(schema.string()), // Objects metadata: schema.object({ key: schema.string(), value: schema.string(), }), // Built-in Modelence types userId: schema.userId(), // References a user ID } ``` ## Custom Methods Add custom methods to documents for business logic: ```typescript theme={null} export const dbProducts = new Store('products', { schema: { name: schema.string(), price: schema.number(), discount: schema.number().optional(), }, methods: { getFinalPrice() { return this.discount ? this.price * (1 - this.discount / 100) : this.price; }, hasDiscount() { return !!this.discount && this.discount > 0; } } }); // Usage const product = await dbProducts.findById(productId); console.log(product.getFinalPrice()); // Custom method available ``` ## Indexes For index configuration and examples, see [Indexes](/indexes). The indexes guide covers: * MongoDB `indexes` * Atlas `searchIndexes` * `indexCreationMode` (`blocking` vs `background`) and startup behavior with migrations ## CRUD Operations Stores provide comprehensive methods for data operations: ### Finding Documents ```typescript theme={null} // Find one document const todo = await dbTodos.findOne({ userId: user.id }); // Find by ID const todo = await dbTodos.findById(todoId); // Require one (throws error if not found) const todo = await dbTodos.requireById(todoId); // Fetch multiple documents const todos = await dbTodos.fetch( { userId: user.id }, { projection: { title: 1, isCompleted: 1, createdAt: 1 }, sort: { createdAt: -1 }, limit: 10 } ); // Exclude heavy fields when they are not needed const chunks = await dbDocumentChunks.fetch( { documentId }, { projection: { embedding: 0 } } ); // Count documents const count = await dbTodos.countDocuments({ isCompleted: false }); ``` ### Inserting Documents ```typescript theme={null} // Insert one const { insertedId } = await dbTodos.insertOne({ title: 'Buy groceries', isCompleted: false, userId: user.id, createdAt: new Date() }); // Insert many const result = await dbTodos.insertMany([ { title: 'Task 1', isCompleted: false, userId: user.id, createdAt: new Date() }, { title: 'Task 2', isCompleted: false, userId: user.id, createdAt: new Date() } ]); ``` ### Updating Documents ```typescript theme={null} // Update one await dbTodos.updateOne( { _id: new ObjectId(todoId) }, { $set: { isCompleted: true } } ); // Update one with convenience selector (by ID string) await dbTodos.updateOne( todoId, { $set: { isCompleted: true } } ); // Upsert (update or insert) await dbTodos.upsertOne( { userId: user.id, title: 'Unique task' }, { $set: { isCompleted: false } } ); // Atomic find-or-create — returns the document and whether it was just created const { doc, isNew } = await dbTodos.findOneAndUpsert( { userId: user.id, title: 'Unique task' }, { $setOnInsert: { userId: user.id, title: 'Unique task', isCompleted: false } } ); if (isNew) { // ...run first-time setup for the new document } // Update many await dbTodos.updateMany( { userId: user.id }, { $set: { isArchived: true } } ); ``` `findOneAndUpsert` is the atomic form of a check-then-create: it matches or inserts in a single operation and reports `isNew` (from the driver's upsert result), so concurrent callers can't race between a lookup and an insert. Pass `upsert: false` to make it a pure find-and-report that returns `{ doc: null, isNew: false }` when nothing matches. It always returns the post-operation document. ### Deleting Documents ```typescript theme={null} // Delete one await dbTodos.deleteOne({ _id: new ObjectId(todoId) }); // Delete many await dbTodos.deleteMany({ isCompleted: true }); ``` ### Advanced Operations ```typescript theme={null} // Aggregation pipeline const stats = await dbTodos.aggregate([ { $match: { userId: user.id } }, { $group: { _id: '$isCompleted', count: { $sum: 1 } }} ]).toArray(); // Bulk write operations await dbTodos.bulkWrite([ { insertOne: { document: { title: 'New task', /* ... */ } } }, { updateOne: { filter: { _id: new ObjectId(todoId) }, update: { $set: { isCompleted: true } } } }, { deleteOne: { filter: { _id: new ObjectId(oldTodoId) } } } ]); ``` ## Including Stores in Modules Register stores in your module to automatically provision them: ```typescript theme={null} import { Module } from 'modelence/server'; import { dbTodos } from './db'; export default new Module('todo', { stores: [dbTodos], queries: { async getAll() { return await dbTodos.fetch({}); } } }); ``` When your application starts, Modelence will: * Provision the collection in MongoDB * Create all configured indexes * Create all configured search indexes Stores handle all MongoDB connection management automatically. Just define your Store and include it in a module - Modelence takes care of the rest. ## Extending Stores Use the `extend()` method to add custom schema fields, indexes, methods, and search indexes to any store, including system collections: ```typescript theme={null} import { schema, dbUsers } from 'modelence/server'; // Extend the users collection export const extendedDbUsers = dbUsers.extend({ schema: { firstName: schema.string(), lastName: schema.string(), companyId: schema.objectId().optional(), }, indexes: [ { key: { companyId: 1 } }, { key: { lastName: 1, firstName: 1 } }, ], methods: { getFullName() { return `${this.firstName} ${this.lastName}`; } } }); // Fully typed with new fields and methods! const user = await extendedDbUsers.findOne({ firstName: 'John' }); console.log(user?.getFullName()); // ✅ Custom methods work console.log(user?.companyId); // ✅ Type-safe fields console.log(user?.handle); // ✅ Original fields preserved ``` The `extend()` method creates a new Store instance with merged schema, methods, indexes, and search indexes. The extended store shares the same MongoDB collection as the original. ## Best Practices 1. **Define stores per domain** - Keep related data in the same module 2. **Plan index strategy** - See [Indexes](/indexes) for configuration patterns and startup mode tradeoffs 3. **Leverage custom methods** - Encapsulate business logic in document methods 4. **Type safety** - Let TypeScript guide you with schema-based types 5. **Use Atlas Search intentionally** - Use `searchIndexes` for advanced full-text search use cases 6. **Extend system collections early** - Extend system collections like `dbUsers` before using them in your application 7. **Use sparse indexes** - For optional fields with low cardinality, use `sparse: true` to save space ## API Reference For a complete list of available methods and detailed API documentation, see the [Store API Reference](/api-reference/modelence/server/classes/Store). # Telemetry Source: https://docs.modelence.com/telemetry Logging and monitoring your Modelence application Modelence includes built-in telemetry and logging functionality to help you monitor and debug your application. This guide covers the logging functions and environment variables you can use to control telemetry behavior. ## Logging Functions Modelence provides three logging functions for different severity levels. These functions automatically integrate with your telemetry provider when enabled, while also supporting console output for local development. ### logDebug Use `logDebug` for detailed debugging information that is typically only useful during development or troubleshooting. ```typescript theme={null} import { logDebug } from 'modelence/telemetry'; logDebug('Processing user request', { userId: user.id, action: 'profile_update' }); ``` **When it logs:** * To telemetry provider: Always (when telemetry is enabled) * To console: Only when `MODELENCE_LOG_LEVEL=debug` ### logInfo Use `logInfo` for general informational messages about application flow and important events. ```typescript theme={null} import { logInfo } from 'modelence/telemetry'; logInfo('User authenticated successfully', { userId: user.id, method: 'password' }); ``` **When it logs:** * To telemetry provider: Always (when telemetry is enabled) * To console: When `MODELENCE_LOG_LEVEL=debug` or `MODELENCE_LOG_LEVEL=info` ### logError Use `logError` for error conditions and exceptions that need attention. ```typescript theme={null} import { logError } from 'modelence/telemetry'; logError('Failed to process payment', { userId: user.id, error: error.message, orderId: order.id }); ``` **When it logs:** * To telemetry provider: Always (when telemetry is enabled) * To console: When `MODELENCE_LOG_LEVEL=debug`, `MODELENCE_LOG_LEVEL=info`, or `MODELENCE_LOG_LEVEL=error` ## Function Signature All three logging functions accept the same parameters: ```typescript theme={null} logDebug(message: string, args: object) logInfo(message: string, args: object) logError(message: string, args: object) ``` * **message**: A descriptive string explaining what is being logged * **args**: An object containing contextual data (user IDs, request details, etc.) ## Environment Variables ### `MODELENCE_LOG_LEVEL` Controls the verbosity of console logging. This is especially useful during local development or when debugging production issues. **Valid values:** * `debug` - Logs all messages (debug, info, and error) to console * `info` - Logs info and error messages to console * `error` - Logs only error messages to console * Not set - No console logging (default when telemetry is enabled) **Default behavior:** * When telemetry is **enabled** and `MODELENCE_LOG_LEVEL` is **not set**: No console logging * When telemetry is **disabled** and `MODELENCE_LOG_LEVEL` is **not set**: Defaults to `info` level **Example usage:** ```bash theme={null} # In your .env file or shell MODELENCE_LOG_LEVEL=debug ``` ```bash theme={null} # For development - see all logs MODELENCE_LOG_LEVEL=debug npm run dev # For production debugging - see info and errors only MODELENCE_LOG_LEVEL=info npm start # For production monitoring - see only errors MODELENCE_LOG_LEVEL=error npm start ``` ## Log Level Behavior Matrix | Log Level | logDebug console | logInfo console | logError console | Telemetry | | ---------------------------- | ---------------- | --------------- | ---------------- | -------------- | | `debug` | ✓ | ✓ | ✓ | ✓ (if enabled) | | `info` | ✗ | ✓ | ✓ | ✓ (if enabled) | | `error` | ✗ | ✗ | ✓ | ✓ (if enabled) | | Not set (telemetry enabled) | ✗ | ✗ | ✗ | ✓ | | Not set (telemetry disabled) | ✗ | ✓ | ✓ | ✗ | ## Additional Telemetry Functions Modelence also provides advanced telemetry functions for performance monitoring and error tracking: ### startTransaction Track performance of operations like routes, methods, or background jobs: ```typescript theme={null} import { startTransaction } from 'modelence/telemetry'; const transaction = startTransaction('method', 'processOrder', { orderId: order.id }); try { // Your operation here await processOrder(order); transaction.end('success'); } catch (error) { transaction.end('failure'); throw error; } ``` **Transaction types:** * `method` - API method calls * `route` - HTTP route handlers * `cron` - Scheduled jobs * `ai` - AI operations * `custom` - Custom operations ### captureError Capture and report errors to your telemetry provider: ```typescript theme={null} import { captureError } from 'modelence/telemetry'; try { await riskyOperation(); } catch (error) { captureError(error); // Handle error... } ``` When telemetry is disabled, `captureError` falls back to `console.error`. ## Best Practices 1. **Use appropriate log levels**: Reserve `logError` for actual errors, use `logInfo` for important events, and `logDebug` for detailed troubleshooting information. 2. **Include context**: Always provide relevant context in the `args` object to make debugging easier: ```typescript theme={null} logInfo('Order processed', { orderId: order.id, userId: user.id, amount: order.total, paymentMethod: order.paymentMethod }); ``` 3. **Avoid logging sensitive data**: Never log passwords, API keys, or personally identifiable information (PII): ```typescript theme={null} // ❌ Bad logDebug('User login', { password: user.password }); // ✓ Good logDebug('User login', { userId: user.id, method: 'password' }); ``` 4. **Use transactions for performance tracking**: Wrap important operations in transactions to monitor their performance and success rates. 5. **Configure log levels per environment**: * **Development**: `MODELENCE_LOG_LEVEL=debug` for maximum visibility * **Staging**: `MODELENCE_LOG_LEVEL=info` for important events * **Production**: No `MODELENCE_LOG_LEVEL` set (rely on telemetry) or `MODELENCE_LOG_LEVEL=error` for critical issues only ## Telemetry Integration By default, Modelence logs are sent to your configured telemetry provider (like Modelence Cloud). To configure telemetry for your application: 1. Visit [cloud.modelence.com](https://cloud.modelence.com) 2. Select your project and environment 3. Navigate to **Application** → **Telemetry** settings 4. Configure your telemetry preferences All logging functions (`logDebug`, `logInfo`, `logError`) automatically send data to your telemetry provider when it's enabled, giving you centralized visibility into your application's behavior. ## Next Steps * Learn about [Authentication](/authentication) to add user management * Explore [Email](/email) configuration for transactional emails * Review [WebSockets](/websockets) for real-time features # Todo App Source: https://docs.modelence.com/tutorial Build a simple Todo app with Modelence In this tutorial, we'll build a complete Todo app using Modelence. You'll learn how to: * Create **MongoDB stores** with TypeScript schemas * Build **modules** with queries and mutations * Create **React components** that interact with your backend This tutorial assumes you've already [created a Modelence project](/quickstart) and [completed the setup](/setup). If you haven't done so, please complete those steps first. ## Step 1: Create a Todo Store Stores in Modelence are MongoDB collections with built-in TypeScript support, schema and helper methods. They help you to: * Define **type-safe schemas** for your data * Handle **CRUD operations** with MongoDB * Add **custom methods** to your documents * Configure **indexes** for better performance ### Set up the project structure The recommended approach in Modelence is to group code by modules/domains into separate directories. For our Todo app, create an `src/server/todo` directory and add a `db.ts` file: ```typescript title="src/server/todo/db.ts" theme={null} import { Store, schema } from 'modelence/server'; export const dbTodos = new Store('todos', { // Define the schema for your documents. Modelence schema is based on and closely resembles Zod types. schema: { title: schema.string(), isCompleted: schema.boolean(), dueDate: schema.date().optional(), userId: schema.userId(), // Built-in Modelence type for user references createdAt: schema.date(), }, // Configure MongoDB indexes indexes: [ { key: { userId: 1 } }, { key: { dueDate: 1 } }, ], // Add custom methods to documents. These are available on instances // returned by server-side Store methods (e.g. findById, fetch). // They are stripped when data is serialized over the wire to the client. methods: { isOverdue() { return this.dueDate ? this.dueDate < new Date() : false; } } }); ``` ### Using the Store Once defined, you can use your Store object to perform operations on your collection: ```typescript theme={null} const { insertedId } = await dbTodos.insertOne({ title: 'Buy groceries', isCompleted: false, dueDate: new Date('2023-01-31'), userId: '123', createdAt: new Date() }); const todo = await dbTodos.findById(insertedId); console.log(todo.isOverdue()); ``` ### Working with Documents Stores provide a comprehensive set of methods for working with MongoDB documents, including finding, inserting, updating, and deleting records. All methods are fully typed with TypeScript. See the [Store API Reference](/api-reference/modelence/server/classes/Store) for a complete list of available methods and their usage. Stores automatically handle MongoDB connection management, collection provisioning and index creation. Just define your Store and start using it - Modelence takes care of the rest. ## Step 2: Create a Todo Module Modules are the core building blocks of a Modelence application. They help you organize your application's functionality into cohesive units that can contain queries, mutations, stores, cron jobs and configurations. Create a new file at `src/server/todo/index.ts`: ```typescript title="src/server/todo/index.ts" theme={null} import { Module } from 'modelence/server'; import { dbTodos } from './db'; export default new Module('todo', { /* Include the store we created earlier so it will be automatically provisioned in MongoDB when the server starts. */ stores: [dbTodos], /* Module queries and mutations are similar to the corresponding concepts from GraphQL. */ queries: { async getOne({ id }) { return await dbTodos.findById(id); }, async getAll() { return await dbTodos.fetch({}); } }, mutations: { async create({ title, dueDate }, { user }) { const { insertedId } = await dbTodos.insertOne({ title, dueDate, userId: user.id, isCompleted: false, createdAt: new Date() }); return insertedId; }, async update({ id, title, dueDate, isCompleted }) { return await dbTodos.updateOne(id, { $set: { title, dueDate, isCompleted } }); }, async delete({ id }) { return await dbTodos.deleteOne(id); } }, }); ``` ### Include the Module Now, add the Module to your main server file at `src/server/app.ts`: ```typescript title="src/server/app.ts" theme={null} import { startApp } from 'modelence/server'; import todoModule from './todo'; startApp({ modules: [todoModule] }); ``` As soon as your app starts, Modelence will: * Provision the `dbTodos` store in MongoDB * Make the queries and mutations available for calling ## Step 3: Create the Frontend Modelence is frontend-agnostic, so you are free to use any routing library you like. We will use React Router for this example, which is what's included in the default Modelence starter. ### Add a new route Edit `src/client/routes.ts` to add a new route for our todos: ```typescript title="src/client/routes.ts" theme={null} import { lazy } from 'react'; export const routes = [ // ... your existing routes { path: '/todos', Component: lazy(() => import('./TodosPage')) }, ]; ``` ### Create the TodosPage component Create a new component at `src/client/TodosPage.tsx`: ```tsx title="src/client/TodosPage.tsx" theme={null} import { useState } from 'react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { modelenceQuery, modelenceMutation, createQueryKey } from 'modelence/client'; // Helper: Store `methods` only live on server-side document instances and // are stripped when results are serialized over the wire. Reimplement // `isOverdue` on the client against the plain JSON shape. function isOverdue(todo: { dueDate?: string | Date | null }): boolean { if (!todo.dueDate) return false; return new Date(todo.dueDate) < new Date(); } export default function TodosPage() { const [newTodoTitle, setNewTodoTitle] = useState(''); const queryClient = useQueryClient(); const { data: todos, isPending: isLoading, error } = useQuery( modelenceQuery('todo.getAll') ); // `modelenceQuery('todo.getAll')` uses queryKey `['todo.getAll', {}]`, so // invalidation must match that exact shape. `createQueryKey` builds it // for us — passing `['todo.getAll']` would silently no-op. const invalidateTodos = () => { queryClient.invalidateQueries({ queryKey: createQueryKey('todo.getAll') }); }; const { mutate: createTodo, isPending: isCreating } = useMutation({ ...modelenceMutation('todo.create'), onSuccess: () => { setNewTodoTitle(''); invalidateTodos(); }, }); const { mutate: updateTodo } = useMutation({ ...modelenceMutation('todo.update'), onSuccess: invalidateTodos, }); const { mutate: deleteTodo } = useMutation({ ...modelenceMutation('todo.delete'), onSuccess: invalidateTodos, }); const handleCreateTodo = (e: React.FormEvent) => { e.preventDefault(); const title = newTodoTitle.trim(); if (!title) return; createTodo({ title }); }; const handleToggleComplete = (todo: any) => { updateTodo({ id: todo._id, title: todo.title, dueDate: todo.dueDate, isCompleted: !todo.isCompleted }); }; const handleDeleteTodo = (id: string) => { deleteTodo({ id }); }; if (isLoading) { return (
Loading todos...
); } if (error) { return (
Error: {error.message}
); } return (

My Todos

{/* Add new todo form */}
setNewTodoTitle(e.target.value)} placeholder="Add a new todo..." className="flex-1 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" />
{/* Todos list */}
{todos?.length === 0 ? (

No todos yet. Add one above!

) : ( todos?.map((todo) => (
handleToggleComplete(todo)} className="w-5 h-5 text-blue-600" /> {todo.title} {todo.dueDate && ( Due: {new Date(todo.dueDate).toLocaleDateString()} )}
)) )}
); } ``` ## Complete Example Want to see the full working code? Check it out on GitHub, along with other examples: See the complete source code for this tutorial on GitHub, including all files and additional features. # Voyage AI Source: https://docs.modelence.com/voyage-ai Build semantic search with Modelence, MongoDB and Voyage AI In this tutorial, you'll learn how to integrate Voyage AI with Modelence to build powerful semantic search capabilities. You'll learn how to: * Generate **embeddings** using Voyage AI's embedding models * Store embeddings in **MongoDB** using vector fields * Perform **vector search** with MongoDB's vector search capabilities * Use **reranking** to improve search results This tutorial assumes you've already [created a Modelence project](/quickstart) and [completed the setup](/setup). If you haven't done so, please complete those steps first. ## What is Voyage AI? Voyage AI provides state-of-the-art embedding and reranking models that enable semantic search, recommendation systems, and RAG (Retrieval-Augmented Generation) applications. Their models are optimized for: * **High-quality embeddings** for semantic similarity * **Reranking** to improve search result relevance * **Domain-specific fine-tuning** options ## Prerequisites Before starting, you'll need: 1. A Voyage AI API key - [Get one here](https://www.voyageai.com/) 2. A Modelence account with MongoDB configured ## Quick Start with Template The fastest way to get started is using the Voyage AI template: ```bash theme={null} npx create-modelence-app@latest my-voyage-app --template voyage-ai ``` This creates a ready-to-use project with all the code from this tutorial pre-configured. ### Setup Steps 1. **Create an account** on [cloud.modelence.com](https://cloud.modelence.com/) 2. **Create an application and local environment** in the Modelence Cloud dashboard 3. **Open the Settings page** of your environment and click on **Setup Local Environment** 4. **Copy the command** from the "Connect to Modelence Cloud" section and execute it in your project directory 5. **Add your Voyage AI API key**: * Get your API key from [voyageai.com](https://www.voyageai.com/) * In the Modelence Cloud dashboard, open your environment's **Application** tab and set the `voyage.apiKey` config to your API key 6. **Run the project**: ```bash theme={null} npm run dev ``` You can also view a [live demo](https://voyage-ai-mg8435n3pj5-sandbox.prod.modelence.app) of the complete example. ## Manual Setup If you want to add Voyage AI to an existing project, follow these steps: ## Step 1: Install Dependencies Install the Voyage AI client library: ```bash theme={null} npm install voyageai ``` ## Step 2: Create a Document Store with Vector Embeddings Stores in Modelence support vector embeddings out of the box with the `schema.embedding()` type and vector search indexes. Create a new directory `src/server/voyage` and add a `db.ts` file: ```typescript title="src/server/voyage/db.ts" theme={null} import { Store, schema } from 'modelence/server'; export const dbDocuments = new Store('documents', { schema: { content: schema.string(), metadata: schema.object({ title: schema.string(), description: schema.string(), }), embedding: schema.embedding(), createdAt: schema.date(), }, indexes: [ { key: { createdAt: -1 } }, ], searchIndexes: [ Store.vectorIndex({ field: 'embedding', dimensions: 1024, // Voyage-3.5 default (supports 256, 512, 1024, 2048) }), ], }); ``` The `schema.embedding()` type is a special type for storing vector embeddings. The `vectorIndex()` method creates a MongoDB vector search index for fast similarity searches. ## Step 3: Create Voyage AI Helper Functions Create a `voyage.ts` file to handle embedding generation and reranking: ```typescript title="src/server/voyage/voyage.ts" theme={null} import { getConfig } from 'modelence/server'; import { VoyageAIClient } from 'voyageai'; let voyageClient: VoyageAIClient | null = null; export function getVoyageClient() { if (!voyageClient) { const apiKey = getConfig('voyage.apiKey') as string || process.env.VOYAGE_API_KEY; if (!apiKey) { throw new Error('VOYAGE_API_KEY environment variable is not set'); } voyageClient = new VoyageAIClient({ apiKey }); } return voyageClient; } export async function generateEmbedding( text: string, inputType: 'query' | 'document' = 'document' ): Promise { const client = getVoyageClient(); const result = await client.embed({ input: [text], model: 'voyage-3.5', inputType, }); return result.data?.[0].embedding || []; } export async function rerank>( results: T[], field: string, query: string ) { const client = getVoyageClient(); const rerankedResponse = await client.rerank({ model: 'rerank-2.5', query: query, documents: results.map(doc => doc[field]), topK: 10, }); // Map the reranked results back to the original documents return rerankedResponse.data?.map(rerankedDoc => { const index = rerankedDoc.index || 0; return { ...results[index], score: rerankedDoc.relevanceScore }; }) || results; } ``` ### Key Points: * **Input Type**: Voyage AI supports different input types (`query` vs `document`) to optimize embeddings for different use cases * **Model Selection**: `voyage-3.5` is the latest embedding model supporting 4 dimension options (256, 512, 1024 default, and 2048). See all available [embedding models](https://docs.voyageai.com/docs/embeddings) * **Reranking**: Improves search results by reordering them based on relevance to the query. See all available [reranker models](https://docs.voyageai.com/docs/reranker) ## Step 4: Create a Module with Search Capabilities Create an `index.ts` file to tie everything together: ```typescript title="src/server/voyage/index.ts" theme={null} import { Module, ObjectId } from 'modelence/server'; import { z } from 'zod'; import { dbDocuments } from './db'; import { generateEmbedding, rerank } from './voyage'; export default new Module('voyage', { stores: [dbDocuments], queries: { async getDocuments() { return dbDocuments.fetch({}, { sort: { createdAt: -1 }, limit: 50, }); }, async searchSimilar(args) { const { query } = z.object({ query: z.string(), }).parse(args); // Generate embedding for the query const queryEmbedding = await generateEmbedding(query, 'query'); // Perform vector search using MongoDB const results = await (await dbDocuments.vectorSearch({ field: 'embedding', embedding: queryEmbedding, numCandidates: 100, limit: 10, projection: { content: 1, metadata: 1, createdAt: 1, }, })).toArray(); // Rerank results for better relevance return await rerank(results, 'content', query); }, }, mutations: { async addDocument(args) { const { title, description } = z.object({ title: z.string().min(1), description: z.string().min(1), }).parse(args); // Combine title and description for embedding const content = `${title}\n${description}`; // Generate embedding for the document const embedding = await generateEmbedding(content, 'document'); const result = await dbDocuments.insertOne({ content, metadata: { title, description, }, embedding, createdAt: new Date(), }); return { id: result.insertedId.toString(), content, metadata: { title, description }, createdAt: new Date(), }; }, async deleteDocument(args) { const { id } = z.object({ id: z.string(), }).parse(args); await dbDocuments.deleteOne({ _id: new ObjectId(id) }); return { success: true }; }, }, configSchema: { // 'secret' values are always server-only and masked in the Cloud dashboard; isPublic is not allowed. apiKey: { type: 'secret', default: '', }, }, }); ``` ### Understanding Vector Search The `vectorSearch()` method performs semantic search using MongoDB's vector search capabilities: * **field**: The field containing the embedding vectors * **embedding**: The query embedding to search for * **numCandidates**: Number of candidates to consider (higher = more accurate but slower) * **limit**: Maximum number of results to return * **projection**: Fields to include in results ## Step 5: Include the Module Add the Voyage module to your main server file: ```typescript title="src/server/app.ts" theme={null} import { startApp } from 'modelence/server'; import voyageModule from './voyage'; startApp({ modules: [voyageModule] }); ``` ## Step 6: Configure the API Key You can configure the Voyage AI API key in two ways: ### Option 1: Environment Variable Add to your `.env` file: ```bash theme={null} VOYAGE_API_KEY=your_api_key_here ``` ### Option 2: Module Config Store it securely in MongoDB using Modelence's config system: ```typescript theme={null} import { setConfig } from 'modelence/server'; await setConfig('voyage.apiKey', 'your_api_key_here'); ``` ## Step 7: Build the Frontend Create a React component to interact with your semantic search backend: ```tsx title="src/client/pages/VoyageSearchPage.tsx" theme={null} import { useState } from 'react'; import { useMutation, useQuery } from '@tanstack/react-query'; import { modelenceMutation, modelenceQuery } from 'modelence/client'; interface Document { _id: string; content: string; metadata: { title: string; description: string; }; createdAt: Date; } interface SearchResult extends Document { score: number; } export default function VoyageSearchPage() { const [title, setTitle] = useState(''); const [description, setDescription] = useState(''); const [searchQuery, setSearchQuery] = useState(''); const [searchResults, setSearchResults] = useState([]); const { data: documents, refetch } = useQuery( modelenceQuery('voyage.getDocuments') ); const addDocument = useMutation(modelenceMutation('voyage.addDocument')); const deleteDocument = useMutation(modelenceMutation('voyage.deleteDocument')); const searchSimilar = useMutation(modelenceMutation('voyage.searchSimilar')); const handleAddDocument = async (e: React.FormEvent) => { e.preventDefault(); if (!title.trim() || !description.trim()) return; await addDocument.mutateAsync({ title, description }); setTitle(''); setDescription(''); refetch(); }; const handleSearch = async (e: React.FormEvent) => { e.preventDefault(); if (!searchQuery.trim()) return; const results = await searchSimilar.mutateAsync({ query: searchQuery }); setSearchResults(results as SearchResult[]); }; return (

Semantic Search with Voyage AI

{/* Search Form */}

Search Documents

setSearchQuery(e.target.value)} placeholder="Enter your search query..." className="flex-1 px-4 py-2 border rounded" />
{/* Search Results */} {searchResults.length > 0 && (

Found {searchResults.length} results

{searchResults.map((result) => (

{result.metadata.title}

{result.metadata.description}

Relevance: {(result.score * 100).toFixed(0)}%
))}
)}
{/* Add Document Form */}

Add New Document

setTitle(e.target.value)} placeholder="Document title..." className="w-full px-4 py-2 border rounded" />