0

I created a simple JS library with common functions:

!!window.JsUtils || (window.JsUtils = {});

JsUtils = (function () {
    "use strict";
    return {
        randomHex: function (len) {
            var maxlen = 8;
            var min = Math.pow(16, Math.min(len, maxlen) - 1);
            var max = Math.pow(16, Math.min(len, maxlen)) - 1;
            var n = Math.floor(Math.random() * (max - min + 1)) + min;
            var r = n.toString(16);
            while (r.length < len) {
                r = r + randHex(len - maxlen);
            }
            return r;
        },
        ...
    };
}());

I'd like to be able to install it trhough NPM, so that whenever I update the core I can update it on my projects. But I cannot find a linear guide on how to to this..

Till now I only understood you have to init an npm project

npm init

Fill the questions...and you have a package.json like this:

{
  "name": "js-utils",
  "version": "0.2.0",
  "description": "Some common used JS functions",
  "main": "js-utils.js",
  "directories": {
    "test": "test"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/tonysamperi/js-utils.git"
  },
  "keywords": [
    "js",
    "utils",
    "library",
    "utility",
    "utilities",
    "javascript"
  ],
  "author": "Tony Samperi <github@tonysamperi.it> (tonysamperi.github.io)",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/tonysamperi/js-utils/issues"
  },
  "homepage": "https://github.com/tonysamperi/js-utils#readme"
}

But..would this work in npm?

Sampgun
  • 2,822
  • 1
  • 21
  • 38
  • but you want to use it in node ? because node does not have window object – Maciej Kozieja Apr 24 '18 at 18:40
  • yeah I'd also like to use it in node, like lodash! Ok so step1: remove the window references... – Sampgun Apr 24 '18 at 18:41
  • You can, in theory, publish anything to NPM, if I'm not mistaken. You'll just need to change, what @MaciejKozieja already pointed out – Luca Kiebel Apr 24 '18 at 18:42
  • 1
    If the goal is to use the same script for both, you can [prepare it as a UMD](https://github.com/umdjs/umd), with the use of `window`, `module`, etc. conditional. – [How can I share code between Node.js and the browser?](https://stackoverflow.com/questions/3225251/how-can-i-share-code-between-node-js-and-the-browser) – Jonathan Lonowski Apr 24 '18 at 18:44
  • ok, very good. Thanks to @JonathanLonowski, the linked answer is very helpful. Luca sei italiano? :) – Sampgun Apr 24 '18 at 18:47

2 Answers2

1

You just have to add exports in main file if you want to use it in node. Just like so

module.exports = {
  randomHex(len) {
    var maxlen = 8;
    var min = Math.pow(16, Math.min(len, maxlen) - 1);
    var max = Math.pow(16, Math.min(len, maxlen)) - 1;
    var n = Math.floor(Math.random() * (max - min + 1)) + min;
    var r = n.toString(16);
    while (r.length < len) {
      r = r + randHex(len - maxlen);
    }
    return r;
  },
}

or like so

module.exports.randomHex = function(len) {
    var maxlen = 8;
    var min = Math.pow(16, Math.min(len, maxlen) - 1);
    var max = Math.pow(16, Math.min(len, maxlen)) - 1;
    var n = Math.floor(Math.random() * (max - min + 1)) + min;
    var r = n.toString(16);
    while (r.length < len) {
      r = r + randHex(len - maxlen);
    }
    return r;
  },

Then just run npm publish and your package will be publicly avalieble

Browser loader:

!function () {
    class Module { constructor(exports) { Object.assign(this, exports) } }
    const modules = {}
    const fetchSync = (file) => {
      var xhr = new XMLHttpRequest()
      xhr.open("GET", file, false)
      xhr.send(null)
      return xhr.responseText
    }

    window.require = (file) => {
      file = file.replace('.js', '').replace(/^\.\//, '')
      const name = `${file}.js`.match(/\/?(.*)\.js/)[1]
      if (modules[file]) return modules[file].exports
      const module_code = fetchSync(`${file}.js`)
      let exports = { exports: {} }
      Function('module', 'require', module_code)(exports, require)

      const module = modules[file] = new Module(exports.exports)
      return window[name] = module
    }
  }()
Maciej Kozieja
  • 1,812
  • 1
  • 13
  • 32
  • Ok thanks, but this way it won't work client-side, right? – Sampgun Apr 24 '18 at 18:50
  • It could if you created fancy loader won't even be that hard but the problem is that it will install to node_modules dir and you would have to expose it wchih i think is bad – Maciej Kozieja Apr 24 '18 at 18:53
  • 1
    But still, unless you use some native browser objects or node modules you should be just fine – Maciej Kozieja Apr 24 '18 at 18:55
  • Yep. It should be something like lodash...So I shouln't use anything like the document... If it goes to node_modules..not a problem...I just want that if I download it to any folder it works on client... – Sampgun Apr 24 '18 at 18:57
  • Here, I created loader for you. Unfortunetly it has to use sync-module loading but it works just like in node. – Maciej Kozieja Apr 24 '18 at 19:24
  • We were just saying above not to use the window...what should be that? Another js file? – Sampgun Apr 24 '18 at 19:32
  • This loader will allow require() to be used in browser just like in node it will fetch code from file given by name and then evaluate it to create module just like in node now you can use require("module-name") in browser and in node but what i ment earlier is that if you use node or browser specific stuff it will work only on one side – Maciej Kozieja Apr 24 '18 at 19:38
  • You can't use ` – Maciej Kozieja Apr 24 '18 at 19:39
  • So, this is not what I want – Sampgun Apr 24 '18 at 19:56
0

This is the solution. I'm about to publish so...we'll see if it works.. For now ok on the client-side.

I was also able to determine if you are on client-side or server-side.

(function (exports) {

    function isClient() {
        return typeof window !== "undefined" && !!window.document;
    }

    var clientJsUtils = (function () {
        return {
            htmlCountDown: function (duration, updateFreq, targetEl) {
                var counter = JsUtils.roundNumber(duration, 1000) / 1000;
                var interval;
                var print = function () {
                    counter -= updateFreq / 1000;
                    counter < 0 && (counter = 0);
                    targetEl.innerHTML = counter.toFixed(2);
                };
                interval = setInterval(function () {
                    print();
                }, updateFreq);
                setTimeout(function () {
                    clearInterval(interval);
                    print();
                }, duration);
            },
            jQueryLoad: function () {
                var jq = document.createElement('script');
                jq.src = "https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js";
                jq.onload = function () {
                    console.info("jQuery loaded.");
                };
                jq.onerror = function () {
                    console.info("jQuery not loaded.");
                };
                document.getElementsByTagName('head')[0].appendChild(jq);
            },
            logWithStyle: function (title, msg, style) {
                console.group(title || "");
                console.log("%c" + msg, style);
                console.groupEnd();
            }
        };
    }());

    var JsUtils = (function () {
        hybridJsUtils = {
            randomHex: function randomHex(len) {
                var maxlen = 8;
                var min = Math.pow(16, Math.min(len, maxlen) - 1);
                var max = Math.pow(16, Math.min(len, maxlen)) - 1;
                var n = Math.floor(Math.random() * (max - min + 1)) + min;
                var r = n.toString(16);
                while (r.length < len) {
                    r = r + randomHex(len - maxlen);
                }
                return r;
            },
            randomInt: function (min, max, excludeMin, excludeMax) {
                if (!min || isNaN(min)) {
                    min = 0;
                }
                if (!max || isNaN(max)) {
                    max = 1;
                }
                excludeMax = excludeMax == "true"; //forces to have true or "true"
                excludeMin = excludeMin == "true"; //forces to have true or "true"
                var result = 0;
                if (excludeMax) {
                    result = Math.random() * (max - min) + min;
                }
                else {
                    result = Math.floor(Math.random() * (max - min + 1)) + min;
                }
                return excludeMin ? result : ++result;
            },
            removeTrailingSlash: function (target) {
                return target.replace(/\/$/, "");
            },
            roundNumber: function (value, closest) {
                //cleanup
                if (typeof value === typeof "") {
                    value = value.replace(/[^\d\.\-\ ]/g, "");
                }
                if (isNaN(value *= 1)) {
                    return 0;
                }
                if (typeof closest !== typeof 0 || closest < 1) {
                    closest = 1;
                }
                return Math.round(value / closest) * closest;
            }
        };

        return isClient() ? Object.assign(hybridJsUtils, clientJsUtils) : hybridJsUtils;
    }());

    Object.assign(exports, JsUtils);

})(typeof exports === "undefined" ? this["JsUtils"] = {} : exports);

This is the current version. (1.0.2)

npm install hybrid-js-utils
Sampgun
  • 2,822
  • 1
  • 21
  • 38