@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.
- package/LICENSE +673 -0
- package/README.md +5 -0
- package/bin/compile +63 -0
- package/bin/copy-static-files +13 -0
- package/bin/install +5 -0
- package/bin/precompile +55 -0
- package/bin/prepublish +7 -0
- package/bin/remap-paths +113 -0
- package/bin/test +9 -0
- package/config/tsconfig.json +37 -0
- package/package.json +33 -0
- package/src/bootstrap/start.ts +12 -0
- package/src/client/bootstrap.ts +5 -0
- package/src/client/client.ts +54 -0
- package/src/client/enum/key-code.ts +34 -0
- package/src/client/enum/page-type.ts +19 -0
- package/src/client/factory/page.ts +61 -0
- package/src/client/page/confirm-delete-block.ts +30 -0
- package/src/client/page/create-block.ts +6 -0
- package/src/client/page/day.ts +8 -0
- package/src/client/page/edit-block.ts +43 -0
- package/src/client/page/edit-custom.ts +16 -0
- package/src/client/page/home.ts +8 -0
- package/src/client/page/login.ts +8 -0
- package/src/client/page/logout.ts +8 -0
- package/src/client/page/month.ts +8 -0
- package/src/client/page/move-block.ts +8 -0
- package/src/client/page/select-block-type.ts +56 -0
- package/src/client/page/settings.ts +8 -0
- package/src/client/page/view-custom.ts +665 -0
- package/src/client/page/week.ts +8 -0
- package/src/client/page/year.ts +8 -0
- package/src/client/page.ts +128 -0
- package/src/client/shim/execute.ts +5 -0
- package/src/client/shim/logger.ts +44 -0
- package/src/client/utility/get-meta-value.ts +23 -0
- package/src/common/builder/block/background.ts +25 -0
- package/src/common/builder/block/folder.ts +43 -0
- package/src/common/builder/block/header.ts +15 -0
- package/src/common/builder/block/link.ts +32 -0
- package/src/common/builder/block/multicolumn.ts +16 -0
- package/src/common/builder/block/note.ts +13 -0
- package/src/common/builder/block/whitespace.ts +13 -0
- package/src/common/utility/get-parent-path.ts +29 -0
- package/src/constant/month-names.ts +16 -0
- package/src/enum/action-type.ts +11 -0
- package/src/enum/block-type.ts +18 -0
- package/src/enum/calendar-view-mode.ts +9 -0
- package/src/enum/color.ts +15 -0
- package/src/enum/default-role.ts +6 -0
- package/src/enum/directory-item-type.ts +6 -0
- package/src/enum/emoji.ts +94 -0
- package/src/enum/field-type.ts +8 -0
- package/src/enum/header-size.ts +7 -0
- package/src/enum/permission-type.ts +8 -0
- package/src/enum/time-place-visibility.ts +8 -0
- package/src/enum/tool-type.ts +14 -0
- package/src/index.ts +8 -0
- package/src/interface/hydration-callback.ts +7 -0
- package/src/interface/provider.ts +8 -0
- package/src/interface/repository.ts +12 -0
- package/src/lib/array/add.ts +10 -0
- package/src/lib/array/assert-is-empty.ts +23 -0
- package/src/lib/array/clone.ts +5 -0
- package/src/lib/array/difference.ts +8 -0
- package/src/lib/array/empty.ts +6 -0
- package/src/lib/array/equal.ts +24 -0
- package/src/lib/array/get-first-value.ts +5 -0
- package/src/lib/array/get-last-value.ts +5 -0
- package/src/lib/array/get-max-value.ts +5 -0
- package/src/lib/array/get-value-after.ts +23 -0
- package/src/lib/array/get-value-before.ts +23 -0
- package/src/lib/array/get-values-between.ts +18 -0
- package/src/lib/array/index.ts +5 -0
- package/src/lib/array/is-empty.ts +6 -0
- package/src/lib/array/remove.ts +19 -0
- package/src/lib/array/sum.ts +11 -0
- package/src/lib/array/unique.ts +13 -0
- package/src/lib/environment/bootstrap.ts +1 -0
- package/src/lib/environment/enum/environment-type.ts +8 -0
- package/src/lib/environment/enum/service-type.ts +5 -0
- package/src/lib/environment/index.ts +7 -0
- package/src/lib/environment/utility/get-environment-type.ts +28 -0
- package/src/lib/environment/utility/is-browser.ts +5 -0
- package/src/lib/environment/utility/is-development.ts +10 -0
- package/src/lib/environment/utility/is-production-or-staging.ts +8 -0
- package/src/lib/environment/utility/is-production.ts +10 -0
- package/src/lib/environment/utility/is-staging.ts +10 -0
- package/src/lib/errors/enum/error-type.ts +13 -0
- package/src/lib/errors/error/base.ts +40 -0
- package/src/lib/errors/error/conflict.ts +16 -0
- package/src/lib/errors/error/generic.ts +23 -0
- package/src/lib/errors/error/invalid.ts +14 -0
- package/src/lib/errors/error/invariant-violation.ts +5 -0
- package/src/lib/errors/error/not-allowed.ts +14 -0
- package/src/lib/errors/error/not-found.ts +16 -0
- package/src/lib/errors/error/not-implemented.ts +20 -0
- package/src/lib/errors/error/omitted.ts +14 -0
- package/src/lib/errors/error/timeout.ts +14 -0
- package/src/lib/errors/error/unauthorized.ts +14 -0
- package/src/lib/errors/index.ts +18 -0
- package/src/lib/errors/sugar/invariant.ts +7 -0
- package/src/lib/errors/type/coded-error.ts +7 -0
- package/src/lib/errors/type/error-data.ts +11 -0
- package/src/lib/errors/utility/create-error-for-error-type.ts +60 -0
- package/src/lib/errors/utility/create-error-from-ambiguous-json-data.ts +26 -0
- package/src/lib/errors/utility/error-matches.ts +28 -0
- package/src/lib/errors/utility/get-error-type-for-posix-error-code.ts +37 -0
- package/src/lib/errors/utility/get-error-type-for-status-code.ts +38 -0
- package/src/lib/errors/utility/get-message-for-error-type.ts +29 -0
- package/src/lib/errors/utility/matches-posix-error-code.ts +11 -0
- package/src/lib/errors/utility/wrap-error.ts +39 -0
- package/src/lib/event-emitter/index.ts +63 -0
- package/src/lib/execution-context/execution-context.ts +90 -0
- package/src/lib/execution-context/index.ts +8 -0
- package/src/lib/execution-context/type/session.ts +7 -0
- package/src/lib/feature/feature.ts +108 -0
- package/src/lib/feature/index.ts +3 -0
- package/src/lib/filesystem/bootstrap.ts +1 -0
- package/src/lib/filesystem/enum/file-extension.ts +19 -0
- package/src/lib/filesystem/index.ts +4 -0
- package/src/lib/filesystem/utility/exists.ts +21 -0
- package/src/lib/filesystem/utility/get-extension-for-filepath.ts +20 -0
- package/src/lib/filesystem/utility/strip-extension.ts +26 -0
- package/src/lib/grammar/index.ts +3 -0
- package/src/lib/grammar/noun-inflector.ts +104 -0
- package/src/lib/grammar/utility/get-words-from-identifier.ts +9 -0
- package/src/lib/grammar/verb-inflector.ts +344 -0
- package/src/lib/http/buffer-stream.ts +76 -0
- package/src/lib/http/enum/content-type.ts +19 -0
- package/src/lib/http/enum/cookie-attribute.ts +11 -0
- package/src/lib/http/enum/header.ts +29 -0
- package/src/lib/http/enum/method.ts +11 -0
- package/src/lib/http/enum/same-site-policy.ts +7 -0
- package/src/lib/http/enum/status-code.ts +9 -0
- package/src/lib/http/factory/body-parser.ts +55 -0
- package/src/lib/http/index.ts +24 -0
- package/src/lib/http/interface/client-request.ts +15 -0
- package/src/lib/http/interface/incoming-message.ts +24 -0
- package/src/lib/http/interface/network-library.ts +9 -0
- package/src/lib/http/interface/request-callback.ts +7 -0
- package/src/lib/http/isomorphic/request.ts +77 -0
- package/src/lib/http/isomorphic/response.ts +77 -0
- package/src/lib/http/isomorphic.ts +20 -0
- package/src/lib/http/parser/accept-header.ts +35 -0
- package/src/lib/http/parser/basic-auth-header.ts +48 -0
- package/src/lib/http/parser/body/json.ts +14 -0
- package/src/lib/http/parser/body/multipart.ts +89 -0
- package/src/lib/http/parser/body/url-encoded.ts +16 -0
- package/src/lib/http/parser/body.ts +44 -0
- package/src/lib/http/parser/cookie.ts +114 -0
- package/src/lib/http/parser/querystring.ts +92 -0
- package/src/lib/http/parser/url.ts +76 -0
- package/src/lib/http/request/incoming.ts +299 -0
- package/src/lib/http/request/outgoing.ts +276 -0
- package/src/lib/http/request.ts +26 -0
- package/src/lib/http/response/incoming.ts +243 -0
- package/src/lib/http/response/outgoing.ts +160 -0
- package/src/lib/http/response.ts +74 -0
- package/src/lib/http/serializer/basic-auth-header.ts +27 -0
- package/src/lib/http/serializer/cookie.ts +90 -0
- package/src/lib/http/serializer/query-data.ts +54 -0
- package/src/lib/http/transaction.ts +320 -0
- package/src/lib/http/type/basic-auth-credentials.ts +6 -0
- package/src/lib/http/type/header-map.ts +5 -0
- package/src/lib/http/type/log-attributes.ts +12 -0
- package/src/lib/http/type/path-parameters.ts +5 -0
- package/src/lib/http/type/query-data.ts +7 -0
- package/src/lib/http/type/query-value.ts +11 -0
- package/src/lib/http/type/request-options.ts +16 -0
- package/src/lib/http/type/transaction-data.ts +4 -0
- package/src/lib/http/utility/get-content-type-for-extension.ts +47 -0
- package/src/lib/http/utility/get-library-for-protocol.ts +25 -0
- package/src/lib/http/utility/get-status-code-for-error-type.ts +37 -0
- package/src/lib/http/utility/get-status-code-for-error.ts +13 -0
- package/src/lib/http/utility/is-client-error-status.ts +15 -0
- package/src/lib/http/utility/is-error-status.ts +9 -0
- package/src/lib/http/utility/is-server-error-status.ts +7 -0
- package/src/lib/http/utility/is-success-status.ts +7 -0
- package/src/lib/http/utility/proxy-request.ts +58 -0
- package/src/lib/http/utility/serialize-request-options.ts +9 -0
- package/src/lib/http/utility/slug-generator.ts +20 -0
- package/src/lib/key-generator/index.ts +3 -0
- package/src/lib/key-generator/key-generator.ts +7 -0
- package/src/lib/logger/enum/ansi-escape-code.ts +14 -0
- package/src/lib/logger/enum/log-level.ts +8 -0
- package/src/lib/logger/formatter.ts +59 -0
- package/src/lib/logger/index.ts +7 -0
- package/src/lib/logger/interface/error-reporter.ts +7 -0
- package/src/lib/logger/interface/logger.ts +13 -0
- package/src/lib/logger/logger.ts +239 -0
- package/src/lib/logger/type/error-parameters.ts +9 -0
- package/src/lib/logger/type/loggable-data.ts +5 -0
- package/src/lib/logger/type/loggable-value.ts +1 -0
- package/src/lib/metrics/dispatcher.ts +264 -0
- package/src/lib/metrics/enum/dispatch-mode.ts +6 -0
- package/src/lib/metrics/index.ts +2 -0
- package/src/lib/metrics/settings-hydrator.ts +51 -0
- package/src/lib/metrics/type/dispatcher-settings.ts +12 -0
- package/src/lib/metrics/type/tag-map.ts +5 -0
- package/src/lib/network/bootstrap.ts +1 -0
- package/src/lib/network/enum/connection-status.ts +14 -0
- package/src/lib/network/enum/http-status-code.ts +75 -0
- package/src/lib/network/enum/network-protocol.ts +10 -0
- package/src/lib/network/event-emitter.ts +63 -0
- package/src/lib/network/index.ts +7 -0
- package/src/lib/network/interface/socket.ts +42 -0
- package/src/lib/network/type/socket-options.ts +6 -0
- package/src/lib/network/utility/get-protocol-from-url.ts +15 -0
- package/src/lib/operation/index.ts +6 -0
- package/src/lib/operation/operation/auto-logging.ts +94 -0
- package/src/lib/operation/operation/silent.ts +17 -0
- package/src/lib/operation/operation.ts +80 -0
- package/src/lib/process/bootstrap.ts +1 -0
- package/src/lib/process/enum/posix-error-code.ts +138 -0
- package/src/lib/process/enum/process-signal.ts +68 -0
- package/src/lib/process/error.ts +6 -0
- package/src/lib/process/execute.ts +77 -0
- package/src/lib/process/index.ts +4 -0
- package/src/lib/process/type/command-options.ts +9 -0
- package/src/lib/process/utility/bind-process-lifespan-to.ts +10 -0
- package/src/lib/promise-wrapper/index.ts +3 -0
- package/src/lib/promise-wrapper/promise-wrapper.ts +51 -0
- package/src/lib/random/chance.ts +5 -0
- package/src/lib/random/element.ts +7 -0
- package/src/lib/random/elements.ts +12 -0
- package/src/lib/random/enum.ts +34 -0
- package/src/lib/random/enums.ts +11 -0
- package/src/lib/random/index.ts +3 -0
- package/src/lib/random/number.ts +8 -0
- package/src/lib/server/base.ts +194 -0
- package/src/lib/server/enum/server-event.ts +5 -0
- package/src/lib/server/enum/server-status.ts +10 -0
- package/src/lib/server/http/endpoint/ping.ts +21 -0
- package/src/lib/server/http/endpoint.ts +345 -0
- package/src/lib/server/http/interface/endpoint-constructor.ts +12 -0
- package/src/lib/server/http/interface/result-serializer.ts +5 -0
- package/src/lib/server/http/middleware.ts +18 -0
- package/src/lib/server/http/result-serializer/html.ts +92 -0
- package/src/lib/server/http/result-serializer/json.ts +23 -0
- package/src/lib/server/http/route.ts +104 -0
- package/src/lib/server/http/router.ts +125 -0
- package/src/lib/server/http/type/session-resolver.ts +8 -0
- package/src/lib/server/http/utility/create-server.ts +34 -0
- package/src/lib/server/http/utility/path-parser.ts +49 -0
- package/src/lib/server/http/utility/standardize-html-indentation.ts +54 -0
- package/src/lib/server/http/websocket-wrapper.ts +83 -0
- package/src/lib/server/http.ts +301 -0
- package/src/lib/server/index.ts +5 -0
- package/src/lib/server/tcp.ts +53 -0
- package/src/lib/server/type/server-options.ts +10 -0
- package/src/lib/string/calculate-length.ts +17 -0
- package/src/lib/string/capitalize.ts +8 -0
- package/src/lib/string/create-slug.ts +14 -0
- package/src/lib/string/enum/ansi-escape-code.ts +14 -0
- package/src/lib/string/enum/string-encoding.ts +9 -0
- package/src/lib/string/hyphenate.ts +5 -0
- package/src/lib/string/index.ts +3 -0
- package/src/lib/string/pad.ts +14 -0
- package/src/lib/string/trim-multiline.ts +21 -0
- package/src/lib/string/trim.ts +8 -0
- package/src/lib/tcp/channel.ts +13 -0
- package/src/lib/tcp/connection/incoming.ts +72 -0
- package/src/lib/tcp/connection/outgoing.ts +219 -0
- package/src/lib/tcp/connection.ts +360 -0
- package/src/lib/tcp/enum/connection-event.ts +12 -0
- package/src/lib/tcp/enum/message-type.ts +9 -0
- package/src/lib/tcp/index.ts +1 -0
- package/src/lib/tcp/type/connection-parameters.ts +6 -0
- package/src/lib/tcp/type/message/channel-close.ts +9 -0
- package/src/lib/tcp/type/message/channel-open.ts +9 -0
- package/src/lib/tcp/type/message.ts +10 -0
- package/src/lib/test/index.ts +2 -0
- package/src/lib/test/utility/build-config.ts +17 -0
- package/src/lib/test/utility/build-execution-context.ts +11 -0
- package/src/lib/time/bootstrap.ts +1 -0
- package/src/lib/time/enum/time-interval.ts +12 -0
- package/src/lib/time/index.ts +4 -0
- package/src/lib/time/utility/format-duration.ts +139 -0
- package/src/lib/time/utility/format-relative-duration.ts +22 -0
- package/src/lib/time/utility/sleep.ts +9 -0
- package/src/operation.ts +18 -0
- package/src/server/endpoint/abstract-page.ts +126 -0
- package/src/server/endpoint/action/create.ts +545 -0
- package/src/server/endpoint/action/get.ts +231 -0
- package/src/server/endpoint/base.ts +51 -0
- package/src/server/endpoint/day.ts +13 -0
- package/src/server/endpoint/generic-page.ts +14 -0
- package/src/server/endpoint/index.ts +11 -0
- package/src/server/endpoint/login.ts +45 -0
- package/src/server/endpoint/logout.ts +38 -0
- package/src/server/endpoint/month.ts +35 -0
- package/src/server/endpoint/robots.ts +18 -0
- package/src/server/endpoint/session/create.ts +62 -0
- package/src/server/endpoint/settings/get.ts +40 -0
- package/src/server/endpoint/settings/update.ts +44 -0
- package/src/server/endpoint/today.ts +15 -0
- package/src/server/endpoint/week.ts +34 -0
- package/src/server/endpoint/year.ts +34 -0
- package/src/server/enum/custom-page-type.ts +10 -0
- package/src/server/factory/block-result-serializer.ts +115 -0
- package/src/server/middleware/base.ts +6 -0
- package/src/server/middleware/error-handler.ts +177 -0
- package/src/server/middleware/static-file.ts +83 -0
- package/src/server/operation/add-block.ts +110 -0
- package/src/server/operation/create-session.ts +43 -0
- package/src/server/operation/delete-block.ts +96 -0
- package/src/server/operation/demote-block.ts +108 -0
- package/src/server/operation/destroy-session.ts +26 -0
- package/src/server/operation/load-account.ts +30 -0
- package/src/server/operation/load-block.ts +48 -0
- package/src/server/operation/load-directory-items.ts +75 -0
- package/src/server/operation/load-page.ts +368 -0
- package/src/server/operation/promote-block.ts +104 -0
- package/src/server/operation/save-page.ts +60 -0
- package/src/server/operation/update-account-settings.ts +52 -0
- package/src/server/operation/update-block.ts +124 -0
- package/src/server/repository/memory.ts +112 -0
- package/src/server/result-serializer/action.ts +939 -0
- package/src/server/result-serializer/base.ts +1267 -0
- package/src/server/result-serializer/block/audio.ts +33 -0
- package/src/server/result-serializer/block/background.ts +20 -0
- package/src/server/result-serializer/block/calendar.ts +148 -0
- package/src/server/result-serializer/block/directory.ts +57 -0
- package/src/server/result-serializer/block/ephemeral.ts +14 -0
- package/src/server/result-serializer/block/folder.ts +106 -0
- package/src/server/result-serializer/block/header.ts +31 -0
- package/src/server/result-serializer/block/image.ts +46 -0
- package/src/server/result-serializer/block/link.ts +40 -0
- package/src/server/result-serializer/block/list.ts +140 -0
- package/src/server/result-serializer/block/multi-column.ts +97 -0
- package/src/server/result-serializer/block/note.ts +44 -0
- package/src/server/result-serializer/block/todo.ts +78 -0
- package/src/server/result-serializer/block/whitespace.ts +15 -0
- package/src/server/result-serializer/block.ts +248 -0
- package/src/server/result-serializer/common/time-place-options.ts +33 -0
- package/src/server/result-serializer/login.ts +58 -0
- package/src/server/result-serializer/month.ts +170 -0
- package/src/server/result-serializer/page.ts +548 -0
- package/src/server/result-serializer/settings.ts +85 -0
- package/src/server/result-serializer/week.ts +195 -0
- package/src/server/result-serializer/year.ts +160 -0
- package/src/server/utility/accepts-content-type.ts +16 -0
- package/src/server/utility/accepts-html.ts +9 -0
- package/src/server/utility/accepts-json.ts +9 -0
- package/src/server/utility/add-days.ts +11 -0
- package/src/server/utility/create-date.ts +23 -0
- package/src/server/utility/create-index-path.ts +5 -0
- package/src/server/utility/create-slug.ts +9 -0
- package/src/server/utility/create-toast-path.ts +19 -0
- package/src/server/utility/date-less-than.ts +5 -0
- package/src/server/utility/date-occurs-before.ts +22 -0
- package/src/server/utility/date-to-key.ts +7 -0
- package/src/server/utility/date-to-label.ts +5 -0
- package/src/server/utility/date-to-path.ts +9 -0
- package/src/server/utility/dates-are-equal.ts +22 -0
- package/src/server/utility/dates-are-in-order.ts +9 -0
- package/src/server/utility/dates-are-on-the-same-day.ts +9 -0
- package/src/server/utility/dates-in-same-month.ts +8 -0
- package/src/server/utility/day-to-date.ts +40 -0
- package/src/server/utility/decrement-date.ts +11 -0
- package/src/server/utility/get-block-at-index-path.ts +32 -0
- package/src/server/utility/get-block-permissions.ts +15 -0
- package/src/server/utility/get-compact-label-for-date.ts +8 -0
- package/src/server/utility/get-custom-page-type-for-path.ts +37 -0
- package/src/server/utility/get-element-id-for-block.ts +15 -0
- package/src/server/utility/get-emoji-for-block-type.ts +39 -0
- package/src/server/utility/get-emoji-for-tool-type.ts +20 -0
- package/src/server/utility/get-end-of-month.ts +13 -0
- package/src/server/utility/get-end-of-week.ts +13 -0
- package/src/server/utility/get-filepath-for-folder-block.ts +23 -0
- package/src/server/utility/get-hex-for-color.ts +31 -0
- package/src/server/utility/get-label-for-time-place-visibility.ts +23 -0
- package/src/server/utility/get-month-name.ts +18 -0
- package/src/server/utility/get-next-day.ts +7 -0
- package/src/server/utility/get-next-month.ts +12 -0
- package/src/server/utility/get-next-week.ts +12 -0
- package/src/server/utility/get-next-year.ts +13 -0
- package/src/server/utility/get-ordinal-label-for-week.ts +11 -0
- package/src/server/utility/get-ordinal-of-week-within-month.ts +15 -0
- package/src/server/utility/get-padded-date.ts +11 -0
- package/src/server/utility/get-parent-index-path.ts +18 -0
- package/src/server/utility/get-path-for-folder-block.ts +25 -0
- package/src/server/utility/get-path-from-url.ts +13 -0
- package/src/server/utility/get-previous-index-path.ts +27 -0
- package/src/server/utility/get-previous-month.ts +12 -0
- package/src/server/utility/get-previous-week.ts +11 -0
- package/src/server/utility/get-previous-year.ts +13 -0
- package/src/server/utility/get-random-emoji-for-date.ts +109 -0
- package/src/server/utility/get-short-label-for-date.ts +11 -0
- package/src/server/utility/get-short-month-name.ts +9 -0
- package/src/server/utility/get-short-ordinal.ts +26 -0
- package/src/server/utility/get-siblings-and-index-for-index-path.ts +67 -0
- package/src/server/utility/get-start-of-month.ts +11 -0
- package/src/server/utility/get-start-of-week.ts +12 -0
- package/src/server/utility/get-start-of-year.ts +12 -0
- package/src/server/utility/get-weekday-name.ts +24 -0
- package/src/server/utility/increment-date.ts +15 -0
- package/src/server/utility/is-index-path.ts +5 -0
- package/src/server/utility/key-to-date.ts +25 -0
- package/src/server/utility/month-has-week-containing-date.ts +13 -0
- package/src/server/utility/month-to-date.ts +28 -0
- package/src/server/utility/month-to-path.ts +10 -0
- package/src/server/utility/months-are-equal.ts +8 -0
- package/src/server/utility/parse-index-path.ts +23 -0
- package/src/server/utility/path-is-date.ts +13 -0
- package/src/server/utility/path-to-date.ts +24 -0
- package/src/server/utility/subtract-days.ts +7 -0
- package/src/server/utility/validate-month.ts +10 -0
- package/src/server/utility/validate-page.ts +46 -0
- package/src/server/utility/validate-path.ts +9 -0
- package/src/server/utility/validate-url.ts +12 -0
- package/src/server/utility/week-greater-than.ts +10 -0
- package/src/server/utility/week-to-date.ts +8 -0
- package/src/server/utility/week-to-path.ts +12 -0
- package/src/server/utility/weeks-are-equal.ts +8 -0
- package/src/server/utility/year-to-date.ts +26 -0
- package/src/server/utility/year-to-path.ts +7 -0
- package/src/server/utility/years-are-equal.ts +8 -0
- package/src/server.ts +140 -0
- package/src/test.ts +195 -0
- package/src/type/account-settings.ts +9 -0
- package/src/type/account.ts +11 -0
- package/src/type/action/add-block.ts +74 -0
- package/src/type/action/complete-block.ts +10 -0
- package/src/type/action/delete-block.ts +11 -0
- package/src/type/action/demote-block.ts +9 -0
- package/src/type/action/edit-block.ts +11 -0
- package/src/type/action/promote-block.ts +9 -0
- package/src/type/action.ts +9 -0
- package/src/type/block/audio.ts +8 -0
- package/src/type/block/background.ts +10 -0
- package/src/type/block/directory.ts +18 -0
- package/src/type/block/ephemeral.ts +9 -0
- package/src/type/block/folder.ts +14 -0
- package/src/type/block/header.ts +11 -0
- package/src/type/block/image.ts +8 -0
- package/src/type/block/link.ts +12 -0
- package/src/type/block/list.ts +24 -0
- package/src/type/block/multi-column.ts +10 -0
- package/src/type/block/note.ts +9 -0
- package/src/type/block/todo.ts +10 -0
- package/src/type/block/whitespace.ts +9 -0
- package/src/type/block-metadata.ts +14 -0
- package/src/type/block.ts +18 -0
- package/src/type/day.ts +5 -0
- package/src/type/field-definition.ts +8 -0
- package/src/type/field-value.ts +5 -0
- package/src/type/file.ts +6 -0
- package/src/type/month.ts +5 -0
- package/src/type/page.ts +8 -0
- package/src/type/price.ts +11 -0
- package/src/type/resource.ts +5 -0
- package/src/type/runtime-config.ts +13 -0
- package/src/type/server-settings.ts +17 -0
- package/src/type/toast.ts +8 -0
- package/src/type/week.ts +5 -0
- package/src/type/year.ts +5 -0
- package/test/unit/index.ts +11 -0
- package/test/unit/server/operation/promote-block.ts +84 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// This is a stripped-down representation of HTTP.ClientRequest, which has a
|
|
2
|
+
// lot of extra bells and whistles that we don't use, and which I didn't copy
|
|
3
|
+
// over into the isomorphic library.
|
|
4
|
+
|
|
5
|
+
interface ErrorCallback {
|
|
6
|
+
(error: Error): void;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface ClientRequest {
|
|
10
|
+
on(event: 'error', callback: ErrorCallback): void;
|
|
11
|
+
write(content: Buffer): void;
|
|
12
|
+
end(): void;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default ClientRequest;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import StatusCode from 'lib/http/enum/status-code';
|
|
2
|
+
|
|
3
|
+
interface EndCallback {
|
|
4
|
+
(): void;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
interface DataCallback {
|
|
8
|
+
(data: Buffer): void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface ErrorCallback {
|
|
12
|
+
(error: Error): void;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface IncomingMessage {
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
17
|
+
statusCode?: StatusCode;
|
|
18
|
+
headers: Record<string, string | string[] | undefined>;
|
|
19
|
+
on(event: 'end', callback: EndCallback): void;
|
|
20
|
+
on(event: 'data', callback: DataCallback): void;
|
|
21
|
+
on(event: 'error', callback: ErrorCallback): void;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default IncomingMessage;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import ClientRequest from 'lib/http/interface/client-request';
|
|
2
|
+
import RequestOptions from 'lib/http/type/request-options';
|
|
3
|
+
import RequestCallback from 'lib/http/interface/request-callback';
|
|
4
|
+
|
|
5
|
+
interface NetworkLibrary {
|
|
6
|
+
request(options: RequestOptions, callback: RequestCallback): ClientRequest;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export default NetworkLibrary;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import {StringEncoding} from 'lib/string';
|
|
2
|
+
import {EventEmitter} from 'lib/network';
|
|
3
|
+
|
|
4
|
+
import HttpMethod from 'lib/http/enum/method';
|
|
5
|
+
import ClientRequest from 'lib/http/interface/client-request';
|
|
6
|
+
import RequestOptions from 'lib/http/type/request-options';
|
|
7
|
+
import IsomorphicResponse from 'lib/http/isomorphic/response';
|
|
8
|
+
|
|
9
|
+
class IsomorphicRequest extends EventEmitter implements ClientRequest {
|
|
10
|
+
private options: RequestOptions;
|
|
11
|
+
private data: Buffer;
|
|
12
|
+
|
|
13
|
+
public constructor(options: RequestOptions) {
|
|
14
|
+
super();
|
|
15
|
+
|
|
16
|
+
this.options = options;
|
|
17
|
+
this.data = Buffer.from('');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public write(content: Buffer): void {
|
|
21
|
+
this.data = Buffer.concat([this.data, content]);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public end(): void {
|
|
25
|
+
// NOTE: `protocol` should be affixed with a trailing colon already:
|
|
26
|
+
const {protocol, hostname, port, path, method, headers} = this.getOptions();
|
|
27
|
+
const url = `${protocol}//${hostname}:${port}${path}`;
|
|
28
|
+
const body = this.getBody();
|
|
29
|
+
|
|
30
|
+
const raw_request = new Request(url, {
|
|
31
|
+
method,
|
|
32
|
+
headers,
|
|
33
|
+
body
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const promise = window.fetch(raw_request);
|
|
37
|
+
|
|
38
|
+
promise.then(this.handleRawResponse.bind(this));
|
|
39
|
+
promise.catch(this.handleError.bind(this));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
private handleRawResponse(raw_response: Response): void {
|
|
43
|
+
const response = new IsomorphicResponse(raw_response);
|
|
44
|
+
|
|
45
|
+
this.emit('response', response);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private handleError(error: Error): void {
|
|
49
|
+
this.emit('error', error);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
private getBody(): string | undefined {
|
|
53
|
+
const method = this.getMethod();
|
|
54
|
+
|
|
55
|
+
switch (method) {
|
|
56
|
+
case HttpMethod.HEAD:
|
|
57
|
+
case HttpMethod.GET:
|
|
58
|
+
case HttpMethod.DELETE:
|
|
59
|
+
case HttpMethod.OPTIONS:
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return this.data.toString(StringEncoding.UTF8);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private getMethod(): HttpMethod {
|
|
67
|
+
const options = this.getOptions();
|
|
68
|
+
|
|
69
|
+
return options.method;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
private getOptions(): RequestOptions {
|
|
73
|
+
return this.options;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export default IsomorphicRequest;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import {EventEmitter} from 'lib/network';
|
|
2
|
+
|
|
3
|
+
import HeaderMap from 'lib/http/type/header-map';
|
|
4
|
+
import StatusCode from 'lib/http/enum/status-code';
|
|
5
|
+
import IncomingMessage from 'lib/http/interface/incoming-message';
|
|
6
|
+
|
|
7
|
+
function isArrayBufferSupported(): boolean {
|
|
8
|
+
if (typeof Buffer === 'undefined') {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const array = new Uint8Array([1]);
|
|
13
|
+
const buffer = Buffer.from(array.buffer);
|
|
14
|
+
|
|
15
|
+
return buffer[0] === 1;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const ARRAY_BUFFER_SUPPORTED = isArrayBufferSupported();
|
|
19
|
+
|
|
20
|
+
function convertHeaders(headers: Headers): HeaderMap {
|
|
21
|
+
const result: HeaderMap = {};
|
|
22
|
+
|
|
23
|
+
headers.forEach((value, key) => {
|
|
24
|
+
result[key] = value;
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function convertArrayBuffer(array_buffer: ArrayBuffer): Buffer {
|
|
31
|
+
if (ARRAY_BUFFER_SUPPORTED) {
|
|
32
|
+
return Buffer.from(array_buffer);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const buffer = Buffer.alloc(array_buffer.byteLength);
|
|
36
|
+
const view = new Uint8Array(array_buffer);
|
|
37
|
+
|
|
38
|
+
let i = 0;
|
|
39
|
+
|
|
40
|
+
while (i < buffer.length) {
|
|
41
|
+
buffer[i] = view[i];
|
|
42
|
+
i++;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return buffer;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
class IsomorphicResponse extends EventEmitter implements IncomingMessage {
|
|
49
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
50
|
+
public statusCode: StatusCode;
|
|
51
|
+
public headers: HeaderMap;
|
|
52
|
+
|
|
53
|
+
public constructor(raw_response: Response) {
|
|
54
|
+
super();
|
|
55
|
+
|
|
56
|
+
this.statusCode = raw_response.status as StatusCode;
|
|
57
|
+
this.headers = convertHeaders(raw_response.headers);
|
|
58
|
+
|
|
59
|
+
const promise = raw_response.arrayBuffer();
|
|
60
|
+
|
|
61
|
+
promise.then(this.handleEnd.bind(this));
|
|
62
|
+
promise.catch(this.handleError.bind(this));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private handleEnd(array_buffer: ArrayBuffer): void {
|
|
66
|
+
const buffer = convertArrayBuffer(array_buffer);
|
|
67
|
+
|
|
68
|
+
this.emit('data', buffer);
|
|
69
|
+
this.emit('end');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
private handleError(error: Error): void {
|
|
73
|
+
this.emit('error', error);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export default IsomorphicResponse;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import ClientRequest from 'lib/http/interface/client-request';
|
|
2
|
+
import RequestOptions from 'lib/http/type/request-options';
|
|
3
|
+
import NetworkLibrary from 'lib/http/interface/network-library';
|
|
4
|
+
import RequestCallback from 'lib/http/interface/request-callback';
|
|
5
|
+
import IsomorphicRequest from 'lib/http/isomorphic/request';
|
|
6
|
+
|
|
7
|
+
class IsomorphicHttp implements NetworkLibrary {
|
|
8
|
+
public request(
|
|
9
|
+
options: RequestOptions,
|
|
10
|
+
callback: RequestCallback
|
|
11
|
+
): ClientRequest {
|
|
12
|
+
const request = new IsomorphicRequest(options);
|
|
13
|
+
|
|
14
|
+
request.on('response', callback);
|
|
15
|
+
|
|
16
|
+
return request;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default IsomorphicHttp;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import ContentType from 'lib/http/enum/content-type';
|
|
2
|
+
|
|
3
|
+
class AcceptHeaderParser {
|
|
4
|
+
private accept_header: string;
|
|
5
|
+
|
|
6
|
+
public constructor(accept_header: string) {
|
|
7
|
+
this.accept_header = accept_header;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
public getContentType(): ContentType {
|
|
11
|
+
const accept_header = this.getAcceptHeader();
|
|
12
|
+
const parts = accept_header.split(',');
|
|
13
|
+
const supported_content_types = Object.values(ContentType) as string[];
|
|
14
|
+
|
|
15
|
+
// TODO: Trim off trailing ';q=0.8'.
|
|
16
|
+
// Right now it doesn't really matter because most browsers specify */*
|
|
17
|
+
// as the trailing content type, and we don't match on that anyway.
|
|
18
|
+
|
|
19
|
+
const content_type = parts.find((part) => {
|
|
20
|
+
return supported_content_types.includes(part);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
if (content_type === undefined) {
|
|
24
|
+
return ContentType.TEXT;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return content_type as ContentType;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
private getAcceptHeader(): string {
|
|
31
|
+
return this.accept_header;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export default AcceptHeaderParser;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {StringEncoding} from 'lib/string';
|
|
2
|
+
|
|
3
|
+
import BasicAuthCredentials from 'lib/http/type/basic-auth-credentials';
|
|
4
|
+
|
|
5
|
+
class BasicAuthHeaderParser {
|
|
6
|
+
private header_value: string;
|
|
7
|
+
|
|
8
|
+
public constructor(header_value: string) {
|
|
9
|
+
this.header_value = header_value;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
public parse(): BasicAuthCredentials {
|
|
13
|
+
const header_value = this.getHeaderValue();
|
|
14
|
+
const parts = header_value.split(' ');
|
|
15
|
+
const prefix = parts[0];
|
|
16
|
+
|
|
17
|
+
if (prefix !== 'Basic') {
|
|
18
|
+
throw new Error('Invalid header format');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const suffix = parts[1];
|
|
22
|
+
|
|
23
|
+
if (suffix === undefined) {
|
|
24
|
+
throw new Error('Invalid header format');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const buffer = Buffer.from(suffix, StringEncoding.BASE64);
|
|
28
|
+
const decoded_suffix = buffer.toString(StringEncoding.UTF8);
|
|
29
|
+
const suffix_parts = decoded_suffix.split(':');
|
|
30
|
+
const username = suffix_parts[0];
|
|
31
|
+
const password = suffix_parts[1];
|
|
32
|
+
|
|
33
|
+
if (username === undefined || password === undefined) {
|
|
34
|
+
throw new Error('Invalid header format');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
username,
|
|
39
|
+
password
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
private getHeaderValue(): string {
|
|
44
|
+
return this.header_value;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export default BasicAuthHeaderParser;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {StringEncoding} from 'lib/string';
|
|
2
|
+
|
|
3
|
+
import BodyParser from 'lib/http/parser/body';
|
|
4
|
+
import TransactionData from 'lib/http/type/transaction-data';
|
|
5
|
+
|
|
6
|
+
class JsonBodyParser extends BodyParser {
|
|
7
|
+
protected transformBuffer(buffer: Buffer): TransactionData {
|
|
8
|
+
const string_body = buffer.toString(StringEncoding.UTF8);
|
|
9
|
+
|
|
10
|
+
return JSON.parse(string_body);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default JsonBodyParser;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import HTTP from 'http';
|
|
2
|
+
import Stream from 'stream';
|
|
3
|
+
|
|
4
|
+
import Formidable from 'formidable';
|
|
5
|
+
|
|
6
|
+
import PromiseWrapper from 'lib/promise-wrapper';
|
|
7
|
+
import {InvalidError} from 'lib/errors';
|
|
8
|
+
import {getFirstValue} from 'lib/array';
|
|
9
|
+
import {getExtensionForFilepath} from 'lib/filesystem';
|
|
10
|
+
|
|
11
|
+
import BodyParser from 'lib/http/parser/body';
|
|
12
|
+
import TransactionData from 'lib/http/type/transaction-data';
|
|
13
|
+
|
|
14
|
+
class MultipartBodyParser extends BodyParser {
|
|
15
|
+
private native_request: HTTP.IncomingMessage;
|
|
16
|
+
|
|
17
|
+
public constructor(
|
|
18
|
+
stream: Stream.Readable,
|
|
19
|
+
native_request: HTTP.IncomingMessage
|
|
20
|
+
) {
|
|
21
|
+
super(stream);
|
|
22
|
+
|
|
23
|
+
this.native_request = native_request;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public async parse(): Promise<TransactionData> {
|
|
27
|
+
const native_request = this.getNativeRequest();
|
|
28
|
+
|
|
29
|
+
const form = Formidable({
|
|
30
|
+
allowEmptyFiles: true,
|
|
31
|
+
minFileSize: 0
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const promise_wrapper = new PromiseWrapper<TransactionData>();
|
|
35
|
+
|
|
36
|
+
form.on('fileBegin', (_form_name, file) => {
|
|
37
|
+
// The uploadImage() utility, which is used downstream of here to
|
|
38
|
+
// upload the specified file to the assets server, requires that the
|
|
39
|
+
// source filepath have a valid file extension. However, Formidable's
|
|
40
|
+
// default behavior uploads the file to /tmp without one. So we need
|
|
41
|
+
// to tack it on ourselves (thankfully we have the means to do so here).
|
|
42
|
+
|
|
43
|
+
if (file.originalFilename === null) {
|
|
44
|
+
throw new InvalidError(`
|
|
45
|
+
Tried to read file upload name, but it was not set
|
|
46
|
+
`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const extension = getExtensionForFilepath(file.originalFilename);
|
|
50
|
+
const new_filepath = `${file.filepath}.${extension}`;
|
|
51
|
+
|
|
52
|
+
file.filepath = new_filepath;
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
form.parse(native_request, (error, fields, files) => {
|
|
56
|
+
if (error) {
|
|
57
|
+
promise_wrapper.reject(error);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const flat_fields: Record<string, string | string[] | undefined> = {};
|
|
62
|
+
|
|
63
|
+
Object.entries(fields).forEach(([key, values]) => {
|
|
64
|
+
if (values !== undefined && values.length === 1) {
|
|
65
|
+
flat_fields[key] = getFirstValue(values);
|
|
66
|
+
} else {
|
|
67
|
+
flat_fields[key] = values;
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
promise_wrapper.resolve({
|
|
72
|
+
...flat_fields,
|
|
73
|
+
...files
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
return promise_wrapper.getPromise();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
protected transformBuffer(_buffer: Buffer): TransactionData {
|
|
81
|
+
throw new Error('Not implemented');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private getNativeRequest(): HTTP.IncomingMessage {
|
|
85
|
+
return this.native_request;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export default MultipartBodyParser;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {StringEncoding} from 'lib/string';
|
|
2
|
+
|
|
3
|
+
import BodyParser from 'lib/http/parser/body';
|
|
4
|
+
import TransactionData from 'lib/http/type/transaction-data';
|
|
5
|
+
import QuerystringParser from 'lib/http/parser/querystring';
|
|
6
|
+
|
|
7
|
+
class UrlEncodedBodyParser extends BodyParser {
|
|
8
|
+
protected transformBuffer(buffer: Buffer): TransactionData {
|
|
9
|
+
const querystring = buffer.toString(StringEncoding.UTF8);
|
|
10
|
+
const parser = new QuerystringParser(querystring);
|
|
11
|
+
|
|
12
|
+
return parser.parse();
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default UrlEncodedBodyParser;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import Stream from 'stream';
|
|
2
|
+
|
|
3
|
+
import TransactionData from 'lib/http/type/transaction-data';
|
|
4
|
+
|
|
5
|
+
abstract class BodyParser {
|
|
6
|
+
private stream: Stream.Readable;
|
|
7
|
+
|
|
8
|
+
public constructor(stream: Stream.Readable) {
|
|
9
|
+
this.stream = stream;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
public async parse(): Promise<TransactionData> {
|
|
13
|
+
const buffer = await this.readBuffer();
|
|
14
|
+
|
|
15
|
+
return this.transformBuffer(buffer);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
private readBuffer(): Promise<Buffer> {
|
|
19
|
+
const stream = this.getStream();
|
|
20
|
+
const chunks: Buffer[] = [];
|
|
21
|
+
|
|
22
|
+
stream.on('data', (data) => {
|
|
23
|
+
chunks.push(data);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
return new Promise((resolve, reject) => {
|
|
27
|
+
stream.on('end', () => {
|
|
28
|
+
const body = Buffer.concat(chunks);
|
|
29
|
+
|
|
30
|
+
resolve(body);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
stream.on('error', reject);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
private getStream(): Stream.Readable {
|
|
38
|
+
return this.stream;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
protected abstract transformBuffer(buffer: Buffer): TransactionData;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export default BodyParser;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This class reads the cookie value supplied by the browser and parses
|
|
3
|
+
* it into its constituent pieces. The only thing we really read from it is
|
|
4
|
+
* the current user's session id.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import Logger from 'lib/logger';
|
|
8
|
+
|
|
9
|
+
import CookieAttribute from 'lib/http/enum/cookie-attribute';
|
|
10
|
+
|
|
11
|
+
interface CookieValueMap {
|
|
12
|
+
[key: string]: string | boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
class CookieParser {
|
|
16
|
+
private header_value: string;
|
|
17
|
+
private parsed = false;
|
|
18
|
+
private cookie_values: CookieValueMap | undefined;
|
|
19
|
+
|
|
20
|
+
public constructor(header_value: string) {
|
|
21
|
+
this.header_value = header_value;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public getSessionId(): string | undefined {
|
|
25
|
+
const value = this.getValueForCookieAttribute(CookieAttribute.SESSION);
|
|
26
|
+
|
|
27
|
+
return value as string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public getValueForCookieAttribute(
|
|
31
|
+
cookie_attribute: CookieAttribute
|
|
32
|
+
): string | boolean | undefined {
|
|
33
|
+
this.parseIfNecessary();
|
|
34
|
+
|
|
35
|
+
return this.getCookieValues()[cookie_attribute];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
private parseIfNecessary(): void {
|
|
39
|
+
if (this.parsed === false) {
|
|
40
|
+
this.parse();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
private parse(): void {
|
|
45
|
+
this.parsed = true;
|
|
46
|
+
|
|
47
|
+
const header_value = this.getHeaderValue();
|
|
48
|
+
|
|
49
|
+
if (!header_value) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const parts = header_value.split(';');
|
|
54
|
+
|
|
55
|
+
parts.forEach((part) => {
|
|
56
|
+
this.parseCookiePart(part);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
private parseCookiePart(cookie_part: string): void {
|
|
61
|
+
const delimiter_index = cookie_part.indexOf('=');
|
|
62
|
+
|
|
63
|
+
let cookie_attribute;
|
|
64
|
+
let cookie_value;
|
|
65
|
+
|
|
66
|
+
if (delimiter_index === -1) {
|
|
67
|
+
cookie_attribute = cookie_part;
|
|
68
|
+
cookie_value = true;
|
|
69
|
+
} else {
|
|
70
|
+
cookie_attribute = cookie_part.slice(0, delimiter_index);
|
|
71
|
+
cookie_value = cookie_part.slice(delimiter_index + 1).trim();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
cookie_attribute = cookie_attribute.trim();
|
|
75
|
+
|
|
76
|
+
if (!this.isSupportedCookieAttribute(cookie_attribute)) {
|
|
77
|
+
return void new Logger().warn(`
|
|
78
|
+
Received unsupported cookie in cookie header: ${cookie_attribute}
|
|
79
|
+
`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return void this.setValueForCookieAttribute(
|
|
83
|
+
cookie_attribute as CookieAttribute,
|
|
84
|
+
cookie_value
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private isSupportedCookieAttribute(potential_attribute: string): boolean {
|
|
89
|
+
const attributes = Object.values(CookieAttribute) as string[];
|
|
90
|
+
|
|
91
|
+
return attributes.includes(potential_attribute);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
private setValueForCookieAttribute(
|
|
95
|
+
cookie_attribute: CookieAttribute,
|
|
96
|
+
value: string | boolean
|
|
97
|
+
): void {
|
|
98
|
+
this.getCookieValues()[cookie_attribute] = value;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private getCookieValues(): CookieValueMap {
|
|
102
|
+
if (!this.cookie_values) {
|
|
103
|
+
this.cookie_values = {};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return this.cookie_values;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private getHeaderValue(): string {
|
|
110
|
+
return this.header_value;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export default CookieParser;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import Querystring from 'querystring';
|
|
2
|
+
|
|
3
|
+
import TransactionData from 'lib/http/type/transaction-data';
|
|
4
|
+
|
|
5
|
+
function isNumericKey(key: string): boolean {
|
|
6
|
+
const parsed_key = parseInt(key, 10);
|
|
7
|
+
|
|
8
|
+
return isNaN(parsed_key) === false;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function mergeValue(
|
|
12
|
+
result: Record<string, unknown>,
|
|
13
|
+
key: string,
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
15
|
+
value: any
|
|
16
|
+
): void {
|
|
17
|
+
const brace_index = key.indexOf('[');
|
|
18
|
+
|
|
19
|
+
if (brace_index === -1) {
|
|
20
|
+
result[key] = value;
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const prefix = key.slice(0, brace_index);
|
|
25
|
+
const suffix = key.slice(brace_index);
|
|
26
|
+
|
|
27
|
+
let index = 0;
|
|
28
|
+
let previous_key = prefix;
|
|
29
|
+
let current_key = '';
|
|
30
|
+
let target = result;
|
|
31
|
+
|
|
32
|
+
while (index < suffix.length) {
|
|
33
|
+
const character = suffix[index];
|
|
34
|
+
|
|
35
|
+
index++;
|
|
36
|
+
|
|
37
|
+
if (character === '[') {
|
|
38
|
+
current_key = '';
|
|
39
|
+
} else if (character === ']') {
|
|
40
|
+
if (previous_key === '') {
|
|
41
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
42
|
+
const array = (target as unknown) as any[];
|
|
43
|
+
const index_key = Math.max(0, array.length - 1);
|
|
44
|
+
|
|
45
|
+
previous_key = index_key.toString();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (target[previous_key] === undefined) {
|
|
49
|
+
if (current_key === '' || isNumericKey(current_key)) {
|
|
50
|
+
target[previous_key] = [];
|
|
51
|
+
} else {
|
|
52
|
+
target[previous_key] = {};
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
target = target[previous_key] as Record<string, unknown>;
|
|
57
|
+
previous_key = current_key;
|
|
58
|
+
} else {
|
|
59
|
+
current_key += character;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
target[current_key] = value;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
class QuerystringParser {
|
|
67
|
+
private querystring: string;
|
|
68
|
+
|
|
69
|
+
public constructor(querystring: string) {
|
|
70
|
+
this.querystring = querystring;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
public parse(): TransactionData {
|
|
74
|
+
const querystring = this.getQuerystring();
|
|
75
|
+
const result = {};
|
|
76
|
+
const raw_data = Querystring.parse(querystring);
|
|
77
|
+
|
|
78
|
+
Object.keys(raw_data).forEach((key) => {
|
|
79
|
+
const value = raw_data[key];
|
|
80
|
+
|
|
81
|
+
mergeValue(result, key, value);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
private getQuerystring(): string {
|
|
88
|
+
return this.querystring;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export default QuerystringParser;
|