@cavuno/board 4.27.0 → 4.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/CHANGELOG.md +45 -0
- package/dist/{_spec-B_pBNVUd.d.mts → _spec-DQvmsp5o.d.mts} +102 -20
- package/dist/{_spec-B_pBNVUd.d.ts → _spec-DQvmsp5o.d.ts} +102 -20
- package/dist/{blog-DzGRUsj5.d.ts → blog-CUkvhn3c.d.ts} +1 -1
- package/dist/{blog-fhXRik6k.d.mts → blog-CvuObn9O.d.mts} +1 -1
- package/dist/{board-fVAXZ8T5.d.ts → board-CCG1pO6r.d.ts} +2 -2
- package/dist/{board-DEiEHcpe.d.mts → board-D6xOidUX.d.mts} +2 -2
- package/dist/{breadcrumbs-qE3CD--N.d.mts → breadcrumbs-BBvJ5gq-.d.mts} +2 -2
- package/dist/{breadcrumbs-DNaaP3xa.d.ts → breadcrumbs-D2Cwrju4.d.ts} +2 -2
- package/dist/browser/cavuno-board.global.min.js +1 -1
- package/dist/{chunk-DUTQOLOF.mjs → chunk-EHSB2VAJ.mjs} +4 -0
- package/dist/filters.d.mts +2 -2
- package/dist/filters.d.ts +2 -2
- package/dist/format.d.mts +4 -4
- package/dist/format.d.ts +4 -4
- package/dist/index.d.mts +91 -14
- package/dist/index.d.ts +91 -14
- package/dist/index.js +44 -4
- package/dist/index.mjs +41 -5
- package/dist/{jobs-R-h3A3kl.d.mts → jobs-CEIuahbz.d.ts} +9 -7
- package/dist/{jobs-BRysn2m0.d.ts → jobs-DjMcghv6.d.mts} +9 -7
- package/dist/{search-BlB690ma.d.mts → search-C0LiPXVb.d.mts} +1 -1
- package/dist/{search-BK_zHHNQ.d.ts → search-D-EjtZH3.d.ts} +1 -1
- package/dist/{seo-C7gMl6Y7.d.ts → seo-CjNGqZZH.d.ts} +1 -1
- package/dist/{seo-0mbZ7M_E.d.mts → seo-DCQp8V1c.d.mts} +1 -1
- package/dist/seo-files.d.mts +2 -2
- package/dist/seo-files.d.ts +2 -2
- package/dist/seo.d.mts +6 -6
- package/dist/seo.d.ts +6 -6
- package/dist/server.d.mts +6 -6
- package/dist/server.d.ts +6 -6
- package/dist/server.mjs +1 -1
- package/dist/sitemap.d.mts +6 -6
- package/dist/sitemap.d.ts +6 -6
- package/dist/sitemap.mjs +1 -1
- package/dist/suggest.d.mts +2 -2
- package/dist/suggest.d.ts +2 -2
- package/package.json +1 -1
- package/skills/cavuno-board-account/SKILL.md +27 -0
- package/skills/cavuno-board-errors/SKILL.md +1 -1
- package/skills/cavuno-board-filters/SKILL.md +90 -1
- package/skills/cavuno-board-format/SKILL.md +52 -0
- package/skills/cavuno-board-post-a-job/SKILL.md +24 -0
- package/skills/cavuno-board-salaries/SKILL.md +7 -0
- package/skills/manifest.json +2 -2
package/dist/index.js
CHANGED
|
@@ -89,6 +89,9 @@ var BOARD_API_ERROR_CODES = [
|
|
|
89
89
|
"categories_not_found",
|
|
90
90
|
"skills_not_found",
|
|
91
91
|
"places_not_found",
|
|
92
|
+
// Location search + `locationId` on job office locations
|
|
93
|
+
"locations_invalid_id",
|
|
94
|
+
"locations_unavailable",
|
|
92
95
|
// Companies (public reads)
|
|
93
96
|
"companies_not_found",
|
|
94
97
|
"company_markets_not_found",
|
|
@@ -120,6 +123,7 @@ var BOARD_API_ERROR_CODES = [
|
|
|
120
123
|
"candidate_handle_taken",
|
|
121
124
|
"candidate_job_not_found",
|
|
122
125
|
"candidate_notification_preference_paused",
|
|
126
|
+
"candidate_profile_required",
|
|
123
127
|
"resume_invalid_file",
|
|
124
128
|
"resume_upload_forbidden",
|
|
125
129
|
// Applications
|
|
@@ -359,7 +363,7 @@ async function clearSession(storage) {
|
|
|
359
363
|
}
|
|
360
364
|
|
|
361
365
|
// src/version.ts
|
|
362
|
-
var SDK_VERSION = "4.
|
|
366
|
+
var SDK_VERSION = "4.28.0";
|
|
363
367
|
|
|
364
368
|
// src/client.ts
|
|
365
369
|
function isRawBody(body) {
|
|
@@ -1234,6 +1238,37 @@ function jobsNamespace(client) {
|
|
|
1234
1238
|
};
|
|
1235
1239
|
}
|
|
1236
1240
|
|
|
1241
|
+
// src/namespaces/locations.ts
|
|
1242
|
+
function locationsNamespace(client) {
|
|
1243
|
+
return {
|
|
1244
|
+
/**
|
|
1245
|
+
* GET /locations/search — worldwide autocomplete over countries,
|
|
1246
|
+
* regions, cities, and localities, not only places the board's jobs already
|
|
1247
|
+
* use (that is `taxonomy.places.list({ q })`). Order is the contract: do
|
|
1248
|
+
* not re-sort. Complete a pick with `locations.resolve` using the same
|
|
1249
|
+
* session before sending its `id` as `locationId` later.
|
|
1250
|
+
*
|
|
1251
|
+
* @example
|
|
1252
|
+
* const session = crypto.randomUUID();
|
|
1253
|
+
* const { data } = await board.locations.search({ q: 'berl', session });
|
|
1254
|
+
*/
|
|
1255
|
+
search(query, options) {
|
|
1256
|
+
return client.fetch("/locations/search", {
|
|
1257
|
+
...options,
|
|
1258
|
+
query
|
|
1259
|
+
});
|
|
1260
|
+
},
|
|
1261
|
+
/** Complete a picked suggestion with the same search session. */
|
|
1262
|
+
resolve(input, options) {
|
|
1263
|
+
return client.fetch("/locations/resolve", {
|
|
1264
|
+
...options,
|
|
1265
|
+
method: "POST",
|
|
1266
|
+
body: input
|
|
1267
|
+
});
|
|
1268
|
+
}
|
|
1269
|
+
};
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1237
1272
|
// src/namespaces/me.ts
|
|
1238
1273
|
function meNamespace(client) {
|
|
1239
1274
|
return {
|
|
@@ -1995,15 +2030,19 @@ function meNamespace(client) {
|
|
|
1995
2030
|
/**
|
|
1996
2031
|
* Pay for / publish a held draft. Select billing: a paid plan
|
|
1997
2032
|
* returns `{ status: 'checkout', checkoutUrl }` (send the buyer there;
|
|
1998
|
-
* the webhook publishes on payment); a free
|
|
1999
|
-
*
|
|
2000
|
-
*
|
|
2033
|
+
* the webhook publishes on payment); a free plan publishes immediately
|
|
2034
|
+
* (`status: 'published'`) unless the board requires free-job approval
|
|
2035
|
+
* (`status: 'pending_approval'`); bundle, subscription, and member-credit
|
|
2036
|
+
* posts always publish immediately; an invoice plan emails a Stripe
|
|
2037
|
+
* invoice (`status: 'invoice_sent'`) or holds an on-issue post for
|
|
2038
|
+
* approval.
|
|
2001
2039
|
*
|
|
2002
2040
|
* @example
|
|
2003
2041
|
* const r = await board.me.companies.jobs.checkout('acme', jobId, {
|
|
2004
2042
|
* billing: { type: 'new', planId },
|
|
2005
2043
|
* });
|
|
2006
2044
|
* if (r.status === 'checkout') location.href = r.checkoutUrl!;
|
|
2045
|
+
* if (r.status === 'pending_approval') showAwaitingReview(r.jobId);
|
|
2007
2046
|
*/
|
|
2008
2047
|
checkout(slug, id, body, options) {
|
|
2009
2048
|
return client.fetch(
|
|
@@ -3665,6 +3704,7 @@ function createBoardClient(options) {
|
|
|
3665
3704
|
password: passwordNamespace(client),
|
|
3666
3705
|
taxonomy: taxonomyNamespace(client),
|
|
3667
3706
|
search: searchNamespace(client),
|
|
3707
|
+
locations: locationsNamespace(client),
|
|
3668
3708
|
redirects: redirectsNamespace(client),
|
|
3669
3709
|
jobAlerts: jobAlertsNamespace(client),
|
|
3670
3710
|
jobPosting: jobPostingNamespace(client),
|
package/dist/index.mjs
CHANGED
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
isRateLimited,
|
|
22
22
|
isUnauthorized,
|
|
23
23
|
isValidationError
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-EHSB2VAJ.mjs";
|
|
25
25
|
|
|
26
26
|
// src/query.ts
|
|
27
27
|
function toSearchParams(query) {
|
|
@@ -42,7 +42,7 @@ function toSearchParams(query) {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
// src/version.ts
|
|
45
|
-
var SDK_VERSION = "4.
|
|
45
|
+
var SDK_VERSION = "4.28.0";
|
|
46
46
|
|
|
47
47
|
// src/client.ts
|
|
48
48
|
function isRawBody(body) {
|
|
@@ -917,6 +917,37 @@ function jobsNamespace(client) {
|
|
|
917
917
|
};
|
|
918
918
|
}
|
|
919
919
|
|
|
920
|
+
// src/namespaces/locations.ts
|
|
921
|
+
function locationsNamespace(client) {
|
|
922
|
+
return {
|
|
923
|
+
/**
|
|
924
|
+
* GET /locations/search — worldwide autocomplete over countries,
|
|
925
|
+
* regions, cities, and localities, not only places the board's jobs already
|
|
926
|
+
* use (that is `taxonomy.places.list({ q })`). Order is the contract: do
|
|
927
|
+
* not re-sort. Complete a pick with `locations.resolve` using the same
|
|
928
|
+
* session before sending its `id` as `locationId` later.
|
|
929
|
+
*
|
|
930
|
+
* @example
|
|
931
|
+
* const session = crypto.randomUUID();
|
|
932
|
+
* const { data } = await board.locations.search({ q: 'berl', session });
|
|
933
|
+
*/
|
|
934
|
+
search(query, options) {
|
|
935
|
+
return client.fetch("/locations/search", {
|
|
936
|
+
...options,
|
|
937
|
+
query
|
|
938
|
+
});
|
|
939
|
+
},
|
|
940
|
+
/** Complete a picked suggestion with the same search session. */
|
|
941
|
+
resolve(input, options) {
|
|
942
|
+
return client.fetch("/locations/resolve", {
|
|
943
|
+
...options,
|
|
944
|
+
method: "POST",
|
|
945
|
+
body: input
|
|
946
|
+
});
|
|
947
|
+
}
|
|
948
|
+
};
|
|
949
|
+
}
|
|
950
|
+
|
|
920
951
|
// src/namespaces/me.ts
|
|
921
952
|
function meNamespace(client) {
|
|
922
953
|
return {
|
|
@@ -1678,15 +1709,19 @@ function meNamespace(client) {
|
|
|
1678
1709
|
/**
|
|
1679
1710
|
* Pay for / publish a held draft. Select billing: a paid plan
|
|
1680
1711
|
* returns `{ status: 'checkout', checkoutUrl }` (send the buyer there;
|
|
1681
|
-
* the webhook publishes on payment); a free
|
|
1682
|
-
*
|
|
1683
|
-
*
|
|
1712
|
+
* the webhook publishes on payment); a free plan publishes immediately
|
|
1713
|
+
* (`status: 'published'`) unless the board requires free-job approval
|
|
1714
|
+
* (`status: 'pending_approval'`); bundle, subscription, and member-credit
|
|
1715
|
+
* posts always publish immediately; an invoice plan emails a Stripe
|
|
1716
|
+
* invoice (`status: 'invoice_sent'`) or holds an on-issue post for
|
|
1717
|
+
* approval.
|
|
1684
1718
|
*
|
|
1685
1719
|
* @example
|
|
1686
1720
|
* const r = await board.me.companies.jobs.checkout('acme', jobId, {
|
|
1687
1721
|
* billing: { type: 'new', planId },
|
|
1688
1722
|
* });
|
|
1689
1723
|
* if (r.status === 'checkout') location.href = r.checkoutUrl!;
|
|
1724
|
+
* if (r.status === 'pending_approval') showAwaitingReview(r.jobId);
|
|
1690
1725
|
*/
|
|
1691
1726
|
checkout(slug, id, body, options) {
|
|
1692
1727
|
return client.fetch(
|
|
@@ -3318,6 +3353,7 @@ function createBoardClient(options) {
|
|
|
3318
3353
|
password: passwordNamespace(client),
|
|
3319
3354
|
taxonomy: taxonomyNamespace(client),
|
|
3320
3355
|
search: searchNamespace(client),
|
|
3356
|
+
locations: locationsNamespace(client),
|
|
3321
3357
|
redirects: redirectsNamespace(client),
|
|
3322
3358
|
jobAlerts: jobAlertsNamespace(client),
|
|
3323
3359
|
jobPosting: jobPostingNamespace(client),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as Schemas } from './_spec-
|
|
1
|
+
import { S as Schemas } from './_spec-DQvmsp5o.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Optional pagination metadata returned by Board API list operations.
|
|
@@ -119,11 +119,13 @@ type ObjectReferenceFilter = {
|
|
|
119
119
|
key: string;
|
|
120
120
|
recordIds: string[];
|
|
121
121
|
};
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
122
|
+
/**
|
|
123
|
+
* The `jobs.search` body, aliased from the spec like the response types.
|
|
124
|
+
* `filters.customFields` matches the job's own custom fields and
|
|
125
|
+
* `filters.companyCustomFields` the public profile fields of the job's
|
|
126
|
+
* company; both take {@link CustomFieldFilter} clauses (the tests pin that
|
|
127
|
+
* the spec shape and `CustomFieldFilter` stay identical).
|
|
128
|
+
*/
|
|
129
|
+
type JobsSearchBody = Schemas['PublicSearchJobsBody'];
|
|
128
130
|
|
|
129
131
|
export type { CustomFieldValues as C, EmploymentType as E, JobSort as J, ListEnvelope as L, ObjectReferenceFilter as O, PublicJob as P, RemoteOption as R, Seniority as S, CustomFieldFilter as a, JobCollectionChoiceQuery as b, JobsListQuery as c, JobCardListEnvelope as d, JobsSearchBody as e, JobCardSearchEnvelope as f, JobsSimilarQuery as g, SearchEnvelope as h, CustomFieldValue as i, CustomFilterValue as j, EducationRequirement as k, JobCatalogPagination as l, JobCollectionChoiceList as m, JobCollectionFieldDefinition as n, JobCompany as o, OfficeLocation as p, OffsetPagination as q, PublicJobCard as r, RelatedSearch as s, RemotePermit as t, RemoteTimezone as u, ResolvedJobCollectionField as v, StorefrontPagination as w };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as Schemas } from './_spec-
|
|
1
|
+
import { S as Schemas } from './_spec-DQvmsp5o.mjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Optional pagination metadata returned by Board API list operations.
|
|
@@ -119,11 +119,13 @@ type ObjectReferenceFilter = {
|
|
|
119
119
|
key: string;
|
|
120
120
|
recordIds: string[];
|
|
121
121
|
};
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
122
|
+
/**
|
|
123
|
+
* The `jobs.search` body, aliased from the spec like the response types.
|
|
124
|
+
* `filters.customFields` matches the job's own custom fields and
|
|
125
|
+
* `filters.companyCustomFields` the public profile fields of the job's
|
|
126
|
+
* company; both take {@link CustomFieldFilter} clauses (the tests pin that
|
|
127
|
+
* the spec shape and `CustomFieldFilter` stay identical).
|
|
128
|
+
*/
|
|
129
|
+
type JobsSearchBody = Schemas['PublicSearchJobsBody'];
|
|
128
130
|
|
|
129
131
|
export type { CustomFieldValues as C, EmploymentType as E, JobSort as J, ListEnvelope as L, ObjectReferenceFilter as O, PublicJob as P, RemoteOption as R, Seniority as S, CustomFieldFilter as a, JobCollectionChoiceQuery as b, JobsListQuery as c, JobCardListEnvelope as d, JobsSearchBody as e, JobCardSearchEnvelope as f, JobsSimilarQuery as g, SearchEnvelope as h, CustomFieldValue as i, CustomFilterValue as j, EducationRequirement as k, JobCatalogPagination as l, JobCollectionChoiceList as m, JobCollectionFieldDefinition as n, JobCompany as o, OfficeLocation as p, OffsetPagination as q, PublicJobCard as r, RelatedSearch as s, RemotePermit as t, RemoteTimezone as u, ResolvedJobCollectionField as v, StorefrontPagination as w };
|
package/dist/seo-files.d.mts
CHANGED
package/dist/seo-files.d.ts
CHANGED
package/dist/seo.d.mts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { P as PublicBlogPostSummary, B as BlogAuthorEmbed } from './blog-
|
|
2
|
-
import { e as JsonLdObject } from './breadcrumbs-
|
|
3
|
-
export { A as ALL_COUNTRY_CODES, B as BreadcrumbItemInput, g as FaqItem, J as JobBreadcrumb, h as JsonLdBoard, N as NumberNotation, i as SENIORITY_ORDER, j as SalaryFaqEntry, k as SalaryJsonLdOptions, l as SalaryOccupationListOptions, b as buildJobBreadcrumbs, m as buildSalaryFaq, o as companyCategorySalaryJsonLd, p as companySalaryJsonLd, q as createBreadcrumbJsonLd, r as createJobPostingJsonLd, s as crossAxisSalaryJsonLd, t as faqJsonLd, c as formatSalaryStat, d as formatSalaryStatRange, u as itemListJsonLd, v as locationSalaryJsonLd, n as normalizeWebsiteUrl, w as skillSalaryJsonLd, x as sortBySeniority, y as titleSalaryJsonLd } from './breadcrumbs-
|
|
4
|
-
import './_spec-
|
|
5
|
-
import './board-
|
|
6
|
-
import './jobs-
|
|
1
|
+
import { P as PublicBlogPostSummary, B as BlogAuthorEmbed } from './blog-CvuObn9O.mjs';
|
|
2
|
+
import { e as JsonLdObject } from './breadcrumbs-BBvJ5gq-.mjs';
|
|
3
|
+
export { A as ALL_COUNTRY_CODES, B as BreadcrumbItemInput, g as FaqItem, J as JobBreadcrumb, h as JsonLdBoard, N as NumberNotation, i as SENIORITY_ORDER, j as SalaryFaqEntry, k as SalaryJsonLdOptions, l as SalaryOccupationListOptions, b as buildJobBreadcrumbs, m as buildSalaryFaq, o as companyCategorySalaryJsonLd, p as companySalaryJsonLd, q as createBreadcrumbJsonLd, r as createJobPostingJsonLd, s as crossAxisSalaryJsonLd, t as faqJsonLd, c as formatSalaryStat, d as formatSalaryStatRange, u as itemListJsonLd, v as locationSalaryJsonLd, n as normalizeWebsiteUrl, w as skillSalaryJsonLd, x as sortBySeniority, y as titleSalaryJsonLd } from './breadcrumbs-BBvJ5gq-.mjs';
|
|
4
|
+
import './_spec-DQvmsp5o.mjs';
|
|
5
|
+
import './board-D6xOidUX.mjs';
|
|
6
|
+
import './jobs-DjMcghv6.mjs';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Blog structured data on the `@cavuno/board` wire types, transcribed from
|
package/dist/seo.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { P as PublicBlogPostSummary, B as BlogAuthorEmbed } from './blog-
|
|
2
|
-
import { e as JsonLdObject } from './breadcrumbs-
|
|
3
|
-
export { A as ALL_COUNTRY_CODES, B as BreadcrumbItemInput, g as FaqItem, J as JobBreadcrumb, h as JsonLdBoard, N as NumberNotation, i as SENIORITY_ORDER, j as SalaryFaqEntry, k as SalaryJsonLdOptions, l as SalaryOccupationListOptions, b as buildJobBreadcrumbs, m as buildSalaryFaq, o as companyCategorySalaryJsonLd, p as companySalaryJsonLd, q as createBreadcrumbJsonLd, r as createJobPostingJsonLd, s as crossAxisSalaryJsonLd, t as faqJsonLd, c as formatSalaryStat, d as formatSalaryStatRange, u as itemListJsonLd, v as locationSalaryJsonLd, n as normalizeWebsiteUrl, w as skillSalaryJsonLd, x as sortBySeniority, y as titleSalaryJsonLd } from './breadcrumbs-
|
|
4
|
-
import './_spec-
|
|
5
|
-
import './board-
|
|
6
|
-
import './jobs-
|
|
1
|
+
import { P as PublicBlogPostSummary, B as BlogAuthorEmbed } from './blog-CUkvhn3c.js';
|
|
2
|
+
import { e as JsonLdObject } from './breadcrumbs-D2Cwrju4.js';
|
|
3
|
+
export { A as ALL_COUNTRY_CODES, B as BreadcrumbItemInput, g as FaqItem, J as JobBreadcrumb, h as JsonLdBoard, N as NumberNotation, i as SENIORITY_ORDER, j as SalaryFaqEntry, k as SalaryJsonLdOptions, l as SalaryOccupationListOptions, b as buildJobBreadcrumbs, m as buildSalaryFaq, o as companyCategorySalaryJsonLd, p as companySalaryJsonLd, q as createBreadcrumbJsonLd, r as createJobPostingJsonLd, s as crossAxisSalaryJsonLd, t as faqJsonLd, c as formatSalaryStat, d as formatSalaryStatRange, u as itemListJsonLd, v as locationSalaryJsonLd, n as normalizeWebsiteUrl, w as skillSalaryJsonLd, x as sortBySeniority, y as titleSalaryJsonLd } from './breadcrumbs-D2Cwrju4.js';
|
|
4
|
+
import './_spec-DQvmsp5o.js';
|
|
5
|
+
import './board-CCG1pO6r.js';
|
|
6
|
+
import './jobs-CEIuahbz.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Blog structured data on the `@cavuno/board` wire types, transcribed from
|
package/dist/server.d.mts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { BoardSdk } from './index.mjs';
|
|
2
|
-
import './_spec-
|
|
3
|
-
import './search-
|
|
4
|
-
import './board-
|
|
5
|
-
import './jobs-
|
|
6
|
-
import './seo-
|
|
7
|
-
import './blog-
|
|
2
|
+
import './_spec-DQvmsp5o.mjs';
|
|
3
|
+
import './search-C0LiPXVb.mjs';
|
|
4
|
+
import './board-D6xOidUX.mjs';
|
|
5
|
+
import './jobs-DjMcghv6.mjs';
|
|
6
|
+
import './seo-DCQp8V1c.mjs';
|
|
7
|
+
import './blog-CvuObn9O.mjs';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Session cookie codec — pure (no framework imports, no node imports) so it
|
package/dist/server.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { BoardSdk } from './index.js';
|
|
2
|
-
import './_spec-
|
|
3
|
-
import './search-
|
|
4
|
-
import './board-
|
|
5
|
-
import './jobs-
|
|
6
|
-
import './seo-
|
|
7
|
-
import './blog-
|
|
2
|
+
import './_spec-DQvmsp5o.js';
|
|
3
|
+
import './search-D-EjtZH3.js';
|
|
4
|
+
import './board-CCG1pO6r.js';
|
|
5
|
+
import './jobs-CEIuahbz.js';
|
|
6
|
+
import './seo-CjNGqZZH.js';
|
|
7
|
+
import './blog-CUkvhn3c.js';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Session cookie codec — pure (no framework imports, no node imports) so it
|
package/dist/server.mjs
CHANGED
package/dist/sitemap.d.mts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { BoardSdk } from './index.mjs';
|
|
2
|
-
import './_spec-
|
|
3
|
-
import './search-
|
|
4
|
-
import './board-
|
|
5
|
-
import './jobs-
|
|
6
|
-
import './seo-
|
|
7
|
-
import './blog-
|
|
2
|
+
import './_spec-DQvmsp5o.mjs';
|
|
3
|
+
import './search-C0LiPXVb.mjs';
|
|
4
|
+
import './board-D6xOidUX.mjs';
|
|
5
|
+
import './jobs-DjMcghv6.mjs';
|
|
6
|
+
import './seo-DCQp8V1c.mjs';
|
|
7
|
+
import './blog-CvuObn9O.mjs';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Sitemap primitives — the pure XML + bucket-filename logic behind a board
|
package/dist/sitemap.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { BoardSdk } from './index.js';
|
|
2
|
-
import './_spec-
|
|
3
|
-
import './search-
|
|
4
|
-
import './board-
|
|
5
|
-
import './jobs-
|
|
6
|
-
import './seo-
|
|
7
|
-
import './blog-
|
|
2
|
+
import './_spec-DQvmsp5o.js';
|
|
3
|
+
import './search-D-EjtZH3.js';
|
|
4
|
+
import './board-CCG1pO6r.js';
|
|
5
|
+
import './jobs-CEIuahbz.js';
|
|
6
|
+
import './seo-CjNGqZZH.js';
|
|
7
|
+
import './blog-CUkvhn3c.js';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Sitemap primitives — the pure XML + bucket-filename logic behind a board
|
package/dist/sitemap.mjs
CHANGED
package/dist/suggest.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { h as SuggestionItem, b as SearchSuggestQuery, F as FetchOptions, g as SuggestResult } from './search-
|
|
2
|
-
import './_spec-
|
|
1
|
+
import { h as SuggestionItem, b as SearchSuggestQuery, F as FetchOptions, g as SuggestResult } from './search-C0LiPXVb.mjs';
|
|
2
|
+
import './_spec-DQvmsp5o.mjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* `@cavuno/board/suggest` — framework-agnostic headless search-suggest
|
package/dist/suggest.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { h as SuggestionItem, b as SearchSuggestQuery, F as FetchOptions, g as SuggestResult } from './search-
|
|
2
|
-
import './_spec-
|
|
1
|
+
import { h as SuggestionItem, b as SearchSuggestQuery, F as FetchOptions, g as SuggestResult } from './search-D-EjtZH3.js';
|
|
2
|
+
import './_spec-DQvmsp5o.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* `@cavuno/board/suggest` — framework-agnostic headless search-suggest
|
package/package.json
CHANGED
|
@@ -11,6 +11,31 @@ Anonymous methods here are token-based email unsubscribe and email-change confir
|
|
|
11
11
|
|
|
12
12
|
The host application owns forms, file pickers, and cookie plumbing; this SDK surface supplies data operations.
|
|
13
13
|
|
|
14
|
+
## Candidate screens are candidate-only
|
|
15
|
+
|
|
16
|
+
A board user is either a candidate or an employer (`me.role`). Only candidates have a candidate profile. Render candidate screens and fields (the profile form, profile completeness, resume upload, experience, education, skills, and languages) only when `me.role === 'candidate'`. On the account page, give an employer account the employer profile view instead: avatar, `displayName` (the one profile field every account can update), and a link to the employer screens (`board.me.companies.*`). Never show them the empty candidate form.
|
|
17
|
+
|
|
18
|
+
The API is the backstop: a profile write from an account with no candidate profile returns 403 `candidate_profile_required` before anything is saved. `displayName` alone is the one profile field every account can update. Surface this error as a message; never swallow it and report "Saved".
|
|
19
|
+
|
|
20
|
+
```ts snippet
|
|
21
|
+
import { isBoardApiError } from '@cavuno/board';
|
|
22
|
+
|
|
23
|
+
const me = await board.me.retrieve();
|
|
24
|
+
if (me.role !== 'candidate') {
|
|
25
|
+
return renderEmployerProfile(me); // avatar, displayName, link to employer screens
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
await board.me.profile.update({ headline: 'Staff Engineer' });
|
|
30
|
+
showSaved();
|
|
31
|
+
} catch (error) {
|
|
32
|
+
if (isBoardApiError(error) && error.code === 'candidate_profile_required') {
|
|
33
|
+
return showError('Only candidate accounts have a candidate profile.');
|
|
34
|
+
}
|
|
35
|
+
throw error;
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
14
39
|
## Account and profile
|
|
15
40
|
|
|
16
41
|
Account deletion is a synchronous, irreversible cascade over the profile, collections, saved jobs, alerts, avatar, and resume. Obtain explicit confirmation before calling it.
|
|
@@ -252,6 +277,8 @@ await board.me.notificationPreferences.unsubscribeWithToken({
|
|
|
252
277
|
|
|
253
278
|
## Completion gate
|
|
254
279
|
|
|
280
|
+
- Candidate screens render only for `me.role === 'candidate'`; an employer account gets the employer profile view (avatar, `displayName`, link to employer screens).
|
|
281
|
+
- A `candidate_profile_required` 403 shows an error and never a "Saved" state.
|
|
255
282
|
- The profile form follows `forms.talent`: order matches, hidden fields are absent, and required fields block save while empty.
|
|
256
283
|
- Profile update is visible after retrieval.
|
|
257
284
|
- Scalar field updates preserve omitted values; collection selection updates preserve every selection the user meant to keep.
|
|
@@ -44,7 +44,7 @@ try {
|
|
|
44
44
|
}
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
The remaining status guards are `isForbidden` for 403 and `isConflict` for 409. Record `code` and `requestId` in support diagnostics. Because v1 may add error codes, unmatched `BoardApiError` instances still need a safe generic state.
|
|
47
|
+
The remaining status guards are `isForbidden` for 403 and `isConflict` for 409. A 403 `candidate_profile_required` means an account that is not a candidate (for example an employer) tried to write candidate profile data: gate candidate screens on `me.role === 'candidate'` and show the error rather than a success state. Record `code` and `requestId` in support diagnostics. Because v1 may add error codes, unmatched `BoardApiError` instances still need a safe generic state.
|
|
48
48
|
|
|
49
49
|
**Complete when:** every expected failure has one typed branch, an invalid resource renders not-found, and unmatched failures retain their original error.
|
|
50
50
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: cavuno-board-filters
|
|
3
|
-
description: Listing-filter contracts with @cavuno/board. Use for job filter controls, profile-field filters, collection choices, sort controls, listing URL validation, or taxonomy-backed filter options.
|
|
3
|
+
description: Listing-filter contracts with @cavuno/board. Use for job filter controls, job and company custom-field filters, profile-field filters, collection choices, sort controls, listing URL validation, or taxonomy-backed filter options.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Listing filters
|
|
@@ -150,6 +150,60 @@ const { items } = await board.search.suggest({
|
|
|
150
150
|
The host router owns URL serialization and saved-filter persistence.
|
|
151
151
|
Locations come from `board.taxonomy.places` rather than a static filter export.
|
|
152
152
|
|
|
153
|
+
## Filter jobs by a job custom field
|
|
154
|
+
|
|
155
|
+
The operator's job custom fields arrive as definitions on
|
|
156
|
+
`board.context().customFields.job`. Expose a field as a filter only when the
|
|
157
|
+
operator intends it as one: keep an explicit list of filter keys in your app
|
|
158
|
+
config. Do not render a dropdown for every select field automatically; most
|
|
159
|
+
custom fields are details for the job page, not listing facets.
|
|
160
|
+
|
|
161
|
+
```ts snippet
|
|
162
|
+
const context = await board.context();
|
|
163
|
+
|
|
164
|
+
// The operator picked these; everything else stays a job-page detail.
|
|
165
|
+
const FILTER_FIELD_KEYS = ['work_type'];
|
|
166
|
+
const filterFields = context.customFields.job.filter(
|
|
167
|
+
(field) =>
|
|
168
|
+
FILTER_FIELD_KEYS.includes(field.key) &&
|
|
169
|
+
(field.type === 'single_select' || field.type === 'multi_select'));
|
|
170
|
+
|
|
171
|
+
// Controls: option KEYS are the values, option labels are the text.
|
|
172
|
+
const controls = filterFields.map((field) => ({
|
|
173
|
+
key: field.key,
|
|
174
|
+
label: field.label,
|
|
175
|
+
options: (field.options ?? []).map((option) => ({
|
|
176
|
+
value: option.key,
|
|
177
|
+
label: option.label,
|
|
178
|
+
})),
|
|
179
|
+
}));
|
|
180
|
+
|
|
181
|
+
// URL state holds option keys (`/jobs?work_type=contract`), never labels.
|
|
182
|
+
// Drop anything that is not a current option before it reaches the API.
|
|
183
|
+
const customFields = filterFields.flatMap((field) => {
|
|
184
|
+
const values = searchParams
|
|
185
|
+
.getAll(field.key)
|
|
186
|
+
.filter((value) => field.options?.some((option) => option.key === value));
|
|
187
|
+
return values.length > 0 ? [{ key: field.key, values }] : [];
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
const results = await board.jobs.search({
|
|
191
|
+
query: filters.q,
|
|
192
|
+
filters: {
|
|
193
|
+
seniority: filters.seniority,
|
|
194
|
+
customFields: customFields.length > 0 ? customFields : undefined,
|
|
195
|
+
},
|
|
196
|
+
limit: 20,
|
|
197
|
+
});
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Clauses are AND-matched; values inside one clause are alternatives. Each
|
|
201
|
+
request takes at most 10 clauses of 10 values. An unknown key or an option key
|
|
202
|
+
the field no longer offers returns `invalid_filter`, so validate URL input
|
|
203
|
+
against the definitions as above. Boolean and number fields filter the same way
|
|
204
|
+
with `values: [true]` or `values: [3]`. Labels change when the operator renames
|
|
205
|
+
an option; keys do not, so bookmarked URLs keep working.
|
|
206
|
+
|
|
153
207
|
## Build filters from public profile fields
|
|
154
208
|
|
|
155
209
|
`board.profileFields.retrieve('company')` and `retrieve('candidate')` return only public scalar and collection-reference definitions. Use each stored field key for filtering. For a collection reference, page or search its active public choices and submit the returned record `id`; the optional `logoUrl` is display metadata.
|
|
@@ -189,6 +243,36 @@ void talent.data;
|
|
|
189
243
|
|
|
190
244
|
Clauses are AND-matched. Values or record IDs inside one clause are alternatives. Unknown, private, invalid, or archived choices return `invalid_filter`; each array accepts at most 10 clauses and each clause at most 10 choices. Job search supports scalar `customFields` under `filters`, but job collection references are outside this surface.
|
|
191
245
|
|
|
246
|
+
## Filter jobs by job and company custom fields
|
|
247
|
+
|
|
248
|
+
`jobs.search` takes two custom-field filters. `filters.customFields` matches the job's own fields, defined in `board.context().customFields.job`. `filters.companyCustomFields` matches the public profile fields of the job's company, defined in `board.profileFields.retrieve('company')`. Both use the clause shape above; the two lists never share keys, so a job field and a company field may both be called `type`.
|
|
249
|
+
|
|
250
|
+
```ts snippet
|
|
251
|
+
const [context, companyFields] = await Promise.all([
|
|
252
|
+
board.context(),
|
|
253
|
+
board.profileFields.retrieve('company'),
|
|
254
|
+
]);
|
|
255
|
+
const opportunityType = context.customFields.job.find(
|
|
256
|
+
(field) => field.key === 'opportunity_type');
|
|
257
|
+
const employerType = companyFields.definitions.find(
|
|
258
|
+
(field) => field.key === 'employer_type');
|
|
259
|
+
|
|
260
|
+
const results = await board.jobs.search({
|
|
261
|
+
query: filters.q,
|
|
262
|
+
filters: {
|
|
263
|
+
customFields: [{ key: 'opportunity_type', values: ['identified'] }],
|
|
264
|
+
companyCustomFields: [{ key: 'employer_type', values: ['acco'] }],
|
|
265
|
+
},
|
|
266
|
+
limit: 20,
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
void opportunityType;
|
|
270
|
+
void employerType;
|
|
271
|
+
void results.data;
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Render each dropdown from the definition's `options` in order: show `label`, submit `key`, and keep the key in the URL so shared links survive a label change. Accept only keys the current definition offers; drop anything else from a hand-typed URL. Only `jobs.search` takes these filters. A company's jobs are re-indexed automatically when its values change. Worked example: [Custom field filters and badges](https://cavuno.com/docs/sdk/cookbook/custom-field-filters-and-badges).
|
|
275
|
+
|
|
192
276
|
## Completion gate
|
|
193
277
|
|
|
194
278
|
Finish only after every applicable check passes:
|
|
@@ -204,8 +288,13 @@ Finish only after every applicable check passes:
|
|
|
204
288
|
- `/jobs?category=engineering,design` sends
|
|
205
289
|
`filters.categories: ['engineering', 'design']` to `jobs.search`.
|
|
206
290
|
- Every paged taxonomy request forwards the previous opaque `nextCursor`.
|
|
291
|
+
- Job custom-field controls exist only for keys the operator chose as
|
|
292
|
+
filters, read their options from `board.context().customFields.job`, and send
|
|
293
|
+
option keys in `filters.customFields`; an unknown option in the URL never
|
|
294
|
+
reaches the API.
|
|
207
295
|
- Company and talent custom controls come from `board.profileFields`; private definitions and archived choices never become filter options.
|
|
208
296
|
- Profile-filter requests use stored scalar values and returned collection entry IDs, not display labels.
|
|
297
|
+
- Job-field dropdowns send `filters.customFields` and company-field dropdowns send `filters.companyCustomFields` to `jobs.search`, both built from the current definitions; a stale option key in the URL is dropped, not sent.
|
|
209
298
|
|
|
210
299
|
## Cavuno SDK reference
|
|
211
300
|
|