SitecoreAI Connector
Developer Integration
TypeScript Support

TypeScript Support

The SDK provides comprehensive TypeScript support with exported types for type-safe development.

Available Types

The SDK exports all TypeScript types, allowing you to work with Bynder asset data in a type-safe manner:

Core Types

  • AssetFile - Individual file/derivative with URL, width, height, and name
  • Asset - Complete asset object with ID, name, files, metadata, etc.
  • BynderAssetResponse - Full API response wrapping assets array
  • MetaProperties - Asset metadata including categories, tags, etc.

Derivative Types

  • ImageDerivative - Image derivative names ('mini', 'thumbnail', 'webImage', 'original')
  • VideoDerivative - Video derivative names ('mp4', 'webm')

Component Props

  • BynderDamImageProps - Props for BynderDamImage component
  • BynderDamNextImageProps - Props for BynderDamNextImage component
  • BynderDamLinkProps - Props for BynderDamLink component
  • BynderDamVideoProps - Props for BynderDamVideo component

Importing Types

Import types using TypeScript's type keyword for optimal tree-shaking:

import type {
  Asset,
  AssetFile,
  BynderAssetResponse,
  MetaProperties,
  ImageDerivative,
  VideoDerivative,
} from '@neworange/bynder-dam-connector-sitecoreai-sdk';

Why use type imports?

  • Removes types at compile time (no runtime overhead)
  • Enables better tree-shaking
  • Clearly indicates it's a type-only import
  • TypeScript best practice

Type-Safe Data Processing

Use types to create helper functions that work with Bynder data:

import type { 
  BynderAssetResponse, 
  Asset, 
  AssetFile, 
  ImageDerivative 
} from '@neworange/bynder-dam-connector-sitecoreai-sdk';
 
function processAssetMetadata(asset: BynderAssetResponse): string {
  if (!asset.assets || asset.assets.length === 0) {
    return 'No asset data available';
  }
 
  const firstAsset: Asset = asset.assets[0];
  const fileCount = firstAsset.files?.length || 0;
 
  return `Asset: ${firstAsset.name} (${firstAsset.assetType}) - ${fileCount} derivatives`;
}
 
function getPreferredDerivative(
  asset: BynderAssetResponse,
  preferred: ImageDerivative
): AssetFile | null {
  if (!asset.assets?.[0]?.files) return null;
 
  return (
    asset.assets[0].files.find((f) => f.name === preferred) ||
    asset.assets[0].files.find((f) => f.name === 'webImage') ||
    asset.assets[0].files[0] ||
    null
  );
}

Metadata Extraction

Extract and work with asset metadata in a type-safe way:

import type { 
  BynderAssetResponse, 
  MetaProperties 
} from '@neworange/bynder-dam-connector-sitecoreai-sdk';
 
function extractMetadata(asset: BynderAssetResponse): {
  id: string;
  name: string;
  type: string;
  created: Date;
  properties: MetaProperties;
} | null {
  if (!asset.assets?.[0]) return null;
 
  const firstAsset = asset.assets[0];
 
  return {
    id: firstAsset.id,
    name: firstAsset.name,
    type: firstAsset.assetType,
    created: new Date(firstAsset.createdAt),
    properties: firstAsset.metaProperties || {},
  };
}
 
// Usage
const metadata = extractMetadata(asset);
if (metadata) {
  console.log(`Asset: ${metadata.name}`);
  console.log(`Created: ${metadata.created.toLocaleDateString()}`);
  console.log(`Categories: ${metadata.properties.category?.join(', ')}`);
}

Extending Component Props

Use exported prop types to create custom wrapper components:

import { BynderDamImage } from '@neworange/bynder-dam-connector-sitecoreai-sdk';
import type { BynderDamImageProps } from '@neworange/bynder-dam-connector-sitecoreai-sdk';
 
interface CustomImageProps extends BynderDamImageProps {
  showCaption?: boolean;
  captionClassName?: string;
}
 
export function CustomBynderImage({ 
  showCaption, 
  captionClassName,
  asset,
  ...props 
}: CustomImageProps) {
  const assetName = asset?.assets?.[0]?.name;
 
  return (
    <div>
      <BynderDamImage asset={asset} {...props} />
      {showCaption && assetName && (
        <p className={captionClassName}>{assetName}</p>
      )}
    </div>
  );
}

Type Guards

Create type guards for runtime validation:

import type { 
  BynderAssetResponse, 
  Asset 
} from '@neworange/bynder-dam-connector-sitecoreai-sdk';
 
function isBynderAssetResponse(value: unknown): value is BynderAssetResponse {
  if (!value || typeof value !== 'object') return false;
  
  const v = value as BynderAssetResponse;
  return (
    v.type === 'Assets' &&
    Array.isArray(v.assets)
  );
}
 
function hasValidAssets(asset: BynderAssetResponse): boolean {
  return (
    Array.isArray(asset.assets) &&
    asset.assets.length > 0 &&
    asset.assets[0].files !== undefined
  );
}
 
// Usage
function SafeComponent({ data }: { data: unknown }) {
  if (!isBynderAssetResponse(data)) {
    return <div>Invalid data format</div>;
  }
 
  if (!hasValidAssets(data)) {
    return <div>No assets available</div>;
  }
 
  return <BynderDamImage asset={data} alt="Asset" />;
}

React Component Typing

Typed Component Props

import type { BynderAssetResponse } from '@neworange/bynder-dam-connector-sitecoreai-sdk';
 
interface ProductCardProps {
  asset: BynderAssetResponse;
  title: string;
  price: number;
}
 
export function ProductCard({ asset, title, price }: ProductCardProps) {
  return (
    <div className="product-card">
      <BynderDamImage asset={asset} alt={title} />
      <h3>{title}</h3>
      <p>${price}</p>
    </div>
  );
}

Optional Asset Props

import type { BynderAssetResponse } from '@neworange/bynder-dam-connector-sitecoreai-sdk';
 
interface HeroProps {
  asset?: BynderAssetResponse | null;
  heading: string;
  subtitle: string;
}
 
export function Hero({ asset, heading, subtitle }: HeroProps) {
  return (
    <section>
      {asset && <BynderDamImage asset={asset} alt={heading} />}
      <h1>{heading}</h1>
      <p>{subtitle}</p>
    </section>
  );
}

API Response Typing

Type API responses that return Bynder assets:

import type { BynderAssetResponse } from '@neworange/bynder-dam-connector-sitecoreai-sdk';
 
interface ApiResponse {
  success: boolean;
  data: {
    product: {
      id: string;
      name: string;
      image: BynderAssetResponse;
    };
  };
}
 
async function fetchProduct(id: string): Promise<ApiResponse> {
  const response = await fetch(`/api/products/${id}`);
  return response.json();
}
 
// Usage
const { data } = await fetchProduct('123');
return <BynderDamImage asset={data.product.image} alt={data.product.name} />;

State Management Typing

React State

import { useState } from 'react';
import type { BynderAssetResponse } from '@neworange/bynder-dam-connector-sitecoreai-sdk';
 
function Gallery() {
  const [assets, setAssets] = useState<BynderAssetResponse[]>([]);
  const [loading, setLoading] = useState<boolean>(true);
 
  // ... fetch logic
 
  return (
    <div className="gallery">
      {assets.map((asset, index) => (
        <BynderDamImage key={index} asset={asset} alt={`Image ${index + 1}`} />
      ))}
    </div>
  );
}

Redux Store

import type { BynderAssetResponse } from '@neworange/bynder-dam-connector-sitecoreai-sdk';
 
interface ProductState {
  assets: Record<string, BynderAssetResponse>;
  loading: boolean;
  error: string | null;
}
 
const initialState: ProductState = {
  assets: {},
  loading: false,
  error: null,
};

Zustand Store

import { create } from 'zustand';
import type { BynderAssetResponse } from '@neworange/bynder-dam-connector-sitecoreai-sdk';
 
interface AssetStore {
  assets: BynderAssetResponse[];
  addAsset: (asset: BynderAssetResponse) => void;
  clearAssets: () => void;
}
 
const useAssetStore = create<AssetStore>((set) => ({
  assets: [],
  addAsset: (asset) => set((state) => ({ 
    assets: [...state.assets, asset] 
  })),
  clearAssets: () => set({ assets: [] }),
}));

Server Components (Next.js)

Type server component props with Bynder assets:

import type { BynderAssetResponse } from '@neworange/bynder-dam-connector-sitecoreai-sdk';
 
interface PageProps {
  params: { id: string };
}
 
async function getData(id: string): Promise<BynderAssetResponse> {
  const res = await fetch(`https://api.example.com/assets/${id}`);
  return res.json();
}
 
export default async function AssetPage({ params }: PageProps) {
  const asset = await getData(params.id);
  
  return <BynderDamNextImage asset={asset} alt="Asset" />;
}

Common Use Cases for Standalone Types

1. API Integration

Type API responses from your Bynder integration without importing React components:

import type { BynderAssetResponse } from '@neworange/bynder-dam-connector-sitecoreai-sdk';
 
async function fetchBynderAssets(): Promise<BynderAssetResponse[]> {
  const response = await fetch('/api/bynder/assets');
  return response.json();
}

2. Data Transformation

Build utility functions to process Bynder data:

import type { Asset, AssetFile } from '@neworange/bynder-dam-connector-sitecoreai-sdk';
 
function getAssetUrl(asset: Asset, derivativeName: string): string | null {
  const file = asset.files?.find(f => f.name === derivativeName);
  return file?.url || null;
}

3. Custom Components

Create your own components with proper typing:

import type { BynderAssetResponse } from '@neworange/bynder-dam-connector-sitecoreai-sdk';
 
interface CustomGalleryProps {
  assets: BynderAssetResponse[];
  columns: number;
}
 
export function CustomGallery({ assets, columns }: CustomGalleryProps) {
  // Custom implementation
}

4. State Management

Type Redux/Zustand stores that hold Bynder assets (see examples above).

5. Server Components

Use types in Next.js server components without importing React code (see example above).

Benefits of TypeScript Support

  • Type Safety - Catch errors at compile time
  • IntelliSense - Auto-completion in your IDE
  • Documentation - Types serve as inline documentation
  • Refactoring - Safe refactoring with type checking
  • Tree-Shaking - Type imports are removed at build time
  • Developer Experience - Better DX with proper types