@statedelta/protocol
v1.1.0
Published
The protocol of the StateDelta launcher ecosystem — interfaces and pure helpers, no implementation.
Downloads
62
Maintainers
Readme
@statedelta/protocol
O protocolo do ecossistema launcher StateDelta — versão 1.0.
@statedelta/protocol declara apenas interfaces e helpers puros — sem
implementação. É a interlíngua: todo pacote do pipeline do launcher
(chain · gateway · launcher · conformance · cli) e toda engine miram nos
contratos definidos aqui.
O protocolo é agnóstico de engine — nunca importa uma engine, não carrega tipos engine-específicos (sem tick, sem realm, sem modelo de estado), e não declara nada sobre como uma engine em execução é operada. É puramente o contrato launcher↔engine.
Instalação
pnpm add @statedelta/protocolO que tem dentro
| Conceito | Símbolos | Propósito |
|---|---|---|
| Costura de engine | EngineFactory, LaunchContext, EngineConfig, PROTOCOL_VERSION | O contrato de uma chamada pelo qual o launcher dá vida a uma engine. |
| Host | Host, SchemaService, CacheService | A superfície de plataforma que um host fornece a uma engine — capacidades root + à la carte. |
| Protocolo de documento | StateDoc, MergeDeltaDoc, TailDeltaDoc, Entry, NormalizedEntry, DocumentRequires, extractEntries, … | Cadeia StateDoc/DeltaDoc, o modo assembly. body/patch/input permanecem opacos. |
| Artifact | Artifact, MergeArtifact, TailArtifact, ArtifactDep, ResolvedRequires, isMergeArtifact, isTailArtifact | A saída fechada e cacheável do launcher — 1 main + N deps paralelas. |
| Resolução | accumulateRequires, validateAccumulatedRequires, resolveRequires, ResolutionError, ResolutionErrorCode, isResolutionError | Acumula requires (engine + resources + deps) pela chain; validação fail-fast. |
| Environment | StateDeltaEnvironment, createEnvironment, IProvider, IMiddleware, IGateway | Registro das instâncias que o launcher fornece — factories de engine, providers/middlewares do Gateway, resources nomeados. |
| Eventos | EventEmitter, IEventEmitter | Emitter type-safe usado entre os pacotes. |
A costura de engine
O launcher resolve uma cadeia de documentos num Artifact e termina
ali — nunca dirige a engine. Para dar vida a uma engine, ele entrega um
único LaunchContext a uma EngineFactory:
type EngineFactory<TRunning = unknown> = (
ctx: LaunchContext,
) => TRunning | Promise<TRunning>;
interface LaunchContext {
readonly artifact: Artifact; // o conteúdo resolvido
readonly config: EngineConfig; // o env-bag ambient
readonly host: Host; // a superfície viva de capacidades do launcher
readonly protocol: string; // o nível do protocolo (ex.: "1.0")
}Um objeto — para que a assinatura nunca mude. Uma capacidade nova de
protocolo é um campo novo no LaunchContext ou um método novo no Host,
nunca um parâmetro novo. O bundle da engine exporta a factory com o nome
create.
TRunning é genérico: o protocolo não nomeia nada sobre como uma engine
em execução é operada — tick, estado, observação são a API própria da
engine, no pacote dela.
EngineConfig é o env-bag — um Record<string, unknown> permissivo,
estilo process.env. A engine lê (e valida) só as chaves que entende.
Chave de convenção: mode: "dev" | "prod".
O Host
Host é a superfície de plataforma que todo host conforme — o launcher,
ou qualquer aplicação que instancie uma engine — fornece:
interface Host {
readonly schema: SchemaService; // ROOT — sempre presente
readonly cache: CacheService; // ROOT — sempre presente
getDependency(name: string): Promise<unknown>; // à la carte — requires.deps
getResource(name: string): unknown; // à la carte — requires.resources
}- Capacidades root (
schema,cache) — propriedades tipadas, sempre presentes, garantidas pelo protocolo. Versionam JUNTO com o protocolo. - À la carte (
getDependency,getResource) — por chave string: o nome precisa ter sido declarado norequiresdo documento e validado na resolução; um nome não-declarado lança.
O protocolo declara as interfaces; um host (o launcher) as implementa —
espelho de como o IGateway é declarado aqui e implementado pelo
@statedelta/gateway.
O Artifact
O launcher resolve uma chain e termina num Artifact — fechado,
cacheável, content-addressable. Discriminado por assembly:
merge— o launcher achatou a chain (deepMerge) num único estado consolidado emmain. A engine boota.tail—mainé{ body, entries[] }: o body do StateDoc mais os entries operacionais ordenados. A engine boota o body e replaya os entries.
deps são paralelas — baixadas e integridade-verificadas pelo launcher,
mantidas separadas do main para import lazy via host.getDependency.
Resolução — requires
Um documento declara o que precisa num bloco só — requires:
interface DocumentRequires {
engine?: string; // "[email protected]"
resources?: readonly string[]; // capacidades opcionais do host
deps?: Readonly<Record<string, string>>; // documentos de dependência
}requires acumula pela chain e é validado fail-fast na resolução,
antes de qualquer engine tocar o conteúdo:
engine— o StateDoc root é autoritativo; uma declaração posterior divergente →ENGINE_DECLARATION_CONFLICT.resources— acumulam por união de conjunto; ausente no environment →RESOURCE_NOT_AVAILABLE.deps— mesclados por nome; falha de fetch/verificação →DEP_NOT_AVAILABLE.
Capacidades root (schema, cache) nunca são declaradas aqui — estão
sempre presentes.
Exemplo rápido
import {
createEnvironment,
type EngineFactory,
} from "@statedelta/protocol";
// Um adapter de engine é uma EngineFactory — recebe o LaunchContext e
// devolve uma engine rodando.
const myEngine: EngineFactory = (ctx) => {
// ctx.artifact — conteúdo resolvido; ctx.host — schema/cache/deps/resources
return createMyRunningEngine(ctx);
};
const env = createEnvironment({
engines: { "[email protected]": myEngine },
resources: { fetch: globalThis.fetch },
}).freeze();Versionização do protocolo
PROTOCOL_VERSION ("1.0") é a versão do contrato observável —
EngineFactory, LaunchContext, Host, Artifact,
ResolutionErrorCode. Não é a versão do pacote npm.
O protocolo evolui aditivamente dentro de um major: uma capacidade
nova é um campo/método novo, nunca um parâmetro novo nem um símbolo
removido — bump de minor. Uma quebra é bump de major. Uma engine declara
o range de protocolo que aceita; o launcher checa na resolução e lança
ENGINE_PROTOCOL_INCOMPATIBLE num mismatch.
Princípios de design
- Só protocolo — sem implementação, sem tipos engine-específicos. Tipos e helpers puros.
- Agnóstico de engine —
TRunningé genérico; o protocolo nunca nomeia tick, estado, replay. Qualquer engine pode mirar nele. body/patch/inputopacos — o protocolo os carrega; só a engine os interpreta.- Fail-fast na fronteira —
ResolutionErroré lançado na resolução, antes de o conteúdo chegar a uma engine. - Evolução aditiva — a costura cresce, nunca muda de forma.
Pacotes que consomem isto
@statedelta/gateway— I/O de documento (IProvider,IMiddleware)@statedelta/chain— navegação da chain (DocumentHeader)@statedelta/launcher— o pipeline completo →Artifact→ engine@statedelta/conformance— a suíte do protocolo do launcher@statedelta/cli— CLI do launcher
Veja também
ARCHITECTURE.md— arquitetura internadocs/protocols/DOCUMENT-PROTOCOL.md— o protocolo de documento JSONdocs/proposals/PROPOSAL-PROTOCOL-1.0.md— a especificação do protocolo 1.0
Licença
MIT
