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