@gravito/signal 1.0.0-alpha.2 → 1.0.0-alpha.5
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/README.zh-TW.md +27 -0
- package/dist/OrbitSignal-IPSA2CDO.mjs +7 -0
- package/dist/OrbitSignal-MABW4DDW.mjs +7 -0
- package/dist/OrbitSignal-QSW5VQ5M.mjs +7 -0
- package/dist/OrbitSignal-R22QHWAA.mjs +7 -0
- package/dist/ReactRenderer-24SQ4KRU.mjs +27 -0
- package/dist/VueRenderer-SUP66ISX.mjs +29 -0
- package/dist/chunk-456QRYFW.mjs +401 -0
- package/dist/chunk-EBO3CZXG.mjs +15 -0
- package/dist/chunk-F6MVTUCT.mjs +421 -0
- package/dist/chunk-NEQCQSZI.mjs +406 -0
- package/dist/chunk-YLVDJSED.mjs +431 -0
- package/dist/index.d.mts +26 -18
- package/dist/index.d.ts +26 -18
- package/dist/index.js +59 -28
- package/dist/index.mjs +10 -10
- package/dist/server-renderer-4W4FI7YG.mjs +37269 -0
- package/package.json +12 -13
- package/src/OrbitSignal.ts +16 -21
- package/src/augmentation.ts +13 -0
- package/src/dev/DevServer.ts +26 -10
- package/src/index.ts +2 -0
- package/src/renderers/ReactRenderer.ts +5 -4
- package/src/renderers/TemplateRenderer.ts +7 -5
- package/src/renderers/VueRenderer.ts +5 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gravito/signal",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.5",
|
|
4
4
|
"description": "Powerful email framework for Gravito applications with Dev UI and multi-renderer support.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -26,11 +26,11 @@
|
|
|
26
26
|
"nodemailer": "^6.9.1"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
29
|
-
"gravito-core": "1.0.0-beta.
|
|
30
|
-
"@gravito/stream": "1.0.0-alpha.
|
|
31
|
-
"@gravito/prism": "1.0.0-beta.
|
|
32
|
-
"react": "^
|
|
33
|
-
"react-dom": "^
|
|
29
|
+
"gravito-core": "1.0.0-beta.4",
|
|
30
|
+
"@gravito/stream": "1.0.0-alpha.5",
|
|
31
|
+
"@gravito/prism": "1.0.0-beta.4",
|
|
32
|
+
"react": "^19.0.0",
|
|
33
|
+
"react-dom": "^19.0.0",
|
|
34
34
|
"vue": "^3.0.0"
|
|
35
35
|
},
|
|
36
36
|
"peerDependenciesMeta": {
|
|
@@ -48,16 +48,15 @@
|
|
|
48
48
|
}
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@gravito/
|
|
52
|
-
"@gravito/
|
|
51
|
+
"@gravito/prism": "1.0.0-beta.4",
|
|
52
|
+
"@gravito/stream": "1.0.0-alpha.5",
|
|
53
53
|
"@types/mjml": "^4.7.4",
|
|
54
54
|
"@types/nodemailer": "^6.4.14",
|
|
55
|
-
"@types/react": "^
|
|
56
|
-
"@types/react-dom": "^
|
|
55
|
+
"@types/react": "^19.0.0",
|
|
56
|
+
"@types/react-dom": "^19.0.0",
|
|
57
57
|
"@vue/server-renderer": "^3.0.0",
|
|
58
|
-
"gravito-core": "1.0.0-beta.
|
|
59
|
-
"
|
|
60
|
-
"tsup": "^8.0.2",
|
|
58
|
+
"gravito-core": "1.0.0-beta.4",
|
|
59
|
+
"tsup": "8.5.1",
|
|
61
60
|
"typescript": "^5.0.0",
|
|
62
61
|
"vue": "^3.0.0"
|
|
63
62
|
},
|
package/src/OrbitSignal.ts
CHANGED
|
@@ -18,6 +18,9 @@ export class OrbitSignal implements GravitoOrbit {
|
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* Get the singleton instance of OrbitSignal
|
|
21
|
+
*
|
|
22
|
+
* @returns The singleton instance of OrbitSignal.
|
|
23
|
+
* @throws {Error} If OrbitSignal has not been initialized.
|
|
21
24
|
*/
|
|
22
25
|
static getInstance(): OrbitSignal {
|
|
23
26
|
if (!OrbitSignal.instance) {
|
|
@@ -28,6 +31,9 @@ export class OrbitSignal implements GravitoOrbit {
|
|
|
28
31
|
|
|
29
32
|
/**
|
|
30
33
|
* Configure the OrbitSignal instance
|
|
34
|
+
*
|
|
35
|
+
* @param config - The mail configuration object.
|
|
36
|
+
* @returns A new instance of OrbitSignal.
|
|
31
37
|
*/
|
|
32
38
|
static configure(config: MailConfig): OrbitSignal {
|
|
33
39
|
// Basic validation
|
|
@@ -40,6 +46,8 @@ export class OrbitSignal implements GravitoOrbit {
|
|
|
40
46
|
|
|
41
47
|
/**
|
|
42
48
|
* Install the orbit into PlanetCore
|
|
49
|
+
*
|
|
50
|
+
* @param core - The PlanetCore instance.
|
|
43
51
|
*/
|
|
44
52
|
install(core: PlanetCore): void {
|
|
45
53
|
core.logger.info('[OrbitSignal] Initializing Mail Service (Exposed as: mail)')
|
|
@@ -66,11 +74,16 @@ export class OrbitSignal implements GravitoOrbit {
|
|
|
66
74
|
queue: (mailable: Mailable) => this.queue(mailable),
|
|
67
75
|
})
|
|
68
76
|
await next()
|
|
77
|
+
return undefined
|
|
69
78
|
})
|
|
70
79
|
}
|
|
71
80
|
|
|
72
81
|
/**
|
|
73
82
|
* Send a mailable instance
|
|
83
|
+
*
|
|
84
|
+
* @param mailable - The mailable object to send.
|
|
85
|
+
* @returns A promise that resolves when the email is sent.
|
|
86
|
+
* @throws {Error} If the message is missing "from" or "to" addresses, or if no transport is configured.
|
|
74
87
|
*/
|
|
75
88
|
async send(mailable: Mailable): Promise<void> {
|
|
76
89
|
// 1. Build envelope and get configuration
|
|
@@ -115,6 +128,9 @@ export class OrbitSignal implements GravitoOrbit {
|
|
|
115
128
|
*
|
|
116
129
|
* Push a mailable into the queue for execution.
|
|
117
130
|
* Requires OrbitStream to be installed and available in the context.
|
|
131
|
+
*
|
|
132
|
+
* @param mailable - The mailable object to queue.
|
|
133
|
+
* @returns A promise that resolves when the job is pushed to the queue or sent immediately if no queue service is found.
|
|
118
134
|
*/
|
|
119
135
|
async queue(mailable: Mailable): Promise<void> {
|
|
120
136
|
// Try to get queue service from context.
|
|
@@ -135,24 +151,3 @@ export class OrbitSignal implements GravitoOrbit {
|
|
|
135
151
|
}
|
|
136
152
|
}
|
|
137
153
|
}
|
|
138
|
-
|
|
139
|
-
// Module augmentation for Hono (backward compatibility)
|
|
140
|
-
declare module 'hono' {
|
|
141
|
-
interface ContextVariableMap {
|
|
142
|
-
mail: {
|
|
143
|
-
send: (mailable: Mailable) => Promise<void>
|
|
144
|
-
queue: (mailable: Mailable) => Promise<void>
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Module augmentation for GravitoVariables (new abstraction)
|
|
150
|
-
declare module 'gravito-core' {
|
|
151
|
-
interface GravitoVariables {
|
|
152
|
-
/** Mail service for sending emails */
|
|
153
|
-
mail?: {
|
|
154
|
-
send: (mailable: Mailable) => Promise<void>
|
|
155
|
-
queue: (mailable: Mailable) => Promise<void>
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export {}
|
|
2
|
+
|
|
3
|
+
// Module augmentation for GravitoVariables (new abstraction)
|
|
4
|
+
declare module 'gravito-core' {
|
|
5
|
+
interface GravitoVariables {
|
|
6
|
+
/** Mail service for sending emails */
|
|
7
|
+
mail?: {
|
|
8
|
+
// Use any for params to break circularity in dts generation if any
|
|
9
|
+
send: (mailable: any) => Promise<void>
|
|
10
|
+
queue: (mailable: any) => Promise<void>
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
package/src/dev/DevServer.ts
CHANGED
|
@@ -24,8 +24,11 @@ export class DevServer {
|
|
|
24
24
|
// 2. Single Email Preview
|
|
25
25
|
router.get(`${prefix}/:id`, (ctx) => {
|
|
26
26
|
const id = ctx.req.param('id')
|
|
27
|
-
|
|
27
|
+
if (!id) {
|
|
28
|
+
return ctx.text('Bad Request', 400)
|
|
29
|
+
}
|
|
28
30
|
|
|
31
|
+
const entry = this.mailbox.get(id)
|
|
29
32
|
if (!entry) {
|
|
30
33
|
return ctx.text('Email not found', 404)
|
|
31
34
|
}
|
|
@@ -35,6 +38,10 @@ export class DevServer {
|
|
|
35
38
|
// 3. Iframe Content: HTML
|
|
36
39
|
router.get(`${prefix}/:id/html`, (ctx) => {
|
|
37
40
|
const id = ctx.req.param('id')
|
|
41
|
+
if (!id) {
|
|
42
|
+
return ctx.text('Bad Request', 400)
|
|
43
|
+
}
|
|
44
|
+
|
|
38
45
|
const entry = this.mailbox.get(id)
|
|
39
46
|
if (!entry) {
|
|
40
47
|
return ctx.text('Not found', 404)
|
|
@@ -45,18 +52,26 @@ export class DevServer {
|
|
|
45
52
|
// 4. Iframe Content: Text
|
|
46
53
|
router.get(`${prefix}/:id/text`, (ctx) => {
|
|
47
54
|
const id = ctx.req.param('id')
|
|
55
|
+
if (!id) {
|
|
56
|
+
return ctx.text('Bad Request', 400)
|
|
57
|
+
}
|
|
58
|
+
|
|
48
59
|
const entry = this.mailbox.get(id)
|
|
49
60
|
if (!entry) {
|
|
50
61
|
return ctx.text('Not found', 404)
|
|
51
62
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
63
|
+
|
|
64
|
+
ctx.header('Content-Type', 'text/plain; charset=utf-8')
|
|
65
|
+
return ctx.text(entry.text || 'No text content', 200)
|
|
55
66
|
})
|
|
56
67
|
|
|
57
68
|
// 5. Raw JSON
|
|
58
69
|
router.get(`${prefix}/:id/raw`, (ctx) => {
|
|
59
70
|
const id = ctx.req.param('id')
|
|
71
|
+
if (!id) {
|
|
72
|
+
return ctx.json({ error: 'Bad Request' }, 400)
|
|
73
|
+
}
|
|
74
|
+
|
|
60
75
|
const entry = this.mailbox.get(id)
|
|
61
76
|
if (!entry) {
|
|
62
77
|
return ctx.json({ error: 'Not found' }, 404)
|
|
@@ -66,12 +81,16 @@ export class DevServer {
|
|
|
66
81
|
|
|
67
82
|
// 6. API: Delete Single
|
|
68
83
|
router.get(`${prefix}/:id/delete`, (ctx) => {
|
|
69
|
-
// Using GET for simple links/redirects without JS fetch if needed, but better use fetch from UI
|
|
70
|
-
// Actually let's accept POST or DELETE
|
|
71
84
|
return ctx.text('Method not allowed', 405)
|
|
72
85
|
})
|
|
86
|
+
|
|
73
87
|
router.delete(`${prefix}/:id`, (ctx) => {
|
|
74
|
-
const
|
|
88
|
+
const id = ctx.req.param('id')
|
|
89
|
+
if (!id) {
|
|
90
|
+
return ctx.json({ success: false, error: 'Bad Request' }, 400)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const success = this.mailbox.delete(id)
|
|
75
94
|
return ctx.json({ success })
|
|
76
95
|
})
|
|
77
96
|
|
|
@@ -81,9 +100,6 @@ export class DevServer {
|
|
|
81
100
|
return ctx.json({ success: true })
|
|
82
101
|
})
|
|
83
102
|
|
|
84
|
-
// Redirect /__mail/ to /__mail
|
|
85
|
-
// core.router.get(prefix + '/', (c) => c.redirect(prefix));
|
|
86
|
-
|
|
87
103
|
core.logger.info(`[OrbitSignal] Dev Mailbox available at ${prefix}`)
|
|
88
104
|
}
|
|
89
105
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import { type ComponentType, createElement } from 'react'
|
|
2
|
-
import { renderToStaticMarkup } from 'react-dom/server'
|
|
3
1
|
import type { Renderer, RenderResult } from './Renderer'
|
|
4
2
|
|
|
5
3
|
export class ReactRenderer<P extends object = object> implements Renderer {
|
|
6
4
|
constructor(
|
|
7
|
-
private component:
|
|
5
|
+
private component: any, // Use any to avoid hard React dependency in types
|
|
8
6
|
private props?: P
|
|
9
7
|
) {}
|
|
10
8
|
|
|
11
9
|
async render(data: Record<string, unknown>): Promise<RenderResult> {
|
|
10
|
+
// Dynamic imports to avoid hard dependencies on react/react-dom
|
|
11
|
+
const { createElement } = await import('react')
|
|
12
|
+
const { renderToStaticMarkup } = await import('react-dom/server')
|
|
13
|
+
|
|
12
14
|
const mergedProps = { ...this.props, ...data } as P
|
|
13
15
|
|
|
14
|
-
// We assume the component is a standard React component
|
|
15
16
|
const element = createElement(this.component, mergedProps)
|
|
16
17
|
const html = renderToStaticMarkup(element)
|
|
17
18
|
|
|
@@ -1,20 +1,22 @@
|
|
|
1
|
-
import { TemplateEngine } from '@gravito/prism'
|
|
2
1
|
import type { Renderer, RenderResult } from './Renderer'
|
|
3
2
|
|
|
4
3
|
export class TemplateRenderer implements Renderer {
|
|
5
|
-
private engine: TemplateEngine
|
|
6
4
|
private template: string
|
|
5
|
+
private viewsDir: string
|
|
7
6
|
|
|
8
7
|
constructor(templateName: string, viewsDir?: string) {
|
|
9
8
|
this.template = templateName
|
|
10
9
|
// Default to src/emails if not provided, falling back to process cwd
|
|
11
|
-
|
|
12
|
-
this.engine = new TemplateEngine(defaultDir)
|
|
10
|
+
this.viewsDir = viewsDir || `${process.cwd()}/src/emails`
|
|
13
11
|
}
|
|
14
12
|
|
|
15
13
|
async render(data: Record<string, unknown>): Promise<RenderResult> {
|
|
14
|
+
// Dynamic import to avoid hard dependency on @gravito/prism
|
|
15
|
+
const { TemplateEngine } = await import('@gravito/prism')
|
|
16
|
+
const engine = new TemplateEngine(this.viewsDir)
|
|
17
|
+
|
|
16
18
|
// Disable automatic layout by default for emails, unless explicitly handled in template
|
|
17
|
-
const html =
|
|
19
|
+
const html = engine.render(this.template, data, {})
|
|
18
20
|
|
|
19
21
|
return {
|
|
20
22
|
html,
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import { renderToString } from '@vue/server-renderer'
|
|
2
|
-
import { type Component, createSSRApp, h } from 'vue'
|
|
3
1
|
import type { Renderer, RenderResult } from './Renderer'
|
|
4
2
|
|
|
5
3
|
export class VueRenderer<P extends object = object> implements Renderer {
|
|
6
4
|
constructor(
|
|
7
|
-
private component:
|
|
5
|
+
private component: any, // Use any to avoid hard Vue dependency in types
|
|
8
6
|
private props?: P
|
|
9
7
|
) {}
|
|
10
8
|
|
|
11
9
|
async render(data: Record<string, unknown>): Promise<RenderResult> {
|
|
10
|
+
// Dynamic imports to avoid hard dependencies on vue/@vue/server-renderer
|
|
11
|
+
const { createSSRApp, h } = await import('vue')
|
|
12
|
+
const { renderToString } = await import('@vue/server-renderer')
|
|
13
|
+
|
|
12
14
|
const mergedProps = { ...this.props, ...data }
|
|
13
15
|
|
|
14
16
|
const app = createSSRApp({
|