Skip to content

Latest commit

 

History

History
789 lines (579 loc) · 21.3 KB

File metadata and controls

789 lines (579 loc) · 21.3 KB

API Reference

Complete API documentation for @gridatek/nx-supabase

Table of Contents


Generators

Generators are used to scaffold new projects and configurations.

init Generator

Initializes the @gridatek/nx-supabase plugin in your workspace.

Usage:

npx nx g @gridatek/nx-supabase:init [options]

Options:

Option Type Default Description
--skipPackageJson boolean false Skip adding Supabase CLI to package.json devDependencies

What it does:

  1. Adds supabase CLI (^2.65.6) to devDependencies (unless --skipPackageJson is true)
  2. Registers @gridatek/nx-supabase plugin in nx.json
  3. Returns a callback to install dependencies

Example:

# Standard initialization
npx nx g @gridatek/nx-supabase:init

# Skip package.json modification (manual Supabase CLI installation)
npx nx g @gridatek/nx-supabase:init --skipPackageJson

Notes:

  • This generator is automatically run when using nx add @gridatek/nx-supabase
  • The plugin won't be added twice if it already exists in nx.json

project Generator

Creates a new Supabase project in your workspace.

Usage:

npx nx g @gridatek/nx-supabase:project <name> [options]

Arguments:

Argument Type Required Description
name string Yes The name of the Supabase project

Options:

Option Type Default Description
--directory string project name Directory where the project will be created. Defaults to project name if not specified
--environments string undefined Comma-separated list of additional environments to create (beyond production and local)

What it creates:

<project-root>/
├── production/              # Base configuration (always created)
│   └── config.toml          # Supabase configuration (generated by callback)
├── local/                   # Local environment (always created, empty)
├── [additional-envs]/       # Any additional environments specified (empty)
├── .generated/              # Build output directory
│   └── .gitkeep
├── .gitignore               # Ignores .generated/
├── README.md                # Project documentation
└── project.json             # Nx project configuration

Note: The generator creates empty environment directories. Users create migrations/ and seeds/ subdirectories as needed.

Examples:

# Basic project (defaults to project name as directory in the root)
npx nx g @gridatek/nx-supabase:project my-supabase
# Creates at: my-supabase/ (in the root)

# Custom directory (project name ≠ folder name)
npx nx g @gridatek/nx-supabase:project my-supabase --directory=apps/backend/supabase
# Creates at: apps/backend/supabase/
# Run with: nx run my-supabase:start

# Or match folder name to project name
npx nx g @gridatek/nx-supabase:project my-supabase --directory=apps/my-api/my-supabase
# Creates at: apps/my-api/my-supabase/

# With additional environments
npx nx g @gridatek/nx-supabase:project my-supabase \
  --directory=apps/backend/supabase \
  --environments=staging,qa,dev
# Creates at: apps/backend/supabase/

Environment Behavior:

  • production and local are always created by default
  • Use --environments to add additional environments like staging, qa, dev, etc.
  • If you specify production or local in --environments, they will be filtered out (no duplicates)

Project Configuration:

Creates a project.json with:

{
  "name": "my-supabase",
  "root": "my-supabase",
  "projectType": "application",
  "sourceRoot": "my-supabase"
}

Targets (build, start, stop, run-command) are inferred by the plugin, not explicitly defined.


Executors

Executors are used to run tasks on your Supabase projects.

build Executor

Builds environment configurations by merging production config with environment-specific files.

Usage:

npx nx run <project>:build

Schema:

interface BuildExecutorSchema {
  // No options - configuration is derived from project structure
}

Behavior:

  1. Locates the project root from Nx context
  2. Finds all environment directories (excludes .generated/ and hidden directories)
  3. For each environment except production:
    • Cleans .generated/<env>/ directory
    • Copies files from production/ (base configuration)
    • Overlays files from <env>/ (environment-specific overrides)
    • Skips .gitkeep files
  4. All environments are built to .generated/<env>/supabase/

Output:

  • .generated/<env>/supabase/ for all environments
  • Cached by Nx for faster rebuilds

Inputs (for caching):

  • All files in environment directories: {projectRoot}/<env>/**/*

Outputs (for caching):

  • {projectRoot}/.generated

Example:

# Build all environments
npx nx run my-api:build

# Build with verbose logging
npx nx run my-api:build --verbose

# Clear cache and rebuild
npx nx run my-api:build --skip-nx-cache

Notes:

  • Automatically runs before start target (via dependsOn)
  • Uses Nx caching for fast incremental builds
  • Safe to run multiple times (cleans before building)

start Executor

Starts a Supabase instance using the Supabase CLI.

Usage:

npx nx run <project>:start [options]

Schema:

interface StartExecutorSchema {
  env?: string;  // Default: 'local'
}

Options:

Option Type Default Description
--env string 'local' Environment to use (local, production, staging, etc.)

Behavior:

  1. Runs build target first (via dependsOn)
  2. Determines working directory:
    • All environments: Uses .generated/<env>/supabase/
  3. Validates that config.toml exists
  4. Executes supabase start in the appropriate directory
  5. Streams output to console
  6. Waits for process to complete

Examples:

# Start with default local environment
npx nx run my-api:start

# Start with production configuration
npx nx run my-api:start --env=production

# Start with staging environment
npx nx run my-api:start --env=staging

Notes:

  • Requires Docker to be running
  • First run may take several minutes to download Docker images
  • Process runs in foreground by default
  • Use Ctrl+C to stop, or use the stop target

Error Handling:

  • Returns { success: false } if environment directory doesn't exist
  • Suggests running build target if .generated/<env> is missing
  • Returns exit code from Supabase CLI

stop Executor

Stops a running Supabase instance.

Usage:

npx nx run <project>:stop [options]

Schema:

interface StopExecutorSchema {
  env?: string;  // Default: 'local'
}

Options:

Option Type Default Description
--env string 'local' Environment to stop (local, production, staging, etc.)

Behavior:

  1. Determines working directory (same logic as start)
  2. Validates environment exists
  3. Executes supabase stop --no-backup in the appropriate directory
  4. Streams output to console

Examples:

# Stop local environment
npx nx run my-api:stop

# Stop production environment
npx nx run my-api:stop --env=production

Notes:

  • Uses --no-backup flag to avoid creating database dumps
  • Safe to run even if Supabase is not running
  • Stops Docker containers for the specific project

gen-types Executor

Generates TypeScript types from your Supabase database schema.

Usage:

npx nx run <project>:gen-types [options]

Schema:

interface GenTypesExecutorSchema {
  projectId?: string;   // Remote project ID (if not provided, uses local)
  outputPath?: string;  // Output file path (default: 'database.types.ts')
  schema?: string;      // Comma-separated list of schemas (e.g., 'public,auth')
}

Options:

Option Type Default Description
--projectId string - Supabase project ID. If not provided, generates types from local database
--outputPath string 'database.types.ts' Output file path relative to workspace root
--schema string - Comma-separated list of schemas to include (e.g., 'public,auth')

Behavior:

  1. Runs build target first (via dependsOn)
  2. Determines mode based on projectId:
    • Local mode (no projectId): Uses .generated/local/supabase/ directory
    • Remote mode (with projectId): Uses project root directory
  3. Validates environment directory exists (local mode only)
  4. Executes supabase gen types typescript with appropriate flags
  5. Captures stdout and writes to output file
  6. Creates output directory if needed

Examples:

# Generate types from local database (default)
npx nx run my-api:gen-types

# Generate types with custom output path
npx nx run my-api:gen-types --outputPath=src/types/database.types.ts

# Generate types from remote project
npx nx run my-api:gen-types --projectId=abcdefghijklmnop

# Generate types for specific schemas
npx nx run my-api:gen-types --schema=public,auth

# Combine options
npx nx run my-api:gen-types \
  --projectId=abcdefghijklmnop \
  --outputPath=libs/shared/types/src/database.types.ts \
  --schema=public

Notes:

  • For local mode, ensure Supabase is running (nx run <project>:start)
  • For remote mode, ensure you're authenticated (supabase login)
  • Output file is relative to workspace root, not project root
  • The executor automatically creates parent directories if they don't exist

Error Handling:

  • Returns { success: false } if local environment doesn't exist
  • Suggests running build target if .generated/local is missing
  • Returns failure if Supabase CLI command fails

run-command Executor

Runs any arbitrary Supabase CLI command in the appropriate environment context.

Usage:

npx nx run <project>:run-command --command="<supabase-command>" [options]

Schema:

interface RunCommandExecutorSchema {
  command: string | string[];  // Required: Supabase CLI command to run
  env?: string;                // Default: 'local'
}

Options:

Option Type Default Required Description
--command string or string[] - Yes Supabase CLI command to execute
--env string 'local' No Environment context (local, production, staging, etc.)

Behavior:

  1. Determines working directory based on environment
  2. Validates environment directory and config exist
  3. Parses command string (or joins array)
  4. Executes command via npx in shell mode
  5. Streams stdout/stderr to console
  6. Returns success/failure based on exit code

Examples:

# Check status
npx nx run my-api:run-command --command="supabase status"

# Create a new migration
npx nx run my-api:run-command --command="supabase migration new create_users"

# Reset database
npx nx run my-api:run-command --command="supabase db reset"

# Run migration up
npx nx run my-api:run-command --command="supabase db push"

# With specific environment
npx nx run my-api:run-command \
  --env=staging \
  --command="supabase db diff --use-migra"

# Array format (useful in project.json)
npx nx run my-api:run-command \
  --command="['supabase', 'migration', 'new', 'my_table']"

Common Commands:

Command Description
supabase status Show status of all services
supabase start Start Supabase (prefer using start target)
supabase stop Stop Supabase (prefer using stop target)
supabase db reset Reset database to initial state
supabase db push Apply pending migrations
supabase db diff Show SQL diff
supabase migration new <name> Create new migration
supabase gen types typescript Generate TypeScript types (prefer using gen-types executor)
supabase functions new <name> Create new Edge Function
supabase link --project-ref <ref> Link to remote project

Notes:

  • Runs in shell mode, so shell operators (pipes, redirects) are supported
  • Working directory is set to environment directory
  • All Supabase CLI commands available
  • Return value indicates success/failure of command

push-db-functions Executor

Pushes all SQL files in db_functions/ to a Postgres database. Intended for idempotent definitions (CREATE OR REPLACE FUNCTION, CREATE OR REPLACE VIEW, RLS policy resets, etc.) that you want re-applied on every deploy without creating a migration.

Unlike supabase db query --file, this executor uses the pg driver's simple-query protocol, so files containing multiple statements — including function bodies with $$ ... $$ delimiters — are supported.

Usage:

npx nx run <project>:push-db-functions [options]

Schema:

interface PushDbFunctionsExecutorSchema {
  env?: string;           // Default: 'local'
  functionsDir?: string;  // Override directory (relative to workspace root or absolute)
  dbUrl?: string;         // Postgres connection string
}

Options:

Option Type Default Description
--env string 'local' Environment to use. The executor reads SQL from .generated/<env>/supabase/db_functions/
--functionsDir string Override directory containing .sql files. Relative paths resolve from the workspace root
--dbUrl string Postgres connection string. Overrides $SUPABASE_DB_URL and auto-discovery

Behavior:

  1. Runs build target first (via dependsOn)
  2. Resolves the functions directory (option override, else .generated/<env>/supabase/db_functions/ under project root)
  3. Resolves the database URL in this order:
    • --dbUrl option
    • $SUPABASE_DB_URL env var
    • supabase status -o env in the environment directory (local mode)
  4. Collects *.sql files sorted alphabetically
  5. Connects via pg.Client, executes each file as a single simple query, closes the connection

Examples:

# Push local functions (auto-discovers DB URL from `supabase status`)
npx nx run my-api:push-db-functions

# Push to staging with explicit URL
SUPABASE_DB_URL="postgresql://..." npx nx run my-api:push-db-functions --env=staging

# Custom functions directory
npx nx run my-api:push-db-functions --functionsDir=custom/sql/

CI Usage:

In GitHub Actions, pass the DB URL via a secret:

- name: Push database functions
  run: npx nx run my-api:push-db-functions --env=production
  env:
    SUPABASE_DB_URL: ${{ secrets.SUPABASE_DB_URL }}

Notes:

  • Files are executed in alphabetical order — prefix them (01_, 02_) if ordering matters
  • Statements run outside an outer transaction, so each file is autonomous
  • Keep these files idempotent (CREATE OR REPLACE, DROP ... IF EXISTS); don't use for migrations

Error Handling:

  • Returns { success: false } if the functions directory doesn't exist
  • Returns { success: false } if no DB URL can be resolved
  • Returns { success: false } on any SQL execution error (connection is closed in a finally)

Plugin Options

Configure the plugin behavior in nx.json.

Schema:

interface SupabasePluginOptions {
  buildTargetName?: string;
  startTargetName?: string;
  stopTargetName?: string;
  runCommandTargetName?: string;
  statusTargetName?: string;
  dbResetTargetName?: string;
  dbPushTargetName?: string;
  dbPullTargetName?: string;
  genTypesTargetName?: string;
  genTypesOutputPath?: string;
  migrationNewTargetName?: string;
  linkTargetName?: string;
  dbDiffTargetName?: string;
  pushDbFunctionsTargetName?: string;
}

Options:

Option Type Default Description
buildTargetName string 'build' Name of the build target
startTargetName string 'start' Name of the start target
stopTargetName string 'stop' Name of the stop target
runCommandTargetName string 'run-command' Name of the run-command target
statusTargetName string 'status' Name of the status target
dbResetTargetName string 'db-reset' Name of the db-reset target
dbPushTargetName string 'db-push' Name of the db-push target
dbPullTargetName string 'db-pull' Name of the db-pull target
genTypesTargetName string 'gen-types' Name of the gen-types target
genTypesOutputPath string 'database.types.ts' Default output path for generated types
migrationNewTargetName string 'migration-new' Name of the migration-new target
linkTargetName string 'link' Name of the link target
dbDiffTargetName string 'db-diff' Name of the db-diff target
pushDbFunctionsTargetName string 'push-db-functions' Name of the push-db-functions target

Example Configuration:

{
  "plugins": [
    {
      "plugin": "@gridatek/nx-supabase",
      "options": {
        "buildTargetName": "supabase-build",
        "startTargetName": "supabase-start",
        "stopTargetName": "supabase-stop",
        "genTypesTargetName": "generate-types",
        "genTypesOutputPath": "libs/shared/types/src/database.types.ts",
        "runCommandTargetName": "supabase"
      }
    }
  ]
}

Inferred Tasks:

The plugin uses createNodesV2 API to automatically infer tasks for projects that have a production/config.toml file.

Detection Pattern:

**/production/config.toml

Inferred Target Configuration:

For each detected project, the plugin creates:

{
  build: {
    executor: '@gridatek/nx-supabase:build',
    cache: true,
    inputs: [
      '{projectRoot}/production/**/*',
      '{projectRoot}/local/**/*',
      '{projectRoot}/<other-envs>/**/*'
    ],
    outputs: ['{projectRoot}/.generated']
  },
  start: {
    executor: '@gridatek/nx-supabase:run-command',
    options: { command: 'supabase start' },
    dependsOn: ['build']
  },
  stop: {
    executor: '@gridatek/nx-supabase:run-command',
    options: { command: 'supabase stop --no-backup' }
  },
  'run-command': {
    executor: '@gridatek/nx-supabase:run-command'
  }
}

Project Name Extraction:

The plugin extracts the project name from config.toml:

project_id = "my-project-name"  # Used as Nx project name

This allows projects without project.json to be automatically detected and integrated into the Nx graph.


Type Definitions

ExecutorContext

Standard Nx executor context, provided by @nx/devkit:

interface ExecutorContext {
  root: string;
  cwd: string;
  isVerbose: boolean;
  projectName?: string;
  projectsConfigurations?: {
    projects: Record<string, ProjectConfiguration>;
    version: number;
  };
  nxJsonConfiguration?: any;
  projectGraph?: ProjectGraph;
}

Return Values

All executors return a Promise with success status:

interface ExecutorResult {
  success: boolean;
}

Error Codes

Common error scenarios and how to resolve them:

Error Cause Solution
"No project name found in context" Executor called without valid project context Ensure you're using nx run <project>:target
"Project not found" Project name doesn't exist in workspace Check project name with nx show projects
"Production directory not found" Missing production/ folder Run project generator or create manually
"Environment 'X' not found" Specified environment doesn't exist Run build target or create environment directory
"Config file not found" Missing config.toml in environment Run build target or check config exists
"Supabase command failed with code X" Supabase CLI error Check Supabase CLI logs and Docker status

Advanced Usage

Custom Target Configuration

Override inferred targets in project.json:

{
  "name": "my-api",
  "targets": {
    "build": {
      "executor": "@gridatek/nx-supabase:build"
    },
    "start:dev": {
      "executor": "@gridatek/nx-supabase:run-command",
      "options": {
        "command": "supabase start",
        "env": "local"
      },
      "dependsOn": ["build"]
    },
    "migrate": {
      "executor": "@gridatek/nx-supabase:run-command",
      "options": {
        "command": "supabase db reset",
        "env": "local"
      }
    },
    "types": {
      "executor": "@gridatek/nx-supabase:gen-types",
      "options": {
        "outputPath": "types/database.ts"
      }
    }
  }
}

Programmatic Usage

Use executors programmatically in scripts:

import { ExecutorContext } from '@nx/devkit';
import buildExecutor from '@gridatek/nx-supabase/build';

async function customBuild(context: ExecutorContext) {
  const result = await buildExecutor({}, context);
  if (!result.success) {
    throw new Error('Build failed');
  }
}

For more examples and patterns, see Best Practices and Advanced Usage.