gengo-ts 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,24 @@
1
+ // src/webhook/hono.ts
2
+ function honoAdapter(handler) {
3
+ return async (c) => {
4
+ if (c.req.method !== "POST") {
5
+ return c.text("Method not allowed", 405);
6
+ }
7
+ try {
8
+ const body = await c.req.parseBody();
9
+ const result = await handler.handleFormData(body);
10
+ if (result.success) {
11
+ return c.text("OK", 200);
12
+ } else {
13
+ return c.text(result.error?.message ?? "Processing failed", 500);
14
+ }
15
+ } catch (error) {
16
+ const message = error instanceof Error ? error.message : "Unknown error";
17
+ return c.text(message, 500);
18
+ }
19
+ };
20
+ }
21
+
22
+ export { honoAdapter };
23
+ //# sourceMappingURL=hono.js.map
24
+ //# sourceMappingURL=hono.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/webhook/hono.ts"],"names":[],"mappings":";AAsCO,SAAS,YAAY,OAAA,EAAsC;AAChE,EAAA,OAAO,OAAO,CAAA,KAAM;AAClB,IAAA,IAAI,CAAA,CAAE,GAAA,CAAI,MAAA,KAAW,MAAA,EAAQ;AAC3B,MAAA,OAAO,CAAA,CAAE,IAAA,CAAK,oBAAA,EAAsB,GAAG,CAAA;AAAA,IACzC;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,MAAM,CAAA,CAAE,GAAA,CAAI,SAAA,EAAU;AACnC,MAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,cAAA,CAAe,IAA8B,CAAA;AAE1E,MAAA,IAAI,OAAO,OAAA,EAAS;AAClB,QAAA,OAAO,CAAA,CAAE,IAAA,CAAK,IAAA,EAAM,GAAG,CAAA;AAAA,MACzB,CAAA,MAAO;AACL,QAAA,OAAO,EAAE,IAAA,CAAK,MAAA,CAAO,KAAA,EAAO,OAAA,IAAW,qBAAqB,GAAG,CAAA;AAAA,MACjE;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,OAAA,GAAU,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,eAAA;AACzD,MAAA,OAAO,CAAA,CAAE,IAAA,CAAK,OAAA,EAAS,GAAG,CAAA;AAAA,IAC5B;AAAA,EACF,CAAA;AACF","file":"hono.js","sourcesContent":["import type { WebhookHandler } from './index.js';\n\n/**\n * Hono-compatible context interface\n */\ninterface HonoContext {\n req: {\n method: string;\n parseBody(): Promise<Record<string, string>>;\n };\n text(body: string, status?: number): Response;\n}\n\n/**\n * Hono handler type\n */\ntype HonoHandler = (c: HonoContext) => Promise<Response>;\n\n/**\n * Creates a Hono handler adapter for the webhook handler\n *\n * @example\n * ```typescript\n * import { Hono } from 'hono';\n * import { createWebhookHandler } from 'gengo-ts/webhook';\n * import { honoAdapter } from 'gengo-ts/webhook/hono';\n *\n * const app = new Hono();\n *\n * const handler = createWebhookHandler({\n * onJobUpdate: (job) => {\n * console.log('Job updated:', job.job_id, job.status);\n * },\n * });\n *\n * app.post('/webhook', honoAdapter(handler));\n * ```\n */\nexport function honoAdapter(handler: WebhookHandler): HonoHandler {\n return async (c) => {\n if (c.req.method !== 'POST') {\n return c.text('Method not allowed', 405);\n }\n\n try {\n const body = await c.req.parseBody();\n const result = await handler.handleFormData(body as Record<string, string>);\n\n if (result.success) {\n return c.text('OK', 200);\n } else {\n return c.text(result.error?.message ?? 'Processing failed', 500);\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n return c.text(message, 500);\n }\n };\n}\n"]}
@@ -0,0 +1,95 @@
1
+ import { T as Tier, a as JobStatus, C as Currency } from '../common-Bk4hl8fX.js';
2
+
3
+ /**
4
+ * Job callback payload sent by Gengo
5
+ */
6
+ interface JobCallback {
7
+ job_id: number;
8
+ order_id: number;
9
+ body_src: string;
10
+ body_tgt: string;
11
+ lc_src: string;
12
+ lc_tgt: string;
13
+ unit_count: number;
14
+ tier: Tier;
15
+ credits: number;
16
+ status: JobStatus;
17
+ eta: number;
18
+ ctime: number;
19
+ callback_url: string;
20
+ auto_approve: boolean;
21
+ custom_data: string;
22
+ slug: string;
23
+ currency: Currency;
24
+ file_url_src?: string;
25
+ file_url_tgt?: string;
26
+ }
27
+ /**
28
+ * Comment callback payload sent by Gengo
29
+ */
30
+ interface CommentCallback {
31
+ job_id: string;
32
+ body: string;
33
+ ctime: string;
34
+ custom_data?: string;
35
+ file_url_tgt?: string;
36
+ }
37
+ /**
38
+ * Webhook handler callbacks
39
+ */
40
+ interface WebhookHandlerCallbacks {
41
+ /** Called when a job status update is received */
42
+ onJobUpdate?: (job: JobCallback) => void | Promise<void>;
43
+ /** Called when a translator comment is received */
44
+ onComment?: (comment: CommentCallback) => void | Promise<void>;
45
+ /** Called when an error occurs during processing */
46
+ onError?: (error: Error) => void | Promise<void>;
47
+ }
48
+ /**
49
+ * Parsed webhook payload
50
+ */
51
+ type WebhookPayload = {
52
+ type: 'job';
53
+ data: JobCallback;
54
+ } | {
55
+ type: 'comment';
56
+ data: CommentCallback;
57
+ };
58
+ /**
59
+ * Result of webhook processing
60
+ */
61
+ interface WebhookResult {
62
+ success: boolean;
63
+ type?: 'job' | 'comment';
64
+ error?: Error;
65
+ }
66
+
67
+ /**
68
+ * Webhook handler for processing Gengo callbacks
69
+ */
70
+ declare class WebhookHandler {
71
+ private readonly callbacks;
72
+ constructor(callbacks: WebhookHandlerCallbacks);
73
+ /**
74
+ * Parses form data and returns the webhook payload
75
+ */
76
+ parsePayload(formData: URLSearchParams | FormData | Record<string, string>): WebhookPayload | null;
77
+ /**
78
+ * Processes a webhook payload and calls the appropriate callback
79
+ */
80
+ process(payload: WebhookPayload): Promise<WebhookResult>;
81
+ /**
82
+ * Parses and processes a webhook request body
83
+ */
84
+ handleFormData(formData: URLSearchParams | FormData | Record<string, string>): Promise<WebhookResult>;
85
+ }
86
+ /**
87
+ * Creates a webhook handler with the specified callbacks
88
+ */
89
+ declare function createWebhookHandler(callbacks: WebhookHandlerCallbacks): WebhookHandler;
90
+ /**
91
+ * Handles a raw Web Request (for Deno, Bun, Cloudflare Workers)
92
+ */
93
+ declare function handleRequest(request: Request, handler: WebhookHandler): Promise<Response>;
94
+
95
+ export { type CommentCallback, type JobCallback, WebhookHandler, type WebhookHandlerCallbacks, type WebhookPayload, type WebhookResult, createWebhookHandler, handleRequest };
@@ -0,0 +1,100 @@
1
+ // src/webhook/index.ts
2
+ var WebhookHandler = class {
3
+ constructor(callbacks) {
4
+ this.callbacks = callbacks;
5
+ }
6
+ /**
7
+ * Parses form data and returns the webhook payload
8
+ */
9
+ parsePayload(formData) {
10
+ let jobData = null;
11
+ let commentData = null;
12
+ if (formData instanceof URLSearchParams) {
13
+ jobData = formData.get("job");
14
+ commentData = formData.get("comment");
15
+ } else if (formData instanceof FormData) {
16
+ const jobValue = formData.get("job");
17
+ const commentValue = formData.get("comment");
18
+ jobData = typeof jobValue === "string" ? jobValue : null;
19
+ commentData = typeof commentValue === "string" ? commentValue : null;
20
+ } else {
21
+ jobData = formData["job"] ?? null;
22
+ commentData = formData["comment"] ?? null;
23
+ }
24
+ if (jobData) {
25
+ return { type: "job", data: JSON.parse(jobData) };
26
+ }
27
+ if (commentData) {
28
+ return { type: "comment", data: JSON.parse(commentData) };
29
+ }
30
+ return null;
31
+ }
32
+ /**
33
+ * Processes a webhook payload and calls the appropriate callback
34
+ */
35
+ async process(payload) {
36
+ try {
37
+ if (payload.type === "job" && this.callbacks.onJobUpdate) {
38
+ await this.callbacks.onJobUpdate(payload.data);
39
+ return { success: true, type: "job" };
40
+ }
41
+ if (payload.type === "comment" && this.callbacks.onComment) {
42
+ await this.callbacks.onComment(payload.data);
43
+ return { success: true, type: "comment" };
44
+ }
45
+ return { success: true, type: payload.type };
46
+ } catch (error) {
47
+ const err = error instanceof Error ? error : new Error(String(error));
48
+ if (this.callbacks.onError) {
49
+ await this.callbacks.onError(err);
50
+ }
51
+ return { success: false, error: err };
52
+ }
53
+ }
54
+ /**
55
+ * Parses and processes a webhook request body
56
+ */
57
+ async handleFormData(formData) {
58
+ const payload = this.parsePayload(formData);
59
+ if (!payload) {
60
+ return {
61
+ success: false,
62
+ error: new Error("Invalid webhook payload: no job or comment data found")
63
+ };
64
+ }
65
+ return this.process(payload);
66
+ }
67
+ };
68
+ function createWebhookHandler(callbacks) {
69
+ return new WebhookHandler(callbacks);
70
+ }
71
+ async function handleRequest(request, handler) {
72
+ if (request.method !== "POST") {
73
+ return new Response("Method not allowed", { status: 405 });
74
+ }
75
+ const contentType = request.headers.get("content-type") ?? "";
76
+ try {
77
+ let formData;
78
+ if (contentType.includes("application/x-www-form-urlencoded")) {
79
+ const text = await request.text();
80
+ formData = new URLSearchParams(text);
81
+ } else if (contentType.includes("multipart/form-data")) {
82
+ formData = await request.formData();
83
+ } else {
84
+ return new Response("Unsupported content type", { status: 415 });
85
+ }
86
+ const result = await handler.handleFormData(formData);
87
+ if (result.success) {
88
+ return new Response("OK", { status: 200 });
89
+ } else {
90
+ return new Response(result.error?.message ?? "Processing failed", { status: 500 });
91
+ }
92
+ } catch (error) {
93
+ const message = error instanceof Error ? error.message : "Unknown error";
94
+ return new Response(message, { status: 500 });
95
+ }
96
+ }
97
+
98
+ export { WebhookHandler, createWebhookHandler, handleRequest };
99
+ //# sourceMappingURL=index.js.map
100
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/webhook/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type {\n JobCallback,\n CommentCallback,\n WebhookHandlerCallbacks,\n WebhookPayload,\n WebhookResult,\n} from './types.js';\n\nexport type {\n JobCallback,\n CommentCallback,\n WebhookHandlerCallbacks,\n WebhookPayload,\n WebhookResult,\n};\n\n/**\n * Webhook handler for processing Gengo callbacks\n */\nexport class WebhookHandler {\n constructor(private readonly callbacks: WebhookHandlerCallbacks) {}\n\n /**\n * Parses form data and returns the webhook payload\n */\n parsePayload(formData: URLSearchParams | FormData | Record<string, string>): WebhookPayload | null {\n let jobData: string | null = null;\n let commentData: string | null = null;\n\n if (formData instanceof URLSearchParams) {\n jobData = formData.get('job');\n commentData = formData.get('comment');\n } else if (formData instanceof FormData) {\n const jobValue = formData.get('job');\n const commentValue = formData.get('comment');\n jobData = typeof jobValue === 'string' ? jobValue : null;\n commentData = typeof commentValue === 'string' ? commentValue : null;\n } else {\n jobData = formData['job'] ?? null;\n commentData = formData['comment'] ?? null;\n }\n\n if (jobData) {\n return { type: 'job', data: JSON.parse(jobData) as JobCallback };\n }\n\n if (commentData) {\n return { type: 'comment', data: JSON.parse(commentData) as CommentCallback };\n }\n\n return null;\n }\n\n /**\n * Processes a webhook payload and calls the appropriate callback\n */\n async process(payload: WebhookPayload): Promise<WebhookResult> {\n try {\n if (payload.type === 'job' && this.callbacks.onJobUpdate) {\n await this.callbacks.onJobUpdate(payload.data);\n return { success: true, type: 'job' };\n }\n\n if (payload.type === 'comment' && this.callbacks.onComment) {\n await this.callbacks.onComment(payload.data);\n return { success: true, type: 'comment' };\n }\n\n return { success: true, type: payload.type };\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n if (this.callbacks.onError) {\n await this.callbacks.onError(err);\n }\n return { success: false, error: err };\n }\n }\n\n /**\n * Parses and processes a webhook request body\n */\n async handleFormData(\n formData: URLSearchParams | FormData | Record<string, string>\n ): Promise<WebhookResult> {\n const payload = this.parsePayload(formData);\n\n if (!payload) {\n return {\n success: false,\n error: new Error('Invalid webhook payload: no job or comment data found'),\n };\n }\n\n return this.process(payload);\n }\n}\n\n/**\n * Creates a webhook handler with the specified callbacks\n */\nexport function createWebhookHandler(\n callbacks: WebhookHandlerCallbacks\n): WebhookHandler {\n return new WebhookHandler(callbacks);\n}\n\n/**\n * Handles a raw Web Request (for Deno, Bun, Cloudflare Workers)\n */\nexport async function handleRequest(\n request: Request,\n handler: WebhookHandler\n): Promise<Response> {\n if (request.method !== 'POST') {\n return new Response('Method not allowed', { status: 405 });\n }\n\n const contentType = request.headers.get('content-type') ?? '';\n\n try {\n let formData: URLSearchParams | FormData;\n\n if (contentType.includes('application/x-www-form-urlencoded')) {\n const text = await request.text();\n formData = new URLSearchParams(text);\n } else if (contentType.includes('multipart/form-data')) {\n formData = await request.formData();\n } else {\n return new Response('Unsupported content type', { status: 415 });\n }\n\n const result = await handler.handleFormData(formData);\n\n if (result.success) {\n return new Response('OK', { status: 200 });\n } else {\n return new Response(result.error?.message ?? 'Processing failed', { status: 500 });\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n return new Response(message, { status: 500 });\n }\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "gengo-ts",
3
+ "version": "1.0.0",
4
+ "description": "Modern TypeScript client for the Gengo Translation API",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ },
14
+ "./webhook": {
15
+ "types": "./dist/webhook/index.d.ts",
16
+ "import": "./dist/webhook/index.js"
17
+ },
18
+ "./webhook/express": {
19
+ "types": "./dist/webhook/express.d.ts",
20
+ "import": "./dist/webhook/express.js"
21
+ },
22
+ "./webhook/hono": {
23
+ "types": "./dist/webhook/hono.d.ts",
24
+ "import": "./dist/webhook/hono.js"
25
+ }
26
+ },
27
+ "files": [
28
+ "dist",
29
+ "README.md"
30
+ ],
31
+ "scripts": {
32
+ "build": "tsup",
33
+ "dev": "tsup --watch",
34
+ "typecheck": "tsc --noEmit",
35
+ "clean": "rm -rf dist"
36
+ },
37
+ "keywords": [
38
+ "gengo",
39
+ "translation",
40
+ "api",
41
+ "typescript",
42
+ "i18n",
43
+ "localization"
44
+ ],
45
+ "author": "",
46
+ "license": "MIT",
47
+ "engines": {
48
+ "node": ">=18.0.0"
49
+ },
50
+ "devDependencies": {
51
+ "@types/node": "^20.10.0",
52
+ "tsup": "^8.0.1",
53
+ "typescript": "^5.3.0"
54
+ },
55
+ "peerDependencies": {
56
+ "express": "^4.18.0 || ^5.0.0",
57
+ "hono": "^3.0.0 || ^4.0.0"
58
+ },
59
+ "peerDependenciesMeta": {
60
+ "express": {
61
+ "optional": true
62
+ },
63
+ "hono": {
64
+ "optional": true
65
+ }
66
+ }
67
+ }