Openstatus www.openstatus.dev

๐Ÿ’Œ email subscriber (#509)

* ๐Ÿ’Œ email subscriber

* ๐Ÿ’Œ email subscriber

* ๐Ÿ’Œ email subscriber

* ๐Ÿ’Œ subscriber

* ๐Ÿ’Œ subscriber

* ๐Ÿ’Œ subscriber

* ๐Ÿ’Œ subscriber

authored by

Thibault Le Ouay and committed by
GitHub
7c074441 4e25fce3

+1943 -162
+1
apps/server/package.json
··· 14 14 "@hono/sentry": "1.0.0", 15 15 "@hono/zod-openapi": "0.8.3", 16 16 "@openstatus/db": "workspace:*", 17 + "@openstatus/emails": "workspace:*", 17 18 "@openstatus/notification-discord": "workspace:*", 18 19 "@openstatus/notification-emails": "workspace:*", 19 20 "@openstatus/notification-slack": "workspace:*",
+129
apps/server/src/v1/page.ts
··· 1 + import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi"; 2 + 3 + import { and, eq } from "@openstatus/db"; 4 + import { db } from "@openstatus/db/src/db"; 5 + import { page, pageSubscriber } from "@openstatus/db/src/schema"; 6 + import { sendEmail, SubscribeEmail } from "@openstatus/emails"; 7 + 8 + import type { Variables } from "."; 9 + import { ErrorSchema } from "./shared"; 10 + 11 + const pageApi = new OpenAPIHono<{ Variables: Variables }>(); 12 + 13 + const ParamsSchema = z.object({ 14 + id: z 15 + .string() 16 + .min(1) 17 + .openapi({ 18 + param: { 19 + name: "id", 20 + in: "path", 21 + }, 22 + description: "The id of the page", 23 + example: "1", 24 + }), 25 + }); 26 + 27 + const pageSubscriberSchema = z.object({ 28 + email: z.string().email().openapi({ 29 + description: "The email of the subscriber", 30 + }), 31 + }); 32 + 33 + const postRouteSubscriber = createRoute({ 34 + method: "post", 35 + tags: ["status_report"], 36 + path: "/:id/update", 37 + description: "Add a subscriber to a status report", 38 + request: { 39 + params: ParamsSchema, 40 + body: { 41 + description: "the subscriber payload", 42 + content: { 43 + "application/json": { 44 + schema: z.object({ 45 + email: z 46 + .string() 47 + .email() 48 + .openapi({ description: "The email of the subscriber" }), 49 + }), 50 + }, 51 + }, 52 + }, 53 + }, 54 + responses: { 55 + 200: { 56 + content: { 57 + "application/json": { 58 + schema: pageSubscriberSchema, 59 + }, 60 + }, 61 + description: "The user", 62 + }, 63 + 400: { 64 + content: { 65 + "application/json": { 66 + schema: ErrorSchema, 67 + }, 68 + }, 69 + description: "Returns an error", 70 + }, 71 + }, 72 + }); 73 + 74 + pageApi.openapi(postRouteSubscriber, async (c) => { 75 + const input = c.req.valid("json"); 76 + const { id } = c.req.valid("param"); 77 + const workspaceId = Number(c.get("workspaceId")); 78 + 79 + const pageId = Number(id); 80 + const _page = await db 81 + .select() 82 + .from(page) 83 + .where(and(eq(page.id, pageId), eq(page.workspaceId, workspaceId))) 84 + .get(); 85 + 86 + if (!_page) return c.jsonT({ code: 401, message: "Not authorized" }); 87 + 88 + const alreadySubscribed = await db 89 + .select() 90 + .from(pageSubscriber) 91 + .where( 92 + and( 93 + eq(pageSubscriber.email, input.email), 94 + eq(pageSubscriber.pageId, pageId), 95 + ), 96 + ) 97 + .get(); 98 + if (alreadySubscribed) 99 + return c.jsonT({ code: 401, message: "Already subscribed" }); 100 + 101 + // TODO: send email for verification 102 + const token = (Math.random() + 1).toString(36).substring(10); 103 + 104 + await sendEmail({ 105 + react: SubscribeEmail({ 106 + domain: _page.slug, 107 + token: token, 108 + page: page.title, 109 + }), 110 + from: "OpenStatus <notification@openstatus.dev>", 111 + to: [input.email], 112 + subject: "Verify your subscription", 113 + }); 114 + const _statusReportSubscriberUpdate = await db 115 + .insert(pageSubscriber) 116 + .values({ 117 + email: input.email, 118 + token, 119 + expiresAt: new Date(Date.now() + 1000 * 60 * 60 * 24 * 7), 120 + }) 121 + .returning() 122 + .get(); 123 + 124 + const data = pageSubscriberSchema.parse(_statusReportSubscriberUpdate); 125 + 126 + return c.jsonT({ 127 + ...data, 128 + }); 129 + });
+1
apps/server/src/v1/statusReport.ts
··· 58 58 }) 59 59 .default([]), 60 60 }); 61 + 61 62 const getAllRoute = createRoute({ 62 63 method: "get", 63 64 tags: ["status_report"],
+61
apps/web/src/app/status-page/[domain]/subscribe/route.ts
··· 1 + import { z } from "zod"; 2 + 3 + import { and, eq } from "@openstatus/db"; 4 + import { db } from "@openstatus/db/src/db"; 5 + import { page, pageSubscriber } from "@openstatus/db/src/schema"; 6 + import { sendEmail, SubscribeEmail } from "@openstatus/emails"; 7 + 8 + export async function POST( 9 + req: Request, 10 + { params }: { params: { domain: string } }, 11 + ) { 12 + // 13 + const data = await req.json(); 14 + const result = z.object({ email: z.string().email() }).parse(data); 15 + 16 + const pageData = await db 17 + .select() 18 + .from(page) 19 + .where(eq(page.slug, params.domain)) 20 + .get(); 21 + if (!pageData) { 22 + return new Response("Not found", { status: 401 }); 23 + } 24 + 25 + const alreadySubscribed = await db 26 + .select() 27 + .from(pageSubscriber) 28 + .where( 29 + and( 30 + eq(pageSubscriber.email, data.email), 31 + eq(pageSubscriber.pageId, pageData?.id), 32 + ), 33 + ) 34 + .get(); 35 + 36 + if (alreadySubscribed) { 37 + return new Response("Not found", { status: 401 }); 38 + } 39 + 40 + const token = (Math.random() + 1).toString(36).substring(10); 41 + 42 + await sendEmail({ 43 + react: SubscribeEmail({ 44 + domain: params.domain, 45 + token: token, 46 + page: pageData.title, 47 + }), 48 + from: "OpenStatus <notification@openstatus.dev>", 49 + to: [result.email], 50 + subject: "Verify your subscription", 51 + }); 52 + await db 53 + .insert(pageSubscriber) 54 + .values({ 55 + email: result.email, 56 + token, 57 + expiresAt: new Date(Date.now() + 1000 * 60 * 60 * 24 * 7), 58 + }) 59 + .execute(); 60 + return Response.json({ message: "Hello world" }); 61 + }
+39
apps/web/src/app/status-page/[domain]/verify/[token]/route.ts
··· 1 + import { and, db, eq } from "@openstatus/db"; 2 + import { page, pageSubscriber } from "@openstatus/db/src/schema"; 3 + 4 + export async function GET( 5 + request: Request, 6 + { params }: { params: { domain: string; token: string } }, 7 + ) { 8 + const pageId = await db 9 + .select() 10 + .from(page) 11 + .where(eq(page.slug, params.domain)) 12 + .get(); 13 + if (!pageId) { 14 + return new Response("Not found", { status: 401 }); 15 + } 16 + 17 + const subscriber = await db 18 + .select() 19 + .from(pageSubscriber) 20 + .where( 21 + and( 22 + eq(pageSubscriber.token, params.token), 23 + eq(pageSubscriber.pageId, pageId?.id), 24 + ), 25 + ) 26 + .get(); 27 + 28 + if (!subscriber) { 29 + return new Response("Not found", { status: 401 }); 30 + } 31 + 32 + await db 33 + .update(pageSubscriber) 34 + .set({ acceptedAt: new Date() }) 35 + .where(eq(pageSubscriber.id, subscriber.id)) 36 + .execute(); 37 + 38 + return Response.redirect(`https://${params.domain}.openstatus.dev`); 39 + }
+11
packages/db/drizzle/0013_tired_paladin.sql
··· 1 + CREATE TABLE `page_subscriber` ( 2 + `id` integer PRIMARY KEY NOT NULL, 3 + `email` text NOT NULL, 4 + `page_id` integer, 5 + `token` text, 6 + `accepted_at` integer, 7 + `expires_at` integer, 8 + `created_at` integer DEFAULT (strftime('%s', 'now')), 9 + `updated_at` integer DEFAULT (strftime('%s', 'now')), 10 + FOREIGN KEY (`page_id`) REFERENCES `page`(`id`) ON UPDATE no action ON DELETE no action 11 + );
+1250
packages/db/drizzle/meta/0013_snapshot.json
··· 1 + { 2 + "version": "5", 3 + "dialect": "sqlite", 4 + "id": "5ac15aa5-4512-4f06-92e3-4410ce097034", 5 + "prevId": "b5c53ce9-981d-4a7c-a0da-c82e517fc0a3", 6 + "tables": { 7 + "status_report_to_monitors": { 8 + "name": "status_report_to_monitors", 9 + "columns": { 10 + "monitor_id": { 11 + "name": "monitor_id", 12 + "type": "integer", 13 + "primaryKey": false, 14 + "notNull": true, 15 + "autoincrement": false 16 + }, 17 + "status_report_id": { 18 + "name": "status_report_id", 19 + "type": "integer", 20 + "primaryKey": false, 21 + "notNull": true, 22 + "autoincrement": false 23 + } 24 + }, 25 + "indexes": {}, 26 + "foreignKeys": { 27 + "status_report_to_monitors_monitor_id_monitor_id_fk": { 28 + "name": "status_report_to_monitors_monitor_id_monitor_id_fk", 29 + "tableFrom": "status_report_to_monitors", 30 + "tableTo": "monitor", 31 + "columnsFrom": [ 32 + "monitor_id" 33 + ], 34 + "columnsTo": [ 35 + "id" 36 + ], 37 + "onDelete": "cascade", 38 + "onUpdate": "no action" 39 + }, 40 + "status_report_to_monitors_status_report_id_status_report_id_fk": { 41 + "name": "status_report_to_monitors_status_report_id_status_report_id_fk", 42 + "tableFrom": "status_report_to_monitors", 43 + "tableTo": "status_report", 44 + "columnsFrom": [ 45 + "status_report_id" 46 + ], 47 + "columnsTo": [ 48 + "id" 49 + ], 50 + "onDelete": "cascade", 51 + "onUpdate": "no action" 52 + } 53 + }, 54 + "compositePrimaryKeys": { 55 + "status_report_to_monitors_monitor_id_status_report_id_pk": { 56 + "columns": [ 57 + "monitor_id", 58 + "status_report_id" 59 + ] 60 + } 61 + }, 62 + "uniqueConstraints": {} 63 + }, 64 + "status_reports_to_pages": { 65 + "name": "status_reports_to_pages", 66 + "columns": { 67 + "page_id": { 68 + "name": "page_id", 69 + "type": "integer", 70 + "primaryKey": false, 71 + "notNull": true, 72 + "autoincrement": false 73 + }, 74 + "status_report_id": { 75 + "name": "status_report_id", 76 + "type": "integer", 77 + "primaryKey": false, 78 + "notNull": true, 79 + "autoincrement": false 80 + } 81 + }, 82 + "indexes": {}, 83 + "foreignKeys": { 84 + "status_reports_to_pages_page_id_page_id_fk": { 85 + "name": "status_reports_to_pages_page_id_page_id_fk", 86 + "tableFrom": "status_reports_to_pages", 87 + "tableTo": "page", 88 + "columnsFrom": [ 89 + "page_id" 90 + ], 91 + "columnsTo": [ 92 + "id" 93 + ], 94 + "onDelete": "cascade", 95 + "onUpdate": "no action" 96 + }, 97 + "status_reports_to_pages_status_report_id_status_report_id_fk": { 98 + "name": "status_reports_to_pages_status_report_id_status_report_id_fk", 99 + "tableFrom": "status_reports_to_pages", 100 + "tableTo": "status_report", 101 + "columnsFrom": [ 102 + "status_report_id" 103 + ], 104 + "columnsTo": [ 105 + "id" 106 + ], 107 + "onDelete": "cascade", 108 + "onUpdate": "no action" 109 + } 110 + }, 111 + "compositePrimaryKeys": { 112 + "status_reports_to_pages_page_id_status_report_id_pk": { 113 + "columns": [ 114 + "page_id", 115 + "status_report_id" 116 + ] 117 + } 118 + }, 119 + "uniqueConstraints": {} 120 + }, 121 + "status_report": { 122 + "name": "status_report", 123 + "columns": { 124 + "id": { 125 + "name": "id", 126 + "type": "integer", 127 + "primaryKey": true, 128 + "notNull": true, 129 + "autoincrement": false 130 + }, 131 + "status": { 132 + "name": "status", 133 + "type": "text", 134 + "primaryKey": false, 135 + "notNull": true, 136 + "autoincrement": false 137 + }, 138 + "title": { 139 + "name": "title", 140 + "type": "text(256)", 141 + "primaryKey": false, 142 + "notNull": true, 143 + "autoincrement": false 144 + }, 145 + "workspace_id": { 146 + "name": "workspace_id", 147 + "type": "integer", 148 + "primaryKey": false, 149 + "notNull": false, 150 + "autoincrement": false 151 + }, 152 + "created_at": { 153 + "name": "created_at", 154 + "type": "integer", 155 + "primaryKey": false, 156 + "notNull": false, 157 + "autoincrement": false, 158 + "default": "(strftime('%s', 'now'))" 159 + }, 160 + "updated_at": { 161 + "name": "updated_at", 162 + "type": "integer", 163 + "primaryKey": false, 164 + "notNull": false, 165 + "autoincrement": false, 166 + "default": "(strftime('%s', 'now'))" 167 + } 168 + }, 169 + "indexes": {}, 170 + "foreignKeys": { 171 + "status_report_workspace_id_workspace_id_fk": { 172 + "name": "status_report_workspace_id_workspace_id_fk", 173 + "tableFrom": "status_report", 174 + "tableTo": "workspace", 175 + "columnsFrom": [ 176 + "workspace_id" 177 + ], 178 + "columnsTo": [ 179 + "id" 180 + ], 181 + "onDelete": "no action", 182 + "onUpdate": "no action" 183 + } 184 + }, 185 + "compositePrimaryKeys": {}, 186 + "uniqueConstraints": {} 187 + }, 188 + "status_report_update": { 189 + "name": "status_report_update", 190 + "columns": { 191 + "id": { 192 + "name": "id", 193 + "type": "integer", 194 + "primaryKey": true, 195 + "notNull": true, 196 + "autoincrement": false 197 + }, 198 + "status": { 199 + "name": "status", 200 + "type": "text(4)", 201 + "primaryKey": false, 202 + "notNull": true, 203 + "autoincrement": false 204 + }, 205 + "date": { 206 + "name": "date", 207 + "type": "integer", 208 + "primaryKey": false, 209 + "notNull": true, 210 + "autoincrement": false 211 + }, 212 + "message": { 213 + "name": "message", 214 + "type": "text", 215 + "primaryKey": false, 216 + "notNull": true, 217 + "autoincrement": false 218 + }, 219 + "status_report_id": { 220 + "name": "status_report_id", 221 + "type": "integer", 222 + "primaryKey": false, 223 + "notNull": true, 224 + "autoincrement": false 225 + }, 226 + "created_at": { 227 + "name": "created_at", 228 + "type": "integer", 229 + "primaryKey": false, 230 + "notNull": false, 231 + "autoincrement": false, 232 + "default": "(strftime('%s', 'now'))" 233 + }, 234 + "updated_at": { 235 + "name": "updated_at", 236 + "type": "integer", 237 + "primaryKey": false, 238 + "notNull": false, 239 + "autoincrement": false, 240 + "default": "(strftime('%s', 'now'))" 241 + } 242 + }, 243 + "indexes": {}, 244 + "foreignKeys": { 245 + "status_report_update_status_report_id_status_report_id_fk": { 246 + "name": "status_report_update_status_report_id_status_report_id_fk", 247 + "tableFrom": "status_report_update", 248 + "tableTo": "status_report", 249 + "columnsFrom": [ 250 + "status_report_id" 251 + ], 252 + "columnsTo": [ 253 + "id" 254 + ], 255 + "onDelete": "cascade", 256 + "onUpdate": "no action" 257 + } 258 + }, 259 + "compositePrimaryKeys": {}, 260 + "uniqueConstraints": {} 261 + }, 262 + "integration": { 263 + "name": "integration", 264 + "columns": { 265 + "id": { 266 + "name": "id", 267 + "type": "integer", 268 + "primaryKey": true, 269 + "notNull": true, 270 + "autoincrement": false 271 + }, 272 + "name": { 273 + "name": "name", 274 + "type": "text(256)", 275 + "primaryKey": false, 276 + "notNull": true, 277 + "autoincrement": false 278 + }, 279 + "workspace_id": { 280 + "name": "workspace_id", 281 + "type": "integer", 282 + "primaryKey": false, 283 + "notNull": false, 284 + "autoincrement": false 285 + }, 286 + "credential": { 287 + "name": "credential", 288 + "type": "text", 289 + "primaryKey": false, 290 + "notNull": false, 291 + "autoincrement": false 292 + }, 293 + "external_id": { 294 + "name": "external_id", 295 + "type": "text", 296 + "primaryKey": false, 297 + "notNull": true, 298 + "autoincrement": false 299 + }, 300 + "created_at": { 301 + "name": "created_at", 302 + "type": "integer", 303 + "primaryKey": false, 304 + "notNull": false, 305 + "autoincrement": false, 306 + "default": "(strftime('%s', 'now'))" 307 + }, 308 + "updated_at": { 309 + "name": "updated_at", 310 + "type": "integer", 311 + "primaryKey": false, 312 + "notNull": false, 313 + "autoincrement": false, 314 + "default": "(strftime('%s', 'now'))" 315 + }, 316 + "data": { 317 + "name": "data", 318 + "type": "text", 319 + "primaryKey": false, 320 + "notNull": true, 321 + "autoincrement": false 322 + } 323 + }, 324 + "indexes": {}, 325 + "foreignKeys": { 326 + "integration_workspace_id_workspace_id_fk": { 327 + "name": "integration_workspace_id_workspace_id_fk", 328 + "tableFrom": "integration", 329 + "tableTo": "workspace", 330 + "columnsFrom": [ 331 + "workspace_id" 332 + ], 333 + "columnsTo": [ 334 + "id" 335 + ], 336 + "onDelete": "no action", 337 + "onUpdate": "no action" 338 + } 339 + }, 340 + "compositePrimaryKeys": {}, 341 + "uniqueConstraints": {} 342 + }, 343 + "page": { 344 + "name": "page", 345 + "columns": { 346 + "id": { 347 + "name": "id", 348 + "type": "integer", 349 + "primaryKey": true, 350 + "notNull": true, 351 + "autoincrement": false 352 + }, 353 + "workspace_id": { 354 + "name": "workspace_id", 355 + "type": "integer", 356 + "primaryKey": false, 357 + "notNull": true, 358 + "autoincrement": false 359 + }, 360 + "title": { 361 + "name": "title", 362 + "type": "text", 363 + "primaryKey": false, 364 + "notNull": true, 365 + "autoincrement": false 366 + }, 367 + "description": { 368 + "name": "description", 369 + "type": "text", 370 + "primaryKey": false, 371 + "notNull": true, 372 + "autoincrement": false 373 + }, 374 + "icon": { 375 + "name": "icon", 376 + "type": "text(256)", 377 + "primaryKey": false, 378 + "notNull": false, 379 + "autoincrement": false, 380 + "default": "''" 381 + }, 382 + "slug": { 383 + "name": "slug", 384 + "type": "text(256)", 385 + "primaryKey": false, 386 + "notNull": true, 387 + "autoincrement": false 388 + }, 389 + "custom_domain": { 390 + "name": "custom_domain", 391 + "type": "text(256)", 392 + "primaryKey": false, 393 + "notNull": true, 394 + "autoincrement": false 395 + }, 396 + "published": { 397 + "name": "published", 398 + "type": "integer", 399 + "primaryKey": false, 400 + "notNull": false, 401 + "autoincrement": false, 402 + "default": false 403 + }, 404 + "created_at": { 405 + "name": "created_at", 406 + "type": "integer", 407 + "primaryKey": false, 408 + "notNull": false, 409 + "autoincrement": false, 410 + "default": "(strftime('%s', 'now'))" 411 + }, 412 + "updated_at": { 413 + "name": "updated_at", 414 + "type": "integer", 415 + "primaryKey": false, 416 + "notNull": false, 417 + "autoincrement": false, 418 + "default": "(strftime('%s', 'now'))" 419 + } 420 + }, 421 + "indexes": { 422 + "page_slug_unique": { 423 + "name": "page_slug_unique", 424 + "columns": [ 425 + "slug" 426 + ], 427 + "isUnique": true 428 + } 429 + }, 430 + "foreignKeys": { 431 + "page_workspace_id_workspace_id_fk": { 432 + "name": "page_workspace_id_workspace_id_fk", 433 + "tableFrom": "page", 434 + "tableTo": "workspace", 435 + "columnsFrom": [ 436 + "workspace_id" 437 + ], 438 + "columnsTo": [ 439 + "id" 440 + ], 441 + "onDelete": "cascade", 442 + "onUpdate": "no action" 443 + } 444 + }, 445 + "compositePrimaryKeys": {}, 446 + "uniqueConstraints": {} 447 + }, 448 + "monitor": { 449 + "name": "monitor", 450 + "columns": { 451 + "id": { 452 + "name": "id", 453 + "type": "integer", 454 + "primaryKey": true, 455 + "notNull": true, 456 + "autoincrement": false 457 + }, 458 + "job_type": { 459 + "name": "job_type", 460 + "type": "text", 461 + "primaryKey": false, 462 + "notNull": true, 463 + "autoincrement": false, 464 + "default": "'other'" 465 + }, 466 + "periodicity": { 467 + "name": "periodicity", 468 + "type": "text", 469 + "primaryKey": false, 470 + "notNull": true, 471 + "autoincrement": false, 472 + "default": "'other'" 473 + }, 474 + "status": { 475 + "name": "status", 476 + "type": "text", 477 + "primaryKey": false, 478 + "notNull": true, 479 + "autoincrement": false, 480 + "default": "'active'" 481 + }, 482 + "active": { 483 + "name": "active", 484 + "type": "integer", 485 + "primaryKey": false, 486 + "notNull": false, 487 + "autoincrement": false, 488 + "default": false 489 + }, 490 + "regions": { 491 + "name": "regions", 492 + "type": "text", 493 + "primaryKey": false, 494 + "notNull": true, 495 + "autoincrement": false, 496 + "default": "''" 497 + }, 498 + "url": { 499 + "name": "url", 500 + "type": "text(2048)", 501 + "primaryKey": false, 502 + "notNull": true, 503 + "autoincrement": false 504 + }, 505 + "name": { 506 + "name": "name", 507 + "type": "text(256)", 508 + "primaryKey": false, 509 + "notNull": true, 510 + "autoincrement": false, 511 + "default": "''" 512 + }, 513 + "description": { 514 + "name": "description", 515 + "type": "text", 516 + "primaryKey": false, 517 + "notNull": true, 518 + "autoincrement": false, 519 + "default": "''" 520 + }, 521 + "headers": { 522 + "name": "headers", 523 + "type": "text", 524 + "primaryKey": false, 525 + "notNull": false, 526 + "autoincrement": false, 527 + "default": "''" 528 + }, 529 + "body": { 530 + "name": "body", 531 + "type": "text", 532 + "primaryKey": false, 533 + "notNull": false, 534 + "autoincrement": false, 535 + "default": "''" 536 + }, 537 + "method": { 538 + "name": "method", 539 + "type": "text", 540 + "primaryKey": false, 541 + "notNull": false, 542 + "autoincrement": false, 543 + "default": "'GET'" 544 + }, 545 + "workspace_id": { 546 + "name": "workspace_id", 547 + "type": "integer", 548 + "primaryKey": false, 549 + "notNull": false, 550 + "autoincrement": false 551 + }, 552 + "created_at": { 553 + "name": "created_at", 554 + "type": "integer", 555 + "primaryKey": false, 556 + "notNull": false, 557 + "autoincrement": false, 558 + "default": "(strftime('%s', 'now'))" 559 + }, 560 + "updated_at": { 561 + "name": "updated_at", 562 + "type": "integer", 563 + "primaryKey": false, 564 + "notNull": false, 565 + "autoincrement": false, 566 + "default": "(strftime('%s', 'now'))" 567 + } 568 + }, 569 + "indexes": {}, 570 + "foreignKeys": { 571 + "monitor_workspace_id_workspace_id_fk": { 572 + "name": "monitor_workspace_id_workspace_id_fk", 573 + "tableFrom": "monitor", 574 + "tableTo": "workspace", 575 + "columnsFrom": [ 576 + "workspace_id" 577 + ], 578 + "columnsTo": [ 579 + "id" 580 + ], 581 + "onDelete": "no action", 582 + "onUpdate": "no action" 583 + } 584 + }, 585 + "compositePrimaryKeys": {}, 586 + "uniqueConstraints": {} 587 + }, 588 + "monitors_to_pages": { 589 + "name": "monitors_to_pages", 590 + "columns": { 591 + "monitor_id": { 592 + "name": "monitor_id", 593 + "type": "integer", 594 + "primaryKey": false, 595 + "notNull": true, 596 + "autoincrement": false 597 + }, 598 + "page_id": { 599 + "name": "page_id", 600 + "type": "integer", 601 + "primaryKey": false, 602 + "notNull": true, 603 + "autoincrement": false 604 + } 605 + }, 606 + "indexes": {}, 607 + "foreignKeys": { 608 + "monitors_to_pages_monitor_id_monitor_id_fk": { 609 + "name": "monitors_to_pages_monitor_id_monitor_id_fk", 610 + "tableFrom": "monitors_to_pages", 611 + "tableTo": "monitor", 612 + "columnsFrom": [ 613 + "monitor_id" 614 + ], 615 + "columnsTo": [ 616 + "id" 617 + ], 618 + "onDelete": "cascade", 619 + "onUpdate": "no action" 620 + }, 621 + "monitors_to_pages_page_id_page_id_fk": { 622 + "name": "monitors_to_pages_page_id_page_id_fk", 623 + "tableFrom": "monitors_to_pages", 624 + "tableTo": "page", 625 + "columnsFrom": [ 626 + "page_id" 627 + ], 628 + "columnsTo": [ 629 + "id" 630 + ], 631 + "onDelete": "cascade", 632 + "onUpdate": "no action" 633 + } 634 + }, 635 + "compositePrimaryKeys": { 636 + "monitors_to_pages_monitor_id_page_id_pk": { 637 + "columns": [ 638 + "monitor_id", 639 + "page_id" 640 + ] 641 + } 642 + }, 643 + "uniqueConstraints": {} 644 + }, 645 + "user": { 646 + "name": "user", 647 + "columns": { 648 + "id": { 649 + "name": "id", 650 + "type": "integer", 651 + "primaryKey": true, 652 + "notNull": true, 653 + "autoincrement": false 654 + }, 655 + "tenant_id": { 656 + "name": "tenant_id", 657 + "type": "text(256)", 658 + "primaryKey": false, 659 + "notNull": false, 660 + "autoincrement": false 661 + }, 662 + "first_name": { 663 + "name": "first_name", 664 + "type": "text", 665 + "primaryKey": false, 666 + "notNull": false, 667 + "autoincrement": false, 668 + "default": "''" 669 + }, 670 + "last_name": { 671 + "name": "last_name", 672 + "type": "text", 673 + "primaryKey": false, 674 + "notNull": false, 675 + "autoincrement": false, 676 + "default": "''" 677 + }, 678 + "email": { 679 + "name": "email", 680 + "type": "text", 681 + "primaryKey": false, 682 + "notNull": false, 683 + "autoincrement": false, 684 + "default": "''" 685 + }, 686 + "photo_url": { 687 + "name": "photo_url", 688 + "type": "text", 689 + "primaryKey": false, 690 + "notNull": false, 691 + "autoincrement": false, 692 + "default": "''" 693 + }, 694 + "created_at": { 695 + "name": "created_at", 696 + "type": "integer", 697 + "primaryKey": false, 698 + "notNull": false, 699 + "autoincrement": false, 700 + "default": "(strftime('%s', 'now'))" 701 + }, 702 + "updated_at": { 703 + "name": "updated_at", 704 + "type": "integer", 705 + "primaryKey": false, 706 + "notNull": false, 707 + "autoincrement": false, 708 + "default": "(strftime('%s', 'now'))" 709 + } 710 + }, 711 + "indexes": { 712 + "user_tenant_id_unique": { 713 + "name": "user_tenant_id_unique", 714 + "columns": [ 715 + "tenant_id" 716 + ], 717 + "isUnique": true 718 + } 719 + }, 720 + "foreignKeys": {}, 721 + "compositePrimaryKeys": {}, 722 + "uniqueConstraints": {} 723 + }, 724 + "users_to_workspaces": { 725 + "name": "users_to_workspaces", 726 + "columns": { 727 + "user_id": { 728 + "name": "user_id", 729 + "type": "integer", 730 + "primaryKey": false, 731 + "notNull": true, 732 + "autoincrement": false 733 + }, 734 + "workspace_id": { 735 + "name": "workspace_id", 736 + "type": "integer", 737 + "primaryKey": false, 738 + "notNull": true, 739 + "autoincrement": false 740 + }, 741 + "role": { 742 + "name": "role", 743 + "type": "text", 744 + "primaryKey": false, 745 + "notNull": true, 746 + "autoincrement": false, 747 + "default": "'member'" 748 + } 749 + }, 750 + "indexes": {}, 751 + "foreignKeys": { 752 + "users_to_workspaces_user_id_user_id_fk": { 753 + "name": "users_to_workspaces_user_id_user_id_fk", 754 + "tableFrom": "users_to_workspaces", 755 + "tableTo": "user", 756 + "columnsFrom": [ 757 + "user_id" 758 + ], 759 + "columnsTo": [ 760 + "id" 761 + ], 762 + "onDelete": "no action", 763 + "onUpdate": "no action" 764 + }, 765 + "users_to_workspaces_workspace_id_workspace_id_fk": { 766 + "name": "users_to_workspaces_workspace_id_workspace_id_fk", 767 + "tableFrom": "users_to_workspaces", 768 + "tableTo": "workspace", 769 + "columnsFrom": [ 770 + "workspace_id" 771 + ], 772 + "columnsTo": [ 773 + "id" 774 + ], 775 + "onDelete": "no action", 776 + "onUpdate": "no action" 777 + } 778 + }, 779 + "compositePrimaryKeys": { 780 + "users_to_workspaces_user_id_workspace_id_pk": { 781 + "columns": [ 782 + "user_id", 783 + "workspace_id" 784 + ] 785 + } 786 + }, 787 + "uniqueConstraints": {} 788 + }, 789 + "page_subscriber": { 790 + "name": "page_subscriber", 791 + "columns": { 792 + "id": { 793 + "name": "id", 794 + "type": "integer", 795 + "primaryKey": true, 796 + "notNull": true, 797 + "autoincrement": false 798 + }, 799 + "email": { 800 + "name": "email", 801 + "type": "text", 802 + "primaryKey": false, 803 + "notNull": true, 804 + "autoincrement": false 805 + }, 806 + "page_id": { 807 + "name": "page_id", 808 + "type": "integer", 809 + "primaryKey": false, 810 + "notNull": false, 811 + "autoincrement": false 812 + }, 813 + "token": { 814 + "name": "token", 815 + "type": "text", 816 + "primaryKey": false, 817 + "notNull": false, 818 + "autoincrement": false 819 + }, 820 + "accepted_at": { 821 + "name": "accepted_at", 822 + "type": "integer", 823 + "primaryKey": false, 824 + "notNull": false, 825 + "autoincrement": false 826 + }, 827 + "expires_at": { 828 + "name": "expires_at", 829 + "type": "integer", 830 + "primaryKey": false, 831 + "notNull": false, 832 + "autoincrement": false 833 + }, 834 + "created_at": { 835 + "name": "created_at", 836 + "type": "integer", 837 + "primaryKey": false, 838 + "notNull": false, 839 + "autoincrement": false, 840 + "default": "(strftime('%s', 'now'))" 841 + }, 842 + "updated_at": { 843 + "name": "updated_at", 844 + "type": "integer", 845 + "primaryKey": false, 846 + "notNull": false, 847 + "autoincrement": false, 848 + "default": "(strftime('%s', 'now'))" 849 + } 850 + }, 851 + "indexes": {}, 852 + "foreignKeys": { 853 + "page_subscriber_page_id_page_id_fk": { 854 + "name": "page_subscriber_page_id_page_id_fk", 855 + "tableFrom": "page_subscriber", 856 + "tableTo": "page", 857 + "columnsFrom": [ 858 + "page_id" 859 + ], 860 + "columnsTo": [ 861 + "id" 862 + ], 863 + "onDelete": "no action", 864 + "onUpdate": "no action" 865 + } 866 + }, 867 + "compositePrimaryKeys": {}, 868 + "uniqueConstraints": {} 869 + }, 870 + "workspace": { 871 + "name": "workspace", 872 + "columns": { 873 + "id": { 874 + "name": "id", 875 + "type": "integer", 876 + "primaryKey": true, 877 + "notNull": true, 878 + "autoincrement": false 879 + }, 880 + "slug": { 881 + "name": "slug", 882 + "type": "text", 883 + "primaryKey": false, 884 + "notNull": true, 885 + "autoincrement": false 886 + }, 887 + "name": { 888 + "name": "name", 889 + "type": "text", 890 + "primaryKey": false, 891 + "notNull": false, 892 + "autoincrement": false 893 + }, 894 + "stripe_id": { 895 + "name": "stripe_id", 896 + "type": "text(256)", 897 + "primaryKey": false, 898 + "notNull": false, 899 + "autoincrement": false 900 + }, 901 + "subscription_id": { 902 + "name": "subscription_id", 903 + "type": "text", 904 + "primaryKey": false, 905 + "notNull": false, 906 + "autoincrement": false 907 + }, 908 + "plan": { 909 + "name": "plan", 910 + "type": "text", 911 + "primaryKey": false, 912 + "notNull": false, 913 + "autoincrement": false 914 + }, 915 + "ends_at": { 916 + "name": "ends_at", 917 + "type": "integer", 918 + "primaryKey": false, 919 + "notNull": false, 920 + "autoincrement": false 921 + }, 922 + "paid_until": { 923 + "name": "paid_until", 924 + "type": "integer", 925 + "primaryKey": false, 926 + "notNull": false, 927 + "autoincrement": false 928 + }, 929 + "created_at": { 930 + "name": "created_at", 931 + "type": "integer", 932 + "primaryKey": false, 933 + "notNull": false, 934 + "autoincrement": false, 935 + "default": "(strftime('%s', 'now'))" 936 + }, 937 + "updated_at": { 938 + "name": "updated_at", 939 + "type": "integer", 940 + "primaryKey": false, 941 + "notNull": false, 942 + "autoincrement": false, 943 + "default": "(strftime('%s', 'now'))" 944 + } 945 + }, 946 + "indexes": { 947 + "workspace_slug_unique": { 948 + "name": "workspace_slug_unique", 949 + "columns": [ 950 + "slug" 951 + ], 952 + "isUnique": true 953 + }, 954 + "workspace_stripe_id_unique": { 955 + "name": "workspace_stripe_id_unique", 956 + "columns": [ 957 + "stripe_id" 958 + ], 959 + "isUnique": true 960 + } 961 + }, 962 + "foreignKeys": {}, 963 + "compositePrimaryKeys": {}, 964 + "uniqueConstraints": {} 965 + }, 966 + "notification": { 967 + "name": "notification", 968 + "columns": { 969 + "id": { 970 + "name": "id", 971 + "type": "integer", 972 + "primaryKey": true, 973 + "notNull": true, 974 + "autoincrement": false 975 + }, 976 + "name": { 977 + "name": "name", 978 + "type": "text", 979 + "primaryKey": false, 980 + "notNull": true, 981 + "autoincrement": false 982 + }, 983 + "provider": { 984 + "name": "provider", 985 + "type": "text", 986 + "primaryKey": false, 987 + "notNull": true, 988 + "autoincrement": false 989 + }, 990 + "data": { 991 + "name": "data", 992 + "type": "text", 993 + "primaryKey": false, 994 + "notNull": false, 995 + "autoincrement": false, 996 + "default": "'{}'" 997 + }, 998 + "workspace_id": { 999 + "name": "workspace_id", 1000 + "type": "integer", 1001 + "primaryKey": false, 1002 + "notNull": false, 1003 + "autoincrement": false 1004 + }, 1005 + "created_at": { 1006 + "name": "created_at", 1007 + "type": "integer", 1008 + "primaryKey": false, 1009 + "notNull": false, 1010 + "autoincrement": false, 1011 + "default": "(strftime('%s', 'now'))" 1012 + }, 1013 + "updated_at": { 1014 + "name": "updated_at", 1015 + "type": "integer", 1016 + "primaryKey": false, 1017 + "notNull": false, 1018 + "autoincrement": false, 1019 + "default": "(strftime('%s', 'now'))" 1020 + } 1021 + }, 1022 + "indexes": {}, 1023 + "foreignKeys": { 1024 + "notification_workspace_id_workspace_id_fk": { 1025 + "name": "notification_workspace_id_workspace_id_fk", 1026 + "tableFrom": "notification", 1027 + "tableTo": "workspace", 1028 + "columnsFrom": [ 1029 + "workspace_id" 1030 + ], 1031 + "columnsTo": [ 1032 + "id" 1033 + ], 1034 + "onDelete": "no action", 1035 + "onUpdate": "no action" 1036 + } 1037 + }, 1038 + "compositePrimaryKeys": {}, 1039 + "uniqueConstraints": {} 1040 + }, 1041 + "notifications_to_monitors": { 1042 + "name": "notifications_to_monitors", 1043 + "columns": { 1044 + "monitor_id": { 1045 + "name": "monitor_id", 1046 + "type": "integer", 1047 + "primaryKey": false, 1048 + "notNull": true, 1049 + "autoincrement": false 1050 + }, 1051 + "notification_id": { 1052 + "name": "notification_id", 1053 + "type": "integer", 1054 + "primaryKey": false, 1055 + "notNull": true, 1056 + "autoincrement": false 1057 + } 1058 + }, 1059 + "indexes": {}, 1060 + "foreignKeys": { 1061 + "notifications_to_monitors_monitor_id_monitor_id_fk": { 1062 + "name": "notifications_to_monitors_monitor_id_monitor_id_fk", 1063 + "tableFrom": "notifications_to_monitors", 1064 + "tableTo": "monitor", 1065 + "columnsFrom": [ 1066 + "monitor_id" 1067 + ], 1068 + "columnsTo": [ 1069 + "id" 1070 + ], 1071 + "onDelete": "cascade", 1072 + "onUpdate": "no action" 1073 + }, 1074 + "notifications_to_monitors_notification_id_notification_id_fk": { 1075 + "name": "notifications_to_monitors_notification_id_notification_id_fk", 1076 + "tableFrom": "notifications_to_monitors", 1077 + "tableTo": "notification", 1078 + "columnsFrom": [ 1079 + "notification_id" 1080 + ], 1081 + "columnsTo": [ 1082 + "id" 1083 + ], 1084 + "onDelete": "cascade", 1085 + "onUpdate": "no action" 1086 + } 1087 + }, 1088 + "compositePrimaryKeys": { 1089 + "notifications_to_monitors_monitor_id_notification_id_pk": { 1090 + "columns": [ 1091 + "monitor_id", 1092 + "notification_id" 1093 + ] 1094 + } 1095 + }, 1096 + "uniqueConstraints": {} 1097 + }, 1098 + "monitor_status": { 1099 + "name": "monitor_status", 1100 + "columns": { 1101 + "monitor_id": { 1102 + "name": "monitor_id", 1103 + "type": "integer", 1104 + "primaryKey": false, 1105 + "notNull": true, 1106 + "autoincrement": false 1107 + }, 1108 + "region": { 1109 + "name": "region", 1110 + "type": "text", 1111 + "primaryKey": false, 1112 + "notNull": true, 1113 + "autoincrement": false, 1114 + "default": "''" 1115 + }, 1116 + "status": { 1117 + "name": "status", 1118 + "type": "text", 1119 + "primaryKey": false, 1120 + "notNull": true, 1121 + "autoincrement": false, 1122 + "default": "'active'" 1123 + }, 1124 + "created_at": { 1125 + "name": "created_at", 1126 + "type": "integer", 1127 + "primaryKey": false, 1128 + "notNull": false, 1129 + "autoincrement": false, 1130 + "default": "(strftime('%s', 'now'))" 1131 + }, 1132 + "updated_at": { 1133 + "name": "updated_at", 1134 + "type": "integer", 1135 + "primaryKey": false, 1136 + "notNull": false, 1137 + "autoincrement": false, 1138 + "default": "(strftime('%s', 'now'))" 1139 + } 1140 + }, 1141 + "indexes": { 1142 + "monitor_status_idx": { 1143 + "name": "monitor_status_idx", 1144 + "columns": [ 1145 + "monitor_id", 1146 + "region" 1147 + ], 1148 + "isUnique": false 1149 + } 1150 + }, 1151 + "foreignKeys": { 1152 + "monitor_status_monitor_id_monitor_id_fk": { 1153 + "name": "monitor_status_monitor_id_monitor_id_fk", 1154 + "tableFrom": "monitor_status", 1155 + "tableTo": "monitor", 1156 + "columnsFrom": [ 1157 + "monitor_id" 1158 + ], 1159 + "columnsTo": [ 1160 + "id" 1161 + ], 1162 + "onDelete": "cascade", 1163 + "onUpdate": "no action" 1164 + } 1165 + }, 1166 + "compositePrimaryKeys": { 1167 + "monitor_status_monitor_id_region_pk": { 1168 + "columns": [ 1169 + "monitor_id", 1170 + "region" 1171 + ] 1172 + } 1173 + }, 1174 + "uniqueConstraints": {} 1175 + }, 1176 + "invitation": { 1177 + "name": "invitation", 1178 + "columns": { 1179 + "id": { 1180 + "name": "id", 1181 + "type": "integer", 1182 + "primaryKey": true, 1183 + "notNull": true, 1184 + "autoincrement": false 1185 + }, 1186 + "email": { 1187 + "name": "email", 1188 + "type": "text", 1189 + "primaryKey": false, 1190 + "notNull": true, 1191 + "autoincrement": false 1192 + }, 1193 + "role": { 1194 + "name": "role", 1195 + "type": "text", 1196 + "primaryKey": false, 1197 + "notNull": true, 1198 + "autoincrement": false, 1199 + "default": "'member'" 1200 + }, 1201 + "workspace_id": { 1202 + "name": "workspace_id", 1203 + "type": "integer", 1204 + "primaryKey": false, 1205 + "notNull": true, 1206 + "autoincrement": false 1207 + }, 1208 + "token": { 1209 + "name": "token", 1210 + "type": "text", 1211 + "primaryKey": false, 1212 + "notNull": true, 1213 + "autoincrement": false 1214 + }, 1215 + "expires_at": { 1216 + "name": "expires_at", 1217 + "type": "integer", 1218 + "primaryKey": false, 1219 + "notNull": true, 1220 + "autoincrement": false 1221 + }, 1222 + "created_at": { 1223 + "name": "created_at", 1224 + "type": "integer", 1225 + "primaryKey": false, 1226 + "notNull": false, 1227 + "autoincrement": false, 1228 + "default": "(strftime('%s', 'now'))" 1229 + }, 1230 + "accepted_at": { 1231 + "name": "accepted_at", 1232 + "type": "integer", 1233 + "primaryKey": false, 1234 + "notNull": false, 1235 + "autoincrement": false 1236 + } 1237 + }, 1238 + "indexes": {}, 1239 + "foreignKeys": {}, 1240 + "compositePrimaryKeys": {}, 1241 + "uniqueConstraints": {} 1242 + } 1243 + }, 1244 + "enums": {}, 1245 + "_meta": { 1246 + "schemas": {}, 1247 + "tables": {}, 1248 + "columns": {} 1249 + } 1250 + }
+7
packages/db/drizzle/meta/_journal.json
··· 92 92 "when": 1701713135829, 93 93 "tag": "0012_tan_magma", 94 94 "breakpoints": true 95 + }, 96 + { 97 + "idx": 13, 98 + "version": "5", 99 + "when": 1702144660818, 100 + "tag": "0013_tired_paladin", 101 + "breakpoints": true 95 102 } 96 103 ] 97 104 }
+1
packages/db/src/schema/index.ts
··· 3 3 export * from "./pages"; 4 4 export * from "./monitors"; 5 5 export * from "./users"; 6 + export * from "./page_subscribers"; 6 7 export * from "./workspaces"; 7 8 export * from "./shared"; 8 9 export * from "./notifications";
+3
packages/db/src/schema/page_subscribers/index.ts
··· 1 + export * from "./status_reports_subscribers"; 2 + export * from "./validation"; 3 + export type * from "./validation";
+28
packages/db/src/schema/page_subscribers/status_reports_subscribers.ts
··· 1 + import { relations, sql } from "drizzle-orm"; 2 + import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core"; 3 + 4 + import { page } from "../pages"; 5 + 6 + export const pageSubscriber = sqliteTable("page_subscriber", { 7 + id: integer("id").primaryKey(), 8 + email: text("email").notNull(), 9 + 10 + pageId: integer("page_id").references(() => page.id), 11 + 12 + token: text("token"), 13 + acceptedAt: integer("accepted_at", { mode: "timestamp" }), 14 + expiresAt: integer("expires_at", { mode: "timestamp" }), 15 + createdAt: integer("created_at", { mode: "timestamp" }).default( 16 + sql`(strftime('%s', 'now'))`, 17 + ), 18 + updatedAt: integer("updated_at", { mode: "timestamp" }).default( 19 + sql`(strftime('%s', 'now'))`, 20 + ), 21 + }); 22 + 23 + export const pageSubscriberRelation = relations(pageSubscriber, ({ one }) => ({ 24 + page: one(page, { 25 + fields: [pageSubscriber.pageId], 26 + references: [page.id], 27 + }), 28 + }));
+13
packages/db/src/schema/page_subscribers/validation.ts
··· 1 + import { createInsertSchema, createSelectSchema } from "drizzle-zod"; 2 + import { z } from "zod"; 3 + 4 + import { pageSubscriber } from "./status_reports_subscribers"; 5 + 6 + export const insertPageSubscriberSchema = createInsertSchema(pageSubscriber, { 7 + email: z.string().email(), 8 + }); 9 + 10 + export const selectPageSubscriberSchema = createSelectSchema(pageSubscriber); 11 + 12 + export type InsertPageSubscriber = z.infer<typeof insertPageSubscriberSchema>; 13 + export type PageSubscriber = z.infer<typeof selectPageSubscriberSchema>;
-1
packages/emails/emails/alert.tsx
··· 11 11 Preview, 12 12 Row, 13 13 Section, 14 - Tailwind, 15 14 Text, 16 15 } from "@react-email/components"; 17 16 import { z } from "zod";
+42
packages/emails/emails/subscribe.tsx
··· 1 + import { Body, Head, Html, Link, Preview } from "@react-email/components"; 2 + 3 + const SubscribeEmail = ({ 4 + token, 5 + page, 6 + domain, 7 + }: { 8 + token: string; 9 + page: string; 10 + domain: string; 11 + }) => { 12 + return ( 13 + <Html> 14 + <Head> 15 + <title>Confirm your subscription to {page} Status Page</title> 16 + <Preview>Confirm your subscription to {page} Status Page</Preview> 17 + <Body> 18 + <h1>Confirm your subscription to {page} Status Page</h1> 19 + <p> 20 + You are receiving this email because you subscribed to receive 21 + updates from {page} Status Page. 22 + </p> 23 + <p> 24 + To confirm your subscription, please click the link below. If you 25 + believe this is a mistake, please ignore this email. 26 + </p> 27 + <p> 28 + <a href={`https://${domain}.openstatus.dev/verify/${token}`}> 29 + Confirm subscription 30 + </a> 31 + </p> 32 + <br /> 33 + <br /> 34 + ๐Ÿš€ Powered by 35 + <Link href="https://www.openstatus.dev">OpenStatus.dev</Link> 36 + </Body> 37 + </Head> 38 + </Html> 39 + ); 40 + }; 41 + 42 + export default SubscribeEmail;
+4 -3
packages/emails/index.ts
··· 1 - import type { ReactElement } from "react"; 2 1 import { Resend } from "resend"; 3 2 4 3 import { Alert, EmailDataSchema } from "./emails/alert"; 4 + import SubscribeEmail from "./emails/subscribe"; 5 5 import { validateEmailNotDisposable } from "./emails/utils/utils"; 6 6 import WaitingList from "./emails/waiting-list"; 7 7 import WelcomeEmail from "./emails/welcome"; ··· 13 13 validateEmailNotDisposable, 14 14 Alert, 15 15 EmailDataSchema, 16 + SubscribeEmail, 16 17 }; 17 18 18 19 export const resend = new Resend(env.RESEND_API_KEY); 19 20 20 21 export interface Emails { 21 22 react: JSX.Element; 22 - subject: "Welcome to OpenStatus.dev ๐Ÿ‘‹"; 23 + subject: string; 23 24 to: string[]; 24 - from: "Thibault Le Ouay Ducasse <thibault@openstatus.dev>"; 25 + from: string; 25 26 } 26 27 27 28 export const sendEmail = async (email: Emails) => {
+2 -2
packages/emails/package.json
··· 16 16 "@react-email/html": "0.0.4", 17 17 "@react-email/tailwind": "0.0.9", 18 18 "@t3-oss/env-core": "0.7.0", 19 - "react-email": "1.9.5", 20 - "resend": "1.1.0", 19 + "react-email": "1.10.0", 20 + "resend": "2.0.0", 21 21 "zod": "3.22.2" 22 22 }, 23 23 "devDependencies": {
+351 -156
pnpm-lock.yaml
··· 46 46 '@openstatus/db': 47 47 specifier: workspace:* 48 48 version: link:../../packages/db 49 + '@openstatus/emails': 50 + specifier: workspace:* 51 + version: link:../../packages/emails 49 52 '@openstatus/notification-discord': 50 53 specifier: workspace:* 51 54 version: link:../../packages/notifications/discord ··· 509 512 specifier: 0.7.0 510 513 version: 0.7.0(typescript@5.2.2)(zod@3.22.2) 511 514 react-email: 512 - specifier: 1.9.5 513 - version: 1.9.5 515 + specifier: 1.10.0 516 + version: 1.10.0 514 517 resend: 515 - specifier: 1.1.0 516 - version: 1.1.0 518 + specifier: 2.0.0 519 + version: 2.0.0 517 520 zod: 518 521 specifier: 3.22.2 519 522 version: 3.22.2 ··· 2346 2349 - supports-color 2347 2350 dev: true 2348 2351 2352 + /@isaacs/cliui@8.0.2: 2353 + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} 2354 + engines: {node: '>=12'} 2355 + dependencies: 2356 + string-width: 5.1.2 2357 + string-width-cjs: /string-width@4.2.3 2358 + strip-ansi: 7.1.0 2359 + strip-ansi-cjs: /strip-ansi@6.0.1 2360 + wrap-ansi: 8.1.0 2361 + wrap-ansi-cjs: /wrap-ansi@7.0.0 2362 + dev: false 2363 + 2349 2364 /@jest/environment@29.7.0: 2350 2365 resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} 2351 2366 engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} ··· 2965 2980 tslib: 2.6.2 2966 2981 webcrypto-core: 1.7.7 2967 2982 dev: false 2983 + 2984 + /@pkgjs/parseargs@0.11.0: 2985 + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} 2986 + engines: {node: '>=14'} 2987 + requiresBuild: true 2988 + dev: false 2989 + optional: true 2968 2990 2969 2991 /@protobufjs/aspromise@1.1.2: 2970 2992 resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} ··· 4410 4432 react: 18.2.0 4411 4433 dev: false 4412 4434 4413 - /@react-email/render@0.0.6: 4414 - resolution: {integrity: sha512-6zs7WZbd37TcPT1OmMPH/kcBpv0QSi+k3om7LyDnbdIcrbwOO/OstVwUaa/6zgvDvnq9Y2wOosbru7j5kUrW9A==} 4415 - engines: {node: '>=16.0.0'} 4435 + /@react-email/render@0.0.10: 4436 + resolution: {integrity: sha512-FdLhg/E5PH5qZU/jf9NbvRi5v5134kbX7o8zIhOJIk/TALxB18ggprnH5tQX96dGQFqlLob8OLReaRwrpEF7YA==} 4437 + engines: {node: '>=18.0.0'} 4416 4438 dependencies: 4417 - html-to-text: 9.0.3 4439 + html-to-text: 9.0.5 4418 4440 pretty: 2.0.0 4419 4441 react: 18.2.0 4420 4442 react-dom: 18.2.0(react@18.2.0) ··· 4425 4447 engines: {node: '>=16.0.0'} 4426 4448 dependencies: 4427 4449 html-to-text: 9.0.3 4450 + pretty: 2.0.0 4451 + react: 18.2.0 4452 + react-dom: 18.2.0(react@18.2.0) 4453 + dev: false 4454 + 4455 + /@react-email/render@0.0.9: 4456 + resolution: {integrity: sha512-nrim7wiACnaXsGtL7GF6jp3Qmml8J6vAjAH88jkC8lIbfNZaCyuPQHANjyYIXlvQeAbsWADQJFZgOHUqFqjh/A==} 4457 + engines: {node: '>=18.0.0'} 4458 + dependencies: 4459 + html-to-text: 9.0.5 4428 4460 pretty: 2.0.0 4429 4461 react: 18.2.0 4430 4462 react-dom: 18.2.0(react@18.2.0) ··· 4515 4547 dependencies: 4516 4548 domhandler: 5.0.3 4517 4549 selderee: 0.10.0 4550 + dev: false 4551 + 4552 + /@selderee/plugin-htmlparser2@0.11.0: 4553 + resolution: {integrity: sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==} 4554 + dependencies: 4555 + domhandler: 5.0.3 4556 + selderee: 0.11.0 4518 4557 dev: false 4519 4558 4520 4559 /@sentry-internal/tracing@7.73.0: ··· 5162 5201 resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} 5163 5202 dev: true 5164 5203 5204 + /@types/minimist@1.2.5: 5205 + resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} 5206 + dev: false 5207 + 5165 5208 /@types/ms@0.7.33: 5166 5209 resolution: {integrity: sha512-AuHIyzR5Hea7ij0P9q7vx7xu4z0C28ucwjAZC0ja7JhINyCnOw8/DnvAPQQ9TfOlCtZAmCERKQX9+o1mgQhuOQ==} 5167 5210 ··· 5597 5640 dependencies: 5598 5641 type-fest: 0.21.3 5599 5642 dev: true 5643 + 5644 + /ansi-regex@2.1.1: 5645 + resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} 5646 + engines: {node: '>=0.10.0'} 5647 + dev: false 5600 5648 5601 5649 /ansi-regex@5.0.1: 5602 5650 resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 5603 5651 engines: {node: '>=8'} 5604 5652 5653 + /ansi-regex@6.0.1: 5654 + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} 5655 + engines: {node: '>=12'} 5656 + dev: false 5657 + 5605 5658 /ansi-sequence-parser@1.1.1: 5606 5659 resolution: {integrity: sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==} 5660 + dev: false 5661 + 5662 + /ansi-styles@2.2.1: 5663 + resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==} 5664 + engines: {node: '>=0.10.0'} 5607 5665 dev: false 5608 5666 5609 5667 /ansi-styles@3.2.1: ··· 5621 5679 /ansi-styles@5.2.0: 5622 5680 resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} 5623 5681 engines: {node: '>=10'} 5682 + dev: false 5683 + 5684 + /ansi-styles@6.2.1: 5685 + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} 5686 + engines: {node: '>=12'} 5624 5687 dev: false 5625 5688 5626 5689 /any-promise@1.3.0: ··· 5741 5804 is-shared-array-buffer: 1.0.2 5742 5805 dev: false 5743 5806 5807 + /arrify@1.0.1: 5808 + resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} 5809 + engines: {node: '>=0.10.0'} 5810 + dev: false 5811 + 5744 5812 /asn1js@3.0.5: 5745 5813 resolution: {integrity: sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==} 5746 5814 engines: {node: '>=12.0.0'} ··· 5834 5902 prebuild-install: 7.1.1 5835 5903 dev: false 5836 5904 5837 - /big-integer@1.6.51: 5838 - resolution: {integrity: sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==} 5839 - engines: {node: '>=0.6'} 5840 - dev: false 5841 - 5842 5905 /bignumber.js@9.1.2: 5843 5906 resolution: {integrity: sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==} 5844 5907 dev: false ··· 5846 5909 /binary-extensions@2.2.0: 5847 5910 resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} 5848 5911 engines: {node: '>=8'} 5849 - 5850 - /binary@0.3.0: 5851 - resolution: {integrity: sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==} 5852 - dependencies: 5853 - buffers: 0.1.1 5854 - chainsaw: 0.1.0 5855 - dev: false 5856 5912 5857 5913 /bindings@1.5.0: 5858 5914 resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} ··· 5905 5961 /buffer-from@1.1.2: 5906 5962 resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} 5907 5963 5908 - /buffer-indexof-polyfill@1.0.2: 5909 - resolution: {integrity: sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==} 5910 - engines: {node: '>=0.10'} 5911 - dev: false 5912 - 5913 5964 /buffer@5.7.1: 5914 5965 resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} 5915 5966 dependencies: 5916 5967 base64-js: 1.5.1 5917 5968 ieee754: 1.2.1 5918 - 5919 - /buffers@0.1.1: 5920 - resolution: {integrity: sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==} 5921 - engines: {node: '>=0.2.0'} 5922 - dev: false 5923 5969 5924 5970 /bufferutil@4.0.7: 5925 5971 resolution: {integrity: sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw==} ··· 6023 6069 /ccount@2.0.1: 6024 6070 resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} 6025 6071 6026 - /chainsaw@0.1.0: 6027 - resolution: {integrity: sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==} 6072 + /chalk@1.1.3: 6073 + resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} 6074 + engines: {node: '>=0.10.0'} 6028 6075 dependencies: 6029 - traverse: 0.3.9 6076 + ansi-styles: 2.2.1 6077 + escape-string-regexp: 1.0.5 6078 + has-ansi: 2.0.0 6079 + strip-ansi: 3.0.1 6080 + supports-color: 2.0.0 6030 6081 dev: false 6031 6082 6032 6083 /chalk@2.4.2: ··· 6154 6205 dependencies: 6155 6206 restore-cursor: 3.1.0 6156 6207 6208 + /cli-spinner@0.2.10: 6209 + resolution: {integrity: sha512-U0sSQ+JJvSLi1pAYuJykwiA8Dsr15uHEy85iCJ6A+0DjVxivr3d+N2Wjvodeg89uP5K6TswFkKBfAD7B3YSn/Q==} 6210 + engines: {node: '>=0.10'} 6211 + dev: false 6212 + 6157 6213 /cli-spinners@2.9.1: 6158 6214 resolution: {integrity: sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==} 6159 6215 engines: {node: '>=6'} ··· 6250 6306 /commander@4.1.1: 6251 6307 resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} 6252 6308 engines: {node: '>= 6'} 6253 - 6254 - /commander@5.1.0: 6255 - resolution: {integrity: sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==} 6256 - engines: {node: '>= 6'} 6257 - dev: false 6258 6309 6259 6310 /commander@9.4.1: 6260 6311 resolution: {integrity: sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==} ··· 6528 6579 dependencies: 6529 6580 ms: 2.1.2 6530 6581 6582 + /decamelize-keys@1.1.1: 6583 + resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} 6584 + engines: {node: '>=0.10.0'} 6585 + dependencies: 6586 + decamelize: 1.2.0 6587 + map-obj: 1.0.1 6588 + dev: false 6589 + 6590 + /decamelize@1.2.0: 6591 + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} 6592 + engines: {node: '>=0.10.0'} 6593 + dev: false 6594 + 6531 6595 /decimal.js-light@2.5.1: 6532 6596 resolution: {integrity: sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==} 6533 6597 dev: false ··· 6870 6934 zod: 3.22.2 6871 6935 dev: false 6872 6936 6873 - /duplexer2@0.1.4: 6874 - resolution: {integrity: sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==} 6875 - dependencies: 6876 - readable-stream: 2.3.8 6877 - dev: false 6878 - 6879 6937 /duplexify@4.1.2: 6880 6938 resolution: {integrity: sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==} 6881 6939 dependencies: ··· 6883 6941 inherits: 2.0.4 6884 6942 readable-stream: 3.6.2 6885 6943 stream-shift: 1.0.1 6944 + dev: false 6945 + 6946 + /eastasianwidth@0.2.0: 6947 + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} 6886 6948 dev: false 6887 6949 6888 6950 /ecdsa-sig-formatter@1.0.11: ··· 7622 7684 engines: {node: '>=6.0.0'} 7623 7685 dev: false 7624 7686 7625 - /fast-folder-size@1.6.1: 7626 - resolution: {integrity: sha512-F3tRpfkAzb7TT2JNKaJUglyuRjRa+jelQD94s9OSqkfEeytLmupCqQiD+H2KoIXGtp4pB5m4zNmv5m2Ktcr+LA==} 7627 - hasBin: true 7628 - requiresBuild: true 7629 - dependencies: 7630 - unzipper: 0.10.14 7631 - dev: false 7632 - 7633 7687 /fast-glob@3.3.1: 7634 7688 resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} 7635 7689 engines: {node: '>=8.6.0'} ··· 7724 7778 is-callable: 1.2.7 7725 7779 dev: false 7726 7780 7781 + /foreground-child@3.1.1: 7782 + resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} 7783 + engines: {node: '>=14'} 7784 + dependencies: 7785 + cross-spawn: 7.0.3 7786 + signal-exit: 4.1.0 7787 + dev: false 7788 + 7727 7789 /form-data@2.5.1: 7728 7790 resolution: {integrity: sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==} 7729 7791 engines: {node: '>= 0.12'} ··· 7811 7873 requiresBuild: true 7812 7874 optional: true 7813 7875 7814 - /fstream@1.0.12: 7815 - resolution: {integrity: sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==} 7816 - engines: {node: '>=0.6'} 7817 - dependencies: 7818 - graceful-fs: 4.2.11 7819 - inherits: 2.0.4 7820 - mkdirp: 0.5.6 7821 - rimraf: 2.7.1 7822 - dev: false 7823 - 7824 7876 /function-bind@1.1.2: 7825 7877 resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} 7826 7878 dev: false ··· 7938 7990 /glob-to-regexp@0.4.1: 7939 7991 resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} 7940 7992 7993 + /glob@10.3.4: 7994 + resolution: {integrity: sha512-6LFElP3A+i/Q8XQKEvZjkEWEOTgAIALR9AO2rwT8bgPhDd1anmqDJDZ6lLddI4ehxxxR1S5RIqKe1uapMQfYaQ==} 7995 + engines: {node: '>=16 || 14 >=14.17'} 7996 + hasBin: true 7997 + dependencies: 7998 + foreground-child: 3.1.1 7999 + jackspeak: 2.3.6 8000 + minimatch: 9.0.1 8001 + minipass: 7.0.4 8002 + path-scurry: 1.10.1 8003 + dev: false 8004 + 7941 8005 /glob@7.1.6: 7942 8006 resolution: {integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==} 7943 8007 dependencies: ··· 7969 8033 once: 1.4.0 7970 8034 path-is-absolute: 1.0.1 7971 8035 7972 - /glob@8.0.3: 7973 - resolution: {integrity: sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==} 7974 - engines: {node: '>=12'} 7975 - dependencies: 7976 - fs.realpath: 1.0.0 7977 - inflight: 1.0.6 7978 - inherits: 2.0.4 7979 - minimatch: 5.1.6 7980 - once: 1.4.0 7981 - dev: false 7982 - 7983 8036 /glob@8.1.0: 7984 8037 resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} 7985 8038 engines: {node: '>=12'} ··· 8121 8174 sisteransi: 1.0.5 8122 8175 dev: true 8123 8176 8177 + /hard-rejection@2.1.0: 8178 + resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} 8179 + engines: {node: '>=6'} 8180 + dev: false 8181 + 8182 + /has-ansi@2.0.0: 8183 + resolution: {integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==} 8184 + engines: {node: '>=0.10.0'} 8185 + dependencies: 8186 + ansi-regex: 2.1.1 8187 + dev: false 8188 + 8124 8189 /has-bigints@1.0.2: 8125 8190 resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} 8126 8191 dev: false ··· 8391 8456 selderee: 0.10.0 8392 8457 dev: false 8393 8458 8459 + /html-to-text@9.0.5: 8460 + resolution: {integrity: sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==} 8461 + engines: {node: '>=14'} 8462 + dependencies: 8463 + '@selderee/plugin-htmlparser2': 0.11.0 8464 + deepmerge: 4.3.1 8465 + dom-serializer: 2.0.0 8466 + htmlparser2: 8.0.2 8467 + selderee: 0.11.0 8468 + dev: false 8469 + 8394 8470 /html-void-elements@2.0.1: 8395 8471 resolution: {integrity: sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==} 8396 8472 dev: false ··· 8519 8595 /indent-string@4.0.0: 8520 8596 resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} 8521 8597 engines: {node: '>=8'} 8522 - dev: true 8523 8598 8524 8599 /inflection@2.0.1: 8525 8600 resolution: {integrity: sha512-wzkZHqpb4eGrOKBl34xy3umnYHx8Si5R1U4fwmdxLo5gdH6mEK8gclckTj/qWqy4Je0bsDYe/qazZYuO7xe3XQ==} ··· 8774 8849 resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} 8775 8850 engines: {node: '>=8'} 8776 8851 8852 + /is-plain-obj@1.1.0: 8853 + resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} 8854 + engines: {node: '>=0.10.0'} 8855 + dev: false 8856 + 8777 8857 /is-plain-obj@3.0.0: 8778 8858 resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==} 8779 8859 engines: {node: '>=10'} ··· 8888 8968 engines: {node: '>=0.10.0'} 8889 8969 dev: false 8890 8970 8891 - /isarray@1.0.0: 8892 - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} 8893 - dev: false 8894 - 8895 8971 /isarray@2.0.5: 8896 8972 resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} 8897 8973 dev: false ··· 8921 8997 has-symbols: 1.0.3 8922 8998 reflect.getprototypeof: 1.0.4 8923 8999 set-function-name: 2.0.1 9000 + dev: false 9001 + 9002 + /jackspeak@2.3.6: 9003 + resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} 9004 + engines: {node: '>=14'} 9005 + dependencies: 9006 + '@isaacs/cliui': 8.0.2 9007 + optionalDependencies: 9008 + '@pkgjs/parseargs': 0.11.0 8924 9009 dev: false 8925 9010 8926 9011 /jest-environment-jsdom@29.7.0: ··· 9222 9307 /lines-and-columns@1.2.4: 9223 9308 resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} 9224 9309 9225 - /listenercount@1.0.1: 9226 - resolution: {integrity: sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==} 9227 - dev: false 9228 - 9229 9310 /load-tsconfig@0.2.5: 9230 9311 resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} 9231 9312 engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} ··· 9261 9342 /lodash.get@4.4.2: 9262 9343 resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} 9263 9344 dev: true 9345 + 9346 + /lodash.includes@4.3.0: 9347 + resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} 9348 + dev: false 9264 9349 9265 9350 /lodash.isplainobject@4.0.6: 9266 9351 resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} ··· 9314 9399 resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} 9315 9400 dependencies: 9316 9401 tslib: 2.6.2 9402 + dev: false 9403 + 9404 + /lru-cache@10.1.0: 9405 + resolution: {integrity: sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==} 9406 + engines: {node: 14 || >=16.14} 9317 9407 dev: false 9318 9408 9319 9409 /lru-cache@5.1.1: ··· 9366 9456 resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} 9367 9457 dev: true 9368 9458 9459 + /map-obj@1.0.1: 9460 + resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} 9461 + engines: {node: '>=0.10.0'} 9462 + dev: false 9463 + 9369 9464 /map-obj@4.3.0: 9370 9465 resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} 9371 9466 engines: {node: '>=8'} ··· 9609 9704 next-tick: 1.1.0 9610 9705 timers-ext: 0.1.7 9611 9706 dev: true 9707 + 9708 + /meow@7.1.1: 9709 + resolution: {integrity: sha512-GWHvA5QOcS412WCo8vwKDlTelGLsCGBVevQB5Kva961rmNfun0PCbv5+xta2kUMFJyR8/oWnn7ddeKdosbAPbA==} 9710 + engines: {node: '>=10'} 9711 + dependencies: 9712 + '@types/minimist': 1.2.5 9713 + camelcase-keys: 6.2.2 9714 + decamelize-keys: 1.1.1 9715 + hard-rejection: 2.1.0 9716 + minimist-options: 4.1.0 9717 + normalize-package-data: 2.5.0 9718 + read-pkg-up: 7.0.1 9719 + redent: 3.0.0 9720 + trim-newlines: 3.0.1 9721 + type-fest: 0.13.1 9722 + yargs-parser: 18.1.3 9723 + dev: false 9612 9724 9613 9725 /merge-stream@2.0.0: 9614 9726 resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} ··· 9977 10089 engines: {node: '>=10'} 9978 10090 dev: false 9979 10091 10092 + /min-indent@1.0.1: 10093 + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} 10094 + engines: {node: '>=4'} 10095 + dev: false 10096 + 9980 10097 /minimatch@3.1.2: 9981 10098 resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} 9982 10099 dependencies: ··· 10001 10118 dependencies: 10002 10119 brace-expansion: 2.0.1 10003 10120 10121 + /minimist-options@4.1.0: 10122 + resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} 10123 + engines: {node: '>= 6'} 10124 + dependencies: 10125 + arrify: 1.0.1 10126 + is-plain-obj: 1.1.0 10127 + kind-of: 6.0.3 10128 + dev: false 10129 + 10004 10130 /minimist@1.2.8: 10005 10131 resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} 10132 + 10133 + /minipass@7.0.4: 10134 + resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} 10135 + engines: {node: '>=16 || 14 >=14.17'} 10136 + dev: false 10006 10137 10007 10138 /mkdirp-classic@0.5.3: 10008 10139 resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} ··· 10510 10641 peberminta: 0.8.0 10511 10642 dev: false 10512 10643 10644 + /parseley@0.12.1: 10645 + resolution: {integrity: sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==} 10646 + dependencies: 10647 + leac: 0.6.0 10648 + peberminta: 0.9.0 10649 + dev: false 10650 + 10513 10651 /pascal-case@2.0.1: 10514 10652 resolution: {integrity: sha512-qjS4s8rBOJa2Xm0jmxXiyh1+OFf6ekCWOvUaRgAQSktzlTbMotS0nmG9gyYAybCWBcuP4fsBeRCKNwGBnMe2OQ==} 10515 10653 dependencies: ··· 10545 10683 /path-parse@1.0.7: 10546 10684 resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 10547 10685 10686 + /path-scurry@1.10.1: 10687 + resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} 10688 + engines: {node: '>=16 || 14 >=14.17'} 10689 + dependencies: 10690 + lru-cache: 10.1.0 10691 + minipass: 7.0.4 10692 + dev: false 10693 + 10548 10694 /path-to-regexp@6.2.1: 10549 10695 resolution: {integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==} 10550 10696 dev: false ··· 10555 10701 10556 10702 /peberminta@0.8.0: 10557 10703 resolution: {integrity: sha512-YYEs+eauIjDH5nUEGi18EohWE0nV2QbGTqmxQcqgZ/0g+laPCQmuIqq7EBLVi9uim9zMgfJv0QBZEnQ3uHw/Tw==} 10704 + dev: false 10705 + 10706 + /peberminta@0.9.0: 10707 + resolution: {integrity: sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==} 10558 10708 dev: false 10559 10709 10560 10710 /periscopic@3.1.0: ··· 10818 10968 hasBin: true 10819 10969 dev: true 10820 10970 10821 - /pretty-bytes@5.6.0: 10822 - resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==} 10823 - engines: {node: '>=6'} 10824 - dev: false 10825 - 10826 10971 /pretty-format@29.7.0: 10827 10972 resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} 10828 10973 engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} ··· 10839 10984 condense-newlines: 0.2.1 10840 10985 extend-shallow: 2.0.1 10841 10986 js-beautify: 1.14.9 10842 - dev: false 10843 - 10844 - /process-nextick-args@2.0.1: 10845 - resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} 10846 10987 dev: false 10847 10988 10848 10989 /progress@2.0.3: ··· 11003 11144 react: 18.2.0 11004 11145 scheduler: 0.23.0 11005 11146 11006 - /react-email@1.9.5: 11007 - resolution: {integrity: sha512-c2ubADlAGKAsfmQRDQd0s3/o+wUW/WCVhwiZo+RkUgsP35RhzDBQisFfxHEX8trjNf0eSv4R9g3ASmRF1vAP8A==} 11008 - engines: {node: '>=16.0.0'} 11147 + /react-email@1.10.0: 11148 + resolution: {integrity: sha512-IrLs28p3Iqyx9JASSrdEoTC+TQeb3jDcJ++2xzVS71yR6U8GYAqff7NKPGZJIA6z5oGtwRFv6GCViR4JiGdmXg==} 11149 + engines: {node: '>=18.0.0'} 11009 11150 hasBin: true 11010 11151 dependencies: 11011 11152 '@commander-js/extra-typings': 9.4.1(commander@9.4.1) 11012 11153 '@manypkg/find-root': 2.2.1 11013 11154 '@octokit/rest': 19.0.7 11014 - '@react-email/render': 0.0.6 11155 + '@react-email/render': 0.0.10 11015 11156 chokidar: 3.5.3 11016 11157 commander: 9.4.1 11017 11158 detect-package-manager: 2.0.1 11018 11159 esbuild: 0.16.4 11019 11160 fs-extra: 11.1.1 11020 - glob: 8.0.3 11161 + glob: 10.3.4 11021 11162 log-symbols: 4.1.0 11022 11163 normalize-path: 3.0.0 11023 11164 ora: 5.4.1 11024 11165 read-pkg: 5.2.0 11025 11166 shelljs: 0.8.5 11026 - tree-node-cli: 1.6.0 11167 + tree-cli: 0.6.7 11027 11168 transitivePeerDependencies: 11028 11169 - encoding 11029 11170 dev: false ··· 11210 11351 dependencies: 11211 11352 pify: 2.3.0 11212 11353 11354 + /read-pkg-up@7.0.1: 11355 + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} 11356 + engines: {node: '>=8'} 11357 + dependencies: 11358 + find-up: 4.1.0 11359 + read-pkg: 5.2.0 11360 + type-fest: 0.8.1 11361 + dev: false 11362 + 11213 11363 /read-pkg@5.2.0: 11214 11364 resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} 11215 11365 engines: {node: '>=8'} ··· 11230 11380 strip-bom: 3.0.0 11231 11381 dev: false 11232 11382 11233 - /readable-stream@2.3.8: 11234 - resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} 11235 - dependencies: 11236 - core-util-is: 1.0.3 11237 - inherits: 2.0.4 11238 - isarray: 1.0.0 11239 - process-nextick-args: 2.0.1 11240 - safe-buffer: 5.1.2 11241 - string_decoder: 1.1.1 11242 - util-deprecate: 1.0.2 11243 - dev: false 11244 - 11245 11383 /readable-stream@3.6.2: 11246 11384 resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} 11247 11385 engines: {node: '>= 6'} ··· 11293 11431 engines: {node: '>= 0.10'} 11294 11432 dependencies: 11295 11433 resolve: 1.22.8 11434 + dev: false 11435 + 11436 + /redent@3.0.0: 11437 + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} 11438 + engines: {node: '>=8'} 11439 + dependencies: 11440 + indent-string: 4.0.0 11441 + strip-indent: 3.0.0 11296 11442 dev: false 11297 11443 11298 11444 /reflect.getprototypeof@1.0.4: ··· 11470 11616 type-fest: 3.13.0 11471 11617 dev: false 11472 11618 11619 + /resend@2.0.0: 11620 + resolution: {integrity: sha512-jAh0DN84ZjjmzGM2vMjJ1hphPBg1mG98dzopF7kJzmin62v8ESg4og2iCKWdkAboGOT2SeO5exbr/8Xh8gLddw==} 11621 + engines: {node: '>=18'} 11622 + dependencies: 11623 + '@react-email/render': 0.0.9 11624 + dev: false 11625 + 11473 11626 /resolve-from@4.0.0: 11474 11627 resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} 11475 11628 engines: {node: '>=4'} ··· 11522 11675 /reusify@1.0.4: 11523 11676 resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} 11524 11677 engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 11525 - 11526 - /rimraf@2.7.1: 11527 - resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} 11528 - hasBin: true 11529 - dependencies: 11530 - glob: 7.2.3 11531 - dev: false 11532 11678 11533 11679 /rimraf@3.0.2: 11534 11680 resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} ··· 11591 11737 isarray: 2.0.5 11592 11738 dev: false 11593 11739 11594 - /safe-buffer@5.1.2: 11595 - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} 11596 - dev: false 11597 - 11598 11740 /safe-buffer@5.2.1: 11599 11741 resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} 11600 11742 ··· 11633 11775 resolution: {integrity: sha512-DEL/RW/f4qLw/NrVg97xKaEBC8IpzIG2fvxnzCp3Z4yk4jQ3MXom+Imav9wApjxX2dfS3eW7x0DXafJr85i39A==} 11634 11776 dependencies: 11635 11777 parseley: 0.11.0 11778 + dev: false 11779 + 11780 + /selderee@0.11.0: 11781 + resolution: {integrity: sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==} 11782 + dependencies: 11783 + parseley: 0.12.1 11636 11784 dev: false 11637 11785 11638 11786 /semver@5.7.2: ··· 11677 11825 has-property-descriptors: 1.0.0 11678 11826 dev: false 11679 11827 11680 - /setimmediate@1.0.5: 11681 - resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} 11682 - dev: false 11683 - 11684 11828 /setprototypeof@1.1.1: 11685 11829 resolution: {integrity: sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==} 11686 11830 dev: false ··· 11724 11868 11725 11869 /signal-exit@3.0.7: 11726 11870 resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} 11871 + 11872 + /signal-exit@4.1.0: 11873 + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} 11874 + engines: {node: '>=14'} 11875 + dev: false 11727 11876 11728 11877 /simple-concat@1.0.1: 11729 11878 resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} ··· 11903 12052 is-fullwidth-code-point: 3.0.0 11904 12053 strip-ansi: 6.0.1 11905 12054 12055 + /string-width@5.1.2: 12056 + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} 12057 + engines: {node: '>=12'} 12058 + dependencies: 12059 + eastasianwidth: 0.2.0 12060 + emoji-regex: 9.2.2 12061 + strip-ansi: 7.1.0 12062 + dev: false 12063 + 11906 12064 /string.prototype.matchall@4.0.10: 11907 12065 resolution: {integrity: sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==} 11908 12066 dependencies: ··· 11942 12100 es-abstract: 1.22.2 11943 12101 dev: false 11944 12102 11945 - /string_decoder@1.1.1: 11946 - resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} 11947 - dependencies: 11948 - safe-buffer: 5.1.2 11949 - dev: false 11950 - 11951 12103 /string_decoder@1.3.0: 11952 12104 resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} 11953 12105 dependencies: ··· 11960 12112 character-entities-legacy: 3.0.0 11961 12113 dev: false 11962 12114 12115 + /strip-ansi@3.0.1: 12116 + resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==} 12117 + engines: {node: '>=0.10.0'} 12118 + dependencies: 12119 + ansi-regex: 2.1.1 12120 + dev: false 12121 + 11963 12122 /strip-ansi@6.0.1: 11964 12123 resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 11965 12124 engines: {node: '>=8'} 11966 12125 dependencies: 11967 12126 ansi-regex: 5.0.1 11968 12127 12128 + /strip-ansi@7.1.0: 12129 + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} 12130 + engines: {node: '>=12'} 12131 + dependencies: 12132 + ansi-regex: 6.0.1 12133 + dev: false 12134 + 11969 12135 /strip-bom-string@1.0.0: 11970 12136 resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==} 11971 12137 engines: {node: '>=0.10.0'} ··· 11979 12145 /strip-final-newline@2.0.0: 11980 12146 resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} 11981 12147 engines: {node: '>=6'} 12148 + 12149 + /strip-indent@3.0.0: 12150 + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} 12151 + engines: {node: '>=8'} 12152 + dependencies: 12153 + min-indent: 1.0.1 12154 + dev: false 11982 12155 11983 12156 /strip-json-comments@2.0.1: 11984 12157 resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} ··· 12053 12226 engines: {node: '>=10'} 12054 12227 dependencies: 12055 12228 copy-anything: 3.0.5 12229 + dev: false 12230 + 12231 + /supports-color@2.0.0: 12232 + resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} 12233 + engines: {node: '>=0.8.0'} 12056 12234 dev: false 12057 12235 12058 12236 /supports-color@5.5.0: ··· 12356 12534 punycode: 2.3.0 12357 12535 dev: false 12358 12536 12359 - /traverse@0.3.9: 12360 - resolution: {integrity: sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==} 12537 + /tree-cli@0.6.7: 12538 + resolution: {integrity: sha512-jfnB5YKY6Glf6bsFmQ9W97TtkPVLnHsjOR6ZdRf4zhyFRQeLheasvzE5XBJI2Hxt7ZyMyIbXUV7E2YPZbixgtA==} 12539 + engines: {node: '>=8.10.9'} 12540 + hasBin: true 12541 + dependencies: 12542 + bluebird: 3.4.7 12543 + chalk: 1.1.3 12544 + cli-spinner: 0.2.10 12545 + lodash.includes: 4.3.0 12546 + meow: 7.1.1 12547 + object-assign: 4.1.1 12361 12548 dev: false 12362 12549 12363 12550 /tree-kill@1.2.2: 12364 12551 resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} 12365 12552 hasBin: true 12366 12553 dev: true 12367 - 12368 - /tree-node-cli@1.6.0: 12369 - resolution: {integrity: sha512-M8um5Lbl76rWU5aC8oOeEhruiCM29lFCKnwpxrwMjpRicHXJx+bb9Cak11G3zYLrMb6Glsrhnn90rHIzDJrjvg==} 12370 - hasBin: true 12371 - dependencies: 12372 - commander: 5.1.0 12373 - fast-folder-size: 1.6.1 12374 - pretty-bytes: 5.6.0 12375 - dev: false 12376 12554 12377 12555 /trim-lines@3.0.1: 12378 12556 resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} 12379 12557 dev: false 12380 12558 12559 + /trim-newlines@3.0.1: 12560 + resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} 12561 + engines: {node: '>=8'} 12562 + dev: false 12563 + 12381 12564 /trough@2.1.0: 12382 12565 resolution: {integrity: sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==} 12383 12566 ··· 12578 12761 engines: {node: '>=4'} 12579 12762 dev: false 12580 12763 12764 + /type-fest@0.13.1: 12765 + resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} 12766 + engines: {node: '>=10'} 12767 + dev: false 12768 + 12581 12769 /type-fest@0.20.2: 12582 12770 resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} 12583 12771 engines: {node: '>=10'} ··· 12594 12782 12595 12783 /type-fest@0.7.1: 12596 12784 resolution: {integrity: sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==} 12785 + engines: {node: '>=8'} 12786 + dev: false 12787 + 12788 + /type-fest@0.8.1: 12789 + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} 12597 12790 engines: {node: '>=8'} 12598 12791 dev: false 12599 12792 ··· 12787 12980 engines: {node: '>= 0.8'} 12788 12981 dev: false 12789 12982 12790 - /unzipper@0.10.14: 12791 - resolution: {integrity: sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==} 12792 - dependencies: 12793 - big-integer: 1.6.51 12794 - binary: 0.3.0 12795 - bluebird: 3.4.7 12796 - buffer-indexof-polyfill: 1.0.2 12797 - duplexer2: 0.1.4 12798 - fstream: 1.0.12 12799 - graceful-fs: 4.2.11 12800 - listenercount: 1.0.1 12801 - readable-stream: 2.3.8 12802 - setimmediate: 1.0.5 12803 - dev: false 12804 - 12805 12983 /update-browserslist-db@1.0.13(browserslist@4.22.1): 12806 12984 resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} 12807 12985 hasBin: true ··· 13153 13331 strip-ansi: 6.0.1 13154 13332 dev: false 13155 13333 13334 + /wrap-ansi@8.1.0: 13335 + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} 13336 + engines: {node: '>=12'} 13337 + dependencies: 13338 + ansi-styles: 6.2.1 13339 + string-width: 5.1.2 13340 + strip-ansi: 7.1.0 13341 + dev: false 13342 + 13156 13343 /wrappy@1.0.2: 13157 13344 resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} 13158 13345 ··· 13205 13392 /yaml@2.3.3: 13206 13393 resolution: {integrity: sha512-zw0VAJxgeZ6+++/su5AFoqBbZbrEakwu+X0M5HmcwUiBL7AzcuPKjj5we4xfQLp78LkEMpD0cOnUhmgOVy3KdQ==} 13207 13394 engines: {node: '>= 14'} 13395 + 13396 + /yargs-parser@18.1.3: 13397 + resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} 13398 + engines: {node: '>=6'} 13399 + dependencies: 13400 + camelcase: 5.3.1 13401 + decamelize: 1.2.0 13402 + dev: false 13208 13403 13209 13404 /yargs-parser@21.1.1: 13210 13405 resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}