@vigilkids/cms-nuxt 0.0.2 → 0.2.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/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": ">=3.15.0"
6
6
  },
7
- "version": "0.0.2",
7
+ "version": "0.2.0",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "0.8.4",
10
10
  "unbuild": "unknown"
package/dist/module.mjs CHANGED
@@ -49,6 +49,10 @@ const module = defineNuxtModule({
49
49
  });
50
50
  }
51
51
  if (options.preview?.enabled !== false) {
52
+ addServerHandler({
53
+ middleware: true,
54
+ handler: resolve("./runtime/server/middleware/preview-context")
55
+ });
52
56
  addServerHandler({
53
57
  route: "/api/preview",
54
58
  method: "get",
@@ -1,5 +1,5 @@
1
- import { toRef } from "vue";
2
1
  import { useAsyncData, useHead, useRuntimeConfig, useSeoMeta } from "#imports";
2
+ import { toRef } from "vue";
3
3
  import { useCmsClient } from "./useCmsClient.js";
4
4
  export function useArticle(slug) {
5
5
  const resolvedSlug = toRef(slug);
@@ -29,14 +29,16 @@ export function useArticle(slug) {
29
29
  });
30
30
  useHead({
31
31
  script: () => {
32
- if (!article.value?.json_ld || Object.keys(article.value.json_ld).length === 0) return [];
32
+ if (!article.value?.json_ld || Object.keys(article.value.json_ld).length === 0)
33
+ return [];
33
34
  return [{ type: "application/ld+json", innerHTML: JSON.stringify(article.value.json_ld) }];
34
35
  }
35
36
  });
36
37
  useHead({
37
38
  link: () => {
38
39
  const a = article.value;
39
- if (!a?.available_locales || a.available_locales.length <= 1) return [];
40
+ if (!a?.available_locales || a.available_locales.length <= 1)
41
+ return [];
40
42
  const publicConfig = useRuntimeConfig().public;
41
43
  const siteUrl = publicConfig.siteUrl ?? "";
42
44
  const links = a.available_locales.map((locale) => ({
@@ -1,5 +1,5 @@
1
- import { computed, toRef } from "vue";
2
1
  import { useAsyncData } from "#imports";
2
+ import { computed, toRef } from "vue";
3
3
  import { useCmsClient } from "./useCmsClient.js";
4
4
  export function useArticleList(params) {
5
5
  const resolvedParams = toRef(params);
@@ -1,14 +1,16 @@
1
- import { toRef } from "vue";
2
1
  import { useAsyncData } from "#imports";
2
+ import { toRef } from "vue";
3
3
  import { useCmsClient } from "./useCmsClient.js";
4
4
  export function useAuthor(slug) {
5
5
  const resolvedSlug = toRef(slug);
6
6
  const client = useCmsClient();
7
- const { data: author, status, error } = useAsyncData(
8
- `cms-author-${resolvedSlug.value}`,
9
- () => client.getAuthor(resolvedSlug.value),
10
- { watch: [resolvedSlug] }
11
- );
7
+ const {
8
+ data: author,
9
+ status,
10
+ error
11
+ } = useAsyncData(`cms-author-${resolvedSlug.value}`, () => client.getAuthor(resolvedSlug.value), {
12
+ watch: [resolvedSlug]
13
+ });
12
14
  const { data: articles } = useAsyncData(
13
15
  `cms-author-articles-${resolvedSlug.value}`,
14
16
  () => client.getAuthorArticles(resolvedSlug.value),
@@ -1,5 +1,5 @@
1
- import { toRef } from "vue";
2
1
  import { useSeoMeta } from "#imports";
2
+ import { toRef } from "vue";
3
3
  export function useBlogSeo(options) {
4
4
  const title = toRef(options.title);
5
5
  const description = toRef(options.description ?? "");
@@ -1,20 +1,19 @@
1
- import { computed } from "vue";
2
1
  import { useAsyncData } from "#imports";
2
+ import { computed } from "vue";
3
3
  import { useCmsClient } from "./useCmsClient.js";
4
4
  export function useCategories() {
5
5
  const client = useCmsClient();
6
- const { data, status, error } = useAsyncData(
7
- "cms-categories",
8
- () => client.getCategories(),
9
- { dedupe: "defer" }
10
- );
6
+ const { data, status, error } = useAsyncData("cms-categories", () => client.getCategories(), {
7
+ dedupe: "defer"
8
+ });
11
9
  const categories = computed(() => data.value ?? []);
12
10
  const flatCategories = computed(() => {
13
11
  const result = [];
14
12
  function flatten(nodes) {
15
13
  for (const node of nodes) {
16
14
  result.push(node);
17
- if (node.children?.length) flatten(node.children);
15
+ if (node.children?.length)
16
+ flatten(node.children);
18
17
  }
19
18
  }
20
19
  flatten(categories.value);
@@ -1,5 +1,5 @@
1
- import { CmsClient } from "@vigilkids/cms-client";
2
1
  import { useRuntimeConfig, useState } from "#imports";
2
+ import { CmsClient } from "@vigilkids/cms-client";
3
3
  export function useCmsClient() {
4
4
  const config = useRuntimeConfig();
5
5
  const previewToken = useState("cmsPreviewToken", () => null);
@@ -1,10 +1,23 @@
1
- import { computed } from "vue";
2
- import { useRuntimeConfig, useState } from "#imports";
1
+ import { useCookie, useRequestEvent, useRoute, useRuntimeConfig } from "#imports";
2
+ import { computed, ref } from "vue";
3
+ export function useCmsPreviewToken() {
4
+ const config = useRuntimeConfig();
5
+ const cookieName = config.public.cms.preview?.cookieName ?? "__preview_token";
6
+ if (import.meta.server) {
7
+ const event = useRequestEvent();
8
+ const token = event?.context?.__cms_preview_token ?? null;
9
+ return ref(token);
10
+ }
11
+ const cookie = useCookie(cookieName);
12
+ return computed(
13
+ () => cookie.value ? decodeURIComponent(cookie.value) : null
14
+ );
15
+ }
3
16
  export function useCmsPreview() {
4
- const previewToken = useState("cmsPreviewToken", () => null);
5
- const isPreview = computed(() => !!previewToken.value);
17
+ const token = useCmsPreviewToken();
18
+ const route = useRoute();
19
+ const isPreview = computed(() => !!token.value || route.query._preview === "1");
6
20
  function exitPreview() {
7
- previewToken.value = null;
8
21
  if (import.meta.client) {
9
22
  const config = useRuntimeConfig();
10
23
  const cookieName = config.public.cms.preview?.cookieName ?? "__preview_token";
@@ -12,5 +25,5 @@ export function useCmsPreview() {
12
25
  window.location.reload();
13
26
  }
14
27
  }
15
- return { isPreview, previewToken, exitPreview };
28
+ return { isPreview, previewToken: token, exitPreview };
16
29
  }
@@ -1,6 +1,6 @@
1
- import { createError, defineEventHandler, getHeader, readRawBody } from "h3";
2
1
  import { useRuntimeConfig, useStorage } from "#imports";
3
2
  import { verifyWebhookSignature } from "@vigilkids/cms-client/webhook";
3
+ import { createError, defineEventHandler, getHeader, readRawBody } from "h3";
4
4
  export default defineEventHandler(async (event) => {
5
5
  const config = useRuntimeConfig();
6
6
  const secret = config.cms.webhookSecret;
@@ -29,11 +29,13 @@ export default defineEventHandler(async (event) => {
29
29
  paths.push(`${localePrefix}/blog/${payload.slug}`);
30
30
  paths.push(`${localePrefix}/blog`);
31
31
  const storage = useStorage("cache:nitro:routes");
32
+ const allKeys = await storage.getKeys("_:");
32
33
  let cleared = 0;
33
34
  for (const path of paths) {
34
- const cacheKey = path.replace(/\//g, ":");
35
- if (await storage.hasItem(cacheKey)) {
36
- await storage.removeItem(cacheKey);
35
+ const escapedPrefix = path.replace(/\W/g, "").slice(0, 16);
36
+ const matchingKeys = allKeys.filter((k) => k.startsWith(`_:${escapedPrefix}.`));
37
+ for (const key of matchingKeys) {
38
+ await storage.removeItem(key);
37
39
  cleared++;
38
40
  }
39
41
  }
@@ -1,5 +1,5 @@
1
- import { createError, defineEventHandler, getQuery, sendRedirect, setCookie } from "h3";
2
1
  import { useRuntimeConfig } from "#imports";
2
+ import { createError, defineEventHandler, getQuery, sendRedirect, setCookie } from "h3";
3
3
  export default defineEventHandler(async (event) => {
4
4
  const query = getQuery(event);
5
5
  const token = query.token;
@@ -23,9 +23,9 @@ export default defineEventHandler(async (event) => {
23
23
  let prefix = "";
24
24
  if (locale && locale !== defaultLocale) {
25
25
  const prefixes = cmsConfig.localePrefixes ?? {};
26
- prefix = "/" + (prefixes[locale] ?? locale.toLowerCase());
26
+ prefix = `/${prefixes[locale] ?? locale.toLowerCase()}`;
27
27
  }
28
28
  const articlePath = cmsConfig.preview?.articlePath ?? "/blog/{slug}";
29
29
  const path = articlePath.replace("{slug}", slug);
30
- return sendRedirect(event, `${prefix}${path}`, 302);
30
+ return sendRedirect(event, `${prefix}${path}?_preview=1`, 302);
31
31
  });
@@ -0,0 +1,10 @@
1
+ import { useRuntimeConfig } from "#imports";
2
+ import { defineEventHandler, getCookie } from "h3";
3
+ export default defineEventHandler((event) => {
4
+ const config = useRuntimeConfig();
5
+ const cookieName = config.public.cms.preview?.cookieName ?? "__preview_token";
6
+ const raw = getCookie(event, cookieName);
7
+ if (raw) {
8
+ event.context.__cms_preview_token = decodeURIComponent(raw);
9
+ }
10
+ });
@@ -1,10 +1,11 @@
1
- import { defineEventHandler, getRequestURL, sendRedirect } from "h3";
2
1
  import { useRuntimeConfig } from "#imports";
2
+ import { defineEventHandler, getRequestURL, sendRedirect } from "h3";
3
3
  let cachedRules = null;
4
4
  let cacheExpiry = 0;
5
5
  async function loadRules() {
6
6
  const now = Date.now();
7
- if (cachedRules && now < cacheExpiry) return cachedRules;
7
+ if (cachedRules && now < cacheExpiry)
8
+ return cachedRules;
8
9
  const config = useRuntimeConfig();
9
10
  const cacheTtl = config.cms.redirects?.cacheTtl ?? 3e5;
10
11
  try {
@@ -1,5 +1,5 @@
1
- import { CmsClient } from "@vigilkids/cms-client";
2
1
  import { useRuntimeConfig } from "#imports";
2
+ import { CmsClient } from "@vigilkids/cms-client";
3
3
  let _client = null;
4
4
  export function useServerCmsClient() {
5
5
  if (!_client) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vigilkids/cms-nuxt",
3
- "version": "0.0.2",
3
+ "version": "0.2.0",
4
4
  "description": "Nuxt 3 module for OnEx CMS — composables, server routes, middleware, sitemap",
5
5
  "type": "module",
6
6
  "main": "./dist/module.mjs",
@@ -17,7 +17,10 @@
17
17
  "sideEffects": false,
18
18
  "scripts": {
19
19
  "build": "nuxt-module-build build",
20
- "prepack": "nuxt-module-build build"
20
+ "prepack": "nuxt-module-build build",
21
+ "lint": "eslint .",
22
+ "lint:fix": "eslint . --fix",
23
+ "format": "prettier --write src/"
21
24
  },
22
25
  "publishConfig": {
23
26
  "access": "public"
@@ -28,11 +31,15 @@
28
31
  "directory": "packages/cms-nuxt"
29
32
  },
30
33
  "devDependencies": {
34
+ "@antfu/eslint-config": "^4.13.2",
31
35
  "@nuxt/kit": "^3.15.0",
32
36
  "@nuxt/module-builder": "^0.8.0",
33
37
  "@nuxt/schema": "^3.15.0",
34
38
  "@types/node": "^22.0.0",
39
+ "eslint": "^9.22.0",
40
+ "eslint-config-prettier": "^10.1.1",
35
41
  "h3": "^1.12.0",
42
+ "prettier": "^3.5.3",
36
43
  "vue": "^3.4.0"
37
44
  },
38
45
  "peerDependencies": {