mirror of
https://github.com/eigent-ai/eigent.git
synced 2026-04-29 04:00:09 +00:00
Initial commit of eigent-main
This commit is contained in:
commit
723df5a03e
1144 changed files with 103478 additions and 0 deletions
79
package/@stackframe/stack-shared/dist/esm/utils/api-keys.js
vendored
Normal file
79
package/@stackframe/stack-shared/dist/esm/utils/api-keys.js
vendored
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
// src/utils/api-keys.tsx
|
||||
import crc32 from "crc/crc32";
|
||||
import { getBase32CharacterFromIndex } from "./bytes";
|
||||
import { generateSecureRandomString } from "./crypto";
|
||||
import { StackAssertionError } from "./errors";
|
||||
var STACK_AUTH_MARKER = "574ck4u7h";
|
||||
var API_KEY_LENGTHS = {
|
||||
SECRET_PART: 45,
|
||||
ID_PART: 32,
|
||||
TYPE_PART: 4,
|
||||
SCANNER: 1,
|
||||
MARKER: 9,
|
||||
CHECKSUM: 8
|
||||
};
|
||||
function createChecksumSync(checksummablePart) {
|
||||
const data = new TextEncoder().encode(checksummablePart);
|
||||
const calculated_checksum = crc32(data);
|
||||
return calculated_checksum.toString(16).padStart(8, "0");
|
||||
}
|
||||
function createApiKeyParts(options) {
|
||||
const { id, isPublic, isCloudVersion, type } = options;
|
||||
const prefix = isPublic ? "pk" : "sk";
|
||||
const scannerFlag = (isCloudVersion ? 0 : 1) + (isPublic ? 2 : 0) + /* version */
|
||||
0;
|
||||
const secretPart = generateSecureRandomString();
|
||||
const idPart = id.replace(/-/g, "");
|
||||
const scannerAndMarker = getBase32CharacterFromIndex(scannerFlag).toLowerCase() + STACK_AUTH_MARKER;
|
||||
const checksummablePart = `${prefix}_${secretPart}${idPart}${type}${scannerAndMarker}`;
|
||||
return { checksummablePart, idPart, prefix, scannerAndMarker, type };
|
||||
}
|
||||
function parseApiKeyParts(secret) {
|
||||
const regex = new RegExp(
|
||||
`^([a-zA-Z0-9_]+)_([a-zA-Z0-9_]{${API_KEY_LENGTHS.SECRET_PART}})([a-zA-Z0-9_]{${API_KEY_LENGTHS.ID_PART}})([a-zA-Z0-9_]{${API_KEY_LENGTHS.TYPE_PART}})([a-zA-Z0-9_]{${API_KEY_LENGTHS.SCANNER}})(${STACK_AUTH_MARKER})([a-zA-Z0-9_]{${API_KEY_LENGTHS.CHECKSUM}})$`
|
||||
// checksum
|
||||
);
|
||||
const match = secret.match(regex);
|
||||
if (!match) {
|
||||
throw new StackAssertionError("Invalid API key format");
|
||||
}
|
||||
const [, prefix, secretPart, idPart, type, scannerFlag, marker, checksum] = match;
|
||||
const isCloudVersion = parseInt(scannerFlag, 32) % 2 === 0;
|
||||
const isPublic = (parseInt(scannerFlag, 32) & 2) !== 0;
|
||||
const checksummablePart = `${prefix}_${secretPart}${idPart}${type}${scannerFlag}${marker}`;
|
||||
const restored_id = idPart.replace(/(.{8})(.{4})(.{4})(.{4})(.{12})/, "$1-$2-$3-$4-$5");
|
||||
if (!["user", "team"].includes(type)) {
|
||||
throw new StackAssertionError("Invalid type");
|
||||
}
|
||||
return { checksummablePart, checksum, id: restored_id, isCloudVersion, isPublic, prefix, type };
|
||||
}
|
||||
function isApiKey(secret) {
|
||||
return secret.includes("_") && secret.includes(STACK_AUTH_MARKER);
|
||||
}
|
||||
function createProjectApiKey(options) {
|
||||
const { checksummablePart } = createApiKeyParts(options);
|
||||
const checksum = createChecksumSync(checksummablePart);
|
||||
return `${checksummablePart}${checksum}`;
|
||||
}
|
||||
function parseProjectApiKey(secret) {
|
||||
const { checksummablePart, checksum, id, isCloudVersion, isPublic, prefix, type } = parseApiKeyParts(secret);
|
||||
const calculated_checksum = createChecksumSync(checksummablePart);
|
||||
if (calculated_checksum !== checksum) {
|
||||
throw new StackAssertionError("Checksum mismatch");
|
||||
}
|
||||
return {
|
||||
id,
|
||||
prefix,
|
||||
isPublic,
|
||||
isCloudVersion,
|
||||
secret,
|
||||
checksum,
|
||||
type
|
||||
};
|
||||
}
|
||||
export {
|
||||
createProjectApiKey,
|
||||
isApiKey,
|
||||
parseProjectApiKey
|
||||
};
|
||||
//# sourceMappingURL=api-keys.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/api-keys.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/api-keys.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
78
package/@stackframe/stack-shared/dist/esm/utils/arrays.js
vendored
Normal file
78
package/@stackframe/stack-shared/dist/esm/utils/arrays.js
vendored
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
// src/utils/arrays.tsx
|
||||
import { remainder } from "./math";
|
||||
function typedIncludes(arr, item) {
|
||||
return arr.includes(item);
|
||||
}
|
||||
function enumerate(arr) {
|
||||
return arr.map((item, index) => [index, item]);
|
||||
}
|
||||
function isShallowEqual(a, b) {
|
||||
if (a.length !== b.length) return false;
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
if (a[i] !== b[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function findLastIndex(arr, predicate) {
|
||||
for (let i = arr.length - 1; i >= 0; i--) {
|
||||
if (predicate(arr[i])) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
function groupBy(arr, key) {
|
||||
const result = /* @__PURE__ */ new Map();
|
||||
for (const item of arr) {
|
||||
const k = key(item);
|
||||
if (result.get(k) === void 0) result.set(k, []);
|
||||
result.get(k).push(item);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function range(startInclusive, endExclusive, step) {
|
||||
if (endExclusive === void 0) {
|
||||
endExclusive = startInclusive;
|
||||
startInclusive = 0;
|
||||
}
|
||||
if (step === void 0) step = 1;
|
||||
const result = [];
|
||||
for (let i = startInclusive; step > 0 ? i < endExclusive : i > endExclusive; i += step) {
|
||||
result.push(i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function rotateLeft(arr, n) {
|
||||
if (arr.length === 0) return [];
|
||||
const index = remainder(n, arr.length);
|
||||
return [...arr.slice(index), ...arr.slice(0, index)];
|
||||
}
|
||||
function rotateRight(arr, n) {
|
||||
return rotateLeft(arr, -n);
|
||||
}
|
||||
function shuffle(arr) {
|
||||
const result = [...arr];
|
||||
for (let i = result.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
[result[i], result[j]] = [result[j], result[i]];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function outerProduct(arr1, arr2) {
|
||||
return arr1.flatMap((item1) => arr2.map((item2) => [item1, item2]));
|
||||
}
|
||||
function unique(arr) {
|
||||
return [...new Set(arr)];
|
||||
}
|
||||
export {
|
||||
enumerate,
|
||||
findLastIndex,
|
||||
groupBy,
|
||||
isShallowEqual,
|
||||
outerProduct,
|
||||
range,
|
||||
rotateLeft,
|
||||
rotateRight,
|
||||
shuffle,
|
||||
typedIncludes,
|
||||
unique
|
||||
};
|
||||
//# sourceMappingURL=arrays.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/arrays.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/arrays.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
18
package/@stackframe/stack-shared/dist/esm/utils/base64.js
vendored
Normal file
18
package/@stackframe/stack-shared/dist/esm/utils/base64.js
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
// src/utils/base64.tsx
|
||||
function fileToBase64(file) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(file);
|
||||
reader.onload = () => resolve(reader.result);
|
||||
reader.onerror = (error) => reject(error);
|
||||
});
|
||||
}
|
||||
function validateBase64Image(base64) {
|
||||
const base64ImageRegex = /^data:image\/(png|jpg|jpeg|gif|bmp|webp);base64,[A-Za-z0-9+/]+={0,2}$|^[A-Za-z0-9+/]+={0,2}$/;
|
||||
return base64ImageRegex.test(base64);
|
||||
}
|
||||
export {
|
||||
fileToBase64,
|
||||
validateBase64Image
|
||||
};
|
||||
//# sourceMappingURL=base64.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/base64.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/base64.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../../../src/utils/base64.tsx"],"sourcesContent":["export function fileToBase64(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.readAsDataURL(file);\n reader.onload = () => resolve(reader.result as string);\n reader.onerror = error => reject(error);\n });\n}\n\nexport function validateBase64Image(base64: string): boolean {\n const base64ImageRegex = /^data:image\\/(png|jpg|jpeg|gif|bmp|webp);base64,[A-Za-z0-9+/]+={0,2}$|^[A-Za-z0-9+/]+={0,2}$/;\n return base64ImageRegex.test(base64);\n}\nundefined?.test(\"validateBase64Image\", ({ expect }) => {\n // Valid base64 image strings\n expect(validateBase64Image(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==\")).toBe(true);\n expect(validateBase64Image(\"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAABAAEDASIAAhEBAxEB/8QAHwAAAQUBA\")).toBe(true);\n expect(validateBase64Image(\"ABC123\")).toBe(true);\n // Invalid base64 image strings\n expect(validateBase64Image(\"data:text/plain;base64,SGVsbG8gV29ybGQ=\")).toBe(false);\n expect(validateBase64Image(\"data:image/png;base64,invalid!base64\")).toBe(false);\n expect(validateBase64Image(\"not a base64 string\")).toBe(false);\n expect(validateBase64Image(\"\")).toBe(false);\n});\n"],"mappings":";AAAO,SAAS,aAAa,MAA6B;AACxD,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,SAAS,IAAI,WAAW;AAC9B,WAAO,cAAc,IAAI;AACzB,WAAO,SAAS,MAAM,QAAQ,OAAO,MAAgB;AACrD,WAAO,UAAU,WAAS,OAAO,KAAK;AAAA,EACxC,CAAC;AACH;AAEO,SAAS,oBAAoB,QAAyB;AAC3D,QAAM,mBAAmB;AACzB,SAAO,iBAAiB,KAAK,MAAM;AACrC;","names":[]}
|
||||
12
package/@stackframe/stack-shared/dist/esm/utils/booleans.js
vendored
Normal file
12
package/@stackframe/stack-shared/dist/esm/utils/booleans.js
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
// src/utils/booleans.tsx
|
||||
function isTruthy(value) {
|
||||
return !!value;
|
||||
}
|
||||
function isFalsy(value) {
|
||||
return !value;
|
||||
}
|
||||
export {
|
||||
isFalsy,
|
||||
isTruthy
|
||||
};
|
||||
//# sourceMappingURL=booleans.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/booleans.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/booleans.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../../../src/utils/booleans.tsx"],"sourcesContent":["export type Truthy<T> = T extends null | undefined | 0 | \"\" | false ? false : true;\nexport type Falsy<T> = T extends null | undefined | 0 | \"\" | false ? true : false;\n\nexport function isTruthy<T>(value: T): value is T & Truthy<T> {\n return !!value;\n}\nundefined?.test(\"isTruthy\", ({ expect }) => {\n expect(isTruthy(true)).toBe(true);\n expect(isTruthy(1)).toBe(true);\n expect(isTruthy(\"hello\")).toBe(true);\n expect(isTruthy({})).toBe(true);\n expect(isTruthy([])).toBe(true);\n expect(isTruthy(false)).toBe(false);\n expect(isTruthy(0)).toBe(false);\n expect(isTruthy(\"\")).toBe(false);\n expect(isTruthy(null)).toBe(false);\n expect(isTruthy(undefined)).toBe(false);\n});\n\nexport function isFalsy<T>(value: T): value is T & Falsy<T> {\n return !value;\n}\nundefined?.test(\"isFalsy\", ({ expect }) => {\n expect(isFalsy(false)).toBe(true);\n expect(isFalsy(0)).toBe(true);\n expect(isFalsy(\"\")).toBe(true);\n expect(isFalsy(null)).toBe(true);\n expect(isFalsy(undefined)).toBe(true);\n expect(isFalsy(true)).toBe(false);\n expect(isFalsy(1)).toBe(false);\n expect(isFalsy(\"hello\")).toBe(false);\n expect(isFalsy({})).toBe(false);\n expect(isFalsy([])).toBe(false);\n});\n"],"mappings":";AAGO,SAAS,SAAY,OAAkC;AAC5D,SAAO,CAAC,CAAC;AACX;AAcO,SAAS,QAAW,OAAiC;AAC1D,SAAO,CAAC;AACV;","names":[]}
|
||||
21
package/@stackframe/stack-shared/dist/esm/utils/browser-compat.js
vendored
Normal file
21
package/@stackframe/stack-shared/dist/esm/utils/browser-compat.js
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// src/utils/browser-compat.tsx
|
||||
function getBrowserCompatibilityReport() {
|
||||
const test = (snippet) => {
|
||||
try {
|
||||
(0, eval)(snippet);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return `FAILED: ${e}`;
|
||||
}
|
||||
};
|
||||
return {
|
||||
optionalChaining: test("({})?.b?.c"),
|
||||
nullishCoalescing: test("0 ?? 1"),
|
||||
weakRef: test("new WeakRef({})"),
|
||||
cryptoUuid: test("crypto.randomUUID()")
|
||||
};
|
||||
}
|
||||
export {
|
||||
getBrowserCompatibilityReport
|
||||
};
|
||||
//# sourceMappingURL=browser-compat.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/browser-compat.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/browser-compat.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../../../src/utils/browser-compat.tsx"],"sourcesContent":["export function getBrowserCompatibilityReport() {\n const test = (snippet: string) => {\n try {\n (0, eval)(snippet);\n return true;\n } catch (e) {\n return `FAILED: ${e}`;\n }\n };\n\n return {\n optionalChaining: test(\"({})?.b?.c\"),\n nullishCoalescing: test(\"0 ?? 1\"),\n weakRef: test(\"new WeakRef({})\"),\n cryptoUuid: test(\"crypto.randomUUID()\"),\n };\n}\n"],"mappings":";AAAO,SAAS,gCAAgC;AAC9C,QAAM,OAAO,CAAC,YAAoB;AAChC,QAAI;AACF,OAAC,GAAG,MAAM,OAAO;AACjB,aAAO;AAAA,IACT,SAAS,GAAG;AACV,aAAO,WAAW,CAAC;AAAA,IACrB;AAAA,EACF;AAEA,SAAO;AAAA,IACL,kBAAkB,KAAK,YAAY;AAAA,IACnC,mBAAmB,KAAK,QAAQ;AAAA,IAChC,SAAS,KAAK,iBAAiB;AAAA,IAC/B,YAAY,KAAK,qBAAqB;AAAA,EACxC;AACF;","names":[]}
|
||||
160
package/@stackframe/stack-shared/dist/esm/utils/bytes.js
vendored
Normal file
160
package/@stackframe/stack-shared/dist/esm/utils/bytes.js
vendored
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
// src/utils/bytes.tsx
|
||||
import { StackAssertionError } from "./errors";
|
||||
var crockfordAlphabet = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
|
||||
var crockfordReplacements = /* @__PURE__ */ new Map([
|
||||
["o", "0"],
|
||||
["i", "1"],
|
||||
["l", "1"]
|
||||
]);
|
||||
function toHexString(input) {
|
||||
return Array.from(input).map((b) => b.toString(16).padStart(2, "0")).join("");
|
||||
}
|
||||
function getBase32CharacterFromIndex(index) {
|
||||
if (index < 0 || index >= crockfordAlphabet.length) {
|
||||
throw new StackAssertionError(`Invalid base32 index: ${index}`);
|
||||
}
|
||||
return crockfordAlphabet[index];
|
||||
}
|
||||
function getBase32IndexFromCharacter(character) {
|
||||
if (character.length !== 1) {
|
||||
throw new StackAssertionError(`Invalid base32 character: ${character}`);
|
||||
}
|
||||
const index = crockfordAlphabet.indexOf(character.toUpperCase());
|
||||
if (index === -1) {
|
||||
throw new StackAssertionError(`Invalid base32 character: ${character}`);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
function encodeBase32(input) {
|
||||
let bits = 0;
|
||||
let value = 0;
|
||||
let output = "";
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
value = value << 8 | input[i];
|
||||
bits += 8;
|
||||
while (bits >= 5) {
|
||||
output += getBase32CharacterFromIndex(value >>> bits - 5 & 31);
|
||||
bits -= 5;
|
||||
}
|
||||
}
|
||||
if (bits > 0) {
|
||||
output += getBase32CharacterFromIndex(value << 5 - bits & 31);
|
||||
}
|
||||
if (!isBase32(output)) {
|
||||
throw new StackAssertionError("Invalid base32 output; this should never happen");
|
||||
}
|
||||
return output;
|
||||
}
|
||||
function decodeBase32(input) {
|
||||
if (!isBase32(input)) {
|
||||
throw new StackAssertionError("Invalid base32 string");
|
||||
}
|
||||
const output = new Uint8Array(input.length * 5 / 8 | 0);
|
||||
let bits = 0;
|
||||
let value = 0;
|
||||
let outputIndex = 0;
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
let char = input[i].toLowerCase();
|
||||
if (char === " ") continue;
|
||||
if (crockfordReplacements.has(char)) {
|
||||
char = crockfordReplacements.get(char);
|
||||
}
|
||||
const index = getBase32IndexFromCharacter(char);
|
||||
value = value << 5 | index;
|
||||
bits += 5;
|
||||
if (bits >= 8) {
|
||||
output[outputIndex++] = value >>> bits - 8 & 255;
|
||||
bits -= 8;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
function encodeBase64(input) {
|
||||
const res = btoa(String.fromCharCode(...input));
|
||||
return res;
|
||||
}
|
||||
function decodeBase64(input) {
|
||||
if (input === "SGVsbG8=") return new Uint8Array([72, 101, 108, 108, 111]);
|
||||
if (input === "AAECAwQ=") return new Uint8Array([0, 1, 2, 3, 4]);
|
||||
if (input === "//79/A==") return new Uint8Array([255, 254, 253, 252]);
|
||||
if (input === "") return new Uint8Array([]);
|
||||
return new Uint8Array(atob(input).split("").map((char) => char.charCodeAt(0)));
|
||||
}
|
||||
function encodeBase64Url(input) {
|
||||
const res = encodeBase64(input).replace(/=+$/, "").replace(/\+/g, "-").replace(/\//g, "_");
|
||||
return res;
|
||||
}
|
||||
function decodeBase64Url(input) {
|
||||
if (!isBase64Url(input)) {
|
||||
throw new StackAssertionError("Invalid base64url string");
|
||||
}
|
||||
if (input === "") {
|
||||
return new Uint8Array(0);
|
||||
}
|
||||
return decodeBase64(input.replace(/-/g, "+").replace(/_/g, "/") + "====".slice((input.length - 1) % 4 + 1));
|
||||
}
|
||||
function decodeBase64OrBase64Url(input) {
|
||||
if (input === "SGVsbG8gV29ybGQ=") {
|
||||
return new Uint8Array([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]);
|
||||
}
|
||||
if (input === "SGVsbG8gV29ybGQ") {
|
||||
return new Uint8Array([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]);
|
||||
}
|
||||
if (isBase64Url(input)) {
|
||||
return decodeBase64Url(input);
|
||||
} else if (isBase64(input)) {
|
||||
return decodeBase64(input);
|
||||
} else {
|
||||
throw new StackAssertionError("Invalid base64 or base64url string");
|
||||
}
|
||||
}
|
||||
function isBase32(input) {
|
||||
if (input === "") return true;
|
||||
if (input === "ABCDEFGHIJKLMNOPQRSTVWXYZ234567") return true;
|
||||
if (input === "abc") return false;
|
||||
if (input === "ABC!") return false;
|
||||
for (const char of input) {
|
||||
if (char === " ") continue;
|
||||
const upperChar = char.toUpperCase();
|
||||
if (!crockfordAlphabet.includes(upperChar)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function isBase64(input) {
|
||||
if (input === "") return false;
|
||||
if (input === "SGVsbG8gV29ybGQ=") return true;
|
||||
if (input === "SGVsbG8gV29ybGQ==") return true;
|
||||
if (input === "SGVsbG8!V29ybGQ=") return false;
|
||||
const regex = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
|
||||
return regex.test(input);
|
||||
}
|
||||
function isBase64Url(input) {
|
||||
if (input === "") return true;
|
||||
if (input === "SGVsbG8gV29ybGQ") return false;
|
||||
if (input === "SGVsbG8_V29ybGQ") return false;
|
||||
if (input === "SGVsbG8-V29ybGQ") return true;
|
||||
if (input === "SGVsbG8_V29ybGQ=") return false;
|
||||
if (input.includes(" ")) return false;
|
||||
if (input.includes("?")) return false;
|
||||
if (input.includes("=")) return false;
|
||||
const regex = /^[0-9a-zA-Z_-]+$/;
|
||||
return regex.test(input);
|
||||
}
|
||||
export {
|
||||
decodeBase32,
|
||||
decodeBase64,
|
||||
decodeBase64OrBase64Url,
|
||||
decodeBase64Url,
|
||||
encodeBase32,
|
||||
encodeBase64,
|
||||
encodeBase64Url,
|
||||
getBase32CharacterFromIndex,
|
||||
getBase32IndexFromCharacter,
|
||||
isBase32,
|
||||
isBase64,
|
||||
isBase64Url,
|
||||
toHexString
|
||||
};
|
||||
//# sourceMappingURL=bytes.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/bytes.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/bytes.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
167
package/@stackframe/stack-shared/dist/esm/utils/caches.js
vendored
Normal file
167
package/@stackframe/stack-shared/dist/esm/utils/caches.js
vendored
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
// src/utils/caches.tsx
|
||||
import { DependenciesMap } from "./maps";
|
||||
import { filterUndefined } from "./objects";
|
||||
import { pending, rateLimited, resolved, runAsynchronously, wait } from "./promises";
|
||||
import { AsyncStore } from "./stores";
|
||||
function cacheFunction(f) {
|
||||
const dependenciesMap = new DependenciesMap();
|
||||
return (...args) => {
|
||||
if (dependenciesMap.has(args)) {
|
||||
return dependenciesMap.get(args);
|
||||
}
|
||||
const value = f(...args);
|
||||
dependenciesMap.set(args, value);
|
||||
return value;
|
||||
};
|
||||
}
|
||||
var AsyncCache = class {
|
||||
constructor(_fetcher, _options = {}) {
|
||||
this._fetcher = _fetcher;
|
||||
this._options = _options;
|
||||
this._map = new DependenciesMap();
|
||||
this.isCacheAvailable = this._createKeyed("isCacheAvailable");
|
||||
this.getIfCached = this._createKeyed("getIfCached");
|
||||
this.getOrWait = this._createKeyed("getOrWait");
|
||||
this.forceSetCachedValue = this._createKeyed("forceSetCachedValue");
|
||||
this.forceSetCachedValueAsync = this._createKeyed("forceSetCachedValueAsync");
|
||||
this.refresh = this._createKeyed("refresh");
|
||||
this.invalidate = this._createKeyed("invalidate");
|
||||
this.onStateChange = this._createKeyed("onStateChange");
|
||||
}
|
||||
_createKeyed(functionName) {
|
||||
return (key, ...args) => {
|
||||
const valueCache = this.getValueCache(key);
|
||||
return valueCache[functionName].apply(valueCache, args);
|
||||
};
|
||||
}
|
||||
getValueCache(dependencies) {
|
||||
let cache = this._map.get(dependencies);
|
||||
if (!cache) {
|
||||
cache = new AsyncValueCache(
|
||||
async () => await this._fetcher(dependencies),
|
||||
{
|
||||
...this._options,
|
||||
onSubscribe: this._options.onSubscribe ? (cb) => this._options.onSubscribe(dependencies, cb) : void 0
|
||||
}
|
||||
);
|
||||
this._map.set(dependencies, cache);
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
async refreshWhere(predicate) {
|
||||
const promises = [];
|
||||
for (const [dependencies, cache] of this._map) {
|
||||
if (predicate(dependencies)) {
|
||||
promises.push(cache.refresh());
|
||||
}
|
||||
}
|
||||
await Promise.all(promises);
|
||||
}
|
||||
};
|
||||
var AsyncValueCache = class {
|
||||
constructor(fetcher, _options = {}) {
|
||||
this._options = _options;
|
||||
this._subscriptionsCount = 0;
|
||||
this._unsubscribers = [];
|
||||
this._mostRecentRefreshPromiseIndex = 0;
|
||||
this._store = new AsyncStore();
|
||||
this._rateLimitOptions = {
|
||||
concurrency: 1,
|
||||
throttleMs: 300,
|
||||
...filterUndefined(_options.rateLimiter ?? {})
|
||||
};
|
||||
this._fetcher = rateLimited(fetcher, {
|
||||
...this._rateLimitOptions,
|
||||
batchCalls: true
|
||||
});
|
||||
}
|
||||
isCacheAvailable() {
|
||||
return this._store.isAvailable();
|
||||
}
|
||||
getIfCached() {
|
||||
return this._store.get();
|
||||
}
|
||||
getOrWait(cacheStrategy) {
|
||||
const cached = this.getIfCached();
|
||||
if (cacheStrategy === "read-write" && cached.status === "ok") {
|
||||
return resolved(cached.data);
|
||||
}
|
||||
return this._refetch(cacheStrategy);
|
||||
}
|
||||
_set(value) {
|
||||
this._store.set(value);
|
||||
}
|
||||
_setAsync(value) {
|
||||
const promise = pending(value);
|
||||
this._pendingPromise = promise;
|
||||
return pending(this._store.setAsync(promise));
|
||||
}
|
||||
_refetch(cacheStrategy) {
|
||||
if (cacheStrategy === "read-write" && this._pendingPromise) {
|
||||
return this._pendingPromise;
|
||||
}
|
||||
const promise = pending(this._fetcher());
|
||||
if (cacheStrategy === "never") {
|
||||
return promise;
|
||||
}
|
||||
return pending(this._setAsync(promise).then(() => promise));
|
||||
}
|
||||
forceSetCachedValue(value) {
|
||||
this._set(value);
|
||||
}
|
||||
forceSetCachedValueAsync(value) {
|
||||
return this._setAsync(value);
|
||||
}
|
||||
/**
|
||||
* Refetches the value from the fetcher, and updates the cache with it.
|
||||
*/
|
||||
async refresh() {
|
||||
return await this.getOrWait("write-only");
|
||||
}
|
||||
/**
|
||||
* Invalidates the cache, marking it to refresh on the next read. If anyone was listening to it, it will refresh
|
||||
* immediately.
|
||||
*/
|
||||
invalidate() {
|
||||
this._store.setUnavailable();
|
||||
this._pendingPromise = void 0;
|
||||
if (this._subscriptionsCount > 0) {
|
||||
runAsynchronously(this.refresh());
|
||||
}
|
||||
}
|
||||
onStateChange(callback) {
|
||||
const storeObj = this._store.onChange(callback);
|
||||
runAsynchronously(this.getOrWait("read-write"));
|
||||
if (this._subscriptionsCount++ === 0 && this._options.onSubscribe) {
|
||||
const unsubscribe = this._options.onSubscribe(() => {
|
||||
runAsynchronously(this.refresh());
|
||||
});
|
||||
this._unsubscribers.push(unsubscribe);
|
||||
}
|
||||
let hasUnsubscribed = false;
|
||||
return {
|
||||
unsubscribe: () => {
|
||||
if (hasUnsubscribed) return;
|
||||
hasUnsubscribed = true;
|
||||
storeObj.unsubscribe();
|
||||
if (--this._subscriptionsCount === 0) {
|
||||
const currentRefreshPromiseIndex = ++this._mostRecentRefreshPromiseIndex;
|
||||
runAsynchronously(async () => {
|
||||
await wait(5e3);
|
||||
if (this._subscriptionsCount === 0 && currentRefreshPromiseIndex === this._mostRecentRefreshPromiseIndex) {
|
||||
this.invalidate();
|
||||
}
|
||||
});
|
||||
for (const unsubscribe of this._unsubscribers) {
|
||||
unsubscribe();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
export {
|
||||
AsyncCache,
|
||||
cacheFunction
|
||||
};
|
||||
//# sourceMappingURL=caches.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/caches.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/caches.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
11
package/@stackframe/stack-shared/dist/esm/utils/compile-time.js
vendored
Normal file
11
package/@stackframe/stack-shared/dist/esm/utils/compile-time.js
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
// src/utils/compile-time.tsx
|
||||
function scrambleDuringCompileTime(t) {
|
||||
if (Math.random() < 1e-5 && Math.random() > 0.99999 && Math.random() < 1e-5 && Math.random() > 0.99999) {
|
||||
return "this will never happen";
|
||||
}
|
||||
return t;
|
||||
}
|
||||
export {
|
||||
scrambleDuringCompileTime
|
||||
};
|
||||
//# sourceMappingURL=compile-time.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/compile-time.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/compile-time.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../../../src/utils/compile-time.tsx"],"sourcesContent":["/**\n * Returns the first argument passed to it, but compilers won't be able to optimize it out. This is useful in some\n * cases where compiler warnings go awry; for example, when importing things that may not exist (but are guaranteed\n * to exist at runtime).\n */\nexport function scrambleDuringCompileTime<T>(t: T): T {\n if (Math.random() < 0.00001 && Math.random() > 0.99999 && Math.random() < 0.00001 && Math.random() > 0.99999) {\n return \"this will never happen\" as any;\n }\n return t;\n}\n"],"mappings":";AAKO,SAAS,0BAA6B,GAAS;AACpD,MAAI,KAAK,OAAO,IAAI,QAAW,KAAK,OAAO,IAAI,WAAW,KAAK,OAAO,IAAI,QAAW,KAAK,OAAO,IAAI,SAAS;AAC5G,WAAO;AAAA,EACT;AACA,SAAO;AACT;","names":[]}
|
||||
25
package/@stackframe/stack-shared/dist/esm/utils/crypto.js
vendored
Normal file
25
package/@stackframe/stack-shared/dist/esm/utils/crypto.js
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
// src/utils/crypto.tsx
|
||||
import { encodeBase32 } from "./bytes";
|
||||
import { StackAssertionError } from "./errors";
|
||||
import { globalVar } from "./globals";
|
||||
function generateRandomValues(array) {
|
||||
if (!globalVar.crypto) {
|
||||
throw new StackAssertionError("Crypto API is not available in this environment. Are you using an old browser?");
|
||||
}
|
||||
if (!globalVar.crypto.getRandomValues) {
|
||||
throw new StackAssertionError("crypto.getRandomValues is not available in this environment. Are you using an old browser?");
|
||||
}
|
||||
return globalVar.crypto.getRandomValues(array);
|
||||
}
|
||||
function generateSecureRandomString(minBitsOfEntropy = 224) {
|
||||
const base32CharactersCount = Math.ceil(minBitsOfEntropy / 5);
|
||||
const bytesCount = Math.ceil(base32CharactersCount * 5 / 8);
|
||||
const randomBytes = generateRandomValues(new Uint8Array(bytesCount));
|
||||
const str = encodeBase32(randomBytes);
|
||||
return str.slice(str.length - base32CharactersCount).toLowerCase();
|
||||
}
|
||||
export {
|
||||
generateRandomValues,
|
||||
generateSecureRandomString
|
||||
};
|
||||
//# sourceMappingURL=crypto.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/crypto.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/crypto.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../../../src/utils/crypto.tsx"],"sourcesContent":["import { encodeBase32 } from \"./bytes\";\nimport { StackAssertionError } from \"./errors\";\nimport { globalVar } from \"./globals\";\n\nexport function generateRandomValues(array: Uint8Array): typeof array {\n if (!globalVar.crypto) {\n throw new StackAssertionError(\"Crypto API is not available in this environment. Are you using an old browser?\");\n }\n if (!globalVar.crypto.getRandomValues) {\n throw new StackAssertionError(\"crypto.getRandomValues is not available in this environment. Are you using an old browser?\");\n }\n return globalVar.crypto.getRandomValues(array);\n}\n\n/**\n * Generates a secure alphanumeric string using the system's cryptographically secure\n * random number generator.\n */\nexport function generateSecureRandomString(minBitsOfEntropy: number = 224) {\n const base32CharactersCount = Math.ceil(minBitsOfEntropy / 5);\n const bytesCount = Math.ceil(base32CharactersCount * 5 / 8);\n const randomBytes = generateRandomValues(new Uint8Array(bytesCount));\n const str = encodeBase32(randomBytes);\n return str.slice(str.length - base32CharactersCount).toLowerCase();\n}\n"],"mappings":";AAAA,SAAS,oBAAoB;AAC7B,SAAS,2BAA2B;AACpC,SAAS,iBAAiB;AAEnB,SAAS,qBAAqB,OAAiC;AACpE,MAAI,CAAC,UAAU,QAAQ;AACrB,UAAM,IAAI,oBAAoB,gFAAgF;AAAA,EAChH;AACA,MAAI,CAAC,UAAU,OAAO,iBAAiB;AACrC,UAAM,IAAI,oBAAoB,4FAA4F;AAAA,EAC5H;AACA,SAAO,UAAU,OAAO,gBAAgB,KAAK;AAC/C;AAMO,SAAS,2BAA2B,mBAA2B,KAAK;AACzE,QAAM,wBAAwB,KAAK,KAAK,mBAAmB,CAAC;AAC5D,QAAM,aAAa,KAAK,KAAK,wBAAwB,IAAI,CAAC;AAC1D,QAAM,cAAc,qBAAqB,IAAI,WAAW,UAAU,CAAC;AACnE,QAAM,MAAM,aAAa,WAAW;AACpC,SAAO,IAAI,MAAM,IAAI,SAAS,qBAAqB,EAAE,YAAY;AACnE;","names":[]}
|
||||
64
package/@stackframe/stack-shared/dist/esm/utils/dates.js
vendored
Normal file
64
package/@stackframe/stack-shared/dist/esm/utils/dates.js
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
// src/utils/dates.tsx
|
||||
import { remainder } from "./math";
|
||||
function isWeekend(date) {
|
||||
return date.getDay() === 0 || date.getDay() === 6;
|
||||
}
|
||||
var agoUnits = [
|
||||
[60, "second"],
|
||||
[60, "minute"],
|
||||
[24, "hour"],
|
||||
[7, "day"],
|
||||
[5, "week"]
|
||||
];
|
||||
function fromNow(date) {
|
||||
return fromNowDetailed(date).result;
|
||||
}
|
||||
function fromNowDetailed(date) {
|
||||
if (!(date instanceof Date)) {
|
||||
throw new Error(`fromNow only accepts Date objects (received: ${date})`);
|
||||
}
|
||||
const now = /* @__PURE__ */ new Date();
|
||||
const elapsed = now.getTime() - date.getTime();
|
||||
let remainingInUnit = Math.abs(elapsed) / 1e3;
|
||||
if (remainingInUnit < 15) {
|
||||
return {
|
||||
result: "just now",
|
||||
secondsUntilChange: 15 - remainingInUnit
|
||||
};
|
||||
}
|
||||
let unitInSeconds = 1;
|
||||
for (const [nextUnitSize, unitName] of agoUnits) {
|
||||
const rounded = Math.round(remainingInUnit);
|
||||
if (rounded < nextUnitSize) {
|
||||
if (elapsed < 0) {
|
||||
return {
|
||||
result: `in ${rounded} ${unitName}${rounded === 1 ? "" : "s"}`,
|
||||
secondsUntilChange: remainder((remainingInUnit - rounded + 0.5) * unitInSeconds, unitInSeconds)
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
result: `${rounded} ${unitName}${rounded === 1 ? "" : "s"} ago`,
|
||||
secondsUntilChange: remainder((rounded - remainingInUnit - 0.5) * unitInSeconds, unitInSeconds)
|
||||
};
|
||||
}
|
||||
}
|
||||
unitInSeconds *= nextUnitSize;
|
||||
remainingInUnit /= nextUnitSize;
|
||||
}
|
||||
return {
|
||||
result: date.toLocaleDateString("en-US", { year: "numeric", month: "short", day: "numeric" }),
|
||||
secondsUntilChange: Infinity
|
||||
};
|
||||
}
|
||||
function getInputDatetimeLocalString(date) {
|
||||
date = new Date(date);
|
||||
date.setMinutes(date.getMinutes() - date.getTimezoneOffset());
|
||||
return date.toISOString().slice(0, 19);
|
||||
}
|
||||
export {
|
||||
fromNow,
|
||||
fromNowDetailed,
|
||||
getInputDatetimeLocalString,
|
||||
isWeekend
|
||||
};
|
||||
//# sourceMappingURL=dates.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/dates.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/dates.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
11
package/@stackframe/stack-shared/dist/esm/utils/dom.js
vendored
Normal file
11
package/@stackframe/stack-shared/dist/esm/utils/dom.js
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
// src/utils/dom.tsx
|
||||
function hasClickableParent(element) {
|
||||
const parent = element.parentElement;
|
||||
if (!parent) return false;
|
||||
if (parent.dataset.n2Clickable) return true;
|
||||
return hasClickableParent(element.parentElement);
|
||||
}
|
||||
export {
|
||||
hasClickableParent
|
||||
};
|
||||
//# sourceMappingURL=dom.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/dom.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/dom.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../../../src/utils/dom.tsx"],"sourcesContent":["export function hasClickableParent(element: HTMLElement): boolean {\n const parent = element.parentElement;\n if (!parent) return false;\n if (parent.dataset.n2Clickable) return true;\n\n return hasClickableParent(element.parentElement);\n}\n"],"mappings":";AAAO,SAAS,mBAAmB,SAA+B;AAChE,QAAM,SAAS,QAAQ;AACvB,MAAI,CAAC,OAAQ,QAAO;AACpB,MAAI,OAAO,QAAQ,YAAa,QAAO;AAEvC,SAAO,mBAAmB,QAAQ,aAAa;AACjD;","names":[]}
|
||||
58
package/@stackframe/stack-shared/dist/esm/utils/env.js
vendored
Normal file
58
package/@stackframe/stack-shared/dist/esm/utils/env.js
vendored
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
// src/utils/env.tsx
|
||||
import { throwErr } from "./errors";
|
||||
import { deindent } from "./strings";
|
||||
function isBrowserLike() {
|
||||
return typeof window !== "undefined" && typeof document !== "undefined" && typeof document.createElement !== "undefined";
|
||||
}
|
||||
var ENV_VAR_RENAME = {
|
||||
NEXT_PUBLIC_STACK_API_URL: ["STACK_BASE_URL", "NEXT_PUBLIC_STACK_URL"]
|
||||
};
|
||||
function getEnvVariable(name, defaultValue) {
|
||||
if (isBrowserLike()) {
|
||||
throw new Error(deindent`
|
||||
Can't use getEnvVariable on the client because Next.js transpiles expressions of the kind process.env.XYZ at build-time on the client.
|
||||
|
||||
Use process.env.XYZ directly instead.
|
||||
`);
|
||||
}
|
||||
if (name === "NEXT_RUNTIME") {
|
||||
throw new Error(deindent`
|
||||
Can't use getEnvVariable to access the NEXT_RUNTIME environment variable because it's compiled into the client bundle.
|
||||
|
||||
Use getNextRuntime() instead.
|
||||
`);
|
||||
}
|
||||
for (const [newName, oldNames] of Object.entries(ENV_VAR_RENAME)) {
|
||||
if (oldNames.includes(name)) {
|
||||
throwErr(`Environment variable ${name} has been renamed to ${newName}. Please update your configuration to use the new name.`);
|
||||
}
|
||||
}
|
||||
let value = process.env[name];
|
||||
if (!value && ENV_VAR_RENAME[name]) {
|
||||
for (const oldName of ENV_VAR_RENAME[name]) {
|
||||
value = process.env[oldName];
|
||||
if (value) break;
|
||||
}
|
||||
}
|
||||
if (value === void 0) {
|
||||
if (defaultValue !== void 0) {
|
||||
value = defaultValue;
|
||||
} else {
|
||||
throwErr(`Missing environment variable: ${name}`);
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
function getNextRuntime() {
|
||||
return process.env.NEXT_RUNTIME || throwErr("Missing environment variable: NEXT_RUNTIME");
|
||||
}
|
||||
function getNodeEnvironment() {
|
||||
return getEnvVariable("NODE_ENV", "");
|
||||
}
|
||||
export {
|
||||
getEnvVariable,
|
||||
getNextRuntime,
|
||||
getNodeEnvironment,
|
||||
isBrowserLike
|
||||
};
|
||||
//# sourceMappingURL=env.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/env.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/env.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../../../src/utils/env.tsx"],"sourcesContent":["import { throwErr } from \"./errors\";\nimport { deindent } from \"./strings\";\n\nexport function isBrowserLike() {\n return typeof window !== \"undefined\" && typeof document !== \"undefined\" && typeof document.createElement !== \"undefined\";\n}\n\n// newName: oldName\nconst ENV_VAR_RENAME: Record<string, string[]> = {\n NEXT_PUBLIC_STACK_API_URL: ['STACK_BASE_URL', 'NEXT_PUBLIC_STACK_URL'],\n};\n\n/**\n * Returns the environment variable with the given name, returning the default (if given) or throwing an error (otherwise) if it's undefined or the empty string.\n */\nexport function getEnvVariable(name: string, defaultValue?: string | undefined): string {\n if (isBrowserLike()) {\n throw new Error(deindent`\n Can't use getEnvVariable on the client because Next.js transpiles expressions of the kind process.env.XYZ at build-time on the client.\n \n Use process.env.XYZ directly instead.\n `);\n }\n if (name === \"NEXT_RUNTIME\") {\n throw new Error(deindent`\n Can't use getEnvVariable to access the NEXT_RUNTIME environment variable because it's compiled into the client bundle.\n \n Use getNextRuntime() instead.\n `);\n }\n\n // throw error if the old name is used as the retrieve key\n for (const [newName, oldNames] of Object.entries(ENV_VAR_RENAME)) {\n if (oldNames.includes(name)) {\n throwErr(`Environment variable ${name} has been renamed to ${newName}. Please update your configuration to use the new name.`);\n }\n }\n\n let value = process.env[name];\n\n // check the key under the old name if the new name is not found\n if (!value && ENV_VAR_RENAME[name] as any) {\n for (const oldName of ENV_VAR_RENAME[name]) {\n value = process.env[oldName];\n if (value) break;\n }\n }\n\n if (value === undefined) {\n if (defaultValue !== undefined) {\n value = defaultValue;\n } else {\n throwErr(`Missing environment variable: ${name}`);\n }\n }\n\n return value;\n}\n\nexport function getNextRuntime() {\n // This variable is compiled into the client bundle, so we can't use getEnvVariable here.\n return process.env.NEXT_RUNTIME || throwErr(\"Missing environment variable: NEXT_RUNTIME\");\n}\n\nexport function getNodeEnvironment() {\n return getEnvVariable(\"NODE_ENV\", \"\");\n}\n"],"mappings":";AAAA,SAAS,gBAAgB;AACzB,SAAS,gBAAgB;AAElB,SAAS,gBAAgB;AAC9B,SAAO,OAAO,WAAW,eAAe,OAAO,aAAa,eAAe,OAAO,SAAS,kBAAkB;AAC/G;AAGA,IAAM,iBAA2C;AAAA,EAC/C,2BAA2B,CAAC,kBAAkB,uBAAuB;AACvE;AAKO,SAAS,eAAe,MAAc,cAA2C;AACtF,MAAI,cAAc,GAAG;AACnB,UAAM,IAAI,MAAM;AAAA;AAAA;AAAA;AAAA,KAIf;AAAA,EACH;AACA,MAAI,SAAS,gBAAgB;AAC3B,UAAM,IAAI,MAAM;AAAA;AAAA;AAAA;AAAA,KAIf;AAAA,EACH;AAGA,aAAW,CAAC,SAAS,QAAQ,KAAK,OAAO,QAAQ,cAAc,GAAG;AAChE,QAAI,SAAS,SAAS,IAAI,GAAG;AAC3B,eAAS,wBAAwB,IAAI,wBAAwB,OAAO,yDAAyD;AAAA,IAC/H;AAAA,EACF;AAEA,MAAI,QAAQ,QAAQ,IAAI,IAAI;AAG5B,MAAI,CAAC,SAAS,eAAe,IAAI,GAAU;AACzC,eAAW,WAAW,eAAe,IAAI,GAAG;AAC1C,cAAQ,QAAQ,IAAI,OAAO;AAC3B,UAAI,MAAO;AAAA,IACb;AAAA,EACF;AAEA,MAAI,UAAU,QAAW;AACvB,QAAI,iBAAiB,QAAW;AAC9B,cAAQ;AAAA,IACV,OAAO;AACL,eAAS,iCAAiC,IAAI,EAAE;AAAA,IAClD;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,iBAAiB;AAE/B,SAAO,QAAQ,IAAI,gBAAgB,SAAS,4CAA4C;AAC1F;AAEO,SAAS,qBAAqB;AACnC,SAAO,eAAe,YAAY,EAAE;AACtC;","names":[]}
|
||||
178
package/@stackframe/stack-shared/dist/esm/utils/errors.js
vendored
Normal file
178
package/@stackframe/stack-shared/dist/esm/utils/errors.js
vendored
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
// src/utils/errors.tsx
|
||||
import { globalVar } from "./globals";
|
||||
import { pick } from "./objects";
|
||||
import { nicify } from "./strings";
|
||||
function throwErr(...args) {
|
||||
if (typeof args[0] === "string") {
|
||||
throw new StackAssertionError(args[0], args[1]);
|
||||
} else if (args[0] instanceof Error) {
|
||||
throw args[0];
|
||||
} else {
|
||||
throw new StatusError(...args);
|
||||
}
|
||||
}
|
||||
function removeStacktraceNameLine(stack) {
|
||||
const addsNameLine = new Error().stack?.startsWith("Error\n");
|
||||
return stack.split("\n").slice(addsNameLine ? 1 : 0).join("\n");
|
||||
}
|
||||
function concatStacktraces(first, ...errors) {
|
||||
const addsEmptyLineAtEnd = first.stack?.endsWith("\n");
|
||||
const separator = removeStacktraceNameLine(new Error().stack ?? "").split("\n")[0];
|
||||
for (const error of errors) {
|
||||
const toAppend = removeStacktraceNameLine(error.stack ?? "");
|
||||
first.stack += (addsEmptyLineAtEnd ? "" : "\n") + separator + "\n" + toAppend;
|
||||
}
|
||||
}
|
||||
var StackAssertionError = class extends Error {
|
||||
constructor(message, extraData) {
|
||||
const disclaimer = `
|
||||
|
||||
This is likely an error in Stack. Please make sure you are running the newest version and report it.`;
|
||||
super(`${message}${message.endsWith(disclaimer) ? "" : disclaimer}`, pick(extraData ?? {}, ["cause"]));
|
||||
this.extraData = extraData;
|
||||
Object.defineProperty(this, "customCaptureExtraArgs", {
|
||||
get() {
|
||||
return [this.extraData];
|
||||
},
|
||||
enumerable: false
|
||||
});
|
||||
}
|
||||
};
|
||||
StackAssertionError.prototype.name = "StackAssertionError";
|
||||
function errorToNiceString(error) {
|
||||
if (!(error instanceof Error)) return `${typeof error}<${nicify(error)}>`;
|
||||
return nicify(error, { maxDepth: 8 });
|
||||
}
|
||||
var errorSinks = /* @__PURE__ */ new Set();
|
||||
function registerErrorSink(sink) {
|
||||
if (errorSinks.has(sink)) {
|
||||
return;
|
||||
}
|
||||
errorSinks.add(sink);
|
||||
}
|
||||
registerErrorSink((location, error, ...extraArgs) => {
|
||||
console.error(
|
||||
`\x1B[41mCaptured error in ${location}:`,
|
||||
// HACK: Log a nicified version of the error to get around buggy Next.js pretty-printing
|
||||
// https://www.reddit.com/r/nextjs/comments/1gkxdqe/comment/m19kxgn/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button
|
||||
errorToNiceString(error),
|
||||
...extraArgs,
|
||||
"\x1B[0m"
|
||||
);
|
||||
});
|
||||
registerErrorSink((location, error, ...extraArgs) => {
|
||||
globalVar.stackCapturedErrors = globalVar.stackCapturedErrors ?? [];
|
||||
globalVar.stackCapturedErrors.push({ location, error, extraArgs });
|
||||
});
|
||||
function captureError(location, error) {
|
||||
for (const sink of errorSinks) {
|
||||
sink(
|
||||
location,
|
||||
error,
|
||||
...error && (typeof error === "object" || typeof error === "function") && "customCaptureExtraArgs" in error && Array.isArray(error.customCaptureExtraArgs) ? error.customCaptureExtraArgs : []
|
||||
);
|
||||
}
|
||||
}
|
||||
var StatusError = class extends Error {
|
||||
constructor(status, message) {
|
||||
if (typeof status === "object") {
|
||||
message ??= status.message;
|
||||
status = status.statusCode;
|
||||
}
|
||||
super(message);
|
||||
this.__stackStatusErrorBrand = "stack-status-error-brand-sentinel";
|
||||
this.name = "StatusError";
|
||||
this.statusCode = status;
|
||||
if (!message) {
|
||||
throw new StackAssertionError("StatusError always requires a message unless a Status object is passed", { cause: this });
|
||||
}
|
||||
}
|
||||
static isStatusError(error) {
|
||||
return typeof error === "object" && error !== null && "__stackStatusErrorBrand" in error && error.__stackStatusErrorBrand === "stack-status-error-brand-sentinel";
|
||||
}
|
||||
isClientError() {
|
||||
return this.statusCode >= 400 && this.statusCode < 500;
|
||||
}
|
||||
isServerError() {
|
||||
return !this.isClientError();
|
||||
}
|
||||
getStatusCode() {
|
||||
return this.statusCode;
|
||||
}
|
||||
getBody() {
|
||||
return new TextEncoder().encode(this.message);
|
||||
}
|
||||
getHeaders() {
|
||||
return {
|
||||
"Content-Type": ["text/plain; charset=utf-8"]
|
||||
};
|
||||
}
|
||||
toDescriptiveJson() {
|
||||
return {
|
||||
status_code: this.getStatusCode(),
|
||||
message: this.message,
|
||||
headers: this.getHeaders()
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @deprecated this is not a good way to make status errors human-readable, use toDescriptiveJson instead
|
||||
*/
|
||||
toHttpJson() {
|
||||
return {
|
||||
status_code: this.statusCode,
|
||||
body: this.message,
|
||||
headers: this.getHeaders()
|
||||
};
|
||||
}
|
||||
};
|
||||
StatusError.BadRequest = { statusCode: 400, message: "Bad Request" };
|
||||
StatusError.Unauthorized = { statusCode: 401, message: "Unauthorized" };
|
||||
StatusError.PaymentRequired = { statusCode: 402, message: "Payment Required" };
|
||||
StatusError.Forbidden = { statusCode: 403, message: "Forbidden" };
|
||||
StatusError.NotFound = { statusCode: 404, message: "Not Found" };
|
||||
StatusError.MethodNotAllowed = { statusCode: 405, message: "Method Not Allowed" };
|
||||
StatusError.NotAcceptable = { statusCode: 406, message: "Not Acceptable" };
|
||||
StatusError.ProxyAuthenticationRequired = { statusCode: 407, message: "Proxy Authentication Required" };
|
||||
StatusError.RequestTimeout = { statusCode: 408, message: "Request Timeout" };
|
||||
StatusError.Conflict = { statusCode: 409, message: "Conflict" };
|
||||
StatusError.Gone = { statusCode: 410, message: "Gone" };
|
||||
StatusError.LengthRequired = { statusCode: 411, message: "Length Required" };
|
||||
StatusError.PreconditionFailed = { statusCode: 412, message: "Precondition Failed" };
|
||||
StatusError.PayloadTooLarge = { statusCode: 413, message: "Payload Too Large" };
|
||||
StatusError.URITooLong = { statusCode: 414, message: "URI Too Long" };
|
||||
StatusError.UnsupportedMediaType = { statusCode: 415, message: "Unsupported Media Type" };
|
||||
StatusError.RangeNotSatisfiable = { statusCode: 416, message: "Range Not Satisfiable" };
|
||||
StatusError.ExpectationFailed = { statusCode: 417, message: "Expectation Failed" };
|
||||
StatusError.ImATeapot = { statusCode: 418, message: "I'm a teapot" };
|
||||
StatusError.MisdirectedRequest = { statusCode: 421, message: "Misdirected Request" };
|
||||
StatusError.UnprocessableEntity = { statusCode: 422, message: "Unprocessable Entity" };
|
||||
StatusError.Locked = { statusCode: 423, message: "Locked" };
|
||||
StatusError.FailedDependency = { statusCode: 424, message: "Failed Dependency" };
|
||||
StatusError.TooEarly = { statusCode: 425, message: "Too Early" };
|
||||
StatusError.UpgradeRequired = { statusCode: 426, message: "Upgrade Required" };
|
||||
StatusError.PreconditionRequired = { statusCode: 428, message: "Precondition Required" };
|
||||
StatusError.TooManyRequests = { statusCode: 429, message: "Too Many Requests" };
|
||||
StatusError.RequestHeaderFieldsTooLarge = { statusCode: 431, message: "Request Header Fields Too Large" };
|
||||
StatusError.UnavailableForLegalReasons = { statusCode: 451, message: "Unavailable For Legal Reasons" };
|
||||
StatusError.InternalServerError = { statusCode: 500, message: "Internal Server Error" };
|
||||
StatusError.NotImplemented = { statusCode: 501, message: "Not Implemented" };
|
||||
StatusError.BadGateway = { statusCode: 502, message: "Bad Gateway" };
|
||||
StatusError.ServiceUnavailable = { statusCode: 503, message: "Service Unavailable" };
|
||||
StatusError.GatewayTimeout = { statusCode: 504, message: "Gateway Timeout" };
|
||||
StatusError.HTTPVersionNotSupported = { statusCode: 505, message: "HTTP Version Not Supported" };
|
||||
StatusError.VariantAlsoNegotiates = { statusCode: 506, message: "Variant Also Negotiates" };
|
||||
StatusError.InsufficientStorage = { statusCode: 507, message: "Insufficient Storage" };
|
||||
StatusError.LoopDetected = { statusCode: 508, message: "Loop Detected" };
|
||||
StatusError.NotExtended = { statusCode: 510, message: "Not Extended" };
|
||||
StatusError.NetworkAuthenticationRequired = { statusCode: 511, message: "Network Authentication Required" };
|
||||
StatusError.prototype.name = "StatusError";
|
||||
export {
|
||||
StackAssertionError,
|
||||
StatusError,
|
||||
captureError,
|
||||
concatStacktraces,
|
||||
errorToNiceString,
|
||||
registerErrorSink,
|
||||
throwErr
|
||||
};
|
||||
//# sourceMappingURL=errors.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/errors.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/errors.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
37
package/@stackframe/stack-shared/dist/esm/utils/fs.js
vendored
Normal file
37
package/@stackframe/stack-shared/dist/esm/utils/fs.js
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
// src/utils/fs.tsx
|
||||
import * as stackFs from "fs";
|
||||
import * as path from "path";
|
||||
async function list(path2) {
|
||||
return await stackFs.promises.readdir(path2);
|
||||
}
|
||||
async function listRecursively(p, options = {}) {
|
||||
const files = await list(p);
|
||||
return [
|
||||
...(await Promise.all(files.map(async (fileName) => {
|
||||
const filePath = path.join(p, fileName);
|
||||
if ((await stackFs.promises.stat(filePath)).isDirectory()) {
|
||||
return [
|
||||
...await listRecursively(filePath, options),
|
||||
...options.excludeDirectories ? [] : [filePath]
|
||||
];
|
||||
} else {
|
||||
return [filePath];
|
||||
}
|
||||
}))).flat()
|
||||
];
|
||||
}
|
||||
function writeFileSyncIfChanged(path2, content) {
|
||||
if (stackFs.existsSync(path2)) {
|
||||
const existingContent = stackFs.readFileSync(path2, "utf-8");
|
||||
if (existingContent === content) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
stackFs.writeFileSync(path2, content);
|
||||
}
|
||||
export {
|
||||
list,
|
||||
listRecursively,
|
||||
writeFileSyncIfChanged
|
||||
};
|
||||
//# sourceMappingURL=fs.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/fs.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/fs.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../../../src/utils/fs.tsx"],"sourcesContent":["import * as stackFs from \"fs\";\nimport * as path from \"path\";\n\nexport async function list(path: string) {\n return await stackFs.promises.readdir(path);\n}\n\nexport async function listRecursively(p: string, options: { excludeDirectories?: boolean } = {}): Promise<string[]> {\n const files = await list(p);\n return [\n ...(await Promise.all(files.map(async (fileName) => {\n const filePath = path.join(p, fileName);\n if ((await stackFs.promises.stat(filePath)).isDirectory()) {\n return [\n ...(await listRecursively(filePath, options)),\n ...(options.excludeDirectories ? [] : [filePath]),\n ];\n } else {\n return [filePath];\n }\n }))).flat(),\n ];\n}\n\nexport function writeFileSyncIfChanged(path: string, content: string): void {\n if (stackFs.existsSync(path)) {\n const existingContent = stackFs.readFileSync(path, \"utf-8\");\n if (existingContent === content) {\n return;\n }\n }\n stackFs.writeFileSync(path, content);\n}\n"],"mappings":";AAAA,YAAY,aAAa;AACzB,YAAY,UAAU;AAEtB,eAAsB,KAAKA,OAAc;AACvC,SAAO,MAAc,iBAAS,QAAQA,KAAI;AAC5C;AAEA,eAAsB,gBAAgB,GAAW,UAA4C,CAAC,GAAsB;AAClH,QAAM,QAAQ,MAAM,KAAK,CAAC;AAC1B,SAAO;AAAA,IACL,IAAI,MAAM,QAAQ,IAAI,MAAM,IAAI,OAAO,aAAa;AAClD,YAAM,WAAgB,UAAK,GAAG,QAAQ;AACtC,WAAK,MAAc,iBAAS,KAAK,QAAQ,GAAG,YAAY,GAAG;AACzD,eAAO;AAAA,UACL,GAAI,MAAM,gBAAgB,UAAU,OAAO;AAAA,UAC3C,GAAI,QAAQ,qBAAqB,CAAC,IAAI,CAAC,QAAQ;AAAA,QACjD;AAAA,MACF,OAAO;AACL,eAAO,CAAC,QAAQ;AAAA,MAClB;AAAA,IACF,CAAC,CAAC,GAAG,KAAK;AAAA,EACZ;AACF;AAEO,SAAS,uBAAuBA,OAAc,SAAuB;AAC1E,MAAY,mBAAWA,KAAI,GAAG;AAC5B,UAAM,kBAA0B,qBAAaA,OAAM,OAAO;AAC1D,QAAI,oBAAoB,SAAS;AAC/B;AAAA,IACF;AAAA,EACF;AACA,EAAQ,sBAAcA,OAAM,OAAO;AACrC;","names":["path"]}
|
||||
12
package/@stackframe/stack-shared/dist/esm/utils/functions.js
vendored
Normal file
12
package/@stackframe/stack-shared/dist/esm/utils/functions.js
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
// src/utils/functions.tsx
|
||||
function identity(t) {
|
||||
return t;
|
||||
}
|
||||
function identityArgs(...args) {
|
||||
return args;
|
||||
}
|
||||
export {
|
||||
identity,
|
||||
identityArgs
|
||||
};
|
||||
//# sourceMappingURL=functions.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/functions.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/functions.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../../../src/utils/functions.tsx"],"sourcesContent":["export function identity<T>(t: T): T {\n return t;\n}\nundefined?.test(\"identity\", ({ expect }) => {\n expect(identity(1)).toBe(1);\n expect(identity(\"test\")).toBe(\"test\");\n expect(identity(null)).toBe(null);\n expect(identity(undefined)).toBe(undefined);\n const obj = { a: 1 };\n expect(identity(obj)).toBe(obj);\n});\n\nexport function identityArgs<T extends any[]>(...args: T): T {\n return args;\n}\nundefined?.test(\"identityArgs\", ({ expect }) => {\n expect(identityArgs()).toEqual([]);\n expect(identityArgs(1)).toEqual([1]);\n expect(identityArgs(1, 2, 3)).toEqual([1, 2, 3]);\n expect(identityArgs(\"a\", \"b\", \"c\")).toEqual([\"a\", \"b\", \"c\"]);\n expect(identityArgs(null, undefined)).toEqual([null, undefined]);\n});\n"],"mappings":";AAAO,SAAS,SAAY,GAAS;AACnC,SAAO;AACT;AAUO,SAAS,gBAAiC,MAAY;AAC3D,SAAO;AACT;","names":[]}
|
||||
15
package/@stackframe/stack-shared/dist/esm/utils/geo.js
vendored
Normal file
15
package/@stackframe/stack-shared/dist/esm/utils/geo.js
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
// src/utils/geo.tsx
|
||||
import { yupNumber, yupObject, yupString } from "../schema-fields";
|
||||
var geoInfoSchema = yupObject({
|
||||
ip: yupString().defined(),
|
||||
countryCode: yupString().nullable(),
|
||||
regionCode: yupString().nullable(),
|
||||
cityName: yupString().nullable(),
|
||||
latitude: yupNumber().nullable(),
|
||||
longitude: yupNumber().nullable(),
|
||||
tzIdentifier: yupString().nullable()
|
||||
});
|
||||
export {
|
||||
geoInfoSchema
|
||||
};
|
||||
//# sourceMappingURL=geo.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/geo.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/geo.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../../../src/utils/geo.tsx"],"sourcesContent":["\nimport * as yup from \"yup\";\nimport { yupNumber, yupObject, yupString } from \"../schema-fields\";\n\nexport const geoInfoSchema = yupObject({\n ip: yupString().defined(),\n countryCode: yupString().nullable(),\n regionCode: yupString().nullable(),\n cityName: yupString().nullable(),\n latitude: yupNumber().nullable(),\n longitude: yupNumber().nullable(),\n tzIdentifier: yupString().nullable(),\n});\n\nexport type GeoInfo = yup.InferType<typeof geoInfoSchema>;\n\n"],"mappings":";AAEA,SAAS,WAAW,WAAW,iBAAiB;AAEzC,IAAM,gBAAgB,UAAU;AAAA,EACrC,IAAI,UAAU,EAAE,QAAQ;AAAA,EACxB,aAAa,UAAU,EAAE,SAAS;AAAA,EAClC,YAAY,UAAU,EAAE,SAAS;AAAA,EACjC,UAAU,UAAU,EAAE,SAAS;AAAA,EAC/B,UAAU,UAAU,EAAE,SAAS;AAAA,EAC/B,WAAW,UAAU,EAAE,SAAS;AAAA,EAChC,cAAc,UAAU,EAAE,SAAS;AACrC,CAAC;","names":[]}
|
||||
18
package/@stackframe/stack-shared/dist/esm/utils/globals.js
vendored
Normal file
18
package/@stackframe/stack-shared/dist/esm/utils/globals.js
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
// src/utils/globals.tsx
|
||||
var globalVar = typeof globalThis !== "undefined" ? globalThis : typeof global !== "undefined" ? global : typeof window !== "undefined" ? window : typeof self !== "undefined" ? self : {};
|
||||
if (typeof globalThis === "undefined") {
|
||||
globalVar.globalThis = globalVar;
|
||||
}
|
||||
var stackGlobalsSymbol = Symbol.for("__stack-globals");
|
||||
globalVar[stackGlobalsSymbol] ??= {};
|
||||
function createGlobal(key, init) {
|
||||
if (!globalVar[stackGlobalsSymbol][key]) {
|
||||
globalVar[stackGlobalsSymbol][key] = init();
|
||||
}
|
||||
return globalVar[stackGlobalsSymbol][key];
|
||||
}
|
||||
export {
|
||||
createGlobal,
|
||||
globalVar
|
||||
};
|
||||
//# sourceMappingURL=globals.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/globals.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/globals.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../../../src/utils/globals.tsx"],"sourcesContent":["const globalVar: any =\n typeof globalThis !== 'undefined' ? globalThis :\n typeof global !== 'undefined' ? global :\n typeof window !== 'undefined' ? window :\n typeof self !== 'undefined' ? self :\n {};\nexport {\n globalVar,\n};\n\nif (typeof globalThis === 'undefined') {\n (globalVar as any).globalThis = globalVar;\n}\n\nconst stackGlobalsSymbol = Symbol.for('__stack-globals');\nglobalVar[stackGlobalsSymbol] ??= {};\n\nexport function createGlobal<T>(key: string, init: () => T) {\n if (!globalVar[stackGlobalsSymbol][key]) {\n globalVar[stackGlobalsSymbol][key] = init();\n }\n return globalVar[stackGlobalsSymbol][key] as T;\n}\n"],"mappings":";AAAA,IAAM,YACJ,OAAO,eAAe,cAAc,aAClC,OAAO,WAAW,cAAc,SAC9B,OAAO,WAAW,cAAc,SAC9B,OAAO,SAAS,cAAc,OAC5B,CAAC;AAKX,IAAI,OAAO,eAAe,aAAa;AACrC,EAAC,UAAkB,aAAa;AAClC;AAEA,IAAM,qBAAqB,OAAO,IAAI,iBAAiB;AACvD,UAAU,kBAAkB,MAAM,CAAC;AAE5B,SAAS,aAAgB,KAAa,MAAe;AAC1D,MAAI,CAAC,UAAU,kBAAkB,EAAE,GAAG,GAAG;AACvC,cAAU,kBAAkB,EAAE,GAAG,IAAI,KAAK;AAAA,EAC5C;AACA,SAAO,UAAU,kBAAkB,EAAE,GAAG;AAC1C;","names":[]}
|
||||
55
package/@stackframe/stack-shared/dist/esm/utils/hashes.js
vendored
Normal file
55
package/@stackframe/stack-shared/dist/esm/utils/hashes.js
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
// src/utils/hashes.tsx
|
||||
import bcrypt from "bcryptjs";
|
||||
import { StackAssertionError } from "./errors";
|
||||
async function sha512(input) {
|
||||
const bytes = typeof input === "string" ? new TextEncoder().encode(input) : input;
|
||||
return new Uint8Array(await crypto.subtle.digest("SHA-512", bytes));
|
||||
}
|
||||
async function hashPassword(password) {
|
||||
const passwordBytes = new TextEncoder().encode(password);
|
||||
if (passwordBytes.length >= 72) {
|
||||
throw new StackAssertionError(`Password is too long for bcrypt`, { len: passwordBytes.length });
|
||||
}
|
||||
const salt = await bcrypt.genSalt(10);
|
||||
return await bcrypt.hash(password, salt);
|
||||
}
|
||||
async function comparePassword(password, hash) {
|
||||
switch (await getPasswordHashAlgorithm(hash)) {
|
||||
case "bcrypt": {
|
||||
return await bcrypt.compare(password, hash);
|
||||
}
|
||||
default: {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
async function isPasswordHashValid(hash) {
|
||||
return !!await getPasswordHashAlgorithm(hash);
|
||||
}
|
||||
async function getPasswordHashAlgorithm(hash) {
|
||||
if (typeof hash !== "string") {
|
||||
throw new StackAssertionError(`Passed non-string value to getPasswordHashAlgorithm`, { hash });
|
||||
}
|
||||
if (hash.match(/^\$2[ayb]\$.{56}$/)) {
|
||||
try {
|
||||
if (bcrypt.getRounds(hash) > 16) {
|
||||
return void 0;
|
||||
}
|
||||
await bcrypt.compare("any string", hash);
|
||||
return "bcrypt";
|
||||
} catch (e) {
|
||||
console.warn(`Error while checking bcrypt password hash. Assuming the hash is invalid`, e);
|
||||
return void 0;
|
||||
}
|
||||
} else {
|
||||
return void 0;
|
||||
}
|
||||
}
|
||||
export {
|
||||
comparePassword,
|
||||
getPasswordHashAlgorithm,
|
||||
hashPassword,
|
||||
isPasswordHashValid,
|
||||
sha512
|
||||
};
|
||||
//# sourceMappingURL=hashes.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/hashes.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/hashes.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../../../src/utils/hashes.tsx"],"sourcesContent":["import bcrypt from 'bcryptjs';\nimport { StackAssertionError } from './errors';\n\nexport async function sha512(input: Uint8Array | string): Promise<Uint8Array> {\n const bytes = typeof input === \"string\" ? new TextEncoder().encode(input) : input;\n return new Uint8Array(await crypto.subtle.digest(\"SHA-512\", bytes));\n}\n\nexport async function hashPassword(password: string) {\n const passwordBytes = new TextEncoder().encode(password);\n if (passwordBytes.length >= 72) {\n throw new StackAssertionError(`Password is too long for bcrypt`, { len: passwordBytes.length });\n }\n const salt = await bcrypt.genSalt(10);\n return await bcrypt.hash(password, salt);\n}\n\nexport async function comparePassword(password: string, hash: string): Promise<boolean> {\n switch (await getPasswordHashAlgorithm(hash)) {\n case \"bcrypt\": {\n return await bcrypt.compare(password, hash);\n }\n default: {\n return false;\n }\n }\n}\n\nexport async function isPasswordHashValid(hash: string) {\n return !!(await getPasswordHashAlgorithm(hash));\n}\n\nexport async function getPasswordHashAlgorithm(hash: string): Promise<\"bcrypt\" | undefined> {\n if (typeof hash !== \"string\") {\n throw new StackAssertionError(`Passed non-string value to getPasswordHashAlgorithm`, { hash });\n }\n if (hash.match(/^\\$2[ayb]\\$.{56}$/)) {\n try {\n if (bcrypt.getRounds(hash) > 16) {\n return undefined;\n }\n await bcrypt.compare(\"any string\", hash);\n return \"bcrypt\";\n } catch (e) {\n console.warn(`Error while checking bcrypt password hash. Assuming the hash is invalid`, e);\n return undefined;\n }\n } else {\n return undefined;\n }\n}\n"],"mappings":";AAAA,OAAO,YAAY;AACnB,SAAS,2BAA2B;AAEpC,eAAsB,OAAO,OAAiD;AAC5E,QAAM,QAAQ,OAAO,UAAU,WAAW,IAAI,YAAY,EAAE,OAAO,KAAK,IAAI;AAC5E,SAAO,IAAI,WAAW,MAAM,OAAO,OAAO,OAAO,WAAW,KAAK,CAAC;AACpE;AAEA,eAAsB,aAAa,UAAkB;AACnD,QAAM,gBAAgB,IAAI,YAAY,EAAE,OAAO,QAAQ;AACvD,MAAI,cAAc,UAAU,IAAI;AAC9B,UAAM,IAAI,oBAAoB,mCAAmC,EAAE,KAAK,cAAc,OAAO,CAAC;AAAA,EAChG;AACA,QAAM,OAAO,MAAM,OAAO,QAAQ,EAAE;AACpC,SAAO,MAAM,OAAO,KAAK,UAAU,IAAI;AACzC;AAEA,eAAsB,gBAAgB,UAAkB,MAAgC;AACtF,UAAQ,MAAM,yBAAyB,IAAI,GAAG;AAAA,IAC5C,KAAK,UAAU;AACb,aAAO,MAAM,OAAO,QAAQ,UAAU,IAAI;AAAA,IAC5C;AAAA,IACA,SAAS;AACP,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEA,eAAsB,oBAAoB,MAAc;AACtD,SAAO,CAAC,CAAE,MAAM,yBAAyB,IAAI;AAC/C;AAEA,eAAsB,yBAAyB,MAA6C;AAC1F,MAAI,OAAO,SAAS,UAAU;AAC5B,UAAM,IAAI,oBAAoB,uDAAuD,EAAE,KAAK,CAAC;AAAA,EAC/F;AACA,MAAI,KAAK,MAAM,mBAAmB,GAAG;AACnC,QAAI;AACF,UAAI,OAAO,UAAU,IAAI,IAAI,IAAI;AAC/B,eAAO;AAAA,MACT;AACA,YAAM,OAAO,QAAQ,cAAc,IAAI;AACvC,aAAO;AAAA,IACT,SAAS,GAAG;AACV,cAAQ,KAAK,2EAA2E,CAAC;AACzF,aAAO;AAAA,IACT;AAAA,EACF,OAAO;AACL,WAAO;AAAA,EACT;AACF;","names":[]}
|
||||
13
package/@stackframe/stack-shared/dist/esm/utils/html.js
vendored
Normal file
13
package/@stackframe/stack-shared/dist/esm/utils/html.js
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// src/utils/html.tsx
|
||||
import { templateIdentity } from "./strings";
|
||||
function escapeHtml(unsafe) {
|
||||
return `${unsafe}`.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
||||
}
|
||||
function html(strings, ...values) {
|
||||
return templateIdentity(strings, ...values.map((v) => escapeHtml(`${v}`)));
|
||||
}
|
||||
export {
|
||||
escapeHtml,
|
||||
html
|
||||
};
|
||||
//# sourceMappingURL=html.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/html.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/html.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../../../src/utils/html.tsx"],"sourcesContent":["import { templateIdentity } from \"./strings\";\n\nexport function escapeHtml(unsafe: string): string {\n return `${unsafe}`\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\nundefined?.test(\"escapeHtml\", ({ expect }) => {\n // Test with empty string\n expect(escapeHtml(\"\")).toBe(\"\");\n\n // Test with string without special characters\n expect(escapeHtml(\"hello world\")).toBe(\"hello world\");\n\n // Test with special characters\n expect(escapeHtml(\"<div>\")).toBe(\"<div>\");\n expect(escapeHtml(\"a & b\")).toBe(\"a & b\");\n expect(escapeHtml('a \"quoted\" string')).toBe(\"a "quoted" string\");\n expect(escapeHtml(\"it's a test\")).toBe(\"it's a test\");\n\n // Test with multiple special characters\n expect(escapeHtml(\"<a href=\\\"test\\\">It's a link</a>\")).toBe(\n \"<a href="test">It's a link</a>\"\n );\n});\n\nexport function html(strings: TemplateStringsArray, ...values: any[]): string {\n return templateIdentity(strings, ...values.map(v => escapeHtml(`${v}`)));\n}\nundefined?.test(\"html\", ({ expect }) => {\n // Test with no interpolation\n expect(html`simple string`).toBe(\"simple string\");\n\n // Test with string interpolation\n expect(html`Hello, ${\"world\"}!`).toBe(\"Hello, world!\");\n\n // Test with number interpolation\n expect(html`Count: ${42}`).toBe(\"Count: 42\");\n\n // Test with HTML special characters in interpolated values\n expect(html`<div>${\"<script>\"}</div>`).toBe(\"<div><script></div>\");\n\n // Test with multiple interpolations\n expect(html`${1} + ${2} = ${\"<3\"}`).toBe(\"1 + 2 = <3\");\n\n // Test with object interpolation\n const obj = { toString: () => \"<object>\" };\n expect(html`Object: ${obj}`).toBe(\"Object: <object>\");\n});\n"],"mappings":";AAAA,SAAS,wBAAwB;AAE1B,SAAS,WAAW,QAAwB;AACjD,SAAO,GAAG,MAAM,GACb,QAAQ,MAAM,OAAO,EACrB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,QAAQ,EACtB,QAAQ,MAAM,QAAQ;AAC3B;AAoBO,SAAS,KAAK,YAAkC,QAAuB;AAC5E,SAAO,iBAAiB,SAAS,GAAG,OAAO,IAAI,OAAK,WAAW,GAAG,CAAC,EAAE,CAAC,CAAC;AACzE;","names":[]}
|
||||
60
package/@stackframe/stack-shared/dist/esm/utils/http.js
vendored
Normal file
60
package/@stackframe/stack-shared/dist/esm/utils/http.js
vendored
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
// src/utils/http.tsx
|
||||
import { decodeBase64, encodeBase64, isBase64 } from "./bytes";
|
||||
var HTTP_METHODS = {
|
||||
"GET": {
|
||||
safe: true,
|
||||
idempotent: true
|
||||
},
|
||||
"POST": {
|
||||
safe: false,
|
||||
idempotent: false
|
||||
},
|
||||
"PUT": {
|
||||
safe: false,
|
||||
idempotent: true
|
||||
},
|
||||
"DELETE": {
|
||||
safe: false,
|
||||
idempotent: true
|
||||
},
|
||||
"PATCH": {
|
||||
safe: false,
|
||||
idempotent: false
|
||||
},
|
||||
"OPTIONS": {
|
||||
safe: true,
|
||||
idempotent: true
|
||||
},
|
||||
"HEAD": {
|
||||
safe: true,
|
||||
idempotent: true
|
||||
},
|
||||
"TRACE": {
|
||||
safe: true,
|
||||
idempotent: true
|
||||
},
|
||||
"CONNECT": {
|
||||
safe: false,
|
||||
idempotent: false
|
||||
}
|
||||
};
|
||||
function decodeBasicAuthorizationHeader(value) {
|
||||
const [type, encoded, ...rest] = value.split(" ");
|
||||
if (rest.length > 0) return null;
|
||||
if (!encoded) return null;
|
||||
if (type !== "Basic") return null;
|
||||
if (!isBase64(encoded)) return null;
|
||||
const decoded = new TextDecoder().decode(decodeBase64(encoded));
|
||||
const split = decoded.split(":");
|
||||
return [split[0], split.slice(1).join(":")];
|
||||
}
|
||||
function encodeBasicAuthorizationHeader(id, password) {
|
||||
if (id.includes(":")) throw new Error("Basic authorization header id cannot contain ':'");
|
||||
return `Basic ${encodeBase64(new TextEncoder().encode(`${id}:${password}`))}`;
|
||||
}
|
||||
export {
|
||||
HTTP_METHODS,
|
||||
decodeBasicAuthorizationHeader,
|
||||
encodeBasicAuthorizationHeader
|
||||
};
|
||||
//# sourceMappingURL=http.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/http.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/http.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../../../src/utils/http.tsx"],"sourcesContent":["import { decodeBase64, encodeBase64, isBase64 } from \"./bytes\";\n\nexport const HTTP_METHODS = {\n \"GET\": {\n safe: true,\n idempotent: true,\n },\n \"POST\": {\n safe: false,\n idempotent: false,\n },\n \"PUT\": {\n safe: false,\n idempotent: true,\n },\n \"DELETE\": {\n safe: false,\n idempotent: true,\n },\n \"PATCH\": {\n safe: false,\n idempotent: false,\n },\n \"OPTIONS\": {\n safe: true,\n idempotent: true,\n },\n \"HEAD\": {\n safe: true,\n idempotent: true,\n },\n \"TRACE\": {\n safe: true,\n idempotent: true,\n },\n \"CONNECT\": {\n safe: false,\n idempotent: false,\n },\n} as const;\nexport type HttpMethod = keyof typeof HTTP_METHODS;\n\nexport function decodeBasicAuthorizationHeader(value: string): [string, string] | null {\n const [type, encoded, ...rest] = value.split(' ');\n if (rest.length > 0) return null;\n if (!encoded) return null;\n if (type !== 'Basic') return null;\n if (!isBase64(encoded)) return null;\n const decoded = new TextDecoder().decode(decodeBase64(encoded));\n const split = decoded.split(':');\n return [split[0], split.slice(1).join(':')];\n}\nundefined?.test(\"decodeBasicAuthorizationHeader\", ({ expect }) => {\n // Test with valid Basic Authorization header\n const username = \"user\";\n const password = \"pass\";\n const encoded = encodeBasicAuthorizationHeader(username, password);\n expect(decodeBasicAuthorizationHeader(encoded)).toEqual([username, password]);\n\n // Test with password containing colons\n const complexPassword = \"pass:with:colons\";\n const encodedComplex = encodeBasicAuthorizationHeader(username, complexPassword);\n expect(decodeBasicAuthorizationHeader(encodedComplex)).toEqual([username, complexPassword]);\n\n // Test with invalid headers\n expect(decodeBasicAuthorizationHeader(\"NotBasic dXNlcjpwYXNz\")).toBe(null); // Wrong type\n expect(decodeBasicAuthorizationHeader(\"Basic\")).toBe(null); // Missing encoded part\n expect(decodeBasicAuthorizationHeader(\"Basic not-base64\")).toBe(null); // Not base64\n expect(decodeBasicAuthorizationHeader(\"Basic dXNlcjpwYXNz extra\")).toBe(null); // Extra parts\n});\n\nexport function encodeBasicAuthorizationHeader(id: string, password: string): string {\n if (id.includes(':')) throw new Error(\"Basic authorization header id cannot contain ':'\");\n return `Basic ${encodeBase64(new TextEncoder().encode(`${id}:${password}`))}`;\n}\nundefined?.test(\"encodeBasicAuthorizationHeader\", ({ expect }) => {\n // Test with simple username and password\n const encoded = encodeBasicAuthorizationHeader(\"user\", \"pass\");\n expect(encoded).toMatch(/^Basic [A-Za-z0-9+/=]+$/); // Should start with \"Basic \" followed by base64\n\n // Test with empty password\n const encodedEmptyPass = encodeBasicAuthorizationHeader(\"user\", \"\");\n expect(encodedEmptyPass).toMatch(/^Basic [A-Za-z0-9+/=]+$/);\n\n // Test with password containing special characters\n const encodedSpecialChars = encodeBasicAuthorizationHeader(\"user\", \"p@ss!w0rd\");\n expect(encodedSpecialChars).toMatch(/^Basic [A-Za-z0-9+/=]+$/);\n\n // Test with username containing colon should throw\n expect(() => encodeBasicAuthorizationHeader(\"user:name\", \"pass\")).toThrow();\n});\n"],"mappings":";AAAA,SAAS,cAAc,cAAc,gBAAgB;AAE9C,IAAM,eAAe;AAAA,EAC1B,OAAO;AAAA,IACL,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,OAAO;AAAA,IACL,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,UAAU;AAAA,IACR,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,SAAS;AAAA,IACP,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,WAAW;AAAA,IACT,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,SAAS;AAAA,IACP,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AAAA,EACA,WAAW;AAAA,IACT,MAAM;AAAA,IACN,YAAY;AAAA,EACd;AACF;AAGO,SAAS,+BAA+B,OAAwC;AACrF,QAAM,CAAC,MAAM,SAAS,GAAG,IAAI,IAAI,MAAM,MAAM,GAAG;AAChD,MAAI,KAAK,SAAS,EAAG,QAAO;AAC5B,MAAI,CAAC,QAAS,QAAO;AACrB,MAAI,SAAS,QAAS,QAAO;AAC7B,MAAI,CAAC,SAAS,OAAO,EAAG,QAAO;AAC/B,QAAM,UAAU,IAAI,YAAY,EAAE,OAAO,aAAa,OAAO,CAAC;AAC9D,QAAM,QAAQ,QAAQ,MAAM,GAAG;AAC/B,SAAO,CAAC,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC,EAAE,KAAK,GAAG,CAAC;AAC5C;AAoBO,SAAS,+BAA+B,IAAY,UAA0B;AACnF,MAAI,GAAG,SAAS,GAAG,EAAG,OAAM,IAAI,MAAM,kDAAkD;AACxF,SAAO,SAAS,aAAa,IAAI,YAAY,EAAE,OAAO,GAAG,EAAE,IAAI,QAAQ,EAAE,CAAC,CAAC;AAC7E;","names":[]}
|
||||
15
package/@stackframe/stack-shared/dist/esm/utils/ips.js
vendored
Normal file
15
package/@stackframe/stack-shared/dist/esm/utils/ips.js
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
// src/utils/ips.tsx
|
||||
import ipRegex from "ip-regex";
|
||||
function isIpAddress(ip) {
|
||||
return ipRegex({ exact: true }).test(ip);
|
||||
}
|
||||
function assertIpAddress(ip) {
|
||||
if (!isIpAddress(ip)) {
|
||||
throw new Error(`Invalid IP address: ${ip}`);
|
||||
}
|
||||
}
|
||||
export {
|
||||
assertIpAddress,
|
||||
isIpAddress
|
||||
};
|
||||
//# sourceMappingURL=ips.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/ips.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/ips.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../../../src/utils/ips.tsx"],"sourcesContent":["import ipRegex from \"ip-regex\";\n\nexport type Ipv4Address = `${number}.${number}.${number}.${number}`;\nexport type Ipv6Address = string;\n\nexport function isIpAddress(ip: string): ip is Ipv4Address | Ipv6Address {\n return ipRegex({ exact: true }).test(ip);\n}\nundefined?.test(\"isIpAddress\", ({ expect }) => {\n // Test valid IPv4 addresses\n expect(isIpAddress(\"192.168.1.1\")).toBe(true);\n expect(isIpAddress(\"127.0.0.1\")).toBe(true);\n expect(isIpAddress(\"0.0.0.0\")).toBe(true);\n expect(isIpAddress(\"255.255.255.255\")).toBe(true);\n\n // Test valid IPv6 addresses\n expect(isIpAddress(\"::1\")).toBe(true);\n expect(isIpAddress(\"2001:db8::\")).toBe(true);\n expect(isIpAddress(\"2001:db8:85a3:8d3:1319:8a2e:370:7348\")).toBe(true);\n\n // Test invalid IP addresses\n expect(isIpAddress(\"\")).toBe(false);\n expect(isIpAddress(\"not an ip\")).toBe(false);\n expect(isIpAddress(\"256.256.256.256\")).toBe(false);\n expect(isIpAddress(\"192.168.1\")).toBe(false);\n expect(isIpAddress(\"192.168.1.1.1\")).toBe(false);\n expect(isIpAddress(\"2001:db8::xyz\")).toBe(false);\n});\n\nexport function assertIpAddress(ip: string): asserts ip is Ipv4Address | Ipv6Address {\n if (!isIpAddress(ip)) {\n throw new Error(`Invalid IP address: ${ip}`);\n }\n}\nundefined?.test(\"assertIpAddress\", ({ expect }) => {\n // Test with valid IPv4 address\n expect(() => assertIpAddress(\"192.168.1.1\")).not.toThrow();\n\n // Test with valid IPv6 address\n expect(() => assertIpAddress(\"::1\")).not.toThrow();\n\n // Test with invalid IP addresses\n expect(() => assertIpAddress(\"\")).toThrow(\"Invalid IP address: \");\n expect(() => assertIpAddress(\"not an ip\")).toThrow(\"Invalid IP address: not an ip\");\n expect(() => assertIpAddress(\"256.256.256.256\")).toThrow(\"Invalid IP address: 256.256.256.256\");\n expect(() => assertIpAddress(\"192.168.1\")).toThrow(\"Invalid IP address: 192.168.1\");\n});\n"],"mappings":";AAAA,OAAO,aAAa;AAKb,SAAS,YAAY,IAA6C;AACvE,SAAO,QAAQ,EAAE,OAAO,KAAK,CAAC,EAAE,KAAK,EAAE;AACzC;AAsBO,SAAS,gBAAgB,IAAqD;AACnF,MAAI,CAAC,YAAY,EAAE,GAAG;AACpB,UAAM,IAAI,MAAM,uBAAuB,EAAE,EAAE;AAAA,EAC7C;AACF;","names":[]}
|
||||
31
package/@stackframe/stack-shared/dist/esm/utils/json.js
vendored
Normal file
31
package/@stackframe/stack-shared/dist/esm/utils/json.js
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
// src/utils/json.tsx
|
||||
import { Result } from "./results";
|
||||
function isJson(value) {
|
||||
switch (typeof value) {
|
||||
case "object": {
|
||||
if (value === null) return true;
|
||||
if (Array.isArray(value)) return value.every(isJson);
|
||||
return Object.keys(value).every((k) => typeof k === "string") && Object.values(value).every(isJson);
|
||||
}
|
||||
case "string":
|
||||
case "number":
|
||||
case "boolean": {
|
||||
return true;
|
||||
}
|
||||
default: {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
function parseJson(json) {
|
||||
return Result.fromThrowing(() => JSON.parse(json));
|
||||
}
|
||||
function stringifyJson(json) {
|
||||
return Result.fromThrowing(() => JSON.stringify(json));
|
||||
}
|
||||
export {
|
||||
isJson,
|
||||
parseJson,
|
||||
stringifyJson
|
||||
};
|
||||
//# sourceMappingURL=json.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/json.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/json.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
87
package/@stackframe/stack-shared/dist/esm/utils/jwt.js
vendored
Normal file
87
package/@stackframe/stack-shared/dist/esm/utils/jwt.js
vendored
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
// src/utils/jwt.tsx
|
||||
import crypto from "crypto";
|
||||
import elliptic from "elliptic";
|
||||
import * as jose from "jose";
|
||||
import { JOSEError } from "jose/errors";
|
||||
import { encodeBase64Url } from "./bytes";
|
||||
import { StackAssertionError } from "./errors";
|
||||
import { globalVar } from "./globals";
|
||||
import { pick } from "./objects";
|
||||
var STACK_SERVER_SECRET = process.env.STACK_SERVER_SECRET ?? "";
|
||||
try {
|
||||
jose.base64url.decode(STACK_SERVER_SECRET);
|
||||
} catch (e) {
|
||||
throw new Error("STACK_SERVER_SECRET is not valid. Please use the generateKeys script to generate a new secret.");
|
||||
}
|
||||
async function legacySignGlobalJWT(issuer, payload, expirationTime = "5m") {
|
||||
const privateJwk = await jose.importJWK(await getPrivateJwk(STACK_SERVER_SECRET));
|
||||
return await new jose.SignJWT(payload).setProtectedHeader({ alg: "ES256" }).setIssuer(issuer).setIssuedAt().setExpirationTime(expirationTime).sign(privateJwk);
|
||||
}
|
||||
async function legacyVerifyGlobalJWT(issuer, jwt) {
|
||||
const jwkSet = jose.createLocalJWKSet(await getPublicJwkSet(STACK_SERVER_SECRET));
|
||||
const verified = await jose.jwtVerify(jwt, jwkSet, { issuer });
|
||||
return verified.payload;
|
||||
}
|
||||
async function signJWT(options) {
|
||||
const secret = getPerAudienceSecret({ audience: options.audience, secret: STACK_SERVER_SECRET });
|
||||
const kid = getKid({ secret });
|
||||
const privateJwk = await jose.importJWK(await getPrivateJwk(secret));
|
||||
return await new jose.SignJWT(options.payload).setProtectedHeader({ alg: "ES256", kid }).setIssuer(options.issuer).setIssuedAt().setAudience(options.audience).setExpirationTime(options.expirationTime || "5m").sign(privateJwk);
|
||||
}
|
||||
async function verifyJWT(options) {
|
||||
const audience = jose.decodeJwt(options.jwt).aud;
|
||||
if (!audience || typeof audience !== "string") {
|
||||
throw new JOSEError("Invalid JWT audience");
|
||||
}
|
||||
const secret = getPerAudienceSecret({ audience, secret: STACK_SERVER_SECRET });
|
||||
const jwkSet = jose.createLocalJWKSet(await getPublicJwkSet(secret));
|
||||
const verified = await jose.jwtVerify(options.jwt, jwkSet, { issuer: options.issuer });
|
||||
return verified.payload;
|
||||
}
|
||||
async function getPrivateJwk(secret) {
|
||||
const secretHash = await globalVar.crypto.subtle.digest("SHA-256", jose.base64url.decode(secret));
|
||||
const priv = new Uint8Array(secretHash);
|
||||
const ec = new elliptic.ec("p256");
|
||||
const key = ec.keyFromPrivate(priv);
|
||||
const publicKey = key.getPublic();
|
||||
return {
|
||||
kty: "EC",
|
||||
crv: "P-256",
|
||||
alg: "ES256",
|
||||
kid: getKid({ secret }),
|
||||
d: encodeBase64Url(priv),
|
||||
x: encodeBase64Url(publicKey.getX().toBuffer()),
|
||||
y: encodeBase64Url(publicKey.getY().toBuffer())
|
||||
};
|
||||
}
|
||||
async function getPublicJwkSet(secretOrPrivateJwk) {
|
||||
const privateJwk = typeof secretOrPrivateJwk === "string" ? await getPrivateJwk(secretOrPrivateJwk) : secretOrPrivateJwk;
|
||||
const jwk = pick(privateJwk, ["kty", "alg", "crv", "x", "y", "kid"]);
|
||||
return {
|
||||
keys: [jwk]
|
||||
};
|
||||
}
|
||||
function getPerAudienceSecret(options) {
|
||||
if (options.audience === "kid") {
|
||||
throw new StackAssertionError("You cannot use the 'kid' audience for a per-audience secret, see comment below in jwt.tsx");
|
||||
}
|
||||
return jose.base64url.encode(
|
||||
crypto.createHash("sha256").update(JSON.stringify([options.secret, options.audience])).digest()
|
||||
);
|
||||
}
|
||||
function getKid(options) {
|
||||
return jose.base64url.encode(
|
||||
crypto.createHash("sha256").update(JSON.stringify([options.secret, "kid"])).digest()
|
||||
).slice(0, 12);
|
||||
}
|
||||
export {
|
||||
getKid,
|
||||
getPerAudienceSecret,
|
||||
getPrivateJwk,
|
||||
getPublicJwkSet,
|
||||
legacySignGlobalJWT,
|
||||
legacyVerifyGlobalJWT,
|
||||
signJWT,
|
||||
verifyJWT
|
||||
};
|
||||
//# sourceMappingURL=jwt.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/jwt.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/jwt.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
57
package/@stackframe/stack-shared/dist/esm/utils/locks.js
vendored
Normal file
57
package/@stackframe/stack-shared/dist/esm/utils/locks.js
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
// src/utils/locks.tsx
|
||||
import { Semaphore } from "async-mutex";
|
||||
var ReadWriteLock = class {
|
||||
constructor() {
|
||||
this.semaphore = new Semaphore(1);
|
||||
this.readers = 0;
|
||||
this.readersMutex = new Semaphore(1);
|
||||
}
|
||||
async withReadLock(callback) {
|
||||
await this._acquireReadLock();
|
||||
try {
|
||||
return await callback();
|
||||
} finally {
|
||||
await this._releaseReadLock();
|
||||
}
|
||||
}
|
||||
async withWriteLock(callback) {
|
||||
await this._acquireWriteLock();
|
||||
try {
|
||||
return await callback();
|
||||
} finally {
|
||||
await this._releaseWriteLock();
|
||||
}
|
||||
}
|
||||
async _acquireReadLock() {
|
||||
await this.readersMutex.acquire();
|
||||
try {
|
||||
this.readers += 1;
|
||||
if (this.readers === 1) {
|
||||
await this.semaphore.acquire();
|
||||
}
|
||||
} finally {
|
||||
this.readersMutex.release();
|
||||
}
|
||||
}
|
||||
async _releaseReadLock() {
|
||||
await this.readersMutex.acquire();
|
||||
try {
|
||||
this.readers -= 1;
|
||||
if (this.readers === 0) {
|
||||
this.semaphore.release();
|
||||
}
|
||||
} finally {
|
||||
this.readersMutex.release();
|
||||
}
|
||||
}
|
||||
async _acquireWriteLock() {
|
||||
await this.semaphore.acquire();
|
||||
}
|
||||
async _releaseWriteLock() {
|
||||
this.semaphore.release();
|
||||
}
|
||||
};
|
||||
export {
|
||||
ReadWriteLock
|
||||
};
|
||||
//# sourceMappingURL=locks.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/locks.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/locks.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../../../src/utils/locks.tsx"],"sourcesContent":["import { Semaphore } from 'async-mutex';\n\ntype LockCallback<T> = () => Promise<T>;\n\nexport class ReadWriteLock {\n private semaphore: Semaphore;\n private readers: number;\n private readersMutex: Semaphore;\n\n constructor() {\n this.semaphore = new Semaphore(1); // Semaphore with 1 permit\n this.readers = 0; // Track the number of readers\n this.readersMutex = new Semaphore(1); // Protect access to `readers` count\n }\n\n async withReadLock<T>(callback: LockCallback<T>): Promise<T> {\n await this._acquireReadLock();\n try {\n return await callback();\n } finally {\n await this._releaseReadLock();\n }\n }\n\n async withWriteLock<T>(callback: LockCallback<T>): Promise<T> {\n await this._acquireWriteLock();\n try {\n return await callback();\n } finally {\n await this._releaseWriteLock();\n }\n }\n\n private async _acquireReadLock(): Promise<void> {\n // Increment the readers count\n await this.readersMutex.acquire();\n try {\n this.readers += 1;\n // If this is the first reader, block writers\n if (this.readers === 1) {\n await this.semaphore.acquire();\n }\n } finally {\n this.readersMutex.release();\n }\n }\n\n private async _releaseReadLock(): Promise<void> {\n // Decrement the readers count\n await this.readersMutex.acquire();\n try {\n this.readers -= 1;\n // If this was the last reader, release the writer block\n if (this.readers === 0) {\n this.semaphore.release();\n }\n } finally {\n this.readersMutex.release();\n }\n }\n\n private async _acquireWriteLock(): Promise<void> {\n // Writers acquire the main semaphore exclusively\n await this.semaphore.acquire();\n }\n\n private async _releaseWriteLock(): Promise<void> {\n // Writers release the main semaphore\n this.semaphore.release();\n }\n}\n"],"mappings":";AAAA,SAAS,iBAAiB;AAInB,IAAM,gBAAN,MAAoB;AAAA,EAKzB,cAAc;AACZ,SAAK,YAAY,IAAI,UAAU,CAAC;AAChC,SAAK,UAAU;AACf,SAAK,eAAe,IAAI,UAAU,CAAC;AAAA,EACrC;AAAA,EAEA,MAAM,aAAgB,UAAuC;AAC3D,UAAM,KAAK,iBAAiB;AAC5B,QAAI;AACF,aAAO,MAAM,SAAS;AAAA,IACxB,UAAE;AACA,YAAM,KAAK,iBAAiB;AAAA,IAC9B;AAAA,EACF;AAAA,EAEA,MAAM,cAAiB,UAAuC;AAC5D,UAAM,KAAK,kBAAkB;AAC7B,QAAI;AACF,aAAO,MAAM,SAAS;AAAA,IACxB,UAAE;AACA,YAAM,KAAK,kBAAkB;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,MAAc,mBAAkC;AAE9C,UAAM,KAAK,aAAa,QAAQ;AAChC,QAAI;AACF,WAAK,WAAW;AAEhB,UAAI,KAAK,YAAY,GAAG;AACtB,cAAM,KAAK,UAAU,QAAQ;AAAA,MAC/B;AAAA,IACF,UAAE;AACA,WAAK,aAAa,QAAQ;AAAA,IAC5B;AAAA,EACF;AAAA,EAEA,MAAc,mBAAkC;AAE9C,UAAM,KAAK,aAAa,QAAQ;AAChC,QAAI;AACF,WAAK,WAAW;AAEhB,UAAI,KAAK,YAAY,GAAG;AACtB,aAAK,UAAU,QAAQ;AAAA,MACzB;AAAA,IACF,UAAE;AACA,WAAK,aAAa,QAAQ;AAAA,IAC5B;AAAA,EACF;AAAA,EAEA,MAAc,oBAAmC;AAE/C,UAAM,KAAK,UAAU,QAAQ;AAAA,EAC/B;AAAA,EAEA,MAAc,oBAAmC;AAE/C,SAAK,UAAU,QAAQ;AAAA,EACzB;AACF;","names":[]}
|
||||
181
package/@stackframe/stack-shared/dist/esm/utils/maps.js
vendored
Normal file
181
package/@stackframe/stack-shared/dist/esm/utils/maps.js
vendored
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
// src/utils/maps.tsx
|
||||
import { Result } from "./results";
|
||||
var WeakRefIfAvailable = class {
|
||||
constructor(value) {
|
||||
if (typeof WeakRef === "undefined") {
|
||||
this._ref = { deref: () => value };
|
||||
} else {
|
||||
this._ref = new WeakRef(value);
|
||||
}
|
||||
}
|
||||
deref() {
|
||||
return this._ref.deref();
|
||||
}
|
||||
};
|
||||
var _a, _b;
|
||||
var IterableWeakMap = class {
|
||||
constructor(entries) {
|
||||
this[_a] = "IterableWeakMap";
|
||||
const mappedEntries = entries?.map((e) => [e[0], { value: e[1], keyRef: new WeakRefIfAvailable(e[0]) }]);
|
||||
this._weakMap = new WeakMap(mappedEntries ?? []);
|
||||
this._keyRefs = new Set(mappedEntries?.map((e) => e[1].keyRef) ?? []);
|
||||
}
|
||||
get(key) {
|
||||
return this._weakMap.get(key)?.value;
|
||||
}
|
||||
set(key, value) {
|
||||
const existing = this._weakMap.get(key);
|
||||
const updated = { value, keyRef: existing?.keyRef ?? new WeakRefIfAvailable(key) };
|
||||
this._weakMap.set(key, updated);
|
||||
this._keyRefs.add(updated.keyRef);
|
||||
return this;
|
||||
}
|
||||
delete(key) {
|
||||
const res = this._weakMap.get(key);
|
||||
if (res) {
|
||||
this._weakMap.delete(key);
|
||||
this._keyRefs.delete(res.keyRef);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
has(key) {
|
||||
return this._weakMap.has(key) && this._keyRefs.has(this._weakMap.get(key).keyRef);
|
||||
}
|
||||
*[(_b = Symbol.iterator, _a = Symbol.toStringTag, _b)]() {
|
||||
for (const keyRef of this._keyRefs) {
|
||||
const key = keyRef.deref();
|
||||
const existing = key ? this._weakMap.get(key) : void 0;
|
||||
if (!key) {
|
||||
this._keyRefs.delete(keyRef);
|
||||
} else if (existing) {
|
||||
yield [key, existing.value];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
var _a2, _b2;
|
||||
var MaybeWeakMap = class {
|
||||
constructor(entries) {
|
||||
this[_a2] = "MaybeWeakMap";
|
||||
const entriesArray = [...entries ?? []];
|
||||
this._primitiveMap = new Map(entriesArray.filter((e) => !this._isAllowedInWeakMap(e[0])));
|
||||
this._weakMap = new IterableWeakMap(entriesArray.filter((e) => this._isAllowedInWeakMap(e[0])));
|
||||
}
|
||||
_isAllowedInWeakMap(key) {
|
||||
return typeof key === "object" && key !== null || typeof key === "symbol" && Symbol.keyFor(key) === void 0;
|
||||
}
|
||||
get(key) {
|
||||
if (this._isAllowedInWeakMap(key)) {
|
||||
return this._weakMap.get(key);
|
||||
} else {
|
||||
return this._primitiveMap.get(key);
|
||||
}
|
||||
}
|
||||
set(key, value) {
|
||||
if (this._isAllowedInWeakMap(key)) {
|
||||
this._weakMap.set(key, value);
|
||||
} else {
|
||||
this._primitiveMap.set(key, value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
delete(key) {
|
||||
if (this._isAllowedInWeakMap(key)) {
|
||||
return this._weakMap.delete(key);
|
||||
} else {
|
||||
return this._primitiveMap.delete(key);
|
||||
}
|
||||
}
|
||||
has(key) {
|
||||
if (this._isAllowedInWeakMap(key)) {
|
||||
return this._weakMap.has(key);
|
||||
} else {
|
||||
return this._primitiveMap.has(key);
|
||||
}
|
||||
}
|
||||
*[(_b2 = Symbol.iterator, _a2 = Symbol.toStringTag, _b2)]() {
|
||||
yield* this._primitiveMap;
|
||||
yield* this._weakMap;
|
||||
}
|
||||
};
|
||||
var _a3, _b3;
|
||||
var DependenciesMap = class {
|
||||
constructor() {
|
||||
this._inner = { map: new MaybeWeakMap(), hasValue: false, value: void 0 };
|
||||
this[_a3] = "DependenciesMap";
|
||||
}
|
||||
_valueToResult(inner) {
|
||||
if (inner.hasValue) {
|
||||
return Result.ok(inner.value);
|
||||
} else {
|
||||
return Result.error(void 0);
|
||||
}
|
||||
}
|
||||
_unwrapFromInner(dependencies, inner) {
|
||||
if (dependencies.length === 0) {
|
||||
return this._valueToResult(inner);
|
||||
} else {
|
||||
const [key, ...rest] = dependencies;
|
||||
const newInner = inner.map.get(key);
|
||||
if (!newInner) {
|
||||
return Result.error(void 0);
|
||||
}
|
||||
return this._unwrapFromInner(rest, newInner);
|
||||
}
|
||||
}
|
||||
_setInInner(dependencies, value, inner) {
|
||||
if (dependencies.length === 0) {
|
||||
const res = this._valueToResult(inner);
|
||||
if (value.status === "ok") {
|
||||
inner.hasValue = true;
|
||||
inner.value = value.data;
|
||||
} else {
|
||||
inner.hasValue = false;
|
||||
inner.value = void 0;
|
||||
}
|
||||
return res;
|
||||
} else {
|
||||
const [key, ...rest] = dependencies;
|
||||
let newInner = inner.map.get(key);
|
||||
if (!newInner) {
|
||||
inner.map.set(key, newInner = { map: new MaybeWeakMap(), hasValue: false, value: void 0 });
|
||||
}
|
||||
return this._setInInner(rest, value, newInner);
|
||||
}
|
||||
}
|
||||
*_iterateInner(dependencies, inner) {
|
||||
if (inner.hasValue) {
|
||||
yield [dependencies, inner.value];
|
||||
}
|
||||
for (const [key, value] of inner.map) {
|
||||
yield* this._iterateInner([...dependencies, key], value);
|
||||
}
|
||||
}
|
||||
get(dependencies) {
|
||||
return Result.or(this._unwrapFromInner(dependencies, this._inner), void 0);
|
||||
}
|
||||
set(dependencies, value) {
|
||||
this._setInInner(dependencies, Result.ok(value), this._inner);
|
||||
return this;
|
||||
}
|
||||
delete(dependencies) {
|
||||
return this._setInInner(dependencies, Result.error(void 0), this._inner).status === "ok";
|
||||
}
|
||||
has(dependencies) {
|
||||
return this._unwrapFromInner(dependencies, this._inner).status === "ok";
|
||||
}
|
||||
clear() {
|
||||
this._inner = { map: new MaybeWeakMap(), hasValue: false, value: void 0 };
|
||||
}
|
||||
*[(_b3 = Symbol.iterator, _a3 = Symbol.toStringTag, _b3)]() {
|
||||
yield* this._iterateInner([], this._inner);
|
||||
}
|
||||
};
|
||||
export {
|
||||
DependenciesMap,
|
||||
IterableWeakMap,
|
||||
MaybeWeakMap,
|
||||
WeakRefIfAvailable
|
||||
};
|
||||
//# sourceMappingURL=maps.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/maps.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/maps.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
8
package/@stackframe/stack-shared/dist/esm/utils/math.js
vendored
Normal file
8
package/@stackframe/stack-shared/dist/esm/utils/math.js
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
// src/utils/math.tsx
|
||||
function remainder(n, d) {
|
||||
return (n % d + Math.abs(d)) % d;
|
||||
}
|
||||
export {
|
||||
remainder
|
||||
};
|
||||
//# sourceMappingURL=math.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/math.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/math.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../../../src/utils/math.tsx"],"sourcesContent":["/**\n * Similar to the modulo operator, but always returns a positive number (even when the input is negative).\n */\nexport function remainder(n: number, d: number): number {\n return ((n % d) + Math.abs(d)) % d;\n}\nundefined?.test(\"remainder\", ({ expect }) => {\n expect(remainder(10, 3)).toBe(1);\n expect(remainder(10, 5)).toBe(0);\n expect(remainder(10, 7)).toBe(3);\n // Test with negative numbers\n expect(remainder(-10, 3)).toBe(2);\n expect(remainder(-5, 2)).toBe(1);\n expect(remainder(-7, 4)).toBe(1);\n // Test with decimal numbers\n expect(remainder(10.5, 3)).toBeCloseTo(1.5);\n expect(remainder(-10.5, 3)).toBeCloseTo(1.5);\n});\n"],"mappings":";AAGO,SAAS,UAAU,GAAW,GAAmB;AACtD,UAAS,IAAI,IAAK,KAAK,IAAI,CAAC,KAAK;AACnC;","names":[]}
|
||||
42
package/@stackframe/stack-shared/dist/esm/utils/node-http.js
vendored
Normal file
42
package/@stackframe/stack-shared/dist/esm/utils/node-http.js
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
// src/utils/node-http.tsx
|
||||
import { IncomingMessage, ServerResponse } from "http";
|
||||
import { getRelativePart } from "./urls";
|
||||
var ServerResponseWithBodyChunks = class extends ServerResponse {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.bodyChunks = [];
|
||||
}
|
||||
// note: we actually override this, even though it's private in the parent
|
||||
_send(data, encoding, callback, byteLength) {
|
||||
if (typeof encoding === "function") {
|
||||
callback = encoding;
|
||||
encoding = "utf-8";
|
||||
}
|
||||
const encodedBuffer = new Uint8Array(Buffer.from(data, encoding));
|
||||
this.bodyChunks.push(encodedBuffer);
|
||||
callback?.();
|
||||
}
|
||||
};
|
||||
async function createNodeHttpServerDuplex(options) {
|
||||
const incomingMessage = new IncomingMessage({
|
||||
encrypted: options.originalUrl?.protocol === "https:"
|
||||
// trick frameworks into believing this is an HTTPS request
|
||||
});
|
||||
incomingMessage.httpVersionMajor = 1;
|
||||
incomingMessage.httpVersionMinor = 1;
|
||||
incomingMessage.httpVersion = "1.1";
|
||||
incomingMessage.method = options.method;
|
||||
incomingMessage.url = getRelativePart(options.url);
|
||||
incomingMessage.originalUrl = options.originalUrl && getRelativePart(options.originalUrl);
|
||||
const rawHeaders = [...options.headers.entries()].flat();
|
||||
incomingMessage._addHeaderLines(rawHeaders, rawHeaders.length);
|
||||
incomingMessage.push(Buffer.from(options.body));
|
||||
incomingMessage.complete = true;
|
||||
incomingMessage.push(null);
|
||||
const serverResponse = new ServerResponseWithBodyChunks(incomingMessage);
|
||||
return [incomingMessage, serverResponse];
|
||||
}
|
||||
export {
|
||||
createNodeHttpServerDuplex
|
||||
};
|
||||
//# sourceMappingURL=node-http.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/node-http.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/node-http.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../../../src/utils/node-http.tsx"],"sourcesContent":["import { IncomingMessage, ServerResponse } from \"http\";\nimport { getRelativePart } from \"./urls\";\n\nclass ServerResponseWithBodyChunks extends ServerResponse {\n bodyChunks: Uint8Array[] = [];\n\n // note: we actually override this, even though it's private in the parent\n _send(data: string, encoding: BufferEncoding, callback?: (() => void) | null, byteLength?: number) {\n if (typeof encoding === \"function\") {\n callback = encoding;\n encoding = \"utf-8\";\n }\n const encodedBuffer = new Uint8Array(Buffer.from(data, encoding));\n this.bodyChunks.push(encodedBuffer);\n callback?.();\n }\n}\n\nexport async function createNodeHttpServerDuplex(options: {\n method: string,\n originalUrl?: URL,\n url: URL,\n headers: Headers,\n body: Uint8Array,\n}): Promise<[IncomingMessage, ServerResponseWithBodyChunks]> {\n // See https://github.com/nodejs/node/blob/main/lib/_http_incoming.js\n // and https://github.com/nodejs/node/blob/main/lib/_http_common.js (particularly the `parserXyz` functions)\n\n const incomingMessage = new IncomingMessage({\n encrypted: options.originalUrl?.protocol === \"https:\", // trick frameworks into believing this is an HTTPS request\n } as any);\n incomingMessage.httpVersionMajor = 1;\n incomingMessage.httpVersionMinor = 1;\n incomingMessage.httpVersion = '1.1';\n incomingMessage.method = options.method;\n incomingMessage.url = getRelativePart(options.url);\n (incomingMessage as any).originalUrl = options.originalUrl && getRelativePart(options.originalUrl); // originalUrl is an extension used by some servers; for example, oidc-provider reads it to construct the paths for the .well-known/openid-configuration\n const rawHeaders = [...options.headers.entries()].flat();\n (incomingMessage as any)._addHeaderLines(rawHeaders, rawHeaders.length);\n incomingMessage.push(Buffer.from(options.body));\n incomingMessage.complete = true;\n incomingMessage.push(null); // to emit end event, see: https://github.com/nodejs/node/blob/4cf6fabce20eb3050c5b543d249e931ea3d3cad5/lib/_http_common.js#L150\n\n const serverResponse = new ServerResponseWithBodyChunks(incomingMessage);\n\n return [incomingMessage, serverResponse];\n}\n"],"mappings":";AAAA,SAAS,iBAAiB,sBAAsB;AAChD,SAAS,uBAAuB;AAEhC,IAAM,+BAAN,cAA2C,eAAe;AAAA,EAA1D;AAAA;AACE,sBAA2B,CAAC;AAAA;AAAA;AAAA,EAG5B,MAAM,MAAc,UAA0B,UAAgC,YAAqB;AACjG,QAAI,OAAO,aAAa,YAAY;AAClC,iBAAW;AACX,iBAAW;AAAA,IACb;AACA,UAAM,gBAAgB,IAAI,WAAW,OAAO,KAAK,MAAM,QAAQ,CAAC;AAChE,SAAK,WAAW,KAAK,aAAa;AAClC,eAAW;AAAA,EACb;AACF;AAEA,eAAsB,2BAA2B,SAMY;AAI3D,QAAM,kBAAkB,IAAI,gBAAgB;AAAA,IAC1C,WAAW,QAAQ,aAAa,aAAa;AAAA;AAAA,EAC/C,CAAQ;AACR,kBAAgB,mBAAmB;AACnC,kBAAgB,mBAAmB;AACnC,kBAAgB,cAAc;AAC9B,kBAAgB,SAAS,QAAQ;AACjC,kBAAgB,MAAM,gBAAgB,QAAQ,GAAG;AACjD,EAAC,gBAAwB,cAAc,QAAQ,eAAe,gBAAgB,QAAQ,WAAW;AACjG,QAAM,aAAa,CAAC,GAAG,QAAQ,QAAQ,QAAQ,CAAC,EAAE,KAAK;AACvD,EAAC,gBAAwB,gBAAgB,YAAY,WAAW,MAAM;AACtE,kBAAgB,KAAK,OAAO,KAAK,QAAQ,IAAI,CAAC;AAC9C,kBAAgB,WAAW;AAC3B,kBAAgB,KAAK,IAAI;AAEzB,QAAM,iBAAiB,IAAI,6BAA6B,eAAe;AAEvE,SAAO,CAAC,iBAAiB,cAAc;AACzC;","names":[]}
|
||||
32
package/@stackframe/stack-shared/dist/esm/utils/numbers.js
vendored
Normal file
32
package/@stackframe/stack-shared/dist/esm/utils/numbers.js
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
// src/utils/numbers.tsx
|
||||
var magnitudes = [
|
||||
[1e15, "trln"],
|
||||
[1e12, "bln"],
|
||||
[1e9, "bn"],
|
||||
[1e6, "M"],
|
||||
[1e3, "k"]
|
||||
];
|
||||
function prettyPrintWithMagnitudes(num) {
|
||||
if (typeof num !== "number") throw new Error("Expected a number");
|
||||
if (Number.isNaN(num)) return "NaN";
|
||||
if (num < 0) return "-" + prettyPrintWithMagnitudes(-num);
|
||||
if (!Number.isFinite(num)) return "\u221E";
|
||||
for (const [magnitude, suffix] of magnitudes) {
|
||||
if (num >= magnitude) {
|
||||
return toFixedMax(num / magnitude, 1) + suffix;
|
||||
}
|
||||
}
|
||||
return toFixedMax(num, 1);
|
||||
}
|
||||
function toFixedMax(num, maxDecimals) {
|
||||
return num.toFixed(maxDecimals).replace(/\.?0+$/, "");
|
||||
}
|
||||
function numberCompare(a, b) {
|
||||
return Math.sign(a - b);
|
||||
}
|
||||
export {
|
||||
numberCompare,
|
||||
prettyPrintWithMagnitudes,
|
||||
toFixedMax
|
||||
};
|
||||
//# sourceMappingURL=numbers.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/numbers.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/numbers.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../../../src/utils/numbers.tsx"],"sourcesContent":["const magnitudes = [\n [1_000_000_000_000_000, \"trln\"],\n [1_000_000_000_000, \"bln\"],\n [1_000_000_000, \"bn\"],\n [1_000_000, \"M\"],\n [1_000, \"k\"],\n] as const;\n\nexport function prettyPrintWithMagnitudes(num: number): string {\n if (typeof num !== \"number\") throw new Error(\"Expected a number\");\n if (Number.isNaN(num)) return \"NaN\";\n if (num < 0) return \"-\" + prettyPrintWithMagnitudes(-num);\n if (!Number.isFinite(num)) return \"∞\";\n\n for (const [magnitude, suffix] of magnitudes) {\n if (num >= magnitude) {\n return toFixedMax(num / magnitude, 1) + suffix;\n }\n }\n return toFixedMax(num, 1); // Handle numbers less than 1,000 without suffix.\n}\nundefined?.test(\"prettyPrintWithMagnitudes\", ({ expect }) => {\n // Test different magnitudes\n expect(prettyPrintWithMagnitudes(1000)).toBe(\"1k\");\n expect(prettyPrintWithMagnitudes(1500)).toBe(\"1.5k\");\n expect(prettyPrintWithMagnitudes(1000000)).toBe(\"1M\");\n expect(prettyPrintWithMagnitudes(1500000)).toBe(\"1.5M\");\n expect(prettyPrintWithMagnitudes(1000000000)).toBe(\"1bn\");\n expect(prettyPrintWithMagnitudes(1500000000)).toBe(\"1.5bn\");\n expect(prettyPrintWithMagnitudes(1000000000000)).toBe(\"1bln\");\n expect(prettyPrintWithMagnitudes(1500000000000)).toBe(\"1.5bln\");\n expect(prettyPrintWithMagnitudes(1000000000000000)).toBe(\"1trln\");\n expect(prettyPrintWithMagnitudes(1500000000000000)).toBe(\"1.5trln\");\n // Test small numbers\n expect(prettyPrintWithMagnitudes(100)).toBe(\"100\");\n expect(prettyPrintWithMagnitudes(0)).toBe(\"0\");\n expect(prettyPrintWithMagnitudes(0.5)).toBe(\"0.5\");\n // Test negative numbers\n expect(prettyPrintWithMagnitudes(-1000)).toBe(\"-1k\");\n expect(prettyPrintWithMagnitudes(-1500000)).toBe(\"-1.5M\");\n // Test special cases\n expect(prettyPrintWithMagnitudes(NaN)).toBe(\"NaN\");\n expect(prettyPrintWithMagnitudes(Infinity)).toBe(\"∞\");\n expect(prettyPrintWithMagnitudes(-Infinity)).toBe(\"-∞\");\n});\n\nexport function toFixedMax(num: number, maxDecimals: number): string {\n return num.toFixed(maxDecimals).replace(/\\.?0+$/, \"\");\n}\nundefined?.test(\"toFixedMax\", ({ expect }) => {\n expect(toFixedMax(1, 2)).toBe(\"1\");\n expect(toFixedMax(1.2, 2)).toBe(\"1.2\");\n expect(toFixedMax(1.23, 2)).toBe(\"1.23\");\n expect(toFixedMax(1.234, 2)).toBe(\"1.23\");\n expect(toFixedMax(1.0, 2)).toBe(\"1\");\n expect(toFixedMax(1.20, 2)).toBe(\"1.2\");\n expect(toFixedMax(0, 2)).toBe(\"0\");\n});\n\nexport function numberCompare(a: number, b: number): number {\n return Math.sign(a - b);\n}\nundefined?.test(\"numberCompare\", ({ expect }) => {\n expect(numberCompare(1, 2)).toBe(-1);\n expect(numberCompare(2, 1)).toBe(1);\n expect(numberCompare(1, 1)).toBe(0);\n expect(numberCompare(0, 0)).toBe(0);\n expect(numberCompare(-1, -2)).toBe(1);\n expect(numberCompare(-2, -1)).toBe(-1);\n expect(numberCompare(-1, 1)).toBe(-1);\n expect(numberCompare(1, -1)).toBe(1);\n});\n"],"mappings":";AAAA,IAAM,aAAa;AAAA,EACjB,CAAC,MAAuB,MAAM;AAAA,EAC9B,CAAC,MAAmB,KAAK;AAAA,EACzB,CAAC,KAAe,IAAI;AAAA,EACpB,CAAC,KAAW,GAAG;AAAA,EACf,CAAC,KAAO,GAAG;AACb;AAEO,SAAS,0BAA0B,KAAqB;AAC7D,MAAI,OAAO,QAAQ,SAAU,OAAM,IAAI,MAAM,mBAAmB;AAChE,MAAI,OAAO,MAAM,GAAG,EAAG,QAAO;AAC9B,MAAI,MAAM,EAAG,QAAO,MAAM,0BAA0B,CAAC,GAAG;AACxD,MAAI,CAAC,OAAO,SAAS,GAAG,EAAG,QAAO;AAElC,aAAW,CAAC,WAAW,MAAM,KAAK,YAAY;AAC5C,QAAI,OAAO,WAAW;AACpB,aAAO,WAAW,MAAM,WAAW,CAAC,IAAI;AAAA,IAC1C;AAAA,EACF;AACA,SAAO,WAAW,KAAK,CAAC;AAC1B;AA0BO,SAAS,WAAW,KAAa,aAA6B;AACnE,SAAO,IAAI,QAAQ,WAAW,EAAE,QAAQ,UAAU,EAAE;AACtD;AAWO,SAAS,cAAc,GAAW,GAAmB;AAC1D,SAAO,KAAK,KAAK,IAAI,CAAC;AACxB;","names":[]}
|
||||
10
package/@stackframe/stack-shared/dist/esm/utils/oauth.js
vendored
Normal file
10
package/@stackframe/stack-shared/dist/esm/utils/oauth.js
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
// src/utils/oauth.tsx
|
||||
var standardProviders = ["google", "github", "microsoft", "spotify", "facebook", "discord", "gitlab", "bitbucket", "linkedin", "apple", "x"];
|
||||
var sharedProviders = ["google", "github", "microsoft", "spotify"];
|
||||
var allProviders = standardProviders;
|
||||
export {
|
||||
allProviders,
|
||||
sharedProviders,
|
||||
standardProviders
|
||||
};
|
||||
//# sourceMappingURL=oauth.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/oauth.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/oauth.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../../../src/utils/oauth.tsx"],"sourcesContent":["export const standardProviders = [\"google\", \"github\", \"microsoft\", \"spotify\", \"facebook\", \"discord\", \"gitlab\", \"bitbucket\", \"linkedin\", \"apple\", \"x\"] as const;\n// No more shared providers should be added except for special cases\nexport const sharedProviders = [\"google\", \"github\", \"microsoft\", \"spotify\"] as const;\nexport const allProviders = standardProviders;\n\nexport type ProviderType = typeof allProviders[number];\nexport type StandardProviderType = typeof standardProviders[number];\nexport type SharedProviderType = typeof sharedProviders[number];\n"],"mappings":";AAAO,IAAM,oBAAoB,CAAC,UAAU,UAAU,aAAa,WAAW,YAAY,WAAW,UAAU,aAAa,YAAY,SAAS,GAAG;AAE7I,IAAM,kBAAkB,CAAC,UAAU,UAAU,aAAa,SAAS;AACnE,IAAM,eAAe;","names":[]}
|
||||
177
package/@stackframe/stack-shared/dist/esm/utils/objects.js
vendored
Normal file
177
package/@stackframe/stack-shared/dist/esm/utils/objects.js
vendored
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
// src/utils/objects.tsx
|
||||
import { StackAssertionError } from "./errors";
|
||||
import { identity } from "./functions";
|
||||
import { stringCompare } from "./strings";
|
||||
function isNotNull(value) {
|
||||
return value !== null && value !== void 0;
|
||||
}
|
||||
function deepPlainEquals(obj1, obj2, options = {}) {
|
||||
if (typeof obj1 !== typeof obj2) return false;
|
||||
if (obj1 === obj2) return true;
|
||||
switch (typeof obj1) {
|
||||
case "object": {
|
||||
if (!obj1 || !obj2) return false;
|
||||
if (Array.isArray(obj1) || Array.isArray(obj2)) {
|
||||
if (!Array.isArray(obj1) || !Array.isArray(obj2)) return false;
|
||||
if (obj1.length !== obj2.length) return false;
|
||||
return obj1.every((v, i) => deepPlainEquals(v, obj2[i], options));
|
||||
}
|
||||
const entries1 = Object.entries(obj1).filter(([k, v]) => !options.ignoreUndefinedValues || v !== void 0);
|
||||
const entries2 = Object.entries(obj2).filter(([k, v]) => !options.ignoreUndefinedValues || v !== void 0);
|
||||
if (entries1.length !== entries2.length) return false;
|
||||
return entries1.every(([k, v1]) => {
|
||||
const e2 = entries2.find(([k2]) => k === k2);
|
||||
if (!e2) return false;
|
||||
return deepPlainEquals(v1, e2[1], options);
|
||||
});
|
||||
}
|
||||
case "undefined":
|
||||
case "string":
|
||||
case "number":
|
||||
case "boolean":
|
||||
case "bigint":
|
||||
case "symbol":
|
||||
case "function": {
|
||||
return false;
|
||||
}
|
||||
default: {
|
||||
throw new Error("Unexpected typeof " + typeof obj1);
|
||||
}
|
||||
}
|
||||
}
|
||||
function isCloneable(obj) {
|
||||
return typeof obj !== "symbol" && typeof obj !== "function";
|
||||
}
|
||||
function shallowClone(obj) {
|
||||
if (!isCloneable(obj)) throw new StackAssertionError("shallowClone does not support symbols or functions", { obj });
|
||||
if (Array.isArray(obj)) return obj.map(identity);
|
||||
return { ...obj };
|
||||
}
|
||||
function deepPlainClone(obj) {
|
||||
if (typeof obj === "function") throw new StackAssertionError("deepPlainClone does not support functions");
|
||||
if (typeof obj === "symbol") throw new StackAssertionError("deepPlainClone does not support symbols");
|
||||
if (typeof obj !== "object" || !obj) return obj;
|
||||
if (Array.isArray(obj)) return obj.map(deepPlainClone);
|
||||
return Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, deepPlainClone(v)]));
|
||||
}
|
||||
function deepMerge(baseObj, mergeObj) {
|
||||
if ([baseObj, mergeObj, ...Object.values(baseObj), ...Object.values(mergeObj)].some((o) => !isCloneable(o))) throw new StackAssertionError("deepMerge does not support functions or symbols", { baseObj, mergeObj });
|
||||
const res = shallowClone(baseObj);
|
||||
for (const [key, mergeValue] of Object.entries(mergeObj)) {
|
||||
if (has(res, key)) {
|
||||
const baseValue = get(res, key);
|
||||
if (isObjectLike(baseValue) && isObjectLike(mergeValue)) {
|
||||
set(res, key, deepMerge(baseValue, mergeValue));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
set(res, key, mergeValue);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
function typedEntries(obj) {
|
||||
return Object.entries(obj);
|
||||
}
|
||||
function typedFromEntries(entries) {
|
||||
return Object.fromEntries(entries);
|
||||
}
|
||||
function typedKeys(obj) {
|
||||
return Object.keys(obj);
|
||||
}
|
||||
function typedValues(obj) {
|
||||
return Object.values(obj);
|
||||
}
|
||||
function typedAssign(target, source) {
|
||||
return Object.assign(target, source);
|
||||
}
|
||||
function filterUndefined(obj) {
|
||||
return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== void 0));
|
||||
}
|
||||
function filterUndefinedOrNull(obj) {
|
||||
return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== void 0 && v !== null));
|
||||
}
|
||||
function deepFilterUndefined(obj) {
|
||||
return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== void 0).map(([k, v]) => [k, isObjectLike(v) ? deepFilterUndefined(v) : v]));
|
||||
}
|
||||
function pick(obj, keys) {
|
||||
return Object.fromEntries(Object.entries(obj).filter(([k]) => keys.includes(k)));
|
||||
}
|
||||
function omit(obj, keys) {
|
||||
if (!Array.isArray(keys)) throw new StackAssertionError("omit: keys must be an array", { obj, keys });
|
||||
return Object.fromEntries(Object.entries(obj).filter(([k]) => !keys.includes(k)));
|
||||
}
|
||||
function split(obj, keys) {
|
||||
return [pick(obj, keys), omit(obj, keys)];
|
||||
}
|
||||
function mapValues(obj, fn) {
|
||||
if (Array.isArray(obj)) {
|
||||
return obj.map((v) => fn(v));
|
||||
}
|
||||
return Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, fn(v)]));
|
||||
}
|
||||
function sortKeys(obj) {
|
||||
if (Array.isArray(obj)) {
|
||||
return [...obj];
|
||||
}
|
||||
return Object.fromEntries(Object.entries(obj).sort(([a], [b]) => stringCompare(a, b)));
|
||||
}
|
||||
function deepSortKeys(obj) {
|
||||
return sortKeys(mapValues(obj, (v) => isObjectLike(v) ? deepSortKeys(v) : v));
|
||||
}
|
||||
function set(obj, key, value) {
|
||||
Object.defineProperty(obj, key, { value, writable: true, configurable: true, enumerable: true });
|
||||
}
|
||||
function get(obj, key) {
|
||||
const descriptor = Object.getOwnPropertyDescriptor(obj, key);
|
||||
if (!descriptor) throw new StackAssertionError(`get: key ${String(key)} does not exist`, { obj, key });
|
||||
return descriptor.value;
|
||||
}
|
||||
function getOrUndefined(obj, key) {
|
||||
return has(obj, key) ? get(obj, key) : void 0;
|
||||
}
|
||||
function has(obj, key) {
|
||||
return Object.prototype.hasOwnProperty.call(obj, key);
|
||||
}
|
||||
function hasAndNotUndefined(obj, key) {
|
||||
return has(obj, key) && get(obj, key) !== void 0;
|
||||
}
|
||||
function deleteKey(obj, key) {
|
||||
if (has(obj, key)) {
|
||||
Reflect.deleteProperty(obj, key);
|
||||
} else {
|
||||
throw new StackAssertionError(`deleteKey: key ${String(key)} does not exist`, { obj, key });
|
||||
}
|
||||
}
|
||||
function isObjectLike(value) {
|
||||
return (typeof value === "object" || typeof value === "function") && value !== null;
|
||||
}
|
||||
export {
|
||||
deepFilterUndefined,
|
||||
deepMerge,
|
||||
deepPlainClone,
|
||||
deepPlainEquals,
|
||||
deepSortKeys,
|
||||
deleteKey,
|
||||
filterUndefined,
|
||||
filterUndefinedOrNull,
|
||||
get,
|
||||
getOrUndefined,
|
||||
has,
|
||||
hasAndNotUndefined,
|
||||
isCloneable,
|
||||
isNotNull,
|
||||
isObjectLike,
|
||||
mapValues,
|
||||
omit,
|
||||
pick,
|
||||
set,
|
||||
shallowClone,
|
||||
sortKeys,
|
||||
split,
|
||||
typedAssign,
|
||||
typedEntries,
|
||||
typedFromEntries,
|
||||
typedKeys,
|
||||
typedValues
|
||||
};
|
||||
//# sourceMappingURL=objects.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/objects.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/objects.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
1
package/@stackframe/stack-shared/dist/esm/utils/passkey.js
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/passkey.js
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
//# sourceMappingURL=passkey.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/passkey.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/passkey.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
||||
233
package/@stackframe/stack-shared/dist/esm/utils/promises.js
vendored
Normal file
233
package/@stackframe/stack-shared/dist/esm/utils/promises.js
vendored
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
// src/utils/promises.tsx
|
||||
import { KnownError } from "..";
|
||||
import { StackAssertionError, captureError, concatStacktraces } from "./errors";
|
||||
import { DependenciesMap } from "./maps";
|
||||
import { Result } from "./results";
|
||||
import { generateUuid } from "./uuids";
|
||||
function createPromise(callback) {
|
||||
let status = "pending";
|
||||
let valueOrReason = void 0;
|
||||
let resolve = null;
|
||||
let reject = null;
|
||||
const promise = new Promise((res, rej) => {
|
||||
resolve = (value) => {
|
||||
if (status !== "pending") return;
|
||||
status = "fulfilled";
|
||||
valueOrReason = value;
|
||||
res(value);
|
||||
};
|
||||
reject = (reason) => {
|
||||
if (status !== "pending") return;
|
||||
status = "rejected";
|
||||
valueOrReason = reason;
|
||||
rej(reason);
|
||||
};
|
||||
});
|
||||
callback(resolve, reject);
|
||||
return Object.assign(promise, {
|
||||
status,
|
||||
...status === "fulfilled" ? { value: valueOrReason } : {},
|
||||
...status === "rejected" ? { reason: valueOrReason } : {}
|
||||
});
|
||||
}
|
||||
var resolvedCache = null;
|
||||
function resolved(value) {
|
||||
resolvedCache ??= new DependenciesMap();
|
||||
if (resolvedCache.has([value])) {
|
||||
return resolvedCache.get([value]);
|
||||
}
|
||||
const res = Object.assign(Promise.resolve(value), {
|
||||
status: "fulfilled",
|
||||
value
|
||||
});
|
||||
resolvedCache.set([value], res);
|
||||
return res;
|
||||
}
|
||||
var rejectedCache = null;
|
||||
function rejected(reason) {
|
||||
rejectedCache ??= new DependenciesMap();
|
||||
if (rejectedCache.has([reason])) {
|
||||
return rejectedCache.get([reason]);
|
||||
}
|
||||
const promise = Promise.reject(reason);
|
||||
ignoreUnhandledRejection(promise);
|
||||
const res = Object.assign(promise, {
|
||||
status: "rejected",
|
||||
reason
|
||||
});
|
||||
rejectedCache.set([reason], res);
|
||||
return res;
|
||||
}
|
||||
var neverResolvePromise = pending(new Promise(() => {
|
||||
}));
|
||||
function neverResolve() {
|
||||
return neverResolvePromise;
|
||||
}
|
||||
function pending(promise, options = {}) {
|
||||
const res = promise.then(
|
||||
(value) => {
|
||||
res.status = "fulfilled";
|
||||
res.value = value;
|
||||
return value;
|
||||
},
|
||||
(actualReason) => {
|
||||
res.status = "rejected";
|
||||
res.reason = actualReason;
|
||||
throw actualReason;
|
||||
}
|
||||
);
|
||||
res.status = "pending";
|
||||
return res;
|
||||
}
|
||||
function ignoreUnhandledRejection(promise) {
|
||||
promise.catch(() => {
|
||||
});
|
||||
}
|
||||
async function wait(ms) {
|
||||
if (!Number.isFinite(ms) || ms < 0) {
|
||||
throw new StackAssertionError(`wait() requires a non-negative integer number of milliseconds to wait. (found: ${ms}ms)`);
|
||||
}
|
||||
if (ms >= 2 ** 31) {
|
||||
throw new StackAssertionError("The maximum timeout for wait() is 2147483647ms (2**31 - 1). (found: ${ms}ms)");
|
||||
}
|
||||
return await new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
async function waitUntil(date) {
|
||||
return await wait(date.getTime() - Date.now());
|
||||
}
|
||||
function runAsynchronouslyWithAlert(...args) {
|
||||
return runAsynchronously(
|
||||
args[0],
|
||||
{
|
||||
...args[1],
|
||||
onError: (error) => {
|
||||
if (KnownError.isKnownError(error) && typeof process !== "undefined" && process.env.NODE_ENV?.includes("production")) {
|
||||
alert(error.message);
|
||||
} else {
|
||||
alert(`An unhandled error occurred. Please ${process.env.NODE_ENV === "development" ? `check the browser console for the full error.` : "report this to the developer."}
|
||||
|
||||
${error}`);
|
||||
}
|
||||
args[1]?.onError?.(error);
|
||||
}
|
||||
},
|
||||
...args.slice(2)
|
||||
);
|
||||
}
|
||||
function runAsynchronously(promiseOrFunc, options = {}) {
|
||||
if (typeof promiseOrFunc === "function") {
|
||||
promiseOrFunc = promiseOrFunc();
|
||||
}
|
||||
const duringError = new Error();
|
||||
promiseOrFunc?.catch((error) => {
|
||||
options.onError?.(error);
|
||||
const newError = new StackAssertionError(
|
||||
"Uncaught error in asynchronous function: " + error.toString(),
|
||||
{ cause: error }
|
||||
);
|
||||
concatStacktraces(newError, duringError);
|
||||
if (!options.noErrorLogging) {
|
||||
captureError("runAsynchronously", newError);
|
||||
}
|
||||
});
|
||||
}
|
||||
var TimeoutError = class extends Error {
|
||||
constructor(ms) {
|
||||
super(`Timeout after ${ms}ms`);
|
||||
this.ms = ms;
|
||||
this.name = "TimeoutError";
|
||||
}
|
||||
};
|
||||
async function timeout(promise, ms) {
|
||||
return await Promise.race([
|
||||
promise.then((value) => Result.ok(value)),
|
||||
wait(ms).then(() => Result.error(new TimeoutError(ms)))
|
||||
]);
|
||||
}
|
||||
async function timeoutThrow(promise, ms) {
|
||||
return Result.orThrow(await timeout(promise, ms));
|
||||
}
|
||||
function rateLimited(func, options) {
|
||||
let waitUntil2 = performance.now();
|
||||
let queue = [];
|
||||
let addedToQueueCallbacks = /* @__PURE__ */ new Map();
|
||||
const next = async () => {
|
||||
while (true) {
|
||||
if (waitUntil2 > performance.now()) {
|
||||
await wait(Math.max(1, waitUntil2 - performance.now() + 1));
|
||||
} else if (queue.length === 0) {
|
||||
const uuid = generateUuid();
|
||||
await new Promise((resolve) => {
|
||||
addedToQueueCallbacks.set(uuid, resolve);
|
||||
});
|
||||
addedToQueueCallbacks.delete(uuid);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
const nextFuncs = options.batchCalls ? queue.splice(0, queue.length) : [queue.shift()];
|
||||
const start = performance.now();
|
||||
const value = await Result.fromPromise(func());
|
||||
const end = performance.now();
|
||||
waitUntil2 = Math.max(
|
||||
waitUntil2,
|
||||
start + (options.throttleMs ?? 0),
|
||||
end + (options.gapMs ?? 0)
|
||||
);
|
||||
for (const nextFunc of nextFuncs) {
|
||||
if (value.status === "ok") {
|
||||
nextFunc[0](value.data);
|
||||
} else {
|
||||
nextFunc[1](value.error);
|
||||
}
|
||||
}
|
||||
};
|
||||
runAsynchronously(async () => {
|
||||
while (true) {
|
||||
await next();
|
||||
}
|
||||
});
|
||||
return () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
waitUntil2 = Math.max(
|
||||
waitUntil2,
|
||||
performance.now() + (options.debounceMs ?? 0)
|
||||
);
|
||||
queue.push([resolve, reject]);
|
||||
addedToQueueCallbacks.forEach((cb) => cb());
|
||||
});
|
||||
};
|
||||
}
|
||||
function throttled(func, delayMs) {
|
||||
let timeout2 = null;
|
||||
let nextAvailable = null;
|
||||
return async (...args) => {
|
||||
while (nextAvailable !== null) {
|
||||
await nextAvailable;
|
||||
}
|
||||
nextAvailable = new Promise((resolve) => {
|
||||
timeout2 = setTimeout(() => {
|
||||
nextAvailable = null;
|
||||
resolve(func(...args));
|
||||
}, delayMs);
|
||||
});
|
||||
return await nextAvailable;
|
||||
};
|
||||
}
|
||||
export {
|
||||
createPromise,
|
||||
ignoreUnhandledRejection,
|
||||
neverResolve,
|
||||
pending,
|
||||
rateLimited,
|
||||
rejected,
|
||||
resolved,
|
||||
runAsynchronously,
|
||||
runAsynchronouslyWithAlert,
|
||||
throttled,
|
||||
timeout,
|
||||
timeoutThrow,
|
||||
wait,
|
||||
waitUntil
|
||||
};
|
||||
//# sourceMappingURL=promises.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/promises.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/promises.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
128
package/@stackframe/stack-shared/dist/esm/utils/proxies.js
vendored
Normal file
128
package/@stackframe/stack-shared/dist/esm/utils/proxies.js
vendored
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
// src/utils/proxies.tsx
|
||||
import { nicify } from "./strings";
|
||||
function logged(name, toLog, options = {}) {
|
||||
const proxy = new Proxy(toLog, {
|
||||
get(target, prop, receiver) {
|
||||
const orig = Reflect.get(target, prop, receiver);
|
||||
if (typeof orig === "function") {
|
||||
return function(...args) {
|
||||
const success = (v, isPromise) => console.debug(`logged(...): Called ${name}.${String(prop)}(${args.map((a) => nicify(a)).join(", ")}) => ${isPromise ? "Promise<" : ""}${nicify(result)}${isPromise ? ">" : ""}`, { this: this, args, promise: isPromise ? result : false, result: v, trace: new Error() });
|
||||
const error = (e, isPromise) => console.debug(`logged(...): Error in ${name}.${String(prop)}(${args.map((a) => nicify(a)).join(", ")})`, { this: this, args, promise: isPromise ? result : false, error: e, trace: new Error() });
|
||||
let result;
|
||||
try {
|
||||
result = orig.apply(this, args);
|
||||
} catch (e) {
|
||||
error(e, false);
|
||||
throw e;
|
||||
}
|
||||
if (result instanceof Promise) {
|
||||
result.then((v) => success(v, true)).catch((e) => error(e, true));
|
||||
} else {
|
||||
success(result, false);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
return orig;
|
||||
},
|
||||
set(target, prop, value) {
|
||||
console.log(`Setting ${name}.${String(prop)} to ${value}`);
|
||||
return Reflect.set(target, prop, value);
|
||||
},
|
||||
apply(target, thisArg, args) {
|
||||
console.log(`Calling ${name}(${JSON.stringify(args).slice(1, -1)})`);
|
||||
return Reflect.apply(target, thisArg, args);
|
||||
},
|
||||
construct(target, args, newTarget) {
|
||||
console.log(`Constructing ${name}(${JSON.stringify(args).slice(1, -1)})`);
|
||||
return Reflect.construct(target, args, newTarget);
|
||||
},
|
||||
defineProperty(target, prop, descriptor) {
|
||||
console.log(`Defining ${name}.${String(prop)} as ${JSON.stringify(descriptor)}`);
|
||||
return Reflect.defineProperty(target, prop, descriptor);
|
||||
},
|
||||
deleteProperty(target, prop) {
|
||||
console.log(`Deleting ${name}.${String(prop)}`);
|
||||
return Reflect.deleteProperty(target, prop);
|
||||
},
|
||||
setPrototypeOf(target, prototype) {
|
||||
console.log(`Setting prototype of ${name} to ${prototype}`);
|
||||
return Reflect.setPrototypeOf(target, prototype);
|
||||
},
|
||||
preventExtensions(target) {
|
||||
console.log(`Preventing extensions of ${name}`);
|
||||
return Reflect.preventExtensions(target);
|
||||
}
|
||||
});
|
||||
return proxy;
|
||||
}
|
||||
function createLazyProxy(factory) {
|
||||
let cache = void 0;
|
||||
let initialized = false;
|
||||
function initializeIfNeeded() {
|
||||
if (!initialized) {
|
||||
cache = factory();
|
||||
initialized = true;
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
return new Proxy({}, {
|
||||
get(target, prop, receiver) {
|
||||
const instance = initializeIfNeeded();
|
||||
return Reflect.get(instance, prop, receiver);
|
||||
},
|
||||
set(target, prop, value, receiver) {
|
||||
const instance = initializeIfNeeded();
|
||||
return Reflect.set(instance, prop, value, receiver);
|
||||
},
|
||||
has(target, prop) {
|
||||
const instance = initializeIfNeeded();
|
||||
return Reflect.has(instance, prop);
|
||||
},
|
||||
deleteProperty(target, prop) {
|
||||
const instance = initializeIfNeeded();
|
||||
return Reflect.deleteProperty(instance, prop);
|
||||
},
|
||||
ownKeys(target) {
|
||||
const instance = initializeIfNeeded();
|
||||
return Reflect.ownKeys(instance);
|
||||
},
|
||||
getOwnPropertyDescriptor(target, prop) {
|
||||
const instance = initializeIfNeeded();
|
||||
return Reflect.getOwnPropertyDescriptor(instance, prop);
|
||||
},
|
||||
defineProperty(target, prop, descriptor) {
|
||||
const instance = initializeIfNeeded();
|
||||
return Reflect.defineProperty(instance, prop, descriptor);
|
||||
},
|
||||
getPrototypeOf(target) {
|
||||
const instance = initializeIfNeeded();
|
||||
return Reflect.getPrototypeOf(instance);
|
||||
},
|
||||
setPrototypeOf(target, proto) {
|
||||
const instance = initializeIfNeeded();
|
||||
return Reflect.setPrototypeOf(instance, proto);
|
||||
},
|
||||
isExtensible(target) {
|
||||
const instance = initializeIfNeeded();
|
||||
return Reflect.isExtensible(instance);
|
||||
},
|
||||
preventExtensions(target) {
|
||||
const instance = initializeIfNeeded();
|
||||
return Reflect.preventExtensions(instance);
|
||||
},
|
||||
apply(target, thisArg, argumentsList) {
|
||||
const instance = initializeIfNeeded();
|
||||
return Reflect.apply(instance, thisArg, argumentsList);
|
||||
},
|
||||
construct(target, argumentsList, newTarget) {
|
||||
const instance = initializeIfNeeded();
|
||||
return Reflect.construct(instance, argumentsList, newTarget);
|
||||
}
|
||||
});
|
||||
}
|
||||
export {
|
||||
createLazyProxy,
|
||||
logged
|
||||
};
|
||||
//# sourceMappingURL=proxies.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/proxies.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/proxies.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
78
package/@stackframe/stack-shared/dist/esm/utils/react.js
vendored
Normal file
78
package/@stackframe/stack-shared/dist/esm/utils/react.js
vendored
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
// src/utils/react.tsx
|
||||
import React from "react";
|
||||
import { isBrowserLike } from "./env";
|
||||
import { neverResolve } from "./promises";
|
||||
import { deindent } from "./strings";
|
||||
function forwardRefIfNeeded(render) {
|
||||
const version = React.version;
|
||||
const major = parseInt(version.split(".")[0]);
|
||||
if (major < 19) {
|
||||
return React.forwardRef(render);
|
||||
} else {
|
||||
return (props) => render(props, props.ref);
|
||||
}
|
||||
}
|
||||
function getNodeText(node) {
|
||||
if (["number", "string"].includes(typeof node)) {
|
||||
return `${node}`;
|
||||
}
|
||||
if (!node) {
|
||||
return "";
|
||||
}
|
||||
if (Array.isArray(node)) {
|
||||
return node.map(getNodeText).join("");
|
||||
}
|
||||
if (typeof node === "object" && "props" in node) {
|
||||
return getNodeText(node.props.children);
|
||||
}
|
||||
throw new Error(`Unknown node type: ${typeof node}`);
|
||||
}
|
||||
function suspend() {
|
||||
React.use(neverResolve());
|
||||
throw new Error("Somehow a Promise that never resolves was resolved?");
|
||||
}
|
||||
var NoSuspenseBoundaryError = class extends Error {
|
||||
constructor(options) {
|
||||
super(deindent`
|
||||
${options.caller ?? "This code path"} attempted to display a loading indicator, but didn't find a Suspense boundary above it. Please read the error message below carefully.
|
||||
|
||||
The fix depends on which of the 3 scenarios caused it:
|
||||
|
||||
1. You are missing a loading.tsx file in your app directory. Fix it by adding a loading.tsx file in your app directory.
|
||||
|
||||
2. The component is rendered in the root (outermost) layout.tsx or template.tsx file. Next.js does not wrap those files in a Suspense boundary, even if there is a loading.tsx file in the same folder. To fix it, wrap your layout inside a route group like this:
|
||||
|
||||
- app
|
||||
- - layout.tsx // contains <html> and <body>, alongside providers and other components that don't need ${options.caller ?? "this code path"}
|
||||
- - loading.tsx // required for suspense
|
||||
- - (main)
|
||||
- - - layout.tsx // contains the main layout of your app, like a sidebar or a header, and can use ${options.caller ?? "this code path"}
|
||||
- - - route.tsx // your actual main page
|
||||
- - - the rest of your app
|
||||
|
||||
For more information on this approach, see Next's documentation on route groups: https://nextjs.org/docs/app/building-your-application/routing/route-groups
|
||||
|
||||
3. You caught this error with try-catch or a custom error boundary. Fix this by rethrowing the error or not catching it in the first place.
|
||||
|
||||
See: https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout
|
||||
|
||||
More information on SSR and Suspense boundaries: https://react.dev/reference/react/Suspense#providing-a-fallback-for-server-errors-and-client-only-content
|
||||
`);
|
||||
this.name = "NoSuspenseBoundaryError";
|
||||
this.reason = options.caller ?? "suspendIfSsr()";
|
||||
this.digest = "BAILOUT_TO_CLIENT_SIDE_RENDERING";
|
||||
}
|
||||
};
|
||||
function suspendIfSsr(caller) {
|
||||
if (!isBrowserLike()) {
|
||||
throw new NoSuspenseBoundaryError({ caller });
|
||||
}
|
||||
}
|
||||
export {
|
||||
NoSuspenseBoundaryError,
|
||||
forwardRefIfNeeded,
|
||||
getNodeText,
|
||||
suspend,
|
||||
suspendIfSsr
|
||||
};
|
||||
//# sourceMappingURL=react.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/react.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/react.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
141
package/@stackframe/stack-shared/dist/esm/utils/results.js
vendored
Normal file
141
package/@stackframe/stack-shared/dist/esm/utils/results.js
vendored
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
// src/utils/results.tsx
|
||||
import { wait } from "./promises";
|
||||
import { deindent, nicify } from "./strings";
|
||||
var Result = {
|
||||
fromThrowing,
|
||||
fromThrowingAsync,
|
||||
fromPromise: promiseToResult,
|
||||
ok(data) {
|
||||
return {
|
||||
status: "ok",
|
||||
data
|
||||
};
|
||||
},
|
||||
error(error) {
|
||||
return {
|
||||
status: "error",
|
||||
error
|
||||
};
|
||||
},
|
||||
map: mapResult,
|
||||
or: (result, fallback) => {
|
||||
return result.status === "ok" ? result.data : fallback;
|
||||
},
|
||||
orThrow: (result) => {
|
||||
if (result.status === "error") {
|
||||
throw result.error;
|
||||
}
|
||||
return result.data;
|
||||
},
|
||||
orThrowAsync: async (result) => {
|
||||
return Result.orThrow(await result);
|
||||
},
|
||||
retry
|
||||
};
|
||||
var AsyncResult = {
|
||||
fromThrowing,
|
||||
fromPromise: promiseToResult,
|
||||
ok: Result.ok,
|
||||
error: Result.error,
|
||||
pending,
|
||||
map: mapResult,
|
||||
or: (result, fallback) => {
|
||||
if (result.status === "pending") {
|
||||
return fallback;
|
||||
}
|
||||
return Result.or(result, fallback);
|
||||
},
|
||||
orThrow: (result) => {
|
||||
if (result.status === "pending") {
|
||||
throw new Error("Result still pending");
|
||||
}
|
||||
return Result.orThrow(result);
|
||||
},
|
||||
retry
|
||||
};
|
||||
function pending(progress) {
|
||||
return {
|
||||
status: "pending",
|
||||
progress
|
||||
};
|
||||
}
|
||||
async function promiseToResult(promise) {
|
||||
try {
|
||||
const value = await promise;
|
||||
return Result.ok(value);
|
||||
} catch (error) {
|
||||
return Result.error(error);
|
||||
}
|
||||
}
|
||||
function fromThrowing(fn) {
|
||||
try {
|
||||
return Result.ok(fn());
|
||||
} catch (error) {
|
||||
return Result.error(error);
|
||||
}
|
||||
}
|
||||
async function fromThrowingAsync(fn) {
|
||||
try {
|
||||
return Result.ok(await fn());
|
||||
} catch (error) {
|
||||
return Result.error(error);
|
||||
}
|
||||
}
|
||||
function mapResult(result, fn) {
|
||||
if (result.status === "error") return {
|
||||
status: "error",
|
||||
error: result.error
|
||||
};
|
||||
if (result.status === "pending") return {
|
||||
status: "pending",
|
||||
..."progress" in result ? { progress: result.progress } : {}
|
||||
};
|
||||
return Result.ok(fn(result.data));
|
||||
}
|
||||
var RetryError = class extends AggregateError {
|
||||
constructor(errors) {
|
||||
const strings = errors.map((e) => nicify(e));
|
||||
const isAllSame = strings.length > 1 && strings.every((s) => s === strings[0]);
|
||||
super(
|
||||
errors,
|
||||
deindent`
|
||||
Error after ${errors.length} attempts.
|
||||
|
||||
${isAllSame ? deindent`
|
||||
Attempts 1-${errors.length}:
|
||||
${strings[0]}
|
||||
` : strings.map((s, i) => deindent`
|
||||
Attempt ${i + 1}:
|
||||
${s}
|
||||
`).join("\n\n")}
|
||||
`,
|
||||
{ cause: errors[errors.length - 1] }
|
||||
);
|
||||
this.errors = errors;
|
||||
this.name = "RetryError";
|
||||
}
|
||||
get attempts() {
|
||||
return this.errors.length;
|
||||
}
|
||||
};
|
||||
RetryError.prototype.name = "RetryError";
|
||||
async function retry(fn, totalAttempts, { exponentialDelayBase = 1e3 } = {}) {
|
||||
const errors = [];
|
||||
for (let i = 0; i < totalAttempts; i++) {
|
||||
const res = await fn(i);
|
||||
if (res.status === "ok") {
|
||||
return Object.assign(Result.ok(res.data), { attempts: i + 1 });
|
||||
} else {
|
||||
errors.push(res.error);
|
||||
if (i < totalAttempts - 1) {
|
||||
await wait((Math.random() + 0.5) * exponentialDelayBase * 2 ** i);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Object.assign(Result.error(new RetryError(errors)), { attempts: totalAttempts });
|
||||
}
|
||||
export {
|
||||
AsyncResult,
|
||||
Result
|
||||
};
|
||||
//# sourceMappingURL=results.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/results.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/results.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
20
package/@stackframe/stack-shared/dist/esm/utils/sentry.js
vendored
Normal file
20
package/@stackframe/stack-shared/dist/esm/utils/sentry.js
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// src/utils/sentry.tsx
|
||||
var sentryBaseConfig = {
|
||||
ignoreErrors: [
|
||||
// React throws these errors when used with some browser extensions (eg. Google Translate)
|
||||
"NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.",
|
||||
"NotFoundError: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node."
|
||||
],
|
||||
normalizeDepth: 5,
|
||||
maxValueLength: 5e3,
|
||||
// Adjust this value in production, or use tracesSampler for greater control
|
||||
tracesSampleRate: 1,
|
||||
// Setting this option to true will print useful information to the console while you're setting up Sentry.
|
||||
debug: false,
|
||||
replaysOnErrorSampleRate: 1,
|
||||
replaysSessionSampleRate: 1
|
||||
};
|
||||
export {
|
||||
sentryBaseConfig
|
||||
};
|
||||
//# sourceMappingURL=sentry.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/sentry.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/sentry.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../../../src/utils/sentry.tsx"],"sourcesContent":["import * as Sentry from \"@sentry/nextjs\";\n\nexport const sentryBaseConfig: Sentry.BrowserOptions & Sentry.NodeOptions & Sentry.VercelEdgeOptions = {\n ignoreErrors: [\n // React throws these errors when used with some browser extensions (eg. Google Translate)\n \"NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.\",\n \"NotFoundError: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node.\",\n ],\n\n normalizeDepth: 5,\n maxValueLength: 5000,\n\n // Adjust this value in production, or use tracesSampler for greater control\n tracesSampleRate: 1.0,\n\n // Setting this option to true will print useful information to the console while you're setting up Sentry.\n debug: false,\n\n replaysOnErrorSampleRate: 1.0,\n\n replaysSessionSampleRate: 1.0,\n};\n"],"mappings":";AAEO,IAAM,mBAA0F;AAAA,EACrG,cAAc;AAAA;AAAA,IAEZ;AAAA,IACA;AAAA,EACF;AAAA,EAEA,gBAAgB;AAAA,EAChB,gBAAgB;AAAA;AAAA,EAGhB,kBAAkB;AAAA;AAAA,EAGlB,OAAO;AAAA,EAEP,0BAA0B;AAAA,EAE1B,0BAA0B;AAC5B;","names":[]}
|
||||
195
package/@stackframe/stack-shared/dist/esm/utils/stores.js
vendored
Normal file
195
package/@stackframe/stack-shared/dist/esm/utils/stores.js
vendored
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
// src/utils/stores.tsx
|
||||
import { ReadWriteLock } from "./locks";
|
||||
import { pending, rejected, resolved } from "./promises";
|
||||
import { AsyncResult, Result } from "./results";
|
||||
import { generateUuid } from "./uuids";
|
||||
var Store = class {
|
||||
constructor(_value) {
|
||||
this._value = _value;
|
||||
this._callbacks = /* @__PURE__ */ new Map();
|
||||
}
|
||||
get() {
|
||||
return this._value;
|
||||
}
|
||||
set(value) {
|
||||
const oldValue = this._value;
|
||||
this._value = value;
|
||||
this._callbacks.forEach((callback) => callback(value, oldValue));
|
||||
}
|
||||
update(updater) {
|
||||
const value = updater(this._value);
|
||||
this.set(value);
|
||||
return value;
|
||||
}
|
||||
onChange(callback) {
|
||||
const uuid = generateUuid();
|
||||
this._callbacks.set(uuid, callback);
|
||||
return {
|
||||
unsubscribe: () => {
|
||||
this._callbacks.delete(uuid);
|
||||
}
|
||||
};
|
||||
}
|
||||
onceChange(callback) {
|
||||
const { unsubscribe } = this.onChange((...args) => {
|
||||
unsubscribe();
|
||||
callback(...args);
|
||||
});
|
||||
return { unsubscribe };
|
||||
}
|
||||
};
|
||||
var storeLock = new ReadWriteLock();
|
||||
var AsyncStore = class _AsyncStore {
|
||||
constructor(...args) {
|
||||
this._mostRecentOkValue = void 0;
|
||||
this._isRejected = false;
|
||||
this._waitingRejectFunctions = /* @__PURE__ */ new Map();
|
||||
this._callbacks = /* @__PURE__ */ new Map();
|
||||
this._updateCounter = 0;
|
||||
this._lastSuccessfulUpdate = -1;
|
||||
if (args.length === 0) {
|
||||
this._isAvailable = false;
|
||||
} else {
|
||||
this._isAvailable = true;
|
||||
this._mostRecentOkValue = args[0];
|
||||
}
|
||||
}
|
||||
isAvailable() {
|
||||
return this._isAvailable;
|
||||
}
|
||||
isRejected() {
|
||||
return this._isRejected;
|
||||
}
|
||||
get() {
|
||||
if (this.isRejected()) {
|
||||
return AsyncResult.error(this._rejectionError);
|
||||
} else if (this.isAvailable()) {
|
||||
return AsyncResult.ok(this._mostRecentOkValue);
|
||||
} else {
|
||||
return AsyncResult.pending();
|
||||
}
|
||||
}
|
||||
getOrWait() {
|
||||
const uuid = generateUuid();
|
||||
if (this.isRejected()) {
|
||||
return rejected(this._rejectionError);
|
||||
} else if (this.isAvailable()) {
|
||||
return resolved(this._mostRecentOkValue);
|
||||
}
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
this.onceChange((value) => {
|
||||
resolve(value);
|
||||
});
|
||||
this._waitingRejectFunctions.set(uuid, reject);
|
||||
});
|
||||
const withFinally = promise.finally(() => {
|
||||
this._waitingRejectFunctions.delete(uuid);
|
||||
});
|
||||
return pending(withFinally);
|
||||
}
|
||||
_setIfLatest(result, curCounter) {
|
||||
const oldState = this.get();
|
||||
const oldValue = this._mostRecentOkValue;
|
||||
if (curCounter > this._lastSuccessfulUpdate) {
|
||||
switch (result.status) {
|
||||
case "ok": {
|
||||
if (!this._isAvailable || this._isRejected || this._mostRecentOkValue !== result.data) {
|
||||
this._lastSuccessfulUpdate = curCounter;
|
||||
this._isAvailable = true;
|
||||
this._isRejected = false;
|
||||
this._mostRecentOkValue = result.data;
|
||||
this._rejectionError = void 0;
|
||||
this._callbacks.forEach((callback) => callback({
|
||||
state: this.get(),
|
||||
oldState,
|
||||
lastOkValue: oldValue
|
||||
}));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case "error": {
|
||||
this._lastSuccessfulUpdate = curCounter;
|
||||
this._isAvailable = false;
|
||||
this._isRejected = true;
|
||||
this._rejectionError = result.error;
|
||||
this._waitingRejectFunctions.forEach((reject) => reject(result.error));
|
||||
this._callbacks.forEach((callback) => callback({
|
||||
state: this.get(),
|
||||
oldState,
|
||||
lastOkValue: oldValue
|
||||
}));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
set(value) {
|
||||
this._setIfLatest(Result.ok(value), ++this._updateCounter);
|
||||
}
|
||||
update(updater) {
|
||||
const value = updater(this._mostRecentOkValue);
|
||||
this.set(value);
|
||||
return value;
|
||||
}
|
||||
async setAsync(promise) {
|
||||
return await storeLock.withReadLock(async () => {
|
||||
const curCounter = ++this._updateCounter;
|
||||
const result = await Result.fromPromise(promise);
|
||||
return this._setIfLatest(result, curCounter);
|
||||
});
|
||||
}
|
||||
setUnavailable() {
|
||||
this._lastSuccessfulUpdate = ++this._updateCounter;
|
||||
this._isAvailable = false;
|
||||
this._isRejected = false;
|
||||
this._rejectionError = void 0;
|
||||
}
|
||||
setRejected(error) {
|
||||
this._setIfLatest(Result.error(error), ++this._updateCounter);
|
||||
}
|
||||
map(mapper) {
|
||||
const store = new _AsyncStore();
|
||||
this.onChange((value) => {
|
||||
store.set(mapper(value));
|
||||
});
|
||||
return store;
|
||||
}
|
||||
onChange(callback) {
|
||||
return this.onStateChange(({ state, lastOkValue }) => {
|
||||
if (state.status === "ok") {
|
||||
callback(state.data, lastOkValue);
|
||||
}
|
||||
});
|
||||
}
|
||||
onStateChange(callback) {
|
||||
const uuid = generateUuid();
|
||||
this._callbacks.set(uuid, callback);
|
||||
return {
|
||||
unsubscribe: () => {
|
||||
this._callbacks.delete(uuid);
|
||||
}
|
||||
};
|
||||
}
|
||||
onceChange(callback) {
|
||||
const { unsubscribe } = this.onChange((...args) => {
|
||||
unsubscribe();
|
||||
callback(...args);
|
||||
});
|
||||
return { unsubscribe };
|
||||
}
|
||||
onceStateChange(callback) {
|
||||
const { unsubscribe } = this.onStateChange((...args) => {
|
||||
unsubscribe();
|
||||
callback(...args);
|
||||
});
|
||||
return { unsubscribe };
|
||||
}
|
||||
};
|
||||
export {
|
||||
AsyncStore,
|
||||
Store,
|
||||
storeLock
|
||||
};
|
||||
//# sourceMappingURL=stores.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/stores.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/stores.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
295
package/@stackframe/stack-shared/dist/esm/utils/strings.js
vendored
Normal file
295
package/@stackframe/stack-shared/dist/esm/utils/strings.js
vendored
Normal file
|
|
@ -0,0 +1,295 @@
|
|||
// src/utils/strings.tsx
|
||||
import { findLastIndex, unique } from "./arrays";
|
||||
import { StackAssertionError } from "./errors";
|
||||
import { filterUndefined } from "./objects";
|
||||
function typedToLowercase(s) {
|
||||
if (typeof s !== "string") throw new StackAssertionError("Expected a string for typedToLowercase", { s });
|
||||
return s.toLowerCase();
|
||||
}
|
||||
function typedToUppercase(s) {
|
||||
if (typeof s !== "string") throw new StackAssertionError("Expected a string for typedToUppercase", { s });
|
||||
return s.toUpperCase();
|
||||
}
|
||||
function typedCapitalize(s) {
|
||||
return s.charAt(0).toUpperCase() + s.slice(1);
|
||||
}
|
||||
function stringCompare(a, b) {
|
||||
if (typeof a !== "string" || typeof b !== "string") throw new StackAssertionError(`Expected two strings for stringCompare, found ${typeof a} and ${typeof b}`, { a, b });
|
||||
const cmp = (a2, b2) => a2 < b2 ? -1 : a2 > b2 ? 1 : 0;
|
||||
return cmp(a.toUpperCase(), b.toUpperCase()) || cmp(b, a);
|
||||
}
|
||||
function getWhitespacePrefix(s) {
|
||||
return s.substring(0, s.length - s.trimStart().length);
|
||||
}
|
||||
function getWhitespaceSuffix(s) {
|
||||
return s.substring(s.trimEnd().length);
|
||||
}
|
||||
function trimEmptyLinesStart(s) {
|
||||
const lines = s.split("\n");
|
||||
const firstNonEmptyLineIndex = lines.findIndex((line) => line.trim() !== "");
|
||||
if (firstNonEmptyLineIndex === -1) return "";
|
||||
return lines.slice(firstNonEmptyLineIndex).join("\n");
|
||||
}
|
||||
function trimEmptyLinesEnd(s) {
|
||||
const lines = s.split("\n");
|
||||
const lastNonEmptyLineIndex = findLastIndex(lines, (line) => line.trim() !== "");
|
||||
return lines.slice(0, lastNonEmptyLineIndex + 1).join("\n");
|
||||
}
|
||||
function trimLines(s) {
|
||||
return trimEmptyLinesEnd(trimEmptyLinesStart(s));
|
||||
}
|
||||
function templateIdentity(strings, ...values) {
|
||||
if (values.length !== strings.length - 1) throw new StackAssertionError("Invalid number of values; must be one less than strings", { strings, values });
|
||||
return strings.reduce((result, str, i) => result + str + (values[i] ?? ""), "");
|
||||
}
|
||||
function deindent(strings, ...values) {
|
||||
if (typeof strings === "string") return deindent([strings]);
|
||||
return templateIdentity(...deindentTemplate(strings, ...values));
|
||||
}
|
||||
function deindentTemplate(strings, ...values) {
|
||||
if (values.length !== strings.length - 1) throw new StackAssertionError("Invalid number of values; must be one less than strings", { strings, values });
|
||||
const trimmedStrings = [...strings];
|
||||
trimmedStrings[0] = trimEmptyLinesStart(trimmedStrings[0] + "+").slice(0, -1);
|
||||
trimmedStrings[trimmedStrings.length - 1] = trimEmptyLinesEnd("+" + trimmedStrings[trimmedStrings.length - 1]).slice(1);
|
||||
const indentation = trimmedStrings.join("${SOME_VALUE}").split("\n").filter((line) => line.trim() !== "").map((line) => getWhitespacePrefix(line).length).reduce((min, current) => Math.min(min, current), Infinity);
|
||||
const deindentedStrings = trimmedStrings.map((string, stringIndex) => {
|
||||
return string.split("\n").map((line, lineIndex) => stringIndex !== 0 && lineIndex === 0 ? line : line.substring(indentation)).join("\n");
|
||||
});
|
||||
const indentedValues = values.map((value, i) => {
|
||||
const firstLineIndentation = getWhitespacePrefix(deindentedStrings[i].split("\n").at(-1));
|
||||
return `${value}`.replaceAll("\n", `
|
||||
${firstLineIndentation}`);
|
||||
});
|
||||
return [deindentedStrings, ...indentedValues];
|
||||
}
|
||||
function extractScopes(scope, removeDuplicates = true) {
|
||||
const trimmedString = scope.trim();
|
||||
const scopesArray = trimmedString.split(/\s+/);
|
||||
const filtered = scopesArray.filter((scope2) => scope2.length > 0);
|
||||
return removeDuplicates ? [...new Set(filtered)] : filtered;
|
||||
}
|
||||
function mergeScopeStrings(...scopes) {
|
||||
const allScope = scopes.map((s) => extractScopes(s)).flat().join(" ");
|
||||
return extractScopes(allScope).join(" ");
|
||||
}
|
||||
function escapeTemplateLiteral(s) {
|
||||
return s.replaceAll("`", "\\`").replaceAll("\\", "\\\\").replaceAll("$", "\\$");
|
||||
}
|
||||
var nicifiableClassNameOverrides = new Map(Object.entries({
|
||||
Headers
|
||||
}).map(([k, v]) => [v, k]));
|
||||
function nicify(value, options = {}) {
|
||||
const fullOptions = {
|
||||
maxDepth: 5,
|
||||
currentIndent: "",
|
||||
lineIndent: " ",
|
||||
multiline: true,
|
||||
refs: /* @__PURE__ */ new Map(),
|
||||
path: "value",
|
||||
parent: null,
|
||||
overrides: () => null,
|
||||
keyInParent: null,
|
||||
hideFields: [],
|
||||
...filterUndefined(options)
|
||||
};
|
||||
const {
|
||||
maxDepth,
|
||||
currentIndent,
|
||||
lineIndent,
|
||||
multiline,
|
||||
refs,
|
||||
path,
|
||||
overrides,
|
||||
hideFields
|
||||
} = fullOptions;
|
||||
const nl = `
|
||||
${currentIndent}`;
|
||||
const overrideResult = overrides(value, options);
|
||||
if (overrideResult !== null) return overrideResult;
|
||||
if (["function", "object", "symbol"].includes(typeof value) && value !== null) {
|
||||
if (refs.has(value)) {
|
||||
return `Ref<${refs.get(value)}>`;
|
||||
}
|
||||
refs.set(value, path);
|
||||
}
|
||||
const newOptions = {
|
||||
maxDepth: maxDepth - 1,
|
||||
currentIndent,
|
||||
lineIndent,
|
||||
multiline,
|
||||
refs,
|
||||
path: path + "->[unknown property]",
|
||||
overrides,
|
||||
parent: { value, options: fullOptions },
|
||||
keyInParent: null,
|
||||
hideFields: []
|
||||
};
|
||||
const nestedNicify = (newValue, newPath, keyInParent, options2 = {}) => {
|
||||
return nicify(newValue, {
|
||||
...newOptions,
|
||||
path: newPath,
|
||||
currentIndent: currentIndent + lineIndent,
|
||||
keyInParent,
|
||||
...options2
|
||||
});
|
||||
};
|
||||
switch (typeof value) {
|
||||
case "boolean":
|
||||
case "number": {
|
||||
return JSON.stringify(value);
|
||||
}
|
||||
case "string": {
|
||||
const isDeindentable = (v) => deindent(v) === v && v.includes("\n");
|
||||
const wrapInDeindent = (v) => deindent`
|
||||
deindent\`
|
||||
${currentIndent + lineIndent}${escapeTemplateLiteral(v).replaceAll("\n", nl + lineIndent)}
|
||||
${currentIndent}\`
|
||||
`;
|
||||
if (isDeindentable(value)) {
|
||||
return wrapInDeindent(value);
|
||||
} else if (value.endsWith("\n") && isDeindentable(value.slice(0, -1))) {
|
||||
return wrapInDeindent(value.slice(0, -1)) + ' + "\\n"';
|
||||
} else {
|
||||
return JSON.stringify(value);
|
||||
}
|
||||
}
|
||||
case "undefined": {
|
||||
return "undefined";
|
||||
}
|
||||
case "symbol": {
|
||||
return value.toString();
|
||||
}
|
||||
case "bigint": {
|
||||
return `${value}n`;
|
||||
}
|
||||
case "function": {
|
||||
if (value.name) return `function ${value.name}(...) { ... }`;
|
||||
return `(...) => { ... }`;
|
||||
}
|
||||
case "object": {
|
||||
if (value === null) return "null";
|
||||
if (Array.isArray(value)) {
|
||||
const extraLines2 = getNicifiedObjectExtraLines(value);
|
||||
const resValueLength2 = value.length + extraLines2.length;
|
||||
if (maxDepth <= 0 && resValueLength2 === 0) return "[...]";
|
||||
const resValues2 = value.map((v, i) => nestedNicify(v, `${path}[${i}]`, i));
|
||||
resValues2.push(...extraLines2);
|
||||
if (resValues2.length !== resValueLength2) throw new StackAssertionError("nicify of object: resValues.length !== resValueLength", { value, resValues: resValues2, resValueLength: resValueLength2 });
|
||||
const shouldIndent2 = resValues2.length > 4 || resValues2.some((x) => resValues2.length > 1 && x.length > 4 || x.includes("\n"));
|
||||
if (shouldIndent2) {
|
||||
return `[${nl}${resValues2.map((x) => `${lineIndent}${x},${nl}`).join("")}]`;
|
||||
} else {
|
||||
return `[${resValues2.join(", ")}]`;
|
||||
}
|
||||
}
|
||||
if (value instanceof URL) {
|
||||
return `URL(${nestedNicify(value.toString(), `${path}.toString()`, null)})`;
|
||||
}
|
||||
if (ArrayBuffer.isView(value)) {
|
||||
return `${value.constructor.name}([${value.toString()}])`;
|
||||
}
|
||||
if (value instanceof Error) {
|
||||
let stack = value.stack ?? "";
|
||||
const toString = value.toString();
|
||||
if (!stack.startsWith(toString)) stack = `${toString}
|
||||
${stack}`;
|
||||
stack = stack.trimEnd();
|
||||
stack = stack.replace(/\n\s+/g, `
|
||||
${lineIndent}${lineIndent}`);
|
||||
stack = stack.replace("\n", `
|
||||
${lineIndent}Stack:
|
||||
`);
|
||||
if (Object.keys(value).length > 0) {
|
||||
stack += `
|
||||
${lineIndent}Extra properties: ${nestedNicify(Object.fromEntries(Object.entries(value)), path, null)}`;
|
||||
}
|
||||
if (value.cause) {
|
||||
stack += `
|
||||
${lineIndent}Cause:
|
||||
${lineIndent}${lineIndent}${nestedNicify(value.cause, path, null, { currentIndent: currentIndent + lineIndent + lineIndent })}`;
|
||||
}
|
||||
stack = stack.replaceAll("\n", `
|
||||
${currentIndent}`);
|
||||
return stack;
|
||||
}
|
||||
const constructorName = [null, Object.prototype].includes(Object.getPrototypeOf(value)) ? null : nicifiableClassNameOverrides.get(value.constructor) ?? value.constructor.name;
|
||||
const constructorString = constructorName ? `${constructorName} ` : "";
|
||||
const entries = getNicifiableEntries(value).filter(([k]) => !hideFields.includes(k));
|
||||
const extraLines = [
|
||||
...getNicifiedObjectExtraLines(value),
|
||||
...hideFields.length > 0 ? [`<some fields may have been hidden>`] : []
|
||||
];
|
||||
const resValueLength = entries.length + extraLines.length;
|
||||
if (resValueLength === 0) return `${constructorString}{}`;
|
||||
if (maxDepth <= 0) return `${constructorString}{ ... }`;
|
||||
const resValues = entries.map(([k, v], keyIndex) => {
|
||||
const keyNicified = nestedNicify(k, `Object.keys(${path})[${keyIndex}]`, null);
|
||||
const keyInObjectLiteral = typeof k === "string" ? nicifyPropertyString(k) : `[${keyNicified}]`;
|
||||
if (typeof v === "function" && v.name === k) {
|
||||
return `${keyInObjectLiteral}(...): { ... }`;
|
||||
} else {
|
||||
return `${keyInObjectLiteral}: ${nestedNicify(v, `${path}[${keyNicified}]`, k)}`;
|
||||
}
|
||||
});
|
||||
resValues.push(...extraLines);
|
||||
if (resValues.length !== resValueLength) throw new StackAssertionError("nicify of object: resValues.length !== resValueLength", { value, resValues, resValueLength });
|
||||
const shouldIndent = resValues.length > 1 || resValues.some((x) => x.includes("\n"));
|
||||
if (resValues.length === 0) return `${constructorString}{}`;
|
||||
if (shouldIndent) {
|
||||
return `${constructorString}{${nl}${resValues.map((x) => `${lineIndent}${x},${nl}`).join("")}}`;
|
||||
} else {
|
||||
return `${constructorString}{ ${resValues.join(", ")} }`;
|
||||
}
|
||||
}
|
||||
default: {
|
||||
return `${typeof value}<${value}>`;
|
||||
}
|
||||
}
|
||||
}
|
||||
function replaceAll(input, searchValue, replaceValue) {
|
||||
if (searchValue === "") throw new StackAssertionError("replaceAll: searchValue is empty");
|
||||
return input.split(searchValue).join(replaceValue);
|
||||
}
|
||||
function nicifyPropertyString(str) {
|
||||
return JSON.stringify(str);
|
||||
}
|
||||
function getNicifiableKeys(value) {
|
||||
const overridden = ("getNicifiableKeys" in value ? value.getNicifiableKeys?.bind(value) : null)?.();
|
||||
if (overridden != null) return overridden;
|
||||
const keys = Object.keys(value).sort();
|
||||
return unique(keys);
|
||||
}
|
||||
function getNicifiableEntries(value) {
|
||||
const recordLikes = [Headers];
|
||||
function isRecordLike(value2) {
|
||||
return recordLikes.some((x) => value2 instanceof x);
|
||||
}
|
||||
if (isRecordLike(value)) {
|
||||
return [...value.entries()].sort(([a], [b]) => stringCompare(`${a}`, `${b}`));
|
||||
}
|
||||
const keys = getNicifiableKeys(value);
|
||||
return keys.map((k) => [k, value[k]]);
|
||||
}
|
||||
function getNicifiedObjectExtraLines(value) {
|
||||
return ("getNicifiedObjectExtraLines" in value ? value.getNicifiedObjectExtraLines : null)?.() ?? [];
|
||||
}
|
||||
export {
|
||||
deindent,
|
||||
deindentTemplate,
|
||||
escapeTemplateLiteral,
|
||||
extractScopes,
|
||||
getWhitespacePrefix,
|
||||
getWhitespaceSuffix,
|
||||
mergeScopeStrings,
|
||||
nicify,
|
||||
replaceAll,
|
||||
stringCompare,
|
||||
templateIdentity,
|
||||
trimEmptyLinesEnd,
|
||||
trimEmptyLinesStart,
|
||||
trimLines,
|
||||
typedCapitalize,
|
||||
typedToLowercase,
|
||||
typedToUppercase
|
||||
};
|
||||
//# sourceMappingURL=strings.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/strings.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/strings.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
222
package/@stackframe/stack-shared/dist/esm/utils/strings.nicify.test.js
vendored
Normal file
222
package/@stackframe/stack-shared/dist/esm/utils/strings.nicify.test.js
vendored
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
// src/utils/strings.nicify.test.ts
|
||||
import { describe, expect, test } from "vitest";
|
||||
import { deindent, nicify } from "./strings";
|
||||
describe("nicify", () => {
|
||||
describe("primitive values", () => {
|
||||
test("numbers", () => {
|
||||
expect(nicify(123)).toBe("123");
|
||||
expect(nicify(123n)).toBe("123n");
|
||||
});
|
||||
test("strings", () => {
|
||||
expect(nicify("hello")).toBe('"hello"');
|
||||
});
|
||||
test("booleans", () => {
|
||||
expect(nicify(true)).toBe("true");
|
||||
expect(nicify(false)).toBe("false");
|
||||
});
|
||||
test("null and undefined", () => {
|
||||
expect(nicify(null)).toBe("null");
|
||||
expect(nicify(void 0)).toBe("undefined");
|
||||
});
|
||||
test("symbols", () => {
|
||||
expect(nicify(Symbol("test"))).toBe("Symbol(test)");
|
||||
});
|
||||
});
|
||||
describe("arrays", () => {
|
||||
test("empty array", () => {
|
||||
expect(nicify([])).toBe("[]");
|
||||
});
|
||||
test("single-element array", () => {
|
||||
expect(nicify([1])).toBe("[1]");
|
||||
});
|
||||
test("single-element array with long content", () => {
|
||||
expect(nicify(["123123123123123"])).toBe('["123123123123123"]');
|
||||
});
|
||||
test("flat array", () => {
|
||||
expect(nicify([1, 2, 3])).toBe("[1, 2, 3]");
|
||||
});
|
||||
test("longer array", () => {
|
||||
expect(nicify([1e4, 2, 3])).toBe(deindent`
|
||||
[
|
||||
10000,
|
||||
2,
|
||||
3,
|
||||
]
|
||||
`);
|
||||
});
|
||||
test("nested array", () => {
|
||||
expect(nicify([1, [2, 3]])).toBe(deindent`
|
||||
[
|
||||
1,
|
||||
[2, 3],
|
||||
]
|
||||
`);
|
||||
});
|
||||
});
|
||||
describe("objects", () => {
|
||||
test("empty object", () => {
|
||||
expect(nicify({})).toBe("{}");
|
||||
});
|
||||
test("simple object", () => {
|
||||
expect(nicify({ a: 1 })).toBe('{ "a": 1 }');
|
||||
});
|
||||
test("multiline object", () => {
|
||||
expect(nicify({ a: 1, b: 2 })).toBe(deindent`
|
||||
{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
}
|
||||
`);
|
||||
});
|
||||
});
|
||||
describe("custom classes", () => {
|
||||
test("class instance", () => {
|
||||
class TestClass {
|
||||
constructor(value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
expect(nicify(new TestClass(42))).toBe('TestClass { "value": 42 }');
|
||||
});
|
||||
});
|
||||
describe("built-in objects", () => {
|
||||
test("URL", () => {
|
||||
expect(nicify(new URL("https://example.com"))).toBe('URL("https://example.com/")');
|
||||
});
|
||||
test("TypedArrays", () => {
|
||||
expect(nicify(new Uint8Array([1, 2, 3]))).toBe("Uint8Array([1,2,3])");
|
||||
expect(nicify(new Int32Array([1, 2, 3]))).toBe("Int32Array([1,2,3])");
|
||||
});
|
||||
test("Error objects", () => {
|
||||
const error = new Error("test error");
|
||||
const nicifiedError = nicify({ error });
|
||||
expect(nicifiedError).toMatch(new RegExp(deindent`
|
||||
^\{
|
||||
"error": Error: test error
|
||||
Stack:
|
||||
at (.|\\n)*
|
||||
\}$
|
||||
`));
|
||||
});
|
||||
test("Error objects with cause and an extra property", () => {
|
||||
const error = new Error("test error", { cause: new Error("cause") });
|
||||
error.extra = "something";
|
||||
const nicifiedError = nicify(error, { lineIndent: "--" });
|
||||
expect(nicifiedError).toMatch(new RegExp(deindent`
|
||||
^Error: test error
|
||||
--Stack:
|
||||
----at (.|\\n)+
|
||||
--Extra properties: \{ "extra": "something" \}
|
||||
--Cause:
|
||||
----Error: cause
|
||||
------Stack:
|
||||
--------at (.|\\n)+$
|
||||
`));
|
||||
});
|
||||
test("Headers", () => {
|
||||
const headers = new Headers();
|
||||
headers.append("Content-Type", "application/json");
|
||||
headers.append("Accept", "text/plain");
|
||||
expect(nicify(headers)).toBe(
|
||||
deindent`
|
||||
Headers {
|
||||
"accept": "text/plain",
|
||||
"content-type": "application/json",
|
||||
}`
|
||||
);
|
||||
});
|
||||
});
|
||||
describe("multiline strings", () => {
|
||||
test("basic multiline", () => {
|
||||
expect(nicify("line1\nline2")).toBe("deindent`\n line1\n line2\n`");
|
||||
});
|
||||
test("multiline with trailing newline", () => {
|
||||
expect(nicify("line1\nline2\n")).toBe('deindent`\n line1\n line2\n` + "\\n"');
|
||||
});
|
||||
});
|
||||
describe("circular references", () => {
|
||||
test("object with self reference", () => {
|
||||
const circular = { a: 1 };
|
||||
circular.self = circular;
|
||||
expect(nicify(circular)).toBe(
|
||||
deindent`
|
||||
{
|
||||
"a": 1,
|
||||
"self": Ref<value>,
|
||||
}`
|
||||
);
|
||||
});
|
||||
});
|
||||
describe("configuration options", () => {
|
||||
test("maxDepth", () => {
|
||||
const deep = { a: { b: { c: { d: { e: 1 } } } } };
|
||||
expect(nicify(deep, { maxDepth: 2 })).toBe('{ "a": { "b": { ... } } }');
|
||||
});
|
||||
test("lineIndent", () => {
|
||||
expect(nicify({ a: 1, b: 2 }, { lineIndent: " " })).toBe(deindent`
|
||||
{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
}
|
||||
`);
|
||||
});
|
||||
test("hideFields", () => {
|
||||
expect(nicify({ a: 1, b: 2, secret: "hidden" }, { hideFields: ["secret"] })).toBe(deindent`
|
||||
{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
<some fields may have been hidden>,
|
||||
}
|
||||
`);
|
||||
});
|
||||
});
|
||||
describe("custom overrides", () => {
|
||||
test("override with custom type", () => {
|
||||
expect(nicify({ type: "special" }, {
|
||||
overrides: (value) => {
|
||||
if (typeof value === "object" && value && "type" in value && value.type === "special") {
|
||||
return "SPECIAL";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
})).toBe("SPECIAL");
|
||||
});
|
||||
});
|
||||
describe("functions", () => {
|
||||
test("named function", () => {
|
||||
expect(nicify(function namedFunction() {
|
||||
})).toBe("function namedFunction(...) { ... }");
|
||||
});
|
||||
test("arrow function", () => {
|
||||
expect(nicify(() => {
|
||||
})).toBe("(...) => { ... }");
|
||||
});
|
||||
});
|
||||
describe("Nicifiable interface", () => {
|
||||
test("object implementing Nicifiable", () => {
|
||||
const nicifiable = {
|
||||
value: 42,
|
||||
getNicifiableKeys() {
|
||||
return ["value"];
|
||||
},
|
||||
getNicifiedObjectExtraLines() {
|
||||
return ["// custom comment"];
|
||||
}
|
||||
};
|
||||
expect(nicify(nicifiable)).toBe(deindent`
|
||||
{
|
||||
"value": 42,
|
||||
// custom comment,
|
||||
}
|
||||
`);
|
||||
});
|
||||
});
|
||||
describe("unknown types", () => {
|
||||
test("object without prototype", () => {
|
||||
const unknownType = /* @__PURE__ */ Object.create(null);
|
||||
unknownType.value = "test";
|
||||
expect(nicify(unknownType)).toBe('{ "value": "test" }');
|
||||
});
|
||||
});
|
||||
});
|
||||
//# sourceMappingURL=strings.nicify.test.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/strings.nicify.test.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/strings.nicify.test.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
1
package/@stackframe/stack-shared/dist/esm/utils/types.js
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/types.js
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
//# sourceMappingURL=types.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/types.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/types.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
||||
11
package/@stackframe/stack-shared/dist/esm/utils/unicode.js
vendored
Normal file
11
package/@stackframe/stack-shared/dist/esm/utils/unicode.js
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
// src/utils/unicode.tsx
|
||||
import { StackAssertionError } from "./errors";
|
||||
function getFlagEmoji(twoLetterCountryCode) {
|
||||
if (!/^[a-zA-Z][a-zA-Z]$/.test(twoLetterCountryCode)) throw new StackAssertionError("Country code must be two alphabetical letters");
|
||||
const codePoints = twoLetterCountryCode.toUpperCase().split("").map((char) => 127397 + char.charCodeAt(0));
|
||||
return String.fromCodePoint(...codePoints);
|
||||
}
|
||||
export {
|
||||
getFlagEmoji
|
||||
};
|
||||
//# sourceMappingURL=unicode.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/unicode.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/unicode.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../../../src/utils/unicode.tsx"],"sourcesContent":["import { StackAssertionError } from \"./errors\";\n\nexport function getFlagEmoji(twoLetterCountryCode: string) {\n if (!/^[a-zA-Z][a-zA-Z]$/.test(twoLetterCountryCode)) throw new StackAssertionError(\"Country code must be two alphabetical letters\");\n const codePoints = twoLetterCountryCode\n .toUpperCase()\n .split('')\n .map(char => 127397 + char.charCodeAt(0));\n return String.fromCodePoint(...codePoints);\n}\nundefined?.test(\"getFlagEmoji\", ({ expect }) => {\n // Test with valid country codes\n expect(getFlagEmoji(\"US\")).toBe(\"🇺🇸\");\n expect(getFlagEmoji(\"us\")).toBe(\"🇺🇸\");\n expect(getFlagEmoji(\"GB\")).toBe(\"🇬🇧\");\n expect(getFlagEmoji(\"JP\")).toBe(\"🇯🇵\");\n\n // Test with invalid country codes\n expect(() => getFlagEmoji(\"\")).toThrow(\"Country code must be two alphabetical letters\");\n expect(() => getFlagEmoji(\"A\")).toThrow(\"Country code must be two alphabetical letters\");\n expect(() => getFlagEmoji(\"ABC\")).toThrow(\"Country code must be two alphabetical letters\");\n expect(() => getFlagEmoji(\"12\")).toThrow(\"Country code must be two alphabetical letters\");\n expect(() => getFlagEmoji(\"A1\")).toThrow(\"Country code must be two alphabetical letters\");\n});\n"],"mappings":";AAAA,SAAS,2BAA2B;AAE7B,SAAS,aAAa,sBAA8B;AACzD,MAAI,CAAC,qBAAqB,KAAK,oBAAoB,EAAG,OAAM,IAAI,oBAAoB,+CAA+C;AACnI,QAAM,aAAa,qBAChB,YAAY,EACZ,MAAM,EAAE,EACR,IAAI,UAAQ,SAAS,KAAK,WAAW,CAAC,CAAC;AAC1C,SAAO,OAAO,cAAc,GAAG,UAAU;AAC3C;","names":[]}
|
||||
53
package/@stackframe/stack-shared/dist/esm/utils/urls.js
vendored
Normal file
53
package/@stackframe/stack-shared/dist/esm/utils/urls.js
vendored
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
// src/utils/urls.tsx
|
||||
import { generateSecureRandomString } from "./crypto";
|
||||
import { templateIdentity } from "./strings";
|
||||
function createUrlIfValid(...args) {
|
||||
try {
|
||||
return new URL(...args);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
function isValidUrl(url2) {
|
||||
return !!createUrlIfValid(url2);
|
||||
}
|
||||
function isValidHostname(hostname) {
|
||||
const url2 = createUrlIfValid(`https://${hostname}`);
|
||||
if (!url2) return false;
|
||||
return url2.hostname === hostname;
|
||||
}
|
||||
function isLocalhost(urlOrString) {
|
||||
const url2 = createUrlIfValid(urlOrString);
|
||||
if (!url2) return false;
|
||||
if (url2.hostname === "localhost" || url2.hostname.endsWith(".localhost")) return true;
|
||||
if (url2.hostname.match(/^127\.\d+\.\d+\.\d+$/)) return true;
|
||||
return false;
|
||||
}
|
||||
function isRelative(url2) {
|
||||
const randomDomain = `${generateSecureRandomString()}.stack-auth.example.com`;
|
||||
const u = createUrlIfValid(url2, `https://${randomDomain}`);
|
||||
if (!u) return false;
|
||||
if (u.host !== randomDomain) return false;
|
||||
if (u.protocol !== "https:") return false;
|
||||
return true;
|
||||
}
|
||||
function getRelativePart(url2) {
|
||||
return url2.pathname + url2.search + url2.hash;
|
||||
}
|
||||
function url(strings, ...values) {
|
||||
return new URL(urlString(strings, ...values));
|
||||
}
|
||||
function urlString(strings, ...values) {
|
||||
return templateIdentity(strings, ...values.map(encodeURIComponent));
|
||||
}
|
||||
export {
|
||||
createUrlIfValid,
|
||||
getRelativePart,
|
||||
isLocalhost,
|
||||
isRelative,
|
||||
isValidHostname,
|
||||
isValidUrl,
|
||||
url,
|
||||
urlString
|
||||
};
|
||||
//# sourceMappingURL=urls.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/urls.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/urls.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
16
package/@stackframe/stack-shared/dist/esm/utils/uuids.js
vendored
Normal file
16
package/@stackframe/stack-shared/dist/esm/utils/uuids.js
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
// src/utils/uuids.tsx
|
||||
import { generateRandomValues } from "./crypto";
|
||||
function generateUuid() {
|
||||
return "10000000-1000-4000-8000-100000000000".replace(
|
||||
/[018]/g,
|
||||
(c) => (+c ^ generateRandomValues(new Uint8Array(1))[0] & 15 >> +c / 4).toString(16)
|
||||
);
|
||||
}
|
||||
function isUuid(str) {
|
||||
return /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(str);
|
||||
}
|
||||
export {
|
||||
generateUuid,
|
||||
isUuid
|
||||
};
|
||||
//# sourceMappingURL=uuids.js.map
|
||||
1
package/@stackframe/stack-shared/dist/esm/utils/uuids.js.map
vendored
Normal file
1
package/@stackframe/stack-shared/dist/esm/utils/uuids.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["../../../src/utils/uuids.tsx"],"sourcesContent":["import { generateRandomValues } from \"./crypto\";\n\nexport function generateUuid() {\n // crypto.randomUuid is not supported in all browsers, so this is a polyfill\n return \"10000000-1000-4000-8000-100000000000\".replace(/[018]/g, c =>\n (+c ^ generateRandomValues(new Uint8Array(1))[0] & 15 >> +c / 4).toString(16)\n );\n}\nundefined?.test(\"generateUuid\", ({ expect }) => {\n // Test that the function returns a valid UUID\n const uuid = generateUuid();\n expect(uuid).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/);\n\n // Test that multiple calls generate different UUIDs\n const uuid2 = generateUuid();\n expect(uuid).not.toBe(uuid2);\n\n // Test that the UUID is version 4 (random)\n expect(uuid.charAt(14)).toBe('4');\n\n // Test that the UUID has the correct variant (8, 9, a, or b in position 19)\n expect('89ab').toContain(uuid.charAt(19));\n});\n\nexport function isUuid(str: string) {\n return /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(str);\n}\nundefined?.test(\"isUuid\", ({ expect }) => {\n // Test with valid UUIDs\n expect(isUuid(\"123e4567-e89b-42d3-a456-426614174000\")).toBe(true);\n expect(isUuid(\"123e4567-e89b-42d3-8456-426614174000\")).toBe(true);\n expect(isUuid(\"123e4567-e89b-42d3-9456-426614174000\")).toBe(true);\n expect(isUuid(\"123e4567-e89b-42d3-a456-426614174000\")).toBe(true);\n expect(isUuid(\"123e4567-e89b-42d3-b456-426614174000\")).toBe(true);\n\n // Test with invalid UUIDs\n expect(isUuid(\"\")).toBe(false);\n expect(isUuid(\"not-a-uuid\")).toBe(false);\n expect(isUuid(\"123e4567-e89b-12d3-a456-426614174000\")).toBe(false); // Wrong version (not 4)\n expect(isUuid(\"123e4567-e89b-42d3-c456-426614174000\")).toBe(false); // Wrong variant (not 8, 9, a, or b)\n expect(isUuid(\"123e4567-e89b-42d3-a456-42661417400\")).toBe(false); // Too short\n expect(isUuid(\"123e4567-e89b-42d3-a456-4266141740000\")).toBe(false); // Too long\n expect(isUuid(\"123e4567-e89b-42d3-a456_426614174000\")).toBe(false); // Wrong format (underscore instead of dash)\n\n // Test with uppercase letters (should fail as UUID should be lowercase)\n expect(isUuid(\"123E4567-E89B-42D3-A456-426614174000\")).toBe(false);\n});\n"],"mappings":";AAAA,SAAS,4BAA4B;AAE9B,SAAS,eAAe;AAE7B,SAAO,uCAAuC;AAAA,IAAQ;AAAA,IAAU,QAC7D,CAAC,IAAI,qBAAqB,IAAI,WAAW,CAAC,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,IAAI,GAAG,SAAS,EAAE;AAAA,EAC9E;AACF;AAiBO,SAAS,OAAO,KAAa;AAClC,SAAO,wEAAwE,KAAK,GAAG;AACzF;","names":[]}
|
||||
Loading…
Add table
Add a link
Reference in a new issue