@gravito/signal 1.0.0-alpha.3 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravito/signal",
3
- "version": "1.0.0-alpha.3",
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.2",
30
- "@gravito/stream": "1.0.0-alpha.2",
31
- "@gravito/prism": "^0.1.0",
32
- "react": "^18.0.0",
33
- "react-dom": "^18.0.0",
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,15 +48,15 @@
48
48
  }
49
49
  },
50
50
  "devDependencies": {
51
- "@gravito/stream": "1.0.0-alpha.2",
52
- "@gravito/prism": "^0.1.0",
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": "^18.2.0",
56
- "@types/react-dom": "^18.2.0",
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.2",
59
- "tsup": "^8.0.2",
58
+ "gravito-core": "1.0.0-beta.4",
59
+ "tsup": "8.5.1",
60
60
  "typescript": "^5.0.0",
61
61
  "vue": "^3.0.0"
62
62
  },
@@ -69,4 +69,4 @@
69
69
  "url": "git+https://github.com/gravito-framework/gravito.git",
70
70
  "directory": "packages/signal"
71
71
  }
72
- }
72
+ }
@@ -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)')
@@ -72,6 +80,10 @@ export class OrbitSignal implements GravitoOrbit {
72
80
 
73
81
  /**
74
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.
75
87
  */
76
88
  async send(mailable: Mailable): Promise<void> {
77
89
  // 1. Build envelope and get configuration
@@ -116,6 +128,9 @@ export class OrbitSignal implements GravitoOrbit {
116
128
  *
117
129
  * Push a mailable into the queue for execution.
118
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.
119
134
  */
120
135
  async queue(mailable: Mailable): Promise<void> {
121
136
  // Try to get queue service from context.
@@ -136,14 +151,3 @@ export class OrbitSignal implements GravitoOrbit {
136
151
  }
137
152
  }
138
153
  }
139
-
140
- // Module augmentation for GravitoVariables (new abstraction)
141
- declare module 'gravito-core' {
142
- interface GravitoVariables {
143
- /** Mail service for sending emails */
144
- mail?: {
145
- send: (mailable: Mailable) => Promise<void>
146
- queue: (mailable: Mailable) => Promise<void>
147
- }
148
- }
149
- }
@@ -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
+ }
@@ -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
- const entry = this.mailbox.get(id)
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
- return ctx.text(entry.text || 'No text content', 200, {
53
- 'Content-Type': 'text/plain; charset=utf-8',
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 success = this.mailbox.delete(ctx.req.param('id'))
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,3 +1,5 @@
1
+ import './augmentation'
2
+
1
3
  export type { Queueable } from '@gravito/stream'
2
4
  export { DevMailbox, type MailboxEntry } from './dev/DevMailbox'
3
5
  export { Mailable } from './Mailable'
@@ -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: ComponentType<P>,
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
- const defaultDir = viewsDir || `${process.cwd()}/src/emails`
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 = this.engine.render(this.template, data, {})
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: 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({