vintasend-pug 0.9.0 → 0.10.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/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/pug-inline-email-template-renderer.d.ts +34 -0
- package/dist/pug-inline-email-template-renderer.d.ts.map +1 -0
- package/dist/pug-inline-email-template-renderer.js +97 -0
- package/dist/scripts/compile-pug-templates.d.ts +3 -0
- package/dist/scripts/compile-pug-templates.d.ts.map +1 -0
- package/dist/scripts/compile-pug-templates.js +71 -0
- package/package.json +13 -10
- package/src/scripts/compile-pug-templates.ts +90 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export { PugEmailTemplateRendererFactory } from './pug-email-template-renderer';
|
|
2
2
|
export type { PugEmailTemplateRenderer } from './pug-email-template-renderer';
|
|
3
|
+
export { PugInlineEmailTemplateRendererFactory } from './pug-inline-email-template-renderer';
|
|
4
|
+
export type { PugInlineEmailTemplateRenderer } from './pug-inline-email-template-renderer';
|
|
3
5
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,+BAA+B,EAAE,MAAM,+BAA+B,CAAC;AAChF,YAAY,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,+BAA+B,EAAE,MAAM,+BAA+B,CAAC;AAChF,YAAY,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAC9E,OAAO,EAAE,qCAAqC,EAAE,MAAM,sCAAsC,CAAC;AAC7F,YAAY,EAAE,8BAA8B,EAAE,MAAM,sCAAsC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { BaseEmailTemplateRenderer } from 'vintasend';
|
|
2
|
+
import type { EmailTemplateContent } from 'vintasend/dist/services/notification-template-renderers/base-email-template-renderer';
|
|
3
|
+
import type { JsonObject } from 'vintasend/dist/types/json-values';
|
|
4
|
+
import type { DatabaseNotification } from 'vintasend/dist/types/notification';
|
|
5
|
+
import type { BaseNotificationTypeConfig } from 'vintasend/dist/types/notification-type-config';
|
|
6
|
+
import type { BaseLogger } from 'vintasend/dist/services/loggers/base-logger';
|
|
7
|
+
/**
|
|
8
|
+
* Custom email template renderer that compiles Pug templates from strings
|
|
9
|
+
* instead of reading from file paths.
|
|
10
|
+
*
|
|
11
|
+
* This is necessary for bot deployments where templates are embedded as constants
|
|
12
|
+
* rather than separate files.
|
|
13
|
+
*/
|
|
14
|
+
export declare class PugInlineEmailTemplateRenderer<Config extends BaseNotificationTypeConfig> implements BaseEmailTemplateRenderer<Config> {
|
|
15
|
+
private templates;
|
|
16
|
+
private logger;
|
|
17
|
+
constructor(generatedTemplates: Record<string, string>);
|
|
18
|
+
/**
|
|
19
|
+
* Inject logger (called by VintaSend when logger exists)
|
|
20
|
+
*/
|
|
21
|
+
injectLogger(logger: BaseLogger): void;
|
|
22
|
+
render(notification: DatabaseNotification<Config>, context: JsonObject): Promise<{
|
|
23
|
+
subject: string;
|
|
24
|
+
body: string;
|
|
25
|
+
}>;
|
|
26
|
+
renderFromTemplateContent(notification: DatabaseNotification<Config>, templateContent: EmailTemplateContent, context: JsonObject): Promise<{
|
|
27
|
+
subject: string;
|
|
28
|
+
body: string;
|
|
29
|
+
}>;
|
|
30
|
+
}
|
|
31
|
+
export declare class PugInlineEmailTemplateRendererFactory<Config extends BaseNotificationTypeConfig> {
|
|
32
|
+
create(generatedTemplates: Record<string, string>): PugInlineEmailTemplateRenderer<Config>;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=pug-inline-email-template-renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pug-inline-email-template-renderer.d.ts","sourceRoot":"","sources":["../src/pug-inline-email-template-renderer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sFAAsF,CAAC;AACjI,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,+CAA+C,CAAC;AAChG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6CAA6C,CAAC;AAG9E;;;;;;GAMG;AACH,qBAAa,8BAA8B,CAAC,MAAM,SAAS,0BAA0B,CACnF,YAAW,yBAAyB,CAAC,MAAM,CAAC;IAE5C,OAAO,CAAC,SAAS,CAAyB;IAC1C,OAAO,CAAC,MAAM,CAA2B;gBAE7B,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAItD;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAIhC,MAAM,CACV,YAAY,EAAE,oBAAoB,CAAC,MAAM,CAAC,EAC1C,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IA8CvC,yBAAyB,CAC7B,YAAY,EAAE,oBAAoB,CAAC,MAAM,CAAC,EAC1C,eAAe,EAAE,oBAAoB,EACrC,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAiC9C;AAED,qBAAa,qCAAqC,CAAC,MAAM,SAAS,0BAA0B;IAC1F,MAAM,CAAC,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,8BAA8B,CAAC,MAAM,CAAC;CAG3F"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import * as pug from 'pug';
|
|
2
|
+
/**
|
|
3
|
+
* Custom email template renderer that compiles Pug templates from strings
|
|
4
|
+
* instead of reading from file paths.
|
|
5
|
+
*
|
|
6
|
+
* This is necessary for bot deployments where templates are embedded as constants
|
|
7
|
+
* rather than separate files.
|
|
8
|
+
*/
|
|
9
|
+
export class PugInlineEmailTemplateRenderer {
|
|
10
|
+
constructor(generatedTemplates) {
|
|
11
|
+
this.logger = null;
|
|
12
|
+
this.templates = generatedTemplates;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Inject logger (called by VintaSend when logger exists)
|
|
16
|
+
*/
|
|
17
|
+
injectLogger(logger) {
|
|
18
|
+
this.logger = logger;
|
|
19
|
+
}
|
|
20
|
+
async render(notification, context) {
|
|
21
|
+
// Check if body template is provided
|
|
22
|
+
const bodyTemplateKey = notification.bodyTemplate;
|
|
23
|
+
if (!bodyTemplateKey) {
|
|
24
|
+
throw new Error('Body template is required');
|
|
25
|
+
}
|
|
26
|
+
if (!(bodyTemplateKey in this.templates)) {
|
|
27
|
+
throw new Error(`Body template "${bodyTemplateKey}" not found in templates`);
|
|
28
|
+
}
|
|
29
|
+
// Check if subject template is provided
|
|
30
|
+
const subjectTemplateKey = notification.subjectTemplate;
|
|
31
|
+
if (!subjectTemplateKey) {
|
|
32
|
+
throw new Error('Subject template is required');
|
|
33
|
+
}
|
|
34
|
+
if (!(subjectTemplateKey in this.templates)) {
|
|
35
|
+
throw new Error(`Subject template "${subjectTemplateKey}" not found in templates`);
|
|
36
|
+
}
|
|
37
|
+
let body;
|
|
38
|
+
try {
|
|
39
|
+
// Compile and render the body template from string
|
|
40
|
+
const bodyTemplate = pug.compile(this.templates[bodyTemplateKey]);
|
|
41
|
+
body = bodyTemplate(context);
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
if (this.logger) {
|
|
45
|
+
this.logger.error('[PugInlineEmailTemplateRenderer] Error rendering body template');
|
|
46
|
+
}
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
let subject;
|
|
50
|
+
try {
|
|
51
|
+
// Compile and render the subject template from string
|
|
52
|
+
const subjectTemplate = pug.compile(this.templates[subjectTemplateKey]);
|
|
53
|
+
subject = subjectTemplate(context);
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
if (this.logger) {
|
|
57
|
+
this.logger.error('[PugInlineEmailTemplateRenderer] Error rendering subject template');
|
|
58
|
+
}
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
return { subject, body };
|
|
62
|
+
}
|
|
63
|
+
async renderFromTemplateContent(notification, templateContent, context) {
|
|
64
|
+
this.logger?.info(`[PugInlineEmailTemplateRenderer] Rendering template from content for notification ${notification.id}`);
|
|
65
|
+
let body;
|
|
66
|
+
try {
|
|
67
|
+
const bodyTemplate = pug.compile(templateContent.body);
|
|
68
|
+
body = bodyTemplate(context);
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
if (this.logger) {
|
|
72
|
+
this.logger.error('[PugInlineEmailTemplateRenderer] Error rendering body template content');
|
|
73
|
+
}
|
|
74
|
+
throw error;
|
|
75
|
+
}
|
|
76
|
+
if (!templateContent.subject) {
|
|
77
|
+
throw new Error('Subject template is required');
|
|
78
|
+
}
|
|
79
|
+
let subject;
|
|
80
|
+
try {
|
|
81
|
+
const subjectTemplate = pug.compile(templateContent.subject);
|
|
82
|
+
subject = subjectTemplate(context);
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
if (this.logger) {
|
|
86
|
+
this.logger.error('[PugInlineEmailTemplateRenderer] Error rendering subject template content');
|
|
87
|
+
}
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
return { subject, body };
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
export class PugInlineEmailTemplateRendererFactory {
|
|
94
|
+
create(generatedTemplates) {
|
|
95
|
+
return new PugInlineEmailTemplateRenderer(generatedTemplates);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile-pug-templates.d.ts","sourceRoot":"","sources":["../../src/scripts/compile-pug-templates.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
/**
|
|
5
|
+
* Recursively finds all .pug files in a directory
|
|
6
|
+
*/
|
|
7
|
+
function findPugFiles(dir, baseDir, files = new Map()) {
|
|
8
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
9
|
+
for (const entry of entries) {
|
|
10
|
+
const fullPath = path.join(dir, entry.name);
|
|
11
|
+
if (entry.isDirectory()) {
|
|
12
|
+
// Recursively search subdirectories
|
|
13
|
+
findPugFiles(fullPath, baseDir, files);
|
|
14
|
+
}
|
|
15
|
+
else if (entry.isFile() && entry.name.endsWith('.pug')) {
|
|
16
|
+
// Read the pug file content
|
|
17
|
+
const content = fs.readFileSync(fullPath, 'utf-8');
|
|
18
|
+
// Use relative path from base directory as the key
|
|
19
|
+
// Normalize to POSIX-style path (forward slashes) for cross-platform consistency
|
|
20
|
+
const relativePath = path.relative(baseDir, fullPath).replace(/\\/g, '/');
|
|
21
|
+
files.set(relativePath, content);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return files;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Main function to compile pug templates to JSON
|
|
28
|
+
*/
|
|
29
|
+
function compilePugTemplates(inputDir = './templates', outputFile = 'compiled-templates.json') {
|
|
30
|
+
// Validate input directory exists
|
|
31
|
+
if (!fs.existsSync(inputDir)) {
|
|
32
|
+
console.error(`Error: Directory "${inputDir}" does not exist.`);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
if (!fs.statSync(inputDir).isDirectory()) {
|
|
36
|
+
console.error(`Error: "${inputDir}" is not a directory.`);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
console.log(`Searching for .pug files in: ${inputDir}`);
|
|
40
|
+
// Find all pug files
|
|
41
|
+
const pugFiles = findPugFiles(inputDir, inputDir);
|
|
42
|
+
console.log(`Found ${pugFiles.size} .pug file(s)`);
|
|
43
|
+
// Convert Map to plain object
|
|
44
|
+
const result = {};
|
|
45
|
+
for (const [filePath, content] of pugFiles.entries()) {
|
|
46
|
+
result[filePath] = content;
|
|
47
|
+
console.log(` - ${filePath}`);
|
|
48
|
+
}
|
|
49
|
+
// Write to output file
|
|
50
|
+
const outputContent = JSON.stringify(result, null, 2);
|
|
51
|
+
fs.writeFileSync(outputFile, outputContent, 'utf-8');
|
|
52
|
+
console.log(`\nSuccessfully compiled templates to: ${outputFile}`);
|
|
53
|
+
}
|
|
54
|
+
// Parse command line arguments
|
|
55
|
+
const args = process.argv.slice(2);
|
|
56
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
57
|
+
console.log('Usage: compile-pug-templates [input-directory] [output-file]');
|
|
58
|
+
console.log('');
|
|
59
|
+
console.log('Arguments:');
|
|
60
|
+
console.log(' input-directory Directory containing .pug templates (default: ./templates)');
|
|
61
|
+
console.log(' output-file Output JSON file path (default: compiled-templates.json)');
|
|
62
|
+
console.log('');
|
|
63
|
+
console.log('Examples:');
|
|
64
|
+
console.log(' compile-pug-templates');
|
|
65
|
+
console.log(' compile-pug-templates ./templates');
|
|
66
|
+
console.log(' compile-pug-templates ./templates ./compiled-templates.json');
|
|
67
|
+
process.exit(0);
|
|
68
|
+
}
|
|
69
|
+
const [inputDir, outputFile] = args;
|
|
70
|
+
// Run the compilation
|
|
71
|
+
compilePugTemplates(inputDir, outputFile);
|
package/package.json
CHANGED
|
@@ -1,29 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vintasend-pug",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"build": "tsc",
|
|
8
8
|
"prepublishOnly": "npm run build",
|
|
9
|
-
"test": "
|
|
10
|
-
"test:watch": "
|
|
11
|
-
"test:coverage": "
|
|
9
|
+
"test": "vitest run",
|
|
10
|
+
"test:watch": "vitest",
|
|
11
|
+
"test:coverage": "vitest run --coverage"
|
|
12
12
|
},
|
|
13
13
|
"files": [
|
|
14
|
-
"dist"
|
|
14
|
+
"dist",
|
|
15
|
+
"src/scripts/compile-pug-templates.ts"
|
|
15
16
|
],
|
|
17
|
+
"bin": {
|
|
18
|
+
"compile-pug-templates": "dist/scripts/compile-pug-templates.js"
|
|
19
|
+
},
|
|
16
20
|
"author": "Hugo Bessa",
|
|
17
21
|
"license": "MIT",
|
|
18
22
|
"dependencies": {
|
|
19
23
|
"pug": "^3.0.3",
|
|
20
|
-
"vintasend": "^0.
|
|
24
|
+
"vintasend": "^0.10.0"
|
|
21
25
|
},
|
|
22
26
|
"devDependencies": {
|
|
23
|
-
"@types/jest": "^30.0.0",
|
|
24
27
|
"@types/pug": "^2.0.10",
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
+
"@vitest/coverage-v8": "4.0.18",
|
|
29
|
+
"typescript": "^5.9.3",
|
|
30
|
+
"vitest": "4.0.18"
|
|
28
31
|
}
|
|
29
32
|
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
|
|
5
|
+
interface PugTemplatesMap {
|
|
6
|
+
[key: string]: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Recursively finds all .pug files in a directory
|
|
11
|
+
*/
|
|
12
|
+
function findPugFiles(dir: string, baseDir: string, files: Map<string, string> = new Map()): Map<string, string> {
|
|
13
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
14
|
+
|
|
15
|
+
for (const entry of entries) {
|
|
16
|
+
const fullPath = path.join(dir, entry.name);
|
|
17
|
+
|
|
18
|
+
if (entry.isDirectory()) {
|
|
19
|
+
// Recursively search subdirectories
|
|
20
|
+
findPugFiles(fullPath, baseDir, files);
|
|
21
|
+
} else if (entry.isFile() && entry.name.endsWith('.pug')) {
|
|
22
|
+
// Read the pug file content
|
|
23
|
+
const content = fs.readFileSync(fullPath, 'utf-8');
|
|
24
|
+
// Use relative path from base directory as the key
|
|
25
|
+
// Normalize to POSIX-style path (forward slashes) for cross-platform consistency
|
|
26
|
+
const relativePath = path.relative(baseDir, fullPath).replace(/\\/g, '/');
|
|
27
|
+
files.set(relativePath, content);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return files;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Main function to compile pug templates to JSON
|
|
36
|
+
*/
|
|
37
|
+
function compilePugTemplates(inputDir: string = './templates', outputFile: string = 'compiled-templates.json'): void {
|
|
38
|
+
// Validate input directory exists
|
|
39
|
+
if (!fs.existsSync(inputDir)) {
|
|
40
|
+
console.error(`Error: Directory "${inputDir}" does not exist.`);
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (!fs.statSync(inputDir).isDirectory()) {
|
|
45
|
+
console.error(`Error: "${inputDir}" is not a directory.`);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
console.log(`Searching for .pug files in: ${inputDir}`);
|
|
50
|
+
|
|
51
|
+
// Find all pug files
|
|
52
|
+
const pugFiles = findPugFiles(inputDir, inputDir);
|
|
53
|
+
|
|
54
|
+
console.log(`Found ${pugFiles.size} .pug file(s)`);
|
|
55
|
+
|
|
56
|
+
// Convert Map to plain object
|
|
57
|
+
const result: PugTemplatesMap = {};
|
|
58
|
+
for (const [filePath, content] of pugFiles.entries()) {
|
|
59
|
+
result[filePath] = content;
|
|
60
|
+
console.log(` - ${filePath}`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Write to output file
|
|
64
|
+
const outputContent = JSON.stringify(result, null, 2);
|
|
65
|
+
fs.writeFileSync(outputFile, outputContent, 'utf-8');
|
|
66
|
+
|
|
67
|
+
console.log(`\nSuccessfully compiled templates to: ${outputFile}`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Parse command line arguments
|
|
71
|
+
const args = process.argv.slice(2);
|
|
72
|
+
|
|
73
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
74
|
+
console.log('Usage: compile-pug-templates [input-directory] [output-file]');
|
|
75
|
+
console.log('');
|
|
76
|
+
console.log('Arguments:');
|
|
77
|
+
console.log(' input-directory Directory containing .pug templates (default: ./templates)');
|
|
78
|
+
console.log(' output-file Output JSON file path (default: compiled-templates.json)');
|
|
79
|
+
console.log('');
|
|
80
|
+
console.log('Examples:');
|
|
81
|
+
console.log(' compile-pug-templates');
|
|
82
|
+
console.log(' compile-pug-templates ./templates');
|
|
83
|
+
console.log(' compile-pug-templates ./templates ./compiled-templates.json');
|
|
84
|
+
process.exit(0);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const [inputDir, outputFile] = args;
|
|
88
|
+
|
|
89
|
+
// Run the compilation
|
|
90
|
+
compilePugTemplates(inputDir, outputFile);
|