@im-nobsidian/core 0.20.0 → 0.22.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/dist/index.d.ts CHANGED
@@ -1578,6 +1578,11 @@ interface NotionClientOptions {
1578
1578
  readonly notifications?: NotificationMode;
1579
1579
  readonly fetch?: typeof globalThis.fetch;
1580
1580
  }
1581
+ /** 덧붙일 자리 — 블록 뒤(`after`) · 맨 앞(`atStart`). 없으면 맨 끝. */
1582
+ interface AppendPosition {
1583
+ readonly after?: string;
1584
+ readonly atStart?: boolean;
1585
+ }
1581
1586
  declare class NotionClient {
1582
1587
  private readonly client;
1583
1588
  private readonly sema;
@@ -1880,31 +1885,31 @@ declare class NotionClient {
1880
1885
  */
1881
1886
  getBlockTree(blockId: string): Promise<BlockTreeNode[]>;
1882
1887
  /**
1883
- * 자식 블록을 덧붙인다. `options.after` 를 주면 그 블록 **바로 뒤**에 삽입한다
1888
+ * 자식 블록을 덧붙인다. `options.after` 를 주면 그 블록 **바로 뒤**에, `options.atStart` 면 맨 앞에 삽입한다
1884
1889
  * (기본은 맨 끝). 자리표시자를 실제 미디어 블록으로 제자리 교체할 때 필요하다.
1885
1890
  *
1886
1891
  * 실측(2025-09-03): position 삽입 응답의 `results` 는 방금 넣은 블록뿐 아니라
1887
1892
  * 삽입 지점 이후의 형제까지 함께 돌려준다. 앞에서부터 batch 길이만큼이 새 블록이므로
1888
1893
  * 배치를 이어 붙일 때는 그 마지막 id 를 다음 기준점으로 삼는다.
1889
1894
  */
1890
- appendChildren(blockId: string, children: unknown[], options?: {
1891
- readonly after?: string;
1892
- }): Promise<string[]>;
1895
+ appendChildren(blockId: string, children: unknown[], options?: AppendPosition): Promise<string[]>;
1893
1896
  /**
1894
1897
  * {@link appendChildren} 과 같되 새로 만든 블록을 통째로 돌려준다. 파일을 붙인 미디어 블록은
1895
1898
  * 응답에 Notion 이 저장한 파일의 URL 이 실려 온다 — 다시 조회하지 않고 그 파일을 알아 둔다(S-05).
1896
1899
  */
1897
- appendChildBlocks(blockId: string, children: unknown[], options?: {
1898
- readonly after?: string;
1899
- }): Promise<(BlockObjectResponse | PartialBlockObjectResponse)[]>;
1900
+ appendChildBlocks(blockId: string, children: unknown[], options?: AppendPosition): Promise<(BlockObjectResponse | PartialBlockObjectResponse)[]>;
1900
1901
  /**
1901
1902
  * 깊이 제한 없는 블록 트리를 맨 끝에 덧붙인다 — 요청 한도(깊이 두 단계 · 100 개 · 1000 블록)를 넘는
1902
1903
  * 자식은 부모를 만든 뒤 그 아래에 마저 붙인다({@link shapeAppendRequests}). 더 깊은 블록의 id 는
1903
1904
  * 응답에 없어 부모의 자식 목록을 읽어 찾는다.
1904
1905
  *
1906
+ * `options.atStart` 면 맨 위 블록을 맨 앞에 넣는다 — 본문 뒤에 둘 블록(폴더 첨부)을 남기고 본문만 바꿀 때.
1907
+ *
1905
1908
  * 중간에 실패하면 그때까지 만든 블록은 남는다 — 호출측이 실패로 알린다.
1906
1909
  */
1907
- appendBlockTree(parentId: string, blocks: readonly BlockRequest[]): Promise<void>;
1910
+ appendBlockTree(parentId: string, blocks: readonly BlockRequest[], options?: {
1911
+ readonly atStart?: boolean;
1912
+ }): Promise<void>;
1908
1913
  deleteBlock(blockId: string): Promise<void>;
1909
1914
  /**
1910
1915
  * 코드 블록의 글을 바꾼다 — Markdown API 로 보낼 수 없는 코드(코드 속 ``` 줄, S-22)를 블록으로
@@ -2821,6 +2826,12 @@ declare class SyncOrchestrator {
2821
2826
  * 있든 없든 push 마다 부른다 — 바뀌지 않은 첨부는 파일 기록이 건너뛴다.
2822
2827
  */
2823
2828
  private pushVaultFiles;
2829
+ /**
2830
+ * 폴더 첨부를 노트의 페이지에 붙이거나 지울 때({@link NotePageWrites}) — 쓰기 전에 원격과 맞던 노트만 쓴 뒤의 원격을 본
2831
+ * 것으로 적는다. 받지 않은 Notion 편집이 걸린 노트를 적으면 다음 pull 이 그 편집을 받지 않는다. 읽지 못하면 적지 않는다 —
2832
+ * 다음 push 가 그 노트를 올리지 않고 pull 을 먼저 하라고 알릴 뿐이다.
2833
+ */
2834
+ private notePageWrites;
2824
2835
  /**
2825
2836
  * @param mergedByPull sync dry-run 만 — 앞선 pull dry-run 이 합칠 노트. 실제 sync 는 합친 뒤 원격을 본 것으로
2826
2837
  * 적어 push 가 올린다 — dry-run 은 받지 않아 원격이 바뀐 그대로라, 원격을 보고 거절하지 않는다.
@@ -3329,6 +3340,21 @@ interface FileHandlerOptions {
3329
3340
  * 파일을. 기본 false.
3330
3341
  */
3331
3342
  readonly deleteSync?: boolean;
3343
+ /**
3344
+ * 볼트 맨 위 파일을 싣는 페이지({@link rootFilesPageOf}) — 페이지 모드의 루트. 없으면(DB 모드) 볼트 맨 위 파일은 경고로 남는다.
3345
+ * 루트는 사용자의 페이지라 노트 페이지처럼 적어 둔 폴더 첨부만 제 것으로 본다.
3346
+ */
3347
+ readonly rootPageId?: string | null;
3348
+ }
3349
+ /**
3350
+ * 노트의 페이지에 폴더 첨부 블록을 붙이거나 지울 때(ADR-056) — 그 쓰기로 노트 페이지의 수정 시각 · 본문이 바뀐다. 알리지 않으면
3351
+ * 다음 push 가 그 노트를 «Notion 에서도 바뀐 페이지» 로 보고 올리지 않는다.
3352
+ */
3353
+ interface NotePageWrites {
3354
+ /** 쓰기 전 — 그 노트가 지금 원격과 맞는지 본다. */
3355
+ begin(pageId: string): Promise<void>;
3356
+ /** 쓴 뒤 — 맞던 노트는 지금 원격을 본 것으로 적는다. 맞지 않던 노트(받지 않은 Notion 편집)는 그대로 둔다. */
3357
+ end(pageId: string): Promise<void>;
3332
3358
  }
3333
3359
  /** 노트 없는 폴더의 Notion 페이지를 마련하는 쪽 — push 의 폴더 배치(`FolderPlacement`). */
3334
3360
  interface FolderPageProvider {
@@ -3356,6 +3382,7 @@ declare class FileHandler {
3356
3382
  private readonly itemTimeoutMs;
3357
3383
  private readonly attachmentsFolder;
3358
3384
  private readonly deleteSync;
3385
+ private readonly rootPageId;
3359
3386
  constructor(vaultFs: VaultFS, notionClient: NotionClient, stateDb: IStateDB, concurrency?: number, options?: FileHandlerOptions);
3360
3387
  private get fetchFn();
3361
3388
  pushFilesForFolder(folderPageId: string, folderPath: string): Promise<FileUploadResult[]>;
@@ -3376,12 +3403,31 @@ declare class FileHandler {
3376
3403
  * @returns 업로드 결과. 변경 없음(스킵)이거나 실패했으면 null.
3377
3404
  */
3378
3405
  private pushSingleFile;
3379
- /** 올린 뒤 바뀌지 않았나 — 크기가 같으면 읽지 않는다. */
3406
+ /**
3407
+ * 올리거나 받은 뒤 바뀌지 않았나 — 그때의 표(크기 · 수정 시각, {@link fileStampOf})와 같으면 읽지 않는다. 크기가 다르면 바뀌었다.
3408
+ * 크기만 같으면 내용으로 견주고, 같으면 지금 표를 적어 다음에는 읽지 않는다. 예전에는 크기가 같으면 바뀌지 않았다고 봐, 같은
3409
+ * 크기로 고친 파일을 올리지 않았다.
3410
+ */
3380
3411
  private isUnchanged;
3381
3412
  /** pull 이 받은 것을 두는 폴더 안인가. */
3382
3413
  private inAttachmentsFolder;
3383
- /** 폴더 첨부를 둘 Notion 페이지 — 폴더 노트 없는 폴더의 페이지(폴더 레코드)만. 맨 위는 루트 기록이 있을 때만. */
3414
+ /**
3415
+ * 폴더 첨부를 둘 Notion 페이지 — 그 폴더의 Notion 자리({@link folderContainer} 와 같은 차례). 폴더 노트(`X/X.md`)나 노트
3416
+ * 이름의 폴더(`X.md` 옆 `X/`)면 그 노트의 페이지 끝(ADR-056), 아니면 push 가 만든 폴더 페이지. 맨 위는 루트 페이지 끝.
3417
+ * 행 이름의 폴더(`DB/행/`)는 그 행의 페이지 끝. DB 폴더는 둘 곳이 없다 — Notion 의 DB 는 본문이 없다.
3418
+ */
3384
3419
  private folderPageOf;
3420
+ /**
3421
+ * 이 폴더를 품은 노트의 페이지 — 폴더 노트 · 노트(행 포함) 이름의 폴더 · 볼트 맨 위는 루트 페이지. 본문이 이 도구의 것이
3422
+ * 아니거나(루트) 노트의 것이라, 적어 둔 폴더 첨부만 제 것으로 본다. 없으면 null.
3423
+ */
3424
+ private notePageOf;
3425
+ private folderRecordPageOf;
3426
+ /**
3427
+ * 이 기록이 그 폴더의 폴더 첨부인가. 노트의 페이지에는 그 노트가 임베드해 올린 파일도 같은 페이지로 적혀 있다 — 폴더
3428
+ * 첨부로 적어 둔 것({@link folderFileIdsOf})만이다.
3429
+ */
3430
+ private isFolderFileEntry;
3385
3431
  /**
3386
3432
  * 업로드 후보 목록 — 도구 내부 산출물(`.base`/`.notion.json`)은 아예 빼고, Notion 이 받지 않는
3387
3433
  * 형식은 따로 모은다.
@@ -3400,12 +3446,14 @@ declare class FileHandler {
3400
3446
  * @param failed 올리지 못한 첨부를 담을 곳 — push 결과의 `failed` 를 넘기면 CLI · 플러그인이 처리하지 못한 것으로
3401
3447
  * 보인다. 예전엔 경고 로그로만 남아 push 가 「실패 0」 으로 끝났다.
3402
3448
  */
3403
- pushAllFiles(failed?: FailedOperation[], folders?: FolderPageProvider): Promise<FileUploadResult[]>;
3449
+ pushAllFiles(failed?: FailedOperation[], folders?: FolderPageProvider, noteWrites?: NotePageWrites): Promise<FileUploadResult[]>;
3404
3450
  /**
3405
3451
  * 볼트에서 지운 폴더 첨부를 Notion 에서도 지운다(deleteSync) — 폴더 페이지에 적힌 파일 가운데 볼트에 없는 것의 블록과 기록.
3406
3452
  * 포함 · 제외 패턴으로 빠진 파일은 볼트에 있어 지우지 않는다.
3407
3453
  */
3408
3454
  private removeDeletedFolderFiles;
3455
+ /** 노트의 페이지에 쓰는 동안을 알린다({@link NotePageWrites}) — 폴더 페이지는 노트가 없어 알릴 것이 없다. */
3456
+ private writingNotePage;
3409
3457
  /** 폴더 첨부를 둘 페이지 — 노트 없는 폴더면 마련한다. 둘 곳이 없으면 그 파일들을 `stranded` 에 담고 null. */
3410
3458
  private provideFolderPage;
3411
3459
  /**
@@ -3444,11 +3492,23 @@ declare class FileHandler {
3444
3492
  caption?: string;
3445
3493
  }>, targetFolder: string): Promise<FileDownloadResult[]>;
3446
3494
  private uploadFile;
3447
- /** 이 페이지에서 같은 이름의 파일 블록 중 방금 붙인 것 말고를 지운다. */
3495
+ /**
3496
+ * 처음 보는 파일이 이 페이지에 적어 둔 같은 이름의 폴더 첨부를 옮긴 것인가 — 그 기록의 경로가 볼트에서 사라졌으면 옮겼다(폴더 ·
3497
+ * 폴더 노트 · 노트의 이름 바꾸기). 기록 · 파일 id · 표를 새 경로로 옮긴다. `same` 이면 내용이 같아 올리지 않는다. 다르면 옮긴
3498
+ * 기록을 옛 것으로 올려 옛 블록을 지운다. 예전에는 새 파일로 올려 노트 페이지에 같은 파일의 블록이 둘 남았다.
3499
+ */
3500
+ private movedHere;
3501
+ /**
3502
+ * 이 페이지에서 그 폴더 첨부의 블록 중 방금 붙인 것(`keep`) 말고를 지운다. 폴더 페이지는 같은 이름의 파일 블록 모두(id 를
3503
+ * 적기 전에 올린 블록도). 노트의 페이지는 노트가 임베드한 같은 이름의 파일이 있을 수 있어, 적어 둔 Notion 파일 id 의 블록과
3504
+ * 표시를 단 캡션({@link folderFileCaption})의 블록만 — 다른 볼트가 같은 파일을 먼저 고쳐 올린 블록은 id 를 모르지만 표시가 있다.
3505
+ * 예전에는 id 로만 지워, 두 볼트가 따로 고쳐 올리면 블록이 둘 남았다.
3506
+ */
3448
3507
  private removeOlderBlocks;
3449
3508
  /**
3450
- * 폴더 첨부의 파일 블록 — 캡션에 파일 이름을 적는다. 받는 쪽이 그 표시로 폴더 첨부를 알아본다({@link folderFilesOf}) —
3451
- * 자식 페이지가 없는 폴더 페이지는 PDF 하나만 붙인 노트와 모양이 같다.
3509
+ * 폴더 첨부의 파일 블록 — 캡션에 표시를 단 파일 이름을 적는다({@link folderFileCaption}). 받는 쪽이 그 표시로 폴더 첨부를
3510
+ * 알아본다 — 자식 페이지가 없는 폴더 페이지는 PDF 하나만 붙인 노트와 모양이 같고, 노트 페이지의 폴더 첨부는 그 노트의
3511
+ * 임베드와 같은 블록이다.
3452
3512
  */
3453
3513
  private createFileBlock;
3454
3514
  private extractFilename;
@@ -3683,6 +3743,11 @@ interface RowProgress {
3683
3743
  planned(count: number): void;
3684
3744
  done(item: ProgressItem): void;
3685
3745
  }
3746
+ /** 행 페이지 끝에서 뗀 폴더 첨부 — `complete` 면 빠진 파일을 Notion 에서 지운 것으로 본다. */
3747
+ interface RowFolderFiles {
3748
+ readonly files: readonly FolderFileRef[];
3749
+ readonly complete: boolean;
3750
+ }
3686
3751
  declare class DatabaseSyncer {
3687
3752
  private readonly config;
3688
3753
  private readonly stateDb;
@@ -3700,6 +3765,8 @@ declare class DatabaseSyncer {
3700
3765
  * 채운다({@link RemoteDetector.noteBodyChildren}).
3701
3766
  */
3702
3767
  private readonly noteRowBody;
3768
+ /** 행 이름의 폴더에 그 행 페이지의 폴더 첨부를 받는다(ADR-056) — `PagePuller.receiveFolderFiles`. */
3769
+ private readonly receiveRowFiles;
3703
3770
  private readonly propertyMapper;
3704
3771
  private decorationsCache?;
3705
3772
  /**
@@ -3759,7 +3826,9 @@ declare class DatabaseSyncer {
3759
3826
  * 받은 행 본문(Notion 원문)을 알린다 — 감지가 행의 하위 페이지를 빠뜨렸을 때 그 본문의 자식 태그로
3760
3827
  * 채운다({@link RemoteDetector.noteBodyChildren}).
3761
3828
  */
3762
- noteRowBody?: (pageId: string, rawMarkdown: string) => void);
3829
+ noteRowBody?: (pageId: string, rawMarkdown: string) => void,
3830
+ /** 행 이름의 폴더에 그 행 페이지의 폴더 첨부를 받는다(ADR-056) — `PagePuller.receiveFolderFiles`. */
3831
+ receiveRowFiles?: (folder: string, pageId: string, files: readonly FolderFileRef[], complete: boolean) => Promise<void>);
3763
3832
  pullAll(opts?: {
3764
3833
  readonly paths?: readonly string[];
3765
3834
  readonly progress?: RowProgress;
@@ -4021,6 +4090,8 @@ declare class DatabaseSyncer {
4021
4090
  bodyFingerprint: string;
4022
4091
  /** 원격 본문에 페이지 시절의 속성 블록이 있었나 — 받으며 걷어 냈다. */
4023
4092
  propertiesBlock: boolean;
4093
+ /** 행 끝에서 뗀 폴더 첨부(ADR-056 · 행 이름의 폴더) — 받는 것은 호출측이 정한다. */
4094
+ folderFiles: RowFolderFiles;
4024
4095
  }>;
4025
4096
  /**
4026
4097
  * 행의 본문 밖이 지난 동기화 사본 그대로인가(N-05) — 제목과 보낼 수 있는 속성, 아이콘 · 커버.
@@ -4107,6 +4178,11 @@ declare class DatabaseSyncer {
4107
4178
  * 든다. 추적하는 노트가 없으면 null.
4108
4179
  */
4109
4180
  private adoptedChildrenOf;
4181
+ /**
4182
+ * 이 노트 · 행 옆의 폴더(`from`)가 그것의 것인가 — 하위 페이지가 있거나, 그 페이지에 올린 폴더 첨부(ADR-056)가 든 폴더.
4183
+ * 예전에는 하위 페이지만 보아 행의 이름을 따라 옮길 때 폴더 첨부만 든 폴더가 옛 이름에 남았다.
4184
+ */
4185
+ private holdsChildren;
4110
4186
  /**
4111
4187
  * Notion 에서 바꾼 제목으로 행 이름을 바꿀 자리(`sync.renameOnTitleChange`) — 바꿀 것이 없으면 null.
4112
4188
  * 받기 · pull dry-run · status 가 같은 판정을 쓴다. 행의 하위 페이지 폴더(`행/`)도 새 이름으로 옮기며, 옮길 수
@@ -4118,7 +4194,12 @@ declare class DatabaseSyncer {
4118
4194
  } | {
4119
4195
  reason: string;
4120
4196
  } | null>;
4197
+ /**
4198
+ * 행 하나를 받고 그 행 페이지의 폴더 첨부를 행 이름의 폴더에 받는다(ADR-056) — 노트가 충돌로 남거나 로컬을 지켜도 파일은
4199
+ * 제 규칙대로 받는다(페이지와 같다). 행을 옮겼으면 옮긴 자리로.
4200
+ */
4121
4201
  private pullDatabasePage;
4202
+ private pullDatabaseRow;
4122
4203
  }
4123
4204
 
4124
4205
  declare class FrontmatterExtractor implements Processor {