@cavuno/board 3.1.0 → 3.2.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.
Files changed (41) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/blog-DGBHmExV.d.mts +29 -0
  3. package/dist/blog-iV9XEIGf.d.ts +29 -0
  4. package/dist/{salaries-ChSqDBAM.d.mts → board-BJbXd_9_.d.mts} +14 -27
  5. package/dist/{salaries-BahBpxWT.d.ts → board-JhdUWIoq.d.ts} +14 -27
  6. package/dist/breadcrumbs-1hMjcsqA.d.mts +171 -0
  7. package/dist/breadcrumbs-DexU07TT.d.ts +171 -0
  8. package/dist/chunk-2ETP5UH4.mjs +271 -0
  9. package/dist/chunk-DLSO6XXY.mjs +33 -0
  10. package/dist/chunk-IJCJ26SQ.mjs +596 -0
  11. package/dist/chunk-L7ZOYWHW.mjs +98 -0
  12. package/dist/chunk-LUGJWOT7.mjs +96 -0
  13. package/dist/chunk-NXY3OWGF.mjs +1060 -0
  14. package/dist/chunk-STE77MAT.mjs +844 -0
  15. package/dist/filters.mjs +7 -668
  16. package/dist/format.d.mts +2 -1
  17. package/dist/format.d.ts +2 -1
  18. package/dist/format.js +592 -523
  19. package/dist/format.mjs +19 -680
  20. package/dist/go.mjs +4 -29
  21. package/dist/index.d.mts +5 -4
  22. package/dist/index.d.ts +5 -4
  23. package/dist/index.js +1 -1
  24. package/dist/index.mjs +22 -278
  25. package/dist/paths.mjs +20 -77
  26. package/dist/route-contract.mjs +30 -1079
  27. package/dist/seo.d.mts +14 -171
  28. package/dist/seo.d.ts +14 -171
  29. package/dist/seo.js +1 -1
  30. package/dist/seo.mjs +24 -1399
  31. package/dist/server.d.mts +2 -2
  32. package/dist/server.d.ts +2 -2
  33. package/dist/server.mjs +5 -31
  34. package/dist/sitemap.d.mts +2 -2
  35. package/dist/sitemap.d.ts +2 -2
  36. package/dist/sitemap.mjs +20 -96
  37. package/dist/well-known.mjs +4 -421
  38. package/package.json +6 -3
  39. package/skills/manifest.json +1 -1
  40. package/dist/board-NE98PlwN.d.ts +0 -16
  41. package/dist/board-muu8BI8P.d.mts +0 -16
@@ -0,0 +1,271 @@
1
+ // src/errors.ts
2
+ var BOARD_API_ERROR_CODES = [
3
+ // Cross-cutting envelope
4
+ "internal_error",
5
+ "validation_bad_request",
6
+ "validation_payload_too_large",
7
+ "rate_limited",
8
+ "rate_limit_unavailable",
9
+ "search_unavailable",
10
+ "too_many_filter_values",
11
+ "pagination_invalid_cursor",
12
+ "pagination_offset_too_large",
13
+ "auth_unauthenticated",
14
+ "auth_forbidden",
15
+ "plan_upgrade_required",
16
+ "unknown_error",
17
+ // Board resolution + custom pages
18
+ "boards_not_found",
19
+ "board_page_not_found",
20
+ // Board-user auth
21
+ "board_auth_email_taken",
22
+ "board_auth_invalid_credentials",
23
+ "board_auth_invalid_token",
24
+ "board_auth_registration_disabled",
25
+ "board_auth_token_expired",
26
+ // Board password gate
27
+ "board_password_required",
28
+ "board_password_invalid",
29
+ // Jobs browse
30
+ "jobs_not_found",
31
+ "jobs_invalid_filter",
32
+ // Taxonomy
33
+ "categories_not_found",
34
+ "skills_not_found",
35
+ "places_not_found",
36
+ // Companies (public reads)
37
+ "companies_not_found",
38
+ "company_markets_not_found",
39
+ "company_salary_not_found",
40
+ "company_category_salary_not_found",
41
+ // Salaries
42
+ "salaries_title_not_found",
43
+ "salaries_skill_not_found",
44
+ "salaries_location_not_found",
45
+ "salaries_title_location_not_found",
46
+ "salaries_skill_location_not_found",
47
+ // Blog (public reads)
48
+ "blog_post_not_found",
49
+ "blog_author_not_found",
50
+ "blog_tag_not_found",
51
+ // Talent directory
52
+ "talent_not_found",
53
+ "talent_directory_not_found",
54
+ "talent_directory_restricted",
55
+ // Job alerts (anonymous + authenticated)
56
+ "job_alert_not_found",
57
+ "job_alerts_disabled",
58
+ "candidate_alert_limit_reached",
59
+ "candidate_alert_not_found",
60
+ // Candidate account
61
+ "candidate_entry_not_found",
62
+ "candidate_handle_taken",
63
+ "candidate_job_not_found",
64
+ "resume_invalid_file",
65
+ "resume_upload_forbidden",
66
+ // Applications
67
+ "applications_external_apply_only",
68
+ "applications_guest_not_allowed",
69
+ "applications_job_not_found",
70
+ "applications_not_found",
71
+ "applications_resume_invalid_file",
72
+ "applications_unprocessable",
73
+ // Messaging
74
+ "messaging_application_not_found",
75
+ "messaging_application_not_linked",
76
+ "messaging_blocked",
77
+ "messaging_cannot_block_self",
78
+ "messaging_cold_rule",
79
+ "messaging_conversation_not_found",
80
+ "messaging_disabled",
81
+ "messaging_edit_window_expired",
82
+ "messaging_message_deleted",
83
+ "messaging_message_not_found",
84
+ "messaging_not_author",
85
+ "messaging_not_participant",
86
+ "messaging_not_permitted",
87
+ "messaging_not_recipient",
88
+ "messaging_rate_limited",
89
+ "messaging_recipient_not_found",
90
+ "messaging_recipient_not_open",
91
+ "messaging_unsend_window_expired",
92
+ // Employer self-service
93
+ "employer_applicant_not_found",
94
+ "employer_ats_unprocessable",
95
+ "employer_checkout_failed",
96
+ "employer_company_exists",
97
+ "employer_company_name_taken",
98
+ "employer_company_not_found",
99
+ "employer_job_not_found",
100
+ "employer_job_slug_taken",
101
+ "employer_jobs_quota_exceeded",
102
+ "employer_not_member",
103
+ "employer_payment_required",
104
+ "employer_pipeline_stage_not_found",
105
+ // Candidate job-access paywall
106
+ "paywall_already_active",
107
+ "paywall_disabled",
108
+ "paywall_invalid_checkout_session",
109
+ "paywall_no_candidate_profile",
110
+ "paywall_no_recurring_subscription",
111
+ "paywall_offer_not_found",
112
+ // Public job posting
113
+ "job_posting_logo_lookup_unavailable",
114
+ "job_posting_logo_not_found",
115
+ "job_posting_rejected"
116
+ ];
117
+ var BoardApiError = class extends Error {
118
+ status;
119
+ /** `<domain>_<snake_reason>` code from the v1 error envelope. */
120
+ code;
121
+ /** Structured, per-code details — shape varies by `code`. */
122
+ details;
123
+ requestId;
124
+ /** The parsed response body, untouched. */
125
+ raw;
126
+ constructor(input) {
127
+ super(input.message);
128
+ this.name = "BoardApiError";
129
+ this.status = input.status;
130
+ this.code = input.code;
131
+ this.details = input.details;
132
+ this.requestId = input.requestId;
133
+ this.raw = input.raw;
134
+ }
135
+ };
136
+ function isBoardApiError(e) {
137
+ return e instanceof Error && e.name === "BoardApiError" && typeof e.status === "number" && typeof e.code === "string";
138
+ }
139
+ function isNotFound(e) {
140
+ return isBoardApiError(e) && e.status === 404;
141
+ }
142
+ function isUnauthorized(e) {
143
+ return isBoardApiError(e) && e.status === 401;
144
+ }
145
+ function isBoardPasswordRequired(e) {
146
+ return isBoardApiError(e) && e.status === 401 && e.code === "board_password_required";
147
+ }
148
+ function isForbidden(e) {
149
+ return isBoardApiError(e) && e.status === 403;
150
+ }
151
+ function isValidationError(e) {
152
+ return isBoardApiError(e) && e.status === 400 && e.code === "validation_bad_request";
153
+ }
154
+ function isRateLimited(e) {
155
+ return isBoardApiError(e) && e.status === 429;
156
+ }
157
+ function isConflict(e) {
158
+ return isBoardApiError(e) && e.status === 409;
159
+ }
160
+
161
+ // src/scope.ts
162
+ function scopeToken(board) {
163
+ let hash = 5381;
164
+ for (let i = 0; i < board.length; i++) {
165
+ hash = (hash << 5) + hash + board.charCodeAt(i) >>> 0;
166
+ }
167
+ const sanitized = board.replace(/[^a-zA-Z0-9_-]/g, "_");
168
+ return `${sanitized}-${hash.toString(36)}`;
169
+ }
170
+
171
+ // src/storage.ts
172
+ var ACCESS_TOKEN_KEY = "cavuno_board_access_token";
173
+ var REFRESH_TOKEN_KEY = "cavuno_board_refresh_token";
174
+ var BOARD_ACCESS_GRANT_KEY = "cavuno_board_access_grant";
175
+ function isBrowser() {
176
+ return typeof globalThis.document !== "undefined";
177
+ }
178
+ function memoryStorage() {
179
+ const backing = /* @__PURE__ */ new Map();
180
+ return {
181
+ getItem: (key) => backing.get(key) ?? null,
182
+ setItem: (key, value) => {
183
+ backing.set(key, value);
184
+ },
185
+ removeItem: (key) => {
186
+ backing.delete(key);
187
+ }
188
+ };
189
+ }
190
+ function browserStorage(mode, scope) {
191
+ if (!isBrowser()) {
192
+ throw new Error(
193
+ `storage mode '${mode}' is browser-only \u2014 use 'nostore' + per-call headers on the server`
194
+ );
195
+ }
196
+ let backing;
197
+ try {
198
+ backing = mode === "local" ? globalThis.localStorage : globalThis.sessionStorage;
199
+ if (!backing) throw new Error("unavailable");
200
+ } catch {
201
+ throw new Error(
202
+ `storage mode '${mode}' is unavailable in this browsing context (storage access is blocked \u2014 e.g. a sandboxed or third-party iframe). Use 'memory', or 'nostore' + per-call headers.`
203
+ );
204
+ }
205
+ const suffix = scope ? `:${scopeToken(scope)}` : "";
206
+ return {
207
+ getItem: (key) => backing.getItem(`${key}${suffix}`),
208
+ setItem: (key, value) => {
209
+ backing.setItem(`${key}${suffix}`, value);
210
+ },
211
+ removeItem: (key) => {
212
+ backing.removeItem(`${key}${suffix}`);
213
+ }
214
+ };
215
+ }
216
+ var NOSTORE_BRAND = /* @__PURE__ */ Symbol.for("@cavuno/board:nostore");
217
+ function isNoStore(storage) {
218
+ return storage[NOSTORE_BRAND] === true;
219
+ }
220
+ var NOSTORE = {
221
+ [NOSTORE_BRAND]: true,
222
+ getItem: () => null,
223
+ setItem: () => {
224
+ },
225
+ removeItem: () => {
226
+ }
227
+ };
228
+ function resolveStorage(mode, scope) {
229
+ const resolved = mode ?? (isBrowser() ? "memory" : "nostore");
230
+ if (typeof resolved === "object") return resolved;
231
+ switch (resolved) {
232
+ case "memory":
233
+ return memoryStorage();
234
+ case "nostore":
235
+ return NOSTORE;
236
+ case "local":
237
+ case "session":
238
+ return browserStorage(resolved, scope);
239
+ default:
240
+ throw new Error(`Unknown storage mode '${String(resolved)}'`);
241
+ }
242
+ }
243
+ async function writeSession(storage, session) {
244
+ await storage.setItem(ACCESS_TOKEN_KEY, session.accessToken);
245
+ await storage.setItem(REFRESH_TOKEN_KEY, session.refreshToken);
246
+ }
247
+ async function clearSession(storage) {
248
+ await storage.removeItem(ACCESS_TOKEN_KEY);
249
+ await storage.removeItem(REFRESH_TOKEN_KEY);
250
+ }
251
+
252
+ export {
253
+ BOARD_API_ERROR_CODES,
254
+ BoardApiError,
255
+ isBoardApiError,
256
+ isNotFound,
257
+ isUnauthorized,
258
+ isBoardPasswordRequired,
259
+ isForbidden,
260
+ isValidationError,
261
+ isRateLimited,
262
+ isConflict,
263
+ scopeToken,
264
+ ACCESS_TOKEN_KEY,
265
+ REFRESH_TOKEN_KEY,
266
+ BOARD_ACCESS_GRANT_KEY,
267
+ isNoStore,
268
+ resolveStorage,
269
+ writeSession,
270
+ clearSession
271
+ };
@@ -0,0 +1,33 @@
1
+ // src/pagination.ts
2
+ function paginate(listFn, query, options) {
3
+ async function* pages() {
4
+ let current = query;
5
+ for (; ; ) {
6
+ const page = await listFn(current, options);
7
+ yield page;
8
+ if (!page.hasMore || page.nextCursor === null) return;
9
+ const { offset: _offset, ...rest } = current ?? {};
10
+ current = { ...rest, cursor: page.nextCursor };
11
+ }
12
+ }
13
+ return {
14
+ pages,
15
+ async *[Symbol.asyncIterator]() {
16
+ for await (const page of pages()) {
17
+ yield* page.data;
18
+ }
19
+ },
20
+ async toArray({ limit }) {
21
+ const items = [];
22
+ for await (const page of pages()) {
23
+ items.push(...page.data);
24
+ if (items.length >= limit) break;
25
+ }
26
+ return items.slice(0, limit);
27
+ }
28
+ };
29
+ }
30
+
31
+ export {
32
+ paginate
33
+ };