import type { AnyResourceManagerDefinition, ResourceManagerDefinition, ManagedResource, } from "./types.js"; const RESOURCE_MANAGER_DEFINITION_BRAND = Symbol.for("pi-workflows.resource-manager-definition"); const RESOURCE_MANAGER_NAME_PATTERN = /^[a-z][a-z0-9-]*$/; export function defineResourceManager( definition: ResourceManagerDefinition, ): ResourceManagerDefinition { assertValidResourceManagerDefinition(definition); if (isResourceManagerDefinition(definition)) { return definition; } Object.defineProperty(definition, RESOURCE_MANAGER_DEFINITION_BRAND, { value: true, enumerable: false, configurable: false, writable: false, }); return definition; } export function isResourceManagerDefinition(value: unknown): value is AnyResourceManagerDefinition { return ( value !== null && typeof value === "object" && (value as Record)[RESOURCE_MANAGER_DEFINITION_BRAND] === true ); } export function assertValidResourceManagerDefinition( definition: ResourceManagerDefinition, ): void { if (definition === null || typeof definition !== "object") { throw new Error("Invalid resource manager definition: expected an object"); } if (!RESOURCE_MANAGER_NAME_PATTERN.test(definition.name)) { throw new Error( `Invalid resource manager definition: name ${JSON.stringify(definition.name)} must match ${RESOURCE_MANAGER_NAME_PATTERN.source}`, ); } if (typeof definition.initialStatus !== "function") { throw new Error("Invalid resource manager definition: initialStatus must be a function"); } if (typeof definition.reconcile !== "function") { throw new Error("Invalid resource manager definition: reconcile must be a function"); } if ( definition.timeoutMs !== undefined && (!Number.isSafeInteger(definition.timeoutMs) || definition.timeoutMs <= 0) ) { throw new Error( "Invalid resource manager definition: timeoutMs must be a positive safe integer", ); } } export function asAnyResourceManagerDefinition( definition: ResourceManagerDefinition, ): AnyResourceManagerDefinition { return definition as unknown as ResourceManagerDefinition; } export function asTypedResource( resource: ManagedResource, ): ManagedResource { return resource as ManagedResource; }