@pranaysahith/decap-cms-core 3.9.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 (299) hide show
  1. package/README.md +9 -0
  2. package/dist/@pranaysahith/decap-cms-core.js +52 -0
  3. package/dist/@pranaysahith/decap-cms-core.js.LICENSE.txt +141 -0
  4. package/dist/@pranaysahith/decap-cms-core.js.map +1 -0
  5. package/dist/decap-cms-core.js +47 -0
  6. package/dist/decap-cms-core.js.LICENSE.txt +116 -0
  7. package/dist/decap-cms-core.js.map +1 -0
  8. package/dist/esm/actions/auth.js +97 -0
  9. package/dist/esm/actions/collections.js +15 -0
  10. package/dist/esm/actions/config.js +493 -0
  11. package/dist/esm/actions/deploys.js +79 -0
  12. package/dist/esm/actions/editorialWorkflow.js +480 -0
  13. package/dist/esm/actions/entries.js +865 -0
  14. package/dist/esm/actions/media.js +147 -0
  15. package/dist/esm/actions/mediaLibrary.js +552 -0
  16. package/dist/esm/actions/notifications.js +21 -0
  17. package/dist/esm/actions/search.js +149 -0
  18. package/dist/esm/actions/status.js +74 -0
  19. package/dist/esm/actions/waitUntil.js +32 -0
  20. package/dist/esm/backend.js +1082 -0
  21. package/dist/esm/bootstrap.js +101 -0
  22. package/dist/esm/components/App/App.js +289 -0
  23. package/dist/esm/components/App/Header.js +172 -0
  24. package/dist/esm/components/App/NotFoundPage.js +19 -0
  25. package/dist/esm/components/Collection/Collection.js +198 -0
  26. package/dist/esm/components/Collection/CollectionControls.js +46 -0
  27. package/dist/esm/components/Collection/CollectionSearch.js +222 -0
  28. package/dist/esm/components/Collection/CollectionTop.js +68 -0
  29. package/dist/esm/components/Collection/ControlButton.js +17 -0
  30. package/dist/esm/components/Collection/Entries/Entries.js +73 -0
  31. package/dist/esm/components/Collection/Entries/EntriesCollection.js +241 -0
  32. package/dist/esm/components/Collection/Entries/EntriesSearch.js +113 -0
  33. package/dist/esm/components/Collection/Entries/EntryCard.js +177 -0
  34. package/dist/esm/components/Collection/Entries/EntryListing.js +143 -0
  35. package/dist/esm/components/Collection/FilterControl.js +33 -0
  36. package/dist/esm/components/Collection/FolderRenameControl.js +403 -0
  37. package/dist/esm/components/Collection/GroupControl.js +33 -0
  38. package/dist/esm/components/Collection/NestedCollection.js +308 -0
  39. package/dist/esm/components/Collection/Sidebar.js +91 -0
  40. package/dist/esm/components/Collection/SortControl.js +59 -0
  41. package/dist/esm/components/Collection/ViewStyleControl.js +38 -0
  42. package/dist/esm/components/Editor/Editor.js +466 -0
  43. package/dist/esm/components/Editor/EditorControlPane/EditorControl.js +395 -0
  44. package/dist/esm/components/Editor/EditorControlPane/EditorControlPane.js +254 -0
  45. package/dist/esm/components/Editor/EditorControlPane/Widget.js +374 -0
  46. package/dist/esm/components/Editor/EditorInterface.js +386 -0
  47. package/dist/esm/components/Editor/EditorPreviewPane/EditorPreview.js +47 -0
  48. package/dist/esm/components/Editor/EditorPreviewPane/EditorPreviewContent.js +66 -0
  49. package/dist/esm/components/Editor/EditorPreviewPane/EditorPreviewPane.js +288 -0
  50. package/dist/esm/components/Editor/EditorPreviewPane/PreviewHOC.js +27 -0
  51. package/dist/esm/components/Editor/EditorToolbar.js +536 -0
  52. package/dist/esm/components/Editor/EntryPathEditor.js +272 -0
  53. package/dist/esm/components/Editor/withWorkflow.js +56 -0
  54. package/dist/esm/components/EditorWidgets/Unknown/UnknownControl.js +18 -0
  55. package/dist/esm/components/EditorWidgets/Unknown/UnknownPreview.js +20 -0
  56. package/dist/esm/components/EditorWidgets/index.js +4 -0
  57. package/dist/esm/components/MediaLibrary/EmptyMessage.js +22 -0
  58. package/dist/esm/components/MediaLibrary/MediaLibrary.js +446 -0
  59. package/dist/esm/components/MediaLibrary/MediaLibraryButtons.js +93 -0
  60. package/dist/esm/components/MediaLibrary/MediaLibraryCard.js +99 -0
  61. package/dist/esm/components/MediaLibrary/MediaLibraryCardGrid.js +198 -0
  62. package/dist/esm/components/MediaLibrary/MediaLibraryHeader.js +32 -0
  63. package/dist/esm/components/MediaLibrary/MediaLibraryModal.js +156 -0
  64. package/dist/esm/components/MediaLibrary/MediaLibrarySearch.js +51 -0
  65. package/dist/esm/components/MediaLibrary/MediaLibraryTop.js +123 -0
  66. package/dist/esm/components/UI/DragDrop.js +67 -0
  67. package/dist/esm/components/UI/ErrorBoundary.js +173 -0
  68. package/dist/esm/components/UI/FileUploadButton.js +27 -0
  69. package/dist/esm/components/UI/Modal.js +104 -0
  70. package/dist/esm/components/UI/Notifications.js +62 -0
  71. package/dist/esm/components/UI/SettingsDropdown.js +107 -0
  72. package/dist/esm/components/UI/index.js +6 -0
  73. package/dist/esm/components/Workflow/Workflow.js +133 -0
  74. package/dist/esm/components/Workflow/WorkflowCard.js +128 -0
  75. package/dist/esm/components/Workflow/WorkflowList.js +204 -0
  76. package/dist/esm/constants/collectionTypes.js +2 -0
  77. package/dist/esm/constants/collectionViews.js +2 -0
  78. package/dist/esm/constants/commitProps.js +2 -0
  79. package/dist/esm/constants/configSchema.js +644 -0
  80. package/dist/esm/constants/fieldInference.js +57 -0
  81. package/dist/esm/constants/publishModes.js +18 -0
  82. package/dist/esm/constants/validationErrorTypes.js +6 -0
  83. package/dist/esm/formats/formats.js +83 -0
  84. package/dist/esm/formats/frontmatter.js +146 -0
  85. package/dist/esm/formats/helpers.js +12 -0
  86. package/dist/esm/formats/json.js +8 -0
  87. package/dist/esm/formats/toml.js +32 -0
  88. package/dist/esm/formats/yaml.js +51 -0
  89. package/dist/esm/index.js +7 -0
  90. package/dist/esm/integrations/index.js +28 -0
  91. package/dist/esm/integrations/providers/algolia/implementation.js +174 -0
  92. package/dist/esm/integrations/providers/assetStore/implementation.js +165 -0
  93. package/dist/esm/lib/consoleError.js +3 -0
  94. package/dist/esm/lib/formatters.js +191 -0
  95. package/dist/esm/lib/i18n.js +367 -0
  96. package/dist/esm/lib/phrases.js +6 -0
  97. package/dist/esm/lib/polyfill.js +8 -0
  98. package/dist/esm/lib/registry.js +329 -0
  99. package/dist/esm/lib/serializeEntryValues.js +67 -0
  100. package/dist/esm/lib/stega.js +142 -0
  101. package/dist/esm/lib/textHelper.js +9 -0
  102. package/dist/esm/lib/urlHelper.js +111 -0
  103. package/dist/esm/mediaLibrary.js +37 -0
  104. package/dist/esm/reducers/auth.js +27 -0
  105. package/dist/esm/reducers/collections.js +428 -0
  106. package/dist/esm/reducers/combinedReducer.js +8 -0
  107. package/dist/esm/reducers/config.js +29 -0
  108. package/dist/esm/reducers/cursors.js +31 -0
  109. package/dist/esm/reducers/deploys.js +45 -0
  110. package/dist/esm/reducers/editorialWorkflow.js +83 -0
  111. package/dist/esm/reducers/entries.js +568 -0
  112. package/dist/esm/reducers/entryDraft.js +212 -0
  113. package/dist/esm/reducers/globalUI.js +25 -0
  114. package/dist/esm/reducers/index.js +66 -0
  115. package/dist/esm/reducers/integrations.js +53 -0
  116. package/dist/esm/reducers/mediaLibrary.js +252 -0
  117. package/dist/esm/reducers/medias.js +68 -0
  118. package/dist/esm/reducers/notifications.js +23 -0
  119. package/dist/esm/reducers/search.js +92 -0
  120. package/dist/esm/reducers/status.js +30 -0
  121. package/dist/esm/redux/index.js +7 -0
  122. package/dist/esm/redux/middleware/waitUntilAction.js +48 -0
  123. package/dist/esm/routing/history.js +12 -0
  124. package/dist/esm/types/diacritics.d.js +0 -0
  125. package/dist/esm/types/global.d.js +1 -0
  126. package/dist/esm/types/immutable.js +7 -0
  127. package/dist/esm/types/redux.js +14 -0
  128. package/dist/esm/types/tomlify-j0.4.d.js +0 -0
  129. package/dist/esm/valueObjects/AssetProxy.js +44 -0
  130. package/dist/esm/valueObjects/EditorComponent.js +34 -0
  131. package/dist/esm/valueObjects/Entry.js +20 -0
  132. package/index.d.ts +618 -0
  133. package/package.json +106 -0
  134. package/src/__tests__/backend.spec.js +1161 -0
  135. package/src/actions/__tests__/config.spec.js +1009 -0
  136. package/src/actions/__tests__/editorialWorkflow.spec.js +216 -0
  137. package/src/actions/__tests__/entries.spec.js +596 -0
  138. package/src/actions/__tests__/media.spec.ts +171 -0
  139. package/src/actions/__tests__/mediaLibrary.spec.js +327 -0
  140. package/src/actions/__tests__/search.spec.js +209 -0
  141. package/src/actions/auth.ts +127 -0
  142. package/src/actions/collections.ts +18 -0
  143. package/src/actions/config.ts +565 -0
  144. package/src/actions/deploys.ts +104 -0
  145. package/src/actions/editorialWorkflow.ts +567 -0
  146. package/src/actions/entries.ts +1055 -0
  147. package/src/actions/media.ts +139 -0
  148. package/src/actions/mediaLibrary.ts +574 -0
  149. package/src/actions/notifications.ts +36 -0
  150. package/src/actions/search.ts +221 -0
  151. package/src/actions/status.ts +99 -0
  152. package/src/actions/waitUntil.ts +49 -0
  153. package/src/backend.ts +1400 -0
  154. package/src/bootstrap.js +104 -0
  155. package/src/components/App/App.js +286 -0
  156. package/src/components/App/Header.js +266 -0
  157. package/src/components/App/NotFoundPage.js +23 -0
  158. package/src/components/Collection/Collection.js +210 -0
  159. package/src/components/Collection/CollectionControls.js +58 -0
  160. package/src/components/Collection/CollectionSearch.js +243 -0
  161. package/src/components/Collection/CollectionTop.js +81 -0
  162. package/src/components/Collection/ControlButton.js +27 -0
  163. package/src/components/Collection/Entries/Entries.js +82 -0
  164. package/src/components/Collection/Entries/EntriesCollection.js +277 -0
  165. package/src/components/Collection/Entries/EntriesSearch.js +102 -0
  166. package/src/components/Collection/Entries/EntryCard.js +246 -0
  167. package/src/components/Collection/Entries/EntryListing.js +151 -0
  168. package/src/components/Collection/Entries/__tests__/EntriesCollection.spec.js +163 -0
  169. package/src/components/Collection/Entries/__tests__/__snapshots__/EntriesCollection.spec.js.snap +46 -0
  170. package/src/components/Collection/FilterControl.js +39 -0
  171. package/src/components/Collection/GroupControl.js +39 -0
  172. package/src/components/Collection/NestedCollection.js +330 -0
  173. package/src/components/Collection/Sidebar.js +136 -0
  174. package/src/components/Collection/SortControl.js +68 -0
  175. package/src/components/Collection/ViewStyleControl.js +50 -0
  176. package/src/components/Collection/__tests__/Collection.spec.js +75 -0
  177. package/src/components/Collection/__tests__/NestedCollection.spec.js +445 -0
  178. package/src/components/Collection/__tests__/Sidebar.spec.js +87 -0
  179. package/src/components/Collection/__tests__/__snapshots__/Collection.spec.js.snap +144 -0
  180. package/src/components/Collection/__tests__/__snapshots__/NestedCollection.spec.js.snap +550 -0
  181. package/src/components/Collection/__tests__/__snapshots__/Sidebar.spec.js.snap +312 -0
  182. package/src/components/Editor/Editor.js +497 -0
  183. package/src/components/Editor/EditorControlPane/EditorControl.js +452 -0
  184. package/src/components/Editor/EditorControlPane/EditorControlPane.js +269 -0
  185. package/src/components/Editor/EditorControlPane/Widget.js +384 -0
  186. package/src/components/Editor/EditorInterface.js +444 -0
  187. package/src/components/Editor/EditorPreviewPane/EditorPreview.js +40 -0
  188. package/src/components/Editor/EditorPreviewPane/EditorPreviewContent.js +74 -0
  189. package/src/components/Editor/EditorPreviewPane/EditorPreviewPane.js +333 -0
  190. package/src/components/Editor/EditorPreviewPane/PreviewHOC.js +33 -0
  191. package/src/components/Editor/EditorToolbar.js +691 -0
  192. package/src/components/Editor/__tests__/Editor.spec.js +221 -0
  193. package/src/components/Editor/__tests__/EditorToolbar.spec.js +120 -0
  194. package/src/components/Editor/__tests__/__snapshots__/Editor.spec.js.snap +45 -0
  195. package/src/components/Editor/__tests__/__snapshots__/EditorToolbar.spec.js.snap +4233 -0
  196. package/src/components/Editor/withWorkflow.js +61 -0
  197. package/src/components/EditorWidgets/Unknown/UnknownControl.js +17 -0
  198. package/src/components/EditorWidgets/Unknown/UnknownPreview.js +19 -0
  199. package/src/components/EditorWidgets/index.js +5 -0
  200. package/src/components/MediaLibrary/EmptyMessage.js +28 -0
  201. package/src/components/MediaLibrary/MediaLibrary.js +411 -0
  202. package/src/components/MediaLibrary/MediaLibraryButtons.js +136 -0
  203. package/src/components/MediaLibrary/MediaLibraryCard.js +128 -0
  204. package/src/components/MediaLibrary/MediaLibraryCardGrid.js +199 -0
  205. package/src/components/MediaLibrary/MediaLibraryHeader.js +48 -0
  206. package/src/components/MediaLibrary/MediaLibraryModal.js +200 -0
  207. package/src/components/MediaLibrary/MediaLibrarySearch.js +61 -0
  208. package/src/components/MediaLibrary/MediaLibraryTop.js +143 -0
  209. package/src/components/MediaLibrary/__tests__/MediaLibraryButtons.spec.js +45 -0
  210. package/src/components/MediaLibrary/__tests__/MediaLibraryCard.spec.js +49 -0
  211. package/src/components/MediaLibrary/__tests__/__snapshots__/MediaLibraryCard.spec.js.snap +264 -0
  212. package/src/components/UI/DragDrop.js +66 -0
  213. package/src/components/UI/ErrorBoundary.js +214 -0
  214. package/src/components/UI/FileUploadButton.js +24 -0
  215. package/src/components/UI/Modal.js +112 -0
  216. package/src/components/UI/Notifications.tsx +83 -0
  217. package/src/components/UI/SettingsDropdown.js +103 -0
  218. package/src/components/UI/__tests__/ErrorBoundary.spec.js +57 -0
  219. package/src/components/UI/index.js +6 -0
  220. package/src/components/Workflow/Workflow.js +169 -0
  221. package/src/components/Workflow/WorkflowCard.js +177 -0
  222. package/src/components/Workflow/WorkflowList.js +272 -0
  223. package/src/constants/__tests__/configSchema.spec.js +611 -0
  224. package/src/constants/collectionTypes.ts +2 -0
  225. package/src/constants/collectionViews.js +2 -0
  226. package/src/constants/commitProps.ts +2 -0
  227. package/src/constants/configSchema.js +441 -0
  228. package/src/constants/fieldInference.tsx +78 -0
  229. package/src/constants/publishModes.ts +22 -0
  230. package/src/constants/validationErrorTypes.js +6 -0
  231. package/src/formats/__tests__/formats.spec.js +87 -0
  232. package/src/formats/__tests__/frontmatter.spec.js +429 -0
  233. package/src/formats/__tests__/toml.spec.js +9 -0
  234. package/src/formats/__tests__/yaml.spec.js +162 -0
  235. package/src/formats/formats.ts +97 -0
  236. package/src/formats/frontmatter.ts +150 -0
  237. package/src/formats/helpers.ts +14 -0
  238. package/src/formats/json.ts +9 -0
  239. package/src/formats/toml.ts +33 -0
  240. package/src/formats/yaml.ts +58 -0
  241. package/src/index.js +8 -0
  242. package/src/integrations/index.js +35 -0
  243. package/src/integrations/providers/algolia/implementation.js +176 -0
  244. package/src/integrations/providers/assetStore/implementation.js +148 -0
  245. package/src/lib/__tests__/formatters.spec.js +751 -0
  246. package/src/lib/__tests__/i18n.spec.js +792 -0
  247. package/src/lib/__tests__/phrases.spec.js +119 -0
  248. package/src/lib/__tests__/registry.spec.js +261 -0
  249. package/src/lib/__tests__/serializeEntryValues.spec.js +22 -0
  250. package/src/lib/__tests__/urlHelper.spec.js +138 -0
  251. package/src/lib/consoleError.js +7 -0
  252. package/src/lib/formatters.ts +286 -0
  253. package/src/lib/i18n.ts +454 -0
  254. package/src/lib/phrases.js +8 -0
  255. package/src/lib/polyfill.js +9 -0
  256. package/src/lib/registry.js +312 -0
  257. package/src/lib/serializeEntryValues.js +75 -0
  258. package/src/lib/stega.ts +145 -0
  259. package/src/lib/textHelper.js +11 -0
  260. package/src/lib/urlHelper.ts +128 -0
  261. package/src/mediaLibrary.ts +51 -0
  262. package/src/reducers/__tests__/auth.spec.ts +38 -0
  263. package/src/reducers/__tests__/collections.spec.js +610 -0
  264. package/src/reducers/__tests__/config.spec.js +38 -0
  265. package/src/reducers/__tests__/entries.spec.js +694 -0
  266. package/src/reducers/__tests__/entryDraft.spec.js +297 -0
  267. package/src/reducers/__tests__/globalUI.js +43 -0
  268. package/src/reducers/__tests__/integrations.spec.ts +76 -0
  269. package/src/reducers/__tests__/mediaLibrary.spec.js +154 -0
  270. package/src/reducers/__tests__/medias.spec.ts +49 -0
  271. package/src/reducers/auth.ts +46 -0
  272. package/src/reducers/collections.ts +535 -0
  273. package/src/reducers/combinedReducer.ts +11 -0
  274. package/src/reducers/config.ts +38 -0
  275. package/src/reducers/cursors.js +36 -0
  276. package/src/reducers/deploys.ts +52 -0
  277. package/src/reducers/editorialWorkflow.ts +163 -0
  278. package/src/reducers/entries.ts +819 -0
  279. package/src/reducers/entryDraft.js +260 -0
  280. package/src/reducers/globalUI.ts +45 -0
  281. package/src/reducers/index.ts +82 -0
  282. package/src/reducers/integrations.ts +59 -0
  283. package/src/reducers/mediaLibrary.ts +296 -0
  284. package/src/reducers/medias.ts +66 -0
  285. package/src/reducers/notifications.ts +52 -0
  286. package/src/reducers/search.ts +111 -0
  287. package/src/reducers/status.ts +40 -0
  288. package/src/redux/index.ts +18 -0
  289. package/src/redux/middleware/waitUntilAction.ts +64 -0
  290. package/src/routing/__tests__/history.spec.ts +49 -0
  291. package/src/routing/history.ts +17 -0
  292. package/src/types/diacritics.d.ts +1 -0
  293. package/src/types/global.d.ts +8 -0
  294. package/src/types/immutable.ts +49 -0
  295. package/src/types/redux.ts +827 -0
  296. package/src/types/tomlify-j0.4.d.ts +13 -0
  297. package/src/valueObjects/AssetProxy.ts +48 -0
  298. package/src/valueObjects/EditorComponent.js +38 -0
  299. package/src/valueObjects/Entry.ts +63 -0
@@ -0,0 +1,150 @@
1
+ import matter from 'gray-matter';
2
+
3
+ import tomlFormatter from './toml';
4
+ import yamlFormatter from './yaml';
5
+ import jsonFormatter from './json';
6
+
7
+ const Languages = {
8
+ YAML: 'yaml',
9
+ TOML: 'toml',
10
+ JSON: 'json',
11
+ } as const;
12
+
13
+ type Language = (typeof Languages)[keyof typeof Languages];
14
+
15
+ export type Delimiter = string | [string, string];
16
+ type Format = { language: Language; delimiters: Delimiter };
17
+
18
+ const parsers = {
19
+ toml: {
20
+ parse: (input: string) => tomlFormatter.fromFile(input),
21
+ stringify: (metadata: object, opts?: { sortedKeys?: string[] }) => {
22
+ const { sortedKeys } = opts || {};
23
+ return tomlFormatter.toFile(metadata, sortedKeys);
24
+ },
25
+ },
26
+ json: {
27
+ parse: (input: string) => {
28
+ let JSONinput = input.trim();
29
+ // Fix JSON if leading and trailing brackets were trimmed.
30
+ if (JSONinput.slice(0, 1) !== '{') {
31
+ JSONinput = '{' + JSONinput + '}';
32
+ }
33
+ return jsonFormatter.fromFile(JSONinput);
34
+ },
35
+ stringify: (metadata: object) => {
36
+ let JSONoutput = jsonFormatter.toFile(metadata).trim();
37
+ // Trim leading and trailing brackets.
38
+ if (JSONoutput.slice(0, 1) === '{' && JSONoutput.slice(-1) === '}') {
39
+ JSONoutput = JSONoutput.slice(1, -1);
40
+ }
41
+ return JSONoutput;
42
+ },
43
+ },
44
+ yaml: {
45
+ parse: (input: string) => yamlFormatter.fromFile(input),
46
+ stringify: (
47
+ metadata: object,
48
+ opts?: { sortedKeys?: string[]; comments?: Record<string, string> },
49
+ ) => {
50
+ const { sortedKeys, comments } = opts || {};
51
+ return yamlFormatter.toFile(metadata, sortedKeys, comments);
52
+ },
53
+ },
54
+ };
55
+
56
+ function inferFrontmatterFormat(str: string) {
57
+ const lineEnd = str.indexOf('\n');
58
+ const firstLine = str.slice(0, lineEnd !== -1 ? lineEnd : 0).trim();
59
+ if (firstLine.length > 3 && firstLine.slice(0, 3) === '---') {
60
+ // No need to infer, `gray-matter` will handle things like `---toml` for us.
61
+ return;
62
+ }
63
+ switch (firstLine) {
64
+ case '---':
65
+ return getFormatOpts(Languages.YAML);
66
+ case '+++':
67
+ return getFormatOpts(Languages.TOML);
68
+ case '{':
69
+ return getFormatOpts(Languages.JSON);
70
+ default:
71
+ console.warn('Unrecognized front-matter format.');
72
+ }
73
+ }
74
+
75
+ export function getFormatOpts(format?: Language, customDelimiter?: Delimiter) {
76
+ if (!format) {
77
+ return undefined;
78
+ }
79
+
80
+ const formats: { [key in Language]: Format } = {
81
+ yaml: { language: Languages.YAML, delimiters: '---' },
82
+ toml: { language: Languages.TOML, delimiters: '+++' },
83
+ json: { language: Languages.JSON, delimiters: ['{', '}'] },
84
+ };
85
+
86
+ const { language, delimiters } = formats[format];
87
+
88
+ return {
89
+ language,
90
+ delimiters: customDelimiter || delimiters,
91
+ };
92
+ }
93
+
94
+ export class FrontmatterFormatter {
95
+ format?: Format;
96
+
97
+ constructor(format?: Language, customDelimiter?: Delimiter) {
98
+ this.format = getFormatOpts(format, customDelimiter);
99
+ }
100
+
101
+ fromFile(content: string) {
102
+ const format = this.format || inferFrontmatterFormat(content);
103
+ const result = matter(content, { engines: parsers, ...format });
104
+ // in the absent of a body when serializing an entry we use an empty one
105
+ // when calling `toFile`, so we don't want to add it when parsing.
106
+ return {
107
+ ...result.data,
108
+ ...(result.content.trim() && { body: result.content }),
109
+ };
110
+ }
111
+
112
+ toFile(
113
+ data: { body?: string } & Record<string, unknown>,
114
+ sortedKeys?: string[],
115
+ comments?: Record<string, string>,
116
+ ) {
117
+ const { body = '', ...meta } = data;
118
+
119
+ // Stringify to YAML if the format was not set
120
+ const format = this.format || getFormatOpts(Languages.YAML);
121
+
122
+ // gray-matter always adds a line break at the end which trips our
123
+ // change detection logic
124
+ // https://github.com/jonschlinkert/gray-matter/issues/96
125
+ const trimLastLineBreak = body.slice(-1) !== '\n';
126
+ const file = matter.stringify(body, meta, {
127
+ engines: parsers,
128
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
129
+ // @ts-ignore `sortedKeys` is not recognized by gray-matter, so it gets passed through to the parser
130
+ sortedKeys,
131
+ comments,
132
+ ...format,
133
+ });
134
+ return trimLastLineBreak && file.slice(-1) === '\n' ? file.slice(0, -1) : file;
135
+ }
136
+ }
137
+
138
+ export const FrontmatterInfer = new FrontmatterFormatter();
139
+
140
+ export function frontmatterYAML(customDelimiter?: Delimiter) {
141
+ return new FrontmatterFormatter(Languages.YAML, customDelimiter);
142
+ }
143
+
144
+ export function frontmatterTOML(customDelimiter?: Delimiter) {
145
+ return new FrontmatterFormatter(Languages.TOML, customDelimiter);
146
+ }
147
+
148
+ export function frontmatterJSON(customDelimiter?: Delimiter) {
149
+ return new FrontmatterFormatter(Languages.JSON, customDelimiter);
150
+ }
@@ -0,0 +1,14 @@
1
+ export function sortKeys<Item>(
2
+ sortedKeys: string[],
3
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4
+ selector: (a: Item) => string = (a: any) => a,
5
+ ) {
6
+ return (a: Item, b: Item) => {
7
+ const idxA = sortedKeys.indexOf(selector(a));
8
+ const idxB = sortedKeys.indexOf(selector(b));
9
+ if (idxA === -1 || idxB === -1) return 0;
10
+ if (idxA > idxB) return 1;
11
+ if (idxA < idxB) return -1;
12
+ return 0;
13
+ };
14
+ }
@@ -0,0 +1,9 @@
1
+ export default {
2
+ fromFile(content: string) {
3
+ return JSON.parse(content);
4
+ },
5
+
6
+ toFile(data: object) {
7
+ return JSON.stringify(data, null, 2);
8
+ },
9
+ };
@@ -0,0 +1,33 @@
1
+ import parseToml from '@iarna/toml/parse-string';
2
+ import tomlify from 'tomlify-j0.4';
3
+ import dayjs from 'dayjs';
4
+
5
+ import AssetProxy from '../valueObjects/AssetProxy';
6
+ import { sortKeys } from './helpers';
7
+
8
+ function outputReplacer(_key: string, value: unknown) {
9
+ if (dayjs.isDayjs(value)) {
10
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
11
+ // @ts-ignore
12
+ return value.format(value._f);
13
+ }
14
+ if (value instanceof AssetProxy) {
15
+ return `${value.path}`;
16
+ }
17
+ if (typeof value === 'number' && Number.isInteger(value)) {
18
+ // Return the string representation of integers so tomlify won't render with tenths (".0")
19
+ return value.toString();
20
+ }
21
+ // Return `false` to use default (`undefined` would delete key).
22
+ return false;
23
+ }
24
+
25
+ export default {
26
+ fromFile(content: string) {
27
+ return parseToml(content);
28
+ },
29
+
30
+ toFile(data: object, sortedKeys: string[] = []) {
31
+ return tomlify.toToml(data, { replace: outputReplacer, sort: sortKeys(sortedKeys) });
32
+ },
33
+ };
@@ -0,0 +1,58 @@
1
+ import yaml from 'yaml';
2
+
3
+ import { sortKeys } from './helpers';
4
+
5
+ import type { YAMLMap, YAMLSeq, Pair, Node } from 'yaml/types';
6
+
7
+ function addComments(items: Array<Pair>, comments: Record<string, string>, prefix = '') {
8
+ items.forEach(item => {
9
+ if (item.key !== undefined) {
10
+ const itemKey = item.key.toString();
11
+ const key = prefix ? `${prefix}.${itemKey}` : itemKey;
12
+ if (comments[key]) {
13
+ const value = comments[key].split('\\n').join('\n ');
14
+ item.commentBefore = ` ${value}`;
15
+ }
16
+ if (Array.isArray(item.value?.items)) {
17
+ addComments(item.value.items, comments, key);
18
+ }
19
+ }
20
+ });
21
+ }
22
+
23
+ const timestampTag = {
24
+ identify: (value: unknown) => value instanceof Date,
25
+ default: true,
26
+ tag: '!timestamp',
27
+ test: RegExp(
28
+ '^' +
29
+ '([0-9]{4})-([0-9]{2})-([0-9]{2})' + // YYYY-MM-DD
30
+ 'T' + // T
31
+ '([0-9]{2}):([0-9]{2}):([0-9]{2}(\\.[0-9]+)?)' + // HH:MM:SS(.ss)?
32
+ 'Z' + // Z
33
+ '$',
34
+ ),
35
+ resolve: (str: string) => new Date(str),
36
+ stringify: (value: Node) => (value as Date).toISOString(),
37
+ } as const;
38
+
39
+ export default {
40
+ fromFile(content: string) {
41
+ if (content && content.trim().endsWith('---')) {
42
+ content = content.trim().slice(0, -3);
43
+ }
44
+ return yaml.parse(content, { customTags: [timestampTag] });
45
+ },
46
+
47
+ toFile(data: object, sortedKeys: string[] = [], comments: Record<string, string> = {}) {
48
+ const contents = yaml.createNode(data) as YAMLMap | YAMLSeq;
49
+
50
+ addComments(contents.items, comments);
51
+
52
+ contents.items.sort(sortKeys(sortedKeys, item => item.key?.toString()));
53
+ const doc = new yaml.Document();
54
+ doc.contents = contents;
55
+
56
+ return doc.toString();
57
+ },
58
+ };
package/src/index.js ADDED
@@ -0,0 +1,8 @@
1
+ import bootstrap from './bootstrap';
2
+ import Registry from './lib/registry';
3
+
4
+ export const DecapCmsCore = {
5
+ ...Registry,
6
+ init: bootstrap,
7
+ };
8
+ export default DecapCmsCore;
@@ -0,0 +1,35 @@
1
+ import { Map } from 'immutable';
2
+
3
+ import Algolia from './providers/algolia/implementation';
4
+ import AssetStore from './providers/assetStore/implementation';
5
+
6
+ export function resolveIntegrations(integrationsConfig, getToken) {
7
+ let integrationInstances = Map({});
8
+ integrationsConfig.get('providers').forEach((providerData, providerName) => {
9
+ switch (providerName) {
10
+ case 'algolia':
11
+ integrationInstances = integrationInstances.set('algolia', new Algolia(providerData));
12
+ break;
13
+ case 'assetStore':
14
+ integrationInstances = integrationInstances.set(
15
+ 'assetStore',
16
+ new AssetStore(providerData, getToken),
17
+ );
18
+ break;
19
+ }
20
+ });
21
+ return integrationInstances;
22
+ }
23
+
24
+ export const getIntegrationProvider = (function () {
25
+ let integrations = null;
26
+
27
+ return (integrationsConfig, getToken, provider) => {
28
+ if (integrations) {
29
+ return integrations.get(provider);
30
+ } else {
31
+ integrations = resolveIntegrations(integrationsConfig, getToken);
32
+ return integrations.get(provider);
33
+ }
34
+ };
35
+ })();
@@ -0,0 +1,176 @@
1
+ import flatten from 'lodash/flatten';
2
+ import { unsentRequest } from 'decap-cms-lib-util';
3
+
4
+ import { createEntry } from '../../../valueObjects/Entry';
5
+ import { selectEntrySlug } from '../../../reducers/collections';
6
+
7
+ const { fetchWithTimeout: fetch } = unsentRequest;
8
+
9
+ function getSlug(path) {
10
+ return path
11
+ .split('/')
12
+ .pop()
13
+ .replace(/\.[^.]+$/, '');
14
+ }
15
+
16
+ export default class Algolia {
17
+ constructor(config) {
18
+ this.config = config;
19
+ if (config.get('applicationID') == null || config.get('apiKey') == null) {
20
+ throw 'The Algolia search integration needs the credentials (applicationID and apiKey) in the integration configuration.';
21
+ }
22
+
23
+ this.applicationID = config.get('applicationID');
24
+ this.apiKey = config.get('apiKey');
25
+
26
+ const prefix = config.get('indexPrefix');
27
+ this.indexPrefix = prefix ? `${prefix}-` : '';
28
+
29
+ this.searchURL = `https://${this.applicationID}-dsn.algolia.net/1`;
30
+
31
+ this.entriesCache = {
32
+ collection: null,
33
+ page: null,
34
+ entries: [],
35
+ };
36
+ }
37
+
38
+ requestHeaders(headers = {}) {
39
+ return {
40
+ 'X-Algolia-API-Key': this.apiKey,
41
+ 'X-Algolia-Application-Id': this.applicationID,
42
+ 'Content-Type': 'application/json',
43
+ ...headers,
44
+ };
45
+ }
46
+
47
+ parseJsonResponse(response) {
48
+ return response.json().then(json => {
49
+ if (!response.ok) {
50
+ return Promise.reject(json);
51
+ }
52
+
53
+ return json;
54
+ });
55
+ }
56
+
57
+ urlFor(path, options) {
58
+ const params = [];
59
+ if (options.params) {
60
+ for (const key in options.params) {
61
+ params.push(`${key}=${encodeURIComponent(options.params[key])}`);
62
+ }
63
+ }
64
+ if (params.length) {
65
+ path += `?${params.join('&')}`;
66
+ }
67
+ return path;
68
+ }
69
+
70
+ request(path, options = {}) {
71
+ const headers = this.requestHeaders(options.headers || {});
72
+ const url = this.urlFor(path, options);
73
+ return fetch(url, { ...options, headers }).then(response => {
74
+ const contentType = response.headers.get('Content-Type');
75
+ if (contentType && contentType.match(/json/)) {
76
+ return this.parseJsonResponse(response);
77
+ }
78
+
79
+ return response.text();
80
+ });
81
+ }
82
+
83
+ search(collections, searchTerm, page) {
84
+ const searchCollections = collections.map(collection => ({
85
+ indexName: `${this.indexPrefix}${collection}`,
86
+ params: `query=${searchTerm}&page=${page}`,
87
+ }));
88
+
89
+ return this.request(`${this.searchURL}/indexes/*/queries`, {
90
+ method: 'POST',
91
+ body: JSON.stringify({ requests: searchCollections }),
92
+ }).then(response => {
93
+ const entries = response.results.map((result, index) =>
94
+ result.hits.map(hit => {
95
+ const slug = getSlug(hit.path);
96
+ return createEntry(collections[index], slug, hit.path, { data: hit.data, partial: true });
97
+ }),
98
+ );
99
+
100
+ return { entries: flatten(entries), pagination: page };
101
+ });
102
+ }
103
+
104
+ searchBy(field, collection, query) {
105
+ return this.request(`${this.searchURL}/indexes/${this.indexPrefix}${collection}`, {
106
+ params: {
107
+ restrictSearchableAttributes: field,
108
+ query,
109
+ },
110
+ });
111
+ }
112
+
113
+ listEntries(collection, page) {
114
+ if (this.entriesCache.collection === collection && this.entriesCache.page === page) {
115
+ return Promise.resolve({ page: this.entriesCache.page, entries: this.entriesCache.entries });
116
+ } else {
117
+ return this.request(
118
+ `${this.searchURL}/indexes/${this.indexPrefix}${collection.get('name')}`,
119
+ {
120
+ params: { page },
121
+ },
122
+ ).then(response => {
123
+ const entries = response.hits.map(hit => {
124
+ const slug = selectEntrySlug(collection, hit.path);
125
+ return createEntry(collection.get('name'), slug, hit.path, {
126
+ data: hit.data,
127
+ partial: true,
128
+ });
129
+ });
130
+ this.entriesCache = { collection, pagination: response.page, entries };
131
+ return { entries, pagination: response.page };
132
+ });
133
+ }
134
+ }
135
+
136
+ async listAllEntries(collection) {
137
+ const params = {
138
+ hitsPerPage: 1000,
139
+ };
140
+ let response = await this.request(
141
+ `${this.searchURL}/indexes/${this.indexPrefix}${collection.get('name')}`,
142
+ { params },
143
+ );
144
+ let { nbPages = 0, hits, page } = response;
145
+ page = page + 1;
146
+ while (page < nbPages) {
147
+ response = await this.request(
148
+ `${this.searchURL}/indexes/${this.indexPrefix}${collection.get('name')}`,
149
+ {
150
+ params: { ...params, page },
151
+ },
152
+ );
153
+ hits = [...hits, ...response.hits];
154
+ page = page + 1;
155
+ }
156
+ const entries = hits.map(hit => {
157
+ const slug = selectEntrySlug(collection, hit.path);
158
+ return createEntry(collection.get('name'), slug, hit.path, {
159
+ data: hit.data,
160
+ partial: true,
161
+ });
162
+ });
163
+
164
+ return entries;
165
+ }
166
+
167
+ getEntry(collection, slug) {
168
+ return this.searchBy('slug', collection.get('name'), slug).then(response => {
169
+ const entry = response.hits.filter(hit => hit.slug === slug)[0];
170
+ return createEntry(collection.get('name'), slug, entry.path, {
171
+ data: entry.data,
172
+ partial: true,
173
+ });
174
+ });
175
+ }
176
+ }
@@ -0,0 +1,148 @@
1
+ import pickBy from 'lodash/pickBy';
2
+ import trimEnd from 'lodash/trimEnd';
3
+ import { unsentRequest } from 'decap-cms-lib-util';
4
+
5
+ import { addParams } from '../../../lib/urlHelper';
6
+
7
+ const { fetchWithTimeout: fetch } = unsentRequest;
8
+
9
+ export default class AssetStore {
10
+ constructor(config, getToken) {
11
+ this.config = config;
12
+ if (config.get('getSignedFormURL') == null) {
13
+ throw 'The AssetStore integration needs the getSignedFormURL in the integration configuration.';
14
+ }
15
+ this.getToken = getToken;
16
+
17
+ this.shouldConfirmUpload = config.get('shouldConfirmUpload', false);
18
+ this.getSignedFormURL = trimEnd(config.get('getSignedFormURL'), '/');
19
+ }
20
+
21
+ parseJsonResponse(response) {
22
+ return response.json().then(json => {
23
+ if (!response.ok) {
24
+ return Promise.reject(json);
25
+ }
26
+
27
+ return json;
28
+ });
29
+ }
30
+
31
+ urlFor(path, options) {
32
+ const params = [];
33
+ if (options.params) {
34
+ for (const key in options.params) {
35
+ params.push(`${key}=${encodeURIComponent(options.params[key])}`);
36
+ }
37
+ }
38
+ if (params.length) {
39
+ path += `?${params.join('&')}`;
40
+ }
41
+ return path;
42
+ }
43
+
44
+ requestHeaders(headers = {}) {
45
+ return {
46
+ ...headers,
47
+ };
48
+ }
49
+
50
+ confirmRequest(assetID) {
51
+ this.getToken().then(token =>
52
+ this.request(`${this.getSignedFormURL}/${assetID}`, {
53
+ method: 'PUT',
54
+ headers: {
55
+ 'Content-Type': 'application/json',
56
+ Authorization: `Bearer ${token}`,
57
+ },
58
+ body: JSON.stringify({ state: 'uploaded' }),
59
+ }),
60
+ );
61
+ }
62
+
63
+ async request(path, options = {}) {
64
+ const headers = this.requestHeaders(options.headers || {});
65
+ const url = this.urlFor(path, options);
66
+ const response = await fetch(url, { ...options, headers });
67
+ const contentType = response.headers.get('Content-Type');
68
+ const isJson = contentType && contentType.match(/json/);
69
+ const content = isJson ? await this.parseJsonResponse(response) : response.text();
70
+ return content;
71
+ }
72
+
73
+ async retrieve(query, page, privateUpload) {
74
+ const params = pickBy(
75
+ { search: query, page, filter: privateUpload ? 'private' : 'public' },
76
+ val => !!val,
77
+ );
78
+ const url = addParams(this.getSignedFormURL, params);
79
+ const token = await this.getToken();
80
+ const headers = {
81
+ 'Content-Type': 'application/json',
82
+ Authorization: `Bearer ${token}`,
83
+ };
84
+ const response = await this.request(url, { headers });
85
+ const files = response.map(({ id, name, size, url }) => {
86
+ return { id, name, size, displayURL: url, url, path: url };
87
+ });
88
+ return files;
89
+ }
90
+
91
+ delete(assetID) {
92
+ const url = `${this.getSignedFormURL}/${assetID}`;
93
+ return this.getToken().then(token =>
94
+ this.request(url, {
95
+ method: 'DELETE',
96
+ headers: {
97
+ 'Content-Type': 'application/json',
98
+ Authorization: `Bearer ${token}`,
99
+ },
100
+ }),
101
+ );
102
+ }
103
+
104
+ async upload(file, privateUpload = false) {
105
+ const fileData = {
106
+ name: file.name,
107
+ size: file.size,
108
+ };
109
+ if (file.type) {
110
+ fileData.content_type = file.type;
111
+ }
112
+
113
+ if (privateUpload) {
114
+ fileData.visibility = 'private';
115
+ }
116
+
117
+ try {
118
+ const token = await this.getToken();
119
+ const response = await this.request(this.getSignedFormURL, {
120
+ method: 'POST',
121
+ headers: {
122
+ 'Content-Type': 'application/json',
123
+ Authorization: `Bearer ${token}`,
124
+ },
125
+ body: JSON.stringify(fileData),
126
+ });
127
+ const formURL = response.form.url;
128
+ const formFields = response.form.fields;
129
+ const { id, name, size, url } = response.asset;
130
+
131
+ const formData = new FormData();
132
+ Object.keys(formFields).forEach(key => formData.append(key, formFields[key]));
133
+ formData.append('file', file, file.name);
134
+
135
+ await this.request(formURL, { method: 'POST', body: formData });
136
+
137
+ if (this.shouldConfirmUpload) {
138
+ await this.confirmRequest(id);
139
+ }
140
+
141
+ const asset = { id, name, size, displayURL: url, url, path: url };
142
+ return { success: true, asset };
143
+ } catch (error) {
144
+ console.error(error);
145
+ throw error;
146
+ }
147
+ }
148
+ }