Abo-API: Nachweis-ID nach Appwrite-Regeln, Webhook bei dauerhaften Fehlern, Tests
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
7df0b72019
commit
887e1e54a0
10 files changed
+409
-107
No files matched your search
@@ -3,11 +3,26 @@ import http from 'node:http'
|
||||
/**
|
||||
* Appwrite-Nachbau für Tests: die REST-Pfade, die server/services/appwriteAdmin.js benutzt, im
|
||||
* Speicher. Mit schema = { collection: ['attr', ...] } lehnt er unbekannte Attribute ab wie
|
||||
* Appwrite ("Invalid document structure: Unknown attribute").
|
||||
* Appwrite ("Invalid document structure: Unknown attribute"). Dokument-IDs prüft er wie Appwrite
|
||||
* (höchstens 36 Zeichen aus a-z, A-Z, 0-9, Punkt, Bindestrich, Unterstrich, kein Sonderzeichen am
|
||||
* Anfang). failNext({ collection?, method?, status, message? }) lässt die nächste passende Anfrage
|
||||
* mit diesem Status scheitern (Fehlerpfade wie "Appwrite nicht erreichbar" oder "Collection fehlt").
|
||||
*/
|
||||
export async function startAppwriteMock({ schema = {} } = {}) {
|
||||
const collections = new Map()
|
||||
let sequence = 0
|
||||
let pendingFailure = null
|
||||
|
||||
// Wie Appwrite (Validator UID): 'unique()' ist erlaubt, sonst [A-Za-z0-9][A-Za-z0-9._-]{0,35}
|
||||
const validDocumentId = (id) => id === 'unique()' || (typeof id === 'string' && /^[A-Za-z0-9][A-Za-z0-9._-]{0,35}$/.test(id))
|
||||
const invalidDocumentId = [
|
||||
400,
|
||||
{
|
||||
message: 'Invalid `documentId` param: UID must contain at most 36 chars. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char',
|
||||
code: 400,
|
||||
type: 'general_argument_invalid',
|
||||
},
|
||||
]
|
||||
|
||||
const docs = (collection) => {
|
||||
if (!collections.has(collection)) collections.set(collection, new Map())
|
||||
@@ -83,9 +98,21 @@ export async function startAppwriteMock({ schema = {} } = {}) {
|
||||
const store = docs(collection)
|
||||
const notFound = [404, { message: 'Document with the requested ID could not be found.', code: 404, type: 'document_not_found' }]
|
||||
|
||||
// Eingeplanter Fehler (failNext): genau eine passende Anfrage scheitert
|
||||
if (
|
||||
pendingFailure &&
|
||||
(!pendingFailure.collection || pendingFailure.collection === collection) &&
|
||||
(!pendingFailure.method || pendingFailure.method === req.method)
|
||||
) {
|
||||
const { status, message } = pendingFailure
|
||||
pendingFailure = null
|
||||
return [status, { message: message || `Nachbau: eingeplanter Fehler ${status}`, code: status, type: 'general_server_error' }]
|
||||
}
|
||||
|
||||
if (!id && req.method === 'GET') return list(collection, url.searchParams.getAll('queries[]'))
|
||||
if (!id && req.method === 'POST') {
|
||||
const { documentId, data = {} } = await readBody(req)
|
||||
if (!validDocumentId(documentId)) return invalidDocumentId
|
||||
if (store.has(documentId)) {
|
||||
return [409, { message: 'Document with the requested ID already exists.', code: 409, type: 'document_already_exists' }]
|
||||
}
|
||||
@@ -128,6 +155,10 @@ export async function startAppwriteMock({ schema = {} } = {}) {
|
||||
url: `http://127.0.0.1:${server.address().port}/v1`,
|
||||
docs: (collection) => new Map([...docs(collection)].map(([id, doc]) => [id, publicDoc(doc)])),
|
||||
seed,
|
||||
/** Naechste passende Dokument-Anfrage scheitert mit status (einmalig). */
|
||||
failNext: ({ collection = null, method = null, status = 500, message = '' }) => {
|
||||
pendingFailure = { collection, method, status, message }
|
||||
},
|
||||
close: () => new Promise((resolve) => server.close(resolve)),
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user