feat: wire BuildPulse to Appwrite-backed persistence
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
const endpoint = process.env.APPWRITE_SELF_HOSTED_URL || 'https://app.friborg.uk/v1'
|
||||
const projectId = process.env.APPWRITE_SELF_HOSTED_PROJECT_ID || 'freecastle'
|
||||
|
||||
export const BUILDPULSE_DATABASE_ID = process.env.BUILDPULSE_APPWRITE_DATABASE_ID || process.env.APPWRITE_SELF_HOSTED_DATABASE_ID || 'freecastle'
|
||||
export const BUILDPULSE_COLLECTION_ID = process.env.BUILDPULSE_APPWRITE_COLLECTION_ID || 'runtime'
|
||||
export const BUILDPULSE_DOCUMENT_ID = process.env.BUILDPULSE_APPWRITE_DOCUMENT_ID || 'buildpulse_state'
|
||||
export const BUILDPULSE_DOCUMENT_KEY = process.env.BUILDPULSE_APPWRITE_DOCUMENT_KEY || 'buildpulse_state'
|
||||
|
||||
const baseHeaders = {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Appwrite-Project': projectId,
|
||||
}
|
||||
|
||||
const documentUrl = `${endpoint}/databases/${BUILDPULSE_DATABASE_ID}/collections/${BUILDPULSE_COLLECTION_ID}/documents/${BUILDPULSE_DOCUMENT_ID}`
|
||||
const collectionUrl = `${endpoint}/databases/${BUILDPULSE_DATABASE_ID}/collections/${BUILDPULSE_COLLECTION_ID}/documents`
|
||||
|
||||
async function appwriteFetch(url, init = {}) {
|
||||
const response = await fetch(url, {
|
||||
...init,
|
||||
headers: {
|
||||
...baseHeaders,
|
||||
...(init.headers || {}),
|
||||
},
|
||||
})
|
||||
|
||||
if (response.status === 204) return null
|
||||
|
||||
const text = await response.text()
|
||||
const payload = text ? JSON.parse(text) : null
|
||||
|
||||
if (!response.ok) {
|
||||
const error = new Error(payload?.message || `Appwrite request failed with ${response.status}`)
|
||||
error.status = response.status
|
||||
error.payload = payload
|
||||
throw error
|
||||
}
|
||||
|
||||
return payload
|
||||
}
|
||||
|
||||
export async function fetchStoredAppState() {
|
||||
try {
|
||||
const document = await appwriteFetch(documentUrl)
|
||||
return document?.value ? JSON.parse(document.value) : null
|
||||
} catch (error) {
|
||||
if (error?.status === 404) return null
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
export async function persistAppState(state) {
|
||||
const body = {
|
||||
data: {
|
||||
key: BUILDPULSE_DOCUMENT_KEY,
|
||||
value: JSON.stringify(state),
|
||||
updatedAt: new Date().toISOString(),
|
||||
},
|
||||
}
|
||||
|
||||
try {
|
||||
return await appwriteFetch(documentUrl, {
|
||||
method: 'PATCH',
|
||||
body: JSON.stringify(body),
|
||||
})
|
||||
} catch (error) {
|
||||
if (error?.status !== 404) throw error
|
||||
}
|
||||
|
||||
return appwriteFetch(collectionUrl, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
documentId: BUILDPULSE_DOCUMENT_ID,
|
||||
...body,
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
export async function checkBackendHealth() {
|
||||
const document = await appwriteFetch(documentUrl).catch((error) => {
|
||||
if (error?.status === 404) return null
|
||||
throw error
|
||||
})
|
||||
|
||||
return {
|
||||
ok: true,
|
||||
backend: 'appwrite',
|
||||
endpoint,
|
||||
databaseId: BUILDPULSE_DATABASE_ID,
|
||||
collectionId: BUILDPULSE_COLLECTION_ID,
|
||||
documentPresent: Boolean(document),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user