@frigear-nu/menu 0.0.8 → 0.0.10

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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@frigear-nu/menu",
3
3
  "configKey": "menus",
4
- "version": "0.0.8",
4
+ "version": "0.0.10",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.3",
7
7
  "unbuild": "unknown"
package/dist/module.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { defineNuxtModule, createResolver, addImports, hasNuxtModule, addTypeTemplate, addTemplate, addPlugin, addServerImports } from '@nuxt/kit';
2
- import { registerModule } from '@frigear-nu/module-kit/utils';
1
+ import { defineNuxtModule, createResolver, addImports, hasNuxtModule, addTypeTemplate, addPlugin, addServerImports } from '@nuxt/kit';
2
+ import { registerModule, defineVirtualRegistry } from '@frigear-nu/module-kit/utils';
3
3
 
4
4
  const DEFAULT_CONTENT_COLLECTION = "config";
5
5
  const DEFAULT_CONTENT_FIELD = "navigation";
@@ -39,20 +39,32 @@ const module$1 = defineNuxtModule({
39
39
  }
40
40
  `
41
41
  });
42
- nuxt.hook("modules:done", () => {
43
- const staticItems = nuxt.options.menus?._extensions ?? {};
44
- const sources = Array.isArray(nuxt.options.menus?._sources) ? nuxt.options.menus._sources : [];
45
- const sourcesTemplate = addTemplate({
46
- filename: "#menus/sources.mjs",
47
- write: true,
48
- getContents: () => `
42
+ defineVirtualRegistry(nuxt, {
43
+ filename: "#menus/sources.mjs",
44
+ alias: "#menus/sources",
45
+ collect: () => ({
46
+ staticItems: nuxt.options.menus?._extensions ?? {},
47
+ sources: Array.isArray(nuxt.options.menus?._sources) ? nuxt.options.menus._sources : []
48
+ }),
49
+ contents: ({ staticItems, sources }) => `
50
+ export const staticItems = ${JSON.stringify(staticItems)}
51
+ ${sources.map((source, index) => `import source${index} from ${JSON.stringify(source.file)}`).join("\n")}
52
+ export const sources = [${sources.map((source, index) => `{ menu: ${JSON.stringify(source.menu)}, source: source${index} }`).join(", ")}]
53
+ `,
54
+ resolved: ({ staticItems }) => nuxt.callHook("menus:resolved", staticItems)
55
+ });
56
+ defineVirtualRegistry(nuxt, {
57
+ filename: "#menus/server-sources",
58
+ target: "server",
59
+ collect: () => ({
60
+ staticItems: nuxt.options.menus?._extensions ?? {},
61
+ sources: Array.isArray(nuxt.options.menus?._sources) ? nuxt.options.menus._sources : []
62
+ }),
63
+ contents: ({ staticItems, sources }) => `
49
64
  export const staticItems = ${JSON.stringify(staticItems)}
50
65
  ${sources.map((source, index) => `import source${index} from ${JSON.stringify(source.file)}`).join("\n")}
51
66
  export const sources = [${sources.map((source, index) => `{ menu: ${JSON.stringify(source.menu)}, source: source${index} }`).join(", ")}]
52
67
  `
53
- });
54
- nuxt.options.alias["#menus/sources"] = sourcesTemplate.dst;
55
- nuxt.callHook("menus:resolved", staticItems);
56
68
  });
57
69
  addPlugin(resolver.resolve("./runtime/app/plugins/menus"));
58
70
  addServerImports({
@@ -1,3 +1,15 @@
1
- import { type MenuItem } from '../utils/menu.js';
2
1
  import type { H3Event } from 'h3';
3
- export declare const useMenu: (event: H3Event, path: string) => Promise<MenuItem[]>;
2
+ import { type MenuItem } from '../utils/menu.js';
3
+ /**
4
+ * Server counterpart of the client `useMenu`: resolves a menu's (or menu group's) items merged from
5
+ * every source - `extendMenu` items, `runtime/menus.ts` sources and the `@nuxt/content` source -
6
+ * with content items first, sorted by `order`. Accepts the same paths, wildcards included.
7
+ * Labels are not translated; pass `locale` to read a localized content collection.
8
+ *
9
+ * ```ts
10
+ * export default defineEventHandler(event => useMenu(event, 'dashboard.*'))
11
+ * ```
12
+ */
13
+ export declare const useMenu: (event: H3Event, path: string, options?: {
14
+ locale?: string;
15
+ }) => Promise<MenuItem[]>;
@@ -1,27 +1,45 @@
1
- import { collectMenuItems, matchesMenuGroup, parseMenuPath, sortByOrder } from "../utils/menu.js";
2
1
  import { useRuntimeConfig } from "nitropack/runtime";
3
- export const useMenu = async (event, path) => {
4
- const parsed = parseMenuPath(path);
5
- const { menu } = parsed;
6
- const config = useRuntimeConfig(event);
7
- const menus = config.public.menus;
8
- const registered = collectMenuItems(menus[menu], parsed);
9
- const content = await loadContentItems(menu, parsed, "");
10
- const result = sortByOrder([...registered, ...content]);
11
- return result;
12
- };
2
+ import { staticItems, sources } from "#menus/server-sources";
3
+ import { collectMenuItems, matchesMenuGroup, parseMenuPath, sortByOrder } from "../utils/menu.js";
4
+ import { menus, pushMenuItems, resetMenus } from "../app/utils/state.js";
5
+ let registered;
6
+ function registerItems() {
7
+ registered ??= (async () => {
8
+ resetMenus();
9
+ for (const [menu, groups] of Object.entries(staticItems)) {
10
+ for (const [group, items] of Object.entries(groups)) {
11
+ if (items.length > 0) pushMenuItems(menu, group, items);
12
+ }
13
+ }
14
+ for (const { menu, source } of sources) {
15
+ const items = [];
16
+ await source(items);
17
+ if (items.length > 0) pushMenuItems(menu, "", items);
18
+ }
19
+ })().catch((error) => {
20
+ registered = void 0;
21
+ throw error;
22
+ });
23
+ return registered;
24
+ }
13
25
  function localizedCollectionName(name, locale) {
14
26
  return locale ? `${name}_${locale.replace(/-/g, "_")}` : name;
15
27
  }
16
- async function loadContentItems(menu, parsed, locale) {
17
- const config = useRuntimeConfig().public.menus ?? {};
28
+ async function loadContentItems(event, menu, parsed, locale) {
29
+ const config = useRuntimeConfig(event).public.menus ?? {};
18
30
  const source = config.content?.[menu];
19
31
  if (!source) return [];
20
- const collection = localizedCollectionName(source.collection, locale);
21
- const entry = await queryCollection(collection).first();
32
+ const { queryCollection } = await import("@nuxt/content/server");
33
+ const entry = await queryCollection(event, localizedCollectionName(source.collection, locale)).first();
22
34
  const items = entry?.[source.field] ?? [];
23
35
  return items.filter((item) => {
24
36
  const group = item.group ?? "";
25
37
  return parsed.wildcard ? matchesMenuGroup(group, parsed.group) : group === parsed.group;
26
38
  });
27
39
  }
40
+ export const useMenu = async (event, path, options = {}) => {
41
+ const parsed = parseMenuPath(path);
42
+ await registerItems();
43
+ const content = await loadContentItems(event, parsed.menu, parsed, options.locale);
44
+ return sortByOrder([...content, ...collectMenuItems(menus[parsed.menu], parsed)]);
45
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frigear-nu/menu",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
4
4
  "description": "Named, shareable navigation menus - modules contribute items (extendMenu / a runtime/menus.ts source) and/or Nuxt Content, consumers read them via useMenu and render them however they like.",
5
5
  "homepage": "https://docs.frigear.dev/modules/menu",
6
6
  "repository": {
@@ -31,7 +31,7 @@
31
31
  ],
32
32
  "dependencies": {
33
33
  "@nuxt/kit": "^4.6.0",
34
- "@frigear-nu/module-kit": "0.1.6",
34
+ "@frigear-nu/module-kit": "1.0.0",
35
35
  "zod": "^4.6.5"
36
36
  },
37
37
  "devDependencies": {