@real1ty-obsidian-plugins/utils 2.15.0 → 2.16.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.
@@ -6,6 +6,7 @@ export interface FrontmatterPropagationModalOptions {
6
6
  instanceCount: number;
7
7
  onConfirm: () => void | Promise<void>;
8
8
  onCancel?: () => void | Promise<void>;
9
+ cssPrefix?: string;
9
10
  }
10
11
  export declare class FrontmatterPropagationModal extends Modal {
11
12
  private options;
@@ -1 +1 @@
1
- {"version":3,"file":"frontmatter-propagation-modal.d.ts","sourceRoot":"","sources":["../../src/components/frontmatter-propagation-modal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,GAAG,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAE3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAGhE,MAAM,WAAW,kCAAkC;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,eAAe,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,QAAQ,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AAED,qBAAa,2BAA4B,SAAQ,KAAK;IACrD,OAAO,CAAC,OAAO,CAAqC;gBAExC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,kCAAkC;IAKjE,MAAM,IAAI,IAAI;IAqFd,OAAO,IAAI,IAAI;CAIf"}
1
+ {"version":3,"file":"frontmatter-propagation-modal.d.ts","sourceRoot":"","sources":["../../src/components/frontmatter-propagation-modal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,GAAG,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAE3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAGhE,MAAM,WAAW,kCAAkC;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,eAAe,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,QAAQ,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,2BAA4B,SAAQ,KAAK;IACrD,OAAO,CAAC,OAAO,CAAqC;gBAExC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,kCAAkC;IAKjE,MAAM,IAAI,IAAI;IAwFd,OAAO,IAAI,IAAI;CAIf"}
@@ -6,47 +6,51 @@ export class FrontmatterPropagationModal extends Modal {
6
6
  this.options = options;
7
7
  }
8
8
  onOpen() {
9
+ var _a;
9
10
  const { contentEl } = this;
11
+ const prefix = (_a = this.options.cssPrefix) !== null && _a !== void 0 ? _a : "frontmatter-propagation";
10
12
  contentEl.empty();
11
13
  contentEl.createEl("h2", { text: "Propagate frontmatter changes?" });
12
14
  contentEl.createEl("p", {
13
15
  text: `The recurring event "${this.options.eventTitle}" has frontmatter changes. Do you want to apply these changes to all ${this.options.instanceCount} physical instances?`,
14
16
  });
15
- const changesContainer = contentEl.createDiv({ cls: "prisma-frontmatter-changes" });
17
+ const changesContainer = contentEl.createDiv({ cls: `${prefix}-frontmatter-changes` });
16
18
  if (this.options.diff.added.length > 0) {
17
- const addedSection = changesContainer.createDiv({ cls: "prisma-changes-section" });
19
+ const addedSection = changesContainer.createDiv({
20
+ cls: `${prefix}-frontmatter-changes-section`,
21
+ });
18
22
  addedSection.createEl("h4", { text: "Added properties:" });
19
23
  const addedList = addedSection.createEl("ul");
20
24
  for (const change of this.options.diff.added) {
21
25
  addedList.createEl("li", {
22
26
  text: formatChangeForDisplay(change),
23
- cls: "prisma-change-added",
27
+ cls: `${prefix}-change-added`,
24
28
  });
25
29
  }
26
30
  }
27
31
  if (this.options.diff.modified.length > 0) {
28
- const modifiedSection = changesContainer.createDiv({ cls: "prisma-changes-section" });
32
+ const modifiedSection = changesContainer.createDiv({ cls: `${prefix}-changes-section` });
29
33
  modifiedSection.createEl("h4", { text: "Modified properties:" });
30
34
  const modifiedList = modifiedSection.createEl("ul");
31
35
  for (const change of this.options.diff.modified) {
32
36
  modifiedList.createEl("li", {
33
37
  text: formatChangeForDisplay(change),
34
- cls: "prisma-change-modified",
38
+ cls: `${prefix}-change-modified`,
35
39
  });
36
40
  }
37
41
  }
38
42
  if (this.options.diff.deleted.length > 0) {
39
- const deletedSection = changesContainer.createDiv({ cls: "prisma-changes-section" });
43
+ const deletedSection = changesContainer.createDiv({ cls: `${prefix}-changes-section` });
40
44
  deletedSection.createEl("h4", { text: "Deleted properties:" });
41
45
  const deletedList = deletedSection.createEl("ul");
42
46
  for (const change of this.options.diff.deleted) {
43
47
  deletedList.createEl("li", {
44
48
  text: formatChangeForDisplay(change),
45
- cls: "prisma-change-deleted",
49
+ cls: `${prefix}-change-deleted`,
46
50
  });
47
51
  }
48
52
  }
49
- const buttonContainer = contentEl.createDiv({ cls: "prisma-modal-buttons" });
53
+ const buttonContainer = contentEl.createDiv({ cls: `${prefix}-modal-buttons` });
50
54
  const yesButton = buttonContainer.createEl("button", {
51
55
  text: "Yes, propagate",
52
56
  cls: "mod-cta",
@@ -1 +1 @@
1
- {"version":3,"file":"frontmatter-propagation-modal.js","sourceRoot":"","sources":["../../src/components/frontmatter-propagation-modal.ts"],"names":[],"mappings":"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","sourcesContent":["import { type App, Modal } from \"obsidian\";\n\nimport type { FrontmatterDiff } from \"../file/frontmatter-diff\";\nimport { formatChangeForDisplay } from \"../file/frontmatter-diff\";\n\nexport interface FrontmatterPropagationModalOptions {\n\teventTitle: string;\n\tdiff: FrontmatterDiff;\n\tinstanceCount: number;\n\tonConfirm: () => void | Promise<void>;\n\tonCancel?: () => void | Promise<void>;\n}\n\nexport class FrontmatterPropagationModal extends Modal {\n\tprivate options: FrontmatterPropagationModalOptions;\n\n\tconstructor(app: App, options: FrontmatterPropagationModalOptions) {\n\t\tsuper(app);\n\t\tthis.options = options;\n\t}\n\n\tonOpen(): void {\n\t\tconst { contentEl } = this;\n\n\t\tcontentEl.empty();\n\n\t\tcontentEl.createEl(\"h2\", { text: \"Propagate frontmatter changes?\" });\n\n\t\tcontentEl.createEl(\"p\", {\n\t\t\ttext: `The recurring event \"${this.options.eventTitle}\" has frontmatter changes. Do you want to apply these changes to all ${this.options.instanceCount} physical instances?`,\n\t\t});\n\n\t\tconst changesContainer = contentEl.createDiv({ cls: \"prisma-frontmatter-changes\" });\n\n\t\tif (this.options.diff.added.length > 0) {\n\t\t\tconst addedSection = changesContainer.createDiv({ cls: \"prisma-changes-section\" });\n\t\t\taddedSection.createEl(\"h4\", { text: \"Added properties:\" });\n\t\t\tconst addedList = addedSection.createEl(\"ul\");\n\n\t\t\tfor (const change of this.options.diff.added) {\n\t\t\t\taddedList.createEl(\"li\", {\n\t\t\t\t\ttext: formatChangeForDisplay(change),\n\t\t\t\t\tcls: \"prisma-change-added\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tif (this.options.diff.modified.length > 0) {\n\t\t\tconst modifiedSection = changesContainer.createDiv({ cls: \"prisma-changes-section\" });\n\t\t\tmodifiedSection.createEl(\"h4\", { text: \"Modified properties:\" });\n\t\t\tconst modifiedList = modifiedSection.createEl(\"ul\");\n\n\t\t\tfor (const change of this.options.diff.modified) {\n\t\t\t\tmodifiedList.createEl(\"li\", {\n\t\t\t\t\ttext: formatChangeForDisplay(change),\n\t\t\t\t\tcls: \"prisma-change-modified\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tif (this.options.diff.deleted.length > 0) {\n\t\t\tconst deletedSection = changesContainer.createDiv({ cls: \"prisma-changes-section\" });\n\t\t\tdeletedSection.createEl(\"h4\", { text: \"Deleted properties:\" });\n\t\t\tconst deletedList = deletedSection.createEl(\"ul\");\n\n\t\t\tfor (const change of this.options.diff.deleted) {\n\t\t\t\tdeletedList.createEl(\"li\", {\n\t\t\t\t\ttext: formatChangeForDisplay(change),\n\t\t\t\t\tcls: \"prisma-change-deleted\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tconst buttonContainer = contentEl.createDiv({ cls: \"prisma-modal-buttons\" });\n\n\t\tconst yesButton = buttonContainer.createEl(\"button\", {\n\t\t\ttext: \"Yes, propagate\",\n\t\t\tcls: \"mod-cta\",\n\t\t});\n\n\t\tyesButton.addEventListener(\"click\", () => {\n\t\t\tvoid Promise.resolve(this.options.onConfirm())\n\t\t\t\t.then(() => {\n\t\t\t\t\tthis.close();\n\t\t\t\t})\n\t\t\t\t.catch((error) => {\n\t\t\t\t\tconsole.error(\"Error in onConfirm callback:\", error);\n\t\t\t\t\tthis.close();\n\t\t\t\t});\n\t\t});\n\n\t\tconst noButton = buttonContainer.createEl(\"button\", { text: \"No, skip\" });\n\n\t\tnoButton.addEventListener(\"click\", () => {\n\t\t\tconst result = this.options.onCancel?.();\n\n\t\t\tif (result instanceof Promise) {\n\t\t\t\tvoid result.catch((error) => {\n\t\t\t\t\tconsole.error(\"Error in onCancel callback:\", error);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tthis.close();\n\t\t});\n\t}\n\n\tonClose(): void {\n\t\tconst { contentEl } = this;\n\t\tcontentEl.empty();\n\t}\n}\n"]}
1
+ {"version":3,"file":"frontmatter-propagation-modal.js","sourceRoot":"","sources":["../../src/components/frontmatter-propagation-modal.ts"],"names":[],"mappings":"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","sourcesContent":["import { type App, Modal } from \"obsidian\";\n\nimport type { FrontmatterDiff } from \"../file/frontmatter-diff\";\nimport { formatChangeForDisplay } from \"../file/frontmatter-diff\";\n\nexport interface FrontmatterPropagationModalOptions {\n\teventTitle: string;\n\tdiff: FrontmatterDiff;\n\tinstanceCount: number;\n\tonConfirm: () => void | Promise<void>;\n\tonCancel?: () => void | Promise<void>;\n\tcssPrefix?: string;\n}\n\nexport class FrontmatterPropagationModal extends Modal {\n\tprivate options: FrontmatterPropagationModalOptions;\n\n\tconstructor(app: App, options: FrontmatterPropagationModalOptions) {\n\t\tsuper(app);\n\t\tthis.options = options;\n\t}\n\n\tonOpen(): void {\n\t\tconst { contentEl } = this;\n\t\tconst prefix = this.options.cssPrefix ?? \"frontmatter-propagation\";\n\n\t\tcontentEl.empty();\n\n\t\tcontentEl.createEl(\"h2\", { text: \"Propagate frontmatter changes?\" });\n\n\t\tcontentEl.createEl(\"p\", {\n\t\t\ttext: `The recurring event \"${this.options.eventTitle}\" has frontmatter changes. Do you want to apply these changes to all ${this.options.instanceCount} physical instances?`,\n\t\t});\n\n\t\tconst changesContainer = contentEl.createDiv({ cls: `${prefix}-frontmatter-changes` });\n\n\t\tif (this.options.diff.added.length > 0) {\n\t\t\tconst addedSection = changesContainer.createDiv({\n\t\t\t\tcls: `${prefix}-frontmatter-changes-section`,\n\t\t\t});\n\t\t\taddedSection.createEl(\"h4\", { text: \"Added properties:\" });\n\t\t\tconst addedList = addedSection.createEl(\"ul\");\n\n\t\t\tfor (const change of this.options.diff.added) {\n\t\t\t\taddedList.createEl(\"li\", {\n\t\t\t\t\ttext: formatChangeForDisplay(change),\n\t\t\t\t\tcls: `${prefix}-change-added`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tif (this.options.diff.modified.length > 0) {\n\t\t\tconst modifiedSection = changesContainer.createDiv({ cls: `${prefix}-changes-section` });\n\t\t\tmodifiedSection.createEl(\"h4\", { text: \"Modified properties:\" });\n\t\t\tconst modifiedList = modifiedSection.createEl(\"ul\");\n\n\t\t\tfor (const change of this.options.diff.modified) {\n\t\t\t\tmodifiedList.createEl(\"li\", {\n\t\t\t\t\ttext: formatChangeForDisplay(change),\n\t\t\t\t\tcls: `${prefix}-change-modified`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tif (this.options.diff.deleted.length > 0) {\n\t\t\tconst deletedSection = changesContainer.createDiv({ cls: `${prefix}-changes-section` });\n\t\t\tdeletedSection.createEl(\"h4\", { text: \"Deleted properties:\" });\n\t\t\tconst deletedList = deletedSection.createEl(\"ul\");\n\n\t\t\tfor (const change of this.options.diff.deleted) {\n\t\t\t\tdeletedList.createEl(\"li\", {\n\t\t\t\t\ttext: formatChangeForDisplay(change),\n\t\t\t\t\tcls: `${prefix}-change-deleted`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tconst buttonContainer = contentEl.createDiv({ cls: `${prefix}-modal-buttons` });\n\n\t\tconst yesButton = buttonContainer.createEl(\"button\", {\n\t\t\ttext: \"Yes, propagate\",\n\t\t\tcls: \"mod-cta\",\n\t\t});\n\n\t\tyesButton.addEventListener(\"click\", () => {\n\t\t\tvoid Promise.resolve(this.options.onConfirm())\n\t\t\t\t.then(() => {\n\t\t\t\t\tthis.close();\n\t\t\t\t})\n\t\t\t\t.catch((error) => {\n\t\t\t\t\tconsole.error(\"Error in onConfirm callback:\", error);\n\t\t\t\t\tthis.close();\n\t\t\t\t});\n\t\t});\n\n\t\tconst noButton = buttonContainer.createEl(\"button\", { text: \"No, skip\" });\n\n\t\tnoButton.addEventListener(\"click\", () => {\n\t\t\tconst result = this.options.onCancel?.();\n\n\t\t\tif (result instanceof Promise) {\n\t\t\t\tvoid result.catch((error) => {\n\t\t\t\t\tconsole.error(\"Error in onCancel callback:\", error);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tthis.close();\n\t\t});\n\t}\n\n\tonClose(): void {\n\t\tconst { contentEl } = this;\n\t\tcontentEl.empty();\n\t}\n}\n"]}
@@ -4,6 +4,7 @@ export * from "./evaluator";
4
4
  export * from "./expression-utils";
5
5
  export * from "./frontmatter-value";
6
6
  export * from "./generate";
7
+ export * from "./indexer";
7
8
  export * from "./property-renderer";
8
9
  export * from "./validation";
9
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC"}
@@ -4,6 +4,7 @@ export * from "./evaluator";
4
4
  export * from "./expression-utils";
5
5
  export * from "./frontmatter-value";
6
6
  export * from "./generate";
7
+ export * from "./indexer";
7
8
  export * from "./property-renderer";
8
9
  export * from "./validation";
9
10
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC","sourcesContent":["export * from \"./color-utils\";\nexport * from \"./css-utils\";\nexport * from \"./evaluator\";\nexport * from \"./expression-utils\";\nexport * from \"./frontmatter-value\";\nexport * from \"./generate\";\nexport * from \"./property-renderer\";\nexport * from \"./validation\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC","sourcesContent":["export * from \"./color-utils\";\nexport * from \"./css-utils\";\nexport * from \"./evaluator\";\nexport * from \"./expression-utils\";\nexport * from \"./frontmatter-value\";\nexport * from \"./generate\";\nexport * from \"./indexer\";\nexport * from \"./property-renderer\";\nexport * from \"./validation\";\n"]}
@@ -0,0 +1,118 @@
1
+ import { type App } from "obsidian";
2
+ import { type BehaviorSubject, type Observable } from "rxjs";
3
+ import { type FrontmatterDiff } from "../file/frontmatter-diff";
4
+ /**
5
+ * Generic frontmatter object type for indexer
6
+ */
7
+ export type IndexerFrontmatter = Record<string, unknown>;
8
+ /**
9
+ * Configuration for the generic indexer
10
+ */
11
+ export interface IndexerConfig {
12
+ /**
13
+ * Directory to scan for files (e.g., "Calendar", "Notes")
14
+ * If empty string or undefined, scans entire vault
15
+ */
16
+ directory?: string;
17
+ /**
18
+ * Properties to exclude when comparing frontmatter diffs
19
+ */
20
+ excludedDiffProps?: Set<string>;
21
+ /**
22
+ * Concurrency limit for file scanning operations
23
+ */
24
+ scanConcurrency?: number;
25
+ /**
26
+ * Debounce time in milliseconds for file change events
27
+ */
28
+ debounceMs?: number;
29
+ }
30
+ /**
31
+ * Raw file source with frontmatter and metadata
32
+ */
33
+ export interface FileSource {
34
+ filePath: string;
35
+ mtime: number;
36
+ frontmatter: IndexerFrontmatter;
37
+ folder: string;
38
+ }
39
+ /**
40
+ * Types of indexer events
41
+ */
42
+ export type IndexerEventType = "file-changed" | "file-deleted";
43
+ /**
44
+ * Generic indexer event
45
+ */
46
+ export interface IndexerEvent {
47
+ type: IndexerEventType;
48
+ filePath: string;
49
+ oldPath?: string;
50
+ source?: FileSource;
51
+ oldFrontmatter?: IndexerFrontmatter;
52
+ frontmatterDiff?: FrontmatterDiff;
53
+ }
54
+ /**
55
+ * Generic indexer that listens to Obsidian vault events and emits
56
+ * RxJS observables with frontmatter diffs and metadata.
57
+ *
58
+ * This indexer is framework-agnostic and can be used by any plugin
59
+ * that needs to track file changes with frontmatter.
60
+ */
61
+ export declare class Indexer {
62
+ private config;
63
+ private fileSub;
64
+ private configSubscription;
65
+ private vault;
66
+ private metadataCache;
67
+ private scanEventsSubject;
68
+ private indexingCompleteSubject;
69
+ private frontmatterCache;
70
+ readonly events$: Observable<IndexerEvent>;
71
+ readonly indexingComplete$: Observable<boolean>;
72
+ constructor(_app: App, configStore: BehaviorSubject<IndexerConfig>);
73
+ /**
74
+ * Start the indexer and perform initial scan
75
+ */
76
+ start(): Promise<void>;
77
+ /**
78
+ * Stop the indexer and clean up subscriptions
79
+ */
80
+ stop(): void;
81
+ /**
82
+ * Clear cache and rescan all files
83
+ */
84
+ resync(): void;
85
+ /**
86
+ * Scan all markdown files in the configured directory
87
+ */
88
+ private scanAllFiles;
89
+ /**
90
+ * Create an observable from a vault event
91
+ */
92
+ private fromVaultEvent;
93
+ /**
94
+ * Type guard to check if file is a markdown file
95
+ */
96
+ private static isMarkdownFile;
97
+ /**
98
+ * Filter to only relevant markdown files in configured directory
99
+ */
100
+ private toRelevantFiles;
101
+ /**
102
+ * Debounce events by file path
103
+ */
104
+ private debounceByPath;
105
+ /**
106
+ * Build the file system events observable stream
107
+ */
108
+ private buildFileSystemEvents$;
109
+ /**
110
+ * Build an indexer event from a file
111
+ */
112
+ private buildEvent;
113
+ /**
114
+ * Check if file is in the configured directory
115
+ */
116
+ private isRelevantFile;
117
+ }
118
+ //# sourceMappingURL=indexer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexer.d.ts","sourceRoot":"","sources":["../../src/core/indexer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,GAAG,EAA6D,MAAM,UAAU,CAAC;AAC/F,OAAO,EACN,KAAK,eAAe,EAKpB,KAAK,UAAU,EAKf,MAAM,MAAM,CAAC;AAGd,OAAO,EAAsB,KAAK,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAEpF;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEzD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,iBAAiB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAEhC;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,kBAAkB,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,cAAc,GAAG,cAAc,CAAC;AAE/D;;GAEG;AACH,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,gBAAgB,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,cAAc,CAAC,EAAE,kBAAkB,CAAC;IACpC,eAAe,CAAC,EAAE,eAAe,CAAC;CAClC;AAQD;;;;;;GAMG;AACH,qBAAa,OAAO;IACnB,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,kBAAkB,CAA6B;IACvD,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,iBAAiB,CAA+B;IACxD,OAAO,CAAC,uBAAuB,CAAyC;IACxE,OAAO,CAAC,gBAAgB,CAA8C;IAEtE,SAAgB,OAAO,EAAE,UAAU,CAAC,YAAY,CAAC,CAAC;IAClD,SAAgB,iBAAiB,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;gBAE3C,IAAI,EAAE,GAAG,EAAE,WAAW,EAAE,eAAe,CAAC,aAAa,CAAC;IAkClE;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAY5B;;OAEG;IACH,IAAI,IAAI,IAAI;IAQZ;;OAEG;IACH,MAAM,IAAI,IAAI;IAMd;;OAEG;YACW,YAAY;IA+B1B;;OAEG;IACH,OAAO,CAAC,cAAc;IA6BtB;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;IAI7B;;OAEG;IACH,OAAO,CAAC,eAAe;IAQvB;;OAEG;IACH,OAAO,CAAC,cAAc;IAQtB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA4C9B;;OAEG;YACW,UAAU;IA+BxB;;OAEG;IACH,OAAO,CAAC,cAAc;CAGtB"}
@@ -0,0 +1,205 @@
1
+ import { __awaiter } from "tslib";
2
+ import { TFile } from "obsidian";
3
+ import { from, fromEventPattern, lastValueFrom, merge, of, BehaviorSubject as RxBehaviorSubject, Subject, } from "rxjs";
4
+ import { debounceTime, filter, groupBy, map, mergeMap, switchMap, toArray } from "rxjs/operators";
5
+ import { isFileInConfiguredDirectory } from "../file/file";
6
+ import { compareFrontmatter } from "../file/frontmatter-diff";
7
+ /**
8
+ * Generic indexer that listens to Obsidian vault events and emits
9
+ * RxJS observables with frontmatter diffs and metadata.
10
+ *
11
+ * This indexer is framework-agnostic and can be used by any plugin
12
+ * that needs to track file changes with frontmatter.
13
+ */
14
+ export class Indexer {
15
+ constructor(_app, configStore) {
16
+ this.fileSub = null;
17
+ this.configSubscription = null;
18
+ this.scanEventsSubject = new Subject();
19
+ this.indexingCompleteSubject = new RxBehaviorSubject(false);
20
+ this.frontmatterCache = new Map();
21
+ this.vault = _app.vault;
22
+ this.metadataCache = _app.metadataCache;
23
+ // Set defaults
24
+ this.config = {
25
+ directory: configStore.value.directory || "",
26
+ excludedDiffProps: configStore.value.excludedDiffProps || new Set(),
27
+ scanConcurrency: configStore.value.scanConcurrency || 10,
28
+ debounceMs: configStore.value.debounceMs || 100,
29
+ };
30
+ // Subscribe to config changes
31
+ this.configSubscription = configStore.subscribe((newConfig) => {
32
+ const directoryChanged = this.config.directory !== (newConfig.directory || "");
33
+ this.config = {
34
+ directory: newConfig.directory || "",
35
+ excludedDiffProps: newConfig.excludedDiffProps || new Set(),
36
+ scanConcurrency: newConfig.scanConcurrency || 10,
37
+ debounceMs: newConfig.debounceMs || 100,
38
+ };
39
+ // Rescan if directory changed
40
+ if (directoryChanged) {
41
+ this.indexingCompleteSubject.next(false);
42
+ void this.scanAllFiles();
43
+ }
44
+ });
45
+ this.events$ = this.scanEventsSubject.asObservable();
46
+ this.indexingComplete$ = this.indexingCompleteSubject.asObservable();
47
+ }
48
+ /**
49
+ * Start the indexer and perform initial scan
50
+ */
51
+ start() {
52
+ return __awaiter(this, void 0, void 0, function* () {
53
+ this.indexingCompleteSubject.next(false);
54
+ const fileSystemEvents$ = this.buildFileSystemEvents$();
55
+ this.fileSub = fileSystemEvents$.subscribe((event) => {
56
+ this.scanEventsSubject.next(event);
57
+ });
58
+ yield this.scanAllFiles();
59
+ });
60
+ }
61
+ /**
62
+ * Stop the indexer and clean up subscriptions
63
+ */
64
+ stop() {
65
+ var _a, _b;
66
+ (_a = this.fileSub) === null || _a === void 0 ? void 0 : _a.unsubscribe();
67
+ this.fileSub = null;
68
+ (_b = this.configSubscription) === null || _b === void 0 ? void 0 : _b.unsubscribe();
69
+ this.configSubscription = null;
70
+ this.indexingCompleteSubject.complete();
71
+ }
72
+ /**
73
+ * Clear cache and rescan all files
74
+ */
75
+ resync() {
76
+ this.frontmatterCache.clear();
77
+ this.indexingCompleteSubject.next(false);
78
+ void this.scanAllFiles();
79
+ }
80
+ /**
81
+ * Scan all markdown files in the configured directory
82
+ */
83
+ scanAllFiles() {
84
+ return __awaiter(this, void 0, void 0, function* () {
85
+ const allFiles = this.vault.getMarkdownFiles();
86
+ const relevantFiles = allFiles.filter((file) => this.isRelevantFile(file));
87
+ const events$ = from(relevantFiles).pipe(mergeMap((file) => __awaiter(this, void 0, void 0, function* () {
88
+ try {
89
+ return yield this.buildEvent(file);
90
+ }
91
+ catch (error) {
92
+ console.error(`Error processing file ${file.path}:`, error);
93
+ return null;
94
+ }
95
+ }), this.config.scanConcurrency), filter((event) => event !== null), toArray());
96
+ try {
97
+ const allEvents = yield lastValueFrom(events$);
98
+ for (const event of allEvents) {
99
+ this.scanEventsSubject.next(event);
100
+ }
101
+ this.indexingCompleteSubject.next(true);
102
+ }
103
+ catch (error) {
104
+ console.error("❌ Error during file scanning:", error);
105
+ this.indexingCompleteSubject.next(true);
106
+ }
107
+ });
108
+ }
109
+ /**
110
+ * Create an observable from a vault event
111
+ */
112
+ fromVaultEvent(eventName) {
113
+ if (eventName === "create") {
114
+ return fromEventPattern((handler) => this.vault.on("create", handler), (handler) => this.vault.off("create", handler));
115
+ }
116
+ if (eventName === "modify") {
117
+ return fromEventPattern((handler) => this.vault.on("modify", handler), (handler) => this.vault.off("modify", handler));
118
+ }
119
+ if (eventName === "delete") {
120
+ return fromEventPattern((handler) => this.vault.on("delete", handler), (handler) => this.vault.off("delete", handler));
121
+ }
122
+ // eventName === "rename"
123
+ return fromEventPattern((handler) => this.vault.on("rename", handler), (handler) => this.vault.off("rename", handler)).pipe(map(([file]) => file));
124
+ }
125
+ /**
126
+ * Type guard to check if file is a markdown file
127
+ */
128
+ static isMarkdownFile(f) {
129
+ return f instanceof TFile && f.extension === "md";
130
+ }
131
+ /**
132
+ * Filter to only relevant markdown files in configured directory
133
+ */
134
+ toRelevantFiles() {
135
+ return (source) => source.pipe(filter((f) => Indexer.isMarkdownFile(f)), filter((f) => this.isRelevantFile(f)));
136
+ }
137
+ /**
138
+ * Debounce events by file path
139
+ */
140
+ debounceByPath(ms, key) {
141
+ return (source) => source.pipe(groupBy(key), mergeMap((g$) => g$.pipe(debounceTime(ms))));
142
+ }
143
+ /**
144
+ * Build the file system events observable stream
145
+ */
146
+ buildFileSystemEvents$() {
147
+ const created$ = this.fromVaultEvent("create").pipe(this.toRelevantFiles());
148
+ const modified$ = this.fromVaultEvent("modify").pipe(this.toRelevantFiles());
149
+ const deleted$ = this.fromVaultEvent("delete").pipe(this.toRelevantFiles());
150
+ const renamed$ = fromEventPattern((handler) => this.vault.on("rename", handler), (handler) => this.vault.off("rename", handler));
151
+ const changedIntents$ = merge(created$, modified$).pipe(this.debounceByPath(this.config.debounceMs, (f) => f.path), map((file) => ({ kind: "changed", file, path: file.path })));
152
+ const deletedIntents$ = deleted$.pipe(map((file) => ({ kind: "deleted", path: file.path })));
153
+ const renamedIntents$ = renamed$.pipe(map(([f, oldPath]) => [f, oldPath]), filter(([f]) => Indexer.isMarkdownFile(f) && this.isRelevantFile(f)), mergeMap(([f, oldPath]) => [
154
+ { kind: "deleted", path: oldPath },
155
+ { kind: "changed", file: f, path: f.path, oldPath },
156
+ ]));
157
+ const intents$ = merge(changedIntents$, deletedIntents$, renamedIntents$);
158
+ return intents$.pipe(switchMap((intent) => {
159
+ if (intent.kind === "deleted") {
160
+ this.frontmatterCache.delete(intent.path);
161
+ return of({ type: "file-deleted", filePath: intent.path });
162
+ }
163
+ return from(this.buildEvent(intent.file, intent.oldPath)).pipe(filter((e) => e !== null));
164
+ }));
165
+ }
166
+ /**
167
+ * Build an indexer event from a file
168
+ */
169
+ buildEvent(file, oldPath) {
170
+ return __awaiter(this, void 0, void 0, function* () {
171
+ var _a;
172
+ const cache = this.metadataCache.getFileCache(file);
173
+ if (!cache || !cache.frontmatter)
174
+ return null;
175
+ const { frontmatter } = cache;
176
+ const oldFrontmatter = this.frontmatterCache.get(file.path);
177
+ const source = {
178
+ filePath: file.path,
179
+ mtime: file.stat.mtime,
180
+ frontmatter,
181
+ folder: ((_a = file.parent) === null || _a === void 0 ? void 0 : _a.path) || "",
182
+ };
183
+ const event = {
184
+ type: "file-changed",
185
+ filePath: file.path,
186
+ oldPath,
187
+ source,
188
+ oldFrontmatter,
189
+ frontmatterDiff: oldFrontmatter
190
+ ? compareFrontmatter(oldFrontmatter, frontmatter, this.config.excludedDiffProps)
191
+ : undefined,
192
+ };
193
+ // Update cache
194
+ this.frontmatterCache.set(file.path, Object.assign({}, frontmatter));
195
+ return event;
196
+ });
197
+ }
198
+ /**
199
+ * Check if file is in the configured directory
200
+ */
201
+ isRelevantFile(file) {
202
+ return isFileInConfiguredDirectory(file.path, this.config.directory);
203
+ }
204
+ }
205
+ //# sourceMappingURL=indexer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexer.js","sourceRoot":"","sources":["../../src/core/indexer.ts"],"names":[],"mappings":"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","sourcesContent":["import { type App, type MetadataCache, type TAbstractFile, TFile, type Vault } from \"obsidian\";\nimport {\n\ttype BehaviorSubject,\n\tfrom,\n\tfromEventPattern,\n\tlastValueFrom,\n\tmerge,\n\ttype Observable,\n\tof,\n\tBehaviorSubject as RxBehaviorSubject,\n\tSubject,\n\ttype Subscription,\n} from \"rxjs\";\nimport { debounceTime, filter, groupBy, map, mergeMap, switchMap, toArray } from \"rxjs/operators\";\nimport { isFileInConfiguredDirectory } from \"../file/file\";\nimport { compareFrontmatter, type FrontmatterDiff } from \"../file/frontmatter-diff\";\n\n/**\n * Generic frontmatter object type for indexer\n */\nexport type IndexerFrontmatter = Record<string, unknown>;\n\n/**\n * Configuration for the generic indexer\n */\nexport interface IndexerConfig {\n\t/**\n\t * Directory to scan for files (e.g., \"Calendar\", \"Notes\")\n\t * If empty string or undefined, scans entire vault\n\t */\n\tdirectory?: string;\n\n\t/**\n\t * Properties to exclude when comparing frontmatter diffs\n\t */\n\texcludedDiffProps?: Set<string>;\n\n\t/**\n\t * Concurrency limit for file scanning operations\n\t */\n\tscanConcurrency?: number;\n\n\t/**\n\t * Debounce time in milliseconds for file change events\n\t */\n\tdebounceMs?: number;\n}\n\n/**\n * Raw file source with frontmatter and metadata\n */\nexport interface FileSource {\n\tfilePath: string;\n\tmtime: number;\n\tfrontmatter: IndexerFrontmatter;\n\tfolder: string;\n}\n\n/**\n * Types of indexer events\n */\nexport type IndexerEventType = \"file-changed\" | \"file-deleted\";\n\n/**\n * Generic indexer event\n */\nexport interface IndexerEvent {\n\ttype: IndexerEventType;\n\tfilePath: string;\n\toldPath?: string;\n\tsource?: FileSource;\n\toldFrontmatter?: IndexerFrontmatter;\n\tfrontmatterDiff?: FrontmatterDiff;\n}\n\ntype VaultEvent = \"create\" | \"modify\" | \"delete\" | \"rename\";\n\ntype FileIntent =\n\t| { kind: \"changed\"; file: TFile; path: string; oldPath?: string }\n\t| { kind: \"deleted\"; path: string };\n\n/**\n * Generic indexer that listens to Obsidian vault events and emits\n * RxJS observables with frontmatter diffs and metadata.\n *\n * This indexer is framework-agnostic and can be used by any plugin\n * that needs to track file changes with frontmatter.\n */\nexport class Indexer {\n\tprivate config: Required<IndexerConfig>;\n\tprivate fileSub: Subscription | null = null;\n\tprivate configSubscription: Subscription | null = null;\n\tprivate vault: Vault;\n\tprivate metadataCache: MetadataCache;\n\tprivate scanEventsSubject = new Subject<IndexerEvent>();\n\tprivate indexingCompleteSubject = new RxBehaviorSubject<boolean>(false);\n\tprivate frontmatterCache: Map<string, IndexerFrontmatter> = new Map();\n\n\tpublic readonly events$: Observable<IndexerEvent>;\n\tpublic readonly indexingComplete$: Observable<boolean>;\n\n\tconstructor(_app: App, configStore: BehaviorSubject<IndexerConfig>) {\n\t\tthis.vault = _app.vault;\n\t\tthis.metadataCache = _app.metadataCache;\n\n\t\t// Set defaults\n\t\tthis.config = {\n\t\t\tdirectory: configStore.value.directory || \"\",\n\t\t\texcludedDiffProps: configStore.value.excludedDiffProps || new Set(),\n\t\t\tscanConcurrency: configStore.value.scanConcurrency || 10,\n\t\t\tdebounceMs: configStore.value.debounceMs || 100,\n\t\t};\n\n\t\t// Subscribe to config changes\n\t\tthis.configSubscription = configStore.subscribe((newConfig) => {\n\t\t\tconst directoryChanged = this.config.directory !== (newConfig.directory || \"\");\n\n\t\t\tthis.config = {\n\t\t\t\tdirectory: newConfig.directory || \"\",\n\t\t\t\texcludedDiffProps: newConfig.excludedDiffProps || new Set(),\n\t\t\t\tscanConcurrency: newConfig.scanConcurrency || 10,\n\t\t\t\tdebounceMs: newConfig.debounceMs || 100,\n\t\t\t};\n\n\t\t\t// Rescan if directory changed\n\t\t\tif (directoryChanged) {\n\t\t\t\tthis.indexingCompleteSubject.next(false);\n\t\t\t\tvoid this.scanAllFiles();\n\t\t\t}\n\t\t});\n\n\t\tthis.events$ = this.scanEventsSubject.asObservable();\n\t\tthis.indexingComplete$ = this.indexingCompleteSubject.asObservable();\n\t}\n\n\t/**\n\t * Start the indexer and perform initial scan\n\t */\n\tasync start(): Promise<void> {\n\t\tthis.indexingCompleteSubject.next(false);\n\n\t\tconst fileSystemEvents$ = this.buildFileSystemEvents$();\n\n\t\tthis.fileSub = fileSystemEvents$.subscribe((event) => {\n\t\t\tthis.scanEventsSubject.next(event);\n\t\t});\n\n\t\tawait this.scanAllFiles();\n\t}\n\n\t/**\n\t * Stop the indexer and clean up subscriptions\n\t */\n\tstop(): void {\n\t\tthis.fileSub?.unsubscribe();\n\t\tthis.fileSub = null;\n\t\tthis.configSubscription?.unsubscribe();\n\t\tthis.configSubscription = null;\n\t\tthis.indexingCompleteSubject.complete();\n\t}\n\n\t/**\n\t * Clear cache and rescan all files\n\t */\n\tresync(): void {\n\t\tthis.frontmatterCache.clear();\n\t\tthis.indexingCompleteSubject.next(false);\n\t\tvoid this.scanAllFiles();\n\t}\n\n\t/**\n\t * Scan all markdown files in the configured directory\n\t */\n\tprivate async scanAllFiles(): Promise<void> {\n\t\tconst allFiles = this.vault.getMarkdownFiles();\n\t\tconst relevantFiles = allFiles.filter((file) => this.isRelevantFile(file));\n\n\t\tconst events$ = from(relevantFiles).pipe(\n\t\t\tmergeMap(async (file) => {\n\t\t\t\ttry {\n\t\t\t\t\treturn await this.buildEvent(file);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.error(`Error processing file ${file.path}:`, error);\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}, this.config.scanConcurrency),\n\t\t\tfilter((event): event is IndexerEvent => event !== null),\n\t\t\ttoArray()\n\t\t);\n\n\t\ttry {\n\t\t\tconst allEvents = await lastValueFrom(events$);\n\n\t\t\tfor (const event of allEvents) {\n\t\t\t\tthis.scanEventsSubject.next(event);\n\t\t\t}\n\n\t\t\tthis.indexingCompleteSubject.next(true);\n\t\t} catch (error) {\n\t\t\tconsole.error(\"❌ Error during file scanning:\", error);\n\t\t\tthis.indexingCompleteSubject.next(true);\n\t\t}\n\t}\n\n\t/**\n\t * Create an observable from a vault event\n\t */\n\tprivate fromVaultEvent(eventName: VaultEvent): Observable<TAbstractFile> {\n\t\tif (eventName === \"create\") {\n\t\t\treturn fromEventPattern<TAbstractFile>(\n\t\t\t\t(handler) => this.vault.on(\"create\", handler),\n\t\t\t\t(handler) => this.vault.off(\"create\", handler)\n\t\t\t);\n\t\t}\n\n\t\tif (eventName === \"modify\") {\n\t\t\treturn fromEventPattern<TAbstractFile>(\n\t\t\t\t(handler) => this.vault.on(\"modify\", handler),\n\t\t\t\t(handler) => this.vault.off(\"modify\", handler)\n\t\t\t);\n\t\t}\n\n\t\tif (eventName === \"delete\") {\n\t\t\treturn fromEventPattern<TAbstractFile>(\n\t\t\t\t(handler) => this.vault.on(\"delete\", handler),\n\t\t\t\t(handler) => this.vault.off(\"delete\", handler)\n\t\t\t);\n\t\t}\n\n\t\t// eventName === \"rename\"\n\t\treturn fromEventPattern<[TAbstractFile, string]>(\n\t\t\t(handler) => this.vault.on(\"rename\", handler),\n\t\t\t(handler) => this.vault.off(\"rename\", handler)\n\t\t).pipe(map(([file]) => file));\n\t}\n\n\t/**\n\t * Type guard to check if file is a markdown file\n\t */\n\tprivate static isMarkdownFile(f: TAbstractFile): f is TFile {\n\t\treturn f instanceof TFile && f.extension === \"md\";\n\t}\n\n\t/**\n\t * Filter to only relevant markdown files in configured directory\n\t */\n\tprivate toRelevantFiles<T extends TAbstractFile>() {\n\t\treturn (source: Observable<T>) =>\n\t\t\tsource.pipe(\n\t\t\t\tfilter((f: TAbstractFile): f is TFile => Indexer.isMarkdownFile(f)),\n\t\t\t\tfilter((f) => this.isRelevantFile(f))\n\t\t\t);\n\t}\n\n\t/**\n\t * Debounce events by file path\n\t */\n\tprivate debounceByPath<T>(ms: number, key: (x: T) => string) {\n\t\treturn (source: Observable<T>) =>\n\t\t\tsource.pipe(\n\t\t\t\tgroupBy(key),\n\t\t\t\tmergeMap((g$) => g$.pipe(debounceTime(ms)))\n\t\t\t);\n\t}\n\n\t/**\n\t * Build the file system events observable stream\n\t */\n\tprivate buildFileSystemEvents$(): Observable<IndexerEvent> {\n\t\tconst created$ = this.fromVaultEvent(\"create\").pipe(this.toRelevantFiles());\n\t\tconst modified$ = this.fromVaultEvent(\"modify\").pipe(this.toRelevantFiles());\n\t\tconst deleted$ = this.fromVaultEvent(\"delete\").pipe(this.toRelevantFiles());\n\n\t\tconst renamed$ = fromEventPattern<[TAbstractFile, string]>(\n\t\t\t(handler) => this.vault.on(\"rename\", handler),\n\t\t\t(handler) => this.vault.off(\"rename\", handler)\n\t\t);\n\n\t\tconst changedIntents$ = merge(created$, modified$).pipe(\n\t\t\tthis.debounceByPath(this.config.debounceMs, (f) => f.path),\n\t\t\tmap((file): FileIntent => ({ kind: \"changed\", file, path: file.path }))\n\t\t);\n\n\t\tconst deletedIntents$ = deleted$.pipe(\n\t\t\tmap((file): FileIntent => ({ kind: \"deleted\", path: file.path }))\n\t\t);\n\n\t\tconst renamedIntents$ = renamed$.pipe(\n\t\t\tmap(([f, oldPath]) => [f, oldPath] as const),\n\t\t\tfilter(([f]) => Indexer.isMarkdownFile(f) && this.isRelevantFile(f)),\n\t\t\tmergeMap(([f, oldPath]) => [\n\t\t\t\t{ kind: \"deleted\", path: oldPath } as FileIntent,\n\t\t\t\t{ kind: \"changed\", file: f, path: f.path, oldPath } as FileIntent,\n\t\t\t])\n\t\t);\n\n\t\tconst intents$ = merge(changedIntents$, deletedIntents$, renamedIntents$);\n\n\t\treturn intents$.pipe(\n\t\t\tswitchMap((intent) => {\n\t\t\t\tif (intent.kind === \"deleted\") {\n\t\t\t\t\tthis.frontmatterCache.delete(intent.path);\n\t\t\t\t\treturn of<IndexerEvent>({ type: \"file-deleted\", filePath: intent.path });\n\t\t\t\t}\n\n\t\t\t\treturn from(this.buildEvent(intent.file, intent.oldPath)).pipe(\n\t\t\t\t\tfilter((e): e is IndexerEvent => e !== null)\n\t\t\t\t);\n\t\t\t})\n\t\t);\n\t}\n\n\t/**\n\t * Build an indexer event from a file\n\t */\n\tprivate async buildEvent(file: TFile, oldPath?: string): Promise<IndexerEvent | null> {\n\t\tconst cache = this.metadataCache.getFileCache(file);\n\t\tif (!cache || !cache.frontmatter) return null;\n\n\t\tconst { frontmatter } = cache;\n\t\tconst oldFrontmatter = this.frontmatterCache.get(file.path);\n\n\t\tconst source: FileSource = {\n\t\t\tfilePath: file.path,\n\t\t\tmtime: file.stat.mtime,\n\t\t\tfrontmatter,\n\t\t\tfolder: file.parent?.path || \"\",\n\t\t};\n\n\t\tconst event: IndexerEvent = {\n\t\t\ttype: \"file-changed\",\n\t\t\tfilePath: file.path,\n\t\t\toldPath,\n\t\t\tsource,\n\t\t\toldFrontmatter,\n\t\t\tfrontmatterDiff: oldFrontmatter\n\t\t\t\t? compareFrontmatter(oldFrontmatter, frontmatter, this.config.excludedDiffProps)\n\t\t\t\t: undefined,\n\t\t};\n\n\t\t// Update cache\n\t\tthis.frontmatterCache.set(file.path, { ...frontmatter });\n\n\t\treturn event;\n\t}\n\n\t/**\n\t * Check if file is in the configured directory\n\t */\n\tprivate isRelevantFile(file: TFile): boolean {\n\t\treturn isFileInConfiguredDirectory(file.path, this.config.directory);\n\t}\n}\n"]}
@@ -0,0 +1,12 @@
1
+ import type { App } from "obsidian";
2
+ import type { Frontmatter, FrontmatterDiff } from "./frontmatter-diff";
3
+ export interface NexusPropertiesSettings {
4
+ excludedPropagatedProps?: string;
5
+ parentProp: string;
6
+ childrenProp: string;
7
+ relatedProp: string;
8
+ zettelIdProp: string;
9
+ }
10
+ export declare function parseExcludedProps(settings: NexusPropertiesSettings): Set<string>;
11
+ export declare function applyFrontmatterChanges(app: App, targetPath: string, sourceFrontmatter: Frontmatter, diff: FrontmatterDiff): Promise<void>;
12
+ //# sourceMappingURL=frontmatter-propagation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontmatter-propagation.d.ts","sourceRoot":"","sources":["../../src/file/frontmatter-propagation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAEpC,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAEvE,MAAM,WAAW,uBAAuB;IACvC,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,uBAAuB,GAAG,GAAG,CAAC,MAAM,CAAC,CAejF;AAED,wBAAsB,uBAAuB,CAC5C,GAAG,EAAE,GAAG,EACR,UAAU,EAAE,MAAM,EAClB,iBAAiB,EAAE,WAAW,EAC9B,IAAI,EAAE,eAAe,GACnB,OAAO,CAAC,IAAI,CAAC,CAwBf"}
@@ -0,0 +1,42 @@
1
+ import { __awaiter } from "tslib";
2
+ import { TFile } from "obsidian";
3
+ export function parseExcludedProps(settings) {
4
+ const excludedPropsStr = settings.excludedPropagatedProps || "";
5
+ const userExcluded = excludedPropsStr
6
+ .split(",")
7
+ .map((prop) => prop.trim())
8
+ .filter((prop) => prop.length > 0);
9
+ const alwaysExcluded = [
10
+ settings.parentProp,
11
+ settings.childrenProp,
12
+ settings.relatedProp,
13
+ settings.zettelIdProp,
14
+ ];
15
+ return new Set([...alwaysExcluded, ...userExcluded]);
16
+ }
17
+ export function applyFrontmatterChanges(app, targetPath, sourceFrontmatter, diff) {
18
+ return __awaiter(this, void 0, void 0, function* () {
19
+ try {
20
+ const file = app.vault.getAbstractFileByPath(targetPath);
21
+ if (!(file instanceof TFile)) {
22
+ console.warn(`Target file not found: ${targetPath}`);
23
+ return;
24
+ }
25
+ yield app.fileManager.processFrontMatter(file, (fm) => {
26
+ for (const change of diff.added) {
27
+ fm[change.key] = sourceFrontmatter[change.key];
28
+ }
29
+ for (const change of diff.modified) {
30
+ fm[change.key] = sourceFrontmatter[change.key];
31
+ }
32
+ for (const change of diff.deleted) {
33
+ delete fm[change.key];
34
+ }
35
+ });
36
+ }
37
+ catch (error) {
38
+ console.error(`Error applying frontmatter changes to ${targetPath}:`, error);
39
+ }
40
+ });
41
+ }
42
+ //# sourceMappingURL=frontmatter-propagation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontmatter-propagation.js","sourceRoot":"","sources":["../../src/file/frontmatter-propagation.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAWjC,MAAM,UAAU,kBAAkB,CAAC,QAAiC;IACnE,MAAM,gBAAgB,GAAG,QAAQ,CAAC,uBAAuB,IAAI,EAAE,CAAC;IAChE,MAAM,YAAY,GAAG,gBAAgB;SACnC,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAEpC,MAAM,cAAc,GAAG;QACtB,QAAQ,CAAC,UAAU;QACnB,QAAQ,CAAC,YAAY;QACrB,QAAQ,CAAC,WAAW;QACpB,QAAQ,CAAC,YAAY;KACrB,CAAC;IAEF,OAAO,IAAI,GAAG,CAAC,CAAC,GAAG,cAAc,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,UAAgB,uBAAuB,CAC5C,GAAQ,EACR,UAAkB,EAClB,iBAA8B,EAC9B,IAAqB;;QAErB,IAAI,CAAC;YACJ,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,qBAAqB,CAAC,UAAU,CAAC,CAAC;YACzD,IAAI,CAAC,CAAC,IAAI,YAAY,KAAK,CAAC,EAAE,CAAC;gBAC9B,OAAO,CAAC,IAAI,CAAC,0BAA0B,UAAU,EAAE,CAAC,CAAC;gBACrD,OAAO;YACR,CAAC;YAED,MAAM,GAAG,CAAC,WAAW,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE;gBACrD,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;oBACjC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,iBAAiB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAChD,CAAC;gBAED,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACpC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,iBAAiB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAChD,CAAC;gBAED,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;oBACnC,OAAO,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACvB,CAAC;YACF,CAAC,CAAC,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,CAAC,KAAK,CAAC,yCAAyC,UAAU,GAAG,EAAE,KAAK,CAAC,CAAC;QAC9E,CAAC;IACF,CAAC;CAAA","sourcesContent":["import type { App } from \"obsidian\";\nimport { TFile } from \"obsidian\";\nimport type { Frontmatter, FrontmatterDiff } from \"./frontmatter-diff\";\n\nexport interface NexusPropertiesSettings {\n\texcludedPropagatedProps?: string;\n\tparentProp: string;\n\tchildrenProp: string;\n\trelatedProp: string;\n\tzettelIdProp: string;\n}\n\nexport function parseExcludedProps(settings: NexusPropertiesSettings): Set<string> {\n\tconst excludedPropsStr = settings.excludedPropagatedProps || \"\";\n\tconst userExcluded = excludedPropsStr\n\t\t.split(\",\")\n\t\t.map((prop) => prop.trim())\n\t\t.filter((prop) => prop.length > 0);\n\n\tconst alwaysExcluded = [\n\t\tsettings.parentProp,\n\t\tsettings.childrenProp,\n\t\tsettings.relatedProp,\n\t\tsettings.zettelIdProp,\n\t];\n\n\treturn new Set([...alwaysExcluded, ...userExcluded]);\n}\n\nexport async function applyFrontmatterChanges(\n\tapp: App,\n\ttargetPath: string,\n\tsourceFrontmatter: Frontmatter,\n\tdiff: FrontmatterDiff\n): Promise<void> {\n\ttry {\n\t\tconst file = app.vault.getAbstractFileByPath(targetPath);\n\t\tif (!(file instanceof TFile)) {\n\t\t\tconsole.warn(`Target file not found: ${targetPath}`);\n\t\t\treturn;\n\t\t}\n\n\t\tawait app.fileManager.processFrontMatter(file, (fm) => {\n\t\t\tfor (const change of diff.added) {\n\t\t\t\tfm[change.key] = sourceFrontmatter[change.key];\n\t\t\t}\n\n\t\t\tfor (const change of diff.modified) {\n\t\t\t\tfm[change.key] = sourceFrontmatter[change.key];\n\t\t\t}\n\n\t\t\tfor (const change of diff.deleted) {\n\t\t\t\tdelete fm[change.key];\n\t\t\t}\n\t\t});\n\t} catch (error) {\n\t\tconsole.error(`Error applying frontmatter changes to ${targetPath}:`, error);\n\t}\n}\n"]}
@@ -4,6 +4,7 @@ export * from "./file-operations";
4
4
  export * from "./file-utils";
5
5
  export * from "./frontmatter";
6
6
  export * from "./frontmatter-diff";
7
+ export * from "./frontmatter-propagation";
7
8
  export * from "./link-parser";
8
9
  export * from "./property-utils";
9
10
  export * from "./templater";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/file/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,QAAQ,CAAC;AACvB,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/file/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,QAAQ,CAAC;AACvB,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC"}
@@ -4,6 +4,7 @@ export * from "./file-operations";
4
4
  export * from "./file-utils";
5
5
  export * from "./frontmatter";
6
6
  export * from "./frontmatter-diff";
7
+ export * from "./frontmatter-propagation";
7
8
  export * from "./link-parser";
8
9
  export * from "./property-utils";
9
10
  export * from "./templater";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/file/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,QAAQ,CAAC;AACvB,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC","sourcesContent":["export * from \"./child-reference\";\nexport * from \"./file\";\nexport * from \"./file-operations\";\nexport * from \"./file-utils\";\nexport * from \"./frontmatter\";\nexport * from \"./frontmatter-diff\";\nexport * from \"./link-parser\";\nexport * from \"./property-utils\";\nexport * from \"./templater\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/file/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,QAAQ,CAAC;AACvB,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC","sourcesContent":["export * from \"./child-reference\";\nexport * from \"./file\";\nexport * from \"./file-operations\";\nexport * from \"./file-utils\";\nexport * from \"./frontmatter\";\nexport * from \"./frontmatter-diff\";\nexport * from \"./frontmatter-propagation\";\nexport * from \"./link-parser\";\nexport * from \"./property-utils\";\nexport * from \"./templater\";\n"]}
@@ -1,4 +1,14 @@
1
- import { type App, type TFile } from "obsidian";
1
+ import { type App, TFile } from "obsidian";
2
+ export interface FileCreationOptions {
3
+ title: string;
4
+ targetDirectory: string;
5
+ filename?: string;
6
+ content?: string;
7
+ frontmatter?: Record<string, unknown>;
8
+ templatePath?: string;
9
+ useTemplater?: boolean;
10
+ }
2
11
  export declare function isTemplaterAvailable(app: App): boolean;
3
12
  export declare function createFromTemplate(app: App, templatePath: string, targetFolder?: string, filename?: string, openNewNote?: boolean): Promise<TFile | null>;
13
+ export declare function createFileWithTemplate(app: App, options: FileCreationOptions): Promise<TFile>;
4
14
  //# sourceMappingURL=templater.d.ts.map