├── .coveralls.yml ├── .eslintrc.json ├── .gitignore ├── .gitmodules ├── .jsbeautify ├── .jshintrc ├── .npmignore ├── .travis.yml ├── Gruntfile.js ├── README.md ├── __STRUCTURE ├── .eslintrc.json ├── app │ └── views │ │ ├── default │ │ ├── index.ejs │ │ └── show.ejs │ │ ├── home │ │ ├── error404.ejs │ │ ├── error500.ejs │ │ └── index.ejs │ │ ├── item │ │ ├── index.ejs │ │ └── show.ejs │ │ ├── shared │ │ ├── content.ejs │ │ ├── footer.ejs │ │ ├── header.ejs │ │ ├── nav.ejs │ │ ├── nav_header.ejs │ │ ├── simple_nav.ejs │ │ └── single.ejs │ │ └── user │ │ ├── index.ejs │ │ └── show.ejs ├── content │ ├── config │ │ ├── config.js │ │ ├── databases │ │ │ └── standard │ │ │ │ └── models │ │ │ │ ├── account.lowkie.js │ │ │ │ ├── account.mongoose.js │ │ │ │ ├── account.sequelize.js │ │ │ │ ├── asset.lowkie.js │ │ │ │ ├── asset.mongoose.js │ │ │ │ ├── asset.sequelize.js │ │ │ │ ├── attribute.sequelize.js │ │ │ │ ├── category.lowkie.js │ │ │ │ ├── category.mongoose.js │ │ │ │ ├── category.sequelize.js │ │ │ │ ├── contenttype.lowkie.js │ │ │ │ ├── contenttype.mongoose.js │ │ │ │ ├── contenttype.sequelize.js │ │ │ │ ├── data.lowkie.js │ │ │ │ ├── data.mongoose.js │ │ │ │ ├── data.sequelize.js │ │ │ │ ├── item.lowkie.js │ │ │ │ ├── item.mongoose.js │ │ │ │ ├── item.sequelize.js │ │ │ │ ├── tag.lowkie.js │ │ │ │ ├── tag.mongoose.js │ │ │ │ ├── tag.sequelize.js │ │ │ │ ├── user.lowkie.js │ │ │ │ ├── user.mongoose.js │ │ │ │ ├── user.sequelize.js │ │ │ │ ├── usergroup.lowkie.js │ │ │ │ ├── usergroup.mongoose.js │ │ │ │ ├── usergroup.sequelize.js │ │ │ │ ├── userprivilege.lowkie.js │ │ │ │ ├── userprivilege.mongoose.js │ │ │ │ ├── userprivilege.sequelize.js │ │ │ │ ├── userrole.lowkie.js │ │ │ │ ├── userrole.mongoose.js │ │ │ │ └── userrole.sequelize.js │ │ └── startup.js │ └── container │ │ └── periodicjs.container.default │ │ ├── .eslintrc.json │ │ ├── LICENSE │ │ ├── README.md │ │ ├── commands │ │ └── index.js │ │ ├── config │ │ ├── databases │ │ │ └── .gitkeep │ │ └── settings.js │ │ ├── controllers │ │ └── index.js │ │ ├── doc │ │ └── .gitkeep │ │ ├── index.js │ │ ├── package.json │ │ ├── periodicjs.ext.json │ │ ├── resources │ │ └── .gitkeep │ │ ├── routers │ │ └── index.js │ │ ├── test │ │ └── .gitkeep │ │ ├── transforms │ │ └── index.js │ │ ├── utilities │ │ ├── .gitkeep │ │ └── index.js │ │ └── views │ │ └── .gitkeep ├── logs │ └── .gitkeep ├── processes │ └── .gitkeep └── public │ ├── .gitkeep │ ├── favicon.png │ ├── stylesheets │ └── default.css │ └── uploads │ └── files │ └── .gitkeep ├── bin ├── __SETUP │ ├── index.js │ └── package.json └── index.js ├── doc ├── .sample.env ├── README.md ├── advanced │ └── 00-testing-developing.md ├── api.md ├── cli │ ├── 01-overview.md │ ├── 02-command-line-interface.md │ └── 03-interactive-shell.md ├── configuration │ ├── 01-overview.md │ ├── 02-what-are-periodic-configurations.md │ ├── 03-how-are-runtime-environments-configured.md │ ├── 04-creating-your-own-configurations.md │ └── 05-adding-and-removing-configurations.md ├── extensions │ ├── 01-overview.md │ ├── 02-what-are-periodic-extensions.md │ ├── 03-how-are-extensions-loaded.md │ ├── 04-what-are-some-common-extensions.md │ ├── 05-installing-and-removing-extensions.md │ ├── 06-configuring-extensions.md │ └── 07-creating-your-own-extensions.md ├── getting_started.md ├── html │ ├── Periodic.Periodic.html │ ├── Periodic.html │ ├── fonts │ │ ├── OpenSans-Bold-webfont.eot │ │ ├── OpenSans-Bold-webfont.svg │ │ ├── OpenSans-Bold-webfont.woff │ │ ├── OpenSans-BoldItalic-webfont.eot │ │ ├── OpenSans-BoldItalic-webfont.svg │ │ ├── OpenSans-BoldItalic-webfont.woff │ │ ├── OpenSans-Italic-webfont.eot │ │ ├── OpenSans-Italic-webfont.svg │ │ ├── OpenSans-Italic-webfont.woff │ │ ├── OpenSans-Light-webfont.eot │ │ ├── OpenSans-Light-webfont.svg │ │ ├── OpenSans-Light-webfont.woff │ │ ├── OpenSans-LightItalic-webfont.eot │ │ ├── OpenSans-LightItalic-webfont.svg │ │ ├── OpenSans-LightItalic-webfont.woff │ │ ├── OpenSans-Regular-webfont.eot │ │ ├── OpenSans-Regular-webfont.svg │ │ └── OpenSans-Regular-webfont.woff │ ├── global.html │ ├── index.html │ ├── index.js.html │ ├── lib_defaults_environment.js.html │ ├── lib_init_config.js.html │ ├── lib_init_consoleTimer.js.html │ ├── lib_init_express.js.html │ ├── lib_init_folderStructure.js.html │ ├── lib_init_logger.js.html │ ├── lib_init_runtime.js.html │ ├── lib_periodicClass.js.html │ ├── lib_periodicProxyHandler.js.html │ ├── lib_schemas_config.lowkie.js.html │ ├── lib_schemas_config.mongoose.js.html │ ├── lib_utilities_routing.js.html │ ├── lib_utilities_viewHelper.js.html │ ├── module-periodic.html │ ├── scripts │ │ ├── linenumber.js │ │ └── prettify │ │ │ ├── Apache-License-2.0.txt │ │ │ ├── lang-css.js │ │ │ └── prettify.js │ └── styles │ │ ├── jsdoc-default.css │ │ ├── prettify-jsdoc.css │ │ └── prettify-tomorrow.css ├── images │ ├── dark_logo_transparent_background.png │ ├── getting-started │ │ └── 01-setup-install.gif │ ├── logo.png │ ├── logo.svg │ ├── logo_sm.png │ ├── white_logo_color_background.png │ └── white_logo_color_background.svg └── overview │ ├── 03-singleton.md │ ├── 04-initialization.md │ ├── 05-customization.md │ └── command_line_interface.md ├── index.js ├── jsdoc.json ├── lib ├── crud │ ├── __EXT_CONTAINER_STRUCTURE │ │ ├── .coveralls.yml │ │ ├── .eslintrc.json │ │ ├── .travis.yml │ │ ├── Gruntfile.js │ │ ├── LICENSE │ │ ├── README.md │ │ ├── commands │ │ │ └── index.js │ │ ├── config │ │ │ ├── databases │ │ │ │ └── .gitkeep │ │ │ └── settings.js │ │ ├── controllers │ │ │ └── index.js │ │ ├── doc │ │ │ └── .gitkeep │ │ ├── index.js │ │ ├── jsdoc.json │ │ ├── package.json │ │ ├── periodicjs.ext.json │ │ ├── public │ │ │ └── .gitkeep │ │ ├── resources │ │ │ ├── .gitkeep │ │ │ └── async_routers │ │ │ │ └── index.js │ │ ├── routers │ │ │ └── index.js │ │ ├── test │ │ │ └── unit │ │ │ │ └── periodic_extension_spec.js │ │ ├── transforms │ │ │ └── index.js │ │ ├── utilities │ │ │ └── index.js │ │ └── views │ │ │ └── .gitkeep │ ├── config.js │ ├── ext.js │ └── index.js ├── defaults │ ├── demo │ │ ├── certs │ │ │ ├── 2017.testperiodic.ssl_cert.pem │ │ │ ├── 2017.testperiodic.ssl_key.p12 │ │ │ ├── 2017.testperiodic.ssl_key.pem │ │ │ └── 2017.testperiodic.ssl_key.pfx │ │ └── configs │ │ │ └── testconfig.json │ ├── environment.js │ ├── index.js │ └── schema │ │ ├── index.js │ │ ├── lowkie.schema.js │ │ ├── mongoose.schema.js │ │ └── sequelize.schema.js ├── extension │ ├── index.js │ ├── install.js │ ├── setup.js │ └── uninstall.js ├── init │ ├── cli.js │ ├── cluster.js │ ├── config.js │ ├── consoleTimer.js │ ├── express.js │ ├── folderStructure.js │ ├── index.js │ ├── logger.js │ ├── runtime.js │ └── server.js ├── periodic.js ├── periodicClass.js ├── periodicProxyHandler.js ├── schemas │ ├── config.lowkie.js │ ├── config.mongoose.js │ ├── config.sequelize.js │ ├── extension.lowkie.js │ ├── extension.mongoose.js │ ├── extension.sequelize.js │ └── index.js └── utilities │ ├── auth.js │ ├── fetchUtils.js │ ├── index.js │ ├── middleware.js │ ├── mock.js │ ├── routing.js │ └── viewHelper.js ├── package-lock.json ├── package.json ├── test ├── mock │ ├── config │ │ ├── config_test_config.js │ │ └── ext_doc.js │ ├── extensions │ │ ├── periodicjs.ext.admin │ │ │ ├── package.json │ │ │ └── periodicjs.ext.json │ │ ├── periodicjs.ext.cloudupload │ │ │ ├── package.json │ │ │ └── periodicjs.ext.json │ │ ├── periodicjs.ext.db_seed │ │ │ ├── package.json │ │ │ └── periodicjs.ext.json │ │ ├── periodicjs.ext.login │ │ │ ├── package.json │ │ │ └── periodicjs.ext.json │ │ ├── periodicjs.ext.login_mfa │ │ │ ├── package.json │ │ │ └── periodicjs.ext.json │ │ ├── periodicjs.ext.mailer │ │ │ ├── package.json │ │ │ └── periodicjs.ext.json │ │ ├── periodicjs.ext.oauth2client │ │ │ ├── package.json │ │ │ └── periodicjs.ext.json │ │ ├── periodicjs.ext.oauth2server │ │ │ ├── package.json │ │ │ └── periodicjs.ext.json │ │ ├── periodicjs.ext.test │ │ │ ├── package.json │ │ │ └── periodicjs.ext.json │ │ └── periodicjs.ext.uac │ │ │ ├── package.json │ │ │ └── periodicjs.ext.json │ └── sample_configs │ │ ├── display_config.json │ │ ├── dummy_config.json │ │ └── server_config.json └── unit │ ├── crud │ ├── config_spec.js │ ├── ext_spec.js │ └── newtestext.md │ ├── defaults │ └── schemas.js │ ├── extension │ ├── install_spec.js │ ├── setup_spec.js │ └── uninstall_spec.js │ ├── init │ ├── cli_spec.js │ ├── cluster_spec.js │ ├── config_databases_spec.js │ ├── config_spec.js │ ├── console_spec.js │ ├── express_spec.js │ ├── folder_structure_spec.js │ ├── logger_spec.js │ ├── runtime_spec.js │ └── server_spec.js │ ├── periodic_spec.js │ ├── proxyhandler_spec.js │ └── utilities │ ├── fetch_utils_spec.js │ ├── mock_spec.js │ ├── routing_spec.js │ └── viewHelper_spec.js └── yarn.lock /.coveralls.yml: -------------------------------------------------------------------------------- 1 | service_name: travis-pro 2 | repo_token: T6XtkChp4izGFpxoTM4xSbyiDXsELA8Bb -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "eslint:recommended", 3 | "plugins": [], 4 | "parserOptions": { 5 | "ecmaFeatures": { 6 | "ecmaVersion": 6, 7 | "jsx": true 8 | } 9 | }, 10 | "ecmaFeatures": { 11 | "ecmaVersion": 6 12 | }, 13 | "rules": { 14 | "jsx-quotes": ["error", "prefer-double"], 15 | "indent": ["error", 2], 16 | "quotes": ["error", "single"], 17 | "semi": ["warn", "always"], 18 | "comma-dangle": ["warn", "always"], 19 | "comma-spacing": "warn", 20 | "array-bracket-spacing": "warn", 21 | "object-curly-spacing": ["error", "always"], 22 | "eqeqeq": "warn", 23 | "no-cond-assign": ["warn", "always"], 24 | "no-unused-vars": "warn", 25 | "no-console": "warn", 26 | "brace-style": ["warn", "1tbs"], 27 | "strict": ["error", "safe"] 28 | }, 29 | "env": { 30 | "browser": true, 31 | "commonjs": true, 32 | "es6": true, 33 | "node": true 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | logs/* 3 | .DS_store 4 | *.DS_store 5 | lib-cov 6 | *.seed 7 | *.log 8 | #*.csv 9 | *.dat 10 | *.out 11 | *.pid 12 | *.swp 13 | *.swo 14 | *.gz 15 | *.tempconf 16 | dump.rdb 17 | session-store.db 18 | package-lock.json 19 | .vscode 20 | .nyc_output 21 | 22 | 23 | 24 | # Logs 25 | !logs 26 | *.log 27 | 28 | # Runtime data 29 | pids 30 | *.pid 31 | *.seed 32 | !processes 33 | processes/* 34 | 35 | # Directory for instrumented libs generated by jscoverage/JSCover 36 | lib-cov 37 | 38 | # Coverage directory used by tools like istanbul 39 | coverage 40 | 41 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 42 | .grunt 43 | 44 | # Compiled binary addons (http://nodejs.org/api/addons.html) 45 | build/Release 46 | 47 | # Dependency directory 48 | # Deployed apps should consider commenting this line out: 49 | # see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git 50 | node_modules 51 | typings/* 52 | public/uploads/files 53 | !public/uploads/files/2014/10 54 | !cache 55 | cache/* 56 | content/files/backups 57 | content/files/backups/.restoretemp 58 | content/files/backups/.tempbackup 59 | *.backup 60 | !.gitignore 61 | !*.gitignore 62 | coverage.html 63 | 64 | #.DS_Store 65 | #lib-cov 66 | #coverage.html 67 | #.git* 68 | #docs/ 69 | #examples/ 70 | #support/ 71 | #test/ 72 | #testing.js 73 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule ".coverage"] 2 | path = .coverage 3 | url = https://github.com/visionmedia/node-jscoverage 4 | -------------------------------------------------------------------------------- /.jsbeautify: -------------------------------------------------------------------------------- 1 | { 2 | "html": { 3 | "braceStyle": "collapse", 4 | "indentChar": " ", 5 | "indentScripts": "keep", 6 | "indentSize": 2, 7 | "maxPreserveNewlines": 10, 8 | "preserveNewlines": true, 9 | "unformatted": ["a", "sub", "sup", "b", "i", "u"], 10 | "wrapLineLength": 0 11 | }, 12 | "ejs": { 13 | "indentChar": " ", 14 | "indentScripts": "keep", 15 | "indentInnerHtml":true, 16 | "indentSize": 2, 17 | "maxPreserveNewlines": 10, 18 | "preserveNewlines": true, 19 | "wrapLineLength": 0, 20 | "spaceBeforeConditional": true, 21 | "unformatted": ["a", "sub", "sup", "b", "i", "u","%=","%"] 22 | }, 23 | "css": { 24 | "indentChar": " ", 25 | "indentSize": 2, 26 | "indentWithTabs": true 27 | }, 28 | "less": { 29 | "indentChar": " ", 30 | "indentSize": 2, 31 | "indentWithTabs": true 32 | }, 33 | "js": { 34 | "braceStyle": "end-expand", 35 | "breakChainedMethods": false, 36 | "e4x": false, 37 | "evalCode": false, 38 | "indentChar": " ", 39 | "indentLevel": 0, 40 | "indentSize": 2, 41 | "indentWithTabs": true, 42 | "jslintHappy": true, 43 | "keepArrayIndentation": false, 44 | "keepFunctionIndentation": false, 45 | "maxPreserveNewlines": 10, 46 | "preserveNewlines": true, 47 | "spaceBeforeConditional": true, 48 | "spaceInParen": false, 49 | "unescapeStrings": false, 50 | "wrapLineLength": 0 51 | } 52 | } -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "curly": true, 3 | "noempty": true, 4 | "newcap": true, 5 | "eqeqeq": true, 6 | "eqnull": true, 7 | "undef": true, 8 | "esversion": 6, 9 | "devel": true, 10 | "node": true, 11 | "browser": true, 12 | "evil": false, 13 | "latedef": true, 14 | "nonew": true, 15 | "trailing": true, 16 | "immed": true, 17 | "smarttabs": true, 18 | "strict": true, 19 | "predef": [ 20 | "describe", 21 | "it", 22 | "before", 23 | "beforeEach", 24 | "after", 25 | "afterEach" 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | logs/* 3 | .DS_store 4 | *.DS_store 5 | lib-cov 6 | *.seed 7 | *.log 8 | #*.csv 9 | *.dat 10 | *.out 11 | *.pid 12 | *.swp 13 | *.swo 14 | *.gz 15 | *.tempconf 16 | 17 | # Logs 18 | !logs 19 | *.log 20 | 21 | # Runtime data 22 | pids 23 | *.pid 24 | *.seed 25 | !processes 26 | processes/* 27 | 28 | # Directory for instrumented libs generated by jscoverage/JSCover 29 | lib-cov 30 | 31 | # Coverage directory used by tools like istanbul 32 | coverage 33 | 34 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 35 | .grunt 36 | 37 | # Compiled binary addons (http://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directory 41 | # Deployed apps should consider commenting this line out: 42 | # see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git 43 | node_modules 44 | public/uploads/files 45 | !public/uploads/files/2014/10 46 | !cache 47 | cache/* 48 | content/files/backups 49 | content/files/backups/.restoretemp 50 | content/files/backups/.tempbackup 51 | *.backup 52 | !.gitignore 53 | !*.gitignore 54 | coverage.html 55 | 56 | #.DS_Store 57 | #lib-cov 58 | #coverage.html 59 | #.git* 60 | #docs/ 61 | #examples/ 62 | #support/ 63 | #test/ 64 | #testing.js -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '10' 4 | - '9' 5 | - '8' 6 | env: 7 | - CXX=g++-4.8 8 | addons: 9 | apt: 10 | sources: 11 | - ubuntu-toolchain-r-test 12 | packages: 13 | - g++-4.8 14 | 15 | services: 16 | - mongodb 17 | - postgresql 18 | - redis-server 19 | 20 | notifications: 21 | irc: 22 | channels: 23 | - "irc.freenode.org#periodicjs" 24 | template: 25 | - "Build by %{author} :" 26 | - "Git Info: %{branch} - %{commit} with the message %{commit_message}" 27 | - "Travis states: %{message}" 28 | - "Build Details: %{build_url}" 29 | - "Change View: %{compare_url}" 30 | - "result = %{result}" 31 | - "elapsed time... %{duration}" 32 | use_notice: true 33 | skip_join: false 34 | 35 | install: 36 | - npm install grunt-cli istanbul -g 37 | - npm install 38 | # - npm install --skip_app_post_install=true 39 | 40 | branches: 41 | only: 42 | - master 43 | - periodic10 44 | - devel 45 | git: 46 | submodules: false 47 | 48 | before_script: 49 | - psql -c 'create database travis_ci_test;' -U postgres 50 | 51 | script: 52 | - npm set progress=false && grunt test 53 | -------------------------------------------------------------------------------- /__STRUCTURE/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "eslint:recommended", 3 | "plugins": [], 4 | "parserOptions": { 5 | "ecmaFeatures": { 6 | "ecmaVersion": 6, 7 | "jsx": true 8 | } 9 | }, 10 | "ecmaFeatures": { 11 | "ecmaVersion": 6 12 | }, 13 | "rules": { 14 | "jsx-quotes": ["error", "prefer-double"], 15 | "indent": ["error", 2], 16 | "quotes": ["error", "single"], 17 | "semi": ["warn", "always"], 18 | "comma-dangle": ["warn", "always"], 19 | "comma-spacing": "warn", 20 | "array-bracket-spacing": "warn", 21 | "object-curly-spacing": ["error", "always"], 22 | "eqeqeq": "warn", 23 | "no-cond-assign": ["warn", "always"], 24 | "no-unused-vars": "warn", 25 | "no-console": "warn", 26 | "brace-style": ["warn", "1tbs"], 27 | "strict": ["error", "safe"] 28 | }, 29 | "env": { 30 | "browser": true, 31 | "commonjs": true, 32 | "es6": true, 33 | "node": true 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /__STRUCTURE/app/views/default/index.ejs: -------------------------------------------------------------------------------- 1 | <%- include('../shared/header') %> 2 | <%- include('../shared/nav') %> 3 | <% 4 | const pluralize = periodic.viewHelper.pluralize; 5 | const entityFromURL = locals.request.parsed.pathname.replace(/\//gi,'');// const entityFromURL = locals.request.originalurl.split('/')[locals.request.originalurl.split('/').length-1]; 6 | const singularEntity = pluralize.singular(entityFromURL); 7 | %> 8 | 9 | <%- include('../shared/content',{ 10 | entitytype:singularEntity, 11 | items: locals[entityFromURL], 12 | }); 13 | %> 14 | <%- include('../shared/footer') %> -------------------------------------------------------------------------------- /__STRUCTURE/app/views/default/show.ejs: -------------------------------------------------------------------------------- 1 | <%- include('../shared/header') %> 2 | <%- include('../shared/nav') %> 3 | <% 4 | const pluralize = periodic.viewHelper.pluralize; 5 | const entityFromURL = locals.request.originalurl.split('/')[locals.request.originalurl.split('/').length-1]; 6 | const singularEntity = pluralize.singular(entityFromURL); 7 | %> 8 | <%- 9 | include('../shared/single',{ 10 | entitytype:singularEntity, 11 | }) 12 | %> 13 | <%- include('../shared/footer') %> -------------------------------------------------------------------------------- /__STRUCTURE/app/views/home/error404.ejs: -------------------------------------------------------------------------------- 1 | <%- include('../shared/header') %> 2 | <%- include('../shared/nav') %> 3 | <% var errorTitle=''; 4 | try{ 5 | errorTitle = locals.error.toString().split('\n')[0]; 6 | } catch(e){ 7 | errorTitle = locals.error.message; 8 | } 9 | %> 10 |
11 |
12 | <% if(locals.appenvironment!=='production'){%> 13 |
14 | 15 | <%- errorTitle %> 16 | 17 |
18 |
<%- locals.error.stack %>
19 |
20 |
21 | <%} 22 | else{%> 23 |

Internal Server Error

24 | <%} %> 25 |
26 |
27 | <%- include('../shared/footer') %> -------------------------------------------------------------------------------- /__STRUCTURE/app/views/home/error500.ejs: -------------------------------------------------------------------------------- 1 | <%- include('../shared/header') %> 2 | <%- include('../shared/nav') %> 3 | <% var errorTitle=''; 4 | try{ 5 | errorTitle = locals.error.toString().split('\n')[0]; 6 | } catch(e){ 7 | errorTitle = locals.error.message; 8 | } 9 | %> 10 |
11 |
12 | <% if(locals.appenvironment!=='production'){%> 13 |
14 | 15 | <%- errorTitle %> 16 | 17 |
18 |
<%- error.stack %>
19 |
20 |
21 | <%} 22 | else{%> 23 |

Internal Server Error

24 | <%} %> 25 |
26 |
27 | <%- include('../shared/footer') %> -------------------------------------------------------------------------------- /__STRUCTURE/app/views/home/index.ejs: -------------------------------------------------------------------------------- 1 | <%- include('../shared/header') %> 2 | <%- include('../shared/nav') %> 3 |
4 |
5 |
6 |
7 | 8 |
9 |
10 |
11 |

Periodic is a library for rapidily develop database agnostic enterprise applications with express & node.js.

12 |

Easily define themes, routes and extensions to build your own CMS, ERP, ECM, API Server and more.

13 |
14 |
15 |
16 | <%- include('../shared/footer') %> -------------------------------------------------------------------------------- /__STRUCTURE/app/views/item/index.ejs: -------------------------------------------------------------------------------- 1 | <%- include('../shared/header') %> 2 | <%- include('../shared/nav') %> 3 | <%- include('../shared/content',{ 4 | entitytype:'item', 5 | items, 6 | }) %> 7 | <%- include('../shared/footer') %> -------------------------------------------------------------------------------- /__STRUCTURE/app/views/item/show.ejs: -------------------------------------------------------------------------------- 1 | <%- include('../shared/header') %> 2 | <%- include('../shared/nav') %> 3 | <%- 4 | include('../shared/single',{ 5 | entitytype:'item', 6 | }) 7 | %> 8 | <%- include('../shared/footer') %> -------------------------------------------------------------------------------- /__STRUCTURE/app/views/shared/content.ejs: -------------------------------------------------------------------------------- 1 | <% 2 | const pluralize = periodic.viewHelper.pluralize; 3 | const capitalize = periodic.viewHelper.capitalize; 4 | const path = periodic.viewHelper.path; 5 | // console.log({locals},'items[pluralize(entitytype)]',items[pluralize(entitytype)]) 6 | // console.log({items}); 7 | const hasItems = ( 8 | items && 9 | items[pluralize(entitytype)] && 10 | items[pluralize(entitytype)].documents.length) ? true:false; 11 | const entityName = { 12 | name: entitytype, 13 | plural: pluralize(entitytype), 14 | capitalized: (capitalize(entitytype)), 15 | pluralCapitalized: pluralize(capitalize(entitytype)), 16 | }; 17 | const entityPage = { 18 | count: (hasItems) ? items[`${entityName.plural}total`] : 0, 19 | limit: (hasItems) ? items[`${entitytype}limit`] : 0, 20 | totalpages: (hasItems) ? items[`${entityName.plural}totalpages`] : 1, 21 | currentpage: (hasItems) ? items[`${entitytype}page_current`] : 1, 22 | } 23 | // console.log({entityPage,items}); 24 | %> 25 |
26 |
27 |
28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | <% if(hasItems){ 41 | items[pluralize(entitytype)].documents.map(item=>{%> 42 | 43 | 44 | 45 | 46 | 47 | 48 | <%}); 49 | } else{%> 50 | 51 | 52 | 53 | <%}%> 54 | 55 | 56 | 57 | 61 | 63 | 64 | 69 | 70 | 71 |
IDTitleCreatedUpdated
<%- item._id %><%- item.title || item.name %><%- item.createdat %><%- item.updatedat %>
No <%- entityName.pluralCapitalized %>
<% if(entityPage.currentpage > 1){%> 58 | Prev Page 59 | <%} %> 60 | Page <%- entityPage.currentpage %> of <%- entityPage.totalpages %> 62 | Showing <%- (entityPage.limit > entityPage.count)? entityPage.count: entityPage.limit %> of <%- entityPage.count %> 65 | <% if(entityPage.currentpage <= entityPage.totalpages -1){ %> 66 | Next Page 67 | <% } %> 68 |
72 |
73 |
-------------------------------------------------------------------------------- /__STRUCTURE/app/views/shared/footer.ejs: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /__STRUCTURE/app/views/shared/header.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | <% if(locals && locals.periodic && locals.periodic.page_data){%> 7 | <%- locals.periodic.page_data.title%> 8 | 9 | 10 | 11 | 12 | <%}%> 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /__STRUCTURE/app/views/shared/nav.ejs: -------------------------------------------------------------------------------- 1 | <%- include('./nav_header') %> 2 |
3 | <%if(locals.periodic && locals.periodic.core_data_list){ 4 | const pluralize = periodic.viewHelper.pluralize; 5 | const capitalize = periodic.viewHelper.capitalize; 6 | %> 7 | 25 | <%}%> -------------------------------------------------------------------------------- /__STRUCTURE/app/views/shared/nav_header.ejs: -------------------------------------------------------------------------------- 1 |
2 | 15 |
-------------------------------------------------------------------------------- /__STRUCTURE/app/views/shared/simple_nav.ejs: -------------------------------------------------------------------------------- 1 | <%- include('./nav_header') %> 2 |
-------------------------------------------------------------------------------- /__STRUCTURE/app/views/shared/single.ejs: -------------------------------------------------------------------------------- 1 | <% 2 | const pluralize = periodic.viewHelper.pluralize; 3 | const capitalize = periodic.viewHelper.capitalize; 4 | %> 5 |
6 |
7 |

<%- (capitalize(entitytype)) %> › <%- data.title %> (<%- data.name %>)

8 |

9 | 10 | ID: <%- data._id %>
11 | Updated: <%- data.updatedat %>
12 | Created: <%- data.createdat %> 13 |
14 |

15 |

<%- data.description || data.content %>

16 |
17 |
-------------------------------------------------------------------------------- /__STRUCTURE/app/views/user/index.ejs: -------------------------------------------------------------------------------- 1 | <%- include('../shared/header') %> 2 | <%- include('../shared/nav') %> 3 | <%- include('../shared/content',{ 4 | entitytype:'user', 5 | items: users, 6 | }) %> 7 | <%- include('../shared/footer') %> -------------------------------------------------------------------------------- /__STRUCTURE/app/views/user/show.ejs: -------------------------------------------------------------------------------- 1 | <%- include('../shared/header') %> 2 | <%- include('../shared/nav') %> 3 | <%- 4 | include('../shared/single',{ 5 | entitytype:'user', 6 | }) 7 | %> 8 | <%- include('../shared/footer') %> -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/account.lowkie.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const lowkie = require('lowkie'); 4 | const Schema = lowkie.Schema; 5 | const ObjectId = Schema.ObjectId; 6 | const scheme = { 7 | email: { 8 | type: String, 9 | }, 10 | firstname: String, 11 | lastname: String, 12 | name: { 13 | type: String, 14 | }, 15 | password: String, 16 | url: String, 17 | birthday: Date, 18 | userid: { 19 | type: Number, 20 | }, 21 | accesstoken: String, 22 | description: { 23 | type: String, 24 | 'default': 'No profile' 25 | }, 26 | activated: { 27 | type: Boolean, 28 | 'default': false 29 | }, 30 | location: { 31 | city: String, 32 | country: String, 33 | state: String, 34 | zip: String, 35 | loc: { 36 | longitude: Number, 37 | latitude: Number 38 | } 39 | }, 40 | accounttype: { 41 | type: String, 42 | 'default': 'basic' 43 | }, 44 | gender: { 45 | type: String 46 | }, 47 | assets: [{ 48 | type: ObjectId, 49 | ref: 'Asset' 50 | }], 51 | primaryasset: { 52 | type: ObjectId, 53 | ref: 'Asset' 54 | }, 55 | coverimages: [{ 56 | type: ObjectId, 57 | ref: 'Asset' 58 | }], 59 | coverimage: { 60 | type: ObjectId, 61 | ref: 'Asset' 62 | }, 63 | userroles: [{ 64 | type: ObjectId, 65 | ref: 'Userrole' 66 | }], 67 | tags: [{ 68 | type: ObjectId, 69 | ref: 'Tag' 70 | }], 71 | categories: [{ 72 | type: ObjectId, 73 | ref: 'Category' 74 | }], 75 | apikey: String, 76 | random: Number 77 | }; 78 | 79 | module.exports = { 80 | scheme, 81 | options: {}, 82 | coreDataOptions: { 83 | docid: '_id', 84 | sort: { createdat: -1, }, 85 | search: ['email', 'firstname', 'lastname', 'name', ], 86 | population: 'assets primaryasset coverimages coverimage userroles tags categories' 87 | } 88 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/account.mongoose.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const mongoose = require('mongoose'); 4 | const Schema = mongoose.Schema; 5 | const ObjectId = Schema.ObjectId; 6 | const scheme = { 7 | id: ObjectId, 8 | email: { 9 | type: String, 10 | index: { 11 | unique: true, 12 | sparse: false 13 | } 14 | }, 15 | firstname: String, 16 | lastname: String, 17 | name: { 18 | type: String, 19 | index: { 20 | unique: true, 21 | sparse: true 22 | } 23 | }, 24 | password: String, 25 | url: String, 26 | birthday: Date, 27 | userid: { 28 | type: Number, 29 | index: { 30 | sparse: true 31 | } 32 | }, 33 | accesstoken: String, 34 | description: { 35 | type: String, 36 | 'default': 'No profile' 37 | }, 38 | activated: { 39 | type: Boolean, 40 | 'default': false 41 | }, 42 | location: { 43 | city: String, 44 | country: String, 45 | state: String, 46 | zip: String, 47 | loc: { 48 | longitude: Number, 49 | latitude: Number 50 | } 51 | }, 52 | accounttype: { 53 | type: String, 54 | 'default': 'basic' 55 | }, 56 | gender: { 57 | type: String 58 | }, 59 | assets: [{ 60 | type: ObjectId, 61 | ref: 'Asset' 62 | }], 63 | primaryasset: { 64 | type: ObjectId, 65 | ref: 'Asset' 66 | }, 67 | coverimages: [{ 68 | type: ObjectId, 69 | ref: 'Asset' 70 | }], 71 | coverimage: { 72 | type: ObjectId, 73 | ref: 'Asset' 74 | }, 75 | userroles: [{ 76 | type: ObjectId, 77 | ref: 'Userrole' 78 | }], 79 | tags: [{ 80 | type: ObjectId, 81 | ref: 'Tag' 82 | }], 83 | categories: [{ 84 | type: ObjectId, 85 | ref: 'Category' 86 | }], 87 | apikey: String, 88 | random: Number 89 | }; 90 | 91 | module.exports = { 92 | scheme, 93 | options: {}, 94 | coreDataOptions: { 95 | docid: '_id', 96 | sort: { createdat: -1, }, 97 | search: ['email', 'firstname', 'lastname', 'name', ], 98 | population: 'assets primaryasset coverimages userroles tags categories' 99 | } 100 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/asset.lowkie.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const lowkie = require('lowkie'); 4 | const Schema = lowkie.Schema; 5 | const ObjectId = Schema.ObjectId; 6 | const scheme = { 7 | id: ObjectId, 8 | title: String, 9 | name: String, 10 | status: { 11 | type: String, 12 | 'default': 'VALID', 13 | }, 14 | size: Number, 15 | author: { 16 | type: ObjectId, 17 | ref: 'User', 18 | }, 19 | userid: ObjectId, 20 | username: String, 21 | assettype: String, 22 | authors: [{ 23 | type: ObjectId, 24 | ref: 'User', 25 | }, ], 26 | tags: [{ 27 | type: ObjectId, 28 | ref: 'Tag', 29 | }, ], 30 | categories: [{ 31 | type: ObjectId, 32 | ref: 'Category', 33 | }, ], 34 | related_assets: [{ 35 | type: ObjectId, 36 | ref: 'Asset', 37 | }, ], 38 | encrypted_client_side: String, 39 | fileurl: String, 40 | locationtype: String, 41 | description: String, 42 | content: String, 43 | filedata: Schema.Types.Mixed, 44 | attributes: Schema.Types.Mixed, 45 | versions: Schema.Types.Mixed, 46 | random: Number, 47 | }; 48 | 49 | module.exports = { 50 | scheme, 51 | options: {}, 52 | coreDataOptions: { 53 | docid: '_id', 54 | sort: { createdat: -1, }, 55 | search: ['title', 'name', ], 56 | population: 'author authors tags categories related_assets', 57 | }, 58 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/asset.mongoose.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const mongoose = require('mongoose'); 4 | const Schema = mongoose.Schema; 5 | const ObjectId = Schema.ObjectId; 6 | const scheme = { 7 | id: ObjectId, 8 | title: String, 9 | name: String, 10 | status: { 11 | type: String, 12 | 'default': 'VALID', 13 | }, 14 | size: Number, 15 | author: { 16 | type: ObjectId, 17 | ref: 'User', 18 | }, 19 | userid: ObjectId, 20 | username: String, 21 | assettype: String, 22 | authors: [{ 23 | type: ObjectId, 24 | ref: 'User', 25 | }, ], 26 | tags: [{ 27 | type: ObjectId, 28 | ref: 'Tag', 29 | }, ], 30 | categories: [{ 31 | type: ObjectId, 32 | ref: 'Category', 33 | }, ], 34 | related_assets: [{ 35 | type: ObjectId, 36 | ref: 'Asset', 37 | }, ], 38 | encrypted_client_side: String, 39 | fileurl: String, 40 | locationtype: String, 41 | description: String, 42 | content: String, 43 | filedata: Schema.Types.Mixed, 44 | attributes: Schema.Types.Mixed, 45 | versions: Schema.Types.Mixed, 46 | random: Number, 47 | }; 48 | 49 | module.exports = { 50 | scheme, 51 | options: {}, 52 | coreDataOptions: { 53 | docid: '_id', 54 | sort: { createdat: -1, }, 55 | search: ['title', 'name', ], 56 | population: 'author authors tags categories related_assets', 57 | }, 58 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/attribute.sequelize.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const Sequelize = require('sequelize'); 3 | 4 | const scheme = { 5 | _id: { 6 | type: Sequelize.INTEGER, 7 | primaryKey: true, 8 | autoIncrement: true, 9 | }, 10 | title: { 11 | type: Sequelize.STRING, 12 | }, 13 | name: { 14 | type: Sequelize.STRING, 15 | }, 16 | description: { 17 | type: Sequelize.TEXT, 18 | }, 19 | datatype: { 20 | type: Sequelize.STRING, 21 | }, 22 | // data: { 23 | 24 | // }, 25 | defaultvalue: { 26 | type: Sequelize.STRING, 27 | } 28 | }; 29 | 30 | const options = { 31 | underscored: true, 32 | timestamps: true, 33 | indexes: [{ 34 | fields: ['createdat'], 35 | }], 36 | }; 37 | 38 | const associations = [ 39 | ]; 40 | 41 | module.exports = { 42 | scheme, 43 | options, 44 | associations, 45 | coreDataOptions: { 46 | docid: ['_id', 'name'], 47 | sort: { createdat: -1, }, 48 | search: ['title', 'name', ], 49 | }, 50 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/category.lowkie.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const lowkie = require('lowkie'); 4 | const Schema = lowkie.Schema; 5 | const ObjectId = Schema.ObjectId; 6 | 7 | const scheme = { 8 | id: ObjectId, 9 | title: String, 10 | name: String, 11 | dek: String, 12 | content: String, 13 | author: { 14 | type: ObjectId, 15 | ref: 'User' 16 | }, 17 | primaryasset: { 18 | type: ObjectId, 19 | ref: 'Asset' 20 | }, 21 | parent: [{ 22 | type: ObjectId, 23 | ref: 'Category', 24 | }], 25 | random: Number 26 | }; 27 | 28 | module.exports = { 29 | scheme, 30 | options: {}, 31 | coreDataOptions: { 32 | docid: '_id', 33 | sort: { createdat: -1, }, 34 | search: ['title', 'name', 'dek', 'content', ], 35 | population: 'author primaryasset parent' 36 | } 37 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/category.mongoose.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const mongoose = require('mongoose'); 4 | const Schema = mongoose.Schema; 5 | const ObjectId = Schema.ObjectId; 6 | const scheme = { 7 | id: ObjectId, 8 | title: String, 9 | name: { 10 | type: String, 11 | unique: true 12 | }, 13 | dek: String, 14 | content: String, 15 | author: { 16 | type: ObjectId, 17 | ref: 'User' 18 | }, 19 | primaryasset: { 20 | type: ObjectId, 21 | ref: 'Asset' 22 | }, 23 | parent: [{ 24 | type: ObjectId, 25 | ref: 'Category', 26 | index: true 27 | }], 28 | random: Number 29 | }; 30 | 31 | module.exports = { 32 | scheme, 33 | options: {}, 34 | coreDataOptions: { 35 | docid: '_id', 36 | sort: { createdat: -1, }, 37 | search: ['title', 'name', 'dek', 'content', ], 38 | population: 'author primaryasset parent' 39 | } 40 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/category.sequelize.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const Sequelize = require('sequelize'); 3 | 4 | const scheme = { 5 | _id: { 6 | type: Sequelize.INTEGER, 7 | primaryKey: true, 8 | autoIncrement: true, 9 | }, 10 | title: { 11 | type: Sequelize.STRING, 12 | }, 13 | author: { 14 | type: Sequelize.STRING, 15 | }, 16 | name: { 17 | type: Sequelize.STRING, 18 | unique: 'category_name', 19 | }, 20 | dek: { 21 | type: Sequelize.STRING, 22 | }, 23 | content: { 24 | type: Sequelize.TEXT, 25 | }, 26 | random: { 27 | type: Sequelize.FLOAT, 28 | }, 29 | }; 30 | 31 | const options = { 32 | underscored: true, 33 | timestamps: true, 34 | indexes: [ 35 | { 36 | fields: [ 37 | 'createdat', 38 | ], 39 | }, 40 | ], 41 | createdAt: 'createdat', 42 | updatedAt: 'updatedat', 43 | }; 44 | 45 | const associations = [ 46 | // { 47 | // source: 'user', 48 | // association: 'hasMany', 49 | // target: 'category', 50 | // options: { 51 | // as: 'author', 52 | // foreignKey: 'author', 53 | // }, 54 | // }, 55 | // { 56 | // source: 'asset', 57 | // association: 'hasMany', 58 | // target: 'category', 59 | // options: { 60 | // as: 'primaryasset', 61 | // foreignKey: 'primaryasset', 62 | // }, 63 | // }, 64 | { 65 | source: 'category', 66 | association: 'belongsToMany', 67 | target: 'category', 68 | options: { 69 | as: 'parent', 70 | through: 'category_parent', 71 | }, 72 | }, 73 | ]; 74 | 75 | module.exports = { 76 | scheme, 77 | options, 78 | associations, 79 | coreDataOptions: { 80 | docid: ['_id', 'name'], 81 | sort: { createdat: -1, }, 82 | search: ['title', 'name', 'dek', 'content', ], 83 | population: 'author primaryasset parent' 84 | }, 85 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/contenttype.lowkie.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const lowkie = require('lowkie'); 3 | const Schema = lowkie.Schema; 4 | const ObjectId = Schema.ObjectId; 5 | const scheme = { 6 | id: ObjectId, 7 | title: String, 8 | name: { 9 | type: String, 10 | }, 11 | author: { 12 | type: ObjectId, 13 | ref: 'User' 14 | }, 15 | attributes: [{ 16 | title: String, 17 | name: String, 18 | description: String, 19 | datatype: String, 20 | data: Schema.Types.Mixed, 21 | defaultvalue: String 22 | }] 23 | }; 24 | 25 | module.exports = { 26 | scheme, 27 | options: {}, 28 | coreDataOptions: { 29 | docid: '_id', 30 | sort: { createdat: -1, }, 31 | search: ['title', 'name', ], 32 | population: 'author' 33 | } 34 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/contenttype.mongoose.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const mongoose = require('mongoose'); 4 | const Schema = mongoose.Schema; 5 | const ObjectId = Schema.ObjectId; 6 | const scheme = { 7 | id: ObjectId, 8 | title: String, 9 | name: { 10 | type: String, 11 | unique: true 12 | }, 13 | author: { 14 | type: ObjectId, 15 | ref: 'User' 16 | }, 17 | attributes: [{ 18 | title: String, 19 | name: String, 20 | description: String, 21 | datatype: String, 22 | data: Schema.Types.Mixed, 23 | defaultvalue: String 24 | }] 25 | }; 26 | 27 | module.exports = { 28 | scheme, 29 | options: {}, 30 | coreDataOptions: { 31 | docid: '_id', 32 | sort: { createdat: -1, }, 33 | search: ['title', 'name', ], 34 | population: 'author' 35 | } 36 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/contenttype.sequelize.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const Sequelize = require('sequelize'); 3 | 4 | const scheme = { 5 | _id: { 6 | type: Sequelize.INTEGER, 7 | primaryKey: true, 8 | autoIncrement: true, 9 | }, 10 | title: { 11 | type: Sequelize.STRING, 12 | }, 13 | name: { 14 | type: Sequelize.STRING, 15 | unique: 'contenttype_name', 16 | }, 17 | }; 18 | 19 | const options = { 20 | underscored: true, 21 | timestamps: true, 22 | indexes: [ 23 | { 24 | fields: [ 25 | 'createdat', 26 | ], 27 | }, 28 | ], 29 | createdAt: 'createdat', 30 | updatedAt: 'updatedat', 31 | hooks: { 32 | beforeCreate: (asset, options) => { 33 | asset.attributes = asset._attributes; 34 | }, 35 | beforeUpdate: (asset, options) => { 36 | asset.attributes = asset._attributes; 37 | }, 38 | }, 39 | }; 40 | 41 | const associations = [ 42 | // { 43 | // target: 'user', 44 | // association: 'hasOne', 45 | // source: 'contenttype', 46 | // options: { 47 | // as: 'author', 48 | // foreignKey: 'author', 49 | // }, 50 | // }, 51 | ]; 52 | 53 | module.exports = { 54 | scheme, 55 | options, 56 | associations, 57 | coreDataOptions: { 58 | docid: ['_id', 'name'], 59 | sort: { createdat: -1, }, 60 | search: ['title', 'name', ], 61 | population: 'author attributes', 62 | }, 63 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/data.lowkie.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const lowkie = require('lowkie'); 3 | const Schema = lowkie.Schema; 4 | const ObjectId = Schema.ObjectId; 5 | const scheme = { 6 | id: ObjectId, 7 | status: { 8 | type: String, 9 | 'default': 'active' 10 | }, 11 | publishat: { 12 | type: Date, 13 | 'default': Date.now, 14 | }, 15 | title: String, 16 | name: { 17 | type: String, 18 | }, 19 | content: String, 20 | tags: [{ 21 | type: ObjectId, 22 | ref: 'Tag' 23 | }], 24 | categories: [{ 25 | type: ObjectId, 26 | ref: 'Category' 27 | }], 28 | primaryauthor: { 29 | type: ObjectId, 30 | ref: 'User' 31 | }, 32 | random: Number 33 | }; 34 | 35 | module.exports = { 36 | scheme, 37 | options: {}, 38 | coreDataOptions: { 39 | docid: '_id', 40 | sort: { createdat: -1, }, 41 | search: ['title', 'name', 'content'], 42 | population: 'tags categories primaryauthor', 43 | } 44 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/data.mongoose.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const mongoose = require('mongoose'); 4 | const Schema = mongoose.Schema; 5 | const ObjectId = Schema.ObjectId; 6 | const scheme = { 7 | id: ObjectId, 8 | status: { 9 | type: String, 10 | 'default': 'active' 11 | }, 12 | publishat: { 13 | type: Date, 14 | 'default': Date.now, 15 | index: true 16 | }, 17 | title: String, 18 | name: { 19 | type: String, 20 | unique: true 21 | }, 22 | content: String, 23 | tags: [{ 24 | type: ObjectId, 25 | ref: 'Tag' 26 | }], 27 | categories: [{ 28 | type: ObjectId, 29 | ref: 'Category' 30 | }], 31 | primaryauthor: { 32 | type: ObjectId, 33 | ref: 'User' 34 | }, 35 | random: Number 36 | }; 37 | 38 | module.exports = { 39 | scheme, 40 | options: {}, 41 | coreDataOptions: { 42 | docid: '_id', 43 | sort: { createdat: -1, }, 44 | search: ['title', 'name', 'content'], 45 | population: 'tags categories primaryauthor', 46 | } 47 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/data.sequelize.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const Sequelize = require('sequelize'); 3 | 4 | const scheme = { 5 | _id: { 6 | type: Sequelize.INTEGER, 7 | primaryKey: true, 8 | autoIncrement: true, 9 | }, 10 | status: { 11 | type: Sequelize.STRING, 12 | default: 'active', 13 | }, 14 | publishat: { 15 | type: Sequelize.DATE, 16 | defaultValue: Sequelize.NOW, 17 | }, 18 | title: { 19 | type: Sequelize.STRING, 20 | }, 21 | // primaryauthor: { 22 | // type: Sequelize.STRING, 23 | // }, 24 | name: { 25 | type: Sequelize.STRING, 26 | unique: 'data_name', 27 | }, 28 | content: { 29 | type: Sequelize.TEXT, 30 | }, 31 | random: { 32 | type: Sequelize.FLOAT, 33 | }, 34 | }; 35 | 36 | const options = { 37 | underscored: true, 38 | timestamps: true, 39 | indexes: [ 40 | { 41 | fields: [ 42 | 'createdat', 43 | ], 44 | }, 45 | ], 46 | createdAt: 'createdat', 47 | updatedAt: 'updatedat', 48 | }; 49 | 50 | const associations = [ 51 | // { 52 | // target: 'data', 53 | // association: 'hasOne', 54 | // source: 'user', 55 | // options: { 56 | // as: 'primaryauthor', 57 | // // foreignKey: 'primaryauthor', 58 | // }, 59 | // }, 60 | // { 61 | // source: 'user', 62 | // association: 'hasMany', 63 | // target: 'data', 64 | // options: { 65 | // as: 'primaryauthor', 66 | // foreignKey: 'primaryauthor', 67 | // }, 68 | // }, 69 | { 70 | source: 'data', 71 | association: 'belongsToMany', 72 | target: 'asset', 73 | options: { 74 | as: 'assets', 75 | through: 'data_assets', 76 | }, 77 | }, 78 | { 79 | source: 'data', 80 | association: 'belongsToMany', 81 | target: 'tag', 82 | options: { 83 | as:'tags', 84 | through: 'data_tags', 85 | }, 86 | }, 87 | { 88 | source: 'data', 89 | association: 'belongsToMany', 90 | target: 'category', 91 | options: { 92 | as:'categories', 93 | through: 'data_categories', 94 | }, 95 | }, 96 | ]; 97 | 98 | module.exports = { 99 | scheme, 100 | options, 101 | associations, 102 | coreDataOptions: { 103 | docid: ['_id', 'name'], 104 | sort: { createdat: -1, }, 105 | search: ['title', 'name', 'content'], 106 | // population: 'tags categories primaryauthor', 107 | }, 108 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/item.lowkie.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const lowkie = require('lowkie'); 3 | const Schema = lowkie.Schema; 4 | const ObjectId = Schema.ObjectId; 5 | const scheme = { 6 | status: { 7 | type: String, 8 | default: 'draft', 9 | }, 10 | publishat: { 11 | type: Date, 12 | default: Date.now, 13 | }, 14 | name: String, 15 | title: String, 16 | dek: String, 17 | content: String, 18 | link: String, 19 | visibility: String, 20 | visibilitypassword: Date, 21 | random: Number, 22 | primaryasset: { 23 | type: ObjectId, 24 | ref: 'Asset', 25 | }, 26 | primaryauthor: { 27 | type: ObjectId, 28 | ref: 'User', 29 | }, 30 | source: { 31 | type: ObjectId, 32 | ref: 'Source', 33 | }, 34 | assets: [{ 35 | type: ObjectId, 36 | ref: 'Asset', 37 | }, ], 38 | authors: [{ 39 | type: ObjectId, 40 | ref: 'User', 41 | }, ], 42 | tags: [{ 43 | type: ObjectId, 44 | ref: 'Tag', 45 | }, ], 46 | categories: [{ 47 | type: ObjectId, 48 | ref: 'Category', 49 | }, ], 50 | contenttypes: [{ 51 | type: ObjectId, 52 | ref: 'Contenttype', 53 | }, ], 54 | }; 55 | 56 | module.exports = { 57 | scheme, 58 | options: {}, 59 | coreDataOptions: { 60 | docid: ['_id', 'name'], 61 | sort: { createdat: -1, }, 62 | search: ['name', 'title', 'dek', 'content', 'link', ], 63 | // limit: 500, 64 | // skip: 0, 65 | population: 'primaryauthor primaryasset asset assets authors tags categories contenttypes', 66 | // fields: {}, 67 | // pagelength:15, 68 | // tract_changes:true, 69 | // xss_whitelist:['p','b'], 70 | }, 71 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/item.mongoose.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const mongoose = require('mongoose'); 3 | const Schema = mongoose.Schema; 4 | const ObjectId = Schema.ObjectId; 5 | const scheme = { 6 | id: ObjectId, 7 | status: { 8 | type: String, 9 | default: 'draft', 10 | }, 11 | publishat: { 12 | type: Date, 13 | default: Date.now, 14 | }, 15 | name: { 16 | type: String, 17 | unique: true, 18 | }, 19 | title: String, 20 | dek: String, 21 | content: String, 22 | link: String, 23 | visibility: String, 24 | visibilitypassword: Date, 25 | random: Number, 26 | // primaryasset: { 27 | // type: ObjectId, 28 | // ref: 'Asset' 29 | // }, 30 | primaryauthor: { 31 | type: ObjectId, 32 | ref: 'User', 33 | }, 34 | // source: { 35 | // type: ObjectId, 36 | // ref: 'Source' 37 | // }, 38 | 39 | // assets: [{ 40 | // type: ObjectId, 41 | // ref: 'Asset' 42 | // }], 43 | // authors: [{ 44 | // type: ObjectId, 45 | // ref: 'User' 46 | // }], 47 | // tags: [{ 48 | // type: ObjectId, 49 | // ref: 'Tag' 50 | // }], 51 | // categories: [{ 52 | // type: ObjectId, 53 | // ref: 'Category' 54 | // }], 55 | // contenttypes: [{ 56 | // type: ObjectId, 57 | // ref: 'Contenttype' 58 | // }], 59 | }; 60 | 61 | module.exports = { 62 | scheme, 63 | options: {}, 64 | coreDataOptions: { 65 | docid: [ '_id', 'name', ], 66 | sort: { createdat: -1, }, 67 | search: [ 'name', 'title', 'dek', 'content', 'link', ], 68 | // limit: 500, 69 | // skip: 0, 70 | population: 'primaryauthor primaryasset asset assets authors tags categories contenttypes', 71 | // fields: {}, 72 | // pagelength:15, 73 | // tract_changes:true, 74 | // xss_whitelist:['p','b'], 75 | }, 76 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/item.sequelize.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const Sequelize = require('sequelize'); 3 | 4 | const scheme = { 5 | _id: { 6 | type: Sequelize.INTEGER, 7 | // type: Sequelize.UUID, 8 | primaryKey: true, 9 | autoIncrement: true, 10 | }, 11 | status: { 12 | type: Sequelize.STRING, 13 | default: 'draft', 14 | }, 15 | publishat: { 16 | type: Sequelize.DATE, 17 | defaultValue: Sequelize.NOW, 18 | }, 19 | name: { 20 | type: Sequelize.STRING, 21 | unique: 'item_name', 22 | }, 23 | title: { 24 | type: Sequelize.STRING, 25 | }, 26 | dek: { 27 | type: Sequelize.TEXT, 28 | }, 29 | content: { 30 | type: Sequelize.TEXT, 31 | }, 32 | link: { 33 | type: Sequelize.STRING, 34 | }, 35 | visibility: { 36 | type: Sequelize.STRING, 37 | }, 38 | visibilitypassword: { 39 | type: Sequelize.STRING, 40 | }, 41 | random: { 42 | type: Sequelize.FLOAT, 43 | }, 44 | }; 45 | 46 | const options = { 47 | underscored: true, 48 | timestamps: true, 49 | indexes: [{ 50 | fields: ['createdat'], 51 | }], 52 | createdAt: 'createdat', 53 | updatedAt: 'updatedat', 54 | }; 55 | 56 | const associations = [ 57 | // { 58 | // source: 'user', 59 | // association: 'hasMany', 60 | // target: 'item', 61 | // options: { 62 | // as: 'primaryauthor', 63 | // foreignKey: 'primaryauthor', 64 | // }, 65 | // }, 66 | // { 67 | // target: 'item', 68 | // association: 'hasMany', 69 | // source: 'asset', 70 | // options: { 71 | // as: 'primaryasset', 72 | // foreignKey: 'primaryasset', 73 | // }, 74 | // }, 75 | { 76 | source: 'item', 77 | association: 'belongsToMany', 78 | target: 'user', 79 | options: { 80 | as: 'authors', 81 | through: 'item_authors', 82 | }, 83 | }, 84 | { 85 | source: 'item', 86 | association: 'belongsToMany', 87 | target: 'asset', 88 | options: { 89 | as: 'assets', 90 | through: 'item_assets', 91 | }, 92 | }, 93 | { 94 | source: 'item', 95 | association: 'belongsToMany', 96 | target: 'tag', 97 | options: { 98 | as:'tags', 99 | through: 'item_tags', 100 | }, 101 | }, 102 | { 103 | source: 'item', 104 | association: 'belongsToMany', 105 | target: 'category', 106 | options: { 107 | as:'categories', 108 | through: 'item_categories', 109 | }, 110 | }, 111 | { 112 | source: 'item', 113 | association: 'belongsToMany', 114 | target: 'contenttype', 115 | options: { 116 | as:'contenttypes', 117 | through: 'item_contenttypes', 118 | }, 119 | }, 120 | ]; 121 | 122 | module.exports = { 123 | scheme, 124 | options, 125 | associations, 126 | coreDataOptions: { 127 | docid: ['_id', 'name'], 128 | sort: { createdat: -1, }, 129 | search: ['name', 'title', 'dek', 'content', 'link', ], 130 | // limit: 500, 131 | // skip: 0, 132 | population: 'primaryauthor primaryasset asset assets authors tags categories contenttypes', 133 | // fields: {}, 134 | // pagelength:15, 135 | // tract_changes:true, 136 | // xss_whitelist:['p','b'], 137 | }, 138 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/tag.lowkie.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const lowkie = require('lowkie'); 3 | const Schema = lowkie.Schema; 4 | const ObjectId = Schema.ObjectId; 5 | const scheme = { 6 | id: ObjectId, 7 | title: String, 8 | name: { 9 | type: String, 10 | }, 11 | dek: String, 12 | content: String, 13 | author: { 14 | type: ObjectId, 15 | ref: 'User' 16 | }, 17 | primaryasset: { 18 | type: ObjectId, 19 | ref: 'Asset' 20 | }, 21 | parent: [{ 22 | type: ObjectId, 23 | ref: 'Tag' 24 | }], 25 | random: Number 26 | }; 27 | 28 | module.exports = { 29 | scheme, 30 | options: {}, 31 | coreDataOptions: { 32 | docid: '_id', 33 | sort: { createdat: -1, }, 34 | search: ['title', 'name', 'dek', 'content'], 35 | population: 'author primaryasset parent', 36 | } 37 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/tag.mongoose.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const mongoose = require('mongoose'); 4 | const Schema = mongoose.Schema; 5 | const ObjectId = Schema.ObjectId; 6 | const scheme = { 7 | id: ObjectId, 8 | title: String, 9 | name: { 10 | type: String, 11 | unique: true 12 | }, 13 | dek: String, 14 | content: String, 15 | author: { 16 | type: ObjectId, 17 | ref: 'User' 18 | }, 19 | primaryasset: { 20 | type: ObjectId, 21 | ref: 'Asset' 22 | }, 23 | parent: [{ 24 | type: ObjectId, 25 | ref: 'Tag' 26 | }], 27 | random: Number 28 | }; 29 | 30 | module.exports = { 31 | scheme, 32 | options: {}, 33 | coreDataOptions: { 34 | docid: '_id', 35 | sort: { createdat: -1, }, 36 | search: ['title', 'name', 'dek', 'content'], 37 | population: 'author primaryasset parent', 38 | } 39 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/tag.sequelize.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const Sequelize = require('sequelize'); 3 | 4 | const scheme = { 5 | _id: { 6 | type: Sequelize.INTEGER, 7 | primaryKey: true, 8 | autoIncrement: true, 9 | }, 10 | title: { 11 | type: Sequelize.STRING, 12 | }, 13 | name: { 14 | type: Sequelize.STRING, 15 | unique: 'tag_name', 16 | }, 17 | dek: { 18 | type: Sequelize.STRING, 19 | }, 20 | content: { 21 | type: Sequelize.TEXT, 22 | }, 23 | random: { 24 | type: Sequelize.FLOAT, 25 | }, 26 | }; 27 | 28 | const options = { 29 | underscored: true, 30 | timestamps: true, 31 | indexes: [{ 32 | fields: ['createdat'], 33 | }], 34 | }; 35 | 36 | const associations = [ 37 | // { 38 | // source: 'user', 39 | // association: 'hasMany', 40 | // target: 'tag', 41 | // options: { 42 | // as: 'author', 43 | // foreignKey: 'author', 44 | // }, 45 | // }, 46 | // { 47 | // source: 'asset', 48 | // association: 'hasMany', 49 | // target: 'tag', 50 | // options: { 51 | // as: 'primaryasset', 52 | // foreignKey: 'primaryasset', 53 | // }, 54 | // }, 55 | { 56 | source: 'tag', 57 | association: 'belongsToMany', 58 | target: 'tag', 59 | options: { 60 | as: 'parent', 61 | through: 'tag_parent', 62 | }, 63 | }, 64 | ]; 65 | 66 | module.exports = { 67 | scheme, 68 | options, 69 | associations, 70 | coreDataOptions: { 71 | docid: ['_id', 'name'], 72 | sort: { createdat: -1, }, 73 | search: ['title', 'name', 'dek', 'content', ], 74 | population: 'author primaryasset parent' 75 | }, 76 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/user.lowkie.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const lowkie = require('lowkie'); 3 | const Schema = lowkie.Schema; 4 | const ObjectId = Schema.ObjectId; 5 | const scheme = { 6 | name: String, 7 | email: String, 8 | firstname: String, 9 | lastname: String, 10 | password: String, 11 | url: String, 12 | birthday: Date, 13 | userid: Number, 14 | accesstoken: String, 15 | gender: String, 16 | activated: Boolean, 17 | description: { 18 | type: String, 19 | default: 'No Profile', 20 | }, 21 | accounttype: { 22 | type: String, 23 | default: 'basic', 24 | }, 25 | location: { 26 | city: String, 27 | country: String, 28 | state: String, 29 | zip: String, 30 | longitude: Number, 31 | latitude: Number, 32 | }, 33 | primaryasset: { 34 | type: ObjectId, 35 | ref: 'Asset', 36 | }, 37 | coverimage: { 38 | type: ObjectId, 39 | ref: 'Asset', 40 | }, 41 | coverimages: [{ 42 | type: ObjectId, 43 | ref: 'Asset', 44 | }, ], 45 | assets: [{ 46 | type: ObjectId, 47 | ref: 'Asset', 48 | }, ], 49 | userroles: [{ 50 | type: ObjectId, 51 | ref: 'Userrole', 52 | }, ], 53 | tags: [{ 54 | type: ObjectId, 55 | ref: 'Tag', 56 | }, ], 57 | categories: [{ 58 | type: ObjectId, 59 | ref: 'Contenttype', 60 | }, ], 61 | contenttypes: [{ 62 | type: ObjectId, 63 | ref: 'Contenttype', 64 | }, ], 65 | }; 66 | 67 | module.exports = { 68 | scheme, 69 | options: {}, 70 | coreDataOptions: { 71 | docid: ['_id', 'name', ], 72 | sort: { createdat: -1, }, 73 | search: ['name', 'email', 'firstname', 'lastname', 'description'], 74 | // limit: 500, 75 | // skip: 0, 76 | population: 'coverimage coverimages primaryasset assets userroles tags categories contenttypes', 77 | // fields: {}, 78 | // pagelength:15, 79 | // tract_changes:true, 80 | // xss_whitelist:['p','b'], 81 | }, 82 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/user.mongoose.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const mongoose = require('mongoose'); 3 | const Schema = mongoose.Schema; 4 | const ObjectId = Schema.ObjectId; 5 | const scheme = { 6 | name: String, 7 | email: String, 8 | firstname: String, 9 | lastname: String, 10 | password: String, 11 | url: String, 12 | birthday: Date, 13 | userid: Number, 14 | accesstoken: String, 15 | gender: String, 16 | activated: Boolean, 17 | description: { 18 | type: String, 19 | default: 'No Profile', 20 | }, 21 | accounttype: { 22 | type: String, 23 | default: 'basic', 24 | }, 25 | location: { 26 | city: String, 27 | country: String, 28 | state: String, 29 | zip: String, 30 | longitude: Number, 31 | latitude: Number, 32 | }, 33 | // primaryasset: { 34 | // type: ObjectId, 35 | // ref: 'Asset' 36 | // }, 37 | // coverimage: { 38 | // type: ObjectId, 39 | // ref: 'Asset' 40 | // }, 41 | // coverimages: [{ 42 | // type: ObjectId, 43 | // ref: 'Asset' 44 | // }], 45 | // assets: [{ 46 | // type: ObjectId, 47 | // ref: 'Asset' 48 | // }], 49 | // userroles: [{ 50 | // type: ObjectId, 51 | // ref: 'Userrole' 52 | // }], 53 | // tags: [{ 54 | // type: ObjectId, 55 | // ref: 'Tag' 56 | // }], 57 | // categories: [{ 58 | // type: ObjectId, 59 | // ref: 'Contenttype' 60 | // }], 61 | // contenttypes: [{ 62 | // type: ObjectId, 63 | // ref: 'Contenttype' 64 | // }], 65 | }; 66 | 67 | module.exports = { 68 | scheme, 69 | options: {}, 70 | coreDataOptions: { 71 | docid:['_id', 'name',], 72 | sort: { createdat: -1, }, 73 | search:['name', 'email', 'firstname', 'lastname', 'description',], 74 | // limit: 500, 75 | // skip: 0, 76 | population: 'coverimage coverimages primaryasset assets userroles tags categories contenttypes', 77 | // fields: {}, 78 | // pagelength:15, 79 | // tract_changes:true, 80 | // xss_whitelist:['p','b'], 81 | }, 82 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/usergroup.lowkie.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const lowkie = require('lowkie'); 3 | const Schema = lowkie.Schema; 4 | const ObjectId = Schema.ObjectId; 5 | const scheme = { 6 | id: ObjectId, 7 | usergroupid: { 8 | type: Number, 9 | }, 10 | title: String, 11 | name: { 12 | type: String, 13 | }, 14 | roles: [{ 15 | type: ObjectId, 16 | ref: 'Userrole' 17 | }], 18 | author: { 19 | type: ObjectId, 20 | ref: 'User' 21 | }, 22 | description: String, 23 | random: Number 24 | }; 25 | 26 | module.exports = { 27 | scheme, 28 | options: {}, 29 | coreDataOptions: { 30 | docid: '_id', 31 | sort: { createdat: -1, }, 32 | search: ['title', 'name', 'description'], 33 | population: 'roles author' 34 | } 35 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/usergroup.mongoose.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const mongoose = require('mongoose'); 4 | const Schema = mongoose.Schema; 5 | const ObjectId = Schema.ObjectId; 6 | const scheme = { 7 | id: ObjectId, 8 | usergroupid: { 9 | type: Number, 10 | unique: true 11 | }, 12 | title: String, 13 | name: { 14 | type: String, 15 | unique: true 16 | }, 17 | roles: [{ 18 | type: ObjectId, 19 | ref: 'Userrole' 20 | }], 21 | author: { 22 | type: ObjectId, 23 | ref: 'User' 24 | }, 25 | description: String, 26 | random: Number 27 | }; 28 | 29 | module.exports = { 30 | scheme, 31 | options: {}, 32 | coreDataOptions: { 33 | docid: '_id', 34 | sort: { createdat: -1, }, 35 | search: ['title', 'name', 'description'], 36 | population: 'roles author' 37 | } 38 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/usergroup.sequelize.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const Sequelize = require('sequelize'); 3 | 4 | const scheme = { 5 | _id: { 6 | type: Sequelize.INTEGER, 7 | primaryKey: true, 8 | autoIncrement: true, 9 | }, 10 | usergroupid: { 11 | type: Sequelize.INTEGER, 12 | unique: 'usergroupid_idx', 13 | }, 14 | title: { 15 | type: Sequelize.STRING, 16 | }, 17 | name: { 18 | type: Sequelize.STRING, 19 | unique: 'usergroup_name', 20 | }, 21 | description: { 22 | type: Sequelize.TEXT, 23 | }, 24 | random: { 25 | type: Sequelize.FLOAT, 26 | }, 27 | }; 28 | 29 | const options = { 30 | underscored: true, 31 | timestamps: true, 32 | indexes: [{ 33 | fields: ['createdat'], 34 | }], 35 | createdAt: 'createdat', 36 | updatedAt: 'updatedat', 37 | }; 38 | 39 | const associations = [ 40 | // { 41 | // source: 'user', 42 | // association: 'hasMany', 43 | // target: 'usergroup', 44 | // options: { 45 | // as: 'author', 46 | // foreignKey: 'author', 47 | // }, 48 | // }, 49 | // { 50 | // source: 'account', 51 | // association: 'hasMany', 52 | // target: 'usergroup', 53 | // options: { 54 | // as: 'creator', 55 | // foreignKey: 'creator', 56 | // }, 57 | // }, 58 | { 59 | source: 'usergroup', 60 | association: 'belongsToMany', 61 | target: 'userrole', 62 | options: { 63 | as:'roles', 64 | through: 'usergroup_userroles', 65 | }, 66 | }, 67 | ]; 68 | 69 | module.exports = { 70 | scheme, 71 | options, 72 | associations, 73 | coreDataOptions: { 74 | docid: ['_id', 'name'], 75 | sort: { createdat: -1, }, 76 | search: ['title', 'name', 'description'], 77 | population: 'roles author creator' 78 | }, 79 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/userprivilege.lowkie.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const lowkie = require('lowkie'); 3 | const Schema = lowkie.Schema; 4 | const ObjectId = Schema.ObjectId; 5 | const scheme = { 6 | id: ObjectId, 7 | userprivilegeid: { 8 | type: Number, 9 | }, 10 | title: String, 11 | name: { 12 | type: String, 13 | }, 14 | author: { 15 | type: ObjectId, 16 | ref: 'User' 17 | }, 18 | description: String, 19 | random: Number 20 | }; 21 | 22 | module.exports = { 23 | scheme, 24 | options: {}, 25 | coreDataOptions: { 26 | docid: '_id', 27 | sort: { createdat: -1, }, 28 | search: ['title', 'name', 'description'], 29 | population: 'author' 30 | } 31 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/userprivilege.mongoose.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const mongoose = require('mongoose'); 4 | const Schema = mongoose.Schema; 5 | const ObjectId = Schema.ObjectId; 6 | const scheme = { 7 | id: ObjectId, 8 | userprivilegeid: { 9 | type: Number, 10 | unique: true 11 | }, 12 | title: String, 13 | name: { 14 | type: String, 15 | unique: true 16 | }, 17 | author: { 18 | type: ObjectId, 19 | ref: 'User' 20 | }, 21 | description: String, 22 | random: Number 23 | }; 24 | 25 | module.exports = { 26 | scheme, 27 | options: {}, 28 | coreDataOptions: { 29 | docid: '_id', 30 | sort: { createdat: -1, }, 31 | search: ['title', 'name', 'description'], 32 | population: 'author' 33 | } 34 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/userprivilege.sequelize.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const Sequelize = require('sequelize'); 3 | 4 | const scheme = { 5 | _id: { 6 | type: Sequelize.INTEGER, 7 | primaryKey: true, 8 | autoIncrement: true, 9 | }, 10 | userprivilegeid: { 11 | type: Sequelize.INTEGER, 12 | unique: 'userprivilegeid_idx', 13 | }, 14 | title: { 15 | type: Sequelize.STRING, 16 | }, 17 | name: { 18 | type: Sequelize.STRING, 19 | unique: 'userprivilege_name', 20 | }, 21 | description: { 22 | type: Sequelize.TEXT, 23 | }, 24 | random: { 25 | type: Sequelize.FLOAT, 26 | }, 27 | }; 28 | 29 | const options = { 30 | underscored: true, 31 | timestamps: true, 32 | indexes: [{ 33 | fields: ['createdat'], 34 | }], 35 | createdAt: 'createdat', 36 | updatedAt: 'updatedat', 37 | }; 38 | 39 | const associations = [ 40 | // { 41 | // source: 'user', 42 | // association: 'hasMany', 43 | // target: 'userprivilege', 44 | // options: { 45 | // as: 'author', 46 | // foreignKey: 'author', 47 | // }, 48 | // }, 49 | // { 50 | // source: 'account', 51 | // association: 'hasMany', 52 | // target: 'userprivilege', 53 | // options: { 54 | // as: 'creator', 55 | // foreignKey: 'creator', 56 | // }, 57 | // }, 58 | ]; 59 | 60 | module.exports = { 61 | scheme, 62 | options, 63 | associations, 64 | coreDataOptions: { 65 | docid: ['_id', 'name'], 66 | sort: { createdat: -1, }, 67 | search: ['title', 'name', 'description'], 68 | // population: 'author creator', 69 | }, 70 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/userrole.lowkie.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const lowkie = require('lowkie'); 3 | const Schema = lowkie.Schema; 4 | const ObjectId = Schema.ObjectId; 5 | const scheme = { 6 | id: ObjectId, 7 | userroleid: Number, 8 | title: String, 9 | name: String, 10 | privileges: [{ 11 | type: ObjectId, 12 | ref: 'Userprivilege' 13 | }], 14 | author: { 15 | type: ObjectId, 16 | ref: 'User' 17 | }, 18 | description: String, 19 | random: Number 20 | }; 21 | 22 | module.exports = { 23 | scheme, 24 | options: {}, 25 | coreDataOptions: { 26 | docid: '_id', 27 | sort: { createdat: -1, }, 28 | search: ['title', 'name', 'description'], 29 | population: 'privileges author', 30 | } 31 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/userrole.mongoose.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const mongoose = require('mongoose'); 4 | const Schema = mongoose.Schema; 5 | const ObjectId = Schema.ObjectId; 6 | const scheme = { 7 | id: ObjectId, 8 | userroleid: { 9 | type: Number, 10 | unique: true 11 | }, 12 | title: String, 13 | name: { 14 | type: String, 15 | unique: true 16 | }, 17 | privileges: [{ 18 | type: ObjectId, 19 | ref: 'Userprivilege' 20 | }], 21 | author: { 22 | type: ObjectId, 23 | ref: 'User' 24 | }, 25 | description: String, 26 | random: Number 27 | }; 28 | 29 | module.exports = { 30 | scheme, 31 | options: {}, 32 | coreDataOptions: { 33 | docid: '_id', 34 | sort: { createdat: -1, }, 35 | search: ['title', 'name', 'description'], 36 | population: 'privileges author', 37 | } 38 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/databases/standard/models/userrole.sequelize.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const Sequelize = require('sequelize'); 3 | 4 | const scheme = { 5 | _id: { 6 | type: Sequelize.INTEGER, 7 | primaryKey: true, 8 | autoIncrement: true, 9 | }, 10 | userroleid: { 11 | type: Sequelize.INTEGER, 12 | unique: 'userroleid_idx', 13 | }, 14 | title: { 15 | type: Sequelize.STRING, 16 | }, 17 | name: { 18 | type: Sequelize.STRING, 19 | unique: 'userrole_name', 20 | }, 21 | description: { 22 | type: Sequelize.TEXT, 23 | }, 24 | random: { 25 | type: Sequelize.FLOAT, 26 | }, 27 | }; 28 | 29 | const options = { 30 | underscored: true, 31 | timestamps: true, 32 | indexes: [{ 33 | fields: ['createdat'], 34 | }], 35 | createdAt: 'createdat', 36 | updatedAt: 'updatedat', 37 | }; 38 | 39 | const associations = [ 40 | // { 41 | // source: 'user', 42 | // association: 'hasMany', 43 | // target: 'userrole', 44 | // options: { 45 | // as: 'author', 46 | // foreignKey: 'author', 47 | // }, 48 | // }, 49 | // { 50 | // source: 'account', 51 | // association: 'hasMany', 52 | // target: 'userrole', 53 | // options: { 54 | // as: 'creator', 55 | // foreignKey: 'creator', 56 | // }, 57 | // }, 58 | { 59 | source: 'userrole', 60 | association: 'belongsToMany', 61 | target: 'userprivilege', 62 | options: { 63 | as:'privileges', 64 | through: 'userrole_userprivileges', 65 | }, 66 | }, 67 | ]; 68 | 69 | module.exports = { 70 | scheme, 71 | options, 72 | associations, 73 | coreDataOptions: { 74 | docid: ['_id', 'name'], 75 | sort: { createdat: -1, }, 76 | search: ['title', 'name', 'description'], 77 | population: 'privileges author creator', 78 | }, 79 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/config/startup.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * this function is used to add additional customizations to the express application before the express server starts. The function is bound with the periodic singleton instance 5 | * 6 | * @returns 7 | */ 8 | function customExpressConfiguration() { 9 | return new Promise((resolve, reject) => { 10 | /** 11 | * this.app// is a reference to periodic's express instance 12 | * app.use((req,res,next)=>{ 13 | * //custom middleware 14 | * next(); 15 | * }) 16 | */ 17 | resolve(true); 18 | }); 19 | } 20 | 21 | module.exports = { 22 | customExpressConfiguration, 23 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/container/periodicjs.container.default/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "eslint:recommended", 3 | "plugins": [], 4 | "parserOptions": { 5 | "ecmaFeatures": { 6 | "ecmaVersion": 6, 7 | "jsx": true 8 | } 9 | }, 10 | "ecmaFeatures": { 11 | "ecmaVersion": 6 12 | }, 13 | "rules": { 14 | "jsx-quotes": ["error", "prefer-double"], 15 | "indent": ["error", 2], 16 | "quotes": ["error", "single"], 17 | "semi": ["warn", "always"], 18 | "comma-dangle": ["warn", "always"], 19 | "comma-spacing": "warn", 20 | "array-bracket-spacing": "warn", 21 | "object-curly-spacing": ["error", "always"], 22 | "eqeqeq": "warn", 23 | "no-cond-assign": ["warn", "always"], 24 | "no-unused-vars": "warn", 25 | "no-console": "warn", 26 | "brace-style": ["warn", "1tbs"], 27 | "strict": ["error", "safe"] 28 | }, 29 | "env": { 30 | "browser": true, 31 | "commonjs": true, 32 | "es6": true, 33 | "node": true 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /__STRUCTURE/content/container/periodicjs.container.default/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /__STRUCTURE/content/container/periodicjs.container.default/README.md: -------------------------------------------------------------------------------- 1 | # periodicjs.ext.test -------------------------------------------------------------------------------- /__STRUCTURE/content/container/periodicjs.container.default/commands/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const periodic = require('periodicjs'); 3 | 4 | module.exports = { 5 | hello: (options) => { 6 | periodic.logger.silly('hello',{options}); 7 | return new Promise((resolve, reject) => { 8 | resolve(true); 9 | }); 10 | } 11 | } -------------------------------------------------------------------------------- /__STRUCTURE/content/container/periodicjs.container.default/config/databases/.gitkeep: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------------- /__STRUCTURE/content/container/periodicjs.container.default/config/settings.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | settings: { 5 | defaults:true, 6 | }, 7 | databases: { 8 | }, 9 | }; -------------------------------------------------------------------------------- /__STRUCTURE/content/container/periodicjs.container.default/controllers/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const periodic = require('periodicjs'); 3 | 4 | module.exports = { 5 | test: (req, res, next) => { 6 | periodic.logger.silly('test middleware'); 7 | next(); 8 | } 9 | } -------------------------------------------------------------------------------- /__STRUCTURE/content/container/periodicjs.container.default/doc/.gitkeep: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------------- /__STRUCTURE/content/container/periodicjs.container.default/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | // const periodic = require('periodicjs'); 3 | 4 | module.exports = () => { 5 | return Promise.resolve(true); 6 | } -------------------------------------------------------------------------------- /__STRUCTURE/content/container/periodicjs.container.default/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "periodicjs.ext.sample", 3 | "description": "sample extension.", 4 | "version": "0.0.1", 5 | "main": "index.js", 6 | "engines": { 7 | "node": "^6.x" 8 | }, 9 | "contributors": [ 10 | ], 11 | "repository": { 12 | }, 13 | "config": { 14 | "blanket": { 15 | "pattern": [ 16 | "content/themes" 17 | ] 18 | } 19 | }, 20 | "license": "MIT", 21 | "scripts": { 22 | "test": "mocha -R spec --recursive" 23 | }, 24 | "dependencies": { 25 | }, 26 | "devDependencies": { 27 | "browserify": "^13.0.0", 28 | "chai": "^3.0.0", 29 | "chai-as-promised": "^6.0.0", 30 | "coveralls": "^2.11.9", 31 | "grunt": "^1.0.1", 32 | "grunt-browserify": "^5.0.0", 33 | "grunt-contrib-copy": "^1.0.0", 34 | "grunt-contrib-cssmin": "^1.0.1", 35 | "grunt-contrib-jshint": "^1.0.0", 36 | "grunt-contrib-uglify": "^1.0.1", 37 | "grunt-contrib-watch": "^1.0.0", 38 | "grunt-coveralls": "^1.0.1", 39 | "grunt-jsbeautifier": "~0.2.7", 40 | "grunt-jsdoc": "^2.0.0", 41 | "grunt-mocha-cov": "^0.4.0", 42 | "grunt-mocha-istanbul": "^4.0.2", 43 | "grunt-newer": "^1.1.1", 44 | "grunt-simple-mocha": "^0.4.1", 45 | "istanbul": "^0.4.3", 46 | "jsdoc": "^3.3.2", 47 | "mocha": "^2.2.5", 48 | "mocha-lcov-reporter": "^1.2.0", 49 | "mocha-sinon": "^2.0.0", 50 | "sinon": "^1.17.4", 51 | "sinon-chai": "^2.8.0" 52 | }, 53 | "keywords": [ 54 | ], 55 | "bugs": { 56 | }, 57 | "maintainers": [], 58 | "directories": {}, 59 | "optionalDependencies": {} 60 | } -------------------------------------------------------------------------------- /__STRUCTURE/content/container/periodicjs.container.default/periodicjs.ext.json: -------------------------------------------------------------------------------- 1 | { 2 | "periodic_compatibility": "10.0.0", 3 | "periodic_dependencies": [], 4 | "periodic_type": 10, 5 | "periodic_priority": 0, 6 | "periodic_config": { 7 | } 8 | } -------------------------------------------------------------------------------- /__STRUCTURE/content/container/periodicjs.container.default/resources/.gitkeep: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------------- /__STRUCTURE/content/container/periodicjs.container.default/routers/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const periodic = require('periodicjs'); 4 | const extensionRouter = periodic.express.Router(); 5 | 6 | extensionRouter.all('/', (req, res) => { 7 | const viewtemplate = 'home/index'; 8 | const viewdata = { 9 | periodic: { 10 | appname: periodic.settings.name, 11 | }, 12 | }; 13 | periodic.core.controller.renderView(req, res, viewtemplate, viewdata); 14 | }); 15 | 16 | module.exports = extensionRouter; -------------------------------------------------------------------------------- /__STRUCTURE/content/container/periodicjs.container.default/test/.gitkeep: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------------- /__STRUCTURE/content/container/periodicjs.container.default/transforms/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const periodic = require('periodicjs'); 3 | function testPreTransform(req) { 4 | return new Promise((resolve, reject) => { 5 | periodic.logger.silly('sample pre transfrom', req.params.id); 6 | resolve(req); 7 | }); 8 | } 9 | function testPostTransform(req) { 10 | return new Promise((resolve, reject) => { 11 | periodic.logger.silly('sample post transfrom', req.params.id); 12 | resolve(req); 13 | }); 14 | } 15 | 16 | module.exports = { 17 | pre: { 18 | GET: { 19 | '/some/route/path/:id':[testPreTransform] 20 | }, 21 | PUT: { 22 | } 23 | }, 24 | post: { 25 | GET: { 26 | '/another/route/test/:id':[testPostTransform] 27 | }, 28 | PUT: { 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /__STRUCTURE/content/container/periodicjs.container.default/utilities/.gitkeep: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------------- /__STRUCTURE/content/container/periodicjs.container.default/utilities/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = {}; -------------------------------------------------------------------------------- /__STRUCTURE/content/container/periodicjs.container.default/views/.gitkeep: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------------- /__STRUCTURE/logs/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/repetere/periodicjs/fc31f56c348a831dc407d95785195c12a589b44a/__STRUCTURE/logs/.gitkeep -------------------------------------------------------------------------------- /__STRUCTURE/processes/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/repetere/periodicjs/fc31f56c348a831dc407d95785195c12a589b44a/__STRUCTURE/processes/.gitkeep -------------------------------------------------------------------------------- /__STRUCTURE/public/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/repetere/periodicjs/fc31f56c348a831dc407d95785195c12a589b44a/__STRUCTURE/public/.gitkeep -------------------------------------------------------------------------------- /__STRUCTURE/public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/repetere/periodicjs/fc31f56c348a831dc407d95785195c12a589b44a/__STRUCTURE/public/favicon.png -------------------------------------------------------------------------------- /__STRUCTURE/public/uploads/files/.gitkeep: -------------------------------------------------------------------------------- 1 | { 2 | "cron":{ 3 | "development":{ 4 | "replicationfrom":"qa", 5 | "replicationcron":"59 2 * * * *" 6 | }, 7 | "qa":{ 8 | "replicationfrom":"production", 9 | "replicationcron":"59 3 * * * *" 10 | } 11 | }, 12 | "qa":{ 13 | "host": "192.168.100.100", 14 | "port": 22, 15 | "username": "root", 16 | "password": "serverpassword", 17 | "webAppPath" : "/var/www/mywebapp" 18 | }, 19 | "production":{ 20 | "host": "192.168.200.100", 21 | "port": 22, 22 | "privateKey": "path/to/private/key", 23 | "username": "sshusername", 24 | "webAppPath" : "/var/www/mywebapp" 25 | } 26 | } -------------------------------------------------------------------------------- /bin/__SETUP/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const periodic = require('periodicjs'); 4 | 5 | periodic.init({ 6 | debug: true, 7 | }) 8 | .then(periodicInitStatus => { 9 | console.log({ periodicInitStatus }); 10 | }) 11 | .catch(e => { 12 | console.error(e); 13 | }); -------------------------------------------------------------------------------- /bin/__SETUP/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-app-server", 3 | "description": "Simple enterprise node app server.", 4 | "version": "0.0.1", 5 | "main": "index.js", 6 | "engines": { 7 | "node": "^10.x" 8 | }, 9 | "license": "MIT", 10 | "scripts": { 11 | "start": "node index.js --e", 12 | "test": "mocha -R spec --recursive" 13 | }, 14 | "dependencies": { 15 | "periodicjs": "^10.70.54" 16 | } 17 | } -------------------------------------------------------------------------------- /doc/.sample.env: -------------------------------------------------------------------------------- 1 | DB_CONFIG={"settings":{"name":"my app"},"configuration":{"type":"db","db":"sequelize","options":{"database":"dbname","username":"username","password":"pw","connection_options":{"dialect":"postgres","port":"5432","host":"hostname"}}}} 2 | -------------------------------------------------------------------------------- /doc/advanced/00-testing-developing.md: -------------------------------------------------------------------------------- 1 | # Testing and Developing Periodic 2 | 3 | ## Testing 4 | *Make sure you have grunt installed* 5 | ``` 6 | $ npm install -g grunt-cli 7 | ``` 8 | 9 | Then run grunt test or npm test 10 | ``` 11 | $ grunt test && grunt coveralls #or locally $ npm test 12 | ``` 13 | 14 | ## Documentation 15 | 16 | For generating documentation, make sure you have jsdoc-to-markdown installed 17 | 18 | ``` 19 | $ npm install -g jsdoc-to-markdown 20 | ``` 21 | Then generate updated docs 22 | ``` 23 | $ grunt doc 24 | $ jsdoc2md bin/**/*.js lib/**/*.js index.js > doc/api.md -------------------------------------------------------------------------------- /doc/cli/01-overview.md: -------------------------------------------------------------------------------- 1 | # Command Line Interface 2 | 3 | Periodic comes with a built in Command Line Interface (CLI) with three main features 4 | * REPL - an interactive shell 5 | * CRUD - access to periodic's internal persistent storage faculties 6 | * Tasks - access to mounted asychronous methods from extensions and containers. 7 | 8 | ## `$ periodicjs repl` - interactive periodic shell 9 | 10 | ```console 11 | $ periodicjs repl 12 | $ #alternatively 13 | $ node [path/to/app_root/]index.js --cli --repl 14 | ``` 15 | 16 | The `repl` CLI command creates an interactive shell with access to your fully initialized periodic application 17 | 18 | ```javascript 19 | const repl = require('repl'); 20 | const r = repl.start('$p > '); 21 | r.context.$p = periodic; 22 | ``` 23 | 24 | ## `$ periodicjs commands` - asynchronous mounted tasks 25 | 26 | ```console 27 | $ periodicjs command extension periodicjs.ext.dbseed import path/to/seedfile.json 28 | $ #alternatively 29 | $ node [path/to/app_root/]index.js --cli --command --ext --name=periodicjs.ext.dbseed --task=import --args 30 | ``` 31 | 32 | The `commands` CLI command calls mounted asynchronous procedures called **tasks** from your periodic application during start up. Extensions and Containers tasks are mounted from exported asynchronous functions located in `[name-of-ext||name-of-container]/tasks/index.js`. 33 | 34 | ```javascript 35 | //parsed command line arguments 36 | const options = { 37 | argv: { 38 | cli: true, //required 39 | command: true, //required 40 | ext: true, //optional 41 | container: true, //optional 42 | name: 'name of container or extension', //required 43 | task: 'name of cli command async function', //required 44 | args: 'arguments passed to command function' //optional 45 | } 46 | }; 47 | 48 | //method called: 49 | const commandType = (options.argv.ext) ? 'extensions' : 'container'; 50 | periodic.resources.commands[commandType] 51 | .get(options.argv.name)[options.argv.task] 52 | .call(periodic, options.argv.args) 53 | .then(periodic.logger.info) 54 | .catch(periodic.logger.error); 55 | ``` 56 | 57 | ## `$ periodicjs crud` - internal storage helpers 58 | 59 | ```console 60 | $ periodicjs crud extension create periodicjs.ext.dbseed 61 | $ #alternatively 62 | $ node [path/to/app_root/]index.js --cli --crud=extension --crud_op=create --crud_arg=periodicjs.ext.dbseed 63 | ``` 64 | 65 | The `crud` command calls the internal periodic persistence storage methods. Periodic's CRUD functions are used to create, retrieve, update, delete configurations and extensions 66 | 67 | ```javascript 68 | //parsed command line arguments 69 | const options = { 70 | argv: { 71 | cli: true, //required 72 | crud: 'ext'||'config'||'con', //required 73 | crud_op: 'create'||'remove'||'update'||'get'||'list'||'init', //required 74 | crug_arg: 'arguments passed to command function' //optional 75 | } 76 | }; 77 | 78 | //method called: 79 | periodic.crud[options.argv.crud][options.argv.crud_op](options.argv.crud_arg) 80 | .then(periodic.logger.info) 81 | .catch(periodic.logger.error); 82 | ``` 83 | 84 | There are a number of helper crud methods 85 | 86 | * `$ periodicjs addExtension periodicjs.ext.dbseed` 87 | * `$ periodicjs removeExtension periodicjs.ext.dbseed` 88 | * `$ periodicjs addContainer react-single-page-theme` 89 | * `$ periodicjs removeContainer react-single-page-theme` 90 | 91 | -------------------------------------------------------------------------------- /doc/cli/02-command-line-interface.md: -------------------------------------------------------------------------------- 1 | # Command Line Interface 2 | 3 | Periodic comes with a built in Command Line Interface (CLI) with three main features 4 | * REPL - an interactive shell 5 | * CRUD - access to periodic's internal persistent storage faculties 6 | * Tasks - access to mounted asychronous methods from extensions and containers. 7 | 8 | ## `$ periodicjs repl` - interactive periodic shell 9 | 10 | ```console 11 | $ periodicjs repl 12 | $ #alternatively 13 | $ node [path/to/app_root/]index.js --cli --repl 14 | ``` 15 | 16 | The `repl` CLI command creates an interactive shell with access to your fully initialized periodic application 17 | 18 | ```javascript 19 | const repl = require('repl'); 20 | const r = repl.start('$p > '); 21 | r.context.$p = periodic;Í 22 | ``` 23 | 24 | ## `$ periodicjs commands` - asynchronous mounted tasks 25 | 26 | ```console 27 | $ periodicjs command extension periodicjs.ext.dbseed import path/to/seedfile.json 28 | $ #alternatively 29 | $ node [path/to/app_root/]index.js --cli --command --ext --name=periodicjs.ext.dbseed --task=import --args 30 | ``` 31 | 32 | The `commands` CLI command calls mounted asynchronous procedures called **tasks** from your periodic application during start up. Extensions and Containers tasks are mounted from exported asynchronous functions located in `[name-of-ext||name-of-container]/tasks/index.js`. 33 | 34 | ```javascript 35 | //parsed command line arguments 36 | const options = { 37 | argv: { 38 | cli: true, //required 39 | command: true, //required 40 | ext: true, //optional 41 | container: true, //optional 42 | name: 'name of container or extension', //required 43 | task: 'name of cli command async function', //required 44 | args: 'arguments passed to command function' //optional 45 | } 46 | }; 47 | 48 | //method called: 49 | const commandType = (options.argv.ext) ? 'extensions' : 'container'; 50 | periodic.resources.commands[commandType] 51 | .get(options.argv.name)[options.argv.task] 52 | .call(periodic, options.argv.args) 53 | .then(periodic.logger.info) 54 | .catch(periodic.logger.error); 55 | ``` 56 | 57 | ## `$ periodicjs crud` - internal storage helpers 58 | 59 | ```console 60 | $ periodicjs crud extension create periodicjs.ext.dbseed 61 | $ #alternatively 62 | $ node [path/to/app_root/]index.js --cli --crud=extension --crud_op=create --crud_arg=periodicjs.ext.dbseed 63 | ``` 64 | 65 | The `crud` command calls the internal periodic persistence storage methods. Periodic's CRUD functions are used to create, retrieve, update, delete configurations and extensions 66 | 67 | ```javascript 68 | //parsed command line arguments 69 | const options = { 70 | argv: { 71 | cli: true, //required 72 | crud: 'ext'||'config'||'con', //required 73 | crud_op: 'create'||'remove'||'update'||'get'||'list'||'init', //required 74 | crug_arg: 'arguments passed to command function' //optional 75 | } 76 | }; 77 | 78 | //method called: 79 | periodic.crud[options.argv.crud][options.argv.crud_op](options.argv.crud_arg) 80 | .then(periodic.logger.info) 81 | .catch(periodic.logger.error); 82 | ``` 83 | 84 | There are a number of helper crud methods 85 | 86 | * `$ periodicjs addExtension periodicjs.ext.dbseed` 87 | * `$ periodicjs removeExtension periodicjs.ext.dbseed` 88 | * `$ periodicjs addContainer react-single-page-theme` 89 | * `$ periodicjs removeContainer react-single-page-theme` 90 | 91 | -------------------------------------------------------------------------------- /doc/cli/03-interactive-shell.md: -------------------------------------------------------------------------------- 1 | # Command Line Interface 2 | 3 | Periodic comes with a built in Command Line Interface (CLI) with three main features 4 | * REPL - an interactive shell 5 | * CRUD - access to periodic's internal persistent storage faculties 6 | * Tasks - access to mounted asychronous methods from extensions and containers. 7 | 8 | ## `$ periodicjs repl` - interactive periodic shell 9 | 10 | ```console 11 | $ periodicjs repl 12 | $ #alternatively 13 | $ node [path/to/app_root/]index.js --cli --repl 14 | ``` 15 | 16 | The `repl` CLI command creates an interactive shell with access to your fully initialized periodic application 17 | 18 | ```javascript 19 | const repl = require('repl'); 20 | const r = repl.start('$p > '); 21 | r.context.$p = periodic;Í 22 | ``` 23 | 24 | ## `$ periodicjs commands` - asynchronous mounted tasks 25 | 26 | ```console 27 | $ periodicjs command extension periodicjs.ext.dbseed import path/to/seedfile.json 28 | $ #alternatively 29 | $ node [path/to/app_root/]index.js --cli --command --ext --name=periodicjs.ext.dbseed --task=import --args 30 | ``` 31 | 32 | The `commands` CLI command calls mounted asynchronous procedures called **tasks** from your periodic application during start up. Extensions and Containers tasks are mounted from exported asynchronous functions located in `[name-of-ext||name-of-container]/tasks/index.js`. 33 | 34 | ```javascript 35 | //parsed command line arguments 36 | const options = { 37 | argv: { 38 | cli: true, //required 39 | command: true, //required 40 | ext: true, //optional 41 | container: true, //optional 42 | name: 'name of container or extension', //required 43 | task: 'name of cli command async function', //required 44 | args: 'arguments passed to command function' //optional 45 | } 46 | }; 47 | 48 | //method called: 49 | const commandType = (options.argv.ext) ? 'extensions' : 'container'; 50 | periodic.resources.commands[commandType] 51 | .get(options.argv.name)[options.argv.task] 52 | .call(periodic, options.argv.args) 53 | .then(periodic.logger.info) 54 | .catch(periodic.logger.error); 55 | ``` 56 | 57 | ## `$ periodicjs crud` - internal storage helpers 58 | 59 | ```console 60 | $ periodicjs crud extension create periodicjs.ext.dbseed 61 | $ #alternatively 62 | $ node [path/to/app_root/]index.js --cli --crud=extension --crud_op=create --crud_arg=periodicjs.ext.dbseed 63 | ``` 64 | 65 | The `crud` command calls the internal periodic persistence storage methods. Periodic's CRUD functions are used to create, retrieve, update, delete configurations and extensions 66 | 67 | ```javascript 68 | //parsed command line arguments 69 | const options = { 70 | argv: { 71 | cli: true, //required 72 | crud: 'ext'||'config'||'con', //required 73 | crud_op: 'create'||'remove'||'update'||'get'||'list'||'init', //required 74 | crug_arg: 'arguments passed to command function' //optional 75 | } 76 | }; 77 | 78 | //method called: 79 | periodic.crud[options.argv.crud][options.argv.crud_op](options.argv.crud_arg) 80 | .then(periodic.logger.info) 81 | .catch(periodic.logger.error); 82 | ``` 83 | 84 | There are a number of helper crud methods 85 | 86 | * `$ periodicjs addExtension periodicjs.ext.dbseed` 87 | * `$ periodicjs removeExtension periodicjs.ext.dbseed` 88 | * `$ periodicjs addContainer react-single-page-theme` 89 | * `$ periodicjs removeContainer react-single-page-theme` 90 | 91 | -------------------------------------------------------------------------------- /doc/configuration/01-overview.md: -------------------------------------------------------------------------------- 1 | # Configuration 2 | 3 | Configurations are a declarative mechanism for customizing your application and are located in your application's configuration database. 4 | 5 | With Configurations, you can overwrite the default settings for you application, loaded extensions and your application's container. 6 | 7 | * [ What are Periodic Configurations? ](https://github.com/repetere/periodicjs/blob/master/doc/configuration/02-what-are-periodic-configurations.md) 8 | * [ How are runtime environments configured? ](https://github.com/repetere/periodicjs/blob/master/doc/configuration/03-how-are-runtime-environments-configured.md) 9 | * [ How are Configurations loaded? ](https://github.com/repetere/periodicjs/blob/master/doc/configuration/03-how-are-configurations-loaded.md) 10 | * [ Creating Configurations ](https://github.com/repetere/periodicjs/blob/master/doc/configuration/04-creating-your-own-configurations.md) 11 | * [ Adding and Removing Configurations ](https://github.com/repetere/periodicjs/blob/master/doc/configuration/05-adding-and-removing-configurations.md) 12 | 13 | NEXT: [ What are Periodic Configurations? ](https://github.com/repetere/periodicjs/blob/master/doc/configuration/02-what-are-periodic-configurations.md) 14 | -------------------------------------------------------------------------------- /doc/configuration/03-how-are-runtime-environments-configured.md: -------------------------------------------------------------------------------- 1 | # How are runtime environments configured? 2 | 3 | In order to run your application, a runtime environment must be configured. 4 | 5 | ## Runtime environment command line argument 6 | 7 | Setting the runtime environment via a command line argument, or as an environment variable. 8 | 9 | Periodic will prioritize command line arguments over environment variables 10 | 11 | ``` 12 | $ node index.js development 13 | ``` 14 | ``` 15 | $ node index.js -e development 16 | ``` 17 | ``` 18 | $ node index.js --e=development 19 | ``` 20 | ``` 21 | $ NODE_ENV=development node index.js 22 | ``` 23 | ``` 24 | $ ENV=development node index.js 25 | ``` 26 | 27 | After you've specified a runtime environment via the command line, periodic will store the last runtime environment in your applications configuration db (in the file path `content/config/process/runtime.json`). 28 | 29 | ## (Advanced) Runtime environment database configuration record 30 | 31 | You can add/update the database record in the configuration database for your saved runtime environment 32 | ```javascript 33 | { 34 | "filepath" : "content/config/process/runtime.json", 35 | "config" : { 36 | "process" : { 37 | "runtime" : "development" //you can set the saved runtime environment 38 | } 39 | } 40 | } 41 | ``` 42 | 43 | NEXT: [ Creating Configurations ](https://github.com/repetere/periodicjs/blob/master/doc/configuration/04-creating-your-own-configurations.md) 44 | -------------------------------------------------------------------------------- /doc/configuration/05-adding-and-removing-configurations.md: -------------------------------------------------------------------------------- 1 | # Adding configurations - `$ periodicjs addConfig path/to/some/file.json` 2 | 3 | You can add configurations to your database manually or you can use the Periodic CLI to add configurations. 4 | 5 | ```console 6 | $ cd path/to/app_root 7 | $ periodicjs addConfig [path/to/some/file.json] 8 | $ #alternatively 9 | $ node [path/to/app_root/]index.js --cli --crud=config --crud_op=create --crud_arg=[path/to/some/file.json] 10 | ``` 11 | 12 | Behind the scenes, the CLI uses periodic's internal crud methods to add a new database record via Core Data 13 | ```javascript 14 | const configurationDB = periodic.datas.get('configuration'); //Core Data DB 15 | 16 | function create(filepath){ 17 | const createdat = Date.now(); 18 | const updatedat = Date.now(); 19 | return new Promise((resolve,reject)=>{ 20 | fs.readJSON(path.resolve(filepath)) 21 | .then(configJSON => { 22 | resolve(configurationDB.create({ 23 | newdoc: Object.assign({}, 24 | configJSON, { 25 | createdat, 26 | updatedat, 27 | }), 28 | })); 29 | }) 30 | .catch(reject); 31 | }); 32 | } 33 | ``` 34 | 35 | Example: 36 | ```console 37 | $ cd /var/www/webapp 38 | $ periodicjs addConfig ~/my-documents/my-app-config.json 39 | ``` 40 | 41 | # Removing configurations - `$ periodicjs removeConfig [id-of-db-config]` 42 | 43 | To remove a configuration from the configuration db, you must specify the database record id. 44 | 45 | ```console 46 | $ cd path/to/app_root 47 | $ periodicjs removeConfig [id-of-db-config] 48 | $ #alternatively 49 | $ node [path/to/app_root/]index.js --cli --crud=ext --crud_op=remove --crud_arg=[id-of-db-config] 50 | ``` 51 | 52 | Example: 53 | ```console 54 | $ cd /var/www/webapp 55 | $ periodicjs removeConfig 5914a3711a04c73349623be5 56 | ``` 57 | 58 | NEXT: [ Extensions ](https://github.com/repetere/periodicjs/blob/master/doc/extensions/01-overview.md) -------------------------------------------------------------------------------- /doc/extensions/01-overview.md: -------------------------------------------------------------------------------- 1 | # Extensions 2 | 3 | Extensions are used to add functionality to your periodic application. Extensions are loaded, initialized, configured and mounted during the periodic initialization process. 4 | 5 | Extensions are typically stitched together to build a customized web application or API. 6 | 7 | * [ What are Periodic Extensions? ](https://github.com/repetere/periodicjs/blob/master/doc/extensions/02-what-are-periodic-extensions.md) 8 | * [ How do Periodic Extensions work? ](https://github.com/repetere/periodicjs/blob/master/doc/extensions/03-how-are-extensions-loaded.md) 9 | * [ How are Extensions loaded? ](https://github.com/repetere/periodicjs/blob/master/doc/extensions/03-how-are-extensions-loaded.md) 10 | * [ What are some common Extensions? ](https://github.com/repetere/periodicjs/blob/master/doc/extensions/04-what-are-some-common-extensions.md) 11 | * [ Installing and Removing Extensions ](https://github.com/repetere/periodicjs/blob/master/doc/extensions/05-installing-and-removing-extensions.md) 12 | * [ Configuring Extensions ](https://github.com/repetere/periodicjs/blob/master/doc/extensions/06-configuring-extensions.md) 13 | * [ Creating Extensions ](https://github.com/repetere/periodicjs/blob/master/doc/extensions/07-creating-your-own-extensions.md) 14 | 15 | NEXT: [ What are Periodic Extensions? ](https://github.com/repetere/periodicjs/blob/master/doc/extensions/02-what-are-periodic-extensions.md) -------------------------------------------------------------------------------- /doc/extensions/04-what-are-some-common-extensions.md: -------------------------------------------------------------------------------- 1 | # What are some common Extensions? 2 | 3 | In Periodic10 there are no restrictions on the naming convention for extensions, but they are typically prefixed with `periodicjs.ext` 4 | 5 | * periodicjs.ext.packagecloud 6 | * An extension for using packagecloud to upload files to a numerous cloud storage service providers (e.g. Amazon S3). 7 | * periodicjs.ext.passport 8 | * An extension for using passport to handle user authentication via multple authentication strategies (OAuth, OAuth2, Social Signin [Facebook, Twitter, Google, etc], Single Sign-On). 9 | * periodicjs.ext.oauth2client 10 | * The ability to authenticate users with OAuth2. 11 | * periodicjs.ext.oauth2server 12 | * An extension enabling your application to serve as an OAuth2 server. 13 | * periodicjs.ext.reactadmin 14 | * A React based Single Page Application Admin UI for your web application, with auto-generated views based off of your database models. 15 | * periodicjs.ext.user_access_control 16 | * An extension for providing granular ACL within your application 17 | * periodicjs.ext.basicadmin 18 | * A very basic admin ui based off of your database models. 19 | * periodicjs.ext.dbseed 20 | * An export/import data extension for loading data into your application 21 | 22 | NEXT: [ Installing and Removing Extensions ](https://github.com/repetere/periodicjs/blob/master/doc/extensions/05-installing-and-removing-extensions.md) -------------------------------------------------------------------------------- /doc/extensions/05-installing-and-removing-extensions.md: -------------------------------------------------------------------------------- 1 | # Installing extensions - `$ periodicjs addExtension [name-of-extension]` 2 | 3 | Periodic extensions are regular node modules, so to install a new extension use npm (or yarn) to install your extension and then add the extension to your application's extension database. 4 | 5 | ```console 6 | $ cd path/to/application_root 7 | $ npm i [name-of-extension] 8 | $ periodicjs addExtension [name-of-extension] 9 | $ #alternatively 10 | $ node [path/to/app_root/]index.js --cli --crud=ext --crud_op=create --crud_arg=[name-of-extension] 11 | ``` 12 | 13 | # Removing extensions - `$ periodicjs removeExtension [name-of-extension]` 14 | 15 | Similarly, to remove an extension, use npm (or yarn) to remove the extension and also remove the extension from your application's extension db. 16 | 17 | ```console 18 | $ cd path/to/application_root 19 | $ npm i [name-of-extension] 20 | $ periodicjs removeExtension [name-of-extension] 21 | $ #alternatively 22 | $ node [path/to/app_root/]index.js --cli --crud=ext --crud_op=remove --crud_arg=[name-of-extension] 23 | ``` 24 | 25 | NEXT: [ Configuring Extensions ](https://github.com/repetere/periodicjs/blob/master/doc/extensions/06-configuring-extensions.md) 26 | -------------------------------------------------------------------------------- /doc/extensions/06-configuring-extensions.md: -------------------------------------------------------------------------------- 1 | # Creating configurations - `$ periodicjs createConfig extension [name] [environment] [filepath]` 2 | 3 | You can use the periodic CLI to create the scaffolding for a new configuration. 4 | 5 | Example (creating an extension configuration): 6 | ```console 7 | $ cd /var/www/webapp 8 | $ periodicjs createConfig ext periodicjs.ext.dbseed development ~/Desktop/dev.dbseed-config.json 9 | ``` 10 | 11 | ### Adding configurations - `$ periodicjs addConfig path/to/some/file.json` 12 | 13 | You can add configurations to your database manually or you can use the Periodic CLI to add configurations. 14 | ```console 15 | $ cd path/to/app_root 16 | $ periodicjs addConfig ~/Desktop/dev.dbseed-config.json 17 | ``` 18 | 19 | ### Removing configurations - `$ periodicjs removeConfig [id-of-db-config]` 20 | 21 | To remove a configuration from the configuration db, you must specify the database record id. 22 | 23 | ```console 24 | $ cd path/to/app_root 25 | $ periodicjs removeConfig [id-of-db-config] 26 | $ periodicjs removeConfig 5914a3711a04c73349623be5 27 | ``` 28 | 29 | NEXT: [ Creating Extensions ](https://github.com/repetere/periodicjs/blob/master/doc/extensions/07-creating-your-own-extensions.md) 30 | -------------------------------------------------------------------------------- /doc/extensions/07-creating-your-own-extensions.md: -------------------------------------------------------------------------------- 1 | # Creating extensions - `$ periodicjs createExtension [name-of-extension]` 2 | 3 | You can use the periodic CLI to create the scaffolding for a new extension. Internally the CLI command uses periodic's crud methods to scaffold your extension 4 | 5 | ```console 6 | $ cd path/to/application_root 7 | $ periodicjs createExtension [name-of-extension] 8 | $ #alternatively 9 | $ node [path/to/app_root/]index.js --cli --crud=ext --crud_op=init --crud_arg=[name-of-extension] 10 | ``` 11 | 12 | Have the command, you will have a new extension created in your node modules folder, with scaffolding for the 7 features 13 | 14 | 15 | ```javascript 16 | // app_root/node_modules/[name-of-extension] 17 | .coveralls.yml //placeholder for coveralls.io integration 18 | .eslintrc.json //default eslint rules 19 | .travis.yml //placeholder for travis-ci.org integration 20 | Gruntfile.js //auto-generated Grunt file for documentation and tests 21 | README.md //auto-generated readme 22 | commands //directory for CLI commands 23 | config //directory for default settings 24 | controllers //directory for express router middleware functions 25 | index.js //default extension module 26 | jsdoc.json //default jsdoc settings 27 | package.json //auto generated package.json file 28 | periodicjs.ext.json //auto generated extension manifest 29 | resources //placeholder for front-end scripts 30 | routers //directory for express routes 31 | test //auto generated tests 32 | transforms //placeholder directory for data transforms 33 | utilities // directory for app.locals.extensions properties 34 | views // front-end views directories 35 | ``` 36 | -------------------------------------------------------------------------------- /doc/getting_started.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | 4 | ![Getting started](https://raw.githubusercontent.com/repetere/periodicjs/master/doc/images/getting-started/01-setup-install.gif) 5 | 6 | With Periodic 10, you can get up and running with periodic with zero configuration. It takes 30 seconds to create your first application server with periodic. 7 | 8 | ```console 9 | $ npm install periodicjs -g 10 | $ periodicjs setup [name-of-application] 11 | $ cd [name-of-application] 12 | $ npm install 13 | $ npm start [name of environment] 14 | ``` 15 | 16 | ## The four step install 17 | 1. Install periodic globally to use the Command Line Interface (CLI) 18 | 2. Create a new application 19 | 3. Change directory to your new **application root** and Install periodic's dependencies 20 | 4. Start your application 21 | 22 | ### 1. Install periodic globally to use the CLI (optional) 23 | 24 | ``` 25 | $ npm install periodicjs -g 26 | ``` 27 | Periodic comes with a built in CLI, REPL and other tools to fast track development. Using the CLI is completely optional. 28 | 29 | ### 2. Create a new node application with the CLI (optional) 30 | 31 | ``` 32 | $ periodicjs setup [name-of-application] 33 | ``` 34 | The `setup` command will create a zero-configuration scaffolded node.js web application. 35 | * The `setup` command create's a new directory for your application, this directory is what is referred to as the `app_root` or your **application root**. 36 | * After your `app_root` directory is created, two scaffolded `package.json` and `index.js` files are created 37 | 38 | #### index.js 39 | ```javascript 40 | //example ES6 import periodic from 'periodic'; //periodic singleton 41 | //example index.js - ES5 42 | 'use strict'; 43 | const periodic = require('periodicjs'); //periodic singleton 44 | periodic.init() 45 | .then(console.log.bind(console)) //log startup status 46 | .catch(console.error.bind(console)) //log any errors 47 | ``` 48 | 49 | #### package.json 50 | ```json 51 | { 52 | "name": "[name-of-application]", 53 | "description": "Simple app server.", 54 | "version": "0.0.1", 55 | "main": "index.js", 56 | "engines": { 57 | "node": "^6.x" 58 | }, 59 | "scripts": { 60 | "start": "node index.js --e", 61 | "test": "mocha -R spec --recursive" 62 | }, 63 | "dependencies": { 64 | "periodicjs": "^10.0.0" 65 | } 66 | } 67 | ``` 68 | 69 | ### 3. Change directory to your new **application root** and install periodic dependencies 70 | 71 | ``` 72 | $ cd [name-of-application] 73 | $ npm install 74 | ``` 75 | 76 | The scaffolded `package.json` file only has one dependency **periodicjs**. In order to use multiple databases you may need to install other dependencies (read more about configuring periodic). 77 | 78 | 79 | ### 4. Start your application 80 | 81 | ``` 82 | $ npm start [name of environment] 83 | ``` 84 | 85 | Periodic requires a runtime environment to be defined when your application starts. Your periodic application can have an unlimited number of environments all with different configuration settings. 86 | 87 | NEXT: [ How Periodic works ](https://github.com/repetere/periodicjs/blob/master/doc/README.md) 88 | -------------------------------------------------------------------------------- /doc/html/fonts/OpenSans-Bold-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/repetere/periodicjs/fc31f56c348a831dc407d95785195c12a589b44a/doc/html/fonts/OpenSans-Bold-webfont.eot -------------------------------------------------------------------------------- /doc/html/fonts/OpenSans-Bold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/repetere/periodicjs/fc31f56c348a831dc407d95785195c12a589b44a/doc/html/fonts/OpenSans-Bold-webfont.woff -------------------------------------------------------------------------------- /doc/html/fonts/OpenSans-BoldItalic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/repetere/periodicjs/fc31f56c348a831dc407d95785195c12a589b44a/doc/html/fonts/OpenSans-BoldItalic-webfont.eot -------------------------------------------------------------------------------- /doc/html/fonts/OpenSans-BoldItalic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/repetere/periodicjs/fc31f56c348a831dc407d95785195c12a589b44a/doc/html/fonts/OpenSans-BoldItalic-webfont.woff -------------------------------------------------------------------------------- /doc/html/fonts/OpenSans-Italic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/repetere/periodicjs/fc31f56c348a831dc407d95785195c12a589b44a/doc/html/fonts/OpenSans-Italic-webfont.eot -------------------------------------------------------------------------------- /doc/html/fonts/OpenSans-Italic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/repetere/periodicjs/fc31f56c348a831dc407d95785195c12a589b44a/doc/html/fonts/OpenSans-Italic-webfont.woff -------------------------------------------------------------------------------- /doc/html/fonts/OpenSans-Light-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/repetere/periodicjs/fc31f56c348a831dc407d95785195c12a589b44a/doc/html/fonts/OpenSans-Light-webfont.eot -------------------------------------------------------------------------------- /doc/html/fonts/OpenSans-Light-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/repetere/periodicjs/fc31f56c348a831dc407d95785195c12a589b44a/doc/html/fonts/OpenSans-Light-webfont.woff -------------------------------------------------------------------------------- /doc/html/fonts/OpenSans-LightItalic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/repetere/periodicjs/fc31f56c348a831dc407d95785195c12a589b44a/doc/html/fonts/OpenSans-LightItalic-webfont.eot -------------------------------------------------------------------------------- /doc/html/fonts/OpenSans-LightItalic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/repetere/periodicjs/fc31f56c348a831dc407d95785195c12a589b44a/doc/html/fonts/OpenSans-LightItalic-webfont.woff -------------------------------------------------------------------------------- /doc/html/fonts/OpenSans-Regular-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/repetere/periodicjs/fc31f56c348a831dc407d95785195c12a589b44a/doc/html/fonts/OpenSans-Regular-webfont.eot -------------------------------------------------------------------------------- /doc/html/fonts/OpenSans-Regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/repetere/periodicjs/fc31f56c348a831dc407d95785195c12a589b44a/doc/html/fonts/OpenSans-Regular-webfont.woff -------------------------------------------------------------------------------- /doc/html/index.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | JSDoc: Source: index.js 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 |

Source: index.js

21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 |
'use strict';
30 | // require('babel-polyfill');
31 | // require('proxy-polyfill');
32 | /**
33 |  * Periodic is an application framework for building enterprise javascript applications.
34 |  * @exports periodic a reference to the periodic singleton module
35 |  */
36 | module.exports = require('./lib/periodic');
37 |
38 |
39 | 40 | 41 | 42 | 43 |
44 | 45 | 48 | 49 |
50 | 51 |
52 | Documentation generated by JSDoc 3.5.5 on Wed Jul 18 2018 23:08:12 GMT-0400 (Eastern Daylight Time) 53 |
54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /doc/html/lib_schemas_config.lowkie.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | JSDoc: Source: lib/schemas/config.lowkie.js 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 |

Source: lib/schemas/config.lowkie.js

21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 |
'use strict';
30 | const lowkie = require('lowkie');
31 | const configSchema = lowkie.Schema({
32 |   filepath: String,
33 |   environment: String,
34 |   container: {
35 |     type: String,
36 |     default: 'periodicjs.container.default',
37 |   },
38 |   config: lowkie.Schema.Types.Mixed,
39 |   createdat: {
40 |     type: Date,
41 |     'default': Date.now,
42 |     // index: true,
43 |   },
44 |   updatedat: {
45 |     type: Date,
46 |     'default': Date.now
47 |   },
48 | });
49 | /**
50 |  * name_of_file: string (e.g. 'content/config/extensions.json','content/config/environment/development.json','content/config/extensions/peridicjs.ext.dbseed.json')
51 | application_environment: string
52 | settings: schema_type_mixed
53 |  */
54 | 
55 | module.exports = configSchema;
56 |
57 |
58 | 59 | 60 | 61 | 62 |
63 | 64 | 67 | 68 |
69 | 70 |
71 | Documentation generated by JSDoc 3.5.5 on Wed Jul 18 2018 23:08:12 GMT-0400 (Eastern Daylight Time) 72 |
73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /doc/html/scripts/linenumber.js: -------------------------------------------------------------------------------- 1 | /*global document */ 2 | (function() { 3 | var source = document.getElementsByClassName('prettyprint source linenums'); 4 | var i = 0; 5 | var lineNumber = 0; 6 | var lineId; 7 | var lines; 8 | var totalLines; 9 | var anchorHash; 10 | 11 | if (source && source[0]) { 12 | anchorHash = document.location.hash.substring(1); 13 | lines = source[0].getElementsByTagName('li'); 14 | totalLines = lines.length; 15 | 16 | for (; i < totalLines; i++) { 17 | lineNumber++; 18 | lineId = 'line' + lineNumber; 19 | lines[i].id = lineId; 20 | if (lineId === anchorHash) { 21 | lines[i].className += ' selected'; 22 | } 23 | } 24 | } 25 | })(); 26 | -------------------------------------------------------------------------------- /doc/html/scripts/prettify/lang-css.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com", 2 | /^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); 3 | -------------------------------------------------------------------------------- /doc/html/styles/prettify-jsdoc.css: -------------------------------------------------------------------------------- 1 | /* JSDoc prettify.js theme */ 2 | 3 | /* plain text */ 4 | .pln { 5 | color: #000000; 6 | font-weight: normal; 7 | font-style: normal; 8 | } 9 | 10 | /* string content */ 11 | .str { 12 | color: #006400; 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | 17 | /* a keyword */ 18 | .kwd { 19 | color: #000000; 20 | font-weight: bold; 21 | font-style: normal; 22 | } 23 | 24 | /* a comment */ 25 | .com { 26 | font-weight: normal; 27 | font-style: italic; 28 | } 29 | 30 | /* a type name */ 31 | .typ { 32 | color: #000000; 33 | font-weight: normal; 34 | font-style: normal; 35 | } 36 | 37 | /* a literal value */ 38 | .lit { 39 | color: #006400; 40 | font-weight: normal; 41 | font-style: normal; 42 | } 43 | 44 | /* punctuation */ 45 | .pun { 46 | color: #000000; 47 | font-weight: bold; 48 | font-style: normal; 49 | } 50 | 51 | /* lisp open bracket */ 52 | .opn { 53 | color: #000000; 54 | font-weight: bold; 55 | font-style: normal; 56 | } 57 | 58 | /* lisp close bracket */ 59 | .clo { 60 | color: #000000; 61 | font-weight: bold; 62 | font-style: normal; 63 | } 64 | 65 | /* a markup tag name */ 66 | .tag { 67 | color: #006400; 68 | font-weight: normal; 69 | font-style: normal; 70 | } 71 | 72 | /* a markup attribute name */ 73 | .atn { 74 | color: #006400; 75 | font-weight: normal; 76 | font-style: normal; 77 | } 78 | 79 | /* a markup attribute value */ 80 | .atv { 81 | color: #006400; 82 | font-weight: normal; 83 | font-style: normal; 84 | } 85 | 86 | /* a declaration */ 87 | .dec { 88 | color: #000000; 89 | font-weight: bold; 90 | font-style: normal; 91 | } 92 | 93 | /* a variable name */ 94 | .var { 95 | color: #000000; 96 | font-weight: normal; 97 | font-style: normal; 98 | } 99 | 100 | /* a function name */ 101 | .fun { 102 | color: #000000; 103 | font-weight: bold; 104 | font-style: normal; 105 | } 106 | 107 | /* Specify class=linenums on a pre to get line numbering */ 108 | ol.linenums { 109 | margin-top: 0; 110 | margin-bottom: 0; 111 | } 112 | -------------------------------------------------------------------------------- /doc/html/styles/prettify-tomorrow.css: -------------------------------------------------------------------------------- 1 | /* Tomorrow Theme */ 2 | /* Original theme - https://github.com/chriskempson/tomorrow-theme */ 3 | /* Pretty printing styles. Used with prettify.js. */ 4 | /* SPAN elements with the classes below are added by prettyprint. */ 5 | /* plain text */ 6 | .pln { 7 | color: #4d4d4c; } 8 | 9 | @media screen { 10 | /* string content */ 11 | .str { 12 | color: #718c00; } 13 | 14 | /* a keyword */ 15 | .kwd { 16 | color: #8959a8; } 17 | 18 | /* a comment */ 19 | .com { 20 | color: #8e908c; } 21 | 22 | /* a type name */ 23 | .typ { 24 | color: #4271ae; } 25 | 26 | /* a literal value */ 27 | .lit { 28 | color: #f5871f; } 29 | 30 | /* punctuation */ 31 | .pun { 32 | color: #4d4d4c; } 33 | 34 | /* lisp open bracket */ 35 | .opn { 36 | color: #4d4d4c; } 37 | 38 | /* lisp close bracket */ 39 | .clo { 40 | color: #4d4d4c; } 41 | 42 | /* a markup tag name */ 43 | .tag { 44 | color: #c82829; } 45 | 46 | /* a markup attribute name */ 47 | .atn { 48 | color: #f5871f; } 49 | 50 | /* a markup attribute value */ 51 | .atv { 52 | color: #3e999f; } 53 | 54 | /* a declaration */ 55 | .dec { 56 | color: #f5871f; } 57 | 58 | /* a variable name */ 59 | .var { 60 | color: #c82829; } 61 | 62 | /* a function name */ 63 | .fun { 64 | color: #4271ae; } } 65 | /* Use higher contrast and text-weight for printable form. */ 66 | @media print, projection { 67 | .str { 68 | color: #060; } 69 | 70 | .kwd { 71 | color: #006; 72 | font-weight: bold; } 73 | 74 | .com { 75 | color: #600; 76 | font-style: italic; } 77 | 78 | .typ { 79 | color: #404; 80 | font-weight: bold; } 81 | 82 | .lit { 83 | color: #044; } 84 | 85 | .pun, .opn, .clo { 86 | color: #440; } 87 | 88 | .tag { 89 | color: #006; 90 | font-weight: bold; } 91 | 92 | .atn { 93 | color: #404; } 94 | 95 | .atv { 96 | color: #060; } } 97 | /* Style */ 98 | /* 99 | pre.prettyprint { 100 | background: white; 101 | font-family: Consolas, Monaco, 'Andale Mono', monospace; 102 | font-size: 12px; 103 | line-height: 1.5; 104 | border: 1px solid #ccc; 105 | padding: 10px; } 106 | */ 107 | 108 | /* Specify class=linenums on a pre to get line numbering */ 109 | ol.linenums { 110 | margin-top: 0; 111 | margin-bottom: 0; } 112 | 113 | /* IE indents via margin-left */ 114 | li.L0, 115 | li.L1, 116 | li.L2, 117 | li.L3, 118 | li.L4, 119 | li.L5, 120 | li.L6, 121 | li.L7, 122 | li.L8, 123 | li.L9 { 124 | /* */ } 125 | 126 | /* Alternate shading for lines */ 127 | li.L1, 128 | li.L3, 129 | li.L5, 130 | li.L7, 131 | li.L9 { 132 | /* */ } 133 | -------------------------------------------------------------------------------- /doc/images/dark_logo_transparent_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/repetere/periodicjs/fc31f56c348a831dc407d95785195c12a589b44a/doc/images/dark_logo_transparent_background.png -------------------------------------------------------------------------------- /doc/images/getting-started/01-setup-install.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/repetere/periodicjs/fc31f56c348a831dc407d95785195c12a589b44a/doc/images/getting-started/01-setup-install.gif -------------------------------------------------------------------------------- /doc/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/repetere/periodicjs/fc31f56c348a831dc407d95785195c12a589b44a/doc/images/logo.png -------------------------------------------------------------------------------- /doc/images/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /doc/images/logo_sm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/repetere/periodicjs/fc31f56c348a831dc407d95785195c12a589b44a/doc/images/logo_sm.png -------------------------------------------------------------------------------- /doc/images/white_logo_color_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/repetere/periodicjs/fc31f56c348a831dc407d95785195c12a589b44a/doc/images/white_logo_color_background.png -------------------------------------------------------------------------------- /doc/overview/command_line_interface.md: -------------------------------------------------------------------------------- 1 | # Command Line Interface 2 | 3 | Periodic comes with a built in Command Line Interface (CLI) with three main features 4 | * REPL - an interactive shell 5 | * CRUD - access to periodic's internal persistent storage faculties 6 | * Tasks - access to mounted asychronous methods from extensions and containers. 7 | 8 | ## `$ periodicjs repl` - interactive periodic shell 9 | 10 | ```console 11 | $ periodicjs repl 12 | $ #alternatively 13 | $ node [path/to/app_root/]index.js --cli --repl 14 | ``` 15 | 16 | The `repl` CLI command creates an interactive shell with access to your fully initialized periodic application 17 | 18 | ```javascript 19 | const repl = require('repl'); 20 | const r = repl.start('$p > '); 21 | r.context.$p = periodic; 22 | ``` 23 | 24 | ## `$ periodicjs commands` - asynchronous mounted tasks 25 | 26 | ```console 27 | $ periodicjs command extension periodicjs.ext.dbseed import path/to/seedfile.json 28 | $ #alternatively 29 | $ node [path/to/app_root/]index.js --cli --command --ext --name=periodicjs.ext.dbseed --task=import --args 30 | ``` 31 | 32 | The `commands` CLI command calls mounted asynchronous procedures called **tasks** from your periodic application during start up. Extensions and Containers tasks are mounted from exported asynchronous functions located in `[name-of-ext||name-of-container]/tasks/index.js`. 33 | 34 | ```javascript 35 | //parsed command line arguments 36 | const options = { 37 | argv: { 38 | cli: true, //required 39 | command: true, //required 40 | ext: true, //optional 41 | container: true, //optional 42 | name: 'name of container or extension', //required 43 | task: 'name of cli command async function', //required 44 | args: 'arguments passed to command function' //optional 45 | } 46 | }; 47 | 48 | //method called: 49 | const commandType = (options.argv.ext) ? 'extensions' : 'container'; 50 | periodic.resources.commands[commandType] 51 | .get(options.argv.name)[options.argv.task] 52 | .call(periodic, options.argv.args) 53 | .then(periodic.logger.info) 54 | .catch(periodic.logger.error); 55 | ``` 56 | 57 | ## `$ periodicjs crud` - internal storage helpers 58 | 59 | ```console 60 | $ periodicjs crud extension create periodicjs.ext.dbseed 61 | $ #alternatively 62 | $ node [path/to/app_root/]index.js --cli --crud=extension --crud_op=create --crud_arg=periodicjs.ext.dbseed 63 | ``` 64 | 65 | The `crud` command calls the internal periodic persistence storage methods. Periodic's CRUD functions are used to create, retrieve, update, delete configurations and extensions 66 | 67 | ```javascript 68 | //parsed command line arguments 69 | const options = { 70 | argv: { 71 | cli: true, //required 72 | crud: 'ext'||'config'||'con', //required 73 | crud_op: 'create'||'remove'||'update'||'get'||'list'||'init', //required 74 | crug_arg: 'arguments passed to command function' //optional 75 | } 76 | }; 77 | 78 | //method called: 79 | periodic.crud[options.argv.crud][options.argv.crud_op](options.argv.crud_arg) 80 | .then(periodic.logger.info) 81 | .catch(periodic.logger.error); 82 | ``` 83 | 84 | There are a number of helper crud methods 85 | 86 | * `$ periodicjs addExtension periodicjs.ext.dbseed` 87 | * `$ periodicjs removeExtension periodicjs.ext.dbseed` 88 | * `$ periodicjs addContainer react-single-page-theme` 89 | * `$ periodicjs removeContainer react-single-page-theme` 90 | 91 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | // require('babel-polyfill'); 3 | // require('proxy-polyfill'); 4 | /** 5 | * Periodic is an application framework for building enterprise javascript applications. 6 | * @exports periodic a reference to the periodic singleton module 7 | */ 8 | module.exports = require('./lib/periodic'); -------------------------------------------------------------------------------- /jsdoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "tags": { 3 | "allowUnknownTags": true 4 | }, 5 | "plugins": [ 6 | "plugins/markdown" 7 | ], 8 | "source": { 9 | "include": ["README.md"] 10 | }, 11 | "markdown": { 12 | "parser": "gfm", 13 | "hardwrap": true 14 | }, 15 | "templates": { 16 | "cleverLinks": true, 17 | "monospaceLinks": true 18 | } 19 | } -------------------------------------------------------------------------------- /lib/crud/__EXT_CONTAINER_STRUCTURE/.coveralls.yml: -------------------------------------------------------------------------------- 1 | service_name: travis-pro 2 | repo_token: U47HivigNTVyEgSm5Z79vUdwsD0WvCYGp -------------------------------------------------------------------------------- /lib/crud/__EXT_CONTAINER_STRUCTURE/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "eslint:recommended", 3 | "plugins": [], 4 | "parserOptions": { 5 | "ecmaFeatures": { 6 | "ecmaVersion": 6, 7 | "jsx": true 8 | } 9 | }, 10 | "ecmaFeatures": { 11 | "ecmaVersion": 6 12 | }, 13 | "rules": { 14 | "jsx-quotes": ["error", "prefer-double"], 15 | "indent": ["error", 2], 16 | "quotes": ["error", "single"], 17 | "semi": ["warn", "always"], 18 | "comma-dangle": ["warn", "always"], 19 | "comma-spacing": "warn", 20 | "array-bracket-spacing": "warn", 21 | "object-curly-spacing": ["error", "always"], 22 | "eqeqeq": "warn", 23 | "no-cond-assign": ["warn", "always"], 24 | "no-unused-vars": "warn", 25 | "no-console": "warn", 26 | "brace-style": ["warn", "1tbs"], 27 | "strict": ["error", "safe"] 28 | }, 29 | "env": { 30 | "browser": true, 31 | "commonjs": true, 32 | "es6": true, 33 | "node": true 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/crud/__EXT_CONTAINER_STRUCTURE/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "6.9.1" -------------------------------------------------------------------------------- /lib/crud/__EXT_CONTAINER_STRUCTURE/Gruntfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const testPaths = ['./test/**/*.js',]; 5 | 6 | module.exports = function (grunt) { 7 | grunt.initConfig({ 8 | mocha_istanbul: { 9 | coverage: { 10 | src: testPaths, // multiple folders also works 11 | reportFormats: ['cobertura', 'lcovonly',], 12 | }, 13 | }, 14 | istanbul_check_coverage: { 15 | default: { 16 | options: { 17 | coverageFolder: 'coverage', // will check both coverage folders and merge the coverage results 18 | check: { 19 | lines: 80, 20 | branches: 80, 21 | functions: 80, 22 | statements: 80, 23 | }, 24 | }, 25 | }, 26 | }, 27 | coveralls: { 28 | // Options relevant to all targets 29 | options: { 30 | // When true, grunt-coveralls will only print a warning rather than 31 | // an error, to prevent CI builds from failing unnecessarily (e.g. if 32 | // coveralls.io is down). Optional, defaults to false. 33 | force: false, 34 | }, 35 | all: { 36 | // LCOV coverage file (can be string, glob or array) 37 | src: 'coverage/*.info', 38 | options: { 39 | // Any options for just this target 40 | }, 41 | }, 42 | }, 43 | simplemocha: { 44 | options: { 45 | globals: ['should', 'navigator', 'x',], 46 | timeout: 3000, 47 | ignoreLeaks: true, 48 | ui: 'bdd', 49 | reporter: 'spec', 50 | }, 51 | all: { 52 | src: testPaths, 53 | }, 54 | }, 55 | jsdoc: { 56 | dist: { 57 | src: ['lib/**/*.js', 'index.js',], 58 | options: { 59 | destination: 'doc/html', 60 | configure: 'jsdoc.json', 61 | }, 62 | }, 63 | }, 64 | }); 65 | 66 | // Loading dependencies 67 | for (var key in grunt.file.readJSON('package.json').devDependencies) { 68 | if (key.indexOf('grunt') === 0 && key !== 'grunt') { 69 | grunt.loadNpmTasks(key); 70 | } 71 | } 72 | grunt.registerTask('doc', 'jsdoc'); 73 | grunt.registerTask('test', 'mocha_istanbul'); 74 | grunt.registerTask('default', [/*'lint',*/'test', /*'browserify',*/ 'doc', /*'uglify',*/ ]); 75 | }; -------------------------------------------------------------------------------- /lib/crud/__EXT_CONTAINER_STRUCTURE/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /lib/crud/__EXT_CONTAINER_STRUCTURE/README.md: -------------------------------------------------------------------------------- 1 | # periodicjs.ext.test -------------------------------------------------------------------------------- /lib/crud/__EXT_CONTAINER_STRUCTURE/commands/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const periodic = require('periodicjs'); 3 | 4 | module.exports = { 5 | hello: (options) => { 6 | periodic.logger.silly('hello',{options}); 7 | return new Promise((resolve, reject) => { 8 | resolve(true); 9 | }); 10 | } 11 | } -------------------------------------------------------------------------------- /lib/crud/__EXT_CONTAINER_STRUCTURE/config/databases/.gitkeep: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------------- /lib/crud/__EXT_CONTAINER_STRUCTURE/config/settings.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | settings: { 5 | defaults:true, 6 | }, 7 | databases: { 8 | }, 9 | }; -------------------------------------------------------------------------------- /lib/crud/__EXT_CONTAINER_STRUCTURE/controllers/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const periodic = require('periodicjs'); 3 | 4 | module.exports = { 5 | test: (req, res, next) => { 6 | periodic.logger.silly('test middleware'); 7 | next(); 8 | } 9 | } -------------------------------------------------------------------------------- /lib/crud/__EXT_CONTAINER_STRUCTURE/doc/.gitkeep: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------------- /lib/crud/__EXT_CONTAINER_STRUCTURE/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const periodic = require('periodicjs'); 3 | 4 | module.exports = () => { 5 | return Promise.resolve(true); 6 | } -------------------------------------------------------------------------------- /lib/crud/__EXT_CONTAINER_STRUCTURE/jsdoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "tags": { 3 | "allowUnknownTags": true 4 | }, 5 | "plugins": [ 6 | "plugins/markdown" 7 | ], 8 | "source":{ 9 | "include": ["README.md"] 10 | }, 11 | "markdown": { 12 | "parser": "gfm", 13 | "hardwrap": true 14 | }, 15 | "templates": { 16 | "cleverLinks": true, 17 | "monospaceLinks": true 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /lib/crud/__EXT_CONTAINER_STRUCTURE/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "periodicjs.ext.sample", 3 | "description": "sample extension.", 4 | "version": "0.0.1", 5 | "main": "index.js", 6 | "engines": { 7 | "node": "^6.x" 8 | }, 9 | "contributors": [ 10 | ], 11 | "repository": { 12 | }, 13 | "config": { 14 | "blanket": { 15 | "pattern": [ 16 | "content/themes" 17 | ] 18 | } 19 | }, 20 | "license": "MIT", 21 | "scripts": { 22 | "test": "mocha -R spec --recursive" 23 | }, 24 | "dependencies": { 25 | }, 26 | "devDependencies": { 27 | "browserify": "^13.0.0", 28 | "chai": "^3.0.0", 29 | "chai-as-promised": "^6.0.0", 30 | "coveralls": "^2.11.9", 31 | "grunt": "^1.0.1", 32 | "grunt-browserify": "^5.0.0", 33 | "grunt-contrib-copy": "^1.0.0", 34 | "grunt-contrib-cssmin": "^1.0.1", 35 | "grunt-contrib-jshint": "^1.0.0", 36 | "grunt-contrib-uglify": "^1.0.1", 37 | "grunt-contrib-watch": "^1.0.0", 38 | "grunt-coveralls": "^1.0.1", 39 | "grunt-jsbeautifier": "~0.2.7", 40 | "grunt-jsdoc": "^2.0.0", 41 | "grunt-mocha-cov": "^0.4.0", 42 | "grunt-mocha-istanbul": "^4.0.2", 43 | "grunt-newer": "^1.1.1", 44 | "grunt-simple-mocha": "^0.4.1", 45 | "istanbul": "^0.4.3", 46 | "jsdoc": "^3.3.2", 47 | "mocha": "^2.2.5", 48 | "periodicjs": "10.0.53", 49 | "node-mocks-http": "^1.6.2", 50 | "mocha-lcov-reporter": "^1.2.0", 51 | "mocha-sinon": "^2.0.0", 52 | "semver": "^5.3.0", 53 | "sinon": "^1.17.4", 54 | "sinon-chai": "^2.8.0" 55 | }, 56 | "keywords": [ 57 | ], 58 | "bugs": { 59 | }, 60 | "maintainers": [], 61 | "directories": {}, 62 | "optionalDependencies": {} 63 | } -------------------------------------------------------------------------------- /lib/crud/__EXT_CONTAINER_STRUCTURE/periodicjs.ext.json: -------------------------------------------------------------------------------- 1 | { 2 | "periodic_compatibility": "10.0.0", 3 | "periodic_dependencies": [], 4 | "periodic_type": 7, 5 | "periodic_priority": 0, 6 | "periodic_config": { 7 | } 8 | } -------------------------------------------------------------------------------- /lib/crud/__EXT_CONTAINER_STRUCTURE/public/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/repetere/periodicjs/fc31f56c348a831dc407d95785195c12a589b44a/lib/crud/__EXT_CONTAINER_STRUCTURE/public/.gitkeep -------------------------------------------------------------------------------- /lib/crud/__EXT_CONTAINER_STRUCTURE/resources/.gitkeep: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------------- /lib/crud/__EXT_CONTAINER_STRUCTURE/resources/async_routers/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | //required after configuration loaded 3 | const periodic = require('periodicjs'); 4 | const { Router, EventRouter, } = require('simple-socket-router/bundle/router.cjs.js'); 5 | const router = new Router(); 6 | // const socketAuth = require('socketio-auth'); 7 | 8 | // const { server: socketServer, sockets: socketConnections, } = periodic.servers.get('socket.io'); 9 | // router.addRoute('/test/users', function(req, res){ 10 | // console.log('got the 2nd test route'); 11 | // res.send('ok'); 12 | // }); 13 | // socketServer.on('connection', socket => { 14 | // socket.emit('debug', { status:'another test', }); 15 | // socket.use(EventRouter({ socket, router ,})); 16 | // }); 17 | 18 | // const AuthRoutes = socketServer.of('/auth'); 19 | // socketAuth(AuthRoutes, { //to use globally - socketAuth(socketServer, { 20 | // authenticate: (socket, data, callback) => { 21 | //get credentials sent by the client 22 | // const username = data.username; 23 | // const password = data.password; 24 | 25 | // db.findUser('User', {username:username}, function(err, user) { 26 | 27 | // //inform the callback of auth success/failure 28 | // if (err || !user) return callback(new Error("User not found")); 29 | // return callback(null, user.password == password); 30 | // }); 31 | // }, 32 | // postAuthenticate: (socket, data) => { 33 | // console.log('postauth', { data, }); 34 | // const username = data.username; 35 | 36 | // db.findUser('User', {username:username}, function(err, user) { 37 | // socket.client.user = user; 38 | // }); 39 | // }, 40 | // disconnect: (socket) => { 41 | // console.log(socket.id + ' disconnected'); 42 | // }, 43 | // timeout:1000, 44 | // }); 45 | // AuthRoutes.register('test:path', function(req, res, next){ 46 | // console.log('request:', req.query, req.socket); 47 | // res.send({ 48 | // query: req.query, 49 | // }); 50 | // next(); 51 | // }); 52 | 53 | module.exports = {}; -------------------------------------------------------------------------------- /lib/crud/__EXT_CONTAINER_STRUCTURE/routers/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const periodic = require('periodicjs'); 4 | const extensionRouter = periodic.express.Router(); 5 | const fs = require('fs-extra'); 6 | const path = require('path'); 7 | const packageJson = fs.readJsonSync(path.join(__dirname, '../package.json')); 8 | const preTransforms = periodic.utilities.middleware.preTransforms(periodic); 9 | 10 | extensionRouter.all(packageJson.name, preTransforms, (req, res) => { 11 | res.send(`EXTENSION ${packageJson.name}`); 12 | }); 13 | 14 | module.exports = extensionRouter; -------------------------------------------------------------------------------- /lib/crud/__EXT_CONTAINER_STRUCTURE/transforms/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const periodic = require('periodicjs'); 3 | function testPreTransform(req) { 4 | return new Promise((resolve, reject) => { 5 | periodic.logger.silly('sample pre transfrom', req.params.id); 6 | resolve(req); 7 | }); 8 | } 9 | function testPostTransform(req) { 10 | return new Promise((resolve, reject) => { 11 | periodic.logger.silly('sample post transfrom', req.params.id); 12 | resolve(req); 13 | }); 14 | } 15 | 16 | module.exports = { 17 | pre: { 18 | GET: { 19 | '/some/route/path/:id':[testPreTransform] 20 | }, 21 | PUT: { 22 | } 23 | }, 24 | post: { 25 | GET: { 26 | '/another/route/test/:id':[testPostTransform] 27 | }, 28 | PUT: { 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /lib/crud/__EXT_CONTAINER_STRUCTURE/utilities/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = {}; -------------------------------------------------------------------------------- /lib/crud/__EXT_CONTAINER_STRUCTURE/views/.gitkeep: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------------- /lib/crud/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const config = require('./config'); 3 | // const controller = require('./controller'); 4 | // const db = require('./db'); 5 | const ext = require('./ext'); 6 | 7 | module.exports = { 8 | config, 9 | // controller, 10 | // db, 11 | ext, 12 | }; -------------------------------------------------------------------------------- /lib/defaults/demo/certs/2017.testperiodic.ssl_cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEaDCCA1CgAwIBAgIJAP1qzBmNE2/nMA0GCSqGSIb3DQEBBQUAMH8xCzAJBgNV 3 | BAYTAlVTMREwDwYDVQQIEwhOZXcgWW9yazERMA8GA1UEBxMITmV3IFlvcmsxHjAc 4 | BgNVBAoTFVRlc3QgUGVyaW9kaWMgRGV2IExMQzEWMBQGA1UECxMNVGVzdCBQZXJp 5 | b2RpYzESMBAGA1UEAxMJbG9jYWxob3N0MB4XDTE3MDUxNTE5MzU0N1oXDTIwMDIw 6 | OTE5MzU0N1owfzELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYD 7 | VQQHEwhOZXcgWW9yazEeMBwGA1UEChMVVGVzdCBQZXJpb2RpYyBEZXYgTExDMRYw 8 | FAYDVQQLEw1UZXN0IFBlcmlvZGljMRIwEAYDVQQDEwlsb2NhbGhvc3QwggEiMA0G 9 | CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJaMYYuMXLzrv1i00dglLkVWRblsAP 10 | jUiQbr8Lm5roNACW6p/xaKzVaMh66mfPytC1tifNWN1dVuproOXQ6gJetwgJybLu 11 | 5vPR+ozkKHNj3+NGjbXA4c8mJkW/fLiB5Fq3wD724Ky9qShvY/UWkkODMaU6ZVrN 12 | uSBHE8+cNhNzMm8LQbt99dMuE4gaUGgqtC3tFIV0JvAjYMBzGGYNPyRmXjcydxPk 13 | dUJcjvZB0unDVBBMeBLFCWgaORV4N+J7X+lRcwAgGM84kjg+IOlwaGXuLrrSuwXg 14 | AgOai7aGxmv0cfywE1wz1Q2J3aZbDr2YWRIgLLWNnPnpS6Moc8DDYbhTAgMBAAGj 15 | geYwgeMwHQYDVR0OBBYEFC42EMr2pmgxlzEpZtpSJ+P99A5lMIGzBgNVHSMEgasw 16 | gaiAFC42EMr2pmgxlzEpZtpSJ+P99A5loYGEpIGBMH8xCzAJBgNVBAYTAlVTMREw 17 | DwYDVQQIEwhOZXcgWW9yazERMA8GA1UEBxMITmV3IFlvcmsxHjAcBgNVBAoTFVRl 18 | c3QgUGVyaW9kaWMgRGV2IExMQzEWMBQGA1UECxMNVGVzdCBQZXJpb2RpYzESMBAG 19 | A1UEAxMJbG9jYWxob3N0ggkA/WrMGY0Tb+cwDAYDVR0TBAUwAwEB/zANBgkqhkiG 20 | 9w0BAQUFAAOCAQEAAR+2Rhp5QzcwV5rycwF0uYKlq7cTgbC15eGoCcmyMp9Bg4VN 21 | 7lOaOAlzJ8ySM1K7UtL1659ZBUHVz4VLK+XajblAfWwnz6a94ICziagQ1X231OQj 22 | F+i4fVnj4XTIoaFJrFC8HOl+I8sb4s6ckbAbc/VqraryeWZ1ovOx+inBQEUYDqgS 23 | HFvd2lQAt5I3sfdRasLt6KOOJsHBolJDXxLK2LRDIpkfI4AAyn//im8UR2Qg6zD1 24 | ygI0mvmU3ia+eHuqbQBqq2zIiRyQgkm56p2EJnqYxGJ9KYQke4HO5kQXjG/BbuAF 25 | ZegN1YlU3jyYk+Dpg2vm7f6B8ji1TT38Eovmog== 26 | -----END CERTIFICATE----- 27 | -------------------------------------------------------------------------------- /lib/defaults/demo/certs/2017.testperiodic.ssl_key.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/repetere/periodicjs/fc31f56c348a831dc407d95785195c12a589b44a/lib/defaults/demo/certs/2017.testperiodic.ssl_key.p12 -------------------------------------------------------------------------------- /lib/defaults/demo/certs/2017.testperiodic.ssl_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpAIBAAKCAQEAyWjGGLjFy8679YtNHYJS5FVkW5bAD41IkG6/C5ua6DQAluqf 3 | 8Wis1WjIeupnz8rQtbYnzVjdXVbqa6Dl0OoCXrcICcmy7ubz0fqM5ChzY9/jRo21 4 | wOHPJiZFv3y4geRat8A+9uCsvakob2P1FpJDgzGlOmVazbkgRxPPnDYTczJvC0G7 5 | ffXTLhOIGlBoKrQt7RSFdCbwI2DAcxhmDT8kZl43MncT5HVCXI72QdLpw1QQTHgS 6 | xQloGjkVeDfie1/pUXMAIBjPOJI4PiDpcGhl7i660rsF4AIDmou2hsZr9HH8sBNc 7 | M9UNid2mWw69mFkSICy1jZz56UujKHPAw2G4UwIDAQABAoIBAAScHUybjgtoI+0u 8 | zwkJ3pPTUIS4IpU4ipyjrEO7wAPojMrne9mup6YKy+vkSZP79GL0VFzi1843Gw5z 9 | lE7/zCYW0lxG/Y1yQ8pejbL7KgjzKuSGgc50XKVm4tnLJP30GA90mvxTkCCXKpHC 10 | G+30Uw9Bp6J6h2WGAzMdRPcyVaehSXI/06G3Sx+X9EXFC6Rmg+MyqXA739VaMmyE 11 | wvYe5maMUV/5E6d6RWMEwh9UPaVVUtEHDJ1XLRIktjRUmYBFzJ5STn064r46jVA1 12 | uGC0z0LiZbzP8xaj3nFnulhPFMmC44ybfcRUfA0+GMv8cphK6jflhIUl3/Zfr6dT 13 | yCA+z8ECgYEA98XWPSB0/gFwckC7QGv1keVdnn+IOrX1XQN2qCbrXzGSIYSKcpG4 14 | KQ6F95FwzW66xbI3CTENjDZv6fGIsieSs2QHDmSiVIOQ6h0L82FO6ECrrK9Z/jrr 15 | EpD7YQcDEU5YAjZfeERjjrRuDbtDBNHs2PEi1/PgUur/vdR+n0wFTekCgYEA0BjU 16 | TaH0D2QXKVphttu7JaLtaCsCXdY0IW/FVEbyviHmuMl+yNLAXVn1ALjaxrp99Yz3 17 | B3aqNcbPQTGOG7LPygukd50w2hcWi8fRRuHXRx3ebSnq8gpNXrqvx3+FC1u/ALST 18 | ZlrroKwb9noJZ2lSiUIywSgBaYLLNV5LPXNyQtsCgYEAsQhwHNjV/q80ks3hfRQm 19 | MAo8LAVfZuOf3secvmSghDG9Aanb6iRn+x3fZpZKjN3zIVJGtJCR537106e6TeCs 20 | lvR/fi81NUGUB1KduVXrtVKP1yCrIlUipO9mTVtfO7xIcbw71oi2wb31bGZCam07 21 | 133jsX0U6OnztMThfBwrJhECgYEAvHH/r929ekKVhulGG6WYMFj+zJpGJlvYEX96 22 | HvuwzuU8XpJ5sbrIYMEZ0XGVDOnNLxRcj/Gx6ckD3nHV0td2u+0XHwrGNnk5/ZMR 23 | vTK/FLPDvO98x3r03ZgJnouoG8UVjrn30XT8dB/noqiY44DJMWs1Mx3bSYUcKFQf 24 | pqJpEokCgYA5qLgWxR6XFudbpm0GsD3ZwkKkdHbq2nlomnZ02fKPVf1jmSyoyI3K 25 | ca74D3BUEapyxzzgLs7uQNrA+16WABpeaqssvbKKuBuwXlFoHo6UNgyAMwG0eGfy 26 | I21nAh5VB0fKWhv7GbOznTvrcdrvRXrqIoEHs9M7YtMwTDh1XcFJ2Q== 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /lib/defaults/demo/certs/2017.testperiodic.ssl_key.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/repetere/periodicjs/fc31f56c348a831dc407d95785195c12a589b44a/lib/defaults/demo/certs/2017.testperiodic.ssl_key.pfx -------------------------------------------------------------------------------- /lib/defaults/demo/configs/testconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "filepath":"content/config/appconfig/myconfig.json", 3 | "environment":"test", 4 | "config":{ 5 | "some":"data", 6 | "test":true 7 | } 8 | } -------------------------------------------------------------------------------- /lib/defaults/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const environment = require('./environment')(); 3 | 4 | module.exports = { 5 | environment 6 | }; -------------------------------------------------------------------------------- /lib/defaults/schema/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const lowkie = require('./lowkie.schema.js'); 3 | const mongoose = require('./mongoose.schema.js'); 4 | const sequelize = require('./sequelize.schema.js'); 5 | 6 | 7 | module.exports = { 8 | lowkie, 9 | mongoose, 10 | sequelize, 11 | coreDataOptions: { 12 | configuration: { 13 | docid: ['_id','filepath',], 14 | sort: { filepath: -1, createdat: -1, }, 15 | search: ['filepath', ], 16 | // population: 'assets primaryasset coverimages coverimage userroles tags categories' 17 | }, 18 | extension: { 19 | docid: ['_id','name',], 20 | sort: { periodic_type: 1, periodic_priority: 1, createdat: -1, }, 21 | search: [ 'name', ], 22 | // population: 'assets primaryasset coverimages coverimage userroles tags categories' 23 | }, 24 | }, 25 | }; -------------------------------------------------------------------------------- /lib/defaults/schema/lowkie.schema.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const lowkie = require('lowkie'); 3 | const Schema = lowkie.Schema; 4 | const ObjectId = Schema.ObjectId; 5 | 6 | module.exports = (modelName) => { 7 | return { 8 | entitytype: { 9 | type: String, 10 | default: modelName, 11 | }, 12 | _attributes: Schema.Types.Mixed, 13 | entity_attributes: Schema.Types.Mixed, 14 | contenttypeattributes: Schema.Types.Mixed, 15 | extensionattributes: Schema.Types.Mixed, 16 | random: Number, 17 | createdat: { 18 | type: Date, 19 | 'default': Date.now, 20 | }, 21 | updatedat: { 22 | type: Date, 23 | 'default': Date.now, 24 | }, 25 | }; 26 | }; -------------------------------------------------------------------------------- /lib/defaults/schema/mongoose.schema.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const mongoose = require('mongoose'); 3 | const Schema = mongoose.Schema; 4 | const ObjectId = Schema.ObjectId; 5 | 6 | module.exports = (modelName) => { 7 | return { 8 | id: ObjectId, 9 | entitytype: { 10 | type: String, 11 | default: modelName, 12 | }, 13 | _attributes: Schema.Types.Mixed, 14 | entity_attributes: Schema.Types.Mixed, 15 | contenttypeattributes: Schema.Types.Mixed, 16 | extensionattributes: Schema.Types.Mixed, 17 | random: { 18 | type: Number, 19 | sparse: true, 20 | }, 21 | createdat: { 22 | type: Date, 23 | 'default': Date.now, 24 | index: true, 25 | }, 26 | updatedat: { 27 | type: Date, 28 | 'default': Date.now, 29 | index: true, 30 | }, 31 | }; 32 | }; 33 | -------------------------------------------------------------------------------- /lib/defaults/schema/sequelize.schema.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const Sequelize = require('sequelize'); 3 | 4 | module.exports = (modelName) => { 5 | return { 6 | _id: { 7 | type: Sequelize.INTEGER, 8 | // type: Sequelize.UUID, 9 | primaryKey: true, 10 | autoIncrement: true, 11 | }, 12 | entitytype: { 13 | type: Sequelize.STRING, 14 | default: modelName, 15 | }, 16 | _attributes: { 17 | type: Sequelize.TEXT, 18 | field:'_attributes', 19 | // allowNull: false, 20 | get() { 21 | return this.getDataValue('_attributes')? JSON.parse(this.getDataValue('_attributes')):{}; 22 | }, 23 | set(val) { 24 | this.setDataValue('_attributes', JSON.stringify(val, null, 2)); 25 | }, 26 | }, 27 | entity_attributes: { 28 | type: Sequelize.TEXT, 29 | // allowNull: false, 30 | get() { 31 | return this.getDataValue('entity_attributes')? JSON.parse(this.getDataValue('entity_attributes')):{}; 32 | }, 33 | set(val) { 34 | this.setDataValue('entity_attributes', JSON.stringify(val, null, 2)); 35 | }, 36 | }, 37 | contenttypeattributes: { 38 | type: Sequelize.TEXT, 39 | // allowNull: false, 40 | get() { 41 | return this.getDataValue('contenttypeattributes')? JSON.parse(this.getDataValue('contenttypeattributes')):{}; 42 | }, 43 | set(val) { 44 | this.setDataValue('contenttypeattributes', JSON.stringify(val, null, 2)); 45 | }, 46 | }, 47 | extensionattributes: { 48 | type: Sequelize.TEXT, 49 | // allowNull: false, 50 | get() { 51 | return this.getDataValue('extensionattributes')? JSON.parse(this.getDataValue('extensionattributes')):{}; 52 | }, 53 | set(val) { 54 | this.setDataValue('extensionattributes', JSON.stringify(val, null, 2)); 55 | }, 56 | }, 57 | random: Sequelize.FLOAT, 58 | createdat: { 59 | type: Sequelize.DATE, 60 | defaultValue: Sequelize.NOW, 61 | }, 62 | updatedat: { 63 | type: Sequelize.DATE, 64 | defaultValue: Sequelize.NOW, 65 | }, 66 | }; 67 | }; -------------------------------------------------------------------------------- /lib/extension/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const install = require('./install'); 3 | const setup = require('./setup'); 4 | const uninstall = require('./uninstall'); 5 | 6 | module.exports = { 7 | install, 8 | setup, 9 | uninstall, 10 | }; -------------------------------------------------------------------------------- /lib/extension/install.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function installExtension(arg) { 4 | return new Promise((resolve, reject) => { 5 | try { 6 | if (arg === 'throw') throw new Error('Throw an error'); 7 | // console.log('installing extension'); 8 | resolve(true); 9 | } catch (e) { 10 | reject(e); 11 | } 12 | }); 13 | } 14 | 15 | module.exports = { 16 | installExtension, 17 | }; -------------------------------------------------------------------------------- /lib/extension/uninstall.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function uninstallExtension(arg) { 4 | return new Promise((resolve, reject) => { 5 | try { 6 | if (arg === 'throw') throw new Error('Throw an error'); 7 | // console.log('installing extension'); 8 | resolve(true); 9 | } catch (e) { 10 | reject(e); 11 | } 12 | }); 13 | } 14 | 15 | module.exports = { 16 | uninstallExtension, 17 | }; -------------------------------------------------------------------------------- /lib/init/consoleTimer.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const Promisie = require('promisie'); 3 | const path = require('path'); 4 | const fs = Promisie.promisifyAll(require('fs-extra')); 5 | const __STRUCTURE_DIR = path.resolve(__dirname, '../../__STRUCTURE'); 6 | 7 | /** 8 | * Starts intialization console timer 9 | * 10 | * @returns Promise 11 | */ 12 | function startTimer() { 13 | return new Promise((resolve, reject) => { 14 | try { 15 | this.config.time_start = new Date().valueOf(); 16 | resolve(true); 17 | } catch (e) { 18 | reject(e); 19 | } 20 | }); 21 | } 22 | 23 | /** 24 | * Ends initialization console timer 25 | * 26 | * @returns Promise 27 | */ 28 | function endTimer() { 29 | return new Promise((resolve, reject) => { 30 | try { 31 | this.config.time_end = new Date().valueOf(); 32 | this.logger.verbose(`Initialized Periodic in ${((this.config.time_end-this.config.time_start) / 1000).toFixed(2)} seconds`) 33 | resolve(true); 34 | } catch (e) { 35 | reject(e); 36 | } 37 | }); 38 | } 39 | 40 | /** 41 | * exports console timing functions 42 | */ 43 | module.exports = { 44 | startTimer, 45 | endTimer, 46 | }; -------------------------------------------------------------------------------- /lib/init/folderStructure.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const path = require('path'); 3 | const fs = require('fs-extra'); 4 | const __STRUCTURE_DIR = path.resolve(__dirname, '../../__STRUCTURE'); 5 | const clusterModule = require('cluster'); 6 | 7 | /** 8 | * this will setup a periodic application folder structure if one doesnt exist, it will not overwrite existing configs 9 | * 10 | * @returns Promise setUpFolderStructure will copy folders from the application __STRUCTURE directory to initialize the application 11 | */ 12 | function setUpFolderStructure() { 13 | const cluster = this.cluster || clusterModule; 14 | return new Promise((resolve, reject) => { 15 | try { 16 | if (process.env.npm_config_skip_cli_reconfig || this.config.skip_reconfig) { 17 | return resolve(true); 18 | } else if (cluster.isMaster===false) { 19 | return resolve(true); 20 | } else { 21 | fs.copy(__STRUCTURE_DIR, this.config.app_root, { 22 | overwrite: false, 23 | clobber: false, 24 | preserveTimestamps: true, 25 | }) 26 | .then(() => { //check to make sure there arent two config files (both a json and a js file, if there are both, use the json file) 27 | return Promise.all([ 28 | fs.copy(path.join(__STRUCTURE_DIR, 'public'), path.join(this.config.app_root, 'public'), { 29 | overwrite: true, 30 | clobber: true, 31 | preserveTimestamps: true, 32 | filter: (src, dest) => { 33 | return src.indexOf('favicon') === -1; 34 | }, 35 | }), 36 | fs.copy(path.join(__STRUCTURE_DIR, 'app'), path.join(this.config.app_root, 'app'), { 37 | overwrite: true, 38 | clobber: true, 39 | preserveTimestamps: true, 40 | }), 41 | ]); 42 | }) 43 | .then(() => { //check to make sure there arent two config files (both a json and a js file, if there are both, use the json file) 44 | return fs.readdir(path.join(this.config.app_root, 'content/config')); 45 | }) 46 | .then(configFiles => { 47 | if (configFiles.indexOf('config.json') !== -1 && configFiles.indexOf('config.js') !== -1) { 48 | resolve(fs.remove(path.join(this.config.app_root, 'content/config/config.js'))); 49 | } else { 50 | resolve(true); 51 | } 52 | }) 53 | .catch(reject); 54 | } 55 | } catch (e) { 56 | reject(e); 57 | } 58 | }); 59 | } 60 | module.exports = setUpFolderStructure; -------------------------------------------------------------------------------- /lib/init/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const setUpFolderStructure = require('./folderStructure'); 3 | const timer = require('./consoleTimer'); 4 | const config = require('./config'); 5 | const runtime = require('./runtime'); 6 | const logger = require('./logger'); 7 | const express = require('./express'); 8 | const server = require('./server'); 9 | const cluster = require('./cluster'); 10 | const cli = require('./cli'); 11 | 12 | module.exports = { 13 | setUpFolderStructure, 14 | timer, 15 | config, 16 | runtime, 17 | logger, 18 | express, 19 | server, 20 | cluster, 21 | cli, 22 | }; -------------------------------------------------------------------------------- /lib/init/logger.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const winston = require('winston'); 3 | const path = require('path'); 4 | 5 | function getDefaultWinstonLoggerConfig(options) { 6 | try { 7 | const { periodic, fileNamePathAddition, } = options; 8 | return (periodic.environment === 'production') ? { 9 | transports: [ 10 | new(winston.transports.Console)({ 11 | level: 'error', 12 | colorize: true, 13 | }), 14 | new(winston.transports.File)({ 15 | filename: path.join(periodic.config.app_root, 'logs', fileNamePathAddition + '.exception-errors.log'), 16 | }), 17 | ], 18 | exitOnError: this.settings.logger.winston_exit_on_error, 19 | handleExceptions: true, 20 | } : { 21 | transports: [ 22 | new(winston.transports.Console)({ 23 | colorize: true, 24 | level: 'silly', 25 | prettyPrint: true, 26 | timestamp: true, 27 | }), 28 | new(winston.transports.File)({ 29 | filename: path.join(periodic.config.app_root, 'logs', fileNamePathAddition + '.app.log'), 30 | }), 31 | ], 32 | exitOnError: this.settings.logger.winston_exit_on_error, 33 | exceptionHandlers: [ 34 | new(winston.transports.Console)({ 35 | colorize: true, 36 | json: true, 37 | prettyPrint: true, 38 | timestamp: true, 39 | }), 40 | new(winston.transports.File)({ 41 | filename: path.join(periodic.config.app_root, 'logs', fileNamePathAddition + '.exception-errors.log'), 42 | }), 43 | ], 44 | handleExceptions: true, 45 | }; 46 | } catch (e) { 47 | this.logger.error(e); 48 | return {}; 49 | } 50 | } 51 | 52 | /** 53 | * configures winston 54 | * 55 | * @returns {Promise} configureLogger sets up winston 56 | */ 57 | function configureLogger() { 58 | return new Promise((resolve, reject) => { 59 | try { 60 | const d = new Date(); 61 | const fileNamePathAddition = this.environment + '-' + d.getUTCFullYear() + '.' + (d.getUTCMonth() + 1) + '.' + d.getUTCDate(); 62 | if (this.settings.logger.use_winston_logger && this.environment !== 'DISABLELOG') { 63 | const winstonLogger = new(winston.Logger)(); 64 | winstonLogger.exitOnError = this.settings.logger.winston_exit_on_error; 65 | if (this.settings.logger.use_standard_logging) { 66 | winstonLogger.configure(getDefaultWinstonLoggerConfig.call(this, { 67 | fileNamePathAddition, 68 | periodic: this, 69 | })); 70 | } 71 | this.logger = winstonLogger; 72 | } 73 | resolve(true); 74 | } catch (e) { 75 | reject(e); 76 | } 77 | }); 78 | } 79 | 80 | function catchProcessErrors(options) { 81 | const catchProcess = options.process || process; 82 | return new Promise((resolve, reject) => { 83 | try { 84 | if (!this.logger) this.logger = console; 85 | catchProcess.on('uncaughtException', this.logger.error.bind(this.logger)); 86 | catchProcess.on('warning', this.logger.warn.bind(this.logger)); 87 | catchProcess.on('unhandledRejection', this.logger.error.bind(this.logger)); 88 | resolve(this.config); 89 | } catch (e) { 90 | reject(e); 91 | } 92 | }); 93 | } 94 | 95 | module.exports = { 96 | configureLogger, 97 | catchProcessErrors, 98 | getDefaultWinstonLoggerConfig, 99 | }; -------------------------------------------------------------------------------- /lib/periodic.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const periodicClass = require('./periodicClass'); 3 | 4 | exports.Periodic = periodicClass; 5 | module.exports = new periodicClass({}); -------------------------------------------------------------------------------- /lib/periodicProxyHandler.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @function handler 5 | * @description this is the proxy handler for periodic, provides access to native expess methods as well. 6 | * 7 | * @returns {object} 8 | */ 9 | function proxyHandler() { 10 | //bound this; 11 | return { 12 | get: function (target, name) { 13 | if (name === 'configuration') { 14 | return target.datas.get('configuration'); 15 | } else if (name === 'db') { 16 | return target.dbs.get('standard'); 17 | } else if (name === 'environment') { 18 | return target.config.process.runtime; 19 | } else if (name === 'container') { 20 | return target.settings.container; 21 | } else if (name === 'theme') { 22 | return target.settings.container.name; 23 | } else if (name === '_settings_container') { 24 | const containerName = target.settings.container.name; 25 | return target.settings.container[containerName]; 26 | } else if (name && typeof name ==='string' && name.includes('_settings_extension')) { 27 | const extensionName = name.replace('_settings_extensions_', ''); 28 | return target.settings.extensions[extensionName]; 29 | } else if (name && typeof name ==='string' && name.includes('_utilities_')) { //_utilities_extensions_periodicjs.ext.dblogger 30 | const [ spacer, utilities, type, ] = name.split('_'); 31 | const property = name.replace(`_utilities_${type}_`, ''); 32 | return target.locals[type].get(property); 33 | } else if (name && typeof name ==='string' && name.includes('_controllers_')) { //_controllers_extensions_periodicjs.ext.dblogger 34 | const [ spacer, controller, type, ] = name.split('_'); 35 | const contollerProp = (type === 'extensions') 36 | ? 'extension' 37 | : (type === 'containers') 38 | ? 'container' 39 | : type; 40 | const property = name.replace(`_controllers_${type}_`, ''); 41 | return target.controllers[contollerProp].get(property); 42 | } else { 43 | return target[name]; 44 | } 45 | }, 46 | }; 47 | } 48 | 49 | module.exports = proxyHandler; -------------------------------------------------------------------------------- /lib/schemas/config.lowkie.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const lowkie = require('lowkie'); 3 | const configSchema = lowkie.Schema({ 4 | filepath: String, 5 | environment: String, 6 | container: { 7 | type: String, 8 | default: 'periodicjs.container.default', 9 | }, 10 | config: lowkie.Schema.Types.Mixed, 11 | createdat: { 12 | type: Date, 13 | 'default': Date.now, 14 | // index: true, 15 | }, 16 | updatedat: { 17 | type: Date, 18 | 'default': Date.now 19 | }, 20 | }); 21 | /** 22 | * name_of_file: string (e.g. 'content/config/extensions.json','content/config/environment/development.json','content/config/extensions/peridicjs.ext.dbseed.json') 23 | application_environment: string 24 | settings: schema_type_mixed 25 | */ 26 | 27 | module.exports = configSchema; -------------------------------------------------------------------------------- /lib/schemas/config.mongoose.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const mongoose = require('mongoose'); 3 | const Schema = mongoose.Schema; 4 | const ObjectId = Schema.ObjectId; 5 | const configSchema = new Schema({ 6 | id: ObjectId, 7 | filepath: String, 8 | environment: String, 9 | container: { 10 | type: String, 11 | default: 'periodicjs.container.default', 12 | }, 13 | config: Schema.Types.Mixed, 14 | createdat: { 15 | type: Date, 16 | 'default': Date.now, 17 | // index: true, 18 | }, 19 | updatedat: { 20 | type: Date, 21 | 'default': Date.now 22 | }, 23 | }); 24 | /** 25 | * name_of_file: string (e.g. 'content/config/extensions.json','content/config/environment/development.json','content/config/extensions/peridicjs.ext.dbseed.json') 26 | application_environment: string 27 | settings: schema_type_mixed 28 | */ 29 | 30 | module.exports = configSchema; -------------------------------------------------------------------------------- /lib/schemas/config.sequelize.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const Sequelize = require('sequelize'); 3 | 4 | const scheme = { 5 | _id: { 6 | type: Sequelize.INTEGER, 7 | // type: Sequelize.UUID, 8 | primaryKey: true, 9 | autoIncrement: true, 10 | }, 11 | filepath: { 12 | type: Sequelize.STRING, 13 | }, 14 | environment: { 15 | type: Sequelize.STRING, 16 | }, 17 | container: { 18 | type: Sequelize.STRING, 19 | defaultValue: 'periodicjs.container.default', 20 | }, 21 | config: Sequelize.TEXT, 22 | createdat: { 23 | type: Sequelize.DATE, 24 | defaultValue: Sequelize.NOW, 25 | }, 26 | updatedat: { 27 | type: Sequelize.DATE, 28 | defaultValue: Sequelize.NOW, 29 | }, 30 | }; 31 | const options = { 32 | underscored: true, 33 | timestamps: true, 34 | indexes: [{ 35 | fields: ['createdat',], 36 | },], 37 | getterMethods: { 38 | config: function() { 39 | // // console.log('getterTHIS', this); 40 | // console.log('this.dataValues.config', this.dataValues.config); 41 | // // console.log('this.config', this.config); 42 | // // console.log('this.config.toString()', this.config.toString()); 43 | // console.log('this.filepath', this.filepath); 44 | return JSON.parse(this.dataValues.config); 45 | }, 46 | }, 47 | setterMethods: { 48 | config: function(value) { 49 | this.setDataValue('config', JSON.stringify(value, null, 2)); 50 | }, 51 | }, 52 | }; 53 | 54 | module.exports = { 55 | scheme, 56 | options, 57 | }; -------------------------------------------------------------------------------- /lib/schemas/extension.lowkie.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const lowkie = require('lowkie'); 3 | const Schema = lowkie.Schema; 4 | const extensionSchema = lowkie.Schema({ 5 | name: String, 6 | require: String, 7 | source: String, 8 | version: String, 9 | enabled: Boolean, 10 | periodic_type: Number, //0-core, 1-communication, 2-auth, 3-uac, 4-api, 5-admin,6-data,7-ui 11 | periodic_priority: Number, 12 | periodic_compatibility: String, 13 | periodic_config: Schema.Types.Mixed, 14 | periodic_dependencies: Schema.Types.Mixed, 15 | author: Schema.Types.Mixed, 16 | contributors: Schema.Types.Mixed, 17 | description: String, 18 | createdat: { 19 | type: Date, 20 | 'default': Date.now, 21 | }, 22 | updatedat: { 23 | type: Date, 24 | 'default': Date.now, 25 | }, 26 | }); 27 | 28 | module.exports = extensionSchema; 29 | 30 | /** 31 | * 32 | * { 33 | "name": "periodicjs.ext.oauth2server", 34 | "version": "3.1.0", 35 | "periodicCompatibility": "9.0.0", 36 | "installed": true, 37 | "enabled": true, 38 | "date": "2017-05-05T01:37:24.140Z", 39 | "periodicConfig": { 40 | "periodicCompatibility": "9.0.0", 41 | "periodicDependencies": [ 42 | { 43 | "extname": "periodicjs.ext.login", 44 | "version": "~7.0.3" 45 | } 46 | ], 47 | "periodicjs.ext.reactadmin": { 48 | "manifests": [ 49 | "node_modules/periodicjs.ext.oauth2server/views/reactadmin/manifests" 50 | ], 51 | "unauthenticated_manifests": [ 52 | "node_modules/periodicjs.ext.oauth2server/views/reactadmin/unauthenticated_manifests" 53 | ], 54 | "navigation": "node_modules/periodicjs.ext.oauth2server/views/reactadmin/components/navigation.manifest.js" 55 | } 56 | } 57 | }, 58 | * 59 | */ -------------------------------------------------------------------------------- /lib/schemas/extension.mongoose.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const mongoose = require('mongoose'); 3 | const Schema = mongoose.Schema; 4 | const ObjectId = Schema.ObjectId; 5 | const extensionSchema = new Schema({ 6 | id: ObjectId, 7 | name: { 8 | type: String, 9 | unique: true, 10 | }, 11 | require: String, 12 | source: String, 13 | version: String, 14 | enabled: Boolean, 15 | periodic_type: Number, //0-core, 1-communication, 2-auth, 3-uac, 4-api, 5-admin,6-data,7-ui 16 | periodic_priority: Number, 17 | periodic_compatibility: String, 18 | periodic_config: Schema.Types.Mixed, 19 | periodic_dependencies: Schema.Types.Mixed, 20 | author: Schema.Types.Mixed, 21 | contributors: Schema.Types.Mixed, 22 | description: String, 23 | createdat: { 24 | type: Date, 25 | 'default': Date.now, 26 | // index: true, 27 | }, 28 | updatedat: { 29 | type: Date, 30 | 'default': Date.now, 31 | }, 32 | }); 33 | 34 | module.exports = extensionSchema; 35 | /** 36 | * 37 | * { 38 | "name": "periodicjs.ext.oauth2server", 39 | "version": "3.1.0", 40 | "periodicCompatibility": "9.0.0", 41 | "installed": true, 42 | "enabled": true, 43 | "date": "2017-05-05T01:37:24.140Z", 44 | "periodicConfig": { 45 | "periodicCompatibility": "9.0.0", 46 | "periodicDependencies": [ 47 | { 48 | "extname": "periodicjs.ext.login", 49 | "version": "~7.0.3" 50 | } 51 | ], 52 | "periodicjs.ext.reactadmin": { 53 | "manifests": [ 54 | "node_modules/periodicjs.ext.oauth2server/views/reactadmin/manifests" 55 | ], 56 | "unauthenticated_manifests": [ 57 | "node_modules/periodicjs.ext.oauth2server/views/reactadmin/unauthenticated_manifests" 58 | ], 59 | "navigation": "node_modules/periodicjs.ext.oauth2server/views/reactadmin/components/navigation.manifest.js" 60 | } 61 | } 62 | }, 63 | * 64 | */ -------------------------------------------------------------------------------- /lib/schemas/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const lowkieConfigSchema = require('./config.lowkie'); 3 | const mongooseConfigSchema = require('./config.mongoose'); 4 | const sequelizeConfigSchema = require('./config.sequelize'); 5 | const lowkieExtensionSchema = require('./extension.lowkie'); 6 | const mongooseExtensionSchema = require('./extension.mongoose'); 7 | const sequelizeExtensionSchema = require('./extension.sequelize'); 8 | const schemas = { 9 | config: { 10 | lowkie: lowkieConfigSchema, 11 | mongoose: mongooseConfigSchema, 12 | sequelize: sequelizeConfigSchema, 13 | }, 14 | extension: { 15 | lowkie: lowkieExtensionSchema, 16 | mongoose: mongooseExtensionSchema, 17 | sequelize: sequelizeExtensionSchema, 18 | } 19 | }; 20 | 21 | module.exports = schemas; -------------------------------------------------------------------------------- /lib/utilities/auth.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | let bcrypt; 3 | try { 4 | bcrypt = require('bcrypt'); 5 | } catch (e) { 6 | bcrypt = require('bcrypt-nodejs'); 7 | console.error('Native bcrypt support disabled', e); 8 | } 9 | 10 | function comparePassword(options) { 11 | const { candidatePassword, userPassword, } = options; 12 | return new Promise((resolve, reject) => { 13 | if (!userPassword) return reject(new Error(`Invalid Password (${userPassword})`)); 14 | try { 15 | bcrypt.compare(userPassword, candidatePassword, (err, isMatch) => { 16 | if (err) { 17 | return reject(err); 18 | } else { 19 | return resolve(isMatch); 20 | } 21 | }); 22 | } catch (e) { 23 | return reject(e); 24 | } 25 | }); 26 | } 27 | 28 | function hasPrivilege(options) { 29 | const { user, privilege, } = options; 30 | // console.log(' hasPrivilege user, privilege',user,privilege); 31 | return user.accounttype === 'admin' || user.privileges[privilege]; 32 | } 33 | 34 | function generateRandomToken() { 35 | // var user = this, 36 | var chars = '_!abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890', 37 | token = new Date().getTime() + '_'; 38 | for (var x = 0; x < 16; x++) { 39 | var i = Math.floor(Math.random() * 62); 40 | token += chars.charAt(i); 41 | } 42 | return token; 43 | } 44 | 45 | function encryptPassword(options) { 46 | const { password, saltLength = 10, } = options; 47 | return new Promise((resolve, reject) => { 48 | try { 49 | bcrypt.genSalt(saltLength, (err, salt) => { 50 | if (err) { 51 | return reject(err); 52 | } else { 53 | bcrypt.hash(password, salt, (err, hash) => { 54 | if (err) { 55 | return reject(err); 56 | } else { 57 | return resolve(hash); 58 | } 59 | }); 60 | } 61 | }); 62 | } catch (e) { 63 | reject(e); 64 | } 65 | }); 66 | } 67 | 68 | module.exports = { 69 | encryptPassword, 70 | comparePassword, 71 | hasPrivilege, 72 | generateRandomToken, 73 | }; -------------------------------------------------------------------------------- /lib/utilities/fetchUtils.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const semver = require('semver'); 3 | 4 | function generateErrorResponse(error) { 5 | return { 6 | status: 'error', 7 | data: { error, }, 8 | }; 9 | } 10 | 11 | function isVersionUpToDate(inputVersion, latestVersion) { 12 | return semver.gte(inputVersion, latestVersion); 13 | } 14 | 15 | function checkStatus(response) { 16 | return new Promise((resolve, reject) => { 17 | if (response.status >= 200 && response.status < 300) { 18 | resolve(response); 19 | } else { 20 | let error = new Error(response.statusText); 21 | error.response = response; 22 | try{ 23 | // console.debug({response}) 24 | response.json() 25 | .then(res => { 26 | reject(generateErrorFromResponse({ res, error })); 27 | }) 28 | .catch(()=>{ 29 | reject(error); 30 | }) 31 | } catch(e){ 32 | reject(error); 33 | } 34 | } 35 | }); 36 | }; 37 | 38 | function generateErrorFromResponse(options) { 39 | const { res, error } = options; 40 | if (res.data) { 41 | if (res.data.error) { 42 | return (res.data.error); 43 | } else{ 44 | return (JSON.stringify(res.data)); 45 | } 46 | } else { 47 | return(error); 48 | } 49 | } 50 | 51 | module.exports = { 52 | isVersionUpToDate, 53 | generateErrorFromResponse, 54 | generateErrorResponse, 55 | checkStatus, 56 | }; -------------------------------------------------------------------------------- /lib/utilities/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const fetchUtils = require('./fetchUtils'); 3 | const mock = require('./mock'); 4 | const auth = require('./auth'); 5 | const routing = require('./routing'); 6 | const middleware = require('./middleware'); 7 | const viewHelper = require('./viewHelper'); 8 | module.exports = { 9 | fetchUtils, 10 | auth, 11 | mock, 12 | routing, 13 | middleware, 14 | viewHelper, 15 | }; -------------------------------------------------------------------------------- /lib/utilities/middleware.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const PathRegExp = require('path-to-regexp'); 3 | const Promisie = require('promisie'); 4 | const ROUTE_MAP = new Map(); 5 | 6 | function preTransforms(periodic) { 7 | return transformRequest.call(periodic, 'pre', periodic.transforms); 8 | } 9 | 10 | function postTransforms(periodic) { 11 | return transformRequest.call(periodic, 'post', periodic.transforms); 12 | } 13 | 14 | const transformRequest = (type, tranforms) => (req, res, next) => { 15 | let transformsObj = tranforms || this.tranforms; 16 | let transformType = (type === 'pre') ? transformsObj.pre : transformsObj.post; 17 | let transformsFilters = (transformType[req.method]) ? 18 | findMatchingRoute(transformType[req.method], (req._parsedOriginalUrl) ? req._parsedOriginalUrl.pathname : req._parsedUrl.pathname) : 19 | false; 20 | if (transformsFilters && transformsFilters.length > 0) { 21 | Promisie.pipe(transformType[req.method][transformsFilters])(req) 22 | .then(newreq => { 23 | if (req.redirectResponse) { 24 | res.redirect(req.redirectResponse); 25 | } else if (req.sendResponse) { 26 | res.send(req.sendResponse); 27 | } else if (req.error) { 28 | res.status(500).send({ 29 | result: 'error', 30 | data: { 31 | error: req.error, 32 | }, 33 | }); 34 | } else if (!req.sentResponse) { 35 | req = newreq; 36 | next(); 37 | } 38 | }) 39 | .catch(next); 40 | } else { 41 | next(); 42 | } 43 | }; 44 | 45 | function getParameterized(route) { 46 | if (ROUTE_MAP.has(route)) return ROUTE_MAP.get(route); 47 | else { 48 | let keys = []; 49 | let result = new PathRegExp(route, keys); 50 | ROUTE_MAP.set(route, { 51 | re: result, 52 | keys, 53 | }); 54 | return { keys, re: result, }; 55 | } 56 | } 57 | 58 | function findMatchingRoute(routes, location) { 59 | let matching; 60 | location = (/\?[^\s]+$/.test(location)) ? location.replace(/^([^\s\?]+)\?[^\s]+$/, '$1') : location; 61 | Object.keys(routes).forEach(key => { 62 | let result = getParameterized(key); 63 | if (result.re.test(location) && !matching) matching = key; 64 | }); 65 | return matching; 66 | } 67 | 68 | function jsonReq(req) { 69 | if (req && req.headers && req.headers.accept) { 70 | return req.headers.accept.indexOf('json') > -1 || req.is('json') || req.query.format === 'json' || /^json$/i.test(req.query.format); 71 | } else if (req && req.headers && req.headers.accepts) { 72 | return req.headers.accepts.indexOf('json') > -1 || req.is('json') || req.query.format === 'json' || /^json$/i.test(req.query.format); 73 | } else { 74 | return req.is('json') || req.query.format === 'json' || /^json$/i.test(req.query.format); 75 | } 76 | } 77 | 78 | module.exports = { 79 | preTransforms, 80 | postTransforms, 81 | transformRequest, 82 | getParameterized, 83 | findMatchingRoute, 84 | jsonReq, 85 | }; -------------------------------------------------------------------------------- /lib/utilities/mock.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function tempPromise(arg) { 4 | return new Promise((resolve, reject) => { 5 | try { 6 | if (arg === 'throw') throw new Error('Throw an error'); 7 | resolve(true); 8 | } catch (e) { 9 | reject(e); 10 | } 11 | }); 12 | } 13 | 14 | module.exports = { 15 | tempPromise, 16 | }; -------------------------------------------------------------------------------- /lib/utilities/routing.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * returns a string that's used in an express router that's always prefixed with a preceding '/' 5 | * 6 | * @param {String} adminPath 7 | * @returns {String} route used for express router, that's always prefixed with a "/" 8 | */ 9 | function _route_prefix(adminPath) { 10 | return (adminPath === '') 11 | ? '/' 12 | : (adminPath && adminPath.charAt(0) === '/') 13 | ? adminPath 14 | : '/' + adminPath; 15 | } 16 | 17 | /** 18 | * returns a route string without the precending '/' 19 | * 20 | * @param {String} adminPath 21 | * @returns {String} 22 | */ 23 | function _admin_prefix(adminPath) { 24 | return _route_prefix(adminPath).substr(1); 25 | } 26 | 27 | /** 28 | * returns a route string that always has a preceding '/' and a suffixed '/', this is typically used for specifiying links to paths as absolute urls 29 | * 30 | * @param {String} adminPath 31 | * @returns {String} 32 | */ 33 | function _manifest_prefix(adminPath) { 34 | var admin_prefix = _admin_prefix(adminPath); 35 | return (admin_prefix.length > 0) 36 | ? '/'+admin_prefix+'/' 37 | : '/'; 38 | } 39 | 40 | /** 41 | * short hand function to return all prefix types 42 | * 43 | * @param {String} adminPath 44 | * @returns {String} 45 | */ 46 | function all_prefixes(adminPath){ 47 | return { 48 | route_prefix : _route_prefix(adminPath), 49 | admin_prefix : _admin_prefix(adminPath), 50 | manifest_prefix : _manifest_prefix(adminPath), 51 | }; 52 | } 53 | 54 | function splitModelNameReducer(result, model_name) { 55 | let split = model_name.split('_'); 56 | let parent = split.shift(); 57 | let child = split.join('_'); 58 | result[parent] = result[parent] || []; 59 | result[parent].push(child); 60 | return result; 61 | } 62 | 63 | function regexModelNameReducer(result, model_name) { 64 | let [parent, child, ] = model_name.replace(/^([^\s_]+)_{1}(.+)$/, '$1 $2').split(' '); 65 | result[parent] = result[parent] || []; 66 | result[parent].push(child); 67 | return result; 68 | } 69 | 70 | 71 | /** 72 | * Enforces the shape of an api response, by allow for three properties (result,status and data) all other properties are on data 73 | * 74 | * @param {string} options.result result of request (usually sucess or error) 75 | * @param {number} options.status http resonse code equivalent 76 | * @param {object} options.data data for response 77 | * @returns {object} with the shape {result,status,data} 78 | */ 79 | function formatResponse(options = {}) { 80 | const formattedOptions = Object.keys(options).reduce((result, key) => { 81 | if (key === 'result') { 82 | result[ key ] = options[ key ].toString(); 83 | } else if (key === 'status') { 84 | result[ key ] = parseInt(options[ key ], 10); 85 | } else if(key==='data'){ 86 | result.data = Object.assign({},result.data,options[ key ]); 87 | } else { 88 | result.data[ key ] = options[ key ]; 89 | } 90 | return result; 91 | }, { data: {}, }); 92 | return Object.assign({}, { 93 | result: 'success', 94 | status: 200, 95 | data:{}, 96 | }, formattedOptions); 97 | } 98 | 99 | module.exports = { 100 | splitModelNameReducer, 101 | regexModelNameReducer, 102 | all_prefixes, 103 | formatResponse, 104 | route_prefix : _route_prefix, 105 | admin_prefix : _admin_prefix, 106 | manifest_prefix : _manifest_prefix, 107 | }; -------------------------------------------------------------------------------- /lib/utilities/viewHelper.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const querystring = require('querystring'); 3 | const path = require('path'); 4 | const numeral = require('numeral'); 5 | const pluralize = require('pluralize'); 6 | const capitalize = require('capitalize'); 7 | const moment = require('moment'); 8 | const util = require('util'); 9 | 10 | module.exports = { 11 | querystring, 12 | numeral, 13 | moment, 14 | pluralize, 15 | capitalize, 16 | path, 17 | inspect: util.inspect, 18 | /** helper function exposes a server javascript object to the client 19 | * @param {object} obj server object for the client 20 | * @param {object} nameOfClientObj name of exposed server object for the client 21 | * @returns {string} javascript statement that contains server javascript object 22 | */ 23 | passObjToClient: function(obj, nameOfClientObj) { 24 | return 'var ' + nameOfClientObj + ' = ' + (JSON.stringify(obj)); 25 | }, 26 | }; -------------------------------------------------------------------------------- /test/mock/config/config_test_config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = (options = {}) => { 4 | return { 5 | "configuration": { 6 | "type": options.config_type||"db", 7 | "db": options.db ||"lowkie", 8 | "options": Object.assign({ 9 | "dbpath": `${options.dbpathprefix ? options.dbpathprefix+'/' :''}content/config/settings/config_db.json`, 10 | },options.db_config_options), 11 | }, 12 | "settings": Object.assign({}, 13 | { 14 | "name": "My Config APP", 15 | }, options.settingsProp), 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /test/mock/config/ext_doc.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const crypto = require('crypto'); 3 | 4 | module.exports = (options = {}) => { 5 | const ext = Object.assign({},{ 6 | "name": "periodicjs.ext.test", 7 | "source": "npm", 8 | "version": "0.4.5", 9 | "enabled": true, 10 | "periodic_type": 5, 11 | "periodic_compatibility": "10.0.0", 12 | "periodic_config": { 13 | "reactadmin": { 14 | "navigation": "node_modules/periodicjs.ext.reactadmin/views/reactadmin/components/navigation.manifest.js", 15 | "manifests": [ 16 | "node_modules/periodicjs.ext.reactadmin/views/reactadmin/manifests", 17 | ], 18 | "unauthenticated_manifests": [ 19 | "node_modules/periodicjs.ext.reactadmin/views/public/home/", 20 | ], 21 | }, 22 | }, 23 | "periodic_dependencies": [ 24 | { 25 | "extname": "periodicjs.ext.mailer", 26 | "version": "~10.0.0", 27 | }, 28 | { 29 | "extname": "periodicjs.ext.login", 30 | "version": "~11.0.0" 31 | }, 32 | { 33 | "extname": "periodicjs.ext.uac", 34 | "version": "~7.0.0" 35 | }, 36 | { 37 | "extname": "periodicjs.ext.oauth2server", 38 | "version": "5.0.0" 39 | } 40 | ], 41 | "author": { 42 | "name": "yaw joseph etse", 43 | "email": "yaw.etse@gmail.com" 44 | }, 45 | "contributors": [ 46 | { "name": "jan" }, 47 | { "name": "iris" } 48 | ], 49 | "description": "admin center", 50 | "createdat": Date.now(), 51 | "updatedat": Date.now(), 52 | "_id": crypto.createHash('md5').update(`${new Date().valueOf}${Math.random()}`).digest('hex'), 53 | },options); 54 | return ext; 55 | } 56 | -------------------------------------------------------------------------------- /test/mock/extensions/periodicjs.ext.admin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "periodicjs.ext.admin", 3 | "version": "0.4.5", 4 | "author": { 5 | "name": "yaw joseph etse", 6 | "email": "yaw.etse@gmail.com" 7 | }, 8 | "description": "admin center", 9 | "contributors": [{ 10 | "name": "jan" 11 | }, 12 | { 13 | "name": "iris" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /test/mock/extensions/periodicjs.ext.admin/periodicjs.ext.json: -------------------------------------------------------------------------------- 1 | { 2 | "periodic_compatibility": "9.0.0", 3 | "periodic_dependencies": [{ 4 | "extname": "periodicjs.ext.mailer", 5 | "version": "~10.0.0" 6 | }, { 7 | "extname": "periodicjs.ext.login", 8 | "version": "~11.0.0" 9 | }, { 10 | "extname": "periodicjs.ext.uac", 11 | "version": "~7.0.0" 12 | }, { 13 | "extname": "periodicjs.ext.oauth2server", 14 | "version": "5.0.0" 15 | }], 16 | "periodic_type": 5, 17 | "periodic_priority": 0, 18 | "periodic_config": { 19 | "reactadmin": { 20 | "navigation": "node_modules/periodicjs.ext.reactadmin/views/reactadmin/components/navigation.manifest.js", 21 | "manifests": [ 22 | "node_modules/periodicjs.ext.reactadmin/views/reactadmin/manifests" 23 | ], 24 | "unauthenticated_manifests": [ 25 | "node_modules/periodicjs.ext.reactadmin/views/public/home/" 26 | ] 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /test/mock/extensions/periodicjs.ext.cloudupload/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "periodicjs.ext.cloudupload", 3 | "version": "8.1.5", 4 | "author": { 5 | "name": "yaw joseph etse", 6 | "email": "yaw.etse@gmail.com" 7 | }, 8 | "description": "cloud based uploads", 9 | "contributors": [{ 10 | "name": "jan" 11 | }, 12 | { 13 | "name": "iris" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /test/mock/extensions/periodicjs.ext.cloudupload/periodicjs.ext.json: -------------------------------------------------------------------------------- 1 | { 2 | "periodic_compatibility": "10.0.0", 3 | "periodic_dependencies": [], 4 | "periodic_type": 0, 5 | "periodic_priority": 0, 6 | "periodic_config": { 7 | "reactadmin": { 8 | "navigation": "node_modules/periodicjs.ext.reactadmin/views/reactadmin/components/navigation.manifest.js", 9 | "manifests": [ 10 | "node_modules/periodicjs.ext.reactadmin/views/reactadmin/manifests" 11 | ], 12 | "unauthenticated_manifests": [ 13 | "node_modules/periodicjs.ext.reactadmin/views/public/home/" 14 | ] 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /test/mock/extensions/periodicjs.ext.db_seed/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "periodicjs.ext.test", 3 | "version": "0.0.1", 4 | "author": { 5 | "name": "yaw joseph etse", 6 | "email": "yaw.etse@gmail.com" 7 | }, 8 | "description": "test extension", 9 | "contributors": [{ 10 | "name": "jan" 11 | }, 12 | { 13 | "name": "iris" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /test/mock/extensions/periodicjs.ext.db_seed/periodicjs.ext.json: -------------------------------------------------------------------------------- 1 | { 2 | "periodic_compatibility": "10.0.0", 3 | "periodic_dependencies": [{ 4 | "extname": "periodicjs.ext.mailer", 5 | "version": "~6.0.0" 6 | }, { 7 | "extname": "periodicjs.ext.login", 8 | "version": "~7.2.0" 9 | }, { 10 | "extname": "periodicjs.ext.user_access_control", 11 | "version": "~7.0.0" 12 | }, { 13 | "extname": "periodicjs.ext.oauth2server", 14 | "version": "2.0.4" 15 | }], 16 | "periodic_type": 0, 17 | "periodic_priority": 0, 18 | "periodic_config": { 19 | "reactadmin": { 20 | "navigation": "node_modules/periodicjs.ext.reactadmin/views/reactadmin/components/navigation.manifest.js", 21 | "manifests": [ 22 | "node_modules/periodicjs.ext.reactadmin/views/reactadmin/manifests" 23 | ], 24 | "unauthenticated_manifests": [ 25 | "node_modules/periodicjs.ext.reactadmin/views/public/home/" 26 | ] 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /test/mock/extensions/periodicjs.ext.login/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "periodicjs.ext.login", 3 | "version": "9.3.1", 4 | "author": { 5 | "name": "yaw joseph etse", 6 | "email": "yaw.etse@gmail.com" 7 | }, 8 | "description": "test extension", 9 | "contributors": [{ 10 | "name": "jan" 11 | }, 12 | { 13 | "name": "iris" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /test/mock/extensions/periodicjs.ext.login/periodicjs.ext.json: -------------------------------------------------------------------------------- 1 | { 2 | "periodic_compatibility": "10.0.0", 3 | "periodic_dependencies": [{ 4 | "extname": "periodicjs.ext.mailer", 5 | "version": "~10.0.0" 6 | }], 7 | "periodic_type": 2, 8 | "periodic_priority": 0, 9 | "periodic_config": { 10 | "reactadmin": { 11 | "navigation": "node_modules/periodicjs.ext.reactadmin/views/reactadmin/components/navigation.manifest.js", 12 | "manifests": [ 13 | "node_modules/periodicjs.ext.reactadmin/views/reactadmin/manifests" 14 | ], 15 | "unauthenticated_manifests": [ 16 | "node_modules/periodicjs.ext.reactadmin/views/public/home/" 17 | ] 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /test/mock/extensions/periodicjs.ext.login_mfa/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "periodicjs.ext.login_mfa", 3 | "version": "6.0.1", 4 | "author": { 5 | "name": "yaw joseph etse", 6 | "email": "yaw.etse@gmail.com" 7 | }, 8 | "description": "test extension", 9 | "contributors": [{ 10 | "name": "jan" 11 | }, 12 | { 13 | "name": "iris" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /test/mock/extensions/periodicjs.ext.login_mfa/periodicjs.ext.json: -------------------------------------------------------------------------------- 1 | { 2 | "periodic_compatibility": "10.0.0", 3 | "periodic_dependencies": [{ 4 | "extname": "periodicjs.ext.mailer", 5 | "version": "~6.0.0" 6 | }, { 7 | "extname": "periodicjs.ext.login", 8 | "version": "~7.2.0" 9 | }], 10 | "periodic_type": 2, 11 | "periodic_priority": 1, 12 | "periodic_config": { 13 | "reactadmin": { 14 | "navigation": "node_modules/periodicjs.ext.reactadmin/views/reactadmin/components/navigation.manifest.js", 15 | "manifests": [ 16 | "node_modules/periodicjs.ext.reactadmin/views/reactadmin/manifests" 17 | ], 18 | "unauthenticated_manifests": [ 19 | "node_modules/periodicjs.ext.reactadmin/views/public/home/" 20 | ] 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /test/mock/extensions/periodicjs.ext.mailer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "periodicjs.ext.mailer", 3 | "version": "9.1.1", 4 | "author": { 5 | "name": "yaw joseph etse", 6 | "email": "yaw.etse@gmail.com" 7 | }, 8 | "description": "node mailer", 9 | "contributors": [{ 10 | "name": "jan" 11 | }, 12 | { 13 | "name": "iris" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /test/mock/extensions/periodicjs.ext.mailer/periodicjs.ext.json: -------------------------------------------------------------------------------- 1 | { 2 | "periodic_compatibility": "10.0.0", 3 | "periodic_dependencies": [], 4 | "periodic_type": 1, 5 | "periodic_priority": 0, 6 | "periodic_config": { 7 | "reactadmin": { 8 | "navigation": "node_modules/periodicjs.ext.reactadmin/views/reactadmin/components/navigation.manifest.js", 9 | "manifests": [ 10 | "node_modules/periodicjs.ext.reactadmin/views/reactadmin/manifests" 11 | ], 12 | "unauthenticated_manifests": [ 13 | "node_modules/periodicjs.ext.reactadmin/views/public/home/" 14 | ] 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /test/mock/extensions/periodicjs.ext.oauth2client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "periodicjs.ext.oauth2client", 3 | "version": "8.0.1", 4 | "author": { 5 | "name": "yaw joseph etse", 6 | "email": "yaw.etse@gmail.com" 7 | }, 8 | "description": "test extension", 9 | "contributors": [{ 10 | "name": "jan" 11 | }, 12 | { 13 | "name": "iris" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /test/mock/extensions/periodicjs.ext.oauth2client/periodicjs.ext.json: -------------------------------------------------------------------------------- 1 | { 2 | "periodic_compatibility": "10.0.0", 3 | "periodic_dependencies": [{ 4 | "extname": "periodicjs.ext.login", 5 | "version": "~7.2.0" 6 | }], 7 | "periodic_type": 4, 8 | "periodic_priority": 1, 9 | "periodic_config": { 10 | "reactadmin": { 11 | "navigation": "node_modules/periodicjs.ext.reactadmin/views/reactadmin/components/navigation.manifest.js", 12 | "manifests": [ 13 | "node_modules/periodicjs.ext.reactadmin/views/reactadmin/manifests" 14 | ], 15 | "unauthenticated_manifests": [ 16 | "node_modules/periodicjs.ext.reactadmin/views/public/home/" 17 | ] 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /test/mock/extensions/periodicjs.ext.oauth2server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "periodicjs.ext.oauth2server", 3 | "version": "8.0.1", 4 | "author": { 5 | "name": "yaw joseph etse", 6 | "email": "yaw.etse@gmail.com" 7 | }, 8 | "description": "test extension", 9 | "contributors": [{ 10 | "name": "jan" 11 | }, 12 | { 13 | "name": "iris" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /test/mock/extensions/periodicjs.ext.oauth2server/periodicjs.ext.json: -------------------------------------------------------------------------------- 1 | { 2 | "periodic_compatibility": "10.0.0", 3 | "periodic_dependencies": [{ 4 | "extname": "periodicjs.ext.login", 5 | "version": "~7.2.0" 6 | }, { 7 | "extname": "periodicjs.ext.user_access_control", 8 | "version": "~7.0.0" 9 | }, { 10 | "extname": "periodicjs.ext.oauth2server", 11 | "version": "2.0.4" 12 | }], 13 | "periodic_type": 0, 14 | "periodic_priority": 0, 15 | "periodic_config": { 16 | "reactadmin": { 17 | "navigation": "node_modules/periodicjs.ext.reactadmin/views/reactadmin/components/navigation.manifest.js", 18 | "manifests": [ 19 | "node_modules/periodicjs.ext.reactadmin/views/reactadmin/manifests" 20 | ], 21 | "unauthenticated_manifests": [ 22 | "node_modules/periodicjs.ext.reactadmin/views/public/home/" 23 | ] 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /test/mock/extensions/periodicjs.ext.test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "periodicjs.ext.test", 3 | "version": "0.0.1", 4 | "author": { 5 | "name": "yaw joseph etse", 6 | "email": "yaw.etse@gmail.com" 7 | }, 8 | "description": "test extension", 9 | "contributors": [{ 10 | "name": "jan" 11 | }, 12 | { 13 | "name": "iris" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /test/mock/extensions/periodicjs.ext.test/periodicjs.ext.json: -------------------------------------------------------------------------------- 1 | { 2 | "periodic_compatibility": "10.0.0", 3 | "periodic_dependencies": [{ 4 | "extname": "periodicjs.ext.mailer", 5 | "version": "~6.0.0" 6 | }, { 7 | "extname": "periodicjs.ext.login", 8 | "version": "~7.2.0" 9 | }, { 10 | "extname": "periodicjs.ext.user_access_control", 11 | "version": "~7.0.0", 12 | "optional": true 13 | }, { 14 | "extname": "periodicjs.ext.oauth2server", 15 | "version": "2.0.4" 16 | }], 17 | "periodic_type": 0, 18 | "periodic_priority": 0, 19 | "periodic_config": { 20 | "reactadmin": { 21 | "navigation": "node_modules/periodicjs.ext.reactadmin/views/reactadmin/components/navigation.manifest.js", 22 | "manifests": [ 23 | "node_modules/periodicjs.ext.reactadmin/views/reactadmin/manifests" 24 | ], 25 | "unauthenticated_manifests": [ 26 | "node_modules/periodicjs.ext.reactadmin/views/public/home/" 27 | ] 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /test/mock/extensions/periodicjs.ext.uac/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "periodicjs.ext.uac", 3 | "version": "4.8.1", 4 | "author": { 5 | "name": "yaw joseph etse", 6 | "email": "yaw.etse@gmail.com" 7 | }, 8 | "description": "test extension", 9 | "contributors": [{ 10 | "name": "jan" 11 | }, 12 | { 13 | "name": "iris" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /test/mock/extensions/periodicjs.ext.uac/periodicjs.ext.json: -------------------------------------------------------------------------------- 1 | { 2 | "periodic_compatibility": "10.0.0", 3 | "periodic_dependencies": [{ 4 | "extname": "periodicjs.ext.mailer", 5 | "version": "~6.0.0" 6 | }, { 7 | "extname": "periodicjs.ext.login", 8 | "version": "~7.2.0" 9 | }, { 10 | "extname": "periodicjs.ext.user_access_control", 11 | "version": "~7.0.0" 12 | }, { 13 | "extname": "periodicjs.ext.oauth2server", 14 | "version": "2.0.4" 15 | }], 16 | "periodic_type": 3, 17 | "periodic_priority": 10, 18 | "periodic_config": { 19 | "reactadmin": { 20 | "navigation": "node_modules/periodicjs.ext.reactadmin/views/reactadmin/components/navigation.manifest.js", 21 | "manifests": [ 22 | "node_modules/periodicjs.ext.reactadmin/views/reactadmin/manifests" 23 | ], 24 | "unauthenticated_manifests": [ 25 | "node_modules/periodicjs.ext.reactadmin/views/public/home/" 26 | ] 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /test/mock/sample_configs/display_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "filepath":"content/config/front-end/display.json", 3 | "environment":"test", 4 | "config":{ 5 | "html":5, 6 | "engine":"React", 7 | "responsive":{ 8 | "unit":"rem", 9 | "modular":[1,2,3,4,5] 10 | }, 11 | "test":true 12 | } 13 | } -------------------------------------------------------------------------------- /test/mock/sample_configs/dummy_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "filepath":"content/config/appconfig/dummy.json", 3 | "environment":"test", 4 | "container":"default", 5 | "config":{ 6 | "some":"data", 7 | "test":true 8 | } 9 | } -------------------------------------------------------------------------------- /test/mock/sample_configs/server_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "filepath":"content/config/server/config.json", 3 | "environment":"test", 4 | "config":{ 5 | "express_version":"5.0.1", 6 | "caching":{ 7 | "data":"redis", 8 | "view":"disk" 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /test/unit/crud/newtestext.md: -------------------------------------------------------------------------------- 1 | # newtestext [![Coverage Status](https://coveralls.io/repos/github/githubUserOrgName/newtestext/badge.svg?branch=master)](https://coveralls.io/github/githubUserOrgName/newtestext?branch=master) [![Build Status](https://travis-ci.org/githubUserOrgName/newtestext.svg?branch=master)](https://travis-ci.org/githubUserOrgName/newtestext) 2 | 3 | A simple extension. 4 | 5 | [API Documentation](https://github.com/githubUserOrgName/newtestext/blob/master/doc/api.md) 6 | 7 | ## Usage 8 | 9 | ### CLI TASK 10 | 11 | You can preform a task via CLI 12 | ``` 13 | $ cd path/to/application/root 14 | ### Using the CLI 15 | $ periodicjs ext newtestext hello 16 | ### Calling Manually 17 | $ node index.js --cli --command --ext --name=newtestext --task=hello 18 | ``` 19 | 20 | ## Configuration 21 | 22 | You can configure newtestext 23 | 24 | ### Default Configuration 25 | ```javascript 26 | { 27 | settings: { 28 | defaults: true, 29 | }, 30 | databases: { 31 | }, 32 | }; 33 | ``` 34 | 35 | 36 | ## Installation 37 | 38 | ### Installing the Extension 39 | 40 | Install like any other extension, run `npm run install newtestext` from your periodic application root directory and then run `periodicjs addExtension newtestext`. 41 | ``` 42 | $ cd path/to/application/root 43 | $ npm run install newtestext 44 | $ periodicjs addExtension newtestext 45 | ``` 46 | ### Uninstalling the Extension 47 | 48 | Run `npm run uninstall newtestext` from your periodic application root directory and then run `periodicjs removeExtension newtestext`. 49 | ``` 50 | $ cd path/to/application/root 51 | $ npm run uninstall newtestext 52 | $ periodicjs removeExtension newtestext 53 | ``` 54 | 55 | 56 | ## Testing 57 | *Make sure you have grunt installed* 58 | ``` 59 | $ npm install -g grunt-cli 60 | ``` 61 | 62 | Then run grunt test or npm test 63 | ``` 64 | $ grunt test && grunt coveralls #or locally $ npm test 65 | ``` 66 | For generating documentation 67 | ``` 68 | $ grunt doc 69 | $ jsdoc2md commands/**/*.js config/**/*.js controllers/**/*.js transforms/**/*.js utilities/**/*.js index.js > doc/api.md 70 | ``` 71 | ##Notes 72 | * Check out https://github.com/repetere/periodicjs for the full Periodic Documentation -------------------------------------------------------------------------------- /test/unit/extension/install_spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /*jshint expr: true*/ 3 | const path = require('path'); 4 | const events = require('events'); 5 | const chai = require('chai'); 6 | const sinon = require('sinon'); 7 | const fs = require('fs-extra'); 8 | const expect = require('chai').expect; 9 | const periodic = require('../../../index'); 10 | const periodicClass = require('../../../lib/periodicClass'); 11 | const install = require('../../../lib/extension/install'); 12 | chai.use(require('sinon-chai')); 13 | chai.use(require('chai-as-promised')); 14 | 15 | describe('Periodic Extension install', function() { 16 | this.timeout(10000); 17 | describe('installExtension', () => { 18 | it('should resolve as true', () => { 19 | expect(install.installExtension()).to.eventually.be.fulfilled; 20 | }); 21 | it('should reject an errors', () => { 22 | expect(install.installExtension('throw')).to.eventually.be.rejected; 23 | }); 24 | it('should return a promise', () => { 25 | expect(install.installExtension()).to.be.a('promise'); 26 | }); 27 | }); 28 | }); -------------------------------------------------------------------------------- /test/unit/extension/uninstall_spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /*jshint expr: true*/ 3 | const path = require('path'); 4 | const events = require('events'); 5 | const chai = require('chai'); 6 | const sinon = require('sinon'); 7 | const fs = require('fs-extra'); 8 | const expect = require('chai').expect; 9 | const periodic = require('../../../index'); 10 | const periodicClass = require('../../../lib/periodicClass'); 11 | const uninstall = require('../../../lib/extension/uninstall'); 12 | chai.use(require('sinon-chai')); 13 | chai.use(require('chai-as-promised')); 14 | 15 | describe('Periodic Extension uninstall', function() { 16 | this.timeout(10000); 17 | describe('uninstallExtension', () => { 18 | it('should resolve as true', () => { 19 | expect(uninstall.uninstallExtension()).to.eventually.be.fulfilled; 20 | }); 21 | it('should reject an errors', () => { 22 | expect(uninstall.uninstallExtension('throw')).to.eventually.be.rejected; 23 | }); 24 | it('should return a promise', () => { 25 | expect(uninstall.uninstallExtension()).to.be.a('promise'); 26 | }); 27 | }); 28 | }); -------------------------------------------------------------------------------- /test/unit/init/console_spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /*jshint expr: true*/ 3 | const path = require('path'); 4 | const events = require('events'); 5 | const chai = require('chai'); 6 | const sinon = require('sinon'); 7 | const fs = require('fs-extra'); 8 | const expect = require('chai').expect; 9 | const periodic = require('../../../index'); 10 | const periodicClass = require('../../../lib/periodicClass'); 11 | const consoleTimer = require('../../../lib/init/consoleTimer'); 12 | const testPathDir = path.resolve(__dirname, '../../mock/spec/periodic'); 13 | const initTestConsoleTimePathDir = path.join(testPathDir, 'testConsoleTime'); 14 | const initTestConsoleTimeEndPathDir = path.join(testPathDir, 'testConsoleTimeEnd'); 15 | chai.use(require('sinon-chai')); 16 | chai.use(require('chai-as-promised')); 17 | 18 | describe('Periodic Init Console Timer', function() { 19 | this.timeout(10000); 20 | before('initialize console test periodic dir', (done) => { 21 | Promise.all([ 22 | fs.ensureDir(initTestConsoleTimePathDir), 23 | fs.ensureDir(initTestConsoleTimeEndPathDir), 24 | ]) 25 | .then(() => { 26 | done(); 27 | }).catch(done); 28 | }); 29 | describe('Initialization errors', () => { 30 | it('stores intialization start time', (done) => { 31 | const mockThis = { 32 | config: {}, 33 | }; 34 | consoleTimer.startTimer.call(mockThis) 35 | .then(result => { 36 | expect(result).to.be.true; 37 | expect(mockThis.config.time_start).to.be.a('number'); 38 | done(); 39 | }) 40 | .catch(done); 41 | }); 42 | it('stores intialization end time', (done) => { 43 | const infoSpy = sinon.spy(); 44 | const mockThis = { 45 | config: {}, 46 | logger: { 47 | verbose: infoSpy, 48 | }, 49 | }; 50 | consoleTimer.endTimer.call(mockThis) 51 | .then(result => { 52 | expect(result).to.be.true; 53 | expect(infoSpy.called).to.be.true; 54 | expect(mockThis.config.time_end).to.be.a('number'); 55 | done(); 56 | }) 57 | .catch(done); 58 | }); 59 | it('should handle errors', () => { 60 | expect(consoleTimer.startTimer()).to.eventually.be.rejected; 61 | expect(consoleTimer.endTimer()).to.eventually.be.rejected; 62 | }); 63 | }); 64 | after('remove console test periodic dir', (done) => { 65 | Promise.all([ 66 | fs.remove(initTestConsoleTimePathDir), 67 | fs.remove(initTestConsoleTimeEndPathDir), 68 | ]) 69 | .then(() => { 70 | done(); 71 | }).catch(done); 72 | }); 73 | }); -------------------------------------------------------------------------------- /test/unit/proxyhandler_spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /*jshint expr: true*/ 3 | const path = require('path'); 4 | const events = require('events'); 5 | const chai = require('chai'); 6 | const expect = require('chai').expect; 7 | const sinon = require('sinon'); 8 | let periodicProxyHandler = require('../../lib/periodicProxyHandler'); 9 | 10 | describe('Periodic Class ProxyHandler', function() { 11 | it('should be a proxy handler', () => { 12 | expect(periodicProxyHandler).to.be.a('function'); 13 | }); 14 | it('should return a proxy handler object', () => { 15 | expect(periodicProxyHandler()).to.be.a('object'); 16 | }); 17 | it('should trap get property access', () => { 18 | let spy = sinon.spy(); 19 | let testProxy = new Proxy(spy, periodicProxyHandler); 20 | testProxy.someprop = '1234'; 21 | testProxy.someprop = testProxy.someprop.toString(); 22 | expect(periodicProxyHandler().get).to.be.a('function'); 23 | expect(testProxy.someprop).to.eql(spy.someprop); 24 | expect(periodicProxyHandler().get(spy, 'someprop')).to.eql(spy.someprop); 25 | }); 26 | it('should alias the configuraiton core data', () => { 27 | const testPeriodicInstance = { 28 | datas: new Map(), 29 | }; 30 | const dummyConfigDBAdapter = {}; 31 | testPeriodicInstance.datas.set('configuration', dummyConfigDBAdapter); 32 | expect(periodicProxyHandler().get(testPeriodicInstance, 'configuration')).to.eql(dummyConfigDBAdapter); 33 | }); 34 | it('should alias the standard db', () => { 35 | const testPeriodicInstance = { 36 | dbs: new Map(), 37 | }; 38 | const dummyConfigDBAdapter = {}; 39 | testPeriodicInstance.dbs.set('standard', dummyConfigDBAdapter); 40 | expect(periodicProxyHandler().get(testPeriodicInstance, 'db')).to.eql(dummyConfigDBAdapter); 41 | }); 42 | it('should alias the process runtime environment', () => { 43 | const testPeriodicInstance = { 44 | config: { 45 | process: { 46 | runtime: 'testenv', 47 | }, 48 | }, 49 | }; 50 | expect(periodicProxyHandler().get(testPeriodicInstance, 'environment')).to.eql('testenv'); 51 | }); 52 | it('should alias the current container settings', () => { 53 | const testPeriodicInstance = { 54 | settings: { 55 | container: { 56 | name: 'testcontainer', 57 | }, 58 | }, 59 | }; 60 | expect(periodicProxyHandler().get(testPeriodicInstance, 'container').name).to.eql('testcontainer'); 61 | }); 62 | }); -------------------------------------------------------------------------------- /test/unit/utilities/mock_spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /*jshint expr: true*/ 3 | const path = require('path'); 4 | const events = require('events'); 5 | const chai = require('chai'); 6 | const sinon = require('sinon'); 7 | const fs = require('fs-extra'); 8 | const expect = require('chai').expect; 9 | const periodic = require('../../../index'); 10 | const periodicClass = require('../../../lib/periodicClass'); 11 | const mock = require('../../../lib/utilities/mock'); 12 | chai.use(require('sinon-chai')); 13 | chai.use(require('chai-as-promised')); 14 | 15 | describe('Periodic Util mock', function() { 16 | this.timeout(10000); 17 | describe('tempPromise', () => { 18 | it('should resolve as true', () => { 19 | expect(mock.tempPromise()).to.eventually.be.fulfilled; 20 | }); 21 | it('should reject an errors', () => { 22 | expect(mock.tempPromise('throw')).to.eventually.be.rejected; 23 | }); 24 | it('should return a promise', () => { 25 | expect(mock.tempPromise()).to.be.a('promise'); 26 | }); 27 | }); 28 | }); -------------------------------------------------------------------------------- /test/unit/utilities/routing_spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /*jshint expr: true*/ 3 | const path = require('path'); 4 | const chai = require('chai'); 5 | const expect = require('chai').expect; 6 | const routing = require('../../../lib/utilities/routing'); 7 | chai.use(require('sinon-chai')); 8 | chai.use(require('chai-as-promised')); 9 | 10 | describe('Periodic Util routing', function() { 11 | this.timeout(10000); 12 | describe('route_prefix', () => { 13 | it('should return the adminPath prefixed with "/" if "/" does not already exist', () => { 14 | expect(routing.route_prefix('r-admin')).to.eql('/r-admin'); 15 | }); 16 | 17 | it('should return the adminPath if "/" already exists', () => { 18 | expect(routing.route_prefix('/r-admin')).to.eql('/r-admin'); 19 | }); 20 | }); 21 | 22 | describe('admin_prefix', () => { 23 | it('should return the adminPath without prefix', () => { 24 | expect(routing.admin_prefix('/r-admin')).to.eql('r-admin'); 25 | }); 26 | }); 27 | 28 | describe('manifest_prefix', () => { 29 | it('should return a route string that has a preceding "/" and a "/" as suffix', () => { 30 | expect(routing.manifest_prefix('/r-admin')).to.eql('/r-admin/'); 31 | }); 32 | }); 33 | 34 | describe('all_prefixes', () => { 35 | it('should return an object with all prefix types', () => { 36 | expect(routing.all_prefixes('/r-admin')).to.deep.equal({ 37 | 'route_prefix': '/r-admin', 38 | 'admin_prefix': 'r-admin', 39 | 'manifest_prefix': '/r-admin/' 40 | }); 41 | }); 42 | }); 43 | 44 | describe('splitModelNameReducer', () => { 45 | it('should return an updated object with key value pair of parent and array of children, given an object and a modelname', () => { 46 | expect(routing.splitModelNameReducer({}, 'standard_user_group')).to.deep.equal({ 47 | 'standard': ['user_group'], 48 | }); 49 | }); 50 | }); 51 | 52 | describe('regexModelNameReducer', () => { 53 | it('should use regex to return an updated object with key value pair of parent and array of children, given an object and a modelname', () => { 54 | expect(routing.regexModelNameReducer({}, 'standard_user_group')).to.deep.equal({ 55 | 'standard': ['user_group'], 56 | }); 57 | }); 58 | }); 59 | 60 | describe('formatResponse', () => { 61 | it('should return a formatted response', () => { 62 | expect(routing.formatResponse()).to.eql({ 63 | result: 'success', 64 | status: 200, 65 | data: {}, 66 | }); 67 | }); 68 | it('should format response with 3 properties', () => { 69 | const customProps = { some: 'random', props: 'should be in data' }; 70 | const formattedRes = routing.formatResponse(customProps); 71 | expect(Object.keys(formattedRes).length).to.eql(3); 72 | expect(formattedRes.data).to.eql(customProps); 73 | }); 74 | it('should enforce data types of props', () => { 75 | const formattedRes = routing.formatResponse({ result: 1203, status: '450' }); 76 | expect(formattedRes.result).to.be.a('string'); 77 | expect(formattedRes.status).to.be.a('number'); 78 | }); 79 | }); 80 | 81 | }); -------------------------------------------------------------------------------- /test/unit/utilities/viewHelper_spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /*jshint expr: true*/ 3 | const path = require('path'); 4 | const events = require('events'); 5 | const chai = require('chai'); 6 | const sinon = require('sinon'); 7 | const fs = require('fs-extra'); 8 | const expect = require('chai').expect; 9 | const periodic = require('../../../index'); 10 | const periodicClass = require('../../../lib/periodicClass'); 11 | const viewHelper = require('../../../lib/utilities/viewHelper'); 12 | chai.use(require('sinon-chai')); 13 | chai.use(require('chai-as-promised')); 14 | 15 | describe('Periodic Util viewHelper', function() { 16 | this.timeout(10000); 17 | describe('passObjToClient', () => { 18 | it('should return a string of an object for window', () => { 19 | const backedObject = { some: 'data' }; 20 | const windowVar = 'testdata'; 21 | expect(viewHelper.passObjToClient(backedObject, windowVar)).to.eql(`var ${windowVar} = ${(JSON.stringify(backedObject))}`); 22 | }); 23 | }); 24 | }); --------------------------------------------------------------------------------