@silexlabs/silex 3.0.1-0 → 3.0.1

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 (250) hide show
  1. package/.env.default +3 -2
  2. package/.silex.js +39 -1
  3. package/README.md +37 -35
  4. package/dist/client/client/api.d.ts +8 -1
  5. package/dist/client/client/assetUrl.d.ts +54 -0
  6. package/dist/client/client/config.d.ts +60 -1
  7. package/dist/client/client/events.d.ts +19 -10
  8. package/dist/client/client/grapesjs/PublicationManager.d.ts +6 -8
  9. package/dist/client/client/grapesjs/PublicationUi.d.ts +8 -10
  10. package/dist/client/client/grapesjs/breadcrumbs.d.ts +1 -0
  11. package/dist/client/client/grapesjs/css-props.d.ts +6 -0
  12. package/dist/client/client/grapesjs/footer.d.ts +2 -0
  13. package/dist/client/client/grapesjs/img.d.ts +6 -0
  14. package/dist/client/client/grapesjs/index.d.ts +6 -2
  15. package/dist/client/client/grapesjs/internal-links.d.ts +1 -1
  16. package/dist/client/client/grapesjs/keymaps.d.ts +123 -0
  17. package/dist/client/client/grapesjs/new-page-dialog.d.ts +1 -1
  18. package/dist/client/client/grapesjs/page-panel.d.ts +7 -1
  19. package/dist/client/client/grapesjs/project-bar.d.ts +20 -0
  20. package/dist/client/client/grapesjs/resize-panel.d.ts +1 -0
  21. package/dist/client/client/grapesjs/rich-text.d.ts +4 -1
  22. package/dist/client/client/grapesjs/semantic.d.ts +1 -1
  23. package/dist/client/client/grapesjs/settings-sections.d.ts +16 -0
  24. package/dist/client/client/grapesjs/settings.d.ts +3 -1
  25. package/dist/client/client/grapesjs/storage.d.ts +1 -0
  26. package/dist/client/client/grapesjs/symbolDialogs.d.ts +1 -1
  27. package/dist/client/client/grapesjs/view-buttons.d.ts +1 -0
  28. package/dist/client/client/index.d.ts +5 -0
  29. package/dist/client/client/publication-transformers.d.ts +42 -0
  30. package/dist/client/client/publish-custom-code-block.d.ts +4 -0
  31. package/dist/client/client/publish-fonts.d.ts +4 -0
  32. package/dist/client/client/utils.d.ts +22 -1
  33. package/dist/client/constants.d.ts +3 -0
  34. package/dist/client/css/admin.css +1107 -411
  35. package/dist/client/css/admin.css.map +1 -0
  36. package/dist/client/grapesjs-filter-styles/dist/index.d.ts +4 -0
  37. package/dist/client/grapesjs-fonts/dist/index.d.ts +4 -0
  38. package/dist/client/grapesjs-fonts/src/commands.d.ts +3 -0
  39. package/dist/client/grapesjs-fonts/src/fonts.d.ts +4 -0
  40. package/dist/client/grapesjs-storage-rate-limit/dist/index.d.ts +4 -0
  41. package/dist/client/grapesjs-ui-suggest-classes/dist/index.d.ts +4 -0
  42. package/dist/client/index.html +3 -2
  43. package/dist/client/js/main.js +305 -170
  44. package/dist/client/js/main.js.LICENSE.txt +21 -1
  45. package/dist/client/page.d.ts +1 -1
  46. package/dist/client/silex-lib/src/ts/client/api.d.ts +90 -0
  47. package/dist/client/silex-lib/src/ts/client/assetUrl.d.ts +54 -0
  48. package/dist/client/silex-lib/src/ts/client/config.d.ts +102 -0
  49. package/dist/client/silex-lib/src/ts/client/events.d.ts +23 -0
  50. package/dist/client/silex-lib/src/ts/client/expose.d.ts +8 -0
  51. package/dist/client/silex-lib/src/ts/client/grapesjs/LoginDialog.d.ts +15 -0
  52. package/dist/client/silex-lib/src/ts/client/grapesjs/PublicationManager.d.ts +73 -0
  53. package/dist/client/silex-lib/src/ts/client/grapesjs/PublicationUi.d.ts +59 -0
  54. package/dist/client/silex-lib/src/ts/client/grapesjs/blocks.d.ts +1 -0
  55. package/dist/client/silex-lib/src/ts/client/grapesjs/breadcrumbs.d.ts +1 -0
  56. package/dist/client/silex-lib/src/ts/client/grapesjs/css-props.d.ts +6 -0
  57. package/dist/client/silex-lib/src/ts/client/grapesjs/footer.d.ts +2 -0
  58. package/dist/client/silex-lib/src/ts/client/grapesjs/img.d.ts +6 -0
  59. package/dist/client/silex-lib/src/ts/client/grapesjs/index.d.ts +9 -0
  60. package/dist/client/silex-lib/src/ts/client/grapesjs/internal-links.d.ts +1 -0
  61. package/dist/client/silex-lib/src/ts/client/grapesjs/keymaps.d.ts +123 -0
  62. package/dist/client/silex-lib/src/ts/client/grapesjs/new-page-dialog.d.ts +2 -0
  63. package/dist/client/silex-lib/src/ts/client/grapesjs/openImport.d.ts +9 -0
  64. package/dist/client/silex-lib/src/ts/client/grapesjs/page-panel.d.ts +9 -0
  65. package/dist/client/silex-lib/src/ts/client/grapesjs/project-bar.d.ts +21 -0
  66. package/dist/client/silex-lib/src/ts/client/grapesjs/resize-panel.d.ts +1 -0
  67. package/dist/client/silex-lib/src/ts/client/grapesjs/rich-text.d.ts +4 -0
  68. package/dist/client/silex-lib/src/ts/client/grapesjs/semantic.d.ts +1 -0
  69. package/dist/client/silex-lib/src/ts/client/grapesjs/settings-sections.d.ts +16 -0
  70. package/dist/client/silex-lib/src/ts/client/grapesjs/settings.d.ts +4 -0
  71. package/dist/client/silex-lib/src/ts/client/grapesjs/storage.d.ts +2 -0
  72. package/dist/client/silex-lib/src/ts/client/grapesjs/symbolDialogs.d.ts +3 -0
  73. package/dist/client/silex-lib/src/ts/client/grapesjs/view-buttons.d.ts +1 -0
  74. package/dist/client/silex-lib/src/ts/client/index.d.ts +10 -0
  75. package/dist/client/silex-lib/src/ts/client/publication-transformers.d.ts +42 -0
  76. package/dist/client/silex-lib/src/ts/client/publish-custom-code-block.d.ts +4 -0
  77. package/dist/client/silex-lib/src/ts/client/publish-fonts.d.ts +4 -0
  78. package/dist/client/silex-lib/src/ts/client/utils.d.ts +22 -0
  79. package/dist/client/silex-lib/src/ts/constants.d.ts +32 -0
  80. package/dist/client/silex-lib/src/ts/page.d.ts +2 -0
  81. package/dist/client/silex-lib/src/ts/types.d.ts +339 -0
  82. package/dist/client/types.d.ts +59 -35
  83. package/dist/plugins/client/client/events.d.ts +19 -10
  84. package/dist/plugins/client/client/events.js +11 -0
  85. package/dist/plugins/client/client/events.js.map +1 -1
  86. package/dist/plugins/client/plugins/client/template.js +119 -71
  87. package/dist/plugins/client/plugins/client/template.js.map +1 -1
  88. package/dist/plugins/client/plugins/client/website-info.d.ts +1 -0
  89. package/dist/plugins/client/plugins/client/website-info.js +72 -0
  90. package/dist/plugins/client/plugins/client/website-info.js.map +1 -0
  91. package/dist/plugins/client/types.d.ts +59 -35
  92. package/dist/plugins/client/types.js +23 -0
  93. package/dist/plugins/client/types.js.map +1 -1
  94. package/dist/plugins/server/constants.d.ts +3 -0
  95. package/dist/plugins/server/constants.js +28 -1
  96. package/dist/plugins/server/constants.js.map +1 -1
  97. package/dist/plugins/server/plugins/server/Cache.js +9 -5
  98. package/dist/plugins/server/plugins/server/Cache.js.map +1 -1
  99. package/dist/plugins/server/plugins/server/DownloadConnector.d.ts +29 -0
  100. package/dist/plugins/server/plugins/server/DownloadConnector.js +127 -0
  101. package/dist/plugins/server/plugins/server/DownloadConnector.js.map +1 -0
  102. package/dist/plugins/server/plugins/server/FtpConnector.d.ts +5 -2
  103. package/dist/plugins/server/plugins/server/FtpConnector.js +38 -23
  104. package/dist/plugins/server/plugins/server/FtpConnector.js.map +1 -1
  105. package/dist/plugins/server/plugins/server/GitlabConnector.d.ts +63 -9
  106. package/dist/plugins/server/plugins/server/GitlabConnector.js +367 -91
  107. package/dist/plugins/server/plugins/server/GitlabConnector.js.map +1 -1
  108. package/dist/plugins/server/plugins/server/GitlabHostingConnector.d.ts +16 -0
  109. package/dist/plugins/server/plugins/server/GitlabHostingConnector.js +209 -0
  110. package/dist/plugins/server/plugins/server/GitlabHostingConnector.js.map +1 -0
  111. package/dist/plugins/server/plugins/server/SslPlugin.js +6 -6
  112. package/dist/plugins/server/plugins/server/SslPlugin.js.map +1 -1
  113. package/dist/plugins/server/plugins/server/StaticPlugin.d.ts +8 -1
  114. package/dist/plugins/server/plugins/server/StaticPlugin.js +5 -31
  115. package/dist/plugins/server/plugins/server/StaticPlugin.js.map +1 -1
  116. package/dist/plugins/server/server/config.js +8 -9
  117. package/dist/plugins/server/server/config.js.map +1 -1
  118. package/dist/plugins/server/server/connectors/FsHosting.d.ts +3 -2
  119. package/dist/plugins/server/server/connectors/FsHosting.js +18 -7
  120. package/dist/plugins/server/server/connectors/FsHosting.js.map +1 -1
  121. package/dist/plugins/server/server/connectors/FsStorage.d.ts +3 -1
  122. package/dist/plugins/server/server/connectors/FsStorage.js +35 -28
  123. package/dist/plugins/server/server/connectors/FsStorage.js.map +1 -1
  124. package/dist/plugins/server/server/connectors/connectors.d.ts +7 -7
  125. package/dist/plugins/server/server/connectors/connectors.js +6 -7
  126. package/dist/plugins/server/server/connectors/connectors.js.map +1 -1
  127. package/dist/plugins/server/server/events.js +16 -0
  128. package/dist/plugins/server/server/events.js.map +1 -1
  129. package/dist/plugins/server/server/jobs.d.ts +6 -0
  130. package/dist/plugins/server/server/jobs.js +12 -8
  131. package/dist/plugins/server/server/jobs.js.map +1 -1
  132. package/dist/plugins/server/server/utils/validation.js +1 -2
  133. package/dist/plugins/server/server/utils/validation.js.map +1 -1
  134. package/dist/plugins/server/types.d.ts +59 -35
  135. package/dist/plugins/server/types.js +24 -1
  136. package/dist/plugins/server/types.js.map +1 -1
  137. package/dist/server/constants.js +27 -1
  138. package/dist/server/plugins/server/Cache.js +9 -5
  139. package/dist/server/server/api/api.js +1 -1
  140. package/dist/server/server/api/connectorApi.js +154 -25
  141. package/dist/server/server/api/publicationApi.js +17 -25
  142. package/dist/server/server/api/websiteApi.js +30 -8
  143. package/dist/server/server/cli.js +9 -6
  144. package/dist/server/server/config.js +8 -9
  145. package/dist/server/server/connectors/FsHosting.js +17 -7
  146. package/dist/server/server/connectors/FsStorage.js +34 -28
  147. package/dist/server/server/connectors/connectors.js +6 -7
  148. package/dist/server/server/express.js +4 -5
  149. package/dist/server/server/index.js +5 -1
  150. package/dist/server/server/jobs.js +11 -8
  151. package/dist/server/server/utils/validation.js +1 -2
  152. package/dist/server/types.js +13 -1
  153. package/package.json +56 -42
  154. package/public/assets/download.png +0 -0
  155. package/public/assets/favicon.ico +0 -0
  156. package/public/assets/favicon.png +0 -0
  157. package/public/assets/ftp.png +0 -0
  158. package/public/assets/gitlab.png +0 -0
  159. package/public/assets/gitlab2.png +0 -0
  160. package/public/assets/laptop.png +0 -0
  161. package/public/assets/logo-silex-small.png +0 -0
  162. package/public/silex.js +5 -23
  163. package/src/css/_variables.scss +23 -20
  164. package/src/css/dialog.scss +27 -1
  165. package/src/css/fonts.scss +31 -0
  166. package/src/css/footer.scss +12 -0
  167. package/src/css/grapesjs-light.scss +180 -0
  168. package/src/css/grapesjs-plugins.scss +227 -0
  169. package/src/css/grapesjs.scss +84 -10
  170. package/src/css/index.scss +12 -1
  171. package/src/css/light.scss +7 -0
  172. package/src/css/project-bar.scss +32 -16
  173. package/src/css/silex.scss +79 -5
  174. package/src/css/website-info.scss +14 -0
  175. package/src/html/index.pug +3 -3
  176. package/src/ts/client/api.ts +38 -14
  177. package/src/ts/client/assetUrl.test.ts +164 -0
  178. package/src/ts/client/assetUrl.ts +254 -0
  179. package/src/ts/client/config.ts +133 -5
  180. package/src/ts/client/events.ts +21 -9
  181. package/src/ts/client/grapesjs/LoginDialog.ts +4 -2
  182. package/src/ts/client/grapesjs/PublicationManager.ts +180 -54
  183. package/src/ts/client/grapesjs/PublicationUi.ts +122 -86
  184. package/src/ts/client/grapesjs/breadcrumbs.ts +79 -0
  185. package/src/ts/client/grapesjs/css-props.ts +910 -0
  186. package/src/ts/client/grapesjs/eleventy.ts +11 -8
  187. package/{dist/plugins/client/page.js → src/ts/client/grapesjs/footer.ts} +24 -13
  188. package/src/ts/client/grapesjs/img.ts +147 -0
  189. package/src/ts/client/grapesjs/index.ts +234 -52
  190. package/src/ts/client/grapesjs/internal-links.test.ts +2 -1
  191. package/src/ts/client/grapesjs/internal-links.ts +14 -7
  192. package/src/ts/client/grapesjs/keymaps.ts +207 -0
  193. package/src/ts/client/grapesjs/new-page-dialog.ts +2 -3
  194. package/src/ts/client/grapesjs/page-panel.ts +92 -7
  195. package/src/ts/client/grapesjs/project-bar.ts +116 -72
  196. package/src/ts/client/grapesjs/resize-panel.ts +20 -0
  197. package/src/ts/client/grapesjs/rich-text.ts +21 -13
  198. package/src/ts/client/grapesjs/semantic.ts +3 -3
  199. package/src/ts/client/grapesjs/settings-sections.ts +117 -0
  200. package/src/ts/client/grapesjs/settings.ts +174 -96
  201. package/src/ts/client/grapesjs/storage.ts +98 -33
  202. package/src/ts/client/grapesjs/symbolDialogs.ts +3 -4
  203. package/src/ts/{plugins/server/AuthPlugin.ts → client/grapesjs/view-buttons.ts} +23 -19
  204. package/src/ts/client/index.ts +35 -16
  205. package/src/ts/client/publication-transformers.test.ts +207 -0
  206. package/src/ts/client/publication-transformers.ts +280 -0
  207. package/{dist/plugins/client/client/utils.js → src/ts/client/publish-custom-code-block.ts} +14 -8
  208. package/src/ts/client/publish-fonts.ts +36 -0
  209. package/src/ts/client/utils.ts +53 -1
  210. package/src/ts/constants.ts +31 -0
  211. package/src/ts/page.ts +2 -2
  212. package/src/ts/plugins/client/template.ts +125 -75
  213. package/src/ts/plugins/client/website-info.ts +84 -0
  214. package/src/ts/plugins/server/Cache.ts +6 -2
  215. package/src/ts/plugins/server/DownloadConnector.ts +146 -0
  216. package/src/ts/plugins/server/FtpConnector.ts +47 -21
  217. package/src/ts/plugins/server/GitlabConnector.ts +423 -108
  218. package/src/ts/plugins/server/GitlabHostingConnector.ts +215 -0
  219. package/src/ts/plugins/server/SslPlugin.ts +5 -5
  220. package/src/ts/plugins/server/StaticPlugin.ts +3 -30
  221. package/src/ts/server/api/connectorApi.ts +165 -28
  222. package/src/ts/server/api/publicationApi.ts +17 -24
  223. package/src/ts/server/api/websiteApi.ts +57 -14
  224. package/src/ts/server/cli.ts +7 -5
  225. package/src/ts/server/config.ts +9 -10
  226. package/src/ts/server/connectors/FsHosting.ts +14 -8
  227. package/src/ts/server/connectors/FsStorage.ts +40 -7
  228. package/src/ts/server/connectors/connectors.ts +8 -6
  229. package/src/ts/server/events.ts +17 -0
  230. package/src/ts/server/express.ts +2 -2
  231. package/src/ts/server/index.ts +6 -0
  232. package/src/ts/server/jobs.ts +14 -2
  233. package/src/ts/server/utils/BackwardCompat.ts +530 -529
  234. package/src/ts/types.ts +78 -34
  235. package/dist/plugins/client/client/utils.d.ts +0 -1
  236. package/dist/plugins/client/client/utils.js.map +0 -1
  237. package/dist/plugins/client/page.d.ts +0 -2
  238. package/dist/plugins/client/page.js.map +0 -1
  239. package/dist/plugins/client/plugins/client/publicationRenderer.d.ts +0 -2
  240. package/dist/plugins/client/plugins/client/publicationRenderer.js +0 -128
  241. package/dist/plugins/client/plugins/client/publicationRenderer.js.map +0 -1
  242. package/dist/plugins/server/plugins/server/AuthPlugin.d.ts +0 -1
  243. package/dist/plugins/server/plugins/server/AuthPlugin.js +0 -38
  244. package/dist/plugins/server/plugins/server/AuthPlugin.js.map +0 -1
  245. package/dist/plugins/server/plugins/server/HooksPlugin.d.ts +0 -7
  246. package/dist/plugins/server/plugins/server/HooksPlugin.js +0 -74
  247. package/dist/plugins/server/plugins/server/HooksPlugin.js.map +0 -1
  248. package/src/example-client-config.js +0 -64
  249. package/src/ts/plugins/client/publicationRenderer.ts +0 -128
  250. package/src/ts/plugins/server/HooksPlugin.ts +0 -76
@@ -47,98 +47,217 @@ const connectors_1 = require("../../server/connectors/connectors");
47
47
  const types_1 = require("../../types");
48
48
  const node_fetch_1 = __importDefault(require("node-fetch"));
49
49
  const crypto_1 = __importStar(require("crypto"));
50
- async function wait(ms) {
51
- return new Promise(resolve => setTimeout(resolve, ms));
52
- }
50
+ const path_1 = require("path");
51
+ const svg = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
52
+ <svg
53
+ xmlns:svg="http://www.w3.org/2000/svg"
54
+ xmlns="http://www.w3.org/2000/svg"
55
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
56
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
57
+ width="1000"
58
+ height="963.197"
59
+ viewBox="0 0 1000 963.197"
60
+ version="1.1"
61
+ id="svg85">
62
+ <sodipodi:namedview
63
+ id="namedview87"
64
+ pagecolor="#ffffff"
65
+ bordercolor="#666666"
66
+ borderopacity="1.0"
67
+ inkscape:pageshadow="2"
68
+ inkscape:pageopacity="0.0"
69
+ inkscape:pagecheckerboard="0"
70
+ showgrid="false"
71
+ inkscape:zoom="1"
72
+ inkscape:cx="991.5"
73
+ inkscape:cy="964.5"
74
+ inkscape:window-width="1126"
75
+ inkscape:window-height="895"
76
+ inkscape:window-x="774"
77
+ inkscape:window-y="12"
78
+ inkscape:window-maximized="0"
79
+ inkscape:current-layer="svg85" />
80
+ <defs
81
+ id="defs74">
82
+ <style
83
+ id="style72">.cls-1{fill:#e24329;}.cls-2{fill:#fc6d26;}.cls-3{fill:#fca326;}</style>
84
+ </defs>
85
+ <g
86
+ id="LOGO"
87
+ transform="matrix(5.2068817,0,0,5.2068817,-489.30756,-507.76085)">
88
+ <path
89
+ class="cls-1"
90
+ d="m 282.83,170.73 -0.27,-0.69 -26.14,-68.22 a 6.81,6.81 0 0 0 -2.69,-3.24 7,7 0 0 0 -8,0.43 7,7 0 0 0 -2.32,3.52 l -17.65,54 h -71.47 l -17.65,-54 a 6.86,6.86 0 0 0 -2.32,-3.53 7,7 0 0 0 -8,-0.43 6.87,6.87 0 0 0 -2.69,3.24 L 97.44,170 l -0.26,0.69 a 48.54,48.54 0 0 0 16.1,56.1 l 0.09,0.07 0.24,0.17 39.82,29.82 19.7,14.91 12,9.06 a 8.07,8.07 0 0 0 9.76,0 l 12,-9.06 19.7,-14.91 40.06,-30 0.1,-0.08 a 48.56,48.56 0 0 0 16.08,-56.04 z"
91
+ id="path76" />
92
+ <path
93
+ class="cls-2"
94
+ d="m 282.83,170.73 -0.27,-0.69 a 88.3,88.3 0 0 0 -35.15,15.8 L 190,229.25 c 19.55,14.79 36.57,27.64 36.57,27.64 l 40.06,-30 0.1,-0.08 a 48.56,48.56 0 0 0 16.1,-56.08 z"
95
+ id="path78" />
96
+ <path
97
+ class="cls-3"
98
+ d="m 153.43,256.89 19.7,14.91 12,9.06 a 8.07,8.07 0 0 0 9.76,0 l 12,-9.06 19.7,-14.91 c 0,0 -17.04,-12.89 -36.59,-27.64 -19.55,14.75 -36.57,27.64 -36.57,27.64 z"
99
+ id="path80" />
100
+ <path
101
+ class="cls-2"
102
+ d="M 132.58,185.84 A 88.19,88.19 0 0 0 97.44,170 l -0.26,0.69 a 48.54,48.54 0 0 0 16.1,56.1 l 0.09,0.07 0.24,0.17 39.82,29.82 c 0,0 17,-12.85 36.57,-27.64 z"
103
+ id="path82" />
104
+ </g>
105
+ </svg>`;
106
+ const encodedSvg = encodeURIComponent(svg);
107
+ const ICON = '/assets/gitlab.png';
53
108
  class GitlabConnector {
54
109
  config;
55
110
  connectorId = 'gitlab';
56
111
  connectorType = types_1.ConnectorType.STORAGE;
57
112
  displayName = 'GitLab';
58
- icon = 'http://gitlab.lcqb.upmc.fr/assets/favicon-075eba76312e8421991a0c1f89a89ee81678bcde72319dd3e8047e2a47cd3a42.ico';
113
+ icon = ICON;
59
114
  disableLogout = false;
60
- color = '#ffffff';
61
- background = '#FC6D26';
115
+ color = '#2B1B63';
116
+ background = 'rgba(252, 109, 38, 0.2)';
62
117
  options;
63
118
  constructor(config, opts) {
64
119
  this.config = config;
65
120
  this.options = {
66
121
  branch: 'main',
67
- assetsFolder: '',
122
+ assetsFolder: 'assets',
123
+ //metaRepo: 'silex-meta',
124
+ //metaRepoFile: 'websites.json',
125
+ repoPrefix: 'silex_',
126
+ scope: 'api', // 'api+read_api+read_user+read_repository+write_repository+email+sudo+profile+openid'
68
127
  ...opts,
69
128
  };
70
129
  if (!this.options.clientId)
71
130
  throw new Error('Missing Gitlab client ID');
72
131
  if (!this.options.clientSecret)
73
132
  throw new Error('Missing Gitlab client secret');
133
+ if (!this.options.domain)
134
+ throw new Error('Missing Gitlab domain');
135
+ if (!this.options.timeOut)
136
+ this.options.timeOut = 15000; /* default value */
74
137
  }
75
138
  // **
76
139
  // Convenience methods for the Gitlab API
77
140
  getAssetPath(path) {
78
- return `${this.options.assetsFolder}${path}`;
141
+ return encodeURIComponent((0, path_1.join)(this.options.assetsFolder, path));
142
+ }
143
+ isUsingOfficialInstance() {
144
+ const gitlabDomainRegexp = /(^|\b)(gitlab\.com)($|\b)/;
145
+ return gitlabDomainRegexp.test(this.options.domain);
79
146
  }
80
147
  async createFile(session, websiteId, path, content, isBase64 = false) {
81
148
  // Remove leading slash
82
149
  const safePath = path.replace(/^\//, '');
150
+ const encodePath = decodeURIComponent(path);
83
151
  return this.callApi(session, `api/v4/projects/${websiteId}/repository/files/${safePath}`, 'POST', {
84
152
  id: websiteId,
85
153
  branch: this.options.branch,
86
154
  content,
87
- commit_message: `Create file ${path} from Silex`,
155
+ commit_message: `Create file ${encodePath} from Silex`,
88
156
  encoding: isBase64 ? 'base64' : undefined,
89
157
  });
90
158
  }
91
159
  async updateFile(session, websiteId, path, content, isBase64 = false) {
92
160
  // Remove leading slash
93
161
  const safePath = path.replace(/^\//, '');
162
+ const encodePath = decodeURIComponent(path);
94
163
  return this.callApi(session, `api/v4/projects/${websiteId}/repository/files/${safePath}`, 'PUT', {
95
164
  id: websiteId,
96
165
  branch: this.options.branch,
97
166
  content: await (0, connectors_1.contentToString)(content),
98
- commit_message: `Update website asset ${path} from Silex`,
167
+ commit_message: `Update website asset ${encodePath} from Silex`,
99
168
  encoding: isBase64 ? 'base64' : undefined,
100
169
  });
101
170
  }
102
- async callApi(session, path, method = 'GET', body = null, params = {}) {
103
- const token = session?.gitlab?.token;
104
- const tokenParam = token ? `access_token=${token.access_token}&` : '';
105
- const paramsStr = Object.entries(params).map(([k, v]) => `${k}=${encodeURIComponent(v.toString())}`).join('&');
106
- const url = `https://gitlab.com/${path}?${tokenParam}${paramsStr}`;
171
+ async readFile(session, websiteId, fileName) {
172
+ const safePath = fileName.replace(/^\//, '');
173
+ // Call the API
174
+ const url = `${this.options.domain}/api/v4/projects/${websiteId}/repository/files/${safePath}?ref=${this.options.branch}&access_token=${this.getSessionToken(session).token?.access_token}`;
107
175
  const response = await (0, node_fetch_1.default)(url, {
108
- method,
176
+ method: 'GET',
109
177
  headers: {
110
178
  'Content-Type': 'application/json',
111
179
  },
112
- body: body ? JSON.stringify(body) : undefined
113
180
  });
114
- let json;
115
- // Handle the case when the server returns an non-JSON response (e.g. 400 Bad Request)
116
- const text = await response.text();
181
+ const json = await response.json();
182
+ if (!response.ok)
183
+ throw new types_1.ApiError(`Error reading file "${fileName}" from Gitlab: ${json?.message ?? json?.error ?? response.statusText}`, response.status);
184
+ // From base64 string to buffer
185
+ const buf = Buffer.from(json.content, 'base64');
186
+ // Return the image bytes
187
+ return buf;
188
+ }
189
+ /*
190
+ * Get the meta repo path for the current user
191
+ * The meta repo contains a JSON file which contains the list of websites
192
+ */
193
+ //private getMetaRepoPath(session: GitlabSession): string {
194
+ // if(!this.getSessionToken(session).username) throw new ApiError('Missing Gitlab user ID. User not logged in?', 401)
195
+ // return encodeURIComponent(`${this.getSessionToken(session).username}/${this.options.metaRepo}`)
196
+ //}
197
+ ///**
198
+ // * Initialize the storage with a meta repo
199
+ // */
200
+ //private async initStorage(session: GitlabSession): Promise<void> {
201
+ // // Create the meta repo
202
+ // try {
203
+ // const project = await this.callApi(session, 'api/v4/projects/', 'POST', {
204
+ // name: this.options.metaRepo,
205
+ // }) as any
206
+ // return this.createFile(session, this.getMetaRepoPath(session), this.options.metaRepoFile, JSON.stringify({
207
+ // websites: {}
208
+ // } as MetaRepoFileContent))
209
+ // } catch (e) {
210
+ // console.error('Could not init storage', e.statusCode, e.httpStatusCode, e)
211
+ // throw e
212
+ // }
213
+ //}
214
+ /**
215
+ * Call the Gitlab API with the user's token and handle errors
216
+ */
217
+ async callApi(session, path, method = 'GET', body = null, params = {}) {
218
+ const token = this.getSessionToken(session).token;
219
+ const tokenParam = token ? `access_token=${token.access_token}&` : '';
220
+ const paramsStr = Object.entries(params).map(([k, v]) => `${k}=${encodeURIComponent(v.toString())}`).join('&');
221
+ const url = `${this.options.domain}/${path}?${tokenParam}${paramsStr}`;
222
+ const headers = {
223
+ 'Content-Type': 'application/json',
224
+ };
225
+ if (method === 'GET' && body) {
226
+ console.error('Gitlab API error (4) - GET request with body', { url, method, body, params });
227
+ }
228
+ // With or without body
229
+ let response;
117
230
  try {
118
- json = JSON.parse(text);
231
+ response = await (0, node_fetch_1.default)(url, body && method !== 'GET' ? {
232
+ method,
233
+ headers,
234
+ body: body ? JSON.stringify(body) : undefined
235
+ } : {
236
+ method,
237
+ headers,
238
+ });
119
239
  }
120
240
  catch (e) {
121
- if (!response.ok) {
122
- // A real error
123
- throw e;
124
- }
125
- else {
126
- // Useless error linked to the fact that the response is not JSON
127
- //console.error('Gitlab API error - could not parse response', response.status, response.statusText, {url, method, body, params, text})
128
- return text;
129
- }
241
+ console.error('Gitlab API error (0)', e);
242
+ throw new types_1.ApiError(`Gitlab API error (0): ${e.message} ${e.code} ${e.name} ${e.type}`, 500);
130
243
  }
244
+ let json;
245
+ // Handle the case when the server returns a non-JSON response (e.g. 400 Bad Request)
246
+ const text = await response.text();
131
247
  if (!response.ok) {
132
- if (response.status === 401 && session?.gitlab?.token?.refresh_token) {
248
+ if (text.includes('A file with this name doesn\'t exist')) {
249
+ throw new types_1.ApiError('Gitlab API error (5): Not Found', 404);
250
+ }
251
+ else if (response.status === 401 && this.getSessionToken(session).token?.refresh_token) {
133
252
  // Refresh the token
134
- const token = session?.gitlab?.token;
253
+ const token = this.getSessionToken(session).token;
135
254
  const body = {
136
255
  grant_type: 'refresh_token',
137
- refresh_token: token.refresh_token,
256
+ refresh_token: token?.refresh_token,
138
257
  client_id: this.options.clientId,
139
258
  client_secret: this.options.clientSecret,
140
259
  };
141
- const response = await (0, node_fetch_1.default)('https://gitlab.com/oauth/token', {
260
+ const response = await (0, node_fetch_1.default)(this.options.domain + '/oauth/token', {
142
261
  method: 'POST',
143
262
  headers: {
144
263
  'Content-Type': 'application/json',
@@ -147,20 +266,42 @@ class GitlabConnector {
147
266
  });
148
267
  const refreshJson = await response.json();
149
268
  if (response.ok) {
150
- session.gitlab.token = {
151
- ...token,
152
- ...refreshJson,
153
- };
269
+ this.setSessionToken(session, {
270
+ token: {
271
+ ...token,
272
+ ...refreshJson,
273
+ },
274
+ });
154
275
  return await this.callApi(session, path, method, body, params);
155
276
  }
156
277
  else {
157
- //console.error('Gitlab API error - could not refresh token', response.status, response.statusText, { url, method, body, params, refreshJson })
158
- throw new types_1.ApiError(`Gitlab API error: ${refreshJson?.message ?? response.statusText}`, response.status);
278
+ const message = typeof refreshJson?.message === 'object' ? Object.entries(refreshJson.message).map(entry => entry.join(' ')).join(' ') : refreshJson?.message ?? refreshJson?.error ?? response.statusText;
279
+ console.error('Gitlab API error (2) - could not refresh token', response.status, response.statusText, { message }, 'refresh_token:', token?.refresh_token);
280
+ // Workaround for when the token is invalid
281
+ // It happens often which is not normal (refresh token should last 6 months)
282
+ this.logout(session);
283
+ // Notify the user
284
+ throw new types_1.ApiError(`Gitlab API error (2): ${message}`, response.status);
159
285
  }
160
286
  }
161
287
  else {
162
- //console.error('Gitlab API error', response.status, response.statusText, { url, method, body, params, json })
163
- throw new types_1.ApiError(`Gitlab API error: ${json?.message ?? json?.error ?? response.statusText}`, response.status);
288
+ const message = typeof json?.message === 'object' ? Object.entries(json.message).map(entry => entry.join(' ')).join(' ') : json?.message ?? json?.error ?? response.statusText;
289
+ console.error('Gitlab API error (1)', response.status, response.statusText, { url, method, body, params, text, message });
290
+ throw new types_1.ApiError(`Gitlab API error (1): ${message}`, response.status);
291
+ }
292
+ }
293
+ try {
294
+ json = JSON.parse(text);
295
+ }
296
+ catch (e) {
297
+ if (!response.ok) {
298
+ // A real error
299
+ throw e;
300
+ }
301
+ else {
302
+ // Useless error linked to the fact that the response is not JSON
303
+ console.error('Gitlab API error (3) - could not parse response', response.status, response.statusText, { url, method, body, params, text });
304
+ return text;
164
305
  }
165
306
  }
166
307
  return json;
@@ -196,14 +337,22 @@ class GitlabConnector {
196
337
  // Create the code challenge
197
338
  const codeChallenge = await this.generateCodeChallenge(codeVerifier);
198
339
  // Store the code verifier and code challenge in the session
199
- session.gitlab = {
200
- ...session.gitlab,
340
+ this.setSessionToken(session, {
341
+ ...this.getSessionToken(session),
201
342
  state,
202
343
  codeVerifier,
203
344
  codeChallenge,
204
- };
205
- const scope = 'api+read_api+read_user+read_repository+write_repository+email+sudo+profile+openid';
206
- return `https://gitlab.com/oauth/authorize?client_id=${this.options.clientId}&redirect_uri=${redirect_uri}&response_type=code&state=${session.gitlab.state}&scope=${scope}&code_challenge=${codeChallenge}&code_challenge_method=S256`;
345
+ });
346
+ return `${this.options.domain}/oauth/authorize?client_id=${this.options.clientId}&redirect_uri=${redirect_uri}&response_type=code&state=${this.getSessionToken(session).state}&scope=${this.options.scope}&code_challenge=${codeChallenge}&code_challenge_method=S256`;
347
+ }
348
+ getSessionToken(session) {
349
+ return (session ?? {})[this.connectorId] ?? {};
350
+ }
351
+ setSessionToken(session, token) {
352
+ session[this.connectorId] = token;
353
+ }
354
+ resetSessionToken(session) {
355
+ delete session[this.connectorId];
207
356
  }
208
357
  getOptions(formData) {
209
358
  return {}; // FIXME: store branch
@@ -215,7 +364,7 @@ class GitlabConnector {
215
364
  return null;
216
365
  }
217
366
  async isLoggedIn(session) {
218
- return !!session?.gitlab?.token;
367
+ return !!this.getSessionToken(session).token;
219
368
  }
220
369
  /**
221
370
  * Get the token from return code
@@ -223,13 +372,20 @@ class GitlabConnector {
223
372
  * OAuth2 Step #2 from https://docs.gitlab.com/ee/api/oauth2.html#authorization-code-with-proof-key-for-code-exchange-pkce
224
373
  */
225
374
  async setToken(session, loginResult) {
226
- if (!loginResult.state || loginResult.state !== session.gitlab?.state)
375
+ const sessionToken = this.getSessionToken(session);
376
+ if (!loginResult.state || loginResult.state !== sessionToken?.state) {
377
+ this.logout(session);
227
378
  throw new types_1.ApiError('Invalid state', 401);
228
- if (!session.gitlab?.codeVerifier)
379
+ }
380
+ if (!sessionToken?.codeVerifier) {
381
+ this.logout(session);
229
382
  throw new types_1.ApiError('Missing code verifier', 401);
230
- if (!session.gitlab?.codeChallenge)
383
+ }
384
+ if (!sessionToken?.codeChallenge) {
385
+ this.logout(session);
231
386
  throw new types_1.ApiError('Missing code challenge', 401);
232
- const token = await (0, node_fetch_1.default)('https://gitlab.com/oauth/token', {
387
+ }
388
+ const response = await (0, node_fetch_1.default)(this.options.domain + '/oauth/token', {
233
389
  method: 'POST',
234
390
  headers: {
235
391
  'Content-Type': 'application/json',
@@ -240,31 +396,70 @@ class GitlabConnector {
240
396
  code: loginResult.code,
241
397
  grant_type: 'authorization_code',
242
398
  redirect_uri: this.getRedirect(),
243
- code_verifier: session.gitlab.codeVerifier,
399
+ code_verifier: sessionToken.codeVerifier,
244
400
  }),
245
- })
246
- .then((response) => response.json());
247
- session.gitlab = { token, state: session.gitlab.state, codeVerifier: session.gitlab.codeVerifier, codeChallenge: session.gitlab.codeChallenge };
401
+ });
402
+ const token = await response.json();
403
+ // Store the token in the session
404
+ this.setSessionToken(session, {
405
+ token,
406
+ ...this.getSessionToken(session),
407
+ });
248
408
  // We need to get the user ID for listWebsites
249
409
  const user = await this.callApi(session, 'api/v4/user');
250
- session.gitlab.userId = user.id;
410
+ // Store the user details in the session
411
+ this.setSessionToken(session, {
412
+ ...this.getSessionToken(session),
413
+ userId: user.id,
414
+ username: user.username,
415
+ });
251
416
  }
252
417
  async logout(session) {
253
- delete session.gitlab;
418
+ this.resetSessionToken(session);
254
419
  }
255
420
  async getUser(session) {
256
421
  const user = await this.callApi(session, 'api/v4/user');
257
422
  return {
258
423
  name: user.name,
259
424
  email: user.email,
425
+ picture: user.avatar_url,
260
426
  storage: await (0, connectors_1.toConnectorData)(session, this),
261
427
  };
262
428
  }
263
429
  async listWebsites(session) {
264
- const projects = await this.callApi(session, `api/v4/users/${session.gitlab?.userId}/projects`);
265
- return projects.map(p => ({
430
+ //try {
431
+ // const result = await this.callApi(session, `api/v4/projects/${this.getMetaRepoPath(session)}/repository/files/${this.options.metaRepoFile}`, 'GET', null, {
432
+ // ref: this.options.branch,
433
+ // })
434
+ // const { content } = result
435
+ // const contentDecoded = Buffer.from(content, 'base64').toString('utf8')
436
+ // const websites = (JSON.parse(contentDecoded) as MetaRepoFileContent).websites
437
+ // return Object.entries(websites).map(([websiteId, {meta, createdAt, updatedAt}]) => ({
438
+ // websiteId,
439
+ // createdAt: new Date(createdAt),
440
+ // updatedAt: new Date(updatedAt),
441
+ // ...meta,
442
+ // }))
443
+ //} catch (e) {
444
+ // console.error('Could not list websites', e.statusCode, e.httpStatusCode, e.code)
445
+ // if (e.statusCode === 404 || e.httpStatusCode === 404) {
446
+ // await this.initStorage(session)
447
+ // return []
448
+ // } else {
449
+ // throw e
450
+ // }
451
+ //}
452
+ const userId = this.getSessionToken(session).userId;
453
+ if (!userId) {
454
+ this.logout(session);
455
+ throw new types_1.ApiError('Missing Gitlab user ID. User not logged in?', 401);
456
+ }
457
+ const projects = await this.callApi(session, `api/v4/users/${userId}/projects`);
458
+ return projects
459
+ .filter(p => p.name.startsWith(this.options.repoPrefix))
460
+ .map(p => ({
266
461
  websiteId: p.id,
267
- name: p.name,
462
+ name: p.name.replace(this.options.repoPrefix, ''),
268
463
  createdAt: p.created_at,
269
464
  updatedAt: p.last_activity_at,
270
465
  connectorUserSettings: {},
@@ -281,10 +476,10 @@ class GitlabConnector {
281
476
  }
282
477
  async createWebsite(session, websiteMeta) {
283
478
  const project = await this.callApi(session, 'api/v4/projects/', 'POST', {
284
- name: websiteMeta.name,
479
+ name: this.options.repoPrefix + websiteMeta.name,
285
480
  });
286
481
  await this.createFile(session, project.id, constants_1.WEBSITE_DATA_FILE, JSON.stringify({}));
287
- await this.createFile(session, project.id, constants_1.WEBSITE_META_DATA_FILE, JSON.stringify(websiteMeta));
482
+ //await this.createFile(session, project.id, WEBSITE_META_DATA_FILE, JSON.stringify(websiteMeta))
288
483
  //await this.updateWebsite(session, project.id, {} as WebsiteData)
289
484
  //await this.setWebsiteMeta(session, project.id, websiteMeta)
290
485
  return project.id;
@@ -294,68 +489,149 @@ class GitlabConnector {
294
489
  branch: this.options.branch,
295
490
  commit_message: 'Update website data from Silex',
296
491
  content: JSON.stringify(websiteData),
297
- file_path: constants_1.WEBSITE_DATA_FILE,
298
492
  id: websiteId,
299
493
  });
300
494
  }
301
495
  async deleteWebsite(session, websiteId) {
496
+ // Delete repo
302
497
  await this.callApi(session, `api/v4/projects/${websiteId}`, 'DELETE');
498
+ //// Load the meta repo data
499
+ //const file = await this.callApi(session, `api/v4/projects/${this.getMetaRepoPath(session)}/repository/files/${this.options.metaRepoFile}`, 'GET', null, {
500
+ // ref: this.options.branch,
501
+ //})
502
+ //const metaRepo = JSON.parse(Buffer.from(file.content, 'base64').toString('utf8')) as MetaRepoFileContent
503
+ //const data = metaRepo.websites[websiteId]
504
+ //if(!data) throw new ApiError(`Website ${websiteId} not found`, 404)
505
+ //// Update or create the website meta data
506
+ //delete metaRepo.websites[websiteId]
507
+ //// Save the meta repo data
508
+ //const project = await this.callApi(session, `api/v4/projects/${this.getMetaRepoPath(session)}/repository/files/${this.options.metaRepoFile}`, 'PUT', {
509
+ // branch: this.options.branch,
510
+ // commit_message: `Delete meta data of ${data.meta.name} (${websiteId}) from Silex`,
511
+ // content: JSON.stringify(metaRepo),
512
+ // file_path: this.options.metaRepoFile,
513
+ //})
514
+ }
515
+ async duplicateWebsite(session, websiteId) {
516
+ // Get the repo meta data
517
+ const meta = await this.getWebsiteMeta(session, websiteId);
518
+ // List all the repository files
519
+ const blobs = await this.callApi(session, `api/v4/projects/${websiteId}/repository/tree`, 'GET', null, {
520
+ recursive: true,
521
+ });
522
+ const files = blobs
523
+ .filter(item => item.type === 'blob')
524
+ .map(item => item.path);
525
+ // Create a new repo
526
+ const newId = await this.createWebsite(session, {
527
+ ...meta,
528
+ name: meta.name + ' Copy ' + new Date().toISOString().replace(/T.*/, '') + ' ' + Math.random().toString(36).substring(2, 4),
529
+ });
530
+ // Upload all files
531
+ for (const file of files) {
532
+ const path = encodeURIComponent(file);
533
+ const content = await this.readFile(session, websiteId, path);
534
+ // From buffer to string
535
+ const contentStr = content.toString('base64');
536
+ switch (file) {
537
+ case constants_1.WEBSITE_DATA_FILE:
538
+ await this.updateFile(session, newId, path, contentStr, true);
539
+ break;
540
+ default:
541
+ await this.createFile(session, newId, path, contentStr, true);
542
+ }
543
+ }
303
544
  }
304
545
  async getWebsiteMeta(session, websiteId) {
305
- const project = await this.callApi(session, `api/v4/projects/${websiteId}/repository/files/${constants_1.WEBSITE_META_DATA_FILE}`);
546
+ //const file = await this.callApi(session, `api/v4/projects/${this.getMetaRepoPath(session)}/repository/files/${this.options.metaRepoFile}`, 'GET', null, {
547
+ // ref: this.options.branch,
548
+ //})
549
+ //const metaRepo = JSON.parse(Buffer.from(file.content, 'base64').toString('utf8')) as MetaRepoFileContent
550
+ //if(!metaRepo.websites[websiteId]) throw new ApiError(`Website ${websiteId} not found`, 404)
551
+ //return {
552
+ // websiteId,
553
+ // createdAt: new Date(metaRepo.websites[websiteId].createdAt),
554
+ // updatedAt: new Date(metaRepo.websites[websiteId].updatedAt),
555
+ // ...metaRepo.websites[websiteId].meta,
556
+ //}
557
+ // const response = await this.callApi(session, `api/v4/projects/${websiteId}/repository/files/${WEBSITE_META_DATA_FILE}`, 'GET', null, {
558
+ // ref: this.options.branch,
559
+ // }) as any
560
+ // Base64 to string to JSON
561
+ // const contentDecoded = Buffer.from(response.content, 'base64').toString('utf8')
562
+ // const websiteMeta = JSON.parse(contentDecoded) as WebsiteMetaFileContent
563
+ const project = await this.callApi(session, `api/v4/projects/${websiteId}`);
306
564
  return {
307
- websiteId: project.id,
308
- name: project.name,
565
+ websiteId,
566
+ name: project.name.replace(this.options.repoPrefix, ''),
567
+ imageUrl: project.avatar_url,
309
568
  createdAt: project.created_at,
310
569
  updatedAt: project.last_activity_at,
311
570
  connectorUserSettings: {},
312
571
  };
313
572
  }
314
573
  async setWebsiteMeta(session, websiteId, websiteMeta) {
315
- const project = await this.callApi(session, `api/v4/projects/${websiteId}/repository/files/${constants_1.WEBSITE_META_DATA_FILE}`, 'PUT', {
316
- branch: this.options.branch,
317
- commit_message: 'Update website meta data from Silex',
318
- content: JSON.stringify(websiteMeta),
319
- file_path: constants_1.WEBSITE_META_DATA_FILE,
320
- id: websiteId,
321
- });
574
+ //// Load the meta repo data
575
+ //const file = await this.callApi(session, `api/v4/projects/${this.getMetaRepoPath(session)}/repository/files/${this.options.metaRepoFile}`, 'GET', null, {
576
+ // ref: this.options.branch,
577
+ //})
578
+ //const metaRepo = JSON.parse(Buffer.from(file.content, 'base64').toString('utf8')) as MetaRepoFileContent
579
+ //// Update or create the website meta data
580
+ //metaRepo.websites[websiteId] = {
581
+ // updatedAt: new Date().toISOString(),
582
+ // createdAt: metaRepo.websites[websiteId]?.createdAt ?? new Date().toISOString(),
583
+ // meta: websiteMeta,
584
+ //}
585
+ //// Save the meta repo data
586
+ //const project = await this.callApi(session, `api/v4/projects/${this.getMetaRepoPath(session)}/repository/files/${this.options.metaRepoFile}`, 'PUT', {
587
+ // branch: this.options.branch,
588
+ // commit_message: `Update website meta data of ${websiteMeta.name} (${websiteId}) from Silex`,
589
+ // content: JSON.stringify(metaRepo),
590
+ // file_path: this.options.metaRepoFile,
591
+ //})
592
+ // Rename the repo if needed
593
+ const oldMeta = await this.getWebsiteMeta(session, websiteId);
594
+ if (websiteMeta.name !== oldMeta.name) {
595
+ await this.callApi(session, `api/v4/projects/${websiteId}`, 'PUT', {
596
+ name: this.options.repoPrefix + websiteMeta.name,
597
+ });
598
+ }
599
+ //// Update the metadata file
600
+ //await this.callApi(session, `api/v4/projects/${websiteId}/repository/files/${WEBSITE_META_DATA_FILE}`, 'PUT', {
601
+ // branch: this.options.branch,
602
+ // commit_message: 'Update website meta data from Silex',
603
+ // content: JSON.stringify(websiteMeta),
604
+ // file_path: WEBSITE_META_DATA_FILE,
605
+ // id: websiteId,
606
+ //})
322
607
  }
323
608
  async writeAssets(session, websiteId, files, status) {
609
+ status && await status({ message: 'in progress...', status: types_1.JobStatus.IN_PROGRESS });
324
610
  // For each file
325
611
  for (const file of files) {
326
612
  // Convert to base64
327
613
  const content = (await (0, connectors_1.contentToBuffer)(file.content)).toString('base64');
614
+ const path = this.getAssetPath(file.path);
328
615
  try {
329
- await this.updateFile(session, websiteId, this.getAssetPath(file.path), content, true);
616
+ await this.updateFile(session, websiteId, path, content, true);
330
617
  }
331
618
  catch (e) {
332
619
  // If the file does not exist, create it
333
- if (e.statusCode === 404 || e.message.endsWith('A file with this name doesn\'t exist')) {
334
- await this.createFile(session, websiteId, file.path, content, true);
620
+ if (e.statusCode === 404 || e.httpStatusCode === 404 || e.message.endsWith('A file with this name doesn\'t exist')) {
621
+ await this.createFile(session, websiteId, path, content, true);
335
622
  }
336
623
  else {
624
+ status && await status({ message: 'Error', status: types_1.JobStatus.ERROR });
337
625
  throw e;
338
626
  }
339
627
  }
340
628
  }
629
+ status && await status({ message: 'Successfull', status: types_1.JobStatus.SUCCESS });
341
630
  }
342
631
  async readAsset(session, websiteId, fileName) {
343
632
  // Remove leading slash
344
633
  const finalPath = this.getAssetPath(fileName);
345
- // Call the API
346
- const url = `https://gitlab.com/api/v4/projects/${websiteId}/repository/files/${finalPath}?ref=${this.options.branch}&access_token=${session.gitlab?.token?.access_token}`;
347
- const response = await (0, node_fetch_1.default)(url, {
348
- method: 'GET',
349
- headers: {
350
- 'Content-Type': 'application/json',
351
- },
352
- });
353
- const json = await response.json();
354
- if (!response.ok)
355
- throw new types_1.ApiError(`Gitlab API error: ${json?.message ?? json?.error ?? response.statusText}`, response.status);
356
- // From base64 string to buffer
357
- const buf = Buffer.from(json.content, 'base64');
358
- return buf;
634
+ return this.readFile(session, websiteId, finalPath);
359
635
  }
360
636
  async deleteAssets(session, websiteId, fileNames) {
361
637
  return this.callApi(session, `api/v4/projects/${websiteId}/repository/commits`, 'POST', {