@gravito/signal 3.1.0 → 3.1.2

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 (68) hide show
  1. package/dist/index.cjs +55126 -81925
  2. package/dist/index.d.ts +513 -1
  3. package/dist/index.js +61492 -0
  4. package/dist/index.mjs +55301 -82110
  5. package/package.json +12 -1
  6. package/CHANGELOG.md +0 -74
  7. package/build.ts +0 -133
  8. package/dist/index.cjs.map +0 -712
  9. package/dist/index.mjs.map +0 -710
  10. package/doc/ADVANCED_RENDERING.md +0 -71
  11. package/doc/DISTRIBUTED_MESSAGING.md +0 -79
  12. package/doc/OPTIMIZATION_PLAN.md +0 -496
  13. package/package.json.bak +0 -75
  14. package/scripts/check-coverage.ts +0 -64
  15. package/src/Mailable.ts +0 -674
  16. package/src/OrbitSignal.ts +0 -451
  17. package/src/Queueable.ts +0 -9
  18. package/src/TypedMailable.ts +0 -96
  19. package/src/dev/DevMailbox.ts +0 -146
  20. package/src/dev/DevServer.ts +0 -192
  21. package/src/dev/storage/FileMailboxStorage.ts +0 -66
  22. package/src/dev/storage/MailboxStorage.ts +0 -15
  23. package/src/dev/storage/MemoryMailboxStorage.ts +0 -36
  24. package/src/dev/ui/mailbox.ts +0 -77
  25. package/src/dev/ui/preview.ts +0 -103
  26. package/src/dev/ui/shared.ts +0 -60
  27. package/src/errors.ts +0 -69
  28. package/src/events.ts +0 -72
  29. package/src/index.ts +0 -41
  30. package/src/renderers/HtmlRenderer.ts +0 -41
  31. package/src/renderers/MjmlRenderer.ts +0 -73
  32. package/src/renderers/ReactMjmlRenderer.ts +0 -94
  33. package/src/renderers/ReactRenderer.ts +0 -66
  34. package/src/renderers/Renderer.ts +0 -67
  35. package/src/renderers/TemplateRenderer.ts +0 -84
  36. package/src/renderers/VueMjmlRenderer.ts +0 -99
  37. package/src/renderers/VueRenderer.ts +0 -71
  38. package/src/renderers/mjml-templates.ts +0 -50
  39. package/src/transports/BaseTransport.ts +0 -148
  40. package/src/transports/LogTransport.ts +0 -55
  41. package/src/transports/MemoryTransport.ts +0 -55
  42. package/src/transports/SesTransport.ts +0 -129
  43. package/src/transports/SmtpTransport.ts +0 -184
  44. package/src/transports/Transport.ts +0 -45
  45. package/src/types.ts +0 -309
  46. package/src/utils/html.ts +0 -43
  47. package/src/webhooks/SendGridWebhookDriver.ts +0 -80
  48. package/src/webhooks/SesWebhookDriver.ts +0 -44
  49. package/tests/DevMailbox.test.ts +0 -54
  50. package/tests/FileMailboxStorage.test.ts +0 -56
  51. package/tests/MjmlLayout.test.ts +0 -28
  52. package/tests/MjmlRenderer.test.ts +0 -53
  53. package/tests/OrbitSignalWebhook.test.ts +0 -56
  54. package/tests/ReactMjmlRenderer.test.ts +0 -33
  55. package/tests/SendGridWebhookDriver.test.ts +0 -69
  56. package/tests/SesWebhookDriver.test.ts +0 -46
  57. package/tests/VueMjmlRenderer.test.ts +0 -35
  58. package/tests/dev-server.test.ts +0 -66
  59. package/tests/log-transport.test.ts +0 -21
  60. package/tests/mailable-extra.test.ts +0 -68
  61. package/tests/mailable.test.ts +0 -77
  62. package/tests/orbit-signal.test.ts +0 -43
  63. package/tests/renderers.test.ts +0 -58
  64. package/tests/template-renderer.test.ts +0 -24
  65. package/tests/transports.test.ts +0 -52
  66. package/tests/ui.test.ts +0 -37
  67. package/tsconfig.build.json +0 -24
  68. package/tsconfig.json +0 -9
package/src/index.ts DELETED
@@ -1,41 +0,0 @@
1
- /**
2
- * OrbitSignal - The central Event Bus and Mail Service for Gravito.
3
- *
4
- * This module provides the core infrastructure for sending emails and managing
5
- * cross-module signals within the Gravito ecosystem. It supports multiple
6
- * transport drivers, template rendering, and a robust development environment.
7
- *
8
- * @packageDocumentation
9
- */
10
-
11
- // import './augmentation'
12
-
13
- export type { Queueable } from '@gravito/stream'
14
- export { DevMailbox, type MailboxEntry } from './dev/DevMailbox'
15
- export { MailErrorCode, MailTransportError } from './errors'
16
- export type { MailEvent, MailEventHandler, MailEventType } from './events'
17
- export { Mailable } from './Mailable'
18
- export { OrbitSignal } from './OrbitSignal'
19
- export { HtmlRenderer } from './renderers/HtmlRenderer'
20
- export { MjmlRenderer } from './renderers/MjmlRenderer'
21
- export * from './renderers/mjml-templates'
22
- export { ReactMjmlRenderer } from './renderers/ReactMjmlRenderer'
23
- export type { Renderer, RenderResult } from './renderers/Renderer'
24
- export { TemplateRenderer } from './renderers/TemplateRenderer'
25
- export { VueMjmlRenderer } from './renderers/VueMjmlRenderer'
26
- export { TypedMailable } from './TypedMailable'
27
- export { BaseTransport, type TransportOptions } from './transports/BaseTransport'
28
- export { LogTransport } from './transports/LogTransport'
29
- export { MemoryTransport } from './transports/MemoryTransport'
30
- export { SesTransport } from './transports/SesTransport'
31
- export { SmtpTransport } from './transports/SmtpTransport'
32
- export type { Transport } from './transports/Transport'
33
- export type {
34
- Address,
35
- Attachment,
36
- Envelope,
37
- MailConfig,
38
- Message,
39
- } from './types'
40
- export { type SendGridWebhookConfig, SendGridWebhookDriver } from './webhooks/SendGridWebhookDriver'
41
- export { SesWebhookDriver } from './webhooks/SesWebhookDriver'
@@ -1,41 +0,0 @@
1
- import { stripHtml } from '../utils/html'
2
- import type { Renderer, RenderResult } from './Renderer'
3
-
4
- /**
5
- * Renderer for plain HTML content.
6
- *
7
- * The simplest renderer - accepts raw HTML strings and automatically generates
8
- * a plain text version by stripping HTML tags. Ideal for pre-rendered HTML or
9
- * when using external HTML generation libraries.
10
- *
11
- * @example
12
- * ```typescript
13
- * const renderer = new HtmlRenderer('<h1>Hello</h1>');
14
- * const result = await renderer.render();
15
- * // result.html: '<h1>Hello</h1>'
16
- * // result.text: 'Hello'
17
- * ```
18
- *
19
- * @public
20
- * @since 3.0.0
21
- */
22
- export class HtmlRenderer implements Renderer {
23
- /**
24
- * Creates an instance of HtmlRenderer.
25
- *
26
- * @param content - The raw HTML string to be rendered.
27
- */
28
- constructor(private content: string) {}
29
-
30
- /**
31
- * Returns the original HTML and a stripped plain text version.
32
- *
33
- * @returns A promise resolving to the rendered content.
34
- */
35
- async render(): Promise<RenderResult> {
36
- return {
37
- html: this.content,
38
- text: stripHtml(this.content),
39
- }
40
- }
41
- }
@@ -1,73 +0,0 @@
1
- import { stripHtml } from '../utils/html'
2
- import type { Renderer, RenderResult } from './Renderer'
3
-
4
- /**
5
- * Renderer for MJML-based emails.
6
- *
7
- * MJML is a markup language designed to reduce the pain of coding a responsive email.
8
- * This renderer lazily loads the `mjml` package to keep the core lightweight.
9
- *
10
- * @example
11
- * ```typescript
12
- * const renderer = new MjmlRenderer('<mjml><mj-body>...</mj-body></mjml>');
13
- * const result = await renderer.render();
14
- * ```
15
- *
16
- * @public
17
- * @since 1.1.0
18
- */
19
- export class MjmlRenderer implements Renderer {
20
- /**
21
- * Creates an instance of MjmlRenderer.
22
- *
23
- * @param content - The MJML markup string to be rendered.
24
- * @param options - Optional MJML transformation options.
25
- * @param deps - Optional dependency injection for testing.
26
- */
27
- constructor(
28
- private content: string,
29
- private options: Record<string, any> = {},
30
- private deps: {
31
- mjml2html?: (mjml: string, options?: any) => any
32
- } = {}
33
- ) {}
34
-
35
- /**
36
- * Renders the MJML content to static HTML.
37
- *
38
- * This method performs a dynamic import of `mjml` to ensure it's only
39
- * loaded if this renderer is actually used.
40
- *
41
- * @returns A promise resolving to the rendered content.
42
- * @throws {Error} If MJML dependencies cannot be loaded or rendering fails.
43
- */
44
- async render(): Promise<RenderResult> {
45
- let mjml2html = this.deps.mjml2html
46
-
47
- if (!mjml2html) {
48
- try {
49
- mjml2html = (await import('mjml')).default
50
- } catch (_e) {
51
- throw new Error(
52
- '[OrbitSignal] The "mjml" package is required for MjmlRenderer. Please install it using "bun add mjml".'
53
- )
54
- }
55
- }
56
-
57
- const { html, errors } = mjml2html(this.content, {
58
- validationLevel: 'soft',
59
- ...this.options,
60
- })
61
-
62
- if (errors && errors.length > 0 && this.options.validationLevel === 'strict') {
63
- throw new Error(
64
- `MJML rendering failed: ${errors.map((e: any) => e.formattedMessage).join(', ')}`
65
- )
66
- }
67
-
68
- return {
69
- html,
70
- text: stripHtml(html),
71
- }
72
- }
73
- }
@@ -1,94 +0,0 @@
1
- import { stripHtml } from '../utils/html'
2
- import type { Renderer, RenderResult } from './Renderer'
3
-
4
- /**
5
- * Renderer for React component-based MJML emails.
6
- *
7
- * Renders React components to MJML string using SSR, then converts
8
- * the MJML to responsive HTML.
9
- *
10
- * @typeParam P - Props type for the React component.
11
- * @public
12
- * @since 1.1.0
13
- */
14
- export class ReactMjmlRenderer<P extends object = object> implements Renderer {
15
- /**
16
- * Creates an instance of ReactMjmlRenderer.
17
- *
18
- * @param component - The React component to render.
19
- * @param props - Initial props for the component.
20
- * @param options - Optional MJML transformation options.
21
- * @param deps - Optional dependency injection for testing.
22
- */
23
- constructor(
24
- private component: any,
25
- private props?: P,
26
- private options: Record<string, any> = {},
27
- private deps: {
28
- createElement?: (...args: any[]) => any
29
- renderToStaticMarkup?: (element: any) => string
30
- mjml2html?: (mjml: string, options?: any) => any
31
- } = {}
32
- ) {}
33
-
34
- /**
35
- * Renders the React component to a static HTML string via MJML.
36
- *
37
- * @param data - Runtime data to be merged with initial props.
38
- * @returns A promise resolving to the rendered content.
39
- * @throws {Error} If MJML rendering fails.
40
- */
41
- async render(data: Record<string, unknown>): Promise<RenderResult> {
42
- let { createElement, renderToStaticMarkup, mjml2html } = this.deps
43
-
44
- if (!createElement || !renderToStaticMarkup) {
45
- try {
46
- const react = await import('react')
47
- const reactDomServer = await import('react-dom/server')
48
- createElement ??= react.createElement
49
- renderToStaticMarkup ??= reactDomServer.renderToStaticMarkup
50
- } catch (_e) {
51
- throw new Error(
52
- '[OrbitSignal] The "react" and "react-dom" packages are required for ReactMjmlRenderer. Please install them using "bun add react react-dom".'
53
- )
54
- }
55
- }
56
-
57
- if (!mjml2html) {
58
- try {
59
- mjml2html = (await import('mjml')).default
60
- } catch (_e) {
61
- throw new Error(
62
- '[OrbitSignal] The "mjml" package is required for ReactMjmlRenderer. Please install it using "bun add mjml".'
63
- )
64
- }
65
- }
66
-
67
- const mergedProps = { ...this.props, ...data } as P
68
- const element = createElement?.(this.component, mergedProps)
69
- const mjml = renderToStaticMarkup?.(element)
70
- if (!mjml) {
71
- throw new Error('Failed to render MJML template')
72
- }
73
-
74
- const result = mjml2html?.(mjml, {
75
- validationLevel: 'soft',
76
- ...this.options,
77
- })
78
- if (!result) {
79
- throw new Error('Failed to convert MJML to HTML')
80
- }
81
- const { html, errors } = result
82
-
83
- if (errors && errors.length > 0 && this.options.validationLevel === 'strict') {
84
- throw new Error(
85
- `MJML rendering failed: ${errors.map((e: any) => e.formattedMessage).join(', ')}`
86
- )
87
- }
88
-
89
- return {
90
- html,
91
- text: stripHtml(html),
92
- }
93
- }
94
- }
@@ -1,66 +0,0 @@
1
- import { stripHtml } from '../utils/html'
2
- import type { Renderer, RenderResult } from './Renderer'
3
-
4
- /**
5
- * Renderer for React component-based emails.
6
- *
7
- * Renders React components to static HTML using server-side rendering (SSR).
8
- * It lazily loads React and ReactDOM dependencies only when needed, preventing
9
- * unnecessary bundle bloat for users who do not use React renderers.
10
- *
11
- * @example
12
- * ```typescript
13
- * const renderer = new ReactRenderer(MyComponent, { title: 'Welcome' });
14
- * const result = await renderer.render({ name: 'John' });
15
- * ```
16
- *
17
- * @typeParam P - Props type for the React component.
18
- * @public
19
- * @since 3.0.0
20
- */
21
- export class ReactRenderer<P extends object = object> implements Renderer {
22
- /**
23
- * Creates an instance of ReactRenderer.
24
- *
25
- * @param component - The React component to render.
26
- * @param props - Initial props for the component.
27
- * @param deps - Optional dependency injection for testing.
28
- */
29
- constructor(
30
- private component: any, // Use any to avoid hard React dependency in types
31
- private props?: P,
32
- private deps: {
33
- createElement?: (...args: any[]) => any
34
- renderToStaticMarkup?: (element: any) => string
35
- } = {}
36
- ) {}
37
-
38
- /**
39
- * Renders the React component to a static HTML string.
40
- *
41
- * This method performs dynamic imports of `react` and `react-dom/server`
42
- * to ensure they are only loaded if this renderer is actually used.
43
- *
44
- * @param data - Runtime data to be merged with initial props.
45
- * @returns A promise resolving to the rendered content.
46
- * @throws {Error} If React dependencies cannot be loaded or rendering fails.
47
- */
48
- async render(data: Record<string, unknown>): Promise<RenderResult> {
49
- // Dynamic imports to avoid hard dependencies on react/react-dom
50
- const createElement = this.deps.createElement ?? (await import('react')).createElement
51
- const renderToStaticMarkup =
52
- this.deps.renderToStaticMarkup ?? (await import('react-dom/server')).renderToStaticMarkup
53
-
54
- const mergedProps = { ...this.props, ...data } as P
55
-
56
- const element = createElement(this.component, mergedProps)
57
- const html = renderToStaticMarkup(element)
58
-
59
- const fullHtml = html.startsWith('<!DOCTYPE') ? html : `<!DOCTYPE html>${html}`
60
-
61
- return {
62
- html: fullHtml,
63
- text: stripHtml(html),
64
- }
65
- }
66
- }
@@ -1,67 +0,0 @@
1
- /**
2
- * Result of a content rendering operation.
3
- *
4
- * This interface defines the structure of the output produced by any renderer.
5
- * It ensures consistency across different rendering strategies (HTML, React, Vue, etc.),
6
- * providing both the final HTML for the email body and an optional plain text version
7
- * for clients that do not support HTML.
8
- *
9
- * @example
10
- * ```typescript
11
- * const result: RenderResult = {
12
- * html: '<html><body><h1>Hello</h1></body></html>',
13
- * text: 'Hello'
14
- * };
15
- * ```
16
- *
17
- * @public
18
- * @since 3.0.0
19
- */
20
- export interface RenderResult {
21
- /**
22
- * The rendered HTML string.
23
- *
24
- * This is the primary content used for the email body.
25
- */
26
- html: string
27
- /**
28
- * Optional rendered plain text string.
29
- *
30
- * Used as a fallback for email clients that cannot display HTML or for accessibility.
31
- */
32
- text?: string
33
- }
34
-
35
- /**
36
- * Interface for email content renderers.
37
- *
38
- * Renderers are responsible for transforming various input formats (raw HTML,
39
- * templates, or UI components) into a standardized {@link RenderResult}.
40
- * This abstraction allows the mail system to support multiple view engines
41
- * and frameworks interchangeably.
42
- *
43
- * @example
44
- * ```typescript
45
- * class MyRenderer implements Renderer {
46
- * async render(data: Record<string, unknown>): Promise<RenderResult> {
47
- * return { html: `<div>${data.name}</div>`, text: String(data.name) };
48
- * }
49
- * }
50
- * ```
51
- *
52
- * @public
53
- * @since 3.0.0
54
- */
55
- export interface Renderer {
56
- /**
57
- * Render the content into HTML and optionally plain text.
58
- *
59
- * This method performs the actual transformation of the source content
60
- * using the provided data context.
61
- *
62
- * @param data - The data context for rendering.
63
- * @returns A promise resolving to the rendered content.
64
- * @throws {Error} If rendering fails due to syntax errors or missing dependencies.
65
- */
66
- render(data: Record<string, unknown>): Promise<RenderResult>
67
- }
@@ -1,84 +0,0 @@
1
- import { stripHtml } from '../utils/html'
2
- import type { Renderer, RenderResult } from './Renderer'
3
-
4
- /**
5
- * Renderer for template-based emails using Gravito Prism.
6
- *
7
- * Renders email templates from the filesystem using the Prism template engine.
8
- * It uses a static cache for the template engine to avoid redundant initialization
9
- * costs when rendering multiple emails from the same directory.
10
- *
11
- * @example
12
- * ```typescript
13
- * const renderer = new TemplateRenderer('welcome', './src/emails');
14
- * const result = await renderer.render({ name: 'John' });
15
- * ```
16
- *
17
- * @public
18
- * @since 3.0.0
19
- */
20
- export class TemplateRenderer implements Renderer {
21
- private template: string
22
- private viewsDir: string
23
- private static engineCache = new Map<string, any>()
24
-
25
- /**
26
- * Creates an instance of TemplateRenderer.
27
- *
28
- * @param templateName - The name of the template file (without extension).
29
- * @param viewsDir - The directory containing template files. Defaults to `src/emails`.
30
- */
31
- constructor(templateName: string, viewsDir?: string) {
32
- this.template = templateName
33
- // Default to src/emails if not provided, falling back to process cwd
34
- this.viewsDir = viewsDir || `${process.cwd()}/src/emails`
35
- }
36
-
37
- /**
38
- * Renders the template with the provided data.
39
- *
40
- * This method lazily loads `@gravito/prism` to ensure the core package
41
- * remains lightweight for users who don't need template rendering.
42
- *
43
- * @param data - The data context for template interpolation.
44
- * @returns A promise resolving to the rendered content.
45
- * @throws {Error} If the template engine fails to load or rendering fails.
46
- */
47
- async render(data: Record<string, unknown>): Promise<RenderResult> {
48
- // Dynamic import to avoid hard dependency on @gravito/prism
49
- const { TemplateEngine } = await import('@gravito/prism')
50
-
51
- const cached = TemplateRenderer.engineCache.get(this.viewsDir)
52
- const engine = cached || new TemplateEngine(this.viewsDir)
53
-
54
- if (!cached) {
55
- TemplateRenderer.engineCache.set(this.viewsDir, engine)
56
- }
57
-
58
- // Disable automatic layout by default for emails, unless explicitly handled in template
59
- const html = engine.render(this.template, data, {})
60
-
61
- return {
62
- html,
63
- text: stripHtml(html),
64
- }
65
- }
66
-
67
- /**
68
- * Clear template engine cache.
69
- *
70
- * Useful in development environments to force recompilation of templates
71
- * after they have been modified on disk.
72
- *
73
- * @example
74
- * ```typescript
75
- * TemplateRenderer.clearCache();
76
- * ```
77
- *
78
- * @public
79
- * @since 3.1.0
80
- */
81
- static clearCache(): void {
82
- TemplateRenderer.engineCache.clear()
83
- }
84
- }
@@ -1,99 +0,0 @@
1
- import { stripHtml } from '../utils/html'
2
- import type { Renderer, RenderResult } from './Renderer'
3
-
4
- /**
5
- * Renderer for Vue component-based MJML emails.
6
- *
7
- * Renders Vue 3 components to MJML string using SSR, then converts
8
- * the MJML to responsive HTML.
9
- *
10
- * @typeParam P - Props type for the Vue component.
11
- * @public
12
- * @since 1.1.0
13
- */
14
- export class VueMjmlRenderer<P extends object = object> implements Renderer {
15
- /**
16
- * Creates an instance of VueMjmlRenderer.
17
- *
18
- * @param component - The Vue component to render.
19
- * @param props - Initial props for the component.
20
- * @param options - Optional MJML transformation options.
21
- * @param deps - Optional dependency injection for testing.
22
- */
23
- constructor(
24
- private component: any,
25
- private props?: P,
26
- private options: Record<string, any> = {},
27
- private deps: {
28
- createSSRApp?: (...args: any[]) => any
29
- h?: (...args: any[]) => any
30
- renderToString?: (app: any) => Promise<string>
31
- mjml2html?: (mjml: string, options?: any) => any
32
- } = {}
33
- ) {}
34
-
35
- /**
36
- * Renders the Vue component to a static HTML string via MJML.
37
- *
38
- * @param data - Runtime data to be merged with initial props.
39
- * @returns A promise resolving to the rendered content.
40
- * @throws {Error} If MJML rendering fails.
41
- */
42
- async render(data: Record<string, unknown>): Promise<RenderResult> {
43
- let { createSSRApp, h, renderToString, mjml2html } = this.deps
44
-
45
- if (!createSSRApp || !h || !renderToString) {
46
- try {
47
- const vue = await import('vue')
48
- const vueServerRenderer = await import('@vue/server-renderer')
49
- createSSRApp ??= vue.createSSRApp
50
- h ??= vue.h
51
- renderToString ??= vueServerRenderer.renderToString
52
- } catch (_e) {
53
- throw new Error(
54
- '[OrbitSignal] The "vue" and "@vue/server-renderer" packages are required for VueMjmlRenderer. Please install them using "bun add vue @vue/server-renderer".'
55
- )
56
- }
57
- }
58
-
59
- if (!mjml2html) {
60
- try {
61
- mjml2html = (await import('mjml')).default
62
- } catch (_e) {
63
- throw new Error(
64
- '[OrbitSignal] The "mjml" package is required for VueMjmlRenderer. Please install it using "bun add mjml".'
65
- )
66
- }
67
- }
68
-
69
- const mergedProps = { ...this.props, ...data }
70
- const app = createSSRApp?.({
71
- render: () => h?.(this.component, mergedProps),
72
- })
73
-
74
- const mjml = await renderToString?.(app)
75
- if (!mjml) {
76
- throw new Error('Failed to render MJML template')
77
- }
78
-
79
- const result = mjml2html?.(mjml, {
80
- validationLevel: 'soft',
81
- ...this.options,
82
- })
83
- if (!result) {
84
- throw new Error('Failed to convert MJML to HTML')
85
- }
86
- const { html, errors } = result
87
-
88
- if (errors && errors.length > 0 && this.options.validationLevel === 'strict') {
89
- throw new Error(
90
- `MJML rendering failed: ${errors.map((e: any) => e.formattedMessage).join(', ')}`
91
- )
92
- }
93
-
94
- return {
95
- html,
96
- text: stripHtml(html),
97
- }
98
- }
99
- }
@@ -1,71 +0,0 @@
1
- import { stripHtml } from '../utils/html'
2
- import type { Renderer, RenderResult } from './Renderer'
3
-
4
- /**
5
- * Renderer for Vue component-based emails.
6
- *
7
- * Renders Vue 3 components to static HTML using server-side rendering (SSR).
8
- * It lazily loads Vue and `@vue/server-renderer` dependencies only when needed,
9
- * preventing unnecessary bundle bloat for users who do not use Vue renderers.
10
- *
11
- * @example
12
- * ```typescript
13
- * const renderer = new VueRenderer(MyComponent, { title: 'Welcome' });
14
- * const result = await renderer.render({ name: 'John' });
15
- * ```
16
- *
17
- * @typeParam P - Props type for the Vue component.
18
- * @public
19
- * @since 3.0.0
20
- */
21
- export class VueRenderer<P extends object = object> implements Renderer {
22
- /**
23
- * Creates an instance of VueRenderer.
24
- *
25
- * @param component - The Vue component to render.
26
- * @param props - Initial props for the component.
27
- * @param deps - Optional dependency injection for testing.
28
- */
29
- constructor(
30
- private component: any, // Use any to avoid hard Vue dependency in types
31
- private props?: P,
32
- private deps: {
33
- createSSRApp?: (...args: any[]) => any
34
- h?: (...args: any[]) => any
35
- renderToString?: (app: any) => Promise<string>
36
- } = {}
37
- ) {}
38
-
39
- /**
40
- * Renders the Vue component to a static HTML string.
41
- *
42
- * This method performs dynamic imports of `vue` and `@vue/server-renderer`
43
- * to ensure they are only loaded if this renderer is actually used.
44
- *
45
- * @param data - Runtime data to be merged with initial props.
46
- * @returns A promise resolving to the rendered content.
47
- * @throws {Error} If Vue dependencies cannot be loaded or rendering fails.
48
- */
49
- async render(data: Record<string, unknown>): Promise<RenderResult> {
50
- // Dynamic imports to avoid hard dependencies on vue/@vue/server-renderer
51
- const createSSRApp = this.deps.createSSRApp ?? (await import('vue')).createSSRApp
52
- const h = this.deps.h ?? (await import('vue')).h
53
- const renderToString =
54
- this.deps.renderToString ?? (await import('@vue/server-renderer')).renderToString
55
-
56
- const mergedProps = { ...this.props, ...data }
57
-
58
- const app = createSSRApp({
59
- render: () => h(this.component, mergedProps),
60
- })
61
-
62
- const html = await renderToString(app)
63
-
64
- const fullHtml = html.startsWith('<!DOCTYPE') ? html : `<!DOCTYPE html>${html}`
65
-
66
- return {
67
- html: fullHtml,
68
- text: stripHtml(html),
69
- }
70
- }
71
- }
@@ -1,50 +0,0 @@
1
- /**
2
- * Base layout for MJML emails.
3
- * Includes common head styles and responsive settings.
4
- *
5
- * Placeholder: {{content}}
6
- */
7
- export const baseLayout = `
8
- <mjml>
9
- <mj-head>
10
- <mj-attributes>
11
- <mj-all font-family="Arial, Helvetica, sans-serif" />
12
- <mj-text font-size="16px" color="#333333" line-height="1.5" />
13
- <mj-section padding="20px" />
14
- </mj-attributes>
15
- <mj-style>
16
- .link-white { color: #ffffff !important; text-decoration: none; }
17
- .footer-text { font-size: 12px; color: #999999; }
18
- </mj-style>
19
- </mj-head>
20
- <mj-body background-color="#f4f4f4">
21
- <mj-section background-color="#ffffff" padding-bottom="0px">
22
- <mj-column>
23
- <mj-image width="150px" src="https://gravito.dev/logo.png" alt="Gravito" />
24
- </mj-column>
25
- </mj-section>
26
-
27
- {{content}}
28
-
29
- <mj-section>
30
- <mj-column>
31
- <mj-divider border-width="1px" border-color="#dddddd" />
32
- <mj-text align="center" css-class="footer-text">
33
- &copy; ${new Date().getFullYear()} Gravito Framework. All rights reserved.
34
- </mj-text>
35
- </mj-column>
36
- </mj-section>
37
- </mj-body>
38
- </mjml>
39
- `
40
-
41
- /**
42
- * A simple transactional component layout.
43
- */
44
- export const transactionLayout = `
45
- <mj-section background-color="#ffffff" padding-top="0px">
46
- <mj-column>
47
- {{content}}
48
- </mj-column>
49
- </mj-section>
50
- `