meilisearch-rails 0.5.1 → 0.7.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/Gemfile +5 -6
- data/LICENSE +1 -1
- data/README.md +31 -38
- data/lib/meilisearch/rails/version.rb +1 -1
- data/lib/meilisearch-rails.rb +22 -14
- data/meilisearch-rails.gemspec +11 -9
- metadata +7 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7b992f0ae920706899ea36534585a605e0ce7dcee087bcb5aa5a1fa7f29fbede
|
4
|
+
data.tar.gz: 7d4339178919b50b791f129485dc20646fb7122910073f99a469ef15e3da7452
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 202e76dd8aa69ee7440698ac6af2cff4d2b80016f50f39da95c24f40a824f2095a8481b1f6db64d95d07428d406739fa04513c8efa0ee29d0bbe95a6d77f7183
|
7
|
+
data.tar.gz: eba66cf0d9a4a5059c40325e8b848478a0268d3650d8f0aacc41598d68c555f6f793d56c19456f79ed08b08fd748a7a1474b2621cd9b211a7dd1c27502fb685c
|
data/Gemfile
CHANGED
@@ -1,14 +1,13 @@
|
|
1
|
-
source '
|
1
|
+
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
|
4
|
-
gem 'meilisearch', '~> 0.18.0'
|
3
|
+
gemspec
|
5
4
|
|
6
5
|
gem 'rubysl', '~> 2.0', platform: :rbx if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
|
7
6
|
|
8
7
|
group :development do
|
9
|
-
gem 'rubocop', '
|
10
|
-
gem 'rubocop-rails'
|
11
|
-
gem 'rubocop-rspec'
|
8
|
+
gem 'rubocop', '1.27.0'
|
9
|
+
gem 'rubocop-rails', '2.13.2'
|
10
|
+
gem 'rubocop-rspec', '2.9.0'
|
12
11
|
end
|
13
12
|
|
14
13
|
group :test do
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -58,7 +58,7 @@ To learn more about Meilisearch, check out our [Documentation](https://docs.meil
|
|
58
58
|
|
59
59
|
## 🤖 Compatibility with Meilisearch
|
60
60
|
|
61
|
-
This package only guarantees the compatibility with the [version v0.
|
61
|
+
This package only guarantees the compatibility with the [version v0.28.0 of Meilisearch](https://github.com/meilisearch/meilisearch/releases/tag/v0.28.0).
|
62
62
|
|
63
63
|
## 🔧 Installation <!-- omit in toc -->
|
64
64
|
|
@@ -84,7 +84,7 @@ For example, if you use Docker:
|
|
84
84
|
|
85
85
|
```bash
|
86
86
|
docker pull getmeili/meilisearch:latest # Fetch the latest version of Meilisearch image from Docker Hub
|
87
|
-
docker run -it --rm -p 7700:7700 getmeili/meilisearch:latest
|
87
|
+
docker run -it --rm -p 7700:7700 getmeili/meilisearch:latest meilisearch --master-key=masterKey
|
88
88
|
```
|
89
89
|
|
90
90
|
NB: you can also download Meilisearch from **Homebrew** or **APT**.
|
@@ -170,10 +170,10 @@ Then, as soon as you use the `search` method, the returning results will be pagi
|
|
170
170
|
<%= will_paginate @hits %> # if using will_paginate
|
171
171
|
```
|
172
172
|
|
173
|
-
The **number of hits per page defaults to 20**, you can customize it by adding the `
|
173
|
+
The **number of hits per page defaults to 20**, you can customize it by adding the `hits_per_page` parameter to your search:
|
174
174
|
|
175
175
|
```ruby
|
176
|
-
Book.search('harry potter',
|
176
|
+
Book.search('harry potter', hits_per_page: 10)
|
177
177
|
```
|
178
178
|
|
179
179
|
#### Extra Configuration <!-- omit in toc -->
|
@@ -228,7 +228,7 @@ Check the dedicated section of the documentation, for more information on the [s
|
|
228
228
|
All the supported options are described in the [search parameters](https://docs.meilisearch.com/reference/features/search_parameters.html) section of the documentation.
|
229
229
|
|
230
230
|
```ruby
|
231
|
-
Book.search('Harry',
|
231
|
+
Book.search('Harry', attributes_to_highlight: ['*'])
|
232
232
|
```
|
233
233
|
👉 Don't forget that `attributes_to_highlight`, `attributes_to_crop`, and
|
234
234
|
`crop_length` can be set up in the `meilisearch` block of your model.
|
@@ -256,24 +256,24 @@ By default, the **index_uid** will be the class name, e.g. `Book`. You can custo
|
|
256
256
|
class Book < ActiveRecord::Base
|
257
257
|
include MeiliSearch::Rails
|
258
258
|
|
259
|
-
meilisearch index_uid: 'MyCustomUID'
|
260
|
-
end
|
259
|
+
meilisearch index_uid: 'MyCustomUID'
|
261
260
|
end
|
262
261
|
```
|
263
262
|
|
264
263
|
#### Index UID according to the environment <!-- omit in toc -->
|
265
264
|
|
266
|
-
You can suffix the index UID with the current Rails environment
|
265
|
+
You can suffix the index UID with the current Rails environment by setting it globally:
|
267
266
|
|
268
267
|
```ruby
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
end
|
268
|
+
MeiliSearch::Rails.configuration = {
|
269
|
+
meilisearch_host: 'YourMeilisearchHost',
|
270
|
+
meilisearch_api_key: 'YourMeilisearchAPIKey',
|
271
|
+
per_environment: true
|
272
|
+
}
|
275
273
|
```
|
276
274
|
|
275
|
+
This way your index UID will look like this `"Book_#{Rails.env}"`.
|
276
|
+
|
277
277
|
### Index configuration
|
278
278
|
|
279
279
|
#### Custom attribute definition
|
@@ -318,8 +318,7 @@ Note that the primary key must have a **unique value**.
|
|
318
318
|
class Book < ActiveRecord::Base
|
319
319
|
include MeiliSearch::Rails
|
320
320
|
|
321
|
-
meilisearch primary_key: 'ISBN'
|
322
|
-
end
|
321
|
+
meilisearch primary_key: 'ISBN'
|
323
322
|
end
|
324
323
|
```
|
325
324
|
#### Conditional indexing
|
@@ -331,8 +330,7 @@ As soon as you use those constraints, `add_documents` and `delete_documents` cal
|
|
331
330
|
class Book < ActiveRecord::Base
|
332
331
|
include MeiliSearch::Rails
|
333
332
|
|
334
|
-
meilisearch if: :published?, unless: :premium?
|
335
|
-
end
|
333
|
+
meilisearch if: :published?, unless: :premium?
|
336
334
|
|
337
335
|
def published?
|
338
336
|
# [...]
|
@@ -369,6 +367,7 @@ class Book < ActiveRecord::Base
|
|
369
367
|
end
|
370
368
|
|
371
369
|
private
|
370
|
+
|
372
371
|
def public?
|
373
372
|
released? && !premium?
|
374
373
|
end
|
@@ -383,10 +382,10 @@ You may want to share an index between several models. You'll need to ensure you
|
|
383
382
|
class Cat < ActiveRecord::Base
|
384
383
|
include MeiliSearch::Rails
|
385
384
|
|
386
|
-
meilisearch index_uid: 'Animals', primary_key: :ms_id
|
387
|
-
end
|
385
|
+
meilisearch index_uid: 'Animals', primary_key: :ms_id
|
388
386
|
|
389
387
|
private
|
388
|
+
|
390
389
|
def ms_id
|
391
390
|
"cat_#{primary_key}" # ensure the cats & dogs primary_keys are not conflicting
|
392
391
|
end
|
@@ -395,10 +394,10 @@ end
|
|
395
394
|
class Dog < ActiveRecord::Base
|
396
395
|
include MeiliSearch::Rails
|
397
396
|
|
398
|
-
meilisearch index_uid: 'Animals', primary_key: :ms_id
|
399
|
-
end
|
397
|
+
meilisearch index_uid: 'Animals', primary_key: :ms_id
|
400
398
|
|
401
399
|
private
|
400
|
+
|
402
401
|
def ms_id
|
403
402
|
"dog_#{primary_key}" # ensure the cats & dogs primary_keys are not conflicting
|
404
403
|
end
|
@@ -413,8 +412,7 @@ You can configure the auto-indexing & auto-removal process to use a queue to per
|
|
413
412
|
class Book < ActiveRecord::Base
|
414
413
|
include MeiliSearch::Rails
|
415
414
|
|
416
|
-
meilisearch enqueue: true
|
417
|
-
end
|
415
|
+
meilisearch enqueue: true # ActiveJob will be triggered using a `meilisearch` queue
|
418
416
|
end
|
419
417
|
```
|
420
418
|
|
@@ -458,16 +456,16 @@ With [**Sidekiq**](https://github.com/mperham/sidekiq):
|
|
458
456
|
class Book < ActiveRecord::Base
|
459
457
|
include MeiliSearch::Rails
|
460
458
|
|
461
|
-
meilisearch enqueue: :
|
459
|
+
meilisearch enqueue: :trigger_sidekiq_job do
|
462
460
|
attribute :title, :author, :description
|
463
461
|
end
|
464
462
|
|
465
|
-
def self.
|
466
|
-
|
463
|
+
def self.trigger_sidekiq_job(record, remove)
|
464
|
+
MySidekiqJob.perform_async(record.id, remove)
|
467
465
|
end
|
468
466
|
end
|
469
467
|
|
470
|
-
class
|
468
|
+
class MySidekiqJob
|
471
469
|
def perform(id, remove)
|
472
470
|
if remove
|
473
471
|
# The record has likely already been removed from your database so we cannot
|
@@ -586,8 +584,7 @@ You can strip all HTML tags from your attributes with the `sanitize` option.
|
|
586
584
|
class Book < ActiveRecord::Base
|
587
585
|
include MeiliSearch::Rails
|
588
586
|
|
589
|
-
meilisearch sanitize: true
|
590
|
-
end
|
587
|
+
meilisearch sanitize: true
|
591
588
|
end
|
592
589
|
```
|
593
590
|
|
@@ -599,8 +596,7 @@ You can force the UTF-8 encoding of all your attributes using the `force_utf8_en
|
|
599
596
|
class Book < ActiveRecord::Base
|
600
597
|
include MeiliSearch::Rails
|
601
598
|
|
602
|
-
meilisearch force_utf8_encoding: true
|
603
|
-
end
|
599
|
+
meilisearch force_utf8_encoding: true
|
604
600
|
end
|
605
601
|
```
|
606
602
|
|
@@ -652,8 +648,7 @@ class Book < ActiveRecord::Base
|
|
652
648
|
include MeiliSearch::Rails
|
653
649
|
|
654
650
|
# Only raise exceptions in development environment.
|
655
|
-
meilisearch raise_on_failure: Rails.env.development?
|
656
|
-
end
|
651
|
+
meilisearch raise_on_failure: Rails.env.development?
|
657
652
|
end
|
658
653
|
```
|
659
654
|
|
@@ -667,8 +662,7 @@ You can force indexing and removing to be synchronous by setting the following o
|
|
667
662
|
class Book < ActiveRecord::Base
|
668
663
|
include MeiliSearch::Rails
|
669
664
|
|
670
|
-
meilisearch synchronous: true
|
671
|
-
end
|
665
|
+
meilisearch synchronous: true
|
672
666
|
end
|
673
667
|
```
|
674
668
|
🚨 This is only recommended for testing purposes, the gem will call the `wait_for_task` method that will stop your code execution until the asynchronous task has been processed by MeilSearch.
|
@@ -681,8 +675,7 @@ You can disable auto-indexing and auto-removing setting the following options:
|
|
681
675
|
class Book < ActiveRecord::Base
|
682
676
|
include MeiliSearch::Rails
|
683
677
|
|
684
|
-
meilisearch auto_index: false, auto_remove: false
|
685
|
-
end
|
678
|
+
meilisearch auto_index: false, auto_remove: false
|
686
679
|
end
|
687
680
|
```
|
688
681
|
|
data/lib/meilisearch-rails.rb
CHANGED
@@ -105,7 +105,7 @@ module MeiliSearch
|
|
105
105
|
end
|
106
106
|
|
107
107
|
def sequel?(document)
|
108
|
-
defined?(::Sequel) && document.class < ::Sequel::Model
|
108
|
+
defined?(::Sequel::Model) && document.class < ::Sequel::Model
|
109
109
|
end
|
110
110
|
|
111
111
|
def active_record?(document)
|
@@ -282,7 +282,7 @@ module MeiliSearch
|
|
282
282
|
case method.to_s
|
283
283
|
when 'search'
|
284
284
|
# some attributes are required
|
285
|
-
{ 'hits' => [], 'hitsPerPage' => 0, 'page' => 0, '
|
285
|
+
{ 'hits' => [], 'hitsPerPage' => 0, 'page' => 0, 'facetDistribution' => {}, 'error' => e }
|
286
286
|
else
|
287
287
|
# empty answer
|
288
288
|
{ 'error' => e }
|
@@ -319,8 +319,12 @@ module MeiliSearch
|
|
319
319
|
|
320
320
|
attr_accessor :formatted
|
321
321
|
|
322
|
+
if options.key?(:per_environment)
|
323
|
+
raise BadConfiguration, ':per_environment option should be defined globally on MeiliSearch::Rails.configuration block.'
|
324
|
+
end
|
325
|
+
|
322
326
|
if options[:synchronous] == true
|
323
|
-
if defined?(::Sequel) && self < Sequel::Model
|
327
|
+
if defined?(::Sequel::Model) && self < Sequel::Model
|
324
328
|
class_eval do
|
325
329
|
copy_after_validation = instance_method(:after_validation)
|
326
330
|
define_method(:after_validation) do |*args|
|
@@ -352,7 +356,7 @@ module MeiliSearch
|
|
352
356
|
end
|
353
357
|
end
|
354
358
|
unless options[:auto_index] == false
|
355
|
-
if defined?(::Sequel) && self < Sequel::Model
|
359
|
+
if defined?(::Sequel::Model) && self < Sequel::Model
|
356
360
|
class_eval do
|
357
361
|
copy_after_validation = instance_method(:after_validation)
|
358
362
|
copy_before_save = instance_method(:before_save)
|
@@ -399,7 +403,7 @@ module MeiliSearch
|
|
399
403
|
end
|
400
404
|
end
|
401
405
|
unless options[:auto_remove] == false
|
402
|
-
if defined?(::Sequel) && self < Sequel::Model
|
406
|
+
if defined?(::Sequel::Model) && self < Sequel::Model
|
403
407
|
class_eval do
|
404
408
|
copy_after_destroy = instance_method(:after_destroy)
|
405
409
|
|
@@ -456,7 +460,7 @@ module MeiliSearch
|
|
456
460
|
end
|
457
461
|
last_task = index.add_documents(documents)
|
458
462
|
end
|
459
|
-
index.wait_for_task(last_task['
|
463
|
+
index.wait_for_task(last_task['taskUid']) if last_task && (synchronous || options[:synchronous])
|
460
464
|
end
|
461
465
|
nil
|
462
466
|
end
|
@@ -472,7 +476,7 @@ module MeiliSearch
|
|
472
476
|
|
473
477
|
index = SafeIndex.new(ms_index_uid(options), true, options)
|
474
478
|
task = index.update_settings(final_settings)
|
475
|
-
index.wait_for_task(task['
|
479
|
+
index.wait_for_task(task['taskUid']) if synchronous
|
476
480
|
end
|
477
481
|
end
|
478
482
|
|
@@ -482,7 +486,7 @@ module MeiliSearch
|
|
482
486
|
|
483
487
|
index = ms_ensure_init(options, settings)
|
484
488
|
task = index.add_documents(documents.map { |d| settings.get_attributes(d).merge ms_pk(options) => ms_primary_key_of(d, options) })
|
485
|
-
index.wait_for_task(task['
|
489
|
+
index.wait_for_task(task['taskUid']) if synchronous || options[:synchronous]
|
486
490
|
end
|
487
491
|
end
|
488
492
|
|
@@ -579,7 +583,7 @@ module MeiliSearch
|
|
579
583
|
end
|
580
584
|
|
581
585
|
def ms_facets_distribution
|
582
|
-
@ms_json['
|
586
|
+
@ms_json['facetDistribution']
|
583
587
|
end
|
584
588
|
|
585
589
|
private
|
@@ -601,8 +605,8 @@ module MeiliSearch
|
|
601
605
|
end
|
602
606
|
|
603
607
|
# Returns raw json hits as follows:
|
604
|
-
# {"hits"=>[{"id"=>"13", "href"=>"apple", "name"=>"iphone"}], "offset"=>0, "limit"=>|| 20, "
|
605
|
-
# "
|
608
|
+
# {"hits"=>[{"id"=>"13", "href"=>"apple", "name"=>"iphone"}], "offset"=>0, "limit"=>|| 20, "estimatedTotalHits"=>1,
|
609
|
+
# "processingTimeMs"=>0, "query"=>"iphone"}
|
606
610
|
json = ms_raw_search(query, params)
|
607
611
|
|
608
612
|
# Returns the ids of the hits: 13
|
@@ -653,8 +657,11 @@ module MeiliSearch
|
|
653
657
|
|
654
658
|
def ms_index_uid(options = nil)
|
655
659
|
options ||= meilisearch_options
|
660
|
+
global_options ||= MeiliSearch::Rails.configuration
|
661
|
+
|
656
662
|
name = options[:index_uid] || model_name.to_s.gsub('::', '_')
|
657
|
-
name = "#{name}_#{::Rails.env}" if
|
663
|
+
name = "#{name}_#{::Rails.env}" if global_options[:per_environment]
|
664
|
+
|
658
665
|
name
|
659
666
|
end
|
660
667
|
|
@@ -674,6 +681,7 @@ module MeiliSearch
|
|
674
681
|
[options[:if], options[:unless]].each do |condition|
|
675
682
|
case condition
|
676
683
|
when nil
|
684
|
+
return false
|
677
685
|
when String, Symbol
|
678
686
|
return true if ms_attribute_changed?(document, condition)
|
679
687
|
else
|
@@ -820,7 +828,7 @@ module MeiliSearch
|
|
820
828
|
def ms_find_in_batches(batch_size, &block)
|
821
829
|
if (defined?(::ActiveRecord) && ancestors.include?(::ActiveRecord::Base)) || respond_to?(:find_in_batches)
|
822
830
|
find_in_batches(batch_size: batch_size, &block)
|
823
|
-
elsif defined?(::Sequel) && self < Sequel::Model
|
831
|
+
elsif defined?(::Sequel::Model) && self < Sequel::Model
|
824
832
|
dataset.extension(:pagination).each_page(batch_size, &block)
|
825
833
|
else
|
826
834
|
# don't worry, mongoid has its own underlying cursor/streaming mechanism
|
@@ -902,7 +910,7 @@ module MeiliSearch
|
|
902
910
|
# ms_must_reindex flag is reset after every commit as part. If we must reindex at any point in
|
903
911
|
# a transaction, keep flag set until it is explicitly unset
|
904
912
|
@ms_must_reindex ||=
|
905
|
-
if defined?(::Sequel) && is_a?(Sequel::Model)
|
913
|
+
if defined?(::Sequel::Model) && is_a?(Sequel::Model)
|
906
914
|
new? || self.class.ms_must_reindex?(self)
|
907
915
|
else
|
908
916
|
new_record? || self.class.ms_must_reindex?(self)
|
data/meilisearch-rails.gemspec
CHANGED
@@ -1,19 +1,21 @@
|
|
1
|
-
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
2
3
|
|
3
|
-
require '
|
4
|
+
require 'meilisearch/rails/version'
|
4
5
|
|
5
6
|
Gem::Specification.new do |s|
|
6
7
|
s.name = 'meilisearch-rails'
|
7
8
|
s.version = MeiliSearch::Rails::VERSION
|
8
9
|
|
9
|
-
s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
|
10
10
|
s.authors = ['Meili']
|
11
|
-
s.description = 'Meilisearch integration for Ruby on Rails. See https://github.com/meilisearch/meilisearch'
|
12
11
|
s.email = 'bonjour@meilisearch.com'
|
13
|
-
|
14
|
-
s.
|
15
|
-
s.
|
12
|
+
|
13
|
+
s.description = 'Meilisearch integration for Ruby on Rails. See https://github.com/meilisearch/meilisearch'
|
14
|
+
s.homepage = 'https://github.com/meilisearch/meilisearch-rails'
|
16
15
|
s.summary = 'Meilisearch integration for Ruby on Rails.'
|
16
|
+
s.licenses = 'MIT'
|
17
|
+
|
18
|
+
s.require_paths = ['lib']
|
17
19
|
|
18
20
|
s.extra_rdoc_files = [
|
19
21
|
'LICENSE',
|
@@ -31,6 +33,6 @@ Gem::Specification.new do |s|
|
|
31
33
|
]
|
32
34
|
|
33
35
|
s.required_ruby_version = '>= 2.6.0'
|
34
|
-
|
35
|
-
s.add_dependency
|
36
|
+
|
37
|
+
s.add_dependency 'meilisearch', '~> 0.19'
|
36
38
|
end
|
metadata
CHANGED
@@ -1,43 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: meilisearch-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Meili
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-07-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: json
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 1.5.1
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: 1.5.1
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: meilisearch
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
30
16
|
requirements:
|
31
|
-
- - "
|
17
|
+
- - "~>"
|
32
18
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.
|
19
|
+
version: '0.19'
|
34
20
|
type: :runtime
|
35
21
|
prerelease: false
|
36
22
|
version_requirements: !ruby/object:Gem::Requirement
|
37
23
|
requirements:
|
38
|
-
- - "
|
24
|
+
- - "~>"
|
39
25
|
- !ruby/object:Gem::Version
|
40
|
-
version: 0.
|
26
|
+
version: '0.19'
|
41
27
|
description: Meilisearch integration for Ruby on Rails. See https://github.com/meilisearch/meilisearch
|
42
28
|
email: bonjour@meilisearch.com
|
43
29
|
executables: []
|
@@ -63,7 +49,7 @@ files:
|
|
63
49
|
- lib/meilisearch/rails/utilities.rb
|
64
50
|
- lib/meilisearch/rails/version.rb
|
65
51
|
- meilisearch-rails.gemspec
|
66
|
-
homepage:
|
52
|
+
homepage: https://github.com/meilisearch/meilisearch-rails
|
67
53
|
licenses:
|
68
54
|
- MIT
|
69
55
|
metadata: {}
|