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​