@stackframe/stack-shared 2.4.27 → 2.5.0
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 +17 -0
- package/dist/interface/adminInterface.d.ts +2 -0
- package/dist/interface/clientInterface.d.ts +5 -0
- package/dist/interface/clientInterface.js +10 -0
- package/dist/interface/crud/current-user.d.ts +1 -1
- package/dist/interface/serverInterface.d.ts +13 -12
- package/dist/interface/serverInterface.js +22 -12
- package/dist/known-errors.d.ts +3 -6
- package/dist/known-errors.js +19 -18
- package/dist/utils/jwt.js +3 -3
- package/dist/utils/strings.d.ts +20 -3
- package/dist/utils/strings.js +124 -14
- package/dist/utils/yup.d.ts +1 -0
- package/dist/utils/yup.js +11 -0
- package/package.json +2 -2
- package/dist/hooks/use-trigger.d.ts +0 -1
- package/dist/hooks/use-trigger.js +0 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @stackframe/stack-shared
|
|
2
2
|
|
|
3
|
+
## 2.5.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Client teams and many bugfixes
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- @stackframe/stack-sc@2.5.0
|
|
12
|
+
|
|
13
|
+
## 2.4.28
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- Bugfixes
|
|
18
|
+
- @stackframe/stack-sc@2.4.28
|
|
19
|
+
|
|
3
20
|
## 2.4.27
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
|
@@ -31,6 +31,8 @@ export type ProjectUpdateOptions = {
|
|
|
31
31
|
allowLocalhost?: boolean;
|
|
32
32
|
createTeamOnSignUp?: boolean;
|
|
33
33
|
emailConfig?: EmailConfigJson;
|
|
34
|
+
teamCreatorDefaultPermissionIds?: string[];
|
|
35
|
+
teamMemberDefaultPermissionIds?: string[];
|
|
34
36
|
};
|
|
35
37
|
};
|
|
36
38
|
export type ApiKeySetBaseJson = {
|
|
@@ -68,6 +68,8 @@ export type ProjectJson = {
|
|
|
68
68
|
emailConfig?: EmailConfigJson;
|
|
69
69
|
domains: DomainConfigJson[];
|
|
70
70
|
createTeamOnSignUp: boolean;
|
|
71
|
+
teamCreatorDefaultPermissions: PermissionDefinitionJson[];
|
|
72
|
+
teamMemberDefaultPermissions: PermissionDefinitionJson[];
|
|
71
73
|
};
|
|
72
74
|
};
|
|
73
75
|
export type OAuthProviderConfigJson = {
|
|
@@ -106,6 +108,8 @@ export type OrglikeJson = {
|
|
|
106
108
|
};
|
|
107
109
|
export type TeamJson = OrglikeJson;
|
|
108
110
|
export type OrganizationJson = OrglikeJson;
|
|
111
|
+
export type OrglikeCustomizableJson = Pick<OrglikeJson, "displayName">;
|
|
112
|
+
export type TeamCustomizableJson = OrglikeCustomizableJson;
|
|
109
113
|
export type TeamMemberJson = {
|
|
110
114
|
userId: string;
|
|
111
115
|
teamId: string;
|
|
@@ -219,6 +223,7 @@ export declare class StackClientInterface {
|
|
|
219
223
|
getAccessToken(provider: string, scope: string, session: InternalSession): Promise<{
|
|
220
224
|
accessToken: string;
|
|
221
225
|
}>;
|
|
226
|
+
createTeamForCurrentUser(data: TeamCustomizableJson, session: InternalSession): Promise<TeamJson>;
|
|
222
227
|
}
|
|
223
228
|
export declare function getProductionModeErrors(project: ProjectJson): ProductionModeError[];
|
|
224
229
|
export {};
|
|
@@ -549,6 +549,16 @@ export class StackClientInterface {
|
|
|
549
549
|
accessToken: json.accessToken,
|
|
550
550
|
};
|
|
551
551
|
}
|
|
552
|
+
async createTeamForCurrentUser(data, session) {
|
|
553
|
+
const response = await this.sendClientRequest("/current-user/teams?server=false", {
|
|
554
|
+
method: "POST",
|
|
555
|
+
headers: {
|
|
556
|
+
"content-type": "application/json",
|
|
557
|
+
},
|
|
558
|
+
body: JSON.stringify(data),
|
|
559
|
+
}, session);
|
|
560
|
+
return await response.json();
|
|
561
|
+
}
|
|
552
562
|
}
|
|
553
563
|
export function getProductionModeErrors(project) {
|
|
554
564
|
const errors = [];
|
|
@@ -2,9 +2,9 @@ import { CrudTypeOf } from "../../crud";
|
|
|
2
2
|
import * as yup from "yup";
|
|
3
3
|
export declare const currentUserCrud: import("../../crud").CrudSchemaFromOptions<{
|
|
4
4
|
clientReadSchema: yup.ObjectSchema<{
|
|
5
|
+
projectId: string;
|
|
5
6
|
displayName: string | null;
|
|
6
7
|
id: string;
|
|
7
|
-
projectId: string;
|
|
8
8
|
clientMetadata: {} | null;
|
|
9
9
|
primaryEmail: string | null;
|
|
10
10
|
primaryEmailVerified: NonNullable<boolean | undefined>;
|
|
@@ -56,31 +56,32 @@ export declare class StackServerInterface extends StackClientInterface {
|
|
|
56
56
|
createPermissionDefinition(data: ServerPermissionDefinitionCustomizableJson): Promise<ServerPermissionDefinitionJson>;
|
|
57
57
|
updatePermissionDefinition(permissionId: string, data: Partial<ServerPermissionDefinitionCustomizableJson>): Promise<void>;
|
|
58
58
|
deletePermissionDefinition(permissionId: string): Promise<void>;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
59
|
+
listServerUsers(): Promise<ServerUserJson[]>;
|
|
60
|
+
listServerTeams(): Promise<ServerTeamJson[]>;
|
|
61
|
+
listServerTeamMembers(teamId: string): Promise<ServerTeamMemberJson[]>;
|
|
62
|
+
createServerTeam(data: ServerTeamCustomizableJson): Promise<ServerTeamJson>;
|
|
63
|
+
updateServerTeam(teamId: string, data: Partial<ServerTeamCustomizableJson>): Promise<void>;
|
|
64
|
+
deleteServerTeam(teamId: string): Promise<void>;
|
|
65
|
+
addServerUserToTeam(options: {
|
|
66
66
|
userId: string;
|
|
67
67
|
teamId: string;
|
|
68
68
|
}): Promise<void>;
|
|
69
|
-
|
|
69
|
+
removeServerUserFromTeam(options: {
|
|
70
70
|
userId: string;
|
|
71
71
|
teamId: string;
|
|
72
72
|
}): Promise<void>;
|
|
73
73
|
setServerUserCustomizableData(userId: string, update: ServerUserUpdateJson): Promise<void>;
|
|
74
|
-
|
|
74
|
+
listServerTeamMemberPermissions(options: {
|
|
75
75
|
teamId: string;
|
|
76
76
|
userId: string;
|
|
77
77
|
type: 'global' | 'team';
|
|
78
78
|
direct: boolean;
|
|
79
79
|
}): Promise<ServerPermissionDefinitionJson[]>;
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
grantServerTeamUserPermission(teamId: string, userId: string, permissionId: string, type: 'global' | 'team'): Promise<void>;
|
|
81
|
+
revokeServerTeamUserPermission(teamId: string, userId: string, permissionId: string, type: 'global' | 'team'): Promise<void>;
|
|
82
|
+
deleteServerServerUser(userId: string): Promise<void>;
|
|
83
83
|
listEmailTemplates(): Promise<ListEmailTemplatesCrud['Server']['Read']>;
|
|
84
84
|
updateEmailTemplate(type: EmailTemplateType, data: EmailTemplateCrud['Server']['Update']): Promise<void>;
|
|
85
85
|
resetEmailTemplate(type: EmailTemplateType): Promise<void>;
|
|
86
|
+
createServerTeamForUser(userId: string, data: ServerTeamCustomizableJson, session: InternalSession): Promise<ServerTeamJson>;
|
|
86
87
|
}
|
|
@@ -71,20 +71,20 @@ export class StackServerInterface extends StackClientInterface {
|
|
|
71
71
|
async deletePermissionDefinition(permissionId) {
|
|
72
72
|
await this.sendServerRequest(`/permission-definitions/${permissionId}?server=true`, { method: "DELETE" }, null);
|
|
73
73
|
}
|
|
74
|
-
async
|
|
74
|
+
async listServerUsers() {
|
|
75
75
|
const response = await this.sendServerRequest("/users?server=true", {}, null);
|
|
76
76
|
return await response.json();
|
|
77
77
|
}
|
|
78
|
-
async
|
|
78
|
+
async listServerTeams() {
|
|
79
79
|
const response = await this.sendServerRequest("/teams?server=true", {}, null);
|
|
80
80
|
const json = await response.json();
|
|
81
81
|
return json;
|
|
82
82
|
}
|
|
83
|
-
async
|
|
83
|
+
async listServerTeamMembers(teamId) {
|
|
84
84
|
const response = await this.sendServerRequest(`/teams/${teamId}/users?server=true`, {}, null);
|
|
85
85
|
return await response.json();
|
|
86
86
|
}
|
|
87
|
-
async
|
|
87
|
+
async createServerTeam(data) {
|
|
88
88
|
const response = await this.sendServerRequest("/teams?server=true", {
|
|
89
89
|
method: "POST",
|
|
90
90
|
headers: {
|
|
@@ -94,7 +94,7 @@ export class StackServerInterface extends StackClientInterface {
|
|
|
94
94
|
}, null);
|
|
95
95
|
return await response.json();
|
|
96
96
|
}
|
|
97
|
-
async
|
|
97
|
+
async updateServerTeam(teamId, data) {
|
|
98
98
|
await this.sendServerRequest(`/teams/${teamId}?server=true`, {
|
|
99
99
|
method: "PUT",
|
|
100
100
|
headers: {
|
|
@@ -103,10 +103,10 @@ export class StackServerInterface extends StackClientInterface {
|
|
|
103
103
|
body: JSON.stringify(data),
|
|
104
104
|
}, null);
|
|
105
105
|
}
|
|
106
|
-
async
|
|
106
|
+
async deleteServerTeam(teamId) {
|
|
107
107
|
await this.sendServerRequest(`/teams/${teamId}?server=true`, { method: "DELETE" }, null);
|
|
108
108
|
}
|
|
109
|
-
async
|
|
109
|
+
async addServerUserToTeam(options) {
|
|
110
110
|
await this.sendServerRequest(`/teams/${options.teamId}/users/${options.userId}?server=true`, {
|
|
111
111
|
method: "POST",
|
|
112
112
|
headers: {
|
|
@@ -115,7 +115,7 @@ export class StackServerInterface extends StackClientInterface {
|
|
|
115
115
|
body: JSON.stringify({}),
|
|
116
116
|
}, null);
|
|
117
117
|
}
|
|
118
|
-
async
|
|
118
|
+
async removeServerUserFromTeam(options) {
|
|
119
119
|
await this.sendServerRequest(`/teams/${options.teamId}/users/${options.userId}?server=true`, {
|
|
120
120
|
method: "DELETE",
|
|
121
121
|
headers: {
|
|
@@ -133,11 +133,11 @@ export class StackServerInterface extends StackClientInterface {
|
|
|
133
133
|
body: JSON.stringify(update),
|
|
134
134
|
}, null);
|
|
135
135
|
}
|
|
136
|
-
async
|
|
136
|
+
async listServerTeamMemberPermissions(options) {
|
|
137
137
|
const response = await this.sendServerRequest(`/teams/${options.teamId}/users/${options.userId}/permissions?server=true&type=${options.type}&direct=${options.direct}`, {}, null);
|
|
138
138
|
return await response.json();
|
|
139
139
|
}
|
|
140
|
-
async
|
|
140
|
+
async grantServerTeamUserPermission(teamId, userId, permissionId, type) {
|
|
141
141
|
await this.sendServerRequest(`/teams/${teamId}/users/${userId}/permissions/${permissionId}?server=true`, {
|
|
142
142
|
method: "POST",
|
|
143
143
|
headers: {
|
|
@@ -146,7 +146,7 @@ export class StackServerInterface extends StackClientInterface {
|
|
|
146
146
|
body: JSON.stringify({ type }),
|
|
147
147
|
}, null);
|
|
148
148
|
}
|
|
149
|
-
async
|
|
149
|
+
async revokeServerTeamUserPermission(teamId, userId, permissionId, type) {
|
|
150
150
|
await this.sendServerRequest(`/teams/${teamId}/users/${userId}/permissions/${permissionId}?server=true`, {
|
|
151
151
|
method: "DELETE",
|
|
152
152
|
headers: {
|
|
@@ -155,7 +155,7 @@ export class StackServerInterface extends StackClientInterface {
|
|
|
155
155
|
body: JSON.stringify({ type }),
|
|
156
156
|
}, null);
|
|
157
157
|
}
|
|
158
|
-
async
|
|
158
|
+
async deleteServerServerUser(userId) {
|
|
159
159
|
await this.sendServerRequest(`/users/${userId}?server=true`, {
|
|
160
160
|
method: "DELETE",
|
|
161
161
|
headers: {
|
|
@@ -180,4 +180,14 @@ export class StackServerInterface extends StackClientInterface {
|
|
|
180
180
|
async resetEmailTemplate(type) {
|
|
181
181
|
await this.sendServerRequest(`/email-templates/${type}?server=true`, { method: "DELETE" }, null);
|
|
182
182
|
}
|
|
183
|
+
async createServerTeamForUser(userId, data, session) {
|
|
184
|
+
const response = await this.sendClientRequest(`/users/${userId}/teams?server=true`, {
|
|
185
|
+
method: "POST",
|
|
186
|
+
headers: {
|
|
187
|
+
"content-type": "application/json",
|
|
188
|
+
},
|
|
189
|
+
body: JSON.stringify(data),
|
|
190
|
+
}, session);
|
|
191
|
+
return await response.json();
|
|
192
|
+
}
|
|
183
193
|
}
|
package/dist/known-errors.d.ts
CHANGED
|
@@ -71,13 +71,13 @@ export declare const KnownErrors: {
|
|
|
71
71
|
RequestTypeWithoutProjectId: KnownErrorConstructor<KnownError & KnownErrorBrand<"PROJECT_AUTHENTICATION_ERROR"> & KnownErrorBrand<"INVALID_PROJECT_AUTHENTICATION"> & KnownErrorBrand<"REQUEST_TYPE_WITHOUT_PROJECT_ID">, [requestType: "client" | "server" | "admin"]> & {
|
|
72
72
|
errorCode: "REQUEST_TYPE_WITHOUT_PROJECT_ID";
|
|
73
73
|
};
|
|
74
|
-
InvalidPublishableClientKey: KnownErrorConstructor<KnownError & KnownErrorBrand<"PROJECT_AUTHENTICATION_ERROR"> & KnownErrorBrand<"INVALID_PROJECT_AUTHENTICATION"> & KnownErrorBrand<"INVALID_PUBLISHABLE_CLIENT_KEY">, []> & {
|
|
74
|
+
InvalidPublishableClientKey: KnownErrorConstructor<KnownError & KnownErrorBrand<"PROJECT_AUTHENTICATION_ERROR"> & KnownErrorBrand<"INVALID_PROJECT_AUTHENTICATION"> & KnownErrorBrand<"INVALID_PUBLISHABLE_CLIENT_KEY">, [projectId: string]> & {
|
|
75
75
|
errorCode: "INVALID_PUBLISHABLE_CLIENT_KEY";
|
|
76
76
|
};
|
|
77
|
-
InvalidSecretServerKey: KnownErrorConstructor<KnownError & KnownErrorBrand<"PROJECT_AUTHENTICATION_ERROR"> & KnownErrorBrand<"INVALID_PROJECT_AUTHENTICATION"> & KnownErrorBrand<"INVALID_SECRET_SERVER_KEY">, []> & {
|
|
77
|
+
InvalidSecretServerKey: KnownErrorConstructor<KnownError & KnownErrorBrand<"PROJECT_AUTHENTICATION_ERROR"> & KnownErrorBrand<"INVALID_PROJECT_AUTHENTICATION"> & KnownErrorBrand<"INVALID_SECRET_SERVER_KEY">, [projectId: string]> & {
|
|
78
78
|
errorCode: "INVALID_SECRET_SERVER_KEY";
|
|
79
79
|
};
|
|
80
|
-
InvalidSuperSecretAdminKey: KnownErrorConstructor<KnownError & KnownErrorBrand<"PROJECT_AUTHENTICATION_ERROR"> & KnownErrorBrand<"INVALID_PROJECT_AUTHENTICATION"> & KnownErrorBrand<"INVALID_SUPER_SECRET_ADMIN_KEY">, []> & {
|
|
80
|
+
InvalidSuperSecretAdminKey: KnownErrorConstructor<KnownError & KnownErrorBrand<"PROJECT_AUTHENTICATION_ERROR"> & KnownErrorBrand<"INVALID_PROJECT_AUTHENTICATION"> & KnownErrorBrand<"INVALID_SUPER_SECRET_ADMIN_KEY">, [projectId: string]> & {
|
|
81
81
|
errorCode: "INVALID_SUPER_SECRET_ADMIN_KEY";
|
|
82
82
|
};
|
|
83
83
|
InvalidAdminAccessToken: KnownErrorConstructor<KnownError & KnownErrorBrand<"PROJECT_AUTHENTICATION_ERROR"> & KnownErrorBrand<"INVALID_PROJECT_AUTHENTICATION"> & KnownErrorBrand<"INVALID_ADMIN_ACCESS_TOKEN">, [statusCode: number, humanReadableMessage: string, details?: Json | undefined]> & {
|
|
@@ -236,9 +236,6 @@ export declare const KnownErrors: {
|
|
|
236
236
|
PermissionScopeMismatch: KnownErrorConstructor<KnownError & KnownErrorBrand<"PERMISSION_SCOPE_MISMATCH">, [permissionId: string, permissionScope: PermissionDefinitionScopeJson, testScope: PermissionDefinitionScopeJson]> & {
|
|
237
237
|
errorCode: "PERMISSION_SCOPE_MISMATCH";
|
|
238
238
|
};
|
|
239
|
-
UserNotInTeam: KnownErrorConstructor<KnownError & KnownErrorBrand<"USER_NOT_IN_TEAM">, [userId: string, teamId: string]> & {
|
|
240
|
-
errorCode: "USER_NOT_IN_TEAM";
|
|
241
|
-
};
|
|
242
239
|
TeamNotFound: KnownErrorConstructor<KnownError & KnownErrorBrand<"TEAM_NOT_FOUND">, [teamId: string]> & {
|
|
243
240
|
errorCode: "TEAM_NOT_FOUND";
|
|
244
241
|
};
|
package/dist/known-errors.js
CHANGED
|
@@ -17,6 +17,7 @@ export class KnownError extends StatusError {
|
|
|
17
17
|
code: this.errorCode,
|
|
18
18
|
message: this.humanReadableMessage,
|
|
19
19
|
details: this.details,
|
|
20
|
+
error: true,
|
|
20
21
|
}, undefined, 2));
|
|
21
22
|
}
|
|
22
23
|
getHeaders() {
|
|
@@ -117,18 +118,27 @@ const RequestTypeWithoutProjectId = createKnownErrorConstructor(InvalidProjectAu
|
|
|
117
118
|
requestType,
|
|
118
119
|
},
|
|
119
120
|
], (json) => [json.requestType]);
|
|
120
|
-
const InvalidPublishableClientKey = createKnownErrorConstructor(InvalidProjectAuthentication, "INVALID_PUBLISHABLE_CLIENT_KEY", () => [
|
|
121
|
+
const InvalidPublishableClientKey = createKnownErrorConstructor(InvalidProjectAuthentication, "INVALID_PUBLISHABLE_CLIENT_KEY", (projectId) => [
|
|
121
122
|
401,
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
123
|
+
`The publishable key is not valid for the project ${JSON.stringify(projectId)}. Does the project and/or the key exist?`,
|
|
124
|
+
{
|
|
125
|
+
projectId,
|
|
126
|
+
},
|
|
127
|
+
], (json) => [json.projectId]);
|
|
128
|
+
const InvalidSecretServerKey = createKnownErrorConstructor(InvalidProjectAuthentication, "INVALID_SECRET_SERVER_KEY", (projectId) => [
|
|
125
129
|
401,
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
130
|
+
`The secret server key is not valid for the project ${JSON.stringify(projectId)}. Does the project and/or the key exist?`,
|
|
131
|
+
{
|
|
132
|
+
projectId,
|
|
133
|
+
},
|
|
134
|
+
], (json) => [json.projectId]);
|
|
135
|
+
const InvalidSuperSecretAdminKey = createKnownErrorConstructor(InvalidProjectAuthentication, "INVALID_SUPER_SECRET_ADMIN_KEY", (projectId) => [
|
|
129
136
|
401,
|
|
130
|
-
|
|
131
|
-
|
|
137
|
+
`The super secret admin key is not valid for the project ${JSON.stringify(projectId)}. Does the project and/or the key exist?`,
|
|
138
|
+
{
|
|
139
|
+
projectId,
|
|
140
|
+
},
|
|
141
|
+
], (json) => [json.projectId]);
|
|
132
142
|
const InvalidAdminAccessToken = createKnownErrorConstructor(InvalidProjectAuthentication, "INVALID_ADMIN_ACCESS_TOKEN", "inherit", "inherit");
|
|
133
143
|
const UnparsableAdminAccessToken = createKnownErrorConstructor(InvalidAdminAccessToken, "UNPARSABLE_ADMIN_ACCESS_TOKEN", () => [
|
|
134
144
|
401,
|
|
@@ -322,14 +332,6 @@ const PermissionScopeMismatch = createKnownErrorConstructor(KnownError, "PERMISS
|
|
|
322
332
|
},
|
|
323
333
|
];
|
|
324
334
|
}, (json) => [json.details.permissionId, json.details.permissionScope, json.details.testScope]);
|
|
325
|
-
const UserNotInTeam = createKnownErrorConstructor(KnownError, "USER_NOT_IN_TEAM", (userId, teamId) => [
|
|
326
|
-
400,
|
|
327
|
-
`User ${userId} is not in team ${teamId}.`,
|
|
328
|
-
{
|
|
329
|
-
userId,
|
|
330
|
-
teamId,
|
|
331
|
-
},
|
|
332
|
-
], (json) => [json.details.userId, json.details.teamId]);
|
|
333
335
|
const TeamNotFound = createKnownErrorConstructor(KnownError, "TEAM_NOT_FOUND", (teamId) => [
|
|
334
336
|
404,
|
|
335
337
|
`Team ${teamId} not found.`,
|
|
@@ -434,7 +436,6 @@ export const KnownErrors = {
|
|
|
434
436
|
EmailAlreadyVerified,
|
|
435
437
|
PermissionNotFound,
|
|
436
438
|
PermissionScopeMismatch,
|
|
437
|
-
UserNotInTeam,
|
|
438
439
|
TeamNotFound,
|
|
439
440
|
EmailTemplateAlreadyExists,
|
|
440
441
|
OAuthConnectionNotConnectedToUser,
|
package/dist/utils/jwt.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import * as jose from "jose";
|
|
2
2
|
import { getEnvVariable } from "./env";
|
|
3
|
-
const
|
|
3
|
+
const STACK_SERVER_SECRET = jose.base64url.decode(getEnvVariable("STACK_SERVER_SECRET"));
|
|
4
4
|
export async function encryptJWT(payload, expirationTime = "5m") {
|
|
5
5
|
return await new jose.EncryptJWT(payload)
|
|
6
6
|
.setProtectedHeader({ alg: "dir", enc: "A128CBC-HS256" })
|
|
7
7
|
.setIssuedAt()
|
|
8
8
|
.setExpirationTime(expirationTime)
|
|
9
|
-
.encrypt(
|
|
9
|
+
.encrypt(STACK_SERVER_SECRET);
|
|
10
10
|
}
|
|
11
11
|
export async function decryptJWT(jwt) {
|
|
12
12
|
if (!jwt) {
|
|
13
13
|
throw new Error("Provided JWT is empty");
|
|
14
14
|
}
|
|
15
|
-
return (await jose.jwtDecrypt(jwt,
|
|
15
|
+
return (await jose.jwtDecrypt(jwt, STACK_SERVER_SECRET)).payload;
|
|
16
16
|
}
|
package/dist/utils/strings.d.ts
CHANGED
|
@@ -41,6 +41,23 @@ export declare function deindent(code: string): string;
|
|
|
41
41
|
export declare function deindent(strings: TemplateStringsArray | readonly string[], ...values: any[]): string;
|
|
42
42
|
export declare function extractScopes(scope: string, removeDuplicates?: boolean): string[];
|
|
43
43
|
export declare function mergeScopeStrings(...scopes: string[]): string;
|
|
44
|
-
export
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
export type Nicifiable = {
|
|
45
|
+
getNicifiableKeys?(): PropertyKey[];
|
|
46
|
+
getNicifiedObjectExtraLines?(): string[];
|
|
47
|
+
};
|
|
48
|
+
export type NicifyOptions = {
|
|
49
|
+
maxDepth: number;
|
|
50
|
+
currentIndent: string;
|
|
51
|
+
lineIndent: string;
|
|
52
|
+
multiline: boolean;
|
|
53
|
+
refs: Map<unknown, string>;
|
|
54
|
+
path: string;
|
|
55
|
+
parent: null | {
|
|
56
|
+
options: NicifyOptions;
|
|
57
|
+
value: unknown;
|
|
58
|
+
};
|
|
59
|
+
keyInParent: PropertyKey | null;
|
|
60
|
+
overrides: (...args: Parameters<typeof nicify>) => ["result", string] | ["replace", unknown] | null;
|
|
61
|
+
};
|
|
62
|
+
export declare function nicify(value: unknown, options?: Partial<NicifyOptions>): string;
|
|
63
|
+
export declare function replaceAll(input: string, searchValue: string, replaceValue: string): string;
|
package/dist/utils/strings.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { StackAssertionError } from "./errors";
|
|
2
|
+
import { filterUndefined } from "./objects";
|
|
1
3
|
export function typedToLowercase(s) {
|
|
2
4
|
return s.toLowerCase();
|
|
3
5
|
}
|
|
@@ -102,7 +104,58 @@ export function mergeScopeStrings(...scopes) {
|
|
|
102
104
|
const allScope = scopes.map((s) => extractScopes(s)).flat().join(" ");
|
|
103
105
|
return extractScopes(allScope).join(" ");
|
|
104
106
|
}
|
|
105
|
-
|
|
107
|
+
/**
|
|
108
|
+
* Some classes have different constructor names in different environments (eg. `Headers` is sometimes called `_Headers`,
|
|
109
|
+
* so we create an object of overrides to handle these cases.
|
|
110
|
+
*/
|
|
111
|
+
const nicifiableClassNameOverrides = new Map(Object.entries({
|
|
112
|
+
Headers,
|
|
113
|
+
}).map(([k, v]) => [v, k]));
|
|
114
|
+
export function nicify(value, options = {}) {
|
|
115
|
+
const fullOptions = {
|
|
116
|
+
maxDepth: 5,
|
|
117
|
+
currentIndent: "",
|
|
118
|
+
lineIndent: " ",
|
|
119
|
+
multiline: true,
|
|
120
|
+
refs: new Map(),
|
|
121
|
+
path: "value",
|
|
122
|
+
parent: null,
|
|
123
|
+
overrides: () => null,
|
|
124
|
+
keyInParent: null,
|
|
125
|
+
...filterUndefined(options),
|
|
126
|
+
};
|
|
127
|
+
const { maxDepth, currentIndent, lineIndent, multiline, refs, path, overrides, } = fullOptions;
|
|
128
|
+
const nl = `\n${currentIndent}`;
|
|
129
|
+
if (["function", "object", "symbol"].includes(typeof value)) {
|
|
130
|
+
if (refs.has(value)) {
|
|
131
|
+
return `Ref<${refs.get(value)}>`;
|
|
132
|
+
}
|
|
133
|
+
refs.set(value, path);
|
|
134
|
+
}
|
|
135
|
+
const overrideResult = overrides(value, options);
|
|
136
|
+
if (overrideResult?.[0] === "result")
|
|
137
|
+
return overrideResult[1];
|
|
138
|
+
else if (overrideResult?.[0] === "replace")
|
|
139
|
+
return nicify(overrideResult[1], options);
|
|
140
|
+
const newOptions = {
|
|
141
|
+
maxDepth: maxDepth - 1,
|
|
142
|
+
currentIndent,
|
|
143
|
+
lineIndent,
|
|
144
|
+
multiline,
|
|
145
|
+
refs,
|
|
146
|
+
path: path + "->[unknown property]",
|
|
147
|
+
overrides,
|
|
148
|
+
parent: { value, options: fullOptions },
|
|
149
|
+
keyInParent: null,
|
|
150
|
+
};
|
|
151
|
+
const nestedNicify = (newValue, newPath, indent, keyInParent) => {
|
|
152
|
+
return nicify(newValue, {
|
|
153
|
+
...newOptions,
|
|
154
|
+
path: newPath,
|
|
155
|
+
currentIndent: currentIndent + (indent ? lineIndent : ""),
|
|
156
|
+
keyInParent,
|
|
157
|
+
});
|
|
158
|
+
};
|
|
106
159
|
switch (typeof value) {
|
|
107
160
|
case "string":
|
|
108
161
|
case "boolean":
|
|
@@ -127,24 +180,81 @@ export function nicify(value, { depth = 5 } = {}) {
|
|
|
127
180
|
if (value === null)
|
|
128
181
|
return "null";
|
|
129
182
|
if (Array.isArray(value)) {
|
|
130
|
-
|
|
183
|
+
const extraLines = getNicifiedObjectExtraLines(value);
|
|
184
|
+
const resValueLength = value.length + extraLines.length;
|
|
185
|
+
if (maxDepth <= 0 && resValueLength === 0)
|
|
131
186
|
return "[...]";
|
|
132
|
-
|
|
187
|
+
const shouldIndent = multiline && resValueLength > 1;
|
|
188
|
+
const resValues = value.map((v, i) => nestedNicify(v, `${path}[${i}]`, shouldIndent, i));
|
|
189
|
+
resValues.push(...extraLines);
|
|
190
|
+
if (resValues.length !== resValueLength)
|
|
191
|
+
throw new StackAssertionError("nicify of object: resValues.length !== resValueLength", { value, resValues, resValueLength });
|
|
192
|
+
if (shouldIndent) {
|
|
193
|
+
return `[${nl}${resValues.map(x => `${lineIndent}${x},${nl}`).join("")}]`;
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
return `[${resValues.join(", ")}]`;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
const constructorName = [null, Object].includes(Object.getPrototypeOf(value)) ? null : (nicifiableClassNameOverrides.get(value.constructor) ?? value.constructor.name);
|
|
200
|
+
const constructorString = constructorName ? `${nicifyPropertyString(constructorName)} ` : "";
|
|
201
|
+
const entries = getNicifiableEntries(value);
|
|
202
|
+
const extraLines = getNicifiedObjectExtraLines(value);
|
|
203
|
+
const resValueLength = entries.length + extraLines.length;
|
|
204
|
+
if (resValueLength === 0)
|
|
205
|
+
return `${constructorString}{}`;
|
|
206
|
+
if (maxDepth <= 0)
|
|
207
|
+
return `${constructorString}{ ... }`;
|
|
208
|
+
const shouldIndent = multiline && resValueLength > 1;
|
|
209
|
+
const resValues = entries.map(([k, v], keyIndex) => {
|
|
210
|
+
const keyNicified = nestedNicify(k, `Object.keys(${path})[${keyIndex}]`, shouldIndent, null);
|
|
211
|
+
const keyInObjectLiteral = typeof k === "string" ? JSON.stringify(k) : `[${keyNicified}]`;
|
|
212
|
+
if (typeof v === "function" && v.name === k) {
|
|
213
|
+
return `${keyInObjectLiteral}(...): { ... }`;
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
return `${keyInObjectLiteral}: ${nestedNicify(v, `${path}[${keyNicified}]`, shouldIndent, k)}`;
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
resValues.push(...extraLines);
|
|
220
|
+
if (resValues.length !== resValueLength)
|
|
221
|
+
throw new StackAssertionError("nicify of object: resValues.length !== resValueLength", { value, resValues, resValueLength });
|
|
222
|
+
if (resValues.length === 0)
|
|
223
|
+
return `${constructorString}{}`;
|
|
224
|
+
if (shouldIndent) {
|
|
225
|
+
return `${constructorString}{${nl}${resValues.map(x => `${lineIndent}${x},${nl}`).join("")}}`;
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
return `${constructorString}{ ${resValues.join(", ")} }`;
|
|
133
229
|
}
|
|
134
|
-
const entries = Object.entries(value);
|
|
135
|
-
if (entries.length === 0)
|
|
136
|
-
return "{}";
|
|
137
|
-
if (depth <= 0)
|
|
138
|
-
return "{...}";
|
|
139
|
-
return `{ ${Object.entries(value).map(([k, v]) => {
|
|
140
|
-
if (typeof v === "function" && v.name === k)
|
|
141
|
-
return `${k}(...): { ... }`;
|
|
142
|
-
else
|
|
143
|
-
return `${k}: ${nicify(v, { depth: depth - 1 })}`;
|
|
144
|
-
}).join(", ")} }`;
|
|
145
230
|
}
|
|
146
231
|
default: {
|
|
147
232
|
return `${typeof value}<${value}>`;
|
|
148
233
|
}
|
|
149
234
|
}
|
|
150
235
|
}
|
|
236
|
+
export function replaceAll(input, searchValue, replaceValue) {
|
|
237
|
+
return input.split(searchValue).join(replaceValue);
|
|
238
|
+
}
|
|
239
|
+
function nicifyPropertyString(str) {
|
|
240
|
+
if (/^[_a-zA-Z][_a-zA-Z0-9]*$/.test(str))
|
|
241
|
+
return str;
|
|
242
|
+
return JSON.stringify(str);
|
|
243
|
+
}
|
|
244
|
+
function getNicifiableKeys(value) {
|
|
245
|
+
return ("getNicifiableKeys" in value ? value.getNicifiableKeys : null)?.() ?? Object.keys(value).sort();
|
|
246
|
+
}
|
|
247
|
+
function getNicifiableEntries(value) {
|
|
248
|
+
const recordLikes = [Headers];
|
|
249
|
+
function isRecordLike(value) {
|
|
250
|
+
return recordLikes.some(x => value instanceof x);
|
|
251
|
+
}
|
|
252
|
+
if (isRecordLike(value)) {
|
|
253
|
+
return [...value.entries()].sort(([a], [b]) => String(a).localeCompare(String(b)));
|
|
254
|
+
}
|
|
255
|
+
const keys = getNicifiableKeys(value);
|
|
256
|
+
return keys.map((k) => [k, value[k]]);
|
|
257
|
+
}
|
|
258
|
+
function getNicifiedObjectExtraLines(value) {
|
|
259
|
+
return ("getNicifiedObjectExtraLines" in value ? value.getNicifiedObjectExtraLines : null)?.() ?? [];
|
|
260
|
+
}
|
package/dist/utils/yup.d.ts
CHANGED
package/dist/utils/yup.js
CHANGED
|
@@ -1,2 +1,13 @@
|
|
|
1
1
|
import * as yup from "yup";
|
|
2
2
|
export const yupJson = yup.mixed().nullable().defined().transform((value) => JSON.parse(JSON.stringify(value)));
|
|
3
|
+
export const yupJsonValidator = yup.string().test("json", "Invalid JSON format", (value) => {
|
|
4
|
+
if (!value)
|
|
5
|
+
return true;
|
|
6
|
+
try {
|
|
7
|
+
JSON.parse(value);
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
catch (error) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stackframe/stack-shared",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"jose": "^5.2.2",
|
|
37
37
|
"oauth4webapi": "^2.10.3",
|
|
38
38
|
"uuid": "^9.0.1",
|
|
39
|
-
"@stackframe/stack-sc": "2.
|
|
39
|
+
"@stackframe/stack-sc": "2.5.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"rimraf": "^5.0.5",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function useTrigger(callback: () => void): () => void;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
export function useTrigger(callback) {
|
|
3
|
-
const [hasTriggered, setHasTriggered] = React.useState(false);
|
|
4
|
-
React.useEffect(() => {
|
|
5
|
-
if (hasTriggered) {
|
|
6
|
-
callback();
|
|
7
|
-
}
|
|
8
|
-
}, [hasTriggered]);
|
|
9
|
-
return () => setHasTriggered(true);
|
|
10
|
-
}
|