46 lines
1.7 KiB
JavaScript
46 lines
1.7 KiB
JavaScript
export const PHASE_EXTRACTED_APP = "extracted-app";
|
|
export const PHASE_MAIN_BUNDLE = "main-bundle";
|
|
|
|
export const PATCH_PHASES = [PHASE_EXTRACTED_APP, PHASE_MAIN_BUNDLE];
|
|
|
|
const ID_PATTERN = /^[a-z0-9][a-z0-9-]*$/;
|
|
|
|
export function definePatch(descriptor) {
|
|
if (descriptor == null || typeof descriptor !== "object" || Array.isArray(descriptor)) {
|
|
throw new TypeError("Patch descriptor must be an object");
|
|
}
|
|
if (typeof descriptor.id !== "string" || !ID_PATTERN.test(descriptor.id)) {
|
|
throw new TypeError(`Patch descriptor id must match ${ID_PATTERN}`);
|
|
}
|
|
if (!PATCH_PHASES.includes(descriptor.phase)) {
|
|
throw new TypeError(`Patch '${descriptor.id}' has unsupported phase '${descriptor.phase}'`);
|
|
}
|
|
if (!Number.isInteger(descriptor.order)) {
|
|
throw new TypeError(`Patch '${descriptor.id}' order must be an integer`);
|
|
}
|
|
if (typeof descriptor.required !== "boolean") {
|
|
throw new TypeError(`Patch '${descriptor.id}' required must be a boolean`);
|
|
}
|
|
if (typeof descriptor.apply !== "function") {
|
|
throw new TypeError(`Patch '${descriptor.id}' must export an apply function`);
|
|
}
|
|
|
|
return Object.freeze({ ...descriptor });
|
|
}
|
|
|
|
export function normalizeDescriptors(descriptors) {
|
|
const normalized = descriptors.map(definePatch);
|
|
const seen = new Set();
|
|
for (const descriptor of normalized) {
|
|
if (seen.has(descriptor.id)) {
|
|
throw new Error(`Duplicate patch descriptor id '${descriptor.id}'`);
|
|
}
|
|
seen.add(descriptor.id);
|
|
}
|
|
|
|
return [...normalized].sort((left, right) => {
|
|
const phaseOrder = PATCH_PHASES.indexOf(left.phase) - PATCH_PHASES.indexOf(right.phase);
|
|
return phaseOrder || left.order - right.order || left.id.localeCompare(right.id);
|
|
});
|
|
}
|