@softarc/native-federation-orchestrator 4.6.0 → 4.7.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 (29) hide show
  1. package/README.md +2 -2
  2. package/fesm2022/@softarc/native-federation-orchestrator.mjs +340 -111
  3. package/fesm2022/@softarc/native-federation-orchestrator.mjs.map +4 -4
  4. package/fesm2022/node.mjs +231 -72
  5. package/fesm2022/node.mjs.map +4 -4
  6. package/fesm2022/options.mjs +6 -0
  7. package/fesm2022/options.mjs.map +2 -2
  8. package/fesm2022/sdk.mjs.map +1 -1
  9. package/node-loader/loader.mjs +26 -6
  10. package/node-loader/loader.mjs.map +2 -2
  11. package/package.json +1 -1
  12. package/quickstart.mjs +15 -15
  13. package/types/lib/core/1.domain/externals/external.contract.d.ts +1 -0
  14. package/types/lib/core/1.domain/externals/version.contract.d.ts +2 -0
  15. package/types/lib/core/2.app/config/index.d.ts +2 -1
  16. package/types/lib/core/2.app/config/mode.contract.d.ts +0 -1
  17. package/types/lib/core/2.app/config/orchestrator-global.contract.d.ts +15 -0
  18. package/types/lib/core/2.app/config/storage.contract.d.ts +14 -2
  19. package/types/lib/core/2.app/driving-ports/for-shared-externals-storage.port.d.ts +1 -1
  20. package/types/lib/core/2.app/steps/pooling/pool-graph.d.ts +7 -12
  21. package/types/lib/core/2.app/steps/pooling/pool.util.d.ts +12 -11
  22. package/types/lib/core/3.adapters/browser/sse-handler.d.ts +0 -8
  23. package/types/lib/core/3.adapters/storage/chunk.repository.d.ts +1 -1
  24. package/types/lib/core/3.adapters/storage/remote-info.repository.d.ts +1 -1
  25. package/types/lib/core/3.adapters/storage/scoped-externals.repository.d.ts +1 -1
  26. package/types/lib/core/3.adapters/storage/shared-externals.repository.d.ts +1 -1
  27. package/types/lib/core/4.config/storage/publish-storage-info.d.ts +9 -0
  28. package/types/lib/testing/pooling/tag-by-npm-scope.d.ts +9 -0
  29. package/types/scripts/node-loader.d.ts +1 -0
@@ -5,6 +5,7 @@ export declare const GLOBAL_SCOPE = "__GLOBAL__";
5
5
  export declare const STRICT_SCOPE = "strict";
6
6
  export type SharedExternal = {
7
7
  dirty: boolean;
8
+ poolName?: string;
8
9
  versions: SharedVersion[];
9
10
  };
10
11
  export type shareScope = Record<string, SharedExternal>;
@@ -13,6 +13,7 @@ export type SharedVersion = Version & {
13
13
  remotes: SharedVersionMeta[];
14
14
  };
15
15
  export type SharedVersionAction = 'skip' | 'scope' | 'share';
16
+ export type PoolCause = 'incompatible' | 'uncovered' | 'torn' | 'unshared';
16
17
  export type SharedVersionMeta = {
17
18
  requiredVersion: string;
18
19
  strictVersion: boolean;
@@ -22,4 +23,5 @@ export type SharedVersionMeta = {
22
23
  pool?: string;
23
24
  entries: Record<string, string>;
24
25
  servedBy?: RemoteName;
26
+ poolCause?: PoolCause;
25
27
  };
@@ -1,6 +1,7 @@
1
1
  export { ImportMapOptions, ImportMapConfig } from './import-map.contract';
2
2
  export { LoggingOptions, LogLevel, LogType, LoggingConfig, LogHandler, Logger, } from './log.contract';
3
- export { StorageOptions, StorageEntry, StorageEntryKey, StorageConfig } from './storage.contract';
3
+ export { StorageOptions, StorageEntry, StorageEntryKey, StorageConfig, StorageType, StorageKey, } from './storage.contract';
4
+ export { NFOrchestratorGlobal, NFOrchestratorStorageInfo } from './orchestrator-global.contract';
4
5
  export { ModeOptions, ModeConfig } from './mode.contract';
5
6
  export { HostOptions, HostConfig } from './host.contract';
6
7
  export { NFOptions, ConfigContract } from './config.contract';
@@ -8,7 +8,6 @@ export type ModeProfileConfig = {
8
8
  };
9
9
  export type ModeFeatureConfig = {
10
10
  convertFlatSharedInfo: boolean;
11
- useAutoExternalPooling: boolean;
12
11
  };
13
12
  export type ModeStrictnessConfig = {
14
13
  strictRemoteEntry: boolean;
@@ -0,0 +1,15 @@
1
+ import type { StorageKey, StorageType } from './storage.contract';
2
+ type NFOrchestratorStorageInfo = Readonly<{
3
+ version: string;
4
+ type: StorageType;
5
+ namespace: string;
6
+ keys: readonly StorageKey[];
7
+ get?: (key: string) => unknown;
8
+ }>;
9
+ type NFOrchestratorGlobal = Readonly<{
10
+ storage: Readonly<Record<string, NFOrchestratorStorageInfo>>;
11
+ }>;
12
+ declare global {
13
+ var __NF_ORCHESTRATOR__: NFOrchestratorGlobal | undefined;
14
+ }
15
+ export { NFOrchestratorGlobal, NFOrchestratorStorageInfo };
@@ -4,7 +4,18 @@ type StorageEntry<TValue> = {
4
4
  clear: () => StorageEntry<TValue>;
5
5
  };
6
6
  type StorageEntryKey = number | symbol | string;
7
- type StorageEntryCreator = (namespace: string) => StorageEntryHandler;
7
+ type StorageType = 'globalThis' | 'localStorage' | 'sessionStorage' | 'custom';
8
+ type StorageEntryCreator = {
9
+ (namespace: string): StorageEntryHandler;
10
+ type?: StorageType;
11
+ };
12
+ declare const STORAGE_KEYS: {
13
+ readonly remotes: "remotes";
14
+ readonly sharedExternals: "shared-externals";
15
+ readonly scopedExternals: "scoped-externals";
16
+ readonly sharedChunks: "shared-chunks";
17
+ };
18
+ type StorageKey = (typeof STORAGE_KEYS)[keyof typeof STORAGE_KEYS];
8
19
  type StorageEntryHandler = <TValue>(key: string, initialValue: TValue) => StorageEntry<TValue>;
9
20
  type StorageConfig = {
10
21
  storage: StorageEntryHandler;
@@ -14,5 +25,6 @@ type StorageOptions = {
14
25
  storage?: StorageEntryCreator;
15
26
  clearStorage?: boolean;
16
27
  storageNamespace?: string;
28
+ exposeStorageGetter?: boolean;
17
29
  };
18
- export { StorageEntry, StorageEntryKey, StorageEntryHandler, StorageConfig, StorageOptions, StorageEntryCreator, };
30
+ export { StorageEntry, StorageEntryKey, StorageEntryHandler, StorageConfig, StorageOptions, StorageEntryCreator, StorageType, StorageKey, STORAGE_KEYS, };
@@ -9,6 +9,6 @@ export type ForSharedExternalsStorage = {
9
9
  scopeType: (shareScope?: string) => 'global' | 'strict' | 'shareScope';
10
10
  removeFromAllScopes: (remoteNames: ReadonlySet<RemoteName>) => void;
11
11
  addOrUpdate: (name: string, external: SharedExternal, shareScope?: string) => ForSharedExternalsStorage;
12
- hasPoolTag: (shareScope?: string) => boolean;
12
+ hasPoolState: (shareScope?: string) => boolean;
13
13
  commit: () => ForSharedExternalsStorage;
14
14
  };
@@ -7,24 +7,19 @@ export type PoolEdge = {
7
7
  };
8
8
  export type PoolCandidate<T> = {
9
9
  name: ExternalName;
10
- scope?: string;
11
10
  tags: readonly PoolEdge[];
12
- remotes: readonly string[];
13
11
  value: T;
14
12
  };
15
- export declare function autoScope(name: string, useAutoExternalPooling: boolean): string | undefined;
16
13
  export declare function owningPackage(name: ExternalName): ExternalName | undefined;
17
14
  /**
18
15
  * Group one shareScope's candidates into pools by shared membership: pool = connected component of a
19
- * graph whose edges are all remote-local — `external -> scope@remote` for each remote that declares
20
- * it (auto-pooling) and `external -> tag@remote` for each declared tag — plus an unconditional
21
- * `entrypoint -> package` edge. A pool therefore forms exactly when some remote declares members
22
- * from both sides. See docs/version-resolver.md.
16
+ * graph whose edges are all remote-local — `external -> tag@remote` for each declared tag — plus an
17
+ * unconditional `entrypoint -> package` edge. See docs/version-resolver.md.
23
18
  *
24
- * Returns only real pools (>=2 members), keyed by and iterated in order of their canonical name
25
- * (smallest member — reload-stable). An explicit-tag member that pooled with nothing is warned
26
- * (likely typo or missing sibling); auto-scope singletons stay silent.
19
+ * Returns only real pools (>=2 members), keyed by `poolName` and iterated in order of their smallest
20
+ * member, which is what keeps the names reload-stable. A tagged member that pooled with nothing is warned
21
+ * (likely typo or missing sibling).
27
22
  */
28
23
  export declare function groupByMembership<T>(candidates: readonly PoolCandidate<T>[], log?: LogHandler): Map<PoolName, T[]>;
29
- /** Init-path grouping: build candidates from the stored shared externals of one shareScope. */
30
- export declare function buildPools(sharedExternals: shareScope, useAutoExternalPooling: boolean, log?: LogHandler): Map<PoolName, PoolMember[]>;
24
+ /** Build candidates from the stored shared externals of one shareScope. */
25
+ export declare function buildPools(sharedExternals: shareScope, log?: LogHandler): Map<PoolName, PoolMember[]>;
@@ -1,18 +1,19 @@
1
- import type { RemoteName } from '../../../1.domain';
1
+ import type { RemoteName, shareScope } from '../../../1.domain';
2
2
  import type { ForSharedExternalsStorage } from '../../driving-ports/for-shared-externals-storage.port';
3
- import type { ModeConfig } from '../../config/mode.contract';
4
- import type { PoolMember } from './pool.types';
3
+ import type { PoolMember, PoolName } from './pool.types';
5
4
  export declare function lazy<T>(make: () => T): () => T;
6
5
  export declare function remotesInPool(members: PoolMember[]): RemoteName[];
7
6
  /**
8
- * The scopes either pooling step has anything to do in. With auto-pooling off only a scope that carries a
9
- * `pool` tag of its own can pool anything, and a pool never spans share scopes — so one tag must not put
10
- * every other scope through a graph build. Auto-pooling on must never early-out, since any scoped package is
11
- * potentially poolable. The `strict` scope is never pooled.
7
+ * The scopes either pooling step has anything to do in. A pool never spans share scopes, so one tag must
8
+ * not put every other scope through a graph build. The `strict` scope is never pooled.
12
9
  *
13
10
  * Names only, so a caller that decides to skip a scope never reads it out of storage.
14
11
  */
15
- export declare function poolableScopes(config: ModeConfig, repo: Pick<ForSharedExternalsStorage, 'getScopes' | 'scopeType' | 'hasPoolTag'>): {
16
- useAutoExternalPooling: boolean;
17
- scopes: string[];
18
- };
12
+ export declare function poolableScopes(repo: Pick<ForSharedExternalsStorage, 'getScopes' | 'scopeType' | 'hasPoolState'>): string[];
13
+ /**
14
+ * Write `poolName` onto every external of the scope that is in a pool under a different name, and clear it —
15
+ * with every copy's `poolCause` — off one that is in none any more. Names are per scope (a suffix
16
+ * disambiguates two pools sharing a tag), so a pool nobody re-elected can still be renamed by another.
17
+ * `skip` names pools whose members the caller is rebuilding itself.
18
+ */
19
+ export declare function syncPoolNames(sharedExternals: shareScope, pools: Map<PoolName, PoolMember[]>, repo: Pick<ForSharedExternalsStorage, 'addOrUpdate'>, scope: string, skip?: ReadonlySet<PoolName>): void;
@@ -1,13 +1,5 @@
1
1
  import type { ImportMapConfig } from '../../2.app/config/import-map.contract';
2
2
  import type { ForSSE } from '../../2.app/driving-ports/for-sse.port';
3
3
  import type { LoggingConfig } from '../../2.app/config/log.contract';
4
- /**
5
- * Watches for federation build completion events and automatically reloads the page.
6
- *
7
- * This function establishes a Server-Sent Events (SSE) connection to listen for
8
- * 'federation-rebuild-complete' notifications. When a build completes successfully,
9
- * it triggers a page reload to reflect the latest changes.
10
- * @param endpoint - The SSE endpoint URL to watch for build notifications.
11
- */
12
4
  declare const createSSEHandler: (config: ImportMapConfig & LoggingConfig) => ForSSE;
13
5
  export { createSSEHandler };
@@ -1,4 +1,4 @@
1
- import type { StorageConfig } from '../../2.app/config/storage.contract';
1
+ import { type StorageConfig } from '../../2.app/config/storage.contract';
2
2
  import type { ForSharedChunksStorage } from '../../2.app/driving-ports/for-shared-chunks-storage.port';
3
3
  declare const createChunkRepository: (config: StorageConfig) => ForSharedChunksStorage;
4
4
  export { createChunkRepository };
@@ -1,4 +1,4 @@
1
- import type { StorageConfig } from '../../2.app/config/storage.contract';
1
+ import { type StorageConfig } from '../../2.app/config/storage.contract';
2
2
  import type { ForRemoteInfoStorage } from '../../2.app/driving-ports/for-remote-info-storage.port';
3
3
  declare const createRemoteInfoRepository: (config: StorageConfig) => ForRemoteInfoStorage;
4
4
  export { createRemoteInfoRepository };
@@ -1,4 +1,4 @@
1
- import type { StorageConfig } from '../../2.app/config/storage.contract';
1
+ import { type StorageConfig } from '../../2.app/config/storage.contract';
2
2
  import type { ForScopedExternalsStorage } from '../../2.app/driving-ports/for-scoped-externals-storage.port';
3
3
  declare const createScopedExternalsRepository: (config: StorageConfig) => ForScopedExternalsStorage;
4
4
  export { createScopedExternalsRepository };
@@ -1,4 +1,4 @@
1
- import type { StorageConfig } from '../../2.app/config/storage.contract';
1
+ import { type StorageConfig } from '../../2.app/config/storage.contract';
2
2
  import type { ForSharedExternalsStorage } from '../../2.app/driving-ports/for-shared-externals-storage.port';
3
3
  declare const createSharedExternalsRepository: (config: StorageConfig) => ForSharedExternalsStorage;
4
4
  export { createSharedExternalsRepository };
@@ -0,0 +1,9 @@
1
+ import { type StorageEntryHandler, type StorageType } from '../../2.app/config/storage.contract';
2
+ type StorageInfoOptions = {
3
+ type: StorageType;
4
+ namespace: string;
5
+ storage: StorageEntryHandler;
6
+ exposeGetter: boolean;
7
+ };
8
+ export declare const publishStorageInfo: (options: StorageInfoOptions) => void;
9
+ export {};
@@ -0,0 +1,9 @@
1
+ import type { shareScope } from '../../core/1.domain';
2
+ export declare const npmScope: (name: string) => string | undefined;
3
+ /** Remote-entry side: tags each untagged scoped `shared` item, returning new objects. */
4
+ export declare const tagSharedInfoByNpmScope: <T extends {
5
+ packageName: string;
6
+ pool?: string;
7
+ }>(shared: readonly T[]) => T[];
8
+ /** Storage side: tags every untagged copy of a scoped external in place, returning the same record. */
9
+ export declare const tagStoredByNpmScope: <T extends shareScope>(externals: T) => T;
@@ -35,6 +35,7 @@ type LoadResult = {
35
35
  format: string;
36
36
  source?: string | ArrayBuffer | Uint8Array;
37
37
  shortCircuit?: boolean;
38
+ responseURL?: string;
38
39
  };
39
40
  type NextLoad = (url: string, context?: LoadContext) => Promise<LoadResult>;
40
41
  export declare function load(url: string, context: LoadContext, nextLoad: NextLoad): Promise<LoadResult>;