{
  "version": 3,
  "sources": ["../../../../src/packages/server/createServer.ts"],
  "sourcesContent": ["import assert from 'node:assert';\nimport http, {\n  type IncomingMessage,\n  type Server,\n  type ServerResponse,\n} from 'node:http';\nimport util from 'node:util';\nimport { globalInfo } from '../logger/index.ts';\nimport type {\n  FetchPackageToStoreOptions,\n  PackageResponse,\n  PkgRequestFetchResult,\n  RequestPackageOptions,\n  StoreController,\n  UploadPkgToStoreOpts,\n} from '../store-controller-types/index.ts';\nimport { locking } from './lock.ts';\nimport type { ImportPackageOpts } from '../cafs-types/index.ts';\nimport type { WantedDependency } from '../resolve-dependencies/index.ts';\n\ntype RequestPackageBody = {\n  msgId: string;\n  wantedDependency: WantedDependency;\n  options: RequestPackageOptions;\n  prefix: string;\n  opts: {\n    addDependencies: string[];\n    removeDependencies: string[];\n    prune: boolean;\n  };\n  storePath: string;\n  id: string;\n  searchQueries: string[];\n};\n\ntype FetchPackageBody = {\n  msgId: string;\n  wantedDependency: WantedDependency;\n  options: FetchPackageToStoreOptions;\n  prefix: string;\n  opts: {\n    addDependencies: string[];\n    removeDependencies: string[];\n    prune: boolean;\n  };\n  storePath: string;\n  id: string;\n  searchQueries: string[];\n};\n\nexport type StoreServerHandle = {\n  close: () => Promise<void>;\n  waitForClose: Promise<void>;\n};\n\nexport function createServer(\n  store: StoreController<\n    PackageResponse,\n    PackageResponse,\n    { isBuilt: boolean; importMethod?: string | undefined }\n  >,\n  opts: {\n    path?: string | undefined;\n    port?: number | undefined;\n    hostname?: string | undefined;\n    ignoreStopRequests?: boolean | undefined;\n    ignoreUploadRequests?: boolean | undefined;\n  }\n): StoreServerHandle {\n  const filesPromises: Record<\n    string,\n    (() => Promise<PkgRequestFetchResult<PackageResponse>>) | undefined\n  > = {};\n\n  const lock = locking<void>();\n\n  const server = http.createServer(\n    async (req: IncomingMessage, res: ServerResponse) => {\n      if (req.method !== 'POST') {\n        res.statusCode = 405; // Method Not Allowed\n        const responseError = {\n          error: `Only POST is allowed, received ${req.method ?? 'unknown'}`,\n        };\n        res.setHeader('Allow', 'POST');\n        res.end(JSON.stringify(responseError));\n        return;\n      }\n\n      try {\n        let requestPackageBody: RequestPackageBody;\n        let fetchPackageBody: FetchPackageBody;\n\n        switch (req.url) {\n          case '/requestPackage': {\n            const bodyPromise = new Promise<RequestPackageBody>(\n              (resolve, reject): void => {\n                let body: any = ''; // eslint-disable-line\n\n                req.on('data', (data) => {\n                  body += data;\n                });\n\n                req.on('end', async () => {\n                  try {\n                    if (body.length > 0) {\n                      body = JSON.parse(body);\n                    } else {\n                      body = {};\n                    }\n                    resolve(body);\n                    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n                  } catch (e: any) {\n                    reject(e);\n                  }\n                });\n              }\n            );\n\n            try {\n              requestPackageBody = await bodyPromise;\n\n              const pkgResponse = await store.requestPackage(\n                requestPackageBody.wantedDependency,\n                requestPackageBody.options\n              );\n\n              if (typeof pkgResponse.fetching === 'function') {\n                filesPromises[requestPackageBody.msgId] = pkgResponse.fetching;\n              }\n\n              res.end(JSON.stringify(pkgResponse.body));\n            } catch (err: unknown) {\n              assert(util.types.isNativeError(err));\n\n              res.end(\n                JSON.stringify({\n                  error: {\n                    message: err.message,\n                    ...(JSON.parse(JSON.stringify(err)) as Record<\n                      string,\n                      unknown\n                    >),\n                  },\n                })\n              );\n            }\n\n            break;\n          }\n\n          case '/fetchPackage': {\n            const bodyPromise = new Promise<FetchPackageBody>(\n              (resolve, reject): void => {\n                let body: any = ''; // eslint-disable-line\n\n                req.on('data', (data) => {\n                  body += data;\n                });\n\n                req.on('end', async () => {\n                  try {\n                    if (body.length > 0) {\n                      body = JSON.parse(body);\n                    } else {\n                      body = {};\n                    }\n                    resolve(body);\n                    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n                  } catch (e: any) {\n                    reject(e);\n                  }\n                });\n              }\n            );\n\n            try {\n              fetchPackageBody = await bodyPromise;\n\n              const pkgResponse = await store.fetchPackage(\n                fetchPackageBody.options\n              );\n\n              filesPromises[fetchPackageBody.msgId] = pkgResponse.fetching;\n\n              res.end(\n                JSON.stringify({ filesIndexFile: pkgResponse.filesIndexFile })\n              );\n            } catch (err: unknown) {\n              assert(util.types.isNativeError(err));\n              res.end(\n                JSON.stringify({\n                  error: {\n                    message: err.message,\n                    ...(JSON.parse(JSON.stringify(err)) as Record<\n                      string,\n                      unknown\n                    >),\n                  },\n                })\n              );\n            }\n            break;\n          }\n\n          case '/packageFilesResponse': {\n            const bodyPromise = new Promise<RequestPackageBody>(\n              (resolve, reject): void => {\n                let body: any = ''; // eslint-disable-line\n\n                req.on('data', (data) => {\n                  body += data;\n                });\n\n                req.on('end', async () => {\n                  try {\n                    if (body.length > 0) {\n                      body = JSON.parse(body);\n                    } else {\n                      body = {};\n                    }\n                    resolve(body);\n                    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n                  } catch (e: any) {\n                    reject(e);\n                  }\n                });\n              }\n            );\n\n            const body = await bodyPromise;\n\n            const filesResponse = await filesPromises[body.msgId]?.();\n\n            delete filesPromises[body.msgId];\n\n            res.end(JSON.stringify(filesResponse));\n\n            break;\n          }\n\n          case '/prune': {\n            // Disable store pruning when a server is running\n            res.statusCode = 403;\n            res.end();\n            break;\n          }\n\n          case '/importPackage': {\n            const bodyPromise = new Promise<{\n              to: string;\n              opts: ImportPackageOpts;\n            }>((resolve, reject): void => {\n              let body: any = ''; // eslint-disable-line\n\n              req.on('data', (data) => {\n                body += data;\n              });\n\n              req.on('end', async () => {\n                try {\n                  if (body.length > 0) {\n                    body = JSON.parse(body);\n                  } else {\n                    body = {};\n                  }\n                  resolve(body);\n                  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n                } catch (e: any) {\n                  reject(e);\n                }\n              });\n            });\n\n            const importPackageBody = await bodyPromise;\n\n            await store.importPackage(\n              importPackageBody.to,\n              importPackageBody.opts\n            );\n\n            res.end(JSON.stringify('OK'));\n\n            break;\n          }\n\n          case '/upload': {\n            // Do not return an error status code, just ignore the upload request entirely\n            if (opts.ignoreUploadRequests === true) {\n              res.statusCode = 403;\n\n              res.end();\n\n              break;\n            }\n\n            const bodyPromise = new Promise<{\n              builtPkgLocation: string;\n              opts: UploadPkgToStoreOpts;\n            }>((resolve, reject): void => {\n              let body: any = ''; // eslint-disable-line\n\n              req.on('data', (data) => {\n                body += data;\n              });\n\n              req.on('end', async () => {\n                try {\n                  if (body.length > 0) {\n                    body = JSON.parse(body);\n                  } else {\n                    body = {};\n                  }\n                  resolve(body);\n                  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n                } catch (e: any) {\n                  reject(e);\n                }\n              });\n            });\n\n            const uploadBody = await bodyPromise;\n\n            await lock(uploadBody.builtPkgLocation, async () =>\n              store.upload(uploadBody.builtPkgLocation, uploadBody.opts)\n            );\n\n            res.end(JSON.stringify('OK'));\n\n            break;\n          }\n\n          case '/stop': {\n            if (opts.ignoreStopRequests === true) {\n              res.statusCode = 403;\n\n              res.end();\n\n              break;\n            }\n\n            globalInfo('Got request to stop the server');\n\n            await close();\n\n            res.end(JSON.stringify('OK'));\n\n            globalInfo('Server stopped');\n\n            break;\n          }\n\n          default: {\n            res.statusCode = 404;\n\n            const error = {\n              error: `${req.url ?? ''} does not match any route`,\n            };\n\n            res.end(JSON.stringify(error));\n          }\n        }\n        // eslint-disable-next-line @typescript-eslint/no-explicit-any\n      } catch (e: any) {\n        res.statusCode = 503;\n\n        const jsonErr = JSON.parse(JSON.stringify(e)) as Record<\n          string,\n          unknown\n        >;\n\n        jsonErr.message = e.message;\n\n        res.end(JSON.stringify(jsonErr));\n      }\n    }\n  );\n\n  let listener: Server;\n\n  if (typeof opts.path === 'string') {\n    listener = server.listen(opts.path);\n  } else {\n    listener = server.listen(opts.port, opts.hostname);\n  }\n\n  const waitForClose = new Promise<void>((resolve) =>\n    listener.once('close', () => {\n      resolve();\n    })\n  );\n\n  return { close, waitForClose };\n\n  async function close(): Promise<void> {\n    listener.close();\n    return store.close();\n  }\n}\n"],
  "mappings": "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",
  "names": ["body"]
}
