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
package/fs2.js CHANGED
@@ -1,1837 +1,1837 @@
1
- // Seems like this will be superceded by fnlfs.
2
-
3
-
4
- var jsgui = require('jsgui3-html');
5
- var child_process = require('child_process');
6
- var ncp_module = require('ncp');
7
- //var checksum = require('./file-checksum');
8
- var rimraf = require('rimraf');
9
- //var child_process = require('child_process');
10
- var ncp = ncp_module.ncp;
11
- var log = console.log;
12
-
13
- // removing libxmljs?
14
-
15
- var each = jsgui.each,
16
- stringify = jsgui.stringify,
17
- is_array = jsgui.is_array;
18
- var is_defined = jsgui.is_defined;
19
- var tof = jsgui.tof,
20
- arrayify = jsgui.arrayify,
21
- mapify = jsgui.mapify;
22
-
23
- var dir_separator = '/';
24
- //if (process.platform === 'win32') dir_separator = '\\';
25
-
26
- var fs = require('fs');
27
- var node_path = require('path');
28
- //var im = require('imagemagick');
29
- //var libxmljs = require("libxmljs");
30
-
31
- var exec = child_process.exec;
32
- var fp = jsgui.fp;
33
- var call_multiple_callback_functions = jsgui.call_multiple_callback_functions;
34
- var call_multi = jsgui.call_multi;
35
-
36
- var Fns = jsgui.Fns;
37
-
38
- // promisify these, put them into fnlfs.
39
- // do more work on fnlfs to make it observables.
40
- // then put that into vhl.
41
- // maybe with a bit of options and config done / automated by vhl.
42
-
43
-
44
-
45
-
46
-
47
- var file_checksum = function (file_path, callback) {
48
- var algo = 'sha256';
49
- var shasum = crypto.createHash(algo);
50
-
51
- var file = file_path;
52
- var s = fs.ReadStream(file);
53
- s.on('data', function (d) {
54
- shasum.update(d);
55
- });
56
- s.on('end', function () {
57
- //var d = shasum.digest('hex');
58
- var digest = shasum.digest('base64');
59
- //console.log(d);
60
- // base64
61
-
62
- callback(null, digest);
63
-
64
- });
65
- }
66
-
67
- var recursive_xml_traversal = function (xml, el_callback) {
68
- if (xml.root) {
69
- var root = xml.root();
70
- recursive_xml_traversal(root, el_callback);
71
- } else {
72
- if (xml.attrs) {
73
- el_callback(xml);
74
- var cns = xml.childNodes();
75
- each(cns, function (i, v) {
76
- recursive_xml_traversal(v, el_callback);
77
- });
78
- }
79
- }
80
- };
81
-
82
- var map_extension_mime_types = {
83
- 'html': 'text/html',
84
- 'htm': 'text/html',
85
- 'ico': 'image/x-icon',
86
- 'txt': 'text/plain',
87
- 'xml': 'application/xml',
88
- 'png': 'image/png',
89
- 'gif': 'image/gif',
90
- 'jpeg': 'image/jpeg',
91
- 'jpg': 'image/jpeg',
92
- 'bmp': 'image/bmp',
93
- 'svg': 'image/svg+xml',
94
- 'mp3': 'audio/mpeg3',
95
- 'ogg': 'audio/ogg',
96
- }
97
-
98
- var sequential_execute_fs_child_processes = function (arr_fs_process_commands, callback) {
99
- // not sure about doing the unused simultaneous method of multithreading.
100
- // may do that version later.
101
-
102
- var l = arr_fs_process_commands.length;
103
- var c = 0;
104
-
105
- var process = function () {
106
- var command = arr_fs_process_commands[c];
107
- c++;
108
-
109
- //console.log('pre exec command ' + command);
110
- exec(command, function (error, stdout, stderr) {
111
- if (error) {
112
- throw (error);
113
- } else {
114
- if (c < l) {
115
- process();
116
- } else {
117
- callback(null);
118
- }
119
- }
120
- })
121
- }
122
- if (c < l) process();
123
- }
124
-
125
- var fs2 = {
126
- 'path_parent': function (strPath) {
127
- var dirSep = '/';
128
- //console.log('strPath', strPath);
129
- var pos1 = strPath.lastIndexOf(dirSep);
130
- if (pos1 > -1) {
131
- var beginning = strPath.substr(0, pos1);
132
- //console.log('beginning ' + beginning);
133
- return beginning;
134
- }
135
- },
136
- 'path_last_part': function (strPath) {
137
- // the last part is not necessarily a file name, it may be.
138
- var dirSep = '/';
139
- var pos1 = strPath.lastIndexOf(dirSep);
140
- if (pos1 > -1) {
141
- var theRest = strPath.substr(pos1 + 1);
142
- //console.log('theRest ' + theRest);
143
- return theRest;
144
- } else {
145
- return strPath;
146
- }
147
- },
148
-
149
-
150
-
151
-
152
-
153
- // depth first walk?
154
- // The contents could be deleted when deleting files.
155
-
156
- // Could have a callback for the directory itself, and only later go into the contents.
157
-
158
- // Recursive delete could have a function return whether to delete it or not, and use rimraf to
159
- // carry out the deletion.
160
-
161
-
162
- // Getting all directory names may be useful.
163
- // Getting the whole file tree.
164
-
165
-
166
- // Get all directory names
167
- //
168
-
169
- 'recursive_dir_names': function (start_path, callback) {
170
- var arr_dir_names = [];
171
- fs2.walk(start_path, function (dir_path, dir_contents) {
172
- arr_dir_names.push(dir_path);
173
- }, function (err, res_all) {
174
- if (err) {
175
- callback(err);
176
-
177
- } else {
178
- callback(null, arr_dir_names);
179
- }
180
- })
181
- },
182
-
183
- 'recursive_dir_delete': function (start_path, fn_check, callback) {
184
- var arr_dir_names = [];
185
- // Walk, but wait until callback of inner function
186
- // walk, async inner.
187
-
188
- fs2.walk_async_inner(start_path, function (dir_path, dir_contents, cb) {
189
- //arr_dir_names.push(dir_path);
190
- var to_delete = fn_check(dir_path);
191
- if (to_delete) {
192
- fs2.delete(dir_path, cb);
193
- cb(null, true);
194
-
195
- } else {
196
- cb(null, false);
197
- }
198
-
199
- }, function (err, res_all) {
200
- if (err) {
201
- callback(err);
202
-
203
- } else {
204
- callback(null, arr_dir_names);
205
- }
206
- })
207
-
208
- },
209
-
210
-
211
-
212
-
213
- // dir_svg_dirs_to_png_dirs
214
- // creates the png directories according to output format.
215
- // could output to multiple formats as well.
216
-
217
- // With an asyncronous inner function, where it then checks to see if the directory still exists...?
218
-
219
- 'walk_async_inner': function (start_path, dir_callback, callback) {
220
- // May also need to know how many to do asymcronously at once.
221
- // may be recursive inside... that could be easier.
222
- // think this does need a callback for call_multi to work right.
223
- console.log('walk start_path', start_path);
224
- var rec = function (path, rcb) {
225
- //console.log('rec path ' + path);
226
- // read the contents from that path.
227
- fs2.dir_contents(path, function (err, contents) {
228
- if (err) {
229
- callback(err);
230
- } else {
231
- //console.log('contents ' + stringify(contents));
232
-
233
- // What about an async callback function, possibly where it deletes that directory?
234
-
235
-
236
- dir_callback(path, contents, function (err, res) {
237
- if (err) {
238
- //callback(err)
239
- } else {
240
- fs2.exists(path, function (err, exists) {
241
- if (exists) {
242
- fs2.dir_contents(path, function (err, contents) {
243
- if (err) {
244
- callback(err);
245
- } else {
246
-
247
- if (contents.directories) {
248
- // will use call_multi
249
- var fns = [];
250
-
251
- //console.log('contents.directories.length', contents.directories.length);
252
- each(contents.directories, function (directory, i) {
253
- //console.log('directory ' + stringify(directory));
254
-
255
- var dirPath = path + '/' + directory;
256
- //log('dirPath ' + dirPath);
257
- fns.push([rec, [dirPath]]);
258
- });
259
- call_multi(1, fns, function (err, res) {
260
- if (err) {
261
- //log('call_multi err ' + err);
262
- throw err;
263
- } else {
264
- //log('call multi cb');
265
- rcb();
266
- }
267
- })
268
- } else {
269
- rcb();
270
- }
271
-
272
- }
273
- });
274
- }
275
- })
276
- }
277
- });
278
- // have the directory callback with all the contents here.
279
- // however, need to go through each of the directories, processing them.
280
- // don't want too much code branching.
281
-
282
-
283
-
284
-
285
- }
286
- })
287
- };
288
- rec(start_path, callback);
289
- },
290
-
291
- 'walk': function (start_path, dir_callback, callback) {
292
- // May also need to know how many to do asymcronously at once.
293
- // may be recursive inside... that could be easier.
294
- // think this does need a callback for call_multi to work right.
295
- console.log('walk start_path', start_path);
296
- var rec = function (path, rcb) {
297
- //console.log('rec path ' + path);
298
- // read the contents from that path.
299
- fs2.dir_contents(path, function (err, contents) {
300
- if (err) {
301
- callback(err);
302
- } else {
303
- //console.log('contents ' + stringify(contents));
304
-
305
- // What about an async callback function, possibly where it deletes that directory?
306
-
307
-
308
- dir_callback(path, contents);
309
- // have the directory callback with all the contents here.
310
- // however, need to go through each of the directories, processing them.
311
- // don't want too much code branching.
312
-
313
- if (contents.directories) {
314
- // will use call_multi
315
- var fns = [];
316
-
317
- //console.log('contents.directories.length', contents.directories.length);
318
- each(contents.directories, function (directory, i) {
319
- //console.log('directory ' + stringify(directory));
320
-
321
- var dirPath = path + '/' + directory;
322
- //log('dirPath ' + dirPath);
323
- fns.push([rec, [dirPath]]);
324
- });
325
- call_multi(fns, function (err, res) {
326
- if (err) {
327
- //log('call_multi err ' + err);
328
- throw err;
329
- } else {
330
- //log('call multi cb');
331
- rcb();
332
- }
333
- })
334
- } else {
335
- rcb();
336
- }
337
-
338
-
339
- }
340
- })
341
- };
342
- rec(start_path, callback);
343
- },
344
- 'exists': function (path, callback) {
345
- fs.exists(path, function (res) {
346
- callback(null, res);
347
- })
348
- },
349
- // want to save a binary file as well.
350
-
351
- // But loading binary gets more complicated as we need to know the format in many cases, so will have specific functions
352
- // to load typed arrays.
353
- // Seems to work OK.
354
- // Will also want to load binary files.
355
- 'save_binary': function (file_path, file_content, callback) {
356
- // the file content could be a typed array.
357
- // just try to create a buffer out of it.
358
- //console.log('save_binary ' + file_path);
359
-
360
- if (file_content.buffer.byteLength) {
361
- // its a typed array
362
- console.log('file_content.length', file_content.length);
363
- var buf = Buffer.from(file_content.buffer);
364
- // but does it calculate the buffer length correctly?
365
- console.log('buf.length', buf.length);
366
-
367
- fs.open(file_path, "w", function (err, fd) {
368
- if (err) {
369
- callback(err);
370
- } else {
371
-
372
- //console.log('file opened');
373
- fs.write(fd, buf, 0, buf.length, function (err, res_write) {
374
- if (err) {
375
- console.log('err', err);
376
- callback(err);
377
- } else {
378
- //console.log('file written');
379
- fs.close(fd);
380
- //console.log('written to file_path ' + file_path);
381
- callback(null, file_path);
382
- }
383
- })
384
- }
385
- });
386
- }
387
- // But does the buf have a bytelength
388
- },
389
- // could put in filter objects...
390
- // so the text begins with something, has an extension, file size
391
- // plain mapify to use here I think.
392
- // may need to modify mapify to support callback functions like arrayify.
393
- // Can save a whole bunch of files as strings.
394
- 'save_file_as_string': mapify(fp(function (a, sig) {
395
- //console.log('save_file_as_string sig ' + sig);
396
- // and could JSON stringify an object.
397
- if (sig == '[s,o,f]' || sig == '[s,a,f]') {
398
- var file_path = a[0];
399
- var file_content = JSON.stringify(a[1]);
400
- var callback = a[2];
401
- return this.save_file_as_string(file_path, file_content, callback);
402
- }
403
-
404
- if (sig == '[s,s,f]') {
405
- var file_path = a[0];
406
- var file_content = a[1];
407
- var callback = a[2];
408
- //console.log('pre write file file_path', file_path);
409
- fs.writeFile(file_path, file_content, function (err) {
410
- if (err) {
411
- //console.log(err);
412
- callback(err);
413
- } else {
414
- //console.log("The file was saved!");
415
- callback(null, true);
416
- // could return the file path?
417
- // returning timing info would be cool as well.
418
- // could maybe make a function that keeps track of it as a function is executed.
419
- }
420
- });
421
- };
422
- })),
423
-
424
- 'process_file_as_string': function (file_path, fnProcess, callback) {
425
- fs2.load_file_as_string(file_path, function (err, str_file) {
426
- if (err) {
427
- callback(err);
428
- } else {
429
- fs2.save_file_as_string(file_path, fnProcess(str_file), callback);
430
- }
431
- });
432
- },
433
- // Loading a file as a Uint8 Typed array will become more important.
434
- // Will be using them rather than buffers in many cases.
435
- // Will be easier to interface with C++ code.
436
- // Probably not needed - as buffer is a Uint8Array.
437
- // May be easier to carry out operations on a Uint8Array in general though.
438
- // Also want to be able to load a file as a buffer.
439
-
440
- 'load_file_as_buffer': fp(function (a, sig) {
441
- //source_path, callback
442
- // should work as an array...
443
- // so when you give it an array of source paths, it loads them all, and returns the result as an array by default.
444
- // can return a map if asked to... would be easier to access in many cases, but problems when there are repeated params.
445
- // I think return map by default.
446
- // Arrayify input, mapify output.
447
- // could use arrayify here possibly...
448
- // could have a concurrency_limit argument.
449
- // would be useful to incorporate that into a lot of code as an option.
450
-
451
- var source_path, concurrency_limit = 4,
452
- callback;
453
- // console.log('load_file_as_string sig ' + sig);
454
-
455
- if (sig == '[a,n,f]') {
456
- source_path = a[0];
457
- concurrency_limit = a[1];
458
- callback = a[2];
459
- }
460
- if (sig == '[s,n,f]') {
461
- source_path = a[0];
462
- concurrency_limit = a[1];
463
- callback = a[2];
464
- }
465
- if (sig == '[a,f]') {
466
- source_path = a[0];
467
- callback = a[1];
468
- }
469
- if (sig == '[s,f]') {
470
- source_path = a[0];
471
- callback = a[1];
472
- }
473
-
474
- if (tof(source_path) == 'string') {
475
- fs.readFile(source_path, function (err, data_buffer) {
476
- if (err) {
477
- //console.log('error reading file at ' + source_path);
478
- //var stack = new Error().stack;
479
- // callback with the error.
480
- //console.log(stack);
481
- //throw err;
482
- callback(err);
483
- } else {
484
- callback(null, data_buffer);
485
- }
486
- //console.log('OK: ' + filename);
487
- //console.log(data)
488
- });
489
-
490
- } else if (tof(source_path) == 'array') {
491
- var res = {};
492
- var fns = [];
493
- each(source_path, function (i, source_path_item) {
494
- fns.push([fs2.load_file_as_buffer, [source_path_item], function (err, res_loaded) {
495
- if (err) throw err;
496
- res[source_path_item] = res_loaded;
497
- }]);
498
- });
499
- call_multi(fns, function (err, res_multi) {
500
- if (err) throw err;
501
- callback(null, res);
502
- });
503
- }
504
- //fs.readFile(filename, 'utf8', function(err, data_buffer) {
505
- }),
506
-
507
- 'load_json_as_object': function (path, callback) {
508
- this.load_file_as_string(path, function (err, str_file) {
509
- if (err) {
510
- callback(err);
511
- } else {
512
- // try/catch?
513
- //return JSON.parse(str_file);
514
-
515
- callback(null, JSON.parse(str_file));
516
- }
517
- });
518
- },
519
-
520
- 'load_file_as_string': fp(function (a, sig) {
521
- //source_path, callback
522
-
523
- // should work as an array...
524
- // so when you give it an array of source paths, it loads them all, and returns the result as an array by default.
525
- // can return a map if asked to... would be easier to access in many cases, but problems when there are repeated params.
526
- // I think return map by default.
527
- // Arrayify input, mapify output.
528
-
529
- // could use arrayify here possibly...
530
-
531
- // could have a concurrency_limit argument.
532
- // would be useful to incorporate that into a lot of code as an option.
533
-
534
- var source_path, concurrency_limit = 4,
535
- callback;
536
-
537
- //console.log('load_file_as_string sig ' + sig);
538
-
539
- if (sig == '[a,n,f]') {
540
- source_path = a[0];
541
- concurrency_limit = a[1];
542
- callback = a[2];
543
- }
544
- if (sig == '[s,n,f]') {
545
- source_path = a[0];
546
- concurrency_limit = a[1];
547
- callback = a[2];
548
- }
549
- if (sig == '[a,f]') {
550
- source_path = a[0];
551
- callback = a[1];
552
- }
553
- if (sig == '[s,f]') {
554
- source_path = a[0];
555
- callback = a[1];
556
- }
557
-
558
- if (tof(source_path) == 'string') {
559
- fs.readFile(source_path, function (err, data_buffer) {
560
- if (err) {
561
- callback(err);
562
- } else {
563
- callback(null, data_buffer.toString());
564
- }
565
- //console.log('OK: ' + filename);
566
- //console.log(data)
567
- });
568
-
569
- } else if (tof(source_path) == 'array') {
570
- var res = {};
571
- var fns = [];
572
- each(source_path, function (source_path_item) {
573
- fns.push([fs2.load_file_as_string, [source_path_item], function (err, res_loaded) {
574
- if (err) throw err;
575
-
576
- res[source_path_item] = res_loaded;
577
-
578
- }]);
579
- });
580
- call_multi(fns, function (err, res_multi) {
581
- if (err) throw err;
582
- callback(null, res);
583
- });
584
- }
585
-
586
- //fs.readFile(filename, 'utf8', function(err, data_buffer) {
587
-
588
- }),
589
-
590
- 'dir_dirs_beginning': function (dir_path, beginning_text, callback) {
591
- //console.log('dir_path ' + dir_path);
592
- //console.log('dir_path ' + tof(dir_path));
593
-
594
- // dir_contents has been arrayified, need to make sure it still works.
595
- //console.log('pre dir_contents');
596
- fs2.dir_contents(dir_path, function (err, dir_contents) {
597
- if (err) {
598
- throw err;
599
- } else {
600
- var directories = dir_contents.directories;
601
- var target_directories = [];
602
- each(directories, function (i, v) {
603
- if (v.substr(0, beginning_text.length) == beginning_text) target_directories.push(v);
604
- });
605
- callback(null, target_directories);
606
- }
607
- })
608
- },
609
-
610
- 'ensure_directory_exists': function (dir_path, callback) {
611
- fs.exists(dir_path, function (exists) {
612
- if (exists) {
613
- callback(null, true);
614
- } else {
615
- // Maybe go backwards recursively and make sure parents exist.
616
- fs.mkdir(dir_path, function (err) {
617
- if (err) {
618
- console.trace();
619
- console.log('dir_path', dir_path);
620
- throw (err);
621
- } else {
622
- callback(null, true);
623
- }
624
- })
625
- }
626
- })
627
- },
628
-
629
- // could use an arrayify function for functions with callbacks.
630
- 'dir_ensure': function (dir_path, callback) {
631
- if (tof(dir_path) == 'array') {
632
- var fns = [];
633
- each(dir_path, function (i, v) {
634
- fns.push([fs2.dir_ensure, [v]]);
635
- });
636
- call_multiple_callback_functions(fns, callback)
637
- } else {
638
- fs.exists(dir_path, function (exists) {
639
- if (exists) {
640
- callback(null, dir_path);
641
- } else {
642
- fs.mkdir(dir_path, function (err, res) {
643
- if (err) {
644
- throw err;
645
- } else {
646
- callback(null, dir_path);
647
- }
648
- })
649
- }
650
- });
651
- }
652
- },
653
-
654
- // dir_ensure_named_numbered
655
-
656
- 'dir_ensure_named_numbered': function (parentPath, name, callback) {
657
- // get the list of directories in the parent, make a map.
658
- this.dir_dirs_beginning(parentPath, name, function (err, resDirsBeginning) {
659
- if (err) {
660
- callback(err);
661
- } else {
662
- //console.log('resDirsBeginning ' + stringify(resDirsBeginning));
663
- var map_dirs_beginning = {};
664
- each(resDirsBeginning, function (i, v) {
665
- map_dirs_beginning[v] = true;
666
- });
667
- //console.log('map_dirs_beginning ' + stringify(map_dirs_beginning));
668
-
669
- // then loop to generate the name
670
- var c = 0,
671
- genName = name + '_' + c;
672
- while (map_dirs_beginning[genName]) {
673
- c++;
674
- genName = name + '_' + c;
675
- }
676
- // then we create the directory.
677
-
678
- var dirPath = parentPath + '/' + genName;
679
- //console.log('dirPath ' + dirPath);
680
- fs2.dir_ensure(dirPath, callback);
681
- }
682
- })
683
-
684
- },
685
-
686
- // likely to use an extension filer on dir_contents?
687
- // that way could also do a traversal_depth, so it looks in subdirectories
688
-
689
-
690
- 'dir_files_by_extension': fp(function (a, sig) {
691
- var path = a[0],
692
- extension = a[1],
693
- include_metadata = false,
694
- callback;
695
- if (a.l == 3) {
696
- callback = a[2];
697
- }
698
- if (a.l == 4) {
699
- include_metadata = a[2];
700
- callback = a[3];
701
- }
702
- var contents_cb = function (err, dir_contents) {
703
- if (err) {
704
-
705
- } else {
706
- //console.log('dir_contents ' + stringify(dir_contents));
707
-
708
- var res = [];
709
- each(dir_contents.files, function (i, v) {
710
- //console.log('v ' + stringify(v));
711
-
712
- var file_name;
713
-
714
- if (tof(v) == 'array') {
715
- file_name = v[0];
716
- }
717
- if (tof(v) == 'string') {
718
- file_name = v[1];
719
- }
720
-
721
- var file_extension = node_path.extname(file_name);
722
- if (extension == file_extension) {
723
-
724
-
725
- res.push(v);
726
- }
727
-
728
- })
729
- //return res;
730
- //console.log('res ' + res);
731
- callback(null, res);
732
- }
733
- };
734
- if (include_metadata) {
735
- fs2.dir_contents(path, include_metadata, contents_cb);
736
- } else {
737
-
738
- fs2.dir_contents(path, contents_cb);
739
- }
740
- }),
741
-
742
- // option include_metadata?
743
- // can include an extension filter.
744
-
745
- // dir_dirs?
746
-
747
- // and have this arrayified on param 0?
748
- // we may then want to get the contents of a bunch of dirs.
749
-
750
- 'dir_dirs': fp(function (a, sig) {
751
- // can still apply to multiple dirs.
752
- // source_dir, callback
753
-
754
- var source_dir, callback;
755
-
756
- //console.log('dir_dirs sig ' + sig);
757
- if (sig == '[s,f]') {
758
- source_dir = a[0];
759
- callback = a[1];
760
- this.dir_contents(source_dir, {
761
- 'files_or_directories': 'directories'
762
- }, callback);
763
- }
764
- if (sig == '[s,o,f]') {
765
- source_dir = a[0];
766
- options = a[1];
767
- callback = a[2];
768
- options.files_or_directories = 'directories';
769
- this.dir_contents(source_dir, options, callback);
770
- }
771
- // but do want this to allow a filter as well.
772
- }),
773
-
774
- // want to be able to load the file contents too.
775
-
776
- // could have this get directory contents recursively to a path... or maybe use the specialised function for that.
777
- 'dir_contents': arrayify(0, fp(function (a, sig) {
778
- // path, callback
779
-
780
- var path = a[0],
781
- filter, include_metadata = false,
782
- include_file_contents = false,
783
- callback, t_filter;
784
- var fs_paths = false;
785
- // with an extension filter...
786
-
787
- var extension_filter;
788
- var regex_filter;
789
- var res_format = 'array';
790
- //console.log('dir_contents sig ' + sig);
791
- // may want to specify options object.
792
- // may want to load the directories, that could be specified as an option.
793
- var files_or_directories;
794
- if (a.l == 2) {
795
- // [s,f]
796
- callback = a[1];
797
- }
798
- if (a.l == 3) {
799
-
800
- // [s,s,f]
801
- // it has an extension filter.
802
-
803
- if (sig == '[s,s,f]') {
804
- filter = a[1];
805
- extension_filter = filter;
806
- t_filter = 'extension';
807
- callback = a[2];
808
- var options = {};
809
- options.files_or_directories = 'files';
810
- }
811
-
812
- // [s,b,f]
813
-
814
- // [s,r,f]
815
-
816
- // [s,o,f]
817
- // can have an options object there.
818
- // another option can be files_or_directories??? better name?
819
-
820
- if (sig == '[s,o,f]') {
821
- //include_metadata = a[1];
822
- var options = a[1];
823
- if (options.include_metadata) include_metadata = options.include_metadata;
824
- if (options.files_or_directories) files_or_directories = options.files_or_directories;
825
- if (options.include_file_contents) include_file_contents = options.include_file_contents;
826
- if (options.res_format) res_format = options.res_format;
827
-
828
- if (options.filter) {
829
- filter = options.filter;
830
- t_filter = tof(filter);
831
-
832
- // then if t_filter is 'object', there will be more filter properties.
833
-
834
- if (t_filter == 'object') {
835
- if (filter.extension) {
836
- //filter = filter.extension;
837
- //t_filter = 'extension';
838
- extension_filter = filter.extension;
839
-
840
- }
841
- if (filter.regex) {
842
- //filter = filter.extension;
843
- //t_filter = 'extension';
844
- regex_filter = filter.regex;
845
-
846
- }
847
- }
848
- }
849
- if (options.fs_paths) {
850
- fs_paths = options.fs_paths;
851
- //throw 'stop';
852
- }
853
- callback = a[2];
854
- //console.log('sof');
855
- }
856
-
857
- if (sig == '[s,b,f]') {
858
- include_metadata = a[1];
859
- callback = a[2];
860
- }
861
- if (sig == '[s,r,f]') {
862
- filter = a[1];
863
- t_filter = 'regex';
864
- regex_filter = filter;
865
- callback = a[2];
866
- }
867
-
868
-
869
-
870
- // regex being the filter
871
- }
872
- if (a.l == 4) {
873
- if (sig == '[s,s,b,f]') {
874
- filter = a[1];
875
- t_filter = 'extension';
876
- include_metadata = a[2];
877
- callback = a[3];
878
- }
879
- if (sig == '[s,s,o,f]') {
880
- filter = a[1];
881
- t_filter = 'extension';
882
- extension_filter = filter;
883
-
884
- //include_metadata = a[2];
885
- var options = a[2];
886
- if (options.metadata) {
887
- include_metadata = options.metadata;
888
- }
889
- if (options.include_metadata) {
890
- include_metadata = options.include_metadata;
891
- }
892
- if (options.fs_paths) {
893
- fs_paths = options.fs_paths;
894
- //throw 'stop';
895
- }
896
- if (options.files_or_directories) files_or_directories = options.files_or_directories;
897
- if (options.include_file_contents) include_file_contents = options.include_file_contents;
898
- if (options.res_format) res_format = options.res_format;
899
-
900
-
901
- callback = a[3];
902
- }
903
- }
904
-
905
- // ssbff?
906
- //console.log ('!callback ' + tof(callback));
907
- //path = path.replace(/\//g, '\\');
908
- //console.log('dir_contents path ' + path);
909
-
910
- //console.log(fs.existsSync(path));
911
-
912
- // readdir working on a bunch of paths automatically?
913
- // or have this function arrayified?
914
- //console.log('pre fs.readdir');
915
- //throw 'stop';
916
- fs.readdir(path, function (err, files) {
917
- if (err) {
918
- //console.log('err ' + err);
919
- var stack = new Error().stack;
920
- console.log(stack);
921
- throw ('err ' + err);
922
- } else {
923
-
924
- //console.log('files ' + stringify(files));
925
- //console.log('typeof files ' + stringify(typeof files));
926
- //console.log('dir_contents path ' + path);
927
- var res = {};
928
- var res_files = [];
929
- var res_directories = [];
930
- var c = files.length;
931
- //console.log('c ' + c);
932
- //console.log ('!2callback ' + tof(callback));
933
- var cb = function () {
934
- //console.log('cb ');
935
- //console.log('files_or_directories', files_or_directories);
936
- if (files_or_directories == 'files') {
937
- callback(null, res_files);
938
- } else if (files_or_directories == 'directories') {
939
- callback(null, res_directories);
940
- } else {
941
-
942
- if (res_files.length > 0) {
943
- res.files = res_files;
944
- }
945
- if (res_directories.length > 0) {
946
- res.directories = res_directories;
947
- }
948
- //return res;
949
- //console.log('res ' + stringify(res));
950
- //console.log('tof callback ' + tof(callback));
951
- //console.log('callback ' + stringify(callback));
952
- callback(null, res);
953
- }
954
-
955
- }
956
-
957
- // maybe this could be done sequentially, perhaps doing n at once.
958
- // limit the simultaneous lookups.
959
-
960
- // want to do sequential function calls, waiting for the callback on each.
961
- // putting the result callback into the result, but calling it with different items.
962
-
963
- if (!files || files.length == 0) {
964
- cb();
965
- }
966
-
967
- //console.log('files.length', files.length);
968
-
969
- //console.log('files', files);
970
-
971
-
972
-
973
- each(files, function (v, i) {
974
- var file_name = v;
975
- //console.log('file_name', file_name);
976
- var file_or_dir_full_path;
977
-
978
- if (path.substr(path.length - 1) == '/') {
979
- file_or_dir_full_path = path + v;
980
- } else {
981
- file_or_dir_full_path = path + dir_separator + v;
982
- }
983
-
984
-
985
-
986
- //console.log('file_or_dir_full_path ' + stringify(file_or_dir_full_path));
987
-
988
- //console.log('i ' + stringify(i));
989
- //console.log('v ' + stringify(v));
990
- // find out if it is a directory.
991
-
992
- // depending on the name and filter, do the next step.
993
- var proceed = true;
994
-
995
- //console.log('extension_filter ' + extension_filter);
996
- //console.log('regex_filter ' + regex_filter);
997
-
998
- if (extension_filter) {
999
- var ext = node_path.extname(file_name);
1000
- //console.log('ext ' + ext);
1001
- proceed = ext == extension_filter;
1002
- }
1003
- if (proceed && regex_filter) {
1004
- //console.log('file_name ' + file_name);
1005
- proceed = regex_filter.test(file_name);
1006
- }
1007
- //console.log('proceed', proceed);
1008
-
1009
-
1010
- if (proceed) {
1011
-
1012
- fs.stat(file_or_dir_full_path, function (err, stats) {
1013
- //console.log('stats', stats);
1014
-
1015
- if (err) {
1016
-
1017
-
1018
-
1019
- //console.log('stats unavailable for ' + file_or_dir_full_path);
1020
-
1021
- var item_res = file_name;
1022
- res_files.push(item_res);
1023
-
1024
- // Probably don't fail whole thing with error...
1025
-
1026
- c--;
1027
- //console.log('c', c);
1028
- if (c == 0) {
1029
- cb();
1030
- }
1031
-
1032
- //throw(err);
1033
-
1034
- } else {
1035
- //console.log('stats.isDirectory() ' + stringify(stats.isDirectory()));
1036
-
1037
- var is_dir = stats.isDirectory();
1038
-
1039
- // not a dir anyway???
1040
- if (is_dir && files_or_directories != 'files') {
1041
- if (fs_paths) {
1042
- res_directories.push(file_or_dir_full_path);
1043
- } else {
1044
- res_directories.push(v);
1045
- }
1046
-
1047
- c--;
1048
- //console.log('c', c);
1049
- if (c == 0) {
1050
- cb();
1051
- }
1052
- } else if (files_or_directories != 'directories') {
1053
-
1054
- // can load the whole file as string if asked to do so.
1055
- // options.load_file == 'string'.
1056
- // if including the file contents... load it as a string.
1057
- // if including both the metadata and the content...
1058
- // could load them both at once.
1059
- // would like the Fns() system with .go rather than using call_multi.
1060
- // it can load the required data... calling a function that loads the metadata as well as a function that loads the file.
1061
- // when there are multiple file calls, the results should arrive in an array I think.
1062
- // fns.go seems like it would be very useful indeed.
1063
- var fns = Fns();
1064
- // and in the results we may need to include the full paths.
1065
- // that could be an option in the metadata function.
1066
- //fns.push([]);
1067
- if (include_metadata) {
1068
- fns.push([fs2.metadata, [file_or_dir_full_path]]);
1069
- // could become fns.push(fs2.metadata, file_or_dir_full_path);
1070
- }
1071
- if (include_file_contents) {
1072
- fns.push([fs2.load_file_as_string, [file_or_dir_full_path]]);
1073
- }
1074
- //console.log('fns.length ' + fns.length);
1075
- if (fns.length > 0) {
1076
- fns.go(function (err, fns_res) {
1077
- if (err) {
1078
- throw err;
1079
- } else {
1080
- //console.log('fns_res ' + stringify(fns_res));
1081
- //console.log('tof(fns_res) ' + tof(fns_res));
1082
- // we may need to return the fs paths with the data...
1083
- // path, content, metadata
1084
- if (include_metadata && include_file_contents) {
1085
- var metadata = fns_res[0];
1086
- var file_contents = fns_res[1];
1087
- if (res_format == 'array') {
1088
- //var res
1089
- var item_res = [file_or_dir_full_path, metadata, file_contents];
1090
- res_files.push(item_res);
1091
- } else if (res_format == 'map') {
1092
- var item_res = {
1093
- //'path': file_or_dir_full_path,
1094
- 'name': file_name,
1095
- 'metadata': metadata,
1096
- 'contents': file_contents
1097
- }
1098
- if (fs_paths) {
1099
- item_res.path = file_or_dir_full_path;
1100
- }
1101
- res_files.push(item_res);
1102
- }
1103
- } else if (include_metadata) {
1104
- var metadata = fns_res[0];
1105
- if (res_format == 'array') {
1106
- var item_res = [file_or_dir_full_path, metadata];
1107
- res_files.push(item_res);
1108
- } else if (res_format == 'map') {
1109
- var item_res = {
1110
- //'path': file_or_dir_full_path,
1111
- 'name': file_name,
1112
- 'metadata': metadata
1113
- }
1114
- if (fs_paths) {
1115
- item_res.path = file_or_dir_full_path;
1116
- }
1117
- res_files.push(item_res);
1118
- }
1119
- } else if (include_file_contents) {
1120
- var file_contents = fn_res[0];
1121
-
1122
- if (res_format == 'array') {
1123
- if (fs_paths) {
1124
- var item_res = [file_or_dir_full_path, file_contents];
1125
- } else {
1126
- var item_res = [file_name, file_contents];
1127
- }
1128
-
1129
-
1130
- res_files.push(item_res);
1131
- } else if (res_format == 'map') {
1132
- var item_res = {
1133
- //'path': file_or_dir_full_path,
1134
- 'name': file_name,
1135
- 'contents': file_contents
1136
- }
1137
- if (fs_paths) {
1138
- item_res.path = file_or_dir_full_path;
1139
- }
1140
- res_files.push(item_res);
1141
- }
1142
- } else {
1143
- // no results in the callback anyway.
1144
- if (fs_paths) {
1145
- var item_res = file_or_dir_full_path;
1146
- } else {
1147
- var item_res = file_name;
1148
- }
1149
- res_files.push(item_res);
1150
- //throw 'not yet implemented';
1151
- }
1152
- c--;
1153
- //console.log('c', c);
1154
- if (c == 0) {
1155
- cb();
1156
- }
1157
- //throw 'stop';
1158
- }
1159
- })
1160
- } else {
1161
- res_files.push(file_name);
1162
- c--;
1163
- //console.log('c', c);
1164
- if (c == 0) {
1165
- cb();
1166
- }
1167
- }
1168
-
1169
-
1170
- } else {
1171
- c--;
1172
- //console.log('c', c);
1173
- if (c == 0) {
1174
- cb();
1175
- }
1176
- //throw 'stop';
1177
- }
1178
-
1179
- }
1180
- })
1181
-
1182
-
1183
-
1184
- } else {
1185
- c--;
1186
- //console.log('c', c);
1187
- if (c == 0) {
1188
- cb();
1189
- }
1190
- }
1191
-
1192
- })
1193
- }
1194
- })
1195
- })),
1196
- // metadata... will make a (mime) type assumption based on the extension.
1197
- // may then read further metadata, possibly verify the file, metadata verification is one thing,
1198
- // has_metadata.
1199
- // There could be further file validation.
1200
- //
1201
-
1202
- // could possibly use arrayify, but arrayify that has been handled to work with callback functions.
1203
- // maybe call file_metadata.
1204
-
1205
- // possibly keep in the core... but it would look into a variety of file formats.
1206
- // possibly have a core version that gets data such as last modified and file size.
1207
- 'metadata': function (path, callback) {
1208
- // this may have options, like including the path in the results?
1209
- // calling metadata on a directory...
1210
- // should this get the metadata for files in the dir?
1211
- // mainly for file metadata.
1212
- // check to see if it exists.
1213
- //console.log('metadata path ' + path);
1214
- fs.exists(path, function (exists) {
1215
- if (!exists) {
1216
- //console.log('file does not exist ' + path);
1217
- //throw('file not found');
1218
- callback(null, false);
1219
- } else {
1220
- //var pos1 = path.lastIndexOf()
1221
- // just get the node.js file stats first.
1222
- fs.stat(path, function (err, stats) {
1223
- var extname = node_path.extname(path);
1224
- var basename = node_path.basename(path);
1225
- //console.log('extname ' + extname);
1226
- var extname2 = extname.substring(1);
1227
- var res = {
1228
- 'size': stats.size,
1229
- 'atime': stats.atime,
1230
- 'mtime': stats.mtime,
1231
- 'ctime': stats.ctime,
1232
- 'isDirectory': stats.isDirectory()
1233
- };
1234
- // atime, mtime, ctime
1235
- callback(null, [basename, res]);
1236
- });
1237
- }
1238
- });
1239
- },
1240
- // copy a file as well.
1241
- // This could be arrayified? But it would need parameter pairs?
1242
-
1243
- 'copy_file': function (source_path, dest_path, callback) {
1244
- //console.log('source_path ' + source_path);
1245
- //console.log('dest_path ' + dest_path);
1246
-
1247
- var r = fs.createReadStream(source_path).pipe(fs.createWriteStream(dest_path));
1248
-
1249
- r.on('close', function () {
1250
- //if (err) throw err;
1251
- //throw 'stop';
1252
- callback(null, true);
1253
- });
1254
- },
1255
-
1256
- 'instruct': fp(function (a, sig) {
1257
- // if it is just an array, and a callback...
1258
- //console.log('instruct sig ' + sig);
1259
- var is_multi_callback = false;
1260
-
1261
- if (a.l == 2) {
1262
- if (tof(a[0]) == 'array' && tof(a[1]) == 'function') {
1263
- // a bunch of instructions to execute, and then a callback.
1264
- var fns = [];
1265
- var instructions = a[0];
1266
- var callback = a[1];
1267
- is_multi_callback = true;
1268
-
1269
- each(instructions, function (i, instruction) {
1270
- fns.push([fs2.instruct, instruction])
1271
- })
1272
-
1273
- call_multiple_callback_functions(fns, function (err, res_multi) {
1274
- if (err) {
1275
- throw err;
1276
- } else {
1277
- callback(null, res_multi);
1278
- }
1279
- })
1280
- }
1281
- }
1282
-
1283
- if (!is_multi_callback) {
1284
- // then check to see if the last one is a callback.
1285
- // the ones before it will be parameters of various kinds.
1286
- // if first is string, last is function.
1287
-
1288
- var last_arg = a[a.l - 1];
1289
- //console.log('tof(last_arg) ' + tof(last_arg));
1290
-
1291
- if (tof(a[0]) == 'string' && tof(last_arg) == 'function') {
1292
- var command_name = a[0];
1293
- var callback = last_arg;
1294
-
1295
- // but basically want to call the right function with the params.
1296
-
1297
- var new_args = a.slice(1);
1298
-
1299
- if (command_name == 'copy') {
1300
- fs2.copy.apply(this, new_args);
1301
- }
1302
- }
1303
- }
1304
- }),
1305
-
1306
- 'process_copy': function (source_path, fn_process, dest_path, callback) {
1307
- fs2.load_file_as_string(source_path, function (err, strFile) {
1308
- if (err) {
1309
- callback(err);
1310
- } else {
1311
- strFile = fn_process(str_file);
1312
- fs2.save_file_as_string(dest_path, callback);
1313
- }
1314
- })
1315
- },
1316
-
1317
- 'copy': function (source_path, dest_path, callback) {
1318
- // dest must be a directory
1319
- ncp.limit = 16;
1320
- //console.log('copy source_path ' + source_path);
1321
- //console.log('copy dest_path ' + dest_path);
1322
-
1323
- //var test_for_same_files = true;
1324
- // testing needs to handle when the dest file does not exist.
1325
- var test_for_same_files = false;
1326
- var ctu = true;
1327
-
1328
- var the_rest = function () {
1329
- ncp(source_path, dest_path, function (err) {
1330
- if (err) {
1331
- return console.error(err);
1332
- }
1333
- callback(null, true);
1334
- //console.log('done!');
1335
- });
1336
- }
1337
-
1338
- if (test_for_same_files) {
1339
- // get the checksum for the source, and the dest.
1340
-
1341
- checksum(source_path, function (err, source_checksum) {
1342
- checksum(dest_path, function (err, dest_checksum) {
1343
- if (source_checksum != dest_checksum) {
1344
- the_rest();
1345
- } else {
1346
- callback(null, false);
1347
- }
1348
-
1349
- })
1350
- })
1351
-
1352
- } else {
1353
- the_rest();
1354
- }
1355
-
1356
- /*
1357
- fs.stat(dest_path, function(err, stats) {
1358
- if (err) {
1359
-
1360
- } else {
1361
-
1362
- if (stats.isDirectory()) {
1363
-
1364
- fs.stat(source_path, function(err, stats) {
1365
- if (err) {
1366
-
1367
- } else {
1368
-
1369
- if (stats.isDirectory()) {
1370
-
1371
- // create the corresponding directory
1372
- // copy every file and directory within that directory to the corresponding directory
1373
-
1374
- // This can be built up using fns.
1375
-
1376
-
1377
-
1378
- } else {
1379
-
1380
- }
1381
-
1382
- }
1383
- });
1384
-
1385
- }
1386
-
1387
- }
1388
- });
1389
- */
1390
- // source can be a file or directory.
1391
-
1392
- // when copying a directory, copy all directories inside it as well (recursively).
1393
-
1394
- },
1395
- 'delete': function (path, callback) {
1396
- // needs to be a versitile delete function.
1397
-
1398
- // use rimraf if it's a directory.
1399
- fs2.metadata(path, function (err, md) {
1400
- if (err) {
1401
- callback(err);
1402
- } else {
1403
- console.log('md ' + stringify(md));
1404
- if (!md) {
1405
- callback(null, false);
1406
- } else {
1407
- console.log('md.isDirectory ' + md.isDirectory);
1408
- if (md[1].isDirectory) {
1409
- console.log('pre rimraf path', path);
1410
- rimraf(path, function (err) {
1411
- if (err) {
1412
- callback(err);
1413
- } else {
1414
- callback(null, true);
1415
- }
1416
- });
1417
- }
1418
- }
1419
-
1420
- }
1421
- })
1422
- },
1423
-
1424
- 'exists': function (path, callback) {
1425
- fs.stat(path, (err, stat) => {
1426
- callback(null, !!stat);
1427
- });
1428
- },
1429
-
1430
- // does not try to delete it if its not there to start with
1431
-
1432
- 'ensure_deleted': function (path, callback) {
1433
- fs2.exists(path, (err, exists) => {
1434
- if (!exists) {
1435
- callback(null, true);
1436
- } else {
1437
- fs2.delete(path, callback);
1438
- }
1439
- });
1440
- },
1441
- // ensure_deleted
1442
-
1443
- 'move': function (source_path, dest_path, callback) {
1444
- var that = this;
1445
- this.copy(source_path, dest_path, (err, res_copy) => {
1446
- if (err) {
1447
- callback(err);
1448
- } else {
1449
- that.delete(source_path, callback);
1450
- }
1451
- })
1452
- },
1453
-
1454
-
1455
- // fs2-traverse?
1456
-
1457
- // maybe keep in core for the moment.
1458
-
1459
-
1460
- 'dir_contents_with_metadata_full_tree': function (start_path, callback) {
1461
- // get this from za?
1462
-
1463
- // I think this will be recursive...
1464
- //console.log('');
1465
- //console.log('dir_contents_with_metadata_to_path');
1466
- //console.log('start_path ' + start_path);
1467
- //console.log('dest_path ' + dest_path);
1468
-
1469
-
1470
- // Let's build this up...
1471
-
1472
- // get the contents and metadata for the path itself.
1473
-
1474
- // Also, this can act as a finite state machine.
1475
- // Can have simultaneous processes too.
1476
-
1477
- // recursive function within this one.
1478
-
1479
- var path_from_start = '';
1480
-
1481
- var res = {};
1482
-
1483
-
1484
- // and look at the dest path...
1485
-
1486
- if (dest_path.length < start_path.length) {
1487
- throw 'dest path length must be >= source path length';
1488
- }
1489
-
1490
- if (dest_path.substr(0, start_path.length) != start_path) {
1491
- throw 'the dest path must start with the start path - therefore being a subdirectory';
1492
- }
1493
-
1494
- var process_path = function (path_from_start, arr_path, current_res_obj, callback) {
1495
- //console.log('process_path');
1496
- //console.log('arr_path ' + stringify(arr_path));
1497
-
1498
- var current_path = start_path + path_from_start;
1499
-
1500
- // will need to put the items into the res properly.
1501
- //console.log('current_path ' + current_path);
1502
- //throw 'stop';
1503
- fs2.dir_contents_with_metadata(current_path, function (err, dir_contents) {
1504
- if (err) {
1505
- throw (err);
1506
- } else {
1507
- // for every file...
1508
- //console.log('have contents for ' + current_path);
1509
-
1510
-
1511
- if (dir_contents.files && dir_contents.files.length > 0) {
1512
- current_res_obj.files = current_res_obj.files || [];
1513
- each(dir_contents.files, function (i, file_info) {
1514
- //console.log('file_info ' + stringify(file_info));
1515
- var file_name = file_info[0];
1516
- var file_md = file_info[1];
1517
- //current_res_obj.files[file_name] = file_md;
1518
-
1519
- current_res_obj.files.push(file_info);
1520
- });
1521
- //console.log('dir_contents ' + stringify(dir_contents));
1522
- }
1523
-
1524
- // for every directory... that gets more complicated.
1525
-
1526
- // won't do the callback yet...
1527
-
1528
- // will get the info from the directories, and put them in an object.
1529
- // name, contents, metadata.
1530
-
1531
- if (dir_contents.directories) {
1532
- // process those directories.
1533
- current_res_obj.directories = current_res_obj.directories || [];
1534
- //var next_path =
1535
- //var next_arr_path = arr_path.slice();
1536
- //next_arr_path.push(
1537
-
1538
- var fns = [];
1539
-
1540
- each(dir_contents.directories, function (i, directory_info) {
1541
- //console.log('directory_info ' + stringify(directory_info));
1542
-
1543
- if (tof(directory_info == 'string')) {
1544
- var directory_name = directory_info;
1545
- var next_arr_path = arr_path.slice();
1546
- next_arr_path.push(directory_name);
1547
-
1548
- var dir_obj = [directory_name, {}, {}];
1549
- current_res_obj.directories.push(dir_obj);
1550
-
1551
- //console.log('path_from_start.substr(path_from_start.length -1) ' + path_from_start.substr(path_from_start.length -1));
1552
-
1553
- //console.log('path_from_start ' + path_from_start);
1554
-
1555
-
1556
- /*
1557
- if (path_from_start.substr(path_from_start.length -1) == dir_separator) {
1558
- throw 'stop';
1559
- var next_path_from_start = path_from_start + directory_name;
1560
- fns.push([process_path, [next_path_from_start, next_arr_path, current_res_obj]]);
1561
- } else {
1562
- var next_path_from_start = path_from_start + directory_name + dir_separator;
1563
- fns.push([process_path, [next_path_from_start, next_arr_path, current_res_obj]]);
1564
- }
1565
- */
1566
-
1567
- var next_path_from_start = path_from_start + directory_name + dir_separator;
1568
- fns.push([process_path, [next_path_from_start, next_arr_path, current_res_obj]]);
1569
-
1570
- } else {
1571
- throw 'string expected';
1572
- }
1573
-
1574
- });
1575
- //console.log('fns.length ' + fns.length);
1576
- if (fns.length > 0) {
1577
- call_multiple_callback_functions(fns, function (err, fns_res) {
1578
- //console.log('fns_res ' + stringify(fns_res));
1579
- callback(null, res);
1580
- });
1581
- } else {
1582
- callback(null, res);
1583
- }
1584
-
1585
- } else {
1586
- //console.log('no directories');
1587
- callback(null, res);
1588
- }
1589
-
1590
- // need to go through every directory there, processing the path.
1591
-
1592
- }
1593
- });
1594
-
1595
- }
1596
-
1597
- process_path('', [], res, function (err, res_process_path) {
1598
- //throw 'stop';
1599
-
1600
- callback(null, res_process_path);
1601
-
1602
- });
1603
- },
1604
-
1605
-
1606
- // could become another option of 'dir_contents'
1607
- // and 'dir_contents' could even become 'contents' where it would load the contents of a file too. Maybe even set contents as well.
1608
-
1609
- // this is unrestricted from that path.
1610
-
1611
- 'dir_contents_with_metadata_to_path': function (start_path, dest_path, callback) {
1612
- // find the sequence of paths to get
1613
-
1614
- // get them in sequence, then construct them into the object.
1615
-
1616
- // maybe difficult?
1617
- // get this from za?
1618
- // I think this will be recursive...
1619
- //console.log('');
1620
- //console.log('dir_contents_with_metadata_to_path');
1621
- //console.log('start_path ' + start_path);
1622
- //console.log('dest_path ' + dest_path);
1623
-
1624
-
1625
- // Let's build this up...
1626
-
1627
- // get the contents and metadata for the path itself.
1628
-
1629
- // Also, this can act as a finite state machine.
1630
- // Can have simultaneous processes too.
1631
-
1632
- // recursive function within this one.
1633
-
1634
- var path_from_start = '';
1635
-
1636
- var s_path_from_start = path_from_start.split(dir_separator);
1637
-
1638
- var res = {};
1639
-
1640
-
1641
- // and look at the dest path...
1642
-
1643
- if (dest_path.length < start_path.length) {
1644
- throw 'dest path length must be >= source path length';
1645
- }
1646
-
1647
- if (dest_path.substr(0, start_path.length) != start_path) {
1648
- throw 'the dest path must start with the start path - therefore being a subdirectory';
1649
- }
1650
-
1651
- var navigation_path = dest_path.substr(start_path.length);
1652
- //console.log('navigation_path ' + navigation_path);
1653
-
1654
- if (navigation_path.substr(navigation_path.length - 1) == dir_separator) {
1655
- navigation_path = navigation_path.substr(0, navigation_path.length - 1);
1656
- }
1657
-
1658
- //console.log('navigation_path ' + navigation_path);
1659
-
1660
- var s_np = navigation_path.split(dir_separator);
1661
- //console.log('s_np ' + stringify(s_np));
1662
-
1663
- //throw 'stop';
1664
-
1665
- var depth = 0;
1666
-
1667
- var process_path = function (path_from_start, arr_path, current_res_obj, depth, callback) {
1668
- //console.log('process_path');
1669
- //console.log('arr_path ' + stringify(arr_path));
1670
-
1671
- var current_path = start_path + path_from_start;
1672
-
1673
- // will need to put the items into the res properly.
1674
- //console.log('current_path ' + current_path);
1675
- //throw 'stop';
1676
- fs2.dir_contents_with_metadata(current_path, function (err, dir_contents) {
1677
- if (err) {
1678
- throw (err);
1679
- } else {
1680
- // for every file...
1681
- //console.log('have contents for ' + current_path);
1682
-
1683
-
1684
- if (dir_contents.files && dir_contents.files.length > 0) {
1685
- current_res_obj.files = current_res_obj.files || [];
1686
- each(dir_contents.files, function (file_info, i) {
1687
- //console.log('file_info ' + stringify(file_info));
1688
- var file_name = file_info[0];
1689
- var file_md = file_info[1];
1690
- //current_res_obj.files[file_name] = file_md;
1691
-
1692
- current_res_obj.files.push(file_info);
1693
- });
1694
- //console.log('dir_contents ' + stringify(dir_contents));
1695
- }
1696
-
1697
- // for every directory... that gets more complicated.
1698
-
1699
- // won't do the callback yet...
1700
-
1701
- // will get the info from the directories, and put them in an object.
1702
- // name, contents, metadata.
1703
-
1704
- if (dir_contents.directories) {
1705
- // process those directories.
1706
- current_res_obj.directories = current_res_obj.directories || [];
1707
- //var next_path =
1708
- //var next_arr_path = arr_path.slice();
1709
- //next_arr_path.push(
1710
-
1711
- var fns = [];
1712
-
1713
- each(dir_contents.directories, function (i, directory_info) {
1714
- //console.log('directory_info ' + stringify(directory_info));
1715
-
1716
- if (tof(directory_info == 'string')) {
1717
- var directory_name = directory_info;
1718
- var next_arr_path = arr_path.slice();
1719
- next_arr_path.push(directory_name);
1720
-
1721
- var dir_obj = [directory_name, {}, {}];
1722
- current_res_obj.directories.push(dir_obj);
1723
-
1724
-
1725
- // check it's the next directory name.
1726
-
1727
- if (directory_name == s_np[depth]) {
1728
-
1729
- var next_path_from_start = path_from_start + directory_name + dir_separator;
1730
- fns.push([process_path, [next_path_from_start, next_arr_path, current_res_obj, depth + 1]]);
1731
-
1732
- }
1733
-
1734
-
1735
-
1736
- } else {
1737
- throw 'string expected';
1738
- }
1739
-
1740
- });
1741
- //console.log('fns.length ' + fns.length);
1742
- if (fns.length > 0) {
1743
- call_multiple_callback_functions(fns, function (err, fns_res) {
1744
- //console.log('fns_res ' + stringify(fns_res));
1745
- callback(null, res);
1746
- });
1747
- } else {
1748
- callback(null, res);
1749
- }
1750
-
1751
-
1752
-
1753
- } else {
1754
- //console.log('no directories');
1755
- callback(null, res);
1756
- }
1757
- // need to go through every directory there, processing the path.
1758
- }
1759
-
1760
- });
1761
-
1762
- }
1763
-
1764
- process_path('', [], res, depth, function (err, res_process_path) {
1765
- //throw 'stop';
1766
-
1767
- callback(null, res_process_path);
1768
-
1769
- });
1770
-
1771
- },
1772
-
1773
-
1774
- // will use the polymorphism of dir_contents and parameters.
1775
- // have this returning the object with files and directories.
1776
- '_dir_contents_with_metadata': function (path, callback) {
1777
- //console.log('dir_contents_with_metadata path ' + path);
1778
-
1779
- if (path.lastIndexOf(dir_separator) != path.length - 1) {
1780
- path = path + dir_separator;
1781
- }
1782
-
1783
- fs2.dir_contents(path, function (err, dir_contents) {
1784
- if (err) {
1785
- //console.log('dir_contents_with_metadata err ' + err);
1786
- } else {
1787
- //console.log('dir_contents_with_metadata path ' + path + ' has callback ');
1788
- var res = {};
1789
-
1790
- if (dir_contents.directories && dir_contents.directories.length > 0) {
1791
- res.directories = dir_contents.directories;
1792
- }
1793
-
1794
- var cb = function () {
1795
- callback(null, res);
1796
- };
1797
-
1798
- if (dir_contents.files && dir_contents.files.length > 0) {
1799
- // do a sequential_call
1800
-
1801
- //console.log('dir_contents.files ' + stringify(dir_contents.files));
1802
-
1803
- var seq_md = sequential_call(fs2.metadata);
1804
- // may be a faster way of getting metadata.
1805
-
1806
- var files_with_paths = [];
1807
- each(dir_contents.files, function (v, i) {
1808
- var full_path = path + v;
1809
- files_with_paths.push(full_path);
1810
- });
1811
-
1812
- //console.log('files_with_paths ' + stringify(files_with_paths));
1813
-
1814
- seq_md(files_with_paths, function (err, res2) {
1815
- if (err) {
1816
-
1817
- } else {
1818
- //console.log('seq_md res ' + stringify(res));
1819
- res.files = res2;
1820
- callback(null, res);
1821
- }
1822
- });
1823
- } else {
1824
- cb();
1825
- }
1826
- }
1827
- })
1828
- }
1829
-
1830
- }
1831
-
1832
-
1833
- //module.exports = fs2;
1834
- // return fs2;
1835
- //});
1836
-
1
+ // Seems like this will be superceded by fnlfs.
2
+
3
+
4
+ var jsgui = require('jsgui3-html');
5
+ var child_process = require('child_process');
6
+ var ncp_module = require('ncp');
7
+ //var checksum = require('./file-checksum');
8
+ var rimraf = require('rimraf');
9
+ //var child_process = require('child_process');
10
+ var ncp = ncp_module.ncp;
11
+ var log = console.log;
12
+
13
+ // removing libxmljs?
14
+
15
+ var each = jsgui.each,
16
+ stringify = jsgui.stringify,
17
+ is_array = jsgui.is_array;
18
+ var is_defined = jsgui.is_defined;
19
+ var tof = jsgui.tof,
20
+ arrayify = jsgui.arrayify,
21
+ mapify = jsgui.mapify;
22
+
23
+ var dir_separator = '/';
24
+ //if (process.platform === 'win32') dir_separator = '\\';
25
+
26
+ var fs = require('fs');
27
+ var node_path = require('path');
28
+ //var im = require('imagemagick');
29
+ //var libxmljs = require("libxmljs");
30
+
31
+ var exec = child_process.exec;
32
+ var fp = jsgui.fp;
33
+ var call_multiple_callback_functions = jsgui.call_multiple_callback_functions;
34
+ var call_multi = jsgui.call_multi;
35
+
36
+ var Fns = jsgui.Fns;
37
+
38
+ // promisify these, put them into fnlfs.
39
+ // do more work on fnlfs to make it observables.
40
+ // then put that into vhl.
41
+ // maybe with a bit of options and config done / automated by vhl.
42
+
43
+
44
+
45
+
46
+
47
+ var file_checksum = function (file_path, callback) {
48
+ var algo = 'sha256';
49
+ var shasum = crypto.createHash(algo);
50
+
51
+ var file = file_path;
52
+ var s = fs.ReadStream(file);
53
+ s.on('data', function (d) {
54
+ shasum.update(d);
55
+ });
56
+ s.on('end', function () {
57
+ //var d = shasum.digest('hex');
58
+ var digest = shasum.digest('base64');
59
+ //console.log(d);
60
+ // base64
61
+
62
+ callback(null, digest);
63
+
64
+ });
65
+ }
66
+
67
+ var recursive_xml_traversal = function (xml, el_callback) {
68
+ if (xml.root) {
69
+ var root = xml.root();
70
+ recursive_xml_traversal(root, el_callback);
71
+ } else {
72
+ if (xml.attrs) {
73
+ el_callback(xml);
74
+ var cns = xml.childNodes();
75
+ each(cns, function (i, v) {
76
+ recursive_xml_traversal(v, el_callback);
77
+ });
78
+ }
79
+ }
80
+ };
81
+
82
+ var map_extension_mime_types = {
83
+ 'html': 'text/html',
84
+ 'htm': 'text/html',
85
+ 'ico': 'image/x-icon',
86
+ 'txt': 'text/plain',
87
+ 'xml': 'application/xml',
88
+ 'png': 'image/png',
89
+ 'gif': 'image/gif',
90
+ 'jpeg': 'image/jpeg',
91
+ 'jpg': 'image/jpeg',
92
+ 'bmp': 'image/bmp',
93
+ 'svg': 'image/svg+xml',
94
+ 'mp3': 'audio/mpeg3',
95
+ 'ogg': 'audio/ogg',
96
+ }
97
+
98
+ var sequential_execute_fs_child_processes = function (arr_fs_process_commands, callback) {
99
+ // not sure about doing the unused simultaneous method of multithreading.
100
+ // may do that version later.
101
+
102
+ var l = arr_fs_process_commands.length;
103
+ var c = 0;
104
+
105
+ var process = function () {
106
+ var command = arr_fs_process_commands[c];
107
+ c++;
108
+
109
+ //console.log('pre exec command ' + command);
110
+ exec(command, function (error, stdout, stderr) {
111
+ if (error) {
112
+ throw (error);
113
+ } else {
114
+ if (c < l) {
115
+ process();
116
+ } else {
117
+ callback(null);
118
+ }
119
+ }
120
+ })
121
+ }
122
+ if (c < l) process();
123
+ }
124
+
125
+ var fs2 = {
126
+ 'path_parent': function (strPath) {
127
+ var dirSep = '/';
128
+ //console.log('strPath', strPath);
129
+ var pos1 = strPath.lastIndexOf(dirSep);
130
+ if (pos1 > -1) {
131
+ var beginning = strPath.substr(0, pos1);
132
+ //console.log('beginning ' + beginning);
133
+ return beginning;
134
+ }
135
+ },
136
+ 'path_last_part': function (strPath) {
137
+ // the last part is not necessarily a file name, it may be.
138
+ var dirSep = '/';
139
+ var pos1 = strPath.lastIndexOf(dirSep);
140
+ if (pos1 > -1) {
141
+ var theRest = strPath.substr(pos1 + 1);
142
+ //console.log('theRest ' + theRest);
143
+ return theRest;
144
+ } else {
145
+ return strPath;
146
+ }
147
+ },
148
+
149
+
150
+
151
+
152
+
153
+ // depth first walk?
154
+ // The contents could be deleted when deleting files.
155
+
156
+ // Could have a callback for the directory itself, and only later go into the contents.
157
+
158
+ // Recursive delete could have a function return whether to delete it or not, and use rimraf to
159
+ // carry out the deletion.
160
+
161
+
162
+ // Getting all directory names may be useful.
163
+ // Getting the whole file tree.
164
+
165
+
166
+ // Get all directory names
167
+ //
168
+
169
+ 'recursive_dir_names': function (start_path, callback) {
170
+ var arr_dir_names = [];
171
+ fs2.walk(start_path, function (dir_path, dir_contents) {
172
+ arr_dir_names.push(dir_path);
173
+ }, function (err, res_all) {
174
+ if (err) {
175
+ callback(err);
176
+
177
+ } else {
178
+ callback(null, arr_dir_names);
179
+ }
180
+ })
181
+ },
182
+
183
+ 'recursive_dir_delete': function (start_path, fn_check, callback) {
184
+ var arr_dir_names = [];
185
+ // Walk, but wait until callback of inner function
186
+ // walk, async inner.
187
+
188
+ fs2.walk_async_inner(start_path, function (dir_path, dir_contents, cb) {
189
+ //arr_dir_names.push(dir_path);
190
+ var to_delete = fn_check(dir_path);
191
+ if (to_delete) {
192
+ fs2.delete(dir_path, cb);
193
+ cb(null, true);
194
+
195
+ } else {
196
+ cb(null, false);
197
+ }
198
+
199
+ }, function (err, res_all) {
200
+ if (err) {
201
+ callback(err);
202
+
203
+ } else {
204
+ callback(null, arr_dir_names);
205
+ }
206
+ })
207
+
208
+ },
209
+
210
+
211
+
212
+
213
+ // dir_svg_dirs_to_png_dirs
214
+ // creates the png directories according to output format.
215
+ // could output to multiple formats as well.
216
+
217
+ // With an asyncronous inner function, where it then checks to see if the directory still exists...?
218
+
219
+ 'walk_async_inner': function (start_path, dir_callback, callback) {
220
+ // May also need to know how many to do asymcronously at once.
221
+ // may be recursive inside... that could be easier.
222
+ // think this does need a callback for call_multi to work right.
223
+ console.log('walk start_path', start_path);
224
+ var rec = function (path, rcb) {
225
+ //console.log('rec path ' + path);
226
+ // read the contents from that path.
227
+ fs2.dir_contents(path, function (err, contents) {
228
+ if (err) {
229
+ callback(err);
230
+ } else {
231
+ //console.log('contents ' + stringify(contents));
232
+
233
+ // What about an async callback function, possibly where it deletes that directory?
234
+
235
+
236
+ dir_callback(path, contents, function (err, res) {
237
+ if (err) {
238
+ //callback(err)
239
+ } else {
240
+ fs2.exists(path, function (err, exists) {
241
+ if (exists) {
242
+ fs2.dir_contents(path, function (err, contents) {
243
+ if (err) {
244
+ callback(err);
245
+ } else {
246
+
247
+ if (contents.directories) {
248
+ // will use call_multi
249
+ var fns = [];
250
+
251
+ //console.log('contents.directories.length', contents.directories.length);
252
+ each(contents.directories, function (directory, i) {
253
+ //console.log('directory ' + stringify(directory));
254
+
255
+ var dirPath = path + '/' + directory;
256
+ //log('dirPath ' + dirPath);
257
+ fns.push([rec, [dirPath]]);
258
+ });
259
+ call_multi(1, fns, function (err, res) {
260
+ if (err) {
261
+ //log('call_multi err ' + err);
262
+ throw err;
263
+ } else {
264
+ //log('call multi cb');
265
+ rcb();
266
+ }
267
+ })
268
+ } else {
269
+ rcb();
270
+ }
271
+
272
+ }
273
+ });
274
+ }
275
+ })
276
+ }
277
+ });
278
+ // have the directory callback with all the contents here.
279
+ // however, need to go through each of the directories, processing them.
280
+ // don't want too much code branching.
281
+
282
+
283
+
284
+
285
+ }
286
+ })
287
+ };
288
+ rec(start_path, callback);
289
+ },
290
+
291
+ 'walk': function (start_path, dir_callback, callback) {
292
+ // May also need to know how many to do asymcronously at once.
293
+ // may be recursive inside... that could be easier.
294
+ // think this does need a callback for call_multi to work right.
295
+ console.log('walk start_path', start_path);
296
+ var rec = function (path, rcb) {
297
+ //console.log('rec path ' + path);
298
+ // read the contents from that path.
299
+ fs2.dir_contents(path, function (err, contents) {
300
+ if (err) {
301
+ callback(err);
302
+ } else {
303
+ //console.log('contents ' + stringify(contents));
304
+
305
+ // What about an async callback function, possibly where it deletes that directory?
306
+
307
+
308
+ dir_callback(path, contents);
309
+ // have the directory callback with all the contents here.
310
+ // however, need to go through each of the directories, processing them.
311
+ // don't want too much code branching.
312
+
313
+ if (contents.directories) {
314
+ // will use call_multi
315
+ var fns = [];
316
+
317
+ //console.log('contents.directories.length', contents.directories.length);
318
+ each(contents.directories, function (directory, i) {
319
+ //console.log('directory ' + stringify(directory));
320
+
321
+ var dirPath = path + '/' + directory;
322
+ //log('dirPath ' + dirPath);
323
+ fns.push([rec, [dirPath]]);
324
+ });
325
+ call_multi(fns, function (err, res) {
326
+ if (err) {
327
+ //log('call_multi err ' + err);
328
+ throw err;
329
+ } else {
330
+ //log('call multi cb');
331
+ rcb();
332
+ }
333
+ })
334
+ } else {
335
+ rcb();
336
+ }
337
+
338
+
339
+ }
340
+ })
341
+ };
342
+ rec(start_path, callback);
343
+ },
344
+ 'exists': function (path, callback) {
345
+ fs.exists(path, function (res) {
346
+ callback(null, res);
347
+ })
348
+ },
349
+ // want to save a binary file as well.
350
+
351
+ // But loading binary gets more complicated as we need to know the format in many cases, so will have specific functions
352
+ // to load typed arrays.
353
+ // Seems to work OK.
354
+ // Will also want to load binary files.
355
+ 'save_binary': function (file_path, file_content, callback) {
356
+ // the file content could be a typed array.
357
+ // just try to create a buffer out of it.
358
+ //console.log('save_binary ' + file_path);
359
+
360
+ if (file_content.buffer.byteLength) {
361
+ // its a typed array
362
+ console.log('file_content.length', file_content.length);
363
+ var buf = Buffer.from(file_content.buffer);
364
+ // but does it calculate the buffer length correctly?
365
+ console.log('buf.length', buf.length);
366
+
367
+ fs.open(file_path, "w", function (err, fd) {
368
+ if (err) {
369
+ callback(err);
370
+ } else {
371
+
372
+ //console.log('file opened');
373
+ fs.write(fd, buf, 0, buf.length, function (err, res_write) {
374
+ if (err) {
375
+ console.log('err', err);
376
+ callback(err);
377
+ } else {
378
+ //console.log('file written');
379
+ fs.close(fd);
380
+ //console.log('written to file_path ' + file_path);
381
+ callback(null, file_path);
382
+ }
383
+ })
384
+ }
385
+ });
386
+ }
387
+ // But does the buf have a bytelength
388
+ },
389
+ // could put in filter objects...
390
+ // so the text begins with something, has an extension, file size
391
+ // plain mapify to use here I think.
392
+ // may need to modify mapify to support callback functions like arrayify.
393
+ // Can save a whole bunch of files as strings.
394
+ 'save_file_as_string': mapify(fp(function (a, sig) {
395
+ //console.log('save_file_as_string sig ' + sig);
396
+ // and could JSON stringify an object.
397
+ if (sig == '[s,o,f]' || sig == '[s,a,f]') {
398
+ var file_path = a[0];
399
+ var file_content = JSON.stringify(a[1]);
400
+ var callback = a[2];
401
+ return this.save_file_as_string(file_path, file_content, callback);
402
+ }
403
+
404
+ if (sig == '[s,s,f]') {
405
+ var file_path = a[0];
406
+ var file_content = a[1];
407
+ var callback = a[2];
408
+ //console.log('pre write file file_path', file_path);
409
+ fs.writeFile(file_path, file_content, function (err) {
410
+ if (err) {
411
+ //console.log(err);
412
+ callback(err);
413
+ } else {
414
+ //console.log("The file was saved!");
415
+ callback(null, true);
416
+ // could return the file path?
417
+ // returning timing info would be cool as well.
418
+ // could maybe make a function that keeps track of it as a function is executed.
419
+ }
420
+ });
421
+ };
422
+ })),
423
+
424
+ 'process_file_as_string': function (file_path, fnProcess, callback) {
425
+ fs2.load_file_as_string(file_path, function (err, str_file) {
426
+ if (err) {
427
+ callback(err);
428
+ } else {
429
+ fs2.save_file_as_string(file_path, fnProcess(str_file), callback);
430
+ }
431
+ });
432
+ },
433
+ // Loading a file as a Uint8 Typed array will become more important.
434
+ // Will be using them rather than buffers in many cases.
435
+ // Will be easier to interface with C++ code.
436
+ // Probably not needed - as buffer is a Uint8Array.
437
+ // May be easier to carry out operations on a Uint8Array in general though.
438
+ // Also want to be able to load a file as a buffer.
439
+
440
+ 'load_file_as_buffer': fp(function (a, sig) {
441
+ //source_path, callback
442
+ // should work as an array...
443
+ // so when you give it an array of source paths, it loads them all, and returns the result as an array by default.
444
+ // can return a map if asked to... would be easier to access in many cases, but problems when there are repeated params.
445
+ // I think return map by default.
446
+ // Arrayify input, mapify output.
447
+ // could use arrayify here possibly...
448
+ // could have a concurrency_limit argument.
449
+ // would be useful to incorporate that into a lot of code as an option.
450
+
451
+ var source_path, concurrency_limit = 4,
452
+ callback;
453
+ // console.log('load_file_as_string sig ' + sig);
454
+
455
+ if (sig == '[a,n,f]') {
456
+ source_path = a[0];
457
+ concurrency_limit = a[1];
458
+ callback = a[2];
459
+ }
460
+ if (sig == '[s,n,f]') {
461
+ source_path = a[0];
462
+ concurrency_limit = a[1];
463
+ callback = a[2];
464
+ }
465
+ if (sig == '[a,f]') {
466
+ source_path = a[0];
467
+ callback = a[1];
468
+ }
469
+ if (sig == '[s,f]') {
470
+ source_path = a[0];
471
+ callback = a[1];
472
+ }
473
+
474
+ if (tof(source_path) == 'string') {
475
+ fs.readFile(source_path, function (err, data_buffer) {
476
+ if (err) {
477
+ //console.log('error reading file at ' + source_path);
478
+ //var stack = new Error().stack;
479
+ // callback with the error.
480
+ //console.log(stack);
481
+ //throw err;
482
+ callback(err);
483
+ } else {
484
+ callback(null, data_buffer);
485
+ }
486
+ //console.log('OK: ' + filename);
487
+ //console.log(data)
488
+ });
489
+
490
+ } else if (tof(source_path) == 'array') {
491
+ var res = {};
492
+ var fns = [];
493
+ each(source_path, function (i, source_path_item) {
494
+ fns.push([fs2.load_file_as_buffer, [source_path_item], function (err, res_loaded) {
495
+ if (err) throw err;
496
+ res[source_path_item] = res_loaded;
497
+ }]);
498
+ });
499
+ call_multi(fns, function (err, res_multi) {
500
+ if (err) throw err;
501
+ callback(null, res);
502
+ });
503
+ }
504
+ //fs.readFile(filename, 'utf8', function(err, data_buffer) {
505
+ }),
506
+
507
+ 'load_json_as_object': function (path, callback) {
508
+ this.load_file_as_string(path, function (err, str_file) {
509
+ if (err) {
510
+ callback(err);
511
+ } else {
512
+ // try/catch?
513
+ //return JSON.parse(str_file);
514
+
515
+ callback(null, JSON.parse(str_file));
516
+ }
517
+ });
518
+ },
519
+
520
+ 'load_file_as_string': fp(function (a, sig) {
521
+ //source_path, callback
522
+
523
+ // should work as an array...
524
+ // so when you give it an array of source paths, it loads them all, and returns the result as an array by default.
525
+ // can return a map if asked to... would be easier to access in many cases, but problems when there are repeated params.
526
+ // I think return map by default.
527
+ // Arrayify input, mapify output.
528
+
529
+ // could use arrayify here possibly...
530
+
531
+ // could have a concurrency_limit argument.
532
+ // would be useful to incorporate that into a lot of code as an option.
533
+
534
+ var source_path, concurrency_limit = 4,
535
+ callback;
536
+
537
+ //console.log('load_file_as_string sig ' + sig);
538
+
539
+ if (sig == '[a,n,f]') {
540
+ source_path = a[0];
541
+ concurrency_limit = a[1];
542
+ callback = a[2];
543
+ }
544
+ if (sig == '[s,n,f]') {
545
+ source_path = a[0];
546
+ concurrency_limit = a[1];
547
+ callback = a[2];
548
+ }
549
+ if (sig == '[a,f]') {
550
+ source_path = a[0];
551
+ callback = a[1];
552
+ }
553
+ if (sig == '[s,f]') {
554
+ source_path = a[0];
555
+ callback = a[1];
556
+ }
557
+
558
+ if (tof(source_path) == 'string') {
559
+ fs.readFile(source_path, function (err, data_buffer) {
560
+ if (err) {
561
+ callback(err);
562
+ } else {
563
+ callback(null, data_buffer.toString());
564
+ }
565
+ //console.log('OK: ' + filename);
566
+ //console.log(data)
567
+ });
568
+
569
+ } else if (tof(source_path) == 'array') {
570
+ var res = {};
571
+ var fns = [];
572
+ each(source_path, function (source_path_item) {
573
+ fns.push([fs2.load_file_as_string, [source_path_item], function (err, res_loaded) {
574
+ if (err) throw err;
575
+
576
+ res[source_path_item] = res_loaded;
577
+
578
+ }]);
579
+ });
580
+ call_multi(fns, function (err, res_multi) {
581
+ if (err) throw err;
582
+ callback(null, res);
583
+ });
584
+ }
585
+
586
+ //fs.readFile(filename, 'utf8', function(err, data_buffer) {
587
+
588
+ }),
589
+
590
+ 'dir_dirs_beginning': function (dir_path, beginning_text, callback) {
591
+ //console.log('dir_path ' + dir_path);
592
+ //console.log('dir_path ' + tof(dir_path));
593
+
594
+ // dir_contents has been arrayified, need to make sure it still works.
595
+ //console.log('pre dir_contents');
596
+ fs2.dir_contents(dir_path, function (err, dir_contents) {
597
+ if (err) {
598
+ throw err;
599
+ } else {
600
+ var directories = dir_contents.directories;
601
+ var target_directories = [];
602
+ each(directories, function (i, v) {
603
+ if (v.substr(0, beginning_text.length) == beginning_text) target_directories.push(v);
604
+ });
605
+ callback(null, target_directories);
606
+ }
607
+ })
608
+ },
609
+
610
+ 'ensure_directory_exists': function (dir_path, callback) {
611
+ fs.exists(dir_path, function (exists) {
612
+ if (exists) {
613
+ callback(null, true);
614
+ } else {
615
+ // Maybe go backwards recursively and make sure parents exist.
616
+ fs.mkdir(dir_path, function (err) {
617
+ if (err) {
618
+ console.trace();
619
+ console.log('dir_path', dir_path);
620
+ throw (err);
621
+ } else {
622
+ callback(null, true);
623
+ }
624
+ })
625
+ }
626
+ })
627
+ },
628
+
629
+ // could use an arrayify function for functions with callbacks.
630
+ 'dir_ensure': function (dir_path, callback) {
631
+ if (tof(dir_path) == 'array') {
632
+ var fns = [];
633
+ each(dir_path, function (i, v) {
634
+ fns.push([fs2.dir_ensure, [v]]);
635
+ });
636
+ call_multiple_callback_functions(fns, callback)
637
+ } else {
638
+ fs.exists(dir_path, function (exists) {
639
+ if (exists) {
640
+ callback(null, dir_path);
641
+ } else {
642
+ fs.mkdir(dir_path, function (err, res) {
643
+ if (err) {
644
+ throw err;
645
+ } else {
646
+ callback(null, dir_path);
647
+ }
648
+ })
649
+ }
650
+ });
651
+ }
652
+ },
653
+
654
+ // dir_ensure_named_numbered
655
+
656
+ 'dir_ensure_named_numbered': function (parentPath, name, callback) {
657
+ // get the list of directories in the parent, make a map.
658
+ this.dir_dirs_beginning(parentPath, name, function (err, resDirsBeginning) {
659
+ if (err) {
660
+ callback(err);
661
+ } else {
662
+ //console.log('resDirsBeginning ' + stringify(resDirsBeginning));
663
+ var map_dirs_beginning = {};
664
+ each(resDirsBeginning, function (i, v) {
665
+ map_dirs_beginning[v] = true;
666
+ });
667
+ //console.log('map_dirs_beginning ' + stringify(map_dirs_beginning));
668
+
669
+ // then loop to generate the name
670
+ var c = 0,
671
+ genName = name + '_' + c;
672
+ while (map_dirs_beginning[genName]) {
673
+ c++;
674
+ genName = name + '_' + c;
675
+ }
676
+ // then we create the directory.
677
+
678
+ var dirPath = parentPath + '/' + genName;
679
+ //console.log('dirPath ' + dirPath);
680
+ fs2.dir_ensure(dirPath, callback);
681
+ }
682
+ })
683
+
684
+ },
685
+
686
+ // likely to use an extension filer on dir_contents?
687
+ // that way could also do a traversal_depth, so it looks in subdirectories
688
+
689
+
690
+ 'dir_files_by_extension': fp(function (a, sig) {
691
+ var path = a[0],
692
+ extension = a[1],
693
+ include_metadata = false,
694
+ callback;
695
+ if (a.l == 3) {
696
+ callback = a[2];
697
+ }
698
+ if (a.l == 4) {
699
+ include_metadata = a[2];
700
+ callback = a[3];
701
+ }
702
+ var contents_cb = function (err, dir_contents) {
703
+ if (err) {
704
+
705
+ } else {
706
+ //console.log('dir_contents ' + stringify(dir_contents));
707
+
708
+ var res = [];
709
+ each(dir_contents.files, function (i, v) {
710
+ //console.log('v ' + stringify(v));
711
+
712
+ var file_name;
713
+
714
+ if (tof(v) == 'array') {
715
+ file_name = v[0];
716
+ }
717
+ if (tof(v) == 'string') {
718
+ file_name = v[1];
719
+ }
720
+
721
+ var file_extension = node_path.extname(file_name);
722
+ if (extension == file_extension) {
723
+
724
+
725
+ res.push(v);
726
+ }
727
+
728
+ })
729
+ //return res;
730
+ //console.log('res ' + res);
731
+ callback(null, res);
732
+ }
733
+ };
734
+ if (include_metadata) {
735
+ fs2.dir_contents(path, include_metadata, contents_cb);
736
+ } else {
737
+
738
+ fs2.dir_contents(path, contents_cb);
739
+ }
740
+ }),
741
+
742
+ // option include_metadata?
743
+ // can include an extension filter.
744
+
745
+ // dir_dirs?
746
+
747
+ // and have this arrayified on param 0?
748
+ // we may then want to get the contents of a bunch of dirs.
749
+
750
+ 'dir_dirs': fp(function (a, sig) {
751
+ // can still apply to multiple dirs.
752
+ // source_dir, callback
753
+
754
+ var source_dir, callback;
755
+
756
+ //console.log('dir_dirs sig ' + sig);
757
+ if (sig == '[s,f]') {
758
+ source_dir = a[0];
759
+ callback = a[1];
760
+ this.dir_contents(source_dir, {
761
+ 'files_or_directories': 'directories'
762
+ }, callback);
763
+ }
764
+ if (sig == '[s,o,f]') {
765
+ source_dir = a[0];
766
+ options = a[1];
767
+ callback = a[2];
768
+ options.files_or_directories = 'directories';
769
+ this.dir_contents(source_dir, options, callback);
770
+ }
771
+ // but do want this to allow a filter as well.
772
+ }),
773
+
774
+ // want to be able to load the file contents too.
775
+
776
+ // could have this get directory contents recursively to a path... or maybe use the specialised function for that.
777
+ 'dir_contents': arrayify(0, fp(function (a, sig) {
778
+ // path, callback
779
+
780
+ var path = a[0],
781
+ filter, include_metadata = false,
782
+ include_file_contents = false,
783
+ callback, t_filter;
784
+ var fs_paths = false;
785
+ // with an extension filter...
786
+
787
+ var extension_filter;
788
+ var regex_filter;
789
+ var res_format = 'array';
790
+ //console.log('dir_contents sig ' + sig);
791
+ // may want to specify options object.
792
+ // may want to load the directories, that could be specified as an option.
793
+ var files_or_directories;
794
+ if (a.l == 2) {
795
+ // [s,f]
796
+ callback = a[1];
797
+ }
798
+ if (a.l == 3) {
799
+
800
+ // [s,s,f]
801
+ // it has an extension filter.
802
+
803
+ if (sig == '[s,s,f]') {
804
+ filter = a[1];
805
+ extension_filter = filter;
806
+ t_filter = 'extension';
807
+ callback = a[2];
808
+ var options = {};
809
+ options.files_or_directories = 'files';
810
+ }
811
+
812
+ // [s,b,f]
813
+
814
+ // [s,r,f]
815
+
816
+ // [s,o,f]
817
+ // can have an options object there.
818
+ // another option can be files_or_directories??? better name?
819
+
820
+ if (sig == '[s,o,f]') {
821
+ //include_metadata = a[1];
822
+ var options = a[1];
823
+ if (options.include_metadata) include_metadata = options.include_metadata;
824
+ if (options.files_or_directories) files_or_directories = options.files_or_directories;
825
+ if (options.include_file_contents) include_file_contents = options.include_file_contents;
826
+ if (options.res_format) res_format = options.res_format;
827
+
828
+ if (options.filter) {
829
+ filter = options.filter;
830
+ t_filter = tof(filter);
831
+
832
+ // then if t_filter is 'object', there will be more filter properties.
833
+
834
+ if (t_filter == 'object') {
835
+ if (filter.extension) {
836
+ //filter = filter.extension;
837
+ //t_filter = 'extension';
838
+ extension_filter = filter.extension;
839
+
840
+ }
841
+ if (filter.regex) {
842
+ //filter = filter.extension;
843
+ //t_filter = 'extension';
844
+ regex_filter = filter.regex;
845
+
846
+ }
847
+ }
848
+ }
849
+ if (options.fs_paths) {
850
+ fs_paths = options.fs_paths;
851
+ //throw 'stop';
852
+ }
853
+ callback = a[2];
854
+ //console.log('sof');
855
+ }
856
+
857
+ if (sig == '[s,b,f]') {
858
+ include_metadata = a[1];
859
+ callback = a[2];
860
+ }
861
+ if (sig == '[s,r,f]') {
862
+ filter = a[1];
863
+ t_filter = 'regex';
864
+ regex_filter = filter;
865
+ callback = a[2];
866
+ }
867
+
868
+
869
+
870
+ // regex being the filter
871
+ }
872
+ if (a.l == 4) {
873
+ if (sig == '[s,s,b,f]') {
874
+ filter = a[1];
875
+ t_filter = 'extension';
876
+ include_metadata = a[2];
877
+ callback = a[3];
878
+ }
879
+ if (sig == '[s,s,o,f]') {
880
+ filter = a[1];
881
+ t_filter = 'extension';
882
+ extension_filter = filter;
883
+
884
+ //include_metadata = a[2];
885
+ var options = a[2];
886
+ if (options.metadata) {
887
+ include_metadata = options.metadata;
888
+ }
889
+ if (options.include_metadata) {
890
+ include_metadata = options.include_metadata;
891
+ }
892
+ if (options.fs_paths) {
893
+ fs_paths = options.fs_paths;
894
+ //throw 'stop';
895
+ }
896
+ if (options.files_or_directories) files_or_directories = options.files_or_directories;
897
+ if (options.include_file_contents) include_file_contents = options.include_file_contents;
898
+ if (options.res_format) res_format = options.res_format;
899
+
900
+
901
+ callback = a[3];
902
+ }
903
+ }
904
+
905
+ // ssbff?
906
+ //console.log ('!callback ' + tof(callback));
907
+ //path = path.replace(/\//g, '\\');
908
+ //console.log('dir_contents path ' + path);
909
+
910
+ //console.log(fs.existsSync(path));
911
+
912
+ // readdir working on a bunch of paths automatically?
913
+ // or have this function arrayified?
914
+ //console.log('pre fs.readdir');
915
+ //throw 'stop';
916
+ fs.readdir(path, function (err, files) {
917
+ if (err) {
918
+ //console.log('err ' + err);
919
+ var stack = new Error().stack;
920
+ console.log(stack);
921
+ throw ('err ' + err);
922
+ } else {
923
+
924
+ //console.log('files ' + stringify(files));
925
+ //console.log('typeof files ' + stringify(typeof files));
926
+ //console.log('dir_contents path ' + path);
927
+ var res = {};
928
+ var res_files = [];
929
+ var res_directories = [];
930
+ var c = files.length;
931
+ //console.log('c ' + c);
932
+ //console.log ('!2callback ' + tof(callback));
933
+ var cb = function () {
934
+ //console.log('cb ');
935
+ //console.log('files_or_directories', files_or_directories);
936
+ if (files_or_directories == 'files') {
937
+ callback(null, res_files);
938
+ } else if (files_or_directories == 'directories') {
939
+ callback(null, res_directories);
940
+ } else {
941
+
942
+ if (res_files.length > 0) {
943
+ res.files = res_files;
944
+ }
945
+ if (res_directories.length > 0) {
946
+ res.directories = res_directories;
947
+ }
948
+ //return res;
949
+ //console.log('res ' + stringify(res));
950
+ //console.log('tof callback ' + tof(callback));
951
+ //console.log('callback ' + stringify(callback));
952
+ callback(null, res);
953
+ }
954
+
955
+ }
956
+
957
+ // maybe this could be done sequentially, perhaps doing n at once.
958
+ // limit the simultaneous lookups.
959
+
960
+ // want to do sequential function calls, waiting for the callback on each.
961
+ // putting the result callback into the result, but calling it with different items.
962
+
963
+ if (!files || files.length == 0) {
964
+ cb();
965
+ }
966
+
967
+ //console.log('files.length', files.length);
968
+
969
+ //console.log('files', files);
970
+
971
+
972
+
973
+ each(files, function (v, i) {
974
+ var file_name = v;
975
+ //console.log('file_name', file_name);
976
+ var file_or_dir_full_path;
977
+
978
+ if (path.substr(path.length - 1) == '/') {
979
+ file_or_dir_full_path = path + v;
980
+ } else {
981
+ file_or_dir_full_path = path + dir_separator + v;
982
+ }
983
+
984
+
985
+
986
+ //console.log('file_or_dir_full_path ' + stringify(file_or_dir_full_path));
987
+
988
+ //console.log('i ' + stringify(i));
989
+ //console.log('v ' + stringify(v));
990
+ // find out if it is a directory.
991
+
992
+ // depending on the name and filter, do the next step.
993
+ var proceed = true;
994
+
995
+ //console.log('extension_filter ' + extension_filter);
996
+ //console.log('regex_filter ' + regex_filter);
997
+
998
+ if (extension_filter) {
999
+ var ext = node_path.extname(file_name);
1000
+ //console.log('ext ' + ext);
1001
+ proceed = ext == extension_filter;
1002
+ }
1003
+ if (proceed && regex_filter) {
1004
+ //console.log('file_name ' + file_name);
1005
+ proceed = regex_filter.test(file_name);
1006
+ }
1007
+ //console.log('proceed', proceed);
1008
+
1009
+
1010
+ if (proceed) {
1011
+
1012
+ fs.stat(file_or_dir_full_path, function (err, stats) {
1013
+ //console.log('stats', stats);
1014
+
1015
+ if (err) {
1016
+
1017
+
1018
+
1019
+ //console.log('stats unavailable for ' + file_or_dir_full_path);
1020
+
1021
+ var item_res = file_name;
1022
+ res_files.push(item_res);
1023
+
1024
+ // Probably don't fail whole thing with error...
1025
+
1026
+ c--;
1027
+ //console.log('c', c);
1028
+ if (c == 0) {
1029
+ cb();
1030
+ }
1031
+
1032
+ //throw(err);
1033
+
1034
+ } else {
1035
+ //console.log('stats.isDirectory() ' + stringify(stats.isDirectory()));
1036
+
1037
+ var is_dir = stats.isDirectory();
1038
+
1039
+ // not a dir anyway???
1040
+ if (is_dir && files_or_directories != 'files') {
1041
+ if (fs_paths) {
1042
+ res_directories.push(file_or_dir_full_path);
1043
+ } else {
1044
+ res_directories.push(v);
1045
+ }
1046
+
1047
+ c--;
1048
+ //console.log('c', c);
1049
+ if (c == 0) {
1050
+ cb();
1051
+ }
1052
+ } else if (files_or_directories != 'directories') {
1053
+
1054
+ // can load the whole file as string if asked to do so.
1055
+ // options.load_file == 'string'.
1056
+ // if including the file contents... load it as a string.
1057
+ // if including both the metadata and the content...
1058
+ // could load them both at once.
1059
+ // would like the Fns() system with .go rather than using call_multi.
1060
+ // it can load the required data... calling a function that loads the metadata as well as a function that loads the file.
1061
+ // when there are multiple file calls, the results should arrive in an array I think.
1062
+ // fns.go seems like it would be very useful indeed.
1063
+ var fns = Fns();
1064
+ // and in the results we may need to include the full paths.
1065
+ // that could be an option in the metadata function.
1066
+ //fns.push([]);
1067
+ if (include_metadata) {
1068
+ fns.push([fs2.metadata, [file_or_dir_full_path]]);
1069
+ // could become fns.push(fs2.metadata, file_or_dir_full_path);
1070
+ }
1071
+ if (include_file_contents) {
1072
+ fns.push([fs2.load_file_as_string, [file_or_dir_full_path]]);
1073
+ }
1074
+ //console.log('fns.length ' + fns.length);
1075
+ if (fns.length > 0) {
1076
+ fns.go(function (err, fns_res) {
1077
+ if (err) {
1078
+ throw err;
1079
+ } else {
1080
+ //console.log('fns_res ' + stringify(fns_res));
1081
+ //console.log('tof(fns_res) ' + tof(fns_res));
1082
+ // we may need to return the fs paths with the data...
1083
+ // path, content, metadata
1084
+ if (include_metadata && include_file_contents) {
1085
+ var metadata = fns_res[0];
1086
+ var file_contents = fns_res[1];
1087
+ if (res_format == 'array') {
1088
+ //var res
1089
+ var item_res = [file_or_dir_full_path, metadata, file_contents];
1090
+ res_files.push(item_res);
1091
+ } else if (res_format == 'map') {
1092
+ var item_res = {
1093
+ //'path': file_or_dir_full_path,
1094
+ 'name': file_name,
1095
+ 'metadata': metadata,
1096
+ 'contents': file_contents
1097
+ }
1098
+ if (fs_paths) {
1099
+ item_res.path = file_or_dir_full_path;
1100
+ }
1101
+ res_files.push(item_res);
1102
+ }
1103
+ } else if (include_metadata) {
1104
+ var metadata = fns_res[0];
1105
+ if (res_format == 'array') {
1106
+ var item_res = [file_or_dir_full_path, metadata];
1107
+ res_files.push(item_res);
1108
+ } else if (res_format == 'map') {
1109
+ var item_res = {
1110
+ //'path': file_or_dir_full_path,
1111
+ 'name': file_name,
1112
+ 'metadata': metadata
1113
+ }
1114
+ if (fs_paths) {
1115
+ item_res.path = file_or_dir_full_path;
1116
+ }
1117
+ res_files.push(item_res);
1118
+ }
1119
+ } else if (include_file_contents) {
1120
+ var file_contents = fn_res[0];
1121
+
1122
+ if (res_format == 'array') {
1123
+ if (fs_paths) {
1124
+ var item_res = [file_or_dir_full_path, file_contents];
1125
+ } else {
1126
+ var item_res = [file_name, file_contents];
1127
+ }
1128
+
1129
+
1130
+ res_files.push(item_res);
1131
+ } else if (res_format == 'map') {
1132
+ var item_res = {
1133
+ //'path': file_or_dir_full_path,
1134
+ 'name': file_name,
1135
+ 'contents': file_contents
1136
+ }
1137
+ if (fs_paths) {
1138
+ item_res.path = file_or_dir_full_path;
1139
+ }
1140
+ res_files.push(item_res);
1141
+ }
1142
+ } else {
1143
+ // no results in the callback anyway.
1144
+ if (fs_paths) {
1145
+ var item_res = file_or_dir_full_path;
1146
+ } else {
1147
+ var item_res = file_name;
1148
+ }
1149
+ res_files.push(item_res);
1150
+ //throw 'not yet implemented';
1151
+ }
1152
+ c--;
1153
+ //console.log('c', c);
1154
+ if (c == 0) {
1155
+ cb();
1156
+ }
1157
+ //throw 'stop';
1158
+ }
1159
+ })
1160
+ } else {
1161
+ res_files.push(file_name);
1162
+ c--;
1163
+ //console.log('c', c);
1164
+ if (c == 0) {
1165
+ cb();
1166
+ }
1167
+ }
1168
+
1169
+
1170
+ } else {
1171
+ c--;
1172
+ //console.log('c', c);
1173
+ if (c == 0) {
1174
+ cb();
1175
+ }
1176
+ //throw 'stop';
1177
+ }
1178
+
1179
+ }
1180
+ })
1181
+
1182
+
1183
+
1184
+ } else {
1185
+ c--;
1186
+ //console.log('c', c);
1187
+ if (c == 0) {
1188
+ cb();
1189
+ }
1190
+ }
1191
+
1192
+ })
1193
+ }
1194
+ })
1195
+ })),
1196
+ // metadata... will make a (mime) type assumption based on the extension.
1197
+ // may then read further metadata, possibly verify the file, metadata verification is one thing,
1198
+ // has_metadata.
1199
+ // There could be further file validation.
1200
+ //
1201
+
1202
+ // could possibly use arrayify, but arrayify that has been handled to work with callback functions.
1203
+ // maybe call file_metadata.
1204
+
1205
+ // possibly keep in the core... but it would look into a variety of file formats.
1206
+ // possibly have a core version that gets data such as last modified and file size.
1207
+ 'metadata': function (path, callback) {
1208
+ // this may have options, like including the path in the results?
1209
+ // calling metadata on a directory...
1210
+ // should this get the metadata for files in the dir?
1211
+ // mainly for file metadata.
1212
+ // check to see if it exists.
1213
+ //console.log('metadata path ' + path);
1214
+ fs.exists(path, function (exists) {
1215
+ if (!exists) {
1216
+ //console.log('file does not exist ' + path);
1217
+ //throw('file not found');
1218
+ callback(null, false);
1219
+ } else {
1220
+ //var pos1 = path.lastIndexOf()
1221
+ // just get the node.js file stats first.
1222
+ fs.stat(path, function (err, stats) {
1223
+ var extname = node_path.extname(path);
1224
+ var basename = node_path.basename(path);
1225
+ //console.log('extname ' + extname);
1226
+ var extname2 = extname.substring(1);
1227
+ var res = {
1228
+ 'size': stats.size,
1229
+ 'atime': stats.atime,
1230
+ 'mtime': stats.mtime,
1231
+ 'ctime': stats.ctime,
1232
+ 'isDirectory': stats.isDirectory()
1233
+ };
1234
+ // atime, mtime, ctime
1235
+ callback(null, [basename, res]);
1236
+ });
1237
+ }
1238
+ });
1239
+ },
1240
+ // copy a file as well.
1241
+ // This could be arrayified? But it would need parameter pairs?
1242
+
1243
+ 'copy_file': function (source_path, dest_path, callback) {
1244
+ //console.log('source_path ' + source_path);
1245
+ //console.log('dest_path ' + dest_path);
1246
+
1247
+ var r = fs.createReadStream(source_path).pipe(fs.createWriteStream(dest_path));
1248
+
1249
+ r.on('close', function () {
1250
+ //if (err) throw err;
1251
+ //throw 'stop';
1252
+ callback(null, true);
1253
+ });
1254
+ },
1255
+
1256
+ 'instruct': fp(function (a, sig) {
1257
+ // if it is just an array, and a callback...
1258
+ //console.log('instruct sig ' + sig);
1259
+ var is_multi_callback = false;
1260
+
1261
+ if (a.l == 2) {
1262
+ if (tof(a[0]) == 'array' && tof(a[1]) == 'function') {
1263
+ // a bunch of instructions to execute, and then a callback.
1264
+ var fns = [];
1265
+ var instructions = a[0];
1266
+ var callback = a[1];
1267
+ is_multi_callback = true;
1268
+
1269
+ each(instructions, function (i, instruction) {
1270
+ fns.push([fs2.instruct, instruction])
1271
+ })
1272
+
1273
+ call_multiple_callback_functions(fns, function (err, res_multi) {
1274
+ if (err) {
1275
+ throw err;
1276
+ } else {
1277
+ callback(null, res_multi);
1278
+ }
1279
+ })
1280
+ }
1281
+ }
1282
+
1283
+ if (!is_multi_callback) {
1284
+ // then check to see if the last one is a callback.
1285
+ // the ones before it will be parameters of various kinds.
1286
+ // if first is string, last is function.
1287
+
1288
+ var last_arg = a[a.l - 1];
1289
+ //console.log('tof(last_arg) ' + tof(last_arg));
1290
+
1291
+ if (tof(a[0]) == 'string' && tof(last_arg) == 'function') {
1292
+ var command_name = a[0];
1293
+ var callback = last_arg;
1294
+
1295
+ // but basically want to call the right function with the params.
1296
+
1297
+ var new_args = a.slice(1);
1298
+
1299
+ if (command_name == 'copy') {
1300
+ fs2.copy.apply(this, new_args);
1301
+ }
1302
+ }
1303
+ }
1304
+ }),
1305
+
1306
+ 'process_copy': function (source_path, fn_process, dest_path, callback) {
1307
+ fs2.load_file_as_string(source_path, function (err, strFile) {
1308
+ if (err) {
1309
+ callback(err);
1310
+ } else {
1311
+ strFile = fn_process(str_file);
1312
+ fs2.save_file_as_string(dest_path, callback);
1313
+ }
1314
+ })
1315
+ },
1316
+
1317
+ 'copy': function (source_path, dest_path, callback) {
1318
+ // dest must be a directory
1319
+ ncp.limit = 16;
1320
+ //console.log('copy source_path ' + source_path);
1321
+ //console.log('copy dest_path ' + dest_path);
1322
+
1323
+ //var test_for_same_files = true;
1324
+ // testing needs to handle when the dest file does not exist.
1325
+ var test_for_same_files = false;
1326
+ var ctu = true;
1327
+
1328
+ var the_rest = function () {
1329
+ ncp(source_path, dest_path, function (err) {
1330
+ if (err) {
1331
+ return console.error(err);
1332
+ }
1333
+ callback(null, true);
1334
+ //console.log('done!');
1335
+ });
1336
+ }
1337
+
1338
+ if (test_for_same_files) {
1339
+ // get the checksum for the source, and the dest.
1340
+
1341
+ checksum(source_path, function (err, source_checksum) {
1342
+ checksum(dest_path, function (err, dest_checksum) {
1343
+ if (source_checksum != dest_checksum) {
1344
+ the_rest();
1345
+ } else {
1346
+ callback(null, false);
1347
+ }
1348
+
1349
+ })
1350
+ })
1351
+
1352
+ } else {
1353
+ the_rest();
1354
+ }
1355
+
1356
+ /*
1357
+ fs.stat(dest_path, function(err, stats) {
1358
+ if (err) {
1359
+
1360
+ } else {
1361
+
1362
+ if (stats.isDirectory()) {
1363
+
1364
+ fs.stat(source_path, function(err, stats) {
1365
+ if (err) {
1366
+
1367
+ } else {
1368
+
1369
+ if (stats.isDirectory()) {
1370
+
1371
+ // create the corresponding directory
1372
+ // copy every file and directory within that directory to the corresponding directory
1373
+
1374
+ // This can be built up using fns.
1375
+
1376
+
1377
+
1378
+ } else {
1379
+
1380
+ }
1381
+
1382
+ }
1383
+ });
1384
+
1385
+ }
1386
+
1387
+ }
1388
+ });
1389
+ */
1390
+ // source can be a file or directory.
1391
+
1392
+ // when copying a directory, copy all directories inside it as well (recursively).
1393
+
1394
+ },
1395
+ 'delete': function (path, callback) {
1396
+ // needs to be a versitile delete function.
1397
+
1398
+ // use rimraf if it's a directory.
1399
+ fs2.metadata(path, function (err, md) {
1400
+ if (err) {
1401
+ callback(err);
1402
+ } else {
1403
+ console.log('md ' + stringify(md));
1404
+ if (!md) {
1405
+ callback(null, false);
1406
+ } else {
1407
+ console.log('md.isDirectory ' + md.isDirectory);
1408
+ if (md[1].isDirectory) {
1409
+ console.log('pre rimraf path', path);
1410
+ rimraf(path, function (err) {
1411
+ if (err) {
1412
+ callback(err);
1413
+ } else {
1414
+ callback(null, true);
1415
+ }
1416
+ });
1417
+ }
1418
+ }
1419
+
1420
+ }
1421
+ })
1422
+ },
1423
+
1424
+ 'exists': function (path, callback) {
1425
+ fs.stat(path, (err, stat) => {
1426
+ callback(null, !!stat);
1427
+ });
1428
+ },
1429
+
1430
+ // does not try to delete it if its not there to start with
1431
+
1432
+ 'ensure_deleted': function (path, callback) {
1433
+ fs2.exists(path, (err, exists) => {
1434
+ if (!exists) {
1435
+ callback(null, true);
1436
+ } else {
1437
+ fs2.delete(path, callback);
1438
+ }
1439
+ });
1440
+ },
1441
+ // ensure_deleted
1442
+
1443
+ 'move': function (source_path, dest_path, callback) {
1444
+ var that = this;
1445
+ this.copy(source_path, dest_path, (err, res_copy) => {
1446
+ if (err) {
1447
+ callback(err);
1448
+ } else {
1449
+ that.delete(source_path, callback);
1450
+ }
1451
+ })
1452
+ },
1453
+
1454
+
1455
+ // fs2-traverse?
1456
+
1457
+ // maybe keep in core for the moment.
1458
+
1459
+
1460
+ 'dir_contents_with_metadata_full_tree': function (start_path, callback) {
1461
+ // get this from za?
1462
+
1463
+ // I think this will be recursive...
1464
+ //console.log('');
1465
+ //console.log('dir_contents_with_metadata_to_path');
1466
+ //console.log('start_path ' + start_path);
1467
+ //console.log('dest_path ' + dest_path);
1468
+
1469
+
1470
+ // Let's build this up...
1471
+
1472
+ // get the contents and metadata for the path itself.
1473
+
1474
+ // Also, this can act as a finite state machine.
1475
+ // Can have simultaneous processes too.
1476
+
1477
+ // recursive function within this one.
1478
+
1479
+ var path_from_start = '';
1480
+
1481
+ var res = {};
1482
+
1483
+
1484
+ // and look at the dest path...
1485
+
1486
+ if (dest_path.length < start_path.length) {
1487
+ throw 'dest path length must be >= source path length';
1488
+ }
1489
+
1490
+ if (dest_path.substr(0, start_path.length) != start_path) {
1491
+ throw 'the dest path must start with the start path - therefore being a subdirectory';
1492
+ }
1493
+
1494
+ var process_path = function (path_from_start, arr_path, current_res_obj, callback) {
1495
+ //console.log('process_path');
1496
+ //console.log('arr_path ' + stringify(arr_path));
1497
+
1498
+ var current_path = start_path + path_from_start;
1499
+
1500
+ // will need to put the items into the res properly.
1501
+ //console.log('current_path ' + current_path);
1502
+ //throw 'stop';
1503
+ fs2.dir_contents_with_metadata(current_path, function (err, dir_contents) {
1504
+ if (err) {
1505
+ throw (err);
1506
+ } else {
1507
+ // for every file...
1508
+ //console.log('have contents for ' + current_path);
1509
+
1510
+
1511
+ if (dir_contents.files && dir_contents.files.length > 0) {
1512
+ current_res_obj.files = current_res_obj.files || [];
1513
+ each(dir_contents.files, function (i, file_info) {
1514
+ //console.log('file_info ' + stringify(file_info));
1515
+ var file_name = file_info[0];
1516
+ var file_md = file_info[1];
1517
+ //current_res_obj.files[file_name] = file_md;
1518
+
1519
+ current_res_obj.files.push(file_info);
1520
+ });
1521
+ //console.log('dir_contents ' + stringify(dir_contents));
1522
+ }
1523
+
1524
+ // for every directory... that gets more complicated.
1525
+
1526
+ // won't do the callback yet...
1527
+
1528
+ // will get the info from the directories, and put them in an object.
1529
+ // name, contents, metadata.
1530
+
1531
+ if (dir_contents.directories) {
1532
+ // process those directories.
1533
+ current_res_obj.directories = current_res_obj.directories || [];
1534
+ //var next_path =
1535
+ //var next_arr_path = arr_path.slice();
1536
+ //next_arr_path.push(
1537
+
1538
+ var fns = [];
1539
+
1540
+ each(dir_contents.directories, function (i, directory_info) {
1541
+ //console.log('directory_info ' + stringify(directory_info));
1542
+
1543
+ if (tof(directory_info == 'string')) {
1544
+ var directory_name = directory_info;
1545
+ var next_arr_path = arr_path.slice();
1546
+ next_arr_path.push(directory_name);
1547
+
1548
+ var dir_obj = [directory_name, {}, {}];
1549
+ current_res_obj.directories.push(dir_obj);
1550
+
1551
+ //console.log('path_from_start.substr(path_from_start.length -1) ' + path_from_start.substr(path_from_start.length -1));
1552
+
1553
+ //console.log('path_from_start ' + path_from_start);
1554
+
1555
+
1556
+ /*
1557
+ if (path_from_start.substr(path_from_start.length -1) == dir_separator) {
1558
+ throw 'stop';
1559
+ var next_path_from_start = path_from_start + directory_name;
1560
+ fns.push([process_path, [next_path_from_start, next_arr_path, current_res_obj]]);
1561
+ } else {
1562
+ var next_path_from_start = path_from_start + directory_name + dir_separator;
1563
+ fns.push([process_path, [next_path_from_start, next_arr_path, current_res_obj]]);
1564
+ }
1565
+ */
1566
+
1567
+ var next_path_from_start = path_from_start + directory_name + dir_separator;
1568
+ fns.push([process_path, [next_path_from_start, next_arr_path, current_res_obj]]);
1569
+
1570
+ } else {
1571
+ throw 'string expected';
1572
+ }
1573
+
1574
+ });
1575
+ //console.log('fns.length ' + fns.length);
1576
+ if (fns.length > 0) {
1577
+ call_multiple_callback_functions(fns, function (err, fns_res) {
1578
+ //console.log('fns_res ' + stringify(fns_res));
1579
+ callback(null, res);
1580
+ });
1581
+ } else {
1582
+ callback(null, res);
1583
+ }
1584
+
1585
+ } else {
1586
+ //console.log('no directories');
1587
+ callback(null, res);
1588
+ }
1589
+
1590
+ // need to go through every directory there, processing the path.
1591
+
1592
+ }
1593
+ });
1594
+
1595
+ }
1596
+
1597
+ process_path('', [], res, function (err, res_process_path) {
1598
+ //throw 'stop';
1599
+
1600
+ callback(null, res_process_path);
1601
+
1602
+ });
1603
+ },
1604
+
1605
+
1606
+ // could become another option of 'dir_contents'
1607
+ // and 'dir_contents' could even become 'contents' where it would load the contents of a file too. Maybe even set contents as well.
1608
+
1609
+ // this is unrestricted from that path.
1610
+
1611
+ 'dir_contents_with_metadata_to_path': function (start_path, dest_path, callback) {
1612
+ // find the sequence of paths to get
1613
+
1614
+ // get them in sequence, then construct them into the object.
1615
+
1616
+ // maybe difficult?
1617
+ // get this from za?
1618
+ // I think this will be recursive...
1619
+ //console.log('');
1620
+ //console.log('dir_contents_with_metadata_to_path');
1621
+ //console.log('start_path ' + start_path);
1622
+ //console.log('dest_path ' + dest_path);
1623
+
1624
+
1625
+ // Let's build this up...
1626
+
1627
+ // get the contents and metadata for the path itself.
1628
+
1629
+ // Also, this can act as a finite state machine.
1630
+ // Can have simultaneous processes too.
1631
+
1632
+ // recursive function within this one.
1633
+
1634
+ var path_from_start = '';
1635
+
1636
+ var s_path_from_start = path_from_start.split(dir_separator);
1637
+
1638
+ var res = {};
1639
+
1640
+
1641
+ // and look at the dest path...
1642
+
1643
+ if (dest_path.length < start_path.length) {
1644
+ throw 'dest path length must be >= source path length';
1645
+ }
1646
+
1647
+ if (dest_path.substr(0, start_path.length) != start_path) {
1648
+ throw 'the dest path must start with the start path - therefore being a subdirectory';
1649
+ }
1650
+
1651
+ var navigation_path = dest_path.substr(start_path.length);
1652
+ //console.log('navigation_path ' + navigation_path);
1653
+
1654
+ if (navigation_path.substr(navigation_path.length - 1) == dir_separator) {
1655
+ navigation_path = navigation_path.substr(0, navigation_path.length - 1);
1656
+ }
1657
+
1658
+ //console.log('navigation_path ' + navigation_path);
1659
+
1660
+ var s_np = navigation_path.split(dir_separator);
1661
+ //console.log('s_np ' + stringify(s_np));
1662
+
1663
+ //throw 'stop';
1664
+
1665
+ var depth = 0;
1666
+
1667
+ var process_path = function (path_from_start, arr_path, current_res_obj, depth, callback) {
1668
+ //console.log('process_path');
1669
+ //console.log('arr_path ' + stringify(arr_path));
1670
+
1671
+ var current_path = start_path + path_from_start;
1672
+
1673
+ // will need to put the items into the res properly.
1674
+ //console.log('current_path ' + current_path);
1675
+ //throw 'stop';
1676
+ fs2.dir_contents_with_metadata(current_path, function (err, dir_contents) {
1677
+ if (err) {
1678
+ throw (err);
1679
+ } else {
1680
+ // for every file...
1681
+ //console.log('have contents for ' + current_path);
1682
+
1683
+
1684
+ if (dir_contents.files && dir_contents.files.length > 0) {
1685
+ current_res_obj.files = current_res_obj.files || [];
1686
+ each(dir_contents.files, function (file_info, i) {
1687
+ //console.log('file_info ' + stringify(file_info));
1688
+ var file_name = file_info[0];
1689
+ var file_md = file_info[1];
1690
+ //current_res_obj.files[file_name] = file_md;
1691
+
1692
+ current_res_obj.files.push(file_info);
1693
+ });
1694
+ //console.log('dir_contents ' + stringify(dir_contents));
1695
+ }
1696
+
1697
+ // for every directory... that gets more complicated.
1698
+
1699
+ // won't do the callback yet...
1700
+
1701
+ // will get the info from the directories, and put them in an object.
1702
+ // name, contents, metadata.
1703
+
1704
+ if (dir_contents.directories) {
1705
+ // process those directories.
1706
+ current_res_obj.directories = current_res_obj.directories || [];
1707
+ //var next_path =
1708
+ //var next_arr_path = arr_path.slice();
1709
+ //next_arr_path.push(
1710
+
1711
+ var fns = [];
1712
+
1713
+ each(dir_contents.directories, function (i, directory_info) {
1714
+ //console.log('directory_info ' + stringify(directory_info));
1715
+
1716
+ if (tof(directory_info == 'string')) {
1717
+ var directory_name = directory_info;
1718
+ var next_arr_path = arr_path.slice();
1719
+ next_arr_path.push(directory_name);
1720
+
1721
+ var dir_obj = [directory_name, {}, {}];
1722
+ current_res_obj.directories.push(dir_obj);
1723
+
1724
+
1725
+ // check it's the next directory name.
1726
+
1727
+ if (directory_name == s_np[depth]) {
1728
+
1729
+ var next_path_from_start = path_from_start + directory_name + dir_separator;
1730
+ fns.push([process_path, [next_path_from_start, next_arr_path, current_res_obj, depth + 1]]);
1731
+
1732
+ }
1733
+
1734
+
1735
+
1736
+ } else {
1737
+ throw 'string expected';
1738
+ }
1739
+
1740
+ });
1741
+ //console.log('fns.length ' + fns.length);
1742
+ if (fns.length > 0) {
1743
+ call_multiple_callback_functions(fns, function (err, fns_res) {
1744
+ //console.log('fns_res ' + stringify(fns_res));
1745
+ callback(null, res);
1746
+ });
1747
+ } else {
1748
+ callback(null, res);
1749
+ }
1750
+
1751
+
1752
+
1753
+ } else {
1754
+ //console.log('no directories');
1755
+ callback(null, res);
1756
+ }
1757
+ // need to go through every directory there, processing the path.
1758
+ }
1759
+
1760
+ });
1761
+
1762
+ }
1763
+
1764
+ process_path('', [], res, depth, function (err, res_process_path) {
1765
+ //throw 'stop';
1766
+
1767
+ callback(null, res_process_path);
1768
+
1769
+ });
1770
+
1771
+ },
1772
+
1773
+
1774
+ // will use the polymorphism of dir_contents and parameters.
1775
+ // have this returning the object with files and directories.
1776
+ '_dir_contents_with_metadata': function (path, callback) {
1777
+ //console.log('dir_contents_with_metadata path ' + path);
1778
+
1779
+ if (path.lastIndexOf(dir_separator) != path.length - 1) {
1780
+ path = path + dir_separator;
1781
+ }
1782
+
1783
+ fs2.dir_contents(path, function (err, dir_contents) {
1784
+ if (err) {
1785
+ //console.log('dir_contents_with_metadata err ' + err);
1786
+ } else {
1787
+ //console.log('dir_contents_with_metadata path ' + path + ' has callback ');
1788
+ var res = {};
1789
+
1790
+ if (dir_contents.directories && dir_contents.directories.length > 0) {
1791
+ res.directories = dir_contents.directories;
1792
+ }
1793
+
1794
+ var cb = function () {
1795
+ callback(null, res);
1796
+ };
1797
+
1798
+ if (dir_contents.files && dir_contents.files.length > 0) {
1799
+ // do a sequential_call
1800
+
1801
+ //console.log('dir_contents.files ' + stringify(dir_contents.files));
1802
+
1803
+ var seq_md = sequential_call(fs2.metadata);
1804
+ // may be a faster way of getting metadata.
1805
+
1806
+ var files_with_paths = [];
1807
+ each(dir_contents.files, function (v, i) {
1808
+ var full_path = path + v;
1809
+ files_with_paths.push(full_path);
1810
+ });
1811
+
1812
+ //console.log('files_with_paths ' + stringify(files_with_paths));
1813
+
1814
+ seq_md(files_with_paths, function (err, res2) {
1815
+ if (err) {
1816
+
1817
+ } else {
1818
+ //console.log('seq_md res ' + stringify(res));
1819
+ res.files = res2;
1820
+ callback(null, res);
1821
+ }
1822
+ });
1823
+ } else {
1824
+ cb();
1825
+ }
1826
+ }
1827
+ })
1828
+ }
1829
+
1830
+ }
1831
+
1832
+
1833
+ //module.exports = fs2;
1834
+ // return fs2;
1835
+ //});
1836
+
1837
1837
  module.exports = fs2;