forked from StyleT/tailorx
-
Notifications
You must be signed in to change notification settings - Fork 1
/
fetch-template.js
127 lines (112 loc) · 3.58 KB
/
fetch-template.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
'use strict';
const path = require('node:path');
const url = require('node:url');
const {
readFile: readFilePromise,
lstat: lstatPromise
} = require('node:fs/promises');
const TEMPLATE_ERROR = 0;
const TEMPLATE_NOT_FOUND = 1;
class TemplateError extends Error {
constructor(...args) {
super(...args);
this.code = TEMPLATE_ERROR;
this.presentable = 'template error';
const [{ code }] = args;
if (code === 'ENOENT') {
this.code = TEMPLATE_NOT_FOUND;
this.presentable = 'template not found';
}
}
}
/**
* Read the file from File System
*
* @param {string} path
*/
const readFile = path =>
readFilePromise(path, 'utf-8').catch(err => {
throw new TemplateError(err);
});
/**
* Returns the template path validating a exactly file or a directory
*
* @param {String} templatesPath - TemplatesPath config
* @param {String} pathname - Path name based on Request Object
*
* @return {Promise} Template Info object on success or TemplateError on fail
*/
const getTemplatePath = (templatesPath, pathname) =>
new Promise((resolve, reject) => {
lstatPromise(templatesPath).then(
data => {
let templateStat = {
isFile: data.isFile()
};
if (templateStat.isFile) {
templateStat.path = templatesPath;
} else {
templateStat.path = factoryFilePath(
templatesPath,
pathname
);
}
return resolve(templateStat);
},
err => {
return reject(new TemplateError(err));
}
);
});
/**
* Returns pathname by request
*
* @param {Object} request - Request Object
*
* @return {String} pathname
*/
const getPathName = request => url.parse(request.url, true).pathname;
/**
* Factory the complete file path
*
* @param {String} templatesPath - Templates dir path
* @param {String} filename - file name without extension
*
* @return {String} complete file path
*/
const factoryFilePath = (templatesPath, filename) =>
`${path.join(templatesPath, filename)}.html`;
/**
* Fetches the template from File System
*
* @param {string} templatesPath - The path where the templates are stored
* @param {function=} baseTemplateFn - Function that returns the Base template name for a given page
*/
module.exports =
(templatesPath, baseTemplateFn) => (request, parseTemplate) => {
const pathname = getPathName(request);
return getTemplatePath(templatesPath, pathname).then(templateStat => {
return readFile(templateStat.path).then(baseTemplate => {
if (
templateStat.isFile ||
typeof baseTemplateFn !== 'function'
) {
return parseTemplate(baseTemplate);
}
const templateName = baseTemplateFn(pathname);
if (!templateName) {
return parseTemplate(baseTemplate);
}
const pageTemplate = baseTemplate;
const baseTemplatePath = factoryFilePath(
templatesPath,
templateName
);
return readFile(baseTemplatePath).then(baseTemplate =>
parseTemplate(baseTemplate, pageTemplate)
);
});
});
};
module.exports.TEMPLATE_ERROR = TEMPLATE_ERROR;
module.exports.TEMPLATE_NOT_FOUND = TEMPLATE_NOT_FOUND;