@stackframe/stack-shared 2.7.8 → 2.7.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/dist/known-errors.d.ts +2 -2
- package/dist/known-errors.js +8 -6
- package/dist/schema-fields.d.ts +5 -0
- package/dist/schema-fields.js +10 -0
- package/dist/utils/booleans.d.ts +4 -0
- package/dist/utils/booleans.js +6 -0
- package/dist/utils/fs.d.ts +4 -0
- package/dist/utils/fs.js +22 -0
- package/dist/utils/numbers.d.ts +1 -0
- package/dist/utils/numbers.js +3 -0
- package/dist/utils/strings.d.ts +1 -0
- package/dist/utils/strings.js +23 -2
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
package/dist/known-errors.d.ts
CHANGED
|
@@ -121,7 +121,7 @@ export declare const KnownErrors: {
|
|
|
121
121
|
};
|
|
122
122
|
AdminAccessTokenExpired: KnownErrorConstructor<KnownError & KnownErrorBrand<"PROJECT_AUTHENTICATION_ERROR"> & {
|
|
123
123
|
constructorArgs: [statusCode: number, humanReadableMessage: string, details?: Json | undefined];
|
|
124
|
-
} & KnownErrorBrand<"INVALID_PROJECT_AUTHENTICATION"> & KnownErrorBrand<"INVALID_ADMIN_ACCESS_TOKEN"> & KnownErrorBrand<"ADMIN_ACCESS_TOKEN_EXPIRED">, []> & {
|
|
124
|
+
} & KnownErrorBrand<"INVALID_PROJECT_AUTHENTICATION"> & KnownErrorBrand<"INVALID_ADMIN_ACCESS_TOKEN"> & KnownErrorBrand<"ADMIN_ACCESS_TOKEN_EXPIRED">, [expiredAt: Date | undefined]> & {
|
|
125
125
|
errorCode: "ADMIN_ACCESS_TOKEN_EXPIRED";
|
|
126
126
|
};
|
|
127
127
|
InvalidProjectForAdminAccessToken: KnownErrorConstructor<KnownError & KnownErrorBrand<"PROJECT_AUTHENTICATION_ERROR"> & {
|
|
@@ -194,7 +194,7 @@ export declare const KnownErrors: {
|
|
|
194
194
|
};
|
|
195
195
|
AccessTokenExpired: KnownErrorConstructor<KnownError & KnownErrorBrand<"SESSION_AUTHENTICATION_ERROR"> & {
|
|
196
196
|
constructorArgs: [statusCode: number, humanReadableMessage: string, details?: Json | undefined];
|
|
197
|
-
} & KnownErrorBrand<"INVALID_SESSION_AUTHENTICATION"> & KnownErrorBrand<"INVALID_ACCESS_TOKEN"> & KnownErrorBrand<"ACCESS_TOKEN_EXPIRED">, []> & {
|
|
197
|
+
} & KnownErrorBrand<"INVALID_SESSION_AUTHENTICATION"> & KnownErrorBrand<"INVALID_ACCESS_TOKEN"> & KnownErrorBrand<"ACCESS_TOKEN_EXPIRED">, [expiredAt: Date | undefined]> & {
|
|
198
198
|
errorCode: "ACCESS_TOKEN_EXPIRED";
|
|
199
199
|
};
|
|
200
200
|
InvalidProjectForAccessToken: KnownErrorConstructor<KnownError & KnownErrorBrand<"SESSION_AUTHENTICATION_ERROR"> & {
|
package/dist/known-errors.js
CHANGED
|
@@ -171,10 +171,11 @@ const UnparsableAdminAccessToken = createKnownErrorConstructor(InvalidAdminAcces
|
|
|
171
171
|
401,
|
|
172
172
|
"Admin access token is not parsable.",
|
|
173
173
|
], () => []);
|
|
174
|
-
const AdminAccessTokenExpired = createKnownErrorConstructor(InvalidAdminAccessToken, "ADMIN_ACCESS_TOKEN_EXPIRED", () => [
|
|
174
|
+
const AdminAccessTokenExpired = createKnownErrorConstructor(InvalidAdminAccessToken, "ADMIN_ACCESS_TOKEN_EXPIRED", (expiredAt) => [
|
|
175
175
|
401,
|
|
176
|
-
|
|
177
|
-
|
|
176
|
+
`Admin access token has expired. Please refresh it and try again.${expiredAt ? ` (The access token expired at ${expiredAt.toISOString()}.)` : ""}`,
|
|
177
|
+
{ expired_at_millis: expiredAt?.getTime() ?? null },
|
|
178
|
+
], (json) => [json.expired_at_millis ?? undefined]);
|
|
178
179
|
const InvalidProjectForAdminAccessToken = createKnownErrorConstructor(InvalidAdminAccessToken, "INVALID_PROJECT_FOR_ADMIN_ACCESS_TOKEN", () => [
|
|
179
180
|
401,
|
|
180
181
|
"Admin access tokens must be created on the internal project.",
|
|
@@ -240,10 +241,11 @@ const UnparsableAccessToken = createKnownErrorConstructor(InvalidAccessToken, "U
|
|
|
240
241
|
401,
|
|
241
242
|
"Access token is not parsable.",
|
|
242
243
|
], () => []);
|
|
243
|
-
const AccessTokenExpired = createKnownErrorConstructor(InvalidAccessToken, "ACCESS_TOKEN_EXPIRED", () => [
|
|
244
|
+
const AccessTokenExpired = createKnownErrorConstructor(InvalidAccessToken, "ACCESS_TOKEN_EXPIRED", (expiredAt) => [
|
|
244
245
|
401,
|
|
245
|
-
|
|
246
|
-
|
|
246
|
+
`Access token has expired. Please refresh it and try again.${expiredAt ? ` (The access token expired at ${expiredAt.toISOString()}.)` : ""}`,
|
|
247
|
+
{ expired_at_millis: expiredAt?.getTime() ?? null },
|
|
248
|
+
], (json) => [json.expired_at_millis ?? undefined]);
|
|
247
249
|
const InvalidProjectForAccessToken = createKnownErrorConstructor(InvalidAccessToken, "INVALID_PROJECT_FOR_ACCESS_TOKEN", () => [
|
|
248
250
|
401,
|
|
249
251
|
"Access token not valid for this project.",
|
package/dist/schema-fields.d.ts
CHANGED
|
@@ -4,6 +4,10 @@ declare module "yup" {
|
|
|
4
4
|
nonEmpty(message?: string): StringSchema<TType, TContext, TDefault, TFlags>;
|
|
5
5
|
empty(): StringSchema<TType, TContext, TDefault, TFlags>;
|
|
6
6
|
}
|
|
7
|
+
interface Schema<TType, TContext, TDefault, TFlags> {
|
|
8
|
+
getNested<K extends keyof TType>(path: K): yup.Schema<TType[K], TContext, TDefault, TFlags>;
|
|
9
|
+
concat<U extends yup.AnySchema>(schema: U): yup.Schema<Omit<TType, keyof yup.InferType<U>> & yup.InferType<U>, TContext, TDefault, TFlags>;
|
|
10
|
+
}
|
|
7
11
|
}
|
|
8
12
|
export declare function yupValidate<S extends yup.ISchema<any>>(schema: S, obj: unknown, options?: yup.ValidateOptions & {
|
|
9
13
|
currentUserId?: string | null;
|
|
@@ -23,6 +27,7 @@ export declare function yupTuple<T extends [unknown, ...unknown[]]>(...args: Par
|
|
|
23
27
|
export declare function yupObject<A extends yup.Maybe<yup.AnyObject>, B extends yup.ObjectShape>(...args: Parameters<typeof yup.object<A, B>>): yup.ObjectSchema<yup.TypeFromShape<B, yup.AnyObject> extends infer T ? T extends yup.TypeFromShape<B, yup.AnyObject> ? T extends {} ? { [k in keyof T]: T[k]; } : T : never : never, yup.AnyObject, yup.DefaultFromShape<B> extends infer T_1 ? T_1 extends yup.DefaultFromShape<B> ? T_1 extends {} ? { [k_1 in keyof T_1]: T_1[k_1]; } : T_1 : never : never, "">;
|
|
24
28
|
export declare function yupNever(): yup.MixedSchema<never>;
|
|
25
29
|
export declare function yupUnion<T extends yup.ISchema<any>[]>(...args: T): yup.MixedSchema<yup.InferType<T[number]>>;
|
|
30
|
+
export declare function ensureObjectSchema<T extends yup.AnyObject>(schema: yup.Schema<T>): yup.ObjectSchema<T> & typeof schema;
|
|
26
31
|
export declare const adaptSchema: yup.MixedSchema<typeof StackAdaptSentinel | undefined, yup.AnyObject, undefined, "">;
|
|
27
32
|
/**
|
|
28
33
|
* Yup's URL schema does not recognize some URLs (including `http://localhost`) as a valid URL. This schema is a workaround for that.
|
package/dist/schema-fields.js
CHANGED
|
@@ -13,6 +13,11 @@ yup.addMethod(yup.string, "nonEmpty", function (message) {
|
|
|
13
13
|
return value !== "";
|
|
14
14
|
});
|
|
15
15
|
});
|
|
16
|
+
yup.addMethod(yup.Schema, "getNested", function (path) {
|
|
17
|
+
if (!path.match(/^[a-zA-Z_][a-zA-Z0-9_]*$/))
|
|
18
|
+
throw new StackAssertionError(`yupSchema.getNested can currently only be used with alphanumeric keys. Fix this in the future. Provided key: ${path}`);
|
|
19
|
+
return yup.reach(this, path);
|
|
20
|
+
});
|
|
16
21
|
export async function yupValidate(schema, obj, options) {
|
|
17
22
|
try {
|
|
18
23
|
return await schema.validate(obj, {
|
|
@@ -155,6 +160,11 @@ export function yupUnion(...args) {
|
|
|
155
160
|
});
|
|
156
161
|
});
|
|
157
162
|
}
|
|
163
|
+
export function ensureObjectSchema(schema) {
|
|
164
|
+
if (!(schema instanceof yup.ObjectSchema))
|
|
165
|
+
throw new StackAssertionError(`assertObjectSchema: schema is not an ObjectSchema: ${schema.describe().type}`);
|
|
166
|
+
return schema;
|
|
167
|
+
}
|
|
158
168
|
// Common
|
|
159
169
|
export const adaptSchema = yupMixed();
|
|
160
170
|
/**
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export type Truthy<T> = T extends null | undefined | 0 | "" | false ? false : true;
|
|
2
|
+
export type Falsy<T> = T extends null | undefined | 0 | "" | false ? true : false;
|
|
3
|
+
export declare function isTruthy<T>(value: T): value is T & Truthy<T>;
|
|
4
|
+
export declare function isFalsy<T>(value: T): value is T & Falsy<T>;
|
package/dist/utils/fs.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as stackFs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
export async function list(path) {
|
|
4
|
+
return await stackFs.promises.readdir(path);
|
|
5
|
+
}
|
|
6
|
+
export async function listRecursively(p, options = {}) {
|
|
7
|
+
const files = await list(p);
|
|
8
|
+
return [
|
|
9
|
+
...(await Promise.all(files.map(async (fileName) => {
|
|
10
|
+
const filePath = path.join(p, fileName);
|
|
11
|
+
if ((await stackFs.promises.stat(filePath)).isDirectory()) {
|
|
12
|
+
return [
|
|
13
|
+
...(await listRecursively(filePath, options)),
|
|
14
|
+
...(options.excludeDirectories ? [] : [filePath]),
|
|
15
|
+
];
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
return [filePath];
|
|
19
|
+
}
|
|
20
|
+
}))).flat(),
|
|
21
|
+
];
|
|
22
|
+
}
|
package/dist/utils/numbers.d.ts
CHANGED
package/dist/utils/numbers.js
CHANGED
package/dist/utils/strings.d.ts
CHANGED
|
@@ -45,6 +45,7 @@ export declare function deindent(code: string): string;
|
|
|
45
45
|
export declare function deindent(strings: TemplateStringsArray | readonly string[], ...values: any[]): string;
|
|
46
46
|
export declare function extractScopes(scope: string, removeDuplicates?: boolean): string[];
|
|
47
47
|
export declare function mergeScopeStrings(...scopes: string[]): string;
|
|
48
|
+
export declare function escapeTemplateLiteral(s: string): string;
|
|
48
49
|
export type Nicifiable = {
|
|
49
50
|
getNicifiableKeys?(): PropertyKey[];
|
|
50
51
|
getNicifiedObjectExtraLines?(): string[];
|
package/dist/utils/strings.js
CHANGED
|
@@ -103,15 +103,20 @@ export function deindent(strings, ...values) {
|
|
|
103
103
|
return templateIdentity(deindentedStrings, ...indentedValues);
|
|
104
104
|
}
|
|
105
105
|
export function extractScopes(scope, removeDuplicates = true) {
|
|
106
|
+
// TODO what is this for? can we move this into the OAuth code in the backend?
|
|
106
107
|
const trimmedString = scope.trim();
|
|
107
108
|
const scopesArray = trimmedString.split(/\s+/);
|
|
108
109
|
const filtered = scopesArray.filter(scope => scope.length > 0);
|
|
109
110
|
return removeDuplicates ? [...new Set(filtered)] : filtered;
|
|
110
111
|
}
|
|
111
112
|
export function mergeScopeStrings(...scopes) {
|
|
113
|
+
// TODO what is this for? can we move this into the OAuth code in the backend?
|
|
112
114
|
const allScope = scopes.map((s) => extractScopes(s)).flat().join(" ");
|
|
113
115
|
return extractScopes(allScope).join(" ");
|
|
114
116
|
}
|
|
117
|
+
export function escapeTemplateLiteral(s) {
|
|
118
|
+
return s.replaceAll("`", "\\`").replaceAll("\\", "\\\\").replaceAll("$", "\\$");
|
|
119
|
+
}
|
|
115
120
|
/**
|
|
116
121
|
* Some classes have different constructor names in different environments (eg. `Headers` is sometimes called `_Headers`,
|
|
117
122
|
* so we create an object of overrides to handle these cases.
|
|
@@ -165,11 +170,27 @@ export function nicify(value, options = {}) {
|
|
|
165
170
|
});
|
|
166
171
|
};
|
|
167
172
|
switch (typeof value) {
|
|
168
|
-
case "string":
|
|
169
173
|
case "boolean":
|
|
170
174
|
case "number": {
|
|
171
175
|
return JSON.stringify(value);
|
|
172
176
|
}
|
|
177
|
+
case "string": {
|
|
178
|
+
const isDeindentable = (v) => deindent(v) === v && v.includes("\n");
|
|
179
|
+
const wrapInDeindent = (v) => deindent `
|
|
180
|
+
deindent\`
|
|
181
|
+
${currentIndent + lineIndent}${escapeTemplateLiteral(value).replaceAll("\n", nl + lineIndent)}
|
|
182
|
+
${currentIndent}\`
|
|
183
|
+
`;
|
|
184
|
+
if (isDeindentable(value)) {
|
|
185
|
+
return wrapInDeindent(value);
|
|
186
|
+
}
|
|
187
|
+
else if (value.endsWith("\n") && isDeindentable(value.slice(0, -1))) {
|
|
188
|
+
return wrapInDeindent(value.slice(0, -1)) + ' + "\\n"';
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
return JSON.stringify(value);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
173
194
|
case "undefined": {
|
|
174
195
|
return "undefined";
|
|
175
196
|
}
|
|
@@ -205,7 +226,7 @@ export function nicify(value, options = {}) {
|
|
|
205
226
|
}
|
|
206
227
|
}
|
|
207
228
|
if (value instanceof URL) {
|
|
208
|
-
return `URL(${
|
|
229
|
+
return `URL(${nicify(value.toString())})`;
|
|
209
230
|
}
|
|
210
231
|
if (ArrayBuffer.isView(value)) {
|
|
211
232
|
return `${value.constructor.name}([${value.toString()}])`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stackframe/stack-shared",
|
|
3
|
-
"version": "2.7.
|
|
3
|
+
"version": "2.7.9",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"oauth4webapi": "^2.10.3",
|
|
52
52
|
"semver": "^7.6.3",
|
|
53
53
|
"uuid": "^9.0.1",
|
|
54
|
-
"@stackframe/stack-sc": "2.7.
|
|
54
|
+
"@stackframe/stack-sc": "2.7.9"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@sentry/nextjs": "^8.40.0",
|