@repo-toolkit/confluence 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.
Files changed (5) hide show
  1. package/README.md +90 -12
  2. package/cli.js +556 -6
  3. package/index.d.ts +130 -1
  4. package/index.js +540 -4
  5. package/package.json +2 -2
package/index.d.ts CHANGED
@@ -18,6 +18,7 @@ declare function isRemoteUrl(src: string): boolean;
18
18
  declare function escapeXmlAttribute(text: string): string;
19
19
  declare function escapeAttachmentFilename(filename: string): string;
20
20
 
21
+ declare const CONFLUENCE_MANAGED_LABEL = "repo-toolkit-confluence";
21
22
  interface ConfluenceClientOptions {
22
23
  baseUrl: string;
23
24
  username: string;
@@ -59,6 +60,23 @@ interface ConfluenceGateway extends AttachmentGateway {
59
60
  getPage(pageId: string): Promise<Page>;
60
61
  createPage(input: CreatePageInput): Promise<Page>;
61
62
  updatePage(input: UpdatePageInput): Promise<Page>;
63
+ getPageDescendants(pageId: string): Promise<PageDescendant[]>;
64
+ getPageLabels(pageId: string): Promise<PageLabel[]>;
65
+ addManagedLabel(pageId: string): Promise<void>;
66
+ deletePage(pageId: string): Promise<void>;
67
+ }
68
+ interface PageDescendant {
69
+ id: string;
70
+ type: string;
71
+ title?: string;
72
+ parentId?: string;
73
+ depth?: number;
74
+ status?: string;
75
+ }
76
+ interface PageLabel {
77
+ name: string;
78
+ prefix: string;
79
+ id?: string;
62
80
  }
63
81
  interface PageBody {
64
82
  representation: 'storage' | 'atlas_doc' | 'wiki' | 'view' | 'export_view';
@@ -145,6 +163,11 @@ declare class ConfluenceClient implements ConfluenceGateway {
145
163
  getPage(pageId: string): Promise<Page>;
146
164
  createPage(input: CreatePageInput): Promise<Page>;
147
165
  updatePage(input: UpdatePageInput): Promise<Page>;
166
+ getPageDescendants(pageId: string): Promise<PageDescendant[]>;
167
+ getPageLabels(pageId: string): Promise<PageLabel[]>;
168
+ addManagedLabel(pageId: string): Promise<void>;
169
+ deletePage(pageId: string): Promise<void>;
170
+ private listAll;
148
171
  getAttachments(pageId: string): Promise<Attachment[]>;
149
172
  uploadAttachment(pageId: string, filePath: string, comment?: string, filename?: string): Promise<Attachment>;
150
173
  updateAttachmentData(pageId: string, attachmentId: string, filePath: string, comment?: string, filename?: string): Promise<Attachment>;
@@ -351,6 +374,19 @@ interface ConfluenceSyncOptions {
351
374
  renderHtmlBlocks?: boolean;
352
375
  /** Repository URL appended to synced pages as an italic source notice. */
353
376
  repositoryUrl?: string;
377
+ /**
378
+ * Destructive reset (default: false). When true, a real sync first moves
379
+ * every page descendant of `parentPageId` — including manual/unlabeled
380
+ * pages — to the Confluence trash, then recreates the local hierarchy.
381
+ * `parentPageId` itself is never deleted.
382
+ */
383
+ clean?: boolean;
384
+ /**
385
+ * Update the target parent summary (default: true). When true, a successful
386
+ * real sync fetches and merges a deterministic tool-managed region into the
387
+ * parent page body, preserving all external content.
388
+ */
389
+ updateParentPage?: boolean;
354
390
  /**
355
391
  * Dry-run: walk the tree and validate every markdown file and local image
356
392
  * source (same preflight as a real sync) then print the plan, but make no
@@ -381,6 +417,10 @@ interface ConfluenceSyncPlan {
381
417
  dryRun: boolean;
382
418
  renderHtmlBlocks: boolean;
383
419
  repositoryUrl: string;
420
+ /** Destructive reset flag; resolved from {@link ConfluenceSyncOptions.clean} with default false. */
421
+ clean: boolean;
422
+ /** Parent-summary flag; resolved from {@link ConfluenceSyncOptions.updateParentPage} with default true. */
423
+ updateParentPage: boolean;
384
424
  /** Validated leaf page title strategy applied during planning. */
385
425
  pageTitleStrategy: PageTitleStrategy;
386
426
  }
@@ -481,8 +521,97 @@ declare class SyncMutationError extends Error {
481
521
  * when a full run completes without error. */
482
522
  interface SyncResult {
483
523
  changes: ReadonlyArray<SyncChange>;
524
+ /** Page ids that received the global ownership marker during this run. */
525
+ labelsAdded: ReadonlyArray<string>;
526
+ /** Page ids trashed by the explicit `clean: true` pre-sync reset. */
527
+ cleanDeletions: ReadonlyArray<string>;
528
+ /** Page ids trashed by the default label-gated prune after a successful sync. */
529
+ pruneDeletions: ReadonlyArray<string>;
530
+ /** Stale labeled pages retained because an unlabeled, non-page, or otherwise
531
+ * retained descendant made deletion unsafe. */
532
+ blocked: ReadonlyArray<string>;
533
+ /** Parent-summary outcome: `updated` when the parent body changed, `unchanged` when already equal, `skipped` when opt-out. */
534
+ parentStatus: 'updated' | 'unchanged' | 'skipped';
535
+ }
536
+ /** A single failed clean/prune deletion. */
537
+ interface ReconciliationFailure {
538
+ pageId: string;
539
+ error: Error;
540
+ }
541
+ /**
542
+ * Structured partial-mutation report for the clean and prune phases. Thrown
543
+ * when trashing a page fails mid-phase. Carries every completed deletion, the
544
+ * failed page, and the planned deletions that were never attempted.
545
+ */
546
+ declare class ReconciliationError extends Error {
547
+ readonly phase: 'clean' | 'prune';
548
+ readonly completed: ReadonlyArray<string>;
549
+ readonly failure: ReconciliationFailure;
550
+ readonly unprocessed: ReadonlyArray<string>;
551
+ constructor(input: {
552
+ phase: 'clean' | 'prune';
553
+ completed: ReadonlyArray<string>;
554
+ failure: ReconciliationFailure;
555
+ unprocessed: ReadonlyArray<string>;
556
+ });
484
557
  }
558
+ declare class ParentSummaryError extends Error {
559
+ readonly phase: 'parent-summary';
560
+ readonly changes: ReadonlyArray<SyncChange>;
561
+ readonly labelsAdded: ReadonlyArray<string>;
562
+ readonly cleanDeletions: ReadonlyArray<string>;
563
+ readonly pruneDeletions: ReadonlyArray<string>;
564
+ readonly blocked: ReadonlyArray<string>;
565
+ readonly failure: ReconciliationFailure;
566
+ constructor(input: {
567
+ changes: ReadonlyArray<SyncChange>;
568
+ labelsAdded: ReadonlyArray<string>;
569
+ cleanDeletions: ReadonlyArray<string>;
570
+ pruneDeletions: ReadonlyArray<string>;
571
+ blocked: ReadonlyArray<string>;
572
+ failure: ReconciliationFailure;
573
+ });
574
+ }
575
+ /** One inventoried descendant of the target page, annotated with ownership. */
576
+ interface RemoteInventoryEntry {
577
+ id: string;
578
+ type: string;
579
+ parentId?: string;
580
+ depth?: number;
581
+ title?: string;
582
+ /** Whether the page carries the exact global ownership marker. */
583
+ labeled: boolean;
584
+ }
585
+ /** Outcome of the pure deletion planners. */
586
+ interface DeletionPlan {
587
+ /** Page ids to trash, ordered deepest-first (children before parents). */
588
+ deletions: ReadonlyArray<string>;
589
+ /** Stale labeled pages retained because deleting them would also remove a
590
+ * retained (unlabeled, non-page, or expected) descendant. */
591
+ blocked: ReadonlyArray<string>;
592
+ }
593
+ /**
594
+ * Pure label-gated stale-page planner. Protects the target page, expected
595
+ * (mapped) ids, unlabeled pages, non-page content, and any stale page with a
596
+ * retained descendant. Throws when the inventory is too incomplete to verify
597
+ * ancestry safely.
598
+ */
599
+ declare function planStalePruning(input: {
600
+ parentPageId: string;
601
+ expectedIds: ReadonlySet<string>;
602
+ inventory: ReadonlyArray<RemoteInventoryEntry>;
603
+ }): DeletionPlan;
604
+ /**
605
+ * Pure explicit-clean planner. Trash every page descendant regardless of
606
+ * label. Fails closed before any deletion when the subtree contains non-page
607
+ * content whose retention cannot be proven, or when the inventory is
608
+ * incomplete.
609
+ */
610
+ declare function planCleanDeletions(input: {
611
+ parentPageId: string;
612
+ inventory: ReadonlyArray<RemoteInventoryEntry>;
613
+ }): DeletionPlan;
485
614
  declare function resolveConfluenceSyncPlan(options?: ConfluenceSyncOptions): ConfluenceSyncPlan;
486
615
  declare function syncConfluenceToDocs(options?: ConfluenceSyncOptions): Promise<SyncResult | void>;
487
616
 
488
- export { type Attachment, type AttachmentGateway, type PreflightResult as AttachmentPreflightResult, ConfluenceApiError, ConfluenceClient, type ConfluenceClientOptions, type ConfluenceGateway, type ConfluenceSyncOptions, type ConfluenceSyncPlan, type CreatePageInput, DEFAULT_PAGE_TITLE_STRATEGY, type DocEntry, type DocTree, INTERACTIVE_FLAG, type LocalSyncEntryPlan, type LocalSyncPlan, LocalSyncValidationAggregateError, type LocalSyncValidationError, type MarkdownConvertOptions, type MarkdownConvertResult, type MermaidBlock, type MermaidPreflightResult, type MermaidRewriteOptions, type MermaidRewriteResult, PAGE_TITLE_STRATEGIES, type Page, type PageBody, type PageTitleStrategy, type PageVersion, type RewriteOptions, type RewriteResult, type SyncChange, type SyncFailure, SyncMutationError, type SyncResult, type UpdatePageInput, type ValidatedAttachmentSource, escapeAttachmentFilename, escapeXmlAttribute, isAllowedUrl, isMarkdownName, isRemoteUrl, markdownToStorage, pageTitleFromSegments, preflightImagesToAttachments, preflightMermaidBlocks, readDocTree, resolveConfluenceSyncPlan, resolvePageTitleStrategy, resolveConfluenceSyncPlan as resolveSyncPlan, rewriteImagesToAttachments, rewriteMermaidBlocks, syncConfluenceToDocs, titleFromSegment, validateAttachmentSources, validateLocalSync };
617
+ export { type Attachment, type AttachmentGateway, type PreflightResult as AttachmentPreflightResult, CONFLUENCE_MANAGED_LABEL, ConfluenceApiError, ConfluenceClient, type ConfluenceClientOptions, type ConfluenceGateway, type ConfluenceSyncOptions, type ConfluenceSyncPlan, type CreatePageInput, DEFAULT_PAGE_TITLE_STRATEGY, type DeletionPlan, type DocEntry, type DocTree, INTERACTIVE_FLAG, type LocalSyncEntryPlan, type LocalSyncPlan, LocalSyncValidationAggregateError, type LocalSyncValidationError, type MarkdownConvertOptions, type MarkdownConvertResult, type MermaidBlock, type MermaidPreflightResult, type MermaidRewriteOptions, type MermaidRewriteResult, PAGE_TITLE_STRATEGIES, type Page, type PageBody, type PageDescendant, type PageLabel, type PageTitleStrategy, type PageVersion, ParentSummaryError, ReconciliationError, type ReconciliationFailure, type RemoteInventoryEntry, type RewriteOptions, type RewriteResult, type SyncChange, type SyncFailure, SyncMutationError, type SyncResult, type UpdatePageInput, type ValidatedAttachmentSource, escapeAttachmentFilename, escapeXmlAttribute, isAllowedUrl, isMarkdownName, isRemoteUrl, markdownToStorage, pageTitleFromSegments, planCleanDeletions, planStalePruning, preflightImagesToAttachments, preflightMermaidBlocks, readDocTree, resolveConfluenceSyncPlan, resolvePageTitleStrategy, resolveConfluenceSyncPlan as resolveSyncPlan, rewriteImagesToAttachments, rewriteMermaidBlocks, syncConfluenceToDocs, titleFromSegment, validateAttachmentSources, validateLocalSync };