Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

MetaEngine Protobuf Fetch

npm version npm downloads License: MIT

Generate framework-agnostic TypeScript services and models from Protobuf definitions using the native Fetch API.

gRPC/Connect transport. Runs on Node, browsers, Vite, SvelteKit, Next.js, Bun, Deno, and any TS runtime that ships fetch. No runtime dependencies in the generated code.


Quick Links


Features

  • Framework-agnostic — works in any TS runtime with fetch
  • Native Fetch API — zero runtime dependencies in generated code
  • gRPC/Connect transport — services, messages, and enums generated straight from .proto
  • Production-ready — Bearer/Basic auth, timeouts, custom headers, middleware, all via CLI flags
  • gRPC-native error handling — opt into a status-code taxonomy (NOT_FOUND, UNAVAILABLE, …) instead of HTTP-status guessing
  • TypeScript — fully typed clients and models
  • Result pattern — opt into ApiResult<T> for structured error handling without exceptions
  • Middleware hooksonRequest / onResponse / onError composable around the request pipeline
  • Vite + SvelteKit--import-meta-env for import.meta.env access
  • Tree-shakeable — separate file per model and per service

Installation

npm install --save-dev @metaengine/protobuf-fetch

Or use directly with npx:

npx @metaengine/protobuf-fetch <input> <output>

Requirements

  • Node.js 18.0 or later
  • .NET 8.0 or later runtime (Download)
  • A TS runtime that supports fetch (Node 18+, all modern browsers, Bun, Deno)

Quick Start

Basic

npx @metaengine/protobuf-fetch service.proto ./src/api \
  --documentation \
  --result-pattern

Production setup

npx @metaengine/protobuf-fetch service.proto ./src/api \
  --bearer-auth API_TOKEN \
  --timeout 30 \
  --custom-header X-Tenant-ID=TENANT_ID \
  --error-handling

With npm scripts

Add to your package.json:

{
  "scripts": {
    "generate:api": "metaengine-protobuf-fetch service.proto ./src/api --bearer-auth API_TOKEN --timeout 30 --error-handling"
  }
}

Then run:

npm run generate:api

Runtime-specific examples

Vite / SvelteKit (uses import.meta.env):

npx @metaengine/protobuf-fetch service.proto ./src/api \
  --import-meta-env \
  --base-url-env VITE_API_URL

Next.js:

npx @metaengine/protobuf-fetch service.proto ./src/api \
  --base-url-env NEXT_PUBLIC_API_URL

Plain Node / Bun / Deno:

npx @metaengine/protobuf-fetch service.proto ./src/api \
  --base-url-env API_BASE_URL

More examples

# Multiple custom headers from env vars
npx @metaengine/protobuf-fetch service.proto ./src/api \
  --custom-header X-Tenant-ID=TENANT_ID \
  --custom-header X-App-Id=APP_ID

# Map well-known timestamp/duration types to strings
npx @metaengine/protobuf-fetch service.proto ./src/api \
  --type-mapping google.protobuf.Timestamp=string \
  --type-mapping google.protobuf.Duration=string

CLI Options

Option Description Default
--base-url-env <name> Environment variable name for base URL API_BASE_URL
--service-suffix <suffix> Service naming suffix Service
--options-threshold <n> Parameter count for options object 4
--documentation Generate JSDoc comments false
--import-meta-env Use import.meta.env for env access (Vite, SvelteKit) false
--result-pattern Return ApiResult<T> instead of T for structured error handling false
--middleware Emit middleware hooks (onRequest, onResponse, onError) in client false
--error-handling gRPC-native error handling keyed on gRPC status codes false
--bearer-auth <env-var-name> Bearer token authentication (runtime token provider) -
--basic-auth <userEnv:passEnv> Basic auth from env vars (e.g. API_USER:API_PASS) -
--timeout <seconds> Request timeout in seconds for all operations -
--custom-header <header=envVarName> Static header from env var. Repeatable. -
--date-transformation Convert google.protobuf.Timestamp fields in responses to Date objects false
--types-barrel Emit an index.ts barrel per folder plus a root index.ts re-exporting everything false
--clean Clean output directory (remove files not in generation) false
--verbose Enable verbose logging false
--type-mapping <name=target> Override TS type for a protobuf type. Repeatable. See Type mapping overrides -
--help, -h Show help message -

Generated Code Structure

output/
  ├── models/                       # One file per message/enum
  │   ├── entity.ts                 # export interface Entity { ... }
  │   ├── create-entity-request.ts
  │   └── ...
  ├── services/                     # One file per proto service
  │   ├── entity.service.ts         # All EntityService RPCs
  │   └── ...
  ├── client.ts                     # ClientConfig, createClient, getDefaultClient
  └── errors.ts                     # ApiResult / error helpers

With --error-handling, two extra models are emitted: models/grpc-status-code.ts and models/grpc-error.ts.


Production-ready features

Bearer authentication

npx @metaengine/protobuf-fetch service.proto ./src/api --bearer-auth API_TOKEN

The generated client.ts exposes an auth config field accepting a token string or an async token provider (() => string | Promise<string>), and adds Authorization: Bearer <token> to every request. This suits gRPC/Connect clients where tokens are refreshed at runtime rather than read once from the environment.

Basic authentication

npx @metaengine/protobuf-fetch service.proto ./src/api --basic-auth API_USER:API_PASS

Reads the username and password from the two named environment variables and sends Authorization: Basic <base64(user:password)>.

Timeout

npx @metaengine/protobuf-fetch service.proto ./src/api --timeout 30

Uses AbortSignal.timeout(seconds * 1000) and composes correctly with consumer-supplied AbortSignal.

Custom headers from env vars

npx @metaengine/protobuf-fetch service.proto ./src/api \
  --custom-header X-Tenant-ID=TENANT_ID \
  --custom-header X-App-Id=APP_ID

Repeatable. Each header value comes from a separate env var.

gRPC-native error handling

npx @metaengine/protobuf-fetch service.proto ./src/api --error-handling

Emits a GrpcError type and a GrpcStatusCode taxonomy. Errors are classified by gRPC status code rather than HTTP status: NOT_FOUND / PERMISSION_DENIED return null; INVALID_ARGUMENT / ALREADY_EXISTS / FAILED_PRECONDITION return the error body; UNAUTHENTICATED / INTERNAL / UNAVAILABLE throw.

Result pattern

npx @metaengine/protobuf-fetch service.proto ./src/api --result-pattern

Operations return ApiResult<T> instead of throwing — useful when you want to handle errors as values rather than exceptions:

const result = await entityService.getEntity({ id: '123' });
if (result.ok) {
  console.log(result.data.name);
} else {
  console.error(result.error.code, result.error.message);
}

Middleware

npx @metaengine/protobuf-fetch service.proto ./src/api --middleware

Generated client emits a Middleware interface and accepts an optional middleware array on ClientConfig:

const client = createClient({
  baseUrl: 'https://api.example.com',
  middleware: [
    {
      onRequest: (req) => { console.log('→', req.url); return req; },
      onResponse: (res) => { console.log('←', res.status); return res; },
      onError: (err) => { console.error('✗', err); throw err; },
    },
  ],
});

Middleware composes with --bearer-auth, --timeout, and --error-handling.


Type mapping overrides

Use --type-mapping to override the TS type emitted for a protobuf type, keyed by its fully-qualified name. Repeatable. Unsupported targets are hard errors.

Target Emitted TS type
string string
number number
Date Date
boolean boolean
npx @metaengine/protobuf-fetch service.proto ./src/api \
  --type-mapping google.protobuf.Timestamp=string \
  --type-mapping google.protobuf.Duration=string

Integer scalars (including int64 / uint64) map to number by design so request bodies survive JSON.stringify and parsed responses match the wire shape. A bigint target is therefore not offered.


See it live

Try the generator with your own spec at https://www.metaengine.eu/converters.


Programmatic Usage

The NuGet package allows programmatic use in .NET projects. See the website documentation for full C# API reference.


Support


License

MIT License - see LICENSE file for details.


About This Repository

This is the documentation and issue tracking repository for MetaEngine Protobuf Fetch. The compiled NPM package is available at @metaengine/protobuf-fetch.

Source code is proprietary, but the package is free to use under MIT license.

About

Generate TypeScript services and models from Protobuf definitions using the native Fetch API — gRPC/Connect transport, framework-agnostic

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors