UNPKG

@formbricks/api

Version:

Formbricks-api is an api wrapper for the Formbricks client API

223 lines (222 loc) 6.9 kB
var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); const ok = (data) => ({ ok: true, data }); const err = (error) => ({ ok: false, error }); const wrapThrowsAsync = (fn) => async (...args) => { try { return { ok: true, data: await fn(...args) }; } catch (error) { return { ok: false, error }; } }; const makeRequest = async (apiHost, endpoint, method, data) => { const url = new URL(apiHost + endpoint); const body = data ? JSON.stringify(data) : void 0; const res = await wrapThrowsAsync(fetch)(url.toString(), { method, headers: { "Content-Type": "application/json" }, body }); if (!res.ok) return err(res.error); const response = res.data; const json = await response.json(); if (!response.ok) { const errorResponse = json; return err({ code: errorResponse.code === "forbidden" ? "forbidden" : "network_error", status: response.status, message: errorResponse.message || "Something went wrong", url, ...Object.keys(errorResponse.details).length > 0 && { details: errorResponse.details } }); } const successResponse = json; return ok(successResponse.data); }; class AttributeAPI { constructor(apiHost, environmentId) { __publicField(this, "apiHost"); __publicField(this, "environmentId"); this.apiHost = apiHost; this.environmentId = environmentId; } async update(attributeUpdateInput) { const attributes = {}; for (const key in attributeUpdateInput.attributes) { attributes[key] = String(attributeUpdateInput.attributes[key]); } return makeRequest( this.apiHost, `/api/v1/client/${this.environmentId}/contacts/${attributeUpdateInput.userId}/attributes`, "PUT", { attributes } ); } } class DisplayAPI { constructor(baseUrl, environmentId) { __publicField(this, "apiHost"); __publicField(this, "environmentId"); this.apiHost = baseUrl; this.environmentId = environmentId; } async create(displayInput) { return makeRequest(this.apiHost, `/api/v1/client/${this.environmentId}/displays`, "POST", displayInput); } } class ResponseAPI { constructor(apiHost, environmentId) { __publicField(this, "apiHost"); __publicField(this, "environmentId"); this.apiHost = apiHost; this.environmentId = environmentId; } async create(responseInput) { return makeRequest(this.apiHost, `/api/v1/client/${this.environmentId}/responses`, "POST", responseInput); } async update({ responseId, finished, endingId, data, ttc, variables, language }) { return makeRequest(this.apiHost, `/api/v1/client/${this.environmentId}/responses/${responseId}`, "PUT", { finished, endingId, data, ttc, variables, language }); } } class StorageAPI { constructor(apiHost, environmentId) { __publicField(this, "apiHost"); __publicField(this, "environmentId"); this.apiHost = apiHost; this.environmentId = environmentId; } async uploadFile(file, { allowedFileExtensions, surveyId } = {}) { if (!file.name || !file.type || !file.base64) { throw new Error(`Invalid file object`); } const payload = { fileName: file.name, fileType: file.type, allowedFileExtensions, surveyId }; const response = await fetch(`${this.apiHost}/api/v1/client/${this.environmentId}/storage`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload) }); if (!response.ok) { throw new Error(`Upload failed with status: ${String(response.status)}`); } const json = await response.json(); const { data } = json; const { signedUrl, fileUrl, signingData, presignedFields, updatedFileName } = data; let requestHeaders = {}; if (signingData) { const { signature, timestamp, uuid } = signingData; requestHeaders = { "X-File-Type": file.type, "X-File-Name": encodeURIComponent(updatedFileName), "X-Survey-ID": surveyId ?? "", "X-Signature": signature, "X-Timestamp": String(timestamp), "X-UUID": uuid }; } const formData = {}; const formDataForS3 = new FormData(); if (presignedFields) { Object.entries(presignedFields).forEach(([key, value]) => { formDataForS3.append(key, value); }); try { const binaryString = atob(file.base64.split(",")[1]); const uint8Array = Uint8Array.from([...binaryString].map((char) => char.charCodeAt(0))); const blob = new Blob([uint8Array], { type: file.type }); formDataForS3.append("file", blob); } catch (err2) { console.error(err2); throw new Error("Error uploading file"); } } formData.fileBase64String = file.base64; let uploadResponse = {}; const signedUrlCopy = signedUrl.replace("http://localhost:3000", this.apiHost); try { uploadResponse = await fetch(signedUrlCopy, { method: "POST", ...signingData ? { headers: { ...requestHeaders } } : {}, body: presignedFields ? formDataForS3 : JSON.stringify(formData) }); } catch (err2) { console.error("Error uploading file", err2); } if (!uploadResponse.ok) { if (signingData) { const uploadJson = await uploadResponse.json(); const error = new Error(uploadJson.message); error.name = "FileTooLargeError"; throw error; } const errorText = await uploadResponse.text(); if (presignedFields && errorText.includes("EntityTooLarge")) { const error = new Error("File size exceeds the size limit for your plan"); error.name = "FileTooLargeError"; throw error; } throw new Error(`Upload failed with status: ${String(uploadResponse.status)}`); } return fileUrl; } } class Client { constructor(options) { __publicField(this, "response"); __publicField(this, "display"); __publicField(this, "storage"); __publicField(this, "attribute"); const { apiHost, environmentId } = options; this.response = new ResponseAPI(apiHost, environmentId); this.display = new DisplayAPI(apiHost, environmentId); this.attribute = new AttributeAPI(apiHost, environmentId); this.storage = new StorageAPI(apiHost, environmentId); } } class FormbricksAPI { constructor(options) { __publicField(this, "client"); this.client = new Client(options); } } export { FormbricksAPI }; //# sourceMappingURL=index.js.map