lightnet 3.4.1 → 3.4.3

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 CHANGED
@@ -1,5 +1,19 @@
1
1
  # lightnet
2
2
 
3
+ ## 3.4.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [#259](https://github.com/LightNetDev/LightNet/pull/259) [`7e61913`](https://github.com/LightNetDev/LightNet/commit/7e61913cf49863807c25cfdb379a878e47642b03) Thanks [@smn-cds](https://github.com/smn-cds)! - Change language selector icon from "scripts" to "web" icon.
8
+
9
+ - [#259](https://github.com/LightNetDev/LightNet/pull/259) [`7e61913`](https://github.com/LightNetDev/LightNet/commit/7e61913cf49863807c25cfdb379a878e47642b03) Thanks [@smn-cds](https://github.com/smn-cds)! - Change icon of share button, make it consistent with open button.
10
+
11
+ ## 3.4.2
12
+
13
+ ### Patch Changes
14
+
15
+ - [#256](https://github.com/LightNetDev/LightNet/pull/256) [`3c005c1`](https://github.com/LightNetDev/LightNet/commit/3c005c10ed55061f00f7d9c74e03be879bd5bb85) Thanks [@smn-cds](https://github.com/smn-cds)! - Improve error messages.
16
+
3
17
  ## 3.4.1
4
18
 
5
19
  ### Patch Changes
package/README.md CHANGED
@@ -1,8 +1,10 @@
1
1
  # LightNet
2
2
 
3
- Share the message of Jesus and strengthen believers worldwide. LightNet empowers you to create digital media libraries, making your content accessible on the web — including videos, audio, images, and books.
3
+ Share the message of Jesus and strengthen believers worldwide.
4
4
 
5
- LightNet is built as an integration for the [Astro](https://astro.build) framework, enabling the creation of statically generated sites that can be hosted on any file server. These sites are fast, easily extendable, and fully support internationalization.
5
+ LightNet empowers ministries to run their own digital media libraries. They can easily share content in the heart language of the communities they serve - including videos, audio, images, and documents.
6
+
7
+ It is built as an integration for the [Astro framework](https://astro.build), enabling the creation of statically generated sites that can be hosted on any file server. These sites are fast, easily extendable, and fully support internationalization.
6
8
 
7
9
  ## Documentation
8
10
 
@@ -6,9 +6,9 @@ case `uname` in
6
6
  esac
7
7
 
8
8
  if [ -z "$NODE_PATH" ]; then
9
- export NODE_PATH="/home/runner/work/LightNet/LightNet/node_modules/.pnpm/astro@5.6.1_@types+node@22.14.0_jiti@2.4.2_lightningcss@1.29.1_rollup@4.39.0_terser@5.39.0_typescript@5.8.3_yaml@2.7.1/node_modules/astro/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/astro@5.6.1_@types+node@22.14.0_jiti@2.4.2_lightningcss@1.29.1_rollup@4.39.0_terser@5.39.0_typescript@5.8.3_yaml@2.7.1/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/node_modules"
9
+ export NODE_PATH="/home/runner/work/LightNet/LightNet/node_modules/.pnpm/astro@5.6.2_@types+node@22.14.1_jiti@2.4.2_lightningcss@1.29.1_rollup@4.40.0_terser@5.39.0_typescript@5.8.3_yaml@2.7.1/node_modules/astro/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/astro@5.6.2_@types+node@22.14.1_jiti@2.4.2_lightningcss@1.29.1_rollup@4.40.0_terser@5.39.0_typescript@5.8.3_yaml@2.7.1/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/node_modules"
10
10
  else
11
- export NODE_PATH="/home/runner/work/LightNet/LightNet/node_modules/.pnpm/astro@5.6.1_@types+node@22.14.0_jiti@2.4.2_lightningcss@1.29.1_rollup@4.39.0_terser@5.39.0_typescript@5.8.3_yaml@2.7.1/node_modules/astro/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/astro@5.6.1_@types+node@22.14.0_jiti@2.4.2_lightningcss@1.29.1_rollup@4.39.0_terser@5.39.0_typescript@5.8.3_yaml@2.7.1/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/node_modules:$NODE_PATH"
11
+ export NODE_PATH="/home/runner/work/LightNet/LightNet/node_modules/.pnpm/astro@5.6.2_@types+node@22.14.1_jiti@2.4.2_lightningcss@1.29.1_rollup@4.40.0_terser@5.39.0_typescript@5.8.3_yaml@2.7.1/node_modules/astro/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/astro@5.6.2_@types+node@22.14.1_jiti@2.4.2_lightningcss@1.29.1_rollup@4.40.0_terser@5.39.0_typescript@5.8.3_yaml@2.7.1/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/node_modules:$NODE_PATH"
12
12
  fi
13
13
  if [ -x "$basedir/node" ]; then
14
14
  exec "$basedir/node" "$basedir/../astro/astro.js" "$@"
@@ -4,11 +4,11 @@
4
4
  "version": "0.0.1",
5
5
  "private": "true",
6
6
  "dependencies": {
7
- "@astrojs/react": "^4.2.3",
7
+ "@astrojs/react": "^4.2.4",
8
8
  "@astrojs/tailwind": "^6.0.2",
9
9
  "@lightnet/decap-admin": "^3.1.0",
10
- "astro": "^5.6.1",
11
- "lightnet": "^3.4.0",
10
+ "astro": "^5.6.2",
11
+ "lightnet": "^3.4.1",
12
12
  "react": "^19.1.0",
13
13
  "react-dom": "^19.1.0",
14
14
  "sharp": "^0.33.5",
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "lightnet",
3
3
  "type": "module",
4
4
  "license": "MIT",
5
- "version": "3.4.1",
5
+ "version": "3.4.3",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "https://github.com/LightNetDev/lightnet",
@@ -45,17 +45,16 @@
45
45
  "@iconify-json/mdi": "^1.2.3",
46
46
  "@iconify/tailwind": "^1.2.0",
47
47
  "@tailwindcss/typography": "^0.5.16",
48
- "@types/react": "^19.1.0",
48
+ "@types/react": "^19.1.2",
49
49
  "daisyui": "^4.12.24",
50
50
  "fuse.js": "^7.1.0",
51
- "i18next": "^24.2.3",
52
- "marked": "^15.0.7",
53
- "yaml": "^2.7.1",
54
- "zod-validation-error": "^3.4.0"
51
+ "i18next": "^25.0.0",
52
+ "marked": "^15.0.8",
53
+ "yaml": "^2.7.1"
55
54
  },
56
55
  "devDependencies": {
57
56
  "@playwright/test": "^1.51.1",
58
- "@types/node": "^22.14.0",
57
+ "@types/node": "^22.14.1",
59
58
  "vitest": "^3.1.1"
60
59
  },
61
60
  "scripts": {
@@ -23,7 +23,8 @@ export function lightnet(lightnetConfig: LightnetConfig): AstroIntegration {
23
23
  const config = verifySchema(
24
24
  configSchema,
25
25
  lightnetConfig,
26
- "Invalid config passed to LightNet integration.",
26
+ "Invalid LightNet configuration",
27
+ "Fix these errors on the LightNet configuration inside astro.config.mjs:",
27
28
  )
28
29
 
29
30
  injectRoute({
@@ -23,5 +23,6 @@ const prepareItem = async (item: unknown) => {
23
23
  mediaItemEntrySchema,
24
24
  item,
25
25
  (id) => `Invalid media item: ${id}`,
26
+ (id) => `Fix these issues inside "src/content/media/${id}.json":`,
26
27
  )
27
28
  }
@@ -7,7 +7,8 @@ export const getMediaType = async (id: string) => {
7
7
  return verifySchema(
8
8
  mediaTypeEntrySchema,
9
9
  await getEntry("media-types", id),
10
- `Received invalid media type ${id}.`,
10
+ (id) => `Invalid media type: "${id}"`,
11
+ (id) => `Fix these issues inside "src/content/media-types/${id}.json":`,
11
12
  )
12
13
  }
13
14
 
@@ -17,7 +18,8 @@ export const getMediaTypes = async () => {
17
18
  verifySchema(
18
19
  mediaTypeEntrySchema,
19
20
  type,
20
- (id) => `Received invalid media type '${id}'.`,
21
+ (id) => `Invalid media type: "${id}"`,
22
+ (id) => `Fix these issues inside "src/content/media-types/${id}.json":`,
21
23
  ),
22
24
  )
23
25
  }
@@ -12,8 +12,8 @@ export const resolveCategoryLabel = (
12
12
  const category = categories.find((c) => c.id === categoryId)
13
13
  if (!category) {
14
14
  throw new AstroError(
15
- `Unknown category: ${categoryId}`,
16
- "Make sure you add the category to the categories content collection.",
15
+ `Missing category "${categoryId}"`,
16
+ `To fix the issue, add a category at "src/content/categories/${categoryId}.json".`,
17
17
  )
18
18
  }
19
19
  return translate(category.data.label)
@@ -11,8 +11,8 @@ export const resolveDefaultLocale = ({
11
11
  const defaultLanguage = languages.find((l) => l.isDefaultSiteLanguage)
12
12
  if (!defaultLanguage) {
13
13
  throw new AstroError(
14
- "No default site language has been set",
15
- "Make sure you have set one language to be the default language by setting the isDefaultSiteLanguage to `true`.",
14
+ "No default site language set",
15
+ "To fix the issue, set isDefaultSiteLanguage for one language in the LightNet configuration in your astro.config.mjs file.",
16
16
  )
17
17
  }
18
18
  return defaultLanguage.code
@@ -12,7 +12,10 @@ export const resolveLanguage = (bcp47: string) => {
12
12
  const language = languages[bcp47]
13
13
 
14
14
  if (!language) {
15
- throw new AstroError(`There is no language definition for: ${bcp47}`)
15
+ throw new AstroError(
16
+ `Missing language code "${bcp47}"`,
17
+ `To fix the issue, add a language with the code "${bcp47}" to the LightNet configuration in your astro.config.mjs file.`,
18
+ )
16
19
  }
17
20
  return {
18
21
  ...language,
@@ -47,7 +47,7 @@ export function useTranslate(bcp47: string | undefined): TranslateFn {
47
47
  if (value.match(/^(?:ln|x)\../i)) {
48
48
  throw new AstroError(
49
49
  `Missing translation: '${key}' is undefined for language '${resolvedLocale}'.`,
50
- `Add a translation for '${key}' to src/translations/${resolvedLocale}.yml`,
50
+ `To fix the issue, add a translation for '${key}' to src/translations/${resolvedLocale}.yml`,
51
51
  )
52
52
  }
53
53
  return value
@@ -17,8 +17,8 @@ const favicons = config.favicon?.map((favicon) => {
17
17
  const type = faviconTypes[extname(favicon.href)]
18
18
  if (!type) {
19
19
  throw new AstroError(
20
- `Unsupported favicon ${favicon.href}`,
21
- "favicon must be a .ico, .gif, .jpg, .png, or .svg file",
20
+ `Unsupported favicon type "${extname(favicon.href)}"`,
21
+ "To fix the issue, set the favicon href to a path ending with .ico, .gif, .jpg, .png, or .svg.",
22
22
  )
23
23
  }
24
24
  return { ...favicon, type }
@@ -27,7 +27,7 @@ function currentPathWithLocale(locale: string) {
27
27
 
28
28
  {
29
29
  translations.length > 1 && (
30
- <Menu icon="mdi--translate" label="ln.header.select-language">
30
+ <Menu icon="mdi--web" label="ln.header.select-language">
31
31
  {translations.map(({ label, locale, active, href }) => (
32
32
  <MenuItem href={href} hreflang={locale} active={active}>
33
33
  {label}
@@ -33,8 +33,8 @@ if (detailsPage?.layout === "custom") {
33
33
  ] as () => Promise<any>
34
34
  if (!customDetailsImport) {
35
35
  throw new AstroError(
36
- `Unknown details page ${detailsPage.customComponent}`,
37
- "Make sure to add your details component within /src/details-pages/",
36
+ `Missing custom details page "${detailsPage.customComponent}"`,
37
+ `To fix the issue, add your details page on "/src/details-pages/${detailsPage.customComponent}".`,
38
38
  )
39
39
  }
40
40
  CustomDetails = (await customDetailsImport()).default
@@ -14,7 +14,10 @@ const { collectionId, disableItem } = Astro.props
14
14
 
15
15
  const collection = await getEntry("media-collections", collectionId)
16
16
  if (!collection) {
17
- throw new AstroError(`Unknown media collection id ${collection}.`)
17
+ throw new AstroError(
18
+ `Missing media-collection "${collectionId}".`,
19
+ `To fix the issue, add a media-collection at "src/content/media-collections/${collectionId}.json".`,
20
+ )
18
21
  }
19
22
  const items = (
20
23
  await queryMediaItems(getMediaItems(), {
@@ -9,7 +9,7 @@ const { src, className } = Astro.props
9
9
  if (!src.endsWith(".mp3")) {
10
10
  throw new AstroError(
11
11
  `Unsupported audio file ${src}`,
12
- "Mp3 is the only supported format.",
12
+ "To fix the issue, reference a mp3 file.",
13
13
  )
14
14
  }
15
15
  ---
@@ -18,11 +18,6 @@ const content = createContentMetadata(item.data.content[0])
18
18
  target={content.target}
19
19
  hreflang={item.data.language}
20
20
  >
21
- {
22
- content.canBeOpened
23
- ? Astro.locals.i18n.t(openActionLabel)
24
- : Astro.locals.i18n.t("ln.details.download")
25
- }
26
21
  {
27
22
  content.isExternal && (
28
23
  <Icon
@@ -31,4 +26,9 @@ const content = createContentMetadata(item.data.content[0])
31
26
  />
32
27
  )
33
28
  }
29
+ {
30
+ content.canBeOpened
31
+ ? Astro.locals.i18n.t(openActionLabel)
32
+ : Astro.locals.i18n.t("ln.details.download")
33
+ }
34
34
  </a>
@@ -10,7 +10,7 @@ interface Props {
10
10
  class="flex cursor-pointer items-center justify-center gap-2 rounded-2xl bg-gray-200 px-6 py-3 font-bold uppercase text-gray-600 shadow-sm hover:bg-gray-300"
11
11
  class:list={[Astro.props.className]}
12
12
  id="share-btn"
13
- ><Icon className="mdi--share-variant-outline" ariaLabel="" />
13
+ ><Icon className="mdi--share" ariaLabel="" />
14
14
  {Astro.locals.i18n.t("ln.details.share")}</button
15
15
  >
16
16
  <div
@@ -20,7 +20,9 @@ export function useSearch() {
20
20
  try {
21
21
  const response = await fetch("/api/search.json")
22
22
  if (!response.ok) {
23
- throw new Error("Network response was not ok")
23
+ throw new Error(
24
+ "Was not able to load search results from /api/search.json.",
25
+ )
24
26
  }
25
27
  const { items }: SearchResponse = await response.json()
26
28
  fuse.current = new Fuse(items, {
@@ -1,15 +1,15 @@
1
1
  import { AstroError } from "astro/errors"
2
2
  import { z } from "astro/zod"
3
- import { fromZodError } from "zod-validation-error"
4
3
 
5
4
  export async function verifySchemaAsync<T extends z.Schema>(
6
5
  schema: T,
7
6
  toVerify: unknown,
8
7
  errorMessage: string | ((id: string | undefined) => string),
8
+ hint: string | ((id: string | undefined) => string),
9
9
  ): Promise<z.output<T>> {
10
10
  const parsed = await schema.safeParseAsync(toVerify)
11
11
  if (!parsed.success) {
12
- throwParseError(toVerify, errorMessage, parsed)
12
+ throwParseError(toVerify, errorMessage, hint, parsed)
13
13
  }
14
14
  return parsed.data
15
15
  }
@@ -18,10 +18,11 @@ export function verifySchema<T extends z.Schema>(
18
18
  schema: T,
19
19
  toVerify: unknown,
20
20
  errorMessage: string | ((id: string | undefined) => string),
21
+ hint: string | ((id: string | undefined) => string),
21
22
  ): z.output<T> {
22
23
  const parsed = schema.safeParse(toVerify, {})
23
24
  if (!parsed.success) {
24
- throwParseError(toVerify, errorMessage, parsed)
25
+ throwParseError(toVerify, errorMessage, hint, parsed)
25
26
  }
26
27
  return parsed.data
27
28
  }
@@ -29,10 +30,15 @@ export function verifySchema<T extends z.Schema>(
29
30
  function throwParseError(
30
31
  toVerify: unknown,
31
32
  errorMessage: string | ((id: string | undefined) => string),
33
+ hint: string | ((id: string | undefined) => string),
32
34
  parsed: z.SafeParseError<unknown>,
33
35
  ) {
34
36
  const id = z.object({ id: z.string() }).safeParse(toVerify).data?.id
35
37
  const message =
36
38
  typeof errorMessage === "string" ? errorMessage : errorMessage(id)
37
- throw new AstroError(message, fromZodError(parsed.error).toString())
39
+ const hintFinal = typeof hint === "string" ? hint : hint(id)
40
+ const issues = parsed.error.errors
41
+ .map((e) => `- ${e.path.join(".")}: ${e.message}`)
42
+ .join("\n")
43
+ throw new AstroError(message, `${hintFinal}\n\n${issues}`)
38
44
  }