@playaos/api-client 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -311,6 +311,21 @@ interface RescheduleInput {
311
311
  interviewerId?: string;
312
312
  timezone?: string;
313
313
  }
314
+ interface CalendarStatus {
315
+ connected: boolean;
316
+ provider: string;
317
+ calendarId: string | null;
318
+ calendarName?: string | null;
319
+ }
320
+ interface GoogleCalendar {
321
+ id: string;
322
+ summary: string;
323
+ primary?: boolean;
324
+ }
325
+ interface SelectCalendarInput {
326
+ calendarId: string;
327
+ calendarName?: string;
328
+ }
314
329
 
315
330
  interface ClientOptions {
316
331
  /** Base URL for authenticated /api/v1 routes, e.g. https://api.playaos.app */
@@ -559,6 +574,34 @@ declare class PlayaOSClient {
559
574
  signal?: AbortSignal;
560
575
  }) => Promise<SetAvailabilityResponse>;
561
576
  };
577
+ calendar: {
578
+ /** Get Google Calendar connection status for an interviewer (PLA-726). Requires admin Bearer. */
579
+ status: (interviewerId: string, opts: {
580
+ accessToken: string;
581
+ signal?: AbortSignal;
582
+ }) => Promise<CalendarStatus>;
583
+ /** List available Google Calendars (PLA-726). Requires admin Bearer. */
584
+ listCalendars: (interviewerId: string, opts: {
585
+ accessToken: string;
586
+ signal?: AbortSignal;
587
+ }) => Promise<{
588
+ calendars: GoogleCalendar[];
589
+ }>;
590
+ /** Select which Google Calendar to use (PLA-726). Requires admin Bearer. */
591
+ select: (interviewerId: string, payload: SelectCalendarInput, opts: {
592
+ accessToken: string;
593
+ signal?: AbortSignal;
594
+ }) => Promise<{
595
+ calendarId: string;
596
+ }>;
597
+ /** Disconnect Google Calendar from interviewer (PLA-726). Requires admin Bearer. */
598
+ disconnect: (interviewerId: string, opts: {
599
+ accessToken: string;
600
+ signal?: AbortSignal;
601
+ }) => Promise<{
602
+ disconnected: boolean;
603
+ }>;
604
+ };
562
605
  bookingTokens: {
563
606
  /** Create a booking token for an application's interview link (PLA-714). Requires admin Bearer token. */
564
607
  create: (payload: CreateBookingTokenInput, opts: {
package/dist/index.js CHANGED
@@ -324,6 +324,46 @@ var PlayaOSClient = class {
324
324
  opts.signal
325
325
  )
326
326
  },
327
+ calendar: {
328
+ /** Get Google Calendar connection status for an interviewer (PLA-726). Requires admin Bearer. */
329
+ status: (interviewerId, opts) => adminEmbed(
330
+ "GET",
331
+ buildEmbedUrl(this.embedBaseUrl, `/admin/scheduling/calendar/${encodeURIComponent(interviewerId)}/status`),
332
+ opts.accessToken,
333
+ void 0,
334
+ opts.signal
335
+ ),
336
+ /** List available Google Calendars (PLA-726). Requires admin Bearer. */
337
+ listCalendars: (interviewerId, opts) => adminEmbed(
338
+ "GET",
339
+ buildEmbedUrl(
340
+ this.embedBaseUrl,
341
+ `/admin/scheduling/calendar/${encodeURIComponent(interviewerId)}/calendars`
342
+ ),
343
+ opts.accessToken,
344
+ void 0,
345
+ opts.signal
346
+ ),
347
+ /** Select which Google Calendar to use (PLA-726). Requires admin Bearer. */
348
+ select: (interviewerId, payload, opts) => adminEmbed(
349
+ "PUT",
350
+ buildEmbedUrl(this.embedBaseUrl, `/admin/scheduling/calendar/${encodeURIComponent(interviewerId)}/select`),
351
+ opts.accessToken,
352
+ payload,
353
+ opts.signal
354
+ ),
355
+ /** Disconnect Google Calendar from interviewer (PLA-726). Requires admin Bearer. */
356
+ disconnect: (interviewerId, opts) => adminEmbed(
357
+ "POST",
358
+ buildEmbedUrl(
359
+ this.embedBaseUrl,
360
+ `/admin/scheduling/calendar/${encodeURIComponent(interviewerId)}/disconnect`
361
+ ),
362
+ opts.accessToken,
363
+ void 0,
364
+ opts.signal
365
+ )
366
+ },
327
367
  bookingTokens: {
328
368
  /** Create a booking token for an application's interview link (PLA-714). Requires admin Bearer token. */
329
369
  create: (payload, opts) => adminEmbed(
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/error.ts","../src/client.ts","../src/exchange.ts"],"sourcesContent":["export class ApiClientError extends Error {\n constructor(\n public readonly status: number,\n public readonly code: string,\n message: string,\n ) {\n super(message);\n this.name = \"ApiClientError\";\n }\n}\n\nexport async function parseError(res: Response): Promise<ApiClientError> {\n try {\n const body = (await res.json()) as { error?: string; code?: string };\n return new ApiClientError(res.status, body.code ?? \"UNKNOWN\", body.error ?? res.statusText);\n } catch {\n return new ApiClientError(res.status, \"UNKNOWN\", res.statusText);\n }\n}\n","import { type ApiClientError, parseError } from \"./error.js\";\nimport type {\n AnnouncementSendPayload,\n AnnouncementSendResponse,\n Application,\n ApplicationAnnotations,\n ApplicationCreatePayload,\n ApplicationCreateResponse,\n ApplicationHistoryResponse,\n ApplicationNote,\n ApplicationScore,\n ApplicationStatus,\n ApplicationTransitionPayload,\n ApplicationTransitionResponse,\n BookingToken,\n BookSlotInput,\n BookSlotResponse,\n CreateBookingTokenInput,\n DuesCreatePayload,\n DuesCreateResponse,\n DuesStatus,\n DuesUpdatePayload,\n DuesUpdateResponse,\n Member,\n MemberCreatePayload,\n MemberCreateResponse,\n MemberDeactivateResponse,\n MemberRole,\n MemberUpdatePayload,\n MemberUpdateResponse,\n OrgConfig,\n OrgUpdatePayload,\n OrgUpdateResponse,\n PaymentPageResponse,\n RescheduleInput,\n SetAvailabilityInput,\n SetAvailabilityResponse,\n Shift,\n Waiver,\n WaiverSignPayload,\n WaiverSignResponse,\n WaiverStatus,\n} from \"./types.js\";\n\nexport type { ApiClientError };\n\ninterface ClientOptions {\n /** Base URL for authenticated /api/v1 routes, e.g. https://api.playaos.app */\n baseUrl: string;\n /** Optional base URL for /api/embed/v1 routes when they live on a different host. */\n embedBaseUrl?: string;\n /** API key in the format pk_live_* */\n apiKey: string;\n}\n\nfunction buildUrl(base: string, path: string, params?: Record<string, string | number | boolean | undefined>): string {\n const url = new URL(`${base}/api/v1${path}`);\n if (params) {\n for (const [k, v] of Object.entries(params)) {\n // Skip undefined and false booleans — z.coerce.boolean() on the server uses Boolean(),\n // which treats any non-empty string (including \"false\") as true. Omitting a false boolean\n // param has the same effect as the server default (unfiltered).\n if (v !== undefined && v !== false) url.searchParams.set(k, String(v));\n }\n }\n return url.toString();\n}\n\nfunction buildEmbedUrl(base: string, path: string): string {\n return `${base}/api/embed/v1${path}`;\n}\n\nasync function getEmbed<T>(url: string, campKey: string, signal?: AbortSignal): Promise<T> {\n const res = await fetch(url, {\n headers: { \"X-Camp-Key\": campKey },\n signal,\n });\n if (!res.ok) throw await parseError(res);\n return res.json() as Promise<T>;\n}\n\nasync function getEmbedAuthed<T>(\n url: string,\n campKey: string,\n opts?: { accessToken?: string; signal?: AbortSignal },\n): Promise<T> {\n const headers: Record<string, string> = { \"X-Camp-Key\": campKey };\n if (opts?.accessToken) headers.Authorization = `Bearer ${opts.accessToken}`;\n const res = await fetch(url, { headers, signal: opts?.signal });\n if (!res.ok) throw await parseError(res);\n return res.json() as Promise<T>;\n}\n\nasync function request<T>(url: string, apiKey: string, signal?: AbortSignal): Promise<T> {\n const res = await fetch(url, {\n headers: { Authorization: `Bearer ${apiKey}` },\n signal,\n });\n if (!res.ok) throw await parseError(res);\n return res.json() as Promise<T>;\n}\n\nasync function post<T>(url: string, apiKey: string, body: unknown, signal?: AbortSignal): Promise<T> {\n const res = await fetch(url, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${apiKey}`, \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n signal,\n });\n if (!res.ok) throw await parseError(res);\n return res.json() as Promise<T>;\n}\n\nasync function postEmbed<T>(\n url: string,\n campKey: string,\n body: unknown,\n opts?: { accessToken?: string; signal?: AbortSignal },\n): Promise<T> {\n const headers: Record<string, string> = {\n \"X-Camp-Key\": campKey,\n \"Content-Type\": \"application/json\",\n };\n if (opts?.accessToken) headers.Authorization = `Bearer ${opts.accessToken}`;\n const res = await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n signal: opts?.signal,\n });\n if (!res.ok) throw await parseError(res);\n return res.json() as Promise<T>;\n}\n\nasync function putEmbed<T>(\n url: string,\n campKey: string,\n body: unknown,\n opts?: { accessToken?: string; signal?: AbortSignal },\n): Promise<T> {\n const headers: Record<string, string> = {\n \"X-Camp-Key\": campKey,\n \"Content-Type\": \"application/json\",\n };\n if (opts?.accessToken) headers.Authorization = `Bearer ${opts.accessToken}`;\n const res = await fetch(url, {\n method: \"PUT\",\n headers,\n body: JSON.stringify(body),\n signal: opts?.signal,\n });\n if (!res.ok) throw await parseError(res);\n return res.json() as Promise<T>;\n}\n\nasync function deleteEmbed<T>(\n url: string,\n campKey: string,\n opts?: { accessToken?: string; signal?: AbortSignal },\n): Promise<T> {\n const headers: Record<string, string> = { \"X-Camp-Key\": campKey };\n if (opts?.accessToken) headers.Authorization = `Bearer ${opts.accessToken}`;\n const res = await fetch(url, { method: \"DELETE\", headers, signal: opts?.signal });\n if (!res.ok) throw await parseError(res);\n return res.json() as Promise<T>;\n}\n\n/**\n * Bearer-only helper for /api/embed/v1/admin/* (PLA-489). The admin token is\n * the sole credential (no X-Camp-Key — orgId comes from the JWT claims\n * server-side). `method` can be GET, POST, PATCH, or PUT; `body` is optional\n * (omitted for GET reads like getAnnotations).\n */\nasync function adminEmbed<T>(\n method: \"GET\" | \"POST\" | \"PATCH\" | \"PUT\",\n url: string,\n accessToken: string,\n body?: unknown,\n signal?: AbortSignal,\n): Promise<T> {\n const headers: Record<string, string> = { Authorization: `Bearer ${accessToken}` };\n const init: RequestInit = { method, headers, signal };\n if (body !== undefined) {\n headers[\"Content-Type\"] = \"application/json\";\n init.body = JSON.stringify(body);\n }\n const res = await fetch(url, init);\n if (!res.ok) throw await parseError(res);\n return res.json() as Promise<T>;\n}\n\nexport class PlayaOSClient {\n private readonly baseUrl: string;\n private readonly embedBaseUrl: string;\n private readonly apiKey: string;\n\n constructor(opts: ClientOptions) {\n this.baseUrl = opts.baseUrl.replace(/\\/+$/, \"\");\n this.embedBaseUrl = (opts.embedBaseUrl ?? opts.baseUrl).replace(/\\/+$/, \"\");\n this.apiKey = opts.apiKey;\n }\n\n readonly members = {\n list: (params?: { role?: MemberRole; status?: string }, opts?: { signal?: AbortSignal }): Promise<Member[]> =>\n request(buildUrl(this.baseUrl, \"/members\", params), this.apiKey, opts?.signal),\n\n get: (id: string, opts?: { signal?: AbortSignal }): Promise<Member> =>\n request(buildUrl(this.baseUrl, `/members/${encodeURIComponent(id)}`), this.apiKey, opts?.signal),\n\n /** Member-self profile update (PLA-700). Requires camp key + member Bearer token. */\n selfUpdate: (\n payload: {\n bio?: string | null;\n playaName?: string | null;\n socialMedia?: Record<string, unknown> | null;\n showSocialsInDirectory?: boolean;\n phone?: string | null;\n emergencyContactName?: string | null;\n emergencyContactRelationship?: string | null;\n emergencyContactPhone?: string | null;\n profilePhotoPath?: string | null;\n yearJoined?: number | null;\n },\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<{ profileId: string }> =>\n putEmbed(buildEmbedUrl(this.embedBaseUrl, \"/members/self\"), this.apiKey, payload, opts),\n\n /** Member-self shift signup + cancel (PLA-705). Requires camp key + member Bearer. */\n shifts: {\n signup: (\n payload: { shiftId: string; role?: string },\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<{ signupId: string; waitlisted: boolean }> =>\n putEmbed(buildEmbedUrl(this.embedBaseUrl, \"/shifts/signup\"), this.apiKey, payload, opts),\n cancel: (\n signupId: string,\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<{ canceled: boolean; promotedSignupId: string | null }> =>\n deleteEmbed(\n buildEmbedUrl(this.embedBaseUrl, `/shifts/signups/${encodeURIComponent(signupId)}`),\n this.apiKey,\n opts,\n ),\n },\n };\n\n readonly applications = {\n list: (\n params?: { status?: ApplicationStatus; year?: number },\n opts?: { signal?: AbortSignal },\n ): Promise<Application[]> => request(buildUrl(this.baseUrl, \"/applications\", params), this.apiKey, opts?.signal),\n\n // Anonymous external-camp submission against POST /api/embed/v1/applications\n // (PLA-481). Uses the X-Camp-Key header rather than Bearer auth. Pass\n // `accessToken` to additionally send a PlayaOS IdP JWT (PLA-573 path) so\n // the server trusts the verified profile claim and skips the email-based\n // bootstrap.\n create: (\n payload: ApplicationCreatePayload,\n opts?: { accessToken?: string; signal?: AbortSignal },\n ): Promise<ApplicationCreateResponse> =>\n postEmbed(buildEmbedUrl(this.embedBaseUrl, \"/applications\"), this.apiKey, payload, opts),\n };\n\n readonly waivers = {\n /** Get the active waiver for an org for the current year. */\n active: (orgId: string, opts?: { signal?: AbortSignal }): Promise<Waiver> =>\n getEmbed(buildEmbedUrl(this.embedBaseUrl, `/waivers/${orgId}/active`), this.apiKey, opts?.signal),\n\n /** Sign a waiver. Requires X-Camp-Key; optional accessToken for Bearer path. */\n sign: (\n payload: WaiverSignPayload,\n opts?: { accessToken?: string; signal?: AbortSignal },\n ): Promise<WaiverSignResponse> =>\n postEmbed(buildEmbedUrl(this.embedBaseUrl, \"/waivers/sign\"), this.apiKey, payload, opts),\n\n /** Has this applicant/member signed the active waiver? Anchor: applicationId query or Bearer accessToken. */\n status: (\n orgId: string,\n opts?: { applicationId?: string; accessToken?: string; signal?: AbortSignal },\n ): Promise<WaiverStatus> => {\n const query = opts?.applicationId ? `?applicationId=${encodeURIComponent(opts.applicationId)}` : \"\";\n return getEmbedAuthed(buildEmbedUrl(this.embedBaseUrl, `/waivers/${orgId}/status${query}`), this.apiKey, opts);\n },\n\n /** Get a short-lived download URL for a completed signature's PDF. Anchor: applicationId query or Bearer. */\n signedPdf: (\n orgId: string,\n signatureId: string,\n opts?: { applicationId?: string; accessToken?: string; signal?: AbortSignal },\n ): Promise<{ url: string }> => {\n const query = opts?.applicationId ? `?applicationId=${encodeURIComponent(opts.applicationId)}` : \"\";\n return getEmbedAuthed(\n buildEmbedUrl(this.embedBaseUrl, `/waivers/${orgId}/signatures/${encodeURIComponent(signatureId)}/pdf${query}`),\n this.apiKey,\n opts,\n );\n },\n };\n\n readonly dues = {\n list: (params?: { userId?: string; year?: number }, opts?: { signal?: AbortSignal }): Promise<DuesStatus[]> =>\n request(buildUrl(this.baseUrl, \"/dues\", params), this.apiKey, opts?.signal),\n };\n\n readonly shifts = {\n list: (\n params?: { year?: number; fromDate?: string; toDate?: string; publishedOnly?: boolean },\n opts?: { signal?: AbortSignal },\n ): Promise<Shift[]> => request(buildUrl(this.baseUrl, \"/shifts\", params), this.apiKey, opts?.signal),\n };\n\n readonly org = {\n get: (opts?: { signal?: AbortSignal }): Promise<OrgConfig> =>\n request(buildUrl(this.baseUrl, \"/org\"), this.apiKey, opts?.signal),\n };\n\n readonly payments = {\n page: (\n memberId: string,\n duesCollectionId?: string,\n opts?: { signal?: AbortSignal },\n ): Promise<PaymentPageResponse> =>\n post(buildUrl(this.baseUrl, \"/payments/page\"), this.apiKey, { memberId, duesCollectionId }, opts?.signal),\n };\n\n // Admin write APIs (PLA-489). Each method requires `accessToken` — a Supabase\n // JWT for a camp admin/super_admin. The org boundary is enforced server-side\n // from the JWT claims; these endpoints do not use the X-Camp-Key.\n readonly admin = {\n applications: {\n /** Get application audit timeline (PLA-712). Requires admin Bearer token. */\n history: (id: string, opts: { accessToken: string; signal?: AbortSignal }): Promise<ApplicationHistoryResponse> =>\n adminEmbed(\n \"GET\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/applications/${encodeURIComponent(id)}/history`),\n opts.accessToken,\n undefined,\n opts.signal,\n ),\n transition: (\n id: string,\n payload: ApplicationTransitionPayload,\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<ApplicationTransitionResponse> =>\n adminEmbed(\n \"PATCH\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/applications/${encodeURIComponent(id)}`),\n opts.accessToken,\n payload,\n opts.signal,\n ),\n getAnnotations: (\n id: string,\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<ApplicationAnnotations> =>\n adminEmbed(\n \"GET\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/applications/${encodeURIComponent(id)}/annotations`),\n opts.accessToken,\n undefined,\n opts.signal,\n ),\n addNote: (\n id: string,\n payload: { body: string },\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<ApplicationNote> =>\n adminEmbed(\n \"POST\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/applications/${encodeURIComponent(id)}/notes`),\n opts.accessToken,\n payload,\n opts.signal,\n ),\n setTags: (\n id: string,\n payload: { tags: string[] },\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<string[]> =>\n adminEmbed(\n \"PUT\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/applications/${encodeURIComponent(id)}/tags`),\n opts.accessToken,\n payload,\n opts.signal,\n ),\n setScore: (\n id: string,\n payload: { value: number },\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<ApplicationScore> =>\n adminEmbed(\n \"PUT\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/applications/${encodeURIComponent(id)}/scores`),\n opts.accessToken,\n payload,\n opts.signal,\n ),\n },\n givebutter: {\n campaigns: {\n list: (opts: { accessToken: string; signal?: AbortSignal }): Promise<unknown[]> =>\n adminEmbed(\n \"GET\",\n buildEmbedUrl(this.embedBaseUrl, \"/admin/givebutter/campaigns\"),\n opts.accessToken,\n undefined,\n opts.signal,\n ),\n discountCodes: {\n list: (campaignId: number, opts: { accessToken: string; signal?: AbortSignal }): Promise<unknown[]> =>\n adminEmbed(\n \"GET\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/givebutter/campaigns/${campaignId}/discount-codes`),\n opts.accessToken,\n undefined,\n opts.signal,\n ),\n create: (\n campaignId: number,\n payload: { code: string; type: string; amount: number; active?: boolean },\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<unknown> =>\n adminEmbed(\n \"POST\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/givebutter/campaigns/${campaignId}/discount-codes`),\n opts.accessToken,\n payload,\n opts.signal,\n ),\n },\n tickets: {\n create: (\n campaignId: number,\n payload: { name: string; price: number; totalQuantity?: number },\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<unknown> =>\n adminEmbed(\n \"POST\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/givebutter/campaigns/${campaignId}/tickets`),\n opts.accessToken,\n payload,\n opts.signal,\n ),\n },\n },\n },\n members: {\n create: (\n payload: MemberCreatePayload,\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<MemberCreateResponse> =>\n adminEmbed(\"POST\", buildEmbedUrl(this.embedBaseUrl, \"/admin/members\"), opts.accessToken, payload, opts.signal),\n\n update: (\n id: string,\n patch: MemberUpdatePayload,\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<MemberUpdateResponse> =>\n adminEmbed(\n \"PATCH\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/members/${encodeURIComponent(id)}`),\n opts.accessToken,\n patch,\n opts.signal,\n ),\n\n deactivate: (\n id: string,\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<MemberDeactivateResponse> =>\n adminEmbed(\n \"PATCH\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/members/${encodeURIComponent(id)}`),\n opts.accessToken,\n { status: \"inactive\" },\n opts.signal,\n ),\n },\n announcements: {\n /** Send an email blast to camp members (PLA-706). Requires admin Bearer token. */\n send: (\n payload: AnnouncementSendPayload,\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<AnnouncementSendResponse> =>\n adminEmbed(\n \"POST\",\n buildEmbedUrl(this.embedBaseUrl, \"/admin/announcements/send\"),\n opts.accessToken,\n payload,\n opts.signal,\n ),\n },\n dues: {\n /** Create a manual dues/payment record (PLA-708). Requires admin Bearer token. */\n create: (\n payload: DuesCreatePayload,\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<DuesCreateResponse> =>\n adminEmbed(\"POST\", buildEmbedUrl(this.embedBaseUrl, \"/admin/dues\"), opts.accessToken, payload, opts.signal),\n\n /** Update a dues/payment record (PLA-708). Requires admin Bearer token. */\n update: (\n id: string,\n payload: DuesUpdatePayload,\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<DuesUpdateResponse> =>\n adminEmbed(\n \"PATCH\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/dues/${encodeURIComponent(id)}`),\n opts.accessToken,\n payload,\n opts.signal,\n ),\n },\n org: {\n /** Update camp configuration settings (PLA-709). Requires admin Bearer token. */\n update: (\n payload: OrgUpdatePayload,\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<OrgUpdateResponse> =>\n adminEmbed(\"PATCH\", buildEmbedUrl(this.embedBaseUrl, \"/admin/org\"), opts.accessToken, payload, opts.signal),\n },\n scheduling: {\n availability: {\n /** Get interview availability for an interviewer (PLA-713). Requires admin Bearer token. */\n get: (\n interviewerId: string,\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<SetAvailabilityResponse> =>\n adminEmbed(\n \"GET\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/scheduling/availability/${encodeURIComponent(interviewerId)}`),\n opts.accessToken,\n undefined,\n opts.signal,\n ),\n /** Set interview availability for an interviewer (PLA-713). Requires admin Bearer token. */\n set: (\n interviewerId: string,\n payload: SetAvailabilityInput,\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<SetAvailabilityResponse> =>\n adminEmbed(\n \"PUT\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/scheduling/availability/${encodeURIComponent(interviewerId)}`),\n opts.accessToken,\n payload,\n opts.signal,\n ),\n },\n bookingTokens: {\n /** Create a booking token for an application's interview link (PLA-714). Requires admin Bearer token. */\n create: (\n payload: CreateBookingTokenInput,\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<BookingToken> =>\n adminEmbed(\n \"POST\",\n buildEmbedUrl(this.embedBaseUrl, \"/admin/booking-tokens\"),\n opts.accessToken,\n payload,\n opts.signal,\n ),\n /** Get an existing booking token for an application (PLA-714). Requires admin Bearer token. */\n get: (applicationId: string, opts: { accessToken: string; signal?: AbortSignal }): Promise<BookingToken> =>\n adminEmbed(\n \"GET\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/booking-tokens/${encodeURIComponent(applicationId)}`),\n opts.accessToken,\n undefined,\n opts.signal,\n ),\n },\n },\n };\n\n // Public embed-booking endpoints (PLA-714). No auth — these are the\n // applicant-facing schedule surface using the hashed booking token.\n readonly schedule = {\n /** List available interview slots for a booking token (PLA-714). Public. */\n getSlots: (\n token: string,\n opts?: { signal?: AbortSignal },\n ): Promise<{ slots: { startsAt: string; endsAt: string }[] }> => {\n const url = `${this.embedBaseUrl}/api/embed/v1/schedule/${encodeURIComponent(token)}`;\n return fetch(url, { signal: opts?.signal }).then((res) => {\n if (!res.ok) throw parseError(res);\n return res.json() as Promise<{ slots: { startsAt: string; endsAt: string }[] }>;\n });\n },\n /** Book an interview slot (PLA-714). Public. */\n book: (token: string, payload: BookSlotInput, opts?: { signal?: AbortSignal }): Promise<BookSlotResponse> => {\n const url = `${this.embedBaseUrl}/api/embed/v1/schedule/${encodeURIComponent(token)}/book`;\n return fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n signal: opts?.signal,\n }).then((res) => {\n if (!res.ok) throw parseError(res);\n return res.json() as Promise<BookSlotResponse>;\n });\n },\n /** Cancel an interview booking (PLA-714). Public. */\n cancel: (token: string, opts?: { signal?: AbortSignal }): Promise<BookSlotResponse> => {\n const url = `${this.embedBaseUrl}/api/embed/v1/schedule/${encodeURIComponent(token)}/cancel`;\n return fetch(url, { method: \"POST\", signal: opts?.signal }).then((res) => {\n if (!res.ok) throw parseError(res);\n return res.json() as Promise<BookSlotResponse>;\n });\n },\n /** Reschedule an interview booking (PLA-714). Public. */\n reschedule: (\n token: string,\n payload: RescheduleInput,\n opts?: { signal?: AbortSignal },\n ): Promise<BookSlotResponse> => {\n const url = `${this.embedBaseUrl}/api/embed/v1/schedule/${encodeURIComponent(token)}/reschedule`;\n return fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n signal: opts?.signal,\n }).then((res) => {\n if (!res.ok) throw parseError(res);\n return res.json() as Promise<BookSlotResponse>;\n });\n },\n };\n}\n\n/** Convenience factory — equivalent to `new PlayaOSClient(opts)`. */\nexport function createClient(opts: ClientOptions): PlayaOSClient {\n return new PlayaOSClient(opts);\n}\n","/**\n * Server-side OAuth-code → ID-token exchange.\n *\n * Swaps a one-time authorization code from the PlayaOS IdP for a short-lived\n * ID token. Confidential clients pass `clientSecret`, which is sent to the\n * token endpoint server-side. Public/PKCE-only clients omit it — the\n * authorization-code + code_verifier pair is the sole credential. Public\n * clients can also exchange directly from the browser via `usePlayaOSAuth`\n * in `@playaos/react`.\n */\n\nexport interface ExchangeParams {\n authBaseUrl?: string;\n code: string;\n codeVerifier: string;\n clientId: string;\n /** Confidential clients only. Omit for public/PKCE-only clients. */\n clientSecret?: string;\n redirectUri: string;\n}\n\nexport interface ExchangeResult {\n idToken: string;\n expiresAt: string;\n /** Confidential clients only. Undefined for public clients. */\n refreshToken?: string;\n}\n\nexport async function exchangeCode(params: ExchangeParams): Promise<ExchangeResult> {\n const base = params.authBaseUrl ?? \"https://auth.playaos.app\";\n // A confidential client is identified by passing clientSecret at all — even an\n // empty string. We forward it as-is so the server validates it (an empty or\n // wrong secret is rejected there); public clients omit the field entirely.\n const isConfidential = params.clientSecret !== undefined;\n const res = await fetch(`${base}/api/auth/v1/exchange`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n code: params.code,\n code_verifier: params.codeVerifier,\n client_id: params.clientId,\n ...(isConfidential ? { client_secret: params.clientSecret } : {}),\n redirect_uri: params.redirectUri,\n }),\n });\n let body: unknown;\n try {\n body = await res.json();\n } catch {\n throw new Error(`Exchange failed: non-JSON response (${res.status})`);\n }\n\n if (!res.ok) {\n const errorReason =\n typeof body === \"object\" && body !== null && \"error\" in body && typeof body.error === \"string\"\n ? body.error\n : String(res.status);\n throw new Error(`Exchange failed: ${errorReason}`);\n }\n\n if (\n typeof body !== \"object\" ||\n body === null ||\n !(\"idToken\" in body) ||\n typeof body.idToken !== \"string\" ||\n !(\"expiresAt\" in body) ||\n typeof body.expiresAt !== \"string\"\n ) {\n throw new Error(\"Exchange failed: malformed success response\");\n }\n\n // The server mints a refresh token only for confidential clients (it sets\n // `withRefreshToken: client.type === \"confidential\"`); public clients get\n // none. Surface it when present, otherwise leave it undefined.\n const refreshToken = \"refreshToken\" in body && typeof body.refreshToken === \"string\" ? body.refreshToken : undefined;\n\n // A confidential client that gets no refresh token means the server response\n // is malformed or the rotation flow is broken — surface it rather than\n // silently returning a result the caller can't refresh.\n if (isConfidential && refreshToken === undefined) {\n throw new Error(\"Exchange failed: confidential client response missing refreshToken\");\n }\n\n return {\n idToken: body.idToken,\n expiresAt: body.expiresAt,\n ...(refreshToken !== undefined ? { refreshToken } : {}),\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/error.ts","../src/client.ts","../src/exchange.ts"],"sourcesContent":["export class ApiClientError extends Error {\n constructor(\n public readonly status: number,\n public readonly code: string,\n message: string,\n ) {\n super(message);\n this.name = \"ApiClientError\";\n }\n}\n\nexport async function parseError(res: Response): Promise<ApiClientError> {\n try {\n const body = (await res.json()) as { error?: string; code?: string };\n return new ApiClientError(res.status, body.code ?? \"UNKNOWN\", body.error ?? res.statusText);\n } catch {\n return new ApiClientError(res.status, \"UNKNOWN\", res.statusText);\n }\n}\n","import { type ApiClientError, parseError } from \"./error.js\";\nimport type {\n AnnouncementSendPayload,\n AnnouncementSendResponse,\n Application,\n ApplicationAnnotations,\n ApplicationCreatePayload,\n ApplicationCreateResponse,\n ApplicationHistoryResponse,\n ApplicationNote,\n ApplicationScore,\n ApplicationStatus,\n ApplicationTransitionPayload,\n ApplicationTransitionResponse,\n BookingToken,\n BookSlotInput,\n BookSlotResponse,\n CalendarStatus,\n CreateBookingTokenInput,\n DuesCreatePayload,\n DuesCreateResponse,\n DuesStatus,\n DuesUpdatePayload,\n DuesUpdateResponse,\n GoogleCalendar,\n Member,\n MemberCreatePayload,\n MemberCreateResponse,\n MemberDeactivateResponse,\n MemberRole,\n MemberUpdatePayload,\n MemberUpdateResponse,\n OrgConfig,\n OrgUpdatePayload,\n OrgUpdateResponse,\n PaymentPageResponse,\n RescheduleInput,\n SelectCalendarInput,\n SetAvailabilityInput,\n SetAvailabilityResponse,\n Shift,\n Waiver,\n WaiverSignPayload,\n WaiverSignResponse,\n WaiverStatus,\n} from \"./types.js\";\n\nexport type { ApiClientError };\n\ninterface ClientOptions {\n /** Base URL for authenticated /api/v1 routes, e.g. https://api.playaos.app */\n baseUrl: string;\n /** Optional base URL for /api/embed/v1 routes when they live on a different host. */\n embedBaseUrl?: string;\n /** API key in the format pk_live_* */\n apiKey: string;\n}\n\nfunction buildUrl(base: string, path: string, params?: Record<string, string | number | boolean | undefined>): string {\n const url = new URL(`${base}/api/v1${path}`);\n if (params) {\n for (const [k, v] of Object.entries(params)) {\n // Skip undefined and false booleans — z.coerce.boolean() on the server uses Boolean(),\n // which treats any non-empty string (including \"false\") as true. Omitting a false boolean\n // param has the same effect as the server default (unfiltered).\n if (v !== undefined && v !== false) url.searchParams.set(k, String(v));\n }\n }\n return url.toString();\n}\n\nfunction buildEmbedUrl(base: string, path: string): string {\n return `${base}/api/embed/v1${path}`;\n}\n\nasync function getEmbed<T>(url: string, campKey: string, signal?: AbortSignal): Promise<T> {\n const res = await fetch(url, {\n headers: { \"X-Camp-Key\": campKey },\n signal,\n });\n if (!res.ok) throw await parseError(res);\n return res.json() as Promise<T>;\n}\n\nasync function getEmbedAuthed<T>(\n url: string,\n campKey: string,\n opts?: { accessToken?: string; signal?: AbortSignal },\n): Promise<T> {\n const headers: Record<string, string> = { \"X-Camp-Key\": campKey };\n if (opts?.accessToken) headers.Authorization = `Bearer ${opts.accessToken}`;\n const res = await fetch(url, { headers, signal: opts?.signal });\n if (!res.ok) throw await parseError(res);\n return res.json() as Promise<T>;\n}\n\nasync function request<T>(url: string, apiKey: string, signal?: AbortSignal): Promise<T> {\n const res = await fetch(url, {\n headers: { Authorization: `Bearer ${apiKey}` },\n signal,\n });\n if (!res.ok) throw await parseError(res);\n return res.json() as Promise<T>;\n}\n\nasync function post<T>(url: string, apiKey: string, body: unknown, signal?: AbortSignal): Promise<T> {\n const res = await fetch(url, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${apiKey}`, \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n signal,\n });\n if (!res.ok) throw await parseError(res);\n return res.json() as Promise<T>;\n}\n\nasync function postEmbed<T>(\n url: string,\n campKey: string,\n body: unknown,\n opts?: { accessToken?: string; signal?: AbortSignal },\n): Promise<T> {\n const headers: Record<string, string> = {\n \"X-Camp-Key\": campKey,\n \"Content-Type\": \"application/json\",\n };\n if (opts?.accessToken) headers.Authorization = `Bearer ${opts.accessToken}`;\n const res = await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n signal: opts?.signal,\n });\n if (!res.ok) throw await parseError(res);\n return res.json() as Promise<T>;\n}\n\nasync function putEmbed<T>(\n url: string,\n campKey: string,\n body: unknown,\n opts?: { accessToken?: string; signal?: AbortSignal },\n): Promise<T> {\n const headers: Record<string, string> = {\n \"X-Camp-Key\": campKey,\n \"Content-Type\": \"application/json\",\n };\n if (opts?.accessToken) headers.Authorization = `Bearer ${opts.accessToken}`;\n const res = await fetch(url, {\n method: \"PUT\",\n headers,\n body: JSON.stringify(body),\n signal: opts?.signal,\n });\n if (!res.ok) throw await parseError(res);\n return res.json() as Promise<T>;\n}\n\nasync function deleteEmbed<T>(\n url: string,\n campKey: string,\n opts?: { accessToken?: string; signal?: AbortSignal },\n): Promise<T> {\n const headers: Record<string, string> = { \"X-Camp-Key\": campKey };\n if (opts?.accessToken) headers.Authorization = `Bearer ${opts.accessToken}`;\n const res = await fetch(url, { method: \"DELETE\", headers, signal: opts?.signal });\n if (!res.ok) throw await parseError(res);\n return res.json() as Promise<T>;\n}\n\n/**\n * Bearer-only helper for /api/embed/v1/admin/* (PLA-489). The admin token is\n * the sole credential (no X-Camp-Key — orgId comes from the JWT claims\n * server-side). `method` can be GET, POST, PATCH, or PUT; `body` is optional\n * (omitted for GET reads like getAnnotations).\n */\nasync function adminEmbed<T>(\n method: \"GET\" | \"POST\" | \"PATCH\" | \"PUT\",\n url: string,\n accessToken: string,\n body?: unknown,\n signal?: AbortSignal,\n): Promise<T> {\n const headers: Record<string, string> = { Authorization: `Bearer ${accessToken}` };\n const init: RequestInit = { method, headers, signal };\n if (body !== undefined) {\n headers[\"Content-Type\"] = \"application/json\";\n init.body = JSON.stringify(body);\n }\n const res = await fetch(url, init);\n if (!res.ok) throw await parseError(res);\n return res.json() as Promise<T>;\n}\n\nexport class PlayaOSClient {\n private readonly baseUrl: string;\n private readonly embedBaseUrl: string;\n private readonly apiKey: string;\n\n constructor(opts: ClientOptions) {\n this.baseUrl = opts.baseUrl.replace(/\\/+$/, \"\");\n this.embedBaseUrl = (opts.embedBaseUrl ?? opts.baseUrl).replace(/\\/+$/, \"\");\n this.apiKey = opts.apiKey;\n }\n\n readonly members = {\n list: (params?: { role?: MemberRole; status?: string }, opts?: { signal?: AbortSignal }): Promise<Member[]> =>\n request(buildUrl(this.baseUrl, \"/members\", params), this.apiKey, opts?.signal),\n\n get: (id: string, opts?: { signal?: AbortSignal }): Promise<Member> =>\n request(buildUrl(this.baseUrl, `/members/${encodeURIComponent(id)}`), this.apiKey, opts?.signal),\n\n /** Member-self profile update (PLA-700). Requires camp key + member Bearer token. */\n selfUpdate: (\n payload: {\n bio?: string | null;\n playaName?: string | null;\n socialMedia?: Record<string, unknown> | null;\n showSocialsInDirectory?: boolean;\n phone?: string | null;\n emergencyContactName?: string | null;\n emergencyContactRelationship?: string | null;\n emergencyContactPhone?: string | null;\n profilePhotoPath?: string | null;\n yearJoined?: number | null;\n },\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<{ profileId: string }> =>\n putEmbed(buildEmbedUrl(this.embedBaseUrl, \"/members/self\"), this.apiKey, payload, opts),\n\n /** Member-self shift signup + cancel (PLA-705). Requires camp key + member Bearer. */\n shifts: {\n signup: (\n payload: { shiftId: string; role?: string },\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<{ signupId: string; waitlisted: boolean }> =>\n putEmbed(buildEmbedUrl(this.embedBaseUrl, \"/shifts/signup\"), this.apiKey, payload, opts),\n cancel: (\n signupId: string,\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<{ canceled: boolean; promotedSignupId: string | null }> =>\n deleteEmbed(\n buildEmbedUrl(this.embedBaseUrl, `/shifts/signups/${encodeURIComponent(signupId)}`),\n this.apiKey,\n opts,\n ),\n },\n };\n\n readonly applications = {\n list: (\n params?: { status?: ApplicationStatus; year?: number },\n opts?: { signal?: AbortSignal },\n ): Promise<Application[]> => request(buildUrl(this.baseUrl, \"/applications\", params), this.apiKey, opts?.signal),\n\n // Anonymous external-camp submission against POST /api/embed/v1/applications\n // (PLA-481). Uses the X-Camp-Key header rather than Bearer auth. Pass\n // `accessToken` to additionally send a PlayaOS IdP JWT (PLA-573 path) so\n // the server trusts the verified profile claim and skips the email-based\n // bootstrap.\n create: (\n payload: ApplicationCreatePayload,\n opts?: { accessToken?: string; signal?: AbortSignal },\n ): Promise<ApplicationCreateResponse> =>\n postEmbed(buildEmbedUrl(this.embedBaseUrl, \"/applications\"), this.apiKey, payload, opts),\n };\n\n readonly waivers = {\n /** Get the active waiver for an org for the current year. */\n active: (orgId: string, opts?: { signal?: AbortSignal }): Promise<Waiver> =>\n getEmbed(buildEmbedUrl(this.embedBaseUrl, `/waivers/${orgId}/active`), this.apiKey, opts?.signal),\n\n /** Sign a waiver. Requires X-Camp-Key; optional accessToken for Bearer path. */\n sign: (\n payload: WaiverSignPayload,\n opts?: { accessToken?: string; signal?: AbortSignal },\n ): Promise<WaiverSignResponse> =>\n postEmbed(buildEmbedUrl(this.embedBaseUrl, \"/waivers/sign\"), this.apiKey, payload, opts),\n\n /** Has this applicant/member signed the active waiver? Anchor: applicationId query or Bearer accessToken. */\n status: (\n orgId: string,\n opts?: { applicationId?: string; accessToken?: string; signal?: AbortSignal },\n ): Promise<WaiverStatus> => {\n const query = opts?.applicationId ? `?applicationId=${encodeURIComponent(opts.applicationId)}` : \"\";\n return getEmbedAuthed(buildEmbedUrl(this.embedBaseUrl, `/waivers/${orgId}/status${query}`), this.apiKey, opts);\n },\n\n /** Get a short-lived download URL for a completed signature's PDF. Anchor: applicationId query or Bearer. */\n signedPdf: (\n orgId: string,\n signatureId: string,\n opts?: { applicationId?: string; accessToken?: string; signal?: AbortSignal },\n ): Promise<{ url: string }> => {\n const query = opts?.applicationId ? `?applicationId=${encodeURIComponent(opts.applicationId)}` : \"\";\n return getEmbedAuthed(\n buildEmbedUrl(this.embedBaseUrl, `/waivers/${orgId}/signatures/${encodeURIComponent(signatureId)}/pdf${query}`),\n this.apiKey,\n opts,\n );\n },\n };\n\n readonly dues = {\n list: (params?: { userId?: string; year?: number }, opts?: { signal?: AbortSignal }): Promise<DuesStatus[]> =>\n request(buildUrl(this.baseUrl, \"/dues\", params), this.apiKey, opts?.signal),\n };\n\n readonly shifts = {\n list: (\n params?: { year?: number; fromDate?: string; toDate?: string; publishedOnly?: boolean },\n opts?: { signal?: AbortSignal },\n ): Promise<Shift[]> => request(buildUrl(this.baseUrl, \"/shifts\", params), this.apiKey, opts?.signal),\n };\n\n readonly org = {\n get: (opts?: { signal?: AbortSignal }): Promise<OrgConfig> =>\n request(buildUrl(this.baseUrl, \"/org\"), this.apiKey, opts?.signal),\n };\n\n readonly payments = {\n page: (\n memberId: string,\n duesCollectionId?: string,\n opts?: { signal?: AbortSignal },\n ): Promise<PaymentPageResponse> =>\n post(buildUrl(this.baseUrl, \"/payments/page\"), this.apiKey, { memberId, duesCollectionId }, opts?.signal),\n };\n\n // Admin write APIs (PLA-489). Each method requires `accessToken` — a Supabase\n // JWT for a camp admin/super_admin. The org boundary is enforced server-side\n // from the JWT claims; these endpoints do not use the X-Camp-Key.\n readonly admin = {\n applications: {\n /** Get application audit timeline (PLA-712). Requires admin Bearer token. */\n history: (id: string, opts: { accessToken: string; signal?: AbortSignal }): Promise<ApplicationHistoryResponse> =>\n adminEmbed(\n \"GET\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/applications/${encodeURIComponent(id)}/history`),\n opts.accessToken,\n undefined,\n opts.signal,\n ),\n transition: (\n id: string,\n payload: ApplicationTransitionPayload,\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<ApplicationTransitionResponse> =>\n adminEmbed(\n \"PATCH\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/applications/${encodeURIComponent(id)}`),\n opts.accessToken,\n payload,\n opts.signal,\n ),\n getAnnotations: (\n id: string,\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<ApplicationAnnotations> =>\n adminEmbed(\n \"GET\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/applications/${encodeURIComponent(id)}/annotations`),\n opts.accessToken,\n undefined,\n opts.signal,\n ),\n addNote: (\n id: string,\n payload: { body: string },\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<ApplicationNote> =>\n adminEmbed(\n \"POST\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/applications/${encodeURIComponent(id)}/notes`),\n opts.accessToken,\n payload,\n opts.signal,\n ),\n setTags: (\n id: string,\n payload: { tags: string[] },\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<string[]> =>\n adminEmbed(\n \"PUT\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/applications/${encodeURIComponent(id)}/tags`),\n opts.accessToken,\n payload,\n opts.signal,\n ),\n setScore: (\n id: string,\n payload: { value: number },\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<ApplicationScore> =>\n adminEmbed(\n \"PUT\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/applications/${encodeURIComponent(id)}/scores`),\n opts.accessToken,\n payload,\n opts.signal,\n ),\n },\n givebutter: {\n campaigns: {\n list: (opts: { accessToken: string; signal?: AbortSignal }): Promise<unknown[]> =>\n adminEmbed(\n \"GET\",\n buildEmbedUrl(this.embedBaseUrl, \"/admin/givebutter/campaigns\"),\n opts.accessToken,\n undefined,\n opts.signal,\n ),\n discountCodes: {\n list: (campaignId: number, opts: { accessToken: string; signal?: AbortSignal }): Promise<unknown[]> =>\n adminEmbed(\n \"GET\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/givebutter/campaigns/${campaignId}/discount-codes`),\n opts.accessToken,\n undefined,\n opts.signal,\n ),\n create: (\n campaignId: number,\n payload: { code: string; type: string; amount: number; active?: boolean },\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<unknown> =>\n adminEmbed(\n \"POST\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/givebutter/campaigns/${campaignId}/discount-codes`),\n opts.accessToken,\n payload,\n opts.signal,\n ),\n },\n tickets: {\n create: (\n campaignId: number,\n payload: { name: string; price: number; totalQuantity?: number },\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<unknown> =>\n adminEmbed(\n \"POST\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/givebutter/campaigns/${campaignId}/tickets`),\n opts.accessToken,\n payload,\n opts.signal,\n ),\n },\n },\n },\n members: {\n create: (\n payload: MemberCreatePayload,\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<MemberCreateResponse> =>\n adminEmbed(\"POST\", buildEmbedUrl(this.embedBaseUrl, \"/admin/members\"), opts.accessToken, payload, opts.signal),\n\n update: (\n id: string,\n patch: MemberUpdatePayload,\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<MemberUpdateResponse> =>\n adminEmbed(\n \"PATCH\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/members/${encodeURIComponent(id)}`),\n opts.accessToken,\n patch,\n opts.signal,\n ),\n\n deactivate: (\n id: string,\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<MemberDeactivateResponse> =>\n adminEmbed(\n \"PATCH\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/members/${encodeURIComponent(id)}`),\n opts.accessToken,\n { status: \"inactive\" },\n opts.signal,\n ),\n },\n announcements: {\n /** Send an email blast to camp members (PLA-706). Requires admin Bearer token. */\n send: (\n payload: AnnouncementSendPayload,\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<AnnouncementSendResponse> =>\n adminEmbed(\n \"POST\",\n buildEmbedUrl(this.embedBaseUrl, \"/admin/announcements/send\"),\n opts.accessToken,\n payload,\n opts.signal,\n ),\n },\n dues: {\n /** Create a manual dues/payment record (PLA-708). Requires admin Bearer token. */\n create: (\n payload: DuesCreatePayload,\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<DuesCreateResponse> =>\n adminEmbed(\"POST\", buildEmbedUrl(this.embedBaseUrl, \"/admin/dues\"), opts.accessToken, payload, opts.signal),\n\n /** Update a dues/payment record (PLA-708). Requires admin Bearer token. */\n update: (\n id: string,\n payload: DuesUpdatePayload,\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<DuesUpdateResponse> =>\n adminEmbed(\n \"PATCH\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/dues/${encodeURIComponent(id)}`),\n opts.accessToken,\n payload,\n opts.signal,\n ),\n },\n org: {\n /** Update camp configuration settings (PLA-709). Requires admin Bearer token. */\n update: (\n payload: OrgUpdatePayload,\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<OrgUpdateResponse> =>\n adminEmbed(\"PATCH\", buildEmbedUrl(this.embedBaseUrl, \"/admin/org\"), opts.accessToken, payload, opts.signal),\n },\n scheduling: {\n availability: {\n /** Get interview availability for an interviewer (PLA-713). Requires admin Bearer token. */\n get: (\n interviewerId: string,\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<SetAvailabilityResponse> =>\n adminEmbed(\n \"GET\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/scheduling/availability/${encodeURIComponent(interviewerId)}`),\n opts.accessToken,\n undefined,\n opts.signal,\n ),\n /** Set interview availability for an interviewer (PLA-713). Requires admin Bearer token. */\n set: (\n interviewerId: string,\n payload: SetAvailabilityInput,\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<SetAvailabilityResponse> =>\n adminEmbed(\n \"PUT\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/scheduling/availability/${encodeURIComponent(interviewerId)}`),\n opts.accessToken,\n payload,\n opts.signal,\n ),\n },\n calendar: {\n /** Get Google Calendar connection status for an interviewer (PLA-726). Requires admin Bearer. */\n status: (interviewerId: string, opts: { accessToken: string; signal?: AbortSignal }): Promise<CalendarStatus> =>\n adminEmbed(\n \"GET\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/scheduling/calendar/${encodeURIComponent(interviewerId)}/status`),\n opts.accessToken,\n undefined,\n opts.signal,\n ),\n /** List available Google Calendars (PLA-726). Requires admin Bearer. */\n listCalendars: (\n interviewerId: string,\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<{ calendars: GoogleCalendar[] }> =>\n adminEmbed(\n \"GET\",\n buildEmbedUrl(\n this.embedBaseUrl,\n `/admin/scheduling/calendar/${encodeURIComponent(interviewerId)}/calendars`,\n ),\n opts.accessToken,\n undefined,\n opts.signal,\n ),\n /** Select which Google Calendar to use (PLA-726). Requires admin Bearer. */\n select: (\n interviewerId: string,\n payload: SelectCalendarInput,\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<{ calendarId: string }> =>\n adminEmbed(\n \"PUT\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/scheduling/calendar/${encodeURIComponent(interviewerId)}/select`),\n opts.accessToken,\n payload,\n opts.signal,\n ),\n /** Disconnect Google Calendar from interviewer (PLA-726). Requires admin Bearer. */\n disconnect: (\n interviewerId: string,\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<{ disconnected: boolean }> =>\n adminEmbed(\n \"POST\",\n buildEmbedUrl(\n this.embedBaseUrl,\n `/admin/scheduling/calendar/${encodeURIComponent(interviewerId)}/disconnect`,\n ),\n opts.accessToken,\n undefined,\n opts.signal,\n ),\n },\n bookingTokens: {\n /** Create a booking token for an application's interview link (PLA-714). Requires admin Bearer token. */\n create: (\n payload: CreateBookingTokenInput,\n opts: { accessToken: string; signal?: AbortSignal },\n ): Promise<BookingToken> =>\n adminEmbed(\n \"POST\",\n buildEmbedUrl(this.embedBaseUrl, \"/admin/booking-tokens\"),\n opts.accessToken,\n payload,\n opts.signal,\n ),\n /** Get an existing booking token for an application (PLA-714). Requires admin Bearer token. */\n get: (applicationId: string, opts: { accessToken: string; signal?: AbortSignal }): Promise<BookingToken> =>\n adminEmbed(\n \"GET\",\n buildEmbedUrl(this.embedBaseUrl, `/admin/booking-tokens/${encodeURIComponent(applicationId)}`),\n opts.accessToken,\n undefined,\n opts.signal,\n ),\n },\n },\n };\n\n // Public embed-booking endpoints (PLA-714). No auth — these are the\n // applicant-facing schedule surface using the hashed booking token.\n readonly schedule = {\n /** List available interview slots for a booking token (PLA-714). Public. */\n getSlots: (\n token: string,\n opts?: { signal?: AbortSignal },\n ): Promise<{ slots: { startsAt: string; endsAt: string }[] }> => {\n const url = `${this.embedBaseUrl}/api/embed/v1/schedule/${encodeURIComponent(token)}`;\n return fetch(url, { signal: opts?.signal }).then((res) => {\n if (!res.ok) throw parseError(res);\n return res.json() as Promise<{ slots: { startsAt: string; endsAt: string }[] }>;\n });\n },\n /** Book an interview slot (PLA-714). Public. */\n book: (token: string, payload: BookSlotInput, opts?: { signal?: AbortSignal }): Promise<BookSlotResponse> => {\n const url = `${this.embedBaseUrl}/api/embed/v1/schedule/${encodeURIComponent(token)}/book`;\n return fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n signal: opts?.signal,\n }).then((res) => {\n if (!res.ok) throw parseError(res);\n return res.json() as Promise<BookSlotResponse>;\n });\n },\n /** Cancel an interview booking (PLA-714). Public. */\n cancel: (token: string, opts?: { signal?: AbortSignal }): Promise<BookSlotResponse> => {\n const url = `${this.embedBaseUrl}/api/embed/v1/schedule/${encodeURIComponent(token)}/cancel`;\n return fetch(url, { method: \"POST\", signal: opts?.signal }).then((res) => {\n if (!res.ok) throw parseError(res);\n return res.json() as Promise<BookSlotResponse>;\n });\n },\n /** Reschedule an interview booking (PLA-714). Public. */\n reschedule: (\n token: string,\n payload: RescheduleInput,\n opts?: { signal?: AbortSignal },\n ): Promise<BookSlotResponse> => {\n const url = `${this.embedBaseUrl}/api/embed/v1/schedule/${encodeURIComponent(token)}/reschedule`;\n return fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n signal: opts?.signal,\n }).then((res) => {\n if (!res.ok) throw parseError(res);\n return res.json() as Promise<BookSlotResponse>;\n });\n },\n };\n}\n\n/** Convenience factory — equivalent to `new PlayaOSClient(opts)`. */\nexport function createClient(opts: ClientOptions): PlayaOSClient {\n return new PlayaOSClient(opts);\n}\n","/**\n * Server-side OAuth-code → ID-token exchange.\n *\n * Swaps a one-time authorization code from the PlayaOS IdP for a short-lived\n * ID token. Confidential clients pass `clientSecret`, which is sent to the\n * token endpoint server-side. Public/PKCE-only clients omit it — the\n * authorization-code + code_verifier pair is the sole credential. Public\n * clients can also exchange directly from the browser via `usePlayaOSAuth`\n * in `@playaos/react`.\n */\n\nexport interface ExchangeParams {\n authBaseUrl?: string;\n code: string;\n codeVerifier: string;\n clientId: string;\n /** Confidential clients only. Omit for public/PKCE-only clients. */\n clientSecret?: string;\n redirectUri: string;\n}\n\nexport interface ExchangeResult {\n idToken: string;\n expiresAt: string;\n /** Confidential clients only. Undefined for public clients. */\n refreshToken?: string;\n}\n\nexport async function exchangeCode(params: ExchangeParams): Promise<ExchangeResult> {\n const base = params.authBaseUrl ?? \"https://auth.playaos.app\";\n // A confidential client is identified by passing clientSecret at all — even an\n // empty string. We forward it as-is so the server validates it (an empty or\n // wrong secret is rejected there); public clients omit the field entirely.\n const isConfidential = params.clientSecret !== undefined;\n const res = await fetch(`${base}/api/auth/v1/exchange`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n code: params.code,\n code_verifier: params.codeVerifier,\n client_id: params.clientId,\n ...(isConfidential ? { client_secret: params.clientSecret } : {}),\n redirect_uri: params.redirectUri,\n }),\n });\n let body: unknown;\n try {\n body = await res.json();\n } catch {\n throw new Error(`Exchange failed: non-JSON response (${res.status})`);\n }\n\n if (!res.ok) {\n const errorReason =\n typeof body === \"object\" && body !== null && \"error\" in body && typeof body.error === \"string\"\n ? body.error\n : String(res.status);\n throw new Error(`Exchange failed: ${errorReason}`);\n }\n\n if (\n typeof body !== \"object\" ||\n body === null ||\n !(\"idToken\" in body) ||\n typeof body.idToken !== \"string\" ||\n !(\"expiresAt\" in body) ||\n typeof body.expiresAt !== \"string\"\n ) {\n throw new Error(\"Exchange failed: malformed success response\");\n }\n\n // The server mints a refresh token only for confidential clients (it sets\n // `withRefreshToken: client.type === \"confidential\"`); public clients get\n // none. Surface it when present, otherwise leave it undefined.\n const refreshToken = \"refreshToken\" in body && typeof body.refreshToken === \"string\" ? body.refreshToken : undefined;\n\n // A confidential client that gets no refresh token means the server response\n // is malformed or the rotation flow is broken — surface it rather than\n // silently returning a result the caller can't refresh.\n if (isConfidential && refreshToken === undefined) {\n throw new Error(\"Exchange failed: confidential client response missing refreshToken\");\n }\n\n return {\n idToken: body.idToken,\n expiresAt: body.expiresAt,\n ...(refreshToken !== undefined ? { refreshToken } : {}),\n };\n}\n"],"mappings":";AAAO,IAAM,iBAAN,cAA6B,MAAM;AAAA,EACxC,YACkB,QACA,MAChB,SACA;AACA,UAAM,OAAO;AAJG;AACA;AAIhB,SAAK,OAAO;AAAA,EACd;AAAA,EANkB;AAAA,EACA;AAMpB;AAEA,eAAsB,WAAW,KAAwC;AACvE,MAAI;AACF,UAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,WAAO,IAAI,eAAe,IAAI,QAAQ,KAAK,QAAQ,WAAW,KAAK,SAAS,IAAI,UAAU;AAAA,EAC5F,QAAQ;AACN,WAAO,IAAI,eAAe,IAAI,QAAQ,WAAW,IAAI,UAAU;AAAA,EACjE;AACF;;;ACwCA,SAAS,SAAS,MAAc,MAAc,QAAwE;AACpH,QAAM,MAAM,IAAI,IAAI,GAAG,IAAI,UAAU,IAAI,EAAE;AAC3C,MAAI,QAAQ;AACV,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,MAAM,GAAG;AAI3C,UAAI,MAAM,UAAa,MAAM,MAAO,KAAI,aAAa,IAAI,GAAG,OAAO,CAAC,CAAC;AAAA,IACvE;AAAA,EACF;AACA,SAAO,IAAI,SAAS;AACtB;AAEA,SAAS,cAAc,MAAc,MAAsB;AACzD,SAAO,GAAG,IAAI,gBAAgB,IAAI;AACpC;AAEA,eAAe,SAAY,KAAa,SAAiB,QAAkC;AACzF,QAAM,MAAM,MAAM,MAAM,KAAK;AAAA,IAC3B,SAAS,EAAE,cAAc,QAAQ;AAAA,IACjC;AAAA,EACF,CAAC;AACD,MAAI,CAAC,IAAI,GAAI,OAAM,MAAM,WAAW,GAAG;AACvC,SAAO,IAAI,KAAK;AAClB;AAEA,eAAe,eACb,KACA,SACA,MACY;AACZ,QAAM,UAAkC,EAAE,cAAc,QAAQ;AAChE,MAAI,MAAM,YAAa,SAAQ,gBAAgB,UAAU,KAAK,WAAW;AACzE,QAAM,MAAM,MAAM,MAAM,KAAK,EAAE,SAAS,QAAQ,MAAM,OAAO,CAAC;AAC9D,MAAI,CAAC,IAAI,GAAI,OAAM,MAAM,WAAW,GAAG;AACvC,SAAO,IAAI,KAAK;AAClB;AAEA,eAAe,QAAW,KAAa,QAAgB,QAAkC;AACvF,QAAM,MAAM,MAAM,MAAM,KAAK;AAAA,IAC3B,SAAS,EAAE,eAAe,UAAU,MAAM,GAAG;AAAA,IAC7C;AAAA,EACF,CAAC;AACD,MAAI,CAAC,IAAI,GAAI,OAAM,MAAM,WAAW,GAAG;AACvC,SAAO,IAAI,KAAK;AAClB;AAEA,eAAe,KAAQ,KAAa,QAAgB,MAAe,QAAkC;AACnG,QAAM,MAAM,MAAM,MAAM,KAAK;AAAA,IAC3B,QAAQ;AAAA,IACR,SAAS,EAAE,eAAe,UAAU,MAAM,IAAI,gBAAgB,mBAAmB;AAAA,IACjF,MAAM,KAAK,UAAU,IAAI;AAAA,IACzB;AAAA,EACF,CAAC;AACD,MAAI,CAAC,IAAI,GAAI,OAAM,MAAM,WAAW,GAAG;AACvC,SAAO,IAAI,KAAK;AAClB;AAEA,eAAe,UACb,KACA,SACA,MACA,MACY;AACZ,QAAM,UAAkC;AAAA,IACtC,cAAc;AAAA,IACd,gBAAgB;AAAA,EAClB;AACA,MAAI,MAAM,YAAa,SAAQ,gBAAgB,UAAU,KAAK,WAAW;AACzE,QAAM,MAAM,MAAM,MAAM,KAAK;AAAA,IAC3B,QAAQ;AAAA,IACR;AAAA,IACA,MAAM,KAAK,UAAU,IAAI;AAAA,IACzB,QAAQ,MAAM;AAAA,EAChB,CAAC;AACD,MAAI,CAAC,IAAI,GAAI,OAAM,MAAM,WAAW,GAAG;AACvC,SAAO,IAAI,KAAK;AAClB;AAEA,eAAe,SACb,KACA,SACA,MACA,MACY;AACZ,QAAM,UAAkC;AAAA,IACtC,cAAc;AAAA,IACd,gBAAgB;AAAA,EAClB;AACA,MAAI,MAAM,YAAa,SAAQ,gBAAgB,UAAU,KAAK,WAAW;AACzE,QAAM,MAAM,MAAM,MAAM,KAAK;AAAA,IAC3B,QAAQ;AAAA,IACR;AAAA,IACA,MAAM,KAAK,UAAU,IAAI;AAAA,IACzB,QAAQ,MAAM;AAAA,EAChB,CAAC;AACD,MAAI,CAAC,IAAI,GAAI,OAAM,MAAM,WAAW,GAAG;AACvC,SAAO,IAAI,KAAK;AAClB;AAEA,eAAe,YACb,KACA,SACA,MACY;AACZ,QAAM,UAAkC,EAAE,cAAc,QAAQ;AAChE,MAAI,MAAM,YAAa,SAAQ,gBAAgB,UAAU,KAAK,WAAW;AACzE,QAAM,MAAM,MAAM,MAAM,KAAK,EAAE,QAAQ,UAAU,SAAS,QAAQ,MAAM,OAAO,CAAC;AAChF,MAAI,CAAC,IAAI,GAAI,OAAM,MAAM,WAAW,GAAG;AACvC,SAAO,IAAI,KAAK;AAClB;AAQA,eAAe,WACb,QACA,KACA,aACA,MACA,QACY;AACZ,QAAM,UAAkC,EAAE,eAAe,UAAU,WAAW,GAAG;AACjF,QAAM,OAAoB,EAAE,QAAQ,SAAS,OAAO;AACpD,MAAI,SAAS,QAAW;AACtB,YAAQ,cAAc,IAAI;AAC1B,SAAK,OAAO,KAAK,UAAU,IAAI;AAAA,EACjC;AACA,QAAM,MAAM,MAAM,MAAM,KAAK,IAAI;AACjC,MAAI,CAAC,IAAI,GAAI,OAAM,MAAM,WAAW,GAAG;AACvC,SAAO,IAAI,KAAK;AAClB;AAEO,IAAM,gBAAN,MAAoB;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,MAAqB;AAC/B,SAAK,UAAU,KAAK,QAAQ,QAAQ,QAAQ,EAAE;AAC9C,SAAK,gBAAgB,KAAK,gBAAgB,KAAK,SAAS,QAAQ,QAAQ,EAAE;AAC1E,SAAK,SAAS,KAAK;AAAA,EACrB;AAAA,EAES,UAAU;AAAA,IACjB,MAAM,CAAC,QAAiD,SACtD,QAAQ,SAAS,KAAK,SAAS,YAAY,MAAM,GAAG,KAAK,QAAQ,MAAM,MAAM;AAAA,IAE/E,KAAK,CAAC,IAAY,SAChB,QAAQ,SAAS,KAAK,SAAS,YAAY,mBAAmB,EAAE,CAAC,EAAE,GAAG,KAAK,QAAQ,MAAM,MAAM;AAAA;AAAA,IAGjG,YAAY,CACV,SAYA,SAEA,SAAS,cAAc,KAAK,cAAc,eAAe,GAAG,KAAK,QAAQ,SAAS,IAAI;AAAA;AAAA,IAGxF,QAAQ;AAAA,MACN,QAAQ,CACN,SACA,SAEA,SAAS,cAAc,KAAK,cAAc,gBAAgB,GAAG,KAAK,QAAQ,SAAS,IAAI;AAAA,MACzF,QAAQ,CACN,UACA,SAEA;AAAA,QACE,cAAc,KAAK,cAAc,mBAAmB,mBAAmB,QAAQ,CAAC,EAAE;AAAA,QAClF,KAAK;AAAA,QACL;AAAA,MACF;AAAA,IACJ;AAAA,EACF;AAAA,EAES,eAAe;AAAA,IACtB,MAAM,CACJ,QACA,SAC2B,QAAQ,SAAS,KAAK,SAAS,iBAAiB,MAAM,GAAG,KAAK,QAAQ,MAAM,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAO/G,QAAQ,CACN,SACA,SAEA,UAAU,cAAc,KAAK,cAAc,eAAe,GAAG,KAAK,QAAQ,SAAS,IAAI;AAAA,EAC3F;AAAA,EAES,UAAU;AAAA;AAAA,IAEjB,QAAQ,CAAC,OAAe,SACtB,SAAS,cAAc,KAAK,cAAc,YAAY,KAAK,SAAS,GAAG,KAAK,QAAQ,MAAM,MAAM;AAAA;AAAA,IAGlG,MAAM,CACJ,SACA,SAEA,UAAU,cAAc,KAAK,cAAc,eAAe,GAAG,KAAK,QAAQ,SAAS,IAAI;AAAA;AAAA,IAGzF,QAAQ,CACN,OACA,SAC0B;AAC1B,YAAM,QAAQ,MAAM,gBAAgB,kBAAkB,mBAAmB,KAAK,aAAa,CAAC,KAAK;AACjG,aAAO,eAAe,cAAc,KAAK,cAAc,YAAY,KAAK,UAAU,KAAK,EAAE,GAAG,KAAK,QAAQ,IAAI;AAAA,IAC/G;AAAA;AAAA,IAGA,WAAW,CACT,OACA,aACA,SAC6B;AAC7B,YAAM,QAAQ,MAAM,gBAAgB,kBAAkB,mBAAmB,KAAK,aAAa,CAAC,KAAK;AACjG,aAAO;AAAA,QACL,cAAc,KAAK,cAAc,YAAY,KAAK,eAAe,mBAAmB,WAAW,CAAC,OAAO,KAAK,EAAE;AAAA,QAC9G,KAAK;AAAA,QACL;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAES,OAAO;AAAA,IACd,MAAM,CAAC,QAA6C,SAClD,QAAQ,SAAS,KAAK,SAAS,SAAS,MAAM,GAAG,KAAK,QAAQ,MAAM,MAAM;AAAA,EAC9E;AAAA,EAES,SAAS;AAAA,IAChB,MAAM,CACJ,QACA,SACqB,QAAQ,SAAS,KAAK,SAAS,WAAW,MAAM,GAAG,KAAK,QAAQ,MAAM,MAAM;AAAA,EACrG;AAAA,EAES,MAAM;AAAA,IACb,KAAK,CAAC,SACJ,QAAQ,SAAS,KAAK,SAAS,MAAM,GAAG,KAAK,QAAQ,MAAM,MAAM;AAAA,EACrE;AAAA,EAES,WAAW;AAAA,IAClB,MAAM,CACJ,UACA,kBACA,SAEA,KAAK,SAAS,KAAK,SAAS,gBAAgB,GAAG,KAAK,QAAQ,EAAE,UAAU,iBAAiB,GAAG,MAAM,MAAM;AAAA,EAC5G;AAAA;AAAA;AAAA;AAAA,EAKS,QAAQ;AAAA,IACf,cAAc;AAAA;AAAA,MAEZ,SAAS,CAAC,IAAY,SACpB;AAAA,QACE;AAAA,QACA,cAAc,KAAK,cAAc,uBAAuB,mBAAmB,EAAE,CAAC,UAAU;AAAA,QACxF,KAAK;AAAA,QACL;AAAA,QACA,KAAK;AAAA,MACP;AAAA,MACF,YAAY,CACV,IACA,SACA,SAEA;AAAA,QACE;AAAA,QACA,cAAc,KAAK,cAAc,uBAAuB,mBAAmB,EAAE,CAAC,EAAE;AAAA,QAChF,KAAK;AAAA,QACL;AAAA,QACA,KAAK;AAAA,MACP;AAAA,MACF,gBAAgB,CACd,IACA,SAEA;AAAA,QACE;AAAA,QACA,cAAc,KAAK,cAAc,uBAAuB,mBAAmB,EAAE,CAAC,cAAc;AAAA,QAC5F,KAAK;AAAA,QACL;AAAA,QACA,KAAK;AAAA,MACP;AAAA,MACF,SAAS,CACP,IACA,SACA,SAEA;AAAA,QACE;AAAA,QACA,cAAc,KAAK,cAAc,uBAAuB,mBAAmB,EAAE,CAAC,QAAQ;AAAA,QACtF,KAAK;AAAA,QACL;AAAA,QACA,KAAK;AAAA,MACP;AAAA,MACF,SAAS,CACP,IACA,SACA,SAEA;AAAA,QACE;AAAA,QACA,cAAc,KAAK,cAAc,uBAAuB,mBAAmB,EAAE,CAAC,OAAO;AAAA,QACrF,KAAK;AAAA,QACL;AAAA,QACA,KAAK;AAAA,MACP;AAAA,MACF,UAAU,CACR,IACA,SACA,SAEA;AAAA,QACE;AAAA,QACA,cAAc,KAAK,cAAc,uBAAuB,mBAAmB,EAAE,CAAC,SAAS;AAAA,QACvF,KAAK;AAAA,QACL;AAAA,QACA,KAAK;AAAA,MACP;AAAA,IACJ;AAAA,IACA,YAAY;AAAA,MACV,WAAW;AAAA,QACT,MAAM,CAAC,SACL;AAAA,UACE;AAAA,UACA,cAAc,KAAK,cAAc,6BAA6B;AAAA,UAC9D,KAAK;AAAA,UACL;AAAA,UACA,KAAK;AAAA,QACP;AAAA,QACF,eAAe;AAAA,UACb,MAAM,CAAC,YAAoB,SACzB;AAAA,YACE;AAAA,YACA,cAAc,KAAK,cAAc,+BAA+B,UAAU,iBAAiB;AAAA,YAC3F,KAAK;AAAA,YACL;AAAA,YACA,KAAK;AAAA,UACP;AAAA,UACF,QAAQ,CACN,YACA,SACA,SAEA;AAAA,YACE;AAAA,YACA,cAAc,KAAK,cAAc,+BAA+B,UAAU,iBAAiB;AAAA,YAC3F,KAAK;AAAA,YACL;AAAA,YACA,KAAK;AAAA,UACP;AAAA,QACJ;AAAA,QACA,SAAS;AAAA,UACP,QAAQ,CACN,YACA,SACA,SAEA;AAAA,YACE;AAAA,YACA,cAAc,KAAK,cAAc,+BAA+B,UAAU,UAAU;AAAA,YACpF,KAAK;AAAA,YACL;AAAA,YACA,KAAK;AAAA,UACP;AAAA,QACJ;AAAA,MACF;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,QAAQ,CACN,SACA,SAEA,WAAW,QAAQ,cAAc,KAAK,cAAc,gBAAgB,GAAG,KAAK,aAAa,SAAS,KAAK,MAAM;AAAA,MAE/G,QAAQ,CACN,IACA,OACA,SAEA;AAAA,QACE;AAAA,QACA,cAAc,KAAK,cAAc,kBAAkB,mBAAmB,EAAE,CAAC,EAAE;AAAA,QAC3E,KAAK;AAAA,QACL;AAAA,QACA,KAAK;AAAA,MACP;AAAA,MAEF,YAAY,CACV,IACA,SAEA;AAAA,QACE;AAAA,QACA,cAAc,KAAK,cAAc,kBAAkB,mBAAmB,EAAE,CAAC,EAAE;AAAA,QAC3E,KAAK;AAAA,QACL,EAAE,QAAQ,WAAW;AAAA,QACrB,KAAK;AAAA,MACP;AAAA,IACJ;AAAA,IACA,eAAe;AAAA;AAAA,MAEb,MAAM,CACJ,SACA,SAEA;AAAA,QACE;AAAA,QACA,cAAc,KAAK,cAAc,2BAA2B;AAAA,QAC5D,KAAK;AAAA,QACL;AAAA,QACA,KAAK;AAAA,MACP;AAAA,IACJ;AAAA,IACA,MAAM;AAAA;AAAA,MAEJ,QAAQ,CACN,SACA,SAEA,WAAW,QAAQ,cAAc,KAAK,cAAc,aAAa,GAAG,KAAK,aAAa,SAAS,KAAK,MAAM;AAAA;AAAA,MAG5G,QAAQ,CACN,IACA,SACA,SAEA;AAAA,QACE;AAAA,QACA,cAAc,KAAK,cAAc,eAAe,mBAAmB,EAAE,CAAC,EAAE;AAAA,QACxE,KAAK;AAAA,QACL;AAAA,QACA,KAAK;AAAA,MACP;AAAA,IACJ;AAAA,IACA,KAAK;AAAA;AAAA,MAEH,QAAQ,CACN,SACA,SAEA,WAAW,SAAS,cAAc,KAAK,cAAc,YAAY,GAAG,KAAK,aAAa,SAAS,KAAK,MAAM;AAAA,IAC9G;AAAA,IACA,YAAY;AAAA,MACV,cAAc;AAAA;AAAA,QAEZ,KAAK,CACH,eACA,SAEA;AAAA,UACE;AAAA,UACA,cAAc,KAAK,cAAc,kCAAkC,mBAAmB,aAAa,CAAC,EAAE;AAAA,UACtG,KAAK;AAAA,UACL;AAAA,UACA,KAAK;AAAA,QACP;AAAA;AAAA,QAEF,KAAK,CACH,eACA,SACA,SAEA;AAAA,UACE;AAAA,UACA,cAAc,KAAK,cAAc,kCAAkC,mBAAmB,aAAa,CAAC,EAAE;AAAA,UACtG,KAAK;AAAA,UACL;AAAA,UACA,KAAK;AAAA,QACP;AAAA,MACJ;AAAA,MACA,UAAU;AAAA;AAAA,QAER,QAAQ,CAAC,eAAuB,SAC9B;AAAA,UACE;AAAA,UACA,cAAc,KAAK,cAAc,8BAA8B,mBAAmB,aAAa,CAAC,SAAS;AAAA,UACzG,KAAK;AAAA,UACL;AAAA,UACA,KAAK;AAAA,QACP;AAAA;AAAA,QAEF,eAAe,CACb,eACA,SAEA;AAAA,UACE;AAAA,UACA;AAAA,YACE,KAAK;AAAA,YACL,8BAA8B,mBAAmB,aAAa,CAAC;AAAA,UACjE;AAAA,UACA,KAAK;AAAA,UACL;AAAA,UACA,KAAK;AAAA,QACP;AAAA;AAAA,QAEF,QAAQ,CACN,eACA,SACA,SAEA;AAAA,UACE;AAAA,UACA,cAAc,KAAK,cAAc,8BAA8B,mBAAmB,aAAa,CAAC,SAAS;AAAA,UACzG,KAAK;AAAA,UACL;AAAA,UACA,KAAK;AAAA,QACP;AAAA;AAAA,QAEF,YAAY,CACV,eACA,SAEA;AAAA,UACE;AAAA,UACA;AAAA,YACE,KAAK;AAAA,YACL,8BAA8B,mBAAmB,aAAa,CAAC;AAAA,UACjE;AAAA,UACA,KAAK;AAAA,UACL;AAAA,UACA,KAAK;AAAA,QACP;AAAA,MACJ;AAAA,MACA,eAAe;AAAA;AAAA,QAEb,QAAQ,CACN,SACA,SAEA;AAAA,UACE;AAAA,UACA,cAAc,KAAK,cAAc,uBAAuB;AAAA,UACxD,KAAK;AAAA,UACL;AAAA,UACA,KAAK;AAAA,QACP;AAAA;AAAA,QAEF,KAAK,CAAC,eAAuB,SAC3B;AAAA,UACE;AAAA,UACA,cAAc,KAAK,cAAc,yBAAyB,mBAAmB,aAAa,CAAC,EAAE;AAAA,UAC7F,KAAK;AAAA,UACL;AAAA,UACA,KAAK;AAAA,QACP;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA,EAIS,WAAW;AAAA;AAAA,IAElB,UAAU,CACR,OACA,SAC+D;AAC/D,YAAM,MAAM,GAAG,KAAK,YAAY,0BAA0B,mBAAmB,KAAK,CAAC;AACnF,aAAO,MAAM,KAAK,EAAE,QAAQ,MAAM,OAAO,CAAC,EAAE,KAAK,CAAC,QAAQ;AACxD,YAAI,CAAC,IAAI,GAAI,OAAM,WAAW,GAAG;AACjC,eAAO,IAAI,KAAK;AAAA,MAClB,CAAC;AAAA,IACH;AAAA;AAAA,IAEA,MAAM,CAAC,OAAe,SAAwB,SAA+D;AAC3G,YAAM,MAAM,GAAG,KAAK,YAAY,0BAA0B,mBAAmB,KAAK,CAAC;AACnF,aAAO,MAAM,KAAK;AAAA,QAChB,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,OAAO;AAAA,QAC5B,QAAQ,MAAM;AAAA,MAChB,CAAC,EAAE,KAAK,CAAC,QAAQ;AACf,YAAI,CAAC,IAAI,GAAI,OAAM,WAAW,GAAG;AACjC,eAAO,IAAI,KAAK;AAAA,MAClB,CAAC;AAAA,IACH;AAAA;AAAA,IAEA,QAAQ,CAAC,OAAe,SAA+D;AACrF,YAAM,MAAM,GAAG,KAAK,YAAY,0BAA0B,mBAAmB,KAAK,CAAC;AACnF,aAAO,MAAM,KAAK,EAAE,QAAQ,QAAQ,QAAQ,MAAM,OAAO,CAAC,EAAE,KAAK,CAAC,QAAQ;AACxE,YAAI,CAAC,IAAI,GAAI,OAAM,WAAW,GAAG;AACjC,eAAO,IAAI,KAAK;AAAA,MAClB,CAAC;AAAA,IACH;AAAA;AAAA,IAEA,YAAY,CACV,OACA,SACA,SAC8B;AAC9B,YAAM,MAAM,GAAG,KAAK,YAAY,0BAA0B,mBAAmB,KAAK,CAAC;AACnF,aAAO,MAAM,KAAK;AAAA,QAChB,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,OAAO;AAAA,QAC5B,QAAQ,MAAM;AAAA,MAChB,CAAC,EAAE,KAAK,CAAC,QAAQ;AACf,YAAI,CAAC,IAAI,GAAI,OAAM,WAAW,GAAG;AACjC,eAAO,IAAI,KAAK;AAAA,MAClB,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAGO,SAAS,aAAa,MAAoC;AAC/D,SAAO,IAAI,cAAc,IAAI;AAC/B;;;ACzpBA,eAAsB,aAAa,QAAiD;AAClF,QAAM,OAAO,OAAO,eAAe;AAInC,QAAM,iBAAiB,OAAO,iBAAiB;AAC/C,QAAM,MAAM,MAAM,MAAM,GAAG,IAAI,yBAAyB;AAAA,IACtD,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,IAC9C,MAAM,KAAK,UAAU;AAAA,MACnB,MAAM,OAAO;AAAA,MACb,eAAe,OAAO;AAAA,MACtB,WAAW,OAAO;AAAA,MAClB,GAAI,iBAAiB,EAAE,eAAe,OAAO,aAAa,IAAI,CAAC;AAAA,MAC/D,cAAc,OAAO;AAAA,IACvB,CAAC;AAAA,EACH,CAAC;AACD,MAAI;AACJ,MAAI;AACF,WAAO,MAAM,IAAI,KAAK;AAAA,EACxB,QAAQ;AACN,UAAM,IAAI,MAAM,uCAAuC,IAAI,MAAM,GAAG;AAAA,EACtE;AAEA,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,cACJ,OAAO,SAAS,YAAY,SAAS,QAAQ,WAAW,QAAQ,OAAO,KAAK,UAAU,WAClF,KAAK,QACL,OAAO,IAAI,MAAM;AACvB,UAAM,IAAI,MAAM,oBAAoB,WAAW,EAAE;AAAA,EACnD;AAEA,MACE,OAAO,SAAS,YAChB,SAAS,QACT,EAAE,aAAa,SACf,OAAO,KAAK,YAAY,YACxB,EAAE,eAAe,SACjB,OAAO,KAAK,cAAc,UAC1B;AACA,UAAM,IAAI,MAAM,6CAA6C;AAAA,EAC/D;AAKA,QAAM,eAAe,kBAAkB,QAAQ,OAAO,KAAK,iBAAiB,WAAW,KAAK,eAAe;AAK3G,MAAI,kBAAkB,iBAAiB,QAAW;AAChD,UAAM,IAAI,MAAM,oEAAoE;AAAA,EACtF;AAEA,SAAO;AAAA,IACL,SAAS,KAAK;AAAA,IACd,WAAW,KAAK;AAAA,IAChB,GAAI,iBAAiB,SAAY,EAAE,aAAa,IAAI,CAAC;AAAA,EACvD;AACF;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playaos/api-client",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "Typed API client for PlayaOS \u2014 manage camp members, dues, shifts, applications, waivers, and annotations",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",