@se-studio/contentful-rest-api 1.1.2 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/README.md +7 -1
  3. package/dist/api/context.d.ts.map +1 -1
  4. package/dist/api/context.js +2 -0
  5. package/dist/api/context.js.map +1 -1
  6. package/dist/api/index.d.ts +2 -0
  7. package/dist/api/index.d.ts.map +1 -1
  8. package/dist/api/index.js +2 -0
  9. package/dist/api/index.js.map +1 -1
  10. package/dist/api/redirects.d.ts +16 -0
  11. package/dist/api/redirects.d.ts.map +1 -0
  12. package/dist/api/redirects.js +106 -0
  13. package/dist/api/redirects.js.map +1 -0
  14. package/dist/api/related-articles.d.ts +6 -1
  15. package/dist/api/related-articles.d.ts.map +1 -1
  16. package/dist/api/related-articles.js +66 -19
  17. package/dist/api/related-articles.js.map +1 -1
  18. package/dist/api/types.d.ts +15 -3
  19. package/dist/api/types.d.ts.map +1 -1
  20. package/dist/baseTypes/baseRedirect.d.ts +126 -0
  21. package/dist/baseTypes/baseRedirect.d.ts.map +1 -0
  22. package/dist/baseTypes/baseRedirect.js +2 -0
  23. package/dist/baseTypes/baseRedirect.js.map +1 -0
  24. package/dist/converters/helpers.d.ts +1 -0
  25. package/dist/converters/helpers.d.ts.map +1 -1
  26. package/dist/converters/helpers.js.map +1 -1
  27. package/dist/converters/index.d.ts +1 -0
  28. package/dist/converters/index.d.ts.map +1 -1
  29. package/dist/converters/index.js +1 -0
  30. package/dist/converters/index.js.map +1 -1
  31. package/dist/converters/redirect.d.ts +20 -0
  32. package/dist/converters/redirect.d.ts.map +1 -0
  33. package/dist/converters/redirect.js +103 -0
  34. package/dist/converters/redirect.js.map +1 -0
  35. package/dist/index.d.ts +2 -1
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +2 -1
  38. package/dist/index.js.map +1 -1
  39. package/dist/revalidation/handlers.d.ts.map +1 -1
  40. package/dist/revalidation/handlers.js +6 -1
  41. package/dist/revalidation/handlers.js.map +1 -1
  42. package/dist/revalidation/tags.d.ts +6 -0
  43. package/dist/revalidation/tags.d.ts.map +1 -1
  44. package/dist/revalidation/tags.js +9 -0
  45. package/dist/revalidation/tags.js.map +1 -1
  46. package/dist/utils/redirectMap.d.ts +25 -0
  47. package/dist/utils/redirectMap.d.ts.map +1 -0
  48. package/dist/utils/redirectMap.js +39 -0
  49. package/dist/utils/redirectMap.js.map +1 -0
  50. package/docs/llms.md +9 -3
  51. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,73 @@
1
1
  # @se-studio/contentful-rest-api
2
2
 
3
+ ## 1.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 31b2200: Add first-class support for managing redirects from Contentful.
8
+
9
+ Editors can now create `redirect` entries (via new content type) using reference pickers for existing Pages/Articles/etc. (for "from" and "to") or raw paths/URLs, plus a status code dropdown (301/302/etc.), active flag, and notes. This makes redirects easy for non-technical users without requiring them to know or type exact slugs.
10
+
11
+ Redirects use the simple rebuild pattern (already proven by A/B tests):
12
+
13
+ - Publish in Contentful → webhook triggers a Vercel Deploy Hook.
14
+ - Build fetches current published redirects (via `getRedirectsWithErrors` / `getRedirectMap` on the helpers from `createAppHelpers`) and bakes a static map (using the new pure `buildRedirectMap`).
15
+ - Middleware performs exact (or lightly normalized) lookups against the baked data with zero runtime cost or external calls.
16
+
17
+ Key additions:
18
+
19
+ - `IRedirect` type + `isRedirect` guard.
20
+ - `BaseRedirectSkeleton`, `baseRedirectConverter` (resolves reference links to concrete `fromPath`/`to` using existing `resolveLink` + project `urlCalculators`).
21
+ - `contentfulRedirectsRest`, revalidation `RedirectTag`, and `buildRedirectMap` / `RedirectMap` types (exported from `@se-studio/contentful-rest-api`).
22
+ - `getRedirectsWithErrors` and `getRedirectMap` (convenience) exposed additively via `createAppHelpers` (like banners).
23
+ - Two Contentful migration scripts: `18-create-redirect-content-type.js` (full CT with rich help text for the picker UX) and `19-remove-redirectTo-fields.js` (cleans up legacy per-page `redirectTo` fields on page/pageVariant).
24
+ - New `@se-studio/skills` entry `se-marketing-sites-redirects` (the canonical guide, including CT spec, migration instructions, generate script example, static middleware example + A/B composition, deploy hook webhook setup, testing, and preview notes).
25
+ - Minimal demo in `example-empty` (middleware + `/api/redirects` route exercising the new helpers at runtime for easy local verification; production apps follow the baked recipe in the skill).
26
+ - Light updates to CLAUDE.md, vercel-setup skill, CONTENT_MODEL.md, and related docs.
27
+
28
+ The model and helpers are forward-compatible if a faster (e.g. Edge Config) path is added later. Legacy `redirectTo` fields are left untouched for now (removal is optional via the migration).
29
+
30
+ This is a new feature (minor bumps).
31
+
32
+ ### Patch Changes
33
+
34
+ - Complete support and documentation for filtered full article lists (#51) + fix client boundary regression (#52).
35
+
36
+ - Re-export `filterRelatedArticles` and `RelatedArticlesOptions` **only** from `@se-studio/core-ui/server` (removed from the main barrel). This keeps the primary `@se-studio/core-ui` entry fully client-safe for common imports (`cn`, `TrackedLink`, `AnalyticsProvider`, `Visual`, etc.). The main barrel no longer transitively pulls `'server-only'`.
37
+
38
+ - `getAllArticleLinks(options)` now fully supports the article listing filter fields (`articleTypeSlugs`/`Ids`, `tagSlugs`/`Ids`, `tagType*`, `authorSlugs`/`Ids` + `strictAuthorMatch`, `before`/`after`, `excludeArticleIds`, `count`, `allowUnindexed`) for News Grids, Publications Lists, person-scoped lists, tag filters, etc. The wrapper delegates to the enhanced `filterRelatedArticles` (OR semantics, slug support, strict author mode, distinct tag scoring, etc.).
39
+
40
+ - Added / expanded docs and examples in core-ui and contentful-rest-api READMEs + llms.md, CMS_INFRASTRUCTURE.md, SERVER_CLIENT_BOUNDARIES.md, the `se-marketing-sites-lib-cms-structure` skill (showing the `getAllArticleLinks({ articleTypeSlugs, strictAuthorMatch, ... })` pattern), and this repo's GitHub issues status tracker (new #51 entry + updated upgrade table).
41
+
42
+ - No changes to runtime behavior for existing bare `getAll*Links()` or `getRelated*` callers (sitemaps, search indexing, llms routes, etc. unaffected). Consumers should import filter symbols from the `/server` subpath when using them directly.
43
+
44
+ This finishes the implementation + docs for the DX improvement requested in #51 (reusable core filtering for full article collections instead of per-site `.filter()` shims). The boundary fix prevents the server-only error that appeared in any app importing from core-ui after the initial #51 changes.
45
+
46
+ - Updated dependencies [31b2200]
47
+ - @se-studio/core-data-types@1.2.0
48
+
49
+ ## 1.2.0
50
+
51
+ ### Minor Changes
52
+
53
+ - feat: support slug-based and tag type filtering for related articles (plus strict author matching)
54
+
55
+ **@se-studio/contentful-rest-api**
56
+
57
+ - Extended `RelatedArticlesOptions` and `filterRelatedArticles` with `articleTypeSlugs`, `tagSlugs`, `tagTypeIds`/`tagTypeSlugs`, `authorSlugs`, and `strictAuthorMatch` (OR semantics with the existing ID-based filters).
58
+ - Tag scoring now correctly counts _distinct_ tags (prevents double-counting when the same tag matches via both an ID and a slug).
59
+ - Updated logging and the `@example` in the JSDoc.
60
+
61
+ **@se-studio/core-ui**
62
+
63
+ - Extended `LinkFetchOptions` (used by `getAll*Links` and `FetchHelpers` / `rendererConfig.fetchHelpers`) with the full set of related article filter fields. Added clear JSDoc noting that the article-specific filters only take effect for `getAllArticleLinks`.
64
+ - `createAppHelpers` now wraps `getAllArticleLinks` so that when any filter criteria (IDs or slugs for types/tags/authors/tagTypes, `strictAuthorMatch`, `excludeArticleIds`, `before`/`after`, `count`) are passed, it fetches the base list then runs it through `filterRelatedArticles` (preserving `errors` and correctly handling `allowUnindexed`).
65
+ - Re-exported `RelatedArticlesOptions` and `filterRelatedArticles` from `@se-studio/core-ui` for convenient use in apps.
66
+ - Added comprehensive tests covering the new filter combinations and the `getAllArticleLinks` wrapper integration.
67
+ - Minor hygiene improvements (import ordering per surgical changes guideline, one-line note that internal `getRelatedArticles`/`getRelatedPeople` now benefit from the richer filter).
68
+
69
+ This enables much more flexible "related content" collections and custom article lists directly from `fetchHelpers.getAllArticleLinks(...)` (or the app helpers) without duplicating filtering/ranking logic.
70
+
3
71
  ## 1.1.2
4
72
 
5
73
  ### Patch Changes
package/README.md CHANGED
@@ -653,7 +653,13 @@ export async function generateStaticParams() {
653
653
  - **`contentfulAllPagesRest`** - Fetches all pages from Contentful
654
654
  - **`contentfulAllPageLinks`** - Fetches all page links plus **page variant** links (metadata only), deduped by slug (page wins)
655
655
  - **`contentfulAllArticleLinks`** - Fetches all article links (lightweight metadata only — no full content). Returns `IContentfulArticleLink[]` (extends `IArticleLink`) including `title`, `subtitle`, `date`, `tags`, `articleType`, `featuredImage` (as `visual`), `visuals`, `description`, optional `download`, and optional `summary` (rich text). Used for listing/browsing UIs. Exposed in apps via `getAllArticleLinks` from `createAppHelpers`.
656
- - **`filterRelatedArticles`** - Filters and ranks article links for Related Articles collections. When `tagIds` is set, articles must match at least one tag (OR); articles with more matching tags rank higher. Also supports article type, author scoring, date range, exclusion list, and `indexed` filtering (see `allowUnindexed`). Used by `@se-studio/core-ui` `getRelatedArticles`.
656
+ - **`filterRelatedArticles`** - Filters and ranks article links (used by Related Articles collections *and* full-list helpers). Supports:
657
+ - Article type (ids or `articleTypeSlugs`)
658
+ - Tags (ids or `tagSlugs`; OR match; more matches = higher rank; distinct counting)
659
+ - Tag types (`tagTypeIds` / `tagTypeSlugs`; hard filter)
660
+ - Authors (ids or `authorSlugs`; score boost by default; `strictAuthorMatch: true` turns it into a hard exclude — required for person-scoped News/Pubs lists)
661
+ - Date range (`before` / `after`), `excludeArticleIds`, `count` (undefined = return all), `allowUnindexed`
662
+ Used by `@se-studio/core-ui` `getRelatedArticles` and the `getAllArticleLinks(options)` wrapper. Import from main in server code, or via `@se-studio/core-ui/server`. See `RelatedArticlesOptions` type.
657
663
  - **`getBreadcrumbLookup`** - Fetches a map of path → breadcrumb label for resolving breadcrumb segments from URL paths. Uses same caching as sitemap. Use with `resolveBreadcrumbSegments` from `@se-studio/core-ui`.
658
664
 
659
665
  #### Client Functions
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/api/context.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACV,oBAAoB,EAKpB,cAAc,EACf,MAAM,uBAAuB,CAAC;AAa/B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,0BAA0B,CAAC,cAAc,EAAE,cAAc,GAAG,oBAAoB,CAwC/F"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/api/context.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACV,oBAAoB,EAKpB,cAAc,EACf,MAAM,uBAAuB,CAAC;AAc/B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,0BAA0B,CAAC,cAAc,EAAE,cAAc,GAAG,oBAAoB,CAyC/F"}
@@ -9,6 +9,7 @@ import { baseLinkConverter } from '../converters/link';
9
9
  import { baseNavigationItemConverter } from '../converters/navigationItem';
10
10
  import { basePageConverter, basePageLinkConverter, basePageVariantLinkConverter, } from '../converters/page';
11
11
  import { basePersonConverter, basePersonLinkConverter } from '../converters/person';
12
+ import { baseRedirectConverter } from '../converters/redirect';
12
13
  import { baseTagConverter, baseTagLinkConverter } from '../converters/tag';
13
14
  import { baseTagTypeConverter } from '../converters/tagType';
14
15
  /**
@@ -59,6 +60,7 @@ export function createBaseConverterContext(urlCalculators) {
59
60
  componentResolver: baseComponentConverter,
60
61
  collectionResolver: baseCollectionConverter,
61
62
  bannerResolver: baseBannerConverter,
63
+ redirectResolver: baseRedirectConverter,
62
64
  linkResolver,
63
65
  contentResolver,
64
66
  urlCalculators,
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/api/context.ts"],"names":[],"mappings":"AACA,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,EACxB,4BAA4B,GAC7B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AAChG,OAAO,EAAE,8BAA8B,EAAE,MAAM,iCAAiC,CAAC;AASjF,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,2BAA2B,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,4BAA4B,GAC7B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AACpF,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,0BAA0B,CAAC,cAA8B;IACvE,MAAM,YAAY,GAAoB,IAAI,GAAG,EAAE,CAAC;IAChD,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,qBAA6C,CAAC,CAAC;IACxE,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,wBAA8D,CAAC,CAAC;IAC5F,YAAY,CAAC,GAAG,CACd,aAAa,EACb,4BAAsE,CACvE,CAAC;IACF,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,oBAA4C,CAAC,CAAC;IACtE,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,uBAA4D,CAAC,CAAC;IACzF,YAAY,CAAC,GAAG,CAAC,aAAa,EAAE,4BAAoD,CAAC,CAAC;IACtF,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,iBAAyC,CAAC,CAAC;IACpE,YAAY,CAAC,GAAG,CAAC,YAAY,EAAE,2BAAmD,CAAC,CAAC;IAEpF,MAAM,eAAe,GAAuB,IAAI,GAAG,EAAE,CAAC;IACtD,eAAe,CAAC,GAAG,CAAC,YAAY,EAAE,uBAAkD,CAAC,CAAC;IACtF,eAAe,CAAC,GAAG,CAAC,WAAW,EAAE,sBAAiD,CAAC,CAAC;IACpF,eAAe,CAAC,GAAG,CACjB,mBAAmB,EACnB,8BAAyD,CAC1D,CAAC;IACF,eAAe,CAAC,GAAG,CAAC,eAAe,EAAE,0BAAqD,CAAC,CAAC;IAE5F,OAAO;QACL,YAAY,EAAE,iBAAiB;QAC/B,sBAAsB,EAAE,2BAA2B;QACnD,eAAe,EAAE,oBAAoB;QACrC,mBAAmB,EAAE,wBAAwB;QAC7C,WAAW,EAAE,gBAAgB;QAC7B,eAAe,EAAE,oBAAoB;QACrC,cAAc,EAAE,mBAAmB;QACnC,kBAAkB,EAAE,uBAAuB;QAC3C,iBAAiB,EAAE,sBAAsB;QACzC,kBAAkB,EAAE,uBAAuB;QAC3C,cAAc,EAAE,mBAAmB;QACnC,YAAY;QACZ,eAAe;QACf,cAAc;QACd,WAAW,EAAE,EAAE;KAChB,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/api/context.ts"],"names":[],"mappings":"AACA,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,EACxB,4BAA4B,GAC7B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AAChG,OAAO,EAAE,8BAA8B,EAAE,MAAM,iCAAiC,CAAC;AASjF,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,2BAA2B,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,4BAA4B,GAC7B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AACpF,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,0BAA0B,CAAC,cAA8B;IACvE,MAAM,YAAY,GAAoB,IAAI,GAAG,EAAE,CAAC;IAChD,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,qBAA6C,CAAC,CAAC;IACxE,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,wBAA8D,CAAC,CAAC;IAC5F,YAAY,CAAC,GAAG,CACd,aAAa,EACb,4BAAsE,CACvE,CAAC;IACF,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,oBAA4C,CAAC,CAAC;IACtE,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,uBAA4D,CAAC,CAAC;IACzF,YAAY,CAAC,GAAG,CAAC,aAAa,EAAE,4BAAoD,CAAC,CAAC;IACtF,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,iBAAyC,CAAC,CAAC;IACpE,YAAY,CAAC,GAAG,CAAC,YAAY,EAAE,2BAAmD,CAAC,CAAC;IAEpF,MAAM,eAAe,GAAuB,IAAI,GAAG,EAAE,CAAC;IACtD,eAAe,CAAC,GAAG,CAAC,YAAY,EAAE,uBAAkD,CAAC,CAAC;IACtF,eAAe,CAAC,GAAG,CAAC,WAAW,EAAE,sBAAiD,CAAC,CAAC;IACpF,eAAe,CAAC,GAAG,CACjB,mBAAmB,EACnB,8BAAyD,CAC1D,CAAC;IACF,eAAe,CAAC,GAAG,CAAC,eAAe,EAAE,0BAAqD,CAAC,CAAC;IAE5F,OAAO;QACL,YAAY,EAAE,iBAAiB;QAC/B,sBAAsB,EAAE,2BAA2B;QACnD,eAAe,EAAE,oBAAoB;QACrC,mBAAmB,EAAE,wBAAwB;QAC7C,WAAW,EAAE,gBAAgB;QAC7B,eAAe,EAAE,oBAAoB;QACrC,cAAc,EAAE,mBAAmB;QACnC,kBAAkB,EAAE,uBAAuB;QAC3C,iBAAiB,EAAE,sBAAsB;QACzC,kBAAkB,EAAE,uBAAuB;QAC3C,cAAc,EAAE,mBAAmB;QACnC,gBAAgB,EAAE,qBAAqB;QACvC,YAAY;QACZ,eAAe;QACf,cAAc;QACd,WAAW,EAAE,EAAE;KAChB,CAAC;AACJ,CAAC"}
@@ -4,6 +4,7 @@
4
4
  * Provides type-safe functions for fetching content from Contentful
5
5
  * with support for caching, retry logic, and error handling.
6
6
  */
7
+ export { buildRedirectMap, type RedirectMap, type RedirectMapEntry } from '../utils/redirectMap';
7
8
  export { contentfulArticleRest } from './article';
8
9
  export { type ArticleTypeFetchOptions, contentfulArticleTypeRest } from './article-type';
9
10
  export { contentfulAssetRest, isBrowserViewable, } from './asset';
@@ -17,6 +18,7 @@ export { contentfulAllArticleLinks, contentfulAllArticleTypeLinks, contentfulAll
17
18
  export { contentfulPageRest } from './page';
18
19
  export { contentfulPersonRest, type PersonFetchOptions } from './person';
19
20
  export { getPreviewEntryInfo, type PreviewContentType, type PreviewEntryInfo } from './preview';
21
+ export { contentfulRedirectsRest } from './redirects';
20
22
  export { filterRelatedArticles } from './related-articles';
21
23
  export { contentfulArticleSitemapEntries, contentfulArticleTypeSitemapEntries, contentfulPageSitemapEntries, contentfulPersonSitemapEntries, contentfulTagSitemapEntries, createSitemapProvider, getAllSitemapEntries, } from './sitemap';
22
24
  export { contentfulTagRest, type TagFetchOptions } from './tag';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,KAAK,uBAAuB,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AACzF,OAAO,EACL,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,mBAAmB,GACpB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,KAAK,kBAAkB,EACvB,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,0BAA0B,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAEzD,OAAO,EACL,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,yBAAyB,EACzB,6BAA6B,EAC7B,sBAAsB,EACtB,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,KAAK,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAEzE,OAAO,EAAE,mBAAmB,EAAE,KAAK,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAEhG,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,OAAO,EACL,+BAA+B,EAC/B,mCAAmC,EACnC,4BAA4B,EAC5B,8BAA8B,EAC9B,2BAA2B,EAC3B,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,iBAAiB,EAAE,KAAK,eAAe,EAAE,MAAM,OAAO,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,KAAK,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAC7E,OAAO,EAAE,sBAAsB,EAAE,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAG3E,YAAY,EACV,oBAAoB,EACpB,mBAAmB,EACnB,aAAa,EACb,qBAAqB,EACrB,sBAAsB,EACtB,sBAAsB,EACtB,aAAa,EACb,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,gBAAgB,EAAE,KAAK,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAEjG,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,KAAK,uBAAuB,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AACzF,OAAO,EACL,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,mBAAmB,GACpB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,KAAK,kBAAkB,EACvB,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,0BAA0B,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAEzD,OAAO,EACL,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,yBAAyB,EACzB,6BAA6B,EAC7B,sBAAsB,EACtB,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,KAAK,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAEzE,OAAO,EAAE,mBAAmB,EAAE,KAAK,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAChG,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,OAAO,EACL,+BAA+B,EAC/B,mCAAmC,EACnC,4BAA4B,EAC5B,8BAA8B,EAC9B,2BAA2B,EAC3B,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,iBAAiB,EAAE,KAAK,eAAe,EAAE,MAAM,OAAO,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,KAAK,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAC7E,OAAO,EAAE,sBAAsB,EAAE,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAG3E,YAAY,EACV,oBAAoB,EACpB,mBAAmB,EACnB,aAAa,EACb,qBAAqB,EACrB,sBAAsB,EACtB,sBAAsB,EACtB,aAAa,EACb,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,SAAS,CAAC"}
package/dist/api/index.js CHANGED
@@ -4,6 +4,7 @@
4
4
  * Provides type-safe functions for fetching content from Contentful
5
5
  * with support for caching, retry logic, and error handling.
6
6
  */
7
+ export { buildRedirectMap } from '../utils/redirectMap';
7
8
  // Single entity fetchers
8
9
  export { contentfulArticleRest } from './article';
9
10
  export { contentfulArticleTypeRest } from './article-type';
@@ -22,6 +23,7 @@ export { contentfulPageRest } from './page';
22
23
  export { contentfulPersonRest } from './person';
23
24
  // Preview
24
25
  export { getPreviewEntryInfo } from './preview';
26
+ export { contentfulRedirectsRest } from './redirects';
25
27
  // Related articles
26
28
  export { filterRelatedArticles } from './related-articles';
27
29
  // Sitemap
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,yBAAyB;AACzB,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAgC,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AACzF,OAAO,EACL,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAGL,mBAAmB,GACpB,MAAM,cAAc,CAAC;AACtB,OAAO,EAEL,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,oBAAoB,CAAC;AAC5B,UAAU;AACV,OAAO,EAAE,0BAA0B,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACzD,wDAAwD;AACxD,OAAO,EACL,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,WAAW,CAAC;AACnB,qBAAqB;AACrB,OAAO,EACL,yBAAyB,EACzB,6BAA6B,EAC7B,sBAAsB,EACtB,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAA2B,MAAM,UAAU,CAAC;AACzE,UAAU;AACV,OAAO,EAAE,mBAAmB,EAAkD,MAAM,WAAW,CAAC;AAChG,mBAAmB;AACnB,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,UAAU;AACV,OAAO,EACL,+BAA+B,EAC/B,mCAAmC,EACnC,4BAA4B,EAC5B,8BAA8B,EAC9B,2BAA2B,EAC3B,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,iBAAiB,EAAwB,MAAM,OAAO,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAA4B,MAAM,YAAY,CAAC;AAC7E,OAAO,EAAE,sBAAsB,EAAyB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,gBAAgB,EAA2C,MAAM,sBAAsB,CAAC;AACjG,yBAAyB;AACzB,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAgC,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AACzF,OAAO,EACL,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAGL,mBAAmB,GACpB,MAAM,cAAc,CAAC;AACtB,OAAO,EAEL,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,oBAAoB,CAAC;AAC5B,UAAU;AACV,OAAO,EAAE,0BAA0B,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACzD,wDAAwD;AACxD,OAAO,EACL,iBAAiB,EACjB,uBAAuB,GACxB,MAAM,WAAW,CAAC;AACnB,qBAAqB;AACrB,OAAO,EACL,yBAAyB,EACzB,6BAA6B,EAC7B,sBAAsB,EACtB,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAA2B,MAAM,UAAU,CAAC;AACzE,UAAU;AACV,OAAO,EAAE,mBAAmB,EAAkD,MAAM,WAAW,CAAC;AAChG,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AACtD,mBAAmB;AACnB,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,UAAU;AACV,OAAO,EACL,+BAA+B,EAC/B,mCAAmC,EACnC,4BAA4B,EAC5B,8BAA8B,EAC9B,2BAA2B,EAC3B,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,iBAAiB,EAAwB,MAAM,OAAO,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAA4B,MAAM,YAAY,CAAC;AAC7E,OAAO,EAAE,sBAAsB,EAAyB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { IRedirect } from '@se-studio/core-data-types';
2
+ import type { BaseConverterContext } from '../converters/helpers';
3
+ import type { CmsResponse, ContentfulConfig, FetchOptions } from '../types';
4
+ export { buildRedirectMap, type RedirectMap, type RedirectMapEntry } from '../utils/redirectMap';
5
+ /**
6
+ * Fetches all redirects from Contentful.
7
+ *
8
+ * Returns published redirects (when not in preview). The list is small by design
9
+ * (typically < a few hundred rules) so a full enumeration with pagination is fine.
10
+ *
11
+ * The converter resolves any reference links (fromPage, toArticle, etc.) into
12
+ * concrete fromPath / to strings so callers (build-time bake or future sync)
13
+ * only ever see simple path → target maps.
14
+ */
15
+ export declare function contentfulRedirectsRest(context: BaseConverterContext, config: ContentfulConfig, options: FetchOptions): Promise<CmsResponse<IRedirect[] | null>>;
16
+ //# sourceMappingURL=redirects.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redirects.d.ts","sourceRoot":"","sources":["../../src/api/redirects.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAG5D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAElE,OAAO,KAAK,EAAY,WAAW,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAWtF,OAAO,EAAE,gBAAgB,EAAE,KAAK,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAEjG;;;;;;;;;GASG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,oBAAoB,EAC7B,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,WAAW,CAAC,SAAS,EAAE,GAAG,IAAI,CAAC,CAAC,CAqG1C"}
@@ -0,0 +1,106 @@
1
+ import { getContentfulClient } from '../client';
2
+ import { getCacheTags } from '../revalidation';
3
+ import { withRetry } from '../utils';
4
+ import { convertAllAssets, convertAllIncludes, convertAllRawAssets, } from './helpers';
5
+ // Re-export the pure map builder (implemented in utils so it has zero server-only deps
6
+ // and can be used in build scripts / edge / tests without pulling Next.js server boundaries).
7
+ export { buildRedirectMap } from '../utils/redirectMap';
8
+ /**
9
+ * Fetches all redirects from Contentful.
10
+ *
11
+ * Returns published redirects (when not in preview). The list is small by design
12
+ * (typically < a few hundred rules) so a full enumeration with pagination is fine.
13
+ *
14
+ * The converter resolves any reference links (fromPage, toArticle, etc.) into
15
+ * concrete fromPath / to strings so callers (build-time bake or future sync)
16
+ * only ever see simple path → target maps.
17
+ */
18
+ export async function contentfulRedirectsRest(context, config, options) {
19
+ const client = getContentfulClient(config, options.preview);
20
+ const redirectCacheTags = getCacheTags('redirect', undefined, options.preview);
21
+ const requestOptions = {
22
+ ...options,
23
+ next: {
24
+ ...options?.next,
25
+ tags: redirectCacheTags,
26
+ },
27
+ };
28
+ const allRedirects = [];
29
+ const errors = [];
30
+ const pageSize = 100;
31
+ let skip = 0;
32
+ let hasMore = true;
33
+ const fetchFn = async () => {
34
+ while (hasMore) {
35
+ try {
36
+ const redirectResponse = await client.getEntries({
37
+ content_type: 'redirect',
38
+ include: 2, // enough to resolve the link targets we care about for hrefs
39
+ locale: options?.locale,
40
+ limit: pageSize,
41
+ skip,
42
+ }, requestOptions);
43
+ if (!redirectResponse.items.length) {
44
+ hasMore = false;
45
+ break;
46
+ }
47
+ const includes = convertAllIncludes(redirectResponse);
48
+ const assets = convertAllAssets(redirectResponse, context);
49
+ const rawAssets = convertAllRawAssets(redirectResponse);
50
+ const fullContext = {
51
+ ...context,
52
+ includes,
53
+ assets,
54
+ rawAssets,
55
+ errors: [],
56
+ externalVideoEmbeds: new Map(),
57
+ };
58
+ for (const redirectEntry of redirectResponse.items) {
59
+ if (!redirectEntry.fields)
60
+ continue;
61
+ try {
62
+ const converted = context.redirectResolver(fullContext, redirectEntry);
63
+ allRedirects.push(converted);
64
+ }
65
+ catch (error) {
66
+ const entryId = redirectEntry.sys.id;
67
+ const entryType = redirectEntry.sys.contentType?.sys?.id;
68
+ const errorMessage = error instanceof Error ? error.message : 'Unknown conversion error';
69
+ errors.push({
70
+ entryId,
71
+ entryType,
72
+ message: errorMessage,
73
+ error,
74
+ });
75
+ }
76
+ }
77
+ if (fullContext.errors.length > 0 &&
78
+ typeof process !== 'undefined' &&
79
+ process.env?.NODE_ENV === 'production') {
80
+ console.error(`CMS conversion errors for redirect:`, {
81
+ errors: fullContext.errors,
82
+ });
83
+ }
84
+ }
85
+ catch (error) {
86
+ const entryId = 'unknown';
87
+ const entryType = 'redirect';
88
+ const errorMessage = error instanceof Error ? error.message : 'Unknown conversion error';
89
+ const cmsError = {
90
+ entryId,
91
+ entryType,
92
+ message: errorMessage,
93
+ error,
94
+ };
95
+ errors.push(cmsError);
96
+ }
97
+ skip += pageSize;
98
+ }
99
+ return { data: allRedirects, errors };
100
+ };
101
+ if (options.retry) {
102
+ return await withRetry(fetchFn, options.retry);
103
+ }
104
+ return await fetchFn();
105
+ }
106
+ //# sourceMappingURL=redirects.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redirects.js","sourceRoot":"","sources":["../../src/api/redirects.ts"],"names":[],"mappings":"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"}
@@ -13,7 +13,12 @@ import type { RelatedArticlesOptions } from './types';
13
13
  * ```ts
14
14
  * const relatedArticles = filterRelatedArticles(allArticles, {
15
15
  * articleTypeIds: ['blog-type-id'],
16
- * tagIds: ['tag-1', 'tag-2'],
16
+ * articleTypeSlugs: ['resources/news'],
17
+ * tagIds: ['tag-1'],
18
+ * tagSlugs: ['tag-2'],
19
+ * tagTypeSlugs: ['condition'],
20
+ * authorSlugs: ['alice'],
21
+ * strictAuthorMatch: true,
17
22
  * excludeArticleIds: [currentArticle.id],
18
23
  * count: 3,
19
24
  * });
@@ -1 +1 @@
1
- {"version":3,"file":"related-articles.d.ts","sourceRoot":"","sources":["../../src/api/related-articles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAClF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAEtD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,YAAY,EAAE,EACxB,OAAO,EAAE,sBAAsB,GAC9B,YAAY,EAAE,CAwGhB"}
1
+ {"version":3,"file":"related-articles.d.ts","sourceRoot":"","sources":["../../src/api/related-articles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAClF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAEtD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,YAAY,EAAE,EACxB,OAAO,EAAE,sBAAsB,GAC9B,YAAY,EAAE,CA6JhB"}
@@ -12,21 +12,31 @@ import { getArticleAuthors } from '@se-studio/core-data-types';
12
12
  * ```ts
13
13
  * const relatedArticles = filterRelatedArticles(allArticles, {
14
14
  * articleTypeIds: ['blog-type-id'],
15
- * tagIds: ['tag-1', 'tag-2'],
15
+ * articleTypeSlugs: ['resources/news'],
16
+ * tagIds: ['tag-1'],
17
+ * tagSlugs: ['tag-2'],
18
+ * tagTypeSlugs: ['condition'],
19
+ * authorSlugs: ['alice'],
20
+ * strictAuthorMatch: true,
16
21
  * excludeArticleIds: [currentArticle.id],
17
22
  * count: 3,
18
23
  * });
19
24
  * ```
20
25
  */
21
26
  export function filterRelatedArticles(articles, options) {
22
- const { excludeArticleIds, articleTypeIds: rawArticleTypeIds, tagIds: rawTagIds, authorIds: rawAuthorIds, before, after, count, } = options;
23
- // Extract and deduplicate IDs from link objects
27
+ const { excludeArticleIds, articleTypeIds: rawArticleTypeIds, articleTypeSlugs: rawArticleTypeSlugs, tagIds: rawTagIds, tagSlugs: rawTagSlugs, tagTypeIds: rawTagTypeIds, tagTypeSlugs: rawTagTypeSlugs, authorIds: rawAuthorIds, authorSlugs: rawAuthorSlugs, strictAuthorMatch, before, after, count, } = options;
28
+ // Extract and deduplicate IDs/slugs
24
29
  const excludeIds = excludeArticleIds ? [...new Set(excludeArticleIds)] : [];
25
30
  const articleTypeIds = rawArticleTypeIds ? [...new Set(rawArticleTypeIds)] : [];
31
+ const articleTypeSlugs = rawArticleTypeSlugs ? [...new Set(rawArticleTypeSlugs)] : [];
26
32
  const tagIds = rawTagIds ? [...new Set(rawTagIds)] : [];
33
+ const tagSlugs = rawTagSlugs ? [...new Set(rawTagSlugs)] : [];
34
+ const tagTypeIds = rawTagTypeIds ? [...new Set(rawTagTypeIds)] : [];
35
+ const tagTypeSlugs = rawTagTypeSlugs ? [...new Set(rawTagTypeSlugs)] : [];
27
36
  const authorIds = rawAuthorIds ? [...new Set(rawAuthorIds)] : [];
37
+ const authorSlugs = rawAuthorSlugs ? [...new Set(rawAuthorSlugs)] : [];
28
38
  if (process.env.LOG_RELATED_ARTICLES) {
29
- console.log(`[RelatedArticles:filter] input: ${articles.length} articles, options: articleTypes=${(rawArticleTypeIds ?? []).join(',') || 'none'} tags=${(rawTagIds ?? []).join(',') || 'none'} authors=${(rawAuthorIds ?? []).join(',') || 'none'} count=${count ?? 'all'}`);
39
+ console.log(`[RelatedArticles:filter] input: ${articles.length} articles, options: articleTypes=${[...(rawArticleTypeIds ?? []), ...(rawArticleTypeSlugs ?? [])].join(',') || 'none'} tags=${[...(rawTagIds ?? []), ...(rawTagSlugs ?? [])].join(',') || 'none'} tagTypes=${[...(rawTagTypeIds ?? []), ...(rawTagTypeSlugs ?? [])].join(',') || 'none'} authors=${[...(rawAuthorIds ?? []), ...(rawAuthorSlugs ?? [])].join(',') || 'none'} strictAuthorMatch=${strictAuthorMatch ?? false} count=${count ?? 'all'}`);
30
40
  }
31
41
  // Score and filter articles
32
42
  const scoredArticles = articles
@@ -40,9 +50,15 @@ export function filterRelatedArticles(articles, options) {
40
50
  if (excludeIds.length > 0 && excludeIds.includes(article.id)) {
41
51
  return null;
42
52
  }
43
- // Filter: Article type (match any of the provided types)
44
- if (articleTypeIds.length > 0) {
45
- if (!article.articleType?.id || !articleTypeIds.includes(article.articleType.id)) {
53
+ // Filter: Article type (match any of the provided types by ID or slug)
54
+ if (articleTypeIds.length > 0 || articleTypeSlugs.length > 0) {
55
+ const matchesById = articleTypeIds.length > 0 &&
56
+ !!article.articleType?.id &&
57
+ articleTypeIds.includes(article.articleType.id);
58
+ const matchesBySlug = articleTypeSlugs.length > 0 &&
59
+ !!article.articleType?.slug &&
60
+ articleTypeSlugs.includes(article.articleType.slug);
61
+ if (!matchesById && !matchesBySlug) {
46
62
  return null;
47
63
  }
48
64
  }
@@ -56,21 +72,52 @@ export function filterRelatedArticles(articles, options) {
56
72
  return null;
57
73
  }
58
74
  }
59
- // Filter + score: Tag matching (must match at least one; more matches = higher score)
60
- if (tagIds.length > 0) {
61
- const articleTagIds = article.tags?.map((tag) => tag.id) ?? [];
62
- const matchingTags = tagIds.filter((tagId) => articleTagIds.includes(tagId));
63
- if (matchingTags.length === 0) {
75
+ // Filter + score: Tag matching by ID or slug (must match at least one; more matches = higher score)
76
+ if (tagIds.length > 0 || tagSlugs.length > 0) {
77
+ const articleTags = article.tags ?? [];
78
+ const matchingTagIds = new Set();
79
+ if (tagIds.length > 0) {
80
+ for (const id of tagIds) {
81
+ const tag = articleTags.find((t) => t.id === id);
82
+ if (tag?.id)
83
+ matchingTagIds.add(tag.id);
84
+ }
85
+ }
86
+ if (tagSlugs.length > 0) {
87
+ for (const slug of tagSlugs) {
88
+ const tag = articleTags.find((t) => t.slug === slug);
89
+ if (tag?.id)
90
+ matchingTagIds.add(tag.id);
91
+ }
92
+ }
93
+ const totalMatches = matchingTagIds.size;
94
+ if (totalMatches === 0) {
64
95
  return null;
65
96
  }
66
- score += matchingTags.length * 10; // Each matching tag adds 10 points
97
+ score += totalMatches * 10; // Each matching *distinct* tag adds 10 points
67
98
  }
68
- // Score: Author matching (match any of the provided authors)
69
- if (authorIds.length > 0) {
70
- const articleAuthorIds = getArticleAuthors(article)
71
- .map((person) => person.id)
72
- .filter(Boolean);
73
- if (articleAuthorIds.some((id) => authorIds.includes(id))) {
99
+ // Filter: Tag type matching (hard filter no scoring)
100
+ if (tagTypeIds.length > 0 || tagTypeSlugs.length > 0) {
101
+ const articleTags = article.tags ?? [];
102
+ const matchesById = tagTypeIds.length > 0 &&
103
+ articleTags.some((t) => t.tagType?.id && tagTypeIds.includes(t.tagType.id));
104
+ const matchesBySlug = tagTypeSlugs.length > 0 &&
105
+ articleTags.some((t) => t.tagType?.slug && tagTypeSlugs.includes(t.tagType.slug));
106
+ if (!matchesById && !matchesBySlug) {
107
+ return null;
108
+ }
109
+ }
110
+ // Filter/score: Author matching by ID or slug
111
+ if (authorIds.length > 0 || authorSlugs.length > 0) {
112
+ const articleAuthors = getArticleAuthors(article);
113
+ const matchesById = authorIds.length > 0 && articleAuthors.some((p) => p.id && authorIds.includes(p.id));
114
+ const matchesBySlug = authorSlugs.length > 0 &&
115
+ articleAuthors.some((p) => p.slug && authorSlugs.includes(p.slug));
116
+ const hasMatch = matchesById || matchesBySlug;
117
+ if (strictAuthorMatch && !hasMatch) {
118
+ return null;
119
+ }
120
+ if (hasMatch) {
74
121
  score += 5; // Matching author adds 5 points
75
122
  }
76
123
  }
@@ -1 +1 @@
1
- {"version":3,"file":"related-articles.js","sourceRoot":"","sources":["../../src/api/related-articles.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"related-articles.js","sourceRoot":"","sources":["../../src/api/related-articles.ts"],"names":[],"mappings":"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"}
@@ -56,12 +56,24 @@ export interface SitemapConfig {
56
56
  export interface RelatedArticlesOptions {
57
57
  /** Articles to exclude from results */
58
58
  excludeArticleIds?: string[];
59
- /** Filter to articles matching any of these article types */
59
+ /** Filter to articles matching any of these article type IDs (OR) */
60
60
  articleTypeIds?: string[];
61
- /** Filter to articles matching any of these tags (OR); articles with more matches rank higher */
61
+ /** Filter to articles matching any of these article type slugs (OR) */
62
+ articleTypeSlugs?: string[];
63
+ /** Filter to articles matching any of these tag IDs (OR); articles with more matches rank higher */
62
64
  tagIds?: string[];
63
- /** Filter/rank by authors - articles with matching authors are ranked higher */
65
+ /** Filter to articles matching any of these tag slugs (OR); articles with more matches rank higher */
66
+ tagSlugs?: string[];
67
+ /** Filter to articles that have at least one tag belonging to any of these tag type IDs */
68
+ tagTypeIds?: string[];
69
+ /** Filter to articles that have at least one tag belonging to any of these tag type slugs */
70
+ tagTypeSlugs?: string[];
71
+ /** Filter/rank by author IDs - articles with matching authors are ranked higher */
64
72
  authorIds?: string[];
73
+ /** Filter/rank by author slugs - articles with matching authors are ranked higher */
74
+ authorSlugs?: string[];
75
+ /** When true, authorIds/authorSlugs become a hard filter (exclude non-matching) rather than just a ranking boost */
76
+ strictAuthorMatch?: boolean;
65
77
  /** Only include articles published before this date */
66
78
  before?: Date;
67
79
  /** Only include articles published after this date */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/api/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/api/types.ts"],"names":[],"mappings":"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"}