Skip to content
Snippets Groups Projects
Verified Commit ccb2cba1 authored by Volker Schukai's avatar Volker Schukai :alien:
Browse files

chore: commit save point

parent a5f8acc0
Branches
Tags
No related merge requests found
Showing
with 2470 additions and 0 deletions
# Created by https://www.toptal.com/developers/gitignore/api/intellij+iml,phpunit,git,vim,visualstudiocode,phpstorm,go,intellij+all,netbeans,dbeaver,node,yarn
# Edit at https://www.toptal.com/developers/gitignore?templates=intellij+iml,phpunit,git,vim,visualstudiocode,phpstorm,go,intellij+all,netbeans,dbeaver,node,yarn
### DBeaver ###
# ide config file
.dbeaver-data-sources*.xml
### Git ###
# Created by git for backups. To disable backups in Git:
# git config --global mergetool.keepBackup false
*.orig
# Created by git when using merge tools for conflicts
*.BACKUP.*
*.BASE.*
*.LOCAL.*
*.REMOTE.*
*_BACKUP_*.txt
*_BASE_*.txt
*_LOCAL_*.txt
*_REMOTE_*.txt
### Go ###
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
# Go workspace file
go.work
### Go Patch ###
/vendor/
/Godeps/
### Intellij+all ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### Intellij+all Patch ###
# Ignore everything but code style settings and run configurations
# that are supposed to be shared within teams.
.idea/*
!.idea/codeStyles
!.idea/runConfigurations
### Intellij+iml ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
# AWS User-specific
# Generated files
# Sensitive or high-churn files
# Gradle
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
# Mongo Explorer plugin
# File-based project format
# IntelliJ
# mpeltonen/sbt-idea plugin
# JIRA plugin
# Cursive Clojure plugin
# SonarLint plugin
# Crashlytics plugin (for Android Studio and IntelliJ)
# Editor-based Rest Client
# Android studio 3.1+ serialized cache file
### Intellij+iml Patch ###
# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
*.iml
modules.xml
.idea/misc.xml
*.ipr
### NetBeans ###
**/nbproject/private/
**/nbproject/Makefile-*.mk
**/nbproject/Package-*.bash
build/
nbbuild/
dist/
nbdist/
.nb-gradle/
### Node ###
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
### Node Patch ###
# Serverless Webpack directories
.webpack/
# Optional stylelint cache
# SvelteKit build / generate output
.svelte-kit
### PhpStorm ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
# AWS User-specific
# Generated files
# Sensitive or high-churn files
# Gradle
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
# Mongo Explorer plugin
# File-based project format
# IntelliJ
# mpeltonen/sbt-idea plugin
# JIRA plugin
# Cursive Clojure plugin
# SonarLint plugin
# Crashlytics plugin (for Android Studio and IntelliJ)
# Editor-based Rest Client
# Android studio 3.1+ serialized cache file
### PhpStorm Patch ###
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
# *.iml
# modules.xml
# .idea/misc.xml
# *.ipr
# Sonarlint plugin
# https://plugins.jetbrains.com/plugin/7973-sonarlint
.idea/**/sonarlint/
# SonarQube Plugin
# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
.idea/**/sonarIssues.xml
# Markdown Navigator plugin
# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
.idea/**/markdown-navigator.xml
.idea/**/markdown-navigator-enh.xml
.idea/**/markdown-navigator/
# Cache file creation bug
# See https://youtrack.jetbrains.com/issue/JBR-2257
.idea/ACHE_FILE
# CodeStream plugin
# https://plugins.jetbrains.com/plugin/12206-codestream
.idea/codestream.xml
# Azure Toolkit for IntelliJ plugin
# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij
.idea/**/azureSettings.xml
### PHPUnit ###
# Covers PHPUnit
# Reference: https://phpunit.de/
# Generated files
.phpunit.result.cache
.phpunit.cache
# PHPUnit
/app/phpunit.xml
/phpunit.xml
# Build data
/build/
### Vim ###
# Swap
[._]*.s[a-v][a-z]
!*.svg # comment out if you don't need vector files
[._]*.sw[a-p]
[._]s[a-rt-v][a-z]
[._]ss[a-gi-z]
[._]sw[a-p]
# Session
Session.vim
Sessionx.vim
# Temporary
.netrwhist
*~
# Auto-generated tag files
tags
# Persistent undo
[._]*.un~
### VisualStudioCode ###
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets
# Local History for Visual Studio Code
.history/
# Built Visual Studio Code Extensions
*.vsix
### VisualStudioCode Patch ###
# Ignore all local history of files
.history
.ionide
# Support for Project snippet scope
.vscode/*.code-snippets
# Ignore code-workspaces
*.code-workspace
### yarn ###
# https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored
.yarn/*
!.yarn/releases
!.yarn/patches
!.yarn/plugins
!.yarn/sdks
!.yarn/versions
# if you are NOT using Zero-installs, then:
# comment the following lines
!.yarn/cache
# and uncomment the following lines
# .pnp.*
Makefile 0 → 100644
#############################################################################################
#############################################################################################
##
## PROJECT-DEFINITIONS
##
#############################################################################################
#############################################################################################
COMPONENT_NAME := NameOfComponent
#############################################################################################
#############################################################################################
##
## MORE GENERAL BLOCK WITH STANDARD DEFINITIONS
##
#############################################################################################
#############################################################################################
# get Makefile directory name: http://stackoverflow.com/a/5982798/376773
THIS_MAKEFILE_PATH:=$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
PROJECT_ROOT:=$(shell cd $(dir $(THIS_MAKEFILE_PATH));pwd)/
THIS_MAKEFILE:=$(PROJECT_ROOT)$(THIS_MAKEFILE_PATH)
-include $(PROJECT_ROOT)project.mk
## Define the location of Makefiles
MAKEFILE_IMPORT_PATH?=$(PROJECT_ROOT)makefiles/
-include $(MAKEFILE_IMPORT_PATH)project.mk
#############################################################################################
#############################################################################################
##
## INCLUSION OF VARIOUS STANDARD RULES
##
#############################################################################################
#############################################################################################
include $(MAKEFILE_IMPORT_PATH)license-agpl3.mk
include $(MAKEFILE_IMPORT_PATH)placeholder.mk
include $(MAKEFILE_IMPORT_PATH)directories-standard.mk
include $(MAKEFILE_IMPORT_PATH)s3.mk
include $(MAKEFILE_IMPORT_PATH)nodejs.mk
include $(MAKEFILE_IMPORT_PATH)color.mk
include $(MAKEFILE_IMPORT_PATH)terminal.mk
include $(MAKEFILE_IMPORT_PATH)output.mk
include $(MAKEFILE_IMPORT_PATH)version.mk
include $(MAKEFILE_IMPORT_PATH)gitignore.mk
include $(MAKEFILE_IMPORT_PATH)target-help.mk
include $(MAKEFILE_IMPORT_PATH)target-variable.mk
include $(MAKEFILE_IMPORT_PATH)target-docman.mk
include $(MAKEFILE_IMPORT_PATH)target-update-makefiles.mk
include $(MAKEFILE_IMPORT_PATH)target-deploy-tool.mk
include $(MAKEFILE_IMPORT_PATH)target-build-nodejs.mk
include $(MAKEFILE_IMPORT_PATH)target-git.mk
include $(MAKEFILE_IMPORT_PATH)terminal-check.mk
#############################################################################################
'use strict';
/**
* Property-Keys
* @author schukai GmbH
*/
/**
* @private
* @type {symbol}
* @memberOf Monster
* @since 1.24.0
*/
const internalSymbol = Symbol('internalData');
/**
* @private
* @type {symbol}
* @memberOf Monster
* @since 1.25.0
*/
const internalStateSymbol = Symbol('state');
export {
internalSymbol,
internalStateSymbol
}
'use strict';
/**
* @author schukai GmbH
*/
import {assignToNamespace, Monster} from '../namespace.js';
import {Base} from '../types/base.js';
/**
* Constraints are used to define conditions that must be met by the value of a variable.
*
* The uniform API of the constraints allows chains to be formed.
*
* The abstract constraint defines the api for all constraints. mainly the method isValid() is defined.
*
* derived classes must implement the method isValid().
*
* @since 1.3.0
* @copyright schukai GmbH
* @memberOf Monster.Constraints
* @summary The abstract constraint
*/
class AbstractConstraint extends Base {
/**
*
*/
constructor() {
super();
}
/**
* this method must return a promise containing the result of the check.
*
* @param {*} value
* @returns {Promise}
*/
isValid(value) {
return Promise.reject(value);
}
}
assignToNamespace('Monster.Constraints', AbstractConstraint);
export {Monster, AbstractConstraint}
\ No newline at end of file
'use strict';
/**
* @author schukai GmbH
*/
import {assignToNamespace, Monster} from '../namespace.js';
import {AbstractConstraint} from "./abstract.js";
/**
* Constraints are used to define conditions that must be met by the value of a variable.
*
* The uniform API of the constraints allows chains to be formed.
*
* Operators allow you to link constraints together. for example, you can check whether a value is an object or an array. each operator has two operands that are linked together.
*
* @since 1.3.0
* @copyright schukai GmbH
* @memberOf Monster.Constraints
* @summary The abstract operator constraint
*/
class AbstractOperator extends AbstractConstraint {
/**
*
* @param {AbstractConstraint} operantA
* @param {AbstractConstraint} operantB
* @throws {TypeError} "parameters must be from type AbstractConstraint"
*/
constructor(operantA, operantB) {
super();
if (!(operantA instanceof AbstractConstraint) || !(operantB instanceof AbstractConstraint)) {
throw new TypeError("parameters must be from type AbstractConstraint")
}
this.operantA = operantA;
this.operantB = operantB;
}
}
assignToNamespace('Monster.Constraints', AbstractOperator);
export {Monster, AbstractOperator}
\ No newline at end of file
'use strict';
/**
* @author schukai GmbH
*/
import {assignToNamespace, Monster} from '../namespace.js';
import {AbstractOperator} from "./abstractoperator.js";
/**
* Constraints are used to define conditions that must be met by the value of a variable.
*
* The uniform API of the constraints allows chains to be formed.
*
* The AndOperator is used to link several contraints. The constraint is fulfilled if all constraints of the operators are fulfilled.
*
* ```
* <script type="module">
* import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/monster.js';
* new Monster.Constraint.AndOperator();
* </script>
* ```
*
* Alternatively, you can also integrate this function individually.
*
* ```
* <script type="module">
* import {AndOperator} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/modules/constraints/andoperator.js';
* new AndOperator();
* </script>
* ```
*
* @example
*
* import {Valid} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/modules/constraints/valid.js';
* import {Invalid} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/modules/constraints/invalid.js';
* import {AndOperator} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/modules/constraints/andoperator.js';
*
* new AndOperator(
* new Valid(), new Valid()).isValid()
* .then(()=>console.log(true))
* .catch(()=>console.log(false));
* // ↦ true
*
* new AndOperator(
* new Invalid(), new Valid()).isValid()
* .then(()=>console.log(true))
* .catch(()=>console.log(false));
* // ↦ false
*
* @since 1.3.0
* @copyright schukai GmbH
* @memberOf Monster.Constraints
* @summary A and operator constraint
*/
class AndOperator extends AbstractOperator {
/**
* this method return a promise containing the result of the check.
*
* @param {*} value
* @returns {Promise}
*/
isValid(value) {
return Promise.all([this.operantA.isValid(value), this.operantB.isValid(value)]);
}
}
assignToNamespace('Monster.Constraints', AndOperator);
export {Monster, AndOperator}
'use strict';
/**
* @author schukai GmbH
*/
import {assignToNamespace, Monster} from '../namespace.js';
import {AbstractConstraint} from "./abstract.js";
/**
* Constraints are used to define conditions that must be met by the value of a variable.
*
* The uniform API of the constraints allows chains to be formed.
*
* The invalid constraint allows an always invalid query to be performed. this constraint is mainly intended for testing.
*
* You can call the method via the monster namespace `new Monster.Constraint.Invalid()`.
*
* ```
* <script type="module">
* import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/monster.js';
* new Monster.Constraint.Invalid();
* </script>
* ```
*
* Alternatively, you can also integrate this function individually.
*
* ```
* <script type="module">
* import {Invalid} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/modules/constraints/invalid.js';
* new Invalid();
* </script>
* ```
*
* @example
*
* import {Invalid} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/modules/constraints/invalid.js';
*
* new Invalid().isValid()
* .then(()=>console.log(true))
* .catch(()=>console.log(false));
* // ↦ false
*
* @since 1.3.0
* @copyright schukai GmbH
* @memberOf Monster.Constraints
* @summary A constraint that always invalid
*/
class Invalid extends AbstractConstraint {
/**
* this method return a rejected promise
*
* @param {*} value
* @returns {Promise}
*/
isValid(value) {
return Promise.reject(value);
}
}
assignToNamespace('Monster.Constraints', Invalid);
export {Monster, Invalid}
'use strict';
/**
* @author schukai GmbH
*/
import {assignToNamespace, Monster} from '../namespace.js';
import {isArray} from "../types/is.js";
import {AbstractConstraint} from "./abstract.js";
/**
* Constraints are used to define conditions that must be met by the value of a variable.
*
* The uniform API of the constraints allows chains to be formed.
*
* You can call the method via the monster namespace `new Monster.Constraint.IsObject()`.
*
* ```
* <script type="module">
* import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/monster.js';
* new Monster.Constraint.IsArray()
* </script>
* ```
*
* Alternatively, you can also integrate this function individually.
*
* ```
* <script type="module">
* import {IsArray} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/modules/constraints/isarray.js';
* console.log(new IsArray())
* </script>
* ```
*
* @example
*
* import {IsArray} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/modules/constraints/isarray.js';
*
* new IsArray()
* .isValid([])
* .then(()=>console.log(true));
* // ↦ true
*
* new IsArray()
* .isValid(99)
* .catch(e=>console.log(e));
* // ↦ 99
*
* @since 1.3.0
* @copyright schukai GmbH
* @memberOf Monster.Constraints
* @summary A constraint to check if a value is an array
*/
class IsArray extends AbstractConstraint {
/**
* this method return a promise containing the result of the check.
*
* @param {*} value
* @returns {Promise}
*/
isValid(value) {
if (isArray(value)) {
return Promise.resolve(value);
}
return Promise.reject(value);
}
}
assignToNamespace('Monster.Constraints', IsArray);
export {Monster, IsArray}
'use strict';
/**
* @author schukai GmbH
*/
import {assignToNamespace, Monster} from '../namespace.js';
import {isObject} from "../types/is.js";
import {AbstractConstraint} from "./abstract.js";
/**
* Constraints are used to define conditions that must be met by the value of a variable.
*
* The uniform API of the constraints allows chains to be formed.
*
* You can call the method via the monster namespace `new Monster.Constraint.IsObject()`.
*
* ```
* <script type="module">
* import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/monster.js';
* console.log(new Monster.Constraint.IsObject())
* </script>
* ```
*
* Alternatively, you can also integrate this function individually.
*
* ```
* <script type="module">
* import {IsObject} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/modules/constraints/isobject.js';
* console.log(new IsObject())
* </script>
* ```
*
* @example
*
* import {IsObject} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/modules/constraints/isobject.js';
*
* new IsObject()
* .isValid({})
* .then(()=>console.log(true));
* // ↦ true
*
*
* new IsObject()
* .isValid(99)
* .catch(e=>console.log(e));
* // ↦ 99
*
* @since 1.3.0
* @copyright schukai GmbH
* @memberOf Monster.Constraints
* @summary A constraint to check if a value is an object
*/
class IsObject extends AbstractConstraint {
/**
* this method return a promise containing the result of the check.
*
* @param {*} value
* @returns {Promise}
*/
isValid(value) {
if (isObject(value)) {
return Promise.resolve(value);
}
return Promise.reject(value);
}
}
assignToNamespace('Monster.Constraints', IsObject);
export {Monster, IsObject}
'use strict';
/**
* Constraints are used to define conditions that must be met by the value of a variable so that the value can be transferred to the system.
*
* @namespace Constraints
* @memberOf Monster
* @author schukai GmbH
*/
/**
* @private
* @type {string}
*/
export const namespace = "Monster.Constraints";
\ No newline at end of file
'use strict';
/**
* @author schukai GmbH
*/
import {assignToNamespace, Monster} from '../namespace.js';
import {AbstractOperator} from "./abstractoperator.js";
/**
* Constraints are used to define conditions that must be met by the value of a variable.
*
* The uniform API of the constraints allows chains to be formed.
*
* The OrOperator is used to link several constraints. The constraint is fulfilled if one of the constraints is fulfilled.
*
* ```
* <script type="module">
* import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/monster.js';
* new Monster.Constraint.OrOperator();
* </script>
* ```
*
* Alternatively, you can also integrate this function individually.
*
* ```
* <script type="module">
* import {OrOperator} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/modules/constraint/oroperator.js';
* new OrOperator();
* </script>
* ```
*
* @example
*
* import {Valid} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/modules/constraints/valid.js';
* import {Invalid} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/modules/constraints/invalid.js';
* import {OrOperator} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/modules/constraints/oroperator.js';
*
* new OrOperator(
* new Valid(), new Invalid()).isValid()
* .then(()=>console.log(true))
* .catch(()=>console.log(false));
* // ↦ true
*
* new OrOperator(
* new Invalid(), new Invalid()).isValid()
* .then(()=>console.log(true))
* .catch(()=>console.log(false));
* // ↦ false
*
* @since 1.3.0
* @copyright schukai GmbH
* @memberOf Monster.Constraints
* @summary A or operator
*/
class OrOperator extends AbstractOperator {
/**
* this method return a promise containing the result of the check.
*
* @param {*} value
* @returns {Promise}
*/
isValid(value) {
var self = this;
return new Promise(function (resolve, reject) {
let a, b;
self.operantA.isValid(value)
.then(function () {
resolve();
}).catch(function () {
a = false;
/** b has already been evaluated and was not true */
if (b === false) {
reject();
}
});
self.operantB.isValid(value)
.then(function () {
resolve();
}).catch(function () {
b = false;
/** b has already been evaluated and was not true */
if (a === false) {
reject();
}
});
});
}
}
assignToNamespace('Monster.Constraints', OrOperator);
export {Monster, OrOperator}
'use strict';
/**
* @author schukai GmbH
*/
import {assignToNamespace, Monster} from '../namespace.js';
import {AbstractConstraint} from "./abstract.js";
/**
* Constraints are used to define conditions that must be met by the value of a variable.
*
* The uniform API of the constraints allows chains to be formed.
*
* The valid constraint allows an always valid query to be performed. this constraint is mainly intended for testing.
*
* You can call the method via the monster namespace `new Monster.Constraint.Valid()`.
*
* ```
* <script type="module">
* import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/monster.js';
* new Monster.Constraint.Valid();
* </script>
* ```
*
* Alternatively, you can also integrate this function individually.
*
* ```
* <script type="module">
* import {Valid} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/modules/constraints/valid.js';
* new Valid();
* </script>
* ```
*
* @example
*
* import {Valid} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/modules/constraints/valid.js';
*
* new Valid().isValid()
* .then(()=>console.log(true))
* .catch(()=>console.log(false));
* // ↦ true
*
* @since 1.3.0
* @copyright schukai GmbH
* @memberOf Monster.Constraints
* @summary A constraint that always valid
*/
class Valid extends AbstractConstraint {
/**
* this method return a promise containing the result of the check.
*
* @param {*} value
* @returns {Promise}
*/
isValid(value) {
return Promise.resolve(value);
}
}
assignToNamespace('Monster.Constraints', Valid);
export {Monster, Valid}
'use strict';
/**
* @author schukai GmbH
*/
import {assignToNamespace, Monster} from '../namespace.js';
import {isFunction, isObject, isString} from "../types/is.js";
import {validateString} from "../types/validate.js";
import {clone} from "../util/clone.js";
import {DELIMITER, Pathfinder, WILDCARD} from "./pathfinder.js";
/**
* @type {string} parent symbol
*/
export const PARENT = '^';
/**
* With the help of the function `buildMap()`, maps can be easily created from data objects.
*
* Either a simple definition `a.b.c` or a template `${a.b.c}` can be specified as the path.
* Key and value can be either a definition or a template. The key does not have to be defined.
*
* You can call the method via the monster namespace `Monster.Data.buildMap()`.
*
* ```
* <script type="module">
* import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/monster.js';
* console.log(Monster.Data.buildMap())
* </script>
* ```
*
* Alternatively, you can also integrate this function individually.
*
* ```
* <script type="module">
* import {buildMap} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/modules/data/buildmap.js';
* console.log(buildMap())
* </script>
* ```
*
* The templates determine the appearance of the keys and the value of the map. Either a single value `id` can be taken or a composite key `${id} ${name}` can be used.
*
* If you want to access values of the parent data set, you have to use the `^` character `${id} ${^.name}`.
*
* @example
*
* import {buildMap} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/modules/data/buildmap.js';
* // a typical data structure as reported by an api
*
* let map;
* let obj = {
* "data": [
* {
* "id": 10,
* "name": "Cassandra",
* "address": {
* "street": "493-4105 Vulputate Street",
* "city": "Saumur",
* "zip": "52628"
* }
* },
* {
* "id": 20,
* "name": "Holly",
* "address": {
* "street": "1762 Eget Rd.",
* "city": "Schwalbach",
* "zip": "952340"
* }
* },
* {
* "id": 30,
* "name": "Guy",
* "address": {
* "street": "957-388 Sollicitudin Avenue",
* "city": "Panchià",
* "zip": "420729"
* }
* }
* ]
* };
*
* // The function is passed this data structure and with the help of the selector `'data.*'` the data to be considered are selected.
* // The key is given by a simple definition `'id'` and the value is given by a template `'${name} (${address.zip} ${address.city})'`.
* map = buildMap(obj, 'data.*', '${name} (${address.zip} ${address.city})', 'id');
* console.log(map);
*
* // ↦ Map(3) {
* // '10' => 'Cassandra (52628 Saumur)',
* // '20' => 'Holly (952340 Schwalbach)',
* // '30' => 'Guy (420729 Panchià)'
* // }
*
* // If no key is specified, the key from the selection, here the array index, is taken.
* map = buildMap(obj, 'data.*', '${name} (${address.zip} ${address.city})');
* console.log(map);
*
* // ↦ Map(3) {
* // '0' => 'Cassandra (52628 Saumur)',
* // '1' => 'Holly (952340 Schwalbach)',
* // '2' => 'Guy (420729 Panchià)'
* // }
*
* // a filter (function(value, key) {}) can be specified to accept only defined entries.
* map = buildMap(obj, 'data.*', '${name} (${address.zip} ${address.city})', 'id', function (value, key) {
* return (value['id'] >= 20) ? true : false
* });
* console.log(map);
*
* // ↦ Map(2) {
* // 20 => 'Holly (952340 Schwalbach)',
* // 30 => 'Guy (420729 Panchià)'
* // }
*
* @param {*} subject
* @param {string|Monster.Data~exampleSelectorCallback} selector
* @param {string} [valueTemplate]
* @param {string} [keyTemplate]
* @param {Monster.Data~exampleFilterCallback} [filter]
* @return {*}
* @memberOf Monster.Data
* @throws {TypeError} value is neither a string nor a function
* @throws {TypeError} the selector callback must return a map
*/
function buildMap(subject, selector, valueTemplate, keyTemplate, filter) {
return assembleParts(subject, selector, filter, function (v, k, m) {
k = build(v, keyTemplate, k);
v = build(v, valueTemplate);
this.set(k, v);
});
}
/**
* @private
* @param {*} subject
* @param {string|Monster.Data~exampleSelectorCallback} selector
* @param {Monster.Data~exampleFilterCallback} [filter]
* @param {function} callback
* @return {Map}
* @throws {TypeError} selector is neither a string nor a function
*/
function assembleParts(subject, selector, filter, callback) {
const result = new Map();
let map;
if (isFunction(selector)) {
map = selector(subject)
if (!(map instanceof Map)) {
throw new TypeError('the selector callback must return a map');
}
} else if (isString(selector)) {
map = new Map;
buildFlatMap.call(map, subject, selector);
} else {
throw new TypeError('selector is neither a string nor a function')
}
if (!(map instanceof Map)) {
return result;
}
map.forEach((v, k, m) => {
if (isFunction(filter)) {
if (filter.call(m, v, k) !== true) return;
}
callback.call(result, v, k, m);
});
return result;
}
/**
* @private
* @param subject
* @param selector
* @param key
* @param parentMap
* @return {*}
*/
function buildFlatMap(subject, selector, key, parentMap) {
const result = this;
const currentMap = new Map;
const resultLength = result.size;
if (key === undefined) key = [];
let parts = selector.split(DELIMITER);
let current = "", currentPath = [];
do {
current = parts.shift();
currentPath.push(current);
if (current === WILDCARD) {
let finder = new Pathfinder(subject);
let map;
try {
map = finder.getVia(currentPath.join(DELIMITER));
} catch (e) {
let a = e;
map = new Map();
}
for (const [k, o] of map) {
let copyKey = clone(key);
currentPath.map((a) => {
copyKey.push((a === WILDCARD) ? k : a)
})
let kk = copyKey.join(DELIMITER);
let sub = buildFlatMap.call(result, o, parts.join(DELIMITER), copyKey, o);
if (isObject(sub) && parentMap !== undefined) {
sub[PARENT] = parentMap;
}
currentMap.set(kk, sub);
}
}
} while (parts.length > 0);
// no set in child run
if (resultLength === result.size) {
for (const [k, o] of currentMap) {
result.set(k, o);
}
}
return subject;
}
/**
* With the help of this filter callback, values can be filtered out. Only if the filter function returns true, the value is taken for the map.
*
* @callback Monster.Data~exampleFilterCallback
* @param {*} value Value
* @param {string} key Key
* @memberOf Monster.Data
* @see {@link Monster.Data.buildMap}
*/
/**
* Alternatively to a string selector a callback can be specified. this must return a map.
*
* @example
* import {buildMap} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/modules/data/buildmap.js';
*
* let obj = {
* "data": [
* {
* "id": 10,
* "name": "Cassandra",
* "enrichment": {
* variants: [
* {
* sku: 1, label: "XXS", price: [
* {vk: '12.12 €'},
* {vk: '12.12 €'}
* ]
* },
* {
* sku: 2, label: "XS", price: [
* {vk: '22.12 €'},
* {vk: '22.12 €'}
* ]
* },
* {
* sku: 3, label: "S", price: [
* {vk: '32.12 €'},
* {vk: '32.12 €'}
* ]
* },
* {
* sku: 4, label: "L", price: [
* {vk: '42.12 €'},
* {vk: '42.12 €'}
* ]
* }
* ]
*
* }
* },
* {
* "id": 20,
* "name": "Yessey!",
* "enrichment": {
* variants: [
* {
* sku: 1, label: "XXS", price: [
* {vk: '12.12 €'},
* {vk: '12.12 €'}
* ]
* },
* {
* sku: 2, label: "XS", price: [
* {vk: '22.12 €'},
* {vk: '22.12 €'}
* ]
* },
* {
* sku: 3, label: "S", price: [
* {vk: '32.12 €'},
* {vk: '32.12 €'}
* ]
* },
* {
* sku: 4, label: "L", price: [
* {vk: '42.12 €'},
* {vk: '42.12 €'}
* ]
* }
* ]
*
* }
* }
* ]
* };
*
* let callback = function (subject) {
* let m = new Map;
*
* for (const [i, b] of Object.entries(subject.data)) {
*
* let key1 = i;
*
* for (const [j, c] of Object.entries(b.enrichment.variants)) {
* let key2 = j;
*
* for (const [k, d] of Object.entries(c.price)) {
*
* let key3 = k;
*
* d.name = b.name;
* d.label = c.label;
* d.id = [key1, key2, key3].join('.');
*
* m.set(d.id, d);
* }
*
* }
* }
* return m;
* }
*
* let map = buildMap(obj, callback, '${name} ${vk}', '${id}')
*
* // ↦ Map(3) {
* // "0.0.0":"Cassandra 12.12 €",
* // "0.0.1":"Cassandra 12.12 €",
* // "0.1.0":"Cassandra 22.12 €",
* // "0.1.1":"Cassandra 22.12 €",
* // "0.2.0":"Cassandra 32.12 €",
* // "0.2.1":"Cassandra 32.12 €",
* // "0.3.0":"Cassandra 42.12 €",
* // "0.3.1":"Cassandra 42.12 €",
* // "1.0.0":"Yessey! 12.12 €",
* // "1.0.1":"Yessey! 12.12 €",
* // "1.1.0":"Yessey! 22.12 €",
* // "1.1.1":"Yessey! 22.12 €",
* // "1.2.0":"Yessey! 32.12 €",
* // "1.2.1":"Yessey! 32.12 €",
* // "1.3.0":"Yessey! 42.12 €",
* // "1.3.1":"Yessey! 42.12 €"
* // }
*
* @callback Monster.Data~exampleSelectorCallback
* @param {*} subject subject
* @return Map
* @since 1.17.0
* @memberOf Monster.Data
* @see {@link Monster.Data.buildMap}
*/
/**
* @private
* @param {*} subject
* @param {string|undefined} definition
* @param {*} defaultValue
* @return {*}
*/
function build(subject, definition, defaultValue) {
if (definition === undefined) return defaultValue ? defaultValue : subject;
validateString(definition);
const regexp = /(?<placeholder>\${(?<path>[a-z\^A-Z.\-_0-9]*)})/gm
const array = [...definition.matchAll(regexp)];
let finder = new Pathfinder(subject);
if (array.length === 0) {
return finder.getVia(definition);
}
array.forEach((a) => {
let groups = a?.['groups'];
let placeholder = groups?.['placeholder']
if (placeholder === undefined) return;
let path = groups?.['path']
let v = finder.getVia(path);
if (v === undefined) v = defaultValue;
definition = definition.replaceAll(placeholder, v);
})
return definition;
}
assignToNamespace('Monster.Data', buildMap);
export {Monster, buildMap, assembleParts}
'use strict';
/**
* @author schukai GmbH
*/
import {assignToNamespace, Monster} from '../namespace.js';
import {isArray, isObject} from "../types/is.js";
import {Node} from "../types/node.js";
import {NodeList} from "../types/nodelist.js";
import {assembleParts} from "./buildmap.js";
import {extend} from "./extend.js";
/**
* @private
* @type {symbol}
*/
const parentSymbol = Symbol('parent');
/**
* @private
* @type {symbol}
*/
const rootSymbol = Symbol('root');
/**
* @typedef {Object} buildTreeOptions
* @property {array} options.rootReferences=[null, undefined] defines the values for elements without parents
* @property {Monster.Data~exampleFilterCallback} options.filter filtering of the values
* @memberOf Monster.Data
*/
/**
* With the help of the function `buildTree()`, nodes can be easily created from data objects.
*
* You can call the method via the monster namespace `Monster.Data.buildTree()`.
*
* ```
* <script type="module">
* import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/buildtree.js';
* Monster.Data.buildTree()
* </script>
* ```
*
* Alternatively, you can also integrate this function individually.
*
* ```
* <script type="module">
* import {buildTree} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/modules/data/buildtree.js';
* buildTree()
* </script>
* ```
*
* @param {*} subject
* @param {string|Monster.Data~exampleSelectorCallback} selector
* @param {string} idKey
* @param {string} parentIDKey
* @param {buildTreeOptions} [options]
* @return {*}
* @memberOf Monster.Data
* @throws {TypeError} value is neither a string nor a function
* @throws {TypeError} the selector callback must return a map
* @throws {Error} the object has no value for the specified id
* @since 1.26.0
*/
function buildTree(subject, selector, idKey, parentIDKey, options) {
const nodes = new Map;
if (!isObject(options)) {
options = {}
}
options = extend({}, {
rootReferences: [null, undefined],
filter: undefined
}, options)
const filter = options?.filter;
let rootReferences = options.rootReferences;
if (!isArray(rootReferences)) {
rootReferences = [rootReferences];
}
const childMap = assembleParts(subject, selector, filter, function (o, k, m) {
const key = o?.[idKey]
let ref = o?.[parentIDKey]
if (rootReferences.indexOf(ref) !== -1) ref = rootSymbol;
if (key === undefined) {
throw new Error('the object has no value for the specified id')
}
o[parentSymbol] = ref;
const node = new Node(o);
this.has(ref) ? this.get(ref).add(node) : this.set(ref, new NodeList().add(node));
nodes.set(key, node);
})
nodes.forEach(node => {
let id = node?.['value']?.[idKey];
if (childMap.has(id)) {
node.childNodes = childMap.get(id);
childMap.delete(id)
}
})
const list = new NodeList;
childMap.forEach((s) => {
if (s instanceof Set) {
s.forEach((n) => {
list.add(n);
})
}
})
return list;
}
assignToNamespace('Monster.Data', buildTree);
export {Monster, buildTree}
'use strict';
/**
* @author schukai GmbH
*/
import {internalSymbol} from "../constants.js";
import {assignToNamespace, Monster} from '../namespace.js';
import {Base} from "../types/base.js";
import {parseDataURL} from "../types/dataurl.js";
import {isString} from "../types/is.js";
import {ProxyObserver} from "../types/proxyobserver.js";
import {validateObject} from "../types/validate.js";
import {extend} from "./extend.js";
import {Pathfinder} from "./pathfinder.js";
/**
* @private
* @type {symbol}
* @memberOf Monster.Data
* @since 1.24.0
*/
const internalDataSymbol = Symbol('internalData');
/**
* The datasource class is the basis for dealing with different data sources.
* It provides a unified interface for accessing data
*
* You can create an object of this class using the monster namespace `Monster.Data.Datasource()`.
*
* ```
* <script type="module">
* import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/monster.js';
* Monster.Data.Datasource()
* </script>
* ```
*
* Alternatively you can import the class directly
*
* ```
* <script type="module">
* import {Datasource} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/modules/data/datasource.js';
* new Datasource()
* </script>
* ```
*
* @example
*
* import {Datasource} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/modules/data/datasource.js'
*
* class MyDatasource extends Datasource {
*
* }
*
* const ds = new MyDatasource();
*
* @since 1.22.0
* @copyright schukai GmbH
* @memberOf Monster.Data
* @summary The datasource class encapsulates the access to data objects.
*/
class Datasource extends Base {
/**
*
*/
constructor() {
super();
this[internalSymbol] = new ProxyObserver({
'options': extend({}, this.defaults)
});
this[internalDataSymbol] = new ProxyObserver({
});
}
/**
* attach a new observer
*
* @param {Observer} observer
* @returns {Datasource}
*/
attachObserver(observer) {
this[internalDataSymbol].attachObserver(observer)
return this;
}
/**
* detach a observer
*
* @param {Observer} observer
* @returns {Datasource}
*/
detachObserver(observer) {
this[internalDataSymbol].detachObserver(observer)
return this;
}
/**
* @param {Observer} observer
* @returns {boolean}
*/
containsObserver(observer) {
return this[internalDataSymbol].containsObserver(observer);
}
/**
* Derived classes can override and extend this method as follows.
*
* ```
* get defaults() {
* return Object.assign({}, super.defaults, {
* myValue:true
* });
* }
* ```
*/
get defaults() {
return {};
}
/**
* Set option
*
* @param {string} path
* @param {*} value
* @return {Datasource}
*/
setOption(path, value) {
new Pathfinder(this[internalSymbol].getSubject()['options']).setVia(path, value);
return this;
}
/**
* @param {string|object} options
* @return {Datasource}
* @throws {Error} the options does not contain a valid json definition
*/
setOptions(options) {
if (isString(options)) {
options = parseOptionsJSON(options)
}
const self = this;
extend(self[internalSymbol].getSubject()['options'], self.defaults, options);
return self;
}
/**
* nested options can be specified by path `a.b.c`
*
* @param {string} path
* @param {*} defaultValue
* @return {*}
*/
getOption(path, defaultValue) {
let value;
try {
value = new Pathfinder(this[internalSymbol].getRealSubject()['options']).getVia(path);
} catch (e) {
}
if (value === undefined) return defaultValue;
return value;
}
/**
* @throws {Error} this method must be implemented by derived classes.
* @return {Promise}
*/
read() {
throw new Error("this method must be implemented by derived classes")
}
/**
* @throws {Error} this method must be implemented by derived classes.
* @return {Promise}
*/
write() {
throw new Error("this method must be implemented by derived classes")
}
/**
* Returns real object
*
* @return {Object|Array}
*/
get() {
const self = this;
return self[internalDataSymbol].getRealSubject();
}
/**
* @param {Object|Array} data
* @return {Datasource}
*/
set(data) {
const self = this;
self[internalDataSymbol].setSubject(data);
return self;
}
}
/**
* @private
* @param data
* @return {Object}
* @throws {Error} the options does not contain a valid json definition
*/
function parseOptionsJSON(data) {
if (isString(data)) {
// the configuration can be specified as a data url.
try {
let dataUrl = parseDataURL(data);
data = dataUrl.content;
} catch (e) {
}
try {
let obj = JSON.parse(data);
validateObject(obj);
return obj;
} catch (e) {
throw new Error('the options does not contain a valid json definition (actual: ' + data + ').');
}
}
return {};
}
assignToNamespace('Monster.Data', Datasource);
export {Monster, Datasource}
'use strict';
/**
* Namespace for datasources
*
* @namespace Monster.Data.Datasource
* @memberOf Monster.Data
* @author schukai GmbH
*/
/**
* @private
* @type {string}
*/
export const namespace = "Monster.Data.Datasource";
\ No newline at end of file
'use strict';
/**
* @author schukai GmbH
*/
import {internalSymbol} from "../../constants.js";
import {assignToNamespace, Monster} from '../../namespace.js';
import {isObject} from "../../types/is.js";
import {Datasource} from "../datasource.js";
import {Pathfinder} from "../pathfinder.js";
import {Pipe} from "../pipe.js";
import {WriteError} from "./restapi/writeerror.js";
/**
* You can create an object of this class using the monster namespace `Monster.Data.Datasource.RestAPI()`.
*
* ```
* <script type="module">
* import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/monster.js';
* Monster.Data.Datasource.RestAPI()
* </script>
* ```
*
* Alternatively you can import the class directly
*
* ```
* <script type="module">
* import {RestAPI} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/modules/data/datasource/restapi.js';
* new RestAPI()
* </script>
* ```
*
* @example
*
* import {RestAPI} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/modules/data/datasource/restapi.js';
*
* const ds = new RestAPI({
* url: 'https://httpbin.org/get'
* },{
* url: 'https://httpbin.org/post'
* });
*
* ds.set({flag:true})
* ds.write().then(()=>console.log('done'));
* ds.read().then(()=>console.log('done'));
*
* @since 1.22.0
* @copyright schukai GmbH
* @memberOf Monster.Data.Datasource
* @summary The LocalStorage class encapsulates the access to data objects.
*/
class RestAPI extends Datasource {
/**
*
* @param {Object} [readDefinition] An options object containing any custom settings that you want to apply to the read request.
* @param {Object} [writeDefinition] An options object containing any custom settings that you want to apply to the write request.
* @throws {TypeError} value is not a string
*/
constructor(readDefinition, writeDefinition) {
super();
const options = {}
if (isObject(readDefinition)) options.read = readDefinition;
if (isObject(writeDefinition)) options.write = writeDefinition;
this.setOptions(options);
}
/**
* @property {string} url=undefined Defines the resource that you wish to fetch.
* @property {Object} write={} Options
* @property {Object} write.init={} An options object containing any custom settings that you want to apply to the request. The parameters are identical to those of the {@link https://developer.mozilla.org/en-US/docs/Web/API/Request/Request|Request constructor}
* @property {string} write.init.method=POST
* @property {string} write.acceptedStatus=[200,201]
* @property {string} write.url URL
* @property {Object} write.mapping the mapping is applied before writing.
* @property {String} write.mapping.transformer Transformer to select the appropriate entries
* @property {Object} write.report
* @property {String} write.report.path Path to validations
* @property {Monster.Data.Datasource~exampleCallback[]} write.mapping.callback with the help of the callback, the structures can be adjusted before writing.
* @property {Object} read.init={} An options object containing any custom settings that you want to apply to the request. The parameters are identical to those of the {@link https://developer.mozilla.org/en-US/docs/Web/API/Request/Request|Request constructor}
* @property {string} read.init.method=GET
* @property {string} read.acceptedStatus=[200]
* @property {string} read.url URL
* @property {Object} read.mapping the mapping is applied after reading.
* @property {String} read.mapping.transformer Transformer to select the appropriate entries
* @property {Monster.Data.Datasource~exampleCallback[]} read.mapping.callback with the help of the callback, the structures can be adjusted after reading.
*/
get defaults() {
return Object.assign({}, super.defaults, {
write: {
init: {
method: 'POST',
},
acceptedStatus: [200, 201],
url: undefined,
mapping: {
transformer: undefined,
callbacks: []
},
report: {
path: undefined
}
},
read: {
init: {
method: 'GET'
},
acceptedStatus: [200],
url: undefined,
mapping: {
transformer: undefined,
callbacks: []
},
},
});
}
/**
* @return {Promise}
* @throws {Error} the options does not contain a valid json definition
* @throws {TypeError} value is not a object
* @throws {Error} the data cannot be read
*/
read() {
const self = this;
let response;
let init = self.getOption('read.init');
if (!isObject(init)) init = {};
return fetch(self.getOption('read.url'), init).then(resp => {
response = resp;
const acceptedStatus = self.getOption('read.acceptedStatus', [200]);
if (acceptedStatus.indexOf(resp.status) === -1) {
throw Error('the data cannot be read (response ' + resp.status + ')')
}
return resp.text()
}).then(body => {
let obj;
try {
obj = JSON.parse(body);
} catch (e) {
if (body.length > 100) {
body = body.substring(0, 97) + '...';
}
throw new Error('the response does not contain a valid json (actual: ' + body + ').');
}
let transformation = self.getOption('read.mapping.transformer');
if (transformation !== undefined) {
const pipe = new Pipe(transformation);
obj = pipe.run(obj);
}
self.set(obj);
return response;
})
}
/**
* @return {Promise}
* @throws {WriteError} the data cannot be written
*/
write() {
const self = this;
let init = self.getOption('write.init');
if (!isObject(init)) init = {};
if (typeof init['headers'] !== 'object') {
init['headers'] = {
'Content-Type': 'application/json'
}
}
let obj = self.get();
let transformation = self.getOption('write.mapping.transformer');
if (transformation !== undefined) {
const pipe = new Pipe(transformation);
obj = pipe.run(obj);
}
let sheathingObject = self.getOption('write.sheathing.object');
let sheathingPath = self.getOption('write.sheathing.path');
let reportPath = self.getOption('write.report.path');
if (sheathingObject && sheathingPath) {
const sub = obj;
obj = sheathingObject;
(new Pathfinder(obj)).setVia(sheathingPath, sub);
}
init['body'] = JSON.stringify(obj);
return fetch(self.getOption('write.url'), init).then(response => {
const acceptedStatus = self.getOption('write.acceptedStatus', [200, 2001]);
if (acceptedStatus.indexOf(response.status) === -1) {
return response.text().then((body) => {
let obj, validation;
try {
obj = JSON.parse(body);
validation = new Pathfinder(obj).getVia(reportPath)
} catch (e) {
if (body.length > 100) {
body = body.substring(0, 97) + '...';
}
throw new Error('the response does not contain a valid json (actual: ' + body + ').');
}
throw new WriteError('the data cannot be written (response ' + response.status + ')', response, validation)
})
}
return response;
});
}
/**
* @return {RestAPI}
*/
getClone() {
const self = this;
return new RestAPI(self[internalSymbol].getRealSubject()['options'].read, self[internalSymbol].getRealSubject()['options'].write);
}
}
/**
* This callback can be passed to a datasource and is used to adapt data structures.
*
* @callback Monster.Data.Datasource~exampleCallback
* @param {*} value Value
* @param {string} key Key
* @memberOf Monster.Data
* @see Monster.Data.Datasource
*/
assignToNamespace('Monster.Data.Datasource', RestAPI);
export {Monster, RestAPI}
'use strict';
/**
* @author schukai GmbH
*/
import {internalSymbol} from "../../../constants.js";
import {assignToNamespace, Monster} from '../../../namespace.js';
/**
* Error message for API requests with extension of request and validation.
*
* @since 1.24.0
* @copyright schukai GmbH
* @memberOf Monster.Data.Datasource.RestAPI
* @summary the error is thrown by the rest api in case of error
*/
class WriteError extends Error {
/**
*
* @param {string} message
* @param {Response} response
*/
constructor(message, response, validation) {
super(message);
this[internalSymbol] = {
response: response,
validation: validation
};
}
/**
* @return {Response}
*/
getResponse() {
return this[internalSymbol]['response']
}
/**
* @return {Object}
*/
getValidation() {
return this[internalSymbol]['validation']
}
}
assignToNamespace('Monster.Data.Datasource.RestAPI', WriteError);
export {Monster, WriteError}
\ No newline at end of file
'use strict';
/**
* @author schukai GmbH
*/
import {internalSymbol} from "../../constants.js";
import {assignToNamespace, Monster} from '../../namespace.js';
import {validateString} from "../../types/validate.js";
import {Datasource} from "../datasource.js";
/**
* @private
* @type {symbol}
*/
const storageObjectSymbol = Symbol('storageObject');
/**
* You can create an object of this class using the monster namespace `Monster.Data.Datasource.Storage()`.
*
* ```
* <script type="module">
* import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/monster.js';
* Monster.Data.Datasource.Storage()
* </script>
* ```
*
* Alternatively you can import the class directly
*
* ```
* <script type="module">
* import {Storage} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/modules/data/datasource/storage.js';
* new Storage()
* </script>
* ```
*
* @example
*
* import {Storage} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/modules/data/datasource/storage.js';
*
* new Datasource();
*
* @since 1.22.0
* @copyright schukai GmbH
* @memberOf Monster.Data.Datasource
* @summary The Storage class encapsulates the access to data objects over WebStorageAPI.
*/
class Storage extends Datasource {
/**
*
* @param {string} key LocalStorage Key
* @throws {TypeError} value is not a string
*/
constructor(key) {
super();
this.setOption('key', validateString(key));
}
/**
* @property {string} key=undefined LocalStorage Key
*/
get defaults() {
return Object.assign({}, super.defaults, {
key: undefined,
});
}
/**
* @throws {Error} this method must be implemented by derived classes.
* @return {external:Storage}
* @private
*/
[storageObjectSymbol]() {
throw new Error("this method must be implemented by derived classes")
}
/**
* @return {Promise}
* @throws {Error} the options does not contain a valid json definition
* @throws {TypeError} value is not a object
* @throws {Error} the data cannot be read
*/
read() {
const self = this;
const storage = self[storageObjectSymbol]();
return new Promise(function (resolve) {
const data = JSON.parse(storage.getItem(self.getOption('key')));
self.set(data??{});
resolve();
})
}
/**
* @return {Storage}
* @throws {Error} the data cannot be written
*/
write() {
const self = this;
const storage = self[storageObjectSymbol]();
return new Promise(function (resolve) {
const data = self.get();
if (data === undefined) {
storage.removeItem(self.getOption('key'));
} else {
storage.setItem(self.getOption('key'), JSON.stringify(data));
}
resolve();
})
}
/**
* @return {Storage}
*/
getClone() {
const self=this;
return new Storage(self[internalSymbol].getRealSubject()['options'].key);
}
}
assignToNamespace('Monster.Data.Datasource', Storage);
export {Monster, Storage, storageObjectSymbol}
'use strict';
/**
* @author schukai GmbH
*/
import {internalSymbol} from "../../../constants.js";
import {assignToNamespace, Monster} from '../../../namespace.js';
import {getGlobalObject} from "../../../types/global.js";
import {Datasource} from "../../datasource.js";
import {Storage, storageObjectSymbol} from "../storage.js";
/**
*
*
* You can create an object of this class using the monster namespace `Monster.Data.Datasource.Storage.LocalStorage()`.
*
* ```
* <script type="module">
* import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/monster.js';
* Monster.Data.Datasource.Storage.LocalStorage()
* </script>
* ```
*
* Alternatively you can import the class directly
*
* ```
* <script type="module">
* import {LocalStorage} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.31.0/dist/modules/data/datasource/storage/localstorage.js';
* new LocalStorage()
* </script>
* ```
*
* @since 1.22.0
* @copyright schukai GmbH
* @memberOf Monster.Data.Datasource.Storage
* @summary The LocalStorage class encapsulates the access to data objects.
*/
class LocalStorage extends Storage {
/**
* @throws {Error} this method must be implemented by derived classes.
* @return {external:localStorage}
* @private
*/
[storageObjectSymbol]() {
return getGlobalObject('localStorage');
}
/**
* Create clone
* @return {LocalStorage}
*/
getClone() {
const self = this;
return new LocalStorage(self[internalSymbol].getRealSubject()['options'].key);
}
}
assignToNamespace('Monster.Data.Datasource.Storage', LocalStorage);
export {Monster, LocalStorage}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment