@cavuno/board 1.21.1 → 1.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -149,7 +149,7 @@ async function clearSession(storage) {
149
149
  }
150
150
 
151
151
  // src/version.ts
152
- var SDK_VERSION = "1.21.1";
152
+ var SDK_VERSION = "1.23.0";
153
153
 
154
154
  // src/client.ts
155
155
  function isRawBody(body) {
@@ -347,6 +347,35 @@ function authNamespace(client) {
347
347
  body
348
348
  });
349
349
  },
350
+ /**
351
+ * Verify the signed-in board user's email with the 6-digit code from the
352
+ * verification email (requires the bearer). Resolves void (204); an
353
+ * invalid/expired code is a 401 `BoardApiError`. Distinct from the
354
+ * anonymous magic-link `verifyEmail({ token })`.
355
+ *
356
+ * @example
357
+ * await board.auth.verifyEmailWithCode({ code: '123456' });
358
+ */
359
+ verifyEmailWithCode(body, options) {
360
+ return client.fetch("/auth/verify-email/otp", {
361
+ ...options,
362
+ method: "POST",
363
+ body
364
+ });
365
+ },
366
+ /**
367
+ * Re-send the verification email (fresh code + magic link) to the signed-in
368
+ * board user. Resolves void (204); no-op if already verified.
369
+ *
370
+ * @example
371
+ * await board.auth.resendVerification();
372
+ */
373
+ resendVerification(options) {
374
+ return client.fetch("/auth/verify-email/resend", {
375
+ ...options,
376
+ method: "POST"
377
+ });
378
+ },
350
379
  /**
351
380
  * Request a password-reset email. Always resolves (204) whether or
352
381
  * not the email exists — no account oracle.
@@ -869,6 +898,53 @@ function jobsNamespace(client) {
869
898
  query
870
899
  }
871
900
  );
901
+ },
902
+ /**
903
+ * Apply to a job natively (ADR-0054). Optional auth: a signed-in candidate
904
+ * applies from their profile (omit name/email); a guest supplies them
905
+ * (allowed only when the board permits applications without sign-up).
906
+ * Idempotent — a repeat apply returns the existing application.
907
+ *
908
+ * @example
909
+ * const application = await board.jobs.apply('senior-chef', {
910
+ * coverNote: 'Excited to cook here.',
911
+ * });
912
+ */
913
+ apply(jobSlug, body, options) {
914
+ return client.fetch(
915
+ `/jobs/${encodeURIComponent(jobSlug)}/apply`,
916
+ { ...options, method: "POST", body: body ?? {} }
917
+ );
918
+ },
919
+ /**
920
+ * Upload + attach a resume to an application (multipart). Signed-in
921
+ * candidates target their own application for the job; a guest passes the
922
+ * `applicationId` returned by `apply`. Returns the updated application.
923
+ *
924
+ * @example
925
+ * await board.jobs.uploadApplicationResume('senior-chef', file);
926
+ */
927
+ uploadApplicationResume(jobSlug, file, opts, options) {
928
+ const form = new FormData();
929
+ form.append("file", file);
930
+ if (opts?.applicationId) form.append("applicationId", opts.applicationId);
931
+ return client.fetch(
932
+ `/jobs/${encodeURIComponent(jobSlug)}/apply/resume`,
933
+ { ...options, method: "POST", body: form }
934
+ );
935
+ },
936
+ /**
937
+ * The authenticated candidate's application for this job (the apply-button
938
+ * "have I applied?" check). Throws a 404 `BoardApiError` when there is none.
939
+ *
940
+ * @example
941
+ * const application = await board.jobs.myApplication('senior-chef');
942
+ */
943
+ myApplication(jobSlug, options) {
944
+ return client.fetch(
945
+ `/jobs/${encodeURIComponent(jobSlug)}/application`,
946
+ options
947
+ );
872
948
  }
873
949
  };
874
950
  }
@@ -1508,6 +1584,185 @@ function meNamespace(client) {
1508
1584
  }
1509
1585
  }
1510
1586
  },
1587
+ /**
1588
+ * The authenticated board user's job-alert preferences (ADR-0053) —
1589
+ * a collection (up to 10). Creating one is active immediately (no
1590
+ * double opt-in — the authenticated action is the consent). There is no
1591
+ * pause: `remove` is the only way to stop an alert.
1592
+ */
1593
+ alerts: {
1594
+ /**
1595
+ * List my job alerts.
1596
+ *
1597
+ * @example
1598
+ * const { data } = await board.me.alerts.list();
1599
+ */
1600
+ list(options) {
1601
+ return client.fetch("/me/alerts", options);
1602
+ },
1603
+ /**
1604
+ * Create a new active job alert.
1605
+ *
1606
+ * @example
1607
+ * await board.me.alerts.create({
1608
+ * frequency: 'weekly',
1609
+ * jobFunctions: ['engineering'],
1610
+ * remoteOptions: ['remote'],
1611
+ * });
1612
+ */
1613
+ create(body, options) {
1614
+ return client.fetch("/me/alerts", {
1615
+ ...options,
1616
+ method: "POST",
1617
+ body
1618
+ });
1619
+ },
1620
+ /**
1621
+ * Retrieve one of my job alerts.
1622
+ *
1623
+ * @example
1624
+ * const alert = await board.me.alerts.retrieve(alertId);
1625
+ */
1626
+ retrieve(alertId, options) {
1627
+ return client.fetch(
1628
+ `/me/alerts/${encodeURIComponent(alertId)}`,
1629
+ options
1630
+ );
1631
+ },
1632
+ /**
1633
+ * Replace a job alert's filters + frequency in full. Returns the updated
1634
+ * alert.
1635
+ *
1636
+ * @example
1637
+ * await board.me.alerts.update(alertId, {
1638
+ * frequency: 'daily',
1639
+ * placeIds: ['ChIJ…'],
1640
+ * });
1641
+ */
1642
+ update(alertId, body, options) {
1643
+ return client.fetch(
1644
+ `/me/alerts/${encodeURIComponent(alertId)}`,
1645
+ { ...options, method: "PUT", body }
1646
+ );
1647
+ },
1648
+ /**
1649
+ * Delete a job alert. Resolves void on success (204).
1650
+ *
1651
+ * @example
1652
+ * await board.me.alerts.remove(alertId);
1653
+ */
1654
+ remove(alertId, options) {
1655
+ return client.fetch(`/me/alerts/${encodeURIComponent(alertId)}`, {
1656
+ ...options,
1657
+ method: "DELETE"
1658
+ });
1659
+ }
1660
+ },
1661
+ /**
1662
+ * The authenticated candidate's applications (ADR-0054). Apply itself lives
1663
+ * on the job (`board.jobs.apply` — it is optional-auth); these manage the
1664
+ * applications the candidate has already submitted, keyed by `applicationId`.
1665
+ */
1666
+ applications: {
1667
+ /**
1668
+ * List my applications, newest first.
1669
+ *
1670
+ * @example
1671
+ * const { data } = await board.me.applications.list();
1672
+ */
1673
+ list(query, options) {
1674
+ return client.fetch("/me/applications", {
1675
+ ...options,
1676
+ query
1677
+ });
1678
+ },
1679
+ /**
1680
+ * Retrieve one of my applications by id.
1681
+ *
1682
+ * @example
1683
+ * const application = await board.me.applications.retrieve(id);
1684
+ */
1685
+ retrieve(applicationId, options) {
1686
+ return client.fetch(
1687
+ `/me/applications/${encodeURIComponent(applicationId)}`,
1688
+ options
1689
+ );
1690
+ },
1691
+ /**
1692
+ * Edit the candidate-facing facts of an application (merge-patch). Only
1693
+ * while it is still editable. Returns the updated application.
1694
+ *
1695
+ * @example
1696
+ * await board.me.applications.updateFacts(id, { coverNote: '…' });
1697
+ */
1698
+ updateFacts(applicationId, body, options) {
1699
+ return client.fetch(
1700
+ `/me/applications/${encodeURIComponent(applicationId)}`,
1701
+ { ...options, method: "PATCH", body }
1702
+ );
1703
+ },
1704
+ /**
1705
+ * Withdraw (permanently delete) an application. Resolves void on 204.
1706
+ *
1707
+ * @example
1708
+ * await board.me.applications.withdraw(id);
1709
+ */
1710
+ withdraw(applicationId, options) {
1711
+ return client.fetch(
1712
+ `/me/applications/${encodeURIComponent(applicationId)}/withdraw`,
1713
+ { ...options, method: "POST" }
1714
+ );
1715
+ }
1716
+ },
1717
+ /**
1718
+ * The candidate's resume (ADR-0055). `upload` starts an async parse that
1719
+ * auto-populates the profile — it returns `parseStatus: 'parsing'`; poll
1720
+ * `retrieve()` until `parsed`/`failed`, then re-read `profile.*`.
1721
+ */
1722
+ resume: {
1723
+ /**
1724
+ * Upload a resume and start the async parse. Returns the resume with
1725
+ * `parseStatus: 'parsing'`.
1726
+ *
1727
+ * @example
1728
+ * await board.me.resume.upload(file, { keepResumeOnFile: true });
1729
+ */
1730
+ upload(file, opts, options) {
1731
+ const form = new FormData();
1732
+ form.append("resume", file);
1733
+ if (opts?.keepResumeOnFile) form.append("keepResumeOnFile", "true");
1734
+ if (opts?.importMode) form.append("importMode", opts.importMode);
1735
+ if (opts?.confirmReplaceAll) form.append("confirmReplaceAll", "true");
1736
+ return client.fetch("/me/resume", {
1737
+ ...options,
1738
+ method: "POST",
1739
+ body: form
1740
+ });
1741
+ },
1742
+ /**
1743
+ * Retrieve my resume state (parse status + stored file). Poll this after
1744
+ * `upload` until `parseStatus` is `parsed` or `failed`.
1745
+ *
1746
+ * @example
1747
+ * const resume = await board.me.resume.retrieve();
1748
+ */
1749
+ retrieve(options) {
1750
+ return client.fetch("/me/resume", options);
1751
+ },
1752
+ /**
1753
+ * Delete my stored resume file + withdraw keep-on-file consent (parsed
1754
+ * profile fields stay). Resolves void (204).
1755
+ *
1756
+ * @example
1757
+ * await board.me.resume.delete();
1758
+ */
1759
+ delete(options) {
1760
+ return client.fetch("/me/resume", {
1761
+ ...options,
1762
+ method: "DELETE"
1763
+ });
1764
+ }
1765
+ },
1511
1766
  savedJobs: {
1512
1767
  /**
1513
1768
  * List the authenticated user's saved jobs (each embeds the full
@@ -1549,6 +1804,256 @@ function meNamespace(client) {
1549
1804
  { ...options, method: "DELETE", query }
1550
1805
  );
1551
1806
  }
1807
+ },
1808
+ /**
1809
+ * The authenticated board user's messaging inbox (doc 34 / ADR-0053).
1810
+ * The v1 surface is polled REST — there is no realtime primitive; poll
1811
+ * `list` / `listMessages` / `unreadCount` on an interval (3–5s is the
1812
+ * reference cadence) for near-live updates.
1813
+ */
1814
+ conversations: {
1815
+ /**
1816
+ * List my conversations (each page sorted most-recent-activity-first;
1817
+ * cross-page cursor order is approximate — see the API docs). `archived:
1818
+ * true` returns the archived view. Poll for inbox liveness.
1819
+ *
1820
+ * @example
1821
+ * const { data } = await board.me.conversations.list({ limit: 20 });
1822
+ */
1823
+ list(query, options) {
1824
+ return client.fetch("/me/conversations", {
1825
+ ...options,
1826
+ query
1827
+ });
1828
+ },
1829
+ /**
1830
+ * The count of distinct conversations with an unread message — the
1831
+ * inbox badge. Poll for liveness.
1832
+ *
1833
+ * @example
1834
+ * const { count } = await board.me.conversations.unreadCount();
1835
+ */
1836
+ unreadCount(options) {
1837
+ return client.fetch(
1838
+ "/me/conversations/unread-count",
1839
+ options
1840
+ );
1841
+ },
1842
+ /**
1843
+ * A conversation's header — live-resolved counterparty identity, the
1844
+ * viewer's role, and the viewer's last-read pointer. The messages are a
1845
+ * separate paginated call (`listMessages`).
1846
+ *
1847
+ * @example
1848
+ * const convo = await board.me.conversations.retrieve(id);
1849
+ */
1850
+ retrieve(id, options) {
1851
+ return client.fetch(
1852
+ `/me/conversations/${encodeURIComponent(id)}`,
1853
+ options
1854
+ );
1855
+ },
1856
+ /**
1857
+ * A conversation's messages, oldest-first (append order). Unsent
1858
+ * messages are tombstones (empty `body`, `deletedAt` set). Poll for the
1859
+ * live thread.
1860
+ *
1861
+ * @example
1862
+ * const { data } = await board.me.conversations.listMessages(id, { limit: 50 });
1863
+ */
1864
+ listMessages(id, query, options) {
1865
+ return client.fetch(
1866
+ `/me/conversations/${encodeURIComponent(id)}/messages`,
1867
+ { ...options, query }
1868
+ );
1869
+ },
1870
+ /**
1871
+ * Cold-initiate a conversation with a candidate (employer-only).
1872
+ * Converges on the existing thread. Returns the created message.
1873
+ *
1874
+ * @example
1875
+ * const msg = await board.me.conversations.start({ candidateBoardUserId, body: 'Hi!' });
1876
+ */
1877
+ start(body, options) {
1878
+ return client.fetch("/me/conversations", {
1879
+ ...options,
1880
+ method: "POST",
1881
+ body
1882
+ });
1883
+ },
1884
+ /**
1885
+ * Message an applicant from the ATS (application context, outside the
1886
+ * talent paywall). Returns the created message.
1887
+ *
1888
+ * @example
1889
+ * const msg = await board.me.conversations.startAboutApplication({ applicationId, body: '…' });
1890
+ */
1891
+ startAboutApplication(body, options) {
1892
+ return client.fetch("/me/conversations/about-application", {
1893
+ ...options,
1894
+ method: "POST",
1895
+ body
1896
+ });
1897
+ },
1898
+ /**
1899
+ * Reply in an existing conversation. Returns the created message.
1900
+ *
1901
+ * @example
1902
+ * const msg = await board.me.conversations.reply(id, { body: 'Sounds good' });
1903
+ */
1904
+ reply(id, body, options) {
1905
+ return client.fetch(
1906
+ `/me/conversations/${encodeURIComponent(id)}/reply`,
1907
+ { ...options, method: "POST", body }
1908
+ );
1909
+ },
1910
+ /**
1911
+ * Mark a conversation read for the viewer. Idempotent.
1912
+ *
1913
+ * @example
1914
+ * await board.me.conversations.markRead(id);
1915
+ */
1916
+ markRead(id, options) {
1917
+ return client.fetch(
1918
+ `/me/conversations/${encodeURIComponent(id)}/read`,
1919
+ { ...options, method: "POST" }
1920
+ );
1921
+ },
1922
+ /**
1923
+ * Archive a conversation for the viewer (per-side). Idempotent.
1924
+ *
1925
+ * @example
1926
+ * await board.me.conversations.archive(id);
1927
+ */
1928
+ archive(id, options) {
1929
+ return client.fetch(
1930
+ `/me/conversations/${encodeURIComponent(id)}/archive`,
1931
+ { ...options, method: "POST" }
1932
+ );
1933
+ },
1934
+ /**
1935
+ * Move an archived conversation back to the main inbox. Idempotent.
1936
+ *
1937
+ * @example
1938
+ * await board.me.conversations.unarchive(id);
1939
+ */
1940
+ unarchive(id, options) {
1941
+ return client.fetch(
1942
+ `/me/conversations/${encodeURIComponent(id)}/unarchive`,
1943
+ { ...options, method: "POST" }
1944
+ );
1945
+ },
1946
+ /**
1947
+ * The existing employer↔candidate conversation id (or null). Tier-3
1948
+ * talent-contact helper — route to an existing thread instead of opening
1949
+ * a composer.
1950
+ *
1951
+ * @example
1952
+ * const { conversationId } = await board.me.conversations.findExisting({ candidateBoardUserId });
1953
+ */
1954
+ findExisting(query, options) {
1955
+ return client.fetch(
1956
+ "/me/conversations/find-existing",
1957
+ { ...options, query }
1958
+ );
1959
+ }
1960
+ },
1961
+ /**
1962
+ * Blocking (doc 34 §E): list / add / remove blocks + a Tier-3 status check.
1963
+ */
1964
+ blocks: {
1965
+ /**
1966
+ * The users I've blocked.
1967
+ *
1968
+ * @example
1969
+ * const { data } = await board.me.blocks.list();
1970
+ */
1971
+ list(options) {
1972
+ return client.fetch("/me/blocks", options);
1973
+ },
1974
+ /**
1975
+ * Block a user (silent). Idempotent.
1976
+ *
1977
+ * @example
1978
+ * await board.me.blocks.create({ boardUserId });
1979
+ */
1980
+ create(body, options) {
1981
+ return client.fetch("/me/blocks", {
1982
+ ...options,
1983
+ method: "POST",
1984
+ body
1985
+ });
1986
+ },
1987
+ /**
1988
+ * Unblock a user. Idempotent.
1989
+ *
1990
+ * @example
1991
+ * await board.me.blocks.remove(boardUserId);
1992
+ */
1993
+ remove(boardUserId, options) {
1994
+ return client.fetch(
1995
+ `/me/blocks/${encodeURIComponent(boardUserId)}`,
1996
+ { ...options, method: "DELETE" }
1997
+ );
1998
+ },
1999
+ /**
2000
+ * Whether I've blocked a user (Tier-3 helper).
2001
+ *
2002
+ * @example
2003
+ * const { blocked } = await board.me.blocks.status(boardUserId);
2004
+ */
2005
+ status(boardUserId, options) {
2006
+ return client.fetch(
2007
+ `/me/blocks/${encodeURIComponent(boardUserId)}`,
2008
+ options
2009
+ );
2010
+ }
2011
+ },
2012
+ /**
2013
+ * Message-scoped actions (doc 34 §E): edit / unsend your own messages
2014
+ * (15-minute window), and report a message addressed to you.
2015
+ */
2016
+ messages: {
2017
+ /**
2018
+ * Edit one of your own messages (within the 15-minute window). Returns
2019
+ * the updated message.
2020
+ *
2021
+ * @example
2022
+ * const msg = await board.me.messages.edit(id, { body: 'fixed typo' });
2023
+ */
2024
+ edit(id, body, options) {
2025
+ return client.fetch(`/me/messages/${encodeURIComponent(id)}`, {
2026
+ ...options,
2027
+ method: "PATCH",
2028
+ body
2029
+ });
2030
+ },
2031
+ /**
2032
+ * Unsend (soft-delete) one of your own messages (within the 15-minute
2033
+ * window). Idempotent. Returns the tombstoned message (empty `body`).
2034
+ *
2035
+ * @example
2036
+ * await board.me.messages.unsend(id);
2037
+ */
2038
+ unsend(id, options) {
2039
+ return client.fetch(`/me/messages/${encodeURIComponent(id)}`, {
2040
+ ...options,
2041
+ method: "DELETE"
2042
+ });
2043
+ },
2044
+ /**
2045
+ * Report a message addressed to you for moderation. Auto-blocks the
2046
+ * author.
2047
+ *
2048
+ * @example
2049
+ * const { blocked } = await board.me.messages.report(id, { reason: 'spam' });
2050
+ */
2051
+ report(id, body, options) {
2052
+ return client.fetch(
2053
+ `/me/messages/${encodeURIComponent(id)}/report`,
2054
+ { ...options, method: "POST", body }
2055
+ );
2056
+ }
1552
2057
  }
1553
2058
  };
1554
2059
  }