@teknologi-umum/pesto
Version:
JavaScript SDK for Pesto
244 lines (236 loc) • 9.34 kB
JavaScript
import fetch from 'node-fetch';
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
// Copyright 2022-2023 Teknologi Umum and contributors
// Licensed 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
//
// https://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.
/**
* Some parameters are missing on the HTTP request or the request body is empty.
*/
class MissingParameterError extends Error {
constructor(message) {
super(message);
this.message = message;
}
}
/**
* Token was empty during Client creation.
*/
class EmptyTokenError extends Error {
constructor() {
super("Empty token");
}
}
/**
* Token was not sent during the HTTP request.
*/
class MissingTokenError extends Error {
constructor() {
super("missing token");
}
}
/**
* Unauthorized request with unknown reason
*/
class UnauthorizedError extends Error {
constructor() {
super("unauthorized for unknown reason");
}
}
/**
* An error occurred on Pesto's server. Client should retry the request after a few seconds.
*
* If the error persist, please contact the Pesto team.
*/
class InternalServerError extends Error {
constructor(message) {
super(message);
this.message = message;
}
}
/**
* Given Client token was not registered on Pesto's API.
*/
class TokenNotRegisteredError extends Error {
constructor() {
super("Token not registered");
}
}
/**
* Provided token is already revoked on Pesto's API.
*/
class TokenRevokedError extends Error {
constructor() {
super("Token revoked");
}
}
/**
* The token exceeds the monthly quota limit defined by the Pesto's API.
*
* To increase your limit, please contact the Pesto team.
*/
class MonthlyLimitExceededError extends Error {
constructor() {
super("Monthly limit exceeded");
}
}
/**
* Client got rate limited by the API for sending burst or too many concurrent requests to Pesto's API.
*
* To get around this, you can implement your own semaphore to handle parallel requests.
* To learn more about semaphore, you can see this Wikipedia article:
* https://en.wikipedia.org/wiki/Semaphore_(programming)
*/
class ServerRateLimitedError extends Error {
constructor() {
super("Server rate limited");
}
}
/**
* Provided language-version combination does not exists on Pesto's API.
*/
class RuntimeNotFoundError extends Error {
constructor(language, version) {
const combination = language !== undefined && version !== undefined ? ` of ${language} and ${version}` : "";
super(`Provided language-version combination${combination} does not exists on Pesto's API`);
}
}
// Copyright 2022-2023 Teknologi Umum and contributors
class PestoClient {
constructor(config) {
var _a;
if (config.token === undefined || config.token === null || config.token === "") {
throw new EmptyTokenError();
}
this.token = config.token;
this.baseURL = (_a = config.baseURL) !== null && _a !== void 0 ? _a : new URL("https://pesto.teknologiumum.com");
}
static fromToken(token) {
return new PestoClient({ token: token });
}
ping(abortSignal) {
return __awaiter(this, void 0, void 0, function* () {
const response = yield fetch(new URL("/api/ping", this.baseURL).toString(), {
signal: abortSignal,
headers: {
"X-Pesto-Token": this.token,
Accept: "application/json"
},
method: "GET"
});
if (response.status !== 200) {
throw yield this.processError(response);
}
const body = (yield response.json());
return { message: body.message };
});
}
listRuntimes(abortSignal) {
return __awaiter(this, void 0, void 0, function* () {
const response = yield fetch(new URL("/api/list-runtimes", this.baseURL).toString(), {
signal: abortSignal,
headers: {
"X-Pesto-Token": this.token,
Accept: "application/json"
},
method: "GET"
});
if (response.status !== 200) {
throw yield this.processError(response);
}
const body = (yield response.json());
return { runtime: body.runtime };
});
}
execute(codeRequest, abortSignal) {
return __awaiter(this, void 0, void 0, function* () {
const response = yield fetch(new URL("/api/execute", this.baseURL).toString(), {
signal: abortSignal,
headers: {
"X-Pesto-Token": this.token,
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify(codeRequest),
method: "POST"
});
if (response.status !== 200) {
yield this.processError(response);
}
const body = (yield response.json());
return {
language: body.language,
version: body.version,
runtime: body.runtime,
compile: body.compile
};
});
}
processError(response) {
return __awaiter(this, void 0, void 0, function* () {
switch (response.status) {
case 404:
throw new Error("api path not found");
case 500: {
const body = (yield response.json());
throw new InternalServerError(body.message);
}
case 401: {
const body = (yield response.json());
if (body.message === "Token must be supplied")
throw new MissingTokenError();
if (body.message === "Token not registered")
throw new TokenNotRegisteredError();
if (body.message === "Token has been revoked")
throw new TokenRevokedError();
throw new UnauthorizedError();
}
case 429: {
const body = (yield response.json());
if ((body === null || body === void 0 ? void 0 : body.message) === "Monthly limit exceeded")
throw new MonthlyLimitExceededError();
throw new ServerRateLimitedError();
}
case 400: {
const body = (yield response.json());
if ((body === null || body === void 0 ? void 0 : body.message) === "Runtime not found")
throw new RuntimeNotFoundError();
if (body === null || body === void 0 ? void 0 : body.message.startsWith("Missing parameters"))
throw new MissingParameterError(body.message);
throw new Error(`${body.message} (this is probably a problem with the SDK, please submit an issue on our Github repository)`);
}
}
const body = yield response.text();
throw new Error(`Received ${response.status} with body ${body} (this is probably a problem with the SDK, please submit an issue on our Github repository)`);
});
}
}
export { PestoClient };