CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-ai-sdk--provider

TypeScript specification and interface definitions for AI language model providers within the Vercel AI SDK ecosystem

Pending
Overview
Eval results
Files

json-utilities.mddocs/

JSON Utilities

Type-safe JSON handling utilities for working with structured data, providing runtime type checking and validation for JSON values.

Capabilities

JSON Type Definitions

Comprehensive type definitions for JSON data structures.

/**
 * Union type representing all valid JSON values
 */
type JSONValue = null | string | number | boolean | JSONObject | JSONArray;

/**
 * JSON object type with string keys and JSON values
 */
type JSONObject = { [key: string]: JSONValue };

/**
 * JSON array type containing JSON values
 */
type JSONArray = JSONValue[];

Type Guard Functions

Runtime type checking functions to validate JSON data structures.

/**
 * Check if a value is a valid JSON value
 * @param value - Value to check
 * @returns True if value is a valid JSON value
 */
function isJSONValue(value: unknown): value is JSONValue;

/**
 * Check if a value is a JSON array
 * @param value - Value to check
 * @returns True if value is a JSON array
 */
function isJSONArray(value: unknown): value is JSONArray;

/**
 * Check if a value is a JSON object
 * @param value - Value to check
 * @returns True if value is a JSON object (not null or array)
 */
function isJSONObject(value: unknown): value is JSONObject;

Usage Examples:

import {
  JSONValue,
  JSONObject,
  JSONArray,
  isJSONValue,
  isJSONArray,
  isJSONObject
} from "@ai-sdk/provider";

// Basic type checking
function processUserData(data: unknown): JSONObject {
  if (!isJSONObject(data)) {
    throw new Error('Expected JSON object');
  }
  
  return data; // TypeScript now knows this is JSONObject
}

// Validate API response
async function fetchAndValidateData(url: string): Promise<JSONObject> {
  const response = await fetch(url);
  const data = await response.json();
  
  if (!isJSONValue(data)) {
    throw new Error('Response is not valid JSON');
  }
  
  if (!isJSONObject(data)) {
    throw new Error('Expected JSON object response');
  }
  
  return data;
}

// Safe array processing
function processItems(items: unknown): string[] {
  if (!isJSONArray(items)) {
    throw new Error('Expected JSON array');
  }
  
  return items
    .filter((item): item is string => typeof item === 'string')
    .map(item => item.trim());
}

// Deep JSON validation
function validateJSONStructure(data: unknown): JSONValue {
  if (data === null) return null;
  
  if (typeof data === 'string' || 
      typeof data === 'number' || 
      typeof data === 'boolean') {
    return data;
  }
  
  if (Array.isArray(data)) {
    return data.map(validateJSONStructure) as JSONArray;
  }
  
  if (typeof data === 'object') {
    const result: JSONObject = {};
    for (const [key, value] of Object.entries(data)) {
      result[key] = validateJSONStructure(value);
    }
    return result;
  }
  
  throw new Error(`Invalid JSON value: ${typeof data}`);
}

// Schema validation helper
interface UserSchema {
  name: string;
  age: number;
  email: string;
  preferences: {
    theme: 'light' | 'dark';
    notifications: boolean;
  };
  tags: string[];
}

function validateUserSchema(data: unknown): UserSchema {
  if (!isJSONObject(data)) {
    throw new Error('Expected user object');
  }
  
  // Validate required fields
  if (typeof data.name !== 'string') {
    throw new Error('Name must be a string');
  }
  
  if (typeof data.age !== 'number') {
    throw new Error('Age must be a number');
  }
  
  if (typeof data.email !== 'string') {
    throw new Error('Email must be a string');
  }
  
  // Validate nested object
  if (!isJSONObject(data.preferences)) {
    throw new Error('Preferences must be an object');
  }
  
  const prefs = data.preferences;
  if (prefs.theme !== 'light' && prefs.theme !== 'dark') {
    throw new Error('Theme must be light or dark');
  }
  
  if (typeof prefs.notifications !== 'boolean') {
    throw new Error('Notifications must be boolean');
  }
  
  // Validate array
  if (!isJSONArray(data.tags)) {
    throw new Error('Tags must be an array');
  }
  
  if (!data.tags.every((tag): tag is string => typeof tag === 'string')) {
    throw new Error('All tags must be strings');
  }
  
  return data as UserSchema;
}

// Safe JSON parsing with validation
function safeParseJSON(text: string): JSONValue {
  try {
    const parsed = JSON.parse(text);
    if (!isJSONValue(parsed)) {
      throw new Error('Parsed value is not valid JSON');
    }
    return parsed;
  } catch (error) {
    throw new Error(`JSON parse error: ${error.message}`);
  }
}

// JSON transformation utilities
function transformJSONObject(
  obj: JSONObject,
  transformer: (key: string, value: JSONValue) => JSONValue
): JSONObject {
  const result: JSONObject = {};
  
  for (const [key, value] of Object.entries(obj)) {
    result[key] = transformer(key, value);
  }
  
  return result;
}

function flattenJSONObject(obj: JSONObject, prefix = ''): Record<string, JSONValue> {
  const result: Record<string, JSONValue> = {};
  
  for (const [key, value] of Object.entries(obj)) {
    const newKey = prefix ? `${prefix}.${key}` : key;
    
    if (isJSONObject(value)) {
      Object.assign(result, flattenJSONObject(value, newKey));
    } else {
      result[newKey] = value;
    }
  }
  
  return result;
}

// Type-safe access patterns
class JSONNavigator {
  constructor(private data: JSONValue) {}
  
  get(path: string): JSONValue | undefined {
    const keys = path.split('.');
    let current = this.data;
    
    for (const key of keys) {
      if (!isJSONObject(current)) {
        return undefined;
      }
      current = current[key];
      if (current === undefined) {
        return undefined;
      }
    }
    
    return current;
  }
  
  getString(path: string): string | undefined {
    const value = this.get(path);
    return typeof value === 'string' ? value : undefined;
  }
  
  getNumber(path: string): number | undefined {
    const value = this.get(path);
    return typeof value === 'number' ? value : undefined;
  }
  
  getBoolean(path: string): boolean | undefined {
    const value = this.get(path);
    return typeof value === 'boolean' ? value : undefined;
  }
  
  getArray(path: string): JSONArray | undefined {
    const value = this.get(path);
    return isJSONArray(value) ? value : undefined;
  }
  
  getObject(path: string): JSONObject | undefined {
    const value = this.get(path);
    return isJSONObject(value) ? value : undefined;
  }
}

// Usage examples
const userData: unknown = {
  name: "Alice",
  age: 30,
  preferences: {
    theme: "dark",
    notifications: true
  },
  tags: ["developer", "typescript"]
};

if (isJSONObject(userData)) {
  const navigator = new JSONNavigator(userData);
  
  console.log('Name:', navigator.getString('name'));
  console.log('Age:', navigator.getNumber('age'));
  console.log('Theme:', navigator.getString('preferences.theme'));
  console.log('Tags:', navigator.getArray('tags'));
}

// Batch validation
function validateBatch(items: unknown[]): JSONValue[] {
  return items.map((item, index) => {
    if (!isJSONValue(item)) {
      throw new Error(`Item at index ${index} is not valid JSON`);
    }
    return item;
  });
}

// JSON diff utility
function compareJSON(a: JSONValue, b: JSONValue): boolean {
  if (a === b) return true;
  
  if (isJSONArray(a) && isJSONArray(b)) {
    if (a.length !== b.length) return false;
    return a.every((item, index) => compareJSON(item, b[index]));
  }
  
  if (isJSONObject(a) && isJSONObject(b)) {
    const keysA = Object.keys(a);
    const keysB = Object.keys(b);
    
    if (keysA.length !== keysB.length) return false;
    
    return keysA.every(key => 
      keysB.includes(key) && compareJSON(a[key], b[key])
    );
  }
  
  return false;
}

// Usage in AI SDK context
function processModelResponse(response: unknown): JSONObject {
  // Validate the response is JSON
  if (!isJSONValue(response)) {
    throw new InvalidResponseDataError({ data: response });
  }
  
  // Ensure it's an object
  if (!isJSONObject(response)) {
    throw new InvalidResponseDataError({ data: response });
  }
  
  return response;
}

function extractToolArgs(toolCall: unknown): JSONObject {
  if (!isJSONObject(toolCall)) {
    throw new Error('Tool call must be an object');
  }
  
  const args = toolCall.args;
  if (!isJSONObject(args)) {
    throw new Error('Tool arguments must be an object');
  }
  
  return args;
}

Install with Tessl CLI

npx tessl i tessl/npm-ai-sdk--provider

docs

embedding-models.md

errors.md

image-models.md

index.md

json-utilities.md

language-models.md

middleware.md

provider.md

speech-models.md

transcription-models.md

tile.json