@supernova-studio/client 1.52.2 → 1.52.4
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 +534 -370
- package/dist/index.d.ts +534 -370
- package/dist/index.js +231 -230
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +408 -407
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9312,6 +9312,182 @@ var DTOElementsGetOutputV2 = _zod.z.object({
|
|
|
9312
9312
|
// src/api/dto/forge/project-member.ts
|
|
9313
9313
|
|
|
9314
9314
|
|
|
9315
|
+
// src/utils/figma.ts
|
|
9316
|
+
var figmaFileIdRegex = /^[0-9a-zA-Z]{22,128}$/;
|
|
9317
|
+
var nodeIdRegex = /^\d+-\d+$/;
|
|
9318
|
+
var nodeTypeRegex = /^[0-9a-zA-Z]^/;
|
|
9319
|
+
var ParsedFigmaFileURLError = /* @__PURE__ */ ((ParsedFigmaFileURLError2) => {
|
|
9320
|
+
ParsedFigmaFileURLError2["InvalidUrl"] = "InvalidUrl";
|
|
9321
|
+
ParsedFigmaFileURLError2["InvalidFigmaFileId"] = "InvalidFigmaFileId";
|
|
9322
|
+
return ParsedFigmaFileURLError2;
|
|
9323
|
+
})(ParsedFigmaFileURLError || {});
|
|
9324
|
+
var FigmaUtils = {
|
|
9325
|
+
tryParseFigmaFileURL(urlString) {
|
|
9326
|
+
if (!URL.canParse(urlString)) {
|
|
9327
|
+
return { status: "Error", error: "InvalidUrl" /* InvalidUrl */ };
|
|
9328
|
+
}
|
|
9329
|
+
const url = new URL(urlString);
|
|
9330
|
+
if (!url.hostname.endsWith("figma.com")) {
|
|
9331
|
+
return { status: "Error", error: "InvalidUrl" /* InvalidUrl */ };
|
|
9332
|
+
}
|
|
9333
|
+
const pathSegments = url.pathname.split("/");
|
|
9334
|
+
if (pathSegments[1] !== "design" && pathSegments[1] !== "file") {
|
|
9335
|
+
return { status: "Error", error: "InvalidUrl" /* InvalidUrl */ };
|
|
9336
|
+
}
|
|
9337
|
+
const fileId = pathSegments[2];
|
|
9338
|
+
if (!fileId || !fileId.match(figmaFileIdRegex)) {
|
|
9339
|
+
return { status: "Error", error: "InvalidFigmaFileId" /* InvalidFigmaFileId */ };
|
|
9340
|
+
}
|
|
9341
|
+
let fileName = null;
|
|
9342
|
+
const rawFileName = pathSegments[3];
|
|
9343
|
+
if (rawFileName) {
|
|
9344
|
+
fileName = rawFileName.replaceAll("-", " ");
|
|
9345
|
+
}
|
|
9346
|
+
let nodeId = null;
|
|
9347
|
+
const nodeIdRaw = url.searchParams.get("node-id");
|
|
9348
|
+
if (nodeIdRaw && nodeIdRaw.match(nodeIdRegex)) {
|
|
9349
|
+
nodeId = nodeIdRaw.replace("-", ":");
|
|
9350
|
+
}
|
|
9351
|
+
let nodeType = null;
|
|
9352
|
+
const nodeTypeRaw = url.searchParams.get("node-type");
|
|
9353
|
+
if (nodeTypeRaw && nodeTypeRaw.match(nodeTypeRegex)) {
|
|
9354
|
+
nodeType = nodeTypeRaw;
|
|
9355
|
+
}
|
|
9356
|
+
return { status: "Success", fileId, fileName, nodeId, nodeType };
|
|
9357
|
+
}
|
|
9358
|
+
};
|
|
9359
|
+
|
|
9360
|
+
// src/utils/hash.ts
|
|
9361
|
+
function hash(input) {
|
|
9362
|
+
return farmhash(input).toString(16);
|
|
9363
|
+
}
|
|
9364
|
+
function farmhash(input) {
|
|
9365
|
+
const seed = 2654435769;
|
|
9366
|
+
let hash2 = seed;
|
|
9367
|
+
for (let i = 0; i < input.length; i++) {
|
|
9368
|
+
const charCode = input.charCodeAt(i);
|
|
9369
|
+
hash2 ^= charCode;
|
|
9370
|
+
hash2 = Math.imul(hash2, 1540483477);
|
|
9371
|
+
hash2 ^= hash2 >>> 15;
|
|
9372
|
+
}
|
|
9373
|
+
hash2 = Math.imul(hash2, 1540483477);
|
|
9374
|
+
hash2 ^= hash2 >>> 13;
|
|
9375
|
+
hash2 = Math.imul(hash2, 1540483477);
|
|
9376
|
+
hash2 ^= hash2 >>> 15;
|
|
9377
|
+
return hash2 >>> 0;
|
|
9378
|
+
}
|
|
9379
|
+
function prepareObject(obj) {
|
|
9380
|
+
if (obj === null || typeof obj !== "object") {
|
|
9381
|
+
return obj;
|
|
9382
|
+
}
|
|
9383
|
+
if (Array.isArray(obj)) {
|
|
9384
|
+
return obj.map(prepareObject);
|
|
9385
|
+
}
|
|
9386
|
+
const sortedObj = {};
|
|
9387
|
+
for (const key of Object.keys(obj).sort()) {
|
|
9388
|
+
if (obj[key] === null || obj[key] === void 0) {
|
|
9389
|
+
continue;
|
|
9390
|
+
}
|
|
9391
|
+
sortedObj[key] = prepareObject(obj[key]);
|
|
9392
|
+
}
|
|
9393
|
+
return sortedObj;
|
|
9394
|
+
}
|
|
9395
|
+
function generateHash(input, debug = false) {
|
|
9396
|
+
if (typeof input === "object") {
|
|
9397
|
+
const sanitized = JSON.stringify(prepareObject(input));
|
|
9398
|
+
if (debug) {
|
|
9399
|
+
console.log("Hashing sanitized string:");
|
|
9400
|
+
console.log(sanitized);
|
|
9401
|
+
}
|
|
9402
|
+
return hash(sanitized);
|
|
9403
|
+
} else {
|
|
9404
|
+
try {
|
|
9405
|
+
const obj = JSON.parse(input);
|
|
9406
|
+
const sanitized = JSON.stringify(prepareObject(obj));
|
|
9407
|
+
if (debug) {
|
|
9408
|
+
console.log("Hashing sanitized string:");
|
|
9409
|
+
console.log(sanitized);
|
|
9410
|
+
}
|
|
9411
|
+
return hash(sanitized);
|
|
9412
|
+
} catch (e2) {
|
|
9413
|
+
return hash(input);
|
|
9414
|
+
}
|
|
9415
|
+
}
|
|
9416
|
+
}
|
|
9417
|
+
|
|
9418
|
+
// src/utils/redirect-validation.ts
|
|
9419
|
+
var exhaustiveInvalidUriPaths = {
|
|
9420
|
+
emptyPath: "",
|
|
9421
|
+
spacesInPath: "/invalid path/with spaces",
|
|
9422
|
+
specialCharacter1: "/path/with|invalid>characters",
|
|
9423
|
+
specialCharacter2: "/path/with<invalid*characters",
|
|
9424
|
+
specialCharacter3: "/path/{invalid}?characters",
|
|
9425
|
+
consecutiveSlashes: "/path//with///too/many/slashes",
|
|
9426
|
+
unencodedPercent: "/path/with/unencoded%percent",
|
|
9427
|
+
unencodedSpaces: "/path/with unencoded spaces",
|
|
9428
|
+
fragmentIdentifier: "/path/with#fragment",
|
|
9429
|
+
queryParameters: "/path/with?query=parameter",
|
|
9430
|
+
nullCharacter: "/path/with/\0nullcharacter",
|
|
9431
|
+
onlySlash: "/",
|
|
9432
|
+
controlCharacter: "/path/with/control\0character",
|
|
9433
|
+
extremelyLongPath: "/" + "a".repeat(2047),
|
|
9434
|
+
invalidStartCharacter: "///path/starting/with/slashes",
|
|
9435
|
+
invalidStartCharacterColon: ":/path/starting/with/colon",
|
|
9436
|
+
invalidTrailingDot: "/path/ending/with/dot.",
|
|
9437
|
+
invalidPercentEncoding1: "/path/with/%2",
|
|
9438
|
+
invalidPercentEncoding2: "/path/with/%ZZ",
|
|
9439
|
+
invalidPercentEncoding3: "/path/with/%G1",
|
|
9440
|
+
reservedCharacter1: "/path/with?<reserved>",
|
|
9441
|
+
reservedCharacter2: '/path/with/"quotes"',
|
|
9442
|
+
reservedCharacter3: "/path/with/[brackets]",
|
|
9443
|
+
reservedCharacter4: "/path/with/\\backslashes",
|
|
9444
|
+
nonAscii1: "/path/with/\u4F60\u597D",
|
|
9445
|
+
nonAscii2: "/path/with/emoji/\u{1F603}",
|
|
9446
|
+
mixedEncodingPath: "/path/%41A%42B%C3%28",
|
|
9447
|
+
directoryTraversal1: "/path/../../etc/passwd",
|
|
9448
|
+
directoryTraversal2: "/path/./././"
|
|
9449
|
+
};
|
|
9450
|
+
function isValidRedirectPath(path) {
|
|
9451
|
+
const trimmedPath = path.toLowerCase().trim();
|
|
9452
|
+
const url = "https://www.example.com" + trimmedPath;
|
|
9453
|
+
if (url.length > 2048) {
|
|
9454
|
+
return {
|
|
9455
|
+
isValid: false,
|
|
9456
|
+
reason: "TooLong"
|
|
9457
|
+
};
|
|
9458
|
+
}
|
|
9459
|
+
if (trimmedPath === "") {
|
|
9460
|
+
return {
|
|
9461
|
+
isValid: false,
|
|
9462
|
+
reason: "Empty"
|
|
9463
|
+
};
|
|
9464
|
+
}
|
|
9465
|
+
if (url === "/") {
|
|
9466
|
+
return {
|
|
9467
|
+
isValid: false,
|
|
9468
|
+
reason: "Empty"
|
|
9469
|
+
};
|
|
9470
|
+
}
|
|
9471
|
+
if (url.includes("?")) {
|
|
9472
|
+
return {
|
|
9473
|
+
isValid: false,
|
|
9474
|
+
reason: "ContainsQuery"
|
|
9475
|
+
};
|
|
9476
|
+
}
|
|
9477
|
+
if (url.includes("#")) {
|
|
9478
|
+
return {
|
|
9479
|
+
isValid: false,
|
|
9480
|
+
reason: "ContainsFragment"
|
|
9481
|
+
};
|
|
9482
|
+
}
|
|
9483
|
+
const regex = /^\/[A-Za-z0-9_-]+(\/[A-Za-z0-9_-]+)*$/;
|
|
9484
|
+
const isValid = regex.test(trimmedPath);
|
|
9485
|
+
return {
|
|
9486
|
+
isValid: regex.test(trimmedPath),
|
|
9487
|
+
reason: !isValid ? "InvalidURI" : void 0
|
|
9488
|
+
};
|
|
9489
|
+
}
|
|
9490
|
+
|
|
9315
9491
|
// src/api/dto/forge/project-invitation.ts
|
|
9316
9492
|
|
|
9317
9493
|
var DTOForgeProjectInvitation = ForgeProjectInvitation;
|
|
@@ -9355,7 +9531,7 @@ var DTORemoveForgeProjectMember = DTOForgeProjectMember.pick({
|
|
|
9355
9531
|
userId: true
|
|
9356
9532
|
});
|
|
9357
9533
|
var DTOForgeProjectMemberListQuery = _zod.z.object({
|
|
9358
|
-
includeImplicitMembers:
|
|
9534
|
+
includeImplicitMembers: zodQueryBoolean().optional()
|
|
9359
9535
|
});
|
|
9360
9536
|
var DTOForgeProjectMembersListResponse = _zod.z.object({
|
|
9361
9537
|
members: _zod.z.array(DTOForgeProjectMember),
|
|
@@ -10333,7 +10509,8 @@ var DTOThreadMessageFinalizeInput = _zod2.default.object({
|
|
|
10333
10509
|
});
|
|
10334
10510
|
var DTOThreadMessageRetryInput = _zod2.default.object({
|
|
10335
10511
|
agentMessageId: Id,
|
|
10336
|
-
runtimeError: _zod2.default.string().optional()
|
|
10512
|
+
runtimeError: _zod2.default.string().optional(),
|
|
10513
|
+
message: DTOThreadMessage.pick({ id: true, body: true }).optional()
|
|
10337
10514
|
});
|
|
10338
10515
|
var DTOThreadMessageUpdateInput = DTOThreadMessage.pick({
|
|
10339
10516
|
id: true
|
|
@@ -10914,6 +11091,58 @@ var DTOMCPStreamResponse = _zod2.default.object({
|
|
|
10914
11091
|
stream: DTOMCPStream
|
|
10915
11092
|
});
|
|
10916
11093
|
|
|
11094
|
+
// src/api/dto/notifications/notifications.ts
|
|
11095
|
+
|
|
11096
|
+
var DTONotificationChatMentionPayload = _zod.z.object({
|
|
11097
|
+
messageAuthorId: _zod.z.string(),
|
|
11098
|
+
messageText: _zod.z.string(),
|
|
11099
|
+
messageId: _zod.z.string(),
|
|
11100
|
+
parentMessageId: _zod.z.string().optional(),
|
|
11101
|
+
workspaceId: _zod.z.string(),
|
|
11102
|
+
projectId: _zod.z.string(),
|
|
11103
|
+
subjectType: _zod.z.string(),
|
|
11104
|
+
threadSubjectId: _zod.z.string(),
|
|
11105
|
+
subjectName: _zod.z.string()
|
|
11106
|
+
});
|
|
11107
|
+
var DTONotificationProjectInvitationPayload = _zod.z.object({
|
|
11108
|
+
workspaceId: _zod.z.string(),
|
|
11109
|
+
projectId: _zod.z.string(),
|
|
11110
|
+
projectTitle: _zod.z.string(),
|
|
11111
|
+
invitedByUserId: _zod.z.string(),
|
|
11112
|
+
invitationRole: _zod.z.string()
|
|
11113
|
+
});
|
|
11114
|
+
var DTONotificationProjectDocumentCommentPayload = _zod.z.object({
|
|
11115
|
+
documentId: _zod.z.string(),
|
|
11116
|
+
entityTitle: _zod.z.string(),
|
|
11117
|
+
projectId: _zod.z.string(),
|
|
11118
|
+
workspaceId: _zod.z.string(),
|
|
11119
|
+
threadId: _zod.z.string(),
|
|
11120
|
+
commentId: _zod.z.string(),
|
|
11121
|
+
commentCreatedAt: _zod.z.string(),
|
|
11122
|
+
commentAuthorId: _zod.z.string(),
|
|
11123
|
+
commentBody: _zod.z.string()
|
|
11124
|
+
});
|
|
11125
|
+
var DTONotificationBase = _zod.z.object({
|
|
11126
|
+
userId: _zod.z.string(),
|
|
11127
|
+
subjectId: _zod.z.string(),
|
|
11128
|
+
roomId: _zod.z.string().optional(),
|
|
11129
|
+
workspaceId: _zod.z.string()
|
|
11130
|
+
});
|
|
11131
|
+
var DTONotificationCreateInput = _zod.z.discriminatedUnion("type", [
|
|
11132
|
+
_zod.z.object({
|
|
11133
|
+
type: _zod.z.literal(DTONotificationType.enum.ChatMention),
|
|
11134
|
+
activityData: DTONotificationChatMentionPayload
|
|
11135
|
+
}),
|
|
11136
|
+
_zod.z.object({
|
|
11137
|
+
type: _zod.z.literal(DTONotificationType.enum.ProjectInvitation),
|
|
11138
|
+
activityData: DTONotificationProjectInvitationPayload
|
|
11139
|
+
}),
|
|
11140
|
+
_zod.z.object({
|
|
11141
|
+
type: _zod.z.literal(DTONotificationType.enum.ProjectDocumentComment),
|
|
11142
|
+
activityData: DTONotificationProjectDocumentCommentPayload
|
|
11143
|
+
})
|
|
11144
|
+
]).and(DTONotificationBase);
|
|
11145
|
+
|
|
10917
11146
|
// src/api/dto/portal/portal-settings.ts
|
|
10918
11147
|
|
|
10919
11148
|
var DTOPortalSettingsTheme = PortalSettingsTheme;
|
|
@@ -11174,234 +11403,6 @@ var DTOTrailEventClientCreate = _zod.z.discriminatedUnion("type", [
|
|
|
11174
11403
|
_zod.z.object({ type: _zod.z.literal("DocumentCommentSent"), payload: DTOTrailEventDocumentCommentSentPayload })
|
|
11175
11404
|
]).and(DTOTrailEventBase.omit({ id: true, createdAt: true, updatedAt: true }));
|
|
11176
11405
|
|
|
11177
|
-
// src/api/dto/notifications/notifications.ts
|
|
11178
|
-
|
|
11179
|
-
var DTONotificationChatMentionPayload = _zod.z.object({
|
|
11180
|
-
messageAuthorId: _zod.z.string(),
|
|
11181
|
-
messageText: _zod.z.string(),
|
|
11182
|
-
messageId: _zod.z.string(),
|
|
11183
|
-
parentMessageId: _zod.z.string().optional(),
|
|
11184
|
-
workspaceId: _zod.z.string(),
|
|
11185
|
-
projectId: _zod.z.string(),
|
|
11186
|
-
subjectType: _zod.z.string(),
|
|
11187
|
-
threadSubjectId: _zod.z.string(),
|
|
11188
|
-
subjectName: _zod.z.string()
|
|
11189
|
-
});
|
|
11190
|
-
var DTONotificationProjectInvitationPayload = _zod.z.object({
|
|
11191
|
-
workspaceId: _zod.z.string(),
|
|
11192
|
-
projectId: _zod.z.string(),
|
|
11193
|
-
projectTitle: _zod.z.string(),
|
|
11194
|
-
invitedByUserId: _zod.z.string(),
|
|
11195
|
-
invitationRole: _zod.z.string()
|
|
11196
|
-
});
|
|
11197
|
-
var DTONotificationProjectDocumentCommentPayload = _zod.z.object({
|
|
11198
|
-
documentId: _zod.z.string(),
|
|
11199
|
-
entityTitle: _zod.z.string(),
|
|
11200
|
-
projectId: _zod.z.string(),
|
|
11201
|
-
workspaceId: _zod.z.string(),
|
|
11202
|
-
threadId: _zod.z.string(),
|
|
11203
|
-
commentId: _zod.z.string(),
|
|
11204
|
-
commentCreatedAt: _zod.z.string(),
|
|
11205
|
-
commentAuthorId: _zod.z.string(),
|
|
11206
|
-
commentBody: _zod.z.string()
|
|
11207
|
-
});
|
|
11208
|
-
var DTONotificationBase = _zod.z.object({
|
|
11209
|
-
userId: _zod.z.string(),
|
|
11210
|
-
subjectId: _zod.z.string(),
|
|
11211
|
-
roomId: _zod.z.string().optional(),
|
|
11212
|
-
workspaceId: _zod.z.string()
|
|
11213
|
-
});
|
|
11214
|
-
var DTONotificationCreateInput = _zod.z.discriminatedUnion("type", [
|
|
11215
|
-
_zod.z.object({
|
|
11216
|
-
type: _zod.z.literal(DTONotificationType.enum.ChatMention),
|
|
11217
|
-
activityData: DTONotificationChatMentionPayload
|
|
11218
|
-
}),
|
|
11219
|
-
_zod.z.object({
|
|
11220
|
-
type: _zod.z.literal(DTONotificationType.enum.ProjectInvitation),
|
|
11221
|
-
activityData: DTONotificationProjectInvitationPayload
|
|
11222
|
-
}),
|
|
11223
|
-
_zod.z.object({
|
|
11224
|
-
type: _zod.z.literal(DTONotificationType.enum.ProjectDocumentComment),
|
|
11225
|
-
activityData: DTONotificationProjectDocumentCommentPayload
|
|
11226
|
-
})
|
|
11227
|
-
]).and(DTONotificationBase);
|
|
11228
|
-
|
|
11229
|
-
// src/utils/figma.ts
|
|
11230
|
-
var figmaFileIdRegex = /^[0-9a-zA-Z]{22,128}$/;
|
|
11231
|
-
var nodeIdRegex = /^\d+-\d+$/;
|
|
11232
|
-
var nodeTypeRegex = /^[0-9a-zA-Z]^/;
|
|
11233
|
-
var ParsedFigmaFileURLError = /* @__PURE__ */ ((ParsedFigmaFileURLError2) => {
|
|
11234
|
-
ParsedFigmaFileURLError2["InvalidUrl"] = "InvalidUrl";
|
|
11235
|
-
ParsedFigmaFileURLError2["InvalidFigmaFileId"] = "InvalidFigmaFileId";
|
|
11236
|
-
return ParsedFigmaFileURLError2;
|
|
11237
|
-
})(ParsedFigmaFileURLError || {});
|
|
11238
|
-
var FigmaUtils = {
|
|
11239
|
-
tryParseFigmaFileURL(urlString) {
|
|
11240
|
-
if (!URL.canParse(urlString)) {
|
|
11241
|
-
return { status: "Error", error: "InvalidUrl" /* InvalidUrl */ };
|
|
11242
|
-
}
|
|
11243
|
-
const url = new URL(urlString);
|
|
11244
|
-
if (!url.hostname.endsWith("figma.com")) {
|
|
11245
|
-
return { status: "Error", error: "InvalidUrl" /* InvalidUrl */ };
|
|
11246
|
-
}
|
|
11247
|
-
const pathSegments = url.pathname.split("/");
|
|
11248
|
-
if (pathSegments[1] !== "design" && pathSegments[1] !== "file") {
|
|
11249
|
-
return { status: "Error", error: "InvalidUrl" /* InvalidUrl */ };
|
|
11250
|
-
}
|
|
11251
|
-
const fileId = pathSegments[2];
|
|
11252
|
-
if (!fileId || !fileId.match(figmaFileIdRegex)) {
|
|
11253
|
-
return { status: "Error", error: "InvalidFigmaFileId" /* InvalidFigmaFileId */ };
|
|
11254
|
-
}
|
|
11255
|
-
let fileName = null;
|
|
11256
|
-
const rawFileName = pathSegments[3];
|
|
11257
|
-
if (rawFileName) {
|
|
11258
|
-
fileName = rawFileName.replaceAll("-", " ");
|
|
11259
|
-
}
|
|
11260
|
-
let nodeId = null;
|
|
11261
|
-
const nodeIdRaw = url.searchParams.get("node-id");
|
|
11262
|
-
if (nodeIdRaw && nodeIdRaw.match(nodeIdRegex)) {
|
|
11263
|
-
nodeId = nodeIdRaw.replace("-", ":");
|
|
11264
|
-
}
|
|
11265
|
-
let nodeType = null;
|
|
11266
|
-
const nodeTypeRaw = url.searchParams.get("node-type");
|
|
11267
|
-
if (nodeTypeRaw && nodeTypeRaw.match(nodeTypeRegex)) {
|
|
11268
|
-
nodeType = nodeTypeRaw;
|
|
11269
|
-
}
|
|
11270
|
-
return { status: "Success", fileId, fileName, nodeId, nodeType };
|
|
11271
|
-
}
|
|
11272
|
-
};
|
|
11273
|
-
|
|
11274
|
-
// src/utils/hash.ts
|
|
11275
|
-
function hash(input) {
|
|
11276
|
-
return farmhash(input).toString(16);
|
|
11277
|
-
}
|
|
11278
|
-
function farmhash(input) {
|
|
11279
|
-
const seed = 2654435769;
|
|
11280
|
-
let hash2 = seed;
|
|
11281
|
-
for (let i = 0; i < input.length; i++) {
|
|
11282
|
-
const charCode = input.charCodeAt(i);
|
|
11283
|
-
hash2 ^= charCode;
|
|
11284
|
-
hash2 = Math.imul(hash2, 1540483477);
|
|
11285
|
-
hash2 ^= hash2 >>> 15;
|
|
11286
|
-
}
|
|
11287
|
-
hash2 = Math.imul(hash2, 1540483477);
|
|
11288
|
-
hash2 ^= hash2 >>> 13;
|
|
11289
|
-
hash2 = Math.imul(hash2, 1540483477);
|
|
11290
|
-
hash2 ^= hash2 >>> 15;
|
|
11291
|
-
return hash2 >>> 0;
|
|
11292
|
-
}
|
|
11293
|
-
function prepareObject(obj) {
|
|
11294
|
-
if (obj === null || typeof obj !== "object") {
|
|
11295
|
-
return obj;
|
|
11296
|
-
}
|
|
11297
|
-
if (Array.isArray(obj)) {
|
|
11298
|
-
return obj.map(prepareObject);
|
|
11299
|
-
}
|
|
11300
|
-
const sortedObj = {};
|
|
11301
|
-
for (const key of Object.keys(obj).sort()) {
|
|
11302
|
-
if (obj[key] === null || obj[key] === void 0) {
|
|
11303
|
-
continue;
|
|
11304
|
-
}
|
|
11305
|
-
sortedObj[key] = prepareObject(obj[key]);
|
|
11306
|
-
}
|
|
11307
|
-
return sortedObj;
|
|
11308
|
-
}
|
|
11309
|
-
function generateHash(input, debug = false) {
|
|
11310
|
-
if (typeof input === "object") {
|
|
11311
|
-
const sanitized = JSON.stringify(prepareObject(input));
|
|
11312
|
-
if (debug) {
|
|
11313
|
-
console.log("Hashing sanitized string:");
|
|
11314
|
-
console.log(sanitized);
|
|
11315
|
-
}
|
|
11316
|
-
return hash(sanitized);
|
|
11317
|
-
} else {
|
|
11318
|
-
try {
|
|
11319
|
-
const obj = JSON.parse(input);
|
|
11320
|
-
const sanitized = JSON.stringify(prepareObject(obj));
|
|
11321
|
-
if (debug) {
|
|
11322
|
-
console.log("Hashing sanitized string:");
|
|
11323
|
-
console.log(sanitized);
|
|
11324
|
-
}
|
|
11325
|
-
return hash(sanitized);
|
|
11326
|
-
} catch (e2) {
|
|
11327
|
-
return hash(input);
|
|
11328
|
-
}
|
|
11329
|
-
}
|
|
11330
|
-
}
|
|
11331
|
-
|
|
11332
|
-
// src/utils/redirect-validation.ts
|
|
11333
|
-
var exhaustiveInvalidUriPaths = {
|
|
11334
|
-
emptyPath: "",
|
|
11335
|
-
spacesInPath: "/invalid path/with spaces",
|
|
11336
|
-
specialCharacter1: "/path/with|invalid>characters",
|
|
11337
|
-
specialCharacter2: "/path/with<invalid*characters",
|
|
11338
|
-
specialCharacter3: "/path/{invalid}?characters",
|
|
11339
|
-
consecutiveSlashes: "/path//with///too/many/slashes",
|
|
11340
|
-
unencodedPercent: "/path/with/unencoded%percent",
|
|
11341
|
-
unencodedSpaces: "/path/with unencoded spaces",
|
|
11342
|
-
fragmentIdentifier: "/path/with#fragment",
|
|
11343
|
-
queryParameters: "/path/with?query=parameter",
|
|
11344
|
-
nullCharacter: "/path/with/\0nullcharacter",
|
|
11345
|
-
onlySlash: "/",
|
|
11346
|
-
controlCharacter: "/path/with/control\0character",
|
|
11347
|
-
extremelyLongPath: "/" + "a".repeat(2047),
|
|
11348
|
-
invalidStartCharacter: "///path/starting/with/slashes",
|
|
11349
|
-
invalidStartCharacterColon: ":/path/starting/with/colon",
|
|
11350
|
-
invalidTrailingDot: "/path/ending/with/dot.",
|
|
11351
|
-
invalidPercentEncoding1: "/path/with/%2",
|
|
11352
|
-
invalidPercentEncoding2: "/path/with/%ZZ",
|
|
11353
|
-
invalidPercentEncoding3: "/path/with/%G1",
|
|
11354
|
-
reservedCharacter1: "/path/with?<reserved>",
|
|
11355
|
-
reservedCharacter2: '/path/with/"quotes"',
|
|
11356
|
-
reservedCharacter3: "/path/with/[brackets]",
|
|
11357
|
-
reservedCharacter4: "/path/with/\\backslashes",
|
|
11358
|
-
nonAscii1: "/path/with/\u4F60\u597D",
|
|
11359
|
-
nonAscii2: "/path/with/emoji/\u{1F603}",
|
|
11360
|
-
mixedEncodingPath: "/path/%41A%42B%C3%28",
|
|
11361
|
-
directoryTraversal1: "/path/../../etc/passwd",
|
|
11362
|
-
directoryTraversal2: "/path/./././"
|
|
11363
|
-
};
|
|
11364
|
-
function isValidRedirectPath(path) {
|
|
11365
|
-
const trimmedPath = path.toLowerCase().trim();
|
|
11366
|
-
const url = "https://www.example.com" + trimmedPath;
|
|
11367
|
-
if (url.length > 2048) {
|
|
11368
|
-
return {
|
|
11369
|
-
isValid: false,
|
|
11370
|
-
reason: "TooLong"
|
|
11371
|
-
};
|
|
11372
|
-
}
|
|
11373
|
-
if (trimmedPath === "") {
|
|
11374
|
-
return {
|
|
11375
|
-
isValid: false,
|
|
11376
|
-
reason: "Empty"
|
|
11377
|
-
};
|
|
11378
|
-
}
|
|
11379
|
-
if (url === "/") {
|
|
11380
|
-
return {
|
|
11381
|
-
isValid: false,
|
|
11382
|
-
reason: "Empty"
|
|
11383
|
-
};
|
|
11384
|
-
}
|
|
11385
|
-
if (url.includes("?")) {
|
|
11386
|
-
return {
|
|
11387
|
-
isValid: false,
|
|
11388
|
-
reason: "ContainsQuery"
|
|
11389
|
-
};
|
|
11390
|
-
}
|
|
11391
|
-
if (url.includes("#")) {
|
|
11392
|
-
return {
|
|
11393
|
-
isValid: false,
|
|
11394
|
-
reason: "ContainsFragment"
|
|
11395
|
-
};
|
|
11396
|
-
}
|
|
11397
|
-
const regex = /^\/[A-Za-z0-9_-]+(\/[A-Za-z0-9_-]+)*$/;
|
|
11398
|
-
const isValid = regex.test(trimmedPath);
|
|
11399
|
-
return {
|
|
11400
|
-
isValid: regex.test(trimmedPath),
|
|
11401
|
-
reason: !isValid ? "InvalidURI" : void 0
|
|
11402
|
-
};
|
|
11403
|
-
}
|
|
11404
|
-
|
|
11405
11406
|
// src/api/endpoints/codegen/exporters.ts
|
|
11406
11407
|
var ExportersEndpoint = class {
|
|
11407
11408
|
constructor(requestExecutor) {
|