npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@fishertsau/moonlight

v1.26.29

Published

Various helpers or lib for javascript projects

Downloads

2,007

Readme

moonlight

  • 提供JavaScript常用的功能,類似helper或是utility,讓javascript專案使用
  • 可用於Server-side專案,如node.js,或是Client-side專案,如vue,react中
  • 發佈於npm中,使用時當作一個package使用
  • 可用於es6與commonjs中

Main functions

  1. Validator
  2. Parser
  3. time
  4. array
  5. hostname
  6. Checker
  7. Utils
  8. Model

Input Validator

  • check the input validity with specified rules

  • only the validated attribute(s) are returned

  • convert data type on validating, e.g '100' to 100 for 'type:number'

  • rules

    • required
    • type:[string|date|datetime|isoDatetime|number|email|bool|boolean|null|nonEmptyString|object]
    • same:attributeName
  • validator:: obj -> obj -> obj

  • examples

       const rules = {
            foo: 'required|type:null', // null
            boo: 'type:bool',  // true, false, 'true', 'false'
            boo: 'type:boolean',  // true, false, 'true', 'false'
     
           // string 
            moo: 'type:string', // string
            moo: 'required|type:emptyString',  // ''
            moo: 'required|type:nonEmptyString',  // non empty string 
            moo: 'required|type:lowerCaseOrNumberString',  // lower case or number string (e.g. 'abc123')
            moo: 'required|type:isNumberString',  // number string  (e.g. '123')
       
            // object 
            boo: 'type:object',  // object
            boo: 'type:emptyObject',  // {}
     
            // same content 
            bar: 'required|same:foo',
      
            // valid values
            loo: 'validValues:[v1,v2,v3]',
      
            aoo: 'type:array', // array
            aoo: 'type:emptyArray', // []
            aoo: 'type:arrayOfString', // ['a','b']
            aoo: 'type:arrayOfInt', // [1,2]
            aoo: 'type:arrayOfNull', // [null, null]
     
            // multiple types 
            soo: 'type:[number,null,nonEmptyString]', // number, null, non empty string
     
           // number & integer 
            foo: 'required|type:number', // number (e.g. 1.2)
            aoo: 'type:int', // integer (e.g. 1)
            aoo: 'type:positiveInt', // > 0
     
            // date & datetime 
            too: 'type:datetime',  // yyyy-mm-dd hh:mm:ss (e.g. '2000-01-01 12:00:00')
            too: 'type:isoDatetime',  // yyyy-mm-ddThh:mm:ss+08:00 (e.g. '2000-01-01T12:00:00+08:00')
            too: 'type:date', // yyyy-mm-dd (e.g. '2000-01-01')
            too: 'type:yearMonthDay', // {year:1, month: 1, day: 1}
    
            // length: same length
            foo: 'sameLength:bar', // same length as bar (e.g. '123' and 'abc')
            foo: 'minLen:3', // min length  (e.g. '123')
            foo: 'maxLen:5', // max length  (e.g. '12345')
     
            // range
            foo: 'range:1,10', // 1 <= foo <= 10 (for int only)
      
            // requiredWhen
            foo: 'requiredWhen:boo', // required when boo is not empty  (e.g. 'foo' is required when 'boo' is not empty)
       
            // app types 
            koo: 'type:email', // email
            koo: 'type:hostname', // hostname (e.g. 'www.google.com')
            koo: 'type:hostnameWithPath', // hostname with path (e.g. 'www.google.com/path')
            koo: 'type:lineId', // line id (e.g. 'U1234567890abcdef1234567890abcdef')
            koo: 'type:twTaxId', // Taiwan tax id  (8 digits) (e.g. '12345678')
            koo: 'type:twMobileNo', // Taiwan mobile number (10 digits) (e.g. '0912345678')
            koo: 'type:twLandPhoneNo', // Taiwan land phone number (9 digits) (e.g. '022345678')
            koo: 'type:addressWithDefault', // address with default value (e.g. {city:1, area:1, street:'abc'})
       };
    
      const validatedData = { foo: 123, bar: 123, koo: '2000-01-01', loo: 'invalidValue', moo: '', aoo:'notArray'};
      let result = validator(rules)(validatedData);
      // => { validated: true ,  values:{foo:123, bar:123,koo:'2000-01-01'}}
      // => { validated: false ,
      //      errors: {
      //         foo: ['foo should be a number.'], 
      //         koo: ['koo should be a string.']
      //         loo: ['loo should be in one of the values: v1,v2,v3.']
      //         moo: ['moo should be an non empty string.']
      //         aoo: ['aoo should be in array format.']
      //      }
      //    }

Parser

  • parseObj :: obj -> QueryString

    • convert an object to query string
    • example:
        parsrStr({a:'foo',b:'bar'})
        //=> a=foo&b=bar
  • parseStr :: QueryString -> obj

    • convert a query string to an object
    • example:
        parsrObj('a=foo&b=bar')
        //=> {a:'foo',b:'bar'}
  • convertKeyValue :: [a] -> obj (a: 'str=str')

    • convert a key-value array to an object
       convertKeyValue(['foo=bar', 'fiz=fuz']);
       //=> {foo:'bar', fiz:'fuz'}
  • convertObjToArr :: obj -> [a] (a: 'str=str')

    • convert an object to a key-value array
       convertKeyValue({ foo: 'bar', fiz: 'fuz' });
       //=> ['foo=bar', 'fiz=fuz']
  • snakeToCamel :: str -> str

    • convert a snake-string to camel-case string
       snakeToCamel('abc_def_ghi')
       //=> 'abcDefGhi'
  • objKeyToCamel :: obj -> obj

    • convert all keys in an object from snake to camel string
    • nested object is supported
       objKeyToCamel({this_is_key: val})
       //=> {thisIsKey: val}
  • camelToSnake :: str -> str

    • convert a camel-case string to snake-case string
       camelToSnake('abcDefGhi')
       //=> 'abc_def_ghi'
  • objKeyToSnake :: obj -> obj

    • convert all keys in an object from camel to snake-case string
    • nested object is supported
       objKeyToSnake({ thisIsKey: 'someVal' })
       //=> { this_is_key: 'someVal' }
  • parseCookie :: string -> obj

    • parse a cookie string to an object
       parseCookie('foo=bar ; equation=E%3Dmc%5E2;   asd=');
       //=> { foo: 'bar', equation: 'E=mc^2', asd: '' }
  • serializeCookie :: obj -> string

    • serialize an object to cookie string
       serializeCookie({ foo: 'bar', equation: 'E=mc^2', asd: '' });
       //=> 'foo=bar;equation=E%3Dmc%5E2;asd='

time

  • now :: null -> DateTime

        now();
        //=> current time
  • isoStrToUtcStr:: isoDatetimeString -> utcDatetimeString

        isoStrToUtcStr('1997-07-16T19:20:35+03:00');
        //=> '1997-07-16 16:20:35'
  • isoStrToTaipeiStr :: isoDatetimeString -> taipeiDatetimeString

       isoStrToTaipeiStr('1997-07-16T19:20:35+03:00');  // utc: 1997-07-16T16:20:35
       //=> '1997-07-17 00:20:35'
{
  // base
  Dayjs,
    now,

    // string to object
    toTimeObj,
    fromIsoTimeStrToObj,
    fromTimeStrAtTZ,
    fromTpeTimeStr,

    // datetime string
    utcDatetimeStrNow, // 2000-01-01 12:00:00
    isoStrNow,

    // string to string
    isoStrToUtcStr,    // 2000-01-01T12:00:00.000Z ->  2000-01-01 12:00:00
    utcStrToIsoStr,
    isoStrToTaipeiStr, // 2000-01-01T12:00:00.000Z ->  2000-01-01 20:00:00
    datetimeStrToDateStr, // 2000-01-01 12:00:00 -> 2000-01-01
    isoStrToTpeDateStr, // 2000-01-01T12:00:00.000Z -> 2000-01-01

    // date|datetime string
    dateAtTZ,
    todayStartInTpeStr,
    todayEndInTpeStr,
    todayEndInIsoStr,
    todayInTpeStrDateOnly,

    // time obj
    todayStartInTpe,
    todayEndInTpe,

    // type check
    isIsoFormat,

    // time zone
    TZ,
    TZ_TYPE,

    // comparison
    isBefore,
    isAfter,
    isBetween,
    isSame,

    // duration
    getDuration,

    // status
    getStatusByTimeFrame,
    STATUS_BY_TIME_FRAME,
    REF_TIME_STATUS_TYPE,

    // time manipulation
    minAgoFromNow,
}

array

  • shuffle :: array -> array
    • re-order the array items randomly

hostname

  • isValidHostname :: String -> Boolean
    • To validate a give hostname

Checker

  isTrue,
  isEmpty,
  isValidBool,
  isFunction,
  isUndefined,

  // object
  isObject,
  isEmptyObject,

  // string
  isString,
  isNonEmptyString,
  isNumberString,
  isEmptyString,
  isLowerCaseOrNumberString,
  isNumberOrString,
  isNumberOrNumberString,

  // number
  isIntBetween,
  isNumber,
  isValidInteger,
  isPositiveInteger,
  isUnsignedInteger,
  isSameNumOrNumStr,

  // number format
  ifOnlyNumberAndLetter,
  ifHexNumberStr,
  ifDecimalNumberStr,

  // time
  isDate,
  isDatetime,
  isIsoFormat,
  isIsoFormatWithZeroOffset,

  // array
  isArray,
  isEmptyArray,
  isNonEmptyArray,
  isArrayOfString,
  isArrayOfInt,
  isArrayOfArray, // [[], []]
  isArrayOfNumber,
  isArrayOfNull,

  // application
  isValidLineId,
  isValidEmail,
  isValidTwTaxId,
  isValidTwMobileNo,
  isValidTwLandPhoneNo,
  isValidTwNationalId,

  isValidHostname,
  isValidHostnameWithPath,
  • isTrue :: a -> boolean

    • To check if a given value is true
  • isEmpty :: a -> boolean

    • To check is a given value is empty
  • isIntBetween:: int a -> int b -> int c -> boolean

    • To check is a given int or value is between the specified range
  • isNumber:: a -> boolean

    • To check is given value is a number
  • isString:: a -> boolean

    • To check is given value is a string
  • isObject:: a -> boolean

    • To check is given value is an object
    • null and array are excluded
  • isValidEmail:: a -> boolean

    • To check is given value is a valid email
  • isValidBool:: a -> boolean

    • To check is given value is a valid boolean value
  • isFunction:: a -> boolean

    • To check is given value a Function
  • isValidHostname:: a -> boolean

    • To check if a given value a valid hostname
  • isDate:: str a -> boolean

    • To check is given string is in date format
    • valid date format: yyyy-mm-dd (time is not included)
  • isDateTime:: str a -> boolean

    • To check is given string is in datetime format
    • valid datetime format includes: unix time (integer), date+time, UTC
  • isIsoFormat:: a -> boolean

    • To check is given value is in ISO 8601 format
  • isIsoFormatWithZeroOffset:: a -> boolean

    • To check is given value is in ISO 8601 format with zero offset

Utils

  • clearSpace:: string -> string

    • To clear or remove space in a string
  • trim

    • To trim the string(s) in object properties and values
    • To trim string(s) in list
    • Can trim string(s) in nested objects or nested array
       trim({
          'p1  ': 'foo ',
          p2: ['  abc', ' def  '],
          p3: { p3_1: ['p31 '] },
          p4: { p4_1: ['p41 ', ' p42'], 'p4_2': {} },
          p5: 100,
         });
       //=> 
        {
          p1: 'foo',
          p2: ['abc', 'def'],
          p3: { p3_1: ['p31'] },
          p4: { p4_1: ['p41', 'p42'], 'p4_2' : {} },
          p5: 100,
        }
  • extractByPath

    • To extract a value from a structured collection object

    • Object structure

       {
          k1: {
            k1a: {}
            k1b: {}
          },
          k2: {
            k2a: {}
            k2b: {}
          }
       }
    • example:
      extractByPath(['info', 'age'])({'person1':{info:{age:10}}, 'person2':{info:{age:20}}});
      //=>  {'person1':10, 'person2':20}
  • getDirty

    • To get the values in new object which differ from that in the original object

    • The function is auto-curry

    • example:

     oriObj = {a:1, b:3}
     newObj = {a:1, b:5, c:7}
    
     getDirty(oriObj)(newObj);
      //=> {b:5, c:7}
  • renameKey

    • To change a key name

    • example:

     oriObj = {foo:1}
    
     renameKey('foo','bar')(oriObj);
      //=> {bar:1}
  • createEventEmitter

    • To create an event emitter

    • example:

    const em = createEventEmitter(); 
    
    // register event handler
    em.on('someEvent', someHandler); 
      
    // remove event handler 
    // A. remove specific handler
    em.remove('someEvent', someHandler); 
    // B. remove all handlers
    em.remove('someEvent'); 
      
    // send out event
    em.emit('someEvent', payload); 
  • pluckObjProp

    • To pluck a nested obj prop

    • example:

      // Functor f => k -> {k:v} -> {k:v}
      const obj = {
                    prop1: { foo: 123, bar: 'abc' },
                    prop2: { foo: 999, bar: 'abc' }
            }
    
      pluckObjProp('foo')(obj)
    
      //=> {prop1: 123, prop2: 999}
  • clean

    • To remove obj props if value is undefined/null/emptyString
    • Applicable to nested object
       clean({
          foo: 123,
          bar: undefined,
          koo: {
            k1: 'abc',
            k2: undefined,
          },
          poo: null,
          moo: '',
      })
       //=> { foo: 123, koo: { k1:'abc'} }
  • cleanNilUndefined

    • To remove obj props if value is undefined/null
    • Applicable to nested object
       clean({
          foo: 123,
          bar: undefined,
          koo: {
            k1: 'abc',
            k2: undefined,
          },
          poo: null,
          moo: '',
      })
       //=> { foo: 123, koo: { k1:'abc'} moo: '' }
  • hasValue

    • To check if an object has specified value
    • Applicable to simple object
       hasValue(123, { foo: 123 })
       //=> true
      
       hasValue('abc', { foo: 123 })
       //=> false 
  • rmArrSquareInReqParamsKey

       harmArrSquareInReqParamsKeys(
          {
            from: 0,
            'ids[]': [ 'abc1705548556993', 'abc1705558802725']
          });
    
       //=> 
          {
             from: 0,
             'ids': [ 'abc1705548556993' , 'abc1705558802725']
           };
  • getObjectDifference

    const obj1 = {
 a: 1,
 b: {
   c: 2,
   d: {
     e: 3,
   },
 },
 f: {
   g: 5,
 },
};

const obj2 = {
 a: 1,
 b: {
   c: 3,
   d: {
     e: 4,
   },
 },
};

getObjectDifference(obj1, obj2);

//=> 
{
 {
   'b.c'
 :
   [2, 3], 'b.d.e'
 :
   [3, 4], f
 :
   [{ g: 5 }, undefined]
 }

MoonUse

  • useRetry

  • useLock

  • useWait

    • To make an action execution wait for a given time before execution
      useWait(1000, action);
      //=> wait for 1000ms, and then run action 
    - ```
    
  • useRedisCache

    • To get value from redis cache, otherwise get the value and cache it
      const foo = await useCache('someCacheKey', getter, {keyLife:100});
      //=> keyLife: key有效時間 (in second)
    - ```
    

Model

  • basicTypes
  YES_NO_TYPE,
  NULLABLE_YES_NO_TYPE,

  STRING_TYPE,
  NON_EMPTY_STRING_TYPE,
  NUMBER_OR_STRING_TYPE,
  NULLABLE_STRING_TYPE,

  INTEGER_TYPE,
  UNSIGNED_INTEGER_TYPE,
  NULLABLE_INTEGER_TYPE,
  POSITIVE_INTEGER_TYPE,
  NULLABLE_UNSIGNED_INTEGER_TYPE,

  BIG_INTEGER_TYPE,
  NULLABLE_BIG_INTEGER_TYPE,

  UNSIGNED_TINY_INTEGER_TYPE,

  NUMBER_TYPE,

  ARRAY_TYPE,
  ARRAY_OF_INT_TYPE,
  NULLABLE_ARRAY_TYPE,

  OBJECT_TYPE,
  NULLABLE_OBJECT_TYPE,

  FUNCTION_TYPE,
  NULLABLE_FUNCTION_TYPE,
- example
```
     Model.basicTypes.STRING_TYPE;
```
  • datetimeTypes
  DATE_TYPE,
  NULLABLE_DATE_TYPE,

  DATETIME_TYPE,
  NULLABLE_DATETIME_TYPE,

  ISO_DATETIME_TYPE,
  NULLABLE_ISO_DATETIME_TYPE,
  • appTypes
  EMAIL_TYPE,
  NULLABLE_EMAIL_TYPE,
  EMPTY_STRING_OR_EMAIL_TYPE,

  LINE_ID_TYPE,
  EMPTY_STRING_OR_LINE_ID_TYPE,

  CITY_TYPE,
  CITY_AREA_TYPE,

  MEDIA_TYPE,

  TW_TAX_ID_TYPE,
  NULLABLE_TW_TAX_ID_TYPE,
  TW_MOBILE_NO_TYPE,

  HOSTNAME_TYPE,
  NULLABLE_HOSTNAME_TYPE,
  EMPTY_STRING_OR_HOSTNAME_TYPE,
  • appTypes.CITY_TYPE (台灣城市)

    • 結構: 整數 (城市編號)

    • properties:

      • validator
      • cityList (台灣城市清單)
    • 會檢查縣市是否為合法值

  • appTypes.CITY_AREA_TYPE (台灣城市與區域)

    • 結構: {cityId: 1, areaId: 1}

    • properties:

      • validator
      • cityList (台灣城市清單)
      • areaList (台灣區域清單,含城市編號與區域號碼)
    • 會檢查縣市與區域的對應,是否為合法值

    • 城市與區域未定: {cityId:0, areaId:0}

    • 使用範例

     const someModelDef = {
       location: {
         type: CITY_AREA_TYPE,
       }
     }
  • cityList內容

  const cityList = [
   { id: 0, name: '未定義' },
   { id: 1, name: '台北市' },
   ...
  ];
  • areaList內容
  const areaList = [
    { id: 0, cityId: 0, name: '未定義', zip: 0 },
    { id: 1, cityId: 1, name: '中正區', zip: 100 },
    ...
  ];