import { fromJson } from "@bufbuild/protobuf"; import type { Value as ValueProto } from "@bufbuild/protobuf/wkt"; import { StructSchema, timestampFromDate } from "@bufbuild/protobuf/wkt"; import type { Value } from "@cerbos/core"; import type { ChangeDetails as ChangeDetailsProto, ChangeDetails_Git, ChangeDetails_Internal, ChangeDetails_Uploader, FileFilter as FileFilterProto, FileOp as FileOpProto, File as FileProto, GetFilesRequest as GetFilesRequestProto, ListFilesRequest as ListFilesRequestProto, ModifyFilesRequest as ModifyFilesRequestProto, ModifyFilesRequest_Condition, ReplaceFilesRequest as ReplaceFilesRequestProto, ReplaceFilesRequest_Condition, StringMatch as StringMatchProto, } from "../protobuf/cerbos/cloud/store/v1/store_pb.js"; import type { MessageInit } from "../protobuf.js"; import type { ChangeDetails, ChangeOrigin, ChangeOriginGit, ChangeOriginInternal, File, FileFilter, FileModificationCondition, FileOperation, GetFilesRequest, ListFilesRequest, ModifyFilesRequest, ReplaceFilesContents, ReplaceFilesRequest, StringMatch, Uploader, } from "../types.js"; import { changeOriginIsChangeOriginGit, changeOriginIsChangeOriginInternal, fileOperationIsFileOperationAddOrUpdate, fileOperationIsFileOperationDelete, replaceFilesContentsIsReplaceFilesContentsUnzipped, replaceFilesContentsIsReplaceFilesContentsZipped, stringMatchIsStringMatchContains, stringMatchIsStringMatchEquals, stringMatchIsStringMatchIn, } from "../types.js"; function changeDetailsToProto({ description, origin, uploader, }: ChangeDetails): MessageInit { return { description: description ?? "", origin: changeOriginToProto(origin), uploader: uploader && uploaderToProto(uploader), }; } function changeOriginToProto( origin: ChangeOrigin | undefined, ): MessageInit["origin"] { if (!origin) { return { case: undefined, value: undefined }; } if (changeOriginIsChangeOriginGit(origin)) { return { case: "git", value: changeOriginGitToProto(origin) }; } if (changeOriginIsChangeOriginInternal(origin)) { return { case: "internal", value: changeOriginInternalToProto(origin) }; } throw new Error("Unknown ChangeOrigin type"); } function changeOriginGitToProto({ repo, ref, hash, message, committer, commitDate, author, authorDate, }: ChangeOriginGit): MessageInit { return { repo: repo ?? "", ref: ref ?? "", hash: hash ?? "", message: message ?? "", committer: committer ?? "", commitDate: commitDate && timestampFromDate(commitDate), author: author ?? "", authorDate: authorDate && timestampFromDate(authorDate), }; } function changeOriginInternalToProto({ source, metadata, }: ChangeOriginInternal): MessageInit { return { source: source ?? "", metadata: mapToProto(metadata ?? {}), }; } function fileFilterToProto({ path }: FileFilter): MessageInit { return { path: path && stringMatchToProto(path), }; } function fileOperationToProto( operation: FileOperation, ): MessageInit { if (fileOperationIsFileOperationAddOrUpdate(operation)) { return { op: { case: "addOrUpdate", value: operation.addOrUpdate } }; } if (fileOperationIsFileOperationDelete(operation)) { return { op: { case: "delete", value: operation.delete } }; } throw new Error("Unknown FileOperation type"); } function fileToProto({ path, contents }: File): MessageInit { return { path, contents }; } export function getFilesRequestToProto({ storeId, files, }: GetFilesRequest): MessageInit { return { storeId, files, }; } export function listFilesRequestToProto({ storeId, filter, }: ListFilesRequest): MessageInit { return { storeId, filter: filter && fileFilterToProto(filter), }; } function mapToProto( map: Record, ): Record> { return fromJson(StructSchema, map).fields; } function modifyFilesConditionToProto({ storeVersionMustEqual, }: FileModificationCondition): MessageInit { return { storeVersionMustEqual, }; } export function modifyFilesRequestToProto({ storeId, operations, condition, changeDetails, }: ModifyFilesRequest): MessageInit { return { storeId, operations: operations.map(fileOperationToProto), condition: condition && modifyFilesConditionToProto(condition), changeDetails: changeDetails && changeDetailsToProto(changeDetails), }; } function replaceFilesConditionToProto({ storeVersionMustEqual, }: FileModificationCondition): MessageInit { return { storeVersionMustEqual, }; } function replaceFilesContentsToProto( contents: ReplaceFilesContents, ): MessageInit["contents"] { if (replaceFilesContentsIsReplaceFilesContentsUnzipped(contents)) { return { case: "files", value: { files: contents.files.map(fileToProto) } }; } if (replaceFilesContentsIsReplaceFilesContentsZipped(contents)) { return { case: "zippedContents", value: contents.zipped }; } throw new Error("Unknown ReplaceFilesContents type"); } export function replaceFilesRequestToProto({ storeId, contents, condition, changeDetails, }: ReplaceFilesRequest): MessageInit { return { storeId, contents: replaceFilesContentsToProto(contents), condition: condition && replaceFilesConditionToProto(condition), changeDetails: changeDetails && changeDetailsToProto(changeDetails), }; } function stringMatchToProto(match: StringMatch): MessageInit { if (stringMatchIsStringMatchEquals(match)) { return { match: { case: "equals", value: match.equals } }; } if (stringMatchIsStringMatchContains(match)) { return { match: { case: "contains", value: match.contains } }; } if (stringMatchIsStringMatchIn(match)) { return { match: { case: "in", value: { values: match.in } } }; } throw new Error("Unknown StringMatch type"); } function uploaderToProto({ name, metadata, }: Uploader): MessageInit { return { name: name ?? "", metadata: mapToProto(metadata ?? {}), }; }