OverviewFilesCommitsIssuesDocsReleasesPeers

pear-git / scripts / old-apply / repo-operations.js

119 lines · javascript ref:
/**
 * Autobase Operation Types for Linked Repos
 *
 * Defines operation constants, JSON encode/decode, and validation
 * for all Autobase-managed collaborative metadata.
 *
 * Operations are appended to Autobase writer cores and processed
 * by the deterministic apply function to build the Hyperbee view.
 */

// Writer management
export const OP_ADD_WRITER = 'add-writer'
export const OP_REMOVE_WRITER = 'remove-writer'

// Git refs (appended after successful push)
export const OP_UPDATE_REF = 'update-ref'
export const OP_DELETE_REF = 'delete-ref'

// Issues
export const OP_CREATE_ISSUE = 'create-issue'
export const OP_UPDATE_ISSUE = 'update-issue'
export const OP_CREATE_COMMENT = 'create-comment'

// Labels
export const OP_CREATE_LABEL = 'create-label'
export const OP_UPDATE_LABEL = 'update-label'
export const OP_DELETE_LABEL = 'delete-label'

// Config
export const OP_SET_META = 'set-meta'

/**
 * Encode an operation to a Buffer for Autobase append
 */
export function encodeOp (op) {
  return Buffer.from(JSON.stringify(op))
}

/**
 * Decode a Buffer back to an operation object
 */
export function decodeOp (buf) {
  return JSON.parse(buf.toString())
}

/**
 * Validate an operation has required fields for its type
 * @returns {{ valid: boolean, error?: string }}
 */
export function validateOp (op) {
  if (!op || !op.type) {
    return { valid: false, error: 'Missing operation type' }
  }

  switch (op.type) {
    case OP_ADD_WRITER:
      if (!op.userId) return { valid: false, error: 'add-writer requires userId' }
      if (!op.serverKey) return { valid: false, error: 'add-writer requires serverKey' }
      if (!op.role || !['owner', 'writer', 'mirror'].includes(op.role)) {
        return { valid: false, error: 'add-writer requires role (owner|writer|mirror)' }
      }
      break

    case OP_REMOVE_WRITER:
      if (!op.userId) return { valid: false, error: 'remove-writer requires userId' }
      break

    case OP_UPDATE_REF:
      if (!op.ref) return { valid: false, error: 'update-ref requires ref' }
      if (!op.hash) return { valid: false, error: 'update-ref requires hash' }
      if (!op.userId) return { valid: false, error: 'update-ref requires userId' }
      break

    case OP_DELETE_REF:
      if (!op.ref) return { valid: false, error: 'delete-ref requires ref' }
      if (!op.userId) return { valid: false, error: 'delete-ref requires userId' }
      break

    case OP_CREATE_ISSUE:
      if (!op.id) return { valid: false, error: 'create-issue requires id' }
      if (!op.title) return { valid: false, error: 'create-issue requires title' }
      if (!op.userId) return { valid: false, error: 'create-issue requires userId' }
      break

    case OP_UPDATE_ISSUE:
      if (!op.id) return { valid: false, error: 'update-issue requires id' }
      if (!op.userId) return { valid: false, error: 'update-issue requires userId' }
      break

    case OP_CREATE_COMMENT:
      if (!op.issueId) return { valid: false, error: 'create-comment requires issueId' }
      if (!op.commentId) return { valid: false, error: 'create-comment requires commentId' }
      if (!op.body) return { valid: false, error: 'create-comment requires body' }
      if (!op.userId) return { valid: false, error: 'create-comment requires userId' }
      break

    case OP_CREATE_LABEL:
      if (!op.name) return { valid: false, error: 'create-label requires name' }
      break

    case OP_UPDATE_LABEL:
      if (!op.name) return { valid: false, error: 'update-label requires name' }
      break

    case OP_DELETE_LABEL:
      if (!op.name) return { valid: false, error: 'delete-label requires name' }
      break

    case OP_SET_META:
      if (!op.key) return { valid: false, error: 'set-meta requires key' }
      break

    default:
      return { valid: false, error: `Unknown operation type: ${op.type}` }
  }

  return { valid: true }
}