@equinor/fusion-framework-cli 15.7.2-next.1 → 15.7.2
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 +15 -12
- package/bin/build/bin.mjs +1 -1
- package/bin/build/cli.mjs +3 -3
- package/dist/esm/lib/app/merge-app-config.js +4 -14
- package/dist/esm/lib/app/merge-app-config.js.map +1 -1
- package/dist/esm/lib/app/merge-app-config.test.js +34 -0
- package/dist/esm/lib/app/merge-app-config.test.js.map +1 -0
- package/dist/esm/lib/app/merge-app-manifests.js +3 -4
- package/dist/esm/lib/app/merge-app-manifests.js.map +1 -1
- package/dist/esm/lib/merge-dev-server-config.js +12 -14
- package/dist/esm/lib/merge-dev-server-config.js.map +1 -1
- package/dist/esm/lib/merge-dev-server-config.test.js +44 -0
- package/dist/esm/lib/merge-dev-server-config.test.js.map +1 -0
- package/dist/esm/lib/portal/load-portal-manifest.js +2 -2
- package/dist/esm/lib/portal/load-portal-manifest.js.map +1 -1
- package/dist/esm/lib/utils/merge-config.js +109 -0
- package/dist/esm/lib/utils/merge-config.js.map +1 -0
- package/dist/esm/lib/utils/tests/merge-config.test.js +48 -0
- package/dist/esm/lib/utils/tests/merge-config.test.js.map +1 -0
- package/dist/esm/version.js +1 -1
- package/dist/types/lib/app/merge-app-config.test.d.ts +1 -0
- package/dist/types/lib/app/merge-app-manifests.d.ts +1 -1
- package/dist/types/lib/merge-dev-server-config.d.ts +2 -2
- package/dist/types/lib/merge-dev-server-config.test.d.ts +1 -0
- package/dist/types/lib/utils/merge-config.d.ts +31 -0
- package/dist/types/lib/utils/tests/merge-config.test.d.ts +1 -0
- package/dist/types/version.d.ts +1 -1
- package/package.json +10 -13
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { mergeConfig } from '../utils/merge-config.js';
|
|
2
2
|
/**
|
|
3
3
|
* Merges a base application configuration object with an overrides object,
|
|
4
4
|
* returning a new configuration object. If the `scopes` property is present
|
|
@@ -11,18 +11,8 @@ import deepmerge from 'deepmerge';
|
|
|
11
11
|
* @returns A new configuration object resulting from merging `base` and `overrides`.
|
|
12
12
|
*/
|
|
13
13
|
export const mergeAppConfig = (base, overrides) => {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
// Replace (rather than deep-merge) scopes so overrides fully control the array
|
|
18
|
-
if (key === 'scopes') {
|
|
19
|
-
return (_target, source) => {
|
|
20
|
-
// If scopes are provided in overrides, replace the base scopes with the new ones
|
|
21
|
-
return source;
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
return undefined; // Use default merging for other keys
|
|
25
|
-
},
|
|
26
|
-
});
|
|
14
|
+
return mergeConfig(base, overrides, (target, source, key) =>
|
|
15
|
+
// Replace scopes so overrides fully control which scopes are requested; append other arrays
|
|
16
|
+
key === 'scopes' ? source : target.concat(source));
|
|
27
17
|
};
|
|
28
18
|
//# sourceMappingURL=merge-app-config.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge-app-config.js","sourceRoot":"","sources":["../../../../src/lib/app/merge-app-config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"merge-app-config.js","sourceRoot":"","sources":["../../../../src/lib/app/merge-app-config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAsB,IAAO,EAAE,SAAqB,EAAK,EAAE;IACvF,OAAO,WAAW,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE;IAC1D,4FAA4F;IAC5F,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAClD,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { mergeAppConfig } from './merge-app-config.js';
|
|
3
|
+
/**
|
|
4
|
+
* Treats a minimal fixture as an app config shape.
|
|
5
|
+
*
|
|
6
|
+
* @template T - Shape the fixture stands in for.
|
|
7
|
+
* @param value - Minimal fixture object.
|
|
8
|
+
* @returns The fixture typed as `T`.
|
|
9
|
+
*/
|
|
10
|
+
const fixture = (value) =>
|
|
11
|
+
// Fixtures only carry the keys under test; the merge never reads the omitted required fields
|
|
12
|
+
value;
|
|
13
|
+
describe('mergeAppConfig', () => {
|
|
14
|
+
it('replaces scopes at any depth while deep-merging other properties', () => {
|
|
15
|
+
const base = fixture({
|
|
16
|
+
environment: { a: 1 },
|
|
17
|
+
endpoints: { api: { url: 'https://base', scopes: ['base/.default'] } },
|
|
18
|
+
});
|
|
19
|
+
const overrides = fixture({
|
|
20
|
+
environment: { b: 2 },
|
|
21
|
+
endpoints: { api: { scopes: ['override/.default'] } },
|
|
22
|
+
});
|
|
23
|
+
expect(mergeAppConfig(base, overrides)).toEqual({
|
|
24
|
+
environment: { a: 1, b: 2 },
|
|
25
|
+
endpoints: { api: { url: 'https://base', scopes: ['override/.default'] } },
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
it('does not mutate the base configuration', () => {
|
|
29
|
+
const base = fixture({ environment: { a: 1 } });
|
|
30
|
+
mergeAppConfig(base, fixture({ environment: { b: 2 } }));
|
|
31
|
+
expect(base).toEqual({ environment: { a: 1 } });
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
//# sourceMappingURL=merge-app-config.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-app-config.test.js","sourceRoot":"","sources":["../../../../src/lib/app/merge-app-config.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD;;;;;;GAMG;AACH,MAAM,OAAO,GAAG,CAAI,KAAc,EAAK,EAAE;AACvC,6FAA6F;AAC7F,KAAU,CAAC;AAEb,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC1E,MAAM,IAAI,GAAG,OAAO,CAAY;YAC9B,WAAW,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE;YACrB,SAAS,EAAE,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,eAAe,CAAC,EAAE,EAAE;SACvE,CAAC,CAAC;QACH,MAAM,SAAS,GAAG,OAAO,CAAqB;YAC5C,WAAW,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE;YACrB,SAAS,EAAE,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,CAAC,mBAAmB,CAAC,EAAE,EAAE;SACtD,CAAC,CAAC;QAEH,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;YAC9C,WAAW,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;YAC3B,SAAS,EAAE,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,mBAAmB,CAAC,EAAE,EAAE;SAC3E,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,IAAI,GAAG,OAAO,CAAY,EAAE,WAAW,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAE3D,cAAc,CAAC,IAAI,EAAE,OAAO,CAAqB,EAAE,WAAW,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAE7E,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { mergeConfig } from '../utils/merge-config.js';
|
|
2
2
|
/**
|
|
3
|
-
* Deeply merges two application manifests
|
|
3
|
+
* Deeply merges two application manifests.
|
|
4
4
|
*
|
|
5
5
|
* This utility is intended for combining a base manifest with an override manifest,
|
|
6
6
|
* supporting recursive merging of nested properties. It is commonly used in scenarios
|
|
@@ -21,8 +21,7 @@ import mergeWith from 'deepmerge';
|
|
|
21
21
|
*/
|
|
22
22
|
export const mergeAppManifests = (base, // The base manifest (may be partial)
|
|
23
23
|
overrides) => {
|
|
24
|
-
|
|
25
|
-
const manifest = mergeWith(base, overrides);
|
|
24
|
+
const manifest = mergeConfig(base, overrides);
|
|
26
25
|
// TODO(#5077): Add assertions or schema validation here if needed
|
|
27
26
|
return manifest;
|
|
28
27
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge-app-manifests.js","sourceRoot":"","sources":["../../../../src/lib/app/merge-app-manifests.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"merge-app-manifests.js","sourceRoot":"","sources":["../../../../src/lib/app/merge-app-manifests.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,IAAmC,EAAE,qCAAqC;AAC1E,SAAwC,EAC3B,EAAE;IACf,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,EAAE,SAAS,CAAgB,CAAC;IAC7D,kEAAkE;IAClE,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC;AAEF,yDAAyD;AACzD,eAAe,iBAAiB,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { mergeConfig } from './utils/merge-config.js';
|
|
2
2
|
/**
|
|
3
3
|
* Merges two arrays of objects by a specified key, ensuring that objects with the same key value
|
|
4
4
|
* are merged, with the `source` array taking precedence over the `target` array for duplicate keys.
|
|
@@ -21,8 +21,8 @@ const keyedArrayMerger = (key, target, source) => {
|
|
|
21
21
|
/**
|
|
22
22
|
* Merges a base development server configuration with an overrides object.
|
|
23
23
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
24
|
+
* Objects are merged recursively. Route arrays (entries with `match` and `middleware`) are
|
|
25
|
+
* merged by `match`, with override routes winning; other arrays are concatenated and de-duplicated.
|
|
26
26
|
*
|
|
27
27
|
* @param base - The base development server configuration.
|
|
28
28
|
* @param overrides - A partial configuration object containing properties to override in the base configuration.
|
|
@@ -31,17 +31,15 @@ const keyedArrayMerger = (key, target, source) => {
|
|
|
31
31
|
* Inline comments are provided for maintainability and clarity.
|
|
32
32
|
*/
|
|
33
33
|
export const mergeDevServerConfig = (base, overrides) => {
|
|
34
|
-
return
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
return [...new Set([...target, ...source])];
|
|
44
|
-
},
|
|
34
|
+
return mergeConfig(base, overrides, (target, source) => {
|
|
35
|
+
// extract the first entry from both arrays to determine the merge strategy
|
|
36
|
+
const entry = source[0] ?? target[0];
|
|
37
|
+
// merge routes by 'match' if the entry is a route object
|
|
38
|
+
if (typeof entry === 'object' && entry !== null && 'match' in entry && 'middleware' in entry) {
|
|
39
|
+
return keyedArrayMerger('match', target, source);
|
|
40
|
+
}
|
|
41
|
+
// Deduplicate the combined target and source entries
|
|
42
|
+
return [...new Set([...target, ...source])];
|
|
45
43
|
});
|
|
46
44
|
};
|
|
47
45
|
// Export as default for convenience in imports
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge-dev-server-config.js","sourceRoot":"","sources":["../../../src/lib/merge-dev-server-config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"merge-dev-server-config.js","sourceRoot":"","sources":["../../../src/lib/merge-dev-server-config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAGtD;;;;;;;;;GASG;AACH,MAAM,gBAAgB,GAAG,CACvB,GAAgB,EAChB,MAAoB,EACpB,MAAoB,EACN,EAAE;IAChB,qEAAqE;IACrE,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CACjC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAChE,EAAW,CACZ,CAAC;IACF,2EAA2E;IAC3E,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CACjC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAChE,EAAW,CACZ,CAAC;IACF,oFAAoF;IACpF,MAAM,aAAa,GAAG,EAAE,GAAG,aAAa,EAAE,GAAG,aAAa,EAAE,CAAC;IAC7D,OAAO,MAAM,CAAC,MAAM,CAAC,aAAa,CAAiB,CAAC;AACtD,CAAC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,IAAsB,EACtB,SAA6C,EAC3B,EAAE;IACpB,OAAO,WAAW,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE;QACrD,2EAA2E;QAC3E,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;QAErC,yDAAyD;QACzD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,IAAI,YAAY,IAAI,KAAK,EAAE,CAAC;YAC7F,OAAO,gBAAgB,CACrB,OAAO,EACP,MAAwC,EACxC,MAAwC,CACzC,CAAC;QACJ,CAAC;QACD,qDAAqD;QACrD,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,+CAA+C;AAC/C,eAAe,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { mergeDevServerConfig } from './merge-dev-server-config.js';
|
|
3
|
+
/**
|
|
4
|
+
* Treats a minimal fixture as a full dev-server shape.
|
|
5
|
+
*
|
|
6
|
+
* @template T - Shape the fixture stands in for.
|
|
7
|
+
* @param value - Minimal fixture object.
|
|
8
|
+
* @returns The fixture typed as `T`.
|
|
9
|
+
*/
|
|
10
|
+
const fixture = (value) =>
|
|
11
|
+
// Fixtures only carry the keys under test; the merge never reads the omitted required fields
|
|
12
|
+
value;
|
|
13
|
+
describe('mergeDevServerConfig', () => {
|
|
14
|
+
it('merges routes by match with override routes winning, and de-duplicates other arrays', () => {
|
|
15
|
+
const baseMiddleware = () => { };
|
|
16
|
+
const overrideMiddleware = () => { };
|
|
17
|
+
const base = fixture({
|
|
18
|
+
api: {
|
|
19
|
+
routes: [
|
|
20
|
+
{ match: '/a', middleware: baseMiddleware },
|
|
21
|
+
{ match: '/b', middleware: baseMiddleware },
|
|
22
|
+
],
|
|
23
|
+
processServices: ['x', 'y'],
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
const overrides = fixture({
|
|
27
|
+
api: {
|
|
28
|
+
routes: [{ match: '/b', middleware: overrideMiddleware }],
|
|
29
|
+
processServices: ['y', 'z'],
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
const result = fixture(mergeDevServerConfig(base, overrides));
|
|
33
|
+
expect(result.api.routes).toEqual([
|
|
34
|
+
{ match: '/a', middleware: baseMiddleware },
|
|
35
|
+
{ match: '/b', middleware: overrideMiddleware },
|
|
36
|
+
]);
|
|
37
|
+
expect(result.api.processServices).toEqual(['x', 'y', 'z']);
|
|
38
|
+
});
|
|
39
|
+
it('keeps base values when overrides are empty', () => {
|
|
40
|
+
const base = fixture({ api: { processServices: ['x'] } });
|
|
41
|
+
expect(mergeDevServerConfig(base, {})).toEqual(base);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
//# sourceMappingURL=merge-dev-server-config.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-dev-server-config.test.js","sourceRoot":"","sources":["../../../src/lib/merge-dev-server-config.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAOpE;;;;;;GAMG;AACH,MAAM,OAAO,GAAG,CAAI,KAAc,EAAK,EAAE;AACvC,6FAA6F;AAC7F,KAAU,CAAC;AAEb,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,qFAAqF,EAAE,GAAG,EAAE;QAC7F,MAAM,cAAc,GAAG,GAAS,EAAE,GAAE,CAAC,CAAC;QACtC,MAAM,kBAAkB,GAAG,GAAS,EAAE,GAAE,CAAC,CAAC;QAC1C,MAAM,IAAI,GAAG,OAAO,CAAmB;YACrC,GAAG,EAAE;gBACH,MAAM,EAAE;oBACN,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,cAAc,EAAE;oBAC3C,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,cAAc,EAAE;iBAC5C;gBACD,eAAe,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC;aAC5B;SACF,CAAC,CAAC;QACH,MAAM,SAAS,GAAG,OAAO,CAAY;YACnC,GAAG,EAAE;gBACH,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,kBAAkB,EAAE,CAAC;gBACzD,eAAe,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC;aAC5B;SACF,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,OAAO,CAAY,oBAAoB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;QAEzE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YAChC,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,cAAc,EAAE;YAC3C,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,kBAAkB,EAAE;SAChD,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,IAAI,GAAG,OAAO,CAAmB,EAAE,GAAG,EAAE,EAAE,eAAe,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;QAE5E,MAAM,CAAC,oBAAoB,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { importConfig } from '@equinor/fusion-imports';
|
|
2
|
-
import
|
|
2
|
+
import { mergeConfig } from '../utils/merge-config.js';
|
|
3
3
|
import { PortalManifestSchema } from './portal-manifest-schema.js';
|
|
4
4
|
/**
|
|
5
5
|
* Loads a portal manifest configuration file, merging it with optional base values and supporting multiple file extensions.
|
|
@@ -38,7 +38,7 @@ export const loadPortalManifest = async (env, options) => {
|
|
|
38
38
|
// If the manifest export is not a function, treat it as an object
|
|
39
39
|
overrides = module.default;
|
|
40
40
|
}
|
|
41
|
-
return overrides ?
|
|
41
|
+
return overrides ? mergeConfig(base, overrides) : base;
|
|
42
42
|
},
|
|
43
43
|
},
|
|
44
44
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load-portal-manifest.js","sourceRoot":"","sources":["../../../../src/lib/portal/load-portal-manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEvD,OAAO,
|
|
1
|
+
{"version":3,"file":"load-portal-manifest.js","sourceRoot":"","sources":["../../../../src/lib/portal/load-portal-manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEvD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAwDnE;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,EACrC,GAAe,EACf,OAAsC,EACA,EAAE;IACxC,iGAAiG;IACjG,MAAM,WAAW,GAAG,OAAO,EAAE,IAAI,IAAI,CAAC,mBAAmB,GAAG,CAAC,WAAW,EAAE,EAAE,iBAAiB,CAAC,CAAC;IAE/F,+EAA+E;IAC/E,MAAM,YAAY,GAAG,MAAM,YAAY,CAAC,WAAW,EAAE;QACnD,OAAO,EAAE,GAAG,CAAC,IAAI,EAAE,iDAAiD;QACpE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,2CAA2C;QAC5E,MAAM,EAAE;YACN,uCAAuC;YACvC,OAAO,EAAE,KAAK,EAAE,MAA4C,EAAc,EAAE;gBAC1E,0EAA0E;gBAC1E,MAAM,IAAI,GAAM,OAAO,EAAE,IAAI,IAAK,EAAQ,CAAC;gBAC3C,IAAI,SAA0C,CAAC;gBAC/C,uFAAuF;gBACvF,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;oBACzC,+EAA+E;oBAC/E,SAAS,GAAG,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,SAAS,CAAC;gBACjE,CAAC;qBAAM,CAAC;oBACN,kEAAkE;oBAClE,SAAS,GAAG,MAAM,CAAC,OAA8B,CAAC;gBACpD,CAAC;gBACD,OAAO,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YACzD,CAAC;SACF;KACF,CAAC,CAAC;IAEH,0EAA0E;IAC1E,8EAA8E;IAC9E,MAAM,QAAQ,GAAG,YAAY,CAAC,MAAW,CAAC;IAC1C,MAAM,UAAU,GAAG,oBAAoB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC5D,2EAA2E;IAC3E,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;QACxB,oEAAoE;QACpE,MAAM,aAAa,GAAG,UAAU,CAAC,KAAK,CAAC,MAAM;aAC1C,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;aAC/C,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,4BAA4B,aAAa,EAAE,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO;QACL,QAAQ;QACR,IAAI,EAAE,YAAY,CAAC,IAAI;QACvB,SAAS,EAAE,YAAY,CAAC,SAAS;KAClC,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks whether a value is an object literal, as opposed to an array or a class instance
|
|
3
|
+
* such as `Date` or `URL`, which replace rather than merge.
|
|
4
|
+
*
|
|
5
|
+
* @param value - Value to inspect.
|
|
6
|
+
* @returns `true` when the value is a plain object.
|
|
7
|
+
*/
|
|
8
|
+
const isConfigObject = (value) => {
|
|
9
|
+
// Primitives and null replace rather than merge
|
|
10
|
+
if (typeof value !== 'object' || value === null) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
const prototype = Object.getPrototypeOf(value);
|
|
14
|
+
return prototype === Object.prototype || prototype === null;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Default array strategy: append override entries after base entries.
|
|
18
|
+
*
|
|
19
|
+
* @param base - Array from the base config.
|
|
20
|
+
* @param overrides - Array from the overrides.
|
|
21
|
+
* @returns A new array with base entries followed by override entries.
|
|
22
|
+
*/
|
|
23
|
+
const appendArrays = (base, overrides) => base.concat(overrides);
|
|
24
|
+
/**
|
|
25
|
+
* Lists an object's entries without `__proto__`, which would replace the prototype of an object
|
|
26
|
+
* it is assigned to (GHSA-gcqx-w48m-w2h4).
|
|
27
|
+
*
|
|
28
|
+
* @param value - Object whose entries are listed.
|
|
29
|
+
* @returns The entries that are safe to assign.
|
|
30
|
+
*/
|
|
31
|
+
const safeEntries = (value) =>
|
|
32
|
+
// `JSON.parse` keeps `__proto__` as an own key, so untrusted config can carry one
|
|
33
|
+
Object.entries(value).filter(([entryKey]) => entryKey !== '__proto__');
|
|
34
|
+
/**
|
|
35
|
+
* Copies plain objects and arrays from the overrides, dropping `__proto__` keys at any depth so
|
|
36
|
+
* an override value that has no base counterpart is cleaned the same way as a merged one.
|
|
37
|
+
*
|
|
38
|
+
* @param value - Value from the overrides.
|
|
39
|
+
* @returns A cleaned copy of plain objects and arrays; any other value as-is.
|
|
40
|
+
*/
|
|
41
|
+
const sanitize = (value) => {
|
|
42
|
+
// Arrays may contain plain objects that carry `__proto__` keys
|
|
43
|
+
if (Array.isArray(value)) {
|
|
44
|
+
// Clean every item, since items never merge with a base value
|
|
45
|
+
return value.map(sanitize);
|
|
46
|
+
}
|
|
47
|
+
// Class instances and primitives are kept as-is
|
|
48
|
+
if (!isConfigObject(value)) {
|
|
49
|
+
return value;
|
|
50
|
+
}
|
|
51
|
+
// Clean each nested value too, since none of them has a base value to merge with
|
|
52
|
+
const entries = safeEntries(value).map(([entryKey, entryValue]) => [
|
|
53
|
+
entryKey,
|
|
54
|
+
sanitize(entryValue),
|
|
55
|
+
]);
|
|
56
|
+
return Object.fromEntries(entries);
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Merges one value from the overrides into the matching base value.
|
|
60
|
+
*
|
|
61
|
+
* @param base - Value from the base config.
|
|
62
|
+
* @param overrides - Value from the overrides.
|
|
63
|
+
* @param mergeArrays - Strategy used when both values are arrays.
|
|
64
|
+
* @param key - Property key of the values, passed to `mergeArrays`.
|
|
65
|
+
* @returns The merged value.
|
|
66
|
+
*/
|
|
67
|
+
const mergeValue = (base, overrides, mergeArrays, key) => {
|
|
68
|
+
// Both sides are lists, so the caller's strategy decides how to combine them
|
|
69
|
+
if (Array.isArray(base) && Array.isArray(overrides)) {
|
|
70
|
+
// Clean override items before the strategy sees them, since it may keep them as-is
|
|
71
|
+
return mergeArrays(base, overrides.map(sanitize), key);
|
|
72
|
+
}
|
|
73
|
+
// Anything other than two plain objects is replaced by the override
|
|
74
|
+
if (!isConfigObject(base) || !isConfigObject(overrides)) {
|
|
75
|
+
return sanitize(overrides);
|
|
76
|
+
}
|
|
77
|
+
// Start from the base keys so keys absent from the overrides survive
|
|
78
|
+
const result = Object.fromEntries(safeEntries(base));
|
|
79
|
+
// Overlay each override key, recursing where both sides define it
|
|
80
|
+
for (const [entryKey, value] of safeEntries(overrides)) {
|
|
81
|
+
result[entryKey] = Object.hasOwn(base, entryKey)
|
|
82
|
+
? mergeValue(base[entryKey], value, mergeArrays, entryKey)
|
|
83
|
+
: sanitize(value);
|
|
84
|
+
}
|
|
85
|
+
return result;
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Deeply merges CLI config overrides (app config, app or portal manifest, dev-server config)
|
|
89
|
+
* into a base config without mutating either input.
|
|
90
|
+
*
|
|
91
|
+
* Plain objects merge key by key with override values winning, including an explicit `undefined`.
|
|
92
|
+
* Arrays are appended unless `mergeArrays` says otherwise. Any other value, including class
|
|
93
|
+
* instances, replaces the base value. Values taken from the overrides are copied with `__proto__`
|
|
94
|
+
* keys removed at any depth; base values that are not overridden are shared with the inputs.
|
|
95
|
+
*
|
|
96
|
+
* @template T - Shape of the config.
|
|
97
|
+
* @param base - Base config.
|
|
98
|
+
* @param overrides - Partial config whose values take precedence.
|
|
99
|
+
* @param mergeArrays - Strategy for combining two arrays at the same key. Defaults to appending.
|
|
100
|
+
* @returns A new config containing the merged values.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```ts
|
|
104
|
+
* mergeConfig({ server: { port: 3000 }, scopes: ['a'] }, { server: { host: 'x' }, scopes: ['b'] });
|
|
105
|
+
* // { server: { port: 3000, host: 'x' }, scopes: ['a', 'b'] }
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
export const mergeConfig = (base, overrides, mergeArrays = appendArrays) => mergeValue(base, overrides, mergeArrays, '');
|
|
109
|
+
//# sourceMappingURL=merge-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-config.js","sourceRoot":"","sources":["../../../../src/lib/utils/merge-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { mergeConfig } from '../merge-config.js';
|
|
3
|
+
describe('mergeConfig', () => {
|
|
4
|
+
it('merges nested objects with overrides winning and appends arrays by default', () => {
|
|
5
|
+
expect(mergeConfig({ server: { port: 3000, host: 'a' }, scopes: ['x'] }, { server: { host: 'b' }, scopes: ['y'], extra: true })).toEqual({ server: { port: 3000, host: 'b' }, scopes: ['x', 'y'], extra: true });
|
|
6
|
+
});
|
|
7
|
+
it('does not mutate the base config', () => {
|
|
8
|
+
const base = { server: { port: 3000 }, scopes: ['x'] };
|
|
9
|
+
mergeConfig(base, { server: { host: 'b' }, scopes: ['y'] });
|
|
10
|
+
expect(base).toEqual({ server: { port: 3000 }, scopes: ['x'] });
|
|
11
|
+
});
|
|
12
|
+
it('lets explicit undefined, arrays, and class instances replace the base value', () => {
|
|
13
|
+
const url = new URL('https://example.com');
|
|
14
|
+
expect(mergeConfig({ a: 1, b: { c: 1 }, url: { href: 'x' } }, { a: undefined, b: [1], url })).toEqual({
|
|
15
|
+
a: undefined,
|
|
16
|
+
b: [1],
|
|
17
|
+
url,
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
it('passes the property key to a custom array strategy', () => {
|
|
21
|
+
const result = mergeConfig({ scopes: ['a'], nested: { scopes: ['b'], list: [1] } }, { scopes: ['x'], nested: { scopes: ['y'], list: [2] } }, (base, overrides, key) => (key === 'scopes' ? overrides : base.concat(overrides)));
|
|
22
|
+
expect(result).toEqual({ scopes: ['x'], nested: { scopes: ['y'], list: [1, 2] } });
|
|
23
|
+
});
|
|
24
|
+
it('ignores __proto__ keys from untrusted overrides', () => {
|
|
25
|
+
const overrides = JSON.parse('{"__proto__": {"polluted": true}, "nested": {"__proto__": {"polluted": true}}}');
|
|
26
|
+
const result = mergeConfig({ nested: {} }, overrides);
|
|
27
|
+
expect(Object.getPrototypeOf(result)).toBe(Object.prototype);
|
|
28
|
+
expect(Object.getPrototypeOf(result.nested)).toBe(Object.prototype);
|
|
29
|
+
expect(result.polluted).toBeUndefined();
|
|
30
|
+
});
|
|
31
|
+
it('strips __proto__ keys from override values that have no base counterpart, at any depth', () => {
|
|
32
|
+
const overrides = JSON.parse('{"added": {"deep": {"__proto__": {"polluted": true}}}, "list": [{"__proto__": {"polluted": true}}], "replaced": {"__proto__": {"polluted": true}}}');
|
|
33
|
+
const base = { list: [], replaced: 'primitive' };
|
|
34
|
+
const result = mergeConfig(base, overrides);
|
|
35
|
+
// Object.assign uses [[Set]], so a surviving own `__proto__` key would swap the prototype
|
|
36
|
+
const reassigned = [
|
|
37
|
+
Object.assign({}, result.added.deep),
|
|
38
|
+
Object.assign({}, result.list[0]),
|
|
39
|
+
Object.assign({}, result.replaced),
|
|
40
|
+
];
|
|
41
|
+
// Each value came from the overrides without a base counterpart to merge with
|
|
42
|
+
for (const value of reassigned) {
|
|
43
|
+
expect(Object.getPrototypeOf(value)).toBe(Object.prototype);
|
|
44
|
+
expect(Object.hasOwn(value, '__proto__')).toBe(false);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
//# sourceMappingURL=merge-config.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-config.test.js","sourceRoot":"","sources":["../../../../../src/lib/utils/tests/merge-config.test.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/version.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { AppManifest } from '@equinor/fusion-framework-module-app';
|
|
2
2
|
import type { RecursivePartial } from '../utils/types.js';
|
|
3
3
|
/**
|
|
4
|
-
* Deeply merges two application manifests
|
|
4
|
+
* Deeply merges two application manifests.
|
|
5
5
|
*
|
|
6
6
|
* This utility is intended for combining a base manifest with an override manifest,
|
|
7
7
|
* supporting recursive merging of nested properties. It is commonly used in scenarios
|
|
@@ -3,8 +3,8 @@ import type { RecursivePartial } from './utils/types.js';
|
|
|
3
3
|
/**
|
|
4
4
|
* Merges a base development server configuration with an overrides object.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* Objects are merged recursively. Route arrays (entries with `match` and `middleware`) are
|
|
7
|
+
* merged by `match`, with override routes winning; other arrays are concatenated and de-duplicated.
|
|
8
8
|
*
|
|
9
9
|
* @param base - The base development server configuration.
|
|
10
10
|
* @param overrides - A partial configuration object containing properties to override in the base configuration.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Combines two arrays found at the same key in a base config and its overrides.
|
|
3
|
+
*
|
|
4
|
+
* @param base - Array from the base config.
|
|
5
|
+
* @param overrides - Array from the overrides.
|
|
6
|
+
* @param key - Property key holding both arrays.
|
|
7
|
+
* @returns The array to keep in the merged config.
|
|
8
|
+
*/
|
|
9
|
+
export type MergeConfigArrays = (base: unknown[], overrides: unknown[], key: string) => unknown[];
|
|
10
|
+
/**
|
|
11
|
+
* Deeply merges CLI config overrides (app config, app or portal manifest, dev-server config)
|
|
12
|
+
* into a base config without mutating either input.
|
|
13
|
+
*
|
|
14
|
+
* Plain objects merge key by key with override values winning, including an explicit `undefined`.
|
|
15
|
+
* Arrays are appended unless `mergeArrays` says otherwise. Any other value, including class
|
|
16
|
+
* instances, replaces the base value. Values taken from the overrides are copied with `__proto__`
|
|
17
|
+
* keys removed at any depth; base values that are not overridden are shared with the inputs.
|
|
18
|
+
*
|
|
19
|
+
* @template T - Shape of the config.
|
|
20
|
+
* @param base - Base config.
|
|
21
|
+
* @param overrides - Partial config whose values take precedence.
|
|
22
|
+
* @param mergeArrays - Strategy for combining two arrays at the same key. Defaults to appending.
|
|
23
|
+
* @returns A new config containing the merged values.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* mergeConfig({ server: { port: 3000 }, scopes: ['a'] }, { server: { host: 'x' }, scopes: ['b'] });
|
|
28
|
+
* // { server: { port: 3000, host: 'x' }, scopes: ['a', 'b'] }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare const mergeConfig: <T>(base: T, overrides: unknown, mergeArrays?: MergeConfigArrays) => T;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/types/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "15.7.2
|
|
1
|
+
export declare const version = "15.7.2";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@equinor/fusion-framework-cli",
|
|
3
|
-
"version": "15.7.2
|
|
3
|
+
"version": "15.7.2",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"Fusion",
|
|
6
6
|
"Fusion Framework",
|
|
@@ -94,23 +94,20 @@
|
|
|
94
94
|
"directory": "packages/cli"
|
|
95
95
|
},
|
|
96
96
|
"dependencies": {
|
|
97
|
-
"@equinor/fusion-framework-dev-portal": "11.1.10
|
|
98
|
-
"@equinor/fusion-framework-dev-server": "2.3.3
|
|
99
|
-
"@equinor/fusion-framework-module-azure-identity": "0.4
|
|
97
|
+
"@equinor/fusion-framework-dev-portal": "11.1.10",
|
|
98
|
+
"@equinor/fusion-framework-dev-server": "2.3.3",
|
|
99
|
+
"@equinor/fusion-framework-module-azure-identity": "0.3.4",
|
|
100
100
|
"@equinor/fusion-framework-vite-plugin-raw-imports": "2.0.5",
|
|
101
101
|
"@equinor/fusion-framework-vite-plugin-react-router": "0.1.5",
|
|
102
102
|
"@equinor/fusion-imports": "2.0.7",
|
|
103
|
-
"@types/inquirer": "^9.0.9",
|
|
104
103
|
"chalk": "^6.0.0",
|
|
105
104
|
"commander": "^15.0.0",
|
|
106
|
-
"deepmerge": "^4.3.1",
|
|
107
105
|
"dotenv": "^18.0.4",
|
|
108
106
|
"execa": "^10.0.0",
|
|
109
107
|
"find-up": "^8.0.0",
|
|
110
108
|
"inquirer": "^14.0.0",
|
|
111
|
-
"is-mergeable-object": "^1.1.1",
|
|
112
109
|
"is-path-inside": "^4.0.0",
|
|
113
|
-
"ora": "^
|
|
110
|
+
"ora": "^10.0.0",
|
|
114
111
|
"read-package-up": "^12.0.0",
|
|
115
112
|
"semver": "^7.7.4",
|
|
116
113
|
"simple-git": "^4.0.1",
|
|
@@ -119,11 +116,11 @@
|
|
|
119
116
|
"zod": "^4.4.3"
|
|
120
117
|
},
|
|
121
118
|
"devDependencies": {
|
|
122
|
-
"@equinor/fusion-framework-cli-plugin-mock-server": "^0.3.3
|
|
123
|
-
"@equinor/fusion-framework-module": "6.
|
|
124
|
-
"@equinor/fusion-framework-module-app": "8.
|
|
125
|
-
"@equinor/fusion-framework-module-http": "8.1.
|
|
126
|
-
"@equinor/fusion-framework-module-service-discovery": "10.
|
|
119
|
+
"@equinor/fusion-framework-cli-plugin-mock-server": "^0.3.3",
|
|
120
|
+
"@equinor/fusion-framework-module": "6.1.6",
|
|
121
|
+
"@equinor/fusion-framework-module-app": "8.2.2",
|
|
122
|
+
"@equinor/fusion-framework-module-http": "8.1.4",
|
|
123
|
+
"@equinor/fusion-framework-module-service-discovery": "10.2.0",
|
|
127
124
|
"@rollup/plugin-commonjs": "^29.0.0",
|
|
128
125
|
"@rollup/plugin-json": "^6.1.0",
|
|
129
126
|
"@rollup/plugin-node-resolve": "^16.0.1",
|