@linagora/linid-im-front-corelib 0.0.5 → 0.0.7

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 (48) hide show
  1. package/README.md +3 -3
  2. package/dist/core-lib.es.js +923 -852
  3. package/dist/core-lib.umd.js +9 -9
  4. package/dist/package.json +19 -14
  5. package/dist/tsconfig.lib.tsbuildinfo +1 -0
  6. package/dist/types/src/index.d.ts +4 -0
  7. package/dist/types/src/services/httpClientService.d.ts +13 -0
  8. package/dist/types/src/services/linIdConfigurationService.d.ts +21 -0
  9. package/dist/types/src/stores/linIdConfigurationStore.d.ts +79 -0
  10. package/dist/types/src/types/linidConfiguration.d.ts +42 -0
  11. package/package.json +18 -13
  12. package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -83
  13. package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -90
  14. package/.github/ISSUE_TEMPLATE/question.yml +0 -31
  15. package/.github/ISSUE_TEMPLATE/security.yml +0 -69
  16. package/.github/actions/setup-node-pnpm/action.yml +0 -29
  17. package/.github/workflows/pull-request.yml +0 -147
  18. package/.github/workflows/release.yml +0 -90
  19. package/.prettierignore +0 -7
  20. package/.prettierrc.json +0 -5
  21. package/.vscode/extensions.json +0 -3
  22. package/.vscode/settings.json +0 -9
  23. package/CHANGELOG.md +0 -40
  24. package/CONTRIBUTING.md +0 -269
  25. package/COPYRIGHT +0 -23
  26. package/docs/components-plugin-zones.md +0 -168
  27. package/docs/helpers.md +0 -188
  28. package/docs/module-lifecycle.md +0 -717
  29. package/docs/types-and-interfaces.md +0 -92
  30. package/eslint.config.js +0 -136
  31. package/src/components/LinidZoneRenderer.vue +0 -77
  32. package/src/index.ts +0 -51
  33. package/src/lifecycle/skeleton.ts +0 -147
  34. package/src/services/federationService.ts +0 -44
  35. package/src/stores/linidZoneStore.ts +0 -62
  36. package/src/types/linidZone.ts +0 -48
  37. package/src/types/module.ts +0 -96
  38. package/src/types/moduleLifecycle.ts +0 -154
  39. package/tests/unit/components/LinidZoneRenderer.spec.js +0 -135
  40. package/tests/unit/lifecycle/skeleton.spec.js +0 -138
  41. package/tests/unit/services/federationService.spec.js +0 -146
  42. package/tests/unit/stores/linidZoneStore.spec.js +0 -94
  43. package/tsconfig.json +0 -14
  44. package/tsconfig.lib.json +0 -20
  45. package/tsconfig.node.json +0 -9
  46. package/tsconfig.spec.json +0 -16
  47. package/vite.config.ts +0 -37
  48. package/vitest.config.ts +0 -19
@@ -1,717 +0,0 @@
1
- # Module Lifecycle System
2
-
3
- The module lifecycle system provides a standardized way for business modules to initialize themselves in the host application.
4
-
5
- ## Overview
6
-
7
- The lifecycle consists of five phases that are executed in sequence for all modules:
8
-
9
- # Module Lifecycle System
10
-
11
- The module lifecycle system provides a standardized way for business modules to initialize themselves in the host application.
12
-
13
- ## Overview
14
-
15
- The lifecycle consists of five phases that are executed in sequence for all modules:
16
-
17
- ```
18
- Setup → Configure → Initialize → Ready → Post-Init
19
- ```
20
-
21
- Each phase has a specific purpose and is executed for **all modules** before moving to the next phase.
22
-
23
- ---
24
-
25
- ## Lifecycle Phases
26
-
27
- ### 1. Setup Phase
28
-
29
- **Purpose:** Validate dependencies and prepare the module
30
-
31
- **When executed:** First phase, after the module is loaded via Module Federation
32
-
33
- **Use cases:**
34
-
35
- - Check if required dependencies are available
36
- - Validate environment
37
- - Prepare internal state
38
- - Check Vue version compatibility
39
-
40
- **Hook signature:**
41
-
42
- ```typescript
43
- async setup(): Promise<ModuleLifecycleResult>
44
- ```
45
-
46
- **Implementation example:**
47
-
48
- ```typescript
49
- async setup(): Promise<ModuleLifecycleResult> {
50
- if (!app) {
51
- return {
52
- success: false,
53
- error: 'Vue app instance not available'
54
- };
55
- }
56
- return { success: true };
57
- }
58
- ```
59
-
60
- ---
61
-
62
- ### 2. Configure Phase
63
-
64
- **Purpose:** Receive and validate host configuration
65
-
66
- **When executed:** After setup, before initialization
67
-
68
- **Use cases:**
69
-
70
- - Receive configuration from host (`module-<name>.json`)
71
- - Validate required configuration fields
72
- - Store configuration for later use
73
- - Apply configuration settings
74
-
75
- **Hook signature:**
76
-
77
- ```typescript
78
- async configure(config: ModuleHostConfig): Promise<ModuleLifecycleResult>
79
- ```
80
-
81
- **Implementation example:**
82
-
83
- ```typescript
84
- async configure(
85
- config: ModuleHostConfig
86
- ): Promise<ModuleLifecycleResult> {
87
- if (!config.id) {
88
- return {
89
- success: false,
90
- error: 'Missing module ID in configuration'
91
- };
92
- }
93
-
94
- return { success: true };
95
- }
96
- ```
97
-
98
- ---
99
-
100
- ### 3. Initialize Phase
101
-
102
- **Purpose:** Register stores and initialize resources
103
-
104
- **When executed:** After configuration
105
-
106
- **Use cases:**
107
-
108
- - Register Pinia stores
109
- - Set up event listeners
110
- - Initialize module-specific resources
111
- - Prepare data structures
112
-
113
- **Hook signature:**
114
-
115
- ```typescript
116
- async initialize(): Promise<ModuleLifecycleResult>
117
- ```
118
-
119
- **Implementation example:**
120
-
121
- ```typescript
122
- async initialize(): Promise<ModuleLifecycleResult> {
123
- // Register Pinia store
124
- const pinia = app.config.globalProperties.$pinia;
125
- pinia.use(myStorePlugin);
126
-
127
- // Initialize module resources
128
- await this.loadInitialData();
129
-
130
- return {
131
- success: true,
132
- metadata: { storesRegistered: 1 }
133
- };
134
- }
135
- ```
136
-
137
- ---
138
-
139
- ### 4. Ready Phase
140
-
141
- **Purpose:** Signal that the module is ready for use
142
-
143
- **When executed:** After all modules are initialized
144
-
145
- **Use cases:**
146
-
147
- - Perform final checks
148
- - Emit ready events
149
- - Log readiness status
150
-
151
- **Hook signature:**
152
-
153
- ```typescript
154
- async ready(): Promise<ModuleLifecycleResult>
155
- ```
156
-
157
- **Implementation example:**
158
-
159
- ```typescript
160
- async ready(): Promise<ModuleLifecycleResult> {
161
- console.log(`Module ${this.name} v${this.version} is ready!`);
162
-
163
- return {
164
- success: true,
165
- metadata: { startTime: Date.now() }
166
- };
167
- }
168
- ```
169
-
170
- ---
171
-
172
- ### 5. Post-Init Phase
173
-
174
- **Purpose:** Cross-module integrations and final setup
175
-
176
- **When executed:** After all modules are ready
177
-
178
- **Use cases:**
179
-
180
- - Integrate with other modules
181
- - Set up cross-module communication
182
- - Perform final setup that requires all modules to be ready
183
-
184
- **Hook signature:**
185
-
186
- ```typescript
187
- async postInit(): Promise<ModuleLifecycleResult>
188
- ```
189
-
190
- **Implementation example:**
191
-
192
- ```typescript
193
- async postInit(): Promise<ModuleLifecycleResult> {
194
- // Access other modules from host's module registry
195
- // Set up cross-module event listeners
196
- // Perform integrations
197
-
198
- return { success: true };
199
- }
200
- ```
201
-
202
- ---
203
-
204
- ## Result Object
205
-
206
- All lifecycle hooks must return a `ModuleLifecycleResult`:
207
-
208
- ```typescript
209
- interface ModuleLifecycleResult {
210
- /**
211
- * Whether the phase completed successfully.
212
- * If false, the error is logged but the module continues through remaining phases.
213
- */
214
- success: boolean;
215
-
216
- /**
217
- * Error message if the phase failed.
218
- */
219
- error?: string;
220
-
221
- /**
222
- * Additional metadata from the phase (for debugging).
223
- */
224
- metadata?: Record<string, unknown>;
225
- }
226
- ```
227
-
228
- ### Success Result
229
-
230
- ```typescript
231
- return { success: true };
232
- ```
233
-
234
- ### Success with Metadata
235
-
236
- ```typescript
237
- return {
238
- success: true,
239
- metadata: {
240
- storesRegistered: 2,
241
- dataLoaded: true,
242
- },
243
- };
244
- ```
245
-
246
- ### Failure Result
247
-
248
- ```typescript
249
- return {
250
- success: false,
251
- error: 'Missing required configuration',
252
- };
253
- ```
254
-
255
- ---
256
-
257
- ## Implementing a Module
258
-
259
- ### Option 1: Extending BasicRemoteModule (Recommended)
260
-
261
- The corelib provides a `BasicRemoteModule` class with default implementations for all hooks:
262
-
263
- ```typescript
264
- import { BasicRemoteModule } from '@linagora/linid-im-front-corelib';
265
- import type { ModuleLifecycleResult } from '@linagora/linid-im-front-corelib';
266
- import type { App } from 'vue';
267
-
268
- class MyModule extends BasicRemoteModule {
269
- constructor() {
270
- super('my-module', 'My Business Module', '1.0.0', 'Description');
271
- }
272
-
273
- // Override only the hooks you need
274
- async initialize(): Promise<ModuleLifecycleResult> {
275
- // do something
276
-
277
- return { success: true };
278
- }
279
- }
280
-
281
- export default new MyModule();
282
- ```
283
-
284
- **Advantages:**
285
-
286
- - ✅ All hooks have default implementations (return success)
287
- - ✅ Override only what you need
288
- - ✅ Object-oriented design
289
- - ✅ Follows SOLID principles
290
- - ✅ Easy to extend and maintain
291
-
292
- ---
293
-
294
- ### Option 2: Implementing RemoteModule Interface
295
-
296
- Implement the `RemoteModule` interface directly for full control:
297
-
298
- ```typescript
299
- import type {
300
- RemoteModule,
301
- ModuleLifecycleResult,
302
- ModuleHostConfig,
303
- } from '@linagora/linid-im-front-corelib';
304
- import type { App } from 'vue';
305
-
306
- class MyModule implements RemoteModule {
307
- id = 'my-module';
308
- name = 'My Business Module';
309
- version = '1.0.0';
310
- description = 'Description of what the module does';
311
-
312
- async setup(): Promise<ModuleLifecycleResult> {
313
- // Validate dependencies
314
- return { success: true };
315
- }
316
-
317
- async configure(
318
- config: ModuleHostConfig
319
- ): Promise<ModuleLifecycleResult> {
320
- // Apply configuration
321
- if (!config.id) {
322
- return { success: false, error: 'Missing module ID' };
323
- }
324
- return { success: true };
325
- }
326
-
327
- async initialize(): Promise<ModuleLifecycleResult> {
328
- // do something
329
- return { success: true };
330
- }
331
-
332
- async ready(): Promise<ModuleLifecycleResult> {
333
- // do something
334
- return { success: true };
335
- }
336
-
337
- async postInit(): Promise<ModuleLifecycleResult> {
338
- // Cross-module integrations
339
- return { success: true };
340
- }
341
- }
342
-
343
- export default new MyModule();
344
- ```
345
-
346
- **Advantages:**
347
-
348
- - ✅ Full control over implementation
349
- - ✅ Implement only needed hooks
350
- - ✅ Type-safe with TypeScript
351
- - ✅ Clean, explicit code
352
-
353
- ---
354
-
355
- ### Module Federation Configuration
356
-
357
- Expose the lifecycle in your module's `vite.config.ts`:
358
-
359
- ```typescript
360
- import { defineConfig } from 'vite';
361
- import federation from '@originjs/vite-plugin-federation';
362
-
363
- export default defineConfig({
364
- plugins: [
365
- federation({
366
- name: 'myBusinessModule',
367
- filename: 'remoteEntry.js',
368
- exposes: {
369
- './lifecycle': './src/lifecycle.ts', // Required for business modules
370
- './MyComponent': './src/components/MyComponent.vue',
371
- },
372
- }),
373
- ],
374
- });
375
- ```
376
-
377
- ---
378
-
379
- ## Best Practices
380
-
381
- ### 1. Keep Phases Focused
382
-
383
- Each phase should have a single, clear responsibility.
384
-
385
- ✅ **Good:**
386
-
387
- ```typescript
388
- async initialize(): Promise<ModuleLifecycleResult> {
389
- return { success: true };
390
- }
391
- ```
392
-
393
- ❌ **Bad:**
394
-
395
- ```typescript
396
- async initialize(): Promise<ModuleLifecycleResult> {
397
- await fetchUserData(); // Should be in ready or postInit
398
- integrateWithOtherModule(); // Should be in postInit
399
- return { success: true };
400
- }
401
- ```
402
-
403
- ---
404
-
405
- ### 2. Always Return a Valid Result
406
-
407
- Never return `undefined` or forget the return statement.
408
-
409
- ✅ **Good:**
410
-
411
- ```typescript
412
- return { success: true };
413
- ```
414
-
415
- ✅ **Good:**
416
-
417
- ```typescript
418
- return {
419
- success: false,
420
- error: 'Missing required configuration',
421
- };
422
- ```
423
-
424
- ❌ **Bad:**
425
-
426
- ```typescript
427
- return; // Invalid, returns undefined
428
- ```
429
-
430
- ---
431
-
432
- ### 3. Use Metadata for Debugging
433
-
434
- Provide useful debugging information in the metadata.
435
-
436
- ```typescript
437
- return {
438
- success: true,
439
- metadata: {
440
- storesRegistered: 2,
441
- routesRegistered: 3,
442
- duration: Date.now() - startTime,
443
- },
444
- };
445
- ```
446
-
447
- ---
448
-
449
- ### 4. Fail Fast in Setup
450
-
451
- Validate prerequisites early in the Setup phase.
452
-
453
- ```typescript
454
- async setup(): Promise<ModuleLifecycleResult> {
455
- if (!window.someRequiredAPI) {
456
- return {
457
- success: false,
458
- error: 'Required API not available'
459
- };
460
- }
461
-
462
- if (!app) {
463
- return {
464
- success: false,
465
- error: 'Vue app instance not available'
466
- };
467
- }
468
-
469
- return { success: true };
470
- }
471
- ```
472
-
473
- ---
474
-
475
- ### 5. Don't Throw Errors
476
-
477
- Return failure results instead of throwing errors.
478
-
479
- ✅ **Good:**
480
-
481
- ```typescript
482
- if (!config.id) {
483
- return { success: false, error: 'Missing module ID' };
484
- }
485
- ```
486
-
487
- ❌ **Bad:**
488
-
489
- ```typescript
490
- if (!config.id) {
491
- throw new Error('Missing module ID'); // Will be caught by host but not clean
492
- }
493
- ```
494
-
495
- **Why:** Thrown errors are caught by the host and converted to failure results, but explicit returns are clearer and follow the expected pattern.
496
-
497
- ---
498
-
499
- ### 6. Implement Only What You Need
500
-
501
- All lifecycle hooks are optional. Don't implement hooks your module doesn't need.
502
-
503
- ```typescript
504
- class SimpleModule extends BasicRemoteModule {
505
- constructor() {
506
- super('simple-module', 'Simple Module', '1.0.0');
507
- }
508
-
509
- async initialize(): Promise<ModuleLifecycleResult> {
510
- return { success: true };
511
- }
512
-
513
- // No need for setup, configure, ready, or postInit
514
- }
515
-
516
- export default new SimpleModule();
517
- ```
518
-
519
- ---
520
-
521
- ## Error Handling
522
-
523
- ### Module Fails to Load
524
-
525
- If a module fails to load via Module Federation, the host will log an error:
526
-
527
- ```
528
- [Module Lifecycle] Failed to load module myBusinessModule/lifecycle: <error>
529
- ```
530
-
531
- **Consequences:**
532
-
533
- - Module is not added to the registry
534
- - Module does not participate in lifecycle phases
535
- - Other modules continue normally
536
-
537
- ---
538
-
539
- ### Phase Execution Fails
540
-
541
- If a lifecycle phase returns `success: false` or throws an error:
542
-
543
- ```
544
- [Module Lifecycle] my-module: Error in initialize phase: <error>
545
- ```
546
-
547
- **Consequences:**
548
-
549
- - Error is logged by the host
550
- - Module continues through remaining phases
551
- - Other modules are not affected
552
-
553
- ---
554
-
555
- ### Invalid Phase Result
556
-
557
- If a lifecycle hook returns an invalid result (not a `ModuleLifecycleResult` object):
558
-
559
- ```
560
- [Module Lifecycle] my-module: Phase setup returned invalid result, treating as success
561
- ```
562
-
563
- **Consequences:**
564
-
565
- - Host treats the phase as successful
566
- - Module continues through remaining phases
567
- - Warning is logged for debugging
568
-
569
- ---
570
-
571
- ## Execution Sequence
572
-
573
- The host executes lifecycle phases in this order:
574
-
575
- ```
576
- Host Application
577
-
578
- ├─ 1. Load modules.json (get list of modules to load)
579
-
580
- ├─ 2. For each module in modules.json:
581
- │ ├─ Load module-<name>.json configuration
582
- │ └─ Load module via Module Federation (remoteName/lifecycle)
583
-
584
- ├─ 3. Phase 1: Setup (all modules in parallel)
585
- │ ├─ module-A.setup(app)
586
- │ ├─ module-B.setup(app)
587
- │ └─ module-C.setup(app)
588
-
589
- ├─ 4. Phase 2: Configure (all modules in parallel)
590
- │ ├─ module-A.configure(app, configA)
591
- │ ├─ module-B.configure(app, configB)
592
- │ └─ module-C.configure(app, configC)
593
-
594
- ├─ 5. Phase 3: Initialize (all modules in parallel)
595
- │ ├─ module-A.initialize(app)
596
- │ ├─ module-B.initialize(app)
597
- │ └─ module-C.initialize(app)
598
-
599
- ├─ 6. Phase 4: Ready (all modules in parallel)
600
- │ ├─ module-A.ready(app)
601
- │ ├─ module-B.ready(app)
602
- │ └─ module-C.ready(app)
603
-
604
- └─ 7. Phase 5: Post-Init (all modules in parallel)
605
- ├─ module-A.postInit(app)
606
- ├─ module-B.postInit(app)
607
- └─ module-C.postInit(app)
608
- ```
609
-
610
- **Key points:**
611
-
612
- - All modules complete one phase before moving to the next
613
- - Phases execute in parallel for all modules (using `Promise.allSettled`)
614
- - Failure in one module doesn't block others
615
-
616
- ---
617
-
618
- ## Integration with Host
619
-
620
- ### Host Responsibilities
621
-
622
- The host application is responsible for:
623
-
624
- 1. ✅ Loading module configurations from `modules.json`
625
- 2. ✅ Loading each module's configuration file (`module-<name>.json`)
626
- 3. ✅ Loading modules via Module Federation
627
- 4. ✅ Executing each lifecycle phase in sequence for all modules
628
- 5. ✅ Handling errors and logging
629
- 6. ✅ Providing the Vue `app` instance to modules
630
-
631
- ### Module Responsibilities
632
-
633
- Business modules are responsible for:
634
-
635
- 1. ✅ Exposing `./lifecycle` in Module Federation config
636
- 2. ✅ Implementing the `RemoteModule` interface (or extending `BasicRemoteModule`)
637
- 3. ✅ Returning valid `ModuleLifecycleResult` from all hooks
638
- 4. ✅ Handling their own errors gracefully
639
- 5. ✅ Using the provided `app` instance correctly
640
-
641
- ---
642
-
643
- ## Future Enhancements
644
-
645
- The following features are planned for future versions:
646
-
647
- ### Router Integration
648
-
649
- Add direct router access for route registration:
650
-
651
- ```typescript
652
- async initialize(): Promise<ModuleLifecycleResult> {
653
- return { success: true };
654
- }
655
- ```
656
-
657
- ### Zone System
658
-
659
- Allow modules to inject components into named zones in the UI.
660
-
661
- ### Module Dependencies
662
-
663
- Declare and validate inter-module dependencies:
664
-
665
- ```typescript
666
- class MyModule extends BasicRemoteModule {
667
- dependencies = ['core-module', 'auth-module'];
668
-
669
- // ...
670
- }
671
- ```
672
-
673
- ### Lazy Loading
674
-
675
- Support for lazy-loaded module features that load on demand.
676
-
677
- ---
678
-
679
- ## Troubleshooting
680
-
681
- ### Module Not Loading
682
-
683
- **Problem:** Module doesn't appear in lifecycle logs
684
-
685
- **Solutions:**
686
-
687
- 1. Check module is listed in host's `modules.json`
688
- 2. Verify config file exists: `module-<name>.json`
689
- 3. Check Module Federation remote is registered in `remotes.json`
690
- 4. Verify module exposes `./lifecycle` in its Module Federation config
691
- 5. Check browser console for loading errors
692
-
693
- ---
694
-
695
- ### Lifecycle Hook Not Called
696
-
697
- **Problem:** A specific lifecycle hook is not being called
698
-
699
- **Solutions:**
700
-
701
- 1. Verify the hook is implemented and exported
702
- 2. Check the hook signature matches the interface
703
- 3. Ensure the hook is `async` and returns a `Promise<ModuleLifecycleResult>`
704
- 4. Check browser console for `[Module Lifecycle]` logs
705
-
706
- ---
707
-
708
- ### Configuration Not Received
709
-
710
- **Problem:** Module's `configure` receives unexpected configuration
711
-
712
- **Solutions:**
713
-
714
- 1. Verify module's `id` matches the `id` in host config
715
- 2. Check the config file path: `module-<module-name>.json`
716
- 3. Validate JSON syntax in config file
717
- 4. Check browser network tab for config file fetch (404?)