@appshell/loader 0.2.0-alpha.0 → 0.2.0-alpha.1

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.2.0-alpha.1](https://github.com/navaris/appshell/compare/@appshell/loader@0.2.0-alpha.0...@appshell/loader@0.2.0-alpha.1) (2023-08-28)
7
+
8
+
9
+ ### Features
10
+
11
+ * environment variable override for federated components ([#27](https://github.com/navaris/appshell/issues/27)) ([d32de0b](https://github.com/navaris/appshell/commit/d32de0b0d1cbb1792715e1b363c80ed4600df155))
12
+
13
+
14
+
15
+
16
+
6
17
  # [0.2.0-alpha.0](https://github.com/navaris/appshell/compare/@appshell/loader@0.1.0...@appshell/loader@0.2.0-alpha.0) (2023-08-23)
7
18
 
8
19
 
@@ -1,6 +1,6 @@
1
1
  /** @jest-environment jsdom */
2
2
  import { AppshellManifest } from '@appshell/config';
3
- import { AppshellRegister } from '@appshell/config/src/types';
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
6
  import * as loadFederatedComponent from '../src/loadFederatedComponent';
@@ -24,13 +24,24 @@ describe('remoteLoader', () => {
24
24
  },
25
25
  },
26
26
  modules: {},
27
- environment: {},
27
+ environment: {
28
+ TestModule: {
29
+ ENV_VAR_A: 'Original value for A',
30
+ },
31
+ },
28
32
  };
29
- const register: AppshellRegister = {
33
+ const config: AppshellGlobalConfig = {
30
34
  index: {
31
35
  'TestModule/TestComponent': 'http://test.com/appshell.manifest.json',
32
36
  },
33
37
  metadata: {},
38
+ overrides: {
39
+ environment: {
40
+ TestModule: {
41
+ ENV_VAR_A: 'New value for A',
42
+ },
43
+ },
44
+ },
34
45
  };
35
46
 
36
47
  beforeEach(() => {
@@ -46,7 +57,7 @@ describe('remoteLoader', () => {
46
57
  .spyOn(loadFederatedComponent, 'default')
47
58
  .mockResolvedValue(Promise.resolve(ExpectedComponent));
48
59
 
49
- const loadRemote = remoteLoader(register);
60
+ const loadRemote = remoteLoader(config);
50
61
  const [ActualComponent, actualManifest] = await loadRemote('TestModule/TestComponent');
51
62
 
52
63
  expect(ActualComponent).toEqual(ExpectedComponent);
@@ -62,7 +73,7 @@ describe('remoteLoader', () => {
62
73
  .spyOn(loadFederatedComponent, 'default')
63
74
  .mockResolvedValue(Promise.resolve(ExpectedComponent));
64
75
 
65
- const loadRemote = remoteLoader(register);
76
+ const loadRemote = remoteLoader(config);
66
77
 
67
78
  await loadRemote('TestModule/TestComponent');
68
79
  await loadRemote('TestModule/TestComponent');
@@ -71,11 +82,26 @@ describe('remoteLoader', () => {
71
82
  expect(fetchDynamicScriptSpy).toHaveBeenCalledTimes(1);
72
83
  });
73
84
 
85
+ it('should apply overridden environment values', async () => {
86
+ const ExpectedComponent = () => 'test component';
87
+ jest.spyOn(fetchDynamicScript, 'default').mockReturnValueOnce(Promise.resolve(true));
88
+ jest
89
+ .spyOn(loadFederatedComponent, 'default')
90
+ .mockResolvedValue(Promise.resolve(ExpectedComponent));
91
+
92
+ const loadRemote = remoteLoader(config);
93
+
94
+ await loadRemote('TestModule/TestComponent');
95
+
96
+ // eslint-disable-next-line no-underscore-dangle
97
+ expect(window.__appshell_env__TestModule).toMatchObject({ ENV_VAR_A: 'New value for A' });
98
+ });
99
+
74
100
  it('should throw if remote key is not found in the registry', async () => {
75
101
  const ExpectedComponent = () => 'test component';
76
102
  jest.spyOn(loadFederatedComponent, 'default').mockResolvedValue(ExpectedComponent);
77
103
 
78
- const loadRemote = remoteLoader(register);
104
+ const loadRemote = remoteLoader(config);
79
105
 
80
106
  await expect(loadRemote('TestModule/DoesNotExist')).rejects.toThrow(
81
107
  /Remote resource not found in registry/i,
@@ -86,7 +112,7 @@ describe('remoteLoader', () => {
86
112
  jest.spyOn(fetchDynamicScript, 'default').mockReturnValueOnce(Promise.resolve(true));
87
113
  jest.spyOn(loadFederatedComponent, 'default').mockRejectedValue(new Error('failed'));
88
114
 
89
- const loadRemote = remoteLoader(register);
115
+ const loadRemote = remoteLoader(config);
90
116
 
91
117
  await expect(loadRemote('TestModule/TestComponent')).rejects.toThrow(
92
118
  /Failed to load component/i,
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 c=o.index[a];if(!c)throw new Error(`Remote resource not found in registry. Expected: ${a}`);try{const o=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(o){n.set(c,o);const i=o.remotes[a];if(window[`__appshell_env__${i.scope}`]=o.environment[i.scope]||{},r.has(i.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)}))})(i.remoteEntryUrl))return r.add(i.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})(i.scope,i.module,i.shareScope),[d,o]}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 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[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 +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,wBAmCE"}
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 +1 @@
1
- {"version":3,"file":"remoteLoader.d.ts","sourceRoot":"","sources":["../../../../src/remoteLoader.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;iCAwBzC,oBAAoB,uBAClB,MAAM;AADhC,wBAsCI"}
1
+ {"version":3,"file":"remoteLoader.d.ts","sourceRoot":"","sources":["../../../../src/remoteLoader.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;iCAwBzC,oBAAoB,uBAClB,MAAM;AADhC,wBA2CI"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appshell/loader",
3
- "version": "0.2.0-alpha.0",
3
+ "version": "0.2.0-alpha.1",
4
4
  "description": "Utility for loading federated components",
5
5
  "main": "dist/main.js",
6
6
  "types": "dist/loader/src/index.d.ts",
@@ -25,5 +25,5 @@
25
25
  "appshell"
26
26
  ],
27
27
  "license": "MIT",
28
- "gitHead": "a4216a032817193034b208f93ac7109458ef2c06"
28
+ "gitHead": "f87947d0d8b10f74461f1b772d79f36f5bdce9e1"
29
29
  }
@@ -40,7 +40,12 @@ export default (config: AppshellGlobalConfig) =>
40
40
 
41
41
  const remote = manifest.remotes[key];
42
42
 
43
- window[`__appshell_env__${remote.scope}`] = manifest.environment[remote.scope] || {};
43
+ const environment = manifest.environment[remote.scope] || {};
44
+ const overrides = config.overrides?.environment[remote.scope] || {};
45
+ window[`__appshell_env__${remote.scope}`] = {
46
+ ...environment,
47
+ ...overrides,
48
+ };
44
49
 
45
50
  const loaded =
46
51
  fetchedScriptCache.has(remote.remoteEntryUrl) ||