alepha 0.13.2 → 0.13.3

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 (76) hide show
  1. package/dist/api-files/index.browser.js +80 -0
  2. package/dist/api-files/index.browser.js.map +1 -0
  3. package/dist/api-jobs/index.browser.js +56 -0
  4. package/dist/api-jobs/index.browser.js.map +1 -0
  5. package/dist/api-notifications/index.browser.js +382 -0
  6. package/dist/api-notifications/index.browser.js.map +1 -0
  7. package/dist/api-notifications/index.d.ts +124 -69
  8. package/dist/api-notifications/index.js +107 -55
  9. package/dist/api-notifications/index.js.map +1 -1
  10. package/dist/api-parameters/index.browser.js +29 -0
  11. package/dist/api-parameters/index.browser.js.map +1 -0
  12. package/dist/api-users/index.d.ts +16 -3
  13. package/dist/api-users/index.js +75 -28
  14. package/dist/api-users/index.js.map +1 -1
  15. package/dist/api-verifications/index.browser.js +52 -0
  16. package/dist/api-verifications/index.browser.js.map +1 -0
  17. package/dist/api-verifications/index.d.ts +117 -95
  18. package/dist/api-verifications/index.js +1 -1
  19. package/dist/api-verifications/index.js.map +1 -1
  20. package/dist/batch/index.js +0 -5
  21. package/dist/batch/index.js.map +1 -1
  22. package/dist/bucket/index.js +7 -5
  23. package/dist/bucket/index.js.map +1 -1
  24. package/dist/cli/{dist-Dl9Vl7Ur.js → dist-lGnqsKpu.js} +11 -15
  25. package/dist/cli/dist-lGnqsKpu.js.map +1 -0
  26. package/dist/cli/index.d.ts +26 -45
  27. package/dist/cli/index.js +40 -58
  28. package/dist/cli/index.js.map +1 -1
  29. package/dist/command/index.d.ts +1 -0
  30. package/dist/command/index.js +9 -0
  31. package/dist/command/index.js.map +1 -1
  32. package/dist/email/index.js +5 -0
  33. package/dist/email/index.js.map +1 -1
  34. package/dist/orm/index.js +3 -3
  35. package/dist/orm/index.js.map +1 -1
  36. package/dist/redis/index.d.ts +10 -10
  37. package/dist/security/index.d.ts +28 -28
  38. package/dist/security/index.js +3 -3
  39. package/dist/security/index.js.map +1 -1
  40. package/dist/server/index.d.ts +9 -9
  41. package/dist/server-auth/index.d.ts +152 -152
  42. package/dist/server-cookies/index.js +2 -2
  43. package/dist/server-cookies/index.js.map +1 -1
  44. package/dist/server-links/index.d.ts +33 -33
  45. package/dist/server-static/index.js +18 -2
  46. package/dist/server-static/index.js.map +1 -1
  47. package/package.json +16 -6
  48. package/src/api-files/index.browser.ts +17 -0
  49. package/src/api-jobs/index.browser.ts +15 -0
  50. package/src/api-notifications/controllers/NotificationController.ts +26 -1
  51. package/src/api-notifications/index.browser.ts +17 -0
  52. package/src/api-notifications/index.ts +1 -0
  53. package/src/api-notifications/schemas/notificationQuerySchema.ts +13 -0
  54. package/src/api-notifications/services/NotificationService.ts +45 -2
  55. package/src/api-parameters/index.browser.ts +12 -0
  56. package/src/api-users/atoms/realmAuthSettingsAtom.ts +3 -1
  57. package/src/api-users/controllers/UserController.ts +21 -1
  58. package/src/api-users/primitives/$userRealm.ts +33 -10
  59. package/src/api-users/providers/UserRealmProvider.ts +1 -0
  60. package/src/api-users/services/SessionService.ts +2 -0
  61. package/src/api-users/services/UserService.ts +56 -16
  62. package/src/api-verifications/index.browser.ts +15 -0
  63. package/src/api-verifications/index.ts +1 -0
  64. package/src/batch/providers/BatchProvider.ts +0 -7
  65. package/src/bucket/index.ts +7 -5
  66. package/src/cli/apps/AlephaCli.ts +27 -1
  67. package/src/cli/apps/AlephaPackageBuilderCli.ts +3 -0
  68. package/src/cli/commands/CoreCommands.ts +6 -2
  69. package/src/cli/commands/ViteCommands.ts +2 -1
  70. package/src/cli/services/ProjectUtils.ts +40 -75
  71. package/src/command/helpers/Asker.ts +10 -0
  72. package/src/email/index.ts +13 -5
  73. package/src/orm/providers/drivers/NodeSqliteProvider.ts +3 -3
  74. package/src/server-cookies/providers/ServerCookiesProvider.ts +2 -1
  75. package/src/server-static/providers/ServerStaticProvider.ts +18 -3
  76. package/dist/cli/dist-Dl9Vl7Ur.js.map +0 -1
@@ -14,6 +14,7 @@ import { CryptoProvider, RealmPrimitive, RealmPrimitiveOptions, UserAccount } fr
14
14
  import * as alepha_server_links0 from "alepha/server/links";
15
15
  import { OAuth2Profile, ServerAuthProvider, WithLinkFn, WithLoginFn } from "alepha/server/auth";
16
16
  import { FileSystemProvider } from "alepha/file";
17
+ import { FileController } from "alepha/api/files";
17
18
  import * as drizzle_orm0 from "drizzle-orm";
18
19
  import { BuildExtraConfigColumns, SQL, SQLWrapper } from "drizzle-orm";
19
20
  import * as drizzle_orm_pg_core0 from "drizzle-orm/pg-core";
@@ -25,7 +26,6 @@ import "alepha/lock";
25
26
  import "drizzle-orm/postgres-js";
26
27
  import "postgres";
27
28
  import "drizzle-orm/sqlite-core";
28
- import { FileController } from "alepha/api/files";
29
29
 
30
30
  //#region src/api-users/atoms/realmAuthSettingsAtom.d.ts
31
31
  declare const realmAuthSettingsAtom: alepha23.Atom<alepha23.TObject<{
@@ -161,7 +161,7 @@ declare class UserRealmProvider {
161
161
  protected realms: Map<string, UserRealm>;
162
162
  avatars: alepha_bucket0.BucketPrimitive;
163
163
  protected readonly onConfigure: alepha23.HookPrimitive<"configure">;
164
- register(userRealmName: string, userRealmOptions?: UserRealmOptions$1): void;
164
+ register(userRealmName: string, userRealmOptions?: UserRealmOptions$1): UserRealm;
165
165
  /**
166
166
  * Gets a registered realm by name, auto-creating default if needed.
167
167
  */
@@ -2220,10 +2220,15 @@ declare class UserService {
2220
2220
  }>>;
2221
2221
  /**
2222
2222
  * Request email verification for a user.
2223
+ * @param email - The email address to verify.
2224
+ * @param userRealmName - Optional realm name.
2225
+ * @param method - The verification method: "code" (default) or "link".
2226
+ * @param verifyUrl - Base URL for verification link (required when method is "link").
2223
2227
  */
2224
- requestEmailVerification(email: string, userRealmName?: string): Promise<boolean>;
2228
+ requestEmailVerification(email: string, userRealmName?: string, method?: "code" | "link", verifyUrl?: string): Promise<boolean>;
2225
2229
  /**
2226
2230
  * Verify a user's email using a valid verification token.
2231
+ * Supports both code (6-digit) and link (UUID) verification tokens.
2227
2232
  */
2228
2233
  verifyEmail(email: string, token: string, userRealmName?: string): Promise<void>;
2229
2234
  /**
@@ -2544,10 +2549,14 @@ declare class UserController {
2544
2549
  /**
2545
2550
  * Request email verification.
2546
2551
  * Generates a verification token using verification service and sends an email to the user.
2552
+ * @param method - The verification method: "code" (default) sends a 6-digit code, "link" sends a clickable verification link.
2553
+ * @param verifyUrl - Required when method is "link". The base URL for the verification link. Token and email will be appended as query params.
2547
2554
  */
2548
2555
  requestEmailVerification: alepha_server0.ActionPrimitiveFn<{
2549
2556
  query: alepha23.TObject<{
2550
2557
  userRealmName: alepha23.TOptional<alepha23.TString>;
2558
+ method: alepha23.TOptional<alepha23.TUnsafe<"link" | "code">>;
2559
+ verifyUrl: alepha23.TOptional<alepha23.TString>;
2551
2560
  }>;
2552
2561
  body: alepha23.TObject<{
2553
2562
  email: alepha23.TString;
@@ -2691,6 +2700,10 @@ interface UserRealmOptions {
2691
2700
  google?: true;
2692
2701
  github?: true;
2693
2702
  };
2703
+ modules?: {
2704
+ files?: boolean;
2705
+ audits?: boolean;
2706
+ };
2694
2707
  }
2695
2708
  //#endregion
2696
2709
  //#region src/api-users/schemas/identityResourceSchema.d.ts
@@ -14,6 +14,7 @@ import { $realm, CryptoProvider, InvalidCredentialsError, SecurityProvider } fro
14
14
  import { $client } from "alepha/server/links";
15
15
  import { $authCredentials, $authGithub, $authGoogle, ServerAuthProvider, authenticationProviderSchema } from "alepha/server/auth";
16
16
  import { FileSystemProvider } from "alepha/file";
17
+ import { AlephaApiFiles } from "alepha/api/files";
17
18
 
18
19
  //#region src/api-users/schemas/identityQuerySchema.ts
19
20
  const identityQuerySchema = t.extend(pageQuerySchema, {
@@ -152,6 +153,7 @@ var UserRealmProvider = class {
152
153
  }
153
154
  }
154
155
  });
156
+ return this.getRealm(userRealmName);
155
157
  }
156
158
  /**
157
159
  * Gets a registered realm by name, auto-creating default if needed.
@@ -1136,11 +1138,16 @@ var UserService = class {
1136
1138
  }
1137
1139
  /**
1138
1140
  * Request email verification for a user.
1141
+ * @param email - The email address to verify.
1142
+ * @param userRealmName - Optional realm name.
1143
+ * @param method - The verification method: "code" (default) or "link".
1144
+ * @param verifyUrl - Base URL for verification link (required when method is "link").
1139
1145
  */
1140
- async requestEmailVerification(email, userRealmName) {
1146
+ async requestEmailVerification(email, userRealmName, method = "code", verifyUrl) {
1141
1147
  this.log.trace("Requesting email verification", {
1142
1148
  email,
1143
- userRealmName
1149
+ userRealmName,
1150
+ method
1144
1151
  });
1145
1152
  const user = await this.users(userRealmName).findOne({ where: { email: { eq: email } } }).catch(() => void 0);
1146
1153
  if (!user) {
@@ -1156,21 +1163,40 @@ var UserService = class {
1156
1163
  }
1157
1164
  try {
1158
1165
  const verification = await this.verificationController.requestVerificationCode({
1159
- params: { type: "code" },
1166
+ params: { type: method },
1160
1167
  body: { target: email }
1161
1168
  });
1162
- await this.userNotifications.emailVerification.push({
1163
- contact: email,
1164
- variables: {
1169
+ if (method === "link") {
1170
+ const url = new URL(verifyUrl || "/verify-email", "http://localhost");
1171
+ url.searchParams.set("email", email);
1172
+ url.searchParams.set("token", verification.token);
1173
+ const fullVerifyUrl = verifyUrl ? `${verifyUrl}${url.search}` : url.pathname + url.search;
1174
+ await this.userNotifications.emailVerificationLink.push({
1175
+ contact: email,
1176
+ variables: {
1177
+ email,
1178
+ verifyUrl: fullVerifyUrl,
1179
+ expiresInMinutes: Math.floor(verification.codeExpiration / 60)
1180
+ }
1181
+ });
1182
+ this.log.debug("Email verification link sent", {
1165
1183
  email,
1166
- code: verification.token,
1167
- expiresInMinutes: Math.floor(verification.codeExpiration / 60)
1168
- }
1169
- });
1170
- this.log.debug("Email verification code sent", {
1171
- email,
1172
- userId: user.id
1173
- });
1184
+ userId: user.id
1185
+ });
1186
+ } else {
1187
+ await this.userNotifications.emailVerification.push({
1188
+ contact: email,
1189
+ variables: {
1190
+ email,
1191
+ code: verification.token,
1192
+ expiresInMinutes: Math.floor(verification.codeExpiration / 60)
1193
+ }
1194
+ });
1195
+ this.log.debug("Email verification code sent", {
1196
+ email,
1197
+ userId: user.id
1198
+ });
1199
+ }
1174
1200
  } catch (error) {
1175
1201
  this.log.warn("Failed to send email verification", {
1176
1202
  email,
@@ -1181,20 +1207,25 @@ var UserService = class {
1181
1207
  }
1182
1208
  /**
1183
1209
  * Verify a user's email using a valid verification token.
1210
+ * Supports both code (6-digit) and link (UUID) verification tokens.
1184
1211
  */
1185
1212
  async verifyEmail(email, token, userRealmName) {
1186
1213
  this.log.trace("Verifying email", {
1187
1214
  email,
1188
1215
  userRealmName
1189
1216
  });
1217
+ const type = /^\d{6}$/.test(token) ? "code" : "link";
1190
1218
  if ((await this.verificationController.validateVerificationCode({
1191
- params: { type: "code" },
1219
+ params: { type },
1192
1220
  body: {
1193
1221
  target: email,
1194
1222
  token
1195
1223
  }
1196
1224
  }).catch(() => {
1197
- this.log.warn("Invalid email verification token", { email });
1225
+ this.log.warn("Invalid email verification token", {
1226
+ email,
1227
+ type
1228
+ });
1198
1229
  throw new BadRequestError("Invalid or expired verification token");
1199
1230
  })).alreadyVerified) {
1200
1231
  this.log.warn("Email verification token already used", { email });
@@ -1204,7 +1235,8 @@ var UserService = class {
1204
1235
  await this.users(userRealmName).updateById(user.id, { emailVerified: true });
1205
1236
  this.log.info("Email verified", {
1206
1237
  email,
1207
- userId: user.id
1238
+ userId: user.id,
1239
+ type
1208
1240
  });
1209
1241
  }
1210
1242
  /**
@@ -1544,12 +1576,21 @@ var UserController = class {
1544
1576
  /**
1545
1577
  * Request email verification.
1546
1578
  * Generates a verification token using verification service and sends an email to the user.
1579
+ * @param method - The verification method: "code" (default) sends a 6-digit code, "link" sends a clickable verification link.
1580
+ * @param verifyUrl - Required when method is "link". The base URL for the verification link. Token and email will be appended as query params.
1547
1581
  */
1548
1582
  requestEmailVerification = $action({
1549
1583
  path: "/users/email-verification/request",
1550
1584
  group: this.group,
1551
1585
  schema: {
1552
- query: t.object({ userRealmName: t.optional(t.string()) }),
1586
+ query: t.object({
1587
+ userRealmName: t.optional(t.string()),
1588
+ method: t.optional(t.enum(["code", "link"], {
1589
+ default: "code",
1590
+ description: "Verification method: \"code\" sends a 6-digit code, \"link\" sends a clickable verification link."
1591
+ })),
1592
+ verifyUrl: t.optional(t.string({ description: "Base URL for verification link. Required when method is \"link\". Token and email will be appended as query params." }))
1593
+ }),
1553
1594
  body: t.object({ email: t.email() }),
1554
1595
  response: t.object({
1555
1596
  success: t.boolean(),
@@ -1557,10 +1598,11 @@ var UserController = class {
1557
1598
  })
1558
1599
  },
1559
1600
  handler: async ({ body, query }) => {
1560
- await this.userService.requestEmailVerification(body.email, query.userRealmName);
1601
+ const method = query.method ?? "code";
1602
+ await this.userService.requestEmailVerification(body.email, query.userRealmName, method, query.verifyUrl);
1561
1603
  return {
1562
1604
  success: true,
1563
- message: "If an account exists with this email, a verification code has been sent."
1605
+ message: method === "link" ? "If an account exists with this email, a verification link has been sent." : "If an account exists with this email, a verification code has been sent."
1564
1606
  };
1565
1607
  }
1566
1608
  });
@@ -1642,7 +1684,7 @@ const realmAuthSettingsAtom = $atom({
1642
1684
  registrationAllowed: true,
1643
1685
  emailEnabled: true,
1644
1686
  emailRequired: true,
1645
- usernameEnabled: true,
1687
+ usernameEnabled: false,
1646
1688
  usernameRequired: false,
1647
1689
  phoneEnabled: false,
1648
1690
  phoneRequired: false,
@@ -1909,6 +1951,7 @@ var SessionService = class {
1909
1951
  realm: realm.name,
1910
1952
  username: profile.email.split("@")[0],
1911
1953
  email: profile.email,
1954
+ emailVerified: true,
1912
1955
  roles: ["user"]
1913
1956
  });
1914
1957
  if (profile.picture) {
@@ -1963,7 +2006,9 @@ const $userRealm = (options = {}) => {
1963
2006
  const securityProvider = alepha.inject(SecurityProvider);
1964
2007
  const userRealmProvider = alepha.inject(UserRealmProvider);
1965
2008
  const name = options.realm?.name ?? DEFAULT_USER_REALM_NAME;
1966
- userRealmProvider.register(name, options);
2009
+ const userRealm = userRealmProvider.register(name, options);
2010
+ if (options.modules?.audits) {}
2011
+ if (options.modules?.files) alepha.with(AlephaApiFiles);
1967
2012
  const realm = $realm({
1968
2013
  ...options.realm,
1969
2014
  name,
@@ -2000,12 +2045,14 @@ const $userRealm = (options = {}) => {
2000
2045
  realm.login = (name$1) => {
2001
2046
  return (credentials) => sessionService.login(name$1, credentials.username, credentials.password);
2002
2047
  };
2003
- if (options.identities) {
2004
- const identities$1 = {};
2005
- if (options.identities?.credentials) identities$1.credentials = $authCredentials(realm);
2006
- if (options.identities?.google) identities$1.google = $authGoogle(realm);
2007
- if (options.identities?.github) identities$1.github = $authGithub(realm);
2008
- alepha.with(() => identities$1);
2048
+ const identities$1 = options.identities ?? { credentials: true };
2049
+ if (identities$1) {
2050
+ const auth = {};
2051
+ if (identities$1.credentials) auth.credentials = $authCredentials(realm);
2052
+ else userRealm.settings.registrationAllowed = false;
2053
+ if (identities$1.google) auth.google = $authGoogle(realm);
2054
+ if (identities$1.github) auth.github = $authGithub(realm);
2055
+ alepha.with(() => auth);
2009
2056
  }
2010
2057
  return realm;
2011
2058
  };