Test Failed
Push — master ( 40c64c...4518ff )
by Dimas
09:34
created

libs/src/compiler/gulpfile.ts   B

Complexity

Total Complexity 43
Complexity/F 4.78

Size

Lines of Code 386
Function Count 9

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 265
dl 0
loc 386
rs 8.96
c 0
b 0
f 0
wmc 43
mnd 34
bc 34
fnc 9
bpm 3.7777
cpm 4.7777
noi 0

9 Functions

Rating   Name   Duplication   Size   Complexity  
A gulpfile.ts ➔ createApp 0 46 4
A gulpfile.ts ➔ single_tsCompile 0 23 2
A gulpfile.ts ➔ multiMinify 0 7 1
A gulpfile.ts ➔ reload_gulp 0 18 2
C gulpfile.ts ➔ filter 0 11 10
A gulpfile.ts ➔ views 0 16 1
A gulpfile.ts ➔ build 0 22 4
F gulpfile.ts ➔ compileAssets 0 58 14
B gulpfile.ts ➔ typescriptCompiler 0 38 5

How to fix   Complexity   

Complexity

Complex classes like libs/src/compiler/gulpfile.ts often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
import * as gulp from "gulp";
2
import ts from "gulp-typescript";
3
import * as fs from "fs";
4
import config from "../compiler/config";
5
import upath from "upath";
6
import path from "path";
7
import framework from "../compiler/index";
8
import log from "../compiler/log";
9
import process from "../compiler/process";
10
const root = process.root;
11
import { exec, ExecException } from "child_process";
12
import { localStorage } from "../node-localstorage/index";
13
import { fixDeps } from "./func";
14
//const spawn = require("child_process").spawn;
15
//const argv = require("yargs").argv;
16
import { argv } from "yargs";
17
import { spawn } from "child_process";
18
import * as proc from "process";
19
20
localStorage.removeItem("compile");
21
console.clear();
22
23
/**
24
 * Build to /src/MVC/themes/assets/js/app.js
25
 * Minify Views Assets
26
 */
27
gulp.task("build", function () {
28
  return build();
29
});
30
31
gulp.task("build-clear", function () {
32
  return build(true);
33
});
34
35
/**
36
 * Build Project
37
 * @param withoutApp
38
 */
39
function build(withoutApp?: boolean) {
40
  try {
41
    var packageJson = root + "/package.json";
42
    if (fs.existsSync(packageJson)) {
43
      var json_pkg = JSON.parse(fs.readFileSync(packageJson).toString());
44
      fixDeps(json_pkg).then(function (json) {
45
        fs.writeFileSync(
46
          root + "/package.json",
47
          JSON.stringify(json, null, 2),
48
          {
49
            encoding: "utf-8",
50
          }
51
        );
52
      });
53
    }
54
  } catch (error) {}
55
  return createApp(withoutApp ? true : false);
56
}
57
58
// watch libs/js/**/* and views
59
gulp.task("watch", async function () {
60
  console.clear();
61
  const files = [
62
    "./libs/js/**/*",
63
    "./libs/src/**/*",
64
    "./src/MVC/**/*",
65
    "./etc/**/*",
66
    "./" + config.app.views + "/**/*",
67
  ];
68
  log.log(
69
    log.random("Listening ") +
70
      files
71
        .map(function (item) {
72
          return log.random(upath.resolve(item));
73
        })
74
        .join(" ")
75
  );
76
77
  var compiler_runner: any = false;
78
  var run_watch = gulp
79
    .watch(files, null)
80
    .on("change", function (
81
      file: string | Buffer | import("url").URL | string[]
82
    ) {
83
      const trigger = function () {
84
        file = framework.normalize(path.resolve(file.toString()));
85
        /**
86
         * Check is library compiler or source compiler
87
         */
88
        const is_Lib = /libs\/(js|src)\//s.test(framework.normalize(file));
89
        const filename_log = framework.filelog(file);
90
91
        if (is_Lib) {
92
          var isCompiler = file.includes("/libs/compiler/");
93
          var isFramework = /((framework|app)\.(js|js.map)|\.map)$/s.test(file);
94
          if (isCompiler || isFramework) return;
95
          //console.log(file, isFramework);
96
          log.log(
97
            log.random("Library compiler triggered by ") +
98
              log.random(framework.filelog(file))
99
          );
100
          log.log(
101
            log
102
              .chalk()
103
              .yellow(`start compile ${log.random("src/MVC/themes/assets/js")}`)
104
          );
105
          if (compiler_runner) {
106
            log.log(log.error("Compiler still running"));
107
          } else {
108
            compiler_runner = setTimeout(function () {
109
              createApp(true);
110
              compiler_runner = null;
111
            }, 5000);
112
          }
113
        } else {
114
          if (/\.(js|scss|css|less)$/s.test(file)) {
115
            if (!/\.min\.(js|css)$/s.test(file)) {
116
              compileAssets(file);
117
            }
118
          } else if (file.endsWith(".ts") && !file.endsWith(".d.ts")) {
119
            if (!/libs\/|libs\\/s.test(file)) {
120
              single_tsCompile(file);
121
            }
122
          } else {
123
            var reason = log.error("undefined");
124
            if (/\.(php|log|txt|htaccess|log)$/s.test(filename_log)) {
125
              reason = log.random("Excluded");
126
            } else if (/\.(d\.ts)$/s.test(filename_log)) {
127
              reason = log.random("Typehint");
128
            }
129
            log.log(`[${reason}] cannot modify ${log.random(filename_log)}`);
130
          }
131
        }
132
      };
133
      return trigger();
134
    });
135
  return run_watch;
136
});
137
138
gulp.task("assets-compile", function () {
139
  function filter(views: any[]) {
140
    return views
141
      .filter(function (item) {
142
        return (
143
          /\.(js|scss|css|sass|less)$/.test(item) &&
144
          !/\.min\.(js|css)$/.test(item) &&
145
          !/\-ori|\-original|\-backup|\.bak/s.test(item)
146
        );
147
      })
148
      .map(function (asset) {
149
        return framework.normalize(asset);
150
      });
151
  }
152
  var css = framework.readdir(root + "/assets/css");
153
  css = filter(css);
154
  var js = framework.readdir(root + "/assets/js");
155
  js = filter(js);
156
});
157
158
gulp.task("default", gulp.series(["build", "watch"]));
159
160
export function reload_gulp() {
161
  //spawn("gulp", ["watch"], { stdio: "inherit" });
162
  //proc.exit();
163
164
  if (proc.env.process_restarting) {
165
    delete proc.env.process_restarting;
166
    // Give old process one second to shut down before continuing ...
167
    //setTimeout(reload_gulp, 1000);
168
    reload_gulp();
169
    proc.exit();
170
    return;
171
  }
172
173
  // Restart process ...
174
  spawn(proc.argv[0], proc.argv.slice(1), {
175
    env: { process_restarting: "1" },
176
    stdio: "ignore",
177
  }).unref();
178
}
179
180
/**
181
 * compile and minify assets
182
 * @param item file full path
183
 */
184
export function compileAssets(item: string | Buffer): any {
185
  const exists = fs.existsSync(item);
186
  if (exists) {
187
    item = item.toString();
188
    var config:
189
      | string
190
      | {
191
          obfuscate: boolean;
192
        } = upath.normalizeSafe(
193
      root + "/src/MVC/config/" + item.replace(framework.root(), "")
194
    );
195
    config = framework.normalize(framework.root() + config);
196
    config = config.replace(/\.(js|css)/s, ".json");
197
    if (fs.existsSync(config)) {
198
      config = require(config);
199
    }
200
201
    if (item.endsWith(".less") && !item.endsWith(".min.less")) {
202
      //console.log(`Compiling LESS ${framework.filelog(item)}`);
203
      framework.less(item);
204
    } else if (item.endsWith(".scss") && !item.endsWith(".min.scss")) {
205
      //console.log(`Compiling SCSS ${framework.filelog(item)}`);
206
      framework.scss(item);
207
    } else if (item.endsWith(".css") && !item.endsWith(".min.css")) {
208
      //console.log(`Minify CSS ${framework.filelog(item)}`);
209
      framework.minCSS(item);
210
    } else if (item.endsWith(".js") && !item.endsWith(".min.js")) {
211
      if (!item.endsWith(".babel.js")) {
212
        //console.log(`Minify JS ${framework.filelog(item)}`);
213
        framework.minJS(item);
214
        var deleteObfuscated = false;
215
        if (typeof config == "object") {
216
          if (config.hasOwnProperty("obfuscate")) {
217
            if (config.obfuscate) {
218
              //console.log(`Obfuscating JS ${framework.filelog(item)}`);
219
              framework.obfuscate(item);
220
            } else {
221
              deleteObfuscated = true;
222
            }
223
          } else {
224
            deleteObfuscated = true;
225
          }
226
        }
227
        if (deleteObfuscated) {
228
          var obfuscatedjs = item.replace(/\.js$/s, ".obfuscated.js");
229
          var obfuscatedminjs = item.replace(/\.js$/s, ".obfuscated.min.js");
230
          framework.unlink(obfuscatedjs);
231
          framework.unlink(obfuscatedminjs);
232
        }
233
      }
234
    } else if (item.endsWith(".ts") && !item.endsWith(".d.ts")) {
235
      if (!/libs\/|libs\\/s.test(item)) {
236
        single_tsCompile(item);
237
      }
238
    }
239
  }
240
}
241
242
/**
243
 * List views folder
244
 */
245
export function views() {
246
  var views = framework.readdir(root + `/${config.app.views}`);
247
  return views
248
    .filter(function (item) {
249
      return (
250
        /\.(js|scss|css|sass|less)$/.test(item) &&
251
        !/\.min\.(js|css)$/.test(item) &&
252
        !/\-ori|\-original|\-backup|\.bak/s.test(item)
253
      );
254
    })
255
    .map(function (asset) {
256
      return framework.normalize(asset);
257
    });
258
}
259
260
/**
261
 * compileAssets multiple assets
262
 * @param assets
263
 */
264
export function multiMinify(assets: any[]): any {
265
  assets.map(compileAssets);
266
}
267
268
localStorage.removeItem("compile");
269
270
var isFirstExecute = true;
271
/**
272
 * Create App.js
273
 * @param withoutView false to not compile views javascripts
274
 */
275
export async function createApp(withoutView: boolean) {
276
  var exists = localStorage.getItem("compile");
277
  if (!exists) {
278
    localStorage.setItem("compile", "running");
279
    var target = upath.normalizeSafe(
280
      upath.resolve(upath.join(root, "src/MVC/themes/assets/js/app.js"))
281
    );
282
    await typescriptCompiler("tsconfig.build.json", root + "/").catch(function (
283
      err
284
    ) {
285
      log.log(log.error(err));
286
    });
287
    await typescriptCompiler("tsconfig.precompiler.json", root + "/").catch(
288
      function (err) {
289
        log.log(log.error(err));
290
      }
291
    );
292
    await typescriptCompiler("tsconfig.compiler.json", root + "/libs/").catch(
293
      function (err) {
294
        log.log(log.error(err));
295
      }
296
    );
297
    //await node2browser(target, path.dirname(target));
298
    await compileAssets(target);
299
    if (!withoutView) {
300
      await multiMinify(views());
301
    }
302
    localStorage.removeItem("compile");
303
    /*execute(
304
      "browserify --standalone Bundle ./src/MVC/themes/assets/js/app.js -o ./src/MVC/themes/assets/js/app.min.js && browserify --standalone Bundle ./src/MVC/themes/assets/js/app.js -o ./src/MVC/themes/assets/js/app.js"
305
    );*/
306
307
    if (!isFirstExecute) {
308
      // reload gulp
309
      reload_gulp();
310
    }
311
    isFirstExecute = false;
312
  } else {
313
    log.log(
314
      log.error("Compiler lock process already exists ") +
315
        log.chalk().yellow("node index.js fix") +
316
        log.chalk().green(" to fix it")
317
    );
318
  }
319
}
320
321
/**
322
 * Single Typescript Compiler
323
 * @param target
324
 * @todo universal-framework typescript compiler support
325
 */
326
export function single_tsCompile(target: string) {
327
  var targetlog = log.chalk().magentaBright(framework.filelog(target));
328
  if (target.endsWith(".d.ts")) {
329
    log.log(`${targetlog} is declaration file`);
330
    return;
331
  }
332
  var dest = path.dirname(target);
333
  log.log(
334
    `${targetlog} > ${log
335
      .chalk()
336
      .yellow(framework.filelog(target.replace(/\.ts$/, ".js")))} start`
337
  );
338
  var tsProject = ts.createProject({
339
    declaration: false,
340
    skipLibCheck: true,
341
  });
342
  return gulp.src(target).pipe(tsProject()).pipe(gulp.dest(dest));
343
}
344
345
/**
346
 * Typescript compiler
347
 * @param source
348
 * @param destination
349
 * @param callback
350
 */
351
export function typescriptCompiler(
352
  source: string,
353
  destination: string,
354
  callback: (arg0: any, arg1: any) => void = null
355
) {
356
  return new Promise((resolve, reject) => {
357
    exec(`tsc -p ${source}`, function (
358
      err: ExecException,
359
      stdout: string,
360
      stderr: string
361
    ) {
362
      if (!err) {
363
        if (typeof callback == "function") {
364
          callback(source, destination);
365
        }
366
        if (stdout.trim().length) {
367
          console.log(stdout);
368
        }
369
        if (stderr.trim().length) {
370
          console.log(stderr);
371
        }
372
        log.log(
373
          log.random("successfully compiled ") +
374
            log.success(path.basename(source))
375
        );
376
        resolve();
377
      } else {
378
        log.log(
379
          log.random("failed compile ") + log.error(path.basename(source))
380
        );
381
        reject(err.message);
382
      }
383
    });
384
  });
385
}
386