@cavuno/board 1.26.0 → 1.28.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.mjs CHANGED
@@ -134,7 +134,7 @@ var BoardApiError = class extends Error {
134
134
  }
135
135
  };
136
136
  function isBoardApiError(e) {
137
- return e instanceof BoardApiError;
137
+ return e instanceof Error && e.name === "BoardApiError";
138
138
  }
139
139
  function isNotFound(e) {
140
140
  return isBoardApiError(e) && e.status === 404;
@@ -195,14 +195,45 @@ function memoryStorage() {
195
195
  }
196
196
  };
197
197
  }
198
+ function scopeToken(board) {
199
+ return board.replace(/[^a-zA-Z0-9_-]/g, "_");
200
+ }
201
+ function browserStorage(mode, scope) {
202
+ if (!isBrowser()) {
203
+ throw new Error(
204
+ `storage mode '${mode}' is browser-only \u2014 use 'nostore' + per-call headers on the server`
205
+ );
206
+ }
207
+ let backing;
208
+ try {
209
+ backing = mode === "local" ? globalThis.localStorage : globalThis.sessionStorage;
210
+ if (!backing) throw new Error("unavailable");
211
+ } catch {
212
+ throw new Error(
213
+ `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.`
214
+ );
215
+ }
216
+ const suffix = scope ? `:${scopeToken(scope)}` : "";
217
+ return {
218
+ getItem: (key) => backing.getItem(`${key}${suffix}`),
219
+ setItem: (key, value) => {
220
+ backing.setItem(`${key}${suffix}`, value);
221
+ },
222
+ removeItem: (key) => {
223
+ backing.removeItem(`${key}${suffix}`);
224
+ }
225
+ };
226
+ }
227
+ var NOSTORE_BRAND = /* @__PURE__ */ Symbol.for("@cavuno/board:nostore");
198
228
  var NOSTORE = {
229
+ [NOSTORE_BRAND]: true,
199
230
  getItem: () => null,
200
231
  setItem: () => {
201
232
  },
202
233
  removeItem: () => {
203
234
  }
204
235
  };
205
- function resolveStorage(mode) {
236
+ function resolveStorage(mode, scope) {
206
237
  const resolved = mode ?? (isBrowser() ? "memory" : "nostore");
207
238
  if (typeof resolved === "object") return resolved;
208
239
  switch (resolved) {
@@ -210,6 +241,9 @@ function resolveStorage(mode) {
210
241
  return memoryStorage();
211
242
  case "nostore":
212
243
  return NOSTORE;
244
+ case "local":
245
+ case "session":
246
+ return browserStorage(resolved, scope);
213
247
  default:
214
248
  throw new Error(`Unknown storage mode '${String(resolved)}'`);
215
249
  }
@@ -224,7 +258,7 @@ async function clearSession(storage) {
224
258
  }
225
259
 
226
260
  // src/version.ts
227
- var SDK_VERSION = "1.26.0";
261
+ var SDK_VERSION = "1.28.0";
228
262
 
229
263
  // src/client.ts
230
264
  function isRawBody(body) {
@@ -2505,12 +2539,31 @@ function paginate(listFn, query, options) {
2505
2539
  };
2506
2540
  }
2507
2541
 
2542
+ // src/messaging-derive.ts
2543
+ function isOwnMessage(message, counterpartyId) {
2544
+ return message.authorBoardUserId !== counterpartyId;
2545
+ }
2546
+ function isColdRule(messages, counterpartyId) {
2547
+ const theyReplied = messages.some(
2548
+ (m) => m.authorBoardUserId === counterpartyId
2549
+ );
2550
+ const iSent = messages.some((m) => m.authorBoardUserId !== counterpartyId);
2551
+ return iSent && !theyReplied;
2552
+ }
2553
+ function lastOwnMessageId(messages, counterpartyId) {
2554
+ for (let i = messages.length - 1; i >= 0; i--) {
2555
+ const message = messages[i];
2556
+ if (message.authorBoardUserId !== counterpartyId) return message.id;
2557
+ }
2558
+ return null;
2559
+ }
2560
+
2508
2561
  // src/index.ts
2509
2562
  function createBoardClient(options) {
2510
2563
  const client = new BoardClient({
2511
2564
  baseUrl: options.baseUrl,
2512
2565
  board: options.board,
2513
- storage: resolveStorage(options.auth?.storage),
2566
+ storage: resolveStorage(options.auth?.storage, options.board),
2514
2567
  globalHeaders: options.globalHeaders,
2515
2568
  onRequest: options.onRequest,
2516
2569
  onResponse: options.onResponse,
@@ -2572,11 +2625,14 @@ export {
2572
2625
  createBoardClient,
2573
2626
  isBoardApiError,
2574
2627
  isBoardPasswordRequired,
2628
+ isColdRule,
2575
2629
  isConflict,
2576
2630
  isForbidden,
2577
2631
  isNotFound,
2632
+ isOwnMessage,
2578
2633
  isRateLimited,
2579
2634
  isUnauthorized,
2580
2635
  isValidationError,
2636
+ lastOwnMessageId,
2581
2637
  paginate
2582
2638
  };
@@ -3833,4 +3833,4 @@ type JobsSimilarQuery = {
3833
3833
  };
3834
3834
  type JobsSearchBody = Schemas['PublicSearchJobsBody'];
3835
3835
 
3836
- export type { CustomFieldValue as C, EmploymentType as E, JobsListQuery as J, ListEnvelope as L, OfficeLocation as O, PublicJob as P, RemoteOption as R, Schemas as S, Seniority as a, RelatedSearch as b, components as c, JobCardListEnvelope as d, JobsSearchBody as e, JobCardSearchEnvelope as f, JobsSimilarQuery as g, SearchEnvelope as h, CustomFieldValues as i, EducationRequirement as j, JobCompany as k, JobSort as l, PublicJobCard as m, RemotePermit as n, RemoteTimezone as o, StorefrontPagination as p };
3836
+ export type { CustomFieldValue as C, EmploymentType as E, JobSort as J, ListEnvelope as L, OfficeLocation as O, PublicJob as P, RemoteOption as R, Seniority as S, PublicJobCard as a, Schemas as b, components as c, JobsListQuery as d, JobCardListEnvelope as e, JobsSearchBody as f, JobCardSearchEnvelope as g, JobsSimilarQuery as h, SearchEnvelope as i, CustomFieldValues as j, EducationRequirement as k, JobCompany as l, RelatedSearch as m, RemotePermit as n, RemoteTimezone as o, StorefrontPagination as p };
@@ -3833,4 +3833,4 @@ type JobsSimilarQuery = {
3833
3833
  };
3834
3834
  type JobsSearchBody = Schemas['PublicSearchJobsBody'];
3835
3835
 
3836
- export type { CustomFieldValue as C, EmploymentType as E, JobsListQuery as J, ListEnvelope as L, OfficeLocation as O, PublicJob as P, RemoteOption as R, Schemas as S, Seniority as a, RelatedSearch as b, components as c, JobCardListEnvelope as d, JobsSearchBody as e, JobCardSearchEnvelope as f, JobsSimilarQuery as g, SearchEnvelope as h, CustomFieldValues as i, EducationRequirement as j, JobCompany as k, JobSort as l, PublicJobCard as m, RemotePermit as n, RemoteTimezone as o, StorefrontPagination as p };
3836
+ export type { CustomFieldValue as C, EmploymentType as E, JobSort as J, ListEnvelope as L, OfficeLocation as O, PublicJob as P, RemoteOption as R, Seniority as S, PublicJobCard as a, Schemas as b, components as c, JobsListQuery as d, JobCardListEnvelope as e, JobsSearchBody as f, JobCardSearchEnvelope as g, JobsSimilarQuery as h, SearchEnvelope as i, CustomFieldValues as j, EducationRequirement as k, JobCompany as l, RelatedSearch as m, RemotePermit as n, RemoteTimezone as o, StorefrontPagination as p };
@@ -0,0 +1,130 @@
1
+ import { b as Schemas, L as ListEnvelope, m as RelatedSearch } from './jobs-DK5mPBgq.js';
2
+
3
+ type PublicBoard = Schemas['PublicBoardContext'];
4
+ type PublicBoardFeatures = PublicBoard['features'];
5
+ type PublicBoardAnalytics = PublicBoard['analytics'];
6
+ type PublicBoardTheme = NonNullable<PublicBoard['theme']>;
7
+ /**
8
+ * An operator-defined custom job-field definition (CAV-294). Board-wide;
9
+ * use it to render and localize a job's opaque `customFieldValues` (resolve
10
+ * option `key`s → labels, honour field `type` and display order). Shared with
11
+ * the Operator API's custom-field surface (one canonical schema).
12
+ */
13
+ type CustomFieldDefinition = Schemas['CustomFieldDefinition'];
14
+ type CustomFieldType = CustomFieldDefinition['type'];
15
+ type CustomFieldOption = Schemas['CustomFieldOption'];
16
+
17
+ /** Author shape embedded on posts (no `object` discriminator). */
18
+ type BlogAuthorEmbed = Schemas['PublicBlogAuthorEmbed'];
19
+ /** Tag shape embedded on posts (no `object` discriminator). */
20
+ type BlogTagEmbed = Schemas['PublicBlogTagEmbed'];
21
+ type PublicBlogAuthor = Schemas['PublicBlogAuthor'];
22
+ type PublicBlogTag = Schemas['PublicBlogTag'];
23
+ type PublicBlogPostSummary = Schemas['PublicBlogPostSummary'];
24
+ /** Detail shape — `html` appears on the single read only, never on summaries. */
25
+ type PublicBlogPost = Schemas['PublicBlogPost'];
26
+ /** Previous (older) + next (newer) posts for the detail prev/next nav. */
27
+ type PublicBlogAdjacentPosts = Schemas['PublicBlogAdjacentPosts'];
28
+ type BlogPostsListQuery = {
29
+ cursor?: string;
30
+ /** 1–100. */
31
+ limit?: number;
32
+ tagSlug?: string;
33
+ authorSlug?: string;
34
+ /** Opt-in only: pass `'true'` to restrict to featured posts. */
35
+ featured?: 'true';
36
+ };
37
+ type BlogSimilarQuery = {
38
+ /** 1–20; default 6. */
39
+ limit?: number;
40
+ };
41
+ type BlogSearchBody = Schemas['PublicBlogSearchBody'];
42
+
43
+ type PublicCompany = Schemas['CompanyPublic'];
44
+ /** A market (sector) a company operates in — name + its source slug. */
45
+ type CompanyMarketRef = Schemas['CompanyMarketRef'];
46
+ /** The company DETAIL shape — `PublicCompany` plus `markets` (detail-only). */
47
+ type PublicCompanyDetail = Schemas['CompanyPublicDetail'];
48
+ /**
49
+ * A company's salary overview (ADR-0046): overall pay, by-seniority rows vs the
50
+ * board baseline, top competitors, top locations, and a per-category summary.
51
+ * Names are board-language localized; the company slug/name are not.
52
+ */
53
+ type CompanySalary = Schemas['CompanySalary'];
54
+ /**
55
+ * A company's salary for one job category: the category's source + board-language
56
+ * canonical slug, by-seniority vs the board-category baseline, and competitors in
57
+ * the category. The category name is localized; the company name is not.
58
+ */
59
+ type CompanyCategorySalary = Schemas['CompanyCategorySalary'];
60
+ /** The companies browse list — `PublicCompany`s + `market` `relatedSearches`. */
61
+ interface CompanyListEnvelope extends ListEnvelope<PublicCompany> {
62
+ relatedSearches?: RelatedSearch[];
63
+ }
64
+ type CompaniesListQuery = {
65
+ cursor?: string;
66
+ /** Scope to a single market (sector) by slug. Unknown slugs 404. */
67
+ marketSlug?: string;
68
+ /** 1–100. */
69
+ limit?: number;
70
+ /**
71
+ * Storefront page offset (companies to skip); takes precedence over
72
+ * `cursor`. Pair with the response `count` to page in parallel.
73
+ */
74
+ offset?: number;
75
+ };
76
+ type CompanyJobsListQuery = {
77
+ cursor?: string;
78
+ /** 1–100. */
79
+ limit?: number;
80
+ };
81
+ type CompanySimilarQuery = {
82
+ /** 1–20, default 6. */
83
+ limit?: number;
84
+ };
85
+ type CompanyMarket = Schemas['CompanyMarket'];
86
+ type CompanyMarketsListQuery = {
87
+ /** 1–200, default 100 (a top-by-company-count preview). */
88
+ limit?: number;
89
+ search?: string;
90
+ };
91
+ type CompaniesSearchBody = Schemas['PublicCompaniesSearchBody'];
92
+
93
+ /** A job title's salary breakdown (overall + by-seniority + top rails). */
94
+ type TitleSalaryDetail = Schemas['TitleSalaryDetail'];
95
+ /** A skill's salary breakdown. */
96
+ type SkillSalaryDetail = Schemas['SkillSalaryDetail'];
97
+ /** A place's salary breakdown (city overall + siblings, or area child cities). */
98
+ type LocationSalaryDetail = Schemas['LocationSalaryDetail'];
99
+ /** A company on the `/salaries/companies` hub (ranked by sample size). */
100
+ type SalaryCompany = Schemas['SalaryCompanyIndexItem'];
101
+ /** A job title on the `/salaries/titles` index. */
102
+ type SalaryTitle = Schemas['SalaryTitleIndexItem'];
103
+ /** A skill on the `/salaries/skills` index. */
104
+ type SalarySkill = Schemas['SalarySkillIndexItem'];
105
+ /**
106
+ * A place on the `/salaries/locations` index — a flattened tree node carrying
107
+ * its `parentSlug` (the consumer rebuilds the country → region → city browse).
108
+ */
109
+ type SalaryLocation = Schemas['SalaryLocationIndexItem'];
110
+ /** A title's salary across locations (flattened `parentSlug` tree). */
111
+ type TitleLocationsIndex = Schemas['TitleLocationsIndex'];
112
+ /** A skill's salary across locations. */
113
+ type SkillLocationsIndex = Schemas['SkillLocationsIndex'];
114
+ /** A place's salary by title (suffix read-model). */
115
+ type LocationTitlesIndex = Schemas['LocationTitlesIndex'];
116
+ /** A place's salary by skill. */
117
+ type LocationSkillsIndex = Schemas['LocationSkillsIndex'];
118
+ /** A title's salary in one place (4 source + canonical slugs). */
119
+ type TitleLocationSalary = Schemas['TitleLocationSalary'];
120
+ /** A skill's salary in one place. */
121
+ type SkillLocationSalary = Schemas['SkillLocationSalary'];
122
+ /**
123
+ * Board-language overlay for a salary read. `en` (the default) is the identity
124
+ * fast-path; a non-`en` locale overlays board-language names + canonical slugs.
125
+ */
126
+ type SalaryDetailQuery = {
127
+ locale?: string;
128
+ };
129
+
130
+ export type { PublicBoardTheme as A, BlogAuthorEmbed as B, CompanyCategorySalary as C, PublicCompany as D, PublicCompanyDetail as E, SalaryCompany as F, SalaryLocation as G, SalarySkill as H, SalaryTitle as I, SkillLocationSalary as J, SkillLocationsIndex as K, LocationSalaryDetail as L, TitleLocationSalary as M, TitleLocationsIndex as N, PublicBoard as P, SkillSalaryDetail as S, TitleSalaryDetail as T, PublicBlogPostSummary as a, CompanySalary as b, CompaniesListQuery as c, CompanyListEnvelope as d, CompaniesSearchBody as e, CompanyJobsListQuery as f, CompanySimilarQuery as g, CompanyMarketsListQuery as h, SalaryDetailQuery as i, BlogPostsListQuery as j, BlogSimilarQuery as k, BlogSearchBody as l, BlogTagEmbed as m, CompanyMarket as n, CompanyMarketRef as o, CustomFieldDefinition as p, CustomFieldOption as q, CustomFieldType as r, LocationSkillsIndex as s, LocationTitlesIndex as t, PublicBlogAdjacentPosts as u, PublicBlogAuthor as v, PublicBlogPost as w, PublicBlogTag as x, PublicBoardAnalytics as y, PublicBoardFeatures as z };
@@ -0,0 +1,130 @@
1
+ import { b as Schemas, L as ListEnvelope, m as RelatedSearch } from './jobs-DK5mPBgq.mjs';
2
+
3
+ type PublicBoard = Schemas['PublicBoardContext'];
4
+ type PublicBoardFeatures = PublicBoard['features'];
5
+ type PublicBoardAnalytics = PublicBoard['analytics'];
6
+ type PublicBoardTheme = NonNullable<PublicBoard['theme']>;
7
+ /**
8
+ * An operator-defined custom job-field definition (CAV-294). Board-wide;
9
+ * use it to render and localize a job's opaque `customFieldValues` (resolve
10
+ * option `key`s → labels, honour field `type` and display order). Shared with
11
+ * the Operator API's custom-field surface (one canonical schema).
12
+ */
13
+ type CustomFieldDefinition = Schemas['CustomFieldDefinition'];
14
+ type CustomFieldType = CustomFieldDefinition['type'];
15
+ type CustomFieldOption = Schemas['CustomFieldOption'];
16
+
17
+ /** Author shape embedded on posts (no `object` discriminator). */
18
+ type BlogAuthorEmbed = Schemas['PublicBlogAuthorEmbed'];
19
+ /** Tag shape embedded on posts (no `object` discriminator). */
20
+ type BlogTagEmbed = Schemas['PublicBlogTagEmbed'];
21
+ type PublicBlogAuthor = Schemas['PublicBlogAuthor'];
22
+ type PublicBlogTag = Schemas['PublicBlogTag'];
23
+ type PublicBlogPostSummary = Schemas['PublicBlogPostSummary'];
24
+ /** Detail shape — `html` appears on the single read only, never on summaries. */
25
+ type PublicBlogPost = Schemas['PublicBlogPost'];
26
+ /** Previous (older) + next (newer) posts for the detail prev/next nav. */
27
+ type PublicBlogAdjacentPosts = Schemas['PublicBlogAdjacentPosts'];
28
+ type BlogPostsListQuery = {
29
+ cursor?: string;
30
+ /** 1–100. */
31
+ limit?: number;
32
+ tagSlug?: string;
33
+ authorSlug?: string;
34
+ /** Opt-in only: pass `'true'` to restrict to featured posts. */
35
+ featured?: 'true';
36
+ };
37
+ type BlogSimilarQuery = {
38
+ /** 1–20; default 6. */
39
+ limit?: number;
40
+ };
41
+ type BlogSearchBody = Schemas['PublicBlogSearchBody'];
42
+
43
+ type PublicCompany = Schemas['CompanyPublic'];
44
+ /** A market (sector) a company operates in — name + its source slug. */
45
+ type CompanyMarketRef = Schemas['CompanyMarketRef'];
46
+ /** The company DETAIL shape — `PublicCompany` plus `markets` (detail-only). */
47
+ type PublicCompanyDetail = Schemas['CompanyPublicDetail'];
48
+ /**
49
+ * A company's salary overview (ADR-0046): overall pay, by-seniority rows vs the
50
+ * board baseline, top competitors, top locations, and a per-category summary.
51
+ * Names are board-language localized; the company slug/name are not.
52
+ */
53
+ type CompanySalary = Schemas['CompanySalary'];
54
+ /**
55
+ * A company's salary for one job category: the category's source + board-language
56
+ * canonical slug, by-seniority vs the board-category baseline, and competitors in
57
+ * the category. The category name is localized; the company name is not.
58
+ */
59
+ type CompanyCategorySalary = Schemas['CompanyCategorySalary'];
60
+ /** The companies browse list — `PublicCompany`s + `market` `relatedSearches`. */
61
+ interface CompanyListEnvelope extends ListEnvelope<PublicCompany> {
62
+ relatedSearches?: RelatedSearch[];
63
+ }
64
+ type CompaniesListQuery = {
65
+ cursor?: string;
66
+ /** Scope to a single market (sector) by slug. Unknown slugs 404. */
67
+ marketSlug?: string;
68
+ /** 1–100. */
69
+ limit?: number;
70
+ /**
71
+ * Storefront page offset (companies to skip); takes precedence over
72
+ * `cursor`. Pair with the response `count` to page in parallel.
73
+ */
74
+ offset?: number;
75
+ };
76
+ type CompanyJobsListQuery = {
77
+ cursor?: string;
78
+ /** 1–100. */
79
+ limit?: number;
80
+ };
81
+ type CompanySimilarQuery = {
82
+ /** 1–20, default 6. */
83
+ limit?: number;
84
+ };
85
+ type CompanyMarket = Schemas['CompanyMarket'];
86
+ type CompanyMarketsListQuery = {
87
+ /** 1–200, default 100 (a top-by-company-count preview). */
88
+ limit?: number;
89
+ search?: string;
90
+ };
91
+ type CompaniesSearchBody = Schemas['PublicCompaniesSearchBody'];
92
+
93
+ /** A job title's salary breakdown (overall + by-seniority + top rails). */
94
+ type TitleSalaryDetail = Schemas['TitleSalaryDetail'];
95
+ /** A skill's salary breakdown. */
96
+ type SkillSalaryDetail = Schemas['SkillSalaryDetail'];
97
+ /** A place's salary breakdown (city overall + siblings, or area child cities). */
98
+ type LocationSalaryDetail = Schemas['LocationSalaryDetail'];
99
+ /** A company on the `/salaries/companies` hub (ranked by sample size). */
100
+ type SalaryCompany = Schemas['SalaryCompanyIndexItem'];
101
+ /** A job title on the `/salaries/titles` index. */
102
+ type SalaryTitle = Schemas['SalaryTitleIndexItem'];
103
+ /** A skill on the `/salaries/skills` index. */
104
+ type SalarySkill = Schemas['SalarySkillIndexItem'];
105
+ /**
106
+ * A place on the `/salaries/locations` index — a flattened tree node carrying
107
+ * its `parentSlug` (the consumer rebuilds the country → region → city browse).
108
+ */
109
+ type SalaryLocation = Schemas['SalaryLocationIndexItem'];
110
+ /** A title's salary across locations (flattened `parentSlug` tree). */
111
+ type TitleLocationsIndex = Schemas['TitleLocationsIndex'];
112
+ /** A skill's salary across locations. */
113
+ type SkillLocationsIndex = Schemas['SkillLocationsIndex'];
114
+ /** A place's salary by title (suffix read-model). */
115
+ type LocationTitlesIndex = Schemas['LocationTitlesIndex'];
116
+ /** A place's salary by skill. */
117
+ type LocationSkillsIndex = Schemas['LocationSkillsIndex'];
118
+ /** A title's salary in one place (4 source + canonical slugs). */
119
+ type TitleLocationSalary = Schemas['TitleLocationSalary'];
120
+ /** A skill's salary in one place. */
121
+ type SkillLocationSalary = Schemas['SkillLocationSalary'];
122
+ /**
123
+ * Board-language overlay for a salary read. `en` (the default) is the identity
124
+ * fast-path; a non-`en` locale overlays board-language names + canonical slugs.
125
+ */
126
+ type SalaryDetailQuery = {
127
+ locale?: string;
128
+ };
129
+
130
+ export type { PublicBoardTheme as A, BlogAuthorEmbed as B, CompanyCategorySalary as C, PublicCompany as D, PublicCompanyDetail as E, SalaryCompany as F, SalaryLocation as G, SalarySkill as H, SalaryTitle as I, SkillLocationSalary as J, SkillLocationsIndex as K, LocationSalaryDetail as L, TitleLocationSalary as M, TitleLocationsIndex as N, PublicBoard as P, SkillSalaryDetail as S, TitleSalaryDetail as T, PublicBlogPostSummary as a, CompanySalary as b, CompaniesListQuery as c, CompanyListEnvelope as d, CompaniesSearchBody as e, CompanyJobsListQuery as f, CompanySimilarQuery as g, CompanyMarketsListQuery as h, SalaryDetailQuery as i, BlogPostsListQuery as j, BlogSimilarQuery as k, BlogSearchBody as l, BlogTagEmbed as m, CompanyMarket as n, CompanyMarketRef as o, CustomFieldDefinition as p, CustomFieldOption as q, CustomFieldType as r, LocationSkillsIndex as s, LocationTitlesIndex as t, PublicBlogAdjacentPosts as u, PublicBlogAuthor as v, PublicBlogPost as w, PublicBlogTag as x, PublicBoardAnalytics as y, PublicBoardFeatures as z };