# @stanterprise/protobuf

TypeScript protobuf definitions and RPC service stubs for the Test System domain (attachments, events, observer service, and test entities). Generated code targets both ESM and CJS using `tsup`.

> NOTE: The currently committed generated TypeScript sources do not fully match the proto definitions under `protobuf/testsystem/v1/**` (naming & package/version differences). See "Schema Status" below. This will be aligned in upcoming steps.

## Contents

- Generated message & enum types (`lib/*.ts`)
- gRPC / protobuf-ts style service client & service descriptors
- Proto source files (versioned) in `protobuf/testsystem/v1/**`
- Build tooling via `tsup`

## Installation

```bash
npm install @stanterprise/protobuf
```

## Quick Usage

This package supports multiple flexible import patterns; see the examples below for details.

### Basic Usage

```ts
// Pattern 1: Full namespace
import { testsystem } from "@stanterprise/protobuf";
const run = new testsystem.v1.entities.TestCaseRun();

// Pattern 2: Version-level
import { v1 } from "@stanterprise/protobuf/testsystem";
const run = new v1.entities.TestCaseRun();

// Pattern 3: Module-level
import { entities } from "@stanterprise/protobuf/testsystem/v1";
const run = new entities.TestCaseRun();

// Pattern 4: Individual class
import { TestCaseRun } from "@stanterprise/protobuf/testsystem/v1/entities";
const run = new TestCaseRun();
```

### Encoding / Decoding Messages

Encoding / decoding a message (protobuf-ts runtime):

```ts
import { Attachment } from "@stanterprise/protobuf";
import { WireType, BinaryWriter, BinaryReader } from "@protobuf-ts/runtime";

const a = Attachment.create({
  name: "log.txt",
  mimeType: "text/plain",
  content: new Uint8Array([1, 2, 3]),
});
// Encode
const writer = new BinaryWriter();
Attachment.internalBinaryWrite(a, writer, { writeUnknownFields: false });
const bytes = writer.finish();
// Decode
const decoded = Attachment.internalBinaryRead(
  new BinaryReader(bytes),
  bytes.length,
  { readUnknownField: false }
);
```

Calling an RPC (unary) with a transport implementation:

```ts
import {
  TestEventCollectorClient,
  TestStartEvent,
} from "@stanterprise/protobuf";
import { GrpcTransport } from "@protobuf-ts/grpc-transport"; // example transport

const transport = new GrpcTransport({
  host: "https://observer.example.com",
});

const client = new TestEventCollectorClient(transport);

const call = client.reportTestStart({
  testId: "T-123",
  testName: "Sample test",
  metadata: { browser: "chrome" },
});

call.response.then((resp) => {
  console.log("Ack:", resp);
});
```

## Schema Status (Current Divergences)

| Aspect         | Proto (`protobuf/testsystem/v1`) | Generated TS (lib)     | Divergence                     |
| -------------- | -------------------------------- | ---------------------- | ------------------------------ | ------------- |
| Package paths  | `testsystem.v1.*`                | `testsystem.*`         | Missing `v1` in generated code |
| Event messages | `*EventRequest` suffix           | `TestStartEvent`, etc. | Name suffix removed            |
| Ack message    | `AckResponse` w/ `error_code`    | `Ack` (no error_code)  | Field & name mismatch          |
| Attachment     | `oneof payload { content         | uri }`                 | Single `content` bytes field   | Oneof missing |
| Entities       | `TestSuite` has `id`             | No `id` field present  | Field missing                  |

These will be reconciled in a future regeneration step. Until then the published package reflects the generated TS API, not the proto sources.

## Regeneration (Planned Standard)

Planned one-generator approach (protobuf-ts):

```bash
mkdir -p lib
protoc \
	--plugin=./node_modules/.bin/protoc-gen-ts_proto \
	--ts_out lib \
	--ts_opt long_type_string,optimize_code_size \
	--proto_path ./protobuf \
	$(git ls-files 'protobuf/testsystem/v1/**/*.proto')
node scripts/gen-index.js
```

> The exact command will be updated once the generator set is trimmed and version pinning strategy finalized.

## Versioning Policy

- Patch: Non-breaking regeneration (comments, doc, internal tooling changes)
- Minor: Additive schema changes (new optional fields, new messages, new RPC methods)
- Major: Breaking schema changes (renames, removed fields/messages, package path changes)

## Design Notes

- Dual ESM/CJS build via `tsup` for Node + bundlers.
- Externalized protobuf runtime libraries to keep package lean.
- Auto-generated `lib/index.ts` consolidates exports (watch for accidental surface expansion if helper files are added).

## Roadmap (Short Term)

1. Align generated code with `v1` proto packages & names
2. Implement `Attachment.payload` oneof correctly
3. Drop unused generator dependencies (`ts-proto`, `ts-protoc-gen`, etc.)
4. Add `exports` map and remove `prepare` generation hook
5. Introduce linting + formatting + CI regeneration verification
6. Document RPC transport setup examples

## Contributing

1. Install deps: `npm install`
2. (Temporary) Generated code is committed; do NOT run `npm run generate` until after divergence plan is executed.
3. Open PRs referencing which proto changes (if any) they rely on.

## License

MIT
