exa-ai 0.3.0 → 0.4.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 +4 -4
- data/README.md +94 -591
- data/exe/exa-ai +112 -9
- data/exe/exa-ai-answer +1 -5
- data/exe/exa-ai-context +1 -4
- data/exe/exa-ai-enrichment-cancel +107 -0
- data/exe/exa-ai-enrichment-create +235 -0
- data/exe/exa-ai-enrichment-delete +121 -0
- data/exe/exa-ai-enrichment-get +103 -0
- data/exe/exa-ai-enrichment-list +98 -0
- data/exe/exa-ai-enrichment-update +170 -0
- data/exe/exa-ai-find-similar +240 -0
- data/exe/exa-ai-get-contents +1 -4
- data/exe/exa-ai-research-get +1 -2
- data/exe/exa-ai-research-list +1 -2
- data/exe/exa-ai-research-start +1 -3
- data/exe/exa-ai-search +1 -3
- data/exe/exa-ai-webset-cancel +96 -0
- data/exe/exa-ai-webset-create +192 -0
- data/exe/exa-ai-webset-delete +110 -0
- data/exe/exa-ai-webset-get +92 -0
- data/exe/exa-ai-webset-item-delete +111 -0
- data/exe/exa-ai-webset-item-get +104 -0
- data/exe/exa-ai-webset-item-list +93 -0
- data/exe/exa-ai-webset-list +90 -0
- data/exe/exa-ai-webset-search-cancel +103 -0
- data/exe/exa-ai-webset-search-create +233 -0
- data/exe/exa-ai-webset-search-get +104 -0
- data/exe/exa-ai-webset-update +139 -0
- data/lib/exa/cli/base.rb +3 -3
- data/lib/exa/cli/formatters/enrichment_formatter.rb +69 -0
- data/lib/exa/cli/formatters/webset_formatter.rb +68 -0
- data/lib/exa/cli/formatters/webset_item_formatter.rb +69 -0
- data/lib/exa/client.rb +172 -0
- data/lib/exa/connection.rb +8 -1
- data/lib/exa/resources/webset.rb +74 -0
- data/lib/exa/resources/webset_collection.rb +33 -0
- data/lib/exa/resources/webset_enrichment.rb +71 -0
- data/lib/exa/resources/webset_enrichment_collection.rb +28 -0
- data/lib/exa/resources/webset_search.rb +112 -0
- data/lib/exa/services/parameter_converter.rb +1 -0
- data/lib/exa/services/websets/cancel.rb +36 -0
- data/lib/exa/services/websets/cancel_enrichment.rb +35 -0
- data/lib/exa/services/websets/cancel_search.rb +44 -0
- data/lib/exa/services/websets/create.rb +45 -0
- data/lib/exa/services/websets/create_enrichment.rb +35 -0
- data/lib/exa/services/websets/create_search.rb +48 -0
- data/lib/exa/services/websets/create_search_validator.rb +128 -0
- data/lib/exa/services/websets/create_validator.rb +189 -0
- data/lib/exa/services/websets/delete.rb +36 -0
- data/lib/exa/services/websets/delete_enrichment.rb +35 -0
- data/lib/exa/services/websets/delete_item.rb +20 -0
- data/lib/exa/services/websets/get_item.rb +20 -0
- data/lib/exa/services/websets/get_search.rb +43 -0
- data/lib/exa/services/websets/list.rb +25 -0
- data/lib/exa/services/websets/list_items.rb +20 -0
- data/lib/exa/services/websets/retrieve.rb +47 -0
- data/lib/exa/services/websets/retrieve_enrichment.rb +35 -0
- data/lib/exa/services/websets/update.rb +37 -0
- data/lib/exa/services/websets/update_enrichment.rb +36 -0
- data/lib/exa/services/websets_parameter_converter.rb +45 -0
- data/lib/exa/version.rb +1 -1
- data/lib/exa-ai.rb +5 -0
- data/lib/exa.rb +26 -0
- metadata +65 -3
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Exa
|
|
4
|
+
module Resources
|
|
5
|
+
# Represents a webset enrichment from the Exa API
|
|
6
|
+
#
|
|
7
|
+
# An enrichment extracts specific data from web entities in a webset.
|
|
8
|
+
class WebsetEnrichment < Struct.new(
|
|
9
|
+
:id,
|
|
10
|
+
:object,
|
|
11
|
+
:status,
|
|
12
|
+
:webset_id,
|
|
13
|
+
:title,
|
|
14
|
+
:description,
|
|
15
|
+
:format,
|
|
16
|
+
:options,
|
|
17
|
+
:instructions,
|
|
18
|
+
:metadata,
|
|
19
|
+
:created_at,
|
|
20
|
+
:updated_at,
|
|
21
|
+
keyword_init: true
|
|
22
|
+
)
|
|
23
|
+
def initialize(
|
|
24
|
+
id:,
|
|
25
|
+
object:,
|
|
26
|
+
status:,
|
|
27
|
+
webset_id: nil,
|
|
28
|
+
title: nil,
|
|
29
|
+
description: nil,
|
|
30
|
+
format: nil,
|
|
31
|
+
options: nil,
|
|
32
|
+
instructions: nil,
|
|
33
|
+
metadata: nil,
|
|
34
|
+
created_at: nil,
|
|
35
|
+
updated_at: nil
|
|
36
|
+
)
|
|
37
|
+
super
|
|
38
|
+
freeze
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def pending?
|
|
42
|
+
status == "pending"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def running?
|
|
46
|
+
status == "running"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def completed?
|
|
50
|
+
status == "completed"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def to_h
|
|
54
|
+
{
|
|
55
|
+
id: id,
|
|
56
|
+
object: object,
|
|
57
|
+
status: status,
|
|
58
|
+
webset_id: webset_id,
|
|
59
|
+
title: title,
|
|
60
|
+
description: description,
|
|
61
|
+
format: format,
|
|
62
|
+
options: options,
|
|
63
|
+
instructions: instructions,
|
|
64
|
+
metadata: metadata,
|
|
65
|
+
created_at: created_at,
|
|
66
|
+
updated_at: updated_at
|
|
67
|
+
}.compact
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Exa
|
|
4
|
+
module Resources
|
|
5
|
+
# Represents a list of enrichments for a webset from the Exa API
|
|
6
|
+
#
|
|
7
|
+
# This class wraps the JSON response from the GET /websets/v0/websets/{id}/enrichments endpoint
|
|
8
|
+
class WebsetEnrichmentCollection < Struct.new(
|
|
9
|
+
:data,
|
|
10
|
+
keyword_init: true
|
|
11
|
+
)
|
|
12
|
+
def initialize(data:)
|
|
13
|
+
super
|
|
14
|
+
freeze
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def empty?
|
|
18
|
+
data.empty?
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def to_h
|
|
22
|
+
{
|
|
23
|
+
data: data
|
|
24
|
+
}
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Exa
|
|
4
|
+
module Resources
|
|
5
|
+
# Represents a search operation within a webset
|
|
6
|
+
#
|
|
7
|
+
# A search finds entities matching specific criteria and can either
|
|
8
|
+
# override existing webset items or append to them.
|
|
9
|
+
class WebsetSearch < Struct.new(
|
|
10
|
+
:id,
|
|
11
|
+
:object,
|
|
12
|
+
:status,
|
|
13
|
+
:webset_id,
|
|
14
|
+
:query,
|
|
15
|
+
:entity,
|
|
16
|
+
:criteria,
|
|
17
|
+
:count,
|
|
18
|
+
:behavior,
|
|
19
|
+
:exclude,
|
|
20
|
+
:scope,
|
|
21
|
+
:progress,
|
|
22
|
+
:recall,
|
|
23
|
+
:metadata,
|
|
24
|
+
:canceled_at,
|
|
25
|
+
:canceled_reason,
|
|
26
|
+
:created_at,
|
|
27
|
+
:updated_at,
|
|
28
|
+
keyword_init: true
|
|
29
|
+
)
|
|
30
|
+
def initialize(
|
|
31
|
+
id:,
|
|
32
|
+
object:,
|
|
33
|
+
status:,
|
|
34
|
+
webset_id: nil,
|
|
35
|
+
query: nil,
|
|
36
|
+
entity: nil,
|
|
37
|
+
criteria: nil,
|
|
38
|
+
count: nil,
|
|
39
|
+
behavior: nil,
|
|
40
|
+
exclude: nil,
|
|
41
|
+
scope: nil,
|
|
42
|
+
progress: nil,
|
|
43
|
+
recall: nil,
|
|
44
|
+
metadata: nil,
|
|
45
|
+
canceled_at: nil,
|
|
46
|
+
canceled_reason: nil,
|
|
47
|
+
created_at: nil,
|
|
48
|
+
updated_at: nil
|
|
49
|
+
)
|
|
50
|
+
super
|
|
51
|
+
freeze
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Status helper methods
|
|
55
|
+
def created?
|
|
56
|
+
status == "created"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def running?
|
|
60
|
+
status == "running"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def completed?
|
|
64
|
+
status == "completed"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def failed?
|
|
68
|
+
status == "failed"
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def canceled?
|
|
72
|
+
status == "canceled"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def in_progress?
|
|
76
|
+
created? || running?
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Behavior helper methods
|
|
80
|
+
def override?
|
|
81
|
+
behavior == "override"
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def append?
|
|
85
|
+
behavior == "append"
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def to_h
|
|
89
|
+
{
|
|
90
|
+
id: id,
|
|
91
|
+
object: object,
|
|
92
|
+
status: status,
|
|
93
|
+
webset_id: webset_id,
|
|
94
|
+
query: query,
|
|
95
|
+
entity: entity,
|
|
96
|
+
criteria: criteria,
|
|
97
|
+
count: count,
|
|
98
|
+
behavior: behavior,
|
|
99
|
+
exclude: exclude,
|
|
100
|
+
scope: scope,
|
|
101
|
+
progress: progress,
|
|
102
|
+
recall: recall,
|
|
103
|
+
metadata: metadata,
|
|
104
|
+
canceled_at: canceled_at,
|
|
105
|
+
canceled_reason: canceled_reason,
|
|
106
|
+
created_at: created_at,
|
|
107
|
+
updated_at: updated_at
|
|
108
|
+
}.compact
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Exa
|
|
4
|
+
module Services
|
|
5
|
+
module Websets
|
|
6
|
+
class Cancel
|
|
7
|
+
def initialize(connection, id:)
|
|
8
|
+
@connection = connection
|
|
9
|
+
@id = id
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def call
|
|
13
|
+
response = @connection.post("/websets/v0/websets/#{@id}/cancel", {})
|
|
14
|
+
body = response.body
|
|
15
|
+
|
|
16
|
+
Resources::Webset.new(
|
|
17
|
+
id: body["id"],
|
|
18
|
+
object: body["object"],
|
|
19
|
+
status: body["status"],
|
|
20
|
+
external_id: body["externalId"],
|
|
21
|
+
title: body["title"],
|
|
22
|
+
searches: body["searches"],
|
|
23
|
+
imports: body["imports"],
|
|
24
|
+
enrichments: body["enrichments"],
|
|
25
|
+
monitors: body["monitors"],
|
|
26
|
+
excludes: body["excludes"],
|
|
27
|
+
metadata: body["metadata"],
|
|
28
|
+
created_at: body["createdAt"],
|
|
29
|
+
updated_at: body["updatedAt"],
|
|
30
|
+
items: body["items"]
|
|
31
|
+
)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Exa
|
|
4
|
+
module Services
|
|
5
|
+
module Websets
|
|
6
|
+
class CancelEnrichment
|
|
7
|
+
def initialize(connection, webset_id:, id:)
|
|
8
|
+
@connection = connection
|
|
9
|
+
@webset_id = webset_id
|
|
10
|
+
@id = id
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def call
|
|
14
|
+
response = @connection.post("/websets/v0/websets/#{@webset_id}/enrichments/#{@id}/cancel", {})
|
|
15
|
+
body = response.body
|
|
16
|
+
|
|
17
|
+
Resources::WebsetEnrichment.new(
|
|
18
|
+
id: body["id"],
|
|
19
|
+
object: body["object"],
|
|
20
|
+
status: body["status"],
|
|
21
|
+
webset_id: body["websetId"],
|
|
22
|
+
title: body["title"],
|
|
23
|
+
description: body["description"],
|
|
24
|
+
format: body["format"],
|
|
25
|
+
options: body["options"],
|
|
26
|
+
instructions: body["instructions"],
|
|
27
|
+
metadata: body["metadata"],
|
|
28
|
+
created_at: body["createdAt"],
|
|
29
|
+
updated_at: body["updatedAt"]
|
|
30
|
+
)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Exa
|
|
4
|
+
module Services
|
|
5
|
+
module Websets
|
|
6
|
+
class CancelSearch
|
|
7
|
+
def initialize(connection, webset_id:, id:)
|
|
8
|
+
@connection = connection
|
|
9
|
+
@webset_id = webset_id
|
|
10
|
+
@id = id
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def call
|
|
14
|
+
response = @connection.post(
|
|
15
|
+
"/websets/v0/websets/#{@webset_id}/searches/#{@id}/cancel",
|
|
16
|
+
{}
|
|
17
|
+
)
|
|
18
|
+
body = response.body
|
|
19
|
+
|
|
20
|
+
Resources::WebsetSearch.new(
|
|
21
|
+
id: body["id"],
|
|
22
|
+
object: body["object"],
|
|
23
|
+
status: body["status"],
|
|
24
|
+
webset_id: body["websetId"],
|
|
25
|
+
query: body["query"],
|
|
26
|
+
entity: body["entity"],
|
|
27
|
+
criteria: body["criteria"],
|
|
28
|
+
count: body["count"],
|
|
29
|
+
behavior: body["behavior"],
|
|
30
|
+
exclude: body["exclude"],
|
|
31
|
+
scope: body["scope"],
|
|
32
|
+
progress: body["progress"],
|
|
33
|
+
recall: body["recall"],
|
|
34
|
+
metadata: body["metadata"],
|
|
35
|
+
canceled_at: body["canceledAt"],
|
|
36
|
+
canceled_reason: body["canceledReason"],
|
|
37
|
+
created_at: body["createdAt"],
|
|
38
|
+
updated_at: body["updatedAt"]
|
|
39
|
+
)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "create_validator"
|
|
4
|
+
require_relative "../websets_parameter_converter"
|
|
5
|
+
|
|
6
|
+
module Exa
|
|
7
|
+
module Services
|
|
8
|
+
module Websets
|
|
9
|
+
class Create
|
|
10
|
+
def initialize(connection, **params)
|
|
11
|
+
@connection = connection
|
|
12
|
+
@params = params
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def call
|
|
16
|
+
# Validate parameters before making the API call
|
|
17
|
+
CreateValidator.validate!(@params)
|
|
18
|
+
|
|
19
|
+
# Convert Ruby snake_case params to API camelCase
|
|
20
|
+
converted_params = WebsetsParameterConverter.convert(@params)
|
|
21
|
+
|
|
22
|
+
response = @connection.post("/websets/v0/websets", converted_params)
|
|
23
|
+
body = response.body
|
|
24
|
+
|
|
25
|
+
Resources::Webset.new(
|
|
26
|
+
id: body["id"],
|
|
27
|
+
object: body["object"],
|
|
28
|
+
status: body["status"],
|
|
29
|
+
external_id: body["externalId"],
|
|
30
|
+
title: body["title"],
|
|
31
|
+
searches: body["searches"],
|
|
32
|
+
imports: body["imports"],
|
|
33
|
+
enrichments: body["enrichments"],
|
|
34
|
+
monitors: body["monitors"],
|
|
35
|
+
excludes: body["excludes"],
|
|
36
|
+
metadata: body["metadata"],
|
|
37
|
+
created_at: body["createdAt"],
|
|
38
|
+
updated_at: body["updatedAt"],
|
|
39
|
+
items: body["items"]
|
|
40
|
+
)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Exa
|
|
4
|
+
module Services
|
|
5
|
+
module Websets
|
|
6
|
+
class CreateEnrichment
|
|
7
|
+
def initialize(connection, webset_id:, **params)
|
|
8
|
+
@connection = connection
|
|
9
|
+
@webset_id = webset_id
|
|
10
|
+
@params = params
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def call
|
|
14
|
+
response = @connection.post("/websets/v0/websets/#{@webset_id}/enrichments", @params)
|
|
15
|
+
body = response.body
|
|
16
|
+
|
|
17
|
+
Resources::WebsetEnrichment.new(
|
|
18
|
+
id: body["id"],
|
|
19
|
+
object: body["object"],
|
|
20
|
+
status: body["status"],
|
|
21
|
+
webset_id: body["websetId"],
|
|
22
|
+
title: body["title"],
|
|
23
|
+
description: body["description"],
|
|
24
|
+
format: body["format"],
|
|
25
|
+
options: body["options"],
|
|
26
|
+
instructions: body["instructions"],
|
|
27
|
+
metadata: body["metadata"],
|
|
28
|
+
created_at: body["createdAt"],
|
|
29
|
+
updated_at: body["updatedAt"]
|
|
30
|
+
)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "create_search_validator"
|
|
4
|
+
|
|
5
|
+
module Exa
|
|
6
|
+
module Services
|
|
7
|
+
module Websets
|
|
8
|
+
class CreateSearch
|
|
9
|
+
def initialize(connection, webset_id:, **params)
|
|
10
|
+
@connection = connection
|
|
11
|
+
@webset_id = webset_id
|
|
12
|
+
@params = params
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def call
|
|
16
|
+
CreateSearchValidator.validate!(@params)
|
|
17
|
+
|
|
18
|
+
response = @connection.post(
|
|
19
|
+
"/websets/v0/websets/#{@webset_id}/searches",
|
|
20
|
+
@params
|
|
21
|
+
)
|
|
22
|
+
body = response.body
|
|
23
|
+
|
|
24
|
+
Resources::WebsetSearch.new(
|
|
25
|
+
id: body["id"],
|
|
26
|
+
object: body["object"],
|
|
27
|
+
status: body["status"],
|
|
28
|
+
webset_id: body["websetId"],
|
|
29
|
+
query: body["query"],
|
|
30
|
+
entity: body["entity"],
|
|
31
|
+
criteria: body["criteria"],
|
|
32
|
+
count: body["count"],
|
|
33
|
+
behavior: body["behavior"],
|
|
34
|
+
exclude: body["exclude"],
|
|
35
|
+
scope: body["scope"],
|
|
36
|
+
progress: body["progress"],
|
|
37
|
+
recall: body["recall"],
|
|
38
|
+
metadata: body["metadata"],
|
|
39
|
+
canceled_at: body["canceledAt"],
|
|
40
|
+
canceled_reason: body["canceledReason"],
|
|
41
|
+
created_at: body["createdAt"],
|
|
42
|
+
updated_at: body["updatedAt"]
|
|
43
|
+
)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Exa
|
|
4
|
+
module Services
|
|
5
|
+
module Websets
|
|
6
|
+
# Validates parameters for webset search creation
|
|
7
|
+
class CreateSearchValidator
|
|
8
|
+
VALID_ENTITY_TYPES = %w[company person article research_paper custom].freeze
|
|
9
|
+
VALID_BEHAVIORS = %w[override append].freeze
|
|
10
|
+
VALID_SOURCE_TYPES = %w[import webset].freeze
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
def validate!(params)
|
|
14
|
+
validate_query!(params[:query]) if params[:query]
|
|
15
|
+
validate_count!(params[:count]) if params[:count]
|
|
16
|
+
validate_entity!(params[:entity]) if params[:entity]
|
|
17
|
+
validate_criteria!(params[:criteria]) if params[:criteria]
|
|
18
|
+
validate_scope!(params[:scope]) if params[:scope]
|
|
19
|
+
validate_exclude!(params[:exclude]) if params[:exclude]
|
|
20
|
+
validate_behavior!(params[:behavior]) if params[:behavior]
|
|
21
|
+
validate_metadata!(params[:metadata]) if params[:metadata]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def validate_query!(query)
|
|
27
|
+
raise ArgumentError, "query must be a String" unless query.is_a?(String)
|
|
28
|
+
raise ArgumentError, "query cannot be empty" if query.strip.empty?
|
|
29
|
+
raise ArgumentError, "query cannot exceed 5000 characters" if query.length > 5000
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def validate_count!(count)
|
|
33
|
+
raise ArgumentError, "count must be a positive Integer" unless count.is_a?(Integer) && count > 0
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def validate_entity!(entity)
|
|
37
|
+
raise ArgumentError, "entity must be a Hash" unless entity.is_a?(Hash)
|
|
38
|
+
raise ArgumentError, "entity[:type] is required" unless entity[:type]
|
|
39
|
+
|
|
40
|
+
type = entity[:type]
|
|
41
|
+
unless VALID_ENTITY_TYPES.include?(type)
|
|
42
|
+
raise ArgumentError, "entity[:type] must be one of: #{VALID_ENTITY_TYPES.join(', ')}"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
if type == "custom"
|
|
46
|
+
raise ArgumentError, "entity[:description] is required for custom entity type" unless entity[:description]
|
|
47
|
+
validate_string_length!(entity[:description], "entity[:description]", min: 2, max: 200)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def validate_criteria!(criteria)
|
|
52
|
+
raise ArgumentError, "criteria must be an Array" unless criteria.is_a?(Array)
|
|
53
|
+
raise ArgumentError, "criteria must have at least 1 item" if criteria.empty?
|
|
54
|
+
raise ArgumentError, "criteria cannot have more than 5 items" if criteria.length > 5
|
|
55
|
+
|
|
56
|
+
criteria.each_with_index do |criterion, index|
|
|
57
|
+
raise ArgumentError, "criteria[#{index}] must be a Hash" unless criterion.is_a?(Hash)
|
|
58
|
+
raise ArgumentError, "criteria[#{index}][:description] is required" unless criterion[:description]
|
|
59
|
+
validate_string_length!(criterion[:description], "criteria[#{index}][:description]", min: 1, max: 1000)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def validate_scope!(scope)
|
|
64
|
+
raise ArgumentError, "scope must be an Array" unless scope.is_a?(Array)
|
|
65
|
+
|
|
66
|
+
scope.each_with_index do |item, index|
|
|
67
|
+
validate_source_reference!(item, "scope[#{index}]")
|
|
68
|
+
|
|
69
|
+
next unless item[:relationship]
|
|
70
|
+
|
|
71
|
+
rel = item[:relationship]
|
|
72
|
+
raise ArgumentError, "scope[#{index}][:relationship] must be a Hash" unless rel.is_a?(Hash)
|
|
73
|
+
raise ArgumentError, "scope[#{index}][:relationship][:definition] is required" unless rel[:definition]
|
|
74
|
+
raise ArgumentError, "scope[#{index}][:relationship][:limit] is required" unless rel[:limit]
|
|
75
|
+
|
|
76
|
+
limit = rel[:limit]
|
|
77
|
+
unless limit.is_a?(Integer) && limit >= 1 && limit <= 10
|
|
78
|
+
raise ArgumentError, "scope[#{index}][:relationship][:limit] must be an Integer between 1 and 10"
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def validate_exclude!(exclude)
|
|
84
|
+
raise ArgumentError, "exclude must be an Array" unless exclude.is_a?(Array)
|
|
85
|
+
|
|
86
|
+
exclude.each_with_index do |item, index|
|
|
87
|
+
validate_source_reference!(item, "exclude[#{index}]")
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def validate_behavior!(behavior)
|
|
92
|
+
unless VALID_BEHAVIORS.include?(behavior)
|
|
93
|
+
raise ArgumentError, "behavior must be one of: #{VALID_BEHAVIORS.join(', ')}"
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def validate_metadata!(metadata)
|
|
98
|
+
raise ArgumentError, "metadata must be a Hash" unless metadata.is_a?(Hash)
|
|
99
|
+
|
|
100
|
+
metadata.each do |key, value|
|
|
101
|
+
raise ArgumentError, "metadata values must be Strings" unless value.is_a?(String)
|
|
102
|
+
raise ArgumentError, "metadata value for '#{key}' cannot exceed 1000 characters" if value.length > 1000
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def validate_source_reference!(item, context)
|
|
107
|
+
raise ArgumentError, "#{context} must be a Hash" unless item.is_a?(Hash)
|
|
108
|
+
raise ArgumentError, "#{context}[:source] is required" unless item[:source]
|
|
109
|
+
raise ArgumentError, "#{context}[:id] is required" unless item[:id]
|
|
110
|
+
|
|
111
|
+
source = item[:source]
|
|
112
|
+
unless VALID_SOURCE_TYPES.include?(source)
|
|
113
|
+
raise ArgumentError, "#{context}[:source] must be one of: #{VALID_SOURCE_TYPES.join(', ')}"
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
raise ArgumentError, "#{context}[:id] must be a non-empty String" unless item[:id].is_a?(String) && !item[:id].empty?
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def validate_string_length!(value, name, min: nil, max: nil)
|
|
120
|
+
raise ArgumentError, "#{name} must be a String" unless value.is_a?(String)
|
|
121
|
+
raise ArgumentError, "#{name} must be at least #{min} characters" if min && value.length < min
|
|
122
|
+
raise ArgumentError, "#{name} cannot exceed #{max} characters" if max && value.length > max
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|