@softarc/native-federation-orchestrator 4.4.1 → 4.5.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 (27) hide show
  1. package/README.md +2 -2
  2. package/fesm2022/@softarc/native-federation-orchestrator.mjs +509 -78
  3. package/fesm2022/@softarc/native-federation-orchestrator.mjs.map +4 -4
  4. package/fesm2022/module-federation.mjs +21 -17
  5. package/fesm2022/module-federation.mjs.map +2 -2
  6. package/fesm2022/node.mjs +439 -72
  7. package/fesm2022/node.mjs.map +4 -4
  8. package/fesm2022/sdk.mjs +63 -1
  9. package/fesm2022/sdk.mjs.map +3 -3
  10. package/package.json +1 -1
  11. package/quickstart.mjs +13 -13
  12. package/types/lib/core/1.domain/externals/version.contract.d.ts +3 -2
  13. package/types/lib/core/1.domain/remote-entry/remote-entry.contract.d.ts +8 -4
  14. package/types/lib/core/2.app/config/mode.contract.d.ts +6 -0
  15. package/types/lib/core/2.app/driver-ports/init/drivers.contract.d.ts +4 -0
  16. package/types/lib/core/2.app/driver-ports/init/for-pooling-dynamic-externals.port.d.ts +8 -0
  17. package/types/lib/core/2.app/driver-ports/init/for-pooling-shared-externals.port.d.ts +1 -0
  18. package/types/lib/core/2.app/driver-ports/init/index.d.ts +2 -0
  19. package/types/lib/core/2.app/driving-ports/for-shared-externals-storage.port.d.ts +2 -0
  20. package/types/lib/core/2.app/steps/convert-to-import-map.d.ts +2 -1
  21. package/types/lib/core/2.app/steps/pooling/pool-dynamic-externals.d.ts +3 -0
  22. package/types/lib/core/2.app/steps/pooling/pool-graph.d.ts +25 -0
  23. package/types/lib/core/2.app/steps/pooling/pool-shared-externals.d.ts +5 -0
  24. package/types/lib/core/2.app/steps/pooling/pool.types.d.ts +25 -0
  25. package/types/lib/core/2.app/steps/pooling/pool.util.d.ts +4 -0
  26. package/types/lib/core/2.app/steps/store-remote-entry.d.ts +2 -2
  27. package/types/lib/core/3.adapters/http/remote-entry-provider.d.ts +2 -1
@@ -4,8 +4,8 @@ export type Version = {
4
4
  tag: VersionName;
5
5
  };
6
6
  export type ScopedVersion = Version & {
7
- file: string;
8
7
  bundle?: string;
8
+ entries: Record<string, string>;
9
9
  };
10
10
  export type SharedVersion = Version & {
11
11
  host: boolean;
@@ -14,10 +14,11 @@ export type SharedVersion = Version & {
14
14
  };
15
15
  export type SharedVersionAction = 'skip' | 'scope' | 'share';
16
16
  export type SharedVersionMeta = {
17
- file: string;
18
17
  requiredVersion: string;
19
18
  strictVersion: boolean;
20
19
  cached: boolean;
21
20
  name: RemoteName;
22
21
  bundle?: string;
22
+ pool?: string;
23
+ entries: Record<string, string>;
23
24
  };
@@ -1,13 +1,17 @@
1
1
  import type { SharedVersionAction } from '../externals/version.contract';
2
2
  import type { RemoteEntryUrl } from './manifest.contract';
3
- import type { ExposesInfo, FederationInfo, SharedInfo } from '@softarc/native-federation/domain';
4
- type RemoteEntry = FederationInfo & {
3
+ import type { DenseSharedInfo, ExposesInfo, FederationInfo, SharedInfo } from '@softarc/native-federation/domain';
4
+ type RawRemoteEntry = FederationInfo;
5
+ type RemoteEntry = Omit<FederationInfo, 'shared'> & {
6
+ shared: DenseSharedInfo[];
5
7
  url: RemoteEntryUrl;
6
8
  host?: boolean;
7
9
  override?: boolean;
8
10
  };
11
+ declare function toDenseSharedInfoFormat(shared: Array<SharedInfo | DenseSharedInfo>): DenseSharedInfo[];
12
+ declare function densifyExternals(shared: Array<SharedInfo | DenseSharedInfo>): Array<SharedInfo | DenseSharedInfo>;
9
13
  type SharedInfoActions = Record<string, {
10
14
  action: SharedVersionAction;
11
- override?: string;
15
+ override?: Record<string, string>;
12
16
  }>;
13
- export { RemoteEntry, FederationInfo, ExposesInfo, SharedInfo, SharedInfoActions };
17
+ export { RawRemoteEntry, RemoteEntry, FederationInfo, ExposesInfo, SharedInfo, DenseSharedInfo, SharedInfoActions, toDenseSharedInfoFormat, densifyExternals, };
@@ -5,6 +5,10 @@ export type ModeProfileConfig = {
5
5
  overrideCachedRemotesIfURLMatches: boolean;
6
6
  cacheTag?: string;
7
7
  };
8
+ export type ModeFeatureConfig = {
9
+ convertFlatSharedInfo: boolean;
10
+ useAutoExternalPooling: boolean;
11
+ };
8
12
  export type ModeStrictnessConfig = {
9
13
  strictRemoteEntry: boolean;
10
14
  strictExternalCompatibility: boolean;
@@ -15,8 +19,10 @@ export type ModeStrictnessConfig = {
15
19
  export type ModeConfig = {
16
20
  strict: ModeStrictnessConfig;
17
21
  profile: ModeProfileConfig;
22
+ feature: ModeFeatureConfig;
18
23
  };
19
24
  export type ModeOptions = {
20
25
  strict?: Partial<ModeStrictnessConfig> | boolean;
21
26
  profile?: Partial<ModeProfileConfig>;
27
+ feature?: Partial<ModeFeatureConfig>;
22
28
  };
@@ -1,5 +1,7 @@
1
1
  import type { ForCommittingChanges } from './for-committing-changes.port';
2
2
  import type { ForDeterminingSharedExternals } from './for-determining-shared-externals.port';
3
+ import type { ForPoolingSharedExternals } from './for-pooling-shared-externals.port';
4
+ import type { ForPoolingDynamicExternals } from './for-pooling-dynamic-externals.port';
3
5
  import type { ForExposingModuleLoader } from './for-exposing-module-loader.port';
4
6
  import type { ForGeneratingImportMap } from './for-generating-import-map';
5
7
  import type { ForGettingRemoteEntries } from './for-getting-remote-entries.port';
@@ -13,11 +15,13 @@ export type InitDriversContract = {
13
15
  getRemoteEntries: ForGettingRemoteEntries;
14
16
  processRemoteEntries: ForProcessingRemoteEntries;
15
17
  determineSharedExternals: ForDeterminingSharedExternals;
18
+ poolSharedExternals: ForPoolingSharedExternals;
16
19
  generateImportMap: ForGeneratingImportMap;
17
20
  commitChanges: ForCommittingChanges;
18
21
  exposeModuleLoader: ForExposingModuleLoader;
19
22
  getRemoteEntry: ForGettingRemoteEntry;
20
23
  updateCache: ForUpdatingCache;
24
+ poolDynamicExternals: ForPoolingDynamicExternals;
21
25
  convertToImportMap: ForConvertingToImportMap;
22
26
  };
23
27
  export type InitDriversFactory = (config: ConfigContract, adapters: DrivingContract) => InitDriversContract;
@@ -0,0 +1,8 @@
1
+ import type { RemoteEntry, SharedInfoActions } from '../../../1.domain';
2
+ export type ForPoolingDynamicExternals = (input: {
3
+ entry: RemoteEntry;
4
+ actions: SharedInfoActions;
5
+ }) => Promise<{
6
+ entry: RemoteEntry;
7
+ actions: SharedInfoActions;
8
+ }>;
@@ -0,0 +1 @@
1
+ export type ForPoolingSharedExternals = () => Promise<void>;
@@ -1,6 +1,8 @@
1
1
  export * from './for-getting-remote-entries.port';
2
2
  export * from './for-processing-remote-entries.port';
3
3
  export * from './for-determining-shared-externals.port';
4
+ export * from './for-pooling-shared-externals.port';
5
+ export * from './for-pooling-dynamic-externals.port';
4
6
  export * from './for-generating-import-map';
5
7
  export * from './for-committing-changes.port';
6
8
  export * from './for-exposing-module-loader.port';
@@ -9,5 +9,7 @@ export type ForSharedExternalsStorage = {
9
9
  scopeType: (shareScope?: string) => 'global' | 'strict' | 'shareScope';
10
10
  removeFromAllScopes: (remoteName: RemoteName) => void;
11
11
  addOrUpdate: (name: string, external: SharedExternal, shareScope?: string) => ForSharedExternalsStorage;
12
+ markPoolTagPresent: () => void;
13
+ hasPoolTag: () => boolean;
12
14
  commit: () => ForSharedExternalsStorage;
13
15
  };
@@ -1,4 +1,5 @@
1
1
  import type { LoggingConfig } from '../config/log.contract';
2
+ import type { ModeConfig } from '../config/mode.contract';
2
3
  import type { ForConvertingToImportMap } from '../driver-ports/init/for-converting-to-import-map';
3
4
  import type { DrivingContract } from '../driving-ports/driving.contract';
4
- export declare function createConvertToImportMap({ log }: LoggingConfig, ports: Pick<DrivingContract, 'sharedChunksRepo'>): ForConvertingToImportMap;
5
+ export declare function createConvertToImportMap(config: LoggingConfig & ModeConfig, ports: Pick<DrivingContract, 'sharedChunksRepo'>): ForConvertingToImportMap;
@@ -0,0 +1,3 @@
1
+ import type { ForPoolingDynamicExternals } from '../../driver-ports/init/for-pooling-dynamic-externals.port';
2
+ import type { ModeConfig } from '../../config/mode.contract';
3
+ export declare function createPoolDynamicExternals(config: ModeConfig): ForPoolingDynamicExternals;
@@ -0,0 +1,25 @@
1
+ import type { ExternalName, shareScope } from '../../../1.domain';
2
+ import type { LogHandler } from '../../config/log.contract';
3
+ import type { PoolMember, PoolName } from './pool.types';
4
+ export type PoolEdge = {
5
+ remote: string;
6
+ tag: string;
7
+ };
8
+ export type PoolCandidate<T> = {
9
+ name: ExternalName;
10
+ scope?: string;
11
+ tags: readonly PoolEdge[];
12
+ value: T;
13
+ };
14
+ export declare function autoScope(name: string, useAutoExternalPooling: boolean): string | undefined;
15
+ /**
16
+ * Group one shareScope's candidates into pools by shared membership: pool = connected component of a
17
+ * graph with edges from auto-pooling (`external -> scope`, global) and declared tags
18
+ * (`external -> tag@remote`, remote-local). See docs/version-resolver.md + plan.md. Returns only real
19
+ * pools (>=2 members), keyed by and iterated in order of their canonical name (smallest member —
20
+ * reload-stable). An explicit-tag member that pooled with nothing is warned (likely typo or missing
21
+ * sibling); auto-scope singletons stay silent.
22
+ */
23
+ export declare function groupByMembership<T>(candidates: readonly PoolCandidate<T>[], log?: LogHandler): Map<PoolName, T[]>;
24
+ /** Init-path grouping: build candidates from the stored shared externals of one shareScope. */
25
+ export declare function buildPools(sharedExternals: shareScope, useAutoExternalPooling: boolean, log?: LogHandler): Map<PoolName, PoolMember[]>;
@@ -0,0 +1,5 @@
1
+ import type { ForPoolingSharedExternals } from '../../driver-ports/init/for-pooling-shared-externals.port';
2
+ import type { DrivingContract } from '../../driving-ports/driving.contract';
3
+ import type { LoggingConfig } from '../../config/log.contract';
4
+ import type { ModeConfig } from '../../config/mode.contract';
5
+ export declare function createPoolSharedExternals(config: LoggingConfig & ModeConfig, ports: Pick<DrivingContract, 'sharedExternalsRepo'>): ForPoolingSharedExternals;
@@ -0,0 +1,25 @@
1
+ import type { ExternalName, RemoteName, SharedExternal, VersionName } from '../../../1.domain';
2
+ export type PoolName = string;
3
+ export type PoolMember = {
4
+ name: ExternalName;
5
+ external: SharedExternal;
6
+ };
7
+ /**
8
+ * The remote chosen to serve a whole pool, plus the version tag it provides for each member.
9
+ * The anchor may be partial: members absent from `tagPerMember` are orphans (no coherent shared
10
+ * build exists) and resolve scoped-only.
11
+ */
12
+ export type PoolAnchor = {
13
+ anchorRemote: RemoteName;
14
+ tagPerMember: Partial<Record<ExternalName, VersionName>>;
15
+ };
16
+ /**
17
+ * How a remote is placed relative to the anchor, decided once for the whole pool:
18
+ * - `follow` — every member it uses is compatible with the anchor tag;
19
+ * - `scope-incompat` — strict-incompatible on ≥1 member; the whole family scopes with no dedup
20
+ * (deduping would inject a foreign build via a shared intermediary).
21
+ * Dominates `scope-coverage`;
22
+ * - `scope-coverage` — compatible where the anchor covers, but uses ≥1 member it does not provide;
23
+ * scoped for coverage, may still dedup same-version members.
24
+ */
25
+ export type RemoteClassification = 'follow' | 'scope-incompat' | 'scope-coverage';
@@ -0,0 +1,4 @@
1
+ import type { RemoteName, SharedVersion } from '../../../1.domain';
2
+ import type { PoolMember } from './pool.types';
3
+ export declare function versionForRemote(member: PoolMember, remote: RemoteName): SharedVersion | undefined;
4
+ export declare function remotesInPool(members: PoolMember[]): RemoteName[];
@@ -1,9 +1,9 @@
1
- import type { RemoteEntry, SharedExternal, SharedInfo, SharedVersion, SharedVersionMeta } from '../../1.domain';
1
+ import { type RemoteEntry, type SharedExternal, type DenseSharedInfo, type SharedVersion, type SharedVersionMeta } from '../../1.domain';
2
2
  import type { DrivingContract } from '../driving-ports/driving.contract';
3
3
  import type { LoggingConfig } from '../config/log.contract';
4
4
  import type { ModeConfig } from '../config/mode.contract';
5
5
  export type StoreRemoteEntry = (remoteEntry: RemoteEntry, onSharedExternal: SharedExternalHandler) => void;
6
- export type SharedExternalHandler = (remoteEntry: RemoteEntry, external: SharedInfo, ctx: SharedExternalContext) => void;
6
+ export type SharedExternalHandler = (remoteEntry: RemoteEntry, external: DenseSharedInfo, ctx: SharedExternalContext) => void;
7
7
  export type SharedExternalContext = {
8
8
  tag: string;
9
9
  remote: SharedVersionMeta;
@@ -1,3 +1,4 @@
1
1
  import type { ForProvidingRemoteEntries } from '../../2.app/driving-ports/for-providing-remote-entries.port';
2
- declare const createRemoteEntryProvider: () => ForProvidingRemoteEntries;
2
+ import type { ModeConfig } from '../../2.app/config/mode.contract';
3
+ declare const createRemoteEntryProvider: (config: ModeConfig) => ForProvidingRemoteEntries;
3
4
  export { createRemoteEntryProvider };