From 57e6d12fbbffb9579f1457f79d7ada794006d4d4 Mon Sep 17 00:00:00 2001 From: sam-butcher Date: Wed, 9 Jul 2025 15:45:59 +0100 Subject: [PATCH 01/13] http driver --- http-ts/concept.ts | 67 ++++++++++++ http-ts/database.ts | 9 ++ http-ts/index.ts | 204 +++++++++++++++++++++++++++++++++++++ http-ts/package.json | 19 ++++ http-ts/params.ts | 37 +++++++ http-ts/pnpm-lock.yaml | 24 +++++ http-ts/query-structure.ts | 190 ++++++++++++++++++++++++++++++++++ http-ts/query.ts | 10 ++ http-ts/response.ts | 96 +++++++++++++++++ http-ts/transaction.ts | 12 +++ http-ts/user.ts | 9 ++ 11 files changed, 677 insertions(+) create mode 100644 http-ts/concept.ts create mode 100644 http-ts/database.ts create mode 100644 http-ts/index.ts create mode 100644 http-ts/package.json create mode 100644 http-ts/params.ts create mode 100644 http-ts/pnpm-lock.yaml create mode 100644 http-ts/query-structure.ts create mode 100644 http-ts/query.ts create mode 100644 http-ts/response.ts create mode 100644 http-ts/transaction.ts create mode 100644 http-ts/user.ts diff --git a/http-ts/concept.ts b/http-ts/concept.ts new file mode 100644 index 000000000..a29c79407 --- /dev/null +++ b/http-ts/concept.ts @@ -0,0 +1,67 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +export type TypeKind = "entityType" | "relationType" | "attributeType" | "roleType"; + +export type ThingKind = "entity" | "relation" | "attribute"; + +export type ValueKind = "value"; + +export type ValueType = "boolean" | "integer" | "double" | "decimal" | "date" | "datetime" | "datetime-tz" | "duration" | "string" | "struct"; + +export type EdgeKind = "isa" | "has" | "links" | "sub" | "owns" | "relates" | "plays" | "isaExact" | "subExact" | "assigned" | "argument"; + +export interface EntityType { + kind: "entityType"; + label: string; +} + +export interface RelationType { + kind: "relationType"; + label: string; +} + +export interface RoleType { + kind: "roleType"; + label: string; +} + +export type AttributeType = { + label: string; + kind: "attributeType"; + valueType: ValueType; +} + +export type Type = InstantiableType | RoleType; +export type InstantiableType = EntityType | RelationType | AttributeType; + +export interface Entity { + kind: "entity"; + iid: string; + type: EntityType; +} + +export interface Relation { + kind: "relation"; + iid: string; + type: RelationType; +} + +export interface Attribute { + kind: "attribute"; + iid: string; + value: any; + valueType: ValueType; + type: AttributeType; +} + +export interface Value { + kind: ValueKind; + value: any; + valueType: ValueType; +} + +export type Concept = Type | Entity | Relation | Attribute | Value; diff --git a/http-ts/database.ts b/http-ts/database.ts new file mode 100644 index 000000000..b15ae19ac --- /dev/null +++ b/http-ts/database.ts @@ -0,0 +1,9 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +export interface Database { + name: string; +} diff --git a/http-ts/index.ts b/http-ts/index.ts new file mode 100644 index 000000000..b49f769ea --- /dev/null +++ b/http-ts/index.ts @@ -0,0 +1,204 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import { TransactionOptions, TransactionType } from "./transaction"; +import { DriverParams, remoteOrigin } from "./params"; +import { + ApiErrorResponse, + ApiResponse, + DatabasesListResponse, + isApiError, + QueryResponse, + SignInResponse, + TransactionOpenResponse, + UsersListResponse, + VersionResponse +} from "./response"; +import { User } from "./user"; +import { Database } from "./database"; +import { QueryOptions } from "./query"; + +const HTTP_UNAUTHORIZED = 401; + +export { isOkResponse, isApiErrorResponse } from "./response"; + +export class TypeDBHttpDriver { + + private token?: string; + + constructor(private params: DriverParams) {} + + listDatabases(): Promise> { + return this.apiGet(`/v1/databases`); + } + + getDatabase(name: String): Promise> { + return this.apiGet(`/v1/databases/${name}`); + } + + createDatabase(name: string): Promise { + return this.apiPost(`/v1/databases/${name}`, {}); + } + + deleteDatabase(name: string): Promise { + return this.apiDelete(`/v1/databases/${name}`); + } + + getDatabaseSchema(name: string): Promise> { + return this.apiGetString(`/v1/databases/${name}/schema`); + } + + getDatabaseTypeSchema(name: string): Promise> { + return this.apiGetString(`/v1/databases/${name}/type-schema`); + } + + listUsers(): Promise> { + return this.apiGet(`/v1/users`); + } + + getUser(username: string): Promise> { + return this.apiGet(`/v1/users/${username}`); + } + + createUser(username: string, password: string): Promise { + return this.apiPost(`/v1/users/${username}`, { password }); + } + + updateUser(username: string, password: string): Promise { + return this.apiPut(`/v1/users/${username}`, { password }); + } + + deleteUser(username: string): Promise { + return this.apiDelete(`/v1/users/${username}`); + } + + openTransaction(databaseName: string, transactionType: TransactionType, transactionOptions?: TransactionOptions): Promise> { + return this.apiPost(`/v1/transactions/open`, { databaseName, transactionType, transactionOptions }); + } + + commitTransaction(transactionId: string): Promise { + return this.apiPost(`/v1/transactions/${transactionId}/commit`, {}); + } + + closeTransaction(transactionId: string): Promise { + return this.apiPost(`/v1/transactions/${transactionId}/close`, {}); + } + + rollbackTransaction(transactionId: string): Promise { + return this.apiPost(`/v1/transactions/${transactionId}/rollback`, {}); + } + + query(transactionId: string, query: string, queryOptions?: QueryOptions): Promise> { + return this.apiPost(`/v1/transactions/${transactionId}/query`, { query, queryOptions }); + } + + oneShotQuery(query: string, commit: boolean, databaseName: string, transactionType: TransactionType, transactionOptions?: TransactionOptions, queryOptions?: QueryOptions) { + return this.apiPost(`/v1/query`, { query, commit, databaseName, transactionType, transactionOptions, queryOptions }); + } + + health(): Promise { + return this.apiGet(`/v1/health`); + } + + version(): Promise> { + return this.apiGet(`/v1/version`); + } + + private async apiGetString(path: string, options?: { headers?: Record }): Promise> { + return this.stringApiReq("GET", path, options); + } + + private async apiGet(path: string, options?: { headers?: Record }): Promise> { + return this.jsonApiReqWithoutBody("GET", path, options); + } + + private async apiDelete(path: string, options?: { headers?: Record }): Promise> { + return this.jsonApiReqWithoutBody("DELETE", path, options); + } + + private async apiPost(path: string, body: BODY, options?: { headers?: Record }): Promise> { + return this.jsonApiReq("POST", path, body, options); + } + + private async apiPut(path: string, body: BODY, options?: { headers?: Record }): Promise> { + return this.jsonApiReq("PUT", path, body, options); + } + + private async jsonApiReqWithoutBody(method: string, path: string, options?: { headers?: Record }): Promise> { + return this.jsonApiReq(method, path, undefined, options); + } + + private async jsonApiReq(method: string, path: string, body?: BODY, options?: { headers?: Record }): Promise> { + const resp = await this.apiReq(method, path, body, undefined, options); + if ("err" in resp) return resp; + const json = await this.jsonOrNull(resp); + if (resp.ok) return { ok: json as RES }; + else if (isApiError(json)) return { err: json, status: resp.status }; + else throw resp; + } + + private async stringApiReq(method: string, path: string, options?: { headers?: Record }): Promise> { + const resp = await this.apiReq(method, path, undefined, options); + if ("err" in resp) return resp; + if (resp.ok) return { ok: await this.stringOrNull(resp) }; + else { + const json = await this.jsonOrNull(resp); + if (isApiError(json)) return { err: json, status: resp.status }; + else throw resp; + } + } + + private async apiReq(method: string, path: string, body?: BODY, options?: { headers?: Record }): Promise { + const url = `${remoteOrigin(this.params)}${path}`; + let tokenResp = await this.getToken(); + if ("err" in tokenResp) return tokenResp; + let bodyString = undefined; + if (body !== undefined) bodyString = JSON.stringify(body) + let headers = Object.assign({ "Authorization": `Bearer ${tokenResp.ok.token}`, "Content-Type": "application/json" }, options?.headers || {}); + let resp = await fetch(url, { method, body: bodyString, headers }); + if (resp.status === HTTP_UNAUTHORIZED) { + tokenResp = await this.refreshToken(); + if ("err" in tokenResp) return tokenResp; + headers = Object.assign({ "Authorization": `Bearer ${tokenResp.ok.token}`, "Content-Type": "application/json" }, options?.headers || {}); + resp = await fetch(url, { method, body: bodyString, headers }); + } + return resp; + } + + private getToken(): Promise> { + if (this.token) { + const resp: ApiResponse ={ ok: { token: this.token } }; + return Promise.resolve(resp); + } else return this.refreshToken(); + } + + private async refreshToken(): Promise> { + const url = `${remoteOrigin(this.params)}/v1/signin`; + const body = { username: this.params.username, password: this.params.password }; + const resp = await fetch(url, { method: "POST", body: JSON.stringify(body), headers: { "Content-Type": "application/json" } }); + const json = await this.jsonOrNull(resp); + if (resp.ok) { + this.token = (json as SignInResponse).token; + return { ok: json }; + } else if (isApiError(json)) { + return { err: json, status: resp.status }; + } else throw resp; + } + + private async jsonOrNull(resp: Response) { + const contentLengthRaw = resp.headers.get("Content-Length"); + const contentLength = parseInt(contentLengthRaw || ""); + if (isNaN(contentLength)) throw `Received invalid Content-Length header: ${contentLengthRaw}`; + return contentLength > 0 ? await resp.json() : null; + } + + private async stringOrNull(resp: Response) { + const contentLengthRaw = resp.headers.get("Content-Length"); + const contentLength = parseInt(contentLengthRaw || ""); + if (isNaN(contentLength)) throw `Received invalid Content-Length header: ${contentLengthRaw}`; + return contentLength > 0 ? await resp.text() : null; + } +} diff --git a/http-ts/package.json b/http-ts/package.json new file mode 100644 index 000000000..16806ebe7 --- /dev/null +++ b/http-ts/package.json @@ -0,0 +1,19 @@ +{ + "name": "@samuel-butcher-typedb/typedb-http-driver", + "version": "0.0.0", + "description": "TypeDB HTTP Driver", + "author": "TypeDB", + "license": "MPL-2.0", + "homepage": "https://typedb.com", + "type": "module", + "main": "index.ts", + "repository": { + "type": "git", + "url": "https://github.com/typedb/typedb-driver" + }, + "keywords": [], + "packageManager": "pnpm@9.15.3+sha512.1f79bc245a66eb0b07c5d4d83131240774642caaa86ef7d0434ab47c0d16f66b04e21e0c086eb61e62c77efc4d7f7ec071afad3796af64892fae66509173893a", + "dependencies": { + "typescript": "^5.8.3" + } +} diff --git a/http-ts/params.ts b/http-ts/params.ts new file mode 100644 index 000000000..583bcca1b --- /dev/null +++ b/http-ts/params.ts @@ -0,0 +1,37 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +export interface DriverParamsBasic { + username: string; + password: string; + addresses: string[]; +} + +export interface DriverParamsTranslated { + username: string; + password: string; + translatedAddresses: TranslatedAddress[]; +} + +export interface TranslatedAddress { + external: string; + internal: string; +} + +export type DriverParams = DriverParamsBasic | DriverParamsTranslated; + +export function isBasicParams(params: DriverParams): params is DriverParamsBasic { + return `addresses` in params; +} + +export function isTranslatedParams(params: DriverParams): params is DriverParamsTranslated { + return `translatedAddresses` in params; +} + +export function remoteOrigin(params: DriverParams) { + if (isBasicParams(params)) return `${params.addresses[0]}`; + else return `${params.translatedAddresses[0].external}`; +} diff --git a/http-ts/pnpm-lock.yaml b/http-ts/pnpm-lock.yaml new file mode 100644 index 000000000..c1755041b --- /dev/null +++ b/http-ts/pnpm-lock.yaml @@ -0,0 +1,24 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: false + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + typescript: + specifier: ^5.8.3 + version: 5.8.3 + +packages: + + typescript@5.8.3: + resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} + engines: {node: '>=14.17'} + hasBin: true + +snapshots: + + typescript@5.8.3: {} diff --git a/http-ts/query-structure.ts b/http-ts/query-structure.ts new file mode 100644 index 000000000..56e740b83 --- /dev/null +++ b/http-ts/query-structure.ts @@ -0,0 +1,190 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import { Type, Value } from "./concept"; + +export type QueryVertexKind = "variable" | "label" | "value"; + +export interface QueryVertexVariable { + tag: "variable"; + id: string, +} + +export interface QueryVertexLabel { + tag: "label"; + type: Type; +} + +export interface QueryVertexValue { + tag: "value"; + value: Value; +} + +export type QueryVertex = QueryVertexVariable | QueryVertexLabel | QueryVertexValue; +// TODO: +// export enum VertexKindOther = { } +export type QueryStructure = { + blocks: { constraints: QueryConstraintAny[] }[], + variables: {[name: string]: QueryVariableInfo }, + outputs: string[], +}; + +export function get_variable_name(structure: QueryStructure, variable: QueryVertexVariable) : string | null { + return structure.variables[variable.id]?.name; +} + +export type QueryVariableInfo = { name: string | null }; + +export type QueryConstraintAny = QueryConstraintIsa | QueryConstraintIsaExact | QueryConstraintHas | QueryConstraintLinks | + QueryConstraintSub | QueryConstraintSubExact | QueryConstraintOwns | QueryConstraintRelates | QueryConstraintPlays | + QueryConstraintExpression | QueryConstraintFunction | QueryConstraintComparison | + QueryConstraintIs | QueryConstraintIid | QueryConstraintKind | QueryConstraintValue | QueryConstraintLabel; + +export type QueryConstraintSpan = { begin: number, end: number }; + +// Instance +export interface QueryConstraintIsa { + tag: "isa", + textSpan: QueryConstraintSpan, + + instance: QueryVertexVariable, + type: QueryVertexVariable | QueryVertexLabel, +} + +export interface QueryConstraintIsaExact { + tag: "isa!", + textSpan: QueryConstraintSpan, + + instance: QueryVertexVariable, + type: QueryVertexVariable | QueryVertexLabel, +} + +export interface QueryConstraintHas { + tag: "has", + textSpan: QueryConstraintSpan, + + owner: QueryVertexVariable + attribute: QueryVertexVariable, +} + + +export interface QueryConstraintLinks { + tag: "links", + textSpan: QueryConstraintSpan, + + relation: QueryVertexVariable, + player: QueryVertexVariable, + role: QueryVertexVariable | QueryVertexLabel, +} + +// Type +export interface QueryConstraintSub { + tag: "sub", + textSpan: QueryConstraintSpan, + + subtype: QueryVertexVariable | QueryVertexLabel, + supertype: QueryVertexVariable | QueryVertexLabel, +} + +export interface QueryConstraintSubExact { + tag: "sub!", + textSpan: QueryConstraintSpan, + + subtype: QueryVertexVariable | QueryVertexLabel, + supertype: QueryVertexVariable | QueryVertexLabel, +} + +export interface QueryConstraintOwns { + tag: "owns", + textSpan: QueryConstraintSpan, + + owner: QueryVertexVariable | QueryVertexLabel, + attribute: QueryVertexVariable | QueryVertexLabel, +} + +export interface QueryConstraintRelates { + tag: "relates", + textSpan: QueryConstraintSpan, + + relation: QueryVertexVariable | QueryVertexLabel, + role: QueryVertexVariable | QueryVertexLabel, +} + +export interface QueryConstraintPlays { + tag: "plays", + textSpan: QueryConstraintSpan, + + player: QueryVertexVariable | QueryVertexLabel, + role: QueryVertexVariable | QueryVertexLabel, +} + +// Function +export interface QueryConstraintExpression { + tag: "expression", + textSpan: QueryConstraintSpan, + + text: string, + arguments: QueryVertexVariable[], + assigned: QueryVertexVariable[], +} + +export interface QueryConstraintFunction { + tag: "functionCall", + textSpan: QueryConstraintSpan, + + name: string, + arguments: QueryVertexVariable[], + assigned: QueryVertexVariable[], +} + +export interface QueryConstraintComparison { + tag: "comparison", + textSpan: QueryConstraintSpan, + + lhs: QueryVertexVariable | QueryVertexValue, + rhs: QueryVertexVariable | QueryVertexValue, + comparator: string, +} + +export interface QueryConstraintIs { + tag: "is", + textSpan: QueryConstraintSpan, + + lhs: QueryVertexVariable, + rhs: QueryVertexVariable, +} + +export interface QueryConstraintIid { + tag: "iid", + textSpan: QueryConstraintSpan, + + concept: QueryVertexVariable, + iid: string, +} + +export interface QueryConstraintLabel { + tag: "label", + textSpan: QueryConstraintSpan, + + type: QueryVertexVariable, + label: string, +} + +export interface QueryConstraintValue { + tag: "value", + textSpan: QueryConstraintSpan, + + attributeType: QueryVertexVariable, + valueType: string, +} + +export interface QueryConstraintKind { + tag: "kind", + textSpan: QueryConstraintSpan, + + type: QueryVertexVariable, + kind: string, +} diff --git a/http-ts/query.ts b/http-ts/query.ts new file mode 100644 index 000000000..25f01f1b2 --- /dev/null +++ b/http-ts/query.ts @@ -0,0 +1,10 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +export interface QueryOptions { + includeInstanceTypes?: boolean; + answerCountLimit?: number; +} diff --git a/http-ts/response.ts b/http-ts/response.ts new file mode 100644 index 000000000..564daf87e --- /dev/null +++ b/http-ts/response.ts @@ -0,0 +1,96 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import { Concept } from "./concept"; +import { Database } from "./database"; +import { User } from "./user"; +import { QueryStructure } from "./query-structure"; + +export interface SignInResponse { + token: string; +} + +export type Distribution = `TypeDB Cluster` | `TypeDB CE`; + +export interface VersionResponse { + distribution: Distribution; + version: string; +} + +export interface DatabasesListResponse { + databases: Database[]; +} + +export interface UsersListResponse { + users: User[]; +} + +export interface TransactionOpenResponse { + transactionId: string; +} + +export type QueryType = "read" | "write" | "schema"; + +export type AnswerType = "ok" | "conceptRows" | "conceptDocuments"; + +export interface ConceptRow { + [varName: string]: Concept | undefined; +} + +export interface ConceptRowAnswer { + involvedBlocks: number[]; + data: ConceptRow; +} + +export type ConceptDocument = Object; + +export type Answer = ConceptRowAnswer | ConceptDocument; + +export interface QueryResponseBase { + answerType: AnswerType; + queryType: QueryType; + comment: string | null; + query: QueryStructure | null; +} + +export interface OkQueryResponse extends QueryResponseBase { + answerType: "ok"; +} + +export interface ConceptRowsQueryResponse extends QueryResponseBase { + answerType: "conceptRows"; + answers: ConceptRowAnswer[]; +} + +export interface ConceptDocumentsQueryResponse extends QueryResponseBase { + answerType: "conceptDocuments"; + answers: ConceptDocument[]; +} + +export type QueryResponse = OkQueryResponse | ConceptRowsQueryResponse | ConceptDocumentsQueryResponse; + +export type ApiOkResponse = { ok: OK_RES }; + +export type ApiError = { code: string; message: string }; + +export interface ApiErrorResponse { + err: ApiError; + status: number; +} + +export function isApiError(err: any): err is ApiError { + return typeof err.code === "string" && typeof err.message === "string"; +} + +export type ApiResponse = ApiOkResponse | ApiErrorResponse; + +export function isOkResponse(res: ApiResponse): res is ApiOkResponse { + return "ok" in res; +} + +export function isApiErrorResponse(res: ApiResponse): res is ApiErrorResponse { + return "err" in res; +} diff --git a/http-ts/transaction.ts b/http-ts/transaction.ts new file mode 100644 index 000000000..b19bed6e4 --- /dev/null +++ b/http-ts/transaction.ts @@ -0,0 +1,12 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +export type TransactionType = "read" | "write" | "schema"; + +export interface TransactionOptions { + schemaLockAcquireTimeoutMillis?: number; + transactionTimeoutMillis?: number; +} diff --git a/http-ts/user.ts b/http-ts/user.ts new file mode 100644 index 000000000..ea13505df --- /dev/null +++ b/http-ts/user.ts @@ -0,0 +1,9 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +export interface User { + username: string; +} From 223c779d1f24142220424f6aeb481010e0a6b7da Mon Sep 17 00:00:00 2001 From: sam-butcher Date: Wed, 9 Jul 2025 16:50:52 +0100 Subject: [PATCH 02/13] more consistent naming, extra exports, readme --- http-ts/README.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ http-ts/index.ts | 13 ++++++++++--- 2 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 http-ts/README.md diff --git a/http-ts/README.md b/http-ts/README.md new file mode 100644 index 000000000..7fd5a1395 --- /dev/null +++ b/http-ts/README.md @@ -0,0 +1,45 @@ +# TypeDB HTTP Typescript Driver + +## Driver Architecture + +To learn about the mechanism that TypeDB drivers use set up communication with databases running on the TypeDB Server, +refer to the [Drivers Overview](https://typedb.com/docs/drivers/overview). + +## API Reference + +To learn about the methods available for executing queries and retrieving their answers using Rust, refer to +the [API Reference](https://typedb.com/docs/drivers/http/api-reference). + +## Install TypeDB HTTP Typescript Driver through NPM + +1. Install `typedb-http-driver` through npm: + +```bash +npm install typedb-http-driver +``` + +2. Make sure the [TypeDB Server](https://docs.typedb.com/docs/running-typedb/install-and-run#start-the-typedb-server) is + running. +3. Use TypeDB Driver in your program: + +```ts +import { TypeDBHttpDriver, isApiErrorResponse } from "typedb-http-driver"; + +const driver = new TypeDBHttpDriver({ + username: "admin", + password: "password", + addresses: [ "localhost:1729" ], +}); + +const readTx = await driver.openTransaction("database-name", "read"); +if (isApiErrorResponse(readTx)) throw readTx; + +const readAnswer = await driver.query(newReadTx.ok.transactionId, "match entity $x;"); +if (isApiErrorResponse(readAnswer)) throw readAnswer; + +if (readAnswer.ok.answerType === "conceptRows") { + readAnswer.ok.answers.forEach((row) => { + console.log(row.data) + }) +} +``` diff --git a/http-ts/index.ts b/http-ts/index.ts index b49f769ea..4a7c72aef 100644 --- a/http-ts/index.ts +++ b/http-ts/index.ts @@ -23,7 +23,14 @@ import { QueryOptions } from "./query"; const HTTP_UNAUTHORIZED = 401; -export { isOkResponse, isApiErrorResponse } from "./response"; +export * from "./concept"; +export * from "./database"; +export * from "./params"; +export * from "./query"; +export * from "./query-structure"; +export * from "./response"; +export * from "./transaction"; +export * from "./user"; export class TypeDBHttpDriver { @@ -31,7 +38,7 @@ export class TypeDBHttpDriver { constructor(private params: DriverParams) {} - listDatabases(): Promise> { + getDatabases(): Promise> { return this.apiGet(`/v1/databases`); } @@ -55,7 +62,7 @@ export class TypeDBHttpDriver { return this.apiGetString(`/v1/databases/${name}/type-schema`); } - listUsers(): Promise> { + getUsers(): Promise> { return this.apiGet(`/v1/users`); } From 98d9f71d526d7cbd2d8487697dc3b7696952de44 Mon Sep 17 00:00:00 2001 From: sam-butcher Date: Wed, 9 Jul 2025 16:52:53 +0100 Subject: [PATCH 03/13] alpha1 --- http-ts/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/http-ts/package.json b/http-ts/package.json index 16806ebe7..81682b9ec 100644 --- a/http-ts/package.json +++ b/http-ts/package.json @@ -1,6 +1,6 @@ { "name": "@samuel-butcher-typedb/typedb-http-driver", - "version": "0.0.0", + "version": "0.0.0-alpha1", "description": "TypeDB HTTP Driver", "author": "TypeDB", "license": "MPL-2.0", From 0b7f407d25d9e8faa99ab7927d041c5cba4907a6 Mon Sep 17 00:00:00 2001 From: sam-butcher Date: Wed, 9 Jul 2025 17:51:44 +0100 Subject: [PATCH 04/13] make http ts driver publishable --- WORKSPACE | 8 ++++ http-ts/BUILD | 94 ++++++++++++++++++++++++++++++++++++++++++ http-ts/README.md | 22 +++++----- http-ts/index.ts | 2 +- http-ts/package.json | 6 +-- http-ts/pnpm-lock.yaml | 20 ++++----- http-ts/tsconfig.json | 69 +++++++++++++++++++++++++++++++ 7 files changed, 194 insertions(+), 27 deletions(-) create mode 100644 http-ts/BUILD create mode 100644 http-ts/tsconfig.json diff --git a/WORKSPACE b/WORKSPACE index 60b1ea36d..454881a6a 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -260,6 +260,14 @@ npm_translate_lock( load("@nodejs_npm//:repositories.bzl", "npm_repositories") npm_repositories() +npm_translate_lock( + name = "http-ts_npm", + pnpm_lock = "//http-ts:pnpm-lock.yaml", +) + +load("@http-ts_npm//:repositories.bzl", http_ts_npm_repositories = "npm_repositories") +http_ts_npm_repositories() + # Setup rules_ts load("@aspect_rules_ts//ts:repositories.bzl", "rules_ts_dependencies") diff --git a/http-ts/BUILD b/http-ts/BUILD new file mode 100644 index 000000000..ce022df0c --- /dev/null +++ b/http-ts/BUILD @@ -0,0 +1,94 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +exports_files([ + "pnpm-lock.yaml", + "package.json", + "tsconfig.json", +]) + +load("@typedb_bazel_distribution//npm:rules.bzl", "assemble_npm", "deploy_npm") +load("@typedb_dependencies//tool/checkstyle:rules.bzl", "checkstyle_test") +load("@typedb_dependencies//distribution:deployment.bzl", "deployment") +load("@aspect_rules_ts//ts:defs.bzl", "ts_project") +load("@aspect_rules_js//js:defs.bzl", "js_binary") +load("@aspect_rules_js//npm:defs.bzl", "npm_link_package", "npm_package") +load("@aspect_bazel_lib//lib:jq.bzl", "jq") +load("@http-ts_npm//:defs.bzl", "npm_link_all_packages") +load("//nodejs:tool/typedoc/rules.bzl", "typedoc_docs") +load("//nodejs:docs_structure.bzl", "dir_mapping") +load("//tool/docs:nodejs/rules.bzl", "typedoc_to_adoc") + +npm_link_all_packages( + name = "node_modules", +) + +ts_project( + name = "driver-http-ts", + srcs = glob(["*.ts"]), + tsconfig = ":tsconfig.json", + declaration = True, + deps = [":node_modules/typescript"], + transpiler = "tsc", + visibility = ["//visibility:public"], + out_dir = "dist", +) + +jq( + name = "package", + srcs = ["package.json"], + filter = "|".join([ + # Don't directly reference $STAMP as it's only set when stamping + # This 'as' syntax results in $stamp being null in unstamped builds. + "$ARGS.named.STAMP as $stamp", + # Provide a default using the "alternative operator" in case $stamp is null. + ".version = ($stamp.STABLE_VERSION // \"0.0.0\")" + ]), +) + +npm_package( + name = "driver-http-ts-npm-package", + srcs = [":driver-http-ts", ":package", "README.md"], + include_runfiles = False, + replace_prefixes = { "dist/": "" }, + visibility = ["//visibility:public"], +) + +assemble_npm( + name= "assemble-npm", + target = ":driver-http-ts-npm-package", +) + +deploy_npm( + name = "deploy-npm", + target = ":assemble-npm", + snapshot = deployment['npm']['snapshot'], + release = deployment['npm']['release'], +) + +checkstyle_test( + name = "checkstyle", + include = glob([ + "*", + ]), + exclude = glob([ + "*.json", + "*.md", + "pnpm-lock.yaml", + ]), + license_type = "apache-header", +) diff --git a/http-ts/README.md b/http-ts/README.md index 7fd5a1395..0a14b70d7 100644 --- a/http-ts/README.md +++ b/http-ts/README.md @@ -2,13 +2,13 @@ ## Driver Architecture -To learn about the mechanism that TypeDB drivers use set up communication with databases running on the TypeDB Server, -refer to the [Drivers Overview](https://typedb.com/docs/drivers/overview). +To learn about how the TypeDB HTTP driver communicates with the TypeDB Server, +refer to the [HTTP API Reference](https://typedb.com/docs/reference/http-api). ## API Reference -To learn about the methods available for executing queries and retrieving their answers using Rust, refer to -the [API Reference](https://typedb.com/docs/drivers/http/api-reference). +To learn about the methods available for executing queries and retrieving their answers using Typescript, refer to +the [API Reference](https://typedb.com/docs/reference/http-drivers/typescript). ## Install TypeDB HTTP Typescript Driver through NPM @@ -31,14 +31,16 @@ const driver = new TypeDBHttpDriver({ addresses: [ "localhost:1729" ], }); -const readTx = await driver.openTransaction("database-name", "read"); -if (isApiErrorResponse(readTx)) throw readTx; +const transactionResponse = await driver.openTransaction("database-name", "read"); +if (isApiErrorResponse(transactionResponse)) throw transactionResponse.err; +const transactionId = transactionResponse.ok.transactionId; -const readAnswer = await driver.query(newReadTx.ok.transactionId, "match entity $x;"); -if (isApiErrorResponse(readAnswer)) throw readAnswer; +const answerResponse = await driver.query(transactionId, "match entity $x;"); +if (isApiErrorResponse(answerResponse)) throw answerResponse.err; +const answer = answerResponse.ok; -if (readAnswer.ok.answerType === "conceptRows") { - readAnswer.ok.answers.forEach((row) => { +if (answer.answerType === "conceptRows") { + answer.answers.forEach((row) => { console.log(row.data) }) } diff --git a/http-ts/index.ts b/http-ts/index.ts index 4a7c72aef..afccb4eb7 100644 --- a/http-ts/index.ts +++ b/http-ts/index.ts @@ -139,7 +139,7 @@ export class TypeDBHttpDriver { } private async jsonApiReq(method: string, path: string, body?: BODY, options?: { headers?: Record }): Promise> { - const resp = await this.apiReq(method, path, body, undefined, options); + const resp = await this.apiReq(method, path, body, options); if ("err" in resp) return resp; const json = await this.jsonOrNull(resp); if (resp.ok) return { ok: json as RES }; diff --git a/http-ts/package.json b/http-ts/package.json index 81682b9ec..2c27ae3c8 100644 --- a/http-ts/package.json +++ b/http-ts/package.json @@ -1,6 +1,6 @@ { "name": "@samuel-butcher-typedb/typedb-http-driver", - "version": "0.0.0-alpha1", + "version": "0.0.0", "description": "TypeDB HTTP Driver", "author": "TypeDB", "license": "MPL-2.0", @@ -11,8 +11,8 @@ "type": "git", "url": "https://github.com/typedb/typedb-driver" }, - "keywords": [], - "packageManager": "pnpm@9.15.3+sha512.1f79bc245a66eb0b07c5d4d83131240774642caaa86ef7d0434ab47c0d16f66b04e21e0c086eb61e62c77efc4d7f7ec071afad3796af64892fae66509173893a", + "keywords": ["database", "typedb"], + "packageManager": "pnpm@8.15.9", "dependencies": { "typescript": "^5.8.3" } diff --git a/http-ts/pnpm-lock.yaml b/http-ts/pnpm-lock.yaml index c1755041b..afd9c1e24 100644 --- a/http-ts/pnpm-lock.yaml +++ b/http-ts/pnpm-lock.yaml @@ -1,24 +1,18 @@ -lockfileVersion: '9.0' +lockfileVersion: '6.0' settings: autoInstallPeers: false excludeLinksFromLockfile: false -importers: - - .: - dependencies: - typescript: - specifier: ^5.8.3 - version: 5.8.3 +dependencies: + typescript: + specifier: ^5.8.3 + version: 5.8.3 packages: - typescript@5.8.3: + /typescript@5.8.3: resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} engines: {node: '>=14.17'} hasBin: true - -snapshots: - - typescript@5.8.3: {} + dev: false diff --git a/http-ts/tsconfig.json b/http-ts/tsconfig.json new file mode 100644 index 000000000..6bc613b0d --- /dev/null +++ b/http-ts/tsconfig.json @@ -0,0 +1,69 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Basic Options */ + // "incremental": true, /* Enable incremental compilation */ + "target": "es2021", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ + "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ + // "lib": [], /* Specify library files to be included in the compilation. */ + // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + "declaration": true, /* Generates corresponding '.d.ts' file. */ + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + // "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "dist", /* Redirect output structure to the directory. */ + // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + + /* Strict Type-Checking Options */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + "strictNullChecks": false, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + + /* Module Resolution Options */ + "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "rootDirs": [] /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + + /* Advanced Options */ + "skipLibCheck": true, /* Skip type checking of declaration files. */ + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + }, + "include": ["*.ts"] +} From 9c84593f4498aeeb840a8eed4a8bff2a1c6960d4 Mon Sep 17 00:00:00 2001 From: sam-butcher Date: Wed, 9 Jul 2025 17:54:43 +0100 Subject: [PATCH 05/13] circleci release process for http ts driver --- .circleci/config.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index f28e253a8..fb12045c8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -477,6 +477,13 @@ commands: export DEPLOY_NPM_PASSWORD=$REPO_TYPEDB_PASSWORD bazel run --jobs=8 --define version=$(git rev-parse HEAD) //nodejs:deploy-npm -- snapshot + deploy-http-ts-npm-snapshot-unix: + steps: + - run: | + export DEPLOY_NPM_USERNAME=$REPO_TYPEDB_USERNAME + export DEPLOY_NPM_PASSWORD=$REPO_TYPEDB_PASSWORD + bazel run --jobs=8 --define version=$(git rev-parse HEAD) //http-ts:deploy-npm -- snapshot + test-npm-snapshot-unix: steps: - run: | @@ -497,6 +504,14 @@ commands: export DEPLOY_NPM_TOKEN=$REPO_NPM_TOKEN bazel run --jobs=8 --define version=$(cat VERSION) //nodejs:deploy-npm --compilation_mode=opt -- release + deploy-http-ts-npm-release-unix: + steps: + - run: | + wget -q -O - https://cli-assets.heroku.com/apt/release.key | apt-key add - + wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | apt-key add - + export DEPLOY_NPM_TOKEN=$REPO_NPM_TOKEN + bazel run --jobs=8 --define version=$(cat VERSION) //http-ts:deploy-npm --compilation_mode=opt -- release + jobs: ################# @@ -621,6 +636,7 @@ jobs: bazel-arch: amd64 - deploy-crate-snapshot-unix - deploy-maven-snapshot-unix + - deploy-http-ts-npm-snapshot-unix # - deploy-npm-snapshot-unix deploy-snapshot-dotnet-any: @@ -777,6 +793,7 @@ jobs: bazel-arch: amd64 - deploy-crate-release-unix - deploy-maven-release-unix + - deploy=http-ts-npm-release-unix # - deploy-npm-release-unix deploy-release-dotnet-any: From 39bf1052ee239b94e52044499e56c0c569a920d8 Mon Sep 17 00:00:00 2001 From: sam-butcher Date: Wed, 9 Jul 2025 17:55:57 +0100 Subject: [PATCH 06/13] correct name --- http-ts/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/http-ts/package.json b/http-ts/package.json index 2c27ae3c8..b54806465 100644 --- a/http-ts/package.json +++ b/http-ts/package.json @@ -1,5 +1,5 @@ { - "name": "@samuel-butcher-typedb/typedb-http-driver", + "name": "typedb-http-driver", "version": "0.0.0", "description": "TypeDB HTTP Driver", "author": "TypeDB", From 8d43394c77f3ec20f016060f72478d989064b11c Mon Sep 17 00:00:00 2001 From: sam-butcher Date: Thu, 10 Jul 2025 08:51:55 +0100 Subject: [PATCH 07/13] trigger ci From 65dbe31eda20c99d629f83c8db203d8a21b313fb Mon Sep 17 00:00:00 2001 From: sam-butcher Date: Thu, 10 Jul 2025 09:15:07 +0100 Subject: [PATCH 08/13] license updates --- http-ts/concept.ts | 19 ++++++++++++++++--- http-ts/database.ts | 19 ++++++++++++++++--- http-ts/index.ts | 19 ++++++++++++++++--- http-ts/package.json | 2 +- http-ts/params.ts | 19 ++++++++++++++++--- http-ts/query-structure.ts | 19 ++++++++++++++++--- http-ts/query.ts | 19 ++++++++++++++++--- http-ts/response.ts | 19 ++++++++++++++++--- http-ts/transaction.ts | 19 ++++++++++++++++--- http-ts/user.ts | 19 ++++++++++++++++--- 10 files changed, 145 insertions(+), 28 deletions(-) diff --git a/http-ts/concept.ts b/http-ts/concept.ts index a29c79407..4e35c62fe 100644 --- a/http-ts/concept.ts +++ b/http-ts/concept.ts @@ -1,7 +1,20 @@ /* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ export type TypeKind = "entityType" | "relationType" | "attributeType" | "roleType"; diff --git a/http-ts/database.ts b/http-ts/database.ts index b15ae19ac..0e2dd3ec1 100644 --- a/http-ts/database.ts +++ b/http-ts/database.ts @@ -1,7 +1,20 @@ /* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ export interface Database { diff --git a/http-ts/index.ts b/http-ts/index.ts index afccb4eb7..46190b5bd 100644 --- a/http-ts/index.ts +++ b/http-ts/index.ts @@ -1,7 +1,20 @@ /* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ import { TransactionOptions, TransactionType } from "./transaction"; diff --git a/http-ts/package.json b/http-ts/package.json index b54806465..d884fdb58 100644 --- a/http-ts/package.json +++ b/http-ts/package.json @@ -3,7 +3,7 @@ "version": "0.0.0", "description": "TypeDB HTTP Driver", "author": "TypeDB", - "license": "MPL-2.0", + "license": "Apache-2.0", "homepage": "https://typedb.com", "type": "module", "main": "index.ts", diff --git a/http-ts/params.ts b/http-ts/params.ts index 583bcca1b..1107f6212 100644 --- a/http-ts/params.ts +++ b/http-ts/params.ts @@ -1,7 +1,20 @@ /* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ export interface DriverParamsBasic { diff --git a/http-ts/query-structure.ts b/http-ts/query-structure.ts index 56e740b83..1cade0820 100644 --- a/http-ts/query-structure.ts +++ b/http-ts/query-structure.ts @@ -1,7 +1,20 @@ /* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ import { Type, Value } from "./concept"; diff --git a/http-ts/query.ts b/http-ts/query.ts index 25f01f1b2..b42888c2e 100644 --- a/http-ts/query.ts +++ b/http-ts/query.ts @@ -1,7 +1,20 @@ /* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ export interface QueryOptions { diff --git a/http-ts/response.ts b/http-ts/response.ts index 564daf87e..016d33438 100644 --- a/http-ts/response.ts +++ b/http-ts/response.ts @@ -1,7 +1,20 @@ /* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ import { Concept } from "./concept"; diff --git a/http-ts/transaction.ts b/http-ts/transaction.ts index b19bed6e4..af6078736 100644 --- a/http-ts/transaction.ts +++ b/http-ts/transaction.ts @@ -1,7 +1,20 @@ /* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ export type TransactionType = "read" | "write" | "schema"; diff --git a/http-ts/user.ts b/http-ts/user.ts index ea13505df..41895484e 100644 --- a/http-ts/user.ts +++ b/http-ts/user.ts @@ -1,7 +1,20 @@ /* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ export interface User { From a34ae3ca76db6eb33ae9f52777040c750b726d41 Mon Sep 17 00:00:00 2001 From: sam-butcher Date: Thu, 10 Jul 2025 09:54:08 +0100 Subject: [PATCH 09/13] update package json name --- http-ts/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/http-ts/package.json b/http-ts/package.json index d884fdb58..32d35bf95 100644 --- a/http-ts/package.json +++ b/http-ts/package.json @@ -1,5 +1,5 @@ { - "name": "typedb-http-driver", + "name": "typedb-driver-http", "version": "0.0.0", "description": "TypeDB HTTP Driver", "author": "TypeDB", From eb240bddb3526145eae8d977fdc6629adc639b1a Mon Sep 17 00:00:00 2001 From: sam-butcher Date: Thu, 10 Jul 2025 10:29:41 +0100 Subject: [PATCH 10/13] cleanup --- .circleci/config.yml | 4 ++-- http-ts/README.md | 2 +- http-ts/database.ts | 22 ---------------------- http-ts/index.ts | 28 ++++++++++++++++++++-------- http-ts/query.ts | 23 ----------------------- http-ts/transaction.ts | 25 ------------------------- http-ts/user.ts | 22 ---------------------- 7 files changed, 23 insertions(+), 103 deletions(-) delete mode 100644 http-ts/database.ts delete mode 100644 http-ts/query.ts delete mode 100644 http-ts/transaction.ts delete mode 100644 http-ts/user.ts diff --git a/.circleci/config.yml b/.circleci/config.yml index fb12045c8..06853ce76 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -482,7 +482,7 @@ commands: - run: | export DEPLOY_NPM_USERNAME=$REPO_TYPEDB_USERNAME export DEPLOY_NPM_PASSWORD=$REPO_TYPEDB_PASSWORD - bazel run --jobs=8 --define version=$(git rev-parse HEAD) //http-ts:deploy-npm -- snapshot + bazel run --define version=$(git rev-parse HEAD) //http-ts:deploy-npm -- snapshot test-npm-snapshot-unix: steps: @@ -510,7 +510,7 @@ commands: wget -q -O - https://cli-assets.heroku.com/apt/release.key | apt-key add - wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | apt-key add - export DEPLOY_NPM_TOKEN=$REPO_NPM_TOKEN - bazel run --jobs=8 --define version=$(cat VERSION) //http-ts:deploy-npm --compilation_mode=opt -- release + bazel run --define version=$(cat VERSION) //http-ts:deploy-npm --compilation_mode=opt -- release jobs: diff --git a/http-ts/README.md b/http-ts/README.md index 0a14b70d7..ad3d527ef 100644 --- a/http-ts/README.md +++ b/http-ts/README.md @@ -23,7 +23,7 @@ npm install typedb-http-driver 3. Use TypeDB Driver in your program: ```ts -import { TypeDBHttpDriver, isApiErrorResponse } from "typedb-http-driver"; +import { TypeDBHttpDriver, isApiErrorResponse } from "typedb-driver-http"; const driver = new TypeDBHttpDriver({ username: "admin", diff --git a/http-ts/database.ts b/http-ts/database.ts deleted file mode 100644 index 0e2dd3ec1..000000000 --- a/http-ts/database.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export interface Database { - name: string; -} diff --git a/http-ts/index.ts b/http-ts/index.ts index 46190b5bd..587acd416 100644 --- a/http-ts/index.ts +++ b/http-ts/index.ts @@ -17,7 +17,6 @@ * under the License. */ -import { TransactionOptions, TransactionType } from "./transaction"; import { DriverParams, remoteOrigin } from "./params"; import { ApiErrorResponse, @@ -30,20 +29,13 @@ import { UsersListResponse, VersionResponse } from "./response"; -import { User } from "./user"; -import { Database } from "./database"; -import { QueryOptions } from "./query"; const HTTP_UNAUTHORIZED = 401; export * from "./concept"; -export * from "./database"; export * from "./params"; -export * from "./query"; export * from "./query-structure"; export * from "./response"; -export * from "./transaction"; -export * from "./user"; export class TypeDBHttpDriver { @@ -222,3 +214,23 @@ export class TypeDBHttpDriver { return contentLength > 0 ? await resp.text() : null; } } + +export interface Database { + name: string; +} + +export type TransactionType = "read" | "write" | "schema"; + +export interface TransactionOptions { + schemaLockAcquireTimeoutMillis?: number; + transactionTimeoutMillis?: number; +} + +export interface QueryOptions { + includeInstanceTypes?: boolean; + answerCountLimit?: number; +} + +export interface User { + username: string; +} diff --git a/http-ts/query.ts b/http-ts/query.ts deleted file mode 100644 index b42888c2e..000000000 --- a/http-ts/query.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export interface QueryOptions { - includeInstanceTypes?: boolean; - answerCountLimit?: number; -} diff --git a/http-ts/transaction.ts b/http-ts/transaction.ts deleted file mode 100644 index af6078736..000000000 --- a/http-ts/transaction.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export type TransactionType = "read" | "write" | "schema"; - -export interface TransactionOptions { - schemaLockAcquireTimeoutMillis?: number; - transactionTimeoutMillis?: number; -} diff --git a/http-ts/user.ts b/http-ts/user.ts deleted file mode 100644 index 41895484e..000000000 --- a/http-ts/user.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export interface User { - username: string; -} From 3a9b499a8f9d3929217d87145afc00ce2f133d69 Mon Sep 17 00:00:00 2001 From: sam-butcher Date: Thu, 10 Jul 2025 10:37:33 +0100 Subject: [PATCH 11/13] remove dead TODO --- http-ts/query-structure.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/http-ts/query-structure.ts b/http-ts/query-structure.ts index 1cade0820..ef7dda737 100644 --- a/http-ts/query-structure.ts +++ b/http-ts/query-structure.ts @@ -37,8 +37,7 @@ export interface QueryVertexValue { } export type QueryVertex = QueryVertexVariable | QueryVertexLabel | QueryVertexValue; -// TODO: -// export enum VertexKindOther = { } + export type QueryStructure = { blocks: { constraints: QueryConstraintAny[] }[], variables: {[name: string]: QueryVariableInfo }, From 0d533fb235dfb19703c81f6f6182b5094832b1e3 Mon Sep 17 00:00:00 2001 From: sam-butcher Date: Thu, 10 Jul 2025 10:47:20 +0100 Subject: [PATCH 12/13] add TODO for tests --- .factory/automation.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.factory/automation.yml b/.factory/automation.yml index 06d2bc6be..a9c3d24fc 100644 --- a/.factory/automation.yml +++ b/.factory/automation.yml @@ -283,6 +283,8 @@ build: # tool/test/stop-cluster-servers.sh # exit $TEST_SUCCESS +# TODO: introduce integration/behaviour tests for http-ts driver + # test-nodejs-integration: # image: typedb-ubuntu-22.04 # dependencies: From 01e50fef7774ac750da22db2d841445a979d104c Mon Sep 17 00:00:00 2001 From: sam-butcher Date: Fri, 11 Jul 2025 08:57:02 +0100 Subject: [PATCH 13/13] cleanup and fixes --- http-ts/README.md | 4 ++-- http-ts/index.ts | 2 ++ http-ts/response.ts | 3 +-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/http-ts/README.md b/http-ts/README.md index ad3d527ef..0bd800353 100644 --- a/http-ts/README.md +++ b/http-ts/README.md @@ -12,10 +12,10 @@ the [API Reference](https://typedb.com/docs/reference/http-drivers/typescript). ## Install TypeDB HTTP Typescript Driver through NPM -1. Install `typedb-http-driver` through npm: +1. Install `typedb-driver-http` through npm: ```bash -npm install typedb-http-driver +npm install typedb-driver-http ``` 2. Make sure the [TypeDB Server](https://docs.typedb.com/docs/running-typedb/install-and-run#start-the-typedb-server) is diff --git a/http-ts/index.ts b/http-ts/index.ts index 587acd416..c96d8bb33 100644 --- a/http-ts/index.ts +++ b/http-ts/index.ts @@ -202,6 +202,7 @@ export class TypeDBHttpDriver { private async jsonOrNull(resp: Response) { const contentLengthRaw = resp.headers.get("Content-Length"); + if (!contentLengthRaw) return null; const contentLength = parseInt(contentLengthRaw || ""); if (isNaN(contentLength)) throw `Received invalid Content-Length header: ${contentLengthRaw}`; return contentLength > 0 ? await resp.json() : null; @@ -209,6 +210,7 @@ export class TypeDBHttpDriver { private async stringOrNull(resp: Response) { const contentLengthRaw = resp.headers.get("Content-Length"); + if (!contentLengthRaw) return null; const contentLength = parseInt(contentLengthRaw || ""); if (isNaN(contentLength)) throw `Received invalid Content-Length header: ${contentLengthRaw}`; return contentLength > 0 ? await resp.text() : null; diff --git a/http-ts/response.ts b/http-ts/response.ts index 016d33438..1495f73cd 100644 --- a/http-ts/response.ts +++ b/http-ts/response.ts @@ -17,9 +17,8 @@ * under the License. */ +import { Database, User } from "index"; import { Concept } from "./concept"; -import { Database } from "./database"; -import { User } from "./user"; import { QueryStructure } from "./query-structure"; export interface SignInResponse {