### Start Kottster Development Server Source: https://kottster.app/docs/index This command starts the local development server for your Kottster application. It typically runs on localhost:5480, but will use an alternative port if the default is occupied. ```bash npm run dev ``` -------------------------------- ### Create New Kottster Project using CLI Source: https://kottster.app/docs/index This command initializes a new Kottster project. Ensure Node.js v20 or above is installed. The CLI creates a project folder and installs dependencies. You can also create a project in the current directory. ```bash npx @kottster/cli@latest new ``` ```bash npx @kottster/cli new . ``` -------------------------------- ### Navigate to Project Directory Source: https://kottster.app/docs/index After creating a new project, you need to change your current directory to the newly created project folder to access its files and run commands. ```bash cd ``` -------------------------------- ### Start Kottster with Docker Compose Source: https://kottster.app/docs/quickstart-docker Starts the Kottster application containers in detached mode using Docker Compose. This is the recommended method for most users due to its simplicity. ```bash docker-compose up -d ``` -------------------------------- ### Clone Repository with Git Source: https://kottster.app/docs/quickstart-docker Clones the Kottster template repository to a local directory and navigates into it. This is the initial step for both Docker Compose and direct Docker command setups. ```bash git clone https://github.com/kottster/kottster-template-js my-kottster-app cd my-kottster-app ``` -------------------------------- ### Build Kottster Docker Image Source: https://kottster.app/docs/quickstart-docker Builds a Docker image for the Kottster application from the Dockerfile in the current directory. This is a prerequisite for running the application using direct Docker commands. ```bash docker build -t my-kottster-app . ``` -------------------------------- ### Manage Direct Docker Containers Source: https://kottster.app/docs/quickstart-docker Commands to stop, remove, and view logs for Kottster containers started with direct Docker commands. Essential for managing individual containers. ```bash docker stop my-kottster-container ``` ```bash docker rm my-kottster-container ``` ```bash docker logs my-kottster-container ``` -------------------------------- ### Manage Docker Compose Containers Source: https://kottster.app/docs/quickstart-docker Commands to stop and view logs for Kottster containers managed by Docker Compose. Ensures proper lifecycle management of the application stack. ```bash docker-compose down ``` ```bash docker-compose logs ``` -------------------------------- ### Execute Application Scripts in Docker Container (Compose) Source: https://kottster.app/docs/quickstart-docker Executes development or production startup scripts within a running Kottster container managed by Docker Compose. Requires the container to be running. ```bash docker exec -it my-kottster-container /dev.sh ``` ```bash docker exec -it my-kottster-container /prod.sh ``` -------------------------------- ### Customize Kottster Ports with Docker Compose Source: https://kottster.app/docs/quickstart-docker Demonstrates how to modify the port mappings for the Kottster application within the `docker-compose.yml` file. Allows users to specify custom host ports. ```yaml ports: - ":5480" - ":5481" ``` -------------------------------- ### Run Kottster Container with Docker Commands Source: https://kottster.app/docs/quickstart-docker Runs the Kottster application container using direct Docker commands, mapping ports, mounting volumes, and assigning a name. This provides more control over container configuration. ```bash docker run -d --name my-kottster-container \ -p 5480:5480 -p 5481:5481 \ -v $(pwd):/app \ -v /app/node_modules \ my-kottster-app ``` -------------------------------- ### Customize Kottster Ports with Docker Commands Source: https://kottster.app/docs/quickstart-docker Illustrates how to change the host port mappings when running the Kottster container using direct Docker commands. This provides flexibility in port assignment. ```bash docker run -d --name my-kottster-container \ -p :5480 -p :5481 \ -v $(pwd):/app \ -v /app/node_modules \ my-kottster-app ``` -------------------------------- ### Configure MySQL Data Source Source: https://kottster.app/docs/data-sources Example configuration for a MySQL data source in Kottster. This JSON file defines connection type and table-specific configurations like exclusion and operation prevention. ```json { "type": "mysql", "tablesConfig": { "payment_methods": { "excluded": true }, "users": { "excludedColumns": ["password"], "preventInsert": true, "preventUpdate": true, "preventDelete": true } } } ``` -------------------------------- ### Access User Context to Get User's Products (JavaScript) Source: https://kottster.app/docs/custom-pages/api This JavaScript example illustrates how to define a server procedure that accesses user context to fetch products associated with the currently logged-in user. It uses Knex to query the 'products' table based on `user.id` and returns the list of products. ```javascript import { app } from '../../_server/app'; import postgresDataSource from '../../_server/data-sources/postgres_db'; const knex = postgresDataSource.getClient(); const controller = app.defineCustomController({ getMyProducts: async (_, { user }) => { // Fetch products added by the current user const products = await knex('products').where({ user_id: user.id }); // Return products data to the frontend return products; }, }); export default controller; ``` -------------------------------- ### Kottster Data Source Structure Example Source: https://kottster.app/docs/project-structure Demonstrates the file structure for a data source within the `_server/data-sources/` directory. It includes the required `dataSource.json` for configuration and `index.js` for database connection and instance export. ```tree _server/data-sources/ ├── your-data-source-name/ │ ├── dataSource.json │ └── index.js ``` -------------------------------- ### Access User Context to Get User's Products with Types (TypeScript) Source: https://kottster.app/docs/custom-pages/api This TypeScript example shows how to retrieve products belonging to the current user by accessing the user context. It defines a `Product` interface for type safety and uses Knex to query the database for products matching the `user.id`. The procedure returns a promise that resolves to an array of `Product` objects. ```typescript import { app } from '../../_server/app'; import postgresDataSource from '../../_server/data-sources/postgres_db'; interface Product { id: number; name: string; price: number; } const knex = postgresDataSource.getClient(); const controller = app.defineCustomController({ getMyProducts: async (_, { user }): Promise => { // Fetch products added by the current user const products = await knex('products').where({ user_id: user.id }); // Return products data to the frontend return products; }, }); // The Procedures type can be used on the frontend // to get type-safety when calling server procedures. export type Procedures = typeof controller.procedures; export default controller; ``` -------------------------------- ### Fetch Product Data from Database (JavaScript) Source: https://kottster.app/docs/custom-pages/api This JavaScript example shows how to define a server controller to fetch product data by its ID from a PostgreSQL database using Knex. It imports the application instance and the database client, then defines a `getProduct` procedure that queries the 'products' table and returns the result. ```javascript import { app } from '../../_server/app'; // Get Knex client from the defined Postgres data source const knex = postgresDataSource.getClient(); const controller = app.defineCustomController({ getProduct: async ({ productId }) => { // Fetch product by id from the database const product = await knex('products').where({ id: productId }).first(); // Return product data to the frontend return product; }, }); export default controller; ``` -------------------------------- ### Basic SQL Queries for Data Fetching Source: https://kottster.app/docs/table/configuration/raw-sql-queries Examples of basic SQL queries to fetch user data across different database systems. These queries select specific columns and filter by status, ordering by creation date. ```sql SELECT id, name, email, created_at FROM users WHERE status = 'active' ORDER BY created_at DESC ``` ```sql SELECT id, name, email, created_at FROM users WHERE status = 'active' ORDER BY created_at DESC ``` ```sql SELECT id, name, email, created_at FROM users WHERE status = 'active' ORDER BY created_at DESC ``` ```sql SELECT id, name, email, created_at FROM users WHERE status = 'active' ORDER BY created_at DESC ``` -------------------------------- ### Count Queries for Pagination Source: https://kottster.app/docs/table/configuration/raw-sql-queries Provides examples of SQL `COUNT(*)` queries required for pagination. These queries determine the total number of records matching the criteria, enabling accurate pagination controls. ```sql SELECT COUNT(*) FROM users WHERE status = 'active' ``` ```sql SELECT COUNT(*) FROM users WHERE status = 'active' ``` ```sql SELECT COUNT(*) FROM users WHERE status = 'active' ``` ```sql SELECT COUNT(*) FROM users WHERE status = 'active' ``` -------------------------------- ### Call Custom Server Procedure from Frontend (JavaScript) Source: https://kottster.app/docs/table/configuration/api Demonstrates how to call a custom backend server procedure ('sendWelcomeEmail') from the frontend using the `useCallProcedure` hook. It handles success and error logging for the email sending operation. This example assumes a basic setup without explicit type safety for the procedure call. ```tsx import { TablePage, useCallProcedure } from '@kottster/react'; export default () => { // Get the callProcedure function const callProcedure = useCallProcedure(); const handleSendWelcomeEmail = async (userId) => { try { // Call the backend procedure const result = await callProcedure('sendWelcomeEmail', { userId }); if (result.success) { console.log(`Email sent successfully to ${result.sentTo}`); } else { console.error('Failed to send email'); } } catch (error) { console.error('Failed to send email:', error); } }; return ( { handleSendWelcomeEmail(record.id); }, }, ]} /> ); }; ``` -------------------------------- ### Database Connection Configuration with Environment Variables (JavaScript) Source: https://kottster.app/docs/security/database-access Example of configuring a PostgreSQL database connection using environment variables for production. It utilizes `getEnvOrThrow` to safely access the database connection string, falling back to a default for development. ```javascript import { getEnvOrThrow } from '@kottster/common'; import { KnexPgAdapter } from '@kottster/server'; import knex from 'knex'; const client = knex({ client: 'pg', connection: process.env.NODE_ENV === 'development' ? 'postgresql://myuser:mypassword@localhost:5432/mydatabase' : getEnvOrThrow('DB_CONNECTION'), searchPath: ['public'], }); export default new KnexPgAdapter(client); ``` -------------------------------- ### Custom Data Fetcher with Pagination in JS Source: https://kottster.app/docs/table/configuration/custom-data-fetcher This example shows how to implement pagination in a custom data fetcher. It fetches data from an external API and returns both the records and the total count for pagination. ```javascript import { app } from '../../_server/app'; const controller = app.defineTableController({ customDataFetcher: async ({ page, pageSize }) => { // Calculate offset for pagination const offset = (page - 1) * pageSize; // Fetch data from external API const response = await fetch( `https://dummyjson.com/products?limit=${pageSize}&skip=${offset}` ); const data = await response.json(); return { records: data.products, total: data.total }; }, }); export default controller; ``` -------------------------------- ### Kottster App Page Structure Example Source: https://kottster.app/docs/project-structure Illustrates the expected file organization for a single page within the `pages/` directory of a Kottster app. It shows the mandatory `page.json` and optional `index.jsx` (frontend component) and `api.server.js` (backend logic) files. ```tree pages/ ├── order-management/ │ ├── page.json ├── user-management/ │ ├── page.json │ ├── index.jsx └── dashboard/ ├── page.json ├── index.jsx └── api.server.js ``` -------------------------------- ### Basic Modal Usage with JSX Source: https://kottster.app/docs/ui/modal-component Demonstrates how to use the Modal component in a React application. It shows how to control the modal's visibility using state and provides a basic structure for the modal's title and content. This example assumes the availability of the 'Page' and 'Modal' components from '@kottster/react'. ```jsx import { Page, Modal } from '@kottster/react'; export default () => { const [isModalOpen, setIsModalOpen] = useState(false); return ( Hello, this is the content of the page. {isModalOpen && ( setIsModalOpen(false)} > This is the content of the modal. )} ); }; ``` -------------------------------- ### Pass Parameters to Backend Procedures with useCallProcedure (JavaScript) Source: https://kottster.app/docs/custom-pages/calling-api Illustrates how to pass parameters to a backend procedure using the `useCallProcedure` hook. The parameters are provided as the second argument to the `callProcedure` function. This example calls 'getProduct' with an ID and displays the product information if available. ```tsx import { useState } from 'react'; import { useCallProcedure, Page } from '@kottster/react'; export default () => { const callProcedure = useCallProcedure(); const [product, setProduct] = useState(null); const loadProduct = async (productId) => { // Pass parameters in the second argument const result = await callProcedure('getProduct', { id: productId }); setProduct(result); }; return ( {product && (

{product.name}

Price: ${product.price}

)}
); }; ``` -------------------------------- ### Fetch Product Data from Database with Types (TypeScript) Source: https://kottster.app/docs/custom-pages/api This TypeScript example demonstrates fetching product data by ID from a PostgreSQL database. It includes type definitions for input and product data, enhancing type safety. Similar to the JavaScript version, it uses Knex for database operations and defines a `getProduct` procedure within a custom controller. ```typescript import { app } from '../../_server/app'; import postgresDataSource from '../../_server/data-sources/postgres_db'; interface GetProductInput { productId: number; } interface Product { id: number; name: string; price: number; } // Get Knex client from the defined Postgres data source const knex = postgresDataSource.getClient(); const controller = app.defineCustomController({ getProduct: async ({ productId }: GetProductInput): Promise => { // Fetch product by id from the database const product = await knex('products').where({ id: productId }).first(); // Return product data to the frontend return product; }, }); // The Procedures type can be used on the frontend // to get type-safety when calling server procedures. export type Procedures = typeof controller.procedures; export default controller; ``` -------------------------------- ### Custom Data Fetcher with Search in JS Source: https://kottster.app/docs/table/configuration/custom-data-fetcher This example demonstrates how to add search functionality to a custom data fetcher. It checks for a search term and modifies the API request accordingly, returning paginated results. ```javascript import { app } from '../../_server/app'; const controller = app.defineTableController({ customDataFetcher: async ({ page, pageSize, search }) => { const offset = (page - 1) * pageSize; let url = `https://dummyjson.com/products?limit=${pageSize}&skip=${offset}`; // Add search parameter if provided if (search) { url = `https://dummyjson.com/products/search?q=${encodeURIComponent(search)}&limit=${pageSize}&skip=${offset}`; } const response = await fetch(url); const data = await response.json(); return { records: data.products, total: data.total }; }, }); export default controller; ``` -------------------------------- ### Define Table Controller with Nested Table Validation (TypeScript) Source: https://kottster.app/docs/table/configuration/api This example shows how to configure both a main table and a nested table using `defineTableController` in a TypeScript file. It includes separate validation logic for inserting records into the main table (email format) and a nested table (order amount validation). ```typescript import { app } from '../../_server/app'; const controller = app.defineTableController({ // Additional configuration for the main table validateRecordBeforeInsert: (values) => { if (!values.email.includes('@')) { throw new Error('Invalid email'); } return true; }, nested: { orders__p__user_id: { // Additional configuration for the nested table validateRecordBeforeInsert: (values) => { if (!values.amount || values.amount <= 0) { throw new Error('Amount must be greater than zero'); } return true; }, }, }, }); export default controller; ``` -------------------------------- ### Call Custom Server Procedure from Frontend (TypeScript) Source: https://kottster.app/docs/table/configuration/api Demonstrates type-safe calling of a custom backend server procedure ('sendWelcomeEmail') from the frontend using the `useCallProcedure` hook. It handles success and error logging and utilizes TypeScript generics for procedure type safety. This example imports the `Procedures` type from the server API definition. ```tsx import { TablePage, useCallProcedure } from '@kottster/react'; import { type Procedures } from './api.server'; export default () => { // Get the type-safe callProcedure function const callProcedure = useCallProcedure(); const handleSendWelcomeEmail = async (userId: number) => { try { // Call the bakend procedure const result = await callProcedure('sendWelcomeEmail', { userId }); if (result.success) { console.log(`Email sent successfully to ${result.sentTo}`); } else { console.error('Failed to send email'); } } catch (error) { console.error('Failed to send email:', error); } }; return ( { handleSendWelcomeEmail(record.id); }, }, ]} /> ); }; ``` -------------------------------- ### Basic SQL Query for Stats (MySQL, PostgreSQL, SQLite, MS SQL) Source: https://kottster.app/docs/dashboard/configuration/raw-sql-queries This SQL query is used to fetch a single numeric value for display as a statistic. It must return exactly one row and one column. Examples are provided for common SQL database systems. ```sql SELECT COUNT(*) FROM orders ``` ```sql SELECT COUNT(*) FROM orders ``` ```sql SELECT COUNT(*) FROM orders ``` ```sql SELECT COUNT(*) FROM orders ``` -------------------------------- ### SQL Queries with Pagination Support Source: https://kottster.app/docs/table/configuration/raw-sql-queries Demonstrates how to modify SQL queries to incorporate pagination using `:limit` and `:offset` parameters. This is crucial for handling large datasets efficiently. ```sql SELECT id, name, email, created_at FROM users WHERE status = 'active' ORDER BY created_at DESC LIMIT :limit OFFSET :offset ``` ```sql SELECT id, name, email, created_at FROM users WHERE status = 'active' ORDER BY created_at DESC LIMIT :limit OFFSET :offset ``` ```sql SELECT id, name, email, created_at FROM users WHERE status = 'active' ORDER BY created_at DESC LIMIT :limit OFFSET :offset ``` ```sql SELECT id, name, email, created_at FROM users WHERE status = 'active' ORDER BY created_at DESC OFFSET :offset ROWS FETCH NEXT :limit ROWS ONLY ``` -------------------------------- ### GET /api/getPost Source: https://kottster.app/docs/custom-pages/introduction This endpoint fetches a single post from the 'posts' table based on the provided postId. It throws an error if the post is not found. ```APIDOC ## GET /api/getPost ### Description Fetches a post from the database using its ID. ### Method GET ### Endpoint `/api/getPost` ### Parameters #### Query Parameters - **postId** (number) - Required - The ID of the post to retrieve. ### Request Example ```json { "postId": 123 } ``` ### Response #### Success Response (200) - **id** (number) - The unique identifier of the post. - **title** (string) - The title of the post. - **content** (string) - The main content of the post. #### Response Example ```json { "id": 123, "title": "Example Post Title", "content": "This is the content of the example post." } ``` #### Error Response (404) - **message** (string) - "Post not found" ``` -------------------------------- ### Check Kottster Package Versions (Bash) Source: https://kottster.app/docs/upgrading This command lists the currently installed versions of the core Kottster packages in your project. It helps you identify which versions you are using before performing an upgrade. ```bash npm list @kottster/common @kottster/cli @kottster/server @kottster/react ``` -------------------------------- ### Upgrade Kottster Packages to Specific Version (Bash) Source: https://kottster.app/docs/upgrading This command installs a specific version for all core Kottster packages. This is useful for maintaining compatibility or rolling back to a known stable version. ```bash npm install @kottster/common@1.2.3 @kottster/cli@1.2.3 @kottster/server@1.2.3 @kottster/react@1.2.3 --save ``` -------------------------------- ### Fetch, Create, and Delete Products with TanStack React Query and TypeScript Source: https://kottster.app/docs/custom-pages/calling-api This snippet showcases fetching products using `useQuery`, creating a product with `useMutation`, and deleting a product with another `useMutation`. It utilizes `useCallProcedure` for API calls and `queryClient.invalidateQueries` for cache management. The component displays a loading state and a list of products with options to add and delete. ```tsx import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useCallProcedure, Page } from '@kottster/react'; import { type Procedures } from './api.server'; export default () => { const callProcedure = useCallProcedure(); const queryClient = useQueryClient(); // Get products using React Query const { data: products, isLoading } = useQuery({ queryKey: ['products'], queryFn: () => callProcedure('getProducts'), }); // Mutation for creating a new product const createProductMutation = useMutation({ mutationFn: (newProduct: { name: string; price: number }) => callProcedure('createProduct', newProduct), onSuccess: () => { // Invalidate and refetch products after successful creation queryClient.invalidateQueries({ queryKey: ['products'] }); }, }); // Mutation for deleting a product const deleteProductMutation = useMutation({ mutationFn: (productId: number) => callProcedure('deleteProduct', { id: productId }), onSuccess: () => { // Invalidate and refetch products after successful deletion queryClient.invalidateQueries({ queryKey: ['products'] }); }, }); const handleCreateProduct = () => { createProductMutation.mutate({ name: 'New Product', price: 99.99, }); }; const handleDeleteProduct = (productId: number) => { deleteProductMutation.mutate(productId); }; if (isLoading) return
Loading...
; return (
    {products?.map(product => (
  • {product.name} - ${product.price}
  • ))}
); }; ``` -------------------------------- ### Define Custom Server Procedure for Sending Welcome Email (JavaScript) Source: https://kottster.app/docs/table/configuration/api Extends a table controller with a custom server-side procedure named 'sendWelcomeEmail'. This procedure retrieves user email from the database and logs a message indicating email sending. It requires access to the app instance and a postgres data source. ```tsx import { app } from '../../_server/app'; import postgresDataSource from '../../_server/data-sources/postgres_db'; // Get Knex client to interact with the database const knex = postgresDataSource.getClient(); const controller = app.defineTableController({}, { // Define a server-side procedure to send a welcome email sendWelcomeEmail: async ({ userId }) => { // Get user email from the database const user = await knex('users').where({ id: userId }).first(); if (!user) { throw new Error('User not found'); } // Send email logic here... console.log(`[server] Sending welcome email to ${user.email}`); return { success: true, sentTo: user.email }; }, }); export default controller; ``` -------------------------------- ### Create Simple Welcome Page with React Source: https://kottster.app/docs/custom-pages/introduction Defines a basic custom page using React. This page displays a static welcome message and is suitable for simple informational content. It requires the '@kottster/react' library. ```jsx import { Page } from '@kottster/react'; export default () => { return (

Hello, world!

Welcome to your custom Kottster page!

); }; ``` -------------------------------- ### Define Custom Data Fetcher for Stats in Kottster Source: https://kottster.app/docs/dashboard/configuration/custom-data-fetcher This example demonstrates how to define a custom data fetcher for a stat in Kottster. It fetches data from an external API and returns a value for the stat. The `customDataFetcher` function is used within the `stats` configuration of `defineDashboardController`. ```javascript import { app } from '../../_server/app'; const controller = app.defineDashboardController({ stats: [ { key: 'stat_1', // Use the key of the stat you want to customize fetchStrategy: 'customFetch', customDataFetcher: async () => { // Fetch data from any source const response = await fetch('https://dummyjson.com/users'); const data = await response.json(); return { value: data.total, }; }, } ], }); export default controller; ``` -------------------------------- ### Basic Page Component Usage in React (JSX) Source: https://kottster.app/docs/ui/page-component Demonstrates the basic usage of the Page component, rendering a page with a title and content. It requires the '@kottster/react' library. The component accepts a 'title' prop for the page heading and renders its children as the page content. ```jsx import { Page } from '@kottster/react'; export default () => ( Hello, this is the content of the page. ); ``` -------------------------------- ### Implement Custom Post-Authentication Middleware Source: https://kottster.app/docs/app-configuration/identity-provider Adds custom security validation after JWT authentication but before request handling. The middleware receives the authenticated user object and the Express request object. It should throw an error if validation fails. This example uses axios to validate user status via an external API. ```javascript import { createApp } from '@kottster/server'; import schema from '../../kottster-app.json'; import axios from 'axios'; export const app = createApp({ schema, secretKey: process.env.SECRET_KEY, postAuthMiddleware: async (user, req) => { // Validate user status with your external API const response = await axios.get( `https://api.example.com/users/${user.id}/status` ); if (!response.data.success) { throw new Error('User not authorized by external service'); } return true; } }); ``` -------------------------------- ### Define Custom Server Procedure for Sending Welcome Email (TypeScript) Source: https://kottster.app/docs/table/configuration/api Extends a table controller with a type-safe custom server-side procedure named 'sendWelcomeEmail'. This procedure retrieves user email from the database and logs a message indicating email sending. It requires access to the app instance, a postgres data source, and defines an input interface for type safety. ```tsx import { app } from '../../_server/app'; import postgresDataSource from '../../_server/data-sources/postgres_db'; interface SendWelcomeEmailInput { userId: number; } // Get Knex client to interact with the database const knex = postgresDataSource.getClient(); const controller = app.defineTableController({}, { // Define a server-side procedure to send a welcome email sendWelcomeEmail: async ({ userId }: SendWelcomeEmailInput) => { // Get user email from the database const user = await knex('users').where({ id: userId }).first(); if (!user) { throw new Error('User not found'); } // Send email logic here... console.log(`[server] Sending welcome email to ${user.email}`); return { success: true, sentTo: user.email }; }, }); export type Procedures = typeof controller.procedures; export default controller; ``` -------------------------------- ### Define Custom API Controller (JavaScript) Source: https://kottster.app/docs/custom-pages/introduction Sets up a custom API endpoint `getPost` using `defineCustomController`. This endpoint fetches a post from the 'posts' database table based on `postId`. It requires the `@kottster/react` library and a PostgreSQL data source configured with Knex. ```tsx import { app } from '../../_server/app'; import postgresDataSource from '../../_server/data-sources/postgres_db'; const knex = postgresDataSource.getClient(); const controller = app.defineCustomController({ getPost: async ({ postId }) => { const post = await knex('posts').where({ id: postId }).first(); if (!post) { throw new Error('Post not found'); } return post; }, }); export default controller; ``` -------------------------------- ### Configure Kottster Identity Provider with SQLite Source: https://kottster.app/docs/app-configuration/identity-provider Sets up the built-in identity provider using SQLite for authentication. It requires a schema, a secret key, and identity provider configuration including database file name, password hashing algorithm, JWT salt, and root administrator credentials. Keys and salts are auto-generated on project initialization. ```javascript import { createApp, createIdentityProvider } from '@kottster/server'; import schema from '../../kottster-app.json'; export const app = createApp({ schema, secretKey: '', identityProvider: createIdentityProvider('sqlite', { fileName: 'app.db', passwordHashAlgorithm: 'bcrypt', jwtSecretSalt: '', // Root admin credentials (set on first launch) rootUsername: '', rootPassword: '', }), }); ``` -------------------------------- ### SQL Queries for Bar Charts (MySQL, PostgreSQL, SQLite, MS SQL) Source: https://kottster.app/docs/dashboard/configuration/raw-sql-queries These SQL queries are suitable for generating bar charts, requiring a categorical X-axis column and numeric Y-axis column(s). Examples show grouping by status to count orders and calculate average order value. ```sql SELECT status as category, COUNT(*) as order_count, AVG(total) as avg_order_value FROM orders GROUP BY status ORDER BY order_count DESC ``` ```sql SELECT status as category, COUNT(*) as order_count, AVG(total) as avg_order_value FROM orders GROUP BY status ORDER BY order_count DESC ``` ```sql SELECT status as category, COUNT(*) as order_count, AVG(total) as avg_order_value FROM orders GROUP BY status ORDER BY order_count DESC ``` ```sql SELECT status as category, COUNT(*) as order_count, AVG(total) as avg_order_value FROM orders GROUP BY status ORDER BY order_count DESC ``` -------------------------------- ### Define Custom Data Fetcher for Charts in Kottster Source: https://kottster.app/docs/dashboard/configuration/custom-data-fetcher This example shows how to define a custom data fetcher for charts (line, area, bar) in Kottster. The `customDataFetcher` function returns an array of objects, where each object represents a data point with a date and corresponding values. This is configured within the `cards` section of `defineDashboardController`. ```javascript import { app } from '../../_server/app'; const controller = app.defineDashboardController({ cards: [ { key: 'card_1', // Use the key of the card you want to customize fetchStrategy: 'customFetch', customDataFetcher: async () => { // Your custom data fetching logic here return { items: [ { date: '2023-01-01', users_count: 100, orders_count: 200 }, { date: '2023-01-02', users_count: 150, orders_count: 250 }, { date: '2023-01-03', users_count: 200, orders_count: 300 } ] }; }, } ], }); export default controller; ``` -------------------------------- ### Call Backend Procedures with useCallProcedure (JavaScript) Source: https://kottster.app/docs/custom-pages/calling-api Demonstrates the basic usage of the `useCallProcedure` hook to call a backend procedure named 'getProducts'. It retrieves the `callProcedure` function and uses it within an async function triggered by a button click. The result is logged to the console. ```tsx import { useCallProcedure, Page } from '@kottster/react'; export default () => { // Get the callProcedure function const callProcedure = useCallProcedure(); const handleClick = async () => { // Call the backend procedure const result = await callProcedure('getProducts'); console.log(result); }; return ( ); }; ``` -------------------------------- ### Define Custom Controller for Products (JavaScript) Source: https://kottster.app/docs/custom-pages/api Sets up a custom controller to handle product-related requests. The `getProducts` function asynchronously fetches and returns a list of products. This function can be extended to interact with databases or external APIs. ```javascript import { app } from '../../_server/app'; const controller = app.defineCustomController({ getProducts: async () => { // Inside this function you can fetch data // from the database, external API, static file, etc. // And return data to the frontend. return [ { id: 1, name: 'Product 1', price: 100 }, { id: 2, name: 'Product 2', price: 200 }, ]; }, }); export default controller; ``` -------------------------------- ### SQL Queries for Line/Area Charts (MySQL, PostgreSQL, SQLite, MS SQL) Source: https://kottster.app/docs/dashboard/configuration/raw-sql-queries These SQL queries are designed to fetch data for line and area charts. They require an X-axis column (typically date/time) and one or more Y-axis numeric columns. Examples include counting orders and summing revenue, grouped by date. ```sql SELECT DATE(created_at) as date, COUNT(*) as order_count, SUM(total) as revenue FROM orders GROUP BY DATE(created_at) ORDER BY date ``` ```sql SELECT DATE(created_at) as date, COUNT(*) as order_count, SUM(total) as revenue FROM orders GROUP BY DATE(created_at) ORDER BY date ``` ```sql SELECT DATE(created_at) as date, COUNT(*) as order_count, SUM(total) as revenue FROM orders GROUP BY DATE(created_at) ORDER BY date ``` ```sql SELECT CAST(created_at AS DATE) as date, COUNT(*) as order_count, SUM(total) as revenue FROM orders GROUP BY CAST(created_at AS DATE) ORDER BY date ``` -------------------------------- ### Implement Backend Controller (`api.server.js`) Source: https://kottster.app/docs/table/introduction Handles custom backend logic and database interactions for a Kottster table page. This file allows for custom fetching logic, validations, or hooks by extending the base configuration from `page.json` using `defineTableController`. It requires importing the `app` object from `../../_server/app`. ```js import { app } from '../../_server/app'; const controller = app.defineTableController({}); export default controller; ``` -------------------------------- ### Define Custom API Controller (TypeScript) Source: https://kottster.app/docs/custom-pages/introduction Sets up a custom API endpoint `getPost` using `defineCustomController` with TypeScript types. This endpoint fetches a post from the 'posts' database table based on `postId`. It requires the `@kottster/react` library, a PostgreSQL data source, and defines input and output types for the procedure. ```tsx import { app } from '../../_server/app'; import postgresDataSource from '../../_server/data-sources/postgres_db'; interface GetPostInput { postId: number; } export interface Post { id: number; title: string; content: string; } const knex = postgresDataSource.getClient(); const controller = app.defineCustomController({ getPost: async ({ postId }: GetPostInput): Promise => { const post = await knex('posts').where({ id: postId }).first(); if (!post) { throw new Error('Post not found'); } return post; }, }); export type Procedures = typeof controller.procedures; export default controller; ``` -------------------------------- ### Add Custom Columns to Table Source: https://kottster.app/docs/table/customization/custom-columns Demonstrates how to add new columns to a table by providing an array of custom column configurations to the `customColumns` prop. Each configuration specifies the column's key, label, position, and a render function for its content. ```jsx import { TablePage } from '@kottster/react'; export default () => ( ( `${record.first_name} ${record.last_name}` ), }, ]} /> ); ``` -------------------------------- ### Server-Side Procedure for Auto-Called Bulk Actions (Node.js) Source: https://kottster.app/docs/table/customization/custom-bulk-actions Defines a server-side controller with a procedure `sendBulkWelcomeEmails` that is automatically called by the client. It logs the action, iterates through records, simulates sending emails, and returns a success count. This is part of the server-side implementation for auto-calling bulk actions. ```js import { app } from '../../_server/app'; const controller = app.defineTableController({}, { sendBulkWelcomeEmails: async (records) => { console.debug(`[server] Sending welcome emails to ${records.length} users`); // Process each record let successCount = 0; for (const record of records) { try { // Send email logic here console.debug(`Sending email to ${record.email}`); successCount++; } catch (error) { console.error(`Failed to send email to ${record.email}:`, error); } } return { success: true, count: successCount }; } }); export default controller; ``` -------------------------------- ### Basic Custom Data Fetcher in JS Source: https://kottster.app/docs/table/configuration/custom-data-fetcher A simple custom data fetcher that returns static records. It demonstrates the basic structure required for a custom data fetcher without pagination or search. ```javascript import { app } from '../../_server/app'; const controller = app.defineTableController({ customDataFetcher: async () => { // Fetch data from any source const sampleRecords = [ { id: 1, name: 'John Doe', email: 'john@example.com' }, { id: 2, name: 'Jane Smith', email: 'jane@example.com' }, { id: 3, name: 'Bob Johnson', email: 'bob@example.com' }, ]; return { records: sampleRecords, }; }, }); export default controller; ``` -------------------------------- ### Configure Page Visibility and Icon in page.json Source: https://kottster.app/docs/app-configuration/sidebar Manually configure page settings, including the icon and sidebar visibility, directly within a page's `page.json` file. This allows for fine-grained control over how pages appear in the sidebar navigation. Set `hideInSidebar` to `true` to exclude a page. ```json { "type": "custom", "title": "Analytics Dashboard", "icon": "pieChart", "hideInSidebar": false } ```