create-warlock 4.0.139 → 4.0.141

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.
Files changed (27) hide show
  1. package/package.json +1 -1
  2. package/templates/warlock/package.json +7 -7
  3. package/templates/warlock/src/app/auth/controllers/forgot-password.controller.ts +6 -29
  4. package/templates/warlock/src/app/auth/controllers/login.controller.ts +5 -11
  5. package/templates/warlock/src/app/auth/controllers/logout-all.controller.ts +2 -2
  6. package/templates/warlock/src/app/auth/controllers/logout.controller.ts +2 -2
  7. package/templates/warlock/src/app/auth/controllers/me.controller.ts +2 -2
  8. package/templates/warlock/src/app/auth/controllers/refresh-token.controller.ts +3 -10
  9. package/templates/warlock/src/app/auth/controllers/reset-password.controller.ts +2 -4
  10. package/templates/warlock/src/app/auth/main.ts +6 -11
  11. package/templates/warlock/src/app/auth/requests/guarded.request.ts +4 -3
  12. package/templates/warlock/src/app/auth/requests/login.request.ts +1 -1
  13. package/templates/warlock/src/app/auth/requests/reset-password.request.ts +1 -1
  14. package/templates/warlock/src/app/auth/routes.ts +12 -12
  15. package/templates/warlock/src/app/auth/services/auth.service.ts +22 -8
  16. package/templates/warlock/src/app/auth/services/forgot-password.service.ts +30 -0
  17. package/templates/warlock/src/app/auth/services/otp.service.ts +1 -1
  18. package/templates/warlock/src/app/auth/services/reset-password.service.ts +9 -3
  19. package/templates/warlock/src/app/users/controllers/{get-users.controller.ts → list-users.controller.ts} +2 -3
  20. package/templates/warlock/src/app/users/models/user/user.model.ts +5 -29
  21. package/templates/warlock/src/app/users/repositories/users.repository.ts +10 -10
  22. package/templates/warlock/src/app/users/resources/user.resource.ts +14 -0
  23. package/templates/warlock/src/app/users/routes.ts +5 -2
  24. package/templates/warlock/src/app/users/services/list-users.service.ts +14 -4
  25. package/templates/warlock/src/config/repository.ts +11 -0
  26. /package/templates/warlock/src/app/auth/{validation → schema}/login.schema.ts +0 -0
  27. /package/templates/warlock/src/app/auth/{validation → schema}/reset-password.schema.ts +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-warlock",
3
- "version": "4.0.139",
3
+ "version": "4.0.141",
4
4
  "main": "./esm/index.js",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -23,13 +23,13 @@
23
23
  "@mongez/reinforcements": "^2.3.17",
24
24
  "@mongez/localization": "^3.2.1",
25
25
  "@mongez/supportive-is": "^2.0.4",
26
- "@warlock.js/auth": "4.0.139",
27
- "@warlock.js/cache": "4.0.139",
28
- "@warlock.js/cascade": "4.0.139",
29
- "@warlock.js/scheduler": "4.0.139",
30
- "@warlock.js/core": "4.0.139",
31
- "@warlock.js/logger": "4.0.139",
32
- "@warlock.js/seal": "4.0.139",
26
+ "@warlock.js/auth": "4.0.141",
27
+ "@warlock.js/cache": "4.0.141",
28
+ "@warlock.js/cascade": "4.0.141",
29
+ "@warlock.js/scheduler": "4.0.141",
30
+ "@warlock.js/core": "4.0.141",
31
+ "@warlock.js/logger": "4.0.141",
32
+ "@warlock.js/seal": "4.0.141",
33
33
  "dayjs": "^1.11.19",
34
34
  "mongodb": "^7.0.0"
35
35
  },
@@ -5,52 +5,29 @@ import {
5
5
  type RequestHandler,
6
6
  type Response,
7
7
  } from "@warlock.js/core";
8
- import { usersRepository } from "app/users/repositories/users.repository";
9
- import { createOtpService } from "../services/otp.service";
8
+ import { forgotPasswordService } from "../services/forgot-password.service";
10
9
 
11
10
  /**
12
11
  * Forgot password controller
13
12
  * POST /auth/forgot-password
14
13
  */
15
- export const forgotPassword: RequestHandler = async (
14
+ export const forgotPasswordController: RequestHandler = async (
16
15
  request: Request,
17
16
  response: Response,
18
17
  ) => {
19
18
  const { email } = request.validated();
20
19
 
21
- // Find user by email (silent fail for security)
22
- const user = await usersRepository.first({ email });
20
+ await forgotPasswordService(email);
23
21
 
24
- if (!user) {
25
- // Silent success - don't reveal if email exists
26
- return response.success({
27
- message: t("auth.otpSent"),
28
- });
29
- }
30
-
31
- // Create OTP
32
- const otp = await createOtpService({
33
- target: email,
34
- channel: "email",
35
- type: "password-reset",
36
- userId: user.id,
37
- userType: user.userType,
38
- });
39
-
40
- // TODO: Send email with OTP code
41
- // await sendPasswordResetEmail(user, otp.get("code"));
42
- console.log(`[DEV] Password reset OTP for ${email}: ${otp.get("code")}`);
43
-
44
- // Always return success for security (don't reveal if email exists)
45
22
  return response.success({
46
23
  message: t("auth.otpSent"),
47
24
  });
48
25
  };
49
26
 
50
- forgotPassword.description = "Request password reset";
27
+ forgotPasswordController.description = "Request password reset";
51
28
 
52
- forgotPassword.validation = {
29
+ forgotPasswordController.validation = {
53
30
  schema: v.object({
54
- email: v.string().email().required(),
31
+ email: v.email().required(),
55
32
  }),
56
33
  };
@@ -1,13 +1,13 @@
1
- import { t, type RequestHandler, type Response } from "@warlock.js/core";
1
+ import { type RequestHandler, type Response } from "@warlock.js/core";
2
2
  import { type LoginRequest } from "../requests/login.request";
3
+ import { loginSchema } from "../schema/login.schema";
3
4
  import { loginService } from "../services/auth.service";
4
- import { loginSchema } from "../validation/login.schema";
5
5
 
6
6
  /**
7
7
  * Login controller
8
8
  * POST /auth/login
9
9
  */
10
- export const login: RequestHandler = async (
10
+ export const loginController: RequestHandler = async (
11
11
  request: LoginRequest,
12
12
  response: Response,
13
13
  ) => {
@@ -16,17 +16,11 @@ export const login: RequestHandler = async (
16
16
  ip: request.ip,
17
17
  });
18
18
 
19
- if (!result) {
20
- return response.unauthorized({
21
- error: t("auth.invalidCredentials"),
22
- });
23
- }
24
-
25
19
  return response.success(result);
26
20
  };
27
21
 
28
- login.description = "User Login";
22
+ loginController.description = "User Login";
29
23
 
30
- login.validation = {
24
+ loginController.validation = {
31
25
  schema: loginSchema,
32
26
  };
@@ -10,7 +10,7 @@ import { logoutAllService } from "../services/auth.service";
10
10
  * Logout from all devices controller
11
11
  * POST /auth/logout-all
12
12
  */
13
- export const logoutAll: RequestHandler = async (
13
+ export const logoutAllController: RequestHandler = async (
14
14
  request: Request,
15
15
  response: Response,
16
16
  ) => {
@@ -21,4 +21,4 @@ export const logoutAll: RequestHandler = async (
21
21
  });
22
22
  };
23
23
 
24
- logoutAll.description = "Logout from all devices";
24
+ logoutAllController.description = "Logout from all devices";
@@ -10,7 +10,7 @@ import { logoutService } from "../services/auth.service";
10
10
  * Logout controller
11
11
  * POST /auth/logout
12
12
  */
13
- export const logout: RequestHandler = async (
13
+ export const logoutController: RequestHandler = async (
14
14
  request: Request,
15
15
  response: Response,
16
16
  ) => {
@@ -21,4 +21,4 @@ export const logout: RequestHandler = async (
21
21
  });
22
22
  };
23
23
 
24
- logout.description = "User Logout";
24
+ logoutController.description = "User Logout";
@@ -8,7 +8,7 @@ import {
8
8
  * Get current user controller
9
9
  * GET /auth/me
10
10
  */
11
- export const me: RequestHandler = async (
11
+ export const meController: RequestHandler = async (
12
12
  request: Request,
13
13
  response: Response,
14
14
  ) => {
@@ -17,4 +17,4 @@ export const me: RequestHandler = async (
17
17
  });
18
18
  };
19
19
 
20
- me.description = "Get Current User";
20
+ meController.description = "Get Current User";
@@ -1,5 +1,4 @@
1
1
  import {
2
- t,
3
2
  v,
4
3
  type Request,
5
4
  type RequestHandler,
@@ -11,7 +10,7 @@ import { refreshTokensService } from "../services/auth.service";
11
10
  * Refresh token controller
12
11
  * POST /auth/refresh-token
13
12
  */
14
- export const refreshToken: RequestHandler = async (
13
+ export const refreshTokenController: RequestHandler = async (
15
14
  request: Request,
16
15
  response: Response,
17
16
  ) => {
@@ -22,18 +21,12 @@ export const refreshToken: RequestHandler = async (
22
21
  ip: request.ip,
23
22
  });
24
23
 
25
- if (!result) {
26
- return response.unauthorized({
27
- error: t("auth.invalidRefreshToken"),
28
- });
29
- }
30
-
31
24
  return response.success(result);
32
25
  };
33
26
 
34
- refreshToken.description = "Refresh Access Token";
27
+ refreshTokenController.description = "Refresh Access Token";
35
28
 
36
- refreshToken.validation = {
29
+ refreshTokenController.validation = {
37
30
  schema: v.object({
38
31
  refreshToken: v.string().required(),
39
32
  }),
@@ -1,7 +1,7 @@
1
1
  import { t, type Response } from "@warlock.js/core";
2
2
  import { type ResetPasswordRequest } from "../requests/reset-password.request";
3
+ import { resetPasswordSchema } from "../schema/reset-password.schema";
3
4
  import { resetPasswordService } from "../services/reset-password.service";
4
- import { resetPasswordSchema } from "../validation/reset-password.schema";
5
5
 
6
6
  /**
7
7
  * Reset password controller
@@ -10,9 +10,7 @@ export const resetPasswordController = async (
10
10
  request: ResetPasswordRequest,
11
11
  response: Response,
12
12
  ) => {
13
- const { email, code, newPassword } = request.validated();
14
-
15
- await resetPasswordService(email, code, newPassword);
13
+ await resetPasswordService(request.validated());
16
14
 
17
15
  return response.success({
18
16
  message: t("auth.passwordResetSuccess"),
@@ -1,16 +1,11 @@
1
1
  import { authService } from "@warlock.js/auth";
2
- import { onceConnected } from "@warlock.js/cascade";
3
2
  import { scheduler } from "app/shared/services/scheduler.service";
4
3
  import { cleanupExpiredOtpsService } from "./services/otp.service";
5
4
 
6
- onceConnected(() => {
7
- // Cleanup expired OTPs every hour
8
- scheduler
9
- .newJob("cleanup-expired-otps", cleanupExpiredOtpsService)
10
- .everyHour();
5
+ // Cleanup expired OTPs every hour
6
+ scheduler.newJob("cleanup-expired-otps", cleanupExpiredOtpsService).everyHour();
11
7
 
12
- // Cleanup expired refresh tokens every hour
13
- scheduler
14
- .newJob("cleanup-expired-tokens", () => authService.cleanupExpiredTokens())
15
- .everyHour();
16
- });
8
+ // Cleanup expired refresh tokens every hour
9
+ scheduler
10
+ .newJob("cleanup-expired-tokens", () => authService.cleanupExpiredTokens())
11
+ .everyHour();
@@ -1,6 +1,7 @@
1
1
  import type { Request } from "@warlock.js/core";
2
2
  import type { User } from "app/users/models/user";
3
3
 
4
- export type GuardedRequest<RequestPayload = unknown> = Request<RequestPayload> & {
5
- user: User;
6
- };
4
+ export type GuardedRequest<RequestPayload = unknown> =
5
+ Request<RequestPayload> & {
6
+ user: User;
7
+ };
@@ -1,4 +1,4 @@
1
1
  import type { Request } from "@warlock.js/core";
2
- import { type LoginSchema } from "../validation/login.schema";
2
+ import { type LoginSchema } from "../schema/login.schema";
3
3
 
4
4
  export type LoginRequest = Request<LoginSchema>;
@@ -1,4 +1,4 @@
1
1
  import type { Request } from "@warlock.js/core";
2
- import { type ResetPasswordSchema } from "../validation/reset-password.schema";
2
+ import { type ResetPasswordSchema } from "../schema/reset-password.schema";
3
3
 
4
4
  export type ResetPasswordRequest = Request<ResetPasswordSchema>;
@@ -1,22 +1,22 @@
1
1
  import { router } from "@warlock.js/core";
2
2
  import { guarded } from "app/shared/utils/router";
3
- import { forgotPassword } from "./controllers/forgot-password.controller";
4
- import { login } from "./controllers/login.controller";
5
- import { logoutAll } from "./controllers/logout-all.controller";
6
- import { logout } from "./controllers/logout.controller";
7
- import { me } from "./controllers/me.controller";
8
- import { refreshToken } from "./controllers/refresh-token.controller";
3
+ import { forgotPasswordController } from "./controllers/forgot-password.controller";
4
+ import { loginController } from "./controllers/login.controller";
5
+ import { logoutAllController } from "./controllers/logout-all.controller";
6
+ import { logoutController } from "./controllers/logout.controller";
7
+ import { meController } from "./controllers/me.controller";
8
+ import { refreshTokenController } from "./controllers/refresh-token.controller";
9
9
  import { resetPasswordController } from "./controllers/reset-password.controller";
10
10
 
11
11
  // Auth routes
12
12
  router.prefix("/auth", () => {
13
- router.post("/login", login);
14
- router.post("/refresh-token", refreshToken);
15
- router.post("/forgot-password", forgotPassword);
13
+ router.post("/login", loginController);
14
+ router.post("/refresh-token", refreshTokenController);
15
+ router.post("/forgot-password", forgotPasswordController);
16
16
  router.post("/reset-password", resetPasswordController);
17
17
  guarded(() => {
18
- router.post("/logout", logout);
19
- router.post("/logout-all", logoutAll);
20
- router.get("/me", me);
18
+ router.post("/logout", logoutController);
19
+ router.post("/logout-all", logoutAllController);
20
+ router.get("/me", meController);
21
21
  });
22
22
  });
@@ -1,5 +1,6 @@
1
- import type { Auth } from "@warlock.js/auth";
1
+ import type { AccessTokenOutput, Auth } from "@warlock.js/auth";
2
2
  import { authService, type DeviceInfo, type TokenPair } from "@warlock.js/auth";
3
+ import { t, UnAuthorizedError } from "@warlock.js/core";
3
4
  import { User } from "app/users/models/user/user.model";
4
5
 
5
6
  export type LoginCredentials = {
@@ -9,12 +10,13 @@ export type LoginCredentials = {
9
10
 
10
11
  export type LoginResult =
11
12
  | {
12
- user: Auth;
13
+ user: User;
13
14
  tokens: TokenPair;
14
15
  }
16
+ | null
15
17
  | {
16
- user: Auth;
17
- accessToken: string;
18
+ user: User;
19
+ accessToken: AccessTokenOutput;
18
20
  };
19
21
 
20
22
  /**
@@ -23,8 +25,14 @@ export type LoginResult =
23
25
  export async function loginService(
24
26
  credentials: LoginCredentials,
25
27
  deviceInfo?: DeviceInfo,
26
- ): Promise<LoginResult | null> {
27
- return authService.login(User, credentials, deviceInfo);
28
+ ): Promise<LoginResult> {
29
+ const result = await authService.login(User, credentials, deviceInfo);
30
+
31
+ if (!result) {
32
+ throw new UnAuthorizedError(t("auth.invalidCredentials"));
33
+ }
34
+
35
+ return result;
28
36
  }
29
37
 
30
38
  /**
@@ -47,6 +55,12 @@ export async function logoutAllService(user: Auth): Promise<void> {
47
55
  export async function refreshTokensService(
48
56
  refreshToken: string,
49
57
  deviceInfo?: DeviceInfo,
50
- ): Promise<TokenPair | null> {
51
- return authService.refreshTokens(refreshToken, deviceInfo);
58
+ ): Promise<TokenPair> {
59
+ const result = await authService.refreshTokens(refreshToken, deviceInfo);
60
+
61
+ if (!result) {
62
+ throw new UnAuthorizedError(t("auth.invalidRefreshToken"));
63
+ }
64
+
65
+ return result;
52
66
  }
@@ -0,0 +1,30 @@
1
+ import { getFirstUserService } from "app/users/services/list-users.service";
2
+ import { createOtpService } from "./otp.service";
3
+
4
+ /**
5
+ * Example Usage:
6
+ * await forgotPasswordService("user@example.com");
7
+ */
8
+
9
+ /**
10
+ * Handle forgot password request
11
+ *
12
+ * @param email - User email address
13
+ * @returns Promise<void>
14
+ */
15
+ export async function forgotPasswordService(email: string): Promise<void> {
16
+ // Find user by email (silent fail for security)
17
+ const user = await getFirstUserService({ email });
18
+
19
+ // Create OTP
20
+ const otp = await createOtpService({
21
+ target: email,
22
+ channel: "email",
23
+ type: "password-reset",
24
+ userId: user.id,
25
+ userType: user.userType,
26
+ });
27
+
28
+ // TODO: Send email with OTP code using a mail service
29
+ // await sendPasswordResetEmail(user, otp.get("code"));
30
+ }
@@ -23,7 +23,7 @@ export type CreateOTPOptions = {
23
23
  target: string;
24
24
  channel: OTPChannel;
25
25
  type: OTPType;
26
- userId?: number;
26
+ userId?: number | string;
27
27
  userType?: string;
28
28
  expiresIn?: Duration;
29
29
  length?: number;
@@ -4,14 +4,20 @@ import { User } from "app/users/models/user";
4
4
  import { AuthErrorCode } from "../utils/auth-error-code";
5
5
  import { verifyOtpService } from "./otp.service";
6
6
 
7
+ type ResetPasswordOptions = {
8
+ email: string;
9
+ code: string;
10
+ newPassword: string;
11
+ };
12
+
7
13
  /**
8
14
  * Reset user password using OTP verification
9
15
  */
10
16
  export async function resetPasswordService(
11
- email: string,
12
- code: string,
13
- newPassword: string,
17
+ options: ResetPasswordOptions,
14
18
  ): Promise<User> {
19
+ const { email, code, newPassword } = options;
20
+
15
21
  // Verify OTP
16
22
  const otp = await verifyOtpService(code, email, "password-reset");
17
23
 
@@ -5,13 +5,12 @@ import {
5
5
  } from "@warlock.js/core";
6
6
  import { usersRepository } from "../repositories/users.repository";
7
7
 
8
- export const getUsersController: RequestHandler = async (
8
+ export const listUsersController: RequestHandler = async (
9
9
  request: Request,
10
10
  response: Response,
11
11
  ) => {
12
12
  const users = await usersRepository.listCached({
13
13
  ...request.all(),
14
- simpleSelect: true,
15
14
  });
16
15
 
17
16
  return response.success({
@@ -19,4 +18,4 @@ export const getUsersController: RequestHandler = async (
19
18
  });
20
19
  };
21
20
 
22
- getUsersController.description = "Get Users Controller";
21
+ listUsersController.description = "List Users Controller";
@@ -1,32 +1,14 @@
1
1
  import { Auth } from "@warlock.js/auth";
2
- import { hasMany, RegisterModel } from "@warlock.js/cascade";
3
- import {
4
- defineResource,
5
- uploadedFileMetadataSchema,
6
- useHashedPassword,
7
- } from "@warlock.js/core";
2
+ import { RegisterModel } from "@warlock.js/cascade";
3
+ import { useHashedPassword } from "@warlock.js/core";
8
4
  import { type Infer, v } from "@warlock.js/seal";
9
- import { type Post } from "app/posts/models/post/post.model";
10
5
  import { globalColumnsSchema } from "app/shared/utils/global-columns-schema";
11
-
12
- const UserResource = defineResource({
13
- schema: {
14
- id: "number",
15
- name: "string",
16
- email: "string",
17
- image: "storageUrl",
18
- createdAt: "date",
19
- updatedAt: "date",
20
- isActive: "boolean",
21
- type: () => "user",
22
- },
23
- });
6
+ import { UserResource } from "app/users/resources/user.resource";
24
7
 
25
8
  export const userSchema = globalColumnsSchema.extend({
26
- name: v.string().required().trim(),
27
- email: v.email().requiredIfEmpty("id").unique("User"),
9
+ name: v.string().required(),
10
+ email: v.email().requiredIfEmpty("id"),
28
11
  image: v.string(),
29
- imageMetadata: uploadedFileMetadataSchema,
30
12
  password: v
31
13
  .string()
32
14
  .min(6)
@@ -48,12 +30,6 @@ export class User extends Auth<UserSchema> {
48
30
  */
49
31
  public static schema = userSchema;
50
32
 
51
- public static relations = {
52
- posts: hasMany("Post", { foreignKey: "authorId" }),
53
- };
54
-
55
- public posts?: Post[];
56
-
57
33
  /**
58
34
  * Embed fields when saving in another model
59
35
  */
@@ -2,22 +2,22 @@ import type { FilterRules, RepositoryOptions } from "@warlock.js/core";
2
2
  import { RepositoryManager } from "@warlock.js/core";
3
3
  import { User } from "../models/user";
4
4
 
5
- class UsersRepository extends RepositoryManager<User> {
6
- public source = User;
5
+ export type UserFilter = {
6
+ email?: string;
7
+ name?: string;
8
+ id?: string;
9
+ };
10
+
11
+ export type UsersListOptions = RepositoryOptions & UserFilter;
7
12
 
8
- public simpleSelectColumns: string[] = ["id", "name", "createdAt"];
13
+ class UsersRepository extends RepositoryManager<User, UserFilter> {
14
+ public source = User;
9
15
 
10
16
  public filterBy: FilterRules = {
11
- id: "int",
17
+ id: "=",
12
18
  name: "like",
13
19
  email: "=",
14
20
  };
15
-
16
- public defaultOptions: RepositoryOptions = {
17
- orderBy: {
18
- createdAt: "desc",
19
- },
20
- };
21
21
  }
22
22
 
23
23
  export const usersRepository = new UsersRepository();
@@ -0,0 +1,14 @@
1
+ import { defineResource } from "@warlock.js/core";
2
+
3
+ export const UserResource = defineResource({
4
+ schema: {
5
+ id: "number",
6
+ name: "string",
7
+ email: "string",
8
+ image: "storageUrl",
9
+ createdAt: "date",
10
+ updatedAt: "date",
11
+ isActive: "boolean",
12
+ type: () => "user",
13
+ },
14
+ });
@@ -1,8 +1,11 @@
1
1
  import { router } from "@warlock.js/core";
2
2
  import { guarded } from "app/shared/utils/router";
3
3
  import { createNewUserController } from "./controllers/create-new-user.controller";
4
- import { getUsersController } from "./controllers/get-users.controller";
4
+ import { listUsersController } from "./controllers/list-users.controller";
5
5
 
6
6
  guarded(() => {
7
- router.route("/users").get(getUsersController).post(createNewUserController);
7
+ router
8
+ .route("/users")
9
+ .list(listUsersController)
10
+ .post(createNewUserController);
8
11
  });
@@ -1,7 +1,17 @@
1
+ import { ResourceNotFoundError } from "@warlock.js/core";
2
+ import type { UsersListOptions } from "../repositories/users.repository";
1
3
  import { usersRepository } from "../repositories/users.repository";
2
4
 
3
- export async function listUsersService() {
4
- return usersRepository.allActiveCached({
5
- select: ["id", "name", "email", "isActive", "age"],
6
- });
5
+ export async function listUsersService(filters: UsersListOptions = {}) {
6
+ return usersRepository.listActiveCached(filters);
7
+ }
8
+
9
+ export async function getFirstUserService(filters: UsersListOptions = {}) {
10
+ const user = await usersRepository.firstActiveCached(filters);
11
+
12
+ if (!user) {
13
+ throw new ResourceNotFoundError("No user found");
14
+ }
15
+
16
+ return user;
7
17
  }
@@ -0,0 +1,11 @@
1
+ import type { RepositoryConfigurations } from "@warlock.js/core";
2
+
3
+ export default {
4
+ isActiveColumn: "status",
5
+ isActiveValue: "active",
6
+ defaultOptions: {
7
+ orderBy: {
8
+ created_at: "desc",
9
+ },
10
+ },
11
+ } as RepositoryConfigurations;