jsgui3-server 0.0.121 → 0.0.123

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