@formbricks/api
Version:
Formbricks-api is an api wrapper for the Formbricks client API
223 lines (222 loc) • 6.9 kB
JavaScript
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