@game-infra/api-schemas-core 0.0.0 → 0.4.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/LICENSE +21 -0
- package/README.md +31 -1
- package/dist/auth.d.ts +50 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +41 -2
- package/dist/auth.js.map +1 -1
- package/dist/backup.d.ts.map +1 -1
- package/dist/backup.js.map +1 -1
- package/dist/contracts.d.ts +347 -1
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +186 -1
- package/dist/contracts.js.map +1 -1
- package/dist/feedback.d.ts.map +1 -1
- package/dist/feedback.js.map +1 -1
- package/dist/gameEntity.d.ts.map +1 -1
- package/dist/gameEntity.js.map +1 -1
- package/dist/index.d.ts +7 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/savegame.d.ts.map +1 -1
- package/dist/savegame.js.map +1 -1
- package/dist/serviceToken.d.ts +393 -0
- package/dist/serviceToken.d.ts.map +1 -0
- package/dist/serviceToken.js +227 -0
- package/dist/serviceToken.js.map +1 -0
- package/dist/user.d.ts +251 -0
- package/dist/user.d.ts.map +1 -0
- package/dist/user.js +147 -0
- package/dist/user.js.map +1 -0
- package/package.json +14 -4
package/dist/user.d.ts
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import { type InferOutput } from "valibot";
|
|
2
|
+
/**
|
|
3
|
+
* Account administration: the endpoints an `admin` account uses to create,
|
|
4
|
+
* edit, and delete other accounts.
|
|
5
|
+
*
|
|
6
|
+
* Every field an administrator can write is validated here rather than in the
|
|
7
|
+
* service, so the console and the service reject the same input with the same
|
|
8
|
+
* message.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Bounds on the claims an administrator can grant.
|
|
12
|
+
*
|
|
13
|
+
* Claims are free-form strings so a game can introduce its own without a
|
|
14
|
+
* release of this package, but they are restricted to a lowercase token: a
|
|
15
|
+
* claim is compared byte for byte by every consumer, and `Admin` or `admin `
|
|
16
|
+
* would be granted, displayed, and then silently never match.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* import { UserAdminValidation } from '@game-infra/api-schemas-core'
|
|
21
|
+
*
|
|
22
|
+
* UserAdminValidation.CLAIM_PATTERN.test('admin') // true
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare const UserAdminValidation: {
|
|
26
|
+
readonly MAX_CLAIM_LENGTH: 64;
|
|
27
|
+
readonly MAX_CLAIMS: 32;
|
|
28
|
+
/** Lowercase letters, digits, and `.`, `:`, `_`, `-`, starting with a letter. */
|
|
29
|
+
readonly CLAIM_PATTERN: RegExp;
|
|
30
|
+
/** The claim that grants account administration, and most internal tools. */
|
|
31
|
+
readonly ADMIN_CLAIM: "admin";
|
|
32
|
+
/** Account ids as they appear in a path: legacy accounts carry negative ids. */
|
|
33
|
+
readonly USER_ID_PATTERN: RegExp;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* An account as an administrator sees it. The password hash never leaves the
|
|
37
|
+
* service; `hasPassword` says whether there is one that can match anything.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```ts
|
|
41
|
+
* import type { UserAccount } from '@game-infra/api-schemas-core'
|
|
42
|
+
*
|
|
43
|
+
* const isAdmin = (user: UserAccount) => user.claims.includes('admin')
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare const UserAccountSchema: import("valibot").ObjectSchema<{
|
|
47
|
+
/** Stable account id. Legacy imported accounts have negative ids. */
|
|
48
|
+
readonly id: import("valibot").NumberSchema<undefined>;
|
|
49
|
+
readonly username: import("valibot").StringSchema<undefined>;
|
|
50
|
+
/** `null` for accounts created without one, such as the legacy imports. */
|
|
51
|
+
readonly email: import("valibot").NullableSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
52
|
+
/** Authorization claims the account holds now. */
|
|
53
|
+
readonly claims: import("valibot").ArraySchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
54
|
+
/**
|
|
55
|
+
* Whether the account has a password that can match at login. `false` for
|
|
56
|
+
* the imported legacy rows until an administrator sets one.
|
|
57
|
+
*/
|
|
58
|
+
readonly hasPassword: import("valibot").BooleanSchema<undefined>;
|
|
59
|
+
/** ISO-8601 creation time. */
|
|
60
|
+
readonly createdAt: import("valibot").StringSchema<undefined>;
|
|
61
|
+
/** ISO-8601 time of the last change to the row. */
|
|
62
|
+
readonly updatedAt: import("valibot").StringSchema<undefined>;
|
|
63
|
+
}, undefined>;
|
|
64
|
+
/**
|
|
65
|
+
* Inferred account record.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```ts
|
|
69
|
+
* import type { UserAccount } from '@game-infra/api-schemas-core'
|
|
70
|
+
*
|
|
71
|
+
* const label = (user: UserAccount) => user.email ?? user.username
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export type UserAccount = InferOutput<typeof UserAccountSchema>;
|
|
75
|
+
/**
|
|
76
|
+
* Every account, ordered by username.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```ts
|
|
80
|
+
* import type { ListUsersResponse } from '@game-infra/api-schemas-core'
|
|
81
|
+
*
|
|
82
|
+
* const count = (response: ListUsersResponse) => response.users?.length ?? 0
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
export declare const ListUsersResponseSchema: import("valibot").ObjectSchema<{
|
|
86
|
+
readonly success: import("valibot").BooleanSchema<undefined>;
|
|
87
|
+
readonly error: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
88
|
+
} & {
|
|
89
|
+
users: import("valibot").OptionalSchema<import("valibot").ArraySchema<import("valibot").ObjectSchema<{
|
|
90
|
+
/** Stable account id. Legacy imported accounts have negative ids. */
|
|
91
|
+
readonly id: import("valibot").NumberSchema<undefined>;
|
|
92
|
+
readonly username: import("valibot").StringSchema<undefined>;
|
|
93
|
+
/** `null` for accounts created without one, such as the legacy imports. */
|
|
94
|
+
readonly email: import("valibot").NullableSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
95
|
+
/** Authorization claims the account holds now. */
|
|
96
|
+
readonly claims: import("valibot").ArraySchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
97
|
+
/**
|
|
98
|
+
* Whether the account has a password that can match at login. `false` for
|
|
99
|
+
* the imported legacy rows until an administrator sets one.
|
|
100
|
+
*/
|
|
101
|
+
readonly hasPassword: import("valibot").BooleanSchema<undefined>;
|
|
102
|
+
/** ISO-8601 creation time. */
|
|
103
|
+
readonly createdAt: import("valibot").StringSchema<undefined>;
|
|
104
|
+
/** ISO-8601 time of the last change to the row. */
|
|
105
|
+
readonly updatedAt: import("valibot").StringSchema<undefined>;
|
|
106
|
+
}, undefined>, undefined>, undefined>;
|
|
107
|
+
}, undefined>;
|
|
108
|
+
/**
|
|
109
|
+
* Inferred list-users response.
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* ```ts
|
|
113
|
+
* import type { ListUsersResponse } from '@game-infra/api-schemas-core'
|
|
114
|
+
*
|
|
115
|
+
* const ok: ListUsersResponse['success'] = true
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
export type ListUsersResponse = InferOutput<typeof ListUsersResponseSchema>;
|
|
119
|
+
/**
|
|
120
|
+
* An administrator creating an account.
|
|
121
|
+
*
|
|
122
|
+
* Unlike self-registration, this can grant claims and can leave the email out.
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```ts
|
|
126
|
+
* import { CreateUserRequestSchema } from '@game-infra/api-schemas-core'
|
|
127
|
+
* import { parse } from 'valibot'
|
|
128
|
+
*
|
|
129
|
+
* parse(CreateUserRequestSchema, { username: 'ada', password: 'hunter22', claims: ['admin'] })
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
export declare const CreateUserRequestSchema: import("valibot").ObjectSchema<{
|
|
133
|
+
readonly username: import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").MinLengthAction<string, 3, undefined>, import("valibot").MaxLengthAction<string, 64, undefined>, import("valibot").RegexAction<string, "Username may not contain @ or whitespace">]>;
|
|
134
|
+
readonly email: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").EmailAction<string, undefined>]>, undefined>;
|
|
135
|
+
readonly password: import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").MinLengthAction<string, 6, undefined>, import("valibot").MaxLengthAction<string, 128, undefined>]>;
|
|
136
|
+
readonly claims: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").ArraySchema<import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").MaxLengthAction<string, 64, undefined>, import("valibot").RegexAction<string, "Claims are lowercase letters, digits, '.', ':', '_' or '-', starting with a letter">]>, undefined>, import("valibot").MaxLengthAction<string[], 32, undefined>]>, undefined>;
|
|
137
|
+
}, undefined>;
|
|
138
|
+
/**
|
|
139
|
+
* Inferred create-user request.
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```ts
|
|
143
|
+
* import type { CreateUserRequest } from '@game-infra/api-schemas-core'
|
|
144
|
+
*
|
|
145
|
+
* const request: CreateUserRequest = { username: 'ada', password: 'hunter22' }
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
export type CreateUserRequest = InferOutput<typeof CreateUserRequestSchema>;
|
|
149
|
+
/**
|
|
150
|
+
* An administrator editing an account. Every field is optional and a missing
|
|
151
|
+
* field keeps its stored value. `email: null` removes the email; `password`
|
|
152
|
+
* replaces the stored hash.
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* ```ts
|
|
156
|
+
* import { UpdateUserRequestSchema } from '@game-infra/api-schemas-core'
|
|
157
|
+
* import { parse } from 'valibot'
|
|
158
|
+
*
|
|
159
|
+
* parse(UpdateUserRequestSchema, { claims: [], password: 'new-secret' })
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
162
|
+
export declare const UpdateUserRequestSchema: import("valibot").ObjectSchema<{
|
|
163
|
+
readonly username: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").MinLengthAction<string, 3, undefined>, import("valibot").MaxLengthAction<string, 64, undefined>, import("valibot").RegexAction<string, "Username may not contain @ or whitespace">]>, undefined>;
|
|
164
|
+
readonly email: import("valibot").OptionalSchema<import("valibot").NullableSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").EmailAction<string, undefined>]>, undefined>, undefined>;
|
|
165
|
+
readonly password: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").MinLengthAction<string, 6, undefined>, import("valibot").MaxLengthAction<string, 128, undefined>]>, undefined>;
|
|
166
|
+
readonly claims: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").ArraySchema<import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").MaxLengthAction<string, 64, undefined>, import("valibot").RegexAction<string, "Claims are lowercase letters, digits, '.', ':', '_' or '-', starting with a letter">]>, undefined>, import("valibot").MaxLengthAction<string[], 32, undefined>]>, undefined>;
|
|
167
|
+
}, undefined>;
|
|
168
|
+
/**
|
|
169
|
+
* Inferred update-user request.
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* ```ts
|
|
173
|
+
* import type { UpdateUserRequest } from '@game-infra/api-schemas-core'
|
|
174
|
+
*
|
|
175
|
+
* const demote: UpdateUserRequest = { claims: [] }
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
export type UpdateUserRequest = InferOutput<typeof UpdateUserRequestSchema>;
|
|
179
|
+
/**
|
|
180
|
+
* The account as stored after a create or update.
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* ```ts
|
|
184
|
+
* import type { UserResponse } from '@game-infra/api-schemas-core'
|
|
185
|
+
*
|
|
186
|
+
* const id = (response: UserResponse) => response.user?.id
|
|
187
|
+
* ```
|
|
188
|
+
*/
|
|
189
|
+
export declare const UserResponseSchema: import("valibot").ObjectSchema<{
|
|
190
|
+
readonly success: import("valibot").BooleanSchema<undefined>;
|
|
191
|
+
readonly error: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
192
|
+
} & {
|
|
193
|
+
user: import("valibot").OptionalSchema<import("valibot").ObjectSchema<{
|
|
194
|
+
/** Stable account id. Legacy imported accounts have negative ids. */
|
|
195
|
+
readonly id: import("valibot").NumberSchema<undefined>;
|
|
196
|
+
readonly username: import("valibot").StringSchema<undefined>;
|
|
197
|
+
/** `null` for accounts created without one, such as the legacy imports. */
|
|
198
|
+
readonly email: import("valibot").NullableSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
199
|
+
/** Authorization claims the account holds now. */
|
|
200
|
+
readonly claims: import("valibot").ArraySchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
201
|
+
/**
|
|
202
|
+
* Whether the account has a password that can match at login. `false` for
|
|
203
|
+
* the imported legacy rows until an administrator sets one.
|
|
204
|
+
*/
|
|
205
|
+
readonly hasPassword: import("valibot").BooleanSchema<undefined>;
|
|
206
|
+
/** ISO-8601 creation time. */
|
|
207
|
+
readonly createdAt: import("valibot").StringSchema<undefined>;
|
|
208
|
+
/** ISO-8601 time of the last change to the row. */
|
|
209
|
+
readonly updatedAt: import("valibot").StringSchema<undefined>;
|
|
210
|
+
}, undefined>, undefined>;
|
|
211
|
+
}, undefined>;
|
|
212
|
+
/**
|
|
213
|
+
* Inferred single-user response.
|
|
214
|
+
*
|
|
215
|
+
* @example
|
|
216
|
+
* ```ts
|
|
217
|
+
* import type { UserResponse } from '@game-infra/api-schemas-core'
|
|
218
|
+
*
|
|
219
|
+
* const ok: UserResponse['success'] = true
|
|
220
|
+
* ```
|
|
221
|
+
*/
|
|
222
|
+
export type UserResponse = InferOutput<typeof UserResponseSchema>;
|
|
223
|
+
/**
|
|
224
|
+
* Result of deleting an account. `revokedServiceTokens` counts the account's
|
|
225
|
+
* service tokens that were still honoured and are now revoked.
|
|
226
|
+
*
|
|
227
|
+
* @example
|
|
228
|
+
* ```ts
|
|
229
|
+
* import type { DeleteUserResponse } from '@game-infra/api-schemas-core'
|
|
230
|
+
*
|
|
231
|
+
* const revoked = (response: DeleteUserResponse) => response.revokedServiceTokens ?? 0
|
|
232
|
+
* ```
|
|
233
|
+
*/
|
|
234
|
+
export declare const DeleteUserResponseSchema: import("valibot").ObjectSchema<{
|
|
235
|
+
readonly success: import("valibot").BooleanSchema<undefined>;
|
|
236
|
+
readonly error: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
237
|
+
} & {
|
|
238
|
+
revokedServiceTokens: import("valibot").OptionalSchema<import("valibot").NumberSchema<undefined>, undefined>;
|
|
239
|
+
}, undefined>;
|
|
240
|
+
/**
|
|
241
|
+
* Inferred delete-user response.
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* ```ts
|
|
245
|
+
* import type { DeleteUserResponse } from '@game-infra/api-schemas-core'
|
|
246
|
+
*
|
|
247
|
+
* const ok: DeleteUserResponse['success'] = true
|
|
248
|
+
* ```
|
|
249
|
+
*/
|
|
250
|
+
export type DeleteUserResponse = InferOutput<typeof DeleteUserResponseSchema>;
|
|
251
|
+
//# sourceMappingURL=user.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../src/user.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,WAAW,EAajB,MAAM,SAAS,CAAC;AAKjB;;;;;;;GAOG;AAEH;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,mBAAmB;aAC9B,gBAAgB,EAAE,EAAE;aACpB,UAAU,EAAE,EAAE;IACd,iFAAiF;aACjF,aAAa;IACb,6EAA6E;aAC7E,WAAW,EAAE,OAAO;IACpB,gFAAgF;aAChF,eAAe;CACP,CAAC;AA6BX;;;;;;;;;;GAUG;AACH,eAAO,MAAM,iBAAiB;IAC5B,qEAAqE;;;IAGrE,2EAA2E;;IAE3E,kDAAkD;;IAElD;;;OAGG;;IAEH,8BAA8B;;IAE9B,mDAAmD;;aAEnD,CAAC;AAEH;;;;;;;;;GASG;AACH,MAAM,MAAM,WAAW,GAAG,WAAW,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAEhE;;;;;;;;;GASG;AACH,eAAO,MAAM,uBAAuB;;;;;QAxClC,qEAAqE;;;QAGrE,2EAA2E;;QAE3E,kDAAkD;;QAElD;;;WAGG;;QAEH,8BAA8B;;QAE9B,mDAAmD;;;aA4BnD,CAAC;AAEH;;;;;;;;;GASG;AACH,MAAM,MAAM,iBAAiB,GAAG,WAAW,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAE5E;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,uBAAuB;;;;;aAKlC,CAAC;AAEH;;;;;;;;;GASG;AACH,MAAM,MAAM,iBAAiB,GAAG,WAAW,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAE5E;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,uBAAuB;;;;;aAKlC,CAAC;AAEH;;;;;;;;;GASG;AACH,MAAM,MAAM,iBAAiB,GAAG,WAAW,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAE5E;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB;;;;;QAlI7B,qEAAqE;;;QAGrE,2EAA2E;;QAE3E,kDAAkD;;QAElD;;;WAGG;;QAEH,8BAA8B;;QAE9B,mDAAmD;;;aAsHnD,CAAC;AAEH;;;;;;;;;GASG;AACH,MAAM,MAAM,YAAY,GAAG,WAAW,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAElE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,wBAAwB;;;;;aAEnC,CAAC;AAEH;;;;;;;;;GASG;AACH,MAAM,MAAM,kBAAkB,GAAG,WAAW,CAAC,OAAO,wBAAwB,CAAC,CAAC"}
|
package/dist/user.js
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { array, boolean, email, maxLength, minLength, nullable, number, object, optional, pipe, regex, string, } from "valibot";
|
|
2
|
+
import { AuthValidation } from "./auth.js";
|
|
3
|
+
import { createSuccessResponseSchema } from "./common.js";
|
|
4
|
+
/**
|
|
5
|
+
* Account administration: the endpoints an `admin` account uses to create,
|
|
6
|
+
* edit, and delete other accounts.
|
|
7
|
+
*
|
|
8
|
+
* Every field an administrator can write is validated here rather than in the
|
|
9
|
+
* service, so the console and the service reject the same input with the same
|
|
10
|
+
* message.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Bounds on the claims an administrator can grant.
|
|
14
|
+
*
|
|
15
|
+
* Claims are free-form strings so a game can introduce its own without a
|
|
16
|
+
* release of this package, but they are restricted to a lowercase token: a
|
|
17
|
+
* claim is compared byte for byte by every consumer, and `Admin` or `admin `
|
|
18
|
+
* would be granted, displayed, and then silently never match.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* import { UserAdminValidation } from '@game-infra/api-schemas-core'
|
|
23
|
+
*
|
|
24
|
+
* UserAdminValidation.CLAIM_PATTERN.test('admin') // true
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export const UserAdminValidation = {
|
|
28
|
+
MAX_CLAIM_LENGTH: 64,
|
|
29
|
+
MAX_CLAIMS: 32,
|
|
30
|
+
/** Lowercase letters, digits, and `.`, `:`, `_`, `-`, starting with a letter. */
|
|
31
|
+
CLAIM_PATTERN: /^[a-z][a-z0-9.:_-]*$/,
|
|
32
|
+
/** The claim that grants account administration, and most internal tools. */
|
|
33
|
+
ADMIN_CLAIM: "admin",
|
|
34
|
+
/** Account ids as they appear in a path: legacy accounts carry negative ids. */
|
|
35
|
+
USER_ID_PATTERN: /^-?\d+$/,
|
|
36
|
+
};
|
|
37
|
+
const UsernameSchema = pipe(string(), minLength(AuthValidation.MIN_USERNAME_LENGTH), maxLength(AuthValidation.MAX_USERNAME_LENGTH), regex(AuthValidation.USERNAME_PATTERN, "Username may not contain @ or whitespace"));
|
|
38
|
+
const PasswordSchema = pipe(string(), minLength(AuthValidation.MIN_PASSWORD_LENGTH), maxLength(AuthValidation.MAX_PASSWORD_LENGTH));
|
|
39
|
+
const ClaimsSchema = pipe(array(pipe(string(), maxLength(UserAdminValidation.MAX_CLAIM_LENGTH), regex(UserAdminValidation.CLAIM_PATTERN, "Claims are lowercase letters, digits, '.', ':', '_' or '-', starting with a letter"))), maxLength(UserAdminValidation.MAX_CLAIMS));
|
|
40
|
+
/**
|
|
41
|
+
* An account as an administrator sees it. The password hash never leaves the
|
|
42
|
+
* service; `hasPassword` says whether there is one that can match anything.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* import type { UserAccount } from '@game-infra/api-schemas-core'
|
|
47
|
+
*
|
|
48
|
+
* const isAdmin = (user: UserAccount) => user.claims.includes('admin')
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export const UserAccountSchema = object({
|
|
52
|
+
/** Stable account id. Legacy imported accounts have negative ids. */
|
|
53
|
+
id: number(),
|
|
54
|
+
username: string(),
|
|
55
|
+
/** `null` for accounts created without one, such as the legacy imports. */
|
|
56
|
+
email: nullable(string()),
|
|
57
|
+
/** Authorization claims the account holds now. */
|
|
58
|
+
claims: array(string()),
|
|
59
|
+
/**
|
|
60
|
+
* Whether the account has a password that can match at login. `false` for
|
|
61
|
+
* the imported legacy rows until an administrator sets one.
|
|
62
|
+
*/
|
|
63
|
+
hasPassword: boolean(),
|
|
64
|
+
/** ISO-8601 creation time. */
|
|
65
|
+
createdAt: string(),
|
|
66
|
+
/** ISO-8601 time of the last change to the row. */
|
|
67
|
+
updatedAt: string(),
|
|
68
|
+
});
|
|
69
|
+
/**
|
|
70
|
+
* Every account, ordered by username.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```ts
|
|
74
|
+
* import type { ListUsersResponse } from '@game-infra/api-schemas-core'
|
|
75
|
+
*
|
|
76
|
+
* const count = (response: ListUsersResponse) => response.users?.length ?? 0
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export const ListUsersResponseSchema = createSuccessResponseSchema({
|
|
80
|
+
users: optional(array(UserAccountSchema)),
|
|
81
|
+
});
|
|
82
|
+
/**
|
|
83
|
+
* An administrator creating an account.
|
|
84
|
+
*
|
|
85
|
+
* Unlike self-registration, this can grant claims and can leave the email out.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```ts
|
|
89
|
+
* import { CreateUserRequestSchema } from '@game-infra/api-schemas-core'
|
|
90
|
+
* import { parse } from 'valibot'
|
|
91
|
+
*
|
|
92
|
+
* parse(CreateUserRequestSchema, { username: 'ada', password: 'hunter22', claims: ['admin'] })
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export const CreateUserRequestSchema = object({
|
|
96
|
+
username: UsernameSchema,
|
|
97
|
+
email: optional(pipe(string(), email())),
|
|
98
|
+
password: PasswordSchema,
|
|
99
|
+
claims: optional(ClaimsSchema),
|
|
100
|
+
});
|
|
101
|
+
/**
|
|
102
|
+
* An administrator editing an account. Every field is optional and a missing
|
|
103
|
+
* field keeps its stored value. `email: null` removes the email; `password`
|
|
104
|
+
* replaces the stored hash.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```ts
|
|
108
|
+
* import { UpdateUserRequestSchema } from '@game-infra/api-schemas-core'
|
|
109
|
+
* import { parse } from 'valibot'
|
|
110
|
+
*
|
|
111
|
+
* parse(UpdateUserRequestSchema, { claims: [], password: 'new-secret' })
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
export const UpdateUserRequestSchema = object({
|
|
115
|
+
username: optional(UsernameSchema),
|
|
116
|
+
email: optional(nullable(pipe(string(), email()))),
|
|
117
|
+
password: optional(PasswordSchema),
|
|
118
|
+
claims: optional(ClaimsSchema),
|
|
119
|
+
});
|
|
120
|
+
/**
|
|
121
|
+
* The account as stored after a create or update.
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```ts
|
|
125
|
+
* import type { UserResponse } from '@game-infra/api-schemas-core'
|
|
126
|
+
*
|
|
127
|
+
* const id = (response: UserResponse) => response.user?.id
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
export const UserResponseSchema = createSuccessResponseSchema({
|
|
131
|
+
user: optional(UserAccountSchema),
|
|
132
|
+
});
|
|
133
|
+
/**
|
|
134
|
+
* Result of deleting an account. `revokedServiceTokens` counts the account's
|
|
135
|
+
* service tokens that were still honoured and are now revoked.
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```ts
|
|
139
|
+
* import type { DeleteUserResponse } from '@game-infra/api-schemas-core'
|
|
140
|
+
*
|
|
141
|
+
* const revoked = (response: DeleteUserResponse) => response.revokedServiceTokens ?? 0
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
export const DeleteUserResponseSchema = createSuccessResponseSchema({
|
|
145
|
+
revokedServiceTokens: optional(number()),
|
|
146
|
+
});
|
|
147
|
+
//# sourceMappingURL=user.js.map
|
package/dist/user.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user.js","sourceRoot":"","sources":["../src/user.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@game-infra/api-schemas-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Generic service API contract: auth, savegame, game-entity, backup, feedback, heartbeat schemas + toad-contracts endpoint definitions",
|
|
5
|
+
"homepage": "https://github.com/kibertoad/game-infra/tree/main/packages/schemas/api-schemas-core#readme",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/kibertoad/game-infra/issues"
|
|
8
|
+
},
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/kibertoad/game-infra.git",
|
|
13
|
+
"directory": "packages/schemas/api-schemas-core"
|
|
14
|
+
},
|
|
5
15
|
"files": [
|
|
6
16
|
"dist"
|
|
7
17
|
],
|
|
@@ -21,11 +31,11 @@
|
|
|
21
31
|
"@toad-contracts/valibot": "0.5.0"
|
|
22
32
|
},
|
|
23
33
|
"devDependencies": {
|
|
24
|
-
"@types/node": "^
|
|
34
|
+
"@types/node": "^26.6.3",
|
|
25
35
|
"rimraf": "^6.1.3",
|
|
26
36
|
"typescript": "^7.0.2",
|
|
27
|
-
"valibot": "^1.
|
|
28
|
-
"vitest": "^4.
|
|
37
|
+
"valibot": "^1.5.0",
|
|
38
|
+
"vitest": "^4.1.11"
|
|
29
39
|
},
|
|
30
40
|
"peerDependencies": {
|
|
31
41
|
"valibot": "^1.4.0"
|