@fedpulse/sdk 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.
- package/LICENSE +21 -0
- package/README.md +331 -0
- package/dist/cjs/client.cjs +138 -0
- package/dist/cjs/errors.cjs +200 -0
- package/dist/cjs/http.cjs +449 -0
- package/dist/cjs/index.cjs +65 -0
- package/dist/cjs/resources/analytics.cjs +134 -0
- package/dist/cjs/resources/assistance.cjs +101 -0
- package/dist/cjs/resources/entities.cjs +149 -0
- package/dist/cjs/resources/exclusions.cjs +135 -0
- package/dist/cjs/resources/intelligence.cjs +96 -0
- package/dist/cjs/resources/opportunities.cjs +170 -0
- package/dist/cjs/resources/webhooks.cjs +262 -0
- package/dist/cjs/types/analytics.cjs +5 -0
- package/dist/cjs/types/assistance.cjs +5 -0
- package/dist/cjs/types/common.cjs +5 -0
- package/dist/cjs/types/entities.cjs +5 -0
- package/dist/cjs/types/exclusions.cjs +5 -0
- package/dist/cjs/types/index.cjs +5 -0
- package/dist/cjs/types/intelligence.cjs +5 -0
- package/dist/cjs/types/opportunities.cjs +5 -0
- package/dist/cjs/types/webhooks.cjs +5 -0
- package/dist/cjs/webhooks-verify.cjs +184 -0
- package/dist/esm/client.js +135 -0
- package/dist/esm/client.js.map +1 -0
- package/dist/esm/errors.js +187 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/http.js +445 -0
- package/dist/esm/http.js.map +1 -0
- package/dist/esm/index.js +40 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/resources/analytics.js +131 -0
- package/dist/esm/resources/analytics.js.map +1 -0
- package/dist/esm/resources/assistance.js +98 -0
- package/dist/esm/resources/assistance.js.map +1 -0
- package/dist/esm/resources/entities.js +146 -0
- package/dist/esm/resources/entities.js.map +1 -0
- package/dist/esm/resources/exclusions.js +132 -0
- package/dist/esm/resources/exclusions.js.map +1 -0
- package/dist/esm/resources/intelligence.js +93 -0
- package/dist/esm/resources/intelligence.js.map +1 -0
- package/dist/esm/resources/opportunities.js +167 -0
- package/dist/esm/resources/opportunities.js.map +1 -0
- package/dist/esm/resources/webhooks.js +259 -0
- package/dist/esm/resources/webhooks.js.map +1 -0
- package/dist/esm/types/analytics.js +5 -0
- package/dist/esm/types/analytics.js.map +1 -0
- package/dist/esm/types/assistance.js +5 -0
- package/dist/esm/types/assistance.js.map +1 -0
- package/dist/esm/types/common.js +5 -0
- package/dist/esm/types/common.js.map +1 -0
- package/dist/esm/types/entities.js +5 -0
- package/dist/esm/types/entities.js.map +1 -0
- package/dist/esm/types/exclusions.js +5 -0
- package/dist/esm/types/exclusions.js.map +1 -0
- package/dist/esm/types/index.js +5 -0
- package/dist/esm/types/index.js.map +1 -0
- package/dist/esm/types/intelligence.js +5 -0
- package/dist/esm/types/intelligence.js.map +1 -0
- package/dist/esm/types/opportunities.js +5 -0
- package/dist/esm/types/opportunities.js.map +1 -0
- package/dist/esm/types/webhooks.js +5 -0
- package/dist/esm/types/webhooks.js.map +1 -0
- package/dist/esm/webhooks-verify.js +179 -0
- package/dist/esm/webhooks-verify.js.map +1 -0
- package/dist/types/client.d.cts +136 -0
- package/dist/types/client.d.ts +136 -0
- package/dist/types/client.d.ts.map +1 -0
- package/dist/types/errors.d.cts +139 -0
- package/dist/types/errors.d.ts +139 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/http.d.cts +137 -0
- package/dist/types/http.d.ts +137 -0
- package/dist/types/http.d.ts.map +1 -0
- package/dist/types/index.d.cts +39 -0
- package/dist/types/index.d.ts +39 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/resources/analytics.d.cts +94 -0
- package/dist/types/resources/analytics.d.ts +94 -0
- package/dist/types/resources/analytics.d.ts.map +1 -0
- package/dist/types/resources/assistance.d.cts +66 -0
- package/dist/types/resources/assistance.d.ts +66 -0
- package/dist/types/resources/assistance.d.ts.map +1 -0
- package/dist/types/resources/entities.d.cts +101 -0
- package/dist/types/resources/entities.d.ts +101 -0
- package/dist/types/resources/entities.d.ts.map +1 -0
- package/dist/types/resources/exclusions.d.cts +84 -0
- package/dist/types/resources/exclusions.d.ts +84 -0
- package/dist/types/resources/exclusions.d.ts.map +1 -0
- package/dist/types/resources/intelligence.d.cts +66 -0
- package/dist/types/resources/intelligence.d.ts +66 -0
- package/dist/types/resources/intelligence.d.ts.map +1 -0
- package/dist/types/resources/opportunities.d.cts +116 -0
- package/dist/types/resources/opportunities.d.ts +116 -0
- package/dist/types/resources/opportunities.d.ts.map +1 -0
- package/dist/types/resources/webhooks.d.cts +180 -0
- package/dist/types/resources/webhooks.d.ts +180 -0
- package/dist/types/resources/webhooks.d.ts.map +1 -0
- package/dist/types/types/analytics.d.cts +85 -0
- package/dist/types/types/analytics.d.ts +85 -0
- package/dist/types/types/analytics.d.ts.map +1 -0
- package/dist/types/types/assistance.d.cts +55 -0
- package/dist/types/types/assistance.d.ts +55 -0
- package/dist/types/types/assistance.d.ts.map +1 -0
- package/dist/types/types/common.d.cts +58 -0
- package/dist/types/types/common.d.ts +58 -0
- package/dist/types/types/common.d.ts.map +1 -0
- package/dist/types/types/entities.d.cts +85 -0
- package/dist/types/types/entities.d.ts +85 -0
- package/dist/types/types/entities.d.ts.map +1 -0
- package/dist/types/types/exclusions.d.cts +81 -0
- package/dist/types/types/exclusions.d.ts +81 -0
- package/dist/types/types/exclusions.d.ts.map +1 -0
- package/dist/types/types/index.d.cts +12 -0
- package/dist/types/types/index.d.ts +12 -0
- package/dist/types/types/index.d.ts.map +1 -0
- package/dist/types/types/intelligence.d.cts +104 -0
- package/dist/types/types/intelligence.d.ts +104 -0
- package/dist/types/types/intelligence.d.ts.map +1 -0
- package/dist/types/types/opportunities.d.cts +149 -0
- package/dist/types/types/opportunities.d.ts +149 -0
- package/dist/types/types/opportunities.d.ts.map +1 -0
- package/dist/types/types/webhooks.d.cts +106 -0
- package/dist/types/types/webhooks.d.ts +106 -0
- package/dist/types/types/webhooks.d.ts.map +1 -0
- package/dist/types/webhooks-verify.d.cts +102 -0
- package/dist/types/webhooks-verify.d.ts +102 -0
- package/dist/types/webhooks-verify.d.ts.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Webhook signature verification for FedPulse webhook deliveries.
|
|
3
|
+
*
|
|
4
|
+
* FedPulse signs every outgoing webhook POST with HMAC-SHA256.
|
|
5
|
+
* Use these utilities to verify that incoming requests are genuinely from
|
|
6
|
+
* FedPulse and have not been tampered with or replayed.
|
|
7
|
+
*
|
|
8
|
+
* ## Signing algorithm:
|
|
9
|
+
* signed_body = `${timestampSeconds}.${rawPayloadJson}`
|
|
10
|
+
* signature = HMAC-SHA256(rawSecret, signed_body) → hex
|
|
11
|
+
*
|
|
12
|
+
* ## Delivery headers (all present on every POST):
|
|
13
|
+
* X-FedPulse-Signature : `sha256={hex_hmac}`
|
|
14
|
+
* X-FedPulse-Timestamp : Unix epoch seconds (string)
|
|
15
|
+
* X-FedPulse-Event : Event type (e.g. "opportunity.new")
|
|
16
|
+
* X-FedPulse-Delivery-Id : UUIDv4 delivery identifier
|
|
17
|
+
*
|
|
18
|
+
* ## Replay protection:
|
|
19
|
+
* Reject deliveries where |now − timestamp| > maxAgeSeconds (default 300s).
|
|
20
|
+
*/
|
|
21
|
+
import { createHmac, timingSafeEqual } from 'node:crypto';
|
|
22
|
+
import { FedPulseError } from './errors.js';
|
|
23
|
+
// ── Constants ─────────────────────────────────────────────────────────────────
|
|
24
|
+
const DEFAULT_MAX_AGE_SECONDS = 300; // 5 minutes — matches API server policy.
|
|
25
|
+
// ── Error types ────────────────────────────────────────────────────────────────
|
|
26
|
+
/** Thrown when webhook signature verification fails. */
|
|
27
|
+
export class WebhookVerificationError extends FedPulseError {
|
|
28
|
+
constructor(message) {
|
|
29
|
+
super({ message, status: 0, code: 'WEBHOOK_VERIFICATION_FAILED' });
|
|
30
|
+
this.name = 'WebhookVerificationError';
|
|
31
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// ── Public API ─────────────────────────────────────────────────────────────────
|
|
35
|
+
/**
|
|
36
|
+
* Verify a FedPulse webhook delivery and parse the payload.
|
|
37
|
+
*
|
|
38
|
+
* This function performs three checks:
|
|
39
|
+
* 1. **Format check** — headers are present and in the expected format.
|
|
40
|
+
* 2. **Timestamp check** — delivery is not older than `maxAgeSeconds`.
|
|
41
|
+
* 3. **Signature check** — HMAC-SHA256 matches using constant-time comparison.
|
|
42
|
+
*
|
|
43
|
+
* Throws `WebhookVerificationError` on any failure.
|
|
44
|
+
* Returns the parsed, verified `WebhookPayload<T>`.
|
|
45
|
+
*
|
|
46
|
+
* @param input Headers, raw body, and secret.
|
|
47
|
+
* @returns Parsed and verified webhook payload.
|
|
48
|
+
*
|
|
49
|
+
* @throws {WebhookVerificationError} If the signature is invalid, the timestamp
|
|
50
|
+
* is out of range, or the headers are malformed.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* // Express.js example (use bodyParser.raw() to get the raw buffer):
|
|
55
|
+
* app.post('/webhooks', express.raw({ type: 'application/json' }), (req, res) => {
|
|
56
|
+
* let payload;
|
|
57
|
+
* try {
|
|
58
|
+
* payload = FedPulse.verifyWebhook({
|
|
59
|
+
* rawBody: req.body,
|
|
60
|
+
* signatureHeader: req.headers['x-fedpulse-signature'] as string,
|
|
61
|
+
* timestampHeader: req.headers['x-fedpulse-timestamp'] as string,
|
|
62
|
+
* secret: process.env.FEDPULSE_WEBHOOK_SECRET!,
|
|
63
|
+
* });
|
|
64
|
+
* } catch (err) {
|
|
65
|
+
* return res.status(400).send('Invalid signature');
|
|
66
|
+
* }
|
|
67
|
+
* console.log('Event:', payload.event, 'Data:', payload.data);
|
|
68
|
+
* res.status(200).send('OK');
|
|
69
|
+
* });
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
export function verifyWebhook(input) {
|
|
73
|
+
const { rawBody, signatureHeader, timestampHeader, secret, options } = input;
|
|
74
|
+
const maxAgeSeconds = options?.maxAgeSeconds ?? DEFAULT_MAX_AGE_SECONDS;
|
|
75
|
+
// ── 1. Validate input presence ─────────────────────────────────────────────
|
|
76
|
+
if (!signatureHeader || typeof signatureHeader !== 'string') {
|
|
77
|
+
throw new WebhookVerificationError('Missing X-FedPulse-Signature header. Ensure the request is from FedPulse.');
|
|
78
|
+
}
|
|
79
|
+
if (!timestampHeader || typeof timestampHeader !== 'string') {
|
|
80
|
+
throw new WebhookVerificationError('Missing X-FedPulse-Timestamp header. Ensure the request is from FedPulse.');
|
|
81
|
+
}
|
|
82
|
+
if (!secret || typeof secret !== 'string' || secret.trim() === '') {
|
|
83
|
+
throw new WebhookVerificationError('Webhook secret must be a non-empty string.');
|
|
84
|
+
}
|
|
85
|
+
if (rawBody === undefined || rawBody === null) {
|
|
86
|
+
throw new WebhookVerificationError('rawBody is required. Pass the exact bytes received from the HTTP request.');
|
|
87
|
+
}
|
|
88
|
+
// ── 2. Parse and validate timestamp ────────────────────────────────────────
|
|
89
|
+
const timestampSeconds = Number(timestampHeader);
|
|
90
|
+
if (!Number.isFinite(timestampSeconds) || timestampSeconds <= 0) {
|
|
91
|
+
throw new WebhookVerificationError(`X-FedPulse-Timestamp is not a valid Unix timestamp: "${timestampHeader}"`);
|
|
92
|
+
}
|
|
93
|
+
const nowSeconds = Math.floor(Date.now() / 1000);
|
|
94
|
+
const ageSeconds = Math.abs(nowSeconds - timestampSeconds);
|
|
95
|
+
if (ageSeconds > maxAgeSeconds) {
|
|
96
|
+
throw new WebhookVerificationError(`Webhook delivery is too old (age: ${ageSeconds}s, max: ${maxAgeSeconds}s). ` +
|
|
97
|
+
'This may indicate a replay attack. Ensure your server clock is synchronised.');
|
|
98
|
+
}
|
|
99
|
+
// ── 3. Parse and validate signature header ─────────────────────────────────
|
|
100
|
+
if (!signatureHeader.startsWith('sha256=')) {
|
|
101
|
+
throw new WebhookVerificationError(`Unsupported signature algorithm. Expected "sha256=..." prefix, got: "${signatureHeader}"`);
|
|
102
|
+
}
|
|
103
|
+
const receivedHex = signatureHeader.slice('sha256='.length);
|
|
104
|
+
if (!receivedHex || !/^[0-9a-f]+$/i.test(receivedHex)) {
|
|
105
|
+
throw new WebhookVerificationError('X-FedPulse-Signature contains an invalid hex string');
|
|
106
|
+
}
|
|
107
|
+
// ── 4. Compute expected signature ──────────────────────────────────────────
|
|
108
|
+
const bodyString = typeof rawBody === 'string' ? rawBody : rawBody.toString('utf8');
|
|
109
|
+
const signedPayload = `${timestampSeconds}.${bodyString}`;
|
|
110
|
+
const expectedHex = createHmac('sha256', secret)
|
|
111
|
+
.update(signedPayload, 'utf8')
|
|
112
|
+
.digest('hex');
|
|
113
|
+
// ── 5. Constant-time comparison ────────────────────────────────────────────
|
|
114
|
+
// Pad both to the same length to avoid length-based timing differences, then
|
|
115
|
+
// use timingSafeEqual to prevent timing attacks.
|
|
116
|
+
const receivedBuf = Buffer.from(receivedHex.toLowerCase(), 'hex');
|
|
117
|
+
const expectedBuf = Buffer.from(expectedHex, 'hex');
|
|
118
|
+
if (receivedBuf.length !== expectedBuf.length ||
|
|
119
|
+
!timingSafeEqual(receivedBuf, expectedBuf)) {
|
|
120
|
+
throw new WebhookVerificationError('Webhook signature does not match. The request may have been tampered with.');
|
|
121
|
+
}
|
|
122
|
+
// ── 6. Parse and return payload ────────────────────────────────────────────
|
|
123
|
+
let payload;
|
|
124
|
+
try {
|
|
125
|
+
payload = JSON.parse(bodyString);
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
throw new WebhookVerificationError('Webhook body is not valid JSON despite a valid signature.');
|
|
129
|
+
}
|
|
130
|
+
if (payload === null ||
|
|
131
|
+
typeof payload !== 'object' ||
|
|
132
|
+
!('event' in payload) ||
|
|
133
|
+
!('timestamp' in payload) ||
|
|
134
|
+
!('data' in payload)) {
|
|
135
|
+
throw new WebhookVerificationError('Webhook payload does not match the expected envelope shape ' +
|
|
136
|
+
'{ event, timestamp, apiVersion, data }.');
|
|
137
|
+
}
|
|
138
|
+
return payload;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Extract the FedPulse webhook headers from a plain headers object.
|
|
142
|
+
*
|
|
143
|
+
* Normalises both lowercase and original-casing variants so you don't
|
|
144
|
+
* have to worry about header casing differences between frameworks.
|
|
145
|
+
*
|
|
146
|
+
* @param headers A plain object or Map of request headers.
|
|
147
|
+
* @returns Extracted signature and timestamp values.
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* ```ts
|
|
151
|
+
* // Works with Express, Fastify, Koa, Next.js API routes, etc.
|
|
152
|
+
* const { signatureHeader, timestampHeader } = extractWebhookHeaders(req.headers);
|
|
153
|
+
* const payload = FedPulse.verifyWebhook({ rawBody, signatureHeader, timestampHeader, secret });
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
export function extractWebhookHeaders(headers) {
|
|
157
|
+
const get = (key) => {
|
|
158
|
+
let value;
|
|
159
|
+
if (headers instanceof Headers) {
|
|
160
|
+
value = headers.get(key);
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
// Case-insensitive lookup for plain objects.
|
|
164
|
+
const lowerKey = key.toLowerCase();
|
|
165
|
+
const entry = Object.entries(headers).find(([k]) => k.toLowerCase() === lowerKey);
|
|
166
|
+
value = entry?.[1];
|
|
167
|
+
}
|
|
168
|
+
if (Array.isArray(value))
|
|
169
|
+
return value[0] ?? '';
|
|
170
|
+
return value ?? '';
|
|
171
|
+
};
|
|
172
|
+
return {
|
|
173
|
+
signatureHeader: get('x-fedpulse-signature'),
|
|
174
|
+
timestampHeader: get('x-fedpulse-timestamp'),
|
|
175
|
+
event: get('x-fedpulse-event'),
|
|
176
|
+
deliveryId: get('x-fedpulse-delivery-id'),
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=webhooks-verify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhooks-verify.js","sourceRoot":"","sources":["../../src/webhooks-verify.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FedPulse SDK — main client class.
|
|
3
|
+
*
|
|
4
|
+
* Instantiate this class with your API key to access all FedPulse
|
|
5
|
+
* data resources and the webhook verification utility.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { FedPulse } from '@fedpulse/sdk';
|
|
10
|
+
*
|
|
11
|
+
* const client = new FedPulse({ apiKey: process.env.FEDPULSE_API_KEY! });
|
|
12
|
+
*
|
|
13
|
+
* // Search contracts
|
|
14
|
+
* const { data } = await client.opportunities.list({ q: 'cloud', naics: '541512' });
|
|
15
|
+
*
|
|
16
|
+
* // Compliance check
|
|
17
|
+
* const { data: status } = await client.exclusions.check({ entities: [{ uei: 'ABCDEF123456' }] });
|
|
18
|
+
*
|
|
19
|
+
* // Verify an incoming webhook
|
|
20
|
+
* const payload = FedPulse.verifyWebhook({ rawBody, signatureHeader, timestampHeader, secret });
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
import { HttpClient } from './http.cjs';
|
|
24
|
+
import type { HttpClientOptions } from './http.cjs';
|
|
25
|
+
import { OpportunitiesResource } from './resources/opportunities.cjs';
|
|
26
|
+
import { ExclusionsResource } from './resources/exclusions.cjs';
|
|
27
|
+
import { EntitiesResource } from './resources/entities.cjs';
|
|
28
|
+
import { IntelligenceResource } from './resources/intelligence.cjs';
|
|
29
|
+
import { AssistanceResource } from './resources/assistance.cjs';
|
|
30
|
+
import { AnalyticsResource } from './resources/analytics.cjs';
|
|
31
|
+
import { WebhooksResource } from './resources/webhooks.cjs';
|
|
32
|
+
import { extractWebhookHeaders, WebhookVerificationError } from './webhooks-verify.cjs';
|
|
33
|
+
import type { VerifyWebhookInput } from './webhooks-verify.cjs';
|
|
34
|
+
import type { WebhookPayload } from './types/webhooks.cjs';
|
|
35
|
+
import type { RateLimitInfo } from './types/common.cjs';
|
|
36
|
+
export type { HttpClientOptions };
|
|
37
|
+
/**
|
|
38
|
+
* Configuration options for the FedPulse SDK client.
|
|
39
|
+
*/
|
|
40
|
+
export interface FedPulseOptions extends Omit<HttpClientOptions, 'apiKey'> {
|
|
41
|
+
/**
|
|
42
|
+
* Your FedPulse API key.
|
|
43
|
+
* Generate one at https://app.fedpulse.dev/dashboard.
|
|
44
|
+
*
|
|
45
|
+
* **Security:** Never hardcode this value. Use environment variables:
|
|
46
|
+
* ```ts
|
|
47
|
+
* const client = new FedPulse({ apiKey: process.env.FEDPULSE_API_KEY! });
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
apiKey: string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The FedPulse SDK client.
|
|
54
|
+
*
|
|
55
|
+
* All API interactions go through the resource properties on this class.
|
|
56
|
+
* The static `verifyWebhook` method can be used independently of a client instance.
|
|
57
|
+
*/
|
|
58
|
+
export declare class FedPulse {
|
|
59
|
+
/** Low-level HTTP client (exposed for advanced usage only). */
|
|
60
|
+
readonly http: HttpClient;
|
|
61
|
+
/** Federal contract opportunities (/v1/opportunities). */
|
|
62
|
+
readonly opportunities: OpportunitiesResource;
|
|
63
|
+
/** SAM.gov exclusions and bulk compliance checks (/v1/exclusions). */
|
|
64
|
+
readonly exclusions: ExclusionsResource;
|
|
65
|
+
/** SAM.gov registered entities / vendors (/v1/entities). */
|
|
66
|
+
readonly entities: EntitiesResource;
|
|
67
|
+
/** 360° entity intelligence and market analysis (/v1/intelligence). */
|
|
68
|
+
readonly intelligence: IntelligenceResource;
|
|
69
|
+
/** Federal assistance listings / CFDA programs (/v1/assistance). */
|
|
70
|
+
readonly assistance: AssistanceResource;
|
|
71
|
+
/** Per-user API usage analytics (/v1/analytics). */
|
|
72
|
+
readonly analytics: AnalyticsResource;
|
|
73
|
+
/** Webhook subscription management (/v1/webhooks). */
|
|
74
|
+
readonly webhooks: WebhooksResource;
|
|
75
|
+
constructor(options: FedPulseOptions);
|
|
76
|
+
/**
|
|
77
|
+
* Most recent rate-limit info observed from API responses.
|
|
78
|
+
*
|
|
79
|
+
* Updated after every API call. Useful for monitoring your rate-limit usage.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```ts
|
|
83
|
+
* await client.opportunities.list({ limit: 25 });
|
|
84
|
+
* console.log('Remaining requests:', client.rateLimit?.remaining);
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
get rateLimit(): RateLimitInfo | null;
|
|
88
|
+
/**
|
|
89
|
+
* Clear the in-memory response cache.
|
|
90
|
+
*
|
|
91
|
+
* Useful after writes that may invalidate cached GET responses.
|
|
92
|
+
*/
|
|
93
|
+
clearCache(): void;
|
|
94
|
+
/**
|
|
95
|
+
* Verify an incoming FedPulse webhook delivery.
|
|
96
|
+
*
|
|
97
|
+
* Validates the HMAC-SHA256 signature, checks the timestamp against replay
|
|
98
|
+
* attacks, and returns the parsed payload on success.
|
|
99
|
+
*
|
|
100
|
+
* **IMPORTANT:** Pass the raw request body bytes — do not parse to JSON first.
|
|
101
|
+
*
|
|
102
|
+
* @param input Headers, raw body, and signing secret.
|
|
103
|
+
* @returns Parsed, verified webhook payload.
|
|
104
|
+
* @throws {WebhookVerificationError} If signature/timestamp is invalid.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```ts
|
|
108
|
+
* // Express.js with `express.raw({ type: 'application/json' })`:
|
|
109
|
+
* const payload = FedPulse.verifyWebhook<{ noticeId: string }>({
|
|
110
|
+
* rawBody: req.body, // Buffer from express.raw()
|
|
111
|
+
* signatureHeader: req.headers['x-fedpulse-signature'] as string,
|
|
112
|
+
* timestampHeader: req.headers['x-fedpulse-timestamp'] as string,
|
|
113
|
+
* secret: process.env.FEDPULSE_WEBHOOK_SECRET!,
|
|
114
|
+
* });
|
|
115
|
+
* console.log(payload.event, payload.data.noticeId);
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
static verifyWebhook<T = unknown>(input: VerifyWebhookInput): WebhookPayload<T>;
|
|
119
|
+
/**
|
|
120
|
+
* Extract FedPulse webhook headers from a request headers object.
|
|
121
|
+
*
|
|
122
|
+
* Handles case-insensitive lookup across Express, Fastify, Next.js, etc.
|
|
123
|
+
*
|
|
124
|
+
* @param headers Headers object (plain object or `Headers` instance).
|
|
125
|
+
* @returns Signature header, timestamp header, event type, and delivery ID.
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```ts
|
|
129
|
+
* const { signatureHeader, timestampHeader } = FedPulse.extractWebhookHeaders(req.headers);
|
|
130
|
+
* const payload = FedPulse.verifyWebhook({ rawBody, signatureHeader, timestampHeader, secret });
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
static extractWebhookHeaders(headers: Record<string, string | string[] | undefined> | Headers): ReturnType<typeof extractWebhookHeaders>;
|
|
134
|
+
}
|
|
135
|
+
export { WebhookVerificationError };
|
|
136
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FedPulse SDK — main client class.
|
|
3
|
+
*
|
|
4
|
+
* Instantiate this class with your API key to access all FedPulse
|
|
5
|
+
* data resources and the webhook verification utility.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { FedPulse } from '@fedpulse/sdk';
|
|
10
|
+
*
|
|
11
|
+
* const client = new FedPulse({ apiKey: process.env.FEDPULSE_API_KEY! });
|
|
12
|
+
*
|
|
13
|
+
* // Search contracts
|
|
14
|
+
* const { data } = await client.opportunities.list({ q: 'cloud', naics: '541512' });
|
|
15
|
+
*
|
|
16
|
+
* // Compliance check
|
|
17
|
+
* const { data: status } = await client.exclusions.check({ entities: [{ uei: 'ABCDEF123456' }] });
|
|
18
|
+
*
|
|
19
|
+
* // Verify an incoming webhook
|
|
20
|
+
* const payload = FedPulse.verifyWebhook({ rawBody, signatureHeader, timestampHeader, secret });
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
import { HttpClient } from './http.js';
|
|
24
|
+
import type { HttpClientOptions } from './http.js';
|
|
25
|
+
import { OpportunitiesResource } from './resources/opportunities.js';
|
|
26
|
+
import { ExclusionsResource } from './resources/exclusions.js';
|
|
27
|
+
import { EntitiesResource } from './resources/entities.js';
|
|
28
|
+
import { IntelligenceResource } from './resources/intelligence.js';
|
|
29
|
+
import { AssistanceResource } from './resources/assistance.js';
|
|
30
|
+
import { AnalyticsResource } from './resources/analytics.js';
|
|
31
|
+
import { WebhooksResource } from './resources/webhooks.js';
|
|
32
|
+
import { extractWebhookHeaders, WebhookVerificationError } from './webhooks-verify.js';
|
|
33
|
+
import type { VerifyWebhookInput } from './webhooks-verify.js';
|
|
34
|
+
import type { WebhookPayload } from './types/webhooks.js';
|
|
35
|
+
import type { RateLimitInfo } from './types/common.js';
|
|
36
|
+
export type { HttpClientOptions };
|
|
37
|
+
/**
|
|
38
|
+
* Configuration options for the FedPulse SDK client.
|
|
39
|
+
*/
|
|
40
|
+
export interface FedPulseOptions extends Omit<HttpClientOptions, 'apiKey'> {
|
|
41
|
+
/**
|
|
42
|
+
* Your FedPulse API key.
|
|
43
|
+
* Generate one at https://app.fedpulse.dev/dashboard.
|
|
44
|
+
*
|
|
45
|
+
* **Security:** Never hardcode this value. Use environment variables:
|
|
46
|
+
* ```ts
|
|
47
|
+
* const client = new FedPulse({ apiKey: process.env.FEDPULSE_API_KEY! });
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
apiKey: string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The FedPulse SDK client.
|
|
54
|
+
*
|
|
55
|
+
* All API interactions go through the resource properties on this class.
|
|
56
|
+
* The static `verifyWebhook` method can be used independently of a client instance.
|
|
57
|
+
*/
|
|
58
|
+
export declare class FedPulse {
|
|
59
|
+
/** Low-level HTTP client (exposed for advanced usage only). */
|
|
60
|
+
readonly http: HttpClient;
|
|
61
|
+
/** Federal contract opportunities (/v1/opportunities). */
|
|
62
|
+
readonly opportunities: OpportunitiesResource;
|
|
63
|
+
/** SAM.gov exclusions and bulk compliance checks (/v1/exclusions). */
|
|
64
|
+
readonly exclusions: ExclusionsResource;
|
|
65
|
+
/** SAM.gov registered entities / vendors (/v1/entities). */
|
|
66
|
+
readonly entities: EntitiesResource;
|
|
67
|
+
/** 360° entity intelligence and market analysis (/v1/intelligence). */
|
|
68
|
+
readonly intelligence: IntelligenceResource;
|
|
69
|
+
/** Federal assistance listings / CFDA programs (/v1/assistance). */
|
|
70
|
+
readonly assistance: AssistanceResource;
|
|
71
|
+
/** Per-user API usage analytics (/v1/analytics). */
|
|
72
|
+
readonly analytics: AnalyticsResource;
|
|
73
|
+
/** Webhook subscription management (/v1/webhooks). */
|
|
74
|
+
readonly webhooks: WebhooksResource;
|
|
75
|
+
constructor(options: FedPulseOptions);
|
|
76
|
+
/**
|
|
77
|
+
* Most recent rate-limit info observed from API responses.
|
|
78
|
+
*
|
|
79
|
+
* Updated after every API call. Useful for monitoring your rate-limit usage.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```ts
|
|
83
|
+
* await client.opportunities.list({ limit: 25 });
|
|
84
|
+
* console.log('Remaining requests:', client.rateLimit?.remaining);
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
get rateLimit(): RateLimitInfo | null;
|
|
88
|
+
/**
|
|
89
|
+
* Clear the in-memory response cache.
|
|
90
|
+
*
|
|
91
|
+
* Useful after writes that may invalidate cached GET responses.
|
|
92
|
+
*/
|
|
93
|
+
clearCache(): void;
|
|
94
|
+
/**
|
|
95
|
+
* Verify an incoming FedPulse webhook delivery.
|
|
96
|
+
*
|
|
97
|
+
* Validates the HMAC-SHA256 signature, checks the timestamp against replay
|
|
98
|
+
* attacks, and returns the parsed payload on success.
|
|
99
|
+
*
|
|
100
|
+
* **IMPORTANT:** Pass the raw request body bytes — do not parse to JSON first.
|
|
101
|
+
*
|
|
102
|
+
* @param input Headers, raw body, and signing secret.
|
|
103
|
+
* @returns Parsed, verified webhook payload.
|
|
104
|
+
* @throws {WebhookVerificationError} If signature/timestamp is invalid.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```ts
|
|
108
|
+
* // Express.js with `express.raw({ type: 'application/json' })`:
|
|
109
|
+
* const payload = FedPulse.verifyWebhook<{ noticeId: string }>({
|
|
110
|
+
* rawBody: req.body, // Buffer from express.raw()
|
|
111
|
+
* signatureHeader: req.headers['x-fedpulse-signature'] as string,
|
|
112
|
+
* timestampHeader: req.headers['x-fedpulse-timestamp'] as string,
|
|
113
|
+
* secret: process.env.FEDPULSE_WEBHOOK_SECRET!,
|
|
114
|
+
* });
|
|
115
|
+
* console.log(payload.event, payload.data.noticeId);
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
static verifyWebhook<T = unknown>(input: VerifyWebhookInput): WebhookPayload<T>;
|
|
119
|
+
/**
|
|
120
|
+
* Extract FedPulse webhook headers from a request headers object.
|
|
121
|
+
*
|
|
122
|
+
* Handles case-insensitive lookup across Express, Fastify, Next.js, etc.
|
|
123
|
+
*
|
|
124
|
+
* @param headers Headers object (plain object or `Headers` instance).
|
|
125
|
+
* @returns Signature header, timestamp header, event type, and delivery ID.
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```ts
|
|
129
|
+
* const { signatureHeader, timestampHeader } = FedPulse.extractWebhookHeaders(req.headers);
|
|
130
|
+
* const payload = FedPulse.verifyWebhook({ rawBody, signatureHeader, timestampHeader, secret });
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
static extractWebhookHeaders(headers: Record<string, string | string[] | undefined> | Headers): ReturnType<typeof extractWebhookHeaders>;
|
|
134
|
+
}
|
|
135
|
+
export { WebhookVerificationError };
|
|
136
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAEL,qBAAqB,EACrB,wBAAwB,EACzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,YAAY,EAAE,iBAAiB,EAAE,CAAC;AAIlC;;GAEG;AACH,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC;IACxE;;;;;;;;OAQG;IACH,MAAM,EAAE,MAAM,CAAC;CAChB;AAID;;;;;GAKG;AACH,qBAAa,QAAQ;IACnB,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAE1B,0DAA0D;IAC1D,QAAQ,CAAC,aAAa,EAAE,qBAAqB,CAAC;IAE9C,sEAAsE;IACtE,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAC;IAExC,4DAA4D;IAC5D,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IAEpC,uEAAuE;IACvE,QAAQ,CAAC,YAAY,EAAE,oBAAoB,CAAC;IAE5C,oEAAoE;IACpE,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAC;IAExC,oDAAoD;IACpD,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAC;IAEtC,sDAAsD;IACtD,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;gBAExB,OAAO,EAAE,eAAe;IAYpC;;;;;;;;;;OAUG;IACH,IAAI,SAAS,IAAI,aAAa,GAAG,IAAI,CAEpC;IAED;;;;OAIG;IACH,UAAU,IAAI,IAAI;IAMlB;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,MAAM,CAAC,aAAa,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,kBAAkB,GAAG,cAAc,CAAC,CAAC,CAAC;IAI/E;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAC,qBAAqB,CAC1B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,GAAG,OAAO,GAC/D,UAAU,CAAC,OAAO,qBAAqB,CAAC;CAG5C;AAED,OAAO,EAAE,wBAAwB,EAAE,CAAC"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FedPulse SDK error classes.
|
|
3
|
+
*
|
|
4
|
+
* All errors thrown by the SDK extend FedPulseError so callers can use
|
|
5
|
+
* `instanceof FedPulseError` to distinguish SDK errors from other exceptions.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Base class for all FedPulse SDK errors.
|
|
9
|
+
*/
|
|
10
|
+
export declare class FedPulseError extends Error {
|
|
11
|
+
/** HTTP status code returned by the API, or 0 for network errors. */
|
|
12
|
+
readonly status: number;
|
|
13
|
+
/** Machine-readable error code from the API (e.g. NOT_FOUND, RATE_LIMIT_EXCEEDED). */
|
|
14
|
+
readonly code: string;
|
|
15
|
+
/** Request ID for debugging — correlates with API logs. */
|
|
16
|
+
readonly requestId: string | undefined;
|
|
17
|
+
/** Additional structured details from the API response. */
|
|
18
|
+
readonly details: unknown | undefined;
|
|
19
|
+
constructor({ message, status, code, requestId, details, }: {
|
|
20
|
+
message: string;
|
|
21
|
+
status: number;
|
|
22
|
+
code: string;
|
|
23
|
+
requestId?: string;
|
|
24
|
+
details?: unknown;
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Thrown when the API returns 401 Unauthorized.
|
|
29
|
+
* Usually caused by missing, invalid, or revoked API key / JWT.
|
|
30
|
+
*/
|
|
31
|
+
export declare class AuthenticationError extends FedPulseError {
|
|
32
|
+
constructor(params: {
|
|
33
|
+
message: string;
|
|
34
|
+
requestId?: string;
|
|
35
|
+
details?: unknown;
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Thrown when the API returns 403 Forbidden.
|
|
40
|
+
* Usually caused by insufficient plan permissions or missing key scope.
|
|
41
|
+
*/
|
|
42
|
+
export declare class PermissionError extends FedPulseError {
|
|
43
|
+
constructor(params: {
|
|
44
|
+
message: string;
|
|
45
|
+
code?: string;
|
|
46
|
+
requestId?: string;
|
|
47
|
+
details?: unknown;
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Thrown when the API returns 404 Not Found.
|
|
52
|
+
*/
|
|
53
|
+
export declare class NotFoundError extends FedPulseError {
|
|
54
|
+
constructor(params: {
|
|
55
|
+
message: string;
|
|
56
|
+
requestId?: string;
|
|
57
|
+
details?: unknown;
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Thrown when the API returns 422 Unprocessable Entity or 400 Bad Request
|
|
62
|
+
* due to invalid request parameters or body.
|
|
63
|
+
*/
|
|
64
|
+
export declare class ValidationError extends FedPulseError {
|
|
65
|
+
constructor(params: {
|
|
66
|
+
message: string;
|
|
67
|
+
status?: number;
|
|
68
|
+
requestId?: string;
|
|
69
|
+
details?: unknown;
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Thrown when the API returns 429 Too Many Requests.
|
|
74
|
+
* The `retryAfter` property indicates when the rate limit resets (Unix seconds).
|
|
75
|
+
*/
|
|
76
|
+
export declare class RateLimitError extends FedPulseError {
|
|
77
|
+
/** Unix epoch seconds when the rate limit window resets. */
|
|
78
|
+
readonly retryAfter: number | undefined;
|
|
79
|
+
constructor(params: {
|
|
80
|
+
message: string;
|
|
81
|
+
retryAfter?: number;
|
|
82
|
+
requestId?: string;
|
|
83
|
+
details?: unknown;
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Thrown when the API returns a 5xx server error.
|
|
88
|
+
*/
|
|
89
|
+
export declare class ServerError extends FedPulseError {
|
|
90
|
+
constructor(params: {
|
|
91
|
+
message: string;
|
|
92
|
+
status?: number;
|
|
93
|
+
code?: string;
|
|
94
|
+
requestId?: string;
|
|
95
|
+
details?: unknown;
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Thrown when a network-level failure occurs (DNS, TCP, timeout, ECONNREFUSED).
|
|
100
|
+
* The `cause` property contains the original error.
|
|
101
|
+
*/
|
|
102
|
+
export declare class NetworkError extends FedPulseError {
|
|
103
|
+
/** The underlying network error. */
|
|
104
|
+
readonly cause: Error;
|
|
105
|
+
constructor(params: {
|
|
106
|
+
message: string;
|
|
107
|
+
cause: Error;
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Thrown when a request exceeds the configured timeout.
|
|
112
|
+
*/
|
|
113
|
+
export declare class TimeoutError extends FedPulseError {
|
|
114
|
+
constructor(params: {
|
|
115
|
+
message: string;
|
|
116
|
+
requestId?: string;
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Thrown when the SDK's retry budget is exhausted.
|
|
121
|
+
* The `lastError` property contains the final underlying error.
|
|
122
|
+
*/
|
|
123
|
+
export declare class RetryExhaustedError extends FedPulseError {
|
|
124
|
+
readonly lastError: FedPulseError;
|
|
125
|
+
readonly attempts: number;
|
|
126
|
+
constructor(params: {
|
|
127
|
+
lastError: FedPulseError;
|
|
128
|
+
attempts: number;
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Factory — parses a raw API error response object into the correct error subtype.
|
|
133
|
+
*
|
|
134
|
+
* @param status HTTP response status code.
|
|
135
|
+
* @param body Parsed JSON body (may be the error envelope or anything).
|
|
136
|
+
* @param headers Response headers map (used for Retry-After).
|
|
137
|
+
*/
|
|
138
|
+
export declare function createApiError(status: number, body: unknown, headers: Record<string, string | null>): FedPulseError;
|
|
139
|
+
//# sourceMappingURL=errors.d.ts.map
|