@astrato-io/sdk

中文文档
0.6.0发布于 2026/10/29SEE LICENSE IN LICENSETypeScriptES Module近 30 天下载 1.8万

Browser SDK for connecting custom applications to Astrato APIs and runtime services.

原始使用文档
文档目录12 节
  1. Installation
  2. Create A Client
  3. Embedded iframe bridge
  4. Data And Metadata
  5. Authenticated Requests And Customization
  6. Visualization Engine
  7. Using Visualizations With The SDK
  8. Host Services
  9. Selection State
  10. Persistence Behavior
  11. Events And Cleanup
  12. Package Build

@astrato-io/sdk

Browser SDK for connecting custom applications to Astrato APIs and runtime services.

Use this package for authentication, Astrato API requests, data and metadata access, events, variables, and group-scoped selection state. Visualization rendering is provided separately by @astrato-io/visualizations.

Installation

npm install @astrato-io/sdk

The package is distributed as ESM and requires a browser environment with fetch, Headers, and URL. RxJS is installed as a package dependency and is used by the public observable APIs.

Create A Client

import { createAstratoClient } from '@astrato-io/sdk';

const client = createAstratoClient({
  baseUrl: 'https://your-astrato-instance.example/',
  tenantId: 'tenant-id',
  auth: {
    token: 'personal-access-token',
  },
  visualizationEngine: true,
});

baseUrl is required. tenantId is used as the default tenant for data and metadata requests.

Authentication can use a fixed token, an asynchronous token provider, or custom headers:

const client = createAstratoClient({
  baseUrl,
  tenantId,
  auth: {
    getAccessToken: async () => refreshAccessToken(),
    headers: {
      'x-client-name': 'customer-portal',
    },
  },
});

When a token is available, the SDK sends it as Authorization: Bearer <token> unless an authorization header was supplied explicitly.

Embedded iframe bridge

An application embedded in a trusted host can use the same SDK client without receiving host credentials. The host establishes a versioned MessagePort connection with one iframe and handles requests through an allowlisted callback. This is an explicit bootstrap: merely being inside an iframe never enables the bridge.

In the host, create the bridge before the iframe application starts. The request callback must validate the relative SDK path, HTTP method, tenant, semantic layer, and operation against the host's own authorization rules, then execute the approved operation with credentials retained in the host. Do not forward child-supplied headers to a privileged network client without a deliberate allowlist. If the bridge is attached after the iframe has already loaded, pass initialLoadComplete: true; this lets the bridge distinguish the first load from a later navigation.

import { createAstratoIframeHostBridge } from '@astrato-io/sdk';

const bridge = createAstratoIframeHostBridge({
  iframe,
  childOrigin: 'null', // for an intentionally opaque sandbox; otherwise use the exact child origin
  context: {
    tenantId,
    semanticLayer: { id: semanticLayerId, datasourceType },
    capabilities: ['query', 'metadata'],
  },
  request: (request, signal) => executeAllowedSdkRequest(request, signal),
});

// Destroy when the iframe is removed or its authority changes.
bridge.destroy();

The iframe's trusted application bootstrap supplies the exact parent origin and connects once. After that, shared application runtime code can discover the established connection synchronously and create the ordinary visualization-enabled client:

import { connectAstratoIframeBridge, getAstratoIframeBridge } from '@astrato-io/sdk';

await connectAstratoIframeBridge({ parentOrigin: trustedParentOrigin });

const connection = getAstratoIframeBridge();
if (!connection) throw new Error('Astrato iframe bridge is unavailable.');
const client = connection.createClient();

createClient() never falls back to fetch. The bridge rejects absolute URLs and credential-bearing headers, bounds request and response sizes, and supports request aborts, timeouts, and disconnect cleanup. Host requests run up to maxConcurrentRequests at once (16 by default); excess requests wait in arrival order, with at most 32 active and queued requests combined. The request timeout includes time spent waiting. An aborted or timed-out active request keeps its concurrency slot until the host callback settles, so the host limit remains accurate even if that callback ignores abort. Host errors are returned as generic codes so private details are not sent to the iframe. The host callback remains the authorization boundary; the context's capabilities list is descriptive. The protocol version is exported as ASTRATO_IFRAME_BRIDGE_PROTOCOL_VERSION and incompatible versions do not connect. Destroying or replacing a connection destroys its SDK clients and invalidates their metadata caches.

Data And Metadata

The direct data service uses the current Astrato data and schema APIs. Query payloads are passed through without hidden filter, variable, or selection changes.

Semantic layer metadata is loaded from the tenant-scoped data view composite endpoint: /api/message/tenants/{tenantId}/schema/dataviews/{semanticLayerId}/composite. This response provides engine field keys, semantic item keys and view connectivity without reconstructing identity from schema, view or field names.

const metadata = await client.services.data.getSemanticLayerMetadata?.('semantic-layer-id');

const result = await client.hostServices.engine.getData({
  semanticLayerId: 'semantic-layer-id',
  query: {
    dimensions: [],
    measures: [],
  },
});

When the visualization engine executes a query, it retains the latest successful query metadata for each visualization object ID. Use that metadata to show the executed SQL, duration, result size, vendor query link, or real warehouse query insights without issuing the data query again:

const metadata = client.hostServices.engine.getLastQueryMetadata?.('sales-by-manufacturer');

const insights =
  metadata?.semanticLayerId && metadata.startTime !== undefined
    ? await client.hostServices.engine.getQueryInsights?.({
        queryID: metadata.queryID,
        semanticLayerId: metadata.semanticLayerId,
        startTime: metadata.startTime,
      })
    : undefined;

Query metadata is isolated by the request context's objectId. If multiple requests for one object overlap, only the newest request may update its metadata. Query-insights availability and response details depend on the connected warehouse.

The visualization engine maps semanticLayerId to the current engine API's legacy databaseID wire field. The low-level client.services.data.query() method remains transparent and posts its query value without rewriting it.

Request context can be configured once on the client and overridden per query:

const client = createAstratoClient({
  baseUrl,
  tenantId,
  auth: { token },
  context: {
    datasourceType: 'snowflake',
    sheetId: 'sheet-id',
    workbookState: 'draft',
    workbookVersionContainerId: 'workbook-version-container-id',
  },
});

Authenticated Requests And Customization

Use client.request() for Astrato endpoints that do not have a dedicated service method. The request uses the configured base URL, authentication, transport events, and error logging:

const response = await client.request({
  method: 'GET',
  url: 'api/example',
});

createAstratoClient() also accepts a custom transport, logger, event bus, data endpoint overrides, and host-service implementations. These options allow applications to integrate their own networking, diagnostics, or platform services without changing visualization code.

Visualization Engine

Current Astrato visualization wrappers require a small synchronous engine surface. Enable the SDK's visualization engine explicitly when the client is used with @astrato-io/visualizations:

const client = createAstratoClient({
  baseUrl,
  tenantId,
  auth: { token },
  visualizationEngine: true,
});

await client.hostServices.engine.fields.getFieldMetadata?.({
  semanticLayerId: 'semantic-layer-id',
  tenantId,
});

Metadata snapshots are reused within one client for five minutes, with at most 16 completed snapshots retained. Pending requests for the same tenant, semantic layer, datasource, and authentication authority share one load. Configure metadataCache on createAstratoClient() when a different bound is appropriate. Call client.hostServices.engine.fields.invalidateMetadata() after a model change; pass the same metadata request to invalidate one layer, or omit it to clear all snapshots. refreshMetadata(request) clears and reloads one layer. A page reload creates a new client and therefore starts with an empty cache.

The default engine resolves authentication once per metadata operation or query and binds its requests to the same headers. Concurrent operations share pending authentication resolution. Callbacks that return a new token on each invocation are supported. When any SDK request observes changed authentication headers, the default engine clears its cached and active metadata. Load metadata again before reading synchronous field or connectivity APIs. Queries resolve authentication before transformation so they cannot substitute fields from the previous authority's metadata. A metadata operation or engine query rejects if a subsequent SDK operation observes changed authentication before it completes; rejected query results do not update query metadata. An older authentication lookup that finishes after a newer successful lookup rejects if its credentials differ from the current ones. Ordinary requests continue resolving their own authentication. Applications that provide their own transport authority without SDK authentication must call invalidateMetadata() when that authority changes. Query results are never cached.

Destroying a client invalidates metadata only in an engine created by that client. An engine supplied through hostServices.engine remains owned by its caller. Grouped-dimension choices survive cache hits; a fresh metadata load initializes them from the model again.

The asynchronous metadata call loads the engine snapshot. Field getters and connectivity checks then read that snapshot synchronously, as required by the visualization wrappers. Fields are identified by engine fieldKey values; the SDK does not parse field keys into view/name references. Semantic dimensions, measures and calculations use the keys and related views supplied by the composite response. View names are retained only where existing visualization APIs still request view-level connectivity.

Projected visualization fields temporarily include schema: 'legacy' because visualization packages still require a nonempty value. This compatibility placeholder is independent of the source database schema and overrides any incoming field schema; it does not change canonical engine keys or source metadata. Consumers should use field keys for identity. Removal of this requirement and placeholder is tracked in ASTA-15281.

Using Visualizations With The SDK

Install both packages and import the visualization stylesheet once in the host application:

npm install @astrato-io/sdk @astrato-io/visualizations
import '@astrato-io/visualizations/styles.css';

Create one SDK client and one visualization runtime for the application. The visualization engine must be enabled so the runtime can load data and semantic-layer metadata through the SDK:

import { createAstratoClient } from '@astrato-io/sdk';
import { createVisualizationRuntime, registerAstratoElements, registry } from '@astrato-io/visualizations';

const tenantId = 'tenant-id';
const semanticLayerId = 'semantic-layer-id';

const client = createAstratoClient({
  baseUrl: 'https://your-astrato-instance.example/',
  tenantId,
  auth: { token: 'personal-access-token' },
  visualizationEngine: true,
});

const runtime = createVisualizationRuntime({
  client,
  registry,
});

runtime.createInstance({
  id: 'sales-by-manufacturer',
  type: 'bar',
  groupId: 'dashboard',
  dataBinding: {
    tenantId,
    semanticLayerId,
    datasourceType: 'snowflake',
  },
});

registerAstratoElements({ runtime });

Render the runtime-owned instance with the framework-neutral web component:

<astrato-visualization instance-id="sales-by-manufacturer"></astrato-visualization>

The element must have non-zero dimensions:

astrato-visualization {
  display: block;
  width: 100%;
  height: 400px;
}

If vSpec is omitted, the runtime creates an empty default visualization. To create a useful initial visualization, use compileVisualizationDefinition() from @astrato-io/visualizations/definitions with semantic-layer metadata loaded through client.hostServices.engine.fields.getFieldMetadata(). Pass the compiled vSpec to runtime.createInstance(). Definitions use exact engine keys and return structured validation issues when compilation fails.

Applications that manage DOM lifecycle directly can mount without a web component:

const container = document.getElementById('chart');

if (!container) {
  throw new Error('Missing chart container.');
}

const handle = await runtime.mount(container, 'sales-by-manufacturer');
const renderResult = await handle.ready;

console.log(renderResult.status);

handle.unmount();
runtime.removeInstance('sales-by-manufacturer');

Instances with the same groupId share selection state. Removing a web component unmounts it automatically; remove runtime instances when they are no longer needed and call client.destroy() when the application disposes the SDK client.

See the @astrato-io/visualizations package README for supported visualization IDs, complete definition schemas, operations, getters, metadata discovery, and custom-element options.

Host Services

The client exposes the same host services through client.services and client.hostServices. SDK and transport events are available separately through client.events.

ServicePurpose
dataQueries, semantic layer metadata, datasource metadata, aggregations, and capabilities
engineOptional visualization-compatible query and field adapter
selectionsGroup-scoped applied and pending selection state
variablesVariable lookup and value resolution
modelVisualization model save compatibility hooks

Applications can replace individual services through hostServices:

const client = createAstratoClient({
  baseUrl,
  hostServices: {
    variables: customVariableService,
  },
});

Data and engine defaults fail clearly when required configuration is missing. Selection and variable defaults use in-memory state.

Selection State

Selections are isolated by groupId. Value and associative selections use their kind together with the engine field key as identity, so both kinds can coexist for one field.

client.services.selections.selectValues('dashboard', {
  field: { fieldKey: '[Orders].[Country]' },
  operator: 'inList',
  values: ['Sweden'],
});

const subscription = client.services.selections.onActiveSelectionChangeApplied('dashboard').subscribe((selection) => {
  console.log(selection.applied);
});

subscription.unsubscribe();

Selection mode defaults to auto. In manual mode, changes remain pending until applyPendingSelections(groupId) is called.

Persistence Behavior

The SDK does not persist visualization or workbook state by default.

  • model.saveProperties() and model.saveLocalVSpec() are compatibility no-ops.
  • No implicit localStorage or IndexedDB storage is used.

Events And Cleanup

const unsubscribe = client.events.on('transport:error', (event) => {
  console.error(event.payload);
});

unsubscribe();
client.destroy();

destroy() clears SDK event subscriptions. Applications should also unsubscribe from service observables they own.

Package Build

The package contains a minified ESM bundle, a single public TypeScript declaration file, this README, package metadata, the supplied LICENSE document, and any notice documents. It contains no source maps. RxJS remains external so application bundlers can deduplicate and tree-shake it.

The JavaScript implementation and public API types are visible to package users. Minification does not make client-side code confidential. Credentials and access rules must remain in the host application and Astrato APIs.

版本与发布记录

@astrato-io/sdk 共发布 3 个版本,首次发布于 2026/10/20;过去 12 个月发布了 3 个版本。

版本发布日期距今
0.6.0latest2026/10/2910 天前
0.5.02026/10/2018 天前
0.0.0-stage2026/10/2018 天前

关于 @astrato-io/sdk 的常见问题

@astrato-io/sdk 是什么?

Browser SDK for connecting custom applications to Astrato APIs and runtime services.

如何安装 @astrato-io/sdk?

在项目目录运行 npm install @astrato-io/sdk,或使用 pnpm add / yarn add / bun add。

@astrato-io/sdk 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@astrato-io/sdk 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@astrato-io/sdk 可以商用吗?

@astrato-io/sdk 使用 SEE LICENSE IN LICENSE 许可。许可条款写在包内的独立文件中,请阅读该文件确认可否商用。以上为概括,不构成法律意见,请以许可原文为准。

@astrato-io/sdk 的下载量有多少?

根据 npm 官方下载统计,@astrato-io/sdk 在 2026/10/07 – 2026/11/05 这 30 天内被下载 17,648 次,日均约 588 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@astrato-io/sdk 还在维护吗?

最新版本 0.6.0 发布于 2026/10/29(10 天前);至今共发布 3 个版本,其中过去 12 个月发布了 3 个;首次发布于 2026/10/20。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。