@joystick.js/node-canary 0.0.0-canary.47 → 0.0.0-canary.470
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/.build/getFilesToBuild.js +26 -0
- package/.build/getPlatformSafeFilePath.js +6 -0
- package/.build/getPlatformSafePath.js +6 -0
- package/.build/index.js +88 -0
- package/.build/isWindows.js +3 -0
- package/dist/action/class.js +1 -82
- package/dist/action/index.js +1 -8
- package/dist/app/accounts/default_user_output_fields.js +1 -0
- package/dist/app/accounts/delete_user.js +1 -0
- package/dist/app/accounts/generate_account_session.js +1 -0
- package/dist/app/accounts/generate_password_reset_token.js +1 -0
- package/dist/app/accounts/get_browser_safe_user.js +1 -0
- package/dist/app/accounts/has_login_token_expired.js +1 -0
- package/dist/app/accounts/index.js +1 -29
- package/dist/app/accounts/login.js +1 -59
- package/dist/app/accounts/recover_password.js +1 -0
- package/dist/app/accounts/reset_password.js +1 -0
- package/dist/app/accounts/roles/add.js +1 -7
- package/dist/app/accounts/roles/grant.js +1 -7
- package/dist/app/accounts/roles/index.js +1 -17
- package/dist/app/accounts/roles/list.js +1 -7
- package/dist/app/accounts/roles/remove.js +1 -7
- package/dist/app/accounts/roles/revoke.js +1 -7
- package/dist/app/accounts/roles/user_has_role.js +1 -0
- package/dist/app/accounts/send_email_verification.js +1 -0
- package/dist/app/accounts/set_account_cookie.js +1 -0
- package/dist/app/accounts/set_password.js +1 -0
- package/dist/app/accounts/signup.js +1 -97
- package/dist/app/accounts/unset_account_cookie.js +1 -0
- package/dist/app/accounts/verify_email.js +1 -0
- package/dist/app/api/accounts/authenticated.js +1 -0
- package/dist/app/api/accounts/login.js +1 -0
- package/dist/app/api/accounts/logout.js +1 -0
- package/dist/app/api/accounts/recover_password.js +1 -0
- package/dist/app/api/accounts/reset_password.js +1 -0
- package/dist/app/api/accounts/signup.js +1 -0
- package/dist/app/api/accounts/user.js +1 -0
- package/dist/app/api/accounts/verify_email.js +1 -0
- package/dist/app/api/format_api_error.js +1 -0
- package/dist/app/api/get.js +2 -0
- package/dist/app/api/get_api_context.js +1 -0
- package/dist/app/api/get_api_for_data_functions.js +1 -0
- package/dist/app/api/get_api_url_component.js +1 -0
- package/dist/app/api/get_output.js +1 -0
- package/dist/app/api/get_value_from_object.js +1 -0
- package/dist/app/api/handle_api_error.js +1 -0
- package/dist/app/api/input_validators.js +1 -0
- package/dist/app/api/is_array_path.js +1 -0
- package/dist/app/api/push/health.js +2 -0
- package/dist/app/api/register_getters.js +1 -0
- package/dist/app/api/register_setters.js +1 -0
- package/dist/app/api/sanitize_api_response.js +1 -0
- package/dist/app/api/set.js +2 -0
- package/dist/app/api/test/accounts/delete.js +1 -0
- package/dist/app/api/test/accounts/signup.js +1 -0
- package/dist/app/api/test/bootstrap.js +1 -0
- package/dist/app/api/test/process.js +1 -0
- package/dist/app/api/test/queues.js +1 -0
- package/dist/app/api/validate_input.js +1 -0
- package/dist/app/api/validate_session.js +1 -0
- package/dist/app/api/validate_type.js +1 -0
- package/dist/app/browser/hmr_client.js +1 -0
- package/dist/app/browser/process_polyfill.js +1 -0
- package/dist/app/cron_jobs/register.js +1 -0
- package/dist/app/databases/database_type_map.js +1 -0
- package/dist/app/databases/get_target_database_connection.js +1 -0
- package/dist/app/databases/mongodb/available_query_parameters.js +1 -0
- package/dist/app/databases/mongodb/build_connection_string.js +1 -0
- package/dist/app/databases/mongodb/build_query_parameters.js +1 -0
- package/dist/app/databases/mongodb/connect.js +6 -0
- package/dist/app/databases/mongodb/create_indexes.js +1 -0
- package/dist/app/databases/postgresql/accounts/create_accounts_metadata_table_columns.js +1 -0
- package/dist/app/databases/postgresql/connect.js +30 -0
- package/dist/app/databases/postgresql/create_indexes.js +1 -0
- package/dist/app/databases/postgresql/create_tables.js +1 -0
- package/dist/app/databases/postgresql/handle_cleanup_queues.js +5 -0
- package/dist/app/databases/postgresql/handle_cleanup_sessions.js +1 -0
- package/dist/app/databases/queries/accounts.js +1 -0
- package/dist/app/databases/queries/map.js +1 -0
- package/dist/app/databases/queries/mongodb/accounts.js +1 -0
- package/dist/app/databases/queries/mongodb/queues.js +1 -0
- package/dist/app/databases/queries/mongodb/sessions.js +1 -0
- package/dist/app/databases/queries/postgresql/accounts.js +1 -0
- package/dist/app/databases/queries/postgresql/queues.js +123 -0
- package/dist/app/databases/queries/postgresql/sessions.js +14 -0
- package/dist/app/databases/queries/sessions.js +1 -0
- package/dist/app/databases/register_database.js +1 -0
- package/dist/app/databases/sql.js +1 -0
- package/dist/app/email/send.js +1 -0
- package/dist/app/email/validate_smtp_settings.js +1 -0
- package/dist/app/fixture/index.js +1 -0
- package/dist/app/generate_machine_id.js +1 -0
- package/dist/app/generate_process_id.js +1 -0
- package/dist/app/get_ssl_certificates.js +1 -0
- package/dist/app/handle_process_errors.js +1 -0
- package/dist/app/index.js +1 -656
- package/dist/app/middleware/account.js +1 -0
- package/dist/app/middleware/body_parser.js +1 -0
- package/dist/app/middleware/build_error.js +1 -0
- package/dist/app/middleware/built_in.js +1 -0
- package/dist/app/middleware/context.js +1 -0
- package/dist/app/middleware/cors.js +1 -22
- package/dist/app/middleware/csp.js +1 -48
- package/dist/app/middleware/generate_insecure_page.js +65 -0
- package/dist/app/middleware/generate_joystick_error_page.js +147 -0
- package/dist/app/middleware/hmr_client.js +1 -0
- package/dist/app/middleware/insecure.js +1 -11
- package/dist/app/middleware/process_browser_polyfill.js +1 -0
- package/dist/app/middleware/render/get_url.js +1 -0
- package/dist/app/middleware/render/index.js +1 -0
- package/dist/app/middleware/request_methods.js +1 -0
- package/dist/app/middleware/session.js +1 -24
- package/dist/app/push_logs.js +1 -0
- package/dist/app/queues/index.js +1 -119
- package/dist/app/register_app_options.js +1 -0
- package/dist/app/routes/register_route_from_function.js +1 -0
- package/dist/app/routes/register_route_from_object.js +1 -0
- package/dist/app/routes/supported_http_methods.js +1 -0
- package/dist/app/settings/load.js +1 -0
- package/dist/app/ssr/index.js +33 -0
- package/dist/app/ssr/set_base_attributes_in_html.js +1 -0
- package/dist/app/ssr/set_head_tags_in_html.js +1 -0
- package/dist/app/start_express.js +1 -0
- package/dist/app/start_node_as_cluster.js +1 -0
- package/dist/app/uploaders/local_upload_progress_middleware.js +1 -0
- package/dist/app/uploaders/register.js +1 -0
- package/dist/app/uploaders/run_upload.js +1 -0
- package/dist/app/uploaders/validate_options.js +1 -0
- package/dist/app/uploaders/validate_uploads.js +1 -0
- package/dist/app/websockets/emit_event.js +1 -0
- package/dist/app/websockets/index.js +1 -0
- package/dist/app/websockets/register.js +1 -0
- package/dist/index.js +4 -76
- package/dist/lib/camel_pascal_to_snake.js +1 -0
- package/dist/lib/constants.js +1 -13
- package/dist/lib/dynamic_import.js +1 -0
- package/dist/lib/escape_html.js +1 -0
- package/dist/lib/escape_key_value_pair.js +1 -0
- package/dist/lib/float_to_decimal_place.js +1 -0
- package/dist/lib/generate_id.js +1 -0
- package/dist/lib/get_browser_safe_request.js +1 -0
- package/dist/lib/get_joystick_build_path.js +1 -0
- package/dist/lib/get_origin.js +1 -0
- package/dist/lib/get_platform_safe_path.js +1 -0
- package/dist/lib/get_sanitized_context.js +1 -0
- package/dist/lib/get_translations.js +1 -0
- package/dist/lib/hash_string.js +1 -0
- package/dist/lib/is_valid_json.js +1 -0
- package/dist/lib/log.js +13 -49
- package/dist/lib/node_path_polyfills.js +1 -0
- package/dist/lib/parse_json.js +1 -0
- package/dist/lib/path_exists.js +1 -0
- package/dist/lib/rainbow_road.js +1 -0
- package/dist/lib/serialize_query_parameters.js +1 -0
- package/dist/lib/set_cookie.js +1 -0
- package/dist/lib/string_to_slug.js +1 -0
- package/dist/lib/timestamps.js +1 -0
- package/dist/lib/types.js +1 -0
- package/dist/lib/unset_cookie.js +1 -0
- package/dist/lib/wait.js +1 -0
- package/dist/test/track_function_call.js +1 -0
- package/increment_version.js +3 -0
- package/package.json +27 -44
- package/src/action/class.js +137 -0
- package/src/action/index.js +8 -0
- package/src/app/accounts/default_user_output_fields.js +10 -0
- package/src/app/accounts/delete_user.js +18 -0
- package/src/app/accounts/generate_account_session.js +11 -0
- package/src/app/accounts/generate_password_reset_token.js +16 -0
- package/src/app/accounts/get_browser_safe_user.js +29 -0
- package/src/app/accounts/has_login_token_expired.js +9 -0
- package/src/app/accounts/index.js +38 -0
- package/src/app/accounts/login.js +82 -0
- package/src/app/accounts/recover_password.js +58 -0
- package/src/app/accounts/reset_password.js +69 -0
- package/src/app/accounts/roles/add.js +7 -0
- package/src/app/accounts/roles/grant.js +7 -0
- package/src/app/accounts/roles/index.js +18 -0
- package/src/app/accounts/roles/list.js +7 -0
- package/src/app/accounts/roles/remove.js +7 -0
- package/src/app/accounts/roles/revoke.js +7 -0
- package/src/app/accounts/roles/user_has_role.js +7 -0
- package/src/app/accounts/send_email_verification.js +48 -0
- package/src/app/accounts/set_account_cookie.js +12 -0
- package/src/app/accounts/set_password.js +46 -0
- package/src/app/accounts/signup.js +158 -0
- package/src/app/accounts/unset_account_cookie.js +12 -0
- package/src/app/accounts/verify_email.js +32 -0
- package/src/app/api/accounts/authenticated.js +17 -0
- package/src/app/api/accounts/login.js +36 -0
- package/src/app/api/accounts/logout.js +20 -0
- package/src/app/api/accounts/recover_password.js +16 -0
- package/src/app/api/accounts/reset_password.js +24 -0
- package/src/app/api/accounts/signup.js +49 -0
- package/src/app/api/accounts/user.js +21 -0
- package/src/app/api/accounts/verify_email.js +11 -0
- package/src/app/api/format_api_error.js +10 -0
- package/src/app/api/get.js +119 -0
- package/src/app/api/get_api_context.js +27 -0
- package/src/app/api/get_api_for_data_functions.js +37 -0
- package/src/app/api/get_api_url_component.js +5 -0
- package/src/app/api/get_output.js +116 -0
- package/src/app/api/get_value_from_object.js +8 -0
- package/src/app/api/handle_api_error.js +28 -0
- package/src/app/api/input_validators.js +227 -0
- package/src/app/api/is_array_path.js +6 -0
- package/src/app/api/push/health.js +17 -0
- package/src/app/api/register_getters.js +57 -0
- package/src/app/api/register_setters.js +55 -0
- package/src/app/api/sanitize_api_response.js +35 -0
- package/src/app/api/set.js +119 -0
- package/src/app/api/test/accounts/delete.js +8 -0
- package/src/app/api/test/accounts/signup.js +50 -0
- package/src/app/api/test/bootstrap.js +39 -0
- package/src/app/api/test/process.js +7 -0
- package/src/app/api/test/queues.js +25 -0
- package/src/app/api/validate_input.js +130 -0
- package/src/app/api/validate_session.js +20 -0
- package/src/app/api/validate_type.js +24 -0
- package/src/app/browser/hmr_client.js +196 -0
- package/src/app/browser/process_polyfill.js +11 -0
- package/src/app/cron_jobs/register.js +29 -0
- package/src/app/databases/database_type_map.js +6 -0
- package/src/app/databases/get_target_database_connection.js +25 -0
- package/{dist/app/databases/mongodb/availableQueryParameters.js → src/app/databases/mongodb/available_query_parameters.js} +3 -4
- package/src/app/databases/mongodb/build_connection_string.js +30 -0
- package/src/app/databases/mongodb/build_query_parameters.js +17 -0
- package/src/app/databases/mongodb/connect.js +42 -0
- package/src/app/databases/mongodb/create_indexes.js +35 -0
- package/src/app/databases/postgresql/accounts/create_accounts_metadata_table_columns.js +18 -0
- package/src/app/databases/postgresql/connect.js +128 -0
- package/src/app/databases/postgresql/create_indexes.js +58 -0
- package/src/app/databases/postgresql/create_tables.js +70 -0
- package/src/app/databases/postgresql/handle_cleanup_queues.js +36 -0
- package/src/app/databases/postgresql/handle_cleanup_sessions.js +5 -0
- package/src/app/databases/queries/accounts.js +17 -0
- package/src/app/databases/queries/map.js +21 -0
- package/src/app/databases/queries/mongodb/accounts.js +360 -0
- package/src/app/databases/queries/mongodb/queues.js +164 -0
- package/src/app/databases/queries/mongodb/sessions.js +22 -0
- package/src/app/databases/queries/postgresql/accounts.js +379 -0
- package/src/app/databases/queries/postgresql/queues.js +294 -0
- package/src/app/databases/queries/postgresql/sessions.js +37 -0
- package/src/app/databases/queries/sessions.js +17 -0
- package/src/app/databases/register_database.js +30 -0
- package/src/app/databases/sql.js +63 -0
- package/src/app/email/send.js +108 -0
- package/src/app/email/validate_smtp_settings.js +53 -0
- package/src/app/fixture/index.js +50 -0
- package/src/app/generate_machine_id.js +26 -0
- package/src/app/generate_process_id.js +30 -0
- package/src/app/get_ssl_certificates.js +23 -0
- package/src/app/handle_process_errors.js +101 -0
- package/src/app/index.js +253 -0
- package/src/app/middleware/account.js +28 -0
- package/src/app/middleware/body_parser.js +18 -0
- package/src/app/middleware/build_error.js +18 -0
- package/src/app/middleware/built_in.js +76 -0
- package/src/app/middleware/context.js +34 -0
- package/src/app/middleware/cors.js +23 -0
- package/src/app/middleware/csp.js +54 -0
- package/src/app/middleware/generate_insecure_page.js +71 -0
- package/{dist/lib/generateErrorPage.js → src/app/middleware/generate_joystick_error_page.js} +25 -21
- package/src/app/middleware/hmr_client.js +12 -0
- package/src/app/middleware/insecure.js +22 -0
- package/src/app/middleware/process_browser_polyfill.js +12 -0
- package/src/app/middleware/render/get_url.js +15 -0
- package/src/app/middleware/render/index.js +93 -0
- package/src/app/middleware/request_methods.js +21 -0
- package/src/app/middleware/session.js +31 -0
- package/src/app/push_logs.js +44 -0
- package/src/app/queues/index.js +268 -0
- package/src/app/register_app_options.js +7 -0
- package/src/app/routes/register_route_from_function.js +10 -0
- package/src/app/routes/register_route_from_object.js +34 -0
- package/src/app/routes/supported_http_methods.js +9 -0
- package/src/app/settings/load.js +33 -0
- package/src/app/ssr/index.js +133 -0
- package/src/app/ssr/set_base_attributes_in_html.js +43 -0
- package/src/app/ssr/set_head_tags_in_html.js +104 -0
- package/src/app/start_express.js +50 -0
- package/src/app/start_node_as_cluster.js +30 -0
- package/src/app/uploaders/local_upload_progress_middleware.js +24 -0
- package/src/app/uploaders/register.js +169 -0
- package/src/app/uploaders/run_upload.js +136 -0
- package/src/app/uploaders/validate_options.js +74 -0
- package/src/app/uploaders/validate_uploads.js +127 -0
- package/src/app/websockets/emit_event.js +14 -0
- package/src/app/websockets/index.js +16 -0
- package/src/app/websockets/register.js +175 -0
- package/src/index.js +81 -0
- package/{dist/lib/camelPascalToSnake.js → src/lib/camel_pascal_to_snake.js} +3 -4
- package/src/lib/constants.js +21 -0
- package/src/lib/dynamic_import.js +8 -0
- package/src/lib/escape_html.js +9 -0
- package/src/lib/escape_key_value_pair.js +15 -0
- package/src/lib/float_to_decimal_place.js +5 -0
- package/src/lib/generate_id.js +15 -0
- package/src/lib/get_browser_safe_request.js +17 -0
- package/src/lib/get_joystick_build_path.js +22 -0
- package/src/lib/get_origin.js +7 -0
- package/src/lib/get_platform_safe_path.js +8 -0
- package/src/lib/get_sanitized_context.js +51 -0
- package/src/lib/get_translations.js +109 -0
- package/src/lib/hash_string.js +7 -0
- package/src/lib/is_valid_json.js +10 -0
- package/src/lib/log.js +42 -0
- package/src/lib/node_path_polyfills.js +23 -0
- package/src/lib/parse_json.js +9 -0
- package/src/lib/path_exists.js +12 -0
- package/src/lib/rainbow_road.js +7 -0
- package/src/lib/serialize_query_parameters.js +7 -0
- package/src/lib/set_cookie.js +16 -0
- package/src/lib/string_to_slug.js +14 -0
- package/src/lib/timestamps.js +48 -0
- package/src/lib/types.js +59 -0
- package/src/lib/unset_cookie.js +11 -0
- package/src/lib/wait.js +9 -0
- package/src/test/track_function_call.js +16 -0
- package/README.md +0 -8
- package/_package.json +0 -63
- package/canary.js +0 -12
- package/dist/api/get.js +0 -29
- package/dist/api/getOrigin.js +0 -6
- package/dist/api/index.js +0 -9
- package/dist/api/set.js +0 -29
- package/dist/app/accounts/defaultUserOutputFields.js +0 -9
- package/dist/app/accounts/generateResetToken.js +0 -28
- package/dist/app/accounts/generateSession.js +0 -15
- package/dist/app/accounts/getBrowserSafeUser.js +0 -24
- package/dist/app/accounts/hasLoginTokenExpired.js +0 -17
- package/dist/app/accounts/hashString.js +0 -7
- package/dist/app/accounts/recoverPassword.js +0 -30
- package/dist/app/accounts/resetPassword.js +0 -73
- package/dist/app/accounts/roles/userHasRole.js +0 -7
- package/dist/app/accounts/runUserQuery.js +0 -15
- package/dist/app/accounts/sendEmailVerification.js +0 -65
- package/dist/app/accounts/setAuthenticationCookie.js +0 -11
- package/dist/app/accounts/setPassword.js +0 -45
- package/dist/app/accounts/unsetAuthenticationCookie.js +0 -11
- package/dist/app/accounts/verifyEmail.js +0 -46
- package/dist/app/databases/getTargetDatabase.js +0 -10
- package/dist/app/databases/getTargetDatabaseConnection.js +0 -19
- package/dist/app/databases/getTargetDatabaseProvider.js +0 -10
- package/dist/app/databases/mongodb/buildConnectionString.js +0 -22
- package/dist/app/databases/mongodb/buildQueryParameters.js +0 -14
- package/dist/app/databases/mongodb/index.js +0 -40
- package/dist/app/databases/mongodb/queries/accounts.js +0 -266
- package/dist/app/databases/mongodb/queries/queues.js +0 -111
- package/dist/app/databases/postgresql/addColumnToTable.js +0 -6
- package/dist/app/databases/postgresql/createAccountsIndexes.js +0 -21
- package/dist/app/databases/postgresql/createAccountsTables.js +0 -39
- package/dist/app/databases/postgresql/createDatabase.js +0 -0
- package/dist/app/databases/postgresql/index.js +0 -55
- package/dist/app/databases/postgresql/queries/accounts.js +0 -186
- package/dist/app/databases/postgresql/queries/queues.js +0 -211
- package/dist/app/databases/queryMap.js +0 -17
- package/dist/app/databases/typesMap.js +0 -7
- package/dist/app/getAPIContext.js +0 -25
- package/dist/app/getAPIURLComponent.js +0 -6
- package/dist/app/getBrowserSafeRequest.js +0 -14
- package/dist/app/getOutput.js +0 -74
- package/dist/app/handleProcessErrors.js +0 -73
- package/dist/app/initExpress.js +0 -41
- package/dist/app/middleware/bodyParser.js +0 -16
- package/dist/app/middleware/hmr/client.js +0 -113
- package/dist/app/middleware/index.js +0 -89
- package/dist/app/middleware/render.js +0 -213
- package/dist/app/middleware/requestMethods.js +0 -19
- package/dist/app/registerGetters.js +0 -45
- package/dist/app/registerSetters.js +0 -45
- package/dist/app/runGetter.js +0 -103
- package/dist/app/runSetter.js +0 -103
- package/dist/app/runUploader.js +0 -143
- package/dist/app/sanitizeAPIResponse.js +0 -27
- package/dist/app/utils/process.js +0 -193
- package/dist/app/validateSession.js +0 -19
- package/dist/app/validateUploaderOptions.js +0 -53
- package/dist/app/validateUploads.js +0 -102
- package/dist/email/render.js +0 -50
- package/dist/email/send.js +0 -55
- package/dist/email/templates/base.css +0 -194
- package/dist/email/templates/base.html +0 -28
- package/dist/email/templates/reset-password.js +0 -13
- package/dist/email/validateSMTPSettings.js +0 -27
- package/dist/lib/escapeHTML.js +0 -9
- package/dist/lib/escapeKeyValuePair.js +0 -13
- package/dist/lib/formatAPIError.js +0 -12
- package/dist/lib/formatErrorString.js +0 -8
- package/dist/lib/generateCookie.js +0 -14
- package/dist/lib/generateId.js +0 -13
- package/dist/lib/generateMachineId.js +0 -15
- package/dist/lib/getBuildPath.js +0 -10
- package/dist/lib/getErrorObject.js +0 -9
- package/dist/lib/getPlatformSafeFilePath.js +0 -8
- package/dist/lib/getPlatformSafePath.js +0 -8
- package/dist/lib/getSSLCertificates.js +0 -19
- package/dist/lib/isValidHTTPMethod.js +0 -7
- package/dist/lib/isValidJSONString.js +0 -11
- package/dist/lib/nodeUrlPolyfills.js +0 -14
- package/dist/lib/objectToSQLKeysString.js +0 -18
- package/dist/lib/objectToSQLValuesString.js +0 -16
- package/dist/lib/obscenedb/debounce.js +0 -12
- package/dist/lib/obscenedb/index.js +0 -61
- package/dist/lib/parseDatabasesFromEnvironment.js +0 -9
- package/dist/lib/rainbowRoad.js +0 -7
- package/dist/lib/readDirectory.js +0 -24
- package/dist/lib/replaceBackslashesWithForwardSlashes.js +0 -8
- package/dist/lib/replaceFileProtocol.js +0 -8
- package/dist/lib/replaceForwardSlashesWithBackslashes.js +0 -8
- package/dist/lib/serializeQueryParameters.js +0 -8
- package/dist/lib/serverAvailable.js +0 -0
- package/dist/lib/setCookie.js +0 -16
- package/dist/lib/supportedHTTPMethods.js +0 -4
- package/dist/lib/unsetCookie.js +0 -13
- package/dist/push/logs/index.js +0 -55
- package/dist/settings/index.js +0 -5
- package/dist/settings/load.js +0 -30
- package/dist/ssr/compileCSS.js +0 -85
- package/dist/ssr/findComponentInTree.js +0 -29
- package/dist/ssr/formatCSS.js +0 -6
- package/dist/ssr/getCSSFromTree.js +0 -33
- package/dist/ssr/index.js +0 -441
- package/dist/ssr/replaceWhenTags.js +0 -37
- package/dist/ssr/setHeadTagsInHTML.js +0 -84
- package/dist/validation/index.js +0 -10
- package/dist/validation/index.test.js +0 -463
- package/dist/validation/inputWithSchema/index.js +0 -105
- package/dist/validation/lib/constants.js +0 -162
- package/dist/validation/lib/getValueFromObject.js +0 -12
- package/dist/validation/lib/getValueFromObject.test.js +0 -7
- package/dist/validation/lib/isArrayPath.js +0 -6
- package/dist/validation/lib/throwError.js +0 -6
- package/dist/validation/lib/typeValidators.js +0 -38
- package/dist/validation/lib/validateType.js +0 -33
- package/dist/validation/schema/index.js +0 -44
- package/dist/websockets/emitWebsocketEvent.js +0 -12
- package/dist/websockets/index.js +0 -12
- package/notes +0 -1
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import supported_http_methods from "./supported_http_methods.js";
|
|
2
|
+
import types from "../../lib/types.js";
|
|
3
|
+
|
|
4
|
+
const register_route_from_object = (express_app = {}, route_path = '', route_handler = {}) => {
|
|
5
|
+
const method = route_handler?.method?.toLowerCase();
|
|
6
|
+
const methods = route_handler?.methods?.map((method) => method?.toLowerCase());
|
|
7
|
+
const methods_for_route = (method ? [method] : methods)?.filter((method) => {
|
|
8
|
+
return supported_http_methods.includes(method);
|
|
9
|
+
});
|
|
10
|
+
const middleware_for_route = types.is_array(route_handler?.middleware) ? route_handler?.middleware : [];
|
|
11
|
+
|
|
12
|
+
if (methods_for_route?.length === 0) {
|
|
13
|
+
console.warn(`Cannot register route ${route_path}. All provided HTTP methods are invalid. Must be one of ${supported_http_methods?.join(', ')}.`);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (!types.is_function(route_handler?.handler)) {
|
|
18
|
+
console.warn(`Cannot register route ${route_path}. Handler must be a function.`);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
for (let i = 0; i < methods_for_route?.length; i += 1) {
|
|
23
|
+
const method_for_route = methods_for_route[i];
|
|
24
|
+
express_app[method_for_route](
|
|
25
|
+
route_path,
|
|
26
|
+
...(middleware_for_route || []),
|
|
27
|
+
async (req, res, next) => {
|
|
28
|
+
route_handler.handler(req, res, next);
|
|
29
|
+
},
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export default register_route_from_object;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import is_valid_json from "../../lib/is_valid_json.js";
|
|
2
|
+
import parse_json from "../../lib/parse_json.js";
|
|
3
|
+
|
|
4
|
+
const default_settings = {
|
|
5
|
+
config: {},
|
|
6
|
+
global: {},
|
|
7
|
+
public: {},
|
|
8
|
+
private: {},
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const load = () => {
|
|
12
|
+
const has_settings = !!process.env.JOYSTICK_SETTINGS;
|
|
13
|
+
const settings = `${process.env.JOYSTICK_SETTINGS}`.replace(/\\/g, '');
|
|
14
|
+
const settings_are_valid = has_settings && is_valid_json(settings);
|
|
15
|
+
|
|
16
|
+
if (!has_settings) {
|
|
17
|
+
return default_settings;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (!settings_are_valid) {
|
|
21
|
+
console.warn(
|
|
22
|
+
`Could not parse settings. Please verify that your settings.${process.env.NODE_ENV}.json file exports a valid JSON object.`
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
return default_settings;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const parsed_settings = parse_json(settings);
|
|
29
|
+
|
|
30
|
+
return parsed_settings || default_settings;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export default load;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import { parseHTML } from 'linkedom';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
import get_api_for_data_functions from "../api/get_api_for_data_functions.js";
|
|
5
|
+
import get_browser_safe_request from "../../lib/get_browser_safe_request.js";
|
|
6
|
+
import load_settings from '../settings/load.js';
|
|
7
|
+
import set_base_attributes_in_html from "./set_base_attributes_in_html.js";
|
|
8
|
+
import set_head_tags_in_html from "./set_head_tags_in_html.js";
|
|
9
|
+
import path_exists from "../../lib/path_exists.js";
|
|
10
|
+
import get_browser_safe_user from '../accounts/get_browser_safe_user.js';
|
|
11
|
+
|
|
12
|
+
const { readFile } = fs.promises;
|
|
13
|
+
const app_settings = load_settings();
|
|
14
|
+
const is_development = process.env.NODE_ENV === 'development';
|
|
15
|
+
|
|
16
|
+
// NOTE: Set a global document so we have access to a pseudo-DOM in @joystick.js/ui
|
|
17
|
+
// when server-side rendering.
|
|
18
|
+
const { document: linkedom_document } = parseHTML('<div></div>');
|
|
19
|
+
|
|
20
|
+
const build_html_response_for_browser = (options = {}) => {
|
|
21
|
+
return options?.base_html
|
|
22
|
+
.replace('${css}', `<style type="text/css" js-css>${options?.css}</style>`)
|
|
23
|
+
.replace(`<div id="app"></div>`, `
|
|
24
|
+
<div id="app">${options?.html}</div>
|
|
25
|
+
<script>
|
|
26
|
+
window.joystick = {
|
|
27
|
+
settings: {
|
|
28
|
+
global: ${JSON.stringify(app_settings?.global)},
|
|
29
|
+
public: ${JSON.stringify(app_settings?.public)},
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
window.__joystick_platform__ = '${os.platform()}';
|
|
34
|
+
window.__joystick_data__ = '${Buffer.from(JSON.stringify(options?.data), 'utf8').toString('base64')}';
|
|
35
|
+
window.__joystick_i18n__ = ${JSON.stringify(options?.translations)};
|
|
36
|
+
${is_development ? `window.__joystick_hmr_port__ = ${parseInt(process.env.PORT, 10) + 1}` : ''}
|
|
37
|
+
window.__joystick_layout_url__ = ${options?.render_layout_path ? `"/_joystick/${options?.render_layout_path}"` : null};
|
|
38
|
+
window.__joystick_page_url__ = ${options?.render_component_path ? `"/_joystick/${options?.render_component_path}"` : null};
|
|
39
|
+
window.__joystick_request__ = ${JSON.stringify(get_browser_safe_request(options?.req))};
|
|
40
|
+
window.__joystick_settings__ = ${JSON.stringify({
|
|
41
|
+
global: app_settings?.global,
|
|
42
|
+
public: app_settings?.public,
|
|
43
|
+
})};
|
|
44
|
+
|
|
45
|
+
window.__joystick_should_auto_mount__ = true;
|
|
46
|
+
window.__joystick_ssr_props__ = ${JSON.stringify(options?.props)};
|
|
47
|
+
window.__joystick_url__ = ${JSON.stringify(options?.url)};
|
|
48
|
+
window.__joystick_user__ = ${JSON.stringify(get_browser_safe_user(options?.req?.context?.user))};
|
|
49
|
+
</script>
|
|
50
|
+
<script type="module" src="/_joystick/utils/process.js"></script>
|
|
51
|
+
<script type="module" src="/_joystick/index.client.js"></script>
|
|
52
|
+
${options?.render_component_path ? `<script type="module" src="/_joystick/${options?.render_component_path}"></script>` : ''}
|
|
53
|
+
${options?.render_layout_path ? `<script type="module" src="/_joystick/${options?.render_layout_path}"></script>` : ''}
|
|
54
|
+
${is_development ? `<script type="module" src="/_joystick/hmr/client.js"></script>` : ''}
|
|
55
|
+
`);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const build_html_response_for_email = (options = {}) => {
|
|
59
|
+
return options?.base_html
|
|
60
|
+
.replace('${css}', `<style type="text/css">${options?.css}</style>`)
|
|
61
|
+
.replace("${subject}", options?.email_options?.subject)
|
|
62
|
+
.replace("${preheader}", options?.email_options?.preheader || "")
|
|
63
|
+
.replace('<div id="email"></div>', `<div id="email">${options?.html}</div>`);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const build_html_response = (options = {}) => {
|
|
67
|
+
return options?.is_email ? build_html_response_for_email(options) : build_html_response_for_browser(options);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const get_base_html_for_email = async (base_html_name = '') => {
|
|
71
|
+
if (await path_exists(`email/${base_html_name ? `base_${base_html_name}` : 'base'}.html`)) {
|
|
72
|
+
return readFile(`email/${base_html_name ? `base_${base_html_name}` : 'base'}.html`, 'utf-8');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
console.warn(`Could not find email/${base_html_name ? `base_${base_html_name}` : 'base'}.html`);
|
|
76
|
+
|
|
77
|
+
return '';
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const get_base_css_for_email = async (base_html_name = '') => {
|
|
81
|
+
if (await path_exists(`email/${base_html_name ? `base_${base_html_name}` : 'base'}.css`)) {
|
|
82
|
+
return readFile(`email/${base_html_name ? `base_${base_html_name}` : 'base'}.css`, 'utf-8');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
console.warn(`Could not find email/${base_html_name ? `base_${base_html_name}` : 'base'}.css`);
|
|
86
|
+
|
|
87
|
+
return '';
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const get_component_instance = (component_to_render = null, component_options = {}) => {
|
|
91
|
+
return component_to_render(component_options);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const ssr = async (ssr_options = {}) => {
|
|
95
|
+
const component_instance = get_component_instance(ssr_options?.component_to_render, ssr_options?.component_options);
|
|
96
|
+
const api = get_api_for_data_functions(ssr_options?.req, ssr_options?.api_schema);
|
|
97
|
+
const ssr_tree = [];
|
|
98
|
+
const ssr_render = await component_instance.render_for_ssr(api, ssr_options?.req, ssr_tree, {
|
|
99
|
+
linkedom_document,
|
|
100
|
+
is_email: ssr_options?.is_email
|
|
101
|
+
});
|
|
102
|
+
const email_base_css = ssr_options?.is_email ? await get_base_css_for_email(ssr_options?.email_options?.base_html_name) : null;
|
|
103
|
+
const email_base_html = ssr_options?.is_email ? await get_base_html_for_email(ssr_options?.email_options?.base_html_name) : null;
|
|
104
|
+
|
|
105
|
+
const html = build_html_response({
|
|
106
|
+
is_email: ssr_options?.is_email,
|
|
107
|
+
attributes: ssr_options?.attributes,
|
|
108
|
+
base_html: ssr_options?.is_email ? email_base_html : ssr_options?.base_html,
|
|
109
|
+
component_instance,
|
|
110
|
+
css: ssr_options?.is_email ? `
|
|
111
|
+
${email_base_css}
|
|
112
|
+
${ssr_render?.css}
|
|
113
|
+
` : ssr_render?.css,
|
|
114
|
+
data: ssr_render?.data,
|
|
115
|
+
email_options: ssr_options?.email_options,
|
|
116
|
+
head: ssr_options?.head,
|
|
117
|
+
html: ssr_render?.html,
|
|
118
|
+
props: ssr_options?.component_options?.props,
|
|
119
|
+
render_component_path: ssr_options?.render_component_path,
|
|
120
|
+
render_layout_path: ssr_options?.render_layout_path,
|
|
121
|
+
req: ssr_options?.req,
|
|
122
|
+
translations: ssr_options?.component_options?.translations,
|
|
123
|
+
url: ssr_options?.component_options?.url,
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
const html_with_head_tags = set_head_tags_in_html(html, ssr_options?.head, ssr_options?.req);
|
|
128
|
+
const html_with_base_attributes = set_base_attributes_in_html(html_with_head_tags, ssr_options?.attributes);
|
|
129
|
+
|
|
130
|
+
return html_with_base_attributes;
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
export default ssr;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { parseHTML } from 'linkedom';
|
|
2
|
+
import types from '../../lib/types.js';
|
|
3
|
+
|
|
4
|
+
const add_attributes_to_dom = (dom = {}, attributes = {}) => {
|
|
5
|
+
const attribute_keys = Object.keys(attributes || {});
|
|
6
|
+
const attribute_keys_without_class_list = attribute_keys?.filter(
|
|
7
|
+
(key) => key !== "class"
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
if (types.is_array(attributes?.class?.list)) {
|
|
11
|
+
if (attributes?.class?.method === "replace") {
|
|
12
|
+
dom.setAttribute("class", attributes.class.list.join(" "));
|
|
13
|
+
} else {
|
|
14
|
+
for (let i = 0; i < attributes.class.list.length; i += 1) {
|
|
15
|
+
const class_name = attributes.class.list[i];
|
|
16
|
+
dom.classList.add(class_name);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
for (let i = 0; i < attribute_keys_without_class_list.length; i += 1) {
|
|
22
|
+
const attribute = attribute_keys_without_class_list[i];
|
|
23
|
+
dom.setAttribute(attribute, attributes[attribute]);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return dom;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const set_base_attributes_in_html = (html = '', attributes = {}) => {
|
|
30
|
+
const { document } = parseHTML(html);
|
|
31
|
+
|
|
32
|
+
if (attributes?.html) {
|
|
33
|
+
add_attributes_to_dom(document.documentElement, attributes.html);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (attributes?.body) {
|
|
37
|
+
add_attributes_to_dom(document.body, attributes.body);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return document.toString();
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export default set_base_attributes_in_html;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import html_parser from 'node-html-parser';
|
|
2
|
+
import types from '../../lib/types.js';
|
|
3
|
+
|
|
4
|
+
const set_head_tags_in_html = (html_string = '', head = null, req = {}) => {
|
|
5
|
+
const html = html_parser.parse(html_string);
|
|
6
|
+
const head_tag = html.querySelector('head');
|
|
7
|
+
|
|
8
|
+
if (req?.context?.session) {
|
|
9
|
+
const meta_tag_wrapper = html_parser.parse(`<meta />`);
|
|
10
|
+
const tag = meta_tag_wrapper.querySelector('meta');
|
|
11
|
+
|
|
12
|
+
tag.setAttribute('name', 'csrf');
|
|
13
|
+
tag.setAttribute('content', req?.context?.session?.csrf);
|
|
14
|
+
|
|
15
|
+
head_tag.appendChild(tag);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (!head) {
|
|
19
|
+
return html.toString();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (head.title) {
|
|
23
|
+
const existing_title = head_tag.querySelector('title');
|
|
24
|
+
|
|
25
|
+
if (existing_title) {
|
|
26
|
+
const new_title = html_parser.parse(`<title>${head.title}</title>`);
|
|
27
|
+
head_tag.exchangeChild(existing_title, new_title);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (!existing_title) {
|
|
31
|
+
head_tag.insertAdjacentHTML('afterbegin', `<title>${head.title}</title>`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (head.tags && head.tags.meta && types.is_array(head.tags.meta) && head.tags.meta.length > 0) {
|
|
36
|
+
for (let i = 0; i < head?.tags?.meta?.length; i += 1) {
|
|
37
|
+
const meta_tag = head.tags.meta[i];
|
|
38
|
+
|
|
39
|
+
const existing_tag = head_tag.querySelector(`meta[name="${meta_tag.name}"]`);
|
|
40
|
+
const new_tag = html_parser.parse(`<meta />`);
|
|
41
|
+
|
|
42
|
+
const meta_tag_entries = Object.entries(meta_tag || {});
|
|
43
|
+
|
|
44
|
+
for (let i = 0; i < meta_tag_entries?.length; i += 1) {
|
|
45
|
+
const [attribute_name, attribute_value] = meta_tag_entries[i];
|
|
46
|
+
new_tag.querySelector('meta').setAttribute(attribute_name, attribute_value);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (existing_tag) {
|
|
50
|
+
head_tag.exchangeChild(existing_tag, new_tag);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!existing_tag) {
|
|
54
|
+
head_tag.appendChild(new_tag);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (head.tags && head.tags.link && types.is_array(head.tags.link) && head.tags.link.length > 0) {
|
|
60
|
+
for (let i = 0; i < head?.tags?.link?.length; i += 1) {
|
|
61
|
+
const link_tag = head?.tags?.link[i];
|
|
62
|
+
const new_tag = html_parser.parse(`<link />`);
|
|
63
|
+
|
|
64
|
+
const link_tag_entries = Object.entries(link_tag || {});
|
|
65
|
+
|
|
66
|
+
for (let i = 0; i < link_tag_entries?.length; i += 1) {
|
|
67
|
+
const [attribute_name, attribute_value] = link_tag_entries[i];
|
|
68
|
+
new_tag.querySelector('link').setAttribute(attribute_name, attribute_value);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
head_tag.appendChild(new_tag);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (head.tags && head.tags.script && Array.isArray(head.tags.script) && head.tags.script.length > 0) {
|
|
76
|
+
for (let i = 0; i < head?.tags?.script?.length; i += 1) {
|
|
77
|
+
const script_tag = head.tags.script[i];
|
|
78
|
+
const new_tag = html_parser.parse(`<script></script>`);
|
|
79
|
+
|
|
80
|
+
const script_tag_entries = Object.entries(script_tag || {});
|
|
81
|
+
|
|
82
|
+
for (let i = 0; i < script_tag_entries?.length; i += 1) {
|
|
83
|
+
const [attribute_name, attribute_value] = script_tag_entries[i];
|
|
84
|
+
new_tag.querySelector('script').setAttribute(attribute_name, attribute_value);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
head_tag.appendChild(new_tag);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (head.jsonld) {
|
|
92
|
+
const new_tag = html_parser.parse(`<script></script>`);
|
|
93
|
+
const tag = new_tag.querySelector('script');
|
|
94
|
+
|
|
95
|
+
tag.setAttribute('type', 'application/ld+json');
|
|
96
|
+
tag.set_content(JSON.stringify(head.jsonld, null, 2));
|
|
97
|
+
|
|
98
|
+
head_tag.appendChild(new_tag);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return html.toString();
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export default set_head_tags_in_html;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import express from "express";
|
|
2
|
+
import https from "https";
|
|
3
|
+
import built_in_middleware from "./middleware/built_in.js";
|
|
4
|
+
import get_joystick_build_path from "../lib/get_joystick_build_path.js";
|
|
5
|
+
import get_ssl_certificates from "./get_ssl_certificates.js";
|
|
6
|
+
import types from "../lib/types.js";
|
|
7
|
+
|
|
8
|
+
const start_express = (on_after_start_server = null, app_instance = {}) => {
|
|
9
|
+
const config = joystick?.settings?.config || {};
|
|
10
|
+
const joystick_build_path = get_joystick_build_path();
|
|
11
|
+
const ssl = get_ssl_certificates(app_instance?.options?.ssl);
|
|
12
|
+
const port = process.env.PORT ? parseInt(process.env.PORT, 10) : 2600;
|
|
13
|
+
|
|
14
|
+
// NOTE: Reassign process.env in case we fell back to default port.
|
|
15
|
+
process.env.PORT = port;
|
|
16
|
+
|
|
17
|
+
const express_app = express();
|
|
18
|
+
const server = ssl ? https.createServer(ssl, express_app).listen(port) : express_app.listen(port);
|
|
19
|
+
|
|
20
|
+
built_in_middleware({
|
|
21
|
+
app_instance,
|
|
22
|
+
csp_config: app_instance?.options?.csp,
|
|
23
|
+
express_app,
|
|
24
|
+
joystick_build_path,
|
|
25
|
+
middleware_config: config?.middleware,
|
|
26
|
+
port,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
if (app_instance?.options?.middleware && types.is_array(app_instance?.options?.middleware)) {
|
|
30
|
+
for (let i = 0; i < app_instance?.options?.middleware?.length; i += 1) {
|
|
31
|
+
const middleware_to_run = app_instance?.options?.middleware[i];
|
|
32
|
+
express_app.use(middleware_to_run);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const instance = {
|
|
37
|
+
port,
|
|
38
|
+
app: express_app,
|
|
39
|
+
server,
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
if (types.is_function(on_after_start_server)) {
|
|
43
|
+
on_after_start_server(instance, app_instance);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return instance;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export default start_express;
|
|
50
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import cluster from "cluster";
|
|
2
|
+
import os from "os";
|
|
3
|
+
|
|
4
|
+
const start_node_as_cluster = (callback = null) => {
|
|
5
|
+
const cpus = os.cpus().length;
|
|
6
|
+
|
|
7
|
+
if (cluster.isPrimary) {
|
|
8
|
+
for (let i = 0; i < cpus; i++) {
|
|
9
|
+
const worker = cluster.fork();
|
|
10
|
+
|
|
11
|
+
worker.on("message", (message) => {
|
|
12
|
+
if (process.send) {
|
|
13
|
+
process.send(message);
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
process.on("message", (message) => {
|
|
18
|
+
worker.send(message);
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
cluster.on("exit", (worker) => {
|
|
23
|
+
console.warn(`Worker ${worker.process.pid} died.`);
|
|
24
|
+
});
|
|
25
|
+
} else {
|
|
26
|
+
callback();
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export default start_node_as_cluster;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import emit_websocket_event from "../websockets/emit_event.js";
|
|
2
|
+
import float_to_decimal_place from '../../lib/float_to_decimal_place.js';
|
|
3
|
+
|
|
4
|
+
const local_upload_progress_middleware = (providers = 1, req = {}, res = {}, next) => {
|
|
5
|
+
let progress = 0;
|
|
6
|
+
const file_size = parseInt(req.headers["content-length"], 10);
|
|
7
|
+
|
|
8
|
+
req.on("data", (chunk) => {
|
|
9
|
+
if (chunk.length > 0) {
|
|
10
|
+
progress += chunk.length;
|
|
11
|
+
const percentage = float_to_decimal_place((progress / (file_size * providers)) * 100);
|
|
12
|
+
emit_websocket_event(
|
|
13
|
+
`uploaders_${req?.headers["x-joystick-upload-id"]}`,
|
|
14
|
+
"progress",
|
|
15
|
+
{ provider: "local", progress: percentage }
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
next();
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export default local_upload_progress_middleware;
|
|
24
|
+
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import multer from 'multer';
|
|
2
|
+
import get_browser_safe_request from '../../lib/get_browser_safe_request.js'
|
|
3
|
+
import handle_api_error from '../api/handle_api_error.js';
|
|
4
|
+
import is_valid_json from '../../lib/is_valid_json.js';
|
|
5
|
+
import local_upload_progress_middleware from './local_upload_progress_middleware.js';
|
|
6
|
+
import run_upload from './run_upload.js';
|
|
7
|
+
import string_to_slug from "../../lib/string_to_slug.js";
|
|
8
|
+
import track_function_call from '../../test/track_function_call.js';
|
|
9
|
+
import types from '../../lib/types.js';
|
|
10
|
+
import validate_uploader_options from './validate_options.js';
|
|
11
|
+
import validate_uploads from './validate_uploads.js';
|
|
12
|
+
|
|
13
|
+
const upload_files = async (upload_options = {}) => {
|
|
14
|
+
const upload_size = parseInt(upload_options?.req?.headers["content-length"], 10);
|
|
15
|
+
const providers = upload_options?.uploader_options?.providers?.includes("local")
|
|
16
|
+
// NOTE: If an explicit local upload is defined, we DO NOT want to account for
|
|
17
|
+
// the transfer from the client to the server. That progress has already been
|
|
18
|
+
// tracked via the local_upload_progress_middleware.
|
|
19
|
+
? upload_options?.uploader_options?.providers.length
|
|
20
|
+
// NOTE: If there IS NOT a local upload, we want to account for the transfer
|
|
21
|
+
// from the client to the server.
|
|
22
|
+
: upload_options?.uploader_options?.providers?.length + 1;
|
|
23
|
+
const total_upload_size_all_providers = upload_size * providers;
|
|
24
|
+
|
|
25
|
+
return run_upload({
|
|
26
|
+
// NOTE: This accounts for the file being uploaded to the server which should factor in to
|
|
27
|
+
// the current upload progress. More important for big files or multiple files.
|
|
28
|
+
existing_upload_progress: upload_size,
|
|
29
|
+
total_upload_size_all_providers,
|
|
30
|
+
uploads: upload_options?.validated_uploads,
|
|
31
|
+
input: upload_options?.upload_input,
|
|
32
|
+
req: upload_options?.req,
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const handle_on_after_upload = async (uploader_name = '', on_after_upload = null, on_after_upload_options = {}) => {
|
|
37
|
+
// NOTE: IF this throws an error, abort upload.
|
|
38
|
+
await on_after_upload({
|
|
39
|
+
input: on_after_upload_options?.input,
|
|
40
|
+
req: on_after_upload_options?.req,
|
|
41
|
+
uploads: on_after_upload_options?.uploads,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
track_function_call(`node.uploaders.${uploader_name}.on_after_upload`, [{
|
|
45
|
+
input: on_after_upload_options?.input,
|
|
46
|
+
req: get_browser_safe_request(on_after_upload_options?.req),
|
|
47
|
+
uploads: on_after_upload_options?.uploads,
|
|
48
|
+
}]);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const handle_on_before_upload = async (uploader_name = '', on_before_upload = null, on_before_upload_options = {}) => {
|
|
52
|
+
// NOTE: IF this throws an error, abort upload.
|
|
53
|
+
await on_before_upload({
|
|
54
|
+
input: on_before_upload_options?.input,
|
|
55
|
+
req: on_before_upload_options?.req,
|
|
56
|
+
uploads: on_before_upload_options?.uploads,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
track_function_call(`node.uploaders.${uploader_name}.on_before_upload`, [{
|
|
60
|
+
input: on_before_upload_options?.input,
|
|
61
|
+
req: get_browser_safe_request(on_before_upload_options?.req),
|
|
62
|
+
uploads: on_before_upload_options?.uploads,
|
|
63
|
+
}]);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const get_uploader_input = (input = '') => {
|
|
67
|
+
return input && is_valid_json(input) && JSON.parse(input);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const handle_upload = async (uploader_name = '', uploader_options = {}, req = {}, res = {}) => {
|
|
71
|
+
try {
|
|
72
|
+
const uploader_input = get_uploader_input(req?.headers['x-joystick-upload-input']);
|
|
73
|
+
|
|
74
|
+
const validated_uploads = await validate_uploads({
|
|
75
|
+
files: req?.files,
|
|
76
|
+
uploader_input,
|
|
77
|
+
uploader_name,
|
|
78
|
+
uploader_options
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
if (validated_uploads?.errors) {
|
|
82
|
+
return handle_api_error(`uploaders.${uploader_name}`, validated_uploads, res);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (types.is_function(uploader_options?.onBeforeUpload) || types.is_function(uploader_options?.on_before_upload)) {
|
|
86
|
+
await handle_on_before_upload(uploader_name, uploader_options?.onBeforeUpload || uploader_options?.on_before_upload, {
|
|
87
|
+
input: uploader_input,
|
|
88
|
+
req,
|
|
89
|
+
uploads: validated_uploads,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const uploaded_files = await upload_files({
|
|
94
|
+
validated_uploads,
|
|
95
|
+
uploader_input,
|
|
96
|
+
uploader_options,
|
|
97
|
+
req,
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
if (types.is_function(uploader_options?.onAfterUpload) || types.is_function(uploader_options?.on_after_upload)) {
|
|
101
|
+
await handle_on_after_upload(uploader_name, uploader_options?.onAfterUpload || uploader_options?.on_after_upload, {
|
|
102
|
+
input: uploader_input,
|
|
103
|
+
req,
|
|
104
|
+
uploads: uploaded_files,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return res.status(200).send(JSON.stringify({ uploads: uploaded_files }));
|
|
109
|
+
} catch (error) {
|
|
110
|
+
handle_api_error(`uploaders.${uploader_name}`, error, res);
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const register_uploader_route = (uploader_name = '', uploader_options = {}, app_instance = {}) => {
|
|
115
|
+
const formatted_uploader_name = string_to_slug(uploader_name);
|
|
116
|
+
const max_upload_size = uploader_options?.maxSizeInMegabytes || uploader_options?.max_size_in_megabytes;
|
|
117
|
+
const uploader = multer({ limits: { fileSize: `${max_upload_size || 10}MB` } });
|
|
118
|
+
// NOTE: Max of 10 files at a time to avoid flooding the server.
|
|
119
|
+
const multer_middleware = uploader.array('files', 10);
|
|
120
|
+
const providers = uploader_options?.providers?.includes('local') ?
|
|
121
|
+
uploader_options?.providers?.length :
|
|
122
|
+
uploader_options?.providers?.length + 1;
|
|
123
|
+
|
|
124
|
+
app_instance.express.app.post(
|
|
125
|
+
`/api/_uploaders/${formatted_uploader_name}`,
|
|
126
|
+
(req, res, next) => local_upload_progress_middleware(providers, req, res, next),
|
|
127
|
+
// NOTE: Sigh. No other way to hook into the error handling for Multer.
|
|
128
|
+
(req, res, next) => multer_middleware(req, res, (multer_error) => {
|
|
129
|
+
if (multer_error) {
|
|
130
|
+
let error = multer_error;
|
|
131
|
+
|
|
132
|
+
if (multer_error?.message === 'File too large') {
|
|
133
|
+
error = new Error(`Max file size is ${max_upload_size}MB.`);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
handle_api_error(`uploader.${uploader_name}`, error, res);
|
|
137
|
+
} else {
|
|
138
|
+
next();
|
|
139
|
+
}
|
|
140
|
+
}),
|
|
141
|
+
(req = {}, res = {}) => handle_upload(uploader_name, uploader_options, req, res),
|
|
142
|
+
);
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const warn_uploader_options_errors = (uploader_options_errors = []) => {
|
|
146
|
+
if (uploader_options_errors?.length > 0) {
|
|
147
|
+
for (let i = 0; i < uploader_options_errors?.length; i += 1) {
|
|
148
|
+
const uploader_options_error = uploader_options_errors[i];
|
|
149
|
+
console.error(uploader_options_error);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const register = (user_uploader_definitions = {}, app_instance = {}) => {
|
|
155
|
+
const uploader_definitions = Object.entries(user_uploader_definitions);
|
|
156
|
+
|
|
157
|
+
for (let i = 0; i < uploader_definitions?.length; i += 1) {
|
|
158
|
+
const [uploader_name, uploader_options] = uploader_definitions[i];
|
|
159
|
+
const uploader_options_errors = validate_uploader_options(uploader_options);
|
|
160
|
+
|
|
161
|
+
warn_uploader_options_errors(uploader_options_errors);
|
|
162
|
+
|
|
163
|
+
if (uploader_options_errors?.length === 0) {
|
|
164
|
+
register_uploader_route(uploader_name, uploader_options, app_instance);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
export default register;
|