@edynamix/mf-isolation 0.0.27 → 0.0.28

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.
package/README.md CHANGED
@@ -148,6 +148,8 @@ export class AppModule {}
148
148
 
149
149
  The base is the module's `APP_BASE_HREF` (or the document's `<base>`); a root base (`/`) is left untouched. A host that redirects case variants of a module's path to lowercase can stop doing so once the module installs this strategy.
150
150
 
151
+ The strategy also passes the router only the address changes within the module's base and aliases. In a host, Back or Forward to another module changes the address before the module is unmounted; the module's router would otherwise take that address for one of its own and either log `NG04002` (no match) or write it back under the module's base (a catch-all or redirect), leaving the page in the wrong module.
152
+
151
153
  ## Angular CDK overlays
152
154
 
153
155
  The Angular integration targets Angular/CDK 19.x. In a hosted application, install the complete provider array so global and connected overlays share the module boundary's viewport and coordinate system:
@@ -1,4 +1,4 @@
1
- import { PathLocationStrategy, PlatformLocation } from '@angular/common';
1
+ import { type LocationChangeListener, PathLocationStrategy, PlatformLocation } from '@angular/common';
2
2
  import { type StaticProvider } from '@angular/core';
3
3
  export declare class CaseInsensitiveBasePathLocationStrategy extends PathLocationStrategy {
4
4
  private readonly addressLocation;
@@ -7,6 +7,7 @@ export declare class CaseInsensitiveBasePathLocationStrategy extends PathLocatio
7
7
  constructor(platformLocation: PlatformLocation, href?: string, aliases?: readonly string[]);
8
8
  path(includeHash?: boolean): string;
9
9
  prepareExternalUrl(internal: string): string;
10
+ onPopState(fn: LocationChangeListener): void;
10
11
  }
11
12
  export declare const provideCaseInsensitiveBasePath: (aliases?: readonly string[]) => StaticProvider[];
12
13
  //# sourceMappingURL=angular-location.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"angular-location.d.ts","sourceRoot":"","sources":["../src/angular-location.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmC,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAC1G,OAAO,EAAoB,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAOtE,qBAAa,uCAAwC,SAAQ,oBAAoB;IAC/E,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAmB;IACnD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoB;gBAE9B,gBAAgB,EAAE,gBAAgB,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,GAAE,SAAS,MAAM,EAAO;IAOrF,IAAI,CAAC,WAAW,UAAQ,GAAG,MAAM;IAIjC,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;CAItD;AAGD,eAAO,MAAM,8BAA8B,GAAI,UAAS,SAAS,MAAM,EAAO,KAAG,cAAc,EAO9F,CAAC","sourcesContent":["import { APP_BASE_HREF, LocationStrategy, PathLocationStrategy, PlatformLocation } from '@angular/common';\nimport { Inject, Optional, type StaticProvider } from '@angular/core';\n\n// IIS serves a module at any letter case of its path, and old bookmarks keep the old case (/AutoPoint/...), but Angular's\n// Location strips the base only on an exact, case-sensitive match, so such an address showed the module's 404 page.\n// This strategy reads the address with the base in its configured case and writes addresses with the base in the case\n// the address bar shows, so /AutoPoint/... and /autopoint/... both work and stay as typed, without a redirect. Aliases\n// are earlier names of the module's path (motcleanse for autocleanse, for example) that open it the same way.\nexport class CaseInsensitiveBasePathLocationStrategy extends PathLocationStrategy {\n private readonly addressLocation: PlatformLocation;\n private readonly base: string;\n private readonly bases: readonly string[];\n\n constructor(platformLocation: PlatformLocation, href?: string, aliases: readonly string[] = []) {\n super(platformLocation, href);\n this.addressLocation = platformLocation;\n this.base = withoutTrailingSlash(this.getBaseHref());\n this.bases = this.base ? [this.base, ...aliases.map(aliasBase)] : [];\n }\n\n override path(includeHash = false): string {\n return replaceBase(super.path(includeHash), this.bases, this.base);\n }\n\n override prepareExternalUrl(internal: string): string {\n const addressBase = matchedBasePrefix(this.addressLocation.pathname, this.bases) ?? this.base;\n return replaceBase(super.prepareExternalUrl(internal), this.bases, addressBase);\n }\n}\n\n// The module's LocationStrategy: its base path (APP_BASE_HREF, or the document's <base>) in any letter case, plus aliases.\nexport const provideCaseInsensitiveBasePath = (aliases: readonly string[] = []): StaticProvider[] => [\n {\n provide: LocationStrategy,\n useFactory: (platformLocation: PlatformLocation, href: string | null) =>\n new CaseInsensitiveBasePathLocationStrategy(platformLocation, href ?? undefined, aliases),\n deps: [PlatformLocation, [new Optional(), new Inject(APP_BASE_HREF)]],\n },\n];\n\n// The start of path that is one of bases in any letter case, followed by the end of the path or a path, query, fragment\n// or matrix separator; undefined when path starts with none of them.\nconst matchedBasePrefix = (path: string, bases: readonly string[]): string | undefined => {\n for (const base of bases) {\n const prefix = path.slice(0, base.length);\n const next = path.charAt(base.length);\n if (base && prefix.toLowerCase() === base.toLowerCase() && (next === '' || '/?#;'.includes(next))) {\n return prefix;\n }\n }\n\n return undefined;\n};\n\nconst replaceBase = (path: string, bases: readonly string[], base: string): string => {\n const prefix = matchedBasePrefix(path, bases);\n return prefix === undefined ? path : base + path.slice(prefix.length);\n};\n\nconst aliasBase = (alias: string): string => `/${alias.replace(/^\\/+|\\/+$/g, '')}`;\n\nconst withoutTrailingSlash = (href: string): string => href.replace(/\\/+$/, '');\n"]}
1
+ {"version":3,"file":"angular-location.d.ts","sourceRoot":"","sources":["../src/angular-location.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,sBAAsB,EAAoB,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACvI,OAAO,EAAoB,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAOtE,qBAAa,uCAAwC,SAAQ,oBAAoB;IAC/E,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAmB;IACnD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoB;gBAE9B,gBAAgB,EAAE,gBAAgB,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,GAAE,SAAS,MAAM,EAAO;IAOrF,IAAI,CAAC,WAAW,UAAQ,GAAG,MAAM;IAIjC,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAS5C,UAAU,CAAC,EAAE,EAAE,sBAAsB,GAAG,IAAI;CAOtD;AAGD,eAAO,MAAM,8BAA8B,GAAI,UAAS,SAAS,MAAM,EAAO,KAAG,cAAc,EAO9F,CAAC","sourcesContent":["import { APP_BASE_HREF, type LocationChangeListener, LocationStrategy, PathLocationStrategy, PlatformLocation } from '@angular/common';\nimport { Inject, Optional, type StaticProvider } from '@angular/core';\n\n// IIS serves a module at any letter case of its path, and old bookmarks keep the old case (/AutoPoint/...), but Angular's\n// Location strips the base only on an exact, case-sensitive match, so such an address showed the module's 404 page.\n// This strategy reads the address with the base in its configured case and writes addresses with the base in the case\n// the address bar shows, so /AutoPoint/... and /autopoint/... both work and stay as typed, without a redirect. Aliases\n// are earlier names of the module's path (motcleanse for autocleanse, for example) that open it the same way.\nexport class CaseInsensitiveBasePathLocationStrategy extends PathLocationStrategy {\n private readonly addressLocation: PlatformLocation;\n private readonly base: string;\n private readonly bases: readonly string[];\n\n constructor(platformLocation: PlatformLocation, href?: string, aliases: readonly string[] = []) {\n super(platformLocation, href);\n this.addressLocation = platformLocation;\n this.base = withoutTrailingSlash(this.getBaseHref());\n this.bases = this.base ? [this.base, ...aliases.map(aliasBase)] : [];\n }\n\n override path(includeHash = false): string {\n return replaceBase(super.path(includeHash), this.bases, this.base);\n }\n\n override prepareExternalUrl(internal: string): string {\n const addressBase = matchedBasePrefix(this.addressLocation.pathname, this.bases) ?? this.base;\n return replaceBase(super.prepareExternalUrl(internal), this.bases, addressBase);\n }\n\n // In the host, Back or Forward to another module changes the address before this module is unmounted. Its router\n // would take that address for one of its own: no match logs NG04002, and a catch-all or redirect writes it back\n // under this module's base, so the page leaves the module it was going to. Changes to an address outside the base\n // and its aliases are not passed on; without a base (the development root), every change is.\n override onPopState(fn: LocationChangeListener): void {\n super.onPopState((event) => {\n if (this.bases.length === 0 || matchedBasePrefix(this.addressLocation.pathname, this.bases) !== undefined) {\n fn(event);\n }\n });\n }\n}\n\n// The module's LocationStrategy: its base path (APP_BASE_HREF, or the document's <base>) in any letter case, plus aliases.\nexport const provideCaseInsensitiveBasePath = (aliases: readonly string[] = []): StaticProvider[] => [\n {\n provide: LocationStrategy,\n useFactory: (platformLocation: PlatformLocation, href: string | null) =>\n new CaseInsensitiveBasePathLocationStrategy(platformLocation, href ?? undefined, aliases),\n deps: [PlatformLocation, [new Optional(), new Inject(APP_BASE_HREF)]],\n },\n];\n\n// The start of path that is one of bases in any letter case, followed by the end of the path or a path, query, fragment\n// or matrix separator; undefined when path starts with none of them.\nconst matchedBasePrefix = (path: string, bases: readonly string[]): string | undefined => {\n for (const base of bases) {\n const prefix = path.slice(0, base.length);\n const next = path.charAt(base.length);\n if (base && prefix.toLowerCase() === base.toLowerCase() && (next === '' || '/?#;'.includes(next))) {\n return prefix;\n }\n }\n\n return undefined;\n};\n\nconst replaceBase = (path: string, bases: readonly string[], base: string): string => {\n const prefix = matchedBasePrefix(path, bases);\n return prefix === undefined ? path : base + path.slice(prefix.length);\n};\n\nconst aliasBase = (alias: string): string => `/${alias.replace(/^\\/+|\\/+$/g, '')}`;\n\nconst withoutTrailingSlash = (href: string): string => href.replace(/\\/+$/, '');\n"]}
@@ -22,6 +22,17 @@ export class CaseInsensitiveBasePathLocationStrategy extends PathLocationStrateg
22
22
  const addressBase = matchedBasePrefix(this.addressLocation.pathname, this.bases) ?? this.base;
23
23
  return replaceBase(super.prepareExternalUrl(internal), this.bases, addressBase);
24
24
  }
25
+ // In the host, Back or Forward to another module changes the address before this module is unmounted. Its router
26
+ // would take that address for one of its own: no match logs NG04002, and a catch-all or redirect writes it back
27
+ // under this module's base, so the page leaves the module it was going to. Changes to an address outside the base
28
+ // and its aliases are not passed on; without a base (the development root), every change is.
29
+ onPopState(fn) {
30
+ super.onPopState((event) => {
31
+ if (this.bases.length === 0 || matchedBasePrefix(this.addressLocation.pathname, this.bases) !== undefined) {
32
+ fn(event);
33
+ }
34
+ });
35
+ }
25
36
  }
26
37
  // The module's LocationStrategy: its base path (APP_BASE_HREF, or the document's <base>) in any letter case, plus aliases.
27
38
  export const provideCaseInsensitiveBasePath = (aliases = []) => [
@@ -1 +1 @@
1
- {"version":3,"file":"angular-location.js","sourceRoot":"","sources":["../src/angular-location.ts"],"names":[],"mappings":"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","sourcesContent":["import { APP_BASE_HREF, LocationStrategy, PathLocationStrategy, PlatformLocation } from '@angular/common';\nimport { Inject, Optional, type StaticProvider } from '@angular/core';\n\n// IIS serves a module at any letter case of its path, and old bookmarks keep the old case (/AutoPoint/...), but Angular's\n// Location strips the base only on an exact, case-sensitive match, so such an address showed the module's 404 page.\n// This strategy reads the address with the base in its configured case and writes addresses with the base in the case\n// the address bar shows, so /AutoPoint/... and /autopoint/... both work and stay as typed, without a redirect. Aliases\n// are earlier names of the module's path (motcleanse for autocleanse, for example) that open it the same way.\nexport class CaseInsensitiveBasePathLocationStrategy extends PathLocationStrategy {\n private readonly addressLocation: PlatformLocation;\n private readonly base: string;\n private readonly bases: readonly string[];\n\n constructor(platformLocation: PlatformLocation, href?: string, aliases: readonly string[] = []) {\n super(platformLocation, href);\n this.addressLocation = platformLocation;\n this.base = withoutTrailingSlash(this.getBaseHref());\n this.bases = this.base ? [this.base, ...aliases.map(aliasBase)] : [];\n }\n\n override path(includeHash = false): string {\n return replaceBase(super.path(includeHash), this.bases, this.base);\n }\n\n override prepareExternalUrl(internal: string): string {\n const addressBase = matchedBasePrefix(this.addressLocation.pathname, this.bases) ?? this.base;\n return replaceBase(super.prepareExternalUrl(internal), this.bases, addressBase);\n }\n}\n\n// The module's LocationStrategy: its base path (APP_BASE_HREF, or the document's <base>) in any letter case, plus aliases.\nexport const provideCaseInsensitiveBasePath = (aliases: readonly string[] = []): StaticProvider[] => [\n {\n provide: LocationStrategy,\n useFactory: (platformLocation: PlatformLocation, href: string | null) =>\n new CaseInsensitiveBasePathLocationStrategy(platformLocation, href ?? undefined, aliases),\n deps: [PlatformLocation, [new Optional(), new Inject(APP_BASE_HREF)]],\n },\n];\n\n// The start of path that is one of bases in any letter case, followed by the end of the path or a path, query, fragment\n// or matrix separator; undefined when path starts with none of them.\nconst matchedBasePrefix = (path: string, bases: readonly string[]): string | undefined => {\n for (const base of bases) {\n const prefix = path.slice(0, base.length);\n const next = path.charAt(base.length);\n if (base && prefix.toLowerCase() === base.toLowerCase() && (next === '' || '/?#;'.includes(next))) {\n return prefix;\n }\n }\n\n return undefined;\n};\n\nconst replaceBase = (path: string, bases: readonly string[], base: string): string => {\n const prefix = matchedBasePrefix(path, bases);\n return prefix === undefined ? path : base + path.slice(prefix.length);\n};\n\nconst aliasBase = (alias: string): string => `/${alias.replace(/^\\/+|\\/+$/g, '')}`;\n\nconst withoutTrailingSlash = (href: string): string => href.replace(/\\/+$/, '');\n"]}
1
+ {"version":3,"file":"angular-location.js","sourceRoot":"","sources":["../src/angular-location.ts"],"names":[],"mappings":"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","sourcesContent":["import { APP_BASE_HREF, type LocationChangeListener, LocationStrategy, PathLocationStrategy, PlatformLocation } from '@angular/common';\nimport { Inject, Optional, type StaticProvider } from '@angular/core';\n\n// IIS serves a module at any letter case of its path, and old bookmarks keep the old case (/AutoPoint/...), but Angular's\n// Location strips the base only on an exact, case-sensitive match, so such an address showed the module's 404 page.\n// This strategy reads the address with the base in its configured case and writes addresses with the base in the case\n// the address bar shows, so /AutoPoint/... and /autopoint/... both work and stay as typed, without a redirect. Aliases\n// are earlier names of the module's path (motcleanse for autocleanse, for example) that open it the same way.\nexport class CaseInsensitiveBasePathLocationStrategy extends PathLocationStrategy {\n private readonly addressLocation: PlatformLocation;\n private readonly base: string;\n private readonly bases: readonly string[];\n\n constructor(platformLocation: PlatformLocation, href?: string, aliases: readonly string[] = []) {\n super(platformLocation, href);\n this.addressLocation = platformLocation;\n this.base = withoutTrailingSlash(this.getBaseHref());\n this.bases = this.base ? [this.base, ...aliases.map(aliasBase)] : [];\n }\n\n override path(includeHash = false): string {\n return replaceBase(super.path(includeHash), this.bases, this.base);\n }\n\n override prepareExternalUrl(internal: string): string {\n const addressBase = matchedBasePrefix(this.addressLocation.pathname, this.bases) ?? this.base;\n return replaceBase(super.prepareExternalUrl(internal), this.bases, addressBase);\n }\n\n // In the host, Back or Forward to another module changes the address before this module is unmounted. Its router\n // would take that address for one of its own: no match logs NG04002, and a catch-all or redirect writes it back\n // under this module's base, so the page leaves the module it was going to. Changes to an address outside the base\n // and its aliases are not passed on; without a base (the development root), every change is.\n override onPopState(fn: LocationChangeListener): void {\n super.onPopState((event) => {\n if (this.bases.length === 0 || matchedBasePrefix(this.addressLocation.pathname, this.bases) !== undefined) {\n fn(event);\n }\n });\n }\n}\n\n// The module's LocationStrategy: its base path (APP_BASE_HREF, or the document's <base>) in any letter case, plus aliases.\nexport const provideCaseInsensitiveBasePath = (aliases: readonly string[] = []): StaticProvider[] => [\n {\n provide: LocationStrategy,\n useFactory: (platformLocation: PlatformLocation, href: string | null) =>\n new CaseInsensitiveBasePathLocationStrategy(platformLocation, href ?? undefined, aliases),\n deps: [PlatformLocation, [new Optional(), new Inject(APP_BASE_HREF)]],\n },\n];\n\n// The start of path that is one of bases in any letter case, followed by the end of the path or a path, query, fragment\n// or matrix separator; undefined when path starts with none of them.\nconst matchedBasePrefix = (path: string, bases: readonly string[]): string | undefined => {\n for (const base of bases) {\n const prefix = path.slice(0, base.length);\n const next = path.charAt(base.length);\n if (base && prefix.toLowerCase() === base.toLowerCase() && (next === '' || '/?#;'.includes(next))) {\n return prefix;\n }\n }\n\n return undefined;\n};\n\nconst replaceBase = (path: string, bases: readonly string[], base: string): string => {\n const prefix = matchedBasePrefix(path, bases);\n return prefix === undefined ? path : base + path.slice(prefix.length);\n};\n\nconst aliasBase = (alias: string): string => `/${alias.replace(/^\\/+|\\/+$/g, '')}`;\n\nconst withoutTrailingSlash = (href: string): string => href.replace(/\\/+$/, '');\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edynamix/mf-isolation",
3
- "version": "0.0.27",
3
+ "version": "0.0.28",
4
4
  "description": "CSS and overlay isolation helpers for eDynamix microfrontends.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",