jsgui3-server 0.0.121 → 0.0.122

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 (278) hide show
  1. package/.vscode/settings.json +6 -0
  2. package/README.md +10 -10
  3. package/controls/Active_HTML_Document.js +116 -116
  4. package/controls/README.md +7 -7
  5. package/controls/page/admin.js +74 -74
  6. package/controls/panel/admin.js +11 -11
  7. package/examples/_css/basic.css +913 -913
  8. package/examples/_css/database-control.css +51 -51
  9. package/examples/_css/jsgui.css +66 -66
  10. package/examples/_css/multi-layout.css +23 -23
  11. package/examples/_css/style.css +1669 -1669
  12. package/examples/_css/top-and-bottom-bars.css +54 -54
  13. package/examples/box/1) square box/client.js +188 -188
  14. package/examples/box/1) square box/server.js +112 -112
  15. package/examples/box/2) twenty square boxes/css flex wrap/client.js +248 -248
  16. package/examples/box/2) twenty square boxes/css flex wrap/server.js +112 -112
  17. package/examples/boxes/square_boxes.js +45 -48
  18. package/examples/boxes/square_boxes_client.js +132 -136
  19. package/examples/client-side-popup-menu-button.html +93 -93
  20. package/examples/color_palette.js +51 -51
  21. package/examples/color_palette_client.js +95 -95
  22. package/examples/controls/1) window/client.js +186 -186
  23. package/examples/controls/1) window/server.js +117 -117
  24. package/examples/controls/10) window, mirrored text inputs/client.js +320 -320
  25. package/examples/controls/10) window, mirrored text inputs/server.js +117 -117
  26. package/examples/controls/11) window, mirrored text fields/client.js +493 -251
  27. package/examples/controls/11) window, mirrored text fields/server.js +117 -117
  28. package/examples/controls/11b) window, shared Data_Object model mirrored text fields/client.js +613 -331
  29. package/examples/controls/11b) window, shared Data_Object model mirrored text fields/server.js +117 -117
  30. package/examples/controls/11c) window, shared Data_Value model mirrored text fields/client.js +617 -617
  31. package/examples/controls/11c) window, shared Data_Value model mirrored text fields/server.js +117 -117
  32. package/examples/controls/11d) window, shared model mirrored integer text fields/client.js +611 -280
  33. package/examples/controls/11d) window, shared model mirrored integer text fields/server.js +134 -22
  34. package/examples/controls/12) window, Select_Options control/client.js +435 -452
  35. package/examples/controls/12) window, Select_Options control/server.js +117 -117
  36. package/examples/controls/2) two windows/client.js +193 -193
  37. package/examples/controls/2) two windows/server.js +113 -113
  38. package/examples/controls/3) five windows/client.js +217 -217
  39. package/examples/controls/3) five windows/server.js +116 -115
  40. package/examples/controls/4) window, tabbed panel/client.js +54 -225
  41. package/examples/controls/4) window, tabbed panel/server.js +17 -117
  42. package/examples/controls/5) window, grid/client.js +204 -484
  43. package/examples/controls/5) window, grid/server.js +117 -119
  44. package/examples/controls/6) window, color_palette/client.js +204 -204
  45. package/examples/controls/6) window, color_palette/server.js +117 -117
  46. package/examples/controls/7) window, month_view/client.js +40 -231
  47. package/examples/controls/7) window, month_view/server.js +117 -117
  48. package/examples/controls/8) window, checkbox/client.js +247 -209
  49. package/examples/controls/8) window, checkbox/server.js +117 -117
  50. package/examples/controls/9) window, date picker/client.js +303 -303
  51. package/examples/controls/9) window, date picker/server.js +117 -117
  52. package/examples/controls/9b) window, shared data.model mirrored date pickers/client.js +398 -398
  53. package/examples/controls/9b) window, shared data.model mirrored date pickers/server.js +117 -117
  54. package/examples/controls/__old/_html-server-color-palette.js +114 -114
  55. package/examples/controls/__old/html-server-combo-box.js +104 -104
  56. package/examples/controls/__old/html-server-list.js +98 -98
  57. package/examples/controls/__old/html-server-popup-menu-button.js +114 -114
  58. package/examples/controls/__old/html-server-start-stop-toggle-button.js +146 -146
  59. package/examples/controls/__old/scs-arrow-button.js +36 -36
  60. package/examples/controls/__old/scs-date-picker.js +157 -157
  61. package/examples/controls/__old/scs-file-browser.js +82 -82
  62. package/examples/controls/__old/scs-item.js +159 -159
  63. package/examples/controls/__old/scs-month-arrow-selector.js +126 -126
  64. package/examples/controls/__old/scs-month-view.js +94 -94
  65. package/examples/controls/__old/scs-start-stop-toggle-button.js +40 -40
  66. package/examples/controls/__old/scs-tree.js +49 -49
  67. package/examples/controls/__old/scs-year-arrow-selector.js +127 -127
  68. package/examples/demos/date-picker.js +119 -119
  69. package/examples/demos/explain-encapsulation.js +9 -9
  70. package/examples/demos/resizing.js +35 -35
  71. package/examples/demos/server_time.js +6 -6
  72. package/examples/grids/grid_1.js +45 -45
  73. package/examples/grids/grid_1_client.js +329 -329
  74. package/examples/html-rendering.js +20 -20
  75. package/examples/html-server.js +105 -105
  76. package/examples/introducing jsgui3/server.js +110 -110
  77. package/examples/mx_display/mx_display_1.js +45 -45
  78. package/examples/mx_display/mx_display_1_client.js +444 -444
  79. package/fs2.js +1836 -1836
  80. package/http/responders/HTTP_Responder.js +15 -15
  81. package/http/responders/static/Static_Route_HTTP_Responder.js +105 -105
  82. package/module.js +34 -34
  83. package/old/_single-control-server.js +418 -418
  84. package/old/single-control-server.js +368 -368
  85. package/old/single-page-app.js +131 -131
  86. package/package.json +42 -42
  87. package/page-context.js +92 -92
  88. package/publishers/helpers/assigners/Assigner.js +10 -10
  89. package/publishers/helpers/assigners/static-compressed-response-buffers/Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner.js +150 -150
  90. package/publishers/helpers/assigners/static-headers/Single_Control_Webpage_Server_Static_Headers_Assigner.js +109 -109
  91. package/publishers/helpers/assigners/static-routes/Single_Control_Webpage_Server_Static_Routes_Assigner.js +91 -91
  92. package/publishers/helpers/assigners/static-uncompressed-response-buffers/Single_Control_Webpage_Server_Static_Uncompressed_Response_Buffers_Assigner.js +104 -104
  93. package/publishers/helpers/preparers/static/bundle/Ready_To_Serve_Preparer.js +18 -18
  94. package/publishers/helpers/preparers/static/bundle/Static_Routes_Responses_Webpage_Bundle_Preparer.js +44 -44
  95. package/publishers/http-function-publisher.js +212 -212
  96. package/publishers/http-html-page-publisher.js +5 -5
  97. package/publishers/http-html-publisher.js +24 -24
  98. package/publishers/http-js-publisher.js +135 -135
  99. package/publishers/http-observable-publisher.js +124 -124
  100. package/publishers/http-publisher.js +53 -53
  101. package/publishers/http-resource-publisher.js +325 -325
  102. package/publishers/http-webpage-publisher.js +659 -658
  103. package/publishers/http-webpageorsite-publisher.js +343 -343
  104. package/publishers/http-website-publisher.js +640 -640
  105. package/publishers/notes.md +9 -9
  106. package/resources/README.md +16 -16
  107. package/resources/_old_website-javascript-resource.js +994 -994
  108. package/resources/_old_website-resource.js +507 -507
  109. package/resources/compile/server-resource-compilation.js +43 -43
  110. package/resources/data-resource.js +118 -118
  111. package/resources/fs-resource.js +146 -146
  112. package/resources/jsbuilder/Abstract_Single_Declaration.js +105 -105
  113. package/resources/jsbuilder/Abstract_Single_Declaration_Sequence.js +42 -42
  114. package/resources/jsbuilder/JS_AST/JS_AST_Abstract_Node.js +61 -61
  115. package/resources/jsbuilder/JS_AST/JS_AST_Abstract_Node_Group.js +41 -41
  116. package/resources/jsbuilder/JS_AST/JS_AST_Group_Shared.js +61 -61
  117. package/resources/jsbuilder/JS_AST/JS_AST_Node.js +93 -93
  118. package/resources/jsbuilder/JS_AST/JS_AST_Node_0-Core.js +253 -253
  119. package/resources/jsbuilder/JS_AST/JS_AST_Node_1-Babel.js +337 -337
  120. package/resources/jsbuilder/JS_AST/JS_AST_Node_10-Changing.js +39 -39
  121. package/resources/jsbuilder/JS_AST/JS_AST_Node_2.1.1-Child.js +96 -96
  122. package/resources/jsbuilder/JS_AST/JS_AST_Node_2.1.2-Parent.js +37 -37
  123. package/resources/jsbuilder/JS_AST/JS_AST_Node_2.1.3-Ancestor.js +61 -61
  124. package/resources/jsbuilder/JS_AST/JS_AST_Node_2.2-Inner.js +43 -43
  125. package/resources/jsbuilder/JS_AST/JS_AST_Node_2.3-All.js +72 -72
  126. package/resources/jsbuilder/JS_AST/JS_AST_Node_2.4-Sibling.js +92 -92
  127. package/resources/jsbuilder/JS_AST/JS_AST_Node_2.5-Available_In_Scope.js +29 -29
  128. package/resources/jsbuilder/JS_AST/JS_AST_Node_2.9-Signature.js +116 -116
  129. package/resources/jsbuilder/JS_AST/JS_AST_Node_3-Basics.js +159 -159
  130. package/resources/jsbuilder/JS_AST/JS_AST_Node_3.0.0-Basics_First.js +178 -178
  131. package/resources/jsbuilder/JS_AST/JS_AST_Node_3.0.1-Basics_Second.js +87 -87
  132. package/resources/jsbuilder/JS_AST/JS_AST_Node_3.0.99-Basics_Last.js +91 -91
  133. package/resources/jsbuilder/JS_AST/JS_AST_Node_3.1-Basics_Each.js +136 -136
  134. package/resources/jsbuilder/JS_AST/JS_AST_Node_3.1.5-Basics_Count.js +73 -73
  135. package/resources/jsbuilder/JS_AST/JS_AST_Node_3.2-Basics_Filter.js +39 -39
  136. package/resources/jsbuilder/JS_AST/JS_AST_Node_3.3-Basics_Collect.js +85 -85
  137. package/resources/jsbuilder/JS_AST/JS_AST_Node_3.4-Basics_Select.js +42 -42
  138. package/resources/jsbuilder/JS_AST/JS_AST_Node_3.5-Basics_Find.js +40 -40
  139. package/resources/jsbuilder/JS_AST/JS_AST_Node_3.6-Basics_Callmap.js +54 -54
  140. package/resources/jsbuilder/JS_AST/JS_AST_Node_4.0-Index_Indexes.js +45 -45
  141. package/resources/jsbuilder/JS_AST/JS_AST_Node_4.1-Index.js +343 -343
  142. package/resources/jsbuilder/JS_AST/JS_AST_Node_5.0-Category.js +38 -38
  143. package/resources/jsbuilder/JS_AST/JS_AST_Node_5.1-Category_Identifier.js +30 -30
  144. package/resources/jsbuilder/JS_AST/JS_AST_Node_5.2-Category_Literal.js +28 -28
  145. package/resources/jsbuilder/JS_AST/JS_AST_Node_5.3-Category_Expression.js +26 -26
  146. package/resources/jsbuilder/JS_AST/JS_AST_Node_5.4-Category_Pattern.js +8 -8
  147. package/resources/jsbuilder/JS_AST/JS_AST_Node_5.5-Category_Declaration.js +43 -43
  148. package/resources/jsbuilder/JS_AST/JS_AST_Node_5.6-Category_Statement.js +21 -21
  149. package/resources/jsbuilder/JS_AST/JS_AST_Node_6.0-Type.js +89 -89
  150. package/resources/jsbuilder/JS_AST/JS_AST_Node_6.1-Type_Class_Declaration.js +8 -8
  151. package/resources/jsbuilder/JS_AST/JS_AST_Node_6.2-Type_Variable_Declaration.js +27 -27
  152. package/resources/jsbuilder/JS_AST/JS_AST_Node_6.3-Type_Variable_Declarator.js +28 -28
  153. package/resources/jsbuilder/JS_AST/JS_AST_Node_7-Query.js +736 -736
  154. package/resources/jsbuilder/JS_AST/JS_AST_Node_8-Features.js +64 -64
  155. package/resources/jsbuilder/JS_AST/JS_AST_Node_9-Planning.js +31 -31
  156. package/resources/jsbuilder/JS_AST/JS_AST_Node_Arrangement.js +15 -15
  157. package/resources/jsbuilder/JS_AST/JS_AST_Node_Feature/JS_AST_Node_Declared_Object.js +305 -305
  158. package/resources/jsbuilder/JS_AST/JS_AST_Node_Feature/JS_AST_Node_Feature.js +77 -77
  159. package/resources/jsbuilder/JS_AST/JS_AST_Node_Feature/JS_AST_Node_Feature_Declaration.js +248 -248
  160. package/resources/jsbuilder/JS_AST/JS_AST_Node_Feature/JS_AST_Node_Feature_Declarator.js +138 -138
  161. package/resources/jsbuilder/JS_AST/JS_AST_Node_Feature/JS_AST_Root_Node_Feature/JS_AST_Root_Node_Feature.js +10 -10
  162. package/resources/jsbuilder/JS_AST/JS_AST_Node_Feature/JS_AST_Root_Node_Feature/JS_AST_Root_Node_Feature_Exported.js +100 -100
  163. package/resources/jsbuilder/JS_AST/JS_AST_Node_Feature/JS_AST_Root_Node_Feature/JS_AST_Root_Node_Feature_Exports.js +60 -60
  164. package/resources/jsbuilder/JS_AST/JS_AST_Node_Feature/JS_AST_Root_Node_Feature/JS_AST_Root_Node_Interpreted.js +179 -179
  165. package/resources/jsbuilder/JS_AST/JS_AST_Node_Feature/JS_AST_Root_Node_Feature/_JSGUI_Root_Node_Interpreted.js +43 -43
  166. package/resources/jsbuilder/JS_AST/JS_AST_Node_Feature/JS_AST_Root_Node_Feature/special_case_objectassign_to_object.js +12 -12
  167. package/resources/jsbuilder/JS_AST/JS_AST_Node_Group.js +35 -35
  168. package/resources/jsbuilder/JS_AST/JS_AST_Operation.js +11 -11
  169. package/resources/jsbuilder/JS_AST/JS_AST_Operation_On_Relationship.js +31 -31
  170. package/resources/jsbuilder/JS_AST/JS_AST_Ordered_Relationship_Node_To_Group.js +37 -37
  171. package/resources/jsbuilder/JS_AST/JS_AST_Ordinal.js +39 -39
  172. package/resources/jsbuilder/JS_AST/JS_AST_Ordinal_Relationship.js +25 -25
  173. package/resources/jsbuilder/JS_AST/JS_AST_Relationship_Node_To_Group.js +200 -200
  174. package/resources/jsbuilder/JS_AST/JS_AST_Relationship_Node_Within_Group_To_Node.js +43 -43
  175. package/resources/jsbuilder/JS_AST/_JS_AST_Node_3.8-Query_Features.js +76 -76
  176. package/resources/jsbuilder/JS_AST/query/enable_array_as_queryable.js +227 -227
  177. package/resources/jsbuilder/JS_AST/query/find_object_keys.js +404 -404
  178. package/resources/jsbuilder/JS_AST/query/node_queries.js +8 -8
  179. package/resources/jsbuilder/JS_AST/query/root_query_identidy.js +11 -11
  180. package/resources/jsbuilder/JS_AST_Node_Extended/JSGUI_Singular_Declaration.js +85 -85
  181. package/resources/jsbuilder/JS_AST_Node_Extended/JS_AST_Node_Declaration.js +123 -123
  182. package/resources/jsbuilder/JS_AST_Node_Extended/JS_AST_Node_Extended.js +87 -87
  183. package/resources/jsbuilder/JS_AST_Node_Extended/JS_AST_Node_Extended_0-Core.js +10 -10
  184. package/resources/jsbuilder/JS_Builder.js +10 -10
  185. package/resources/jsbuilder/JS_File/Feature/JS_File_Declared_Object.js +31 -31
  186. package/resources/jsbuilder/JS_File/Feature/JS_File_Exported_Object_Info.js +25 -25
  187. package/resources/jsbuilder/JS_File/Feature/JS_File_Exports.js +78 -78
  188. package/resources/jsbuilder/JS_File/Feature/JS_File_Feature.js +17 -17
  189. package/resources/jsbuilder/JS_File/Feature/JS_File_Imported_Object_Info.js +25 -25
  190. package/resources/jsbuilder/JS_File/Feature/JS_File_Imports.js +8 -8
  191. package/resources/jsbuilder/JS_File/JS_File.js +12 -12
  192. package/resources/jsbuilder/JS_File/JS_File_0-Core.js +202 -202
  193. package/resources/jsbuilder/JS_File/JS_File_1-Early_Parse.js +175 -175
  194. package/resources/jsbuilder/JS_File/JS_File_2-Babel.js +81 -81
  195. package/resources/jsbuilder/JS_File/JS_File_3-JS_AST_Node.js +86 -86
  196. package/resources/jsbuilder/JS_File/JS_File_4-Query.js +413 -413
  197. package/resources/jsbuilder/JS_File/JS_File_4.1-Query_Features.js +414 -414
  198. package/resources/jsbuilder/JS_File/JS_File_5-Planning.js +59 -59
  199. package/resources/jsbuilder/JS_File/JS_File_6-Changing.js +24 -24
  200. package/resources/jsbuilder/JS_File/JS_File_Export_Reference.js +12 -12
  201. package/resources/jsbuilder/JS_File/JS_File_Import_Reference.js +23 -23
  202. package/resources/jsbuilder/JS_File/JS_File_Import_References.js +31 -31
  203. package/resources/jsbuilder/JS_File/JS_File_Processor.js +16 -16
  204. package/resources/jsbuilder/JS_File/JS_Files.js +15 -15
  205. package/resources/jsbuilder/Module.js +14 -14
  206. package/resources/jsbuilder/Platform.js +13 -13
  207. package/resources/jsbuilder/Platforms.js +69 -69
  208. package/resources/jsbuilder/Project.js +109 -109
  209. package/resources/jsbuilder/Reference.js +1 -1
  210. package/resources/jsbuilder/Reference_Sequence.js +16 -16
  211. package/resources/jsbuilder/Scope.js +29 -29
  212. package/resources/jsbuilder/Variable_Name_Provider.js +42 -42
  213. package/resources/jsbuilder/_JS_File.js +225 -225
  214. package/resources/jsbuilder/ast_query.js +20 -20
  215. package/resources/jsbuilder/babel/babel_consts.js +162 -162
  216. package/resources/jsbuilder/babel/babel_node_tools.js +541 -541
  217. package/resources/jsbuilder/babel/deep_iterate/deep_iterate_babel.js +923 -904
  218. package/resources/jsbuilder/build.js +16 -16
  219. package/resources/jsbuilder/platform_notes.md +66 -66
  220. package/resources/jsbuilder/test/test_ast_node.js +381 -381
  221. package/resources/jsbuilder/test/test_js_file.js +303 -303
  222. package/resources/jsbuilder/test/test_project.js +157 -157
  223. package/resources/local-server-info-resource.js +96 -96
  224. package/resources/notes.txt +10 -10
  225. package/resources/old/website-image-resource.js +1185 -1185
  226. package/resources/process-js.js +498 -498
  227. package/resources/processors/bundlers/bundle.js +29 -29
  228. package/resources/processors/bundlers/bundler.js +23 -23
  229. package/resources/processors/bundlers/css-bundler.js +234 -234
  230. package/resources/processors/bundlers/js/JS_Bundler.js +51 -51
  231. package/resources/processors/bundlers/js/esbuild/Advanced_JS_Bundler_Using_ESBuild.js +388 -391
  232. package/resources/processors/bundlers/js/esbuild/Bundler_Using_ESBuild.js +8 -8
  233. package/resources/processors/bundlers/js/esbuild/Core_JS_Non_Minifying_Bundler_Using_ESBuild.js +188 -188
  234. package/resources/processors/bundlers/js/esbuild/Core_JS_Single_File_Minifying_Bundler_Using_ESBuild.js +191 -192
  235. package/resources/processors/bundlers/js/esbuild/_Old_CSS_Extractor.js +239 -239
  236. package/resources/processors/bundlers/js-bundler.js +263 -263
  237. package/resources/processors/bundlers/test_ast.js +73 -73
  238. package/resources/processors/bundlers/webpage-bundler.js +404 -404
  239. package/resources/processors/bundlers/website-bundler.js +22 -22
  240. package/resources/processors/extractors/Extractor.js +9 -11
  241. package/resources/processors/extractors/js/css_and_js/AST_Node/CSS_And_JS_From_JS_String_Using_AST_Node_Extractor.js +239 -254
  242. package/resources/processors/extractors/js/css_and_js/CSS_And_JS_From_JS_String_Extractor.js +3 -3
  243. package/resources/processors/extractors/string/Pos_Span_String_Extractor.js +93 -93
  244. package/resources/server-installed-tools.js +28 -28
  245. package/resources/server-resource-pool.js +41 -41
  246. package/resources/website-audio-resource.js +735 -735
  247. package/resources/website-css-resource.js +411 -411
  248. package/resources/website-image-resource.js +412 -412
  249. package/resources/website-javascript-resource-processor.js +908 -908
  250. package/resources/website-javascript-resource.js +874 -874
  251. package/resources/website-resource-processor.js +10 -10
  252. package/resources/website-resource.js +164 -164
  253. package/resources/website-static-html-resource.js +199 -199
  254. package/resources/website-template-html-resource.js +231 -231
  255. package/roadmap.md +75 -75
  256. package/server.js +609 -573
  257. package/static-page-context.js +13 -13
  258. package/website/webpage.js +81 -81
  259. package/website/website-group.js +15 -15
  260. package/website/website.js +260 -260
  261. package/examples/controls/11d) window, shared model mirrored integer text fields/both.js +0 -17
  262. package/examples/controls/13) window, shared model mirrored lat_long/client.js +0 -933
  263. package/examples/controls/13) window, shared model mirrored lat_long/server.js +0 -50
  264. package/examples/controls/14) window, control compositional model/client.js +0 -328
  265. package/examples/controls/14) window, control compositional model/server.js +0 -118
  266. package/examples/controls/14a) window, control spec has compositional model/client.js +0 -440
  267. package/examples/controls/14a) window, control spec has compositional model/server.js +0 -118
  268. package/examples/controls/15) window, text field/client.js +0 -256
  269. package/examples/controls/15) window, text field/server.js +0 -39
  270. package/examples/controls/16) Window([Text_Input])/client.js +0 -266
  271. package/examples/controls/16) Window([Text_Input])/server.js +0 -109
  272. package/examples/controls/16a) Window([Text_Input]) Integer data.model.data_type/client.js +0 -494
  273. package/examples/controls/16a) Window([Text_Input]) Integer data.model.data_type/isomorphic.js +0 -24
  274. package/examples/controls/16a) Window([Text_Input]) Integer data.model.data_type/server.js +0 -73
  275. package/examples/controls/2b) two window, context menus/client.js +0 -193
  276. package/examples/controls/2b) two window, context menus/server.js +0 -114
  277. package/examples/controls/4a) window, tabbed panel with various controls inside/client.js +0 -233
  278. package/examples/controls/4a) window, tabbed panel with various controls inside/server.js +0 -118
@@ -1,875 +1,875 @@
1
- // Sep 2023:
2
- // This Resource itself is huge in scope, but maybe would be better to make the Resource more in terms of representing the Resource itself
3
- // and having things like Resource_Processor? Resource_Analyser? Resource_Miner? Resource_Extracter? Resource_Transformer?
4
- // Resource_Bundler? Resource_Builder?
5
-
6
- // Resource_Verb_Carryouter Resource_Processor seems like the general name. Could do analysis, building, extraction etc.
7
- // Raising events / announcements when it finds things.
8
-
9
- // Does seem like refactoring the Resource so it is much simpler will be worth it, but also going into detail on the
10
- // different ways the resources can be processed, doing it in a polymorphic way, observables, promises, making more classes for it if needed.
11
-
12
- // Maybe do want the classes with processing functions built-in?
13
- // Changing the syntax to more explictly use various files and classes which will be interchangable and separately upgradable
14
- // and testable will help.
15
-
16
- // Need to refactor, this code no longer works as first intended, and was slow when it did its full thing.
17
- // Can do things much more optimially, maybe with esbuild and hashing and caching.
18
-
19
- // List of processes that get done on JS resources:
20
- // Parsing
21
- // Extracting CSS
22
- // Building
23
- // Compressing
24
- // (Serving) - probably not a 'process' like the others. But maybe could be.
25
- // Though 'serve' is indeed one of the things the functions currently here perportedly do.
26
- // Many are for some more specific needs / APIs, want to keep the functionalty available but provide and require a few more options.
27
- // Using esbuild or even something else for various parts of it. Encapsulating esbuild or babel within an API so they are swappable easily?
28
-
29
- // Defaulting to esbuild for some things will help.
30
- // Breaking the longer pieces of code up into different files and classes and functions, with more flexibility.
31
- // Do this so that it is very easy to run the server, and also will be able to view the progress of what it does to build,
32
- // and hopefully see it all go very quickly. Maybe % complete estimates.
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
- // Nov 2020:
49
- // Need to overhaul this, bugs are on the client, need to be careful and clear about what will be sent to the client.
50
- // Need to get more into the tools for building JS for the client. Can I do the outline / much of the outline of it myself?
51
- // Build up a huge JS AST of the whole thing.
52
- // Build up a system that understands what code does (to an extent) and how it fits together.
53
-
54
- // Could do my own application-level compression.
55
-
56
- // JS-Build.
57
- // Could identify the resources / files used in the site?
58
-
59
- // Load all the files in, made into a function that will return what the module exports.
60
- // Or not...
61
- // Make the module into just the code, store it as a variable, then be able to build
62
-
63
- // Would make quite a difference - with a lot of localised references made possible.
64
- //
65
-
66
-
67
- // JS_File
68
- // Be able to get transformed versions of it
69
- // JS_File_
70
-
71
-
72
- // Much of this could be better expressed as a Compiler_Resource.
73
-
74
-
75
- // Plan: Do more of this through lower level compilation features.
76
- // Accessing a compilation resource makes sense structurally.
77
-
78
- // May want a server to create and test compilation resources / compilers.
79
-
80
- // Compilers, Bundlers, HTTP Request Handlers - Somewhat lower level, ie tools to get things done.
81
- // Then also: resources which make use of upgraded and new lower level components.
82
-
83
- // Server_Resource could help?
84
-
85
- // Late 2023 - Should keep most of this for the moment, see about using parts when / where needed, also add in other (maybe simpler)
86
- // ways to do things that are needed to publish JS.
87
-
88
- // This resource seems like it's responsible for building JS.
89
- // Seems like a piece of 'server' functionality that will be kind of hidden, need to make sure it's not a leaky abstraction.
90
- // Also worth considering 'shorthands' where specific pieces of functionality are not needed to be specified, but usually we
91
- // need to tell it that it needs to compile the JS (and other things).
92
-
93
- // Maybe this JS resource would be responsible for extracting the CSS from JS and providing it to the CSS resource.
94
- // Would be best to work through getting a few examples, and implementations of simple apps with nice (maybe new) APIs that need
95
- // to be supported by jsgui3.
96
-
97
- // For the moment, don't make anything really complex when it's not needed, but make it so on the lower levels (incl mid)
98
- // it accesses functionality that is structured in a somewhat complex way, but uses it to do things which by default make the whole
99
- // process simple.
100
-
101
- // This runs automatically I think.
102
- // Probably need to get it automatically building the client js on server start if needed.
103
- // Likely best to save it locally, as well as to make a hash of all the files that went into the build, save that, only
104
- // rebuild when it has changed.
105
-
106
- // Could even provide a list of the intial control jsgui IDs, some empty items in an array? or the index of the node in the doc
107
- // and then the control id that will be applied.
108
- // This could make cleaner HTML be served by default, with IDs added later on the client-side using possibly a small amount of
109
- // supplementary info.
110
- // Or the ids could be assigned using xpaths.
111
-
112
-
113
-
114
-
115
-
116
-
117
-
118
-
119
-
120
-
121
-
122
- const path = require('path'),
123
- fs = require('fs'),
124
- url = require('url'),
125
- jsgui = require('jsgui3-html'),
126
- os = require('os'),
127
- http = require('http'),
128
- libUrl = require('url'),
129
- Resource = jsgui.Resource,
130
- fs2 = require('../fs2'),
131
- //brotli = require('iltorb').compress,
132
- //UglifyJS = require('uglify-js'),
133
- zlib = require('zlib');
134
-
135
- //fs.createReadStream(filename).pipe(brotli()).pipe(res);
136
-
137
- const fnl = require('fnl');
138
- const prom_or_cb = fnl.prom_or_cb;
139
- const fnlfs = require('fnlfs');
140
-
141
- const each = jsgui.each,
142
- arrayify = jsgui.arrayify,
143
- tof = jsgui.tof;
144
- const filter_map_by_regex = jsgui.filter_map_by_regex;
145
- const Class = jsgui.Class,
146
- Data_Object = jsgui.Data_Object,
147
- Enhanced_Data_Object = jsgui.Enhanced_Data_Object;
148
- const fp = jsgui.fp,
149
- is_defined = jsgui.is_defined;
150
- const Collection = jsgui.Collection;
151
- const call_multi = jsgui.call_multi,
152
- get_truth_map_from_arr = jsgui.get_truth_map_from_arr;
153
-
154
-
155
- //var zlib = require('zlib');
156
- const util = require('util');
157
-
158
- //const browserify = require('browserify');
159
- const babel = require('@babel/core');
160
-
161
- // Extends AutoStart_Resource?
162
- const stream_to_array = require('stream-to-array');
163
-
164
-
165
- const process_js = require('./process-js');
166
- const {analyse_js_doc_formatting, extract_client_js} = process_js;
167
-
168
-
169
- // A way of serving a file so that it includes custom code.
170
- // Or have a standard client template that is easy to serve.
171
-
172
- // Maybe do more with custom controls, such as custom page controls.
173
- // Those page controls would know which control types are within them.
174
- // That info could then be used to write JS code that sets up the references on the client.
175
-
176
- // Possibly this should have its own routing tree to connect paths with js files?
177
- // Need to set up custom paths.
178
-
179
- class Site_JavaScript extends Resource {
180
- //'fields': {
181
- // 'custom_paths': 'data_object'
182
- //},
183
- constructor(spec) {
184
- super(spec);
185
- //this.meta.set('custom_paths', new Data_Object({}));
186
- //this.custom_paths = new Data_Object({});
187
- // Those are custom file paths.
188
- // could have a collection of directories, indexed by name, that get served.
189
- // Index the collection by string value?
190
- //this.meta.set('served_directories', new Collection({'index_by': 'name'}));
191
-
192
- // But this could be held (only) in the router.
193
- this.served_directories = new Collection({
194
- 'index_by': 'name'
195
- });
196
- }
197
- 'start'(callback) {
198
- //console.log('Site_JavaScript start');
199
- const build_on_start = this.build_on_start;
200
- if (build_on_start) {
201
- this.build_client(function (err, res_build) {
202
- if (err) {
203
- callback(err)
204
- } else {
205
- callback(null, true);
206
- }
207
- })
208
- } else {
209
- callback(null, true);
210
- }
211
- // Let's have it build the client-side code.
212
- // Need the options to ignore various files, as well as to include the source maps in the output.
213
- }
214
- // build client, and serve it from one particular place
215
- // do so with a promise.
216
- // serve_package
217
- // Need to bundle / build together a package from the disk path, then serve it under a URL route.
218
-
219
- // want to give it the file to build.
220
- // There will be a variety of jsgui packages.
221
-
222
-
223
- // Will be better as a promise.
224
-
225
- // client_builder processor?
226
-
227
- // Should use / allow for this functionality, but not default to writing it to disk in a set place,
228
- // have that clearer when it's fully set up, then specify whatever shorthands.
229
-
230
-
231
- // And make this async / promise / observable instead.
232
-
233
-
234
- 'build_client'(callback) {
235
-
236
- console.trace();
237
- throw 'Deprecated';
238
-
239
- // Configurable building mechanisms....
240
- // Want to provide jsgui events / logs on the build process.
241
-
242
- // jsgui.notify could be used for some kinds of internal event logging.
243
- // a specific type of event system.
244
-
245
- // jsgui.raise('notification', )
246
-
247
- // .note may be faster.
248
-
249
-
250
-
251
-
252
- // jsgui.notify('start', 'build_client');
253
-
254
-
255
- // Need the reference relative to the application directory.
256
- //var path = __dirname + '/js/app.js';
257
-
258
- // Can we stream it to a buffer in memory instead?
259
-
260
- // Using a compilation resource may be better long-term.
261
- // Creating and using a relevant abstraction.
262
-
263
- // The server should have already loaded (a few) compilers.
264
-
265
-
266
- var appDir = path.dirname(require.main.filename);
267
-
268
-
269
-
270
-
271
- //console.log('appDir', appDir);
272
- var app_path = appDir + '/js/app.js';
273
- var app_bundle_path = appDir + '/js/app-bundle.js';
274
- var wstream = fs.createWriteStream(app_bundle_path);
275
-
276
-
277
-
278
- var b = browserify();
279
- //b.require(app_path, {
280
- // entry: true,
281
- // debug: true
282
- //});
283
- b.add(app_path);
284
- //console.log('app_path', app_path);
285
- //console.log('pre browserify bundle');
286
- //b.bundle().pipe(process.stdout);
287
-
288
- b.bundle().pipe(wstream);
289
-
290
- wstream.end = function (data) {
291
- //console.log('file bundle write complete');
292
- callback(null, app_bundle_path);
293
- // no more writes after end
294
- // emit "close" (optional)
295
- }
296
-
297
-
298
- }
299
- // Will could serve all jsgui code?
300
- // May be better not to allow server-side code to be read on the client.
301
- // Could have specific directories within jsgui that get served to the client.
302
-
303
-
304
- // May be best thinking of bundling up one or more objects / files ready for the server to serve.
305
-
306
-
307
- 'serve_directory'(path) {
308
- // Serves that directory, as any files given in that directory can be served from /js
309
-
310
- // Perhaps just using the router would be better.
311
-
312
- var served_directories = this.served_directories;
313
- //console.log('served_directories ' + stringify(served_directories));
314
- //served_directories.push(path);
315
- served_directories.push({
316
- 'name': path
317
- });
318
- //console.log('served_directories ' + stringify(served_directories));
319
- //console.log('path ' + path);
320
- //throw 'stop';
321
- }
322
- 'serve_package'(url, js_package, options = {}, callback) {
323
- //console.log('serve_package', url, js_package);
324
- //console.log('js_package', js_package);
325
- //console.log('typeof js_package', typeof js_package);
326
- //let tjp = typeof js_package;
327
- return this.serve_package_from_path(url, require.resolve(js_package), options, callback);
328
- }
329
-
330
- // Possibly some functionality would be better within the js bundler.
331
-
332
-
333
-
334
- 'package'(js_file_path, options = {}, callback) {
335
-
336
- let a = arguments;
337
- if (typeof a[2] === 'function') {
338
- callback = a[2];
339
- options = {
340
- //'babel': 'mini',
341
- 'include_sourcemaps': true
342
- };
343
- }
344
-
345
- return prom_or_cb((resolve, reject) => {
346
- (async () => {
347
- // options
348
- // may want a replacement within the client-side code.
349
- // Can we call browserify on the code string?
350
- // Creating a modified copy of the file would do.
351
- // Load the file, modify it, save it under a different name
352
-
353
- let s = new require('stream').Readable(),
354
- path = require('path').parse(js_file_path);
355
-
356
- let fileContents = await fnlfs.load(js_file_path);
357
- //console.log('1) fileContents.length', fileContents.length);
358
- // are there any replacements to do?
359
- // options.replacements
360
-
361
- if (options.js_mode === 'debug') {
362
- options.include_sourcemaps = true;
363
- }
364
- if (options.js_mode === 'compress' || options.js_mode === 'mini') {
365
- options.include_sourcemaps = false;
366
- options.babel = 'mini';
367
- }
368
-
369
- //console.log('options.babel', options.babel);
370
-
371
- if (options.replace) {
372
- let s_file_contents = fileContents.toString();
373
- //console.log('s_file_contents', s_file_contents);
374
- each(options.replace, (text, key) => {
375
- //console.log('key', key);
376
- //console.log('text', text);
377
- let running_fn = '(' + text + ')();'
378
- //console.log('running_fn', running_fn);
379
- s_file_contents = s_file_contents.split(key).join(running_fn);
380
- })
381
- fileContents = Buffer.from(s_file_contents);
382
- //console.log('2) fileContents.length', fileContents.length);
383
- }
384
- // Then we can replace some of the file contents with specific content given when we tall it to serve that file.
385
- // We have a space for client-side activation.
386
- s.push(fileContents);
387
- s.push(null);
388
-
389
- //let include_sourcemaps = true;
390
-
391
- let b = browserify(s, {
392
- basedir: path.dir,
393
- //builtins: false,
394
- builtins: ['buffer', 'process'],
395
- 'debug': options.include_sourcemaps
396
- });
397
-
398
- let parts = await stream_to_array(b.bundle());
399
-
400
- const buffers = parts
401
- .map(part => util.isBuffer(part) ? part : Buffer.from(part));
402
- let buf_js = Buffer.concat(buffers);
403
- let str_js = buf_js.toString();
404
-
405
- let babel_option = options.babel
406
- //console.log('babel_option', babel_option);
407
- if (babel_option === 'es5') {
408
-
409
- let o_transform = {
410
- "presets": [
411
- "es2015",
412
- "es2017"
413
- ],
414
- "plugins": [
415
- "transform-runtime"
416
- ] //,
417
- //'sourceMaps': 'inline'
418
- };
419
-
420
- if (options.include_sourcemaps) o_transform.sourceMaps = 'inline';
421
- let res_transform = babel.transform(str_js, o_transform);
422
- //console.log('res_transform', res_transform);
423
- //console.log('Object.keys(res_transform)', Object.keys(res_transform));
424
- let jst_es5 = res_transform.code;
425
- //let {jst_es5, map, ast} = babel.transform(str_js);
426
- //console.log('jst_es5.length', jst_es5.length);
427
- buf_js = Buffer.from(jst_es5);
428
- } else if (babel_option === 'mini') {
429
- /*
430
- let o_transform = {
431
- presets: ["minify"]//,
432
- //'sourceMaps': 'inline'
433
- };
434
- */
435
- let o_transform = {
436
- "presets": [
437
- ["minify", {
438
- //"mangle": {
439
- //"exclude": ["MyCustomError"]
440
- //},
441
- //"unsafe": {
442
- // "typeConstructors": false
443
- //},
444
- //"keepFnName": true
445
- }]
446
- ],
447
- //plugins: ["minify-dead-code-elimination"]
448
- };
449
- if (options.include_sourcemaps) o_transform.sourceMaps = 'inline';
450
-
451
- let res_transform = babel.transform(str_js, o_transform);
452
- buf_js = Buffer.from(res_transform.code);
453
- } else {
454
- buf_js = Buffer.from(str_js);
455
- }
456
- resolve(buf_js);
457
- })();
458
- }, callback);
459
- }
460
-
461
- // This is a lot about creating some 'package' that includes built JS and CSS
462
-
463
- // It is not so clear what 'serve' means here though.
464
- // Perhaps using this functionality could take a few more function calls that are more explicit,
465
- // but also be set up so that it happens by default when appropriate, or some other function
466
- // that uses some of the same newly refactored / referenced functions will do the job.
467
-
468
- // Being more explicit about making sure the server has access to:
469
- // 1) The client side JS
470
- // 2) The means to build the client side JS
471
- // 3) Analysis of the client-side JS source file / files
472
- // If they contain CSS, that extracted CSS, as a CSS file.
473
- // Probably best to make a callback saying that it's got it?
474
- // An 'announcement'? New 'announcement' mechanism, so that when the CSS has been found the CSS publisher hears the announcement.
475
- // Means the JS resource or publisher does not need a direct reference to the CSS resource or publisher.
476
-
477
- // Also, make use of the distinction between a Resource and a Publisher.
478
- // A Resource is something like a file on the disk.
479
- // The Resources get provided to the Publishers.
480
- // Then do the Publishers create Resources? Publications? Published_Resources?
481
-
482
-
483
-
484
-
485
-
486
-
487
-
488
-
489
-
490
- // 3) The built client-side JS (with or without sourcemaps)
491
- // 4) The compression setting (brotli/gzip) to compress that client-side JS
492
-
493
-
494
-
495
-
496
- 'serve_package_from_path'(url, js_file_path, options = {}, callback) {
497
- //console.log('serve_package_from_path', url, js_file_path);
498
- // js_mode option may need to be used.
499
-
500
-
501
- // Make it an observable?
502
- // Raise an event when we have the browserified fill js file (uncompressed?).
503
-
504
-
505
- let a = arguments;
506
- if (typeof a[2] === 'function') {
507
- callback = a[2];
508
- options = {
509
- //'babel': 'mini',
510
- 'include_sourcemaps': false
511
- };
512
- }
513
- let serve_raw = options.serve_raw || options.raw;
514
- let accepts_brotli = false;
515
-
516
- // Need to come up with compressed versions.
517
- // An object that provides different versions.
518
-
519
-
520
- return prom_or_cb((resolve, reject) => {
521
- (async () => {
522
- // options
523
- // may want a replacement within the client-side code.
524
- // Can we call browserify on the code string?
525
- // Creating a modified copy of the file would do.
526
- // Load the file, modify it, save it under a different name
527
- const Stream = require('stream');
528
-
529
- let s = new Stream.Readable(),
530
- path = require('path').parse(js_file_path);
531
-
532
- let fileContents = await fnlfs.load(js_file_path);
533
- //console.log('1) fileContents.length', fileContents.length);
534
- // are there any replacements to do?
535
- // options.replacements
536
- if (options.js_mode === 'debug') {
537
- options.include_sourcemaps = true;
538
- }
539
- if (options.js_mode === 'compress' || options.js_mode === 'mini') {
540
- options.include_sourcemaps = false;
541
- options.babel = 'mini';
542
- }
543
- //console.log('options.babel', options.babel);
544
-
545
- // Likely to remove this....
546
- if (options.replace) {
547
- let s_file_contents = fileContents.toString();
548
- //console.log('s_file_contents', s_file_contents);
549
- each(options.replace, (text, key) => {
550
- //console.log('key', key);
551
- //console.log('text', text);
552
- const running_fn = '(' + text + ')();'
553
- //console.log('running_fn', running_fn);
554
- s_file_contents = s_file_contents.split(key).join(running_fn);
555
- })
556
- fileContents = Buffer.from(s_file_contents);
557
- //console.log('2) fileContents.length', fileContents.length);
558
- }
559
-
560
- // Then we can replace some of the file contents with specific content given when we tall it to serve that file.
561
- // We have a space for client-side activation.
562
- // want a raw option with no browserify.
563
- //console.log('serve_raw', serve_raw);
564
- if (serve_raw) {
565
- const escaped_url = url.replace(/\./g, '☺');
566
- //this.custom_paths.set(escaped_url, fileContents);
567
-
568
- throw 'NYI';
569
- } else {
570
- const formatting_info = analyse_js_doc_formatting(fileContents.toString());
571
- //console.log('formatting_info', formatting_info);
572
-
573
- const {arr_lines, line_break, indentation_analysis} = formatting_info;
574
- const {parsed_lines, str_indentation} = indentation_analysis;
575
- const client_root_js = extract_client_js(formatting_info);
576
-
577
- //fnlfs.save('d:\\saved.js', client_root_js);
578
-
579
-
580
- s.push(client_root_js);
581
- s.push(null);
582
- const lines_file_content = [];
583
-
584
- // Don't always include sourcemap?
585
- // Separate out the sourcemap?
586
-
587
- const b = browserify(s, {
588
- basedir: path.dir,
589
- //builtins: false,
590
- builtins: ['buffer'],
591
- 'debug': options.include_sourcemaps
592
- });
593
- // Prefer the idea of sending a stream to browserify.
594
- const parts = await stream_to_array(b.bundle());
595
- /*
596
- var b = browserify([js_file_path], {
597
- 'debug': true
598
- });
599
- */
600
- //let parts = await stream_to_array(b.bundle());
601
- const buffers = parts
602
- .map(part => util.isBuffer(part) ? part : Buffer.from(part));
603
- let buf_js = Buffer.concat(buffers);
604
- const str_js = buf_js.toString();
605
- const str_js_code = str_js;
606
- let str_sourcemap;
607
-
608
- let pos_prior_sourcemap = str_js.indexOf('//# sourceMappingURL');
609
- if (pos_prior_sourcemap > -1) {
610
- str_js_code = str_js.substr(0, pos_prior_sourcemap);
611
- str_sourcemap = str_js.substr(pos_prior_sourcemap);
612
- }
613
- // filter_extract_css
614
-
615
-
616
- /*
617
- const js_remove_comments = (str_js_code) => {
618
- // comments will be OK within a string.
619
-
620
- // Be able to work out what type of code we are in at all points...?
621
- // Non-tokenising scanner...?
622
-
623
- // Knowing whether or not * / // / * is within a string is important - because if it's in a string its not a comment.
624
- // seems like making the scanning parser is a bit of a large task. It would constantly need to know what symbol type / string encapsulator to use.
625
-
626
- // Could split it into lines, spot whenever a line starts a comment...?
627
- }
628
- */
629
-
630
- const filter_js_extract_control_css = (str_js_code) => {
631
- // res = [css, js_no_css]
632
- // Split the js lines.
633
-
634
- const s_js = str_js_code.split('\n');
635
- let within_class_css = false;
636
- const control_css_lines = [];
637
- const js_non_css_lines = [];
638
- // and the non-css lines.
639
- // And need to look for its stop.
640
- // And leave the first and last line out of the css.
641
- each(s_js, js_line => {
642
- let placed_js_line = false;
643
- const pos_class_css_begin = js_line.indexOf('.css = `');
644
- // if its 0
645
-
646
- if (pos_class_css_begin > -1) {
647
- //console.log('js_line', js_line);
648
- within_class_css = true;
649
- }
650
- // Put empty lines (back) into the js array?
651
-
652
- if (within_class_css) {
653
- //console.log('js_line', js_line);
654
-
655
- const pos_control_css_end = js_line.indexOf('`;');
656
- //console.log('pos_control_css_end', pos_control_css_end);
657
- if (pos_control_css_end > -1) {
658
- within_class_css = false;
659
- } else {
660
- if (pos_class_css_begin > -1) {
661
-
662
- } else {
663
- control_css_lines.push(js_line);
664
- }
665
-
666
- }
667
- } else {
668
- js_non_css_lines.push(js_line);
669
- placed_js_line = true;
670
- }
671
-
672
- if (!placed_js_line) {
673
- js_non_css_lines.push('');
674
- }
675
- //let is_control_css_start = js_line.indexOf()
676
-
677
- if (control_css_lines.length > 200) throw 'stop';
678
-
679
- })
680
- return [control_css_lines.join('\n'), js_non_css_lines.join('\n')];
681
- }
682
-
683
- let [str_css, str_js_no_css] = filter_js_extract_control_css(str_js_code);
684
-
685
- // Add the sourcemaps back? Its working.
686
-
687
- if (str_sourcemap) {
688
- str_js_no_css = str_js_no_css + str_sourcemap;
689
- }
690
- this.raise('extracted-controls-css', str_css);
691
- let babel_option = options.babel;
692
-
693
- //console.log('babel_option', babel_option);
694
- //throw 'stop';
695
- //babel_option = 'es5';
696
- //console.log('babel_option', babel_option);
697
- if (babel_option === 'es5') {
698
- // es5 option
699
- // not sure if it babels async await though.
700
- /*
701
- {
702
- "presets": [
703
- "es2015",
704
- "es2017"
705
- ],
706
- "plugins": [
707
- "transform-runtime"
708
- ]
709
- }
710
- */
711
- /*
712
- let res_transform = babel.transform(str_js, {
713
- //'plugins': ['transform-class']
714
- 'plugins': ['transform-es2015-object-super', 'transform-es2015-classes', 'remove-comments'],
715
- 'sourceMaps': 'inline'
716
- //'plugins': ['transform-es2015-classes']
717
- // transform-es2015-object-super
718
- });
719
- */
720
- let o_tranform = {
721
- "presets": [
722
- "es2015",
723
- "es2017"
724
- ],
725
- "plugins": [
726
- "transform-runtime"
727
- ] //,
728
- //'sourceMaps': 'inline'
729
- };
730
- if (options.include_sourcemaps) o_tranform.sourceMaps = 'inline';
731
-
732
- let res_transform = babel.transform(str_js_no_css, o_tranform);
733
- let jst_es5 = res_transform.code;
734
- //let {jst_es5, map, ast} = babel.transform(str_js);
735
- //console.log('jst_es5.length', jst_es5.length);
736
- buf_js = Buffer.from(jst_es5);
737
- } else if (babel_option === 'mini') {
738
- /*
739
- let o_transform = {
740
- presets: ["minify"]//,
741
- //'sourceMaps': 'inline'
742
- };
743
- */
744
- let o_transform = {
745
- "presets": [
746
- ["minify", {
747
- //"mangle": {
748
- //"exclude": ["MyCustomError"]
749
- //},
750
- //"unsafe": {
751
- // "typeConstructors": false
752
- //},
753
- //"keepFnName": true
754
- }]
755
- ],
756
- "comments": false
757
- //plugins: ["minify-dead-code-elimination"]
758
- };
759
-
760
- if (options.include_sourcemaps) o_transform.sourceMaps = 'inline';
761
- let res_transform = babel.transform(str_js_no_css, o_transform);
762
- //let jst_es5 = res_transform.code;
763
- //let {jst_es5, map, ast} = babel.transform(str_js);
764
- //console.log('jst_es5.length', jst_es5.length);
765
- buf_js = Buffer.from(res_transform.code);
766
- } else {
767
- buf_js = Buffer.from(str_js_no_css);
768
- console.log('no babel use');
769
- }
770
- var escaped_url = url.replace(/\./g, '☺');
771
-
772
- //console.log('pre compress buf_js.length', buf_js.length);
773
- zlib.gzip(buf_js, {level: 9}, (err, buffer) => {
774
- console.log('deflated buf_js buffer.length', buffer.length);
775
-
776
- if (err) {
777
- reject(err);
778
- } else {
779
- //
780
- //buffer.encoding = 'deflate';
781
- console.log('');
782
- console.log('escaped_url', escaped_url);
783
- console.log('url', url);
784
- console.log('');
785
-
786
- const rp = this.pool;
787
- console.log('rp', rp);
788
- console.log('rp.resource_names', rp.resource_names);
789
-
790
- const router = rp.get_resource('Site Router');
791
- console.log('router', router);
792
-
793
- router.set_route(url, this, (req, res) => {
794
- console.log('router', [!!req, !!res]);
795
- });
796
-
797
- /*
798
- 'set_route'(str_route, context, fn_handler) {
799
- */
800
-
801
- // Setting up routing here?
802
- // Or returning it to the server?
803
-
804
- // hack_setup_routing - as in it hacks into another part of the system (which is available)
805
- // to set up the routing. A more top-down approach would be for the Server module to set the
806
- // routing up itself.
807
- // May be nice if components / resources could set up their own routing, with access to the
808
- // Resource_Pool.
809
-
810
-
811
-
812
- /*
813
-
814
- // Would need to check operation of custom paths.
815
- // Maybe its use was removed...?
816
- this.custom_paths.set(escaped_url, {
817
- raw: buf_js,
818
- gzip: buffer
819
- });
820
-
821
- */
822
-
823
-
824
-
825
- resolve(true);
826
- }
827
- });
828
- }
829
- })();
830
- }, callback);
831
- }
832
-
833
- /*
834
- 'set_custom_path'(url, file_path) {
835
- var escaped_url = url.replace(/\./g, '☺');
836
- this.custom_paths.set(escaped_url, file_path);
837
- }
838
- */
839
- //
840
-
841
-
842
- // Not so sure that it should process the request.
843
- // A more general purpose request handler...?
844
- // Have more request handling code within one js file, a cenralised portion of the app.
845
- // And then within those request handlers call on useful abstractions.
846
-
847
- // Setting up one or more Compilers seems like it would solve some of what this is doing.
848
- // Even a Compilation_Process object that provides data for monitoring.
849
- // Published with a Resource_Publisher possibly.
850
-
851
- // Website_HTTP_Publisher maybe
852
-
853
- // or just HTTP_Publisher, a Publisher rather than a Resource.
854
- // HTTP_Publisher, which is focused on publishing HTTP, may be the best option here.
855
- // Seems best to fix what we have already first though. Could then work on HTTP_Publisher.
856
-
857
-
858
-
859
- // Website_HTTP_Publisher_Resource possibly?
860
-
861
- //
862
-
863
-
864
-
865
- // Site_JavaScript seems more about bundling / compiling rather than serving.
866
- // Resources could present their data ahead of time / be asked for them and provide it, and the server
867
- // keeps track of info more centrally.
868
- //
869
-
870
-
871
-
872
-
873
- }
874
-
1
+ // Sep 2023:
2
+ // This Resource itself is huge in scope, but maybe would be better to make the Resource more in terms of representing the Resource itself
3
+ // and having things like Resource_Processor? Resource_Analyser? Resource_Miner? Resource_Extracter? Resource_Transformer?
4
+ // Resource_Bundler? Resource_Builder?
5
+
6
+ // Resource_Verb_Carryouter Resource_Processor seems like the general name. Could do analysis, building, extraction etc.
7
+ // Raising events / announcements when it finds things.
8
+
9
+ // Does seem like refactoring the Resource so it is much simpler will be worth it, but also going into detail on the
10
+ // different ways the resources can be processed, doing it in a polymorphic way, observables, promises, making more classes for it if needed.
11
+
12
+ // Maybe do want the classes with processing functions built-in?
13
+ // Changing the syntax to more explictly use various files and classes which will be interchangable and separately upgradable
14
+ // and testable will help.
15
+
16
+ // Need to refactor, this code no longer works as first intended, and was slow when it did its full thing.
17
+ // Can do things much more optimially, maybe with esbuild and hashing and caching.
18
+
19
+ // List of processes that get done on JS resources:
20
+ // Parsing
21
+ // Extracting CSS
22
+ // Building
23
+ // Compressing
24
+ // (Serving) - probably not a 'process' like the others. But maybe could be.
25
+ // Though 'serve' is indeed one of the things the functions currently here perportedly do.
26
+ // Many are for some more specific needs / APIs, want to keep the functionalty available but provide and require a few more options.
27
+ // Using esbuild or even something else for various parts of it. Encapsulating esbuild or babel within an API so they are swappable easily?
28
+
29
+ // Defaulting to esbuild for some things will help.
30
+ // Breaking the longer pieces of code up into different files and classes and functions, with more flexibility.
31
+ // Do this so that it is very easy to run the server, and also will be able to view the progress of what it does to build,
32
+ // and hopefully see it all go very quickly. Maybe % complete estimates.
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+
42
+
43
+
44
+
45
+
46
+
47
+
48
+ // Nov 2020:
49
+ // Need to overhaul this, bugs are on the client, need to be careful and clear about what will be sent to the client.
50
+ // Need to get more into the tools for building JS for the client. Can I do the outline / much of the outline of it myself?
51
+ // Build up a huge JS AST of the whole thing.
52
+ // Build up a system that understands what code does (to an extent) and how it fits together.
53
+
54
+ // Could do my own application-level compression.
55
+
56
+ // JS-Build.
57
+ // Could identify the resources / files used in the site?
58
+
59
+ // Load all the files in, made into a function that will return what the module exports.
60
+ // Or not...
61
+ // Make the module into just the code, store it as a variable, then be able to build
62
+
63
+ // Would make quite a difference - with a lot of localised references made possible.
64
+ //
65
+
66
+
67
+ // JS_File
68
+ // Be able to get transformed versions of it
69
+ // JS_File_
70
+
71
+
72
+ // Much of this could be better expressed as a Compiler_Resource.
73
+
74
+
75
+ // Plan: Do more of this through lower level compilation features.
76
+ // Accessing a compilation resource makes sense structurally.
77
+
78
+ // May want a server to create and test compilation resources / compilers.
79
+
80
+ // Compilers, Bundlers, HTTP Request Handlers - Somewhat lower level, ie tools to get things done.
81
+ // Then also: resources which make use of upgraded and new lower level components.
82
+
83
+ // Server_Resource could help?
84
+
85
+ // Late 2023 - Should keep most of this for the moment, see about using parts when / where needed, also add in other (maybe simpler)
86
+ // ways to do things that are needed to publish JS.
87
+
88
+ // This resource seems like it's responsible for building JS.
89
+ // Seems like a piece of 'server' functionality that will be kind of hidden, need to make sure it's not a leaky abstraction.
90
+ // Also worth considering 'shorthands' where specific pieces of functionality are not needed to be specified, but usually we
91
+ // need to tell it that it needs to compile the JS (and other things).
92
+
93
+ // Maybe this JS resource would be responsible for extracting the CSS from JS and providing it to the CSS resource.
94
+ // Would be best to work through getting a few examples, and implementations of simple apps with nice (maybe new) APIs that need
95
+ // to be supported by jsgui3.
96
+
97
+ // For the moment, don't make anything really complex when it's not needed, but make it so on the lower levels (incl mid)
98
+ // it accesses functionality that is structured in a somewhat complex way, but uses it to do things which by default make the whole
99
+ // process simple.
100
+
101
+ // This runs automatically I think.
102
+ // Probably need to get it automatically building the client js on server start if needed.
103
+ // Likely best to save it locally, as well as to make a hash of all the files that went into the build, save that, only
104
+ // rebuild when it has changed.
105
+
106
+ // Could even provide a list of the intial control jsgui IDs, some empty items in an array? or the index of the node in the doc
107
+ // and then the control id that will be applied.
108
+ // This could make cleaner HTML be served by default, with IDs added later on the client-side using possibly a small amount of
109
+ // supplementary info.
110
+ // Or the ids could be assigned using xpaths.
111
+
112
+
113
+
114
+
115
+
116
+
117
+
118
+
119
+
120
+
121
+
122
+ const path = require('path'),
123
+ fs = require('fs'),
124
+ url = require('url'),
125
+ jsgui = require('jsgui3-html'),
126
+ os = require('os'),
127
+ http = require('http'),
128
+ libUrl = require('url'),
129
+ Resource = jsgui.Resource,
130
+ fs2 = require('../fs2'),
131
+ //brotli = require('iltorb').compress,
132
+ //UglifyJS = require('uglify-js'),
133
+ zlib = require('zlib');
134
+
135
+ //fs.createReadStream(filename).pipe(brotli()).pipe(res);
136
+
137
+ const fnl = require('fnl');
138
+ const prom_or_cb = fnl.prom_or_cb;
139
+ const fnlfs = require('fnlfs');
140
+
141
+ const each = jsgui.each,
142
+ arrayify = jsgui.arrayify,
143
+ tof = jsgui.tof;
144
+ const filter_map_by_regex = jsgui.filter_map_by_regex;
145
+ const Class = jsgui.Class,
146
+ Data_Object = jsgui.Data_Object,
147
+ Enhanced_Data_Object = jsgui.Enhanced_Data_Object;
148
+ const fp = jsgui.fp,
149
+ is_defined = jsgui.is_defined;
150
+ const Collection = jsgui.Collection;
151
+ const call_multi = jsgui.call_multi,
152
+ get_truth_map_from_arr = jsgui.get_truth_map_from_arr;
153
+
154
+
155
+ //var zlib = require('zlib');
156
+ const util = require('util');
157
+
158
+ //const browserify = require('browserify');
159
+ const babel = require('@babel/core');
160
+
161
+ // Extends AutoStart_Resource?
162
+ const stream_to_array = require('stream-to-array');
163
+
164
+
165
+ const process_js = require('./process-js');
166
+ const {analyse_js_doc_formatting, extract_client_js} = process_js;
167
+
168
+
169
+ // A way of serving a file so that it includes custom code.
170
+ // Or have a standard client template that is easy to serve.
171
+
172
+ // Maybe do more with custom controls, such as custom page controls.
173
+ // Those page controls would know which control types are within them.
174
+ // That info could then be used to write JS code that sets up the references on the client.
175
+
176
+ // Possibly this should have its own routing tree to connect paths with js files?
177
+ // Need to set up custom paths.
178
+
179
+ class Site_JavaScript extends Resource {
180
+ //'fields': {
181
+ // 'custom_paths': 'data_object'
182
+ //},
183
+ constructor(spec) {
184
+ super(spec);
185
+ //this.meta.set('custom_paths', new Data_Object({}));
186
+ //this.custom_paths = new Data_Object({});
187
+ // Those are custom file paths.
188
+ // could have a collection of directories, indexed by name, that get served.
189
+ // Index the collection by string value?
190
+ //this.meta.set('served_directories', new Collection({'index_by': 'name'}));
191
+
192
+ // But this could be held (only) in the router.
193
+ this.served_directories = new Collection({
194
+ 'index_by': 'name'
195
+ });
196
+ }
197
+ 'start'(callback) {
198
+ //console.log('Site_JavaScript start');
199
+ const build_on_start = this.build_on_start;
200
+ if (build_on_start) {
201
+ this.build_client(function (err, res_build) {
202
+ if (err) {
203
+ callback(err)
204
+ } else {
205
+ callback(null, true);
206
+ }
207
+ })
208
+ } else {
209
+ callback(null, true);
210
+ }
211
+ // Let's have it build the client-side code.
212
+ // Need the options to ignore various files, as well as to include the source maps in the output.
213
+ }
214
+ // build client, and serve it from one particular place
215
+ // do so with a promise.
216
+ // serve_package
217
+ // Need to bundle / build together a package from the disk path, then serve it under a URL route.
218
+
219
+ // want to give it the file to build.
220
+ // There will be a variety of jsgui packages.
221
+
222
+
223
+ // Will be better as a promise.
224
+
225
+ // client_builder processor?
226
+
227
+ // Should use / allow for this functionality, but not default to writing it to disk in a set place,
228
+ // have that clearer when it's fully set up, then specify whatever shorthands.
229
+
230
+
231
+ // And make this async / promise / observable instead.
232
+
233
+
234
+ 'build_client'(callback) {
235
+
236
+ console.trace();
237
+ throw 'Deprecated';
238
+
239
+ // Configurable building mechanisms....
240
+ // Want to provide jsgui events / logs on the build process.
241
+
242
+ // jsgui.notify could be used for some kinds of internal event logging.
243
+ // a specific type of event system.
244
+
245
+ // jsgui.raise('notification', )
246
+
247
+ // .note may be faster.
248
+
249
+
250
+
251
+
252
+ // jsgui.notify('start', 'build_client');
253
+
254
+
255
+ // Need the reference relative to the application directory.
256
+ //var path = __dirname + '/js/app.js';
257
+
258
+ // Can we stream it to a buffer in memory instead?
259
+
260
+ // Using a compilation resource may be better long-term.
261
+ // Creating and using a relevant abstraction.
262
+
263
+ // The server should have already loaded (a few) compilers.
264
+
265
+
266
+ var appDir = path.dirname(require.main.filename);
267
+
268
+
269
+
270
+
271
+ //console.log('appDir', appDir);
272
+ var app_path = appDir + '/js/app.js';
273
+ var app_bundle_path = appDir + '/js/app-bundle.js';
274
+ var wstream = fs.createWriteStream(app_bundle_path);
275
+
276
+
277
+
278
+ var b = browserify();
279
+ //b.require(app_path, {
280
+ // entry: true,
281
+ // debug: true
282
+ //});
283
+ b.add(app_path);
284
+ //console.log('app_path', app_path);
285
+ //console.log('pre browserify bundle');
286
+ //b.bundle().pipe(process.stdout);
287
+
288
+ b.bundle().pipe(wstream);
289
+
290
+ wstream.end = function (data) {
291
+ //console.log('file bundle write complete');
292
+ callback(null, app_bundle_path);
293
+ // no more writes after end
294
+ // emit "close" (optional)
295
+ }
296
+
297
+
298
+ }
299
+ // Will could serve all jsgui code?
300
+ // May be better not to allow server-side code to be read on the client.
301
+ // Could have specific directories within jsgui that get served to the client.
302
+
303
+
304
+ // May be best thinking of bundling up one or more objects / files ready for the server to serve.
305
+
306
+
307
+ 'serve_directory'(path) {
308
+ // Serves that directory, as any files given in that directory can be served from /js
309
+
310
+ // Perhaps just using the router would be better.
311
+
312
+ var served_directories = this.served_directories;
313
+ //console.log('served_directories ' + stringify(served_directories));
314
+ //served_directories.push(path);
315
+ served_directories.push({
316
+ 'name': path
317
+ });
318
+ //console.log('served_directories ' + stringify(served_directories));
319
+ //console.log('path ' + path);
320
+ //throw 'stop';
321
+ }
322
+ 'serve_package'(url, js_package, options = {}, callback) {
323
+ //console.log('serve_package', url, js_package);
324
+ //console.log('js_package', js_package);
325
+ //console.log('typeof js_package', typeof js_package);
326
+ //let tjp = typeof js_package;
327
+ return this.serve_package_from_path(url, require.resolve(js_package), options, callback);
328
+ }
329
+
330
+ // Possibly some functionality would be better within the js bundler.
331
+
332
+
333
+
334
+ 'package'(js_file_path, options = {}, callback) {
335
+
336
+ let a = arguments;
337
+ if (typeof a[2] === 'function') {
338
+ callback = a[2];
339
+ options = {
340
+ //'babel': 'mini',
341
+ 'include_sourcemaps': true
342
+ };
343
+ }
344
+
345
+ return prom_or_cb((resolve, reject) => {
346
+ (async () => {
347
+ // options
348
+ // may want a replacement within the client-side code.
349
+ // Can we call browserify on the code string?
350
+ // Creating a modified copy of the file would do.
351
+ // Load the file, modify it, save it under a different name
352
+
353
+ let s = new require('stream').Readable(),
354
+ path = require('path').parse(js_file_path);
355
+
356
+ let fileContents = await fnlfs.load(js_file_path);
357
+ //console.log('1) fileContents.length', fileContents.length);
358
+ // are there any replacements to do?
359
+ // options.replacements
360
+
361
+ if (options.js_mode === 'debug') {
362
+ options.include_sourcemaps = true;
363
+ }
364
+ if (options.js_mode === 'compress' || options.js_mode === 'mini') {
365
+ options.include_sourcemaps = false;
366
+ options.babel = 'mini';
367
+ }
368
+
369
+ //console.log('options.babel', options.babel);
370
+
371
+ if (options.replace) {
372
+ let s_file_contents = fileContents.toString();
373
+ //console.log('s_file_contents', s_file_contents);
374
+ each(options.replace, (text, key) => {
375
+ //console.log('key', key);
376
+ //console.log('text', text);
377
+ let running_fn = '(' + text + ')();'
378
+ //console.log('running_fn', running_fn);
379
+ s_file_contents = s_file_contents.split(key).join(running_fn);
380
+ })
381
+ fileContents = Buffer.from(s_file_contents);
382
+ //console.log('2) fileContents.length', fileContents.length);
383
+ }
384
+ // Then we can replace some of the file contents with specific content given when we tall it to serve that file.
385
+ // We have a space for client-side activation.
386
+ s.push(fileContents);
387
+ s.push(null);
388
+
389
+ //let include_sourcemaps = true;
390
+
391
+ let b = browserify(s, {
392
+ basedir: path.dir,
393
+ //builtins: false,
394
+ builtins: ['buffer', 'process'],
395
+ 'debug': options.include_sourcemaps
396
+ });
397
+
398
+ let parts = await stream_to_array(b.bundle());
399
+
400
+ const buffers = parts
401
+ .map(part => util.isBuffer(part) ? part : Buffer.from(part));
402
+ let buf_js = Buffer.concat(buffers);
403
+ let str_js = buf_js.toString();
404
+
405
+ let babel_option = options.babel
406
+ //console.log('babel_option', babel_option);
407
+ if (babel_option === 'es5') {
408
+
409
+ let o_transform = {
410
+ "presets": [
411
+ "es2015",
412
+ "es2017"
413
+ ],
414
+ "plugins": [
415
+ "transform-runtime"
416
+ ] //,
417
+ //'sourceMaps': 'inline'
418
+ };
419
+
420
+ if (options.include_sourcemaps) o_transform.sourceMaps = 'inline';
421
+ let res_transform = babel.transform(str_js, o_transform);
422
+ //console.log('res_transform', res_transform);
423
+ //console.log('Object.keys(res_transform)', Object.keys(res_transform));
424
+ let jst_es5 = res_transform.code;
425
+ //let {jst_es5, map, ast} = babel.transform(str_js);
426
+ //console.log('jst_es5.length', jst_es5.length);
427
+ buf_js = Buffer.from(jst_es5);
428
+ } else if (babel_option === 'mini') {
429
+ /*
430
+ let o_transform = {
431
+ presets: ["minify"]//,
432
+ //'sourceMaps': 'inline'
433
+ };
434
+ */
435
+ let o_transform = {
436
+ "presets": [
437
+ ["minify", {
438
+ //"mangle": {
439
+ //"exclude": ["MyCustomError"]
440
+ //},
441
+ //"unsafe": {
442
+ // "typeConstructors": false
443
+ //},
444
+ //"keepFnName": true
445
+ }]
446
+ ],
447
+ //plugins: ["minify-dead-code-elimination"]
448
+ };
449
+ if (options.include_sourcemaps) o_transform.sourceMaps = 'inline';
450
+
451
+ let res_transform = babel.transform(str_js, o_transform);
452
+ buf_js = Buffer.from(res_transform.code);
453
+ } else {
454
+ buf_js = Buffer.from(str_js);
455
+ }
456
+ resolve(buf_js);
457
+ })();
458
+ }, callback);
459
+ }
460
+
461
+ // This is a lot about creating some 'package' that includes built JS and CSS
462
+
463
+ // It is not so clear what 'serve' means here though.
464
+ // Perhaps using this functionality could take a few more function calls that are more explicit,
465
+ // but also be set up so that it happens by default when appropriate, or some other function
466
+ // that uses some of the same newly refactored / referenced functions will do the job.
467
+
468
+ // Being more explicit about making sure the server has access to:
469
+ // 1) The client side JS
470
+ // 2) The means to build the client side JS
471
+ // 3) Analysis of the client-side JS source file / files
472
+ // If they contain CSS, that extracted CSS, as a CSS file.
473
+ // Probably best to make a callback saying that it's got it?
474
+ // An 'announcement'? New 'announcement' mechanism, so that when the CSS has been found the CSS publisher hears the announcement.
475
+ // Means the JS resource or publisher does not need a direct reference to the CSS resource or publisher.
476
+
477
+ // Also, make use of the distinction between a Resource and a Publisher.
478
+ // A Resource is something like a file on the disk.
479
+ // The Resources get provided to the Publishers.
480
+ // Then do the Publishers create Resources? Publications? Published_Resources?
481
+
482
+
483
+
484
+
485
+
486
+
487
+
488
+
489
+
490
+ // 3) The built client-side JS (with or without sourcemaps)
491
+ // 4) The compression setting (brotli/gzip) to compress that client-side JS
492
+
493
+
494
+
495
+
496
+ 'serve_package_from_path'(url, js_file_path, options = {}, callback) {
497
+ //console.log('serve_package_from_path', url, js_file_path);
498
+ // js_mode option may need to be used.
499
+
500
+
501
+ // Make it an observable?
502
+ // Raise an event when we have the browserified fill js file (uncompressed?).
503
+
504
+
505
+ let a = arguments;
506
+ if (typeof a[2] === 'function') {
507
+ callback = a[2];
508
+ options = {
509
+ //'babel': 'mini',
510
+ 'include_sourcemaps': false
511
+ };
512
+ }
513
+ let serve_raw = options.serve_raw || options.raw;
514
+ let accepts_brotli = false;
515
+
516
+ // Need to come up with compressed versions.
517
+ // An object that provides different versions.
518
+
519
+
520
+ return prom_or_cb((resolve, reject) => {
521
+ (async () => {
522
+ // options
523
+ // may want a replacement within the client-side code.
524
+ // Can we call browserify on the code string?
525
+ // Creating a modified copy of the file would do.
526
+ // Load the file, modify it, save it under a different name
527
+ const Stream = require('stream');
528
+
529
+ let s = new Stream.Readable(),
530
+ path = require('path').parse(js_file_path);
531
+
532
+ let fileContents = await fnlfs.load(js_file_path);
533
+ //console.log('1) fileContents.length', fileContents.length);
534
+ // are there any replacements to do?
535
+ // options.replacements
536
+ if (options.js_mode === 'debug') {
537
+ options.include_sourcemaps = true;
538
+ }
539
+ if (options.js_mode === 'compress' || options.js_mode === 'mini') {
540
+ options.include_sourcemaps = false;
541
+ options.babel = 'mini';
542
+ }
543
+ //console.log('options.babel', options.babel);
544
+
545
+ // Likely to remove this....
546
+ if (options.replace) {
547
+ let s_file_contents = fileContents.toString();
548
+ //console.log('s_file_contents', s_file_contents);
549
+ each(options.replace, (text, key) => {
550
+ //console.log('key', key);
551
+ //console.log('text', text);
552
+ const running_fn = '(' + text + ')();'
553
+ //console.log('running_fn', running_fn);
554
+ s_file_contents = s_file_contents.split(key).join(running_fn);
555
+ })
556
+ fileContents = Buffer.from(s_file_contents);
557
+ //console.log('2) fileContents.length', fileContents.length);
558
+ }
559
+
560
+ // Then we can replace some of the file contents with specific content given when we tall it to serve that file.
561
+ // We have a space for client-side activation.
562
+ // want a raw option with no browserify.
563
+ //console.log('serve_raw', serve_raw);
564
+ if (serve_raw) {
565
+ const escaped_url = url.replace(/\./g, '☺');
566
+ //this.custom_paths.set(escaped_url, fileContents);
567
+
568
+ throw 'NYI';
569
+ } else {
570
+ const formatting_info = analyse_js_doc_formatting(fileContents.toString());
571
+ //console.log('formatting_info', formatting_info);
572
+
573
+ const {arr_lines, line_break, indentation_analysis} = formatting_info;
574
+ const {parsed_lines, str_indentation} = indentation_analysis;
575
+ const client_root_js = extract_client_js(formatting_info);
576
+
577
+ //fnlfs.save('d:\\saved.js', client_root_js);
578
+
579
+
580
+ s.push(client_root_js);
581
+ s.push(null);
582
+ const lines_file_content = [];
583
+
584
+ // Don't always include sourcemap?
585
+ // Separate out the sourcemap?
586
+
587
+ const b = browserify(s, {
588
+ basedir: path.dir,
589
+ //builtins: false,
590
+ builtins: ['buffer'],
591
+ 'debug': options.include_sourcemaps
592
+ });
593
+ // Prefer the idea of sending a stream to browserify.
594
+ const parts = await stream_to_array(b.bundle());
595
+ /*
596
+ var b = browserify([js_file_path], {
597
+ 'debug': true
598
+ });
599
+ */
600
+ //let parts = await stream_to_array(b.bundle());
601
+ const buffers = parts
602
+ .map(part => util.isBuffer(part) ? part : Buffer.from(part));
603
+ let buf_js = Buffer.concat(buffers);
604
+ const str_js = buf_js.toString();
605
+ const str_js_code = str_js;
606
+ let str_sourcemap;
607
+
608
+ let pos_prior_sourcemap = str_js.indexOf('//# sourceMappingURL');
609
+ if (pos_prior_sourcemap > -1) {
610
+ str_js_code = str_js.substr(0, pos_prior_sourcemap);
611
+ str_sourcemap = str_js.substr(pos_prior_sourcemap);
612
+ }
613
+ // filter_extract_css
614
+
615
+
616
+ /*
617
+ const js_remove_comments = (str_js_code) => {
618
+ // comments will be OK within a string.
619
+
620
+ // Be able to work out what type of code we are in at all points...?
621
+ // Non-tokenising scanner...?
622
+
623
+ // Knowing whether or not * / // / * is within a string is important - because if it's in a string its not a comment.
624
+ // seems like making the scanning parser is a bit of a large task. It would constantly need to know what symbol type / string encapsulator to use.
625
+
626
+ // Could split it into lines, spot whenever a line starts a comment...?
627
+ }
628
+ */
629
+
630
+ const filter_js_extract_control_css = (str_js_code) => {
631
+ // res = [css, js_no_css]
632
+ // Split the js lines.
633
+
634
+ const s_js = str_js_code.split('\n');
635
+ let within_class_css = false;
636
+ const control_css_lines = [];
637
+ const js_non_css_lines = [];
638
+ // and the non-css lines.
639
+ // And need to look for its stop.
640
+ // And leave the first and last line out of the css.
641
+ each(s_js, js_line => {
642
+ let placed_js_line = false;
643
+ const pos_class_css_begin = js_line.indexOf('.css = `');
644
+ // if its 0
645
+
646
+ if (pos_class_css_begin > -1) {
647
+ //console.log('js_line', js_line);
648
+ within_class_css = true;
649
+ }
650
+ // Put empty lines (back) into the js array?
651
+
652
+ if (within_class_css) {
653
+ //console.log('js_line', js_line);
654
+
655
+ const pos_control_css_end = js_line.indexOf('`;');
656
+ //console.log('pos_control_css_end', pos_control_css_end);
657
+ if (pos_control_css_end > -1) {
658
+ within_class_css = false;
659
+ } else {
660
+ if (pos_class_css_begin > -1) {
661
+
662
+ } else {
663
+ control_css_lines.push(js_line);
664
+ }
665
+
666
+ }
667
+ } else {
668
+ js_non_css_lines.push(js_line);
669
+ placed_js_line = true;
670
+ }
671
+
672
+ if (!placed_js_line) {
673
+ js_non_css_lines.push('');
674
+ }
675
+ //let is_control_css_start = js_line.indexOf()
676
+
677
+ if (control_css_lines.length > 200) throw 'stop';
678
+
679
+ })
680
+ return [control_css_lines.join('\n'), js_non_css_lines.join('\n')];
681
+ }
682
+
683
+ let [str_css, str_js_no_css] = filter_js_extract_control_css(str_js_code);
684
+
685
+ // Add the sourcemaps back? Its working.
686
+
687
+ if (str_sourcemap) {
688
+ str_js_no_css = str_js_no_css + str_sourcemap;
689
+ }
690
+ this.raise('extracted-controls-css', str_css);
691
+ let babel_option = options.babel;
692
+
693
+ //console.log('babel_option', babel_option);
694
+ //throw 'stop';
695
+ //babel_option = 'es5';
696
+ //console.log('babel_option', babel_option);
697
+ if (babel_option === 'es5') {
698
+ // es5 option
699
+ // not sure if it babels async await though.
700
+ /*
701
+ {
702
+ "presets": [
703
+ "es2015",
704
+ "es2017"
705
+ ],
706
+ "plugins": [
707
+ "transform-runtime"
708
+ ]
709
+ }
710
+ */
711
+ /*
712
+ let res_transform = babel.transform(str_js, {
713
+ //'plugins': ['transform-class']
714
+ 'plugins': ['transform-es2015-object-super', 'transform-es2015-classes', 'remove-comments'],
715
+ 'sourceMaps': 'inline'
716
+ //'plugins': ['transform-es2015-classes']
717
+ // transform-es2015-object-super
718
+ });
719
+ */
720
+ let o_tranform = {
721
+ "presets": [
722
+ "es2015",
723
+ "es2017"
724
+ ],
725
+ "plugins": [
726
+ "transform-runtime"
727
+ ] //,
728
+ //'sourceMaps': 'inline'
729
+ };
730
+ if (options.include_sourcemaps) o_tranform.sourceMaps = 'inline';
731
+
732
+ let res_transform = babel.transform(str_js_no_css, o_tranform);
733
+ let jst_es5 = res_transform.code;
734
+ //let {jst_es5, map, ast} = babel.transform(str_js);
735
+ //console.log('jst_es5.length', jst_es5.length);
736
+ buf_js = Buffer.from(jst_es5);
737
+ } else if (babel_option === 'mini') {
738
+ /*
739
+ let o_transform = {
740
+ presets: ["minify"]//,
741
+ //'sourceMaps': 'inline'
742
+ };
743
+ */
744
+ let o_transform = {
745
+ "presets": [
746
+ ["minify", {
747
+ //"mangle": {
748
+ //"exclude": ["MyCustomError"]
749
+ //},
750
+ //"unsafe": {
751
+ // "typeConstructors": false
752
+ //},
753
+ //"keepFnName": true
754
+ }]
755
+ ],
756
+ "comments": false
757
+ //plugins: ["minify-dead-code-elimination"]
758
+ };
759
+
760
+ if (options.include_sourcemaps) o_transform.sourceMaps = 'inline';
761
+ let res_transform = babel.transform(str_js_no_css, o_transform);
762
+ //let jst_es5 = res_transform.code;
763
+ //let {jst_es5, map, ast} = babel.transform(str_js);
764
+ //console.log('jst_es5.length', jst_es5.length);
765
+ buf_js = Buffer.from(res_transform.code);
766
+ } else {
767
+ buf_js = Buffer.from(str_js_no_css);
768
+ console.log('no babel use');
769
+ }
770
+ var escaped_url = url.replace(/\./g, '☺');
771
+
772
+ //console.log('pre compress buf_js.length', buf_js.length);
773
+ zlib.gzip(buf_js, {level: 9}, (err, buffer) => {
774
+ console.log('deflated buf_js buffer.length', buffer.length);
775
+
776
+ if (err) {
777
+ reject(err);
778
+ } else {
779
+ //
780
+ //buffer.encoding = 'deflate';
781
+ console.log('');
782
+ console.log('escaped_url', escaped_url);
783
+ console.log('url', url);
784
+ console.log('');
785
+
786
+ const rp = this.pool;
787
+ console.log('rp', rp);
788
+ console.log('rp.resource_names', rp.resource_names);
789
+
790
+ const router = rp.get_resource('Site Router');
791
+ console.log('router', router);
792
+
793
+ router.set_route(url, this, (req, res) => {
794
+ console.log('router', [!!req, !!res]);
795
+ });
796
+
797
+ /*
798
+ 'set_route'(str_route, context, fn_handler) {
799
+ */
800
+
801
+ // Setting up routing here?
802
+ // Or returning it to the server?
803
+
804
+ // hack_setup_routing - as in it hacks into another part of the system (which is available)
805
+ // to set up the routing. A more top-down approach would be for the Server module to set the
806
+ // routing up itself.
807
+ // May be nice if components / resources could set up their own routing, with access to the
808
+ // Resource_Pool.
809
+
810
+
811
+
812
+ /*
813
+
814
+ // Would need to check operation of custom paths.
815
+ // Maybe its use was removed...?
816
+ this.custom_paths.set(escaped_url, {
817
+ raw: buf_js,
818
+ gzip: buffer
819
+ });
820
+
821
+ */
822
+
823
+
824
+
825
+ resolve(true);
826
+ }
827
+ });
828
+ }
829
+ })();
830
+ }, callback);
831
+ }
832
+
833
+ /*
834
+ 'set_custom_path'(url, file_path) {
835
+ var escaped_url = url.replace(/\./g, '☺');
836
+ this.custom_paths.set(escaped_url, file_path);
837
+ }
838
+ */
839
+ //
840
+
841
+
842
+ // Not so sure that it should process the request.
843
+ // A more general purpose request handler...?
844
+ // Have more request handling code within one js file, a cenralised portion of the app.
845
+ // And then within those request handlers call on useful abstractions.
846
+
847
+ // Setting up one or more Compilers seems like it would solve some of what this is doing.
848
+ // Even a Compilation_Process object that provides data for monitoring.
849
+ // Published with a Resource_Publisher possibly.
850
+
851
+ // Website_HTTP_Publisher maybe
852
+
853
+ // or just HTTP_Publisher, a Publisher rather than a Resource.
854
+ // HTTP_Publisher, which is focused on publishing HTTP, may be the best option here.
855
+ // Seems best to fix what we have already first though. Could then work on HTTP_Publisher.
856
+
857
+
858
+
859
+ // Website_HTTP_Publisher_Resource possibly?
860
+
861
+ //
862
+
863
+
864
+
865
+ // Site_JavaScript seems more about bundling / compiling rather than serving.
866
+ // Resources could present their data ahead of time / be asked for them and provide it, and the server
867
+ // keeps track of info more centrally.
868
+ //
869
+
870
+
871
+
872
+
873
+ }
874
+
875
875
  module.exports = Site_JavaScript;