@insureco/bio 0.4.0 → 0.5.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/dist/chunk-PLN6QPED.mjs +169 -0
- package/dist/graph.d.mts +204 -0
- package/dist/graph.d.ts +204 -0
- package/dist/graph.js +225 -0
- package/dist/graph.mjs +7 -0
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +161 -0
- package/dist/index.mjs +4 -0
- package/package.json +14 -8
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BioError,
|
|
3
|
+
parseJsonResponse,
|
|
4
|
+
retryDelay,
|
|
5
|
+
sleep
|
|
6
|
+
} from "./chunk-NK5VXXWF.mjs";
|
|
7
|
+
|
|
8
|
+
// src/graph.ts
|
|
9
|
+
var DEFAULT_TIMEOUT_MS = 1e4;
|
|
10
|
+
var BIO_GRAPH_URL = "https://bio-graph.tawa.pro";
|
|
11
|
+
var GraphClient = class _GraphClient {
|
|
12
|
+
graphUrl;
|
|
13
|
+
accessToken;
|
|
14
|
+
timeoutMs;
|
|
15
|
+
constructor(config = {}) {
|
|
16
|
+
this.graphUrl = (config.graphUrl ?? process.env.BIO_GRAPH_URL ?? BIO_GRAPH_URL).replace(/\/$/, "");
|
|
17
|
+
this.accessToken = config.accessToken;
|
|
18
|
+
this.timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Create a GraphClient from environment variables.
|
|
22
|
+
* BIO_GRAPH_URL defaults to https://bio-graph.tawa.pro if not set.
|
|
23
|
+
*/
|
|
24
|
+
static fromEnv(overrides) {
|
|
25
|
+
return new _GraphClient({
|
|
26
|
+
graphUrl: overrides?.graphUrl ?? process.env.BIO_GRAPH_URL,
|
|
27
|
+
accessToken: overrides?.accessToken,
|
|
28
|
+
timeoutMs: overrides?.timeoutMs
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
// ─── Public Profile Routes ────────────────────────────────────────────────
|
|
32
|
+
/** Look up an agent by NPN. Returns agent properties + employment chain. */
|
|
33
|
+
async getAgent(npn) {
|
|
34
|
+
return this.get(`/api/graph/agent/${encodeURIComponent(npn)}`);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Look up an agency by iecHash, raterspotId, or orgSlug.
|
|
38
|
+
* Returns agency properties + staff list + accessible programs.
|
|
39
|
+
*/
|
|
40
|
+
async getAgency(iecHash) {
|
|
41
|
+
return this.get(`/api/graph/agency/${encodeURIComponent(iecHash)}`);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Look up a carrier by NAIC code, iecHash, raterspotId, or orgSlug.
|
|
45
|
+
* Returns carrier properties + managed programs.
|
|
46
|
+
*/
|
|
47
|
+
async getCarrier(naic) {
|
|
48
|
+
return this.get(`/api/graph/carrier/${encodeURIComponent(naic)}`);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Look up a program by iecHash or raterspotId.
|
|
52
|
+
* Returns program properties + managing carrier or MGA.
|
|
53
|
+
*/
|
|
54
|
+
async getProgram(iecHash) {
|
|
55
|
+
return this.get(`/api/graph/program/${encodeURIComponent(iecHash)}`);
|
|
56
|
+
}
|
|
57
|
+
// ─── Authenticated Routes ─────────────────────────────────────────────────
|
|
58
|
+
/**
|
|
59
|
+
* Find programs whose appetite covers a given risk.
|
|
60
|
+
* Requires an accessToken (auth: required).
|
|
61
|
+
*
|
|
62
|
+
* @param input - Risk criteria: NAICS code, state, line of business, optional limits
|
|
63
|
+
*/
|
|
64
|
+
async matchAppetite(input) {
|
|
65
|
+
return this.post("/api/graph/appetite/match", input, { requiresAuth: true });
|
|
66
|
+
}
|
|
67
|
+
// ─── Internal ─────────────────────────────────────────────────────────────
|
|
68
|
+
async get(path, attempt = 0) {
|
|
69
|
+
const url = `${this.graphUrl}${path}`;
|
|
70
|
+
const controller = new AbortController();
|
|
71
|
+
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
72
|
+
let response;
|
|
73
|
+
try {
|
|
74
|
+
response = await fetch(url, {
|
|
75
|
+
headers: this.buildHeaders(),
|
|
76
|
+
signal: controller.signal
|
|
77
|
+
});
|
|
78
|
+
} catch (err) {
|
|
79
|
+
clearTimeout(timer);
|
|
80
|
+
const isTimeout = err instanceof Error && err.name === "AbortError";
|
|
81
|
+
if (!isTimeout && attempt < 2) {
|
|
82
|
+
await sleep(retryDelay(attempt));
|
|
83
|
+
return this.get(path, attempt + 1);
|
|
84
|
+
}
|
|
85
|
+
throw new BioError(
|
|
86
|
+
isTimeout ? "bio-graph request timed out" : `bio-graph request failed: ${String(err)}`,
|
|
87
|
+
isTimeout ? "timeout" : "network_error"
|
|
88
|
+
);
|
|
89
|
+
} finally {
|
|
90
|
+
clearTimeout(timer);
|
|
91
|
+
}
|
|
92
|
+
return this.handleResponse(response, path);
|
|
93
|
+
}
|
|
94
|
+
async post(path, body, opts = {}, attempt = 0) {
|
|
95
|
+
if (opts.requiresAuth && !this.accessToken) {
|
|
96
|
+
throw new BioError(
|
|
97
|
+
`bio-graph ${path} requires an accessToken \u2014 pass it in the GraphClient constructor`,
|
|
98
|
+
"config_error"
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
const url = `${this.graphUrl}${path}`;
|
|
102
|
+
const controller = new AbortController();
|
|
103
|
+
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
104
|
+
let response;
|
|
105
|
+
try {
|
|
106
|
+
response = await fetch(url, {
|
|
107
|
+
method: "POST",
|
|
108
|
+
headers: { ...this.buildHeaders(), "Content-Type": "application/json" },
|
|
109
|
+
body: JSON.stringify(body),
|
|
110
|
+
signal: controller.signal
|
|
111
|
+
});
|
|
112
|
+
} catch (err) {
|
|
113
|
+
clearTimeout(timer);
|
|
114
|
+
const isTimeout = err instanceof Error && err.name === "AbortError";
|
|
115
|
+
if (!isTimeout && attempt < 2) {
|
|
116
|
+
await sleep(retryDelay(attempt));
|
|
117
|
+
return this.post(path, body, opts, attempt + 1);
|
|
118
|
+
}
|
|
119
|
+
throw new BioError(
|
|
120
|
+
isTimeout ? "bio-graph request timed out" : `bio-graph request failed: ${String(err)}`,
|
|
121
|
+
isTimeout ? "timeout" : "network_error"
|
|
122
|
+
);
|
|
123
|
+
} finally {
|
|
124
|
+
clearTimeout(timer);
|
|
125
|
+
}
|
|
126
|
+
return this.handleResponse(response, path);
|
|
127
|
+
}
|
|
128
|
+
buildHeaders() {
|
|
129
|
+
const headers = {};
|
|
130
|
+
if (this.accessToken) {
|
|
131
|
+
headers["Authorization"] = `Bearer ${this.accessToken}`;
|
|
132
|
+
}
|
|
133
|
+
return headers;
|
|
134
|
+
}
|
|
135
|
+
async handleResponse(response, path) {
|
|
136
|
+
if (response.status === 404) {
|
|
137
|
+
throw new BioError(`bio-graph entity not found: ${path}`, "not_found", 404);
|
|
138
|
+
}
|
|
139
|
+
if (response.status === 401) {
|
|
140
|
+
throw new BioError(
|
|
141
|
+
"bio-graph authentication failed \u2014 provide a valid accessToken",
|
|
142
|
+
"unauthorized",
|
|
143
|
+
401
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
if (response.status === 402) {
|
|
147
|
+
throw new BioError(
|
|
148
|
+
"bio-graph call failed \u2014 insufficient gas tokens. Top up at tawa.insureco.io/wallet",
|
|
149
|
+
"insufficient_gas",
|
|
150
|
+
402
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
if (!response.ok) {
|
|
154
|
+
const body2 = await parseJsonResponse(response).catch(() => ({}));
|
|
155
|
+
throw new BioError(
|
|
156
|
+
`bio-graph returned ${response.status} for ${path}`,
|
|
157
|
+
"api_error",
|
|
158
|
+
response.status,
|
|
159
|
+
body2
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
const body = await parseJsonResponse(response);
|
|
163
|
+
return body;
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
export {
|
|
168
|
+
GraphClient
|
|
169
|
+
};
|
package/dist/graph.d.mts
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
interface GraphClientConfig {
|
|
2
|
+
/** Base URL for bio-graph service. Defaults to BIO_GRAPH_URL env var or https://bio-graph.tawa.pro */
|
|
3
|
+
graphUrl?: string;
|
|
4
|
+
/** Bearer token for authenticated routes (appetite/match, same-as-queue, etc.) */
|
|
5
|
+
accessToken?: string;
|
|
6
|
+
/** Request timeout in ms. Default: 10_000 */
|
|
7
|
+
timeoutMs?: number;
|
|
8
|
+
}
|
|
9
|
+
interface AgentEmployer {
|
|
10
|
+
agencyName: string | null;
|
|
11
|
+
agencyIecHash: string | null;
|
|
12
|
+
agencyOrgSlug: string | null;
|
|
13
|
+
agencyRaterspotId: string | null;
|
|
14
|
+
current: boolean;
|
|
15
|
+
}
|
|
16
|
+
interface AgentProfile {
|
|
17
|
+
iecHash: string | null;
|
|
18
|
+
name: string | null;
|
|
19
|
+
npn: string | null;
|
|
20
|
+
bioId: string | null;
|
|
21
|
+
role: string | null;
|
|
22
|
+
email: string | null;
|
|
23
|
+
phone: string | null;
|
|
24
|
+
address: string | null;
|
|
25
|
+
city: string | null;
|
|
26
|
+
state: string | null;
|
|
27
|
+
zip: string | null;
|
|
28
|
+
licenseNo: string | null;
|
|
29
|
+
status: string | null;
|
|
30
|
+
linesOfAuthority: string[];
|
|
31
|
+
territories: string[];
|
|
32
|
+
linesOfBusiness: string[];
|
|
33
|
+
isPublic: boolean;
|
|
34
|
+
claimedAt: string | null;
|
|
35
|
+
employment: AgentEmployer[];
|
|
36
|
+
}
|
|
37
|
+
interface AgencyStaffMember {
|
|
38
|
+
name: string | null;
|
|
39
|
+
npn: string | null;
|
|
40
|
+
iecHash: string | null;
|
|
41
|
+
role: string | null;
|
|
42
|
+
email: string | null;
|
|
43
|
+
}
|
|
44
|
+
interface AgencyProgram {
|
|
45
|
+
name: string | null;
|
|
46
|
+
raterspotId: string | null;
|
|
47
|
+
iecHash: string | null;
|
|
48
|
+
states: string[];
|
|
49
|
+
carrierName: string | null;
|
|
50
|
+
isActive: boolean;
|
|
51
|
+
}
|
|
52
|
+
interface AgencyProfile {
|
|
53
|
+
iecHash: string | null;
|
|
54
|
+
raterspotId: string | null;
|
|
55
|
+
name: string | null;
|
|
56
|
+
orgSlug: string | null;
|
|
57
|
+
orgId: string | null;
|
|
58
|
+
type: string | null;
|
|
59
|
+
email: string | null;
|
|
60
|
+
phone: string | null;
|
|
61
|
+
website: string | null;
|
|
62
|
+
address: string | null;
|
|
63
|
+
city: string | null;
|
|
64
|
+
state: string | null;
|
|
65
|
+
zip: string | null;
|
|
66
|
+
dba: string | null;
|
|
67
|
+
licenseNo: string | null;
|
|
68
|
+
linesOfAuthority: string | null;
|
|
69
|
+
territories: string[];
|
|
70
|
+
linesOfBusiness: string[];
|
|
71
|
+
isPublic: boolean;
|
|
72
|
+
claimedAt: string | null;
|
|
73
|
+
staff: AgencyStaffMember[];
|
|
74
|
+
programs: AgencyProgram[];
|
|
75
|
+
}
|
|
76
|
+
interface CarrierProgram {
|
|
77
|
+
name: string | null;
|
|
78
|
+
iecHash: string | null;
|
|
79
|
+
raterspotId: string | null;
|
|
80
|
+
states: string[];
|
|
81
|
+
isActive: boolean;
|
|
82
|
+
}
|
|
83
|
+
interface CarrierProfile {
|
|
84
|
+
iecHash: string | null;
|
|
85
|
+
raterspotId: string | null;
|
|
86
|
+
name: string | null;
|
|
87
|
+
naic: string | null;
|
|
88
|
+
orgId: string | null;
|
|
89
|
+
orgSlug: string | null;
|
|
90
|
+
email: string | null;
|
|
91
|
+
phone: string | null;
|
|
92
|
+
website: string | null;
|
|
93
|
+
address: string | null;
|
|
94
|
+
city: string | null;
|
|
95
|
+
state: string | null;
|
|
96
|
+
isPublic: boolean;
|
|
97
|
+
claimedAt: string | null;
|
|
98
|
+
programs: CarrierProgram[];
|
|
99
|
+
}
|
|
100
|
+
interface ProgramProfile {
|
|
101
|
+
iecHash: string | null;
|
|
102
|
+
raterspotId: string | null;
|
|
103
|
+
name: string | null;
|
|
104
|
+
abrv: string | null;
|
|
105
|
+
states: string[];
|
|
106
|
+
isActive: boolean;
|
|
107
|
+
ratingEngine: string | null;
|
|
108
|
+
carrierName: string | null;
|
|
109
|
+
carrierNaic: string | null;
|
|
110
|
+
mgaName: string | null;
|
|
111
|
+
managerIecHash: string | null;
|
|
112
|
+
managerRaterspotId: string | null;
|
|
113
|
+
}
|
|
114
|
+
interface AppetiteMatchInput {
|
|
115
|
+
naicsCode: string;
|
|
116
|
+
state: string;
|
|
117
|
+
lineOfBusiness: string;
|
|
118
|
+
limits?: {
|
|
119
|
+
perOccurrence?: number;
|
|
120
|
+
aggregate?: number;
|
|
121
|
+
};
|
|
122
|
+
reason?: string;
|
|
123
|
+
}
|
|
124
|
+
interface AppetiteMatchProgram {
|
|
125
|
+
name: string | null;
|
|
126
|
+
iecHash: string | null;
|
|
127
|
+
raterspotId: string | null;
|
|
128
|
+
states: string[];
|
|
129
|
+
isActive: boolean;
|
|
130
|
+
carrierName: string | null;
|
|
131
|
+
carrierNaic: string | null;
|
|
132
|
+
mgaName: string | null;
|
|
133
|
+
ratingEngine: string | null;
|
|
134
|
+
}
|
|
135
|
+
interface AppetiteMatchResult {
|
|
136
|
+
programs: AppetiteMatchProgram[];
|
|
137
|
+
total: number;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Client for bio-graph InsureBio distribution graph endpoints.
|
|
141
|
+
*
|
|
142
|
+
* Public profile routes (agent, agency, carrier, program) require no auth.
|
|
143
|
+
* Authenticated routes (appetite match, same-as queue) require an accessToken.
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* import { GraphClient } from '@insureco/bio/graph'
|
|
147
|
+
*
|
|
148
|
+
* // Public profile lookups — no auth needed
|
|
149
|
+
* const graph = new GraphClient()
|
|
150
|
+
* const { agent } = await graph.getAgent('1234567')
|
|
151
|
+
*
|
|
152
|
+
* // Authenticated routes — pass a user or service token
|
|
153
|
+
* const graph = new GraphClient({ accessToken: req.headers.authorization?.slice(7) })
|
|
154
|
+
* const result = await graph.matchAppetite({ naicsCode: '2361', state: 'TX', lineOfBusiness: 'GL' })
|
|
155
|
+
*/
|
|
156
|
+
declare class GraphClient {
|
|
157
|
+
private readonly graphUrl;
|
|
158
|
+
private readonly accessToken;
|
|
159
|
+
private readonly timeoutMs;
|
|
160
|
+
constructor(config?: GraphClientConfig);
|
|
161
|
+
/**
|
|
162
|
+
* Create a GraphClient from environment variables.
|
|
163
|
+
* BIO_GRAPH_URL defaults to https://bio-graph.tawa.pro if not set.
|
|
164
|
+
*/
|
|
165
|
+
static fromEnv(overrides?: GraphClientConfig): GraphClient;
|
|
166
|
+
/** Look up an agent by NPN. Returns agent properties + employment chain. */
|
|
167
|
+
getAgent(npn: string): Promise<{
|
|
168
|
+
agent: AgentProfile;
|
|
169
|
+
}>;
|
|
170
|
+
/**
|
|
171
|
+
* Look up an agency by iecHash, raterspotId, or orgSlug.
|
|
172
|
+
* Returns agency properties + staff list + accessible programs.
|
|
173
|
+
*/
|
|
174
|
+
getAgency(iecHash: string): Promise<{
|
|
175
|
+
agency: AgencyProfile;
|
|
176
|
+
}>;
|
|
177
|
+
/**
|
|
178
|
+
* Look up a carrier by NAIC code, iecHash, raterspotId, or orgSlug.
|
|
179
|
+
* Returns carrier properties + managed programs.
|
|
180
|
+
*/
|
|
181
|
+
getCarrier(naic: string): Promise<{
|
|
182
|
+
carrier: CarrierProfile;
|
|
183
|
+
}>;
|
|
184
|
+
/**
|
|
185
|
+
* Look up a program by iecHash or raterspotId.
|
|
186
|
+
* Returns program properties + managing carrier or MGA.
|
|
187
|
+
*/
|
|
188
|
+
getProgram(iecHash: string): Promise<{
|
|
189
|
+
program: ProgramProfile;
|
|
190
|
+
}>;
|
|
191
|
+
/**
|
|
192
|
+
* Find programs whose appetite covers a given risk.
|
|
193
|
+
* Requires an accessToken (auth: required).
|
|
194
|
+
*
|
|
195
|
+
* @param input - Risk criteria: NAICS code, state, line of business, optional limits
|
|
196
|
+
*/
|
|
197
|
+
matchAppetite(input: AppetiteMatchInput): Promise<AppetiteMatchResult>;
|
|
198
|
+
private get;
|
|
199
|
+
private post;
|
|
200
|
+
private buildHeaders;
|
|
201
|
+
private handleResponse;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export { type AgencyProfile, type AgencyProgram, type AgencyStaffMember, type AgentEmployer, type AgentProfile, type AppetiteMatchInput, type AppetiteMatchProgram, type AppetiteMatchResult, type CarrierProfile, type CarrierProgram, GraphClient, type GraphClientConfig, type ProgramProfile };
|
package/dist/graph.d.ts
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
interface GraphClientConfig {
|
|
2
|
+
/** Base URL for bio-graph service. Defaults to BIO_GRAPH_URL env var or https://bio-graph.tawa.pro */
|
|
3
|
+
graphUrl?: string;
|
|
4
|
+
/** Bearer token for authenticated routes (appetite/match, same-as-queue, etc.) */
|
|
5
|
+
accessToken?: string;
|
|
6
|
+
/** Request timeout in ms. Default: 10_000 */
|
|
7
|
+
timeoutMs?: number;
|
|
8
|
+
}
|
|
9
|
+
interface AgentEmployer {
|
|
10
|
+
agencyName: string | null;
|
|
11
|
+
agencyIecHash: string | null;
|
|
12
|
+
agencyOrgSlug: string | null;
|
|
13
|
+
agencyRaterspotId: string | null;
|
|
14
|
+
current: boolean;
|
|
15
|
+
}
|
|
16
|
+
interface AgentProfile {
|
|
17
|
+
iecHash: string | null;
|
|
18
|
+
name: string | null;
|
|
19
|
+
npn: string | null;
|
|
20
|
+
bioId: string | null;
|
|
21
|
+
role: string | null;
|
|
22
|
+
email: string | null;
|
|
23
|
+
phone: string | null;
|
|
24
|
+
address: string | null;
|
|
25
|
+
city: string | null;
|
|
26
|
+
state: string | null;
|
|
27
|
+
zip: string | null;
|
|
28
|
+
licenseNo: string | null;
|
|
29
|
+
status: string | null;
|
|
30
|
+
linesOfAuthority: string[];
|
|
31
|
+
territories: string[];
|
|
32
|
+
linesOfBusiness: string[];
|
|
33
|
+
isPublic: boolean;
|
|
34
|
+
claimedAt: string | null;
|
|
35
|
+
employment: AgentEmployer[];
|
|
36
|
+
}
|
|
37
|
+
interface AgencyStaffMember {
|
|
38
|
+
name: string | null;
|
|
39
|
+
npn: string | null;
|
|
40
|
+
iecHash: string | null;
|
|
41
|
+
role: string | null;
|
|
42
|
+
email: string | null;
|
|
43
|
+
}
|
|
44
|
+
interface AgencyProgram {
|
|
45
|
+
name: string | null;
|
|
46
|
+
raterspotId: string | null;
|
|
47
|
+
iecHash: string | null;
|
|
48
|
+
states: string[];
|
|
49
|
+
carrierName: string | null;
|
|
50
|
+
isActive: boolean;
|
|
51
|
+
}
|
|
52
|
+
interface AgencyProfile {
|
|
53
|
+
iecHash: string | null;
|
|
54
|
+
raterspotId: string | null;
|
|
55
|
+
name: string | null;
|
|
56
|
+
orgSlug: string | null;
|
|
57
|
+
orgId: string | null;
|
|
58
|
+
type: string | null;
|
|
59
|
+
email: string | null;
|
|
60
|
+
phone: string | null;
|
|
61
|
+
website: string | null;
|
|
62
|
+
address: string | null;
|
|
63
|
+
city: string | null;
|
|
64
|
+
state: string | null;
|
|
65
|
+
zip: string | null;
|
|
66
|
+
dba: string | null;
|
|
67
|
+
licenseNo: string | null;
|
|
68
|
+
linesOfAuthority: string | null;
|
|
69
|
+
territories: string[];
|
|
70
|
+
linesOfBusiness: string[];
|
|
71
|
+
isPublic: boolean;
|
|
72
|
+
claimedAt: string | null;
|
|
73
|
+
staff: AgencyStaffMember[];
|
|
74
|
+
programs: AgencyProgram[];
|
|
75
|
+
}
|
|
76
|
+
interface CarrierProgram {
|
|
77
|
+
name: string | null;
|
|
78
|
+
iecHash: string | null;
|
|
79
|
+
raterspotId: string | null;
|
|
80
|
+
states: string[];
|
|
81
|
+
isActive: boolean;
|
|
82
|
+
}
|
|
83
|
+
interface CarrierProfile {
|
|
84
|
+
iecHash: string | null;
|
|
85
|
+
raterspotId: string | null;
|
|
86
|
+
name: string | null;
|
|
87
|
+
naic: string | null;
|
|
88
|
+
orgId: string | null;
|
|
89
|
+
orgSlug: string | null;
|
|
90
|
+
email: string | null;
|
|
91
|
+
phone: string | null;
|
|
92
|
+
website: string | null;
|
|
93
|
+
address: string | null;
|
|
94
|
+
city: string | null;
|
|
95
|
+
state: string | null;
|
|
96
|
+
isPublic: boolean;
|
|
97
|
+
claimedAt: string | null;
|
|
98
|
+
programs: CarrierProgram[];
|
|
99
|
+
}
|
|
100
|
+
interface ProgramProfile {
|
|
101
|
+
iecHash: string | null;
|
|
102
|
+
raterspotId: string | null;
|
|
103
|
+
name: string | null;
|
|
104
|
+
abrv: string | null;
|
|
105
|
+
states: string[];
|
|
106
|
+
isActive: boolean;
|
|
107
|
+
ratingEngine: string | null;
|
|
108
|
+
carrierName: string | null;
|
|
109
|
+
carrierNaic: string | null;
|
|
110
|
+
mgaName: string | null;
|
|
111
|
+
managerIecHash: string | null;
|
|
112
|
+
managerRaterspotId: string | null;
|
|
113
|
+
}
|
|
114
|
+
interface AppetiteMatchInput {
|
|
115
|
+
naicsCode: string;
|
|
116
|
+
state: string;
|
|
117
|
+
lineOfBusiness: string;
|
|
118
|
+
limits?: {
|
|
119
|
+
perOccurrence?: number;
|
|
120
|
+
aggregate?: number;
|
|
121
|
+
};
|
|
122
|
+
reason?: string;
|
|
123
|
+
}
|
|
124
|
+
interface AppetiteMatchProgram {
|
|
125
|
+
name: string | null;
|
|
126
|
+
iecHash: string | null;
|
|
127
|
+
raterspotId: string | null;
|
|
128
|
+
states: string[];
|
|
129
|
+
isActive: boolean;
|
|
130
|
+
carrierName: string | null;
|
|
131
|
+
carrierNaic: string | null;
|
|
132
|
+
mgaName: string | null;
|
|
133
|
+
ratingEngine: string | null;
|
|
134
|
+
}
|
|
135
|
+
interface AppetiteMatchResult {
|
|
136
|
+
programs: AppetiteMatchProgram[];
|
|
137
|
+
total: number;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Client for bio-graph InsureBio distribution graph endpoints.
|
|
141
|
+
*
|
|
142
|
+
* Public profile routes (agent, agency, carrier, program) require no auth.
|
|
143
|
+
* Authenticated routes (appetite match, same-as queue) require an accessToken.
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* import { GraphClient } from '@insureco/bio/graph'
|
|
147
|
+
*
|
|
148
|
+
* // Public profile lookups — no auth needed
|
|
149
|
+
* const graph = new GraphClient()
|
|
150
|
+
* const { agent } = await graph.getAgent('1234567')
|
|
151
|
+
*
|
|
152
|
+
* // Authenticated routes — pass a user or service token
|
|
153
|
+
* const graph = new GraphClient({ accessToken: req.headers.authorization?.slice(7) })
|
|
154
|
+
* const result = await graph.matchAppetite({ naicsCode: '2361', state: 'TX', lineOfBusiness: 'GL' })
|
|
155
|
+
*/
|
|
156
|
+
declare class GraphClient {
|
|
157
|
+
private readonly graphUrl;
|
|
158
|
+
private readonly accessToken;
|
|
159
|
+
private readonly timeoutMs;
|
|
160
|
+
constructor(config?: GraphClientConfig);
|
|
161
|
+
/**
|
|
162
|
+
* Create a GraphClient from environment variables.
|
|
163
|
+
* BIO_GRAPH_URL defaults to https://bio-graph.tawa.pro if not set.
|
|
164
|
+
*/
|
|
165
|
+
static fromEnv(overrides?: GraphClientConfig): GraphClient;
|
|
166
|
+
/** Look up an agent by NPN. Returns agent properties + employment chain. */
|
|
167
|
+
getAgent(npn: string): Promise<{
|
|
168
|
+
agent: AgentProfile;
|
|
169
|
+
}>;
|
|
170
|
+
/**
|
|
171
|
+
* Look up an agency by iecHash, raterspotId, or orgSlug.
|
|
172
|
+
* Returns agency properties + staff list + accessible programs.
|
|
173
|
+
*/
|
|
174
|
+
getAgency(iecHash: string): Promise<{
|
|
175
|
+
agency: AgencyProfile;
|
|
176
|
+
}>;
|
|
177
|
+
/**
|
|
178
|
+
* Look up a carrier by NAIC code, iecHash, raterspotId, or orgSlug.
|
|
179
|
+
* Returns carrier properties + managed programs.
|
|
180
|
+
*/
|
|
181
|
+
getCarrier(naic: string): Promise<{
|
|
182
|
+
carrier: CarrierProfile;
|
|
183
|
+
}>;
|
|
184
|
+
/**
|
|
185
|
+
* Look up a program by iecHash or raterspotId.
|
|
186
|
+
* Returns program properties + managing carrier or MGA.
|
|
187
|
+
*/
|
|
188
|
+
getProgram(iecHash: string): Promise<{
|
|
189
|
+
program: ProgramProfile;
|
|
190
|
+
}>;
|
|
191
|
+
/**
|
|
192
|
+
* Find programs whose appetite covers a given risk.
|
|
193
|
+
* Requires an accessToken (auth: required).
|
|
194
|
+
*
|
|
195
|
+
* @param input - Risk criteria: NAICS code, state, line of business, optional limits
|
|
196
|
+
*/
|
|
197
|
+
matchAppetite(input: AppetiteMatchInput): Promise<AppetiteMatchResult>;
|
|
198
|
+
private get;
|
|
199
|
+
private post;
|
|
200
|
+
private buildHeaders;
|
|
201
|
+
private handleResponse;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export { type AgencyProfile, type AgencyProgram, type AgencyStaffMember, type AgentEmployer, type AgentProfile, type AppetiteMatchInput, type AppetiteMatchProgram, type AppetiteMatchResult, type CarrierProfile, type CarrierProgram, GraphClient, type GraphClientConfig, type ProgramProfile };
|
package/dist/graph.js
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
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/graph.ts
|
|
21
|
+
var graph_exports = {};
|
|
22
|
+
__export(graph_exports, {
|
|
23
|
+
GraphClient: () => GraphClient
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(graph_exports);
|
|
26
|
+
|
|
27
|
+
// src/errors.ts
|
|
28
|
+
var BioError = class extends Error {
|
|
29
|
+
/** HTTP status code (if from an API response) */
|
|
30
|
+
statusCode;
|
|
31
|
+
/** Machine-readable error code (e.g. 'invalid_grant', 'token_expired') */
|
|
32
|
+
code;
|
|
33
|
+
/** Additional error details from the API */
|
|
34
|
+
details;
|
|
35
|
+
constructor(message, code, statusCode, details) {
|
|
36
|
+
super(message);
|
|
37
|
+
this.name = "BioError";
|
|
38
|
+
this.code = code;
|
|
39
|
+
this.statusCode = statusCode;
|
|
40
|
+
this.details = details;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// src/utils.ts
|
|
45
|
+
function retryDelay(attempt) {
|
|
46
|
+
const baseDelay = Math.min(1e3 * 2 ** attempt, 5e3);
|
|
47
|
+
return baseDelay * (0.5 + Math.random() * 0.5);
|
|
48
|
+
}
|
|
49
|
+
function sleep(ms) {
|
|
50
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
51
|
+
}
|
|
52
|
+
async function parseJsonResponse(response) {
|
|
53
|
+
try {
|
|
54
|
+
return await response.json();
|
|
55
|
+
} catch {
|
|
56
|
+
throw new BioError(
|
|
57
|
+
`Bio-ID returned ${response.status} with non-JSON body`,
|
|
58
|
+
"parse_error",
|
|
59
|
+
response.status
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// src/graph.ts
|
|
65
|
+
var DEFAULT_TIMEOUT_MS = 1e4;
|
|
66
|
+
var BIO_GRAPH_URL = "https://bio-graph.tawa.pro";
|
|
67
|
+
var GraphClient = class _GraphClient {
|
|
68
|
+
graphUrl;
|
|
69
|
+
accessToken;
|
|
70
|
+
timeoutMs;
|
|
71
|
+
constructor(config = {}) {
|
|
72
|
+
this.graphUrl = (config.graphUrl ?? process.env.BIO_GRAPH_URL ?? BIO_GRAPH_URL).replace(/\/$/, "");
|
|
73
|
+
this.accessToken = config.accessToken;
|
|
74
|
+
this.timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Create a GraphClient from environment variables.
|
|
78
|
+
* BIO_GRAPH_URL defaults to https://bio-graph.tawa.pro if not set.
|
|
79
|
+
*/
|
|
80
|
+
static fromEnv(overrides) {
|
|
81
|
+
return new _GraphClient({
|
|
82
|
+
graphUrl: overrides?.graphUrl ?? process.env.BIO_GRAPH_URL,
|
|
83
|
+
accessToken: overrides?.accessToken,
|
|
84
|
+
timeoutMs: overrides?.timeoutMs
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
// ─── Public Profile Routes ────────────────────────────────────────────────
|
|
88
|
+
/** Look up an agent by NPN. Returns agent properties + employment chain. */
|
|
89
|
+
async getAgent(npn) {
|
|
90
|
+
return this.get(`/api/graph/agent/${encodeURIComponent(npn)}`);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Look up an agency by iecHash, raterspotId, or orgSlug.
|
|
94
|
+
* Returns agency properties + staff list + accessible programs.
|
|
95
|
+
*/
|
|
96
|
+
async getAgency(iecHash) {
|
|
97
|
+
return this.get(`/api/graph/agency/${encodeURIComponent(iecHash)}`);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Look up a carrier by NAIC code, iecHash, raterspotId, or orgSlug.
|
|
101
|
+
* Returns carrier properties + managed programs.
|
|
102
|
+
*/
|
|
103
|
+
async getCarrier(naic) {
|
|
104
|
+
return this.get(`/api/graph/carrier/${encodeURIComponent(naic)}`);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Look up a program by iecHash or raterspotId.
|
|
108
|
+
* Returns program properties + managing carrier or MGA.
|
|
109
|
+
*/
|
|
110
|
+
async getProgram(iecHash) {
|
|
111
|
+
return this.get(`/api/graph/program/${encodeURIComponent(iecHash)}`);
|
|
112
|
+
}
|
|
113
|
+
// ─── Authenticated Routes ─────────────────────────────────────────────────
|
|
114
|
+
/**
|
|
115
|
+
* Find programs whose appetite covers a given risk.
|
|
116
|
+
* Requires an accessToken (auth: required).
|
|
117
|
+
*
|
|
118
|
+
* @param input - Risk criteria: NAICS code, state, line of business, optional limits
|
|
119
|
+
*/
|
|
120
|
+
async matchAppetite(input) {
|
|
121
|
+
return this.post("/api/graph/appetite/match", input, { requiresAuth: true });
|
|
122
|
+
}
|
|
123
|
+
// ─── Internal ─────────────────────────────────────────────────────────────
|
|
124
|
+
async get(path, attempt = 0) {
|
|
125
|
+
const url = `${this.graphUrl}${path}`;
|
|
126
|
+
const controller = new AbortController();
|
|
127
|
+
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
128
|
+
let response;
|
|
129
|
+
try {
|
|
130
|
+
response = await fetch(url, {
|
|
131
|
+
headers: this.buildHeaders(),
|
|
132
|
+
signal: controller.signal
|
|
133
|
+
});
|
|
134
|
+
} catch (err) {
|
|
135
|
+
clearTimeout(timer);
|
|
136
|
+
const isTimeout = err instanceof Error && err.name === "AbortError";
|
|
137
|
+
if (!isTimeout && attempt < 2) {
|
|
138
|
+
await sleep(retryDelay(attempt));
|
|
139
|
+
return this.get(path, attempt + 1);
|
|
140
|
+
}
|
|
141
|
+
throw new BioError(
|
|
142
|
+
isTimeout ? "bio-graph request timed out" : `bio-graph request failed: ${String(err)}`,
|
|
143
|
+
isTimeout ? "timeout" : "network_error"
|
|
144
|
+
);
|
|
145
|
+
} finally {
|
|
146
|
+
clearTimeout(timer);
|
|
147
|
+
}
|
|
148
|
+
return this.handleResponse(response, path);
|
|
149
|
+
}
|
|
150
|
+
async post(path, body, opts = {}, attempt = 0) {
|
|
151
|
+
if (opts.requiresAuth && !this.accessToken) {
|
|
152
|
+
throw new BioError(
|
|
153
|
+
`bio-graph ${path} requires an accessToken \u2014 pass it in the GraphClient constructor`,
|
|
154
|
+
"config_error"
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
const url = `${this.graphUrl}${path}`;
|
|
158
|
+
const controller = new AbortController();
|
|
159
|
+
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
160
|
+
let response;
|
|
161
|
+
try {
|
|
162
|
+
response = await fetch(url, {
|
|
163
|
+
method: "POST",
|
|
164
|
+
headers: { ...this.buildHeaders(), "Content-Type": "application/json" },
|
|
165
|
+
body: JSON.stringify(body),
|
|
166
|
+
signal: controller.signal
|
|
167
|
+
});
|
|
168
|
+
} catch (err) {
|
|
169
|
+
clearTimeout(timer);
|
|
170
|
+
const isTimeout = err instanceof Error && err.name === "AbortError";
|
|
171
|
+
if (!isTimeout && attempt < 2) {
|
|
172
|
+
await sleep(retryDelay(attempt));
|
|
173
|
+
return this.post(path, body, opts, attempt + 1);
|
|
174
|
+
}
|
|
175
|
+
throw new BioError(
|
|
176
|
+
isTimeout ? "bio-graph request timed out" : `bio-graph request failed: ${String(err)}`,
|
|
177
|
+
isTimeout ? "timeout" : "network_error"
|
|
178
|
+
);
|
|
179
|
+
} finally {
|
|
180
|
+
clearTimeout(timer);
|
|
181
|
+
}
|
|
182
|
+
return this.handleResponse(response, path);
|
|
183
|
+
}
|
|
184
|
+
buildHeaders() {
|
|
185
|
+
const headers = {};
|
|
186
|
+
if (this.accessToken) {
|
|
187
|
+
headers["Authorization"] = `Bearer ${this.accessToken}`;
|
|
188
|
+
}
|
|
189
|
+
return headers;
|
|
190
|
+
}
|
|
191
|
+
async handleResponse(response, path) {
|
|
192
|
+
if (response.status === 404) {
|
|
193
|
+
throw new BioError(`bio-graph entity not found: ${path}`, "not_found", 404);
|
|
194
|
+
}
|
|
195
|
+
if (response.status === 401) {
|
|
196
|
+
throw new BioError(
|
|
197
|
+
"bio-graph authentication failed \u2014 provide a valid accessToken",
|
|
198
|
+
"unauthorized",
|
|
199
|
+
401
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
if (response.status === 402) {
|
|
203
|
+
throw new BioError(
|
|
204
|
+
"bio-graph call failed \u2014 insufficient gas tokens. Top up at tawa.insureco.io/wallet",
|
|
205
|
+
"insufficient_gas",
|
|
206
|
+
402
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
if (!response.ok) {
|
|
210
|
+
const body2 = await parseJsonResponse(response).catch(() => ({}));
|
|
211
|
+
throw new BioError(
|
|
212
|
+
`bio-graph returned ${response.status} for ${path}`,
|
|
213
|
+
"api_error",
|
|
214
|
+
response.status,
|
|
215
|
+
body2
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
const body = await parseJsonResponse(response);
|
|
219
|
+
return body;
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
223
|
+
0 && (module.exports = {
|
|
224
|
+
GraphClient
|
|
225
|
+
});
|
package/dist/graph.mjs
ADDED
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { B as BioAuthConfig, A as AuthorizeOptions, a as AuthorizeResult, T as TokenResponse, b as BioUser, I as IntrospectResult, c as BioAdminConfig, U as UserFilters, d as UpdateUserData, e as BioDepartment, C as CreateDepartmentData, f as BioRole, g as CreateRoleData, h as BioOAuthClient, i as CreateClientData, j as BioTokenPayload, V as VerifyOptions, J as JWKSVerifyOptions } from './types-Dkb-drHZ.mjs';
|
|
2
2
|
export { k as AdminResponse, l as BioAddress, m as BioClientTokenPayload, n as BioMessaging, o as BioUsersConfig, O as OrgMember, p as OrgMemberFilters, q as OrgMembersResult } from './types-Dkb-drHZ.mjs';
|
|
3
|
+
export { AgencyProfile, AgencyProgram, AgencyStaffMember, AgentEmployer, AgentProfile, AppetiteMatchInput, AppetiteMatchProgram, AppetiteMatchResult, CarrierProfile, CarrierProgram, GraphClient, GraphClientConfig, ProgramProfile } from './graph.mjs';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* OAuth flow client for Bio-ID SSO.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { B as BioAuthConfig, A as AuthorizeOptions, a as AuthorizeResult, T as TokenResponse, b as BioUser, I as IntrospectResult, c as BioAdminConfig, U as UserFilters, d as UpdateUserData, e as BioDepartment, C as CreateDepartmentData, f as BioRole, g as CreateRoleData, h as BioOAuthClient, i as CreateClientData, j as BioTokenPayload, V as VerifyOptions, J as JWKSVerifyOptions } from './types-Dkb-drHZ.js';
|
|
2
2
|
export { k as AdminResponse, l as BioAddress, m as BioClientTokenPayload, n as BioMessaging, o as BioUsersConfig, O as OrgMember, p as OrgMemberFilters, q as OrgMembersResult } from './types-Dkb-drHZ.js';
|
|
3
|
+
export { AgencyProfile, AgencyProgram, AgencyStaffMember, AgentEmployer, AgentProfile, AppetiteMatchInput, AppetiteMatchProgram, AppetiteMatchResult, CarrierProfile, CarrierProgram, GraphClient, GraphClientConfig, ProgramProfile } from './graph.js';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* OAuth flow client for Bio-ID SSO.
|
package/dist/index.js
CHANGED
|
@@ -33,6 +33,7 @@ __export(index_exports, {
|
|
|
33
33
|
BioAdmin: () => BioAdmin,
|
|
34
34
|
BioAuth: () => BioAuth,
|
|
35
35
|
BioError: () => BioError,
|
|
36
|
+
GraphClient: () => GraphClient,
|
|
36
37
|
decodeToken: () => decodeToken,
|
|
37
38
|
generatePKCE: () => generatePKCE,
|
|
38
39
|
isTokenExpired: () => isTokenExpired,
|
|
@@ -737,11 +738,171 @@ async function verifyTokenJWKS(token, options) {
|
|
|
737
738
|
}
|
|
738
739
|
return payload;
|
|
739
740
|
}
|
|
741
|
+
|
|
742
|
+
// src/graph.ts
|
|
743
|
+
var DEFAULT_TIMEOUT_MS3 = 1e4;
|
|
744
|
+
var BIO_GRAPH_URL = "https://bio-graph.tawa.pro";
|
|
745
|
+
var GraphClient = class _GraphClient {
|
|
746
|
+
graphUrl;
|
|
747
|
+
accessToken;
|
|
748
|
+
timeoutMs;
|
|
749
|
+
constructor(config = {}) {
|
|
750
|
+
this.graphUrl = (config.graphUrl ?? process.env.BIO_GRAPH_URL ?? BIO_GRAPH_URL).replace(/\/$/, "");
|
|
751
|
+
this.accessToken = config.accessToken;
|
|
752
|
+
this.timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS3;
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* Create a GraphClient from environment variables.
|
|
756
|
+
* BIO_GRAPH_URL defaults to https://bio-graph.tawa.pro if not set.
|
|
757
|
+
*/
|
|
758
|
+
static fromEnv(overrides) {
|
|
759
|
+
return new _GraphClient({
|
|
760
|
+
graphUrl: overrides?.graphUrl ?? process.env.BIO_GRAPH_URL,
|
|
761
|
+
accessToken: overrides?.accessToken,
|
|
762
|
+
timeoutMs: overrides?.timeoutMs
|
|
763
|
+
});
|
|
764
|
+
}
|
|
765
|
+
// ─── Public Profile Routes ────────────────────────────────────────────────
|
|
766
|
+
/** Look up an agent by NPN. Returns agent properties + employment chain. */
|
|
767
|
+
async getAgent(npn) {
|
|
768
|
+
return this.get(`/api/graph/agent/${encodeURIComponent(npn)}`);
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* Look up an agency by iecHash, raterspotId, or orgSlug.
|
|
772
|
+
* Returns agency properties + staff list + accessible programs.
|
|
773
|
+
*/
|
|
774
|
+
async getAgency(iecHash) {
|
|
775
|
+
return this.get(`/api/graph/agency/${encodeURIComponent(iecHash)}`);
|
|
776
|
+
}
|
|
777
|
+
/**
|
|
778
|
+
* Look up a carrier by NAIC code, iecHash, raterspotId, or orgSlug.
|
|
779
|
+
* Returns carrier properties + managed programs.
|
|
780
|
+
*/
|
|
781
|
+
async getCarrier(naic) {
|
|
782
|
+
return this.get(`/api/graph/carrier/${encodeURIComponent(naic)}`);
|
|
783
|
+
}
|
|
784
|
+
/**
|
|
785
|
+
* Look up a program by iecHash or raterspotId.
|
|
786
|
+
* Returns program properties + managing carrier or MGA.
|
|
787
|
+
*/
|
|
788
|
+
async getProgram(iecHash) {
|
|
789
|
+
return this.get(`/api/graph/program/${encodeURIComponent(iecHash)}`);
|
|
790
|
+
}
|
|
791
|
+
// ─── Authenticated Routes ─────────────────────────────────────────────────
|
|
792
|
+
/**
|
|
793
|
+
* Find programs whose appetite covers a given risk.
|
|
794
|
+
* Requires an accessToken (auth: required).
|
|
795
|
+
*
|
|
796
|
+
* @param input - Risk criteria: NAICS code, state, line of business, optional limits
|
|
797
|
+
*/
|
|
798
|
+
async matchAppetite(input) {
|
|
799
|
+
return this.post("/api/graph/appetite/match", input, { requiresAuth: true });
|
|
800
|
+
}
|
|
801
|
+
// ─── Internal ─────────────────────────────────────────────────────────────
|
|
802
|
+
async get(path, attempt = 0) {
|
|
803
|
+
const url = `${this.graphUrl}${path}`;
|
|
804
|
+
const controller = new AbortController();
|
|
805
|
+
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
806
|
+
let response;
|
|
807
|
+
try {
|
|
808
|
+
response = await fetch(url, {
|
|
809
|
+
headers: this.buildHeaders(),
|
|
810
|
+
signal: controller.signal
|
|
811
|
+
});
|
|
812
|
+
} catch (err) {
|
|
813
|
+
clearTimeout(timer);
|
|
814
|
+
const isTimeout = err instanceof Error && err.name === "AbortError";
|
|
815
|
+
if (!isTimeout && attempt < 2) {
|
|
816
|
+
await sleep(retryDelay(attempt));
|
|
817
|
+
return this.get(path, attempt + 1);
|
|
818
|
+
}
|
|
819
|
+
throw new BioError(
|
|
820
|
+
isTimeout ? "bio-graph request timed out" : `bio-graph request failed: ${String(err)}`,
|
|
821
|
+
isTimeout ? "timeout" : "network_error"
|
|
822
|
+
);
|
|
823
|
+
} finally {
|
|
824
|
+
clearTimeout(timer);
|
|
825
|
+
}
|
|
826
|
+
return this.handleResponse(response, path);
|
|
827
|
+
}
|
|
828
|
+
async post(path, body, opts = {}, attempt = 0) {
|
|
829
|
+
if (opts.requiresAuth && !this.accessToken) {
|
|
830
|
+
throw new BioError(
|
|
831
|
+
`bio-graph ${path} requires an accessToken \u2014 pass it in the GraphClient constructor`,
|
|
832
|
+
"config_error"
|
|
833
|
+
);
|
|
834
|
+
}
|
|
835
|
+
const url = `${this.graphUrl}${path}`;
|
|
836
|
+
const controller = new AbortController();
|
|
837
|
+
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
838
|
+
let response;
|
|
839
|
+
try {
|
|
840
|
+
response = await fetch(url, {
|
|
841
|
+
method: "POST",
|
|
842
|
+
headers: { ...this.buildHeaders(), "Content-Type": "application/json" },
|
|
843
|
+
body: JSON.stringify(body),
|
|
844
|
+
signal: controller.signal
|
|
845
|
+
});
|
|
846
|
+
} catch (err) {
|
|
847
|
+
clearTimeout(timer);
|
|
848
|
+
const isTimeout = err instanceof Error && err.name === "AbortError";
|
|
849
|
+
if (!isTimeout && attempt < 2) {
|
|
850
|
+
await sleep(retryDelay(attempt));
|
|
851
|
+
return this.post(path, body, opts, attempt + 1);
|
|
852
|
+
}
|
|
853
|
+
throw new BioError(
|
|
854
|
+
isTimeout ? "bio-graph request timed out" : `bio-graph request failed: ${String(err)}`,
|
|
855
|
+
isTimeout ? "timeout" : "network_error"
|
|
856
|
+
);
|
|
857
|
+
} finally {
|
|
858
|
+
clearTimeout(timer);
|
|
859
|
+
}
|
|
860
|
+
return this.handleResponse(response, path);
|
|
861
|
+
}
|
|
862
|
+
buildHeaders() {
|
|
863
|
+
const headers = {};
|
|
864
|
+
if (this.accessToken) {
|
|
865
|
+
headers["Authorization"] = `Bearer ${this.accessToken}`;
|
|
866
|
+
}
|
|
867
|
+
return headers;
|
|
868
|
+
}
|
|
869
|
+
async handleResponse(response, path) {
|
|
870
|
+
if (response.status === 404) {
|
|
871
|
+
throw new BioError(`bio-graph entity not found: ${path}`, "not_found", 404);
|
|
872
|
+
}
|
|
873
|
+
if (response.status === 401) {
|
|
874
|
+
throw new BioError(
|
|
875
|
+
"bio-graph authentication failed \u2014 provide a valid accessToken",
|
|
876
|
+
"unauthorized",
|
|
877
|
+
401
|
|
878
|
+
);
|
|
879
|
+
}
|
|
880
|
+
if (response.status === 402) {
|
|
881
|
+
throw new BioError(
|
|
882
|
+
"bio-graph call failed \u2014 insufficient gas tokens. Top up at tawa.insureco.io/wallet",
|
|
883
|
+
"insufficient_gas",
|
|
884
|
+
402
|
|
885
|
+
);
|
|
886
|
+
}
|
|
887
|
+
if (!response.ok) {
|
|
888
|
+
const body2 = await parseJsonResponse(response).catch(() => ({}));
|
|
889
|
+
throw new BioError(
|
|
890
|
+
`bio-graph returned ${response.status} for ${path}`,
|
|
891
|
+
"api_error",
|
|
892
|
+
response.status,
|
|
893
|
+
body2
|
|
894
|
+
);
|
|
895
|
+
}
|
|
896
|
+
const body = await parseJsonResponse(response);
|
|
897
|
+
return body;
|
|
898
|
+
}
|
|
899
|
+
};
|
|
740
900
|
// Annotate the CommonJS export names for ESM import in node:
|
|
741
901
|
0 && (module.exports = {
|
|
742
902
|
BioAdmin,
|
|
743
903
|
BioAuth,
|
|
744
904
|
BioError,
|
|
905
|
+
GraphClient,
|
|
745
906
|
decodeToken,
|
|
746
907
|
generatePKCE,
|
|
747
908
|
isTokenExpired,
|
package/dist/index.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@insureco/bio",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "SDK for Bio-ID SSO integration on the Tawa platform",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -15,11 +15,23 @@
|
|
|
15
15
|
"types": "./dist/users.d.ts",
|
|
16
16
|
"import": "./dist/users.mjs",
|
|
17
17
|
"require": "./dist/users.js"
|
|
18
|
+
},
|
|
19
|
+
"./graph": {
|
|
20
|
+
"types": "./dist/graph.d.ts",
|
|
21
|
+
"import": "./dist/graph.mjs",
|
|
22
|
+
"require": "./dist/graph.js"
|
|
18
23
|
}
|
|
19
24
|
},
|
|
20
25
|
"files": [
|
|
21
26
|
"dist"
|
|
22
27
|
],
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "tsup src/index.ts src/users.ts src/graph.ts --format cjs,esm --dts --clean",
|
|
30
|
+
"test": "vitest run",
|
|
31
|
+
"test:watch": "vitest",
|
|
32
|
+
"lint": "tsc --noEmit",
|
|
33
|
+
"prepublishOnly": "npm run build"
|
|
34
|
+
},
|
|
23
35
|
"keywords": [
|
|
24
36
|
"insureco",
|
|
25
37
|
"tawa",
|
|
@@ -42,11 +54,5 @@
|
|
|
42
54
|
},
|
|
43
55
|
"engines": {
|
|
44
56
|
"node": ">=18.0.0"
|
|
45
|
-
},
|
|
46
|
-
"scripts": {
|
|
47
|
-
"build": "tsup src/index.ts src/users.ts --format cjs,esm --dts --clean",
|
|
48
|
-
"test": "vitest run",
|
|
49
|
-
"test:watch": "vitest",
|
|
50
|
-
"lint": "tsc --noEmit"
|
|
51
57
|
}
|
|
52
|
-
}
|
|
58
|
+
}
|