{"version":3,"file":"utils.mjs","sources":["../../../src/strapi/providers/utils.ts"],"sourcesContent":["import { randomUUID } from 'crypto';\nimport { RawData, WebSocket } from 'ws';\n\nimport type { Client, Server } from '../../../types/remote/protocol';\n\nimport {\n  ProviderError,\n  ProviderTransferError,\n  ProviderInitializationError,\n  ProviderValidationError,\n  ProviderErrorDetails,\n} from '../../errors/providers';\nimport { IDiagnosticReporter } from '../../utils/diagnostic';\n\ninterface IDispatcherState {\n  transfer?: { kind: Client.TransferKind; id: string };\n}\n\ninterface IDispatchOptions {\n  attachTransfer?: boolean;\n}\n\ntype Dispatch<T> = Omit<T, 'transferID' | 'uuid'>;\n\nexport const createDispatcher = (\n  ws: WebSocket,\n  retryMessageOptions = {\n    retryMessageMaxRetries: 5,\n    retryMessageTimeout: 30000,\n  },\n  reportInfo?: (message: string) => void\n) => {\n  const state: IDispatcherState = {};\n\n  type DispatchMessage = Dispatch<Client.Message>;\n\n  const dispatch = async <U = null>(\n    message: DispatchMessage,\n    options: IDispatchOptions = {}\n  ): Promise<U | null> => {\n    if (!ws) {\n      throw new Error('No websocket connection found');\n    }\n\n    return new Promise<U | null>((resolve, reject) => {\n      const uuid = randomUUID();\n      const payload = { ...message, uuid };\n      let numberOfTimesMessageWasSent = 0;\n\n      if (options.attachTransfer) {\n        Object.assign(payload, { transferID: state.transfer?.id });\n      }\n\n      if (message.type === 'command') {\n        reportInfo?.(\n          `dispatching message command:${(message as Client.CommandMessage).command} uuid:${uuid} sent:${numberOfTimesMessageWasSent}`\n        );\n      } else if (message.type === 'transfer') {\n        const messageToSend = message as Client.TransferMessage;\n        reportInfo?.(\n          `dispatching message action:${messageToSend.action} ${messageToSend.kind === 'step' ? `step:${messageToSend.step}` : ''} uuid:${uuid} sent:${numberOfTimesMessageWasSent}`\n        );\n      }\n      const stringifiedPayload = JSON.stringify(payload);\n      ws.send(stringifiedPayload, (error) => {\n        if (error) {\n          reject(error);\n        }\n      });\n      const { retryMessageMaxRetries, retryMessageTimeout } = retryMessageOptions;\n      const sendPeriodically = () => {\n        if (numberOfTimesMessageWasSent <= retryMessageMaxRetries) {\n          numberOfTimesMessageWasSent += 1;\n          ws.send(stringifiedPayload, (error) => {\n            if (error) {\n              reject(error);\n            }\n          });\n        } else {\n          reject(new ProviderError('error', 'Request timed out'));\n        }\n      };\n      const interval = setInterval(sendPeriodically, retryMessageTimeout);\n\n      const onResponse = (raw: RawData) => {\n        const response: Server.Message<U> = JSON.parse(raw.toString());\n        if (message.type === 'command') {\n          reportInfo?.(\n            `received response to message command: ${(message as Client.CommandMessage).command} uuid: ${uuid} sent: ${numberOfTimesMessageWasSent}`\n          );\n        } else if (message.type === 'transfer') {\n          const messageToSend = message as Client.TransferMessage;\n          reportInfo?.(\n            `received response to message action:${messageToSend.action} ${messageToSend.kind === 'step' ? `step:${messageToSend.step}` : ''} uuid:${uuid} sent:${numberOfTimesMessageWasSent}`\n          );\n        }\n        if (response.uuid === uuid) {\n          clearInterval(interval);\n          if (response.error) {\n            const message = response.error.message;\n            const details = response.error.details?.details as ProviderErrorDetails;\n            const step = response.error.details?.step;\n            let error = new ProviderError('error', message, details);\n            if (step === 'transfer') {\n              error = new ProviderTransferError(message, details);\n            } else if (step === 'validation') {\n              error = new ProviderValidationError(message, details);\n            } else if (step === 'initialization') {\n              error = new ProviderInitializationError(message);\n            }\n            return reject(error);\n          }\n          resolve(response.data ?? null);\n        } else {\n          ws.once('message', onResponse);\n        }\n      };\n\n      ws.once('message', onResponse);\n    });\n  };\n\n  const dispatchCommand = <U extends Client.Command>(\n    payload: {\n      command: U;\n    } & ([Client.GetCommandParams<U>] extends [never]\n      ? unknown\n      : { params?: Client.GetCommandParams<U> })\n  ) => {\n    return dispatch({ type: 'command', ...payload } as Client.CommandMessage);\n  };\n\n  const dispatchTransferAction = async <T>(action: Client.Action['action']) => {\n    const payload: Dispatch<Client.Action> = { type: 'transfer', kind: 'action', action };\n\n    return dispatch<T>(payload, { attachTransfer: true }) ?? Promise.resolve(null);\n  };\n\n  const dispatchTransferStep = async <\n    T,\n    A extends Client.TransferPushMessage['action'] = Client.TransferPushMessage['action'],\n    S extends Client.TransferPushStep = Client.TransferPushStep,\n  >(\n    payload: {\n      step: S;\n      action: A;\n    } & (A extends 'stream' ? { data: Client.GetTransferPushStreamData<S> } : unknown)\n  ) => {\n    const message: Dispatch<Client.TransferPushMessage> = {\n      type: 'transfer',\n      kind: 'step',\n      ...payload,\n    };\n\n    return dispatch<T>(message, { attachTransfer: true }) ?? Promise.resolve(null);\n  };\n\n  const setTransferProperties = (\n    properties: Exclude<IDispatcherState['transfer'], undefined>\n  ): void => {\n    state.transfer = { ...properties };\n  };\n\n  return {\n    get transferID() {\n      return state.transfer?.id;\n    },\n\n    get transferKind() {\n      return state.transfer?.kind;\n    },\n\n    setTransferProperties,\n\n    dispatch,\n    dispatchCommand,\n    dispatchTransferAction,\n    dispatchTransferStep,\n  };\n};\n\ntype WebsocketParams = ConstructorParameters<typeof WebSocket>;\ntype Address = WebsocketParams[0];\ntype Options = WebsocketParams[2];\n\nexport const connectToWebsocket = (\n  address: Address,\n  options?: Options,\n  diagnostics?: IDiagnosticReporter\n): Promise<WebSocket> => {\n  return new Promise((resolve, reject) => {\n    const server = new WebSocket(address, options);\n    server.once('open', () => {\n      resolve(server);\n    });\n\n    server.on('unexpected-response', (_req, res) => {\n      if (res.statusCode === 401) {\n        return reject(\n          new ProviderInitializationError(\n            'Failed to initialize the connection: Authentication Error'\n          )\n        );\n      }\n\n      if (res.statusCode === 403) {\n        return reject(\n          new ProviderInitializationError(\n            'Failed to initialize the connection: Authorization Error'\n          )\n        );\n      }\n\n      if (res.statusCode === 404) {\n        return reject(\n          new ProviderInitializationError(\n            'Failed to initialize the connection: Data transfer is not enabled on the remote host'\n          )\n        );\n      }\n\n      return reject(\n        new ProviderInitializationError(\n          `Failed to initialize the connection: Unexpected server response ${res.statusCode}`\n        )\n      );\n    });\n\n    server.on('message', (raw: RawData) => {\n      const response: Server.Message = JSON.parse(raw.toString());\n      if (response.diagnostic) {\n        diagnostics?.report({\n          ...response.diagnostic,\n        });\n      }\n    });\n\n    server.once('error', (err) => {\n      reject(\n        new ProviderTransferError(err.message, {\n          details: {\n            error: err.message,\n          },\n        })\n      );\n    });\n  });\n};\n\nexport const trimTrailingSlash = (input: string): string => {\n  return input.replace(/\\/$/, '');\n};\n\nexport const wait = (ms: number) => {\n  return new Promise<void>((resolve) => {\n    setTimeout(resolve, ms);\n  });\n};\n\nexport const waitUntil = async (test: () => boolean, interval: number): Promise<void> => {\n  while (!test()) {\n    await wait(interval);\n  }\n\n  return Promise.resolve();\n};\n"],"names":["createDispatcher","ws","retryMessageOptions","retryMessageMaxRetries","retryMessageTimeout","reportInfo","state","dispatch","message","options","Error","Promise","resolve","reject","uuid","randomUUID","payload","numberOfTimesMessageWasSent","attachTransfer","Object","assign","transferID","transfer","id","type","command","messageToSend","action","kind","step","stringifiedPayload","JSON","stringify","send","error","sendPeriodically","ProviderError","interval","setInterval","onResponse","raw","response","parse","toString","clearInterval","details","ProviderTransferError","ProviderValidationError","ProviderInitializationError","data","once","dispatchCommand","dispatchTransferAction","dispatchTransferStep","setTransferProperties","properties","transferKind","connectToWebsocket","address","diagnostics","server","WebSocket","on","_req","res","statusCode","diagnostic","report","err","trimTrailingSlash","input","replace"],"mappings":"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"}