You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+97-9Lines changed: 97 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -225,15 +225,15 @@ The key properties of headless features:
225
225
226
226
Extension points are declared by **consumer** libs (e.g. `core-admin`, `feature-dashboard`, `shell-nav`, `shell-lifecycle`) via `nacs-contributions.extensionPoints` in their `package.json`. Each extension point has an `itemType` that controls how `prepare-build` generates code for that slot.
227
227
228
-
|`itemType`| Import emitted | DI provider pattern | Status | Example use cases |
|`component`| Static class import |`{ provide: TOKEN, useValue: [...] }`| ✅ Implemented | Dashboard widgets, sidebar nav badges, contextual help panels |
232
-
|`lazy-component`| Dynamic `import()` factory (no static import) |`{ provide: TOKEN, useValue: [{ load: () => import(...) }] }`| ✅ Implemented | Heavy chart/editor widgets, map views — split into their own chunk even when the feature is in config |
|`component`| Static class import |`{ provide: TOKEN, useValue: [...] }`| ✅ Implemented | Dashboard widgets, sidebar nav badges, contextual help panels |
232
+
|`lazy-component`| Dynamic `import()` factory (no static import) |`{ provide: TOKEN, useValue: [{ load: () => import(...) }] }`| ✅ Implemented | Heavy chart/editor widgets, map views — split into their own chunk even when the feature is in config |
|`multi-provider`| Static class import |`{ provide: TOKEN, useClass: X, multi: true }` per contributor | 🔲 Planned | Global search providers, telemetry adapters, notification handlers |
235
+
|`value`|**None** — data inlined from `package.json`|`{ provide: TOKEN, useValue: [...] }`|✅ Implemented | Help topic registrations, permission/capability declarations, i18n namespace registrations, feature flags |
236
+
|`initializer`| Static function import |`{ provide: APP_INITIALIZER, useFactory: fn, deps: [...], multi: true }`| 🔲 Planned | Pre-fetch feature config, register service workers, warm caches before app renders |
237
237
238
238
**Key distinction between `component` and `multi-provider`:**`component` contributions are plain objects in an array — the shell renders them but they cannot inject other services themselves. `multi-provider` contributions are DI-resolved class instances, enabling each contributor to declare its own `deps` and participate fully in Angular's dependency injection graph.
239
239
@@ -304,6 +304,94 @@ npx nx run shell:prepare-build
304
304
305
305
The admin tab will appear automatically in the Administration panel for any client config that includes this feature. Features that declare no `extensions.admin` entry contribute nothing to the admin panel — omission is the opt-out.
306
306
307
+
### Adding a Value Contribution to a Feature
308
+
309
+
Value contributions let features publish **static, structured data** declared entirely in `package.json` — no TypeScript code, no imports, and zero coupling between the contributing feature and the consuming library. The build-tools pipeline reads the JSON at build time, inlines it into the generated composition file as a typed array, and binds it to a DI token via `generatedProviders`. The consuming library injects the token to access all contributed data at runtime.
310
+
311
+
**Step 1 — The consumer library declares the extension point and token:**
312
+
313
+
`libs/shell-help/package.json`:
314
+
315
+
```json
316
+
{
317
+
"name": "@nacs/shell-help",
318
+
"nacs-contributions": {
319
+
"extensionPoints": {
320
+
"help-topic": {
321
+
"itemType": "value",
322
+
"tokenExportName": "HELP_TOPICS"
323
+
}
324
+
}
325
+
}
326
+
}
327
+
```
328
+
329
+
The consumer lib also defines and exports the token and the item interface:
When a feature is removed from a client config, its contributed items disappear automatically on the next `prepare-build` — no code changes required anywhere.
394
+
307
395
### Adding a Lifecycle Hook to a Feature
308
396
309
397
Lifecycle hooks let features respond to application-level events (e.g. `user.logout`, `session.expired`) without importing anything from `@nacs/shell-lifecycle`. The feature exports a plain stateless function; `prepare-build` wires it into the dispatcher via `multi: true` DI providers at build time. If the feature is absent from a client config, its handler is fully tree-shaken.
0 commit comments