{"version":3,"file":"keygenPublisher.js","sourceRoot":"","sources":["../src/keygenPublisher.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arch, httpExecutor, InvalidConfigurationError, isEmptyOrSpaces, log } from \"builder-util\"\nimport { configureRequestOptions, HttpExecutor, parseJson } from \"builder-util-runtime\"\nimport { KeygenOptions } from \"builder-util-runtime/out/publishOptions\"\nimport { getCompleteExtname } from \"builder-util/out/filename\"\nimport { ClientRequest, RequestOptions } from \"http\"\nimport { PublishContext } from \"./\"\nimport { HttpPublisher } from \"./httpPublisher\"\n\ntype RecursivePartial<T> = {\n  [P in keyof T]?: RecursivePartial<T[P]>\n}\n\nexport interface KeygenError {\n  title: string\n  detail: string\n  code: string\n}\n\nexport interface KeygenRelease {\n  id: string\n  type: \"releases\"\n  attributes: {\n    name: string | null\n    description: string | null\n    channel: \"stable\" | \"rc\" | \"beta\" | \"alpha\" | \"dev\"\n    status: \"DRAFT\" | \"PUBLISHED\" | \"YANKED\"\n    tag: string\n    version: string\n    semver: {\n      major: number\n      minor: number\n      patch: number\n      prerelease: string | null\n      build: string | null\n    }\n    metadata: { [s: string]: any }\n    created: string\n    updated: string\n    yanked: string | null\n  }\n  relationships: {\n    account: {\n      data: { type: \"accounts\"; id: string }\n    }\n    product: {\n      data: { type: \"products\"; id: string }\n    }\n  }\n}\n\nexport interface KeygenArtifact {\n  id: string\n  type: \"artifacts\"\n  attributes: {\n    filename: string\n    filetype: string | null\n    filesize: number | null\n    platform: string | null\n    arch: string | null\n    signature: string | null\n    checksum: string | null\n    status: \"WAITING\" | \"UPLOADED\" | \"FAILED\" | \"YANKED\"\n    metadata: { [s: string]: any }\n    created: string\n    updated: string\n  }\n  relationships: {\n    account: {\n      data: { type: \"accounts\"; id: string }\n    }\n    release: {\n      data: { type: \"releases\"; id: string }\n    }\n  }\n  links: {\n    redirect: string\n  }\n}\n\nexport class KeygenPublisher extends HttpPublisher {\n  readonly providerName = \"keygen\"\n  readonly defaultHostname = \"api.keygen.sh\"\n\n  private readonly info: KeygenOptions\n  private readonly auth: string\n  private readonly version: string\n  private readonly basePath: string\n\n  get hostname() {\n    return this.info.host || this.defaultHostname\n  }\n\n  constructor(context: PublishContext, info: KeygenOptions, version: string) {\n    super(context)\n\n    const token = process.env.KEYGEN_TOKEN\n    if (isEmptyOrSpaces(token)) {\n      throw new InvalidConfigurationError(`Keygen token is not set using env \"KEYGEN_TOKEN\" (see https://www.electron.build/publish#KeygenOptions)`)\n    }\n\n    this.info = info\n    this.auth = `Bearer ${token.trim()}`\n    this.version = version\n    this.basePath = `/v1/accounts/${this.info.account}`\n  }\n\n  protected doUpload(\n    fileName: string,\n    _arch: Arch,\n    dataLength: number,\n    requestProcessor: (request: ClientRequest, reject: (error: Error) => void) => void,\n    _file: string\n  ): Promise<string> {\n    return HttpExecutor.retryOnServerError(async () => {\n      const { data, errors } = await this.getOrCreateRelease()\n      if (errors) {\n        throw new Error(`Keygen - Creating release returned errors: ${JSON.stringify(errors)}`)\n      }\n\n      await this.uploadArtifact(data!.id, fileName, dataLength, requestProcessor)\n\n      return data!.id\n    })\n  }\n\n  private async uploadArtifact(\n    releaseId: any,\n    fileName: string,\n    dataLength: number,\n    requestProcessor: (request: ClientRequest, reject: (error: Error) => void) => void\n  ): Promise<void> {\n    const { data, errors } = await this.createArtifact(releaseId, fileName, dataLength)\n    if (errors) {\n      throw new Error(`Keygen - Creating artifact returned errors: ${JSON.stringify(errors)}`)\n    }\n\n    // Follow the redirect and upload directly to S3-equivalent storage provider\n    const url = new URL(data!.links.redirect)\n    const upload: RequestOptions = {\n      hostname: url.hostname,\n      path: url.pathname + url.search,\n      headers: {\n        \"Content-Length\": dataLength,\n      },\n      timeout: this.info.timeout || undefined,\n    }\n\n    await httpExecutor.doApiRequest(configureRequestOptions(upload, null, \"PUT\"), this.context.cancellationToken, requestProcessor)\n  }\n\n  private async createArtifact(releaseId: any, fileName: string, dataLength: number): Promise<{ data?: KeygenArtifact; errors?: KeygenError[] }> {\n    const upload: RequestOptions = {\n      hostname: this.hostname,\n      path: `${this.basePath}/artifacts`,\n      headers: {\n        \"Content-Type\": \"application/vnd.api+json\",\n        Accept: \"application/vnd.api+json\",\n        \"Keygen-Version\": \"1.1\",\n        Prefer: \"no-redirect\",\n      },\n      timeout: this.info.timeout || undefined,\n    }\n\n    const data: RecursivePartial<KeygenArtifact> = {\n      type: \"artifacts\",\n      attributes: {\n        filename: fileName,\n        filetype: getCompleteExtname(fileName),\n        filesize: dataLength,\n        platform: this.info.platform,\n      },\n      relationships: {\n        release: {\n          data: {\n            type: \"releases\",\n            id: releaseId,\n          },\n        },\n      },\n    }\n\n    log.debug({ data: JSON.stringify(data) }, \"Keygen create artifact\")\n\n    return parseJson(httpExecutor.request(configureRequestOptions(upload, this.auth, \"POST\"), this.context.cancellationToken, { data }))\n  }\n\n  private async getOrCreateRelease(): Promise<{ data?: KeygenRelease; errors?: KeygenError[] }> {\n    try {\n      // First, we'll attempt to fetch the release.\n      return await this.getRelease()\n    } catch (e: any) {\n      if (e.statusCode !== 404) {\n        throw e\n      }\n\n      try {\n        // Next, if the release doesn't exist, we'll attempt to create it.\n        return await this.createRelease()\n      } catch (e: any) {\n        if (e.statusCode !== 409 && e.statusCode !== 422) {\n          throw e\n        }\n\n        // Lastly, when a conflict occurs (in the case of parallel uploads),\n        // we'll try to fetch it one last time.\n        return this.getRelease()\n      }\n    }\n  }\n\n  private async getRelease(): Promise<{ data?: KeygenRelease; errors?: KeygenError[] }> {\n    const req: RequestOptions = {\n      hostname: this.hostname,\n      path: `${this.basePath}/releases/${this.version}?product=${this.info.product}`,\n      headers: {\n        Accept: \"application/vnd.api+json\",\n        \"Keygen-Version\": \"1.1\",\n      },\n      timeout: this.info.timeout || undefined,\n    }\n\n    return parseJson(httpExecutor.request(configureRequestOptions(req, this.auth, \"GET\"), this.context.cancellationToken, null))\n  }\n\n  private async createRelease(): Promise<{ data?: KeygenRelease; errors?: KeygenError[] }> {\n    const req: RequestOptions = {\n      hostname: this.hostname,\n      path: `${this.basePath}/releases`,\n      headers: {\n        \"Content-Type\": \"application/vnd.api+json\",\n        Accept: \"application/vnd.api+json\",\n        \"Keygen-Version\": \"1.1\",\n      },\n      timeout: this.info.timeout || undefined,\n    }\n\n    const data: RecursivePartial<KeygenRelease> = {\n      type: \"releases\",\n      attributes: {\n        version: this.version,\n        channel: this.info.channel || \"stable\",\n        status: \"PUBLISHED\",\n      },\n      relationships: {\n        product: {\n          data: {\n            type: \"products\",\n            id: this.info.product,\n          },\n        },\n      },\n    }\n\n    log.debug({ data: JSON.stringify(data) }, \"Keygen create release\")\n\n    return parseJson(httpExecutor.request(configureRequestOptions(req, this.auth, \"POST\"), this.context.cancellationToken, { data }))\n  }\n\n  async deleteRelease(releaseId: string): Promise<void> {\n    const req: RequestOptions = {\n      hostname: this.hostname,\n      path: `${this.basePath}/releases/${releaseId}`,\n      headers: {\n        Accept: \"application/vnd.api+json\",\n        \"Keygen-Version\": \"1.1\",\n      },\n      timeout: this.info.timeout || undefined,\n    }\n    await httpExecutor.request(configureRequestOptions(req, this.auth, \"DELETE\"), this.context.cancellationToken)\n  }\n\n  toString() {\n    const { account, product, platform } = this.info\n    return `Keygen (account: ${account}, product: ${product}, platform: ${platform}, version: ${this.version})`\n  }\n}\n"]}