test-test-ignore-123123 0.0.1.pre.alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +128 -0
- data/lib/sink/base_client.rb +383 -0
- data/lib/sink/base_model.rb +203 -0
- data/lib/sink/client.rb +381 -0
- data/lib/sink/fake_page.rb +39 -0
- data/lib/sink/models/allof_base_parent.rb +11 -0
- data/lib/sink/models/allof_multiple_inline_entries.rb +15 -0
- data/lib/sink/models/api_status.rb +11 -0
- data/lib/sink/models/array_float_items_response.rb +6 -0
- data/lib/sink/models/array_missing_items_response.rb +11 -0
- data/lib/sink/models/array_object_items.rb +11 -0
- data/lib/sink/models/array_object_items_response.rb +11 -0
- data/lib/sink/models/array_recursion.rb +6 -0
- data/lib/sink/models/balance.rb +11 -0
- data/lib/sink/models/basic_shared_model_object.rb +15 -0
- data/lib/sink/models/body_param_top_level_all_of_response.rb +20 -0
- data/lib/sink/models/body_param_union_overlapping_prop_response.rb +11 -0
- data/lib/sink/models/card.rb +144 -0
- data/lib/sink/models/card_list_response.rb +26 -0
- data/lib/sink/models/card_provision_foo_response.rb +11 -0
- data/lib/sink/models/child_inlined_response_response.rb +11 -0
- data/lib/sink/models/child_model.rb +21 -0
- data/lib/sink/models/class_.rb +11 -0
- data/lib/sink/models/client.rb +15 -0
- data/lib/sink/models/company.rb +11 -0
- data/lib/sink/models/company_payment.rb +11 -0
- data/lib/sink/models/complex_query_array_query_response.rb +22 -0
- data/lib/sink/models/config_tool_model_ref_from_nested_response_body_response.rb +17 -0
- data/lib/sink/models/currency.rb +23 -0
- data/lib/sink/models/decorator_test_keep_me_response.rb +11 -0
- data/lib/sink/models/docstring_leading_double_quote_response.rb +12 -0
- data/lib/sink/models/docstring_trailing_double_quote_response.rb +22 -0
- data/lib/sink/models/documents.rb +15 -0
- data/lib/sink/models/eeoc.rb +11 -0
- data/lib/sink/models/employment_data.rb +11 -0
- data/lib/sink/models/enum_basic_response.rb +51 -0
- data/lib/sink/models/export.rb +12 -0
- data/lib/sink/models/funding_account.rb +73 -0
- data/lib/sink/models/import.rb +11 -0
- data/lib/sink/models/interface.rb +11 -0
- data/lib/sink/models/keep_this_resource_keep_this_method_response.rb +11 -0
- data/lib/sink/models/make_ambiguous_schemas_explicit_make_ambiguous_schemas_explicit_response.rb +31 -0
- data/lib/sink/models/make_ambiguous_schemas_looser_make_ambiguous_schemas_looser_response.rb +31 -0
- data/lib/sink/models/map_nullable_items_response.rb +19 -0
- data/lib/sink/models/method_config_skipped_tests_all_response.rb +11 -0
- data/lib/sink/models/method_config_skipped_tests_go_response.rb +11 -0
- data/lib/sink/models/method_config_skipped_tests_java_response.rb +11 -0
- data/lib/sink/models/method_config_skipped_tests_kotlin_response.rb +11 -0
- data/lib/sink/models/method_config_skipped_tests_node_and_python_response.rb +11 -0
- data/lib/sink/models/method_config_skipped_tests_node_response.rb +11 -0
- data/lib/sink/models/method_config_skipped_tests_python_response.rb +11 -0
- data/lib/sink/models/method_config_skipped_tests_ruby_response.rb +11 -0
- data/lib/sink/models/model_from_nested_path.rb +30 -0
- data/lib/sink/models/model_from_nested_response_body_ref.rb +11 -0
- data/lib/sink/models/model_from_schemas_ref.rb +11 -0
- data/lib/sink/models/model_from_schemas_ref_openapi_uri.rb +11 -0
- data/lib/sink/models/model_from_schemas_ref_openapi_uri_jmespath.rb +11 -0
- data/lib/sink/models/model_from_schemas_ref_openapi_uri_jsonpath.rb +11 -0
- data/lib/sink/models/model_level_1.rb +15 -0
- data/lib/sink/models/model_level_2.rb +15 -0
- data/lib/sink/models/model_level_3.rb +15 -0
- data/lib/sink/models/model_referenced_in_parent_and_child.rb +11 -0
- data/lib/sink/models/model_with_nested_model.rb +16 -0
- data/lib/sink/models/my_model.rb +11 -0
- data/lib/sink/models/name_child_prop_import_clash_response.rb +21 -0
- data/lib/sink/models/name_properties_common_conflicts_response.rb +59 -0
- data/lib/sink/models/name_properties_illegal_javascript_identifiers_response.rb +6 -0
- data/lib/sink/models/name_response_property_clashes_model_import_response.rb +15 -0
- data/lib/sink/models/name_response_shadows_pydantic_response.rb +15 -0
- data/lib/sink/models/nested_request_model_a.rb +11 -0
- data/lib/sink/models/nested_request_model_b.rb +11 -0
- data/lib/sink/models/nested_request_model_c.rb +17 -0
- data/lib/sink/models/object_missing_items_response.rb +11 -0
- data/lib/sink/models/object_mixed_known_and_unknown_response.rb +11 -0
- data/lib/sink/models/object_multiple_array_properties_same_ref_response.rb +42 -0
- data/lib/sink/models/object_multiple_properties_same_model_response.rb +19 -0
- data/lib/sink/models/object_multiple_properties_same_ref_response.rb +37 -0
- data/lib/sink/models/object_skipped_props.rb +27 -0
- data/lib/sink/models/object_two_dimensional_array_primitive_property_response.rb +23 -0
- data/lib/sink/models/object_with_any_of_null_property.rb +17 -0
- data/lib/sink/models/object_with_child_ref.rb +15 -0
- data/lib/sink/models/object_with_one_of_null_property.rb +17 -0
- data/lib/sink/models/object_with_union_properties.rb +15 -0
- data/lib/sink/models/openapi_format_array_type_one_entry_response.rb +11 -0
- data/lib/sink/models/openapi_format_array_type_one_entry_with_null_response.rb +11 -0
- data/lib/sink/models/openapi_special_used_used_as_property_name_response.rb +11 -0
- data/lib/sink/models/page_cursor_shared_ref_pagination.rb +15 -0
- data/lib/sink/models/parent_model_with_child_ref.rb +19 -0
- data/lib/sink/models/path_param_colon_suffix_response.rb +11 -0
- data/lib/sink/models/path_param_file_extension_response.rb +11 -0
- data/lib/sink/models/path_param_multiple_response.rb +11 -0
- data/lib/sink/models/path_param_query_param_response.rb +11 -0
- data/lib/sink/models/path_param_singular_response.rb +11 -0
- data/lib/sink/models/primitive_strings_response.rb +11 -0
- data/lib/sink/models/private.rb +11 -0
- data/lib/sink/models/public.rb +11 -0
- data/lib/sink/models/recursion_create_envelope_response.rb +11 -0
- data/lib/sink/models/response_allof_simple_response.rb +15 -0
- data/lib/sink/models/response_array_object_with_union_properties_response.rb +6 -0
- data/lib/sink/models/response_array_response_response.rb +6 -0
- data/lib/sink/models/response_missing_required_response.rb +15 -0
- data/lib/sink/models/response_nested_array_response.rb +21 -0
- data/lib/sink/models/response_object_all_properties_response.rb +49 -0
- data/lib/sink/models/response_object_no_properties_response.rb +8 -0
- data/lib/sink/models/response_object_with_additional_properties_prop_response.rb +17 -0
- data/lib/sink/models/response_object_with_heavily_nested_union_response.rb +11 -0
- data/lib/sink/models/response_only_read_only_properties_response.rb +16 -0
- data/lib/sink/models/responses_allof_cross_object.rb +15 -0
- data/lib/sink/models/return_.rb +11 -0
- data/lib/sink/models/root_response.rb +19 -0
- data/lib/sink/models/self_recursion.rb +15 -0
- data/lib/sink/models/shared_cursor_nested_response_prop_meta.rb +18 -0
- data/lib/sink/models/shared_self_recursion.rb +15 -0
- data/lib/sink/models/shipping_address.rb +62 -0
- data/lib/sink/models/simple_allof.rb +20 -0
- data/lib/sink/models/simple_object.rb +19 -0
- data/lib/sink/models/skip_this_resource_i_never_appear_response.rb +11 -0
- data/lib/sink/models/streaming_basic_response.rb +15 -0
- data/lib/sink/models/streaming_nested_params_response.rb +15 -0
- data/lib/sink/models/streaming_no_discriminator_response.rb +15 -0
- data/lib/sink/models/streaming_query_param_discriminator_response.rb +15 -0
- data/lib/sink/models/streaming_with_unrelated_default_param_response.rb +15 -0
- data/lib/sink/models/type_dates_response.rb +27 -0
- data/lib/sink/models/type_datetimes_response.rb +27 -0
- data/lib/sink/models/union_discriminated_variant_a.rb +19 -0
- data/lib/sink/models/union_discriminated_variant_b.rb +19 -0
- data/lib/sink/models/union_response_discriminated_by_property_name_response.rb +6 -0
- data/lib/sink/models/union_response_discriminated_with_basic_mapping_response.rb +6 -0
- data/lib/sink/models/union_type_mixed_types_response.rb +6 -0
- data/lib/sink/models/union_type_nullable_union_response.rb +6 -0
- data/lib/sink/models/union_type_objects_response.rb +6 -0
- data/lib/sink/models/union_type_super_mixed_types_response.rb +6 -0
- data/lib/sink/models/union_type_unknown_variant_response.rb +6 -0
- data/lib/sink/models/version_1_30_name_create_response.rb +11 -0
- data/lib/sink/models/widget.rb +12 -0
- data/lib/sink/models/write_only_response_simple_response.rb +12 -0
- data/lib/sink/page_cursor.rb +49 -0
- data/lib/sink/page_cursor_from_headers.rb +49 -0
- data/lib/sink/page_cursor_id.rb +45 -0
- data/lib/sink/page_cursor_nested_items.rb +65 -0
- data/lib/sink/page_cursor_nested_object_ref.rb +59 -0
- data/lib/sink/page_cursor_shared_ref.rb +59 -0
- data/lib/sink/page_cursor_top_level_array.rb +46 -0
- data/lib/sink/page_cursor_url.rb +46 -0
- data/lib/sink/page_offset.rb +49 -0
- data/lib/sink/page_offset_no_start_field.rb +45 -0
- data/lib/sink/page_offset_total_count.rb +53 -0
- data/lib/sink/page_page_number.rb +53 -0
- data/lib/sink/page_page_number_without_current_page_response.rb +45 -0
- data/lib/sink/pooled_net_requester.rb +63 -0
- data/lib/sink/request_options.rb +84 -0
- data/lib/sink/resources/body_params/objects.rb +31 -0
- data/lib/sink/resources/body_params/unions.rb +31 -0
- data/lib/sink/resources/body_params.rb +475 -0
- data/lib/sink/resources/cards.rb +488 -0
- data/lib/sink/resources/casing/eeoc.rb +32 -0
- data/lib/sink/resources/casing.rb +15 -0
- data/lib/sink/resources/clients.rb +27 -0
- data/lib/sink/resources/company/payments.rb +28 -0
- data/lib/sink/resources/company.rb +17 -0
- data/lib/sink/resources/complex_queries.rb +56 -0
- data/lib/sink/resources/config_tools/parent_with_skip_node_python/child_only_skip_python.rb +96 -0
- data/lib/sink/resources/config_tools/parent_with_skip_node_python.rb +98 -0
- data/lib/sink/resources/config_tools.rb +37 -0
- data/lib/sink/resources/decorator_tests/keep_this_resource.rb +27 -0
- data/lib/sink/resources/decorator_tests/languages.rb +55 -0
- data/lib/sink/resources/decorator_tests/skip_this_resource.rb +26 -0
- data/lib/sink/resources/decorator_tests.rb +36 -0
- data/lib/sink/resources/deeply_nested/level_one/level_two/level_three.rb +31 -0
- data/lib/sink/resources/deeply_nested/level_one/level_two.rb +33 -0
- data/lib/sink/resources/deeply_nested/level_one.rb +31 -0
- data/lib/sink/resources/deeply_nested.rb +15 -0
- data/lib/sink/resources/docstrings.rb +77 -0
- data/lib/sink/resources/empty_body.rb +55 -0
- data/lib/sink/resources/header_params.rb +33 -0
- data/lib/sink/resources/invalid_schemas/arrays.rb +24 -0
- data/lib/sink/resources/invalid_schemas/objects.rb +24 -0
- data/lib/sink/resources/invalid_schemas.rb +19 -0
- data/lib/sink/resources/make_ambiguous_schemas_explicit.rb +24 -0
- data/lib/sink/resources/make_ambiguous_schemas_looser.rb +24 -0
- data/lib/sink/resources/method_config.rb +156 -0
- data/lib/sink/resources/mixed_params/duplicates.rb +73 -0
- data/lib/sink/resources/mixed_params.rb +81 -0
- data/lib/sink/resources/model_referenced_in_parent_and_child/child.rb +24 -0
- data/lib/sink/resources/model_referenced_in_parent_and_child.rb +26 -0
- data/lib/sink/resources/names/can_cause_clashes/employment_data.rb +15 -0
- data/lib/sink/resources/names/can_cause_clashes/response.rb +30 -0
- data/lib/sink/resources/names/can_cause_clashes.rb +22 -0
- data/lib/sink/resources/names/documents.rb +26 -0
- data/lib/sink/resources/names/openapi_specials.rb +24 -0
- data/lib/sink/resources/names/params.rb +47 -0
- data/lib/sink/resources/names/reserved_names/import.rb +29 -0
- data/lib/sink/resources/names/reserved_names/methods.rb +37 -0
- data/lib/sink/resources/names/reserved_names/public/class_.rb +28 -0
- data/lib/sink/resources/names/reserved_names/public/interface.rb +28 -0
- data/lib/sink/resources/names/reserved_names/public/private.rb +28 -0
- data/lib/sink/resources/names/reserved_names/public.rb +38 -0
- data/lib/sink/resources/names/reserved_names.rb +43 -0
- data/lib/sink/resources/names.rb +139 -0
- data/lib/sink/resources/openapi_formats.rb +48 -0
- data/lib/sink/resources/pagination_tests/cursor.rb +32 -0
- data/lib/sink/resources/pagination_tests/items_types.rb +32 -0
- data/lib/sink/resources/pagination_tests/nested_items.rb +32 -0
- data/lib/sink/resources/pagination_tests/offset.rb +70 -0
- data/lib/sink/resources/pagination_tests/schema_types.rb +51 -0
- data/lib/sink/resources/pagination_tests.rb +31 -0
- data/lib/sink/resources/parent/child.rb +28 -0
- data/lib/sink/resources/parent.rb +17 -0
- data/lib/sink/resources/path_params.rb +196 -0
- data/lib/sink/resources/positional_params.rb +219 -0
- data/lib/sink/resources/query_params.rb +157 -0
- data/lib/sink/resources/recursion/shared_responses.rb +24 -0
- data/lib/sink/resources/recursion.rb +61 -0
- data/lib/sink/resources/resource_refs/paginated_model_first_ref.rb +13 -0
- data/lib/sink/resources/resource_refs/paginated_model_second_ref.rb +13 -0
- data/lib/sink/resources/resource_refs/parent/child.rb +29 -0
- data/lib/sink/resources/resource_refs/parent.rb +30 -0
- data/lib/sink/resources/resource_refs.rb +23 -0
- data/lib/sink/resources/resources.rb +24 -0
- data/lib/sink/resources/responses/union_types.rb +91 -0
- data/lib/sink/resources/responses.rb +297 -0
- data/lib/sink/resources/shared_query_params.rb +45 -0
- data/lib/sink/resources/streaming.rb +96 -0
- data/lib/sink/resources/testing.rb +22 -0
- data/lib/sink/resources/tests.rb +24 -0
- data/lib/sink/resources/tools.rb +30 -0
- data/lib/sink/resources/types/allofs.rb +13 -0
- data/lib/sink/resources/types/arrays.rb +57 -0
- data/lib/sink/resources/types/enums.rb +86 -0
- data/lib/sink/resources/types/maps.rb +27 -0
- data/lib/sink/resources/types/objects.rb +98 -0
- data/lib/sink/resources/types/primitives.rb +31 -0
- data/lib/sink/resources/types/read_only_params.rb +31 -0
- data/lib/sink/resources/types/unions.rb +115 -0
- data/lib/sink/resources/types/write_only_responses.rb +26 -0
- data/lib/sink/resources/types.rb +90 -0
- data/lib/sink/resources/undocumented_resource.rb +44 -0
- data/lib/sink/resources/version_1_30_names.rb +38 -0
- data/lib/sink/resources/widgets.rb +28 -0
- data/lib/sink/util.rb +78 -0
- data/lib/sink/version.rb +5 -0
- data/lib/sink.rb +253 -0
- metadata +301 -0
@@ -0,0 +1,203 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "date"
|
4
|
+
|
5
|
+
module Sink
|
6
|
+
# @!visibility private
|
7
|
+
module Converter
|
8
|
+
# Based on `value`, returns a value that conforms to `type`, to the extent possible:
|
9
|
+
# - If the given `value` conforms to `type` already, the given `value`.
|
10
|
+
# - If it's possible and safe to convert the given `value` to `type`, such a converted value.
|
11
|
+
# - Otherwise, the given `value` unaltered.
|
12
|
+
def self.convert(type, value)
|
13
|
+
# If `type.is_a?(Converter)`, `type` is an instance of a class that mixes
|
14
|
+
# in `Converter`, indicating that the type should define `#convert` on this
|
15
|
+
# instance. This is used for Enums and ArrayOfs, which are parameterized.
|
16
|
+
# If `type.include?(Converter)`, `type` is a class that mixes in `Converter`
|
17
|
+
# which we use to signal that the class should define `.convert`. This is
|
18
|
+
# used where the class itself fully specifies the type, like model classes.
|
19
|
+
# We don't monkey-patch Ruby-native types, so those need to be handled
|
20
|
+
# directly.
|
21
|
+
if type.is_a?(Converter) || type.include?(Converter)
|
22
|
+
type.convert(value)
|
23
|
+
elsif type == Date
|
24
|
+
Date.parse(value)
|
25
|
+
elsif type == DateTime
|
26
|
+
DateTime.parse(value)
|
27
|
+
elsif type == NilClass
|
28
|
+
nil
|
29
|
+
elsif type == Float
|
30
|
+
value.is_a?(Numeric) ? value.to_f : value
|
31
|
+
elsif [Object, Integer, String, Hash].include?(type)
|
32
|
+
value
|
33
|
+
else
|
34
|
+
raise StandardError, "Unexpected type #{type}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# When we don't know what to expect for the value.
|
40
|
+
# @!visibility private
|
41
|
+
class Unknown
|
42
|
+
include Converter
|
43
|
+
|
44
|
+
def self.convert(value)
|
45
|
+
value
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Ruby has no Boolean class; this is something for models to refer to.
|
50
|
+
# @!visibility private
|
51
|
+
class BooleanModel
|
52
|
+
include Converter
|
53
|
+
|
54
|
+
def self.convert(value)
|
55
|
+
value
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# A value from among a specified list of options. OpenAPI enum values map to
|
60
|
+
# Ruby values in the SDK as follows:
|
61
|
+
# boolean => true|false
|
62
|
+
# integer => Integer
|
63
|
+
# float => Float
|
64
|
+
# string => Symbol
|
65
|
+
# We can therefore convert string values to Symbols, but can't convert other
|
66
|
+
# values safely.
|
67
|
+
# @!visibility private
|
68
|
+
class Enum
|
69
|
+
include Converter
|
70
|
+
|
71
|
+
def self.convert(value)
|
72
|
+
if value.is_a?(String)
|
73
|
+
value.to_sym
|
74
|
+
else
|
75
|
+
value
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# @return [Array<Symbol>] All of the valid Symbol values for this enum.
|
80
|
+
def self.values
|
81
|
+
@values ||= constants.map { |c| const_get(c) }
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Array of items of a given type.
|
86
|
+
# @!visibility private
|
87
|
+
class ArrayOf
|
88
|
+
include Converter
|
89
|
+
|
90
|
+
def initialize(items_type_info = nil, enum: nil)
|
91
|
+
@items_type_fn = enum || (items_type_info.is_a?(Proc) ? items_type_info : -> { items_type_info })
|
92
|
+
end
|
93
|
+
|
94
|
+
def convert(value)
|
95
|
+
items_type = @items_type_fn.call
|
96
|
+
value.map { |item| Converter.convert(items_type, item) }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class BaseModel
|
101
|
+
include Converter
|
102
|
+
|
103
|
+
# @!visibility private
|
104
|
+
# Assumes superclass fields are totally defined before fields are accessed / defined on subclasses.
|
105
|
+
def self.fields
|
106
|
+
@fields ||= (superclass == BaseModel ? {} : superclass.fields.dup)
|
107
|
+
end
|
108
|
+
|
109
|
+
# @!visibility private
|
110
|
+
def self.add_field(name_sym, type_info, mode)
|
111
|
+
type_fn = type_info.is_a?(Proc) ? type_info : -> { type_info }
|
112
|
+
fields[name_sym] = {type_fn: type_fn, mode: mode}
|
113
|
+
|
114
|
+
define_method(name_sym) do
|
115
|
+
field_type = type_fn.call
|
116
|
+
Converter.convert(field_type, @data[name_sym])
|
117
|
+
rescue StandardError
|
118
|
+
name = self.class.name.split("::").last
|
119
|
+
raise ConversionError,
|
120
|
+
"Failed to parse #{name}.#{name_sym} as #{field_type.inspect}. To get the unparsed API response, use #{name}[:#{name_sym}]."
|
121
|
+
end
|
122
|
+
define_method("#{name_sym}=") { |val| @data[name_sym] = val }
|
123
|
+
end
|
124
|
+
|
125
|
+
# @!visibility private
|
126
|
+
# NB `required` is just a signal to the reader. We don't do runtime validation anyway.
|
127
|
+
def self.required(name_sym, type_info = nil, mode = :rw, enum: nil)
|
128
|
+
add_field(name_sym, enum || type_info, mode)
|
129
|
+
end
|
130
|
+
|
131
|
+
# @!visibility private
|
132
|
+
# NB `optional` is just a signal to the reader. We don't do runtime validation anyway.
|
133
|
+
def self.optional(name_sym, type_info = nil, mode = :rw, enum: nil)
|
134
|
+
add_field(name_sym, enum || type_info, mode)
|
135
|
+
end
|
136
|
+
|
137
|
+
# @!visibility private
|
138
|
+
def self.convert(data)
|
139
|
+
new(data)
|
140
|
+
end
|
141
|
+
|
142
|
+
# Create a new instance of a model.
|
143
|
+
# @param data [Hash] Model attributes.
|
144
|
+
def initialize(data = {})
|
145
|
+
@data = {}
|
146
|
+
# TODO: what if data isn't a hash?
|
147
|
+
data.each do |field_name, value|
|
148
|
+
next if value.nil?
|
149
|
+
|
150
|
+
field = self.class.fields[field_name.to_sym]
|
151
|
+
if field
|
152
|
+
next if field[:mode] == :w
|
153
|
+
end
|
154
|
+
@data[field_name.to_sym] = value
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# Returns a Hash of the data underlying this object.
|
159
|
+
# Keys are Symbols and values are the parsed / typed domain objects.
|
160
|
+
# The return value indicates which values were ever set on the object -
|
161
|
+
# i.e. there will be a key in this hash if they ever were, even if the
|
162
|
+
# set value was nil.
|
163
|
+
# This method is not recursive.
|
164
|
+
# The returned value is shared by the object, so it should not be mutated.
|
165
|
+
#
|
166
|
+
# @return [Hash{Symbol => Object}] Data for this object.
|
167
|
+
def to_h
|
168
|
+
@data
|
169
|
+
end
|
170
|
+
|
171
|
+
alias_method :to_hash, :to_h
|
172
|
+
|
173
|
+
# Lookup attribute value by key in the object.
|
174
|
+
# If this key was not provided when the object was formed (e.g. because the API response
|
175
|
+
# did not include that key), returns nil.
|
176
|
+
# It is valid to lookup keys that are not in the API spec, for example to access
|
177
|
+
# undocumented features.
|
178
|
+
# Lookup by anything other than a Symbol is an ArgumentError.
|
179
|
+
#
|
180
|
+
# @param key [Symbol] Key to look up by.
|
181
|
+
#
|
182
|
+
# @return [Object] Parsed / typed value at the given key, or nil if no data is available.
|
183
|
+
def [](key)
|
184
|
+
if !key.instance_of?(Symbol)
|
185
|
+
raise ArgumentError, "Expected symbol key for lookup, got #{key.inspect}"
|
186
|
+
end
|
187
|
+
@data[key]
|
188
|
+
end
|
189
|
+
|
190
|
+
# @return [String]
|
191
|
+
def inspect
|
192
|
+
"#<#{self.class.name}:0x#{object_id.to_s(16)} #{@data.inspect}>"
|
193
|
+
end
|
194
|
+
|
195
|
+
# @return [String]
|
196
|
+
def to_s
|
197
|
+
@data.to_s
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
class ConversionError < Error
|
202
|
+
end
|
203
|
+
end
|
data/lib/sink/client.rb
ADDED
@@ -0,0 +1,381 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sink
|
4
|
+
class Client < BaseClient
|
5
|
+
# Default max number of retries to attempt after a failed retryable request.
|
6
|
+
DEFAULT_MAX_RETRIES = 1
|
7
|
+
|
8
|
+
# Client option
|
9
|
+
# @return [String]
|
10
|
+
attr_reader :user_token
|
11
|
+
|
12
|
+
# Client option
|
13
|
+
# @return [String]
|
14
|
+
attr_reader :api_key_header
|
15
|
+
|
16
|
+
# Client option
|
17
|
+
# @return [String]
|
18
|
+
attr_reader :api_key_query
|
19
|
+
|
20
|
+
# Client option
|
21
|
+
# @return [String]
|
22
|
+
attr_reader :username
|
23
|
+
|
24
|
+
# Client option
|
25
|
+
# @return [String]
|
26
|
+
attr_reader :client_id
|
27
|
+
|
28
|
+
# Client option
|
29
|
+
# @return [String]
|
30
|
+
attr_reader :client_secret
|
31
|
+
|
32
|
+
# Client option
|
33
|
+
# @return [Boolean]
|
34
|
+
attr_reader :some_boolean_arg
|
35
|
+
|
36
|
+
# Client option
|
37
|
+
# @return [Integer]
|
38
|
+
attr_reader :some_integer_arg
|
39
|
+
|
40
|
+
# Client option
|
41
|
+
# @return [Float]
|
42
|
+
attr_reader :some_number_arg
|
43
|
+
|
44
|
+
# Client option
|
45
|
+
# @return [Float]
|
46
|
+
attr_reader :some_number_arg_required
|
47
|
+
|
48
|
+
# Client option
|
49
|
+
# @return [Float]
|
50
|
+
attr_reader :some_number_arg_required_no_default
|
51
|
+
|
52
|
+
# Client option
|
53
|
+
# @return [Float]
|
54
|
+
attr_reader :some_number_arg_required_no_default_no_env
|
55
|
+
|
56
|
+
# Client option
|
57
|
+
# @return [String]
|
58
|
+
attr_reader :required_arg_no_env
|
59
|
+
|
60
|
+
# Client option
|
61
|
+
# @return [String]
|
62
|
+
attr_reader :required_arg_no_env_with_default
|
63
|
+
|
64
|
+
# Client option
|
65
|
+
# @return [String]
|
66
|
+
attr_reader :client_path_param
|
67
|
+
|
68
|
+
# Client option
|
69
|
+
# @return [String]
|
70
|
+
attr_reader :camel_case_path
|
71
|
+
|
72
|
+
# Client option
|
73
|
+
# @return [String]
|
74
|
+
attr_reader :client_query_param
|
75
|
+
|
76
|
+
# Client option
|
77
|
+
# @return [String]
|
78
|
+
attr_reader :client_path_or_query_param
|
79
|
+
|
80
|
+
# @return [Sink::Resources::Testing]
|
81
|
+
attr_reader :testing
|
82
|
+
|
83
|
+
# @return [Sink::Resources::ComplexQueries]
|
84
|
+
attr_reader :complex_queries
|
85
|
+
|
86
|
+
# @return [Sink::Resources::Casing]
|
87
|
+
attr_reader :casing
|
88
|
+
|
89
|
+
# @return [Sink::Resources::Tools]
|
90
|
+
attr_reader :tools
|
91
|
+
|
92
|
+
# @return [Sink::Resources::UndocumentedResource]
|
93
|
+
attr_reader :undocumented_resource
|
94
|
+
|
95
|
+
# @return [Sink::Resources::MethodConfig]
|
96
|
+
attr_reader :method_config
|
97
|
+
|
98
|
+
# @return [Sink::Resources::Streaming]
|
99
|
+
attr_reader :streaming
|
100
|
+
|
101
|
+
# @return [Sink::Resources::PaginationTests]
|
102
|
+
attr_reader :pagination_tests
|
103
|
+
|
104
|
+
# @return [Sink::Resources::Docstrings]
|
105
|
+
attr_reader :docstrings
|
106
|
+
|
107
|
+
# @return [Sink::Resources::InvalidSchemas]
|
108
|
+
attr_reader :invalid_schemas
|
109
|
+
|
110
|
+
# @return [Sink::Resources::ResourceRefs]
|
111
|
+
attr_reader :resource_refs
|
112
|
+
|
113
|
+
# @return [Sink::Resources::Cards]
|
114
|
+
attr_reader :cards
|
115
|
+
|
116
|
+
# @return [Sink::Resources::Resources]
|
117
|
+
attr_reader :resources
|
118
|
+
|
119
|
+
# @return [Sink::Resources::ConfigTools]
|
120
|
+
attr_reader :config_tools
|
121
|
+
|
122
|
+
# Stainless API company
|
123
|
+
# @return [Sink::Resources::Company]
|
124
|
+
attr_reader :company
|
125
|
+
|
126
|
+
# @return [Sink::Resources::OpenAPIFormats]
|
127
|
+
attr_reader :openapi_formats
|
128
|
+
|
129
|
+
# @return [Sink::Resources::Parent]
|
130
|
+
attr_reader :parent
|
131
|
+
|
132
|
+
# @return [Sink::Resources::Types]
|
133
|
+
attr_reader :types
|
134
|
+
|
135
|
+
# @return [Sink::Resources::Clients]
|
136
|
+
attr_reader :clients
|
137
|
+
|
138
|
+
# @return [Sink::Resources::Names]
|
139
|
+
attr_reader :names
|
140
|
+
|
141
|
+
# Widget is love
|
142
|
+
# Widget is life
|
143
|
+
# @return [Sink::Resources::Widgets]
|
144
|
+
attr_reader :widgets
|
145
|
+
|
146
|
+
# @return [Sink::Resources::Responses]
|
147
|
+
attr_reader :responses
|
148
|
+
|
149
|
+
# @return [Sink::Resources::PathParams]
|
150
|
+
attr_reader :path_params
|
151
|
+
|
152
|
+
# @return [Sink::Resources::PositionalParams]
|
153
|
+
attr_reader :positional_params
|
154
|
+
|
155
|
+
# @return [Sink::Resources::EmptyBody]
|
156
|
+
attr_reader :empty_body
|
157
|
+
|
158
|
+
# @return [Sink::Resources::QueryParams]
|
159
|
+
attr_reader :query_params
|
160
|
+
|
161
|
+
# @return [Sink::Resources::BodyParams]
|
162
|
+
attr_reader :body_params
|
163
|
+
|
164
|
+
# @return [Sink::Resources::HeaderParams]
|
165
|
+
attr_reader :header_params
|
166
|
+
|
167
|
+
# @return [Sink::Resources::MixedParams]
|
168
|
+
attr_reader :mixed_params
|
169
|
+
|
170
|
+
# @return [Sink::Resources::MakeAmbiguousSchemasLooser]
|
171
|
+
attr_reader :make_ambiguous_schemas_looser
|
172
|
+
|
173
|
+
# @return [Sink::Resources::MakeAmbiguousSchemasExplicit]
|
174
|
+
attr_reader :make_ambiguous_schemas_explicit
|
175
|
+
|
176
|
+
# @return [Sink::Resources::DecoratorTests]
|
177
|
+
attr_reader :decorator_tests
|
178
|
+
|
179
|
+
# @return [Sink::Resources::Tests]
|
180
|
+
attr_reader :tests
|
181
|
+
|
182
|
+
# @return [Sink::Resources::DeeplyNested]
|
183
|
+
attr_reader :deeply_nested
|
184
|
+
|
185
|
+
# @return [Sink::Resources::Version1_30Names]
|
186
|
+
attr_reader :version_1_30_names
|
187
|
+
|
188
|
+
# @return [Sink::Resources::Recursion]
|
189
|
+
attr_reader :recursion
|
190
|
+
|
191
|
+
# @return [Sink::Resources::SharedQueryParams]
|
192
|
+
attr_reader :shared_query_params
|
193
|
+
|
194
|
+
# @return [Sink::Resources::ModelReferencedInParentAndChild]
|
195
|
+
attr_reader :model_referenced_in_parent_and_child
|
196
|
+
|
197
|
+
# Creates and returns a new client for interacting with the API.
|
198
|
+
#
|
199
|
+
# @param environment ["production", "sandbox", nil] Specifies the environment to use for the API.
|
200
|
+
#
|
201
|
+
# Each environment maps to a different base URL:
|
202
|
+
#
|
203
|
+
# - `production` corresponds to `https://demo.stainlessapi.com/`
|
204
|
+
# - `sandbox` corresponds to `https://demo-sanbox.stainlessapi.com/`
|
205
|
+
# @param base_url [String, nil] Override the default base URL for the API, e.g., `"https://api.example.com/v2/"`
|
206
|
+
# @param user_token [String, nil] The API Key for the SINK API, sent as a bearer token Defaults to
|
207
|
+
# `ENV["SINK_CUSTOM_API_KEY_ENV"]`
|
208
|
+
# @param api_key_header [String, nil] The API Key for the SINK API, sent as an api key header Defaults to
|
209
|
+
# `ENV["SINK_CUSTOM_API_KEY_HEADER_ENV"]`
|
210
|
+
# @param api_key_query [String, nil] The API Key for the SINK API, sent as an api key query Defaults to
|
211
|
+
# `ENV["SINK_CUSTOM_API_KEY_QUERY_ENV"]`
|
212
|
+
# @param username [String, nil] Defaults to `ENV["SINK_USER"]`
|
213
|
+
# @param client_id [String, nil] Defaults to `ENV["SINK_CLIENT_ID"]`
|
214
|
+
# @param client_secret [String, nil] Defaults to `ENV["SINK_CLIENT_SECRET"]`
|
215
|
+
# @param some_boolean_arg [Boolean, nil] Defaults to `ENV["SINK_SOME_BOOLEAN_ARG"]`
|
216
|
+
# @param some_integer_arg [Integer, nil] Defaults to `ENV["SINK_SOME_INTEGER_ARG"]`
|
217
|
+
# @param some_number_arg [Float, nil] Defaults to `ENV["SINK_SOME_NUMBER_ARG"]`
|
218
|
+
# @param some_number_arg_required [Float, nil] Defaults to `ENV["SINK_SOME_NUMBER_ARG"]`
|
219
|
+
# @param some_number_arg_required_no_default [Float, nil] Defaults to `ENV["SINK_SOME_NUMBER_ARG"]`
|
220
|
+
# @param some_number_arg_required_no_default_no_env [Float, nil]
|
221
|
+
# @param required_arg_no_env [String, nil]
|
222
|
+
# @param required_arg_no_env_with_default [String, nil]
|
223
|
+
# @param client_path_param [String, nil]
|
224
|
+
# @param camel_case_path [String, nil]
|
225
|
+
# @param client_query_param [String, nil]
|
226
|
+
# @param client_path_or_query_param [String, nil]
|
227
|
+
# @param max_retries [Integer] Max number of retries to attempt after a failed retryable request.
|
228
|
+
#
|
229
|
+
# @return [Sink::Client]
|
230
|
+
def initialize(
|
231
|
+
environment: nil,
|
232
|
+
base_url: nil,
|
233
|
+
user_token: nil,
|
234
|
+
api_key_header: nil,
|
235
|
+
api_key_query: nil,
|
236
|
+
username: nil,
|
237
|
+
client_id: nil,
|
238
|
+
client_secret: nil,
|
239
|
+
some_boolean_arg: nil,
|
240
|
+
some_integer_arg: nil,
|
241
|
+
some_number_arg: nil,
|
242
|
+
some_number_arg_required: nil,
|
243
|
+
some_number_arg_required_no_default: nil,
|
244
|
+
some_number_arg_required_no_default_no_env: nil,
|
245
|
+
required_arg_no_env: nil,
|
246
|
+
required_arg_no_env_with_default: nil,
|
247
|
+
client_path_param: nil,
|
248
|
+
camel_case_path: nil,
|
249
|
+
client_query_param: nil,
|
250
|
+
client_path_or_query_param: nil,
|
251
|
+
max_retries: DEFAULT_MAX_RETRIES
|
252
|
+
)
|
253
|
+
environments = {"production" => "https://demo.stainlessapi.com/", "sandbox" => "https://demo-sanbox.stainlessapi.com/"}
|
254
|
+
if environment && base_url
|
255
|
+
raise ArgumentError, "both environment and base_url given, expected only one"
|
256
|
+
elsif environment
|
257
|
+
if !environments.key?(environment.to_s)
|
258
|
+
raise ArgumentError, "environment must be one of #{environments.keys}, got #{environment}"
|
259
|
+
end
|
260
|
+
base_url = environments[environment.to_s]
|
261
|
+
elsif !base_url
|
262
|
+
base_url = "https://demo.stainlessapi.com/"
|
263
|
+
end
|
264
|
+
|
265
|
+
username_header = [username, ENV["SINK_USER"]].find { |v| !v.nil? }
|
266
|
+
if username_header.nil?
|
267
|
+
raise ArgumentError, "username is required"
|
268
|
+
end
|
269
|
+
client_secret_header = [client_secret, ENV["SINK_CLIENT_SECRET"], "hellosecret"].find { |v| !v.nil? }
|
270
|
+
some_integer_arg_header = [some_integer_arg, ENV["SINK_SOME_INTEGER_ARG"], 123].find { |v| !v.nil? }
|
271
|
+
headers = {
|
272
|
+
"My-Api-Version" => "11",
|
273
|
+
"X-Enable-Metrics" => "1",
|
274
|
+
"X-Client-UserName" => username_header,
|
275
|
+
"X-Client-Secret" => client_secret_header,
|
276
|
+
"X-Integer" => some_integer_arg_header
|
277
|
+
}
|
278
|
+
|
279
|
+
idempotency_header = "Idempotency-Key"
|
280
|
+
|
281
|
+
@user_token = [user_token, ENV["SINK_CUSTOM_API_KEY_ENV"]].find { |v| !v.nil? }
|
282
|
+
@api_key_header = [api_key_header, ENV["SINK_CUSTOM_API_KEY_HEADER_ENV"]].find { |v| !v.nil? }
|
283
|
+
@api_key_query = [api_key_query, ENV["SINK_CUSTOM_API_KEY_QUERY_ENV"]].find { |v| !v.nil? }
|
284
|
+
@client_id = [client_id, ENV["SINK_CLIENT_ID"]].find { |v| !v.nil? }
|
285
|
+
@some_boolean_arg = [some_boolean_arg, ENV["SINK_SOME_BOOLEAN_ARG"], true].find { |v| !v.nil? }
|
286
|
+
@some_number_arg = [some_number_arg, ENV["SINK_SOME_NUMBER_ARG"], 1.2].find { |v| !v.nil? }
|
287
|
+
@some_number_arg_required = [some_number_arg_required, ENV["SINK_SOME_NUMBER_ARG"], 1.2].find do |v|
|
288
|
+
!v.nil?
|
289
|
+
end
|
290
|
+
@some_number_arg_required_no_default = [
|
291
|
+
some_number_arg_required_no_default,
|
292
|
+
ENV["SINK_SOME_NUMBER_ARG"]
|
293
|
+
].find do |v|
|
294
|
+
!v.nil?
|
295
|
+
end
|
296
|
+
if @some_number_arg_required_no_default.nil?
|
297
|
+
raise ArgumentError, "some_number_arg_required_no_default is required"
|
298
|
+
end
|
299
|
+
@some_number_arg_required_no_default_no_env = some_number_arg_required_no_default_no_env
|
300
|
+
if @some_number_arg_required_no_default_no_env.nil?
|
301
|
+
raise ArgumentError, "some_number_arg_required_no_default_no_env is required"
|
302
|
+
end
|
303
|
+
@required_arg_no_env = required_arg_no_env
|
304
|
+
if @required_arg_no_env.nil?
|
305
|
+
raise ArgumentError, "required_arg_no_env is required"
|
306
|
+
end
|
307
|
+
@required_arg_no_env_with_default = [required_arg_no_env_with_default, "hi!"].find { |v| !v.nil? }
|
308
|
+
@client_query_param = client_query_param
|
309
|
+
|
310
|
+
super(
|
311
|
+
base_url: base_url,
|
312
|
+
max_retries: max_retries,
|
313
|
+
headers: headers,
|
314
|
+
idempotency_header: idempotency_header
|
315
|
+
)
|
316
|
+
|
317
|
+
@testing = Sink::Resources::Testing.new(client: self)
|
318
|
+
@complex_queries = Sink::Resources::ComplexQueries.new(client: self)
|
319
|
+
@casing = Sink::Resources::Casing.new(client: self)
|
320
|
+
@tools = Sink::Resources::Tools.new(client: self)
|
321
|
+
@undocumented_resource = Sink::Resources::UndocumentedResource.new(client: self)
|
322
|
+
@method_config = Sink::Resources::MethodConfig.new(client: self)
|
323
|
+
@streaming = Sink::Resources::Streaming.new(client: self)
|
324
|
+
@pagination_tests = Sink::Resources::PaginationTests.new(client: self)
|
325
|
+
@docstrings = Sink::Resources::Docstrings.new(client: self)
|
326
|
+
@invalid_schemas = Sink::Resources::InvalidSchemas.new(client: self)
|
327
|
+
@resource_refs = Sink::Resources::ResourceRefs.new(client: self)
|
328
|
+
@cards = Sink::Resources::Cards.new(client: self)
|
329
|
+
@resources = Sink::Resources::Resources.new(client: self)
|
330
|
+
@config_tools = Sink::Resources::ConfigTools.new(client: self)
|
331
|
+
@company = Sink::Resources::Company.new(client: self)
|
332
|
+
@openapi_formats = Sink::Resources::OpenAPIFormats.new(client: self)
|
333
|
+
@parent = Sink::Resources::Parent.new(client: self)
|
334
|
+
@types = Sink::Resources::Types.new(client: self)
|
335
|
+
@clients = Sink::Resources::Clients.new(client: self)
|
336
|
+
@names = Sink::Resources::Names.new(client: self)
|
337
|
+
@widgets = Sink::Resources::Widgets.new(client: self)
|
338
|
+
@responses = Sink::Resources::Responses.new(client: self)
|
339
|
+
@path_params = Sink::Resources::PathParams.new(client: self)
|
340
|
+
@positional_params = Sink::Resources::PositionalParams.new(client: self)
|
341
|
+
@empty_body = Sink::Resources::EmptyBody.new(client: self)
|
342
|
+
@query_params = Sink::Resources::QueryParams.new(client: self)
|
343
|
+
@body_params = Sink::Resources::BodyParams.new(client: self)
|
344
|
+
@header_params = Sink::Resources::HeaderParams.new(client: self)
|
345
|
+
@mixed_params = Sink::Resources::MixedParams.new(client: self)
|
346
|
+
@make_ambiguous_schemas_looser = Sink::Resources::MakeAmbiguousSchemasLooser.new(client: self)
|
347
|
+
@make_ambiguous_schemas_explicit = Sink::Resources::MakeAmbiguousSchemasExplicit.new(client: self)
|
348
|
+
@decorator_tests = Sink::Resources::DecoratorTests.new(client: self)
|
349
|
+
@tests = Sink::Resources::Tests.new(client: self)
|
350
|
+
@deeply_nested = Sink::Resources::DeeplyNested.new(client: self)
|
351
|
+
@version_1_30_names = Sink::Resources::Version1_30Names.new(client: self)
|
352
|
+
@recursion = Sink::Resources::Recursion.new(client: self)
|
353
|
+
@shared_query_params = Sink::Resources::SharedQueryParams.new(client: self)
|
354
|
+
@model_referenced_in_parent_and_child = Sink::Resources::ModelReferencedInParentAndChild.new(client: self)
|
355
|
+
end
|
356
|
+
|
357
|
+
# @!visibility private
|
358
|
+
def make_status_error(message:, body:, response:)
|
359
|
+
case response.code.to_i
|
360
|
+
when 400
|
361
|
+
Sink::HTTP::BadRequestError.new(message: message, response: response, body: body)
|
362
|
+
when 401
|
363
|
+
Sink::HTTP::AuthenticationError.new(message: message, response: response, body: body)
|
364
|
+
when 403
|
365
|
+
Sink::HTTP::PermissionDeniedError.new(message: message, response: response, body: body)
|
366
|
+
when 404
|
367
|
+
Sink::HTTP::NotFoundError.new(message: message, response: response, body: body)
|
368
|
+
when 409
|
369
|
+
Sink::HTTP::ConflictError.new(message: message, response: response, body: body)
|
370
|
+
when 422
|
371
|
+
Sink::HTTP::UnprocessableEntityError.new(message: message, response: response, body: body)
|
372
|
+
when 429
|
373
|
+
Sink::HTTP::RateLimitError.new(message: message, response: response, body: body)
|
374
|
+
when 500..599
|
375
|
+
Sink::HTTP::InternalServerError.new(message: message, response: response, body: body)
|
376
|
+
else
|
377
|
+
Sink::HTTP::APIStatusError.new(message: message, response: response, body: body)
|
378
|
+
end
|
379
|
+
end
|
380
|
+
end
|
381
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sink
|
4
|
+
class FakePage < ::Array
|
5
|
+
# @!visibility private
|
6
|
+
attr_accessor :client, :req, :opts
|
7
|
+
|
8
|
+
# @!visibility private
|
9
|
+
def initialize(model, raw_data, _response, client, req, opts)
|
10
|
+
super(raw_data.map { |e| model.convert(e) })
|
11
|
+
self.client = client
|
12
|
+
self.req = req
|
13
|
+
self.opts = opts
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [Boolean]
|
17
|
+
def next_page?
|
18
|
+
false
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [FakePage]
|
22
|
+
def next_page
|
23
|
+
raise NotImplementedError
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [nil]
|
27
|
+
def auto_paging_each(&blk)
|
28
|
+
if !blk
|
29
|
+
raise "A block must be given to #auto_paging_each"
|
30
|
+
end
|
31
|
+
page = self
|
32
|
+
loop do
|
33
|
+
page.each { |e| blk.call(e) }
|
34
|
+
break if !page.next_page?
|
35
|
+
page = page.next_page
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sink
|
4
|
+
module Models
|
5
|
+
class AllofMultipleInlineEntries < Sink::Models::AllofBaseParent
|
6
|
+
# @!attribute [rw] in_first_entry
|
7
|
+
# @return [String]
|
8
|
+
optional :in_first_entry, String
|
9
|
+
|
10
|
+
# @!attribute [rw] in_second_entry
|
11
|
+
# @return [Integer]
|
12
|
+
optional :in_second_entry, Integer
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|