@cat-factory/app 0.132.0 → 0.133.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.
@@ -1,7 +1,8 @@
1
- import { defineModule } from '@modular-vue/core'
2
1
  import type { AnyModuleDescriptor } from '@modular-vue/core'
3
2
  import { createRegistry } from '@modular-vue/runtime'
4
3
  import type { ModuleRegistry } from '@modular-vue/runtime'
4
+ import { navigationModule } from '~/modular/nav-contributions'
5
+ import type { AppSlots, NavGates } from '~/modular/nav-contributions'
5
6
 
6
7
  /**
7
8
  * modular-vue registry for the `@cat-factory/app` layer (slice 0 of the
@@ -13,21 +14,29 @@ import type { ModuleRegistry } from '@modular-vue/runtime'
13
14
  * contributes its own, all through the same seam. The registry is resolved and
14
15
  * installed by `app/plugins/modular.client.ts`.
15
16
  *
16
- * Slice 0 wires the plumbing behind ZERO behaviour change: the one first-party
17
- * module carries no navigation / slots / component, so nothing new renders.
18
- * Later slices convert real areas (navigation, result views, wizards, inspector
19
- * panels) into modules registered here.
17
+ * Slice 1 registers the first real feature module: `cat-factory:navigation`
18
+ * contributes the whole nav/command catalog to the `nav` slot, gated reactively
19
+ * by a `gates` service + `navSlotFilter` and rendered by `SideBar`, `CommandBar`,
20
+ * and `BoardToolbar` via `useReactiveSlots`. Later slices add result views,
21
+ * wizards, and inspector panels as further modules registered here.
20
22
  */
21
23
 
22
24
  /**
23
- * First-party modules the layer always registers. Kept tiny on purpose for
24
- * slice 0 a single descriptor with no contributions, present only to prove the
25
- * registration pipeline end to end and give the seam a stable anchor. Real
26
- * feature modules land here as later slices convert each area.
25
+ * The layer's shared-dependency shape (grows as later slices wire more deps).
26
+ * A `type` (not `interface`) so it satisfies the registry's
27
+ * `Record<string, any>` dependency constraint an interface lacks the implicit
28
+ * index signature a type-literal has.
27
29
  */
28
- const FIRST_PARTY_MODULES: readonly AnyModuleDescriptor[] = [
29
- defineModule({ id: 'cat-factory:core', version: '1.0.0' }),
30
- ]
30
+ export type AppDeps = {
31
+ /** Reactive RBAC/availability gates the nav `slotFilter` reads. */
32
+ gates: NavGates
33
+ }
34
+
35
+ /**
36
+ * First-party modules the layer always registers. Real feature modules land
37
+ * here as each area is converted; slice 1 adds the navigation catalog.
38
+ */
39
+ const FIRST_PARTY_MODULES: readonly AnyModuleDescriptor[] = [navigationModule]
31
40
 
32
41
  /**
33
42
  * Consumer-contributed modules, collected before the layer resolves its
@@ -65,9 +74,18 @@ export function __resetConsumerModulesForTest(): void {
65
74
  * contributed via {@link registerAppModule}. A new registry per call because
66
75
  * `resolve()` / `resolveManifest()` are single-commit; the install plugin calls
67
76
  * this exactly once at client startup (`ssr: false`, so a singleton app).
77
+ *
78
+ * `deps.gates` is the reactive gate service the nav `slotFilter` reads; it's
79
+ * built in the install plugin (Vue context) and registered as a `service` so
80
+ * `useReactiveSlots` tracks it. The `nav` slot default is seeded empty so the
81
+ * key always exists even before any module (or with only consumer modules)
82
+ * contributes.
68
83
  */
69
- export function createAppRegistry(): ModuleRegistry<Record<string, unknown>> {
70
- const registry = createRegistry<Record<string, unknown>>({})
84
+ export function createAppRegistry(deps: AppDeps): ModuleRegistry<AppDeps, AppSlots> {
85
+ const registry = createRegistry<AppDeps, AppSlots>({
86
+ services: { gates: deps.gates },
87
+ slots: { nav: [] },
88
+ })
71
89
  for (const mod of [...FIRST_PARTY_MODULES, ...consumerModules]) {
72
90
  registry.register(mod)
73
91
  }
@@ -1,5 +1,7 @@
1
1
  import { installModularApp } from '@modular-vue/nuxt/runtime'
2
2
  import { createAppRegistry } from '~/modular/registry'
3
+ import { navSlotFilter } from '~/modular/nav-contributions'
4
+ import { createNavGates } from '~/modular/nav-gates'
3
5
 
4
6
  /**
5
7
  * Wire the modular-vue registry into the Nuxt app (slice 0 of the modular-vue
@@ -16,17 +18,23 @@ import { createAppRegistry } from '~/modular/registry'
16
18
  *
17
19
  * `ssr: false`, so this runs once on the client and a singleton registry is
18
20
  * fine. `installModularApp` is the router-owning path: it grafts each module's
19
- * routes onto Nuxt's router (none yet — slice 0 modules are non-routed) and
20
- * installs the modular contexts (shared deps, navigation, slots) app-wide. The
21
- * resolved manifest is exposed as `$modular` for later slices; nothing reads it
22
- * yet, which is what keeps this behaviour-neutral.
21
+ * routes onto Nuxt's router (none yet — the nav modules are non-routed) and
22
+ * installs the modular contexts (shared deps, navigation, slots) app-wide.
23
+ *
24
+ * Slice 1 wires the reactive nav gating here: `createNavGates()` builds the
25
+ * reactive `gates` service (Pinia + composables are available in a `post`
26
+ * plugin), which the registry registers as a `service` and `navSlotFilter` reads
27
+ * per item. The shells consume the gated `nav` slot through `useReactiveSlots`,
28
+ * so a permission/connection flip re-gates them with no `recalculateSlots()`.
23
29
  */
24
30
  export default defineNuxtPlugin({
25
31
  name: 'cat-factory:modular',
26
32
  enforce: 'post',
27
33
  setup(nuxtApp) {
28
- const registry = createAppRegistry()
29
- const manifest = installModularApp({ vueApp: nuxtApp.vueApp, $router: useRouter() }, registry)
34
+ const registry = createAppRegistry({ gates: createNavGates() })
35
+ const manifest = installModularApp({ vueApp: nuxtApp.vueApp, $router: useRouter() }, registry, {
36
+ slotFilter: navSlotFilter,
37
+ })
30
38
  return { provide: { modular: manifest } }
31
39
  },
32
40
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cat-factory/app",
3
- "version": "0.132.0",
3
+ "version": "0.133.0",
4
4
  "description": "Reusable Nuxt layer for the Agent Architecture Board SPA (components, stores, composables, pages). Consume it from a thin deployment app via `extends: ['@cat-factory/app']` and point it at your backend with NUXT_PUBLIC_API_BASE. See deploy/frontend for an example.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -21,8 +21,8 @@
21
21
  "@modular-frontend/core": "^0.1.0",
22
22
  "@modular-vue/core": "^1.0.1",
23
23
  "@modular-vue/nuxt": "^0.1.1",
24
- "@modular-vue/runtime": "^1.0.1",
25
- "@modular-vue/vue": "^1.0.0",
24
+ "@modular-vue/runtime": "^1.1.0",
25
+ "@modular-vue/vue": "^1.1.0",
26
26
  "@nuxt/ui": "^4.9.0",
27
27
  "@nuxtjs/i18n": "^10.4.1",
28
28
  "@pinia/nuxt": "^0.11.3",