hookshot-sdk 0.1.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,96 @@
1
+ import * as _repo_api from '@repo/api';
2
+ import { EndpointResponse, CreateEndpointInput, UpdateEndpointInput, IngestEventInput, IngestResponse, WebhookEventResponse, DeliveryAttemptResponse, DlqStats } from '@repo/api';
3
+ export { CreateEndpointInput, DeliveryAttemptResponse, DlqStats, EndpointResponse, EventStatus, IngestEventInput, IngestResponse, UpdateEndpointInput, WebhookEventResponse } from '@repo/api';
4
+
5
+ interface HookshotConfig {
6
+ apiKey: string;
7
+ baseUrl?: string;
8
+ }
9
+ interface ListEventsParams {
10
+ status?: 'pending' | 'delivering' | 'delivered' | 'failed' | 'dlq';
11
+ limit?: number;
12
+ offset?: number;
13
+ }
14
+ interface PaginationParams {
15
+ limit?: number;
16
+ offset?: number;
17
+ }
18
+ interface ReplayOptions {
19
+ resetRetryCount?: boolean;
20
+ }
21
+ interface ListEventsResponse {
22
+ events: _repo_api.WebhookEventResponse[];
23
+ total: number;
24
+ }
25
+ interface ReplayAllResponse {
26
+ replayedCount: number;
27
+ }
28
+ interface PurgeAllResponse {
29
+ purgedCount: number;
30
+ }
31
+
32
+ declare class HookshotClient {
33
+ private readonly apiKey;
34
+ private readonly baseUrl;
35
+ readonly endpoints: EndpointsAPI;
36
+ readonly events: EventsAPI;
37
+ readonly dlq: DlqAPI;
38
+ constructor(config: HookshotConfig);
39
+ request<T>(method: string, path: string, options?: {
40
+ body?: unknown;
41
+ query?: Record<string, string | number | undefined>;
42
+ }): Promise<T>;
43
+ }
44
+ declare class EndpointsAPI {
45
+ private readonly client;
46
+ constructor(client: HookshotClient);
47
+ list(): Promise<EndpointResponse[]>;
48
+ create(data: CreateEndpointInput): Promise<EndpointResponse>;
49
+ get(id: string): Promise<EndpointResponse>;
50
+ update(id: string, data: UpdateEndpointInput): Promise<EndpointResponse>;
51
+ delete(id: string): Promise<void>;
52
+ }
53
+ declare class EventsAPI {
54
+ private readonly client;
55
+ constructor(client: HookshotClient);
56
+ send(data: IngestEventInput): Promise<IngestResponse>;
57
+ list(params?: ListEventsParams): Promise<ListEventsResponse>;
58
+ get(id: string): Promise<WebhookEventResponse>;
59
+ getAttempts(eventId: string): Promise<DeliveryAttemptResponse[]>;
60
+ }
61
+ declare class DlqAPI {
62
+ private readonly client;
63
+ constructor(client: HookshotClient);
64
+ list(params?: PaginationParams): Promise<ListEventsResponse>;
65
+ stats(): Promise<DlqStats>;
66
+ replay(eventId: string, options?: ReplayOptions): Promise<WebhookEventResponse>;
67
+ replayAll(): Promise<ReplayAllResponse>;
68
+ purge(eventId: string): Promise<void>;
69
+ purgeAll(): Promise<PurgeAllResponse>;
70
+ }
71
+
72
+ declare class HookshotError extends Error {
73
+ readonly code: string;
74
+ readonly status: number;
75
+ readonly details?: Record<string, unknown>;
76
+ constructor(options: {
77
+ message: string;
78
+ code: string;
79
+ status: number;
80
+ details?: Record<string, unknown>;
81
+ });
82
+ static fromResponse(status: number, body: unknown): HookshotError;
83
+ static networkError(message: string): HookshotError;
84
+ }
85
+ declare class HookshotValidationError extends HookshotError {
86
+ constructor(message: string, details?: Record<string, unknown>);
87
+ }
88
+ declare class HookshotAuthenticationError extends HookshotError {
89
+ constructor(message?: string);
90
+ }
91
+ declare class HookshotRateLimitError extends HookshotError {
92
+ readonly retryAfter?: number;
93
+ constructor(message?: string, retryAfter?: number);
94
+ }
95
+
96
+ export { HookshotAuthenticationError, HookshotClient, type HookshotConfig, HookshotError, HookshotRateLimitError, HookshotValidationError, type ListEventsParams, type ListEventsResponse, type PaginationParams, type PurgeAllResponse, type ReplayAllResponse, type ReplayOptions };
@@ -0,0 +1,96 @@
1
+ import * as _repo_api from '@repo/api';
2
+ import { EndpointResponse, CreateEndpointInput, UpdateEndpointInput, IngestEventInput, IngestResponse, WebhookEventResponse, DeliveryAttemptResponse, DlqStats } from '@repo/api';
3
+ export { CreateEndpointInput, DeliveryAttemptResponse, DlqStats, EndpointResponse, EventStatus, IngestEventInput, IngestResponse, UpdateEndpointInput, WebhookEventResponse } from '@repo/api';
4
+
5
+ interface HookshotConfig {
6
+ apiKey: string;
7
+ baseUrl?: string;
8
+ }
9
+ interface ListEventsParams {
10
+ status?: 'pending' | 'delivering' | 'delivered' | 'failed' | 'dlq';
11
+ limit?: number;
12
+ offset?: number;
13
+ }
14
+ interface PaginationParams {
15
+ limit?: number;
16
+ offset?: number;
17
+ }
18
+ interface ReplayOptions {
19
+ resetRetryCount?: boolean;
20
+ }
21
+ interface ListEventsResponse {
22
+ events: _repo_api.WebhookEventResponse[];
23
+ total: number;
24
+ }
25
+ interface ReplayAllResponse {
26
+ replayedCount: number;
27
+ }
28
+ interface PurgeAllResponse {
29
+ purgedCount: number;
30
+ }
31
+
32
+ declare class HookshotClient {
33
+ private readonly apiKey;
34
+ private readonly baseUrl;
35
+ readonly endpoints: EndpointsAPI;
36
+ readonly events: EventsAPI;
37
+ readonly dlq: DlqAPI;
38
+ constructor(config: HookshotConfig);
39
+ request<T>(method: string, path: string, options?: {
40
+ body?: unknown;
41
+ query?: Record<string, string | number | undefined>;
42
+ }): Promise<T>;
43
+ }
44
+ declare class EndpointsAPI {
45
+ private readonly client;
46
+ constructor(client: HookshotClient);
47
+ list(): Promise<EndpointResponse[]>;
48
+ create(data: CreateEndpointInput): Promise<EndpointResponse>;
49
+ get(id: string): Promise<EndpointResponse>;
50
+ update(id: string, data: UpdateEndpointInput): Promise<EndpointResponse>;
51
+ delete(id: string): Promise<void>;
52
+ }
53
+ declare class EventsAPI {
54
+ private readonly client;
55
+ constructor(client: HookshotClient);
56
+ send(data: IngestEventInput): Promise<IngestResponse>;
57
+ list(params?: ListEventsParams): Promise<ListEventsResponse>;
58
+ get(id: string): Promise<WebhookEventResponse>;
59
+ getAttempts(eventId: string): Promise<DeliveryAttemptResponse[]>;
60
+ }
61
+ declare class DlqAPI {
62
+ private readonly client;
63
+ constructor(client: HookshotClient);
64
+ list(params?: PaginationParams): Promise<ListEventsResponse>;
65
+ stats(): Promise<DlqStats>;
66
+ replay(eventId: string, options?: ReplayOptions): Promise<WebhookEventResponse>;
67
+ replayAll(): Promise<ReplayAllResponse>;
68
+ purge(eventId: string): Promise<void>;
69
+ purgeAll(): Promise<PurgeAllResponse>;
70
+ }
71
+
72
+ declare class HookshotError extends Error {
73
+ readonly code: string;
74
+ readonly status: number;
75
+ readonly details?: Record<string, unknown>;
76
+ constructor(options: {
77
+ message: string;
78
+ code: string;
79
+ status: number;
80
+ details?: Record<string, unknown>;
81
+ });
82
+ static fromResponse(status: number, body: unknown): HookshotError;
83
+ static networkError(message: string): HookshotError;
84
+ }
85
+ declare class HookshotValidationError extends HookshotError {
86
+ constructor(message: string, details?: Record<string, unknown>);
87
+ }
88
+ declare class HookshotAuthenticationError extends HookshotError {
89
+ constructor(message?: string);
90
+ }
91
+ declare class HookshotRateLimitError extends HookshotError {
92
+ readonly retryAfter?: number;
93
+ constructor(message?: string, retryAfter?: number);
94
+ }
95
+
96
+ export { HookshotAuthenticationError, HookshotClient, type HookshotConfig, HookshotError, HookshotRateLimitError, HookshotValidationError, type ListEventsParams, type ListEventsResponse, type PaginationParams, type PurgeAllResponse, type ReplayAllResponse, type ReplayOptions };
package/dist/index.js ADDED
@@ -0,0 +1,253 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ HookshotAuthenticationError: () => HookshotAuthenticationError,
24
+ HookshotClient: () => HookshotClient,
25
+ HookshotError: () => HookshotError,
26
+ HookshotRateLimitError: () => HookshotRateLimitError,
27
+ HookshotValidationError: () => HookshotValidationError
28
+ });
29
+ module.exports = __toCommonJS(index_exports);
30
+
31
+ // src/errors.ts
32
+ var HookshotError = class _HookshotError extends Error {
33
+ code;
34
+ status;
35
+ details;
36
+ constructor(options) {
37
+ super(options.message);
38
+ this.name = "HookshotError";
39
+ this.code = options.code;
40
+ this.status = options.status;
41
+ this.details = options.details;
42
+ Object.setPrototypeOf(this, _HookshotError.prototype);
43
+ }
44
+ static fromResponse(status, body) {
45
+ const parsed = body;
46
+ return new _HookshotError({
47
+ message: parsed?.message || parsed?.error || `HTTP ${status}`,
48
+ code: parsed?.code || "UNKNOWN_ERROR",
49
+ status,
50
+ details: typeof parsed === "object" && parsed !== null ? parsed : void 0
51
+ });
52
+ }
53
+ static networkError(message) {
54
+ return new _HookshotError({
55
+ message,
56
+ code: "NETWORK_ERROR",
57
+ status: 0
58
+ });
59
+ }
60
+ };
61
+ var HookshotValidationError = class _HookshotValidationError extends HookshotError {
62
+ constructor(message, details) {
63
+ super({
64
+ message,
65
+ code: "VALIDATION_ERROR",
66
+ status: 400,
67
+ details
68
+ });
69
+ this.name = "HookshotValidationError";
70
+ Object.setPrototypeOf(this, _HookshotValidationError.prototype);
71
+ }
72
+ };
73
+ var HookshotAuthenticationError = class _HookshotAuthenticationError extends HookshotError {
74
+ constructor(message = "Invalid or missing API key") {
75
+ super({
76
+ message,
77
+ code: "AUTHENTICATION_ERROR",
78
+ status: 401
79
+ });
80
+ this.name = "HookshotAuthenticationError";
81
+ Object.setPrototypeOf(this, _HookshotAuthenticationError.prototype);
82
+ }
83
+ };
84
+ var HookshotRateLimitError = class _HookshotRateLimitError extends HookshotError {
85
+ retryAfter;
86
+ constructor(message = "Rate limit exceeded", retryAfter) {
87
+ super({
88
+ message,
89
+ code: "RATE_LIMIT_EXCEEDED",
90
+ status: 429,
91
+ details: retryAfter ? { retryAfter } : void 0
92
+ });
93
+ this.name = "HookshotRateLimitError";
94
+ this.retryAfter = retryAfter;
95
+ Object.setPrototypeOf(this, _HookshotRateLimitError.prototype);
96
+ }
97
+ };
98
+
99
+ // src/client.ts
100
+ var DEFAULT_BASE_URL = "http://localhost:3001";
101
+ var HookshotClient = class {
102
+ apiKey;
103
+ baseUrl;
104
+ endpoints;
105
+ events;
106
+ dlq;
107
+ constructor(config) {
108
+ if (!config.apiKey) {
109
+ throw new HookshotError({
110
+ message: "API key is required",
111
+ code: "MISSING_API_KEY",
112
+ status: 400
113
+ });
114
+ }
115
+ this.apiKey = config.apiKey;
116
+ this.baseUrl = (config.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
117
+ this.endpoints = new EndpointsAPI(this);
118
+ this.events = new EventsAPI(this);
119
+ this.dlq = new DlqAPI(this);
120
+ }
121
+ async request(method, path, options) {
122
+ let url = `${this.baseUrl}${path}`;
123
+ if (options?.query) {
124
+ const params = new URLSearchParams();
125
+ for (const [key, value] of Object.entries(options.query)) {
126
+ if (value !== void 0) {
127
+ params.set(key, String(value));
128
+ }
129
+ }
130
+ const qs = params.toString();
131
+ if (qs) {
132
+ url += `?${qs}`;
133
+ }
134
+ }
135
+ const headers = {
136
+ "Content-Type": "application/json",
137
+ "x-api-key": this.apiKey
138
+ };
139
+ const fetchOptions = {
140
+ method,
141
+ headers
142
+ };
143
+ if (options?.body !== void 0) {
144
+ fetchOptions.body = JSON.stringify(options.body);
145
+ }
146
+ let response;
147
+ try {
148
+ response = await fetch(url, fetchOptions);
149
+ } catch (error) {
150
+ throw HookshotError.networkError(
151
+ error instanceof Error ? error.message : "Network request failed"
152
+ );
153
+ }
154
+ if (!response.ok) {
155
+ let body;
156
+ try {
157
+ body = await response.json();
158
+ } catch {
159
+ body = null;
160
+ }
161
+ if (response.status === 401) {
162
+ throw new HookshotAuthenticationError();
163
+ }
164
+ if (response.status === 429) {
165
+ const retryAfter = response.headers.get("Retry-After");
166
+ throw new HookshotRateLimitError(
167
+ "Rate limit exceeded",
168
+ retryAfter ? parseInt(retryAfter, 10) : void 0
169
+ );
170
+ }
171
+ throw HookshotError.fromResponse(response.status, body);
172
+ }
173
+ if (response.status === 204) {
174
+ return void 0;
175
+ }
176
+ return response.json();
177
+ }
178
+ };
179
+ var EndpointsAPI = class {
180
+ constructor(client) {
181
+ this.client = client;
182
+ }
183
+ async list() {
184
+ return this.client.request("GET", "/endpoints");
185
+ }
186
+ async create(data) {
187
+ return this.client.request("POST", "/endpoints", { body: data });
188
+ }
189
+ async get(id) {
190
+ return this.client.request("GET", `/endpoints/${id}`);
191
+ }
192
+ async update(id, data) {
193
+ return this.client.request("PATCH", `/endpoints/${id}`, { body: data });
194
+ }
195
+ async delete(id) {
196
+ return this.client.request("DELETE", `/endpoints/${id}`);
197
+ }
198
+ };
199
+ var EventsAPI = class {
200
+ constructor(client) {
201
+ this.client = client;
202
+ }
203
+ async send(data) {
204
+ return this.client.request("POST", "/ingest", { body: data });
205
+ }
206
+ async list(params) {
207
+ return this.client.request("GET", "/events", {
208
+ query: params
209
+ });
210
+ }
211
+ async get(id) {
212
+ return this.client.request("GET", `/events/${id}`);
213
+ }
214
+ async getAttempts(eventId) {
215
+ return this.client.request("GET", `/events/${eventId}/attempts`);
216
+ }
217
+ };
218
+ var DlqAPI = class {
219
+ constructor(client) {
220
+ this.client = client;
221
+ }
222
+ async list(params) {
223
+ return this.client.request("GET", "/dlq", {
224
+ query: params
225
+ });
226
+ }
227
+ async stats() {
228
+ return this.client.request("GET", "/dlq/stats");
229
+ }
230
+ async replay(eventId, options) {
231
+ return this.client.request("POST", `/dlq/${eventId}/replay`, {
232
+ body: options || {}
233
+ });
234
+ }
235
+ async replayAll() {
236
+ return this.client.request("POST", "/dlq/replay-all");
237
+ }
238
+ async purge(eventId) {
239
+ return this.client.request("DELETE", `/dlq/${eventId}`);
240
+ }
241
+ async purgeAll() {
242
+ return this.client.request("DELETE", "/dlq");
243
+ }
244
+ };
245
+ // Annotate the CommonJS export names for ESM import in node:
246
+ 0 && (module.exports = {
247
+ HookshotAuthenticationError,
248
+ HookshotClient,
249
+ HookshotError,
250
+ HookshotRateLimitError,
251
+ HookshotValidationError
252
+ });
253
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/client.ts"],"sourcesContent":["export { HookshotClient } from './client';\n\nexport {\n HookshotError,\n HookshotValidationError,\n HookshotAuthenticationError,\n HookshotRateLimitError,\n} from './errors';\n\nexport type {\n HookshotConfig,\n ListEventsParams,\n PaginationParams,\n ReplayOptions,\n ListEventsResponse,\n ReplayAllResponse,\n PurgeAllResponse,\n EndpointResponse,\n CreateEndpointInput,\n UpdateEndpointInput,\n WebhookEventResponse,\n IngestEventInput,\n IngestResponse,\n DeliveryAttemptResponse,\n DlqStats,\n EventStatus,\n} from './types';\n","export class HookshotError extends Error {\n public readonly code: string;\n public readonly status: number;\n public readonly details?: Record<string, unknown>;\n\n constructor(options: {\n message: string;\n code: string;\n status: number;\n details?: Record<string, unknown>;\n }) {\n super(options.message);\n this.name = 'HookshotError';\n this.code = options.code;\n this.status = options.status;\n this.details = options.details;\n\n Object.setPrototypeOf(this, HookshotError.prototype);\n }\n\n static fromResponse(status: number, body: unknown): HookshotError {\n const parsed = body as { message?: string; code?: string; error?: string } | null;\n \n return new HookshotError({\n message: parsed?.message || parsed?.error || `HTTP ${status}`,\n code: parsed?.code || 'UNKNOWN_ERROR',\n status,\n details: typeof parsed === 'object' && parsed !== null ? parsed : undefined,\n });\n }\n\n static networkError(message: string): HookshotError {\n return new HookshotError({\n message,\n code: 'NETWORK_ERROR',\n status: 0,\n });\n }\n}\n\nexport class HookshotValidationError extends HookshotError {\n constructor(message: string, details?: Record<string, unknown>) {\n super({\n message,\n code: 'VALIDATION_ERROR',\n status: 400,\n details,\n });\n this.name = 'HookshotValidationError';\n Object.setPrototypeOf(this, HookshotValidationError.prototype);\n }\n}\n\nexport class HookshotAuthenticationError extends HookshotError {\n constructor(message: string = 'Invalid or missing API key') {\n super({\n message,\n code: 'AUTHENTICATION_ERROR',\n status: 401,\n });\n this.name = 'HookshotAuthenticationError';\n Object.setPrototypeOf(this, HookshotAuthenticationError.prototype);\n }\n}\n\nexport class HookshotRateLimitError extends HookshotError {\n public readonly retryAfter?: number;\n\n constructor(message: string = 'Rate limit exceeded', retryAfter?: number) {\n super({\n message,\n code: 'RATE_LIMIT_EXCEEDED',\n status: 429,\n details: retryAfter ? { retryAfter } : undefined,\n });\n this.name = 'HookshotRateLimitError';\n this.retryAfter = retryAfter;\n Object.setPrototypeOf(this, HookshotRateLimitError.prototype);\n }\n}\n","import type {\n EndpointResponse,\n CreateEndpointInput,\n UpdateEndpointInput,\n WebhookEventResponse,\n IngestEventInput,\n IngestResponse,\n DeliveryAttemptResponse,\n DlqStats,\n} from '@repo/api';\n\nimport {\n HookshotError,\n HookshotAuthenticationError,\n HookshotRateLimitError,\n} from './errors';\n\nimport type {\n HookshotConfig,\n ListEventsParams,\n PaginationParams,\n ReplayOptions,\n ListEventsResponse,\n ReplayAllResponse,\n PurgeAllResponse,\n} from './types';\n\nconst DEFAULT_BASE_URL = 'http://localhost:3001';\n\nexport class HookshotClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n\n public readonly endpoints: EndpointsAPI;\n public readonly events: EventsAPI;\n public readonly dlq: DlqAPI;\n\n constructor(config: HookshotConfig) {\n if (!config.apiKey) {\n throw new HookshotError({\n message: 'API key is required',\n code: 'MISSING_API_KEY',\n status: 400,\n });\n }\n\n this.apiKey = config.apiKey;\n this.baseUrl = (config.baseUrl || DEFAULT_BASE_URL).replace(/\\/$/, '');\n\n this.endpoints = new EndpointsAPI(this);\n this.events = new EventsAPI(this);\n this.dlq = new DlqAPI(this);\n }\n\n async request<T>(\n method: string,\n path: string,\n options?: { body?: unknown; query?: Record<string, string | number | undefined> }\n ): Promise<T> {\n let url = `${this.baseUrl}${path}`;\n\n if (options?.query) {\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(options.query)) {\n if (value !== undefined) {\n params.set(key, String(value));\n }\n }\n const qs = params.toString();\n if (qs) {\n url += `?${qs}`;\n }\n }\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'x-api-key': this.apiKey,\n };\n\n const fetchOptions: RequestInit = {\n method,\n headers,\n };\n\n if (options?.body !== undefined) {\n fetchOptions.body = JSON.stringify(options.body);\n }\n\n let response: Response;\n try {\n response = await fetch(url, fetchOptions);\n } catch (error) {\n throw HookshotError.networkError(\n error instanceof Error ? error.message : 'Network request failed'\n );\n }\n\n if (!response.ok) {\n let body: unknown;\n try {\n body = await response.json();\n } catch {\n body = null;\n }\n\n if (response.status === 401) {\n throw new HookshotAuthenticationError();\n }\n\n if (response.status === 429) {\n const retryAfter = response.headers.get('Retry-After');\n throw new HookshotRateLimitError(\n 'Rate limit exceeded',\n retryAfter ? parseInt(retryAfter, 10) : undefined\n );\n }\n\n throw HookshotError.fromResponse(response.status, body);\n }\n\n if (response.status === 204) {\n return undefined as T;\n }\n\n return response.json() as Promise<T>;\n }\n}\n\nclass EndpointsAPI {\n constructor(private readonly client: HookshotClient) {}\n\n async list(): Promise<EndpointResponse[]> {\n return this.client.request<EndpointResponse[]>('GET', '/endpoints');\n }\n\n async create(data: CreateEndpointInput): Promise<EndpointResponse> {\n return this.client.request<EndpointResponse>('POST', '/endpoints', { body: data });\n }\n\n async get(id: string): Promise<EndpointResponse> {\n return this.client.request<EndpointResponse>('GET', `/endpoints/${id}`);\n }\n\n async update(id: string, data: UpdateEndpointInput): Promise<EndpointResponse> {\n return this.client.request<EndpointResponse>('PATCH', `/endpoints/${id}`, { body: data });\n }\n\n async delete(id: string): Promise<void> {\n return this.client.request<void>('DELETE', `/endpoints/${id}`);\n }\n}\n\nclass EventsAPI {\n constructor(private readonly client: HookshotClient) {}\n\n async send(data: IngestEventInput): Promise<IngestResponse> {\n return this.client.request<IngestResponse>('POST', '/ingest', { body: data });\n }\n\n async list(params?: ListEventsParams): Promise<ListEventsResponse> {\n return this.client.request<ListEventsResponse>('GET', '/events', {\n query: params as Record<string, string | number | undefined>,\n });\n }\n\n async get(id: string): Promise<WebhookEventResponse> {\n return this.client.request<WebhookEventResponse>('GET', `/events/${id}`);\n }\n\n async getAttempts(eventId: string): Promise<DeliveryAttemptResponse[]> {\n return this.client.request<DeliveryAttemptResponse[]>('GET', `/events/${eventId}/attempts`);\n }\n}\n\nclass DlqAPI {\n constructor(private readonly client: HookshotClient) {}\n\n async list(params?: PaginationParams): Promise<ListEventsResponse> {\n return this.client.request<ListEventsResponse>('GET', '/dlq', {\n query: params as Record<string, string | number | undefined>,\n });\n }\n\n async stats(): Promise<DlqStats> {\n return this.client.request<DlqStats>('GET', '/dlq/stats');\n }\n\n async replay(eventId: string, options?: ReplayOptions): Promise<WebhookEventResponse> {\n return this.client.request<WebhookEventResponse>('POST', `/dlq/${eventId}/replay`, {\n body: options || {},\n });\n }\n\n async replayAll(): Promise<ReplayAllResponse> {\n return this.client.request<ReplayAllResponse>('POST', '/dlq/replay-all');\n }\n\n async purge(eventId: string): Promise<void> {\n return this.client.request<void>('DELETE', `/dlq/${eventId}`);\n }\n\n async purgeAll(): Promise<PurgeAllResponse> {\n return this.client.request<PurgeAllResponse>('DELETE', '/dlq');\n }\n}\n"],"mappings":"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","names":[]}
package/dist/index.mjs ADDED
@@ -0,0 +1,222 @@
1
+ // src/errors.ts
2
+ var HookshotError = class _HookshotError extends Error {
3
+ code;
4
+ status;
5
+ details;
6
+ constructor(options) {
7
+ super(options.message);
8
+ this.name = "HookshotError";
9
+ this.code = options.code;
10
+ this.status = options.status;
11
+ this.details = options.details;
12
+ Object.setPrototypeOf(this, _HookshotError.prototype);
13
+ }
14
+ static fromResponse(status, body) {
15
+ const parsed = body;
16
+ return new _HookshotError({
17
+ message: parsed?.message || parsed?.error || `HTTP ${status}`,
18
+ code: parsed?.code || "UNKNOWN_ERROR",
19
+ status,
20
+ details: typeof parsed === "object" && parsed !== null ? parsed : void 0
21
+ });
22
+ }
23
+ static networkError(message) {
24
+ return new _HookshotError({
25
+ message,
26
+ code: "NETWORK_ERROR",
27
+ status: 0
28
+ });
29
+ }
30
+ };
31
+ var HookshotValidationError = class _HookshotValidationError extends HookshotError {
32
+ constructor(message, details) {
33
+ super({
34
+ message,
35
+ code: "VALIDATION_ERROR",
36
+ status: 400,
37
+ details
38
+ });
39
+ this.name = "HookshotValidationError";
40
+ Object.setPrototypeOf(this, _HookshotValidationError.prototype);
41
+ }
42
+ };
43
+ var HookshotAuthenticationError = class _HookshotAuthenticationError extends HookshotError {
44
+ constructor(message = "Invalid or missing API key") {
45
+ super({
46
+ message,
47
+ code: "AUTHENTICATION_ERROR",
48
+ status: 401
49
+ });
50
+ this.name = "HookshotAuthenticationError";
51
+ Object.setPrototypeOf(this, _HookshotAuthenticationError.prototype);
52
+ }
53
+ };
54
+ var HookshotRateLimitError = class _HookshotRateLimitError extends HookshotError {
55
+ retryAfter;
56
+ constructor(message = "Rate limit exceeded", retryAfter) {
57
+ super({
58
+ message,
59
+ code: "RATE_LIMIT_EXCEEDED",
60
+ status: 429,
61
+ details: retryAfter ? { retryAfter } : void 0
62
+ });
63
+ this.name = "HookshotRateLimitError";
64
+ this.retryAfter = retryAfter;
65
+ Object.setPrototypeOf(this, _HookshotRateLimitError.prototype);
66
+ }
67
+ };
68
+
69
+ // src/client.ts
70
+ var DEFAULT_BASE_URL = "http://localhost:3001";
71
+ var HookshotClient = class {
72
+ apiKey;
73
+ baseUrl;
74
+ endpoints;
75
+ events;
76
+ dlq;
77
+ constructor(config) {
78
+ if (!config.apiKey) {
79
+ throw new HookshotError({
80
+ message: "API key is required",
81
+ code: "MISSING_API_KEY",
82
+ status: 400
83
+ });
84
+ }
85
+ this.apiKey = config.apiKey;
86
+ this.baseUrl = (config.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
87
+ this.endpoints = new EndpointsAPI(this);
88
+ this.events = new EventsAPI(this);
89
+ this.dlq = new DlqAPI(this);
90
+ }
91
+ async request(method, path, options) {
92
+ let url = `${this.baseUrl}${path}`;
93
+ if (options?.query) {
94
+ const params = new URLSearchParams();
95
+ for (const [key, value] of Object.entries(options.query)) {
96
+ if (value !== void 0) {
97
+ params.set(key, String(value));
98
+ }
99
+ }
100
+ const qs = params.toString();
101
+ if (qs) {
102
+ url += `?${qs}`;
103
+ }
104
+ }
105
+ const headers = {
106
+ "Content-Type": "application/json",
107
+ "x-api-key": this.apiKey
108
+ };
109
+ const fetchOptions = {
110
+ method,
111
+ headers
112
+ };
113
+ if (options?.body !== void 0) {
114
+ fetchOptions.body = JSON.stringify(options.body);
115
+ }
116
+ let response;
117
+ try {
118
+ response = await fetch(url, fetchOptions);
119
+ } catch (error) {
120
+ throw HookshotError.networkError(
121
+ error instanceof Error ? error.message : "Network request failed"
122
+ );
123
+ }
124
+ if (!response.ok) {
125
+ let body;
126
+ try {
127
+ body = await response.json();
128
+ } catch {
129
+ body = null;
130
+ }
131
+ if (response.status === 401) {
132
+ throw new HookshotAuthenticationError();
133
+ }
134
+ if (response.status === 429) {
135
+ const retryAfter = response.headers.get("Retry-After");
136
+ throw new HookshotRateLimitError(
137
+ "Rate limit exceeded",
138
+ retryAfter ? parseInt(retryAfter, 10) : void 0
139
+ );
140
+ }
141
+ throw HookshotError.fromResponse(response.status, body);
142
+ }
143
+ if (response.status === 204) {
144
+ return void 0;
145
+ }
146
+ return response.json();
147
+ }
148
+ };
149
+ var EndpointsAPI = class {
150
+ constructor(client) {
151
+ this.client = client;
152
+ }
153
+ async list() {
154
+ return this.client.request("GET", "/endpoints");
155
+ }
156
+ async create(data) {
157
+ return this.client.request("POST", "/endpoints", { body: data });
158
+ }
159
+ async get(id) {
160
+ return this.client.request("GET", `/endpoints/${id}`);
161
+ }
162
+ async update(id, data) {
163
+ return this.client.request("PATCH", `/endpoints/${id}`, { body: data });
164
+ }
165
+ async delete(id) {
166
+ return this.client.request("DELETE", `/endpoints/${id}`);
167
+ }
168
+ };
169
+ var EventsAPI = class {
170
+ constructor(client) {
171
+ this.client = client;
172
+ }
173
+ async send(data) {
174
+ return this.client.request("POST", "/ingest", { body: data });
175
+ }
176
+ async list(params) {
177
+ return this.client.request("GET", "/events", {
178
+ query: params
179
+ });
180
+ }
181
+ async get(id) {
182
+ return this.client.request("GET", `/events/${id}`);
183
+ }
184
+ async getAttempts(eventId) {
185
+ return this.client.request("GET", `/events/${eventId}/attempts`);
186
+ }
187
+ };
188
+ var DlqAPI = class {
189
+ constructor(client) {
190
+ this.client = client;
191
+ }
192
+ async list(params) {
193
+ return this.client.request("GET", "/dlq", {
194
+ query: params
195
+ });
196
+ }
197
+ async stats() {
198
+ return this.client.request("GET", "/dlq/stats");
199
+ }
200
+ async replay(eventId, options) {
201
+ return this.client.request("POST", `/dlq/${eventId}/replay`, {
202
+ body: options || {}
203
+ });
204
+ }
205
+ async replayAll() {
206
+ return this.client.request("POST", "/dlq/replay-all");
207
+ }
208
+ async purge(eventId) {
209
+ return this.client.request("DELETE", `/dlq/${eventId}`);
210
+ }
211
+ async purgeAll() {
212
+ return this.client.request("DELETE", "/dlq");
213
+ }
214
+ };
215
+ export {
216
+ HookshotAuthenticationError,
217
+ HookshotClient,
218
+ HookshotError,
219
+ HookshotRateLimitError,
220
+ HookshotValidationError
221
+ };
222
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/errors.ts","../src/client.ts"],"sourcesContent":["export class HookshotError extends Error {\n public readonly code: string;\n public readonly status: number;\n public readonly details?: Record<string, unknown>;\n\n constructor(options: {\n message: string;\n code: string;\n status: number;\n details?: Record<string, unknown>;\n }) {\n super(options.message);\n this.name = 'HookshotError';\n this.code = options.code;\n this.status = options.status;\n this.details = options.details;\n\n Object.setPrototypeOf(this, HookshotError.prototype);\n }\n\n static fromResponse(status: number, body: unknown): HookshotError {\n const parsed = body as { message?: string; code?: string; error?: string } | null;\n \n return new HookshotError({\n message: parsed?.message || parsed?.error || `HTTP ${status}`,\n code: parsed?.code || 'UNKNOWN_ERROR',\n status,\n details: typeof parsed === 'object' && parsed !== null ? parsed : undefined,\n });\n }\n\n static networkError(message: string): HookshotError {\n return new HookshotError({\n message,\n code: 'NETWORK_ERROR',\n status: 0,\n });\n }\n}\n\nexport class HookshotValidationError extends HookshotError {\n constructor(message: string, details?: Record<string, unknown>) {\n super({\n message,\n code: 'VALIDATION_ERROR',\n status: 400,\n details,\n });\n this.name = 'HookshotValidationError';\n Object.setPrototypeOf(this, HookshotValidationError.prototype);\n }\n}\n\nexport class HookshotAuthenticationError extends HookshotError {\n constructor(message: string = 'Invalid or missing API key') {\n super({\n message,\n code: 'AUTHENTICATION_ERROR',\n status: 401,\n });\n this.name = 'HookshotAuthenticationError';\n Object.setPrototypeOf(this, HookshotAuthenticationError.prototype);\n }\n}\n\nexport class HookshotRateLimitError extends HookshotError {\n public readonly retryAfter?: number;\n\n constructor(message: string = 'Rate limit exceeded', retryAfter?: number) {\n super({\n message,\n code: 'RATE_LIMIT_EXCEEDED',\n status: 429,\n details: retryAfter ? { retryAfter } : undefined,\n });\n this.name = 'HookshotRateLimitError';\n this.retryAfter = retryAfter;\n Object.setPrototypeOf(this, HookshotRateLimitError.prototype);\n }\n}\n","import type {\n EndpointResponse,\n CreateEndpointInput,\n UpdateEndpointInput,\n WebhookEventResponse,\n IngestEventInput,\n IngestResponse,\n DeliveryAttemptResponse,\n DlqStats,\n} from '@repo/api';\n\nimport {\n HookshotError,\n HookshotAuthenticationError,\n HookshotRateLimitError,\n} from './errors';\n\nimport type {\n HookshotConfig,\n ListEventsParams,\n PaginationParams,\n ReplayOptions,\n ListEventsResponse,\n ReplayAllResponse,\n PurgeAllResponse,\n} from './types';\n\nconst DEFAULT_BASE_URL = 'http://localhost:3001';\n\nexport class HookshotClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n\n public readonly endpoints: EndpointsAPI;\n public readonly events: EventsAPI;\n public readonly dlq: DlqAPI;\n\n constructor(config: HookshotConfig) {\n if (!config.apiKey) {\n throw new HookshotError({\n message: 'API key is required',\n code: 'MISSING_API_KEY',\n status: 400,\n });\n }\n\n this.apiKey = config.apiKey;\n this.baseUrl = (config.baseUrl || DEFAULT_BASE_URL).replace(/\\/$/, '');\n\n this.endpoints = new EndpointsAPI(this);\n this.events = new EventsAPI(this);\n this.dlq = new DlqAPI(this);\n }\n\n async request<T>(\n method: string,\n path: string,\n options?: { body?: unknown; query?: Record<string, string | number | undefined> }\n ): Promise<T> {\n let url = `${this.baseUrl}${path}`;\n\n if (options?.query) {\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(options.query)) {\n if (value !== undefined) {\n params.set(key, String(value));\n }\n }\n const qs = params.toString();\n if (qs) {\n url += `?${qs}`;\n }\n }\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'x-api-key': this.apiKey,\n };\n\n const fetchOptions: RequestInit = {\n method,\n headers,\n };\n\n if (options?.body !== undefined) {\n fetchOptions.body = JSON.stringify(options.body);\n }\n\n let response: Response;\n try {\n response = await fetch(url, fetchOptions);\n } catch (error) {\n throw HookshotError.networkError(\n error instanceof Error ? error.message : 'Network request failed'\n );\n }\n\n if (!response.ok) {\n let body: unknown;\n try {\n body = await response.json();\n } catch {\n body = null;\n }\n\n if (response.status === 401) {\n throw new HookshotAuthenticationError();\n }\n\n if (response.status === 429) {\n const retryAfter = response.headers.get('Retry-After');\n throw new HookshotRateLimitError(\n 'Rate limit exceeded',\n retryAfter ? parseInt(retryAfter, 10) : undefined\n );\n }\n\n throw HookshotError.fromResponse(response.status, body);\n }\n\n if (response.status === 204) {\n return undefined as T;\n }\n\n return response.json() as Promise<T>;\n }\n}\n\nclass EndpointsAPI {\n constructor(private readonly client: HookshotClient) {}\n\n async list(): Promise<EndpointResponse[]> {\n return this.client.request<EndpointResponse[]>('GET', '/endpoints');\n }\n\n async create(data: CreateEndpointInput): Promise<EndpointResponse> {\n return this.client.request<EndpointResponse>('POST', '/endpoints', { body: data });\n }\n\n async get(id: string): Promise<EndpointResponse> {\n return this.client.request<EndpointResponse>('GET', `/endpoints/${id}`);\n }\n\n async update(id: string, data: UpdateEndpointInput): Promise<EndpointResponse> {\n return this.client.request<EndpointResponse>('PATCH', `/endpoints/${id}`, { body: data });\n }\n\n async delete(id: string): Promise<void> {\n return this.client.request<void>('DELETE', `/endpoints/${id}`);\n }\n}\n\nclass EventsAPI {\n constructor(private readonly client: HookshotClient) {}\n\n async send(data: IngestEventInput): Promise<IngestResponse> {\n return this.client.request<IngestResponse>('POST', '/ingest', { body: data });\n }\n\n async list(params?: ListEventsParams): Promise<ListEventsResponse> {\n return this.client.request<ListEventsResponse>('GET', '/events', {\n query: params as Record<string, string | number | undefined>,\n });\n }\n\n async get(id: string): Promise<WebhookEventResponse> {\n return this.client.request<WebhookEventResponse>('GET', `/events/${id}`);\n }\n\n async getAttempts(eventId: string): Promise<DeliveryAttemptResponse[]> {\n return this.client.request<DeliveryAttemptResponse[]>('GET', `/events/${eventId}/attempts`);\n }\n}\n\nclass DlqAPI {\n constructor(private readonly client: HookshotClient) {}\n\n async list(params?: PaginationParams): Promise<ListEventsResponse> {\n return this.client.request<ListEventsResponse>('GET', '/dlq', {\n query: params as Record<string, string | number | undefined>,\n });\n }\n\n async stats(): Promise<DlqStats> {\n return this.client.request<DlqStats>('GET', '/dlq/stats');\n }\n\n async replay(eventId: string, options?: ReplayOptions): Promise<WebhookEventResponse> {\n return this.client.request<WebhookEventResponse>('POST', `/dlq/${eventId}/replay`, {\n body: options || {},\n });\n }\n\n async replayAll(): Promise<ReplayAllResponse> {\n return this.client.request<ReplayAllResponse>('POST', '/dlq/replay-all');\n }\n\n async purge(eventId: string): Promise<void> {\n return this.client.request<void>('DELETE', `/dlq/${eventId}`);\n }\n\n async purgeAll(): Promise<PurgeAllResponse> {\n return this.client.request<PurgeAllResponse>('DELETE', '/dlq');\n }\n}\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "hookshot-sdk",
3
+ "version": "0.1.0",
4
+ "description": "Official SDK for the Hookshot webhook delivery service",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": {
11
+ "types": "./dist/index.d.mts",
12
+ "default": "./dist/index.mjs"
13
+ },
14
+ "require": {
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./dist/index.js"
17
+ }
18
+ }
19
+ },
20
+ "files": [
21
+ "dist"
22
+ ],
23
+ "scripts": {
24
+ "build": "tsup",
25
+ "dev": "tsup --watch",
26
+ "clean": "rm -rf dist",
27
+ "typecheck": "tsc --noEmit"
28
+ },
29
+ "keywords": [
30
+ "webhook",
31
+ "hookshot",
32
+ "sdk",
33
+ "api",
34
+ "retry",
35
+ "dead-letter-queue"
36
+ ],
37
+ "author": "",
38
+ "license": "MIT",
39
+ "dependencies": {},
40
+ "devDependencies": {
41
+ "@repo/api": "workspace:*",
42
+ "@repo/typescript-config": "workspace:*",
43
+ "tsup": "^8.0.0",
44
+ "typescript": "^5.0.0"
45
+ },
46
+ "peerDependencies": {},
47
+ "engines": {
48
+ "node": ">=18.0.0"
49
+ }
50
+ }