A comprehensive TypeScript/JavaScript client library for GridDB Web API with full CRUD operations support.
- 🚀 Full CRUD Operations: Create, Read, Update, Delete with ease
- 🔄 Batch Operations: Efficient batch inserts with error handling
- 🛡️ Type Safety: Full TypeScript support with comprehensive type definitions
- 🔌 Connection Management: Automatic retry logic and connection pooling
- 🎯 SQL & TQL Support: Execute both SQL and TQL queries
- 🔧 Utility Functions: ID generation, data transformation, and more
- 📊 Container Management: Create, drop, and manage GridDB containers
- ⚡ Performance Optimized: Batching, connection reuse, and efficient transformations
npm install @junwatu/griddb-clientor
yarn add @junwatu/griddb-clientCreate a .env file in your project root:
GRIDDB_WEBAPI_URL=http://localhost:8080/griddb/v2
GRIDDB_USERNAME=admin
GRIDDB_PASSWORD=adminimport { GridDB } from '@junwatu/griddb-client';
// Initialize the client
const griddb = new GridDB({
griddbWebApiUrl: process.env.GRIDDB_WEBAPI_URL!,
username: process.env.GRIDDB_USERNAME!,
password: process.env.GRIDDB_PASSWORD!
});
// Create a container
await griddb.createContainer({
containerName: 'users',
columns: [
{ name: 'id', type: 'INTEGER' },
{ name: 'name', type: 'STRING' },
{ name: 'email', type: 'STRING' },
{ name: 'created_at', type: 'TIMESTAMP' }
]
});
// Insert data
await griddb.insert({
containerName: 'users',
data: {
id: 1,
name: 'John Doe',
email: 'john@example.com',
created_at: new Date()
}
});
// Query data
const users = await griddb.select({
containerName: 'users',
where: 'name = ?',
bindings: ['John Doe']
});
console.log(users);| Method | Description |
|---|---|
createContainer(options) |
Create a new container |
dropContainer(name) |
Drop a container |
listContainers() |
List all containers |
containerExists(name) |
Check if container exists |
getSchema(name) |
Get container schema |
insert(options) |
Insert one or more rows |
batchInsert(name, data, batchSize) |
Batch insert with error handling |
select(options) |
Query rows with conditions |
selectOne(options) |
Query a single row |
count(name, where?, bindings?) |
Count rows |
exists(name, where, bindings?) |
Check if rows exist |
update(options) |
Update rows (by rowkey or WHERE clause) |
delete(options) |
Delete rows by condition |
truncate(name) |
Delete all rows from container |
upsert(name, data, uniqueColumns) |
Insert or update |
executeSql(stmt, bindings?) |
Execute raw SELECT query |
executeDml(stmt, bindings?) |
Execute raw DML (INSERT/UPDATE/DELETE) |
executeTql(name, query) |
Execute TQL query |
import { GridDB, GridDBConfig } from '@junwatu/griddb-client';
const config: GridDBConfig = {
griddbWebApiUrl: 'http://localhost:8080/griddb/v2',
username: 'admin',
password: 'admin',
timeout: 30000, // Optional: Request timeout in ms (default: 30000)
retryAttempts: 3, // Optional: Number of retry attempts (default: 3)
retryDelay: 1000 // Optional: Delay between retries in ms (default: 1000)
};
const griddb = new GridDB(config);await griddb.createContainer({
containerName: 'my_container',
columns: [
{ name: 'id', type: 'INTEGER' },
{ name: 'data', type: 'BLOB' },
{ name: 'timestamp', type: 'TIMESTAMP' }
],
containerType: 'COLLECTION', // or 'TIME_SERIES'
rowkey: true, // First column as primary key
ifNotExists: true // Don't error if exists
});await griddb.dropContainer('my_container');const containers = await griddb.listContainers();
console.log(containers); // ['users', 'products', ...]// Object-based insert (property order doesn't matter)
await griddb.insert({
containerName: 'users',
data: { name: 'Alice', email: 'alice@example.com', id: 1 }
});
// Multiple insert with objects
await griddb.insert({
containerName: 'users',
data: [
{ name: 'Bob', email: 'bob@example.com', id: 2 },
{ name: 'Charlie', email: 'charlie@example.com', id: 3 }
]
});
// Mixed object and array data
await griddb.insert({
containerName: 'users',
data: [
{ name: 'Dave', email: 'dave@example.com', id: 4 },
[5, 'Eve', 'eve@example.com'] // Arrays must follow column order
]
});
// Batch insert with error handling
const result = await griddb.batchInsert('users', largeDataArray, 100);
console.log(`Succeeded: ${result.succeeded}, Failed: ${result.failed}`);// Select all
const allUsers = await griddb.select({ containerName: 'users' });
// Select with conditions
const activeUsers = await griddb.select({
containerName: 'users',
columns: ['id', 'name', 'email'],
where: 'status = ? AND created_at > ?',
bindings: ['active', '2024-01-01'],
orderBy: 'created_at',
order: 'DESC',
limit: 10,
offset: 0
});
// Select one
const user = await griddb.selectOne({
containerName: 'users',
where: 'id = ?',
bindings: [1]
});// Update by primary key (upsert via rowkey — recommended)
await griddb.update({
containerName: 'users',
data: { id: 1, name: 'Alice Updated', email: 'alice.new@example.com' }
});
// Update with WHERE clause
await griddb.update({
containerName: 'users',
data: { status: 'inactive' },
where: `last_login < '2023-01-01'`
});Note: When no
whereclause is provided, update uses the Row API (PUT) which upserts by rowkey. When awhereclause is provided, it uses SQL UPDATE via the DML endpoint. For GridDB Cloud, prefer inline values in the WHERE clause over parameterizedbindings.
// Delete by ID
await griddb.delete({
containerName: 'users',
where: 'id = 1'
});
// Delete with condition
await griddb.delete({
containerName: 'users',
where: `status = 'inactive'`
});await griddb.upsert(
'users',
{ id: 1, name: 'Alice', email: 'alice@example.com' },
['id'] // Unique columns to check
);// Delete all rows from a container
await griddb.truncate('users');Use executeSql for read-only SELECT queries. This sends type: 'sql-select' to the /sql/dml/query endpoint.
const result = await griddb.executeSql(
'SELECT * FROM users WHERE age > ? ORDER BY name',
[18]
);
console.log(result.results);Use executeDml for data modification statements. This sends type: 'sql-update' to the /sql/update endpoint, which is required by GridDB Cloud Web API for DML operations.
// Delete with raw SQL
const result = await griddb.executeDml(
'DELETE FROM users WHERE status = ?',
['inactive']
);
console.log(result.updatedRows);
// Update with raw SQL
await griddb.executeDml(
'UPDATE users SET status = ? WHERE last_login < ?',
['inactive', '2023-01-01']
);Note: The high-level
delete(),update(), andtruncate()methods useexecuteDmlinternally. You only needexecuteDmldirectly for complex DML statements not covered by the convenience methods.
const result = await griddb.executeTql(
'users',
'select * where age > 18'
);import { IdGeneratorFactory } from '@junwatu/griddb-client';
// Random integer ID (1-10000)
const randomId = IdGeneratorFactory.random();
// UUID v4
const uuid = IdGeneratorFactory.uuid();
// Timestamp-based ID
const timestampId = IdGeneratorFactory.timestamp();
// Snowflake-like ID
const snowflakeId = IdGeneratorFactory.snowflake();
// Short alphanumeric ID
const shortId = IdGeneratorFactory.short(8);import { blobToBase64, base64ToBlob } from '@junwatu/griddb-client';
// Convert Blob to base64 for storage
const base64 = await blobToBase64(imageBlob);
// Convert base64 back to Blob
const blob = base64ToBlob(base64String, 'image/jpeg');const griddb = new GridDB({
config: {
griddbWebApiUrl: '...',
username: '...',
password: '...'
},
logger: {
debug: (msg, ...args) => console.debug(msg, ...args),
info: (msg, ...args) => console.info(msg, ...args),
warn: (msg, ...args) => console.warn(msg, ...args),
error: (msg, ...args) => console.error(msg, ...args)
}
});// Store image as BLOB
const imageBuffer = await fs.readFile('image.jpg');
const base64Image = imageBuffer.toString('base64');
await griddb.insert({
containerName: 'images',
data: {
id: 1,
image_data: base64Image,
mime_type: 'image/jpeg'
}
});
// Retrieve and convert back
const result = await griddb.selectOne({
containerName: 'images',
where: 'id = ?',
bindings: [1]
});
if (result) {
const imageBlob = base64ToBlob(result.image_data, result.mime_type);
// Use imageBlob...
}import { GridDBError } from '@junwatu/griddb-client';
try {
await griddb.insert({
containerName: 'users',
data: { id: 1, name: 'Test' }
});
} catch (error) {
if (error instanceof GridDBError) {
console.error('GridDB Error:', error.message);
console.error('Status:', error.status);
console.error('Details:', error.details);
} else {
console.error('Unexpected error:', error);
}
}The library exports all type definitions for use in your TypeScript projects:
import {
GridDBConfig,
GridDBColumn,
GridDBRow,
GridDBQuery,
ContainerType,
GridDBColumnType,
CreateOptions,
InsertOptions,
SelectOptions,
UpdateOptions,
DeleteOptions,
QueryResult,
BatchOperationResult
} from '@junwatu/griddb-client';interface GridDBQuery {
type: 'sql-select' | 'sql-update' | 'tql';
stmt: string;
bindings?: GridDBValue[];
}sql-select— Used for SELECT queries via/sql/dml/querysql-update— Used for DML statements (INSERT, UPDATE, DELETE) via/sql/updatetql— Used for TQL queries
This library fully supports GridDB Cloud. GridDB Cloud's Web API strictly separates SELECT queries from DML (data modification) operations at the endpoint level:
| Operation | API Type | Endpoint |
|---|---|---|
| SELECT, COUNT | sql-select |
/sql/dml/query |
| INSERT, UPDATE, DELETE | sql-update |
/sql/update |
The library handles this automatically — select(), selectOne(), count() use the SELECT endpoint, while delete(), update() (with WHERE clause), and truncate() use the DML endpoint.
Tip: Make sure your IP address is added to the GridDB Cloud allowlist, otherwise all requests will return
403 Forbidden.
const griddb = new GridDB({
griddbWebApiUrl: 'https://cloud1.griddb.com/trial1234/griddb/v2/gs_clustertrial1234/dbs/public',
username: 'your_username',
password: 'your_password'
});Create a .env file with the following variables:
# GridDB Web API Configuration
GRIDDB_WEBAPI_URL=http://localhost:8080/griddb/v2
GRIDDB_USERNAME=admin
GRIDDB_PASSWORD=admin
# Optional
GRIDDB_TIMEOUT=30000
GRIDDB_RETRY_ATTEMPTS=3
GRIDDB_RETRY_DELAY=1000npm run buildnpm testnpm run lintnpm run formatMIT
Contributions are welcome! Please feel free to submit a Pull Request.
For issues and questions, please use the GitHub Issues page.