From cb3fafc48f127d7db3959ce494f5a33905d9a9bd Mon Sep 17 00:00:00 2001 From: Aukevanoost Date: Tue, 11 Aug 2026 09:57:15 +0200 Subject: [PATCH 1/4] fix(builders): spell the workspace root the way disk spells it Windows reports the same directory under whatever drive-letter case the caller used, so the root Nx inherits from the invoking shell can differ by case alone from the one esbuild's own working directory and process.cwd() produce. Every path derived from it is then compared as a plain string against paths derived from the other, most damagingly in the angular-compiler plugin's emitted-file cache: its keys follow the TypeScript program (and so the workspace root) while its lookups follow esbuild, so every exposed module reports "File ... not found in TypeScript compilation" and points at tsconfig files/include, which is a dead end. This is why a remote builds from one terminal and not another on the same machine. toCanonicalCase re-spells a root the way fs.realpathSync.native reports it, but only when the two differ by case alone. realpath also resolves symlinks, and adopting a broader difference would move npm-linked and pnpm workspaces off the path they were handed. The .native variant is load-bearing: the JS realpathSync walks the components of the input string and rewrites only the ones that are symlinks, so it preserves the caller's casing and cannot fix this. Applied once per invocation, at the builder boundary, so the four places that read context.workspaceRoot -- including both esbuild bundlers, which reach it through the adapter's closure -- inherit it with no further change. The wrap sits inside runBuilder rather than in createBuilder because runBuilder is re-exported from internal.ts and callable directly. Angular's own build gets the same context: the two halves compare each other's paths (watch sets, cache keys), so splitting the root between them would trade this bug for another. Refs native-federation/angular-adapter#117 --- src/builders/build/builder.ts | 7 +- src/builders/remote/builder.ts | 6 +- src/utils/canonical-workspace-root.spec.ts | 98 ++++++++++++++++++++++ src/utils/canonical-workspace-root.ts | 53 ++++++++++++ 4 files changed, 162 insertions(+), 2 deletions(-) create mode 100644 src/utils/canonical-workspace-root.spec.ts create mode 100644 src/utils/canonical-workspace-root.ts diff --git a/src/builders/build/builder.ts b/src/builders/build/builder.ts index 4180e54..0750fdf 100644 --- a/src/builders/build/builder.ts +++ b/src/builders/build/builder.ts @@ -48,6 +48,7 @@ import { } from "@softarc/native-federation/internal"; import { type Plugin, type PluginBuild } from "esbuild"; import { devHostInstancesPlugin } from "../../plugin/dev-host-instances-plugin.js"; +import { withCanonicalWorkspaceRoot } from "./../../utils/canonical-workspace-root.js"; import { checkForInvalidImports } from "./../../utils/check-for-invalid-imports.js"; import { federationSourceFiles } from "./../../utils/federation-source-files.js"; import { federationBuildNotifier } from "./federation-build-notifier.js"; @@ -127,8 +128,12 @@ const createInternalAngularBuilder = export async function* runBuilder( nfBuilderOptions: NfBuilderSchema & NfInternalOptions, - context: BuilderContext, + builderContext: BuilderContext, ): AsyncIterable { + // One root for the whole invocation, ours and Angular's alike — the two halves compare + // each other's paths as plain strings (watch sets, cache keys). + const context = withCanonicalWorkspaceRoot(builderContext); + let target = targetFromTargetString(nfBuilderOptions.target); let targetOptions = (await context.getTargetOptions( diff --git a/src/builders/remote/builder.ts b/src/builders/remote/builder.ts index 1a7e8e8..65605be 100644 --- a/src/builders/remote/builder.ts +++ b/src/builders/remote/builder.ts @@ -29,6 +29,7 @@ import { } from '@softarc/native-federation/internal'; import { createAngularBuildAdapter } from '../../tools/esbuild/angular-esbuild-adapter.js'; +import { withCanonicalWorkspaceRoot } from '../../utils/canonical-workspace-root.js'; import { checkForInvalidImports } from '../../utils/check-for-invalid-imports.js'; import { federationSourceFiles } from '../../utils/federation-source-files.js'; @@ -52,8 +53,11 @@ import { export async function* runRemoteBuilder( nfBuilderOptions: NfRemoteBuilderSchema & NfRemoteInternalOptions, - context: BuilderContext + builderContext: BuilderContext ): AsyncIterable { + // One root for the whole invocation — see withCanonicalWorkspaceRoot. + const context = withCanonicalWorkspaceRoot(builderContext); + const federationTsConfig = nfBuilderOptions.tsConfig; const outputBase = nfBuilderOptions.outputPath ?? `dist/${context.target!.project}`; const browserOutputPath = path.join(outputBase, 'browser'); diff --git a/src/utils/canonical-workspace-root.spec.ts b/src/utils/canonical-workspace-root.spec.ts new file mode 100644 index 0000000..41d4261 --- /dev/null +++ b/src/utils/canonical-workspace-root.spec.ts @@ -0,0 +1,98 @@ +import * as fs from 'fs'; +import * as path from 'path'; + +import type { BuilderContext } from '@angular-devkit/architect'; + +import { toCanonicalCase, withCanonicalWorkspaceRoot } from './canonical-workspace-root.js'; + +vi.mock('fs'); + +function mockNativeRealpath(impl: (p: string) => string): void { + // vi.mock('fs') stubs realpathSync but not the `.native` property hanging off it. + vi.mocked(fs).realpathSync = Object.assign(vi.fn(), { + native: vi.fn(impl), + }) as unknown as typeof fs.realpathSync; +} + +beforeEach(() => { + vi.clearAllMocks(); +}); + +describe('toCanonicalCase', () => { + // The reported case: Nx inherits `c:\…` from the shell while the filesystem stores `C:\…`. + it('adopts the on-disk spelling when only the case differs', () => { + mockNativeRealpath(() => 'C:\\ws\\project'); + + expect(toCanonicalCase('c:\\ws\\project')).toBe(path.normalize('C:\\ws\\project')); + }); + + it('accepts a correction that also differs in separator style', () => { + mockNativeRealpath(() => 'C:/ws/project'); + + expect(toCanonicalCase('c:\\ws\\project')).toBe(path.normalize('C:/ws/project')); + }); + + it('ignores a trailing slash when deciding whether the paths are the same', () => { + mockNativeRealpath(() => 'C:/ws/project'); + + expect(toCanonicalCase('c:/ws/project/')).toBe(path.normalize('C:/ws/project')); + }); + + // A symlinked workspace root must stay on the path it was handed: npm-linked and pnpm + // setups resolve to a different directory entirely, not to a re-cased one. + it('keeps the input when realpath resolves to a different directory', () => { + mockNativeRealpath(() => '/real/checkout'); + + expect(toCanonicalCase('/links/project')).toBe('/links/project'); + }); + + it('keeps the input when realpath throws', () => { + mockNativeRealpath(() => { + throw new Error('ENOENT'); + }); + + expect(toCanonicalCase('/gone')).toBe('/gone'); + }); + + it('is a no-op when the spelling already matches', () => { + mockNativeRealpath(p => p); + + expect(toCanonicalCase('/ws/project')).toBe('/ws/project'); + }); +}); + +describe('withCanonicalWorkspaceRoot', () => { + function contextWith(workspaceRoot: string) { + return { + workspaceRoot, + target: { project: 'example' }, + logger: { warn: vi.fn() }, + getProjectMetadata: async () => ({ root: 'apps/example' }), + } as unknown as BuilderContext; + } + + it('returns a context carrying the canonical root', () => { + mockNativeRealpath(() => 'C:\\ws'); + const context = contextWith('c:\\ws'); + + expect(withCanonicalWorkspaceRoot(context).workspaceRoot).toBe(path.normalize('C:\\ws')); + }); + + it('keeps the rest of the context reachable', async () => { + mockNativeRealpath(() => 'C:\\ws'); + const context = contextWith('c:\\ws'); + + const derived = withCanonicalWorkspaceRoot(context); + + expect(derived.target).toBe(context.target); + expect(derived.logger).toBe(context.logger); + await expect(derived.getProjectMetadata('example')).resolves.toEqual({ root: 'apps/example' }); + }); + + it('hands back the very same context when nothing needed correcting', () => { + mockNativeRealpath(p => p); + const context = contextWith('/ws'); + + expect(withCanonicalWorkspaceRoot(context)).toBe(context); + }); +}); diff --git a/src/utils/canonical-workspace-root.ts b/src/utils/canonical-workspace-root.ts new file mode 100644 index 0000000..807e802 --- /dev/null +++ b/src/utils/canonical-workspace-root.ts @@ -0,0 +1,53 @@ +import * as fs from 'fs'; +import * as path from 'path'; + +import type { BuilderContext } from '@angular-devkit/architect'; + +/** + * Windows reports the same directory under whatever drive-letter case the caller used, so the + * root Nx inherits from the invoking shell can differ by case alone from the one esbuild's own + * working directory and `process.cwd()` produce. Everything downstream compares paths derived + * from it as plain strings — most damagingly the angular-compiler plugin's emitted-file cache, + * whose keys follow the TypeScript program (and thus the workspace root) while its lookups + * follow esbuild. See issue #117. + */ +export function withCanonicalWorkspaceRoot(context: BuilderContext): BuilderContext { + const workspaceRoot = toCanonicalCase(context.workspaceRoot); + + if (workspaceRoot === context.workspaceRoot) { + return context; + } + + // Derived, not spread: the architect context's methods close over the original object, and a + // non-enumerable or accessor member would not survive a copy. + return Object.create(context, { + workspaceRoot: { value: workspaceRoot, enumerable: true }, + }) as BuilderContext; +} + +/** + * The on-disk spelling of `p`, but only when it differs from `p` by case alone. `realpath` also + * resolves symlinks, and adopting that result would move npm-linked and pnpm workspaces off the + * path they were handed. + */ +export function toCanonicalCase(p: string): string { + let real: string; + + try { + // `fs.realpathSync` walks the components of the string it was given and only rewrites the + // ones that are symlinks, so it preserves the caller's casing. Only the native variant + // reports the case as stored on disk. + real = fs.realpathSync.native(p); + } catch { + return p; + } + + return isSamePath(real, p) ? path.normalize(real) : p; +} + +// Separator style and a trailing slash are not differences worth rejecting a correction over. +const forCompare = (p: string): string => p.replace(/\\/g, '/').replace(/\/+$/, '').toLowerCase(); + +function isSamePath(a: string, b: string): boolean { + return forCompare(a) === forCompare(b); +} From 326d90d756ac4c191053eb8692b6c5a0ea5a590b Mon Sep 17 00:00:00 2001 From: Aukevanoost Date: Tue, 11 Aug 2026 09:57:22 +0200 Subject: [PATCH 2/4] fix(bundler): anchor exposed entry points on the workspace root Core hands exposes over workspace-root-relative, and esbuild resolves relative entry points through its own Go-side working directory, which need not be the root the TypeScript program -- and with it the compiler plugin's cache keys -- was built from. Joining them onto the workspace root removes that second resolver from the picture. Hardening rather than the fix: re-spelling the root is what makes the cache keys match. Anchoring on a mis-cased root would make the request equally wrong and mask the mismatch instead of removing it, so this is only sound on top of the previous commit. Shared mappings arrive absolute already and are left alone. Refs native-federation/angular-adapter#117 --- src/tools/esbuild/angular-bundler.spec.ts | 20 ++++++++++++++++++++ src/tools/esbuild/angular-bundler.ts | 6 +++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/tools/esbuild/angular-bundler.spec.ts b/src/tools/esbuild/angular-bundler.spec.ts index 6d90931..8db0a78 100644 --- a/src/tools/esbuild/angular-bundler.spec.ts +++ b/src/tools/esbuild/angular-bundler.spec.ts @@ -115,4 +115,24 @@ describe('createAngularEsbuildContext', () => { expect(updateFederationTsConfig).not.toHaveBeenCalled(); }); + + // #117: left relative, esbuild resolves these through its own working directory, which need + // not agree with the root the TypeScript program was built from. + it('anchors workspace-root-relative entry points on the workspace root', async () => { + await createAngularEsbuildContext(makeOptions()); + + expect(lastBuildOptions().entryPoints).toEqual([ + { in: path.join(workspaceRoot, 'apps/example/src/main.ts'), out: 'main' }, + ]); + }); + + // Core hands shared mappings over absolute already. + it('leaves an already-absolute entry point untouched', async () => { + const absolute = path.join(workspaceRoot, 'libs', 'ui', 'src', 'index.ts'); + await createAngularEsbuildContext( + makeOptions({ entryPoints: [{ fileName: absolute, outName: 'ui.js' }] }) + ); + + expect(lastBuildOptions().entryPoints).toEqual([{ in: absolute, out: 'ui' }]); + }); }); diff --git a/src/tools/esbuild/angular-bundler.ts b/src/tools/esbuild/angular-bundler.ts index 759dab4..025eb81 100644 --- a/src/tools/esbuild/angular-bundler.ts +++ b/src/tools/esbuild/angular-bundler.ts @@ -147,7 +147,11 @@ export async function createAngularEsbuildContext(options: NormalizedContextOpti const config: esbuild.BuildOptions = { entryPoints: entryPoints.map(ep => ({ - in: ep.fileName, + // Anchored on workspaceRoot rather than left relative (core hands exposes over + // workspace-root-relative): esbuild resolves relative entry points through its own + // working directory, which need not be the root the TypeScript program — and with it + // the compiler plugin's cache keys — was built from. + in: path.isAbsolute(ep.fileName) ? ep.fileName : path.join(workspaceRoot, ep.fileName), out: path.parse(ep.outName).name, })), outdir, From 4b8fed04d262b1426c09987c780d9d28a7576493 Mon Sep 17 00:00:00 2001 From: Aukevanoost Date: Sat, 29 Aug 2026 10:06:52 +0200 Subject: [PATCH 3/4] refactor(utils): name the workspace-root correction after core's Core landed the same rule as `toDiskCase` in `utils/disk-case.ts`; this side called it `toCanonicalCase` in `utils/canonical-workspace-root.ts`. Same guard, same `realpathSync.native` reasoning, two names to reconcile whenever the two implementations are read against each other. Also adopts core's `real === p` early return, so an already-correct root is handed back untouched rather than through `path.normalize`. Behaviour is unchanged -- every consumer joins onto the root -- but the two functions now read line for line. Refs native-federation/angular-adapter#117 --- src/builders/build/builder.ts | 4 +-- src/builders/remote/builder.ts | 6 ++--- ...rkspace-root.spec.ts => disk-case.spec.ts} | 26 +++++++++---------- ...nonical-workspace-root.ts => disk-case.ts} | 21 +++++++++------ 4 files changed, 31 insertions(+), 26 deletions(-) rename src/utils/{canonical-workspace-root.spec.ts => disk-case.spec.ts} (72%) rename src/utils/{canonical-workspace-root.ts => disk-case.ts} (72%) diff --git a/src/builders/build/builder.ts b/src/builders/build/builder.ts index 33d434f..729e8d6 100644 --- a/src/builders/build/builder.ts +++ b/src/builders/build/builder.ts @@ -48,7 +48,7 @@ import { } from "@softarc/native-federation/internal"; import { type Plugin, type PluginBuild } from "esbuild"; import { devHostInstancesPlugin } from "../../plugin/dev-host-instances-plugin.js"; -import { withCanonicalWorkspaceRoot } from "./../../utils/canonical-workspace-root.js"; +import { withDiskCaseWorkspaceRoot } from "./../../utils/disk-case.js"; import { checkForInvalidImports } from "./../../utils/check-for-invalid-imports.js"; import { federationSourceFiles } from "./../../utils/federation-source-files.js"; import { watchpackWatch } from "./../../utils/watchpack-watch.js"; @@ -133,7 +133,7 @@ export async function* runBuilder( ): AsyncIterable { // One root for the whole invocation, ours and Angular's alike — the two halves compare // each other's paths as plain strings (watch sets, cache keys). - const context = withCanonicalWorkspaceRoot(builderContext); + const context = withDiskCaseWorkspaceRoot(builderContext); let target = targetFromTargetString(nfBuilderOptions.target); diff --git a/src/builders/remote/builder.ts b/src/builders/remote/builder.ts index e2862d4..cd1eafb 100644 --- a/src/builders/remote/builder.ts +++ b/src/builders/remote/builder.ts @@ -29,7 +29,7 @@ import { } from '@softarc/native-federation/internal'; import { createAngularBuildAdapter } from '../../tools/esbuild/angular-esbuild-adapter.js'; -import { withCanonicalWorkspaceRoot } from '../../utils/canonical-workspace-root.js'; +import { withDiskCaseWorkspaceRoot } from '../../utils/disk-case.js'; import { checkForInvalidImports } from '../../utils/check-for-invalid-imports.js'; import { federationSourceFiles } from '../../utils/federation-source-files.js'; @@ -55,8 +55,8 @@ export async function* runRemoteBuilder( nfBuilderOptions: NfRemoteBuilderSchema & NfRemoteInternalOptions, builderContext: BuilderContext ): AsyncIterable { - // One root for the whole invocation — see withCanonicalWorkspaceRoot. - const context = withCanonicalWorkspaceRoot(builderContext); + // One root for the whole invocation — see withDiskCaseWorkspaceRoot. + const context = withDiskCaseWorkspaceRoot(builderContext); const federationTsConfig = nfBuilderOptions.tsConfig; const outputBase = nfBuilderOptions.outputPath ?? `dist/${context.target!.project}`; diff --git a/src/utils/canonical-workspace-root.spec.ts b/src/utils/disk-case.spec.ts similarity index 72% rename from src/utils/canonical-workspace-root.spec.ts rename to src/utils/disk-case.spec.ts index 41d4261..6360c08 100644 --- a/src/utils/canonical-workspace-root.spec.ts +++ b/src/utils/disk-case.spec.ts @@ -3,7 +3,7 @@ import * as path from 'path'; import type { BuilderContext } from '@angular-devkit/architect'; -import { toCanonicalCase, withCanonicalWorkspaceRoot } from './canonical-workspace-root.js'; +import { toDiskCase, withDiskCaseWorkspaceRoot } from './disk-case.js'; vi.mock('fs'); @@ -18,24 +18,24 @@ beforeEach(() => { vi.clearAllMocks(); }); -describe('toCanonicalCase', () => { +describe('toDiskCase', () => { // The reported case: Nx inherits `c:\…` from the shell while the filesystem stores `C:\…`. it('adopts the on-disk spelling when only the case differs', () => { mockNativeRealpath(() => 'C:\\ws\\project'); - expect(toCanonicalCase('c:\\ws\\project')).toBe(path.normalize('C:\\ws\\project')); + expect(toDiskCase('c:\\ws\\project')).toBe(path.normalize('C:\\ws\\project')); }); it('accepts a correction that also differs in separator style', () => { mockNativeRealpath(() => 'C:/ws/project'); - expect(toCanonicalCase('c:\\ws\\project')).toBe(path.normalize('C:/ws/project')); + expect(toDiskCase('c:\\ws\\project')).toBe(path.normalize('C:/ws/project')); }); it('ignores a trailing slash when deciding whether the paths are the same', () => { mockNativeRealpath(() => 'C:/ws/project'); - expect(toCanonicalCase('c:/ws/project/')).toBe(path.normalize('C:/ws/project')); + expect(toDiskCase('c:/ws/project/')).toBe(path.normalize('C:/ws/project')); }); // A symlinked workspace root must stay on the path it was handed: npm-linked and pnpm @@ -43,7 +43,7 @@ describe('toCanonicalCase', () => { it('keeps the input when realpath resolves to a different directory', () => { mockNativeRealpath(() => '/real/checkout'); - expect(toCanonicalCase('/links/project')).toBe('/links/project'); + expect(toDiskCase('/links/project')).toBe('/links/project'); }); it('keeps the input when realpath throws', () => { @@ -51,17 +51,17 @@ describe('toCanonicalCase', () => { throw new Error('ENOENT'); }); - expect(toCanonicalCase('/gone')).toBe('/gone'); + expect(toDiskCase('/gone')).toBe('/gone'); }); it('is a no-op when the spelling already matches', () => { mockNativeRealpath(p => p); - expect(toCanonicalCase('/ws/project')).toBe('/ws/project'); + expect(toDiskCase('/ws/project')).toBe('/ws/project'); }); }); -describe('withCanonicalWorkspaceRoot', () => { +describe('withDiskCaseWorkspaceRoot', () => { function contextWith(workspaceRoot: string) { return { workspaceRoot, @@ -71,18 +71,18 @@ describe('withCanonicalWorkspaceRoot', () => { } as unknown as BuilderContext; } - it('returns a context carrying the canonical root', () => { + it('returns a context carrying the on-disk spelling of the root', () => { mockNativeRealpath(() => 'C:\\ws'); const context = contextWith('c:\\ws'); - expect(withCanonicalWorkspaceRoot(context).workspaceRoot).toBe(path.normalize('C:\\ws')); + expect(withDiskCaseWorkspaceRoot(context).workspaceRoot).toBe(path.normalize('C:\\ws')); }); it('keeps the rest of the context reachable', async () => { mockNativeRealpath(() => 'C:\\ws'); const context = contextWith('c:\\ws'); - const derived = withCanonicalWorkspaceRoot(context); + const derived = withDiskCaseWorkspaceRoot(context); expect(derived.target).toBe(context.target); expect(derived.logger).toBe(context.logger); @@ -93,6 +93,6 @@ describe('withCanonicalWorkspaceRoot', () => { mockNativeRealpath(p => p); const context = contextWith('/ws'); - expect(withCanonicalWorkspaceRoot(context)).toBe(context); + expect(withDiskCaseWorkspaceRoot(context)).toBe(context); }); }); diff --git a/src/utils/canonical-workspace-root.ts b/src/utils/disk-case.ts similarity index 72% rename from src/utils/canonical-workspace-root.ts rename to src/utils/disk-case.ts index 807e802..7d6807f 100644 --- a/src/utils/canonical-workspace-root.ts +++ b/src/utils/disk-case.ts @@ -11,8 +11,8 @@ import type { BuilderContext } from '@angular-devkit/architect'; * whose keys follow the TypeScript program (and thus the workspace root) while its lookups * follow esbuild. See issue #117. */ -export function withCanonicalWorkspaceRoot(context: BuilderContext): BuilderContext { - const workspaceRoot = toCanonicalCase(context.workspaceRoot); +export function withDiskCaseWorkspaceRoot(context: BuilderContext): BuilderContext { + const workspaceRoot = toDiskCase(context.workspaceRoot); if (workspaceRoot === context.workspaceRoot) { return context; @@ -28,9 +28,10 @@ export function withCanonicalWorkspaceRoot(context: BuilderContext): BuilderCont /** * The on-disk spelling of `p`, but only when it differs from `p` by case alone. `realpath` also * resolves symlinks, and adopting that result would move npm-linked and pnpm workspaces off the - * path they were handed. + * path they were handed. Mirrors core's `toDiskCase`, which reads disk through an io port where + * this reaches `fs` directly. */ -export function toCanonicalCase(p: string): string { +export function toDiskCase(p: string): string { let real: string; try { @@ -42,12 +43,16 @@ export function toCanonicalCase(p: string): string { return p; } - return isSamePath(real, p) ? path.normalize(real) : p; + if (real === p || !differsOnlyByCase(real, p)) { + return p; + } + + return path.normalize(real); } // Separator style and a trailing slash are not differences worth rejecting a correction over. -const forCompare = (p: string): string => p.replace(/\\/g, '/').replace(/\/+$/, '').toLowerCase(); +const strip = (p: string): string => p.replace(/\\/g, '/').replace(/\/+$/, '').toLowerCase(); -function isSamePath(a: string, b: string): boolean { - return forCompare(a) === forCompare(b); +function differsOnlyByCase(a: string, b: string): boolean { + return strip(a) === strip(b); } From 89bd3e5d4556a707fff7bca1e4a10ed2abafe4d8 Mon Sep 17 00:00:00 2001 From: Aukevanoost Date: Sat, 29 Aug 2026 10:06:56 +0200 Subject: [PATCH 4/4] chore(deps): follow @softarc/native-federation onto 4.5.0 The core half of #117 shipped in the 4.5.0 stable release, so the prerelease spelling now names a version no install resolves to: semver ranks 4.5.0 above 4.5.0-next.1, and `~4.5.0-next.1` already admits it. Refs native-federation/angular-adapter#117 --- package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index cb00e2f..638f250 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "@angular-devkit/core": "~22.1.0", "@angular-devkit/schematics": "~22.1.0", "@chialab/esbuild-plugin-commonjs": "^0.19.0", - "@softarc/native-federation": "~4.5.0-next.1", + "@softarc/native-federation": "~4.5.0", "@softarc/native-federation-orchestrator": "^4.5.2", "es-module-shims": "^2.8.0", "esbuild": "^0.28.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4f55cc3..e381765 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -24,8 +24,8 @@ importers: specifier: ^0.19.0 version: 0.19.1 '@softarc/native-federation': - specifier: ~4.5.0-next.1 - version: 4.5.0-next.1(typescript@6.0.3) + specifier: ~4.5.0 + version: 4.5.0(typescript@6.0.3) '@softarc/native-federation-orchestrator': specifier: ^4.5.2 version: 4.6.0 @@ -1837,8 +1837,8 @@ packages: resolution: {integrity: sha512-8529SINGc3zBdKZcyUsP9vGj4EFjUOljy+43qfwzYSgC3FwkHcAjddf/p86t8kI9CmCp0JGeLkM1IjJ7xahVXQ==, tarball: https://registry.npmjs.org/@softarc/native-federation-orchestrator/-/native-federation-orchestrator-4.6.0.tgz} engines: {node: '>=24.16.0'} - '@softarc/native-federation@4.5.0-next.1': - resolution: {integrity: sha512-HD8BO7b2d/9UIT4nSkq6D99mqB7DKQ35ONAkBpyx41/ojM98bvwzfJxL2UNtFvKqzlYaAeJZ/h0a5EagZ1IuZQ==, tarball: https://registry.npmjs.org/@softarc/native-federation/-/native-federation-4.5.0-next.1.tgz} + '@softarc/native-federation@4.5.0': + resolution: {integrity: sha512-FixGtwyRT7o8nANxecr0UDTZWTzhzLqH+cE3clntzhx/t4BNkNQwqaOZlcyjHNTI6l6nH4zIY4Ct7jaHCjPO3A==, tarball: https://registry.npmjs.org/@softarc/native-federation/-/native-federation-4.5.0.tgz} '@softarc/sheriff-core@0.19.6': resolution: {integrity: sha512-KACxHG9sS7kNWgnnBODzdr14kMLMrJVlQKc+tViUP03p2fRwNhESOA49bz51Yn7dro1mbtMmmFjICLmZSJDZZA==, tarball: https://registry.npmjs.org/@softarc/sheriff-core/-/sheriff-core-0.19.6.tgz} @@ -4675,7 +4675,7 @@ snapshots: dependencies: semver: 7.8.5 - '@softarc/native-federation@4.5.0-next.1(typescript@6.0.3)': + '@softarc/native-federation@4.5.0(typescript@6.0.3)': dependencies: '@softarc/sheriff-core': 0.19.6(typescript@6.0.3) chalk: 6.0.0