@evenicanpm/cms 2.3.0 → 2.4.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.
@@ -0,0 +1,7 @@
1
+
2
+  WARN  Failed to replace env in config: ${NPM_TOKEN}
3
+ ../../apps/strapi |  WARN  Unsupported engine: wanted: {"node":">=18.0.0 <=22.x.x"} (current: {"node":"v24.16.0","pnpm":"11.0.0"})
4
+ $ pnpm dlx @biomejs/biome check --write .
5
+  WARN  Failed to replace env in config: ${NPM_TOKEN}
6
+  WARN  Failed to replace env in config: ${NPM_TOKEN}
7
+ Checked 19 files in 40ms. No fixes applied.
package/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ # @evenicanpm/cms
2
+
3
+ ## 2.4.0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evenicanpm/cms",
3
- "version": "2.3.0",
3
+ "version": "2.4.0",
4
4
  "description": "Strapi 5 client and queries for e4 Headless.",
5
5
  "author": "Evenica",
6
6
  "type": "module",
@@ -17,6 +17,5 @@
17
17
  },
18
18
  "devDependencies": {
19
19
  "@types/node": "^24.0.13"
20
- },
21
- "gitHead": "72bf1aeb02a3d96c587706c0d91606698e38ff6a"
20
+ }
22
21
  }
@@ -10,21 +10,33 @@ const getBlogs = async (options: {
10
10
  pagination: { pageSize: number; page: number };
11
11
  locale?: string;
12
12
  }): Promise<StrapiResponse<Blog[]>> => {
13
- return strapi.find<Blog>("blogs", {
14
- pagination: { ...options.pagination, withCount: true },
15
- populate: "*",
16
- ...getLocaleOption(options),
17
- } as Parameters<typeof strapi.find>[1]);
13
+ try {
14
+ return await strapi.find<Blog>("blogs", {
15
+ pagination: { ...options.pagination, withCount: true },
16
+ populate: "*",
17
+ ...getLocaleOption(options),
18
+ } as Parameters<typeof strapi.find>[1]);
19
+ } catch (error) {
20
+ console.error("error fetching strapi blogs data", error);
21
+ return { data: [] as Blog[], meta: {} } as unknown as StrapiResponse<
22
+ Blog[]
23
+ >;
24
+ }
18
25
  };
19
26
 
20
27
  const getBlog = async (options: {
21
28
  id: string;
22
29
  locale?: string;
23
30
  }): Promise<StrapiResponse<Blog>> => {
24
- return strapi.findOne<Blog>("blogs", options.id, {
25
- populate: "*",
26
- ...getLocaleOption(options),
27
- } as Parameters<typeof strapi.findOne>[2]);
31
+ try {
32
+ return await strapi.findOne<Blog>("blogs", options.id, {
33
+ populate: "*",
34
+ ...getLocaleOption(options),
35
+ } as Parameters<typeof strapi.findOne>[2]);
36
+ } catch (error) {
37
+ console.error("error fetching strapi blog data", error);
38
+ return { data: null, meta: {} } as unknown as StrapiResponse<Blog>;
39
+ }
28
40
  };
29
41
 
30
42
  export { getBlog, getBlogs };
@@ -0,0 +1,32 @@
1
+ import { strapi } from "../../client";
2
+ import type { Footer } from "./types";
3
+
4
+ const getFooter = async (options?: { locale?: string }) => {
5
+ const { locale } = options ?? {};
6
+
7
+ try {
8
+ return await strapi.find<Footer>("footer", {
9
+ populate: {
10
+ sections: {
11
+ on: {
12
+ "footer.logo": {
13
+ populate: { logoImage: true },
14
+ },
15
+ "footer.links": {
16
+ populate: { links: true },
17
+ },
18
+ "footer.contact": {
19
+ populate: { social: true },
20
+ },
21
+ },
22
+ },
23
+ },
24
+ ...(locale ? { locale } : {}),
25
+ } as Parameters<typeof strapi.find>[1]);
26
+ } catch (error) {
27
+ console.warn("footer unavailable from Strapi, falling back to null", error);
28
+ return null;
29
+ }
30
+ };
31
+
32
+ export { getFooter };
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Interface is not auto-generated and needs to be updated
3
+ * whenever Strapi Content-Type is modified.
4
+ *
5
+ * TODO: Auto-generated interfaces from Strapi
6
+ */
7
+
8
+ export interface FooterLink {
9
+ slug: string;
10
+ title: string;
11
+ }
12
+
13
+ export interface FooterSocialLink {
14
+ name: string;
15
+ link: string;
16
+ }
17
+
18
+ interface FooterLogoBlock {
19
+ id: number;
20
+ __component: "footer.logo";
21
+ logoImage?: { url: string; alternativeText?: string };
22
+ description: string;
23
+ }
24
+
25
+ interface FooterLinksBlock {
26
+ id: number;
27
+ __component: "footer.links";
28
+ title: string;
29
+ links: FooterLink[];
30
+ }
31
+
32
+ interface FooterContactBlock {
33
+ id: number;
34
+ __component: "footer.contact";
35
+ address?: string;
36
+ email?: string;
37
+ phoneNumber?: string;
38
+ social: FooterSocialLink[];
39
+ }
40
+
41
+ export type FooterBlock =
42
+ | FooterLogoBlock
43
+ | FooterLinksBlock
44
+ | FooterContactBlock;
45
+
46
+ export interface Footer {
47
+ id: number;
48
+ documentId: string;
49
+ sections: FooterBlock[];
50
+ }
@@ -19,7 +19,7 @@ const getMainNavigation = async () => {
19
19
  );
20
20
  return response;
21
21
  } catch (error) {
22
- console.error("error fetching strapi navigation data", error);
22
+ console.warn("error fetching strapi navigation data", error);
23
23
  return [];
24
24
  }
25
25
  };
@@ -8,22 +8,37 @@ const getPage = async (options: {
8
8
  }) => {
9
9
  const { slug, status, locale } = options;
10
10
 
11
- return await strapi.find<Page>("pages", {
12
- filters: { slug },
13
- populate: {
14
- seo: true,
15
- block: {
16
- on: {
17
- "blocks.hero-image": {
18
- populate: { image: true },
11
+ try {
12
+ return await strapi.find<Page>("pages", {
13
+ filters: { slug },
14
+ populate: {
15
+ seo: true,
16
+ block: {
17
+ on: {
18
+ "blocks.hero-image": {
19
+ populate: { image: true },
20
+ },
21
+ "blocks.rich-text": true,
22
+ },
23
+ },
24
+ headerOverride: {
25
+ populate: "*",
26
+ },
27
+ footerOverride: {
28
+ populate: {
29
+ sections: {
30
+ populate: "*",
31
+ },
19
32
  },
20
- "blocks.rich-text": true,
21
33
  },
22
34
  },
23
- },
24
- ...((status ? { status } : {}) as object),
25
- ...(locale ? { locale } : {}),
26
- } as Parameters<typeof strapi.find>[1]);
35
+ ...((status ? { status } : {}) as object),
36
+ ...(locale ? { locale } : {}),
37
+ } as Parameters<typeof strapi.find>[1]);
38
+ } catch (error) {
39
+ console.warn("error fetching strapi page data", error);
40
+ return { data: [] as Page[], meta: {} };
41
+ }
27
42
  };
28
43
 
29
44
  export { getPage };
@@ -5,16 +5,34 @@
5
5
  * TODO: Auto-generated interfaces from Strapi
6
6
  */
7
7
 
8
+ import type { FooterBlock } from "../footer/types";
9
+
8
10
  type MetaElement = {
9
11
  name: string;
10
12
  content: string;
11
13
  };
12
14
 
15
+ import type { HeaderConfig } from "../header/types";
16
+
17
+ export interface HeaderVariant extends HeaderConfig {
18
+ id: number;
19
+ documentId: string;
20
+ name: string;
21
+ }
22
+ export interface FooterVariant {
23
+ id: number;
24
+ documentId: string;
25
+ name: string;
26
+ sections: FooterBlock[];
27
+ }
28
+
13
29
  export interface Page {
14
30
  id: number;
15
31
  documentId: string;
16
32
  title: string;
17
33
  slug: string;
34
+ overrideHeader?: boolean;
35
+ headerOverride?: HeaderVariant | null;
18
36
  seo: {
19
37
  // blocks.seo component
20
38
  metaTitle?: string;
@@ -26,4 +44,7 @@ export interface Page {
26
44
  } | null;
27
45
 
28
46
  block: Array<{ __component: string; id: number; [key: string]: unknown }>;
47
+
48
+ overrideFooter?: boolean;
49
+ footerOverride?: FooterVariant | null;
29
50
  }
package/src/index.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as blogs from "./content/blogs";
2
+ import * as footer from "./content/footer";
2
3
  import * as header from "./content/header";
3
4
  import * as navigation from "./content/navigation";
4
5
  import * as pages from "./content/pages";
@@ -8,6 +9,7 @@ import * as session from "./session";
8
9
 
9
10
  export const cms = {
10
11
  blogs,
12
+ footer,
11
13
  pages,
12
14
  navigation,
13
15
  locales,