Documentation Index
Fetch the complete documentation index at: https://docs.deep.space/llms.txt
Use this file to discover all available pages before exploring further.
runMigrations(db, migrations)
Idempotently apply a list of SQL migrations to a D1 database. Designed to run at worker startup.
_dpc_migrations(idx INTEGER PRIMARY KEY, applied_at TEXT NOT NULL).
Contract:
- Each array entry is one migration; index in the array is its sequence number.
- Each migration string can contain multiple
;-separated statements. - Don’t put
;inside string literals - the split is naive. - Statements run via
db.prepare(sql).run(), notexec(). - Idempotent - re-running with the same array is a no-op.
- Append new migrations to the end; never reorder or delete entries.
- Throws on any individual migration failure; the failed row is not inserted, so the next deploy retries.
Per-tenant metering
Every deployed app gets aUSAGE_EVENTS Analytics Engine binding automatically - don’t declare it in wrangler.toml. The metering helpers write usage events keyed by OWNER_USER_ID.
All three helpers take a MeteringEnv shape - { USAGE_EVENTS?, OWNER_USER_ID?, APP_NAME? } - which the app’s Env already satisfies because the deploy worker injects all three. The runtime MeteringEnv is intentionally weaker than Env so the helpers compile in shared utility code.
meterAi(env, model, fields)
op='input' and op='output' events. If both are 0, emits op='call' so the model invocation is still recorded.
meterVectorize(env, indexName, op, fields)
query:(vectors + storedCount) * dims(matches CF’s(stored + queries) * dimsformula)upsert/delete/getByIds:vectors * dims
storedCount on queries against non-empty indexes or you’ll significantly undercount.
meterUsage(env, kind, fields)
Generic fallback for any other binding (Browser Rendering, Hyperdrive, custom kinds).
Behavior
All three helpers returnboolean - false when USAGE_EVENTS is missing (local dev) or when Analytics Engine throws. Metering never breaks the calling code path - wrap in void if you prefer to ignore the return.
COST_RATES
Per-units USD multipliers for dashboard rollup. Multiply SUM(_sample_interval * doubles[1]) by the matching rate to get USD without re-querying Cloudflare’s billing API.
Shared Browser Rendering (captureScreenshot)
Render a URL to a PNG via the platform’s shared Browser Rendering binding, without declaring your own [browser] binding in wrangler.toml. Added in v0.3.10.
APP_IDENTITY_TOKEN and APP_NAME (the same HMAC-of-app-name pattern /internal/files uses). The platform enforces a host allowlist (*.app.space, *.deep.space), per-app sliding rate limits, and viewport / timeout clamping.
Imported from 'deepspace/server' - this is a server-side helper, not a browser export.
Example: OG-image route
The scaffold’sworker.ts already binds APP_IDENTITY_TOKEN, APP_NAME, and the PLATFORM_WORKER service binding, so the route below is copy-paste-runnable - no wrangler.toml edits required.
The null return is the contract
captureScreenshot returns null on any non-2xx from the platform - rate limit, allowlist miss, target timeout, BR binding misconfigured platform-side. Underlying errors are logged on the platform side; the caller just sees null. Always branch on it and fall back to a placeholder. Users will hit this path during local dev (see below) and on the first request after an allowlist change.
APP_IDENTITY_TOKEN is only populated after your first npx deepspace deploy. Calls before that, or from a fresh deepspace dev session with no prior deploy, will return null. Test screenshot flows against a deployed environment, or guard with a placeholder during local bring-up.When you still want your own browser_rendering binding
captureScreenshot covers standard preview / OG-image flows on app-owned hosts. Declare your own [browser] binding in wrangler.toml only if you need one of:
- Unmetered Browser Rendering - the shared binding counts against the platform’s per-app sliding rate limit; an app-owned binding is billed and rate-limited on your CF account.
- Custom user agents, headers, or cookies - the shared endpoint sets these platform-side and does not accept overrides.
- Third-party hosts - URLs outside
*.app.space/*.deep.spaceare rejected by the allowlist. Render them via your own binding. - Direct Puppeteer scripting (
page.evaluate, multi-step navigation, PDF export) - the shared endpoint exposes a single capture call only.
[browser] binding = "BROWSER" to wrangler.toml and call env.BROWSER.fetch(...) directly - see custom bindings.
Manifest validation
For tooling that introspects or generates binding manifests.validateBindingManifest returns a discriminated union: on success, { valid: true, bindings }; on failure, { valid: false, errors } carrying one or more ValidationErrors.
The three name/type sets are exported as Set<string> instances, not tuples - use .has(...) rather than indexing.
CustomBinding (wire type)
kv_namespace uses namespace_id, d1 uses id, queue uses queue_name, r2_bucket uses bucket_name, and vectorize uses index_name. analytics_engine.dataset is optional.
See also
- Custom bindings guide - declaring resources in
wrangler.toml - Deployment concepts - auto-provisioning lifecycle