refactor(admin/invites): regenerate types; remove InviteListItem cast
All checks were successful
CI / Unit & Component Tests (push) Successful in 3m17s
CI / OCR Service Tests (push) Successful in 21s
CI / Backend Unit Tests (push) Successful in 3m24s
CI / fail2ban Regex (push) Successful in 42s
CI / Semgrep Security Scan (push) Successful in 19s
CI / Compose Bucket Idempotency (push) Successful in 1m1s
All checks were successful
CI / Unit & Component Tests (push) Successful in 3m17s
CI / OCR Service Tests (push) Successful in 21s
CI / Backend Unit Tests (push) Successful in 3m24s
CI / fail2ban Regex (push) Successful in 42s
CI / Semgrep Security Scan (push) Successful in 19s
CI / Compose Bucket Idempotency (push) Successful in 1m1s
After adding @Schema(requiredMode=REQUIRED) to InviteListItemDTO.shareableUrl, npm run generate:api now emits shareableUrl as required. Replace the hand-rolled InviteListItem interface with a type alias to the generated InviteListItemDTO and remove the two 'as unknown as InviteListItem' casts + TODO comments. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit was merged in pull request #623.
This commit is contained in:
@@ -180,6 +180,22 @@ export interface paths {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/users/{id}/force-logout": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
post: operations["forceLogout"];
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/users/me/password": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -580,6 +596,38 @@ export interface paths {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/auth/logout": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
post: operations["logout"];
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/auth/login": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
post: operations["login"];
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/auth/forgot-password": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -1849,7 +1897,7 @@ export interface components {
|
||||
status: string;
|
||||
/** Format: date-time */
|
||||
createdAt: string;
|
||||
shareableUrl?: string;
|
||||
shareableUrl: string;
|
||||
};
|
||||
GroupDTO: {
|
||||
name?: string;
|
||||
@@ -2011,13 +2059,17 @@ export interface components {
|
||||
lastName?: string;
|
||||
notifyOnMention?: boolean;
|
||||
};
|
||||
LoginRequest: {
|
||||
email?: string;
|
||||
password?: string;
|
||||
};
|
||||
ForgotPasswordRequest: {
|
||||
email?: string;
|
||||
};
|
||||
ImportStatus: {
|
||||
/** @enum {string} */
|
||||
state?: "IDLE" | "RUNNING" | "DONE" | "FAILED";
|
||||
message?: string;
|
||||
statusCode?: string;
|
||||
/** Format: int32 */
|
||||
processed?: number;
|
||||
/** Format: date-time */
|
||||
@@ -2255,14 +2307,14 @@ export interface components {
|
||||
/** Format: int32 */
|
||||
totalPages?: number;
|
||||
pageable?: components["schemas"]["PageableObject"];
|
||||
first?: boolean;
|
||||
last?: boolean;
|
||||
/** Format: int32 */
|
||||
size?: number;
|
||||
content?: components["schemas"]["NotificationDTO"][];
|
||||
/** Format: int32 */
|
||||
number?: number;
|
||||
sort?: components["schemas"]["SortObject"];
|
||||
first?: boolean;
|
||||
last?: boolean;
|
||||
/** Format: int32 */
|
||||
numberOfElements?: number;
|
||||
empty?: boolean;
|
||||
@@ -2410,7 +2462,7 @@ export interface components {
|
||||
};
|
||||
ActivityFeedItemDTO: {
|
||||
/** @enum {string} */
|
||||
kind: "FILE_UPLOADED" | "STATUS_CHANGED" | "METADATA_UPDATED" | "TEXT_SAVED" | "BLOCK_REVIEWED" | "ANNOTATION_CREATED" | "COMMENT_ADDED" | "MENTION_CREATED" | "USER_CREATED" | "USER_DELETED" | "GROUP_MEMBERSHIP_CHANGED";
|
||||
kind: "FILE_UPLOADED" | "STATUS_CHANGED" | "METADATA_UPDATED" | "TEXT_SAVED" | "BLOCK_REVIEWED" | "ANNOTATION_CREATED" | "COMMENT_ADDED" | "MENTION_CREATED" | "USER_CREATED" | "USER_DELETED" | "GROUP_MEMBERSHIP_CHANGED" | "LOGIN_SUCCESS" | "LOGIN_FAILED" | "LOGOUT" | "ADMIN_FORCE_LOGOUT" | "LOGIN_RATE_LIMITED";
|
||||
actor?: components["schemas"]["ActivityActorDTO"];
|
||||
/** Format: uuid */
|
||||
documentId: string;
|
||||
@@ -2954,6 +3006,30 @@ export interface operations {
|
||||
};
|
||||
};
|
||||
};
|
||||
forceLogout: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
id: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description OK */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"*/*": {
|
||||
[key: string]: unknown;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
changePassword: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -3547,6 +3623,7 @@ export interface operations {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
documentId: string;
|
||||
blockId: string;
|
||||
};
|
||||
cookie?: never;
|
||||
@@ -3597,6 +3674,7 @@ export interface operations {
|
||||
header?: never;
|
||||
path: {
|
||||
documentId: string;
|
||||
blockId: string;
|
||||
commentId: string;
|
||||
};
|
||||
cookie?: never;
|
||||
@@ -3791,6 +3869,48 @@ export interface operations {
|
||||
};
|
||||
};
|
||||
};
|
||||
logout: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description OK */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
};
|
||||
};
|
||||
login: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["LoginRequest"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description OK */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"*/*": components["schemas"]["AppUser"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
forgotPassword: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -4985,7 +5105,7 @@ export interface operations {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"*/*": components["schemas"]["DocumentDensityResult"];
|
||||
"application/json": components["schemas"]["DocumentDensityResult"];
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -5061,7 +5181,7 @@ export interface operations {
|
||||
query?: {
|
||||
limit?: number;
|
||||
/** @description Filter by audit kinds; omit for all rollup-eligible kinds */
|
||||
kinds?: ("FILE_UPLOADED" | "STATUS_CHANGED" | "METADATA_UPDATED" | "TEXT_SAVED" | "BLOCK_REVIEWED" | "ANNOTATION_CREATED" | "COMMENT_ADDED" | "MENTION_CREATED" | "USER_CREATED" | "USER_DELETED" | "GROUP_MEMBERSHIP_CHANGED")[];
|
||||
kinds?: ("FILE_UPLOADED" | "STATUS_CHANGED" | "METADATA_UPDATED" | "TEXT_SAVED" | "BLOCK_REVIEWED" | "ANNOTATION_CREATED" | "COMMENT_ADDED" | "MENTION_CREATED" | "USER_CREATED" | "USER_DELETED" | "GROUP_MEMBERSHIP_CHANGED" | "LOGIN_SUCCESS" | "LOGIN_FAILED" | "LOGOUT" | "ADMIN_FORCE_LOGOUT" | "LOGIN_RATE_LIMITED")[];
|
||||
};
|
||||
header?: never;
|
||||
path?: never;
|
||||
|
||||
@@ -4,21 +4,7 @@ import { getErrorMessage } from '$lib/shared/errors';
|
||||
import type { Actions, PageServerLoad } from './$types';
|
||||
import type { components } from '$lib/generated/api';
|
||||
|
||||
// The spec marks shareableUrl optional but the backend always populates it.
|
||||
// Keeping the required shape here avoids null-guarding throughout the page component.
|
||||
export interface InviteListItem {
|
||||
id: string;
|
||||
code: string;
|
||||
displayCode: string;
|
||||
label?: string;
|
||||
useCount: number;
|
||||
maxUses?: number;
|
||||
expiresAt?: string;
|
||||
revoked: boolean;
|
||||
status: string;
|
||||
createdAt: string;
|
||||
shareableUrl: string;
|
||||
}
|
||||
export type InviteListItem = components['schemas']['InviteListItemDTO'];
|
||||
export type UserGroup = components['schemas']['UserGroup'];
|
||||
|
||||
const VALID_STATUSES = ['ACTIVE', 'REVOKED', 'EXPIRED'] as const;
|
||||
@@ -42,8 +28,7 @@ export const load: PageServerLoad = async ({ url, fetch }) => {
|
||||
const code = (invitesResult.error as unknown as { code?: string })?.code;
|
||||
loadError = code ?? 'INTERNAL_ERROR';
|
||||
} else {
|
||||
// TODO: remove cast after next npm run generate:api — shareableUrl is now @Schema(requiredMode=REQUIRED)
|
||||
invites = (invitesResult.data ?? []) as unknown as InviteListItem[];
|
||||
invites = (invitesResult.data ?? []) as InviteListItem[];
|
||||
}
|
||||
|
||||
let groups: UserGroup[] = [];
|
||||
@@ -81,8 +66,7 @@ export const actions = {
|
||||
return fail(result.response.status, { createError: code ?? 'INTERNAL_ERROR' });
|
||||
}
|
||||
|
||||
// TODO: remove cast after next npm run generate:api — shareableUrl is now @Schema(requiredMode=REQUIRED)
|
||||
return { created: result.data! as unknown as InviteListItem };
|
||||
return { created: result.data! as InviteListItem };
|
||||
},
|
||||
|
||||
revoke: async ({ request, fetch }) => {
|
||||
|
||||
Reference in New Issue
Block a user