@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,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fedpulse/sdk — Official JavaScript/TypeScript SDK for the FedPulse API.
|
|
3
|
+
*
|
|
4
|
+
* Quick start:
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { FedPulse } from '@fedpulse/sdk';
|
|
7
|
+
*
|
|
8
|
+
* const client = new FedPulse({ apiKey: process.env.FEDPULSE_API_KEY! });
|
|
9
|
+
*
|
|
10
|
+
* const { data } = await client.opportunities.list({ q: 'cloud', naics: '541512' });
|
|
11
|
+
* console.log(data[0].title);
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* Webhook verification:
|
|
15
|
+
* ```ts
|
|
16
|
+
* const payload = FedPulse.verifyWebhook({
|
|
17
|
+
* rawBody: req.body,
|
|
18
|
+
* signatureHeader: req.headers['x-fedpulse-signature'],
|
|
19
|
+
* timestampHeader: req.headers['x-fedpulse-timestamp'],
|
|
20
|
+
* secret: process.env.FEDPULSE_WEBHOOK_SECRET!,
|
|
21
|
+
* });
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
// ── Main client ────────────────────────────────────────────────────────────────
|
|
25
|
+
export { FedPulse, WebhookVerificationError } from './client.js';
|
|
26
|
+
// ── Error classes ──────────────────────────────────────────────────────────────
|
|
27
|
+
export { FedPulseError, AuthenticationError, PermissionError, NotFoundError, ValidationError, RateLimitError, ServerError, NetworkError, TimeoutError, RetryExhaustedError, } from './errors.js';
|
|
28
|
+
// ── HTTP client (advanced usage) ───────────────────────────────────────────────
|
|
29
|
+
export { HttpClient, buildQueryParams } from './http.js';
|
|
30
|
+
// ── Domain resources ───────────────────────────────────────────────────────────
|
|
31
|
+
export { OpportunitiesResource } from './resources/opportunities.js';
|
|
32
|
+
export { ExclusionsResource } from './resources/exclusions.js';
|
|
33
|
+
export { EntitiesResource } from './resources/entities.js';
|
|
34
|
+
export { IntelligenceResource } from './resources/intelligence.js';
|
|
35
|
+
export { AssistanceResource } from './resources/assistance.js';
|
|
36
|
+
export { AnalyticsResource } from './resources/analytics.js';
|
|
37
|
+
export { WebhooksResource } from './resources/webhooks.js';
|
|
38
|
+
// ── Webhook utilities ──────────────────────────────────────────────────────────
|
|
39
|
+
export { verifyWebhook, extractWebhookHeaders } from './webhooks-verify.js';
|
|
40
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,kFAAkF;AAElF,OAAO,EAAE,QAAQ,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAGjE,kFAAkF;AAElF,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,eAAe,EACf,aAAa,EACb,eAAe,EACf,cAAc,EACd,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAErB,kFAAkF;AAElF,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAGzD,kFAAkF;AAElF,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;AAE3D,kFAAkF;AAElF,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analytics resource client.
|
|
3
|
+
*
|
|
4
|
+
* Wraps all /v1/analytics endpoints (per-user API usage analytics):
|
|
5
|
+
* - summary GET /v1/analytics/summary
|
|
6
|
+
* - chart GET /v1/analytics/chart
|
|
7
|
+
* - endpoints GET /v1/analytics/endpoints
|
|
8
|
+
* - logs GET /v1/analytics/logs
|
|
9
|
+
* - logPages async generator over the logs endpoint
|
|
10
|
+
*
|
|
11
|
+
* All results are scoped to the authenticated user — no cross-user visibility.
|
|
12
|
+
*/
|
|
13
|
+
export class AnalyticsResource {
|
|
14
|
+
http;
|
|
15
|
+
constructor(http) {
|
|
16
|
+
this.http = http;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Get KPI summary totals for the authenticated user.
|
|
20
|
+
*
|
|
21
|
+
* Returns: requests today, this month, in range, 4xx/5xx counts and rates.
|
|
22
|
+
* Analytics data is never cached — always returns live counts.
|
|
23
|
+
*
|
|
24
|
+
* @param params Optional key-scoping and time range.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* const summary = await client.analytics.summary({ range: '7d' });
|
|
29
|
+
* console.log('Requests last 7d:', summary.data.requestsInRange);
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
async summary(params = {}) {
|
|
33
|
+
validateAnalyticsParams(params);
|
|
34
|
+
return this.http.get('/v1/analytics/summary', params, { cacheTtlMs: 0 });
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Get per-day request counts broken down by success / 4xx / 5xx.
|
|
38
|
+
*
|
|
39
|
+
* @param params Optional key-scoping and time range.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* const chart = await client.analytics.chart({ range: '30d' });
|
|
44
|
+
* for (const day of chart.data.days) {
|
|
45
|
+
* console.log(day.date, day.total);
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
async chart(params = {}) {
|
|
50
|
+
validateAnalyticsParams(params);
|
|
51
|
+
return this.http.get('/v1/analytics/chart', params, { cacheTtlMs: 0 });
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Get top-10 endpoints by request volume and by P95 latency.
|
|
55
|
+
*
|
|
56
|
+
* @param params Optional key-scoping and time range.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* const endpoints = await client.analytics.endpoints({ range: '7d' });
|
|
61
|
+
* console.log('Slowest endpoint:', endpoints.data.byLatency[0]?.endpoint);
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
async endpoints(params = {}) {
|
|
65
|
+
validateAnalyticsParams(params);
|
|
66
|
+
return this.http.get('/v1/analytics/endpoints', params, { cacheTtlMs: 0 });
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get paginated API request logs for the authenticated user.
|
|
70
|
+
*
|
|
71
|
+
* Supports cursor-based pagination via the `cursor` parameter.
|
|
72
|
+
* Maximum `limit` is 1000.
|
|
73
|
+
*
|
|
74
|
+
* @param params Filter and pagination parameters.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```ts
|
|
78
|
+
* const logs = await client.analytics.logs({ limit: 50, status: '4xx' });
|
|
79
|
+
* for (const entry of logs.data.items) {
|
|
80
|
+
* console.log(entry.method, entry.endpoint, entry.statusCode);
|
|
81
|
+
* }
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
async logs(params = {}) {
|
|
85
|
+
if (params.limit !== undefined) {
|
|
86
|
+
if (!Number.isInteger(params.limit) || params.limit < 1 || params.limit > 1000) {
|
|
87
|
+
throw new Error('limit must be an integer between 1 and 1000');
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
validateAnalyticsParams(params);
|
|
91
|
+
return this.http.get('/v1/analytics/logs', params, { cacheTtlMs: 0 });
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Async generator that automatically paginates through all log entries.
|
|
95
|
+
*
|
|
96
|
+
* Uses cursor-based pagination. Yields one page at a time.
|
|
97
|
+
*
|
|
98
|
+
* @param params Same parameters as `logs()`. Do not pass `cursor`.
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```ts
|
|
102
|
+
* for await (const page of client.analytics.logPages({ range: '7d' })) {
|
|
103
|
+
* for (const entry of page.data.items) {
|
|
104
|
+
* console.log(entry.requestId, entry.statusCode);
|
|
105
|
+
* }
|
|
106
|
+
* }
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
async *logPages(params) {
|
|
110
|
+
let cursor = undefined;
|
|
111
|
+
let hasMore = true;
|
|
112
|
+
while (hasMore) {
|
|
113
|
+
const result = await this.logs({
|
|
114
|
+
...params,
|
|
115
|
+
...(cursor !== undefined ? { cursor } : {}),
|
|
116
|
+
});
|
|
117
|
+
yield result;
|
|
118
|
+
const logs = result.data;
|
|
119
|
+
cursor = logs.nextCursor ?? undefined;
|
|
120
|
+
hasMore = logs.hasNextPage && cursor !== undefined;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// ── Helpers ────────────────────────────────────────────────────────────────────
|
|
125
|
+
const VALID_RANGES = new Set(['24h', '7d', '30d', '90d']);
|
|
126
|
+
function validateAnalyticsParams(params) {
|
|
127
|
+
if (params.range !== undefined && !VALID_RANGES.has(params.range)) {
|
|
128
|
+
throw new Error(`range must be one of: 24h, 7d, 30d, 90d. Got: "${params.range}"`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=analytics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics.js","sourceRoot":"","sources":["../../../src/resources/analytics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAcH,MAAM,OAAO,iBAAiB;IACX,IAAI,CAAa;IAElC,YAAY,IAAgB;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,OAAO,CACX,SAAiC,EAAE;QAEnC,uBAAuB,CAAC,MAAM,CAAC,CAAC;QAChC,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAClB,uBAAuB,EACvB,MAAiC,EACjC,EAAE,UAAU,EAAE,CAAC,EAAE,CAClB,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,KAAK,CACT,SAA+B,EAAE;QAEjC,uBAAuB,CAAC,MAAM,CAAC,CAAC;QAChC,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAClB,qBAAqB,EACrB,MAAiC,EACjC,EAAE,UAAU,EAAE,CAAC,EAAE,CAClB,CAAC;IACJ,CAAC;IAED;;;;;;;;;;OAUG;IACH,KAAK,CAAC,SAAS,CACb,SAAmC,EAAE;QAErC,uBAAuB,CAAC,MAAM,CAAC,CAAC;QAChC,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAClB,yBAAyB,EACzB,MAAiC,EACjC,EAAE,UAAU,EAAE,CAAC,EAAE,CAClB,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACH,KAAK,CAAC,IAAI,CACR,SAA8B,EAAE;QAEhC,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAC/B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,GAAG,CAAC,IAAI,MAAM,CAAC,KAAK,GAAG,IAAI,EAAE,CAAC;gBAC/E,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;YACjE,CAAC;QACH,CAAC;QACD,uBAAuB,CAAC,MAAM,CAAC,CAAC;QAChC,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAClB,oBAAoB,EACpB,MAAiC,EACjC,EAAE,UAAU,EAAE,CAAC,EAAE,CAClB,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACH,KAAK,CAAC,CAAC,QAAQ,CACb,MAA2C;QAE3C,IAAI,MAAM,GAAuB,SAAS,CAAC;QAC3C,IAAI,OAAO,GAAG,IAAI,CAAC;QAEnB,OAAO,OAAO,EAAE,CAAC;YACf,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC;gBAC7B,GAAG,MAAM;gBACT,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC5C,CAAC,CAAC;YACH,MAAM,MAAM,CAAC;YAEb,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;YACzB,MAAM,GAAG,IAAI,CAAC,UAAU,IAAI,SAAS,CAAC;YACtC,OAAO,GAAG,IAAI,CAAC,WAAW,IAAI,MAAM,KAAK,SAAS,CAAC;QACrD,CAAC;IACH,CAAC;CACF;AAED,kFAAkF;AAElF,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;AAE1D,SAAS,uBAAuB,CAAC,MAA0B;IACzD,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAClE,MAAM,IAAI,KAAK,CACb,kDAAkD,MAAM,CAAC,KAAK,GAAG,CAClE,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Assistance Listings resource client.
|
|
3
|
+
*
|
|
4
|
+
* Wraps all /v1/assistance endpoints:
|
|
5
|
+
* - list GET /v1/assistance
|
|
6
|
+
* - stats GET /v1/assistance/stats
|
|
7
|
+
* - get GET /v1/assistance/:number (CFDA program number)
|
|
8
|
+
* - paginate auto-paginates over the list endpoint
|
|
9
|
+
*/
|
|
10
|
+
export class AssistanceResource {
|
|
11
|
+
http;
|
|
12
|
+
constructor(http) {
|
|
13
|
+
this.http = http;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Search and filter federal assistance listings (CFDA programs).
|
|
17
|
+
*
|
|
18
|
+
* @param params Filter and pagination parameters.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* const result = await client.assistance.list({ agency: 'Department of Energy' });
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
async list(params = {}) {
|
|
26
|
+
return this.http.get('/v1/assistance', params);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Get aggregated statistics for assistance listings.
|
|
30
|
+
*
|
|
31
|
+
* @param params Optional filter parameters.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```ts
|
|
35
|
+
* const stats = await client.assistance.stats();
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
async stats(params = {}) {
|
|
39
|
+
return this.http.get('/v1/assistance/stats', params);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Get a single assistance listing by its CFDA program number.
|
|
43
|
+
*
|
|
44
|
+
* @param programNumber CFDA program number in "XX.XXX" format (e.g. "17.002").
|
|
45
|
+
* @throws {NotFoundError} If the program number does not exist.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```ts
|
|
49
|
+
* const listing = await client.assistance.get('84.048');
|
|
50
|
+
* console.log(listing.data.programTitle);
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
async get(programNumber) {
|
|
54
|
+
if (!programNumber || typeof programNumber !== 'string' || programNumber.trim() === '') {
|
|
55
|
+
throw new Error('programNumber must be a non-empty string');
|
|
56
|
+
}
|
|
57
|
+
const trimmed = programNumber.trim();
|
|
58
|
+
if (!/^\d{2}\.\d{3}$/.test(trimmed)) {
|
|
59
|
+
throw new Error('programNumber must be in "XX.XXX" format (e.g. "17.002")');
|
|
60
|
+
}
|
|
61
|
+
return this.http.get(`/v1/assistance/${encodeURIComponent(trimmed)}`);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Async generator that automatically paginates over all matching assistance listings.
|
|
65
|
+
*
|
|
66
|
+
* @param params Same filter parameters as `list()`. Do not pass `page`.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```ts
|
|
70
|
+
* for await (const page of client.assistance.paginate({ agency: 'HHS' })) {
|
|
71
|
+
* for (const listing of page.data) {
|
|
72
|
+
* console.log(listing.programNumber, listing.programTitle);
|
|
73
|
+
* }
|
|
74
|
+
* }
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
async *paginate(params) {
|
|
78
|
+
let page = 1;
|
|
79
|
+
let hasMore = true;
|
|
80
|
+
while (hasMore) {
|
|
81
|
+
const result = await this.list({ ...params, page });
|
|
82
|
+
yield result;
|
|
83
|
+
const pagination = result.pagination;
|
|
84
|
+
if (pagination === null) {
|
|
85
|
+
hasMore = false;
|
|
86
|
+
}
|
|
87
|
+
else if ('hasNextPage' in pagination) {
|
|
88
|
+
hasMore = pagination.hasNextPage;
|
|
89
|
+
if (hasMore)
|
|
90
|
+
page++;
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
hasMore = false;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=assistance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assistance.js","sourceRoot":"","sources":["../../../src/resources/assistance.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAUH,MAAM,OAAO,kBAAkB;IACZ,IAAI,CAAa;IAElC,YAAY,IAAgB;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,IAAI,CACR,SAA+B,EAAE;QAEjC,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAClB,gBAAgB,EAChB,MAAiC,CAClC,CAAC;IACJ,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,KAAK,CACT,SAAmC,EAAE;QAErC,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAClB,sBAAsB,EACtB,MAAiC,CAClC,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,GAAG,CAAC,aAAqB;QAC7B,IAAI,CAAC,aAAa,IAAI,OAAO,aAAa,KAAK,QAAQ,IAAI,aAAa,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACvF,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC9D,CAAC;QACD,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,EAAE,CAAC;QACrC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;QAC9E,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAClB,kBAAkB,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAChD,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,CAAC,QAAQ,CACb,MAA0C;QAE1C,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,IAAI,OAAO,GAAG,IAAI,CAAC;QAEnB,OAAO,OAAO,EAAE,CAAC;YACf,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YACpD,MAAM,MAAM,CAAC;YAEb,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;YACrC,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;gBACxB,OAAO,GAAG,KAAK,CAAC;YAClB,CAAC;iBAAM,IAAI,aAAa,IAAI,UAAU,EAAE,CAAC;gBACvC,OAAO,GAAG,UAAU,CAAC,WAAW,CAAC;gBACjC,IAAI,OAAO;oBAAE,IAAI,EAAE,CAAC;YACtB,CAAC;iBAAM,CAAC;gBACN,OAAO,GAAG,KAAK,CAAC;YAClB,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Entities resource client.
|
|
3
|
+
*
|
|
4
|
+
* Wraps all /v1/entities endpoints:
|
|
5
|
+
* - list GET /v1/entities
|
|
6
|
+
* - get GET /v1/entities/:uei
|
|
7
|
+
* - opportunities GET /v1/entities/:uei/opportunities
|
|
8
|
+
* - exclusionCheck GET /v1/entities/:uei/exclusion-check
|
|
9
|
+
* - stats GET /v1/entities/stats
|
|
10
|
+
* - paginate auto-paginates over the list endpoint
|
|
11
|
+
*/
|
|
12
|
+
import { ValidationError } from '../errors.js';
|
|
13
|
+
export class EntitiesResource {
|
|
14
|
+
http;
|
|
15
|
+
constructor(http) {
|
|
16
|
+
this.http = http;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Search and filter SAM.gov registered entities (vendors).
|
|
20
|
+
*
|
|
21
|
+
* @param params Filter and pagination parameters.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* const result = await client.entities.list({
|
|
26
|
+
* naics: '541512',
|
|
27
|
+
* certification: '8A',
|
|
28
|
+
* state: 'VA',
|
|
29
|
+
* });
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
async list(params = {}) {
|
|
33
|
+
return this.http.get('/v1/entities', params);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Get the full SAM.gov registration profile for a vendor by UEI.
|
|
37
|
+
*
|
|
38
|
+
* @param uei Unique Entity Identifier (12-char alphanumeric).
|
|
39
|
+
* @throws {NotFoundError} If the entity does not exist.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* const entity = await client.entities.get('ABCDEF123456');
|
|
44
|
+
* console.log(entity.data.legalBusinessName);
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
async get(uei) {
|
|
48
|
+
validateUei(uei);
|
|
49
|
+
return this.http.get(`/v1/entities/${encodeURIComponent(uei.trim().toUpperCase())}`);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Get awarded contract opportunities linked to a vendor.
|
|
53
|
+
*
|
|
54
|
+
* @param uei Unique Entity Identifier.
|
|
55
|
+
* @param params Pagination parameters.
|
|
56
|
+
* @throws {NotFoundError} If the entity does not exist.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* const contracts = await client.entities.opportunities('ABCDEF123456', { limit: 10 });
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
async opportunities(uei, params = {}) {
|
|
64
|
+
validateUei(uei);
|
|
65
|
+
return this.http.get(`/v1/entities/${encodeURIComponent(uei.trim().toUpperCase())}/opportunities`, params);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Check whether a vendor is currently excluded (debarred) from federal contracts.
|
|
69
|
+
*
|
|
70
|
+
* @param uei Unique Entity Identifier.
|
|
71
|
+
* @throws {NotFoundError} If the entity does not exist.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```ts
|
|
75
|
+
* const check = await client.entities.exclusionCheck('ABCDEF123456');
|
|
76
|
+
* if (check.data.excluded) {
|
|
77
|
+
* console.warn('Vendor is EXCLUDED!', check.data.exclusion);
|
|
78
|
+
* }
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
async exclusionCheck(uei) {
|
|
82
|
+
validateUei(uei);
|
|
83
|
+
return this.http.get(`/v1/entities/${encodeURIComponent(uei.trim().toUpperCase())}/exclusion-check`, {}, { cacheTtlMs: 0 } // Never cache exclusion checks — compliance-critical.
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Get aggregated entity registration statistics.
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```ts
|
|
91
|
+
* const stats = await client.entities.stats();
|
|
92
|
+
* console.log('Total registered entities:', stats.data.total);
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
async stats() {
|
|
96
|
+
return this.http.get('/v1/entities/stats');
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Async generator that automatically paginates over all matching entities.
|
|
100
|
+
*
|
|
101
|
+
* @param params Same filter parameters as `list()`. Do not pass `page`.
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* ```ts
|
|
105
|
+
* for await (const page of client.entities.paginate({ naics: '541512' })) {
|
|
106
|
+
* for (const entity of page.data) {
|
|
107
|
+
* console.log(entity.legalBusinessName);
|
|
108
|
+
* }
|
|
109
|
+
* }
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
async *paginate(params) {
|
|
113
|
+
let page = 1;
|
|
114
|
+
let hasMore = true;
|
|
115
|
+
while (hasMore) {
|
|
116
|
+
const result = await this.list({ ...params, page });
|
|
117
|
+
yield result;
|
|
118
|
+
const pagination = result.pagination;
|
|
119
|
+
if (pagination === null) {
|
|
120
|
+
hasMore = false;
|
|
121
|
+
}
|
|
122
|
+
else if ('hasNextPage' in pagination) {
|
|
123
|
+
hasMore = pagination.hasNextPage;
|
|
124
|
+
if (hasMore)
|
|
125
|
+
page++;
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
hasMore = false;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// ── Helpers ────────────────────────────────────────────────────────────────────
|
|
134
|
+
/**
|
|
135
|
+
* Validate UEI format: 12-character alphanumeric string.
|
|
136
|
+
* @throws {Error} If UEI is invalid.
|
|
137
|
+
*/
|
|
138
|
+
function validateUei(uei) {
|
|
139
|
+
if (!uei || typeof uei !== 'string' || uei.trim() === '') {
|
|
140
|
+
throw new ValidationError({ message: 'uei must be a non-empty string', status: 400 });
|
|
141
|
+
}
|
|
142
|
+
if (!/^[A-Za-z0-9]{12}$/.test(uei.trim())) {
|
|
143
|
+
throw new ValidationError({ message: 'uei must be a 12-character alphanumeric string (e.g. ABCDEF123456)', status: 400 });
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=entities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entities.js","sourceRoot":"","sources":["../../../src/resources/entities.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exclusions resource client.
|
|
3
|
+
*
|
|
4
|
+
* Wraps all /v1/exclusions endpoints:
|
|
5
|
+
* - list GET /v1/exclusions
|
|
6
|
+
* - get GET /v1/exclusions/:exclusionId
|
|
7
|
+
* - check POST /v1/exclusions/check (bulk compliance)
|
|
8
|
+
* - stats GET /v1/exclusions/stats
|
|
9
|
+
* - paginate auto-paginates over the list endpoint
|
|
10
|
+
*/
|
|
11
|
+
import { ValidationError } from '../errors.js';
|
|
12
|
+
export class ExclusionsResource {
|
|
13
|
+
http;
|
|
14
|
+
constructor(http) {
|
|
15
|
+
this.http = http;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Search and filter the SAM.gov exclusions database.
|
|
19
|
+
*
|
|
20
|
+
* @param params Filter and pagination parameters.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* const result = await client.exclusions.list({ uei: 'ABCDEF123456' });
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
async list(params = {}) {
|
|
28
|
+
return this.http.get('/v1/exclusions', params);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Get a single exclusion record by its unique ID.
|
|
32
|
+
*
|
|
33
|
+
* @param exclusionId Internal exclusion identifier.
|
|
34
|
+
* @throws {NotFoundError} If the exclusion record does not exist.
|
|
35
|
+
*/
|
|
36
|
+
async get(exclusionId) {
|
|
37
|
+
if (!exclusionId || typeof exclusionId !== 'string' || exclusionId.trim() === '') {
|
|
38
|
+
throw new ValidationError({ message: 'exclusionId must be a non-empty string', status: 400 });
|
|
39
|
+
}
|
|
40
|
+
return this.http.get(`/v1/exclusions/${encodeURIComponent(exclusionId.trim())}`);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Bulk compliance check — verify up to 100 entities against the exclusions database.
|
|
44
|
+
*
|
|
45
|
+
* Each entity must include at least one of: `uei`, `cage`, or `name`.
|
|
46
|
+
* When `fuzzyMatch` is true (default), name matching uses trigram similarity.
|
|
47
|
+
*
|
|
48
|
+
* @param params List of entities and fuzzy-match flag.
|
|
49
|
+
* @returns Per-entity exclusion status with match confidence scores.
|
|
50
|
+
* @throws {ValidationError} If more than 100 entities are provided.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* const result = await client.exclusions.check({
|
|
55
|
+
* entities: [
|
|
56
|
+
* { uei: 'ABCDEF123456' },
|
|
57
|
+
* { name: 'Acme Corporation' },
|
|
58
|
+
* ],
|
|
59
|
+
* });
|
|
60
|
+
* for (const item of result.data) {
|
|
61
|
+
* console.log(item.input.name, '->', item.excluded ? 'EXCLUDED' : 'OK');
|
|
62
|
+
* }
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
async check(params) {
|
|
66
|
+
if (!Array.isArray(params.entities)) {
|
|
67
|
+
throw new ValidationError({ message: 'entities must be an array', status: 400 });
|
|
68
|
+
}
|
|
69
|
+
if (params.entities.length === 0) {
|
|
70
|
+
throw new ValidationError({ message: 'entities array must contain at least one entry', status: 400 });
|
|
71
|
+
}
|
|
72
|
+
if (params.entities.length > 100) {
|
|
73
|
+
throw new ValidationError({ message: 'entities array must not exceed 100 entries', status: 400 });
|
|
74
|
+
}
|
|
75
|
+
for (const [i, entity] of params.entities.entries()) {
|
|
76
|
+
if (!entity.uei && !entity.cage && !entity.name) {
|
|
77
|
+
throw new ValidationError({
|
|
78
|
+
message: `entities[${i}] must include at least one of: uei, cage, name`,
|
|
79
|
+
status: 400,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return this.http.post('/v1/exclusions/check', params);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Get aggregated exclusion statistics.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```ts
|
|
90
|
+
* const stats = await client.exclusions.stats();
|
|
91
|
+
* console.log('Total active exclusions:', stats.data.active);
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
async stats() {
|
|
95
|
+
return this.http.get('/v1/exclusions/stats');
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Async generator that automatically paginates over all matching exclusions.
|
|
99
|
+
*
|
|
100
|
+
* @param params Same filter parameters as `list()`. Do not pass `page`.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```ts
|
|
104
|
+
* for await (const page of client.exclusions.paginate({ agency: 'DEPT OF DEFENSE' })) {
|
|
105
|
+
* for (const exc of page.data) {
|
|
106
|
+
* console.log(exc.name, exc.effectiveDate);
|
|
107
|
+
* }
|
|
108
|
+
* }
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
async *paginate(params) {
|
|
112
|
+
let page = 1;
|
|
113
|
+
let hasMore = true;
|
|
114
|
+
while (hasMore) {
|
|
115
|
+
const result = await this.list({ ...params, page });
|
|
116
|
+
yield result;
|
|
117
|
+
const pagination = result.pagination;
|
|
118
|
+
if (pagination === null) {
|
|
119
|
+
hasMore = false;
|
|
120
|
+
}
|
|
121
|
+
else if ('hasNextPage' in pagination) {
|
|
122
|
+
hasMore = pagination.hasNextPage;
|
|
123
|
+
if (hasMore)
|
|
124
|
+
page++;
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
hasMore = false;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=exclusions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exclusions.js","sourceRoot":"","sources":["../../../src/resources/exclusions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Intelligence resource client.
|
|
3
|
+
*
|
|
4
|
+
* Wraps all /v1/intelligence endpoints:
|
|
5
|
+
* - entityProfile GET /v1/intelligence/entity/:uei
|
|
6
|
+
* - marketAnalysis GET /v1/intelligence/market/:naics
|
|
7
|
+
* - complianceCheck POST /v1/intelligence/compliance-check
|
|
8
|
+
*/
|
|
9
|
+
import { ValidationError } from '../errors.js';
|
|
10
|
+
export class IntelligenceResource {
|
|
11
|
+
http;
|
|
12
|
+
constructor(http) {
|
|
13
|
+
this.http = http;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Get a comprehensive 360° intelligence profile for a vendor.
|
|
17
|
+
*
|
|
18
|
+
* Aggregates: contract history, agency relationships, certifications,
|
|
19
|
+
* exclusion status, and risk indicators into a single response.
|
|
20
|
+
*
|
|
21
|
+
* @param uei Unique Entity Identifier (12-char alphanumeric).
|
|
22
|
+
* @throws {NotFoundError} If the entity does not exist in SAM.gov.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* const profile = await client.intelligence.entityProfile('ABCDEF123456');
|
|
27
|
+
* console.log('Contract count:', profile.data.contractCount);
|
|
28
|
+
* console.log('Risk:', profile.data.riskLevel);
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
async entityProfile(uei) {
|
|
32
|
+
if (!uei || typeof uei !== 'string' || uei.trim() === '') {
|
|
33
|
+
throw new ValidationError({ message: 'uei must be a non-empty string', status: 400 });
|
|
34
|
+
}
|
|
35
|
+
if (!/^[A-Za-z0-9]{12}$/.test(uei.trim())) {
|
|
36
|
+
throw new ValidationError({ message: 'uei must be a 12-character alphanumeric string', status: 400 });
|
|
37
|
+
}
|
|
38
|
+
return this.http.get(`/v1/intelligence/entity/${encodeURIComponent(uei.trim().toUpperCase())}`);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Get a market analysis for a specific NAICS code.
|
|
42
|
+
*
|
|
43
|
+
* Returns: top awardees, top agencies, set-aside breakdown, active solicitations,
|
|
44
|
+
* total market size, and recent award trends.
|
|
45
|
+
*
|
|
46
|
+
* @param naics 2–6 digit NAICS code (more digits = more specific market segment).
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```ts
|
|
50
|
+
* const market = await client.intelligence.marketAnalysis('541512');
|
|
51
|
+
* console.log('Market size (cents):', market.data.totalMarketSize);
|
|
52
|
+
* console.log('Top awardee:', market.data.topAwardees[0]?.name);
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
async marketAnalysis(naics) {
|
|
56
|
+
if (!naics || typeof naics !== 'string' || naics.trim() === '') {
|
|
57
|
+
throw new ValidationError({ message: 'naics must be a non-empty string', status: 400 });
|
|
58
|
+
}
|
|
59
|
+
if (!/^\d{2,6}$/.test(naics.trim())) {
|
|
60
|
+
throw new ValidationError({ message: 'naics must be a numeric string of 2 to 6 digits (e.g. "541512")', status: 400 });
|
|
61
|
+
}
|
|
62
|
+
return this.http.get(`/v1/intelligence/market/${encodeURIComponent(naics.trim())}`);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Perform a full compliance check for a vendor.
|
|
66
|
+
*
|
|
67
|
+
* Returns: exclusion status, SAM.gov registration status, risk score,
|
|
68
|
+
* and risk indicators in one API call.
|
|
69
|
+
*
|
|
70
|
+
* @param params Object containing the UEI to check.
|
|
71
|
+
* @throws {NotFoundError} If the entity does not exist in SAM.gov.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```ts
|
|
75
|
+
* const compliance = await client.intelligence.complianceCheck({ uei: 'ABCDEF123456' });
|
|
76
|
+
* if (compliance.data.excluded || compliance.data.riskLevel === 'high') {
|
|
77
|
+
* console.warn('Do not contract with this vendor.');
|
|
78
|
+
* }
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
async complianceCheck(params) {
|
|
82
|
+
if (!params.uei || typeof params.uei !== 'string' || params.uei.trim() === '') {
|
|
83
|
+
throw new ValidationError({ message: 'params.uei must be a non-empty string', status: 400 });
|
|
84
|
+
}
|
|
85
|
+
if (!/^[A-Za-z0-9]{12}$/.test(params.uei.trim())) {
|
|
86
|
+
throw new ValidationError({ message: 'params.uei must be a 12-character alphanumeric string', status: 400 });
|
|
87
|
+
}
|
|
88
|
+
return this.http.post('/v1/intelligence/compliance-check', {
|
|
89
|
+
uei: params.uei.trim().toUpperCase(),
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=intelligence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intelligence.js","sourceRoot":"","sources":["../../../src/resources/intelligence.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAS/C,MAAM,OAAO,oBAAoB;IACd,IAAI,CAAa;IAElC,YAAY,IAAgB;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACH,KAAK,CAAC,aAAa,CAAC,GAAW;QAC7B,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACzD,MAAM,IAAI,eAAe,CAAC,EAAE,OAAO,EAAE,gCAAgC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACxF,CAAC;QACD,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YAC1C,MAAM,IAAI,eAAe,CAAC,EAAE,OAAO,EAAE,gDAAgD,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACxG,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAClB,2BAA2B,kBAAkB,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,EAAE,CAC1E,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,cAAc,CAAC,KAAa;QAChC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAC/D,MAAM,IAAI,eAAe,CAAC,EAAE,OAAO,EAAE,kCAAkC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAC1F,CAAC;QACD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YACpC,MAAM,IAAI,eAAe,CAAC,EAAE,OAAO,EAAE,iEAAiE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACzH,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAClB,2BAA2B,kBAAkB,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,CAC9D,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;;;;;;OAgBG;IACH,KAAK,CAAC,eAAe,CACnB,MAAoC;QAEpC,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ,IAAI,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAC9E,MAAM,IAAI,eAAe,CAAC,EAAE,OAAO,EAAE,uCAAuC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAC/F,CAAC;QACD,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YACjD,MAAM,IAAI,eAAe,CAAC,EAAE,OAAO,EAAE,uDAAuD,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAC/G,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAoB,mCAAmC,EAAE;YAC5E,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE;SACrC,CAAC,CAAC;IACL,CAAC;CACF"}
|