npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@itwin/scenes-client

v0.6.0

Published

Client-side code for managing scenes

Readme

@itwin/scenes-client

About

This package provides a TypeScript client and types for interacting with the Scenes API.

Installation

npm install @itwin/scenes-client
# or
pnpm add @itwin/scenes-client

Usage

Basic Client Setup

import { SceneClient } from "@itwin/scenes-client";

const client = new SceneClient(async () => "<itwin_platform_auth_token>");

Working with Scenes

Get a Scene

import { OrderByProperties } from "@itwin/scenes-client";

const sceneResponse = await client.getScene({
  iTwinId: "<itwin_id>",
  sceneId: "<scene_id>",
  orderBy: OrderByProperties.NAME, // Optional property to order scene data by
});

console.log(sceneResponse.scene);
/*
{
  id: "<scene_id>",
  displayName: "My Scene",
  iTwinId: "<itwin_id>",
  createdById: "<creator_id>",
  creationTime: "2025-01-01T10:00:00.000Z",
  lastModified: "2025-01-01T10:01:00.000Z",
  sceneData: { objects: [...] },
  isPartial: false
}
*/

Get List of Scenes for an iTwin

import { SceneMinimal } from "@itwin/scenes-client";

// Get a single page of scenes (for UI pagination)
const listResponse = await client.getScenes({
  iTwinId: "<itwin_id>",
  top: 10, // Optional, defaults to 100
  skip: 5, // Optional, defaults to 0
});

console.log(`Found ${listResponse.scenes.length} scenes on this page.`);
listResponse.scenes.forEach((scene: SceneMinimal) => {
  console.log(`${scene.displayName} (${scene.id})`);
});

Get All Scenes with Iterator

import { SceneMinimal } from "@itwin/scenes-client";

// Get all scenes using async iterator
const allScenesIterator = await client.getAllScenes({
  iTwinId: "<itwin_id>",
});

let totalScenes = 0;
for await (const page of allScenesIterator) {
  console.log(`Processing ${page.scenes.length} scenes...`);
  page.scenes.forEach((scene: SceneMinimal) => {
    console.log(`${scene.displayName}`);
    totalScenes++;
  });
}

console.log(`Processed ${totalScenes} total scenes`);

Create a Scene

const createResponse = await client.postScene({
  iTwinId: "<itwin_id>",
  scene: {
    displayName: "Construction Site Overview",
    sceneData: {
      objects: [
        /** (optional) objects to create */
      ],
    },
  },
});

console.log(`Created scene: ${createResponse.scene!.displayName}`);

Replace a Scene

// Fully replace an existing scene by id. Will create a new scene if provided sceneId does not exist.
const putResponse = await client.putScene({
  iTwinId: "<itwin_id>",
  sceneId: "<scene_id>",
  scene: {
    displayName: "Full Scene Payload",
    sceneData: {
      objects: [
        /** (optional) full list of scene objects */
      ],
    },
  },
});

console.log(`Created or replaced scene: ${putResponse.scene!.displayName}`);

Update a Scene's metadata

const updateResponse = await client.patchScene({
  iTwinId: "<itwin_id>",
  sceneId: "<scene_id>",
  scene: {
    displayName: "Updated Scene Name",
  },
});

console.log(`Updated scene: ${updateResponse.scene!.displayName}`);

Delete a Scene

await client.deleteScene({
  iTwinId: "<itwin_id>",
  sceneId: "<scene_id>",
});

console.log("Scene deleted successfully");

Working with Scene Objects

Get a Scene Object

const objectResponse = await client.getObject({
  iTwinId: "<itwin_id>",
  sceneId: "<scene_id>",
  objectId: "<object_id>",
});

console.log(objectResponse.object);
/*
{
  id: "<object_id>",
  sceneId: "<scene_id>",
  displayName: "My View3d Object",
  kind: "View3d",
  version: "1.0.0",
  data: { ... },
  createdById: "<creator_id>",
  creationTime: "2025-01-01T10:00:00.000Z",
  lastModified: "2025-01-01T10:01:00.000Z"
}
*/

Get List of Objects in a Scene

import { OrderByProperties, SceneObject } from "@itwin/scenes-client";

// Get a single page of objects (for UI pagination)
const listResponse = await client.getObjects({
  iTwinId: "<itwin_id>",
  sceneId: "<scene_id>",
  orderBy: OrderByProperties.NAME, // Optional property to order results by
  top: 10, // Optional, defaults to 100
  skip: 5, // Optional, defaults to 0
});

console.log(`Found ${listResponse.objects.length} objects on this page.`);
listResponse.objects.forEach((object: SceneObject) => {
  console.log(`${object.displayName} (${object.id})`);
});

Get All Objects with Iterator

import { SceneObject } from "@itwin/scenes-client";

// Get all objects in a scene using async iterator
const allObjectsIterator = await client.getAllObjects({
  iTwinId: "<itwin_id>",
  sceneId: "<scene_id>",
});

let totalObjects = 0;
for await (const page of allObjectsIterator) {
  console.log(`Processing ${page.objects.length} objects...`);
  page.objects.forEach((object: SceneObject) => {
    console.log(`${object.id}`);
    totalObjects++;
  });
}

console.log(`Processed ${totalObjects} total objects`);

Create Scene Objects

import {
  SceneObject,
  iModelVisibilityCreate,
  LayerCreate,
  RepositoryCreate,
  RepositoryResourceCreate,
  View3dCreate,
} from "@itwin/scenes-client";

// Create objects with strongly typed interfaces
// Note: LayerCreate is an alias for StandardObjectCreate<"Layer", "1.0.0">
const layer: LayerCreate = {
  id: "<layer_id>", // Optional, will be auto-generated if not provided
  kind: "Layer",
  version: "1.0.0",
  displayName: "Buildings", // Optional
  visible: true, // Optional, sets initial visibility state
  data: {},
};

// Note: RepositoryResourceCreate is an alias for StandardObjectCreate<"RepositoryResource", "1.0.0">
const iModelResource: RepositoryResourceCreate = {
  id: "<imodel_object_id>", // Optional
  kind: "RepositoryResource",
  version: "1.0.0",
  displayName: "Main Building Model", // Optional
  parentId: "<layer_id>", // Organize under the layer
  visible: true, // Optional, sets initial visibility state
  data: {
    iTwinId: "<itwin_id>",
    class: "iModels",
    repositoryId: "iModels",
    id: "<imodel_id>",
  },
};

// Note: iModelVisibilityCreate is an alias for ResourceStylingObjectCreate<"iModelVisibility", "1.0.0">
const iModelStyling: iModelVisibilityCreate = {
  kind: "iModelVisibility",
  version: "1.0.0",
  displayName: "Hide Building Elements",
  relatedId: "<imodel_object_id>", // References the iModel resource to style
  data: {
    categories: {
      shownList: "",
      hiddenList: "+300000000A0+ED1+3*2+4+D+3*2+8+4*3+3*5+2+3*4+4+3*2+4*2+3*3+5+4+5+4+8+3*2+5+4+7F",
    },
    models: {
      shownList: "",
      hiddenList: "+20000000002",
    },
    perModelCategoryVisibility: [
      { modelId: "0x20000000079", categoryId: "0x2000000003e", visible: false },
    ],
    alwaysDrawn: "+1*4+4*3",
    neverDrawn: "+21234567890+10000000000*2+20000000000",
  },
};

// Note: View3dCreate is an alias for StandardObjectCreate<"View3d", "1.0.0">
const view3d: View3dCreate = {
  kind: "View3d",
  version: "1.0.0",
  displayName: "Aerial View", // Optional
  data: {
    position: { x: -50.0, y: 75.0, z: 150.0 },
    direction: { x: 0.2, y: 0.2, z: -0.96 },
    isOrthographic: false,
    up: { x: 0, y: 1, z: 0 },
    aspectRatio: 1.33,
    near: 1,
    far: 1000,
    ecefTransform: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
  },
};

// Note: RepositoryCreate is an alias for StandardObjectCreate<"Repository", "1.0.0">
const formsRepository: RepositoryCreate = {
  kind: "Repository",
  version: "1.0.0",
  displayName: "iTwin A Forms", // Optional
  data: {
    iTwinId: "<itwin_id>",
    repositoryId: "Forms",
    class: "Forms",
  },
};

// Create objects in bulk
const createResponse = await client.postObjects({
  iTwinId: "<itwin_id>",
  sceneId: "<scene_id>",
  objects: [layer, view3d, iModelResource, iModelStyling, formsRepository],
});

console.log(`Created ${createResponse.objects.length} objects:`);
createResponse.objects.forEach((obj: SceneObject) => {
  console.log(`Created ${obj.kind} object: ${obj.displayName} (${obj.id})`);
});

Update Scene Objects

import {
  SceneObject,
  SceneObjectUpdate,
  SceneObjectOperation,
  OperationType,
} from "@itwin/scenes-client";

// Update data for a single object with type safety
const objectUpdate: SceneObjectUpdate<"GoogleTilesStyling", "1.0.0"> = {
  displayName: "Updated Global Styling Options",
  data: {
    // Fully typed - IntelliSense shows available properties
    quality: 0.30000001192092896,
    adjustment: [1.309999942779541, 72.0326, -75.6275],
  },
};

const updateResponse = await client.patchObject({
  iTwinId: "<itwin_id>",
  sceneId: "<scene_id>",
  objectId: "<object_id>",
  object: objectUpdate,
});

console.log(`Updated object: ${updateResponse.object.displayName}`);

// Update many scene objects with atomic operations
// All operations execute in provided order
const operations: SceneObjectOperation[] = [
  // 1: Add a new Layer object
  {
    op: OperationType.CREATE,
    payload: {
      id: "<new_layer_id>", // Optional, will be auto-generated if not provided
      kind: "Layer",
      version: "1.0.0",
      displayName: "New Construction Phase", // Optional
      visible: true, // Optional, sets initial visibility state
      data: {},
    },
  },
  //2: Move existing object to the new layer
  {
    op: OperationType.UPDATE,
    id: "<existing_object_id>",
    payload: { parentId: "<new_layer_id>" },
  },
  // 3: Remove old Layer
  { op: OperationType.DELETE, id: "<old_layer_id>" },
  // 4-6: Reorder scene objects
  { op: OperationType.UPDATE, id: "<object_id_1>", payload: { order: 1 } },
  { op: OperationType.UPDATE, id: "<object_id_2>", payload: { order: 2 } },
  { op: OperationType.UPDATE, id: "<object_id_3>", payload: { order: 3 } },
];

const bulkUpdateResponse = await client.patchObjectsOperations({
  iTwinId: "<itwin_id>",
  sceneId: "<scene_id>",
  operations, // Maximum 100 operations per request
});

bulkUpdateResponse.objects.forEach((obj: SceneObject) => {
  console.log(`Created or updated ${obj.kind} object: ${obj.displayName} (${obj.id})`);
});

Delete Scene Objects

// Delete a single object by id
await client.deleteObject({
  iTwinId: "<itwin_id>",
  sceneId: "<scene_id>",
  objectId: "<object_id>",
});

// Delete objects in bulk
await client.deleteObjects({
  iTwinId: "<itwin_id>",
  sceneId: "<scene_id>",
  objectIds: ["<object_id_1>", "<object_id_2>", "<object_id_3>"],
});

Type Safety

This client provides strongly typed interfaces for all scene object operations, giving you compile-time validation:

import { StandardObjectCreate, ResourceStylingObjectCreate } from "@itwin/scenes-client";

// Each schema has its own typed interface
const camera: StandardObjectCreate<"CameraAnimation", "1.0.0"> = {
  kind: "CameraAnimation",
  version: "1.0.0",
  displayName: "Site Walkthrough",
  data: {
    input: [0, 5, 10, 15], // TypeScript knows this should be number[]
    output: [
      {
        camera: {
          position: { x: 0, y: 0, z: 100 },
          direction: { x: 0, y: 1, z: 0 },
          up: { x: 0, y: 0, z: 1 },
          // IntelliSense shows all available camera properties
        },
      },
    ],
  },
};

// Resource styling objects automatically require relatedId
const styling: ResourceStylingObjectCreate<"iModelVisibility", "1.0.0"> = {
  kind: "iModelVisibility",
  version: "1.0.0",
  relatedId: "<repository_object_id>", // TypeScript enforces this field
  data: {
    // IntelliSense shows iModelVisibility specific properties
    categories: { ... },
    models: { ... },
  },
};

Error Handling

import { SceneApiError } from "@itwin/scenes-client";

try {
  const scene = await client.getScene({
    iTwinId: "<itwin_id>",
    sceneId: "<invalid_scene_id>",
  });
} catch (error) {
  if (error instanceof SceneApiError) {
    console.error(`Error getting scene: ${error.status} - ${error.message}`);
    console.error(`Details ${error.details}`);
  }
}

Issues

Please report bugs, feature requests, or questions using the GitHub Issues page.


Copyright © Bentley Systems, Incorporated. All rights reserved. See LICENSE.md for license terms and full copyright notice.