diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..95d898d
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,894 @@
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 4
+indent_style = space
+insert_final_newline = false
+max_line_length = 999
+tab_width = 4
+ij_continuation_indent_size = 8
+ij_formatter_off_tag = @formatter:off
+ij_formatter_on_tag = @formatter:on
+ij_formatter_tags_enabled = false
+ij_smart_tabs = false
+ij_visual_guides = none
+ij_wrap_on_typing = false
+
+[*.blade.php]
+ij_blade_keep_indents_on_empty_lines = false
+
+[*.css]
+ij_css_align_closing_brace_with_properties = false
+ij_css_blank_lines_around_nested_selector = 1
+ij_css_blank_lines_between_blocks = 1
+ij_css_block_comment_add_space = false
+ij_css_brace_placement = end_of_line
+ij_css_enforce_quotes_on_format = false
+ij_css_hex_color_long_format = false
+ij_css_hex_color_lower_case = false
+ij_css_hex_color_short_format = false
+ij_css_hex_color_upper_case = false
+ij_css_keep_blank_lines_in_code = 2
+ij_css_keep_indents_on_empty_lines = false
+ij_css_keep_single_line_blocks = false
+ij_css_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
+ij_css_space_after_colon = true
+ij_css_space_before_opening_brace = true
+ij_css_use_double_quotes = true
+ij_css_value_alignment = do_not_align
+
+[*.feature]
+indent_size = 2
+ij_gherkin_keep_indents_on_empty_lines = false
+
+[*.haml]
+indent_size = 2
+ij_haml_keep_indents_on_empty_lines = false
+
+[*.less]
+indent_size = 2
+ij_less_align_closing_brace_with_properties = false
+ij_less_blank_lines_around_nested_selector = 1
+ij_less_blank_lines_between_blocks = 1
+ij_less_block_comment_add_space = false
+ij_less_brace_placement = 0
+ij_less_enforce_quotes_on_format = false
+ij_less_hex_color_long_format = false
+ij_less_hex_color_lower_case = false
+ij_less_hex_color_short_format = false
+ij_less_hex_color_upper_case = false
+ij_less_keep_blank_lines_in_code = 2
+ij_less_keep_indents_on_empty_lines = false
+ij_less_keep_single_line_blocks = false
+ij_less_line_comment_add_space = false
+ij_less_line_comment_at_first_column = false
+ij_less_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
+ij_less_space_after_colon = true
+ij_less_space_before_opening_brace = true
+ij_less_use_double_quotes = true
+ij_less_value_alignment = 0
+
+[*.sass]
+indent_size = 2
+ij_sass_align_closing_brace_with_properties = false
+ij_sass_blank_lines_around_nested_selector = 1
+ij_sass_blank_lines_between_blocks = 1
+ij_sass_brace_placement = 0
+ij_sass_enforce_quotes_on_format = false
+ij_sass_hex_color_long_format = false
+ij_sass_hex_color_lower_case = false
+ij_sass_hex_color_short_format = false
+ij_sass_hex_color_upper_case = false
+ij_sass_keep_blank_lines_in_code = 2
+ij_sass_keep_indents_on_empty_lines = false
+ij_sass_keep_single_line_blocks = false
+ij_sass_line_comment_add_space = false
+ij_sass_line_comment_at_first_column = false
+ij_sass_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
+ij_sass_space_after_colon = true
+ij_sass_space_before_opening_brace = true
+ij_sass_use_double_quotes = true
+ij_sass_value_alignment = 0
+
+[*.scss]
+ij_scss_align_closing_brace_with_properties = false
+ij_scss_blank_lines_around_nested_selector = 1
+ij_scss_blank_lines_between_blocks = 1
+ij_scss_block_comment_add_space = false
+ij_scss_brace_placement = 0
+ij_scss_enforce_quotes_on_format = false
+ij_scss_hex_color_long_format = false
+ij_scss_hex_color_lower_case = false
+ij_scss_hex_color_short_format = false
+ij_scss_hex_color_upper_case = false
+ij_scss_keep_blank_lines_in_code = 2
+ij_scss_keep_indents_on_empty_lines = false
+ij_scss_keep_single_line_blocks = false
+ij_scss_line_comment_add_space = false
+ij_scss_line_comment_at_first_column = false
+ij_scss_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
+ij_scss_space_after_colon = true
+ij_scss_space_before_opening_brace = true
+ij_scss_use_double_quotes = true
+ij_scss_value_alignment = 0
+
+[*.twig]
+ij_twig_keep_indents_on_empty_lines = false
+ij_twig_spaces_inside_comments_delimiters = true
+ij_twig_spaces_inside_delimiters = true
+ij_twig_spaces_inside_variable_delimiters = true
+
+[*.vue]
+indent_size = 2
+tab_width = 2
+ij_continuation_indent_size = 4
+ij_vue_indent_children_of_top_level = template
+ij_vue_interpolation_new_line_after_start_delimiter = true
+ij_vue_interpolation_new_line_before_end_delimiter = true
+ij_vue_interpolation_wrap = off
+ij_vue_keep_indents_on_empty_lines = false
+ij_vue_spaces_within_interpolation_expressions = true
+
+[.editorconfig]
+ij_editorconfig_align_group_field_declarations = false
+ij_editorconfig_space_after_colon = false
+ij_editorconfig_space_after_comma = true
+ij_editorconfig_space_before_colon = false
+ij_editorconfig_space_before_comma = false
+ij_editorconfig_spaces_around_assignment_operators = true
+
+[{*.ant,*.fxml,*.jhm,*.jnlp,*.jrxml,*.rng,*.tld,*.wsdl,*.xml,*.xsd,*.xsl,*.xslt,*.xul,phpunit.xml.dist}]
+ij_xml_align_attributes = true
+ij_xml_align_text = false
+ij_xml_attribute_wrap = normal
+ij_xml_block_comment_add_space = false
+ij_xml_block_comment_at_first_column = true
+ij_xml_keep_blank_lines = 2
+ij_xml_keep_indents_on_empty_lines = false
+ij_xml_keep_line_breaks = true
+ij_xml_keep_line_breaks_in_text = true
+ij_xml_keep_whitespaces = false
+ij_xml_keep_whitespaces_around_cdata = preserve
+ij_xml_keep_whitespaces_inside_cdata = false
+ij_xml_line_comment_at_first_column = true
+ij_xml_space_after_tag_name = false
+ij_xml_space_around_equals_in_attribute = false
+ij_xml_space_inside_empty_tag = false
+ij_xml_text_wrap = normal
+
+[{*.ats,*.cts,*.mts,*.ts}]
+ij_continuation_indent_size = 4
+ij_typescript_align_imports = false
+ij_typescript_align_multiline_array_initializer_expression = false
+ij_typescript_align_multiline_binary_operation = false
+ij_typescript_align_multiline_chained_methods = false
+ij_typescript_align_multiline_extends_list = false
+ij_typescript_align_multiline_for = true
+ij_typescript_align_multiline_parameters = true
+ij_typescript_align_multiline_parameters_in_calls = false
+ij_typescript_align_multiline_ternary_operation = false
+ij_typescript_align_object_properties = 0
+ij_typescript_align_union_types = false
+ij_typescript_align_var_statements = 0
+ij_typescript_array_initializer_new_line_after_left_brace = false
+ij_typescript_array_initializer_right_brace_on_new_line = false
+ij_typescript_array_initializer_wrap = off
+ij_typescript_assignment_wrap = off
+ij_typescript_binary_operation_sign_on_next_line = false
+ij_typescript_binary_operation_wrap = off
+ij_typescript_blacklist_imports = rxjs/Rx,node_modules/**,**/node_modules/**,@angular/material,@angular/material/typings/**
+ij_typescript_blank_lines_after_imports = 1
+ij_typescript_blank_lines_around_class = 1
+ij_typescript_blank_lines_around_field = 0
+ij_typescript_blank_lines_around_field_in_interface = 0
+ij_typescript_blank_lines_around_function = 1
+ij_typescript_blank_lines_around_method = 1
+ij_typescript_blank_lines_around_method_in_interface = 1
+ij_typescript_block_brace_style = end_of_line
+ij_typescript_block_comment_add_space = false
+ij_typescript_block_comment_at_first_column = true
+ij_typescript_call_parameters_new_line_after_left_paren = false
+ij_typescript_call_parameters_right_paren_on_new_line = false
+ij_typescript_call_parameters_wrap = off
+ij_typescript_catch_on_new_line = false
+ij_typescript_chained_call_dot_on_new_line = true
+ij_typescript_class_brace_style = next_line_if_wrapped
+ij_typescript_comma_on_new_line = false
+ij_typescript_do_while_brace_force = never
+ij_typescript_else_on_new_line = false
+ij_typescript_enforce_trailing_comma = keep
+ij_typescript_enum_constants_wrap = on_every_item
+ij_typescript_extends_keyword_wrap = off
+ij_typescript_extends_list_wrap = off
+ij_typescript_field_prefix = _
+ij_typescript_file_name_style = relaxed
+ij_typescript_finally_on_new_line = false
+ij_typescript_for_brace_force = never
+ij_typescript_for_statement_new_line_after_left_paren = false
+ij_typescript_for_statement_right_paren_on_new_line = false
+ij_typescript_for_statement_wrap = off
+ij_typescript_force_quote_style = false
+ij_typescript_force_semicolon_style = true
+ij_typescript_function_expression_brace_style = end_of_line
+ij_typescript_if_brace_force = never
+ij_typescript_import_merge_members = global
+ij_typescript_import_prefer_absolute_path = global
+ij_typescript_import_sort_members = true
+ij_typescript_import_sort_module_name = false
+ij_typescript_import_use_node_resolution = true
+ij_typescript_imports_wrap = off
+ij_typescript_indent_case_from_switch = true
+ij_typescript_indent_chained_calls = false
+ij_typescript_indent_package_children = 0
+ij_typescript_jsdoc_include_types = false
+ij_typescript_jsx_attribute_value = braces
+ij_typescript_keep_blank_lines_in_code = 2
+ij_typescript_keep_first_column_comment = true
+ij_typescript_keep_indents_on_empty_lines = false
+ij_typescript_keep_line_breaks = true
+ij_typescript_keep_simple_blocks_in_one_line = false
+ij_typescript_keep_simple_methods_in_one_line = false
+ij_typescript_line_comment_add_space = true
+ij_typescript_line_comment_at_first_column = false
+ij_typescript_method_brace_style = next_line_if_wrapped
+ij_typescript_method_call_chain_wrap = off
+ij_typescript_method_parameters_new_line_after_left_paren = false
+ij_typescript_method_parameters_right_paren_on_new_line = false
+ij_typescript_method_parameters_wrap = off
+ij_typescript_object_literal_wrap = off
+ij_typescript_parentheses_expression_new_line_after_left_paren = false
+ij_typescript_parentheses_expression_right_paren_on_new_line = false
+ij_typescript_place_assignment_sign_on_next_line = false
+ij_typescript_prefer_as_type_cast = false
+ij_typescript_prefer_explicit_types_function_expression_returns = false
+ij_typescript_prefer_explicit_types_function_returns = false
+ij_typescript_prefer_explicit_types_vars_fields = false
+ij_typescript_prefer_parameters_wrap = false
+ij_typescript_reformat_c_style_comments = false
+ij_typescript_space_after_colon = true
+ij_typescript_space_after_comma = true
+ij_typescript_space_after_dots_in_rest_parameter = false
+ij_typescript_space_after_generator_mult = true
+ij_typescript_space_after_property_colon = true
+ij_typescript_space_after_quest = true
+ij_typescript_space_after_type_colon = true
+ij_typescript_space_after_unary_not = false
+ij_typescript_space_before_async_arrow_lparen = true
+ij_typescript_space_before_catch_keyword = true
+ij_typescript_space_before_catch_left_brace = true
+ij_typescript_space_before_catch_parentheses = true
+ij_typescript_space_before_class_lbrace = true
+ij_typescript_space_before_class_left_brace = true
+ij_typescript_space_before_colon = true
+ij_typescript_space_before_comma = false
+ij_typescript_space_before_do_left_brace = true
+ij_typescript_space_before_else_keyword = true
+ij_typescript_space_before_else_left_brace = true
+ij_typescript_space_before_finally_keyword = true
+ij_typescript_space_before_finally_left_brace = true
+ij_typescript_space_before_for_left_brace = true
+ij_typescript_space_before_for_parentheses = true
+ij_typescript_space_before_for_semicolon = false
+ij_typescript_space_before_function_left_parenth = true
+ij_typescript_space_before_generator_mult = false
+ij_typescript_space_before_if_left_brace = true
+ij_typescript_space_before_if_parentheses = true
+ij_typescript_space_before_method_call_parentheses = false
+ij_typescript_space_before_method_left_brace = true
+ij_typescript_space_before_method_parentheses = false
+ij_typescript_space_before_property_colon = false
+ij_typescript_space_before_quest = true
+ij_typescript_space_before_switch_left_brace = true
+ij_typescript_space_before_switch_parentheses = true
+ij_typescript_space_before_try_left_brace = true
+ij_typescript_space_before_type_colon = false
+ij_typescript_space_before_unary_not = false
+ij_typescript_space_before_while_keyword = true
+ij_typescript_space_before_while_left_brace = true
+ij_typescript_space_before_while_parentheses = true
+ij_typescript_spaces_around_additive_operators = true
+ij_typescript_spaces_around_arrow_function_operator = true
+ij_typescript_spaces_around_assignment_operators = true
+ij_typescript_spaces_around_bitwise_operators = true
+ij_typescript_spaces_around_equality_operators = true
+ij_typescript_spaces_around_logical_operators = true
+ij_typescript_spaces_around_multiplicative_operators = true
+ij_typescript_spaces_around_relational_operators = true
+ij_typescript_spaces_around_shift_operators = true
+ij_typescript_spaces_around_unary_operator = false
+ij_typescript_spaces_within_array_initializer_brackets = false
+ij_typescript_spaces_within_brackets = false
+ij_typescript_spaces_within_catch_parentheses = false
+ij_typescript_spaces_within_for_parentheses = false
+ij_typescript_spaces_within_if_parentheses = false
+ij_typescript_spaces_within_imports = false
+ij_typescript_spaces_within_interpolation_expressions = true
+ij_typescript_spaces_within_method_call_parentheses = false
+ij_typescript_spaces_within_method_parentheses = false
+ij_typescript_spaces_within_object_literal_braces = true
+ij_typescript_spaces_within_object_type_braces = true
+ij_typescript_spaces_within_parentheses = false
+ij_typescript_spaces_within_switch_parentheses = false
+ij_typescript_spaces_within_type_assertion = false
+ij_typescript_spaces_within_union_types = true
+ij_typescript_spaces_within_while_parentheses = false
+ij_typescript_special_else_if_treatment = true
+ij_typescript_ternary_operation_signs_on_next_line = false
+ij_typescript_ternary_operation_wrap = off
+ij_typescript_union_types_wrap = on_every_item
+ij_typescript_use_chained_calls_group_indents = false
+ij_typescript_use_double_quotes = true
+ij_typescript_use_explicit_js_extension = auto
+ij_typescript_use_path_mapping = always
+ij_typescript_use_public_modifier = false
+ij_typescript_use_semicolon_after_statement = false
+ij_typescript_var_declaration_wrap = normal
+ij_typescript_while_brace_force = never
+ij_typescript_while_on_new_line = false
+ij_typescript_wrap_comments = false
+
+[{*.bash,*.sh,*.zsh}]
+indent_size = 2
+tab_width = 2
+ij_shell_binary_ops_start_line = false
+ij_shell_keep_column_alignment_padding = false
+ij_shell_minify_program = false
+ij_shell_redirect_followed_by_space = false
+ij_shell_switch_cases_indented = false
+ij_shell_use_unix_line_separator = true
+
+[{*.cjs,*.js}]
+ij_continuation_indent_size = 4
+ij_javascript_align_imports = false
+ij_javascript_align_multiline_array_initializer_expression = false
+ij_javascript_align_multiline_binary_operation = false
+ij_javascript_align_multiline_chained_methods = false
+ij_javascript_align_multiline_extends_list = false
+ij_javascript_align_multiline_for = true
+ij_javascript_align_multiline_parameters = true
+ij_javascript_align_multiline_parameters_in_calls = false
+ij_javascript_align_multiline_ternary_operation = false
+ij_javascript_align_object_properties = 0
+ij_javascript_align_union_types = false
+ij_javascript_align_var_statements = 0
+ij_javascript_array_initializer_new_line_after_left_brace = false
+ij_javascript_array_initializer_right_brace_on_new_line = false
+ij_javascript_array_initializer_wrap = off
+ij_javascript_assignment_wrap = off
+ij_javascript_binary_operation_sign_on_next_line = false
+ij_javascript_binary_operation_wrap = off
+ij_javascript_blacklist_imports = rxjs/Rx,node_modules/**,**/node_modules/**,@angular/material,@angular/material/typings/**
+ij_javascript_blank_lines_after_imports = 1
+ij_javascript_blank_lines_around_class = 1
+ij_javascript_blank_lines_around_field = 0
+ij_javascript_blank_lines_around_function = 1
+ij_javascript_blank_lines_around_method = 1
+ij_javascript_block_brace_style = end_of_line
+ij_javascript_block_comment_add_space = false
+ij_javascript_block_comment_at_first_column = true
+ij_javascript_call_parameters_new_line_after_left_paren = false
+ij_javascript_call_parameters_right_paren_on_new_line = false
+ij_javascript_call_parameters_wrap = off
+ij_javascript_catch_on_new_line = false
+ij_javascript_chained_call_dot_on_new_line = true
+ij_javascript_class_brace_style = next_line
+ij_javascript_comma_on_new_line = false
+ij_javascript_do_while_brace_force = never
+ij_javascript_else_on_new_line = false
+ij_javascript_enforce_trailing_comma = keep
+ij_javascript_extends_keyword_wrap = off
+ij_javascript_extends_list_wrap = off
+ij_javascript_field_prefix = _
+ij_javascript_file_name_style = relaxed
+ij_javascript_finally_on_new_line = false
+ij_javascript_for_brace_force = never
+ij_javascript_for_statement_new_line_after_left_paren = false
+ij_javascript_for_statement_right_paren_on_new_line = false
+ij_javascript_for_statement_wrap = off
+ij_javascript_force_quote_style = false
+ij_javascript_force_semicolon_style = false
+ij_javascript_function_expression_brace_style = end_of_line
+ij_javascript_if_brace_force = never
+ij_javascript_import_merge_members = global
+ij_javascript_import_prefer_absolute_path = global
+ij_javascript_import_sort_members = true
+ij_javascript_import_sort_module_name = false
+ij_javascript_import_use_node_resolution = true
+ij_javascript_imports_wrap = off
+ij_javascript_indent_case_from_switch = true
+ij_javascript_indent_chained_calls = false
+ij_javascript_indent_package_children = 0
+ij_javascript_jsx_attribute_value = braces
+ij_javascript_keep_blank_lines_in_code = 2
+ij_javascript_keep_first_column_comment = true
+ij_javascript_keep_indents_on_empty_lines = false
+ij_javascript_keep_line_breaks = true
+ij_javascript_keep_simple_blocks_in_one_line = false
+ij_javascript_keep_simple_methods_in_one_line = false
+ij_javascript_line_comment_add_space = true
+ij_javascript_line_comment_at_first_column = false
+ij_javascript_method_brace_style = next_line
+ij_javascript_method_call_chain_wrap = off
+ij_javascript_method_parameters_new_line_after_left_paren = false
+ij_javascript_method_parameters_right_paren_on_new_line = false
+ij_javascript_method_parameters_wrap = off
+ij_javascript_object_literal_wrap = off
+ij_javascript_parentheses_expression_new_line_after_left_paren = false
+ij_javascript_parentheses_expression_right_paren_on_new_line = false
+ij_javascript_place_assignment_sign_on_next_line = false
+ij_javascript_prefer_as_type_cast = false
+ij_javascript_prefer_explicit_types_function_expression_returns = false
+ij_javascript_prefer_explicit_types_function_returns = false
+ij_javascript_prefer_explicit_types_vars_fields = false
+ij_javascript_prefer_parameters_wrap = false
+ij_javascript_reformat_c_style_comments = true
+ij_javascript_space_after_colon = true
+ij_javascript_space_after_comma = true
+ij_javascript_space_after_dots_in_rest_parameter = false
+ij_javascript_space_after_generator_mult = true
+ij_javascript_space_after_property_colon = true
+ij_javascript_space_after_quest = true
+ij_javascript_space_after_type_colon = true
+ij_javascript_space_after_unary_not = false
+ij_javascript_space_before_async_arrow_lparen = true
+ij_javascript_space_before_catch_keyword = true
+ij_javascript_space_before_catch_left_brace = true
+ij_javascript_space_before_catch_parentheses = true
+ij_javascript_space_before_class_lbrace = true
+ij_javascript_space_before_class_left_brace = true
+ij_javascript_space_before_colon = true
+ij_javascript_space_before_comma = false
+ij_javascript_space_before_do_left_brace = true
+ij_javascript_space_before_else_keyword = true
+ij_javascript_space_before_else_left_brace = true
+ij_javascript_space_before_finally_keyword = true
+ij_javascript_space_before_finally_left_brace = true
+ij_javascript_space_before_for_left_brace = true
+ij_javascript_space_before_for_parentheses = true
+ij_javascript_space_before_for_semicolon = false
+ij_javascript_space_before_function_left_parenth = true
+ij_javascript_space_before_generator_mult = false
+ij_javascript_space_before_if_left_brace = true
+ij_javascript_space_before_if_parentheses = true
+ij_javascript_space_before_method_call_parentheses = false
+ij_javascript_space_before_method_left_brace = true
+ij_javascript_space_before_method_parentheses = false
+ij_javascript_space_before_property_colon = false
+ij_javascript_space_before_quest = true
+ij_javascript_space_before_switch_left_brace = true
+ij_javascript_space_before_switch_parentheses = true
+ij_javascript_space_before_try_left_brace = true
+ij_javascript_space_before_type_colon = false
+ij_javascript_space_before_unary_not = false
+ij_javascript_space_before_while_keyword = true
+ij_javascript_space_before_while_left_brace = true
+ij_javascript_space_before_while_parentheses = true
+ij_javascript_spaces_around_additive_operators = true
+ij_javascript_spaces_around_arrow_function_operator = true
+ij_javascript_spaces_around_assignment_operators = true
+ij_javascript_spaces_around_bitwise_operators = true
+ij_javascript_spaces_around_equality_operators = true
+ij_javascript_spaces_around_logical_operators = true
+ij_javascript_spaces_around_multiplicative_operators = true
+ij_javascript_spaces_around_relational_operators = true
+ij_javascript_spaces_around_shift_operators = true
+ij_javascript_spaces_around_unary_operator = false
+ij_javascript_spaces_within_array_initializer_brackets = false
+ij_javascript_spaces_within_brackets = false
+ij_javascript_spaces_within_catch_parentheses = false
+ij_javascript_spaces_within_for_parentheses = false
+ij_javascript_spaces_within_if_parentheses = false
+ij_javascript_spaces_within_imports = true
+ij_javascript_spaces_within_interpolation_expressions = true
+ij_javascript_spaces_within_method_call_parentheses = false
+ij_javascript_spaces_within_method_parentheses = false
+ij_javascript_spaces_within_object_literal_braces = true
+ij_javascript_spaces_within_object_type_braces = true
+ij_javascript_spaces_within_parentheses = false
+ij_javascript_spaces_within_switch_parentheses = false
+ij_javascript_spaces_within_type_assertion = false
+ij_javascript_spaces_within_union_types = true
+ij_javascript_spaces_within_while_parentheses = false
+ij_javascript_special_else_if_treatment = true
+ij_javascript_ternary_operation_signs_on_next_line = false
+ij_javascript_ternary_operation_wrap = off
+ij_javascript_union_types_wrap = on_every_item
+ij_javascript_use_chained_calls_group_indents = false
+ij_javascript_use_double_quotes = true
+ij_javascript_use_explicit_js_extension = auto
+ij_javascript_use_path_mapping = always
+ij_javascript_use_public_modifier = false
+ij_javascript_use_semicolon_after_statement = true
+ij_javascript_var_declaration_wrap = off
+ij_javascript_while_brace_force = never
+ij_javascript_while_on_new_line = false
+ij_javascript_wrap_comments = false
+
+[{*.cjsx,*.coffee}]
+indent_size = 2
+tab_width = 2
+ij_continuation_indent_size = 2
+ij_coffeescript_align_function_body = false
+ij_coffeescript_align_imports = false
+ij_coffeescript_align_multiline_array_initializer_expression = true
+ij_coffeescript_align_multiline_parameters = true
+ij_coffeescript_align_multiline_parameters_in_calls = false
+ij_coffeescript_align_object_properties = 0
+ij_coffeescript_align_union_types = false
+ij_coffeescript_align_var_statements = 0
+ij_coffeescript_array_initializer_new_line_after_left_brace = false
+ij_coffeescript_array_initializer_right_brace_on_new_line = false
+ij_coffeescript_array_initializer_wrap = normal
+ij_coffeescript_blacklist_imports = rxjs/Rx,node_modules/**,**/node_modules/**,@angular/material,@angular/material/typings/**
+ij_coffeescript_blank_lines_around_function = 1
+ij_coffeescript_call_parameters_new_line_after_left_paren = false
+ij_coffeescript_call_parameters_right_paren_on_new_line = false
+ij_coffeescript_call_parameters_wrap = normal
+ij_coffeescript_chained_call_dot_on_new_line = true
+ij_coffeescript_comma_on_new_line = false
+ij_coffeescript_enforce_trailing_comma = keep
+ij_coffeescript_field_prefix = _
+ij_coffeescript_file_name_style = relaxed
+ij_coffeescript_force_quote_style = false
+ij_coffeescript_force_semicolon_style = false
+ij_coffeescript_function_expression_brace_style = end_of_line
+ij_coffeescript_import_merge_members = global
+ij_coffeescript_import_prefer_absolute_path = global
+ij_coffeescript_import_sort_members = true
+ij_coffeescript_import_sort_module_name = false
+ij_coffeescript_import_use_node_resolution = true
+ij_coffeescript_imports_wrap = on_every_item
+ij_coffeescript_indent_chained_calls = true
+ij_coffeescript_indent_package_children = 0
+ij_coffeescript_jsx_attribute_value = braces
+ij_coffeescript_keep_blank_lines_in_code = 2
+ij_coffeescript_keep_first_column_comment = true
+ij_coffeescript_keep_indents_on_empty_lines = false
+ij_coffeescript_keep_line_breaks = true
+ij_coffeescript_keep_simple_methods_in_one_line = false
+ij_coffeescript_method_parameters_new_line_after_left_paren = false
+ij_coffeescript_method_parameters_right_paren_on_new_line = false
+ij_coffeescript_method_parameters_wrap = off
+ij_coffeescript_object_literal_wrap = on_every_item
+ij_coffeescript_prefer_as_type_cast = false
+ij_coffeescript_prefer_explicit_types_function_expression_returns = false
+ij_coffeescript_prefer_explicit_types_function_returns = false
+ij_coffeescript_prefer_explicit_types_vars_fields = false
+ij_coffeescript_reformat_c_style_comments = false
+ij_coffeescript_space_after_comma = true
+ij_coffeescript_space_after_dots_in_rest_parameter = false
+ij_coffeescript_space_after_generator_mult = true
+ij_coffeescript_space_after_property_colon = true
+ij_coffeescript_space_after_type_colon = true
+ij_coffeescript_space_after_unary_not = false
+ij_coffeescript_space_before_async_arrow_lparen = true
+ij_coffeescript_space_before_class_lbrace = true
+ij_coffeescript_space_before_comma = false
+ij_coffeescript_space_before_function_left_parenth = true
+ij_coffeescript_space_before_generator_mult = false
+ij_coffeescript_space_before_property_colon = false
+ij_coffeescript_space_before_type_colon = false
+ij_coffeescript_space_before_unary_not = false
+ij_coffeescript_spaces_around_additive_operators = true
+ij_coffeescript_spaces_around_arrow_function_operator = true
+ij_coffeescript_spaces_around_assignment_operators = true
+ij_coffeescript_spaces_around_bitwise_operators = true
+ij_coffeescript_spaces_around_equality_operators = true
+ij_coffeescript_spaces_around_logical_operators = true
+ij_coffeescript_spaces_around_multiplicative_operators = true
+ij_coffeescript_spaces_around_relational_operators = true
+ij_coffeescript_spaces_around_shift_operators = true
+ij_coffeescript_spaces_around_unary_operator = false
+ij_coffeescript_spaces_within_array_initializer_braces = false
+ij_coffeescript_spaces_within_array_initializer_brackets = false
+ij_coffeescript_spaces_within_imports = false
+ij_coffeescript_spaces_within_index_brackets = false
+ij_coffeescript_spaces_within_interpolation_expressions = false
+ij_coffeescript_spaces_within_method_call_parentheses = false
+ij_coffeescript_spaces_within_method_parentheses = false
+ij_coffeescript_spaces_within_object_braces = false
+ij_coffeescript_spaces_within_object_literal_braces = false
+ij_coffeescript_spaces_within_object_type_braces = true
+ij_coffeescript_spaces_within_range_brackets = false
+ij_coffeescript_spaces_within_type_assertion = false
+ij_coffeescript_spaces_within_union_types = true
+ij_coffeescript_union_types_wrap = on_every_item
+ij_coffeescript_use_chained_calls_group_indents = false
+ij_coffeescript_use_double_quotes = true
+ij_coffeescript_use_explicit_js_extension = auto
+ij_coffeescript_use_path_mapping = always
+ij_coffeescript_use_public_modifier = false
+ij_coffeescript_use_semicolon_after_statement = false
+ij_coffeescript_var_declaration_wrap = normal
+
+[{*.ctp,*.hphp,*.inc,*.module,*.page,*.php,*.php4,*.php5,*.phtml}]
+ij_continuation_indent_size = 4
+ij_php_align_assignments = false
+ij_php_align_class_constants = false
+ij_php_align_group_field_declarations = false
+ij_php_align_inline_comments = false
+ij_php_align_key_value_pairs = true
+ij_php_align_match_arm_bodies = false
+ij_php_align_multiline_array_initializer_expression = true
+ij_php_align_multiline_binary_operation = false
+ij_php_align_multiline_chained_methods = true
+ij_php_align_multiline_extends_list = false
+ij_php_align_multiline_for = true
+ij_php_align_multiline_parameters = true
+ij_php_align_multiline_parameters_in_calls = false
+ij_php_align_multiline_ternary_operation = true
+ij_php_align_named_arguments = false
+ij_php_align_phpdoc_comments = false
+ij_php_align_phpdoc_param_names = false
+ij_php_anonymous_brace_style = end_of_line
+ij_php_api_weight = 28
+ij_php_array_initializer_new_line_after_left_brace = true
+ij_php_array_initializer_right_brace_on_new_line = true
+ij_php_array_initializer_wrap = off
+ij_php_assignment_wrap = off
+ij_php_attributes_wrap = split_into_lines
+ij_php_author_weight = 28
+ij_php_binary_operation_sign_on_next_line = false
+ij_php_binary_operation_wrap = off
+ij_php_blank_lines_after_class_header = 0
+ij_php_blank_lines_after_function = 1
+ij_php_blank_lines_after_imports = 1
+ij_php_blank_lines_after_opening_tag = 0
+ij_php_blank_lines_after_package = 0
+ij_php_blank_lines_around_class = 1
+ij_php_blank_lines_around_constants = 0
+ij_php_blank_lines_around_field = 0
+ij_php_blank_lines_around_method = 1
+ij_php_blank_lines_before_class_end = 0
+ij_php_blank_lines_before_imports = 1
+ij_php_blank_lines_before_method_body = 0
+ij_php_blank_lines_before_package = 1
+ij_php_blank_lines_before_return_statement = 0
+ij_php_blank_lines_between_imports = 0
+ij_php_block_brace_style = end_of_line
+ij_php_call_parameters_new_line_after_left_paren = false
+ij_php_call_parameters_right_paren_on_new_line = false
+ij_php_call_parameters_wrap = off
+ij_php_catch_on_new_line = false
+ij_php_category_weight = 28
+ij_php_class_brace_style = next_line
+ij_php_comma_after_last_array_element = false
+ij_php_concat_spaces = true
+ij_php_copyright_weight = 28
+ij_php_deprecated_weight = 28
+ij_php_do_while_brace_force = never
+ij_php_else_if_style = as_is
+ij_php_else_on_new_line = false
+ij_php_example_weight = 28
+ij_php_extends_keyword_wrap = off
+ij_php_extends_list_wrap = off
+ij_php_fields_default_visibility = private
+ij_php_filesource_weight = 28
+ij_php_finally_on_new_line = false
+ij_php_for_brace_force = never
+ij_php_for_statement_new_line_after_left_paren = false
+ij_php_for_statement_right_paren_on_new_line = false
+ij_php_for_statement_wrap = off
+ij_php_force_empty_methods_in_one_line = false
+ij_php_force_short_declaration_array_style = false
+ij_php_getters_setters_naming_style = camel_case
+ij_php_getters_setters_order_style = getters_first
+ij_php_global_weight = 28
+ij_php_group_use_wrap = off
+ij_php_if_brace_force = never
+ij_php_if_lparen_on_next_line = false
+ij_php_if_rparen_on_next_line = false
+ij_php_ignore_weight = 28
+ij_php_import_sorting = alphabetic
+ij_php_indent_break_from_case = true
+ij_php_indent_case_from_switch = true
+ij_php_indent_code_in_php_tags = false
+ij_php_internal_weight = 28
+ij_php_keep_blank_lines_after_lbrace = 2
+ij_php_keep_blank_lines_before_right_brace = 2
+ij_php_keep_blank_lines_in_code = 2
+ij_php_keep_blank_lines_in_declarations = 2
+ij_php_keep_control_statement_in_one_line = true
+ij_php_keep_first_column_comment = true
+ij_php_keep_indents_on_empty_lines = false
+ij_php_keep_line_breaks = true
+ij_php_keep_rparen_and_lbrace_on_one_line = false
+ij_php_keep_simple_classes_in_one_line = false
+ij_php_keep_simple_methods_in_one_line = false
+ij_php_lambda_brace_style = end_of_line
+ij_php_license_weight = 28
+ij_php_line_comment_add_space = false
+ij_php_line_comment_at_first_column = true
+ij_php_link_weight = 28
+ij_php_lower_case_boolean_const = false
+ij_php_lower_case_keywords = true
+ij_php_lower_case_null_const = false
+ij_php_method_brace_style = next_line
+ij_php_method_call_chain_wrap = off
+ij_php_method_parameters_new_line_after_left_paren = false
+ij_php_method_parameters_right_paren_on_new_line = false
+ij_php_method_parameters_wrap = off
+ij_php_method_weight = 28
+ij_php_modifier_list_wrap = false
+ij_php_multiline_chained_calls_semicolon_on_new_line = true
+ij_php_namespace_brace_style = 1
+ij_php_new_line_after_php_opening_tag = false
+ij_php_null_type_position = in_the_end
+ij_php_package_weight = 28
+ij_php_param_weight = 0
+ij_php_parameters_attributes_wrap = off
+ij_php_parentheses_expression_new_line_after_left_paren = false
+ij_php_parentheses_expression_right_paren_on_new_line = false
+ij_php_phpdoc_blank_line_before_tags = false
+ij_php_phpdoc_blank_lines_around_parameters = false
+ij_php_phpdoc_keep_blank_lines = true
+ij_php_phpdoc_param_spaces_between_name_and_description = 1
+ij_php_phpdoc_param_spaces_between_tag_and_type = 1
+ij_php_phpdoc_param_spaces_between_type_and_name = 1
+ij_php_phpdoc_use_fqcn = false
+ij_php_phpdoc_wrap_long_lines = false
+ij_php_place_assignment_sign_on_next_line = false
+ij_php_place_parens_for_constructor = 0
+ij_php_property_read_weight = 28
+ij_php_property_weight = 28
+ij_php_property_write_weight = 28
+ij_php_return_type_on_new_line = false
+ij_php_return_weight = 1
+ij_php_see_weight = 28
+ij_php_since_weight = 28
+ij_php_sort_phpdoc_elements = true
+ij_php_space_after_colon = true
+ij_php_space_after_colon_in_enum_backed_type = true
+ij_php_space_after_colon_in_named_argument = true
+ij_php_space_after_colon_in_return_type = true
+ij_php_space_after_comma = true
+ij_php_space_after_for_semicolon = true
+ij_php_space_after_quest = true
+ij_php_space_after_type_cast = false
+ij_php_space_after_unary_not = false
+ij_php_space_before_array_initializer_left_brace = false
+ij_php_space_before_catch_keyword = true
+ij_php_space_before_catch_left_brace = true
+ij_php_space_before_catch_parentheses = true
+ij_php_space_before_class_left_brace = true
+ij_php_space_before_closure_left_parenthesis = true
+ij_php_space_before_colon = true
+ij_php_space_before_colon_in_enum_backed_type = false
+ij_php_space_before_colon_in_named_argument = false
+ij_php_space_before_colon_in_return_type = false
+ij_php_space_before_comma = false
+ij_php_space_before_do_left_brace = true
+ij_php_space_before_else_keyword = true
+ij_php_space_before_else_left_brace = true
+ij_php_space_before_finally_keyword = true
+ij_php_space_before_finally_left_brace = true
+ij_php_space_before_for_left_brace = true
+ij_php_space_before_for_parentheses = true
+ij_php_space_before_for_semicolon = false
+ij_php_space_before_if_left_brace = true
+ij_php_space_before_if_parentheses = true
+ij_php_space_before_method_call_parentheses = false
+ij_php_space_before_method_left_brace = true
+ij_php_space_before_method_parentheses = false
+ij_php_space_before_quest = true
+ij_php_space_before_short_closure_left_parenthesis = false
+ij_php_space_before_switch_left_brace = true
+ij_php_space_before_switch_parentheses = true
+ij_php_space_before_try_left_brace = true
+ij_php_space_before_unary_not = false
+ij_php_space_before_while_keyword = true
+ij_php_space_before_while_left_brace = true
+ij_php_space_before_while_parentheses = true
+ij_php_space_between_ternary_quest_and_colon = false
+ij_php_spaces_around_additive_operators = true
+ij_php_spaces_around_arrow = false
+ij_php_spaces_around_assignment_in_declare = false
+ij_php_spaces_around_assignment_operators = true
+ij_php_spaces_around_bitwise_operators = true
+ij_php_spaces_around_equality_operators = true
+ij_php_spaces_around_logical_operators = true
+ij_php_spaces_around_multiplicative_operators = true
+ij_php_spaces_around_null_coalesce_operator = true
+ij_php_spaces_around_pipe_in_union_type = false
+ij_php_spaces_around_relational_operators = true
+ij_php_spaces_around_shift_operators = true
+ij_php_spaces_around_unary_operator = false
+ij_php_spaces_around_var_within_brackets = false
+ij_php_spaces_within_array_initializer_braces = false
+ij_php_spaces_within_brackets = false
+ij_php_spaces_within_catch_parentheses = false
+ij_php_spaces_within_for_parentheses = false
+ij_php_spaces_within_if_parentheses = false
+ij_php_spaces_within_method_call_parentheses = false
+ij_php_spaces_within_method_parentheses = false
+ij_php_spaces_within_parentheses = false
+ij_php_spaces_within_short_echo_tags = true
+ij_php_spaces_within_switch_parentheses = false
+ij_php_spaces_within_while_parentheses = false
+ij_php_special_else_if_treatment = false
+ij_php_subpackage_weight = 28
+ij_php_ternary_operation_signs_on_next_line = true
+ij_php_ternary_operation_wrap = off
+ij_php_throws_weight = 2
+ij_php_todo_weight = 28
+ij_php_treat_multiline_arrays_and_lambdas_multiline = false
+ij_php_unknown_tag_weight = 28
+ij_php_upper_case_boolean_const = false
+ij_php_upper_case_null_const = false
+ij_php_uses_weight = 28
+ij_php_var_weight = 28
+ij_php_variable_naming_style = mixed
+ij_php_version_weight = 28
+ij_php_while_brace_force = never
+ij_php_while_on_new_line = false
+
+[{*.har,*.jsb2,*.jsb3,*.json,.babelrc,.eslintrc,.stylelintrc,bowerrc,composer.lock,jest.config}]
+indent_size = 4
+ij_json_keep_blank_lines_in_code = 0
+ij_json_keep_indents_on_empty_lines = false
+ij_json_keep_line_breaks = true
+ij_json_space_after_colon = true
+ij_json_space_after_comma = true
+ij_json_space_before_colon = true
+ij_json_space_before_comma = false
+ij_json_spaces_within_braces = false
+ij_json_spaces_within_brackets = false
+ij_json_wrap_long_lines = false
+
+[{*.htm,*.html,*.ng,*.sht,*.shtm,*.shtml}]
+ij_html_add_new_line_before_tags = body,div,p,form,h1,h2,h3
+ij_html_align_attributes = true
+ij_html_align_text = false
+ij_html_attribute_wrap = off
+ij_html_block_comment_add_space = false
+ij_html_block_comment_at_first_column = true
+ij_html_do_not_align_children_of_min_lines = 0
+ij_html_do_not_break_if_inline_tags = title,h1,h2,h3,h4,h5,h6,p
+ij_html_do_not_indent_children_of_tags = html,body,thead,tbody,tfoot
+ij_html_enforce_quotes = false
+ij_html_inline_tags = a,abbr,acronym,b,basefont,bdo,big,br,cite,cite,code,dfn,em,font,i,img,input,kbd,label,q,s,samp,select,small,span,strike,strong,sub,sup,textarea,tt,u,var
+ij_html_keep_blank_lines = 2
+ij_html_keep_indents_on_empty_lines = false
+ij_html_keep_line_breaks = true
+ij_html_keep_line_breaks_in_text = true
+ij_html_keep_whitespaces = false
+ij_html_keep_whitespaces_inside = span,pre,textarea
+ij_html_line_comment_at_first_column = true
+ij_html_new_line_after_last_attribute = never
+ij_html_new_line_before_first_attribute = never
+ij_html_quote_style = double
+ij_html_remove_new_line_before_tags = br
+ij_html_space_after_tag_name = false
+ij_html_space_around_equality_in_attribute = false
+ij_html_space_inside_empty_tag = false
+ij_html_text_wrap = normal
+
+[{*.markdown,*.md}]
+ij_markdown_force_one_space_after_blockquote_symbol = true
+ij_markdown_force_one_space_after_header_symbol = true
+ij_markdown_force_one_space_after_list_bullet = true
+ij_markdown_force_one_space_between_words = true
+ij_markdown_insert_quote_arrows_on_wrap = true
+ij_markdown_keep_indents_on_empty_lines = false
+ij_markdown_keep_line_breaks_inside_text_blocks = true
+ij_markdown_max_lines_around_block_elements = 1
+ij_markdown_max_lines_around_header = 1
+ij_markdown_max_lines_between_paragraphs = 1
+ij_markdown_min_lines_around_block_elements = 1
+ij_markdown_min_lines_around_header = 1
+ij_markdown_min_lines_between_paragraphs = 1
+ij_markdown_wrap_text_if_long = true
+ij_markdown_wrap_text_inside_blockquotes = true
+
+[{*.yaml,*.yml}]
+indent_size = 4
+ij_yaml_align_values_properties = do_not_align
+ij_yaml_autoinsert_sequence_marker = true
+ij_yaml_block_mapping_on_new_line = false
+ij_yaml_indent_sequence_value = true
+ij_yaml_keep_indents_on_empty_lines = false
+ij_yaml_keep_line_breaks = true
+ij_yaml_sequence_on_new_line = false
+ij_yaml_space_before_colon = false
+ij_yaml_spaces_within_braces = true
+ij_yaml_spaces_within_brackets = true
diff --git a/.idea/codeception.xml b/.idea/codeception.xml
deleted file mode 100644
index 330f2dd..0000000
--- a/.idea/codeception.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/phpunit.xml b/.idea/phpunit.xml
deleted file mode 100644
index 4f8104c..0000000
--- a/.idea/phpunit.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/README.md b/README.md
index c9b1852..4917030 100644
--- a/README.md
+++ b/README.md
@@ -119,6 +119,20 @@ class MyController
}
```
+## Sessions
+
+Currently, Symfony might struggle with sessions in worker mode, like loosing logged user or the opposite,
+leaking logged user session to another request due to missing globals (explained at the end).
+
+Bundle introduces `FluffyDiscord\RoadRunnerBundle\Session\WorkerSessionStorageFactory`, that handles native session correctly.
+This factory gets registered automatically by default if you are using `symfony/flex` (pending flex recipe PR). You can also register it manually, for example in `framework.yaml`:
+
+```yaml
+framework:
+ session:
+ storage_factory_id: FluffyDiscord\RoadRunnerBundle\Session\WorkerSessionStorageFactory
+```
+
## Sentry
Built in support for [Sentry](https://packagist.org/packages/sentry/sentry-symfony). Just install & configure it as you normally do.
diff --git a/config/services.php b/config/services.php
index 177308a..636d608 100644
--- a/config/services.php
+++ b/config/services.php
@@ -3,6 +3,7 @@
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
use FluffyDiscord\RoadRunnerBundle\Factory\RPCFactory;
+use FluffyDiscord\RoadRunnerBundle\Session\WorkerSessionStorageFactory;
use FluffyDiscord\RoadRunnerBundle\Worker\CentrifugoWorker;
use FluffyDiscord\RoadRunnerBundle\Worker\HttpWorker as BundleHttpWorker;
use FluffyDiscord\RoadRunnerBundle\Worker\WorkerRegistry;
@@ -20,6 +21,8 @@
use Spiral\RoadRunner\WorkerInterface as RoadRunnerWorkerInterface;
use Symfony\Bridge\PsrHttpMessage\HttpFoundationFactoryInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+use Symfony\Component\HttpFoundation\RequestStack;
+use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag;
use Symfony\Component\HttpKernel\KernelInterface;
return static function (ContainerConfigurator $container) {
@@ -80,6 +83,22 @@
])
;
+ // Worker sessions fix
+ $services
+ ->set(WorkerSessionStorageFactory::class)
+ ->args([
+ param('session.storage.options'),
+ service('session.handler'),
+ inline_service(MetadataBag::class)
+ ->args([
+ param('session.metadata.storage_key'),
+ param('session.metadata.update_threshold'),
+ ]),
+ service(RequestStack::class),
+ false,
+ ])
+ ;
+
// Centrifugo
if (class_exists(RoadRunnerCentrifugoWorker::class)) {
$services
diff --git a/install/.rr.yaml b/install/.rr.yaml
new file mode 100644
index 0000000..f23830f
--- /dev/null
+++ b/install/.rr.yaml
@@ -0,0 +1,36 @@
+######################################################################################
+# THIS IS SAMPLE OF THE CONFIGURATION #
+# IT'S NOT A DEFAULT CONFIGURATION, IT'S JUST A REFERENCE TO ALL OPTIONS AND PLUGINS #
+# MORE DOCS CAN BE FOUND HERE: #
+######################################################################################
+
+# More info: https://docs.roadrunner.dev/docs/general/config
+
+version: "3"
+
+server:
+ command: "php public/index.php"
+ env:
+ - APP_RUNTIME: FluffyDiscord\RoadRunnerBundle\Runtime\Runtime
+http:
+ address: 0.0.0.0:8080
+ pool:
+ debug: true # development only! https://docs.roadrunner.dev/docs/php-worker/pool#workers-pool-configuration
+ middleware: [ "gzip", "static" ]
+ static:
+ dir: "public"
+ forbid: [ ".php", ".htaccess" ]
+
+logs:
+ mode: development
+ channels:
+ http:
+ level: debug
+ server:
+ level: info
+ mode: raw
+ metrics:
+ level: debug
+
+rpc:
+ listen: tcp://127.0.0.1:6001
diff --git a/src/Session/WorkerSessionStorage.php b/src/Session/WorkerSessionStorage.php
new file mode 100644
index 0000000..0533200
--- /dev/null
+++ b/src/Session/WorkerSessionStorage.php
@@ -0,0 +1,91 @@
+started) {
+ return true;
+ }
+
+ if (\PHP_SESSION_ACTIVE === session_status()) {
+ throw new \RuntimeException('Failed to start the session: already started by PHP.');
+ }
+
+ if (filter_var(\ini_get('session.use_cookies'), \FILTER_VALIDATE_BOOL) && headers_sent($file, $line)) {
+ throw new \RuntimeException(sprintf('Failed to start the session because headers have already been sent by "%s" at line %d.', $file, $line));
+ }
+
+ /*
+ * Explanation of the session ID regular expression: `/^[a-zA-Z0-9,-]{22,250}$/`.
+ *
+ * ---------- Part 1
+ *
+ * The part `[a-zA-Z0-9,-]` is related to the PHP ini directive `session.sid_bits_per_character` defined as 6.
+ * See https://www.php.net/manual/en/session.configuration.php#ini.session.sid-bits-per-character.
+ * Allowed values are integers such as:
+ * - 4 for range `a-f0-9`
+ * - 5 for range `a-v0-9`
+ * - 6 for range `a-zA-Z0-9,-`
+ *
+ * ---------- Part 2
+ *
+ * The part `{22,250}` is related to the PHP ini directive `session.sid_length`.
+ * See https://www.php.net/manual/en/session.configuration.php#ini.session.sid-length.
+ * Allowed values are integers between 22 and 256, but we use 250 for the max.
+ *
+ * Where does the 250 come from?
+ * - The length of Windows and Linux filenames is limited to 255 bytes. Then the max must not exceed 255.
+ * - The session filename prefix is `sess_`, a 5 bytes string. Then the max must not exceed 255 - 5 = 250.
+ *
+ * ---------- Conclusion
+ *
+ * The parts 1 and 2 prevent the warning below:
+ * `PHP Warning: SessionHandler::read(): Session ID is too long or contains illegal characters. Only the A-Z, a-z, 0-9, "-", and "," characters are allowed.`
+ *
+ * The part 2 prevents the warning below:
+ * `PHP Warning: SessionHandler::read(): open(filepath, O_RDWR) failed: No such file or directory (2).`
+ */
+ $sessionId = $this->requestStack->getCurrentRequest()?->cookies->get(session_name());
+ if ($sessionId) {
+ if (!preg_match('/^[a-zA-Z0-9,-]{22,250}$/', $sessionId)) {
+ $sessionId = session_create_id();
+ }
+ }
+
+ session_id($sessionId);
+
+ // ok to try and start the session
+ if (!session_start()) {
+ throw new \RuntimeException('Failed to start the session.');
+ }
+
+ $this->loadSession();
+
+ return true;
+
+ }
+
+ public function reset(): void
+ {
+ $this->started = false;
+ $this->saveHandler->close();
+ }
+}
\ No newline at end of file
diff --git a/src/Session/WorkerSessionStorageFactory.php b/src/Session/WorkerSessionStorageFactory.php
new file mode 100644
index 0000000..2222de3
--- /dev/null
+++ b/src/Session/WorkerSessionStorageFactory.php
@@ -0,0 +1,51 @@
+workerSessionStorage === null) {
+ $this->workerSessionStorage = new WorkerSessionStorage($this->options, $this->handler, $this->metaBag, $this->requestStack);
+ }
+
+ if ($this->secure && $request?->isSecure()) {
+ $this->workerSessionStorage->setOptions(['cookie_secure' => true]);
+ }
+
+ return $this->workerSessionStorage;
+ }
+
+ public function reset(): void
+ {
+ $this->workerSessionStorage?->reset();
+ }
+}
diff --git a/src/Worker/HttpWorker.php b/src/Worker/HttpWorker.php
index 7d39e05..734034c 100644
--- a/src/Worker/HttpWorker.php
+++ b/src/Worker/HttpWorker.php
@@ -80,8 +80,9 @@ public function start(): void
$this->sentryHubInterface?->popScope();
}
}
- } catch (\Throwable) {
+ } catch (\Throwable $throwable) {
$worker->getWorker()->stop();
+ throw $throwable;
}
}
}