Add more work on API refactor in builder
This commit is contained in:
parent
bab0bc4266
commit
1f22b4ecfe
|
@ -14,16 +14,25 @@ export const API = createAPIClient({
|
|||
},
|
||||
|
||||
onError: error => {
|
||||
const { url, message, status } = error
|
||||
const { url, message, status, method, handled } = error || {}
|
||||
|
||||
// Log all API errors to Sentry
|
||||
// analytics.captureException(error)
|
||||
|
||||
// Log any errors that we haven't manually handled
|
||||
if (!handled) {
|
||||
console.error("Unhandled error from API client", error)
|
||||
return
|
||||
}
|
||||
|
||||
// Show a notification for any errors
|
||||
if (message) {
|
||||
notifications.error(`Error fetching ${url}: ${message}`)
|
||||
}
|
||||
|
||||
// Log all errors to console
|
||||
console.error(`HTTP ${status} on ${method}:${url}:\n\t${message}`)
|
||||
|
||||
// Logout on 403's
|
||||
if (status === 403) {
|
||||
// Don't do anything if fetching templates.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import { Dropzone, notifications } from "@budibase/bbui"
|
||||
import api from "builderStore/api"
|
||||
import { API } from "api"
|
||||
|
||||
export let value = []
|
||||
export let label
|
||||
|
@ -20,8 +20,12 @@
|
|||
for (let i = 0; i < fileList.length; i++) {
|
||||
data.append("file", fileList[i])
|
||||
}
|
||||
const response = await api.post(`/api/attachments/process`, data, {})
|
||||
return await response.json()
|
||||
try {
|
||||
return await API.uploadBuilderAttachment(data)
|
||||
} catch (error) {
|
||||
notifications.error("Failed to upload attachment")
|
||||
return []
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
async function deployApp() {
|
||||
try {
|
||||
await API.deployApp()
|
||||
await API.deployAppChanges()
|
||||
analytics.captureEvent(Events.APP.PUBLISHED, {
|
||||
appId: $store.appId,
|
||||
})
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
const revert = async () => {
|
||||
try {
|
||||
await API.revertApp(appId)
|
||||
await API.revertAppChanges(appId)
|
||||
|
||||
// Reset frontend state after revert
|
||||
const applicationPkg = await API.fetchAppPackage(appId)
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
Button,
|
||||
} from "@budibase/bbui"
|
||||
import { store } from "builderStore"
|
||||
import api from "builderStore/api"
|
||||
import { API } from "api"
|
||||
import clientPackage from "@budibase/client/package.json"
|
||||
|
||||
let updateModal
|
||||
|
@ -18,26 +18,17 @@
|
|||
$: revertAvailable = $store.revertableVersion != null
|
||||
|
||||
const refreshAppPackage = async () => {
|
||||
const applicationPkg = await api.get(
|
||||
`/api/applications/${appId}/appPackage`
|
||||
)
|
||||
const pkg = await applicationPkg.json()
|
||||
if (applicationPkg.ok) {
|
||||
try {
|
||||
const pkg = await API.fetchAppPackage(appId)
|
||||
await store.actions.initialise(pkg)
|
||||
} else {
|
||||
throw new Error(pkg)
|
||||
} catch (error) {
|
||||
notifications.error("Error fetching app package")
|
||||
}
|
||||
}
|
||||
|
||||
const update = async () => {
|
||||
try {
|
||||
const response = await api.post(
|
||||
`/api/applications/${appId}/client/update`
|
||||
)
|
||||
const json = await response.json()
|
||||
if (response.status !== 200) {
|
||||
throw json.message
|
||||
}
|
||||
await API.updateAppClientVersion(appId)
|
||||
|
||||
// Don't wait for the async refresh, since this causes modal flashing
|
||||
refreshAppPackage()
|
||||
|
@ -47,23 +38,17 @@
|
|||
} catch (err) {
|
||||
notifications.error(`Error updating app: ${err}`)
|
||||
}
|
||||
updateModal.hide()
|
||||
}
|
||||
|
||||
const revert = async () => {
|
||||
try {
|
||||
const revertableVersion = $store.revertableVersion
|
||||
const response = await api.post(
|
||||
`/api/applications/${appId}/client/revert`
|
||||
)
|
||||
const json = await response.json()
|
||||
if (response.status !== 200) {
|
||||
throw json.message
|
||||
}
|
||||
await API.revertAppClientVersion(appId)
|
||||
|
||||
// Don't wait for the async refresh, since this causes modal flashing
|
||||
refreshAppPackage()
|
||||
notifications.success(
|
||||
`App reverted successfully to version ${revertableVersion}`
|
||||
`App reverted successfully to version ${$store.revertableVersion}`
|
||||
)
|
||||
} catch (err) {
|
||||
notifications.error(`Error reverting app: ${err}`)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
import { store, automationStore, hostingStore } from "builderStore"
|
||||
import { admin, auth } from "stores/portal"
|
||||
import { string, mixed, object } from "yup"
|
||||
import api, { get, post } from "builderStore/api"
|
||||
import { API } from "api"
|
||||
import analytics, { Events } from "analytics"
|
||||
import { onMount } from "svelte"
|
||||
import { capitalise } from "helpers"
|
||||
|
@ -99,40 +99,24 @@
|
|||
}
|
||||
|
||||
// Create App
|
||||
const appResp = await post("/api/applications", data, {})
|
||||
const appJson = await appResp.json()
|
||||
if (!appResp.ok) {
|
||||
throw new Error(appJson.message)
|
||||
}
|
||||
|
||||
const createdApp = await API.createApp(data)
|
||||
analytics.captureEvent(Events.APP.CREATED, {
|
||||
name: $values.name,
|
||||
appId: appJson.instance._id,
|
||||
appId: createdApp.instance._id,
|
||||
templateToUse,
|
||||
})
|
||||
|
||||
// Select Correct Application/DB in prep for creating user
|
||||
const applicationPkg = await get(
|
||||
`/api/applications/${appJson.instance._id}/appPackage`
|
||||
)
|
||||
const pkg = await applicationPkg.json()
|
||||
if (applicationPkg.ok) {
|
||||
await store.actions.initialise(pkg)
|
||||
await automationStore.actions.fetch()
|
||||
// update checklist - incase first app
|
||||
await admin.init()
|
||||
} else {
|
||||
throw new Error(pkg)
|
||||
}
|
||||
const pkg = await API.fetchAppPackage(createdApp.instance._id)
|
||||
await store.actions.initialise(pkg)
|
||||
await automationStore.actions.fetch()
|
||||
// Update checklist - in case first app
|
||||
await admin.init()
|
||||
|
||||
// Create user
|
||||
const user = {
|
||||
roleId: $values.roleId,
|
||||
}
|
||||
const userResp = await api.post(`/api/users/metadata/self`, user)
|
||||
await userResp.json()
|
||||
await API.updateOwnMetadata({ roleId: $values.roleId })
|
||||
await auth.setInitInfo({})
|
||||
$goto(`/builder/app/${appJson.instance._id}`)
|
||||
$goto(`/builder/app/${createdApp.instance._id}`)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
notifications.error(error)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import { notifications, ModalContent, Dropzone, Body } from "@budibase/bbui"
|
||||
import { post } from "builderStore/api"
|
||||
import { API } from "api"
|
||||
import { admin } from "stores/portal"
|
||||
|
||||
let submitting = false
|
||||
|
@ -9,24 +9,19 @@
|
|||
|
||||
async function importApps() {
|
||||
submitting = true
|
||||
|
||||
try {
|
||||
// Create form data to create app
|
||||
let data = new FormData()
|
||||
data.append("importFile", value.file)
|
||||
|
||||
// Create App
|
||||
const importResp = await post("/api/cloud/import", data, {})
|
||||
const importJson = await importResp.json()
|
||||
if (!importResp.ok) {
|
||||
throw new Error(importJson.message)
|
||||
}
|
||||
await API.importApps(data)
|
||||
await admin.checkImportComplete()
|
||||
notifications.success("Import complete, please finish registration!")
|
||||
} catch (error) {
|
||||
notifications.error(error)
|
||||
submitting = false
|
||||
notifications.error("Failed to import apps")
|
||||
}
|
||||
submitting = false
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -36,10 +31,10 @@
|
|||
onConfirm={importApps}
|
||||
disabled={!value.file}
|
||||
>
|
||||
<Body
|
||||
>Please upload the file that was exported from your Cloud environment to get
|
||||
started</Body
|
||||
>
|
||||
<Body>
|
||||
Please upload the file that was exported from your Cloud environment to get
|
||||
started
|
||||
</Body>
|
||||
<Dropzone
|
||||
gallery={false}
|
||||
label="File to import"
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
Modal,
|
||||
} from "@budibase/bbui"
|
||||
import { goto } from "@roxi/routify"
|
||||
import api from "builderStore/api"
|
||||
import { API } from "api"
|
||||
import { admin, auth } from "stores/portal"
|
||||
import PasswordRepeatInput from "components/common/users/PasswordRepeatInput.svelte"
|
||||
import ImportAppsModal from "./_components/ImportAppsModal.svelte"
|
||||
|
@ -30,11 +30,7 @@
|
|||
try {
|
||||
adminUser.tenantId = tenantId
|
||||
// Save the admin user
|
||||
const response = await api.post(`/api/global/users/init`, adminUser)
|
||||
const json = await response.json()
|
||||
if (response.status !== 200) {
|
||||
throw new Error(json.message)
|
||||
}
|
||||
await API.createAdminUser(adminUser)
|
||||
notifications.success(`Admin user created`)
|
||||
await admin.init()
|
||||
$goto("../portal")
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
import ChooseIconModal from "components/start/ChooseIconModal.svelte"
|
||||
|
||||
import { store, automationStore } from "builderStore"
|
||||
import api, { del, post, get } from "builderStore/api"
|
||||
import { API } from "api"
|
||||
import { onMount } from "svelte"
|
||||
import { apps, auth, admin, templates } from "stores/portal"
|
||||
import download from "downloadjs"
|
||||
|
@ -116,43 +116,30 @@
|
|||
data.append("templateKey", template.key)
|
||||
|
||||
// Create App
|
||||
const appResp = await post("/api/applications", data, {})
|
||||
const appJson = await appResp.json()
|
||||
if (!appResp.ok) {
|
||||
throw new Error(appJson.message)
|
||||
}
|
||||
|
||||
const createdApp = await API.createApp(data)
|
||||
analytics.captureEvent(Events.APP.CREATED, {
|
||||
name: appName,
|
||||
appId: appJson.instance._id,
|
||||
appId: createdApp.instance._id,
|
||||
template,
|
||||
fromTemplateMarketplace: true,
|
||||
})
|
||||
|
||||
// Select Correct Application/DB in prep for creating user
|
||||
const applicationPkg = await get(
|
||||
`/api/applications/${appJson.instance._id}/appPackage`
|
||||
)
|
||||
const pkg = await applicationPkg.json()
|
||||
if (applicationPkg.ok) {
|
||||
await store.actions.initialise(pkg)
|
||||
await automationStore.actions.fetch()
|
||||
// update checklist - incase first app
|
||||
await admin.init()
|
||||
} else {
|
||||
throw new Error(pkg)
|
||||
}
|
||||
const pkg = await API.fetchAppPackage(createdApp.instance._id)
|
||||
await store.actions.initialise(pkg)
|
||||
await automationStore.actions.fetch()
|
||||
// Update checklist - in case first app
|
||||
await admin.init()
|
||||
|
||||
// Create user
|
||||
const userResp = await api.post(`/api/users/metadata/self`, {
|
||||
await API.updateOwnMetadata({
|
||||
roleId: "BASIC",
|
||||
})
|
||||
await userResp.json()
|
||||
await auth.setInitInfo({})
|
||||
$goto(`/builder/app/${appJson.instance._id}`)
|
||||
$goto(`/builder/app/${createdApp.instance._id}`)
|
||||
} catch (error) {
|
||||
notifications.error("Error creating app")
|
||||
console.error(error)
|
||||
notifications.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -202,17 +189,11 @@
|
|||
return
|
||||
}
|
||||
try {
|
||||
const response = await del(
|
||||
`/api/applications/${selectedApp.prodId}?unpublish=1`
|
||||
)
|
||||
if (response.status !== 200) {
|
||||
const json = await response.json()
|
||||
throw json.message
|
||||
}
|
||||
await API.unpublishApp(selectedApp.prodId)
|
||||
await apps.load()
|
||||
notifications.success("App unpublished successfully")
|
||||
} catch (err) {
|
||||
notifications.error(`Error unpublishing app: ${err}`)
|
||||
notifications.error("Error unpublishing app")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -226,17 +207,13 @@
|
|||
return
|
||||
}
|
||||
try {
|
||||
const response = await del(`/api/applications/${selectedApp?.devId}`)
|
||||
if (response.status !== 200) {
|
||||
const json = await response.json()
|
||||
throw json.message
|
||||
}
|
||||
await API.deleteApp(selectedApp?.devId)
|
||||
await apps.load()
|
||||
// get checklist, just in case that was the last app
|
||||
// Get checklist, just in case that was the last app
|
||||
await admin.init()
|
||||
notifications.success("App deleted successfully")
|
||||
} catch (err) {
|
||||
notifications.error(`Error deleting app: ${err}`)
|
||||
notifications.error("Error deleting app")
|
||||
}
|
||||
selectedApp = null
|
||||
appName = null
|
||||
|
@ -249,15 +226,11 @@
|
|||
|
||||
const releaseLock = async app => {
|
||||
try {
|
||||
const response = await del(`/api/dev/${app.devId}/lock`)
|
||||
if (response.status !== 200) {
|
||||
const json = await response.json()
|
||||
throw json.message
|
||||
}
|
||||
await API.releaseAppLock(app.devId)
|
||||
await apps.load()
|
||||
notifications.success("Lock released successfully")
|
||||
} catch (err) {
|
||||
notifications.error(`Error releasing lock: ${err}`)
|
||||
notifications.error("Error releasing lock")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
Checkbox,
|
||||
} from "@budibase/bbui"
|
||||
import { email } from "stores/portal"
|
||||
import api from "builderStore/api"
|
||||
import { API } from "api"
|
||||
import { cloneDeep } from "lodash/fp"
|
||||
import analytics, { Events } from "analytics"
|
||||
|
||||
|
@ -54,55 +54,48 @@
|
|||
delete smtp.config.auth
|
||||
}
|
||||
// Save your SMTP config
|
||||
const response = await api.post(`/api/global/configs`, smtp)
|
||||
|
||||
if (response.status !== 200) {
|
||||
const error = await response.text()
|
||||
let message
|
||||
try {
|
||||
message = JSON.parse(error).message
|
||||
} catch (err) {
|
||||
message = error
|
||||
}
|
||||
notifications.error(`Failed to save email settings, reason: ${message}`)
|
||||
} else {
|
||||
const json = await response.json()
|
||||
smtpConfig._rev = json._rev
|
||||
smtpConfig._id = json._id
|
||||
notifications.success(`Settings saved.`)
|
||||
try {
|
||||
const savedConfig = await API.saveConfig(smtp)
|
||||
smtpConfig._rev = savedConfig._rev
|
||||
smtpConfig._id = savedConfig._id
|
||||
notifications.success(`Settings saved`)
|
||||
analytics.captureEvent(Events.SMTP.SAVED)
|
||||
} catch (error) {
|
||||
notifications.error(
|
||||
`Failed to save email settings, reason: ${error?.message || "Unknown"}`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchSmtp() {
|
||||
loading = true
|
||||
// fetch the configs for smtp
|
||||
const smtpResponse = await api.get(
|
||||
`/api/global/configs/${ConfigTypes.SMTP}`
|
||||
)
|
||||
const smtpDoc = await smtpResponse.json()
|
||||
|
||||
if (!smtpDoc._id) {
|
||||
smtpConfig = {
|
||||
type: ConfigTypes.SMTP,
|
||||
config: {
|
||||
secure: true,
|
||||
},
|
||||
try {
|
||||
// Fetch the configs for smtp
|
||||
const smtpDoc = await API.getConfig(ConfigTypes.SMTP)
|
||||
if (!smtpDoc._id) {
|
||||
smtpConfig = {
|
||||
type: ConfigTypes.SMTP,
|
||||
config: {
|
||||
secure: true,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
smtpConfig = smtpDoc
|
||||
}
|
||||
} else {
|
||||
smtpConfig = smtpDoc
|
||||
}
|
||||
loading = false
|
||||
requireAuth = smtpConfig.config.auth != null
|
||||
// always attach the auth for the forms purpose -
|
||||
// this will be removed later if required
|
||||
if (!smtpDoc.config) {
|
||||
smtpDoc.config = {}
|
||||
}
|
||||
if (!smtpDoc.config.auth) {
|
||||
smtpConfig.config.auth = {
|
||||
type: "login",
|
||||
loading = false
|
||||
requireAuth = smtpConfig.config.auth != null
|
||||
// Always attach the auth for the forms purpose -
|
||||
// this will be removed later if required
|
||||
if (!smtpDoc.config) {
|
||||
smtpDoc.config = {}
|
||||
}
|
||||
if (!smtpDoc.config.auth) {
|
||||
smtpConfig.config.auth = {
|
||||
type: "login",
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
notifications.error("Error fetching SMTP config")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { writable, get } from "svelte/store"
|
||||
import api from "builderStore/api"
|
||||
import { API } from "api"
|
||||
import { auth } from "stores/portal"
|
||||
|
||||
export function createAdminStore() {
|
||||
|
@ -25,21 +25,19 @@ export function createAdminStore() {
|
|||
async function init() {
|
||||
try {
|
||||
const tenantId = get(auth).tenantId
|
||||
const response = await api.get(
|
||||
`/api/global/configs/checklist?tenantId=${tenantId}`
|
||||
)
|
||||
const json = await response.json()
|
||||
const totalSteps = Object.keys(json).length
|
||||
const completedSteps = Object.values(json).filter(x => x?.checked).length
|
||||
|
||||
const checklist = await API.getChecklist(tenantId)
|
||||
const totalSteps = Object.keys(checklist).length
|
||||
const completedSteps = Object.values(checklist).filter(
|
||||
x => x?.checked
|
||||
).length
|
||||
await getEnvironment()
|
||||
admin.update(store => {
|
||||
store.loaded = true
|
||||
store.checklist = json
|
||||
store.checklist = checklist
|
||||
store.onboardingProgress = (completedSteps / totalSteps) * 100
|
||||
return store
|
||||
})
|
||||
} catch (err) {
|
||||
} catch (error) {
|
||||
admin.update(store => {
|
||||
store.checklist = null
|
||||
return store
|
||||
|
@ -48,11 +46,15 @@ export function createAdminStore() {
|
|||
}
|
||||
|
||||
async function checkImportComplete() {
|
||||
const response = await api.get(`/api/cloud/import/complete`)
|
||||
if (response.status === 200) {
|
||||
const json = await response.json()
|
||||
try {
|
||||
const result = await API.checkImportComplete()
|
||||
admin.update(store => {
|
||||
store.importComplete = json ? json.imported : false
|
||||
store.importComplete = result ? result.imported : false
|
||||
return store
|
||||
})
|
||||
} catch (error) {
|
||||
admin.update(store => {
|
||||
store.importComplete = false
|
||||
return store
|
||||
})
|
||||
}
|
||||
|
@ -65,15 +67,14 @@ export function createAdminStore() {
|
|||
let accountPortalUrl = ""
|
||||
let isDev = false
|
||||
try {
|
||||
const response = await api.get(`/api/system/environment`)
|
||||
const json = await response.json()
|
||||
multiTenancyEnabled = json.multiTenancy
|
||||
cloud = json.cloud
|
||||
disableAccountPortal = json.disableAccountPortal
|
||||
accountPortalUrl = json.accountPortalUrl
|
||||
isDev = json.isDev
|
||||
const environment = await API.getEnvironment()
|
||||
multiTenancyEnabled = environment.multiTenancy
|
||||
cloud = environment.cloud
|
||||
disableAccountPortal = environment.disableAccountPortal
|
||||
accountPortalUrl = environment.accountPortalUrl
|
||||
isDev = environment.isDev
|
||||
} catch (err) {
|
||||
// just let it stay disabled
|
||||
// Just let it stay disabled
|
||||
}
|
||||
admin.update(store => {
|
||||
store.multiTenancy = multiTenancyEnabled
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { writable, get } from "svelte/store"
|
||||
import api from "builderStore/api"
|
||||
import { API } from "api"
|
||||
import { auth } from "stores/portal"
|
||||
|
||||
const OIDC_CONFIG = {
|
||||
|
@ -14,16 +14,17 @@ export function createOidcStore() {
|
|||
|
||||
async function init() {
|
||||
const tenantId = get(auth).tenantId
|
||||
const res = await api.get(
|
||||
`/api/global/configs/public/oidc?tenantId=${tenantId}`
|
||||
)
|
||||
const json = await res.json()
|
||||
|
||||
if (json.status === 400 || Object.keys(json).length === 0) {
|
||||
try {
|
||||
const config = await API.getOIDCConfig(tenantId)
|
||||
if (Object.keys(config || {}).length) {
|
||||
// Just use the first config for now.
|
||||
// We will be support multiple logins buttons later on.
|
||||
set(...config)
|
||||
} else {
|
||||
set(OIDC_CONFIG)
|
||||
}
|
||||
} catch (error) {
|
||||
set(OIDC_CONFIG)
|
||||
} else {
|
||||
// Just use the first config for now. We will be support multiple logins buttons later on.
|
||||
set(...json)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,9 +18,21 @@ export const API = createAPIClient({
|
|||
// We could also log these to sentry.
|
||||
// Or we could check error.status and redirect to login on a 403 etc.
|
||||
onError: error => {
|
||||
if (error.message) {
|
||||
notificationStore.actions.error(error.message)
|
||||
const { status, method, url, message, handled } = error || {}
|
||||
|
||||
// Log any errors that we haven't manually handled
|
||||
if (!handled) {
|
||||
console.error("Unhandled error from API client", error)
|
||||
return
|
||||
}
|
||||
|
||||
// Notify all errors
|
||||
if (message) {
|
||||
notificationStore.actions.error(message)
|
||||
}
|
||||
|
||||
// Log all errors to console
|
||||
console.error(`HTTP ${status} on ${method}:${url}:\n\t${message}`)
|
||||
},
|
||||
|
||||
// Patch certain endpoints with functionality specific to client apps
|
||||
|
|
|
@ -25,7 +25,7 @@ export const buildAppEndpoints = API => ({
|
|||
/**
|
||||
* Deploys the current app.
|
||||
*/
|
||||
deployApp: async () => {
|
||||
deployAppChanges: async () => {
|
||||
return await API.post({
|
||||
url: "/api/deploy",
|
||||
})
|
||||
|
@ -35,12 +35,32 @@ export const buildAppEndpoints = API => ({
|
|||
* Reverts an app to a previous version.
|
||||
* @param appId the app ID to revert
|
||||
*/
|
||||
revertApp: async appId => {
|
||||
revertAppChanges: async appId => {
|
||||
return await API.post({
|
||||
url: `/api/dev/${appId}/revert`,
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates an app's version of the client library.
|
||||
* @param appId the app ID to update
|
||||
*/
|
||||
updateAppClientVersion: async appId => {
|
||||
return await API.post({
|
||||
url: `/api/applications/${appId}/client/update`,
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Reverts an app's version of the client library to the previous version.
|
||||
* @param appId the app ID to revert
|
||||
*/
|
||||
revertAppClientVersion: async appId => {
|
||||
return await API.post({
|
||||
url: `/api/applications/${appId}/client/revert`,
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets a list of app deployments.
|
||||
*/
|
||||
|
@ -49,4 +69,57 @@ export const buildAppEndpoints = API => ({
|
|||
url: "/api/deployments",
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates an app.
|
||||
* @param app the app to create
|
||||
*/
|
||||
createApp: async app => {
|
||||
return await API.post({
|
||||
url: "/api/applications",
|
||||
body: app,
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Imports an export of all apps.
|
||||
* @param apps the FormData containing the apps to import
|
||||
*/
|
||||
importApps: async apps => {
|
||||
return await API.post({
|
||||
url: "/api/cloud/import",
|
||||
body: apps,
|
||||
json: false,
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Unpublishes a published app.
|
||||
* @param appId the production ID of the app to unpublish
|
||||
*/
|
||||
unpublishApp: async appId => {
|
||||
return await API.delete({
|
||||
url: `/api/applications/${appId}?unpublish=1`,
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Deletes a dev app.
|
||||
* @param appId the dev app ID to delete
|
||||
*/
|
||||
deleteApp: async appId => {
|
||||
return await API.delete({
|
||||
url: `/api/applications/${appId}`,
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Releases the lock on a dev app.
|
||||
* @param appId the dev app ID to unlock
|
||||
*/
|
||||
releaseAppLock: async appId => {
|
||||
return await API.delete({
|
||||
url: `/api/dev/${appId}/lock`,
|
||||
})
|
||||
},
|
||||
})
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
export const buildAttachmentEndpoints = API => ({
|
||||
/**
|
||||
* Uploads an attachment to the server.
|
||||
* @param data the attachment to upload
|
||||
* @param tableId the table ID to upload to
|
||||
*/
|
||||
uploadAttachment: async ({ data, tableId }) => {
|
||||
return await API.post({
|
||||
|
@ -9,4 +11,16 @@ export const buildAttachmentEndpoints = API => ({
|
|||
json: false,
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Uploads an attachment to the server as a builder user from the builder.
|
||||
* @param data the data to upload
|
||||
*/
|
||||
uploadBuilderAttachment: async data => {
|
||||
return await API.post({
|
||||
url: "/api/attachments/process",
|
||||
body: data,
|
||||
json: false,
|
||||
})
|
||||
},
|
||||
})
|
||||
|
|
|
@ -31,6 +31,89 @@ export const buildAuthEndpoints = API => ({
|
|||
* Fetches the currently logged in user object
|
||||
*/
|
||||
fetchSelf: async () => {
|
||||
return await API.get({ url: "/api/self" })
|
||||
return await API.get({
|
||||
url: "/api/self",
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the current user metadata.
|
||||
* @param metadata the metadata to save
|
||||
*/
|
||||
updateOwnMetadata: async metadata => {
|
||||
return await API.post({
|
||||
url: "/api/users/metadata/self",
|
||||
body: metadata,
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates an admin user.
|
||||
* @param adminUser the admin user to create
|
||||
*/
|
||||
createAdminUser: async adminUser => {
|
||||
return await API.post({
|
||||
url: "/api/global/users/init",
|
||||
body: adminUser,
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Saves a global config.
|
||||
* @param config the config to save
|
||||
*/
|
||||
saveConfig: async config => {
|
||||
return await API.post({
|
||||
url: "/api/global/configs",
|
||||
body: config,
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets a global config of a certain type.
|
||||
* @param type the type to fetch
|
||||
*/
|
||||
getConfig: async type => {
|
||||
return await API.get({
|
||||
url: `/api/global/configs/${type}`,
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the OIDC config for a certain tenant.
|
||||
* @param tenantId the tenant ID to get the config for
|
||||
*/
|
||||
getOIDCConfig: async tenantId => {
|
||||
return await API.get({
|
||||
url: `/api/global/configs/public/oidc?tenantId=${tenantId}`,
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the checklist for a specific tenant.
|
||||
* @param tenantId the tenant ID to get the checklist for
|
||||
*/
|
||||
getChecklist: async tenantId => {
|
||||
return await API.get({
|
||||
url: `/api/global/configs/checklist?tenantId=${tenantId}`,
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* TODO: find out what this is
|
||||
*/
|
||||
checkImportComplete: async () => {
|
||||
return await API.get({
|
||||
url: "/api/cloud/import/complete",
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the current environment details.
|
||||
*/
|
||||
getEnvironment: async () => {
|
||||
return await API.get({
|
||||
url: "/api/system/environment",
|
||||
})
|
||||
},
|
||||
})
|
||||
|
|
|
@ -30,7 +30,9 @@ export const createAPIClient = config => {
|
|||
}
|
||||
|
||||
// Generates an error object from an API response
|
||||
const makeErrorFromResponse = async response => {
|
||||
const makeErrorFromResponse = async (response, method) => {
|
||||
console.log("making error from", response)
|
||||
|
||||
// Try to read a message from the error
|
||||
let message = response.statusText
|
||||
try {
|
||||
|
@ -47,6 +49,8 @@ export const createAPIClient = config => {
|
|||
message,
|
||||
status: response.status,
|
||||
url: response.url,
|
||||
method,
|
||||
handled: true,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,6 +60,8 @@ export const createAPIClient = config => {
|
|||
message,
|
||||
status: 400,
|
||||
url: "",
|
||||
method: "",
|
||||
handled: true,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,11 +116,7 @@ export const createAPIClient = config => {
|
|||
return null
|
||||
}
|
||||
} else {
|
||||
const error = await makeErrorFromResponse(response)
|
||||
if (config?.onError) {
|
||||
config.onError(error)
|
||||
}
|
||||
throw error
|
||||
throw await makeErrorFromResponse(response, method)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,14 +136,21 @@ export const createAPIClient = config => {
|
|||
return await cache[identifier]
|
||||
}
|
||||
|
||||
// Constructs an API call function for a particular HTTP method.
|
||||
// Constructs an API call function for a particular HTTP method
|
||||
const requestApiCall = method => async params => {
|
||||
let { url, cache = false, external = false } = params
|
||||
if (!external) {
|
||||
url = `/${url}`.replace("//", "/")
|
||||
try {
|
||||
let { url, cache = false, external = false } = params
|
||||
if (!external) {
|
||||
url = `/${url}`.replace("//", "/")
|
||||
}
|
||||
const enrichedParams = { ...params, method, url }
|
||||
return await (cache ? makeCachedApiCall : makeApiCall)(enrichedParams)
|
||||
} catch (error) {
|
||||
if (config?.onError) {
|
||||
config.onError(error)
|
||||
}
|
||||
throw error
|
||||
}
|
||||
const enrichedParams = { ...params, method, url }
|
||||
return await (cache ? makeCachedApiCall : makeApiCall)(enrichedParams)
|
||||
}
|
||||
|
||||
// Build the underlying core API methods
|
||||
|
|
Loading…
Reference in New Issue