@cubicweb/client
Advanced tools
Comparing version 1.6.0 to 1.7.0
@@ -5,3 +5,3 @@ import { RawSchema } from "../schema/raw/Schema"; | ||
*/ | ||
export declare type RQLQuery = [string, RQLParams]; | ||
export type RQLQuery = [string, RQLParams]; | ||
/** | ||
@@ -16,11 +16,11 @@ * Type representing RQL parameters to send along a request. | ||
*/ | ||
export declare type RqlRow = Array<string | number | boolean | null>; | ||
export type RqlRow = Array<string | number | boolean | null>; | ||
/** | ||
* Type representing a RQL request result. | ||
*/ | ||
export declare type ResultSet = Array<RqlRow>; | ||
export type ResultSet = Array<RqlRow>; | ||
/** | ||
* Type representing the body of an error sent by CubicWeb's API. | ||
*/ | ||
declare type ApiError = { | ||
type ApiError = { | ||
title: string; | ||
@@ -33,3 +33,3 @@ message: string; | ||
*/ | ||
export declare type ApiErrorResponse = { | ||
export type ApiErrorResponse = { | ||
status: number; | ||
@@ -114,4 +114,5 @@ } & ApiError; | ||
transactionRollback(uuid: string): Promise<null>; | ||
private handleUserErrors; | ||
} | ||
export {}; | ||
//# sourceMappingURL=Api.d.ts.map |
@@ -12,2 +12,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const Errors_1 = require("../Errors"); | ||
/** | ||
@@ -62,7 +63,12 @@ * Class used to handle requests to the CubicWeb API. | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return nonNullFetchApi(this._rqlApiUrl, { | ||
method: "POST", | ||
body: JSON.stringify({ query, params }), | ||
credentials: "include", // FIXME is it secure? | ||
}); | ||
try { | ||
return yield nonNullFetchApi(this._rqlApiUrl, { | ||
method: "POST", | ||
body: JSON.stringify({ query, params }), | ||
credentials: "include", // FIXME is it secure? | ||
}); | ||
} | ||
catch (e) { | ||
this.handleUserErrors(e); | ||
} | ||
}); | ||
@@ -92,12 +98,16 @@ } | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return fetchApi(this._loginApiUrl, { | ||
method: "POST", | ||
body: JSON.stringify({ | ||
login, | ||
password, | ||
}), | ||
credentials: "include", | ||
}) | ||
.then(() => true) | ||
.catch(() => false); | ||
try { | ||
yield fetchApi(this._loginApiUrl, { | ||
method: "POST", | ||
body: JSON.stringify({ | ||
login, | ||
password, | ||
}), | ||
credentials: "include", | ||
}); | ||
return true; | ||
} | ||
catch (_error) { | ||
return false; | ||
} | ||
}); | ||
@@ -128,7 +138,12 @@ } | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return fetchApi(this._transactionApiUrl.execute, { | ||
method: "POST", | ||
body: JSON.stringify({ uuid, query, params }), | ||
credentials: "include", | ||
}); | ||
try { | ||
return yield fetchApi(this._transactionApiUrl.execute, { | ||
method: "POST", | ||
body: JSON.stringify({ uuid, query, params }), | ||
credentials: "include", | ||
}); | ||
} | ||
catch (e) { | ||
this.handleUserErrors(e); | ||
} | ||
}); | ||
@@ -143,7 +158,12 @@ } | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return fetchApi(this._transactionApiUrl.commit, { | ||
method: "POST", | ||
body: JSON.stringify({ uuid }), | ||
credentials: "include", | ||
}); | ||
try { | ||
return yield fetchApi(this._transactionApiUrl.commit, { | ||
method: "POST", | ||
body: JSON.stringify({ uuid }), | ||
credentials: "include", | ||
}); | ||
} | ||
catch (e) { | ||
this.handleUserErrors(e); | ||
} | ||
}); | ||
@@ -165,2 +185,16 @@ } | ||
} | ||
handleUserErrors(error) { | ||
if (typeof error === "object" && | ||
error !== null && | ||
"title" in error && | ||
typeof error.title === "string" && | ||
"message" in error && | ||
typeof error.message === "string") { | ||
if (error.title === "ValidationError") { | ||
throw new Errors_1.ValidationError(error.message); | ||
} | ||
throw error; | ||
} | ||
throw error; | ||
} | ||
} | ||
@@ -177,6 +211,6 @@ exports.default = Api; | ||
*/ | ||
const nonNullFetchApi = (input, init) => { | ||
return new Promise((resolve, reject) => fetchApi(input, init) | ||
.then((v) => { | ||
if (v == null) { | ||
function nonNullFetchApi(input, init) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const result = yield fetchApi(input, init); | ||
if (result == null) { | ||
const error = { | ||
@@ -187,10 +221,7 @@ status: 500, | ||
}; | ||
reject(error); | ||
throw error; | ||
} | ||
else { | ||
resolve(v); | ||
} | ||
}) | ||
.catch(reject)); | ||
}; | ||
return result; | ||
}); | ||
} | ||
/** | ||
@@ -205,36 +236,35 @@ * Sends a request to the given API route with the `Content-Type` header set and waits for a response. | ||
*/ | ||
const fetchApi = (input, init) => { | ||
let headers = init === null || init === void 0 ? void 0 : init.headers; | ||
if ((init === null || init === void 0 ? void 0 : init.method) && init.method !== "GET" && init.method !== "DELETE") { | ||
headers = Object.assign({ "Content-Type": "application/json;charset=UTF-8" }, init === null || init === void 0 ? void 0 : init.headers); | ||
} | ||
return new Promise((resolve, reject) => fetch(input, Object.assign(Object.assign({}, init), { headers })).then((response) => { | ||
function fetchApi(input, init) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let headers = init === null || init === void 0 ? void 0 : init.headers; | ||
if ((init === null || init === void 0 ? void 0 : init.method) && init.method !== "GET" && init.method !== "DELETE") { | ||
headers = Object.assign({ "Content-Type": "application/json;charset=UTF-8" }, init === null || init === void 0 ? void 0 : init.headers); | ||
} | ||
const response = yield fetch(input, Object.assign(Object.assign({}, init), { headers })); | ||
const status = response.status; | ||
if (status >= 200 && status < 300) { | ||
if (status === 204) { | ||
resolve(null); | ||
return null; | ||
} | ||
else { | ||
response | ||
.json() | ||
.then(resolve) | ||
.catch((e) => { | ||
console.error(e); | ||
resolve(null); | ||
}); | ||
try { | ||
return yield response.json(); | ||
} | ||
catch (e) { | ||
console.error(e); | ||
return null; | ||
} | ||
} | ||
else { | ||
response | ||
.json() | ||
.then((data) => { | ||
reject(Object.assign({ status }, data)); | ||
}) | ||
.catch((e) => { | ||
let json; | ||
try { | ||
json = yield response.json(); | ||
} | ||
catch (e) { | ||
console.error(e); | ||
reject({ status, title: "Error", message: "" }); | ||
}); | ||
throw { status, title: "Error", message: "" }; | ||
} | ||
throw Object.assign({ status }, json); | ||
} | ||
})); | ||
}; | ||
}); | ||
} | ||
//# sourceMappingURL=Api.js.map |
import { Schema } from "../schema/classes/Schema"; | ||
import { RQLParams } from "./Api"; | ||
import { RQLParams, ResultSet } from "./Api"; | ||
import Transaction from "./Transaction"; | ||
@@ -25,3 +25,3 @@ /** | ||
*/ | ||
execute(query: string, params?: RQLParams): Promise<import("./Api").ResultSet>; | ||
execute(query: string, params?: RQLParams): Promise<ResultSet>; | ||
/** | ||
@@ -45,2 +45,4 @@ * Retrieves the CubicWeb instance's JSON schema. | ||
* Once the callback's end is reached, the transaction is automatically committed. | ||
* Note that any exception thrown by the callback will lead to the | ||
* transaction being rolled back. | ||
* | ||
@@ -47,0 +49,0 @@ * @param callback Function to execute transaction requests in. |
@@ -74,2 +74,4 @@ "use strict"; | ||
* Once the callback's end is reached, the transaction is automatically committed. | ||
* Note that any exception thrown by the callback will lead to the | ||
* transaction being rolled back. | ||
* | ||
@@ -83,3 +85,12 @@ * @param callback Function to execute transaction requests in. | ||
yield transaction.begin(); | ||
const result = yield callback(transaction); | ||
let result; | ||
try { | ||
result = yield callback(transaction); | ||
} | ||
catch (error) { | ||
if (!transaction.isClosed()) { | ||
yield transaction.rollback(); | ||
} | ||
throw error; | ||
} | ||
if (!transaction.isClosed()) { | ||
@@ -86,0 +97,0 @@ yield transaction.commit(); |
export declare class InconsistentSchemaError extends Error { | ||
constructor(message: string); | ||
} | ||
export declare class ValidationError extends Error { | ||
constructor(message: string); | ||
} | ||
export declare class TransactionClosedError extends Error { | ||
@@ -5,0 +8,0 @@ constructor(); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.TransactionClosedError = exports.InconsistentSchemaError = void 0; | ||
exports.TransactionClosedError = exports.ValidationError = exports.InconsistentSchemaError = void 0; | ||
class InconsistentSchemaError extends Error { | ||
@@ -11,2 +11,9 @@ constructor(message) { | ||
exports.InconsistentSchemaError = InconsistentSchemaError; | ||
class ValidationError extends Error { | ||
constructor(message) { | ||
super(message); | ||
Object.setPrototypeOf(this, new.target.prototype); | ||
} | ||
} | ||
exports.ValidationError = ValidationError; | ||
class TransactionClosedError extends Error { | ||
@@ -13,0 +20,0 @@ constructor() { |
@@ -22,3 +22,3 @@ import { EntityRawSchemaArray } from "../raw/Entities"; | ||
*/ | ||
export declare type RelationDefinitionMatcher<E extends EntityRawSchemaArray> = Partial<RelationDefinitionRawSchema<E>>; | ||
export type RelationDefinitionMatcher<E extends EntityRawSchemaArray> = Partial<RelationDefinitionRawSchema<E>>; | ||
/** | ||
@@ -30,3 +30,3 @@ * Type representing a raw relation definition matched from a partial raw relation definition schema. | ||
*/ | ||
export declare type MatchedRelationDefinition<E extends EntityRawSchemaArray, R extends RelationDefinitionRawSchemaArray<EntityRawSchemaArray>, M extends RelationDefinitionMatcher<E>> = R[number] extends infer RDef ? (RDef extends M ? RDef : never) : never; | ||
export type MatchedRelationDefinition<E extends EntityRawSchemaArray, R extends RelationDefinitionRawSchemaArray<EntityRawSchemaArray>, M extends RelationDefinitionMatcher<E>> = R[number] extends infer RDef ? (RDef extends M ? RDef : never) : never; | ||
//# sourceMappingURL=Utils.d.ts.map |
/** | ||
* Base type used to describe a constraint. | ||
*/ | ||
declare type ConstraintBase<T extends string, V extends Record<string, unknown> | null> = { | ||
type ConstraintBase<T extends string, V extends Record<string, unknown> | null> = { | ||
type: T; | ||
@@ -11,11 +11,11 @@ value: V; | ||
*/ | ||
export declare type ConstraintOperator = ">" | ">=" | "<" | "<="; | ||
export type ConstraintOperator = ">" | ">=" | "<" | "<="; | ||
/** | ||
* THe type of a constraint message when one is present. | ||
*/ | ||
declare type ConstraintMessage = string | null; | ||
export declare type UniqueConstraint = ConstraintBase<"UniqueConstraint", { | ||
type ConstraintMessage = string | null; | ||
export type UniqueConstraint = ConstraintBase<"UniqueConstraint", { | ||
msg: ConstraintMessage; | ||
}>; | ||
export declare type SizeConstraint = ConstraintBase<"SizeConstraint", { | ||
export type SizeConstraint = ConstraintBase<"SizeConstraint", { | ||
min: number | null; | ||
@@ -25,3 +25,3 @@ max: number | null; | ||
}>; | ||
export declare type RegexpConstraint = ConstraintBase<"RegexpConstraint", { | ||
export type RegexpConstraint = ConstraintBase<"RegexpConstraint", { | ||
regexp: string; | ||
@@ -31,3 +31,3 @@ flags: number; | ||
}>; | ||
export declare type BoundaryConstraint = ConstraintBase<"BoundaryConstraint", { | ||
export type BoundaryConstraint = ConstraintBase<"BoundaryConstraint", { | ||
boundary: number | null; | ||
@@ -37,3 +37,3 @@ op: ConstraintOperator; | ||
}>; | ||
export declare type IntervalBoundConstraint = ConstraintBase<"IntervalBoundConstraint", { | ||
export type IntervalBoundConstraint = ConstraintBase<"IntervalBoundConstraint", { | ||
minvalue: number | null; | ||
@@ -43,15 +43,15 @@ maxvalue: number | null; | ||
}>; | ||
export declare type StaticVocabularyConstraint = ConstraintBase<"StaticVocabularyConstraint", { | ||
export type StaticVocabularyConstraint = ConstraintBase<"StaticVocabularyConstraint", { | ||
values: string[]; | ||
msg: ConstraintMessage; | ||
}>; | ||
export declare type FormatConstraint = ConstraintBase<"FormatConstraint", { | ||
export type FormatConstraint = ConstraintBase<"FormatConstraint", { | ||
values: ["text/rest", "text/markdown", "text/html", "text/plain"]; | ||
msg: ConstraintMessage; | ||
}>; | ||
export declare type RQLVocabularyConstraint = ConstraintBase<"RQLVocabularyConstraint", { | ||
export type RQLVocabularyConstraint = ConstraintBase<"RQLVocabularyConstraint", { | ||
expression: string; | ||
mainvars: string[]; | ||
}>; | ||
export declare type RQLConstraint = ConstraintBase<"RQLConstraint", { | ||
export type RQLConstraint = ConstraintBase<"RQLConstraint", { | ||
expression: string; | ||
@@ -64,8 +64,8 @@ mainvars: string[]; | ||
*/ | ||
export declare type AttributeConstraint = Readonly<UniqueConstraint | SizeConstraint | RegexpConstraint | BoundaryConstraint | IntervalBoundConstraint | StaticVocabularyConstraint | FormatConstraint | RQLConstraint>; | ||
export type AttributeConstraint = Readonly<UniqueConstraint | SizeConstraint | RegexpConstraint | BoundaryConstraint | IntervalBoundConstraint | StaticVocabularyConstraint | FormatConstraint | RQLConstraint>; | ||
/** | ||
* Type representing all possible constraints for relations. | ||
*/ | ||
export declare type RelationConstraint = Readonly<RQLVocabularyConstraint | RQLConstraint>; | ||
export type RelationConstraint = Readonly<RQLVocabularyConstraint | RQLConstraint>; | ||
export {}; | ||
//# sourceMappingURL=Constraints.d.ts.map |
/** | ||
* Type representing an entity schema. | ||
*/ | ||
export declare type EntityRawSchema = { | ||
export type EntityRawSchema = { | ||
type: string; | ||
@@ -12,3 +12,3 @@ final: boolean; | ||
*/ | ||
export declare type EntityRawSchemaArray = ReadonlyArray<EntityRawSchema>; | ||
export type EntityRawSchemaArray = ReadonlyArray<EntityRawSchema>; | ||
//# sourceMappingURL=Entities.d.ts.map |
@@ -6,7 +6,7 @@ import { AttributeConstraint, RelationConstraint } from "./Constraints"; | ||
*/ | ||
export declare type Cardinality = "*" | "1" | "?" | "+"; | ||
export type Cardinality = "*" | "1" | "?" | "+"; | ||
/** | ||
* Type representing a cardinality pair as used in relation definitions. | ||
*/ | ||
export declare type CardinalityPair = `${Cardinality}${Cardinality}`; | ||
export type CardinalityPair = `${Cardinality}${Cardinality}`; | ||
/** | ||
@@ -17,3 +17,3 @@ * Type used as a base to build final relation definitions with primitive types (Int, String, ...). | ||
*/ | ||
declare type BuildObjBase<T extends string> = { | ||
type BuildObjBase<T extends string> = { | ||
object: T; | ||
@@ -75,7 +75,7 @@ final: true; | ||
*/ | ||
export declare type BuildObj = Readonly<StringBuildObj | PasswordBuildObj | BytesBuildObj | IntBuildObj | BigIntBuildObj | FloatBuildObj | BooleanBuildObj | DecimalBuildObj | DateBuildObj | TimeBuildObj | DatetimeBuildObj | TZTimeBuildObj | TZDatetimeBuildObj | IntervalBuildObj | CustomBuildObj<string>>; | ||
export type BuildObj = Readonly<StringBuildObj | PasswordBuildObj | BytesBuildObj | IntBuildObj | BigIntBuildObj | FloatBuildObj | BooleanBuildObj | DecimalBuildObj | DateBuildObj | TimeBuildObj | DatetimeBuildObj | TZTimeBuildObj | TZDatetimeBuildObj | IntervalBuildObj | CustomBuildObj<string>>; | ||
/** | ||
* Type representing the possible options for an attribute. | ||
*/ | ||
export declare type AttributeOptions = { | ||
export type AttributeOptions = { | ||
indexed?: boolean; | ||
@@ -88,3 +88,3 @@ fulltextindexed?: boolean; | ||
*/ | ||
export declare type RelationOptions = { | ||
export type RelationOptions = { | ||
symmetric?: boolean; | ||
@@ -101,3 +101,3 @@ inlined?: boolean; | ||
*/ | ||
export declare type RelationDefinitionRawSchema<ESchemas extends EntityRawSchemaArray, Final extends boolean = boolean> = Readonly<{ | ||
export type RelationDefinitionRawSchema<ESchemas extends EntityRawSchemaArray, Final extends boolean = boolean> = Readonly<{ | ||
type: string; | ||
@@ -120,4 +120,4 @@ description: string; | ||
*/ | ||
export declare type RelationDefinitionRawSchemaArray<ESchemas extends EntityRawSchemaArray> = ReadonlyArray<RelationDefinitionRawSchema<ESchemas, boolean>>; | ||
export type RelationDefinitionRawSchemaArray<ESchemas extends EntityRawSchemaArray> = ReadonlyArray<RelationDefinitionRawSchema<ESchemas, boolean>>; | ||
export {}; | ||
//# sourceMappingURL=RelationDefinitions.d.ts.map |
@@ -9,3 +9,3 @@ import { EntityRawSchemaArray } from "./Entities"; | ||
*/ | ||
export declare type RawSchema<E extends EntityRawSchemaArray = EntityRawSchemaArray, R extends RelationDefinitionRawSchemaArray<E> = RelationDefinitionRawSchemaArray<E>> = { | ||
export type RawSchema<E extends EntityRawSchemaArray = EntityRawSchemaArray, R extends RelationDefinitionRawSchemaArray<E> = RelationDefinitionRawSchemaArray<E>> = { | ||
entities: E; | ||
@@ -12,0 +12,0 @@ relations_definitions: R; |
@@ -9,3 +9,3 @@ import { EntityRawSchemaArray } from "./Entities"; | ||
*/ | ||
export declare type IsLooseSchema<E extends EntityRawSchemaArray> = string extends E[number]["type"] ? true : false; | ||
export type IsLooseSchema<E extends EntityRawSchemaArray> = string extends E[number]["type"] ? true : false; | ||
/** | ||
@@ -15,3 +15,3 @@ * Checks if the given entity type is present in the EntityRawSchemaArray. | ||
*/ | ||
export declare type IsETypeInStrictSchema<E extends EntityRawSchemaArray, EType extends string> = EType extends E[number]["type"] ? true : false; | ||
export type IsETypeInStrictSchema<E extends EntityRawSchemaArray, EType extends string> = EType extends E[number]["type"] ? true : false; | ||
/** | ||
@@ -21,5 +21,5 @@ * Type representing the entity's raw schema matching this type. | ||
*/ | ||
export declare type EntityRawSchemaByType<E extends EntityRawSchemaArray, T extends string> = E[number] extends infer ESchema ? ESchema extends { | ||
export type EntityRawSchemaByType<E extends EntityRawSchemaArray, T extends string> = E[number] extends infer ESchema ? ESchema extends { | ||
type: T; | ||
} ? ESchema : never : never; | ||
//# sourceMappingURL=Utils.d.ts.map |
@@ -5,3 +5,3 @@ { | ||
"author": "Logilab", | ||
"version": "1.6.0", | ||
"version": "1.7.0", | ||
"license": "LGPL-3.0-or-later", | ||
@@ -29,5 +29,5 @@ "main": "lib/index.js", | ||
"devDependencies": { | ||
"typedoc": "^0.23.18", | ||
"typescript": "^4.8.4" | ||
"typedoc": "^0.23.24", | ||
"typescript": "^4.9.4" | ||
} | ||
} |
@@ -0,1 +1,2 @@ | ||
import { ValidationError } from "../Errors"; | ||
import { RawSchema } from "../schema/raw/Schema"; | ||
@@ -100,7 +101,11 @@ | ||
async execute(query: string, params: RQLParams): Promise<ResultSet> { | ||
return nonNullFetchApi<ResultSet>(this._rqlApiUrl, { | ||
method: "POST", | ||
body: JSON.stringify({ query, params }), | ||
credentials: "include", // FIXME is it secure? | ||
}); | ||
try { | ||
return await nonNullFetchApi<ResultSet>(this._rqlApiUrl, { | ||
method: "POST", | ||
body: JSON.stringify({ query, params }), | ||
credentials: "include", // FIXME is it secure? | ||
}); | ||
} catch (e) { | ||
this.handleUserErrors(e); | ||
} | ||
} | ||
@@ -128,12 +133,15 @@ | ||
async login(login: string, password: string): Promise<boolean> { | ||
return fetchApi<null>(this._loginApiUrl, { | ||
method: "POST", | ||
body: JSON.stringify({ | ||
login, | ||
password, | ||
}), | ||
credentials: "include", | ||
}) | ||
.then(() => true) | ||
.catch(() => false); | ||
try { | ||
await fetchApi<null>(this._loginApiUrl, { | ||
method: "POST", | ||
body: JSON.stringify({ | ||
login, | ||
password, | ||
}), | ||
credentials: "include", | ||
}); | ||
return true; | ||
} catch (_error) { | ||
return false; | ||
} | ||
} | ||
@@ -166,7 +174,11 @@ | ||
): Promise<ResultSet | null> { | ||
return fetchApi<ResultSet>(this._transactionApiUrl.execute, { | ||
method: "POST", | ||
body: JSON.stringify({ uuid, query, params }), | ||
credentials: "include", | ||
}); | ||
try { | ||
return await fetchApi<ResultSet>(this._transactionApiUrl.execute, { | ||
method: "POST", | ||
body: JSON.stringify({ uuid, query, params }), | ||
credentials: "include", | ||
}); | ||
} catch (e) { | ||
this.handleUserErrors(e); | ||
} | ||
} | ||
@@ -180,7 +192,11 @@ | ||
async transactionCommit(uuid: string): Promise<null> { | ||
return fetchApi<null>(this._transactionApiUrl.commit, { | ||
method: "POST", | ||
body: JSON.stringify({ uuid }), | ||
credentials: "include", | ||
}); | ||
try { | ||
return await fetchApi<null>(this._transactionApiUrl.commit, { | ||
method: "POST", | ||
body: JSON.stringify({ uuid }), | ||
credentials: "include", | ||
}); | ||
} catch (e) { | ||
this.handleUserErrors(e); | ||
} | ||
} | ||
@@ -200,2 +216,19 @@ | ||
} | ||
private handleUserErrors(error: unknown): never { | ||
if ( | ||
typeof error === "object" && | ||
error !== null && | ||
"title" in error && | ||
typeof error.title === "string" && | ||
"message" in error && | ||
typeof error.message === "string" | ||
) { | ||
if (error.title === "ValidationError") { | ||
throw new ValidationError(error.message); | ||
} | ||
throw error; | ||
} | ||
throw error; | ||
} | ||
} | ||
@@ -212,24 +245,17 @@ | ||
*/ | ||
const nonNullFetchApi = <R = unknown>( | ||
async function nonNullFetchApi<R = unknown>( | ||
input: RequestInfo, | ||
init?: RequestInit | ||
) => { | ||
return new Promise( | ||
(resolve: (value: R) => void, reject: (reason: ApiErrorResponse) => void) => | ||
fetchApi<R>(input, init) | ||
.then((v) => { | ||
if (v == null) { | ||
const error: ApiErrorResponse = { | ||
status: 500, | ||
title: "Unexpected null response", | ||
message: "Response was null but a value was expected", | ||
}; | ||
reject(error); | ||
} else { | ||
resolve(v); | ||
} | ||
}) | ||
.catch(reject) | ||
); | ||
}; | ||
) { | ||
const result = await fetchApi<R>(input, init); | ||
if (result == null) { | ||
const error: ApiErrorResponse = { | ||
status: 500, | ||
title: "Unexpected null response", | ||
message: "Response was null but a value was expected", | ||
}; | ||
throw error; | ||
} | ||
return result; | ||
} | ||
@@ -245,3 +271,6 @@ /** | ||
*/ | ||
const fetchApi = <R = unknown>(input: RequestInfo, init?: RequestInit) => { | ||
async function fetchApi<R = unknown>( | ||
input: RequestInfo, | ||
init?: RequestInit | ||
): Promise<R | null> { | ||
let headers = init?.headers; | ||
@@ -254,40 +283,28 @@ if (init?.method && init.method !== "GET" && init.method !== "DELETE") { | ||
} | ||
return new Promise( | ||
( | ||
resolve: (value: R | null) => void, | ||
reject: (reason: ApiErrorResponse) => void | ||
) => | ||
fetch(input, { | ||
...init, | ||
headers, | ||
}).then((response) => { | ||
const status = response.status; | ||
if (status >= 200 && status < 300) { | ||
if (status === 204) { | ||
resolve(null); | ||
} else { | ||
response | ||
.json() | ||
.then(resolve) | ||
.catch((e) => { | ||
console.error(e); | ||
resolve(null); | ||
}); | ||
} | ||
} else { | ||
response | ||
.json() | ||
.then((data: ApiError) => { | ||
reject({ | ||
status, | ||
...data, | ||
}); | ||
}) | ||
.catch((e) => { | ||
console.error(e); | ||
reject({ status, title: "Error", message: "" }); | ||
}); | ||
} | ||
}) | ||
); | ||
}; | ||
const response = await fetch(input, { | ||
...init, | ||
headers, | ||
}); | ||
const status = response.status; | ||
if (status >= 200 && status < 300) { | ||
if (status === 204) { | ||
return null; | ||
} | ||
try { | ||
return await response.json(); | ||
} catch (e) { | ||
console.error(e); | ||
return null; | ||
} | ||
} else { | ||
let json; | ||
try { | ||
json = await response.json(); | ||
} catch (e) { | ||
console.error(e); | ||
throw { status, title: "Error", message: "" }; | ||
} | ||
throw { status, ...json }; | ||
} | ||
} |
import { Schema } from "../schema/classes/Schema"; | ||
import Api, { RQLParams } from "./Api"; | ||
import Api, { RQLParams, ResultSet } from "./Api"; | ||
import Transaction from "./Transaction"; | ||
@@ -33,3 +33,3 @@ | ||
*/ | ||
async execute(query: string, params: RQLParams = {}) { | ||
async execute(query: string, params: RQLParams = {}): Promise<ResultSet> { | ||
return await this.api.execute(query, params); | ||
@@ -63,2 +63,4 @@ } | ||
* Once the callback's end is reached, the transaction is automatically committed. | ||
* Note that any exception thrown by the callback will lead to the | ||
* transaction being rolled back. | ||
* | ||
@@ -71,3 +73,12 @@ * @param callback Function to execute transaction requests in. | ||
await transaction.begin(); | ||
const result = await callback(transaction); | ||
let result: T; | ||
try { | ||
result = await callback(transaction); | ||
} catch (error) { | ||
if (!transaction.isClosed()) { | ||
await transaction.rollback(); | ||
} | ||
throw error; | ||
} | ||
if (!transaction.isClosed()) { | ||
@@ -74,0 +85,0 @@ await transaction.commit(); |
@@ -8,2 +8,9 @@ export class InconsistentSchemaError extends Error { | ||
export class ValidationError extends Error { | ||
constructor(message: string) { | ||
super(message); | ||
Object.setPrototypeOf(this, new.target.prototype); | ||
} | ||
} | ||
export class TransactionClosedError extends Error { | ||
@@ -10,0 +17,0 @@ constructor() { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
133824
2717