@cavuno/board 3.2.0 → 4.1.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 +433 -0
- package/README.md +6 -2
- package/dist/{_spec-nkWAraS0.d.mts → _spec-BZDv2dc5.d.mts} +100 -68
- package/dist/{_spec-nkWAraS0.d.ts → _spec-BZDv2dc5.d.ts} +100 -68
- package/dist/bin.mjs +7 -2
- package/dist/{blog-iV9XEIGf.d.ts → blog-BHx6iH3Z.d.ts} +1 -1
- package/dist/{blog-DGBHmExV.d.mts → blog-DyDvyQrI.d.mts} +1 -1
- package/dist/{board-JhdUWIoq.d.ts → board-BF3Qao6J.d.mts} +7 -6
- package/dist/{board-BJbXd_9_.d.mts → board-BTEZ0uiI.d.ts} +7 -6
- package/dist/breadcrumbs-SGaWth6C.d.ts +372 -0
- package/dist/breadcrumbs-icxRVydh.d.mts +372 -0
- package/dist/chunk-BGKNXG4H.mjs +146 -0
- package/dist/{chunk-NXY3OWGF.mjs → chunk-T2KC6XGV.mjs} +1 -1
- package/dist/{chunk-STE77MAT.mjs → chunk-YEAQ3JEI.mjs} +143 -134
- package/dist/doctor.js +1 -1
- package/dist/doctor.mjs +1 -1
- package/dist/filters.d.mts +25 -20
- package/dist/filters.d.ts +25 -20
- package/dist/filters.js +3 -692
- package/dist/filters.mjs +3 -29
- package/dist/format.d.mts +57 -231
- package/dist/format.d.ts +57 -231
- package/dist/format.js +327 -968
- package/dist/format.mjs +207 -264
- package/dist/go.js +11 -1
- package/dist/go.mjs +1 -1
- package/dist/index.d.mts +67 -76
- package/dist/index.d.ts +67 -76
- package/dist/index.js +45 -36
- package/dist/index.mjs +45 -36
- package/dist/{jobs-BiEvL9d7.d.ts → jobs-BX6d_sdd.d.mts} +4 -4
- package/dist/{jobs-lVvKCBCU.d.mts → jobs-BbLJfz1z.d.ts} +4 -4
- package/dist/paths.d.mts +89 -1
- package/dist/paths.d.ts +89 -1
- package/dist/paths.js +62 -14
- package/dist/paths.mjs +11 -3
- package/dist/route-contract.js +23 -13
- package/dist/route-contract.mjs +2 -2
- package/dist/{search-CCyFWPi3.d.mts → search-7B-mVRNA.d.ts} +14 -3
- package/dist/{search-CyRvVMUp.d.ts → search-OKrdAHv8.d.mts} +14 -3
- package/dist/seo.d.mts +30 -29
- package/dist/seo.d.ts +30 -29
- package/dist/seo.js +197 -718
- package/dist/seo.mjs +26 -24
- package/dist/server.d.mts +5 -5
- package/dist/server.d.ts +5 -5
- package/dist/sitemap.d.mts +5 -5
- package/dist/sitemap.d.ts +5 -5
- package/dist/sitemap.js +25 -14
- package/dist/sitemap.mjs +3 -2
- package/dist/skills.js +1 -1
- package/dist/skills.mjs +1 -1
- package/dist/suggest.d.mts +2 -2
- package/dist/suggest.d.ts +2 -2
- package/dist/suggest.js +17 -3
- package/dist/suggest.mjs +17 -3
- package/dist/well-known.js +23 -13
- package/dist/well-known.mjs +2 -2
- package/package.json +2 -4
- package/skills/cavuno-board-api-client/SKILL.md +42 -0
- package/skills/cavuno-board-applications/SKILL.md +4 -1
- package/skills/cavuno-board-filters/SKILL.md +11 -12
- package/skills/cavuno-board-format/SKILL.md +68 -56
- package/skills/cavuno-board-i18n/SKILL.md +102 -21
- package/skills/cavuno-board-search-suggestions/SKILL.md +8 -3
- package/skills/cavuno-board-seo/BLOG.md +4 -1
- package/skills/cavuno-board-seo/JOB_AND_BREADCRUMBS.md +5 -2
- package/skills/cavuno-board-seo/LISTING.md +35 -12
- package/skills/cavuno-board-seo/SALARY.md +83 -18
- package/skills/cavuno-board-seo/SKILL.md +3 -2
- package/skills/manifest.json +3 -3
- package/dist/breadcrumbs-1hMjcsqA.d.mts +0 -171
- package/dist/breadcrumbs-DexU07TT.d.ts +0 -171
- package/dist/chunk-IJCJ26SQ.mjs +0 -596
- package/dist/chunk-L7ZOYWHW.mjs +0 -98
- package/dist/chunk-LUGJWOT7.mjs +0 -96
- package/dist/ui-copy-CCkz6CVF.d.mts +0 -230
- package/dist/ui-copy-CCkz6CVF.d.ts +0 -230
package/dist/index.js
CHANGED
|
@@ -312,7 +312,7 @@ async function clearSession(storage) {
|
|
|
312
312
|
}
|
|
313
313
|
|
|
314
314
|
// src/version.ts
|
|
315
|
-
var SDK_VERSION = "
|
|
315
|
+
var SDK_VERSION = "4.1.0";
|
|
316
316
|
|
|
317
317
|
// src/client.ts
|
|
318
318
|
function isRawBody(body) {
|
|
@@ -1114,28 +1114,6 @@ function jobsNamespace(client) {
|
|
|
1114
1114
|
};
|
|
1115
1115
|
}
|
|
1116
1116
|
|
|
1117
|
-
// src/namespaces/legal.ts
|
|
1118
|
-
function legalNamespace(client) {
|
|
1119
|
-
return {
|
|
1120
|
-
/**
|
|
1121
|
-
* Retrieve a board legal/about page — owner-authored prose as portable HTML
|
|
1122
|
-
* (`privacy-policy` / `terms-of-service` / `cookie-policy` / `about`) plus,
|
|
1123
|
-
* for `impressum`, structured legal-entity facts. The starter authors the
|
|
1124
|
-
* layout, breadcrumb labels, and JSON-LD. `impressum` throws
|
|
1125
|
-
* `board_page_not_found` (404) when the board has not enabled it.
|
|
1126
|
-
*
|
|
1127
|
-
* @example
|
|
1128
|
-
* const { title, content } = await board.legal.retrieve('privacy-policy');
|
|
1129
|
-
*/
|
|
1130
|
-
retrieve(type, options) {
|
|
1131
|
-
return client.fetch(
|
|
1132
|
-
`/legal/${encodeURIComponent(type)}`,
|
|
1133
|
-
options
|
|
1134
|
-
);
|
|
1135
|
-
}
|
|
1136
|
-
};
|
|
1137
|
-
}
|
|
1138
|
-
|
|
1139
1117
|
// src/namespaces/me.ts
|
|
1140
1118
|
function meNamespace(client) {
|
|
1141
1119
|
return {
|
|
@@ -2347,6 +2325,40 @@ function meNamespace(client) {
|
|
|
2347
2325
|
);
|
|
2348
2326
|
}
|
|
2349
2327
|
},
|
|
2328
|
+
/**
|
|
2329
|
+
* My marketing-email consent.
|
|
2330
|
+
*
|
|
2331
|
+
* Consent is a property of the board user, given at sign-up or from the
|
|
2332
|
+
* board's own settings page. Both surfaces render board-authored
|
|
2333
|
+
* disclosure wording — the API records the decision, never the prose, so
|
|
2334
|
+
* whatever you show beside these calls is what the person agreed to.
|
|
2335
|
+
*/
|
|
2336
|
+
marketingConsent: {
|
|
2337
|
+
/** My consent, or `null` when no decision has ever been recorded. */
|
|
2338
|
+
retrieve(options) {
|
|
2339
|
+
return client.fetch(
|
|
2340
|
+
"/me/marketing-consent",
|
|
2341
|
+
options
|
|
2342
|
+
);
|
|
2343
|
+
},
|
|
2344
|
+
/**
|
|
2345
|
+
* Grant. Call this only from a surface that displayed your disclosure
|
|
2346
|
+
* copy — nothing server-side can check that you did.
|
|
2347
|
+
*/
|
|
2348
|
+
grant(options) {
|
|
2349
|
+
return client.fetch("/me/marketing-consent/grant", {
|
|
2350
|
+
...options,
|
|
2351
|
+
method: "POST"
|
|
2352
|
+
});
|
|
2353
|
+
},
|
|
2354
|
+
/** Withdraw. Repeating it returns the same state, no new event. */
|
|
2355
|
+
withdraw(options) {
|
|
2356
|
+
return client.fetch(
|
|
2357
|
+
"/me/marketing-consent/withdraw",
|
|
2358
|
+
{ ...options, method: "POST" }
|
|
2359
|
+
);
|
|
2360
|
+
}
|
|
2361
|
+
},
|
|
2350
2362
|
/**
|
|
2351
2363
|
* The candidate job-access paywall — the authenticated money flow . Enumerate offers publicly with `board.paywall.offers()`, then
|
|
2352
2364
|
* `checkout` here; poll `retrieveCheckout` until complete and confirm with
|
|
@@ -2621,12 +2633,18 @@ function salariesNamespace(client) {
|
|
|
2621
2633
|
function searchNamespace(client) {
|
|
2622
2634
|
return {
|
|
2623
2635
|
/**
|
|
2624
|
-
* GET /search/suggest — federated keyword suggestions (companies
|
|
2625
|
-
* taxonomy terms), one interleaved server-ranked list.
|
|
2626
|
-
*
|
|
2636
|
+
* GET /search/suggest — federated keyword suggestions (companies,
|
|
2637
|
+
* markets, taxonomy terms), one interleaved server-ranked list. Pass
|
|
2638
|
+
* `types` to restrict kinds; `limit` applies after that filter. Order
|
|
2639
|
+
* is the contract: do not re-sort. Routing is application-side via
|
|
2640
|
+
* `suggestionPath` from `@cavuno/board/paths`.
|
|
2627
2641
|
*
|
|
2628
2642
|
* @example
|
|
2629
|
-
* const { items } = await board.search.suggest({
|
|
2643
|
+
* const { items } = await board.search.suggest({
|
|
2644
|
+
* q: 'acme',
|
|
2645
|
+
* limit: 10,
|
|
2646
|
+
* types: ['company', 'skill'],
|
|
2647
|
+
* });
|
|
2630
2648
|
*/
|
|
2631
2649
|
suggest(query, options) {
|
|
2632
2650
|
return client.fetch("/search/suggest", {
|
|
@@ -2719,14 +2737,6 @@ function taxonomyNamespace(client) {
|
|
|
2719
2737
|
);
|
|
2720
2738
|
}
|
|
2721
2739
|
},
|
|
2722
|
-
suggestions: {
|
|
2723
|
-
list(query, options) {
|
|
2724
|
-
return client.fetch("/suggestions", {
|
|
2725
|
-
...options,
|
|
2726
|
-
query
|
|
2727
|
-
});
|
|
2728
|
-
}
|
|
2729
|
-
},
|
|
2730
2740
|
places: {
|
|
2731
2741
|
...taxonomyResolver(client, "places"),
|
|
2732
2742
|
/**
|
|
@@ -2853,7 +2863,6 @@ function createBoardClient(options) {
|
|
|
2853
2863
|
embed: embedNamespace(client),
|
|
2854
2864
|
companies: companiesNamespace(client),
|
|
2855
2865
|
blog: blogNamespace(client),
|
|
2856
|
-
legal: legalNamespace(client),
|
|
2857
2866
|
auth: authNamespace(client),
|
|
2858
2867
|
me: meNamespace(client),
|
|
2859
2868
|
password: passwordNamespace(client),
|
package/dist/index.mjs
CHANGED
|
@@ -39,7 +39,7 @@ function toSearchParams(query) {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
// src/version.ts
|
|
42
|
-
var SDK_VERSION = "
|
|
42
|
+
var SDK_VERSION = "4.1.0";
|
|
43
43
|
|
|
44
44
|
// src/client.ts
|
|
45
45
|
function isRawBody(body) {
|
|
@@ -841,28 +841,6 @@ function jobsNamespace(client) {
|
|
|
841
841
|
};
|
|
842
842
|
}
|
|
843
843
|
|
|
844
|
-
// src/namespaces/legal.ts
|
|
845
|
-
function legalNamespace(client) {
|
|
846
|
-
return {
|
|
847
|
-
/**
|
|
848
|
-
* Retrieve a board legal/about page — owner-authored prose as portable HTML
|
|
849
|
-
* (`privacy-policy` / `terms-of-service` / `cookie-policy` / `about`) plus,
|
|
850
|
-
* for `impressum`, structured legal-entity facts. The starter authors the
|
|
851
|
-
* layout, breadcrumb labels, and JSON-LD. `impressum` throws
|
|
852
|
-
* `board_page_not_found` (404) when the board has not enabled it.
|
|
853
|
-
*
|
|
854
|
-
* @example
|
|
855
|
-
* const { title, content } = await board.legal.retrieve('privacy-policy');
|
|
856
|
-
*/
|
|
857
|
-
retrieve(type, options) {
|
|
858
|
-
return client.fetch(
|
|
859
|
-
`/legal/${encodeURIComponent(type)}`,
|
|
860
|
-
options
|
|
861
|
-
);
|
|
862
|
-
}
|
|
863
|
-
};
|
|
864
|
-
}
|
|
865
|
-
|
|
866
844
|
// src/namespaces/me.ts
|
|
867
845
|
function meNamespace(client) {
|
|
868
846
|
return {
|
|
@@ -2074,6 +2052,40 @@ function meNamespace(client) {
|
|
|
2074
2052
|
);
|
|
2075
2053
|
}
|
|
2076
2054
|
},
|
|
2055
|
+
/**
|
|
2056
|
+
* My marketing-email consent.
|
|
2057
|
+
*
|
|
2058
|
+
* Consent is a property of the board user, given at sign-up or from the
|
|
2059
|
+
* board's own settings page. Both surfaces render board-authored
|
|
2060
|
+
* disclosure wording — the API records the decision, never the prose, so
|
|
2061
|
+
* whatever you show beside these calls is what the person agreed to.
|
|
2062
|
+
*/
|
|
2063
|
+
marketingConsent: {
|
|
2064
|
+
/** My consent, or `null` when no decision has ever been recorded. */
|
|
2065
|
+
retrieve(options) {
|
|
2066
|
+
return client.fetch(
|
|
2067
|
+
"/me/marketing-consent",
|
|
2068
|
+
options
|
|
2069
|
+
);
|
|
2070
|
+
},
|
|
2071
|
+
/**
|
|
2072
|
+
* Grant. Call this only from a surface that displayed your disclosure
|
|
2073
|
+
* copy — nothing server-side can check that you did.
|
|
2074
|
+
*/
|
|
2075
|
+
grant(options) {
|
|
2076
|
+
return client.fetch("/me/marketing-consent/grant", {
|
|
2077
|
+
...options,
|
|
2078
|
+
method: "POST"
|
|
2079
|
+
});
|
|
2080
|
+
},
|
|
2081
|
+
/** Withdraw. Repeating it returns the same state, no new event. */
|
|
2082
|
+
withdraw(options) {
|
|
2083
|
+
return client.fetch(
|
|
2084
|
+
"/me/marketing-consent/withdraw",
|
|
2085
|
+
{ ...options, method: "POST" }
|
|
2086
|
+
);
|
|
2087
|
+
}
|
|
2088
|
+
},
|
|
2077
2089
|
/**
|
|
2078
2090
|
* The candidate job-access paywall — the authenticated money flow . Enumerate offers publicly with `board.paywall.offers()`, then
|
|
2079
2091
|
* `checkout` here; poll `retrieveCheckout` until complete and confirm with
|
|
@@ -2348,12 +2360,18 @@ function salariesNamespace(client) {
|
|
|
2348
2360
|
function searchNamespace(client) {
|
|
2349
2361
|
return {
|
|
2350
2362
|
/**
|
|
2351
|
-
* GET /search/suggest — federated keyword suggestions (companies
|
|
2352
|
-
* taxonomy terms), one interleaved server-ranked list.
|
|
2353
|
-
*
|
|
2363
|
+
* GET /search/suggest — federated keyword suggestions (companies,
|
|
2364
|
+
* markets, taxonomy terms), one interleaved server-ranked list. Pass
|
|
2365
|
+
* `types` to restrict kinds; `limit` applies after that filter. Order
|
|
2366
|
+
* is the contract: do not re-sort. Routing is application-side via
|
|
2367
|
+
* `suggestionPath` from `@cavuno/board/paths`.
|
|
2354
2368
|
*
|
|
2355
2369
|
* @example
|
|
2356
|
-
* const { items } = await board.search.suggest({
|
|
2370
|
+
* const { items } = await board.search.suggest({
|
|
2371
|
+
* q: 'acme',
|
|
2372
|
+
* limit: 10,
|
|
2373
|
+
* types: ['company', 'skill'],
|
|
2374
|
+
* });
|
|
2357
2375
|
*/
|
|
2358
2376
|
suggest(query, options) {
|
|
2359
2377
|
return client.fetch("/search/suggest", {
|
|
@@ -2446,14 +2464,6 @@ function taxonomyNamespace(client) {
|
|
|
2446
2464
|
);
|
|
2447
2465
|
}
|
|
2448
2466
|
},
|
|
2449
|
-
suggestions: {
|
|
2450
|
-
list(query, options) {
|
|
2451
|
-
return client.fetch("/suggestions", {
|
|
2452
|
-
...options,
|
|
2453
|
-
query
|
|
2454
|
-
});
|
|
2455
|
-
}
|
|
2456
|
-
},
|
|
2457
2467
|
places: {
|
|
2458
2468
|
...taxonomyResolver(client, "places"),
|
|
2459
2469
|
/**
|
|
@@ -2550,7 +2560,6 @@ function createBoardClient(options) {
|
|
|
2550
2560
|
embed: embedNamespace(client),
|
|
2551
2561
|
companies: companiesNamespace(client),
|
|
2552
2562
|
blog: blogNamespace(client),
|
|
2553
|
-
legal: legalNamespace(client),
|
|
2554
2563
|
auth: authNamespace(client),
|
|
2555
2564
|
me: meNamespace(client),
|
|
2556
2565
|
password: passwordNamespace(client),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as Schemas } from './_spec-
|
|
1
|
+
import { S as Schemas } from './_spec-BZDv2dc5.mjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Optional pagination metadata returned by Board API list operations.
|
|
@@ -36,8 +36,8 @@ type PublicJob = Schemas['PublicJob'];
|
|
|
36
36
|
type PublicJobCard = Schemas['PublicJobCard'];
|
|
37
37
|
/**
|
|
38
38
|
* A job's opaque, display-only custom-field values, keyed by each
|
|
39
|
-
* field's `key`. Resolve labels via the board's `CustomFieldDefinition`s
|
|
40
|
-
* (`board.context().customFields`).
|
|
39
|
+
* field's `key`. Resolve labels via the board's job `CustomFieldDefinition`s
|
|
40
|
+
* (`board.context().customFields.job`).
|
|
41
41
|
*/
|
|
42
42
|
type CustomFieldValues = PublicJob['customFieldValues'];
|
|
43
43
|
type CustomFieldValue = CustomFieldValues[string];
|
|
@@ -104,4 +104,4 @@ type JobsSimilarQuery = {
|
|
|
104
104
|
};
|
|
105
105
|
type JobsSearchBody = Schemas['PublicSearchJobsBody'];
|
|
106
106
|
|
|
107
|
-
export type { CustomFieldValues as C, EmploymentType as E, JobSort as J, ListEnvelope as L, OfficeLocation as O, PublicJob as P, RemoteOption as R, Seniority as S,
|
|
107
|
+
export type { CustomFieldValues as C, EmploymentType as E, JobSort as J, ListEnvelope as L, OfficeLocation as O, PublicJob as P, RemoteOption as R, Seniority as S, JobsListQuery as a, JobCardListEnvelope as b, JobsSearchBody as c, JobCardSearchEnvelope as d, JobsSimilarQuery as e, SearchEnvelope as f, CustomFieldValue as g, EducationRequirement as h, JobCatalogPagination as i, JobCompany as j, OffsetPagination as k, PublicJobCard as l, RelatedSearch as m, RemotePermit as n, RemoteTimezone as o, StorefrontPagination as p };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as Schemas } from './_spec-
|
|
1
|
+
import { S as Schemas } from './_spec-BZDv2dc5.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Optional pagination metadata returned by Board API list operations.
|
|
@@ -36,8 +36,8 @@ type PublicJob = Schemas['PublicJob'];
|
|
|
36
36
|
type PublicJobCard = Schemas['PublicJobCard'];
|
|
37
37
|
/**
|
|
38
38
|
* A job's opaque, display-only custom-field values, keyed by each
|
|
39
|
-
* field's `key`. Resolve labels via the board's `CustomFieldDefinition`s
|
|
40
|
-
* (`board.context().customFields`).
|
|
39
|
+
* field's `key`. Resolve labels via the board's job `CustomFieldDefinition`s
|
|
40
|
+
* (`board.context().customFields.job`).
|
|
41
41
|
*/
|
|
42
42
|
type CustomFieldValues = PublicJob['customFieldValues'];
|
|
43
43
|
type CustomFieldValue = CustomFieldValues[string];
|
|
@@ -104,4 +104,4 @@ type JobsSimilarQuery = {
|
|
|
104
104
|
};
|
|
105
105
|
type JobsSearchBody = Schemas['PublicSearchJobsBody'];
|
|
106
106
|
|
|
107
|
-
export type { CustomFieldValues as C, EmploymentType as E, JobSort as J, ListEnvelope as L, OfficeLocation as O, PublicJob as P, RemoteOption as R, Seniority as S,
|
|
107
|
+
export type { CustomFieldValues as C, EmploymentType as E, JobSort as J, ListEnvelope as L, OfficeLocation as O, PublicJob as P, RemoteOption as R, Seniority as S, JobsListQuery as a, JobCardListEnvelope as b, JobsSearchBody as c, JobCardSearchEnvelope as d, JobsSimilarQuery as e, SearchEnvelope as f, CustomFieldValue as g, EducationRequirement as h, JobCatalogPagination as i, JobCompany as j, OffsetPagination as k, PublicJobCard as l, RelatedSearch as m, RemotePermit as n, RemoteTimezone as o, StorefrontPagination as p };
|
package/dist/paths.d.mts
CHANGED
|
@@ -9,11 +9,27 @@
|
|
|
9
9
|
* zero-dependency — safe to import in server runtimes, on the edge,
|
|
10
10
|
* and in the browser.
|
|
11
11
|
*
|
|
12
|
+
* Dynamic path segments are percent-encoded (URI, not bare IRI) so
|
|
13
|
+
* non-Latin board-language slugs (`SuggestionPathInput.canonicalSlug`)
|
|
14
|
+
* are legal in sitemap `<loc>`, canonical/`og:url`, and email links.
|
|
15
|
+
* Separators (`/`) are never encoded; already-encoded input is not
|
|
16
|
+
* double-encoded.
|
|
17
|
+
*
|
|
12
18
|
* These paths mirror the hosted board's indexed URLs exactly (migration
|
|
13
19
|
* parity). Do NOT change a pattern here without updating the hosted board
|
|
14
20
|
* and the sitemap golden tests in lockstep — the structure is a locked
|
|
15
21
|
* cross-surface contract.
|
|
16
22
|
*/
|
|
23
|
+
/**
|
|
24
|
+
* Percent-encode one path segment for use in a URL path.
|
|
25
|
+
* Round-trips already-encoded input so `%E6…` is not double-encoded.
|
|
26
|
+
* Does not touch path separators — callers encode segments only.
|
|
27
|
+
*
|
|
28
|
+
* `:` is left unencoded so route-contract / well-known templates built via
|
|
29
|
+
* `jobDetailPath(':companySlug', ':jobSlug')` stay RFC-6570-style. Real
|
|
30
|
+
* board slugs are alphanumeric-plus-hyphen; non-ASCII is still encoded.
|
|
31
|
+
*/
|
|
32
|
+
declare function encodePathSegment(segment: string): string;
|
|
17
33
|
/** Job detail — the canonical, indexed job URL. Requires BOTH slugs. */
|
|
18
34
|
declare function jobDetailPath(companySlug: string, jobSlug: string): string;
|
|
19
35
|
/** Category (keyword) job listing. */
|
|
@@ -22,10 +38,81 @@ declare function jobsCategoryPath(categorySlug: string): string;
|
|
|
22
38
|
declare function jobsSkillPath(skillSlug: string): string;
|
|
23
39
|
/** Location job listing. */
|
|
24
40
|
declare function jobsLocationPath(placeSlug: string): string;
|
|
41
|
+
/**
|
|
42
|
+
* Location + category combination job listing
|
|
43
|
+
* (`/jobs/locations/<place>/<category>`).
|
|
44
|
+
*/
|
|
45
|
+
declare function jobsLocationCategoryPath(placeSlug: string, categorySlug: string): string;
|
|
46
|
+
/**
|
|
47
|
+
* Location + skill combination job listing
|
|
48
|
+
* (`/jobs/locations/<place>/skills/<skill>`).
|
|
49
|
+
*/
|
|
50
|
+
declare function jobsLocationSkillPath(placeSlug: string, skillSlug: string): string;
|
|
25
51
|
/** Company profile. */
|
|
26
52
|
declare function companyPath(companySlug: string): string;
|
|
27
53
|
/** Company market (sector) listing. */
|
|
28
54
|
declare function companyMarketPath(marketSlug: string): string;
|
|
55
|
+
/**
|
|
56
|
+
* Suggestion kinds `suggestionPath` understands. Mirrors the wire
|
|
57
|
+
* `SuggestionItem` discriminators (and `termType` for terms) without
|
|
58
|
+
* importing generated OpenAPI types into the paths entry.
|
|
59
|
+
*/
|
|
60
|
+
type SuggestionPathInput = {
|
|
61
|
+
type: 'company';
|
|
62
|
+
slug: string;
|
|
63
|
+
} | {
|
|
64
|
+
type: 'market';
|
|
65
|
+
slug: string;
|
|
66
|
+
} | {
|
|
67
|
+
type: 'post';
|
|
68
|
+
slug: string;
|
|
69
|
+
} | {
|
|
70
|
+
type: 'tag';
|
|
71
|
+
slug: string;
|
|
72
|
+
} | {
|
|
73
|
+
type: 'term';
|
|
74
|
+
termType: 'category' | 'skill';
|
|
75
|
+
/** Board-language URL slug — use `canonicalSlug` from the wire item. */
|
|
76
|
+
canonicalSlug: string;
|
|
77
|
+
};
|
|
78
|
+
/** Search scopes that own different destinations for the same suggestion. */
|
|
79
|
+
type SuggestionPathScope = 'jobs' | 'companies' | 'blog';
|
|
80
|
+
type SuggestionPathOptions = {
|
|
81
|
+
scope: SuggestionPathScope;
|
|
82
|
+
/**
|
|
83
|
+
* Active place slug. When set on the `jobs` scope with a category or
|
|
84
|
+
* skill term, routes into the location combination pages.
|
|
85
|
+
*/
|
|
86
|
+
location?: string;
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Resolve a suggestion to a board-relative path for the given search scope
|
|
90
|
+
* The API never returns an `href` because the same
|
|
91
|
+
* `CompanySuggestion` means "navigate to the company page" under companies
|
|
92
|
+
* scope and "apply a `companySlug` filter" under jobs scope — only the app
|
|
93
|
+
* knows which.
|
|
94
|
+
*
|
|
95
|
+
* Returns `null` when the selection is not a navigation (jobs-scope company
|
|
96
|
+
* → filter, or a kind that has no path under the active scope). Compose from
|
|
97
|
+
* the existing `*Path` helpers; never string-build at the call site.
|
|
98
|
+
*
|
|
99
|
+
* | scope | suggestion | result |
|
|
100
|
+
* | --- | --- | --- |
|
|
101
|
+
* | jobs | skill | `/jobs/skills/<slug>` |
|
|
102
|
+
* | jobs | category | `/jobs/<slug>` |
|
|
103
|
+
* | jobs | skill + location | `/jobs/locations/<loc>/skills/<slug>` |
|
|
104
|
+
* | jobs | category + location | `/jobs/locations/<loc>/<slug>` |
|
|
105
|
+
* | jobs | company | `null` (apply `companySlug` filter) |
|
|
106
|
+
* | jobs | market | `null` |
|
|
107
|
+
* | jobs | post / tag | `null` |
|
|
108
|
+
* | companies | company | `/companies/<slug>` |
|
|
109
|
+
* | companies | market | `/companies/markets/<slug>` |
|
|
110
|
+
* | companies | term / post / tag | `null` |
|
|
111
|
+
* | blog | post | `/blog/<slug>` |
|
|
112
|
+
* | blog | tag | `/blog/tag/<slug>` |
|
|
113
|
+
* | blog | other | `null` |
|
|
114
|
+
*/
|
|
115
|
+
declare function suggestionPath(suggestion: SuggestionPathInput, options: SuggestionPathOptions): string | null;
|
|
29
116
|
/** A company's salary overview. */
|
|
30
117
|
declare function companySalaryPath(companySlug: string): string;
|
|
31
118
|
/** Salary page for a job title. */
|
|
@@ -90,7 +177,8 @@ declare function goAlertsConfirmPath(): string;
|
|
|
90
177
|
/**
|
|
91
178
|
* Prefix a board-relative path with the board origin. A trailing slash on
|
|
92
179
|
* the origin is tolerated (stripped) so callers need not normalise first.
|
|
180
|
+
* Paths from `*Path` helpers already percent-encode dynamic segments.
|
|
93
181
|
*/
|
|
94
182
|
declare function boardUrl(origin: string, path: string): string;
|
|
95
183
|
|
|
96
|
-
export { BOARD_PATHS, blogAuthorPath, blogPostPath, blogTagPath, boardUrl, companyMarketPath, companyPath, companySalaryPath, goAlertsConfirmPath, goAlertsManagePath, goJobPath, jobDetailPath, jobsCategoryPath, jobsLocationPath, jobsSkillPath, salaryLocationPath, salarySkillPath, salaryTitlePath };
|
|
184
|
+
export { BOARD_PATHS, type SuggestionPathInput, type SuggestionPathOptions, type SuggestionPathScope, blogAuthorPath, blogPostPath, blogTagPath, boardUrl, companyMarketPath, companyPath, companySalaryPath, encodePathSegment, goAlertsConfirmPath, goAlertsManagePath, goJobPath, jobDetailPath, jobsCategoryPath, jobsLocationCategoryPath, jobsLocationPath, jobsLocationSkillPath, jobsSkillPath, salaryLocationPath, salarySkillPath, salaryTitlePath, suggestionPath };
|
package/dist/paths.d.ts
CHANGED
|
@@ -9,11 +9,27 @@
|
|
|
9
9
|
* zero-dependency — safe to import in server runtimes, on the edge,
|
|
10
10
|
* and in the browser.
|
|
11
11
|
*
|
|
12
|
+
* Dynamic path segments are percent-encoded (URI, not bare IRI) so
|
|
13
|
+
* non-Latin board-language slugs (`SuggestionPathInput.canonicalSlug`)
|
|
14
|
+
* are legal in sitemap `<loc>`, canonical/`og:url`, and email links.
|
|
15
|
+
* Separators (`/`) are never encoded; already-encoded input is not
|
|
16
|
+
* double-encoded.
|
|
17
|
+
*
|
|
12
18
|
* These paths mirror the hosted board's indexed URLs exactly (migration
|
|
13
19
|
* parity). Do NOT change a pattern here without updating the hosted board
|
|
14
20
|
* and the sitemap golden tests in lockstep — the structure is a locked
|
|
15
21
|
* cross-surface contract.
|
|
16
22
|
*/
|
|
23
|
+
/**
|
|
24
|
+
* Percent-encode one path segment for use in a URL path.
|
|
25
|
+
* Round-trips already-encoded input so `%E6…` is not double-encoded.
|
|
26
|
+
* Does not touch path separators — callers encode segments only.
|
|
27
|
+
*
|
|
28
|
+
* `:` is left unencoded so route-contract / well-known templates built via
|
|
29
|
+
* `jobDetailPath(':companySlug', ':jobSlug')` stay RFC-6570-style. Real
|
|
30
|
+
* board slugs are alphanumeric-plus-hyphen; non-ASCII is still encoded.
|
|
31
|
+
*/
|
|
32
|
+
declare function encodePathSegment(segment: string): string;
|
|
17
33
|
/** Job detail — the canonical, indexed job URL. Requires BOTH slugs. */
|
|
18
34
|
declare function jobDetailPath(companySlug: string, jobSlug: string): string;
|
|
19
35
|
/** Category (keyword) job listing. */
|
|
@@ -22,10 +38,81 @@ declare function jobsCategoryPath(categorySlug: string): string;
|
|
|
22
38
|
declare function jobsSkillPath(skillSlug: string): string;
|
|
23
39
|
/** Location job listing. */
|
|
24
40
|
declare function jobsLocationPath(placeSlug: string): string;
|
|
41
|
+
/**
|
|
42
|
+
* Location + category combination job listing
|
|
43
|
+
* (`/jobs/locations/<place>/<category>`).
|
|
44
|
+
*/
|
|
45
|
+
declare function jobsLocationCategoryPath(placeSlug: string, categorySlug: string): string;
|
|
46
|
+
/**
|
|
47
|
+
* Location + skill combination job listing
|
|
48
|
+
* (`/jobs/locations/<place>/skills/<skill>`).
|
|
49
|
+
*/
|
|
50
|
+
declare function jobsLocationSkillPath(placeSlug: string, skillSlug: string): string;
|
|
25
51
|
/** Company profile. */
|
|
26
52
|
declare function companyPath(companySlug: string): string;
|
|
27
53
|
/** Company market (sector) listing. */
|
|
28
54
|
declare function companyMarketPath(marketSlug: string): string;
|
|
55
|
+
/**
|
|
56
|
+
* Suggestion kinds `suggestionPath` understands. Mirrors the wire
|
|
57
|
+
* `SuggestionItem` discriminators (and `termType` for terms) without
|
|
58
|
+
* importing generated OpenAPI types into the paths entry.
|
|
59
|
+
*/
|
|
60
|
+
type SuggestionPathInput = {
|
|
61
|
+
type: 'company';
|
|
62
|
+
slug: string;
|
|
63
|
+
} | {
|
|
64
|
+
type: 'market';
|
|
65
|
+
slug: string;
|
|
66
|
+
} | {
|
|
67
|
+
type: 'post';
|
|
68
|
+
slug: string;
|
|
69
|
+
} | {
|
|
70
|
+
type: 'tag';
|
|
71
|
+
slug: string;
|
|
72
|
+
} | {
|
|
73
|
+
type: 'term';
|
|
74
|
+
termType: 'category' | 'skill';
|
|
75
|
+
/** Board-language URL slug — use `canonicalSlug` from the wire item. */
|
|
76
|
+
canonicalSlug: string;
|
|
77
|
+
};
|
|
78
|
+
/** Search scopes that own different destinations for the same suggestion. */
|
|
79
|
+
type SuggestionPathScope = 'jobs' | 'companies' | 'blog';
|
|
80
|
+
type SuggestionPathOptions = {
|
|
81
|
+
scope: SuggestionPathScope;
|
|
82
|
+
/**
|
|
83
|
+
* Active place slug. When set on the `jobs` scope with a category or
|
|
84
|
+
* skill term, routes into the location combination pages.
|
|
85
|
+
*/
|
|
86
|
+
location?: string;
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Resolve a suggestion to a board-relative path for the given search scope
|
|
90
|
+
* The API never returns an `href` because the same
|
|
91
|
+
* `CompanySuggestion` means "navigate to the company page" under companies
|
|
92
|
+
* scope and "apply a `companySlug` filter" under jobs scope — only the app
|
|
93
|
+
* knows which.
|
|
94
|
+
*
|
|
95
|
+
* Returns `null` when the selection is not a navigation (jobs-scope company
|
|
96
|
+
* → filter, or a kind that has no path under the active scope). Compose from
|
|
97
|
+
* the existing `*Path` helpers; never string-build at the call site.
|
|
98
|
+
*
|
|
99
|
+
* | scope | suggestion | result |
|
|
100
|
+
* | --- | --- | --- |
|
|
101
|
+
* | jobs | skill | `/jobs/skills/<slug>` |
|
|
102
|
+
* | jobs | category | `/jobs/<slug>` |
|
|
103
|
+
* | jobs | skill + location | `/jobs/locations/<loc>/skills/<slug>` |
|
|
104
|
+
* | jobs | category + location | `/jobs/locations/<loc>/<slug>` |
|
|
105
|
+
* | jobs | company | `null` (apply `companySlug` filter) |
|
|
106
|
+
* | jobs | market | `null` |
|
|
107
|
+
* | jobs | post / tag | `null` |
|
|
108
|
+
* | companies | company | `/companies/<slug>` |
|
|
109
|
+
* | companies | market | `/companies/markets/<slug>` |
|
|
110
|
+
* | companies | term / post / tag | `null` |
|
|
111
|
+
* | blog | post | `/blog/<slug>` |
|
|
112
|
+
* | blog | tag | `/blog/tag/<slug>` |
|
|
113
|
+
* | blog | other | `null` |
|
|
114
|
+
*/
|
|
115
|
+
declare function suggestionPath(suggestion: SuggestionPathInput, options: SuggestionPathOptions): string | null;
|
|
29
116
|
/** A company's salary overview. */
|
|
30
117
|
declare function companySalaryPath(companySlug: string): string;
|
|
31
118
|
/** Salary page for a job title. */
|
|
@@ -90,7 +177,8 @@ declare function goAlertsConfirmPath(): string;
|
|
|
90
177
|
/**
|
|
91
178
|
* Prefix a board-relative path with the board origin. A trailing slash on
|
|
92
179
|
* the origin is tolerated (stripped) so callers need not normalise first.
|
|
180
|
+
* Paths from `*Path` helpers already percent-encode dynamic segments.
|
|
93
181
|
*/
|
|
94
182
|
declare function boardUrl(origin: string, path: string): string;
|
|
95
183
|
|
|
96
|
-
export { BOARD_PATHS, blogAuthorPath, blogPostPath, blogTagPath, boardUrl, companyMarketPath, companyPath, companySalaryPath, goAlertsConfirmPath, goAlertsManagePath, goJobPath, jobDetailPath, jobsCategoryPath, jobsLocationPath, jobsSkillPath, salaryLocationPath, salarySkillPath, salaryTitlePath };
|
|
184
|
+
export { BOARD_PATHS, type SuggestionPathInput, type SuggestionPathOptions, type SuggestionPathScope, blogAuthorPath, blogPostPath, blogTagPath, boardUrl, companyMarketPath, companyPath, companySalaryPath, encodePathSegment, goAlertsConfirmPath, goAlertsManagePath, goJobPath, jobDetailPath, jobsCategoryPath, jobsLocationCategoryPath, jobsLocationPath, jobsLocationSkillPath, jobsSkillPath, salaryLocationPath, salarySkillPath, salaryTitlePath, suggestionPath };
|
package/dist/paths.js
CHANGED
|
@@ -28,56 +28,104 @@ __export(paths_exports, {
|
|
|
28
28
|
companyMarketPath: () => companyMarketPath,
|
|
29
29
|
companyPath: () => companyPath,
|
|
30
30
|
companySalaryPath: () => companySalaryPath,
|
|
31
|
+
encodePathSegment: () => encodePathSegment,
|
|
31
32
|
goAlertsConfirmPath: () => goAlertsConfirmPath,
|
|
32
33
|
goAlertsManagePath: () => goAlertsManagePath,
|
|
33
34
|
goJobPath: () => goJobPath,
|
|
34
35
|
jobDetailPath: () => jobDetailPath,
|
|
35
36
|
jobsCategoryPath: () => jobsCategoryPath,
|
|
37
|
+
jobsLocationCategoryPath: () => jobsLocationCategoryPath,
|
|
36
38
|
jobsLocationPath: () => jobsLocationPath,
|
|
39
|
+
jobsLocationSkillPath: () => jobsLocationSkillPath,
|
|
37
40
|
jobsSkillPath: () => jobsSkillPath,
|
|
38
41
|
salaryLocationPath: () => salaryLocationPath,
|
|
39
42
|
salarySkillPath: () => salarySkillPath,
|
|
40
|
-
salaryTitlePath: () => salaryTitlePath
|
|
43
|
+
salaryTitlePath: () => salaryTitlePath,
|
|
44
|
+
suggestionPath: () => suggestionPath
|
|
41
45
|
});
|
|
42
46
|
module.exports = __toCommonJS(paths_exports);
|
|
47
|
+
function encodePathSegment(segment) {
|
|
48
|
+
try {
|
|
49
|
+
return encodeURIComponent(decodeURIComponent(segment)).replace(
|
|
50
|
+
/%3A/gi,
|
|
51
|
+
":"
|
|
52
|
+
);
|
|
53
|
+
} catch {
|
|
54
|
+
return encodeURIComponent(segment).replace(/%3A/gi, ":");
|
|
55
|
+
}
|
|
56
|
+
}
|
|
43
57
|
function jobDetailPath(companySlug, jobSlug) {
|
|
44
|
-
return `/companies/${companySlug}/jobs/${jobSlug}`;
|
|
58
|
+
return `/companies/${encodePathSegment(companySlug)}/jobs/${encodePathSegment(jobSlug)}`;
|
|
45
59
|
}
|
|
46
60
|
function jobsCategoryPath(categorySlug) {
|
|
47
|
-
return `/jobs/${categorySlug}`;
|
|
61
|
+
return `/jobs/${encodePathSegment(categorySlug)}`;
|
|
48
62
|
}
|
|
49
63
|
function jobsSkillPath(skillSlug) {
|
|
50
|
-
return `/jobs/skills/${skillSlug}`;
|
|
64
|
+
return `/jobs/skills/${encodePathSegment(skillSlug)}`;
|
|
51
65
|
}
|
|
52
66
|
function jobsLocationPath(placeSlug) {
|
|
53
|
-
return `/jobs/locations/${placeSlug}`;
|
|
67
|
+
return `/jobs/locations/${encodePathSegment(placeSlug)}`;
|
|
68
|
+
}
|
|
69
|
+
function jobsLocationCategoryPath(placeSlug, categorySlug) {
|
|
70
|
+
return `${jobsLocationPath(placeSlug)}/${encodePathSegment(categorySlug)}`;
|
|
71
|
+
}
|
|
72
|
+
function jobsLocationSkillPath(placeSlug, skillSlug) {
|
|
73
|
+
return `${jobsLocationPath(placeSlug)}/skills/${encodePathSegment(skillSlug)}`;
|
|
54
74
|
}
|
|
55
75
|
function companyPath(companySlug) {
|
|
56
|
-
return `/companies/${companySlug}`;
|
|
76
|
+
return `/companies/${encodePathSegment(companySlug)}`;
|
|
57
77
|
}
|
|
58
78
|
function companyMarketPath(marketSlug) {
|
|
59
|
-
return `/companies/markets/${marketSlug}`;
|
|
79
|
+
return `/companies/markets/${encodePathSegment(marketSlug)}`;
|
|
80
|
+
}
|
|
81
|
+
function suggestionPath(suggestion, options) {
|
|
82
|
+
const location = options.location?.trim() || void 0;
|
|
83
|
+
if (options.scope === "blog") {
|
|
84
|
+
if (suggestion.type === "post") {
|
|
85
|
+
return blogPostPath(suggestion.slug);
|
|
86
|
+
}
|
|
87
|
+
if (suggestion.type === "tag") {
|
|
88
|
+
return blogTagPath(suggestion.slug);
|
|
89
|
+
}
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
if (options.scope === "jobs") {
|
|
93
|
+
if (suggestion.type === "company" || suggestion.type === "market" || suggestion.type === "post" || suggestion.type === "tag") {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
if (suggestion.termType === "skill") {
|
|
97
|
+
return location ? jobsLocationSkillPath(location, suggestion.canonicalSlug) : jobsSkillPath(suggestion.canonicalSlug);
|
|
98
|
+
}
|
|
99
|
+
return location ? jobsLocationCategoryPath(location, suggestion.canonicalSlug) : jobsCategoryPath(suggestion.canonicalSlug);
|
|
100
|
+
}
|
|
101
|
+
if (suggestion.type === "company") {
|
|
102
|
+
return companyPath(suggestion.slug);
|
|
103
|
+
}
|
|
104
|
+
if (suggestion.type === "market") {
|
|
105
|
+
return companyMarketPath(suggestion.slug);
|
|
106
|
+
}
|
|
107
|
+
return null;
|
|
60
108
|
}
|
|
61
109
|
function companySalaryPath(companySlug) {
|
|
62
|
-
return `/companies/${companySlug}/salaries`;
|
|
110
|
+
return `/companies/${encodePathSegment(companySlug)}/salaries`;
|
|
63
111
|
}
|
|
64
112
|
function salaryTitlePath(titleSlug) {
|
|
65
|
-
return `/salaries/titles/${titleSlug}`;
|
|
113
|
+
return `/salaries/titles/${encodePathSegment(titleSlug)}`;
|
|
66
114
|
}
|
|
67
115
|
function salarySkillPath(skillSlug) {
|
|
68
|
-
return `/salaries/skills/${skillSlug}`;
|
|
116
|
+
return `/salaries/skills/${encodePathSegment(skillSlug)}`;
|
|
69
117
|
}
|
|
70
118
|
function salaryLocationPath(placeSlug) {
|
|
71
|
-
return `/salaries/locations/${placeSlug}`;
|
|
119
|
+
return `/salaries/locations/${encodePathSegment(placeSlug)}`;
|
|
72
120
|
}
|
|
73
121
|
function blogPostPath(postSlug) {
|
|
74
|
-
return `/blog/${postSlug}`;
|
|
122
|
+
return `/blog/${encodePathSegment(postSlug)}`;
|
|
75
123
|
}
|
|
76
124
|
function blogTagPath(tagSlug) {
|
|
77
|
-
return `/blog/tag/${tagSlug}`;
|
|
125
|
+
return `/blog/tag/${encodePathSegment(tagSlug)}`;
|
|
78
126
|
}
|
|
79
127
|
function blogAuthorPath(authorSlug) {
|
|
80
|
-
return `/blog/author/${authorSlug}`;
|
|
128
|
+
return `/blog/author/${encodePathSegment(authorSlug)}`;
|
|
81
129
|
}
|
|
82
130
|
var BOARD_PATHS = {
|
|
83
131
|
home: "/",
|