Add canonical TypeScript Eve contracts

This commit is contained in:
Meta Vens 2026-07-13 23:44:18 +01:00
commit ccb9d56424
30 changed files with 3378 additions and 0 deletions

4
.gitignore vendored
View file

@ -4,6 +4,10 @@ packages/*
!packages/eve-browser-lowering/
!packages/eve-browser-lowering/**
packages/eve-browser-lowering/node_modules/
!packages/eve-contracts/
!packages/eve-contracts/**
packages/eve-contracts/node_modules/
packages/eve-contracts/*.tgz
!packages/org.gamecult.eve.surface/
!packages/org.gamecult.eve.surface/**
!packages/org.gamecult.eve.unity-uitoolkit/

View file

@ -0,0 +1,21 @@
# @gamecult/eve-contracts
Canonical TypeScript types and runtime validators for Eve provider boundaries.
The generated sources come from the JSON Schemas in `../../schemas`; run
`npm run generate` after changing an authoritative schema. `npm test` rejects
schema drift.
```ts
import {
parseEveProviderAdvertisement,
parseEveSurfaceDocument,
parseEveCommandInvocation,
} from "@gamecult/eve-contracts";
const provider = parseEveProviderAdvertisement(untrustedAdvertisement);
const surface = parseEveSurfaceDocument(untrustedSurface);
const command = parseEveCommandInvocation(untrustedCommand);
```
Providers own their state, surfaces, command acceptance, and receipts. This
package owns only the portable contract and validation boundary.

View file

@ -0,0 +1,11 @@
export interface EveCommandDescriptor {
schema: "gamecult.eve.command.v1";
command: string;
label?: string;
surfaceId?: string;
transport?: string;
authority?: string;
result?: string;
payloadSchema?: string;
[k: string]: any;
}

View file

@ -0,0 +1 @@
export {};

View file

@ -0,0 +1,21 @@
export interface EveCommandInvocation {
schema: "gamecult.eve.command_invocation.v1";
providerId: string;
surfaceId: string;
operation: {
operationId: string;
schemaId?: string;
idempotencyKey?: string;
routeHint?: {
[k: string]: any;
};
[k: string]: any;
};
payload: {
[k: string]: any;
};
issuedAt: string;
clientId: string;
commandBoundary: string;
receiptSchema: string;
}

View file

@ -0,0 +1 @@
export {};

View file

@ -0,0 +1,18 @@
export interface EveCommandReceipt {
schema: "gamecult.eve.command_receipt.v1";
receiptId: string;
commandId: string;
command: string;
state: ("accepted" | "denied" | "pending" | "reconciled");
ownerRepo: string;
authority: string;
providerId: string;
surfaceId: string;
message?: string;
diagnostics?: {
[k: string]: any;
}[];
issuedAtUtc?: string;
sourceVersion: number;
[k: string]: any;
}

View file

@ -0,0 +1 @@
export {};

View file

@ -0,0 +1,72 @@
export interface EveProviderAdvertisement {
schema: "gamecult.eve.provider_advertisement.v1";
providerId: string;
serviceId: string;
verseId: string;
rootVerse?: string;
canonicalService?: string;
locatedService?: string;
cultMeshAddress?: string;
title: string;
kind: string;
updatedAt?: string;
updatedAtUtc?: string;
freshness: {
state: string;
lastSeenAt?: string;
lastSeenAtUtc?: string;
maxAgeMs?: number;
[k: string]: any;
};
schemas: (string | {
[k: string]: any;
})[];
witnesses: {
kind: string;
ref?: string;
path?: string;
summary?: string;
[k: string]: any;
}[];
surfaces: {
surfaceId: string;
schema: string;
key?: string;
recordRef?: string;
url?: string;
transport: string;
status?: string;
surfaceKind?: string;
interactionModel?: string;
worldInteraction?: {
projectionKind: string;
stateSchemas: string[];
commandBoundary: string;
commandRecordRef?: string;
receiptSchema: string;
receiptRecordRef?: string;
assetManifestRecordRef?: string;
loweringTargets: string[];
ownership: string;
[k: string]: any;
};
requiresPlugins?: {
[k: string]: any;
}[];
[k: string]: any;
}[];
commands: {
command: string;
transport: string;
summary?: string;
[k: string]: any;
}[];
conformanceScenarios?: {
scenarioId: string;
schema: string;
path: string;
summary?: string;
[k: string]: any;
}[];
[k: string]: any;
}

View file

@ -0,0 +1 @@
export {};

View file

@ -0,0 +1,629 @@
export declare const eveContractSchemas: {
readonly providerAdvertisement: {
readonly $schema: "https://json-schema.org/draft/2020-12/schema";
readonly $id: "gamecult.eve.provider_advertisement.v1";
readonly title: "Eve Provider Advertisement";
readonly type: "object";
readonly required: readonly ["schema", "providerId", "serviceId", "verseId", "title", "kind", "freshness", "schemas", "witnesses", "surfaces", "commands"];
readonly properties: {
readonly schema: {
readonly const: "gamecult.eve.provider_advertisement.v1";
};
readonly providerId: {
readonly type: "string";
readonly minLength: 1;
};
readonly serviceId: {
readonly type: "string";
readonly minLength: 1;
};
readonly verseId: {
readonly type: "string";
readonly minLength: 1;
};
readonly rootVerse: {
readonly type: "string";
readonly minLength: 1;
};
readonly canonicalService: {
readonly type: "string";
};
readonly locatedService: {
readonly type: "string";
};
readonly cultMeshAddress: {
readonly type: "string";
};
readonly title: {
readonly type: "string";
readonly minLength: 1;
};
readonly kind: {
readonly type: "string";
readonly minLength: 1;
};
readonly updatedAt: {
readonly type: "string";
};
readonly updatedAtUtc: {
readonly type: "string";
};
readonly freshness: {
readonly type: "object";
readonly required: readonly ["state"];
readonly properties: {
readonly state: {
readonly type: "string";
readonly minLength: 1;
};
readonly lastSeenAt: {
readonly type: "string";
};
readonly lastSeenAtUtc: {
readonly type: "string";
};
readonly maxAgeMs: {
readonly type: "number";
};
};
readonly additionalProperties: true;
};
readonly schemas: {
readonly type: "array";
readonly items: {
readonly type: readonly ["string", "object"];
};
};
readonly witnesses: {
readonly type: "array";
readonly items: {
readonly type: "object";
readonly required: readonly ["kind"];
readonly properties: {
readonly kind: {
readonly type: "string";
readonly minLength: 1;
};
readonly ref: {
readonly type: "string";
};
readonly path: {
readonly type: "string";
};
readonly summary: {
readonly type: "string";
};
};
readonly additionalProperties: true;
};
};
readonly surfaces: {
readonly type: "array";
readonly items: {
readonly type: "object";
readonly required: readonly ["surfaceId", "schema", "transport"];
readonly properties: {
readonly surfaceId: {
readonly type: "string";
readonly minLength: 1;
};
readonly schema: {
readonly type: "string";
readonly minLength: 1;
};
readonly key: {
readonly type: "string";
};
readonly recordRef: {
readonly type: "string";
};
readonly url: {
readonly type: "string";
};
readonly transport: {
readonly type: "string";
readonly minLength: 1;
};
readonly status: {
readonly type: "string";
readonly minLength: 1;
};
readonly surfaceKind: {
readonly type: "string";
readonly minLength: 1;
};
readonly interactionModel: {
readonly type: "string";
readonly minLength: 1;
};
readonly worldInteraction: {
readonly type: "object";
readonly required: readonly ["projectionKind", "stateSchemas", "commandBoundary", "receiptSchema", "loweringTargets", "ownership"];
readonly properties: {
readonly projectionKind: {
readonly type: "string";
readonly minLength: 1;
};
readonly stateSchemas: {
readonly type: "array";
readonly items: {
readonly type: "string";
readonly minLength: 1;
};
};
readonly commandBoundary: {
readonly type: "string";
readonly minLength: 1;
};
readonly commandRecordRef: {
readonly type: "string";
};
readonly receiptSchema: {
readonly type: "string";
readonly minLength: 1;
};
readonly receiptRecordRef: {
readonly type: "string";
};
readonly assetManifestRecordRef: {
readonly type: "string";
};
readonly loweringTargets: {
readonly type: "array";
readonly items: {
readonly type: "string";
readonly minLength: 1;
};
};
readonly ownership: {
readonly type: "string";
readonly minLength: 1;
};
};
readonly additionalProperties: true;
};
readonly requiresPlugins: {
readonly type: "array";
readonly items: {
readonly type: "object";
readonly required: readonly ["pluginId", "requiredCapabilities"];
readonly properties: {
readonly pluginId: {
readonly type: "string";
readonly minLength: 1;
};
readonly versionRange: {
readonly type: "string";
};
readonly availability: {
readonly type: "string";
readonly enum: readonly ["required", "optional", "optional-nested"];
};
readonly requiredCapabilities: {
readonly type: "array";
readonly items: {
readonly type: "string";
readonly minLength: 1;
};
};
readonly optionalCapabilities: {
readonly type: "array";
readonly items: {
readonly type: "string";
readonly minLength: 1;
};
};
};
readonly allOf: readonly [{
readonly if: {
readonly properties: {
readonly availability: {
readonly const: "required";
};
};
};
readonly then: {
readonly properties: {
readonly requiredCapabilities: {
readonly minItems: 1;
};
};
};
}, {
readonly if: {
readonly required: readonly ["availability"];
readonly properties: {
readonly availability: {
readonly const: "optional-nested";
};
};
};
readonly then: {
readonly required: readonly ["optionalCapabilities"];
readonly properties: {
readonly requiredCapabilities: {
readonly maxItems: 0;
};
readonly optionalCapabilities: {
readonly minItems: 1;
};
};
};
}];
readonly additionalProperties: true;
};
};
};
readonly additionalProperties: true;
};
};
readonly commands: {
readonly type: "array";
readonly items: {
readonly type: "object";
readonly required: readonly ["command", "transport"];
readonly properties: {
readonly command: {
readonly type: "string";
readonly minLength: 1;
};
readonly transport: {
readonly type: "string";
readonly minLength: 1;
};
readonly summary: {
readonly type: "string";
};
};
readonly additionalProperties: true;
};
};
readonly conformanceScenarios: {
readonly type: "array";
readonly items: {
readonly type: "object";
readonly required: readonly ["scenarioId", "schema", "path"];
readonly properties: {
readonly scenarioId: {
readonly type: "string";
readonly minLength: 1;
};
readonly schema: {
readonly type: "string";
readonly minLength: 1;
};
readonly path: {
readonly type: "string";
readonly minLength: 1;
};
readonly summary: {
readonly type: "string";
};
};
readonly additionalProperties: true;
};
};
};
readonly additionalProperties: true;
};
readonly surface: {
readonly $schema: "https://json-schema.org/draft/2020-12/schema";
readonly $id: "gamecult.eve.surface.v1";
readonly title: "Eve Surface Document";
readonly type: "object";
readonly required: readonly ["type", "schema", "providerId", "providerKind", "title", "version", "surface", "commands"];
readonly properties: {
readonly type: {
readonly const: "surface-state";
};
readonly schema: {
readonly const: "gamecult.eve.surface.v1";
};
readonly providerId: {
readonly type: "string";
readonly minLength: 1;
};
readonly providerKind: {
readonly type: "string";
readonly minLength: 1;
};
readonly title: {
readonly type: "string";
readonly minLength: 1;
};
readonly version: {
readonly type: "integer";
readonly minimum: 0;
};
readonly updatedAt: {
readonly type: "string";
readonly minLength: 1;
};
readonly updatedAtUtc: {
readonly type: "string";
readonly minLength: 1;
};
readonly surface: {
readonly type: "object";
readonly required: readonly ["root", "styles"];
readonly properties: {
readonly id: {
readonly type: "string";
};
readonly title: {
readonly type: "string";
};
readonly root: {
readonly $ref: "#/$defs/component";
};
readonly styles: {
readonly type: readonly ["object", "array"];
};
};
readonly additionalProperties: true;
};
readonly commands: {
readonly type: "array";
readonly items: {
readonly $ref: "gamecult.eve.command.v1";
};
};
readonly nodes: {
readonly type: "array";
readonly items: {
readonly type: "object";
};
};
readonly selectedNodeId: {
readonly type: "string";
};
};
readonly $defs: {
readonly component: {
readonly type: "object";
readonly required: readonly ["id", "kind", "props", "children"];
readonly properties: {
readonly id: {
readonly type: "string";
readonly minLength: 1;
};
readonly kind: {
readonly type: "string";
readonly minLength: 1;
};
readonly props: {
readonly type: "object";
};
readonly children: {
readonly type: "array";
readonly items: {
readonly $ref: "#/$defs/component";
};
};
readonly stateBindings: {
readonly type: "array";
readonly items: {
readonly type: "object";
readonly required: readonly ["targetProp", "pointerId", "sourceId", "schemaId", "routeKind"];
readonly properties: {
readonly targetProp: {
readonly type: "string";
readonly minLength: 1;
};
readonly pointerId: {
readonly type: "string";
readonly minLength: 1;
};
readonly sourceId: {
readonly type: "string";
readonly minLength: 1;
};
readonly schemaId: {
readonly type: "string";
readonly minLength: 1;
};
readonly routeKind: {
readonly type: "string";
readonly minLength: 1;
};
readonly routeDescription: {
readonly type: "string";
};
};
readonly additionalProperties: true;
};
};
readonly embeddedDocuments: {
readonly type: "array";
readonly items: {
readonly type: "object";
readonly required: readonly ["slotId", "documentId", "schemaId", "presentationKind"];
readonly properties: {
readonly slotId: {
readonly type: "string";
readonly minLength: 1;
};
readonly documentId: {
readonly type: "string";
readonly minLength: 1;
};
readonly schemaId: {
readonly type: "string";
readonly minLength: 1;
};
readonly presentationKind: {
readonly type: "string";
readonly minLength: 1;
};
readonly routeHint: {
readonly type: readonly ["string", "object"];
};
};
readonly additionalProperties: true;
};
};
};
readonly additionalProperties: true;
};
};
readonly anyOf: readonly [{
readonly required: readonly ["updatedAt"];
}, {
readonly required: readonly ["updatedAtUtc"];
}];
readonly additionalProperties: true;
};
readonly commandDescriptor: {
readonly $schema: "https://json-schema.org/draft/2020-12/schema";
readonly $id: "gamecult.eve.command.v1";
readonly title: "Eve Command Descriptor";
readonly type: "object";
readonly required: readonly ["schema", "command"];
readonly properties: {
readonly schema: {
readonly const: "gamecult.eve.command.v1";
};
readonly command: {
readonly type: "string";
readonly minLength: 1;
};
readonly label: {
readonly type: "string";
};
readonly surfaceId: {
readonly type: "string";
};
readonly transport: {
readonly type: "string";
};
readonly authority: {
readonly type: "string";
};
readonly result: {
readonly type: "string";
};
readonly payloadSchema: {
readonly type: "string";
};
};
readonly additionalProperties: true;
};
readonly commandInvocation: {
readonly $schema: "https://json-schema.org/draft/2020-12/schema";
readonly $id: "gamecult.eve.command_invocation.v1";
readonly title: "Eve Command Invocation";
readonly type: "object";
readonly required: readonly ["schema", "providerId", "surfaceId", "operation", "payload", "issuedAt", "clientId", "commandBoundary", "receiptSchema"];
readonly properties: {
readonly schema: {
readonly const: "gamecult.eve.command_invocation.v1";
};
readonly providerId: {
readonly type: "string";
readonly minLength: 1;
};
readonly surfaceId: {
readonly type: "string";
readonly minLength: 1;
};
readonly operation: {
readonly type: "object";
readonly required: readonly ["operationId"];
readonly properties: {
readonly operationId: {
readonly type: "string";
readonly minLength: 1;
};
readonly schemaId: {
readonly type: "string";
};
readonly idempotencyKey: {
readonly type: "string";
};
readonly routeHint: {
readonly type: "object";
};
};
readonly additionalProperties: true;
};
readonly payload: {
readonly type: "object";
};
readonly issuedAt: {
readonly type: "string";
};
readonly clientId: {
readonly type: "string";
readonly minLength: 1;
};
readonly commandBoundary: {
readonly type: "string";
readonly minLength: 1;
};
readonly receiptSchema: {
readonly type: "string";
readonly minLength: 1;
};
};
readonly additionalProperties: false;
};
readonly commandReceipt: {
readonly $schema: "https://json-schema.org/draft/2020-12/schema";
readonly $id: "gamecult.eve.command_receipt.v1";
readonly title: "Eve Command Receipt";
readonly type: "object";
readonly required: readonly ["schema", "receiptId", "commandId", "command", "state", "ownerRepo", "authority", "providerId", "surfaceId", "sourceVersion"];
readonly properties: {
readonly schema: {
readonly const: "gamecult.eve.command_receipt.v1";
};
readonly receiptId: {
readonly type: "string";
readonly minLength: 1;
};
readonly commandId: {
readonly type: "string";
};
readonly command: {
readonly type: "string";
readonly minLength: 1;
};
readonly state: {
readonly type: "string";
readonly enum: readonly ["accepted", "denied", "pending", "reconciled"];
};
readonly ownerRepo: {
readonly type: "string";
readonly minLength: 1;
};
readonly authority: {
readonly type: "string";
readonly minLength: 1;
};
readonly providerId: {
readonly type: "string";
};
readonly surfaceId: {
readonly type: "string";
};
readonly message: {
readonly type: "string";
};
readonly diagnostics: {
readonly type: "array";
readonly items: {
readonly type: "object";
};
};
readonly issuedAtUtc: {
readonly type: "string";
};
readonly sourceVersion: {
readonly type: "integer";
readonly minimum: 0;
};
};
readonly additionalProperties: true;
};
};
export type EveContractSchemaName = keyof typeof eveContractSchemas;

View file

@ -0,0 +1,752 @@
// Generated by scripts/generate-contracts.mjs. Do not edit by hand.
export const eveContractSchemas = {
"providerAdvertisement": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "gamecult.eve.provider_advertisement.v1",
"title": "Eve Provider Advertisement",
"type": "object",
"required": [
"schema",
"providerId",
"serviceId",
"verseId",
"title",
"kind",
"freshness",
"schemas",
"witnesses",
"surfaces",
"commands"
],
"properties": {
"schema": {
"const": "gamecult.eve.provider_advertisement.v1"
},
"providerId": {
"type": "string",
"minLength": 1
},
"serviceId": {
"type": "string",
"minLength": 1
},
"verseId": {
"type": "string",
"minLength": 1
},
"rootVerse": {
"type": "string",
"minLength": 1
},
"canonicalService": {
"type": "string"
},
"locatedService": {
"type": "string"
},
"cultMeshAddress": {
"type": "string"
},
"title": {
"type": "string",
"minLength": 1
},
"kind": {
"type": "string",
"minLength": 1
},
"updatedAt": {
"type": "string"
},
"updatedAtUtc": {
"type": "string"
},
"freshness": {
"type": "object",
"required": [
"state"
],
"properties": {
"state": {
"type": "string",
"minLength": 1
},
"lastSeenAt": {
"type": "string"
},
"lastSeenAtUtc": {
"type": "string"
},
"maxAgeMs": {
"type": "number"
}
},
"additionalProperties": true
},
"schemas": {
"type": "array",
"items": {
"type": [
"string",
"object"
]
}
},
"witnesses": {
"type": "array",
"items": {
"type": "object",
"required": [
"kind"
],
"properties": {
"kind": {
"type": "string",
"minLength": 1
},
"ref": {
"type": "string"
},
"path": {
"type": "string"
},
"summary": {
"type": "string"
}
},
"additionalProperties": true
}
},
"surfaces": {
"type": "array",
"items": {
"type": "object",
"required": [
"surfaceId",
"schema",
"transport"
],
"properties": {
"surfaceId": {
"type": "string",
"minLength": 1
},
"schema": {
"type": "string",
"minLength": 1
},
"key": {
"type": "string"
},
"recordRef": {
"type": "string"
},
"url": {
"type": "string"
},
"transport": {
"type": "string",
"minLength": 1
},
"status": {
"type": "string",
"minLength": 1
},
"surfaceKind": {
"type": "string",
"minLength": 1
},
"interactionModel": {
"type": "string",
"minLength": 1
},
"worldInteraction": {
"type": "object",
"required": [
"projectionKind",
"stateSchemas",
"commandBoundary",
"receiptSchema",
"loweringTargets",
"ownership"
],
"properties": {
"projectionKind": {
"type": "string",
"minLength": 1
},
"stateSchemas": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
}
},
"commandBoundary": {
"type": "string",
"minLength": 1
},
"commandRecordRef": {
"type": "string"
},
"receiptSchema": {
"type": "string",
"minLength": 1
},
"receiptRecordRef": {
"type": "string"
},
"assetManifestRecordRef": {
"type": "string"
},
"loweringTargets": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
}
},
"ownership": {
"type": "string",
"minLength": 1
}
},
"additionalProperties": true
},
"requiresPlugins": {
"type": "array",
"items": {
"type": "object",
"required": [
"pluginId",
"requiredCapabilities"
],
"properties": {
"pluginId": {
"type": "string",
"minLength": 1
},
"versionRange": {
"type": "string"
},
"availability": {
"type": "string",
"enum": [
"required",
"optional",
"optional-nested"
]
},
"requiredCapabilities": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
}
},
"optionalCapabilities": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
}
}
},
"allOf": [
{
"if": {
"properties": {
"availability": {
"const": "required"
}
}
},
"then": {
"properties": {
"requiredCapabilities": {
"minItems": 1
}
}
}
},
{
"if": {
"required": [
"availability"
],
"properties": {
"availability": {
"const": "optional-nested"
}
}
},
"then": {
"required": [
"optionalCapabilities"
],
"properties": {
"requiredCapabilities": {
"maxItems": 0
},
"optionalCapabilities": {
"minItems": 1
}
}
}
}
],
"additionalProperties": true
}
}
},
"additionalProperties": true
}
},
"commands": {
"type": "array",
"items": {
"type": "object",
"required": [
"command",
"transport"
],
"properties": {
"command": {
"type": "string",
"minLength": 1
},
"transport": {
"type": "string",
"minLength": 1
},
"summary": {
"type": "string"
}
},
"additionalProperties": true
}
},
"conformanceScenarios": {
"type": "array",
"items": {
"type": "object",
"required": [
"scenarioId",
"schema",
"path"
],
"properties": {
"scenarioId": {
"type": "string",
"minLength": 1
},
"schema": {
"type": "string",
"minLength": 1
},
"path": {
"type": "string",
"minLength": 1
},
"summary": {
"type": "string"
}
},
"additionalProperties": true
}
}
},
"additionalProperties": true
},
"surface": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "gamecult.eve.surface.v1",
"title": "Eve Surface Document",
"type": "object",
"required": [
"type",
"schema",
"providerId",
"providerKind",
"title",
"version",
"surface",
"commands"
],
"properties": {
"type": {
"const": "surface-state"
},
"schema": {
"const": "gamecult.eve.surface.v1"
},
"providerId": {
"type": "string",
"minLength": 1
},
"providerKind": {
"type": "string",
"minLength": 1
},
"title": {
"type": "string",
"minLength": 1
},
"version": {
"type": "integer",
"minimum": 0
},
"updatedAt": {
"type": "string",
"minLength": 1
},
"updatedAtUtc": {
"type": "string",
"minLength": 1
},
"surface": {
"type": "object",
"required": [
"root",
"styles"
],
"properties": {
"id": {
"type": "string"
},
"title": {
"type": "string"
},
"root": {
"$ref": "#/$defs/component"
},
"styles": {
"type": [
"object",
"array"
]
}
},
"additionalProperties": true
},
"commands": {
"type": "array",
"items": {
"$ref": "gamecult.eve.command.v1"
}
},
"nodes": {
"type": "array",
"items": {
"type": "object"
}
},
"selectedNodeId": {
"type": "string"
}
},
"$defs": {
"component": {
"type": "object",
"required": [
"id",
"kind",
"props",
"children"
],
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"kind": {
"type": "string",
"minLength": 1
},
"props": {
"type": "object"
},
"children": {
"type": "array",
"items": {
"$ref": "#/$defs/component"
}
},
"stateBindings": {
"type": "array",
"items": {
"type": "object",
"required": [
"targetProp",
"pointerId",
"sourceId",
"schemaId",
"routeKind"
],
"properties": {
"targetProp": {
"type": "string",
"minLength": 1
},
"pointerId": {
"type": "string",
"minLength": 1
},
"sourceId": {
"type": "string",
"minLength": 1
},
"schemaId": {
"type": "string",
"minLength": 1
},
"routeKind": {
"type": "string",
"minLength": 1
},
"routeDescription": {
"type": "string"
}
},
"additionalProperties": true
}
},
"embeddedDocuments": {
"type": "array",
"items": {
"type": "object",
"required": [
"slotId",
"documentId",
"schemaId",
"presentationKind"
],
"properties": {
"slotId": {
"type": "string",
"minLength": 1
},
"documentId": {
"type": "string",
"minLength": 1
},
"schemaId": {
"type": "string",
"minLength": 1
},
"presentationKind": {
"type": "string",
"minLength": 1
},
"routeHint": {
"type": [
"string",
"object"
]
}
},
"additionalProperties": true
}
}
},
"additionalProperties": true
}
},
"anyOf": [
{
"required": [
"updatedAt"
]
},
{
"required": [
"updatedAtUtc"
]
}
],
"additionalProperties": true
},
"commandDescriptor": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "gamecult.eve.command.v1",
"title": "Eve Command Descriptor",
"type": "object",
"required": [
"schema",
"command"
],
"properties": {
"schema": {
"const": "gamecult.eve.command.v1"
},
"command": {
"type": "string",
"minLength": 1
},
"label": {
"type": "string"
},
"surfaceId": {
"type": "string"
},
"transport": {
"type": "string"
},
"authority": {
"type": "string"
},
"result": {
"type": "string"
},
"payloadSchema": {
"type": "string"
}
},
"additionalProperties": true
},
"commandInvocation": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "gamecult.eve.command_invocation.v1",
"title": "Eve Command Invocation",
"type": "object",
"required": [
"schema",
"providerId",
"surfaceId",
"operation",
"payload",
"issuedAt",
"clientId",
"commandBoundary",
"receiptSchema"
],
"properties": {
"schema": {
"const": "gamecult.eve.command_invocation.v1"
},
"providerId": {
"type": "string",
"minLength": 1
},
"surfaceId": {
"type": "string",
"minLength": 1
},
"operation": {
"type": "object",
"required": [
"operationId"
],
"properties": {
"operationId": {
"type": "string",
"minLength": 1
},
"schemaId": {
"type": "string"
},
"idempotencyKey": {
"type": "string"
},
"routeHint": {
"type": "object"
}
},
"additionalProperties": true
},
"payload": {
"type": "object"
},
"issuedAt": {
"type": "string"
},
"clientId": {
"type": "string",
"minLength": 1
},
"commandBoundary": {
"type": "string",
"minLength": 1
},
"receiptSchema": {
"type": "string",
"minLength": 1
}
},
"additionalProperties": false
},
"commandReceipt": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "gamecult.eve.command_receipt.v1",
"title": "Eve Command Receipt",
"type": "object",
"required": [
"schema",
"receiptId",
"commandId",
"command",
"state",
"ownerRepo",
"authority",
"providerId",
"surfaceId",
"sourceVersion"
],
"properties": {
"schema": {
"const": "gamecult.eve.command_receipt.v1"
},
"receiptId": {
"type": "string",
"minLength": 1
},
"commandId": {
"type": "string"
},
"command": {
"type": "string",
"minLength": 1
},
"state": {
"type": "string",
"enum": [
"accepted",
"denied",
"pending",
"reconciled"
]
},
"ownerRepo": {
"type": "string",
"minLength": 1
},
"authority": {
"type": "string",
"minLength": 1
},
"providerId": {
"type": "string"
},
"surfaceId": {
"type": "string"
},
"message": {
"type": "string"
},
"diagnostics": {
"type": "array",
"items": {
"type": "object"
}
},
"issuedAtUtc": {
"type": "string"
},
"sourceVersion": {
"type": "integer",
"minimum": 0
}
},
"additionalProperties": true
}
};

View file

@ -0,0 +1,66 @@
export type EveSurfaceDocument = ({
[k: string]: any;
} & {
type: "surface-state";
schema: "gamecult.eve.surface.v1";
providerId: string;
providerKind: string;
title: string;
version: number;
updatedAt?: string;
updatedAtUtc?: string;
surface: {
id?: string;
title?: string;
root: Component;
styles: ({
[k: string]: any;
} | any[]);
[k: string]: any;
};
commands: EveCommandDescriptor[];
nodes?: {
[k: string]: any;
}[];
selectedNodeId?: string;
[k: string]: any;
});
export interface Component {
id: string;
kind: string;
props: {
[k: string]: any;
};
children: Component[];
stateBindings?: {
targetProp: string;
pointerId: string;
sourceId: string;
schemaId: string;
routeKind: string;
routeDescription?: string;
[k: string]: any;
}[];
embeddedDocuments?: {
slotId: string;
documentId: string;
schemaId: string;
presentationKind: string;
routeHint?: (string | {
[k: string]: any;
});
[k: string]: any;
}[];
[k: string]: any;
}
export interface EveCommandDescriptor {
schema: "gamecult.eve.command.v1";
command: string;
label?: string;
surfaceId?: string;
transport?: string;
authority?: string;
result?: string;
payloadSchema?: string;
[k: string]: any;
}

View file

@ -0,0 +1 @@
export {};

42
packages/eve-contracts/dist/index.d.ts vendored Normal file
View file

@ -0,0 +1,42 @@
import { type ErrorObject } from "ajv/dist/2020.js";
import type { EveCommandDescriptor } from "./generated/command-descriptor.js";
import type { EveCommandInvocation } from "./generated/command-invocation.js";
import type { EveCommandReceipt } from "./generated/command-receipt.js";
import type { EveProviderAdvertisement } from "./generated/provider-advertisement.js";
import type { EveSurfaceDocument } from "./generated/surface.js";
import { type EveContractSchemaName } from "./generated/schemas.js";
export type { EveCommandDescriptor } from "./generated/command-descriptor.js";
export type { EveCommandInvocation } from "./generated/command-invocation.js";
export type { EveCommandReceipt } from "./generated/command-receipt.js";
export type { EveProviderAdvertisement } from "./generated/provider-advertisement.js";
export type { EveSurfaceDocument } from "./generated/surface.js";
export { eveContractSchemas, type EveContractSchemaName } from "./generated/schemas.js";
export declare const EVE_PROVIDER_ADVERTISEMENT_SCHEMA: "gamecult.eve.provider_advertisement.v1";
export declare const EVE_SURFACE_SCHEMA: "gamecult.eve.surface.v1";
export declare const EVE_COMMAND_DESCRIPTOR_SCHEMA: "gamecult.eve.command.v1";
export declare const EVE_COMMAND_INVOCATION_SCHEMA: "gamecult.eve.command_invocation.v1";
export declare const EVE_COMMAND_RECEIPT_SCHEMA: "gamecult.eve.command_receipt.v1";
type ContractTypes = {
providerAdvertisement: EveProviderAdvertisement;
surface: EveSurfaceDocument;
commandDescriptor: EveCommandDescriptor;
commandInvocation: EveCommandInvocation;
commandReceipt: EveCommandReceipt;
};
export declare class EveContractValidationError extends TypeError {
readonly contract: EveContractSchemaName;
readonly errors: readonly ErrorObject[];
constructor(contract: EveContractSchemaName, errors: readonly ErrorObject[]);
}
export declare function isEveContract<K extends EveContractSchemaName>(contract: K, value: unknown): value is ContractTypes[K];
export declare function parseEveContract<K extends EveContractSchemaName>(contract: K, value: unknown): ContractTypes[K];
export declare const isEveProviderAdvertisement: (value: unknown) => value is EveProviderAdvertisement;
export declare const isEveSurfaceDocument: (value: unknown) => value is EveSurfaceDocument;
export declare const isEveCommandDescriptor: (value: unknown) => value is EveCommandDescriptor;
export declare const isEveCommandInvocation: (value: unknown) => value is EveCommandInvocation;
export declare const isEveCommandReceipt: (value: unknown) => value is EveCommandReceipt;
export declare const parseEveProviderAdvertisement: (value: unknown) => EveProviderAdvertisement;
export declare const parseEveSurfaceDocument: (value: unknown) => EveSurfaceDocument;
export declare const parseEveCommandDescriptor: (value: unknown) => EveCommandDescriptor;
export declare const parseEveCommandInvocation: (value: unknown) => EveCommandInvocation;
export declare const parseEveCommandReceipt: (value: unknown) => EveCommandReceipt;

53
packages/eve-contracts/dist/index.js vendored Normal file
View file

@ -0,0 +1,53 @@
import Ajv2020 from "ajv/dist/2020.js";
import { eveContractSchemas } from "./generated/schemas.js";
export { eveContractSchemas } from "./generated/schemas.js";
export const EVE_PROVIDER_ADVERTISEMENT_SCHEMA = "gamecult.eve.provider_advertisement.v1";
export const EVE_SURFACE_SCHEMA = "gamecult.eve.surface.v1";
export const EVE_COMMAND_DESCRIPTOR_SCHEMA = "gamecult.eve.command.v1";
export const EVE_COMMAND_INVOCATION_SCHEMA = "gamecult.eve.command_invocation.v1";
export const EVE_COMMAND_RECEIPT_SCHEMA = "gamecult.eve.command_receipt.v1";
const ajv = new Ajv2020({
allErrors: true,
allowUnionTypes: true,
strict: true,
strictRequired: false,
strictTypes: false,
});
for (const schema of Object.values(eveContractSchemas))
ajv.addSchema(schema);
const validators = Object.fromEntries(Object.entries(eveContractSchemas).map(([name, schema]) => [name, requiredValidator(schema.$id)]));
export class EveContractValidationError extends TypeError {
contract;
errors;
constructor(contract, errors) {
super(`Invalid Eve ${contract}: ${ajv.errorsText(errors, { separator: "; " })}`);
this.name = "EveContractValidationError";
this.contract = contract;
this.errors = errors;
}
}
export function isEveContract(contract, value) {
return Boolean(validators[contract](value));
}
export function parseEveContract(contract, value) {
const validator = validators[contract];
if (!validator(value))
throw new EveContractValidationError(contract, validator.errors ?? []);
return value;
}
export const isEveProviderAdvertisement = (value) => isEveContract("providerAdvertisement", value);
export const isEveSurfaceDocument = (value) => isEveContract("surface", value);
export const isEveCommandDescriptor = (value) => isEveContract("commandDescriptor", value);
export const isEveCommandInvocation = (value) => isEveContract("commandInvocation", value);
export const isEveCommandReceipt = (value) => isEveContract("commandReceipt", value);
export const parseEveProviderAdvertisement = (value) => parseEveContract("providerAdvertisement", value);
export const parseEveSurfaceDocument = (value) => parseEveContract("surface", value);
export const parseEveCommandDescriptor = (value) => parseEveContract("commandDescriptor", value);
export const parseEveCommandInvocation = (value) => parseEveContract("commandInvocation", value);
export const parseEveCommandReceipt = (value) => parseEveContract("commandReceipt", value);
function requiredValidator(schemaId) {
const validator = ajv.getSchema(schemaId);
if (!validator)
throw new Error(`Eve contract schema ${schemaId} was not registered.`);
return validator;
}

302
packages/eve-contracts/package-lock.json generated Normal file
View file

@ -0,0 +1,302 @@
{
"name": "@gamecult/eve-contracts",
"version": "0.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@gamecult/eve-contracts",
"version": "0.1.0",
"license": "MIT",
"dependencies": {
"ajv": "^8.17.1"
},
"devDependencies": {
"@types/node": "^24.0.0",
"json-schema-to-typescript": "^15.0.4",
"typescript": "^5.9.0"
}
},
"node_modules/@apidevtools/json-schema-ref-parser": {
"version": "11.9.3",
"resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.9.3.tgz",
"integrity": "sha512-60vepv88RwcJtSHrD6MjIL6Ta3SOYbgfnkHb+ppAVK+o9mXprRtulx7VlRl3lN3bbvysAfCS7WMVfhUYemB0IQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jsdevtools/ono": "^7.1.3",
"@types/json-schema": "^7.0.15",
"js-yaml": "^4.1.0"
},
"engines": {
"node": ">= 16"
},
"funding": {
"url": "https://github.com/sponsors/philsturgeon"
}
},
"node_modules/@jsdevtools/ono": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz",
"integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/json-schema": {
"version": "7.0.15",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/lodash": {
"version": "4.17.24",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.24.tgz",
"integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/node": {
"version": "24.13.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.3.tgz",
"integrity": "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~7.18.0"
}
},
"node_modules/ajv": {
"version": "8.20.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
"integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
"license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.3",
"fast-uri": "^3.0.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true,
"license": "Python-2.0"
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"license": "MIT"
},
"node_modules/fast-uri": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.3.tgz",
"integrity": "sha512-i70LwGWUduXqzicKXWshooq+sWL1K3WUU5rKZNG/0i3a1OSoX3HqhH5WbWwTmqWfor4urUakGPiRQcleRZTwOg==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fastify"
},
{
"type": "opencollective",
"url": "https://opencollective.com/fastify"
}
],
"license": "BSD-3-Clause"
},
"node_modules/fdir": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12.0.0"
},
"peerDependencies": {
"picomatch": "^3 || ^4"
},
"peerDependenciesMeta": {
"picomatch": {
"optional": true
}
}
},
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"dev": true,
"license": "MIT",
"dependencies": {
"is-extglob": "^2.1.1"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/js-yaml": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz",
"integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/puzrin"
},
{
"type": "github",
"url": "https://github.com/sponsors/nodeca"
}
],
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
},
"bin": {
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/json-schema-to-typescript": {
"version": "15.0.4",
"resolved": "https://registry.npmjs.org/json-schema-to-typescript/-/json-schema-to-typescript-15.0.4.tgz",
"integrity": "sha512-Su9oK8DR4xCmDsLlyvadkXzX6+GGXJpbhwoLtOGArAG61dvbW4YQmSEno2y66ahpIdmLMg6YUf/QHLgiwvkrHQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@apidevtools/json-schema-ref-parser": "^11.5.5",
"@types/json-schema": "^7.0.15",
"@types/lodash": "^4.17.7",
"is-glob": "^4.0.3",
"js-yaml": "^4.1.0",
"lodash": "^4.17.21",
"minimist": "^1.2.8",
"prettier": "^3.2.5",
"tinyglobby": "^0.2.9"
},
"bin": {
"json2ts": "dist/src/cli.js"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
"license": "MIT"
},
"node_modules/lodash": {
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
"integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==",
"dev": true,
"license": "MIT"
},
"node_modules/minimist": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
"dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/picomatch": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz",
"integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/prettier": {
"version": "3.9.5",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.5.tgz",
"integrity": "sha512-/FVl766LpUfB5vXgCYOYa0MeV/441Ia99AeICQIQFTY/Nw0roZwULcXpku5i1/m5kt/baz+s4Zogspd839HSMg==",
"dev": true,
"license": "MIT",
"bin": {
"prettier": "bin/prettier.cjs"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/require-from-string": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/tinyglobby": {
"version": "0.2.17",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
"integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
"dev": true,
"license": "MIT",
"dependencies": {
"fdir": "^6.5.0",
"picomatch": "^4.0.4"
},
"engines": {
"node": ">=12.0.0"
},
"funding": {
"url": "https://github.com/sponsors/SuperchupuDev"
}
},
"node_modules/typescript": {
"version": "5.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
},
"node_modules/undici-types": {
"version": "7.18.2",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
"integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
"dev": true,
"license": "MIT"
}
}
}

View file

@ -0,0 +1,37 @@
{
"name": "@gamecult/eve-contracts",
"version": "0.1.0",
"description": "Canonical TypeScript types and runtime validators for Eve provider contracts.",
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
},
"./schemas": {
"types": "./dist/generated/schemas.d.ts",
"import": "./dist/generated/schemas.js"
}
},
"files": [
"dist",
"README.md"
],
"scripts": {
"generate": "C:\\Progra~1\\nodejs\\node.exe scripts/generate-contracts.mjs",
"generate:check": "C:\\Progra~1\\nodejs\\node.exe scripts/generate-contracts.mjs --check",
"build": "C:\\Progra~1\\nodejs\\node.exe scripts/generate-contracts.mjs --check && C:\\Progra~1\\nodejs\\node.exe ./node_modules/typescript/bin/tsc -p tsconfig.json",
"test": "C:\\Progra~1\\nodejs\\node.exe scripts/generate-contracts.mjs --check && C:\\Progra~1\\nodejs\\node.exe ./node_modules/typescript/bin/tsc -p tsconfig.json && C:\\Progra~1\\nodejs\\node.exe --test test/*.test.mjs"
},
"dependencies": {
"ajv": "^8.17.1"
},
"devDependencies": {
"@types/node": "^24.0.0",
"json-schema-to-typescript": "^15.0.4",
"typescript": "^5.9.0"
},
"license": "MIT"
}

View file

@ -0,0 +1,73 @@
#!/usr/bin/env node
import { mkdir, readFile, writeFile } from "node:fs/promises";
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { compile } from "json-schema-to-typescript";
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const repoRoot = resolve(packageRoot, "..", "..");
const generatedRoot = resolve(packageRoot, "src", "generated");
const contracts = [
["providerAdvertisement", "EveProviderAdvertisement", "provider-advertisement.ts", "gamecult.eve.provider_advertisement.v1.schema.json"],
["surface", "EveSurfaceDocument", "surface.ts", "gamecult.eve.surface.v1.schema.json"],
["commandDescriptor", "EveCommandDescriptor", "command-descriptor.ts", "gamecult.eve.command.v1.schema.json"],
["commandInvocation", "EveCommandInvocation", "command-invocation.ts", "gamecult.eve.command_invocation.v1.schema.json"],
["commandReceipt", "EveCommandReceipt", "command-receipt.ts", "gamecult.eve.command_receipt.v1.schema.json"],
];
const loaded = [];
for (const [key, typeName, generatedFileName, schemaFileName] of contracts) {
const path = resolve(repoRoot, "schemas", schemaFileName);
const source = await readFile(path, "utf8");
const schema = JSON.parse(source);
loaded.push({ key, typeName, generatedFileName, schemaFileName, schema });
}
const schemasById = new Map(loaded.map(({ schema }) => [schema.$id, schema]));
for (const contract of loaded) {
const typeSchema = inlineKnownRefs(contract.schema);
contract.typeSource = (await compile(typeSchema, contract.typeName, {
bannerComment: "",
format: false,
unknownAny: false,
})).trim();
}
const schemasOutput = `${generatedHeader()}\nexport const eveContractSchemas = ${JSON.stringify(
Object.fromEntries(loaded.map(({ key, schema }) => [key, schema])),
null,
2,
)} as const;\n\nexport type EveContractSchemaName = keyof typeof eveContractSchemas;\n`;
await mkdir(generatedRoot, { recursive: true });
for (const { generatedFileName, schemaFileName, typeSource } of loaded) {
await checkOrWrite(
resolve(generatedRoot, generatedFileName),
`${generatedHeader()}\n// Source: schemas/${schemaFileName}\n${typeSource}\n`,
);
}
await checkOrWrite(resolve(generatedRoot, "schemas.ts"), schemasOutput);
function generatedHeader() {
return "// Generated by scripts/generate-contracts.mjs. Do not edit by hand.";
}
async function checkOrWrite(path, expected) {
if (process.argv.includes("--check")) {
const actual = await readFile(path, "utf8").catch(() => "");
if (actual !== expected) {
throw new Error(`${path} is stale. Run npm run generate in ${packageRoot}.`);
}
return;
}
await writeFile(path, expected, "utf8");
}
function inlineKnownRefs(value) {
if (Array.isArray(value)) return value.map(inlineKnownRefs);
if (!value || typeof value !== "object") return value;
if (typeof value.$ref === "string" && schemasById.has(value.$ref)) {
return inlineKnownRefs(schemasById.get(value.$ref));
}
return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, inlineKnownRefs(child)]));
}

View file

@ -0,0 +1,13 @@
// Generated by scripts/generate-contracts.mjs. Do not edit by hand.
// Source: schemas/gamecult.eve.command.v1.schema.json
export interface EveCommandDescriptor {
schema: "gamecult.eve.command.v1"
command: string
label?: string
surfaceId?: string
transport?: string
authority?: string
result?: string
payloadSchema?: string
[k: string]: any
}

View file

@ -0,0 +1,23 @@
// Generated by scripts/generate-contracts.mjs. Do not edit by hand.
// Source: schemas/gamecult.eve.command_invocation.v1.schema.json
export interface EveCommandInvocation {
schema: "gamecult.eve.command_invocation.v1"
providerId: string
surfaceId: string
operation: {
operationId: string
schemaId?: string
idempotencyKey?: string
routeHint?: {
[k: string]: any
}
[k: string]: any
}
payload: {
[k: string]: any
}
issuedAt: string
clientId: string
commandBoundary: string
receiptSchema: string
}

View file

@ -0,0 +1,20 @@
// Generated by scripts/generate-contracts.mjs. Do not edit by hand.
// Source: schemas/gamecult.eve.command_receipt.v1.schema.json
export interface EveCommandReceipt {
schema: "gamecult.eve.command_receipt.v1"
receiptId: string
commandId: string
command: string
state: ("accepted" | "denied" | "pending" | "reconciled")
ownerRepo: string
authority: string
providerId: string
surfaceId: string
message?: string
diagnostics?: {
[k: string]: any
}[]
issuedAtUtc?: string
sourceVersion: number
[k: string]: any
}

View file

@ -0,0 +1,74 @@
// Generated by scripts/generate-contracts.mjs. Do not edit by hand.
// Source: schemas/gamecult.eve.provider_advertisement.v1.schema.json
export interface EveProviderAdvertisement {
schema: "gamecult.eve.provider_advertisement.v1"
providerId: string
serviceId: string
verseId: string
rootVerse?: string
canonicalService?: string
locatedService?: string
cultMeshAddress?: string
title: string
kind: string
updatedAt?: string
updatedAtUtc?: string
freshness: {
state: string
lastSeenAt?: string
lastSeenAtUtc?: string
maxAgeMs?: number
[k: string]: any
}
schemas: (string | {
[k: string]: any
})[]
witnesses: {
kind: string
ref?: string
path?: string
summary?: string
[k: string]: any
}[]
surfaces: {
surfaceId: string
schema: string
key?: string
recordRef?: string
url?: string
transport: string
status?: string
surfaceKind?: string
interactionModel?: string
worldInteraction?: {
projectionKind: string
stateSchemas: string[]
commandBoundary: string
commandRecordRef?: string
receiptSchema: string
receiptRecordRef?: string
assetManifestRecordRef?: string
loweringTargets: string[]
ownership: string
[k: string]: any
}
requiresPlugins?: {
[k: string]: any
}[]
[k: string]: any
}[]
commands: {
command: string
transport: string
summary?: string
[k: string]: any
}[]
conformanceScenarios?: {
scenarioId: string
schema: string
path: string
summary?: string
[k: string]: any
}[]
[k: string]: any
}

View file

@ -0,0 +1,754 @@
// Generated by scripts/generate-contracts.mjs. Do not edit by hand.
export const eveContractSchemas = {
"providerAdvertisement": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "gamecult.eve.provider_advertisement.v1",
"title": "Eve Provider Advertisement",
"type": "object",
"required": [
"schema",
"providerId",
"serviceId",
"verseId",
"title",
"kind",
"freshness",
"schemas",
"witnesses",
"surfaces",
"commands"
],
"properties": {
"schema": {
"const": "gamecult.eve.provider_advertisement.v1"
},
"providerId": {
"type": "string",
"minLength": 1
},
"serviceId": {
"type": "string",
"minLength": 1
},
"verseId": {
"type": "string",
"minLength": 1
},
"rootVerse": {
"type": "string",
"minLength": 1
},
"canonicalService": {
"type": "string"
},
"locatedService": {
"type": "string"
},
"cultMeshAddress": {
"type": "string"
},
"title": {
"type": "string",
"minLength": 1
},
"kind": {
"type": "string",
"minLength": 1
},
"updatedAt": {
"type": "string"
},
"updatedAtUtc": {
"type": "string"
},
"freshness": {
"type": "object",
"required": [
"state"
],
"properties": {
"state": {
"type": "string",
"minLength": 1
},
"lastSeenAt": {
"type": "string"
},
"lastSeenAtUtc": {
"type": "string"
},
"maxAgeMs": {
"type": "number"
}
},
"additionalProperties": true
},
"schemas": {
"type": "array",
"items": {
"type": [
"string",
"object"
]
}
},
"witnesses": {
"type": "array",
"items": {
"type": "object",
"required": [
"kind"
],
"properties": {
"kind": {
"type": "string",
"minLength": 1
},
"ref": {
"type": "string"
},
"path": {
"type": "string"
},
"summary": {
"type": "string"
}
},
"additionalProperties": true
}
},
"surfaces": {
"type": "array",
"items": {
"type": "object",
"required": [
"surfaceId",
"schema",
"transport"
],
"properties": {
"surfaceId": {
"type": "string",
"minLength": 1
},
"schema": {
"type": "string",
"minLength": 1
},
"key": {
"type": "string"
},
"recordRef": {
"type": "string"
},
"url": {
"type": "string"
},
"transport": {
"type": "string",
"minLength": 1
},
"status": {
"type": "string",
"minLength": 1
},
"surfaceKind": {
"type": "string",
"minLength": 1
},
"interactionModel": {
"type": "string",
"minLength": 1
},
"worldInteraction": {
"type": "object",
"required": [
"projectionKind",
"stateSchemas",
"commandBoundary",
"receiptSchema",
"loweringTargets",
"ownership"
],
"properties": {
"projectionKind": {
"type": "string",
"minLength": 1
},
"stateSchemas": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
}
},
"commandBoundary": {
"type": "string",
"minLength": 1
},
"commandRecordRef": {
"type": "string"
},
"receiptSchema": {
"type": "string",
"minLength": 1
},
"receiptRecordRef": {
"type": "string"
},
"assetManifestRecordRef": {
"type": "string"
},
"loweringTargets": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
}
},
"ownership": {
"type": "string",
"minLength": 1
}
},
"additionalProperties": true
},
"requiresPlugins": {
"type": "array",
"items": {
"type": "object",
"required": [
"pluginId",
"requiredCapabilities"
],
"properties": {
"pluginId": {
"type": "string",
"minLength": 1
},
"versionRange": {
"type": "string"
},
"availability": {
"type": "string",
"enum": [
"required",
"optional",
"optional-nested"
]
},
"requiredCapabilities": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
}
},
"optionalCapabilities": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
}
}
},
"allOf": [
{
"if": {
"properties": {
"availability": {
"const": "required"
}
}
},
"then": {
"properties": {
"requiredCapabilities": {
"minItems": 1
}
}
}
},
{
"if": {
"required": [
"availability"
],
"properties": {
"availability": {
"const": "optional-nested"
}
}
},
"then": {
"required": [
"optionalCapabilities"
],
"properties": {
"requiredCapabilities": {
"maxItems": 0
},
"optionalCapabilities": {
"minItems": 1
}
}
}
}
],
"additionalProperties": true
}
}
},
"additionalProperties": true
}
},
"commands": {
"type": "array",
"items": {
"type": "object",
"required": [
"command",
"transport"
],
"properties": {
"command": {
"type": "string",
"minLength": 1
},
"transport": {
"type": "string",
"minLength": 1
},
"summary": {
"type": "string"
}
},
"additionalProperties": true
}
},
"conformanceScenarios": {
"type": "array",
"items": {
"type": "object",
"required": [
"scenarioId",
"schema",
"path"
],
"properties": {
"scenarioId": {
"type": "string",
"minLength": 1
},
"schema": {
"type": "string",
"minLength": 1
},
"path": {
"type": "string",
"minLength": 1
},
"summary": {
"type": "string"
}
},
"additionalProperties": true
}
}
},
"additionalProperties": true
},
"surface": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "gamecult.eve.surface.v1",
"title": "Eve Surface Document",
"type": "object",
"required": [
"type",
"schema",
"providerId",
"providerKind",
"title",
"version",
"surface",
"commands"
],
"properties": {
"type": {
"const": "surface-state"
},
"schema": {
"const": "gamecult.eve.surface.v1"
},
"providerId": {
"type": "string",
"minLength": 1
},
"providerKind": {
"type": "string",
"minLength": 1
},
"title": {
"type": "string",
"minLength": 1
},
"version": {
"type": "integer",
"minimum": 0
},
"updatedAt": {
"type": "string",
"minLength": 1
},
"updatedAtUtc": {
"type": "string",
"minLength": 1
},
"surface": {
"type": "object",
"required": [
"root",
"styles"
],
"properties": {
"id": {
"type": "string"
},
"title": {
"type": "string"
},
"root": {
"$ref": "#/$defs/component"
},
"styles": {
"type": [
"object",
"array"
]
}
},
"additionalProperties": true
},
"commands": {
"type": "array",
"items": {
"$ref": "gamecult.eve.command.v1"
}
},
"nodes": {
"type": "array",
"items": {
"type": "object"
}
},
"selectedNodeId": {
"type": "string"
}
},
"$defs": {
"component": {
"type": "object",
"required": [
"id",
"kind",
"props",
"children"
],
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"kind": {
"type": "string",
"minLength": 1
},
"props": {
"type": "object"
},
"children": {
"type": "array",
"items": {
"$ref": "#/$defs/component"
}
},
"stateBindings": {
"type": "array",
"items": {
"type": "object",
"required": [
"targetProp",
"pointerId",
"sourceId",
"schemaId",
"routeKind"
],
"properties": {
"targetProp": {
"type": "string",
"minLength": 1
},
"pointerId": {
"type": "string",
"minLength": 1
},
"sourceId": {
"type": "string",
"minLength": 1
},
"schemaId": {
"type": "string",
"minLength": 1
},
"routeKind": {
"type": "string",
"minLength": 1
},
"routeDescription": {
"type": "string"
}
},
"additionalProperties": true
}
},
"embeddedDocuments": {
"type": "array",
"items": {
"type": "object",
"required": [
"slotId",
"documentId",
"schemaId",
"presentationKind"
],
"properties": {
"slotId": {
"type": "string",
"minLength": 1
},
"documentId": {
"type": "string",
"minLength": 1
},
"schemaId": {
"type": "string",
"minLength": 1
},
"presentationKind": {
"type": "string",
"minLength": 1
},
"routeHint": {
"type": [
"string",
"object"
]
}
},
"additionalProperties": true
}
}
},
"additionalProperties": true
}
},
"anyOf": [
{
"required": [
"updatedAt"
]
},
{
"required": [
"updatedAtUtc"
]
}
],
"additionalProperties": true
},
"commandDescriptor": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "gamecult.eve.command.v1",
"title": "Eve Command Descriptor",
"type": "object",
"required": [
"schema",
"command"
],
"properties": {
"schema": {
"const": "gamecult.eve.command.v1"
},
"command": {
"type": "string",
"minLength": 1
},
"label": {
"type": "string"
},
"surfaceId": {
"type": "string"
},
"transport": {
"type": "string"
},
"authority": {
"type": "string"
},
"result": {
"type": "string"
},
"payloadSchema": {
"type": "string"
}
},
"additionalProperties": true
},
"commandInvocation": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "gamecult.eve.command_invocation.v1",
"title": "Eve Command Invocation",
"type": "object",
"required": [
"schema",
"providerId",
"surfaceId",
"operation",
"payload",
"issuedAt",
"clientId",
"commandBoundary",
"receiptSchema"
],
"properties": {
"schema": {
"const": "gamecult.eve.command_invocation.v1"
},
"providerId": {
"type": "string",
"minLength": 1
},
"surfaceId": {
"type": "string",
"minLength": 1
},
"operation": {
"type": "object",
"required": [
"operationId"
],
"properties": {
"operationId": {
"type": "string",
"minLength": 1
},
"schemaId": {
"type": "string"
},
"idempotencyKey": {
"type": "string"
},
"routeHint": {
"type": "object"
}
},
"additionalProperties": true
},
"payload": {
"type": "object"
},
"issuedAt": {
"type": "string"
},
"clientId": {
"type": "string",
"minLength": 1
},
"commandBoundary": {
"type": "string",
"minLength": 1
},
"receiptSchema": {
"type": "string",
"minLength": 1
}
},
"additionalProperties": false
},
"commandReceipt": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "gamecult.eve.command_receipt.v1",
"title": "Eve Command Receipt",
"type": "object",
"required": [
"schema",
"receiptId",
"commandId",
"command",
"state",
"ownerRepo",
"authority",
"providerId",
"surfaceId",
"sourceVersion"
],
"properties": {
"schema": {
"const": "gamecult.eve.command_receipt.v1"
},
"receiptId": {
"type": "string",
"minLength": 1
},
"commandId": {
"type": "string"
},
"command": {
"type": "string",
"minLength": 1
},
"state": {
"type": "string",
"enum": [
"accepted",
"denied",
"pending",
"reconciled"
]
},
"ownerRepo": {
"type": "string",
"minLength": 1
},
"authority": {
"type": "string",
"minLength": 1
},
"providerId": {
"type": "string"
},
"surfaceId": {
"type": "string"
},
"message": {
"type": "string"
},
"diagnostics": {
"type": "array",
"items": {
"type": "object"
}
},
"issuedAtUtc": {
"type": "string"
},
"sourceVersion": {
"type": "integer",
"minimum": 0
}
},
"additionalProperties": true
}
} as const;
export type EveContractSchemaName = keyof typeof eveContractSchemas;

View file

@ -0,0 +1,69 @@
// Generated by scripts/generate-contracts.mjs. Do not edit by hand.
// Source: schemas/gamecult.eve.surface.v1.schema.json
export type EveSurfaceDocument = ({
[k: string]: any
} & {
type: "surface-state"
schema: "gamecult.eve.surface.v1"
providerId: string
providerKind: string
title: string
version: number
updatedAt?: string
updatedAtUtc?: string
surface: {
id?: string
title?: string
root: Component
styles: ({
[k: string]: any
} | any[])
[k: string]: any
}
commands: EveCommandDescriptor[]
nodes?: {
[k: string]: any
}[]
selectedNodeId?: string
[k: string]: any
})
export interface Component {
id: string
kind: string
props: {
[k: string]: any
}
children: Component[]
stateBindings?: {
targetProp: string
pointerId: string
sourceId: string
schemaId: string
routeKind: string
routeDescription?: string
[k: string]: any
}[]
embeddedDocuments?: {
slotId: string
documentId: string
schemaId: string
presentationKind: string
routeHint?: (string | {
[k: string]: any
})
[k: string]: any
}[]
[k: string]: any
}
export interface EveCommandDescriptor {
schema: "gamecult.eve.command.v1"
command: string
label?: string
surfaceId?: string
transport?: string
authority?: string
result?: string
payloadSchema?: string
[k: string]: any
}

View file

@ -0,0 +1,97 @@
import Ajv2020, { type ErrorObject, type ValidateFunction } from "ajv/dist/2020.js";
import type { EveCommandDescriptor } from "./generated/command-descriptor.js";
import type { EveCommandInvocation } from "./generated/command-invocation.js";
import type { EveCommandReceipt } from "./generated/command-receipt.js";
import type { EveProviderAdvertisement } from "./generated/provider-advertisement.js";
import type { EveSurfaceDocument } from "./generated/surface.js";
import { eveContractSchemas, type EveContractSchemaName } from "./generated/schemas.js";
export type { EveCommandDescriptor } from "./generated/command-descriptor.js";
export type { EveCommandInvocation } from "./generated/command-invocation.js";
export type { EveCommandReceipt } from "./generated/command-receipt.js";
export type { EveProviderAdvertisement } from "./generated/provider-advertisement.js";
export type { EveSurfaceDocument } from "./generated/surface.js";
export { eveContractSchemas, type EveContractSchemaName } from "./generated/schemas.js";
export const EVE_PROVIDER_ADVERTISEMENT_SCHEMA = "gamecult.eve.provider_advertisement.v1" as const;
export const EVE_SURFACE_SCHEMA = "gamecult.eve.surface.v1" as const;
export const EVE_COMMAND_DESCRIPTOR_SCHEMA = "gamecult.eve.command.v1" as const;
export const EVE_COMMAND_INVOCATION_SCHEMA = "gamecult.eve.command_invocation.v1" as const;
export const EVE_COMMAND_RECEIPT_SCHEMA = "gamecult.eve.command_receipt.v1" as const;
type ContractTypes = {
providerAdvertisement: EveProviderAdvertisement;
surface: EveSurfaceDocument;
commandDescriptor: EveCommandDescriptor;
commandInvocation: EveCommandInvocation;
commandReceipt: EveCommandReceipt;
};
const ajv = new Ajv2020({
allErrors: true,
allowUnionTypes: true,
strict: true,
strictRequired: false,
strictTypes: false,
});
for (const schema of Object.values(eveContractSchemas)) ajv.addSchema(schema);
const validators = Object.fromEntries(
Object.entries(eveContractSchemas).map(([name, schema]) => [name, requiredValidator(schema.$id)]),
) as Record<EveContractSchemaName, ValidateFunction>;
export class EveContractValidationError extends TypeError {
public readonly contract: EveContractSchemaName;
public readonly errors: readonly ErrorObject[];
public constructor(contract: EveContractSchemaName, errors: readonly ErrorObject[]) {
super(`Invalid Eve ${contract}: ${ajv.errorsText(errors as ErrorObject[], { separator: "; " })}`);
this.name = "EveContractValidationError";
this.contract = contract;
this.errors = errors;
}
}
export function isEveContract<K extends EveContractSchemaName>(
contract: K,
value: unknown,
): value is ContractTypes[K] {
return Boolean(validators[contract](value));
}
export function parseEveContract<K extends EveContractSchemaName>(
contract: K,
value: unknown,
): ContractTypes[K] {
const validator = validators[contract];
if (!validator(value)) throw new EveContractValidationError(contract, validator.errors ?? []);
return value as ContractTypes[K];
}
export const isEveProviderAdvertisement = (value: unknown): value is EveProviderAdvertisement =>
isEveContract("providerAdvertisement", value);
export const isEveSurfaceDocument = (value: unknown): value is EveSurfaceDocument =>
isEveContract("surface", value);
export const isEveCommandDescriptor = (value: unknown): value is EveCommandDescriptor =>
isEveContract("commandDescriptor", value);
export const isEveCommandInvocation = (value: unknown): value is EveCommandInvocation =>
isEveContract("commandInvocation", value);
export const isEveCommandReceipt = (value: unknown): value is EveCommandReceipt =>
isEveContract("commandReceipt", value);
export const parseEveProviderAdvertisement = (value: unknown): EveProviderAdvertisement =>
parseEveContract("providerAdvertisement", value);
export const parseEveSurfaceDocument = (value: unknown): EveSurfaceDocument =>
parseEveContract("surface", value);
export const parseEveCommandDescriptor = (value: unknown): EveCommandDescriptor =>
parseEveContract("commandDescriptor", value);
export const parseEveCommandInvocation = (value: unknown): EveCommandInvocation =>
parseEveContract("commandInvocation", value);
export const parseEveCommandReceipt = (value: unknown): EveCommandReceipt =>
parseEveContract("commandReceipt", value);
function requiredValidator(schemaId: string): ValidateFunction {
const validator = ajv.getSchema(schemaId);
if (!validator) throw new Error(`Eve contract schema ${schemaId} was not registered.`);
return validator;
}

View file

@ -0,0 +1,101 @@
import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";
import { resolve } from "node:path";
import test from "node:test";
import {
EveContractValidationError,
isEveCommandDescriptor,
parseEveCommandInvocation,
parseEveCommandReceipt,
parseEveProviderAdvertisement,
parseEveSurfaceDocument,
} from "../dist/index.js";
const command = { schema: "gamecult.eve.command.v1", command: "swarm.set_heat", transport: "cultmesh" };
const surface = {
type: "surface-state",
schema: "gamecult.eve.surface.v1",
providerId: "voidbot.swarm",
providerKind: "agent.swarm",
title: "VoidBot Swarm",
version: 1,
updatedAt: "2026-07-13T00:00:00Z",
surface: {
root: { id: "root", kind: "surface", props: {}, children: [], stateBindings: [], embeddedDocuments: [] },
styles: { tokens: {} },
},
commands: [command],
};
test("accepts canonical provider, surface, command, invocation, and receipt documents", () => {
assert.ok(isEveCommandDescriptor(command));
assert.equal(parseEveSurfaceDocument(surface).providerId, "voidbot.swarm");
assert.equal(parseEveProviderAdvertisement({
schema: "gamecult.eve.provider_advertisement.v1",
providerId: "voidbot.swarm",
serviceId: "voidbot",
verseId: "voidbot.local",
title: "VoidBot Swarm",
kind: "agent.swarm",
freshness: { state: "fresh" },
schemas: ["gamecult.eve.surface.v1"],
witnesses: [],
surfaces: [{ surfaceId: "voidbot.swarm", schema: "gamecult.eve.surface.v1", transport: "cultmesh" }],
commands: [{ command: "swarm.set_heat", transport: "cultmesh" }],
}).providerId, "voidbot.swarm");
assert.equal(parseEveCommandInvocation({
schema: "gamecult.eve.command_invocation.v1",
providerId: "voidbot.swarm",
surfaceId: "voidbot.swarm",
operation: { operationId: "swarm.set_heat" },
payload: { value: 1.25 },
issuedAt: "2026-07-13T00:00:00Z",
clientId: "test",
commandBoundary: "voidbot.swarm.commands",
receiptSchema: "gamecult.eve.command_receipt.v1",
}).operation.operationId, "swarm.set_heat");
assert.equal(parseEveCommandReceipt({
schema: "gamecult.eve.command_receipt.v1",
receiptId: "receipt-1",
commandId: "command-1",
command: "swarm.set_heat",
state: "reconciled",
ownerRepo: "VoidBot",
authority: "voidbot.swarm_control_state.v1",
providerId: "voidbot.swarm",
surfaceId: "voidbot.swarm",
sourceVersion: 1,
}).state, "reconciled");
});
test("rejects missing required fields with contract diagnostics", () => {
assert.throws(
() => parseEveSurfaceDocument({ ...surface, providerId: undefined }),
(error) => error instanceof EveContractValidationError &&
error.contract === "surface" &&
error.errors.some((entry) => entry.keyword === "required" && entry.params.missingProperty === "providerId"),
);
assert.throws(
() => parseEveCommandReceipt({ schema: "gamecult.eve.command_receipt.v1" }),
EveContractValidationError,
);
});
test("published schema constants retain their authoritative ids", async () => {
const schemas = JSON.parse(await readFile(resolve(import.meta.dirname, "..", "..", "..", "schemas", "gamecult.eve.surface.v1.schema.json"), "utf8"));
assert.equal(schemas.$id, "gamecult.eve.surface.v1");
});
test("validates an existing canonical Eve surface fixture", async () => {
const fixturePath = resolve(
import.meta.dirname,
"..",
"..",
"..",
"web",
"fixtures",
"eve-world-smoke-surface.json",
);
const fixture = JSON.parse(await readFile(fixturePath, "utf8"));
assert.equal(parseEveSurfaceDocument(fixture).providerId, "eve.world-smoke");
});

View file

@ -0,0 +1,13 @@
import assert from "node:assert/strict";
import { spawnSync } from "node:child_process";
import { resolve } from "node:path";
import test from "node:test";
test("generated TypeScript contracts match authoritative Eve schemas", () => {
const packageRoot = resolve(import.meta.dirname, "..");
const result = spawnSync(process.execPath, ["scripts/generate-contracts.mjs", "--check"], {
cwd: packageRoot,
encoding: "utf8",
});
assert.equal(result.status, 0, `${result.stdout}\n${result.stderr}`);
});

View file

@ -0,0 +1,13 @@
{
"compilerOptions": {
"declaration": true,
"module": "ES2022",
"moduleResolution": "Bundler",
"noEmitOnError": true,
"outDir": "dist",
"rootDir": "src",
"strict": true,
"target": "ES2022"
},
"include": ["src/**/*.ts"]
}

View file

@ -0,0 +1,95 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "gamecult.eve.surface.v1",
"title": "Eve Surface Document",
"type": "object",
"required": [
"type",
"schema",
"providerId",
"providerKind",
"title",
"version",
"surface",
"commands"
],
"properties": {
"type": { "const": "surface-state" },
"schema": { "const": "gamecult.eve.surface.v1" },
"providerId": { "type": "string", "minLength": 1 },
"providerKind": { "type": "string", "minLength": 1 },
"title": { "type": "string", "minLength": 1 },
"version": { "type": "integer", "minimum": 0 },
"updatedAt": { "type": "string", "minLength": 1 },
"updatedAtUtc": { "type": "string", "minLength": 1 },
"surface": {
"type": "object",
"required": ["root", "styles"],
"properties": {
"id": { "type": "string" },
"title": { "type": "string" },
"root": { "$ref": "#/$defs/component" },
"styles": { "type": ["object", "array"] }
},
"additionalProperties": true
},
"commands": {
"type": "array",
"items": { "$ref": "gamecult.eve.command.v1" }
},
"nodes": { "type": "array", "items": { "type": "object" } },
"selectedNodeId": { "type": "string" }
},
"$defs": {
"component": {
"type": "object",
"required": ["id", "kind", "props", "children"],
"properties": {
"id": { "type": "string", "minLength": 1 },
"kind": { "type": "string", "minLength": 1 },
"props": { "type": "object" },
"children": {
"type": "array",
"items": { "$ref": "#/$defs/component" }
},
"stateBindings": {
"type": "array",
"items": {
"type": "object",
"required": ["targetProp", "pointerId", "sourceId", "schemaId", "routeKind"],
"properties": {
"targetProp": { "type": "string", "minLength": 1 },
"pointerId": { "type": "string", "minLength": 1 },
"sourceId": { "type": "string", "minLength": 1 },
"schemaId": { "type": "string", "minLength": 1 },
"routeKind": { "type": "string", "minLength": 1 },
"routeDescription": { "type": "string" }
},
"additionalProperties": true
}
},
"embeddedDocuments": {
"type": "array",
"items": {
"type": "object",
"required": ["slotId", "documentId", "schemaId", "presentationKind"],
"properties": {
"slotId": { "type": "string", "minLength": 1 },
"documentId": { "type": "string", "minLength": 1 },
"schemaId": { "type": "string", "minLength": 1 },
"presentationKind": { "type": "string", "minLength": 1 },
"routeHint": { "type": ["string", "object"] }
},
"additionalProperties": true
}
}
},
"additionalProperties": true
}
},
"anyOf": [
{ "required": ["updatedAt"] },
{ "required": ["updatedAtUtc"] }
],
"additionalProperties": true
}