@scalemule/nextjs 0.1.38 → 0.1.40
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/client.d.mts +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.js +33 -3
- package/dist/client.mjs +33 -3
- package/dist/{index-Tq5WdDfS.d.mts → index-Bv1m_qQ8.d.mts} +20 -0
- package/dist/{index-Tq5WdDfS.d.ts → index-Bv1m_qQ8.d.ts} +20 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +33 -3
- package/dist/index.mjs +33 -3
- package/dist/server/auth.js +110 -62
- package/dist/server/auth.mjs +111 -63
- package/dist/server/index.d.mts +24 -4
- package/dist/server/index.d.ts +24 -4
- package/dist/server/index.js +161 -103
- package/dist/server/index.mjs +161 -103
- package/dist/server/webhook-handler.d.mts +2 -2
- package/dist/server/webhook-handler.d.ts +2 -2
- package/dist/testing.d.mts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +3 -0
- package/dist/testing.mjs +3 -0
- package/dist/{webhook-handler-Cfa7-yKN.d.ts → webhook-handler-5ymVecTD.d.ts} +1 -1
- package/dist/{webhook-handler-DN4WBjbm.d.mts → webhook-handler-CVmBvPFN.d.mts} +1 -1
- package/package.json +4 -3
package/dist/server/index.js
CHANGED
|
@@ -17,6 +17,9 @@ var ScaleMuleApiError = class extends Error {
|
|
|
17
17
|
this.code = error.code;
|
|
18
18
|
this.field = error.field;
|
|
19
19
|
this.status = status;
|
|
20
|
+
this.requestId = error.requestId;
|
|
21
|
+
this.traceId = error.traceId;
|
|
22
|
+
this.problem = error.problem;
|
|
20
23
|
}
|
|
21
24
|
};
|
|
22
25
|
|
|
@@ -34,40 +37,40 @@ function validateIP(ip) {
|
|
|
34
37
|
return void 0;
|
|
35
38
|
}
|
|
36
39
|
function extractClientContext(request) {
|
|
37
|
-
const
|
|
40
|
+
const headers3 = request.headers;
|
|
38
41
|
let ip;
|
|
39
|
-
const cfConnectingIp =
|
|
42
|
+
const cfConnectingIp = headers3.get("cf-connecting-ip");
|
|
40
43
|
if (cfConnectingIp) {
|
|
41
44
|
ip = validateIP(cfConnectingIp);
|
|
42
45
|
}
|
|
43
46
|
if (!ip) {
|
|
44
|
-
const doConnectingIp =
|
|
47
|
+
const doConnectingIp = headers3.get("do-connecting-ip");
|
|
45
48
|
if (doConnectingIp) {
|
|
46
49
|
ip = validateIP(doConnectingIp);
|
|
47
50
|
}
|
|
48
51
|
}
|
|
49
52
|
if (!ip) {
|
|
50
|
-
const realIp =
|
|
53
|
+
const realIp = headers3.get("x-real-ip");
|
|
51
54
|
if (realIp) {
|
|
52
55
|
ip = validateIP(realIp);
|
|
53
56
|
}
|
|
54
57
|
}
|
|
55
58
|
if (!ip) {
|
|
56
|
-
const forwardedFor =
|
|
59
|
+
const forwardedFor = headers3.get("x-forwarded-for");
|
|
57
60
|
if (forwardedFor) {
|
|
58
61
|
const firstIp = forwardedFor.split(",")[0]?.trim();
|
|
59
62
|
ip = validateIP(firstIp);
|
|
60
63
|
}
|
|
61
64
|
}
|
|
62
65
|
if (!ip) {
|
|
63
|
-
const vercelForwarded =
|
|
66
|
+
const vercelForwarded = headers3.get("x-vercel-forwarded-for");
|
|
64
67
|
if (vercelForwarded) {
|
|
65
68
|
const firstIp = vercelForwarded.split(",")[0]?.trim();
|
|
66
69
|
ip = validateIP(firstIp);
|
|
67
70
|
}
|
|
68
71
|
}
|
|
69
72
|
if (!ip) {
|
|
70
|
-
const trueClientIp =
|
|
73
|
+
const trueClientIp = headers3.get("true-client-ip");
|
|
71
74
|
if (trueClientIp) {
|
|
72
75
|
ip = validateIP(trueClientIp);
|
|
73
76
|
}
|
|
@@ -75,10 +78,10 @@ function extractClientContext(request) {
|
|
|
75
78
|
if (!ip && request.ip) {
|
|
76
79
|
ip = validateIP(request.ip);
|
|
77
80
|
}
|
|
78
|
-
const userAgent =
|
|
79
|
-
const deviceFingerprint =
|
|
80
|
-
const referrer =
|
|
81
|
-
const anonymousId =
|
|
81
|
+
const userAgent = headers3.get("user-agent") || void 0;
|
|
82
|
+
const deviceFingerprint = headers3.get("x-device-fingerprint") || void 0;
|
|
83
|
+
const referrer = headers3.get("referer") || void 0;
|
|
84
|
+
const anonymousId = headers3.get("x-anonymous-id") || void 0;
|
|
82
85
|
return {
|
|
83
86
|
ip,
|
|
84
87
|
userAgent,
|
|
@@ -88,9 +91,9 @@ function extractClientContext(request) {
|
|
|
88
91
|
};
|
|
89
92
|
}
|
|
90
93
|
function extractClientContextFromReq(req) {
|
|
91
|
-
const
|
|
94
|
+
const headers3 = req.headers;
|
|
92
95
|
const getHeader = (name) => {
|
|
93
|
-
const value =
|
|
96
|
+
const value = headers3[name.toLowerCase()];
|
|
94
97
|
if (Array.isArray(value)) {
|
|
95
98
|
return value[0];
|
|
96
99
|
}
|
|
@@ -149,27 +152,27 @@ function extractClientContextFromReq(req) {
|
|
|
149
152
|
};
|
|
150
153
|
}
|
|
151
154
|
function buildClientContextHeaders(context) {
|
|
152
|
-
const
|
|
155
|
+
const headers3 = {};
|
|
153
156
|
if (!context) {
|
|
154
|
-
return
|
|
157
|
+
return headers3;
|
|
155
158
|
}
|
|
156
159
|
if (context.ip) {
|
|
157
|
-
|
|
158
|
-
|
|
160
|
+
headers3["x-sm-forwarded-client-ip"] = context.ip;
|
|
161
|
+
headers3["X-Client-IP"] = context.ip;
|
|
159
162
|
}
|
|
160
163
|
if (context.userAgent) {
|
|
161
|
-
|
|
164
|
+
headers3["X-Client-User-Agent"] = context.userAgent;
|
|
162
165
|
}
|
|
163
166
|
if (context.deviceFingerprint) {
|
|
164
|
-
|
|
167
|
+
headers3["X-Client-Device-Fingerprint"] = context.deviceFingerprint;
|
|
165
168
|
}
|
|
166
169
|
if (context.referrer) {
|
|
167
|
-
|
|
170
|
+
headers3["X-Client-Referrer"] = context.referrer;
|
|
168
171
|
}
|
|
169
172
|
if (context.anonymousId) {
|
|
170
|
-
|
|
173
|
+
headers3["x-anonymous-id"] = context.anonymousId;
|
|
171
174
|
}
|
|
172
|
-
return
|
|
175
|
+
return headers3;
|
|
173
176
|
}
|
|
174
177
|
function buildFlagContext(clientContext, extraContext = {}) {
|
|
175
178
|
const context = { ...extraContext };
|
|
@@ -179,6 +182,25 @@ function buildFlagContext(clientContext, extraContext = {}) {
|
|
|
179
182
|
return context;
|
|
180
183
|
}
|
|
181
184
|
|
|
185
|
+
// src/error-context.ts
|
|
186
|
+
function withErrorContext(error, responseData, headers3) {
|
|
187
|
+
const enriched = { ...error };
|
|
188
|
+
const meta = responseData?.meta;
|
|
189
|
+
const requestId = meta?.request_id ?? headers3?.get("x-request-id") ?? void 0;
|
|
190
|
+
if (requestId !== void 0 && enriched.requestId === void 0) {
|
|
191
|
+
enriched.requestId = requestId;
|
|
192
|
+
}
|
|
193
|
+
const traceId = meta?.trace_id;
|
|
194
|
+
if (traceId !== void 0 && enriched.traceId === void 0) {
|
|
195
|
+
enriched.traceId = traceId;
|
|
196
|
+
}
|
|
197
|
+
const rawError = responseData?.error;
|
|
198
|
+
if (rawError !== null && typeof rawError === "object" && enriched.problem === void 0) {
|
|
199
|
+
enriched.problem = rawError;
|
|
200
|
+
}
|
|
201
|
+
return enriched;
|
|
202
|
+
}
|
|
203
|
+
|
|
182
204
|
// src/server/client.ts
|
|
183
205
|
var GATEWAY_URLS = {
|
|
184
206
|
dev: "https://api-dev.scalemule.com",
|
|
@@ -187,6 +209,7 @@ var GATEWAY_URLS = {
|
|
|
187
209
|
function resolveGatewayUrl(config) {
|
|
188
210
|
if (config.gatewayUrl) return config.gatewayUrl;
|
|
189
211
|
if (process.env.SCALEMULE_API_URL) return process.env.SCALEMULE_API_URL;
|
|
212
|
+
if (process.env.SCALEMULE_GATEWAY_URL) return process.env.SCALEMULE_GATEWAY_URL;
|
|
190
213
|
return GATEWAY_URLS[config.environment || "prod"];
|
|
191
214
|
}
|
|
192
215
|
var ScaleMuleServer = class {
|
|
@@ -575,7 +598,7 @@ var ScaleMuleServer = class {
|
|
|
575
598
|
formData.append("file", blob, file.filename);
|
|
576
599
|
formData.append("sm_user_id", userId);
|
|
577
600
|
const url = `${this.gatewayUrl}/v1/storage/upload`;
|
|
578
|
-
const
|
|
601
|
+
const headers3 = {
|
|
579
602
|
"x-api-key": this.apiKey,
|
|
580
603
|
"x-user-id": userId,
|
|
581
604
|
...buildClientContextHeaders(options?.clientContext)
|
|
@@ -586,7 +609,7 @@ var ScaleMuleServer = class {
|
|
|
586
609
|
try {
|
|
587
610
|
const response = await fetch(url, {
|
|
588
611
|
method: "POST",
|
|
589
|
-
headers:
|
|
612
|
+
headers: headers3,
|
|
590
613
|
body: formData
|
|
591
614
|
});
|
|
592
615
|
const text = await response.text();
|
|
@@ -597,7 +620,11 @@ var ScaleMuleServer = class {
|
|
|
597
620
|
}
|
|
598
621
|
if (!response.ok) {
|
|
599
622
|
throw new ScaleMuleApiError(
|
|
600
|
-
|
|
623
|
+
withErrorContext(
|
|
624
|
+
responseData?.error || { code: "UPLOAD_FAILED", message: text || "Upload failed" },
|
|
625
|
+
responseData,
|
|
626
|
+
response.headers
|
|
627
|
+
)
|
|
601
628
|
);
|
|
602
629
|
}
|
|
603
630
|
const data = responseData?.data !== void 0 ? responseData.data : responseData;
|
|
@@ -808,14 +835,14 @@ var ScaleMuleServer = class {
|
|
|
808
835
|
*/
|
|
809
836
|
async request(method, path, options = {}) {
|
|
810
837
|
const url = `${this.gatewayUrl}${path}`;
|
|
811
|
-
const
|
|
838
|
+
const headers3 = {
|
|
812
839
|
"x-api-key": this.apiKey,
|
|
813
840
|
"Content-Type": "application/json",
|
|
814
841
|
// Forward client context headers if provided
|
|
815
842
|
...buildClientContextHeaders(options.clientContext)
|
|
816
843
|
};
|
|
817
844
|
if (options.sessionToken) {
|
|
818
|
-
|
|
845
|
+
headers3["Authorization"] = `Bearer ${options.sessionToken}`;
|
|
819
846
|
}
|
|
820
847
|
if (this.debug) {
|
|
821
848
|
console.log(`[ScaleMule Server] ${method} ${path}`);
|
|
@@ -826,7 +853,7 @@ var ScaleMuleServer = class {
|
|
|
826
853
|
try {
|
|
827
854
|
const response = await fetch(url, {
|
|
828
855
|
method,
|
|
829
|
-
headers:
|
|
856
|
+
headers: headers3,
|
|
830
857
|
body: options.body ? JSON.stringify(options.body) : void 0
|
|
831
858
|
});
|
|
832
859
|
const rotated = response.headers.get("x-rotated-session-token");
|
|
@@ -840,10 +867,11 @@ var ScaleMuleServer = class {
|
|
|
840
867
|
} catch {
|
|
841
868
|
}
|
|
842
869
|
if (!response.ok) {
|
|
843
|
-
const
|
|
870
|
+
const baseError = responseData?.error || {
|
|
844
871
|
code: `HTTP_${response.status}`,
|
|
845
872
|
message: responseData?.message || text || response.statusText
|
|
846
873
|
};
|
|
874
|
+
const error = withErrorContext(baseError, responseData, response.headers);
|
|
847
875
|
if (response.status === 401 && options.sessionToken && !options.isAutoRefresh) {
|
|
848
876
|
if (this.debug) console.log("[ScaleMule Server] 401 received, attempting auto-refresh...");
|
|
849
877
|
try {
|
|
@@ -922,87 +950,111 @@ function createCookieHeader(name, value, options = {}) {
|
|
|
922
950
|
}
|
|
923
951
|
function createClearCookieHeader(name, options = {}) {
|
|
924
952
|
const path = options.path ?? "/";
|
|
925
|
-
|
|
953
|
+
const secure = options.secure ?? process.env.NODE_ENV === "production";
|
|
954
|
+
const sameSite = options.sameSite ?? "lax";
|
|
955
|
+
let cookie = `${name}=; Path=${path}; Max-Age=0; HttpOnly; SameSite=${sameSite}`;
|
|
956
|
+
if (secure) {
|
|
957
|
+
cookie += "; Secure";
|
|
958
|
+
}
|
|
926
959
|
if (options.domain) {
|
|
927
960
|
cookie += `; Domain=${options.domain}`;
|
|
928
961
|
}
|
|
929
962
|
return cookie;
|
|
930
963
|
}
|
|
931
964
|
function withSession(loginResponse, responseBody, options = {}) {
|
|
932
|
-
const
|
|
933
|
-
|
|
934
|
-
|
|
965
|
+
const headers3 = new Headers();
|
|
966
|
+
headers3.set("Content-Type", "application/json");
|
|
967
|
+
headers3.append(
|
|
935
968
|
"Set-Cookie",
|
|
936
969
|
createCookieHeader(SESSION_COOKIE_NAME, loginResponse.session_token, options)
|
|
937
970
|
);
|
|
938
|
-
|
|
971
|
+
headers3.append(
|
|
939
972
|
"Set-Cookie",
|
|
940
973
|
createCookieHeader(USER_ID_COOKIE_NAME, loginResponse.user.id, options)
|
|
941
974
|
);
|
|
942
975
|
return new Response(JSON.stringify({ success: true, data: responseBody }), {
|
|
943
976
|
status: 200,
|
|
944
|
-
headers:
|
|
977
|
+
headers: headers3
|
|
945
978
|
});
|
|
946
979
|
}
|
|
947
980
|
function withRefreshedSession(sessionToken, userId, responseBody, options = {}) {
|
|
948
|
-
const
|
|
949
|
-
|
|
950
|
-
|
|
981
|
+
const headers3 = new Headers();
|
|
982
|
+
headers3.set("Content-Type", "application/json");
|
|
983
|
+
headers3.append(
|
|
951
984
|
"Set-Cookie",
|
|
952
985
|
createCookieHeader(SESSION_COOKIE_NAME, sessionToken, options)
|
|
953
986
|
);
|
|
954
|
-
|
|
987
|
+
headers3.append(
|
|
955
988
|
"Set-Cookie",
|
|
956
989
|
createCookieHeader(USER_ID_COOKIE_NAME, userId, options)
|
|
957
990
|
);
|
|
958
991
|
return new Response(JSON.stringify({ success: true, data: responseBody }), {
|
|
959
992
|
status: 200,
|
|
960
|
-
headers:
|
|
993
|
+
headers: headers3
|
|
961
994
|
});
|
|
962
995
|
}
|
|
963
996
|
function clearSession(responseBody, options = {}, status = 200) {
|
|
964
|
-
const
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
997
|
+
const headers3 = new Headers();
|
|
998
|
+
headers3.set("Content-Type", "application/json");
|
|
999
|
+
headers3.append("Set-Cookie", createClearCookieHeader(SESSION_COOKIE_NAME, options));
|
|
1000
|
+
headers3.append("Set-Cookie", createClearCookieHeader(USER_ID_COOKIE_NAME, options));
|
|
968
1001
|
return new Response(JSON.stringify({ success: status < 300, data: responseBody }), {
|
|
969
1002
|
status,
|
|
970
|
-
headers:
|
|
1003
|
+
headers: headers3
|
|
971
1004
|
});
|
|
972
1005
|
}
|
|
973
1006
|
async function getSession() {
|
|
974
1007
|
const cookieStore = await headers.cookies();
|
|
975
1008
|
const sessionCookie = cookieStore.get(SESSION_COOKIE_NAME);
|
|
976
1009
|
const userIdCookie = cookieStore.get(USER_ID_COOKIE_NAME);
|
|
977
|
-
if (
|
|
978
|
-
return
|
|
1010
|
+
if (sessionCookie?.value && userIdCookie?.value) {
|
|
1011
|
+
return {
|
|
1012
|
+
sessionToken: sessionCookie.value,
|
|
1013
|
+
userId: userIdCookie.value,
|
|
1014
|
+
expiresAt: /* @__PURE__ */ new Date()
|
|
1015
|
+
// Note: actual expiry is managed by ScaleMule backend
|
|
1016
|
+
};
|
|
979
1017
|
}
|
|
1018
|
+
const headerStore = await headers.headers();
|
|
1019
|
+
return sessionFromAuthHeaders(
|
|
1020
|
+
headerStore.get("authorization"),
|
|
1021
|
+
headerStore.get("x-sm-user-id")
|
|
1022
|
+
);
|
|
1023
|
+
}
|
|
1024
|
+
function sessionFromAuthHeaders(authorization, userId) {
|
|
1025
|
+
if (!authorization || !userId) return null;
|
|
1026
|
+
const match = /^Bearer\s+(.+)$/i.exec(authorization.trim());
|
|
1027
|
+
const token = match?.[1]?.trim();
|
|
1028
|
+
if (!token) return null;
|
|
980
1029
|
return {
|
|
981
|
-
sessionToken:
|
|
982
|
-
userId
|
|
1030
|
+
sessionToken: token,
|
|
1031
|
+
userId,
|
|
983
1032
|
expiresAt: /* @__PURE__ */ new Date()
|
|
984
|
-
// Note: actual expiry is managed by ScaleMule backend
|
|
985
1033
|
};
|
|
986
1034
|
}
|
|
987
1035
|
function getSessionFromRequest(request) {
|
|
988
1036
|
const cookieHeader = request.headers.get("cookie");
|
|
989
|
-
if (
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1037
|
+
if (cookieHeader) {
|
|
1038
|
+
const cookies4 = Object.fromEntries(
|
|
1039
|
+
cookieHeader.split(";").map((c) => {
|
|
1040
|
+
const [key, ...rest] = c.trim().split("=");
|
|
1041
|
+
return [key, decodeURIComponent(rest.join("="))];
|
|
1042
|
+
})
|
|
1043
|
+
);
|
|
1044
|
+
const sessionToken = cookies4[SESSION_COOKIE_NAME];
|
|
1045
|
+
const userId = cookies4[USER_ID_COOKIE_NAME];
|
|
1046
|
+
if (sessionToken && userId) {
|
|
1047
|
+
return {
|
|
1048
|
+
sessionToken,
|
|
1049
|
+
userId,
|
|
1050
|
+
expiresAt: /* @__PURE__ */ new Date()
|
|
1051
|
+
};
|
|
1052
|
+
}
|
|
1000
1053
|
}
|
|
1001
|
-
return
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
};
|
|
1054
|
+
return sessionFromAuthHeaders(
|
|
1055
|
+
request.headers.get("authorization"),
|
|
1056
|
+
request.headers.get("x-sm-user-id")
|
|
1057
|
+
);
|
|
1006
1058
|
}
|
|
1007
1059
|
var MAX_KNOWN_ACCOUNTS = 10;
|
|
1008
1060
|
function maskEmail(email) {
|
|
@@ -1043,7 +1095,7 @@ function applyPrivacyToEntry(entry, privacy) {
|
|
|
1043
1095
|
};
|
|
1044
1096
|
}
|
|
1045
1097
|
}
|
|
1046
|
-
function appendKnownAccountCookie(
|
|
1098
|
+
function appendKnownAccountCookie(headers3, account, existingCookie, options = {}, privacy) {
|
|
1047
1099
|
let accounts = {};
|
|
1048
1100
|
if (existingCookie) {
|
|
1049
1101
|
try {
|
|
@@ -1072,9 +1124,9 @@ function appendKnownAccountCookie(headers2, account, existingCookie, options = {
|
|
|
1072
1124
|
if (options.domain) {
|
|
1073
1125
|
cookie += `; Domain=${options.domain}`;
|
|
1074
1126
|
}
|
|
1075
|
-
|
|
1127
|
+
headers3.append("Set-Cookie", cookie);
|
|
1076
1128
|
}
|
|
1077
|
-
function removeKnownAccountFromCookie(
|
|
1129
|
+
function removeKnownAccountFromCookie(headers3, userId, existingCookie, options = {}) {
|
|
1078
1130
|
let accounts = {};
|
|
1079
1131
|
if (existingCookie) {
|
|
1080
1132
|
try {
|
|
@@ -1094,15 +1146,15 @@ function removeKnownAccountFromCookie(headers2, userId, existingCookie, options
|
|
|
1094
1146
|
if (options.domain) {
|
|
1095
1147
|
cookie += `; Domain=${options.domain}`;
|
|
1096
1148
|
}
|
|
1097
|
-
|
|
1149
|
+
headers3.append("Set-Cookie", cookie);
|
|
1098
1150
|
}
|
|
1099
|
-
function clearKnownAccountsCookie(
|
|
1151
|
+
function clearKnownAccountsCookie(headers3, options = {}) {
|
|
1100
1152
|
const path = options.path ?? "/";
|
|
1101
1153
|
let cookie = `${KNOWN_ACCOUNTS_COOKIE_NAME}=; Path=${path}; Max-Age=0`;
|
|
1102
1154
|
if (options.domain) {
|
|
1103
1155
|
cookie += `; Domain=${options.domain}`;
|
|
1104
1156
|
}
|
|
1105
|
-
|
|
1157
|
+
headers3.append("Set-Cookie", cookie);
|
|
1106
1158
|
}
|
|
1107
1159
|
function getKnownAccountsFromRequest(request) {
|
|
1108
1160
|
const cookieHeader = request.headers.get("cookie");
|
|
@@ -1600,13 +1652,13 @@ function createAuthRoutes(config = {}) {
|
|
|
1600
1652
|
if (!user_id) {
|
|
1601
1653
|
return errorResponse("VALIDATION_ERROR", "user_id required", 400);
|
|
1602
1654
|
}
|
|
1603
|
-
const
|
|
1604
|
-
|
|
1655
|
+
const headers3 = new Headers();
|
|
1656
|
+
headers3.set("Content-Type", "application/json");
|
|
1605
1657
|
const existingKnown = getKnownAccountsCookieRaw(request);
|
|
1606
|
-
removeKnownAccountFromCookie(
|
|
1658
|
+
removeKnownAccountFromCookie(headers3, user_id, existingKnown, cookieOptions);
|
|
1607
1659
|
return new Response(
|
|
1608
1660
|
JSON.stringify({ success: true, data: { message: "Account forgotten" } }),
|
|
1609
|
-
{ status: 200, headers:
|
|
1661
|
+
{ status: 200, headers: headers3 }
|
|
1610
1662
|
);
|
|
1611
1663
|
}
|
|
1612
1664
|
// ==================== Forget All Accounts ====================
|
|
@@ -1614,12 +1666,12 @@ function createAuthRoutes(config = {}) {
|
|
|
1614
1666
|
if (!config.enableAccountSwitcher) {
|
|
1615
1667
|
return errorResponse("NOT_FOUND", "Account switcher not enabled", 404);
|
|
1616
1668
|
}
|
|
1617
|
-
const
|
|
1618
|
-
|
|
1619
|
-
clearKnownAccountsCookie(
|
|
1669
|
+
const headers3 = new Headers();
|
|
1670
|
+
headers3.set("Content-Type", "application/json");
|
|
1671
|
+
clearKnownAccountsCookie(headers3, cookieOptions);
|
|
1620
1672
|
return new Response(
|
|
1621
1673
|
JSON.stringify({ success: true, data: { message: "All accounts forgotten" } }),
|
|
1622
|
-
{ status: 200, headers:
|
|
1674
|
+
{ status: 200, headers: headers3 }
|
|
1623
1675
|
);
|
|
1624
1676
|
}
|
|
1625
1677
|
default:
|
|
@@ -2329,31 +2381,31 @@ function createPushRoutes(config) {
|
|
|
2329
2381
|
const { apiKey, gatewayUrl, csrf = true } = config;
|
|
2330
2382
|
async function proxyToGateway(request, method, subPath) {
|
|
2331
2383
|
const targetUrl = `${gatewayUrl}/v1/communication/push/${subPath}`;
|
|
2332
|
-
const
|
|
2384
|
+
const headers3 = {
|
|
2333
2385
|
"x-api-key": apiKey
|
|
2334
2386
|
};
|
|
2335
2387
|
const session = getSessionFromRequest(request);
|
|
2336
2388
|
if (session?.sessionToken) {
|
|
2337
|
-
|
|
2389
|
+
headers3["Authorization"] = `Bearer ${session.sessionToken}`;
|
|
2338
2390
|
}
|
|
2339
2391
|
const clientContext = extractClientContext(
|
|
2340
2392
|
request
|
|
2341
2393
|
);
|
|
2342
2394
|
const contextHeaders = buildClientContextHeaders(clientContext);
|
|
2343
|
-
Object.assign(
|
|
2395
|
+
Object.assign(headers3, contextHeaders);
|
|
2344
2396
|
const workspaceId = request.headers.get("x-sm-workspace-id");
|
|
2345
2397
|
if (workspaceId) {
|
|
2346
|
-
|
|
2398
|
+
headers3["x-sm-workspace-id"] = workspaceId;
|
|
2347
2399
|
}
|
|
2348
2400
|
const fetchOptions = {
|
|
2349
2401
|
method,
|
|
2350
|
-
headers:
|
|
2402
|
+
headers: headers3
|
|
2351
2403
|
};
|
|
2352
2404
|
if (method !== "GET" && method !== "DELETE") {
|
|
2353
2405
|
try {
|
|
2354
2406
|
const body = await request.text();
|
|
2355
2407
|
if (body) {
|
|
2356
|
-
|
|
2408
|
+
headers3["Content-Type"] = "application/json";
|
|
2357
2409
|
fetchOptions.body = body;
|
|
2358
2410
|
}
|
|
2359
2411
|
} catch {
|
|
@@ -2448,26 +2500,26 @@ function createNotificationRoutes(config) {
|
|
|
2448
2500
|
const { apiKey, gatewayUrl } = config;
|
|
2449
2501
|
async function proxyToGateway(request, method, subPath) {
|
|
2450
2502
|
const targetUrl = `${gatewayUrl}/v1/notifications/${subPath}`;
|
|
2451
|
-
const
|
|
2503
|
+
const headers3 = {
|
|
2452
2504
|
"x-api-key": apiKey,
|
|
2453
2505
|
"Content-Type": "application/json"
|
|
2454
2506
|
};
|
|
2455
2507
|
const session = getSessionFromRequest(request);
|
|
2456
2508
|
if (session?.sessionToken) {
|
|
2457
|
-
|
|
2509
|
+
headers3["Authorization"] = `Bearer ${session.sessionToken}`;
|
|
2458
2510
|
}
|
|
2459
2511
|
const clientContext = extractClientContext(
|
|
2460
2512
|
request
|
|
2461
2513
|
);
|
|
2462
2514
|
const contextHeaders = buildClientContextHeaders(clientContext);
|
|
2463
|
-
Object.assign(
|
|
2515
|
+
Object.assign(headers3, contextHeaders);
|
|
2464
2516
|
const workspaceId = request.headers.get("x-sm-workspace-id");
|
|
2465
2517
|
if (workspaceId) {
|
|
2466
|
-
|
|
2518
|
+
headers3["x-sm-workspace-id"] = workspaceId;
|
|
2467
2519
|
}
|
|
2468
2520
|
const fetchOptions = {
|
|
2469
2521
|
method,
|
|
2470
|
-
headers:
|
|
2522
|
+
headers: headers3
|
|
2471
2523
|
};
|
|
2472
2524
|
if (method === "PATCH") {
|
|
2473
2525
|
try {
|
|
@@ -2512,11 +2564,12 @@ function createNotificationRoutes(config) {
|
|
|
2512
2564
|
|
|
2513
2565
|
// src/server/errors.ts
|
|
2514
2566
|
var ScaleMuleError = class extends Error {
|
|
2515
|
-
constructor(code, message, status = 400, details) {
|
|
2567
|
+
constructor(code, message, status = 400, details, requestId) {
|
|
2516
2568
|
super(message);
|
|
2517
2569
|
this.code = code;
|
|
2518
2570
|
this.status = status;
|
|
2519
2571
|
this.details = details;
|
|
2572
|
+
this.requestId = requestId;
|
|
2520
2573
|
this.name = "ScaleMuleError";
|
|
2521
2574
|
}
|
|
2522
2575
|
};
|
|
@@ -2570,7 +2623,8 @@ function unwrap(result) {
|
|
|
2570
2623
|
code,
|
|
2571
2624
|
err?.message || "An error occurred",
|
|
2572
2625
|
status,
|
|
2573
|
-
err?.details
|
|
2626
|
+
err?.details,
|
|
2627
|
+
err?.requestId ?? envelope.meta?.request_id
|
|
2574
2628
|
);
|
|
2575
2629
|
}
|
|
2576
2630
|
return envelope.data;
|
|
@@ -2619,7 +2673,11 @@ function apiHandler(handler, options) {
|
|
|
2619
2673
|
console.error("Internal API error:", error.message);
|
|
2620
2674
|
}
|
|
2621
2675
|
return Response.json(
|
|
2622
|
-
{
|
|
2676
|
+
{
|
|
2677
|
+
success: false,
|
|
2678
|
+
error: { code: error.code, message: safeMessage },
|
|
2679
|
+
...error.requestId ? { meta: { request_id: error.requestId } } : {}
|
|
2680
|
+
},
|
|
2623
2681
|
{ status: error.status }
|
|
2624
2682
|
);
|
|
2625
2683
|
}
|
|
@@ -3141,47 +3199,47 @@ function formatPermissionsDirective(feature, value) {
|
|
|
3141
3199
|
return `${feature}=(${parts.join(" ")})`;
|
|
3142
3200
|
}
|
|
3143
3201
|
function buildSecurityHeaders(opts = {}) {
|
|
3144
|
-
const
|
|
3202
|
+
const headers3 = [];
|
|
3145
3203
|
const includeHsts = opts.includeHsts ?? true;
|
|
3146
3204
|
const hstsMaxAge = opts.hstsMaxAgeSeconds ?? 31536e3;
|
|
3147
3205
|
if (includeHsts && hstsMaxAge > 0) {
|
|
3148
3206
|
const parts = [`max-age=${hstsMaxAge}`];
|
|
3149
3207
|
if (opts.hstsIncludeSubDomains ?? true) parts.push("includeSubDomains");
|
|
3150
3208
|
if (opts.hstsPreload ?? false) parts.push("preload");
|
|
3151
|
-
|
|
3209
|
+
headers3.push({
|
|
3152
3210
|
key: "Strict-Transport-Security",
|
|
3153
3211
|
value: parts.join("; ")
|
|
3154
3212
|
});
|
|
3155
3213
|
}
|
|
3156
3214
|
const frameOptions = opts.frameOptions === void 0 ? "DENY" : opts.frameOptions;
|
|
3157
3215
|
if (frameOptions !== null) {
|
|
3158
|
-
|
|
3216
|
+
headers3.push({ key: "X-Frame-Options", value: frameOptions });
|
|
3159
3217
|
}
|
|
3160
3218
|
const contentTypeOptions = opts.contentTypeOptions === void 0 ? "nosniff" : opts.contentTypeOptions;
|
|
3161
3219
|
if (contentTypeOptions !== null) {
|
|
3162
|
-
|
|
3220
|
+
headers3.push({ key: "X-Content-Type-Options", value: contentTypeOptions });
|
|
3163
3221
|
}
|
|
3164
|
-
|
|
3222
|
+
headers3.push({
|
|
3165
3223
|
key: "Referrer-Policy",
|
|
3166
3224
|
value: opts.referrerPolicy ?? "strict-origin-when-cross-origin"
|
|
3167
3225
|
});
|
|
3168
3226
|
const xss = opts.xssProtection === void 0 ? "0" : opts.xssProtection;
|
|
3169
3227
|
if (xss !== null) {
|
|
3170
|
-
|
|
3228
|
+
headers3.push({ key: "X-XSS-Protection", value: xss });
|
|
3171
3229
|
}
|
|
3172
3230
|
const permissions = opts.permissionsPolicy === void 0 ? DEFAULT_PERMISSIONS_POLICY : opts.permissionsPolicy;
|
|
3173
3231
|
if (permissions !== null) {
|
|
3174
3232
|
const directives = Object.entries(permissions).map(([feature, value]) => formatPermissionsDirective(feature, value)).join(", ");
|
|
3175
|
-
|
|
3233
|
+
headers3.push({ key: "Permissions-Policy", value: directives });
|
|
3176
3234
|
}
|
|
3177
3235
|
if (opts.extraHeaders?.length) {
|
|
3178
|
-
const byKey = new Map(
|
|
3236
|
+
const byKey = new Map(headers3.map((h) => [h.key.toLowerCase(), h]));
|
|
3179
3237
|
for (const extra of opts.extraHeaders) {
|
|
3180
3238
|
byKey.set(extra.key.toLowerCase(), extra);
|
|
3181
3239
|
}
|
|
3182
3240
|
return Array.from(byKey.values());
|
|
3183
3241
|
}
|
|
3184
|
-
return
|
|
3242
|
+
return headers3;
|
|
3185
3243
|
}
|
|
3186
3244
|
|
|
3187
3245
|
exports.CSRF_COOKIE_NAME = CSRF_COOKIE_NAME;
|