← All @molecule/* packages · App templates

@molecule/api-project-archive-external-state-d1

Provider bond · project-archive-external-state · API (Node) · v1.0.2 · Apache-2.0

Captures and restores a project's Cloudflare D1 databases via wrangler, so archiving a Workers project does not silently drop its data.

npm install @molecule/api-project-archive-external-state-d1

npm · Source on GitHub · Implements @molecule/api-project-archive

How it works

@molecule/api-project-archive-external-state-d1 is a provider bond on the API (Node) side: it implements the project-archive-external-state core interface (@molecule/api-project-archive) with a concrete vendor or library behind it.

Your code calls the core; you wire this provider once at startup. Swapping vendors later is one line in that wiring, not a rewrite.

import { setExternalStateProvider } from '@molecule/api-project-archive'
import { createD1ExternalStateProvider } from '@molecule/api-project-archive-external-state-d1'

setExternalStateProvider(
  createD1ExternalStateProvider({
    // A DECLARATION of what the project owns — never a lookup.
    databaseNames: (projectId) => [`mol_${projectId}`],
  }),
)

Works with: @molecule/api-project-archive

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.

@molecule/api-project-archive-external-state-d1 — captures and restores a project's Cloudflare D1 databases so archiving a Workers project does not silently drop its data.

@molecule/api-project-archive destroys the original once result.verified is true. State whose provider was never written is captured by nobody, verifies clean, and is then permanently deleted — so every state-owning provider bond needs one of these. This is D1's.

Capture shells out to wrangler d1 export, for the same reason the Postgres bond shells out to pg_dump: only the engine that owns the data can produce a consistent snapshot with schema, indexes and constraints intact.

Quick Start

import { setExternalStateProvider } from '@molecule/api-project-archive'
import { createD1ExternalStateProvider } from '@molecule/api-project-archive-external-state-d1'

setExternalStateProvider(
  createD1ExternalStateProvider({
    // A DECLARATION of what the project owns — never a lookup.
    databaseNames: (projectId) => [`mol_${projectId}`],
  }),
)

Type

provider

Installation

npm install @molecule/api-project-archive-external-state-d1 @molecule/api-project-archive

API

Interfaces

D1ExternalStateConfig

How this deployment finds a project's D1 databases.

interface D1ExternalStateConfig {
  /**
   * The D1 database NAMES belonging to `projectId`, as `wrangler` knows them.
   *
   * **This is a DECLARATION, not a search.** An empty array means the project
   * genuinely owns none — and it is the ONLY way to say that. Asking Cloudflare
   * "which databases does this project have?" cannot distinguish "none" from
   * "this API token cannot see them", and the caller DESTROYS the project on a
   * successful capture, so an inferred absence deletes live data. A name that is
   * listed but does not exist is an ERROR, never an absence.
   *
   * @param projectId - The project being archived or restored.
   * @returns Its D1 database names; `[]` when it owns none.
   */
  databaseNames: (projectId: string) => readonly string[] | Promise<readonly string[]>

  /**
   * The `wrangler` executable. Defaults to `wrangler`.
   *
   * Capture needs D1's own tooling for the same reason `pg_dump` cannot dump
   * MySQL: the export has to come from the engine that owns the data.
   */
  wranglerPath?: string

  /**
   * Extra arguments appended to every `wrangler` invocation — typically
   * `['--config', 'wrangler.toml']` or an account selector.
   *
   * Credentials are NOT passed here. `wrangler` reads `CLOUDFLARE_API_TOKEN` /
   * `CLOUDFLARE_ACCOUNT_ID` from the environment, and a token in argv is visible
   * in `ps` to every user on the host.
   */
  wranglerArgs?: readonly string[]

  /**
   * Operate on the deployed (remote) database rather than the local emulator.
   * Defaults to `true`.
   *
   * The default is deliberate: `wrangler d1 export` without `--remote` dumps the
   * LOCAL miniflare database, which in production is empty. Defaulting to local
   * would produce a clean, successful, zero-row capture — and then the caller
   * would destroy the real one.
   */
  remote?: boolean
}

Functions

createD1ExternalStateProvider(config)

Create the provider.

function createD1ExternalStateProvider(config: D1ExternalStateConfig): ProjectExternalStateProvider
  • config — How to find a project's D1 databases.

Returns: A provider ready to bond with setExternalStateProvider.

Constants

KIND

Recorded on every record this provider produces; routes restores back here.

const KIND: 'd1'

Core Interface

Implements @molecule/api-project-archive interface.

Injection Notes

Requirements

Peer dependencies:

  • @molecule/api-project-archive ^1.0.1

Runtime Dependencies

  • @molecule/api-project-archive

  • databaseNames declares; it must never search. Asking Cloudflare which databases a project has cannot distinguish "none" from "this token cannot see them", and the caller destroys the project on a successful capture. An empty array is the only way to say "owns nothing"; a listed name that does not exist is an error.

  • remote defaults to true, deliberately. wrangler d1 export without --remote dumps the LOCAL miniflare database, which in production is empty. Defaulting to local would yield a clean, successful, zero-row capture — and then the caller would destroy the real database.

  • A zero-byte export is treated as a failure, not an empty database. d1 export always emits at least schema statements, so zero bytes means the export did not happen (wrong name, wrong account, silent auth failure).

  • Credentials come from the environment, never argv. wrangler reads CLOUDFLARE_API_TOKEN / CLOUDFLARE_ACCOUNT_ID; a token in argv is visible in ps to every user on the host. wranglerArgs is for --config and similar, not secrets.