CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-prebuild

A command line tool for easily making prebuilt binaries for multiple versions of Node.js, Electron or node-webkit on a specific platform

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

upload-system.mddocs/

Upload System

GitHub releases integration for uploading prebuilt binaries with automatic release creation, duplicate detection, and comprehensive error handling.

Capabilities

Upload Function

Main upload function that handles GitHub release creation and binary asset uploads.

/**
 * Upload prebuilt binaries to GitHub releases
 * @param opts - Upload options including files, authentication, and release settings
 * @param cb - Callback function (err, result) => void
 */
function upload(opts, cb);

interface UploadOptions {
  /** Package.json object containing repository information */
  pkg: PackageJson;
  /** Array of file paths to upload */
  files: string[];
  /** GitHub personal access token for authentication */
  upload: string;
  /** Tag prefix for release tags (defaults to 'v') */
  'tag-prefix'?: string;
  /** Mark the release as a prerelease */
  prerelease?: boolean;
  /** Custom ghreleases instance (for testing) */
  gh?: object;
}

interface UploadResult {
  /** Newly uploaded files */
  new: string[];
  /** Previously uploaded files (skipped) */
  old: string[];
}

interface PackageJson {
  name: string;
  version: string;
  repository?: {
    type: string;
    url: string;
  };
}

Usage Examples:

const upload = require('prebuild/upload');

// Upload prebuilt binaries
upload({
  pkg: require('./package.json'),
  files: [
    'prebuilds/mymodule-v1.0.0-node-v93-linux-x64.tar.gz',
    'prebuilds/mymodule-v1.0.0-node-v93-darwin-x64.tar.gz'
  ],
  upload: 'ghp_your_github_token_here'
}, (err, result) => {
  if (err) throw err;
  console.log('Uploaded:', result.new.length, 'files');
  console.log('Skipped:', result.old.length, 'existing files');
});

// Upload with custom tag prefix for monorepo
upload({
  pkg: require('./package.json'),
  files: ['prebuilds/module-v2.1.0-node-v93-win32-x64.tar.gz'],
  upload: 'ghp_token123',
  'tag-prefix': 'my-package@',
  prerelease: true
}, (err, result) => {
  if (err) throw err;
  console.log('Prerelease created and files uploaded');
});

Release Management

Automatic GitHub release creation with tag generation and duplicate handling.

/**
 * Release creation and management logic
 */
interface ReleaseManagement {
  /** Generated tag name format: {tag-prefix}{package.version} */
  tagFormat: string;
  /** GitHub repository user/owner extracted from package.json */
  repositoryUser: string;
  /** GitHub repository name extracted from package.json */
  repositoryName: string;
  /** OAuth authentication configuration */
  authConfig: GitHubAuth;
}

interface GitHubAuth {
  user: 'x-oauth';
  token: string;
}

Tag Examples:

// Default tag prefix 'v'
// Package version: '1.2.3' → Tag: 'v1.2.3'

// Custom tag prefix for lerna/monorepo
// Tag prefix: 'my-package@', Version: '1.2.3' → Tag: 'my-package@1.2.3'

Asset Management

Intelligent asset upload with duplicate detection and filtering.

/**
 * Asset upload and duplicate detection
 */
interface AssetManagement {
  /** Existing assets on the release */
  existingAssets: string[];
  /** Files to upload (filtered for duplicates) */
  filesToUpload: string[];
  /** Upload operation results */
  uploadResults: UploadResult;
}

Usage Examples:

// The upload system automatically:
// 1. Checks existing assets on the release
// 2. Filters out files that already exist
// 3. Uploads only new files
// 4. Returns summary of new vs existing files

upload({
  pkg: require('./package.json'),
  files: [
    'prebuilds/mod-v1.0.0-node-v93-linux-x64.tar.gz',  // New file
    'prebuilds/mod-v1.0.0-node-v93-darwin-x64.tar.gz'  // Already exists
  ],
  upload: 'token'
}, (err, result) => {
  // result.new: ['mod-v1.0.0-node-v93-linux-x64.tar.gz']
  // result.old: ['mod-v1.0.0-node-v93-darwin-x64.tar.gz']
});

Repository Detection

Automatic repository information extraction from package.json.

/**
 * Repository information extraction
 * @param pkg - Package.json object
 * @returns GitHub repository URL or null
 */
function extractRepositoryInfo(pkg: PackageJson): string | null;

/**
 * Repository URL formats supported:
 * - https://github.com/user/repo
 * - https://github.com/user/repo.git  
 * - git+https://github.com/user/repo.git
 * - git@github.com:user/repo.git
 */
interface RepositoryFormats {
  https: 'https://github.com/user/repo';
  httpsGit: 'https://github.com/user/repo.git';
  gitHttps: 'git+https://github.com/user/repo.git';
  ssh: 'git@github.com:user/repo.git';
}

Package.json Examples:

{
  "name": "my-module",
  "version": "1.0.0",
  "repository": {
    "type": "git",
    "url": "https://github.com/user/my-module.git"
  }
}
{
  "name": "my-module", 
  "version": "1.0.0",
  "repository": "github:user/my-module"
}

Error Handling

Comprehensive error handling for common upload scenarios.

/**
 * Upload error types and handling
 */
interface UploadErrors {
  /** Missing repository field in package.json */
  NoRepositoryError: Error;
  /** GitHub API authentication failure */
  AuthenticationError: Error;
  /** Network/connectivity issues */
  NetworkError: Error;
  /** File not found or access issues */
  FileError: Error;
  /** GitHub rate limiting */
  RateLimitError: Error;
}

/**
 * Error factory functions
 */
interface ErrorFactories {
  noRepository(): Error;
  spawnFailed(cmd: string, args: string[], code: number): Error;
}

Error Examples:

const upload = require('prebuild/upload');

upload({
  pkg: { name: 'test', version: '1.0.0' }, // Missing repository
  files: ['test.tar.gz'],
  upload: 'token'
}, (err, result) => {
  if (err) {
    console.error('Upload failed:', err.message);
    // "package.json is missing a repository field"
  }
});

GitHub Integration

Integration with ghreleases library for GitHub API operations.

/**
 * GitHub API operations through ghreleases
 */
interface GitHubOperations {
  /** Create release if it doesn't exist */
  createRelease(auth: GitHubAuth, user: string, repo: string, options: ReleaseOptions): void;
  /** Get existing release by tag */
  getByTag(auth: GitHubAuth, user: string, repo: string, tag: string): Promise<Release>;
  /** Upload assets to release */
  uploadAssets(auth: GitHubAuth, user: string, repo: string, releaseId: string, files: string[]): void;
}

interface ReleaseOptions {
  tag_name: string;
  prerelease?: boolean;
}

interface Release {
  id: string;
  tag_name: string;
  assets: Asset[];
}

interface Asset {
  name: string;
  id: string;
  download_count: number;
}

Upload Workflow

  1. Repository Validation: Extract and validate GitHub repository URL from package.json
  2. Authentication Setup: Configure OAuth token for GitHub API access
  3. Release Creation: Create release with generated tag if it doesn't exist
  4. Asset Discovery: Fetch existing assets from the release
  5. Duplicate Detection: Filter out files that already exist as assets
  6. File Upload: Upload new files as release assets
  7. Result Reporting: Return summary of uploaded vs existing files

Types

interface PackageJson {
  name: string;
  version: string;
  repository?: {
    type: string;
    url: string;
  } | string;
}

interface GitHubAuth {
  user: 'x-oauth';
  token: string;
}

interface UploadResult {
  new: string[];
  old: string[];
}

Install with Tessl CLI

npx tessl i tessl/npm-prebuild

docs

build-system.md

configuration.md

index.md

upload-system.md

utilities.md

tile.json