@moxn/kb-migrate 0.4.26 → 0.4.27
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/index.js +41 -1
- package/dist/sources/notion-api.d.ts +6 -0
- package/dist/sources/notion-api.js +20 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -487,6 +487,13 @@ program
|
|
|
487
487
|
console.error(` Error pre-creating database "${dbImport.schema.name}": ${error instanceof Error ? error.message : error}`);
|
|
488
488
|
}
|
|
489
489
|
}
|
|
490
|
+
// Also add any other existing mappings (e.g. linked DB → source mappings
|
|
491
|
+
// from prior imports) so they're available during extraction
|
|
492
|
+
for (const [notionId, kbId] of existingMappings) {
|
|
493
|
+
if (!databaseIdMap.has(notionId)) {
|
|
494
|
+
databaseIdMap.set(notionId, kbId);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
490
497
|
// Make the map available during extraction
|
|
491
498
|
source.setDatabaseIdMap(databaseIdMap);
|
|
492
499
|
console.log(` ${databaseIdMap.size} database(s) ready for embed resolution.\n`);
|
|
@@ -509,6 +516,7 @@ program
|
|
|
509
516
|
// Non-fatal — will create new databases
|
|
510
517
|
}
|
|
511
518
|
let inlineCreated = 0;
|
|
519
|
+
let linkedResolved = 0;
|
|
512
520
|
for (const [notionDbId, title] of unresolvedDbs) {
|
|
513
521
|
// Skip if already mapped (could happen if previously imported)
|
|
514
522
|
if (databaseIdMap.has(notionDbId) || currentMappings.has(notionDbId)) {
|
|
@@ -552,12 +560,44 @@ program
|
|
|
552
560
|
console.log(` Created inline database: ${schema.name || title} (${kbDb.id}) — ${entries.length} entries`);
|
|
553
561
|
}
|
|
554
562
|
catch (error) {
|
|
555
|
-
|
|
563
|
+
// Check if this is a linked database — resolve to its source
|
|
564
|
+
const errMsg = error instanceof Error ? error.message : String(error);
|
|
565
|
+
if (errMsg.includes('linked database')) {
|
|
566
|
+
const sourceDbId = await notionApi.resolveLinkedDatabaseSource(notionDbId);
|
|
567
|
+
if (sourceDbId) {
|
|
568
|
+
// Look up the source database in our mappings
|
|
569
|
+
const kbDbId = databaseIdMap.get(sourceDbId) || currentMappings.get(sourceDbId);
|
|
570
|
+
if (kbDbId) {
|
|
571
|
+
databaseIdMap.set(notionDbId, kbDbId);
|
|
572
|
+
// Store mapping so future imports resolve during pre-create
|
|
573
|
+
try {
|
|
574
|
+
await inlineClient.createNotionDatabaseMapping({
|
|
575
|
+
kbDatabaseId: kbDbId,
|
|
576
|
+
notionDatabaseId: notionDbId,
|
|
577
|
+
notionDatabaseTitle: title,
|
|
578
|
+
});
|
|
579
|
+
}
|
|
580
|
+
catch {
|
|
581
|
+
// Non-fatal
|
|
582
|
+
}
|
|
583
|
+
linkedResolved++;
|
|
584
|
+
console.log(` Resolved linked database "${title}" (${notionDbId}) → source ${sourceDbId} → KB ${kbDbId}`);
|
|
585
|
+
continue;
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
console.warn(` Warning: Linked database "${title}" (${notionDbId}) — could not resolve source`);
|
|
589
|
+
}
|
|
590
|
+
else {
|
|
591
|
+
console.warn(` Warning: Failed to create inline database "${title}" (${notionDbId}): ${errMsg}`);
|
|
592
|
+
}
|
|
556
593
|
}
|
|
557
594
|
}
|
|
558
595
|
if (inlineCreated > 0) {
|
|
559
596
|
console.log(` Created ${inlineCreated} inline database(s). Re-run with --on-conflict update to resolve embeds.`);
|
|
560
597
|
}
|
|
598
|
+
if (linkedResolved > 0) {
|
|
599
|
+
console.log(` Resolved ${linkedResolved} linked database(s) to existing source databases.`);
|
|
600
|
+
}
|
|
561
601
|
}
|
|
562
602
|
}
|
|
563
603
|
// Step 4: Resolve cross-references (between page migration and database finalization)
|
|
@@ -225,6 +225,12 @@ export declare class NotionApiClient {
|
|
|
225
225
|
searchDatabases(): Promise<NotionDatabase[]>;
|
|
226
226
|
/** Get a database schema by ID. */
|
|
227
227
|
getDatabase(databaseId: string): Promise<NotionDatabase>;
|
|
228
|
+
/**
|
|
229
|
+
* For a linked database, resolve the source database ID by querying
|
|
230
|
+
* one entry and reading its parent.database_id.
|
|
231
|
+
* Returns null if the database is empty or not queryable.
|
|
232
|
+
*/
|
|
233
|
+
resolveLinkedDatabaseSource(linkedDbId: string): Promise<string | null>;
|
|
228
234
|
/**
|
|
229
235
|
* Query all entries (pages) in a database.
|
|
230
236
|
*/
|
|
@@ -101,6 +101,26 @@ export class NotionApiClient {
|
|
|
101
101
|
async getDatabase(databaseId) {
|
|
102
102
|
return this.request('GET', `/databases/${databaseId}`);
|
|
103
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* For a linked database, resolve the source database ID by querying
|
|
106
|
+
* one entry and reading its parent.database_id.
|
|
107
|
+
* Returns null if the database is empty or not queryable.
|
|
108
|
+
*/
|
|
109
|
+
async resolveLinkedDatabaseSource(linkedDbId) {
|
|
110
|
+
try {
|
|
111
|
+
const response = await this.request('POST', `/databases/${linkedDbId}/query`, { page_size: 1 });
|
|
112
|
+
if (response.results.length > 0) {
|
|
113
|
+
const entry = response.results[0];
|
|
114
|
+
if (entry.parent?.type === 'database_id' && entry.parent.database_id) {
|
|
115
|
+
return entry.parent.database_id.replace(/-/g, '');
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
104
124
|
/**
|
|
105
125
|
* Query all entries (pages) in a database.
|
|
106
126
|
*/
|
package/package.json
CHANGED