ask-notion 0.1.0 → 0.1.1
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/lib/ask/notion/client.rb +29 -7
- data/lib/ask/notion/version.rb +1 -1
- data/lib/ask/skills/notion.use_notion/SKILL.md +131 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 10fd8189426e5d6f0b2a48dceab879344e8875d6edd4d8e40a0c2b8926129047
|
|
4
|
+
data.tar.gz: dc4a9867f46503da940d6f1572c6b17a012478165ff373ef13b8c08d36425632
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 045c832fa42bc8b2e9e905210a8a50949458541343f192fd66f674c41d75f3621c1aae255ded8953afe4f06e6faa1b4008cc4ba15e534e8a8f6fe62da623253d
|
|
7
|
+
data.tar.gz: 9fd11d103a3267320d4f731bf180bfda4e0bb5b8cb7c03871634061ad83bc6e867e2685249af60672112a3dbd05ddfd26511fa42ef849a352baf53657ea16266
|
data/lib/ask/notion/client.rb
CHANGED
|
@@ -5,16 +5,22 @@ require "ask/auth"
|
|
|
5
5
|
|
|
6
6
|
module Ask
|
|
7
7
|
module Notion
|
|
8
|
+
# Default number of retries for transient failures.
|
|
9
|
+
DEFAULT_RETRIES = 3
|
|
10
|
+
|
|
8
11
|
# Returns an authenticated Notion API client configured for an AI agent.
|
|
9
12
|
#
|
|
10
13
|
# Resolves the Notion token via +Ask::Auth.resolve(:notion_token)+ and
|
|
11
|
-
# wraps the client in a proxy that converts
|
|
12
|
-
# into
|
|
14
|
+
# wraps the client in a proxy that converts authentication, timeout, and
|
|
15
|
+
# network errors into ask-rb equivalents.
|
|
13
16
|
#
|
|
14
17
|
# The client inherits default configuration from +Notion::Config+:
|
|
15
18
|
# - +token+: resolved via Ask::Auth
|
|
16
19
|
# - +logger+: default logger
|
|
17
20
|
#
|
|
21
|
+
# Retries transient failures (rate limits, server errors) up to
|
|
22
|
+
# {DEFAULT_RETRIES} times with exponential backoff.
|
|
23
|
+
#
|
|
18
24
|
# @example
|
|
19
25
|
# client = Ask::Notion.client
|
|
20
26
|
# client.database_query(database_id: "abc123")
|
|
@@ -28,17 +34,33 @@ module Ask
|
|
|
28
34
|
ClientProxy.new(::Notion::Client.new(token: token))
|
|
29
35
|
end
|
|
30
36
|
|
|
31
|
-
# Proxies method calls to a +::Notion::Client+, converting authentication
|
|
32
|
-
# errors into
|
|
37
|
+
# Proxies method calls to a +::Notion::Client+, converting authentication,
|
|
38
|
+
# timeout, and network errors into ask-rb exceptions with automatic retry
|
|
39
|
+
# for transient failures.
|
|
33
40
|
class ClientProxy < BasicObject
|
|
34
41
|
def initialize(client)
|
|
35
42
|
@client = client
|
|
36
43
|
end
|
|
37
44
|
|
|
38
45
|
def method_missing(name, ...)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
46
|
+
retries = 0
|
|
47
|
+
begin
|
|
48
|
+
@client.public_send(name, ...)
|
|
49
|
+
rescue ::Notion::Api::Errors::Unauthorized
|
|
50
|
+
::Kernel.raise ::Ask::Auth::InvalidCredential, :notion_token
|
|
51
|
+
rescue ::Notion::Api::Errors::TooManyRequests,
|
|
52
|
+
::Notion::Api::Errors::UnavailableError,
|
|
53
|
+
::Notion::Api::Errors::ServerError,
|
|
54
|
+
::Timeout::Error,
|
|
55
|
+
::Errno::ECONNREFUSED,
|
|
56
|
+
::Errno::ECONNRESET
|
|
57
|
+
retries += 1
|
|
58
|
+
if retries <= ::Ask::Notion::DEFAULT_RETRIES
|
|
59
|
+
::Kernel.sleep(2 ** retries * 0.1)
|
|
60
|
+
retry
|
|
61
|
+
end
|
|
62
|
+
::Kernel.raise
|
|
63
|
+
end
|
|
42
64
|
end
|
|
43
65
|
|
|
44
66
|
def respond_to_missing?(name, include_private = false)
|
data/lib/ask/notion/version.rb
CHANGED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: notion.use_notion
|
|
3
|
+
description: How to navigate the Notion API with notion-ruby-client — discover endpoints, handle auth, pagination, and errors
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Use this skill when you need to interact with Notion — reading/writing pages and
|
|
7
|
+
databases, managing blocks, searching, or updating properties.
|
|
8
|
+
|
|
9
|
+
## Step 1: Get the Client
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
client = Ask::Notion.client
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
This returns an authenticated `Notion::Client`. It expects a valid Notion
|
|
16
|
+
Internal Integration Token resolved via `Ask::Auth.resolve(:notion_token)`.
|
|
17
|
+
|
|
18
|
+
If you get an auth error, read `Ask::Notion::Context::AUTH_HOW` for token setup.
|
|
19
|
+
|
|
20
|
+
## Step 2: Explore the Context
|
|
21
|
+
|
|
22
|
+
The gem ships with structured context you should reference:
|
|
23
|
+
|
|
24
|
+
```ruby
|
|
25
|
+
Ask::Notion::Context::DOCS_URL # Notion developer docs
|
|
26
|
+
Ask::Notion::Context::API_REF_URL # Notion API reference
|
|
27
|
+
Ask::Notion::Context::GEM_DOCS # notion-ruby-client docs
|
|
28
|
+
Ask::Notion::Context::QUICK_START # Copy-paste examples
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The `QUICK_START` constant has examples for database queries, page CRUD, block
|
|
32
|
+
children, and search.
|
|
33
|
+
|
|
34
|
+
## Step 3: Discover Available Methods
|
|
35
|
+
|
|
36
|
+
Use code tools to explore the available client methods:
|
|
37
|
+
|
|
38
|
+
```ruby
|
|
39
|
+
Code.new.call(code: "
|
|
40
|
+
client = Ask::Notion.client
|
|
41
|
+
puts client.methods(false).sort.join(\"\\n\")
|
|
42
|
+
")
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Common Notion API calls:
|
|
46
|
+
- `client.database_query(database_id:, filter:, sorts:)` — query a database
|
|
47
|
+
- `client.database_retrieve(database_id:)` — get database schema
|
|
48
|
+
- `client.page_retrieve(page_id:)` — read a page
|
|
49
|
+
- `client.page_create(parent:, properties:)` — create a page
|
|
50
|
+
- `client.page_update(page_id:, properties:)` — update page properties
|
|
51
|
+
- `client.block_children_list(block_id:)` — list page blocks
|
|
52
|
+
- `client.append_block_children(block_id:, children:)` — add blocks
|
|
53
|
+
- `client.search(query:)` — search across pages and databases
|
|
54
|
+
|
|
55
|
+
For method details, read the client source:
|
|
56
|
+
```ruby
|
|
57
|
+
Grep.new.call(pattern: "def database_query", path: "$GEM_PATH/notion-ruby-client-*/lib")
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Step 4: Property Formatting (Most Common Pitfall)
|
|
61
|
+
|
|
62
|
+
Notion properties are complex. Before creating or updating, always check the
|
|
63
|
+
database schema first:
|
|
64
|
+
|
|
65
|
+
```ruby
|
|
66
|
+
db = client.database_retrieve(database_id: "YOUR_DB_ID")
|
|
67
|
+
db.properties.each do |name, prop|
|
|
68
|
+
puts "#{name}: #{prop.type}"
|
|
69
|
+
end
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Property values follow this format pattern:
|
|
73
|
+
```ruby
|
|
74
|
+
{
|
|
75
|
+
"Name": { title: [{ text: { content: "Page Title" } }] },
|
|
76
|
+
"Status": { status: { name: "Done" } },
|
|
77
|
+
"Date": { date: { start: "2026-01-01" } },
|
|
78
|
+
"Select": { select: { name: "Option" } },
|
|
79
|
+
"Multi-select": { multi_select: [{ name: "Tag1" }] },
|
|
80
|
+
"Number": { number: 42 },
|
|
81
|
+
"Checkbox": { checkbox: true },
|
|
82
|
+
"Email": { email: "user@example.com" },
|
|
83
|
+
"URL": { url: "https://example.com" },
|
|
84
|
+
"Relation": { relation: [{ id: "RELATED_PAGE_ID" }] }
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The `notion-ruby-client` gem does minimal conversion — you pass raw hashes.
|
|
89
|
+
For reference, see `Ask::Notion::Context::API_REF_URL`.
|
|
90
|
+
|
|
91
|
+
## Step 5: Authentication & Common Errors
|
|
92
|
+
|
|
93
|
+
For detailed error guidance, use:
|
|
94
|
+
|
|
95
|
+
```ruby
|
|
96
|
+
Ask::Notion::Errors.for("Notion::Api::Errors::Forbidden")
|
|
97
|
+
Ask::Notion::Errors.status_code_description(403)
|
|
98
|
+
Ask::Notion::Errors::PAGINATION
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Common scenarios:
|
|
102
|
+
- **403 Forbidden**: Integration hasn't been shared with the page/database →
|
|
103
|
+
click "Share" in Notion and add your integration by name
|
|
104
|
+
- **404 Not Found**: Wrong ID or not shared → verify the page ID and sharing
|
|
105
|
+
- **400 Bad Request**: Property values have wrong types → check the schema first
|
|
106
|
+
- **429 Too Many Requests**: Rate limited (3 req/s burst, 90 req/min)
|
|
107
|
+
|
|
108
|
+
## Step 6: Pagination
|
|
109
|
+
|
|
110
|
+
Notion uses cursor-based pagination. The `notion-ruby-client` gem accepts
|
|
111
|
+
a block to auto-paginate:
|
|
112
|
+
|
|
113
|
+
```ruby
|
|
114
|
+
client.database_query(database_id: "DB_ID") do |page|
|
|
115
|
+
puts page.results.map { |r| r.id }
|
|
116
|
+
end
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Or manual pagination:
|
|
120
|
+
```ruby
|
|
121
|
+
response = client.database_query(database_id: "DB_ID", start_cursor: cursor, page_size: 100)
|
|
122
|
+
cursor = response.next_cursor
|
|
123
|
+
# Pass cursor as start_cursor in next request
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Step 7: Fallback Strategy
|
|
127
|
+
|
|
128
|
+
If the client doesn't have a method for what you need:
|
|
129
|
+
1. Check `Ask::Notion::Context::DOCS_URL` for the API endpoint
|
|
130
|
+
2. Notion's API is a REST API — you can use Faraday for any endpoint
|
|
131
|
+
3. Use `client.request(method:, path:, body:)` for custom requests
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ask-notion
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kaka Ruto
|
|
@@ -95,6 +95,7 @@ files:
|
|
|
95
95
|
- lib/ask/notion/context.rb
|
|
96
96
|
- lib/ask/notion/error_guide.rb
|
|
97
97
|
- lib/ask/notion/version.rb
|
|
98
|
+
- lib/ask/skills/notion.use_notion/SKILL.md
|
|
98
99
|
homepage: https://github.com/ask-rb/ask-notion
|
|
99
100
|
licenses:
|
|
100
101
|
- MIT
|