@insureco/relay 0.3.1 → 0.4.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/index.d.mts +24 -11
- package/dist/index.d.ts +24 -11
- package/dist/index.js +66 -16
- package/dist/index.mjs +66 -16
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -73,19 +73,29 @@ interface ApiResponse<T> {
|
|
|
73
73
|
}
|
|
74
74
|
/** Configuration for the RelayClient */
|
|
75
75
|
interface RelayClientConfig {
|
|
76
|
-
/**
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
/**
|
|
77
|
+
* Async function returning a Bearer token (e.g. Bio-ID client_credentials).
|
|
78
|
+
* This is the recommended auth method — works with both gateway (Janus) and direct modes.
|
|
79
|
+
* In gateway mode, the builder auto-provisions BIO_CLIENT_ID + BIO_CLIENT_SECRET.
|
|
80
|
+
*/
|
|
81
|
+
accessTokenFn?: () => Promise<string>;
|
|
80
82
|
/** Janus gateway URL (default: http://janus.janus-prod.svc.cluster.local:3000) */
|
|
81
83
|
janusUrl?: string;
|
|
82
|
-
/** Direct relay URL for local dev (bypasses Janus
|
|
84
|
+
/** Direct relay URL for local dev (bypasses Janus) */
|
|
83
85
|
relayUrl?: string;
|
|
84
|
-
/** Internal API key for direct relay access */
|
|
86
|
+
/** Internal API key for direct relay access (local dev only) */
|
|
85
87
|
internalKey?: string;
|
|
86
|
-
/**
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
/**
|
|
89
|
+
* @deprecated Use accessTokenFn with Bio-ID client_credentials instead.
|
|
90
|
+
* Shared JWT secret for minting service tokens.
|
|
91
|
+
*/
|
|
92
|
+
jwtSecret?: string;
|
|
93
|
+
/**
|
|
94
|
+
* @deprecated Use accessTokenFn with Bio-ID client_credentials instead.
|
|
95
|
+
* Program/org ID included in the JWT.
|
|
96
|
+
*/
|
|
97
|
+
programId?: string;
|
|
98
|
+
/** JWT token lifetime in seconds (default: 300). Only used with legacy jwtSecret auth. */
|
|
89
99
|
tokenTtlSeconds?: number;
|
|
90
100
|
/**
|
|
91
101
|
* Number of retry attempts on transient failures (default: 2).
|
|
@@ -96,7 +106,7 @@ interface RelayClientConfig {
|
|
|
96
106
|
retries?: number;
|
|
97
107
|
/** Request timeout in milliseconds (default: 10000) */
|
|
98
108
|
timeoutMs?: number;
|
|
99
|
-
/** Source service name for metadata (default: programId) */
|
|
109
|
+
/** Source service name for metadata (default: programId or 'unknown') */
|
|
100
110
|
sourceService?: string;
|
|
101
111
|
}
|
|
102
112
|
/** Base options shared by sendEmail and sendSMS */
|
|
@@ -134,7 +144,10 @@ declare class RelayClient {
|
|
|
134
144
|
/**
|
|
135
145
|
* Create a RelayClient from environment variables.
|
|
136
146
|
*
|
|
137
|
-
*
|
|
147
|
+
* Priority:
|
|
148
|
+
* 1. RELAY_DIRECT_URL — local dev (direct to relay, optional RELAY_INTERNAL_KEY)
|
|
149
|
+
* 2. BIO_CLIENT_ID + BIO_CLIENT_SECRET — production gateway (Bio-ID token through Janus)
|
|
150
|
+
* 3. JWT_SECRET + PROGRAM_ID — legacy gateway (self-signed JWT through Janus)
|
|
138
151
|
*/
|
|
139
152
|
static fromEnv(): RelayClient;
|
|
140
153
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -73,19 +73,29 @@ interface ApiResponse<T> {
|
|
|
73
73
|
}
|
|
74
74
|
/** Configuration for the RelayClient */
|
|
75
75
|
interface RelayClientConfig {
|
|
76
|
-
/**
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
/**
|
|
77
|
+
* Async function returning a Bearer token (e.g. Bio-ID client_credentials).
|
|
78
|
+
* This is the recommended auth method — works with both gateway (Janus) and direct modes.
|
|
79
|
+
* In gateway mode, the builder auto-provisions BIO_CLIENT_ID + BIO_CLIENT_SECRET.
|
|
80
|
+
*/
|
|
81
|
+
accessTokenFn?: () => Promise<string>;
|
|
80
82
|
/** Janus gateway URL (default: http://janus.janus-prod.svc.cluster.local:3000) */
|
|
81
83
|
janusUrl?: string;
|
|
82
|
-
/** Direct relay URL for local dev (bypasses Janus
|
|
84
|
+
/** Direct relay URL for local dev (bypasses Janus) */
|
|
83
85
|
relayUrl?: string;
|
|
84
|
-
/** Internal API key for direct relay access */
|
|
86
|
+
/** Internal API key for direct relay access (local dev only) */
|
|
85
87
|
internalKey?: string;
|
|
86
|
-
/**
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
/**
|
|
89
|
+
* @deprecated Use accessTokenFn with Bio-ID client_credentials instead.
|
|
90
|
+
* Shared JWT secret for minting service tokens.
|
|
91
|
+
*/
|
|
92
|
+
jwtSecret?: string;
|
|
93
|
+
/**
|
|
94
|
+
* @deprecated Use accessTokenFn with Bio-ID client_credentials instead.
|
|
95
|
+
* Program/org ID included in the JWT.
|
|
96
|
+
*/
|
|
97
|
+
programId?: string;
|
|
98
|
+
/** JWT token lifetime in seconds (default: 300). Only used with legacy jwtSecret auth. */
|
|
89
99
|
tokenTtlSeconds?: number;
|
|
90
100
|
/**
|
|
91
101
|
* Number of retry attempts on transient failures (default: 2).
|
|
@@ -96,7 +106,7 @@ interface RelayClientConfig {
|
|
|
96
106
|
retries?: number;
|
|
97
107
|
/** Request timeout in milliseconds (default: 10000) */
|
|
98
108
|
timeoutMs?: number;
|
|
99
|
-
/** Source service name for metadata (default: programId) */
|
|
109
|
+
/** Source service name for metadata (default: programId or 'unknown') */
|
|
100
110
|
sourceService?: string;
|
|
101
111
|
}
|
|
102
112
|
/** Base options shared by sendEmail and sendSMS */
|
|
@@ -134,7 +144,10 @@ declare class RelayClient {
|
|
|
134
144
|
/**
|
|
135
145
|
* Create a RelayClient from environment variables.
|
|
136
146
|
*
|
|
137
|
-
*
|
|
147
|
+
* Priority:
|
|
148
|
+
* 1. RELAY_DIRECT_URL — local dev (direct to relay, optional RELAY_INTERNAL_KEY)
|
|
149
|
+
* 2. BIO_CLIENT_ID + BIO_CLIENT_SECRET — production gateway (Bio-ID token through Janus)
|
|
150
|
+
* 3. JWT_SECRET + PROGRAM_ID — legacy gateway (self-signed JWT through Janus)
|
|
138
151
|
*/
|
|
139
152
|
static fromEnv(): RelayClient;
|
|
140
153
|
/**
|
package/dist/index.js
CHANGED
|
@@ -66,6 +66,7 @@ function isTokenExpired(token, bufferSeconds = 30) {
|
|
|
66
66
|
var DEFAULT_JANUS_URL = "http://janus.janus-prod.svc.cluster.local:3000";
|
|
67
67
|
var RELAY_API_PATH = "/api/relay";
|
|
68
68
|
var DEFAULT_TIMEOUT_MS = 1e4;
|
|
69
|
+
var DEFAULT_BIO_ID_URL = "https://bio.tawa.insureco.io";
|
|
69
70
|
var RelayError = class extends Error {
|
|
70
71
|
constructor(message, statusCode, code, details) {
|
|
71
72
|
super(message);
|
|
@@ -79,12 +80,15 @@ var RelayClient = class _RelayClient {
|
|
|
79
80
|
config;
|
|
80
81
|
cachedToken = null;
|
|
81
82
|
constructor(config) {
|
|
82
|
-
|
|
83
|
+
const hasAccessTokenFn = typeof config.accessTokenFn === "function";
|
|
84
|
+
const hasJwtSecret = !!config.jwtSecret;
|
|
85
|
+
const hasRelayUrl = !!config.relayUrl;
|
|
86
|
+
if (!hasAccessTokenFn && !hasJwtSecret && !hasRelayUrl) {
|
|
83
87
|
throw new Error(
|
|
84
|
-
"iec-relay:
|
|
88
|
+
"iec-relay: Provide accessTokenFn (recommended), jwtSecret (legacy), or relayUrl (local dev)"
|
|
85
89
|
);
|
|
86
90
|
}
|
|
87
|
-
if (
|
|
91
|
+
if (hasJwtSecret && !config.programId) {
|
|
88
92
|
throw new Error("iec-relay: programId is required when using jwtSecret");
|
|
89
93
|
}
|
|
90
94
|
this.config = {
|
|
@@ -98,29 +102,71 @@ var RelayClient = class _RelayClient {
|
|
|
98
102
|
/**
|
|
99
103
|
* Create a RelayClient from environment variables.
|
|
100
104
|
*
|
|
101
|
-
*
|
|
105
|
+
* Priority:
|
|
106
|
+
* 1. RELAY_DIRECT_URL — local dev (direct to relay, optional RELAY_INTERNAL_KEY)
|
|
107
|
+
* 2. BIO_CLIENT_ID + BIO_CLIENT_SECRET — production gateway (Bio-ID token through Janus)
|
|
108
|
+
* 3. JWT_SECRET + PROGRAM_ID — legacy gateway (self-signed JWT through Janus)
|
|
102
109
|
*/
|
|
103
110
|
static fromEnv() {
|
|
104
111
|
const relayUrl = process.env.RELAY_DIRECT_URL;
|
|
105
|
-
const internalKey = process.env.RELAY_INTERNAL_KEY;
|
|
106
112
|
if (relayUrl) {
|
|
107
113
|
return new _RelayClient({
|
|
108
114
|
relayUrl,
|
|
109
|
-
internalKey,
|
|
115
|
+
internalKey: process.env.RELAY_INTERNAL_KEY,
|
|
110
116
|
sourceService: process.env.PROGRAM_ID ?? process.env.SERVICE_NAME
|
|
111
117
|
});
|
|
112
118
|
}
|
|
119
|
+
const bioClientId = process.env.BIO_CLIENT_ID;
|
|
120
|
+
const bioClientSecret = process.env.BIO_CLIENT_SECRET;
|
|
121
|
+
if (bioClientId && bioClientSecret) {
|
|
122
|
+
const bioIdUrl = process.env.BIO_ID_URL || DEFAULT_BIO_ID_URL;
|
|
123
|
+
let cachedBioToken = null;
|
|
124
|
+
let bioTokenExpiresAt = 0;
|
|
125
|
+
const accessTokenFn = async () => {
|
|
126
|
+
const now = Date.now();
|
|
127
|
+
if (cachedBioToken && now < bioTokenExpiresAt) {
|
|
128
|
+
return cachedBioToken;
|
|
129
|
+
}
|
|
130
|
+
const response = await fetch(`${bioIdUrl}/api/oauth/token`, {
|
|
131
|
+
method: "POST",
|
|
132
|
+
headers: { "Content-Type": "application/json" },
|
|
133
|
+
body: JSON.stringify({
|
|
134
|
+
grant_type: "client_credentials",
|
|
135
|
+
client_id: bioClientId,
|
|
136
|
+
client_secret: bioClientSecret
|
|
137
|
+
})
|
|
138
|
+
});
|
|
139
|
+
if (!response.ok) {
|
|
140
|
+
const body = await response.text();
|
|
141
|
+
throw new RelayError(
|
|
142
|
+
`Bio-ID token request failed (${response.status}): ${body}`,
|
|
143
|
+
response.status,
|
|
144
|
+
"AUTH_ERROR"
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
const data = await response.json();
|
|
148
|
+
cachedBioToken = data.access_token;
|
|
149
|
+
const expiresIn = (data.expires_in || 900) * 1e3;
|
|
150
|
+
bioTokenExpiresAt = now + expiresIn - 3e4;
|
|
151
|
+
return cachedBioToken;
|
|
152
|
+
};
|
|
153
|
+
return new _RelayClient({
|
|
154
|
+
accessTokenFn,
|
|
155
|
+
janusUrl: process.env.JANUS_URL,
|
|
156
|
+
sourceService: process.env.SERVICE_NAME ?? process.env.PROGRAM_ID
|
|
157
|
+
});
|
|
158
|
+
}
|
|
113
159
|
const jwtSecret = process.env.JWT_SECRET;
|
|
114
|
-
if (
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
160
|
+
if (jwtSecret) {
|
|
161
|
+
return new _RelayClient({
|
|
162
|
+
jwtSecret,
|
|
163
|
+
programId: process.env.PROGRAM_ID,
|
|
164
|
+
janusUrl: process.env.JANUS_URL
|
|
165
|
+
});
|
|
118
166
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
janusUrl: process.env.JANUS_URL
|
|
123
|
-
});
|
|
167
|
+
throw new Error(
|
|
168
|
+
"iec-relay: No auth configured. Set BIO_CLIENT_ID + BIO_CLIENT_SECRET (recommended), JWT_SECRET + PROGRAM_ID (legacy), or RELAY_DIRECT_URL (local dev)"
|
|
169
|
+
);
|
|
124
170
|
}
|
|
125
171
|
/**
|
|
126
172
|
* Send an email through InsureRelay.
|
|
@@ -323,6 +369,10 @@ var RelayClient = class _RelayClient {
|
|
|
323
369
|
}
|
|
324
370
|
const baseUrl = this.config.janusUrl ?? DEFAULT_JANUS_URL;
|
|
325
371
|
const url = `${baseUrl}${RELAY_API_PATH}${path}`;
|
|
372
|
+
if (this.config.accessTokenFn) {
|
|
373
|
+
headers["Authorization"] = `Bearer ${await this.config.accessTokenFn()}`;
|
|
374
|
+
return { url, headers };
|
|
375
|
+
}
|
|
326
376
|
headers["Authorization"] = `Bearer ${this.getToken()}`;
|
|
327
377
|
return { url, headers };
|
|
328
378
|
}
|
|
@@ -332,7 +382,7 @@ var RelayClient = class _RelayClient {
|
|
|
332
382
|
}
|
|
333
383
|
if (!this.config.jwtSecret || !this.config.programId) {
|
|
334
384
|
throw new RelayError(
|
|
335
|
-
"jwtSecret and programId are required for Janus auth",
|
|
385
|
+
"jwtSecret and programId are required for legacy Janus auth",
|
|
336
386
|
500,
|
|
337
387
|
"CONFIG_ERROR"
|
|
338
388
|
);
|
package/dist/index.mjs
CHANGED
|
@@ -37,6 +37,7 @@ function isTokenExpired(token, bufferSeconds = 30) {
|
|
|
37
37
|
var DEFAULT_JANUS_URL = "http://janus.janus-prod.svc.cluster.local:3000";
|
|
38
38
|
var RELAY_API_PATH = "/api/relay";
|
|
39
39
|
var DEFAULT_TIMEOUT_MS = 1e4;
|
|
40
|
+
var DEFAULT_BIO_ID_URL = "https://bio.tawa.insureco.io";
|
|
40
41
|
var RelayError = class extends Error {
|
|
41
42
|
constructor(message, statusCode, code, details) {
|
|
42
43
|
super(message);
|
|
@@ -50,12 +51,15 @@ var RelayClient = class _RelayClient {
|
|
|
50
51
|
config;
|
|
51
52
|
cachedToken = null;
|
|
52
53
|
constructor(config) {
|
|
53
|
-
|
|
54
|
+
const hasAccessTokenFn = typeof config.accessTokenFn === "function";
|
|
55
|
+
const hasJwtSecret = !!config.jwtSecret;
|
|
56
|
+
const hasRelayUrl = !!config.relayUrl;
|
|
57
|
+
if (!hasAccessTokenFn && !hasJwtSecret && !hasRelayUrl) {
|
|
54
58
|
throw new Error(
|
|
55
|
-
"iec-relay:
|
|
59
|
+
"iec-relay: Provide accessTokenFn (recommended), jwtSecret (legacy), or relayUrl (local dev)"
|
|
56
60
|
);
|
|
57
61
|
}
|
|
58
|
-
if (
|
|
62
|
+
if (hasJwtSecret && !config.programId) {
|
|
59
63
|
throw new Error("iec-relay: programId is required when using jwtSecret");
|
|
60
64
|
}
|
|
61
65
|
this.config = {
|
|
@@ -69,29 +73,71 @@ var RelayClient = class _RelayClient {
|
|
|
69
73
|
/**
|
|
70
74
|
* Create a RelayClient from environment variables.
|
|
71
75
|
*
|
|
72
|
-
*
|
|
76
|
+
* Priority:
|
|
77
|
+
* 1. RELAY_DIRECT_URL — local dev (direct to relay, optional RELAY_INTERNAL_KEY)
|
|
78
|
+
* 2. BIO_CLIENT_ID + BIO_CLIENT_SECRET — production gateway (Bio-ID token through Janus)
|
|
79
|
+
* 3. JWT_SECRET + PROGRAM_ID — legacy gateway (self-signed JWT through Janus)
|
|
73
80
|
*/
|
|
74
81
|
static fromEnv() {
|
|
75
82
|
const relayUrl = process.env.RELAY_DIRECT_URL;
|
|
76
|
-
const internalKey = process.env.RELAY_INTERNAL_KEY;
|
|
77
83
|
if (relayUrl) {
|
|
78
84
|
return new _RelayClient({
|
|
79
85
|
relayUrl,
|
|
80
|
-
internalKey,
|
|
86
|
+
internalKey: process.env.RELAY_INTERNAL_KEY,
|
|
81
87
|
sourceService: process.env.PROGRAM_ID ?? process.env.SERVICE_NAME
|
|
82
88
|
});
|
|
83
89
|
}
|
|
90
|
+
const bioClientId = process.env.BIO_CLIENT_ID;
|
|
91
|
+
const bioClientSecret = process.env.BIO_CLIENT_SECRET;
|
|
92
|
+
if (bioClientId && bioClientSecret) {
|
|
93
|
+
const bioIdUrl = process.env.BIO_ID_URL || DEFAULT_BIO_ID_URL;
|
|
94
|
+
let cachedBioToken = null;
|
|
95
|
+
let bioTokenExpiresAt = 0;
|
|
96
|
+
const accessTokenFn = async () => {
|
|
97
|
+
const now = Date.now();
|
|
98
|
+
if (cachedBioToken && now < bioTokenExpiresAt) {
|
|
99
|
+
return cachedBioToken;
|
|
100
|
+
}
|
|
101
|
+
const response = await fetch(`${bioIdUrl}/api/oauth/token`, {
|
|
102
|
+
method: "POST",
|
|
103
|
+
headers: { "Content-Type": "application/json" },
|
|
104
|
+
body: JSON.stringify({
|
|
105
|
+
grant_type: "client_credentials",
|
|
106
|
+
client_id: bioClientId,
|
|
107
|
+
client_secret: bioClientSecret
|
|
108
|
+
})
|
|
109
|
+
});
|
|
110
|
+
if (!response.ok) {
|
|
111
|
+
const body = await response.text();
|
|
112
|
+
throw new RelayError(
|
|
113
|
+
`Bio-ID token request failed (${response.status}): ${body}`,
|
|
114
|
+
response.status,
|
|
115
|
+
"AUTH_ERROR"
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
const data = await response.json();
|
|
119
|
+
cachedBioToken = data.access_token;
|
|
120
|
+
const expiresIn = (data.expires_in || 900) * 1e3;
|
|
121
|
+
bioTokenExpiresAt = now + expiresIn - 3e4;
|
|
122
|
+
return cachedBioToken;
|
|
123
|
+
};
|
|
124
|
+
return new _RelayClient({
|
|
125
|
+
accessTokenFn,
|
|
126
|
+
janusUrl: process.env.JANUS_URL,
|
|
127
|
+
sourceService: process.env.SERVICE_NAME ?? process.env.PROGRAM_ID
|
|
128
|
+
});
|
|
129
|
+
}
|
|
84
130
|
const jwtSecret = process.env.JWT_SECRET;
|
|
85
|
-
if (
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
131
|
+
if (jwtSecret) {
|
|
132
|
+
return new _RelayClient({
|
|
133
|
+
jwtSecret,
|
|
134
|
+
programId: process.env.PROGRAM_ID,
|
|
135
|
+
janusUrl: process.env.JANUS_URL
|
|
136
|
+
});
|
|
89
137
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
janusUrl: process.env.JANUS_URL
|
|
94
|
-
});
|
|
138
|
+
throw new Error(
|
|
139
|
+
"iec-relay: No auth configured. Set BIO_CLIENT_ID + BIO_CLIENT_SECRET (recommended), JWT_SECRET + PROGRAM_ID (legacy), or RELAY_DIRECT_URL (local dev)"
|
|
140
|
+
);
|
|
95
141
|
}
|
|
96
142
|
/**
|
|
97
143
|
* Send an email through InsureRelay.
|
|
@@ -294,6 +340,10 @@ var RelayClient = class _RelayClient {
|
|
|
294
340
|
}
|
|
295
341
|
const baseUrl = this.config.janusUrl ?? DEFAULT_JANUS_URL;
|
|
296
342
|
const url = `${baseUrl}${RELAY_API_PATH}${path}`;
|
|
343
|
+
if (this.config.accessTokenFn) {
|
|
344
|
+
headers["Authorization"] = `Bearer ${await this.config.accessTokenFn()}`;
|
|
345
|
+
return { url, headers };
|
|
346
|
+
}
|
|
297
347
|
headers["Authorization"] = `Bearer ${this.getToken()}`;
|
|
298
348
|
return { url, headers };
|
|
299
349
|
}
|
|
@@ -303,7 +353,7 @@ var RelayClient = class _RelayClient {
|
|
|
303
353
|
}
|
|
304
354
|
if (!this.config.jwtSecret || !this.config.programId) {
|
|
305
355
|
throw new RelayError(
|
|
306
|
-
"jwtSecret and programId are required for Janus auth",
|
|
356
|
+
"jwtSecret and programId are required for legacy Janus auth",
|
|
307
357
|
500,
|
|
308
358
|
"CONFIG_ERROR"
|
|
309
359
|
);
|