lcp-sdk 1.0.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 +13 -0
- data/lib/generated_models.rb +13 -0
- data/lib/lcp_sdk.rb +94 -0
- data/lib/schema-bundle.json +3230 -0
- data/lib/schema_validator.rb +82 -0
- metadata +70 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
|
|
5
|
+
module LcpSdk
|
|
6
|
+
class SchemaValidationError < StandardError; end
|
|
7
|
+
|
|
8
|
+
class SchemaValidator
|
|
9
|
+
def initialize(schema_documents)
|
|
10
|
+
require "json_schemer"
|
|
11
|
+
# Keep a private copy so self-references in core.json can be made
|
|
12
|
+
# fragment-local without mutating the caller's canonical documents.
|
|
13
|
+
@documents = schema_documents.transform_values do |document|
|
|
14
|
+
JSON.parse(JSON.generate(document))
|
|
15
|
+
end
|
|
16
|
+
@documents.each_value do |document|
|
|
17
|
+
rewrite_core_refs(document) if document["$id"] == "https://lcp.dev/schemas/core.json"
|
|
18
|
+
end
|
|
19
|
+
@ids = {}
|
|
20
|
+
@documents.each do |name, document|
|
|
21
|
+
id = document.fetch("$id", name)
|
|
22
|
+
@ids[normalize(name)] = id
|
|
23
|
+
@ids[normalize(id)] = id
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def self.from_directory(root)
|
|
28
|
+
documents = {}
|
|
29
|
+
Dir.glob(File.join(root, "**", "*.json")).each do |path|
|
|
30
|
+
name = path.delete_prefix("#{root}/")
|
|
31
|
+
documents[name] = JSON.parse(File.read(path))
|
|
32
|
+
end
|
|
33
|
+
new(documents)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def validate(schema_name, instance)
|
|
37
|
+
id = @ids.fetch(normalize(schema_name)) { raise KeyError, "unknown LCP schema: #{schema_name}" }
|
|
38
|
+
schema = @documents.values.find { |candidate| candidate["$id"] == id } || @documents.fetch(schema_name)
|
|
39
|
+
errors = JSONSchemer.schema(schema, ref_resolver: lambda do |uri|
|
|
40
|
+
reference = uri.to_s
|
|
41
|
+
@documents.values.find { |candidate| candidate["$id"].to_s == reference } ||
|
|
42
|
+
@documents[reference] ||
|
|
43
|
+
@documents[reference.sub(%r{.*/}, "")]
|
|
44
|
+
end).validate(instance).to_a
|
|
45
|
+
raise SchemaValidationError, "LCP schema validation failed for #{schema_name}: #{errors.first}" unless errors.empty?
|
|
46
|
+
true
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def validate_envelope(envelope)
|
|
50
|
+
validate("schemas/envelope.json", envelope)
|
|
51
|
+
type = envelope.dig("lcp", "message", "type")
|
|
52
|
+
raise SchemaValidationError, "missing lcp.message.type" unless type.is_a?(String)
|
|
53
|
+
validate("schemas/#{type}.json", envelope.dig("lcp", "payload"))
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def validate_offer(offer)
|
|
57
|
+
validate("schemas/offer.json", offer)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def validate_vertical(vertical, attributes)
|
|
61
|
+
validate("verticals/#{vertical}.json", attributes)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
private
|
|
65
|
+
|
|
66
|
+
def rewrite_core_refs(value)
|
|
67
|
+
case value
|
|
68
|
+
when Hash
|
|
69
|
+
if value["$ref"].is_a?(String)
|
|
70
|
+
value["$ref"] = value["$ref"].sub(/\Acore\.json(?=#)/, "")
|
|
71
|
+
end
|
|
72
|
+
value.each_value { |child| rewrite_core_refs(child) }
|
|
73
|
+
when Array
|
|
74
|
+
value.each { |child| rewrite_core_refs(child) }
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def normalize(name)
|
|
79
|
+
name.to_s.tr("\\", "/").sub(%r{^/}, "").sub(%r{^(schemas|verticals)/}, "").sub(/\.json$/, "")
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: lcp-sdk
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Spear Systems
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: json_schemer
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '2.5'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '2.5'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: rake
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '13.0'
|
|
33
|
+
type: :development
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '13.0'
|
|
40
|
+
description: Signing, envelopes, webhooks, and HTTP helpers for LCP.
|
|
41
|
+
executables: []
|
|
42
|
+
extensions: []
|
|
43
|
+
extra_rdoc_files: []
|
|
44
|
+
files:
|
|
45
|
+
- README.md
|
|
46
|
+
- lib/generated_models.rb
|
|
47
|
+
- lib/lcp_sdk.rb
|
|
48
|
+
- lib/schema-bundle.json
|
|
49
|
+
- lib/schema_validator.rb
|
|
50
|
+
licenses:
|
|
51
|
+
- Apache-2.0
|
|
52
|
+
metadata: {}
|
|
53
|
+
rdoc_options: []
|
|
54
|
+
require_paths:
|
|
55
|
+
- lib
|
|
56
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '3.0'
|
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
62
|
+
requirements:
|
|
63
|
+
- - ">="
|
|
64
|
+
- !ruby/object:Gem::Version
|
|
65
|
+
version: '0'
|
|
66
|
+
requirements: []
|
|
67
|
+
rubygems_version: 4.0.16
|
|
68
|
+
specification_version: 4
|
|
69
|
+
summary: LCP Lead Context Protocol SDK
|
|
70
|
+
test_files: []
|