@danypops/tickets 0.8.4 → 0.8.6
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.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@danypops/tickets",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.6",
|
|
4
4
|
"description": "Unified CLI, daemon, and TypeScript library for issue tracking across GitHub, GitLab, and Jira.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
"typecheck": "tsc --noEmit"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@danypops/vehicle-core": "^0.
|
|
28
|
-
"@danypops/vehicle-server": "^0.
|
|
27
|
+
"@danypops/vehicle-core": "^0.12.1",
|
|
28
|
+
"@danypops/vehicle-server": "^0.17.0",
|
|
29
29
|
"@danypops/vehicle-client": "^0.5.0",
|
|
30
30
|
"@danypops/enigma-client": "^0.3.0",
|
|
31
31
|
"@gitbeaker/rest": "^43.8.0",
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import {
|
|
18
18
|
bindVehicleOperation,
|
|
19
|
+
defineErrorMapping,
|
|
19
20
|
defineLooseObjectSchema,
|
|
20
21
|
defineVehicleOperation,
|
|
21
22
|
type LooseObjectProperty,
|
|
@@ -24,11 +25,21 @@ import {
|
|
|
24
25
|
} from "@danypops/vehicle-core";
|
|
25
26
|
import { VehicleRegistry } from "@danypops/vehicle-server";
|
|
26
27
|
import type { BackendCapabilities, TicketService } from "../issue/service.js";
|
|
28
|
+
import { statusForKnownTicketError } from "../rpc/error-status.js";
|
|
27
29
|
import type { TicketOperation } from "../rpc/ops.js";
|
|
28
30
|
import { TICKET_OP_HANDLERS, type TicketsAppDeps } from "../rpc/server.js";
|
|
29
31
|
|
|
30
32
|
const OWNER = "tickets";
|
|
31
33
|
|
|
34
|
+
const withTicketsErrorParity = defineErrorMapping(
|
|
35
|
+
[
|
|
36
|
+
{ matches: (error) => statusForKnownTicketError(error) === 404, category: "not_found" },
|
|
37
|
+
{ matches: (error) => statusForKnownTicketError(error) === 400, category: "validation" },
|
|
38
|
+
{ matches: (error) => statusForKnownTicketError(error) === 422, category: "authorization" },
|
|
39
|
+
],
|
|
40
|
+
{ fallbackCategory: "internal", fallbackCode: "handler-failed", fallbackMessage: "Tickets operation failed" },
|
|
41
|
+
);
|
|
42
|
+
|
|
32
43
|
const LIMITS = { defaultTimeoutMs: 10_000, maxTimeoutMs: 30_000, maxRequestBytes: 65_536, maxResponseBytes: 262_144 };
|
|
33
44
|
|
|
34
45
|
const stringProp: LooseObjectProperty = { type: "string" };
|
|
@@ -285,10 +296,11 @@ export function syncDiscoverAvailability(registry: VehicleRegistry, service: Tic
|
|
|
285
296
|
export function createTicketsVehicleRegistry(deps: Omit<TicketsAppDeps, "vehicleRegistry">): VehicleRegistry {
|
|
286
297
|
const registry = new VehicleRegistry({
|
|
287
298
|
name: "tickets",
|
|
288
|
-
version:
|
|
299
|
+
version: deps.version,
|
|
289
300
|
description: "Unified issue tracking across GitHub, GitLab, and Jira.",
|
|
290
301
|
});
|
|
291
|
-
|
|
302
|
+
// Every handler passes through the reviewed mapper above; unmatched failures stay redacted.
|
|
303
|
+
registry.setExposeHandlerFailureDetails(true);
|
|
292
304
|
for (const spec of OPERATIONS) {
|
|
293
305
|
const operation = defineVehicleOperation({
|
|
294
306
|
name: spec.action,
|
|
@@ -305,7 +317,11 @@ export function createTicketsVehicleRegistry(deps: Omit<TicketsAppDeps, "vehicle
|
|
|
305
317
|
const mapInput = spec.mapInput ?? ((input: Record<string, unknown>) => input);
|
|
306
318
|
registry.register(
|
|
307
319
|
OWNER,
|
|
308
|
-
bindVehicleOperation(
|
|
320
|
+
bindVehicleOperation(
|
|
321
|
+
operation,
|
|
322
|
+
() => async (context) =>
|
|
323
|
+
withTicketsErrorParity<unknown>(() => handler(deps, mapInput(context.input as Record<string, unknown>) as never)),
|
|
324
|
+
),
|
|
309
325
|
);
|
|
310
326
|
}
|
|
311
327
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { AuthRequiredError, IssueNotFoundError } from "../issue/errors.js";
|
|
2
|
+
import { NotSupportedError, UnknownBackendError } from "../issue/service.js";
|
|
3
|
+
import { FocusError } from "../sqlite/focus.js";
|
|
4
|
+
import { SavedQueryNotFoundError } from "../sqlite/saved-queries.js";
|
|
5
|
+
|
|
6
|
+
/** Returns the legacy HTTP status only for reviewed business errors; unknown failures stay unclassified. */
|
|
7
|
+
export function statusForKnownTicketError(error: unknown): number | undefined {
|
|
8
|
+
if (error instanceof IssueNotFoundError || error instanceof SavedQueryNotFoundError) return 404;
|
|
9
|
+
if (error instanceof UnknownBackendError || error instanceof NotSupportedError || error instanceof FocusError) return 400;
|
|
10
|
+
if (error instanceof AuthRequiredError) return 422;
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
package/src/rpc/server.ts
CHANGED
|
@@ -11,12 +11,12 @@ import type { VehicleRegistry } from "@danypops/vehicle-server";
|
|
|
11
11
|
import { createVehicleHttpApp } from "@danypops/vehicle-server/http";
|
|
12
12
|
import type { Logger } from "@danypops/vehicle-server/logging";
|
|
13
13
|
import { errorResponse, healthResponse, jsonResponse, readyResponse, requireBearerToken } from "@danypops/vehicle-server/rpc-http";
|
|
14
|
-
import { AuthRequiredError, IssueNotFoundError } from "../issue/errors.js";
|
|
15
14
|
import { parseRef } from "../issue/issue.js";
|
|
16
|
-
import {
|
|
15
|
+
import type { TicketService } from "../issue/service.js";
|
|
17
16
|
import { FocusError, type FocusStore } from "../sqlite/focus.js";
|
|
18
17
|
import type { Ledger } from "../sqlite/ledger.js";
|
|
19
18
|
import { SavedQueryNotFoundError, type SavedQueryStore } from "../sqlite/saved-queries.js";
|
|
19
|
+
import { statusForKnownTicketError } from "./error-status.js";
|
|
20
20
|
import { TICKET_OPERATIONS, type TicketOperation, type TicketOpInputs, type TicketOpOutputs } from "./ops.js";
|
|
21
21
|
|
|
22
22
|
export interface TicketsAppDeps {
|
|
@@ -117,10 +117,7 @@ function isTicketOperation(value: unknown): value is TicketOperation {
|
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
function statusFor(error: unknown): number {
|
|
120
|
-
|
|
121
|
-
if (error instanceof UnknownBackendError || error instanceof NotSupportedError || error instanceof FocusError) return 400;
|
|
122
|
-
if (error instanceof AuthRequiredError) return 422;
|
|
123
|
-
return 500;
|
|
120
|
+
return statusForKnownTicketError(error) ?? 500;
|
|
124
121
|
}
|
|
125
122
|
|
|
126
123
|
export function buildApp(deps: TicketsAppDeps): { fetch(request: Request): Promise<Response> } {
|