@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
@@ -0,0 +1,66 @@
1
+ const CORE_RUNTIME = new Set([
2
+ 'dataModeling',
3
+ 'interface',
4
+ 'operations',
5
+ 'workflows',
6
+ ]);
7
+ /** Show recognized installed capabilities as well as current runtime capabilities; installation never proves use. */
8
+ export function availableCapabilities(observations, inventory) {
9
+ const known = observations.flatMap((capability) => {
10
+ const providers = inventory.entries.filter((entry) => entry.categories.includes(capability.key));
11
+ const registered = providers.some((entry) => entry.registration === 'observed' &&
12
+ (!inventory.serverRegistrationsComplete ||
13
+ capability.key === 'interface' ||
14
+ entry.evidence.some((source) => source !== 'manifest' && source !== 'clientContribution')));
15
+ if (registered)
16
+ return [capability];
17
+ if (CORE_RUNTIME.has(capability.key) && capability.status !== 'unused')
18
+ return [capability];
19
+ // Older runtimes expose only partial registration evidence; preserve capabilities whose use the collector proved.
20
+ if (!inventory.serverRegistrationsComplete &&
21
+ (capability.status === 'active' || capability.status === 'needsSetup'))
22
+ return [capability];
23
+ if (!providers.some((entry) => entry.installed))
24
+ return [];
25
+ // Keep installed-only capabilities visible, but stale tables and a manifest cannot establish current use.
26
+ // Preserve unreadable observations as unknown rather than turning collection failures into an unused state.
27
+ if (capability.status === null)
28
+ return [capability];
29
+ return [
30
+ {
31
+ ...capability,
32
+ status: 'unused',
33
+ reason: 'installedNotUsed',
34
+ facts: [],
35
+ parts: [],
36
+ },
37
+ ];
38
+ });
39
+ const extensions = inventory.entries
40
+ .filter((entry) => entry.kind === 'plugin' &&
41
+ entry.registration === 'observed' &&
42
+ entry.categories.length === 0)
43
+ .map((entry) => ({
44
+ key: `extension:${entry.name}`,
45
+ title: entry.displayName ?? entry.name,
46
+ ...(entry.description ? { description: entry.description } : {}),
47
+ status: null,
48
+ reason: 'unrecognizedExtension',
49
+ facts: [{ code: 'registeredExtension' }],
50
+ metrics: [],
51
+ parts: [],
52
+ packages: [{ name: entry.name, version: entry.version }],
53
+ completeness: 'complete',
54
+ issues: [],
55
+ }));
56
+ return [...known, ...extensions];
57
+ }
58
+ /** Client-only registrations are added to the same model without changing server usage evidence. */
59
+ export function withAvailableCapabilities(overview, inventory) {
60
+ return {
61
+ ...overview,
62
+ inventory,
63
+ availableCapabilities: availableCapabilities(overview.capabilities, inventory),
64
+ };
65
+ }
66
+ //# sourceMappingURL=available-capabilities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"available-capabilities.js","sourceRoot":"","sources":["../../shared/available-capabilities.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,142 @@
1
+ /**
2
+ * The contract between the server, which collects what an application uses of NocoBase Core, and the page that shows
3
+ * it. Values here are shared by both sides; everything else is a type, so nothing from `server/` reaches the browser.
4
+ */
5
+ /** Built-in collector adapters, in their preferred display order; this is not the universe of available capabilities. */
6
+ export declare const FOUNDATION_CAPABILITIES: readonly ["dataModeling", "files", "usersAndOrganizations", "permissions", "workflows", "aiAgents", "knowledge", "mail", "notifications", "integrations", "interface", "audit", "operations"];
7
+ export type FoundationBuiltinCapabilityKey = (typeof FOUNDATION_CAPABILITIES)[number];
8
+ export type FoundationCapabilityKey = string;
9
+ /**
10
+ * `active`: the application uses it now. `needsSetup`: it is wired in but a required piece of configuration is missing.
11
+ * `unused`: not wired in, not enabled, or not provided. A capability whose collection failed has no status (`null`): a
12
+ * failure is never reported as `unused`.
13
+ */
14
+ export type FoundationStatus = 'active' | 'needsSetup' | 'unused';
15
+ export declare const FOUNDATION_STATUSES: readonly FoundationStatus[];
16
+ /** How much of a capability's evidence could be read this time. */
17
+ export type FoundationCompleteness = 'complete' | 'partial' | 'failed';
18
+ /** A name as the application stores it: plain text, or a translation key in a namespace the page may have loaded. */
19
+ export type FoundationText = string | {
20
+ readonly key: string;
21
+ readonly ns: string;
22
+ };
23
+ export type FoundationFactParam = string | number | readonly FoundationText[];
24
+ /**
25
+ * One established fact about how the application uses a capability, such as "12 collections of its own". The page
26
+ * words it from `code`; `params` carries the values the wording quotes.
27
+ */
28
+ export interface FoundationFact {
29
+ readonly code: string;
30
+ readonly params?: Readonly<Record<string, FoundationFactParam>>;
31
+ }
32
+ export type FoundationMetricUnit = 'count' | 'bytes' | 'tokens';
33
+ export interface FoundationMetric {
34
+ readonly key: string;
35
+ /** Null when it could not be read; never a stand-in zero. */
36
+ readonly value: number | null;
37
+ readonly unit: FoundationMetricUnit;
38
+ /** False when some of the sources it adds up could not be read, so the value is a lower bound. */
39
+ readonly complete: boolean;
40
+ }
41
+ /** A part of a composite capability, such as accounts and organizations under users and organizations. */
42
+ export interface FoundationPart {
43
+ readonly key: string;
44
+ readonly status: FoundationStatus;
45
+ readonly reason?: string;
46
+ }
47
+ export interface FoundationPackage {
48
+ readonly name: string;
49
+ /** The version the application actually resolves. */
50
+ readonly version: string | null;
51
+ }
52
+ export type FoundationIssueCode = 'COLLECTOR_FAILED' | 'COLLECTOR_TIMEOUT' | 'SOURCE_UNREADABLE';
53
+ /** Something that could not be read. `source` names a Collection or a service, never an error message. */
54
+ export interface FoundationIssue {
55
+ readonly code: FoundationIssueCode;
56
+ readonly source?: string;
57
+ }
58
+ export interface FoundationCapability {
59
+ readonly key: FoundationCapabilityKey;
60
+ readonly title?: FoundationText;
61
+ readonly description?: string;
62
+ readonly status: FoundationStatus | null;
63
+ /** Why the capability needs setup or is unused, such as `noChannel`. */
64
+ readonly reason?: string;
65
+ readonly facts: readonly FoundationFact[];
66
+ readonly metrics: readonly FoundationMetric[];
67
+ readonly parts: readonly FoundationPart[];
68
+ readonly packages: readonly FoundationPackage[];
69
+ readonly completeness: FoundationCompleteness;
70
+ readonly issues: readonly FoundationIssue[];
71
+ }
72
+ export interface FoundationOverview {
73
+ readonly capabilities: readonly FoundationCapability[];
74
+ /** Runtime-specific capability items; built-in adapter observations remain available above for existing consumers. */
75
+ readonly availableCapabilities?: readonly FoundationCapability[];
76
+ /** Additive for clients receiving an overview from an older server. */
77
+ readonly inventory?: FoundationProviderInventory;
78
+ /** Static integration evidence; the browser joins this with the current registered navigation. */
79
+ readonly moduleSources?: FoundationModuleSources;
80
+ /** When this result was collected, RFC 3339. A cached result keeps its original time. */
81
+ readonly checkedAt: string;
82
+ readonly durationMs: number;
83
+ /** The database connection the statistics read: always the default one. */
84
+ readonly connection: string;
85
+ }
86
+ export interface FoundationModuleSource {
87
+ readonly packageName: string;
88
+ readonly routeName: string;
89
+ /** Value imports reachable from the page; type-only imports and installed-only packages are excluded. */
90
+ readonly providers: readonly string[];
91
+ readonly apiProviders?: readonly string[];
92
+ readonly complete: boolean;
93
+ }
94
+ export interface FoundationModuleSources {
95
+ readonly routes: readonly FoundationModuleSource[];
96
+ readonly complete: boolean;
97
+ }
98
+ export interface FoundationModuleLink {
99
+ readonly capability: FoundationCapabilityKey;
100
+ readonly evidence: readonly ('page' | 'authentication' | 'authorization' | 'provider' | 'source' | 'apiSource')[];
101
+ readonly providers: readonly string[];
102
+ }
103
+ export interface FoundationBusinessModule {
104
+ readonly id: string;
105
+ readonly title: FoundationText;
106
+ readonly pageCount: number;
107
+ readonly complete: boolean;
108
+ readonly links: readonly FoundationModuleLink[];
109
+ }
110
+ /** Package discovery and usage detection are deliberately separate facts. */
111
+ export interface FoundationProviderEntry {
112
+ readonly name: string;
113
+ readonly displayName?: string;
114
+ readonly description?: string;
115
+ readonly version: string | null;
116
+ readonly installed: boolean;
117
+ readonly kind: 'core' | 'plugin';
118
+ /** An explicit Foundation catalog entry, never inferred from an npm scope or a license string. */
119
+ readonly origin: 'nocobase' | 'unverified';
120
+ readonly categories: readonly FoundationCapabilityKey[];
121
+ /** Only public, current runtime contributions prove registration; absence means unknown, not disabled. */
122
+ readonly registration: 'observed' | 'unknown';
123
+ readonly evidence: readonly ('manifest' | 'databaseContribution' | 'apiContribution' | 'foundationRuntime' | 'serverRegistration' | 'clientContribution')[];
124
+ }
125
+ export interface FoundationProviderInventory {
126
+ readonly entries: readonly FoundationProviderEntry[];
127
+ readonly complete: boolean;
128
+ /** Symbolic sources only: never paths, dependency URLs, credentials or raw errors. */
129
+ readonly unreadable: readonly string[];
130
+ /** Whether the host supplied its complete explicit Server registration snapshot. */
131
+ readonly serverRegistrationsComplete?: boolean;
132
+ }
133
+ /** The key numbers above the capability details, each one a metric of a capability. */
134
+ export declare const FOUNDATION_HIGHLIGHTS: readonly {
135
+ readonly capability: FoundationCapabilityKey;
136
+ readonly metric: string;
137
+ }[];
138
+ /** The URL namespace of the plugin's routes and the domain of its errors. */
139
+ export declare const FOUNDATION_NAMESPACE = "foundation";
140
+ /** The i18n namespace of the plugin's wording. */
141
+ export declare const FOUNDATION_I18N_NAMESPACE = "@nocobase/app-plugin-foundation";
142
+ //# sourceMappingURL=foundation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"foundation.d.ts","sourceRoot":"","sources":["../../shared/foundation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * The contract between the server, which collects what an application uses of NocoBase Core, and the page that shows
3
+ * it. Values here are shared by both sides; everything else is a type, so nothing from `server/` reaches the browser.
4
+ */
5
+ /** Built-in collector adapters, in their preferred display order; this is not the universe of available capabilities. */
6
+ export const FOUNDATION_CAPABILITIES = [
7
+ 'dataModeling',
8
+ 'files',
9
+ 'usersAndOrganizations',
10
+ 'permissions',
11
+ 'workflows',
12
+ 'aiAgents',
13
+ 'knowledge',
14
+ 'mail',
15
+ 'notifications',
16
+ 'integrations',
17
+ 'interface',
18
+ 'audit',
19
+ 'operations',
20
+ ];
21
+ export const FOUNDATION_STATUSES = [
22
+ 'active',
23
+ 'needsSetup',
24
+ 'unused',
25
+ ];
26
+ /** The key numbers above the capability details, each one a metric of a capability. */
27
+ export const FOUNDATION_HIGHLIGHTS = [
28
+ { capability: 'dataModeling', metric: 'businessRecords' },
29
+ { capability: 'usersAndOrganizations', metric: 'accounts' },
30
+ { capability: 'permissions', metric: 'grants' },
31
+ { capability: 'workflows', metric: 'transitions' },
32
+ { capability: 'notifications', metric: 'acceptedDeliveries' },
33
+ { capability: 'operations', metric: 'migrations' },
34
+ ];
35
+ /** The URL namespace of the plugin's routes and the domain of its errors. */
36
+ export const FOUNDATION_NAMESPACE = 'foundation';
37
+ /** The i18n namespace of the plugin's wording. */
38
+ export const FOUNDATION_I18N_NAMESPACE = '@nocobase/app-plugin-foundation';
39
+ //# sourceMappingURL=foundation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"foundation.js","sourceRoot":"","sources":["../../shared/foundation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,yHAAyH;AACzH,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,cAAc;IACd,OAAO;IACP,uBAAuB;IACvB,aAAa;IACb,WAAW;IACX,UAAU;IACV,WAAW;IACX,MAAM;IACN,eAAe;IACf,cAAc;IACd,WAAW;IACX,OAAO;IACP,YAAY;CACJ,CAAC;AAaX,MAAM,CAAC,MAAM,mBAAmB,GAAgC;IAC9D,QAAQ;IACR,YAAY;IACZ,QAAQ;CACT,CAAC;AAsJF,uFAAuF;AACvF,MAAM,CAAC,MAAM,qBAAqB,GAG5B;IACJ,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,EAAE,iBAAiB,EAAE;IACzD,EAAE,UAAU,EAAE,uBAAuB,EAAE,MAAM,EAAE,UAAU,EAAE;IAC3D,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE;IAC/C,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE;IAClD,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,EAAE,oBAAoB,EAAE;IAC7D,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE;CACnD,CAAC;AAEF,6EAA6E;AAC7E,MAAM,CAAC,MAAM,oBAAoB,GAAG,YAAY,CAAC;AAEjD,kDAAkD;AAClD,MAAM,CAAC,MAAM,yBAAyB,GAAG,iCAAiC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,109 @@
1
1
  {
2
2
  "name": "@nocobase/app-plugin-foundation",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "displayName": "App Foundation",
4
+ "description": "Shows which NocoBase Core capabilities an application uses, with live evidence, for its unrestricted administrators.",
5
+ "version": "0.1.0-beta.0",
6
+ "type": "module",
7
+ "prettier": "@nocobase/dev-config/prettier",
8
+ "engines": {
9
+ "node": ">=24.0.0"
10
+ },
11
+ "sideEffects": false,
12
+ "exports": {
13
+ "./server": {
14
+ "types": "./dist/server/index.d.ts",
15
+ "import": "./dist/server/index.js"
16
+ },
17
+ "./client": {
18
+ "types": "./dist/client/index.d.ts",
19
+ "import": "./dist/client/index.js"
20
+ },
21
+ "./client/plugin": {
22
+ "types": "./dist/client/plugin.d.ts",
23
+ "import": "./dist/client/plugin.js"
24
+ },
25
+ "./client/routes": {
26
+ "types": "./dist/client/routes.d.ts",
27
+ "import": "./dist/client/routes.js"
28
+ },
29
+ "./client/pages": {
30
+ "types": "./dist/client/components/foundation-page.d.ts",
31
+ "import": "./dist/client/components/foundation-page.js"
32
+ },
33
+ "./cli": {
34
+ "types": "./dist/cli/index.d.ts",
35
+ "import": "./dist/cli/index.js"
36
+ },
37
+ "./package.json": "./package.json"
38
+ },
39
+ "imports": {
40
+ "#components/*": "./dist/client/components/*.js",
41
+ "#hooks/*": "./dist/client/hooks/*.js",
42
+ "#lib/*": "./dist/client/lib/*.js",
43
+ "#extensions/*": "./dist/client/extensions/*.js"
44
+ },
45
+ "files": [
46
+ "dist",
47
+ "README.md",
48
+ "CHANGELOG.md",
49
+ "skills"
50
+ ],
51
+ "publishConfig": {
52
+ "access": "public"
53
+ },
54
+ "dependencies": {
55
+ "hono": "^4.13.2",
56
+ "zod": "^4.6.5",
57
+ "typescript": "^6.0.3"
58
+ },
59
+ "peerDependencies": {
60
+ "@base-ui/react": "^1.6.0",
61
+ "@tanstack/react-query": "^5.81.5",
62
+ "class-variance-authority": "^0.7.1",
63
+ "cn": "^0.4.0",
64
+ "lucide-react": "^0.487.0",
65
+ "react": "^19.0.0",
66
+ "@nocobase/app-cli": "^1.0.0-beta.26",
67
+ "@nocobase/app-client": "^4.0.0-beta.1",
68
+ "@nocobase/app-plugin-authentication": "^2.0.0-beta.12",
69
+ "@nocobase/app-plugin-authorization": "^1.0.0-beta.30",
70
+ "@nocobase/app-server": "^3.0.0-beta.1",
71
+ "@nocobase/db": "^1.0.0-beta.21",
72
+ "@nocobase/i18n": "^2.0.0-beta.1",
73
+ "@nocobase/service-provider": "^0.0.2-beta.2"
74
+ },
75
+ "devDependencies": {
76
+ "@testing-library/jest-dom": "^7.0.0",
77
+ "@testing-library/react": "^16.3.2",
78
+ "@types/node": "^24.0.0",
79
+ "@types/react": "^19.2.0",
80
+ "@vitejs/plugin-react": "^4.4.1",
81
+ "eslint": "^10.0.0",
82
+ "jsdom": "^30.0.1",
83
+ "prettier": "^3.9.6",
84
+ "react-dom": "^19.2.8",
85
+ "react-router": "^7.0.2",
86
+ "shadcn": "^4.13.1",
87
+ "tailwindcss": "^4.1.4",
88
+ "tw-animate-css": "^1.2.5",
89
+ "vitest": "^4.1.10",
90
+ "@nocobase/app-plugin-api-keys": "1.0.0-beta.18",
91
+ "@nocobase/app-plugin-mail": "1.0.0-beta.16",
92
+ "@nocobase/app-plugin-notification": "1.0.0-beta.29",
93
+ "@nocobase/app-plugin-notification-in-app": "1.0.0-beta.27",
94
+ "@nocobase/app-plugin-scheduler": "1.0.0-beta.19",
95
+ "@nocobase/app-testing": "0.1.0-beta.6",
96
+ "@nocobase/dev-config": "0.1.0-beta.24"
97
+ },
98
+ "scripts": {
99
+ "build": "tsc -p tsconfig.json",
100
+ "typecheck": "tsc -p tsconfig.json --noEmit",
101
+ "test": "vitest run --passWithNoTests",
102
+ "lint": "eslint . --max-warnings 0",
103
+ "lint:fix": "eslint . --fix --max-warnings 0",
104
+ "format": "prettier . --write",
105
+ "format:check": "prettier . --check",
106
+ "check": "pnpm lint && pnpm format:check && pnpm typecheck && pnpm test && pnpm build",
107
+ "fix": "pnpm lint:fix && pnpm format"
108
+ }
6
109
  }
@@ -0,0 +1,68 @@
1
+ ---
2
+ name: nocobase-app-plugin-foundation
3
+ description: Use when an application should show its administrators which NocoBase Core capabilities it uses (the App Foundation page), when registering or moving that page, or when asked why a capability shows as in use, needing setup, not used or undetermined there. Not for business permissions or for building other admin pages.
4
+ ---
5
+
6
+ # App Foundation
7
+
8
+ ## Use this Skill when
9
+
10
+ - The application should get the App Foundation page, or it should move or leave the menu.
11
+ - Someone asks why a capability on that page is in use, needs setup, is not used yet or is undetermined, or where a number comes from.
12
+
13
+ Do not use it to grant the page to a role: it admits only unrestricted access by design.
14
+
15
+ ## Public surfaces
16
+
17
+ - Server plugin: `@nocobase/app-plugin-foundation/server` (default export). Exports `foundationServiceToken`, whose `overview({ refresh? })` answers the same result as the route.
18
+ - Server route: `GET /api/foundation/overview`, optional `refresh=true`. Requires a session or API key of an identity with unrestricted access; anyone else gets `403` with reason `FOUNDATION_FORBIDDEN`.
19
+ - Client plugin: `@nocobase/app-plugin-foundation/client` (default export). `foundation()` adds the page at `/foundation` with a menu entry; options `path`, `navigation: false`, `routes: false` and `settingsGroup: true`. The default template uses `settingsGroup: true` so a bare application already has a localized settings group containing only the protected Foundation page.
20
+ - Page component: `FoundationPage` from `@nocobase/app-plugin-foundation/client/pages`, for an application that routes it itself (`foundation({ routes: false })`). Declare such a route with `authz: 'unrestricted'`.
21
+
22
+ ## Prerequisites
23
+
24
+ The authentication and authorization plugins are registered, as in the default template. The page reads the query cache the application's routes provide.
25
+
26
+ ## App workflow
27
+
28
+ 1. Add the dependency and register the server plugin in `server/plugins.ts` and the client plugin in `client/plugins.ts`.
29
+ 2. Restart the application and open `/foundation` as an administrator holding the root Permission Set.
30
+ 3. Build the application as usual; refresh the page to see new capabilities light up.
31
+
32
+ ## Reading a status
33
+
34
+ - Collected read-only by the plugin; nothing reports to it, so there is nothing to register per capability.
35
+ - In use means wired in: a persisted lifecycle, an enabled schedule, a connected mailbox, a configured notification channel, an API key that has been used. Zero uses still count as in use.
36
+ - Needs setup names what is missing in its reason, such as `noChannel` or `noDrive`.
37
+ - Undetermined means the evidence could not be read this time, never that it is unused; the details list what could not be read.
38
+ - Business record ownership uses `server/catalog.ts`. If an unclassified runtime extension makes ownership uncertain, business counts are withheld; add a supported ownership adapter rather than interpreting them as zero.
39
+
40
+ ## Verification
41
+
42
+ - As the root administrator, `/foundation` shows the capabilities available in this runtime, and `GET /api/foundation/overview` answers `200`.
43
+ - As any other user, the page is not in the menu, and the route answers `403 FOUNDATION_FORBIDDEN`.
44
+ - After adding a Collection, a lifecycle or a notification channel and refreshing, the matching capability changes.
45
+
46
+ ## Reading the provider inventory
47
+
48
+ The visible capability band is dynamic, not a fixed thirteen-item catalog. The optional overview `inventory` lists package manifests, catalog category associations and observed current registration separately. The browser adds Client route and provider owners as view-only evidence. Installation or registration alone never proves a package is configured or used; category usage must not be copied to every provider package.
49
+
50
+ Unknown Pro and custom providers remain visible as unclassified extensions. An npm scope or proprietary license does not verify official origin or Pro identity. Discovery is bounded to direct dependencies, known providers and public observed contributions, so missing evidence means unknown rather than disabled. Do not write invented module associations, usage facts or provider status into application code to make the overview look complete.
51
+
52
+ ## Dynamic registration coverage
53
+
54
+ The host records immutable explicit Server and Client plugin registrations, including provider-only and locales-only plugins. Foundation reads those snapshots itself. A registered Pro or custom provider with no category adapter becomes its own `extension:<packageName>` item; its package title and version are displayed, while usage remains pending recognition. Registration does not prove configuration or use. Unknown extensions enter the band only when registered. Recognized installed capabilities remain visible as unused when there is no current registration or usage evidence; a manifest or stale database tables alone never mark them active. Refreshing after unregistering removes the extension and safely selects another available item. Legacy adapter observations remain in `capabilities`; runtime-specific items are returned in optional `availableCapabilities`.
55
+
56
+ ## Business module matrix
57
+
58
+ Modules follow current registered navigation, with descendant pages grouped under their top-level menu module and translated by their owning namespace. No business-module names or capability relationships are configured in the application. The matrix and module tags use the same dynamic capabilities as the band. Hover or focus a module to highlight its associations; select a checkmark to see evidence and the capability's existing “Without the foundation” explanation.
59
+
60
+ The plugin combines page, authentication and authorization declarations, provider ownership and readable static page dependencies. Follow only referenced values from the selected page export; unused imports, unrelated shared-file exports and uncalled class methods are excluded. A statically matched literal API-client request can additionally establish dependencies on the matching root-mounted endpoint handlers and their referenced values, never every dependency in the router file. A multi-category provider identity alone does not establish all its categories. Opaque dependency injection and generic request wrappers stay unassociated. These references describe integration, not per-module runtime activity; do not turn them into execution counts. The server parses bounded package-local sources without importing application modules, running component loaders or exposing source paths. Deployed or custom layouts without readable declarations keep their runtime navigation and access evidence. Overrides, computed routing and opaque backend services may remain unassociated. Blank cells mean not identified, not unused. Keep all matrix logic in this plugin; no other plugin reports or application-specific mapping is required.
61
+
62
+ Capability details include their associated business modules. API dependency associations require both the statically recognized HTTP method and path; an omitted method follows the API client's `GET` default. A refresh failure is shown while retaining the last successful result and its collection time. A `401` or `403` hides the cached overview. Do not describe cached data as freshly collected or type-only references as runtime integration.
63
+
64
+ ## Sidebar grouping
65
+
66
+ 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.
67
+
68
+ When business settings are added, preserve the template navigation transform: it merges the initial Foundation settings group into the application settings group without changing the page URL or access boundary. Do not remove the initial Foundation entry when keeping unused business administration unregistered.