@cavuno/board 4.7.0 → 4.9.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 (47) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/dist/{_spec-B2ZrXuea.d.mts → _spec-B9Ah8dNs.d.mts} +78 -3
  3. package/dist/{_spec-B2ZrXuea.d.ts → _spec-B9Ah8dNs.d.ts} +78 -3
  4. package/dist/bin.mjs +174 -19
  5. package/dist/{blog-B125P3dS.d.mts → blog-BmqWfLZi.d.mts} +1 -1
  6. package/dist/{blog-BmEG_fhe.d.ts → blog-bh07fZ8Q.d.ts} +1 -1
  7. package/dist/{board-QTX75RxT.d.mts → board-B4jLqmxn.d.mts} +5 -3
  8. package/dist/{board-6woxZtzD.d.ts → board-De8nLbk7.d.ts} +5 -3
  9. package/dist/{breadcrumbs-BVeDYPCw.d.ts → breadcrumbs-B1HVufC7.d.ts} +2 -2
  10. package/dist/{breadcrumbs-CP42mzYb.d.mts → breadcrumbs-BVQL2dNY.d.mts} +2 -2
  11. package/dist/browser/cavuno-board.global.min.js +1 -1
  12. package/dist/{chunk-ZCEAOJ6Y.mjs → chunk-T46JASKG.mjs} +4 -0
  13. package/dist/doctor.d.mts +3 -1
  14. package/dist/doctor.d.ts +3 -1
  15. package/dist/doctor.js +169 -17
  16. package/dist/doctor.mjs +169 -17
  17. package/dist/filters.d.mts +2 -2
  18. package/dist/filters.d.ts +2 -2
  19. package/dist/format.d.mts +4 -4
  20. package/dist/format.d.ts +4 -4
  21. package/dist/index.d.mts +82 -25
  22. package/dist/index.d.ts +82 -25
  23. package/dist/index.js +48 -3
  24. package/dist/index.mjs +45 -4
  25. package/dist/{jobs-DrdhICLO.d.mts → jobs-B7q3BgIK.d.mts} +1 -1
  26. package/dist/{jobs-BH1CgV8J.d.ts → jobs-Iv6Wkvvf.d.ts} +1 -1
  27. package/dist/{search-CCsijbzU.d.ts → search-CbDZwdyl.d.ts} +1 -1
  28. package/dist/{search-B9T6rAhd.d.mts → search-DC0jatQN.d.mts} +1 -1
  29. package/dist/seo-BDFUuvXM.d.ts +12 -0
  30. package/dist/seo-HCE7aCkh.d.mts +12 -0
  31. package/dist/seo-files.d.mts +36 -0
  32. package/dist/seo-files.d.ts +36 -0
  33. package/dist/seo-files.js +102 -0
  34. package/dist/seo-files.mjs +81 -0
  35. package/dist/seo.d.mts +6 -6
  36. package/dist/seo.d.ts +6 -6
  37. package/dist/server.d.mts +6 -5
  38. package/dist/server.d.ts +6 -5
  39. package/dist/server.mjs +1 -1
  40. package/dist/sitemap.d.mts +6 -5
  41. package/dist/sitemap.d.ts +6 -5
  42. package/dist/suggest.d.mts +2 -2
  43. package/dist/suggest.d.ts +2 -2
  44. package/package.json +11 -1
  45. package/skills/cavuno-board-account/SKILL.md +6 -1
  46. package/skills/cavuno-board-filters/SKILL.md +17 -3
  47. package/skills/manifest.json +1 -1
package/dist/index.js CHANGED
@@ -104,6 +104,8 @@ var BOARD_API_ERROR_CODES = [
104
104
  "talent_not_found",
105
105
  "talent_directory_not_found",
106
106
  "talent_directory_restricted",
107
+ "job_recommendations_not_found",
108
+ "recommended_talent_not_found",
107
109
  // Job alerts (anonymous + authenticated)
108
110
  "job_alert_not_found",
109
111
  "job_alerts_disabled",
@@ -113,10 +115,12 @@ var BOARD_API_ERROR_CODES = [
113
115
  "candidate_entry_not_found",
114
116
  "candidate_handle_taken",
115
117
  "candidate_job_not_found",
118
+ "candidate_notification_preference_paused",
116
119
  "resume_invalid_file",
117
120
  "resume_upload_forbidden",
118
121
  // Applications
119
122
  "applications_external_apply_only",
123
+ "applications_country_not_allowed",
120
124
  "applications_guest_not_allowed",
121
125
  "applications_job_not_found",
122
126
  "applications_not_found",
@@ -331,7 +335,7 @@ async function clearSession(storage) {
331
335
  }
332
336
 
333
337
  // src/version.ts
334
- var SDK_VERSION = "4.7.0";
338
+ var SDK_VERSION = "4.9.0";
335
339
 
336
340
  // src/client.ts
337
341
  function isRawBody(body) {
@@ -1045,6 +1049,9 @@ function jobsNamespace(client) {
1045
1049
  },
1046
1050
  /**
1047
1051
  * Retrieve one published job by slug.
1052
+ * Compatible starters pass `x-cavuno-board-capabilities:
1053
+ * apply-gateway-v1` in `options.headers` to opt in to the country-gated
1054
+ * Apply shape. The SDK never sends that capability globally.
1048
1055
  *
1049
1056
  * @example
1050
1057
  * const job = await board.jobs.retrieve('senior-chef');
@@ -1106,6 +1113,43 @@ function jobsNamespace(client) {
1106
1113
  { ...options, method: "POST", body: body ?? {} }
1107
1114
  );
1108
1115
  },
1116
+ /**
1117
+ * Create an opaque external-apply intent. A compatible starter sends the
1118
+ * candidate's browser to `gatewayUrl` (or asks it for the canonical JSON
1119
+ * decision after a real Apply click); never render it as a crawlable link. Pass
1120
+ * `x-cavuno-board-capabilities: apply-gateway-v1` in `options.headers`;
1121
+ * legacy callers receive 404.
1122
+ */
1123
+ createApplyIntent(jobSlug, body, options) {
1124
+ return client.fetch(
1125
+ `/jobs/${encodeURIComponent(jobSlug)}/apply-intents`,
1126
+ { ...options, method: "POST", body }
1127
+ );
1128
+ },
1129
+ /**
1130
+ * Prepare country approval for a signed-in candidate's native Apply.
1131
+ * When required, the candidate browser POSTs directly to `approvalUrl`
1132
+ * with no body or credentials, then supplies the returned opaque receipt
1133
+ * and the same server-owned session key to `apply`. Pass
1134
+ * `x-cavuno-board-capabilities: apply-gateway-v1` in `options.headers` for
1135
+ * both preparation and final Apply.
1136
+ *
1137
+ * @example
1138
+ * const plan = await board.jobs.prepareApplyApproval(
1139
+ * 'senior-chef',
1140
+ * { sessionKey },
1141
+ * { headers: {
1142
+ * authorization: `Bearer ${accessToken}`,
1143
+ * 'x-cavuno-board-capabilities': 'apply-gateway-v1',
1144
+ * } },
1145
+ * );
1146
+ */
1147
+ prepareApplyApproval(jobSlug, body, options) {
1148
+ return client.fetch(
1149
+ `/jobs/${encodeURIComponent(jobSlug)}/apply-approvals`,
1150
+ { ...options, method: "POST", body }
1151
+ );
1152
+ },
1109
1153
  /**
1110
1154
  * Upload + attach a resume to an application (multipart). Signed-in
1111
1155
  * candidates target their own application for the job; a guest passes the
@@ -3086,10 +3130,11 @@ function createBoardClient(options) {
3086
3130
  client,
3087
3131
  /**
3088
3132
  * Board context — identity, brand (`logoUrl` + favicon `icons`), language,
3089
- * features, and analytics.
3133
+ * features, analytics, and AdSense (`ads.enabled` + `ads.clientId`).
3134
+ * Per-placement slot ids are not on this resource.
3090
3135
  *
3091
3136
  * @example
3092
- * const { name, language, logoUrl, icons } = await board.context();
3137
+ * const { name, language, logoUrl, icons, ads } = await board.context();
3093
3138
  */
3094
3139
  context(options2) {
3095
3140
  return client.fetch("", options2);
package/dist/index.mjs CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  isValidationError,
16
16
  resolveStorage,
17
17
  writeSession
18
- } from "./chunk-ZCEAOJ6Y.mjs";
18
+ } from "./chunk-T46JASKG.mjs";
19
19
  import {
20
20
  paginate
21
21
  } from "./chunk-DLSO6XXY.mjs";
@@ -39,7 +39,7 @@ function toSearchParams(query) {
39
39
  }
40
40
 
41
41
  // src/version.ts
42
- var SDK_VERSION = "4.7.0";
42
+ var SDK_VERSION = "4.9.0";
43
43
 
44
44
  // src/client.ts
45
45
  function isRawBody(body) {
@@ -753,6 +753,9 @@ function jobsNamespace(client) {
753
753
  },
754
754
  /**
755
755
  * Retrieve one published job by slug.
756
+ * Compatible starters pass `x-cavuno-board-capabilities:
757
+ * apply-gateway-v1` in `options.headers` to opt in to the country-gated
758
+ * Apply shape. The SDK never sends that capability globally.
756
759
  *
757
760
  * @example
758
761
  * const job = await board.jobs.retrieve('senior-chef');
@@ -814,6 +817,43 @@ function jobsNamespace(client) {
814
817
  { ...options, method: "POST", body: body ?? {} }
815
818
  );
816
819
  },
820
+ /**
821
+ * Create an opaque external-apply intent. A compatible starter sends the
822
+ * candidate's browser to `gatewayUrl` (or asks it for the canonical JSON
823
+ * decision after a real Apply click); never render it as a crawlable link. Pass
824
+ * `x-cavuno-board-capabilities: apply-gateway-v1` in `options.headers`;
825
+ * legacy callers receive 404.
826
+ */
827
+ createApplyIntent(jobSlug, body, options) {
828
+ return client.fetch(
829
+ `/jobs/${encodeURIComponent(jobSlug)}/apply-intents`,
830
+ { ...options, method: "POST", body }
831
+ );
832
+ },
833
+ /**
834
+ * Prepare country approval for a signed-in candidate's native Apply.
835
+ * When required, the candidate browser POSTs directly to `approvalUrl`
836
+ * with no body or credentials, then supplies the returned opaque receipt
837
+ * and the same server-owned session key to `apply`. Pass
838
+ * `x-cavuno-board-capabilities: apply-gateway-v1` in `options.headers` for
839
+ * both preparation and final Apply.
840
+ *
841
+ * @example
842
+ * const plan = await board.jobs.prepareApplyApproval(
843
+ * 'senior-chef',
844
+ * { sessionKey },
845
+ * { headers: {
846
+ * authorization: `Bearer ${accessToken}`,
847
+ * 'x-cavuno-board-capabilities': 'apply-gateway-v1',
848
+ * } },
849
+ * );
850
+ */
851
+ prepareApplyApproval(jobSlug, body, options) {
852
+ return client.fetch(
853
+ `/jobs/${encodeURIComponent(jobSlug)}/apply-approvals`,
854
+ { ...options, method: "POST", body }
855
+ );
856
+ },
817
857
  /**
818
858
  * Upload + attach a resume to an application (multipart). Signed-in
819
859
  * candidates target their own application for the job; a guest passes the
@@ -2764,10 +2804,11 @@ function createBoardClient(options) {
2764
2804
  client,
2765
2805
  /**
2766
2806
  * Board context — identity, brand (`logoUrl` + favicon `icons`), language,
2767
- * features, and analytics.
2807
+ * features, analytics, and AdSense (`ads.enabled` + `ads.clientId`).
2808
+ * Per-placement slot ids are not on this resource.
2768
2809
  *
2769
2810
  * @example
2770
- * const { name, language, logoUrl, icons } = await board.context();
2811
+ * const { name, language, logoUrl, icons, ads } = await board.context();
2771
2812
  */
2772
2813
  context(options2) {
2773
2814
  return client.fetch("", options2);
@@ -1,4 +1,4 @@
1
- import { S as Schemas } from './_spec-B2ZrXuea.mjs';
1
+ import { S as Schemas } from './_spec-B9Ah8dNs.mjs';
2
2
 
3
3
  /**
4
4
  * Optional pagination metadata returned by Board API list operations.
@@ -1,4 +1,4 @@
1
- import { S as Schemas } from './_spec-B2ZrXuea.js';
1
+ import { S as Schemas } from './_spec-B9Ah8dNs.js';
2
2
 
3
3
  /**
4
4
  * Optional pagination metadata returned by Board API list operations.
@@ -1,4 +1,4 @@
1
- import { S as Schemas } from './_spec-B2ZrXuea.js';
1
+ import { S as Schemas } from './_spec-B9Ah8dNs.js';
2
2
 
3
3
  type Awaitable<T> = T | Promise<T>;
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { S as Schemas } from './_spec-B2ZrXuea.mjs';
1
+ import { S as Schemas } from './_spec-B9Ah8dNs.mjs';
2
2
 
3
3
  type Awaitable<T> = T | Promise<T>;
4
4
  /**
@@ -0,0 +1,12 @@
1
+ import { S as Schemas } from './_spec-B9Ah8dNs.js';
2
+
3
+ /**
4
+ * The public SEO-infra payload (`board.seo()`) — platform infrastructure a
5
+ * headless frontend rebuilds `robots.txt` / `ads.txt` / `indexnow-key.txt`
6
+ * (+ the Google site-verification `<meta>`) from, byte-identically to the
7
+ * hosted board. Icons and `themeColor` left in 4.0.0; applications
8
+ * own brand assets and presentation tokens.
9
+ */
10
+ type BoardSeo = Schemas['BoardSeo'];
11
+
12
+ export type { BoardSeo as B };
@@ -0,0 +1,12 @@
1
+ import { S as Schemas } from './_spec-B9Ah8dNs.mjs';
2
+
3
+ /**
4
+ * The public SEO-infra payload (`board.seo()`) — platform infrastructure a
5
+ * headless frontend rebuilds `robots.txt` / `ads.txt` / `indexnow-key.txt`
6
+ * (+ the Google site-verification `<meta>`) from, byte-identically to the
7
+ * hosted board. Icons and `themeColor` left in 4.0.0; applications
8
+ * own brand assets and presentation tokens.
9
+ */
10
+ type BoardSeo = Schemas['BoardSeo'];
11
+
12
+ export type { BoardSeo as B };
@@ -0,0 +1,36 @@
1
+ import { B as BoardSeo } from './seo-HCE7aCkh.mjs';
2
+ import './_spec-B9Ah8dNs.mjs';
3
+
4
+ /**
5
+ * `@cavuno/board/seo-files` — platform-owned crawler/identity file bodies
6
+ * (`robots.txt`, `ads.txt`, `indexnow-key.txt`) plus the Google
7
+ * site-verification meta descriptor.
8
+ *
9
+ * Pure, dependency-free: type-only import of `BoardSeo`. No node builtins,
10
+ * no framework packages. Hosted routes, the dispatch Worker, and the starter
11
+ * share these bytes so the files cannot drift.
12
+ */
13
+
14
+ declare const SEO_FILE_CONTENT_TYPE = "text/plain; charset=utf-8";
15
+ declare const ROBOTS_CACHE_CONTROL = "public, max-age=600, s-maxage=14400, stale-while-revalidate=86400";
16
+ declare const ADS_TXT_CACHE_CONTROL = "public, max-age=3600, must-revalidate";
17
+ declare const INDEXNOW_CACHE_CONTROL = "public, max-age=86400, must-revalidate";
18
+ type SeoFileResponseInit = {
19
+ method?: string;
20
+ };
21
+ /** Lines of the hosted robots body (no sitemap line). Exported so tests and hosted can share the literal. */
22
+ declare function robotsBody(input: {
23
+ canonicalBase: string;
24
+ sandbox?: boolean;
25
+ }): string;
26
+ declare function robotsResponse(seo: Pick<BoardSeo, 'canonicalBase'> & {
27
+ sandbox?: boolean;
28
+ }, init?: SeoFileResponseInit): Response;
29
+ declare function adsTxtResponse(seo: Pick<BoardSeo, 'adsTxt'>, init?: SeoFileResponseInit): Response;
30
+ declare function indexNowResponse(seo: Pick<BoardSeo, 'indexNowKey'>, init?: SeoFileResponseInit): Response;
31
+ declare function googleSiteVerificationMeta(token: string | null | undefined): {
32
+ name: 'google-site-verification';
33
+ content: string;
34
+ } | null;
35
+
36
+ export { ADS_TXT_CACHE_CONTROL, INDEXNOW_CACHE_CONTROL, ROBOTS_CACHE_CONTROL, SEO_FILE_CONTENT_TYPE, type SeoFileResponseInit, adsTxtResponse, googleSiteVerificationMeta, indexNowResponse, robotsBody, robotsResponse };
@@ -0,0 +1,36 @@
1
+ import { B as BoardSeo } from './seo-BDFUuvXM.js';
2
+ import './_spec-B9Ah8dNs.js';
3
+
4
+ /**
5
+ * `@cavuno/board/seo-files` — platform-owned crawler/identity file bodies
6
+ * (`robots.txt`, `ads.txt`, `indexnow-key.txt`) plus the Google
7
+ * site-verification meta descriptor.
8
+ *
9
+ * Pure, dependency-free: type-only import of `BoardSeo`. No node builtins,
10
+ * no framework packages. Hosted routes, the dispatch Worker, and the starter
11
+ * share these bytes so the files cannot drift.
12
+ */
13
+
14
+ declare const SEO_FILE_CONTENT_TYPE = "text/plain; charset=utf-8";
15
+ declare const ROBOTS_CACHE_CONTROL = "public, max-age=600, s-maxage=14400, stale-while-revalidate=86400";
16
+ declare const ADS_TXT_CACHE_CONTROL = "public, max-age=3600, must-revalidate";
17
+ declare const INDEXNOW_CACHE_CONTROL = "public, max-age=86400, must-revalidate";
18
+ type SeoFileResponseInit = {
19
+ method?: string;
20
+ };
21
+ /** Lines of the hosted robots body (no sitemap line). Exported so tests and hosted can share the literal. */
22
+ declare function robotsBody(input: {
23
+ canonicalBase: string;
24
+ sandbox?: boolean;
25
+ }): string;
26
+ declare function robotsResponse(seo: Pick<BoardSeo, 'canonicalBase'> & {
27
+ sandbox?: boolean;
28
+ }, init?: SeoFileResponseInit): Response;
29
+ declare function adsTxtResponse(seo: Pick<BoardSeo, 'adsTxt'>, init?: SeoFileResponseInit): Response;
30
+ declare function indexNowResponse(seo: Pick<BoardSeo, 'indexNowKey'>, init?: SeoFileResponseInit): Response;
31
+ declare function googleSiteVerificationMeta(token: string | null | undefined): {
32
+ name: 'google-site-verification';
33
+ content: string;
34
+ } | null;
35
+
36
+ export { ADS_TXT_CACHE_CONTROL, INDEXNOW_CACHE_CONTROL, ROBOTS_CACHE_CONTROL, SEO_FILE_CONTENT_TYPE, type SeoFileResponseInit, adsTxtResponse, googleSiteVerificationMeta, indexNowResponse, robotsBody, robotsResponse };
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/seo-files/index.ts
21
+ var seo_files_exports = {};
22
+ __export(seo_files_exports, {
23
+ ADS_TXT_CACHE_CONTROL: () => ADS_TXT_CACHE_CONTROL,
24
+ INDEXNOW_CACHE_CONTROL: () => INDEXNOW_CACHE_CONTROL,
25
+ ROBOTS_CACHE_CONTROL: () => ROBOTS_CACHE_CONTROL,
26
+ SEO_FILE_CONTENT_TYPE: () => SEO_FILE_CONTENT_TYPE,
27
+ adsTxtResponse: () => adsTxtResponse,
28
+ googleSiteVerificationMeta: () => googleSiteVerificationMeta,
29
+ indexNowResponse: () => indexNowResponse,
30
+ robotsBody: () => robotsBody,
31
+ robotsResponse: () => robotsResponse
32
+ });
33
+ module.exports = __toCommonJS(seo_files_exports);
34
+ var SEO_FILE_CONTENT_TYPE = "text/plain; charset=utf-8";
35
+ var ROBOTS_CACHE_CONTROL = "public, max-age=600, s-maxage=14400, stale-while-revalidate=86400";
36
+ var ADS_TXT_CACHE_CONTROL = "public, max-age=3600, must-revalidate";
37
+ var INDEXNOW_CACHE_CONTROL = "public, max-age=86400, must-revalidate";
38
+ function robotsBody(input) {
39
+ if (input.sandbox) {
40
+ return ["User-Agent: *", "Disallow: /", ""].join("\n");
41
+ }
42
+ const canonicalBase = input.canonicalBase.replace(/\/+$/, "");
43
+ return [
44
+ "User-Agent: *",
45
+ "Allow: /",
46
+ "Disallow: /go/",
47
+ "Disallow: /t/",
48
+ "Disallow: /jobs?page=",
49
+ "Disallow: /jobs*&page=",
50
+ "Disallow: /jobs/*?page=",
51
+ "Disallow: /companies?page=",
52
+ "Disallow: /companies*&page=",
53
+ "Disallow: /companies/*?page=",
54
+ "Disallow: /talent?page=",
55
+ "Disallow: /talent*&page=",
56
+ "Disallow: /talent/*?page=",
57
+ "",
58
+ `Sitemap: ${canonicalBase}/sitemap.xml`,
59
+ ""
60
+ ].join("\n");
61
+ }
62
+ function robotsResponse(seo, init) {
63
+ return textFileResponse(
64
+ robotsBody({ canonicalBase: seo.canonicalBase, sandbox: seo.sandbox }),
65
+ ROBOTS_CACHE_CONTROL,
66
+ init
67
+ );
68
+ }
69
+ function adsTxtResponse(seo, init) {
70
+ return optionalTextFileResponse(seo.adsTxt, ADS_TXT_CACHE_CONTROL, init);
71
+ }
72
+ function indexNowResponse(seo, init) {
73
+ return optionalTextFileResponse(
74
+ seo.indexNowKey,
75
+ INDEXNOW_CACHE_CONTROL,
76
+ init
77
+ );
78
+ }
79
+ function googleSiteVerificationMeta(token) {
80
+ if (typeof token !== "string") return null;
81
+ const content = token.trim();
82
+ if (!content) return null;
83
+ return { name: "google-site-verification", content };
84
+ }
85
+ function isHead(init) {
86
+ return init?.method?.toUpperCase() === "HEAD";
87
+ }
88
+ function textFileResponse(body, cacheControl, init) {
89
+ return new Response(isHead(init) ? null : body, {
90
+ status: 200,
91
+ headers: {
92
+ "Content-Type": SEO_FILE_CONTENT_TYPE,
93
+ "Cache-Control": cacheControl
94
+ }
95
+ });
96
+ }
97
+ function optionalTextFileResponse(value, cacheControl, init) {
98
+ if (value == null || value === "") {
99
+ return new Response(null, { status: 404 });
100
+ }
101
+ return textFileResponse(value, cacheControl, init);
102
+ }
@@ -0,0 +1,81 @@
1
+ // src/seo-files/index.ts
2
+ var SEO_FILE_CONTENT_TYPE = "text/plain; charset=utf-8";
3
+ var ROBOTS_CACHE_CONTROL = "public, max-age=600, s-maxage=14400, stale-while-revalidate=86400";
4
+ var ADS_TXT_CACHE_CONTROL = "public, max-age=3600, must-revalidate";
5
+ var INDEXNOW_CACHE_CONTROL = "public, max-age=86400, must-revalidate";
6
+ function robotsBody(input) {
7
+ if (input.sandbox) {
8
+ return ["User-Agent: *", "Disallow: /", ""].join("\n");
9
+ }
10
+ const canonicalBase = input.canonicalBase.replace(/\/+$/, "");
11
+ return [
12
+ "User-Agent: *",
13
+ "Allow: /",
14
+ "Disallow: /go/",
15
+ "Disallow: /t/",
16
+ "Disallow: /jobs?page=",
17
+ "Disallow: /jobs*&page=",
18
+ "Disallow: /jobs/*?page=",
19
+ "Disallow: /companies?page=",
20
+ "Disallow: /companies*&page=",
21
+ "Disallow: /companies/*?page=",
22
+ "Disallow: /talent?page=",
23
+ "Disallow: /talent*&page=",
24
+ "Disallow: /talent/*?page=",
25
+ "",
26
+ `Sitemap: ${canonicalBase}/sitemap.xml`,
27
+ ""
28
+ ].join("\n");
29
+ }
30
+ function robotsResponse(seo, init) {
31
+ return textFileResponse(
32
+ robotsBody({ canonicalBase: seo.canonicalBase, sandbox: seo.sandbox }),
33
+ ROBOTS_CACHE_CONTROL,
34
+ init
35
+ );
36
+ }
37
+ function adsTxtResponse(seo, init) {
38
+ return optionalTextFileResponse(seo.adsTxt, ADS_TXT_CACHE_CONTROL, init);
39
+ }
40
+ function indexNowResponse(seo, init) {
41
+ return optionalTextFileResponse(
42
+ seo.indexNowKey,
43
+ INDEXNOW_CACHE_CONTROL,
44
+ init
45
+ );
46
+ }
47
+ function googleSiteVerificationMeta(token) {
48
+ if (typeof token !== "string") return null;
49
+ const content = token.trim();
50
+ if (!content) return null;
51
+ return { name: "google-site-verification", content };
52
+ }
53
+ function isHead(init) {
54
+ return init?.method?.toUpperCase() === "HEAD";
55
+ }
56
+ function textFileResponse(body, cacheControl, init) {
57
+ return new Response(isHead(init) ? null : body, {
58
+ status: 200,
59
+ headers: {
60
+ "Content-Type": SEO_FILE_CONTENT_TYPE,
61
+ "Cache-Control": cacheControl
62
+ }
63
+ });
64
+ }
65
+ function optionalTextFileResponse(value, cacheControl, init) {
66
+ if (value == null || value === "") {
67
+ return new Response(null, { status: 404 });
68
+ }
69
+ return textFileResponse(value, cacheControl, init);
70
+ }
71
+ export {
72
+ ADS_TXT_CACHE_CONTROL,
73
+ INDEXNOW_CACHE_CONTROL,
74
+ ROBOTS_CACHE_CONTROL,
75
+ SEO_FILE_CONTENT_TYPE,
76
+ adsTxtResponse,
77
+ googleSiteVerificationMeta,
78
+ indexNowResponse,
79
+ robotsBody,
80
+ robotsResponse
81
+ };
package/dist/seo.d.mts CHANGED
@@ -1,9 +1,9 @@
1
- import { P as PublicBlogPostSummary, B as BlogAuthorEmbed } from './blog-B125P3dS.mjs';
2
- import { e as JsonLdObject } from './breadcrumbs-CP42mzYb.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-CP42mzYb.mjs';
4
- import './_spec-B2ZrXuea.mjs';
5
- import './board-QTX75RxT.mjs';
6
- import './jobs-DrdhICLO.mjs';
1
+ import { P as PublicBlogPostSummary, B as BlogAuthorEmbed } from './blog-BmqWfLZi.mjs';
2
+ import { e as JsonLdObject } from './breadcrumbs-BVQL2dNY.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-BVQL2dNY.mjs';
4
+ import './_spec-B9Ah8dNs.mjs';
5
+ import './board-B4jLqmxn.mjs';
6
+ import './jobs-B7q3BgIK.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-BmEG_fhe.js';
2
- import { e as JsonLdObject } from './breadcrumbs-BVeDYPCw.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-BVeDYPCw.js';
4
- import './_spec-B2ZrXuea.js';
5
- import './board-6woxZtzD.js';
6
- import './jobs-BH1CgV8J.js';
1
+ import { P as PublicBlogPostSummary, B as BlogAuthorEmbed } from './blog-bh07fZ8Q.js';
2
+ import { e as JsonLdObject } from './breadcrumbs-B1HVufC7.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-B1HVufC7.js';
4
+ import './_spec-B9Ah8dNs.js';
5
+ import './board-De8nLbk7.js';
6
+ import './jobs-Iv6Wkvvf.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,9 +1,10 @@
1
1
  import { BoardSdk } from './index.mjs';
2
- import './_spec-B2ZrXuea.mjs';
3
- import './search-B9T6rAhd.mjs';
4
- import './board-QTX75RxT.mjs';
5
- import './jobs-DrdhICLO.mjs';
6
- import './blog-B125P3dS.mjs';
2
+ import './_spec-B9Ah8dNs.mjs';
3
+ import './search-DC0jatQN.mjs';
4
+ import './board-B4jLqmxn.mjs';
5
+ import './jobs-B7q3BgIK.mjs';
6
+ import './seo-HCE7aCkh.mjs';
7
+ import './blog-BmqWfLZi.mjs';
7
8
 
8
9
  /**
9
10
  * Session cookie codec — pure (no framework imports, no node imports) so it
package/dist/server.d.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  import { BoardSdk } from './index.js';
2
- import './_spec-B2ZrXuea.js';
3
- import './search-CCsijbzU.js';
4
- import './board-6woxZtzD.js';
5
- import './jobs-BH1CgV8J.js';
6
- import './blog-BmEG_fhe.js';
2
+ import './_spec-B9Ah8dNs.js';
3
+ import './search-CbDZwdyl.js';
4
+ import './board-De8nLbk7.js';
5
+ import './jobs-Iv6Wkvvf.js';
6
+ import './seo-BDFUuvXM.js';
7
+ import './blog-bh07fZ8Q.js';
7
8
 
8
9
  /**
9
10
  * Session cookie codec — pure (no framework imports, no node imports) so it
package/dist/server.mjs CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  isNoStore,
3
3
  isUnauthorized,
4
4
  scopeToken
5
- } from "./chunk-ZCEAOJ6Y.mjs";
5
+ } from "./chunk-T46JASKG.mjs";
6
6
 
7
7
  // src/server/cookie.ts
8
8
  var COOKIE_ATTRIBUTES = "Path=/; HttpOnly; Secure; SameSite=Lax";
@@ -1,9 +1,10 @@
1
1
  import { BoardSdk } from './index.mjs';
2
- import './_spec-B2ZrXuea.mjs';
3
- import './search-B9T6rAhd.mjs';
4
- import './board-QTX75RxT.mjs';
5
- import './jobs-DrdhICLO.mjs';
6
- import './blog-B125P3dS.mjs';
2
+ import './_spec-B9Ah8dNs.mjs';
3
+ import './search-DC0jatQN.mjs';
4
+ import './board-B4jLqmxn.mjs';
5
+ import './jobs-B7q3BgIK.mjs';
6
+ import './seo-HCE7aCkh.mjs';
7
+ import './blog-BmqWfLZi.mjs';
7
8
 
8
9
  /**
9
10
  * Sitemap primitives — the pure XML + bucket-filename logic behind a board
package/dist/sitemap.d.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  import { BoardSdk } from './index.js';
2
- import './_spec-B2ZrXuea.js';
3
- import './search-CCsijbzU.js';
4
- import './board-6woxZtzD.js';
5
- import './jobs-BH1CgV8J.js';
6
- import './blog-BmEG_fhe.js';
2
+ import './_spec-B9Ah8dNs.js';
3
+ import './search-CbDZwdyl.js';
4
+ import './board-De8nLbk7.js';
5
+ import './jobs-Iv6Wkvvf.js';
6
+ import './seo-BDFUuvXM.js';
7
+ import './blog-bh07fZ8Q.js';
7
8
 
8
9
  /**
9
10
  * Sitemap primitives — the pure XML + bucket-filename logic behind a board
@@ -1,5 +1,5 @@
1
- import { h as SuggestionItem, b as SearchSuggestQuery, F as FetchOptions, g as SuggestResult } from './search-B9T6rAhd.mjs';
2
- import './_spec-B2ZrXuea.mjs';
1
+ import { h as SuggestionItem, b as SearchSuggestQuery, F as FetchOptions, g as SuggestResult } from './search-DC0jatQN.mjs';
2
+ import './_spec-B9Ah8dNs.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-CCsijbzU.js';
2
- import './_spec-B2ZrXuea.js';
1
+ import { h as SuggestionItem, b as SearchSuggestQuery, F as FetchOptions, g as SuggestResult } from './search-CbDZwdyl.js';
2
+ import './_spec-B9Ah8dNs.js';
3
3
 
4
4
  /**
5
5
  * `@cavuno/board/suggest` — framework-agnostic headless search-suggest
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cavuno/board",
3
- "version": "4.7.0",
3
+ "version": "4.9.0",
4
4
  "description": "Build custom job boards and careers pages with Cavuno’s TypeScript SDK.",
5
5
  "keywords": [
6
6
  "api-client",
@@ -154,6 +154,16 @@
154
154
  "default": "./dist/well-known.js"
155
155
  }
156
156
  },
157
+ "./seo-files": {
158
+ "import": {
159
+ "types": "./dist/seo-files.d.mts",
160
+ "default": "./dist/seo-files.mjs"
161
+ },
162
+ "require": {
163
+ "types": "./dist/seo-files.d.ts",
164
+ "default": "./dist/seo-files.js"
165
+ }
166
+ },
157
167
  "./server": {
158
168
  "import": {
159
169
  "types": "./dist/server.d.mts",