@elumixor/notion-orm 0.1.1 → 2.0.2
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.
- package/README.md +112 -210
- package/dist/ast/constants.d.ts +12 -13
- package/dist/cli.js +5409 -2038
- package/dist/config/helpers.d.ts +3 -1
- package/dist/db-client/add.d.ts +1 -1
- package/dist/db-client/client.d.ts +169 -0
- package/dist/db-client/query.d.ts +2 -2
- package/dist/db-client/{queryTypes.d.ts → types.d.ts} +25 -8
- package/dist/index.js +168 -94
- package/dist/public-api.d.ts +2 -2
- package/package.json +2 -1
- package/dist/db-client/DatabaseClient.d.ts +0 -47
package/README.md
CHANGED
|
@@ -1,267 +1,169 @@
|
|
|
1
|
-
#
|
|
1
|
+
# notion-orm
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
A library to simplify adding and querying [Notion](https://notion.so/product) databases/tables. Giving typeahead/intellisense support on columns and expected column values on user specified databases. Built on top of [Notion API](https://developers.notion.com/)
|
|
6
|
-
|
|
7
|
-
Databases with the following column types are supported:
|
|
8
|
-
|
|
9
|
-
- Multi-select
|
|
10
|
-
- Select
|
|
11
|
-
- Status
|
|
12
|
-
- Date
|
|
13
|
-
- Text
|
|
14
|
-
- Url
|
|
15
|
-
- Checkbox
|
|
16
|
-
- Email
|
|
17
|
-
- Phone Number
|
|
3
|
+
TypeScript ORM for Notion databases. Generates fully-typed clients from your Notion schemas.
|
|
18
4
|
|
|
19
5
|
## Installation
|
|
20
6
|
|
|
21
|
-
The only requirement is a Notion Developer API key ([here](https://developers.notion.com/)) and database IDs you want. Be sure to connect your [integration](https://developers.notion.com/docs/working-with-databases#adding-pages-to-a-database) (🚧 *Permissions* section) with your tables
|
|
22
|
-
|
|
23
7
|
```bash
|
|
24
|
-
npm install @
|
|
8
|
+
npm install @elumixor/notion-orm
|
|
25
9
|
```
|
|
26
10
|
|
|
27
|
-
|
|
11
|
+
## Setup
|
|
12
|
+
|
|
13
|
+
**1. Initialize config**
|
|
28
14
|
|
|
29
15
|
```bash
|
|
30
|
-
|
|
31
|
-
# or
|
|
32
|
-
bun notion init
|
|
16
|
+
notion init
|
|
33
17
|
```
|
|
34
18
|
|
|
35
|
-
|
|
19
|
+
Creates `notion.config.ts` in your project root:
|
|
36
20
|
|
|
37
|
-
```
|
|
38
|
-
|
|
21
|
+
```ts
|
|
22
|
+
import type { NotionConfigType } from "@elumixor/notion-orm";
|
|
39
23
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
auth,
|
|
48
|
-
databaseIds: [
|
|
49
|
-
// Add undashed database source IDs here (ex. "2a3c495da03c80bc99fe000bbf2be4bb")
|
|
50
|
-
// or use the following command to automatically update
|
|
51
|
-
// `notion add <database-source-id or URL>`
|
|
52
|
-
// If you decide to manually add database IDs, be sure to run
|
|
53
|
-
// `notion generate` to properly update the local database types
|
|
54
|
-
],
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
export default NotionConfig;
|
|
24
|
+
export default {
|
|
25
|
+
auth: process.env.NOTION_API_KEY ?? "",
|
|
26
|
+
databases: {
|
|
27
|
+
tasks: "your-notion-tasks-database-id",
|
|
28
|
+
people: "your-notion-people-database-id",
|
|
29
|
+
},
|
|
30
|
+
} satisfies NotionConfigType;
|
|
58
31
|
```
|
|
59
32
|
|
|
60
|
-
|
|
33
|
+
**2. Generate types**
|
|
61
34
|
|
|
62
35
|
```bash
|
|
63
|
-
|
|
36
|
+
notion generate
|
|
64
37
|
```
|
|
65
38
|
|
|
66
|
-
|
|
67
|
-
Unpackaged size is 70.6KB and the installation size is 5.12MB (5.03MB from `@notionhq/client` dependency)
|
|
39
|
+
Generates `generated/notion-orm/` with a typed client per database and an `index.ts` entry point.
|
|
68
40
|
|
|
69
|
-
|
|
41
|
+
**3. Use in your project**
|
|
70
42
|
|
|
71
|
-
|
|
43
|
+
```ts
|
|
44
|
+
import { NotionORM } from "../generated/notion-orm";
|
|
72
45
|
|
|
73
|
-
|
|
74
|
-
// Barrel Import (access to all databases)
|
|
75
|
-
import * as notion from "@haustle/notion-orm";
|
|
76
|
-
notion.databaseName.add();
|
|
77
|
-
notion.databaseName2.query();
|
|
78
|
-
```
|
|
46
|
+
const notion = new NotionORM(process.env.NOTION_API_KEY);
|
|
79
47
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
import {
|
|
83
|
-
databaseName,
|
|
84
|
-
DatabaseSchemaType,
|
|
85
|
-
QuerySchemaType,
|
|
86
|
-
} from "@haustle/notion-orm/build/db/databaseName";
|
|
87
|
-
|
|
88
|
-
databaseName.add();
|
|
48
|
+
// or with a config object
|
|
49
|
+
const notion = new NotionORM({ auth: process.env.NOTION_API_KEY });
|
|
89
50
|
```
|
|
90
51
|
|
|
91
|
-
|
|
92
|
-
- `QuerySchemaType`: Object type accepted in the database’s `query()` function
|
|
52
|
+
## API
|
|
93
53
|
|
|
94
|
-
|
|
54
|
+
All methods are fully typed based on your Notion schema.
|
|
95
55
|
|
|
96
|
-
|
|
56
|
+
### Reading
|
|
97
57
|
|
|
98
|
-
|
|
58
|
+
```ts
|
|
59
|
+
// All records
|
|
60
|
+
const tasks = await notion.tasks.findMany();
|
|
99
61
|
|
|
100
|
-
|
|
101
|
-
notion.
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
numberOfPages: 307, // number
|
|
106
|
-
genre: ["Historical Fiction"], // multi-select
|
|
107
|
-
rating: "⭐️⭐️⭐️⭐️", // select
|
|
108
|
-
startDate: {
|
|
109
|
-
// date
|
|
110
|
-
start: "2023-01-01",
|
|
111
|
-
},
|
|
112
|
-
phone: "0000000000", // phone
|
|
113
|
-
email: "tyrus@haustle.studio", // email
|
|
62
|
+
// With filter, sort, and limit
|
|
63
|
+
const tasks = await notion.tasks.findMany({
|
|
64
|
+
where: { status: { equals: "In Progress" } },
|
|
65
|
+
orderBy: { name: "asc" },
|
|
66
|
+
take: 10,
|
|
114
67
|
});
|
|
115
|
-
```
|
|
116
68
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
| Title | string |
|
|
122
|
-
| Text | string |
|
|
123
|
-
| Select | string |
|
|
124
|
-
| Multi-select | Array (string) |
|
|
125
|
-
| Status | string |
|
|
126
|
-
| Number | number |
|
|
127
|
-
| Date | Object |
|
|
128
|
-
| Phone number | string |
|
|
129
|
-
| Email | string |
|
|
69
|
+
// First match or null
|
|
70
|
+
const task = await notion.tasks.findFirst({
|
|
71
|
+
where: { name: { contains: "bug" } },
|
|
72
|
+
});
|
|
130
73
|
|
|
131
|
-
|
|
74
|
+
// By page ID
|
|
75
|
+
const task = await notion.tasks.findUnique({ where: { id: "page-id" } });
|
|
132
76
|
|
|
133
|
-
|
|
77
|
+
// Page-by-page (UI pagination)
|
|
78
|
+
const page1 = await notion.tasks.paginate({ take: 20 });
|
|
79
|
+
const page2 = await notion.tasks.paginate({
|
|
80
|
+
take: 20,
|
|
81
|
+
after: page1.nextCursor,
|
|
82
|
+
});
|
|
83
|
+
// => { data, nextCursor, hasMore }
|
|
134
84
|
|
|
135
|
-
|
|
85
|
+
// Streaming all results in batches (AsyncIterable)
|
|
86
|
+
for await (const task of notion.tasks.findMany({ stream: 50 })) {
|
|
87
|
+
console.log(task.name);
|
|
88
|
+
}
|
|
136
89
|
|
|
137
|
-
|
|
90
|
+
// Count
|
|
91
|
+
const total = await notion.tasks.count({
|
|
92
|
+
where: { status: { equals: "Done" } },
|
|
93
|
+
});
|
|
94
|
+
```
|
|
138
95
|
|
|
139
|
-
|
|
96
|
+
### Select / omit
|
|
140
97
|
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
contains: "Sci-Fi",
|
|
146
|
-
},
|
|
147
|
-
},
|
|
148
|
-
sort: [
|
|
149
|
-
{
|
|
150
|
-
property: "name",
|
|
151
|
-
direction: "ascending",
|
|
152
|
-
},
|
|
153
|
-
{
|
|
154
|
-
property: "Author name",
|
|
155
|
-
direction: "ascending",
|
|
156
|
-
},
|
|
157
|
-
],
|
|
98
|
+
```ts
|
|
99
|
+
// Return only specific fields
|
|
100
|
+
const tasks = await notion.tasks.findMany({
|
|
101
|
+
select: { name: true, status: true },
|
|
158
102
|
});
|
|
159
|
-
```
|
|
160
103
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
await notion.books.query({
|
|
165
|
-
filter: {
|
|
166
|
-
or: [
|
|
167
|
-
{
|
|
168
|
-
genre: {
|
|
169
|
-
contains: "Sci-Fi",
|
|
170
|
-
},
|
|
171
|
-
},
|
|
172
|
-
{
|
|
173
|
-
genre: {
|
|
174
|
-
contains: "Biography",
|
|
175
|
-
},
|
|
176
|
-
},
|
|
177
|
-
],
|
|
178
|
-
},
|
|
104
|
+
// Exclude specific fields
|
|
105
|
+
const tasks = await notion.tasks.findMany({
|
|
106
|
+
omit: { internalNotes: true },
|
|
179
107
|
});
|
|
180
108
|
```
|
|
181
109
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
```tsx
|
|
185
|
-
{
|
|
186
|
-
rawResponse: { /* Whatever Notion API returns */},
|
|
187
|
-
results: [
|
|
188
|
-
{
|
|
189
|
-
bookName: "How to Change Your Mind",
|
|
190
|
-
genre: ["Non-fiction"],
|
|
191
|
-
numberPages: 460,
|
|
192
|
-
rating: "⭐️⭐️⭐️⭐️"
|
|
193
|
-
},
|
|
194
|
-
]
|
|
195
|
-
}
|
|
196
|
-
```
|
|
110
|
+
### Writing
|
|
197
111
|
|
|
198
|
-
|
|
112
|
+
```ts
|
|
113
|
+
// Create
|
|
114
|
+
const task = await notion.tasks.create({
|
|
115
|
+
data: { name: "Fix bug", status: "Todo" },
|
|
116
|
+
});
|
|
199
117
|
|
|
200
|
-
|
|
118
|
+
// Create many
|
|
119
|
+
await notion.tasks.createMany({
|
|
120
|
+
data: [{ name: "Task A" }, { name: "Task B" }],
|
|
121
|
+
});
|
|
201
122
|
|
|
202
|
-
|
|
123
|
+
// Update by ID
|
|
124
|
+
await notion.tasks.update({
|
|
125
|
+
where: { id: "page-id" },
|
|
126
|
+
data: { status: "Done" },
|
|
127
|
+
});
|
|
203
128
|
|
|
204
|
-
|
|
129
|
+
// Update all matching
|
|
130
|
+
await notion.tasks.updateMany({
|
|
131
|
+
where: { status: { equals: "Todo" } },
|
|
132
|
+
data: { status: "In Progress" },
|
|
133
|
+
});
|
|
205
134
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
},
|
|
213
|
-
},
|
|
214
|
-
});
|
|
215
|
-
return {
|
|
216
|
-
props: {
|
|
217
|
-
apiResponse: response
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
```
|
|
135
|
+
// Upsert
|
|
136
|
+
await notion.tasks.upsert({
|
|
137
|
+
where: { name: { equals: "Fix bug" } },
|
|
138
|
+
create: { name: "Fix bug", status: "Todo" },
|
|
139
|
+
update: { status: "In Progress" },
|
|
140
|
+
});
|
|
221
141
|
|
|
222
|
-
|
|
142
|
+
// Delete by ID
|
|
143
|
+
await notion.tasks.delete({ where: { id: "page-id" } });
|
|
223
144
|
|
|
224
|
-
|
|
225
|
-
|
|
145
|
+
// Delete all matching
|
|
146
|
+
await notion.tasks.deleteMany({
|
|
147
|
+
where: { status: { equals: "Done" } },
|
|
148
|
+
});
|
|
149
|
+
```
|
|
226
150
|
|
|
227
|
-
|
|
228
|
-
const example: DatabaseSchemaType = {
|
|
229
|
-
bookName: "How to Change Your Mind",
|
|
230
|
-
genre: ["Non-fiction"],
|
|
231
|
-
};
|
|
151
|
+
## CLI
|
|
232
152
|
|
|
233
|
-
// make sure this route reflects your API path
|
|
234
|
-
await fetch("/api/notion/books", {
|
|
235
|
-
method: "POST",
|
|
236
|
-
body: JSON.stringify(example),
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
153
|
```
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
<
|
|
154
|
+
notion init Create notion.config.ts
|
|
155
|
+
notion generate Generate types for all configured databases
|
|
156
|
+
notion add <name> <database-id-or-url> Add a database and generate its types
|
|
243
157
|
```
|
|
244
158
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
```tsx
|
|
248
|
-
// pages/api/notion/yourDatabaseName.ts
|
|
159
|
+
## Config options
|
|
249
160
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
161
|
+
| Field | Type | Default | Description |
|
|
162
|
+
| ----------- | ------------------------ | ------------------------ | ------------------------------------------- |
|
|
163
|
+
| `auth` | `string` | — | Notion integration token |
|
|
164
|
+
| `databases` | `Record<string, string>` | — | Map of name → database ID |
|
|
165
|
+
| `outputDir` | `string` | `"generated/notion-orm"` | Output directory (relative to project root) |
|
|
255
166
|
|
|
256
|
-
|
|
257
|
-
req: NextApiRequest,
|
|
258
|
-
res: NextApiResponse
|
|
259
|
-
) {
|
|
260
|
-
const { method, body } = req;
|
|
167
|
+
## Environment
|
|
261
168
|
|
|
262
|
-
|
|
263
|
-
const bodyJSON = JSON.parse(body) as DatabaseSchemaType;
|
|
264
|
-
await yourDatabaseName.add(bodyJSON);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
```
|
|
169
|
+
Set `NOTION_API_KEY` in your environment or `.env` file, or pass it directly via the `auth` field in `notion.config.ts`.
|
package/dist/ast/constants.d.ts
CHANGED
|
@@ -1,27 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Internal constants for AST and db-client modules.
|
|
3
3
|
*/
|
|
4
|
-
/**
|
|
5
|
-
export declare const
|
|
4
|
+
/** Default output directory for generated files, relative to consuming project root */
|
|
5
|
+
export declare const DEFAULT_OUTPUT_DIR = "generated/notion-orm";
|
|
6
|
+
/** Resolve the absolute path to the databases output directory */
|
|
7
|
+
export declare function getDatabasesDir(outputDir?: string): string;
|
|
6
8
|
/** File system paths for CLI output */
|
|
7
|
-
export declare
|
|
8
|
-
/** metadata.json inside
|
|
9
|
+
export declare function getFSPaths(databasesDirPath: string): {
|
|
10
|
+
/** metadata.json inside the output directory */
|
|
9
11
|
readonly metadataFile: string;
|
|
10
|
-
/**
|
|
11
|
-
readonly
|
|
12
|
-
/** generated/index.ts — barrel exporting all DB clients */
|
|
13
|
-
readonly generatedBarrelTs: string;
|
|
12
|
+
/** index.ts — the NotionORM class written to the output directory */
|
|
13
|
+
readonly notionORMFile: string;
|
|
14
14
|
};
|
|
15
15
|
export declare const AST_FS_FILENAMES: {
|
|
16
16
|
readonly METADATA: "metadata.json";
|
|
17
17
|
readonly INDEX_TS: "index.ts";
|
|
18
18
|
};
|
|
19
|
-
/** Import path strings used when generating TypeScript code */
|
|
20
|
-
export declare
|
|
21
|
-
readonly DATABASE_CLIENT:
|
|
22
|
-
readonly QUERY_TYPES:
|
|
19
|
+
/** Import path strings used when generating TypeScript code inside a given output directory */
|
|
20
|
+
export declare function getImportPaths(databasesDirPath: string): {
|
|
21
|
+
readonly DATABASE_CLIENT: string;
|
|
22
|
+
readonly QUERY_TYPES: string;
|
|
23
23
|
readonly ZOD: "zod";
|
|
24
|
-
readonly databaseClass: (className: string) => string;
|
|
25
24
|
};
|
|
26
25
|
export declare const AST_RUNTIME_CONSTANTS: {
|
|
27
26
|
readonly NOTION_API_VERSION: "2025-09-03";
|