### Setup Supamode Project Dependencies and Generation Source: https://makerkit.dev/docs/supamode/installation/clone-repository Installs project dependencies and runs the setup generation command using pnpm and turbo. This is part of the manual setup process. ```bash pnpm i pnpm turbo gen setup ``` -------------------------------- ### Automatic Supamode Application Setup Source: https://makerkit.dev/docs/supamode/installation/clone-repository Automatically sets up a new Supamode application. This command simplifies the initial configuration process. Note that SSH must be configured with GitHub for this command to work. ```bash npx create-supamode-app ``` -------------------------------- ### Install pnpm Package Manager Source: https://makerkit.dev/docs/supamode/installation/clone-repository Installs the pnpm package manager globally using npm. This is a prerequisite for managing Supamode project dependencies. ```bash npm i -g pnpm ``` -------------------------------- ### Manually Clone Supamode Repository Source: https://makerkit.dev/docs/supamode/installation/clone-repository Clones the Supamode repository from GitHub using HTTPS. This method is an alternative to the automatic setup and is useful if SSH is not configured. ```bash git clone https://github.com/makerkit/supamode ``` -------------------------------- ### Start Supabase Services Source: https://makerkit.dev/docs/supamode/installation/running-project Starts the Supabase services, which include the Supabase API, Postgres DB, Studio, and InBucket. Requires Docker to be running. The services are accessible on specific local ports. ```bash pnpm run supabase:web:start ``` -------------------------------- ### Supamode Storage Path Template Example Source: https://makerkit.dev/docs/supamode/configuration/storage This example demonstrates a dynamic storage path template for Supamode, incorporating user ID, filename, and extension. It assumes a structure where files are organized within user-specific folders. For flexibility, it's recommended to always include filename and extension in the template. ```text users/{{user_id}}/{{filename}}.{{extension}} ``` -------------------------------- ### Add Upstream Remote for Updates Source: https://makerkit.dev/docs/supamode/installation/clone-repository Adds a new remote named 'upstream' pointing to the official Supamode repository. This allows users to pull updates from the main project. ```bash git remote add upstream git@github.com:makerkit/supamode ``` -------------------------------- ### Example: Get All Audit Logs Source: https://makerkit.dev/docs/supamode/development/audit-logs-api Provides a practical example of calling the `getAuditLogs` method to retrieve the first page of all audit logs and logging the results, including total count and page information. ```typescript // Get all audit logs (first page) const logs = await auditLogsService.getAuditLogs({}); console.log(`Found ${logs.total} total logs`); console.log(`Showing page ${logs.pageIndex + 1} of ${logs.pageCount}`); console.log(`Logs:`, logs.logs); ``` -------------------------------- ### Example: Get Details of a Specific Audit Log Source: https://makerkit.dev/docs/supamode/development/audit-logs-api An example demonstrating how to retrieve and log the details of a specific audit log entry, including its data and associated user information. ```typescript const details = await auditLogsService.getAuditLogDetails({ id: 'audit-log-456' }); console.log('Log details:', details.log); console.log('User info:', details.user); ``` -------------------------------- ### Supamode Table Display Format Examples (Text) Source: https://makerkit.dev/docs/supamode/configuration/tables Examples of configuring display formats for table data in Supamode. These formats allow for dynamic display of column values, including handling nulls, and can incorporate plain text. ```text {name} ``` ```text {name} - {email} ``` ```text {name || 'N/A'} ``` ```text {name || email} ``` -------------------------------- ### Basic Setup of Storage Service Source: https://makerkit.dev/docs/supamode/development/storage-explorer-api Initializes the StorageService for interacting with Supabase storage. It requires a context object, likely from a web framework like Hono, to establish the connection and security context. ```typescript import { createStorageService } from '@kit/storage-explorer'; import { Context } from 'hono'; // Create service instance const storageService = createStorageService(context); ``` -------------------------------- ### Supamode Deployment Architecture Diagram Source: https://makerkit.dev/docs/supamode/installation/technical-details Visual representation of the recommended deployment setup for Supamode, illustrating the interaction between frontend, backend API, and Supabase database, and highlighting key technologies used in each component. ```mermaid graph TD A[Vercel/Railway Frontend] --> B{Vercel/Railway Backend API}; B --> C[Supabase Database]; A -- Static Assets, React App, Edge Caching --> D(Internet); B -- Hono Server, Environment Variables --> E(Server Environment); C -- Supabase Auth, Storage --> F(Supabase Platform); ``` -------------------------------- ### Utility Function Examples (TypeScript) Source: https://makerkit.dev/docs/supamode/development/packages Demonstrates the creation of pure, testable utility functions for formatting and validation. These functions are designed to be imported and tested independently of complex frameworks or dependencies. ```tsx // packages/features/my-feature/src/utils/formatters.ts export function formatCurrency(amount: number, currency = "USD"): string { return new Intl.NumberFormat("en-US", { style: "currency", currency, }).format(amount); } export function truncateText(text: string, maxLength: number): string { if (text.length <= maxLength) return text; return `${text.slice(0, maxLength - 3)}...`; } ``` ```tsx // packages/features/my-feature/src/utils/validators.ts export function isValidEmail(email: string): boolean { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return emailRegex.test(email); } export function sanitizeInput(input: string): string { return input.trim().replace(/[<>]/g, ""); } ``` -------------------------------- ### Pull Updates from Upstream Source: https://makerkit.dev/docs/supamode/installation/clone-repository Pulls the latest changes from the 'main' branch of the 'upstream' remote repository. This command is used to keep the local codebase up-to-date. ```bash git pull upstream main ``` -------------------------------- ### Package.json for Type Exports Source: https://makerkit.dev/docs/supamode/development/packages Example of a package.json file configuring a specific export path for types, enabling consumers to import type definitions separately from runtime code. ```json // package.json { "name": "@kit/my-feature", "exports": { "./types": "./src/types/index.ts" } } ``` -------------------------------- ### Data Permission Examples (TypeScript) Source: https://makerkit.dev/docs/supamode/configuration/rbac Illustrates data-level permissions with varying granularity. Includes table-level permissions for updating blog posts and schema-wide permissions for reading all public data using a wildcard. ```typescript // Table-Level Data Permission { permission_type: "data", name: "Edit Blog Posts", scope: "table", schema_name: "public", table_name: "blog_posts", action: "update" } // Schema-Wide Data Permission { permission_type: "data", name: "Read All Public Data", scope: "table", schema_name: "public", table_name: "*", // Wildcard for all tables action: "select" } ``` -------------------------------- ### Custom Seeds: User Story Format Example (Markdown) Source: https://makerkit.dev/docs/supamode/configuration/rbac Illustrates the 'user story' format for planning permission structures. This method helps define roles, actions, and the business value they provide, ensuring a clear understanding of access requirements. ```markdown As a [role], I need to [action] so that [business value] Examples: - As a Staff Writer, I need to create article drafts so that I can contribute content - As a Senior Editor, I need to publish articles so that content goes live - As a Freelancer, I need to edit my drafts so that I can refine my work ``` -------------------------------- ### Supamode Seed Generator: Editorial CMS Roles Setup Source: https://makerkit.dev/docs/supamode/configuration/rbac An example of creating a seed file to define roles for a content management system, including roles like Editor-in-Chief, Senior Editor, Staff Writer, Freelancer, and Subscriber, along with their configurations. ```typescript import { Account, Permission, PermissionGroup, Role, SupamodeSeedGenerator, } from '../generator'; const app = new SupamodeSeedGenerator(); // ======================================== // SECTION 1: DEFINE ROLES // ======================================== const editorInChiefRole = Role.create({ app, id: 'editor_in_chief', config: { name: 'Editor-in-Chief', description: 'Full editorial control and staff management', rank: 95, // High authority metadata: { department: 'Editorial', can_publish: true } }, }); const seniorEditorRole = Role.create({ app, id: 'senior_editor', config: { name: 'Senior Editor', description: 'Content oversight and team coordination', rank: 80, metadata: { department: 'Editorial', can_assign_stories: true } }, }); const staffWriterRole = Role.create({ app, id: 'staff_writer', config: { name: 'Staff Writer', description: 'Full-time content creator', rank: 60, metadata: { employment_type: 'full_time' } }, }); const freelancerRole = Role.create({ app, id: 'freelancer', config: { name: 'Freelancer', description: 'Contract-based content contributor', rank: 40, metadata: { employment_type: 'contract' } }, }); const subscriberRole = Role.create({ app, id: 'subscriber', config: { name: 'Subscriber', description: 'Registered reader with premium access', rank: 20 }, }); ``` -------------------------------- ### Testing Utilities with Vitest (TypeScript) Source: https://makerkit.dev/docs/supamode/development/packages Shows how to unit test the previously defined utility functions using Vitest. The examples cover testing currency formatting and text truncation, highlighting the ease of testing exported utilities. ```tsx // packages/features/my-feature/src/utils/__tests__/formatters.test.ts import { describe, it, expect } from "vitest"; import { formatCurrency, truncateText } from "../formatters"; describe("formatCurrency", () => { it("formats USD currency correctly", () => { expect(formatCurrency(1234.56)).toBe("$1,234.56"); }); it("handles different currencies", () => { expect(formatCurrency(1000, "EUR")).toContain("1,000"); }); }); describe("truncateText", () => { it("returns original text if under limit", () => { expect(truncateText("short", 10)).toBe("short"); }); it("truncates and adds ellipsis", () => { expect(truncateText("very long text here", 10)).toBe("very lo..."); }); }); ``` -------------------------------- ### Start Development Servers (SPA and Hono API) Source: https://makerkit.dev/docs/supamode/installation/running-project Runs the Vite server for the React application and the Hono API backend. The SPA runs on port 5173 and the Hono API on port 3000. Vite proxies API requests to the Hono server. ```bash pnpm dev ``` -------------------------------- ### Install a package into another Supamode package/app Source: https://makerkit.dev/docs/supamode/development/packages Installs a specified package into another package or application within the monorepo, using the --filter flag to target the destination. ```bash pnpm i "@kit/my-package" --filter app ``` ```bash pnpm i "@kit/my-package" --filter "@kit/utils" ``` -------------------------------- ### Role Hierarchy Example Source: https://makerkit.dev/docs/supamode/configuration/rbac Illustrates a visual hierarchy of roles based on their rank, demonstrating the concept of authority levels within the Supamode permission system. ```text Super Admin (Rank: 100) ← Ultimate system control ├── Admin (Rank: 90) ← System administration ├── Manager (Rank: 70) ← Content management ├── Editor (Rank: 60) ← Content editing └── Viewer (Rank: 50) ← Read-only access ``` -------------------------------- ### API Route Registration Source: https://makerkit.dev/docs/supamode/development/packages Provides an example of how to register API routes for a feature package. It outlines the export function structure and the use of Hono.js. ```APIDOC ## API Route Registration ### Description This section demonstrates the pattern for registering API routes within a feature package. It emphasizes exporting a function that accepts a Hono router instance and adds specific routes to it. ### Method Export Function ### Endpoint N/A (Registration function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```typescript // packages/features/my-feature/src/api/routes/index.ts import { Hono } from 'hono'; import { zValidator } from '@hono/zod-validator'; import { z } from 'zod'; import { createMyFeatureService } from '../services/my-feature.service'; export function registerMyFeatureRoutes(router: Hono) { registerGetItemRoute(router); registerCreateItemRoute(router); registerUpdateItemRoute(router); registerDeleteItemRoute(router); } // Type exports for RPC client usage export type GetItemRoute = ReturnType; export type CreateItemRoute = ReturnType; ``` ### Response #### Success Response (N/A) N/A #### Response Example N/A ``` -------------------------------- ### Fetch Latest Changes and Update Dependencies Source: https://makerkit.dev/docs/supamode/installation/updating-codebase Fetches the latest changes from the 'upstream' repository's 'main' branch and installs updated project dependencies. ```bash git pull upstream main pnpm i ``` -------------------------------- ### Integrating Feature Router into Main App (TypeScript) Source: https://makerkit.dev/docs/supamode/development/packages Shows how to import and integrate a feature's router configuration into the main application's router setup using `createBrowserRouter` and spreading the feature router object. ```typescript // apps/app/src/main.tsx import { createMyFeatureRouter } from "@kit/my-feature/router"; const router = createBrowserRouter([ { path: "/", Component: AppShell, children: [ { path: "/my-feature", ...createMyFeatureRouter(), // Spread the router configuration }, ], }, ]); ``` -------------------------------- ### Reset Supabase Database Source: https://makerkit.dev/docs/supamode/installation/running-project Resets the Supabase database and applies migrations from the specified directory. This command is essential for starting with a clean database or applying new schema changes. ```bash pnpm run supabase:web:reset ``` -------------------------------- ### Get Download URL Source: https://makerkit.dev/docs/supamode/development/storage-explorer-api Generates download URLs for files, automatically handling public and private buckets. Creates signed URLs for private files. ```typescript async getDownloadUrl(params: { bucket: string; path: string; }): Promise ``` ```typescript const downloadUrl = await storageService.getDownloadUrl({ bucket: 'documents', path: 'reports/annual-report.pdf' }); // Use URL for download window.open(downloadUrl, '_blank'); ``` -------------------------------- ### Granularity Levels Example (Text) Source: https://makerkit.dev/docs/supamode/configuration/rbac Provides a textual representation of data permission granularity, showing how permissions can be applied at the schema, table, or even column level within a database. ```text Schema Level: public.* ├── Table Level: public.blog_posts └── Column Level: public.users.email ``` -------------------------------- ### Custom Seeds: Naming Conventions for Roles, Permissions, and Groups (TypeScript) Source: https://makerkit.dev/docs/supamode/configuration/rbac Provides examples of consistent naming patterns for roles, permissions, and permission groups. Adhering to these conventions improves code readability and maintainability. ```typescript // Role naming: [Level]_[Function] 'senior_editor', 'staff_writer', 'content_manager' // Permission naming: [Action]_[Resource] 'create_articles', 'publish_content', 'manage_users' // Group naming: [Domain]_[Scope] 'editorial_management', 'content_creation', 'user_administration' ``` -------------------------------- ### Permission Group Example (TypeScript) Source: https://makerkit.dev/docs/supamode/configuration/rbac Demonstrates the structure of a permission group named 'Content Management'. It bundles several related permissions like editing blog posts and moderating comments for simplified role management. ```typescript // Content Management Group { name: "Content Management", description: "All permissions needed for content creators", permissions: [ "Read All Blog Posts", "Create Blog Posts", "Edit Own Blog Posts", "Upload Media Files", "Moderate Comments" ] } ``` -------------------------------- ### System Permission Example (TypeScript) Source: https://makerkit.dev/docs/supamode/configuration/rbac Defines a system-level permission for managing user accounts. It specifies the permission type, name, the system resource being accessed ('account'), the action allowed ('update'), and a descriptive text. ```typescript // System Permission Example { permission_type: "system", name: "Manage User Accounts", system_resource: "account", // What system resource action: "update", // What action is allowed description: "Can modify user account details" } ``` -------------------------------- ### Get Bucket Contents Source: https://makerkit.dev/docs/supamode/development/storage-explorer-api Lists files and folders within a specified bucket, with options for path filtering, searching, and pagination. It returns file details and pagination metadata. ```typescript async getBucketContents(params: { bucket: string; path?: string; search?: string; page?: number; limit?: number; }): Promise<{ contents: StorageFile[]; pagination: PaginationInfo; }> ``` ```typescript interface StorageFile { name: string; id: string | null; updated_at: string | null; created_at: string | null; last_accessed_at: string | null; metadata: Record | null; isDirectory: boolean; fileType: string; publicUrl?: string; previewUrl?: string; permissions: { canRead: boolean; canUpdate: boolean; canDelete: boolean; canUpload: boolean; }; } ``` ```typescript const result = await storageService.getBucketContents({ bucket: 'documents', path: 'reports/', search: 'annual', page: 1, limit: 25 }); console.log(result.contents); // Array of files and folders console.log(result.pagination); // Pagination metadata ``` -------------------------------- ### Filter Syntax Example in TypeScript Source: https://makerkit.dev/docs/supamode/development/data-explorer-api Demonstrates various filter syntaxes using SQL operators for comparison, text matching, array operations, null checks, date ranges, and JSON field manipulations. ```typescript const filters = { // Basic comparison 'status.eq': 'active', 'age.gte': 18, 'name.contains': 'john', // Array operations 'category.in': ['electronics', 'books'], 'tags.arrayContains': 'featured', // Date operations 'created_at.after': '2024-01-01', 'updated_at.between': ['2024-01-01', '2024-12-31'], // Null checks 'deleted_at.isNull': true, // JSON operations 'metadata.hasKey': 'premium', 'settings.keyEquals': { theme: 'dark' } }; ``` -------------------------------- ### Basic Pagination for Audit Logs (TypeScript) Source: https://makerkit.dev/docs/supamode/development/audit-logs-api Provides examples of how to implement basic pagination for retrieving audit logs, including fetching the first page and subsequent pages, and accessing total page count and current page index. ```typescript const page1 = await auditLogsService.getAuditLogs({ page: 1, limit: 25 }); const page2 = await auditLogsService.getAuditLogs({ page: 2, limit: 25 }); console.log(`Total pages: ${page1.pageCount}`); console.log(`Current page: ${page1.pageIndex + 1}`); ``` -------------------------------- ### Initialize AdminUserService Source: https://makerkit.dev/docs/supamode/development/users-api Demonstrates how to initialize the AdminUserService with the necessary context. This is the first step to interacting with the Users API. ```typescript import { createAdminUserService } from '@kit/users-explorer'; import { Context } from 'hono'; // Create service instance const adminUserService = createAdminUserService(context); ``` -------------------------------- ### Remove Original Git Remote Source: https://makerkit.dev/docs/supamode/installation/clone-repository Removes the default 'origin' remote from the local repository. This is a step in reconfiguring the repository to pull updates from the upstream. ```bash git remote rm origin ``` -------------------------------- ### Example: Get Audit Logs for Specific Account Source: https://makerkit.dev/docs/supamode/development/audit-logs-api An example illustrating the use of `getAuditLogsByAccountId` to retrieve a limited number of audit log entries for a specified account ID and log the total count. ```typescript const accountLogs = await auditLogsService.getAuditLogsByAccountId({ accountId: 'account-123', page: 1, limit: 50 }); console.log(`Account has ${accountLogs.total} audit log entries`); ``` -------------------------------- ### User Creation & Invitation Source: https://makerkit.dev/docs/supamode/development/users-api This section covers the API endpoints for inviting new users and creating new user accounts with passwords. ```APIDOC ## POST /api/users/invite ### Description Sends an invitation email to a new user. ### Method POST ### Endpoint /api/users/invite ### Parameters #### Request Body - **user.email** (string) - Required - Email address of the user to invite ### Response #### Success Response (200) - **success** (boolean) - Indicates if the invitation was sent successfully. ### Response Example ```json { "success": true } ``` ``` ```APIDOC ## POST /api/users/create ### Description Creates a new user account with a password. ### Method POST ### Endpoint /api/users/create ### Parameters #### Request Body - **user.email** (string) - Required - Email address for the new user - **user.password** (string) - Required - Password for the new user - **user.autoConfirm** (boolean) - Required - Whether to auto-confirm the user's email ### Response #### Success Response (200) - **success** (boolean) - Indicates if the user was created successfully. ### Response Example ```json { "success": true } ``` ``` -------------------------------- ### Create a New User Account Source: https://makerkit.dev/docs/supamode/development/users-api Illustrates how to create a new user account with a specified email, password, and an option for auto-confirming their email. ```typescript async createUser(user: { email: string; password: string; autoConfirm: boolean; }): Promise<{ success: boolean }> ``` ```typescript const result = await adminUserService.createUser({ email: 'newuser@example.com', password: 'securepassword123', autoConfirm: true }); if (result.success) { console.log('User created successfully'); } ``` -------------------------------- ### Example: Get Data Permissions in TypeScript Source: https://makerkit.dev/docs/supamode/development/data-explorer-api Illustrates checking permissions for the 'users' table in the 'public' schema and conditionally displaying a create button if the user has create permissions. ```typescript const permissions = await dataExplorerService.getDataPermissions({ schemaName: 'public', tableName: 'users' }); if (permissions.canCreate) { // Show create button } ``` -------------------------------- ### Example: Get Field Values in TypeScript Source: https://makerkit.dev/docs/supamode/development/data-explorer-api Shows how to fetch unique status values from the 'users' table, including top hits, with a limit of 10 results. Logs the retrieved values and top hits to the console. ```typescript const fieldValues = await dataExplorerService.getFieldValues({ schemaName: 'public', tableName: 'users', fieldName: 'status', includeTopHits: true, limit: 10 }); console.log(fieldValues.values); // [{ value: 'active' }, { value: 'inactive' }] console.log(fieldValues.topHits); // [{ value: 'active', count: 150 }] ``` -------------------------------- ### Initialize Audit Logs Service Source: https://makerkit.dev/docs/supamode/development/audit-logs-api Demonstrates how to create an instance of the AuditLogsService using the provided context. This is the initial step before interacting with audit log functionalities. ```typescript import { createAuditLogsService } from '@kit/audit-logs'; import { Context } from 'hono'; // Create service instance const auditLogsService = createAuditLogsService(context); ``` -------------------------------- ### Registering API Routes with Hono Source: https://makerkit.dev/docs/supamode/development/packages Demonstrates how to register routes in the main API application using Hono, including middleware. This snippet shows the basic structure for setting up an API in the application. ```typescript // apps/api/app/routes.ts import { Hono } from 'hono'; import { registerMyFeatureRoutes } from '@kit/my-feature/routes'; const router = new Hono(); // Register authentication middleware first registerAuthMiddleware(router); // Register your feature routes registerMyFeatureRoutes(router); export default router; ``` -------------------------------- ### Get Table Metadata Source: https://makerkit.dev/docs/supamode/development/data-explorer-api Retrieve table structure and configuration information. ```APIDOC ## Get Table Metadata ### Description Retrieve table structure and configuration information. ### Method `getTableMetadata` ### Parameters * `schemaName` (string) - Required - Database schema name (e.g., 'public') * `tableName` (string) - Required - Target table name ### Request Example ```typescript const metadata = await dataExplorerService.getTableMetadata({ schemaName: 'public', tableName: 'users' }); console.log(metadata.table.displayName); // "Users" console.log(metadata.columns.length); // Number of columns ``` ### Response #### Success Response (200) - `table` (TableMetadata) - Metadata about the table - `columns` (ColumnMetadata[]) - Metadata about the columns ``` -------------------------------- ### Get Bucket Contents Source: https://makerkit.dev/docs/supamode/development/storage-explorer-api Retrieves the contents of a bucket, including file names and their associated permissions. ```typescript // Automatically used by getBucketContents const contents = await storageService.getBucketContents({ bucket: 'documents', path: 'reports/' }); // Each file includes permission information contents.contents.forEach(file => { console.log(file.name, file.permissions); }); ``` -------------------------------- ### Supamode Data Flow Overview Source: https://makerkit.dev/docs/supamode/installation/technical-details Illustrates the data flow within the Supamode application, from user interaction to database calls via TanStack Query and Hono RPC. ```text User Interaction → React Component → TanStack Query → Hono RPC → Database ↑ Type-safe API calls ``` -------------------------------- ### Audit Logging of Data Modifications Source: https://makerkit.dev/docs/supamode/development/data-explorer-api Shows an example where data modifications are automatically logged for audit purposes. ```typescript // This operation will be logged in the audit trail const result = await dataExplorerService.updateRecord({ schemaName: 'public', tableName: 'users', id: 'user-123', data: { status: 'inactive' } }); ``` -------------------------------- ### GET /v1/my-feature/:id Source: https://makerkit.dev/docs/supamode/development/packages Retrieves a specific item by its ID. Includes input validation using Zod and error handling. ```APIDOC ## GET /v1/my-feature/:id ### Description Fetches a specific item from the `/v1/my-feature` resource using its unique identifier. This endpoint validates the provided ID using a UUID schema. ### Method GET ### Endpoint /v1/my-feature/:id ### Parameters #### Path Parameters - **id** (string) - Required - The unique identifier (UUID) of the item to retrieve. #### Query Parameters None #### Request Body None ### Request Example ```bash GET /v1/my-feature/123e4567-e89b-12d3-a456-426614174000 ``` ### Response #### Success Response (200) - **success** (boolean) - Indicates if the operation was successful. - **data** (object) - The retrieved item data. #### Error Response (404) - **error** (string) - Message indicating the item was not found. #### Error Response (500) - **success** (boolean) - Indicates if the operation was successful. - **error** (string) - A user-friendly error message. #### Response Example ```json { "success": true, "data": [ { "id": "123e4567-e89b-12d3-a456-426614174000", "name": "Example Item" } ] } ``` ``` -------------------------------- ### Set Supabase Connection Details in apps/api/.env Source: https://makerkit.dev/docs/supamode/installation/running-project Configures the Supabase URL and database connection URL for the API. This is crucial for backend operations. ```bash SUPABASE_URL=http://localhost:54321 SUPABASE_DATABASE_URL=postgresql://postgres:postgres@127.0.0.1:54322/postgres ``` -------------------------------- ### Get Public URL Source: https://makerkit.dev/docs/supamode/development/storage-explorer-api Generates public URLs for files stored in public buckets, which can be used directly in web applications. ```typescript async getPublicUrl(params: { bucket: string; path: string; }): Promise ``` ```typescript const publicUrl = await storageService.getPublicUrl({ bucket: 'public-assets', path: 'images/logo.png' }); // URL can be used directly in tags ``` -------------------------------- ### Supamode Backend Service Layer Pattern Source: https://makerkit.dev/docs/supamode/installation/technical-details Demonstrates the typical pattern for backend operations in Supamode, involving API Routes, Service Classes, Drizzle ORM, and PostgreSQL. ```text API Route → Service Class → Drizzle ORM → PostgreSQL ``` -------------------------------- ### Documented Complex Type Definition Source: https://makerkit.dev/docs/supamode/development/packages Shows an example of a complex interface with JSDoc comments for better documentation and understanding of its properties and purpose. ```tsx // ✅ Good - documented complex type /** * Configuration for the my-feature widget * @property enabled - Whether the feature is active * @property maxItems - Maximum number of items to display * @property refreshInterval - How often to refresh data (in ms) */ export interface MyFeatureWidgetConfig { enabled: boolean; maxItems: number; refreshInterval?: number; } ``` -------------------------------- ### Service Layer Pattern Source: https://makerkit.dev/docs/supamode/development/packages Illustrates the recommended service layer pattern for keeping Hono routes concise by delegating business logic to dedicated service classes. ```APIDOC ## Service Layer Pattern ### Description This pattern suggests separating business logic from Hono route handlers by creating service classes. This keeps the routes thin and promotes reusability of business logic. ### Method Class Methods ### Endpoint N/A (Service Layer) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```typescript // packages/features/my-feature/src/api/services/my-feature.service.ts import { Context } from "hono"; import { getSupabaseDrizzleClient } from "@kit/supabase/clients/drizzle-client"; export function createMyFeatureService(context: Context) { return new MyFeatureService(context); } class MyFeatureService { constructor(private readonly context: Context) { } async getItem(id: string) { const db = await getSupabaseDrizzleClient(this.context); // Business logic using Drizzle ORM return this.db.select().from(myTable).where(eq(myTable.id, id)); } async createItem(data: CreateItemInput) { const db = await getSupabaseDrizzleClient(this.context); // Complex business logic here return this.db.insert(myTable).values(data).returning(); } } ``` ### Response #### Success Response (N/A) N/A #### Response Example N/A ``` -------------------------------- ### Get Signed URL Source: https://makerkit.dev/docs/supamode/development/storage-explorer-api Generates temporary signed URLs for private files, with an optional expiration time. Useful for time-limited access. ```typescript async getSignedUrl(params: { bucket: string; path: string; expiresIn?: number; }): Promise ``` ```typescript const signedUrl = await storageService.getSignedUrl({ bucket: 'private-documents', path: 'contracts/agreement.pdf', expiresIn: 7200 // 2 hours }); // URL expires after 2 hours ``` -------------------------------- ### GET /api/getDataPermissions Source: https://makerkit.dev/docs/supamode/development/data-explorer-api Checks and returns the user's permissions (create, update, delete) for a specific table within a given schema. ```APIDOC ## GET /api/getDataPermissions ### Description Checks and returns the user's permissions (create, update, delete) for a specific table within a given schema. ### Method GET ### Endpoint `/api/getDataPermissions` ### Parameters #### Path Parameters None #### Query Parameters - **schemaName** (string) - Required - The name of the schema containing the table. - **tableName** (string) - Required - The name of the table to check permissions for. ### Request Example ```json { "schemaName": "public", "tableName": "users" } ``` ### Response #### Success Response (200) - **canCreate** (boolean) - Indicates if the user has permission to create records. - **canUpdate** (boolean) - Indicates if the user has permission to update records. - **canDelete** (boolean) - Indicates if the user has permission to delete records. #### Response Example ```json { "canCreate": true, "canUpdate": false, "canDelete": true } ``` ``` -------------------------------- ### Supamode Seed Generator: Core Architecture and SQL Generation Source: https://makerkit.dev/docs/supamode/configuration/rbac Demonstrates the core architecture of the Supamode Seed Generator, including creating entities (roles, permissions), establishing relationships, and generating SQL scripts. ```typescript // Core Architecture const app = new SupamodeSeedGenerator(); // 1. Create entities const role = Role.create({ app, id: 'custom_role', config: {...} }); const permission = Permission.create({ app, id: 'custom_perm', config: {...} }); // 2. Establish relationships role.addPermission(permission); // 3. Generate SQL const sql = app.generateSql(); ``` -------------------------------- ### Server Plugin with Configuration Support Source: https://makerkit.dev/docs/supamode/development/plugins Demonstrates how to add configuration options to a server-side plugin. This includes defining a schema for configuration and accessing it within the transformer. ```typescript // Server plugin with configuration export const configurablePlugin: DataTypeServicePlugin = { // ... other properties configSchema: { showEmail: { type: "boolean", default: true }, statusColors: { type: "object", default: { active: "green", inactive: "gray" }, }, }, transformer: async (data, context) => { const config = context.config as PluginConfig; // Use config.showEmail, config.statusColors, etc. }, }; ``` -------------------------------- ### Bulk Delete Records Source: https://makerkit.dev/docs/supamode/development/data-explorer-api Provides an example of performing efficient bulk delete operations for large datasets, including checking the results of each deletion. ```typescript // Batch delete multiple records const results = await dataExplorerService.batchDeleteRecords({ schemaName: 'public', tableName: 'temporary_records', items: recordsToDelete }); // Check results results.forEach((result, index) => { if (result.success) { console.log(`Record ${index} deleted successfully`); } else { console.error(`Failed to delete record ${index}`); } }); ``` -------------------------------- ### Query & Filtering - Filter Syntax Source: https://makerkit.dev/docs/supamode/development/data-explorer-api Explains the syntax for specifying filters using the `column.operator` format, with examples for various data types and operations. ```APIDOC ## Query & Filtering - Filter Syntax ### Description Explains the syntax for specifying filters using the `column.operator` format, with examples for various data types and operations. ### Filter Syntax Filters are specified using the format `column.operator`: #### Example Filters ```json { "status.eq": "active", "age.gte": 18, "name.contains": "john", "category.in": ["electronics", "books"], "tags.arrayContains": "featured", "created_at.after": "2024-01-01", "updated_at.between": ["2024-01-01", "2024-12-31"], "deleted_at.isNull": true, "metadata.hasKey": "premium", "settings.keyEquals": { "theme": "dark" } } ``` ``` -------------------------------- ### Search Functionality Example in TypeScript Source: https://makerkit.dev/docs/supamode/development/data-explorer-api Demonstrates using the `search` parameter in `queryTableData` to perform a case-insensitive search across all searchable columns in a table. ```typescript const results = await dataExplorerService.queryTableData({ schemaName: 'public', tableName: 'users', search: 'john doe', page: 0, pageSize: 20 }); ``` -------------------------------- ### Admin Protection Example (TypeScript) Source: https://makerkit.dev/docs/supamode/development/users-api Illustrates the protection mechanism for admin accounts, preventing deletion or modification. Attempting to delete an admin account will result in an error. ```typescript // This will throw an error if trying to delete an admin account try { await adminUserService.deleteUser(adminUserId); } catch (error) { console.error('Cannot delete admin account:', error.message); } ``` -------------------------------- ### Seed Database with Demo Schema Source: https://makerkit.dev/docs/supamode/installation/running-project Executes a SQL command within Supabase Studio's SQL Editor to seed the database with test data. This allows immediate use of the application with predefined user roles. ```sql call supamode.install_demo_schema(); ``` -------------------------------- ### Handling Edge Cases in Rendering Source: https://makerkit.dev/docs/supamode/development/plugins Example of handling potential null or undefined values in the 'value' parameter during client-side rendering to prevent runtime errors. ```typescript renderCell: ({ value }) => { // Always handle null/undefined if (!value) return -; // Type-safe property access return
{value.name}
; }; ``` -------------------------------- ### Initialize Data Explorer Service Source: https://makerkit.dev/docs/supamode/development/data-explorer-api Demonstrates how to import and create an instance of the DataExplorerService using the Hono context. This service is essential for interacting with the database. ```typescript import { createDataExplorerService } from '@kit/data-explorer'; import { Context } from 'hono'; // Create service instance const dataExplorerService = createDataExplorerService(context); ``` -------------------------------- ### Recommended Separate Exports Source: https://makerkit.dev/docs/supamode/development/packages Illustrates the recommended approach for separating exports by type (components, routes, hooks, types). This ensures clean code splitting, security, and optimized builds. ```typescript // ✅ GOOD: Separate exports // @kit/my-feature/components - Only React code // @kit/my-feature/routes - Only server code // @kit/my-feature/hooks - Only React hooks // @kit/my-feature/types - Shared types (safe for both) ``` -------------------------------- ### Get User Permissions Source: https://makerkit.dev/docs/supamode/development/storage-explorer-api Checks user permissions for a specific bucket and path. Returns an object indicating read, update, delete, and upload capabilities. ```typescript async getUserPermissions(params: { bucket: string; path: string; }): Promise<{ canRead: boolean; canUpdate: boolean; canDelete: boolean; canUpload: boolean; }> ``` ```typescript const permissions = await storageService.getUserPermissions({ bucket: 'documents', path: 'reports/sensitive.pdf' }); if (permissions.canRead) { // User can view this file } ``` -------------------------------- ### Generate Supamode Plugin Package using Turbo Source: https://makerkit.dev/docs/supamode/development/plugins This command scaffolds a new plugin package structure for Supamode using the Turbo generator. It sets up essential files like package.json and tsconfig.json. ```bash # From project root turbo gen plugin ``` -------------------------------- ### Transaction Safety Example Source: https://makerkit.dev/docs/supamode/development/data-explorer-api Demonstrates how operations are automatically wrapped in database transactions to ensure data consistency. If an operation fails, the transaction is rolled back. ```typescript // All operations are automatically wrapped in transactions const result = await dataExplorerService.insertRecord({ schemaName: 'public', tableName: 'orders', data: orderData }); // If the operation fails, the transaction is automatically rolled back ``` -------------------------------- ### Sorting Example in TypeScript Source: https://makerkit.dev/docs/supamode/development/data-explorer-api Illustrates how to sort query results by a specific column in a specified direction (ascending or descending) using `sortColumn` and `sortDirection` parameters. ```typescript const results = await dataExplorerService.queryTableData({ schemaName: 'public', tableName: 'users', sortColumn: 'created_at', sortDirection: 'desc', page: 0, pageSize: 20 }); ``` -------------------------------- ### Hono Service Layer Pattern Source: https://makerkit.dev/docs/supamode/development/packages Demonstrates a service layer pattern for Hono routes, delegating business logic to dedicated service classes. This keeps routes thin and promotes code organization. It shows how to create a service instance and implement methods for data retrieval and manipulation using a database client. ```tsx import { Context } from "hono"; import { getSupabaseDrizzleClient } from "@kit/supabase/clients/drizzle-client"; export function createMyFeatureService(context: Context) { return new MyFeatureService(context); } class MyFeatureService { constructor(private readonly context: Context) { } async getItem(id: string) { const db = await getSupabaseDrizzleClient(this.context); // Business logic using Drizzle ORM return this.db.select().from(myTable).where(eq(myTable.id, id)); } async createItem(data: CreateItemInput) { const db = await getSupabaseDrizzleClient(this.context); // Complex business logic here return this.db.insert(myTable).values(data).returning(); } } ``` -------------------------------- ### Supamode Seed Generator: Basic Seed File Structure Source: https://makerkit.dev/docs/supamode/configuration/rbac Illustrates the basic structure of a Supamode seed file, including importing generator classes, initializing the generator, defining the structure, and exporting the configured generator. ```typescript // 1. Import the generator classes import { Account, Permission, PermissionGroup, Role, SupamodeSeedGenerator } from '../generator'; // 2. Initialize the generator const app = new SupamodeSeedGenerator(); // 3. Define your structure (accounts, roles, permissions, groups) // ... your custom definitions ... // 4. Export the configured generator export default app; ``` -------------------------------- ### Example: Batch Delete Records in TypeScript Source: https://makerkit.dev/docs/supamode/development/data-explorer-api Demonstrates the usage of the `batchDeleteRecords` function by deleting user records with specific IDs from the 'users' table in the 'public' schema. ```typescript const results = await dataExplorerService.batchDeleteRecords({ schemaName: 'public', tableName: 'users', items: [ { id: 'user-1' }, { id: 'user-2' }, { id: 'user-3' } ] }); ``` -------------------------------- ### Set Supabase URL in apps/app/.env Source: https://makerkit.dev/docs/supamode/installation/running-project Configures the Supabase URL for the frontend application. This variable is typically used by Vite. ```bash VITE_SUPABASE_URL=http://localhost:54321 ``` -------------------------------- ### Solo Developer Template Seed (solo-seed.ts) Source: https://makerkit.dev/docs/supamode/configuration/permissions-templates This template is designed for individual developers starting a new project. It provides a basic structure and configuration suitable for solo development. ```typescript /// import { supabaseClient, SupabaseClient, } from "@supabase/supabase-js"; // Types interface User { id: string; email: string; } interface Profile { id: string; username: string; avatar_url: string | null; } interface App { id: string; name: string; } // Functions async function getUser(client: SupabaseClient): Promise { const { data } = await client.auth.getUser(); return data?.user || null; } async function getProfile(client: SupabaseClient, userId: string): Promise { const { data } = await client.from("profiles").select("*").eq("id", userId).single(); return data; } async function getApps(client: SupabaseClient): Promise { const { data } = await client.from("apps").select("*"); return data || []; } // Example Usage async function main() { const client = supabaseClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY! ); const user = await getUser(client); if (user) { console.log("Logged in as:", user.email); const profile = await getProfile(client, user.id); if (profile) { console.log("Profile:", profile.username); } } else { console.log("Not logged in."); } const apps = await getApps(client); console.log("Available apps:", apps); } main(); ```