@playaos/api-client 0.57.0 → 0.59.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/README.md +57 -0
- package/dist/applications-schema.d.ts +2 -0
- package/dist/applications-schema.js +4 -1
- package/dist/applications-schema.js.map +1 -1
- package/dist/index.d.ts +507 -183
- package/dist/index.js +236 -40
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -61,6 +61,44 @@ const created = await client.applications.create({
|
|
|
61
61
|
|
|
62
62
|
If your deployment serves both route families from the same host, omit `embedBaseUrl` and the client will reuse `baseUrl`.
|
|
63
63
|
|
|
64
|
+
### External application receipts
|
|
65
|
+
|
|
66
|
+
External forms can submit only the fields they collect, plus structured
|
|
67
|
+
`custom_fields`. Omit uncollected birthdays and acknowledgements; never invent
|
|
68
|
+
affirmative consent to satisfy the multi-step wizard's separate requirements.
|
|
69
|
+
The camp must have an active year configured.
|
|
70
|
+
|
|
71
|
+
The approval workflow requires actual principles agreement. An intake without
|
|
72
|
+
that answer can be stored, but cannot be approved. Collect explicit consent in
|
|
73
|
+
forms intended to complete that workflow and pass `agrees_to_principles: true`
|
|
74
|
+
only after the applicant acknowledges it. Missing consent is never an implied
|
|
75
|
+
agreement, and administrators cannot manufacture it during reconciliation.
|
|
76
|
+
|
|
77
|
+
For retryable submissions, create one UUID per logical application and retain it
|
|
78
|
+
with the draft. Send it as `submission_id` on every identical retry:
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
const receipt = await client.applications.create({
|
|
82
|
+
submission_id: submissionId,
|
|
83
|
+
first_name: "Rain",
|
|
84
|
+
last_name: "",
|
|
85
|
+
email: "rain@example.com",
|
|
86
|
+
custom_fields: { interests: ["pickleball"] },
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
A fresh opted-in acceptance returns `replayed: false`. An identical retry returns
|
|
91
|
+
the same `applicationId` and original `year` with `replayed: true`, without
|
|
92
|
+
changing the saved application. Different answers under an accepted key conflict;
|
|
93
|
+
an email duplicate under another key is not an owned receipt. Retries remain
|
|
94
|
+
scoped to the issuing camp. Keep this operation on the server when its camp
|
|
95
|
+
credential is server-only.
|
|
96
|
+
|
|
97
|
+
Start optional mail or spreadsheet side effects only for an explicit
|
|
98
|
+
`replayed === false` result. A replay or older server's missing flag does not
|
|
99
|
+
prove those side effects are safe to repeat. Saved acceptance and notification
|
|
100
|
+
delivery are separate outcomes; reconcile unknown delivery before resending.
|
|
101
|
+
|
|
64
102
|
## Route hosts
|
|
65
103
|
|
|
66
104
|
- `baseUrl` is used for authenticated `/api/v1/*` routes.
|
|
@@ -121,6 +159,25 @@ try {
|
|
|
121
159
|
}
|
|
122
160
|
```
|
|
123
161
|
|
|
162
|
+
A write to an archived event is refused with `403` and code `EVENT_READ_ONLY`; reading it still
|
|
163
|
+
works. Test for it with `isEventReadOnlyError` rather than the status alone, since `403 FORBIDDEN`
|
|
164
|
+
(scope or role) is a different refusal:
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
import { isEventReadOnlyError } from "@playaos/api-client";
|
|
168
|
+
|
|
169
|
+
try {
|
|
170
|
+
await client.members.shifts.signup({ shiftId }, { accessToken });
|
|
171
|
+
} catch (err) {
|
|
172
|
+
if (isEventReadOnlyError(err)) showNotice("This event is archived and can no longer be changed.");
|
|
173
|
+
else throw err;
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
It also matches the embed spelling `event_read_only`, which methods that fall back to the embed
|
|
178
|
+
API receive. `ApiErrorCode` holds the codes worth branching on (`EVENT_READ_ONLY`, `EVENT_REQUIRED`).
|
|
179
|
+
`err.code` stays a `string`, so new server codes never break your types.
|
|
180
|
+
|
|
124
181
|
## MCP server
|
|
125
182
|
|
|
126
183
|
For AI agent access, use the companion [@playaos/mcp](https://www.npmjs.com/package/@playaos/mcp) package.
|
|
@@ -50,6 +50,8 @@ export declare const step5Schema: z.ZodObject<{
|
|
|
50
50
|
agrees_to_principles: z.ZodLiteral<true>;
|
|
51
51
|
}, z.core.$strip>;
|
|
52
52
|
export declare const applicationSchema: z.ZodObject<{
|
|
53
|
+
submission_id: z.ZodOptional<z.ZodString>;
|
|
54
|
+
event_id: z.ZodOptional<z.ZodString>;
|
|
53
55
|
acknowledged_expectations: z.ZodOptional<z.ZodLiteral<true>>;
|
|
54
56
|
first_name: z.ZodString;
|
|
55
57
|
last_name: z.ZodString;
|
|
@@ -51,9 +51,12 @@ const step5Schema = z.object({
|
|
|
51
51
|
agrees_to_principles: z.literal(true, { error: "You must agree to the 10 Principles" })
|
|
52
52
|
});
|
|
53
53
|
const applicationSchema = z.object({
|
|
54
|
+
submission_id: z.string().uuid().optional(),
|
|
55
|
+
/** The event applied to (ADR-132). Required only when the active camp year has several events. */
|
|
56
|
+
event_id: z.string().uuid().optional(),
|
|
54
57
|
acknowledged_expectations: z.literal(true).optional(),
|
|
55
58
|
first_name: z.string().min(1),
|
|
56
|
-
last_name: z.string()
|
|
59
|
+
last_name: z.string(),
|
|
57
60
|
email: z.string().email(),
|
|
58
61
|
phone: z.string().optional(),
|
|
59
62
|
referral_code: z.string().optional(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"applications-schema.js","names":[],"sources":["../src/applications-schema.ts"],"sourcesContent":["import { z } from \"zod\";\n\n// Single source of truth for the apply-wizard form shape.\n// The portal apply flow and the @playaos/react <ApplicationForm> SDK both import\n// from here so the validation contract can never drift between them (PLA-483).\n// `ApplicationCreatePayload` in ./types.ts is the zod-free wire mirror; a type\n// equivalence test (applications-schema.test.ts) keeps the two locked together.\n\n// Per-step validation schemas\nexport const step0Schema = z.object({\n acknowledged_expectations: z.literal(true, {\n error: \"Please acknowledge the expectations to continue\",\n }),\n});\n\nexport const step1Schema = z.object({\n first_name: z.string().min(1, \"First name is required\"),\n last_name: z.string().min(1, \"Last name is required\"),\n email: z.string().email(\"Invalid email address\"),\n phone: z.string().min(10, \"Phone number is required\"),\n referral_code: z.string().optional(),\n socials: z.string().optional(),\n birthday: z.string().min(1, \"Birthday is required\"),\n hometown: z.string().min(1, \"Location is required\"),\n});\n\nexport const step2Schema = z.object({\n how_heard: z.string().min(1, \"Please tell us how you heard about us\"),\n burning_man_before: z.enum([\"yes\", \"no\"], { error: \"Please select an option\" }),\n burning_man_years: z.string().optional(),\n});\n\nexport const step3Schema = z.object({\n shelter_type: z.enum([\"joining_rv\", \"bringing_rv\", \"shiftpod_tent\", \"car\", \"truck\", \"van\", \"unsure\"], {\n error: \"Please select a shelter type\",\n }),\n shelter_mates: z.string().optional(),\n ticket_status: z.enum([\"looking\", \"have_ticket\", \"unsure\"], { error: \"Please select your ticket status\" }),\n});\n\nexport const step4Schema = z\n .object({\n build_available: z.boolean(),\n build_skills: z.string().optional(),\n strike_available: z.boolean(),\n strike_help: z.string().optional(),\n // commitmentId → value. Integers only on the number branch (per dataType);\n // per-commitment bounds (min/max) are validated against the live defs at\n // form-render + on the server, not here (PLA-682).\n commitments: z.record(z.string(), z.union([z.number().int(), z.boolean()])).optional(),\n })\n .refine((data) => !data.build_available || data.build_skills, {\n message: \"Please tell us about your build skills\",\n path: [\"build_skills\"],\n })\n .refine((data) => !data.strike_available || data.strike_help, {\n message: \"Please tell us how you can help with strike\",\n path: [\"strike_help\"],\n });\n\nexport const step5Schema = z.object({\n about_yourself: z.string().min(50, \"Please write at least 50 characters about yourself\"),\n agrees_to_principles: z.literal(true, { error: \"You must agree to the 10 Principles\" }),\n});\n\n// Combined schema for API-level validation — permissive so external camps\n// can submit applications with only first_name + last_name + email + custom_fields.\n// Step schemas (above) remain strict for the PlayaOS wizard UI.\nexport const applicationSchema = z.object({\n acknowledged_expectations: z.literal(true).optional(),\n first_name: z.string().min(1),\n last_name: z.string()
|
|
1
|
+
{"version":3,"file":"applications-schema.js","names":[],"sources":["../src/applications-schema.ts"],"sourcesContent":["import { z } from \"zod\";\n\n// Single source of truth for the apply-wizard form shape.\n// The portal apply flow and the @playaos/react <ApplicationForm> SDK both import\n// from here so the validation contract can never drift between them (PLA-483).\n// `ApplicationCreatePayload` in ./types.ts is the zod-free wire mirror; a type\n// equivalence test (applications-schema.test.ts) keeps the two locked together.\n\n// Per-step validation schemas\nexport const step0Schema = z.object({\n acknowledged_expectations: z.literal(true, {\n error: \"Please acknowledge the expectations to continue\",\n }),\n});\n\nexport const step1Schema = z.object({\n first_name: z.string().min(1, \"First name is required\"),\n last_name: z.string().min(1, \"Last name is required\"),\n email: z.string().email(\"Invalid email address\"),\n phone: z.string().min(10, \"Phone number is required\"),\n referral_code: z.string().optional(),\n socials: z.string().optional(),\n birthday: z.string().min(1, \"Birthday is required\"),\n hometown: z.string().min(1, \"Location is required\"),\n});\n\nexport const step2Schema = z.object({\n how_heard: z.string().min(1, \"Please tell us how you heard about us\"),\n burning_man_before: z.enum([\"yes\", \"no\"], { error: \"Please select an option\" }),\n burning_man_years: z.string().optional(),\n});\n\nexport const step3Schema = z.object({\n shelter_type: z.enum([\"joining_rv\", \"bringing_rv\", \"shiftpod_tent\", \"car\", \"truck\", \"van\", \"unsure\"], {\n error: \"Please select a shelter type\",\n }),\n shelter_mates: z.string().optional(),\n ticket_status: z.enum([\"looking\", \"have_ticket\", \"unsure\"], { error: \"Please select your ticket status\" }),\n});\n\nexport const step4Schema = z\n .object({\n build_available: z.boolean(),\n build_skills: z.string().optional(),\n strike_available: z.boolean(),\n strike_help: z.string().optional(),\n // commitmentId → value. Integers only on the number branch (per dataType);\n // per-commitment bounds (min/max) are validated against the live defs at\n // form-render + on the server, not here (PLA-682).\n commitments: z.record(z.string(), z.union([z.number().int(), z.boolean()])).optional(),\n })\n .refine((data) => !data.build_available || data.build_skills, {\n message: \"Please tell us about your build skills\",\n path: [\"build_skills\"],\n })\n .refine((data) => !data.strike_available || data.strike_help, {\n message: \"Please tell us how you can help with strike\",\n path: [\"strike_help\"],\n });\n\nexport const step5Schema = z.object({\n about_yourself: z.string().min(50, \"Please write at least 50 characters about yourself\"),\n agrees_to_principles: z.literal(true, { error: \"You must agree to the 10 Principles\" }),\n});\n\n// Combined schema for API-level validation — permissive so external camps\n// can submit applications with only first_name + last_name + email + custom_fields.\n// Step schemas (above) remain strict for the PlayaOS wizard UI.\nexport const applicationSchema = z.object({\n submission_id: z.string().uuid().optional(),\n /** The event applied to (ADR-132). Required only when the active camp year has several events. */\n event_id: z.string().uuid().optional(),\n acknowledged_expectations: z.literal(true).optional(),\n first_name: z.string().min(1),\n last_name: z.string(),\n email: z.string().email(),\n phone: z.string().optional(),\n referral_code: z.string().optional(),\n socials: z.string().optional(),\n birthday: z.string().optional(),\n hometown: z.string().optional(),\n how_heard: z.string().optional(),\n burning_man_before: z.enum([\"yes\", \"no\"]).optional(),\n burning_man_years: z.string().optional(),\n shelter_type: z.enum([\"joining_rv\", \"bringing_rv\", \"shiftpod_tent\", \"car\", \"truck\", \"van\", \"unsure\"]).optional(),\n shelter_mates: z.string().optional(),\n ticket_status: z.enum([\"looking\", \"have_ticket\", \"unsure\"]).optional(),\n build_available: z.boolean().optional(),\n build_skills: z.string().optional(),\n strike_available: z.boolean().optional(),\n strike_help: z.string().optional(),\n about_yourself: z.string().optional(),\n agrees_to_principles: z.literal(true).optional(),\n // Permissive at the API level (no bounds checks) — the server validates each\n // value against the live commitment definition before seeding (PLA-682).\n commitments: z.record(z.string(), z.union([z.number(), z.boolean()])).optional(),\n custom_fields: z.object({}).passthrough().optional(),\n});\n\nexport type ApplicationFormData = z.infer<typeof applicationSchema>;\nexport type Step0Data = z.infer<typeof step0Schema>;\nexport type Step1Data = z.infer<typeof step1Schema>;\nexport type Step2Data = z.infer<typeof step2Schema>;\nexport type Step3Data = z.infer<typeof step3Schema>;\nexport type Step4Data = z.infer<typeof step4Schema>;\nexport type Step5Data = z.infer<typeof step5Schema>;\n"],"mappings":"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"}
|