New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@badrap/libapp

Package Overview
Dependencies
Maintainers
2
Versions
47
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@badrap/libapp - npm Package Compare versions

Comparing version 0.1.5 to 0.1.6

dist/api/base.d.ts

16

dist/api/index.d.ts
import * as v from "@badrap/valita";
export declare class HTTPError extends Error {
readonly statusCode: number;
readonly statusText: string;
constructor(statusCode: number, statusText: string);
}
import { HTTPError } from "./base.js";
import { Kv } from "./kv.js";
export { HTTPError };
export declare class UpdateFailed extends Error {

@@ -28,8 +26,7 @@ constructor();

export declare class API<InstallationState extends Record<string, unknown> = Record<string, unknown>> {
private readonly apiToken;
private readonly baseUrl;
private readonly base;
private readonly stateType;
readonly experimentalKv: Kv;
constructor(apiUrl: string, apiToken: string, stateType?: v.Type<InstallationState>);
private installationUrl;
private request;
private installationPath;
checkAuthToken(token: string): Promise<{

@@ -76,2 +73,1 @@ installationId: string;

}
export {};

@@ -25,22 +25,11 @@ "use strict";

};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.API = exports.UpdateFailed = exports.HTTPError = void 0;
const node_path_1 = __importDefault(require("node:path"));
const v = __importStar(require("@badrap/valita"));
const undici_1 = require("undici");
const base_js_1 = require("./base.js");
Object.defineProperty(exports, "HTTPError", { enumerable: true, get: function () { return base_js_1.HTTPError; } });
const kv_js_1 = require("./kv.js");
function parse(data, type) {
return type.parse(data, { mode: "strip" });
}
class HTTPError extends Error {
constructor(statusCode, statusText) {
super(`HTTP status code ${statusCode} (${statusText})`);
this.statusCode = statusCode;
this.statusText = statusText;
Object.setPrototypeOf(this, new.target.prototype);
}
}
exports.HTTPError = HTTPError;
class UpdateFailed extends Error {

@@ -55,29 +44,19 @@ constructor() {

constructor(apiUrl, apiToken, stateType) {
this.base = new base_js_1.APIBase(apiUrl, apiToken);
this.stateType = stateType !== null && stateType !== void 0 ? stateType : v.record();
this.apiToken = apiToken;
this.baseUrl = new URL(apiUrl);
this.baseUrl.pathname = node_path_1.default.posix.join(this.baseUrl.pathname, "app/");
this.experimentalKv = new kv_js_1.Kv(this.base);
}
installationUrl(installationId, path) {
installationPath(installationId, path) {
if (!installationId.match(/^[a-z0-9_-]{1,}$/i)) {
throw new Error("invalid installation ID");
}
const url = new URL(`installations/${installationId}`, this.baseUrl);
let pathname = `installations/${installationId}`;
if (path) {
url.pathname += `/${path}`;
pathname += `/${path}`;
}
url.pathname = url.pathname.replace(/\/+/g, "/");
return url;
return pathname.replace(/\/+/g, "/");
}
async request(url, options) {
const headers = new undici_1.Headers(options.headers);
headers.set("Authorization", `Bearer ${this.apiToken}`);
const response = await (0, undici_1.fetch)(url, { ...options, headers });
if (!response.ok) {
throw new HTTPError(response.status, response.statusText);
}
return response;
}
async checkAuthToken(token) {
const result = await this.request(new URL("token", this.baseUrl), {
const result = await this.base
.request("/token", {
method: "POST",

@@ -90,3 +69,4 @@ headers: {

}),
}).then((r) => r.json());
})
.then((r) => r.json());
const { installation_id: installationId, session_id: sessionId, expires_at: expiresAt, } = parse(result, v.object({

@@ -100,3 +80,4 @@ installation_id: v.string(),

async seal(data, expiresIn) {
const result = await this.request(new URL("seal", this.baseUrl), {
const result = await this.base
.request("/seal", {
method: "POST",

@@ -110,7 +91,9 @@ headers: {

}),
}).then((r) => r.json());
})
.then((r) => r.json());
return parse(result, v.object({ data: v.string() }).map((r) => r.data));
}
async unseal(data) {
const result = await this.request(new URL("unseal", this.baseUrl), {
const result = await this.base
.request("/unseal", {
method: "POST",

@@ -123,9 +106,9 @@ headers: {

}),
}).then((r) => r.json());
})
.then((r) => r.json());
return parse(result, v.object({ data: v.unknown() }).map((r) => r.data));
}
async getInstallations() {
return this.request(new URL("installations", this.baseUrl), {
method: "GET",
})
return this.base
.request("/installations", { method: "GET" })
.then((r) => r.json())

@@ -141,3 +124,4 @@ .then((r) => parse(r, v.array(v.object({

async createInstallationCallback(installationId, sessionId, callback = {}) {
return this.request(this.installationUrl(installationId, "/callbacks"), {
return this.base
.request(this.installationPath(installationId, "/callbacks"), {
method: "POST",

@@ -157,3 +141,4 @@ headers: {

async getInstallation(installationId) {
return this.request(this.installationUrl(installationId), {
return this.base
.request(this.installationPath(installationId), {
method: "GET",

@@ -169,5 +154,5 @@ })

const { maxRetries = Infinity } = options !== null && options !== void 0 ? options : {};
const url = this.installationUrl(installationId);
const path = this.installationPath(installationId);
for (let i = 0; i <= maxRetries; i++) {
const response = await this.request(url, { method: "GET" });
const response = await this.base.request(path, { method: "GET" });
const etag = response.headers.get("etag");

@@ -187,3 +172,3 @@ const input = await response.json().then((r) => parse(r, v.object({

try {
await this.request(url, {
await this.base.request(path, {
method: "PATCH",

@@ -198,3 +183,3 @@ headers: {

catch (err) {
if (err instanceof HTTPError && err.statusCode === 412) {
if (err instanceof base_js_1.HTTPError && err.statusCode === 412) {
continue;

@@ -209,8 +194,9 @@ }

async removeInstallation(installationId) {
await this.request(this.installationUrl(installationId), {
method: "DELETE",
}).then((r) => r.arrayBuffer());
await this.base
.request(this.installationPath(installationId), { method: "DELETE" })
.then((r) => r.arrayBuffer());
}
async listOwnerAssets(installationId) {
return this.request(this.installationUrl(installationId, "/owner/assets"), {
return this.base
.request(this.installationPath(installationId, "/owner/assets"), {
method: "GET",

@@ -226,3 +212,3 @@ })

try {
await this.request(new URL("feeds", this.baseUrl), {
await this.base.request("/feeds", {
method: "POST",

@@ -241,6 +227,6 @@ headers: {

catch (err) {
if (!(err instanceof HTTPError) || err.statusCode !== 409) {
if (!(err instanceof base_js_1.HTTPError) || err.statusCode !== 409) {
throw err;
}
await this.request(new URL(`feeds/${encodeURIComponent(name)}`, this.baseUrl), {
await this.base.request(`/feeds/${encodeURIComponent(name)}`, {
method: "PATCH",

@@ -260,3 +246,3 @@ headers: {

async feedEventsForInstallation(installationId, feedName, events) {
await this.request(this.installationUrl(installationId, `/feeds/${encodeURIComponent(feedName)}/events`), {
await this.base.request(this.installationPath(installationId, `/feeds/${encodeURIComponent(feedName)}/events`), {
method: "POST",

@@ -263,0 +249,0 @@ headers: {

{
"name": "@badrap/libapp",
"version": "0.1.5",
"version": "0.1.6",
"description": "TypeScript helpers for creating Badrap apps",

@@ -43,8 +43,8 @@ "repository": {

"prettier": "^2.8.4",
"typescript": "^4.9.5"
"typescript": "^5.1.6"
},
"dependencies": {
"@badrap/valita": "^0.2.0",
"undici": "^5.20.0"
"@badrap/valita": "^0.2.1",
"undici": "^5.22.1"
}
}

@@ -1,5 +0,7 @@

import path from "node:path";
import * as v from "@badrap/valita";
import { fetch, RequestInit, Headers, Response } from "undici";
import { HTTPError, APIBase } from "./base.js";
import { Kv } from "./kv.js";
export { HTTPError };
function parse<T>(data: unknown, type: v.Type<T>): T {

@@ -9,9 +11,2 @@ return type.parse(data, { mode: "strip" });

export class HTTPError extends Error {
constructor(readonly statusCode: number, readonly statusText: string) {
super(`HTTP status code ${statusCode} (${statusText})`);
Object.setPrototypeOf(this, new.target.prototype);
}
}
export class UpdateFailed extends Error {

@@ -48,5 +43,5 @@ constructor() {

> {
private readonly apiToken: string;
private readonly baseUrl: URL;
private readonly base: APIBase;
private readonly stateType: v.Type<InstallationState>;
readonly experimentalKv: Kv;

@@ -58,43 +53,32 @@ constructor(

) {
this.base = new APIBase(apiUrl, apiToken);
this.stateType = stateType ?? (v.record() as v.Type<InstallationState>);
this.apiToken = apiToken;
this.baseUrl = new URL(apiUrl);
this.baseUrl.pathname = path.posix.join(this.baseUrl.pathname, "app/");
this.experimentalKv = new Kv(this.base);
}
private installationUrl(installationId: string, path?: string): URL {
private installationPath(installationId: string, path?: string): string {
if (!installationId.match(/^[a-z0-9_-]{1,}$/i)) {
throw new Error("invalid installation ID");
}
const url = new URL(`installations/${installationId}`, this.baseUrl);
let pathname = `installations/${installationId}`;
if (path) {
url.pathname += `/${path}`;
pathname += `/${path}`;
}
url.pathname = url.pathname.replace(/\/+/g, "/");
return url;
return pathname.replace(/\/+/g, "/");
}
private async request(url: URL, options: RequestInit): Promise<Response> {
const headers = new Headers(options.headers);
headers.set("Authorization", `Bearer ${this.apiToken}`);
const response = await fetch(url, { ...options, headers });
if (!response.ok) {
throw new HTTPError(response.status, response.statusText);
}
return response;
}
async checkAuthToken(
token: string
): Promise<{ installationId: string; sessionId: string; expiresAt: number }> {
const result = await this.request(new URL("token", this.baseUrl), {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
token,
}),
}).then((r) => r.json());
const result = await this.base
.request("/token", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
token,
}),
})
.then((r) => r.json());

@@ -118,12 +102,14 @@ const {

async seal(data: unknown, expiresIn: number): Promise<string> {
const result = await this.request(new URL("seal", this.baseUrl), {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
expires_in: expiresIn,
data,
}),
}).then((r) => r.json());
const result = await this.base
.request("/seal", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
expires_in: expiresIn,
data,
}),
})
.then((r) => r.json());

@@ -137,11 +123,13 @@ return parse(

async unseal(data: string): Promise<unknown> {
const result = await this.request(new URL("unseal", this.baseUrl), {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
data,
}),
}).then((r) => r.json());
const result = await this.base
.request("/unseal", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
data,
}),
})
.then((r) => r.json());

@@ -161,5 +149,4 @@ return parse(

> {
return this.request(new URL("installations", this.baseUrl), {
method: "GET",
})
return this.base
.request("/installations", { method: "GET" })
.then((r) => r.json())

@@ -193,13 +180,14 @@ .then((r) =>

): Promise<string> {
return this.request(this.installationUrl(installationId, "/callbacks"), {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
session_id: sessionId,
action: callback.action,
client_state: callback.clientState,
}),
})
return this.base
.request(this.installationPath(installationId, "/callbacks"), {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
session_id: sessionId,
action: callback.action,
client_state: callback.clientState,
}),
})
.then((r) => r.json())

@@ -217,5 +205,6 @@ .then((r) =>

): Promise<Installation<InstallationState>> {
return this.request(this.installationUrl(installationId), {
method: "GET",
})
return this.base
.request(this.installationPath(installationId), {
method: "GET",
})
.then((r) => r.json())

@@ -245,6 +234,6 @@ .then((r) =>

const url = this.installationUrl(installationId);
const path = this.installationPath(installationId);
for (let i = 0; i <= maxRetries; i++) {
const response = await this.request(url, { method: "GET" });
const response = await this.base.request(path, { method: "GET" });
const etag = response.headers.get("etag");

@@ -271,3 +260,3 @@ const input = await response.json().then((r) =>

try {
await this.request(url, {
await this.base.request(path, {
method: "PATCH",

@@ -293,5 +282,5 @@ headers: {

async removeInstallation(installationId: string): Promise<void> {
await this.request(this.installationUrl(installationId), {
method: "DELETE",
}).then((r) => r.arrayBuffer());
await this.base
.request(this.installationPath(installationId), { method: "DELETE" })
.then((r) => r.arrayBuffer());
}

@@ -302,5 +291,6 @@

): Promise<{ type: "ip" | "email" | "domain"; value: string }[]> {
return this.request(this.installationUrl(installationId, "/owner/assets"), {
method: "GET",
})
return this.base
.request(this.installationPath(installationId, "/owner/assets"), {
method: "GET",
})
.then((r) => r.json())

@@ -333,3 +323,3 @@ .then((r) =>

try {
await this.request(new URL("feeds", this.baseUrl), {
await this.base.request("/feeds", {
method: "POST",

@@ -350,17 +340,14 @@ headers: {

}
await this.request(
new URL(`feeds/${encodeURIComponent(name)}`, this.baseUrl),
{
method: "PATCH",
headers: {
"Content-Type": "application/json",
"If-Match": "*",
},
body: JSON.stringify({
title: config?.title,
summary_template: config?.summaryTemplate,
details_template: config?.detailsTemplate,
}),
}
);
await this.base.request(`/feeds/${encodeURIComponent(name)}`, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
"If-Match": "*",
},
body: JSON.stringify({
title: config?.title,
summary_template: config?.summaryTemplate,
details_template: config?.detailsTemplate,
}),
});
}

@@ -374,4 +361,4 @@ }

): Promise<void> {
await this.request(
this.installationUrl(
await this.base.request(
this.installationPath(
installationId,

@@ -378,0 +365,0 @@ `/feeds/${encodeURIComponent(feedName)}/events`

@@ -13,5 +13,6 @@ {

"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true
"noFallthroughCasesInSwitch": true,
"noUncheckedIndexedAccess": true
},
"include": ["./src/**/*"]
}

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc