Initial commit of eigent-main

This commit is contained in:
puzhen 2025-08-12 01:16:39 +02:00
commit 723df5a03e
1144 changed files with 103478 additions and 0 deletions

View file

@ -0,0 +1,135 @@
// src/config/format.ts
import { StackAssertionError, throwErr } from "../utils/errors";
import { deleteKey, filterUndefined, get, hasAndNotUndefined, set } from "../utils/objects";
function isValidConfig(c) {
return getInvalidConfigReason(c) === void 0;
}
function getInvalidConfigReason(c, options = {}) {
const configName = options.configName ?? "config";
if (c === null || typeof c !== "object") return `${configName} must be a non-null object`;
for (const [key, value] of Object.entries(c)) {
if (value === void 0) continue;
if (typeof key !== "string") return `${configName} must have only string keys (found: ${typeof key})`;
if (!key.match(/^[a-zA-Z0-9_:$][a-zA-Z_:$0-9\-]*(?:\.[a-zA-Z0-9_:$][a-zA-Z_:$0-9\-]*)*$/)) return `All keys of ${configName} must consist of only alphanumeric characters, dots, underscores, colons, dollar signs, or hyphens and start with a character other than a hyphen (found: ${key})`;
const entryName = `${configName}.${key}`;
const reason = getInvalidConfigValueReason(value, { valueName: entryName });
if (reason) return reason;
}
return void 0;
}
function getInvalidConfigValueReason(value, options = {}) {
const valueName = options.valueName ?? "value";
switch (typeof value) {
case "string":
case "number":
case "boolean": {
break;
}
case "object": {
if (value === null) {
break;
} else if (Array.isArray(value)) {
for (const [index, v] of value.entries()) {
const reason = getInvalidConfigValueReason(v, { valueName: `${valueName}[${index}]` });
if (reason) return reason;
}
} else {
const reason = getInvalidConfigReason(value, { configName: valueName });
if (reason) return reason;
}
break;
}
default: {
return `${valueName} has an invalid value type ${typeof value} (value: ${value})`;
}
}
return void 0;
}
function assertValidConfig(c) {
const reason = getInvalidConfigReason(c);
if (reason) throw new StackAssertionError(`Invalid config: ${reason}`, { c });
}
function override(c1, ...configs) {
if (configs.length === 0) return c1;
if (configs.length > 1) return override(override(c1, configs[0]), ...configs.slice(1));
const c2 = configs[0];
assertValidConfig(c1);
assertValidConfig(c2);
let result = c1;
for (const key of Object.keys(filterUndefined(c2))) {
result = Object.fromEntries(
Object.entries(result).filter(([k]) => k !== key && !k.startsWith(key + "."))
);
}
return {
...result,
...filterUndefined(c2)
};
}
var NormalizationError = class extends Error {
constructor(...args) {
super(...args);
}
};
NormalizationError.prototype.name = "NormalizationError";
function normalize(c, options = {}) {
assertValidConfig(c);
const onDotIntoNull = options.onDotIntoNull ?? "empty";
const countDots = (s) => s.match(/\./g)?.length ?? 0;
const result = {};
const keysByDepth = Object.keys(c).sort((a, b) => countDots(a) - countDots(b));
outer: for (const key of keysByDepth) {
const keySegmentsWithoutLast = key.split(".");
const last = keySegmentsWithoutLast.pop() ?? throwErr("split returns empty array?");
const value = get(c, key);
if (value === void 0) continue;
let current = result;
for (const keySegment of keySegmentsWithoutLast) {
if (!hasAndNotUndefined(current, keySegment)) {
switch (onDotIntoNull) {
case "empty": {
set(current, keySegment, {});
break;
}
case "throw": {
throw new NormalizationError(`Tried to use dot notation to access ${JSON.stringify(key)}, but ${JSON.stringify(keySegment)} doesn't exist on the object (or is null). Maybe this config is not normalizable?`);
}
case "ignore": {
continue outer;
}
}
}
const value2 = get(current, keySegment);
if (typeof value2 !== "object") {
throw new NormalizationError(`Tried to use dot notation to access ${JSON.stringify(key)}, but ${JSON.stringify(keySegment)} is not an object. Maybe this config is not normalizable?`);
}
current = value2;
}
setNormalizedValue(current, last, value);
}
return result;
}
function normalizeValue(value) {
if (value === null) throw new NormalizationError("Tried to normalize a null value");
if (Array.isArray(value)) return value.map(normalizeValue);
if (typeof value === "object") return normalize(value);
return value;
}
function setNormalizedValue(result, key, value) {
if (value === null) {
if (hasAndNotUndefined(result, key)) {
deleteKey(result, key);
}
} else {
set(result, key, normalizeValue(value));
}
}
export {
NormalizationError,
assertValidConfig,
getInvalidConfigReason,
isValidConfig,
normalize,
override
};
//# sourceMappingURL=format.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,201 @@
// src/config/schema.ts
import * as schemaFields from "../schema-fields";
import { yupBoolean, yupObject, yupRecord, yupString } from "../schema-fields";
import { allProviders } from "../utils/oauth";
import { get, has, isObjectLike, mapValues, set } from "../utils/objects";
var configLevels = ["project", "branch", "environment", "organization"];
var permissionRegex = /^\$?[a-z0-9_:]+$/;
var customPermissionRegex = /^[a-z0-9_:]+$/;
var projectConfigSchema = yupObject({});
var branchRbacDefaultPermissions = yupRecord(
yupString().optional().matches(permissionRegex),
yupBoolean().isTrue().optional()
).optional();
var branchRbacSchema = yupObject({
permissions: yupRecord(
yupString().optional().matches(customPermissionRegex),
yupObject({
description: yupString().optional(),
scope: yupString().oneOf(["team", "project"]).optional(),
containedPermissionIds: yupRecord(
yupString().optional().matches(permissionRegex),
yupBoolean().isTrue().optional()
).optional()
}).optional()
).optional(),
defaultPermissions: yupObject({
teamCreator: branchRbacDefaultPermissions,
teamMember: branchRbacDefaultPermissions,
signUp: branchRbacDefaultPermissions
}).optional()
}).optional();
var branchApiKeysSchema = yupObject({
enabled: yupObject({
team: yupBoolean().optional(),
user: yupBoolean().optional()
}).optional()
}).optional();
var branchAuthSchema = yupObject({
allowSignUp: yupBoolean().optional(),
password: yupObject({
allowSignIn: yupBoolean().optional()
}).optional(),
otp: yupObject({
allowSignIn: yupBoolean().optional()
}).optional(),
passkey: yupObject({
allowSignIn: yupBoolean().optional()
}).optional(),
oauth: yupObject({
accountMergeStrategy: yupString().oneOf(["link_method", "raise_error", "allow_duplicates"]).optional(),
providers: yupRecord(
yupString().optional().matches(permissionRegex),
yupObject({
type: yupString().oneOf(allProviders).optional(),
allowSignIn: yupBoolean().optional(),
allowConnectedAccounts: yupBoolean().optional()
}).defined()
).optional()
}).optional()
}).optional();
var branchDomain = yupObject({
allowLocalhost: yupBoolean().optional()
}).optional();
var branchConfigSchema = projectConfigSchema.concat(yupObject({
rbac: branchRbacSchema,
teams: yupObject({
createPersonalTeamOnSignUp: yupBoolean().optional(),
allowClientTeamCreation: yupBoolean().optional()
}).optional(),
users: yupObject({
allowClientUserDeletion: yupBoolean().optional()
}).optional(),
apiKeys: branchApiKeysSchema,
domains: branchDomain,
auth: branchAuthSchema,
emails: yupObject({})
}));
var environmentConfigSchema = branchConfigSchema.concat(yupObject({
auth: branchConfigSchema.getNested("auth").concat(yupObject({
oauth: branchConfigSchema.getNested("auth").getNested("oauth").concat(yupObject({
providers: yupRecord(
yupString().optional().matches(permissionRegex),
yupObject({
type: yupString().oneOf(allProviders).optional(),
isShared: yupBoolean().optional(),
clientId: schemaFields.oauthClientIdSchema.optional(),
clientSecret: schemaFields.oauthClientSecretSchema.optional(),
facebookConfigId: schemaFields.oauthFacebookConfigIdSchema.optional(),
microsoftTenantId: schemaFields.oauthMicrosoftTenantIdSchema.optional(),
allowSignIn: yupBoolean().optional(),
allowConnectedAccounts: yupBoolean().optional()
})
).optional()
}).optional())
})),
emails: branchConfigSchema.getNested("emails").concat(yupObject({
server: yupObject({
isShared: yupBoolean().optional(),
host: schemaFields.emailHostSchema.optional().nonEmpty(),
port: schemaFields.emailPortSchema.optional(),
username: schemaFields.emailUsernameSchema.optional().nonEmpty(),
password: schemaFields.emailPasswordSchema.optional().nonEmpty(),
senderName: schemaFields.emailSenderNameSchema.optional().nonEmpty(),
senderEmail: schemaFields.emailSenderEmailSchema.optional().nonEmpty()
})
}).optional()),
domains: branchConfigSchema.getNested("domains").concat(yupObject({
trustedDomains: yupRecord(
yupString().uuid().optional(),
yupObject({
baseUrl: schemaFields.urlSchema.optional(),
handlerPath: schemaFields.handlerPathSchema.optional()
})
).optional()
}))
}));
var organizationConfigSchema = environmentConfigSchema.concat(yupObject({}));
var projectConfigDefaults = {};
var branchConfigDefaults = {};
var environmentConfigDefaults = {};
var organizationConfigDefaults = {
rbac: {
permissions: (key) => ({}),
defaultPermissions: {
teamCreator: {},
teamMember: {},
signUp: {}
}
},
apiKeys: {
enabled: {
team: false,
user: false
}
},
teams: {
createPersonalTeamOnSignUp: false,
allowClientTeamCreation: false
},
users: {
allowClientUserDeletion: false
},
domains: {
allowLocalhost: false,
trustedDomains: (key) => ({
handlerPath: "/handler"
})
},
auth: {
allowSignUp: true,
password: {
allowSignIn: false
},
otp: {
allowSignIn: false
},
passkey: {
allowSignIn: false
},
oauth: {
accountMergeStrategy: "link_method",
providers: (key) => ({
isShared: true,
allowSignIn: false,
allowConnectedAccounts: false
})
}
},
emails: {
server: {
isShared: true
}
}
};
function applyDefaults(defaults, config) {
const res = typeof defaults === "function" ? {} : mapValues(defaults, (v) => typeof v === "function" ? {} : typeof v === "object" ? applyDefaults(v, {}) : v);
for (const [key, mergeValue] of Object.entries(config)) {
const baseValue = typeof defaults === "function" ? defaults(key) : has(defaults, key) ? get(defaults, key) : void 0;
if (baseValue !== void 0) {
if (isObjectLike(baseValue) && isObjectLike(mergeValue)) {
set(res, key, applyDefaults(baseValue, mergeValue));
continue;
}
}
set(res, key, mergeValue);
}
return res;
}
export {
applyDefaults,
branchConfigDefaults,
branchConfigSchema,
configLevels,
environmentConfigDefaults,
environmentConfigSchema,
organizationConfigDefaults,
organizationConfigSchema,
projectConfigDefaults,
projectConfigSchema
};
//# sourceMappingURL=schema.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,60 @@
// src/crud.tsx
import { yupObject, yupString } from "./schema-fields";
import { filterUndefined } from "./utils/objects";
function createCrud(options) {
const docs = options.docs ?? {};
const client = {
createSchema: options.clientCreateSchema,
createDocs: docs.clientCreate,
readSchema: options.clientReadSchema,
readDocs: docs.clientRead,
listDocs: docs.clientList,
updateSchema: options.clientUpdateSchema,
updateDocs: docs.clientUpdate,
deleteSchema: options.clientDeleteSchema,
deleteDocs: docs.clientDelete
};
const serverOverrides = filterUndefined({
createSchema: options.serverCreateSchema,
createDocs: docs.serverCreate,
readSchema: options.serverReadSchema,
readDocs: docs.serverRead,
listDocs: docs.serverList,
updateSchema: options.serverUpdateSchema,
updateDocs: docs.serverUpdate,
deleteSchema: options.serverDeleteSchema,
deleteDocs: docs.serverDelete
});
const server = {
...client,
...serverOverrides
};
const adminOverrides = filterUndefined({
createSchema: options.adminCreateSchema,
createDocs: docs.adminCreate,
readSchema: options.adminReadSchema,
readDocs: docs.adminRead,
listDocs: docs.adminList,
updateSchema: options.adminUpdateSchema,
updateDocs: docs.adminUpdate,
deleteSchema: options.adminDeleteSchema,
deleteDocs: docs.adminDelete
});
const admin = {
...server,
...adminOverrides
};
return {
client,
server,
admin,
hasCreate: !!admin.createSchema,
hasRead: !!admin.readSchema,
hasUpdate: !!admin.updateSchema,
hasDelete: !!admin.deleteSchema
};
}
export {
createCrud
};
//# sourceMappingURL=crud.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
//# sourceMappingURL=global.d.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}

View file

@ -0,0 +1,17 @@
// src/helpers/password.ts
import { KnownErrors } from "..";
var minLength = 8;
var maxLength = 70;
function getPasswordError(password) {
if (password.length < minLength) {
return new KnownErrors.PasswordTooShort(minLength);
}
if (password.length > maxLength) {
return new KnownErrors.PasswordTooLong(maxLength);
}
return void 0;
}
export {
getPasswordError
};
//# sourceMappingURL=password.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../../../src/helpers/password.ts"],"sourcesContent":["import { KnownErrors } from \"..\";\n\nconst minLength = 8;\nconst maxLength = 70;\n\nexport function getPasswordError(password: string): KnownErrors[\"PasswordRequirementsNotMet\"] | undefined {\n if (password.length < minLength) {\n return new KnownErrors.PasswordTooShort(minLength);\n }\n\n if (password.length > maxLength) {\n return new KnownErrors.PasswordTooLong(maxLength);\n }\n\n return undefined;\n}\n"],"mappings":";AAAA,SAAS,mBAAmB;AAE5B,IAAM,YAAY;AAClB,IAAM,YAAY;AAEX,SAAS,iBAAiB,UAAyE;AACxG,MAAI,SAAS,SAAS,WAAW;AAC/B,WAAO,IAAI,YAAY,iBAAiB,SAAS;AAAA,EACnD;AAEA,MAAI,SAAS,SAAS,WAAW;AAC/B,WAAO,IAAI,YAAY,gBAAgB,SAAS;AAAA,EAClD;AAEA,SAAO;AACT;","names":[]}

View file

@ -0,0 +1,50 @@
// src/helpers/production-mode.ts
import { StackAssertionError, captureError } from "../utils/errors";
import { isLocalhost } from "../utils/urls";
function getProductionModeErrors(project) {
const errors = [];
const domainsFixUrl = `/projects/${project.id}/domains`;
if (project.config.allow_localhost) {
errors.push({
message: "Localhost is not allowed in production mode, turn off 'Allow localhost' in project settings",
relativeFixUrl: domainsFixUrl
});
}
for (const { domain } of project.config.domains) {
let url;
try {
url = new URL(domain);
} catch (e) {
captureError("production-mode-domain-not-valid", new StackAssertionError("Domain was somehow not a valid URL; we should've caught this when setting the domain in the first place", {
domain,
projectId: project
}));
errors.push({
message: "Trusted domain is not a valid URL: " + domain,
relativeFixUrl: domainsFixUrl
});
continue;
}
if (isLocalhost(url)) {
errors.push({
message: "Localhost domains are not allowed to be trusted in production mode: " + domain,
relativeFixUrl: domainsFixUrl
});
} else if (url.hostname.match(/^\d+(\.\d+)*$/)) {
errors.push({
message: "Direct IPs are not valid for trusted domains in production mode: " + domain,
relativeFixUrl: domainsFixUrl
});
} else if (url.protocol !== "https:") {
errors.push({
message: "Trusted domains should be HTTPS: " + domain,
relativeFixUrl: domainsFixUrl
});
}
}
return errors;
}
export {
getProductionModeErrors
};
//# sourceMappingURL=production-mode.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../../../src/helpers/production-mode.ts"],"sourcesContent":["import { ProjectsCrud } from \"../interface/crud/projects\";\nimport { StackAssertionError, captureError } from \"../utils/errors\";\nimport { isLocalhost } from \"../utils/urls\";\n\nexport type ProductionModeError = {\n message: string,\n relativeFixUrl: `/${string}`,\n};\n\nexport function getProductionModeErrors(project: ProjectsCrud[\"Admin\"][\"Read\"]): ProductionModeError[] {\n const errors: ProductionModeError[] = [];\n const domainsFixUrl = `/projects/${project.id}/domains` as const;\n\n if (project.config.allow_localhost) {\n errors.push({\n message: \"Localhost is not allowed in production mode, turn off 'Allow localhost' in project settings\",\n relativeFixUrl: domainsFixUrl,\n });\n }\n\n for (const { domain } of project.config.domains) {\n let url;\n try {\n url = new URL(domain);\n } catch (e) {\n captureError(\"production-mode-domain-not-valid\", new StackAssertionError(\"Domain was somehow not a valid URL; we should've caught this when setting the domain in the first place\", {\n domain,\n projectId: project\n }));\n errors.push({\n message: \"Trusted domain is not a valid URL: \" + domain,\n relativeFixUrl: domainsFixUrl,\n });\n continue;\n }\n\n if (isLocalhost(url)) {\n errors.push({\n message: \"Localhost domains are not allowed to be trusted in production mode: \" + domain,\n relativeFixUrl: domainsFixUrl,\n });\n } else if (url.hostname.match(/^\\d+(\\.\\d+)*$/)) {\n errors.push({\n message: \"Direct IPs are not valid for trusted domains in production mode: \" + domain,\n relativeFixUrl: domainsFixUrl,\n });\n } else if (url.protocol !== \"https:\") {\n errors.push({\n message: \"Trusted domains should be HTTPS: \" + domain,\n relativeFixUrl: domainsFixUrl,\n });\n }\n }\n\n return errors;\n}\n"],"mappings":";AACA,SAAS,qBAAqB,oBAAoB;AAClD,SAAS,mBAAmB;AAOrB,SAAS,wBAAwB,SAA+D;AACrG,QAAM,SAAgC,CAAC;AACvC,QAAM,gBAAgB,aAAa,QAAQ,EAAE;AAE7C,MAAI,QAAQ,OAAO,iBAAiB;AAClC,WAAO,KAAK;AAAA,MACV,SAAS;AAAA,MACT,gBAAgB;AAAA,IAClB,CAAC;AAAA,EACH;AAEA,aAAW,EAAE,OAAO,KAAK,QAAQ,OAAO,SAAS;AAC/C,QAAI;AACJ,QAAI;AACF,YAAM,IAAI,IAAI,MAAM;AAAA,IACtB,SAAS,GAAG;AACV,mBAAa,oCAAoC,IAAI,oBAAoB,2GAA2G;AAAA,QAClL;AAAA,QACA,WAAW;AAAA,MACb,CAAC,CAAC;AACF,aAAO,KAAK;AAAA,QACV,SAAS,wCAAwC;AAAA,QACjD,gBAAgB;AAAA,MAClB,CAAC;AACD;AAAA,IACF;AAEA,QAAI,YAAY,GAAG,GAAG;AACpB,aAAO,KAAK;AAAA,QACV,SAAS,yEAAyE;AAAA,QAClF,gBAAgB;AAAA,MAClB,CAAC;AAAA,IACH,WAAW,IAAI,SAAS,MAAM,eAAe,GAAG;AAC9C,aAAO,KAAK;AAAA,QACV,SAAS,sEAAsE;AAAA,QAC/E,gBAAgB;AAAA,MAClB,CAAC;AAAA,IACH,WAAW,IAAI,aAAa,UAAU;AACpC,aAAO,KAAK;AAAA,QACV,SAAS,sCAAsC;AAAA,QAC/C,gBAAgB;AAAA,MAClB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;","names":[]}

View file

@ -0,0 +1,38 @@
// src/hooks/use-async-callback.tsx
import React from "react";
import { captureError } from "../utils/errors";
function useAsyncCallback(callback, deps) {
const [error, setError] = React.useState(void 0);
const [loadingCount, setLoadingCount] = React.useState(0);
const cb = React.useCallback(
async (...args) => {
setLoadingCount((c) => c + 1);
try {
return await callback(...args);
} catch (e) {
setError(e);
throw e;
} finally {
setLoadingCount((c) => c - 1);
}
},
deps
);
return [cb, loadingCount > 0, error];
}
function useAsyncCallbackWithLoggedError(callback, deps) {
const [newCallback, loading] = useAsyncCallback(async (...args) => {
try {
return await callback(...args);
} catch (e) {
captureError("async-callback", e);
throw e;
}
}, deps);
return [newCallback, loading];
}
export {
useAsyncCallback,
useAsyncCallbackWithLoggedError
};
//# sourceMappingURL=use-async-callback.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../../../src/hooks/use-async-callback.tsx"],"sourcesContent":["import React from \"react\";\nimport { captureError } from \"../utils/errors\";\n\nexport function useAsyncCallback<A extends any[], R>(\n callback: (...args: A) => Promise<R>,\n deps: React.DependencyList\n): [cb: (...args: A) => Promise<R>, loading: boolean, error: unknown | undefined] {\n const [error, setError] = React.useState<unknown | undefined>(undefined);\n const [loadingCount, setLoadingCount] = React.useState(0);\n\n const cb = React.useCallback(\n async (...args: A) => {\n setLoadingCount((c) => c + 1);\n try {\n return await callback(...args);\n } catch (e) {\n setError(e);\n throw e;\n } finally {\n setLoadingCount((c) => c - 1);\n }\n },\n deps,\n );\n\n return [cb, loadingCount > 0, error];\n}\n\nexport function useAsyncCallbackWithLoggedError<A extends any[], R>(\n callback: (...args: A) => Promise<R>,\n deps: React.DependencyList\n): [cb: (...args: A) => Promise<R>, loading: boolean] {\n const [newCallback, loading] = useAsyncCallback<A, R>(async (...args) => {\n try {\n return await callback(...args);\n } catch (e) {\n captureError(\"async-callback\", e);\n throw e;\n }\n }, deps);\n\n return [newCallback, loading];\n}\n"],"mappings":";AAAA,OAAO,WAAW;AAClB,SAAS,oBAAoB;AAEtB,SAAS,iBACd,UACA,MACgF;AAChF,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAA8B,MAAS;AACvE,QAAM,CAAC,cAAc,eAAe,IAAI,MAAM,SAAS,CAAC;AAExD,QAAM,KAAK,MAAM;AAAA,IACf,UAAU,SAAY;AACpB,sBAAgB,CAAC,MAAM,IAAI,CAAC;AAC5B,UAAI;AACF,eAAO,MAAM,SAAS,GAAG,IAAI;AAAA,MAC/B,SAAS,GAAG;AACV,iBAAS,CAAC;AACV,cAAM;AAAA,MACR,UAAE;AACA,wBAAgB,CAAC,MAAM,IAAI,CAAC;AAAA,MAC9B;AAAA,IACF;AAAA,IACA;AAAA,EACF;AAEA,SAAO,CAAC,IAAI,eAAe,GAAG,KAAK;AACrC;AAEO,SAAS,gCACd,UACA,MACoD;AACpD,QAAM,CAAC,aAAa,OAAO,IAAI,iBAAuB,UAAU,SAAS;AACvE,QAAI;AACF,aAAO,MAAM,SAAS,GAAG,IAAI;AAAA,IAC/B,SAAS,GAAG;AACV,mBAAa,kBAAkB,CAAC;AAChC,YAAM;AAAA,IACR;AAAA,EACF,GAAG,IAAI;AAEP,SAAO,CAAC,aAAa,OAAO;AAC9B;","names":[]}

View file

@ -0,0 +1,23 @@
// src/hooks/use-async-external-store.tsx
import { useEffect, useState } from "react";
import { AsyncResult } from "../utils/results";
function useAsyncExternalStore(subscribe) {
const [isAvailable, setIsAvailable] = useState(false);
const [value, setValue] = useState();
useEffect(() => {
const unsubscribe = subscribe((value2) => {
setValue(() => value2);
setIsAvailable(() => true);
});
return unsubscribe;
}, [subscribe]);
if (isAvailable) {
return AsyncResult.ok(value);
} else {
return AsyncResult.pending();
}
}
export {
useAsyncExternalStore
};
//# sourceMappingURL=use-async-external-store.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../../../src/hooks/use-async-external-store.tsx"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport { AsyncResult } from \"../utils/results\";\n\nexport function useAsyncExternalStore<T>(\n subscribe: (callback: (t: T) => void) => (() => void),\n): AsyncResult<T, never> & { status: \"ok\" | \"pending\" } {\n // sure, the \"sync\" in useSyncExternalStore refers to \"synchronize a store\" and not \"sync/async\", but it's too good of a name to pass up on\n\n const [isAvailable, setIsAvailable] = useState(false);\n const [value, setValue] = useState<T>();\n useEffect(() => {\n const unsubscribe = subscribe((value: T) => {\n setValue(() => value);\n setIsAvailable(() => true);\n });\n return unsubscribe;\n }, [subscribe]);\n\n if (isAvailable) {\n return AsyncResult.ok(value as T);\n } else {\n return AsyncResult.pending();\n }\n}\n"],"mappings":";AAAA,SAAS,WAAW,gBAAgB;AACpC,SAAS,mBAAmB;AAErB,SAAS,sBACd,WACsD;AAGtD,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,KAAK;AACpD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAY;AACtC,YAAU,MAAM;AACd,UAAM,cAAc,UAAU,CAACA,WAAa;AAC1C,eAAS,MAAMA,MAAK;AACpB,qBAAe,MAAM,IAAI;AAAA,IAC3B,CAAC;AACD,WAAO;AAAA,EACT,GAAG,CAAC,SAAS,CAAC;AAEd,MAAI,aAAa;AACf,WAAO,YAAY,GAAG,KAAU;AAAA,EAClC,OAAO;AACL,WAAO,YAAY,QAAQ;AAAA,EAC7B;AACF;","names":["value"]}

View file

@ -0,0 +1,17 @@
// src/hooks/use-hash.tsx
import { useSyncExternalStore } from "react";
import { suspendIfSsr } from "../utils/react";
var useHash = () => {
suspendIfSsr("useHash");
return useSyncExternalStore(
(onChange) => {
const interval = setInterval(() => onChange(), 10);
return () => clearInterval(interval);
},
() => window.location.hash.substring(1)
);
};
export {
useHash
};
//# sourceMappingURL=use-hash.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../../../src/hooks/use-hash.tsx"],"sourcesContent":["import { useSyncExternalStore } from \"react\";\nimport { suspendIfSsr } from \"../utils/react\";\n\nexport const useHash = () => {\n suspendIfSsr(\"useHash\");\n return useSyncExternalStore(\n (onChange) => {\n const interval = setInterval(() => onChange(), 10);\n return () => clearInterval(interval);\n },\n () => window.location.hash.substring(1)\n );\n};\n\n"],"mappings":";AAAA,SAAS,4BAA4B;AACrC,SAAS,oBAAoB;AAEtB,IAAM,UAAU,MAAM;AAC3B,eAAa,SAAS;AACtB,SAAO;AAAA,IACL,CAAC,aAAa;AACZ,YAAM,WAAW,YAAY,MAAM,SAAS,GAAG,EAAE;AACjD,aAAO,MAAM,cAAc,QAAQ;AAAA,IACrC;AAAA,IACA,MAAM,OAAO,SAAS,KAAK,UAAU,CAAC;AAAA,EACxC;AACF;","names":[]}

View file

@ -0,0 +1,61 @@
// src/hooks/use-strict-memo.tsx
import { useId, useInsertionEffect } from "react";
import { Result } from "../utils/results";
var cached = /* @__PURE__ */ new Map();
function unwrapFromInner(dependencies, inner) {
if (dependencies.length === 0 !== "isNotNestedMap" in inner) {
return Result.error(void 0);
}
if ("isNotNestedMap" in inner) {
if (dependencies.length === 0) {
return Result.ok(inner.value);
} else {
return Result.error(void 0);
}
} else {
if (dependencies.length === 0) {
return Result.error(void 0);
} else {
const [key, ...rest] = dependencies;
const newInner = inner.get(key);
if (!newInner) {
return Result.error(void 0);
}
return unwrapFromInner(rest, newInner);
}
}
}
function wrapToInner(dependencies, value) {
if (dependencies.length === 0) {
return { isNotNestedMap: true, value };
}
const [key, ...rest] = dependencies;
const inner = wrapToInner(rest, value);
const isObject = typeof key === "object" && key !== null;
const isUnregisteredSymbol = typeof key === "symbol" && Symbol.keyFor(key) === void 0;
const isWeak = isObject || isUnregisteredSymbol;
const mapType = isWeak ? WeakMap : Map;
return new mapType([[key, inner]]);
}
function useStrictMemo(callback, dependencies) {
const id = useId();
useInsertionEffect(() => {
return () => {
cached.delete(id);
};
}, [id]);
const c = cached.get(id);
if (c) {
const unwrapped = unwrapFromInner(dependencies, c);
if (unwrapped.status === "ok") {
return unwrapped.data;
}
}
const value = callback();
cached.set(id, wrapToInner(dependencies, value));
return value;
}
export {
useStrictMemo
};
//# sourceMappingURL=use-strict-memo.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,22 @@
// src/index.ts
import {
StackAdminInterface
} from "./interface/adminInterface";
import {
StackClientInterface
} from "./interface/clientInterface";
import {
StackServerInterface
} from "./interface/serverInterface";
import {
KnownError,
KnownErrors
} from "./known-errors";
export {
KnownError,
KnownErrors,
StackAdminInterface,
StackClientInterface,
StackServerInterface
};
//# sourceMappingURL=index.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../../src/index.ts"],"sourcesContent":["export {\n StackAdminInterface\n} from \"./interface/adminInterface\";\nexport {\n StackClientInterface\n} from \"./interface/clientInterface\";\nexport {\n StackServerInterface\n} from \"./interface/serverInterface\";\nexport {\n KnownError,\n KnownErrors\n} from \"./known-errors\";\n\n"],"mappings":";AAAA;AAAA,EACE;AAAA,OACK;AACP;AAAA,EACE;AAAA,OACK;AACP;AAAA,EACE;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OACK;","names":[]}

View file

@ -0,0 +1,244 @@
// src/interface/adminInterface.ts
import { StackServerInterface } from "./serverInterface";
var StackAdminInterface = class extends StackServerInterface {
constructor(options) {
super(options);
this.options = options;
}
async sendAdminRequest(path, options, session, requestType = "admin") {
return await this.sendServerRequest(
path,
{
...options,
headers: {
"x-stack-super-secret-admin-key": "superSecretAdminKey" in this.options ? this.options.superSecretAdminKey : "",
...options.headers
}
},
session,
requestType
);
}
async getProject() {
const response = await this.sendAdminRequest(
"/internal/projects/current",
{
method: "GET"
},
null
);
return await response.json();
}
async updateProject(update) {
const response = await this.sendAdminRequest(
"/internal/projects/current",
{
method: "PATCH",
headers: {
"content-type": "application/json"
},
body: JSON.stringify(update)
},
null
);
return await response.json();
}
async createInternalApiKey(options) {
const response = await this.sendAdminRequest(
"/internal/api-keys",
{
method: "POST",
headers: {
"content-type": "application/json"
},
body: JSON.stringify(options)
},
null
);
return await response.json();
}
async listInternalApiKeys() {
const response = await this.sendAdminRequest("/internal/api-keys", {}, null);
const result = await response.json();
return result.items;
}
async revokeInternalApiKeyById(id) {
await this.sendAdminRequest(
`/internal/api-keys/${id}`,
{
method: "PATCH",
headers: {
"content-type": "application/json"
},
body: JSON.stringify({
revoked: true
})
},
null
);
}
async getInternalApiKey(id, session) {
const response = await this.sendAdminRequest(`/internal/api-keys/${id}`, {}, session);
return await response.json();
}
async listEmailTemplates() {
const response = await this.sendAdminRequest(`/email-templates`, {}, null);
const result = await response.json();
return result.items;
}
async updateEmailTemplate(type, data) {
const result = await this.sendAdminRequest(
`/email-templates/${type}`,
{
method: "PATCH",
headers: {
"content-type": "application/json"
},
body: JSON.stringify(data)
},
null
);
return await result.json();
}
async resetEmailTemplate(type) {
await this.sendAdminRequest(
`/email-templates/${type}`,
{ method: "DELETE" },
null
);
}
// Team permission definitions methods
async listTeamPermissionDefinitions() {
const response = await this.sendAdminRequest(`/team-permission-definitions`, {}, null);
const result = await response.json();
return result.items;
}
async createTeamPermissionDefinition(data) {
const response = await this.sendAdminRequest(
"/team-permission-definitions",
{
method: "POST",
headers: {
"content-type": "application/json"
},
body: JSON.stringify(data)
},
null
);
return await response.json();
}
async updateTeamPermissionDefinition(permissionId, data) {
const response = await this.sendAdminRequest(
`/team-permission-definitions/${permissionId}`,
{
method: "PATCH",
headers: {
"content-type": "application/json"
},
body: JSON.stringify(data)
},
null
);
return await response.json();
}
async deleteTeamPermissionDefinition(permissionId) {
await this.sendAdminRequest(
`/team-permission-definitions/${permissionId}`,
{ method: "DELETE" },
null
);
}
async listProjectPermissionDefinitions() {
const response = await this.sendAdminRequest(`/project-permission-definitions`, {}, null);
const result = await response.json();
return result.items;
}
async createProjectPermissionDefinition(data) {
const response = await this.sendAdminRequest(
"/project-permission-definitions",
{
method: "POST",
headers: {
"content-type": "application/json"
},
body: JSON.stringify(data)
},
null
);
return await response.json();
}
async updateProjectPermissionDefinition(permissionId, data) {
const response = await this.sendAdminRequest(
`/project-permission-definitions/${permissionId}`,
{
method: "PATCH",
headers: {
"content-type": "application/json"
},
body: JSON.stringify(data)
},
null
);
return await response.json();
}
async deleteProjectPermissionDefinition(permissionId) {
await this.sendAdminRequest(
`/project-permission-definitions/${permissionId}`,
{ method: "DELETE" },
null
);
}
async getSvixToken() {
const response = await this.sendAdminRequest(
"/webhooks/svix-token",
{
method: "POST",
headers: {
"content-type": "application/json"
},
body: JSON.stringify({})
},
null
);
return await response.json();
}
async deleteProject() {
await this.sendAdminRequest(
"/internal/projects/current",
{
method: "DELETE"
},
null
);
}
async getMetrics() {
const response = await this.sendAdminRequest(
"/internal/metrics",
{
method: "GET"
},
null
);
return await response.json();
}
async sendTestEmail(data) {
const response = await this.sendAdminRequest(`/internal/send-test-email`, {
method: "POST",
headers: {
"content-type": "application/json"
},
body: JSON.stringify(data)
}, null);
return await response.json();
}
async listSentEmails() {
const response = await this.sendAdminRequest("/internal/emails", {
method: "GET"
}, null);
return await response.json();
}
};
export {
StackAdminInterface
};
//# sourceMappingURL=adminInterface.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,77 @@
// src/interface/crud/contact-channels.ts
import { createCrud } from "../../crud";
import { contactChannelIdSchema, contactChannelIsPrimarySchema, contactChannelIsVerifiedSchema, contactChannelTypeSchema, contactChannelUsedForAuthSchema, contactChannelValueSchema, userIdOrMeSchema, userIdSchema, yupMixed, yupObject } from "../../schema-fields";
var contactChannelsClientReadSchema = yupObject({
user_id: userIdSchema.defined(),
id: contactChannelIdSchema.defined(),
value: contactChannelValueSchema.defined(),
type: contactChannelTypeSchema.defined(),
used_for_auth: contactChannelUsedForAuthSchema.defined(),
is_verified: contactChannelIsVerifiedSchema.defined(),
is_primary: contactChannelIsPrimarySchema.defined()
}).defined();
var contactChannelsCrudClientUpdateSchema = yupObject({
value: contactChannelValueSchema.optional(),
type: contactChannelTypeSchema.optional(),
used_for_auth: contactChannelUsedForAuthSchema.optional(),
is_primary: contactChannelIsPrimarySchema.optional()
}).defined();
var contactChannelsCrudServerUpdateSchema = contactChannelsCrudClientUpdateSchema.concat(yupObject({
is_verified: contactChannelIsVerifiedSchema.optional()
}));
var contactChannelsCrudClientCreateSchema = yupObject({
user_id: userIdOrMeSchema.defined(),
value: contactChannelValueSchema.defined(),
type: contactChannelTypeSchema.defined(),
used_for_auth: contactChannelUsedForAuthSchema.defined(),
is_primary: contactChannelIsPrimarySchema.optional()
}).defined();
var contactChannelsCrudServerCreateSchema = contactChannelsCrudClientCreateSchema.concat(yupObject({
is_verified: contactChannelIsVerifiedSchema.optional()
}));
var contactChannelsCrudClientDeleteSchema = yupMixed();
var contactChannelsCrud = createCrud({
clientReadSchema: contactChannelsClientReadSchema,
clientUpdateSchema: contactChannelsCrudClientUpdateSchema,
clientCreateSchema: contactChannelsCrudClientCreateSchema,
clientDeleteSchema: contactChannelsCrudClientDeleteSchema,
serverUpdateSchema: contactChannelsCrudServerUpdateSchema,
serverCreateSchema: contactChannelsCrudServerCreateSchema,
docs: {
clientRead: {
summary: "Get a contact channel",
description: "Retrieves a specific contact channel by the user ID and the contact channel ID.",
tags: ["Contact Channels"]
},
clientCreate: {
summary: "Create a contact channel",
description: "Add a new contact channel for a user.",
tags: ["Contact Channels"]
},
clientUpdate: {
summary: "Update a contact channel",
description: "Updates an existing contact channel. Only the values provided will be updated.",
tags: ["Contact Channels"]
},
clientDelete: {
summary: "Delete a contact channel",
description: "Removes a contact channel for a given user.",
tags: ["Contact Channels"]
},
clientList: {
summary: "List contact channels",
description: "Retrieves a list of all contact channels for a user.",
tags: ["Contact Channels"]
}
}
});
export {
contactChannelsClientReadSchema,
contactChannelsCrud,
contactChannelsCrudClientCreateSchema,
contactChannelsCrudClientDeleteSchema,
contactChannelsCrudClientUpdateSchema,
contactChannelsCrudServerCreateSchema,
contactChannelsCrudServerUpdateSchema
};
//# sourceMappingURL=contact-channels.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/interface/crud/contact-channels.ts"],"sourcesContent":["import { CrudTypeOf, createCrud } from \"../../crud\";\nimport { contactChannelIdSchema, contactChannelIsPrimarySchema, contactChannelIsVerifiedSchema, contactChannelTypeSchema, contactChannelUsedForAuthSchema, contactChannelValueSchema, userIdOrMeSchema, userIdSchema, yupMixed, yupObject } from \"../../schema-fields\";\n\nexport const contactChannelsClientReadSchema = yupObject({\n user_id: userIdSchema.defined(),\n id: contactChannelIdSchema.defined(),\n value: contactChannelValueSchema.defined(),\n type: contactChannelTypeSchema.defined(),\n used_for_auth: contactChannelUsedForAuthSchema.defined(),\n is_verified: contactChannelIsVerifiedSchema.defined(),\n is_primary: contactChannelIsPrimarySchema.defined(),\n}).defined();\n\nexport const contactChannelsCrudClientUpdateSchema = yupObject({\n value: contactChannelValueSchema.optional(),\n type: contactChannelTypeSchema.optional(),\n used_for_auth: contactChannelUsedForAuthSchema.optional(),\n is_primary: contactChannelIsPrimarySchema.optional(),\n}).defined();\n\nexport const contactChannelsCrudServerUpdateSchema = contactChannelsCrudClientUpdateSchema.concat(yupObject({\n is_verified: contactChannelIsVerifiedSchema.optional(),\n}));\n\nexport const contactChannelsCrudClientCreateSchema = yupObject({\n user_id: userIdOrMeSchema.defined(),\n value: contactChannelValueSchema.defined(),\n type: contactChannelTypeSchema.defined(),\n used_for_auth: contactChannelUsedForAuthSchema.defined(),\n is_primary: contactChannelIsPrimarySchema.optional(),\n}).defined();\n\nexport const contactChannelsCrudServerCreateSchema = contactChannelsCrudClientCreateSchema.concat(yupObject({\n is_verified: contactChannelIsVerifiedSchema.optional(),\n}));\n\nexport const contactChannelsCrudClientDeleteSchema = yupMixed();\n\nexport const contactChannelsCrud = createCrud({\n clientReadSchema: contactChannelsClientReadSchema,\n clientUpdateSchema: contactChannelsCrudClientUpdateSchema,\n clientCreateSchema: contactChannelsCrudClientCreateSchema,\n clientDeleteSchema: contactChannelsCrudClientDeleteSchema,\n serverUpdateSchema: contactChannelsCrudServerUpdateSchema,\n serverCreateSchema: contactChannelsCrudServerCreateSchema,\n docs: {\n clientRead: {\n summary: \"Get a contact channel\",\n description: \"Retrieves a specific contact channel by the user ID and the contact channel ID.\",\n tags: [\"Contact Channels\"],\n },\n clientCreate: {\n summary: \"Create a contact channel\",\n description: \"Add a new contact channel for a user.\",\n tags: [\"Contact Channels\"],\n },\n clientUpdate: {\n summary: \"Update a contact channel\",\n description: \"Updates an existing contact channel. Only the values provided will be updated.\",\n tags: [\"Contact Channels\"],\n },\n clientDelete: {\n summary: \"Delete a contact channel\",\n description: \"Removes a contact channel for a given user.\",\n tags: [\"Contact Channels\"],\n },\n clientList: {\n summary: \"List contact channels\",\n description: \"Retrieves a list of all contact channels for a user.\",\n tags: [\"Contact Channels\"],\n }\n }\n});\nexport type ContactChannelsCrud = CrudTypeOf<typeof contactChannelsCrud>;\n"],"mappings":";AAAA,SAAqB,kBAAkB;AACvC,SAAS,wBAAwB,+BAA+B,gCAAgC,0BAA0B,iCAAiC,2BAA2B,kBAAkB,cAAc,UAAU,iBAAiB;AAE1O,IAAM,kCAAkC,UAAU;AAAA,EACvD,SAAS,aAAa,QAAQ;AAAA,EAC9B,IAAI,uBAAuB,QAAQ;AAAA,EACnC,OAAO,0BAA0B,QAAQ;AAAA,EACzC,MAAM,yBAAyB,QAAQ;AAAA,EACvC,eAAe,gCAAgC,QAAQ;AAAA,EACvD,aAAa,+BAA+B,QAAQ;AAAA,EACpD,YAAY,8BAA8B,QAAQ;AACpD,CAAC,EAAE,QAAQ;AAEJ,IAAM,wCAAwC,UAAU;AAAA,EAC7D,OAAO,0BAA0B,SAAS;AAAA,EAC1C,MAAM,yBAAyB,SAAS;AAAA,EACxC,eAAe,gCAAgC,SAAS;AAAA,EACxD,YAAY,8BAA8B,SAAS;AACrD,CAAC,EAAE,QAAQ;AAEJ,IAAM,wCAAwC,sCAAsC,OAAO,UAAU;AAAA,EAC1G,aAAa,+BAA+B,SAAS;AACvD,CAAC,CAAC;AAEK,IAAM,wCAAwC,UAAU;AAAA,EAC7D,SAAS,iBAAiB,QAAQ;AAAA,EAClC,OAAO,0BAA0B,QAAQ;AAAA,EACzC,MAAM,yBAAyB,QAAQ;AAAA,EACvC,eAAe,gCAAgC,QAAQ;AAAA,EACvD,YAAY,8BAA8B,SAAS;AACrD,CAAC,EAAE,QAAQ;AAEJ,IAAM,wCAAwC,sCAAsC,OAAO,UAAU;AAAA,EAC1G,aAAa,+BAA+B,SAAS;AACvD,CAAC,CAAC;AAEK,IAAM,wCAAwC,SAAS;AAEvD,IAAM,sBAAsB,WAAW;AAAA,EAC5C,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,oBAAoB;AAAA,EACpB,oBAAoB;AAAA,EACpB,oBAAoB;AAAA,EACpB,oBAAoB;AAAA,EACpB,MAAM;AAAA,IACJ,YAAY;AAAA,MACV,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM,CAAC,kBAAkB;AAAA,IAC3B;AAAA,IACA,cAAc;AAAA,MACZ,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM,CAAC,kBAAkB;AAAA,IAC3B;AAAA,IACA,cAAc;AAAA,MACZ,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM,CAAC,kBAAkB;AAAA,IAC3B;AAAA,IACA,cAAc;AAAA,MACZ,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM,CAAC,kBAAkB;AAAA,IAC3B;AAAA,IACA,YAAY;AAAA,MACV,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM,CAAC,kBAAkB;AAAA,IAC3B;AAAA,EACF;AACF,CAAC;","names":[]}

View file

@ -0,0 +1,65 @@
// src/interface/crud/current-user.ts
import { createCrud } from "../../crud";
import { yupObject } from "../../schema-fields";
import { teamsCrudClientReadSchema } from "./teams";
import { usersCrudServerDeleteSchema, usersCrudServerReadSchema, usersCrudServerUpdateSchema } from "./users";
var clientUpdateSchema = usersCrudServerUpdateSchema.pick([
"display_name",
"profile_image_url",
"client_metadata",
"selected_team_id",
"totp_secret_base64",
"otp_auth_enabled",
"passkey_auth_enabled"
]).defined();
var serverUpdateSchema = usersCrudServerUpdateSchema;
var clientReadSchema = usersCrudServerReadSchema.pick([
"id",
"primary_email",
"primary_email_verified",
"display_name",
"client_metadata",
"client_read_only_metadata",
"profile_image_url",
"signed_up_at_millis",
"has_password",
"auth_with_email",
"oauth_providers",
"selected_team_id",
"requires_totp_mfa",
"otp_auth_enabled",
"passkey_auth_enabled",
"is_anonymous"
]).concat(yupObject({
selected_team: teamsCrudClientReadSchema.nullable().defined()
})).defined();
var serverReadSchema = usersCrudServerReadSchema.defined();
var clientDeleteSchema = usersCrudServerDeleteSchema;
var currentUserCrud = createCrud({
clientReadSchema,
serverReadSchema,
clientUpdateSchema,
serverUpdateSchema,
clientDeleteSchema,
docs: {
clientRead: {
summary: "Get current user",
description: "Gets the currently authenticated user.",
tags: ["Users"]
},
clientUpdate: {
summary: "Update current user",
description: "Updates the currently authenticated user. Only the values provided will be updated.",
tags: ["Users"]
},
clientDelete: {
summary: "Delete current user",
description: "Deletes the currently authenticated user. Use this with caution.",
tags: ["Users"]
}
}
});
export {
currentUserCrud
};
//# sourceMappingURL=current-user.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/interface/crud/current-user.ts"],"sourcesContent":["import { CrudTypeOf, createCrud } from \"../../crud\";\nimport { yupObject } from \"../../schema-fields\";\nimport { teamsCrudClientReadSchema } from \"./teams\";\nimport { usersCrudServerDeleteSchema, usersCrudServerReadSchema, usersCrudServerUpdateSchema } from \"./users\";\n\nconst clientUpdateSchema = usersCrudServerUpdateSchema.pick([\n \"display_name\",\n \"profile_image_url\",\n \"client_metadata\",\n \"selected_team_id\",\n \"totp_secret_base64\",\n \"otp_auth_enabled\",\n \"passkey_auth_enabled\",\n]).defined();\n\nconst serverUpdateSchema = usersCrudServerUpdateSchema;\n\nconst clientReadSchema = usersCrudServerReadSchema.pick([\n \"id\",\n \"primary_email\",\n \"primary_email_verified\",\n \"display_name\",\n \"client_metadata\",\n \"client_read_only_metadata\",\n \"profile_image_url\",\n \"signed_up_at_millis\",\n \"has_password\",\n \"auth_with_email\",\n \"oauth_providers\",\n \"selected_team_id\",\n \"requires_totp_mfa\",\n \"otp_auth_enabled\",\n \"passkey_auth_enabled\",\n \"is_anonymous\",\n]).concat(yupObject({\n selected_team: teamsCrudClientReadSchema.nullable().defined(),\n})).defined();\n\nconst serverReadSchema = usersCrudServerReadSchema.defined();\n\nconst clientDeleteSchema = usersCrudServerDeleteSchema;\n\nexport const currentUserCrud = createCrud({\n clientReadSchema,\n serverReadSchema,\n clientUpdateSchema,\n serverUpdateSchema,\n clientDeleteSchema,\n docs: {\n clientRead: {\n summary: 'Get current user',\n description: 'Gets the currently authenticated user.',\n tags: ['Users'],\n },\n clientUpdate: {\n summary: 'Update current user',\n description: 'Updates the currently authenticated user. Only the values provided will be updated.',\n tags: ['Users'],\n },\n clientDelete: {\n summary: 'Delete current user',\n description: 'Deletes the currently authenticated user. Use this with caution.',\n tags: ['Users'],\n },\n },\n});\nexport type CurrentUserCrud = CrudTypeOf<typeof currentUserCrud>;\n"],"mappings":";AAAA,SAAqB,kBAAkB;AACvC,SAAS,iBAAiB;AAC1B,SAAS,iCAAiC;AAC1C,SAAS,6BAA6B,2BAA2B,mCAAmC;AAEpG,IAAM,qBAAqB,4BAA4B,KAAK;AAAA,EAC1D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC,EAAE,QAAQ;AAEX,IAAM,qBAAqB;AAE3B,IAAM,mBAAmB,0BAA0B,KAAK;AAAA,EACtD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC,EAAE,OAAO,UAAU;AAAA,EAClB,eAAe,0BAA0B,SAAS,EAAE,QAAQ;AAC9D,CAAC,CAAC,EAAE,QAAQ;AAEZ,IAAM,mBAAmB,0BAA0B,QAAQ;AAE3D,IAAM,qBAAqB;AAEpB,IAAM,kBAAkB,WAAW;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,MAAM;AAAA,IACJ,YAAY;AAAA,MACV,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM,CAAC,OAAO;AAAA,IAChB;AAAA,IACA,cAAc;AAAA,MACZ,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM,CAAC,OAAO;AAAA,IAChB;AAAA,IACA,cAAc;AAAA,MACZ,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM,CAAC,OAAO;AAAA,IAChB;AAAA,EACF;AACF,CAAC;","names":[]}

View file

@ -0,0 +1,52 @@
// src/interface/crud/email-templates.ts
import { createCrud } from "../../crud";
import { jsonSchema, yupBoolean, yupMixed, yupObject, yupString } from "../../schema-fields";
var emailTemplateTypes = ["email_verification", "password_reset", "magic_link", "team_invitation"];
var emailTemplateAdminReadSchema = yupObject({
type: yupString().oneOf(emailTemplateTypes).defined(),
subject: yupString().defined(),
content: jsonSchema.defined(),
is_default: yupBoolean().defined()
}).defined();
var emailTemplateCrudAdminUpdateSchema = yupObject({
content: jsonSchema.nonNullable().optional(),
subject: yupString().optional()
}).defined();
var emailTemplateCrudAdminDeleteSchema = yupMixed();
var emailTemplateCrudAdminCreateSchema = yupObject({
type: yupString().oneOf(emailTemplateTypes).defined(),
content: jsonSchema.defined(),
subject: yupString().defined()
}).defined();
var emailTemplateCrud = createCrud({
adminReadSchema: emailTemplateAdminReadSchema,
adminUpdateSchema: emailTemplateCrudAdminUpdateSchema,
adminCreateSchema: emailTemplateCrudAdminCreateSchema,
adminDeleteSchema: emailTemplateCrudAdminDeleteSchema,
docs: {
adminRead: {
hidden: true
},
adminCreate: {
hidden: true
},
adminUpdate: {
hidden: true
},
adminDelete: {
hidden: true
},
adminList: {
hidden: true
}
}
});
export {
emailTemplateAdminReadSchema,
emailTemplateCrud,
emailTemplateCrudAdminCreateSchema,
emailTemplateCrudAdminDeleteSchema,
emailTemplateCrudAdminUpdateSchema,
emailTemplateTypes
};
//# sourceMappingURL=email-templates.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/interface/crud/email-templates.ts"],"sourcesContent":["import { CrudTypeOf, createCrud } from \"../../crud\";\nimport { jsonSchema, yupBoolean, yupMixed, yupObject, yupString } from \"../../schema-fields\";\n\nexport type EmailTemplateType = typeof emailTemplateTypes[number];\nexport const emailTemplateTypes = ['email_verification', 'password_reset', 'magic_link', 'team_invitation'] as const;\n\nexport const emailTemplateAdminReadSchema = yupObject({\n type: yupString().oneOf(emailTemplateTypes).defined(),\n subject: yupString().defined(),\n content: jsonSchema.defined(),\n is_default: yupBoolean().defined(),\n}).defined();\n\nexport const emailTemplateCrudAdminUpdateSchema = yupObject({\n content: jsonSchema.nonNullable().optional(),\n subject: yupString().optional(),\n}).defined();\n\nexport const emailTemplateCrudAdminDeleteSchema = yupMixed();\n\nexport const emailTemplateCrudAdminCreateSchema = yupObject({\n type: yupString().oneOf(emailTemplateTypes).defined(),\n content: jsonSchema.defined(),\n subject: yupString().defined(),\n}).defined();\n\nexport const emailTemplateCrud = createCrud({\n adminReadSchema: emailTemplateAdminReadSchema,\n adminUpdateSchema: emailTemplateCrudAdminUpdateSchema,\n adminCreateSchema: emailTemplateCrudAdminCreateSchema,\n adminDeleteSchema: emailTemplateCrudAdminDeleteSchema,\n docs: {\n adminRead: {\n hidden: true,\n },\n adminCreate: {\n hidden: true,\n },\n adminUpdate: {\n hidden: true,\n },\n adminDelete: {\n hidden: true,\n },\n adminList: {\n hidden: true,\n }\n }\n});\nexport type EmailTemplateCrud = CrudTypeOf<typeof emailTemplateCrud>;\n"],"mappings":";AAAA,SAAqB,kBAAkB;AACvC,SAAS,YAAY,YAAY,UAAU,WAAW,iBAAiB;AAGhE,IAAM,qBAAqB,CAAC,sBAAsB,kBAAkB,cAAc,iBAAiB;AAEnG,IAAM,+BAA+B,UAAU;AAAA,EACpD,MAAM,UAAU,EAAE,MAAM,kBAAkB,EAAE,QAAQ;AAAA,EACpD,SAAS,UAAU,EAAE,QAAQ;AAAA,EAC7B,SAAS,WAAW,QAAQ;AAAA,EAC5B,YAAY,WAAW,EAAE,QAAQ;AACnC,CAAC,EAAE,QAAQ;AAEJ,IAAM,qCAAqC,UAAU;AAAA,EAC1D,SAAS,WAAW,YAAY,EAAE,SAAS;AAAA,EAC3C,SAAS,UAAU,EAAE,SAAS;AAChC,CAAC,EAAE,QAAQ;AAEJ,IAAM,qCAAqC,SAAS;AAEpD,IAAM,qCAAqC,UAAU;AAAA,EAC1D,MAAM,UAAU,EAAE,MAAM,kBAAkB,EAAE,QAAQ;AAAA,EACpD,SAAS,WAAW,QAAQ;AAAA,EAC5B,SAAS,UAAU,EAAE,QAAQ;AAC/B,CAAC,EAAE,QAAQ;AAEJ,IAAM,oBAAoB,WAAW;AAAA,EAC1C,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,mBAAmB;AAAA,EACnB,mBAAmB;AAAA,EACnB,MAAM;AAAA,IACJ,WAAW;AAAA,MACT,QAAQ;AAAA,IACV;AAAA,IACA,aAAa;AAAA,MACX,QAAQ;AAAA,IACV;AAAA,IACA,aAAa;AAAA,MACX,QAAQ;AAAA,IACV;AAAA,IACA,aAAa;AAAA,MACX,QAAQ;AAAA,IACV;AAAA,IACA,WAAW;AAAA,MACT,QAAQ;AAAA,IACV;AAAA,EACF;AACF,CAAC;","names":[]}

View file

@ -0,0 +1,20 @@
// src/interface/crud/emails.ts
import { createCrud } from "../../crud";
import * as fieldSchema from "../../schema-fields";
import { emailConfigWithoutPasswordSchema } from "./projects";
var sentEmailReadSchema = fieldSchema.yupObject({
id: fieldSchema.yupString().defined(),
subject: fieldSchema.yupString().defined(),
sent_at_millis: fieldSchema.yupNumber().defined(),
to: fieldSchema.yupArray(fieldSchema.yupString().defined()),
sender_config: emailConfigWithoutPasswordSchema.defined(),
error: fieldSchema.yupMixed().nullable().optional()
}).defined();
var internalEmailsCrud = createCrud({
adminReadSchema: sentEmailReadSchema
});
export {
internalEmailsCrud,
sentEmailReadSchema
};
//# sourceMappingURL=emails.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/interface/crud/emails.ts"],"sourcesContent":["import { createCrud, CrudTypeOf } from \"../../crud\";\nimport * as fieldSchema from \"../../schema-fields\";\nimport { emailConfigWithoutPasswordSchema } from \"./projects\";\n\n\nexport const sentEmailReadSchema = fieldSchema.yupObject({\n id: fieldSchema.yupString().defined(),\n subject: fieldSchema.yupString().defined(),\n sent_at_millis: fieldSchema.yupNumber().defined(),\n to: fieldSchema.yupArray(fieldSchema.yupString().defined()),\n sender_config: emailConfigWithoutPasswordSchema.defined(),\n error: fieldSchema.yupMixed().nullable().optional(),\n}).defined();\n\nexport const internalEmailsCrud = createCrud({\n adminReadSchema: sentEmailReadSchema,\n});\n\nexport type InternalEmailsCrud = CrudTypeOf<typeof internalEmailsCrud>;\n"],"mappings":";AAAA,SAAS,kBAA8B;AACvC,YAAY,iBAAiB;AAC7B,SAAS,wCAAwC;AAG1C,IAAM,sBAAkC,sBAAU;AAAA,EACvD,IAAgB,sBAAU,EAAE,QAAQ;AAAA,EACpC,SAAqB,sBAAU,EAAE,QAAQ;AAAA,EACzC,gBAA4B,sBAAU,EAAE,QAAQ;AAAA,EAChD,IAAgB,qBAAqB,sBAAU,EAAE,QAAQ,CAAC;AAAA,EAC1D,eAAe,iCAAiC,QAAQ;AAAA,EACxD,OAAmB,qBAAS,EAAE,SAAS,EAAE,SAAS;AACpD,CAAC,EAAE,QAAQ;AAEJ,IAAM,qBAAqB,WAAW;AAAA,EAC3C,iBAAiB;AACnB,CAAC;","names":[]}

View file

@ -0,0 +1,69 @@
// src/interface/crud/internal-api-keys.ts
import { createCrud } from "../../crud";
import { yupBoolean, yupMixed, yupNumber, yupObject, yupString } from "../../schema-fields";
var baseInternalApiKeysReadSchema = yupObject({
id: yupString().defined(),
description: yupString().defined(),
expires_at_millis: yupNumber().defined(),
manually_revoked_at_millis: yupNumber().optional(),
created_at_millis: yupNumber().defined()
});
var internalApiKeysCreateInputSchema = yupObject({
description: yupString().defined(),
expires_at_millis: yupNumber().defined(),
has_publishable_client_key: yupBoolean().defined(),
has_secret_server_key: yupBoolean().defined(),
has_super_secret_admin_key: yupBoolean().defined()
});
var internalApiKeysCreateOutputSchema = baseInternalApiKeysReadSchema.concat(yupObject({
publishable_client_key: yupString().optional(),
secret_server_key: yupString().optional(),
super_secret_admin_key: yupString().optional()
}).defined());
var internalApiKeysCrudAdminObfuscatedReadSchema = baseInternalApiKeysReadSchema.concat(yupObject({
publishable_client_key: yupObject({
last_four: yupString().defined()
}).optional(),
secret_server_key: yupObject({
last_four: yupString().defined()
}).optional(),
super_secret_admin_key: yupObject({
last_four: yupString().defined()
}).optional()
}));
var internalApiKeysCrudAdminUpdateSchema = yupObject({
description: yupString().optional(),
revoked: yupBoolean().oneOf([true]).optional()
}).defined();
var internalApiKeysCrudAdminDeleteSchema = yupMixed();
var internalApiKeysCrud = createCrud({
adminReadSchema: internalApiKeysCrudAdminObfuscatedReadSchema,
adminUpdateSchema: internalApiKeysCrudAdminUpdateSchema,
adminDeleteSchema: internalApiKeysCrudAdminDeleteSchema,
docs: {
adminList: {
hidden: true
},
adminRead: {
hidden: true
},
adminCreate: {
hidden: true
},
adminUpdate: {
hidden: true
},
adminDelete: {
hidden: true
}
}
});
export {
internalApiKeysCreateInputSchema,
internalApiKeysCreateOutputSchema,
internalApiKeysCrud,
internalApiKeysCrudAdminDeleteSchema,
internalApiKeysCrudAdminObfuscatedReadSchema,
internalApiKeysCrudAdminUpdateSchema
};
//# sourceMappingURL=internal-api-keys.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/interface/crud/internal-api-keys.ts"],"sourcesContent":["import { CrudTypeOf, createCrud } from \"../../crud\";\nimport { yupBoolean, yupMixed, yupNumber, yupObject, yupString } from \"../../schema-fields\";\n\nconst baseInternalApiKeysReadSchema = yupObject({\n id: yupString().defined(),\n description: yupString().defined(),\n expires_at_millis: yupNumber().defined(),\n manually_revoked_at_millis: yupNumber().optional(),\n created_at_millis: yupNumber().defined(),\n});\n\n// Used for the result of the create endpoint\nexport const internalApiKeysCreateInputSchema = yupObject({\n description: yupString().defined(),\n expires_at_millis: yupNumber().defined(),\n has_publishable_client_key: yupBoolean().defined(),\n has_secret_server_key: yupBoolean().defined(),\n has_super_secret_admin_key: yupBoolean().defined(),\n});\n\nexport const internalApiKeysCreateOutputSchema = baseInternalApiKeysReadSchema.concat(yupObject({\n publishable_client_key: yupString().optional(),\n secret_server_key: yupString().optional(),\n super_secret_admin_key: yupString().optional(),\n}).defined());\n\n// Used for list, read and update endpoints after the initial creation\nexport const internalApiKeysCrudAdminObfuscatedReadSchema = baseInternalApiKeysReadSchema.concat(yupObject({\n publishable_client_key: yupObject({\n last_four: yupString().defined(),\n }).optional(),\n secret_server_key: yupObject({\n last_four: yupString().defined(),\n }).optional(),\n super_secret_admin_key: yupObject({\n last_four: yupString().defined(),\n }).optional(),\n}));\n\nexport const internalApiKeysCrudAdminUpdateSchema = yupObject({\n description: yupString().optional(),\n revoked: yupBoolean().oneOf([true]).optional(),\n}).defined();\n\nexport const internalApiKeysCrudAdminDeleteSchema = yupMixed();\n\nexport const internalApiKeysCrud = createCrud({\n adminReadSchema: internalApiKeysCrudAdminObfuscatedReadSchema,\n adminUpdateSchema: internalApiKeysCrudAdminUpdateSchema,\n adminDeleteSchema: internalApiKeysCrudAdminDeleteSchema,\n docs: {\n adminList: {\n hidden: true,\n },\n adminRead: {\n hidden: true,\n },\n adminCreate: {\n hidden: true,\n },\n adminUpdate: {\n hidden: true,\n },\n adminDelete: {\n hidden: true,\n },\n },\n});\nexport type InternalApiKeysCrud = CrudTypeOf<typeof internalApiKeysCrud>;\n"],"mappings":";AAAA,SAAqB,kBAAkB;AACvC,SAAS,YAAY,UAAU,WAAW,WAAW,iBAAiB;AAEtE,IAAM,gCAAgC,UAAU;AAAA,EAC9C,IAAI,UAAU,EAAE,QAAQ;AAAA,EACxB,aAAa,UAAU,EAAE,QAAQ;AAAA,EACjC,mBAAmB,UAAU,EAAE,QAAQ;AAAA,EACvC,4BAA4B,UAAU,EAAE,SAAS;AAAA,EACjD,mBAAmB,UAAU,EAAE,QAAQ;AACzC,CAAC;AAGM,IAAM,mCAAmC,UAAU;AAAA,EACxD,aAAa,UAAU,EAAE,QAAQ;AAAA,EACjC,mBAAmB,UAAU,EAAE,QAAQ;AAAA,EACvC,4BAA4B,WAAW,EAAE,QAAQ;AAAA,EACjD,uBAAuB,WAAW,EAAE,QAAQ;AAAA,EAC5C,4BAA4B,WAAW,EAAE,QAAQ;AACnD,CAAC;AAEM,IAAM,oCAAoC,8BAA8B,OAAO,UAAU;AAAA,EAC9F,wBAAwB,UAAU,EAAE,SAAS;AAAA,EAC7C,mBAAmB,UAAU,EAAE,SAAS;AAAA,EACxC,wBAAwB,UAAU,EAAE,SAAS;AAC/C,CAAC,EAAE,QAAQ,CAAC;AAGL,IAAM,+CAA+C,8BAA8B,OAAO,UAAU;AAAA,EACzG,wBAAwB,UAAU;AAAA,IAChC,WAAW,UAAU,EAAE,QAAQ;AAAA,EACjC,CAAC,EAAE,SAAS;AAAA,EACZ,mBAAmB,UAAU;AAAA,IAC3B,WAAW,UAAU,EAAE,QAAQ;AAAA,EACjC,CAAC,EAAE,SAAS;AAAA,EACZ,wBAAwB,UAAU;AAAA,IAChC,WAAW,UAAU,EAAE,QAAQ;AAAA,EACjC,CAAC,EAAE,SAAS;AACd,CAAC,CAAC;AAEK,IAAM,uCAAuC,UAAU;AAAA,EAC5D,aAAa,UAAU,EAAE,SAAS;AAAA,EAClC,SAAS,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,SAAS;AAC/C,CAAC,EAAE,QAAQ;AAEJ,IAAM,uCAAuC,SAAS;AAEtD,IAAM,sBAAsB,WAAW;AAAA,EAC5C,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,mBAAmB;AAAA,EACnB,MAAM;AAAA,IACJ,WAAW;AAAA,MACT,QAAQ;AAAA,IACV;AAAA,IACA,WAAW;AAAA,MACT,QAAQ;AAAA,IACV;AAAA,IACA,aAAa;AAAA,MACX,QAAQ;AAAA,IACV;AAAA,IACA,aAAa;AAAA,MACX,QAAQ;AAAA,IACV;AAAA,IACA,aAAa;AAAA,MACX,QAAQ;AAAA,IACV;AAAA,EACF;AACF,CAAC;","names":[]}

View file

@ -0,0 +1,24 @@
// src/interface/crud/oauth.ts
import { createCrud } from "../../crud";
import { yupObject, yupString } from "../../schema-fields";
var connectedAccountAccessTokenReadSchema = yupObject({
access_token: yupString().defined()
}).defined();
var connectedAccountAccessTokenCreateSchema = yupObject({
scope: yupString().optional()
}).defined();
var connectedAccountAccessTokenCrud = createCrud({
clientReadSchema: connectedAccountAccessTokenReadSchema,
clientCreateSchema: connectedAccountAccessTokenCreateSchema,
docs: {
clientCreate: {
hidden: true
}
}
});
export {
connectedAccountAccessTokenCreateSchema,
connectedAccountAccessTokenCrud,
connectedAccountAccessTokenReadSchema
};
//# sourceMappingURL=oauth.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/interface/crud/oauth.ts"],"sourcesContent":["import { CrudTypeOf, createCrud } from \"../../crud\";\nimport { yupObject, yupString } from \"../../schema-fields\";\n\nexport const connectedAccountAccessTokenReadSchema = yupObject({\n access_token: yupString().defined(),\n}).defined();\n\nexport const connectedAccountAccessTokenCreateSchema = yupObject({\n scope: yupString().optional(),\n}).defined();\n\nexport const connectedAccountAccessTokenCrud = createCrud({\n clientReadSchema: connectedAccountAccessTokenReadSchema,\n clientCreateSchema: connectedAccountAccessTokenCreateSchema,\n docs: {\n clientCreate: {\n hidden: true,\n }\n },\n});\nexport type ConnectedAccountAccessTokenCrud = CrudTypeOf<typeof connectedAccountAccessTokenCrud>;\n"],"mappings":";AAAA,SAAqB,kBAAkB;AACvC,SAAS,WAAW,iBAAiB;AAE9B,IAAM,wCAAwC,UAAU;AAAA,EAC7D,cAAc,UAAU,EAAE,QAAQ;AACpC,CAAC,EAAE,QAAQ;AAEJ,IAAM,0CAA0C,UAAU;AAAA,EAC/D,OAAO,UAAU,EAAE,SAAS;AAC9B,CAAC,EAAE,QAAQ;AAEJ,IAAM,kCAAkC,WAAW;AAAA,EACxD,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,MAAM;AAAA,IACJ,cAAc;AAAA,MACZ,QAAQ;AAAA,IACV;AAAA,EACF;AACF,CAAC;","names":[]}

View file

@ -0,0 +1,98 @@
// src/interface/crud/project-api-keys.ts
import { createCrud } from "../../crud";
import { userIdOrMeSchema, yupBoolean, yupNumber, yupObject, yupString } from "../../schema-fields";
import { typedFromEntries } from "../../utils/objects";
function createApiKeyCrud(type, idFieldName, idSchema) {
const projectApiKeysReadSchema = yupObject({
id: yupString().defined(),
description: yupString().defined(),
expires_at_millis: yupNumber().optional(),
manually_revoked_at_millis: yupNumber().optional(),
created_at_millis: yupNumber().defined(),
is_public: yupBoolean().defined(),
value: yupObject({
last_four: yupString().defined()
}).defined(),
type: yupString().oneOf([type]).defined(),
...typedFromEntries([[idFieldName, idSchema]])
});
const projectApiKeysUpdateSchema = yupObject({
description: yupString().optional(),
revoked: yupBoolean().oneOf([true]).optional()
}).defined();
const projectApiKeysCrud = createCrud({
clientReadSchema: projectApiKeysReadSchema,
clientUpdateSchema: projectApiKeysUpdateSchema,
docs: {
clientCreate: {
description: `Create a new ${type} API key`,
displayName: `Create ${type} API key`,
tags: ["API Keys"],
summary: `Create ${type} API key`
},
clientList: {
description: `List all ${type} API keys for the project with their metadata and status`,
displayName: `List ${type} API keys`,
summary: `List ${type} API keys`,
tags: ["API Keys"]
},
clientRead: {
description: `Get details of a specific ${type} API key`,
displayName: `Get ${type} API key`,
summary: `Get ${type} API key details`,
tags: ["API Keys"]
},
clientUpdate: {
description: `Update an ${type} API key`,
displayName: `Update ${type} API key`,
summary: `Update ${type} API key`,
tags: ["API Keys"]
},
serverDelete: {
description: `Delete an ${type} API key`,
displayName: `Delete ${type} API key`,
summary: `Delete ${type} API key`,
tags: ["API Keys"]
}
}
});
const projectApiKeysCreateInputSchema = yupObject({
description: yupString().defined(),
expires_at_millis: yupNumber().nullable().defined(),
is_public: yupBoolean().optional(),
/*
prefix: yupString().optional().nonEmpty().test("prefix", "Prefix must contain only alphanumeric characters and underscores", (value) => {
if (!value) return true;
return /^[a-zA-Z0-9_]+$/.test(value);
}),
*/
...typedFromEntries([[idFieldName, idSchema]])
});
const projectApiKeysCreateOutputSchema = projectApiKeysReadSchema.omit(["value"]).concat(yupObject({
value: yupString().defined()
}));
return {
crud: projectApiKeysCrud,
createInputSchema: projectApiKeysCreateInputSchema,
createOutputSchema: projectApiKeysCreateOutputSchema
};
}
var {
crud: userApiKeysCrud,
createInputSchema: userApiKeysCreateInputSchema,
createOutputSchema: userApiKeysCreateOutputSchema
} = createApiKeyCrud("user", "user_id", userIdOrMeSchema.defined());
var {
crud: teamApiKeysCrud,
createInputSchema: teamApiKeysCreateInputSchema,
createOutputSchema: teamApiKeysCreateOutputSchema
} = createApiKeyCrud("team", "team_id", yupString().defined());
export {
teamApiKeysCreateInputSchema,
teamApiKeysCreateOutputSchema,
teamApiKeysCrud,
userApiKeysCreateInputSchema,
userApiKeysCreateOutputSchema,
userApiKeysCrud
};
//# sourceMappingURL=project-api-keys.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,113 @@
// src/interface/crud/project-permissions.ts
import { createCrud } from "../../crud";
import * as schemaFields from "../../schema-fields";
import { yupMixed, yupObject } from "../../schema-fields";
var projectPermissionsCrudClientReadSchema = yupObject({
id: schemaFields.permissionDefinitionIdSchema.defined(),
user_id: schemaFields.userIdSchema.defined()
}).defined();
var projectPermissionsCrudServerCreateSchema = yupObject({}).defined();
var projectPermissionsCrudServerDeleteSchema = yupMixed();
var projectPermissionsCrud = createCrud({
clientReadSchema: projectPermissionsCrudClientReadSchema,
serverCreateSchema: projectPermissionsCrudServerCreateSchema,
serverDeleteSchema: projectPermissionsCrudServerDeleteSchema,
docs: {
clientList: {
summary: "List project permissions",
description: "List global permissions of the current user. `user_id=me` must be set for client requests. `(user_id, permission_id)` together uniquely identify a permission.",
tags: ["Permissions"]
},
serverList: {
summary: "List project permissions",
description: "Query and filter the permission with `user_id` and `permission_id`. `(user_id, permission_id)` together uniquely identify a permission.",
tags: ["Permissions"]
},
serverCreate: {
summary: "Grant a global permission to a user",
description: "Grant a global permission to a user (the permission must be created first on the Stack dashboard)",
tags: ["Permissions"]
},
serverDelete: {
summary: "Revoke a global permission from a user",
description: "Revoke a global permission from a user",
tags: ["Permissions"]
}
}
});
var projectPermissionCreatedWebhookEvent = {
type: "project_permission.created",
schema: projectPermissionsCrud.server.readSchema,
metadata: {
summary: "Project Permission Created",
description: "This event is triggered when a project permission is created.",
tags: ["Users"]
}
};
var projectPermissionDeletedWebhookEvent = {
type: "project_permission.deleted",
schema: projectPermissionsCrud.server.readSchema,
metadata: {
summary: "Project Permission Deleted",
description: "This event is triggered when a project permission is deleted.",
tags: ["Users"]
}
};
var projectPermissionDefinitionsCrudAdminReadSchema = yupObject({
id: schemaFields.permissionDefinitionIdSchema.defined(),
description: schemaFields.teamPermissionDescriptionSchema.optional(),
contained_permission_ids: schemaFields.containedPermissionIdsSchema.defined()
}).defined();
var projectPermissionDefinitionsCrudAdminCreateSchema = yupObject({
id: schemaFields.customPermissionDefinitionIdSchema.defined(),
description: schemaFields.teamPermissionDescriptionSchema.optional(),
contained_permission_ids: schemaFields.containedPermissionIdsSchema.optional()
}).defined();
var projectPermissionDefinitionsCrudAdminUpdateSchema = yupObject({
id: schemaFields.customPermissionDefinitionIdSchema.optional(),
description: schemaFields.teamPermissionDescriptionSchema.optional(),
contained_permission_ids: schemaFields.containedPermissionIdsSchema.optional()
}).defined();
var projectPermissionDefinitionsCrudAdminDeleteSchema = yupMixed();
var projectPermissionDefinitionsCrud = createCrud({
adminReadSchema: projectPermissionDefinitionsCrudAdminReadSchema,
adminCreateSchema: projectPermissionDefinitionsCrudAdminCreateSchema,
adminUpdateSchema: projectPermissionDefinitionsCrudAdminUpdateSchema,
adminDeleteSchema: projectPermissionDefinitionsCrudAdminDeleteSchema,
docs: {
adminList: {
summary: "List project permission definitions",
description: "Query and filter project permission definitions (the equivalent of listing permissions on the Stack dashboard)",
tags: ["Permissions"]
},
adminCreate: {
summary: "Create a new project permission definition",
description: "Create a new project permission definition (the equivalent of creating a new permission on the Stack dashboard)",
tags: ["Permissions"]
},
adminUpdate: {
summary: "Update a project permission definition",
description: "Update a project permission definition (the equivalent of updating a permission on the Stack dashboard)",
tags: ["Permissions"]
},
adminDelete: {
summary: "Delete a project permission definition",
description: "Delete a project permission definition (the equivalent of deleting a permission on the Stack dashboard)",
tags: ["Permissions"]
}
}
});
export {
projectPermissionCreatedWebhookEvent,
projectPermissionDefinitionsCrud,
projectPermissionDefinitionsCrudAdminCreateSchema,
projectPermissionDefinitionsCrudAdminDeleteSchema,
projectPermissionDefinitionsCrudAdminReadSchema,
projectPermissionDefinitionsCrudAdminUpdateSchema,
projectPermissionDeletedWebhookEvent,
projectPermissionsCrud,
projectPermissionsCrudClientReadSchema,
projectPermissionsCrudServerCreateSchema,
projectPermissionsCrudServerDeleteSchema
};
//# sourceMappingURL=project-permissions.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,181 @@
// src/interface/crud/projects.ts
import { createCrud } from "../../crud";
import * as schemaFields from "../../schema-fields";
import { yupArray, yupObject, yupString } from "../../schema-fields";
var teamPermissionSchema = yupObject({
id: yupString().defined()
}).defined();
var oauthProviderSchema = yupObject({
id: schemaFields.oauthIdSchema.defined(),
type: schemaFields.oauthTypeSchema.defined(),
client_id: schemaFields.yupDefinedAndNonEmptyWhen(
schemaFields.oauthClientIdSchema,
{ type: "standard" }
),
client_secret: schemaFields.yupDefinedAndNonEmptyWhen(
schemaFields.oauthClientSecretSchema,
{ type: "standard" }
),
// extra params
facebook_config_id: schemaFields.oauthFacebookConfigIdSchema.optional(),
microsoft_tenant_id: schemaFields.oauthMicrosoftTenantIdSchema.optional()
});
var enabledOAuthProviderSchema = yupObject({
id: schemaFields.oauthIdSchema.defined()
});
var emailConfigSchema = yupObject({
type: schemaFields.emailTypeSchema.defined(),
host: schemaFields.yupDefinedAndNonEmptyWhen(schemaFields.emailHostSchema, {
type: "standard"
}),
port: schemaFields.yupDefinedWhen(schemaFields.emailPortSchema, {
type: "standard"
}),
username: schemaFields.yupDefinedAndNonEmptyWhen(schemaFields.emailUsernameSchema, {
type: "standard"
}),
password: schemaFields.yupDefinedAndNonEmptyWhen(schemaFields.emailPasswordSchema, {
type: "standard"
}),
sender_name: schemaFields.yupDefinedAndNonEmptyWhen(schemaFields.emailSenderNameSchema, {
type: "standard"
}),
sender_email: schemaFields.yupDefinedAndNonEmptyWhen(schemaFields.emailSenderEmailSchema, {
type: "standard"
})
});
var emailConfigWithoutPasswordSchema = emailConfigSchema.pick(["type", "host", "port", "username", "sender_name", "sender_email"]);
var domainSchema = yupObject({
domain: schemaFields.urlSchema.defined().matches(/^https?:\/\//, "URL must start with http:// or https://").meta({ openapiField: { description: "URL. Must start with http:// or https://", exampleValue: "https://example.com" } }),
handler_path: schemaFields.handlerPathSchema.defined()
});
var projectsCrudAdminReadSchema = yupObject({
id: schemaFields.projectIdSchema.defined(),
display_name: schemaFields.projectDisplayNameSchema.defined(),
description: schemaFields.projectDescriptionSchema.nonNullable().defined(),
created_at_millis: schemaFields.projectCreatedAtMillisSchema.defined(),
user_count: schemaFields.projectUserCountSchema.defined(),
is_production_mode: schemaFields.projectIsProductionModeSchema.defined(),
/** @deprecated */
config: yupObject({
allow_localhost: schemaFields.projectAllowLocalhostSchema.defined(),
sign_up_enabled: schemaFields.projectSignUpEnabledSchema.defined(),
credential_enabled: schemaFields.projectCredentialEnabledSchema.defined(),
magic_link_enabled: schemaFields.projectMagicLinkEnabledSchema.defined(),
passkey_enabled: schemaFields.projectPasskeyEnabledSchema.defined(),
// TODO: remove this
client_team_creation_enabled: schemaFields.projectClientTeamCreationEnabledSchema.defined(),
client_user_deletion_enabled: schemaFields.projectClientUserDeletionEnabledSchema.defined(),
allow_user_api_keys: schemaFields.yupBoolean().defined(),
allow_team_api_keys: schemaFields.yupBoolean().defined(),
oauth_providers: yupArray(oauthProviderSchema.defined()).defined(),
enabled_oauth_providers: yupArray(enabledOAuthProviderSchema.defined()).defined().meta({ openapiField: { hidden: true } }),
domains: yupArray(domainSchema.defined()).defined(),
email_config: emailConfigSchema.defined(),
create_team_on_sign_up: schemaFields.projectCreateTeamOnSignUpSchema.defined(),
team_creator_default_permissions: yupArray(teamPermissionSchema.defined()).defined(),
team_member_default_permissions: yupArray(teamPermissionSchema.defined()).defined(),
user_default_permissions: yupArray(teamPermissionSchema.defined()).defined(),
oauth_account_merge_strategy: schemaFields.oauthAccountMergeStrategySchema.defined()
}).defined().meta({ openapiField: { hidden: true } })
}).defined();
var projectsCrudClientReadSchema = yupObject({
id: schemaFields.projectIdSchema.defined(),
display_name: schemaFields.projectDisplayNameSchema.defined(),
config: yupObject({
sign_up_enabled: schemaFields.projectSignUpEnabledSchema.defined(),
credential_enabled: schemaFields.projectCredentialEnabledSchema.defined(),
magic_link_enabled: schemaFields.projectMagicLinkEnabledSchema.defined(),
passkey_enabled: schemaFields.projectPasskeyEnabledSchema.defined(),
client_team_creation_enabled: schemaFields.projectClientTeamCreationEnabledSchema.defined(),
client_user_deletion_enabled: schemaFields.projectClientUserDeletionEnabledSchema.defined(),
allow_user_api_keys: schemaFields.yupBoolean().defined(),
allow_team_api_keys: schemaFields.yupBoolean().defined(),
enabled_oauth_providers: yupArray(enabledOAuthProviderSchema.defined()).defined().meta({ openapiField: { hidden: true } })
}).defined().meta({ openapiField: { hidden: true } })
}).defined();
var projectsCrudAdminUpdateSchema = yupObject({
display_name: schemaFields.projectDisplayNameSchema.optional(),
description: schemaFields.projectDescriptionSchema.optional(),
is_production_mode: schemaFields.projectIsProductionModeSchema.optional(),
config: yupObject({
sign_up_enabled: schemaFields.projectSignUpEnabledSchema.optional(),
credential_enabled: schemaFields.projectCredentialEnabledSchema.optional(),
magic_link_enabled: schemaFields.projectMagicLinkEnabledSchema.optional(),
passkey_enabled: schemaFields.projectPasskeyEnabledSchema.optional(),
client_team_creation_enabled: schemaFields.projectClientTeamCreationEnabledSchema.optional(),
client_user_deletion_enabled: schemaFields.projectClientUserDeletionEnabledSchema.optional(),
allow_localhost: schemaFields.projectAllowLocalhostSchema.optional(),
allow_user_api_keys: schemaFields.yupBoolean().optional(),
allow_team_api_keys: schemaFields.yupBoolean().optional(),
email_config: emailConfigSchema.optional().default(void 0),
domains: yupArray(domainSchema.defined()).optional().default(void 0),
oauth_providers: yupArray(oauthProviderSchema.defined()).optional().default(void 0),
create_team_on_sign_up: schemaFields.projectCreateTeamOnSignUpSchema.optional(),
team_creator_default_permissions: yupArray(teamPermissionSchema.defined()).optional(),
team_member_default_permissions: yupArray(teamPermissionSchema.defined()).optional(),
user_default_permissions: yupArray(teamPermissionSchema.defined()).optional(),
oauth_account_merge_strategy: schemaFields.oauthAccountMergeStrategySchema.optional()
}).optional().default(void 0)
}).defined();
var projectsCrudAdminCreateSchema = projectsCrudAdminUpdateSchema.concat(yupObject({
display_name: schemaFields.projectDisplayNameSchema.defined()
}).defined());
var projectsCrudAdminDeleteSchema = schemaFields.yupMixed();
var clientProjectsCrud = createCrud({
clientReadSchema: projectsCrudClientReadSchema,
docs: {
clientRead: {
summary: "Get the current project",
description: "Get the current project information including display name, OAuth providers and authentication methods. Useful for display the available login options to the user.",
tags: ["Projects"]
}
}
});
var projectsCrud = createCrud({
adminReadSchema: projectsCrudAdminReadSchema,
adminUpdateSchema: projectsCrudAdminUpdateSchema,
adminDeleteSchema: projectsCrudAdminDeleteSchema,
docs: {
adminRead: {
summary: "Get the current project",
description: "Get the current project information and configuration including display name, OAuth providers, email configuration, etc.",
tags: ["Projects"]
},
adminUpdate: {
summary: "Update the current project",
description: "Update the current project information and configuration including display name, OAuth providers, email configuration, etc.",
tags: ["Projects"]
},
adminDelete: {
summary: "Delete the current project",
description: "Delete the current project and all associated data (including users, teams, API keys, project configs, etc.). Be careful, this action is irreversible.",
tags: ["Projects"]
}
}
});
var adminUserProjectsCrud = createCrud({
clientReadSchema: projectsCrudAdminReadSchema,
clientCreateSchema: projectsCrudAdminCreateSchema,
docs: {
clientList: {
hidden: true
},
clientCreate: {
hidden: true
}
}
});
export {
adminUserProjectsCrud,
clientProjectsCrud,
emailConfigSchema,
emailConfigWithoutPasswordSchema,
projectsCrud,
projectsCrudAdminCreateSchema,
projectsCrudAdminDeleteSchema,
projectsCrudAdminReadSchema,
projectsCrudAdminUpdateSchema,
projectsCrudClientReadSchema
};
//# sourceMappingURL=projects.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,62 @@
// src/interface/crud/sessions.ts
import { createCrud } from "../../crud";
import { yupBoolean, yupMixed, yupNumber, yupObject, yupString } from "../../schema-fields";
import { geoInfoSchema } from "../../utils/geo";
var sessionsCrudServerCreateSchema = yupObject({
user_id: yupString().uuid().defined(),
expires_in_millis: yupNumber().max(1e3 * 60 * 60 * 24 * 367).default(1e3 * 60 * 60 * 24 * 365),
is_impersonation: yupBoolean().default(false)
}).defined();
var sessionsCreateOutputSchema = yupObject({
refresh_token: yupString().defined(),
access_token: yupString().defined()
}).defined();
var sessionsCrudReadSchema = yupObject({
id: yupString().defined(),
user_id: yupString().uuid().defined(),
created_at: yupNumber().defined(),
is_impersonation: yupBoolean().defined(),
last_used_at: yupNumber().optional(),
is_current_session: yupBoolean(),
// TODO move this to a shared type
// TODO: what about if not trusted?
last_used_at_end_user_ip_info: geoInfoSchema.optional()
}).defined();
var sessionsCrudDeleteSchema = yupMixed();
var sessionsCrud = createCrud({
// serverCreateSchema: sessionsCrudServerCreateSchema,
serverReadSchema: sessionsCrudReadSchema,
serverDeleteSchema: sessionsCrudDeleteSchema,
clientReadSchema: sessionsCrudReadSchema,
clientDeleteSchema: sessionsCrudDeleteSchema,
docs: {
serverList: {
summary: "List sessions",
description: "List all sessions for the current user.",
tags: ["Sessions"]
},
serverDelete: {
summary: "Delete session",
description: "Delete a session by ID.",
tags: ["Sessions"]
},
clientList: {
summary: "List sessions",
description: "List all sessions for the current user.",
tags: ["Sessions"]
},
clientDelete: {
summary: "Delete session",
description: "Delete a session by ID.",
tags: ["Sessions"]
}
}
});
export {
sessionsCreateOutputSchema,
sessionsCrud,
sessionsCrudDeleteSchema,
sessionsCrudReadSchema,
sessionsCrudServerCreateSchema
};
//# sourceMappingURL=sessions.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/interface/crud/sessions.ts"],"sourcesContent":["import { CrudTypeOf, createCrud } from \"../../crud\";\nimport { yupBoolean, yupMixed, yupNumber, yupObject, yupString } from \"../../schema-fields\";\nimport { geoInfoSchema } from \"../../utils/geo\";\n\n\n// Create\nexport const sessionsCrudServerCreateSchema = yupObject({\n user_id: yupString().uuid().defined(),\n expires_in_millis: yupNumber().max(1000 * 60 * 60 * 24 * 367).default(1000 * 60 * 60 * 24 * 365),\n is_impersonation: yupBoolean().default(false),\n}).defined();\n\n\nexport const sessionsCreateOutputSchema = yupObject({\n refresh_token: yupString().defined(),\n access_token: yupString().defined(),\n}).defined();\n\n\nexport const sessionsCrudReadSchema = yupObject({\n id: yupString().defined(),\n user_id: yupString().uuid().defined(),\n created_at: yupNumber().defined(),\n is_impersonation: yupBoolean().defined(),\n last_used_at: yupNumber().optional(),\n is_current_session: yupBoolean(),\n // TODO move this to a shared type\n // TODO: what about if not trusted?\n last_used_at_end_user_ip_info: geoInfoSchema.optional(),\n}).defined();\n\n\n// Delete\nexport const sessionsCrudDeleteSchema = yupMixed();\n\n\nexport const sessionsCrud = createCrud({\n // serverCreateSchema: sessionsCrudServerCreateSchema,\n serverReadSchema: sessionsCrudReadSchema,\n serverDeleteSchema: sessionsCrudDeleteSchema,\n clientReadSchema: sessionsCrudReadSchema,\n clientDeleteSchema: sessionsCrudDeleteSchema,\n docs: {\n serverList: {\n summary: \"List sessions\",\n description: \"List all sessions for the current user.\",\n tags: [\"Sessions\"],\n },\n serverDelete: {\n summary: \"Delete session\",\n description: \"Delete a session by ID.\",\n tags: [\"Sessions\"],\n },\n clientList: {\n summary: \"List sessions\",\n description: \"List all sessions for the current user.\",\n tags: [\"Sessions\"],\n },\n clientDelete: {\n summary: \"Delete session\",\n description: \"Delete a session by ID.\",\n tags: [\"Sessions\"],\n },\n },\n});\nexport type SessionsCrud = CrudTypeOf<typeof sessionsCrud>;\n"],"mappings":";AAAA,SAAqB,kBAAkB;AACvC,SAAS,YAAY,UAAU,WAAW,WAAW,iBAAiB;AACtE,SAAS,qBAAqB;AAIvB,IAAM,iCAAiC,UAAU;AAAA,EACtD,SAAS,UAAU,EAAE,KAAK,EAAE,QAAQ;AAAA,EACpC,mBAAmB,UAAU,EAAE,IAAI,MAAO,KAAK,KAAK,KAAK,GAAG,EAAE,QAAQ,MAAO,KAAK,KAAK,KAAK,GAAG;AAAA,EAC/F,kBAAkB,WAAW,EAAE,QAAQ,KAAK;AAC9C,CAAC,EAAE,QAAQ;AAGJ,IAAM,6BAA6B,UAAU;AAAA,EAClD,eAAe,UAAU,EAAE,QAAQ;AAAA,EACnC,cAAc,UAAU,EAAE,QAAQ;AACpC,CAAC,EAAE,QAAQ;AAGJ,IAAM,yBAAyB,UAAU;AAAA,EAC9C,IAAI,UAAU,EAAE,QAAQ;AAAA,EACxB,SAAS,UAAU,EAAE,KAAK,EAAE,QAAQ;AAAA,EACpC,YAAY,UAAU,EAAE,QAAQ;AAAA,EAChC,kBAAkB,WAAW,EAAE,QAAQ;AAAA,EACvC,cAAc,UAAU,EAAE,SAAS;AAAA,EACnC,oBAAoB,WAAW;AAAA;AAAA;AAAA,EAG/B,+BAA+B,cAAc,SAAS;AACxD,CAAC,EAAE,QAAQ;AAIJ,IAAM,2BAA2B,SAAS;AAG1C,IAAM,eAAe,WAAW;AAAA;AAAA,EAErC,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,MAAM;AAAA,IACJ,YAAY;AAAA,MACV,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM,CAAC,UAAU;AAAA,IACnB;AAAA,IACA,cAAc;AAAA,MACZ,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM,CAAC,UAAU;AAAA,IACnB;AAAA,IACA,YAAY;AAAA,MACV,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM,CAAC,UAAU;AAAA,IACnB;AAAA,IACA,cAAc;AAAA,MACZ,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM,CAAC,UAAU;AAAA,IACnB;AAAA,EACF;AACF,CAAC;","names":[]}

View file

@ -0,0 +1,22 @@
// src/interface/crud/svix-token.ts
import { createCrud } from "../../crud";
import { yupObject, yupString } from "../../schema-fields";
var svixTokenAdminReadSchema = yupObject({
token: yupString().defined()
}).defined();
var svixTokenAdminCreateSchema = yupObject({}).defined();
var svixTokenCrud = createCrud({
adminReadSchema: svixTokenAdminReadSchema,
adminCreateSchema: svixTokenAdminCreateSchema,
docs: {
adminCreate: {
hidden: true
}
}
});
export {
svixTokenAdminCreateSchema,
svixTokenAdminReadSchema,
svixTokenCrud
};
//# sourceMappingURL=svix-token.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/interface/crud/svix-token.ts"],"sourcesContent":["import { CrudTypeOf, createCrud } from \"../../crud\";\nimport { yupObject, yupString } from \"../../schema-fields\";\n\nexport const svixTokenAdminReadSchema = yupObject({\n token: yupString().defined(),\n}).defined();\n\nexport const svixTokenAdminCreateSchema = yupObject({}).defined();\n\nexport const svixTokenCrud = createCrud({\n adminReadSchema: svixTokenAdminReadSchema,\n adminCreateSchema: svixTokenAdminCreateSchema,\n docs: {\n adminCreate: {\n hidden: true,\n },\n }\n});\nexport type SvixTokenCrud = CrudTypeOf<typeof svixTokenCrud>;\n"],"mappings":";AAAA,SAAqB,kBAAkB;AACvC,SAAS,WAAW,iBAAiB;AAE9B,IAAM,2BAA2B,UAAU;AAAA,EAChD,OAAO,UAAU,EAAE,QAAQ;AAC7B,CAAC,EAAE,QAAQ;AAEJ,IAAM,6BAA6B,UAAU,CAAC,CAAC,EAAE,QAAQ;AAEzD,IAAM,gBAAgB,WAAW;AAAA,EACtC,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,MAAM;AAAA,IACJ,aAAa;AAAA,MACX,QAAQ;AAAA,IACV;AAAA,EACF;AACF,CAAC;","names":[]}

View file

@ -0,0 +1,23 @@
// src/interface/crud/team-invitation-details.ts
import { createCrud } from "../../crud";
import * as schemaFields from "../../schema-fields";
import { yupObject } from "../../schema-fields";
var teamInvitationDetailsClientReadSchema = yupObject({
team_id: schemaFields.teamIdSchema.defined(),
team_display_name: schemaFields.teamDisplayNameSchema.defined()
}).defined();
var teamInvitationDetailsCrud = createCrud({
clientReadSchema: teamInvitationDetailsClientReadSchema,
docs: {
clientRead: {
summary: "Get the team details with invitation code",
description: "",
tags: ["Teams"]
}
}
});
export {
teamInvitationDetailsClientReadSchema,
teamInvitationDetailsCrud
};
//# sourceMappingURL=team-invitation-details.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/interface/crud/team-invitation-details.ts"],"sourcesContent":["import { CrudTypeOf, createCrud } from \"../../crud\";\nimport * as schemaFields from \"../../schema-fields\";\nimport { yupObject } from \"../../schema-fields\";\n\n\nexport const teamInvitationDetailsClientReadSchema = yupObject({\n team_id: schemaFields.teamIdSchema.defined(),\n team_display_name: schemaFields.teamDisplayNameSchema.defined(),\n}).defined();\n\nexport const teamInvitationDetailsCrud = createCrud({\n clientReadSchema: teamInvitationDetailsClientReadSchema,\n docs: {\n clientRead: {\n summary: \"Get the team details with invitation code\",\n description: \"\",\n tags: [\"Teams\"],\n },\n },\n});\n\nexport type TeamInvitationDetailsCrud = CrudTypeOf<typeof teamInvitationDetailsCrud>;\n"],"mappings":";AAAA,SAAqB,kBAAkB;AACvC,YAAY,kBAAkB;AAC9B,SAAS,iBAAiB;AAGnB,IAAM,wCAAwC,UAAU;AAAA,EAC7D,SAAsB,0BAAa,QAAQ;AAAA,EAC3C,mBAAgC,mCAAsB,QAAQ;AAChE,CAAC,EAAE,QAAQ;AAEJ,IAAM,4BAA4B,WAAW;AAAA,EAClD,kBAAkB;AAAA,EAClB,MAAM;AAAA,IACJ,YAAY;AAAA,MACV,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM,CAAC,OAAO;AAAA,IAChB;AAAA,EACF;AACF,CAAC;","names":[]}

View file

@ -0,0 +1,36 @@
// src/interface/crud/team-invitation.ts
import { createCrud } from "../../crud";
import * as schemaFields from "../../schema-fields";
import { yupObject } from "../../schema-fields";
var teamInvitationDetailsClientReadSchema = yupObject({
id: schemaFields.yupString().uuid().defined(),
team_id: schemaFields.teamIdSchema.defined(),
expires_at_millis: schemaFields.yupNumber().defined(),
recipient_email: schemaFields.emailSchema.defined()
}).defined();
var teamInvitationCrud = createCrud({
clientReadSchema: teamInvitationDetailsClientReadSchema,
clientDeleteSchema: schemaFields.yupMixed(),
docs: {
clientRead: {
summary: "Get the team details with invitation code",
description: "",
tags: ["Teams"]
},
clientList: {
summary: "List team invitations",
description: "",
tags: ["Teams"]
},
clientDelete: {
summary: "Delete a team invitation",
description: "",
tags: ["Teams"]
}
}
});
export {
teamInvitationCrud,
teamInvitationDetailsClientReadSchema
};
//# sourceMappingURL=team-invitation.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/interface/crud/team-invitation.ts"],"sourcesContent":["import { CrudTypeOf, createCrud } from \"../../crud\";\nimport * as schemaFields from \"../../schema-fields\";\nimport { yupObject } from \"../../schema-fields\";\n\nexport const teamInvitationDetailsClientReadSchema = yupObject({\n id: schemaFields.yupString().uuid().defined(),\n team_id: schemaFields.teamIdSchema.defined(),\n expires_at_millis: schemaFields.yupNumber().defined(),\n recipient_email: schemaFields.emailSchema.defined(),\n}).defined();\n\nexport const teamInvitationCrud = createCrud({\n clientReadSchema: teamInvitationDetailsClientReadSchema,\n clientDeleteSchema: schemaFields.yupMixed(),\n docs: {\n clientRead: {\n summary: \"Get the team details with invitation code\",\n description: \"\",\n tags: [\"Teams\"],\n },\n clientList: {\n summary: \"List team invitations\",\n description: \"\",\n tags: [\"Teams\"],\n },\n clientDelete: {\n summary: \"Delete a team invitation\",\n description: \"\",\n tags: [\"Teams\"],\n },\n },\n});\n\nexport type TeamInvitationCrud = CrudTypeOf<typeof teamInvitationCrud>;\n"],"mappings":";AAAA,SAAqB,kBAAkB;AACvC,YAAY,kBAAkB;AAC9B,SAAS,iBAAiB;AAEnB,IAAM,wCAAwC,UAAU;AAAA,EAC7D,IAAiB,uBAAU,EAAE,KAAK,EAAE,QAAQ;AAAA,EAC5C,SAAsB,0BAAa,QAAQ;AAAA,EAC3C,mBAAgC,uBAAU,EAAE,QAAQ;AAAA,EACpD,iBAA8B,yBAAY,QAAQ;AACpD,CAAC,EAAE,QAAQ;AAEJ,IAAM,qBAAqB,WAAW;AAAA,EAC3C,kBAAkB;AAAA,EAClB,oBAAiC,sBAAS;AAAA,EAC1C,MAAM;AAAA,IACJ,YAAY;AAAA,MACV,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM,CAAC,OAAO;AAAA,IAChB;AAAA,IACA,YAAY;AAAA,MACV,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM,CAAC,OAAO;AAAA,IAChB;AAAA,IACA,cAAc;AAAA,MACZ,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM,CAAC,OAAO;AAAA,IAChB;AAAA,EACF;AACF,CAAC;","names":[]}

View file

@ -0,0 +1,62 @@
// src/interface/crud/team-member-profiles.ts
import { createCrud } from "../../crud";
import * as schemaFields from "../../schema-fields";
import { yupObject } from "../../schema-fields";
import { usersCrudServerReadSchema } from "./users";
var teamMemberProfilesCrudClientReadSchema = yupObject({
team_id: schemaFields.teamIdSchema.defined(),
user_id: schemaFields.userIdSchema.defined(),
display_name: schemaFields.teamMemberDisplayNameSchema.nullable().defined(),
profile_image_url: schemaFields.teamMemberProfileImageUrlSchema.nullable().defined()
}).defined();
var teamMemberProfilesCrudServerReadSchema = teamMemberProfilesCrudClientReadSchema.concat(yupObject({
user: usersCrudServerReadSchema.defined()
})).defined();
var teamMemberProfilesCrudClientUpdateSchema = yupObject({
display_name: schemaFields.teamMemberDisplayNameSchema.optional(),
profile_image_url: schemaFields.teamMemberProfileImageUrlSchema.nullable().optional()
}).defined();
var teamMemberProfilesCrud = createCrud({
clientReadSchema: teamMemberProfilesCrudClientReadSchema,
serverReadSchema: teamMemberProfilesCrudServerReadSchema,
clientUpdateSchema: teamMemberProfilesCrudClientUpdateSchema,
docs: {
clientList: {
summary: "List team members profiles",
description: "List team members profiles. You always need to specify a `team_id` that your are a member of on the client. You can always filter for your own profile by setting `me` as the `user_id` in the path parameters. If you want list all the profiles in a team, you need to have the `$read_members` permission in that team.",
tags: ["Teams"]
},
serverList: {
summary: "List team members profiles",
description: "List team members profiles and filter by team ID and user ID",
tags: ["Teams"]
},
clientRead: {
summary: "Get a team member profile",
description: "Get a team member profile. you can always get your own profile by setting `me` as the `user_id` in the path parameters on the client. If you want to get someone else's profile in a team, you need to have the `$read_members` permission in that team.",
tags: ["Teams"]
},
serverRead: {
summary: "Get a team member profile",
description: "Get a team member profile by user ID",
tags: ["Teams"]
},
clientUpdate: {
summary: "Update your team member profile",
description: "Update your own team member profile. `user_id` must be `me` in the path parameters on the client.",
tags: ["Teams"]
},
serverUpdate: {
summary: "Update a team member profile",
description: "Update a team member profile by user ID",
tags: ["Teams"]
}
}
});
export {
teamMemberProfilesCrud,
teamMemberProfilesCrudClientReadSchema,
teamMemberProfilesCrudClientUpdateSchema,
teamMemberProfilesCrudServerReadSchema
};
//# sourceMappingURL=team-member-profiles.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/interface/crud/team-member-profiles.ts"],"sourcesContent":["import { CrudTypeOf, createCrud } from \"../../crud\";\nimport * as schemaFields from \"../../schema-fields\";\nimport { yupObject } from \"../../schema-fields\";\nimport { usersCrudServerReadSchema } from \"./users\";\n\n\nexport const teamMemberProfilesCrudClientReadSchema = yupObject({\n team_id: schemaFields.teamIdSchema.defined(),\n user_id: schemaFields.userIdSchema.defined(),\n display_name: schemaFields.teamMemberDisplayNameSchema.nullable().defined(),\n profile_image_url: schemaFields.teamMemberProfileImageUrlSchema.nullable().defined(),\n}).defined();\n\nexport const teamMemberProfilesCrudServerReadSchema = teamMemberProfilesCrudClientReadSchema.concat(yupObject({\n user: usersCrudServerReadSchema.defined(),\n})).defined();\n\nexport const teamMemberProfilesCrudClientUpdateSchema = yupObject({\n display_name: schemaFields.teamMemberDisplayNameSchema.optional(),\n profile_image_url: schemaFields.teamMemberProfileImageUrlSchema.nullable().optional(),\n}).defined();\n\nexport const teamMemberProfilesCrud = createCrud({\n clientReadSchema: teamMemberProfilesCrudClientReadSchema,\n serverReadSchema: teamMemberProfilesCrudServerReadSchema,\n clientUpdateSchema: teamMemberProfilesCrudClientUpdateSchema,\n docs: {\n clientList: {\n summary: \"List team members profiles\",\n description: \"List team members profiles. You always need to specify a `team_id` that your are a member of on the client. You can always filter for your own profile by setting `me` as the `user_id` in the path parameters. If you want list all the profiles in a team, you need to have the `$read_members` permission in that team.\",\n tags: [\"Teams\"],\n },\n serverList: {\n summary: \"List team members profiles\",\n description: \"List team members profiles and filter by team ID and user ID\",\n tags: [\"Teams\"],\n },\n clientRead: {\n summary: \"Get a team member profile\",\n description: \"Get a team member profile. you can always get your own profile by setting `me` as the `user_id` in the path parameters on the client. If you want to get someone else's profile in a team, you need to have the `$read_members` permission in that team.\",\n tags: [\"Teams\"],\n },\n serverRead: {\n summary: \"Get a team member profile\",\n description: \"Get a team member profile by user ID\",\n tags: [\"Teams\"],\n },\n clientUpdate: {\n summary: \"Update your team member profile\",\n description: \"Update your own team member profile. `user_id` must be `me` in the path parameters on the client.\",\n tags: [\"Teams\"],\n },\n serverUpdate: {\n summary: \"Update a team member profile\",\n description: \"Update a team member profile by user ID\",\n tags: [\"Teams\"],\n },\n },\n});\n\nexport type TeamMemberProfilesCrud = CrudTypeOf<typeof teamMemberProfilesCrud>;\n"],"mappings":";AAAA,SAAqB,kBAAkB;AACvC,YAAY,kBAAkB;AAC9B,SAAS,iBAAiB;AAC1B,SAAS,iCAAiC;AAGnC,IAAM,yCAAyC,UAAU;AAAA,EAC9D,SAAsB,0BAAa,QAAQ;AAAA,EAC3C,SAAsB,0BAAa,QAAQ;AAAA,EAC3C,cAA2B,yCAA4B,SAAS,EAAE,QAAQ;AAAA,EAC1E,mBAAgC,6CAAgC,SAAS,EAAE,QAAQ;AACrF,CAAC,EAAE,QAAQ;AAEJ,IAAM,yCAAyC,uCAAuC,OAAO,UAAU;AAAA,EAC5G,MAAM,0BAA0B,QAAQ;AAC1C,CAAC,CAAC,EAAE,QAAQ;AAEL,IAAM,2CAA2C,UAAU;AAAA,EAChE,cAA2B,yCAA4B,SAAS;AAAA,EAChE,mBAAgC,6CAAgC,SAAS,EAAE,SAAS;AACtF,CAAC,EAAE,QAAQ;AAEJ,IAAM,yBAAyB,WAAW;AAAA,EAC/C,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,MAAM;AAAA,IACJ,YAAY;AAAA,MACV,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM,CAAC,OAAO;AAAA,IAChB;AAAA,IACA,YAAY;AAAA,MACV,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM,CAAC,OAAO;AAAA,IAChB;AAAA,IACA,YAAY;AAAA,MACV,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM,CAAC,OAAO;AAAA,IAChB;AAAA,IACA,YAAY;AAAA,MACV,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM,CAAC,OAAO;AAAA,IAChB;AAAA,IACA,cAAc;AAAA,MACZ,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM,CAAC,OAAO;AAAA,IAChB;AAAA,IACA,cAAc;AAAA,MACZ,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM,CAAC,OAAO;AAAA,IAChB;AAAA,EACF;AACF,CAAC;","names":[]}

View file

@ -0,0 +1,60 @@
// src/interface/crud/team-memberships.ts
import { createCrud } from "../../crud";
import { yupMixed, yupObject, yupString } from "../../schema-fields";
var teamMembershipsCrudClientReadSchema = yupObject({
team_id: yupString().defined(),
user_id: yupString().defined()
}).defined();
var teamMembershipsCrudServerCreateSchema = yupObject({}).defined();
var teamMembershipsCrudClientDeleteSchema = yupMixed();
var teamMembershipsCrud = createCrud({
// Client
clientReadSchema: teamMembershipsCrudClientReadSchema,
clientDeleteSchema: teamMembershipsCrudClientDeleteSchema,
// Server
serverCreateSchema: teamMembershipsCrudServerCreateSchema,
docs: {
serverCreate: {
summary: "Add a user to a team",
description: "",
tags: ["Teams"]
},
clientDelete: {
summary: "Remove a user from a team",
description: "All the users are allowed to remove themselves from a team (`user_id=me`). Only the users who have the `$remove_members` permission are allowed to remove other users from a team. `team_id` is must an ID of a team that the user is a member of.",
tags: ["Teams"]
},
serverDelete: {
summary: "Remove a user from a team",
description: "",
tags: ["Teams"]
}
}
});
var teamMembershipCreatedWebhookEvent = {
type: "team_membership.created",
schema: teamMembershipsCrud.server.readSchema,
metadata: {
summary: "Team Membership Created",
description: "This event is triggered when a user is added to a team.",
tags: ["Teams"]
}
};
var teamMembershipDeletedWebhookEvent = {
type: "team_membership.deleted",
schema: teamMembershipsCrud.server.readSchema,
metadata: {
summary: "Team Membership Deleted",
description: "This event is triggered when a user is removed from a team.",
tags: ["Teams"]
}
};
export {
teamMembershipCreatedWebhookEvent,
teamMembershipDeletedWebhookEvent,
teamMembershipsCrud,
teamMembershipsCrudClientDeleteSchema,
teamMembershipsCrudClientReadSchema,
teamMembershipsCrudServerCreateSchema
};
//# sourceMappingURL=team-memberships.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/interface/crud/team-memberships.ts"],"sourcesContent":["import { CrudTypeOf, createCrud } from \"../../crud\";\nimport { yupMixed, yupObject, yupString } from \"../../schema-fields\";\nimport { WebhookEvent } from \"../webhooks\";\n\nexport const teamMembershipsCrudClientReadSchema = yupObject({\n team_id: yupString().defined(),\n user_id: yupString().defined(),\n}).defined();\nexport const teamMembershipsCrudServerCreateSchema = yupObject({}).defined();\nexport const teamMembershipsCrudClientDeleteSchema = yupMixed();\n\nexport const teamMembershipsCrud = createCrud({\n // Client\n clientReadSchema: teamMembershipsCrudClientReadSchema,\n clientDeleteSchema: teamMembershipsCrudClientDeleteSchema,\n // Server\n serverCreateSchema: teamMembershipsCrudServerCreateSchema,\n docs: {\n serverCreate: {\n summary: \"Add a user to a team\",\n description: \"\",\n tags: [\"Teams\"],\n },\n clientDelete: {\n summary: \"Remove a user from a team\",\n description: \"All the users are allowed to remove themselves from a team (`user_id=me`). Only the users who have the `$remove_members` permission are allowed to remove other users from a team. `team_id` is must an ID of a team that the user is a member of.\",\n tags: [\"Teams\"],\n },\n serverDelete: {\n summary: \"Remove a user from a team\",\n description: \"\",\n tags: [\"Teams\"],\n },\n },\n});\nexport type TeamMembershipsCrud = CrudTypeOf<typeof teamMembershipsCrud>;\n\nexport const teamMembershipCreatedWebhookEvent = {\n type: \"team_membership.created\",\n schema: teamMembershipsCrud.server.readSchema,\n metadata: {\n summary: \"Team Membership Created\",\n description: \"This event is triggered when a user is added to a team.\",\n tags: [\"Teams\"],\n },\n} satisfies WebhookEvent<typeof teamMembershipsCrud.server.readSchema>;\n\nexport const teamMembershipDeletedWebhookEvent = {\n type: \"team_membership.deleted\",\n schema: teamMembershipsCrud.server.readSchema,\n metadata: {\n summary: \"Team Membership Deleted\",\n description: \"This event is triggered when a user is removed from a team.\",\n tags: [\"Teams\"],\n },\n} satisfies WebhookEvent<typeof teamMembershipsCrud.server.readSchema>;\n"],"mappings":";AAAA,SAAqB,kBAAkB;AACvC,SAAS,UAAU,WAAW,iBAAiB;AAGxC,IAAM,sCAAsC,UAAU;AAAA,EAC3D,SAAS,UAAU,EAAE,QAAQ;AAAA,EAC7B,SAAS,UAAU,EAAE,QAAQ;AAC/B,CAAC,EAAE,QAAQ;AACJ,IAAM,wCAAwC,UAAU,CAAC,CAAC,EAAE,QAAQ;AACpE,IAAM,wCAAwC,SAAS;AAEvD,IAAM,sBAAsB,WAAW;AAAA;AAAA,EAE5C,kBAAkB;AAAA,EAClB,oBAAoB;AAAA;AAAA,EAEpB,oBAAoB;AAAA,EACpB,MAAM;AAAA,IACJ,cAAc;AAAA,MACZ,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM,CAAC,OAAO;AAAA,IAChB;AAAA,IACA,cAAc;AAAA,MACZ,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM,CAAC,OAAO;AAAA,IAChB;AAAA,IACA,cAAc;AAAA,MACZ,SAAS;AAAA,MACT,aAAa;AAAA,MACb,MAAM,CAAC,OAAO;AAAA,IAChB;AAAA,EACF;AACF,CAAC;AAGM,IAAM,oCAAoC;AAAA,EAC/C,MAAM;AAAA,EACN,QAAQ,oBAAoB,OAAO;AAAA,EACnC,UAAU;AAAA,IACR,SAAS;AAAA,IACT,aAAa;AAAA,IACb,MAAM,CAAC,OAAO;AAAA,EAChB;AACF;AAEO,IAAM,oCAAoC;AAAA,EAC/C,MAAM;AAAA,EACN,QAAQ,oBAAoB,OAAO;AAAA,EACnC,UAAU;AAAA,IACR,SAAS;AAAA,IACT,aAAa;AAAA,IACb,MAAM,CAAC,OAAO;AAAA,EAChB;AACF;","names":[]}

View file

@ -0,0 +1,114 @@
// src/interface/crud/team-permissions.ts
import { createCrud } from "../../crud";
import * as schemaFields from "../../schema-fields";
import { yupMixed, yupObject } from "../../schema-fields";
var teamPermissionsCrudClientReadSchema = yupObject({
id: schemaFields.permissionDefinitionIdSchema.defined(),
user_id: schemaFields.userIdSchema.defined(),
team_id: schemaFields.teamIdSchema.defined()
}).defined();
var teamPermissionsCrudServerCreateSchema = yupObject({}).defined();
var teamPermissionsCrudServerDeleteSchema = yupMixed();
var teamPermissionsCrud = createCrud({
clientReadSchema: teamPermissionsCrudClientReadSchema,
serverCreateSchema: teamPermissionsCrudServerCreateSchema,
serverDeleteSchema: teamPermissionsCrudServerDeleteSchema,
docs: {
clientList: {
summary: "List team permissions",
description: "List team permissions of the current user. `user_id=me` must be set for client requests. Note that this might contain the permissions with the same permission ID across different teams. `(team_id, user_id, permission_id)` together uniquely identify a permission.",
tags: ["Permissions"]
},
serverList: {
summary: "List team permissions of a user",
description: "Query and filter the permission with `team_id`, `user_id`, and `permission_id`. Note that this might contain the permissions with the same permission ID across different teams and users. `(team_id, user_id, permission_id)` together uniquely identify a permission.",
tags: ["Permissions"]
},
serverCreate: {
summary: "Grant a team permission to a user",
description: "Grant a team permission to a user (the team permission must be created first on the Stack dashboard)",
tags: ["Permissions"]
},
serverDelete: {
summary: "Revoke a team permission from a user",
description: "Revoke a team permission from a user",
tags: ["Permissions"]
}
}
});
var teamPermissionCreatedWebhookEvent = {
type: "team_permission.created",
schema: teamPermissionsCrud.server.readSchema,
metadata: {
summary: "Team Permission Created",
description: "This event is triggered when a team permission is created.",
tags: ["Teams"]
}
};
var teamPermissionDeletedWebhookEvent = {
type: "team_permission.deleted",
schema: teamPermissionsCrud.server.readSchema,
metadata: {
summary: "Team Permission Deleted",
description: "This event is triggered when a team permission is deleted.",
tags: ["Teams"]
}
};
var teamPermissionDefinitionsCrudAdminReadSchema = yupObject({
id: schemaFields.permissionDefinitionIdSchema.defined(),
description: schemaFields.teamPermissionDescriptionSchema.optional(),
contained_permission_ids: schemaFields.containedPermissionIdsSchema.defined()
}).defined();
var teamPermissionDefinitionsCrudAdminCreateSchema = yupObject({
id: schemaFields.customPermissionDefinitionIdSchema.defined(),
description: schemaFields.teamPermissionDescriptionSchema.optional(),
contained_permission_ids: schemaFields.containedPermissionIdsSchema.optional()
}).defined();
var teamPermissionDefinitionsCrudAdminUpdateSchema = yupObject({
id: schemaFields.customPermissionDefinitionIdSchema.optional(),
description: schemaFields.teamPermissionDescriptionSchema.optional(),
contained_permission_ids: schemaFields.containedPermissionIdsSchema.optional()
}).defined();
var teamPermissionDefinitionsCrudAdminDeleteSchema = yupMixed();
var teamPermissionDefinitionsCrud = createCrud({
adminReadSchema: teamPermissionDefinitionsCrudAdminReadSchema,
adminCreateSchema: teamPermissionDefinitionsCrudAdminCreateSchema,
adminUpdateSchema: teamPermissionDefinitionsCrudAdminUpdateSchema,
adminDeleteSchema: teamPermissionDefinitionsCrudAdminDeleteSchema,
docs: {
adminList: {
summary: "List team permission definitions",
description: "Query and filter the permission with team_id, user_id, and permission_id (the equivalent of listing permissions on the Stack dashboard)",
tags: ["Permissions"]
},
adminCreate: {
summary: "Create a new team permission definition",
description: "Create a new permission definition (the equivalent of creating a new permission on the Stack dashboard)",
tags: ["Permissions"]
},
adminUpdate: {
summary: "Update a team permission definition",
description: "Update a permission definition (the equivalent of updating a permission on the Stack dashboard)",
tags: ["Permissions"]
},
adminDelete: {
summary: "Delete a team permission definition",
description: "Delete a permission definition (the equivalent of deleting a permission on the Stack dashboard)",
tags: ["Permissions"]
}
}
});
export {
teamPermissionCreatedWebhookEvent,
teamPermissionDefinitionsCrud,
teamPermissionDefinitionsCrudAdminCreateSchema,
teamPermissionDefinitionsCrudAdminDeleteSchema,
teamPermissionDefinitionsCrudAdminReadSchema,
teamPermissionDefinitionsCrudAdminUpdateSchema,
teamPermissionDeletedWebhookEvent,
teamPermissionsCrud,
teamPermissionsCrudClientReadSchema,
teamPermissionsCrudServerCreateSchema,
teamPermissionsCrudServerDeleteSchema
};
//# sourceMappingURL=team-permissions.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,143 @@
// src/interface/crud/teams.ts
import { createCrud } from "../../crud";
import * as fieldSchema from "../../schema-fields";
import { yupObject as yupObject2 } from "../../schema-fields";
var teamsCrudClientReadSchema = yupObject2({
id: fieldSchema.teamIdSchema.defined(),
display_name: fieldSchema.teamDisplayNameSchema.defined(),
profile_image_url: fieldSchema.teamProfileImageUrlSchema.nullable().defined(),
client_metadata: fieldSchema.teamClientMetadataSchema.optional(),
client_read_only_metadata: fieldSchema.teamClientReadOnlyMetadataSchema.optional()
}).defined();
var teamsCrudServerReadSchema = teamsCrudClientReadSchema.concat(yupObject2({
created_at_millis: fieldSchema.teamCreatedAtMillisSchema.defined(),
server_metadata: fieldSchema.teamServerMetadataSchema.optional()
}).defined());
var teamsCrudClientUpdateSchema = yupObject2({
display_name: fieldSchema.teamDisplayNameSchema.optional(),
profile_image_url: fieldSchema.teamProfileImageUrlSchema.nullable().optional(),
client_metadata: fieldSchema.teamClientMetadataSchema.optional()
}).defined();
var teamsCrudServerUpdateSchema = teamsCrudClientUpdateSchema.concat(yupObject2({
client_read_only_metadata: fieldSchema.teamClientReadOnlyMetadataSchema.optional(),
server_metadata: fieldSchema.teamServerMetadataSchema.optional()
}).defined());
var teamsCrudClientCreateSchema = teamsCrudClientUpdateSchema.concat(yupObject2({
display_name: fieldSchema.teamDisplayNameSchema.defined(),
creator_user_id: fieldSchema.teamCreatorUserIdSchema.optional()
}).defined());
var teamsCrudServerCreateSchema = teamsCrudServerUpdateSchema.concat(yupObject2({
display_name: fieldSchema.teamDisplayNameSchema.defined(),
creator_user_id: fieldSchema.teamCreatorUserIdSchema.optional()
}).defined());
var teamsCrudClientDeleteSchema = fieldSchema.yupMixed();
var teamsCrudServerDeleteSchema = teamsCrudClientDeleteSchema;
var teamsCrud = createCrud({
// Client
clientReadSchema: teamsCrudClientReadSchema,
clientUpdateSchema: teamsCrudClientUpdateSchema,
clientCreateSchema: teamsCrudClientCreateSchema,
clientDeleteSchema: teamsCrudClientDeleteSchema,
// Server
serverReadSchema: teamsCrudServerReadSchema,
serverUpdateSchema: teamsCrudServerUpdateSchema,
serverCreateSchema: teamsCrudServerCreateSchema,
serverDeleteSchema: teamsCrudServerDeleteSchema,
docs: {
clientList: {
summary: "List teams",
description: "List all the teams that the current user is a member of. `user_id=me` must be passed in the query parameters.",
tags: ["Teams"]
},
clientCreate: {
summary: "Create a team",
description: "Create a new team and optionally add the current user as a member.",
tags: ["Teams"]
},
clientRead: {
summary: "Get a team",
description: "Get a team that the current user is a member of.",
tags: ["Teams"]
},
clientUpdate: {
summary: "Update a team",
description: "Update the team information. Only allowed if the current user is a member of the team and has the `$update_team` permission.",
tags: ["Teams"]
},
clientDelete: {
summary: "Delete a team",
description: "Delete a team. Only allowed if the current user is a member of the team and has the `$delete_team` permission.",
tags: ["Teams"]
},
serverCreate: {
summary: "Create a team",
description: "Create a new team and optionally add the current user as a member.",
tags: ["Teams"]
},
serverList: {
summary: "List teams",
description: "List all the teams in the project.",
tags: ["Teams"]
},
serverRead: {
summary: "Get a team",
description: "Get a team by ID.",
tags: ["Teams"]
},
serverUpdate: {
summary: "Update a team",
description: "Update the team information by ID.",
tags: ["Teams"]
},
serverDelete: {
summary: "Delete a team",
description: "Delete a team by ID.",
tags: ["Teams"]
}
}
});
var teamCreatedWebhookEvent = {
type: "team.created",
schema: teamsCrud.server.readSchema,
metadata: {
summary: "Team Created",
description: "This event is triggered when a team is created.",
tags: ["Teams"]
}
};
var teamUpdatedWebhookEvent = {
type: "team.updated",
schema: teamsCrud.server.readSchema,
metadata: {
summary: "Team Updated",
description: "This event is triggered when a team is updated.",
tags: ["Teams"]
}
};
var webhookTeamDeletedSchema = fieldSchema.yupObject({
id: fieldSchema.userIdSchema.defined()
}).defined();
var teamDeletedWebhookEvent = {
type: "team.deleted",
schema: webhookTeamDeletedSchema,
metadata: {
summary: "Team Deleted",
description: "This event is triggered when a team is deleted.",
tags: ["Teams"]
}
};
export {
teamCreatedWebhookEvent,
teamDeletedWebhookEvent,
teamUpdatedWebhookEvent,
teamsCrud,
teamsCrudClientCreateSchema,
teamsCrudClientDeleteSchema,
teamsCrudClientReadSchema,
teamsCrudClientUpdateSchema,
teamsCrudServerCreateSchema,
teamsCrudServerDeleteSchema,
teamsCrudServerReadSchema,
teamsCrudServerUpdateSchema
};
//# sourceMappingURL=teams.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,139 @@
// src/interface/crud/users.ts
import { createCrud } from "../../crud";
import * as fieldSchema from "../../schema-fields";
import { teamsCrudServerReadSchema } from "./teams";
var usersCrudServerUpdateSchema = fieldSchema.yupObject({
display_name: fieldSchema.userDisplayNameSchema.optional(),
profile_image_url: fieldSchema.profileImageUrlSchema.nullable().optional(),
client_metadata: fieldSchema.userClientMetadataSchema.optional(),
client_read_only_metadata: fieldSchema.userClientReadOnlyMetadataSchema.optional(),
server_metadata: fieldSchema.userServerMetadataSchema.optional(),
primary_email: fieldSchema.primaryEmailSchema.nullable().optional().nonEmpty(),
primary_email_verified: fieldSchema.primaryEmailVerifiedSchema.optional(),
primary_email_auth_enabled: fieldSchema.primaryEmailAuthEnabledSchema.optional(),
passkey_auth_enabled: fieldSchema.userOtpAuthEnabledSchema.optional(),
password: fieldSchema.userPasswordMutationSchema.optional(),
password_hash: fieldSchema.userPasswordHashMutationSchema.optional(),
otp_auth_enabled: fieldSchema.userOtpAuthEnabledMutationSchema.optional(),
totp_secret_base64: fieldSchema.userTotpSecretMutationSchema.optional(),
selected_team_id: fieldSchema.selectedTeamIdSchema.nullable().optional(),
is_anonymous: fieldSchema.yupBoolean().oneOf([false]).optional()
}).defined();
var usersCrudServerReadSchema = fieldSchema.yupObject({
id: fieldSchema.userIdSchema.defined(),
primary_email: fieldSchema.primaryEmailSchema.nullable().defined(),
primary_email_verified: fieldSchema.primaryEmailVerifiedSchema.defined(),
primary_email_auth_enabled: fieldSchema.primaryEmailAuthEnabledSchema.defined(),
display_name: fieldSchema.userDisplayNameSchema.nullable().defined(),
selected_team: teamsCrudServerReadSchema.nullable().defined(),
selected_team_id: fieldSchema.selectedTeamIdSchema.nullable().defined(),
profile_image_url: fieldSchema.profileImageUrlSchema.nullable().defined(),
signed_up_at_millis: fieldSchema.signedUpAtMillisSchema.defined(),
has_password: fieldSchema.userHasPasswordSchema.defined(),
otp_auth_enabled: fieldSchema.userOtpAuthEnabledSchema.defined(),
passkey_auth_enabled: fieldSchema.userOtpAuthEnabledSchema.defined(),
client_metadata: fieldSchema.userClientMetadataSchema,
client_read_only_metadata: fieldSchema.userClientReadOnlyMetadataSchema,
server_metadata: fieldSchema.userServerMetadataSchema,
last_active_at_millis: fieldSchema.userLastActiveAtMillisSchema.nonNullable().defined(),
is_anonymous: fieldSchema.yupBoolean().defined(),
oauth_providers: fieldSchema.yupArray(fieldSchema.yupObject({
id: fieldSchema.yupString().defined(),
account_id: fieldSchema.yupString().defined(),
email: fieldSchema.yupString().nullable()
}).defined()).defined().meta({ openapiField: { hidden: true } }),
/**
* @deprecated
*/
auth_with_email: fieldSchema.yupBoolean().defined().meta({ openapiField: { hidden: true, description: "Whether the user can authenticate with their primary e-mail. If set to true, the user can log-in with credentials and/or magic link, if enabled in the project settings.", exampleValue: true } }),
/**
* @deprecated
*/
requires_totp_mfa: fieldSchema.yupBoolean().defined().meta({ openapiField: { hidden: true, description: "Whether the user is required to use TOTP MFA to sign in", exampleValue: false } })
}).defined();
var usersCrudServerCreateSchema = usersCrudServerUpdateSchema.omit(["selected_team_id"]).concat(fieldSchema.yupObject({
oauth_providers: fieldSchema.yupArray(fieldSchema.yupObject({
id: fieldSchema.yupString().defined(),
account_id: fieldSchema.yupString().defined(),
email: fieldSchema.yupString().nullable().defined().default(null)
}).defined()).optional().meta({ openapiField: { hidden: true } }),
is_anonymous: fieldSchema.yupBoolean().optional()
}).defined());
var usersCrudServerDeleteSchema = fieldSchema.yupMixed();
var usersCrud = createCrud({
serverReadSchema: usersCrudServerReadSchema,
serverUpdateSchema: usersCrudServerUpdateSchema,
serverCreateSchema: usersCrudServerCreateSchema,
serverDeleteSchema: usersCrudServerDeleteSchema,
docs: {
serverCreate: {
tags: ["Users"],
summary: "Create user",
description: "Creates a new user. E-mail authentication is always enabled, and no password is set, meaning the only way to authenticate the newly created user is through magic link."
},
serverRead: {
tags: ["Users"],
summary: "Get user",
description: "Gets a user by user ID."
},
serverUpdate: {
tags: ["Users"],
summary: "Update user",
description: "Updates a user. Only the values provided will be updated."
},
serverDelete: {
tags: ["Users"],
summary: "Delete user",
description: "Deletes a user. Use this with caution."
},
serverList: {
tags: ["Users"],
summary: "List users",
description: "Lists all the users in the project."
}
}
});
var userCreatedWebhookEvent = {
type: "user.created",
schema: usersCrud.server.readSchema,
metadata: {
summary: "User Created",
description: "This event is triggered when a user is created.",
tags: ["Users"]
}
};
var userUpdatedWebhookEvent = {
type: "user.updated",
schema: usersCrud.server.readSchema,
metadata: {
summary: "User Updated",
description: "This event is triggered when a user is updated.",
tags: ["Users"]
}
};
var webhookUserDeletedSchema = fieldSchema.yupObject({
id: fieldSchema.userIdSchema.defined(),
teams: fieldSchema.yupArray(fieldSchema.yupObject({
id: fieldSchema.yupString().defined()
})).defined()
}).defined();
var userDeletedWebhookEvent = {
type: "user.deleted",
schema: webhookUserDeletedSchema,
metadata: {
summary: "User Deleted",
description: "This event is triggered when a user is deleted.",
tags: ["Users"]
}
};
export {
userCreatedWebhookEvent,
userDeletedWebhookEvent,
userUpdatedWebhookEvent,
usersCrud,
usersCrudServerCreateSchema,
usersCrudServerDeleteSchema,
usersCrudServerReadSchema,
usersCrudServerUpdateSchema
};
//# sourceMappingURL=users.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,511 @@
// src/interface/serverInterface.ts
import { KnownErrors } from "../known-errors";
import { StackAssertionError } from "../utils/errors";
import { filterUndefined } from "../utils/objects";
import { Result } from "../utils/results";
import { urlString } from "../utils/urls";
import {
StackClientInterface
} from "./clientInterface";
var StackServerInterface = class extends StackClientInterface {
constructor(options) {
super(options);
this.options = options;
}
async sendServerRequest(path, options, session, requestType = "server") {
return await this.sendClientRequest(
path,
{
...options,
headers: {
"x-stack-secret-server-key": "secretServerKey" in this.options ? this.options.secretServerKey : "",
...options.headers
}
},
session,
requestType
);
}
async sendServerRequestAndCatchKnownError(path, requestOptions, tokenStoreOrNull, errorsToCatch) {
try {
return Result.ok(await this.sendServerRequest(path, requestOptions, tokenStoreOrNull));
} catch (e) {
for (const errorType of errorsToCatch) {
if (errorType.isInstance(e)) {
return Result.error(e);
}
}
throw e;
}
}
async createServerUser(data) {
const response = await this.sendServerRequest(
"/users",
{
method: "POST",
headers: {
"content-type": "application/json"
},
body: JSON.stringify(data)
},
null
);
return await response.json();
}
async getServerUserByToken(session) {
const responseOrError = await this.sendServerRequestAndCatchKnownError(
"/users/me",
{},
session,
[KnownErrors.CannotGetOwnUserWithoutUser]
);
if (responseOrError.status === "error") {
if (KnownErrors.CannotGetOwnUserWithoutUser.isInstance(responseOrError.error)) {
return null;
} else {
throw new StackAssertionError("Unexpected uncaught error", { cause: responseOrError.error });
}
}
const response = responseOrError.data;
const user = await response.json();
if (!user) throw new StackAssertionError("User endpoint returned null; this should never happen");
return user;
}
async getServerUserById(userId) {
const responseOrError = await this.sendServerRequestAndCatchKnownError(
urlString`/users/${userId}`,
{},
null,
[KnownErrors.UserNotFound]
);
if (responseOrError.status === "error") {
return Result.error(responseOrError.error);
}
const user = await responseOrError.data.json();
return Result.ok(user);
}
async listServerTeamInvitations(options) {
const response = await this.sendServerRequest(
urlString`/team-invitations?team_id=${options.teamId}`,
{},
null
);
const result = await response.json();
return result.items;
}
async revokeServerTeamInvitation(invitationId, teamId) {
await this.sendServerRequest(
urlString`/team-invitations/${invitationId}?team_id=${teamId}`,
{ method: "DELETE" },
null
);
}
async listServerTeamMemberProfiles(options) {
const response = await this.sendServerRequest(
urlString`/team-member-profiles?team_id=${options.teamId}`,
{},
null
);
const result = await response.json();
return result.items;
}
async getServerTeamMemberProfile(options) {
const response = await this.sendServerRequest(
urlString`/team-member-profiles/${options.teamId}/${options.userId}`,
{},
null
);
return await response.json();
}
async listServerTeamPermissions(options, session) {
const response = await this.sendServerRequest(
`/team-permissions?${new URLSearchParams(filterUndefined({
user_id: options.userId,
team_id: options.teamId,
recursive: options.recursive.toString()
}))}`,
{},
session
);
const result = await response.json();
return result.items;
}
async listServerProjectPermissions(options, session) {
const response = await this.sendServerRequest(
`/project-permissions?${new URLSearchParams(filterUndefined({
user_id: options.userId,
recursive: options.recursive.toString()
}))}`,
{},
session
);
const result = await response.json();
return result.items;
}
async listServerUsers(options) {
const searchParams = new URLSearchParams(filterUndefined({
cursor: options.cursor,
limit: options.limit?.toString(),
desc: options.desc?.toString(),
...options.orderBy ? {
order_by: {
signedUpAt: "signed_up_at"
}[options.orderBy]
} : {},
...options.query ? {
query: options.query
} : {}
}));
const response = await this.sendServerRequest("/users?" + searchParams.toString(), {}, null);
return await response.json();
}
async listServerTeams(options) {
const response = await this.sendServerRequest(
`/teams?${new URLSearchParams(filterUndefined({
user_id: options?.userId
}))}`,
{},
null
);
const result = await response.json();
return result.items;
}
async getServerTeam(teamId) {
const response = await this.sendServerRequest(
`/teams/${teamId}`,
{},
null
);
return await response.json();
}
async listServerTeamUsers(teamId) {
const response = await this.sendServerRequest(`/users?team_id=${teamId}`, {}, null);
const result = await response.json();
return result.items;
}
/* when passing a session, the user will be added to the team */
async createServerTeam(data) {
const response = await this.sendServerRequest(
"/teams",
{
method: "POST",
headers: {
"content-type": "application/json"
},
body: JSON.stringify(data)
},
null
);
return await response.json();
}
async updateServerTeam(teamId, data) {
const response = await this.sendServerRequest(
urlString`/teams/${teamId}`,
{
method: "PATCH",
headers: {
"content-type": "application/json"
},
body: JSON.stringify(data)
},
null
);
return await response.json();
}
async deleteServerTeam(teamId) {
await this.sendServerRequest(
urlString`/teams/${teamId}`,
{ method: "DELETE" },
null
);
}
async addServerUserToTeam(options) {
const response = await this.sendServerRequest(
urlString`/team-memberships/${options.teamId}/${options.userId}`,
{
method: "POST",
headers: {
"content-type": "application/json"
},
body: JSON.stringify({})
},
null
);
return await response.json();
}
async removeServerUserFromTeam(options) {
await this.sendServerRequest(
urlString`/team-memberships/${options.teamId}/${options.userId}`,
{
method: "DELETE",
headers: {
"content-type": "application/json"
},
body: JSON.stringify({})
},
null
);
}
async updateServerUser(userId, update) {
const response = await this.sendServerRequest(
urlString`/users/${userId}`,
{
method: "PATCH",
headers: {
"content-type": "application/json"
},
body: JSON.stringify(update)
},
null
);
return await response.json();
}
async createServerProviderAccessToken(userId, provider, scope) {
const response = await this.sendServerRequest(
urlString`/connected-accounts/${userId}/${provider}/access-token`,
{
method: "POST",
headers: {
"content-type": "application/json"
},
body: JSON.stringify({ scope })
},
null
);
return await response.json();
}
async createServerUserSession(userId, expiresInMillis, isImpersonation) {
const response = await this.sendServerRequest(
"/auth/sessions",
{
method: "POST",
headers: {
"content-type": "application/json"
},
body: JSON.stringify({
user_id: userId,
expires_in_millis: expiresInMillis,
is_impersonation: isImpersonation
})
},
null
);
const result = await response.json();
return {
accessToken: result.access_token,
refreshToken: result.refresh_token
};
}
async leaveServerTeam(options) {
await this.sendClientRequest(
urlString`/team-memberships/${options.teamId}/${options.userId}`,
{
method: "DELETE",
headers: {
"content-type": "application/json"
},
body: JSON.stringify({})
},
null
);
}
async updateServerTeamMemberProfile(options) {
await this.sendServerRequest(
urlString`/team-member-profiles/${options.teamId}/${options.userId}`,
{
method: "PATCH",
headers: {
"content-type": "application/json"
},
body: JSON.stringify(options.profile)
},
null
);
}
async grantServerTeamUserPermission(teamId, userId, permissionId) {
await this.sendServerRequest(
urlString`/team-permissions/${teamId}/${userId}/${permissionId}`,
{
method: "POST",
headers: {
"content-type": "application/json"
},
body: JSON.stringify({})
},
null
);
}
async grantServerProjectPermission(userId, permissionId) {
await this.sendServerRequest(
urlString`/project-permissions/${userId}/${permissionId}`,
{
method: "POST",
headers: {
"content-type": "application/json"
},
body: JSON.stringify({})
},
null
);
}
async revokeServerTeamUserPermission(teamId, userId, permissionId) {
await this.sendServerRequest(
urlString`/team-permissions/${teamId}/${userId}/${permissionId}`,
{
method: "DELETE",
headers: {
"content-type": "application/json"
},
body: JSON.stringify({})
},
null
);
}
async revokeServerProjectPermission(userId, permissionId) {
await this.sendServerRequest(
urlString`/project-permissions/${userId}/${permissionId}`,
{
method: "DELETE",
headers: {
"content-type": "application/json"
},
body: JSON.stringify({})
},
null
);
}
async deleteServerUser(userId) {
await this.sendServerRequest(
urlString`/users/${userId}`,
{
method: "DELETE",
headers: {
"content-type": "application/json"
},
body: JSON.stringify({})
},
null
);
}
async createServerContactChannel(data) {
const response = await this.sendServerRequest(
"/contact-channels",
{
method: "POST",
headers: {
"content-type": "application/json"
},
body: JSON.stringify(data)
},
null
);
return await response.json();
}
async updateServerContactChannel(userId, contactChannelId, data) {
const response = await this.sendServerRequest(
urlString`/contact-channels/${userId}/${contactChannelId}`,
{
method: "PATCH",
headers: {
"content-type": "application/json"
},
body: JSON.stringify(data)
},
null
);
return await response.json();
}
async deleteServerContactChannel(userId, contactChannelId) {
await this.sendServerRequest(
urlString`/contact-channels/${userId}/${contactChannelId}`,
{
method: "DELETE"
},
null
);
}
async listServerContactChannels(userId) {
const response = await this.sendServerRequest(
urlString`/contact-channels?user_id=${userId}`,
{
method: "GET"
},
null
);
const json = await response.json();
return json.items;
}
async sendServerContactChannelVerificationEmail(userId, contactChannelId, callbackUrl) {
await this.sendServerRequest(
urlString`/contact-channels/${userId}/${contactChannelId}/send-verification-code`,
{
method: "POST",
headers: {
"content-type": "application/json"
},
body: JSON.stringify({ callback_url: callbackUrl })
},
null
);
}
async listServerSessions(userId) {
const response = await this.sendServerRequest(
urlString`/auth/sessions?user_id=${userId}`,
{
method: "GET"
},
null
);
return await response.json();
}
async deleteServerSession(sessionId) {
await this.sendServerRequest(
urlString`/auth/sessions/${sessionId}`,
{
method: "DELETE"
},
null
);
}
async sendServerTeamInvitation(options) {
await this.sendServerRequest(
"/team-invitations/send-code",
{
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
email: options.email,
team_id: options.teamId,
callback_url: options.callbackUrl
})
},
null
);
}
async updatePassword(options) {
const res = await this.sendServerRequestAndCatchKnownError(
"/auth/password/update",
{
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
old_password: options.oldPassword,
new_password: options.newPassword
})
},
null,
[KnownErrors.PasswordConfirmationMismatch, KnownErrors.PasswordRequirementsNotMet]
);
if (res.status === "error") {
return res.error;
}
}
};
export {
StackServerInterface
};
//# sourceMappingURL=serverInterface.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,21 @@
// src/interface/webhooks.ts
import { teamMembershipCreatedWebhookEvent, teamMembershipDeletedWebhookEvent } from "./crud/team-memberships";
import { teamPermissionCreatedWebhookEvent, teamPermissionDeletedWebhookEvent } from "./crud/team-permissions";
import { teamCreatedWebhookEvent, teamDeletedWebhookEvent, teamUpdatedWebhookEvent } from "./crud/teams";
import { userCreatedWebhookEvent, userDeletedWebhookEvent, userUpdatedWebhookEvent } from "./crud/users";
var webhookEvents = [
userCreatedWebhookEvent,
userUpdatedWebhookEvent,
userDeletedWebhookEvent,
teamCreatedWebhookEvent,
teamUpdatedWebhookEvent,
teamDeletedWebhookEvent,
teamMembershipCreatedWebhookEvent,
teamMembershipDeletedWebhookEvent,
teamPermissionCreatedWebhookEvent,
teamPermissionDeletedWebhookEvent
];
export {
webhookEvents
};
//# sourceMappingURL=webhooks.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../../../src/interface/webhooks.ts"],"sourcesContent":["import * as yup from \"yup\";\nimport { teamMembershipCreatedWebhookEvent, teamMembershipDeletedWebhookEvent } from \"./crud/team-memberships\";\nimport { teamPermissionCreatedWebhookEvent, teamPermissionDeletedWebhookEvent } from \"./crud/team-permissions\";\nimport { teamCreatedWebhookEvent, teamDeletedWebhookEvent, teamUpdatedWebhookEvent } from \"./crud/teams\";\nimport { userCreatedWebhookEvent, userDeletedWebhookEvent, userUpdatedWebhookEvent } from \"./crud/users\";\n\nexport type WebhookEvent<S extends yup.Schema> = {\n type: string,\n schema: S,\n metadata: {\n summary: string,\n description: string,\n tags?: string[],\n },\n};\n\nexport const webhookEvents = [\n userCreatedWebhookEvent,\n userUpdatedWebhookEvent,\n userDeletedWebhookEvent,\n teamCreatedWebhookEvent,\n teamUpdatedWebhookEvent,\n teamDeletedWebhookEvent,\n teamMembershipCreatedWebhookEvent,\n teamMembershipDeletedWebhookEvent,\n teamPermissionCreatedWebhookEvent,\n teamPermissionDeletedWebhookEvent,\n] as const;\n"],"mappings":";AACA,SAAS,mCAAmC,yCAAyC;AACrF,SAAS,mCAAmC,yCAAyC;AACrF,SAAS,yBAAyB,yBAAyB,+BAA+B;AAC1F,SAAS,yBAAyB,yBAAyB,+BAA+B;AAYnF,IAAM,gBAAgB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;","names":[]}

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,486 @@
// src/schema-fields.ts
import * as yup from "yup";
import { KnownErrors } from ".";
import { isBase64 } from "./utils/bytes";
import { StackAssertionError, throwErr } from "./utils/errors";
import { decodeBasicAuthorizationHeader } from "./utils/http";
import { allProviders } from "./utils/oauth";
import { deepPlainClone, omit } from "./utils/objects";
import { isValidUrl } from "./utils/urls";
import { isUuid } from "./utils/uuids";
yup.addMethod(yup.string, "nonEmpty", function(message) {
return this.test(
"non-empty",
message ?? (({ path }) => `${path} must not be empty`),
(value) => {
return value !== "";
}
);
});
yup.addMethod(yup.Schema, "getNested", function(path) {
if (!path.match(/^[a-zA-Z_][a-zA-Z0-9_]*$/)) throw new StackAssertionError(`yupSchema.getNested can currently only be used with alphanumeric keys. Fix this in the future. Provided key: ${path}`);
return yup.reach(this, path);
});
async function yupValidate(schema, obj, options) {
try {
return await schema.validate(obj, {
...omit(options ?? {}, ["currentUserId"]),
context: {
...options?.context,
stackAllowUserIdMe: options?.currentUserId !== void 0
}
});
} catch (error) {
if (error instanceof ReplaceFieldWithOwnUserId) {
const currentUserId = options?.currentUserId;
if (!currentUserId) throw new KnownErrors.CannotGetOwnUserWithoutUser();
let pathRemaining = error.path;
const fieldPath = [];
while (pathRemaining.length > 0) {
if (pathRemaining.startsWith("[")) {
const index = pathRemaining.indexOf("]");
if (index < 0) throw new StackAssertionError("Invalid path");
fieldPath.push(JSON.parse(pathRemaining.slice(1, index)));
pathRemaining = pathRemaining.slice(index + 1);
} else {
let dotIndex = pathRemaining.indexOf(".");
if (dotIndex === -1) dotIndex = pathRemaining.length;
fieldPath.push(pathRemaining.slice(0, dotIndex));
pathRemaining = pathRemaining.slice(dotIndex + 1);
}
}
const newObj = deepPlainClone(obj);
let it = newObj;
for (const field of fieldPath.slice(0, -1)) {
if (!Object.prototype.hasOwnProperty.call(it, field)) {
throw new StackAssertionError(`Segment ${field} of path ${error.path} not found in object`);
}
it = it[field];
}
it[fieldPath[fieldPath.length - 1]] = currentUserId;
return await yupValidate(schema, newObj, options);
}
throw error;
}
}
var _idDescription = (identify) => `The unique identifier of the ${identify}`;
var _displayNameDescription = (identify) => `Human-readable ${identify} display name. This is not a unique identifier.`;
var _clientMetaDataDescription = (identify) => `Client metadata. Used as a data store, accessible from the client side. Do not store information that should not be exposed to the client.`;
var _clientReadOnlyMetaDataDescription = (identify) => `Client read-only, server-writable metadata. Used as a data store, accessible from the client side. Do not store information that should not be exposed to the client. The client can read this data, but cannot modify it. This is useful for things like subscription status.`;
var _profileImageUrlDescription = (identify) => `URL of the profile image for ${identify}. Can be a Base64 encoded image. Must be smaller than 100KB. Please compress and crop to a square before passing in.`;
var _serverMetaDataDescription = (identify) => `Server metadata. Used as a data store, only accessible from the server side. You can store secret information related to the ${identify} here.`;
var _atMillisDescription = (identify) => `(the number of milliseconds since epoch, January 1, 1970, UTC)`;
var _createdAtMillisDescription = (identify) => `The time the ${identify} was created ${_atMillisDescription(identify)}`;
var _signedUpAtMillisDescription = `The time the user signed up ${_atMillisDescription}`;
var _lastActiveAtMillisDescription = `The time the user was last active ${_atMillisDescription}`;
function yupString(...args) {
return yup.string(...args);
}
function yupNumber(...args) {
return yup.number(...args);
}
function yupBoolean(...args) {
return yup.boolean(...args);
}
function yupDate(...args) {
return yup.date(...args);
}
function yupMixed(...args) {
return yup.mixed(...args);
}
function yupArray(...args) {
return yup.array(...args);
}
function yupTuple(...args) {
return yup.tuple(...args);
}
function yupObject(...args) {
const object2 = yup.object(...args).test(
"no-unknown-object-properties",
({ path }) => `${path} contains unknown properties`,
(value, context) => {
if (context.options.context?.noUnknownPathPrefixes?.some((prefix) => context.path.startsWith(prefix))) {
if (context.schema.spec.noUnknown !== false) {
const availableKeys = new Set(Object.keys(context.schema.fields));
const unknownKeys = Object.keys(value ?? {}).filter((key) => !availableKeys.has(key));
if (unknownKeys.length > 0) {
return context.createError({
message: `${context.path || "Object"} contains unknown properties: ${unknownKeys.join(", ")}`,
path: context.path,
params: { unknownKeys, availableKeys }
});
}
}
}
return true;
}
);
return object2.default(void 0);
}
function yupNever() {
return yupMixed().test("never", "This value should never be reached", () => false);
}
function yupUnion(...args) {
if (args.length === 0) throw new Error("yupUnion must have at least one schema");
const [first] = args;
const firstDesc = first.describe();
for (const schema of args) {
const desc = schema.describe();
if (desc.type !== firstDesc.type) throw new StackAssertionError(`yupUnion must have schemas of the same type (got: ${firstDesc.type} and ${desc.type})`, { first, schema, firstDesc, desc });
}
return yupMixed().test("is-one-of", "Invalid value", async (value, context) => {
const errors = [];
for (const schema of args) {
try {
await yupValidate(schema, value, context.options);
return true;
} catch (e) {
errors.push(e);
}
}
return context.createError({
message: `${context.path} is not matched by any of the provided schemas:
${errors.map((e, i) => " Schema " + i + ": \n " + e.errors.join("\n ")).join("\n")}`,
path: context.path
});
});
}
function yupRecord(keySchema, valueSchema) {
return yupObject().unknown(true).test(
"record",
"${path} must be a record of valid values",
async function(value, context) {
if (value == null) return true;
const { path, createError } = this;
if (typeof value !== "object") {
return createError({ message: `${path} must be an object` });
}
for (const key of Object.keys(value)) {
await yupValidate(keySchema, key, context.options);
try {
await yupValidate(valueSchema, value[key], {
...context.options,
context: {
...context.options.context,
path: path ? `${path}.${key}` : key
}
});
} catch (e) {
return createError({
path: path ? `${path}.${key}` : key,
message: e.message
});
}
}
return true;
}
);
}
function ensureObjectSchema(schema) {
if (!(schema instanceof yup.ObjectSchema)) throw new StackAssertionError(`assertObjectSchema: schema is not an ObjectSchema: ${schema.describe().type}`);
return schema;
}
var adaptSchema = yupMixed();
var urlSchema = yupString().test({
name: "no-spaces",
message: (params) => `${params.path} contains spaces`,
test: (value) => value == null || !value.includes(" ")
}).test({
name: "url",
message: (params) => `${params.path} is not a valid URL`,
test: (value) => value == null || isValidUrl(value)
});
var jsonSchema = yupMixed().nullable().defined().transform((value) => JSON.parse(JSON.stringify(value)));
var jsonStringSchema = yupString().test("json", (params) => `${params.path} is not valid JSON`, (value) => {
if (value == null) return true;
try {
JSON.parse(value);
return true;
} catch (error) {
return false;
}
});
var jsonStringOrEmptySchema = yupString().test("json", (params) => `${params.path} is not valid JSON`, (value) => {
if (!value) return true;
try {
JSON.parse(value);
return true;
} catch (error) {
return false;
}
});
var base64Schema = yupString().test("is-base64", (params) => `${params.path} is not valid base64`, (value) => {
if (value == null) return true;
return isBase64(value);
});
var passwordSchema = yupString().max(70);
var strictEmailSchema = (message) => yupString().email(message).matches(/^[^.]+(\.[^.]+)*@.*\.[^.][^.]+$/, message);
var emailSchema = yupString().email();
var clientOrHigherAuthTypeSchema = yupString().oneOf(["client", "server", "admin"]).defined();
var serverOrHigherAuthTypeSchema = yupString().oneOf(["server", "admin"]).defined();
var adminAuthTypeSchema = yupString().oneOf(["admin"]).defined();
var projectIdSchema = yupString().test((v) => v === void 0 || v === "internal" || isUuid(v)).meta({ openapiField: { description: _idDescription("project"), exampleValue: "e0b52f4d-dece-408c-af49-d23061bb0f8d" } });
var projectBranchIdSchema = yupString().nonEmpty().max(255).meta({ openapiField: { description: _idDescription("project branch"), exampleValue: "main" } });
var projectDisplayNameSchema = yupString().meta({ openapiField: { description: _displayNameDescription("project"), exampleValue: "MyMusic" } });
var projectDescriptionSchema = yupString().nullable().meta({ openapiField: { description: "A human readable description of the project", exampleValue: "A music streaming service" } });
var projectCreatedAtMillisSchema = yupNumber().meta({ openapiField: { description: _createdAtMillisDescription("project"), exampleValue: 163e10 } });
var projectUserCountSchema = yupNumber().meta({ openapiField: { description: "The number of users in this project", exampleValue: 10 } });
var projectIsProductionModeSchema = yupBoolean().meta({ openapiField: { description: "Whether the project is in production mode", exampleValue: true } });
var projectConfigIdSchema = yupString().meta({ openapiField: { description: _idDescription("project config"), exampleValue: "d09201f0-54f5-40bd-89ff-6d1815ddad24" } });
var projectAllowLocalhostSchema = yupBoolean().meta({ openapiField: { description: "Whether localhost is allowed as a domain for this project. Should only be allowed in development mode", exampleValue: true } });
var projectCreateTeamOnSignUpSchema = yupBoolean().meta({ openapiField: { description: "Whether a team should be created for each user that signs up", exampleValue: true } });
var projectMagicLinkEnabledSchema = yupBoolean().meta({ openapiField: { description: "Whether magic link authentication is enabled for this project", exampleValue: true } });
var projectPasskeyEnabledSchema = yupBoolean().meta({ openapiField: { description: "Whether passkey authentication is enabled for this project", exampleValue: true } });
var projectClientTeamCreationEnabledSchema = yupBoolean().meta({ openapiField: { description: "Whether client users can create teams", exampleValue: true } });
var projectClientUserDeletionEnabledSchema = yupBoolean().meta({ openapiField: { description: "Whether client users can delete their own account from the client", exampleValue: true } });
var projectSignUpEnabledSchema = yupBoolean().meta({ openapiField: { description: "Whether users can sign up new accounts, or whether they are only allowed to sign in to existing accounts. Regardless of this option, the server API can always create new users with the `POST /users` endpoint.", exampleValue: true } });
var projectCredentialEnabledSchema = yupBoolean().meta({ openapiField: { description: "Whether email password authentication is enabled for this project", exampleValue: true } });
var oauthIdSchema = yupString().oneOf(allProviders).meta({ openapiField: { description: `OAuth provider ID, one of ${allProviders.map((x) => `\`${x}\``).join(", ")}`, exampleValue: "google" } });
var oauthEnabledSchema = yupBoolean().meta({ openapiField: { description: "Whether the OAuth provider is enabled. If an provider is first enabled, then disabled, it will be shown in the list but with enabled=false", exampleValue: true } });
var oauthTypeSchema = yupString().oneOf(["shared", "standard"]).meta({ openapiField: { description: 'OAuth provider type, one of shared, standard. "shared" uses Stack shared OAuth keys and it is only meant for development. "standard" uses your own OAuth keys and will show your logo and company name when signing in with the provider.', exampleValue: "standard" } });
var oauthClientIdSchema = yupString().meta({ openapiField: { description: 'OAuth client ID. Needs to be specified when using type="standard"', exampleValue: "google-oauth-client-id" } });
var oauthClientSecretSchema = yupString().meta({ openapiField: { description: 'OAuth client secret. Needs to be specified when using type="standard"', exampleValue: "google-oauth-client-secret" } });
var oauthFacebookConfigIdSchema = yupString().meta({ openapiField: { description: "The configuration id for Facebook business login (for things like ads and marketing). This is only required if you are using the standard OAuth with Facebook and you are using Facebook business login." } });
var oauthMicrosoftTenantIdSchema = yupString().meta({ openapiField: { description: "The Microsoft tenant id for Microsoft directory. This is only required if you are using the standard OAuth with Microsoft and you have an Azure AD tenant." } });
var oauthAccountMergeStrategySchema = yupString().oneOf(["link_method", "raise_error", "allow_duplicates"]).meta({ openapiField: { description: "Determines how to handle OAuth logins that match an existing user by email. `link_method` adds the OAuth method to the existing user. `raise_error` rejects the login with an error. `allow_duplicates` creates a new user.", exampleValue: "link_method" } });
var emailTypeSchema = yupString().oneOf(["shared", "standard"]).meta({ openapiField: { description: 'Email provider type, one of shared, standard. "shared" uses Stack shared email provider and it is only meant for development. "standard" uses your own email server and will have your email address as the sender.', exampleValue: "standard" } });
var emailSenderNameSchema = yupString().meta({ openapiField: { description: 'Email sender name. Needs to be specified when using type="standard"', exampleValue: "Stack" } });
var emailHostSchema = yupString().meta({ openapiField: { description: 'Email host. Needs to be specified when using type="standard"', exampleValue: "smtp.your-domain.com" } });
var emailPortSchema = yupNumber().min(0).max(65535).meta({ openapiField: { description: 'Email port. Needs to be specified when using type="standard"', exampleValue: 587 } });
var emailUsernameSchema = yupString().meta({ openapiField: { description: 'Email username. Needs to be specified when using type="standard"', exampleValue: "smtp-email" } });
var emailSenderEmailSchema = emailSchema.meta({ openapiField: { description: 'Email sender email. Needs to be specified when using type="standard"', exampleValue: "example@your-domain.com" } });
var emailPasswordSchema = passwordSchema.meta({ openapiField: { description: 'Email password. Needs to be specified when using type="standard"', exampleValue: "your-email-password" } });
var handlerPathSchema = yupString().test("is-handler-path", "Handler path must start with /", (value) => value?.startsWith("/")).meta({ openapiField: { description: 'Handler path. If you did not setup a custom handler path, it should be "/handler" by default. It needs to start with /', exampleValue: "/handler" } });
var ReplaceFieldWithOwnUserId = class extends Error {
constructor(path) {
super(`This error should be caught by whoever validated the schema, and the field in the path '${path}' should be replaced with the current user's id. This is a workaround to yup not providing access to the context inside the transform function.`);
this.path = path;
}
};
var userIdMeSentinelUuid = "cad564fd-f81b-43f4-b390-98abf3fcc17e";
var userIdOrMeSchema = yupString().uuid().transform((v) => {
if (v === "me") return userIdMeSentinelUuid;
else return v;
}).test((v, context) => {
if (!("stackAllowUserIdMe" in (context.options.context ?? {}))) throw new StackAssertionError("userIdOrMeSchema is not allowed in this context. Make sure you're using yupValidate from schema-fields.ts to validate, instead of schema.validate(...).");
if (!context.options.context?.stackAllowUserIdMe) throw new StackAssertionError("userIdOrMeSchema is not allowed in this context. Make sure you're passing in the currentUserId option in yupValidate.");
if (v === userIdMeSentinelUuid) throw new ReplaceFieldWithOwnUserId(context.path);
return true;
}).meta({ openapiField: { description: "The ID of the user, or the special value `me` for the currently authenticated user", exampleValue: "3241a285-8329-4d69-8f3d-316e08cf140c" } });
var userIdSchema = yupString().uuid().meta({ openapiField: { description: _idDescription("user"), exampleValue: "3241a285-8329-4d69-8f3d-316e08cf140c" } });
var primaryEmailSchema = emailSchema.meta({ openapiField: { description: "Primary email", exampleValue: "johndoe@example.com" } });
var primaryEmailAuthEnabledSchema = yupBoolean().meta({ openapiField: { description: "Whether the primary email is used for authentication. If this is set to `false`, the user will not be able to sign in with the primary email with password or OTP", exampleValue: true } });
var primaryEmailVerifiedSchema = yupBoolean().meta({ openapiField: { description: "Whether the primary email has been verified to belong to this user", exampleValue: true } });
var userDisplayNameSchema = yupString().nullable().meta({ openapiField: { description: _displayNameDescription("user"), exampleValue: "John Doe" } });
var selectedTeamIdSchema = yupString().uuid().meta({ openapiField: { description: "ID of the team currently selected by the user", exampleValue: "team-id" } });
var profileImageUrlSchema = urlSchema.max(1e6).meta({ openapiField: { description: _profileImageUrlDescription("user"), exampleValue: "https://example.com/image.jpg" } });
var signedUpAtMillisSchema = yupNumber().meta({ openapiField: { description: _signedUpAtMillisDescription, exampleValue: 163e10 } });
var userClientMetadataSchema = jsonSchema.meta({ openapiField: { description: _clientMetaDataDescription("user"), exampleValue: { key: "value" } } });
var userClientReadOnlyMetadataSchema = jsonSchema.meta({ openapiField: { description: _clientReadOnlyMetaDataDescription("user"), exampleValue: { key: "value" } } });
var userServerMetadataSchema = jsonSchema.meta({ openapiField: { description: _serverMetaDataDescription("user"), exampleValue: { key: "value" } } });
var userOAuthProviderSchema = yupObject({
id: yupString().defined(),
type: yupString().oneOf(allProviders).defined(),
provider_user_id: yupString().defined()
});
var userLastActiveAtMillisSchema = yupNumber().nullable().meta({ openapiField: { description: _lastActiveAtMillisDescription, exampleValue: 163e10 } });
var userPasskeyAuthEnabledSchema = yupBoolean().meta({ openapiField: { hidden: true, description: "Whether the user has passkeys enabled", exampleValue: false } });
var userOtpAuthEnabledSchema = yupBoolean().meta({ openapiField: { hidden: true, description: "Whether the user has OTP/magic link enabled. ", exampleValue: true } });
var userOtpAuthEnabledMutationSchema = yupBoolean().meta({ openapiField: { hidden: true, description: "Whether the user has OTP/magic link enabled. Note that only accounts with verified emails can sign-in with OTP.", exampleValue: true } });
var userHasPasswordSchema = yupBoolean().meta({ openapiField: { hidden: true, description: "Whether the user has a password set. If the user does not have a password set, they will not be able to sign in with email/password.", exampleValue: true } });
var userPasswordMutationSchema = passwordSchema.nullable().meta({ openapiField: { description: "Sets the user's password. Doing so revokes all current sessions.", exampleValue: "my-new-password" } }).max(70);
var userPasswordHashMutationSchema = yupString().nonEmpty().meta({ openapiField: { description: "If `password` is not given, sets the user's password hash to the given string in Modular Crypt Format (ex.: `$2a$10$VIhIOofSMqGdGlL4wzE//e.77dAQGqNtF/1dT7bqCrVtQuInWy2qi`). Doing so revokes all current sessions." } });
var userTotpSecretMutationSchema = base64Schema.nullable().meta({ openapiField: { description: "Enables 2FA and sets a TOTP secret for the user. Set to null to disable 2FA.", exampleValue: "dG90cC1zZWNyZXQ=" } });
var signInEmailSchema = strictEmailSchema(void 0).meta({ openapiField: { description: "The email to sign in with.", exampleValue: "johndoe@example.com" } });
var emailOtpSignInCallbackUrlSchema = urlSchema.meta({ openapiField: { description: "The base callback URL to construct the magic link from. A query parameter `code` with the verification code will be appended to it. The page should then make a request to the `/auth/otp/sign-in` endpoint.", exampleValue: "https://example.com/handler/magic-link-callback" } });
var emailVerificationCallbackUrlSchema = urlSchema.meta({ openapiField: { description: "The base callback URL to construct a verification link for the verification e-mail. A query parameter `code` with the verification code will be appended to it. The page should then make a request to the `/contact-channels/verify` endpoint.", exampleValue: "https://example.com/handler/email-verification" } });
var accessTokenResponseSchema = yupString().meta({ openapiField: { description: "Short-lived access token that can be used to authenticate the user", exampleValue: "eyJhmMiJB2TO...diI4QT" } });
var refreshTokenResponseSchema = yupString().meta({ openapiField: { description: "Long-lived refresh token that can be used to obtain a new access token", exampleValue: "i8ns3aq2...14y" } });
var signInResponseSchema = yupObject({
refresh_token: refreshTokenResponseSchema.defined(),
access_token: accessTokenResponseSchema.defined(),
is_new_user: yupBoolean().meta({ openapiField: { description: "Whether the user is a new user", exampleValue: true } }).defined(),
user_id: userIdSchema.defined()
});
var teamSystemPermissions = [
"$update_team",
"$delete_team",
"$read_members",
"$remove_members",
"$invite_members",
"$manage_api_keys"
];
var permissionDefinitionIdSchema = yupString().matches(/^\$?[a-z0-9_:]+$/, 'Only lowercase letters, numbers, ":", "_" and optional "$" at the beginning are allowed').test("is-system-permission", "System permissions must start with a dollar sign", (value, ctx) => {
if (!value) return true;
if (value.startsWith("$") && !teamSystemPermissions.includes(value)) {
return ctx.createError({ message: "Invalid system permission" });
}
return true;
}).meta({ openapiField: { description: `The permission ID used to uniquely identify a permission. Can either be a custom permission with lowercase letters, numbers, \`:\`, and \`_\` characters, or one of the system permissions: ${teamSystemPermissions.map((x) => `\`${x}\``).join(", ")}`, exampleValue: "read_secret_info" } });
var customPermissionDefinitionIdSchema = yupString().matches(/^[a-z0-9_:]+$/, 'Only lowercase letters, numbers, ":", "_" are allowed').meta({ openapiField: { description: 'The permission ID used to uniquely identify a permission. Can only contain lowercase letters, numbers, ":", and "_" characters', exampleValue: "read_secret_info" } });
var teamPermissionDescriptionSchema = yupString().meta({ openapiField: { description: "A human-readable description of the permission", exampleValue: "Read secret information" } });
var containedPermissionIdsSchema = yupArray(permissionDefinitionIdSchema.defined()).meta({ openapiField: { description: "The IDs of the permissions that are contained in this permission", exampleValue: ["read_public_info"] } });
var teamIdSchema = yupString().uuid().meta({ openapiField: { description: _idDescription("team"), exampleValue: "ad962777-8244-496a-b6a2-e0c6a449c79e" } });
var teamDisplayNameSchema = yupString().meta({ openapiField: { description: _displayNameDescription("team"), exampleValue: "My Team" } });
var teamProfileImageUrlSchema = urlSchema.max(1e6).meta({ openapiField: { description: _profileImageUrlDescription("team"), exampleValue: "https://example.com/image.jpg" } });
var teamClientMetadataSchema = jsonSchema.meta({ openapiField: { description: _clientMetaDataDescription("team"), exampleValue: { key: "value" } } });
var teamClientReadOnlyMetadataSchema = jsonSchema.meta({ openapiField: { description: _clientReadOnlyMetaDataDescription("team"), exampleValue: { key: "value" } } });
var teamServerMetadataSchema = jsonSchema.meta({ openapiField: { description: _serverMetaDataDescription("team"), exampleValue: { key: "value" } } });
var teamCreatedAtMillisSchema = yupNumber().meta({ openapiField: { description: _createdAtMillisDescription("team"), exampleValue: 163e10 } });
var teamInvitationEmailSchema = emailSchema.meta({ openapiField: { description: "The email of the user to invite.", exampleValue: "johndoe@example.com" } });
var teamInvitationCallbackUrlSchema = urlSchema.meta({ openapiField: { description: "The base callback URL to construct an invite link with. A query parameter `code` with the verification code will be appended to it. The page should then make a request to the `/team-invitations/accept` endpoint.", exampleValue: "https://example.com/handler/team-invitation" } });
var teamCreatorUserIdSchema = userIdOrMeSchema.meta({ openapiField: { description: 'The ID of the creator of the team. If not specified, the user will not be added to the team. Can be either "me" or the ID of the user. Only used on the client side.', exampleValue: "me" } });
var teamMemberDisplayNameSchema = yupString().meta({ openapiField: { description: _displayNameDescription("team member") + " Note that this is separate from the display_name of the user.", exampleValue: "John Doe" } });
var teamMemberProfileImageUrlSchema = urlSchema.max(1e6).meta({ openapiField: { description: _profileImageUrlDescription("team member"), exampleValue: "https://example.com/image.jpg" } });
var contactChannelIdSchema = yupString().uuid().meta({ openapiField: { description: _idDescription("contact channel"), exampleValue: "b3d396b8-c574-4c80-97b3-50031675ceb2" } });
var contactChannelTypeSchema = yupString().oneOf(["email"]).meta({ openapiField: { description: `The type of the contact channel. Currently only "email" is supported.`, exampleValue: "email" } });
var contactChannelValueSchema = yupString().when("type", {
is: "email",
then: (schema) => schema.email()
}).meta({ openapiField: { description: "The value of the contact channel. For email, this should be a valid email address.", exampleValue: "johndoe@example.com" } });
var contactChannelUsedForAuthSchema = yupBoolean().meta({ openapiField: { description: "Whether the contact channel is used for authentication. If this is set to `true`, the user will be able to sign in with the contact channel with password or OTP.", exampleValue: true } });
var contactChannelIsVerifiedSchema = yupBoolean().meta({ openapiField: { description: "Whether the contact channel has been verified. If this is set to `true`, the contact channel has been verified to belong to the user.", exampleValue: true } });
var contactChannelIsPrimarySchema = yupBoolean().meta({ openapiField: { description: "Whether the contact channel is the primary contact channel. If this is set to `true`, it will be used for authentication and notifications by default.", exampleValue: true } });
var basicAuthorizationHeaderSchema = yupString().test("is-basic-authorization-header", 'Authorization header must be in the format "Basic <base64>"', (value) => {
if (!value) return true;
return decodeBasicAuthorizationHeader(value) !== null;
});
var neonAuthorizationHeaderSchema = basicAuthorizationHeaderSchema.test("is-neon-authorization-header", "Invalid client_id:client_secret values; did you use the correct values for the Neon integration?", (value) => {
if (!value) return true;
const [clientId, clientSecret] = decodeBasicAuthorizationHeader(value) ?? throwErr(`Neon authz header invalid? This should've been validated by basicAuthorizationHeaderSchema: ${value}`);
for (const neonClientConfig of JSON.parse(process.env.STACK_NEON_INTEGRATION_CLIENTS_CONFIG || "[]")) {
if (clientId === neonClientConfig.client_id && clientSecret === neonClientConfig.client_secret) return true;
}
return false;
});
function yupDefinedWhen(schema, triggers) {
const entries = Object.entries(triggers);
return schema.when(entries.map(([key]) => key), {
is: (...values) => entries.every(([key, value], index) => value === values[index]),
then: (schema2) => schema2.defined(),
otherwise: (schema2) => schema2.optional()
});
}
function yupDefinedAndNonEmptyWhen(schema, triggers) {
const entries = Object.entries(triggers);
return schema.when(entries.map(([key]) => key), {
is: (...values) => entries.every(([key, value], index) => value === values[index]),
then: (schema2) => schema2.defined().nonEmpty(),
otherwise: (schema2) => schema2.optional()
});
}
export {
ReplaceFieldWithOwnUserId,
accessTokenResponseSchema,
adaptSchema,
adminAuthTypeSchema,
base64Schema,
basicAuthorizationHeaderSchema,
clientOrHigherAuthTypeSchema,
contactChannelIdSchema,
contactChannelIsPrimarySchema,
contactChannelIsVerifiedSchema,
contactChannelTypeSchema,
contactChannelUsedForAuthSchema,
contactChannelValueSchema,
containedPermissionIdsSchema,
customPermissionDefinitionIdSchema,
emailHostSchema,
emailOtpSignInCallbackUrlSchema,
emailPasswordSchema,
emailPortSchema,
emailSchema,
emailSenderEmailSchema,
emailSenderNameSchema,
emailTypeSchema,
emailUsernameSchema,
emailVerificationCallbackUrlSchema,
ensureObjectSchema,
handlerPathSchema,
jsonSchema,
jsonStringOrEmptySchema,
jsonStringSchema,
neonAuthorizationHeaderSchema,
oauthAccountMergeStrategySchema,
oauthClientIdSchema,
oauthClientSecretSchema,
oauthEnabledSchema,
oauthFacebookConfigIdSchema,
oauthIdSchema,
oauthMicrosoftTenantIdSchema,
oauthTypeSchema,
passwordSchema,
permissionDefinitionIdSchema,
primaryEmailAuthEnabledSchema,
primaryEmailSchema,
primaryEmailVerifiedSchema,
profileImageUrlSchema,
projectAllowLocalhostSchema,
projectBranchIdSchema,
projectClientTeamCreationEnabledSchema,
projectClientUserDeletionEnabledSchema,
projectConfigIdSchema,
projectCreateTeamOnSignUpSchema,
projectCreatedAtMillisSchema,
projectCredentialEnabledSchema,
projectDescriptionSchema,
projectDisplayNameSchema,
projectIdSchema,
projectIsProductionModeSchema,
projectMagicLinkEnabledSchema,
projectPasskeyEnabledSchema,
projectSignUpEnabledSchema,
projectUserCountSchema,
refreshTokenResponseSchema,
selectedTeamIdSchema,
serverOrHigherAuthTypeSchema,
signInEmailSchema,
signInResponseSchema,
signedUpAtMillisSchema,
strictEmailSchema,
teamClientMetadataSchema,
teamClientReadOnlyMetadataSchema,
teamCreatedAtMillisSchema,
teamCreatorUserIdSchema,
teamDisplayNameSchema,
teamIdSchema,
teamInvitationCallbackUrlSchema,
teamInvitationEmailSchema,
teamMemberDisplayNameSchema,
teamMemberProfileImageUrlSchema,
teamPermissionDescriptionSchema,
teamProfileImageUrlSchema,
teamServerMetadataSchema,
teamSystemPermissions,
urlSchema,
userClientMetadataSchema,
userClientReadOnlyMetadataSchema,
userDisplayNameSchema,
userHasPasswordSchema,
userIdOrMeSchema,
userIdSchema,
userLastActiveAtMillisSchema,
userOAuthProviderSchema,
userOtpAuthEnabledMutationSchema,
userOtpAuthEnabledSchema,
userPasskeyAuthEnabledSchema,
userPasswordHashMutationSchema,
userPasswordMutationSchema,
userServerMetadataSchema,
userTotpSecretMutationSchema,
yupArray,
yupBoolean,
yupDate,
yupDefinedAndNonEmptyWhen,
yupDefinedWhen,
yupMixed,
yupNever,
yupNumber,
yupObject,
yupRecord,
yupString,
yupTuple,
yupUnion,
yupValidate
};
//# sourceMappingURL=schema-fields.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,168 @@
// src/sessions.ts
import * as jose from "jose";
import { StackAssertionError } from "./utils/errors";
import { Store } from "./utils/stores";
var AccessToken = class {
constructor(token) {
this.token = token;
if (token === "undefined") {
throw new StackAssertionError("Access token is the string 'undefined'; it's unlikely this is the correct value. They're supposed to be unguessable!");
}
}
get decoded() {
return jose.decodeJwt(this.token);
}
get expiresAt() {
const { exp } = this.decoded;
if (exp === void 0) return /* @__PURE__ */ new Date(864e13);
return new Date(exp * 1e3);
}
/**
* @returns The number of milliseconds until the access token expires, or 0 if it has already expired.
*/
get expiresInMillis() {
return Math.max(0, this.expiresAt.getTime() - Date.now());
}
isExpired() {
return this.expiresInMillis <= 0;
}
};
var RefreshToken = class {
constructor(token) {
this.token = token;
if (token === "undefined") {
throw new StackAssertionError("Refresh token is the string 'undefined'; it's unlikely this is the correct value. They're supposed to be unguessable!");
}
}
};
var InternalSession = class _InternalSession {
constructor(_options) {
this._options = _options;
/**
* Whether the session as a whole is known to be invalid (ie. both access and refresh tokens are invalid). Used as a cache to avoid making multiple requests to the server (sessions never go back to being valid after being invalidated).
*
* It is possible for the access token to be invalid but the refresh token to be valid, in which case the session is
* still valid (just needs a refresh). It is also possible for the access token to be valid but the refresh token to
* be invalid, in which case the session is also valid (eg. if the refresh token is null because the user only passed
* in an access token, eg. in a server-side request handler).
*/
this._knownToBeInvalid = new Store(false);
this._refreshPromise = null;
this._accessToken = new Store(_options.accessToken ? new AccessToken(_options.accessToken) : null);
this._refreshToken = _options.refreshToken ? new RefreshToken(_options.refreshToken) : null;
if (_options.accessToken === null && _options.refreshToken === null) {
this._knownToBeInvalid.set(true);
}
this.sessionKey = _InternalSession.calculateSessionKey({ accessToken: _options.accessToken ?? null, refreshToken: _options.refreshToken });
}
static calculateSessionKey(ofTokens) {
if (ofTokens.refreshToken) {
return `refresh-${ofTokens.refreshToken}`;
} else if (ofTokens.accessToken) {
return `access-${ofTokens.accessToken}`;
} else {
return "not-logged-in";
}
}
isKnownToBeInvalid() {
return this._knownToBeInvalid.get();
}
/**
* Marks the session object as invalid, meaning that the refresh and access tokens can no longer be used.
*/
markInvalid() {
this._accessToken.set(null);
this._knownToBeInvalid.set(true);
}
onInvalidate(callback) {
return this._knownToBeInvalid.onChange(() => callback());
}
/**
* Returns the access token if it is found in the cache, fetching it otherwise.
*
* This is usually the function you want to call to get an access token. Either set `minMillisUntilExpiration` to a reasonable value, or catch errors that occur if it expires, and call `markAccessTokenExpired` to mark the token as expired if so (after which a call to this function will always refetch the token).
*
* @returns null if the session is known to be invalid, cached tokens if they exist in the cache (which may or may not be valid still), or new tokens otherwise.
*/
async getOrFetchLikelyValidTokens(minMillisUntilExpiration) {
if (minMillisUntilExpiration >= 6e4) {
throw new Error(`Required access token expiry ${minMillisUntilExpiration}ms is too long; access tokens are too short to be used for more than 60s`);
}
const accessToken = this._getPotentiallyInvalidAccessTokenIfAvailable();
if (!accessToken || accessToken.expiresInMillis < minMillisUntilExpiration) {
const newTokens = await this.fetchNewTokens();
const expiresInMillis = newTokens?.accessToken.expiresInMillis;
if (expiresInMillis && expiresInMillis < minMillisUntilExpiration) {
throw new StackAssertionError(`Required access token expiry ${minMillisUntilExpiration}ms is too long; access tokens are too short when they're generated (${expiresInMillis}ms)`);
}
return newTokens;
}
return { accessToken, refreshToken: this._refreshToken };
}
/**
* Fetches new tokens that are, at the time of fetching, guaranteed to be valid.
*
* The newly generated tokens are short-lived, so it's good practice not to rely on their validity (if possible). However, this function is useful in some cases where you only want to pass access tokens to a service, and you want to make sure said access token has the longest possible lifetime.
*
* In most cases, you should prefer `getOrFetchLikelyValidTokens`.
*
* @returns null if the session is known to be invalid, or new tokens otherwise (which, at the time of fetching, are guaranteed to be valid).
*/
async fetchNewTokens() {
const accessToken = await this._getNewlyFetchedAccessToken();
return accessToken ? { accessToken, refreshToken: this._refreshToken } : null;
}
markAccessTokenExpired(accessToken) {
if (this._accessToken.get() === accessToken) {
this._accessToken.set(null);
}
}
/**
* Note that a callback invocation with `null` does not mean the session has been invalidated; the access token may just have expired. Use `onInvalidate` to detect invalidation.
*/
onAccessTokenChange(callback) {
return this._accessToken.onChange(callback);
}
/**
* @returns An access token, which may be expired or expire soon, or null if it is known to be invalid.
*/
_getPotentiallyInvalidAccessTokenIfAvailable() {
if (!this._refreshToken) return null;
if (this.isKnownToBeInvalid()) return null;
const accessToken = this._accessToken.get();
if (accessToken && !accessToken.isExpired()) return accessToken;
return null;
}
/**
* You should prefer `_getOrFetchPotentiallyInvalidAccessToken` in almost all cases.
*
* @returns A newly fetched access token (never read from cache), or null if the session either does not represent a user or the session is invalid.
*/
async _getNewlyFetchedAccessToken() {
if (!this._refreshToken) return null;
if (this._knownToBeInvalid.get()) return null;
if (!this._refreshPromise) {
this._refreshAndSetRefreshPromise(this._refreshToken);
}
return await this._refreshPromise;
}
_refreshAndSetRefreshPromise(refreshToken) {
let refreshPromise = this._options.refreshAccessTokenCallback(refreshToken).then((accessToken) => {
if (refreshPromise === this._refreshPromise) {
this._refreshPromise = null;
this._accessToken.set(accessToken);
if (!accessToken) {
this.markInvalid();
}
}
return accessToken;
});
this._refreshPromise = refreshPromise;
}
};
export {
AccessToken,
InternalSession,
RefreshToken
};
//# sourceMappingURL=sessions.js.map

File diff suppressed because one or more lines are too long

View 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

File diff suppressed because one or more lines are too long

View 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

File diff suppressed because one or more lines are too long

View 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

View 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":[]}

View 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

View 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":[]}

View 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

View 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":[]}

View 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

File diff suppressed because one or more lines are too long

View 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

File diff suppressed because one or more lines are too long

View 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

View 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":[]}

View 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

View 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":[]}

View 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

File diff suppressed because one or more lines are too long

View 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

View 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":[]}

View 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

View 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":[]}

View 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

File diff suppressed because one or more lines are too long

View 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

View 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"]}

Some files were not shown because too many files have changed in this diff Show more