import { normalizeNdcCredentialReference, } from "./credential-reference.mjs"; export const DEVICE_SENSITIVE_REFERENCE_COMMAND_KINDS = Object.freeze([ "device_credential_binding.upsert", "device_credential_binding.revoke", ]); const commandKindSet = new Set(DEVICE_SENSITIVE_REFERENCE_COMMAND_KINDS); const purposePattern = /^[a-z][a-z0-9._-]{1,63}$/; const resolutionPattern = /^[a-z][a-z0-9._-]{1,63}$/; export function isSensitiveReferenceManagementCommand(kind) { return commandKindSet.has(kind); } export function normalizeSensitiveReferenceManagementCommand(kind, input) { if (!commandKindSet.has(kind)) { throw new TypeError("device_sensitive_reference_command_kind_invalid"); } assertPlainObject(input); if (kind === "device_credential_binding.upsert") { assertAllowedKeys(input, [ "projectRef", "deviceRef", "purpose", "credentialRef", ]); return Object.freeze({ projectId: normalizeEntityRef(input.projectRef, "project"), deviceId: normalizeEntityRef(input.deviceRef, "device"), purpose: normalizePattern( input.purpose, purposePattern, "device_credential_purpose_invalid", ), credentialRef: normalizeNdcCredentialReference(input.credentialRef), }); } assertAllowedKeys(input, [ "projectRef", "deviceRef", "purpose", "resolutionCode", ]); return Object.freeze({ projectId: normalizeEntityRef(input.projectRef, "project"), deviceId: normalizeEntityRef(input.deviceRef, "device"), purpose: normalizePattern( input.purpose, purposePattern, "device_credential_purpose_invalid", ), resolutionCode: normalizePattern( input.resolutionCode, resolutionPattern, "device_credential_resolution_code_invalid", ), }); } function normalizeEntityRef(value, prefix) { if (typeof value !== "string") { throw new TypeError(`device_${prefix}_ref_invalid`); } const match = value.match(new RegExp( `^${prefix}:([0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})$`, "i", )); if (!match) throw new TypeError(`device_${prefix}_ref_invalid`); return match[1].toLowerCase(); } function normalizePattern(value, pattern, code) { if (typeof value !== "string" || !pattern.test(value)) { throw new TypeError(code); } return value; } function assertPlainObject(value) { if (!value || typeof value !== "object" || Array.isArray(value)) { throw new TypeError("device_sensitive_reference_command_invalid"); } } function assertAllowedKeys(input, allowed) { const allowedSet = new Set(allowed); for (const key of Object.keys(input)) { if (!allowedSet.has(key)) { throw new TypeError(`device_management_command_field_unexpected:${key}`); } } }