main 46e83d2b9afd cached
13 files
18.2 KB
5.2k tokens
25 symbols
1 requests
Download .txt
Repository: nathanhleung/protobuf-ts-types
Branch: main
Commit: 46e83d2b9afd
Files: 13
Total size: 18.2 KB

Directory structure:
gitextract_yi7hy7a5/

├── .gitignore
├── README.md
├── examples/
│   ├── README.md
│   └── basic/
│       ├── .gitignore
│       ├── index.ts
│       ├── package.json
│       └── tsconfig.json
├── package.json
├── src/
│   ├── array.ts
│   ├── index.ts
│   ├── proto.ts
│   └── string.ts
└── tsconfig.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Snowpack dependency directory (https://snowpack.dev/)
web_modules/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional stylelint cache
.stylelintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache

# Next.js build output
.next
out

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# vuepress v2.x temp and cache directory
.temp
.cache

# vitepress build output
**/.vitepress/dist

# vitepress cache directory
**/.vitepress/cache

# Docusaurus cache and generated files
.docusaurus

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port

# Stores VSCode versions used for testing VSCode extensions
.vscode-test

# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*


================================================
FILE: README.md
================================================
# protobuf-ts-types

> Zero-codegen, no-compile TypeScript `type` inference from protobuf `message`s.

`protobuf-ts-types` lets you define language-agnostic `message` types in `proto` format, then infers TypeScript types from them with no additional codegen.

[Try on github.dev](https://github.dev/nathanhleung/protobuf-ts-types/blob/main/examples/basic/index.ts) | [View on CodeSandbox](https://codesandbox.io/p/github/nathanhleung/protobuf-ts-types/main?import=true&embed=1&file=%2Fexamples%2Fbasic%2Findex.ts) | [Discuss on Hacker News](https://news.ycombinator.com/item?id=43682547)

> [!WARNING]
> Proof of concept, not production ready. See [Limitations](#limitations) below for more details.

<img src="./screenshot.png" width="400px" alt="Screenshot" style="border: 1px solid #eee;">

## How it Works

In short, aggressive use of TypeScript's [template literal types](https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html). Annotated example from the source:

```ts
// Pass the proto string you want to infer `message` names from as a generic parameter
type MessageNames<Proto extends string> =
  // Infer `message` parts using template literal type
  WrapWithNewlines<Proto> extends `${string}${Whitespace}message${Whitespace}${infer MessageName}${OptionalWhitespace}{${string}}${infer Rest}`
    ? // Recursively infer remaining message names
      [MessageName, ...MessageNames<Rest>]
    : [];
```

See more in [`src/proto.ts`](./src/proto.ts).

## Usage

First, install the package.

```
npm install https://github.com/nathanhleung/protobuf-ts-types
```

Then, use it in TypeScript.

```ts
import { pbt } from "protobuf-ts-types";

const proto = `
    syntax = "proto3";

    message Person {
      string name = 1;
      int32 id = 2;
      bool is_ceo = 3;
      optional string description = 4;
    }

    message Group {
        string name = 1;
        repeated Person people = 2;
    }
`;

// `Proto` is a mapping of message names to message types, inferred from the
// `proto` source string above.
type Proto = pbt.infer<typeof proto>;

type Person = Proto["Person"];
type Person2 = pbt.infer<typeof proto, "Person">;

// `Person` and `Person2` are the same type:
// ```
// {
//     name: string;
//     id: number;
//     is_ceo: boolean;
//     description?: string;
// }
// ```

type Group = pbt.infer<typeof proto, "Group">;

function greetPerson(person: Person) {
  console.log(`Hello, ${person.name}!`);

  if (person.description) {
    console.log(`${person.description}`);
  } else {
    console.log("(no description)");
  }
}

function greetGroup(group: Group) {
  console.log(`=========${"=".repeat(group.name.length)}===`);
  console.log(`= Hello, ${group.name}! =`);
  console.log(`=========${"=".repeat(group.name.length)}===`);

  for (const person of group.people) {
    greetPerson(person);
    console.log();
  }
}

// If the structure of the `Group` or any of the individual `Person`s does not
// match the type, TypeScript will show an error.
greetGroup({
  name: "Hooli",
  people: [
    {
      name: "Gavin Belson",
      id: 0,
      is_ceo: true,
      description: "CEO of Hooli",
    },
    {
      name: "Richard Hendricks",
      id: 1,
      is_ceo: true,
      description: "CEO of Pied Piper",
    },
    {
      name: "Dinesh Chugtai",
      id: 2,
      is_ceo: false,
      description: "Software Engineer",
    },
    {
      name: "Jared Dunn",
      id: 3,
      is_ceo: false,
    },
  ],
});

// Output:
// ```
// =================
// = Hello, Hooli! =
// =================
// Hello, Gavin Belson!
// CEO of Hooli

// Hello, Richard Hendricks!
// CEO of Pied Piper

// Hello, Dinesh Chugtai!
// Software Engineer

// Hello, Jared Dunn!
// (no description)
// ```
```

## Limitations

* If not using inline (i.e., literals in TypeScript) proto `string`s `as const`, probably requires a [`ts-patch`](https://github.com/nonara/ts-patch) compiler patch to import `.proto` files until https://github.com/microsoft/TypeScript/issues/42219 is resolved
* `service`s and `rpc`s are not supported (only `message`s)
* `oneof` and `map` fields are not supported
* `import`s are not supported (for now, concatenate)

## API

### `pbt`

Top-level exported namespace.

```
import { pbt } from "protobuf-ts-types";
```

### `pbt.infer<Proto extends string, MessageName extends string = "">`

Given a proto source string, infers the types of the `message`s in the source.

#### Returns

* If `MessageName` is an empty string, the returned type is a mapping from message names to message types.
* If `MessageName` is a known `message`, the returned type is the inferred type of the given `MessageName`.
* If `MessageName` is not a known `message`, the returned type is `never`.


================================================
FILE: examples/README.md
================================================
# protobuf-ts-types Examples

## Usage

Open the directory of the example you want to run in VSCode, then run

```
npm install
npm start
```


================================================
FILE: examples/basic/.gitignore
================================================
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Snowpack dependency directory (https://snowpack.dev/)
web_modules/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional stylelint cache
.stylelintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache

# Next.js build output
.next
out

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# vuepress v2.x temp and cache directory
.temp
.cache

# vitepress build output
**/.vitepress/dist

# vitepress cache directory
**/.vitepress/cache

# Docusaurus cache and generated files
.docusaurus

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port

# Stores VSCode versions used for testing VSCode extensions
.vscode-test

# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*


================================================
FILE: examples/basic/index.ts
================================================
import { pbt } from "../../src/index";

const proto = `
  syntax = "proto3";
  
  message Person {
      string name = 1;
      int32 id = 2;
      bool is_ceo = 3;
      optional string description = 4;
  }

  message Group {
      string name = 1;
      repeated Person people = 2;
  }
`;

type Proto = pbt.infer<typeof proto>;
type Person = Proto["Person"];
type Group = Proto["Group"];

function greetPerson(person: Person) {
  console.log(`Hello, ${person.name}!`);

  if (person.description) {
    console.log(`${person.description}`);
  } else {
    console.log("(no description)");
  }
}

function greetGroup(group: Group) {
  console.log(`=========${"=".repeat(group.name.length)}===`);
  console.log(`= Hello, ${group.name}! =`);
  console.log(`=========${"=".repeat(group.name.length)}===`);

  for (const person of group.people) {
    greetPerson(person);
    console.log();
  }
}

greetGroup({
  name: "Hooli",
  people: [
    {
      name: "Gavin Belson",
      id: 0,
      is_ceo: true,
      description: "CEO of Hooli",
    },
    {
      name: "Richard Hendricks",
      id: 1,
      is_ceo: true,
      description: "CEO of Pied Piper",
    },
    {
      name: "Dinesh Chugtai",
      id: 2,
      is_ceo: false,
      description: "Software Engineer",
    },
    {
      name: "Jared Dunn",
      id: 3,
      is_ceo: false,
    },
  ],
});


================================================
FILE: examples/basic/package.json
================================================
{
  "name": "@protobuf-ts-types/example-basic",
  "version": "1.0.0",
  "main": "index.ts",
  "private": true,
  "scripts": {
    "start": "tsx index.ts"
  },
  "author": "nathanhleung",
  "license": "Apache-2.0",
  "description": "",
  "devDependencies": {
    "tsx": "^4.19.3",
    "typescript": "^5.8.3"
  }
}


================================================
FILE: examples/basic/tsconfig.json
================================================
{
  "extends": "../../tsconfig.json",
}



================================================
FILE: package.json
================================================
{
  "name": "protobuf-ts-types",
  "author": "nathanhleung",
  "version": "0.0.1",
  "description": "Zero-codegen TypeScript `type` inference from protobuf `message`s",
  "keywords": [
    "protobuf",
    "protobufjs",
    "protobuf-es",
    "proto",
    "buf",
    "typescript",
    "type",
    "inference",
    "codegen",
    "grpc",
    "grpc-web",
    "connect"
  ],
  "main": "src/index.ts",
  "homepage": "https://github.com/nathanhleung/protobuf-ts-types#readme",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/nathanhleung/protobuf-ts-types.git"
  },
  "license": "Apache-2.0",
  "devDependencies": {
    "@types/node": "^22.14.1",
    "typescript": "^5.8.3"
  },
  "dependencies": {
    "type-fest": "^4.39.1"
  }
}


================================================
FILE: src/array.ts
================================================
import type { Trim } from "type-fest";

/**
 * Trims leading and trailing whitespace from each element of the given array
 * of strings.
 */
export type MapTrim<Strings extends string[]> = Strings extends [
  infer Head,
  ...infer Tail
]
  ? Head extends string
    ? Tail extends string[]
      ? [Trim<Head>, ...MapTrim<Tail>]
      : []
    : []
  : [];

/**
 * Removes empty strings from the given array of strings.
 */
export type FilterEmpty<Strings extends string[]> = Strings extends [
  infer Head,
  ...infer Tail
]
  ? Head extends ""
    ? FilterEmpty<Tail extends string[] ? Tail : []>
    : [Head, ...FilterEmpty<Tail extends string[] ? Tail : []>]
  : [];

/**
 * Given an array of objects, creates an object type where the keys are the
 * values of the given key for each object. Think of it as a combination of
 * lodash's [`keyBy`](https://lodash.com/docs/4.17.15#keyBy) and
 * [`pick`](https://lodash.com/docs/4.17.15#pick).
 */
export type KeyBy<
  Objects extends { [key in Key]: string | number | symbol }[],
  Key extends string
> = {
  [Object in Objects[number] as Object[Key]]: Object;
};


================================================
FILE: src/index.ts
================================================
import type { infer as Infer } from "./proto";

export namespace pbt {
  export type infer<
    Proto extends string,
    MessageName extends string = ""
  > = Infer<Proto, MessageName>;
}


================================================
FILE: src/proto.ts
================================================
import type { Split, Trim } from "type-fest";
import type { FilterEmpty, KeyBy, MapTrim } from "./array";
import type {
  OptionalWhitespace,
  StringToNumber,
  Whitespace,
  WrapWithNewlines,
} from "./string";

/**
 * Extracts message names from the given proto string.
 */
type MessageNames<Proto extends string> =
  WrapWithNewlines<Proto> extends `${string}${Whitespace}message${Whitespace}${infer MessageName}${OptionalWhitespace}{${string}}${infer Rest}`
    ? [MessageName, ...MessageNames<Rest>]
    : [];

/**
 * Extracts field definitions of the given message name.
 */
type RawFieldDefinitions<
  Proto extends string,
  MessageName extends MessageNames<Proto>[number]
> = WrapWithNewlines<Proto> extends `${string}${Whitespace}message${Whitespace}${MessageName}${OptionalWhitespace}{${infer FieldDefinitions}}${string}`
  ? FilterEmpty<MapTrim<Split<FieldDefinitions, ";">>>
  : [];

/**
 * Given a raw field definition extracted by `RawFieldDefinitions`, parses it
 * into an object type.
 */
type ParseRawFieldDefinition<
  Proto extends string,
  RawFieldDefinition extends string
> = RawFieldDefinition extends `${infer FieldCardinality}${Whitespace}${infer FieldType}${Whitespace}${infer FieldName}${OptionalWhitespace}=${OptionalWhitespace}${infer FieldNumber}`
  ? FieldName extends ""
    ? RawFieldDefinition extends `${infer FieldType}${Whitespace}${infer FieldName}${OptionalWhitespace}=${OptionalWhitespace}${infer FieldNumber}`
      ? {
          type: ParseFieldType<Proto, Trim<FieldType>>;
          name: Trim<FieldName>;
          number: StringToNumber<Trim<FieldNumber>>;
        }
      : never
    : {
        type: ParseFieldType<Proto, Trim<FieldType>, Trim<FieldCardinality>>;
        name: Trim<FieldName>;
        number: StringToNumber<Trim<FieldNumber>>;
      }
  : never;

/**
 * Given a raw field type, parses it into a TypeScript type, handling
 * cardinality appropriately.
 */
type ParseFieldType<
  Proto extends string,
  RawFieldType extends string,
  Cardinality extends string = ""
> = Cardinality extends "optional"
  ? ParseRawFieldType<Proto, RawFieldType> | undefined
  : Cardinality extends "repeated"
  ? ParseRawFieldType<Proto, RawFieldType>[]
  : ParseRawFieldType<Proto, RawFieldType>;

/**
 * Given a raw field type, parses it into a TypeScript type.
 */
type ParseRawFieldType<
  Proto extends string,
  RawType extends string
> = RawType extends "string"
  ? string
  : RawType extends "bool"
  ? boolean
  : RawType extends "bytes"
  ? Uint8Array
  : RawType extends "float"
  ? number
  : RawType extends "double"
  ? number
  : RawType extends "int32"
  ? number
  : RawType extends "int64"
  ? number
  : RawType extends "uint32"
  ? number
  : RawType extends "uint64"
  ? number
  : MessagesByMessageName<Proto>[RawType];

/**
 * Given raw field definitions extracted by `RawFieldDefinitions`, parses them
 * into object types using `ParseRawFieldDefinition`.
 */
type ParseRawFieldDefinitions<
  Proto extends string,
  RawDefinitions extends string[]
> = RawDefinitions extends [infer Head, ...infer Tail]
  ? Head extends string
    ? Tail extends string[]
      ? [
          ParseRawFieldDefinition<Proto, Head>,
          ...ParseRawFieldDefinitions<Proto, Tail>
        ]
      : []
    : []
  : [];

/**
 * Extracts field definitions for a given message name.
 */
type FieldDefinitions<
  Proto extends string,
  MessageName extends MessageNames<Proto>[number]
> = ParseRawFieldDefinitions<Proto, RawFieldDefinitions<Proto, MessageName>>;

/**
 * Extracts a mapping of field names to field definitions for a given message
 * name.
 */
type FieldDefinitionsByFieldName<
  Proto extends string,
  MessageName extends MessageNames<Proto>[number]
> = KeyBy<FieldDefinitions<Proto, MessageName>, "name">;

/**
 * Extracts the field names for a given message name.
 */
type FieldNames<
  Proto extends string,
  MessageName extends MessageNames<Proto>[number]
> = keyof FieldDefinitionsByFieldName<Proto, MessageName>;

/**
 * Infers the type of the named message in the given proto string.
 */
type MessageType<
  Proto extends string,
  MessageName extends MessageNames<Proto>[number]
> = {
  [k in FieldNames<
    Proto,
    MessageName
  > as undefined extends FieldDefinitionsByFieldName<
    Proto,
    MessageName
  >[k]["type"]
    ? never
    : k]: FieldDefinitionsByFieldName<Proto, MessageName>[k]["type"];
} & {
  [k in FieldNames<
    Proto,
    MessageName
  > as undefined extends FieldDefinitionsByFieldName<
    Proto,
    MessageName
  >[k]["type"]
    ? k
    : never]?: FieldDefinitionsByFieldName<Proto, MessageName>[k]["type"];
};

/**
 * Creates a mapping of message names to their respective inferred types for
 * the given proto string.
 */
type MessagesByMessageName<Proto extends string> = {
  [k in MessageNames<Proto>[number]]: MessageType<Proto, k>;
};

export type infer<
  Proto extends string,
  MessageName extends string = ""
> = MessageName extends ""
  ? MessagesByMessageName<Proto>
  : MessageName extends MessageNames<Proto>[number]
  ? MessagesByMessageName<Proto>[MessageName]
  : never;


================================================
FILE: src/string.ts
================================================
/** Wraps the given string type with newlines. */
export type WrapWithNewlines<T extends string> = `\n${T}\n`;

/** A space, tab, newline, or carriage return. */
export type Whitespace = " " | "\t" | "\n" | "\r";

export type OptionalWhitespace = "" | Whitespace;

export type StringToNumber<T extends string> =
  T extends `${infer N extends number}` ? N : never;


================================================
FILE: tsconfig.json
================================================
{
  "compilerOptions": {
    "module": "CommonJS",
    "lib": ["ES2024"],
    "types": ["node"],
    "target": "ES2024",
    "allowJs": false,
    "noEmit": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  }
}
Download .txt
gitextract_yi7hy7a5/

├── .gitignore
├── README.md
├── examples/
│   ├── README.md
│   └── basic/
│       ├── .gitignore
│       ├── index.ts
│       ├── package.json
│       └── tsconfig.json
├── package.json
├── src/
│   ├── array.ts
│   ├── index.ts
│   ├── proto.ts
│   └── string.ts
└── tsconfig.json
Download .txt
SYMBOL INDEX (25 symbols across 5 files)

FILE: examples/basic/index.ts
  type Proto (line 19) | type Proto = pbt.infer<typeof proto>;
  type Person (line 20) | type Person = Proto["Person"];
  type Group (line 21) | type Group = Proto["Group"];
  function greetPerson (line 23) | function greetPerson(person: Person) {
  function greetGroup (line 33) | function greetGroup(group: Group) {

FILE: src/array.ts
  type MapTrim (line 7) | type MapTrim<Strings extends string[]> = Strings extends [
  type FilterEmpty (line 21) | type FilterEmpty<Strings extends string[]> = Strings extends [
  type KeyBy (line 36) | type KeyBy<

FILE: src/index.ts
  type infer (line 4) | type infer<

FILE: src/proto.ts
  type MessageNames (line 13) | type MessageNames<Proto extends string> =
  type RawFieldDefinitions (line 21) | type RawFieldDefinitions<
  type ParseRawFieldDefinition (line 32) | type ParseRawFieldDefinition<
  type ParseFieldType (line 55) | type ParseFieldType<
  type ParseRawFieldType (line 68) | type ParseRawFieldType<
  type ParseRawFieldDefinitions (line 95) | type ParseRawFieldDefinitions<
  type FieldDefinitions (line 112) | type FieldDefinitions<
  type FieldDefinitionsByFieldName (line 121) | type FieldDefinitionsByFieldName<
  type FieldNames (line 129) | type FieldNames<
  type MessageType (line 137) | type MessageType<
  type MessagesByMessageName (line 166) | type MessagesByMessageName<Proto extends string> = {
  type infer (line 170) | type infer<

FILE: src/string.ts
  type WrapWithNewlines (line 2) | type WrapWithNewlines<T extends string> = `\n${T}\n`;
  type Whitespace (line 5) | type Whitespace = " " | "\t" | "\n" | "\r";
  type OptionalWhitespace (line 7) | type OptionalWhitespace = "" | Whitespace;
  type StringToNumber (line 9) | type StringToNumber<T extends string> =
Condensed preview — 13 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (20K chars).
[
  {
    "path": ".gitignore",
    "chars": 2141,
    "preview": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\nlerna-debug.log*\n.pnpm-debug.log*\n\n# Diagnostic reports"
  },
  {
    "path": "README.md",
    "chars": 4741,
    "preview": "# protobuf-ts-types\n\n> Zero-codegen, no-compile TypeScript `type` inference from protobuf `message`s.\n\n`protobuf-ts-type"
  },
  {
    "path": "examples/README.md",
    "chars": 141,
    "preview": "# protobuf-ts-types Examples\n\n## Usage\n\nOpen the directory of the example you want to run in VSCode, then run\n\n```\nnpm i"
  },
  {
    "path": "examples/basic/.gitignore",
    "chars": 2141,
    "preview": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\nlerna-debug.log*\n.pnpm-debug.log*\n\n# Diagnostic reports"
  },
  {
    "path": "examples/basic/index.ts",
    "chars": 1363,
    "preview": "import { pbt } from \"../../src/index\";\n\nconst proto = `\n  syntax = \"proto3\";\n  \n  message Person {\n      string name = 1"
  },
  {
    "path": "examples/basic/package.json",
    "chars": 313,
    "preview": "{\n  \"name\": \"@protobuf-ts-types/example-basic\",\n  \"version\": \"1.0.0\",\n  \"main\": \"index.ts\",\n  \"private\": true,\n  \"script"
  },
  {
    "path": "examples/basic/tsconfig.json",
    "chars": 41,
    "preview": "{\n  \"extends\": \"../../tsconfig.json\",\n}\n\n"
  },
  {
    "path": "package.json",
    "chars": 750,
    "preview": "{\n  \"name\": \"protobuf-ts-types\",\n  \"author\": \"nathanhleung\",\n  \"version\": \"0.0.1\",\n  \"description\": \"Zero-codegen TypeSc"
  },
  {
    "path": "src/array.ts",
    "chars": 1116,
    "preview": "import type { Trim } from \"type-fest\";\n\n/**\n * Trims leading and trailing whitespace from each element of the given arra"
  },
  {
    "path": "src/index.ts",
    "chars": 189,
    "preview": "import type { infer as Infer } from \"./proto\";\n\nexport namespace pbt {\n  export type infer<\n    Proto extends string,\n  "
  },
  {
    "path": "src/proto.ts",
    "chars": 5106,
    "preview": "import type { Split, Trim } from \"type-fest\";\nimport type { FilterEmpty, KeyBy, MapTrim } from \"./array\";\nimport type {\n"
  },
  {
    "path": "src/string.ts",
    "chars": 365,
    "preview": "/** Wraps the given string type with newlines. */\nexport type WrapWithNewlines<T extends string> = `\\n${T}\\n`;\n\n/** A sp"
  },
  {
    "path": "tsconfig.json",
    "chars": 260,
    "preview": "{\n  \"compilerOptions\": {\n    \"module\": \"CommonJS\",\n    \"lib\": [\"ES2024\"],\n    \"types\": [\"node\"],\n    \"target\": \"ES2024\","
  }
]

About this extraction

This page contains the full source code of the nathanhleung/protobuf-ts-types GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 13 files (18.2 KB), approximately 5.2k tokens, and a symbol index with 25 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!