@gravito/signal 3.0.3 → 3.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +89 -60
  3. package/README.zh-TW.md +140 -9
  4. package/dist/MjmlRenderer-IUH663FT.mjs +8 -0
  5. package/dist/ReactMjmlRenderer-C3P5YO5L.mjs +8 -0
  6. package/dist/ReactRenderer-2JFLRVST.mjs +45 -0
  7. package/dist/{ReactRenderer-L5INVYKT.mjs → ReactRenderer-LYEOSYFS.mjs} +9 -8
  8. package/dist/ReactRenderer-V54CUUEI.mjs +45 -0
  9. package/dist/VueMjmlRenderer-4F4CXHDB.mjs +8 -0
  10. package/dist/VueMjmlRenderer-5WZR4CQG.mjs +8 -0
  11. package/dist/VueMjmlRenderer-U5YMWI44.mjs +8 -0
  12. package/dist/VueRenderer-3YBRQXME.mjs +48 -0
  13. package/dist/VueRenderer-46JGXTJ2.mjs +48 -0
  14. package/dist/VueRenderer-5KWD4R3C.mjs +48 -0
  15. package/dist/VueRenderer-C23U4O5E.mjs +48 -0
  16. package/dist/VueRenderer-LEVDFLHP.mjs +31 -0
  17. package/dist/VueRenderer-RNHSCCRI.mjs +48 -0
  18. package/dist/chunk-3WOR3XSL.mjs +82 -0
  19. package/dist/chunk-DBFIVHHG.mjs +79 -0
  20. package/dist/{chunk-6DZX6EAA.mjs → chunk-HEBXNMVQ.mjs} +12 -1
  21. package/dist/chunk-KB7IDDBT.mjs +82 -0
  22. package/dist/chunk-LZL5UUPC.mjs +82 -0
  23. package/dist/chunk-W6LXIJKK.mjs +57 -0
  24. package/dist/chunk-XBIVBJS2.mjs +8 -0
  25. package/dist/index.d.mts +1680 -209
  26. package/dist/index.d.ts +1680 -209
  27. package/dist/index.js +69405 -542
  28. package/dist/index.mjs +993 -110
  29. package/dist/lib-HJTRWKU5.mjs +67788 -0
  30. package/dist/{VueRenderer-Z5PRVBNH.mjs → server-renderer-4IM3P5XZ.mjs} +308 -423
  31. package/dist/server-renderer-7KWFSTPV.mjs +37193 -0
  32. package/dist/{VueRenderer-S65ZARRI.mjs → server-renderer-S5FPSTJ2.mjs} +931 -877
  33. package/dist/server-renderer-X5LUFVWT.mjs +37193 -0
  34. package/doc/OPTIMIZATION_PLAN.md +496 -0
  35. package/package.json +14 -12
  36. package/scripts/check-coverage.ts +64 -0
  37. package/src/Mailable.ts +340 -44
  38. package/src/OrbitSignal.ts +350 -50
  39. package/src/TypedMailable.ts +96 -0
  40. package/src/dev/DevMailbox.ts +89 -33
  41. package/src/dev/DevServer.ts +14 -14
  42. package/src/dev/storage/FileMailboxStorage.ts +66 -0
  43. package/src/dev/storage/MailboxStorage.ts +15 -0
  44. package/src/dev/storage/MemoryMailboxStorage.ts +36 -0
  45. package/src/dev/ui/mailbox.ts +1 -1
  46. package/src/dev/ui/preview.ts +4 -4
  47. package/src/errors.ts +69 -0
  48. package/src/events.ts +72 -0
  49. package/src/index.ts +20 -1
  50. package/src/renderers/HtmlRenderer.ts +20 -18
  51. package/src/renderers/MjmlRenderer.ts +73 -0
  52. package/src/renderers/ReactMjmlRenderer.ts +94 -0
  53. package/src/renderers/ReactRenderer.ts +26 -21
  54. package/src/renderers/Renderer.ts +43 -3
  55. package/src/renderers/TemplateRenderer.ts +48 -15
  56. package/src/renderers/VueMjmlRenderer.ts +99 -0
  57. package/src/renderers/VueRenderer.ts +26 -21
  58. package/src/renderers/mjml-templates.ts +50 -0
  59. package/src/transports/BaseTransport.ts +148 -0
  60. package/src/transports/LogTransport.ts +28 -6
  61. package/src/transports/MemoryTransport.ts +34 -6
  62. package/src/transports/SesTransport.ts +62 -17
  63. package/src/transports/SmtpTransport.ts +123 -27
  64. package/src/transports/Transport.ts +33 -4
  65. package/src/types.ts +172 -3
  66. package/src/utils/html.ts +43 -0
  67. package/src/webhooks/SendGridWebhookDriver.ts +80 -0
  68. package/src/webhooks/SesWebhookDriver.ts +44 -0
  69. package/tests/DevMailbox.test.ts +54 -0
  70. package/tests/FileMailboxStorage.test.ts +56 -0
  71. package/tests/MjmlLayout.test.ts +28 -0
  72. package/tests/MjmlRenderer.test.ts +53 -0
  73. package/tests/OrbitSignalWebhook.test.ts +56 -0
  74. package/tests/ReactMjmlRenderer.test.ts +33 -0
  75. package/tests/SendGridWebhookDriver.test.ts +69 -0
  76. package/tests/SesWebhookDriver.test.ts +46 -0
  77. package/tests/VueMjmlRenderer.test.ts +35 -0
  78. package/tests/dev-server.test.ts +1 -1
  79. package/tests/transports.test.ts +3 -3
  80. package/tsconfig.json +12 -24
  81. package/dist/OrbitMail-2Z7ZTKYA.mjs +0 -7
  82. package/dist/OrbitMail-BGV32HWN.mjs +0 -7
  83. package/dist/OrbitMail-FUYZQSAV.mjs +0 -7
  84. package/dist/OrbitMail-NAPCRK7B.mjs +0 -7
  85. package/dist/OrbitMail-REGJ276B.mjs +0 -7
  86. package/dist/OrbitMail-TCFBJWDT.mjs +0 -7
  87. package/dist/OrbitMail-XZZW6U4N.mjs +0 -7
  88. package/dist/OrbitSignal-IPSA2CDO.mjs +0 -7
  89. package/dist/OrbitSignal-MABW4DDW.mjs +0 -7
  90. package/dist/OrbitSignal-QSW5VQ5M.mjs +0 -7
  91. package/dist/OrbitSignal-R22QHWAA.mjs +0 -7
  92. package/dist/OrbitSignal-ZKKMEC27.mjs +0 -7
  93. package/dist/chunk-3U2CYJO5.mjs +0 -367
  94. package/dist/chunk-3XFC4T6M.mjs +0 -392
  95. package/dist/chunk-456QRYFW.mjs +0 -401
  96. package/dist/chunk-DT3R2TNV.mjs +0 -367
  97. package/dist/chunk-F6MVTUCT.mjs +0 -421
  98. package/dist/chunk-GADWIVC4.mjs +0 -400
  99. package/dist/chunk-HHKFAMSE.mjs +0 -380
  100. package/dist/chunk-NEQCQSZI.mjs +0 -406
  101. package/dist/chunk-OKRNL6PN.mjs +0 -400
  102. package/dist/chunk-ULN3GMY2.mjs +0 -367
  103. package/dist/chunk-XAWO7RSP.mjs +0 -398
  104. package/dist/chunk-YLVDJSED.mjs +0 -431
@@ -0,0 +1,33 @@
1
+ import { describe, expect, it, mock } from 'bun:test'
2
+ import { ReactMjmlRenderer } from '../src/renderers/ReactMjmlRenderer'
3
+
4
+ describe('ReactMjmlRenderer', () => {
5
+ it('should render React component to MJML then to HTML', async () => {
6
+ const mockComponent = {}
7
+ const mockElement = { type: 'mjml' }
8
+ const mockMjml = '<mjml><mj-body>Hello</mj-body></mjml>'
9
+ const mockHtml = '<html><body>Hello</body></html>'
10
+
11
+ const createElement = mock(() => mockElement)
12
+ const renderToStaticMarkup = mock(() => mockMjml)
13
+ const mjml2html = mock(() => ({ html: mockHtml, errors: [] }))
14
+
15
+ const renderer = new ReactMjmlRenderer(
16
+ mockComponent,
17
+ { name: 'World' },
18
+ {},
19
+ {
20
+ createElement,
21
+ renderToStaticMarkup,
22
+ mjml2html,
23
+ }
24
+ )
25
+
26
+ const result = await renderer.render({ extra: 'data' })
27
+
28
+ expect(createElement).toHaveBeenCalledWith(mockComponent, { name: 'World', extra: 'data' })
29
+ expect(renderToStaticMarkup).toHaveBeenCalledWith(mockElement)
30
+ expect(mjml2html).toHaveBeenCalledWith(mockMjml, expect.any(Object))
31
+ expect(result.html).toBe(mockHtml)
32
+ })
33
+ })
@@ -0,0 +1,69 @@
1
+ import { describe, expect, it } from 'bun:test'
2
+ import type { GravitoContext } from '@gravito/core'
3
+ import { SendGridWebhookDriver } from '../src/webhooks/SendGridWebhookDriver'
4
+
5
+ describe('SendGridWebhookDriver', () => {
6
+ it('should parse batch events from request body', async () => {
7
+ const driver = new SendGridWebhookDriver()
8
+
9
+ const mockEvents = [
10
+ { event: 'delivered', email: 'user1@example.com', timestamp: 123456789 },
11
+ { event: 'opened', email: 'user1@example.com', timestamp: 123456790 },
12
+ ]
13
+
14
+ const mockCtx = {
15
+ req: {
16
+ json: async () => mockEvents,
17
+ header: () => undefined,
18
+ },
19
+ } as unknown as GravitoContext
20
+
21
+ const result = await driver.handle(mockCtx)
22
+
23
+ expect(result).toHaveLength(2)
24
+ expect(result?.[0].event).toBe('delivered')
25
+ expect(result?.[1].event).toBe('opened')
26
+ expect(result?.[0].payload.email).toBe('user1@example.com')
27
+ })
28
+
29
+ it('should handle single event body', async () => {
30
+ const driver = new SendGridWebhookDriver()
31
+ const mockEvent = { event: 'bounced', email: 'bad@example.com' }
32
+
33
+ const mockCtx = {
34
+ req: {
35
+ json: async () => mockEvent,
36
+ header: () => undefined,
37
+ },
38
+ } as unknown as GravitoContext
39
+
40
+ const result = await driver.handle(mockCtx)
41
+ expect(result).toHaveLength(1)
42
+ expect(result?.[0].event).toBe('bounced')
43
+ })
44
+
45
+ it('should return null for empty body', async () => {
46
+ const driver = new SendGridWebhookDriver()
47
+ const mockCtx = {
48
+ req: {
49
+ json: async () => [],
50
+ header: () => undefined,
51
+ },
52
+ } as unknown as GravitoContext
53
+
54
+ const result = await driver.handle(mockCtx)
55
+ expect(result).toBeNull()
56
+ })
57
+
58
+ it('should throw if public key is set but signature is missing', async () => {
59
+ const driver = new SendGridWebhookDriver({ publicKey: 'some-key' })
60
+ const mockCtx = {
61
+ req: {
62
+ json: async () => [{ event: 'test' }],
63
+ header: (_name: string) => undefined,
64
+ },
65
+ } as unknown as GravitoContext
66
+
67
+ expect(driver.handle(mockCtx)).rejects.toThrow('Missing SendGrid signature headers')
68
+ })
69
+ })
@@ -0,0 +1,46 @@
1
+ import { describe, expect, it } from 'bun:test'
2
+ import type { GravitoContext } from '@gravito/core'
3
+ import { SesWebhookDriver } from '../src/webhooks/SesWebhookDriver'
4
+
5
+ describe('SesWebhookDriver', () => {
6
+ it('should parse SNS notification events', async () => {
7
+ const driver = new SesWebhookDriver()
8
+
9
+ const mockSnsBody = {
10
+ Type: 'Notification',
11
+ Message: JSON.stringify({
12
+ notificationType: 'Bounce',
13
+ bounce: { bounceType: 'Permanent', bounceSubType: 'General' },
14
+ }),
15
+ }
16
+
17
+ const mockCtx = {
18
+ req: {
19
+ json: async () => mockSnsBody,
20
+ },
21
+ } as unknown as GravitoContext
22
+
23
+ const result = await driver.handle(mockCtx)
24
+
25
+ expect(result).toHaveLength(1)
26
+ expect(result?.[0].event).toBe('bounce')
27
+ expect(result?.[0].payload.bounce.bounceType).toBe('Permanent')
28
+ })
29
+
30
+ it('should handle subscription confirmation', async () => {
31
+ const driver = new SesWebhookDriver()
32
+ const mockSnsBody = {
33
+ Type: 'SubscriptionConfirmation',
34
+ SubscribeURL: 'https://sns.aws.com/confirm',
35
+ }
36
+
37
+ const mockCtx = {
38
+ req: {
39
+ json: async () => mockSnsBody,
40
+ },
41
+ } as unknown as GravitoContext
42
+
43
+ const result = await driver.handle(mockCtx)
44
+ expect(result?.[0].event).toBe('sns:subscription')
45
+ })
46
+ })
@@ -0,0 +1,35 @@
1
+ import { describe, expect, it, mock } from 'bun:test'
2
+ import { VueMjmlRenderer } from '../src/renderers/VueMjmlRenderer'
3
+
4
+ describe('VueMjmlRenderer', () => {
5
+ it('should render Vue component to MJML then to HTML', async () => {
6
+ const mockComponent = { name: 'Test' }
7
+ const mockApp = { _context: {} }
8
+ const mockMjml = '<mjml><mj-body>Vue MJML</mj-body></mjml>'
9
+ const mockHtml = '<html><body>Vue MJML</body></html>'
10
+
11
+ const createSSRApp = mock(() => mockApp)
12
+ const h = mock(() => ({}))
13
+ const renderToString = mock(async () => mockMjml)
14
+ const mjml2html = mock(() => ({ html: mockHtml, errors: [] }))
15
+
16
+ const renderer = new VueMjmlRenderer(
17
+ mockComponent,
18
+ { name: 'World' },
19
+ {},
20
+ {
21
+ createSSRApp,
22
+ h,
23
+ renderToString,
24
+ mjml2html,
25
+ }
26
+ )
27
+
28
+ const result = await renderer.render({ extra: 'data' })
29
+
30
+ expect(createSSRApp).toHaveBeenCalled()
31
+ expect(renderToString).toHaveBeenCalledWith(mockApp)
32
+ expect(mjml2html).toHaveBeenCalledWith(mockMjml, expect.any(Object))
33
+ expect(result.html).toBe(mockHtml)
34
+ })
35
+ })
@@ -20,7 +20,7 @@ const createCore = () => {
20
20
  describe('DevServer', () => {
21
21
  it('registers mailbox routes and serves entries', async () => {
22
22
  const mailbox = new DevMailbox()
23
- const entry = mailbox.add({
23
+ const entry = await mailbox.add({
24
24
  from: { address: 'from@example.com' },
25
25
  to: [{ address: 'to@example.com' }],
26
26
  subject: 'Hello',
@@ -19,7 +19,7 @@ describe('Transports', () => {
19
19
 
20
20
  await transport.send(message)
21
21
 
22
- const entries = mailbox.list()
22
+ const entries = await mailbox.list()
23
23
  expect(entries).toHaveLength(1)
24
24
 
25
25
  const entry = entries[0]
@@ -44,9 +44,9 @@ describe('Transports', () => {
44
44
  })
45
45
  }
46
46
 
47
- expect(mailbox.list().length).toBeLessThanOrEqual(50)
47
+ expect((await mailbox.list()).length).toBeLessThanOrEqual(50)
48
48
  // Should be the latest ones (last one added is index 0)
49
- expect(mailbox.list()[0].envelope.subject).toBe('Msg 59')
49
+ expect((await mailbox.list())[0].envelope.subject).toBe('Msg 59')
50
50
  })
51
51
  })
52
52
  })
package/tsconfig.json CHANGED
@@ -1,26 +1,14 @@
1
1
  {
2
- "extends": "../../tsconfig.json",
3
- "compilerOptions": {
4
- "outDir": "./dist",
5
- "baseUrl": ".",
6
- "paths": {
7
- "@gravito/core": [
8
- "../../packages/core/src/index.ts"
9
- ],
10
- "@gravito/*": [
11
- "../../packages/*/src/index.ts"
12
- ]
13
- },
14
- "types": [
15
- "bun-types"
16
- ]
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "baseUrl": ".",
6
+ "paths": {
7
+ "@gravito/core": ["../../packages/core/src/index.ts"],
8
+ "@gravito/*": ["../../packages/*/src/index.ts"]
17
9
  },
18
- "include": [
19
- "src/**/*"
20
- ],
21
- "exclude": [
22
- "node_modules",
23
- "dist",
24
- "**/*.test.ts"
25
- ]
26
- }
10
+ "types": ["bun-types"]
11
+ },
12
+ "include": ["src/**/*"],
13
+ "exclude": ["node_modules", "dist", "**/*.test.ts"]
14
+ }
@@ -1,7 +0,0 @@
1
- import {
2
- OrbitMail
3
- } from "./chunk-XAWO7RSP.mjs";
4
- import "./chunk-6DZX6EAA.mjs";
5
- export {
6
- OrbitMail
7
- };
@@ -1,7 +0,0 @@
1
- import {
2
- OrbitMail
3
- } from "./chunk-DT3R2TNV.mjs";
4
- import "./chunk-6DZX6EAA.mjs";
5
- export {
6
- OrbitMail
7
- };
@@ -1,7 +0,0 @@
1
- import {
2
- OrbitMail
3
- } from "./chunk-OKRNL6PN.mjs";
4
- import "./chunk-6DZX6EAA.mjs";
5
- export {
6
- OrbitMail
7
- };
@@ -1,7 +0,0 @@
1
- import {
2
- OrbitMail
3
- } from "./chunk-HHKFAMSE.mjs";
4
- import "./chunk-6DZX6EAA.mjs";
5
- export {
6
- OrbitMail
7
- };
@@ -1,7 +0,0 @@
1
- import {
2
- OrbitMail
3
- } from "./chunk-3XFC4T6M.mjs";
4
- import "./chunk-6DZX6EAA.mjs";
5
- export {
6
- OrbitMail
7
- };
@@ -1,7 +0,0 @@
1
- import {
2
- OrbitMail
3
- } from "./chunk-3U2CYJO5.mjs";
4
- import "./chunk-6DZX6EAA.mjs";
5
- export {
6
- OrbitMail
7
- };
@@ -1,7 +0,0 @@
1
- import {
2
- OrbitMail
3
- } from "./chunk-ULN3GMY2.mjs";
4
- import "./chunk-6DZX6EAA.mjs";
5
- export {
6
- OrbitMail
7
- };
@@ -1,7 +0,0 @@
1
- import {
2
- OrbitSignal
3
- } from "./chunk-YLVDJSED.mjs";
4
- import "./chunk-EBO3CZXG.mjs";
5
- export {
6
- OrbitSignal
7
- };
@@ -1,7 +0,0 @@
1
- import {
2
- OrbitSignal
3
- } from "./chunk-456QRYFW.mjs";
4
- import "./chunk-6DZX6EAA.mjs";
5
- export {
6
- OrbitSignal
7
- };
@@ -1,7 +0,0 @@
1
- import {
2
- OrbitSignal
3
- } from "./chunk-NEQCQSZI.mjs";
4
- import "./chunk-EBO3CZXG.mjs";
5
- export {
6
- OrbitSignal
7
- };
@@ -1,7 +0,0 @@
1
- import {
2
- OrbitSignal
3
- } from "./chunk-F6MVTUCT.mjs";
4
- import "./chunk-EBO3CZXG.mjs";
5
- export {
6
- OrbitSignal
7
- };
@@ -1,7 +0,0 @@
1
- import {
2
- OrbitSignal
3
- } from "./chunk-GADWIVC4.mjs";
4
- import "./chunk-6DZX6EAA.mjs";
5
- export {
6
- OrbitSignal
7
- };