1import {
2 alchemyLabelKeys,
3 createInternalLabels,
4 hasAlchemyLabels,
5} from "../Labels.ts";
6
7export { createInternalLabels, hasAlchemyLabels };
8
9/**
10 * Stamp Alchemy ownership into a description. Used by Network Security
11 * resources that have no labels field (UrlList, TlsInspectionPolicy).
12 */
13export const encodeDescription = (
14 labels: Record<string, string>,
15 description: string | undefined,
16): string => {
17 const marker = `[alchemy ${alchemyLabelKeys.stack}=${labels[alchemyLabelKeys.stack]} ${alchemyLabelKeys.stage}=${labels[alchemyLabelKeys.stage]} ${alchemyLabelKeys.id}=${labels[alchemyLabelKeys.id]}]`;
18 return description ? `${marker}\n${description}` : marker;
19};
20
21export const parseDescription = (
22 description: string | undefined,
23): {
24 labels: Record<string, string>;
25 description: string | undefined;
26} => {
27 if (!description?.startsWith("[alchemy ")) {
28 return { labels: {}, description };
29 }
30 const end = description.indexOf("]");
31 if (end < 0) return { labels: {}, description };
32 const labels: Record<string, string> = {};
33 for (const part of description.slice("[alchemy ".length, end).split(/\s+/)) {
34 const eq = part.indexOf("=");
35 if (eq > 0) {
36 labels[part.slice(0, eq)] = part.slice(eq + 1);
37 }
38 }
39 const rest = description.slice(end + 1).replace(/^\n/, "");
40 return { labels, description: rest.length > 0 ? rest : undefined };
41};
42
43export const hasOwnershipMarker = (description: string | undefined) =>
44 Object.keys(parseDescription(description).labels).some((key) =>
45 key.startsWith("alchemy-"),
46 );
47
48export const sameJson = (left: unknown, right: unknown) =>
49 JSON.stringify(left ?? null) === JSON.stringify(right ?? null);
50
51export const sameStringList = (
52 left: readonly string[] | undefined,
53 right: readonly string[] | undefined,
54) => JSON.stringify([...(left ?? [])]) === JSON.stringify([...(right ?? [])]);