← All @molecule/* packages · App templates

@molecule/api-staging-state

Utility · staging · API (Node) · v1.0.1 · Apache-2.0

State management for active staging environments

npm install @molecule/api-staging-state

npm · Source on GitHub

How it works

@molecule/api-staging-state is a utility package for the API (Node) side (staging).

import { addEnvironment, listEnvironments, allocatePort } from '@molecule/api-staging-state'

const ports = await allocatePort('/path/to/project', { start: 4001, end: 4099 })
await addEnvironment('/path/to/project', {
  slug: 'feat-login',
  branch: 'feature/login',
  driver: 'docker-compose',
  status: 'running',
  createdAt: new Date().toISOString(),
  updatedAt: new Date().toISOString(),
  urls: { api: `http://localhost:${ports.api}` },
  ports,
})

Reference

Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit src/index.ts JSDoc, not this file.

State management for active staging environments in molecule.dev.

Manages the .molecule/staging.json file that tracks ephemeral branch-per-feature staging environments within a project.

Quick Start

import { addEnvironment, listEnvironments, allocatePort } from '@molecule/api-staging-state'

const ports = await allocatePort('/path/to/project', { start: 4001, end: 4099 })
await addEnvironment('/path/to/project', {
  slug: 'feat-login',
  branch: 'feature/login',
  driver: 'docker-compose',
  status: 'running',
  createdAt: new Date().toISOString(),
  updatedAt: new Date().toISOString(),
  urls: { api: `http://localhost:${ports.api}` },
  ports,
})

Type

utility

Installation

npm install @molecule/api-staging-state

API

Interfaces

StagingEnvironmentRecord

Record for a single active staging environment.

interface StagingEnvironmentRecord {
  /** Unique slug derived from branch name. */
  slug: string

  /** Original git branch name. */
  branch: string

  /** Name of the staging driver managing this environment. */
  driver: string

  /** ISO 8601 creation timestamp. */
  createdAt: string

  /** ISO 8601 last-updated timestamp. */
  updatedAt: string

  /** Deployed URLs. */
  urls: { api?: string; app?: string }

  /** Allocated ports. */
  ports: { api?: number; app?: number; db?: number }

  /** Current environment status. */
  status: 'running' | 'stopped' | 'error' | 'creating' | 'destroying'

  /** Driver-specific metadata. */
  driverMeta?: Record<string, unknown>
}

StagingState

Root state file schema for .molecule/staging.json.

interface StagingState {
  /** Schema version. */
  version: 1

  /** Active environments keyed by slug. */
  environments: Record<string, StagingEnvironmentRecord>
}

Functions

addEnvironment(projectPath, record)

Adds or updates an environment record in the state file.

function addEnvironment(projectPath: string, record: StagingEnvironmentRecord): Promise<void>
  • projectPath — Absolute path to the project root.
  • record — The environment record to add or update.

allocatePort(projectPath, portRange)

Allocates a set of non-colliding ports for a new staging environment. Each environment needs three ports: API, App, and DB. Ports are allocated sequentially from the range, skipping any already in use.

function allocatePort(
  projectPath: string,
  portRange: { start: number; end: number },
): Promise<{ api: number; app: number; db: number }>
  • projectPath — Absolute path to the project root.
  • portRange — The port range to allocate from.
  • portRange.start — First port in the range (inclusive).
  • portRange.end — Last port in the range (inclusive).

Returns: An object with allocated api, app, and db ports.

getEnvironment(projectPath, slug)

Retrieves a single environment record by slug.

function getEnvironment(
  projectPath: string,
  slug: string,
): Promise<StagingEnvironmentRecord | undefined>
  • projectPath — Absolute path to the project root.
  • slug — The slug to look up.

Returns: The environment record, or undefined if not found.

listEnvironments(projectPath)

Lists all active environment records.

function listEnvironments(projectPath: string): Promise<StagingEnvironmentRecord[]>
  • projectPath — Absolute path to the project root.

Returns: Array of all environment records.

loadState(projectPath)

Loads the staging state from disk. Returns an empty state if the file does not exist.

function loadState(projectPath: string): Promise<StagingState>
  • projectPath — Absolute path to the project root.

Returns: The current staging state.

removeEnvironment(projectPath, slug)

Removes an environment record from the state file.

function removeEnvironment(projectPath: string, slug: string): Promise<void>
  • projectPath — Absolute path to the project root.
  • slug — The slug of the environment to remove.

saveState(projectPath, state)

Persists the staging state to disk, creating the .molecule/ directory if needed.

function saveState(projectPath: string, state: StagingState): Promise<void>
  • projectPath — Absolute path to the project root.
  • state — The state to persist.

statePath(projectPath)

Returns the absolute path to the staging state file.

function statePath(projectPath: string): string
  • projectPath — Absolute path to the project root.

Returns: Absolute path to .molecule/staging.json.

Injection Notes

Used by the mlcl stage staging drivers; the state file is per-project bookkeeping, not a database. Two sharp edges:

  • No locking, and mutations are read-modify-overwrite. loadState() treats ANY read failure (missing, unreadable, corrupt JSON) as an empty state, so a concurrent mutator or a transient read error followed by a save can drop previously-tracked environments. Serialize access (one driver process at a time per project).
  • allocatePort() only avoids ports recorded in this state file — it never probes the OS. A port held by an unrelated process is still handed out; callers should tolerate bind failures and retry with the next range.