@odla-ai/chapter 0.40.1 → 0.40.2

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.
@@ -1676,7 +1676,14 @@ async function createClerkUser(secretKey, input, fetchImpl = fetch) {
1676
1676
  headers: { authorization: `Bearer ${secretKey}`, "content-type": "application/json" },
1677
1677
  body: JSON.stringify(body)
1678
1678
  });
1679
- if (res.ok) return { ok: true, status: res.status };
1679
+ if (res.ok) {
1680
+ const body2 = typeof res.json === "function" ? await res.json().catch(() => null) : null;
1681
+ return {
1682
+ ok: true,
1683
+ status: res.status,
1684
+ ...typeof body2?.id === "string" && body2.id ? { userId: body2.id } : {}
1685
+ };
1686
+ }
1680
1687
  const healed = heal(res.status);
1681
1688
  const repair = input.repairMetadata ?? {
1682
1689
  ...input.publicMetadata !== void 0 ? { publicMetadata: input.publicMetadata } : {},
@@ -1726,6 +1733,34 @@ async function syncApplicantPrivateMetadata(db, chapter, applicationId, fields,
1726
1733
  return false;
1727
1734
  }
1728
1735
  }
1736
+ var AccountProvisioningError = class extends Error {
1737
+ constructor(code, status) {
1738
+ super(code);
1739
+ this.code = code;
1740
+ this.status = status;
1741
+ }
1742
+ code;
1743
+ status;
1744
+ name = "AccountProvisioningError";
1745
+ };
1746
+ async function provisionApplicantForRoute(db, chapter, applicationId, fields) {
1747
+ try {
1748
+ await provisionApplicant(db, chapter, applicationId, fields);
1749
+ return null;
1750
+ } catch (error) {
1751
+ if (!(error instanceof AccountProvisioningError)) throw error;
1752
+ return {
1753
+ status: error.status,
1754
+ body: {
1755
+ error: {
1756
+ code: error.code,
1757
+ message: error.code === "clerk_secret_unavailable" ? "account provisioning credential is unavailable" : "account provisioning failed"
1758
+ },
1759
+ applicationId
1760
+ }
1761
+ };
1762
+ }
1763
+ }
1729
1764
  async function provisionApplicant(db, chapter, applicationId, fields) {
1730
1765
  const email = typeof fields.email === "string" ? fields.email : "";
1731
1766
  if (!email) return;
@@ -1750,9 +1785,9 @@ async function provisionApplicant(db, chapter, applicationId, fields) {
1750
1785
  } catch {
1751
1786
  }
1752
1787
  if (chapter.account === "none") return;
1788
+ const secret = await getVaultSecret(db, "clerk_secret_key");
1789
+ if (!secret) throw new AccountProvisioningError("clerk_secret_unavailable", 503);
1753
1790
  try {
1754
- const secret = await getVaultSecret(db, "clerk_secret_key");
1755
- if (!secret) return;
1756
1791
  const privateMetadata = applicantPrivateMetadata(chapter, applicationId, fields);
1757
1792
  if (chapter.account === "create") {
1758
1793
  const result = await createClerkUser(secret, {
@@ -1765,11 +1800,13 @@ async function provisionApplicant(db, chapter, applicationId, fields) {
1765
1800
  privateMetadata: applicantPrivateMetadata(chapter, applicationId, fields, true)
1766
1801
  }
1767
1802
  });
1768
- if (result.ok && (!result.existed || result.refreshed)) {
1769
- await markPrivateMetadataSynced(db, applicationId);
1803
+ if (!result.ok || result.existed && !result.refreshed) {
1804
+ throw new AccountProvisioningError("clerk_account_provisioning_failed", 502);
1770
1805
  }
1806
+ await markPrivateMetadataSynced(db, applicationId, result.userId);
1771
1807
  } else {
1772
1808
  const result = await createClerkInvitation(secret, { email });
1809
+ if (!result.ok) throw new AccountProvisioningError("clerk_account_provisioning_failed", 502);
1773
1810
  if (result.existed) {
1774
1811
  const refreshed = await updateClerkUserMetadataByEmail(secret, email, {
1775
1812
  publicMetadata: publicProfileRemoval,
@@ -1778,7 +1815,9 @@ async function provisionApplicant(db, chapter, applicationId, fields) {
1778
1815
  if (refreshed) await markPrivateMetadataSynced(db, applicationId);
1779
1816
  }
1780
1817
  }
1781
- } catch {
1818
+ } catch (error) {
1819
+ if (error instanceof AccountProvisioningError) throw error;
1820
+ throw new AccountProvisioningError("clerk_account_provisioning_failed", 502);
1782
1821
  }
1783
1822
  }
1784
1823
  async function notifyAdminOfApplication(db, env, chapterId, applicationId, fields) {
@@ -2002,8 +2041,9 @@ var handleMember = async (req, url, env, ctx) => {
2002
2041
  if (effectiveChapter.sends.adminNotification === "submit") {
2003
2042
  await notifyAdminOfApplication(db, env, chapter.id, result.id, parsed);
2004
2043
  }
2005
- await provisionApplicant(db, effectiveChapter, result.id, parsed);
2006
2044
  }
2045
+ const provisioningFailure = await provisionApplicantForRoute(db, effectiveChapter, result.id, parsed);
2046
+ if (provisioningFailure) return json(provisioningFailure.body, provisioningFailure.status);
2007
2047
  const apps = (await db.query({ applications: { $: { where: { id: result.id }, limit: 1 } } })).applications;
2008
2048
  const canonical2 = Array.isArray(apps) ? apps[0] : void 0;
2009
2049
  const groups = (await db.query({ groups: { $: { where: { id: chapter.id }, limit: 1 } } })).groups;