import { randomUUID } from 'node:crypto'; const names = [ 'OUTRESERVE_SUPPLY_BASE_URL', 'OUTRESERVE_SUPPLY_API_KEY', 'OUTRESERVE_PROPERTY_ID', 'OUTRESERVE_UNIT_ID', 'OUTRESERVE_DATE_FROM', 'OUTRESERVE_DATE_TO', 'OUTRESERVE_INCORPORATED_RESERVATION_SEQUENCE', ]; for (const name of names) { if (!process.env[name]) throw new Error(`Set ${name} before running this example`); } const base = process.env.OUTRESERVE_SUPPLY_BASE_URL.replace(/\/$/, ''); const propertyId = process.env.OUTRESERVE_PROPERTY_ID; const url = `${base}/properties/${encodeURIComponent(propertyId)}/ari`; const range = new URLSearchParams({ date_from: process.env.OUTRESERVE_DATE_FROM, date_to: process.env.OUTRESERVE_DATE_TO, }); const authorization = `Bearer ${process.env.OUTRESERVE_SUPPLY_API_KEY}`; const incorporationSequence = process.env.OUTRESERVE_INCORPORATED_RESERVATION_SEQUENCE; if (!/^(0|[1-9]\d*)$/.test(incorporationSequence) || !Number.isSafeInteger(Number(incorporationSequence))) { throw new Error('Set OUTRESERVE_INCORPORATED_RESERVATION_SEQUENCE to a nonnegative safe integer'); } async function request(path, options = {}) { const response = await fetch(path, { ...options, headers: { Authorization: authorization, ...options.headers }, }); const contentType = response.headers.get('content-type') || ''; const text = await response.text(); const body = contentType.includes('json') && text ? JSON.parse(text) : text; if (!response.ok) { const code = typeof body === 'object' && body !== null ? body.code : undefined; throw new Error(`Supply API ${response.status} ${code || ''}: ${JSON.stringify(body)}`); } return body; } const current = await request(`${url}?${range}`); const revision = current?.data?.calendar_revision; if (revision === undefined || revision === null) { throw new Error('GET ARI did not return data.calendar_revision; inspect before writing'); } const update = { updates: [{ scope: 'unit', unit_id: process.env.OUTRESERVE_UNIT_ID, date_from: process.env.OUTRESERVE_DATE_FROM, date_to: process.env.OUTRESERVE_DATE_TO, available_count: 1, incorporated_reservation_sequence: Number(incorporationSequence), rate_minor: 18500, stop_sell: false, }], }; const key = randomUUID(); const result = await request(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'If-Match': `"${revision}"`, 'Idempotency-Key': key, }, body: JSON.stringify(update), }); console.log(JSON.stringify({ applied: result, readback: await request(`${url}?${range}`) }, null, 2));