refactor IntegrityMetadataSet for improved structure and flexible input

This commit is contained in:
Nebel 2024-10-02 17:50:02 +09:00
parent f538f67971
commit f7ac85b913
Signed by: nebel
GPG key ID: 79807D08C6EF6460

View file

@ -115,58 +115,66 @@ export async function createIntegrityMetadata(
/** Integrity Metadata Set Options */ /** Integrity Metadata Set Options */
export type IntegrityMetadataSetOptions = { export type IntegrityMetadataSetOptions = {
getPrioritizedHashAlgorithm: GetPrioritizedHashAlgorithm; getPrioritizedHashAlgorithm?: GetPrioritizedHashAlgorithm;
}; };
/** Integrity Metadata Set */ /** Integrity Metadata Set */
export class IntegrityMetadataSet extends Map< export class IntegrityMetadataSet {
HashAlgorithm, /** [W3C Subresource Integrity 3.3.4 Get the strongest metadata from set.](https://www.w3.org/TR/SRI/#get-the-strongest-metadata-from-set) */
IntegrityMetadata readonly strongest: Array<IntegrityMetadata> = [];
> {
getPrioritizedHashAlgorithm: GetPrioritizedHashAlgorithm; #set: ReadonlyArray<IntegrityMetadata>;
constructor( constructor(
integrity: string, integrity:
options: IntegrityMetadataSetOptions = { | ReadonlyArray<IntegrityMetadataLike | string | null | undefined>
getPrioritizedHashAlgorithm, | IntegrityMetadataLike
}, | string
| null
| undefined,
{
getPrioritizedHashAlgorithm:
_getPrioritizedHashAlgorithm = getPrioritizedHashAlgorithm,
}: IntegrityMetadataSetOptions = {},
) { ) {
super(); const set: ReadonlyArray<
IntegrityMetadataLike | string | null | undefined
> = [integrity]
.flat()
.flatMap(
(
integrity: IntegrityMetadataLike | string | null | undefined,
): ReadonlyArray<IntegrityMetadataLike | string | null | undefined> =>
typeof integrity === "string"
? integrity.split(SeparatorRegex)
: [integrity],
);
const integrityMetadata = integrity.split(SeparatorRegex); this.#set = set
.map((integrity) => new IntegrityMetadata(integrity))
.filter((integrityMetadata) => integrityMetadata.toString() !== "");
for (const integrity of integrityMetadata.filter(Boolean)) { for (const integrityMetadata of this.#set) {
const integrityMetadata = new IntegrityMetadata(integrity); const [strongest = new IntegrityMetadata("")] = this.strongest;
if (integrityMetadata.alg) { const prioritizedHashAlgorithm = _getPrioritizedHashAlgorithm(
this.set(integrityMetadata.alg, integrityMetadata); strongest.alg as HashAlgorithm,
integrityMetadata.alg as HashAlgorithm,
);
switch (prioritizedHashAlgorithm) {
case "":
this.strongest.push(integrityMetadata);
break;
case integrityMetadata.alg:
this.strongest = [integrityMetadata];
break;
} }
} }
this.getPrioritizedHashAlgorithm = options.getPrioritizedHashAlgorithm;
} }
/** [W3C Subresource Integrity 3.3.4 Get the strongest metadata from set.](https://www.w3.org/TR/SRI/#get-the-strongest-metadata-from-set) */ join(separator = " "): string {
get strongest(): IntegrityMetadata { return this.#set.map(String).join(separator);
const [hashAlgorithm = "sha512"]: ReadonlyArray<HashAlgorithm> = [
...this.keys(),
].sort((a, b) => {
switch (this.getPrioritizedHashAlgorithm(a, b)) {
default:
case "":
return 0;
case a:
return -1;
case b:
return +1;
}
});
return this.get(hashAlgorithm) ?? new IntegrityMetadata("");
}
join(separator = " ") {
return [...this.values()].map(String).join(separator);
} }
toString(): string { toString(): string {