Skip to content

Commit 31b8fd0

Browse files
feat: add hash-server sample with TypeScript configuration and dependencies
- Created package.json for hash-server with dependencies on athena-classifier-sdk and TypeScript. - Added tsconfig.json with strict type checking and module resolution settings. - Updated authenticationManager.ts to improve error handling and type definitions. - Modified hashing.ts to support both Readable streams and Buffer types. - Refactored index.ts to enhance type safety and event handling. - Updated global tsconfig.json to enforce stricter type checking and module settings. - Adjusted tsconfig.release.json to include source maps and proper module targeting.
1 parent cc3c5c6 commit 31b8fd0

16 files changed

Lines changed: 1300 additions & 33 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ coverage
1111

1212
# Transpiled files
1313
build/
14+
dist/
1415

1516
# VS Code
1617
.vscode

__tests__/unit/main.test.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { describe, it, } from 'vitest';
2-
import { ClassificationOutput, ClassifierSdk, ClassifyImageInput, ImageFormat } from '../../src';
2+
import { ClassificationOutput, ClassifierSdk, type ClassifyImageInput, ImageFormat } from '../../src';
33
import fs from 'fs';
44
import { randomUUID } from 'crypto';
55

@@ -56,7 +56,7 @@ describe('ClassifierSdk', () => {
5656

5757
// Create 10 input objects, each with a new stream and unique correlationId
5858
const inputs: ClassifyImageInput[] = correlationIds.map((correlationId) => ({
59-
imageStream: fs.createReadStream(imagePath),
59+
data: fs.createReadStream(imagePath),
6060
format: ImageFormat.PNG,
6161
correlationId
6262
}));
@@ -110,6 +110,7 @@ describe('ClassifierSdk', () => {
110110
const expectedOutputs = correlationIds.map(id => (
111111
{
112112
correlationId: id,
113+
error: undefined,
113114
classifications: expect.toBeOneOf([expect.arrayContaining([
114115
{
115116
label: expect.any(String),
@@ -165,9 +166,9 @@ describe('ClassifierSdk', () => {
165166

166167
await sdk.open();
167168

168-
const imageStream = fs.createReadStream(imagePath);
169+
const data = fs.createReadStream(imagePath);
169170
const options: ClassifyImageInput = {
170-
imageStream,
171+
data,
171172
correlationId,
172173
resize: true,
173174
};
@@ -185,6 +186,7 @@ describe('ClassifierSdk', () => {
185186
expect(first).toMatchObject([
186187
{
187188
correlationId,
189+
error: undefined,
188190
classifications: expect.toBeOneOf([expect.arrayContaining([
189191
{
190192
label: expect.any(String),
@@ -242,9 +244,9 @@ describe('ClassifierSdk', () => {
242244

243245
await sdk.open();
244246

245-
const imageStream = fs.createReadStream(imagePath);
247+
const data = fs.createReadStream(imagePath);
246248
const options: ClassifyImageInput = {
247-
imageStream,
249+
data,
248250
correlationId,
249251
format: ImageFormat.JPEG,
250252
};
@@ -262,6 +264,7 @@ describe('ClassifierSdk', () => {
262264
expect(first).toMatchObject([
263265
{
264266
correlationId,
267+
error: undefined,
265268
classifications: expect.toBeOneOf([expect.arrayContaining([
266269
{
267270
label: expect.any(String),

__tests__/vitest.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export default defineConfig({
1010
coverage: {
1111
enabled: true,
1212
provider: 'v8',
13-
exclude: [...coverageConfigDefaults.exclude, 'build/**/*', 'src/athena/**/*']
13+
exclude: [...coverageConfigDefaults.exclude, 'build/**/*','samples/**/*', 'src/athena/**/*']
1414
},
1515
},
1616
})

eslint.config.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import tseslint from 'typescript-eslint';
99
// You should change it to your needs following the documentation.
1010
export default tseslint.config(
1111
{
12-
ignores: ['**/build/**', '.venv/**', '**/__tests__/**', '**/tmp/**', '**/coverage/**', 'src/athena/**'],
12+
ignores: ['**/dist/**', 'samples/**', '.venv/**', '**/__tests__/**', '**/tmp/**', '**/coverage/**', 'src/athena/**'],
1313
},
1414
eslint.configs.recommended,
1515
eslintConfigPrettier,

package.json

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
11
{
22
"name": "@crispthinking/athena-classifier-sdk",
33
"version": "0.1.0",
4-
"main": "./dist/index.js",
4+
"main": "./dist/src/index.js",
55
"description": "A Node.js SDK for the Athena classifier that uses gRPC transport.",
66
"type": "module",
77
"engines": {
88
"node": ">= 22.11 < 23"
99
},
10+
"files": [
11+
"dist/",
12+
"README.md",
13+
"LICENSE"
14+
],
15+
"exports": {
16+
".": {
17+
"import": "./dist/index.js",
18+
"require": "./dist/index.js"
19+
}
20+
},
1021
"devDependencies": {
1122
"@eslint/js": "~9.17",
1223
"@protobuf-ts/plugin": "^2.11.1",
@@ -39,7 +50,7 @@
3950
"build": "tsc -p tsconfig.json",
4051
"build:watch": "tsc -w -p tsconfig.json",
4152
"build:release": "npm run clean && tsc -p tsconfig.release.json",
42-
"codegen": "npx protoc --plugin=protoc-gen-ts=./node_modules/.bin/protoc-gen-ts --ts_out=client_grpc1:./src/athena --proto_path=./athena-protobufs/athena ./athena-protobufs/athena/athena.proto",
53+
"codegen": "npx protoc --plugin=protoc-gen-ts=./node_modules/.bin/protoc-gen-ts --ts_out=import_style=module,client_grpc1:./src/athena --proto_path=./athena-protobufs/athena ./athena-protobufs/athena/athena.proto",
4354
"lint": "eslint .",
4455
"test": "vitest run unit --config __tests__/vitest.config.ts",
4556
"test:coverage": "vitest run unit --config __tests__/vitest.config.ts --coverage.enabled --coverage.all",

samples/hash-server/.npmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@crispthinking:registry=https://npm.pkg.github.com

samples/hash-server/448x448.jpg

4.53 KB
Loading

samples/hash-server/index.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { ClassifierSdk, HashType, ImageFormat, RequestEncoding, type ClassifyImageInput } from '@crispthinking/athena-classifier-sdk';
2+
import { randomUUID } from 'crypto';
3+
import { createReadStream } from 'fs';
4+
import { inspect } from 'util';
5+
6+
7+
const sdk = new ClassifierSdk({
8+
authentication: {
9+
clientId: process.env.VITE_ATHENA_CLIENT_ID,
10+
clientSecret: process.env.VITE_ATHENA_CLIENT_SECRET,
11+
issuerUrl: process.env.VITE_OAUTH_ISSUER,
12+
scope: "manage:classify"
13+
},
14+
grpcAddress: 'csam-classification-messages.crispdev.com:443',
15+
affiliate: 'test-affiliate',
16+
deploymentId: 'node-js-client-test'
17+
});
18+
19+
sdk.on('data', (data) => {
20+
for(const item of data.outputs)
21+
{
22+
console.log(inspect(item, { showHidden: false, colors: true, depth: null, maxArrayLength: null, showProxy: false }));
23+
}
24+
});
25+
26+
await sdk.open();
27+
28+
// Enter loop to run until keypress entered.
29+
process.stdin.on('data', async (data) => {
30+
const input = data.toString().trim();
31+
if (input === 'exit') {
32+
await sdk.close();
33+
process.exit(0);
34+
}
35+
});
36+
37+
// Break if sigterm
38+
process.on('SIGTERM', async () => {
39+
await sdk.close();
40+
process.exit(0);
41+
});
42+
43+
while(true)
44+
{
45+
const inputs = Array.from({ length: 3 }, () => ({
46+
data: createReadStream('448x448.jpg'),
47+
format: ImageFormat.JPEG,
48+
correlationId: randomUUID(),
49+
encoding: RequestEncoding.UNCOMPRESSED,
50+
includeHashes: [HashType.MD5, HashType.SHA1]
51+
} as ClassifyImageInput));
52+
53+
await sdk.sendClassifyRequest(inputs);
54+
55+
// Sleep for 10 seconds
56+
await new Promise((resolve) => setTimeout(resolve, Math.random() * 10000));
57+
}

0 commit comments

Comments
 (0)