@fc3/mmcadi 0.1.0

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 (460) hide show
  1. package/LICENSE +673 -0
  2. package/README.md +5 -0
  3. package/bin/compile +63 -0
  4. package/bin/copy-static-files +13 -0
  5. package/bin/install +5 -0
  6. package/bin/precompile +55 -0
  7. package/bin/prepublish +7 -0
  8. package/bin/remap-paths +113 -0
  9. package/bin/test +9 -0
  10. package/config/tsconfig.json +37 -0
  11. package/package.json +33 -0
  12. package/src/bootstrap/start.ts +12 -0
  13. package/src/client/bootstrap.ts +5 -0
  14. package/src/client/client.ts +54 -0
  15. package/src/client/enum/key-code.ts +34 -0
  16. package/src/client/enum/page-type.ts +19 -0
  17. package/src/client/factory/page.ts +61 -0
  18. package/src/client/page/confirm-delete-block.ts +30 -0
  19. package/src/client/page/create-block.ts +6 -0
  20. package/src/client/page/day.ts +8 -0
  21. package/src/client/page/edit-block.ts +43 -0
  22. package/src/client/page/edit-custom.ts +16 -0
  23. package/src/client/page/home.ts +8 -0
  24. package/src/client/page/login.ts +8 -0
  25. package/src/client/page/logout.ts +8 -0
  26. package/src/client/page/month.ts +8 -0
  27. package/src/client/page/move-block.ts +8 -0
  28. package/src/client/page/select-block-type.ts +56 -0
  29. package/src/client/page/settings.ts +8 -0
  30. package/src/client/page/view-custom.ts +665 -0
  31. package/src/client/page/week.ts +8 -0
  32. package/src/client/page/year.ts +8 -0
  33. package/src/client/page.ts +128 -0
  34. package/src/client/shim/execute.ts +5 -0
  35. package/src/client/shim/logger.ts +44 -0
  36. package/src/client/utility/get-meta-value.ts +23 -0
  37. package/src/common/builder/block/background.ts +25 -0
  38. package/src/common/builder/block/folder.ts +43 -0
  39. package/src/common/builder/block/header.ts +15 -0
  40. package/src/common/builder/block/link.ts +32 -0
  41. package/src/common/builder/block/multicolumn.ts +16 -0
  42. package/src/common/builder/block/note.ts +13 -0
  43. package/src/common/builder/block/whitespace.ts +13 -0
  44. package/src/common/utility/get-parent-path.ts +29 -0
  45. package/src/constant/month-names.ts +16 -0
  46. package/src/enum/action-type.ts +11 -0
  47. package/src/enum/block-type.ts +18 -0
  48. package/src/enum/calendar-view-mode.ts +9 -0
  49. package/src/enum/color.ts +15 -0
  50. package/src/enum/default-role.ts +6 -0
  51. package/src/enum/directory-item-type.ts +6 -0
  52. package/src/enum/emoji.ts +94 -0
  53. package/src/enum/field-type.ts +8 -0
  54. package/src/enum/header-size.ts +7 -0
  55. package/src/enum/permission-type.ts +8 -0
  56. package/src/enum/time-place-visibility.ts +8 -0
  57. package/src/enum/tool-type.ts +14 -0
  58. package/src/index.ts +8 -0
  59. package/src/interface/hydration-callback.ts +7 -0
  60. package/src/interface/provider.ts +8 -0
  61. package/src/interface/repository.ts +12 -0
  62. package/src/lib/array/add.ts +10 -0
  63. package/src/lib/array/assert-is-empty.ts +23 -0
  64. package/src/lib/array/clone.ts +5 -0
  65. package/src/lib/array/difference.ts +8 -0
  66. package/src/lib/array/empty.ts +6 -0
  67. package/src/lib/array/equal.ts +24 -0
  68. package/src/lib/array/get-first-value.ts +5 -0
  69. package/src/lib/array/get-last-value.ts +5 -0
  70. package/src/lib/array/get-max-value.ts +5 -0
  71. package/src/lib/array/get-value-after.ts +23 -0
  72. package/src/lib/array/get-value-before.ts +23 -0
  73. package/src/lib/array/get-values-between.ts +18 -0
  74. package/src/lib/array/index.ts +5 -0
  75. package/src/lib/array/is-empty.ts +6 -0
  76. package/src/lib/array/remove.ts +19 -0
  77. package/src/lib/array/sum.ts +11 -0
  78. package/src/lib/array/unique.ts +13 -0
  79. package/src/lib/environment/bootstrap.ts +1 -0
  80. package/src/lib/environment/enum/environment-type.ts +8 -0
  81. package/src/lib/environment/enum/service-type.ts +5 -0
  82. package/src/lib/environment/index.ts +7 -0
  83. package/src/lib/environment/utility/get-environment-type.ts +28 -0
  84. package/src/lib/environment/utility/is-browser.ts +5 -0
  85. package/src/lib/environment/utility/is-development.ts +10 -0
  86. package/src/lib/environment/utility/is-production-or-staging.ts +8 -0
  87. package/src/lib/environment/utility/is-production.ts +10 -0
  88. package/src/lib/environment/utility/is-staging.ts +10 -0
  89. package/src/lib/errors/enum/error-type.ts +13 -0
  90. package/src/lib/errors/error/base.ts +40 -0
  91. package/src/lib/errors/error/conflict.ts +16 -0
  92. package/src/lib/errors/error/generic.ts +23 -0
  93. package/src/lib/errors/error/invalid.ts +14 -0
  94. package/src/lib/errors/error/invariant-violation.ts +5 -0
  95. package/src/lib/errors/error/not-allowed.ts +14 -0
  96. package/src/lib/errors/error/not-found.ts +16 -0
  97. package/src/lib/errors/error/not-implemented.ts +20 -0
  98. package/src/lib/errors/error/omitted.ts +14 -0
  99. package/src/lib/errors/error/timeout.ts +14 -0
  100. package/src/lib/errors/error/unauthorized.ts +14 -0
  101. package/src/lib/errors/index.ts +18 -0
  102. package/src/lib/errors/sugar/invariant.ts +7 -0
  103. package/src/lib/errors/type/coded-error.ts +7 -0
  104. package/src/lib/errors/type/error-data.ts +11 -0
  105. package/src/lib/errors/utility/create-error-for-error-type.ts +60 -0
  106. package/src/lib/errors/utility/create-error-from-ambiguous-json-data.ts +26 -0
  107. package/src/lib/errors/utility/error-matches.ts +28 -0
  108. package/src/lib/errors/utility/get-error-type-for-posix-error-code.ts +37 -0
  109. package/src/lib/errors/utility/get-error-type-for-status-code.ts +38 -0
  110. package/src/lib/errors/utility/get-message-for-error-type.ts +29 -0
  111. package/src/lib/errors/utility/matches-posix-error-code.ts +11 -0
  112. package/src/lib/errors/utility/wrap-error.ts +39 -0
  113. package/src/lib/event-emitter/index.ts +63 -0
  114. package/src/lib/execution-context/execution-context.ts +90 -0
  115. package/src/lib/execution-context/index.ts +8 -0
  116. package/src/lib/execution-context/type/session.ts +7 -0
  117. package/src/lib/feature/feature.ts +108 -0
  118. package/src/lib/feature/index.ts +3 -0
  119. package/src/lib/filesystem/bootstrap.ts +1 -0
  120. package/src/lib/filesystem/enum/file-extension.ts +19 -0
  121. package/src/lib/filesystem/index.ts +4 -0
  122. package/src/lib/filesystem/utility/exists.ts +21 -0
  123. package/src/lib/filesystem/utility/get-extension-for-filepath.ts +20 -0
  124. package/src/lib/filesystem/utility/strip-extension.ts +26 -0
  125. package/src/lib/grammar/index.ts +3 -0
  126. package/src/lib/grammar/noun-inflector.ts +104 -0
  127. package/src/lib/grammar/utility/get-words-from-identifier.ts +9 -0
  128. package/src/lib/grammar/verb-inflector.ts +344 -0
  129. package/src/lib/http/buffer-stream.ts +76 -0
  130. package/src/lib/http/enum/content-type.ts +19 -0
  131. package/src/lib/http/enum/cookie-attribute.ts +11 -0
  132. package/src/lib/http/enum/header.ts +29 -0
  133. package/src/lib/http/enum/method.ts +11 -0
  134. package/src/lib/http/enum/same-site-policy.ts +7 -0
  135. package/src/lib/http/enum/status-code.ts +9 -0
  136. package/src/lib/http/factory/body-parser.ts +55 -0
  137. package/src/lib/http/index.ts +24 -0
  138. package/src/lib/http/interface/client-request.ts +15 -0
  139. package/src/lib/http/interface/incoming-message.ts +24 -0
  140. package/src/lib/http/interface/network-library.ts +9 -0
  141. package/src/lib/http/interface/request-callback.ts +7 -0
  142. package/src/lib/http/isomorphic/request.ts +77 -0
  143. package/src/lib/http/isomorphic/response.ts +77 -0
  144. package/src/lib/http/isomorphic.ts +20 -0
  145. package/src/lib/http/parser/accept-header.ts +35 -0
  146. package/src/lib/http/parser/basic-auth-header.ts +48 -0
  147. package/src/lib/http/parser/body/json.ts +14 -0
  148. package/src/lib/http/parser/body/multipart.ts +89 -0
  149. package/src/lib/http/parser/body/url-encoded.ts +16 -0
  150. package/src/lib/http/parser/body.ts +44 -0
  151. package/src/lib/http/parser/cookie.ts +114 -0
  152. package/src/lib/http/parser/querystring.ts +92 -0
  153. package/src/lib/http/parser/url.ts +76 -0
  154. package/src/lib/http/request/incoming.ts +299 -0
  155. package/src/lib/http/request/outgoing.ts +276 -0
  156. package/src/lib/http/request.ts +26 -0
  157. package/src/lib/http/response/incoming.ts +243 -0
  158. package/src/lib/http/response/outgoing.ts +160 -0
  159. package/src/lib/http/response.ts +74 -0
  160. package/src/lib/http/serializer/basic-auth-header.ts +27 -0
  161. package/src/lib/http/serializer/cookie.ts +90 -0
  162. package/src/lib/http/serializer/query-data.ts +54 -0
  163. package/src/lib/http/transaction.ts +320 -0
  164. package/src/lib/http/type/basic-auth-credentials.ts +6 -0
  165. package/src/lib/http/type/header-map.ts +5 -0
  166. package/src/lib/http/type/log-attributes.ts +12 -0
  167. package/src/lib/http/type/path-parameters.ts +5 -0
  168. package/src/lib/http/type/query-data.ts +7 -0
  169. package/src/lib/http/type/query-value.ts +11 -0
  170. package/src/lib/http/type/request-options.ts +16 -0
  171. package/src/lib/http/type/transaction-data.ts +4 -0
  172. package/src/lib/http/utility/get-content-type-for-extension.ts +47 -0
  173. package/src/lib/http/utility/get-library-for-protocol.ts +25 -0
  174. package/src/lib/http/utility/get-status-code-for-error-type.ts +37 -0
  175. package/src/lib/http/utility/get-status-code-for-error.ts +13 -0
  176. package/src/lib/http/utility/is-client-error-status.ts +15 -0
  177. package/src/lib/http/utility/is-error-status.ts +9 -0
  178. package/src/lib/http/utility/is-server-error-status.ts +7 -0
  179. package/src/lib/http/utility/is-success-status.ts +7 -0
  180. package/src/lib/http/utility/proxy-request.ts +58 -0
  181. package/src/lib/http/utility/serialize-request-options.ts +9 -0
  182. package/src/lib/http/utility/slug-generator.ts +20 -0
  183. package/src/lib/key-generator/index.ts +3 -0
  184. package/src/lib/key-generator/key-generator.ts +7 -0
  185. package/src/lib/logger/enum/ansi-escape-code.ts +14 -0
  186. package/src/lib/logger/enum/log-level.ts +8 -0
  187. package/src/lib/logger/formatter.ts +59 -0
  188. package/src/lib/logger/index.ts +7 -0
  189. package/src/lib/logger/interface/error-reporter.ts +7 -0
  190. package/src/lib/logger/interface/logger.ts +13 -0
  191. package/src/lib/logger/logger.ts +239 -0
  192. package/src/lib/logger/type/error-parameters.ts +9 -0
  193. package/src/lib/logger/type/loggable-data.ts +5 -0
  194. package/src/lib/logger/type/loggable-value.ts +1 -0
  195. package/src/lib/metrics/dispatcher.ts +264 -0
  196. package/src/lib/metrics/enum/dispatch-mode.ts +6 -0
  197. package/src/lib/metrics/index.ts +2 -0
  198. package/src/lib/metrics/settings-hydrator.ts +51 -0
  199. package/src/lib/metrics/type/dispatcher-settings.ts +12 -0
  200. package/src/lib/metrics/type/tag-map.ts +5 -0
  201. package/src/lib/network/bootstrap.ts +1 -0
  202. package/src/lib/network/enum/connection-status.ts +14 -0
  203. package/src/lib/network/enum/http-status-code.ts +75 -0
  204. package/src/lib/network/enum/network-protocol.ts +10 -0
  205. package/src/lib/network/event-emitter.ts +63 -0
  206. package/src/lib/network/index.ts +7 -0
  207. package/src/lib/network/interface/socket.ts +42 -0
  208. package/src/lib/network/type/socket-options.ts +6 -0
  209. package/src/lib/network/utility/get-protocol-from-url.ts +15 -0
  210. package/src/lib/operation/index.ts +6 -0
  211. package/src/lib/operation/operation/auto-logging.ts +94 -0
  212. package/src/lib/operation/operation/silent.ts +17 -0
  213. package/src/lib/operation/operation.ts +80 -0
  214. package/src/lib/process/bootstrap.ts +1 -0
  215. package/src/lib/process/enum/posix-error-code.ts +138 -0
  216. package/src/lib/process/enum/process-signal.ts +68 -0
  217. package/src/lib/process/error.ts +6 -0
  218. package/src/lib/process/execute.ts +77 -0
  219. package/src/lib/process/index.ts +4 -0
  220. package/src/lib/process/type/command-options.ts +9 -0
  221. package/src/lib/process/utility/bind-process-lifespan-to.ts +10 -0
  222. package/src/lib/promise-wrapper/index.ts +3 -0
  223. package/src/lib/promise-wrapper/promise-wrapper.ts +51 -0
  224. package/src/lib/random/chance.ts +5 -0
  225. package/src/lib/random/element.ts +7 -0
  226. package/src/lib/random/elements.ts +12 -0
  227. package/src/lib/random/enum.ts +34 -0
  228. package/src/lib/random/enums.ts +11 -0
  229. package/src/lib/random/index.ts +3 -0
  230. package/src/lib/random/number.ts +8 -0
  231. package/src/lib/server/base.ts +194 -0
  232. package/src/lib/server/enum/server-event.ts +5 -0
  233. package/src/lib/server/enum/server-status.ts +10 -0
  234. package/src/lib/server/http/endpoint/ping.ts +21 -0
  235. package/src/lib/server/http/endpoint.ts +345 -0
  236. package/src/lib/server/http/interface/endpoint-constructor.ts +12 -0
  237. package/src/lib/server/http/interface/result-serializer.ts +5 -0
  238. package/src/lib/server/http/middleware.ts +18 -0
  239. package/src/lib/server/http/result-serializer/html.ts +92 -0
  240. package/src/lib/server/http/result-serializer/json.ts +23 -0
  241. package/src/lib/server/http/route.ts +104 -0
  242. package/src/lib/server/http/router.ts +125 -0
  243. package/src/lib/server/http/type/session-resolver.ts +8 -0
  244. package/src/lib/server/http/utility/create-server.ts +34 -0
  245. package/src/lib/server/http/utility/path-parser.ts +49 -0
  246. package/src/lib/server/http/utility/standardize-html-indentation.ts +54 -0
  247. package/src/lib/server/http/websocket-wrapper.ts +83 -0
  248. package/src/lib/server/http.ts +301 -0
  249. package/src/lib/server/index.ts +5 -0
  250. package/src/lib/server/tcp.ts +53 -0
  251. package/src/lib/server/type/server-options.ts +10 -0
  252. package/src/lib/string/calculate-length.ts +17 -0
  253. package/src/lib/string/capitalize.ts +8 -0
  254. package/src/lib/string/create-slug.ts +14 -0
  255. package/src/lib/string/enum/ansi-escape-code.ts +14 -0
  256. package/src/lib/string/enum/string-encoding.ts +9 -0
  257. package/src/lib/string/hyphenate.ts +5 -0
  258. package/src/lib/string/index.ts +3 -0
  259. package/src/lib/string/pad.ts +14 -0
  260. package/src/lib/string/trim-multiline.ts +21 -0
  261. package/src/lib/string/trim.ts +8 -0
  262. package/src/lib/tcp/channel.ts +13 -0
  263. package/src/lib/tcp/connection/incoming.ts +72 -0
  264. package/src/lib/tcp/connection/outgoing.ts +219 -0
  265. package/src/lib/tcp/connection.ts +360 -0
  266. package/src/lib/tcp/enum/connection-event.ts +12 -0
  267. package/src/lib/tcp/enum/message-type.ts +9 -0
  268. package/src/lib/tcp/index.ts +1 -0
  269. package/src/lib/tcp/type/connection-parameters.ts +6 -0
  270. package/src/lib/tcp/type/message/channel-close.ts +9 -0
  271. package/src/lib/tcp/type/message/channel-open.ts +9 -0
  272. package/src/lib/tcp/type/message.ts +10 -0
  273. package/src/lib/test/index.ts +2 -0
  274. package/src/lib/test/utility/build-config.ts +17 -0
  275. package/src/lib/test/utility/build-execution-context.ts +11 -0
  276. package/src/lib/time/bootstrap.ts +1 -0
  277. package/src/lib/time/enum/time-interval.ts +12 -0
  278. package/src/lib/time/index.ts +4 -0
  279. package/src/lib/time/utility/format-duration.ts +139 -0
  280. package/src/lib/time/utility/format-relative-duration.ts +22 -0
  281. package/src/lib/time/utility/sleep.ts +9 -0
  282. package/src/operation.ts +18 -0
  283. package/src/server/endpoint/abstract-page.ts +126 -0
  284. package/src/server/endpoint/action/create.ts +545 -0
  285. package/src/server/endpoint/action/get.ts +231 -0
  286. package/src/server/endpoint/base.ts +51 -0
  287. package/src/server/endpoint/day.ts +13 -0
  288. package/src/server/endpoint/generic-page.ts +14 -0
  289. package/src/server/endpoint/index.ts +11 -0
  290. package/src/server/endpoint/login.ts +45 -0
  291. package/src/server/endpoint/logout.ts +38 -0
  292. package/src/server/endpoint/month.ts +35 -0
  293. package/src/server/endpoint/robots.ts +18 -0
  294. package/src/server/endpoint/session/create.ts +62 -0
  295. package/src/server/endpoint/settings/get.ts +40 -0
  296. package/src/server/endpoint/settings/update.ts +44 -0
  297. package/src/server/endpoint/today.ts +15 -0
  298. package/src/server/endpoint/week.ts +34 -0
  299. package/src/server/endpoint/year.ts +34 -0
  300. package/src/server/enum/custom-page-type.ts +10 -0
  301. package/src/server/factory/block-result-serializer.ts +115 -0
  302. package/src/server/middleware/base.ts +6 -0
  303. package/src/server/middleware/error-handler.ts +177 -0
  304. package/src/server/middleware/static-file.ts +83 -0
  305. package/src/server/operation/add-block.ts +110 -0
  306. package/src/server/operation/create-session.ts +43 -0
  307. package/src/server/operation/delete-block.ts +96 -0
  308. package/src/server/operation/demote-block.ts +108 -0
  309. package/src/server/operation/destroy-session.ts +26 -0
  310. package/src/server/operation/load-account.ts +30 -0
  311. package/src/server/operation/load-block.ts +48 -0
  312. package/src/server/operation/load-directory-items.ts +75 -0
  313. package/src/server/operation/load-page.ts +368 -0
  314. package/src/server/operation/promote-block.ts +104 -0
  315. package/src/server/operation/save-page.ts +60 -0
  316. package/src/server/operation/update-account-settings.ts +52 -0
  317. package/src/server/operation/update-block.ts +124 -0
  318. package/src/server/repository/memory.ts +112 -0
  319. package/src/server/result-serializer/action.ts +939 -0
  320. package/src/server/result-serializer/base.ts +1267 -0
  321. package/src/server/result-serializer/block/audio.ts +33 -0
  322. package/src/server/result-serializer/block/background.ts +20 -0
  323. package/src/server/result-serializer/block/calendar.ts +148 -0
  324. package/src/server/result-serializer/block/directory.ts +57 -0
  325. package/src/server/result-serializer/block/ephemeral.ts +14 -0
  326. package/src/server/result-serializer/block/folder.ts +106 -0
  327. package/src/server/result-serializer/block/header.ts +31 -0
  328. package/src/server/result-serializer/block/image.ts +46 -0
  329. package/src/server/result-serializer/block/link.ts +40 -0
  330. package/src/server/result-serializer/block/list.ts +140 -0
  331. package/src/server/result-serializer/block/multi-column.ts +97 -0
  332. package/src/server/result-serializer/block/note.ts +44 -0
  333. package/src/server/result-serializer/block/todo.ts +78 -0
  334. package/src/server/result-serializer/block/whitespace.ts +15 -0
  335. package/src/server/result-serializer/block.ts +248 -0
  336. package/src/server/result-serializer/common/time-place-options.ts +33 -0
  337. package/src/server/result-serializer/login.ts +58 -0
  338. package/src/server/result-serializer/month.ts +170 -0
  339. package/src/server/result-serializer/page.ts +548 -0
  340. package/src/server/result-serializer/settings.ts +85 -0
  341. package/src/server/result-serializer/week.ts +195 -0
  342. package/src/server/result-serializer/year.ts +160 -0
  343. package/src/server/utility/accepts-content-type.ts +16 -0
  344. package/src/server/utility/accepts-html.ts +9 -0
  345. package/src/server/utility/accepts-json.ts +9 -0
  346. package/src/server/utility/add-days.ts +11 -0
  347. package/src/server/utility/create-date.ts +23 -0
  348. package/src/server/utility/create-index-path.ts +5 -0
  349. package/src/server/utility/create-slug.ts +9 -0
  350. package/src/server/utility/create-toast-path.ts +19 -0
  351. package/src/server/utility/date-less-than.ts +5 -0
  352. package/src/server/utility/date-occurs-before.ts +22 -0
  353. package/src/server/utility/date-to-key.ts +7 -0
  354. package/src/server/utility/date-to-label.ts +5 -0
  355. package/src/server/utility/date-to-path.ts +9 -0
  356. package/src/server/utility/dates-are-equal.ts +22 -0
  357. package/src/server/utility/dates-are-in-order.ts +9 -0
  358. package/src/server/utility/dates-are-on-the-same-day.ts +9 -0
  359. package/src/server/utility/dates-in-same-month.ts +8 -0
  360. package/src/server/utility/day-to-date.ts +40 -0
  361. package/src/server/utility/decrement-date.ts +11 -0
  362. package/src/server/utility/get-block-at-index-path.ts +32 -0
  363. package/src/server/utility/get-block-permissions.ts +15 -0
  364. package/src/server/utility/get-compact-label-for-date.ts +8 -0
  365. package/src/server/utility/get-custom-page-type-for-path.ts +37 -0
  366. package/src/server/utility/get-element-id-for-block.ts +15 -0
  367. package/src/server/utility/get-emoji-for-block-type.ts +39 -0
  368. package/src/server/utility/get-emoji-for-tool-type.ts +20 -0
  369. package/src/server/utility/get-end-of-month.ts +13 -0
  370. package/src/server/utility/get-end-of-week.ts +13 -0
  371. package/src/server/utility/get-filepath-for-folder-block.ts +23 -0
  372. package/src/server/utility/get-hex-for-color.ts +31 -0
  373. package/src/server/utility/get-label-for-time-place-visibility.ts +23 -0
  374. package/src/server/utility/get-month-name.ts +18 -0
  375. package/src/server/utility/get-next-day.ts +7 -0
  376. package/src/server/utility/get-next-month.ts +12 -0
  377. package/src/server/utility/get-next-week.ts +12 -0
  378. package/src/server/utility/get-next-year.ts +13 -0
  379. package/src/server/utility/get-ordinal-label-for-week.ts +11 -0
  380. package/src/server/utility/get-ordinal-of-week-within-month.ts +15 -0
  381. package/src/server/utility/get-padded-date.ts +11 -0
  382. package/src/server/utility/get-parent-index-path.ts +18 -0
  383. package/src/server/utility/get-path-for-folder-block.ts +25 -0
  384. package/src/server/utility/get-path-from-url.ts +13 -0
  385. package/src/server/utility/get-previous-index-path.ts +27 -0
  386. package/src/server/utility/get-previous-month.ts +12 -0
  387. package/src/server/utility/get-previous-week.ts +11 -0
  388. package/src/server/utility/get-previous-year.ts +13 -0
  389. package/src/server/utility/get-random-emoji-for-date.ts +109 -0
  390. package/src/server/utility/get-short-label-for-date.ts +11 -0
  391. package/src/server/utility/get-short-month-name.ts +9 -0
  392. package/src/server/utility/get-short-ordinal.ts +26 -0
  393. package/src/server/utility/get-siblings-and-index-for-index-path.ts +67 -0
  394. package/src/server/utility/get-start-of-month.ts +11 -0
  395. package/src/server/utility/get-start-of-week.ts +12 -0
  396. package/src/server/utility/get-start-of-year.ts +12 -0
  397. package/src/server/utility/get-weekday-name.ts +24 -0
  398. package/src/server/utility/increment-date.ts +15 -0
  399. package/src/server/utility/is-index-path.ts +5 -0
  400. package/src/server/utility/key-to-date.ts +25 -0
  401. package/src/server/utility/month-has-week-containing-date.ts +13 -0
  402. package/src/server/utility/month-to-date.ts +28 -0
  403. package/src/server/utility/month-to-path.ts +10 -0
  404. package/src/server/utility/months-are-equal.ts +8 -0
  405. package/src/server/utility/parse-index-path.ts +23 -0
  406. package/src/server/utility/path-is-date.ts +13 -0
  407. package/src/server/utility/path-to-date.ts +24 -0
  408. package/src/server/utility/subtract-days.ts +7 -0
  409. package/src/server/utility/validate-month.ts +10 -0
  410. package/src/server/utility/validate-page.ts +46 -0
  411. package/src/server/utility/validate-path.ts +9 -0
  412. package/src/server/utility/validate-url.ts +12 -0
  413. package/src/server/utility/week-greater-than.ts +10 -0
  414. package/src/server/utility/week-to-date.ts +8 -0
  415. package/src/server/utility/week-to-path.ts +12 -0
  416. package/src/server/utility/weeks-are-equal.ts +8 -0
  417. package/src/server/utility/year-to-date.ts +26 -0
  418. package/src/server/utility/year-to-path.ts +7 -0
  419. package/src/server/utility/years-are-equal.ts +8 -0
  420. package/src/server.ts +140 -0
  421. package/src/test.ts +195 -0
  422. package/src/type/account-settings.ts +9 -0
  423. package/src/type/account.ts +11 -0
  424. package/src/type/action/add-block.ts +74 -0
  425. package/src/type/action/complete-block.ts +10 -0
  426. package/src/type/action/delete-block.ts +11 -0
  427. package/src/type/action/demote-block.ts +9 -0
  428. package/src/type/action/edit-block.ts +11 -0
  429. package/src/type/action/promote-block.ts +9 -0
  430. package/src/type/action.ts +9 -0
  431. package/src/type/block/audio.ts +8 -0
  432. package/src/type/block/background.ts +10 -0
  433. package/src/type/block/directory.ts +18 -0
  434. package/src/type/block/ephemeral.ts +9 -0
  435. package/src/type/block/folder.ts +14 -0
  436. package/src/type/block/header.ts +11 -0
  437. package/src/type/block/image.ts +8 -0
  438. package/src/type/block/link.ts +12 -0
  439. package/src/type/block/list.ts +24 -0
  440. package/src/type/block/multi-column.ts +10 -0
  441. package/src/type/block/note.ts +9 -0
  442. package/src/type/block/todo.ts +10 -0
  443. package/src/type/block/whitespace.ts +9 -0
  444. package/src/type/block-metadata.ts +14 -0
  445. package/src/type/block.ts +18 -0
  446. package/src/type/day.ts +5 -0
  447. package/src/type/field-definition.ts +8 -0
  448. package/src/type/field-value.ts +5 -0
  449. package/src/type/file.ts +6 -0
  450. package/src/type/month.ts +5 -0
  451. package/src/type/page.ts +8 -0
  452. package/src/type/price.ts +11 -0
  453. package/src/type/resource.ts +5 -0
  454. package/src/type/runtime-config.ts +13 -0
  455. package/src/type/server-settings.ts +17 -0
  456. package/src/type/toast.ts +8 -0
  457. package/src/type/week.ts +5 -0
  458. package/src/type/year.ts +5 -0
  459. package/test/unit/index.ts +11 -0
  460. package/test/unit/server/operation/promote-block.ts +84 -0
@@ -0,0 +1,109 @@
1
+ import Emoji from 'enum/emoji';
2
+ import {InvariantViolation} from 'lib/errors';
3
+ import {randomElement} from 'lib/random';
4
+
5
+ enum Season {
6
+ SPRING = 'spring',
7
+ SUMMER = 'summer',
8
+ AUTUMN = 'autumn',
9
+ WINTER = 'winter'
10
+ }
11
+
12
+ enum Month {
13
+ JANUARY,
14
+ FEBRUARY,
15
+ MARCH,
16
+ APRIL,
17
+ MAY,
18
+ JUNE,
19
+ JULY,
20
+ AUGUST,
21
+ SEPTEMBER,
22
+ OCTOBER,
23
+ NOVEMBER,
24
+ DECEMBER
25
+ }
26
+
27
+ const SEASONAL_EMOJI: Record<Season, Emoji[]> = {
28
+ [Season.WINTER]: [
29
+ Emoji.SNOWMAN,
30
+ Emoji.SNOWFLAKE,
31
+ Emoji.SNOW_CLOUD,
32
+ Emoji.SCARF,
33
+ Emoji.GLOVES,
34
+ Emoji.CANDLE,
35
+ Emoji.CHRISTMAS_TREE,
36
+ Emoji.SOCKS,
37
+ Emoji.COLD_FACE,
38
+ ],
39
+ [Season.SPRING]: [
40
+ Emoji.SEEDLING,
41
+ Emoji.TULIP,
42
+ Emoji.BEE,
43
+ Emoji.HATCHING_CHICK,
44
+ Emoji.NEST_WITH_EGGS,
45
+ Emoji.BLOSSOM,
46
+ Emoji.UMBRELLA,
47
+ Emoji.RAINBOW,
48
+ Emoji.PICNIC_BASKET,
49
+ ],
50
+ [Season.SUMMER]: [
51
+ Emoji.SUN_WITH_FACE,
52
+ Emoji.BEACH_UMBRELLA,
53
+ Emoji.WATERMELON,
54
+ Emoji.SUNGLASSES,
55
+ Emoji.ICE_CREAM,
56
+ Emoji.SUNFLOWER,
57
+ Emoji.CAMPING,
58
+ Emoji.JUICE_BOX,
59
+ Emoji.PARASOL,
60
+ ],
61
+ [Season.AUTUMN]: [
62
+ Emoji.MAPLE_LEAF,
63
+ Emoji.FALLEN_LEAF,
64
+ Emoji.TURKEY,
65
+ Emoji.JACK_O_LANTERN,
66
+ Emoji.PIE,
67
+ Emoji.LOG,
68
+ Emoji.SPIDER_WEB,
69
+ Emoji.BACKPACK,
70
+ Emoji.CHESTNUT,
71
+ ]
72
+ };
73
+
74
+ function getSeasonForDate(date: Date): Season {
75
+ const month = date.getUTCMonth();
76
+
77
+ switch (month) {
78
+ case Month.DECEMBER:
79
+ case Month.JANUARY:
80
+ case Month.FEBRUARY:
81
+ return Season.WINTER;
82
+ case Month.MARCH:
83
+ case Month.APRIL:
84
+ case Month.MAY:
85
+ return Season.SPRING;
86
+ case Month.JUNE:
87
+ case Month.JULY:
88
+ case Month.AUGUST:
89
+ return Season.SUMMER;
90
+ case Month.SEPTEMBER:
91
+ case Month.OCTOBER:
92
+ case Month.NOVEMBER:
93
+ return Season.AUTUMN;
94
+ default:
95
+ throw new InvariantViolation(`Invalid month: ${month}`);
96
+ }
97
+ }
98
+
99
+ function getRandomEmojiForSeason(season: Season): Emoji {
100
+ const subset = SEASONAL_EMOJI[season];
101
+
102
+ return randomElement(subset) as Emoji;
103
+ }
104
+
105
+ function getRandomEmojiForDate(date: Date): Emoji {
106
+ return getRandomEmojiForSeason(getSeasonForDate(date));
107
+ }
108
+
109
+ export default getRandomEmojiForDate;
@@ -0,0 +1,11 @@
1
+ import getShortMonthName from 'server/utility/get-short-month-name';
2
+
3
+ function getShortLabelForDate(date: Date): string {
4
+ const month = getShortMonthName(date);
5
+ const day = date.getUTCDate();
6
+ const year = date.getUTCFullYear();
7
+
8
+ return `${month} ${day} ${year} `;
9
+ }
10
+
11
+ export default getShortLabelForDate;
@@ -0,0 +1,9 @@
1
+ import getMonthName from 'server/utility/get-month-name';
2
+
3
+ function getShortMonthName(date: Date): string {
4
+ const month_name = getMonthName(date);
5
+
6
+ return month_name.slice(0, 3);
7
+ }
8
+
9
+ export default getShortMonthName;
@@ -0,0 +1,26 @@
1
+ function getOrdinalSuffix(index: number): string {
2
+ if (index > 10 && index < 20) {
3
+ return 'th';
4
+ }
5
+
6
+ const modulus = index % 10;
7
+
8
+ switch (modulus) {
9
+ case 1:
10
+ return 'st';
11
+ case 2:
12
+ return 'nd';
13
+ case 3:
14
+ return 'rd';
15
+ default:
16
+ return 'th';
17
+ }
18
+ }
19
+
20
+ function getShortOrdinal(index: number): string {
21
+ const suffix = getOrdinalSuffix(index);
22
+
23
+ return `${index}${suffix}`;
24
+ }
25
+
26
+ export default getShortOrdinal;
@@ -0,0 +1,67 @@
1
+ import {InvalidError} from 'lib/errors';
2
+ import {getLastValue} from 'lib/array';
3
+
4
+ import Page from 'type/page';
5
+ import Block from 'type/block';
6
+ import parseIndexPath from 'server/utility/parse-index-path';
7
+
8
+ type SiblingsAndIndex = {
9
+ siblings: Block[];
10
+ index: number;
11
+ };
12
+
13
+ function getSiblingsAndIndexForIndexPath(page: Page, index_path: string): SiblingsAndIndex {
14
+ const parsed_path = parseIndexPath(index_path);
15
+ const first_index = parsed_path[0];
16
+
17
+ if (parsed_path.length === 1) {
18
+ return {
19
+ siblings: page.blocks,
20
+ index: first_index
21
+ };
22
+ }
23
+
24
+ let current = page.blocks[first_index];
25
+
26
+ if (!current) {
27
+ throw new InvalidError(`Invalid index path segment: ${first_index}`);
28
+ }
29
+
30
+ let i = 1;
31
+
32
+ while (i < parsed_path.length - 1) {
33
+ const segment = parsed_path[i++];
34
+ const children = current.children;
35
+
36
+ if (children === undefined) {
37
+ throw new InvalidError(`Path segment ${i} has no children`);
38
+ }
39
+
40
+ current = children[segment];
41
+
42
+ if (!current) {
43
+ throw new InvalidError(`
44
+ Invalid index path segment at depth ${i}: ${segment}
45
+ `);
46
+ }
47
+ }
48
+
49
+ const siblings = current.children;
50
+
51
+ if (siblings === undefined) {
52
+ throw new InvalidError('Final ancestor has no children');
53
+ }
54
+
55
+ const index = getLastValue(parsed_path);
56
+
57
+ if (index === undefined) {
58
+ throw new InvalidError('Parsed path had no final part');
59
+ }
60
+
61
+ return {
62
+ siblings,
63
+ index
64
+ };
65
+ }
66
+
67
+ export default getSiblingsAndIndexForIndexPath;
@@ -0,0 +1,11 @@
1
+ import createDate from 'server/utility/create-date';
2
+
3
+ function getStartOfMonth(date: Date): Date {
4
+ const new_date = createDate(date);
5
+
6
+ new_date.setUTCDate(1);
7
+
8
+ return new_date;
9
+ }
10
+
11
+ export default getStartOfMonth;
@@ -0,0 +1,12 @@
1
+ import createDate from 'server/utility/create-date';
2
+
3
+ function getStartOfWeek(date: Date): Date {
4
+ const new_date = createDate(date);
5
+ const current_day = new_date.getUTCDay();
6
+
7
+ new_date.setUTCDate(new_date.getUTCDate() - current_day);
8
+
9
+ return new_date;
10
+ }
11
+
12
+ export default getStartOfWeek;
@@ -0,0 +1,12 @@
1
+ import createDate from 'server/utility/create-date';
2
+
3
+ function getStartOfYear(date: Date): Date {
4
+ const new_date = createDate(date);
5
+
6
+ new_date.setUTCMonth(0);
7
+ new_date.setUTCDate(1);
8
+
9
+ return new_date;
10
+ }
11
+
12
+ export default getStartOfYear;
@@ -0,0 +1,24 @@
1
+ import {InvariantViolation} from 'lib/errors';
2
+
3
+ const WEEKDAY_NAMES = [
4
+ 'sunday',
5
+ 'monday',
6
+ 'tuesday',
7
+ 'wednesday',
8
+ 'thursday',
9
+ 'friday',
10
+ 'saturday'
11
+ ];
12
+
13
+ function getWeekdayName(date: Date): string {
14
+ const weekday_index = date.getUTCDay();
15
+ const weekday_name = WEEKDAY_NAMES[weekday_index];
16
+
17
+ if (weekday_name === undefined) {
18
+ throw new InvariantViolation(`Invalid weekday index: ${weekday_index}`);
19
+ }
20
+
21
+ return weekday_name;
22
+ }
23
+
24
+ export default getWeekdayName;
@@ -0,0 +1,15 @@
1
+ import createDate from 'server/utility/create-date';
2
+
3
+ function incrementDate(date: Date, days?: number): Date {
4
+ if (days === undefined) {
5
+ days = 1;
6
+ }
7
+
8
+ const new_date = createDate(date);
9
+
10
+ new_date.setUTCDate(date.getUTCDate() + days);
11
+
12
+ return new_date;
13
+ }
14
+
15
+ export default incrementDate;
@@ -0,0 +1,5 @@
1
+ function isIndexPath(path: string): boolean {
2
+ return path === '/' || path === '/index';
3
+ }
4
+
5
+ export default isIndexPath;
@@ -0,0 +1,25 @@
1
+ import {InvalidError} from 'lib/errors';
2
+
3
+ import createDate from 'server/utility/create-date';
4
+
5
+ const DATE_REGEX = /^\/day\/([0-9]+)-([0-9]+)-([0-9]+)$/;
6
+
7
+ function keyToDate(key: string): Date {
8
+ const match = key.match(DATE_REGEX);
9
+
10
+ if (!match) {
11
+ throw new InvalidError(`Key did not include a valid date: ${key}`);
12
+ }
13
+
14
+ const month = parseInt(match[1]) - 1;
15
+ const day = parseInt(match[2]);
16
+ const year = parseInt(match[3]);
17
+
18
+ if (isNaN(month) || isNaN(day) || isNaN(year)) {
19
+ throw new InvalidError(`The specified date components are not valid: ${key}`);
20
+ }
21
+
22
+ return createDate(year, month, day);
23
+ }
24
+
25
+ export default keyToDate;
@@ -0,0 +1,13 @@
1
+ import getStartOfWeek from 'server/utility/get-start-of-week';
2
+ import getEndOfWeek from 'server/utility/get-end-of-week';
3
+ import getEndOfMonth from 'server/utility/get-end-of-month';
4
+ import datesAreInOrder from 'server/utility/dates-are-in-order';
5
+
6
+ function monthHasWeekContainingDate(month: Date, date: Date): boolean {
7
+ const first_week_start = getStartOfWeek(month);
8
+ const final_week_end = getEndOfWeek(getEndOfMonth(month));
9
+
10
+ return datesAreInOrder(first_week_start, date, final_week_end);
11
+ }
12
+
13
+ export default monthHasWeekContainingDate;
@@ -0,0 +1,28 @@
1
+ import {InvalidError} from 'lib/errors';
2
+
3
+ import MonthNames from 'constant/month-names';
4
+ import Month from 'type/month';
5
+
6
+ const month_segment = MonthNames.join('|');
7
+ const MONTH_REGEX = new RegExp(`^(${month_segment})\-([0-9][0-9][0-9][0-9])$`);
8
+
9
+ function monthToDate(month: Month): Date {
10
+ const {key} = month;
11
+ const match = key.match(MONTH_REGEX);
12
+
13
+ if (!match) {
14
+ throw new InvalidError(`Invalid month: ${key}`);
15
+ }
16
+
17
+ const month_name = match[1];
18
+ const month_index = MonthNames.indexOf(month_name) + 1;
19
+ const year = parseInt(match[2]);
20
+
21
+ if (isNaN(year) || isNaN(month_index)) {
22
+ throw new InvalidError(`Invalid month components: ${key}`);
23
+ }
24
+
25
+ return new Date(`${year}-${month_index}-01`);
26
+ }
27
+
28
+ export default monthToDate;
@@ -0,0 +1,10 @@
1
+ import getMonthName from 'server/utility/get-month-name';
2
+
3
+ function monthToPath(date: Date): string {
4
+ const month_name = getMonthName(date);
5
+ const year = date.getUTCFullYear();
6
+
7
+ return `/month/${month_name}-${year}`;
8
+ }
9
+
10
+ export default monthToPath;
@@ -0,0 +1,8 @@
1
+ import getStartOfMonth from 'server/utility/get-start-of-month';
2
+ import datesAreEqual from 'server/utility/dates-are-equal';
3
+
4
+ function monthsAreEqual(a: Date, b: Date): boolean {
5
+ return datesAreEqual(getStartOfMonth(a), getStartOfMonth(b));
6
+ }
7
+
8
+ export default monthsAreEqual;
@@ -0,0 +1,23 @@
1
+ import {InvariantViolation} from 'lib/errors';
2
+
3
+ function parseIndexPath(index_path: string): number[] {
4
+ if (index_path === undefined) {
5
+ throw new InvariantViolation(`Undefined index path`);
6
+ }
7
+
8
+ if (index_path.trim() === '') {
9
+ throw new InvariantViolation(`Invalid index path: ${index_path}`);
10
+ }
11
+
12
+ return index_path.split('.').map((part) => {
13
+ const parsed_part = parseInt(part);
14
+
15
+ if (isNaN(parsed_part)) {
16
+ throw new InvariantViolation(`Invalid index path: ${index_path}`);
17
+ }
18
+
19
+ return parsed_part;
20
+ });
21
+ }
22
+
23
+ export default parseIndexPath;
@@ -0,0 +1,13 @@
1
+ import validatePath from 'server/utility/validate-path';
2
+
3
+ const DateRegex = /^\/(year|month|week|day)\/([0-9]+)-([0-9]+)-([0-9]+)$/;
4
+
5
+ export {DateRegex};
6
+
7
+ function pathIsDate(path: string): boolean {
8
+ validatePath(path);
9
+
10
+ return DateRegex.test(path);
11
+ }
12
+
13
+ export default pathIsDate;
@@ -0,0 +1,24 @@
1
+ import {InvalidError} from 'lib/errors';
2
+
3
+ import {DateRegex} from 'server/utility/path-is-date';
4
+ import createDate from 'server/utility/create-date';
5
+
6
+ function pathToDate(key: string): Date {
7
+ const match = key.match(DateRegex);
8
+
9
+ if (!match) {
10
+ throw new InvalidError(`Key did not include a valid date: ${key}`);
11
+ }
12
+
13
+ const month = parseInt(match[2]) - 1;
14
+ const day = parseInt(match[3]);
15
+ const year = parseInt(match[4]);
16
+
17
+ if (isNaN(month) || isNaN(day) || isNaN(year)) {
18
+ throw new InvalidError(`Key did not include a valid date: ${key}`);
19
+ }
20
+
21
+ return createDate(year, month, day);
22
+ }
23
+
24
+ export default pathToDate;
@@ -0,0 +1,7 @@
1
+ import addDays from 'server/utility/add-days';
2
+
3
+ function subtractDays(old_date: Date, days: number): Date {
4
+ return addDays(old_date, days * -1);
5
+ }
6
+
7
+ export default subtractDays;
@@ -0,0 +1,10 @@
1
+ import Month from 'type/month';
2
+ import monthToDate from 'server/utility/month-to-date';
3
+
4
+ function validateMonth(month: Month): Month {
5
+ monthToDate(month);
6
+
7
+ return month;
8
+ }
9
+
10
+ export default validateMonth;
@@ -0,0 +1,46 @@
1
+ import {InvariantViolation} from 'lib/errors';
2
+
3
+ import Page from 'type/page';
4
+ import Block from 'type/block';
5
+
6
+ interface PageWithPossibleTitle extends Page {
7
+ readonly title?: string;
8
+ }
9
+
10
+ function validateBlock(block: Block, page_path: string, index: number): void {
11
+ if (typeof block !== 'object') {
12
+ throw new InvariantViolation(`
13
+ Invalid block in page ${page_path} at index ${index}: not a block object
14
+ `);
15
+ }
16
+
17
+ if (typeof block.created_at !== 'number') {
18
+ throw new InvariantViolation(`
19
+ Block in page ${page_path} at index ${index} did not have a valid created_at
20
+ `);
21
+ }
22
+ }
23
+
24
+ function validatePage(page: Page): void {
25
+ const {path} = page;
26
+
27
+ if (path === undefined) {
28
+ throw new InvariantViolation(`
29
+ Page had no path: ${JSON.stringify(page)}
30
+ `);
31
+ }
32
+
33
+ const coerced_page = page as PageWithPossibleTitle;
34
+
35
+ if (coerced_page.title !== undefined) {
36
+ throw new InvariantViolation(`
37
+ Page had a title: ${JSON.stringify(page)}
38
+ `);
39
+ }
40
+
41
+ coerced_page.blocks.forEach((block, index) => {
42
+ validateBlock(block, path, index);
43
+ });
44
+ }
45
+
46
+ export default validatePage;
@@ -0,0 +1,9 @@
1
+ import {InvalidError} from 'lib/errors';
2
+
3
+ function validatePath(path: string): void {
4
+ if (!path.startsWith('/')) {
5
+ throw new InvalidError(`Invalid path: ${path}`);
6
+ }
7
+ }
8
+
9
+ export default validatePath;
@@ -0,0 +1,12 @@
1
+ import {InvalidError} from 'lib/errors';
2
+
3
+ function validateUrl(url: string): void {
4
+ try {
5
+ new URL(url);
6
+ } catch (error) {
7
+ console.trace();
8
+ throw new InvalidError(`Invalid url: ${url}`);
9
+ }
10
+ }
11
+
12
+ export default validateUrl;
@@ -0,0 +1,10 @@
1
+ import getStartOfWeek from 'server/utility/get-start-of-week';
2
+
3
+ function weekGreaterThan(date: Date, target: Date): boolean {
4
+ const truncated_date = getStartOfWeek(date);
5
+ const truncated_target = getStartOfWeek(target);
6
+
7
+ return truncated_date > truncated_target;
8
+ }
9
+
10
+ export default weekGreaterThan;
@@ -0,0 +1,8 @@
1
+ import Week from 'type/week';
2
+ import dayToDate from 'server/utility/day-to-date';
3
+
4
+ function weekToDate(week: Week): Date {
5
+ return dayToDate(week);
6
+ }
7
+
8
+ export default weekToDate;
@@ -0,0 +1,12 @@
1
+ import getMonthName from 'server/utility/get-month-name';
2
+ import getPaddedDate from 'server/utility/get-padded-date';
3
+
4
+ function weekToPath(week: Date): string {
5
+ const month_name = getMonthName(week);
6
+ const day = getPaddedDate(week);
7
+ const year = week.getUTCFullYear();
8
+
9
+ return `/week/${month_name}-${day}-${year}`;
10
+ }
11
+
12
+ export default weekToPath;
@@ -0,0 +1,8 @@
1
+ import datesAreEqual from 'server/utility/dates-are-equal';
2
+ import getStartOfWeek from 'server/utility/get-start-of-week';
3
+
4
+ function weeksAreEqual(a: Date, b: Date): boolean {
5
+ return datesAreEqual(getStartOfWeek(a), getStartOfWeek(b));
6
+ }
7
+
8
+ export default weeksAreEqual;
@@ -0,0 +1,26 @@
1
+ import {InvalidError} from 'lib/errors';
2
+
3
+ import Year from 'type/year';
4
+
5
+ const YEAR_REGEX = new RegExp(`^([0-9][0-9][0-9][0-9])$`);
6
+
7
+ function yearToDate(year: Year): Date {
8
+ const {key} = year;
9
+ const match = key.match(YEAR_REGEX);
10
+
11
+ if (!match) {
12
+ throw new InvalidError(`Invalid year: ${key}`);
13
+ }
14
+
15
+ const numeric_year = parseInt(match[1]);
16
+
17
+ if (isNaN(numeric_year)) {
18
+ throw new InvalidError(`Invalid year: ${key}`);
19
+ }
20
+
21
+ const date_string = `${numeric_year}-01-01`;
22
+
23
+ return new Date(date_string);
24
+ }
25
+
26
+ export default yearToDate;
@@ -0,0 +1,7 @@
1
+ function yearToPath(date: Date): string {
2
+ const year = date.getUTCFullYear();
3
+
4
+ return `/year/${year}`;
5
+ }
6
+
7
+ export default yearToPath;
@@ -0,0 +1,8 @@
1
+ import datesAreEqual from 'server/utility/dates-are-equal';
2
+ import getStartOfYear from 'server/utility/get-start-of-year';
3
+
4
+ function yearsAreEqual(a: Date, b: Date): boolean {
5
+ return datesAreEqual(getStartOfYear(a), getStartOfYear(b));
6
+ }
7
+
8
+ export default yearsAreEqual;