@cavuno/board 1.25.0 → 1.27.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/README.md +88 -0
- package/dist/bin.mjs +67 -34
- package/dist/filters.d.mts +55 -0
- package/dist/filters.d.ts +55 -0
- package/dist/filters.js +193 -0
- package/dist/filters.mjs +170 -0
- package/dist/format.d.mts +240 -0
- package/dist/format.d.ts +240 -0
- package/dist/format.js +453 -0
- package/dist/format.mjs +430 -0
- package/dist/index.d.mts +81 -3965
- package/dist/index.d.ts +81 -3965
- package/dist/index.js +154 -7
- package/dist/index.mjs +151 -4
- package/dist/jobs-DK5mPBgq.d.mts +3836 -0
- package/dist/jobs-DK5mPBgq.d.ts +3836 -0
- package/dist/salaries-CXt6Vkrp.d.ts +130 -0
- package/dist/salaries-CrJsaZe6.d.mts +130 -0
- package/dist/seo.d.mts +288 -0
- package/dist/seo.d.ts +288 -0
- package/dist/seo.js +1102 -0
- package/dist/seo.mjs +1079 -0
- package/dist/sitemap.d.mts +63 -0
- package/dist/sitemap.d.ts +63 -0
- package/dist/sitemap.js +353 -0
- package/dist/sitemap.mjs +330 -0
- package/dist/theme.d.mts +63 -0
- package/dist/theme.d.ts +63 -0
- package/dist/theme.js +149 -0
- package/dist/theme.mjs +128 -0
- package/package.json +57 -2
- package/skills/cavuno-board-account/SKILL.md +147 -0
- package/skills/cavuno-board-applications/SKILL.md +110 -0
- package/skills/cavuno-board-blog/SKILL.md +99 -0
- package/skills/cavuno-board-companies/SKILL.md +99 -0
- package/skills/cavuno-board-filters/SKILL.md +89 -0
- package/skills/cavuno-board-format/SKILL.md +104 -0
- package/skills/cavuno-board-job-alerts/SKILL.md +115 -0
- package/skills/cavuno-board-job-posting/SKILL.md +130 -0
- package/skills/cavuno-board-jobs/SKILL.md +15 -0
- package/skills/cavuno-board-messaging/SKILL.md +121 -0
- package/skills/cavuno-board-paywall/SKILL.md +108 -0
- package/skills/cavuno-board-salaries/SKILL.md +87 -0
- package/skills/cavuno-board-seo/SKILL.md +180 -0
- package/skills/cavuno-board-setup/SKILL.md +26 -2
- package/skills/cavuno-board-sitemap/SKILL.md +147 -0
- package/skills/cavuno-board-smoke-test/SKILL.md +84 -0
- package/skills/cavuno-board-theme/SKILL.md +69 -0
- package/skills/manifest.json +106 -1
|
@@ -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 };
|
package/dist/seo.d.mts
ADDED
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import { P as PublicBoard, a as PublicBlogPostSummary, B as BlogAuthorEmbed, C as CompanyCategorySalary, b as CompanySalary, L as LocationSalaryDetail, S as SkillSalaryDetail, T as TitleSalaryDetail } from './salaries-CrJsaZe6.mjs';
|
|
2
|
+
import { P as PublicJob } from './jobs-DK5mPBgq.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Google for Jobs `JobPosting` structured data on the `@cavuno/board` wire
|
|
6
|
+
* types, transcribed field-by-field from the hosted board's generator
|
|
7
|
+
* (`_lib/job-posting-json-ld.ts` + `job-posting-location-json-ld.ts`) and
|
|
8
|
+
* golden-tested against it in-monorepo (ADR-0057).
|
|
9
|
+
*
|
|
10
|
+
* JSON-LD structure is locale-neutral per schema.org — no board-language
|
|
11
|
+
* parameter here; the only display strings are wire values passed through.
|
|
12
|
+
*
|
|
13
|
+
* Named exclusions (hosted behaviours with no wire twin, recorded in the
|
|
14
|
+
* parity ledger):
|
|
15
|
+
* - `board.companyLegalName` — hosted falls back to it for the
|
|
16
|
+
* organization name between `company.name` and `board.name`; the wire
|
|
17
|
+
* board context does not expose it.
|
|
18
|
+
* - `board.companyWebsiteUrl` — hosted falls back to it for `sameAs` when
|
|
19
|
+
* the company has no website; not on the wire.
|
|
20
|
+
* - the hosted `job.place`/`locationLabel` jobLocation fallback (used when
|
|
21
|
+
* a job has no office locations) — the wire `PublicJob` carries no
|
|
22
|
+
* resolved place geo, only `officeLocations`.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
type JsonLdObject = Record<string, unknown>;
|
|
26
|
+
/** The only board fields JSON-LD needs — keeps callers' shapes flexible. */
|
|
27
|
+
type JsonLdBoard = Pick<PublicBoard, 'name' | 'logoUrl'>;
|
|
28
|
+
/**
|
|
29
|
+
* Worldwide-remote jobs must still emit `applicantLocationRequirements`
|
|
30
|
+
* next to TELECOMMUTE (Google requires a location signal), so the hosted
|
|
31
|
+
* board — and this transcription — lists every country it recognises.
|
|
32
|
+
*
|
|
33
|
+
* This is the hosted board's exact country catalog (`@kit/data-remote`
|
|
34
|
+
* `COUNTRIES`, built from `world-countries`): sorted by English common
|
|
35
|
+
* name, includes `XK` (Kosovo), excludes `KP` (North Korea). Golden-tested
|
|
36
|
+
* against the hosted list so the two cannot drift.
|
|
37
|
+
*/
|
|
38
|
+
declare const ALL_COUNTRY_CODES: readonly ["AF", "AX", "AL", "DZ", "AS", "AD", "AO", "AI", "AQ", "AG", "AR", "AM", "AW", "AU", "AT", "AZ", "BS", "BH", "BD", "BB", "BY", "BE", "BZ", "BJ", "BM", "BT", "BO", "BA", "BW", "BV", "BR", "IO", "VG", "BN", "BG", "BF", "BI", "KH", "CM", "CA", "CV", "BQ", "KY", "CF", "TD", "CL", "CN", "CX", "CC", "CO", "KM", "CK", "CR", "HR", "CU", "CW", "CY", "CZ", "DK", "DJ", "DM", "DO", "CD", "EC", "EG", "SV", "GQ", "ER", "EE", "SZ", "ET", "FK", "FO", "FJ", "FI", "FR", "GF", "PF", "TF", "GA", "GM", "GE", "DE", "GH", "GI", "GR", "GL", "GD", "GP", "GU", "GT", "GG", "GN", "GW", "GY", "HT", "HM", "HN", "HK", "HU", "IS", "IN", "ID", "IR", "IQ", "IE", "IM", "IL", "IT", "CI", "JM", "JP", "JE", "JO", "KZ", "KE", "KI", "XK", "KW", "KG", "LA", "LV", "LB", "LS", "LR", "LY", "LI", "LT", "LU", "MO", "MG", "MW", "MY", "MV", "ML", "MT", "MH", "MQ", "MR", "MU", "YT", "MX", "FM", "MD", "MC", "MN", "ME", "MS", "MA", "MZ", "MM", "NA", "NR", "NP", "NL", "NC", "NZ", "NI", "NE", "NG", "NU", "NF", "MK", "MP", "NO", "OM", "PK", "PW", "PS", "PA", "PG", "PY", "PE", "PH", "PN", "PL", "PT", "PR", "QA", "CG", "RE", "RO", "RU", "RW", "BL", "SH", "KN", "LC", "MF", "PM", "VC", "WS", "SM", "ST", "SA", "SN", "RS", "SC", "SL", "SG", "SX", "SK", "SI", "SB", "SO", "ZA", "GS", "KR", "SS", "ES", "LK", "SD", "SR", "SJ", "SE", "CH", "SY", "TW", "TJ", "TZ", "TH", "TL", "TG", "TK", "TO", "TT", "TN", "TR", "TM", "TC", "TV", "UG", "UA", "AE", "GB", "US", "UM", "VI", "UY", "UZ", "VU", "VA", "VE", "VN", "WF", "EH", "YE", "ZM", "ZW"];
|
|
39
|
+
/**
|
|
40
|
+
* Build the Google for Jobs `JobPosting` JSON-LD object for a job detail
|
|
41
|
+
* page, or `null` when nothing renderable remains after pruning. Embed the
|
|
42
|
+
* result in a `<script type="application/ld+json">` tag.
|
|
43
|
+
*/
|
|
44
|
+
declare function createJobPostingJsonLd({ job, board, shareUrl, }: {
|
|
45
|
+
job: PublicJob;
|
|
46
|
+
board: JsonLdBoard;
|
|
47
|
+
shareUrl: string;
|
|
48
|
+
}): JsonLdObject | null;
|
|
49
|
+
/**
|
|
50
|
+
* Prefix `https://` onto scheme-less company websites; `null` for
|
|
51
|
+
* blank input (hosted shape — a whitespace-only website never becomes
|
|
52
|
+
* a bare `https://` `sameAs`).
|
|
53
|
+
*/
|
|
54
|
+
declare function normalizeWebsiteUrl(website: string): string | null;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Blog structured data on the `@cavuno/board` wire types, transcribed from
|
|
58
|
+
* the hosted board's builders (`blog/_lib/server/blog-json-ld.ts`:
|
|
59
|
+
* `createArticleJsonLd` + `createAuthorProfilePageJsonLd`) and golden-tested
|
|
60
|
+
* against them in-monorepo (ADR-0057).
|
|
61
|
+
*
|
|
62
|
+
* JSON-LD structure is locale-neutral — no board-language parameter; every
|
|
63
|
+
* display string is a wire value (or caller copy) passed through.
|
|
64
|
+
*/
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* The post fields the Article builder reads — the detail `PublicBlogPost`
|
|
68
|
+
* satisfies this.
|
|
69
|
+
*/
|
|
70
|
+
type ArticleJsonLdPost = Pick<PublicBlogPostSummary, 'title' | 'customExcerpt' | 'publishedAt' | 'coverUrl' | 'authors'>;
|
|
71
|
+
/**
|
|
72
|
+
* `Article` (+ author/publisher) for a blog post — mirrors the hosted
|
|
73
|
+
* Article JSON-LD.
|
|
74
|
+
*
|
|
75
|
+
* `image` follows the hosted precedence: the post's cover (feature) image
|
|
76
|
+
* first, then `ogImageUrl` — pass your page's OG image URL (hosted passes
|
|
77
|
+
* its generated `/blog/:slug/og` card; OG generation itself is app-owned
|
|
78
|
+
* per ADR-0039).
|
|
79
|
+
*/
|
|
80
|
+
declare function createBlogArticleJsonLd({ post, boardName, permalink, ogImageUrl, }: {
|
|
81
|
+
post: ArticleJsonLdPost;
|
|
82
|
+
boardName: string;
|
|
83
|
+
permalink: string;
|
|
84
|
+
/** Fallback image when the post has no cover, e.g. your generated OG card URL. */
|
|
85
|
+
ogImageUrl?: string | null;
|
|
86
|
+
}): JsonLdObject;
|
|
87
|
+
/**
|
|
88
|
+
* `ProfilePage` for a blog author page — the hosted shape: a `Person` main
|
|
89
|
+
* entity (id-anchored at `#profile`, social links normalized into `sameAs`),
|
|
90
|
+
* the author's recent posts as `hasPart` Articles, and a WriteAction
|
|
91
|
+
* `InteractionCounter` for the post count.
|
|
92
|
+
*
|
|
93
|
+
* Returns `null` when the author has no name. `hasPart` URLs assume the
|
|
94
|
+
* `/blog/:slug` post route (the hosted and starter convention).
|
|
95
|
+
*/
|
|
96
|
+
declare function createAuthorProfileJsonLd({ author, canonical, description, origin, posts, totalPosts, }: {
|
|
97
|
+
author: BlogAuthorEmbed;
|
|
98
|
+
/** Absolute canonical URL of the author page. */
|
|
99
|
+
canonical: string;
|
|
100
|
+
/** Author blurb — hosted passes the bio (or its templated hero copy). */
|
|
101
|
+
description: string;
|
|
102
|
+
/** Site origin for `hasPart` post URLs; `null` omits the posts. */
|
|
103
|
+
origin: string | null;
|
|
104
|
+
/** The author's recent posts (newest first) — the builder keeps the first 5. */
|
|
105
|
+
posts: Pick<PublicBlogPostSummary, 'title' | 'slug' | 'publishedAt'>[];
|
|
106
|
+
totalPosts: number;
|
|
107
|
+
}): JsonLdObject | null;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* `BreadcrumbList` structured data, transcribed from the hosted board's
|
|
111
|
+
* `boards/_lib/server/breadcrumb-json-ld.ts` (`createBreadcrumbListJsonLd`)
|
|
112
|
+
* and golden-tested against it in-monorepo (ADR-0057).
|
|
113
|
+
*
|
|
114
|
+
* The hosted builder resolves relative hrefs against the board's canonical
|
|
115
|
+
* origin (custom domain aware, db-backed); this transcription takes the
|
|
116
|
+
* origin as a plain argument instead — pass absolute hrefs, or provide
|
|
117
|
+
* `options.origin` for relative ones. JSON-LD structure is locale-neutral:
|
|
118
|
+
* the labels are caller copy passed through.
|
|
119
|
+
*/
|
|
120
|
+
|
|
121
|
+
interface BreadcrumbItemInput {
|
|
122
|
+
label: string | null | undefined;
|
|
123
|
+
href?: string | null;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Build a `BreadcrumbList`, hosted semantics: labels are trimmed and empty
|
|
127
|
+
* items dropped; fewer than 2 surviving items → `null` (a single crumb is
|
|
128
|
+
* not a trail); the current page (no `href`) omits `item` per schema.org.
|
|
129
|
+
* Relative hrefs resolve against `options.origin`; without an origin a
|
|
130
|
+
* relative item is omitted (never emit a relative `item` URL).
|
|
131
|
+
*/
|
|
132
|
+
declare function createBreadcrumbJsonLd(items: BreadcrumbItemInput[], options?: {
|
|
133
|
+
origin?: string | null;
|
|
134
|
+
}): JsonLdObject | null;
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Framework-neutral `<head>` + structural JSON-LD builders for jobs-listing
|
|
138
|
+
* pages (ADR-0057). Locale-neutral pass-through: the caller supplies the
|
|
139
|
+
* heading/board copy (title/description COPY is board-SEO-config +
|
|
140
|
+
* localized — a named exclusion; these builders replicate the hosted
|
|
141
|
+
* STRUCTURE: title with result count, canonical, Open Graph, breadcrumb +
|
|
142
|
+
* job `ItemList`).
|
|
143
|
+
*/
|
|
144
|
+
|
|
145
|
+
interface ListingHeadOptions {
|
|
146
|
+
boardName: string;
|
|
147
|
+
origin: string;
|
|
148
|
+
/** Absolute path of THIS page, for canonical / og:url, e.g. `/jobs/robotik`. */
|
|
149
|
+
path: string;
|
|
150
|
+
/** Human heading, e.g. `Robotik jobs in Berlin` or `Jobs`. */
|
|
151
|
+
heading: string;
|
|
152
|
+
/** Result count — prefixed into the title (`N heading`). */
|
|
153
|
+
count?: number;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Meta/link descriptors for a jobs-listing page — title (with result
|
|
157
|
+
* count), meta description, Open Graph, and `<link rel=canonical>`.
|
|
158
|
+
* Framework-neutral: map `meta`/`links` into your head manager.
|
|
159
|
+
*/
|
|
160
|
+
declare function listingHead(options: ListingHeadOptions): {
|
|
161
|
+
meta: ({
|
|
162
|
+
title: string;
|
|
163
|
+
name?: undefined;
|
|
164
|
+
content?: undefined;
|
|
165
|
+
property?: undefined;
|
|
166
|
+
} | {
|
|
167
|
+
name: string;
|
|
168
|
+
content: string;
|
|
169
|
+
title?: undefined;
|
|
170
|
+
property?: undefined;
|
|
171
|
+
} | {
|
|
172
|
+
property: string;
|
|
173
|
+
content: string;
|
|
174
|
+
title?: undefined;
|
|
175
|
+
name?: undefined;
|
|
176
|
+
})[];
|
|
177
|
+
links: {
|
|
178
|
+
rel: string;
|
|
179
|
+
href: string;
|
|
180
|
+
}[];
|
|
181
|
+
};
|
|
182
|
+
interface JobLink {
|
|
183
|
+
slug: string;
|
|
184
|
+
company: {
|
|
185
|
+
slug: string;
|
|
186
|
+
} | null;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* `BreadcrumbList` (+ `ItemList` of the visible jobs) JSON-LD for a listing
|
|
190
|
+
* page, mirroring the structural JSON-LD the hosted board emits. The rich
|
|
191
|
+
* category set (`Occupation`/`FAQPage`/`MonetaryAmountDistribution`) lives
|
|
192
|
+
* in `./salary` — feed it the salary detail reads.
|
|
193
|
+
*/
|
|
194
|
+
declare function listingJsonLd(options: {
|
|
195
|
+
origin: string;
|
|
196
|
+
/** Breadcrumb trail; the current (last) page omits `path` → no `item` (schema.org). */
|
|
197
|
+
breadcrumbs: Array<{
|
|
198
|
+
name: string;
|
|
199
|
+
path?: string;
|
|
200
|
+
}>;
|
|
201
|
+
jobs?: JobLink[];
|
|
202
|
+
}): JsonLdObject[];
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Compact USD amount in the board language (`$90K`, de: `90.000 $`) — the
|
|
206
|
+
* hosted salary-page money formatter. USD-hardcoded (hosted quirk); the
|
|
207
|
+
* locale drives digits, grouping, and symbol placement only.
|
|
208
|
+
*/
|
|
209
|
+
declare function formatUsd(locale: string, value: number): string;
|
|
210
|
+
/** `formatUsd(min) – formatUsd(max)` with the hosted spaced en dash. */
|
|
211
|
+
declare function formatRange(locale: string, min: number, max: number): string;
|
|
212
|
+
/**
|
|
213
|
+
* Seniority display label. Precedence (hosted shape): owner override >
|
|
214
|
+
* board-language lexicon (en = the English source labels) > title-case
|
|
215
|
+
* fallback for an unknown key (CAV-352 / 9b).
|
|
216
|
+
*/
|
|
217
|
+
declare function formatSeniority(locale: string, value: string, overrides?: Record<string, string>): string;
|
|
218
|
+
/** The canonical seniority ladder order the hosted salary pages sort by. */
|
|
219
|
+
declare const SENIORITY_ORDER: readonly ["entry_level", "associate", "mid_level", "senior", "lead", "principal", "director", "executive"];
|
|
220
|
+
/** Sort rows by `SENIORITY_ORDER` (unknown keys sink to the end). Non-mutating. */
|
|
221
|
+
declare function sortBySeniority<T extends {
|
|
222
|
+
seniority: string;
|
|
223
|
+
}>(items: T[]): T[];
|
|
224
|
+
interface FaqItem {
|
|
225
|
+
q: string;
|
|
226
|
+
a: string;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* A templated salary FAQ (interim — see the module doc). The sentences are
|
|
230
|
+
* English; the embedded range is board-language-formatted via `formatRange`
|
|
231
|
+
* (the only part hosted localizes). Empty when there is no overall figure.
|
|
232
|
+
*/
|
|
233
|
+
declare function buildSalaryFaq(locale: string, label: string, overall: {
|
|
234
|
+
avgMin: number;
|
|
235
|
+
avgMax: number;
|
|
236
|
+
jobCount: number;
|
|
237
|
+
} | null): FaqItem[];
|
|
238
|
+
/** An `ItemList` for a salary index page (the listing's items + their URLs). */
|
|
239
|
+
declare function itemListJsonLd(items: {
|
|
240
|
+
name: string;
|
|
241
|
+
url: string;
|
|
242
|
+
}[]): JsonLdObject | null;
|
|
243
|
+
/** A `FAQPage` from `buildSalaryFaq` items (or any `{q,a}` list). */
|
|
244
|
+
declare function faqJsonLd(faqs: FaqItem[]): JsonLdObject | null;
|
|
245
|
+
/**
|
|
246
|
+
* `Occupation` for a job-title salary page. Per-seniority distribution
|
|
247
|
+
* names embed the board-language seniority label (`formatSeniority`).
|
|
248
|
+
*/
|
|
249
|
+
declare function titleSalaryJsonLd(locale: string, d: TitleSalaryDetail): JsonLdObject | null;
|
|
250
|
+
/** `Occupation` for a skill salary page (overall distribution + median). */
|
|
251
|
+
declare function skillSalaryJsonLd(d: SkillSalaryDetail): JsonLdObject | null;
|
|
252
|
+
/**
|
|
253
|
+
* `Occupation` for a location salary page. City-level pages only (the
|
|
254
|
+
* hosted page gates on city/locality); `null` otherwise.
|
|
255
|
+
*/
|
|
256
|
+
declare function locationSalaryJsonLd(d: LocationSalaryDetail): JsonLdObject | null;
|
|
257
|
+
/**
|
|
258
|
+
* Cross-axis (title×location / skill×location) `Occupation` JSON-LD. Takes
|
|
259
|
+
* primitives to stay decoupled from the two cross-axis detail wire types.
|
|
260
|
+
*/
|
|
261
|
+
declare function crossAxisSalaryJsonLd(locale: string, args: {
|
|
262
|
+
name: string;
|
|
263
|
+
placeName: string;
|
|
264
|
+
countryCode: string;
|
|
265
|
+
overall: {
|
|
266
|
+
avgMin: number;
|
|
267
|
+
avgMax: number;
|
|
268
|
+
p25Min: number | null;
|
|
269
|
+
p75Max: number | null;
|
|
270
|
+
} | null;
|
|
271
|
+
bySeniority: {
|
|
272
|
+
seniority: string;
|
|
273
|
+
avgSalaryMin: number;
|
|
274
|
+
avgSalaryMax: number;
|
|
275
|
+
}[];
|
|
276
|
+
currency: string;
|
|
277
|
+
}): JsonLdObject | null;
|
|
278
|
+
/**
|
|
279
|
+
* `OccupationAggregationByEmployer` for a company's salary overview —
|
|
280
|
+
* mirrors the hosted company-salary page's Google-salary structured data
|
|
281
|
+
* (base + per-seniority distributions, the board median/IQR baseline as
|
|
282
|
+
* the aggregate stats).
|
|
283
|
+
*/
|
|
284
|
+
declare function companySalaryJsonLd(locale: string, d: CompanySalary): JsonLdObject | null;
|
|
285
|
+
/** `Occupation` for one job category at a company (the hosted category page). */
|
|
286
|
+
declare function companyCategorySalaryJsonLd(locale: string, d: CompanyCategorySalary): JsonLdObject | null;
|
|
287
|
+
|
|
288
|
+
export { ALL_COUNTRY_CODES, type ArticleJsonLdPost, type BreadcrumbItemInput, type FaqItem, type JsonLdBoard, type JsonLdObject, type ListingHeadOptions, SENIORITY_ORDER, buildSalaryFaq, companyCategorySalaryJsonLd, companySalaryJsonLd, createAuthorProfileJsonLd, createBlogArticleJsonLd, createBreadcrumbJsonLd, createJobPostingJsonLd, crossAxisSalaryJsonLd, faqJsonLd, formatRange, formatSeniority, formatUsd, itemListJsonLd, listingHead, listingJsonLd, locationSalaryJsonLd, normalizeWebsiteUrl, skillSalaryJsonLd, sortBySeniority, titleSalaryJsonLd };
|