type: reference
title: "Studio Package Contracts (@honua/sdk-js/studio)"
description: "One browser-safe import path for the Studio package families, the unified validation and preview envelopes, the capability manifest, and the publish, share and embed contracts."
resource: "https://www.npmjs.com/package/@honua/sdk-js"
Studio Package Contracts (@honua/sdk-js/studio)
Status: experimental.
@honua/sdk-js/studio is the single, browser-safe import path for the Studio
package families, their unified validation/preview envelopes, the capability
manifest, and the publish/share/embed contracts. It exists so Console browser
interop, MCP, QGIS, generated apps, and embeds consume one set of
server-owned contract projections instead of forking their own package
schemas.
import {
HONUA_QUERY_PACKAGE_FORMAT_V1,
type HonuaStudioPackage,
type StudioPackageValidationResponse,
tagStudioPackage,
toStudioValidationResponse,
} from "@honua/sdk-js/studio";
MCP / QGIS safety
The barrel exports only types and pure functions and never imports from
operator, esri-compat, web-components, interactions, or realtime —
none of the MapLibre/DOM/Console-coupled modules. MCP servers and QGIS plugins
can import @honua/sdk-js/studio without pulling renderer code or triggering a
build error from Console/Esri internals.
The established map and app shapes are re-exported from their leaf modules.
The distinct dashboard artifact is authored by the sdk-js Studio agent path;
Console and other renderers consume the validated package read-only.
The map family additionally has a published JSON Schema,
schemas/honua-map-package.v1.json
(https://honua.io/schemas/honua-map-package.v1.json). It is the canonical
description of the artifact for JS, the CLI, MCP, and Studio alike, and it is what validateMapPackage is built from. exportMapPackage / importMapPackage
(@honua/sdk-js/runtime) move that artifact between clients without embedded
credentials or unbounded data.
The schema deliberately stops at the artifact. Lifecycle states (ephemeral preview, mutable draft, immutable saved version, publication proposal, active publication, superseded), content-hash identity, optimistic concurrency, and actor/tenant/authorization fields belong to the canonical honua-server composition contract and are never minted client-side.
Package families and format constants
Each family is gated by a format constant — the canonical version string,
exactly as on MapPackage. A loader refuses any other value.
| Family | Format constant | Format string | Projection type | Stability |
|---|---|---|---|---|
| query | HONUA_QUERY_PACKAGE_FORMAT_V1 |
honua_query_package.v1 |
HonuaQueryPackage |
experimental (stub) |
| analysis | HONUA_ANALYSIS_PACKAGE_FORMAT_V1 |
honua_analysis_package.v1 |
HonuaAnalysisPackage |
experimental (stub) |
| map | HONUA_MAP_PACKAGE_FORMAT_V1 |
honua_map_package.v1 |
HonuaMapPackage |
stable family, re-exported |
| dashboard | HONUA_DASHBOARD_PACKAGE_FORMAT_V1 |
honua_dashboard_package.v1 |
HonuaDashboardPackage |
experimental, Studio-authored |
| report | HONUA_REPORT_PACKAGE_FORMAT_V1 |
honua_report_package.v1 |
HonuaReportPackage |
experimental (stub) |
| form | HONUA_FORM_PACKAGE_FORMAT_V1 |
honua_form_package.v1 |
HonuaFormPackage |
experimental (stub) |
| app | — (uses HonuaGeneratedAppPackage.version) |
— | HonuaGeneratedAppPackage |
re-exported |
| workflow | HONUA_WORKFLOW_PACKAGE_FORMAT_V1 |
honua_workflow_package.v1 |
HonuaWorkflowPackage |
experimental (stub) |
| gp | HONUA_GP_PACKAGE_FORMAT_V1 |
honua_gp_package.v1 |
HonuaGPPackage |
experimental (stub) |
| etl | HONUA_ETL_PACKAGE_FORMAT_V1 |
honua_etl_package.v1 |
HonuaETLPackage |
experimental (stub) |
The stub families (query, analysis, report, form, workflow, gp, etl) have no
finalized server contract yet. Their interfaces are minimal and open-ended
(every field optional beyond packageId/format, plus [extra: string]: unknown) so additive server changes never break a client. They expand once the
matching server contract lands. The map and generated-app (app) families
are established shapes; dashboard is a dedicated Studio-authored artifact.
Lifecycle status is shared across families via HonuaStudioPackageStatus
("Draft" | "Composing" | "Ready" | "Failed" | "Expired"), the same union as
HonuaMapPackageStatus.
The HonuaStudioPackage discriminated union
HonuaStudioPackage is a union tagged by a client-side packageFamily field.
The server wire shape does not carry packageFamily — projection helpers
add it. Build a tagged value with tagStudioPackage(family, pkg) rather than
casting a raw wire object, then narrow on packageFamily:
const tagged = tagStudioPackage("query", rawQueryPackage);
if (tagged.packageFamily === "query") {
// tagged is narrowed to { packageFamily: "query" } & HonuaQueryPackage
console.log(tagged.querySpec?.where);
}
STUDIO_PACKAGE_FAMILIES enumerates every family discriminant and
isStudioPackageFamily(value) guards an untrusted string.
Unified validation response
Every family returns the same { valid, diagnostics, pkg? } shape through
StudioPackageValidationResponse<T>, so SDK, Console, MCP, and QGIS clients
consume one contract:
interface StudioPackageValidationResponse<T> {
readonly valid: boolean;
readonly diagnostics: readonly StudioPackageDiagnostic[];
readonly pkg?: T;
}
The existing map-family ValidateMapPackageResult is not renamed — it is
structurally bridged:
import { validateMapPackage } from "@honua/sdk-js/runtime";
import { fromMapPackageValidation } from "@honua/sdk-js/studio";
const response = fromMapPackageValidation(validateMapPackage(rawMapPackage));
// response: StudioPackageValidationResponse<HonuaMapPackage>
For other families, the generic adapter takes the field name holding the package:
toStudioValidationResponse<HonuaQueryPackage>(rawQueryResult, "queryPackage");
HonuaMapPackageDiagnostic is already a structural subtype of
StudioPackageDiagnostic (it only adds packageId?), so map diagnostics flow
through unchanged. For convenience, fromMapPackageValidation and
toStudioValidationResponse are also re-exported from @honua/sdk-js/runtime
(tagged @experimental) so existing map-package consumers can bridge from the
path they already use.
StudioPackagePreviewResponse<T> is the parallel envelope for previewing a
package (composed without publishing), carrying optional artifacts and
diagnostics.
Capability manifest
StudioCapabilityManifest lets a client gate UI/tool exposure on what the
connected server actually supports:
import { hasCapability, getCapability } from "@honua/sdk-js/studio";
if (hasCapability(manifest, "package.query")) {
// advertise the query builder
}
hasCapability is true only for an advertised and available capability;
getCapability returns the entry regardless of enabled state.
Every entry preserves the server-owned lifecycle and optInRequired
governance fields. Lifecycle remains an open string so future values are not
coerced to GA; missing governance fields raise
HonuaCapabilityManifestContractError instead of silently defaulting.
Publish, share, and embed
StudioPublishRequest<T>, StudioPublishResponse, and StudioEmbedConfig
carry the versioned publication contract for generated artifacts.
HonuaShareRequest / HonuaShareResponse are re-exported from
control-plane/types (single source of truth — not re-declared) so Console
and MCP reach the share contract from the one @honua/sdk-js/studio path
without taking on the full control-plane client.
StudioEmbedConfig.token / embedUrl describe an already-issued embed
descriptor; the type does not imply a token-minting call inside the SDK.
Generated apps
Generated apps consume published map, dashboard, report, and app
package projections from @honua/sdk-js/studio without importing Console or
MapLibre code. HonuaDashboardPackage is the authored dashboard artifact;
HonuaGeneratedAppManifest remains a runtime hydration projection rather than
the dashboard authoring wire format. For the preview runtime, see
docs/generated-app-runtime.md.
Versioning
Every new export is tagged @experimental in JSDoc and is subpath-only (not
re-exported from the root barrels), so it is outside the SDK semver contract
until the matching server contracts land. The format constants follow the
HONUA_X_PACKAGE_FORMAT_V1 = "honua_x_package.v1" pattern.
For dashboard, additive optional fields remain compatible within
honua_dashboard_package.v1. Removing or renaming a field, changing its
meaning, or changing requiredness requires a new format discriminator. Readers
preserve unknown properties, writers emit only explicitly supported formats,
and validators never guess, downgrade, or rewrite an unknown format. Renderer
state is derived and must not be serialized back into the authored package.
The dashboard artifact may reference the portable map artifact through
mapPackageId; it does not embed credentials or mint
another map representation. Publication state, stable lifecycle identity,
tenant/actor, authorization, optimistic concurrency, audit, and correlation
remain outside the package.
Cross-surface parity (MCP / QGIS)
The parity layer that makes packages portable across Console, MCP, and QGIS —
a shared provenance envelope, a family-agnostic validateStudioPackage
helper, a documented Vega-Lite chart subset, and cross-surface fixtures — is
documented in studio-package-parity.md.