@cavuno/board 4.21.1 → 4.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/dist/{_spec-CyNKpM_j.d.mts → _spec-p1bcDr9R.d.mts} +7 -0
- package/dist/{_spec-CyNKpM_j.d.ts → _spec-p1bcDr9R.d.ts} +7 -0
- package/dist/bin.mjs +58 -2
- package/dist/{blog-BNIqGayD.d.mts → blog-CsI8GdJS.d.mts} +1 -1
- package/dist/{blog-CRvaDyzJ.d.ts → blog-DB4YIfn4.d.ts} +1 -1
- package/dist/{board-mn3GVbrC.d.mts → board-CuIyeFsj.d.mts} +2 -2
- package/dist/{board-CXNxSlUB.d.ts → board-Dq9gD7qr.d.ts} +2 -2
- package/dist/{breadcrumbs-Bi4LHNAF.d.mts → breadcrumbs-B_WTKaIk.d.mts} +2 -2
- package/dist/{breadcrumbs-Crk6Q69T.d.ts → breadcrumbs-CyCZ8N8_.d.ts} +2 -2
- package/dist/browser/cavuno-board.global.min.js +1 -1
- package/dist/{chunk-LWJOSIXX.mjs → chunk-DP2ZZZEO.mjs} +3 -0
- package/dist/doctor.js +58 -2
- package/dist/doctor.mjs +58 -2
- 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 +35 -13
- package/dist/index.d.ts +35 -13
- package/dist/index.js +43 -1
- package/dist/index.mjs +41 -2
- package/dist/{jobs-CALE3I8I.d.mts → jobs-Bv12BcSA.d.mts} +1 -1
- package/dist/{jobs-CSWXqLZR.d.ts → jobs-C-sBPgNp.d.ts} +1 -1
- package/dist/{search-B_hwS-xu.d.mts → search-CNeOnhWb.d.mts} +1 -1
- package/dist/{search-BRCbe1Nm.d.ts → search-W28d76OJ.d.ts} +1 -1
- package/dist/{seo-CS4lrG20.d.mts → seo-BGHJcfev.d.mts} +1 -1
- package/dist/{seo-D1u-RmLQ.d.ts → seo-DAHd1ngs.d.ts} +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 +37 -7
- package/dist/sitemap.d.ts +37 -7
- package/dist/sitemap.js +34 -9
- package/dist/sitemap.mjs +35 -10
- package/dist/suggest.d.mts +2 -2
- package/dist/suggest.d.ts +2 -2
- package/package.json +1 -1
- package/skills/cavuno-board-companies/SKILL.md +6 -0
- package/skills/cavuno-board-sitemap/SKILL.md +51 -2
- package/skills/manifest.json +1 -1
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-CsI8GdJS.mjs';
|
|
2
|
+
import { e as JsonLdObject } from './breadcrumbs-B_WTKaIk.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-B_WTKaIk.mjs';
|
|
4
|
+
import './_spec-p1bcDr9R.mjs';
|
|
5
|
+
import './board-CuIyeFsj.mjs';
|
|
6
|
+
import './jobs-Bv12BcSA.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-DB4YIfn4.js';
|
|
2
|
+
import { e as JsonLdObject } from './breadcrumbs-CyCZ8N8_.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-CyCZ8N8_.js';
|
|
4
|
+
import './_spec-p1bcDr9R.js';
|
|
5
|
+
import './board-Dq9gD7qr.js';
|
|
6
|
+
import './jobs-C-sBPgNp.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-p1bcDr9R.mjs';
|
|
3
|
+
import './search-CNeOnhWb.mjs';
|
|
4
|
+
import './board-CuIyeFsj.mjs';
|
|
5
|
+
import './jobs-Bv12BcSA.mjs';
|
|
6
|
+
import './seo-BGHJcfev.mjs';
|
|
7
|
+
import './blog-CsI8GdJS.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-p1bcDr9R.js';
|
|
3
|
+
import './search-W28d76OJ.js';
|
|
4
|
+
import './board-Dq9gD7qr.js';
|
|
5
|
+
import './jobs-C-sBPgNp.js';
|
|
6
|
+
import './seo-DAHd1ngs.js';
|
|
7
|
+
import './blog-DB4YIfn4.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-p1bcDr9R.mjs';
|
|
3
|
+
import './search-CNeOnhWb.mjs';
|
|
4
|
+
import './board-CuIyeFsj.mjs';
|
|
5
|
+
import './jobs-Bv12BcSA.mjs';
|
|
6
|
+
import './seo-BGHJcfev.mjs';
|
|
7
|
+
import './blog-CsI8GdJS.mjs';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Sitemap primitives — the pure XML + bucket-filename logic behind a board
|
|
@@ -70,6 +70,36 @@ declare const MIN_JOBS_PER_INDEXED_PAGE = 5;
|
|
|
70
70
|
* urlset when a board lacks that content (valid, just zero URLs).
|
|
71
71
|
*/
|
|
72
72
|
declare function listedBuckets(board: BoardSdk): Promise<SitemapBucket[]>;
|
|
73
|
+
/**
|
|
74
|
+
* One listed bucket, with the freshness stamp the board publishes for it.
|
|
75
|
+
*
|
|
76
|
+
* `lastModified` is present only on the mirror path, and only for the buckets
|
|
77
|
+
* the board tracks one for — the legacy fallback has no such stamp, so it
|
|
78
|
+
* yields bucket names alone. Feed these straight to `renderSitemapIndex` and
|
|
79
|
+
* each `<sitemap>` gets a `<lastmod>`.
|
|
80
|
+
*/
|
|
81
|
+
interface ListedSitemapBucket {
|
|
82
|
+
bucket: SitemapBucket;
|
|
83
|
+
/** ISO 8601 timestamp of the newest content in the bucket, when known. */
|
|
84
|
+
lastModified?: string;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Like `listedBuckets`, but keeps each bucket's `lastModified`. Same two
|
|
88
|
+
* paths, same ordering, same error rules — the only difference is that the
|
|
89
|
+
* freshness stamp survives.
|
|
90
|
+
*/
|
|
91
|
+
declare function listedBucketEntries(board: BoardSdk): Promise<ListedSitemapBucket[]>;
|
|
73
92
|
declare function buildBucketUrls(board: BoardSdk, origin: string, bucket: SitemapBucket): Promise<string[]>;
|
|
93
|
+
/**
|
|
94
|
+
* Like `buildBucketUrls`, but keeps each URL's `lastModified` where the board
|
|
95
|
+
* publishes one. The result feeds `renderUrlset` directly, so every `<url>`
|
|
96
|
+
* that has a freshness stamp gets a `<lastmod>` — the signal crawlers use to
|
|
97
|
+
* prioritise recrawl across a large sitemap.
|
|
98
|
+
*
|
|
99
|
+
* On the legacy fallback path the catalog endpoints expose no per-URL stamp,
|
|
100
|
+
* so entries come back as `{ url }` only — identical output to
|
|
101
|
+
* `buildBucketUrls`, just in the wider shape.
|
|
102
|
+
*/
|
|
103
|
+
declare function buildBucketEntries(board: BoardSdk, origin: string, bucket: SitemapBucket): Promise<SitemapUrlEntry[]>;
|
|
74
104
|
|
|
75
|
-
export { MIN_JOBS_PER_INDEXED_PAGE, SITEMAP_BUCKETS, SITEMAP_CHUNK_SIZE, type SitemapBucket, type SitemapIndexEntry, type SitemapUrlEntry, bucketFilename, buildBucketUrls, chunk, listedBuckets, parseBucketFilename, renderSitemapIndex, renderUrlset, xmlEscape };
|
|
105
|
+
export { type ListedSitemapBucket, MIN_JOBS_PER_INDEXED_PAGE, SITEMAP_BUCKETS, SITEMAP_CHUNK_SIZE, type SitemapBucket, type SitemapIndexEntry, type SitemapUrlEntry, bucketFilename, buildBucketEntries, buildBucketUrls, chunk, listedBucketEntries, listedBuckets, parseBucketFilename, renderSitemapIndex, renderUrlset, xmlEscape };
|
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-p1bcDr9R.js';
|
|
3
|
+
import './search-W28d76OJ.js';
|
|
4
|
+
import './board-Dq9gD7qr.js';
|
|
5
|
+
import './jobs-C-sBPgNp.js';
|
|
6
|
+
import './seo-DAHd1ngs.js';
|
|
7
|
+
import './blog-DB4YIfn4.js';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Sitemap primitives — the pure XML + bucket-filename logic behind a board
|
|
@@ -70,6 +70,36 @@ declare const MIN_JOBS_PER_INDEXED_PAGE = 5;
|
|
|
70
70
|
* urlset when a board lacks that content (valid, just zero URLs).
|
|
71
71
|
*/
|
|
72
72
|
declare function listedBuckets(board: BoardSdk): Promise<SitemapBucket[]>;
|
|
73
|
+
/**
|
|
74
|
+
* One listed bucket, with the freshness stamp the board publishes for it.
|
|
75
|
+
*
|
|
76
|
+
* `lastModified` is present only on the mirror path, and only for the buckets
|
|
77
|
+
* the board tracks one for — the legacy fallback has no such stamp, so it
|
|
78
|
+
* yields bucket names alone. Feed these straight to `renderSitemapIndex` and
|
|
79
|
+
* each `<sitemap>` gets a `<lastmod>`.
|
|
80
|
+
*/
|
|
81
|
+
interface ListedSitemapBucket {
|
|
82
|
+
bucket: SitemapBucket;
|
|
83
|
+
/** ISO 8601 timestamp of the newest content in the bucket, when known. */
|
|
84
|
+
lastModified?: string;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Like `listedBuckets`, but keeps each bucket's `lastModified`. Same two
|
|
88
|
+
* paths, same ordering, same error rules — the only difference is that the
|
|
89
|
+
* freshness stamp survives.
|
|
90
|
+
*/
|
|
91
|
+
declare function listedBucketEntries(board: BoardSdk): Promise<ListedSitemapBucket[]>;
|
|
73
92
|
declare function buildBucketUrls(board: BoardSdk, origin: string, bucket: SitemapBucket): Promise<string[]>;
|
|
93
|
+
/**
|
|
94
|
+
* Like `buildBucketUrls`, but keeps each URL's `lastModified` where the board
|
|
95
|
+
* publishes one. The result feeds `renderUrlset` directly, so every `<url>`
|
|
96
|
+
* that has a freshness stamp gets a `<lastmod>` — the signal crawlers use to
|
|
97
|
+
* prioritise recrawl across a large sitemap.
|
|
98
|
+
*
|
|
99
|
+
* On the legacy fallback path the catalog endpoints expose no per-URL stamp,
|
|
100
|
+
* so entries come back as `{ url }` only — identical output to
|
|
101
|
+
* `buildBucketUrls`, just in the wider shape.
|
|
102
|
+
*/
|
|
103
|
+
declare function buildBucketEntries(board: BoardSdk, origin: string, bucket: SitemapBucket): Promise<SitemapUrlEntry[]>;
|
|
74
104
|
|
|
75
|
-
export { MIN_JOBS_PER_INDEXED_PAGE, SITEMAP_BUCKETS, SITEMAP_CHUNK_SIZE, type SitemapBucket, type SitemapIndexEntry, type SitemapUrlEntry, bucketFilename, buildBucketUrls, chunk, listedBuckets, parseBucketFilename, renderSitemapIndex, renderUrlset, xmlEscape };
|
|
105
|
+
export { type ListedSitemapBucket, MIN_JOBS_PER_INDEXED_PAGE, SITEMAP_BUCKETS, SITEMAP_CHUNK_SIZE, type SitemapBucket, type SitemapIndexEntry, type SitemapUrlEntry, bucketFilename, buildBucketEntries, buildBucketUrls, chunk, listedBucketEntries, listedBuckets, parseBucketFilename, renderSitemapIndex, renderUrlset, xmlEscape };
|
package/dist/sitemap.js
CHANGED
|
@@ -24,8 +24,10 @@ __export(sitemap_exports, {
|
|
|
24
24
|
SITEMAP_BUCKETS: () => SITEMAP_BUCKETS,
|
|
25
25
|
SITEMAP_CHUNK_SIZE: () => SITEMAP_CHUNK_SIZE,
|
|
26
26
|
bucketFilename: () => bucketFilename,
|
|
27
|
+
buildBucketEntries: () => buildBucketEntries,
|
|
27
28
|
buildBucketUrls: () => buildBucketUrls,
|
|
28
29
|
chunk: () => chunk,
|
|
30
|
+
listedBucketEntries: () => listedBucketEntries,
|
|
29
31
|
listedBuckets: () => listedBuckets,
|
|
30
32
|
parseBucketFilename: () => parseBucketFilename,
|
|
31
33
|
renderSitemapIndex: () => renderSitemapIndex,
|
|
@@ -305,34 +307,57 @@ function enumerateCompanies(board) {
|
|
|
305
307
|
}
|
|
306
308
|
var MIRROR_PAGE = 1e3;
|
|
307
309
|
async function listedBuckets(board) {
|
|
310
|
+
const listed = await listedBucketEntries(board);
|
|
311
|
+
return listed.map((entry) => entry.bucket);
|
|
312
|
+
}
|
|
313
|
+
async function listedBucketEntries(board) {
|
|
308
314
|
try {
|
|
309
315
|
const index = await board.sitemap();
|
|
310
|
-
const published = new
|
|
311
|
-
|
|
316
|
+
const published = new Map(
|
|
317
|
+
index.buckets.map((entry) => [entry.bucket, entry.lastModified])
|
|
318
|
+
);
|
|
319
|
+
return SITEMAP_BUCKETS.filter((bucket) => published.has(bucket)).map(
|
|
320
|
+
(bucket) => {
|
|
321
|
+
const lastModified = published.get(bucket);
|
|
322
|
+
return lastModified === void 0 ? { bucket } : { bucket, lastModified };
|
|
323
|
+
}
|
|
324
|
+
);
|
|
312
325
|
} catch (error) {
|
|
313
326
|
if (!isNotFound(error)) throw error;
|
|
314
327
|
const { features } = await board.context();
|
|
315
|
-
return SITEMAP_BUCKETS.filter((b) => b !== "blog" || features.blog)
|
|
328
|
+
return SITEMAP_BUCKETS.filter((b) => b !== "blog" || features.blog).map(
|
|
329
|
+
(bucket) => ({ bucket })
|
|
330
|
+
);
|
|
316
331
|
}
|
|
317
332
|
}
|
|
318
333
|
async function buildBucketUrls(board, origin, bucket) {
|
|
334
|
+
const entries = await buildBucketEntries(board, origin, bucket);
|
|
335
|
+
return entries.map((entry) => entry.url);
|
|
336
|
+
}
|
|
337
|
+
async function buildBucketEntries(board, origin, bucket) {
|
|
319
338
|
try {
|
|
320
|
-
return await
|
|
339
|
+
return await mirrorBucketEntries(board, origin, bucket);
|
|
321
340
|
} catch (error) {
|
|
322
341
|
if (!isNotFound(error)) throw error;
|
|
323
|
-
|
|
342
|
+
const urls = await legacyBucketUrls(board, origin, bucket);
|
|
343
|
+
return urls.map((url) => ({ url }));
|
|
324
344
|
}
|
|
325
345
|
}
|
|
326
|
-
async function
|
|
346
|
+
async function mirrorBucketEntries(board, origin, bucket) {
|
|
327
347
|
const pages = paginate(
|
|
328
348
|
(query, options) => board.sitemap.entries(bucket, query, options),
|
|
329
349
|
{ limit: MIRROR_PAGE }
|
|
330
350
|
).pages();
|
|
331
|
-
const
|
|
351
|
+
const entries = [];
|
|
332
352
|
for await (const page of pages) {
|
|
333
|
-
for (const entry of page.data)
|
|
353
|
+
for (const entry of page.data) {
|
|
354
|
+
const url = `${origin}${entry.path}`;
|
|
355
|
+
entries.push(
|
|
356
|
+
entry.lastModified === void 0 ? { url } : { url, lastModified: entry.lastModified }
|
|
357
|
+
);
|
|
358
|
+
}
|
|
334
359
|
}
|
|
335
|
-
return
|
|
360
|
+
return entries;
|
|
336
361
|
}
|
|
337
362
|
async function legacyBucketUrls(board, origin, bucket) {
|
|
338
363
|
switch (bucket) {
|
package/dist/sitemap.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-DLSO6XXY.mjs";
|
|
4
4
|
import {
|
|
5
5
|
isNotFound
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-DP2ZZZEO.mjs";
|
|
7
7
|
import {
|
|
8
8
|
BOARD_PATHS,
|
|
9
9
|
blogAuthorPath,
|
|
@@ -178,34 +178,57 @@ function enumerateCompanies(board) {
|
|
|
178
178
|
}
|
|
179
179
|
var MIRROR_PAGE = 1e3;
|
|
180
180
|
async function listedBuckets(board) {
|
|
181
|
+
const listed = await listedBucketEntries(board);
|
|
182
|
+
return listed.map((entry) => entry.bucket);
|
|
183
|
+
}
|
|
184
|
+
async function listedBucketEntries(board) {
|
|
181
185
|
try {
|
|
182
186
|
const index = await board.sitemap();
|
|
183
|
-
const published = new
|
|
184
|
-
|
|
187
|
+
const published = new Map(
|
|
188
|
+
index.buckets.map((entry) => [entry.bucket, entry.lastModified])
|
|
189
|
+
);
|
|
190
|
+
return SITEMAP_BUCKETS.filter((bucket) => published.has(bucket)).map(
|
|
191
|
+
(bucket) => {
|
|
192
|
+
const lastModified = published.get(bucket);
|
|
193
|
+
return lastModified === void 0 ? { bucket } : { bucket, lastModified };
|
|
194
|
+
}
|
|
195
|
+
);
|
|
185
196
|
} catch (error) {
|
|
186
197
|
if (!isNotFound(error)) throw error;
|
|
187
198
|
const { features } = await board.context();
|
|
188
|
-
return SITEMAP_BUCKETS.filter((b) => b !== "blog" || features.blog)
|
|
199
|
+
return SITEMAP_BUCKETS.filter((b) => b !== "blog" || features.blog).map(
|
|
200
|
+
(bucket) => ({ bucket })
|
|
201
|
+
);
|
|
189
202
|
}
|
|
190
203
|
}
|
|
191
204
|
async function buildBucketUrls(board, origin, bucket) {
|
|
205
|
+
const entries = await buildBucketEntries(board, origin, bucket);
|
|
206
|
+
return entries.map((entry) => entry.url);
|
|
207
|
+
}
|
|
208
|
+
async function buildBucketEntries(board, origin, bucket) {
|
|
192
209
|
try {
|
|
193
|
-
return await
|
|
210
|
+
return await mirrorBucketEntries(board, origin, bucket);
|
|
194
211
|
} catch (error) {
|
|
195
212
|
if (!isNotFound(error)) throw error;
|
|
196
|
-
|
|
213
|
+
const urls = await legacyBucketUrls(board, origin, bucket);
|
|
214
|
+
return urls.map((url) => ({ url }));
|
|
197
215
|
}
|
|
198
216
|
}
|
|
199
|
-
async function
|
|
217
|
+
async function mirrorBucketEntries(board, origin, bucket) {
|
|
200
218
|
const pages = paginate(
|
|
201
219
|
(query, options) => board.sitemap.entries(bucket, query, options),
|
|
202
220
|
{ limit: MIRROR_PAGE }
|
|
203
221
|
).pages();
|
|
204
|
-
const
|
|
222
|
+
const entries = [];
|
|
205
223
|
for await (const page of pages) {
|
|
206
|
-
for (const entry of page.data)
|
|
224
|
+
for (const entry of page.data) {
|
|
225
|
+
const url = `${origin}${entry.path}`;
|
|
226
|
+
entries.push(
|
|
227
|
+
entry.lastModified === void 0 ? { url } : { url, lastModified: entry.lastModified }
|
|
228
|
+
);
|
|
229
|
+
}
|
|
207
230
|
}
|
|
208
|
-
return
|
|
231
|
+
return entries;
|
|
209
232
|
}
|
|
210
233
|
async function legacyBucketUrls(board, origin, bucket) {
|
|
211
234
|
switch (bucket) {
|
|
@@ -354,8 +377,10 @@ export {
|
|
|
354
377
|
SITEMAP_BUCKETS,
|
|
355
378
|
SITEMAP_CHUNK_SIZE,
|
|
356
379
|
bucketFilename,
|
|
380
|
+
buildBucketEntries,
|
|
357
381
|
buildBucketUrls,
|
|
358
382
|
chunk,
|
|
383
|
+
listedBucketEntries,
|
|
359
384
|
listedBuckets,
|
|
360
385
|
parseBucketFilename,
|
|
361
386
|
renderSitemapIndex,
|
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-CNeOnhWb.mjs';
|
|
2
|
+
import './_spec-p1bcDr9R.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-W28d76OJ.js';
|
|
2
|
+
import './_spec-p1bcDr9R.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* `@cavuno/board/suggest` — framework-agnostic headless search-suggest
|
package/package.json
CHANGED
|
@@ -18,6 +18,12 @@ Demoting, removing, or leaving as the last admin is `last_admin`. Admins
|
|
|
18
18
|
invite by email; approved members can list pending invites; accept is
|
|
19
19
|
session-gated on `board.me.acceptInvite`.
|
|
20
20
|
|
|
21
|
+
An approved member can buy a public, priced membership plan for the company
|
|
22
|
+
with `board.me.companies.startMembershipCheckout(slug, body)`. It returns the
|
|
23
|
+
same embedded-checkout mount kit as talent access; poll
|
|
24
|
+
`retrieveMembershipCheckout(slug, sessionId)` after the return redirect. A
|
|
25
|
+
company that already holds a membership is `membership_seat_taken`.
|
|
26
|
+
|
|
21
27
|
```ts snippet
|
|
22
28
|
await board.me.companies.delete('acme');
|
|
23
29
|
const { data: members } = await board.me.companies.listMembers('acme');
|
|
@@ -18,7 +18,10 @@ The pure XML tier exports `SITEMAP_BUCKETS`, `SITEMAP_CHUNK_SIZE` (45,000),
|
|
|
18
18
|
`chunk`, `bucketFilename`, `parseBucketFilename`, `renderUrlset`, and
|
|
19
19
|
`renderSitemapIndex`. The catalog tier exports `listedBuckets(board)` and
|
|
20
20
|
`buildBucketUrls(board, origin, bucket)`; it walks the SDK and applies the
|
|
21
|
-
hosted indexing policy.
|
|
21
|
+
hosted indexing policy. `listedBucketEntries(board)` and
|
|
22
|
+
`buildBucketEntries(board, origin, bucket)` are the freshness-preserving
|
|
23
|
+
siblings: same walk and same policy, but each result keeps its
|
|
24
|
+
`lastModified`.
|
|
22
25
|
|
|
23
26
|
## Serve the index
|
|
24
27
|
|
|
@@ -77,9 +80,55 @@ return xmlResponse(renderUrlset(page));
|
|
|
77
80
|
serialize to ISO 8601. `renderSitemapIndex` accepts strings or
|
|
78
81
|
`{ url, lastModified? }`. The hosted format omits `changefreq` and `priority`.
|
|
79
82
|
|
|
83
|
+
## Emit `<lastmod>`
|
|
84
|
+
|
|
85
|
+
Freshness is the strongest recrawl-priority signal on a large sitemap, so
|
|
86
|
+
prefer the entries walkers. `buildBucketEntries` returns
|
|
87
|
+
`{ url, lastModified? }[]` that feeds `renderUrlset` unchanged, and
|
|
88
|
+
`listedBucketEntries` returns `{ bucket, lastModified? }[]` for the index.
|
|
89
|
+
The board publishes a stamp per URL and per bucket wherever it tracks one;
|
|
90
|
+
entries without one simply omit `<lastmod>`.
|
|
91
|
+
|
|
92
|
+
```ts snippet
|
|
93
|
+
import {
|
|
94
|
+
SITEMAP_CHUNK_SIZE,
|
|
95
|
+
buildBucketEntries,
|
|
96
|
+
bucketFilename,
|
|
97
|
+
chunk,
|
|
98
|
+
listedBucketEntries,
|
|
99
|
+
renderSitemapIndex,
|
|
100
|
+
renderUrlset,
|
|
101
|
+
type SitemapIndexEntry,
|
|
102
|
+
} from '@cavuno/board/sitemap';
|
|
103
|
+
|
|
104
|
+
// Index: one <sitemap> per chunk, each carrying its bucket's stamp. Buckets
|
|
105
|
+
// over SITEMAP_CHUNK_SIZE produce -2, -3, … files; list every one.
|
|
106
|
+
const sitemaps: SitemapIndexEntry[] = [];
|
|
107
|
+
for (const { bucket, lastModified } of await listedBucketEntries(board)) {
|
|
108
|
+
const chunks = chunk(await buildBucketEntries(board, origin, bucket), SITEMAP_CHUNK_SIZE);
|
|
109
|
+
for (let i = 0; i < Math.max(chunks.length, 1); i += 1) {
|
|
110
|
+
sitemaps.push({
|
|
111
|
+
url: `${origin}/sitemap/${bucketFilename(bucket, i)}`,
|
|
112
|
+
...(lastModified ? { lastModified } : {}),
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
const indexXml = renderSitemapIndex(sitemaps);
|
|
117
|
+
|
|
118
|
+
// Bucket file: every <url> keeps its own stamp.
|
|
119
|
+
const entries = await buildBucketEntries(board, origin, parsed.bucket);
|
|
120
|
+
const page = chunk(entries, SITEMAP_CHUNK_SIZE)[parsed.chunkIndex] ?? [];
|
|
121
|
+
const bucketXml = renderUrlset(page);
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
`buildBucketUrls` and `listedBuckets` still return plain strings and bucket
|
|
125
|
+
names; they are unchanged, and a sitemap built from them carries no
|
|
126
|
+
`<lastmod>`.
|
|
127
|
+
|
|
80
128
|
## Keep the walker policy intact
|
|
81
129
|
|
|
82
|
-
`
|
|
130
|
+
`buildBucketEntries` is the policy boundary (`buildBucketUrls` is a map over
|
|
131
|
+
it):
|
|
83
132
|
|
|
84
133
|
- Taxonomy and location pages enter the sitemap at five distinct jobs,
|
|
85
134
|
`MIN_JOBS_PER_INDEXED_PAGE`.
|
package/skills/manifest.json
CHANGED