@travetto/email-compiler 3.4.5 → 4.0.0-rc.0

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.4.5",
3
+ "version": "4.0.0-rc.0",
4
4
  "description": "Email compiling module",
5
5
  "keywords": [
6
6
  "email",
@@ -26,12 +26,12 @@
26
26
  "directory": "module/email-compiler"
27
27
  },
28
28
  "dependencies": {
29
- "@travetto/base": "^3.4.2",
30
- "@travetto/config": "^3.4.4",
31
- "@travetto/di": "^3.4.2",
32
- "@travetto/email": "^3.4.4",
33
- "@travetto/image": "^3.4.3",
34
- "@travetto/worker": "^3.4.2",
29
+ "@travetto/base": "^4.0.0-rc.0",
30
+ "@travetto/config": "^4.0.0-rc.0",
31
+ "@travetto/di": "^4.0.0-rc.0",
32
+ "@travetto/email": "^4.0.0-rc.0",
33
+ "@travetto/image": "^4.0.0-rc.0",
34
+ "@travetto/worker": "^4.0.0-rc.0",
35
35
  "@types/inline-css": "^3.0.3",
36
36
  "html-entities": "^2.4.0",
37
37
  "inline-css": "^4.0.2",
@@ -39,7 +39,7 @@
39
39
  "sass": "^1.69.5"
40
40
  },
41
41
  "peerDependencies": {
42
- "@travetto/cli": "^3.4.7"
42
+ "@travetto/cli": "^4.0.0-rc.0"
43
43
  },
44
44
  "peerDependenciesMeta": {
45
45
  "@travetto/cli": {
package/src/compiler.ts CHANGED
@@ -1,16 +1,14 @@
1
- import fs from 'fs/promises';
1
+ import fs from 'node:fs/promises';
2
2
 
3
- import { CompilerClient, TypedObject } from '@travetto/base';
3
+ import { FileLoader, TypedObject, WatchEvent, watchCompiler } from '@travetto/base';
4
4
  import { EmailCompileSource, EmailCompiled, EmailCompileContext, MailUtil } from '@travetto/email';
5
- import { RootIndex, path } from '@travetto/manifest';
6
- import { ManualAsyncIterator as Queue } from '@travetto/worker';
5
+ import { RuntimeIndex, path } from '@travetto/manifest';
6
+ import { WorkQueue } from '@travetto/worker';
7
7
 
8
8
  import { EmailCompileUtil } from './util';
9
9
 
10
10
  const VALID_FILE = (file: string): boolean => /[.](scss|css|png|jpe?g|gif|ya?ml)$/.test(file) && !/[.]compiled[.]/.test(file);
11
11
 
12
- type WatchEvent = { action: 'create' | 'update' | 'delete', file: string, folder: string };
13
-
14
12
  /**
15
13
  * Email compilation support
16
14
  */
@@ -20,20 +18,23 @@ export class EmailCompiler {
20
18
  * Watch folders as needed
21
19
  */
22
20
  static async #watchFolders(folders: string[], handler: (ev: WatchEvent) => void, signal: AbortSignal): Promise<void> {
23
- const lib = await import('@parcel/watcher');
24
21
  for (const src of folders) {
25
- const cleanup = await lib.subscribe(src, async (err, events) => {
26
- for (const ev of events) {
27
- handler({ action: ev.type, file: path.toPosix(ev.path), folder: src });
22
+ (async (): Promise<void> => {
23
+ for await (const ev of fs.watch(src, {
24
+ recursive: true,
25
+ signal,
26
+ persistent: false
27
+ })) {
28
+ const exists = ev.filename ? await fs.stat(ev.filename).catch(() => false) : false;
29
+ handler({ action: !!exists ? 'create' : 'delete', file: path.toPosix(ev.filename!), folder: src });
28
30
  }
29
- });
30
- signal.addEventListener('abort', () => cleanup.unsubscribe());
31
+ })();
31
32
  }
32
33
  }
33
34
 
34
35
  /** Load Template */
35
36
  static async loadTemplate(file: string): Promise<EmailCompileContext> {
36
- const entry = RootIndex.getEntry(file);
37
+ const entry = RuntimeIndex.getEntry(file);
37
38
  if (!entry) {
38
39
  throw new Error(`Unable to find template for ${file}`);
39
40
  }
@@ -53,7 +54,7 @@ export class EmailCompiler {
53
54
  * Grab list of all available templates
54
55
  */
55
56
  static findAllTemplates(mod?: string): string[] {
56
- return RootIndex
57
+ return RuntimeIndex
57
58
  .find({
58
59
  module: m => !mod ? m.roles.includes('std') : mod === m.name,
59
60
  folder: f => f === 'support',
@@ -66,8 +67,8 @@ export class EmailCompiler {
66
67
  * Get output files
67
68
  */
68
69
  static getOutputFiles(file: string): EmailCompiled {
69
- const entry = RootIndex.getEntry(file)!;
70
- const mod = RootIndex.getModule(entry.module)!;
70
+ const entry = RuntimeIndex.getEntry(file)!;
71
+ const mod = RuntimeIndex.getModule(entry.module)!;
71
72
  return EmailCompileUtil.getOutputs(file, path.join(mod.sourcePath, 'resources'));
72
73
  }
73
74
 
@@ -118,29 +119,23 @@ export class EmailCompiler {
118
119
  * Watch compilation
119
120
  */
120
121
  static async * watchCompile(): AsyncIterable<string> {
121
- const all = this.findAllTemplates()
122
- .map(x => RootIndex.resolveModulePath(`${RootIndex.getEntry(x)!.module}#resources`))
123
- .reduce<{ set: Set<string>, arr: string[] }>((a, v) => {
124
- if (!a.set.has(v)) {
125
- a.set.add(v);
126
- a.arr.push(v);
127
- }
128
- return a;
129
- }, { set: new Set(), arr: [] }).arr;
122
+ const all = FileLoader.resolvePaths(
123
+ this.findAllTemplates().map(x => `${RuntimeIndex.getEntry(x)!.module}#resources`)
124
+ );
130
125
 
131
126
  const ctrl = new AbortController();
132
- const stream = new Queue<WatchEvent>([], ctrl.signal);
127
+ const stream = new WorkQueue<WatchEvent>([], ctrl.signal);
133
128
 
134
129
  // watch resources
135
130
  this.#watchFolders(all, ev => stream.add(ev), ctrl.signal);
136
131
 
137
132
  // Watch template files
138
- new CompilerClient().onFileChange(ev => {
139
- const src = RootIndex.getEntry(ev.file);
133
+ watchCompiler(ev => {
134
+ const src = RuntimeIndex.getEntry(ev.file);
140
135
  if (src && EmailCompileUtil.isTemplateFile(src.sourceFile)) {
141
136
  setTimeout(() => stream.add({ ...ev, file: src.sourceFile }), 100); // Wait for it to be loaded
142
137
  }
143
- });
138
+ }, { signal: ctrl.signal });
144
139
 
145
140
  for await (const { file, action } of stream) {
146
141
  if (action === 'delete') {
@@ -154,7 +149,7 @@ export class EmailCompiler {
154
149
  yield file;
155
150
  } else if (VALID_FILE(file)) {
156
151
  const rootFile = file.replace(/\/resources.*/, '/package.json');
157
- const mod = RootIndex.getFromSource(rootFile)!.module;
152
+ const mod = RuntimeIndex.getFromSource(rootFile)!.module;
158
153
  const changed = await this.compileAll(mod);
159
154
  console.log(`Successfully compiled ${changed.length} templates`, { changed, file });
160
155
  yield* changed;
package/src/util.ts CHANGED
@@ -1,5 +1,5 @@
1
- import util from 'util';
2
- import { Readable } from 'stream';
1
+ import util from 'node:util';
2
+ import { Readable } from 'node:stream';
3
3
 
4
4
  import { ResourceLoader, StreamUtil } from '@travetto/base';
5
5
  import {
@@ -80,12 +80,12 @@ export class EmailCompileUtil {
80
80
  /**
81
81
  * Compile SCSS content with roots as search paths for additional assets
82
82
  */
83
- static async compileSass(src: { data: string } | { file: string }, roots: string[]): Promise<string> {
83
+ static async compileSass(src: { data: string } | { file: string }, roots: string[] | readonly string[]): Promise<string> {
84
84
  const sass = await import('sass');
85
85
  const result = await util.promisify(sass.render)({
86
86
  ...src,
87
87
  sourceMap: false,
88
- includePaths: roots
88
+ includePaths: roots.slice(0)
89
89
  });
90
90
  return result!.css.toString();
91
91
  }
@@ -1,6 +1,6 @@
1
- import fs from 'fs/promises';
1
+ import fs from 'node:fs/promises';
2
2
 
3
- import { IndexedModule, RootIndex, path } from '@travetto/manifest';
3
+ import { IndexedModule, RuntimeIndex, path } from '@travetto/manifest';
4
4
  import { YamlUtil } from '@travetto/yaml';
5
5
 
6
6
  interface ConfigType {
@@ -40,7 +40,7 @@ export class $EditorConfig {
40
40
  };
41
41
 
42
42
  #getEmailConfig(mod: IndexedModule): string {
43
- return this.#configFile[mod.name] ??= path.resolve(mod.sourcePath, 'resources/email/dev.yml');
43
+ return this.#configFile[mod.name] ??= path.resolve(mod.sourcePath, 'resources/email/local.yml');
44
44
  }
45
45
 
46
46
  /**
@@ -48,7 +48,7 @@ export class $EditorConfig {
48
48
  */
49
49
  async get(file: string): Promise<ConfigType> {
50
50
  try {
51
- const mod = RootIndex.getModuleFromSource(file)!;
51
+ const mod = RuntimeIndex.getModuleFromSource(file)!;
52
52
  const resolved = this.#getEmailConfig(mod);
53
53
  const content = await fs.readFile(resolved, 'utf8');
54
54
  return YamlUtil.parse<ConfigType>(content);
@@ -74,7 +74,7 @@ export class $EditorConfig {
74
74
 
75
75
  async ensureConfig(file: string): Promise<string> {
76
76
  console.log('Ensuring config', file);
77
- const mod = RootIndex.getModuleFromSource(file)!;
77
+ const mod = RuntimeIndex.getModuleFromSource(file)!;
78
78
  const resolved = this.#getEmailConfig(mod);
79
79
  if (!(await fs.stat(resolved).catch(() => { }))) {
80
80
  await fs.mkdir(path.dirname(resolved), { recursive: true });
@@ -1,4 +1,4 @@
1
- import { ShutdownManager } from '@travetto/base';
1
+ import { ExecUtil } from '@travetto/base';
2
2
 
3
3
  import { EmailCompilationManager } from './manager';
4
4
  import { EditorSendService } from './send';
@@ -54,8 +54,8 @@ export class EditorState {
54
54
  }
55
55
 
56
56
  response(response: OutboundMessage): void {
57
- if (process.send) {
58
- process.send(response);
57
+ if (process.connected) {
58
+ process.send?.(response);
59
59
  }
60
60
  }
61
61
 
@@ -108,7 +108,7 @@ export class EditorState {
108
108
  }
109
109
  });
110
110
 
111
- process.on('disconnect', () => ShutdownManager.execute());
111
+ ExecUtil.exitOnDisconnect();
112
112
  process.send?.('ready');
113
113
 
114
114
  for await (const f of EmailCompiler.watchCompile()) {
@@ -1,4 +1,4 @@
1
- import fs from 'fs/promises';
1
+ import fs from 'node:fs/promises';
2
2
 
3
3
  import { type MailInterpolator, type EmailCompiled } from '@travetto/email';
4
4
  import { DependencyRegistry } from '@travetto/di';
@@ -3,7 +3,7 @@ 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
+ import { RuntimeIndex } from '@travetto/manifest';
7
7
 
8
8
  /**
9
9
  * Util for sending emails
@@ -16,7 +16,7 @@ export class EditorSendService {
16
16
  * Get mail service
17
17
  */
18
18
  static async getMailService(file: string): Promise<MailService> {
19
- const mod = RootIndex.getModuleFromSource(file)!.name;
19
+ const mod = RuntimeIndex.getModuleFromSource(file)!.name;
20
20
 
21
21
  if (!this.#svc[mod]) {
22
22
  const senderConfig = await EditorConfig.getSenderConfig(file);
@@ -34,7 +34,7 @@ export class EditorSendService {
34
34
  DependencyRegistry.install(cls, { curr: cls, type: 'added' });
35
35
  } else if (!DependencyRegistry.getCandidateTypes(MailTransportTarget).length) {
36
36
  const errorMessage = `
37
- Please configure your email setup and/or credentials for testing. In the file \`email/dev.yml\`, you can specify \`sender\` configuration.
37
+ Please configure your email setup and/or credentials for testing. In the file \`email/local.yml\`, you can specify \`sender\` configuration.
38
38
  Email sending will not work until the above is fixed. A sample configuration would look like:
39
39
 
40
40
  ${EditorConfig.getDefaultConfig()}`.trim();
@@ -1,6 +1,6 @@
1
1
  import { RootRegistry } from '@travetto/registry';
2
2
  import { CliCommandShape, CliCommand, cliTpl } from '@travetto/cli';
3
- import { Env, defineEnv } from '@travetto/base';
3
+ import { Env } from '@travetto/base';
4
4
 
5
5
  import { EmailCompiler } from '../src/compiler';
6
6
 
@@ -14,8 +14,8 @@ export class EmailCompileCommand implements CliCommandShape {
14
14
  watch?: boolean;
15
15
 
16
16
  preMain(): void {
17
- Env.addToList('TRV_PROFILES', 'email-dev');
18
- defineEnv({ debug: false, dynamic: this.watch });
17
+ Env.DEBUG.set(false);
18
+ Env.TRV_DYNAMIC.set(this.watch);
19
19
  }
20
20
 
21
21
  async main(): Promise<void> {
@@ -1,4 +1,4 @@
1
- import { Env, defineEnv } from '@travetto/base';
1
+ import { Env } from '@travetto/base';
2
2
  import { CliCommand, CliUtil } from '@travetto/cli';
3
3
  import { RootRegistry } from '@travetto/registry';
4
4
 
@@ -6,12 +6,11 @@ import { EditorState } from './bin/editor';
6
6
  import { EmailCompilationManager } from './bin/manager';
7
7
 
8
8
  /** The email editor compilation service and output serving */
9
- @CliCommand()
9
+ @CliCommand({ addEnv: true })
10
10
  export class EmailEditorCommand {
11
11
 
12
12
  preMain(): void {
13
- Env.addToList('TRV_PROFILES', 'email-dev');
14
- defineEnv({ envName: 'dev', dynamic: true });
13
+ Env.TRV_DYNAMIC.set(true);
15
14
  }
16
15
 
17
16
  async main(): Promise<void> {
@@ -1,7 +1,6 @@
1
1
  import { path } from '@travetto/manifest';
2
2
  import { RootRegistry } from '@travetto/registry';
3
3
  import { CliCommandShape, CliCommand } from '@travetto/cli';
4
- import { Env, defineEnv } from '@travetto/base';
5
4
 
6
5
  import { EmailCompilationManager } from './bin/manager';
7
6
  import { EditorConfig } from './bin/config';
@@ -12,14 +11,9 @@ import { EmailCompiler } from '../src/compiler';
12
11
  /**
13
12
  * CLI Entry point for running the email server
14
13
  */
15
- @CliCommand()
14
+ @CliCommand({ addEnv: true })
16
15
  export class EmailTestCommand implements CliCommandShape {
17
16
 
18
- preMain(): void {
19
- Env.addToList('TRV_PROFILES', 'email-dev');
20
- defineEnv({ envName: 'dev' });
21
- }
22
-
23
17
  async main(file: string, to: string): Promise<void> {
24
18
  file = path.resolve(file);
25
19
  await RootRegistry.init();