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

@textql/sdk

v1.0.2

Published

TextQL Platform SDK - TypeScript/JavaScript client for TextQL APIs

Readme

TextQL Platform SDK

TypeScript/JavaScript client library for TextQL with a clean, intuitive API.

Installation

npm install @textql/sdk

Getting Your API Key

You can get your API key if you are an admin in:

https://app.textql.com/settings → Configuration → API Keys

Quick Start

import { createTextQLClient } from '@textql/sdk';

// Initialize client
const client = createTextQLClient({
  apiKey: 'your-api-key'
});

Tooling Configuration


// Configure which capabilities are enabled for your chat:
// NOTE: Once a chat is created, it will assume the paradigms that it is created with.
// Sending chats different paradigm configurations will lead to issues.

const tools = {
  connectorIds: [513, 514],       // Database connectors to use
  webSearchEnabled: true,         // Enable web search
  sqlEnabled: true,               // Enable SQL queries
  pythonEnabled: true,            // Enable Python execution
  ontologyEnabled: false,         // Enable ontology queries
  tableauEnabled: false,          // Enable Tableau integration
  powerbiEnabled: false,          // Enable PowerBI integration
  googleDriveEnabled: false,      // Enable Google Drive access
};

Chat Endpoints

Streaming Endpoint

// Stream a chat conversation
const stream = client.chat.stream({
  question: "Draw me a picture of the sky, query the connected db. Make the image of the sky reflect the data stored",
  tools : config
});

for await (const message of stream) {
  const { case: messageCase, value } = message.message;

  switch (messageCase) {
    case 'text':
      process.stdout.write(value);
      break;
    case 'metadata':
      console.log(`\nChat ID: ${value.chatId}`);
      break;
    case 'preview':
      console.log(`\nPreview URL: ${value.url}`);
      break;
    default:
      console.log(`\nUnknown message type: ${messageCase}`);
      break;
  }
}

Example Output:

Chat ID: 51903b7f-554d-44c4-a465-02b8269de13e
I'll query the connected database to see what data is available, then create a sky visualization that reflects the data patterns.
[Generating SQL]
[SQL Execution Succeeded]

...

[Generating SQL]
[SQL Execution Succeeded]
Perfect! Now I'll create a sky visualization that reflects this Netflix viewing data. I'll use the data patterns to influence the sky's appearance.
[Generating Python]
[Python Execution Succeeded]

Preview URL: https://staging.textql.com/asset/proxy/.../netflix_sky.png
I've created a beautiful sky visualization that reflects the Netflix streaming data from your database! Here's how the data influenced the artwork:

**Data-Driven Sky Elements:**

- **Stars** - Each of the 50 brightest stars represents a Netflix show, with brightness and size proportional to view counts. The most-watched shows shine brightest!

- **Golden Constellation** - The 5 golden stars connected by lines represent the top 5 most-viewed shows:
  1. Fool Me Once (107.5M views)
  2. Bridgerton Season 3 (91.9M views)
  3. Baby Reindeer (87.6M views)
  4. The Gentlemen (75.9M views)
  5. Avatar: The Last Airbender (71.1M views)

- **The Moon** - Represents the massive total of 13.9 billion hours viewed across all shows

- **Shooting Stars** - Three shooting stars represent the most recently released shows in the dataset

- **Purple Nebulae** - Subtle clouds scattered throughout represent the distribution of viewing hours

The sky captures 100 shows with 2.3 billion total views and 13.9 billion hours of content consumed. It's a twilight scene where data becomes celestial beauty!
Chat ID: 51903b7f-554d-44c4-a465-02b8269de13e

Chat Endpoint - Non-Streaming

// Non-streaming (get complete response at once)
const chat = await client.chat.chat({
  question: "Tell me something interesting",
  chatId: "existing-chat-id",  // Optional: continue existing chat
});

console.log(chat)

Expected Response:

_ChatResponse {
  id: 'c11a84ba-0fa5-45d4-8e03-8a3c1ff809a9',
  model: 'MODEL_SONNET_4_5',
  response: "Here's something fascinating from your Citibike NYC data:\n" +
    '\n' +
    '## The Tale of Two Riders\n' +
    '\n' +
    "Between January 2021 and October 2025, Citibike recorded **174.4 million trips** in NYC. But there's a striking behavioral difference between casual riders and members:\n" +
    '\n' +
    '**Casual riders take trips that are 2.3x LONGER than members** - averaging 29.5 minutes vs. just 12.8 minutes for members. However, **members take 3.9x MORE trips** overall!\n' +
    '\n' +
    'This suggests completely different use patterns:\n' +
    '- **Members** use Citibike for efficient, point-to-point transportation (likely commuting)\n' +
    '- **Casual riders** use it for leisurely exploration and sightseeing\n' +
    '\n' +
    "There's also an interesting bike preference: casual riders on classic bikes take the longest trips of all - averaging nearly 37 minutes! This might indicate tourists taking their time to explore the city at a relaxed pace.\n" +
    '\n' +
    'Would you like me to dig deeper into any particular aspect of this data, like seasonal patterns or popular routes?',
  chatId: 'ec08af41-419a-4de6-938f-637d1632fad8',
  assets: [
    _PreviewCell {
      target: 'citibike_insights.png',
      previewType: 'image',
      name: 'citibike_insights.png',
      url: 'https://staging.textql.com/asset/proxy/.../citibike_insights.png'
    }
  ],
  createdAt: Timestamp { seconds: 1763509903n, nanos: 476257862 }
}

Note: chatId is the correct field to use when referencing a chat (e.g. continuation/get/cancel). DO NOT use id to reference a chat.

Get Chat

const history = await client.chat.getChat({
  chatId: "77fdc628-5bc7-4a60-b0cf-fed6b89f2878"
});

console.log(history);

Expected Response:

{
  chat: {
    id: "77fdc628-5bc7-4a60-b0cf-fed6b89f2878",
    paradigm: {
      type: "TYPE_UNIVERSAL",
      options: {
        universal: {
          connectorIds: [44],
          webSearchEnabled: true,
          ontologyEnabled: true,
          pythonEnabled: true
        }
      }
    },
    model: "MODEL_SONNET_4_5",
    summary: "Create Simple Smiley Face"
  },
  messages: [
    {
      role: "user",
      content: "draw me a picture",
      createdAt: { seconds: 1763500426, nanos: 875203000 }
    },
    {
      role: "assistant",
      content: "I'll create a simple smiley face for you!",
      createdAt: { seconds: 1763500644, nanos: 286802000 }
    }
  ],
  assets: [
    {
      target: "smiley_face.png",
      previewType: "image",
      name: "smiley_face.png",
      url: "https://staging.textql.com/asset/proxy/.../smiley_face.png"
    }
  ]
}

Connectors API

List Connectors

List and manage data connectors:

const connectors = await client.connectors.listConnectors({});

console.log(connectors);

Expected Response:

{
  connectors: [
    {
      id: 2,
      name: "Ticket Selling Business",
      connectorType: "REDSHIFT",
      memberId: "member-test-7a8e991e-74b2-458d-a3d2-db97fa12f941",
      createdAt: {
        seconds: 1727297306,
        nanos: 121768000
      },
      lastSynced: {
        seconds: 1755643111,
        nanos: 990895000
      },
      redshiftMetadata: {
        host: "<host>",
        port: "<port>",
        user: "<user>",
        database: "<database>",
        schemas: "<schema>",
        dialect: "Redshift",
        sslMode: true
      }
    }
  ]
}

Playbooks API

Create Playbook

const playbook = await client.playbooks.createPlaybook({
  name: 'Weekly Sales Report',
  prompt: 'Analyze transactions in my Snowflake data warehouse and compare them with our Salesforce revenue reports. Reconcile any discrepancies between the data sources and highlight anomalies or unusual finance trends from the past week.',
  paradigmOptions: {
    universal: {
      connectorIds: [1, 2, 3],
      webSearchEnabled: true,
      pythonEnabled: true,
      sqlEnabled: true
    }
  },
  cronString: "0 9 * * 1",
  status: "STATUS_ACTIVE",
  reportOutputStyle: "EXECUTIVE_REPORT"
});

console.log(playbook);

Expected Response:

{
  playbook: {
    id: "7f232107-bf1d-4d3b-ab29-24d6173c86c6",
    orgId: "organization-test-1526533d-fc7e-4b44-9ec9-5f40ba8ee0d2",
    memberId: "0106c059-33de-4145-a010-d012604aba66",
    connectorId: 1,
    name: "Weekly Sales Report",
    createdAt: {
      seconds: 1763504471,
      nanos: 727166000
    },
    updatedAt: {
      seconds: 1763504471,
      nanos: 727166000
    },
    status: "STATUS_ACTIVE",
    triggerType: "TRIGGER_TYPE_CRON",
    cronString: "0 13 * * *",
    paradigmOptions: {
      universal: {
        connectorIds: [1],
        webSearchEnabled: true,
        pythonEnabled: true
      }
    },
    paradigmType: "TYPE_UNIVERSAL",
    owner: {
      memberId: "0106c059-33de-4145-a010-d012604aba66",
      memberEmail: "[email protected]",
      memberName: ""
    },
    hasWritePermission: true,
    reportOutputStyle: "EXECUTIVE_REPORT",
    maxConcurrentTemplates: 2,
    autoOptimizeConcurrency: true,
    connectorIds: [1]
  },
  createdAt: {
    seconds: 1763504471,
    nanos: 727166000
  }
}

Note: The id field above is how you reference this playbook (get, update, delete).

List Playbooks

List all playbooks:

const playbooks = await client.playbooks.listPlaybooks({});

for (const playbook of playbooks.playbooks) {
  console.log(`${playbook.id}: ${playbook.name}`);
}

Get Playbook

const playbook = await client.playbooks.getPlaybook({
  playbookId: "19f46117-bebc-48d3-aeeb-11c792c72155"
});

console.log(playbook);

Expected Response:

{
  playbook: {
    id: "19f46117-bebc-48d3-aeeb-11c792c72155",
    orgId: "organization-test-1526533d-fc7e-4b44-9ec9-5f40ba8ee0d2",
    memberId: "member-test-d670dbd3-3861-4d0c-b60b-d45014e9397c",
    name: "My Analysis Report",
    prompt: "plot sinx and then cosx have tanx as the hero image",
    createdAt: {
      seconds: 1748468778,
      nanos: 260770000
    },
    updatedAt: {
      seconds: 1761844687,
      nanos: 36299000
    },
    status: "STATUS_ACTIVE",
    triggerType: "TRIGGER_TYPE_CRON",
    cronString: "55 23 * * *",
    latestChatId: "4d454a91-25f5-4ff1-890c-3a5b822b86fd",
    emailAddresses: "[email protected]",
    slackChannelId: "C08646B7LAG",
    paradigmOptions: {
      sql: {
        connectorIds: [32]
      }
    },
    paradigmType: "TYPE_SQL",
    owner: {
      memberId: "member-test-d670dbd3-3861-4d0c-b60b-d45014e9397c",
      memberEmail: "[email protected]",
      memberName: "User Name"
    },
    hasWritePermission: true,
    reportOutputStyle: "EXECUTIVE_REPORT",
    maxConcurrentTemplates: 2,
    autoOptimizeConcurrency: true,
    connectorIds: [32]
  }
}

Update Playbook

const playbook = await client.playbooks.updatePlaybook({
  playbookId: "7f232107-bf1d-4d3b-ab29-24d6173c86c6",
  name: "Updated Sales Report",
  prompt: "Updated analysis prompt",
  status: "STATUS_ACTIVE",
  cronString: "0 7 * * *",
  emailAddresses: ["[email protected]"], // Must be in organization
  maxConcurrentTemplates: 5,
  autoOptimizeConcurrency: true,
  paradigmOptions: {
    universal: {
      connectorIds: [2],
      webSearchEnabled: true,
      pythonEnabled: true,
      sqlEnabled: true // SQL must be enabled when using connectors
    }
  }
});

console.log(playbook);

Expected Response:

{
  playbook: {
    id: "7f232107-bf1d-4d3b-ab29-24d6173c86c6",
    orgId: "organization-test-1526533d-fc7e-4b44-9ec9-5f40ba8ee0d2",
    memberId: "0106c059-33de-4145-a010-d012604aba66",
    connectorId: 2,
    name: "Updated Sales Report",
    prompt: "Updated analysis prompt",
    createdAt: {
      seconds: 1763504471,
      nanos: 727166000
    },
    updatedAt: {
      seconds: 1763504976,
      nanos: 967037000
    },
    status: "STATUS_ACTIVE",
    triggerType: "TRIGGER_TYPE_CRON",
    cronString: "0 7 * * *",
    paradigmOptions: {
      universal: {
        connectorIds: [2],
        webSearchEnabled: true,
        sqlEnabled: true,
        pythonEnabled: true
      }
    },
    paradigmType: "TYPE_UNIVERSAL",
    owner: {
      memberId: "0106c059-33de-4145-a010-d012604aba66",
      memberEmail: "[email protected]",
      memberName: ""
    },
    hasWritePermission: true,
    reportOutputStyle: "EXECUTIVE_REPORT",
    maxConcurrentTemplates: 5,
    autoOptimizeConcurrency: true,
    connectorIds: [2]
  },
  updatedAt: {
    seconds: 1763504976,
    nanos: 967037000
  }
}

Delete Playbook

const result = await client.playbooks.deletePlaybook({
  playbookId: "7f232107-bf1d-4d3b-ab29-24d6173c86c6"
});

console.log(result);

Expected Response:

{
  playbookId: "7f232107-bf1d-4d3b-ab29-24d6173c86c6",
  deletedAt: {
    seconds: 1763505132,
    nanos: 206457486
  }
}

API Reference

The SDK provides full TypeScript types for all API requests and responses. Use your IDE's autocomplete to explore available methods and types.

Available Services

  • ChatService: Send questions, stream responses, manage chats
  • ConnectorService: Manage database and BI tool connections
  • PlaybookService: Create and manage automated playbooks

Requirements

  • Node.js >= 14
  • TypeScript >= 4.5 (recommended)

License

MIT