Appwrite: Bulk-Create, Bereichsabfragen, seitenweises Laden, genauerer Nachbau
appwriteAdmin: adminFetch kennt die Option raw (Body unverpackt), createDocuments (Bulk-Create, alles oder nichts, 409 bei vorhandener ID), listAllDocuments (seitenweise per cursorAfter, sortiert nach $id, Fehler ueber max) und Query.between/greaterThanEqual/ lessThanEqual/cursorAfter. Nachbau: Bulk-Create mit Alles-oder-nichts (409/400, hoechstens 100), die neuen Abfragen samt cursorAfter, Zeitpunktvergleich fuer ISO-Datumswerte, Optionen datetimes (Normalisierung auf +00:00, leeres Datum => 400) und defaultLimit (Standard-Limit wie Appwrite). Ohne die Optionen unveraendert. testApp exportiert send(method, path, opts). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
334dc1e669
commit
a5e12d7f34
4 files changed
+407
-23
No files matched your search
@@ -25,7 +25,8 @@ function formatRequestBody(body, method, { raw = false } = {}) {
|
||||
return payload
|
||||
}
|
||||
|
||||
async function adminFetch(path, { method = 'GET', body, queries = [] } = {}) {
|
||||
/** raw: true schickt den Body unverpackt (sonst wird er zu { data, documentId }; Pfade unter /users sind immer roh). */
|
||||
async function adminFetch(path, { method = 'GET', body, queries = [], raw = false } = {}) {
|
||||
if (!config.appwrite.apiKey) {
|
||||
const error = new Error('APPWRITE_API_KEY fehlt in .env')
|
||||
error.status = 500
|
||||
@@ -37,7 +38,7 @@ async function adminFetch(path, { method = 'GET', body, queries = [] } = {}) {
|
||||
url.searchParams.append('queries[]', q)
|
||||
}
|
||||
|
||||
const useRawBody = path.startsWith('/users')
|
||||
const useRawBody = raw || path.startsWith('/users')
|
||||
const requestBody = formatRequestBody(body, method, { raw: useRawBody })
|
||||
|
||||
const response = await fetch(url.toString(), {
|
||||
@@ -77,6 +78,12 @@ export const Query = {
|
||||
limit: (n) => ({ method: 'limit', values: [n] }),
|
||||
greaterThan: (attribute, value) => ({ method: 'greaterThan', attribute, values: [value] }),
|
||||
lessThan: (attribute, value) => ({ method: 'lessThan', attribute, values: [value] }),
|
||||
greaterThanEqual: (attribute, value) => ({ method: 'greaterThanEqual', attribute, values: [value] }),
|
||||
lessThanEqual: (attribute, value) => ({ method: 'lessThanEqual', attribute, values: [value] }),
|
||||
/** Beide Grenzen inklusiv */
|
||||
between: (attribute, start, end) => ({ method: 'between', attribute, values: [start, end] }),
|
||||
/** Seite nach dem Dokument mit dieser ID (zusammen mit orderAsc/orderDesc und limit) */
|
||||
cursorAfter: (documentId) => ({ method: 'cursorAfter', values: [documentId] }),
|
||||
orderDesc: (attribute) => ({ method: 'orderDesc', attribute }),
|
||||
orderAsc: (attribute) => ({ method: 'orderAsc', attribute }),
|
||||
}
|
||||
@@ -157,6 +164,34 @@ export async function listDocuments(collectionId, queries = []) {
|
||||
return result.documents
|
||||
}
|
||||
|
||||
/**
|
||||
* Ein Aufruf mit allen Seiten: sortiert nach $id, Seite fuer Seite per cursorAfter, bis eine Seite kuerzer als
|
||||
* pageSize ist. queries enthalten nur Filter, nie limit/order/cursor (die setzt die Funktion selbst). Mehr als max
|
||||
* Treffer ist ein Fehler (Schutz vor unbeabsichtigtem Vollabzug).
|
||||
*/
|
||||
export async function listAllDocuments(collectionId, queries = [], { pageSize = 500, max = 20000 } = {}) {
|
||||
if (!Number.isInteger(pageSize) || pageSize < 1) throw new Error(`listAllDocuments: pageSize muss eine ganze Zahl ab 1 sein, nicht ${pageSize}`)
|
||||
const all = []
|
||||
let cursor = null
|
||||
for (;;) {
|
||||
const page = await listDocuments(collectionId, [
|
||||
...queries,
|
||||
Query.limit(pageSize),
|
||||
Query.orderAsc('$id'),
|
||||
...(cursor ? [Query.cursorAfter(cursor)] : []),
|
||||
])
|
||||
all.push(...page)
|
||||
if (all.length > max) {
|
||||
const error = new Error(`listAllDocuments: mehr als ${max} Dokumente in ${collectionId}`)
|
||||
error.status = 500
|
||||
error.type = 'list_limit_exceeded'
|
||||
throw error
|
||||
}
|
||||
if (page.length < pageSize) return all
|
||||
cursor = page[page.length - 1].$id
|
||||
}
|
||||
}
|
||||
|
||||
export async function getCustomerByAppwriteUserId(appwriteUserId) {
|
||||
const docs = await listDocuments(config.collections.customers, [
|
||||
Query.equal('appwriteUserId', appwriteUserId),
|
||||
@@ -218,6 +253,17 @@ export async function createDocument(collectionId, data, documentId = ID.unique(
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Mehrere Dokumente in einer Anfrage (Appwrite 1.8.1 Bulk-Create, hoechstens 100): alles oder nichts. Ist eine
|
||||
* $id schon vergeben, antwortet Appwrite 409 document_already_exists und schreibt nichts (err.status === 409).
|
||||
* Jedes Dokument bringt seine $id mit: [{ $id, ...felder }]. Liefert die angelegten Dokumente.
|
||||
*/
|
||||
export async function createDocuments(collectionId, documents) {
|
||||
if (documents.length === 0) return []
|
||||
const result = await adminFetch(collectionPath(collectionId), { method: 'POST', body: { documents }, raw: true })
|
||||
return result.documents
|
||||
}
|
||||
|
||||
export async function deleteDocument(collectionId, documentId) {
|
||||
return adminFetch(`${collectionPath(collectionId)}/${documentId}`, {
|
||||
method: 'DELETE',
|
||||
|
||||
Reference in new issue
Block a user