1 | "use strict";
|
2 |
|
3 | const
|
4 | Fs = require("fs"),
|
5 | Path = require("path"),
|
6 | Util = require("./util");
|
7 |
|
8 | const EXTENSIONS = ['js', 'xjs', 'css', 'ini', 'dep', 'vert', 'frag', 'wrk'];
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 | class Module {
|
23 | |
24 |
|
25 |
|
26 |
|
27 | constructor(_moduleName, _srcPath) {
|
28 | const
|
29 | moduleName = typeof _moduleName === 'string' && _moduleName.startsWith("mod/")
|
30 | ? _moduleName.substr( 4 ) : _moduleName,
|
31 | srcPath = Array.isArray(_srcPath) ? _srcPath : [_srcPath],
|
32 | candidates = getCandidates(moduleName, srcPath),
|
33 | candidate = getFirstViableCandidate(candidates),
|
34 | properties = { name: moduleName };
|
35 | for( const extension of EXTENSIONS) {
|
36 | properties[`path${Util.capitalize( extension )}`] = `${candidate}.${extension}`;
|
37 | properties[`exists${Util.capitalize( extension )}`] =
|
38 | () => Fs.existsSync( `${candidate}.${extension}` );
|
39 | }
|
40 | properties.lastModificationTime = () => {
|
41 | let time = 0;
|
42 | for( const extension of EXTENSIONS) {
|
43 | const filename = `${candidate}.${extension}`;
|
44 | if( !Fs.exists(filename) ) continue;
|
45 | const stat = FS.statSync( filename );
|
46 | time = Math.max( time, stat.mtime.getTime() );
|
47 | }
|
48 | return time;
|
49 | };
|
50 | Util.readonly(this, properties);
|
51 | }
|
52 | }
|
53 |
|
54 |
|
55 |
|
56 |
|
57 |
|
58 |
|
59 |
|
60 |
|
61 |
|
62 |
|
63 |
|
64 |
|
65 | function getCandidates(moduleName, srcPath) {
|
66 | const
|
67 | candidates = [],
|
68 | moduleNames = getSynonyms(moduleName);
|
69 |
|
70 | for( const path of srcPath) {
|
71 | for( const name of moduleNames) {
|
72 | candidates.push( Path.resolve( path, "mod", name) );
|
73 | }
|
74 | }
|
75 | return candidates;
|
76 | }
|
77 |
|
78 |
|
79 |
|
80 |
|
81 |
|
82 |
|
83 |
|
84 |
|
85 |
|
86 |
|
87 |
|
88 | function getSynonyms(moduleName) {
|
89 | const preferredName = moduleName.split(".").join("/");
|
90 | if( preferredName === moduleName) {
|
91 | return [moduleName];
|
92 | }
|
93 | return [preferredName, moduleName];
|
94 | }
|
95 |
|
96 |
|
97 |
|
98 |
|
99 |
|
100 |
|
101 |
|
102 |
|
103 | function getFirstViableCandidate(candidates) {
|
104 | for( const candidate of candidates) {
|
105 | const fileJS = `${candidate}.js`;
|
106 | if( Fs.existsSync(fileJS) ) return candidate;
|
107 | const fileXJS = `${candidate}.xjs`;
|
108 | if( Fs.existsSync(fileXJS) ) return candidate;
|
109 | }
|
110 |
|
111 | return candidates[0];
|
112 | }
|
113 |
|
114 |
|
115 |
|
116 |
|
117 |
|
118 |
|
119 |
|
120 |
|
121 |
|
122 |
|
123 | Module.fromFilename = function(filename, _srcPath) {
|
124 | const
|
125 | srcPath = Array.isArray(_srcPath) ? _srcPath : [_srcPath];
|
126 |
|
127 | for( const path of srcPath) {
|
128 | const absPath = Path.resolve( path );
|
129 | const relative = Path.relative( absPath, path );
|
130 | console.info("[module] path, relative=", path, relative);
|
131 | }
|
132 |
|
133 | return null;
|
134 | };
|
135 |
|
136 |
|
137 | module.exports = Module;
|