Skip to content

Commit 20e55df

Browse files
committed
fix: lint and pre-commit configuration
1 parent 5993fb3 commit 20e55df

6 files changed

Lines changed: 1428 additions & 869 deletions

File tree

.pre-commit-config.yaml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Pre-commit configuration for athena-nodejs-client
2+
# See https://pre-commit.com for more information
3+
# See https://pre-commit.com/hooks.html for more hooks
4+
repos:
5+
# General file checks
6+
- repo: https://github.com/pre-commit/pre-commit-hooks
7+
rev: v4.5.0
8+
hooks:
9+
- id: trailing-whitespace
10+
- id: end-of-file-fixer
11+
- id: check-yaml
12+
- id: check-added-large-files
13+
- id: check-json
14+
exclude: ^samples/
15+
- id: check-merge-conflict
16+
17+
# Node.js/npm hooks
18+
- repo: local
19+
hooks:
20+
# Run all linting checks
21+
- id: lint-all
22+
name: Lint All (ESLint + Prettier + TypeScript)
23+
entry: npm run lint:all
24+
language: system
25+
pass_filenames: false
26+
always_run: true
27+
28+
# Global settings
29+
default_stages: [pre-commit]
30+
fail_fast: true

README.md

Lines changed: 85 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,79 @@ Athena is a gRPC-based image classification service designed for CSAM (Child Sex
1616

1717
# Contributing
1818

19+
## Code Quality and Pre-commit Hooks
20+
21+
This project uses pre-commit hooks to ensure code quality and consistency. The hooks run linting, formatting, and type checking before each commit.
22+
23+
### Setting up Pre-commit Hooks
24+
25+
1. **Install pre-commit** (if not already installed):
26+
```sh
27+
uvx pre-commit --help
28+
```
29+
Or install globally:
30+
```sh
31+
uv tool install pre-commit
32+
```
33+
34+
2. **Install the hooks**:
35+
```sh
36+
uvx pre-commit install
37+
```
38+
39+
3. **Run all quality checks manually**:
40+
```sh
41+
npm run lint:all
42+
```
43+
44+
### What the Pre-commit Hooks Check
45+
46+
- **ESLint**: Code quality and style issues
47+
- **Prettier**: Code formatting consistency
48+
- **TypeScript**: Type checking and compilation
49+
- **File checks**: Trailing whitespace, file endings, large files, etc.
50+
- **Submodule status**: Ensures submodules are properly tracked
51+
52+
### Manual Quality Checks
53+
54+
You can run individual checks manually:
55+
56+
```sh
57+
# Run ESLint
58+
npm run lint
59+
60+
# Check Prettier formatting
61+
npm run prettier:check
62+
63+
# Fix Prettier formatting
64+
npm run prettier
65+
66+
# TypeScript type checking
67+
npx tsc --noEmit
68+
69+
# Run all checks at once
70+
npm run lint:all
71+
```
72+
1973
## Updating the Protobuf definitions
2074

21-
Protobufs are stored in the [@crispthinking/athena-protobuffs](https://github.com/crispthinking/athena-protobufs) repository.
75+
Protobufs are stored as a git submodule from the [@crispthinking/athena-nodejs-client](https://github.com/crispthinking/athena-nodejs-client.git) repository.
2276

23-
To update the protobuf definitions for client generation, run:
24-
`git subtree pull --prefix=athena-protobufs https://github.com/crispthinking/athena-protobufs.git <sha> --squash`
77+
To update the protobuf definitions for client generation:
78+
79+
1. **Update the submodule to the latest version:**
80+
```sh
81+
git submodule update --remote athena-protobufs
82+
```
83+
84+
2. **Or update to a specific commit:**
85+
```sh
86+
cd athena-protobufs
87+
git checkout <commit-sha>
88+
cd ..
89+
git add athena-protobufs
90+
git commit -m "Update protobuf definitions to <commit-sha>"
91+
```
2592

2693
## Regenerating the TypeScript gRPC Client
2794

@@ -36,22 +103,33 @@ This project uses [`@protobuf-ts/plugin`](https://github.com/timostamm/protobuf-
36103
```
37104

38105
2. **Run the following command to regenerate the client and types:**
106+
```sh
107+
npm run codegen
108+
```
109+
110+
Or manually with:
39111
```sh
40112
npx protoc \
41113
--plugin=protoc-gen-ts=./node_modules/.bin/protoc-gen-ts \
42114
--ts_out=client_grpc1:./src/athena \
43-
--proto_path=./athena-protobufs/athena \
44-
./athena-protobufs/athena/athena.proto
115+
--proto_path=./athena-protobufs/athena-protobufs/athena \
116+
./athena-protobufs/athena-protobufs/athena/athena.proto
45117
```
46118
- This will generate `.ts` files in `src/athena/` including a gRPC client compatible with `@grpc/grpc-js`.
47119

48120
3. **Update your imports in your code as needed:**
49121
- The main client will be in `src/athena/athena.grpc-client.ts`.
50122
- Message types and enums are in `src/athena/athena.ts`.
51123

124+
3. **Format the generated code:**
125+
```sh
126+
npm run prettier
127+
```
128+
52129
### Notes
53-
- If you add or change proto files, rerun the above command to keep the TypeScript client in sync.
130+
- If you update proto files in the submodule, rerun `npm run codegen` to keep the TypeScript client in sync.
54131
- If you see TypeScript errors about missing modules, ensure your `tsconfig.json` includes the `src/athena` directory and restart your IDE/tsserver.
132+
- The generated files are automatically formatted by the pre-commit hooks, but you can run `npm run prettier` manually if needed.
55133

56134
---
57135

@@ -65,4 +143,4 @@ curl -LsSf https://astral.sh/uv/install.sh | sh
65143
uv sync
66144
cd docs
67145
make html
68-
The built documentation will be available in docs/build/html/index.html.
146+
The built documentation will be available in docs/build/html/index.html.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@
5252
"build:release": "npm run clean && tsc -p tsconfig.release.json",
5353
"codegen": "npx protoc --plugin=protoc-gen-ts=./node_modules/.bin/protoc-gen-ts --ts_out=client_grpc1:./src/athena --proto_path=./athena-protobufs/athena-protobufs/athena ./athena-protobufs/athena-protobufs/athena/athena.proto",
5454
"lint": "eslint .",
55+
"lint:all": "npm run lint && npm run prettier:check && npx tsc --noEmit",
56+
"precommit:setup": "echo 'To install pre-commit hooks, run: uv tool install pre-commit && uvx pre-commit install'",
5557
"test": "vitest run unit --config __tests__/vitest.config.ts",
5658
"test:coverage": "vitest run unit --config __tests__/vitest.config.ts --coverage.enabled --coverage.all",
5759
"prettier": "prettier \"{src,__{tests}__}/**/*.{ts,mts}\" --config .prettierrc --write",

src/athena/athena.grpc-client.ts

Lines changed: 139 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
// @generated by protobuf-ts 2.11.1 with parameter client_grpc1
22
// @generated from protobuf file "athena.proto" (package "athena", syntax proto3)
33
// tslint:disable
4-
import { ClassifierService } from "./athena";
5-
import type { BinaryWriteOptions } from "@protobuf-ts/runtime";
6-
import type { BinaryReadOptions } from "@protobuf-ts/runtime";
7-
import type { ListDeploymentsResponse } from "./athena";
8-
import type { Empty } from "./google/protobuf/empty";
9-
import type { ClassifyResponse } from "./athena";
10-
import type { ClassifyRequest } from "./athena";
11-
import * as grpc from "@grpc/grpc-js";
4+
import { ClassifierService } from './athena';
5+
import type { BinaryWriteOptions } from '@protobuf-ts/runtime';
6+
import type { BinaryReadOptions } from '@protobuf-ts/runtime';
7+
import type { ListDeploymentsResponse } from './athena';
8+
import type { Empty } from './google/protobuf/empty';
9+
import type { ClassifyResponse } from './athena';
10+
import type { ClassifyRequest } from './athena';
11+
import * as grpc from '@grpc/grpc-js';
1212
/**
1313
* The classifier service definition.
1414
* Provides image classification capabilities with session-based streaming
@@ -17,26 +17,59 @@ import * as grpc from "@grpc/grpc-js";
1717
* @generated from protobuf service athena.ClassifierService
1818
*/
1919
export interface IClassifierServiceClient {
20-
/**
21-
* Classify images in a deployment-based streaming context
22-
* Multiple affiliates can join the same deployment to share responses
23-
* Supports bidirectional streaming for real-time classification
24-
*
25-
* @generated from protobuf rpc: Classify
26-
*/
27-
classify(metadata: grpc.Metadata, options?: grpc.CallOptions): grpc.ClientDuplexStream<ClassifyRequest, ClassifyResponse>;
28-
classify(options?: grpc.CallOptions): grpc.ClientDuplexStream<ClassifyRequest, ClassifyResponse>;
29-
/**
30-
* Retrieves a list of all active deployment IDs
31-
* Returns the active deployment_id values that can be used in Classify requests
32-
* Useful for monitoring and debugging active connections
33-
*
34-
* @generated from protobuf rpc: ListDeployments
35-
*/
36-
listDeployments(input: Empty, metadata: grpc.Metadata, options: grpc.CallOptions, callback: (err: grpc.ServiceError | null, value?: ListDeploymentsResponse) => void): grpc.ClientUnaryCall;
37-
listDeployments(input: Empty, metadata: grpc.Metadata, callback: (err: grpc.ServiceError | null, value?: ListDeploymentsResponse) => void): grpc.ClientUnaryCall;
38-
listDeployments(input: Empty, options: grpc.CallOptions, callback: (err: grpc.ServiceError | null, value?: ListDeploymentsResponse) => void): grpc.ClientUnaryCall;
39-
listDeployments(input: Empty, callback: (err: grpc.ServiceError | null, value?: ListDeploymentsResponse) => void): grpc.ClientUnaryCall;
20+
/**
21+
* Classify images in a deployment-based streaming context
22+
* Multiple affiliates can join the same deployment to share responses
23+
* Supports bidirectional streaming for real-time classification
24+
*
25+
* @generated from protobuf rpc: Classify
26+
*/
27+
classify(
28+
metadata: grpc.Metadata,
29+
options?: grpc.CallOptions,
30+
): grpc.ClientDuplexStream<ClassifyRequest, ClassifyResponse>;
31+
classify(
32+
options?: grpc.CallOptions,
33+
): grpc.ClientDuplexStream<ClassifyRequest, ClassifyResponse>;
34+
/**
35+
* Retrieves a list of all active deployment IDs
36+
* Returns the active deployment_id values that can be used in Classify requests
37+
* Useful for monitoring and debugging active connections
38+
*
39+
* @generated from protobuf rpc: ListDeployments
40+
*/
41+
listDeployments(
42+
input: Empty,
43+
metadata: grpc.Metadata,
44+
options: grpc.CallOptions,
45+
callback: (
46+
err: grpc.ServiceError | null,
47+
value?: ListDeploymentsResponse,
48+
) => void,
49+
): grpc.ClientUnaryCall;
50+
listDeployments(
51+
input: Empty,
52+
metadata: grpc.Metadata,
53+
callback: (
54+
err: grpc.ServiceError | null,
55+
value?: ListDeploymentsResponse,
56+
) => void,
57+
): grpc.ClientUnaryCall;
58+
listDeployments(
59+
input: Empty,
60+
options: grpc.CallOptions,
61+
callback: (
62+
err: grpc.ServiceError | null,
63+
value?: ListDeploymentsResponse,
64+
) => void,
65+
): grpc.ClientUnaryCall;
66+
listDeployments(
67+
input: Empty,
68+
callback: (
69+
err: grpc.ServiceError | null,
70+
value?: ListDeploymentsResponse,
71+
) => void,
72+
): grpc.ClientUnaryCall;
4073
}
4174
/**
4275
* The classifier service definition.
@@ -45,32 +78,82 @@ export interface IClassifierServiceClient {
4578
*
4679
* @generated from protobuf service athena.ClassifierService
4780
*/
48-
export class ClassifierServiceClient extends grpc.Client implements IClassifierServiceClient {
49-
private readonly _binaryOptions: Partial<BinaryReadOptions & BinaryWriteOptions>;
50-
constructor(address: string, credentials: grpc.ChannelCredentials, options: grpc.ClientOptions = {}, binaryOptions: Partial<BinaryReadOptions & BinaryWriteOptions> = {}) {
51-
super(address, credentials, options);
52-
this._binaryOptions = binaryOptions;
53-
}
54-
/**
55-
* Classify images in a deployment-based streaming context
56-
* Multiple affiliates can join the same deployment to share responses
57-
* Supports bidirectional streaming for real-time classification
58-
*
59-
* @generated from protobuf rpc: Classify
60-
*/
61-
classify(metadata?: grpc.Metadata | grpc.CallOptions, options?: grpc.CallOptions): grpc.ClientDuplexStream<ClassifyRequest, ClassifyResponse> {
62-
const method = ClassifierService.methods[0];
63-
return this.makeBidiStreamRequest<ClassifyRequest, ClassifyResponse>(`/${ClassifierService.typeName}/${method.name}`, (value: ClassifyRequest): Buffer => Buffer.from(method.I.toBinary(value, this._binaryOptions)), (value: Buffer): ClassifyResponse => method.O.fromBinary(value, this._binaryOptions), (metadata as any), options);
64-
}
65-
/**
66-
* Retrieves a list of all active deployment IDs
67-
* Returns the active deployment_id values that can be used in Classify requests
68-
* Useful for monitoring and debugging active connections
69-
*
70-
* @generated from protobuf rpc: ListDeployments
71-
*/
72-
listDeployments(input: Empty, metadata: grpc.Metadata | grpc.CallOptions | ((err: grpc.ServiceError | null, value?: ListDeploymentsResponse) => void), options?: grpc.CallOptions | ((err: grpc.ServiceError | null, value?: ListDeploymentsResponse) => void), callback?: ((err: grpc.ServiceError | null, value?: ListDeploymentsResponse) => void)): grpc.ClientUnaryCall {
73-
const method = ClassifierService.methods[1];
74-
return this.makeUnaryRequest<Empty, ListDeploymentsResponse>(`/${ClassifierService.typeName}/${method.name}`, (value: Empty): Buffer => Buffer.from(method.I.toBinary(value, this._binaryOptions)), (value: Buffer): ListDeploymentsResponse => method.O.fromBinary(value, this._binaryOptions), input, (metadata as any), (options as any), (callback as any));
75-
}
81+
export class ClassifierServiceClient
82+
extends grpc.Client
83+
implements IClassifierServiceClient
84+
{
85+
private readonly _binaryOptions: Partial<
86+
BinaryReadOptions & BinaryWriteOptions
87+
>;
88+
constructor(
89+
address: string,
90+
credentials: grpc.ChannelCredentials,
91+
options: grpc.ClientOptions = {},
92+
binaryOptions: Partial<BinaryReadOptions & BinaryWriteOptions> = {},
93+
) {
94+
super(address, credentials, options);
95+
this._binaryOptions = binaryOptions;
96+
}
97+
/**
98+
* Classify images in a deployment-based streaming context
99+
* Multiple affiliates can join the same deployment to share responses
100+
* Supports bidirectional streaming for real-time classification
101+
*
102+
* @generated from protobuf rpc: Classify
103+
*/
104+
classify(
105+
metadata?: grpc.Metadata | grpc.CallOptions,
106+
options?: grpc.CallOptions,
107+
): grpc.ClientDuplexStream<ClassifyRequest, ClassifyResponse> {
108+
const method = ClassifierService.methods[0];
109+
return this.makeBidiStreamRequest<ClassifyRequest, ClassifyResponse>(
110+
`/${ClassifierService.typeName}/${method.name}`,
111+
(value: ClassifyRequest): Buffer =>
112+
Buffer.from(method.I.toBinary(value, this._binaryOptions)),
113+
(value: Buffer): ClassifyResponse =>
114+
method.O.fromBinary(value, this._binaryOptions),
115+
metadata as any,
116+
options,
117+
);
118+
}
119+
/**
120+
* Retrieves a list of all active deployment IDs
121+
* Returns the active deployment_id values that can be used in Classify requests
122+
* Useful for monitoring and debugging active connections
123+
*
124+
* @generated from protobuf rpc: ListDeployments
125+
*/
126+
listDeployments(
127+
input: Empty,
128+
metadata:
129+
| grpc.Metadata
130+
| grpc.CallOptions
131+
| ((
132+
err: grpc.ServiceError | null,
133+
value?: ListDeploymentsResponse,
134+
) => void),
135+
options?:
136+
| grpc.CallOptions
137+
| ((
138+
err: grpc.ServiceError | null,
139+
value?: ListDeploymentsResponse,
140+
) => void),
141+
callback?: (
142+
err: grpc.ServiceError | null,
143+
value?: ListDeploymentsResponse,
144+
) => void,
145+
): grpc.ClientUnaryCall {
146+
const method = ClassifierService.methods[1];
147+
return this.makeUnaryRequest<Empty, ListDeploymentsResponse>(
148+
`/${ClassifierService.typeName}/${method.name}`,
149+
(value: Empty): Buffer =>
150+
Buffer.from(method.I.toBinary(value, this._binaryOptions)),
151+
(value: Buffer): ListDeploymentsResponse =>
152+
method.O.fromBinary(value, this._binaryOptions),
153+
input,
154+
metadata as any,
155+
options as any,
156+
callback as any,
157+
);
158+
}
76159
}

0 commit comments

Comments
 (0)