OverviewFilesCommitsIssuesDocsReleasesPeers

pear-git / lib / facades / deploy-facade.js

116 lines · javascript ref:
/**
 * DeployFacade — SharedDeployRegistry-compatible facade over unified MetadataBase
 *
 * Implements the exact same public API as SharedDeployRegistry but delegates
 * all operations to MetadataBase. Zero changes needed in route files.
 *
 * Key renames: app:{repoName} → deploy:{repoName}
 */

export class DeployFacade {
  constructor ({ metadataBase }) {
    this._meta = metadataBase
  }

  // ── Properties (delegate to MetadataBase) ────────────────────

  get bootstrapKey () { return this._meta.key }
  get bootstrapKeyHex () { return this._meta.bootstrapKeyHex }
  get discoveryKey () { return this._meta.discoveryKey }
  get localKey () { return this._meta.localKey }
  get writable () { return this._meta.writable }
  get view () { return this._meta.view }

  // Expose _base for wakeup protocol compatibility
  get _base () { return this._meta._base }

  async ready () {}

  // ── Write operations ─────────────────────────────────────────

  async registerServer (serverKey, opts = {}) {
    await this._meta.append({
      v: 2,
      ns: 'deploy',
      type: 'register-server',
      serverKey,
      instanceUrl: opts.instanceUrl || null,
      hostname: opts.hostname || null,
      timestamp: Date.now()
    })
  }

  async deployComplete (repoName, opts) {
    await this._meta.append({
      v: 2,
      ns: 'deploy',
      type: 'deploy-complete',
      repoName,
      commitHash: opts.commitHash,
      branch: opts.branch,
      channel: opts.channel || repoName,
      serverKey: opts.serverKey || null,
      timestamp: Date.now()
    })
  }

  async addWriter (writerKey) {
    const keyHex = Buffer.isBuffer(writerKey) ? writerKey.toString('hex') : writerKey
    await this._meta.append({
      v: 2,
      ns: 'deploy',
      type: 'add-writer',
      writerKey: keyHex,
      timestamp: Date.now()
    })
  }

  // ── Read operations ──────────────────────────────────────────

  async getServer (serverKey) {
    return this._meta.getByKey(`server:${serverKey}`)
  }

  async listServers () {
    return this._meta.list('server')
  }

  async getApp (repoName) {
    return this._meta.getByKey(`deploy:${repoName}`)
  }

  async listApps () {
    return this._meta.list('deploy')
  }

  async getDeployLog (repoName, opts = {}) {
    await this._meta.update()
    const results = []
    const limit = opts.limit || 50
    for await (const entry of this._meta.view.createReadStream({
      gt: `deploy-log:${repoName}:`,
      lt: `deploy-log:${repoName}:\xff`,
      reverse: true,
      limit
    })) {
      results.push(entry.value)
    }
    return results
  }

  // ── Lifecycle ────────────────────────────────────────────────

  async replicate (stream) {
    // Replication handled by MetadataBase's corestore
    return stream
  }

  async update () {
    await this._meta.update()
  }

  async close () {
    // MetadataBase owns the Autobase lifecycle
  }
}