@appshell/loader 0.2.1 → 0.3.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.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,17 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [0.3.0](https://github.com/navaris/appshell/compare/@appshell/loader@0.2.1...@appshell/loader@0.3.0) (2024-01-25)
7
+
8
+
9
+ ### Features
10
+
11
+ * AppshellComponent impl ([2b82621](https://github.com/navaris/appshell/commit/2b82621c13302f790a8e1c457f9a82f39903fc1f))
12
+
13
+
14
+
15
+
16
+
6
17
  ## [0.2.1](https://github.com/navaris/appshell/compare/@appshell/loader@0.2.0...@appshell/loader@0.2.1) (2023-08-29)
7
18
 
8
19
 
package/README.md CHANGED
@@ -11,7 +11,7 @@
11
11
 
12
12
  # @appshell/loader
13
13
 
14
- Dynamically load federated components for micro-frontends built with Appshell and Webpack Module federation.
14
+ Dynamically load Appshell components for micro-frontends built with Appshell and Webpack Module federation.
15
15
 
16
16
  Working examples can be found [here](https://github.com/navaris/appshell/tree/main/examples).
17
17
 
@@ -35,7 +35,7 @@ or
35
35
  pnpm add -D @appshell/loader
36
36
  ```
37
37
 
38
- The default export from this package is the loader function. It is given the global appshell configuration, and returns an async function that can be called to dynamically load federated components.
38
+ The default export from this package is the loader function. It is given the global appshell configuration, and returns an async function that can be called to dynamically load Appshell components.
39
39
 
40
40
  ```ts
41
41
  import componentLoader from '@appshell/loader';
@@ -1,6 +1,6 @@
1
1
  /** @jest-environment jsdom */
2
2
  /* eslint-disable no-underscore-dangle */
3
- import loadFederatedComponent from '../src/loadFederatedComponent';
3
+ import loadAppshellComponent from '../src/loadAppshellComponent';
4
4
  import { ModuleContainer, ShareScope } from '../src/types';
5
5
 
6
6
  type ComponentType = () => string;
@@ -49,7 +49,7 @@ const containers: Record<string, Record<string, ModuleContainer<ComponentType>>>
49
49
  },
50
50
  };
51
51
 
52
- describe('loadFederatedComponent', () => {
52
+ describe('loadAppshellComponent', () => {
53
53
  beforeEach(() => {
54
54
  window.__webpack_init_sharing__ = jest.fn(async (shareScope: string) => {
55
55
  // eslint-disable-next-line @typescript-eslint/dot-notation
@@ -70,12 +70,12 @@ describe('loadFederatedComponent', () => {
70
70
  window.__webpack_share_scopes__ = {};
71
71
  });
72
72
 
73
- it('should load the federated component from the default scope', async () => {
73
+ it('should load the Appshell component from the default scope', async () => {
74
74
  const scope = 'TestModule';
75
75
  const module = './TestComponent';
76
76
  const shareScope = undefined;
77
77
 
78
- const Component = await loadFederatedComponent<ComponentType>(scope, module, shareScope);
78
+ const Component = await loadAppshellComponent<ComponentType>(scope, module, shareScope);
79
79
 
80
80
  expect(Component).toBe(TestComponent);
81
81
  });
@@ -85,7 +85,7 @@ describe('loadFederatedComponent', () => {
85
85
  const module = './TestComponent';
86
86
  const shareScope = 'does_not_exist';
87
87
 
88
- await expect(loadFederatedComponent<ComponentType>(scope, module, shareScope)).rejects.toThrow(
88
+ await expect(loadAppshellComponent<ComponentType>(scope, module, shareScope)).rejects.toThrow(
89
89
  /Failed to find module container/i,
90
90
  );
91
91
  });
@@ -95,7 +95,7 @@ describe('loadFederatedComponent', () => {
95
95
  const module = './TestComponent';
96
96
  const shareScope = 'no_factory';
97
97
 
98
- await expect(loadFederatedComponent<ComponentType>(scope, module, shareScope)).rejects.toThrow(
98
+ await expect(loadAppshellComponent<ComponentType>(scope, module, shareScope)).rejects.toThrow(
99
99
  /Invalid factory produced/i,
100
100
  );
101
101
  });
@@ -3,13 +3,13 @@ import { AppshellManifest } from '@appshell/config';
3
3
  import { AppshellGlobalConfig } from '@appshell/config/src/types';
4
4
  import fetch, { enableFetchMocks } from 'jest-fetch-mock';
5
5
  import * as fetchDynamicScript from '../src/fetchDynamicScript';
6
- import * as loadFederatedComponent from '../src/loadFederatedComponent';
6
+ import * as loadAppshellComponent from '../src/loadAppshellComponent';
7
7
  import remoteLoader from '../src/remoteLoader';
8
8
 
9
9
  enableFetchMocks();
10
10
 
11
11
  jest.mock('../src/fetchDynamicScript');
12
- jest.mock('../src/loadFederatedComponent');
12
+ jest.mock('../src/loadAppshellComponent');
13
13
 
14
14
  describe('remoteLoader', () => {
15
15
  const manifest: AppshellManifest = {
@@ -50,11 +50,11 @@ describe('remoteLoader', () => {
50
50
  );
51
51
  });
52
52
 
53
- it('should return the federated component if it is found in the registry', async () => {
53
+ it('should return the Appshell component if it is found in the registry', async () => {
54
54
  const ExpectedComponent = () => 'test component';
55
55
  jest.spyOn(fetchDynamicScript, 'default').mockReturnValueOnce(Promise.resolve(true));
56
56
  jest
57
- .spyOn(loadFederatedComponent, 'default')
57
+ .spyOn(loadAppshellComponent, 'default')
58
58
  .mockResolvedValue(Promise.resolve(ExpectedComponent));
59
59
 
60
60
  const loadRemote = remoteLoader(config);
@@ -70,7 +70,7 @@ describe('remoteLoader', () => {
70
70
  .spyOn(fetchDynamicScript, 'default')
71
71
  .mockReturnValueOnce(Promise.resolve(true));
72
72
  jest
73
- .spyOn(loadFederatedComponent, 'default')
73
+ .spyOn(loadAppshellComponent, 'default')
74
74
  .mockResolvedValue(Promise.resolve(ExpectedComponent));
75
75
 
76
76
  const loadRemote = remoteLoader(config);
@@ -86,7 +86,7 @@ describe('remoteLoader', () => {
86
86
  const ExpectedComponent = () => 'test component';
87
87
  jest.spyOn(fetchDynamicScript, 'default').mockReturnValueOnce(Promise.resolve(true));
88
88
  jest
89
- .spyOn(loadFederatedComponent, 'default')
89
+ .spyOn(loadAppshellComponent, 'default')
90
90
  .mockResolvedValue(Promise.resolve(ExpectedComponent));
91
91
 
92
92
  const loadRemote = remoteLoader(config);
@@ -99,7 +99,7 @@ describe('remoteLoader', () => {
99
99
 
100
100
  it('should throw if remote key is not found in the registry', async () => {
101
101
  const ExpectedComponent = () => 'test component';
102
- jest.spyOn(loadFederatedComponent, 'default').mockResolvedValue(ExpectedComponent);
102
+ jest.spyOn(loadAppshellComponent, 'default').mockResolvedValue(ExpectedComponent);
103
103
 
104
104
  const loadRemote = remoteLoader(config);
105
105
 
@@ -108,9 +108,9 @@ describe('remoteLoader', () => {
108
108
  );
109
109
  });
110
110
 
111
- it('should throw if load federated component fails', async () => {
111
+ it('should throw if load Appshell component fails', async () => {
112
112
  jest.spyOn(fetchDynamicScript, 'default').mockReturnValueOnce(Promise.resolve(true));
113
- jest.spyOn(loadFederatedComponent, 'default').mockRejectedValue(new Error('failed'));
113
+ jest.spyOn(loadAppshellComponent, 'default').mockRejectedValue(new Error('failed'));
114
114
 
115
115
  const loadRemote = remoteLoader(config);
116
116
 
package/dist/main.js CHANGED
@@ -1 +1 @@
1
- !function(e,o){if("object"==typeof exports&&"object"==typeof module)module.exports=o();else if("function"==typeof define&&define.amd)define([],o);else{var t=o();for(var r in t)("object"==typeof exports?exports:e)[r]=t[r]}}(self,(()=>(()=>{"use strict";var e={d:(o,t)=>{for(var r in t)e.o(t,r)&&!e.o(o,r)&&Object.defineProperty(o,r,{enumerable:!0,get:t[r]})},o:(e,o)=>Object.prototype.hasOwnProperty.call(e,o),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}};(()=>{e.S={};var o={},t={};e.I=(r,n)=>{n||(n=[]);var a=t[r];if(a||(a=t[r]={}),!(n.indexOf(a)>=0)){if(n.push(a),o[r])return o[r];e.o(e.S,r)||(e.S[r]={}),e.S[r];var d=[];return o[r]=d.length?Promise.all(d).then((()=>o[r]=1)):1}}})();var o={};e.r(o),e.d(o,{default:()=>a});const t=new Set,r=new Set,n=new Map,a=o=>async a=>{let d;const i=o.index[a];if(!i)throw new Error(`Remote resource not found in registry. Expected: ${a}`);try{const c=await(async e=>{if(n.has(e))return n.get(e);n.set(e,void 0);const o=await fetch(e);if(o.ok)return o.json();const t=await o.text();throw new Error(`Failed to get manifest from ${e}. ${t}`)})(i);if(c){n.set(i,c);const s=c.remotes[a],l=c.environment[s.scope]||{},f=o.overrides?.environment&&o.overrides?.environment[s.scope]||{};if(window[`__appshell_env__${s.scope}`]={...l,...f},r.has(s.remoteEntryUrl)||await(async e=>{const o=document.createElement("script");return new Promise(((r,n)=>{t.has(e)?r(!1):(t.add(e),o.src=e,o.type="text/javascript",o.async=!0,o.onload=()=>{console.debug(`Remote entry fetched from '${e}'.`),r(!0)},o.onerror=()=>{const o=`Failed to fetch remote entry from '${e}'.`;console.error(o),n(o)},document.head.appendChild(o))})).finally((()=>{document.head.contains(o)&&document.head.removeChild(o)}))})(s.remoteEntryUrl))return r.add(s.remoteEntryUrl),d=await(async(o,t,r="default")=>{console.debug(`loading federated component: { scope: ${o}, module: ${t}, shareScope: ${r} }`),await e.I(r);const n=window[o];if(!n)throw new Error(`Failed to find module container ${o}`);await n.init(e.S[r]);const a=await n.get(t);if(!a)throw new Error(`Invalid factory produced by container for module ${t}.`);const d=a();return console.debug(`federated component loaded: { scope: ${o}, module: ${t}, shareScope: ${r} }`),d.default})(s.scope,s.module,s.shareScope),[d,c]}return[null,null]}catch(e){throw new Error(`Failed to load component '${a}'. ${e?.toString()}`)}};return o})()));
1
+ !function(e,o){if("object"==typeof exports&&"object"==typeof module)module.exports=o();else if("function"==typeof define&&define.amd)define([],o);else{var t=o();for(var r in t)("object"==typeof exports?exports:e)[r]=t[r]}}(self,(()=>(()=>{"use strict";var e={d:(o,t)=>{for(var r in t)e.o(t,r)&&!e.o(o,r)&&Object.defineProperty(o,r,{enumerable:!0,get:t[r]})},o:(e,o)=>Object.prototype.hasOwnProperty.call(e,o),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}};(()=>{e.S={};var o={},t={};e.I=(r,n)=>{n||(n=[]);var a=t[r];if(a||(a=t[r]={}),!(n.indexOf(a)>=0)){if(n.push(a),o[r])return o[r];e.o(e.S,r)||(e.S[r]={}),e.S[r];var i=[];return o[r]=i.length?Promise.all(i).then((()=>o[r]=1)):1}}})();var o={};e.r(o),e.d(o,{default:()=>a});const t=new Set,r=new Set,n=new Map,a=o=>async a=>{let i;const c=o.index[a];if(!c)throw new Error(`Remote resource not found in registry. Expected: ${a}`);try{const d=await(async e=>{if(n.has(e))return n.get(e);n.set(e,void 0);const o=await fetch(e);if(o.ok)return o.json();const t=await o.text();throw new Error(`Failed to get manifest from ${e}. ${t}`)})(c);if(d){n.set(c,d);const s=d.remotes[a],l=d.environment[s.scope]||{},f=o.overrides?.environment&&o.overrides?.environment[s.scope]||{};if(window[`__appshell_env__${s.scope}`]={...l,...f},r.has(s.remoteEntryUrl)||await(async e=>{const o=document.createElement("script");return new Promise(((r,n)=>{t.has(e)?r(!1):(t.add(e),o.src=e,o.type="text/javascript",o.async=!0,o.onload=()=>{console.debug(`Remote entry fetched from '${e}'.`),r(!0)},o.onerror=()=>{const o=`Failed to fetch remote entry from '${e}'.`;console.error(o),n(o)},document.head.appendChild(o))})).finally((()=>{document.head.contains(o)&&document.head.removeChild(o)}))})(s.remoteEntryUrl))return r.add(s.remoteEntryUrl),i=await(async(o,t,r="default")=>{console.debug(`loading Appshell component: { scope: ${o}, module: ${t}, shareScope: ${r} }`),await e.I(r);const n=window[o];if(!n)throw new Error(`Failed to find module container ${o}`);await n.init(e.S[r]);const a=await n.get(t);if(!a)throw new Error(`Invalid factory produced by container for module ${t}.`);const i=a();return console.debug(`Appshell component loaded: { scope: ${o}, module: ${t}, shareScope: ${r} }`),i.default})(s.scope,s.module,s.shareScope),[i,d]}return[null,null]}catch(e){throw new Error(`Failed to load component '${a}'. ${e?.toString()}`)}};return o})()));
@@ -1 +1 @@
1
- {"version":3,"file":"appshell.config.d.ts","sourceRoot":"","sources":["../../../../../../config/src/mappers/appshell.config.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,gBAAgB,EAEhB,gBAAgB,EAChB,SAAS,EACV,MAAM,UAAU,CAAC;AA6DlB,eAAO,MAAM,kBAAkB,wDACnB,gBAAgB,QACpB,SAAS,gCAQhB,CAAC"}
1
+ {"version":3,"file":"appshell.config.d.ts","sourceRoot":"","sources":["../../../../../../config/src/mappers/appshell.config.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,gBAAgB,EAEhB,gBAAgB,EAChB,SAAS,EACV,MAAM,UAAU,CAAC;AAiElB,eAAO,MAAM,kBAAkB,wDACnB,gBAAgB,QACpB,SAAS,gCAQhB,CAAC"}
@@ -1,4 +1,4 @@
1
1
  import { AppshellManifest } from './types';
2
- declare const _default: (manifest: AppshellManifest, registryPathOrUrl: string) => Promise<void>;
2
+ declare const _default: (manifest: AppshellManifest, registryPathOrUrl: string, allowOverrides?: boolean) => Promise<void>;
3
3
  export default _default;
4
4
  //# sourceMappingURL=register.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../../../../config/src/register.ts"],"names":[],"mappings":"AAEA,OAAO,EAAwB,gBAAgB,EAAmB,MAAM,SAAS,CAAC;mCAclD,gBAAgB,qBAAqB,MAAM;AAA3E,wBAuCE"}
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../../../../config/src/register.ts"],"names":[],"mappings":"AAEA,OAAO,EAAwB,gBAAgB,EAAmB,MAAM,SAAS,CAAC;mCAetE,gBAAgB,qBACP,MAAM;AAF3B,wBA2CE"}
@@ -11,4 +11,4 @@ declare global {
11
11
  }
12
12
  declare const _default: <TComponent>(scope: string, module: string, shareScope?: string) => Promise<TComponent>;
13
13
  export default _default;
14
- //# sourceMappingURL=loadFederatedComponent.d.ts.map
14
+ //# sourceMappingURL=loadAppshellComponent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadAppshellComponent.d.ts","sourceRoot":"","sources":["../../../../src/loadAppshellComponent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,UAAU,EAAE,MAAM,SAAS,CAAC;AAGtD,OAAO,CAAC,MAAM,CAAC;IACb,SAAS,wBAAwB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7D,MAAM,wBAAwB,EAAE;QAAE,OAAO,EAAE,UAAU,CAAA;KAAE,CAAC;IACxD,UAAU,MAAM;QACd,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QACvB,wBAAwB,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;KACtD;CACF;4CAIwC,MAAM,UAAU,MAAM;AAA/D,wBAgCE"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@appshell/loader",
3
- "version": "0.2.1",
4
- "description": "Utility for loading federated components",
3
+ "version": "0.3.0",
4
+ "description": "Utility for loading Appshell components",
5
5
  "main": "dist/main.js",
6
6
  "types": "dist/loader/src/index.d.ts",
7
7
  "repository": "https://github.com/navaris/appshell.git",
@@ -25,5 +25,5 @@
25
25
  "appshell"
26
26
  ],
27
27
  "license": "MIT",
28
- "gitHead": "06e1095792287e9fbe3841f25251829fdf9f047b"
28
+ "gitHead": "554727a36140e4b8f609159795e1011801824108"
29
29
  }
@@ -16,7 +16,7 @@ type ShareScopes = keyof typeof __webpack_share_scopes__;
16
16
  export default async <TComponent>(scope: string, module: string, shareScope = 'default') => {
17
17
  // eslint-disable-next-line no-console
18
18
  console.debug(
19
- `loading federated component: { scope: ${scope}, module: ${module}, shareScope: ${shareScope} }`,
19
+ `loading Appshell component: { scope: ${scope}, module: ${module}, shareScope: ${shareScope} }`,
20
20
  );
21
21
 
22
22
  // Initializes the share scope. This fills it with known provided modules from this build and all remotes
@@ -39,7 +39,7 @@ export default async <TComponent>(scope: string, module: string, shareScope = 'd
39
39
 
40
40
  // eslint-disable-next-line no-console
41
41
  console.debug(
42
- `federated component loaded: { scope: ${scope}, module: ${module}, shareScope: ${shareScope} }`,
42
+ `Appshell component loaded: { scope: ${scope}, module: ${module}, shareScope: ${shareScope} }`,
43
43
  );
44
44
 
45
45
  const Component = Module.default;
@@ -2,7 +2,7 @@
2
2
  import { type AppshellManifest } from '@appshell/config';
3
3
  import { AppshellGlobalConfig } from 'packages/config/src/types';
4
4
  import fetchDynamicScript from './fetchDynamicScript';
5
- import loadFederatedComponent from './loadFederatedComponent';
5
+ import loadAppshellComponent from './loadAppshellComponent';
6
6
 
7
7
  const fetchedScriptCache = new Set<string>();
8
8
  const fetchedManifestCache = new Map<string, AppshellManifest | undefined>();
@@ -53,7 +53,7 @@ export default (config: AppshellGlobalConfig) =>
53
53
  (await fetchDynamicScript(remote.remoteEntryUrl));
54
54
  if (loaded) {
55
55
  fetchedScriptCache.add(remote.remoteEntryUrl);
56
- Component = await loadFederatedComponent<TComponent>(
56
+ Component = await loadAppshellComponent<TComponent>(
57
57
  remote.scope,
58
58
  remote.module,
59
59
  remote.shareScope,
@@ -1 +0,0 @@
1
- {"version":3,"file":"loadFederatedComponent.d.ts","sourceRoot":"","sources":["../../../../src/loadFederatedComponent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,UAAU,EAAE,MAAM,SAAS,CAAC;AAGtD,OAAO,CAAC,MAAM,CAAC;IACb,SAAS,wBAAwB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7D,MAAM,wBAAwB,EAAE;QAAE,OAAO,EAAE,UAAU,CAAA;KAAE,CAAC;IACxD,UAAU,MAAM;QACd,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QACvB,wBAAwB,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;KACtD;CACF;4CAIwC,MAAM,UAAU,MAAM;AAA/D,wBAgCE"}