Named Data

TurboWarp custom extension · Composition API · v0.4.0

Share data between extensions by name, not by copy.

Named Data is a shared contract and provider registry for unsandboxed TurboWarp extensions. One extension registers a provider for a namespace and kind; any other extension resolves namespace + name + kind + scope and receives metadata and a byte or stream body, without the payload ever passing through the registry.

Reference
Registry
Provider
Metadata + body

Who uses it

Infrastructure for the other extensions.

Named Data has almost no blocks of its own. Its value is the registry that data-owning extensions share. Separately bundled extensions find the same registry through the stable key Symbol.for('@kubohiroya/turbowarp-named-data/registry'), so load order and bundling do not split it.

Asset Cache

Publishes named image, audio, and text assets as the asset kind.

Structured Data

Publishes JSON and YAML values as the structured kind, optionally with a schema identity.

Document Data

Publishes HTML and Markdown documents as the document kind.

Binary Data

Publishes raw bytes as the binary kind for other extensions to stream.

Quick start

Enable, load, check.

The registry is a startup-fixed feature that is off by default. The flag is read once when the bundle starts, so it must be set before the extension loads.

  1. Enable the feature flag

    In the host page, or in the editor's browser console for a quick test, set:

    globalThis.__TW_NAMED_DATA_FEATURE_FLAGS__ = {
      NAMED_DATA_REGISTRY_MVP: true
    };
  2. Load the extension

    In TurboWarp, choose Add Extension → Custom Extension, use this file, and enable Run extension without sandbox:

    https://cdn.jsdelivr.net/npm/@kubohiroya/turbowarp-named-data@0.4.0/dist/named-data.js
  3. Check availability

    The single Boolean block confirms that the shared registry was installed.

    if <named data registry available?> then
      say [ready]

How it works

The registry routes; providers own the data.

The registry keeps only provider registrations, keyed by (namespace, kind), and the release callbacks of bodies that are currently open. Payload, storage, and caching stay inside each provider.

Resolving a reference

A consumer passes a reference, a representation, and a target or project context to the registry. The registry selects the provider registered for the reference's namespace and kind, asks whether it can resolve the request, then calls stat or openBody. The consumer receives metadata and a borrowed body, and releases it when finished.

What a reference contains

FieldValuesMeaning
namespace Lowercase, starts with a letter, up to 64 of a-z 0-9 . - Logical ownership domain. Providers of different kinds may share one namespace.
name Provider-defined string The value's name inside the namespace.
kind structured, document, binary, asset Data type. Together with the namespace it selects the provider.
scope target, project Target scope needs a target identity; project scope needs a project identity. One is never substituted for the other.
schemaRef (optional) {id, version} Structured references only. A stable schema ID and a complete SemVer version, never a schema body.

What a provider returns

Metadata

  • nativeRepresentation: how the provider stores it
  • representation: the form selected for this body
  • mediaType, optional byteLength and sha256- digest
  • revision: opaque; never parse or order it
  • replayable: whether the body can be read again

Body

  • Uint8Array or ReadableStream<Uint8Array>
  • Returned directly to the consumer, never stored in the registry
  • Borrowed: call release(reason) when finished

Composition API

Provide and consume from your own extension.

Other packages import the side-effect-free ESM entrypoint. Importing it does not register a TurboWarp extension; it only exposes the contract, registry functions, and feature-flag declarations.

pnpm add --save-exact @kubohiroya/turbowarp-named-data@0.4.0

Register a provider

import {
  installNamedDataRegistry,
  type NamedDataProvider
} from '@kubohiroya/turbowarp-named-data/composition';

const registry = installNamedDataRegistry(runtime);
const provider: NamedDataProvider = {
  namespace: 'com.example.notes',
  kind: 'document',
  canResolve: (ref, rep) => rep === 'markdown',
  stat: (ref, rep, ctx) => ({ /* metadata */ }),
  openBody: (ref, rep, ctx) => ({ /* metadata, body, release */ }),
  release: () => {}
};
const registration = registry.registerProvider(provider);

A second provider for the same (namespace, kind) fails with NAMED_DATA_PROVIDER_CONFLICT.

Resolve a reference

import {getNamedDataRegistry}
  from '@kubohiroya/turbowarp-named-data/composition';

const registry = getNamedDataRegistry(runtime);
const opened = await registry?.openBody(
  {namespace: 'com.example.notes', name: 'intro',
   kind: 'document', scope: 'project'},
  'markdown',
  {project: projectIdentity}
);
try {
  // read opened.body
} finally {
  await opened?.release('complete');
}

getNamedDataRegistry returns undefined when no registry is installed.

ExportUse it to…
installNamedDataRegistry(runtime)Install the shared registry, or return the compatible one already on the runtime.
getNamedDataRegistry(runtime)Retrieve the shared registry without installing one.
bindNamedDataRegistryLifecycle(runtime, registry)Clear session state on PROJECT_STOP_ALL. Returns an unbind function; bindings are reference-counted.
NamedDataError, NAMED_DATA_ERROR_CODESThrow and recognize stable NAMED_DATA_* codes.
NAMED_DATA_KINDS, NAMED_DATA_SCOPES, NAMED_DATA_REPRESENTATIONSValidate inputs against the canonical lists.
FEATURE_FLAGSRead the startup-fixed flags the bundle saw.

Types are published from dist/types/composition.d.ts. The wire-safe reference shape is also available as a JSON Schema.

Lifecycle and schema identity

Stop cleans up; schemas are named, never guessed.

When the project stops

  1. Every open body handle is released.
  2. Session providers are unregistered and released.
  3. Persistent providers keep their registration and run clearSession().

Registrations are session-scoped unless registered with {lifetime: 'persistent'}. Release operations are idempotent, so a provider can safely be released more than once.

Optional schema references

Structured references may carry schemaRef: {id, version}, for example {id: 'com.example.profile', version: '1.2.0'}. The provider must return the exact same identity in its metadata. The registry transports the identity only; schema documents, validators, and JSON values remain the provider's and consumer's responsibility. Providers publish schema references only when the separate startup flag NAMED_DATA_SCHEMA_REF is enabled (default off).

Reference

Blocks, flags, and error codes

I want to…UseImportant behavior
Check from a script that the registry existsnamed data registry available?Shown only while NAMED_DATA_REGISTRY_MVP is on.
Turn the registry onNAMED_DATA_REGISTRY_MVP: trueRead once at bundle startup; default off.
Publish schema identitiesNAMED_DATA_SCHEMA_REF: trueOpt-in for providers; default off.
Register or read dataComposition APIExtension-to-extension only; there are no value blocks for bodies.

Error codes

CodeMeaning
NAMED_DATA_INVALID_REFThe reference or provider descriptor is malformed.
NAMED_DATA_INVALID_REGISTRYThe shared symbol slot holds an incompatible object. It is never overwritten.
NAMED_DATA_PROVIDER_CONFLICTA provider is already registered for this (namespace, kind).
NAMED_DATA_PROVIDER_NOT_FOUNDNo provider is registered for this namespace.
NAMED_DATA_KIND_MISMATCHThe namespace has providers, but none for this kind.
NAMED_DATA_NOT_FOUNDThe provider has no value under this name.
NAMED_DATA_SCOPE_MISMATCHThe context lacks the target or project identity the scope requires.
NAMED_DATA_SCHEMA_NOT_FOUND / …_VERSION_MISMATCH / …_UNRESOLVEDSchema identity is missing, differs, or cannot be resolved.
NAMED_DATA_REPRESENTATION_UNSUPPORTEDThe provider cannot produce the requested representation.
NAMED_DATA_INVALID_METADATAThe provider returned metadata or a body that fails validation.
NAMED_DATA_BODY_TOO_LARGEThe body exceeds a provider or consumer limit.
NAMED_DATA_ABORTEDThe context's AbortSignal fired.
NAMED_DATA_PROVIDER_RELEASEDThe provider was released before or during the request.

Troubleshooting

When a reference does not resolve

The palette shows no blocks
NAMED_DATA_REGISTRY_MVP was not true when the bundle started. Set globalThis.__TW_NAMED_DATA_FEATURE_FLAGS__ first, then reload the editor and load the extension again. Changing the flag after loading has no effect.
The extension refuses to load
Named Data must run unsandboxed. Enable Run extension without sandbox in the custom extension dialog. Only load extension code you trust.
Two extensions see different registries
Both must use installNamedDataRegistry or getNamedDataRegistry on the same TurboWarp runtime. A private registry created inside one extension is not shared. If the symbol slot already holds an incompatible object, the call fails with NAMED_DATA_INVALID_REGISTRY.
A target-scoped reference fails in project context
Target scope requires context.target and project scope requires context.project. The registry reports NAMED_DATA_SCOPE_MISMATCH instead of substituting one for the other.
Data disappears after pressing stop
Session providers are released on PROJECT_STOP_ALL. Register long-lived providers with {lifetime: 'persistent'} and implement clearSession() to drop only per-run state.

Named Data: complete block reference

All 1 blocks are documented below, including compatibility blocks and blocks available through optional features. Select a block to read its behavior, arguments, default values, and menu choices. Each block has a permanent link.

named data registry available?

Reports whether the startup-fixed Named Data registry feature is enabled.

Block type: BOOLEAN. Opcode: isRegistryAvailable. Permanent link

This block has no arguments.

Repository guide and examples