appos 0.6.0-0 → 0.7.0-0
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/dist/alert-BdX0Zt8k.js +103 -0
- package/dist/animated-check-CKu20goQ.js +68 -0
- package/dist/api/auth.d.mts +4 -0
- package/dist/api/auth.mjs +276 -0
- package/dist/api/cache.d.mts +3 -0
- package/dist/api/cache.mjs +28 -0
- package/dist/{exports/cli/index.d.mts → api/cli.d.mts} +8 -7
- package/dist/{exports/cli/index.mjs → api/cli.mjs} +46 -56
- package/dist/api/container.d.mts +6 -0
- package/dist/api/container.mjs +52 -0
- package/dist/api/database.d.mts +5 -0
- package/dist/api/database.mjs +8 -0
- package/dist/api/event.d.mts +6 -0
- package/dist/api/event.mjs +5 -0
- package/dist/api/instrumentation.d.mts +4 -0
- package/dist/api/instrumentation.mjs +11 -0
- package/dist/api/mailer.d.mts +6 -0
- package/dist/api/mailer.mjs +114 -0
- package/dist/api/observability.d.mts +4 -0
- package/dist/api/observability.mjs +79 -0
- package/dist/api/openapi.d.mts +6 -0
- package/dist/api/openapi.mjs +5 -0
- package/dist/api/server.d.mts +6 -0
- package/dist/api/server.mjs +8 -0
- package/dist/{exports/web/routes.d.mts → api/ssr.d.mts} +26 -11
- package/dist/{exports/web/routes.mjs → api/ssr.mjs} +24 -28
- package/dist/api/storage.d.mts +6 -0
- package/dist/{exports/api/index.mjs → api/storage.mjs} +77 -736
- package/dist/api/worker.d.mts +26 -0
- package/dist/api/worker.mjs +3 -0
- package/dist/api/workflow.d.mts +6 -0
- package/dist/api/workflow.mjs +7 -0
- package/dist/app-context-Cossa4Qc.mjs +3 -0
- package/dist/auth-BBivVOI9.mjs +26 -0
- package/dist/{exports/web/index.d.ts → auth-CmsO5ob5.d.ts} +6657 -9434
- package/dist/auth-D0zoZI7U.d.mts +5145 -0
- package/dist/auth-schema-OUnjUQlj.mjs +385 -0
- package/dist/badge-BFQXkO9d.js +49 -0
- package/dist/brand-C669gH_G.d.ts +88 -0
- package/dist/brand-CjbfdIEo.js +114 -0
- package/dist/button-CBH7xJ8q.js +81 -0
- package/dist/cache-jHw6mJPK.d.mts +75 -0
- package/dist/card-X792kQrC.js +154 -0
- package/dist/checkbox-e3A3glfd.js +33 -0
- package/dist/{exports/constants-BicCnEiJ.mjs → constants-DCwXUedR.mjs} +40 -6
- package/dist/container-xweZOaov.d.mts +2842 -0
- package/dist/context-9Yd81kh5.mjs +13 -0
- package/dist/context-La08hSVU.js +45 -0
- package/dist/database-Ca_pujXd.d.mts +102 -0
- package/dist/database-DSEtnffO.mjs +220 -0
- package/dist/{exports/storybook/index.d.ts → devtools/storybook.d.ts} +1 -1
- package/dist/{exports/storybook/index.js → devtools/storybook.js} +1 -1
- package/dist/devtools/test-mock.mjs +3 -0
- package/dist/{exports/tests/setup.mjs → devtools/test-setup.mjs} +1 -1
- package/dist/{exports/tests/api.d.mts → devtools/test.d.mts} +16 -6
- package/dist/{exports/tests/api.mjs → devtools/test.mjs} +30 -15
- package/dist/{exports/vite/index.d.mts → devtools/vite.d.mts} +65 -6
- package/dist/{exports/vite/index.mjs → devtools/vite.mjs} +157 -6
- package/dist/empty-BonqCObb.js +61 -0
- package/dist/env-C-0yH_Q3.mjs +26 -0
- package/dist/event-1yFQJHwn.mjs +236 -0
- package/dist/field-7rMKJCeh.js +115 -0
- package/dist/input-D9PbuBOa.js +27 -0
- package/dist/input-otp-zHrdocki.js +48 -0
- package/dist/{exports/instrumentation-Dqv_rRlR.mjs → instrumentation-DCouyaIn.mjs} +1 -1
- package/dist/label-C0h_-ojZ.js +26 -0
- package/dist/logger-rlLu_iK1.d.mts +20 -0
- package/dist/observability-Bd2pNUXs.d.mts +43 -0
- package/dist/openapi-DVd0_Ppp.mjs +467 -0
- package/dist/panel-Cy7DsMUA.mjs +57 -0
- package/dist/panel-D1XK_PR5.mjs +5 -0
- package/dist/redis-a5sw5J3L.mjs +41 -0
- package/dist/routes-BB8_4xq3.mjs +1123 -0
- package/dist/routes-Dv-T8LMT.mjs +4 -0
- package/dist/separator-DDbWY6ol.js +28 -0
- package/dist/server-CWYF5Oeg.mjs +1673 -0
- package/dist/spinner-CaEB5f1z.js +28 -0
- package/dist/textarea-CFblOAyj.js +25 -0
- package/dist/universal/auth.d.ts +139 -0
- package/dist/universal/auth.js +108 -0
- package/dist/universal/config.d.ts +47 -0
- package/dist/universal/config.js +128 -0
- package/dist/use-mobile-Dg2CI44J.js +19 -0
- package/dist/utils-4n921m5r.js +52 -0
- package/dist/utils-NKi1RiLK.d.ts +50 -0
- package/dist/web/auth.d.ts +4 -0
- package/dist/web/auth.js +88 -0
- package/dist/web/hooks.d.ts +4 -0
- package/dist/web/hooks.js +3 -0
- package/dist/web/i18n.d.ts +76 -0
- package/dist/web/i18n.js +58 -0
- package/dist/web/router.d.ts +3 -0
- package/dist/web/router.js +4 -0
- package/dist/web/ui/accordion.d.ts +79 -0
- package/dist/web/ui/accordion.js +112 -0
- package/dist/web/ui/alert-dialog.d.ts +200 -0
- package/dist/web/ui/alert-dialog.js +239 -0
- package/dist/web/ui/alert.d.ts +84 -0
- package/dist/web/ui/alert.js +4 -0
- package/dist/web/ui/animated-check.d.ts +38 -0
- package/dist/web/ui/animated-check.js +6 -0
- package/dist/web/ui/aspect-ratio.d.ts +26 -0
- package/dist/web/ui/aspect-ratio.js +28 -0
- package/dist/web/ui/auth.d.ts +4 -0
- package/dist/web/ui/auth.js +3432 -0
- package/dist/web/ui/avatar.d.ts +115 -0
- package/dist/web/ui/avatar.js +134 -0
- package/dist/web/ui/badge.d.ts +32 -0
- package/dist/web/ui/badge.js +4 -0
- package/dist/web/ui/brand.d.ts +3 -0
- package/dist/web/ui/brand.js +6 -0
- package/dist/web/ui/breadcrumb.d.ts +130 -0
- package/dist/web/ui/breadcrumb.js +166 -0
- package/dist/web/ui/button-group.d.ts +28 -0
- package/dist/web/ui/button-group.js +43 -0
- package/dist/web/ui/button.d.ts +83 -0
- package/dist/web/ui/button.js +6 -0
- package/dist/web/ui/calendar.d.ts +26 -0
- package/dist/web/ui/calendar.js +107 -0
- package/dist/web/ui/card.d.ts +134 -0
- package/dist/web/ui/card.js +4 -0
- package/dist/web/ui/carousel.d.ts +56 -0
- package/dist/web/ui/carousel.js +135 -0
- package/dist/web/ui/chart.d.ts +90 -0
- package/dist/web/ui/chart.js +142 -0
- package/dist/web/ui/checkbox.d.ts +22 -0
- package/dist/web/ui/checkbox.js +6 -0
- package/dist/web/ui/collapsible.d.ts +15 -0
- package/dist/web/ui/collapsible.js +27 -0
- package/dist/web/ui/command.d.ts +55 -0
- package/dist/web/ui/command.js +93 -0
- package/dist/web/ui/context-menu.d.ts +80 -0
- package/dist/web/ui/context-menu.js +133 -0
- package/dist/web/ui/dialog.d.ts +169 -0
- package/dist/web/ui/dialog.js +212 -0
- package/dist/web/ui/drawer.d.ts +44 -0
- package/dist/web/ui/drawer.js +80 -0
- package/dist/web/ui/dropdown-menu.d.ts +84 -0
- package/dist/web/ui/dropdown-menu.js +137 -0
- package/dist/web/ui/empty.d.ts +36 -0
- package/dist/web/ui/empty.js +4 -0
- package/dist/web/ui/error-page.d.ts +32 -0
- package/dist/web/ui/error-page.js +87 -0
- package/dist/web/ui/field.d.ts +67 -0
- package/dist/web/ui/field.js +8 -0
- package/dist/web/ui/hover-card.d.ts +20 -0
- package/dist/web/ui/hover-card.js +39 -0
- package/dist/web/ui/input-group.d.ts +45 -0
- package/dist/web/ui/input-group.js +81 -0
- package/dist/web/ui/input-otp.d.ts +28 -0
- package/dist/web/ui/input-otp.js +6 -0
- package/dist/web/ui/input.d.ts +22 -0
- package/dist/web/ui/input.js +4 -0
- package/dist/web/ui/item.d.ts +61 -0
- package/dist/web/ui/item.js +122 -0
- package/dist/web/ui/kbd.d.ts +14 -0
- package/dist/web/ui/kbd.js +21 -0
- package/dist/web/ui/label.d.ts +22 -0
- package/dist/web/ui/label.js +6 -0
- package/dist/web/ui/menubar.d.ts +80 -0
- package/dist/web/ui/menubar.js +136 -0
- package/dist/web/ui/navigation-menu.d.ts +46 -0
- package/dist/web/ui/navigation-menu.js +84 -0
- package/dist/web/ui/pagination.d.ts +131 -0
- package/dist/web/ui/pagination.js +171 -0
- package/dist/web/ui/popover.d.ts +33 -0
- package/dist/web/ui/popover.js +57 -0
- package/dist/web/ui/progress.d.ts +74 -0
- package/dist/web/ui/progress.js +93 -0
- package/dist/web/ui/radio-group.d.ts +15 -0
- package/dist/web/ui/radio-group.js +31 -0
- package/dist/web/ui/resizable.d.ts +20 -0
- package/dist/web/ui/resizable.js +31 -0
- package/dist/web/ui/scroll-area.d.ts +16 -0
- package/dist/web/ui/scroll-area.js +39 -0
- package/dist/web/ui/select.d.ts +167 -0
- package/dist/web/ui/select.js +211 -0
- package/dist/web/ui/separator.d.ts +23 -0
- package/dist/web/ui/separator.js +6 -0
- package/dist/web/ui/sheet.d.ts +42 -0
- package/dist/web/ui/sheet.js +91 -0
- package/dist/web/ui/sidebar.d.ts +160 -0
- package/dist/web/ui/sidebar.js +382 -0
- package/dist/web/ui/skeleton.d.ts +22 -0
- package/dist/web/ui/skeleton.js +26 -0
- package/dist/web/ui/slider.d.ts +26 -0
- package/dist/web/ui/slider.js +55 -0
- package/dist/web/ui/sonner.d.ts +9 -0
- package/dist/web/ui/sonner.js +33 -0
- package/dist/web/ui/spinner.d.ts +22 -0
- package/dist/web/ui/spinner.js +4 -0
- package/dist/web/ui/switch.d.ts +25 -0
- package/dist/web/ui/switch.js +34 -0
- package/dist/web/ui/table.d.ts +38 -0
- package/dist/web/ui/table.js +69 -0
- package/dist/web/ui/tabs.d.ts +84 -0
- package/dist/web/ui/tabs.js +103 -0
- package/dist/web/ui/textarea.d.ts +21 -0
- package/dist/web/ui/textarea.js +4 -0
- package/dist/web/ui/toggle-group.d.ts +28 -0
- package/dist/web/ui/toggle-group.js +55 -0
- package/dist/web/ui/toggle.d.ts +32 -0
- package/dist/web/ui/toggle.js +53 -0
- package/dist/web/ui/tooltip.d.ts +72 -0
- package/dist/web/ui/tooltip.js +91 -0
- package/dist/worker-D4L3BmuS.mjs +24 -0
- package/dist/{exports/send-email-CXxlkfFL.mjs → workflow-BUI7kC5c.mjs} +118 -765
- package/package.json +382 -90
- package/src/devtools/panel/index.ts +114 -0
- package/src/devtools/panel/modules/emails/compatibility.ts +289 -0
- package/src/devtools/panel/modules/emails/discovery.ts +242 -0
- package/src/devtools/panel/modules/emails/linter.ts +501 -0
- package/src/devtools/panel/modules/emails/render.ts +155 -0
- package/src/devtools/panel/modules/emails/routes.ts +502 -0
- package/src/devtools/panel/modules/emails/schema.ts +82 -0
- package/src/devtools/panel/modules/emails/spam-checker.ts +231 -0
- package/src/{storybook → devtools/storybook}/.storybook/main.ts +12 -4
- package/src/{storybook → devtools/storybook}/.storybook/manager.ts +1 -1
- package/src/{storybook → devtools/storybook}/.storybook/preview.tsx +7 -1
- package/src/{storybook → devtools/storybook}/docs/Introduction.mdx +3 -1
- package/src/{web/client/auth-paths.ts → universal/auth.ts} +54 -6
- package/src/universal/config.test.ts +473 -0
- package/src/universal/config.ts +205 -0
- package/src/universal/date.ts +1 -0
- package/src/universal/locales/en/ui.json +232 -0
- package/src/universal/locales/zh-CN/ui.json +232 -0
- package/src/universal/locales/zh-TW/ui.json +232 -0
- package/src/universal/toolkit.ts +1 -0
- package/src/universal/zod.ts +1 -0
- package/src/web/auth.ts +6 -0
- package/src/web/client/auth.ts +6 -11
- package/src/web/client/i18n.d.ts +2 -0
- package/src/web/client/i18n.ts +6 -1
- package/src/web/devtools/index.ts +1 -0
- package/src/web/devtools/modules/dashboard.tsx +151 -0
- package/src/web/devtools/modules/emails.tsx +1338 -0
- package/src/web/devtools/overlay.tsx +109 -0
- package/src/web/devtools/panel.tsx +353 -0
- package/src/web/font/index.ts +1 -3
- package/src/web/hooks.ts +4 -0
- package/src/web/i18n.ts +11 -0
- package/src/web/index.ts +1 -2
- package/src/web/router.ts +5 -0
- package/src/web/routes/auth/_layout.tsx +17 -15
- package/src/web/routes/auth/email-otp.tsx +2 -2
- package/src/web/routes/auth/forgot-password.tsx +1 -1
- package/src/web/routes/auth/login.tsx +3 -2
- package/src/web/routes/auth/phone-otp.tsx +2 -2
- package/src/web/routes/auth/reset-password.tsx +3 -7
- package/src/web/routes/auth/signup.tsx +2 -2
- package/src/web/routes/auth/utils.ts +21 -10
- package/src/web/routes/auth/verify-email.tsx +2 -2
- package/src/web/routes.ts +4 -9
- package/src/web/ui/alert-dialog.stories.tsx +2 -2
- package/src/web/ui/auth/auth-layout.stories.tsx +81 -72
- package/src/web/ui/auth/auth-layout.tsx +70 -138
- package/src/web/ui/auth/brand-content.stories.tsx +272 -0
- package/src/web/ui/auth/brand-content.tsx +431 -0
- package/src/web/ui/auth/context.tsx +2 -2
- package/src/web/ui/auth/hooks.ts +1 -1
- package/src/web/ui/auth/index.ts +24 -1
- package/src/web/ui/auth.ts +4 -0
- package/src/web/ui/checkbox.stories.tsx +2 -1
- package/src/web/ui/collapsible.stories.tsx +2 -2
- package/src/web/ui/command.stories.tsx +1 -1
- package/src/web/ui/context-menu.stories.tsx +1 -1
- package/src/web/ui/dialog.stories.tsx +4 -4
- package/src/web/ui/drawer.stories.tsx +4 -4
- package/src/web/ui/dropdown-menu.stories.tsx +2 -2
- package/src/web/ui/empty.stories.tsx +2 -2
- package/src/web/ui/error-page.stories.tsx +1 -1
- package/src/web/ui/error-page.tsx +1 -1
- package/src/web/ui/field.stories.tsx +5 -6
- package/src/web/ui/globals.css +2 -1
- package/src/web/ui/hover-card.stories.tsx +3 -5
- package/src/web/ui/input-group.stories.tsx +2 -2
- package/src/web/ui/input-otp.stories.tsx +1 -1
- package/src/web/ui/input.stories.tsx +2 -1
- package/src/web/ui/item.stories.tsx +3 -3
- package/src/web/ui/kbd.stories.tsx +1 -1
- package/src/web/ui/label.stories.tsx +4 -1
- package/src/web/ui/locales/en/devtools.json +102 -0
- package/src/web/ui/locales/zh-CN/devtools.json +102 -0
- package/src/web/ui/locales/zh-TW/devtools.json +102 -0
- package/src/web/ui/menubar.stories.tsx +1 -1
- package/src/web/ui/navigation-menu.stories.tsx +1 -1
- package/src/web/ui/navigation-menu.tsx +3 -3
- package/src/web/ui/pagination.stories.tsx +1 -1
- package/src/web/ui/popover.stories.tsx +4 -4
- package/src/web/ui/progress.stories.tsx +1 -1
- package/src/web/ui/radio-group.stories.tsx +3 -4
- package/src/web/ui/resizable.stories.tsx +1 -1
- package/src/web/ui/scroll-area.stories.tsx +2 -1
- package/src/web/ui/select.stories.tsx +1 -1
- package/src/web/ui/sheet.stories.tsx +4 -4
- package/src/web/ui/sidebar.stories.tsx +1 -1
- package/src/web/ui/sidebar.tsx +1 -1
- package/src/web/ui/skeleton.stories.tsx +1 -1
- package/src/web/ui/slider.stories.tsx +1 -1
- package/src/web/ui/sonner.stories.tsx +2 -1
- package/src/web/ui/spinner.stories.tsx +2 -1
- package/src/web/ui/switch.stories.tsx +2 -1
- package/src/web/ui/table.stories.tsx +3 -3
- package/src/web/ui/tabs.stories.tsx +5 -8
- package/src/web/ui/textarea.stories.tsx +3 -1
- package/src/web/ui/toggle.stories.tsx +1 -1
- package/src/web/ui/tooltip.stories.tsx +2 -2
- package/dist/exports/api/index.d.mts +0 -5
- package/dist/exports/api/orm-seed.d.mts +0 -1
- package/dist/exports/api/orm-seed.mjs +0 -3
- package/dist/exports/api/orm.d.mts +0 -3
- package/dist/exports/api/orm.mjs +0 -5
- package/dist/exports/api/workflows/index.d.mts +0 -74
- package/dist/exports/api/workflows/index.mjs +0 -4
- package/dist/exports/app-context-B1VJ9qnH.mjs +0 -3
- package/dist/exports/auth-BCOIpGDO.d.mts +0 -870
- package/dist/exports/index-Di4PdhuL.d.mts +0 -7174
- package/dist/exports/instrumentation.d.mts +0 -2
- package/dist/exports/instrumentation.mjs +0 -5
- package/dist/exports/mock-DLfalkIV.mjs +0 -9
- package/dist/exports/openapi-uisUTLq7.mjs +0 -1483
- package/dist/exports/orm-D-7F2n1J.d.mts +0 -10
- package/dist/exports/orm-DbH3_5aw.mjs +0 -36
- package/dist/exports/server-cD8Pckgj.mjs +0 -509
- package/dist/exports/ssr-BsfNjYlJ.mjs +0 -16
- package/dist/exports/tests/mock.mjs +0 -5
- package/dist/exports/tests/react.d.mts +0 -2
- package/dist/exports/tests/react.mjs +0 -5
- package/dist/exports/web/index.js +0 -8178
- package/dist/exports/web/ssr.d.mts +0 -20
- package/dist/exports/web/ssr.mjs +0 -3
- /package/dist/{exports/app-context-LF4QmPUC.mjs → app-context-CaxDuPj-.mjs} +0 -0
- /package/dist/{exports/chunk-DCbLExaX.mjs → chunk-BkPCcwIn.mjs} +0 -0
- /package/dist/{exports/tests/mock.d.mts → devtools/test-mock.d.mts} +0 -0
- /package/dist/{exports/tests/setup.d.mts → devtools/test-setup.d.mts} +0 -0
- /package/dist/{exports/instrumentation-CFIspF8-.d.mts → instrumentation-DhJYpza5.d.mts} +0 -0
- /package/dist/{exports/vendors → universal}/date.d.ts +0 -0
- /package/dist/{exports/vendors → universal}/date.js +0 -0
- /package/dist/{exports/vendors → universal}/toolkit.d.ts +0 -0
- /package/dist/{exports/vendors → universal}/toolkit.js +0 -0
- /package/dist/{exports/vendors → universal}/zod.d.ts +0 -0
- /package/dist/{exports/vendors → universal}/zod.js +0 -0
- /package/dist/{exports/vite-compat-CICObU9F.mjs → vite-compat-El4psBQm.mjs} +0 -0
- /package/dist/{exports/youch-handler-CHwX0Fou.mjs → youch-handler-D951Exws.mjs} +0 -0
- /package/src/{storybook → devtools/storybook}/components/ColorGrid.tsx +0 -0
- /package/src/{storybook → devtools/storybook}/components/IconGallery.tsx +0 -0
- /package/src/{storybook → devtools/storybook}/components/SpacingScale.tsx +0 -0
- /package/src/{storybook → devtools/storybook}/components/TypographyScale.tsx +0 -0
- /package/src/{storybook → devtools/storybook}/components/index.ts +0 -0
- /package/src/{storybook → devtools/storybook}/docs/foundations/Colors.mdx +0 -0
- /package/src/{storybook → devtools/storybook}/docs/foundations/Icons.mdx +0 -0
- /package/src/{storybook → devtools/storybook}/docs/foundations/Spacing.mdx +0 -0
- /package/src/{storybook → devtools/storybook}/docs/foundations/Typography.mdx +0 -0
- /package/src/{storybook → devtools/storybook}/index.ts +0 -0
- /package/src/{storybook → devtools/storybook}/shims/void-elements.js +0 -0
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spam checking module using Postmark SpamCheck API.
|
|
3
|
+
*
|
|
4
|
+
* Uses the free Postmark SpamAssassin API to detect spam patterns in emails.
|
|
5
|
+
* No API key required.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A single spam rule matched by SpamAssassin.
|
|
10
|
+
*/
|
|
11
|
+
export interface SpamRule {
|
|
12
|
+
/**
|
|
13
|
+
* The SpamAssassin rule name.
|
|
14
|
+
*/
|
|
15
|
+
rule: string;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Human-readable description of the rule.
|
|
19
|
+
*/
|
|
20
|
+
description: string;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Points added to the spam score by this rule.
|
|
24
|
+
*/
|
|
25
|
+
score: number;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Result of spam checking an email.
|
|
30
|
+
*/
|
|
31
|
+
export interface SpamCheckResult {
|
|
32
|
+
/**
|
|
33
|
+
* Whether the check was successful.
|
|
34
|
+
*/
|
|
35
|
+
success: boolean;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The total spam score (lower is better, typically 5+ is spam).
|
|
39
|
+
*/
|
|
40
|
+
score: number;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* List of SpamAssassin rules that matched.
|
|
44
|
+
*/
|
|
45
|
+
rules: SpamRule[];
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Time taken to check in milliseconds.
|
|
49
|
+
*/
|
|
50
|
+
checkTime: number;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Error message if the check failed.
|
|
54
|
+
*/
|
|
55
|
+
error?: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Postmark SpamCheck API response structure.
|
|
60
|
+
*/
|
|
61
|
+
interface PostmarkSpamResponse {
|
|
62
|
+
success: boolean;
|
|
63
|
+
score: string;
|
|
64
|
+
rules: Array<{
|
|
65
|
+
score: string;
|
|
66
|
+
description: string;
|
|
67
|
+
}>;
|
|
68
|
+
report?: string;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Constructs a raw email message from HTML and text content.
|
|
73
|
+
*
|
|
74
|
+
* SpamAssassin requires a full email message with headers and body.
|
|
75
|
+
* This creates a minimal MIME message for analysis.
|
|
76
|
+
*
|
|
77
|
+
* @param html - The HTML content of the email.
|
|
78
|
+
* @param text - The plain text content of the email.
|
|
79
|
+
* @param subject - Optional subject line.
|
|
80
|
+
* @returns Raw email message string.
|
|
81
|
+
*/
|
|
82
|
+
function constructRawEmail(
|
|
83
|
+
html: string,
|
|
84
|
+
text: string,
|
|
85
|
+
subject = "Test Email",
|
|
86
|
+
): string {
|
|
87
|
+
const boundary = `----=_Part_${Date.now()}_${Math.random().toString(36).substring(2)}`;
|
|
88
|
+
|
|
89
|
+
const headers = [
|
|
90
|
+
"MIME-Version: 1.0",
|
|
91
|
+
"From: test@example.com",
|
|
92
|
+
"To: recipient@example.com",
|
|
93
|
+
`Subject: ${subject}`,
|
|
94
|
+
`Content-Type: multipart/alternative; boundary="${boundary}"`,
|
|
95
|
+
"",
|
|
96
|
+
].join("\r\n");
|
|
97
|
+
|
|
98
|
+
const textPart = [
|
|
99
|
+
`--${boundary}`,
|
|
100
|
+
"Content-Type: text/plain; charset=utf-8",
|
|
101
|
+
"Content-Transfer-Encoding: quoted-printable",
|
|
102
|
+
"",
|
|
103
|
+
text,
|
|
104
|
+
].join("\r\n");
|
|
105
|
+
|
|
106
|
+
const htmlPart = [
|
|
107
|
+
`--${boundary}`,
|
|
108
|
+
"Content-Type: text/html; charset=utf-8",
|
|
109
|
+
"Content-Transfer-Encoding: quoted-printable",
|
|
110
|
+
"",
|
|
111
|
+
html,
|
|
112
|
+
].join("\r\n");
|
|
113
|
+
|
|
114
|
+
const closing = `--${boundary}--`;
|
|
115
|
+
|
|
116
|
+
return [headers, textPart, htmlPart, closing].join("\r\n");
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Checks email content for spam patterns using Postmark SpamCheck API.
|
|
121
|
+
*
|
|
122
|
+
* Algorithm:
|
|
123
|
+
* 1. Construct a raw MIME email from HTML and text content.
|
|
124
|
+
* 2. Send to Postmark's free SpamCheck API.
|
|
125
|
+
* 3. Parse the response and extract rules.
|
|
126
|
+
* 4. Return structured result with score and matched rules.
|
|
127
|
+
*
|
|
128
|
+
* @param html - The HTML content of the email.
|
|
129
|
+
* @param text - The plain text content of the email.
|
|
130
|
+
* @param subject - Optional subject line for the test email.
|
|
131
|
+
* @returns Spam check result with score and matched rules.
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* ```typescript
|
|
135
|
+
* const result = await checkSpamScore(htmlContent, textContent);
|
|
136
|
+
* console.log(`Spam score: ${result.score}`);
|
|
137
|
+
* for (const rule of result.rules) {
|
|
138
|
+
* console.log(`[${rule.score}] ${rule.description}`);
|
|
139
|
+
* }
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
export async function checkSpamScore(
|
|
143
|
+
html: string,
|
|
144
|
+
text: string,
|
|
145
|
+
subject?: string,
|
|
146
|
+
): Promise<SpamCheckResult> {
|
|
147
|
+
const start = performance.now();
|
|
148
|
+
|
|
149
|
+
try {
|
|
150
|
+
const rawEmail = constructRawEmail(html, text, subject);
|
|
151
|
+
|
|
152
|
+
const response = await fetch("https://spamcheck.postmarkapp.com/filter", {
|
|
153
|
+
method: "POST",
|
|
154
|
+
headers: {
|
|
155
|
+
"Content-Type": "application/json",
|
|
156
|
+
Accept: "application/json",
|
|
157
|
+
},
|
|
158
|
+
body: JSON.stringify({
|
|
159
|
+
email: rawEmail,
|
|
160
|
+
options: "long",
|
|
161
|
+
}),
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
if (!response.ok) {
|
|
165
|
+
return {
|
|
166
|
+
success: false,
|
|
167
|
+
score: 0,
|
|
168
|
+
rules: [],
|
|
169
|
+
checkTime: performance.now() - start,
|
|
170
|
+
error: `SpamCheck API returned ${response.status}`,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const data = (await response.json()) as PostmarkSpamResponse;
|
|
175
|
+
|
|
176
|
+
if (!data.success) {
|
|
177
|
+
return {
|
|
178
|
+
success: false,
|
|
179
|
+
score: 0,
|
|
180
|
+
rules: [],
|
|
181
|
+
checkTime: performance.now() - start,
|
|
182
|
+
error: "SpamCheck API returned unsuccessful response",
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Parse the rules from the report
|
|
187
|
+
const rules: SpamRule[] = data.rules.map((rule) => ({
|
|
188
|
+
rule: extractRuleName(rule.description),
|
|
189
|
+
description: cleanRuleDescription(rule.description),
|
|
190
|
+
score: Number.parseFloat(rule.score),
|
|
191
|
+
}));
|
|
192
|
+
|
|
193
|
+
return {
|
|
194
|
+
success: true,
|
|
195
|
+
score: Number.parseFloat(data.score),
|
|
196
|
+
rules,
|
|
197
|
+
checkTime: performance.now() - start,
|
|
198
|
+
};
|
|
199
|
+
} catch (error) {
|
|
200
|
+
return {
|
|
201
|
+
success: false,
|
|
202
|
+
score: 0,
|
|
203
|
+
rules: [],
|
|
204
|
+
checkTime: performance.now() - start,
|
|
205
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Extracts the rule name from a SpamAssassin rule description.
|
|
212
|
+
*
|
|
213
|
+
* @param description - The full rule description.
|
|
214
|
+
* @returns The rule name or "UNKNOWN".
|
|
215
|
+
*/
|
|
216
|
+
function extractRuleName(description: string): string {
|
|
217
|
+
// SpamAssassin rule names are usually the first word in uppercase
|
|
218
|
+
const match = /^([A-Z0-9_]+)/.exec(description.trim());
|
|
219
|
+
return match?.[1] ?? "UNKNOWN";
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Cleans up a SpamAssassin rule description for display.
|
|
224
|
+
*
|
|
225
|
+
* @param description - The raw rule description.
|
|
226
|
+
* @returns Cleaned description.
|
|
227
|
+
*/
|
|
228
|
+
function cleanRuleDescription(description: string): string {
|
|
229
|
+
// Remove the rule name prefix if present
|
|
230
|
+
return description.replace(/^[A-Z0-9_]+\s*/, "").trim();
|
|
231
|
+
}
|
|
@@ -11,17 +11,17 @@ import {
|
|
|
11
11
|
getStoredFontsConfig,
|
|
12
12
|
resolveFontConfig,
|
|
13
13
|
viteFontPlugin,
|
|
14
|
-
} from "appos/vite";
|
|
14
|
+
} from "appos/devtools/vite";
|
|
15
15
|
import type { Plugin } from "vite";
|
|
16
16
|
import { mergeConfig } from "vite";
|
|
17
17
|
import {
|
|
18
18
|
type ParsedTheme,
|
|
19
19
|
parseThemeFromString,
|
|
20
|
-
} from "
|
|
20
|
+
} from "../../../web/lib/colors.ts";
|
|
21
21
|
|
|
22
22
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
23
23
|
const storybookDir = join(__dirname, "..");
|
|
24
|
-
const apposRoot = join(__dirname, "
|
|
24
|
+
const apposRoot = join(__dirname, "../../../..");
|
|
25
25
|
const appRoot = process.cwd();
|
|
26
26
|
const appName = `${process.env.APP_NAME || "AppOS"} Design System`;
|
|
27
27
|
|
|
@@ -142,6 +142,14 @@ export default {
|
|
|
142
142
|
})();
|
|
143
143
|
window.STORYBOOK_THEME = ${JSON.stringify(buildStorybookTheme(theme))};
|
|
144
144
|
window.STORYBOOK_BRAND_TITLE = '<img src="/logo.png" alt="" style="height: 28px; margin-right: 4px; vertical-align: middle;" />' + ${JSON.stringify(appName)};
|
|
145
|
+
</script>`,
|
|
146
|
+
previewHead: (head) => `${head}
|
|
147
|
+
<link rel="icon" href="/favicon.ico" />
|
|
148
|
+
<title>${appName}</title>
|
|
149
|
+
<style>${fontCss}</style>
|
|
150
|
+
<script>
|
|
151
|
+
window.STORYBOOK_THEME = ${JSON.stringify(buildStorybookTheme(theme))};
|
|
152
|
+
window.STORYBOOK_BRAND_TITLE = '<img src="/logo.png" alt="" style="height: 28px; margin-right: 4px; vertical-align: middle;" />' + ${JSON.stringify(appName)};
|
|
145
153
|
</script>`,
|
|
146
154
|
staticDirs: [join(appRoot, "public")],
|
|
147
155
|
stories: [
|
|
@@ -187,8 +195,8 @@ window.STORYBOOK_BRAND_TITLE = '<img src="/logo.png" alt="" style="height: 28px;
|
|
|
187
195
|
resolve: {
|
|
188
196
|
alias: {
|
|
189
197
|
"#api": join(appRoot, "api"),
|
|
190
|
-
"#isomorphic": join(appRoot, "isomorphic"),
|
|
191
198
|
"#src": join(apposRoot, "src"),
|
|
199
|
+
"#universal": join(appRoot, "universal"),
|
|
192
200
|
"#web": join(appRoot, "web"),
|
|
193
201
|
"void-elements": join(storybookDir, "shims/void-elements.js"),
|
|
194
202
|
},
|
|
@@ -2,7 +2,7 @@ import { addons } from "storybook/manager-api";
|
|
|
2
2
|
import { create } from "storybook/theming";
|
|
3
3
|
|
|
4
4
|
/** Storybook theme configuration from CSS variables. */
|
|
5
|
-
interface StorybookTheme {
|
|
5
|
+
export interface StorybookTheme {
|
|
6
6
|
base: "light" | "dark";
|
|
7
7
|
colorPrimary: string;
|
|
8
8
|
colorSecondary: string;
|
|
@@ -5,8 +5,11 @@ import { withThemeByClassName } from "@storybook/addon-themes";
|
|
|
5
5
|
import type { Preview, ReactRenderer } from "@storybook/react";
|
|
6
6
|
import i18n from "i18next";
|
|
7
7
|
import { I18nextProvider, initReactI18next } from "react-i18next";
|
|
8
|
+
import { create } from "storybook/theming";
|
|
8
9
|
import { withRouter } from "storybook-addon-remix-react-router";
|
|
9
|
-
import enUI from "
|
|
10
|
+
import enUI from "../../../web/ui/locales/en/ui.json";
|
|
11
|
+
// Import to get Window.STORYBOOK_THEME declaration
|
|
12
|
+
import type {} from "./manager.ts";
|
|
10
13
|
|
|
11
14
|
// Initialize i18n synchronously for Storybook with bundled translations.
|
|
12
15
|
i18n.use(initReactI18next).init({
|
|
@@ -64,6 +67,9 @@ export default {
|
|
|
64
67
|
* nothing. It can be removed once the bug is fixed.
|
|
65
68
|
*/
|
|
66
69
|
container: DocsContainer,
|
|
70
|
+
theme: window.STORYBOOK_THEME
|
|
71
|
+
? create(window.STORYBOOK_THEME)
|
|
72
|
+
: undefined,
|
|
67
73
|
source: {
|
|
68
74
|
type: "dynamic",
|
|
69
75
|
excludeDecorators: true,
|
|
@@ -16,7 +16,9 @@ Explore foundations, components, and patterns that power your product.
|
|
|
16
16
|
## Usage
|
|
17
17
|
|
|
18
18
|
```tsx
|
|
19
|
-
import { Button
|
|
19
|
+
import { Button } from "appos/web/ui/button";
|
|
20
|
+
import { Card } from "appos/web/ui/card";
|
|
21
|
+
import { Input } from "appos/web/ui/input";
|
|
20
22
|
|
|
21
23
|
function MyComponent() {
|
|
22
24
|
return (
|
|
@@ -1,13 +1,43 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* This module contains auth path configuration and redirect utilities that are
|
|
5
|
-
* safe to import in client-side code (no Node.js APIs).
|
|
6
|
-
*
|
|
7
|
-
* For route building (uses Node.js APIs), see routes/auth/utils.ts.
|
|
2
|
+
* Universal auth constants and types - no Node.js or browser-specific APIs.
|
|
8
3
|
*/
|
|
9
4
|
import { redirect } from "react-router";
|
|
10
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Default base path for auth routes.
|
|
8
|
+
*/
|
|
9
|
+
export const AUTH_BASE_PATH = "/auth" as const;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Default base URL (empty - same origin).
|
|
13
|
+
*/
|
|
14
|
+
export const AUTH_BASE_URL = "" as const;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Array of all supported captcha providers.
|
|
18
|
+
* Use with z.enum() for config validation.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* CAPTCHA_PROVIDER: z.enum(captchaProviders).optional(),
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export const captchaProviders = [
|
|
26
|
+
"captchafox",
|
|
27
|
+
"cloudflare-turnstile",
|
|
28
|
+
"google-recaptcha",
|
|
29
|
+
"hcaptcha",
|
|
30
|
+
] as const;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Captcha provider type.
|
|
34
|
+
*/
|
|
35
|
+
export type CaptchaProvider = (typeof captchaProviders)[number];
|
|
36
|
+
|
|
37
|
+
// ============================================================================
|
|
38
|
+
// Auth Paths
|
|
39
|
+
// ============================================================================
|
|
40
|
+
|
|
11
41
|
/**
|
|
12
42
|
* Configuration for authentication route paths.
|
|
13
43
|
*
|
|
@@ -81,6 +111,10 @@ export const DEFAULT_AUTH_PATHS: AuthPaths = {
|
|
|
81
111
|
emailOtp: "/email-login",
|
|
82
112
|
};
|
|
83
113
|
|
|
114
|
+
// ============================================================================
|
|
115
|
+
// Auth Redirect Utilities
|
|
116
|
+
// ============================================================================
|
|
117
|
+
|
|
84
118
|
/**
|
|
85
119
|
* Creates a redirect response to the login page with the return URL preserved.
|
|
86
120
|
*
|
|
@@ -146,3 +180,17 @@ export function definePostAuthRedirect(
|
|
|
146
180
|
const redirectTo = url.searchParams.get("redirect") || fallbackPath;
|
|
147
181
|
return redirect(redirectTo);
|
|
148
182
|
}
|
|
183
|
+
|
|
184
|
+
// ============================================================================
|
|
185
|
+
// Auth Layout Types (used for config, no React runtime deps)
|
|
186
|
+
// ============================================================================
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Available layout variants for authentication pages.
|
|
190
|
+
*/
|
|
191
|
+
export const authLayoutVariants = ["centered", "split", "minimal"] as const;
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Auth layout variant type.
|
|
195
|
+
*/
|
|
196
|
+
export type AuthLayoutVariant = (typeof authLayoutVariants)[number];
|