@moxn/kb-migrate 0.4.18 → 0.4.19
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/dist/export-notion.js
CHANGED
|
@@ -137,7 +137,12 @@ export async function runNotionExport(options) {
|
|
|
137
137
|
// Use the parent page ID as the target for database creation
|
|
138
138
|
const parentPageId = options.parentPageId;
|
|
139
139
|
const result = await exportDatabase(dbCtx, dbId, parentPageId);
|
|
140
|
-
const icon = {
|
|
140
|
+
const icon = {
|
|
141
|
+
created: '\u2713',
|
|
142
|
+
updated: '\u21bb',
|
|
143
|
+
skipped: '-',
|
|
144
|
+
failed: '\u2717',
|
|
145
|
+
}[result.status];
|
|
141
146
|
console.log(` ${icon} ${result.status}: ${result.kbDatabaseName} (${result.entriesCreated} entries)`);
|
|
142
147
|
if (result.error)
|
|
143
148
|
console.log(` Error: ${result.error}`);
|
|
@@ -165,7 +170,8 @@ export async function runNotionExport(options) {
|
|
|
165
170
|
// ============================================
|
|
166
171
|
if (!options.dryRun) {
|
|
167
172
|
// Find documents that have references and were successfully exported
|
|
168
|
-
const successfulExports = results.filter((r) => (r.status === 'created' || r.status === 'updated' || r.status === 'skipped') &&
|
|
173
|
+
const successfulExports = results.filter((r) => (r.status === 'created' || r.status === 'updated' || r.status === 'skipped') &&
|
|
174
|
+
r.externalId);
|
|
169
175
|
if (successfulExports.length > 0) {
|
|
170
176
|
console.log(`\nPass 2: Resolving cross-references for ${successfulExports.length} documents...`);
|
|
171
177
|
let totalResolved = 0;
|
package/dist/targets/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Target registry and factory
|
|
3
3
|
*/
|
|
4
|
-
export { ExportTarget, type ExportTargetConfig, type ExportTargetResult, type ExportTargetLog } from './base.js';
|
|
4
|
+
export { ExportTarget, type ExportTargetConfig, type ExportTargetResult, type ExportTargetLog, } from './base.js';
|
|
5
5
|
export { NotionExportTarget, type NotionExportConfig } from './notion.js';
|
|
6
|
-
export { exportDatabase, type DatabaseExportResult, type DatabaseExportContext } from './notion-database-export.js';
|
|
6
|
+
export { exportDatabase, type DatabaseExportResult, type DatabaseExportContext, } from './notion-database-export.js';
|
package/dist/targets/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Target registry and factory
|
|
3
3
|
*/
|
|
4
|
-
export { ExportTarget } from './base.js';
|
|
4
|
+
export { ExportTarget, } from './base.js';
|
|
5
5
|
export { NotionExportTarget } from './notion.js';
|
|
6
|
-
export { exportDatabase } from './notion-database-export.js';
|
|
6
|
+
export { exportDatabase, } from './notion-database-export.js';
|
|
@@ -28,7 +28,7 @@ const HEX_TO_NOTION_COLOR = {
|
|
|
28
28
|
function hexToNotionColor(hex) {
|
|
29
29
|
if (!hex)
|
|
30
30
|
return 'default';
|
|
31
|
-
return HEX_TO_NOTION_COLOR[hex.toUpperCase()] ?? HEX_TO_NOTION_COLOR[hex] ?? 'default';
|
|
31
|
+
return (HEX_TO_NOTION_COLOR[hex.toUpperCase()] ?? HEX_TO_NOTION_COLOR[hex] ?? 'default');
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
34
34
|
* Export a single KB database to Notion.
|
package/dist/targets/notion.js
CHANGED
|
@@ -196,7 +196,6 @@ async function uploadFileToNotion(client, url, filename, contentType) {
|
|
|
196
196
|
*/
|
|
197
197
|
function reconstructCallouts(blocks) {
|
|
198
198
|
const emojiPrefixRe = /^(\p{Emoji_Presentation}|\p{Emoji}\uFE0F?)\s/u;
|
|
199
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
200
199
|
return blocks.map((block) => {
|
|
201
200
|
// Case 1: paragraph with emoji prefix
|
|
202
201
|
if (block.type === 'paragraph') {
|
|
@@ -214,7 +213,7 @@ function reconstructCallouts(blocks) {
|
|
|
214
213
|
const calloutRichText = [
|
|
215
214
|
{ ...firstSegment, text: { ...firstSegment.text, content: strippedContent } },
|
|
216
215
|
...richText.slice(1),
|
|
217
|
-
].filter((rt) => rt.text?.content);
|
|
216
|
+
].filter((rt) => 'text' in rt && rt.text?.content);
|
|
218
217
|
return {
|
|
219
218
|
object: 'block',
|
|
220
219
|
type: 'callout',
|
|
@@ -311,7 +310,11 @@ async function sectionsToNotionBlocks(sections, options) {
|
|
|
311
310
|
for (let i = 0; i < parts.length; i++) {
|
|
312
311
|
if (i > 0) {
|
|
313
312
|
flushText();
|
|
314
|
-
allBlocks.push({
|
|
313
|
+
allBlocks.push({
|
|
314
|
+
object: 'block',
|
|
315
|
+
type: 'divider',
|
|
316
|
+
divider: {},
|
|
317
|
+
});
|
|
315
318
|
}
|
|
316
319
|
const part = parts[i];
|
|
317
320
|
if (part.trim()) {
|
|
@@ -323,9 +326,12 @@ async function sectionsToNotionBlocks(sections, options) {
|
|
|
323
326
|
else if (block.blockType === 'image' && block.url) {
|
|
324
327
|
flushText();
|
|
325
328
|
if (block.storageKey && options?.notionClient) {
|
|
326
|
-
const fname = block.filename ||
|
|
329
|
+
const fname = block.filename ||
|
|
330
|
+
deriveFilename(block.storageKey, block.mimeType || 'image/png');
|
|
327
331
|
const uploadId = await uploadFileToNotion(options.notionClient, block.url, fname, block.mimeType || 'image/png');
|
|
328
|
-
allBlocks.push(uploadId
|
|
332
|
+
allBlocks.push(uploadId
|
|
333
|
+
? notionImageUploadBlock(uploadId, block.alt)
|
|
334
|
+
: notionImageBlock(block.url, block.alt));
|
|
329
335
|
}
|
|
330
336
|
else {
|
|
331
337
|
allBlocks.push(notionImageBlock(block.url, block.alt));
|
|
@@ -334,10 +340,13 @@ async function sectionsToNotionBlocks(sections, options) {
|
|
|
334
340
|
else if (block.blockType === 'document' && block.url) {
|
|
335
341
|
flushText();
|
|
336
342
|
if (block.storageKey && options?.notionClient) {
|
|
337
|
-
const fname = block.filename ||
|
|
343
|
+
const fname = block.filename ||
|
|
344
|
+
deriveFilename(block.storageKey, block.mimeType || 'application/octet-stream');
|
|
338
345
|
const uploadId = await uploadFileToNotion(options.notionClient, block.url, fname, block.mimeType || 'application/octet-stream');
|
|
339
346
|
if (uploadId) {
|
|
340
|
-
allBlocks.push(block.mimeType === 'application/pdf'
|
|
347
|
+
allBlocks.push(block.mimeType === 'application/pdf'
|
|
348
|
+
? notionPdfUploadBlock(uploadId, block.filename)
|
|
349
|
+
: notionFileUploadBlock(uploadId, block.filename));
|
|
341
350
|
}
|
|
342
351
|
else if (block.mimeType === 'application/pdf') {
|
|
343
352
|
allBlocks.push(notionPdfBlock(block.url, block.filename));
|
|
@@ -358,7 +367,9 @@ async function sectionsToNotionBlocks(sections, options) {
|
|
|
358
367
|
if (block.storageKey && options?.notionClient) {
|
|
359
368
|
const fname = block.filename || deriveFilename(block.storageKey, 'text/csv');
|
|
360
369
|
const uploadId = await uploadFileToNotion(options.notionClient, block.url, fname, 'text/csv');
|
|
361
|
-
allBlocks.push(uploadId
|
|
370
|
+
allBlocks.push(uploadId
|
|
371
|
+
? notionFileUploadBlock(uploadId, block.filename || 'data.csv')
|
|
372
|
+
: notionFileBlock(block.url, block.filename || 'data.csv'));
|
|
362
373
|
}
|
|
363
374
|
else {
|
|
364
375
|
allBlocks.push(notionFileBlock(block.url, block.filename || 'data.csv'));
|
|
@@ -453,7 +464,9 @@ export class NotionExportTarget extends ExportTarget {
|
|
|
453
464
|
*/
|
|
454
465
|
async resolveAndAppendReferences(doc, notionPageId) {
|
|
455
466
|
// Extract references from section content (no upload needed for reference pass)
|
|
456
|
-
const { references } = await sectionsToNotionBlocks(doc.sections, {
|
|
467
|
+
const { references } = await sectionsToNotionBlocks(doc.sections, {
|
|
468
|
+
extractReferences: true,
|
|
469
|
+
});
|
|
457
470
|
if (references.length === 0) {
|
|
458
471
|
return { resolved: 0, unresolved: 0 };
|
|
459
472
|
}
|
|
@@ -623,7 +636,10 @@ export class NotionExportTarget extends ExportTarget {
|
|
|
623
636
|
// Notion page creation / update
|
|
624
637
|
// ============================================
|
|
625
638
|
async createNotionPage(doc) {
|
|
626
|
-
const { blocks } = await sectionsToNotionBlocks(doc.sections, {
|
|
639
|
+
const { blocks } = await sectionsToNotionBlocks(doc.sections, {
|
|
640
|
+
extractReferences: true,
|
|
641
|
+
notionClient: this.client,
|
|
642
|
+
});
|
|
627
643
|
// First batch: up to 100 blocks as children of the new page
|
|
628
644
|
const firstBatch = blocks.slice(0, MAX_BLOCKS_PER_APPEND);
|
|
629
645
|
const remainingBlocks = blocks.slice(MAX_BLOCKS_PER_APPEND);
|
|
@@ -655,7 +671,10 @@ export class NotionExportTarget extends ExportTarget {
|
|
|
655
671
|
},
|
|
656
672
|
});
|
|
657
673
|
await this.clearPageContent(notionPageId);
|
|
658
|
-
const { blocks } = await sectionsToNotionBlocks(doc.sections, {
|
|
674
|
+
const { blocks } = await sectionsToNotionBlocks(doc.sections, {
|
|
675
|
+
extractReferences: true,
|
|
676
|
+
notionClient: this.client,
|
|
677
|
+
});
|
|
659
678
|
await this.appendRemainingBlocks(notionPageId, blocks);
|
|
660
679
|
}
|
|
661
680
|
async clearPageContent(pageId) {
|
package/package.json
CHANGED