@nocobase/app-plugin-foundation 0.0.0-stage → 0.1.0-beta.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.
Files changed (220) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +86 -2
  3. package/dist/cli/index.d.ts +4 -0
  4. package/dist/cli/index.d.ts.map +1 -0
  5. package/dist/cli/index.js +16 -0
  6. package/dist/cli/index.js.map +1 -0
  7. package/dist/cli/module-manifest.d.ts +9 -0
  8. package/dist/cli/module-manifest.d.ts.map +1 -0
  9. package/dist/cli/module-manifest.js +12 -0
  10. package/dist/cli/module-manifest.js.map +1 -0
  11. package/dist/client/api.d.ts +17 -0
  12. package/dist/client/api.d.ts.map +1 -0
  13. package/dist/client/api.js +51 -0
  14. package/dist/client/api.js.map +1 -0
  15. package/dist/client/business-modules.d.ts +5 -0
  16. package/dist/client/business-modules.d.ts.map +1 -0
  17. package/dist/client/business-modules.js +81 -0
  18. package/dist/client/business-modules.js.map +1 -0
  19. package/dist/client/components/capability-icons.d.ts +4 -0
  20. package/dist/client/components/capability-icons.d.ts.map +1 -0
  21. package/dist/client/components/capability-icons.js +17 -0
  22. package/dist/client/components/capability-icons.js.map +1 -0
  23. package/dist/client/components/format.d.ts +7 -0
  24. package/dist/client/components/format.d.ts.map +1 -0
  25. package/dist/client/components/format.js +42 -0
  26. package/dist/client/components/format.js.map +1 -0
  27. package/dist/client/components/foundation-page.d.ts +15 -0
  28. package/dist/client/components/foundation-page.d.ts.map +1 -0
  29. package/dist/client/components/foundation-page.js +207 -0
  30. package/dist/client/components/foundation-page.js.map +1 -0
  31. package/dist/client/components/foundation-translation.d.ts +12 -0
  32. package/dist/client/components/foundation-translation.d.ts.map +1 -0
  33. package/dist/client/components/foundation-translation.js +19 -0
  34. package/dist/client/components/foundation-translation.js.map +1 -0
  35. package/dist/client/components/module-matrix.d.ts +9 -0
  36. package/dist/client/components/module-matrix.d.ts.map +1 -0
  37. package/dist/client/components/module-matrix.js +56 -0
  38. package/dist/client/components/module-matrix.js.map +1 -0
  39. package/dist/client/components/ui/button.d.ts +8 -0
  40. package/dist/client/components/ui/button.d.ts.map +1 -0
  41. package/dist/client/components/ui/button.js +35 -0
  42. package/dist/client/components/ui/button.js.map +1 -0
  43. package/dist/client/components/ui/collapsible.d.ts +7 -0
  44. package/dist/client/components/ui/collapsible.d.ts.map +1 -0
  45. package/dist/client/components/ui/collapsible.js +13 -0
  46. package/dist/client/components/ui/collapsible.js.map +1 -0
  47. package/dist/client/components/ui/table.d.ts +11 -0
  48. package/dist/client/components/ui/table.d.ts.map +1 -0
  49. package/dist/client/components/ui/table.js +28 -0
  50. package/dist/client/components/ui/table.js.map +1 -0
  51. package/dist/client/index.d.ts +6 -0
  52. package/dist/client/index.d.ts.map +1 -0
  53. package/dist/client/index.js +7 -0
  54. package/dist/client/index.js.map +1 -0
  55. package/dist/client/locales/de-DE.d.ts +4 -0
  56. package/dist/client/locales/de-DE.d.ts.map +1 -0
  57. package/dist/client/locales/de-DE.js +315 -0
  58. package/dist/client/locales/de-DE.js.map +1 -0
  59. package/dist/client/locales/en-US.d.ts +317 -0
  60. package/dist/client/locales/en-US.d.ts.map +1 -0
  61. package/dist/client/locales/en-US.js +315 -0
  62. package/dist/client/locales/en-US.js.map +1 -0
  63. package/dist/client/locales/es-ES.d.ts +4 -0
  64. package/dist/client/locales/es-ES.d.ts.map +1 -0
  65. package/dist/client/locales/es-ES.js +316 -0
  66. package/dist/client/locales/es-ES.js.map +1 -0
  67. package/dist/client/locales/fr-FR.d.ts +4 -0
  68. package/dist/client/locales/fr-FR.d.ts.map +1 -0
  69. package/dist/client/locales/fr-FR.js +316 -0
  70. package/dist/client/locales/fr-FR.js.map +1 -0
  71. package/dist/client/locales/id-ID.d.ts +4 -0
  72. package/dist/client/locales/id-ID.d.ts.map +1 -0
  73. package/dist/client/locales/id-ID.js +315 -0
  74. package/dist/client/locales/id-ID.js.map +1 -0
  75. package/dist/client/locales/index.d.ts +4 -0
  76. package/dist/client/locales/index.d.ts.map +1 -0
  77. package/dist/client/locales/index.js +14 -0
  78. package/dist/client/locales/index.js.map +1 -0
  79. package/dist/client/locales/ja-JP.d.ts +4 -0
  80. package/dist/client/locales/ja-JP.d.ts.map +1 -0
  81. package/dist/client/locales/ja-JP.js +315 -0
  82. package/dist/client/locales/ja-JP.js.map +1 -0
  83. package/dist/client/locales/pt-BR.d.ts +4 -0
  84. package/dist/client/locales/pt-BR.d.ts.map +1 -0
  85. package/dist/client/locales/pt-BR.js +316 -0
  86. package/dist/client/locales/pt-BR.js.map +1 -0
  87. package/dist/client/locales/vi-VN.d.ts +4 -0
  88. package/dist/client/locales/vi-VN.d.ts.map +1 -0
  89. package/dist/client/locales/vi-VN.js +315 -0
  90. package/dist/client/locales/vi-VN.js.map +1 -0
  91. package/dist/client/locales/zh-CN.d.ts +4 -0
  92. package/dist/client/locales/zh-CN.d.ts.map +1 -0
  93. package/dist/client/locales/zh-CN.js +315 -0
  94. package/dist/client/locales/zh-CN.js.map +1 -0
  95. package/dist/client/locales/zh-TW.d.ts +4 -0
  96. package/dist/client/locales/zh-TW.d.ts.map +1 -0
  97. package/dist/client/locales/zh-TW.js +315 -0
  98. package/dist/client/locales/zh-TW.js.map +1 -0
  99. package/dist/client/navigation.d.ts +8 -0
  100. package/dist/client/navigation.d.ts.map +1 -0
  101. package/dist/client/navigation.js +21 -0
  102. package/dist/client/navigation.js.map +1 -0
  103. package/dist/client/plugin.d.ts +11 -0
  104. package/dist/client/plugin.d.ts.map +1 -0
  105. package/dist/client/plugin.js +10 -0
  106. package/dist/client/plugin.js.map +1 -0
  107. package/dist/client/provider-inventory.d.ts +6 -0
  108. package/dist/client/provider-inventory.d.ts.map +1 -0
  109. package/dist/client/provider-inventory.js +49 -0
  110. package/dist/client/provider-inventory.js.map +1 -0
  111. package/dist/client/routes.d.ts +18 -0
  112. package/dist/client/routes.d.ts.map +1 -0
  113. package/dist/client/routes.js +41 -0
  114. package/dist/client/routes.js.map +1 -0
  115. package/dist/package.d.ts +2 -0
  116. package/dist/package.d.ts.map +1 -0
  117. package/dist/package.js +2 -0
  118. package/dist/package.js.map +1 -0
  119. package/dist/server/capabilities/data.d.ts +7 -0
  120. package/dist/server/capabilities/data.d.ts.map +1 -0
  121. package/dist/server/capabilities/data.js +108 -0
  122. package/dist/server/capabilities/data.js.map +1 -0
  123. package/dist/server/capabilities/index.d.ts +5 -0
  124. package/dist/server/capabilities/index.d.ts.map +1 -0
  125. package/dist/server/capabilities/index.js +24 -0
  126. package/dist/server/capabilities/index.js.map +1 -0
  127. package/dist/server/capabilities/intelligence.d.ts +4 -0
  128. package/dist/server/capabilities/intelligence.d.ts.map +1 -0
  129. package/dist/server/capabilities/intelligence.js +97 -0
  130. package/dist/server/capabilities/intelligence.js.map +1 -0
  131. package/dist/server/capabilities/messaging.d.ts +4 -0
  132. package/dist/server/capabilities/messaging.d.ts.map +1 -0
  133. package/dist/server/capabilities/messaging.js +108 -0
  134. package/dist/server/capabilities/messaging.js.map +1 -0
  135. package/dist/server/capabilities/people.d.ts +4 -0
  136. package/dist/server/capabilities/people.d.ts.map +1 -0
  137. package/dist/server/capabilities/people.js +151 -0
  138. package/dist/server/capabilities/people.js.map +1 -0
  139. package/dist/server/capabilities/platform.d.ts +10 -0
  140. package/dist/server/capabilities/platform.d.ts.map +1 -0
  141. package/dist/server/capabilities/platform.js +143 -0
  142. package/dist/server/capabilities/platform.js.map +1 -0
  143. package/dist/server/capabilities/processes.d.ts +3 -0
  144. package/dist/server/capabilities/processes.d.ts.map +1 -0
  145. package/dist/server/capabilities/processes.js +86 -0
  146. package/dist/server/capabilities/processes.js.map +1 -0
  147. package/dist/server/capabilities/types.d.ts +38 -0
  148. package/dist/server/capabilities/types.d.ts.map +1 -0
  149. package/dist/server/capabilities/types.js +23 -0
  150. package/dist/server/capabilities/types.js.map +1 -0
  151. package/dist/server/catalog.d.ts +3 -0
  152. package/dist/server/catalog.d.ts.map +1 -0
  153. package/dist/server/catalog.js +44 -0
  154. package/dist/server/catalog.js.map +1 -0
  155. package/dist/server/index.d.ts +6 -0
  156. package/dist/server/index.d.ts.map +1 -0
  157. package/dist/server/index.js +5 -0
  158. package/dist/server/index.js.map +1 -0
  159. package/dist/server/inventory.d.ts +48 -0
  160. package/dist/server/inventory.d.ts.map +1 -0
  161. package/dist/server/inventory.js +158 -0
  162. package/dist/server/inventory.js.map +1 -0
  163. package/dist/server/module-manifest.d.ts +10 -0
  164. package/dist/server/module-manifest.d.ts.map +1 -0
  165. package/dist/server/module-manifest.js +65 -0
  166. package/dist/server/module-manifest.js.map +1 -0
  167. package/dist/server/module-sources.d.ts +5 -0
  168. package/dist/server/module-sources.d.ts.map +1 -0
  169. package/dist/server/module-sources.js +535 -0
  170. package/dist/server/module-sources.js.map +1 -0
  171. package/dist/server/packages.d.ts +18 -0
  172. package/dist/server/packages.d.ts.map +1 -0
  173. package/dist/server/packages.js +62 -0
  174. package/dist/server/packages.js.map +1 -0
  175. package/dist/server/plugin.d.ts +4 -0
  176. package/dist/server/plugin.d.ts.map +1 -0
  177. package/dist/server/plugin.js +12 -0
  178. package/dist/server/plugin.js.map +1 -0
  179. package/dist/server/provider-inventory.d.ts +13 -0
  180. package/dist/server/provider-inventory.d.ts.map +1 -0
  181. package/dist/server/provider-inventory.js +180 -0
  182. package/dist/server/provider-inventory.js.map +1 -0
  183. package/dist/server/providers/foundation.d.ts +7 -0
  184. package/dist/server/providers/foundation.d.ts.map +1 -0
  185. package/dist/server/providers/foundation.js +24 -0
  186. package/dist/server/providers/foundation.js.map +1 -0
  187. package/dist/server/providers/index.d.ts +4 -0
  188. package/dist/server/providers/index.d.ts.map +1 -0
  189. package/dist/server/providers/index.js +6 -0
  190. package/dist/server/providers/index.js.map +1 -0
  191. package/dist/server/routes/index.d.ts +6 -0
  192. package/dist/server/routes/index.d.ts.map +1 -0
  193. package/dist/server/routes/index.js +54 -0
  194. package/dist/server/routes/index.js.map +1 -0
  195. package/dist/server/routes/schemas.d.ts +7 -0
  196. package/dist/server/routes/schemas.d.ts.map +1 -0
  197. package/dist/server/routes/schemas.js +138 -0
  198. package/dist/server/routes/schemas.js.map +1 -0
  199. package/dist/server/services/foundation.d.ts +37 -0
  200. package/dist/server/services/foundation.d.ts.map +1 -0
  201. package/dist/server/services/foundation.js +175 -0
  202. package/dist/server/services/foundation.js.map +1 -0
  203. package/dist/server/source-evidence.d.ts +19 -0
  204. package/dist/server/source-evidence.d.ts.map +1 -0
  205. package/dist/server/source-evidence.js +169 -0
  206. package/dist/server/source-evidence.js.map +1 -0
  207. package/dist/server/tokens.d.ts +12 -0
  208. package/dist/server/tokens.d.ts.map +1 -0
  209. package/dist/server/tokens.js +3 -0
  210. package/dist/server/tokens.js.map +1 -0
  211. package/dist/shared/available-capabilities.d.ts +6 -0
  212. package/dist/shared/available-capabilities.d.ts.map +1 -0
  213. package/dist/shared/available-capabilities.js +66 -0
  214. package/dist/shared/available-capabilities.js.map +1 -0
  215. package/dist/shared/foundation.d.ts +142 -0
  216. package/dist/shared/foundation.d.ts.map +1 -0
  217. package/dist/shared/foundation.js +39 -0
  218. package/dist/shared/foundation.js.map +1 -0
  219. package/package.json +106 -3
  220. package/skills/nocobase-app-plugin-foundation/SKILL.md +68 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,32 @@
1
+ # @nocobase/app-plugin-foundation
2
+
3
+ ## 0.1.0-beta.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 62da032: Add App Foundation for administrators with unrestricted access: a dynamic capability overview, live statistics, business-module associations, qualitative value explanations, and resolved provider package versions. Collect evidence read-only inside the plugin, include recognized installed capabilities and registered extensions, and distinguish installation, registration, configuration and use. Support all ten Client locales and responsive layouts.
8
+
9
+ Derive module associations from registered navigation, authentication and authorization declarations, bounded value-reachable source references, and explicitly matched API handlers. Ignore unused imports, type-only references and unrelated handlers. Keep unsupported or unreadable evidence undetermined rather than guessing usage; report incomplete counts and refresh failures. Cache successful overviews for 30 seconds with a manual refresh action.
10
+
11
+ Expose optional immutable Client and Server registration snapshots so the plugin can discover provider-only and locales-only registrations without reloading contributions. Keep collection, classification, authorization and presentation in the Foundation plugin.
12
+
13
+ Show deduplicated related package names and versions once within capability details, keeping technical discovery counts and diagnostic evidence internal. Export a permission-preserving helper for placing the Foundation link last in an existing settings navigation group.
14
+
15
+ ### Patch Changes
16
+
17
+ - 62da032: Install and register App Foundation in the default template so unrestricted administrators can inspect an empty application immediately. Provide a localized settings group that merges into application-owned settings as business administration is added, while retaining the protected /foundation route and server authorization.
18
+ - 62da032: Preserve application module capability associations in a validated deployment artifact generated by the Foundation CLI build hook, without shipping business source code. Register the hook in the default template. Read all permission configuration pages before reporting totals, and synchronize the generated UI Registry catalog.
19
+ - Updated dependencies [62da032]
20
+ - Updated dependencies [8b30952]
21
+ - Updated dependencies [4f0d96e]
22
+ - @nocobase/app-client@4.0.0-beta.1
23
+ - @nocobase/app-server@3.0.0-beta.1
24
+ - @nocobase/app-cli@1.0.0-beta.26
25
+ - @nocobase/app-plugin-authentication@2.0.0-beta.12
26
+ - @nocobase/app-plugin-authorization@1.0.0-beta.30
27
+
28
+ ## 0.0.1
29
+
30
+ ### Patch Changes
31
+
32
+ - Add the initial plugin scaffold.
package/README.md CHANGED
@@ -1,3 +1,87 @@
1
- # Temporary Holding Version
1
+ # @nocobase/app-plugin-foundation
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Shows which NocoBase Core capabilities an application uses, with live evidence, for its unrestricted administrators.
4
+
5
+ The App Foundation page derives its visible capability items from the current application's recognized installed providers, Core runtime evidence and explicit Client/Server plugin registrations. Its total is dynamic. Built-in collectors provide usage facts for recognized capabilities, and registered Pro or custom plugins without a matching adapter appear as independent extension items with their own package title and version. An unknown extension is never labeled in use solely because it is registered.
6
+
7
+ ## Registering the plugin
8
+
9
+ ```ts
10
+ // server/plugins.ts
11
+ import foundation from '@nocobase/app-plugin-foundation/server';
12
+
13
+ // client/plugins.ts
14
+ import foundation from '@nocobase/app-plugin-foundation/client';
15
+ // foundation() adds the page at /foundation with a menu entry; foundation({ path, navigation: false }) moves it or
16
+ // leaves it out of the menu, and foundation({ routes: false }) leaves the routing to the application, which renders
17
+ // `FoundationPage` from `@nocobase/app-plugin-foundation/client/pages`.
18
+ ```
19
+
20
+ The plugin needs the authentication and authorization plugins, which every application built from the default template registers. Its page reads the query cache the application's routes provide.
21
+
22
+ ## Who can see it
23
+
24
+ Only an identity with unrestricted access, such as a holder of the root Permission Set (`authorization.permissionSets.rootSet`, `root` by default), opens the page or reads `GET /api/foundation/overview`. It is not a grant: no Permission Set can give it to anyone else. Everyone else gets `403 FOUNDATION_FORBIDDEN`.
25
+
26
+ ## How it collects
27
+
28
+ Everything is collected by this plugin, read-only, when the page asks; no other plugin or agent reports to it. It reads the Collections of the default connection, the application's configuration, the services registered in its container, the migration history, and the `package.json` of each package the application resolves from its own root. A result is cached for 30 seconds; `?refresh=true` collects again. Each capability gets 10 seconds, and four read at a time.
29
+
30
+ The rules every capability follows:
31
+
32
+ - An installed package proves nothing: a capability is in use only when the application is wired to it, such as a lifecycle store, an enabled schedule, a connected mailbox or a configured channel.
33
+ - Zero uses is not "not used": a lifecycle no record has moved through yet is in use.
34
+ - Records are counted only in the application's own Collections. The Collections NocoBase packages keep are listed in `server/catalog.ts`; a package that adds one under a new name must be added there, or its records count as the application's. Views are not counted, so no row is counted twice.
35
+ - A capability whose evidence cannot be read has no status rather than a guessed one, and a count that could only be read in part is marked as a lower bound. No driver error reaches the response.
36
+ - Accepted notification deliveries are accepted by the provider, which is not the same as received.
37
+
38
+ ## What it does not do yet
39
+
40
+ - It does not claim exhaustive module associations: opaque service wiring, computed requests and unsupported source layouts remain unassociated.
41
+ - It reads the default connection only.
42
+ - Organization support remains unrecognized. The audit category says no supported provider has been recognized; it does not claim that additional Pro or custom providers cannot supply audit capabilities.
43
+ - It does not verify migration checksums, report upgrade times or official test results, all of which need evidence it cannot read today.
44
+ - The interface capability reports the languages the server offers; it cannot count the application's pages, which the application's own router owns.
45
+
46
+ ## Verification
47
+
48
+ ```bash
49
+ pnpm --filter @nocobase/app-plugin-foundation lint
50
+ pnpm --filter @nocobase/app-plugin-foundation typecheck
51
+ pnpm --filter @nocobase/app-plugin-foundation test
52
+ pnpm --filter @nocobase/app-plugin-foundation build
53
+ ```
54
+
55
+ ## Dynamic capabilities and provider discovery
56
+
57
+ The built-in collector catalog is an ordered set of adapters, not the complete universe of NocoBase capabilities and not a fixed display denominator. The optional `availableCapabilities` response contains runtime-specific items. Existing `capabilities` observations remain for compatible consumers. The browser merges Client-only registration evidence into the same pure selection model, without replacing server usage facts.
58
+
59
+ The host retains the explicit Server registration snapshot (`app.registeredServerPlugins`) and Client registration snapshot (`runtime.registeredPlugins`). This covers plugins contributing only services or locales, independently of package scope, naming conventions or a hardcoded provider list. The Foundation plugin reads these snapshots; other plugins do not need a reporting integration. Older hosts fall back to partial public contribution evidence.
60
+
61
+ Known providers are associated with supported capability groups. A registered provider with no category adapter becomes an independent `extension:<packageName>` item, so a newly injected Pro or custom plugin can grow the band without editing a capability enum. The item uses the installed or resolved manifest title and version and has an undetermined usage status. Its presence means registration, not configuration or use. Unregistering an unknown extension removes its item. Recognized installed capabilities stay in the band as unused when there is no current registration or usage evidence; installation alone never marks them active. Historical database records do not establish current use after unregistration.
62
+
63
+ Discovery also reads direct application dependencies and known providers for the package inventory. Generic `./server` exports do not identify plugins. Filesystem locations, dependency URLs and plugin options never reach the API response. Source labels come from an explicit Foundation catalog; an npm scope or proprietary license alone verifies neither official origin nor Pro edition.
64
+
65
+ The registration registry establishes which Client/Server plugins were connected, but cannot generically infer the semantics or actual usage of arbitrary plugin code. Foundation-owned adapters still provide detailed configuration, metrics and Collection ownership rules. Unknown runtime extensions keep their usage pending; business totals are withheld when unknown ownership could mix plugin rows into business data. CLI-only and application-local modules without Client/Server registration are not counted as registered extension items. This page is not an exhaustive inventory of every function exported by every package.
66
+
67
+ Refresh collects current evidence again. Configuration collections are read in stable pages rather than treating the first 1000 records as an exact total; a failed page leaves the statistic unavailable. Client resources cover all ten supported locales.
68
+
69
+ ## Business modules and capability matrix
70
+
71
+ The plugin derives modules from the current Client navigation tree. A top-level menu page or group is a module; its child pages, drawers and tabs belong to that module. Titles use the owning application's or plugin's locale namespace. Guest routes and Foundation itself are excluded. Adding, removing or renaming registered routes updates the matrix without an application-specific module list. Matrix columns use the same dynamic capability list as the band, including registered Pro and other extensions.
72
+
73
+ Associations have explicit evidence: a registered page uses the interface, required authentication uses accounts, and explicit page authorization uses permissions. A plugin-owned page can establish its provider's single recognized category; a multi-category package alone cannot establish which capability the page uses. The Foundation server parses readable page declarations and follows referenced value symbols from the selected page export through local aliases, re-exports, functions and components. Literal API-client requests, including templates with dynamic path segments, are matched by HTTP method and path to explicit root-mounted Hono endpoints. Only those endpoint handlers and their referenced values contribute backend dependencies. Unused imports, unrelated exports in a barrel/shared file, uncalled class methods, other endpoints and unreferenced routers do not establish module use. Installation and global registration alone never fill the matrix. These checks identify static integration dependencies rather than proof of past execution; opaque dependency injection and generic request wrappers stay unassociated instead of borrowing a provider's complete import graph.
74
+
75
+ The parser reads files without evaluating application code or invoking page loaders. Package-local real paths, at most 400 source files per package and 512 KB per file bound the scan; filesystem paths, code and raw errors are absent from the response. This server-only parser uses TypeScript as a runtime dependency. Results share the overview cache and Refresh operation and the existing unrestricted administrator boundary. The matrix has no storage, migration or new kernel change.
76
+
77
+ Source discovery currently supports conventional `client/routes` entries, relative imports, package `imports` aliases and explicitly root-mounted API routers. Loader factories, computed imports, component overrides and alternate entry layouts may be unavailable. Register `foundation` from `@nocobase/app-plugin-foundation/cli` in `cli/plugins.ts` (the default template does this). Its `afterServerBuild` hook runs `pnpm nocobase foundation modules build` to write `dist/server/foundation-modules.json`. This versioned, application-bound artifact preserves only route/provider associations, not source code, absolute paths or configuration values. Repeated generation produces identical bytes; the runtime validates it and uses it only when application page declarations are absent. Existing deployed applications must rebuild after registering this CLI contribution to gain the artifact. Deployed applications without readable page declarations or a valid build artifact retain navigation and permission evidence; opaque backend wiring and unsupported plugins stay unassociated. A blank cell means not identified, never proof that the module does not use the capability. No per-module execution numbers are inferred. Hover or focus a module tag to highlight its capabilities; select a matrix checkmark to read its integration evidence and the work that would otherwise need to be implemented. On narrow screens the matrix becomes module cards.
78
+
79
+ The capability detail lists its automatically associated business modules beside the application evidence, so readers can connect a shared capability to their own business before inspecting package names. Static API dependency matching respects the request method (`GET` when omitted) as well as the path; computed methods stay unassociated, and type-only re-exports do not establish dependencies. A failed refresh retains the last successful result with a visible warning and unchanged collection time. If a refresh returns `401` or `403`, the page hides cached internals and shows the access boundary instead.
80
+
81
+ ## Sidebar grouping
82
+
83
+ Use `foundation({ settingsGroup: true })` in a bare application to wrap the protected page in a localized System settings group. The default template enables this on initial creation. The group disappears when its page is denied; the navigation helper merges it into the application settings group when that group becomes available.
84
+
85
+ The host can call `groupFoundationNavigation(items)` from `@nocobase/app-plugin-foundation/client` in its existing `client/lib/navigation-transform.ts` hook, after permission filtering. The helper places an already-visible Foundation entry last in the existing `settings` navigation group, avoiding a separate sidebar group gap. Pass the host’s group name as the second argument when different. It preserves route identity, `/foundation`, authorization and other navigation metadata, never creates a hidden entry and leaves Foundation standalone if no settings group exists. The App needs only the hook call; grouping logic stays in this plugin and does not change Core or the sidebar renderer.
86
+
87
+ Related package names and versions appear once inside the selected capability detail, combining the capability adapter's packages with providers classified into that capability and deduplicating by package name. Discovery counts and diagnostic evidence remain internal and are not rendered on the value page. Unclassified registered extensions remain selectable in the capability band and display their own package and version without treating registration as proof of use.
@@ -0,0 +1,4 @@
1
+ import { type AppCliPlugin } from '@nocobase/app-cli';
2
+ declare const foundationCli: AppCliPlugin;
3
+ export default foundationCli;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGvE,QAAA,MAAM,aAAa,EAAE,YAWnB,CAAC;AACH,eAAe,aAAa,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { defineCliPlugin } from '@nocobase/app-cli';
2
+ import BuildModuleManifest from './module-manifest.js';
3
+ const foundationCli = defineCliPlugin({
4
+ packageName: '@nocobase/app-plugin-foundation',
5
+ devCommands: { 'modules:build': BuildModuleManifest },
6
+ buildHooks: {
7
+ afterServerBuild: [
8
+ {
9
+ label: 'Collect Foundation module associations',
10
+ command: ['pnpm', 'nocobase', 'foundation', 'modules', 'build'],
11
+ },
12
+ ],
13
+ },
14
+ });
15
+ export default foundationCli;
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAqB,MAAM,mBAAmB,CAAC;AACvE,OAAO,mBAAmB,MAAM,sBAAsB,CAAC;AAEvD,MAAM,aAAa,GAAiB,eAAe,CAAC;IAClD,WAAW,EAAE,iCAAiC;IAC9C,WAAW,EAAE,EAAE,eAAe,EAAE,mBAAmB,EAAE;IACrD,UAAU,EAAE;QACV,gBAAgB,EAAE;YAChB;gBACE,KAAK,EAAE,wCAAwC;gBAC/C,OAAO,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,CAAC;aAChE;SACF;KACF;CACF,CAAC,CAAC;AACH,eAAe,aAAa,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { AppCommand } from '@nocobase/app-cli';
2
+ export default class BuildModuleManifest extends AppCommand {
3
+ static summary: string;
4
+ run(): Promise<{
5
+ readonly routes: number;
6
+ readonly complete: boolean;
7
+ }>;
8
+ }
9
+ //# sourceMappingURL=module-manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-manifest.d.ts","sourceRoot":"","sources":["../../cli/module-manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,MAAM,CAAC,OAAO,OAAO,mBAAoB,SAAQ,UAAU;IACzD,OAAgB,OAAO,SACwC;IAElD,GAAG,IAAI,OAAO,CAAC;QAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;KAC5B,CAAC;CAQH"}
@@ -0,0 +1,12 @@
1
+ import { AppCommand } from '@nocobase/app-cli';
2
+ export default class BuildModuleManifest extends AppCommand {
3
+ static summary = 'Preserve Foundation module associations in the deployment.';
4
+ async run() {
5
+ await this.parse(BuildModuleManifest);
6
+ const { writeModuleManifest } = await import('../server/module-manifest.js');
7
+ const result = await writeModuleManifest(this.rootDir);
8
+ this.log(`Preserved ${result.routes} Foundation route associations.`);
9
+ return result;
10
+ }
11
+ }
12
+ //# sourceMappingURL=module-manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-manifest.js","sourceRoot":"","sources":["../../cli/module-manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,MAAM,CAAC,OAAO,OAAO,mBAAoB,SAAQ,UAAU;IACzD,MAAM,CAAU,OAAO,GACrB,4DAA4D,CAAC;IAExD,KAAK,CAAC,GAAG;QAId,MAAM,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACtC,MAAM,EAAE,mBAAmB,EAAE,GAC3B,MAAM,MAAM,CAAC,8BAA8B,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvD,IAAI,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,MAAM,iCAAiC,CAAC,CAAC;QACtE,OAAO,MAAM,CAAC;IAChB,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { type ApiClient } from '@nocobase/app-client';
2
+ import { type FoundationOverview } from '../shared/foundation.js';
3
+ /** Reads the overview. Every call is a GET; the plugin writes nothing. */
4
+ export declare function fetchFoundationOverview(api: ApiClient, options?: {
5
+ readonly refresh?: boolean;
6
+ }): Promise<FoundationOverview>;
7
+ export declare const FOUNDATION_OVERVIEW_QUERY_KEY: readonly ["foundation", "overview"];
8
+ export type FoundationLoadError = 'forbidden' | 'failed';
9
+ export interface FoundationOverviewState {
10
+ readonly overview?: FoundationOverview;
11
+ readonly error?: FoundationLoadError;
12
+ readonly loading: boolean;
13
+ /** Collects again on the server, bypassing its cache. */
14
+ readonly refresh: () => void;
15
+ }
16
+ export declare function useFoundationOverview(): FoundationOverviewState;
17
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../client/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,SAAS,EACf,MAAM,sBAAsB,CAAC;AAI9B,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,yBAAyB,CAAC;AAEjC,0EAA0E;AAC1E,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,SAAS,EACd,OAAO,GAAE;IAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAC3C,OAAO,CAAC,kBAAkB,CAAC,CAM7B;AAED,eAAO,MAAM,6BAA6B,qCAGhC,CAAC;AAEX,MAAM,MAAM,mBAAmB,GAAG,WAAW,GAAG,QAAQ,CAAC;AAEzD,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IACvC,QAAQ,CAAC,KAAK,CAAC,EAAE,mBAAmB,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,yDAAyD;IACzD,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;CAC9B;AAED,wBAAgB,qBAAqB,IAAI,uBAAuB,CAkC/D"}
@@ -0,0 +1,51 @@
1
+ import { ApiClientError, useApiClient, } from '@nocobase/app-client';
2
+ import { useQuery, useQueryClient } from '@tanstack/react-query';
3
+ import { useCallback } from 'react';
4
+ import { FOUNDATION_NAMESPACE, } from '../shared/foundation.js';
5
+ /** Reads the overview. Every call is a GET; the plugin writes nothing. */
6
+ export async function fetchFoundationOverview(api, options = {}) {
7
+ const { data } = await api.request({
8
+ path: `${FOUNDATION_NAMESPACE}/overview`,
9
+ query: options.refresh ? { refresh: 'true' } : {},
10
+ });
11
+ return data;
12
+ }
13
+ export const FOUNDATION_OVERVIEW_QUERY_KEY = [
14
+ 'foundation',
15
+ 'overview',
16
+ ];
17
+ export function useFoundationOverview() {
18
+ const api = useApiClient();
19
+ const queryClient = useQueryClient();
20
+ const query = useQuery({
21
+ queryKey: FOUNDATION_OVERVIEW_QUERY_KEY,
22
+ queryFn: () => fetchFoundationOverview(api),
23
+ // A refused or failed overview is answered as it is; the page offers its own retry.
24
+ retry: false,
25
+ refetchOnWindowFocus: false,
26
+ });
27
+ const refresh = useCallback(() => {
28
+ void queryClient
29
+ .fetchQuery({
30
+ queryKey: FOUNDATION_OVERVIEW_QUERY_KEY,
31
+ queryFn: () => fetchFoundationOverview(api, { refresh: true }),
32
+ staleTime: 0,
33
+ })
34
+ .catch(() => undefined);
35
+ }, [api, queryClient]);
36
+ const error = query.error === null
37
+ ? undefined
38
+ : query.error instanceof ApiClientError &&
39
+ (query.error.status === 401 || query.error.status === 403)
40
+ ? 'forbidden'
41
+ : 'failed';
42
+ return {
43
+ ...(query.data === undefined || error === 'forbidden'
44
+ ? {}
45
+ : { overview: query.data }),
46
+ ...(error === undefined ? {} : { error }),
47
+ loading: query.isFetching,
48
+ refresh,
49
+ };
50
+ }
51
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../client/api.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,YAAY,GAEb,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAEpC,OAAO,EACL,oBAAoB,GAErB,MAAM,yBAAyB,CAAC;AAEjC,0EAA0E;AAC1E,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,GAAc,EACd,UAA0C,EAAE;IAE5C,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,GAAG,CAAC,OAAO,CAAwC;QACxE,IAAI,EAAE,GAAG,oBAAoB,WAAW;QACxC,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE;KAClD,CAAC,CAAC;IACH,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,MAAM,6BAA6B,GAAG;IAC3C,YAAY;IACZ,UAAU;CACF,CAAC;AAYX,MAAM,UAAU,qBAAqB;IACnC,MAAM,GAAG,GAAG,YAAY,EAAE,CAAC;IAC3B,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,MAAM,KAAK,GAAG,QAAQ,CAAC;QACrB,QAAQ,EAAE,6BAA6B;QACvC,OAAO,EAAE,GAAG,EAAE,CAAC,uBAAuB,CAAC,GAAG,CAAC;QAC3C,oFAAoF;QACpF,KAAK,EAAE,KAAK;QACZ,oBAAoB,EAAE,KAAK;KAC5B,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE;QAC/B,KAAK,WAAW;aACb,UAAU,CAAC;YACV,QAAQ,EAAE,6BAA6B;YACvC,OAAO,EAAE,GAAG,EAAE,CAAC,uBAAuB,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAC9D,SAAS,EAAE,CAAC;SACb,CAAC;aACD,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAC5B,CAAC,EAAE,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC;IACvB,MAAM,KAAK,GACT,KAAK,CAAC,KAAK,KAAK,IAAI;QAClB,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,KAAK,CAAC,KAAK,YAAY,cAAc;YACnC,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,GAAG,CAAC;YAC5D,CAAC,CAAC,WAAW;YACb,CAAC,CAAC,QAAQ,CAAC;IACjB,OAAO;QACL,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,KAAK,WAAW;YACnD,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;QAC7B,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;QACzC,OAAO,EAAE,KAAK,CAAC,UAAU;QACzB,OAAO;KACR,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { type AppClientRegisteredRoute } from '@nocobase/app-client/plugins';
2
+ import type { FoundationBusinessModule, FoundationModuleSources, FoundationProviderInventory } from '../shared/foundation.js';
3
+ /** Navigation supplies module identity and titles; child pages belong to their nearest top-level menu module. */
4
+ export declare function businessModules(routes: readonly AppClientRegisteredRoute[], inventory: FoundationProviderInventory | undefined, sources: FoundationModuleSources | undefined, capabilities: readonly string[]): readonly FoundationBusinessModule[];
5
+ //# sourceMappingURL=business-modules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"business-modules.d.ts","sourceRoot":"","sources":["../../client/business-modules.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,wBAAwB,EAC9B,MAAM,8BAA8B,CAAC;AAEtC,OAAO,KAAK,EACV,wBAAwB,EAExB,uBAAuB,EACvB,2BAA2B,EAC5B,MAAM,yBAAyB,CAAC;AAIjC,iHAAiH;AACjH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,SAAS,wBAAwB,EAAE,EAC3C,SAAS,EAAE,2BAA2B,GAAG,SAAS,EAClD,OAAO,EAAE,uBAAuB,GAAG,SAAS,EAC5C,YAAY,EAAE,SAAS,MAAM,EAAE,GAC9B,SAAS,wBAAwB,EAAE,CAsFrC"}
@@ -0,0 +1,81 @@
1
+ import { compareNavigationOrder, } from '@nocobase/app-client/plugins';
2
+ const SELF = '@nocobase/app-plugin-foundation';
3
+ /** Navigation supplies module identity and titles; child pages belong to their nearest top-level menu module. */
4
+ export function businessModules(routes, inventory, sources, capabilities) {
5
+ const available = new Set(capabilities);
6
+ const modules = [];
7
+ const descendants = (route) => route.packageName === SELF || route.auth === 'guest'
8
+ ? []
9
+ : [route, ...(route.children ?? []).flatMap(descendants)];
10
+ const visit = (nodes) => {
11
+ for (const node of [...nodes].sort(compareNavigationOrder)) {
12
+ if (node.packageName === SELF || node.auth === 'guest')
13
+ continue;
14
+ if (!node.navigation) {
15
+ visit(node.children ?? []);
16
+ continue;
17
+ }
18
+ const pages = descendants(node).filter((route) => route.componentLoader);
19
+ if (!pages.length)
20
+ continue;
21
+ const links = new Map();
22
+ const add = (key, evidence, provider) => {
23
+ if (!available.has(key))
24
+ return;
25
+ const link = links.get(key) ?? {
26
+ evidence: new Set(),
27
+ providers: new Set(),
28
+ };
29
+ link.evidence.add(evidence);
30
+ if (provider)
31
+ link.providers.add(provider);
32
+ links.set(key, link);
33
+ };
34
+ const provider = (name, evidence) => {
35
+ const entry = inventory?.entries.find((item) => item.name === name);
36
+ if (!entry || name === SELF)
37
+ return;
38
+ // A broad SDK/provider can implement several unrelated capabilities. A package reference cannot
39
+ // establish which of them this page uses; retain only more specific route/source evidence.
40
+ if (entry.categories.length > 1)
41
+ return;
42
+ const keys = entry.categories.length
43
+ ? entry.categories
44
+ : [`extension:${name}`];
45
+ for (const key of keys)
46
+ add(key, evidence, name);
47
+ };
48
+ let complete = true;
49
+ for (const page of pages) {
50
+ add('interface', 'page');
51
+ if (page.auth === 'required')
52
+ add('usersAndOrganizations', 'authentication');
53
+ if (page.authz && page.authz !== 'skip')
54
+ add('permissions', 'authorization');
55
+ if (page.source === 'plugin')
56
+ provider(page.packageName, 'provider');
57
+ const source = sources?.routes.find((item) => item.packageName === page.packageName &&
58
+ item.routeName === page.name);
59
+ complete &&= source?.complete ?? false;
60
+ for (const name of source?.providers ?? [])
61
+ provider(name, 'source');
62
+ for (const name of source?.apiProviders ?? [])
63
+ provider(name, 'apiSource');
64
+ }
65
+ modules.push({
66
+ id: node.id,
67
+ title: { key: node.navigation.title, ns: node.packageName },
68
+ pageCount: pages.length,
69
+ complete,
70
+ links: [...links].map(([capability, link]) => ({
71
+ capability,
72
+ evidence: [...link.evidence],
73
+ providers: [...link.providers].sort(),
74
+ })),
75
+ });
76
+ }
77
+ };
78
+ visit(routes);
79
+ return modules;
80
+ }
81
+ //# sourceMappingURL=business-modules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"business-modules.js","sourceRoot":"","sources":["../../client/business-modules.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { type LucideIcon } from 'lucide-react';
2
+ import type { FoundationCapabilityKey } from '../../shared/foundation.js';
3
+ export declare const CAPABILITY_ICONS: Readonly<Record<FoundationCapabilityKey, LucideIcon | undefined>>;
4
+ //# sourceMappingURL=capability-icons.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability-icons.d.ts","sourceRoot":"","sources":["../../../client/components/capability-icons.ts"],"names":[],"mappings":"AAAA,OAAO,EAcL,KAAK,UAAU,EAChB,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAE1E,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CACrC,MAAM,CAAC,uBAAuB,EAAE,UAAU,GAAG,SAAS,CAAC,CAexD,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { Bell, BookOpen, Bot, Database, FileText, History, KeyRound, LayoutGrid, Mail, Plug, Users, Workflow, Wrench, } from 'lucide-react';
2
+ export const CAPABILITY_ICONS = {
3
+ dataModeling: Database,
4
+ files: FileText,
5
+ usersAndOrganizations: Users,
6
+ permissions: KeyRound,
7
+ workflows: Workflow,
8
+ aiAgents: Bot,
9
+ knowledge: BookOpen,
10
+ mail: Mail,
11
+ notifications: Bell,
12
+ integrations: Plug,
13
+ interface: LayoutGrid,
14
+ audit: History,
15
+ operations: Wrench,
16
+ };
17
+ //# sourceMappingURL=capability-icons.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability-icons.js","sourceRoot":"","sources":["../../../client/components/capability-icons.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EACJ,QAAQ,EACR,GAAG,EACH,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,UAAU,EACV,IAAI,EACJ,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,MAAM,GAEP,MAAM,cAAc,CAAC;AAItB,MAAM,CAAC,MAAM,gBAAgB,GAEzB;IACF,YAAY,EAAE,QAAQ;IACtB,KAAK,EAAE,QAAQ;IACf,qBAAqB,EAAE,KAAK;IAC5B,WAAW,EAAE,QAAQ;IACrB,SAAS,EAAE,QAAQ;IACnB,QAAQ,EAAE,GAAG;IACb,SAAS,EAAE,QAAQ;IACnB,IAAI,EAAE,IAAI;IACV,aAAa,EAAE,IAAI;IACnB,YAAY,EAAE,IAAI;IAClB,SAAS,EAAE,UAAU;IACrB,KAAK,EAAE,OAAO;IACd,UAAU,EAAE,MAAM;CACnB,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { FoundationFactParam, FoundationMetric, FoundationText } from '../../shared/foundation.js';
2
+ export declare function formatNumber(value: number, locale: string): string;
3
+ export declare function formatMetricValue(metric: FoundationMetric, locale: string): string | undefined;
4
+ export declare function formatTime(iso: string, locale: string): string;
5
+ /** The values a fact's wording quotes, formatted for the reader: numbers grouped, lists joined, times localized. */
6
+ export declare function formatFactParams(params: Readonly<Record<string, FoundationFactParam>> | undefined, locale: string, translate: (text: FoundationText) => string): Record<string, string>;
7
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../client/components/format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,EACf,MAAM,4BAA4B,CAAC;AAIpC,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAElE;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,MAAM,GACb,MAAM,GAAG,SAAS,CAUpB;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAO9D;AAED,oHAAoH;AACpH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,GAAG,SAAS,EACjE,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,MAAM,GAC1C,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAYxB"}
@@ -0,0 +1,42 @@
1
+ const BYTE_UNITS = ['B', 'KB', 'MB', 'GB', 'TB'];
2
+ export function formatNumber(value, locale) {
3
+ return new Intl.NumberFormat(locale).format(value);
4
+ }
5
+ export function formatMetricValue(metric, locale) {
6
+ if (metric.value === null)
7
+ return undefined;
8
+ if (metric.unit !== 'bytes')
9
+ return formatNumber(metric.value, locale);
10
+ let value = metric.value;
11
+ let unit = 0;
12
+ while (value >= 1024 && unit < BYTE_UNITS.length - 1) {
13
+ value /= 1024;
14
+ unit += 1;
15
+ }
16
+ return `${new Intl.NumberFormat(locale, { maximumFractionDigits: 1 }).format(value)} ${BYTE_UNITS[unit] ?? 'B'}`;
17
+ }
18
+ export function formatTime(iso, locale) {
19
+ const time = Date.parse(iso);
20
+ if (Number.isNaN(time))
21
+ return iso;
22
+ return new Intl.DateTimeFormat(locale, {
23
+ dateStyle: 'medium',
24
+ timeStyle: 'short',
25
+ }).format(time);
26
+ }
27
+ /** The values a fact's wording quotes, formatted for the reader: numbers grouped, lists joined, times localized. */
28
+ export function formatFactParams(params, locale, translate) {
29
+ const formatted = {};
30
+ for (const [key, value] of Object.entries(params ?? {})) {
31
+ if (typeof value === 'number')
32
+ formatted[key] = formatNumber(value, locale);
33
+ else if (typeof value === 'string')
34
+ formatted[key] = key === 'at' ? formatTime(value, locale) : value;
35
+ else
36
+ formatted[key] = new Intl.ListFormat(locale, {
37
+ type: 'conjunction',
38
+ }).format(value.map(translate));
39
+ }
40
+ return formatted;
41
+ }
42
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../../client/components/format.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAEjD,MAAM,UAAU,YAAY,CAAC,KAAa,EAAE,MAAc;IACxD,OAAO,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,MAAwB,EACxB,MAAc;IAEd,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAC5C,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,YAAY,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACvE,IAAI,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;IACzB,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,OAAO,KAAK,IAAI,IAAI,IAAI,IAAI,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrD,KAAK,IAAI,IAAI,CAAC;QACd,IAAI,IAAI,CAAC,CAAC;IACZ,CAAC;IACD,OAAO,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,EAAE,qBAAqB,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC;AACnH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,MAAc;IACpD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;QAAE,OAAO,GAAG,CAAC;IACnC,OAAO,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE;QACrC,SAAS,EAAE,QAAQ;QACnB,SAAS,EAAE,OAAO;KACnB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAClB,CAAC;AAED,oHAAoH;AACpH,MAAM,UAAU,gBAAgB,CAC9B,MAAiE,EACjE,MAAc,EACd,SAA2C;IAE3C,MAAM,SAAS,GAA2B,EAAE,CAAC;IAC7C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAC;QACxD,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,SAAS,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;aACvE,IAAI,OAAO,KAAK,KAAK,QAAQ;YAChC,SAAS,CAAC,GAAG,CAAC,GAAG,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;;YAElE,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE;gBAC3C,IAAI,EAAE,aAAa;aACpB,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { type ReactElement } from 'react';
2
+ import { type FoundationOverview } from '../../shared/foundation.js';
3
+ import { businessModules } from '../business-modules.js';
4
+ export declare function FoundationPage(): ReactElement;
5
+ export interface FoundationOverviewViewProps {
6
+ readonly overview: FoundationOverview;
7
+ readonly refreshing?: boolean;
8
+ readonly onRefresh?: () => void;
9
+ readonly clientProviders?: readonly string[];
10
+ readonly registeredRoutes?: Parameters<typeof businessModules>[0];
11
+ }
12
+ /** The band, the key numbers and the selected capability's details, for a page that loads the overview itself. */
13
+ export declare function FoundationOverviewView({ overview: serverOverview, refreshing, onRefresh, clientProviders, registeredRoutes, }: FoundationOverviewViewProps): ReactElement;
14
+ export default FoundationPage;
15
+ //# sourceMappingURL=foundation-page.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"foundation-page.d.ts","sourceRoot":"","sources":["../../../client/components/foundation-page.tsx"],"names":[],"mappings":"AAGA,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,OAAO,CAAC;AAEf,OAAO,EAKL,KAAK,kBAAkB,EAGxB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAmDzD,wBAAgB,cAAc,IAAI,YAAY,CA0D7C;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAC;IACtC,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IAChC,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7C,QAAQ,CAAC,gBAAgB,CAAC,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;CACnE;AAED,kHAAkH;AAClH,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EAAE,cAAc,EACxB,UAAkB,EAClB,SAAS,EACT,eAAoB,EACpB,gBAAqB,GACtB,EAAE,2BAA2B,GAAG,YAAY,CAwM5C;AA+dD,eAAe,cAAc,CAAC"}