This commit is contained in:
Martin Donnelly 2020-11-17 11:16:34 +00:00
commit c30b36b3f6
67 changed files with 12692 additions and 0 deletions

32
.editorconfig Normal file
View File

@ -0,0 +1,32 @@
; http://editorconfig.org
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 2
[*.txt]
insert_final_newline = false
trim_trailing_whitespace = false
[*.py]
indent_size = 4
[*.m]
indent_size = 4
[Makefile]
indent_style = tab
indent_size = 8
[*.{js,json,ts}]
indent_style = space
indent_size = 2
[*.md]
trim_trailing_whitespace = false

72
.eslintrc.json Normal file
View File

@ -0,0 +1,72 @@
{
"parserOptions": {
"ecmaVersion": 2020,
"sourceType": "module",
"ecmaFeatures": {
"jsx": false
}
},
"env": {
"browser": true,
"node": true,
"es2020": true,
"mocha": true
},
"parser": "@typescript-eslint/parser",
"extends": ["eslint:recommended"],
"rules": {
"no-console": 2,
"no-with": 2,
"brace-style": [
2,
"1tbs",
{
"allowSingleLine": true
}
],
"no-mixed-spaces-and-tabs": 2,
"one-var": [
2,
{
"uninitialized": "always",
"initialized": "never"
}
],
"quote-props": [2, "as-needed"],
"key-spacing": [
2,
{
"beforeColon": false,
"afterColon": true
}
],
"space-unary-ops": [
2,
{
"nonwords": false,
"overrides": {}
}
],
"space-before-function-paren": [2, "never"],
"space-in-parens": [2, "never"],
"no-trailing-spaces": 2,
"max-len": [2, 160],
"camelcase": 0,
"curly": [2, "all"],
"keyword-spacing": [2, {}],
"spaced-comment": [2, "always"],
"space-infix-ops": 2,
"space-before-blocks": [2, "always"],
"comma-dangle": 0,
"no-else-return": 0,
"indent": [
2,
2,
{
"SwitchCase": 1
}
],
"linebreak-style": [2, "unix"],
"quotes": [2, "single"]
}
}

182
.gitignore vendored Normal file
View File

@ -0,0 +1,182 @@
# Created by .ignore support plugin (hsz.mobi)
### Archives template
# It's better to unpack these files and commit the raw source because
# git has its own built in compression methods.
*.7z
*.jar
*.rar
*.zip
*.gz
*.bzip
*.bz2
*.xz
*.lzma
*.cab
#packing-only formats
*.iso
*.tar
#package management formats
*.dmg
*.xpi
*.gem
*.egg
*.deb
*.rpm
*.msi
*.msm
*.msp
### Windows template
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# Windows shortcuts
*.lnk
### OSX template
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
*.iml
## Directory-based project format:
.idea/
# if you remove the above rule, at least ignore the following:
# User-specific stuff:
# .idea/workspace.xml
# .idea/tasks.xml
# .idea/dictionaries
# Sensitive or high-churn files:
# .idea/dataSources.ids
# .idea/dataSources.xml
# .idea/sqlDataSources.xml
# .idea/dynamic.xml
# .idea/uiDesigner.xml
# Gradle:
# .idea/gradle.xml
# .idea/libraries
# Mongo Explorer plugin:
# .idea/mongoSettings.xml
## File-based project format:
*.ipr
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
### Node template
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directory
# https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git
node_modules
bower_components
### VisualStudioCode template
.settings
### Xcode template
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## Build generated
build/
DerivedData
## Various settings
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
## Other
*.xccheckout
*.moved-aside
*.xcuserstate
dist
.nyc_output
.prettierc

6
.prettierrc Normal file
View File

@ -0,0 +1,6 @@
{
"semi": true,
"trailingComma": "none",
"singleQuote": true,
"printWidth": 120
}

1944
out.json Normal file

File diff suppressed because it is too large Load Diff

6468
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

57
package.json Normal file
View File

@ -0,0 +1,57 @@
{
"name": "@rakh/utils",
"version": "2.0.0",
"main": "dist/commonjs/index.js",
"module": "dist/es/index.js",
"jsnext:main": "dist/es/index.js",
"scripts": {
"release": "vik patch -t",
"clean": "rm -rf dist",
"prepublish": "npm run clean && npm run compile",
"test": "jest --coverage && npm run compile",
"compile:es": "tsc --declaration true --declarationMap true --module esnext --outDir './dist/es'",
"compile:commonjs": "tsc --declaration true --declarationMap true --module commonjs --outDir './dist/commonjs'",
"compile": "npm run clean && npm run compile:es && npm run compile:commonjs"
},
"author": "Martin Donnelly",
"license": "ISC",
"dependencies": {
"save": "^2.4.0",
"typedoc": "^0.19.2"
},
"devDependencies": {
"@types/jest": "^26.0.15",
"@types/sinon": "^9.0.8",
"jest": "^26.6.3",
"marked": "^1.2.4",
"prettier": "^2.1.2",
"sinon": "^9.2.1",
"ts-jest": "^26.4.4",
"ts-node": "^9.0.0",
"typescript": "^4.0.5",
"vik": "^0.4.0"
},
"description": "",
"jest": {
"transform": {
"^.+\\.tsx?$": "ts-jest"
},
"testRegex": "/ts-src/.*.test.(jsx?|tsx?)$",
"testPathIgnorePatterns": [
"/node_modules/",
"/dist/"
],
"collectCoverageFrom": [
"ts-src/**/*.tsx",
"ts-src/**/*.ts"
],
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"jsx",
"json",
"node"
]
}
}

0
readme.MD Normal file
View File

31
rollup.config.js Normal file
View File

@ -0,0 +1,31 @@
/**
* Created by WebStorm.
* User: martin
* Date: 01/06/2020
* Time: 15:04
*/
import pkg from './package.json';
import resolve from "@rollup/plugin-node-resolve";
import commonjs from "@rollup/plugin-commonjs";
import {terser} from "rollup-plugin-terser";
export default {
input: 'src/index.js',
output: [{
file: pkg.main,
format: 'cjs',
name: pkg.name
},{
file: pkg.module,
format: 'es',
name: pkg.name
}],
plugins:[resolve(), commonjs()
,terser()
],
external:[
...Object.keys(pkg.dependencies || {}),
...Object.keys(pkg.peerDependencies || {}),
]
};

2
scripts/build.sh Executable file
View File

@ -0,0 +1,2 @@
tsc --declaration true --declarationMap true --module esnext --outDir '../dist/es'
tsc --declaration true --declarationMap true --module commonjs --outDir '../dist/commonjs'

12
scripts/create-index.js Normal file
View File

@ -0,0 +1,12 @@
const fs = require('fs');
const path = require('path');
const content = fs
.readdirSync(path.join(__dirname, '../ts-src'))
.filter((name) => name.endsWith('.ts') && !name.includes('test.ts') && !name.startsWith('_'))
.map((name) => name.replace('.ts', ''))
.filter((name) => name !== 'index')
.map((name) => `export * from './${name}';`)
.join('\n');
fs.writeFileSync(path.join(__dirname, '../ts-src/index.ts'), content);

364
scripts/def.json Normal file
View File

@ -0,0 +1,364 @@
[
{
"name": "arrayFromObj",
"category": "",
"description": "<p>Create an array from an Object using specified fields</p>\n",
"methods": [
{
"tag": null,
"signature": "",
"category": "",
"indexed": false,
"pipeable": false,
"example": "U.arrayFromObj({ a: 1, b: 2 }, ['a', 'b']) // => [1, 2]\n",
"args": [
{
"name": "jsonObj",
"description": "The Original object"
},
{
"name": "wantedFields",
"description": "The required fields\n"
}
],
"returns": {
"name": "Array",
"description": ""
}
}
]
},
{
"name": "debounce",
"category": "",
"description": "<p>Debounce the calling of a function</p>\n",
"methods": [
{
"tag": null,
"signature": "U.debounce(fn, time)\n",
"category": "",
"indexed": false,
"pipeable": false,
"example": "",
"args": [
{
"name": "fn",
"description": "The function to be debounced"
},
{
"name": "time",
"description": "How long to wait"
}
],
"returns": {
"name": "Object",
"description": ""
}
}
]
},
{
"name": "distance",
"category": "",
"description": "<p>Calculate the distance between two lat long points</p>\n",
"methods": [
{
"tag": null,
"signature": "U.distance(lat1, long1, lat2, long2)\n",
"category": "",
"indexed": false,
"pipeable": false,
"example": "distance(1, 1, 2, 2) // => 157.22543203805722;\n",
"args": [
{
"name": "lat1"
},
{
"name": "lon1"
},
{
"name": "lat2"
},
{
"name": "lon2",
"description": "\n"
}
],
"returns": {
"name": "number",
"description": ""
}
},
{
"tag": null,
"signature": "U.distance(latLong1, latLong2)\n",
"category": "",
"indexed": false,
"pipeable": false,
"example": "const a: U.LatLong = new LatLong(1, 1)\nconst b: U.LatLong = new LatLong(2, 2)\nU.distance(a, b) // => 157.22543203805722\n",
"args": [
{
"name": "latLong1"
},
{
"name": "latLong2",
"description": "\n"
}
],
"returns": {
"name": "number",
"description": ""
}
}
]
},
{
"name": "extractFromObj",
"category": "",
"description": "<p>Extract an object from another object using specific fields</p>\n",
"methods": [
{
"tag": null,
"signature": "U.extractFromObj(jsonObj, wantedFields)\n",
"category": "",
"indexed": false,
"pipeable": false,
"example": "U.extractFromObj({ a: 1, b: 2 }, ['a']) // => { a: 1 }\n",
"args": [
{
"name": "jsonObj",
"description": "The source object"
},
{
"name": "wantedFields",
"description": "The required fields"
}
],
"returns": {
"name": "Object",
"description": ""
}
}
]
},
{
"name": "hasOwn",
"category": "",
"description": "<p>Check if an object has an property</p>\n",
"methods": [
{
"tag": null,
"signature": "",
"category": "",
"indexed": false,
"pipeable": false,
"example": "U.hasOwn({ bob: '1' }, 'bob') // => true\n",
"args": [
{
"name": "obj",
"description": "The source object"
},
{
"name": "prop",
"description": "The required property"
}
],
"returns": {
"name": "boolean",
"description": ""
}
}
]
},
{
"name": "hourFloor",
"category": "",
"description": "<p>Get the hour floor as a Base 32 string</p>\n",
"methods": [
{
"tag": null,
"signature": "",
"category": "",
"indexed": false,
"pipeable": false,
"example": "U.hourFloor(1605532173) // => '1fnp540'\n",
"args": [
{
"name": "timestamp",
"description": "The timestamp as a number"
}
],
"returns": {
"name": "string",
"description": ""
}
}
]
},
{
"name": "isEmpty",
"category": "",
"description": "<p>Check if an object is empty</p>\n",
"methods": [
{
"tag": null,
"signature": "",
"category": "",
"indexed": false,
"pipeable": false,
"example": "U.isEmpty({}) // => true\nU.isEmpty({ bob: true }) // => false\n",
"args": [
{
"name": "obj",
"description": "The object being checked\n"
}
],
"returns": {
"name": "boolean",
"description": ""
}
}
]
},
{
"name": "maybePluralize",
"category": "",
"description": "<p>Maybe pluralize a count:</p>\n",
"methods": [
{
"tag": null,
"signature": "U.maybePluralize(number, noun, suffix)\n",
"category": "",
"indexed": false,
"pipeable": false,
"example": "U.maybePluralize(1, 'Bag', 's') // => 1 Bag\nU.maybePluralize(5, 'Bag', 's') // => 5 Bags\n",
"args": [
{
"name": "count",
"description": "the value counting"
},
{
"name": "noun",
"description": "the name of the value"
},
{
"name": "suffix",
"description": "the suffix"
}
],
"returns": {
"name": "string",
"description": ""
}
}
]
},
{
"name": "once",
"category": "",
"description": "<p>Trigger a function once and then prevent it from triggering again</p>\n",
"methods": [
{
"tag": null,
"signature": "U.once(fn)\n",
"category": "",
"indexed": false,
"pipeable": false,
"example": "",
"args": [
{
"name": "fn",
"description": "\n"
}
],
"returns": {
"name": "Object",
"description": ""
}
}
]
},
{
"name": "partOfDay",
"category": "",
"description": "<p>Get a string phrase for the current time of day</p>\n",
"methods": [
{
"tag": null,
"signature": "U.partOfDay(timeString, today)\n",
"category": "",
"indexed": false,
"pipeable": false,
"example": "U.partOfDay('13:00') // => 'Afternoon'\n",
"args": [
{
"name": "timeString"
},
{
"name": "today",
"description": "\n"
}
],
"returns": {
"name": "string",
"description": ""
}
}
]
},
{
"name": "throttle",
"category": "",
"description": "<p>Throttle the calling of a function</p>\n",
"methods": [
{
"tag": null,
"signature": "U.throttle(callback, limit)\n",
"category": "",
"indexed": false,
"pipeable": false,
"example": "",
"args": [
{
"name": "callback"
},
{
"name": "limit",
"description": "\n"
}
],
"returns": {
"name": "Object",
"description": ""
}
}
]
},
{
"name": "toHour",
"category": "",
"description": "<p>Return the number of Milliseconds to the hour for the supplied timestamp</p>\n",
"methods": [
{
"tag": null,
"signature": "U.toHour(currentTimsestamp, extra)\n",
"category": "",
"indexed": false,
"pipeable": false,
"example": "U.toHour('13:00') // => 1605532173\n",
"args": [
{
"name": "currentTimsestamp"
},
{
"name": "extra"
}
],
"returns": {
"name": "number",
"description": ""
}
}
]
}
]

119
scripts/generate.ts Normal file
View File

@ -0,0 +1,119 @@
import * as fs from 'fs';
import marked from 'marked';
import prettier from 'prettier';
import data from '../out.json';
export interface MethodDoc {
tag: string;
signature: string;
example: string;
args: JsTagProps[];
returns: JsTagProps;
}
export interface FnDocProps {
name: string;
description: string;
category: string;
methods: MethodDoc[];
}
export interface JsTagProps {
name: string;
description: string;
}
function getReturnType(signature) {
const type = signature.type.type;
if (type === 'intrinsic') {
return signature.type.name;
}
if (type === 'array') {
return 'Array';
}
return 'Object';
}
const ret = data.children
.map((method: any) => {
const target =
method.children &&
method.children.filter(
(item: any) =>
(item.kindString === 'Function' || item.kindString === 'Module') &&
item.signatures &&
item.flags.isExported
)[0];
if (!target) {
return;
}
console.log('processing', target.name);
const signatures = target.signatures.filter(s => s.comment);
if (!signatures.length) {
return null;
}
const comment = signatures[0].comment;
return {
name: target.name,
category: '',
description: marked(
(comment.shortText + '\n' + (comment.text || '')).trim(),
{ breaks: true }
),
methods: signatures.map(signature => {
const tags = signature.comment.tags || target.comment.tags || [];
const isDataFirst = tags.find(item => item.tag === 'data_first');
const isDataLast = tags.find(item => item.tag === 'data_last');
const getTag = name =>
tags
.filter(item => item.tag === name)
.map(item => item.text.trim())
.join('\n');
const hasTag = name => !!tags.find(item => item.tag === name);
function getExample() {
let str = getTag('example');
if (str) {
return prettier.format(str, {
semi: false,
singleQuote: true,
parser: 'typescript',
});
}
str = getTag('example-raw');
return str
.split('\n')
.map(str => str.replace(/^ /, ''))
.join('\n');
}
const parameters = signature.parameters || [];
return {
tag: isDataFirst ? 'Data First' : isDataLast ? 'Data Last' : null,
signature: prettier.format(getTag('signature'), {
semi: false,
singleQuote: true,
parser: 'typescript',
}),
category: getTag('category'),
indexed: hasTag('indexed'),
pipeable: hasTag('pipeable'),
example: getExample(),
args: parameters.map((item: any) => ({
name: item.name,
description: item.comment && item.comment.text,
})),
returns: {
name: getReturnType(signature),
description: getTag('returns'),
},
};
}),
};
})
.filter(item => item)
.map(item => {
item.category = item.methods[0].category;
return item;
});
fs.writeFileSync('./def.json', JSON.stringify(ret, null, 2));

7
scripts/readme.js Normal file
View File

@ -0,0 +1,7 @@
const fs = require('fs');
const path = require('path');
const marked = require('marked');
const md = fs.readFileSync(path.join(__dirname, '../README.md'), 'utf8');
console.log(marked(md));

66
scripts/tsconfig.json Normal file
View File

@ -0,0 +1,66 @@
{
"compilerOptions": {
/* Basic Options */
"target":
"es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */,
"module":
"commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
"resolveJsonModule": true,
"lib": [
"es6",
"es2017.object"
] /* Specify library files to be included in the compilation. */,
// "allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
// "declaration": true, /* Generates corresponding '.d.ts' file. */
// "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
// "outDir": "./", /* Redirect output structure to the directory. */
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
/* Strict Type-Checking Options */
"strict": true /* Enable all strict type-checking options. */,
"noImplicitAny": false /* Raise error on expressions and declarations with an implied 'any' type. */,
"strictNullChecks": false /* Enable strict null checks. */,
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
/* Additional Checks */
"noUnusedLocals": true /* Report errors on unused locals. */,
"noUnusedParameters": true /* Report errors on unused parameters. */,
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
"noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */,
/* Module Resolution Options */
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
// "typeRoots": [], /* List of folders to include type definitions from. */
// "types": [], /* Type declaration files to be included in compilation. */
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
/* Source Map Options */
// "sourceRoot": "./", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
// "mapRoot": "./", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
/* Experimental Options */
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
}
}

54
src/LocalStorage.js Normal file
View File

@ -0,0 +1,54 @@
/**
* Created by WebStorm.
* User: martin
* Date: 01/06/2020
* Time: 14:23
*/
function supportsLocalStorage() {
try {
if (!localStorage)return false;
else return true;
// May only need the above simple test
// - old versions of firefox may cause problem?
// return 'localStorage' in window && window['localStorage']!==null;
}
catch(e) {
return false;
}
}
let LocalStorage = {};
if (supportsLocalStorage())
LocalStorage = {
'set':function ( i, v ) {
if (typeof v === 'object' || typeof v === 'array')
localStorage[i] = JSON.stringify(v);
else
localStorage[i] = v;
},
'get':function ( i ) {
return localStorage[i];
},
'exists':function(i) {
return !(typeof(localStorage[i]) === 'undefined');
}
};
else
LocalStorage = {
'save':function ( i, v ) {
document.cookie = `${i }=${ encodeURIComponent(v)}`;
},
'load':function ( i ) {
var s = `; ${ document.cookie };`,
p = s.indexOf(`; ${ i }=`);
if (p < 0)return '';
p = p + i.length + 3;
var p2 = s.indexOf(';', p + 1);
return decodeURIComponent(s.substring(p, p2));
}
};
module.exports = LocalStorage;

82
src/general/array.js Normal file
View File

@ -0,0 +1,82 @@
// Hive Colony Framework
// Copyright (c) 2008-2020 Hive Solutions Lda.
//
// This file is part of Hive Colony Framework.
//
// Hive Colony Framework is free software: you can redistribute it and/or modify
// it under the terms of the Apache License as published by the Apache
// Foundation, either version 2.0 of the License, or (at your option) any
// later version.
//
// Hive Colony Framework is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// Apache License for more details.
//
// You should have received a copy of the Apache License along with
// Hive Colony Framework. If not, see <http://www.apache.org/licenses/>.
// __author__ = João Magalhães <joamag@hive.pt>
// __version__ = 1.0.0
// __revision__ = $LastChangedRevision$
// __date__ = $LastChangedDate$
// __copyright__ = Copyright (c) 2008-2020 Hive Solutions Lda.
// __license__ = Apache License, Version 2.0
var _global = typeof global === "undefined" ? window : global;
var Array = (_global.Array = _global.Array || {});
if (typeof Array.prototype.indexOf === "undefined") {
Array.prototype.indexOf = function(obj, start) {
for (var i = start || 0, j = this.length; i < j; i++) {
if (this[i] === obj) {
return i;
}
}
return -1;
};
}
if (typeof Array.prototype.indexOfObject === "undefined") {
Array.prototype.indexOfObject = function(obj) {
var isObject = typeof obj === "object";
if (!isObject) {
return this.indexOf(obj);
}
for (var index = 0; index < this.length; index++) {
var valid = true;
var _obj = this[index];
for (var key in obj) {
var value = obj[key];
var _value = _obj[key];
if (value === _value) {
continue;
}
valid = false;
break;
}
if (!valid) {
continue;
}
return index;
}
return -1;
};
}
if (typeof Array.prototype.isIn === "undefined") {
Array.prototype.isIn = function(obj) {
return this.indexOf(obj) !== -1;
};
}
if (typeof module !== "undefined") {
module.exports = {
Array: Array
};
}

186
src/general/browser.js Normal file
View File

@ -0,0 +1,186 @@
// Hive Colony Framework
// Copyright (c) 2008-2020 Hive Solutions Lda.
//
// This file is part of Hive Colony Framework.
//
// Hive Colony Framework is free software: you can redistribute it and/or modify
// it under the terms of the Apache License as published by the Apache
// Foundation, either version 2.0 of the License, or (at your option) any
// later version.
//
// Hive Colony Framework is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// Apache License for more details.
//
// You should have received a copy of the Apache License along with
// Hive Colony Framework. If not, see <http://www.apache.org/licenses/>.
// __author__ = João Magalhães <joamag@hive.pt>
// __version__ = 1.0.0
// __revision__ = $LastChangedRevision$
// __date__ = $LastChangedDate$
// __copyright__ = Copyright (c) 2008-2020 Hive Solutions Lda.
// __license__ = Apache License, Version 2.0
var _global = typeof global === "undefined" ? window : global;
var BrowserDetect = (_global.BrowserDetect = _global.BrowserDetect || {});
var navigator = (_global.navigator = _global.navigator || {});
var frame = _global;
BrowserDetect = function() {
BrowserDetect.browser =
BrowserDetect.searchString(BrowserDetect.DATA_BROWSER) || "Unknown browser";
BrowserDetect.version =
BrowserDetect.searchVersion(navigator.userAgent) ||
BrowserDetect.searchVersion(navigator.appVersion) ||
"Unknown version";
BrowserDetect.os = BrowserDetect.searchString(BrowserDetect.DATA_OS) || "Unknown OS";
};
BrowserDetect.searchString = function(data) {
for (var index = 0; index < data.length; index++) {
var dataString = data[index].string;
var dataProp = data[index].prop;
BrowserDetect.versionSearchString = data[index].versionSearch || data[index].identity;
if (dataString) {
if (dataString.indexOf(data[index].subString) !== -1) {
return data[index].identity;
}
} else if (dataProp) {
return data[index].identity;
}
}
};
BrowserDetect.searchVersion = function(dataString) {
// in case the provided data string is not a valid one
// returns an invalid value immediately
if (!dataString) {
return null;
}
// tries to search for the version search string
var index = dataString.indexOf(BrowserDetect.versionSearchString);
// in case the version search string is not found
// returns immediately, no version could be detected
if (index === -1) {
return null;
}
// returns the float version of the discovered number
// string in the "middle" of the data string
return parseFloat(dataString.substring(index + BrowserDetect.versionSearchString.length + 1));
};
BrowserDetect.DATA_BROWSER = [
{
string: navigator.userAgent,
identity: "Edge",
subString: "Edge",
versionSearch: "Edge"
},
{
string: navigator.userAgent,
identity: "Chrome",
subString: "Chrome"
},
{
string: navigator.userAgent,
identity: "OmniWeb",
subString: "OmniWeb",
versionSearch: "OmniWeb/"
},
{
string: navigator.vendor,
identity: "Safari",
subString: "Apple",
versionSearch: "Version"
},
{
prop: frame.opera,
identity: "Opera"
},
{
string: navigator.vendor,
identity: "iCab",
subString: "iCab"
},
{
string: navigator.vendor,
identity: "Konqueror",
subString: "KDE"
},
{
string: navigator.userAgent,
identity: "Firefox",
subString: "Firefox"
},
{
string: navigator.vendor,
identity: "Camino",
subString: "Camino"
},
{
string: navigator.userAgent,
identity: "Netscape",
subString: "Netscape"
},
{
string: navigator.userAgent,
identity: "Explorer",
subString: "MSIE",
versionSearch: "MSIE"
},
{
string: navigator.userAgent,
identity: "Explorer",
subString: "Trident",
versionSearch: "rv"
},
{
string: navigator.userAgent,
identity: "Mozilla",
subString: "Gecko",
versionSearch: "rv"
},
{
string: navigator.userAgent,
identity: "Netscape",
subString: "Mozilla",
versionSearch: "Mozilla"
}
];
BrowserDetect.DATA_OS = [
{
string: navigator.platform,
identity: "Windows",
subString: "Win"
},
{
string: navigator.platform,
identity: "Mac",
subString: "Mac"
},
{
string: navigator.userAgent,
identity: "iPhone/iPod",
subString: "iPhone"
},
{
string: navigator.platform,
identity: "Linux",
subString: "Linux"
}
];
// initializes the browser detection system
BrowserDetect();
if (typeof module !== "undefined") {
module.exports = {
BrowserDetect: BrowserDetect
};
}

View File

@ -0,0 +1,63 @@
// Hive Colony Framework
// Copyright (c) 2008-2020 Hive Solutions Lda.
//
// This file is part of Hive Colony Framework.
//
// Hive Colony Framework is free software: you can redistribute it and/or modify
// it under the terms of the Apache License as published by the Apache
// Foundation, either version 2.0 of the License, or (at your option) any
// later version.
//
// Hive Colony Framework is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// Apache License for more details.
//
// You should have received a copy of the Apache License along with
// Hive Colony Framework. If not, see <http://www.apache.org/licenses/>.
// __author__ = João Magalhães <joamag@hive.pt>
// __version__ = 1.0.0
// __revision__ = $LastChangedRevision$
// __date__ = $LastChangedDate$
// __copyright__ = Copyright (c) 2008-2020 Hive Solutions Lda.
// __license__ = Apache License, Version 2.0
var _global = typeof global === "undefined" ? window : global;
var ClassReference = (_global.ClassReference = _global.ClassReference || {});
/**
* Returns the class reference correspondent to the provided class name.
*
* @param {String}
* className Name of the class.
* @return {Class} Class reference.
*/
ClassReference.getClassReference = function(className) {
// splits the class name
var nameTokens = className.split(".");
// retrieves the initial reference (the window)
var reference = window;
// starts the token value
var tokenValue = null;
// iterates over the tokens lenght
for (var offset = 0; offset < nameTokens.length; offset++) {
// retrieves the current token value
tokenValue = nameTokens[offset];
// updates the current reference
reference = reference[tokenValue];
}
// returns the reference
return reference;
};
if (typeof module !== "undefined") {
module.exports = {
ClassReference: ClassReference
};
}

213
src/general/cookie.js Normal file
View File

@ -0,0 +1,213 @@
// Hive Colony Framework
// Copyright (c) 2008-2020 Hive Solutions Lda.
//
// This file is part of Hive Colony Framework.
//
// Hive Colony Framework is free software: you can redistribute it and/or modify
// it under the terms of the Apache License as published by the Apache
// Foundation, either version 2.0 of the License, or (at your option) any
// later version.
//
// Hive Colony Framework is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// Apache License for more details.
//
// You should have received a copy of the Apache License along with
// Hive Colony Framework. If not, see <http://www.apache.org/licenses/>.
// __author__ = João Magalhães <joamag@hive.pt>
// __version__ = 1.0.0
// __revision__ = $LastChangedRevision$
// __date__ = $LastChangedDate$
// __copyright__ = Copyright (c) 2008-2020 Hive Solutions Lda.
// __license__ = Apache License, Version 2.0
var _global = typeof global === "undefined" ? window : global;
var Cookie = (_global._Cookie = _global.Cookie || {});
/**
* Constructor of the class.
*/
Cookie = function(name) {
this.name = name || null;
this.value = null;
this.timeoutTime = null;
this.secure = false;
};
/**
* Saves the cookie serializing it into the browser native form.
*/
Cookie.prototype.save = function() {
// retrieves the cookie attributes
var cookieName = this.name;
var cookieValue = this.value;
var cookieTimeoutTime = this.timeoutTime;
var cookieDomain = this.secure;
var cookieSecure = this.secure;
// creates the cookie final value
var cookieFinalValue =
cookieName +
"=" +
escape(cookieValue) +
(cookieTimeoutTime ? ";expires=" + new Date(cookieTimeoutTime * 1000).toUTCString() : "") +
(cookieDomain ? ";domain=" + cookieDomain : "") +
(cookieSecure ? ";secure" : "");
// sets the cookie final value in the document
document.cookie = cookieFinalValue;
};
/**
* Loads the current cookie from the cookie storage, using the cookie name as
* reference for the loading process.
*
* @param {String} cookie If provided overrides the default provider of the
* cookie (from the document).
* @return {Boolean} The result of the loading.
*/
Cookie.prototype.load = function(cookie) {
// tries to retrieve the default cookie string value
// that is going to be parsed
cookie = cookie || document.cookie;
// retrieves the cookies list, by splitting the
// list arround the typical character
var cookiesList = cookie.split(";");
// sets the cookie found flag
var cookieFound = false;
// iterates over all the cookies in the list of
// cookies retrieves from the string
for (var index = 0; index < cookiesList.length; index++) {
// retrives the reference to the current value
// (cookie) in iteration
var value = cookiesList[index];
// splits the cookie value to get the name and the value
var cookieSplitted = value.split("=");
// tims left/right whitespace in the cookie name
var cookieName = cookieSplitted[0].replace(/^\s+|\s+$/g, "");
// in case it's the same cookie name
if (cookieName === this.name) {
// sets the cookie found flag
cookieFound = true;
// in case there is a valid cookie value
if (cookieSplitted.length > 1) {
this.value = unescape(cookieSplitted[1].replace(/^\s+|\s+$/g, ""));
}
// breaks the current loop
break;
}
}
return cookieFound;
};
/**
* Retrieves the name.
*
* @return {String} The name.
*/
Cookie.prototype.getName = function() {
return this.name;
};
/**
* Sets the name.
*
* @param {String}
* name The name.
*/
Cookie.prototype.setName = function(name) {
this.name = name;
};
/**
* Retrieves the value.
*
* @return {String} The value.
*/
Cookie.prototype.getValue = function() {
return this.value;
};
/**
* Sets the value.
*
* @param {String}
* value The value.
*/
Cookie.prototype.setValue = function(value) {
this.value = value;
};
/**
* Retrieves the timeout time.
*
* @return {Date} The timeout time.
*/
Cookie.prototype.getTimeoutTime = function() {
return this.timeoutTime;
};
/**
* Sets the timeout time.
*
* @param {Date}
* timeoutTime The timeout time.
*/
Cookie.prototype.setTimeoutTime = function(timeoutTime) {
this.timeoutTime = timeoutTime;
};
/**
* Retrieves the domain.
*
* @return {String} The domain.
*/
Cookie.prototype.getDomain = function() {
return this.domain;
};
/**
* Sets the domain.
*
* @param {String}
* domain The domain.
*/
Cookie.prototype.setDomain = function(domain) {
this.domain = domain;
};
/**
* Retrieves the secure.
*
* @return {String} The secure.
*/
Cookie.prototype.getSecure = function() {
return this.secure;
};
/**
* Sets the secure.
*
* @param {String}
* secure The secure.
*/
Cookie.prototype.setSecure = function(secure) {
this.secure = secure;
};
if (typeof module !== "undefined") {
module.exports = {
Cookie: Cookie
};
}

136
src/general/date.js Normal file
View File

@ -0,0 +1,136 @@
// Hive Colony Framework
// Copyright (c) 2008-2020 Hive Solutions Lda.
//
// This file is part of Hive Colony Framework.
//
// Hive Colony Framework is free software: you can redistribute it and/or modify
// it under the terms of the Apache License as published by the Apache
// Foundation, either version 2.0 of the License, or (at your option) any
// later version.
//
// Hive Colony Framework is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// Apache License for more details.
//
// You should have received a copy of the Apache License along with
// Hive Colony Framework. If not, see <http://www.apache.org/licenses/>.
// __author__ = João Magalhães <joamag@hive.pt>
// __version__ = 1.0.0
// __revision__ = $LastChangedRevision$
// __date__ = $LastChangedDate$
// __copyright__ = Copyright (c) 2008-2020 Hive Solutions Lda.
// __license__ = Apache License, Version 2.0
var _global = typeof global === "undefined" ? window : global;
var Date = (_global.Date = _global.Date || {});
/**
* Parses the given date string (without utc offset) retrieving an utc timestamp
* representing the given date.
*
* @param {String}
* dateString The date string (without utc offset) to be parsed for
* retrieval of the timestamp.
* @return {Integer} The integer representing the utc timestamp in miliseconds.
*/
Date.parseUtc = function(dateString) {
// creats a new date object
var date = new Date(dateString);
// retrieves the time zone name from the date time zone structure
var dateTimeZoneStructure = date.getTimeZoneStructure();
var timeZoneName = dateTimeZoneStructure.time_zone_name;
// creates the date string from the date string and the time zone name
// or it uses the new date
dateString = dateString ? dateString + " " + timeZoneName : date;
// parses the date string retrieving the timestamp
// (in miliseconds) in utc
var timestamp = Date.parse(dateString);
// returns the timestamp (in utc)
return timestamp;
};
/**
* Retrieves the time zone structure for the current default time zone.
*
* @return {Map} The time zone structure for the current default time zone.
*/
Date.prototype.getTimeZoneStructure = function() {
// creates the index variable that is going to be used
// in the internal function iteration cycles
var index = 0;
// retrieves the javascript utc offset
var javascriptUtcOffset = this.getTimezoneOffset() * -1;
// calculates the real utc offset from the javascript one
var utcOffset = javascriptUtcOffset * 60;
// calculates the absolute javascript utc offset
var absoluteJavascriptUtcOffset = Math.abs(javascriptUtcOffset);
// calculates the utc offset in hours
var utcOffsetHours = Math.floor(absoluteJavascriptUtcOffset / 60);
// calculates the utc offset in minutes
var utcOffsetMinutes = absoluteJavascriptUtcOffset % 60;
// converts the utc offset in hours to string
var utcOffsetHoursString = utcOffsetHours.toString();
// converts the utc offset in minutes to string
var utcOffsetMinutesString = utcOffsetMinutes.toString();
// retrieves the utc offset in hours string length
var utcOffsetHoursStringLength = utcOffsetHoursString.length;
// retrieves the utc offset in minutes string length
var utcOffsetMinutesStringLength = utcOffsetMinutesString.length;
// iterates over the remaining digits (while less than two)
for (index = utcOffsetHoursStringLength; index < 2; index++) {
// prepends a zero to the utc offset in hours string
utcOffsetHoursString = "0" + utcOffsetHoursString;
}
// iterates over the remaining digits (while less than two)
for (index = utcOffsetMinutesStringLength; index < 2; index++) {
// prepends a zero to the utc offset in minutes string
utcOffsetMinutesString = "0" + utcOffsetMinutesString;
}
// in case the utc offset is greater or equal to zero
if (utcOffset >= 0) {
// prepends the plus operator to the utc offset in hours string
utcOffsetHoursString = "+" + utcOffsetHoursString;
} else {
// prepends the minus operator to the utc offset in hours string
utcOffsetHoursString = "-" + utcOffsetHoursString;
}
// retrieves the time zone name
var timeZoneName = "GMT" + utcOffsetHoursString + utcOffsetMinutesString;
// creates the time zone structure
var timeZoneStructure = {};
// sets the utc offset value in the time zone structure
timeZoneStructure.utc_offset = utcOffset;
// sets the time zone name in the time zone structure
timeZoneStructure.time_zone_name = timeZoneName;
// returns the time zone structure
return timeZoneStructure;
};
if (typeof module !== "undefined") {
module.exports = {
Date: Date
};
}

25
src/general/index.js Normal file
View File

@ -0,0 +1,25 @@
const array = require("./array");
const browser = require("./browser");
const classReference = require("./class_reference");
const cookie = require("./cookie");
const date = require("./date");
const math = require("./math");
const mobile = require("./mobile");
const namespace = require("./namespace");
const number = require("./number");
const object = require("./object");
const root = require("./root");
const stackTrace = require("./stack_trace");
Object.assign(module.exports, array);
Object.assign(module.exports, browser);
Object.assign(module.exports, classReference);
Object.assign(module.exports, cookie);
Object.assign(module.exports, date);
Object.assign(module.exports, math);
Object.assign(module.exports, mobile);
Object.assign(module.exports, namespace);
Object.assign(module.exports, number);
Object.assign(module.exports, object);
Object.assign(module.exports, root);
Object.assign(module.exports, stackTrace);

39
src/general/math.js Normal file
View File

@ -0,0 +1,39 @@
// Hive Colony Framework
// Copyright (c) 2008-2020 Hive Solutions Lda.
//
// This file is part of Hive Colony Framework.
//
// Hive Colony Framework is free software: you can redistribute it and/or modify
// it under the terms of the Apache License as published by the Apache
// Foundation, either version 2.0 of the License, or (at your option) any
// later version.
//
// Hive Colony Framework is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// Apache License for more details.
//
// You should have received a copy of the Apache License along with
// Hive Colony Framework. If not, see <http://www.apache.org/licenses/>.
// __author__ = João Magalhães <joamag@hive.pt>
// __version__ = 1.0.0
// __revision__ = $LastChangedRevision$
// __date__ = $LastChangedDate$
// __copyright__ = Copyright (c) 2008-2020 Hive Solutions Lda.
// __license__ = Apache License, Version 2.0
var _global = typeof global === "undefined" ? window : global;
var Math = (_global.Math = _global.Math || {});
if (typeof Math.log10 === "undefined") {
Math.log10 = function(value) {
return Math.log(value) / Math.LN10;
};
}
if (typeof module !== "undefined") {
module.exports = {
Math: Math
};
}

125
src/general/mobile.js Normal file
View File

@ -0,0 +1,125 @@
// Hive Colony Framework
// Copyright (c) 2008-2020 Hive Solutions Lda.
//
// This file is part of Hive Colony Framework.
//
// Hive Colony Framework is free software: you can redistribute it and/or modify
// it under the terms of the Apache License as published by the Apache
// Foundation, either version 2.0 of the License, or (at your option) any
// later version.
//
// Hive Colony Framework is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// Apache License for more details.
//
// You should have received a copy of the Apache License along with
// Hive Colony Framework. If not, see <http://www.apache.org/licenses/>.
// __author__ = João Magalhães <joamag@hive.pt>
// __version__ = 1.0.0
// __revision__ = $LastChangedRevision$
// __date__ = $LastChangedDate$
// __copyright__ = Copyright (c) 2008-2020 Hive Solutions Lda.
// __license__ = Apache License, Version 2.0
var _global = typeof global === "undefined" ? window : global;
var Mobile = (_global.Mobile = _global.Mobile || {});
var document = (_global.document = _global.document || {});
/**
* If the mobile touch event propagation structure should performed only under
* a previous validation of tag naming.
*/
Mobile.SAFE = true;
/**
* The list containing the various tags that are considered to be valid for the
* mouse operation events, this is only used in case the safe mode is enabled.
*/
Mobile.VALID = ["DIV", "IMG", "SPAN", "CANVAS"];
Mobile.touchHandler = function(event) {
// retrieves the complete set of touches and uses
// only the first one for type reference
var touches = event.changedTouches;
var first = touches[0];
var type = "";
// switches over the type of touch event associating
// the proper equivalent mouse enve to each of them
switch (event.type) {
case "touchstart":
type = "mousedown";
break;
case "touchmove":
type = "mousemove";
break;
case "touchend":
type = "mouseup";
break;
default:
return;
}
// verifies if the current event is considered to be valid,
// this occurs if the target of the type of the target is
// considered to be valid according to the current rules
var isValid = Mobile.VALID.indexOf(first.target.tagName) === -1;
if (Mobile.SAFE && isValid) {
return;
}
// creates the new mouse event that will emulate the
// touch event that has just been raised, it should
// be completly equivalent to the original touch
var mouseEvent = document.createEvent("MouseEvent");
mouseEvent.initMouseEvent(
type,
true,
true,
window,
1,
first.screenX,
first.screenY,
first.clientX,
first.clientY,
false,
false,
false,
false,
0,
null
);
// dispatches the event to the original target of the
// touch event (pure emulation)
first.target.dispatchEvent(mouseEvent);
};
Mobile.init = function() {
// verifies if the event listener adding is suported
// for the current environment and in case it's not
// returns immediately to avoid errors
if (!document.addEventListener) {
return;
}
// registers the complete set of touch event in the
// document so that proper emulation is possible
document.addEventListener("touchstart", Mobile.touchHandler, true);
document.addEventListener("touchmove", Mobile.touchHandler, true);
document.addEventListener("touchend", Mobile.touchHandler, true);
document.addEventListener("touchcancel", Mobile.touchHandler, true);
};
Mobile.init();
if (typeof module !== "undefined") {
module.exports = {
Mobile: Mobile
};
}

53
src/general/namespace.js Normal file
View File

@ -0,0 +1,53 @@
// Hive Colony Framework
// Copyright (c) 2008-2020 Hive Solutions Lda.
//
// This file is part of Hive Colony Framework.
//
// Hive Colony Framework is free software: you can redistribute it and/or modify
// it under the terms of the Apache License as published by the Apache
// Foundation, either version 2.0 of the License, or (at your option) any
// later version.
//
// Hive Colony Framework is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// Apache License for more details.
//
// You should have received a copy of the Apache License along with
// Hive Colony Framework. If not, see <http://www.apache.org/licenses/>.
// __author__ = João Magalhães <joamag@hive.pt>
// __version__ = 1.0.0
// __revision__ = $LastChangedRevision$
// __date__ = $LastChangedDate$
// __copyright__ = Copyright (c) 2008-2020 Hive Solutions Lda.
// __license__ = Apache License, Version 2.0
var _global = typeof global === "undefined" ? window : global;
var String = (_global.String = _global.String || {});
/**
* Creates a namespace using the current string and the given separator value.
*
* @param {String}
* separator The separator value to be used for splitting the
* namespace.
*/
String.prototype.namespace = function(separator) {
// splits the value arround the separator
var splittedValue = this.split(separator || ".");
splittedValue.inject(window, function(parent, child) {
// sets the object value
var object = (parent[child] = parent[child] || {});
// returns the object
return object;
});
};
if (typeof module !== "undefined") {
module.exports = {
String: String
};
}

145
src/general/number.js Normal file
View File

@ -0,0 +1,145 @@
// Hive Colony Framework
// Copyright (c) 2008-2020 Hive Solutions Lda.
//
// This file is part of Hive Colony Framework.
//
// Hive Colony Framework is free software: you can redistribute it and/or modify
// it under the terms of the Apache License as published by the Apache
// Foundation, either version 2.0 of the License, or (at your option) any
// later version.
//
// Hive Colony Framework is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// Apache License for more details.
//
// You should have received a copy of the Apache License along with
// Hive Colony Framework. If not, see <http://www.apache.org/licenses/>.
// __author__ = João Magalhães <joamag@hive.pt>
// __version__ = 1.0.0
// __revision__ = $LastChangedRevision$
// __date__ = $LastChangedDate$
// __copyright__ = Copyright (c) 2008-2020 Hive Solutions Lda.
// __license__ = Apache License, Version 2.0
var _global = typeof global === "undefined" ? window : global;
var Number = (_global.Number = _global.Number || {});
Number.SYMBOLS = {
EUR: ["€", 1],
USD: ["$", -1],
GBP: ["£", -1],
BRL: ["R$", -1],
CAD: ["$", -1],
AUD: ["$", -1],
JPY: ["¥", -1],
RUB: ["₽", 1],
KRW: ["₩", -1],
CHF: ["fr.", 1],
SGD: ["$", -1],
MXN: ["$", -1],
DKK: ["kr.", 1],
SEK: ["kr.", 1],
PLN: ["zł", 1],
TWD: ["NT$", -1]
};
Number.DECIMAL_PLACES = {
EUR: 2,
USD: 2,
GBP: 2,
BRL: 2,
CAD: 2,
AUD: 2,
JPY: 0,
RUB: 2,
KRW: 0,
CHF: 2,
SGD: 2,
MXN: 2,
DKK: 2,
SEK: 2,
PLN: 2,
TWD: 2
};
Number.SEPARATOR = {
EUR: ",",
USD: ".",
GBP: ".",
BRL: ",",
CAD: ".",
AUD: ".",
JPY: ".",
RUB: ",",
KRW: ".",
CHF: ".",
SGD: ".",
MXN: ".",
DKK: ".",
SEK: ",",
PLN: "."
};
Number.THOUSANDS = {
EUR: " ",
USD: ",",
GBP: ",",
BRL: ".",
CAD: ",",
AUD: ",",
JPY: ",",
RUB: " ",
KRW: ",",
CHF: ",",
SGD: ",",
MXN: ",",
DKK: ",",
SEK: ".",
PLN: " ",
TWD: ","
};
Number.prototype.formatMoney = function(places, separator, thousands, currency, useSymbol) {
var number = this;
var defaultPlaces = Number.DECIMAL_PLACES[currency];
var defaultSeparator = Number.SEPARATOR[currency];
var defaultThousands = Number.THOUSANDS[currency];
defaultPlaces = defaultPlaces === undefined ? 2 : defaultPlaces;
defaultSeparator = defaultSeparator === undefined ? "." : defaultSeparator;
defaultThousands = defaultThousands === undefined ? "," : defaultThousands;
places = isNaN(parseInt(places)) ? defaultPlaces : places;
separator = separator === null || separator === undefined ? defaultSeparator : separator;
thousands = thousands === null || thousands === undefined ? defaultThousands : thousands;
var signal = number < 0 ? "-" : "";
var integer = parseInt(Math.abs(+number || 0).toFixed(places)) + "";
var remaining = integer.length;
remaining = remaining > 3 ? remaining % 3 : 0;
var money = signal;
money += remaining ? integer.substr(0, remaining) + thousands : "";
money += integer.substr(remaining).replace(/(\d{3})(?=\d)/g, "$1" + thousands);
money += places
? separator +
Math.abs(Math.abs(number) - integer)
.toFixed(places)
.slice(2)
: "";
money = currency ? Number._formatCurrency(money, currency, useSymbol) : money;
return money;
};
Number._formatCurrency = function(money, currency, useSymbol) {
var symbol = useSymbol ? Number.SYMBOLS[currency] : null;
symbol = symbol || [currency, 1];
var position = symbol[1];
symbol = symbol[0];
money = position === 1 ? money + " " + symbol : symbol + " " + money;
return money;
};
if (typeof module !== "undefined") {
module.exports = {
Number: Number
};
}

182
src/general/object.js Normal file
View File

@ -0,0 +1,182 @@
// Hive Colony Framework
// Copyright (c) 2008-2020 Hive Solutions Lda.
//
// This file is part of Hive Colony Framework.
//
// Hive Colony Framework is free software: you can redistribute it and/or modify
// it under the terms of the Apache License as published by the Apache
// Foundation, either version 2.0 of the License, or (at your option) any
// later version.
//
// Hive Colony Framework is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// Apache License for more details.
//
// You should have received a copy of the Apache License along with
// Hive Colony Framework. If not, see <http://www.apache.org/licenses/>.
// __author__ = João Magalhães <joamag@hive.pt>
// __version__ = 1.0.0
// __revision__ = $LastChangedRevision$
// __date__ = $LastChangedDate$
// __copyright__ = Copyright (c) 2008-2020 Hive Solutions Lda.
// __license__ = Apache License, Version 2.0
var _global = typeof global === "undefined" ? window : global;
var _Object = (_global._Object = _global._Object || {});
/**
* Retrieves an element from the given object for the given key, in case the
* element is not found the default value is returned.
*
* @param {Object}
* object The object to be used to retrieve the element.
* @param {String}
* key The index key to be used in the retrieval.
* @param {Object}
* defaultValue The default value to be returned in case no element
* is found.
* @return {Object} The retrieved element.
*/
_Object.get = function(object, key, defaultValue) {
// tries to retrieve the value
var value = object[key];
// returns the valid value
return value !== null && value !== undefined ? value : defaultValue;
};
/**
* Creates a new constructor for the given base constructor and base class. The
* inheritance process changes the given class prototype references.
*
* @param {Function}
* constructorFunction The base constructor function to be used.
* @param {Class}
* baseClass The base class to inherit from.
* @return {Function} The newly created constructor / class.
*/
_Object.inherit = function(constructorFunction, baseClass) {
var targetClass = function() {
// creates the base element
// eslint-disable-next-line new-cap
this.base = new baseClass();
// call the constructor function
constructorFunction.apply(this, arguments);
};
// iterates over all the elements of the base class prototype
for (var element in baseClass.prototype) {
// creates the current element in the target class
this.createElement(targetClass, baseClass, element);
}
// returns the target class (constructor)
return targetClass;
};
/**
* Creates an element in the target class. The new element references the
* element in the base class.
*
* @param {Class}
* targetClass The target class to be used.
* @param {Class}
* baseClass The base class to be used.
* @param {String}
* element The name of the element to be created.
*/
_Object.createElement = function(targetClass, baseClass, element) {
// in case the element is invalid
if (!element || !baseClass.prototype[element]) {
// returns immediately
return;
}
// retrieves the base fnction for the current element
var baseFunction = baseClass.prototype[element];
targetClass.prototype[element] = function() {
return baseFunction.apply(this, arguments);
};
};
/**
* Extends the given object with the given extension object.
*
* @param {Object}
* object The base object to be used.
* @param {Object}
* extensionObject The object ot be used to extend the base one.
* @return {Object} The resulting object.
*/
_Object.extend = function(object, extensionObject) {
// allocates the space for the values and for
// the keys that are going to be used
var value = null;
var key = null;
// allocates the new object map
var newObject = {};
// iterates over all the keys in the
// base object
for (key in object) {
// retrieves the value
value = object[key];
// sets the value in the new object
newObject[key] = value;
}
// iterates over all the keys in
// the extension object
for (key in extensionObject) {
// retrieves the value and then sets
// the value in the new object
value = extensionObject[key];
newObject[key] = value;
}
// returns the new object
return newObject;
};
/**
* Extends the given object with the given extension object. This method uses
* the base object for the creation of the resulting object.
*
* @param {Object}
* object The base object to be used.
* @param {Object}
* extensionObject The object ot be used to extend the base one.
* @return {Object} The resulting object.
*/
_Object._extend = function(object, extensionObject) {
// allocates the space for the values and for
// the keys that are going to be used
var value = null;
var key = null;
// iterates over all the keys in
// the extension object
for (key in extensionObject) {
// retrieves the value
value = extensionObject[key];
// sets the value in the base object
object[key] = value;
}
// returns the base object as the
// resulting object
return object;
};
if (typeof module !== "undefined") {
module.exports = {
_Object: _Object
};
}

55
src/general/root.js Normal file
View File

@ -0,0 +1,55 @@
// Hive Colony Framework
// Copyright (c) 2008-2020 Hive Solutions Lda.
//
// This file is part of Hive Colony Framework.
//
// Hive Colony Framework is free software: you can redistribute it and/or modify
// it under the terms of the Apache License as published by the Apache
// Foundation, either version 2.0 of the License, or (at your option) any
// later version.
//
// Hive Colony Framework is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// Apache License for more details.
//
// You should have received a copy of the Apache License along with
// Hive Colony Framework. If not, see <http://www.apache.org/licenses/>.
// __author__ = João Magalhães <joamag@hive.pt>
// __version__ = 1.0.0
// __revision__ = $LastChangedRevision$
// __date__ = $LastChangedDate$
// __copyright__ = Copyright (c) 2008-2020 Hive Solutions Lda.
// __license__ = Apache License, Version 2.0
var _global = typeof global === "undefined" ? window : global;
var Object = (_global.Object = _global.Object || {});
Object.isEmpty = function(object) {
for (var property in object) {
if (object[property] !== undefined) {
return false;
}
}
return true;
};
Object.clone = function(object, recursive) {
if (object === null || object === undefined || typeof object !== "object") {
return object;
}
var cloned = new object.constructor();
for (var key in object) {
var value = object[key];
value = recursive ? Object.clone(value) : value;
cloned[key] = value;
}
return cloned;
};
if (typeof module !== "undefined") {
module.exports = {
Object: Object
};
}

196
src/general/stack_trace.js Normal file
View File

@ -0,0 +1,196 @@
// Hive Colony Framework
// Copyright (c) 2008-2020 Hive Solutions Lda.
//
// This file is part of Hive Colony Framework.
//
// Hive Colony Framework is free software: you can redistribute it and/or modify
// it under the terms of the Apache License as published by the Apache
// Foundation, either version 2.0 of the License, or (at your option) any
// later version.
//
// Hive Colony Framework is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// Apache License for more details.
//
// You should have received a copy of the Apache License along with
// Hive Colony Framework. If not, see <http://www.apache.org/licenses/>.
// __author__ = João Magalhães <joamag@hive.pt>
// __version__ = 1.0.0
// __revision__ = $LastChangedRevision$
// __date__ = $LastChangedDate$
// __copyright__ = Copyright (c) 2008-2020 Hive Solutions Lda.
// __license__ = Apache License, Version 2.0
var _global = typeof global === "undefined" ? window : global;
var StackTrace = (_global.StackTrace = _global.StackTrace || {});
/**
* The default complete stack value.
*
* @type Boolean
*/
StackTrace.DEFAULT_COMPLETE_STACK_VALUE = false;
/**
* Retrieves the stack trace for the current state.
*
* @param {Boolean}
* completeStack Defines if the stack should be complete (function
* contents) or not.
* @return {List} The result list with the stack trace.
*/
StackTrace.getStackTrace = function(completeStack) {
// sets the complete stack value
completeStack = completeStack || StackTrace.DEFAULT_COMPLETE_STACK_VALUE;
// starts the result list
var result = [];
try {
// tries to acess an attribute in an undefined value to raise an exception
// eslint-disable-next-line no-unused-expressions,no-undef
invalid.invalid;
} catch (exception) {
// parses the error stack using the given exception
var stack = StackTrace.parseErrorStack(exception, completeStack);
// iterates over the stack list
for (var i = 1; i < stack.length; i++) {
// appends the stack item to the result list
result.push(stack[i]);
}
}
// returns the result list
return result;
};
/**
* Retrieves the stack trace (as a string) for the current state.
*
* @param {Boolean}
* completeStack Defines if the stack should be complete (function
* contents) or not.
* @return {String} The result string with the stack trace.
*/
StackTrace.getStackTraceString = function(completeStack) {
// sets the complete stack value
completeStack = completeStack || StackTrace.DEFAULT_COMPLETE_STACK_VALUE;
// retrieves the stack trace result
var result = StackTrace.getStackTrace(completeStack);
// creates the stack string as a join of the result
var stackTraceString = result.join("\n");
// returns the stack trace string
return stackTraceString;
};
/**
* Parses the error stack from the given exception.
*
* @param {Exception}
* exception The exception to be parsed to retrieve the error stack.
* @param {Boolean}
* completeStack Defines if the stack should be complete (function
* contents) or not.
* @return {List} The error stack list.
*/
StackTrace.parseErrorStack = function(exception, completeStack) {
// sets the complete stack value
completeStack = completeStack || StackTrace.DEFAULT_COMPLETE_STACK_VALUE;
// starts the value of the name variable to be used in the
// possible retrieval of the function name
var name = null;
var functionValue = null;
// starts the stack list
var stack = [];
// in case there is no exception defined
if (!exception) {
return stack;
}
// in case there is an exception stack defined (firefox)
if (exception.stack) {
// splits the stack list in the new line character
var stackList = exception.stack.split("\n");
// iterates over all the element of the stack list
for (var i = 0; i < stackList.length - 1; i++) {
// retrieves the function value
functionValue = stackList[i];
// retrieves the symbol name
name = functionValue.match(/^(\w*)/)[1];
// in case the symbol name is not defined
if (!name) {
// sets the symbol name as anonymous
name = "anonymous";
}
stack[stack.length] = name;
}
}
// in case there is no exception stack defined (webkit and ie)
else {
// sets the initial the current function
// eslint-disable-next-line no-caller
var currentFunction = arguments.callee.caller;
// while there is a valid current function defined
while (currentFunction) {
// retrieves the function value
functionValue = currentFunction.toString();
// in case the stack should be complete
if (completeStack) {
// adds the function value to the stack
stack.push(functionValue);
} else {
// retrieves the symbol name
name = functionValue.substring(
functionValue.indexOf("function") + 8,
functionValue.indexOf("(")
);
// in case the symbol name is not valid
if (name === " ") {
// sets the symbol name as anonymous
name = "anonymous";
}
// retrieves the function argument names
var functionArguments = currentFunction.argumentNames();
// creates the arguments string joining all the arguments
// in the function arguments list
var argumentsString = functionArguments.join(",");
// creates the function string
var functionString = name + "(" + argumentsString + ")";
// adds the function string to the stack
stack.push(functionString);
}
// sets the new current function
currentFunction = currentFunction.caller;
}
}
// returns the stack
return stack;
};
if (typeof module !== "undefined") {
module.exports = {
StackTrace: StackTrace
};
}

16
src/index.js Normal file
View File

@ -0,0 +1,16 @@
/**
* Created by WebStorm.
* User: martin
* Date: 01/06/2020
* Time: 14:19
*/
const LocalStorage = require('./LocalStorage');
const utils = require('./utils');
exports.LocalStorage=LocalStorage;
exports.Utils=utils;

View File

@ -0,0 +1,3 @@
const simpleFormatter = require("./simple_formatter");
Object.assign(module.exports, simpleFormatter);

View File

@ -0,0 +1,66 @@
// Hive Colony Framework
// Copyright (c) 2008-2020 Hive Solutions Lda.
//
// This file is part of Hive Colony Framework.
//
// Hive Colony Framework is free software: you can redistribute it and/or modify
// it under the terms of the Apache License as published by the Apache
// Foundation, either version 2.0 of the License, or (at your option) any
// later version.
//
// Hive Colony Framework is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// Apache License for more details.
//
// You should have received a copy of the Apache License along with
// Hive Colony Framework. If not, see <http://www.apache.org/licenses/>.
// __author__ = João Magalhães <joamag@hive.pt>
// __version__ = 1.0.0
// __revision__ = $LastChangedRevision$
// __date__ = $LastChangedDate$
// __copyright__ = Copyright (c) 2008-2020 Hive Solutions Lda.
// __license__ = Apache License, Version 2.0
if (typeof require !== "undefined") {
var logging = require("../logging");
var general = require("../../general");
var Logging = logging.Logging;
var _Object = general._Object;
}
/**
* Constructor of the class.
*/
Logging.SimpleFormatter = function(formatString) {
this.formatString = formatString || "{asctime} [{level}] {message}";
};
Logging.SimpleFormatter = _Object.inherit(Logging.SimpleFormatter, Logging.Formatter);
Logging.SimpleFormatter.prototype.format = function(record) {
var date = new Date();
var asctime = "{0}-{1}-{2} {3}:{4}:{5},{6}".format(
date.getFullYear(),
String(date.getMonth()).padStart(2, "0"),
String(date.getDay()).padStart(2, "0"),
date.getHours(),
date.getMinutes(),
date.getSeconds(),
date.getMilliseconds()
);
var level = record.getLevelString();
var message = record.getMessage();
return this.formatString.formatOptions({
level: level,
asctime: asctime,
message: message
});
};
if (typeof module !== "undefined") {
module.exports = {
Logging: Logging
};
}

View File

@ -0,0 +1,112 @@
// Hive Colony Framework
// Copyright (c) 2008-2020 Hive Solutions Lda.
//
// This file is part of Hive Colony Framework.
//
// Hive Colony Framework is free software: you can redistribute it and/or modify
// it under the terms of the Apache License as published by the Apache
// Foundation, either version 2.0 of the License, or (at your option) any
// later version.
//
// Hive Colony Framework is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// Apache License for more details.
//
// You should have received a copy of the Apache License along with
// Hive Colony Framework. If not, see <http://www.apache.org/licenses/>.
// __author__ = João Magalhães <joamag@hive.pt>
// __version__ = 1.0.0
// __revision__ = $LastChangedRevision$
// __date__ = $LastChangedDate$
// __copyright__ = Copyright (c) 2008-2020 Hive Solutions Lda.
// __license__ = Apache License, Version 2.0
if (typeof require !== "undefined") {
var logging = require("../logging");
var general = require("../../general");
var Logging = logging.Logging;
var _Object = general._Object;
}
/**
* Constructor of the class.
*
* @param {Object}
* instance The options consoale instance to be used in the construction.
* @param {Boolean}
* noDefaults If the defaults (handlers) should not be applied to a possible
* new instance to be constructed.
*/
Logging.ConsolaHandler = function(instance, noDefaults) {
// tries to require the consola dependency to be used
// for the ouput of the logging, notice that if webpack
// exits the requirement is ignored
// eslint-disable-next-line camelcase
if (typeof __webpack_require__ === "undefined") {
var consola = require("consola");
}
var parameters = {
level: 0,
reporters: [],
types: []
};
this.instance = instance || (consola.create ? consola : new consola.Consola(parameters));
if (!noDefaults && consola.FancyReporter) {
// clears any if the previously added reporters and then
// adds the fancy reporter as the default one
this.instance.clear();
this.instance.add(new consola.FancyReporter());
}
};
Logging.ConsolaHandler = _Object.inherit(Logging.ConsolaHandler, Logging.Handler);
Logging.ConsolaHandler.MAPPING = {
NOTSET: "debug",
DEBUG: "debug",
INFO: "info",
WARNING: "warning",
ERROR: "error",
CRITICAL: "critical"
};
Logging.ConsolaHandler.isReady = function() {
try {
// eslint-disable-next-line camelcase
if (typeof __webpack_require__ === "undefined") {
require.resolve("consola");
}
} catch (error) {
return false;
}
if (!process || !process.stdout || !process.stdout.isTTY) {
return false;
}
return true;
};
Logging.ConsolaHandler.prototype.emit = function(record) {
this.base.emit(record);
// formats the record retrieving the message that
// is going to be sent to the concrete handler
var message = this.format(record);
// retrieves the level string for the current record
// and uses it to retrieve the associated method name
// fo the consola environment
var levelString = record.getLevelString();
var name = Logging.ConsolaHandler.MAPPING[levelString];
// calls the appropriate method under the consola environment
// for the logging of the message
this.instance[name](message);
};
if (typeof module !== "undefined") {
module.exports = {
Logging: Logging
};
}

View File

@ -0,0 +1,7 @@
const consolaHandler = require("./consola_handler");
const loggyHandler = require("./loggy_handler");
const streamHandler = require("./stream_handler");
Object.assign(module.exports, consolaHandler);
Object.assign(module.exports, loggyHandler);
Object.assign(module.exports, streamHandler);

View File

@ -0,0 +1,113 @@
// Hive Colony Framework
// Copyright (c) 2008-2020 Hive Solutions Lda.
//
// This file is part of Hive Colony Framework.
//
// Hive Colony Framework is free software: you can redistribute it and/or modify
// it under the terms of the Apache License as published by the Apache
// Foundation, either version 2.0 of the License, or (at your option) any
// later version.
//
// Hive Colony Framework is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// Apache License for more details.
//
// You should have received a copy of the Apache License along with
// Hive Colony Framework. If not, see <http://www.apache.org/licenses/>.
// __author__ = João Magalhães <joamag@hive.pt>
// __version__ = 1.0.0
// __revision__ = $LastChangedRevision$
// __date__ = $LastChangedDate$
// __copyright__ = Copyright (c) 2008-2020 Hive Solutions Lda.
// __license__ = Apache License, Version 2.0
if (typeof require !== "undefined") {
var logging = require("../logging");
var general = require("../../general");
var Logging = logging.Logging;
var _Object = general._Object;
}
var _global = typeof global === "undefined" ? window : global;
var jQuery = (_global.jQuery = _global.jQuery || null);
/**
* Constructor of the class.
*
* @param {Object}
* options The options for the handler construction.
*/
Logging.LoggyHandler = function(options) {
// starts the queue of pending messages
this.recordQueue = [];
// sets the current scope
var scope = this;
jQuery(document).ready(function() {
// starts the loggy structures and then
// runs the flush operation
jQuery("body").loggy("default", options);
scope.flush();
});
};
Logging.LoggyHandler = _Object.inherit(Logging.LoggyHandler, Logging.Handler);
Logging.LoggyHandler.prototype.flush = function() {
this.base.flush();
// iterates over all the records in the record queue
for (var index = 0; index < this.recordQueue.length; index++) {
// retrieves the current record and
// emits the record
var record = this.recordQueue[index];
this.emit(record);
}
// creates a new record queue
this.recordQueue = [];
};
Logging.LoggyHandler.prototype.emit = function(record) {
this.base.emit(record);
// in case the structure is not initialized, the emit
// operation in loggy must be delayed
if (!this.initialized()) {
// adds the record to the records queue and
// then return immediately as there's nothing
// else that may be done for now
this.recordQueue.push(record);
return;
}
// formats the record retrieving the message that
// is going to be sent to the concrete handler
var message = this.format(record);
// retrieves the record level string and runs the
// lowercasing operation in it to retrive the current
// valid message type value for it
var levelString = record.getLevelString();
var messageType = levelString.toLowerCase();
// sends the log message to the loggy so that it can
// be properly handled by it
jQuery("body").loggy("log", {
message: message,
messageType: messageType
});
};
Logging.LoggyHandler.prototype.initialized = function() {
return jQuery("body").loggy("initialized");
};
if (typeof module !== "undefined") {
module.exports = {
Logging: Logging
};
}

View File

@ -0,0 +1,61 @@
// Hive Colony Framework
// Copyright (c) 2008-2020 Hive Solutions Lda.
//
// This file is part of Hive Colony Framework.
//
// Hive Colony Framework is free software: you can redistribute it and/or modify
// it under the terms of the Apache License as published by the Apache
// Foundation, either version 2.0 of the License, or (at your option) any
// later version.
//
// Hive Colony Framework is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// Apache License for more details.
//
// You should have received a copy of the Apache License along with
// Hive Colony Framework. If not, see <http://www.apache.org/licenses/>.
// __author__ = João Magalhães <joamag@hive.pt>
// __version__ = 1.0.0
// __revision__ = $LastChangedRevision$
// __date__ = $LastChangedDate$
// __copyright__ = Copyright (c) 2008-2020 Hive Solutions Lda.
// __license__ = Apache License, Version 2.0
if (typeof require !== "undefined") {
var logging = require("../logging");
var general = require("../../general");
var Logging = logging.Logging;
var _Object = general._Object;
}
/**
* Constructor of the class.
*
* @param {Object}
* stream The stream to be used.
*/
Logging.StreamHandler = function(stream) {
this.stream = stream || console;
};
Logging.StreamHandler = _Object.inherit(Logging.StreamHandler, Logging.Handler);
Logging.StreamHandler.prototype.emit = function(record) {
this.base.emit(record);
// formats the record retrieving the message
var message = this.format(record);
// prints the message to the stream
// flushes the stream
this.stream.info(message);
this.flush();
};
if (typeof module !== "undefined") {
module.exports = {
Logging: Logging
};
}

7
src/logging/index.js Normal file
View File

@ -0,0 +1,7 @@
const formatters = require("./formatters");
const handlers = require("./handlers");
const logging = require("./logging");
Object.assign(module.exports, formatters);
Object.assign(module.exports, handlers);
Object.assign(module.exports, logging);

441
src/logging/logging.js Normal file
View File

@ -0,0 +1,441 @@
// Hive Colony Framework
// Copyright (c) 2008-2020 Hive Solutions Lda.
//
// This file is part of Hive Colony Framework.
//
// Hive Colony Framework is free software: you can redistribute it and/or modify
// it under the terms of the Apache License as published by the Apache
// Foundation, either version 2.0 of the License, or (at your option) any
// later version.
//
// Hive Colony Framework is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// Apache License for more details.
//
// You should have received a copy of the Apache License along with
// Hive Colony Framework. If not, see <http://www.apache.org/licenses/>.
// __author__ = João Magalhães <joamag@hive.pt>
// __version__ = 1.0.0
// __revision__ = $LastChangedRevision$
// __date__ = $LastChangedDate$
// __copyright__ = Copyright (c) 2008-2020 Hive Solutions Lda.
// __license__ = Apache License, Version 2.0
var _global = typeof global === "undefined" ? window : global;
var Logging = (_global.Logging = _global.Logging || {});
/**
* The currently created loggers.
*
* @type Map
*/
Logging.loggers = {};
Logging.getLogger = function(loggerName, defaults) {
// ensures the proper loading of the stream handler to avoid
// any unwanted behaviour (in the defaults creation)
if (typeof require !== "undefined") {
require("./handlers");
require("./formatters");
}
// verifies if the defaults have been sent and if that's
// not the case builds the default ones
if (typeof defaults === "undefined") {
defaults = {
handlers: [Logging.StreamHandler],
formatter: Logging.SimpleFormatter
};
}
// starts the initial reference to logger, this may
// be contructed by the end of the execution
var logger = null;
// retrieves the logger name, falling back to the
// default name in case none is provided
loggerName = loggerName || Logging.constants.DEFAULT_LOGGER_NAME;
// in case there is no logger with the given
// name in the logger map
if (!Logging.loggers[loggerName]) {
// creates a new logger with the given name and
// sets the logger in the loggers map
logger = new Logging.Logger(loggerName, defaults.level || undefined);
Logging.loggers[loggerName] = logger;
// iterates over the multiple values of the defaults
// to buld the proper handlers
var defaultHandlers = defaults.handlers || [];
for (var index = 0; index < defaultHandlers.length; index++) {
var handler = new defaultHandlers[index]();
logger.addHandler(handler);
}
// creates the default formatter for the logger and set it
// changing the value for all the current handlers
var DefaultFormatter = defaults.formatter || null;
if (DefaultFormatter) {
var formatter = new DefaultFormatter();
logger.setFormatter(formatter);
}
}
// retrieves the logger and returns it to
// the caller method
logger = Logging.loggers[loggerName];
return logger;
};
Logging.debug = function(messageValue) {
Logging.getLogger(Logging.constants.DEFAULT_LOGGER_NAME).debug(messageValue);
};
Logging.info = function(messageValue) {
Logging.getLogger(Logging.constants.DEFAULT_LOGGER_NAME).info(messageValue);
};
Logging.warn = function(messageValue) {
Logging.getLogger(Logging.constants.DEFAULT_LOGGER_NAME).warn(messageValue);
};
Logging.error = function(messageValue) {
Logging.getLogger(Logging.constants.DEFAULT_LOGGER_NAME).error(messageValue);
};
Logging.critical = function(messageValue) {
Logging.getLogger(Logging.constants.DEFAULT_LOGGER_NAME).critical(messageValue);
};
/**
* The map containig the logging contants.
*
* @type Map
*/
Logging.constants = {
/**
* The critical number.
*
* @type Integer
*/
CRITICAL: 50,
/**
* The error number.
*
* @type Integer
*/
ERROR: 40,
/**
* The warning number.
*
* @type Integer
*/
WARNING: 30,
/**
* The info number.
*
* @type Integer
*/
INFO: 20,
/**
* The debug number.
*
* @type Integer
*/
DEBUG: 10,
/**
* The not set number.
*
* @type Integer
*/
NOTSET: 0,
/**
* The default level number.
*
* @type Integer
*/
DEFAULT_LEVEL: 20,
/**
* The critical value.
*
* @type String
*/
CRITICAL_VALUE: "CRITICAL",
/**
* The error value.
*
* @type String
*/
ERROR_VALUE: "ERROR",
/**
* The warning value.
*
* @type String
*/
WARNING_VALUE: "WARNING",
/**
* The info value.
*
* @type String
*/
INFO_VALUE: "INFO",
/**
* The debug value.
*
* @type String
*/
DEBUG_VALUE: "DEBUG",
/**
* The not set value.
*
* @type String
*/
NOTSET_VALUE: "NOTSET",
/**
* The default level value.
*
* @type String
*/
DEFAULT_LEVEL_VALUE: "INFO",
/**
* The default logger name.
*
* @type String
*/
DEFAULT_LOGGER_NAME: "default"
};
Logging.LevelsMap = {};
Logging.LevelsMap[Logging.constants.CRITICAL] = Logging.constants.CRITICAL_VALUE;
Logging.LevelsMap[Logging.constants.ERROR] = Logging.constants.ERROR_VALUE;
Logging.LevelsMap[Logging.constants.WARNING] = Logging.constants.WARNING_VALUE;
Logging.LevelsMap[Logging.constants.INFO] = Logging.constants.INFO_VALUE;
Logging.LevelsMap[Logging.constants.DEBUG] = Logging.constants.DEBUG_VALUE;
Logging.LevelsMap[Logging.constants.NOTSET] = Logging.constants.NOTSET_VALUE;
Logging.LevelsMap[Logging.constants.CRITICAL_VALUE] = Logging.constants.CRITICAL;
Logging.LevelsMap[Logging.constants.ERROR_VALUE] = Logging.constants.ERROR;
Logging.LevelsMap[Logging.constants.WARNING_VALUE] = Logging.constants.WARNING;
Logging.LevelsMap[Logging.constants.INFO_VALUE] = Logging.constants.INFO;
Logging.LevelsMap[Logging.constants.DEBUG_VALUE] = Logging.constants.DEBUG;
Logging.LevelsMap[Logging.constants.NOTSET_VALUE] = Logging.constants.NOTSET;
/**
* Constructor of the class.
*
* @param {String}
* loggerName The name of the logger.
*/
Logging.Logger = function(loggerName, level, handlers) {
this.loggerName = loggerName;
this.level = typeof level === "undefined" ? Logging.constants.DEFAULT_LEVEL : level;
this.handlers = typeof handlers === "undefined" ? [] : handlers;
};
/**
* Adds a new handler to the logger.
*
* @param {Handler}
* handler The handler to be added to the logger.
*/
Logging.Logger.prototype.addHandler = function(handler) {
this.handlers.push(handler);
};
/**
* Sets the level of verbosity.
*
* @param {String}
* level The level of verbosity to be set.
*/
Logging.Logger.prototype.setLevel = function(level) {
this.level = level;
};
Logging.Logger.prototype.debug = function(messageValue) {
if (this.isEnabledFor(Logging.constants.DEBUG)) {
this._log(messageValue, Logging.constants.DEBUG);
}
};
Logging.Logger.prototype.info = function(messageValue) {
if (this.isEnabledFor(Logging.constants.INFO)) {
this._log(messageValue, Logging.constants.INFO);
}
};
Logging.Logger.prototype.warn = function(messageValue) {
if (this.isEnabledFor(Logging.constants.WARNING)) {
this._log(messageValue, Logging.constants.WARNING);
}
};
Logging.Logger.prototype.error = function(messageValue) {
if (this.isEnabledFor(Logging.constants.ERROR)) {
this._log(messageValue, Logging.constants.ERROR);
}
};
Logging.Logger.prototype.critical = function(messageValue) {
if (this.isEnabledFor(Logging.constants.CRITICAL)) {
this._log(messageValue, Logging.constants.CRITICAL);
}
};
Logging.Logger.prototype.isEnabledFor = function(level) {
return level >= this.getEffectiveLevel();
};
Logging.Logger.prototype.getEffectiveLevel = function() {
return this.level;
};
Logging.Logger.prototype.setFormatter = function(formatter) {
for (var index = 0; index < this.handlers.length; index++) {
var handler = this.handlers[index];
handler.setFormatter(formatter);
}
};
Logging.Logger.prototype._log = function(messageValue, level) {
// creates a new record for the message value and the level
var record = new Logging.Record(messageValue, level);
// handles the record
this.handle(record);
};
Logging.Logger.prototype.handle = function(record) {
// calls the handlers for the record
this.callHandlers(record);
};
Logging.Logger.prototype.callHandlers = function(record) {
// iterates over all the handlers
for (var index = 0; index < this.handlers.length; index++) {
// retrieves the current handler and
// handles the record with the handler
var handler = this.handlers[index];
handler.handle(record);
}
};
/**
* Constructor of the class.
*
* @param {String}
* message The message.
* @param {Integer}
* level The level.
*/
Logging.Record = function(message, level) {
this.message = message;
this.level = level;
};
/**
* Retrieves the message.
*
* @return {String} The message.
*/
Logging.Record.prototype.getMessage = function() {
return this.message;
};
/**
* Retrieves the level.
*
* @return {Integer} The level.
*/
Logging.Record.prototype.getLevel = function() {
return this.level;
};
/**
* Retrieves the level string value.
*
* @return {String} The level string value.
*/
Logging.Record.prototype.getLevelString = function() {
return Logging.LevelsMap[this.level];
};
/**
* Constructor of the class.
*/
Logging.Handler = function() {
this.formatter = null;
};
Logging.Handler.isReady = function() {
return true;
};
/**
* Sets the formatter for the handler.
*
* @param {Formatter}
* formatter The formatter for the handler.
*/
Logging.Handler.prototype.setFormatter = function(formatter) {
this.formatter = formatter;
};
Logging.Handler.prototype.handle = function(record) {
// emits the record so that it gets pipelined
// to the inner implementation
this.emit(record);
};
Logging.Handler.prototype.format = function(record) {
// sets the inital value for the message
var message = null;
// in case no formatter
if (!this.formatter) {
// retrieves the record message and returns
// it to the caller method
message = record.getMessage();
return message;
}
// formats the message using the formatter
// and returns it to the caller
message = this.formatter.format(record);
return message;
};
Logging.Handler.prototype.flush = function() {};
Logging.Handler.prototype.emit = function(record) {};
/**
* Constructor of the class.
*/
Logging.Formatter = function() {};
Logging.Formatter.prototype.format = function(record) {};
if (typeof module !== "undefined") {
module.exports = {
Logging: Logging
};
}

262
src/utils.js Normal file
View File

@ -0,0 +1,262 @@
/**
*
* @param timeString
* @param today
* @returns {string}
*/
const partOfDay = (timeString, today) => {
console.log(new Date());
if (timeString === undefined || timeString === null)
timeString = (new Date()).getHours().toString();
if (today === undefined)
today = false;
const hours = timeString.substring(0, 2);
let dayBit;
console.log('Hours', hours);
if (hours >= 0 && hours < 4)
dayBit = 'Late Night';
else if (hours >= 4 && hours < 7)
dayBit = 'Early Morning';
else if (hours >= 7 && hours < 12)
dayBit = 'Morning';
else if (hours >= 12 && hours < 17)
dayBit = 'Afternoon';
else if (hours < 21)
dayBit = 'Evening';
else
dayBit = 'Night';
if (today)
dayBit = dayBit === 'night' ? 'tonight' : `this ${dayBit}`;
console.log('partOfDay', dayBit);
return dayBit;
};
/**
*
* @param extra
* @returns {number}
*/
const toHour = (extra = 0) => {
const now = new Date();
return (3600000 - (now.getTime() % 3600000)) + extra;
};
/**
*
* @returns {string}
*/
const hourFloor = () => {
const now = new Date();
return parseInt(~~(now.getTime() / 3600000) * 3600000, 10).toString(32);
};
/**
*
* @param d
* @returns {number}
*/
const getWeek = function (d) {
var target = new Date(d.valueOf());
var dayNr = (d.getDay() + 6) % 7;
target.setDate(target.getDate() - dayNr + 3);
var firstThursday = target.valueOf();
target.setMonth(0, 1);
if (target.getDay() != 4) {
target.setMonth(0, 1 + ((4 - target.getDay()) + 7) % 7);
}
return 1 + Math.ceil((firstThursday - target) / 604800000);
}
/**
*
* @param lat1
* @param lon1
* @param lat2
* @param lon2
* @returns {number}
*/
const distance = (lat1, lon1, lat2, lon2) => {
const p = 0.017453292519943295; // Math.PI / 180
const c = Math.cos;
const a = 0.5 - c((lat2 - lat1) * p) / 2 +
c(lat1 * p) * c(lat2 * p) *
(1 - c((lon2 - lon1) * p)) / 2;
return 12742 * Math.asin(Math.sqrt(a)); // 2 * R; R = 6371 km
};
function splitURL(url) {
}
/**
*
* @param count
* @param noun
* @param suffix
* @returns {string}
*/
const maybePluralize = (count, noun, suffix = 's') =>
`${count} ${noun}${count !== 1 ? suffix : ''}`;
/**
*
* @param fn
* @param time
* @returns {Function}
* @private
*/
const debounce = function (fn, time) {
let timeout;
return function (...args) { // <-- not an arrow function
const functionCall = () => fn.apply(this, args);
clearTimeout(timeout);
timeout = setTimeout(functionCall, time);
};
};
/**
*
* @param callback
* @param limit
* @returns {Function}
* @private
*/
const throttle = (callback, limit) => {
var wait = false;
return function (...args) {
if (!wait) {
callback.apply(null, args);
wait = true;
setTimeout(function () {
wait = false;
}, limit);
}
};
};
/**
*
* @param func
* @returns {function(): *}
* @private
*/
const once = function (func) {
var alreadyCalled = false;
var result;
return function (...args) {
if (!alreadyCalled) {
result = func.apply(this, args);
alreadyCalled = true;
}
return result;
};
};
/**
*
* @param obj
* @returns {boolean|boolean}
*/
const isEmpty = obj => [Object, Array].includes((obj || {}).constructor) && !Object.entries((obj || {})).length;
const hasOwnProperty = Object.prototype.hasOwnProperty;
/**
*
* @param obj
* @param prop
* @returns {boolean}
*/
const hasOwn = (obj, prop) => hasOwnProperty.call(obj, prop);
/**
*
* @param obj
* @param path
* @param defaultValue
* @returns {*}
*/
const get = (obj, path, defaultValue = undefined) => {
const travel = regexp =>
String.prototype.split
.call(path, regexp)
.filter(Boolean)
.reduce((res, key) => (res !== null && res !== undefined ? res[key] : res), obj);
const result = travel(/[,[\]]+?/) || travel(/[,[\].]+?/);
return result === undefined || result === obj ? defaultValue : result;
};
const arrayFromObj = (jsonObj, wantedFields) => {
return wantedFields.map((key) => {
if (jsonObj.hasOwnProperty(key))
return jsonObj[key];
});
};
const extractFromObj = (jsonObj, wantedFields) => {
return Object.keys(jsonObj).reduce((obj, key) => {
if (wantedFields.includes(key))
obj[key] = jsonObj[key];
return obj;
}, {});
};
const objectMatcher = (obj, matcher) => {
if (typeof(obj) !== 'object' || obj === null) return false;
let count = Object.keys(obj).length;
const keys = Object.keys(obj);
if (count !== matcher.length) return false;
matcher.forEach((item) => {
if (keys.indexOf(item) !== -1)
count--;
});
return (count === 0);
};
exports = {
'partOfDay': partOfDay,
'toHour': toHour,
'hourFloor': hourFloor,
'getWeek': getWeek,
'distance': distance,
'maybePluralize': maybePluralize,
'debounce': debounce,
'throttle': throttle,
'once': once,
'isEmpty': isEmpty,
'hasOwn': hasOwn,
'get': get,
'arrayFromObj' : arrayFromObj,
'extractFromObj' : extractFromObj,
'objectMatcher' : objectMatcher
};
// module.exports = { partOfDay, toHour, hourFloor, distance, maybePluralize, debounce, throttle, once, isEmpty, hasOwn, get, Logger, LocalStorage };
module.exports = exports;

View File

@ -0,0 +1,7 @@
import { arrayFromObj } from './arrayFromObj';
test('It creates the proper array', function () {
const testObj = { a: 1, b: 2 };
expect(arrayFromObj(testObj, ['a', 'b'])).toEqual([1, 2]);
});

16
ts-src/arrayFromObj.ts Normal file
View File

@ -0,0 +1,16 @@
/**
* Create an array from an Object using specified fields
* @param jsonObj The Original object
* @param wantedFields The required fields
*
* @example
* U.arrayFromObj({ a: 1, b: 2 }, ['a', 'b']) // => [1, 2]
*/
export function arrayFromObj(jsonObj: Object, wantedFields: string[]): any[] {
return wantedFields.map((key) => {
if (jsonObj.hasOwnProperty(key)) {
const { value }: any = Object.getOwnPropertyDescriptor(jsonObj, key);
return value;
}
});
}

31
ts-src/debounce.test.ts Normal file
View File

@ -0,0 +1,31 @@
import { debounce } from '../ts-src/debounce';
import * as sinon from 'sinon';
let clock: sinon.SinonFakeTimers;
beforeEach(() => {
clock = sinon.useFakeTimers();
});
afterEach(() => {
clock.restore();
});
test('Should only trigger once', function () {
const func = jest.fn();
const debouncedFunc = debounce(func, 1000);
debouncedFunc();
expect(func).toHaveBeenCalledTimes(0);
// Call it several times with 500ms between each call
for (let i = 0; i < 10; i++) {
clock.tick(500);
debouncedFunc();
}
expect(func).toHaveBeenCalledTimes(0); // func not called
// wait 1000ms
clock.tick(1000);
expect(func).toHaveBeenCalledTimes(1);
});

23
ts-src/debounce.ts Normal file
View File

@ -0,0 +1,23 @@
/**
* Debounce the calling of a function
* @param fn The function to be debounced
* @param time How long to wait
* @returns {Function}
*
* @signature
* U.debounce(fn, time)
*
*/
export function debounce(fn: Function, time: number): Function {
let timeout: NodeJS.Timeout;
return function (...args: any): any {
// <-- not an arrow function
// @ts-ignore
const functionCall = () => fn.apply(<any>this, args);
clearTimeout(timeout);
timeout = setTimeout(functionCall, time);
};
}

13
ts-src/distance.test.ts Normal file
View File

@ -0,0 +1,13 @@
import { distance } from './distance';
import { LatLong } from './latLong';
test('Should return the correct Base32 value', () => {
expect(distance(1, 1, 2, 2)).toEqual(157.22543203805722);
});
test('Should return the correct Base32 value', () => {
const a: LatLong = new LatLong(1, 1);
const b: LatLong = new LatLong(2, 2);
expect(distance(a, b)).toEqual(157.22543203805722);
});

57
ts-src/distance.ts Normal file
View File

@ -0,0 +1,57 @@
import { LatLong } from './latLong';
/**
* Calculate the distance between two lat long points
* @param lat1
* @param lon1
* @param lat2
* @param lon2
*
* @signature
* U.distance(lat1, long1, lat2, long2)
*
* @example
* distance(1, 1, 2, 2) // => 157.22543203805722;
*/
export function distance(lat1: number, lon1: number, lat2: number, lon2: number): number;
/**
* Calculate the distance between two lat long points
* @param latLong1
* @param latLong2
*
* @signature
* U.distance(latLong1, latLong2)
*
* @example
*
* const a: U.LatLong = new LatLong(1, 1);
* const b: U.LatLong = new LatLong(2, 2);
* U.distance(a, b) // => 157.22543203805722
*
*/
export function distance(latLong1: LatLong, latLong2: LatLong): number;
/**
* Calculate the Distance between two lat long points
*/
export function distance(): number {
if (arguments.length === 4) {
return _distance(arguments[0], arguments[1], arguments[2], arguments[3]);
} else if (arguments.length === 2) {
return _distance(
<number>arguments[0].lat,
<number>arguments[0].long,
<number>arguments[1].lat,
<number>arguments[1].long
);
} else return 0;
}
function _distance(lat1: number, lon1: number, lat2: number, lon2: number): number {
const p = 0.017453292519943295; // Math.PI / 180
const c = Math.cos;
const a = 0.5 - c((lat2 - lat1) * p) / 2 + (c(lat1 * p) * c(lat2 * p) * (1 - c((lon2 - lon1) * p))) / 2;
return 12742 * Math.asin(Math.sqrt(a)); // 2 * R; R = 6371 km
}

View File

@ -0,0 +1,13 @@
import { extractFromObj } from './extractFromObj';
test('It should correctly extract values', function () {
const o = { a: 1, b: 2 };
expect(extractFromObj(o, ['a'])).toEqual({ a: 1 });
});
test('It should correctly extract more complex structure', function () {
const o = { a: { bob: 1, steve: 2 }, b: 2 };
expect(extractFromObj(o, ['a'])).toEqual({ a: { bob: 1, steve: 2 } });
});

27
ts-src/extractFromObj.ts Normal file
View File

@ -0,0 +1,27 @@
/**
* Extract an object from another object using specific fields
* @param jsonObj The source object
* @param wantedFields The required fields
* @signature
* U.extractFromObj(jsonObj, wantedFields)
*
* @example
* U.extractFromObj({ a: 1, b: 2 }, ['a']) // => { a: 1 }
*
*/
export function extractFromObj(jsonObj: Object, wantedFields: string[]): {} {
return Object.keys(jsonObj).reduce((obj, key) => {
if (wantedFields.includes(key)) {
const { value }: any = Object.getOwnPropertyDescriptor(jsonObj, key);
Object.defineProperty(obj, key, {
value: value,
writable: true,
enumerable: true,
configurable: true
});
}
return obj;
}, {});
}

13
ts-src/hasOwn.test.ts Normal file
View File

@ -0,0 +1,13 @@
import { hasOwn } from './hasOwn';
let testObj: Object = {
bob: true
};
test('It has a specified property', function () {
expect(hasOwn(testObj, 'bob')).toBeTruthy();
});
test('It does not have a specified property', function () {
expect(hasOwn(testObj, 'Steve')).toBeFalsy();
});

14
ts-src/hasOwn.ts Normal file
View File

@ -0,0 +1,14 @@
const hasOwnProperty = Object.prototype.hasOwnProperty;
/**
* Check if an object has an property
* @param obj The source object
* @param prop The required property
* @returns {boolean}
*
* @example
* U.hasOwn({bob:'1'}, 'bob') // => true
*/
export function hasOwn(obj: Object, prop: string): boolean {
return hasOwnProperty.call(obj, prop);
}

5
ts-src/hourFloor.test.ts Normal file
View File

@ -0,0 +1,5 @@
import { hourFloor } from './hourFloor';
test('Should return the correct Base32 value', () => {
expect(hourFloor(1605532173)).toEqual('1fnp540');
});

12
ts-src/hourFloor.ts Normal file
View File

@ -0,0 +1,12 @@
/**
* Get the hour floor as a Base 32 string
* @param timestamp The timestamp as a number
* @returns {string}
*
* @example
* U.hourFloor(1605532173) // => '1fnp540'
*/
export function hourFloor(timestamp: number): string {
return (Math.floor(timestamp / 3600000) * 3600000).toString(32);
}

13
ts-src/index.ts Normal file
View File

@ -0,0 +1,13 @@
export * from './arrayFromObj';
export * from './debounce';
export * from './distance';
export * from './extractFromObj';
export * from './hasOwn';
export * from './hourFloor';
export * from './isEmpty';
export * from './latLong';
export * from './maybePluralize';
export * from './once';
export * from './partOfDay';
export * from './throttle';
export * from './toHour';

9
ts-src/isEmpty.test.ts Normal file
View File

@ -0,0 +1,9 @@
import { isEmpty } from './isEmpty';
test('Object is empty', function () {
expect(isEmpty({})).toBe(true);
});
test('Object is not empty', function () {
expect(isEmpty({ bob: true })).toBe(false);
});

12
ts-src/isEmpty.ts Normal file
View File

@ -0,0 +1,12 @@
/**
* Check if an object is empty
* @param obj The object being checked
*
* @example
* U.isEmpty({}) // => true
* U.isEmpty({ bob: true }) // => false
*/
export function isEmpty(obj: Object): boolean {
// @ts-ignore
return [Object, Array].includes((obj || {}).constructor) && !Object.entries(obj || {}).length;
}

16
ts-src/latLong.ts Normal file
View File

@ -0,0 +1,16 @@
/**
* Calculate the distance between two latLongs
* @param lat1
* @param lon1
* @param lat2
* @param lon2
* @returns {number}
*/
export class LatLong {
lat: number;
long: number;
constructor(lat:number, long:number) {
this.lat = lat;
this.long = long;
}
}

View File

@ -0,0 +1,9 @@
import { maybePluralize } from './maybePluralize';
test('Should be 1 Bag', () => {
expect(maybePluralize(1, 'Bag', 's')).toEqual('1 Bag');
});
test('Should be 5 Bags', () => {
expect(maybePluralize(5, 'Bag', 's')).toEqual('5 Bags');
});

18
ts-src/maybePluralize.ts Normal file
View File

@ -0,0 +1,18 @@
/**
* Maybe pluralize a count:
*
* @param count the value counting
* @param noun the name of the value
* @param suffix the suffix
* @returns {string}
*
* @signature
* U.maybePluralize(number, noun, suffix)
*
* @example
* U.maybePluralize(1, 'Bag', 's') // => 1 Bag
* U.maybePluralize(5, 'Bag', 's') // => 5 Bags
*/
export function maybePluralize(count: number, noun: string, suffix = 's'): string {
return `${count} ${noun}${count !== 1 ? suffix : ''}`;
}

15
ts-src/once.test.ts Normal file
View File

@ -0,0 +1,15 @@
import { once } from './once';
test('It should trigger once', function () {
const func = jest.fn();
const onetimeFunc = once(func);
onetimeFunc();
expect(func).toHaveBeenCalledTimes(1);
onetimeFunc();
expect(func).toHaveBeenCalledTimes(1);
});

22
ts-src/once.ts Normal file
View File

@ -0,0 +1,22 @@
/**
* Trigger a function once and then prevent it from triggering again
* @returns {Function}
* @param fn
*
* @signature
* U.once(fn)
*/
export function once(fn: Function): Function {
let alreadyCalled: boolean = false;
let result: Function;
return function (...args: any): any {
if (!alreadyCalled) {
// @ts-ignore
result = fn.apply(<any>this, args);
alreadyCalled = true;
}
return result;
};
}

9
ts-src/partOfDay.test.ts Normal file
View File

@ -0,0 +1,9 @@
import { partOfDay } from './partOfDay';
test('Should return Afternoon', () => {
expect(partOfDay('12:00', false)).toEqual('Afternoon');
});
test('Should return Late Night', () => {
expect(partOfDay('00:00', false)).toEqual('Late Night');
});

30
ts-src/partOfDay.ts Normal file
View File

@ -0,0 +1,30 @@
/**
* Get a string phrase for the current time of day
* @param timeString
* @param today
*
* @signature
* U.partOfDay(timeString, today)
* @example
* U.partOfDay('13:00') // => 'Afternoon'
*/
export function partOfDay(timeString: string, today: boolean = false): string {
if (timeString === undefined || timeString === null) timeString = new Date().getHours().toString();
if (today === undefined) today = false;
const hours: number = parseInt(timeString.substring(0, 2), 10);
let dayBit;
if (hours >= 0 && hours < 4) dayBit = 'Late Night';
else if (hours >= 4 && hours < 7) dayBit = 'Early Morning';
else if (hours >= 7 && hours < 12) dayBit = 'Morning';
else if (hours >= 12 && hours < 17) dayBit = 'Afternoon';
else if (hours < 21) dayBit = 'Evening';
else dayBit = 'Night';
if (today) dayBit = dayBit === 'night' ? 'tonight' : `this ${dayBit}`;
return dayBit;
}

32
ts-src/throttle.test.ts Normal file
View File

@ -0,0 +1,32 @@
import { throttle } from './throttle';
import * as sinon from 'sinon';
let clock: sinon.SinonFakeTimers;
beforeEach(() => {
clock = sinon.useFakeTimers();
});
afterEach(() => {
clock.restore();
});
test('It should throttle calls', function () {
const func = jest.fn();
const throttledFunc = throttle(func, 1000);
throttledFunc();
expect(func).toHaveBeenCalledTimes(1);
throttledFunc();
expect(func).toHaveBeenCalledTimes(1);
clock.tick(1000);
throttledFunc();
expect(func).toHaveBeenCalledTimes(2);
});

22
ts-src/throttle.ts Normal file
View File

@ -0,0 +1,22 @@
/**
* Throttle the calling of a function
* @returns {Function}
* @param callback
* @param limit
*
* @signature
* U.throttle(callback, limit)
*/
export function throttle(callback: Function, limit: number): Function {
var wait: boolean = false;
return function (...args: any): any {
if (!wait) {
callback.apply(null, args);
wait = true;
setTimeout(function () {
wait = false;
}, limit);
}
};
}

5
ts-src/toHour.test.ts Normal file
View File

@ -0,0 +1,5 @@
import { toHour } from './toHour';
test('Should return number of MS to the hour', () => {
expect(toHour(1605532173, 0)).toEqual(67827);
});

14
ts-src/toHour.ts Normal file
View File

@ -0,0 +1,14 @@
/**
* Return the number of Milliseconds to the hour for the supplied timestamp
* @param currentTimsestamp
* @param extra
* @returns {number}
* *
* @signature
* U.toHour(currentTimsestamp, extra)
* @example
* U.toHour('13:00') // => 1605532173
*/
export function toHour(currentTimsestamp: number, extra: number = 0): number {
return 3600000 - (currentTimsestamp % 3600000) + extra;
}

163
ts-src/utils.txt Normal file
View File

@ -0,0 +1,163 @@
///<reference path="../node_modules/@types/node/globals.d.ts"/>
/**
*
* @param timeString
* @param today
* @returns {string}
*/
const partOfDay = (timeString:string, today:boolean = false):string => {
console.log(new Date());
if (timeString === undefined || timeString === null)
timeString = (new Date()).getHours().toString();
if (today === undefined)
today = false;
const hours:number = parseInt(timeString.substring(0, 2),10);
let dayBit;
console.log('Hours', hours);
if (hours >= 0 && hours < 4)
dayBit = 'Late Night';
else if (hours >= 4 && hours < 7)
dayBit = 'Early Morning';
else if (hours >= 7 && hours < 12)
dayBit = 'Morning';
else if (hours >= 12 && hours < 17)
dayBit = 'Afternoon';
else if (hours < 21)
dayBit = 'Evening';
else
dayBit = 'Night';
if (today)
dayBit = dayBit === 'night' ? 'tonight' : `this ${dayBit}`;
console.log('partOfDay', dayBit);
return dayBit;
};
/**
*
* @param extra
* @returns {number}
*/
const toHour = (extra:number = 0):number => {
const now = new Date();
return (3600000 - (now.getTime() % 3600000)) + extra;
};
/**
*
* @returns {string}
*/
const hourFloor = ():string => {
const now:Date = new Date();
return (~~(now.getTime() / 3600000) * 3600000).toString(32);
};
/**
* Calculate the distance between two latLongs
* @param lat1
* @param lon1
* @param lat2
* @param lon2
* @returns {number}
*/
const distance = (lat1:number, lon1:number, lat2:number, lon2:number) : number => {
const p = 0.017453292519943295; // Math.PI / 180
const c = Math.cos;
const a = 0.5 - c((lat2 - lat1) * p) / 2 +
c(lat1 * p) * c(lat2 * p) *
(1 - c((lon2 - lon1) * p)) / 2;
return 12742 * Math.asin(Math.sqrt(a)); // 2 * R; R = 6371 km
};
/**
* Maybe pluralize a count:
* EG:
* > 1 Bag
* > 5 Bags
*
* @param count
* @param noun
* @param suffix
* @returns {string}
*/
const maybePluralize = (count:number, noun:string, suffix = 's'):string =>
`${count} ${noun}${count !== 1 ? suffix : ''}`;
/**
*
* @param fn
* @param time
* @returns {Function}
* @private
*/
const debounce = function (fn:Function, time:number):Function {
let timeout:NodeJS.Timeout;
return function (...args:any):any { // <-- not an arrow function
const functionCall = () => fn.apply(this, args);
clearTimeout(timeout);
timeout = setTimeout(functionCall, time);
};
};
/**
*
* @param callback
* @param limit
* @returns {Function}
* @private
*/
const throttle = (callback:Function, limit:number):Function => {
var wait:boolean = false;
return function (...args:any):any {
if (!wait) {
callback.apply(null, args);
wait = true;
setTimeout(function () {
wait = false;
}, limit);
}
};
};
/**
*
* @param func
* @returns {function(): *}
* @private
*/
const once = function (func:Function): Function {
var alreadyCalled = false;
var result:Function;
return (...args: any): any => {
if (!alreadyCalled) {
result = func.apply(this, args);
alreadyCalled = true;
}
return result;
};
};

68
tsconfig.json Normal file
View File

@ -0,0 +1,68 @@
{
"compilerOptions": {
/* Basic Options */
"target":
"es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */,
"module":
"esnext" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
"lib": [
"es6",
"es2017.object"
] /* Specify library files to be included in the compilation. */,
// "allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
// "declaration": true, /* Generates corresponding '.d.ts' file. */
// "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
"outDir": "./dist" /* Redirect output structure to the directory. */,
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
"noEmit": false,
"declaration": false,
"declarationMap": false,
/* Strict Type-Checking Options */
"strict": true /* Enable all strict type-checking options. */,
"noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
"strictNullChecks": true /* Enable strict null checks. */,
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
/* Additional Checks */
"noUnusedLocals": true /* Report errors on unused locals. */,
"noUnusedParameters": false /* Report errors on unused parameters. */,
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
"noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */,
/* Module Resolution Options */
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
// "typeRoots": [], /* List of folders to include type definitions from. */
// "types": [], /* Type declaration files to be included in compilation. */
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
/* Source Map Options */
// "sourceRoot": "./", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
// "mapRoot": "./", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
/* Experimental Options */
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */,
"skipLibCheck": true
},
"include": ["ts-src"],
"exclude": ["node_modules"]
}