chalknotes 0.0.34 → 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.
- package/README.md +143 -188
- package/bin/chalknotes.js +31 -0
- package/bin/cli.js +27 -288
- package/dist/commands/init.d.ts +6 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +196 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/scaffold.d.ts +6 -0
- package/dist/commands/scaffold.d.ts.map +1 -0
- package/dist/commands/scaffold.js +196 -0
- package/dist/commands/scaffold.js.map +1 -0
- package/dist/index.d.ts +53 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +163 -0
- package/dist/index.js.map +1 -0
- package/dist/notion/client.d.ts +14 -0
- package/dist/notion/client.d.ts.map +1 -0
- package/dist/notion/client.js +191 -0
- package/dist/notion/client.js.map +1 -0
- package/dist/plugins/parser.d.ts +10 -0
- package/dist/plugins/parser.d.ts.map +1 -0
- package/dist/plugins/parser.js +307 -0
- package/dist/plugins/parser.js.map +1 -0
- package/dist/templates/components.d.ts +4 -0
- package/dist/templates/components.d.ts.map +1 -0
- package/dist/templates/components.js +556 -0
- package/dist/templates/components.js.map +1 -0
- package/dist/templates/pages.d.ts +4 -0
- package/dist/templates/pages.d.ts.map +1 -0
- package/dist/templates/pages.js +321 -0
- package/dist/templates/pages.js.map +1 -0
- package/dist/types/index.d.ts +64 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/config.d.ts +12 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +99 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/detection.d.ts +19 -0
- package/dist/utils/detection.d.ts.map +1 -0
- package/dist/utils/detection.js +246 -0
- package/dist/utils/detection.js.map +1 -0
- package/dist/utils/logger.d.ts +10 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +62 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +47 -10
- package/templates/example-config.js +34 -0
- package/templates/example-env +3 -0
- package/src/index.js +0 -10
- package/src/lib/getAllPosts.js +0 -35
- package/src/lib/getPostBySlug.js +0 -380
- package/src/lib/nextHelpers.js +0 -36
- package/src/lib/notion.js +0 -11
- package/src/utils.js +0 -6
package/src/lib/getPostBySlug.js
DELETED
|
@@ -1,380 +0,0 @@
|
|
|
1
|
-
const { notion, dbId } = require("./notion")
|
|
2
|
-
const { slugify } = require("../utils")
|
|
3
|
-
|
|
4
|
-
const getPostBySlug = async (slug) => {
|
|
5
|
-
try {
|
|
6
|
-
const response = await notion.databases.query({
|
|
7
|
-
database_id: dbId,
|
|
8
|
-
filter: {
|
|
9
|
-
property: "Published",
|
|
10
|
-
checkbox: {
|
|
11
|
-
equals: true,
|
|
12
|
-
},
|
|
13
|
-
},
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
if (response.results.length === 0) {
|
|
17
|
-
throw new Error("No posts found")
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
for (const page of response.results) {
|
|
21
|
-
const titleProperty = page.properties["Name"]
|
|
22
|
-
const title = titleProperty?.title?.[0]?.plain_text
|
|
23
|
-
const pageSlug = slugify(title)
|
|
24
|
-
|
|
25
|
-
if (pageSlug === slug) {
|
|
26
|
-
const response = await notion.blocks.children.list({
|
|
27
|
-
block_id: page.id,
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
let content = []
|
|
31
|
-
for (const block of response.results) {
|
|
32
|
-
content.push(convertBlockToStructuredJSON(block))
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return {
|
|
36
|
-
title,
|
|
37
|
-
slug: pageSlug,
|
|
38
|
-
blocks: content,
|
|
39
|
-
notionPageId: page.id,
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
throw new Error(`No post found with slug "${slug}"`)
|
|
45
|
-
} catch (error) {
|
|
46
|
-
console.error(error)
|
|
47
|
-
throw new Error(`Error fetching posts from Notion: ${error.message}`)
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function convertBlockToStructuredJSON(block) {
|
|
52
|
-
const base = { type: block.type };
|
|
53
|
-
|
|
54
|
-
switch (block.type) {
|
|
55
|
-
case "paragraph":
|
|
56
|
-
return {
|
|
57
|
-
...base,
|
|
58
|
-
text: extractPlainText(block.paragraph.rich_text),
|
|
59
|
-
richText: block.paragraph.rich_text,
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
case "heading_1":
|
|
63
|
-
case "heading_2":
|
|
64
|
-
case "heading_3":
|
|
65
|
-
return {
|
|
66
|
-
...base,
|
|
67
|
-
text: extractPlainText(block[block.type].rich_text),
|
|
68
|
-
richText: block[block.type].rich_text,
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
case "bulleted_list_item":
|
|
72
|
-
case "numbered_list_item":
|
|
73
|
-
return {
|
|
74
|
-
...base,
|
|
75
|
-
text: extractPlainText(block[block.type].rich_text),
|
|
76
|
-
richText: block[block.type].rich_text,
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
case "image": {
|
|
80
|
-
const image = block.image;
|
|
81
|
-
const url = image.type === "external" ? image.external.url : image.file.url;
|
|
82
|
-
const caption = extractPlainText(image.caption);
|
|
83
|
-
return {
|
|
84
|
-
...base,
|
|
85
|
-
imageUrl: url,
|
|
86
|
-
caption,
|
|
87
|
-
alt: caption || "Blog image from Notion",
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
case "quote":
|
|
92
|
-
return {
|
|
93
|
-
...base,
|
|
94
|
-
text: extractPlainText(block.quote.rich_text),
|
|
95
|
-
richText: block.quote.rich_text,
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
case "code":
|
|
99
|
-
return {
|
|
100
|
-
...base,
|
|
101
|
-
code: extractPlainText(block.code.rich_text),
|
|
102
|
-
language: block.code.language || "text",
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
case "divider":
|
|
106
|
-
return { ...base };
|
|
107
|
-
|
|
108
|
-
case "callout":
|
|
109
|
-
return { ...base };
|
|
110
|
-
|
|
111
|
-
case "toggle":
|
|
112
|
-
return { ...base };
|
|
113
|
-
|
|
114
|
-
case "table_of_contents":
|
|
115
|
-
return { ...base };
|
|
116
|
-
case "bookmark":
|
|
117
|
-
return { ...base };
|
|
118
|
-
|
|
119
|
-
case "equation":
|
|
120
|
-
return { ...base };
|
|
121
|
-
|
|
122
|
-
case "table":
|
|
123
|
-
return { ...base };
|
|
124
|
-
|
|
125
|
-
default:
|
|
126
|
-
return {
|
|
127
|
-
...base,
|
|
128
|
-
unsupported: true,
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
function extractPlainText(richText = []) {
|
|
134
|
-
return richText.map(t => t.plain_text).join("");
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Process individual Notion blocks and convert to HTML
|
|
140
|
-
* @param {Object} block - Notion block object
|
|
141
|
-
* @returns {string} HTML string
|
|
142
|
-
*/
|
|
143
|
-
function processBlock(block) {
|
|
144
|
-
switch (block.type) {
|
|
145
|
-
case "paragraph":
|
|
146
|
-
return processRichText(block.paragraph.rich_text, "p", "mb-6 leading-relaxed text-slate-700 text-base")
|
|
147
|
-
|
|
148
|
-
case "heading_1":
|
|
149
|
-
return processRichText(
|
|
150
|
-
block.heading_1.rich_text,
|
|
151
|
-
"h1",
|
|
152
|
-
"text-4xl font-extrabold mb-8 mt-12 text-slate-900 border-b border-slate-200 pb-6",
|
|
153
|
-
)
|
|
154
|
-
|
|
155
|
-
case "heading_2":
|
|
156
|
-
return processRichText(block.heading_2.rich_text, "h2", "text-3xl font-bold mb-6 mt-10 text-slate-900")
|
|
157
|
-
|
|
158
|
-
case "heading_3":
|
|
159
|
-
return processRichText(block.heading_3.rich_text, "h3", "text-2xl font-semibold mb-4 mt-8 text-slate-900")
|
|
160
|
-
|
|
161
|
-
case "bulleted_list_item":
|
|
162
|
-
return processRichText(
|
|
163
|
-
block.bulleted_list_item.rich_text,
|
|
164
|
-
"li",
|
|
165
|
-
"mb-2 ml-6 leading-relaxed text-slate-700 list-disc",
|
|
166
|
-
)
|
|
167
|
-
|
|
168
|
-
case "numbered_list_item":
|
|
169
|
-
return processRichText(
|
|
170
|
-
block.numbered_list_item.rich_text,
|
|
171
|
-
"li",
|
|
172
|
-
"mb-2 ml-6 leading-relaxed text-slate-700 list-decimal",
|
|
173
|
-
)
|
|
174
|
-
|
|
175
|
-
case "quote":
|
|
176
|
-
return processRichText(
|
|
177
|
-
block.quote.rich_text,
|
|
178
|
-
"blockquote",
|
|
179
|
-
"border-l-4 border-indigo-400 pl-6 italic text-slate-600 mb-8 bg-slate-50 py-6 rounded-r-xl text-lg leading-relaxed font-medium",
|
|
180
|
-
)
|
|
181
|
-
|
|
182
|
-
case "code":
|
|
183
|
-
const codeContent = block.code.rich_text.map((text) => text.plain_text).join("")
|
|
184
|
-
const language = block.code.language || "text"
|
|
185
|
-
return `<pre class="bg-slate-900 text-slate-100 p-6 rounded-xl overflow-x-auto mb-8 text-sm leading-6 shadow-xl border border-slate-800"><code class="language-${language}">${escapeHtml(codeContent)}</code></pre>`
|
|
186
|
-
|
|
187
|
-
case "image":
|
|
188
|
-
return processImage(block.image)
|
|
189
|
-
|
|
190
|
-
case "divider":
|
|
191
|
-
return '<hr class="my-12 border-slate-200" />'
|
|
192
|
-
|
|
193
|
-
case "callout":
|
|
194
|
-
return processCallout(block.callout)
|
|
195
|
-
|
|
196
|
-
case "toggle":
|
|
197
|
-
return processToggle(block.toggle)
|
|
198
|
-
|
|
199
|
-
case "table_of_contents":
|
|
200
|
-
return '<div class="bg-indigo-50 border border-indigo-200 rounded-xl p-6 mb-8 shadow-sm"><p class="text-indigo-900 font-semibold text-lg">📋 Table of Contents</p><p class="text-indigo-600 text-sm mt-1">(Generated automatically)</p></div>'
|
|
201
|
-
|
|
202
|
-
case "bookmark":
|
|
203
|
-
return processBookmark(block.bookmark)
|
|
204
|
-
|
|
205
|
-
case "equation":
|
|
206
|
-
return `<div class="bg-slate-50 p-6 rounded-xl mb-8 text-center border border-slate-200 shadow-sm"><p class="text-slate-600 mb-3 font-semibold">📐 Mathematical equation</p><p class="font-mono text-sm bg-white p-4 rounded-lg border shadow-sm">${block.equation.expression}</p></div>`
|
|
207
|
-
|
|
208
|
-
default:
|
|
209
|
-
// For unsupported blocks, try to extract plain text
|
|
210
|
-
if (block[block.type]?.rich_text) {
|
|
211
|
-
return processRichText(block[block.type].rich_text, "p", "mb-6 text-slate-500 italic text-base")
|
|
212
|
-
}
|
|
213
|
-
return ""
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Process image block with size, alignment, and alt text
|
|
219
|
-
* @param {Object} image - Notion image block
|
|
220
|
-
* @returns {string} HTML string
|
|
221
|
-
*/
|
|
222
|
-
function processImage(image) {
|
|
223
|
-
const imageUrl = image.type === "external" ? image.external.url : image.file.url;
|
|
224
|
-
const caption = image.caption?.map((text) => text.plain_text).join("") || "";
|
|
225
|
-
const altText = caption || "Blog image from Notion";
|
|
226
|
-
|
|
227
|
-
// Strict size constraints for blog layout
|
|
228
|
-
const containerClasses = "max-w-[400px] mx-auto px-4 my-4";
|
|
229
|
-
const figureClasses = "relative w-full max-w-[300px] sm:max-w-[400px] h-[300px]";
|
|
230
|
-
|
|
231
|
-
// Log image URL for debugging
|
|
232
|
-
console.log("Image URL:", imageUrl);
|
|
233
|
-
|
|
234
|
-
return `
|
|
235
|
-
<div className="${containerClasses}">
|
|
236
|
-
<figure className="${figureClasses}">
|
|
237
|
-
<Image
|
|
238
|
-
src="${imageUrl}"
|
|
239
|
-
alt="${escapeHtml(altText)}"
|
|
240
|
-
fill
|
|
241
|
-
className="rounded-xl object-contain"
|
|
242
|
-
sizes="(max-width: 640px) 300px, 400px"
|
|
243
|
-
priority={false}
|
|
244
|
-
/>
|
|
245
|
-
${caption ? `<figcaption className="text-slate-600 mt-2 text-sm text-center font-medium italic">${escapeHtml(caption)}</figcaption>` : ""}
|
|
246
|
-
</figure>
|
|
247
|
-
</div>
|
|
248
|
-
`.trim();
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
/**
|
|
253
|
-
* Process callout block
|
|
254
|
-
* @param {Object} callout - Notion callout block
|
|
255
|
-
* @returns {string} HTML string
|
|
256
|
-
*/
|
|
257
|
-
function processCallout(callout) {
|
|
258
|
-
const content = processRichText(callout.rich_text, "div", "")
|
|
259
|
-
const icon = callout.icon?.emoji || "💡"
|
|
260
|
-
const bgColor = callout.color || "blue"
|
|
261
|
-
|
|
262
|
-
const colorClasses = {
|
|
263
|
-
blue: "bg-blue-50 border-blue-200 text-blue-900",
|
|
264
|
-
gray: "bg-slate-50 border-slate-200 text-slate-900",
|
|
265
|
-
yellow: "bg-amber-50 border-amber-200 text-amber-900",
|
|
266
|
-
red: "bg-red-50 border-red-200 text-red-900",
|
|
267
|
-
green: "bg-emerald-50 border-emerald-200 text-emerald-900",
|
|
268
|
-
purple: "bg-purple-50 border-purple-200 text-purple-900",
|
|
269
|
-
pink: "bg-pink-50 border-pink-200 text-pink-900",
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
const colorClass = colorClasses[bgColor] || colorClasses.blue
|
|
273
|
-
|
|
274
|
-
return `
|
|
275
|
-
<div class="${colorClass} border-l-4 p-6 my-8 rounded-r-xl shadow-sm">
|
|
276
|
-
<div class="flex items-start">
|
|
277
|
-
<span class="mr-4 text-2xl flex-shrink-0">${icon}</span>
|
|
278
|
-
<div class="flex-1 leading-relaxed text-base font-medium">${content}</div>
|
|
279
|
-
</div>
|
|
280
|
-
</div>
|
|
281
|
-
`.trim()
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
/**
|
|
285
|
-
* Process bookmark block
|
|
286
|
-
* @param {Object} bookmark - Notion bookmark block
|
|
287
|
-
* @returns {string} HTML string
|
|
288
|
-
*/
|
|
289
|
-
function processBookmark(bookmark) {
|
|
290
|
-
const url = bookmark.url
|
|
291
|
-
const title = bookmark.caption?.[0]?.plain_text || "Bookmark"
|
|
292
|
-
|
|
293
|
-
return `
|
|
294
|
-
<div class="my-8">
|
|
295
|
-
<a href="${url}" target="_blank" rel="noopener noreferrer" class="block border border-slate-200 rounded-xl p-6 hover:border-slate-300 hover:shadow-lg transition-all duration-300 bg-white hover:bg-slate-50">
|
|
296
|
-
<div class="flex items-center">
|
|
297
|
-
<div class="flex-1 min-w-0">
|
|
298
|
-
<p class="font-semibold text-slate-900 truncate text-lg">${escapeHtml(title)}</p>
|
|
299
|
-
<p class="text-sm text-slate-500 truncate mt-2">${url}</p>
|
|
300
|
-
</div>
|
|
301
|
-
<svg class="w-6 h-6 text-slate-400 ml-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
302
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"></path>
|
|
303
|
-
</svg>
|
|
304
|
-
</div>
|
|
305
|
-
</a>
|
|
306
|
-
</div>
|
|
307
|
-
`.trim()
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
/**
|
|
311
|
-
* Process toggle block
|
|
312
|
-
* @param {Object} toggle - Notion toggle block
|
|
313
|
-
* @returns {string} HTML string
|
|
314
|
-
*/
|
|
315
|
-
function processToggle(toggle) {
|
|
316
|
-
const content = processRichText(toggle.rich_text, "div", "")
|
|
317
|
-
return `
|
|
318
|
-
<details class="my-6">
|
|
319
|
-
<summary class="cursor-pointer font-semibold text-slate-700 hover:text-slate-900 text-lg leading-relaxed transition-colors duration-200">
|
|
320
|
-
${content}
|
|
321
|
-
</summary>
|
|
322
|
-
<div class="mt-4 pl-6 border-l-2 border-slate-200">
|
|
323
|
-
<!-- Toggle content would go here if Notion API provided it -->
|
|
324
|
-
<p class="text-slate-600 text-base italic">Toggle content not available in current API</p>
|
|
325
|
-
</div>
|
|
326
|
-
</details>
|
|
327
|
-
`.trim()
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
/**
|
|
331
|
-
* Process rich text and apply formatting
|
|
332
|
-
* @param {Array} richText - Array of rich text objects
|
|
333
|
-
* @param {string} tag - HTML tag to wrap content
|
|
334
|
-
* @param {string} className - CSS classes
|
|
335
|
-
* @returns {string} HTML string
|
|
336
|
-
*/
|
|
337
|
-
function processRichText(richText, tag, className) {
|
|
338
|
-
if (!richText || richText.length === 0) return ""
|
|
339
|
-
|
|
340
|
-
const content = richText
|
|
341
|
-
.map((text) => {
|
|
342
|
-
let result = text.plain_text
|
|
343
|
-
|
|
344
|
-
// Apply annotations
|
|
345
|
-
if (text.annotations.bold) result = `<strong class="font-bold">${result}</strong>`
|
|
346
|
-
if (text.annotations.italic) result = `<em class="italic">${result}</em>`
|
|
347
|
-
if (text.annotations.strikethrough) result = `<del class="line-through">${result}</del>`
|
|
348
|
-
if (text.annotations.code)
|
|
349
|
-
result = `<code class="bg-slate-100 px-2 py-1 rounded-md text-sm font-mono text-slate-800 border border-slate-200">${result}</code>`
|
|
350
|
-
|
|
351
|
-
// Apply links
|
|
352
|
-
if (text.href)
|
|
353
|
-
result = `<a href="${text.href}" class="text-indigo-600 hover:text-indigo-800 underline font-medium transition-colors duration-200" target="_blank" rel="noopener noreferrer">${result}</a>`
|
|
354
|
-
|
|
355
|
-
return result
|
|
356
|
-
})
|
|
357
|
-
.join("")
|
|
358
|
-
|
|
359
|
-
return `<${tag} class="${className}">${content}</${tag}>`
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
/**
|
|
363
|
-
* Escape HTML special characters
|
|
364
|
-
* @param {string} text - Text to escape
|
|
365
|
-
* @returns {string} Escaped text
|
|
366
|
-
*/
|
|
367
|
-
function escapeHtml(text) {
|
|
368
|
-
const map = {
|
|
369
|
-
"&": "&",
|
|
370
|
-
"<": "<",
|
|
371
|
-
">": ">",
|
|
372
|
-
'"': """,
|
|
373
|
-
"'": "'",
|
|
374
|
-
}
|
|
375
|
-
return text.replace(/[&<>"']/g, (m) => map[m])
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
module.exports = {
|
|
379
|
-
getPostBySlug,
|
|
380
|
-
}
|
package/src/lib/nextHelpers.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
const { getAllPosts } = require('./getAllPosts');
|
|
2
|
-
const { getPostBySlug } = require('./getPostBySlug');
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Provides static props for a post page using slug
|
|
6
|
-
*/
|
|
7
|
-
const getStaticPropsForPost = async ({ params }) => {
|
|
8
|
-
const post = await getPostBySlug(params.slug);
|
|
9
|
-
|
|
10
|
-
return {
|
|
11
|
-
props: {
|
|
12
|
-
post
|
|
13
|
-
}
|
|
14
|
-
};
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Provides static paths for all blog posts
|
|
19
|
-
*/
|
|
20
|
-
const getStaticPathsForPosts = async () => {
|
|
21
|
-
const posts = await getAllPosts();
|
|
22
|
-
|
|
23
|
-
const paths = posts.map((post) => ({
|
|
24
|
-
params: { slug: post.slug }
|
|
25
|
-
}));
|
|
26
|
-
|
|
27
|
-
return {
|
|
28
|
-
paths,
|
|
29
|
-
fallback: false,
|
|
30
|
-
};
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
module.exports = {
|
|
34
|
-
getStaticPropsForPost,
|
|
35
|
-
getStaticPathsForPosts
|
|
36
|
-
};
|
package/src/lib/notion.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
const { Client } = require('@notionhq/client');
|
|
2
|
-
const dotenv = require('dotenv');
|
|
3
|
-
dotenv.config();
|
|
4
|
-
|
|
5
|
-
const notion = new Client({ auth: process.env.NOTION_TOKEN });
|
|
6
|
-
const dbId = process.env.NOTION_DATABASE_ID;
|
|
7
|
-
|
|
8
|
-
module.exports = {
|
|
9
|
-
notion,
|
|
10
|
-
dbId
|
|
11
|
-
}
|