Skip to main content

TypeScript SDK

The TypeScript SDK (@shaped.ai/client) is *generated from the Shaped API schema. It includes types and inline documentation so your editor’s IntelliSense/auto‑completion can surface all methods, options, and return types as you build.

Install

Install from npm:

Install
npm install @shaped.ai/client

or with Yarn:

yarn add @shaped.ai/client

Instantiate the client

Import and construct the Client with your API key:

import { Client } from '@shaped.ai/client';

const client = new Client('YOUR_API_KEY');

You can also read the key from environment variables (Node.js):

import { Client } from '@shaped.ai/client';

const apiKey = process.env.SHAPED_API_KEY!;
const client = new Client(apiKey);

Load data from raw records

This pattern mirrors the Python examples and is useful when you want to push data directly from your application.

1. Create a custom table

Use the TableRequest type to define a CUSTOM schema and create it via client.createTable:

import type { TableRequest } from '@shaped.ai/client';

const tableConfig: TableRequest = {
schema_type: 'CUSTOM',
name: 'pixar_movies',
column_schema: {
item_id: 'Int64',
movie_title: 'String',
poster_url: 'String',
description: 'String',
release_date: 'String',
cast: 'Array(String)',
},
};

await client.createTable(tableConfig);

2. Insert raw records

Insert arrays of JavaScript objects using insertTableRows:

const records: Array<Record<string, any>> = [
{
item_id: 187541,
movie_title: 'Incredibles 2 (2018)',
poster_url:
'https://m.media-amazon.com/images/M/MV5BMTEzNzY0OTg0NTdeQTJeQWpwZ15BbWU4MDU3OTg3MjUz._V1_QL75_UX380_CR0,0,380,562_.jpg',
description:
"The Incredibles family takes on a new mission which involves a change in family roles.",
release_date: '2018-06-15',
cast: ['Craig T. Nelson', 'Holly Hunter'],
},
{
item_id: 177765,
movie_title: 'Coco (2017)',
poster_url:
'https://m.media-amazon.com/images/M/MV5BMDIyM2E2NTAtMzlhNy00ZGUxLWI1NjgtZDY5MzhiMDc5NGU3XkEyXkFqcGc@._V1_QL75_UY562_CR7,0,380,562_.jpg',
description:
'Aspiring musician Miguel enters the Land of the Dead to find his great‑great‑grandfather.',
release_date: '2017-11-22',
cast: ['Anthony Gonzalez', 'Gael García Bernal'],
},
];

await client.insertTableRows('pixar_movies', records);

Load data from connectors (MongoDB example)

As with Python, connector tables are defined via the Tables API or CLI, and appear as normal tables when queried via the SDK.

1. Define a MongoDB connector table

Use the createTable method to sync an external data source to a Shaped table. This example uses a MongoDB table.

import type { TableRequest } from '@shaped.ai/client';

const tableConfig: TableRequest = {
"name": "mongodb_dataset",
"schema_type": "MONGODB",
"collection": "movies",
"database": "movielens",
"mongodb_connection_string": "mongodb://user:password@host:port/database",
"start_date": "2024-01-01",
}

await client.createTable(tableConfig);

The table mongodb_dataset will be synced on the schedule you configure and is now available to engines and queries.

See the Connector Reference for a full list of external data sources you can sync with.

2. Use the connector table from TypeScript

You reference the connector table just like any other table when configuring engines in TypeScript:

import { Engine } from '@shaped.ai/client';

const mongoEngine = new Engine('mongodb_semantic_search');

mongoEngine.items('mongodb_dataset');

mongoEngine.withEmbedding({
name: 'mongo_text_embedding',
encoder: {
type: 'hugging_face',
model_name: 'sentence-transformers/all-MiniLM-L6-v2',
item_fields: ['document'], // JSON document column
},
});

await client.createEngine(mongoEngine);

For more on MongoDB options and behavior, see the MongoDB connector docs.


Create engines with vector embeddings

On TypeScript, you configure engines using the Engine helper class. It wraps the engine configuration in a convenient, chainable interface.

1. Define the engine

import { Engine } from '@shaped.ai/client';

const semanticSearchEngine = new Engine('semantic_search');

2. Connect to an item table

Use .items to connect the engine to your table:

semanticSearchEngine.items('pixar_movies');

3. Configure an embedding index

Configure a HuggingFace encoder for semantic / vector search:

const embeddingModel = 'sentence-transformers/all-MiniLM-L6-v2';

semanticSearchEngine.withEmbedding({
name: 'movie_text_embedding',
encoder: {
type: 'hugging_face',
model_name: embeddingModel,
item_fields: ['movie_title', 'description'],
},
});

4. Create the engine (start encoding)

await client.createEngine(semanticSearchEngine);

Once status is ACTIVE, the engine is ready for queries.


Query data with the fluent builder

The TypeScript SDK exposes a builder pattern via RankQueryBuilder that compiles to ShapedQL under the hood.

import { RankQueryBuilder } from '@shaped.ai/client';

const query = new RankQueryBuilder()
.from('item')
.retrieve(step =>
step.textSearch(
'$query',
{ type: 'lexical' },
{ limit: 50 },
),
)
.limit(20)
.build();

const results = await client.executeQuery(
'text_search',
query,
{ query: 'Incredibles' },
true,
);
import { RankQueryBuilder } from '@shaped.ai/client';

const query = new RankQueryBuilder()
.from('item')
.retrieve(step =>
step.textSearch(
'$query',
{ type: 'vector', textEmbeddingRef: 'movie_text_embedding' },
{ limit: 50 },
),
)
.limit(20)
.build();

const results = await client.executeQuery(
'semantic_search',
query,
{ query: 'animated superhero family' },
true,
);

3. Hybrid search with multiple retrievers

import { RankQueryBuilder } from '@shaped.ai/client';

const query = new RankQueryBuilder()
.from('item')
.retrieve(step =>
step.textSearch(
'$query',
{ type: 'lexical' },
{ limit: 50, name: 'lexical_search' },
),
)
.retrieve(step =>
step.textSearch(
'$query',
{ type: 'vector', textEmbeddingRef: 'movie_text_embedding' },
{ limit: 50, name: 'vector_search' },
),
)
.limit(20)
.build();

const results = await client.executeQuery(
'hybrid_search',
query,
{ query: 'Pixar movies about family' },
true,
);

4. Personalized search with a value model

import { RankQueryBuilder } from '@shaped.ai/client';

const query = new RankQueryBuilder()
.from('item')
.retrieve(step =>
step.textSearch(
'$query',
{ type: 'lexical' },
{ limit: 50, name: 'lexical_search' },
),
)
.retrieve(step =>
step.textSearch(
'$query',
{ type: 'vector', textEmbeddingRef: 'movie_text_embedding' },
{ limit: 50, name: 'vector_search' },
),
)
.score({
valueModel: 'click_through_rate',
inputUserId: '$user_id',
inputInteractionsItemIds: '$interaction_item_ids',
})
.limit(20)
.build();

const results = await client.executeQuery(
'personalized_search',
query,
{
query: 'Pixar',
user_id: 'user1',
interaction_item_ids: ['187541', '177765', '1'],
},
true,
);

Next steps