notion_ruby_mapping 0.1.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.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +37 -0
  4. data/CHANGELOG.md +5 -0
  5. data/CODE_OF_CONDUCT.md +84 -0
  6. data/Gemfile +6 -0
  7. data/Guardfile +72 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +408 -0
  10. data/Rakefile +12 -0
  11. data/bin/console +15 -0
  12. data/bin/setup +8 -0
  13. data/lib/notion_ruby_mapping/base.rb +49 -0
  14. data/lib/notion_ruby_mapping/block.rb +10 -0
  15. data/lib/notion_ruby_mapping/checkbox_property.rb +9 -0
  16. data/lib/notion_ruby_mapping/created_by_property.rb +7 -0
  17. data/lib/notion_ruby_mapping/created_time_property.rb +7 -0
  18. data/lib/notion_ruby_mapping/database.rb +15 -0
  19. data/lib/notion_ruby_mapping/date_base_property.rb +73 -0
  20. data/lib/notion_ruby_mapping/date_property.rb +7 -0
  21. data/lib/notion_ruby_mapping/email_property.rb +7 -0
  22. data/lib/notion_ruby_mapping/files_property.rb +9 -0
  23. data/lib/notion_ruby_mapping/formula_property.rb +11 -0
  24. data/lib/notion_ruby_mapping/last_edited_by_property.rb +7 -0
  25. data/lib/notion_ruby_mapping/last_edited_time_property.rb +7 -0
  26. data/lib/notion_ruby_mapping/list.rb +16 -0
  27. data/lib/notion_ruby_mapping/multi_property.rb +9 -0
  28. data/lib/notion_ruby_mapping/multi_select_property.rb +8 -0
  29. data/lib/notion_ruby_mapping/notion_cache.rb +100 -0
  30. data/lib/notion_ruby_mapping/number_property.rb +11 -0
  31. data/lib/notion_ruby_mapping/page.rb +16 -0
  32. data/lib/notion_ruby_mapping/people_property.rb +7 -0
  33. data/lib/notion_ruby_mapping/phone_number_property.rb +7 -0
  34. data/lib/notion_ruby_mapping/property.rb +88 -0
  35. data/lib/notion_ruby_mapping/query.rb +50 -0
  36. data/lib/notion_ruby_mapping/relation_property.rb +8 -0
  37. data/lib/notion_ruby_mapping/rich_text_property.rb +7 -0
  38. data/lib/notion_ruby_mapping/select_property.rb +10 -0
  39. data/lib/notion_ruby_mapping/text_property.rb +11 -0
  40. data/lib/notion_ruby_mapping/title_property.rb +7 -0
  41. data/lib/notion_ruby_mapping/url_property.rb +7 -0
  42. data/lib/notion_ruby_mapping/version.rb +5 -0
  43. data/lib/notion_ruby_mapping.rb +9 -0
  44. data/notion_ruby_mapping.gemspec +47 -0
  45. data/sig/notion_ruby_mapping.rbs +4 -0
  46. metadata +171 -0
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionRubyMapping
4
+ # Notion Base object (Parent of Page / Database / List)
5
+ class Base
6
+ def initialize(json: nil, id: nil)
7
+ @nc = NotionCache.instance
8
+ @json = json
9
+ @id = @nc.hex_id(id || @json["id"])
10
+ end
11
+ attr_reader :json, :id
12
+
13
+ # @param [Object] json
14
+ # @return [NotionRubyMapping::Block, NotionRubyMapping::List, NotionRubyMapping::Database, NotionRubyMapping::Page]
15
+ def self.create_from_json(json)
16
+ case json["object"]
17
+ when "page"
18
+ Page.new json: json
19
+ when "database"
20
+ Database.new json: json
21
+ when "list"
22
+ List.new json: json
23
+ when "block"
24
+ Block.new json: json
25
+ else
26
+ throw Notion::Api::Errors::ObjectNotFound
27
+ end
28
+ end
29
+
30
+ # @return [NotionRubyMapping::List]
31
+ def children
32
+ @children ||= @nc.block_children(id)
33
+ end
34
+
35
+ def update_json(json)
36
+ if @json.nil? || @json["type"] == json["type"]
37
+ @json = json
38
+ clear_object
39
+ end
40
+ end
41
+
42
+ def clear_object
43
+ end
44
+
45
+ def icon
46
+ @json["icon"]
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionRubyMapping
4
+ # Notion block
5
+ class Block < Base
6
+ def self.find(key)
7
+ NotionCache.instance.block key
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionRubyMapping
4
+ # Checkbox property
5
+ class CheckboxProperty < Property
6
+ include EqualsDoesNotEqual
7
+ TYPE = :checkbox
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionRubyMapping
4
+ class CreatedByProperty < MultiProperty
5
+ TYPE = :created_by
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionRubyMapping
4
+ class CreatedTimeProperty < DateBaseProperty
5
+ TYPE = :created_time
6
+ end
7
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionRubyMapping
4
+ # Notion database
5
+ class Database < Base
6
+ def self.find(key)
7
+ NotionCache.instance.database key
8
+ end
9
+
10
+ def self.query(id, query = nil)
11
+ query ||= Query.new
12
+ NotionCache.instance.database_query(id, query)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "date"
4
+
5
+ module NotionRubyMapping
6
+ # Date base property (date, created_time, last_edited_time)
7
+ class DateBaseProperty < Property
8
+ include IsEmptyIsNotEmpty
9
+
10
+ # @param [Date, Time, DateTime, String] obj
11
+ # @return [String] iso8601 format string
12
+ def value_str(obj)
13
+ case obj
14
+ when Date
15
+ obj.iso8601
16
+ when Time
17
+ obj.strftime("%Y-%m-%dT%H:%M:%S%:z")
18
+ when DateTime
19
+ obj.iso8601
20
+ else
21
+ obj
22
+ end
23
+ end
24
+
25
+ def filter_equals(value)
26
+ make_filter_query :equals, value_str(value)
27
+ end
28
+
29
+ def filter_does_not_equal(value)
30
+ make_filter_query :does_not_equal, value_str(value)
31
+ end
32
+
33
+ def filter_before(value)
34
+ make_filter_query :before, value_str(value)
35
+ end
36
+
37
+ def filter_after(value)
38
+ make_filter_query :after, value_str(value)
39
+ end
40
+
41
+ def filter_on_or_before(value)
42
+ make_filter_query :on_or_before, value_str(value)
43
+ end
44
+
45
+ def filter_on_or_after(value)
46
+ make_filter_query :on_or_after, value_str(value)
47
+ end
48
+
49
+ def filter_past_week
50
+ make_filter_query :past_week, {}
51
+ end
52
+
53
+ def filter_past_month
54
+ make_filter_query :past_month, {}
55
+ end
56
+
57
+ def filter_past_year
58
+ make_filter_query :past_year, {}
59
+ end
60
+
61
+ def filter_next_week
62
+ make_filter_query :next_week, {}
63
+ end
64
+
65
+ def filter_next_month
66
+ make_filter_query :next_month, {}
67
+ end
68
+
69
+ def filter_next_year
70
+ make_filter_query :next_year, {}
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionRubyMapping
4
+ class DateProperty < DateBaseProperty
5
+ TYPE = :date
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionRubyMapping
4
+ class EmailProperty < TextProperty
5
+ TYPE = :email
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionRubyMapping
4
+ # Select property
5
+ class FilesProperty < Property
6
+ include IsEmptyIsNotEmpty
7
+ TYPE = :files
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionRubyMapping
4
+ # Formula property
5
+ class FormulaProperty < DateBaseProperty
6
+ include ContainsDoesNotContain
7
+ include StartsWithEndsWith
8
+ include GreaterThanLessThan
9
+ TYPE = :formula
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionRubyMapping
4
+ class LastEditedByProperty < MultiProperty
5
+ TYPE = :last_edited_by
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionRubyMapping
4
+ class LastEditedTimeProperty < DateBaseProperty
5
+ TYPE = :last_edited_time
6
+ end
7
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionRubyMapping
4
+ # Notion List object
5
+ class List < Base
6
+ include Enumerable
7
+
8
+ def each
9
+ return enum_for(:each) unless block_given?
10
+
11
+ json["results"].each do |block_json|
12
+ yield Base.create_from_json(block_json)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionRubyMapping
4
+ # MultiSelect property
5
+ class MultiProperty < Property
6
+ include ContainsDoesNotContain
7
+ include IsEmptyIsNotEmpty
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionRubyMapping
4
+ # MultiSelect property
5
+ class MultiSelectProperty < MultiProperty
6
+ TYPE = :multi_select
7
+ end
8
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "singleton"
4
+ require "notion"
5
+
6
+ module NotionRubyMapping
7
+ # singleton class of caching Notion objects
8
+ class NotionCache
9
+ include Singleton
10
+
11
+ def initialize
12
+ @object_hash = {}
13
+ @client = nil
14
+ @wait = 0
15
+ end
16
+ attr_reader :object_hash, :client
17
+ attr_accessor :use_cache
18
+
19
+ # @param [String] notion_token
20
+ # @return [NotionRubyMapping::NotionCache] self (NotionCache.instance)
21
+ def create_client(notion_token, wait = 0.3333)
22
+ @client ||= Notion::Client.new token: notion_token
23
+ @wait = wait
24
+ self
25
+ end
26
+
27
+ # @param [String] id id string with "-"
28
+ # @return [String] id without "-"
29
+ def hex_id(id)
30
+ id&.gsub "-", ""
31
+ end
32
+
33
+ # @param [String] id id (with or without "-")
34
+ # @return [NotionRubyMapping::Block, NotionRubyMapping::List, NotionRubyMapping::Database, NotionRubyMapping::Page, nil]
35
+ def object_for_key(id)
36
+ key = hex_id(id)
37
+ return @object_hash[key] if @object_hash.key? key
38
+
39
+ begin
40
+ json = yield(@client)
41
+ p json
42
+ @object_hash[key] = Base.create_from_json json
43
+ rescue StandardError
44
+ nil
45
+ end
46
+ end
47
+
48
+ # @param [String] id
49
+ # @return [NotionRubyMapping::Page, nil] Page object or nil
50
+ def page(id)
51
+ object_for_key(id) do
52
+ sleep @wait
53
+ @client.page page_id: id
54
+ end
55
+ end
56
+
57
+ # @param [String] id
58
+ # @return [NotionRubyMapping::Database, nil] Database object or nil
59
+ def database(id)
60
+ object_for_key(id) do
61
+ sleep @wait
62
+ @client.database database_id: id
63
+ end
64
+ end
65
+
66
+ # @param [String] id
67
+ # @return [NotionRubyMapping::Block, nil]
68
+ def block(id)
69
+ object_for_key(id) do
70
+ sleep @wait
71
+ @client.block block_id: id
72
+ end
73
+ end
74
+
75
+ def block_children(id)
76
+ array = []
77
+ sleep @wait
78
+ @client.block_children(block_id: id, sleep_interval: @wait, max_retries: 20) do |page|
79
+ array.concat page.results
80
+ end
81
+ Base.create_from_json({"object" => "list", "results" => array})
82
+ end
83
+
84
+ def database_query(id, query)
85
+ array = []
86
+ parameters = {database_id: id, sleep_interval: @wait, max_retries: 20}
87
+ parameters[:filter] = query.filter unless query.filter.empty?
88
+ parameters[:sort] = query.sort unless query.sort.empty?
89
+ @client.database_query(**parameters) do |page|
90
+ array.concat page.results
91
+ end
92
+ Base.create_from_json({"object" => "list", "results" => array})
93
+ end
94
+
95
+ def update_page(id, payload)
96
+ sleep @wait
97
+ @client.update_page payload.merge({page_id: id})
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionRubyMapping
4
+ # Number property
5
+ class NumberProperty < Property
6
+ include EqualsDoesNotEqual
7
+ include GreaterThanLessThan
8
+ include IsEmptyIsNotEmpty
9
+ TYPE = :number
10
+ end
11
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionRubyMapping
4
+ # Notion page object
5
+ class Page < Base
6
+ def self.find(key)
7
+ NotionCache.instance.page key
8
+ end
9
+
10
+ def set_icon(emoji: nil, url: nil)
11
+ payload = emoji ? {type: :emoji, emoji: emoji} : {type: :external, external: {url: url}}
12
+ update_json @nc.update_page(id, {icon: payload})
13
+ self
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionRubyMapping
4
+ class PeopleProperty < MultiProperty
5
+ TYPE = :people
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionRubyMapping
4
+ class PhoneNumberProperty < TextProperty
5
+ TYPE = :phone_number
6
+ end
7
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionRubyMapping
4
+ # abstract class for property
5
+ class Property
6
+ def initialize(name)
7
+ @name = name
8
+ end
9
+ attr_reader :name
10
+
11
+ # @param [Symbol] key query parameter
12
+ # @param [Object] value query value
13
+ # @return [NotionRubyMapping::Query] generated Query object
14
+ def make_filter_query(key, value)
15
+ Query.new(filter: {property: @name, type => {key => value}})
16
+ end
17
+
18
+ # @return [Symbol] property type
19
+ def type
20
+ self.class::TYPE
21
+ end
22
+ end
23
+
24
+ # module for make query of equals and does_not_equal
25
+ module EqualsDoesNotEqual
26
+ # @param [String, Number] value
27
+ # @return [Object]
28
+ def filter_equals(value)
29
+ make_filter_query :equals, value
30
+ end
31
+
32
+ def filter_does_not_equal(value)
33
+ make_filter_query :does_not_equal, value
34
+ end
35
+ end
36
+
37
+ # module for make query of contains and does_not_contain
38
+ module ContainsDoesNotContain
39
+ def filter_contains(value)
40
+ make_filter_query :contains, value
41
+ end
42
+
43
+ def filter_does_not_contain(value)
44
+ make_filter_query :does_not_contain, value
45
+ end
46
+ end
47
+
48
+ # module for make query of starts_with and ends_with
49
+ module StartsWithEndsWith
50
+ def filter_starts_with(value)
51
+ make_filter_query :starts_with, value
52
+ end
53
+
54
+ def filter_ends_with(value)
55
+ make_filter_query :ends_with, value
56
+ end
57
+ end
58
+
59
+ # module for make query of is_empty and is_not_empty
60
+ module IsEmptyIsNotEmpty
61
+ def filter_is_empty
62
+ make_filter_query :is_empty, true
63
+ end
64
+
65
+ def filter_is_not_empty
66
+ make_filter_query :is_not_empty, true
67
+ end
68
+ end
69
+
70
+ # module for make query of starts_with and ends_with
71
+ module GreaterThanLessThan
72
+ def filter_greater_than(value)
73
+ make_filter_query :greater_than, value
74
+ end
75
+
76
+ def filter_less_than(value)
77
+ make_filter_query :less_than, value
78
+ end
79
+
80
+ def filter_greater_than_or_equal_to(value)
81
+ make_filter_query :greater_than_or_equal_to, value
82
+ end
83
+
84
+ def filter_less_than_or_equal_to(value)
85
+ make_filter_query :less_than_or_equal_to, value
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionRubyMapping
4
+ # Query object
5
+ class Query
6
+ def initialize(filter: {}, sort: [])
7
+ @filter = filter
8
+ @sort = sort
9
+ end
10
+ attr_reader :filter, :sort
11
+
12
+ # @param [Query] other_query other query
13
+ # @return [NotionRubyMapping::Query] updated self (Query object)
14
+ def and(other_query)
15
+ if @filter.key? :and
16
+ @filter[:and] << other_query.filter
17
+ else
18
+ @filter = {and: [@filter, other_query.filter]}
19
+ end
20
+ self
21
+ end
22
+
23
+ # @param [Query] other_query other query
24
+ # @return [NotionRubyMapping::Query] updated self (Query object)
25
+ def or(other_query)
26
+ if @filter.key? :or
27
+ @filter[:or] << other_query.filter
28
+ else
29
+ @filter = {or: [@filter, other_query.filter]}
30
+ end
31
+ self
32
+ end
33
+
34
+ # @param [NotionRubyMapping::Property] property
35
+ # @return [NotionRubyMapping::Query] updated self (Query object)
36
+ def ascending(property)
37
+ key = property.is_a?(LastEditedTimeProperty) || property.is_a?(CreatedTimeProperty) ? :timestamp : :property
38
+ @sort << {key => property.name, direction: "ascending"}
39
+ self
40
+ end
41
+
42
+ # @param [NotionRubyMapping::Property] property
43
+ # @return [NotionRubyMapping::Query] updated self (Query object)
44
+ def descending(property)
45
+ key = property.is_a?(LastEditedTimeProperty) || property.is_a?(CreatedTimeProperty) ? :timestamp : :property
46
+ @sort << {key => property.name, direction: "descending"}
47
+ self
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionRubyMapping
4
+ # MultiSelect property
5
+ class RelationProperty < MultiProperty
6
+ TYPE = :relation
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionRubyMapping
4
+ class RichTextProperty < TextProperty
5
+ TYPE = :rich_text
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionRubyMapping
4
+ # Select property
5
+ class SelectProperty < Property
6
+ include EqualsDoesNotEqual
7
+ include IsEmptyIsNotEmpty
8
+ TYPE = :select
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionRubyMapping
4
+ # Text property
5
+ class TextProperty < Property
6
+ include EqualsDoesNotEqual
7
+ include ContainsDoesNotContain
8
+ include StartsWithEndsWith
9
+ include IsEmptyIsNotEmpty
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionRubyMapping
4
+ class TitleProperty < TextProperty
5
+ TYPE = :title
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionRubyMapping
4
+ class UrlProperty < TextProperty
5
+ TYPE = :url
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NotionRubyMapping
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ %w[version notion_cache base page database list block property text_property title_property rich_text_property
4
+ url_property email_property phone_number_property number_property checkbox_property select_property
5
+ multi_property multi_select_property date_base_property date_property created_time_property last_edited_time_property
6
+ people_property created_by_property last_edited_by_property files_property relation_property formula_property
7
+ query].each do |k|
8
+ require_relative "notion_ruby_mapping/#{k}"
9
+ end