gina 0.0.9-p91b → 0.1.1-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (466) hide show
  1. package/INSTALL.md +46 -0
  2. package/{core/asset/html/static.html → Icon/r} +0 -0
  3. package/LICENSE +1 -1
  4. package/README-4Contributors.md +96 -0
  5. package/README.md +296 -104
  6. package/bin/cli +287 -0
  7. package/bin/cli-debug +60 -0
  8. package/bin/cmd +184 -0
  9. package/bin/gina +180 -0
  10. package/config/logger.json +17 -0
  11. package/doc/framework/cli/doc.json +9 -0
  12. package/doc/framework/index.md +60 -0
  13. package/framework/v0.1.1-alpha.2/AUTHORS +7 -0
  14. package/{core/utils/lib/inherits → framework/v0.1.1-alpha.2}/LICENSE +1 -1
  15. package/framework/v0.1.1-alpha.2/VERSION +1 -0
  16. package/{core/locales/dist/language/en.json → framework/v0.1.1-alpha.2/core/asset/html/nolayout.html} +0 -0
  17. package/{core/locales/dist/language/fr.json → framework/v0.1.1-alpha.2/core/asset/html/static.html} +0 -0
  18. package/{core → framework/v0.1.1-alpha.2/core}/asset/img/android-chrome-192x192.png +0 -0
  19. package/{core → framework/v0.1.1-alpha.2/core}/asset/img/android-chrome-512x512.png +0 -0
  20. package/{core → framework/v0.1.1-alpha.2/core}/asset/img/apple-touch-icon.png +0 -0
  21. package/{core → framework/v0.1.1-alpha.2/core}/asset/img/favicon-16x16.png +0 -0
  22. package/{core → framework/v0.1.1-alpha.2/core}/asset/img/favicon-32x32.png +0 -0
  23. package/{core → framework/v0.1.1-alpha.2/core}/asset/img/favicon.ico +0 -0
  24. package/framework/v0.1.1-alpha.2/core/asset/js/plugin/dist/gina.js +20904 -0
  25. package/framework/v0.1.1-alpha.2/core/asset/js/plugin/dist/gina.js.map +56 -0
  26. package/framework/v0.1.1-alpha.2/core/asset/js/plugin/dist/gina.min.css +1 -0
  27. package/framework/v0.1.1-alpha.2/core/asset/js/plugin/dist/gina.min.css.map +1 -0
  28. package/framework/v0.1.1-alpha.2/core/asset/js/plugin/dist/gina.min.js +736 -0
  29. package/framework/v0.1.1-alpha.2/core/asset/js/plugin/dist/gina.min.js.map +56 -0
  30. package/framework/v0.1.1-alpha.2/core/asset/js/plugin/dist/gina.onload.min.js +5 -0
  31. package/framework/v0.1.1-alpha.2/core/asset/js/plugin/dist/gina.onload.min.js.map +8 -0
  32. package/framework/v0.1.1-alpha.2/core/asset/js/plugin/readme.md +192 -0
  33. package/framework/v0.1.1-alpha.2/core/asset/js/plugin/uuid.json +23 -0
  34. package/framework/v0.1.1-alpha.2/core/config.js +2308 -0
  35. package/framework/v0.1.1-alpha.2/core/connectors/couchbase/index.js +757 -0
  36. package/framework/v0.1.1-alpha.2/core/connectors/couchbase/lib/connector.js +20 -0
  37. package/framework/v0.1.1-alpha.2/core/connectors/couchbase/lib/connector.v2.js +429 -0
  38. package/framework/v0.1.1-alpha.2/core/connectors/couchbase/lib/connector.v3.js +432 -0
  39. package/framework/v0.1.1-alpha.2/core/connectors/couchbase/lib/n1ql.js +14 -0
  40. package/framework/v0.1.1-alpha.2/core/connectors/couchbase/lib/session-store.js +21 -0
  41. package/framework/v0.1.1-alpha.2/core/connectors/couchbase/lib/session-store.v2.js +258 -0
  42. package/framework/v0.1.1-alpha.2/core/connectors/couchbase/lib/session-store.v3.js +341 -0
  43. package/{core → framework/v0.1.1-alpha.2/core}/controller/controller.framework.js +3 -2
  44. package/framework/v0.1.1-alpha.2/core/controller/controller.js +3990 -0
  45. package/{core → framework/v0.1.1-alpha.2/core}/controller/index.js +5 -5
  46. package/framework/v0.1.1-alpha.2/core/deps/busboy/.travis.yml +17 -0
  47. package/framework/v0.1.1-alpha.2/core/deps/busboy/LICENSE +19 -0
  48. package/framework/v0.1.1-alpha.2/core/deps/busboy/README.md +225 -0
  49. package/framework/v0.1.1-alpha.2/core/deps/busboy/deps/encoding/encoding-indexes.js +73 -0
  50. package/framework/v0.1.1-alpha.2/core/deps/busboy/deps/encoding/encoding.js +2391 -0
  51. package/framework/v0.1.1-alpha.2/core/deps/busboy/lib/main.js +89 -0
  52. package/framework/v0.1.1-alpha.2/core/deps/busboy/lib/types/multipart.js +328 -0
  53. package/framework/v0.1.1-alpha.2/core/deps/busboy/lib/types/urlencoded.js +214 -0
  54. package/framework/v0.1.1-alpha.2/core/deps/busboy/lib/utils.js +191 -0
  55. package/framework/v0.1.1-alpha.2/core/deps/busboy/package.json +69 -0
  56. package/framework/v0.1.1-alpha.2/core/deps/swig-client/swig-2.0.0.min.js +5 -0
  57. package/{core → framework/v0.1.1-alpha.2/core}/dev/index.js +5 -5
  58. package/{core → framework/v0.1.1-alpha.2/core}/dev/lib/class.js +1 -1
  59. package/{core → framework/v0.1.1-alpha.2/core}/dev/lib/factory.js +1 -1
  60. package/{core → framework/v0.1.1-alpha.2/core}/dev/lib/tools.js +0 -0
  61. package/framework/v0.1.1-alpha.2/core/gna.js +1070 -0
  62. package/{core → framework/v0.1.1-alpha.2/core}/locales/README.md +41 -2
  63. package/{core → framework/v0.1.1-alpha.2/core}/locales/currency.json +0 -0
  64. package/{core/plugins/README.md → framework/v0.1.1-alpha.2/core/locales/dist/language/en.json} +0 -0
  65. package/{core/plugins/lib/intl/README.md → framework/v0.1.1-alpha.2/core/locales/dist/language/fr.json} +0 -0
  66. package/{core → framework/v0.1.1-alpha.2/core}/locales/dist/region/en.json +0 -0
  67. package/framework/v0.1.1-alpha.2/core/locales/dist/region/fr.json +9492 -0
  68. package/{core → framework/v0.1.1-alpha.2/core}/locales/index.js +5 -4
  69. package/{core → framework/v0.1.1-alpha.2/core}/locales/src/make.js +15 -12
  70. package/{core → framework/v0.1.1-alpha.2/core}/locales/src/resources/currency.csv +0 -0
  71. package/{core → framework/v0.1.1-alpha.2/core}/locales/src/resources/region.csv +0 -0
  72. package/{core → framework/v0.1.1-alpha.2/core}/locales/src/resources/region.mapping.json +0 -0
  73. package/{core → framework/v0.1.1-alpha.2/core}/mime.types +0 -0
  74. package/{core → framework/v0.1.1-alpha.2/core}/model/entity.js +156 -196
  75. package/{core → framework/v0.1.1-alpha.2/core}/model/index.js +67 -48
  76. package/{core → framework/v0.1.1-alpha.2/core}/model/template/entityFactory.js +2 -2
  77. package/{core → framework/v0.1.1-alpha.2/core}/model/template/index.js +8 -10
  78. package/{core/plugins/lib/storage → framework/v0.1.1-alpha.2/core/plugins}/README.md +0 -0
  79. package/{core → framework/v0.1.1-alpha.2/core}/plugins/index.js +3 -3
  80. package/{core/plugins/lib/validator → framework/v0.1.1-alpha.2/core/plugins/lib/file}/README.md +0 -0
  81. package/{core/plugins/lib/intl → framework/v0.1.1-alpha.2/core/plugins/lib/file}/build.json +0 -0
  82. package/framework/v0.1.1-alpha.2/core/plugins/lib/file/package.json +25 -0
  83. package/{core/utils/lib/collection → framework/v0.1.1-alpha.2/core/plugins/lib/intl}/README.md +0 -0
  84. package/{core/plugins/lib/storage → framework/v0.1.1-alpha.2/core/plugins/lib/intl}/build.json +0 -0
  85. package/{core → framework/v0.1.1-alpha.2/core}/plugins/lib/intl/package.json +3 -3
  86. package/{core → framework/v0.1.1-alpha.2/core}/plugins/lib/intl/src/main.js +17 -1
  87. package/{core/utils/lib/routing → framework/v0.1.1-alpha.2/core/plugins/lib/storage}/README.md +0 -0
  88. package/{core/plugins/lib/validator → framework/v0.1.1-alpha.2/core/plugins/lib/storage}/build.json +0 -0
  89. package/{core → framework/v0.1.1-alpha.2/core}/plugins/lib/storage/package.json +2 -2
  90. package/{core → framework/v0.1.1-alpha.2/core}/plugins/lib/storage/src/main.js +91 -85
  91. package/{core/utils/lib/url → framework/v0.1.1-alpha.2/core/plugins/lib/validator}/README.md +0 -0
  92. package/{core/utils/lib/collection → framework/v0.1.1-alpha.2/core/plugins/lib/validator}/build.json +0 -0
  93. package/{core → framework/v0.1.1-alpha.2/core}/plugins/lib/validator/package.json +3 -3
  94. package/framework/v0.1.1-alpha.2/core/plugins/lib/validator/src/form-validator.js +1762 -0
  95. package/framework/v0.1.1-alpha.2/core/plugins/lib/validator/src/main.js +6917 -0
  96. package/framework/v0.1.1-alpha.2/core/router.js +664 -0
  97. package/framework/v0.1.1-alpha.2/core/server.express.js +213 -0
  98. package/framework/v0.1.1-alpha.2/core/server.isaac.js +386 -0
  99. package/framework/v0.1.1-alpha.2/core/server.js +3010 -0
  100. package/{core → framework/v0.1.1-alpha.2/core}/status.codes +8 -0
  101. package/framework/v0.1.1-alpha.2/core/template/boilerplate/bundle/config/app.json +6 -0
  102. package/framework/v0.1.1-alpha.2/core/template/boilerplate/bundle/config/routing.json +11 -0
  103. package/framework/v0.1.1-alpha.2/core/template/boilerplate/bundle/config/settings.json +9 -0
  104. package/framework/v0.1.1-alpha.2/core/template/boilerplate/bundle/config/settings.server.json +30 -0
  105. package/framework/v0.1.1-alpha.2/core/template/boilerplate/bundle/config/templates.json +42 -0
  106. package/framework/v0.1.1-alpha.2/core/template/boilerplate/bundle/controllers/controller.content.js +39 -0
  107. package/framework/v0.1.1-alpha.2/core/template/boilerplate/bundle/controllers/controller.js +30 -0
  108. package/framework/v0.1.1-alpha.2/core/template/boilerplate/bundle/controllers/setup.js +111 -0
  109. package/{core/template/samples → framework/v0.1.1-alpha.2/core/template/boilerplate}/bundle/index.js +0 -0
  110. package/{core/template/samples/bundle → framework/v0.1.1-alpha.2/core/template/boilerplate/bundle_namespace}/controllers/controller.js +9 -7
  111. package/{core/template/views → framework/v0.1.1-alpha.2/core/template/boilerplate/bundle_public}/css/default.css +0 -0
  112. package/{core/template/views → framework/v0.1.1-alpha.2/core/template/boilerplate/bundle_public}/css/vendor/readme.md +0 -0
  113. package/{core/template/views → framework/v0.1.1-alpha.2/core/template/boilerplate/bundle_public}/favicon.ico +0 -0
  114. package/framework/v0.1.1-alpha.2/core/template/boilerplate/bundle_public/js/vendor/readme.md +1 -0
  115. package/framework/v0.1.1-alpha.2/core/template/boilerplate/bundle_public/readme.md +1 -0
  116. package/framework/v0.1.1-alpha.2/core/template/boilerplate/bundle_templates/handlers/main.js +24 -0
  117. package/{core/template/views/html/default.html → framework/v0.1.1-alpha.2/core/template/boilerplate/bundle_templates/html/homepage.html} +0 -0
  118. package/{core/template/views/html/layout.html → framework/v0.1.1-alpha.2/core/template/boilerplate/bundle_templates/html/layout/main.html} +2 -2
  119. package/{core → framework/v0.1.1-alpha.2/core}/template/command/gina.bat.tpl +0 -0
  120. package/{core → framework/v0.1.1-alpha.2/core}/template/command/gina.tpl +1 -1
  121. package/framework/v0.1.1-alpha.2/core/template/conf/env.json +76 -0
  122. package/{core/template/conf/project.json → framework/v0.1.1-alpha.2/core/template/conf/manifest.json} +1 -0
  123. package/{core → framework/v0.1.1-alpha.2/core}/template/conf/package.json +2 -2
  124. package/framework/v0.1.1-alpha.2/core/template/conf/settings.json +92 -0
  125. package/framework/v0.1.1-alpha.2/core/template/conf/statics.json +10 -0
  126. package/framework/v0.1.1-alpha.2/core/template/conf/templates.json +37 -0
  127. package/{core → framework/v0.1.1-alpha.2/core}/template/error/client/json/401.json +0 -0
  128. package/{core → framework/v0.1.1-alpha.2/core}/template/error/client/json/403.json +0 -0
  129. package/{core → framework/v0.1.1-alpha.2/core}/template/error/client/json/404.json +0 -0
  130. package/{core → framework/v0.1.1-alpha.2/core}/template/error/server/html/50x.html +0 -0
  131. package/{core → framework/v0.1.1-alpha.2/core}/template/error/server/json/500.json +0 -0
  132. package/{core → framework/v0.1.1-alpha.2/core}/template/error/server/json/503.json +0 -0
  133. package/{core/utils/lib/routing/build.json → framework/v0.1.1-alpha.2/core/template/extensions/logger/config.json} +0 -0
  134. package/{core/utils → framework/v0.1.1-alpha.2}/helpers/console.js +3 -3
  135. package/{core/utils → framework/v0.1.1-alpha.2}/helpers/context.js +240 -49
  136. package/framework/v0.1.1-alpha.2/helpers/dateFormat.js +528 -0
  137. package/framework/v0.1.1-alpha.2/helpers/index.js +79 -0
  138. package/framework/v0.1.1-alpha.2/helpers/json/README.md +0 -0
  139. package/framework/v0.1.1-alpha.2/helpers/json/package.json +20 -0
  140. package/framework/v0.1.1-alpha.2/helpers/json/src/main.js +97 -0
  141. package/{core/utils → framework/v0.1.1-alpha.2}/helpers/path.js +342 -140
  142. package/framework/v0.1.1-alpha.2/helpers/plugins/README.md +4 -0
  143. package/framework/v0.1.1-alpha.2/helpers/plugins/package.json +20 -0
  144. package/framework/v0.1.1-alpha.2/helpers/plugins/src/api-error.js +160 -0
  145. package/framework/v0.1.1-alpha.2/helpers/plugins/src/main.js +32 -0
  146. package/framework/v0.1.1-alpha.2/helpers/prototypes.js +218 -0
  147. package/{core/utils → framework/v0.1.1-alpha.2}/helpers/task.js +49 -29
  148. package/{core/utils → framework/v0.1.1-alpha.2}/helpers/text.js +7 -7
  149. package/framework/v0.1.1-alpha.2/lib/archiver/README.md +0 -0
  150. package/framework/v0.1.1-alpha.2/lib/archiver/build.json +0 -0
  151. package/framework/v0.1.1-alpha.2/lib/archiver/package.json +20 -0
  152. package/framework/v0.1.1-alpha.2/lib/archiver/src/dep/jszip.min.js +15 -0
  153. package/framework/v0.1.1-alpha.2/lib/archiver/src/main.js +499 -0
  154. package/framework/v0.1.1-alpha.2/lib/cmd/aliases.json +13 -0
  155. package/framework/v0.1.1-alpha.2/lib/cmd/bundle/add.js +507 -0
  156. package/framework/v0.1.1-alpha.2/lib/cmd/bundle/arguments.json +4 -0
  157. package/framework/v0.1.1-alpha.2/lib/cmd/bundle/copy.js +15 -0
  158. package/framework/v0.1.1-alpha.2/lib/cmd/bundle/cp.js +2 -0
  159. package/framework/v0.1.1-alpha.2/lib/cmd/bundle/help.js +28 -0
  160. package/framework/v0.1.1-alpha.2/lib/cmd/bundle/help.txt +67 -0
  161. package/framework/v0.1.1-alpha.2/lib/cmd/bundle/list.js +129 -0
  162. package/framework/v0.1.1-alpha.2/lib/cmd/bundle/remove.js +229 -0
  163. package/framework/v0.1.1-alpha.2/lib/cmd/bundle/rename.js +4 -0
  164. package/framework/v0.1.1-alpha.2/lib/cmd/bundle/restart.js +235 -0
  165. package/framework/v0.1.1-alpha.2/lib/cmd/bundle/rm.js +2 -0
  166. package/framework/v0.1.1-alpha.2/lib/cmd/bundle/start.js +394 -0
  167. package/framework/v0.1.1-alpha.2/lib/cmd/bundle/status.js +3 -0
  168. package/framework/v0.1.1-alpha.2/lib/cmd/bundle/stop.js +232 -0
  169. package/framework/v0.1.1-alpha.2/lib/cmd/env/add.js +436 -0
  170. package/framework/v0.1.1-alpha.2/lib/cmd/env/get.js +62 -0
  171. package/framework/v0.1.1-alpha.2/lib/cmd/env/help.js +28 -0
  172. package/framework/v0.1.1-alpha.2/lib/cmd/env/help.txt +33 -0
  173. package/framework/v0.1.1-alpha.2/lib/cmd/env/link-dev.js +80 -0
  174. package/framework/v0.1.1-alpha.2/lib/cmd/env/list.js +111 -0
  175. package/framework/v0.1.1-alpha.2/lib/cmd/env/remove.js +150 -0
  176. package/framework/v0.1.1-alpha.2/lib/cmd/env/rm.js +2 -0
  177. package/framework/v0.1.1-alpha.2/lib/cmd/env/set.js +57 -0
  178. package/framework/v0.1.1-alpha.2/lib/cmd/env/unset.js +44 -0
  179. package/framework/v0.1.1-alpha.2/lib/cmd/env/use.js +79 -0
  180. package/framework/v0.1.1-alpha.2/lib/cmd/framework/dot.js +70 -0
  181. package/framework/v0.1.1-alpha.2/lib/cmd/framework/get.js +0 -0
  182. package/framework/v0.1.1-alpha.2/lib/cmd/framework/help.js +39 -0
  183. package/framework/v0.1.1-alpha.2/lib/cmd/framework/help.txt +31 -0
  184. package/framework/v0.1.1-alpha.2/lib/cmd/framework/init.js +514 -0
  185. package/{core/utils/lib/cmd → framework/v0.1.1-alpha.2/lib/cmd/framework}/msg.json +3 -3
  186. package/framework/v0.1.1-alpha.2/lib/cmd/framework/open.js +50 -0
  187. package/framework/v0.1.1-alpha.2/lib/cmd/framework/restart.js +124 -0
  188. package/framework/v0.1.1-alpha.2/lib/cmd/framework/set.js +161 -0
  189. package/framework/v0.1.1-alpha.2/lib/cmd/framework/start.js +96 -0
  190. package/framework/v0.1.1-alpha.2/lib/cmd/framework/status.js +72 -0
  191. package/framework/v0.1.1-alpha.2/lib/cmd/framework/stop.js +159 -0
  192. package/framework/v0.1.1-alpha.2/lib/cmd/framework/tail.js +183 -0
  193. package/framework/v0.1.1-alpha.2/lib/cmd/framework/update.js +0 -0
  194. package/framework/v0.1.1-alpha.2/lib/cmd/framework/version.js +44 -0
  195. package/framework/v0.1.1-alpha.2/lib/cmd/gina-dev.1.md +66 -0
  196. package/framework/v0.1.1-alpha.2/lib/cmd/gina-framework.1.md +100 -0
  197. package/framework/v0.1.1-alpha.2/lib/cmd/gina.1.md +79 -0
  198. package/framework/v0.1.1-alpha.2/lib/cmd/helper.js +1147 -0
  199. package/framework/v0.1.1-alpha.2/lib/cmd/index.js +170 -0
  200. package/framework/v0.1.1-alpha.2/lib/cmd/msg.json +20 -0
  201. package/framework/v0.1.1-alpha.2/lib/cmd/port/help.js +28 -0
  202. package/framework/v0.1.1-alpha.2/lib/cmd/port/help.txt +31 -0
  203. package/framework/v0.1.1-alpha.2/lib/cmd/port/inc/scan.js +108 -0
  204. package/framework/v0.1.1-alpha.2/lib/cmd/port/list.js +176 -0
  205. package/framework/v0.1.1-alpha.2/lib/cmd/port/set.js +0 -0
  206. package/framework/v0.1.1-alpha.2/lib/cmd/project/add.js +528 -0
  207. package/framework/v0.1.1-alpha.2/lib/cmd/project/arguments.json +9 -0
  208. package/framework/v0.1.1-alpha.2/lib/cmd/project/build.js +115 -0
  209. package/framework/v0.1.1-alpha.2/lib/cmd/project/help.js +28 -0
  210. package/framework/v0.1.1-alpha.2/lib/cmd/project/help.txt +76 -0
  211. package/framework/v0.1.1-alpha.2/lib/cmd/project/import.js +2 -0
  212. package/framework/v0.1.1-alpha.2/lib/cmd/project/list.js +55 -0
  213. package/framework/v0.1.1-alpha.2/lib/cmd/project/move.js +0 -0
  214. package/framework/v0.1.1-alpha.2/lib/cmd/project/remove.js +144 -0
  215. package/framework/v0.1.1-alpha.2/lib/cmd/project/rename.js +162 -0
  216. package/framework/v0.1.1-alpha.2/lib/cmd/project/restart.js +0 -0
  217. package/framework/v0.1.1-alpha.2/lib/cmd/project/rm.js +2 -0
  218. package/framework/v0.1.1-alpha.2/lib/cmd/project/start.js +0 -0
  219. package/framework/v0.1.1-alpha.2/lib/cmd/project/status.js +3 -0
  220. package/framework/v0.1.1-alpha.2/lib/cmd/project/stop.js +0 -0
  221. package/framework/v0.1.1-alpha.2/lib/cmd/protocol/help.js +27 -0
  222. package/framework/v0.1.1-alpha.2/lib/cmd/protocol/help.txt +57 -0
  223. package/framework/v0.1.1-alpha.2/lib/cmd/protocol/list.js +239 -0
  224. package/framework/v0.1.1-alpha.2/lib/cmd/protocol/set.js +631 -0
  225. package/framework/v0.1.1-alpha.2/lib/cmd/scope/help.js +28 -0
  226. package/framework/v0.1.1-alpha.2/lib/cmd/scope/help.txt +33 -0
  227. package/framework/v0.1.1-alpha.2/lib/cmd/scope/link-local.js +80 -0
  228. package/framework/v0.1.1-alpha.2/lib/cmd/scope/list.js +116 -0
  229. package/framework/v0.1.1-alpha.2/lib/cmd/scope/remove.js +150 -0
  230. package/framework/v0.1.1-alpha.2/lib/cmd/scope/rm.js +2 -0
  231. package/framework/v0.1.1-alpha.2/lib/cmd/scope/set.js +57 -0
  232. package/framework/v0.1.1-alpha.2/lib/cmd/scope/unset.js +44 -0
  233. package/framework/v0.1.1-alpha.2/lib/cmd/scope/use.js +79 -0
  234. package/framework/v0.1.1-alpha.2/lib/cmd/view/add.js +311 -0
  235. package/framework/v0.1.1-alpha.2/lib/collection/README.md +5 -0
  236. package/framework/v0.1.1-alpha.2/lib/collection/build.json +0 -0
  237. package/{core/utils → framework/v0.1.1-alpha.2}/lib/collection/package.json +2 -2
  238. package/framework/v0.1.1-alpha.2/lib/collection/src/main.js +1459 -0
  239. package/{core/utils → framework/v0.1.1-alpha.2}/lib/config.js +49 -34
  240. package/framework/v0.1.1-alpha.2/lib/cron/README.md +7 -0
  241. package/framework/v0.1.1-alpha.2/lib/cron/package.json +20 -0
  242. package/framework/v0.1.1-alpha.2/lib/cron/src/main.js +176 -0
  243. package/{core/utils → framework/v0.1.1-alpha.2}/lib/generator/index.js +8 -4
  244. package/framework/v0.1.1-alpha.2/lib/index.js +116 -0
  245. package/framework/v0.1.1-alpha.2/lib/inherits/LICENSE +19 -0
  246. package/{core/utils → framework/v0.1.1-alpha.2}/lib/inherits/README.md +0 -0
  247. package/{core/utils → framework/v0.1.1-alpha.2}/lib/inherits/example/inheriting_eventemitter.js +0 -0
  248. package/{core/utils → framework/v0.1.1-alpha.2}/lib/inherits/example/protected_inheritance.js +0 -0
  249. package/{core/utils → framework/v0.1.1-alpha.2}/lib/inherits/example/simple_inheritance.js +0 -0
  250. package/{core/utils → framework/v0.1.1-alpha.2}/lib/inherits/example/super_attribute_overridden_by_child_on_init.js +0 -0
  251. package/{core/utils → framework/v0.1.1-alpha.2}/lib/inherits/package.json +2 -2
  252. package/{core/utils → framework/v0.1.1-alpha.2}/lib/inherits/src/main.js +18 -19
  253. package/framework/v0.1.1-alpha.2/lib/logger/README.md +7 -0
  254. package/framework/v0.1.1-alpha.2/lib/logger/package.json +20 -0
  255. package/framework/v0.1.1-alpha.2/lib/logger/src/containers/default/index.js +55 -0
  256. package/framework/v0.1.1-alpha.2/lib/logger/src/containers/file/index.js +251 -0
  257. package/framework/v0.1.1-alpha.2/lib/logger/src/containers/file/lib/logrotator/README.md +100 -0
  258. package/framework/v0.1.1-alpha.2/lib/logger/src/containers/file/lib/logrotator/index.js +274 -0
  259. package/framework/v0.1.1-alpha.2/lib/logger/src/containers/mq/index.js +52 -0
  260. package/framework/v0.1.1-alpha.2/lib/logger/src/containers/mq/listener.js +302 -0
  261. package/framework/v0.1.1-alpha.2/lib/logger/src/containers/mq/speaker.js +118 -0
  262. package/framework/v0.1.1-alpha.2/lib/logger/src/helper.js +131 -0
  263. package/framework/v0.1.1-alpha.2/lib/logger/src/main.js +734 -0
  264. package/{core/utils → framework/v0.1.1-alpha.2}/lib/math/index.js +58 -35
  265. package/{core/utils → framework/v0.1.1-alpha.2}/lib/merge/README.md +5 -0
  266. package/{core/utils → framework/v0.1.1-alpha.2}/lib/merge/example/merge.js +1 -1
  267. package/{core/utils → framework/v0.1.1-alpha.2}/lib/merge/example/merge_2_literal objects.js +0 -0
  268. package/{core/utils → framework/v0.1.1-alpha.2}/lib/merge/example/merge_and_preserve_first.js +2 -0
  269. package/{core/utils → framework/v0.1.1-alpha.2}/lib/merge/package.json +2 -2
  270. package/framework/v0.1.1-alpha.2/lib/merge/src/main.js +531 -0
  271. package/{core/utils → framework/v0.1.1-alpha.2}/lib/model.js +42 -19
  272. package/framework/v0.1.1-alpha.2/lib/proc.js +518 -0
  273. package/framework/v0.1.1-alpha.2/lib/routing/README.md +0 -0
  274. package/framework/v0.1.1-alpha.2/lib/routing/build.json +0 -0
  275. package/{core/utils → framework/v0.1.1-alpha.2}/lib/routing/package.json +2 -2
  276. package/framework/v0.1.1-alpha.2/lib/routing/src/main.js +1492 -0
  277. package/framework/v0.1.1-alpha.2/lib/session-store.js +33 -0
  278. package/{core/utils → framework/v0.1.1-alpha.2}/lib/shell.js +43 -30
  279. package/framework/v0.1.1-alpha.2/lib/swig-filters/README.md +0 -0
  280. package/framework/v0.1.1-alpha.2/lib/swig-filters/package.json +20 -0
  281. package/framework/v0.1.1-alpha.2/lib/swig-filters/src/main.js +322 -0
  282. package/framework/v0.1.1-alpha.2/lib/url/README.md +0 -0
  283. package/{core/utils → framework/v0.1.1-alpha.2}/lib/url/index.js +2 -1
  284. package/{core/utils → framework/v0.1.1-alpha.2}/lib/url/mocks.json +0 -0
  285. package/{core/utils → framework/v0.1.1-alpha.2}/lib/url/routing.json +9 -9
  286. package/{core/utils → framework/v0.1.1-alpha.2}/lib/url/test.js +0 -0
  287. package/{core/utils → framework/v0.1.1-alpha.2}/lib/validator.js +7 -7
  288. package/framework/v0.1.1-alpha.2/package.json +14 -0
  289. package/package.json +35 -33
  290. package/resources/etc/init.d/debian/gina +117 -0
  291. package/resources/home/framework/env.json +34 -0
  292. package/resources/home/framework/locals.json +14 -0
  293. package/resources/home/framework/project.json +48 -0
  294. package/resources/home/framework/projects.json +6 -0
  295. package/resources/home/main.json +47 -0
  296. package/resources/home/settings.json +22 -0
  297. package/resources/home/user/extensions/logger/default/config.json +77 -0
  298. package/resources/home/user/extensions/logger/file/config.json +11 -0
  299. package/resources/img/android-chrome-192x192.png +0 -0
  300. package/resources/img/android-chrome-512x512.png +0 -0
  301. package/resources/img/apple-touch-icon.png +0 -0
  302. package/resources/img/favicon-16x16.png +0 -0
  303. package/resources/img/favicon-32x32.png +0 -0
  304. package/resources/img/favicon.ico +0 -0
  305. package/resources/package.json.template +50 -0
  306. package/script/lib.js +24 -0
  307. package/script/post_install.js +449 -157
  308. package/script/pre_install.js +277 -36
  309. package/script/prepare_version.js +425 -0
  310. package/utils/helper.js +438 -0
  311. package/utils/prototypes.js +239 -0
  312. package/utils/prototypes.json_clone.js +175 -0
  313. package/.npmignore +0 -6
  314. package/MIDDLEWARE +0 -1
  315. package/SUCCESS +0 -1
  316. package/VERSION +0 -1
  317. package/core/asset/html/nolayout.html +0 -1
  318. package/core/asset/js/plugin/build.dev.json +0 -28
  319. package/core/asset/js/plugin/build.json +0 -31
  320. package/core/asset/js/plugin/dist/gina.min.css +0 -1
  321. package/core/asset/js/plugin/dist/gina.min.css.map +0 -1
  322. package/core/asset/js/plugin/dist/gina.min.js +0 -13731
  323. package/core/asset/js/plugin/dist/gina.min.js.map +0 -42
  324. package/core/asset/js/plugin/dist/gina.onload.min.js +0 -3
  325. package/core/asset/js/plugin/dist/gina.onload.min.js.map +0 -8
  326. package/core/asset/js/plugin/readme.md +0 -152
  327. package/core/asset/js/plugin/src/gina/main.js +0 -132
  328. package/core/asset/js/plugin/src/gina/popin/css/design.css +0 -23
  329. package/core/asset/js/plugin/src/gina/popin/css/main.css +0 -1112
  330. package/core/asset/js/plugin/src/gina/popin/css/popin.css +0 -3
  331. package/core/asset/js/plugin/src/gina/popin/css/popin.css.map +0 -1
  332. package/core/asset/js/plugin/src/gina/popin/doc/TOC.md +0 -29
  333. package/core/asset/js/plugin/src/gina/popin/doc/css.md +0 -162
  334. package/core/asset/js/plugin/src/gina/popin/doc/extend.md +0 -663
  335. package/core/asset/js/plugin/src/gina/popin/doc/faq.md +0 -46
  336. package/core/asset/js/plugin/src/gina/popin/doc/html.md +0 -227
  337. package/core/asset/js/plugin/src/gina/popin/doc/js.md +0 -37
  338. package/core/asset/js/plugin/src/gina/popin/doc/misc.md +0 -178
  339. package/core/asset/js/plugin/src/gina/popin/doc/usage.md +0 -130
  340. package/core/asset/js/plugin/src/gina/popin/main.js +0 -783
  341. package/core/asset/js/plugin/src/gina/popin/sass/config.sass +0 -37
  342. package/core/asset/js/plugin/src/gina/popin/sass/gina-design.sass +0 -622
  343. package/core/asset/js/plugin/src/gina/popin/sass/gina-popin.sass +0 -54
  344. package/core/asset/js/plugin/src/gina/popin/sass/helper.scss +0 -73
  345. package/core/asset/js/plugin/src/gina/toolbar/.npmignore +0 -19
  346. package/core/asset/js/plugin/src/gina/toolbar/css/toolbar.css +0 -433
  347. package/core/asset/js/plugin/src/gina/toolbar/css/toolbar.css.map +0 -1
  348. package/core/asset/js/plugin/src/gina/toolbar/index.html +0 -285
  349. package/core/asset/js/plugin/src/gina/toolbar/index.kit +0 -120
  350. package/core/asset/js/plugin/src/gina/toolbar/jquery-3.1.0.min.js +0 -4
  351. package/core/asset/js/plugin/src/gina/toolbar/main.js +0 -693
  352. package/core/asset/js/plugin/src/gina/toolbar/mock.gina.json +0 -1
  353. package/core/asset/js/plugin/src/gina/toolbar/mock.user.json +0 -1
  354. package/core/asset/js/plugin/src/gina/toolbar/readme.md +0 -7
  355. package/core/asset/js/plugin/src/gina/toolbar/sass/toolbar.sass +0 -563
  356. package/core/asset/js/plugin/src/gina/toolbar/svg-src/Info-color.svg +0 -1
  357. package/core/asset/js/plugin/src/gina/toolbar/svg-src/Info-grey.svg +0 -1
  358. package/core/asset/js/plugin/src/gina/toolbar/svg-src/error-color.svg +0 -1
  359. package/core/asset/js/plugin/src/gina/toolbar/svg-src/error-grey.svg +0 -1
  360. package/core/asset/js/plugin/src/gina/toolbar/svg-src/info-optim.svg +0 -13
  361. package/core/asset/js/plugin/src/gina/toolbar/svg-src/logo-gina.svg +0 -1
  362. package/core/asset/js/plugin/src/gina/toolbar/svg-src/settings-big.svg +0 -1
  363. package/core/asset/js/plugin/src/gina/toolbar/svg-src/settings.afdesign +0 -0
  364. package/core/asset/js/plugin/src/gina/toolbar/svg-src/settings.svg +0 -1
  365. package/core/asset/js/plugin/src/gina/toolbar/svg-src/stripe-calendar-optim.svg +0 -1
  366. package/core/asset/js/plugin/src/gina/toolbar/svg-src/stripe-calendar.svg +0 -1
  367. package/core/asset/js/plugin/src/gina/toolbar/svg-src/stripe-card-optim.svg +0 -1
  368. package/core/asset/js/plugin/src/gina/toolbar/svg-src/stripe-card.svg +0 -1
  369. package/core/asset/js/plugin/src/gina/toolbar/svg-src/stripe-lock-optim.svg +0 -1
  370. package/core/asset/js/plugin/src/gina/toolbar/svg-src/stripe-lock.svg +0 -1
  371. package/core/asset/js/plugin/src/gina/toolbar/svg-src/warning-color.svg +0 -1
  372. package/core/asset/js/plugin/src/gina/toolbar/svg-src/warning-grey.svg +0 -1
  373. package/core/asset/js/plugin/src/gina/toolbar/test.jpg +0 -0
  374. package/core/asset/js/plugin/src/gina/toolbar/toolbar.html +0 -104
  375. package/core/asset/js/plugin/src/gina/utils/dom.js +0 -24
  376. package/core/asset/js/plugin/src/gina/utils/events.js +0 -201
  377. package/core/asset/js/plugin/src/gina/utils/loader.js +0 -57
  378. package/core/asset/js/plugin/src/main.js +0 -235
  379. package/core/asset/js/plugin/src/vendor/jquery/1.11.1-css-event_alias.min.js +0 -5
  380. package/core/asset/js/plugin/src/vendor/jquery/1.12.4.min.js +0 -5
  381. package/core/asset/js/plugin/src/vendor/jquery/2.1.1-css-event_alias-sizzle.min.js +0 -4
  382. package/core/asset/js/plugin/src/vendor/jquery/README.md +0 -14
  383. package/core/asset/js/plugin/src/vendor/jquery/slim-3.1.1.min.js +0 -4
  384. package/core/config.js +0 -1225
  385. package/core/controller/controller.js +0 -1860
  386. package/core/gna.js +0 -908
  387. package/core/plugins/lib/validator/src/form-validator.js +0 -788
  388. package/core/plugins/lib/validator/src/main.js +0 -2056
  389. package/core/router.js +0 -717
  390. package/core/server.js +0 -1363
  391. package/core/template/conf/env.json +0 -70
  392. package/core/template/conf/settings.json +0 -48
  393. package/core/template/conf/statics.json +0 -6
  394. package/core/template/conf/views.json +0 -16
  395. package/core/template/samples/bundle/config/app.json +0 -4
  396. package/core/template/samples/bundle/config/routing.json +0 -9
  397. package/core/template/samples/bundle/controllers/setup.js +0 -33
  398. package/core/template/views/js/vendor/readme.md +0 -1
  399. package/core/template/views/readme.md +0 -1
  400. package/core/utils/helpers/dateFormat.js +0 -264
  401. package/core/utils/helpers/index.js +0 -202
  402. package/core/utils/index.js +0 -75
  403. package/core/utils/lib/cmd/app.js +0 -686
  404. package/core/utils/lib/cmd/basic.help.txt +0 -40
  405. package/core/utils/lib/cmd/basic.js +0 -141
  406. package/core/utils/lib/cmd/gina-add-bundle.js +0 -328
  407. package/core/utils/lib/cmd/gina-add-views.js +0 -99
  408. package/core/utils/lib/cmd/gina-build.js +0 -218
  409. package/core/utils/lib/cmd/gina-clean.js +0 -26
  410. package/core/utils/lib/cmd/gina-connect.js +0 -176
  411. package/core/utils/lib/cmd/gina-delete-bundle.js +0 -176
  412. package/core/utils/lib/cmd/gina-deploy.js +0 -452
  413. package/core/utils/lib/cmd/gina-init-project.js +0 -83
  414. package/core/utils/lib/cmd/gina-start-bundle.js +0 -3
  415. package/core/utils/lib/cmd/gina-start.js +0 -3
  416. package/core/utils/lib/cmd/index.js +0 -157
  417. package/core/utils/lib/cmd/project.js +0 -14
  418. package/core/utils/lib/collection/src/main.js +0 -650
  419. package/core/utils/lib/logger/containers/file.js +0 -11
  420. package/core/utils/lib/logger/index.js +0 -260
  421. package/core/utils/lib/merge/src/main.js +0 -344
  422. package/core/utils/lib/proc.js +0 -416
  423. package/core/utils/lib/routing/src/main.js +0 -165
  424. package/documentation/css/default.css +0 -3
  425. package/documentation/html/home.html +0 -6
  426. package/documentation/html/inc/_footer.html +0 -5
  427. package/documentation/html/layout.html +0 -21
  428. package/documentation/img/debug-conf1.png +0 -0
  429. package/documentation/img/debug-conf2.png +0 -0
  430. package/documentation/img/debug-conf3.png +0 -0
  431. package/documentation/img/debug-conf4.png +0 -0
  432. package/documentation/img/debug-conf5.png +0 -0
  433. package/documentation/img/debug-conf6.png +0 -0
  434. package/documentation/img/debug-conf7.png +0 -0
  435. package/documentation/img/debug-new1.png +0 -0
  436. package/documentation/img/debug-new2.png +0 -0
  437. package/documentation/img/debug-start.png +0 -0
  438. package/documentation/md/api/controller/main.md +0 -74
  439. package/migration_note.md +0 -7
  440. package/package-lock.json +0 -611
  441. package/script/pre_publish.js +0 -207
  442. package/tutorial/Commands/README.md +0 -56
  443. package/tutorial/Commands/add-bundle-result.png +0 -0
  444. package/tutorial/Commands/add-bundle.png +0 -0
  445. package/tutorial/Commands/delete-bundle.png +0 -0
  446. package/tutorial/Commands/help.png +0 -0
  447. package/tutorial/Commands/init-project.png +0 -0
  448. package/tutorial/Commands/start-bundle-result.png +0 -0
  449. package/tutorial/Commands/start-bundle-stop.png +0 -0
  450. package/tutorial/Commands/start-bundle.png +0 -0
  451. package/tutorial/Commands/version.png +0 -0
  452. package/tutorial/ETC/README.md +0 -74
  453. package/tutorial/ETC/add-bundle-result.png +0 -0
  454. package/tutorial/ETC/add-bundle.png +0 -0
  455. package/tutorial/ETC/init-project.png +0 -0
  456. package/tutorial/Install/README.md +0 -54
  457. package/tutorial/Install/git-get.png +0 -0
  458. package/tutorial/Install/git-install-end.png +0 -0
  459. package/tutorial/Install/git-install-result.png +0 -0
  460. package/tutorial/Install/git-install-start.png +0 -0
  461. package/tutorial/Install/install-end.png +0 -0
  462. package/tutorial/Install/install-result.png +0 -0
  463. package/tutorial/Install/install-start.png +0 -0
  464. package/tutorial/WebStorm/README.md +0 -30
  465. package/tutorial/WebStorm/closure-compiler.png +0 -0
  466. package/tutorial/WebStorm/sass.png +0 -0
@@ -0,0 +1,3010 @@
1
+ //"use strict";
2
+ //Imports.
3
+ const fs = require('fs');
4
+ const os = require('os');
5
+ const path = require('path');
6
+ const EventEmitter = require('events').EventEmitter;
7
+ const Busboy = require('./deps/busboy');
8
+ const Stream = require('stream');
9
+ const zlib = require('zlib'); // gzip / deflate
10
+ const util = require('util');
11
+ var https = require('https');
12
+ const sslChecker = require('ssl-checker');
13
+
14
+ const swig = require( _(GINA_FRAMEWORK_DIR +'/node_modules/swig', true) );
15
+ var Config = require('./config');
16
+ var Router = require('./router');
17
+ var lib = require('./../lib');
18
+ var routingUtils = lib.routing;
19
+ var inherits = lib.inherits;
20
+ var merge = lib.merge;
21
+ var Proc = lib.Proc;
22
+ var console = lib.logger;
23
+ var SwigFilters = lib.SwigFilters;
24
+
25
+ function Server(options) {
26
+
27
+ // switching logger flow
28
+ //console.switchFlow('server');
29
+
30
+ var e = new EventEmitter();
31
+ var self = this;
32
+ var local = {
33
+ router : null,
34
+ hasViews: {}
35
+ };
36
+ var Engine = null;
37
+
38
+ this.conf = {
39
+ core: {}
40
+ };
41
+
42
+ this.routing = {};
43
+ //this.activeChild = 0;
44
+
45
+ var initSwigEngine = function(conf) {
46
+ // swig options
47
+ var dir = conf.content.templates._common.html;
48
+ var swigOptions = {
49
+ autoescape: ( typeof(conf.autoescape) != 'undefined') ? conf.autoescape: false,
50
+ loader: swig.loaders.fs(dir),
51
+ cache: (conf.cacheless) ? false : 'memory'
52
+ };
53
+
54
+ swig.setDefaults(swigOptions);
55
+
56
+ var filters = SwigFilters({
57
+ options : conf,
58
+ isProxyHost : getContext('isProxyHost'),
59
+ // throwError : self.throwError,
60
+ // req : local.req,
61
+ // res : local.res
62
+ });
63
+
64
+ try {
65
+ // Allows you to get a bundle web root
66
+ // swig.setFilter('getWebroot', filters.getWebroot);
67
+ // swig.setFilter('nl2br', filters.nl2br);
68
+ for (let filter in filters) {
69
+ if ( typeof(filters[filter]) == 'function' && !/^getConfig$/.test(filter) ) {
70
+ swig.setFilter(filter, filters[filter]);
71
+ }
72
+ }
73
+
74
+ } catch (err) {
75
+ throw err;
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Set Configuration
81
+ * @param {object} options Configuration
82
+ *
83
+ *
84
+ * @callback callback responseCallback
85
+ * @param {boolean} complete
86
+ * @public
87
+ */
88
+ var init = function(options) {
89
+
90
+ self.projectName = options.projectName;
91
+ //Starting app.
92
+ self.appName = options.bundle;
93
+ self.env = options.env;
94
+ self.version = options.version;
95
+ local.router = new Router(self.env);
96
+
97
+ //True => multiple bundles sharing the same server (port).
98
+ self.isStandalone = options.isStandalone;
99
+ self.bundles = options.bundles;
100
+ self.executionPath = options.executionPath;
101
+
102
+
103
+ if (!self.isStandalone) {
104
+ //Only load the related conf / env.
105
+ self.conf[self.appName] = {};
106
+ self.conf[self.appName][self.env] = options.conf[self.appName][self.env];
107
+ self.conf[self.appName][self.env].bundlesPath = options.conf[self.appName][self.env].bundlesPath;
108
+ self.conf[self.appName][self.env].modelsPath = options.conf[self.appName][self.env].modelsPath;
109
+ self.conf[self.appName][self.env].executionPath = options.conf[self.appName][self.env].executionPath = self.executionPath;
110
+ } else {
111
+
112
+ //console.log("Running mode not handled yet..", self.appName, " VS ", self.bundles);
113
+ //Load all conf for the related apps & env.
114
+ var apps = self.bundles;
115
+ for (var i=0; i<apps.length; ++i) {
116
+ self.conf[apps[i]] = {};
117
+ self.conf[apps[i]][self.env] = options.conf[apps[i]][self.env];
118
+ self.conf[apps[i]][self.env].bundlesPath = options.conf[apps[i]][self.env].bundlesPath;
119
+ self.conf[apps[i]][self.env].modelsPath = options.conf[apps[i]][self.env].modelsPath;
120
+ }
121
+ }
122
+
123
+
124
+ try {
125
+
126
+ // updating server protocol
127
+ var serverOpt = {};
128
+ var ioServerOpt = null;
129
+ if ( typeof(options.conf[self.appName][self.env].content.settings.ioServer) != 'undefined' ) {
130
+ ioServerOpt = JSON.clone(options.conf[self.appName][self.env].content.settings.ioServer);
131
+ }
132
+
133
+
134
+ if (
135
+ typeof(options.conf[self.appName][self.env].content.settings.server) != 'undefined'
136
+ && options.conf[self.appName][self.env].content.settings.server != ''
137
+ && options.conf[self.appName][self.env].content.settings.server != null
138
+ ) {
139
+ serverOpt = options.conf[self.appName][self.env].content.settings.server;
140
+ }
141
+
142
+ serverOpt = merge({
143
+ bundle : self.appName,
144
+ env : self.env
145
+ },
146
+ serverOpt,
147
+ {
148
+ engine: options.conf[self.appName][self.env].server.engine,
149
+ protocol: options.conf[self.appName][self.env].server.protocol,
150
+ scheme: options.conf[self.appName][self.env].server.scheme
151
+ }
152
+ );
153
+
154
+ self.engine = serverOpt.engine;
155
+ console.debug('[ BUNDLE ][ server ][ init ] Initializing [ '+ self.appName +' ] server with `'+ serverOpt.engine +'`engine');
156
+
157
+ // controlling one last time protocol & ports
158
+ var ctx = getContext('gina'),
159
+ projectConf = ctx.project,
160
+ //protocols = projectConf.protocols,
161
+ // TODO - check if the user prefered protocol is register in projectConf
162
+ portsReverse = ctx.portsReverse;
163
+
164
+ // locking port & protocol so it can't be changed by the user's settings
165
+ self.conf[self.appName][self.env].server.protocol = serverOpt.protocol;
166
+ self.conf[self.appName][self.env].server.scheme = serverOpt.scheme;
167
+ self.conf[self.appName][self.env].server.engine = serverOpt.engine;
168
+
169
+ serverOpt.port = self.conf[self.appName][self.env].server.port = portsReverse[ self.appName +'@'+ self.projectName ][self.env][serverOpt.protocol][serverOpt.scheme];
170
+ self.conf[self.appName][self.env].server.debugPort = getContext().debugPort;
171
+
172
+ // engine.io options
173
+ if ( ioServerOpt ) {
174
+ serverOpt.ioServer = ioServerOpt
175
+ }
176
+
177
+ Engine = require('./server.' + ((typeof (serverOpt.engine) != 'undefined' && serverOpt.engine != '') ? serverOpt.engine : 'express'));
178
+ var engine = new Engine(serverOpt);
179
+
180
+ // swigEngine to render thrown HTML errors
181
+ if ( hasViews(self.appName) ) {
182
+ initSwigEngine(self.conf[self.appName][self.env]);
183
+ }
184
+
185
+
186
+ // setting timezone
187
+ if (
188
+ typeof(options.conf[self.appName][self.env].content.settings.region) != 'undefined'
189
+ && typeof(options.conf[self.appName][self.env].content.settings.region.timeZone) != 'undefined'
190
+ ) {
191
+ process.env.TZ = options.conf[self.appName][self.env].content.settings.region.timeZone;
192
+ }
193
+
194
+ self.emit('configured', false, engine.instance, engine.middleware, self.conf[self.appName][self.env]);
195
+
196
+ } catch (err) {
197
+
198
+ console.emerg('[ BUNDLE ] [ '+ self.appName +' ] ServerEngine ' + err.stack)
199
+ process.exit(1)
200
+ }
201
+ }
202
+
203
+ this.isCacheless = function() {
204
+ return (/^true$/i.test(process.env.NODE_ENV_IS_DEV)) ? true : false
205
+ }
206
+
207
+ this.onConfigured = function(callback) {
208
+ self.once('configured', function(err, instance, middleware, conf) {
209
+ callback(err, instance, middleware, conf)
210
+ });
211
+
212
+ init(options);
213
+ }
214
+
215
+
216
+ this.verifyCertificate = async function(endpoint, port) {
217
+ let sslDetails = null;
218
+ console.debug('Checking certificate validity...');
219
+ try {
220
+ sslDetails = await sslChecker(endpoint, {
221
+ method: 'GET',
222
+ // rejectUnauthorized: true,
223
+ port: port || 443,
224
+ ca: fs.readFileSync(self.conf[self.appName][self.env].content.settings.server.credentials.ca),
225
+ agent: new https.Agent({
226
+ maxCachedSessions: 0
227
+ })
228
+ });
229
+ } catch (err) {
230
+ console.emerg(sslDetails +'\n'+ err.stack);
231
+ return;
232
+ }
233
+
234
+
235
+ const failed = !sslDetails.valid;
236
+ const humanView = JSON.stringify(sslDetails, null, ' ');
237
+ if (failed) {
238
+ if (sslDetails.daysRemaining > -1) {
239
+ console.emerg(`[Certificate] ${endpoint} : It is like there is a problem with your CA certificate${'\n'} ${humanView}`);
240
+ return;
241
+ }
242
+ console.emerg(`[Certificate] ${endpoint} has no valid certificate: ${'\n'} ${humanView}`);
243
+ return;
244
+ }
245
+ }
246
+
247
+ this.start = function(instance) {
248
+ if (instance) {
249
+ self.instance = instance;
250
+ //Router configuration.
251
+ var router = local.router;
252
+
253
+ instance.throwError = throwError;
254
+ instance.getAssets = getAssets;
255
+ instance.completeHeaders = completeHeaders;
256
+
257
+ router.setServerInstance(instance);
258
+ }
259
+
260
+ onRequest()
261
+ }
262
+
263
+
264
+
265
+ /**
266
+ * onRoutesLoaded
267
+ *
268
+ *
269
+ * */
270
+ var onRoutesLoaded = function(callback) {
271
+
272
+ var config = new Config()
273
+ , conf = config.getInstance(self.appName)
274
+ , serverCoreConf = self.conf.core
275
+ , routing = {}
276
+ , reverseRouting = {}
277
+ , cacheless = config.isCacheless()
278
+ , env = self.env
279
+ , apps = conf.allBundles//conf.bundles
280
+ , filename = ''
281
+ , appName = ''
282
+ , tmp = {}
283
+ , standaloneTmp = {}
284
+ , main = ''
285
+ , tmpContent = ''
286
+ , i = 0
287
+ , file = null // template file
288
+ , wroot = null
289
+ , hasWebRoot = false
290
+ , webrootAutoredirect = null
291
+ , localWroot = null
292
+ , originalRules = []
293
+ , oRuleCount = 0;
294
+
295
+ //Standalone or shared instance mode. It doesn't matter.
296
+ for (; i<apps.length; ++i) {
297
+ config.setServerCoreConf(apps[i], self.env, serverCoreConf);
298
+
299
+ var appPath = _(conf.envConf[apps[i]][self.env].bundlesPath+ '/' + apps[i]);
300
+ appName = apps[i];
301
+
302
+ //Specific case.
303
+ if (!self.isStandalone && i == 0) appName = apps[i];
304
+
305
+ try {
306
+ main = _(appPath + '/config/' + conf.envConf[apps[i]][self.env].configFiles.routing);
307
+ filename = main;//by default
308
+ filename = conf.envConf[apps[i]][self.env].configFiles.routing.replace(/.json/, '.' +env + '.json');
309
+ filename = _(appPath + '/config/' + filename);
310
+ //Can't do a thing without.
311
+ if ( !fs.existsSync(filename) ) {
312
+ filename = main
313
+ }
314
+
315
+ if (cacheless) {
316
+ delete require.cache[require.resolve(_(filename, true))]
317
+ }
318
+
319
+ if (filename != main) {
320
+ routing = tmpContent = merge(require(main), require(filename), true);
321
+
322
+ } else {
323
+ try {
324
+ tmpContent = require(filename);
325
+ } catch (err) {
326
+ // do not block here because the bundle is not build for the same env
327
+ console.warn(err.stack);
328
+ continue
329
+ }
330
+ }
331
+
332
+ try {
333
+
334
+ wroot = conf.envConf[apps[i]][self.env].server.webroot;
335
+ webrootAutoredirect = conf.envConf[apps[i]][self.env].server.webrootAutoredirect;
336
+ // renaming rule for standalone setup
337
+ if ( self.isStandalone && apps[i] != self.appName && wroot == '/') {
338
+ wroot = '/'+ apps[i];
339
+ conf.envConf[apps[i]][self.env].server.webroot = wroot
340
+ }
341
+
342
+ if (wroot.length >1) {
343
+ hasWebRoot = true
344
+ } else {
345
+ hasWebRoot = false
346
+ }
347
+
348
+ tmp = tmpContent;
349
+ //Adding important properties; also done in core/config.
350
+ for (var rule in tmp){
351
+ tmp[rule.toLowerCase() +'@'+ appName] = tmp[rule];
352
+ delete tmp[rule];
353
+ file = ruleShort = rule.toLowerCase();
354
+ rule = rule.toLowerCase() +'@'+ appName;
355
+
356
+
357
+ tmp[rule].bundle = (tmp[rule].bundle) ? tmp[rule].bundle : apps[i]; // for reverse search
358
+ tmp[rule].param.file = ( typeof(tmp) != 'string' && typeof(tmp[rule].param.file) != 'undefined' ) ? tmp[rule].param.file : file; // get template file
359
+ // by default, method is inherited from the request
360
+ if (
361
+ hasWebRoot && typeof(tmp[rule].param.path) != 'undefined' && typeof(tmp[rule].param.ignoreWebRoot) == 'undefined'
362
+ || hasWebRoot && typeof(tmp[rule].param.path) != 'undefined' && !tmp[rule].param.ignoreWebRoot
363
+ ) {
364
+ tmp[rule].param.path = wroot + tmp[rule].param.path
365
+ }
366
+
367
+ if (typeof(tmp[rule].url) != 'object') {
368
+ if (tmp[rule].url.length > 1 && tmp[rule].url.substr(0,1) != '/') {
369
+ tmp[rule].url = '/'+tmp[rule].url
370
+ }/** else if (tmp[rule].url.length > 1 && conf.envConf[apps[i]][self.env].server.webroot.substr(conf.envConf[apps[i]][self.env].server.webroot.length-1,1) == '/') {
371
+ tmp[rule].url = tmp[rule].url.substr(1)
372
+ }*/ else {
373
+ if (wroot.substr(wroot.length-1,1) == '/') {
374
+ wroot = wroot.substr(wroot.length-1,1).replace('/', '')
375
+ }
376
+ }
377
+
378
+
379
+ if (tmp[rule].bundle != apps[i]) { // allowing to override bundle name in routing.json
380
+ // originalRule is used to facilitate cross bundles (hypertext)linking
381
+ originalRules[oRuleCount] = ( self.isStandalone && tmp[rule] && apps[i] != self.appName) ? apps[i] + '-' + rule : rule;
382
+ ++oRuleCount;
383
+
384
+ localWroot = conf.envConf[tmp[rule].bundle][self.env].server.webroot;
385
+ // standalone setup
386
+ if ( self.isStandalone && tmp[rule].bundle != self.appName && localWroot == '/') {
387
+ localWroot = '/'+ routing[rule].bundle;
388
+ conf.envConf[tmp[rule].bundle][self.env].server.webroot = localWroot
389
+ }
390
+ if (localWroot.substr(localWroot.length-1,1) == '/') {
391
+ localWroot = localWroot.substr(localWroot.length-1,1).replace('/', '')
392
+ }
393
+ if ( typeof(tmp[rule].param.ignoreWebRoot) == 'undefined' || !tmp[rule].param.ignoreWebRoot )
394
+ tmp[rule].url = localWroot + tmp[rule].url
395
+ } else {
396
+ if ( typeof(tmp[rule].param.ignoreWebRoot) == 'undefined' || !tmp[rule].param.ignoreWebRoot )
397
+ tmp[rule].url = wroot + tmp[rule].url
398
+ else if (!tmp[rule].url.length)
399
+ tmp[rule].url += '/'
400
+ }
401
+
402
+ } else {
403
+
404
+ for (var u=0; u<tmp[rule].url.length; ++u) {
405
+ if (tmp[rule].url[u].length > 1 && tmp[rule].url[u].substr(0,1) != '/') {
406
+ tmp[rule].url[u] = '/'+tmp[rule].url[u]
407
+ } else {
408
+ if (wroot.substr(wroot.length-1,1) == '/') {
409
+ wroot = wroot.substr(wroot.length-1,1).replace('/', '')
410
+ }
411
+ }
412
+ if ( typeof(tmp[rule].param.ignoreWebRoot) == 'undefined' || !tmp[rule].param.ignoreWebRoot )
413
+ tmp[rule].url[u] = wroot + tmp[rule].url[u]
414
+ else if (!tmp[rule].url.length)
415
+ tmp[rule].url += '/'
416
+ }
417
+ }
418
+
419
+ if( hasViews(apps[i]) ) {
420
+ // This is only an issue when it comes to the frontend dev
421
+ // views.routeNameAsFilenameEnabled is set to true by default
422
+ // IF [ false ] the action is used as filename
423
+ if ( !conf.envConf[apps[i]][self.env].content.templates['_common'].routeNameAsFilenameEnabled && tmp[rule].param.bundle != 'framework') {
424
+ var tmpRouting = [];
425
+ for (var r = 0, len = tmp[rule].param.file.length; r < len; ++r) {
426
+ if (/[A-Z]/.test(tmp[rule].param.file.charAt(r))) {
427
+ tmpRouting[0] = tmp[rule].param.file.substring(0, r);
428
+ tmpRouting[1] = '-' + (tmp[rule].param.file.charAt(r)).toLocaleLowerCase();
429
+ tmpRouting[2] = tmp[rule].param.file.substring(r + 1);
430
+ tmp[rule].param.file = tmpRouting[0] + tmpRouting[1] + tmpRouting[2];
431
+ ++r
432
+ }
433
+ }
434
+ }
435
+ }
436
+
437
+ if ( self.isStandalone && tmp[rule]) {
438
+ standaloneTmp[rule] = JSON.clone(tmp[rule]);
439
+ }
440
+ }// EO for
441
+
442
+
443
+ } catch (err) {
444
+ self.routing = routing = null;
445
+ console.error(err.stack||err.message);
446
+ callback(err)
447
+ }
448
+
449
+ } catch (err) {
450
+ console.warn(err, err.stack||err.message);
451
+ callback(err)
452
+ }
453
+
454
+
455
+ routing = merge(routing, ((self.isStandalone && apps[i] != self.appName ) ? standaloneTmp : tmp), true);
456
+ // originalRule is used to facilitate cross bundles (hypertext)linking
457
+ for (let r = 0, len = originalRules.length; r < len; r++) { // for each rule ( originalRules[r] )
458
+ routing[originalRules[r]].originalRule = (routing[originalRules[r]].bundle === self.appName ) ? config.getOriginalRule(originalRules[r], routing) : config.getOriginalRule(routing[originalRules[r]].bundle +'-'+ originalRules[r], routing)
459
+ }
460
+
461
+ // reverse routing
462
+ for (let rule in routing) {
463
+ if ( typeof(routing[rule].url) != 'object' ) {
464
+ reverseRouting[routing[rule].url] = rule
465
+ } else {
466
+ for (let u = 0, len = routing[rule].url.length; u < len; ++u) {
467
+ reverseRouting[routing[rule].url[u]] = rule
468
+ }
469
+ }
470
+ }
471
+
472
+ config.setRouting(apps[i], self.env, routing);
473
+ config.setReverseRouting(apps[i], self.env, reverseRouting);
474
+
475
+ if (apps[i] == self.appName) {
476
+ self.routing = routing;
477
+ self.reverseRouting = reverseRouting
478
+ }
479
+
480
+ }//EO for.
481
+
482
+
483
+ callback(false)
484
+ }
485
+
486
+ var hasViews = function(bundle) {
487
+ var _hasViews = false, conf = new Config().getInstance(bundle);
488
+ if (typeof(local.hasViews[bundle]) != 'undefined') {
489
+ _hasViews = local.hasViews[bundle];
490
+ } else {
491
+ _hasViews = ( typeof(conf.envConf[bundle][self.env].content['templates']) != 'undefined' ) ? true : false;
492
+ local.hasViews[bundle] = _hasViews;
493
+ }
494
+
495
+ return _hasViews
496
+ }
497
+
498
+ var parseCollection = function (collection, obj) {
499
+
500
+ for(var i = 0, len = collection.length; i<len; ++i) {
501
+ obj[i] = parseObject(collection[i], obj);
502
+ }
503
+
504
+ return obj
505
+ }
506
+
507
+ var parseObject = function (tmp, obj) {
508
+ var el = []
509
+ , key = null
510
+ ;
511
+
512
+ for (var o in tmp) {
513
+
514
+ el[0] = o;
515
+ el[1] = tmp[o];
516
+
517
+ if ( /^(.*)\[(.*)\]/.test(el[0]) ) { // some[field] ?
518
+ key = el[0].replace(/\]/g, '').split(/\[/g);
519
+ obj = parseLocalObj(obj, key, 0, el[1])
520
+ } else {
521
+ obj[ el[0] ] = el[1]
522
+ }
523
+ }
524
+
525
+ return obj
526
+ }
527
+
528
+ var parseBody = function(body) {
529
+ var obj = null, tmp = null, arr = null;
530
+ if ( /^(\{|\[|\%7B|\%5B)/.test(body) ) {
531
+ try {
532
+ obj = {};
533
+
534
+ if ( /^(\%7B|\%5B)/.test(body) ) {
535
+ tmp = JSON.parse(decodeURIComponent(body))
536
+ } else {
537
+ tmp = JSON.parse(body)
538
+ }
539
+
540
+ if ( Array.isArray(tmp) ) {
541
+ obj = parseCollection(tmp, obj)
542
+ } else {
543
+ obj = parseObject(tmp, obj)
544
+ }
545
+
546
+ return obj
547
+ } catch (err) {
548
+ console.error('[365] could not parse body:\n' + body)
549
+ }
550
+
551
+ } else {
552
+ obj = {};
553
+ arr = body.split(/&/g);
554
+ if ( /(\"false\"|\"true\"|\"on\")/.test(body) )
555
+ body = body.replace(/\"false\"/g, false).replace(/\"true\"/g, true).replace(/\"on\"/g, true);
556
+
557
+
558
+ var el = {}
559
+ , value = null
560
+ , key = null;
561
+
562
+ for (var i = 0, len = arr.length; i < len; ++i) {
563
+ if (!arr[i]) continue;
564
+
565
+ arr[i] = decodeURIComponent(arr[i]);
566
+
567
+ if ( /^\{/.test(arr[i]) || /\=\{/.test(arr[i]) || /\=\[/.test(arr[i]) ) {
568
+ //if ( /^\{/.test(arr[i]) ) { // is a json string
569
+ try {
570
+ if (/^\{/.test(arr[i])) {
571
+ obj = JSON.parse(arr[i]);
572
+ break;
573
+ } else {
574
+ el = arr[i].match(/\=(.*)/);
575
+ el[0] = arr[i].split(/\=/)[0];
576
+ obj[ el[0] ] = JSON.parse( el[1] );
577
+ }
578
+
579
+
580
+ } catch (err) {
581
+ console.error('[parseBody#1] could not parse body:\n' + arr[i])
582
+ }
583
+ } else {
584
+ el = arr[i].split(/=/);
585
+ if ( /\{\}\"\:/.test(el[1]) ) { //might be a json
586
+ try {
587
+ el[1] = JSON.parse(el[1])
588
+ } catch (err) {
589
+ console.error('[parseBody#2] could not parse body:\n' + el[1])
590
+ }
591
+ }
592
+
593
+ if ( typeof(el[1]) == 'string' && !/\[object /.test(el[1])) {
594
+ key = null;
595
+ el[0] = decodeURIComponent(el[0]);
596
+ el[1] = decodeURIComponent(el[1]);
597
+
598
+ if ( /^(.*)\[(.*)\]/.test(el[0]) ) { // some[field] ?
599
+ key = el[0].replace(/\]/g, '').split(/\[/g);
600
+ obj = parseLocalObj(obj, key, 0, el[1])
601
+ } else {
602
+ obj[ el[0] ] = el[1]
603
+ }
604
+ }
605
+ }
606
+ }
607
+
608
+ return obj
609
+ }
610
+
611
+
612
+ }
613
+
614
+ var parseLocalObj = function(obj, key, k, value) {
615
+
616
+ if ( typeof(obj[ key[k] ]) == 'undefined' ) {
617
+ obj[ key[k] ] = {};
618
+ }
619
+
620
+ for (var prop in obj) {
621
+
622
+ if (k == key.length-1) {
623
+
624
+ if (prop == key[k]) {
625
+ obj[prop] = ( typeof(value) != 'undefined' ) ? value : '';
626
+ }
627
+
628
+ } else if ( key.indexOf(prop) > -1 ) {
629
+ ++k;
630
+ if ( !obj[prop][ key[k] ] )
631
+ obj[prop][ key[k] ] = {};
632
+
633
+
634
+ parseLocalObj(obj[prop], key, k, value)
635
+
636
+ }
637
+ }
638
+
639
+ return obj;
640
+ }
641
+
642
+ var getAssetFilenameFromUrl = function(bundleConf, url) {
643
+
644
+ var staticsArr = bundleConf.publicResources;
645
+ url = decodeURIComponent( url );
646
+ var staticProps = {
647
+ firstLevel : '/'+ url.split(/\//g)[1] + '/',
648
+ isFile : /^\/[A-Za-z0-9_-]+\.(.*)$/.test(url)
649
+ };
650
+ var notFound = '404.html'
651
+
652
+ var filename = null
653
+ , path = null
654
+ , altConf = ( typeof(staticProps.firstLevel) != 'undefined' && typeof(self.conf.reverseRouting) != 'undefined' ) ? self.conf.reverseRouting[staticProps.firstLevel] : false
655
+ , backedupPath = null
656
+ ;
657
+ if (
658
+ staticProps.isFile && staticsArr.indexOf(url) > -1
659
+ || staticsArr.indexOf(staticProps.firstLevel) > -1
660
+ || typeof(altConf) != 'undefined' && altConf
661
+ ) {
662
+
663
+ // by default
664
+ path = url.replace(url.substr(url.lastIndexOf('/')+1), '');
665
+ if ( typeof(altConf) != 'undefined' && altConf ) {
666
+ bundleConf = self.conf[altConf.split(/\@/)[1]][bundleConf.env];
667
+ backedupPath = path;
668
+ path = path.replace(staticProps.firstLevel, '/');
669
+ }
670
+
671
+
672
+ // catch `statics.json` defined paths || bundleConf.staticResources.indexOf(url.replace(url.substr(url.lastIndexOf('/')+1), '')) > -1
673
+ if ( bundleConf.staticResources.indexOf(path) > -1 || bundleConf.staticResources.indexOf(staticProps.firstLevel) > -1 ) {
674
+ if ( typeof(altConf) != 'undefined' && altConf && backedupPath ) {
675
+ filename = (bundleConf.staticResources.indexOf(path) > -1) ? bundleConf.content.statics[path] + url.replace(backedupPath, '/') : bundleConf.content.statics[staticProps.firstLevel] + url.replace(staticProps.firstLevel, '/');
676
+ } else {
677
+ filename = (bundleConf.staticResources.indexOf(path) > -1) ? bundleConf.content.statics[path] + url.replace(path, '/') : bundleConf.content.statics[staticProps.firstLevel] + url.replace(staticProps.firstLevel, '/');
678
+ }
679
+ } else {
680
+ filename = ( bundleConf.staticResources.indexOf(url) > -1 ) ? bundleConf.content.statics[url] : bundleConf.publicPath + url;
681
+ }
682
+
683
+
684
+ if ( !fs.existsSync(filename) )
685
+ return notFound;
686
+
687
+ return filename
688
+
689
+ } else {
690
+ return notFound
691
+ }
692
+ }
693
+
694
+ var readFromUrl = function(url, encoding) {
695
+ return new (require('httpclient').HttpClient)({
696
+ method: 'GET',
697
+ url: url
698
+ }).finish().body.read().decodeToString();
699
+ }
700
+
701
+ /**
702
+ * Get Assets
703
+ *
704
+ * @param {object} bundleConf
705
+ * @param {string} layoutStr
706
+ * @param {object} [swig] - when called from controller
707
+ * @param {object} [data] - when called from controller
708
+ */
709
+ var getAssets = function (bundleConf, layoutStr, swig, data) {
710
+
711
+ // layout search for <link|script|img>
712
+ var layoutAssets = layoutStr.match(/<link .*?<\/link>|<link .*?(rel\=\"(stylesheet|icon|manifest|(.*)\-icon))(.*)|<script.*?<\/script>|<img .*?(.*)/g) || [];
713
+
714
+ var assets = {}
715
+ , cssFiles = []
716
+ , aCount = 0
717
+ , i = 0
718
+ , len = 0
719
+ , domain = null
720
+ , key = null // [ code ] url
721
+ , ext = null
722
+ , url = null
723
+ , filename = null
724
+ ;
725
+
726
+ // user's defineds assets
727
+ var layoutClasses = [];
728
+
729
+ // layout assets
730
+ i = 0;
731
+ len = layoutAssets.length;
732
+ var type = null
733
+ , isAvailable = null
734
+ , tag = null
735
+ , properties = null
736
+ , p = 0
737
+ , pArr = []
738
+ ;
739
+ for (; i < len; ++i) {
740
+
741
+ if (
742
+ !/(\<img|\<link|\<script)/g.test(layoutAssets[i])
743
+ || /\<img/.test(layoutAssets[i]) && /srcset/.test(layoutAssets[i]) // not able to handle this case for now
744
+ ) {
745
+ continue;
746
+ }
747
+
748
+ if ( /\<img/.test(layoutAssets[i]) ) {
749
+ type = 'image';
750
+ tag = 'img';
751
+ }
752
+
753
+ if ( /\<script/.test(layoutAssets[i]) ) {
754
+ type = 'javascript';
755
+ tag = 'script';
756
+ }
757
+
758
+ if ( /\<link/.test(layoutAssets[i]) ) {
759
+ if ( /rel\=\"stylesheet/.test(layoutAssets[i]) ) {
760
+ type = 'stylesheet';
761
+ } else if ( /rel\=\"(icon|(.*)\-icon)/.test(layoutAssets[i]) ) {
762
+ type = 'image';
763
+ } else {
764
+ type = 'file';
765
+ }
766
+
767
+ tag = 'link';
768
+ }
769
+
770
+ domain = null;
771
+ try {
772
+ url = layoutAssets[i].match(/(src|href)\=(\".*?\"|\'.*?\')/)[0];
773
+ } catch (err) {
774
+ console.warn('Problem with this asset ('+ i +'/'+ len +'): '+ layoutAssets[i].substr(0, 80) +'...');
775
+ continue;
776
+ }
777
+
778
+
779
+ if ( /data\:/.test(url) ) { // ignoring "data:..."
780
+ continue
781
+ }
782
+ //url = url.replace(/((src|href)\=\"|(src|href)\=\'|\"|\')/g, '');
783
+ url = url.replace(/((src|href)\=\"|(src|href)\=\')/g, '');
784
+ if ( !/^\{\{/.test(url) ) {
785
+ url = url.replace(/(\"|\')/g, '');
786
+ }
787
+ if (swig && /^\{\{/.test(url) )
788
+ url = swig.compile(url, swig.getOptions())(data);
789
+
790
+ if (!/(\:\/\/|^\/\/)/.test(url) ) {
791
+ filename = getAssetFilenameFromUrl(bundleConf, url);
792
+ } else {
793
+ domain = url.match(/^.*:\/\/[a-z0-9._-]+\/?/);
794
+ //url = ( new RegExp('/'+ bundleConf.host +'/' ).test(domain) ) ? url.replace(domain, '/') : url;
795
+
796
+ if ( ! new RegExp('/'+ bundleConf.host +'/' ).test(domain) ) {
797
+ continue;
798
+ }
799
+
800
+ url = url.replace(domain, '/');
801
+ filename = url
802
+ }
803
+ //key = (( /404/.test(filename) ) ? '[404]' : '[200]') +' '+ url;
804
+ key = url;
805
+ isAvailable = ( /404/.test(filename) ) ? false : true;
806
+ if ( isAvailable ) {
807
+ try {
808
+ ext = url.substr(url.lastIndexOf('.')).match(/(\.[A-Za-z0-9]+)/)[0];
809
+ } catch(err) {
810
+
811
+ console.warn('No extension found for `'+ filename +'`\n'+ err.stack );
812
+ ext = null
813
+ }
814
+ }
815
+
816
+
817
+ assets[key] = {
818
+ type : type,
819
+ url : url,
820
+ ext : ext,
821
+ mime : (!ext) ? 'NA' : (bundleConf.server.coreConfiguration.mime[ext.substr(1)] || 'NA'),
822
+ filename : ( /404/.test(filename) ) ? 'not found' : filename,
823
+ isAvailable : isAvailable
824
+ };
825
+
826
+ if (domain)
827
+ assets[key].domain = domain;
828
+
829
+ if ( type == 'stylesheet' && !/not found/.test(assets[key].filename) ) {
830
+ cssFiles.push(assets[key].filename)
831
+ }
832
+
833
+ properties = layoutAssets[i].replace( new RegExp('(\<'+ tag +'\\s+|\>|\/\>|\<\/'+ tag +'\>)', 'g'), '').replace(/[A-Za-z]+\s+/, '$&="true" ').split(/\"\s+/g);
834
+ p = 0;
835
+
836
+ for (; p < properties.length; ++p ) {
837
+
838
+ pArr = properties[p].split(/\=/g);
839
+ if ( /(src|href)/.test(pArr[0]) )
840
+ continue;
841
+
842
+ assets[key][pArr[0]] = (pArr[1]) ? pArr[1].replace(/\"/g, '') : pArr[1];
843
+ }
844
+ //++aCount
845
+ }
846
+
847
+ // getting layout css classes in order to retrieve active css assets from <asset>.css
848
+ var classesArr = layoutStr.match(/class=\"([A-Za-z0-9_-\s+]+)\"?/g);
849
+
850
+ if ( classesArr ) {
851
+ var cCount = 0
852
+ , cArr = null
853
+ , cArrI = null
854
+ , cArrLen = null
855
+ ;
856
+ i = 0;
857
+ len = classesArr.length;
858
+ for (; i < len; ++i) {
859
+ classesArr[i] = classesArr[i].replace(/(\"|class\=)/g, '').trim();
860
+
861
+ if ( /\s+/g.test(classesArr[i]) ) {
862
+ cArrI = 0;
863
+ cArr = classesArr[i].replace(/\s+/g, ',').split(/\,/g);
864
+ //cArr = classesArr[i].split(/\s+/g);
865
+ cArrLen = cArr.length;
866
+
867
+ for (; cArrI < cArrLen; ++cArrI) {
868
+
869
+ if ( layoutClasses.indexOf( cArr[cArrI] ) < 0) {
870
+ layoutClasses[cCount] = cArr[cArrI];
871
+
872
+ ++cCount
873
+ }
874
+ }
875
+ continue;
876
+ }
877
+
878
+ if ( layoutClasses.indexOf( classesArr[i] ) < 0) {
879
+ layoutClasses[cCount] = classesArr[i];
880
+ ++cCount
881
+ }
882
+ }
883
+ assets._classes = {
884
+ total: layoutClasses.length,
885
+ list: layoutClasses.join(', ')
886
+ };
887
+
888
+ // parsing css files
889
+ i = 0, len = cssFiles.length;
890
+ var cssContent = null
891
+ , hasUrls = null
892
+ , definition = null
893
+ , defName = null
894
+ , d = null
895
+ , dLen = null
896
+ , cssMatched = null
897
+ ;
898
+ var cssArr = null, classNames = null, assetsInClassFound = {};
899
+ for (; i < len; ++i) {
900
+ //if ( /^(http|https)\:/.test(cssFiles[i]) ) {
901
+ // cssContent = readFromUrl(cssFiles[i], bundleConf.encoding);
902
+ //} else {
903
+ cssContent = fs.readFileSync(cssFiles[i], bundleConf.encoding).toString();
904
+ //}
905
+
906
+ hasUrls = ( /(url\(|url\s+\()/.test(cssContent) ) ? true : false;
907
+ if (!hasUrls) continue;
908
+
909
+ cssArr = cssContent.split(/}/g);
910
+ for (let c = 0; c < cssArr.length; ++c) {
911
+
912
+ if ( /(\@media|\@font-face)/.test(cssArr[c]) ) { // one day maybe !
913
+ continue
914
+ }
915
+
916
+ if ( /(url\(|url\s+\()/.test(cssArr[c]) && !/data\:|\@font-face/.test(cssArr[c]) ) {
917
+
918
+ url = cssArr[c].match(/((background\:url|url)+\()([A-Za-z0-9->~_.,:"'%/\s+]+).*?\)+/g)[0].replace(/((background\:url|url)+\(|\))/g, '').trim();
919
+ if ( typeof(assetsInClassFound[url]) != 'undefined') continue; // already defined
920
+
921
+ //cssMatched = cssArr[c].match(/((\.[A-Za-z0-9-_.,;:"'%\s+]+)(\s+\{|{))/);
922
+ cssMatched = cssArr[c].match(/((\.[A-Za-z0-9->~_.,;:"'%\s+]+)(\s+\{|{))/);
923
+ if ( !cssMatched ) { // might be a symbol problem : not supported by the regex
924
+ console.warn('[ HTTP2 ][ ASSETS ][ cssMatchedException ] `'+ cssFiles[i] +'`: unable to match definition for url : '+ url +'\n'+ cssArr[c]);
925
+ continue;
926
+ }
927
+ definition = cssMatched[0].replace(/\{/g, '');
928
+
929
+ classNames = definition.replace(/\./g, '').split(/\s+/);
930
+
931
+
932
+ for( let clss = 0; clss < classNames.length; ++clss) {
933
+ // this asset is in use
934
+ if ( layoutClasses.indexOf(classNames[clss] < 0 && typeof(assetsInClassFound[url]) == 'undefined') ) {
935
+ //console.debug(' found -> (' + url +')');
936
+ assetsInClassFound[url] = true;
937
+ // assetsInClassFound[url] = {
938
+ // cssFile: cssFiles[i],
939
+ // definition: definition,
940
+ // url: url
941
+ // }
942
+ if (!/(\:\/\/|^\/\/)/.test(url) ) {
943
+ filename = getAssetFilenameFromUrl(bundleConf, url);
944
+ } else {
945
+ domain = url.match(/^.*:\/\/[a-z0-9._-]+\/?/);
946
+ url = url.replace(domain, '/');
947
+ filename = url
948
+ }
949
+
950
+ //key = (( /404/.test(filename) ) ? '[404]' : '[200]') +' '+ url;
951
+ key = url;
952
+ isAvailable = ( /404/.test(filename) ) ? false : true;
953
+ ext = url.substr(url.lastIndexOf('.')).match(/(\.[A-Za-z0-9]+)/)[0];
954
+ assets[key] = {
955
+ referrer : cssFiles[i],
956
+ definition : definition,
957
+ type : type,
958
+ url : url,
959
+ ext : ext,
960
+ mime : bundleConf.server.coreConfiguration.mime[ext.substr(1)] || 'NA',
961
+ filename : ( /404/.test(filename) ) ? 'not found' : filename
962
+ };
963
+
964
+ if (domain)
965
+ assets[key].domain = domain;
966
+
967
+ break;
968
+ }
969
+ }
970
+ }
971
+ //font-family: source-sans-pro, sans-serif;
972
+
973
+
974
+ }
975
+
976
+ // match all definitions .xxx {}
977
+ //definitions = cssContent.match(/((\.[A-Za-z0-9-_.\s+]+)+(\s+\{|{))([A-Za-z0-9-@'"/._:;()\s+]+)\}/g);
978
+ //definitions = cssContent.match(/((\.[A-Za-z0-9-_.\s+]+)+(\s+\{|{))?/g);
979
+ // d = 0, dLen = definitions.length;
980
+ // for (; d < dLen; ++d) {
981
+ // if ( definitions[d] )
982
+ // }
983
+
984
+ // fonts, images, background - attention required to relative paths !!
985
+ //var inSourceAssets = cssContent.match(/((background\:url|url)+\()([A-Za-z0-9-_."']+).*?\)+/g);
986
+ }
987
+
988
+ assets._cssassets = assetsInClassFound.count();
989
+ } // EO if (classesArr) {
990
+
991
+
992
+
993
+ // TODO - report
994
+ /**
995
+ * assets._report = {
996
+ * total : ${int: aCount}, // assets count
997
+ * warning : [
998
+ * {
999
+ * message: "too many requests",
1000
+ * hint: "you should lower this"
1001
+ * },
1002
+ * {...}
1003
+ * ],
1004
+ * error: [
1005
+ * {
1006
+ * message: "${int: eCount} asset(s) not found",
1007
+ * hint: "check your assets location"
1008
+ * },
1009
+ * {
1010
+ *
1011
+ * }
1012
+ * ]
1013
+ * }
1014
+ */
1015
+
1016
+ if (swig) {
1017
+ var assetsStr = JSON.stringify(assets);
1018
+ assets = swig.compile( assetsStr.substring(1, assetsStr.length-1), swig.getOptions() )(data);
1019
+ return '{'+ assets +'}'
1020
+ } else {
1021
+ return assets
1022
+ }
1023
+ }
1024
+
1025
+ // var getHeaderFromPseudoHeader = function(header) {
1026
+
1027
+ // var htt2Headers = {
1028
+ // ':status' : 'status',
1029
+ // ':method' : 'method',
1030
+ // ':authority': 'host',
1031
+ // ':scheme' : 'scheme', // not sure
1032
+ // ':path' : 'path', // not sure
1033
+ // ':protocol' : 'protocol' // not sure
1034
+ // };
1035
+
1036
+ // if ( typeof(htt2Headers[header]) != 'undefined' ) {
1037
+ // return htt2Headers[header]
1038
+ // }
1039
+
1040
+ // return header
1041
+ // }
1042
+
1043
+ var completeHeaders = function(responseHeaders, request, response) {
1044
+
1045
+ var resHeaders = null
1046
+ , referer = null
1047
+ , authority = null
1048
+ , method = null
1049
+ , scheme = null
1050
+ , re = null
1051
+ , allowedOrigin = null
1052
+ , sameOrigin = false
1053
+ , conf = self.conf[self.appName][self.env]
1054
+ ;
1055
+
1056
+ if ( typeof(responseHeaders) == 'undefined' || !responseHeaders) {
1057
+ responseHeaders = {};
1058
+ }
1059
+
1060
+ // Copy to avoid override
1061
+ resHeaders = JSON.clone(conf.server.response.header);
1062
+ if ( typeof(request.routing) == 'undefined' ) {
1063
+ request.routing = {
1064
+ 'url': request.url,
1065
+ 'method': request.method
1066
+ }
1067
+ }
1068
+ if ( typeof(request.routing.bundle) == 'undefined' ) {
1069
+ request.routing.bundle = self.appName
1070
+ }
1071
+ // Should not override main server.response.header.methods
1072
+ resHeaders['access-control-allow-methods'] = request.routing.method.replace(/(\,\s+|\,)/g, ', ').toUpperCase();
1073
+
1074
+
1075
+ if ( typeof(request.headers.origin) != 'undefined' ) {
1076
+ authority = request.headers.origin;
1077
+ } else if (request.headers.referer) {
1078
+ referer = request.headers.referer.match(/[^http://|^https://|][a-z0-9-_.:]+\//)[0];
1079
+ referer = request.headers.referer.match(/^(http|https)\:\/\/?/)[0] + referer.substring(0, referer.length-1);
1080
+ }
1081
+
1082
+ // access-control-allow-origin settings
1083
+ if ( resHeaders.count() > 0 ) {
1084
+ // authority by default if no Access Control Allow Origin set
1085
+ //authority = ( typeof(referer) != 'undefined') ? conf.server.scheme +'://'+ request.headers.referer.match(/:\/\/(.[^\/]+)(.*)/)[1] : (request.headers[':scheme'] +'://'+request.headers[':authority'] || conf.server.scheme +'://'+request.headers.host || null);
1086
+ if (!authority) {
1087
+ if (!referer) {
1088
+ if ( /http\/2/.test(conf.server.protocol) ) {
1089
+ authority = request.headers[':authority'] || request.headers.host;
1090
+ scheme = request.headers[':scheme'] || request.headers['x-forwarded-proto'] || conf.server.scheme;
1091
+ } else {
1092
+ authority = request.headers.host;
1093
+ scheme = ( new RegExp(authority).test(referer) ) ? referer.match(/^http(.*)\:\/\//)[0].replace(/\:\/\//, '') : conf.server.scheme;
1094
+ }
1095
+ authority = scheme +'://'+ authority;
1096
+ } else {
1097
+ authority = referer;
1098
+ sameOrigin = authority;
1099
+ }
1100
+ }
1101
+
1102
+ if (!sameOrigin && conf.hostname == authority || !sameOrigin && conf.hostname.replace(/\:\d+$/, '') == authority.replace(/\:\d+$/, '') ) {
1103
+ sameOrigin = authority
1104
+ }
1105
+
1106
+ re = new RegExp(authority);
1107
+ allowedOrigin = ( typeof(conf.server.response.header['access-control-allow-origin']) != 'undefined' && conf.server.response.header['access-control-allow-origin'] != '' ) ? conf.server.response.header['access-control-allow-origin'] : authority;
1108
+ var found = null, origin = null, origins = null; // to handles multiple origins
1109
+ var originHostReplacement = function(name) {
1110
+ name = name.split(/\@/);
1111
+ var bundle = name[0]
1112
+ , project = name[1]
1113
+ , arr = null
1114
+ , domain = null
1115
+ ;
1116
+ var env = conf.env; // current env by default
1117
+ if ( /\//.test(name[1]) ) {
1118
+ arr = name[1].split(/\//);
1119
+ project = arr[0];
1120
+ env = (arr[1]) ? arr[1] : env;
1121
+ }
1122
+
1123
+ domain = ( !/^http/.test(self.conf[bundle][env].hostname) || /^\/\//.test(self.conf[bundle][env].hostname) ) ? scheme +'://'+ self.conf[bundle][env].hostname.replace(/^\/\//, '') : self.conf[bundle][env].hostname;
1124
+ sameOrigin = (domain == self.conf[bundle][env].hostname) ? self.conf[bundle][env].hostname : false;
1125
+
1126
+ return domain
1127
+ }
1128
+
1129
+ var headerValue = null;
1130
+ for (var h in resHeaders) {
1131
+ if (!response.headersSent) {
1132
+ // handles multiple origins
1133
+ if ( /access\-control\-allow\-origin/i.test(h) ) { // re.test(resHeaders[h]
1134
+ if (sameOrigin) {
1135
+ origin = sameOrigin
1136
+ } else {
1137
+ if ( /\,/.test(allowedOrigin) ) {
1138
+ origins = allowedOrigin.replace(/\s+/g, '').replace(/([a-z0-9_-]+\@[a-z0-9_-]+|[a-z0-9_-]+\@[a-z0-9_-]+\/[a-z0-9_-]+\@[a-z0-9_-]+)/ig, originHostReplacement).split(/\,/g);
1139
+
1140
+ found = ( origins.indexOf(authority) > -1 ) ? origins[origins.indexOf(authority)] : false;
1141
+ if ( found != false ) {
1142
+ origin = found
1143
+ }
1144
+ } else {
1145
+ origin = allowedOrigin
1146
+ }
1147
+ }
1148
+
1149
+ if (origin || sameOrigin) {
1150
+ if (!origin && sameOrigin)
1151
+ origin = sameOrigin;
1152
+
1153
+
1154
+ response.setHeader(h, origin);
1155
+ }
1156
+ sameOrigin = false;
1157
+ } else {
1158
+ headerValue = resHeaders[h];
1159
+ try {
1160
+ response.setHeader(h, headerValue)
1161
+ } catch (headerError) {
1162
+ console.error(headerError)
1163
+ }
1164
+ }
1165
+ }
1166
+ }
1167
+ }
1168
+
1169
+ // update response
1170
+ try {
1171
+ if ( responseHeaders && responseHeaders.count() > 0 ) {
1172
+ return merge(responseHeaders, response.getHeaders());
1173
+ }
1174
+ return response.getHeaders();
1175
+ } catch(err) {
1176
+ return responseHeaders
1177
+ }
1178
+ }
1179
+
1180
+ this.onHttp2Stream = function(stream, headers, response) {
1181
+
1182
+ if (!stream.pushAllowed) {
1183
+ //header = merge({ ':status': 200 }, response.getHeaders());
1184
+ stream.respond({ ':status': 200 });
1185
+ stream.end();
1186
+ return;
1187
+ }
1188
+
1189
+ if (stream.headersSent) return;
1190
+
1191
+ if ( !this._options.template ) {
1192
+ throwError({stream: stream}, 500, 'Internal server error\n' + headers[':path'] + '\nNo template found');
1193
+ return;
1194
+ }
1195
+
1196
+ var header = null, isWebroot = false, pathname = null;
1197
+ if (
1198
+ headers[':path'] == '/'
1199
+ || headers[':path'] == this._options.conf.server.webroot
1200
+ ) {
1201
+
1202
+ if (
1203
+ this._options.conf.server.webroot != headers[':path']
1204
+ && this._options.conf.server.webrootAutoredirect
1205
+ || headers[':path'] == this._options.conf.server.webroot
1206
+ && this._options.conf.server.webrootAutoredirect
1207
+ ) {
1208
+
1209
+ header = {
1210
+ ':status': 301
1211
+ };
1212
+
1213
+ if (cacheless) {
1214
+ header['cache-control'] = 'no-cache, no-store, must-revalidate';
1215
+ header['pragma'] = 'no-cache';
1216
+ header['expires'] = '0';
1217
+ }
1218
+ header['location'] = this._options.conf.server.webroot;
1219
+
1220
+ stream.respond(header);
1221
+ stream.end();
1222
+ return;
1223
+ } else {
1224
+ isWebroot = true;
1225
+ }
1226
+ }
1227
+
1228
+ if (
1229
+ typeof(this._options.template.assets) != 'undefined'
1230
+ && typeof(this._options.template.assets[ headers[':path'] ]) != 'undefined'
1231
+ && this._options.template.assets[ headers[':path'] ].isAvailable
1232
+ || isWebroot
1233
+ ) {
1234
+ // by default
1235
+ header = {
1236
+ ':status': 200
1237
+ };
1238
+ var url = (isWebroot) ? this._referrer : headers[':path'];
1239
+ var assets = this._options.template.assets;
1240
+ var responseHeaders = ( typeof(this._responseHeaders) != 'undefined') ? this._responseHeaders : null;
1241
+ var conf = this._options.conf;
1242
+ var asset = {
1243
+ url : url,
1244
+ filename : assets[ url ].filename,
1245
+ file : null,
1246
+ isAvailable : assets[ url ].isAvailable,
1247
+ mime : assets[ url ].mime,
1248
+ encoding : conf.encoding,
1249
+ isHandler : false
1250
+ }
1251
+ , cacheless = conf.cacheless
1252
+ ;
1253
+
1254
+ console.debug('h2 pushing: '+ headers[':path'] + ' -> '+ asset.filename);
1255
+
1256
+ // adding handler `gina.ready(...)` wrapper
1257
+ if ( new RegExp('^'+ conf.handlersPath).test(asset.filename) ) {
1258
+
1259
+ if ( !fs.existsSync(asset.filename) ) {
1260
+ throwError({stream: stream}, 404, 'Page not found: \n' + headers[':path']);
1261
+ return;
1262
+ }
1263
+
1264
+ asset.isHandler = true;
1265
+ asset.file = fs.readFileSync(asset.filename, asset.encoding).toString();
1266
+ asset.file = '(gina.ready(function onGinaReady($){\n'+ asset.file + '\n},window["originalContext"]));';
1267
+
1268
+ stream.respond(header);
1269
+ stream.end(asset.file);
1270
+
1271
+ return;
1272
+ }
1273
+
1274
+ stream.pushStream({ ':path': headers[':path'] }, function onPushStream(err, pushStream, headers){
1275
+
1276
+
1277
+ if ( err ) {
1278
+ header[':status'] = 500;
1279
+ if (err.code === 'ENOENT' || !asset.isAvailable ) {
1280
+ header[':status'] = 404;
1281
+ }
1282
+ //console.info(headers[':method'] +' ['+ header[':status'] +'] '+ headers[':path'] + '\n' + (err.stack|err.message|err));
1283
+ var msg = ( header[':status'] == 404 ) ? 'Page not found: \n' + asset.url : 'Internal server error\n' + (err.stack|err.message|err)
1284
+ throwError({stream: pushStream}, header[':status'], msg);
1285
+ return;
1286
+ }
1287
+
1288
+
1289
+ header['content-type'] = ( !/charset/.test(asset.mime ) ) ? asset.mime + '; charset='+ asset.encoding : asset.mime;
1290
+
1291
+ if (cacheless) {
1292
+ // source maps integration for javascript & css
1293
+ if ( /(.js|.css)$/.test(asset.filename) && fs.existsSync(asset.filename +'.map') ) {
1294
+ //pathname = asset.filename +'.map';
1295
+ pathname = headers[':path'] +'.map';
1296
+ // serve without cache
1297
+ header['X-SourceMap'] = pathname;
1298
+ header['cache-control'] = 'no-cache, no-store, must-revalidate';
1299
+ header['pragma'] = 'no-cache';
1300
+ header['expires'] = '0';
1301
+ }
1302
+ }
1303
+
1304
+ if (responseHeaders) {
1305
+ header = merge(header, responseHeaders);
1306
+ }
1307
+ header = completeHeaders(header, local.request, response);
1308
+ pushStream.respondWithFile(
1309
+ asset.filename
1310
+ , header
1311
+ //, { onError }
1312
+ );
1313
+
1314
+ });
1315
+ } else {
1316
+ var status = 404;
1317
+ if ( /\/$/.test(headers[':path']) && this._options.template.assets[ headers[':path'] +'index.html' ].isAvailable ) { // preview of directory is forbidden
1318
+ status = 403;
1319
+ headers[':status'] = status;
1320
+ }
1321
+ return throwError({stream: stream}, status, 'Page not found: \n' + headers[':path']);
1322
+ }
1323
+ }
1324
+
1325
+
1326
+
1327
+ var getResponseProtocol = function (response) {
1328
+
1329
+ var protocol = 'http/'+ local.request.httpVersion; // inheriting request protocol version by default
1330
+ var bundleConf = self.conf[self.appName][self.env];
1331
+ // switching protocol to h2 when possible
1332
+ if ( /http\/2/.test(bundleConf.server.protocol) && response.stream ) {
1333
+ protocol = bundleConf.server.protocol;
1334
+ }
1335
+
1336
+ return protocol;
1337
+ }
1338
+
1339
+ /**
1340
+ * Default http/1.x statics handler - For http/2.x check the SuperController
1341
+ * @param {object} staticProps - Expected : .isStaticFilename & .firstLevel
1342
+ * @param {object} request
1343
+ * @param {object} response
1344
+ * @param {callback} next
1345
+ */
1346
+ var handleStatics = function(staticProps, request, response, next) {
1347
+
1348
+
1349
+ var conf = self.conf
1350
+ , bundleConf = conf[self.appName][self.env]
1351
+ , webroot = bundleConf.server.webroot
1352
+ , re = new RegExp('^'+ webroot)
1353
+ , publicPathRe = new RegExp('^'+ bundleConf.publicPath)
1354
+ , pathname = ( webroot.length > 1 && re.test(request.url) ) ? request.url.replace(re, '/') : request.url
1355
+ , contentType = null
1356
+ , stream = null
1357
+ , header = null
1358
+ , protocol = getResponseProtocol(response)
1359
+ ;
1360
+
1361
+
1362
+ // h2 protocol response option
1363
+ if ( /http\/2/.test(protocol) ) {
1364
+
1365
+ stream = response.stream;
1366
+
1367
+ if ( typeof(self._options) == 'undefined') {
1368
+ self._options = {
1369
+ template: {
1370
+ assets: {}
1371
+ },
1372
+ conf: bundleConf
1373
+ }
1374
+ }
1375
+
1376
+ self._options.conf = bundleConf
1377
+ }
1378
+
1379
+ var cacheless = bundleConf.cacheless;
1380
+ // by default
1381
+ var filename = bundleConf.publicPath + pathname;
1382
+ var isFilenameDir = null
1383
+ , dirname = null
1384
+ , isBinary = null
1385
+ , hanlersPath = null
1386
+ ;
1387
+
1388
+ // catch `statics.json` defined paths
1389
+ var staticIndex = bundleConf.staticResources.indexOf(pathname);
1390
+ if ( staticProps.isStaticFilename && staticIndex > -1 ) {
1391
+ filename = bundleConf.content.statics[ bundleConf.staticResources[staticIndex] ]
1392
+ } else {
1393
+ var s = 0, sLen = bundleConf.staticResources.length;
1394
+ for ( ; s < sLen; ++s ) {
1395
+ //if ( new RegExp('^'+ bundleConf.staticResources[s]).test(pathname) ) {
1396
+ if ( eval('/^' + bundleConf.staticResources[s].replace(/\//g,'\\/') +'/').test(pathname) ) {
1397
+ filename = bundleConf.content.statics[ bundleConf.staticResources[s] ] +'/'+ pathname.replace(bundleConf.staticResources[s], '');
1398
+ break;
1399
+ }
1400
+ }
1401
+ }
1402
+
1403
+ filename = decodeURIComponent(filename);
1404
+ fs.exists(filename, function onStaticExists(exist) {
1405
+
1406
+ if (!exist) {
1407
+ throwError(response, 404, 'Page not found: \n' + pathname, next);
1408
+ return;
1409
+ } else {
1410
+
1411
+ isFilenameDir = fs.statSync(filename).isDirectory();
1412
+ if ( isFilenameDir ) {
1413
+ dirname = request.url;
1414
+ filename += 'index.html';
1415
+ request.url += 'index.html';
1416
+
1417
+ if ( !fs.existsSync(filename) ) {
1418
+ throwError(response, 403, 'Forbidden: \n' + pathname, next);
1419
+ return;
1420
+ } else {
1421
+ var ext = 'html';
1422
+ if ( /http\/2/.test(protocol) ) {
1423
+ header = {
1424
+ ':status': 301,
1425
+ 'location': request.url,
1426
+ 'content-type': bundleConf.server.coreConfiguration.mime[ext]+'; charset='+ bundleConf.encoding
1427
+ };
1428
+
1429
+ if (cacheless) {
1430
+ header['cache-control'] = 'no-cache, no-store, must-revalidate';
1431
+ header['pragma'] = 'no-cache';
1432
+ header['expires'] = '0';
1433
+ }
1434
+ request = checkPreflightRequest(request);
1435
+ header = completeHeaders(header, request, response);
1436
+
1437
+ if (!stream.destroyed) {
1438
+ stream.respond(header);
1439
+ stream.end();
1440
+ }
1441
+
1442
+ } else {
1443
+ response.setHeader('location', request.url);
1444
+ request = checkPreflightRequest(request);
1445
+ completeHeaders(null, request, response);
1446
+ if (cacheless) {
1447
+ response.writeHead(301, {
1448
+ 'cache-control': 'no-cache, no-store, must-revalidate', // preventing browsers from using cache
1449
+ 'pragma': 'no-cache',
1450
+ 'expires': '0',
1451
+ 'content-type': bundleConf.server.coreConfiguration.mime[ext]
1452
+ });
1453
+ }
1454
+ response.end()
1455
+ }
1456
+ }
1457
+ return;
1458
+ }
1459
+
1460
+
1461
+ if (cacheless)
1462
+ delete require.cache[require.resolve(filename)];
1463
+
1464
+
1465
+ fs.readFile(filename, bundleConf.encoding, function onStaticFileRead(err, file) {
1466
+ if (err) {
1467
+ throwError(response, 404, 'Page not found: \n' + pathname, next);
1468
+ return;
1469
+ } else if (!response.headersSent) {
1470
+
1471
+ isBinary = true;
1472
+
1473
+ try {
1474
+ contentType = getHead(response, filename);
1475
+
1476
+ // adding gina loader
1477
+ if ( /text\/html/i.test(contentType) && self.isCacheless() ) {
1478
+ isBinary = false;
1479
+ // javascriptsDeferEnabled
1480
+ if (bundleConf.content.templates._common.javascriptsDeferEnabled ) {
1481
+ file = file.replace(/\<\/head\>/i, '\t'+ bundleConf.content.templates._common.ginaLoader +'\n</head>');
1482
+ } else {
1483
+ file = file.replace(/\<\/body\>/i, '\t'+ bundleConf.content.templates._common.ginaLoader +'\n</body>');
1484
+ }
1485
+
1486
+ } else {
1487
+ // adding handler `gina.ready(...)` wrapper
1488
+ hanlersPath = bundleConf.handlersPath;
1489
+
1490
+ if ( new RegExp('^'+ hanlersPath).test(filename) ) {
1491
+ isBinary = false;
1492
+ file = '(gina.ready(function onGinaReady($){\n'+ file + '\n},window["originalContext"]));'
1493
+ }
1494
+ }
1495
+
1496
+ if ( /http\/2/.test(protocol) ) {
1497
+ self._isStatic = true;
1498
+ self._referrer = request.url;
1499
+ var ext = request.url.match(/\.([A-Za-z0-9]+)$/);
1500
+ request.url = ( ext != null && typeof(ext[0]) != 'undefined' ) ? request.url : request.url + 'index.html';
1501
+
1502
+ self._responseHeaders = response.getHeaders();
1503
+ if (!isBinary && typeof(self._options.template.assets[request.url]) == 'undefined')
1504
+ self._options.template.assets = getAssets(bundleConf, file);
1505
+
1506
+ if (
1507
+ typeof(self._options.template.assets[request.url]) == 'undefined'
1508
+ || isBinary
1509
+ ) {
1510
+
1511
+ self._options.template.assets[request.url] = {
1512
+ ext: ( ext != null && typeof(ext[0]) != 'undefined' ) ? ext[0] : null,
1513
+ isAvailable: true,
1514
+ mime: contentType,
1515
+ url: request.url,
1516
+ filename: filename
1517
+ }
1518
+ }
1519
+
1520
+ self.instance._isXMLRequest = request.isXMLRequest;
1521
+ self.instance._getAssetFilenameFromUrl = getAssetFilenameFromUrl;
1522
+
1523
+ var isPathMatchingUrl = null;
1524
+ if ( !self.instance._http2streamEventInitalized ) {
1525
+ self.instance._http2streamEventInitalized = true;
1526
+ self.instance.on('stream', function onHttp2Strem(stream, headers) {
1527
+
1528
+ if (!self._isStatic) return;
1529
+
1530
+ if (!this._isXMLRequest) {
1531
+ isPathMatchingUrl = true;
1532
+ if (headers[':path'] != request.url) {
1533
+ request.url = headers[':path'];
1534
+ isPathMatchingUrl = false;
1535
+ }
1536
+
1537
+ // for new requests
1538
+ if (!isPathMatchingUrl) {
1539
+ pathname = ( webroot.length > 1 && re.test(request.url) ) ? request.url.replace(re, '/') : request.url;
1540
+ isFilenameDir = (webroot == request.url) ? true: false;
1541
+
1542
+ if ( !isFilenameDir && !/404\.html/.test(filename) && fs.existsSync(filename) )
1543
+ isFilenameDir = fs.statSync(filename).isDirectory();
1544
+ if (!isFilenameDir) {
1545
+ filename = this._getAssetFilenameFromUrl(bundleConf, pathname);
1546
+ }
1547
+
1548
+ if ( !isFilenameDir && !fs.existsSync(filename) ) {
1549
+ throwError(response, 404, 'Page not found: \n' + pathname, next);
1550
+ return;
1551
+ }
1552
+
1553
+
1554
+ if ( isFilenameDir ) {
1555
+ dirname = bundleConf.publicPath + pathname;
1556
+ filename = dirname + 'index.html';
1557
+ request.url += 'index.html';
1558
+ if ( !fs.existsSync(filename) ) {
1559
+ throwError(response, 403, 'Forbidden: \n' + pathname, next);
1560
+ return;
1561
+ } else {
1562
+ header = {
1563
+ ':status': 301,
1564
+ 'location': request.url
1565
+ };
1566
+
1567
+ if (cacheless) {
1568
+ header['cache-control'] = 'no-cache, no-store, must-revalidate';
1569
+ header['pragma'] = 'no-cache';
1570
+ header['expires'] = '0';
1571
+ }
1572
+
1573
+
1574
+ stream.respond(header);
1575
+ stream.end();
1576
+ }
1577
+ }
1578
+ }
1579
+
1580
+ contentType = getHead(response, filename);
1581
+ contentType = contentType +'; charset='+ bundleConf.encoding;
1582
+ ext = request.url.match(/\.([A-Za-z0-9]+)$/);
1583
+ request.url = ( ext != null && typeof(ext[0]) != 'undefined' ) ? request.url : request.url + 'index.html';
1584
+ if (
1585
+ !isPathMatchingUrl
1586
+ && typeof(self._options.template.assets[request.url]) == 'undefined'
1587
+ ) {
1588
+
1589
+ self._options.template.assets[request.url] = {
1590
+ ext: ( ext != null && typeof(ext[0]) != 'undefined' ) ? ext[0] : null,
1591
+ //isAvailable: true,
1592
+ isAvailable: (!/404\.html/.test(filename)) ? true : false,
1593
+ mime: contentType,
1594
+ url: request.url,
1595
+ filename: filename
1596
+ }
1597
+ }
1598
+
1599
+ if (!fs.existsSync(filename)) return;
1600
+ isBinary = ( /text\/html/i.test(contentType) ) ? false : true;
1601
+ if ( isBinary ) {
1602
+ // override
1603
+ self._options.template.assets[request.url] = {
1604
+ ext: ( ext != null && typeof(ext[0]) != 'undefined' ) ? ext[0] : null,
1605
+ isAvailable: true,
1606
+ mime: contentType,
1607
+ url: request.url,
1608
+ filename: filename
1609
+ }
1610
+ }
1611
+ self.onHttp2Stream(stream, headers, response);
1612
+ }
1613
+
1614
+ }); // EO self.instance.on('stream' ..
1615
+ }
1616
+
1617
+
1618
+ header = {
1619
+ ':status': 200,
1620
+ 'content-type': contentType + '; charset='+ bundleConf.encoding
1621
+ };
1622
+
1623
+ if (cacheless) {
1624
+ // source maps integration for javascript & css
1625
+ if ( /(.js|.css)$/.test(filename) && fs.existsSync(filename +'.map') && !/sourceMappingURL/.test(file) ) {
1626
+ //pathname = pathname +'.map';
1627
+ pathname = webroot + pathname.substr(1) +'.map';
1628
+ // serve without cache
1629
+ header['X-SourceMap'] = pathname;
1630
+ header['cache-control'] = 'no-cache, no-store, must-revalidate';
1631
+ header['pragma'] = 'no-cache';
1632
+ header['expires'] = '0';
1633
+ }
1634
+ }
1635
+
1636
+ header = completeHeaders(header, request, response);
1637
+ if (isBinary) {
1638
+ stream.respondWithFile(filename, header)
1639
+ } else {
1640
+ stream.respond(header);
1641
+ stream.end(file);
1642
+ }
1643
+ // Fixed on march 15 2021 by removing the return
1644
+ // Could be the cause why the push is pending
1645
+ //return;
1646
+ } else {
1647
+
1648
+ completeHeaders(null, request, response);
1649
+ response.setHeader('content-type', contentType +'; charset='+ bundleConf.encoding);
1650
+ // if (/\.(woff|woff2)$/i.test(filename) ) {
1651
+ // response.setHeader("Transfer-Encoding", 'Identity')
1652
+ // }
1653
+ if (isBinary) {
1654
+ response.setHeader('content-length', fs.statSync(filename).size);
1655
+ }
1656
+
1657
+ if (cacheless) {
1658
+ // source maps integration for javascript & css
1659
+ if ( /(.js|.css)$/.test(filename) && fs.existsSync(filename +'.map') && !/sourceMappingURL/.test(file) ) {
1660
+ //pathname = pathname +'.map'
1661
+ pathname = webroot + pathname.substr(1) +'.map';
1662
+ response.setHeader("X-SourceMap", pathname)
1663
+ }
1664
+
1665
+ // serve without cache
1666
+ response.writeHead(200, {
1667
+ 'cache-control': 'no-cache, no-store, must-revalidate', // preventing browsers from caching it
1668
+ 'pragma': 'no-cache',
1669
+ 'expires': '0'
1670
+ });
1671
+
1672
+ } else {
1673
+ response.writeHead(200)
1674
+ }
1675
+
1676
+
1677
+ if (isBinary) { // images, javascript, pdf ....
1678
+ fs.createReadStream(filename)
1679
+ .on('end', function onResponse(){
1680
+ console.info(request.method +' [200] '+ pathname);
1681
+ })
1682
+ .pipe(response);
1683
+ } else {
1684
+ response.write(file, bundleConf.encoding);
1685
+ response.end();
1686
+ console.info(request.method +' [200] '+ pathname);
1687
+ }
1688
+
1689
+ return;
1690
+ }
1691
+
1692
+ } catch(err) {
1693
+ throwError(response, 500, err.stack);
1694
+ return;
1695
+ }
1696
+ }
1697
+
1698
+ return
1699
+ });
1700
+
1701
+ }
1702
+ })
1703
+ }
1704
+
1705
+
1706
+ var onRequest = function() {
1707
+
1708
+ var apps = self.bundles;
1709
+ var webrootLen = self.conf[self.appName][self.env].server.webroot.length;
1710
+
1711
+ // catch all (request urls)
1712
+ self.instance.all('*', function onInstance(request, response, next) {
1713
+
1714
+
1715
+ request.setEncoding(self.conf[self.appName][self.env].encoding);
1716
+ // be carfull, if you are using jQuery + cross domain, you have to set the header manually in your $.ajax query -> headers: {'X-Requested-With': 'XMLHttpRequest'}
1717
+ request.isXMLRequest = ( request.headers['x-requested-with'] && request.headers['x-requested-with'] == 'XMLHttpRequest' ) ? true : false;
1718
+
1719
+ // Passing credentials :
1720
+ // - if you are using jQuery + cross domain, you have to set the `xhrFields` in your $.ajax query -> xhrFields: { withCredentials: true }
1721
+ // - if you are using another solution or doing it by hand, make sure to properly set the header: headers: {'access-control-allow-credentials': true }
1722
+ /**
1723
+ * NB.: jQuery
1724
+ * The `withCredentials` property will include any cookies from the remote domain in the request,
1725
+ * and it will also set any cookies from the remote domain.
1726
+ * Note that these cookies still honor same-origin policies, so your JavaScript code can’t access the cookies
1727
+ * from document.cookie or the response headers.
1728
+ * They can only be controlled/produced by the remote domain.
1729
+ * */
1730
+ request.isWithCredentials = ( request.headers['access-control-allow-credentials'] && request.headers['access-control-allow-credentials'] == true ) ? true : false;
1731
+ /**
1732
+ * Intercept gina headers
1733
+ */
1734
+ if ( typeof(request.headers['x-gina-form-id']) != 'undefined' ) {
1735
+ var ginaHeaders = {
1736
+ form: {
1737
+ id: request.headers['x-gina-form-id']
1738
+ }
1739
+ };
1740
+ if ( typeof(request.headers['x-gina-form-rule']) != 'undefined' ) {
1741
+ var rule = request.headers['x-gina-form-rule'].split(/\@/);
1742
+ ginaHeaders.form.rule = rule[0];
1743
+ ginaHeaders.form.bundle = rule[1];
1744
+ }
1745
+ request.ginaHeaders = ginaHeaders;
1746
+ }
1747
+
1748
+ local.request = request;
1749
+
1750
+ response.setHeader('x-powered-by', 'Gina/'+ GINA_VERSION );
1751
+
1752
+
1753
+
1754
+ // Fixing an express js bug :(
1755
+ // express is trying to force : /path/dir => /path/dir/
1756
+ // which causes : /path/dir/path/dir/ <---- by trying to add a slash in the end
1757
+ // if (
1758
+ // webrootLen > 1
1759
+ // && request.url === self.conf[self.appName][self.env].server.webroot + '/' + self.conf[self.appName][self.env].server.webroot + '/'
1760
+ // ) {
1761
+ // request.url = self.conf[self.appName][self.env].server.webroot
1762
+ // }
1763
+
1764
+
1765
+ // webroot filter
1766
+ var isWebrootHandledByRouting = ( self.conf[self.appName][self.env].server.webroot == request.url && !fs.existsSync( _(self.conf[self.appName][self.env].publicPath +'/index.html', true) ) ) ? true : false;
1767
+ // webrootAutoredirect case
1768
+ if (
1769
+ request.url == '/'
1770
+ && typeof(self.conf[self.appName][self.env].server.webroot) != 'undefined'
1771
+ && /^true$/i.test(self.conf[self.appName][self.env].server.webrootAutoredirect)
1772
+ ) {
1773
+ var routing = self.conf[self.appName][self.env].content.routing;
1774
+ if (
1775
+ typeof(routing['webroot@'+self.appName]) != 'undefined'
1776
+ && self.conf[self.appName][self.env].server.webroot == routing['webroot@'+self.appName].webroot
1777
+ ) {
1778
+ var urls = routing['webroot@'+self.appName].url.split(',');
1779
+ if ( urls.indexOf('/') > -1 ) {
1780
+ isWebrootHandledByRouting = true;
1781
+ }
1782
+ }
1783
+ }
1784
+
1785
+ // priority to statics - this portion of code has been duplicated to SuperController : see `isStaticRoute` method
1786
+ var staticsArr = self.conf[self.appName][self.env].publicResources;
1787
+ var staticProps = {
1788
+ isStaticFilename: false
1789
+ };
1790
+
1791
+ if (!isWebrootHandledByRouting) {
1792
+
1793
+ staticProps.firstLevel = '/' + request.url.split(/\//g)[1] + '/';
1794
+
1795
+ // to be considered as a stativ content, url must content at least 2 caracters after last `.`: .js, .html are ok
1796
+ var ext = request.url.match(/(\.([A-Za-z0-9]+){2}|\/)$/);
1797
+ var isImage = false;
1798
+ if ( typeof(ext) != 'undefined' && ext != null) {
1799
+ ext = ext[0];
1800
+ // if image with `@` found
1801
+ if ( /^image/i.test(self.conf[self.appName][self.env].server.coreConfiguration.mime[ext.substr(1)]) ) {
1802
+ isImage = true
1803
+ }
1804
+ }
1805
+ if (
1806
+ ext != null
1807
+ // and must not be an email
1808
+ && !/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(request.url)
1809
+ // and must be handled by mime.types
1810
+ && typeof(self.conf[self.appName][self.env].server.coreConfiguration.mime[ext.substr(1)]) != 'undefined'
1811
+ ||
1812
+ ext != null
1813
+ && isImage
1814
+
1815
+ ) {
1816
+ staticProps.isStaticFilename = true
1817
+ }
1818
+ }
1819
+
1820
+
1821
+
1822
+ // handle resources from public with webroot in url
1823
+ if ( staticProps.isStaticFilename && self.conf[self.appName][self.env].server.webroot != '/' && staticProps.firstLevel == self.conf[self.appName][self.env].server.webroot ) {
1824
+ var matchedFirstInUrl = request.url.replace(self.conf[self.appName][self.env].server.webroot, '').match(/[A-Za-z0-9_-]+\/?/);
1825
+ if ( matchedFirstInUrl && matchedFirstInUrl.length > 0 ) {
1826
+ staticProps.firstLevel = self.conf[self.appName][self.env].server.webroot + matchedFirstInUrl[0]
1827
+ }
1828
+ }
1829
+
1830
+ if (
1831
+ staticProps.isStaticFilename && staticsArr.indexOf(request.url) > -1
1832
+ || staticProps.isStaticFilename && staticsArr.indexOf( request.url.replace(request.url.substr(request.url.lastIndexOf('/')+1), '') ) > -1
1833
+ //|| staticProps.isStaticFilename && staticsArr.indexOf(staticProps.firstLevel) > -1
1834
+ // take ^/dir/sub/*
1835
+ || staticProps.isStaticFilename && new RegExp('^'+ staticProps.firstLevel).test(request.url)
1836
+ || /\/$/.test(request.url) && !isWebrootHandledByRouting && !/\/engine\.io\//.test(request.url)
1837
+ ) {
1838
+ self._isStatic = true;
1839
+
1840
+
1841
+ self._referrer = request.url;
1842
+ // by default - used in `composeHeadersMiddleware`: see Default Global Middlewares (gna.js)
1843
+ request.routing = {
1844
+ 'url': request.url,
1845
+ 'method': 'GET',
1846
+ 'bundle' : self.appName
1847
+ };
1848
+ request = checkPreflightRequest(request);
1849
+ local.request = request; // update request
1850
+ // filtered to handle only html for now
1851
+ if ( /text\/html/.test(request.headers['accept'])
1852
+ && /^isaac/.test(self.engine)
1853
+ && self.instance._expressMiddlewares.length > 0
1854
+ ||
1855
+ request.isPreflightRequest
1856
+ && /^isaac/.test(self.engine)
1857
+ && self.instance._expressMiddlewares.length > 0
1858
+ ) {
1859
+
1860
+ nextMiddleware._index = 0;
1861
+ nextMiddleware._count = self.instance._expressMiddlewares.length-1;
1862
+ nextMiddleware._request = request;
1863
+ nextMiddleware._response = response;
1864
+ nextMiddleware._next = next;
1865
+ nextMiddleware._nextAction = 'handleStatics';
1866
+ nextMiddleware._staticProps = staticProps;
1867
+
1868
+
1869
+ nextMiddleware()
1870
+ } else {
1871
+ handleStatics(staticProps, request, response, next);
1872
+ }
1873
+
1874
+ } else { // not a static request
1875
+ self._isStatic = false;
1876
+ // init content
1877
+ request.body = ( typeof(request.body) != 'undefined' ) ? request.body : {};
1878
+ request.get = {};
1879
+ request.post = {};
1880
+ request.put = {};
1881
+ request.delete = {};
1882
+ request.files = [];
1883
+ //request.patch = {}; ???
1884
+ //request.cookies = {}; // ???
1885
+ //request.copy ???
1886
+
1887
+
1888
+
1889
+ // multipart wrapper for uploads
1890
+ // files are available from your controller or any middlewares:
1891
+ // @param {object} req.files
1892
+ if ( /multipart\/form-data;/.test(request.headers['content-type']) ) {
1893
+ // TODO - get options from settings.json & settings.{env}.json ...
1894
+ // -> https://github.com/mscdex/busboy
1895
+ var opt = self.conf[self.appName][self.env].content.settings.upload;
1896
+ // checking size
1897
+ var maxSize = parseInt(opt.maxFieldsSize);
1898
+ var fileSize = request.headers["content-length"]/1024/1024; //MB
1899
+ var hasAutoTmpCleanupTimeout = (
1900
+ typeof(opt.autoTmpCleanupTimeout) != 'undefined'
1901
+ && opt.autoTmpCleanupTimeout != ''
1902
+ && opt.autoTmpCleanupTimeout != 0
1903
+ && !/false/i.test(opt.autoTmpCleanupTimeout)
1904
+ ) ? true : false;
1905
+ var autoTmpCleanupTimeout = (!hasAutoTmpCleanupTimeout) ? null : opt.autoTmpCleanupTimeout; //ms
1906
+
1907
+ if (fileSize > maxSize) {
1908
+ return throwError(response, 431, 'Attachment exceeded maximum file size [ '+ opt.maxFieldsSize +' ]');
1909
+ }
1910
+
1911
+ var uploadDir = opt.uploadDir || os.tmpdir();
1912
+
1913
+ /**
1914
+ * str2ab
1915
+ * One common practical question about ArrayBuffer is how to convert a String to an ArrayBuffer and vice-versa.
1916
+ * Since an ArrayBuffer is, in fact, a byte array, this conversion requires that both ends agree on how
1917
+ * to represent the characters in the String as bytes.
1918
+ * You probably have seen this "agreement" before: it is the
1919
+ * String's character encoding (and the usual "agreement terms" are, for example, Unicode UTF-16 and iso8859-1).
1920
+ * Thus, supposing you and the other party have agreed on the UTF-16 encoding
1921
+ *
1922
+ * ref.:
1923
+ * - https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
1924
+ * - https://jsperf.com/arraybuffer-string-conversion/4
1925
+ *
1926
+ * @param {string} str
1927
+ *
1928
+ * @returns {array} buffer
1929
+ * */
1930
+ var str2ab = function(str, bits) {
1931
+
1932
+ var bytesLength = str.length
1933
+ //, bits = 8 // default bytesLength
1934
+ , bits = ( typeof (bits) != 'undefined' ) ? (bits/8) : 1
1935
+ , buffer = new ArrayBuffer(bytesLength * bits) // `bits` bytes for each char
1936
+ , bufView = null;
1937
+
1938
+ switch (bytesLength) {
1939
+ case 8:
1940
+ bufView = new Uint8Array(buffer);
1941
+ break;
1942
+
1943
+ case 16:
1944
+ bufView = new Uint16Array(buffer);
1945
+ break;
1946
+
1947
+ case 32:
1948
+ bufView = new Uint32Array(buffer);
1949
+ break;
1950
+
1951
+ default:
1952
+ bufView = new Uint8Array(buffer);
1953
+ break;
1954
+ }
1955
+ //var buf = new ArrayBuffer(str.length * 2); // 2 bytes for each char when using Uint16Array(buf)
1956
+ //var buf = new ArrayBuffer(str.length); // Uint8Array
1957
+ //var bufView = new Uint8Array(buf);
1958
+ for (var i = 0, strLen = str.length; i < strLen; i++) {
1959
+ bufView[i] = str.charCodeAt(i);
1960
+ }
1961
+
1962
+ return buffer;
1963
+ };
1964
+
1965
+ /**
1966
+ * str2ab
1967
+ *
1968
+ * With TypedArray now available, the Buffer class implements the Uint8Array API
1969
+ * in a manner that is more optimized and suitable for Node.js.
1970
+ * ref.:
1971
+ * - https://nodejs.org/api/buffer.html#buffer_buffer_from_buffer_alloc_and_buffer_allocunsafe
1972
+ *
1973
+ * @param {string} str
1974
+ *
1975
+ * @returns {array} buffer
1976
+ */
1977
+ // var str2ab = function(str, encoding) {
1978
+
1979
+ // const buffer = Buffer.allocUnsafe(str.length);
1980
+
1981
+ // for (let i = 0, len = str.len; i < len; i++) {
1982
+ // buffer[i] = str.charCodeAt(i);
1983
+ // }
1984
+
1985
+ // return buffer;
1986
+ // }
1987
+
1988
+
1989
+ var fileObj = null
1990
+ , fileCount = 0
1991
+ , tmpFilename = null
1992
+ , writeStreams = []
1993
+ , index = 0;
1994
+
1995
+ request.files = [];
1996
+ request.routing = {
1997
+ 'url': request.url,
1998
+ 'method': 'POST',
1999
+ 'bundle' : self.appName
2000
+ };
2001
+ var busboy = new Busboy({ headers: request.headers });
2002
+
2003
+ // busboy.on('field', function(fieldname, val, fieldnameTruncated, valTruncated) {
2004
+ // console.log('Field [' + fieldname + ']: value: ' + inspect(val));
2005
+ // });
2006
+ busboy.on('file', function(fieldname, file, filename, encoding, mimetype, group) {
2007
+
2008
+ file._dataLen = 0;
2009
+ ++fileCount;
2010
+
2011
+ if (
2012
+ typeof(group) != 'undefined'
2013
+ && group != 'untagged'
2014
+ && typeof(opt.groups[group]) != 'undefined'
2015
+ ) {
2016
+ // allowed extensions
2017
+ if ( typeof(opt.groups[group].allowedExtensions) != 'undefined'
2018
+ && opt.groups[group].allowedExtensions != '*'
2019
+ ) {
2020
+ var ext = opt.groups[group].allowedExtensions;
2021
+ var fileExt = filename.substr(filename.lastIndexOf('.')+1)
2022
+ if ( !Array.isArray(ext) ) {
2023
+ ext = [ext]
2024
+ }
2025
+
2026
+ if ( ext.indexOf(fileExt) < 0 ) {
2027
+ throwError(response, 400, '`'+ fileExt +'` is not an allowed extension. See `'+ group +'` upload group definition.');
2028
+ return false;
2029
+ }
2030
+ }
2031
+
2032
+ // multiple or single
2033
+ if ( typeof(opt.groups[group].isMultipleAllowed) != 'undefined'
2034
+ && !opt.groups[group].isMultipleAllowed
2035
+ && fileCount > 1
2036
+ ) {
2037
+ throwError(response, 400, 'multiple uploads not allowed. See `'+ group +'` upload group definition.');
2038
+ return false;
2039
+ }
2040
+ }
2041
+
2042
+
2043
+ // TODO - https://github.com/TooTallNate/node-wav
2044
+ //file._mimetype = mimetype;
2045
+
2046
+ // creating file
2047
+ writeStreams[index] = fs.createWriteStream( _(uploadDir + '/' + filename) );
2048
+ // https://strongloop.com/strongblog/practical-examples-of-the-new-node-js-streams-api/
2049
+ var liner = new require('stream').Transform({objectMode: true});
2050
+
2051
+ liner._transform = function (chunk, encoding, done) {
2052
+
2053
+ var str = chunk.toString();
2054
+ file._dataLen += str.length;
2055
+
2056
+ var ab = Buffer.from(str2ab(str));
2057
+ this.push(ab)
2058
+
2059
+ done()
2060
+ }
2061
+
2062
+ // liner._flush = function (done) {
2063
+ // done()
2064
+ // }
2065
+
2066
+ file.pipe(liner).pipe(writeStreams[index]);
2067
+ ++index;
2068
+
2069
+
2070
+ file.on('end', function() {
2071
+
2072
+ //fileObj = Buffer.from(str2ab(this._dataChunk));
2073
+ //delete this._dataChunk;
2074
+
2075
+ tmpFilename = _(uploadDir + '/' + filename);
2076
+
2077
+ request.files.push({
2078
+ name: fieldname,
2079
+ group: group,
2080
+ originalFilename: filename,
2081
+ encoding: encoding,
2082
+ type: mimetype,
2083
+ size: this._dataLen,
2084
+ path: tmpFilename
2085
+ });
2086
+
2087
+ // /tmp autoTmpCleanupTimeout
2088
+ if (autoTmpCleanupTimeout) {
2089
+ setTimeout((tmpFilename) => {
2090
+ console.debug('[ BUNDLE ][ '+self.appName+' ][ server ][ upload ] Now removing `'+ tmpFilename +'` from tmp');
2091
+ var tmpFilename = new _(tmpFilename);
2092
+ if (tmpFilename.existsSync())
2093
+ tmpFilename.rmSync();
2094
+ }, autoTmpCleanupTimeout, tmpFilename);
2095
+ }
2096
+ });
2097
+ });
2098
+
2099
+ busboy.on('finish', function() {
2100
+ var total = writeStreams.length;
2101
+ for (var ws = 0, wsLen = writeStreams.length; ws < wsLen; ++ws ) {
2102
+
2103
+ writeStreams[ws].on('error', function(err) {
2104
+ console.error('[ busboy ] [ onWriteError ]', err);
2105
+ throwError(response, 500, 'Internal server error\n' + err, next);
2106
+ this.close();
2107
+ return;
2108
+ });
2109
+
2110
+ writeStreams[ws].on('finish', function() {
2111
+ this.close( function onUploaded(){
2112
+ --total;
2113
+ console.debug('closing writestreams : ' + total);
2114
+
2115
+ if (total == 0) {
2116
+ loadBundleConfiguration(request, response, next, function onBundleConfigurationLoaded(err, bundle, pathname, config, req, res, next) {
2117
+ if (!req.handled) {
2118
+ req.handled = true;
2119
+ if (err) {
2120
+ if (!res.headersSent)
2121
+ throwError(response, 500, 'Internal server error\n' + err.stack, next);
2122
+ return;
2123
+ } else {
2124
+ handle(req, res, next, bundle, pathname, config)
2125
+ }
2126
+ }
2127
+ })
2128
+ }
2129
+ })
2130
+ });
2131
+ }
2132
+ });
2133
+
2134
+ request.pipe(busboy);
2135
+ } else {
2136
+
2137
+
2138
+ request.on('data', function(chunk){ // for this to work, don't forget the name attr for you form elements
2139
+ if ( typeof(request.body) == 'object') {
2140
+ request.body = '';
2141
+ }
2142
+ request.body += chunk.toString()
2143
+ });
2144
+
2145
+ request.on('end', function onEnd() {
2146
+ processRequestData(request, response, next);
2147
+ });
2148
+
2149
+ if (request.end) request.end();
2150
+
2151
+
2152
+ } //EO if multipart
2153
+ }
2154
+
2155
+
2156
+ });//EO this.instance
2157
+
2158
+
2159
+ self.instance.listen(self.conf[self.appName][self.env].server.port);//By Default 3100
2160
+ self.instance.timeout = (1000 * 300); // e.g.: 1000x60 => 60 sec
2161
+
2162
+ self.emit('started', self.conf[self.appName][self.env], true);
2163
+ }
2164
+
2165
+ var processRequestData = function(request, response, next) {
2166
+
2167
+ var bodyStr = null, obj = null;
2168
+ // to compare with /core/controller/controller.js -> getParams()
2169
+ switch( request.method.toLowerCase() ) {
2170
+ case 'post':
2171
+ var configuring = false, msg = null, isPostSet = false;
2172
+ if ( typeof(request.body) == 'string' ) {
2173
+ // get rid of encoding issues
2174
+ try {
2175
+ if ( !/multipart\/form-data;/.test(request.headers['content-type']) ) {
2176
+ if ( /application\/x\-www\-form\-urlencoded/.test(request.headers['content-type']) && /\+/.test(request.body) ) {
2177
+ request.body = request.body.replace(/\+/g, ' ');
2178
+ }
2179
+
2180
+ if ( request.body.substr(0,1) == '?')
2181
+ request.body = request.body.substr(1);
2182
+
2183
+ try {
2184
+ bodyStr = decodeURIComponent(request.body); // it is already a string for sure
2185
+ } catch (err) {
2186
+ bodyStr = request.body;
2187
+ }
2188
+
2189
+ // false & true case
2190
+ if ( /(\"false\"|\"true\"|\"on\")/.test(bodyStr) )
2191
+ bodyStr = bodyStr.replace(/\"false\"/g, false).replace(/\"true\"/g, true).replace(/\"on\"/g, true);
2192
+ if ( /(\"null\")/i.test(bodyStr) )
2193
+ bodyStr = bodyStr.replace(/\"null\"/ig, null);
2194
+
2195
+ try {
2196
+ obj = parseBody(bodyStr);
2197
+ request.post = obj;
2198
+ isPostSet = true;
2199
+ } catch (err) {
2200
+ // ignore this one
2201
+ msg = '[ Could properly evaluate POST ] '+ request.url +'\n'+ err.stack;
2202
+ console.warn(msg);
2203
+ }
2204
+ if (!isPostSet) {
2205
+ try {
2206
+ if (obj.count() == 0 && bodyStr.length > 1) {
2207
+ request.post = obj;
2208
+ } else {
2209
+ request.post = JSON.parse(bodyStr)
2210
+ }
2211
+
2212
+ } catch (err) {
2213
+ msg = '[ Exception found for POST ] '+ request.url +'\n'+ err.stack;
2214
+ console.warn(msg);
2215
+ }
2216
+ }
2217
+ }
2218
+
2219
+ } catch (err) {
2220
+ msg = '[ Could properly evaluate POST ] '+ request.url +'\n'+ err.stack;
2221
+ console.warn(msg);
2222
+ }
2223
+
2224
+ } else {
2225
+ // 2016-05-19: fix to handle requests from swagger/express
2226
+ if (request.body.count() == 0 && typeof(request.query) != 'string' && request.query.count() > 0 ) {
2227
+ request.body = request.query
2228
+ }
2229
+ bodyStr = JSON.stringify(request.body);
2230
+ // false & true case
2231
+ if ( /(\"false\"|\"true\"|\"on\")/.test(bodyStr) )
2232
+ bodyStr = bodyStr.replace(/\"false\"/g, false).replace(/\"true\"/g, true).replace(/\"on\"/g, true);
2233
+
2234
+ obj = JSON.parse(bodyStr)
2235
+ }
2236
+
2237
+ try {
2238
+ if ( obj.count() > 0 ) {
2239
+ // still need this to allow compatibility with express & connect middlewares
2240
+ request.body = request.post = obj;
2241
+ }
2242
+ } catch (err) {
2243
+ msg = '[ Could complete POST ] '+ request.url +'\n'+ err.stack;
2244
+ console.error(msg);
2245
+ throwError(response, 500, err, next);
2246
+ return;
2247
+ }
2248
+
2249
+
2250
+ // see.: https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#POST
2251
+ // Responses to this method are not cacheable,
2252
+ // unless the response includes appropriate cache-control or expires header fields.
2253
+ // However, the 303 (See Other) response can be used to direct the user agent to retrieve a cacheable resource.
2254
+ if ( !response.headersSent ) {
2255
+ response.setHeader('cache-control', 'no-cache, no-store, must-revalidate');
2256
+ response.setHeader('pragma', 'no-cache');
2257
+ response.setHeader('expires', '0');
2258
+ }
2259
+
2260
+
2261
+ // cleaning
2262
+ request.query = undefined;
2263
+ request.get = undefined;
2264
+ request.put = undefined;
2265
+ request.delete = undefined;
2266
+ break;
2267
+
2268
+ case 'get':
2269
+ // if ( typeof(request.query) == 'string' && /^(\{|\[\{)/.test(request.query) ) {
2270
+ // bodyStr = request.query.replace(/\"{/g, '{').replace(/}\"/g, '}').replace(/\\/g, '');
2271
+ // request.query = JSON.parse(bodyStr);
2272
+ // }
2273
+ if ( typeof(request.query) != 'undefined' && request.query.count() > 0 ) {
2274
+ var inheritedDataObj = {};
2275
+ if ( typeof(request.query.inheritedData) != 'undefined' ) {
2276
+
2277
+
2278
+ if ( typeof(request.query.inheritedData) == 'string' ) {
2279
+ inheritedDataObj = parseBody(decodeURIComponent(request.query.inheritedData));
2280
+ } else {
2281
+ inheritedDataObj = JSON.clone(request.query.inheritedData);
2282
+ }
2283
+
2284
+ delete request.query.inheritedData;
2285
+
2286
+ }
2287
+
2288
+ bodyStr = JSON.stringify(request.query).replace(/\"{/g, '{').replace(/}\"/g, '}').replace(/\\/g, '');
2289
+ // false & true case
2290
+ if ( /(\"false\"|\"true\"|\"on\")/i.test(bodyStr) )
2291
+ bodyStr = bodyStr.replace(/\"false\"/ig, false).replace(/\"true\"/ig, true).replace(/\"on\"/ig, true);
2292
+ if ( /(\"null\")/i.test(bodyStr) )
2293
+ bodyStr = bodyStr.replace(/\"null\"/ig, null);
2294
+
2295
+
2296
+ obj = parseBody(decodeURIComponent(bodyStr));
2297
+
2298
+ request.query = merge(obj, inheritedDataObj);
2299
+ delete obj;
2300
+
2301
+ request.get = request.query;
2302
+ }
2303
+ // else, will be matching route params against url context instead, once route is identified
2304
+
2305
+
2306
+ // cleaning
2307
+ request.query = undefined;
2308
+ request.post = undefined;
2309
+ request.put = undefined;
2310
+ request.delete = undefined;
2311
+ break;
2312
+
2313
+ case 'put':
2314
+ // eg.: PUT /user/set/1
2315
+ if ( typeof(request.body) == 'string' ) {
2316
+ // get rid of encoding issues
2317
+ try {
2318
+ if ( !/multipart\/form-data;/.test(request.headers['content-type']) ) {
2319
+ if ( !/application\/x\-www\-form\-urlencoded/.test(request.headers['content-type']) ) {
2320
+ request.body = request.body.replace(/\+/g, ' ');
2321
+ }
2322
+
2323
+ if ( request.body.substr(0,1) == '?')
2324
+ request.body = request.body.substr(1);
2325
+
2326
+ // false & true case
2327
+ try {
2328
+ bodyStr = decodeURIComponent(request.body); // it is already a string for sure
2329
+ } catch (err) {
2330
+ bodyStr = request.body;
2331
+ }
2332
+
2333
+ // false & true case
2334
+ if ( /(\"false\"|\"true\"|\"on\")/.test(bodyStr) )
2335
+ bodyStr = bodyStr.replace(/\"false\"/g, false).replace(/\"true\"/g, true).replace(/\"on\"/g, true);
2336
+ if ( /(\"null\")/i.test(bodyStr) )
2337
+ bodyStr = bodyStr.replace(/\"null\"/ig, null);
2338
+
2339
+ obj = parseBody(bodyStr);
2340
+
2341
+ if ( typeof(obj) != 'undefined' && obj.count() == 0 && bodyStr.length > 1 ) {
2342
+ try {
2343
+ request.put = merge(request.put, obj);
2344
+ } catch (err) {
2345
+ console.log('Case `put` #0 [ merge error ]: ' + (err.stack||err.message))
2346
+ }
2347
+ }
2348
+ }
2349
+
2350
+ } catch (err) {
2351
+ var msg = '[ '+request.url+' ]\nCould not evaluate PUT.\n'+ err.stack;
2352
+ throwError(response, 500, msg, next);
2353
+ return;
2354
+ }
2355
+
2356
+ } else {
2357
+ // 2016-05-19: fix to handle requests from swagger/express
2358
+ if (request.body.count() == 0 && typeof(request.query) != 'string' && request.query.count() > 0 ) {
2359
+ request.body = request.query
2360
+ }
2361
+ bodyStr = JSON.stringify(request.body);
2362
+ // false & true case
2363
+ if ( /(\"false\"|\"true\"|\"on\")/.test(bodyStr) )
2364
+ bodyStr = bodyStr.replace(/\"false\"/g, false).replace(/\"true\"/g, true).replace(/\"on\"/g, true);
2365
+ if ( /(\"null\")/i.test(bodyStr) )
2366
+ bodyStr = bodyStr.replace(/\"null\"/ig, null);
2367
+
2368
+ obj = JSON.parse(bodyStr)
2369
+ }
2370
+
2371
+ if ( obj && typeof(obj) != 'undefined' && obj.count() > 0 ) {
2372
+ // still need this to allow compatibility with express & connect middlewares
2373
+ request.body = request.put = merge(request.put, obj);
2374
+ }
2375
+
2376
+
2377
+ request.query = undefined; // added on september 13 2016
2378
+ request.post = undefined;
2379
+ request.delete = undefined;
2380
+ request.get = undefined;
2381
+
2382
+ delete obj;
2383
+ break;
2384
+
2385
+
2386
+ case 'delete':
2387
+ if ( request.query.count() > 0 ) {
2388
+ request.delete = request.query;
2389
+
2390
+ }
2391
+ // else, matching route params against url context instead once, route is identified
2392
+
2393
+ request.post = undefined;
2394
+ request.put = undefined;
2395
+ request.get = undefined;
2396
+ break
2397
+
2398
+
2399
+ };
2400
+
2401
+ loadBundleConfiguration(request, response, next, function onLoadBundleConfiguration (err, bundle, pathname, config, req, res, next) {
2402
+ if (!req.handled) {
2403
+ req.handled = true;
2404
+ if (err) {
2405
+ throwError(response, 500, 'Internal server error\n' + err.stack, next);
2406
+ return;
2407
+ } else {
2408
+ handle(req, res, next, bundle, pathname, config)
2409
+ }
2410
+ } else {
2411
+ if (typeof(next) != 'undefined')
2412
+ return next();
2413
+ else
2414
+ return;
2415
+ }
2416
+
2417
+ return;
2418
+ })
2419
+ }
2420
+
2421
+ var getHead = function(response, file) {
2422
+ try {
2423
+ var s = file.split(/\./);
2424
+ var ext = s[s.length-1];
2425
+ var type = null;
2426
+ var mime = self.conf[self.appName][self.env].server.coreConfiguration.mime;
2427
+
2428
+ if( typeof(mime[ext]) != 'undefined' ) {
2429
+ type = mime[ext];
2430
+ } else {
2431
+ console.warn('[ '+file+' ] extension: `'+s[2]+'` not supported by gina: `core/mime.types`. Replacing with `plain/text` ')
2432
+ }
2433
+ return type || 'plain/text'
2434
+ } catch (err) {
2435
+ console.error('Error while trying to getHead('+ file +') extention. Replacing with `plain/text` '+ err.stack);
2436
+ return 'plain/text'
2437
+ }
2438
+
2439
+ }
2440
+
2441
+ var loadBundleConfiguration = function(req, res, next, callback) {
2442
+
2443
+ var config = new Config();
2444
+ config.setBundles(self.bundles);
2445
+ var conf = config.getInstance(); // for all loaded bundles
2446
+ if ( typeof(conf) != 'undefined') {//for cacheless mode
2447
+ self.conf = conf;
2448
+ }
2449
+
2450
+ var pathname = req.url;
2451
+ var bundle = self.appName; // by default
2452
+
2453
+ // finding bundle
2454
+ if (self.isStandalone) {
2455
+
2456
+ end:
2457
+ for (var b in conf) {
2458
+ if (self.bundles.indexOf(b) < 0) continue;
2459
+ if ( typeof(conf[b][self.env].content) != 'undefined' && typeof(conf[b][self.env].content.statics) != 'undefined' && conf[b][self.env].content.statics.count() > 0 ) {
2460
+ for (var s in conf[b][self.env].content.statics) {
2461
+ s = (s.substr(0,1) == '/') ? s.substr(1) : s;
2462
+ if ( (new RegExp('^/'+s)).test(pathname) ) {
2463
+ bundle = b;
2464
+ break end
2465
+ }
2466
+ }
2467
+ } else {
2468
+ // no statics ... use startingApp and leave it to handle()
2469
+ self.isNotStatic = true
2470
+ break
2471
+ }
2472
+ }
2473
+ }
2474
+
2475
+
2476
+ if ( /\/favicon\.ico/.test(pathname) && !hasViews(bundle)) {
2477
+ callback(false, bundle, pathname, config, req, res, next);
2478
+ return false
2479
+ }
2480
+
2481
+ onBundleConfigLoaded(bundle, {
2482
+ err : false,
2483
+ config : config,
2484
+ pathname : pathname,
2485
+ req : req,
2486
+ res : res,
2487
+ conf : config,
2488
+ next : next,
2489
+ callback : callback
2490
+ });
2491
+
2492
+ return;
2493
+ }
2494
+
2495
+ var onBundleConfigLoaded = function(bundle, options) {
2496
+ var err = options.err
2497
+ , cacheless = options.config.isCacheless()
2498
+ , pathname = options.pathname
2499
+ , req = options.req
2500
+ , res = options.res
2501
+ , config = options.conf
2502
+ , next = options.next
2503
+ , callback = options.callback;
2504
+
2505
+ //Reloading assets & files.
2506
+ // if (!cacheless) { // all but dev & debug
2507
+ callback(err, bundle, pathname, options.config, req, res, next)
2508
+ // } else {
2509
+ // config.refresh(bundle, function(err, routing) {
2510
+ // if (err) {
2511
+ // throwError(res, 500, 'Internal server error: \n' + (err.stack||err), next)
2512
+ // return;
2513
+ // } else {
2514
+ // refreshing routing at the same time.
2515
+ // self.routing = routing;
2516
+ // callback(err, bundle, pathname, options.config, req, res, next)
2517
+ // }
2518
+ // })
2519
+ // }
2520
+ }
2521
+
2522
+ // Express middleware portability when using another engine instead of expressjs
2523
+ var nextMiddleware = function(err) {
2524
+
2525
+ var router = local.router;
2526
+ var expressMiddlewares = self.instance._expressMiddlewares;
2527
+
2528
+ if (err) {
2529
+ throwError(nextMiddleware._response, 500, (err.stack|err.message|err), nextMiddleware._next, nextMiddleware._nextAction);
2530
+ return;
2531
+ }
2532
+
2533
+ expressMiddlewares[nextMiddleware._index](nextMiddleware._request, nextMiddleware._response, function onNextMiddleware(err, request, response) {
2534
+ ++nextMiddleware._index;
2535
+
2536
+ if (err) {
2537
+ throwError(nextMiddleware._response, 500, (err.stack||err.message||err), nextMiddleware._next, nextMiddleware._nextAction);
2538
+ return;
2539
+ }
2540
+
2541
+ if (request)
2542
+ nextMiddleware._request = request;
2543
+
2544
+ if (response)
2545
+ nextMiddleware._response = response;
2546
+
2547
+ if (nextMiddleware._index > nextMiddleware._count) {
2548
+
2549
+ if ( nextMiddleware._nextAction == 'route' ) {
2550
+
2551
+ router._server = self.instance;
2552
+ router.route(nextMiddleware._request, nextMiddleware._response, nextMiddleware._next, nextMiddleware._request.routing)
2553
+
2554
+ } else { // handle statics
2555
+ self._responseHeaders = nextMiddleware._response.getHeaders();
2556
+ handleStatics(nextMiddleware._staticProps, nextMiddleware._request, nextMiddleware._response, nextMiddleware._next);
2557
+ }
2558
+
2559
+ } else {
2560
+ nextMiddleware.call(this, err, true)
2561
+ }
2562
+ });
2563
+ };
2564
+
2565
+ var checkPreflightRequest = function(request) {
2566
+ var config = self.conf[self.appName][self.env];
2567
+ // by default, if not set in `${projectPath}/env.json`
2568
+ var corsMethod = 'GET, POST, HEAD';
2569
+ // See https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
2570
+ if (
2571
+ typeof(config.server.response.header['access-control-allow-methods']) != 'undefined'
2572
+ &&
2573
+ config.server.response.header['access-control-allow-methods'] != ''
2574
+ ) {
2575
+ // as defined in `${projectPath}/env.json`
2576
+ corsMethod = config.server.response.header['access-control-allow-methods'];
2577
+ }
2578
+
2579
+ var method = ( /http\/2/.test(config.server.protocol) ) ? request.headers[':method'] : request.method
2580
+ //, reMethod = new RegExp(method, 'i')
2581
+ , reAccessAllowMethod = new RegExp('(' + corsMethod.replace(/\,\s+|\s+\,|\,/g, '|') +')', 'i')
2582
+ // preflight support - conditions required
2583
+ , isPreflightRequest = (
2584
+ // must meet all the following conditions
2585
+ /OPTIONS/i.test(method)
2586
+ && typeof(request.headers['access-control-request-method']) != 'undefined'
2587
+
2588
+ // as defined in `${projectPath}/env.json`,
2589
+ // request method must match: config.server.response.header['access-control-allow-methods']
2590
+ && reAccessAllowMethod.test(request.headers['access-control-request-method'])
2591
+ && typeof(request.headers['access-control-request-headers']) != 'undefined'
2592
+ ) ? true : false
2593
+ , accessControlRequestHeaders = null
2594
+ , serverResponseHeaders = config.server.response.header//config.envConf[self.appName][self.env].server.response.header
2595
+ ;
2596
+
2597
+ // additional checks
2598
+ // /(application\/x\-www\-form\-urlencoded|multipart\/form\-data|text\/plain)/i.test(request.headers['accept'])
2599
+
2600
+ request.isPreflightRequest = isPreflightRequest;
2601
+ if (isPreflightRequest) { // update request/response
2602
+ method = request.headers['access-control-request-method'];
2603
+ // updating to avoid conflict with requested route
2604
+ if ( /http\/2/.test(config.server.protocol) ) {
2605
+ request.headers[':method'] = method;
2606
+ } else {
2607
+ request.method = method
2608
+ }
2609
+ accessControlRequestHeaders = ( typeof(request.headers['access-control-request-headers']) != 'undefined' ) ? request.headers['access-control-request-headers'] : '';
2610
+ if ( typeof(request.headers['access-control-request-credentials']) != 'undefined' && typeof(serverResponseHeaders['access-control-allow-credentials']) != 'undefined' ) {
2611
+ request.isWithCredentials = true;
2612
+ }
2613
+ if (accessControlRequestHeaders.length > 0) {
2614
+ for (var h in accessControlRequestHeaders) {
2615
+ if ( /x\-requested\-with/i.test(h) && /x\-requested\-with/i.test(serverResponseHeaders['access-control-allow-headers']) ) {
2616
+ request.isXMLRequest = true;
2617
+ }
2618
+ }
2619
+ }
2620
+ }
2621
+
2622
+ return request
2623
+ }
2624
+
2625
+ var handle = async function(req, res, next, bundle, pathname, config) {
2626
+
2627
+ var matched = false
2628
+ , isRoute = {}
2629
+ , withViews = hasViews(bundle)
2630
+ , router = local.router
2631
+ , cacheless = config.isCacheless()
2632
+ , wroot = null
2633
+ ;
2634
+
2635
+ //matched = routingUtils.getRouteByUrl(req.url, bundle, (req.method||req[':method']), req);
2636
+
2637
+ req = checkPreflightRequest(req);
2638
+ var params = {}
2639
+ , _routing = {}
2640
+ , method = ( /http\/2/.test(self.conf[self.appName][self.env].server.protocol) ) ? req.headers[':method'] : req.method
2641
+ , reMethod = new RegExp(method, 'i')
2642
+ ;
2643
+ try {
2644
+
2645
+
2646
+ var routing = config.getRouting(bundle, self.env);
2647
+
2648
+ if ( routing == null || routing.count() == 0 ) {
2649
+ console.error('Malformed routing or Null value for bundle [' + bundle + '] => ' + req.url);
2650
+ throwError(res, 500, 'Internal server error\nMalformed routing or Null value for bundle [' + bundle + '] => ' + req.url, next);
2651
+ return;
2652
+ }
2653
+
2654
+ } catch (err) {
2655
+ throwError(res, 500, err.stack, next);
2656
+ return;
2657
+ }
2658
+ var isMethodAllowed = null, hostname = null;
2659
+ out:
2660
+ for (var name in routing) {
2661
+ if (typeof(routing[name]['param']) == 'undefined')
2662
+ break;
2663
+
2664
+ // updating hostname
2665
+ // if (
2666
+ // typeof(routing[name].hostname) == 'undefined' && !/^redirect$/.test(routing[name].param.control)
2667
+ // || !routing[name].hostname && !/^redirect$/.test(routing[name].param.control)
2668
+ // ) {
2669
+ // hostname = self.conf[routing[name].bundle][self.env].hostname;
2670
+ // routing[name].hostname = self.conf.routing[name].hostname = hostname;
2671
+ // }
2672
+
2673
+ // For debug only
2674
+ // if ( name == 'name-of-targeted-rule@bundle') {
2675
+ // console.debug('checking: ', name);
2676
+ // }
2677
+
2678
+ if (routing[name].bundle != bundle) continue;
2679
+ // method filter
2680
+ method = routing[name].method;
2681
+ if ( /\,/.test( method ) && reMethod.test(method) ) {
2682
+ method = req.method
2683
+ }
2684
+
2685
+ //Preparing params to relay to the router.
2686
+ params = {
2687
+ method : method,
2688
+ requirements : routing[name].requirements,
2689
+ namespace : routing[name].namespace || undefined,
2690
+ url : unescape(pathname), /// avoid %20
2691
+ rule : routing[name].originalRule || name,
2692
+ param : JSON.clone(routing[name].param),
2693
+ middleware : JSON.clone(routing[name].middleware),
2694
+ bundle : routing[name].bundle,
2695
+ isXMLRequest : req.isXMLRequest,
2696
+ isWithCredentials : req.isWithCredentials
2697
+ };
2698
+
2699
+ //Parsing for the right url.
2700
+ try {
2701
+ isRoute = await routingUtils.compareUrls(params, routing[name].url, req, res, next);
2702
+ } catch (err) {
2703
+ var msg = 'Internal server error.\nRule [ '+name+' ] needs your attention.\n';
2704
+ // TODO - Refactor `ApiError`to handle the following param
2705
+ // var e = new ApiError({ message: msg, stack: err.stack});
2706
+ // throwError(res, e)
2707
+ throwError(res, 500, 'Internal server error.\nRule [ '+name+' ] needs your attention.\n'+ err.stack);
2708
+ break;
2709
+ }
2710
+
2711
+ if ( pathname == routing[name].url || isRoute.past ) {
2712
+
2713
+ _routing = req.routing;
2714
+
2715
+ // comparing routing method VS request.url method
2716
+ isMethodAllowed = reMethod.test(_routing.method);
2717
+ if (!isMethodAllowed) {
2718
+ // Exception - Method override
2719
+ if ( /get/i.test(req.method) && /delete/i.test(_routing.method) ) {
2720
+ console.debug('ignoring case request.method[GET] on routing.method[DELETE]');
2721
+ req.method = _routing.method;
2722
+ isMethodAllowed = true;
2723
+ } else {
2724
+ throwError(res, 405, 'Method Not Allowed.\n'+ ' `'+req.url+'` is expecting `' + _routing.method.toUpperCase() +'` method but got `'+ req.method.toUpperCase() +'` instead');
2725
+ break;
2726
+ }
2727
+ }// else {
2728
+
2729
+ // handling GET method exception - if no param found
2730
+ var methods = ['get', 'delete'], method = req.method.toLowerCase();
2731
+ var p = null;
2732
+ if (
2733
+ methods.indexOf(method) > -1 && typeof(req.query) != 'undefined' && req.query.count() == 0
2734
+ || methods.indexOf(method) > -1 && typeof(req.query) == 'undefined' && typeof(req.params) != 'undefined' && req.params.count() > 1
2735
+ ) {
2736
+ //req.params = parseObject(req.params);
2737
+ p = 0;
2738
+ for (let parameter in req.params) {
2739
+ if (p > 0) {
2740
+ // false & true case
2741
+ if ( /^(false|true|on)$/.test( req.params[parameter] ) && typeof(req.params[parameter]) == 'string' )
2742
+ req.params[parameter] = ( /^(true|on)$/.test( req.params[parameter] ) ) ? true : false;
2743
+
2744
+ req[method][parameter] = req.params[parameter]
2745
+ }
2746
+ ++p
2747
+ }
2748
+
2749
+ } else if ( method == 'put' ) { // merging req.params with req.put (passed through URI)
2750
+ p = 0;
2751
+ for (let parameter in req.params) {
2752
+ if (p > 0) {
2753
+ // false & true case
2754
+ if ( /^(false|true|on)$/.test( req.params[parameter] ) && typeof(req.params[parameter]) == 'string' )
2755
+ req.params[parameter] = ( /^(true|on)$/.test( req.params[parameter] ) ) ? true : false;
2756
+
2757
+ req[method][parameter] = req.params[parameter]
2758
+ }
2759
+ ++p
2760
+ }
2761
+ }
2762
+
2763
+
2764
+ // onRouting Event ???
2765
+ if (isRoute.past) {
2766
+ matched = true;
2767
+ isRoute = {};
2768
+
2769
+ break;
2770
+ }
2771
+ //}
2772
+ }
2773
+ }
2774
+
2775
+
2776
+
2777
+ if (matched) {
2778
+ if ( /^isaac/.test(self.engine) && self.instance._expressMiddlewares.length > 0) {
2779
+ nextMiddleware._index = 0;
2780
+ nextMiddleware._count = self.instance._expressMiddlewares.length-1;
2781
+ nextMiddleware._request = req;
2782
+ nextMiddleware._response = res;
2783
+ nextMiddleware._next = next;
2784
+ nextMiddleware._nextAction = 'route'
2785
+
2786
+ nextMiddleware()
2787
+ } else {
2788
+ router._server = self.instance;
2789
+ router.route(req, res, next, req.routing)
2790
+ }
2791
+ } else {
2792
+ throwError(res, 404, 'Page not found: \n' + pathname, next);
2793
+ return;
2794
+ }
2795
+ }
2796
+
2797
+
2798
+
2799
+
2800
+ var throwError = function(res, code, msg, next) {
2801
+
2802
+ var withViews = local.hasViews[self.appName] || hasViews(self.appName);
2803
+ var isUsingTemplate = self.conf[self.appName][self.env].template;
2804
+ var isXMLRequest = local.request.isXMLRequest;
2805
+ var protocol = getResponseProtocol(res);
2806
+ var stream = ( /http\/2/.test(protocol) && res.stream ) ? res.stream : null;
2807
+ var header = ( /http\/2/.test(protocol) && res.stream ) ? {} : null;
2808
+ var err = null;
2809
+ var bundleConf = self.conf[self.appName][self.env];
2810
+
2811
+ if ( typeof(msg) != 'object' ) {
2812
+ err = {
2813
+ code: code,
2814
+ message: msg
2815
+ }
2816
+ } else {
2817
+ err = JSON.clone(msg);
2818
+ }
2819
+
2820
+ if (!res.headersSent) {
2821
+ res.headersSent = true;
2822
+ local.request = checkPreflightRequest(local.request);
2823
+ // updated filter on controller.js : 2020/09/25
2824
+ //if (isXMLRequest || !withViews || !isUsingTemplate ) {
2825
+ if (isXMLRequest || !withViews || !isUsingTemplate || withViews && !isUsingTemplate ) {
2826
+ // allowing this.throwError(err)
2827
+ if ( typeof(code) == 'object' && !msg && typeof(code.status) != 'undefined' && typeof(code.error) != 'undefined' ) {
2828
+ msg = code.error;
2829
+ code = code.status;
2830
+ }
2831
+
2832
+ // Internet Explorer override
2833
+ if ( /msie/i.test(local.request.headers['user-agent']) ) {
2834
+ if ( /http\/2/.test(protocol) && stream ) {
2835
+ header = {
2836
+ ':status': code,
2837
+ 'content-type': 'text/plain; charset='+ bundleConf.encoding
2838
+ //'content-type': bundleConf.server.coreConfiguration.mime[ext]+'; charset='+ bundleConf.encoding
2839
+ };
2840
+ } else {
2841
+ res.writeHead(code, 'content-type', 'text/plain; charset='+ bundleConf.encoding)
2842
+ }
2843
+
2844
+ } else {
2845
+ if ( /http\/2/.test(protocol) && stream ) {
2846
+ header = {
2847
+ ':status': code,
2848
+ 'content-type': 'application/json; charset='+ bundleConf.encoding
2849
+ };
2850
+ } else {
2851
+ res.writeHead(code, { 'content-type': 'application/json; charset='+ bundleConf.encoding } )
2852
+ }
2853
+ }
2854
+
2855
+ console.error('[ BUNDLE ][ '+self.appName+' ] '+ local.request.method +' [ '+code+' ] '+ local.request.url);
2856
+
2857
+ header = completeHeaders(header, local.request, res);
2858
+ if ( /http\/2/.test(protocol) && stream) {
2859
+ stream.respond(header);
2860
+ stream.end(JSON.stringify({
2861
+ status: code,
2862
+ error: msg
2863
+ }));
2864
+
2865
+ } else {
2866
+ res.end(JSON.stringify({
2867
+ status: code,
2868
+ error: msg
2869
+ }));
2870
+ }
2871
+ return;
2872
+
2873
+ } else {
2874
+
2875
+ //console.error('[ BUNDLE ][ '+self.appName+' ] '+ local.request.method +' [ '+code+' ] '+ local.request.url);
2876
+ console.error(local.request.method +' [ '+code+' ] '+ local.request.url);
2877
+ // intercept none HTML mime types
2878
+ var url = unescape(local.request.url) /// avoid %20
2879
+ , ext = null
2880
+ , isHtmlContent = false
2881
+ , hasCustomErrorFile = false
2882
+ , eCode = code.toString().substr(0,1) + 'xx'
2883
+ ;
2884
+ var extArr = url.substr(url.lastIndexOf('.')).match(/(\.[A-Za-z0-9]+)/);
2885
+ if (extArr) {
2886
+ ext = extArr[0].substr(1);
2887
+ }
2888
+ if ( !ext || /^(html|htm)$/i.test(ext) ) {
2889
+ isHtmlContent = true;
2890
+ }
2891
+
2892
+ if (
2893
+ isHtmlContent
2894
+ && typeof(bundleConf.content.templates._common.errorFiles) != 'undefined'
2895
+ && typeof(bundleConf.content.templates._common.errorFiles[code]) != 'undefined'
2896
+ ||
2897
+ isHtmlContent
2898
+ && typeof(bundleConf.content.templates._common.errorFiles) != 'undefined'
2899
+ && typeof(bundleConf.content.templates._common.errorFiles[eCode]) != 'undefined'
2900
+ ) {
2901
+ hasCustomErrorFile = true;
2902
+
2903
+ var eFilename = null
2904
+ , eData = {
2905
+ isRenderingCustomError : true,
2906
+ bundle : self.appName,
2907
+ status : code || null,
2908
+ message : msg || null,
2909
+ pathname : url
2910
+ }
2911
+ ;
2912
+
2913
+ if ( typeof(err) == 'object' && err.count() > 0 ) {
2914
+ if ( typeof(err.stack) != 'undefined' ) {
2915
+ eData.stack = err.stack
2916
+ }
2917
+ if ( !eData.message && typeof(err.message) != 'undefined' ) {
2918
+ eData.message = err.message
2919
+ }
2920
+ }
2921
+ if (
2922
+ code
2923
+ // See: framework/${version}/core/status.code
2924
+ && typeof(bundleConf.server.coreConfiguration.statusCodes[code]) != 'undefined'
2925
+ ) {
2926
+ eData.title = bundleConf.server.coreConfiguration.statusCodes[code];
2927
+ }
2928
+
2929
+ if ( typeof(local.request.routing) != 'undefined' ) {
2930
+ eData.routing = local.request.routing;
2931
+ }
2932
+
2933
+ if (typeof(bundleConf.content.templates._common.errorFiles[code]) != 'undefined') {
2934
+ eFilename = bundleConf.content.templates._common.errorFiles[code];
2935
+ } else {
2936
+ eFilename = bundleConf.content.templates._common.errorFiles[eCode];
2937
+ }
2938
+
2939
+ var eRule = 'custom-error-page@'+ self.appName;
2940
+ var routeObj = routingUtils.getRoute(eRule);
2941
+ routeObj.rule = eRule;
2942
+ routeObj.url = url;
2943
+ routeObj.param.title = ( typeof(eData.title) != 'undefined' ) ? eData.title : 'Error ' + eData.status;
2944
+ routeObj.param.file = eFilename;
2945
+ routeObj.param.error = eData;
2946
+ routeObj.param.displayToolbar = self.isCacheless();
2947
+
2948
+ local.request.routing = routeObj;
2949
+
2950
+ // if ( /^isaac/.test(self.engine) && self.instance._expressMiddlewares.length > 0) {
2951
+ // nextMiddleware._index = 0;
2952
+ // nextMiddleware._count = self.instance._expressMiddlewares.length-1;
2953
+ // nextMiddleware._request = local.request;
2954
+ // nextMiddleware._response = res;
2955
+ // nextMiddleware._next = next;
2956
+ // nextMiddleware._nextAction = 'route'
2957
+
2958
+ // nextMiddleware()
2959
+ // } else {
2960
+ var router = local.router;
2961
+ if ( typeof(router._server) == 'undefined' ) {
2962
+ router._server = self.instance;
2963
+ }
2964
+ router.route(local.request, res, next, local.request.routing);
2965
+ // }
2966
+
2967
+ return;
2968
+ }
2969
+
2970
+ if ( /http\/2/.test(protocol) && stream ) {
2971
+ header = {
2972
+ ':status': code,
2973
+ 'content-type': bundleConf.server.coreConfiguration.mime[ext]+'; charset='+ bundleConf.encoding
2974
+ };
2975
+ } else {
2976
+ res.writeHead(code, { 'content-type': bundleConf.server.coreConfiguration.mime[ext]+'; charset='+ bundleConf.encoding });
2977
+ }
2978
+
2979
+ header = completeHeaders(header, local.request, res);
2980
+ if ( /http\/2/.test(protocol) && stream ) {
2981
+ // TODO - Check if the stream has not been closed before sending response
2982
+ // if (stream && !stream.destroyed) {
2983
+ stream.respond(header);
2984
+ if ( isHtmlContent && !hasCustomErrorFile ) {
2985
+ stream.end('<html><body><pre><h1>Error '+ code +'.</h1><pre>'+ msg + '</pre></body></html>');
2986
+ } else {
2987
+ stream.end();
2988
+ }
2989
+
2990
+ // }
2991
+ } else {
2992
+ if ( isHtmlContent && !hasCustomErrorFile ) {
2993
+ res.end('<html><body><pre><h1>Error '+ code +'.</h1><pre>'+ msg + '</pre></body><html>');
2994
+ } else {
2995
+ res.end()
2996
+ }
2997
+ }
2998
+ return;
2999
+ }
3000
+
3001
+ } else {
3002
+ if ( typeof(next) != 'undefined' )
3003
+ next();
3004
+ return;
3005
+ }
3006
+ }
3007
+ };
3008
+
3009
+ Server = inherits(Server, EventEmitter);
3010
+ module.exports = Server