Skip to content

Commit 851147b

Browse files
committed
feat(compartment-mapper): create Compartment Map Transforms
1 parent 0bbde9b commit 851147b

15 files changed

+2914
-135
lines changed

packages/compartment-mapper/node-modules.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
export * from './src/types-external.js';
33

44
export { mapNodeModules } from './src/node-modules.js';
5+
export { defaultCompartmentMapTransforms } from './src/compartment-map-transforms/index.js';
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
/**
2+
* Functions for transforming {@link CompartmentMapDescriptor CompartmentMapDescriptors}.
3+
*
4+
* @module
5+
*/
6+
7+
import { getPolicyForPackage } from '../policy.js';
8+
import { generateCanonicalName } from '../policy-format.js';
9+
import { defaultCompartmentMapTransforms } from './transforms.js';
10+
11+
export { defaultCompartmentMapTransforms };
12+
13+
/**
14+
* @import {CompartmentDescriptor,
15+
* CompartmentDescriptorMetadata,
16+
* CompartmentMapDescriptor,
17+
* CompartmentMapTransformContext,
18+
* CompartmentMapTransformFn,
19+
* CompartmentMapTransformOptions,
20+
GetCanonicalNameFn,
21+
* LogFn,
22+
* } from '../types.js'
23+
*/
24+
25+
const { stringify: q } = JSON;
26+
const { freeze, create } = Object;
27+
28+
/**
29+
* Dummy logger
30+
* @type {LogFn}
31+
*/
32+
const noop = () => {};
33+
34+
/**
35+
* Creates a {@link CompartmentMapTransformContext} for use with
36+
* {@link CompartmentMapTransformFn CompartmentMapTransformFns}.
37+
*
38+
* @param {CompartmentMapDescriptor} compartmentMap
39+
* @param {WeakMap<CompartmentDescriptor, CompartmentDescriptorMetadata>} metadataMap
40+
* @param {Map<string, string>} canonicalNameToCompartmentNameMap
41+
* @param {CompartmentMapTransformOptions} options
42+
* @returns {Readonly<CompartmentMapTransformContext>}
43+
*/
44+
const makeCompartmentMapTransformContext = (
45+
compartmentMap,
46+
metadataMap,
47+
canonicalNameToCompartmentNameMap,
48+
{ policy, log: _log = noop },
49+
) => {
50+
const { compartments } = compartmentMap;
51+
const entryCompartmentDescriptor =
52+
compartments[compartmentMap.entry.compartment];
53+
54+
/** @type {CompartmentMapTransformContext} */
55+
const context = {
56+
metadataMap: freeze(metadataMap),
57+
getCompartmentDescriptor: freeze(name => compartments[name]),
58+
getCanonicalName: freeze(compartmentDescriptorOrName => {
59+
/** @type {CompartmentDescriptor|undefined} */
60+
let compartmentDescriptor;
61+
if (typeof compartmentDescriptorOrName === 'string') {
62+
compartmentDescriptor = context.getCompartmentDescriptor(
63+
compartmentDescriptorOrName,
64+
);
65+
} else {
66+
compartmentDescriptor = compartmentDescriptorOrName;
67+
}
68+
if (
69+
!compartmentDescriptor?.path ||
70+
compartmentDescriptor === entryCompartmentDescriptor
71+
) {
72+
return undefined;
73+
}
74+
const metadata = /** @type {CompartmentDescriptorMetadata} */ (
75+
metadataMap.get(compartmentDescriptor) ?? create(null)
76+
);
77+
if (metadata.canonicalName) {
78+
return metadata.canonicalName;
79+
}
80+
const canonicalName = generateCanonicalName({
81+
isEntry: false,
82+
path: compartmentDescriptor.path,
83+
name: compartmentDescriptor.name,
84+
});
85+
metadata.canonicalName = canonicalName;
86+
metadataMap.set(compartmentDescriptor, metadata);
87+
return canonicalName;
88+
}),
89+
getCompartmentName: freeze(canonicalName =>
90+
canonicalNameToCompartmentNameMap.get(canonicalName),
91+
),
92+
getPackagePolicy: freeze((compartmentDescriptor, somePolicy = policy) => {
93+
assert(compartmentDescriptor, 'compartmentDescriptor expected');
94+
const { path, name } = compartmentDescriptor;
95+
if (!path) {
96+
return undefined;
97+
}
98+
return somePolicy
99+
? getPolicyForPackage(
100+
{
101+
isEntry: compartmentDescriptor === entryCompartmentDescriptor,
102+
path,
103+
name,
104+
},
105+
somePolicy,
106+
)
107+
: compartmentDescriptor.policy;
108+
}),
109+
};
110+
111+
return freeze(context);
112+
};
113+
114+
/**
115+
* Applies one or more {@link CompartmentMapTransformFn CompartmentMapTransformFns} to a
116+
* {@link CompartmentMapDescriptor}.
117+
*
118+
* @template {CompartmentMapTransformOptions} Options
119+
* @template {ReadonlyArray<CompartmentMapTransformFn<Options>>} [Transforms=ReadonlyArray<CompartmentMapTransformFn<Options>>]
120+
* @param {CompartmentMapDescriptor} compartmentMap
121+
* @param {WeakMap<CompartmentDescriptor, CompartmentDescriptorMetadata>} metadataMap
122+
* @param {Map<string, string>} canonicalNameToCompartmentNameMap
123+
* @param {Transforms} transforms
124+
* @param {Options} optionsForTransforms
125+
* @returns {Promise<CompartmentMapDescriptor>} Transformed compartment map
126+
* @internal
127+
*/
128+
export const applyCompartmentMapTransforms = async (
129+
compartmentMap,
130+
metadataMap,
131+
canonicalNameToCompartmentNameMap,
132+
transforms,
133+
optionsForTransforms,
134+
) => {
135+
await null;
136+
assert(optionsForTransforms !== undefined, 'optionsForTransforms expected');
137+
138+
const context = makeCompartmentMapTransformContext(
139+
compartmentMap,
140+
metadataMap,
141+
canonicalNameToCompartmentNameMap,
142+
optionsForTransforms,
143+
);
144+
145+
for (const transform of transforms ?? defaultCompartmentMapTransforms) {
146+
try {
147+
// eslint-disable-next-line no-await-in-loop
148+
compartmentMap = await transform({
149+
compartmentMap,
150+
options: optionsForTransforms,
151+
context,
152+
});
153+
} catch (err) {
154+
throw new Error(
155+
`Compartment Map Transform ${q(transform.name)} errored during execution: ${err.message}`,
156+
{ cause: err },
157+
);
158+
}
159+
}
160+
return compartmentMap;
161+
};

0 commit comments

Comments
 (0)