Completed
Push — master ( 0dd02f...6db2b4 )
by Dimas
45:39 queued 27:24
created

libs/src/compiler/gulpfile.ts   A

Complexity

Total Complexity 40
Complexity/F 5

Size

Lines of Code 381
Function Count 8

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 256
dl 0
loc 381
rs 9.2
c 0
b 0
f 0
wmc 40
mnd 32
bc 32
fnc 8
bpm 4
cpm 5
noi 0

8 Functions

Rating   Name   Duplication   Size   Complexity  
A gulpfile.ts ➔ createApp 0 37 3
A gulpfile.ts ➔ single_tsCompile 0 24 2
A gulpfile.ts ➔ multiMinify 0 7 1
C gulpfile.ts ➔ node2browser 0 29 11
A gulpfile.ts ➔ views 0 16 1
A gulpfile.ts ➔ build 0 22 4
B gulpfile.ts ➔ typescriptCompiler 0 38 5
D gulpfile.ts ➔ minify 0 49 13

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