@odla-ai/chapter 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -184,6 +184,20 @@ async function createClerkUser(secretKey, input, fetchImpl = fetch) {
184
184
  }
185
185
 
186
186
  // src/member.ts
187
+ function hasDisclaimerAck(fields) {
188
+ return fields.disclaimerAck === true || fields.disclaimerAck === "true";
189
+ }
190
+ var IDENTITY_FIELDS = /* @__PURE__ */ new Set(["email", "firstName", "lastName"]);
191
+ function applicantProfile(chapter, fields) {
192
+ const profile = {};
193
+ for (const f of [...chapter.application.required, ...chapter.application.optional]) {
194
+ if (IDENTITY_FIELDS.has(f)) continue;
195
+ const v = fields[f];
196
+ if (typeof v === "string" && v.trim() !== "") profile[f] = v.trim();
197
+ }
198
+ if (fields.focus !== void 0) profile.focus = fields.focus;
199
+ return Object.keys(profile).length > 0 ? profile : void 0;
200
+ }
187
201
  async function submitApplication(db, chapter, fields, opts) {
188
202
  const app = chapter.application;
189
203
  for (const f of app.required) {
@@ -195,6 +209,10 @@ async function submitApplication(db, chapter, fields, opts) {
195
209
  const cap = app.maxLen[f] ?? app.defaultMaxLen;
196
210
  if (typeof v === "string" && v.length > cap) return { ok: false, error: `${f} exceeds ${cap} characters` };
197
211
  }
212
+ const acked = hasDisclaimerAck(fields);
213
+ if (app.requireDisclaimerAck && !acked) {
214
+ return { ok: false, error: "disclaimerAck is required" };
215
+ }
198
216
  const id = opts.newId();
199
217
  const row = { id, status: chapter.pipeline.initial, createdAt: opts.now };
200
218
  for (const f of [...app.required, ...app.optional]) {
@@ -202,11 +220,12 @@ async function submitApplication(db, chapter, fields, opts) {
202
220
  }
203
221
  if (fields.focus !== void 0) row.focus = fields.focus;
204
222
  if (opts.groupId) row.groupId = opts.groupId;
223
+ if (acked) row.disclaimerAckAt = opts.now;
205
224
  const { duplicate } = await db.transact(
206
225
  [{ t: "update", ns: "applications", id, attrs: row }],
207
226
  opts.submissionId ? { mutationId: `join:${opts.submissionId}` } : void 0
208
227
  );
209
- return { ok: true, id, duplicate, status: chapter.pipeline.initial };
228
+ return { ok: true, id, duplicate, status: chapter.pipeline.initial, disclaimerAckAt: acked ? opts.now : null };
210
229
  }
211
230
  function joinConfig(group, paymentsReady) {
212
231
  return {
@@ -515,8 +534,13 @@ async function provisionApplicant(db, chapter, applicationId, fields) {
515
534
  try {
516
535
  const secret = await getVaultSecret(db, "clerk_secret_key");
517
536
  if (secret) {
518
- if (chapter.account === "create") await createClerkUser(secret, { email, firstName: s(fields.firstName), lastName: s(fields.lastName) });
519
- else await createClerkInvitation(secret, { email });
537
+ const profile = applicantProfile(chapter, fields);
538
+ const publicMetadata = { applicationId, ...profile ? { profile } : {} };
539
+ if (chapter.account === "create") {
540
+ await createClerkUser(secret, { email, firstName: s(fields.firstName), lastName: s(fields.lastName), publicMetadata });
541
+ } else {
542
+ await createClerkInvitation(secret, { email, publicMetadata });
543
+ }
520
544
  }
521
545
  } catch {
522
546
  }
@@ -657,7 +681,14 @@ var handleMember = async (req, url, env, ctx) => {
657
681
  }
658
682
  await provisionApplicant(db, chapter, result.id, parsed);
659
683
  }
660
- return json({ id: result.id, duplicate: result.duplicate, status: result.status });
684
+ return json({
685
+ id: result.id,
686
+ duplicate: result.duplicate,
687
+ status: result.status,
688
+ // Echoed so a site can see (and assert in an integration test) whether its
689
+ // join page actually posted the ack. Absent consent is otherwise invisible.
690
+ disclaimerAckAt: result.disclaimerAckAt
691
+ });
661
692
  }
662
693
  return null;
663
694
  };