@getstrata/bootstrap 0.4.2 → 0.4.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # @getstrata/bootstrap changelog
2
2
 
3
+ ## 0.4.3
4
+
5
+ - Cookie session `mapUser` / row mapping can pass `email_verified_at` through as `emailVerifiedAt` so HTML email verification works.
6
+ - Session insert binds `expires_at` as an ISO string so SQLite cookie login does not fail parameter binding.
7
+
3
8
  ## 0.4.2
4
9
 
5
10
  - `HttpKernel.wrapApi` uses `withJsonErrorHandling`. Hybrid views do not turn API errors into HTML.
package/README.md CHANGED
@@ -38,4 +38,4 @@ HTML apps should bind `createCookieSessionAuthManager` from `@getstrata/bootstra
38
38
 
39
39
  `registerDefaultJobs()` registers `cache.invalidate-tags` and `audit.export` only. Apps that dispatch model webhooks should call `registerWebhookJobs()` themselves.
40
40
 
41
- These subpaths assemble leftover fixture HTTP for framework tests and are not a generic starter API: `@getstrata/bootstrap/createRoutes`, `@getstrata/bootstrap/schedule`, `@getstrata/bootstrap/createWebRoutes`. New apps should use `buildWebModuleRoutes` / `buildModuleRoutes`. HiroApp uses `createApp()` in `apps/hiroapp`.
41
+ These subpaths assemble leftover fixture HTTP for framework tests and are not a generic starter API: `@getstrata/bootstrap/createRoutes`, `@getstrata/bootstrap/schedule`, `@getstrata/bootstrap/createWebRoutes`. New apps should use `buildWebModuleRoutes` / `buildModuleRoutes`. Generated examples use `createApp()` in `apps/hiroapp`.
@@ -6,6 +6,7 @@ export interface SessionUser {
6
6
  email: string;
7
7
  learn_subscriber?: boolean;
8
8
  is_admin?: boolean;
9
+ email_verified_at?: Date | string | null;
9
10
  }
10
11
  type SqlClient = {
11
12
  unsafe<T>(query: string, params?: readonly unknown[]): Promise<T[]>;
@@ -34,7 +34,8 @@ function defaultSessionSql() {
34
34
  function defaultMapSessionUser(user) {
35
35
  return {
36
36
  id: user.id,
37
- role: user.is_admin ? "admin" : "member"
37
+ role: user.is_admin ? "admin" : "member",
38
+ ...user.email_verified_at !== undefined ? { emailVerifiedAt: user.email_verified_at } : {}
38
39
  };
39
40
  }
40
41
  function sessionDisplayName(row, email) {
@@ -53,7 +54,8 @@ function mapSessionUserRow(row) {
53
54
  name: sessionDisplayName(row, email),
54
55
  email,
55
56
  learn_subscriber: Boolean(row.learn_subscriber),
56
- is_admin: Boolean(row.is_admin)
57
+ is_admin: Boolean(row.is_admin),
58
+ ...row.email_verified_at !== undefined ? { email_verified_at: row.email_verified_at } : {}
57
59
  };
58
60
  }
59
61
  async function defaultLoadSessionUser(sql, sessionId) {
@@ -120,7 +122,7 @@ class CookieSessionStore {
120
122
  const id = randomBytes(32).toString("hex");
121
123
  const expires = new Date(Date.now() + this.maxAgeSeconds * 1000);
122
124
  await this.sql().unsafe(`INSERT INTO sessions (id, user_id, expires_at, user_agent, ip_address, last_active_at)
123
- VALUES (${sqlPlaceholder(1)}, ${sqlPlaceholder(2)}, ${sqlPlaceholder(3)}, ${sqlPlaceholder(4)}, ${sqlPlaceholder(5)}, ${sqlNow()})`, [id, user.id, expires, meta.userAgent ?? null, meta.ipAddress ?? null]);
125
+ VALUES (${sqlPlaceholder(1)}, ${sqlPlaceholder(2)}, ${sqlPlaceholder(3)}, ${sqlPlaceholder(4)}, ${sqlPlaceholder(5)}, ${sqlNow()})`, [id, user.id, expires.toISOString(), meta.userAgent ?? null, meta.ipAddress ?? null]);
124
126
  return id;
125
127
  }
126
128
  async destroy(sessionId) {
package/dist/index.js CHANGED
@@ -1423,7 +1423,8 @@ function defaultSessionSql() {
1423
1423
  function defaultMapSessionUser(user) {
1424
1424
  return {
1425
1425
  id: user.id,
1426
- role: user.is_admin ? "admin" : "member"
1426
+ role: user.is_admin ? "admin" : "member",
1427
+ ...user.email_verified_at !== undefined ? { emailVerifiedAt: user.email_verified_at } : {}
1427
1428
  };
1428
1429
  }
1429
1430
  function sessionDisplayName(row, email) {
@@ -1442,7 +1443,8 @@ function mapSessionUserRow(row) {
1442
1443
  name: sessionDisplayName(row, email),
1443
1444
  email,
1444
1445
  learn_subscriber: Boolean(row.learn_subscriber),
1445
- is_admin: Boolean(row.is_admin)
1446
+ is_admin: Boolean(row.is_admin),
1447
+ ...row.email_verified_at !== undefined ? { email_verified_at: row.email_verified_at } : {}
1446
1448
  };
1447
1449
  }
1448
1450
  async function defaultLoadSessionUser(sql, sessionId) {
@@ -1509,7 +1511,7 @@ class CookieSessionStore {
1509
1511
  const id = randomBytes(32).toString("hex");
1510
1512
  const expires = new Date(Date.now() + this.maxAgeSeconds * 1000);
1511
1513
  await this.sql().unsafe(`INSERT INTO sessions (id, user_id, expires_at, user_agent, ip_address, last_active_at)
1512
- VALUES (${sqlPlaceholder(1)}, ${sqlPlaceholder(2)}, ${sqlPlaceholder(3)}, ${sqlPlaceholder(4)}, ${sqlPlaceholder(5)}, ${sqlNow()})`, [id, user.id, expires, meta.userAgent ?? null, meta.ipAddress ?? null]);
1514
+ VALUES (${sqlPlaceholder(1)}, ${sqlPlaceholder(2)}, ${sqlPlaceholder(3)}, ${sqlPlaceholder(4)}, ${sqlPlaceholder(5)}, ${sqlNow()})`, [id, user.id, expires.toISOString(), meta.userAgent ?? null, meta.ipAddress ?? null]);
1513
1515
  return id;
1514
1516
  }
1515
1517
  async destroy(sessionId) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getstrata/bootstrap",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "description": "Strata application bootstrap: HttpKernel, DI, web session helpers",
5
5
  "type": "module",
6
6
  "license": "MIT",