// Drop-in JavaScript client library for the Friendship Tracker HTTP API. // // Save this file alongside your source as `friendship_client.js` and import // the operation functions you need: // // import { setToken, account_list, account_create } from "./friendship_client.js" // setToken("pat_...") // const rows = await account_list({ limit: 20, sort: "-created_at" }) // const fresh = await account_create({ name: "Example GmbH" }) // // CommonJS works too: // // const { setToken, account_list } = require("./friendship_client.js") // // Every endpoint exposed by the HTTP API is wrapped as a typed // `_` function. List endpoints take an options object; // get/update/delete endpoints take the row id as their first argument. // // Provided as-is, with no warranty. Vendor freely; modify if you need // to. Targets ES2020+; uses the global `fetch` (Node 18+ / browser). // // DO NOT EDIT THIS FILE MANUALLY - re-download from the docs site instead. // Local edits will be overwritten by the once-per-day version check. const _g = (typeof globalThis !== 'undefined') ? globalThis : (typeof self !== 'undefined' ? self : this) // `require` only exists in CommonJS, `__filename` only in CommonJS. // Reach for them through the global so a strict ESM build still loads // the file. Both are wrapped in feature checks before any actual call. let _nodeRequire = null try { _nodeRequire = (_g && _g.require) || (typeof require === 'function' ? require : null) } catch (_e) { _nodeRequire = null } let _nodeFilename = null try { _nodeFilename = (typeof __filename !== 'undefined') ? __filename : null } catch (_e) { _nodeFilename = null } // ── Identity (substituted at generation time) ──────────────────────── export const APP_SLUG = "friendship" export const APP_NAME = "Friendship Tracker" export const MODULE_NAME = "friendship_client" export const CLIENT_VERSION = "0.3.13" export const LANGUAGE = "javascript" const DEFAULT_BASE = "https://friendship-tracker.com" // Per-type metadata baked at generation time. Inspect at runtime when // calling code needs to know the legal filters / sort columns / // max_limit for a model without a second round-trip. export const TYPES = JSON.parse(String.raw`{"activity":{"ops":["list","read","create","update","delete"],"create_fields":["parent_id","kind","summary","description","occurred_at","location"],"update_fields":["kind","summary","description","occurred_at","location"],"allowed_filters":["data__parent_id","data__kind","status","is_archived","owned_by"],"allowed_sorts":["created_at","data__occurred_at"],"default_sort":"data__occurred_at","max_limit":200,"fields":[{"name":"kind","type":"enum","values":["meeting","call","email","message","event","other"]},{"name":"summary","type":"string","max_len":400},{"name":"location","type":"string","max_len":200},{"name":"parent_id","type":"string","max_len":64,"ref":{"type":"contact","owned":true,"optional":false}},{"name":"description","type":"string","max_len":4000},{"name":"occurred_at","type":"string","max_len":32}]},"contact":{"ops":["list","read","create","update","delete"],"create_fields":["name","nickname","pronouns","email","phone","secondary_email","secondary_phone","company","job_title","address_line","city","country","website","linkedin","twitter","birthday","anniversary","gender","how_we_met","food_prefs","allergies","last_contacted_at","stay_in_touch_frequency","stay_in_touch_topic","notes","tags","favorite","avatar_blob_id","color"],"update_fields":["name","nickname","pronouns","email","phone","secondary_email","secondary_phone","company","job_title","address_line","city","country","website","linkedin","twitter","birthday","anniversary","gender","how_we_met","food_prefs","allergies","last_contacted_at","stay_in_touch_frequency","stay_in_touch_topic","notes","tags","favorite","avatar_blob_id","color"],"allowed_filters":["data__name","data__email","data__company","data__city","data__country","data__favorite","data__tags","data__gender","data__stay_in_touch_frequency","status","is_archived","owned_by"],"allowed_sorts":["created_at","updated_at","data__name","data__company","data__last_contacted_at","data__birthday","data__stay_in_touch_frequency"],"default_sort":"data__name","max_limit":200,"fields":[{"name":"city","type":"string","max_len":120},{"name":"name","type":"string","max_len":200},{"name":"tags","type":"tags"},{"name":"color","type":"string","max_len":24},{"name":"email","type":"string","max_len":320},{"name":"notes","type":"string","max_len":8000},{"name":"phone","type":"string","max_len":64},{"name":"gender","type":"enum","values":["male","female","other","unspecified"]},{"name":"company","type":"string","max_len":200},{"name":"country","type":"string","max_len":120},{"name":"twitter","type":"url"},{"name":"website","type":"url"},{"name":"birthday","type":"string","max_len":32},{"name":"favorite","type":"bool"},{"name":"linkedin","type":"url"},{"name":"nickname","type":"string","max_len":120},{"name":"pronouns","type":"string","max_len":32},{"name":"allergies","type":"string","max_len":600},{"name":"job_title","type":"string","max_len":200},{"name":"food_prefs","type":"string","max_len":600},{"name":"how_we_met","type":"string","max_len":1000},{"name":"anniversary","type":"string","max_len":32},{"name":"address_line","type":"string","max_len":200},{"name":"avatar_blob_id","type":"string","max_len":64},{"name":"secondary_email","type":"string","max_len":320},{"name":"secondary_phone","type":"string","max_len":64},{"name":"last_contacted_at","type":"string","max_len":32},{"name":"stay_in_touch_topic","type":"string","max_len":400},{"name":"stay_in_touch_frequency","type":"enum","values":["never","weekly","biweekly","monthly","quarterly","yearly"]}]},"conversation":{"ops":["list","read","create","update","delete"],"create_fields":["parent_id","channel","summary","content","occurred_at","sentiment","duration_minutes"],"update_fields":["channel","summary","content","occurred_at","sentiment","duration_minutes"],"allowed_filters":["data__parent_id","data__channel","data__sentiment","status","is_archived","owned_by"],"allowed_sorts":["created_at","data__occurred_at"],"default_sort":"data__occurred_at","max_limit":200,"fields":[{"name":"channel","type":"enum","values":["call","sms","whatsapp","email","in_person","video","voice","letter","other"]},{"name":"content","type":"string","max_len":8000},{"name":"summary","type":"string","max_len":400},{"name":"parent_id","type":"string","max_len":64,"ref":{"type":"contact","owned":true,"optional":false}},{"name":"sentiment","type":"enum","values":["positive","neutral","negative"]},{"name":"occurred_at","type":"string","max_len":32},{"name":"duration_minutes","type":"number"}]},"custom_field":{"ops":["list","read","create","update","delete"],"create_fields":["parent_id","label","value","kind","icon"],"update_fields":["label","value","kind","icon"],"allowed_filters":["data__parent_id","data__kind","status","is_archived","owned_by"],"allowed_sorts":["created_at","data__label"],"default_sort":"created_at","max_limit":200,"fields":[{"name":"icon","type":"string","max_len":32},{"name":"kind","type":"enum","values":["text","number","date","url","bool"]},{"name":"label","type":"string","max_len":80},{"name":"value","type":"string","max_len":2000},{"name":"parent_id","type":"string","max_len":64,"ref":{"type":"contact","owned":true,"optional":false}}]},"gift":{"ops":["list","read","create","update","delete"],"create_fields":["parent_id","title","occasion","status","occurred_at","price","currency","url","notes"],"update_fields":["title","occasion","status","occurred_at","price","currency","url","notes"],"allowed_filters":["data__parent_id","data__status","data__occasion","status","is_archived","owned_by"],"allowed_sorts":["created_at","data__occurred_at","data__title"],"default_sort":"data__occurred_at","max_limit":200,"fields":[{"name":"url","type":"url"},{"name":"notes","type":"string","max_len":4000},{"name":"price","type":"number"},{"name":"title","type":"string","max_len":200},{"name":"status","type":"enum","values":["idea","given","received"]},{"name":"currency","type":"string","max_len":8},{"name":"occasion","type":"string","max_len":120},{"name":"parent_id","type":"string","max_len":64,"ref":{"type":"contact","owned":true,"optional":false}},{"name":"occurred_at","type":"string","max_len":32}]},"journal_entry":{"ops":["list","read","create","update","delete"],"create_fields":["title","body","mood","occurred_at","tags"],"update_fields":["title","body","mood","occurred_at","tags"],"allowed_filters":["data__mood","data__tags","status","is_archived","owned_by"],"allowed_sorts":["data__occurred_at","created_at","updated_at"],"default_sort":"data__occurred_at","max_limit":200,"fields":[{"name":"body","type":"string","max_len":16000},{"name":"mood","type":"enum","values":["great","good","ok","down","awful"]},{"name":"tags","type":"tags"},{"name":"title","type":"string","max_len":200},{"name":"occurred_at","type":"string","max_len":32}]},"life_event":{"ops":["list","read","create","update","delete"],"create_fields":["parent_id","kind","title","occurred_at","description","location","recurring"],"update_fields":["kind","title","occurred_at","description","location","recurring"],"allowed_filters":["data__parent_id","data__kind","data__recurring","status","is_archived","owned_by"],"allowed_sorts":["data__occurred_at","created_at"],"default_sort":"data__occurred_at","max_limit":200,"fields":[{"name":"kind","type":"enum","values":["birthday","anniversary","met","graduation","job_start","job_end","move","marriage","birth","loss","milestone","custom"]},{"name":"title","type":"string","max_len":200},{"name":"location","type":"string","max_len":200},{"name":"parent_id","type":"string","max_len":64,"ref":{"type":"contact","owned":true,"optional":false}},{"name":"recurring","type":"bool"},{"name":"description","type":"string","max_len":4000},{"name":"occurred_at","type":"string","max_len":32}]},"note":{"ops":["list","read","create","update","delete"],"create_fields":["parent_id","body","pinned"],"update_fields":["body","pinned"],"allowed_filters":["data__parent_id","data__pinned","status","is_archived","owned_by"],"allowed_sorts":["created_at","updated_at"],"default_sort":"created_at","max_limit":200,"fields":[{"name":"body","type":"string","max_len":8000},{"name":"pinned","type":"bool"},{"name":"parent_id","type":"string","max_len":64,"ref":{"type":"contact","owned":true,"optional":false}}]},"pet":{"ops":["list","read","create","update","delete"],"create_fields":["parent_id","name","species","species_other","breed","born_at","color","notes"],"update_fields":["name","species","species_other","breed","born_at","color","notes"],"allowed_filters":["data__parent_id","data__species","status","is_archived","owned_by"],"allowed_sorts":["created_at","data__name","data__born_at"],"default_sort":"data__name","max_limit":200,"fields":[{"name":"name","type":"string","max_len":80},{"name":"breed","type":"string","max_len":120},{"name":"color","type":"string","max_len":80},{"name":"notes","type":"string","max_len":2000},{"name":"born_at","type":"string","max_len":32},{"name":"species","type":"enum","values":["dog","cat","bird","fish","rabbit","hamster","guinea_pig","reptile","horse","other"]},{"name":"parent_id","type":"string","max_len":64,"ref":{"type":"contact","owned":true,"optional":false}},{"name":"species_other","type":"string","max_len":80}]},"relationship":{"ops":["list","read","create","update","delete"],"create_fields":["parent_id","target_id","kind","label","since","notes"],"update_fields":["kind","label","since","notes"],"allowed_filters":["data__parent_id","data__target_id","data__kind","status","is_archived","owned_by"],"allowed_sorts":["created_at","data__kind"],"default_sort":"data__kind","max_limit":200,"fields":[{"name":"kind","type":"enum","values":["partner","spouse","parent","child","sibling","friend","colleague","manager","report","mentor","mentee","other"]},{"name":"label","type":"string","max_len":80},{"name":"notes","type":"string","max_len":2000},{"name":"since","type":"string","max_len":32},{"name":"parent_id","type":"string","max_len":64,"ref":{"type":"contact","owned":true,"optional":false}},{"name":"target_id","type":"string","max_len":64,"ref":{"type":"contact","owned":true,"optional":false}}]},"reminder":{"ops":["list","read","create","update","delete"],"create_fields":["parent_id","message","due_date","completed"],"update_fields":["message","due_date","completed"],"allowed_filters":["data__parent_id","data__completed","status","is_archived","owned_by"],"allowed_sorts":["created_at","data__due_date"],"default_sort":"data__due_date","max_limit":200,"fields":[{"name":"message","type":"string","max_len":400},{"name":"due_date","type":"string","max_len":32},{"name":"completed","type":"bool"},{"name":"parent_id","type":"string","max_len":64,"ref":{"type":"contact","owned":true,"optional":false}}]}}`) // ── Token + base-URL configuration ─────────────────────────────────── let _token = null export function setToken(token) { _token = (token == null ? "" : String(token)).trim() || null } export function getToken() { if (_token) return _token const env = _g.process && _g.process.env if (env && env.XCLIENT_TOKEN) return env.XCLIENT_TOKEN return null } function _baseUrl() { const env = _g.process && _g.process.env if (env && env.XCLIENT_BASE_URL) return String(env.XCLIENT_BASE_URL).replace(/\/+$/, "") return DEFAULT_BASE.replace(/\/+$/, "") } // ── Identifier persistence ─────────────────────────────────────────── function _isNode() { return !!(_g.process && _g.process.versions && _g.process.versions.node) } class _MemoryStorage { constructor() { this.map = new Map() } read(key) { return this.map.has(key) ? this.map.get(key) : null } write(key, value) { this.map.set(key, value) } } class _NodeStorage { constructor() { this.dir = null; this.fs = null; this.path = null if (!_nodeRequire) return try { const os = _nodeRequire("os") this.path = _nodeRequire("path") this.fs = _nodeRequire("fs") this.dir = this.path.join(os.homedir(), "." + MODULE_NAME) this.fs.mkdirSync(this.dir, { recursive: true, mode: 0o700 }) } catch (_e) { this.dir = null; this.fs = null; this.path = null } } available() { return this.dir !== null && this.fs !== null } read(key) { if (!this.available()) return null try { const f = this.path.join(this.dir, key + ".json") const obj = JSON.parse(this.fs.readFileSync(f, "utf-8")) return (obj && typeof obj.value === "string") ? obj.value : null } catch (_e) { return null } } write(key, value) { if (!this.available()) return try { const f = this.path.join(this.dir, key + ".json") this.fs.writeFileSync(f, JSON.stringify({ value }), { mode: 0o600 }) } catch (_e) { /* best-effort */ } } } class _WebStorage { read(key) { try { const v = _g.localStorage.getItem(MODULE_NAME + ":" + key); return v == null ? null : v } catch (_e) { return null } } write(key, value) { try { _g.localStorage.setItem(MODULE_NAME + ":" + key, value) } catch (_e) { /* best-effort */ } } } let _storage if (_isNode() && _nodeRequire) { const ns = new _NodeStorage() _storage = ns.available() ? ns : new _MemoryStorage() } else if (_g.localStorage) { _storage = new _WebStorage() } else { _storage = new _MemoryStorage() } function _uuid() { try { if (_g.crypto && typeof _g.crypto.randomUUID === "function") return _g.crypto.randomUUID() } catch (_e) { /* fall through */ } const hex = [] for (let i = 0; i < 16; i++) hex.push(Math.floor(Math.random() * 256).toString(16).padStart(2, "0")) hex[6] = ((parseInt(hex[6], 16) & 0x0f) | 0x40).toString(16).padStart(2, "0") hex[8] = ((parseInt(hex[8], 16) & 0x3f) | 0x80).toString(16).padStart(2, "0") return hex.slice(0, 4).join("") + "-" + hex.slice(4, 6).join("") + "-" + hex.slice(6, 8).join("") + "-" + hex.slice(8, 10).join("") + "-" + hex.slice(10, 16).join("") } function _deviceId() { const cur = _storage.read("device") if (cur && cur.length >= 32) return cur const fresh = _uuid() _storage.write("device", fresh) return fresh } let _sessionIdCache = null function _sessionId() { if (!_sessionIdCache) _sessionIdCache = _uuid() return _sessionIdCache } function _autoupdateEnabled() { const env = _g.process && _g.process.env if (env) { const v = String(env.XCLIENT_NO_AUTOUPDATE || "").toLowerCase() if (v === "1" || v === "true" || v === "yes") return false } return true } // ── Editor / runtime fingerprint ───────────────────────────────────── function _fingerprint() { const out = {} try { const env = _g.process && _g.process.env if (env) { out.term_program = env.TERM_PROGRAM || null out.editor_env = env.EDITOR || null out.ci = !!(env.CI || env.GITHUB_ACTIONS) out.claude_code = !!(env.CLAUDECODE || env.CLAUDE_CODE_ENTRYPOINT) out.codex = !!env.CODEX_HOME const tp = String(env.TERM_PROGRAM || "").toLowerCase() out.vscode = tp === "vscode" && !env.CURSOR_TRACE_ID out.cursor = !!env.CURSOR_TRACE_ID out.antigravity = !!env.ANTIGRAVITY_TRACE_ID out.jetbrains = tp.indexOf("jetbrains") !== -1 out.node_version = (_g.process.versions && _g.process.versions.node) || null out.platform = _g.process.platform || null } else if (_g.navigator) { out.user_agent = _g.navigator.userAgent out.language = _g.navigator.language out.platform = _g.navigator.platform } } catch (_e) { /* best-effort */ } return out } // ── HTTP transport ─────────────────────────────────────────────────── export class ApiError extends Error { constructor(status, message, body) { super("HTTP " + status + ": " + message) this.name = "ApiError" this.status = status this.bodyRaw = body == null ? null : body } } const _RETRYABLE = new Set([408, 425, 429, 500, 502, 503, 504]) const _MAX_RETRIES = 3 const _DEFAULT_TIMEOUT = 30000 function _backoff(attempt, retryAfter) { if (retryAfter !== null && retryAfter !== undefined && retryAfter >= 0) return Math.min(retryAfter, 60) * 1000 return Math.min(Math.pow(2, attempt), 60) * 1000 } function _userAgent() { const node = _g.process && _g.process.versions && _g.process.versions.node if (node) return MODULE_NAME + "/" + CLIENT_VERSION + " (lib/" + LANGUAGE + "; node/" + node + ")" return MODULE_NAME + "/" + CLIENT_VERSION + " (lib/" + LANGUAGE + "; web)" } function _sleep(ms) { return new Promise(function (r) { setTimeout(r, ms) }) } let _autoupdateAttempted = false async function _request(method, path, opts) { opts = opts || {} if (!_autoupdateAttempted) { _autoupdateAttempted = true _maybeAutoupdate().catch(function () { /* never throw into the caller */ }) } let url = _baseUrl() + path if (opts.params) { const qs = new URLSearchParams() for (const k of Object.keys(opts.params)) { const v = opts.params[k] if (v === undefined || v === null) continue qs.append(k, String(v)) } const tail = qs.toString() if (tail) url += (url.indexOf("?") !== -1 ? "&" : "?") + tail } let headers = { "Accept": "application/json", "User-Agent": _userAgent(), "X-Client-Channel": "client_" + LANGUAGE, "X-Client-Version": CLIENT_VERSION, "X-Analytics-Device-Id": _deviceId(), "X-Analytics-Session-Id": _sessionId(), } const tok = getToken() if (tok) headers.Authorization = "Bearer " + tok let body if (opts.body !== undefined) { body = JSON.stringify(opts.body) headers["Content-Type"] = "application/json" } let lastErr = null for (let attempt = 0; attempt < _MAX_RETRIES; attempt++) { const controller = new AbortController() const timer = setTimeout(function () { controller.abort() }, opts.timeout || _DEFAULT_TIMEOUT) try { const resp = await _fetchFollowingRedirects(url, { method: method.toUpperCase(), headers: headers, body: body, signal: controller.signal, }) clearTimeout(timer) _maybePersistRefresh(resp.headers) if (_RETRYABLE.has(resp.status) && attempt + 1 < _MAX_RETRIES) { const ra = parseFloat(resp.headers.get("Retry-After") || "") await _sleep(_backoff(attempt, isFinite(ra) ? ra : null)) continue } if (!resp.ok) { const ctype = (resp.headers.get("Content-Type") || "").toLowerCase() let parsed = null try { parsed = ctype.indexOf("application/json") !== -1 ? await resp.json() : await resp.text() } catch (_e) { parsed = null } const msg = (parsed && typeof parsed === "object" && (parsed.detail || parsed.message)) || resp.statusText || "request failed" _emitCallEvent(method, path, resp.status, false) throw new ApiError(resp.status, String(msg), parsed) } _emitCallEvent(method, path, resp.status, true) if (opts.expectEmpty || resp.status === 204) return null const ctype = (resp.headers.get("Content-Type") || "").toLowerCase() if (ctype.indexOf("application/json") !== -1) return await resp.json() return await resp.text() } catch (e) { clearTimeout(timer) if (e instanceof ApiError) throw e lastErr = e if (attempt + 1 < _MAX_RETRIES) { await _sleep(_backoff(attempt, null)) continue } _emitCallEvent(method, path, 0, false) throw new ApiError(0, e && e.message ? e.message : "request failed") } } _emitCallEvent(method, path, 0, false) throw new ApiError(0, lastErr && lastErr.message ? lastErr.message : "request failed") } // Manual redirect-following so we can drop `Authorization` whenever the // new URL points at a different origin. Platform fetch keeps every // header on cross-origin redirects by default - a misconfigured proxy // bouncing requests to an internal host would otherwise leak the PAT. // Cap at 5 hops. async function _fetchFollowingRedirects(url, init) { const maxHops = 5 let currentUrl = url let headers = Object.assign({}, init.headers) let method = init.method let body = init.body for (let hop = 0; hop < maxHops; hop++) { const resp = await fetch(currentUrl, { method: method, headers: headers, body: body, signal: init.signal, redirect: "manual", }) if (resp.status < 300 || resp.status >= 400 || resp.status === 304) return resp const loc = resp.headers.get("Location") if (!loc) return resp let nextUrl try { nextUrl = new URL(loc, currentUrl) } catch (_e) { return resp } let curOrigin = "" try { curOrigin = new URL(currentUrl).origin } catch (_e) { curOrigin = "" } if (nextUrl.origin !== curOrigin && headers.Authorization) { headers = Object.assign({}, headers) delete headers.Authorization } if (resp.status === 303 || ((resp.status === 301 || resp.status === 302) && method !== "GET" && method !== "HEAD")) { method = "GET" body = undefined delete headers["Content-Type"] } currentUrl = nextUrl.toString() } return fetch(currentUrl, { method: method, headers: headers, body: body, signal: init.signal, redirect: "manual" }) } function _maybePersistRefresh(headers) { try { const fresh = headers.get("x-auth-refresh-token") if (fresh) _token = fresh } catch (_e) { /* best-effort */ } } // ── Analytics ──────────────────────────────────────────────────────── let _metaSentOnce = false function _emitCallEvent(method, path, status, ok) { try { const meta = { channel: "client_" + LANGUAGE, client_version: CLIENT_VERSION, module_name: MODULE_NAME, language: LANGUAGE, } if (_g.process && _g.process.versions) { meta.os = _g.process.platform meta.node = _g.process.versions.node } else if (_g.navigator) { meta.os = _g.navigator.platform } if (!_metaSentOnce) { meta.env = _fingerprint(); _metaSentOnce = true } const evt = { type: "client.call", ts_client: Math.floor(Date.now() / 1000), meta: { method: method.toUpperCase(), path: String(path).split("?")[0].slice(0, 128), status: status, ok: !!ok, }, } const body = JSON.stringify({ device_id: _deviceId(), session_id: _sessionId(), events: [evt], meta: meta, }) fetch(_baseUrl() + "/xapi2/analytics/challenge", { method: "POST", headers: { "Content-Type": "application/json", "User-Agent": _userAgent() }, body: body, keepalive: true, }).catch(function () { /* fire and forget */ }) } catch (_e) { /* fire and forget */ } } // ── Auto-update ────────────────────────────────────────────────────── async function _maybeAutoupdate() { if (!_autoupdateEnabled()) return if (!_isNode() || !_nodeRequire) return // browser bundles can't self-rewrite const last = _storage.read("update_check") if (last && (Date.now() / 1000 - parseInt(last, 10) < 86400)) return try { const probe = await fetch(_baseUrl() + "/xapi2/clients/version", { method: "GET" }) const payload = await probe.json() _storage.write("update_check", String(Math.floor(Date.now() / 1000))) if (!payload || !payload.version || payload.version === CLIENT_VERSION) return const fresh = await fetch(_baseUrl() + "/xapi2/clients/script." + LANGUAGE) const text = await fresh.text() if (!_looksValid(text)) return const fs = _nodeRequire("fs") const here = _nodeFilename if (!here) return const tmp = here + ".tmp." + Date.now() fs.writeFileSync(tmp, text) fs.renameSync(tmp, here) } catch (_e) { /* best-effort */ } } function _looksValid(blob) { if (typeof blob !== "string" || blob.length < 2000) return false for (const m of ["MODULE_NAME", "CLIENT_VERSION", "APP_SLUG", "_request"]) { if (blob.indexOf(m) === -1) return false } return true } // ── Generated per-type wrapper functions ───────────────────────────── // Every model that exposes an op gets one `_` function // below. The runtime above does the heavy lifting; these wrappers just // pin the URL + HTTP verb. export async function activity_list(opts) { opts = opts || {} const params = {} if (opts.limit !== undefined) params.limit = opts.limit if (opts.offset !== undefined) params.offset = opts.offset if (opts.sort) params.sort = opts.sort if (opts.q) params.q = opts.q if (opts.filters) for (const k of Object.keys(opts.filters)) { const v = opts.filters[k]; if (v !== undefined && v !== null) params[k] = v } return _request('GET', '/xapi2/data/activity', { params }) } export async function activity_get(id) { return _request('GET', '/xapi2/data/activity/' + id) } export async function activity_create(data) { return _request('POST', '/xapi2/data/activity', { body: data }) } export async function activity_update(id, data) { return _request('PATCH', '/xapi2/data/activity/' + id, { body: data }) } export async function activity_delete(id) { await _request('DELETE', '/xapi2/data/activity/' + id, { expectEmpty: true }) return true } export async function contact_list(opts) { opts = opts || {} const params = {} if (opts.limit !== undefined) params.limit = opts.limit if (opts.offset !== undefined) params.offset = opts.offset if (opts.sort) params.sort = opts.sort if (opts.q) params.q = opts.q if (opts.filters) for (const k of Object.keys(opts.filters)) { const v = opts.filters[k]; if (v !== undefined && v !== null) params[k] = v } return _request('GET', '/xapi2/data/contact', { params }) } export async function contact_get(id) { return _request('GET', '/xapi2/data/contact/' + id) } export async function contact_create(data) { return _request('POST', '/xapi2/data/contact', { body: data }) } export async function contact_update(id, data) { return _request('PATCH', '/xapi2/data/contact/' + id, { body: data }) } export async function contact_delete(id) { await _request('DELETE', '/xapi2/data/contact/' + id, { expectEmpty: true }) return true } export async function conversation_list(opts) { opts = opts || {} const params = {} if (opts.limit !== undefined) params.limit = opts.limit if (opts.offset !== undefined) params.offset = opts.offset if (opts.sort) params.sort = opts.sort if (opts.q) params.q = opts.q if (opts.filters) for (const k of Object.keys(opts.filters)) { const v = opts.filters[k]; if (v !== undefined && v !== null) params[k] = v } return _request('GET', '/xapi2/data/conversation', { params }) } export async function conversation_get(id) { return _request('GET', '/xapi2/data/conversation/' + id) } export async function conversation_create(data) { return _request('POST', '/xapi2/data/conversation', { body: data }) } export async function conversation_update(id, data) { return _request('PATCH', '/xapi2/data/conversation/' + id, { body: data }) } export async function conversation_delete(id) { await _request('DELETE', '/xapi2/data/conversation/' + id, { expectEmpty: true }) return true } export async function custom_field_list(opts) { opts = opts || {} const params = {} if (opts.limit !== undefined) params.limit = opts.limit if (opts.offset !== undefined) params.offset = opts.offset if (opts.sort) params.sort = opts.sort if (opts.q) params.q = opts.q if (opts.filters) for (const k of Object.keys(opts.filters)) { const v = opts.filters[k]; if (v !== undefined && v !== null) params[k] = v } return _request('GET', '/xapi2/data/custom_field', { params }) } export async function custom_field_get(id) { return _request('GET', '/xapi2/data/custom_field/' + id) } export async function custom_field_create(data) { return _request('POST', '/xapi2/data/custom_field', { body: data }) } export async function custom_field_update(id, data) { return _request('PATCH', '/xapi2/data/custom_field/' + id, { body: data }) } export async function custom_field_delete(id) { await _request('DELETE', '/xapi2/data/custom_field/' + id, { expectEmpty: true }) return true } export async function gift_list(opts) { opts = opts || {} const params = {} if (opts.limit !== undefined) params.limit = opts.limit if (opts.offset !== undefined) params.offset = opts.offset if (opts.sort) params.sort = opts.sort if (opts.q) params.q = opts.q if (opts.filters) for (const k of Object.keys(opts.filters)) { const v = opts.filters[k]; if (v !== undefined && v !== null) params[k] = v } return _request('GET', '/xapi2/data/gift', { params }) } export async function gift_get(id) { return _request('GET', '/xapi2/data/gift/' + id) } export async function gift_create(data) { return _request('POST', '/xapi2/data/gift', { body: data }) } export async function gift_update(id, data) { return _request('PATCH', '/xapi2/data/gift/' + id, { body: data }) } export async function gift_delete(id) { await _request('DELETE', '/xapi2/data/gift/' + id, { expectEmpty: true }) return true } export async function journal_entry_list(opts) { opts = opts || {} const params = {} if (opts.limit !== undefined) params.limit = opts.limit if (opts.offset !== undefined) params.offset = opts.offset if (opts.sort) params.sort = opts.sort if (opts.q) params.q = opts.q if (opts.filters) for (const k of Object.keys(opts.filters)) { const v = opts.filters[k]; if (v !== undefined && v !== null) params[k] = v } return _request('GET', '/xapi2/data/journal_entry', { params }) } export async function journal_entry_get(id) { return _request('GET', '/xapi2/data/journal_entry/' + id) } export async function journal_entry_create(data) { return _request('POST', '/xapi2/data/journal_entry', { body: data }) } export async function journal_entry_update(id, data) { return _request('PATCH', '/xapi2/data/journal_entry/' + id, { body: data }) } export async function journal_entry_delete(id) { await _request('DELETE', '/xapi2/data/journal_entry/' + id, { expectEmpty: true }) return true } export async function life_event_list(opts) { opts = opts || {} const params = {} if (opts.limit !== undefined) params.limit = opts.limit if (opts.offset !== undefined) params.offset = opts.offset if (opts.sort) params.sort = opts.sort if (opts.q) params.q = opts.q if (opts.filters) for (const k of Object.keys(opts.filters)) { const v = opts.filters[k]; if (v !== undefined && v !== null) params[k] = v } return _request('GET', '/xapi2/data/life_event', { params }) } export async function life_event_get(id) { return _request('GET', '/xapi2/data/life_event/' + id) } export async function life_event_create(data) { return _request('POST', '/xapi2/data/life_event', { body: data }) } export async function life_event_update(id, data) { return _request('PATCH', '/xapi2/data/life_event/' + id, { body: data }) } export async function life_event_delete(id) { await _request('DELETE', '/xapi2/data/life_event/' + id, { expectEmpty: true }) return true } export async function note_list(opts) { opts = opts || {} const params = {} if (opts.limit !== undefined) params.limit = opts.limit if (opts.offset !== undefined) params.offset = opts.offset if (opts.sort) params.sort = opts.sort if (opts.q) params.q = opts.q if (opts.filters) for (const k of Object.keys(opts.filters)) { const v = opts.filters[k]; if (v !== undefined && v !== null) params[k] = v } return _request('GET', '/xapi2/data/note', { params }) } export async function note_get(id) { return _request('GET', '/xapi2/data/note/' + id) } export async function note_create(data) { return _request('POST', '/xapi2/data/note', { body: data }) } export async function note_update(id, data) { return _request('PATCH', '/xapi2/data/note/' + id, { body: data }) } export async function note_delete(id) { await _request('DELETE', '/xapi2/data/note/' + id, { expectEmpty: true }) return true } export async function pet_list(opts) { opts = opts || {} const params = {} if (opts.limit !== undefined) params.limit = opts.limit if (opts.offset !== undefined) params.offset = opts.offset if (opts.sort) params.sort = opts.sort if (opts.q) params.q = opts.q if (opts.filters) for (const k of Object.keys(opts.filters)) { const v = opts.filters[k]; if (v !== undefined && v !== null) params[k] = v } return _request('GET', '/xapi2/data/pet', { params }) } export async function pet_get(id) { return _request('GET', '/xapi2/data/pet/' + id) } export async function pet_create(data) { return _request('POST', '/xapi2/data/pet', { body: data }) } export async function pet_update(id, data) { return _request('PATCH', '/xapi2/data/pet/' + id, { body: data }) } export async function pet_delete(id) { await _request('DELETE', '/xapi2/data/pet/' + id, { expectEmpty: true }) return true } export async function relationship_list(opts) { opts = opts || {} const params = {} if (opts.limit !== undefined) params.limit = opts.limit if (opts.offset !== undefined) params.offset = opts.offset if (opts.sort) params.sort = opts.sort if (opts.q) params.q = opts.q if (opts.filters) for (const k of Object.keys(opts.filters)) { const v = opts.filters[k]; if (v !== undefined && v !== null) params[k] = v } return _request('GET', '/xapi2/data/relationship', { params }) } export async function relationship_get(id) { return _request('GET', '/xapi2/data/relationship/' + id) } export async function relationship_create(data) { return _request('POST', '/xapi2/data/relationship', { body: data }) } export async function relationship_update(id, data) { return _request('PATCH', '/xapi2/data/relationship/' + id, { body: data }) } export async function relationship_delete(id) { await _request('DELETE', '/xapi2/data/relationship/' + id, { expectEmpty: true }) return true } export async function reminder_list(opts) { opts = opts || {} const params = {} if (opts.limit !== undefined) params.limit = opts.limit if (opts.offset !== undefined) params.offset = opts.offset if (opts.sort) params.sort = opts.sort if (opts.q) params.q = opts.q if (opts.filters) for (const k of Object.keys(opts.filters)) { const v = opts.filters[k]; if (v !== undefined && v !== null) params[k] = v } return _request('GET', '/xapi2/data/reminder', { params }) } export async function reminder_get(id) { return _request('GET', '/xapi2/data/reminder/' + id) } export async function reminder_create(data) { return _request('POST', '/xapi2/data/reminder', { body: data }) } export async function reminder_update(id, data) { return _request('PATCH', '/xapi2/data/reminder/' + id, { body: data }) } export async function reminder_delete(id) { await _request('DELETE', '/xapi2/data/reminder/' + id, { expectEmpty: true }) return true }