@domino-sdk/relay 1.0.0-next.2 → 1.0.0-next.34
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 +13 -1
- package/build.mjs +18 -1
- package/dist/activity-B8k9Sa_a.d.ts +9112 -0
- package/dist/authoring.d.ts +1355 -182
- package/dist/authoring.js +658 -225
- package/dist/automatic-outcomes-B1xrETxm.d.ts +758 -0
- package/dist/avatar.d.ts +29 -0
- package/dist/avatar.js +21 -0
- package/dist/browser-J7tUpXxy.d.ts +4154 -0
- package/dist/browser.d.ts +11 -4580
- package/dist/browser.js +8 -6
- package/dist/capability-error-DNMwKmlL.d.ts +458 -0
- package/dist/chunk-36HTX2BM.js +1223 -0
- package/dist/chunk-6QJ3LADK.js +112 -0
- package/dist/chunk-BGGKNIRP.js +171 -0
- package/dist/chunk-EYH5RDIE.js +496 -0
- package/dist/chunk-GQKYAQM6.js +84 -0
- package/dist/chunk-GUP7YRR4.js +42 -0
- package/dist/chunk-GZ6FJAXN.js +1659 -0
- package/dist/chunk-JON5SESL.js +2986 -0
- package/dist/chunk-MC6V6VMG.js +49 -0
- package/dist/chunk-NPGENI7K.js +37 -0
- package/dist/chunk-V7UKZLHA.js +35 -0
- package/dist/chunk-VFHHLN6A.js +284 -0
- package/dist/chunk-WJSSJ7AF.js +151 -0
- package/dist/{chunk-VH4OQ5VX.js → chunk-XFMSUPNS.js} +26 -5
- package/dist/{chunk-FDWRBMB3.js → chunk-ZVIRG24J.js} +150 -33
- package/dist/client-XiuFnug_.d.ts +4262 -0
- package/dist/groups-Ck-OxzjD.d.ts +2449 -0
- package/dist/identity-integration-GxAHdKR2.d.ts +58 -0
- package/dist/images-Dv-P5VBw.d.ts +234 -0
- package/dist/index.d.ts +15 -13115
- package/dist/index.js +30 -689
- package/dist/internal.d.ts +159 -0
- package/dist/internal.js +79 -0
- package/dist/offers-Cy-e4o5x.d.ts +431 -0
- package/dist/outcomes-kVB-Juzs.d.ts +4902 -0
- package/dist/pages-BBYD21IE.d.ts +359 -0
- package/dist/participant-rewards-3duLb8YJ.d.ts +668 -0
- package/dist/portal-proxy.js +26 -9
- package/dist/profiles-D2aFcOxu.d.ts +297 -0
- package/dist/react/index.d.ts +3378 -3318
- package/dist/react/index.js +1635 -783
- package/dist/request-error-DWduJCGV.d.ts +62 -0
- package/dist/schema-DfJzH2ci.d.ts +5644 -0
- package/dist/schema.d.ts +15 -3388
- package/dist/schema.js +790 -3
- package/dist/server/index.d.ts +81498 -0
- package/dist/server/index.js +2520 -0
- package/dist/streaks-CWyq8Px5.d.ts +71 -0
- package/dist/submission-input-BZkm6ohU.d.ts +290 -0
- package/dist/units-CwgsPB_r.d.ts +9 -0
- package/dist/vite.d.ts +1 -1
- package/dist/vite.js +1 -0
- package/dist/wallet-YssWxGg8.d.ts +228 -0
- package/package.json +24 -5
- package/dist/chunk-4KNTMNXA.js +0 -1847
- package/dist/chunk-B76BAJ25.js +0 -624
- package/dist/chunk-NKGJEYZM.js +0 -1833
- package/dist/chunk-ONDBQSMU.js +0 -373
- package/dist/submission-input-JDwq3EVK.d.ts +0 -4986
package/dist/chunk-4KNTMNXA.js
DELETED
|
@@ -1,1847 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
authoringIdentityShape,
|
|
3
|
-
engagementArtifactSchema,
|
|
4
|
-
engagementBoundaryPageSchema,
|
|
5
|
-
engagementDeploymentEntrySchema,
|
|
6
|
-
engagementPageQuerySchema,
|
|
7
|
-
engagementPageSchema,
|
|
8
|
-
leaderboardArtifactSchema,
|
|
9
|
-
leaderboardDefinitionSchema,
|
|
10
|
-
leaderboardPageSchema,
|
|
11
|
-
leaderboardPlacementSchema,
|
|
12
|
-
leaderboardPreviewSchema,
|
|
13
|
-
leaderboardQuerySchema,
|
|
14
|
-
normalizeAuthoringIdentity,
|
|
15
|
-
publishedReferralSchema,
|
|
16
|
-
referralAcceptSchema,
|
|
17
|
-
referralArtifactSchema,
|
|
18
|
-
referralDefinitionSchema,
|
|
19
|
-
referralHistorySchema,
|
|
20
|
-
referralSummarySchema,
|
|
21
|
-
validateAuthoringIdentity
|
|
22
|
-
} from "./chunk-B76BAJ25.js";
|
|
23
|
-
import {
|
|
24
|
-
authScopeSchema,
|
|
25
|
-
exchangeResultSchema,
|
|
26
|
-
memberSummarySchema,
|
|
27
|
-
sessionSchema
|
|
28
|
-
} from "./chunk-VH4OQ5VX.js";
|
|
29
|
-
import {
|
|
30
|
-
AVATAR_UPLOAD_LIMIT,
|
|
31
|
-
avatarUploadTypes,
|
|
32
|
-
linkedWalletSchema,
|
|
33
|
-
ownProfileSchema,
|
|
34
|
-
profileCompletionPageSchema,
|
|
35
|
-
profileCompletionQuerySchema,
|
|
36
|
-
profileReferralSchema,
|
|
37
|
-
profileSummarySchema,
|
|
38
|
-
profileUpdateSchema,
|
|
39
|
-
walletAddressInput,
|
|
40
|
-
walletAddressInputSchema,
|
|
41
|
-
walletChallengeInputSchema,
|
|
42
|
-
walletChallengeSchema,
|
|
43
|
-
walletConnectionSchema,
|
|
44
|
-
walletMessageChallengeSchema,
|
|
45
|
-
walletProofSchema,
|
|
46
|
-
walletSignInNetworksSchema,
|
|
47
|
-
walletSignatureSchema,
|
|
48
|
-
walletUnlinkInputSchema
|
|
49
|
-
} from "./chunk-ONDBQSMU.js";
|
|
50
|
-
import {
|
|
51
|
-
accountConnectionSchema,
|
|
52
|
-
attemptSchema,
|
|
53
|
-
authProviderSchema,
|
|
54
|
-
contentAdmissionPageSchema,
|
|
55
|
-
contentAdmissionQuerySchema,
|
|
56
|
-
contentAdmissionSchema,
|
|
57
|
-
contentEnrollmentInputSchema,
|
|
58
|
-
contentEnrollmentSchema,
|
|
59
|
-
contentPerformancePageSchema,
|
|
60
|
-
contentPerformanceQuerySchema,
|
|
61
|
-
contentQualificationPageSchema,
|
|
62
|
-
contentQualificationQuerySchema,
|
|
63
|
-
contentReleaseInputSchema,
|
|
64
|
-
entitlementSchema,
|
|
65
|
-
errorSchema,
|
|
66
|
-
evidenceSchema,
|
|
67
|
-
identifier,
|
|
68
|
-
memberProgressSchema,
|
|
69
|
-
photoResultSchema,
|
|
70
|
-
pickupAvailabilitySchema,
|
|
71
|
-
pickupSelectionSchema,
|
|
72
|
-
publishedReleaseSchema,
|
|
73
|
-
publishedTrackerSchema,
|
|
74
|
-
questDescriptionSchema,
|
|
75
|
-
quizEvidenceSchema,
|
|
76
|
-
releaseSchema,
|
|
77
|
-
reviewModeSchema,
|
|
78
|
-
settingsValuesSchema,
|
|
79
|
-
snapshotSchema,
|
|
80
|
-
storedReviewModeSchema,
|
|
81
|
-
submissionEvidenceSchema,
|
|
82
|
-
templateSchema,
|
|
83
|
-
tieredRewardReferenceSchema,
|
|
84
|
-
trackerArtifactSchema,
|
|
85
|
-
validateSubmissionValue,
|
|
86
|
-
valueEvidenceSchema,
|
|
87
|
-
xTweetSchema
|
|
88
|
-
} from "./chunk-NKGJEYZM.js";
|
|
89
|
-
|
|
90
|
-
// src/point-ledgers.ts
|
|
91
|
-
import { z } from "zod";
|
|
92
|
-
var pointLedgerPropertiesSchema = z.object({
|
|
93
|
-
name: z.string().trim().min(1).max(120),
|
|
94
|
-
description: z.string().trim().max(1e3).default("")
|
|
95
|
-
}).strict();
|
|
96
|
-
var createPointLedgerSchema = pointLedgerPropertiesSchema.extend({ actionId: identifier, key: identifier.optional() }).strict();
|
|
97
|
-
var pointLedgerSchema = pointLedgerPropertiesSchema.extend({
|
|
98
|
-
id: identifier
|
|
99
|
-
});
|
|
100
|
-
var pointLedgerDeclarationSchema = pointLedgerPropertiesSchema.extend({ key: identifier }).strict();
|
|
101
|
-
var pointLedgerReferenceSchema = z.object({
|
|
102
|
-
id: identifier,
|
|
103
|
-
key: identifier.nullable(),
|
|
104
|
-
name: z.string()
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
// src/reward-deliveries.ts
|
|
108
|
-
import { z as z2 } from "zod";
|
|
109
|
-
var rewardDeliverySchema = z2.object({
|
|
110
|
-
id: z2.string(),
|
|
111
|
-
quest: z2.string(),
|
|
112
|
-
completion: z2.string(),
|
|
113
|
-
member: z2.string(),
|
|
114
|
-
provider: z2.literal("discord"),
|
|
115
|
-
action: z2.literal("grant-role"),
|
|
116
|
-
roleId: z2.string(),
|
|
117
|
-
/**
|
|
118
|
-
* `failed` is terminal: Discord rejected the grant permanently (unknown role,
|
|
119
|
-
* member left the server, missing permissions) or retries ran out after
|
|
120
|
-
* about a day. An operator can retry it once the cause is fixed.
|
|
121
|
-
*/
|
|
122
|
-
status: z2.enum(["pending", "delivered", "failed"]),
|
|
123
|
-
/** Provider attempts in the current round; an operator retry starts a new round at zero. */
|
|
124
|
-
attempts: z2.number().int(),
|
|
125
|
-
/** While pending with a `lastError`, when the next attempt is scheduled. */
|
|
126
|
-
nextAt: z2.number(),
|
|
127
|
-
lastError: z2.string().nullable(),
|
|
128
|
-
createdAt: z2.number(),
|
|
129
|
-
deliveredAt: z2.number().nullable()
|
|
130
|
-
});
|
|
131
|
-
var rewardDeliveriesSchema = z2.object({
|
|
132
|
-
deliveries: z2.array(rewardDeliverySchema)
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
// src/catalog.ts
|
|
136
|
-
import { z as z3 } from "zod";
|
|
137
|
-
var interactionSchema = z3.enum([
|
|
138
|
-
"photo",
|
|
139
|
-
"text",
|
|
140
|
-
"url",
|
|
141
|
-
"quiz",
|
|
142
|
-
"claim",
|
|
143
|
-
"staff",
|
|
144
|
-
"automatic"
|
|
145
|
-
]);
|
|
146
|
-
function questInteraction(trigger) {
|
|
147
|
-
return trigger.kind === "automatic" ? "automatic" : trigger.actor === "staff" ? "staff" : trigger.input === "none" ? "claim" : trigger.input;
|
|
148
|
-
}
|
|
149
|
-
var questTypeVersionSchema = z3.object({
|
|
150
|
-
key: identifier.optional(),
|
|
151
|
-
id: identifier,
|
|
152
|
-
version: identifier,
|
|
153
|
-
code: z3.string(),
|
|
154
|
-
definition: questDescriptionSchema,
|
|
155
|
-
provider: storedReviewModeSchema,
|
|
156
|
-
createdAt: z3.number()
|
|
157
|
-
});
|
|
158
|
-
var collectionSlotSchema = z3.object({
|
|
159
|
-
id: identifier,
|
|
160
|
-
key: identifier.optional(),
|
|
161
|
-
title: z3.string().trim().min(1).max(120)
|
|
162
|
-
}).strict();
|
|
163
|
-
var collectionSlotDeclarationSchema = collectionSlotSchema.omit({ id: true }).extend(authoringIdentityShape).strict().superRefine(validateAuthoringIdentity).transform(normalizeAuthoringIdentity);
|
|
164
|
-
var questCollectionSchema = collectionSlotSchema.extend({
|
|
165
|
-
quests: z3.array(identifier).max(100).refine(
|
|
166
|
-
(v) => new Set(v).size === v.length,
|
|
167
|
-
"A collection can contain a quest only once"
|
|
168
|
-
)
|
|
169
|
-
});
|
|
170
|
-
var questInstanceSchema = z3.object({
|
|
171
|
-
id: identifier,
|
|
172
|
-
title: z3.string().trim().min(1).max(120),
|
|
173
|
-
typeVersion: identifier,
|
|
174
|
-
settings: settingsValuesSchema,
|
|
175
|
-
requires: z3.array(identifier).max(30),
|
|
176
|
-
status: z3.enum(["active", "paused", "archived"])
|
|
177
|
-
}).strict();
|
|
178
|
-
var questDraftChangesSchema = z3.object({
|
|
179
|
-
quests: z3.array(
|
|
180
|
-
questInstanceSchema.extend({ expectedRelease: identifier.nullable() })
|
|
181
|
-
).max(50),
|
|
182
|
-
collections: z3.array(questCollectionSchema).max(50)
|
|
183
|
-
}).strict();
|
|
184
|
-
var draftBase = z3.object({
|
|
185
|
-
id: identifier,
|
|
186
|
-
revision: z3.number().int().positive(),
|
|
187
|
-
baseRevision: z3.number().int().nonnegative(),
|
|
188
|
-
changes: questDraftChangesSchema
|
|
189
|
-
});
|
|
190
|
-
var questDraftSchema = z3.discriminatedUnion("status", [
|
|
191
|
-
draftBase.extend({ status: z3.literal("draft") }),
|
|
192
|
-
draftBase.extend({
|
|
193
|
-
status: z3.literal("published"),
|
|
194
|
-
releaseIds: z3.array(identifier)
|
|
195
|
-
})
|
|
196
|
-
]);
|
|
197
|
-
var questCatalogSchema = z3.object({
|
|
198
|
-
revision: z3.number().int().nonnegative(),
|
|
199
|
-
types: z3.array(questTypeVersionSchema),
|
|
200
|
-
collections: z3.array(questCollectionSchema),
|
|
201
|
-
quests: z3.array(questInstanceSchema),
|
|
202
|
-
drafts: z3.array(questDraftSchema),
|
|
203
|
-
releases: z3.array(publishedReleaseSchema).default([]),
|
|
204
|
-
supportedInteractions: z3.array(interactionSchema)
|
|
205
|
-
});
|
|
206
|
-
var catalogDeploymentSchema = z3.object({
|
|
207
|
-
expectedRevision: z3.number().int().nonnegative(),
|
|
208
|
-
types: z3.array(
|
|
209
|
-
z3.object({
|
|
210
|
-
code: z3.string().min(1).max(1e6),
|
|
211
|
-
provider: reviewModeSchema
|
|
212
|
-
})
|
|
213
|
-
).max(50).default([]),
|
|
214
|
-
collections: z3.array(collectionSlotDeclarationSchema).max(50).default([]),
|
|
215
|
-
supportedInteractions: z3.array(interactionSchema).min(1).optional()
|
|
216
|
-
}).strict();
|
|
217
|
-
var catalogDeploymentPreviewSchema = z3.object({
|
|
218
|
-
revision: z3.number().int().nonnegative(),
|
|
219
|
-
types: z3.array(questTypeVersionSchema),
|
|
220
|
-
collections: z3.array(collectionSlotSchema),
|
|
221
|
-
supportedInteractions: z3.array(interactionSchema)
|
|
222
|
-
});
|
|
223
|
-
var saveQuestDraftSchema = z3.object({
|
|
224
|
-
id: identifier.optional(),
|
|
225
|
-
actionId: identifier,
|
|
226
|
-
expectedRevision: z3.number().int().nonnegative(),
|
|
227
|
-
baseRevision: z3.number().int().nonnegative(),
|
|
228
|
-
changes: questDraftChangesSchema
|
|
229
|
-
}).strict();
|
|
230
|
-
var publishQuestDraftSchema = z3.object({ id: identifier, expectedRevision: z3.number().int().positive() }).strict();
|
|
231
|
-
var questRewardViewSchema = z3.discriminatedUnion("kind", [
|
|
232
|
-
z3.object({
|
|
233
|
-
kind: z3.literal("points"),
|
|
234
|
-
label: z3.string(),
|
|
235
|
-
amount: z3.number().int().nonnegative(),
|
|
236
|
-
ledger: pointLedgerReferenceSchema
|
|
237
|
-
}),
|
|
238
|
-
z3.object({
|
|
239
|
-
kind: z3.literal("tier"),
|
|
240
|
-
label: z3.string(),
|
|
241
|
-
reward: tieredRewardReferenceSchema.extend({ title: z3.string() }),
|
|
242
|
-
tier: identifier
|
|
243
|
-
}),
|
|
244
|
-
z3.object({ kind: z3.literal("integration"), label: z3.string() })
|
|
245
|
-
]);
|
|
246
|
-
var questViewSchema = memberProgressSchema.shape.quests.element.extend(
|
|
247
|
-
{
|
|
248
|
-
release: identifier,
|
|
249
|
-
interaction: interactionSchema,
|
|
250
|
-
lifecycle: z3.enum(["active", "paused", "archived"]),
|
|
251
|
-
rewards: z3.array(questRewardViewSchema)
|
|
252
|
-
}
|
|
253
|
-
);
|
|
254
|
-
var collectionViewSchema = z3.object({
|
|
255
|
-
key: identifier.optional(),
|
|
256
|
-
id: identifier,
|
|
257
|
-
title: z3.string(),
|
|
258
|
-
quests: z3.array(questViewSchema)
|
|
259
|
-
});
|
|
260
|
-
var questExperienceSchema = z3.object({
|
|
261
|
-
member: identifier,
|
|
262
|
-
quests: z3.array(questViewSchema),
|
|
263
|
-
collections: z3.array(collectionViewSchema)
|
|
264
|
-
});
|
|
265
|
-
var questPublicationPreviewSchema = z3.object({
|
|
266
|
-
draft: questDraftSchema,
|
|
267
|
-
releases: z3.array(publishedReleaseSchema),
|
|
268
|
-
affectedCollections: z3.array(questCollectionSchema)
|
|
269
|
-
});
|
|
270
|
-
var allocateQuestSchema = z3.object({ actionId: identifier }).strict();
|
|
271
|
-
var allocatedQuestSchema = z3.object({ id: identifier });
|
|
272
|
-
|
|
273
|
-
// src/errors.ts
|
|
274
|
-
var RelayError = class extends Error {
|
|
275
|
-
constructor(message, status, missing = [], code) {
|
|
276
|
-
super(message);
|
|
277
|
-
this.status = status;
|
|
278
|
-
this.missing = missing;
|
|
279
|
-
this.code = code;
|
|
280
|
-
}
|
|
281
|
-
status;
|
|
282
|
-
missing;
|
|
283
|
-
code;
|
|
284
|
-
};
|
|
285
|
-
|
|
286
|
-
// src/submissions.ts
|
|
287
|
-
import { z as z4 } from "zod";
|
|
288
|
-
var common = {
|
|
289
|
-
id: identifier,
|
|
290
|
-
quest: identifier,
|
|
291
|
-
release: identifier.optional()
|
|
292
|
-
};
|
|
293
|
-
var claimInputSchema = z4.union([
|
|
294
|
-
submissionEvidenceSchema,
|
|
295
|
-
z4.object({ kind: z4.literal("none") }).strict()
|
|
296
|
-
]);
|
|
297
|
-
var draftSchema = z4.union([
|
|
298
|
-
claimInputSchema,
|
|
299
|
-
z4.object({ kind: z4.literal("photo"), file: z4.instanceof(Blob) })
|
|
300
|
-
]);
|
|
301
|
-
var recordSchema = z4.union([
|
|
302
|
-
z4.object({
|
|
303
|
-
...common,
|
|
304
|
-
stage: z4.literal("review"),
|
|
305
|
-
draft: draftSchema.nullable()
|
|
306
|
-
}),
|
|
307
|
-
z4.object({ ...common, stage: z4.literal("upload"), file: z4.instanceof(Blob) }),
|
|
308
|
-
z4.object({
|
|
309
|
-
...common,
|
|
310
|
-
stage: z4.literal("claim"),
|
|
311
|
-
evidence: identifier,
|
|
312
|
-
file: z4.instanceof(Blob).optional()
|
|
313
|
-
}),
|
|
314
|
-
z4.object({
|
|
315
|
-
...common,
|
|
316
|
-
stage: z4.literal("submitted"),
|
|
317
|
-
evidence: identifier,
|
|
318
|
-
attempt: identifier
|
|
319
|
-
}),
|
|
320
|
-
z4.object({ ...common, stage: z4.literal("claim"), input: claimInputSchema }),
|
|
321
|
-
z4.object({
|
|
322
|
-
...common,
|
|
323
|
-
stage: z4.literal("submitted"),
|
|
324
|
-
input: claimInputSchema,
|
|
325
|
-
attempt: identifier
|
|
326
|
-
})
|
|
327
|
-
]);
|
|
328
|
-
function submissions(transport, configuredStore, namespace) {
|
|
329
|
-
async function open(quest, options = {
|
|
330
|
-
input: "photo"
|
|
331
|
-
}) {
|
|
332
|
-
if (!configuredStore) {
|
|
333
|
-
throw new Error(
|
|
334
|
-
"Submissions require durable storage. Use createBrowserRelayClient or provide a SubmissionStore."
|
|
335
|
-
);
|
|
336
|
-
}
|
|
337
|
-
const store = configuredStore;
|
|
338
|
-
identifier.parse(quest);
|
|
339
|
-
const session = await transport.session();
|
|
340
|
-
if (session?.principal.kind !== "member") {
|
|
341
|
-
throw new Error("Sign in to submit an activity");
|
|
342
|
-
}
|
|
343
|
-
const sessionId = session.id;
|
|
344
|
-
const key = JSON.stringify([
|
|
345
|
-
"relay-submission-v1",
|
|
346
|
-
namespace,
|
|
347
|
-
session.organization,
|
|
348
|
-
session.environment,
|
|
349
|
-
session.project,
|
|
350
|
-
session.principal.member,
|
|
351
|
-
quest
|
|
352
|
-
]);
|
|
353
|
-
async function currentSession() {
|
|
354
|
-
const current = await transport.session();
|
|
355
|
-
if (current?.id !== sessionId) {
|
|
356
|
-
throw new Error(
|
|
357
|
-
"Your session changed. Reopen the submission before continuing."
|
|
358
|
-
);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
async function read() {
|
|
362
|
-
const saved = await store.read(key);
|
|
363
|
-
if (saved === void 0 || saved === null) {
|
|
364
|
-
return null;
|
|
365
|
-
}
|
|
366
|
-
const parsed = recordSchema.safeParse(saved);
|
|
367
|
-
if (!parsed.success || parsed.data.quest !== quest) {
|
|
368
|
-
throw new Error(
|
|
369
|
-
"Saved submission could not be read. Do not create another claim until it is recovered."
|
|
370
|
-
);
|
|
371
|
-
}
|
|
372
|
-
const record = parsed.data;
|
|
373
|
-
const input = record.stage === "review" ? record.draft?.kind : "input" in record ? record.input.kind : "photo";
|
|
374
|
-
if (!options.recoverPrevious && input !== options.input) {
|
|
375
|
-
throw new Error(
|
|
376
|
-
"Saved submission uses a different input type. Reopen it with its original type to recover it."
|
|
377
|
-
);
|
|
378
|
-
}
|
|
379
|
-
return record;
|
|
380
|
-
}
|
|
381
|
-
function claim(record) {
|
|
382
|
-
return transport.claim(
|
|
383
|
-
{
|
|
384
|
-
quest,
|
|
385
|
-
actionId: record.id,
|
|
386
|
-
...record.release ? { release: record.release } : {},
|
|
387
|
-
..."evidence" in record ? { evidence: record.evidence } : record.input.kind !== "none" ? { input: record.input } : {}
|
|
388
|
-
},
|
|
389
|
-
sessionId
|
|
390
|
-
);
|
|
391
|
-
}
|
|
392
|
-
async function resumeRecord(saved) {
|
|
393
|
-
if (saved.stage === "review") {
|
|
394
|
-
throw new QuestUpdatedError(
|
|
395
|
-
"This quest changed. Review it before submitting again.",
|
|
396
|
-
"quest-updated",
|
|
397
|
-
saved.draft
|
|
398
|
-
);
|
|
399
|
-
}
|
|
400
|
-
let record = saved;
|
|
401
|
-
if (record.stage === "upload") {
|
|
402
|
-
const evidence = await transport.upload(
|
|
403
|
-
record.file,
|
|
404
|
-
record.id,
|
|
405
|
-
sessionId
|
|
406
|
-
);
|
|
407
|
-
record = {
|
|
408
|
-
id: record.id,
|
|
409
|
-
quest,
|
|
410
|
-
...record.release ? { release: record.release } : {},
|
|
411
|
-
file: record.file,
|
|
412
|
-
stage: "claim",
|
|
413
|
-
evidence: evidence.id
|
|
414
|
-
};
|
|
415
|
-
await store.write(key, record);
|
|
416
|
-
}
|
|
417
|
-
let attempt;
|
|
418
|
-
try {
|
|
419
|
-
attempt = await claim(record);
|
|
420
|
-
} catch (error) {
|
|
421
|
-
if (error instanceof RelayError && error.status === 422 && error.code === "invalid-submission" && record.stage === "claim") {
|
|
422
|
-
await store.write(key, null);
|
|
423
|
-
throw error;
|
|
424
|
-
}
|
|
425
|
-
if (error instanceof RelayError && error.status === 409 && (error.code === "quest-updated" || error.code === "stale-quiz") && record.stage === "claim") {
|
|
426
|
-
const draft = "input" in record ? record.input : "file" in record && record.file ? { kind: "photo", file: record.file } : null;
|
|
427
|
-
await store.write(
|
|
428
|
-
key,
|
|
429
|
-
error.code === "quest-updated" ? {
|
|
430
|
-
id: record.id,
|
|
431
|
-
quest,
|
|
432
|
-
release: record.release,
|
|
433
|
-
stage: "review",
|
|
434
|
-
draft
|
|
435
|
-
} : null
|
|
436
|
-
);
|
|
437
|
-
throw new QuestUpdatedError(error.message, error.code, draft);
|
|
438
|
-
}
|
|
439
|
-
throw error;
|
|
440
|
-
}
|
|
441
|
-
await store.write(key, {
|
|
442
|
-
...record,
|
|
443
|
-
stage: "submitted",
|
|
444
|
-
attempt: attempt.id
|
|
445
|
-
});
|
|
446
|
-
if (attempt.status === "failed") {
|
|
447
|
-
attempt = await transport.retry(attempt.id, sessionId);
|
|
448
|
-
}
|
|
449
|
-
return attempt;
|
|
450
|
-
}
|
|
451
|
-
async function submit(record) {
|
|
452
|
-
return store.exclusive(key, async () => {
|
|
453
|
-
await currentSession();
|
|
454
|
-
const existing = await read();
|
|
455
|
-
if (existing?.stage === "review" && existing.release === record.release) {
|
|
456
|
-
throw new QuestUpdatedError(
|
|
457
|
-
"Review the latest quest before submitting again.",
|
|
458
|
-
"quest-updated",
|
|
459
|
-
existing.draft
|
|
460
|
-
);
|
|
461
|
-
}
|
|
462
|
-
if (existing && existing.stage !== "submitted" && existing.stage !== "review") {
|
|
463
|
-
throw new Error(
|
|
464
|
-
"A submission is unfinished. Resume it before choosing new input."
|
|
465
|
-
);
|
|
466
|
-
}
|
|
467
|
-
if (existing?.stage === "submitted") {
|
|
468
|
-
const previous = await claim(existing);
|
|
469
|
-
if (previous.status === "failed") {
|
|
470
|
-
return transport.retry(previous.id, sessionId);
|
|
471
|
-
}
|
|
472
|
-
if (previous.status !== "rejected" && !(options.repeatable && previous.status === "accepted")) {
|
|
473
|
-
return previous;
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
await store.write(key, record);
|
|
477
|
-
return resumeRecord(record);
|
|
478
|
-
});
|
|
479
|
-
}
|
|
480
|
-
const handle = {
|
|
481
|
-
async discard() {
|
|
482
|
-
return store.exclusive(key, async () => {
|
|
483
|
-
await currentSession();
|
|
484
|
-
const record = await read();
|
|
485
|
-
if (!record) {
|
|
486
|
-
return;
|
|
487
|
-
}
|
|
488
|
-
if (record.stage !== "submitted") {
|
|
489
|
-
throw new Error(
|
|
490
|
-
"Resume the unfinished submission before starting over."
|
|
491
|
-
);
|
|
492
|
-
}
|
|
493
|
-
const attempt = await claim(record);
|
|
494
|
-
if (attempt.status !== "failed" && attempt.status !== "rejected" && !(options.repeatable && attempt.status === "accepted")) {
|
|
495
|
-
throw new Error(
|
|
496
|
-
"Only a failed or rejected submission can be discarded."
|
|
497
|
-
);
|
|
498
|
-
}
|
|
499
|
-
await store.write(key, null);
|
|
500
|
-
});
|
|
501
|
-
},
|
|
502
|
-
async status() {
|
|
503
|
-
await currentSession();
|
|
504
|
-
const record = await read();
|
|
505
|
-
if (!record) {
|
|
506
|
-
return { kind: "empty" };
|
|
507
|
-
}
|
|
508
|
-
if (record.stage === "review") {
|
|
509
|
-
return { kind: "needs-review" };
|
|
510
|
-
}
|
|
511
|
-
return record.stage === "submitted" ? { kind: "submitted", attempt: record.attempt } : { kind: "pending", stage: record.stage };
|
|
512
|
-
},
|
|
513
|
-
async resume() {
|
|
514
|
-
return store.exclusive(key, async () => {
|
|
515
|
-
await currentSession();
|
|
516
|
-
const record = await read();
|
|
517
|
-
if (!record) {
|
|
518
|
-
throw new Error("There is no saved submission to resume");
|
|
519
|
-
}
|
|
520
|
-
return resumeRecord(record);
|
|
521
|
-
});
|
|
522
|
-
}
|
|
523
|
-
};
|
|
524
|
-
if (options.input === "text" || options.input === "url") {
|
|
525
|
-
const kind = options.input;
|
|
526
|
-
return {
|
|
527
|
-
...handle,
|
|
528
|
-
submit(value) {
|
|
529
|
-
const input = valueEvidenceSchema.parse({ kind, value });
|
|
530
|
-
return submit({
|
|
531
|
-
id: crypto.randomUUID(),
|
|
532
|
-
quest,
|
|
533
|
-
release: options.release,
|
|
534
|
-
stage: "claim",
|
|
535
|
-
input
|
|
536
|
-
});
|
|
537
|
-
}
|
|
538
|
-
};
|
|
539
|
-
}
|
|
540
|
-
if (options.input === "quiz") {
|
|
541
|
-
return {
|
|
542
|
-
...handle,
|
|
543
|
-
submit(answers, version) {
|
|
544
|
-
const input = quizEvidenceSchema.parse({
|
|
545
|
-
kind: "quiz",
|
|
546
|
-
answers,
|
|
547
|
-
...version || options.release ? { release: version?.release ?? options.release } : {}
|
|
548
|
-
});
|
|
549
|
-
return submit({
|
|
550
|
-
id: crypto.randomUUID(),
|
|
551
|
-
...options.release ? { release: options.release } : {},
|
|
552
|
-
quest,
|
|
553
|
-
stage: "claim",
|
|
554
|
-
input
|
|
555
|
-
});
|
|
556
|
-
}
|
|
557
|
-
};
|
|
558
|
-
}
|
|
559
|
-
if (options.input === "none") {
|
|
560
|
-
return {
|
|
561
|
-
...handle,
|
|
562
|
-
submit() {
|
|
563
|
-
return submit({
|
|
564
|
-
id: crypto.randomUUID(),
|
|
565
|
-
...options.release ? { release: options.release } : {},
|
|
566
|
-
quest,
|
|
567
|
-
stage: "claim",
|
|
568
|
-
input: { kind: "none" }
|
|
569
|
-
});
|
|
570
|
-
}
|
|
571
|
-
};
|
|
572
|
-
}
|
|
573
|
-
return {
|
|
574
|
-
...handle,
|
|
575
|
-
async submit(file) {
|
|
576
|
-
if (!["image/jpeg", "image/png"].includes(file.type) || file.size === 0 || file.size > 5 * 1024 * 1024) {
|
|
577
|
-
throw new Error("Choose a JPG or PNG photo under 5 MB");
|
|
578
|
-
}
|
|
579
|
-
const bytes = new Uint8Array(await file.slice(0, 4).arrayBuffer());
|
|
580
|
-
const signature = file.type === "image/png" ? [137, 80, 78, 71] : [255, 216, 255];
|
|
581
|
-
if (!signature.every((byte, index) => bytes[index] === byte)) {
|
|
582
|
-
throw new Error("Image content does not match its file type");
|
|
583
|
-
}
|
|
584
|
-
return submit({
|
|
585
|
-
id: crypto.randomUUID(),
|
|
586
|
-
...options.release ? { release: options.release } : {},
|
|
587
|
-
quest,
|
|
588
|
-
stage: "upload",
|
|
589
|
-
file
|
|
590
|
-
});
|
|
591
|
-
}
|
|
592
|
-
};
|
|
593
|
-
}
|
|
594
|
-
return open;
|
|
595
|
-
}
|
|
596
|
-
var QuestUpdatedError = class extends RelayError {
|
|
597
|
-
constructor(message, code, draft) {
|
|
598
|
-
super(message, 409, [], code);
|
|
599
|
-
this.draft = draft;
|
|
600
|
-
}
|
|
601
|
-
draft;
|
|
602
|
-
};
|
|
603
|
-
|
|
604
|
-
// src/quest-experience.ts
|
|
605
|
-
function reconcileQuestDraft(view, draft) {
|
|
606
|
-
if (!draft) {
|
|
607
|
-
return null;
|
|
608
|
-
}
|
|
609
|
-
if (draft.kind === "text" || draft.kind === "url") {
|
|
610
|
-
return view.interaction === draft.kind ? draft : null;
|
|
611
|
-
}
|
|
612
|
-
if (draft.kind === "photo") {
|
|
613
|
-
return view.interaction === "photo" ? draft : null;
|
|
614
|
-
}
|
|
615
|
-
if (draft.kind === "none") {
|
|
616
|
-
return view.interaction === "claim" ? draft : null;
|
|
617
|
-
}
|
|
618
|
-
if (view.interaction !== "quiz") {
|
|
619
|
-
return null;
|
|
620
|
-
}
|
|
621
|
-
const answers = Object.fromEntries(
|
|
622
|
-
(view.presentation.quiz ?? []).flatMap((q) => {
|
|
623
|
-
const answer = draft.answers[q.id];
|
|
624
|
-
return q.choices.some((c) => c.id === answer) ? [[q.id, answer]] : [];
|
|
625
|
-
})
|
|
626
|
-
);
|
|
627
|
-
return { kind: "quiz", release: view.release, answers };
|
|
628
|
-
}
|
|
629
|
-
function questActions(submission, latest) {
|
|
630
|
-
return async (view) => {
|
|
631
|
-
async function run(task) {
|
|
632
|
-
try {
|
|
633
|
-
return { kind: "submitted", attempt: await task() };
|
|
634
|
-
} catch (error) {
|
|
635
|
-
if (!(error instanceof QuestUpdatedError)) {
|
|
636
|
-
throw error;
|
|
637
|
-
}
|
|
638
|
-
const current = await latest(view.quest).catch(() => {
|
|
639
|
-
throw error;
|
|
640
|
-
});
|
|
641
|
-
return {
|
|
642
|
-
kind: "quest-updated",
|
|
643
|
-
latest: current,
|
|
644
|
-
originalDraft: error.draft,
|
|
645
|
-
draft: reconcileQuestDraft(current, error.draft)
|
|
646
|
-
};
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
if (view.lifecycle !== "active" || view.interaction === "staff" || view.interaction === "automatic") {
|
|
650
|
-
const handle = await submission(view.quest, {
|
|
651
|
-
input: "none",
|
|
652
|
-
release: view.release,
|
|
653
|
-
recoverPrevious: true,
|
|
654
|
-
repeatable: view.completion.kind === "keyed"
|
|
655
|
-
});
|
|
656
|
-
return {
|
|
657
|
-
kind: "status",
|
|
658
|
-
view,
|
|
659
|
-
status: handle.status,
|
|
660
|
-
discard: handle.discard,
|
|
661
|
-
resume: () => run(handle.resume)
|
|
662
|
-
};
|
|
663
|
-
}
|
|
664
|
-
switch (view.interaction) {
|
|
665
|
-
case "text":
|
|
666
|
-
case "url": {
|
|
667
|
-
const kind = view.interaction;
|
|
668
|
-
const handle = await submission(view.quest, {
|
|
669
|
-
input: kind,
|
|
670
|
-
release: view.release,
|
|
671
|
-
recoverPrevious: true,
|
|
672
|
-
repeatable: view.completion.kind === "keyed"
|
|
673
|
-
});
|
|
674
|
-
return {
|
|
675
|
-
kind,
|
|
676
|
-
view,
|
|
677
|
-
status: handle.status,
|
|
678
|
-
discard: handle.discard,
|
|
679
|
-
resume: () => run(handle.resume),
|
|
680
|
-
submit: (value) => run(() => {
|
|
681
|
-
if (view.trigger.kind !== "manual" || view.trigger.input !== "text" && view.trigger.input !== "url") {
|
|
682
|
-
throw new Error("Quest input changed");
|
|
683
|
-
}
|
|
684
|
-
const problem = validateSubmissionValue(
|
|
685
|
-
{ kind, value },
|
|
686
|
-
view.trigger
|
|
687
|
-
);
|
|
688
|
-
if (problem) {
|
|
689
|
-
throw new Error(problem);
|
|
690
|
-
}
|
|
691
|
-
return handle.submit(value);
|
|
692
|
-
})
|
|
693
|
-
};
|
|
694
|
-
}
|
|
695
|
-
case "photo": {
|
|
696
|
-
const handle = await submission(view.quest, {
|
|
697
|
-
input: "photo",
|
|
698
|
-
release: view.release,
|
|
699
|
-
recoverPrevious: true,
|
|
700
|
-
repeatable: view.completion.kind === "keyed"
|
|
701
|
-
});
|
|
702
|
-
return {
|
|
703
|
-
kind: "photo",
|
|
704
|
-
view,
|
|
705
|
-
status: handle.status,
|
|
706
|
-
discard: handle.discard,
|
|
707
|
-
resume: () => run(handle.resume),
|
|
708
|
-
submit: (file) => run(() => handle.submit(file))
|
|
709
|
-
};
|
|
710
|
-
}
|
|
711
|
-
case "quiz": {
|
|
712
|
-
const handle = await submission(view.quest, {
|
|
713
|
-
input: "quiz",
|
|
714
|
-
release: view.release,
|
|
715
|
-
recoverPrevious: true,
|
|
716
|
-
repeatable: view.completion.kind === "keyed"
|
|
717
|
-
});
|
|
718
|
-
return {
|
|
719
|
-
kind: "quiz",
|
|
720
|
-
view,
|
|
721
|
-
status: handle.status,
|
|
722
|
-
discard: handle.discard,
|
|
723
|
-
resume: () => run(handle.resume),
|
|
724
|
-
submit: (answers) => run(() => handle.submit(answers, { release: view.release }))
|
|
725
|
-
};
|
|
726
|
-
}
|
|
727
|
-
case "claim": {
|
|
728
|
-
const handle = await submission(view.quest, {
|
|
729
|
-
input: "none",
|
|
730
|
-
release: view.release,
|
|
731
|
-
recoverPrevious: true,
|
|
732
|
-
repeatable: view.completion.kind === "keyed"
|
|
733
|
-
});
|
|
734
|
-
return {
|
|
735
|
-
kind: "claim",
|
|
736
|
-
view,
|
|
737
|
-
status: handle.status,
|
|
738
|
-
discard: handle.discard,
|
|
739
|
-
resume: () => run(handle.resume),
|
|
740
|
-
submit: () => run(handle.submit)
|
|
741
|
-
};
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
};
|
|
745
|
-
}
|
|
746
|
-
|
|
747
|
-
// src/progress.ts
|
|
748
|
-
function observeProgress(transport, listener, options = {}, onDispose = () => {
|
|
749
|
-
}) {
|
|
750
|
-
const interval = options.intervalMs ?? 1500;
|
|
751
|
-
const maximum = options.maxBackoffMs ?? 3e4;
|
|
752
|
-
if (!Number.isFinite(interval) || interval <= 0 || !Number.isFinite(maximum) || maximum < interval) {
|
|
753
|
-
throw new Error(
|
|
754
|
-
"Progress polling requires a positive interval and a maximum at least as large"
|
|
755
|
-
);
|
|
756
|
-
}
|
|
757
|
-
let disposed = false;
|
|
758
|
-
let controller;
|
|
759
|
-
let timer;
|
|
760
|
-
let sessionId;
|
|
761
|
-
let failures = 0;
|
|
762
|
-
function clear() {
|
|
763
|
-
controller?.abort();
|
|
764
|
-
if (timer !== void 0) {
|
|
765
|
-
clearTimeout(timer);
|
|
766
|
-
}
|
|
767
|
-
sessionId = void 0;
|
|
768
|
-
if (!disposed) {
|
|
769
|
-
listener({ kind: "loading" });
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
async function refresh() {
|
|
773
|
-
if (disposed) {
|
|
774
|
-
return;
|
|
775
|
-
}
|
|
776
|
-
controller?.abort();
|
|
777
|
-
if (timer !== void 0) {
|
|
778
|
-
clearTimeout(timer);
|
|
779
|
-
}
|
|
780
|
-
const request = new AbortController();
|
|
781
|
-
controller = request;
|
|
782
|
-
const current = () => !disposed && !request.signal.aborted;
|
|
783
|
-
try {
|
|
784
|
-
const session = await transport.session(request.signal);
|
|
785
|
-
if (!current()) {
|
|
786
|
-
return;
|
|
787
|
-
}
|
|
788
|
-
if (sessionId !== (session?.id ?? null)) {
|
|
789
|
-
sessionId = session?.id ?? null;
|
|
790
|
-
listener({ kind: "session", session });
|
|
791
|
-
}
|
|
792
|
-
if (session?.principal.kind === "member") {
|
|
793
|
-
const progress = await transport.progress(session.id, request.signal);
|
|
794
|
-
if (!current()) {
|
|
795
|
-
return;
|
|
796
|
-
}
|
|
797
|
-
const confirmed = await transport.session(request.signal);
|
|
798
|
-
if (!current()) {
|
|
799
|
-
return;
|
|
800
|
-
}
|
|
801
|
-
if (confirmed?.id !== session.id || progress.member !== session.principal.member) {
|
|
802
|
-
sessionId = void 0;
|
|
803
|
-
listener({ kind: "loading" });
|
|
804
|
-
return;
|
|
805
|
-
}
|
|
806
|
-
listener({ kind: "ready", session: confirmed, progress });
|
|
807
|
-
}
|
|
808
|
-
failures = 0;
|
|
809
|
-
} catch (error) {
|
|
810
|
-
if (!current()) {
|
|
811
|
-
return;
|
|
812
|
-
}
|
|
813
|
-
failures = Math.min(failures + 1, 20);
|
|
814
|
-
sessionId = void 0;
|
|
815
|
-
listener({
|
|
816
|
-
kind: "error",
|
|
817
|
-
error: error instanceof Error ? error : new Error("Could not refresh progress")
|
|
818
|
-
});
|
|
819
|
-
} finally {
|
|
820
|
-
if (current()) {
|
|
821
|
-
timer = setTimeout(
|
|
822
|
-
() => void refresh(),
|
|
823
|
-
Math.min(maximum, interval * 2 ** failures)
|
|
824
|
-
);
|
|
825
|
-
}
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
const observer = {
|
|
829
|
-
refresh,
|
|
830
|
-
clear,
|
|
831
|
-
dispose() {
|
|
832
|
-
if (disposed) {
|
|
833
|
-
return;
|
|
834
|
-
}
|
|
835
|
-
disposed = true;
|
|
836
|
-
controller?.abort();
|
|
837
|
-
if (timer !== void 0) {
|
|
838
|
-
clearTimeout(timer);
|
|
839
|
-
}
|
|
840
|
-
onDispose();
|
|
841
|
-
}
|
|
842
|
-
};
|
|
843
|
-
return observer;
|
|
844
|
-
}
|
|
845
|
-
|
|
846
|
-
// src/index.ts
|
|
847
|
-
import { z as z10 } from "zod";
|
|
848
|
-
|
|
849
|
-
// src/avatar.ts
|
|
850
|
-
import { createAvatar } from "@dicebear/core";
|
|
851
|
-
import * as shapes from "@dicebear/shapes";
|
|
852
|
-
function avatarSrc(avatar) {
|
|
853
|
-
return avatar.source === "generated" ? defaultAvatar(avatar.seed) : avatar.url;
|
|
854
|
-
}
|
|
855
|
-
function defaultAvatar(seed) {
|
|
856
|
-
return createAvatar(shapes, { seed }).toDataUri();
|
|
857
|
-
}
|
|
858
|
-
function defaultAvatarSvg(seed) {
|
|
859
|
-
return createAvatar(shapes, { seed }).toString();
|
|
860
|
-
}
|
|
861
|
-
function walletAvatarSeed(wallet) {
|
|
862
|
-
return `${wallet.chain}:${wallet.chain === "solana" ? wallet.address : wallet.address.toLowerCase()}`;
|
|
863
|
-
}
|
|
864
|
-
|
|
865
|
-
// src/collection.ts
|
|
866
|
-
import { z as z5 } from "zod";
|
|
867
|
-
var collectionCodeSchema = z5.string().regex(/^relay:collect:[a-f0-9]{64}$/);
|
|
868
|
-
var collectionPassSchema = z5.object({
|
|
869
|
-
code: collectionCodeSchema,
|
|
870
|
-
expiresAt: z5.number(),
|
|
871
|
-
entitlement: identifier
|
|
872
|
-
});
|
|
873
|
-
var collectionResolveSchema = z5.object({ code: collectionCodeSchema }).strict();
|
|
874
|
-
var collectionBeginSchema = collectionResolveSchema.extend({
|
|
875
|
-
actionId: identifier,
|
|
876
|
-
revision: z5.number().int().positive(),
|
|
877
|
-
selection: pickupSelectionSchema.optional()
|
|
878
|
-
});
|
|
879
|
-
var collectionPreviewSchema = z5.object({
|
|
880
|
-
entitlement: entitlementSchema,
|
|
881
|
-
inventory: pickupAvailabilitySchema,
|
|
882
|
-
expiresAt: z5.number()
|
|
883
|
-
});
|
|
884
|
-
|
|
885
|
-
// src/configuration.ts
|
|
886
|
-
function questConfiguration(release) {
|
|
887
|
-
return release.configuration ?? {
|
|
888
|
-
defaults: Object.fromEntries(
|
|
889
|
-
Object.entries(release.fields).map(([key, field]) => [
|
|
890
|
-
key,
|
|
891
|
-
field.default
|
|
892
|
-
])
|
|
893
|
-
),
|
|
894
|
-
overrides: { ...release.values },
|
|
895
|
-
preserved: Object.keys(release.values)
|
|
896
|
-
};
|
|
897
|
-
}
|
|
898
|
-
|
|
899
|
-
// src/deployments.ts
|
|
900
|
-
import { z as z8 } from "zod";
|
|
901
|
-
|
|
902
|
-
// src/images.ts
|
|
903
|
-
import { z as z7 } from "zod";
|
|
904
|
-
|
|
905
|
-
// src/x.ts
|
|
906
|
-
import { z as z6 } from "zod";
|
|
907
|
-
var xIdSchema = z6.string().regex(/^[0-9]{1,20}$/);
|
|
908
|
-
var xConnectionSchema = z6.object({ userId: xIdSchema });
|
|
909
|
-
var xProfileSchema = z6.object({
|
|
910
|
-
id: xIdSchema,
|
|
911
|
-
username: z6.string(),
|
|
912
|
-
name: z6.string(),
|
|
913
|
-
bio: z6.string().nullable(),
|
|
914
|
-
profileImageUrl: z6.string().url().nullable(),
|
|
915
|
-
followersCount: z6.number().int().nonnegative().nullable(),
|
|
916
|
-
verified: z6.boolean().nullable()
|
|
917
|
-
});
|
|
918
|
-
var xPostSchema = xTweetSchema.extend({
|
|
919
|
-
quotedTweetId: xIdSchema.nullish().transform((v) => v ?? null),
|
|
920
|
-
inReplyToUserId: xIdSchema.nullish().transform((v) => v ?? null),
|
|
921
|
-
inReplyToStatusId: xIdSchema.nullish().transform((v) => v ?? null),
|
|
922
|
-
retweetedTweetId: xIdSchema.nullish().transform((v) => v ?? null),
|
|
923
|
-
/**
|
|
924
|
-
* Attached media in post order. Videos and GIFs carry their preview image URL. Like the tracker
|
|
925
|
-
* projection (migration 0056), a list with any malformed item is dropped whole, so positions
|
|
926
|
-
* never shift and a bad entry never fails the post read.
|
|
927
|
-
*/
|
|
928
|
-
media: z6.unknown().transform(
|
|
929
|
-
(value) => z6.array(z6.object({ type: z6.string(), url: z6.string() })).safeParse(value).data ?? []
|
|
930
|
-
)
|
|
931
|
-
});
|
|
932
|
-
var xRequestSchema = z6.discriminatedUnion("operation", [
|
|
933
|
-
z6.object({ operation: z6.literal("connection") }).strict(),
|
|
934
|
-
z6.object({ operation: z6.literal("profile") }).strict(),
|
|
935
|
-
z6.object({ operation: z6.literal("post"), postId: xIdSchema }).strict(),
|
|
936
|
-
z6.object({ operation: z6.literal("follows"), userId: xIdSchema }).strict(),
|
|
937
|
-
z6.object({ operation: z6.literal("reposted"), postId: xIdSchema }).strict()
|
|
938
|
-
]);
|
|
939
|
-
|
|
940
|
-
// src/images.ts
|
|
941
|
-
var imageReferenceSchema = z7.union([
|
|
942
|
-
z7.strictObject({ evidence: z7.string().min(1).max(256) }),
|
|
943
|
-
z7.strictObject({ x: z7.literal("profile") }),
|
|
944
|
-
z7.strictObject({
|
|
945
|
-
x: z7.literal("post"),
|
|
946
|
-
postId: xIdSchema,
|
|
947
|
-
index: z7.number().int().min(0).max(3).default(0)
|
|
948
|
-
}),
|
|
949
|
-
z7.strictObject({ asset: identifier })
|
|
950
|
-
]);
|
|
951
|
-
var criteria = z7.string().trim().min(1).max(2e3);
|
|
952
|
-
var imageFieldSchema = z7.strictObject({
|
|
953
|
-
type: z7.enum(["string", "number", "boolean"]),
|
|
954
|
-
description: z7.string().trim().min(1).max(500)
|
|
955
|
-
});
|
|
956
|
-
var imageFieldsSchema = z7.record(z7.string().regex(/^[a-zA-Z][a-zA-Z0-9_]{0,39}$/), imageFieldSchema).refine((fields) => {
|
|
957
|
-
const count = Object.keys(fields).length;
|
|
958
|
-
return count >= 1 && count <= 12;
|
|
959
|
-
}, "Declare between 1 and 12 fields");
|
|
960
|
-
var imageRequestSchema = z7.discriminatedUnion("operation", [
|
|
961
|
-
z7.strictObject({
|
|
962
|
-
operation: z7.literal("inspect"),
|
|
963
|
-
image: imageReferenceSchema
|
|
964
|
-
}),
|
|
965
|
-
z7.strictObject({
|
|
966
|
-
operation: z7.literal("compare"),
|
|
967
|
-
images: z7.tuple([imageReferenceSchema, imageReferenceSchema])
|
|
968
|
-
}),
|
|
969
|
-
z7.strictObject({
|
|
970
|
-
operation: z7.literal("review"),
|
|
971
|
-
images: z7.array(imageReferenceSchema).min(1).max(4),
|
|
972
|
-
criteria
|
|
973
|
-
}),
|
|
974
|
-
z7.strictObject({
|
|
975
|
-
operation: z7.literal("extract"),
|
|
976
|
-
image: imageReferenceSchema,
|
|
977
|
-
fields: imageFieldsSchema
|
|
978
|
-
}),
|
|
979
|
-
z7.strictObject({
|
|
980
|
-
operation: z7.literal("seen"),
|
|
981
|
-
image: imageReferenceSchema,
|
|
982
|
-
maxDistance: z7.number().int().min(0).max(8).default(8)
|
|
983
|
-
})
|
|
984
|
-
]);
|
|
985
|
-
var hash = z7.string().regex(/^[0-9a-f]{16}$/);
|
|
986
|
-
var imageInspectionSchema = z7.strictObject({
|
|
987
|
-
width: z7.number().int().positive(),
|
|
988
|
-
height: z7.number().int().positive(),
|
|
989
|
-
format: z7.enum(["jpeg", "png", "webp", "gif", "avif"]),
|
|
990
|
-
bytes: z7.number().int().positive(),
|
|
991
|
-
sha256: z7.string().regex(/^[0-9a-f]{64}$/),
|
|
992
|
-
phash: hash,
|
|
993
|
-
dhash: hash
|
|
994
|
-
});
|
|
995
|
-
var distance = z7.number().int().min(0).max(64);
|
|
996
|
-
var imageComparisonSchema = z7.strictObject({
|
|
997
|
-
identical: z7.boolean(),
|
|
998
|
-
phashDistance: distance,
|
|
999
|
-
dhashDistance: distance
|
|
1000
|
-
});
|
|
1001
|
-
var imageExtractionSchema = z7.strictObject({
|
|
1002
|
-
values: z7.record(
|
|
1003
|
-
z7.string(),
|
|
1004
|
-
z7.union([z7.string().max(2e3), z7.number(), z7.boolean(), z7.null()])
|
|
1005
|
-
),
|
|
1006
|
-
reason: z7.string().min(1).max(2e3)
|
|
1007
|
-
});
|
|
1008
|
-
var imageSightingsSchema = z7.strictObject({
|
|
1009
|
-
matches: z7.number().int().nonnegative(),
|
|
1010
|
-
closestDistance: distance.nullable(),
|
|
1011
|
-
firstSeenAt: z7.number().int().nonnegative().nullable()
|
|
1012
|
-
});
|
|
1013
|
-
var sha256 = z7.string().regex(/^[0-9a-f]{64}$/);
|
|
1014
|
-
var imageSize = z7.number().int().positive().max(5 * 1024 * 1024);
|
|
1015
|
-
var imageAssetArtifactSchema = z7.strictObject({
|
|
1016
|
-
key: identifier,
|
|
1017
|
-
sha256,
|
|
1018
|
-
size: imageSize,
|
|
1019
|
-
path: z7.string().min(1).max(500).optional()
|
|
1020
|
-
});
|
|
1021
|
-
var imageUploadRequestSchema = z7.strictObject({
|
|
1022
|
-
images: z7.array(
|
|
1023
|
-
z7.strictObject({
|
|
1024
|
-
sha256,
|
|
1025
|
-
size: imageSize,
|
|
1026
|
-
type: z7.enum(["image/jpeg", "image/png", "image/webp"])
|
|
1027
|
-
})
|
|
1028
|
-
).min(1).max(10)
|
|
1029
|
-
});
|
|
1030
|
-
var imageUploadsSchema = z7.strictObject({
|
|
1031
|
-
images: z7.array(
|
|
1032
|
-
z7.strictObject({
|
|
1033
|
-
sha256,
|
|
1034
|
-
upload: z7.strictObject({
|
|
1035
|
-
url: z7.string().url(),
|
|
1036
|
-
headers: z7.record(z7.string(), z7.string()),
|
|
1037
|
-
expiresAt: z7.number().int().positive()
|
|
1038
|
-
}).nullable()
|
|
1039
|
-
})
|
|
1040
|
-
)
|
|
1041
|
-
});
|
|
1042
|
-
var publishedImageSchema = z7.strictObject({
|
|
1043
|
-
key: identifier,
|
|
1044
|
-
sha256,
|
|
1045
|
-
type: z7.enum(["image/jpeg", "image/png", "image/webp"]),
|
|
1046
|
-
size: imageSize,
|
|
1047
|
-
width: z7.number().int().positive(),
|
|
1048
|
-
height: z7.number().int().positive()
|
|
1049
|
-
});
|
|
1050
|
-
function parseImageExtraction(raw, value) {
|
|
1051
|
-
const result = imageExtractionSchema.parse(value);
|
|
1052
|
-
const fields = imageFieldsSchema.parse(raw);
|
|
1053
|
-
for (const [key, field] of Object.entries(fields)) {
|
|
1054
|
-
const extracted = result.values[key];
|
|
1055
|
-
if (extracted === void 0) {
|
|
1056
|
-
throw new Error("Image extraction omitted " + key);
|
|
1057
|
-
}
|
|
1058
|
-
if (extracted !== null && typeof extracted !== field.type) {
|
|
1059
|
-
throw new Error("Image extraction returned the wrong type for " + key);
|
|
1060
|
-
}
|
|
1061
|
-
}
|
|
1062
|
-
if (Object.keys(result.values).some((key) => !Object.hasOwn(fields, key))) {
|
|
1063
|
-
throw new Error("Image extraction returned an undeclared field");
|
|
1064
|
-
}
|
|
1065
|
-
return result;
|
|
1066
|
-
}
|
|
1067
|
-
function parseImageResult(request, value) {
|
|
1068
|
-
switch (request.operation) {
|
|
1069
|
-
case "inspect":
|
|
1070
|
-
return imageInspectionSchema.parse(value);
|
|
1071
|
-
case "compare":
|
|
1072
|
-
return imageComparisonSchema.parse(value);
|
|
1073
|
-
case "review":
|
|
1074
|
-
return photoResultSchema.parse(value);
|
|
1075
|
-
case "extract":
|
|
1076
|
-
return parseImageExtraction(request.fields, value);
|
|
1077
|
-
case "seen":
|
|
1078
|
-
return imageSightingsSchema.parse(value);
|
|
1079
|
-
}
|
|
1080
|
-
}
|
|
1081
|
-
|
|
1082
|
-
// src/deployments.ts
|
|
1083
|
-
var projectCatalogArtifactSchema = catalogDeploymentSchema.omit({ expectedRevision: true }).extend({
|
|
1084
|
-
engagement: z8.array(engagementArtifactSchema).max(50).default([]),
|
|
1085
|
-
trackers: z8.array(trackerArtifactSchema).max(50).default([]),
|
|
1086
|
-
pointLedgers: z8.array(pointLedgerDeclarationSchema).max(50).default([]),
|
|
1087
|
-
referrals: z8.array(referralArtifactSchema).max(50).default([]),
|
|
1088
|
-
leaderboards: z8.array(leaderboardArtifactSchema).max(50).default([]),
|
|
1089
|
-
images: z8.array(imageAssetArtifactSchema).max(10).default([])
|
|
1090
|
-
});
|
|
1091
|
-
var projectDeploymentSchema = projectCatalogArtifactSchema.extend({ releases: z8.array(releaseSchema).max(50).default([]) }).refine(
|
|
1092
|
-
(value) => value.engagement.length > 0 || value.trackers.length > 0 || value.pointLedgers.length > 0 || value.releases.length > 0 || value.leaderboards.length > 0 || value.referrals.length > 0 || value.images.length > 0 || value.types.length > 0 || value.collections.length > 0 || value.supportedInteractions !== void 0,
|
|
1093
|
-
"No resources configured. Add engagement, trackers, quests, questTypes, pointLedgers, leaderboards, referrals, images, collections, or supportedInteractions to relay.json."
|
|
1094
|
-
);
|
|
1095
|
-
var deploymentPreviewSchema = z8.object({
|
|
1096
|
-
id: identifier,
|
|
1097
|
-
engagement: z8.array(engagementDeploymentEntrySchema).default([]),
|
|
1098
|
-
trackers: z8.array(publishedTrackerSchema).default([]),
|
|
1099
|
-
baseRevision: z8.number().int().nonnegative(),
|
|
1100
|
-
pointLedgers: z8.array(pointLedgerSchema).default([]),
|
|
1101
|
-
releases: z8.array(publishedReleaseSchema),
|
|
1102
|
-
types: z8.array(questTypeVersionSchema),
|
|
1103
|
-
collections: z8.array(questCollectionSchema),
|
|
1104
|
-
supportedInteractions: z8.array(interactionSchema),
|
|
1105
|
-
referrals: z8.array(publishedReferralSchema).default([]),
|
|
1106
|
-
leaderboards: z8.array(leaderboardPreviewSchema).default([]),
|
|
1107
|
-
images: z8.array(publishedImageSchema).default([])
|
|
1108
|
-
});
|
|
1109
|
-
var publishDeploymentSchema = z8.object({ id: identifier }).strict();
|
|
1110
|
-
var deploymentResultSchema = deploymentPreviewSchema.extend({
|
|
1111
|
-
revision: z8.number().int().positive()
|
|
1112
|
-
});
|
|
1113
|
-
|
|
1114
|
-
// src/identity-integration.ts
|
|
1115
|
-
import { z as z9 } from "zod";
|
|
1116
|
-
var identityIntegrationInputSchema = z9.object({
|
|
1117
|
-
name: z9.string().trim().min(1).max(80),
|
|
1118
|
-
origin: z9.string().url().refine((value) => {
|
|
1119
|
-
const url = new URL(value);
|
|
1120
|
-
return url.protocol === "https:" && url.origin === value;
|
|
1121
|
-
}, "Use an exact HTTPS application origin")
|
|
1122
|
-
}).strict();
|
|
1123
|
-
var identityIntegrationSchema = authScopeSchema.extend({
|
|
1124
|
-
id: z9.string().uuid(),
|
|
1125
|
-
name: z9.string(),
|
|
1126
|
-
origin: z9.string(),
|
|
1127
|
-
expiresAt: z9.number()
|
|
1128
|
-
});
|
|
1129
|
-
var identityIntegrationSecretSchema = identityIntegrationSchema.extend(
|
|
1130
|
-
{
|
|
1131
|
-
token: z9.string()
|
|
1132
|
-
}
|
|
1133
|
-
);
|
|
1134
|
-
var participantExchangeSchema = z9.object({
|
|
1135
|
-
subject: z9.string().min(1).max(200),
|
|
1136
|
-
previousToken: z9.string().max(200).optional()
|
|
1137
|
-
}).strict();
|
|
1138
|
-
|
|
1139
|
-
// src/index.ts
|
|
1140
|
-
function createRelayClient(options) {
|
|
1141
|
-
async function send(path, init = {}) {
|
|
1142
|
-
const headers = new Headers(init.headers);
|
|
1143
|
-
if (options.token) {
|
|
1144
|
-
headers.set("Authorization", `Bearer ${options.token}`);
|
|
1145
|
-
}
|
|
1146
|
-
if (options.organization) {
|
|
1147
|
-
headers.set("X-Relay-Organization", options.organization);
|
|
1148
|
-
}
|
|
1149
|
-
if (options.project) {
|
|
1150
|
-
headers.set("X-Relay-Project", options.project);
|
|
1151
|
-
}
|
|
1152
|
-
if (options.environment) {
|
|
1153
|
-
headers.set("X-Relay-Environment", options.environment);
|
|
1154
|
-
}
|
|
1155
|
-
if (init.method && init.method !== "GET") {
|
|
1156
|
-
headers.set("X-Relay-CSRF", "1");
|
|
1157
|
-
}
|
|
1158
|
-
const response = await fetch(options.baseUrl + path, {
|
|
1159
|
-
...init,
|
|
1160
|
-
signal: init.signal ? AbortSignal.any([init.signal, AbortSignal.timeout(15e3)]) : AbortSignal.timeout(15e3),
|
|
1161
|
-
headers
|
|
1162
|
-
});
|
|
1163
|
-
if (!response.ok) {
|
|
1164
|
-
const value = await response.json().catch(() => null);
|
|
1165
|
-
const error = errorSchema.safeParse(value);
|
|
1166
|
-
throw new RelayError(
|
|
1167
|
-
error.success ? error.data.error : `Request failed (${response.status})`,
|
|
1168
|
-
response.status,
|
|
1169
|
-
error.success ? error.data.missing : [],
|
|
1170
|
-
error.success ? error.data.code : void 0
|
|
1171
|
-
);
|
|
1172
|
-
}
|
|
1173
|
-
return response;
|
|
1174
|
-
}
|
|
1175
|
-
async function request(path, schema, init = {}) {
|
|
1176
|
-
const response = await send(path, init);
|
|
1177
|
-
const value = await response.json();
|
|
1178
|
-
return schema.parse(value);
|
|
1179
|
-
}
|
|
1180
|
-
async function walletRequest(path, schema, init = {}) {
|
|
1181
|
-
for (let attempt = 0; ; attempt++) {
|
|
1182
|
-
let response;
|
|
1183
|
-
try {
|
|
1184
|
-
response = await send(path, init);
|
|
1185
|
-
} catch (error) {
|
|
1186
|
-
const transient = error instanceof RelayError && [500, 502, 503, 504].includes(error.status) || error instanceof TypeError || error instanceof DOMException && error.name === "TimeoutError";
|
|
1187
|
-
if (!transient || attempt === 2) {
|
|
1188
|
-
throw error;
|
|
1189
|
-
}
|
|
1190
|
-
await new Promise(
|
|
1191
|
-
(resolve) => setTimeout(resolve, attempt === 0 ? 250 : 750)
|
|
1192
|
-
);
|
|
1193
|
-
continue;
|
|
1194
|
-
}
|
|
1195
|
-
const value = await response.json();
|
|
1196
|
-
return schema.parse(value);
|
|
1197
|
-
}
|
|
1198
|
-
}
|
|
1199
|
-
function query(path, values) {
|
|
1200
|
-
const params = new URLSearchParams();
|
|
1201
|
-
for (const [key, value] of Object.entries(values)) {
|
|
1202
|
-
if (value !== void 0) {
|
|
1203
|
-
params.set(key, String(value));
|
|
1204
|
-
}
|
|
1205
|
-
}
|
|
1206
|
-
return path + "?" + params;
|
|
1207
|
-
}
|
|
1208
|
-
function json(body) {
|
|
1209
|
-
return {
|
|
1210
|
-
method: "POST",
|
|
1211
|
-
headers: { "Content-Type": "application/json" },
|
|
1212
|
-
body: JSON.stringify(body)
|
|
1213
|
-
};
|
|
1214
|
-
}
|
|
1215
|
-
function sessionHeaders(session) {
|
|
1216
|
-
return { "Content-Type": "application/json", "X-Relay-Session": session };
|
|
1217
|
-
}
|
|
1218
|
-
const submission = submissions(
|
|
1219
|
-
{
|
|
1220
|
-
session: () => request("/v1/auth/session", sessionSchema.nullable()),
|
|
1221
|
-
upload: (file, action, session) => request("/v1/me/evidence", evidenceSchema, {
|
|
1222
|
-
method: "POST",
|
|
1223
|
-
headers: {
|
|
1224
|
-
"Content-Type": file.type,
|
|
1225
|
-
"X-Relay-Upload-ID": action,
|
|
1226
|
-
"X-Relay-Session": session
|
|
1227
|
-
},
|
|
1228
|
-
body: file
|
|
1229
|
-
}),
|
|
1230
|
-
claim: (input, session) => request("/v1/me/attempts", attemptSchema, {
|
|
1231
|
-
...json(input),
|
|
1232
|
-
headers: {
|
|
1233
|
-
"Content-Type": "application/json",
|
|
1234
|
-
"X-Relay-Session": session
|
|
1235
|
-
}
|
|
1236
|
-
}),
|
|
1237
|
-
retry: (attempt, session) => request(`/v1/attempts/${attempt}/retry`, attemptSchema, {
|
|
1238
|
-
...json({}),
|
|
1239
|
-
headers: {
|
|
1240
|
-
"Content-Type": "application/json",
|
|
1241
|
-
"X-Relay-Session": session
|
|
1242
|
-
}
|
|
1243
|
-
})
|
|
1244
|
-
},
|
|
1245
|
-
options.submissionStore,
|
|
1246
|
-
options.baseUrl
|
|
1247
|
-
);
|
|
1248
|
-
const observers = /* @__PURE__ */ new Set();
|
|
1249
|
-
async function changeSession(task) {
|
|
1250
|
-
for (const observer of observers) {
|
|
1251
|
-
observer.clear();
|
|
1252
|
-
}
|
|
1253
|
-
try {
|
|
1254
|
-
return await task();
|
|
1255
|
-
} finally {
|
|
1256
|
-
for (const observer of observers) {
|
|
1257
|
-
void observer.refresh();
|
|
1258
|
-
}
|
|
1259
|
-
}
|
|
1260
|
-
}
|
|
1261
|
-
const experience = () => request("/v1/me/experience", questExperienceSchema);
|
|
1262
|
-
async function getQuest(id) {
|
|
1263
|
-
const quest = (await experience()).quests.find(
|
|
1264
|
-
(q) => q.quest === id || q.key === id
|
|
1265
|
-
);
|
|
1266
|
-
if (!quest) {
|
|
1267
|
-
throw new RelayError("Quest not found", 404);
|
|
1268
|
-
}
|
|
1269
|
-
return quest;
|
|
1270
|
-
}
|
|
1271
|
-
return {
|
|
1272
|
-
referrals: {
|
|
1273
|
-
list: () => request("/v1/referrals", z10.array(referralDefinitionSchema)),
|
|
1274
|
-
summary: () => request("/v1/referrals/me", referralSummarySchema),
|
|
1275
|
-
history: (before) => request(
|
|
1276
|
-
query("/v1/referrals/history", { before }),
|
|
1277
|
-
referralHistorySchema
|
|
1278
|
-
),
|
|
1279
|
-
accept: (input) => request("/v1/referrals/accept", z10.object({ ok: z10.literal(true) }), {
|
|
1280
|
-
method: "POST",
|
|
1281
|
-
body: JSON.stringify(referralAcceptSchema.parse(input))
|
|
1282
|
-
})
|
|
1283
|
-
},
|
|
1284
|
-
tieredRewards: {
|
|
1285
|
-
/**
|
|
1286
|
-
* The project's tiered rewards with their keys. Entitlements and reward
|
|
1287
|
-
* definitions name them by ID: use this to find the ID for a key.
|
|
1288
|
-
*/
|
|
1289
|
-
list: () => request("/v1/tiered-rewards", z10.array(tieredRewardReferenceSchema))
|
|
1290
|
-
},
|
|
1291
|
-
pointLedgers: {
|
|
1292
|
-
/**
|
|
1293
|
-
* The project's point ledgers with their keys and names. Reads return
|
|
1294
|
-
* ledger IDs: use this to find the ID for a key, or a ledger's name.
|
|
1295
|
-
*/
|
|
1296
|
-
list: () => request("/v1/point-ledgers", z10.array(pointLedgerReferenceSchema))
|
|
1297
|
-
},
|
|
1298
|
-
leaderboards: {
|
|
1299
|
-
list: () => request("/v1/leaderboards", z10.array(leaderboardDefinitionSchema)),
|
|
1300
|
-
standings: (board, options2 = {}) => {
|
|
1301
|
-
const parsed = leaderboardQuerySchema.parse(options2);
|
|
1302
|
-
return request(
|
|
1303
|
-
query(`/v1/leaderboards/${identifier.parse(board)}`, parsed),
|
|
1304
|
-
leaderboardPageSchema
|
|
1305
|
-
);
|
|
1306
|
-
},
|
|
1307
|
-
/**
|
|
1308
|
-
* A profile's current rank and score on `board` (`profile.id` from a leaderboard row or
|
|
1309
|
-
* `profiles.mine()`). Needs the board's access, like `standings`; a profile this viewer
|
|
1310
|
-
* cannot see is a 404, as in `profiles.get`.
|
|
1311
|
-
*/
|
|
1312
|
-
placement: (board, profile) => request(
|
|
1313
|
-
`/v1/leaderboards/${identifier.parse(board)}/profiles/${identifier.parse(profile)}`,
|
|
1314
|
-
leaderboardPlacementSchema
|
|
1315
|
-
)
|
|
1316
|
-
},
|
|
1317
|
-
/**
|
|
1318
|
-
* Participant profiles: the display name and avatar other participants see where the project
|
|
1319
|
-
* enables profiles in Console. Render an avatar with `avatarSrc(profile.avatar)`.
|
|
1320
|
-
*/
|
|
1321
|
-
profiles: {
|
|
1322
|
-
/** The signed-in member's own profile, whatever the project shows to others. */
|
|
1323
|
-
mine: () => request("/v1/me/profile", ownProfileSchema),
|
|
1324
|
-
/**
|
|
1325
|
-
* Changes the member's own name, avatar choice or visibility; omitted fields stay, and null
|
|
1326
|
-
* returns to the default. `session` (the ID the app read) makes a changed session a 409.
|
|
1327
|
-
*/
|
|
1328
|
-
update: async (input, options2 = {}) => request("/v1/me/profile", ownProfileSchema, {
|
|
1329
|
-
method: "POST",
|
|
1330
|
-
headers: {
|
|
1331
|
-
"Content-Type": "application/json",
|
|
1332
|
-
...options2.session ? { "X-Relay-Session": options2.session } : {}
|
|
1333
|
-
},
|
|
1334
|
-
body: JSON.stringify(profileUpdateSchema.parse(input))
|
|
1335
|
-
}),
|
|
1336
|
-
/**
|
|
1337
|
-
* Uploads a JPEG, PNG or WebP of at most 5 MB as the member's avatar. The server crops it to
|
|
1338
|
-
* a 512×512 WebP without metadata. Retrying with the same `uploadId` is idempotent.
|
|
1339
|
-
*/
|
|
1340
|
-
uploadAvatar: async (file, options2 = {}) => {
|
|
1341
|
-
if (!avatarUploadTypes.includes(file.type)) {
|
|
1342
|
-
throw new RelayError("Use a JPEG, PNG or WebP image", 400);
|
|
1343
|
-
}
|
|
1344
|
-
if (file.size > AVATAR_UPLOAD_LIMIT) {
|
|
1345
|
-
throw new RelayError("Use an image smaller than 5 MB", 413);
|
|
1346
|
-
}
|
|
1347
|
-
return request("/v1/me/profile/avatar", ownProfileSchema, {
|
|
1348
|
-
method: "POST",
|
|
1349
|
-
headers: {
|
|
1350
|
-
"Content-Type": file.type,
|
|
1351
|
-
"X-Relay-Upload-ID": identifier.parse(
|
|
1352
|
-
options2.uploadId ?? crypto.randomUUID()
|
|
1353
|
-
),
|
|
1354
|
-
...options2.session ? { "X-Relay-Session": options2.session } : {}
|
|
1355
|
-
},
|
|
1356
|
-
body: file
|
|
1357
|
-
});
|
|
1358
|
-
},
|
|
1359
|
-
/**
|
|
1360
|
-
* A profile's name and avatar by its public ID (`profile.id` from a leaderboard row or
|
|
1361
|
-
* `mine()`). A profile that is missing, hidden or not visible to this viewer is a 404.
|
|
1362
|
-
*/
|
|
1363
|
-
get: (profile) => request(
|
|
1364
|
-
`/v1/profiles/${identifier.parse(profile)}`,
|
|
1365
|
-
profileSummarySchema
|
|
1366
|
-
),
|
|
1367
|
-
/**
|
|
1368
|
-
* A page of the profile's completions of quests that show on profiles, most recently
|
|
1369
|
-
* completed first. Pass the page's `nextCursor` as `cursor` for the next one.
|
|
1370
|
-
*/
|
|
1371
|
-
completions: (profile, options2 = {}) => request(
|
|
1372
|
-
query(
|
|
1373
|
-
`/v1/profiles/${identifier.parse(profile)}/completions`,
|
|
1374
|
-
profileCompletionQuerySchema.parse(options2)
|
|
1375
|
-
),
|
|
1376
|
-
profileCompletionPageSchema
|
|
1377
|
-
),
|
|
1378
|
-
/**
|
|
1379
|
-
* The profile's invited and qualified counts and milestones in one referral program. Needs
|
|
1380
|
-
* a signed-in participant, as referral programs do.
|
|
1381
|
-
*/
|
|
1382
|
-
referral: (profile, program) => request(
|
|
1383
|
-
`/v1/profiles/${identifier.parse(profile)}/referrals/${identifier.parse(program)}`,
|
|
1384
|
-
profileReferralSchema
|
|
1385
|
-
)
|
|
1386
|
-
},
|
|
1387
|
-
quests: {
|
|
1388
|
-
get: getQuest,
|
|
1389
|
-
retry: async (view) => {
|
|
1390
|
-
if (view.trigger.kind === "automatic") {
|
|
1391
|
-
throw new Error(
|
|
1392
|
-
"Automatic quests recover without participant retries."
|
|
1393
|
-
);
|
|
1394
|
-
}
|
|
1395
|
-
if (!view.attempt || view.attempt.status !== "failed") {
|
|
1396
|
-
throw new Error("There is no failed attempt to retry.");
|
|
1397
|
-
}
|
|
1398
|
-
const session = await request(
|
|
1399
|
-
"/v1/auth/session",
|
|
1400
|
-
sessionSchema.nullable()
|
|
1401
|
-
);
|
|
1402
|
-
if (session?.principal.kind !== "member") {
|
|
1403
|
-
throw new Error("Sign in to retry verification.");
|
|
1404
|
-
}
|
|
1405
|
-
return request(`/v1/attempts/${view.attempt.id}/retry`, attemptSchema, {
|
|
1406
|
-
...json({}),
|
|
1407
|
-
headers: {
|
|
1408
|
-
"Content-Type": "application/json",
|
|
1409
|
-
"X-Relay-Session": session.id
|
|
1410
|
-
}
|
|
1411
|
-
});
|
|
1412
|
-
},
|
|
1413
|
-
experience,
|
|
1414
|
-
collection: async (id) => {
|
|
1415
|
-
const collection = (await experience()).collections.find(
|
|
1416
|
-
(c) => c.id === id || c.key === id
|
|
1417
|
-
);
|
|
1418
|
-
if (!collection) {
|
|
1419
|
-
throw new RelayError("Collection not found", 404);
|
|
1420
|
-
}
|
|
1421
|
-
return collection;
|
|
1422
|
-
},
|
|
1423
|
-
open: questActions(submission, getQuest),
|
|
1424
|
-
observe: (listener, options2) => {
|
|
1425
|
-
const observer = observeProgress(
|
|
1426
|
-
{
|
|
1427
|
-
session: (signal) => request("/v1/auth/session", sessionSchema.nullable(), { signal }),
|
|
1428
|
-
progress: (session, signal) => request("/v1/me/experience", questExperienceSchema, {
|
|
1429
|
-
signal,
|
|
1430
|
-
headers: { "X-Relay-Session": session }
|
|
1431
|
-
})
|
|
1432
|
-
},
|
|
1433
|
-
listener,
|
|
1434
|
-
options2,
|
|
1435
|
-
() => observers.delete(observer)
|
|
1436
|
-
);
|
|
1437
|
-
observers.add(observer);
|
|
1438
|
-
observer.clear();
|
|
1439
|
-
void observer.refresh();
|
|
1440
|
-
return { refresh: observer.refresh, dispose: observer.dispose };
|
|
1441
|
-
}
|
|
1442
|
-
},
|
|
1443
|
-
/** The signed-in member's linked Solana, EVM and Cosmos wallets for this project. */
|
|
1444
|
-
wallets: {
|
|
1445
|
-
list: () => walletRequest(
|
|
1446
|
-
"/v1/me/wallets",
|
|
1447
|
-
z10.object({ wallets: z10.array(linkedWalletSchema) })
|
|
1448
|
-
).then((result) => result.wallets),
|
|
1449
|
-
challenge: (input, session) => walletRequest(
|
|
1450
|
-
"/v1/me/wallets/challenge",
|
|
1451
|
-
walletMessageChallengeSchema,
|
|
1452
|
-
{
|
|
1453
|
-
...json(walletAddressInputSchema.parse(input)),
|
|
1454
|
-
headers: sessionHeaders(session)
|
|
1455
|
-
}
|
|
1456
|
-
),
|
|
1457
|
-
verify: (input, session) => walletRequest("/v1/me/wallets/verify", linkedWalletSchema, {
|
|
1458
|
-
...json(walletSignatureSchema.parse(input)),
|
|
1459
|
-
headers: sessionHeaders(session)
|
|
1460
|
-
}),
|
|
1461
|
-
/** The address stays bound to this member: another member still cannot link it. */
|
|
1462
|
-
unlink: (wallet) => request(
|
|
1463
|
-
"/v1/me/wallets/unlink",
|
|
1464
|
-
z10.object({ ok: z10.literal(true) }),
|
|
1465
|
-
json(
|
|
1466
|
-
walletUnlinkInputSchema.parse({
|
|
1467
|
-
chain: wallet.chain,
|
|
1468
|
-
address: wallet.address
|
|
1469
|
-
})
|
|
1470
|
-
)
|
|
1471
|
-
),
|
|
1472
|
-
/** Asks the signer for its address, signs the returned challenge, and links the wallet. */
|
|
1473
|
-
link: async (signer) => {
|
|
1474
|
-
const session = await request(
|
|
1475
|
-
"/v1/auth/session",
|
|
1476
|
-
sessionSchema.nullable()
|
|
1477
|
-
);
|
|
1478
|
-
if (!session) {
|
|
1479
|
-
throw new RelayError("Sign in to continue", 401);
|
|
1480
|
-
}
|
|
1481
|
-
const challenge = await walletRequest(
|
|
1482
|
-
"/v1/me/wallets/challenge",
|
|
1483
|
-
walletMessageChallengeSchema,
|
|
1484
|
-
{
|
|
1485
|
-
...json(
|
|
1486
|
-
walletAddressInputSchema.parse(await walletAddressInput(signer))
|
|
1487
|
-
),
|
|
1488
|
-
headers: sessionHeaders(session.id)
|
|
1489
|
-
}
|
|
1490
|
-
);
|
|
1491
|
-
const proof = await signer.sign(challenge.message, challenge.address);
|
|
1492
|
-
return walletRequest("/v1/me/wallets/verify", linkedWalletSchema, {
|
|
1493
|
-
...json(
|
|
1494
|
-
walletSignatureSchema.parse({ challenge: challenge.id, ...proof })
|
|
1495
|
-
),
|
|
1496
|
-
headers: sessionHeaders(session.id)
|
|
1497
|
-
});
|
|
1498
|
-
}
|
|
1499
|
-
},
|
|
1500
|
-
/** @deprecated Use `wallets` (multi-chain). This reads and replaces the newest Solana wallet. */
|
|
1501
|
-
wallet: {
|
|
1502
|
-
connection: () => walletRequest("/v1/me/wallet", walletConnectionSchema.nullable()),
|
|
1503
|
-
challenge: (input, session) => walletRequest("/v1/me/wallet/challenge", walletChallengeSchema, {
|
|
1504
|
-
...json(walletChallengeInputSchema.parse(input)),
|
|
1505
|
-
headers: sessionHeaders(session)
|
|
1506
|
-
}),
|
|
1507
|
-
verify: (input, session) => walletRequest("/v1/me/wallet/verify", walletConnectionSchema, {
|
|
1508
|
-
...json(walletProofSchema.parse(input)),
|
|
1509
|
-
headers: sessionHeaders(session)
|
|
1510
|
-
})
|
|
1511
|
-
},
|
|
1512
|
-
auth: {
|
|
1513
|
-
providers: () => request(
|
|
1514
|
-
"/v1/auth/providers",
|
|
1515
|
-
z10.object({
|
|
1516
|
-
providers: z10.array(
|
|
1517
|
-
z10.object({
|
|
1518
|
-
provider: authProviderSchema,
|
|
1519
|
-
configured: z10.boolean()
|
|
1520
|
-
})
|
|
1521
|
-
),
|
|
1522
|
-
email: z10.boolean(),
|
|
1523
|
-
/** The wallet sign-in this project enabled; older servers omit it. */
|
|
1524
|
-
wallets: walletSignInNetworksSchema.default([]),
|
|
1525
|
-
demo: z10.boolean()
|
|
1526
|
-
})
|
|
1527
|
-
),
|
|
1528
|
-
start: (provider, mode) => request(
|
|
1529
|
-
"/v1/auth/start",
|
|
1530
|
-
z10.object({ url: z10.string() }),
|
|
1531
|
-
json({ provider, mode })
|
|
1532
|
-
),
|
|
1533
|
-
emailStart: (email) => request(
|
|
1534
|
-
"/v1/auth/email/start",
|
|
1535
|
-
z10.object({ challenge: z10.string() }),
|
|
1536
|
-
json({ email })
|
|
1537
|
-
),
|
|
1538
|
-
emailVerify: (challenge, code) => changeSession(
|
|
1539
|
-
() => request(
|
|
1540
|
-
"/v1/auth/email/verify",
|
|
1541
|
-
sessionSchema,
|
|
1542
|
-
json({ challenge, code })
|
|
1543
|
-
)
|
|
1544
|
-
),
|
|
1545
|
-
/**
|
|
1546
|
-
* Sign in, or sign up, with a Solana, EVM or Cosmos wallet where the project enabled it
|
|
1547
|
-
* (`providers().wallets`). A wallet the member linked while signed in cannot sign in.
|
|
1548
|
-
*/
|
|
1549
|
-
wallet: {
|
|
1550
|
-
/** A sign-in challenge for the wallet's address; binds the flow to this browser. */
|
|
1551
|
-
start: (input) => request(
|
|
1552
|
-
"/v1/auth/wallet/start",
|
|
1553
|
-
walletMessageChallengeSchema,
|
|
1554
|
-
json(walletAddressInputSchema.parse(input))
|
|
1555
|
-
),
|
|
1556
|
-
/** Verifies the signed challenge and starts the session. Not retried: start again instead. */
|
|
1557
|
-
verify: (proof) => changeSession(
|
|
1558
|
-
() => request(
|
|
1559
|
-
"/v1/auth/wallet/verify",
|
|
1560
|
-
sessionSchema,
|
|
1561
|
-
json(walletSignatureSchema.parse(proof))
|
|
1562
|
-
)
|
|
1563
|
-
),
|
|
1564
|
-
/**
|
|
1565
|
-
* Asks the signer for its address, signs the challenge and starts the session. Throws a
|
|
1566
|
-
* `RelayError` with status 403 when the project has not enabled this wallet family.
|
|
1567
|
-
*/
|
|
1568
|
-
signIn: async (signer) => {
|
|
1569
|
-
const challenge = await request(
|
|
1570
|
-
"/v1/auth/wallet/start",
|
|
1571
|
-
walletMessageChallengeSchema,
|
|
1572
|
-
json(
|
|
1573
|
-
walletAddressInputSchema.parse(await walletAddressInput(signer))
|
|
1574
|
-
)
|
|
1575
|
-
);
|
|
1576
|
-
const proof = await signer.sign(challenge.message, challenge.address);
|
|
1577
|
-
return changeSession(
|
|
1578
|
-
() => request(
|
|
1579
|
-
"/v1/auth/wallet/verify",
|
|
1580
|
-
sessionSchema,
|
|
1581
|
-
json(
|
|
1582
|
-
walletSignatureSchema.parse({
|
|
1583
|
-
challenge: challenge.id,
|
|
1584
|
-
...proof
|
|
1585
|
-
})
|
|
1586
|
-
)
|
|
1587
|
-
)
|
|
1588
|
-
);
|
|
1589
|
-
}
|
|
1590
|
-
},
|
|
1591
|
-
accounts: () => request("/v1/auth/accounts", z10.array(accountConnectionSchema)),
|
|
1592
|
-
disconnect: (provider) => request(
|
|
1593
|
-
"/v1/auth/accounts/disconnect",
|
|
1594
|
-
z10.object({ ok: z10.boolean() }),
|
|
1595
|
-
json({ provider })
|
|
1596
|
-
),
|
|
1597
|
-
connections: () => request(
|
|
1598
|
-
"/v1/auth/connections",
|
|
1599
|
-
z10.array(
|
|
1600
|
-
z10.object({
|
|
1601
|
-
provider: z10.string(),
|
|
1602
|
-
subject: z10.string(),
|
|
1603
|
-
signInEnabled: z10.boolean()
|
|
1604
|
-
})
|
|
1605
|
-
)
|
|
1606
|
-
),
|
|
1607
|
-
session: () => request("/v1/auth/session", sessionSchema.nullable()),
|
|
1608
|
-
signOut: () => changeSession(
|
|
1609
|
-
() => request("/v1/auth/logout", z10.object({ ok: z10.boolean() }), json({}))
|
|
1610
|
-
),
|
|
1611
|
-
/** Local development only. Existing hosted apps use createParticipantBackend from /portal-proxy. */
|
|
1612
|
-
exchange: (input) => request("/v1/auth/exchange", exchangeResultSchema, json(input))
|
|
1613
|
-
},
|
|
1614
|
-
me: {
|
|
1615
|
-
/** The signed-in member, and the seed of their generated avatar: `defaultAvatar(avatarSeed)`. */
|
|
1616
|
-
get: () => request("/v1/me", memberSummarySchema),
|
|
1617
|
-
observeProgress: (listener, options2) => {
|
|
1618
|
-
const observer = observeProgress(
|
|
1619
|
-
{
|
|
1620
|
-
session: (signal) => request("/v1/auth/session", sessionSchema.nullable(), { signal }),
|
|
1621
|
-
progress: (session, signal) => request("/v1/me/progress", memberProgressSchema, {
|
|
1622
|
-
signal,
|
|
1623
|
-
headers: { "X-Relay-Session": session }
|
|
1624
|
-
})
|
|
1625
|
-
},
|
|
1626
|
-
listener,
|
|
1627
|
-
options2,
|
|
1628
|
-
() => observers.delete(observer)
|
|
1629
|
-
);
|
|
1630
|
-
observers.add(observer);
|
|
1631
|
-
observer.clear();
|
|
1632
|
-
void observer.refresh();
|
|
1633
|
-
return { refresh: observer.refresh, dispose: observer.dispose };
|
|
1634
|
-
},
|
|
1635
|
-
submission,
|
|
1636
|
-
collectionPass: (entitlement, session) => request("/v1/me/collection-pass", collectionPassSchema, {
|
|
1637
|
-
...json({ entitlement: identifier.parse(entitlement) }),
|
|
1638
|
-
headers: {
|
|
1639
|
-
"Content-Type": "application/json",
|
|
1640
|
-
"X-Relay-Session": session
|
|
1641
|
-
}
|
|
1642
|
-
}),
|
|
1643
|
-
/** @deprecated The participant API does not verify passes. Verify them on your server and call `POST /management/v1/passes/verify`. */
|
|
1644
|
-
linkPass: (code) => request("/v1/me/pass", attemptSchema, json({ code })),
|
|
1645
|
-
progress: () => request("/v1/me/progress", memberProgressSchema),
|
|
1646
|
-
rewardDeliveries: () => request("/v1/reward-deliveries", rewardDeliveriesSchema),
|
|
1647
|
-
claim: (input, options2) => request("/v1/me/attempts", attemptSchema, {
|
|
1648
|
-
...json(input),
|
|
1649
|
-
headers: {
|
|
1650
|
-
"Content-Type": "application/json",
|
|
1651
|
-
...options2 ? { "X-Relay-Session": options2.session } : {}
|
|
1652
|
-
}
|
|
1653
|
-
}),
|
|
1654
|
-
upload: (file) => request("/v1/me/evidence", evidenceSchema, {
|
|
1655
|
-
method: "POST",
|
|
1656
|
-
headers: { "Content-Type": file.type },
|
|
1657
|
-
body: file
|
|
1658
|
-
})
|
|
1659
|
-
},
|
|
1660
|
-
evidence: {
|
|
1661
|
-
async download(id, requestOptions) {
|
|
1662
|
-
const response = await send(
|
|
1663
|
-
`/v1/evidence/${identifier.parse(id)}`,
|
|
1664
|
-
requestOptions
|
|
1665
|
-
);
|
|
1666
|
-
const type = response.headers.get("Content-Type");
|
|
1667
|
-
if (type !== "image/jpeg" && type !== "image/png") {
|
|
1668
|
-
throw new RelayError("Unexpected evidence content type", 502);
|
|
1669
|
-
}
|
|
1670
|
-
return response.blob();
|
|
1671
|
-
}
|
|
1672
|
-
},
|
|
1673
|
-
/** @deprecated The participant API accepts only member sessions and rejects this staff call. Use the management API with a management key instead. */
|
|
1674
|
-
lookupMember: (issuer, subject) => request(
|
|
1675
|
-
"/v1/members/lookup",
|
|
1676
|
-
z10.object({ member: z10.string() }),
|
|
1677
|
-
json({ issuer, subject })
|
|
1678
|
-
),
|
|
1679
|
-
/** @deprecated Removed from the participant API. Build quests with `domino` and `@domino-sdk/relay/build`. */
|
|
1680
|
-
journeyTemplate: () => request("/v1/journey-template", z10.array(templateSchema)),
|
|
1681
|
-
/** @deprecated Removed from the participant API. Build quests with `domino` and `@domino-sdk/relay/build`. */
|
|
1682
|
-
template: () => request("/v1/template", templateSchema),
|
|
1683
|
-
/** @deprecated The participant API accepts only member sessions and rejects this staff call. Use the management API with a management key instead. */
|
|
1684
|
-
snapshot: () => request("/v1/snapshot", snapshotSchema),
|
|
1685
|
-
/** @deprecated The participant API rejects publication. Publish with `domino deploy` or the management API. */
|
|
1686
|
-
publish: (release) => request("/v1/releases", publishedReleaseSchema, json(release)),
|
|
1687
|
-
/** @deprecated The participant API rejects publication. Publish with `domino deploy` or the management API. */
|
|
1688
|
-
publishBatch: (releases) => request(
|
|
1689
|
-
"/v1/releases/batch",
|
|
1690
|
-
z10.array(publishedReleaseSchema),
|
|
1691
|
-
json({ releases })
|
|
1692
|
-
),
|
|
1693
|
-
progress: (member) => request(
|
|
1694
|
-
`/v1/members/${encodeURIComponent(member)}/progress`,
|
|
1695
|
-
memberProgressSchema
|
|
1696
|
-
),
|
|
1697
|
-
/** @deprecated The participant API accepts only member sessions and rejects this staff call. Use the management API with a management key instead. */
|
|
1698
|
-
beginHandover: (id, input) => request(`/v1/entitlements/${id}/begin`, entitlementSchema, json(input)),
|
|
1699
|
-
/** @deprecated The participant API accepts only member sessions and rejects this staff call. Use the management API with a management key instead. */
|
|
1700
|
-
confirmHandover: (id, input) => request(`/v1/entitlements/${id}/confirm`, entitlementSchema, json(input)),
|
|
1701
|
-
upload: (member, file) => request(
|
|
1702
|
-
`/v1/evidence?member=${encodeURIComponent(member)}`,
|
|
1703
|
-
evidenceSchema,
|
|
1704
|
-
{
|
|
1705
|
-
method: "POST",
|
|
1706
|
-
headers: { "Content-Type": file.type },
|
|
1707
|
-
body: file
|
|
1708
|
-
}
|
|
1709
|
-
),
|
|
1710
|
-
engagement: {
|
|
1711
|
-
boundaries: (input) => request(
|
|
1712
|
-
"/v1/engagement/boundaries?" + new URLSearchParams(
|
|
1713
|
-
Object.entries(engagementPageQuerySchema.parse(input)).flatMap(
|
|
1714
|
-
([key, value]) => value === void 0 ? [] : [[key, String(value)]]
|
|
1715
|
-
)
|
|
1716
|
-
).toString(),
|
|
1717
|
-
engagementBoundaryPageSchema
|
|
1718
|
-
),
|
|
1719
|
-
page: (input) => request(
|
|
1720
|
-
"/v1/engagement/history?" + new URLSearchParams(
|
|
1721
|
-
Object.entries(engagementPageQuerySchema.parse(input)).flatMap(
|
|
1722
|
-
([key, value]) => value === void 0 ? [] : [[key, String(value)]]
|
|
1723
|
-
)
|
|
1724
|
-
).toString(),
|
|
1725
|
-
engagementPageSchema
|
|
1726
|
-
)
|
|
1727
|
-
},
|
|
1728
|
-
content: {
|
|
1729
|
-
performance: (input) => request(
|
|
1730
|
-
"/v1/content/performance?" + new URLSearchParams(
|
|
1731
|
-
Object.entries(
|
|
1732
|
-
contentPerformanceQuerySchema.parse(input)
|
|
1733
|
-
).flatMap(
|
|
1734
|
-
([key, value]) => value === void 0 ? [] : [[key, String(value)]]
|
|
1735
|
-
)
|
|
1736
|
-
).toString(),
|
|
1737
|
-
contentPerformancePageSchema
|
|
1738
|
-
),
|
|
1739
|
-
qualifications: (input) => request(
|
|
1740
|
-
"/v1/content/qualifications?" + new URLSearchParams(
|
|
1741
|
-
Object.entries(
|
|
1742
|
-
contentQualificationQuerySchema.parse(input)
|
|
1743
|
-
).flatMap(
|
|
1744
|
-
([key, value]) => value === void 0 ? [] : [[key, String(value)]]
|
|
1745
|
-
)
|
|
1746
|
-
).toString(),
|
|
1747
|
-
contentQualificationPageSchema
|
|
1748
|
-
),
|
|
1749
|
-
admissions: (input) => request(
|
|
1750
|
-
"/v1/content/admissions?" + new URLSearchParams(
|
|
1751
|
-
Object.entries(contentAdmissionQuerySchema.parse(input)).flatMap(
|
|
1752
|
-
([key, value]) => value === void 0 ? [] : [[key, value]]
|
|
1753
|
-
)
|
|
1754
|
-
).toString(),
|
|
1755
|
-
contentAdmissionPageSchema
|
|
1756
|
-
),
|
|
1757
|
-
enroll: (input) => request(
|
|
1758
|
-
"/v1/content/enrollments",
|
|
1759
|
-
contentEnrollmentSchema,
|
|
1760
|
-
json(contentEnrollmentInputSchema.parse(input))
|
|
1761
|
-
),
|
|
1762
|
-
claim: (input) => request(
|
|
1763
|
-
"/v1/content/claims",
|
|
1764
|
-
contentAdmissionSchema,
|
|
1765
|
-
json(contentReleaseInputSchema.parse(input))
|
|
1766
|
-
)
|
|
1767
|
-
},
|
|
1768
|
-
submit: (input) => request("/v1/attempts", attemptSchema, json(input)),
|
|
1769
|
-
retry: (id) => request(`/v1/attempts/${id}/retry`, attemptSchema, json({})),
|
|
1770
|
-
/** @deprecated The participant API accepts only member sessions and rejects this staff call. Use the management API with a management key instead. */
|
|
1771
|
-
decide: (id, input) => request(`/v1/attempts/${id}/review`, attemptSchema, json(input))
|
|
1772
|
-
};
|
|
1773
|
-
}
|
|
1774
|
-
|
|
1775
|
-
export {
|
|
1776
|
-
pointLedgerPropertiesSchema,
|
|
1777
|
-
createPointLedgerSchema,
|
|
1778
|
-
pointLedgerSchema,
|
|
1779
|
-
pointLedgerDeclarationSchema,
|
|
1780
|
-
pointLedgerReferenceSchema,
|
|
1781
|
-
rewardDeliverySchema,
|
|
1782
|
-
rewardDeliveriesSchema,
|
|
1783
|
-
interactionSchema,
|
|
1784
|
-
questInteraction,
|
|
1785
|
-
questTypeVersionSchema,
|
|
1786
|
-
collectionSlotSchema,
|
|
1787
|
-
collectionSlotDeclarationSchema,
|
|
1788
|
-
questCollectionSchema,
|
|
1789
|
-
questInstanceSchema,
|
|
1790
|
-
questDraftChangesSchema,
|
|
1791
|
-
questDraftSchema,
|
|
1792
|
-
questCatalogSchema,
|
|
1793
|
-
catalogDeploymentSchema,
|
|
1794
|
-
catalogDeploymentPreviewSchema,
|
|
1795
|
-
saveQuestDraftSchema,
|
|
1796
|
-
publishQuestDraftSchema,
|
|
1797
|
-
questRewardViewSchema,
|
|
1798
|
-
questViewSchema,
|
|
1799
|
-
collectionViewSchema,
|
|
1800
|
-
questExperienceSchema,
|
|
1801
|
-
questPublicationPreviewSchema,
|
|
1802
|
-
allocateQuestSchema,
|
|
1803
|
-
allocatedQuestSchema,
|
|
1804
|
-
RelayError,
|
|
1805
|
-
QuestUpdatedError,
|
|
1806
|
-
reconcileQuestDraft,
|
|
1807
|
-
questActions,
|
|
1808
|
-
avatarSrc,
|
|
1809
|
-
defaultAvatar,
|
|
1810
|
-
defaultAvatarSvg,
|
|
1811
|
-
walletAvatarSeed,
|
|
1812
|
-
collectionCodeSchema,
|
|
1813
|
-
collectionPassSchema,
|
|
1814
|
-
collectionResolveSchema,
|
|
1815
|
-
collectionBeginSchema,
|
|
1816
|
-
collectionPreviewSchema,
|
|
1817
|
-
questConfiguration,
|
|
1818
|
-
xIdSchema,
|
|
1819
|
-
xConnectionSchema,
|
|
1820
|
-
xProfileSchema,
|
|
1821
|
-
xPostSchema,
|
|
1822
|
-
xRequestSchema,
|
|
1823
|
-
imageReferenceSchema,
|
|
1824
|
-
imageFieldSchema,
|
|
1825
|
-
imageFieldsSchema,
|
|
1826
|
-
imageRequestSchema,
|
|
1827
|
-
imageInspectionSchema,
|
|
1828
|
-
imageComparisonSchema,
|
|
1829
|
-
imageExtractionSchema,
|
|
1830
|
-
imageSightingsSchema,
|
|
1831
|
-
imageAssetArtifactSchema,
|
|
1832
|
-
imageUploadRequestSchema,
|
|
1833
|
-
imageUploadsSchema,
|
|
1834
|
-
publishedImageSchema,
|
|
1835
|
-
parseImageExtraction,
|
|
1836
|
-
parseImageResult,
|
|
1837
|
-
projectCatalogArtifactSchema,
|
|
1838
|
-
projectDeploymentSchema,
|
|
1839
|
-
deploymentPreviewSchema,
|
|
1840
|
-
publishDeploymentSchema,
|
|
1841
|
-
deploymentResultSchema,
|
|
1842
|
-
identityIntegrationInputSchema,
|
|
1843
|
-
identityIntegrationSchema,
|
|
1844
|
-
identityIntegrationSecretSchema,
|
|
1845
|
-
participantExchangeSchema,
|
|
1846
|
-
createRelayClient
|
|
1847
|
-
};
|