@kedaruma/revlm-client 1.0.11 → 1.0.14
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 +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +52 -3
- package/dist/index.mjs +52 -3
- package/package.json +4 -2
package/dist/index.d.mts
CHANGED
|
@@ -174,6 +174,11 @@ type RevlmOptions = {
|
|
|
174
174
|
provisionalAuthDomain?: string;
|
|
175
175
|
autoSetToken?: boolean;
|
|
176
176
|
autoRefreshOn401?: boolean;
|
|
177
|
+
sigv4SecretKey?: string;
|
|
178
|
+
sigv4AccessKey?: string;
|
|
179
|
+
sigv4Region?: string;
|
|
180
|
+
sigv4Service?: string;
|
|
181
|
+
sigv4Enabled?: boolean;
|
|
177
182
|
};
|
|
178
183
|
type RevlmResponse<T = any> = {
|
|
179
184
|
ok: boolean;
|
|
@@ -193,6 +198,7 @@ declare class Revlm {
|
|
|
193
198
|
private provisionalAuthDomain;
|
|
194
199
|
private autoSetToken;
|
|
195
200
|
private autoRefreshOn401;
|
|
201
|
+
private sigv4Signer;
|
|
196
202
|
constructor(baseUrl: string, opts?: RevlmOptions);
|
|
197
203
|
setToken(token: string): void;
|
|
198
204
|
getToken(): string | undefined;
|
|
@@ -204,6 +210,7 @@ declare class Revlm {
|
|
|
204
210
|
private parseResponse;
|
|
205
211
|
private request;
|
|
206
212
|
private shouldSkipAuthRetry;
|
|
213
|
+
private signIfNeeded;
|
|
207
214
|
private requestWithRetry;
|
|
208
215
|
login(authId: string, password: string): Promise<LoginResponse>;
|
|
209
216
|
provisionalLogin(authId: string): Promise<ProvisionalLoginResponse>;
|
package/dist/index.d.ts
CHANGED
|
@@ -174,6 +174,11 @@ type RevlmOptions = {
|
|
|
174
174
|
provisionalAuthDomain?: string;
|
|
175
175
|
autoSetToken?: boolean;
|
|
176
176
|
autoRefreshOn401?: boolean;
|
|
177
|
+
sigv4SecretKey?: string;
|
|
178
|
+
sigv4AccessKey?: string;
|
|
179
|
+
sigv4Region?: string;
|
|
180
|
+
sigv4Service?: string;
|
|
181
|
+
sigv4Enabled?: boolean;
|
|
177
182
|
};
|
|
178
183
|
type RevlmResponse<T = any> = {
|
|
179
184
|
ok: boolean;
|
|
@@ -193,6 +198,7 @@ declare class Revlm {
|
|
|
193
198
|
private provisionalAuthDomain;
|
|
194
199
|
private autoSetToken;
|
|
195
200
|
private autoRefreshOn401;
|
|
201
|
+
private sigv4Signer;
|
|
196
202
|
constructor(baseUrl: string, opts?: RevlmOptions);
|
|
197
203
|
setToken(token: string): void;
|
|
198
204
|
getToken(): string | undefined;
|
|
@@ -204,6 +210,7 @@ declare class Revlm {
|
|
|
204
210
|
private parseResponse;
|
|
205
211
|
private request;
|
|
206
212
|
private shouldSkipAuthRetry;
|
|
213
|
+
private signIfNeeded;
|
|
207
214
|
private requestWithRetry;
|
|
208
215
|
login(authId: string, password: string): Promise<LoginResponse>;
|
|
209
216
|
provisionalLogin(authId: string): Promise<ProvisionalLoginResponse>;
|
package/dist/index.js
CHANGED
|
@@ -46,6 +46,8 @@ module.exports = __toCommonJS(index_exports);
|
|
|
46
46
|
// src/Revlm.ts
|
|
47
47
|
var import_bson = require("bson");
|
|
48
48
|
var import_revlm_shared = require("@kedaruma/revlm-shared");
|
|
49
|
+
var import_signature_v4 = require("@aws-sdk/signature-v4");
|
|
50
|
+
var import_sha256_js = require("@aws-crypto/sha256-js");
|
|
49
51
|
|
|
50
52
|
// src/MdbCollection.ts
|
|
51
53
|
var MdbCollection = class {
|
|
@@ -156,6 +158,7 @@ var Revlm = class {
|
|
|
156
158
|
provisionalAuthDomain;
|
|
157
159
|
autoSetToken;
|
|
158
160
|
autoRefreshOn401;
|
|
161
|
+
sigv4Signer;
|
|
159
162
|
constructor(baseUrl, opts = {}) {
|
|
160
163
|
if (!baseUrl) throw new Error("baseUrl is required");
|
|
161
164
|
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
@@ -166,6 +169,24 @@ var Revlm = class {
|
|
|
166
169
|
this.provisionalAuthDomain = opts.provisionalAuthDomain || "";
|
|
167
170
|
this.autoSetToken = opts.autoSetToken ?? true;
|
|
168
171
|
this.autoRefreshOn401 = opts.autoRefreshOn401 || false;
|
|
172
|
+
const sigv4SecretKey = opts.sigv4SecretKey || process.env.REVLM_SIGV4_SECRET_KEY;
|
|
173
|
+
const sigv4AccessKey = opts.sigv4AccessKey || process.env.REVLM_SIGV4_ACCESS_KEY || "revlm-access";
|
|
174
|
+
const sigv4Region = opts.sigv4Region || process.env.REVLM_SIGV4_REGION || "revlm";
|
|
175
|
+
const sigv4Service = opts.sigv4Service || process.env.REVLM_SIGV4_SERVICE || "revlm";
|
|
176
|
+
const sigv4Enabled = opts.sigv4Enabled ?? true;
|
|
177
|
+
if (sigv4Enabled) {
|
|
178
|
+
if (!sigv4SecretKey) {
|
|
179
|
+
throw new Error("SigV4 is enabled but REVLM_SIGV4_SECRET_KEY or opts.sigv4SecretKey is not provided");
|
|
180
|
+
}
|
|
181
|
+
this.sigv4Signer = new import_signature_v4.SignatureV4({
|
|
182
|
+
credentials: { accessKeyId: sigv4AccessKey, secretAccessKey: sigv4SecretKey },
|
|
183
|
+
region: sigv4Region,
|
|
184
|
+
service: sigv4Service,
|
|
185
|
+
sha256: import_sha256_js.Sha256
|
|
186
|
+
});
|
|
187
|
+
} else {
|
|
188
|
+
this.sigv4Signer = null;
|
|
189
|
+
}
|
|
169
190
|
if (!this.fetchImpl) {
|
|
170
191
|
throw new Error("No fetch implementation available. Provide fetchImpl in options or run in Node 18+ with global fetch.");
|
|
171
192
|
}
|
|
@@ -214,7 +235,7 @@ var Revlm = class {
|
|
|
214
235
|
headers["Content-Type"] = "application/ejson";
|
|
215
236
|
}
|
|
216
237
|
if (this._token) {
|
|
217
|
-
headers["
|
|
238
|
+
headers["X-Revlm-JWT"] = `Bearer ${this._token}`;
|
|
218
239
|
}
|
|
219
240
|
return headers;
|
|
220
241
|
}
|
|
@@ -238,6 +259,33 @@ var Revlm = class {
|
|
|
238
259
|
const pathname = path.startsWith("http") ? new URL(path).pathname : path;
|
|
239
260
|
return pathname.includes("/login") || pathname.includes("/provisional-login") || pathname.includes("/refresh-token") || pathname.includes("/verify-token");
|
|
240
261
|
}
|
|
262
|
+
async signIfNeeded(url, method, headers, body) {
|
|
263
|
+
if (!this.sigv4Signer) {
|
|
264
|
+
return { signedUrl: url, signedHeaders: headers };
|
|
265
|
+
}
|
|
266
|
+
const u = new URL(url);
|
|
267
|
+
const signingHeaders = {
|
|
268
|
+
host: u.host,
|
|
269
|
+
...headers
|
|
270
|
+
};
|
|
271
|
+
const reqToSign = {
|
|
272
|
+
method,
|
|
273
|
+
protocol: u.protocol,
|
|
274
|
+
path: u.pathname + (u.search || ""),
|
|
275
|
+
hostname: u.hostname,
|
|
276
|
+
headers: signingHeaders,
|
|
277
|
+
body: body ?? ""
|
|
278
|
+
};
|
|
279
|
+
if (u.port) {
|
|
280
|
+
reqToSign.port = Number(u.port);
|
|
281
|
+
}
|
|
282
|
+
const signed = await this.sigv4Signer.sign(reqToSign);
|
|
283
|
+
const signedHeaders = {};
|
|
284
|
+
Object.entries(signed.headers || {}).forEach(([k, v]) => {
|
|
285
|
+
signedHeaders[k] = Array.isArray(v) ? v.join(",") : String(v);
|
|
286
|
+
});
|
|
287
|
+
return { signedUrl: url, signedHeaders };
|
|
288
|
+
}
|
|
241
289
|
async requestWithRetry(path, method = "POST", body, opts = { allowAuthRetry: false, retrying: false }) {
|
|
242
290
|
const { allowAuthRetry, retrying } = opts;
|
|
243
291
|
const url = path.startsWith("http") ? path : `${this.baseUrl}${path.startsWith("/") ? "" : "/"}${path}`;
|
|
@@ -247,10 +295,11 @@ var Revlm = class {
|
|
|
247
295
|
if (hasBody) {
|
|
248
296
|
serializedBody = import_bson.EJSON.stringify(body);
|
|
249
297
|
}
|
|
298
|
+
const { signedUrl, signedHeaders } = await this.signIfNeeded(url, method, headers, serializedBody);
|
|
250
299
|
try {
|
|
251
|
-
const res = await this.fetchImpl(
|
|
300
|
+
const res = await this.fetchImpl(signedUrl, {
|
|
252
301
|
method,
|
|
253
|
-
headers,
|
|
302
|
+
headers: signedHeaders,
|
|
254
303
|
body: serializedBody
|
|
255
304
|
});
|
|
256
305
|
const parsed = await this.parseResponse(res);
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// src/Revlm.ts
|
|
2
2
|
import { EJSON } from "bson";
|
|
3
3
|
import { AuthClient } from "@kedaruma/revlm-shared";
|
|
4
|
+
import { SignatureV4 } from "@aws-sdk/signature-v4";
|
|
5
|
+
import { Sha256 } from "@aws-crypto/sha256-js";
|
|
4
6
|
|
|
5
7
|
// src/MdbCollection.ts
|
|
6
8
|
var MdbCollection = class {
|
|
@@ -111,6 +113,7 @@ var Revlm = class {
|
|
|
111
113
|
provisionalAuthDomain;
|
|
112
114
|
autoSetToken;
|
|
113
115
|
autoRefreshOn401;
|
|
116
|
+
sigv4Signer;
|
|
114
117
|
constructor(baseUrl, opts = {}) {
|
|
115
118
|
if (!baseUrl) throw new Error("baseUrl is required");
|
|
116
119
|
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
@@ -121,6 +124,24 @@ var Revlm = class {
|
|
|
121
124
|
this.provisionalAuthDomain = opts.provisionalAuthDomain || "";
|
|
122
125
|
this.autoSetToken = opts.autoSetToken ?? true;
|
|
123
126
|
this.autoRefreshOn401 = opts.autoRefreshOn401 || false;
|
|
127
|
+
const sigv4SecretKey = opts.sigv4SecretKey || process.env.REVLM_SIGV4_SECRET_KEY;
|
|
128
|
+
const sigv4AccessKey = opts.sigv4AccessKey || process.env.REVLM_SIGV4_ACCESS_KEY || "revlm-access";
|
|
129
|
+
const sigv4Region = opts.sigv4Region || process.env.REVLM_SIGV4_REGION || "revlm";
|
|
130
|
+
const sigv4Service = opts.sigv4Service || process.env.REVLM_SIGV4_SERVICE || "revlm";
|
|
131
|
+
const sigv4Enabled = opts.sigv4Enabled ?? true;
|
|
132
|
+
if (sigv4Enabled) {
|
|
133
|
+
if (!sigv4SecretKey) {
|
|
134
|
+
throw new Error("SigV4 is enabled but REVLM_SIGV4_SECRET_KEY or opts.sigv4SecretKey is not provided");
|
|
135
|
+
}
|
|
136
|
+
this.sigv4Signer = new SignatureV4({
|
|
137
|
+
credentials: { accessKeyId: sigv4AccessKey, secretAccessKey: sigv4SecretKey },
|
|
138
|
+
region: sigv4Region,
|
|
139
|
+
service: sigv4Service,
|
|
140
|
+
sha256: Sha256
|
|
141
|
+
});
|
|
142
|
+
} else {
|
|
143
|
+
this.sigv4Signer = null;
|
|
144
|
+
}
|
|
124
145
|
if (!this.fetchImpl) {
|
|
125
146
|
throw new Error("No fetch implementation available. Provide fetchImpl in options or run in Node 18+ with global fetch.");
|
|
126
147
|
}
|
|
@@ -169,7 +190,7 @@ var Revlm = class {
|
|
|
169
190
|
headers["Content-Type"] = "application/ejson";
|
|
170
191
|
}
|
|
171
192
|
if (this._token) {
|
|
172
|
-
headers["
|
|
193
|
+
headers["X-Revlm-JWT"] = `Bearer ${this._token}`;
|
|
173
194
|
}
|
|
174
195
|
return headers;
|
|
175
196
|
}
|
|
@@ -193,6 +214,33 @@ var Revlm = class {
|
|
|
193
214
|
const pathname = path.startsWith("http") ? new URL(path).pathname : path;
|
|
194
215
|
return pathname.includes("/login") || pathname.includes("/provisional-login") || pathname.includes("/refresh-token") || pathname.includes("/verify-token");
|
|
195
216
|
}
|
|
217
|
+
async signIfNeeded(url, method, headers, body) {
|
|
218
|
+
if (!this.sigv4Signer) {
|
|
219
|
+
return { signedUrl: url, signedHeaders: headers };
|
|
220
|
+
}
|
|
221
|
+
const u = new URL(url);
|
|
222
|
+
const signingHeaders = {
|
|
223
|
+
host: u.host,
|
|
224
|
+
...headers
|
|
225
|
+
};
|
|
226
|
+
const reqToSign = {
|
|
227
|
+
method,
|
|
228
|
+
protocol: u.protocol,
|
|
229
|
+
path: u.pathname + (u.search || ""),
|
|
230
|
+
hostname: u.hostname,
|
|
231
|
+
headers: signingHeaders,
|
|
232
|
+
body: body ?? ""
|
|
233
|
+
};
|
|
234
|
+
if (u.port) {
|
|
235
|
+
reqToSign.port = Number(u.port);
|
|
236
|
+
}
|
|
237
|
+
const signed = await this.sigv4Signer.sign(reqToSign);
|
|
238
|
+
const signedHeaders = {};
|
|
239
|
+
Object.entries(signed.headers || {}).forEach(([k, v]) => {
|
|
240
|
+
signedHeaders[k] = Array.isArray(v) ? v.join(",") : String(v);
|
|
241
|
+
});
|
|
242
|
+
return { signedUrl: url, signedHeaders };
|
|
243
|
+
}
|
|
196
244
|
async requestWithRetry(path, method = "POST", body, opts = { allowAuthRetry: false, retrying: false }) {
|
|
197
245
|
const { allowAuthRetry, retrying } = opts;
|
|
198
246
|
const url = path.startsWith("http") ? path : `${this.baseUrl}${path.startsWith("/") ? "" : "/"}${path}`;
|
|
@@ -202,10 +250,11 @@ var Revlm = class {
|
|
|
202
250
|
if (hasBody) {
|
|
203
251
|
serializedBody = EJSON.stringify(body);
|
|
204
252
|
}
|
|
253
|
+
const { signedUrl, signedHeaders } = await this.signIfNeeded(url, method, headers, serializedBody);
|
|
205
254
|
try {
|
|
206
|
-
const res = await this.fetchImpl(
|
|
255
|
+
const res = await this.fetchImpl(signedUrl, {
|
|
207
256
|
method,
|
|
208
|
-
headers,
|
|
257
|
+
headers: signedHeaders,
|
|
209
258
|
body: serializedBody
|
|
210
259
|
});
|
|
211
260
|
const parsed = await this.parseResponse(res);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kedaruma/revlm-client",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.14",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "TypeScript client SDK for talking to the Revlm server replacement for MongoDB Realm.",
|
|
6
6
|
"keywords": [
|
|
@@ -36,9 +36,11 @@
|
|
|
36
36
|
"access": "public"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
+
"@aws-sdk/signature-v4": "^3.374.0",
|
|
40
|
+
"@aws-crypto/sha256-js": "^5.2.0",
|
|
39
41
|
"bson": "^6.10.4",
|
|
40
42
|
"dotenv": "^17.2.3",
|
|
41
|
-
"@kedaruma/revlm-shared": "1.0.
|
|
43
|
+
"@kedaruma/revlm-shared": "1.0.5"
|
|
42
44
|
},
|
|
43
45
|
"devDependencies": {
|
|
44
46
|
"tsup": "^8.5.1"
|