TypeScript / JavaScript SDK
Relevant source files
The following files were used as context for generating this wiki page:
The TypeScript / JavaScript SDK provides a native npm package for interacting with services modeled in Crucible. It translates the shared Intermediate Representation (IR) into type-safe TypeScript files, including models, schemas, and a service client. The SDK targets modern environments such as browsers and Node.js 22, utilizing standard APIs like fetch, Request, and crypto.subtle.
Sources: AGENTS.md:121-124, crates/crucible-codegen-ts/src/snippet.rs:1-5
SDK Architecture
The SDK generation process converts Crucible service definitions into a structured npm package. The generator produces several core files that manage type safety, data validation, and network communication.
Core Components
| Component | Description |
|---|---|
client.ts | Contains the service client class with methods for each operation. |
models.ts | Defines TypeScript interfaces and types for service shapes. |
schemas.ts | Holds the wire contract and runtime validation logic. |
errors.ts | Exports modeled error classes that extend the base ServiceError. |
runtime.ts | A zero-dependency runtime copied into every package to handle transport and retries. |
Sources: crates/crucible-codegen-ts/tests/golden.rs:163-176, AGENTS.md:121-124
Data Flow
The following diagram illustrates how a user request flows through the SDK to the service.
The SDK uses a phased pipeline where requests are validated against schemas before being dispatched via the fetch API. Responses are checked for modeled errors, which are thrown as specific class instances.
Sources: crates/crucible-codegen-ts/src/snippet.rs:125-155, AGENTS.md:65-70
Type Mapping and Naming
The generator maps Crucible IR shapes to native TypeScript types. It handles collisions with global objects and reserved words by using globalThis or providing diagnostic errors during generation.
Type Conversions
| Crucible Shape | TypeScript Type | Notes |
|---|---|---|
String | string | |
Long / BigInteger | bigint | Appends n suffix in snippets. |
BigDecimal | Decimal | Imported from the SDK runtime. |
Timestamp | globalThis.Date | Always qualified to avoid shadowing. |
Blob | globalThis.Uint8Array | Handles binary data. |
Document | Document | Represents arbitrary JSON. |
Unit | Unit | Equivalent to an empty object {}. |
Sources: crates/crucible-codegen-ts/src/names.rs:13-33, crates/crucible-codegen-ts/src/snippet.rs:37-60
Naming Conventions
The SDK follows specific transformation rules for identifiers:
- Methods: Operation names are camelCased (e.g.,
CreateGraphbecomescreateGraph). Leading acronyms are treated as words (SQLQuerybecomessqlQuery). - Properties: Property keys are written as bare identifiers unless they contain special characters or are reserved words like
__proto__, in which case they are quoted or use computed property syntax. - Optionality: Members are optional in TypeScript interfaces if they are optional in the model or have a default value (which the server or client runtime fills).
Sources: crates/crucible-codegen-ts/src/names.rs:60-93, crates/crucible-codegen-ts/src/names.rs:43-58
Configuration and Construction
SDK packages are configured during the build process using the TsSdk builder. This builder allows developers to set package metadata, endpoints, and middleware.
The builder constructs the options required for the code generator to produce the native npm package.
Sources: crates/crucible-build/src/ts_sdk.rs:11-75
Client Construction
Clients are typically constructed with an optional configuration object. If an endpoint is not provided during generation, the client expects the ENDPOINT environment variable. For authenticated services, a token (string or function returning a promise) is required.
// Sources: [crates/crucible-codegen-ts/src/snippet.rs:113-124]
import { WeatherClient } from "@example/weather";
const client = new WeatherClient({
endpoint: process.env.WEATHER_ENDPOINT,
token: process.env.WEATHER_TOKEN
});
Pagination and Error Handling
Pagination
Paginated operations provide a paginate<Operation> method that returns an async iterator. The iterator stops automatically when the service response no longer contains a "next token".
// Sources: [crates/crucible-codegen-ts/src/snippet.rs:175-190]
for await (const page of client.paginateListCities(input)) {
console.log(page.items);
}
Error Handling
Modeled errors are exported as classes. Callers distinguish between different failure modes using the instanceof operator.
// Sources: [crates/crucible-codegen-ts/src/snippet.rs:145-154]
try {
const output = await client.getCity(input);
} catch (error) {
if (error instanceof NoSuchResourceError) {
console.error(`Error (HTTP ${error.$metadata.status}):`, error.message);
} else {
throw error;
}
}
Package Metadata
The SDK generator produces a package.json that includes essential metadata and publishing configurations.
| Field | Source / Logic |
|---|---|
publishConfig | Configured via npm_registry with support for scoped registries. |
files | Automatically includes dist, crucible.json, crucible-model.json, README.md, and AGENTS.md. |
scripts | Includes TypeDoc configuration for API reference generation. |
Sources: crates/crucible-codegen-ts/tests/golden.rs:364-375, crates/crucible-codegen-ts/src/snippet.rs:252-261
Conclusion
The TypeScript / JavaScript SDK provides a type-safe, dependency-free environment for interacting with Crucible services. By mapping service shapes to native types and providing robust runtime support for pagination, retries, and error handling, it ensures consistent behavior across browser and Node.js environments. Significant attention is given to identifier safety, preventing collisions with JavaScript globals and ensuring deterministic output.
Sources: AGENTS.md:121-125, crates/crucible-codegen-ts/src/names.rs:150-165