@travetto/email-compiler 3.1.21 → 3.1.22

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": "@travetto/email-compiler",
3
- "version": "3.1.21",
3
+ "version": "3.1.22",
4
4
  "description": "Email compiling module",
5
5
  "keywords": [
6
6
  "email",
package/src/compiler.ts CHANGED
@@ -128,6 +128,7 @@ export class EmailCompiler {
128
128
  try {
129
129
  if (EmailCompileUtil.isTemplateFile(file)) {
130
130
  await this.compile(file, true);
131
+ console.log(`Successfully compiled ${1} templates`, { changed: [file] });
131
132
  yield file;
132
133
  } else if (VALID_FILE(file)) {
133
134
  const rootFile = file.replace(/\/resources.*/, '/package.json');
@@ -1,6 +1,6 @@
1
1
  import fs from 'fs/promises';
2
2
 
3
- import { path } from '@travetto/manifest';
3
+ import { RootIndex, path } from '@travetto/manifest';
4
4
  import { YamlUtil } from '@travetto/yaml';
5
5
 
6
6
  interface ConfigType {
@@ -22,7 +22,7 @@ interface ConfigType {
22
22
  */
23
23
  export class $EditorConfig {
24
24
 
25
- #configFile = path.resolve('resources/email/dev.yml');
25
+ #configFile: Record<string, string> = {};
26
26
  #defaultConfig = {
27
27
  to: 'my-email@gmail.com',
28
28
  from: 'from-email@gmail.com',
@@ -42,9 +42,10 @@ export class $EditorConfig {
42
42
  /**
43
43
  *
44
44
  */
45
- async get(): Promise<ConfigType> {
45
+ async get(file: string): Promise<ConfigType> {
46
46
  try {
47
- const content = await fs.readFile(this.#configFile, 'utf8');
47
+ const mod = RootIndex.getModuleFromSource(file)!.name;
48
+ const content = await fs.readFile(this.#configFile[mod], 'utf8');
48
49
  return YamlUtil.parse<ConfigType>(content);
49
50
  } catch {
50
51
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
@@ -52,13 +53,13 @@ export class $EditorConfig {
52
53
  }
53
54
  }
54
55
 
55
- async getContext(): Promise<Exclude<ConfigType['context'], undefined>> {
56
- const conf = await this.get();
56
+ async getContext(file: string): Promise<Exclude<ConfigType['context'], undefined>> {
57
+ const conf = await this.get(file);
57
58
  return conf.context ?? {};
58
59
  }
59
60
 
60
- async getSenderConfig(): Promise<Exclude<ConfigType['sender'], undefined>> {
61
- const conf = await this.get();
61
+ async getSenderConfig(file: string): Promise<Exclude<ConfigType['sender'], undefined>> {
62
+ const conf = await this.get(file);
62
63
  return conf.sender ?? {};
63
64
  }
64
65
 
@@ -66,13 +67,15 @@ export class $EditorConfig {
66
67
  return YamlUtil.serialize(this.#defaultConfig);
67
68
  }
68
69
 
69
- async ensureConfig(): Promise<string> {
70
- const file = this.#configFile;
71
- if (!(await fs.stat(file).catch(() => { }))) {
72
- await fs.mkdir(path.dirname(file), { recursive: true });
73
- await fs.writeFile(file, this.getDefaultConfig(), { encoding: 'utf8' });
70
+ async ensureConfig(file: string): Promise<string> {
71
+ console.log('Ensuring config', file);
72
+ const mod = RootIndex.getModuleFromSource(file)!;
73
+ const resolved = this.#configFile[mod.name] ??= path.resolve(mod.sourcePath, 'resources/email/dev.yml');
74
+ if (!(await fs.stat(resolved).catch(() => { }))) {
75
+ await fs.mkdir(path.dirname(resolved), { recursive: true });
76
+ await fs.writeFile(resolved, this.getDefaultConfig(), { encoding: 'utf8' });
74
77
  }
75
- return file;
78
+ return resolved;
76
79
  }
77
80
  }
78
81
 
@@ -1,3 +1,5 @@
1
+ import { ShutdownManager } from '@travetto/base';
2
+
1
3
  import { EmailCompilationManager } from './manager';
2
4
  import { EditorSendService } from './send';
3
5
  import { EditorConfig } from './config';
@@ -6,7 +8,7 @@ import { EmailCompiler } from '../../src/compiler';
6
8
  import { EmailCompileUtil } from '../../src/util';
7
9
 
8
10
  type InboundMessage =
9
- { type: 'configure' } |
11
+ { type: 'configure', file: string } |
10
12
  { type: 'redraw', file: string } |
11
13
  { type: 'send', file: string, from?: string, to?: string };
12
14
 
@@ -23,12 +25,10 @@ type OutboundMessage =
23
25
  export class EditorState {
24
26
 
25
27
  #lastFile = '';
26
- #sender: EditorSendService;
27
28
  #template: EmailCompilationManager;
28
29
 
29
30
  constructor(template: EmailCompilationManager) {
30
31
  this.#template = template;
31
- this.#sender = new EditorSendService();
32
32
  }
33
33
 
34
34
  async renderFile(file: string): Promise<void> {
@@ -36,7 +36,7 @@ export class EditorState {
36
36
  if (file) {
37
37
  try {
38
38
  const content = await this.#template.resolveCompiledTemplate(
39
- file, await EditorConfig.getContext()
39
+ file, await EditorConfig.getContext(file)
40
40
  );
41
41
  this.response({
42
42
  type: 'changed',
@@ -60,7 +60,7 @@ export class EditorState {
60
60
  }
61
61
 
62
62
  async onConfigure(msg: InboundMessage & { type: 'configure' }): Promise<void> {
63
- this.response({ type: 'configured', file: await EditorConfig.ensureConfig() });
63
+ this.response({ type: 'configured', file: await EditorConfig.ensureConfig(msg.file) });
64
64
  }
65
65
 
66
66
  async #onRedraw(msg: InboundMessage & { type: 'redraw' }): Promise<void> {
@@ -77,15 +77,15 @@ export class EditorState {
77
77
  }
78
78
 
79
79
  async onSend(msg: InboundMessage & { type: 'send' }): Promise<void> {
80
- const cfg = await EditorConfig.get();
80
+ const cfg = await EditorConfig.get(msg.file);
81
81
  const to = msg.to || cfg.to;
82
82
  const from = msg.from || cfg.from;
83
83
  const content = await this.#template.resolveCompiledTemplate(
84
- msg.file!, await EditorConfig.getContext()
84
+ msg.file, await EditorConfig.getContext(msg.file)
85
85
  );
86
86
 
87
87
  try {
88
- const url = await this.#sender.sendEmail({ from, to, ...content, });
88
+ const url = await EditorSendService.sendEmail(msg.file, { from, to, ...content, });
89
89
  this.response({ type: 'sent', to, file: msg.file, ...url });
90
90
  } catch (err) {
91
91
  if (err && err instanceof Error) {
@@ -107,6 +107,10 @@ export class EditorState {
107
107
  case 'send': this.onSend(msg); break;
108
108
  }
109
109
  });
110
+
111
+ process.on('disconnect', () => ShutdownManager.execute());
112
+ process.send?.('ready');
113
+
110
114
  for await (const f of EmailCompiler.watchCompile()) {
111
115
  await this.renderFile(f);
112
116
  }
@@ -3,20 +3,23 @@ import { MailTransportTarget } from '@travetto/email/src/internal/types';
3
3
  import { DependencyRegistry } from '@travetto/di';
4
4
 
5
5
  import { EditorConfig } from './config';
6
+ import { RootIndex } from '@travetto/manifest';
6
7
 
7
8
  /**
8
9
  * Util for sending emails
9
10
  */
10
11
  export class EditorSendService {
11
12
 
12
- #svc: MailService;
13
+ static #svc: Record<string, MailService> = {};
13
14
 
14
15
  /**
15
16
  * Get mail service
16
17
  */
17
- async getMailService(): Promise<MailService> {
18
- if (!this.#svc) {
19
- const senderConfig = await EditorConfig.getSenderConfig();
18
+ static async getMailService(file: string): Promise<MailService> {
19
+ const mod = RootIndex.getModuleFromSource(file)!.name;
20
+
21
+ if (!this.#svc[mod]) {
22
+ const senderConfig = await EditorConfig.getSenderConfig(file);
20
23
 
21
24
  if (senderConfig?.host?.includes('ethereal.email')) {
22
25
  const cls = class { };
@@ -39,22 +42,22 @@ ${EditorConfig.getDefaultConfig()}`.trim();
39
42
  throw new Error(errorMessage);
40
43
  }
41
44
 
42
- this.#svc = await DependencyRegistry.getInstance(MailService);
45
+ this.#svc[mod] = await DependencyRegistry.getInstance(MailService);
43
46
  }
44
- return this.#svc;
47
+ return this.#svc[mod];
45
48
  }
46
49
 
47
50
  /**
48
51
  * Resolve template
49
52
  */
50
- async sendEmail(message: MessageOptions): Promise<{
53
+ static async sendEmail(file: string, message: MessageOptions): Promise<{
51
54
  url?: string | false;
52
55
  }> {
53
56
  const to = message.to!;
54
57
  try {
55
58
  console.log('Sending email', { to });
56
59
  // Let the engine template
57
- const svc = await this.getMailService();
60
+ const svc = await this.getMailService(file);
58
61
  if (!svc) {
59
62
  throw new Error('Node mailer support is missing');
60
63
  }
@@ -62,7 +65,7 @@ ${EditorConfig.getDefaultConfig()}`.trim();
62
65
  const info = await svc.send<{ host?: string } & SentMessage>(message);
63
66
  console.log('Sent email', { to });
64
67
 
65
- const senderConfig = await EditorConfig.getSenderConfig();
68
+ const senderConfig = await EditorConfig.getSenderConfig(file);
66
69
  return senderConfig.host?.includes('ethereal.email') ? {
67
70
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any
68
71
  url: (await import('nodemailer')).getTestMessageUrl(info as any)
@@ -1,6 +1,5 @@
1
- import { GlobalEnvConfig, ShutdownManager } from '@travetto/base';
1
+ import { GlobalEnvConfig } from '@travetto/base';
2
2
  import { CliCommand } from '@travetto/cli';
3
- import { RootIndex } from '@travetto/manifest';
4
3
  import { RootRegistry } from '@travetto/registry';
5
4
 
6
5
  import { EditorState } from './bin/editor';
@@ -11,19 +10,11 @@ import { EmailCompilationManager } from './bin/manager';
11
10
  export class EmailEditorCommand {
12
11
 
13
12
  envInit(): GlobalEnvConfig {
14
- return {
15
- envName: 'dev',
16
- resourcePaths: [`${RootIndex.getModule('@travetto/email-compiler')!.sourcePath}/resources`]
17
- };
13
+ return { envName: 'dev', dynamic: true };
18
14
  }
19
15
 
20
16
  async main(): Promise<void> {
21
17
  await RootRegistry.init();
22
- const editor = new EditorState(await EmailCompilationManager.createInstance());
23
- await editor.init();
24
- if (process.send) {
25
- process.on('disconnect', () => ShutdownManager.execute());
26
- process.send('ready');
27
- }
18
+ await new EditorState(await EmailCompilationManager.createInstance()).init();
28
19
  }
29
20
  }
@@ -25,10 +25,9 @@ export class EmailTestCommand implements CliCommandShape {
25
25
  await EmailCompiler.compile(file, true);
26
26
 
27
27
  const mgr = await EmailCompilationManager.createInstance();
28
- const send = new EditorSendService();
29
- const cfg = await EditorConfig.get();
28
+ const cfg = await EditorConfig.get(file);
29
+ const content = await mgr.resolveCompiledTemplate(file, await EditorConfig.getContext(file));
30
30
 
31
- const content = await mgr.resolveCompiledTemplate(file!, await EditorConfig.getContext());
32
- await send.sendEmail({ from: cfg.from, to, ...content, });
31
+ await EditorSendService.sendEmail(file, { from: cfg.from, to, ...content, });
33
32
  }
34
33
  }