@jwilleke/ngdpbase-types 0.0.0 → 5.18.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 (302) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +16 -2
  3. package/lib/packages/ngdpbase-types/index.d.ts +32 -0
  4. package/lib/packages/ngdpbase-types/testing.d.ts +43 -0
  5. package/lib/packages/ngdpbase-types/testing.js +53 -0
  6. package/lib/src/cache/CacheDependencies.d.ts +50 -0
  7. package/lib/src/cache/CacheDependencies.js +50 -0
  8. package/lib/src/cache/ICacheAdapter.d.ts +86 -0
  9. package/lib/src/cache/RegionCache.d.ts +171 -0
  10. package/lib/src/context/ActorContext.d.ts +48 -0
  11. package/lib/src/context/ActorContext.js +33 -0
  12. package/lib/src/context/ApiContext.d.ts +194 -0
  13. package/lib/src/context/ApiContext.js +273 -0
  14. package/lib/src/context/BaseContext.d.ts +110 -0
  15. package/lib/src/context/BaseContext.js +143 -0
  16. package/lib/src/context/JobContext.d.ts +153 -0
  17. package/lib/src/context/JobContext.js +144 -0
  18. package/lib/src/context/WikiContext.d.ts +404 -0
  19. package/lib/src/context/bootActions.d.ts +64 -0
  20. package/lib/src/context/bootActions.js +111 -0
  21. package/lib/src/converters/HtmlConverter.d.ts +70 -0
  22. package/lib/src/converters/IContentConverter.d.ts +94 -0
  23. package/lib/src/converters/JSPWikiConverter.d.ts +117 -0
  24. package/lib/src/converters/conversionWarning.d.ts +15 -0
  25. package/lib/src/converters/ncm/bridge.d.ts +22 -0
  26. package/lib/src/converters/ncm/existing.d.ts +23 -0
  27. package/lib/src/converters/ncm/fix/blocks.d.ts +89 -0
  28. package/lib/src/converters/ncm/fix/bulletMarkers.d.ts +21 -0
  29. package/lib/src/converters/ncm/fix/index.d.ts +36 -0
  30. package/lib/src/converters/ncm/fix/jspwikiBullets.d.ts +20 -0
  31. package/lib/src/converters/ncm/fix/jspwikiCodeMarkers.d.ts +38 -0
  32. package/lib/src/converters/ncm/fix/jspwikiHeadings.d.ts +25 -0
  33. package/lib/src/converters/ncm/fix/jspwikiIndent.d.ts +24 -0
  34. package/lib/src/converters/ncm/fix/jspwikiInsert.d.ts +21 -0
  35. package/lib/src/converters/ncm/fix/jspwikiItalic.d.ts +29 -0
  36. package/lib/src/converters/ncm/fix/jspwikiLinkLeftovers.d.ts +27 -0
  37. package/lib/src/converters/ncm/fix/moreInformationFooter.d.ts +25 -0
  38. package/lib/src/converters/ncm/fix/styleClosers.d.ts +25 -0
  39. package/lib/src/converters/ncm/fix/tightenLists.d.ts +30 -0
  40. package/lib/src/converters/ncm/fix/types.d.ts +33 -0
  41. package/lib/src/converters/ncm/footnotes.d.ts +39 -0
  42. package/lib/src/converters/ncm/images.d.ts +49 -0
  43. package/lib/src/converters/ncm/index.d.ts +20 -0
  44. package/lib/src/converters/ncm/links.d.ts +21 -0
  45. package/lib/src/converters/ncm/normalize.d.ts +39 -0
  46. package/lib/src/converters/ncm/placeholder.d.ts +25 -0
  47. package/lib/src/converters/ncm/tables.d.ts +36 -0
  48. package/lib/src/converters/ncm/types.d.ts +42 -0
  49. package/lib/src/http/egressPolicy.d.ts +52 -0
  50. package/lib/src/http/guardedFetch.d.ts +89 -0
  51. package/lib/src/http/guardedFetch.js +113 -0
  52. package/lib/src/http/guardedLookup.d.ts +48 -0
  53. package/lib/src/http/guardedLookup.js +73 -0
  54. package/lib/src/http/ssrf.d.ts +83 -0
  55. package/lib/src/http/ssrf.js +311 -0
  56. package/lib/src/mail/MailProvider.d.ts +36 -0
  57. package/lib/src/mail/NodemailerMailProvider.d.ts +26 -0
  58. package/lib/src/managers/AddonsManager.d.ts +691 -0
  59. package/lib/src/managers/AgentTokenManager.d.ts +269 -0
  60. package/lib/src/managers/AssetManager.d.ts +116 -0
  61. package/lib/src/managers/AttachmentManager.d.ts +1032 -0
  62. package/lib/src/managers/AuthManager.d.ts +1257 -0
  63. package/lib/src/managers/BackgroundJobManager.d.ts +434 -0
  64. package/lib/src/managers/BaseManager.d.ts +391 -0
  65. package/lib/src/managers/BaseManager.js +415 -0
  66. package/lib/src/managers/CacheManager.d.ts +159 -0
  67. package/lib/src/managers/CatalogManager.d.ts +235 -0
  68. package/lib/src/managers/CommentManager.d.ts +75 -0
  69. package/lib/src/managers/ConfigurationManager.d.ts +747 -0
  70. package/lib/src/managers/DatabaseManager.d.ts +89 -0
  71. package/lib/src/managers/DatabaseManager.js +236 -0
  72. package/lib/src/managers/EmailManager.d.ts +47 -0
  73. package/lib/src/managers/ExportManager.d.ts +129 -0
  74. package/lib/src/managers/ExportManager.js +420 -0
  75. package/lib/src/managers/FootnoteManager.d.ts +118 -0
  76. package/lib/src/managers/MediaManager.d.ts +279 -0
  77. package/lib/src/managers/MetricsManager.d.ts +89 -0
  78. package/lib/src/managers/NotificationManager.d.ts +165 -0
  79. package/lib/src/managers/OidcManager.d.ts +210 -0
  80. package/lib/src/managers/OrganizationManager.d.ts +107 -0
  81. package/lib/src/managers/PageManager.d.ts +1645 -0
  82. package/lib/src/managers/PersonManager.d.ts +48 -0
  83. package/lib/src/managers/PluginManager.d.ts +179 -0
  84. package/lib/src/managers/PluginManager.js +393 -0
  85. package/lib/src/managers/PolicyEvaluator.d.ts +213 -0
  86. package/lib/src/managers/RenderingManager.d.ts +358 -0
  87. package/lib/src/managers/RoleManager.d.ts +134 -0
  88. package/lib/src/managers/SearchManager.d.ts +402 -0
  89. package/lib/src/managers/ShareManager.d.ts +251 -0
  90. package/lib/src/managers/TemplateManager.d.ts +176 -0
  91. package/lib/src/managers/ThemeManager.d.ts +56 -0
  92. package/lib/src/managers/UserManager.d.ts +480 -0
  93. package/lib/src/managers/ValidationManager.d.ts +426 -0
  94. package/lib/src/managers/VariableManager.d.ts +145 -0
  95. package/lib/src/middleware/csrf.d.ts +3 -0
  96. package/lib/src/parsers/LinkParser.d.ts +457 -0
  97. package/lib/src/parsers/MarkupParser.d.ts +769 -0
  98. package/lib/src/parsers/context/ParseContext.d.ts +314 -0
  99. package/lib/src/parsers/data/emoji-map.d.ts +18 -0
  100. package/lib/src/parsers/dom/DOMBuilder.d.ts +210 -0
  101. package/lib/src/parsers/dom/DOMParser.d.ts +252 -0
  102. package/lib/src/parsers/dom/Tokenizer.d.ts +358 -0
  103. package/lib/src/parsers/dom/WikiDocument.d.ts +272 -0
  104. package/lib/src/parsers/dom/handlers/DOMLinkHandler.d.ts +260 -0
  105. package/lib/src/parsers/dom/handlers/DOMPluginHandler.d.ts +212 -0
  106. package/lib/src/parsers/dom/handlers/DOMVariableHandler.d.ts +171 -0
  107. package/lib/src/parsers/filters/BaseFilter.d.ts +269 -0
  108. package/lib/src/parsers/filters/FilterChain.d.ts +320 -0
  109. package/lib/src/parsers/handlers/BaseSyntaxHandler.d.ts +331 -0
  110. package/lib/src/parsers/handlers/HandlerRegistry.d.ts +225 -0
  111. package/lib/src/parsers/handlers/JSPWikiPreprocessor.d.ts +89 -0
  112. package/lib/src/parsers/handlers/LinkParserHandler.d.ts +80 -0
  113. package/lib/src/parsers/handlers/PluginSyntaxHandler.d.ts +78 -0
  114. package/lib/src/parsers/handlers/WikiFormHandler.d.ts +149 -0
  115. package/lib/src/parsers/handlers/WikiTagHandler.d.ts +125 -0
  116. package/lib/src/parsers/jspwikiTableRow.d.ts +39 -0
  117. package/lib/src/parsers/styleBlockSyntax.d.ts +14 -0
  118. package/lib/src/plugins/types.d.ts +79 -0
  119. package/lib/src/providers/AgentTokenAuthProvider.d.ts +40 -0
  120. package/lib/src/providers/AuthentikBearerAuthProvider.d.ts +75 -0
  121. package/lib/src/providers/BaseAttachmentProvider.d.ts +197 -0
  122. package/lib/src/providers/BaseAuthProvider.d.ts +220 -0
  123. package/lib/src/providers/BaseCacheProvider.d.ts +140 -0
  124. package/lib/src/providers/BaseCredentialsProvider.d.ts +84 -0
  125. package/lib/src/providers/BaseDatabaseProvider.d.ts +22 -0
  126. package/lib/src/providers/BaseDatabaseProvider.js +12 -0
  127. package/lib/src/providers/BaseLoggingProvider.d.ts +68 -0
  128. package/lib/src/providers/BaseLoggingProvider.js +37 -0
  129. package/lib/src/providers/BaseMediaProvider.d.ts +308 -0
  130. package/lib/src/providers/BasePageProvider.d.ts +337 -0
  131. package/lib/src/providers/BaseProvider.d.ts +98 -0
  132. package/lib/src/providers/BaseProvider.js +74 -0
  133. package/lib/src/providers/BaseSearchProvider.d.ts +362 -0
  134. package/lib/src/providers/BasicAttachmentProvider.d.ts +599 -0
  135. package/lib/src/providers/CloudflareAccessAuthProvider.d.ts +72 -0
  136. package/lib/src/providers/FileCredentialsProvider.d.ts +33 -0
  137. package/lib/src/providers/FileJobStateProvider.d.ts +58 -0
  138. package/lib/src/providers/FileLoggingProvider.d.ts +43 -0
  139. package/lib/src/providers/FileLoggingProvider.js +120 -0
  140. package/lib/src/providers/FileOidcAdapter.d.ts +25 -0
  141. package/lib/src/providers/FileSystemMediaProvider.d.ts +403 -0
  142. package/lib/src/providers/LunrSearchProvider.d.ts +280 -0
  143. package/lib/src/providers/MagicLinkAuthProvider.d.ts +125 -0
  144. package/lib/src/providers/NullCacheProvider.d.ts +72 -0
  145. package/lib/src/providers/OidcAuthProvider.d.ts +180 -0
  146. package/lib/src/providers/OidcBearerAuthProvider.d.ts +30 -0
  147. package/lib/src/providers/PasskeyAuthProvider.d.ts +58 -0
  148. package/lib/src/providers/PasswordAuthProvider.d.ts +20 -0
  149. package/lib/src/providers/SqliteDatabaseProvider.d.ts +55 -0
  150. package/lib/src/providers/SqliteDatabaseProvider.js +90 -0
  151. package/lib/src/providers/SqliteJobStateProvider.d.ts +41 -0
  152. package/lib/src/providers/databaseMigrations.d.ts +8 -0
  153. package/lib/src/providers/databaseMigrations.js +47 -0
  154. package/lib/src/providers/jobState.d.ts +99 -0
  155. package/lib/src/providers/lunrQueryToMiniSearch.d.ts +32 -0
  156. package/lib/src/providers/mediaFilenameDate.d.ts +22 -0
  157. package/lib/src/providers/sqliteLocation.d.ts +17 -0
  158. package/lib/src/providers/sqliteLocation.js +55 -0
  159. package/lib/src/providers/sqliteMigrations.d.ts +48 -0
  160. package/lib/src/providers/sqliteMigrations.js +72 -0
  161. package/lib/src/rendering/githubAlerts.d.ts +22 -0
  162. package/lib/src/rendering/htmlPolicy.d.ts +76 -0
  163. package/lib/src/rendering/markdownConverter.d.ts +73 -0
  164. package/lib/src/security/PolicyDecisionPoint.d.ts +245 -0
  165. package/lib/src/security/PolicyInformationPoint.d.ts +448 -0
  166. package/lib/src/security/pageActions.d.ts +40 -0
  167. package/lib/src/security/permissions.generated.d.ts +78 -0
  168. package/lib/src/types/Asset.d.ts +414 -0
  169. package/lib/src/types/Catalog.d.ts +61 -0
  170. package/lib/src/types/Comment.d.ts +11 -0
  171. package/lib/src/types/Config.d.ts +388 -0
  172. package/lib/src/types/Organization.d.ts +78 -0
  173. package/lib/src/types/OrganizationProvider.d.ts +38 -0
  174. package/lib/src/types/Page.d.ts +220 -0
  175. package/lib/src/types/Person.d.ts +56 -0
  176. package/lib/src/types/PersonProvider.d.ts +25 -0
  177. package/lib/src/types/Policy.d.ts +139 -0
  178. package/lib/src/types/Policy.js +17 -0
  179. package/lib/src/types/Provider.d.ts +810 -0
  180. package/lib/src/types/Role.d.ts +84 -0
  181. package/lib/src/types/RoleProvider.d.ts +35 -0
  182. package/lib/src/types/Schema.d.ts +425 -0
  183. package/lib/src/types/Share.d.ts +172 -0
  184. package/lib/src/types/Share.js +81 -0
  185. package/lib/src/types/User.d.ts +304 -0
  186. package/lib/src/types/Version.d.ts +189 -0
  187. package/lib/src/types/WikiEngine.d.ts +128 -0
  188. package/lib/src/types/express.d.ts +120 -0
  189. package/lib/src/types/express.js +1 -0
  190. package/lib/src/types/guards.d.ts +78 -0
  191. package/lib/src/types/heic-decode.d.ts +16 -0
  192. package/lib/src/types/index.d.ts +19 -0
  193. package/lib/src/types/linkedom.d.ts +77 -0
  194. package/lib/src/types/markdown-it-plugins.d.ts +21 -0
  195. package/lib/src/utils/DeltaStorage.d.ts +118 -0
  196. package/lib/src/utils/LocaleUtils.d.ts +105 -0
  197. package/lib/src/utils/LocaleUtils.js +294 -0
  198. package/lib/src/utils/PageNameMatcher.d.ts +98 -0
  199. package/lib/src/utils/PathPreflight.d.ts +38 -0
  200. package/lib/src/utils/PathPreflight.js +50 -0
  201. package/lib/src/utils/SectionUtils.d.ts +40 -0
  202. package/lib/src/utils/addonConfigLayer.d.ts +144 -0
  203. package/lib/src/utils/addonConfigLayer.js +382 -0
  204. package/lib/src/utils/addonDatabaseRules.d.ts +25 -0
  205. package/lib/src/utils/addonDatabaseRules.js +57 -0
  206. package/lib/src/utils/addonHost.d.ts +51 -0
  207. package/lib/src/utils/addonHost.js +72 -0
  208. package/lib/src/utils/addonInstaller.d.ts +109 -0
  209. package/lib/src/utils/addonLock.d.ts +37 -0
  210. package/lib/src/utils/addonLock.js +48 -0
  211. package/lib/src/utils/addonPageSync.d.ts +45 -0
  212. package/lib/src/utils/addonProvenance.d.ts +48 -0
  213. package/lib/src/utils/addonTarball.d.ts +41 -0
  214. package/lib/src/utils/addonsPathResolver.d.ts +76 -0
  215. package/lib/src/utils/addonsPathResolver.js +129 -0
  216. package/lib/src/utils/assetMetadataTags.d.ts +66 -0
  217. package/lib/src/utils/atomicWrite.d.ts +28 -0
  218. package/lib/src/utils/auditConfigChange.d.ts +57 -0
  219. package/lib/src/utils/auditEventNames.d.ts +50 -0
  220. package/lib/src/utils/auditEventNames.generated.d.ts +163 -0
  221. package/lib/src/utils/auditEventNames.generated.js +168 -0
  222. package/lib/src/utils/auditEventNames.js +49 -0
  223. package/lib/src/utils/auditEvents.d.ts +265 -0
  224. package/lib/src/utils/auditEvents.js +309 -0
  225. package/lib/src/utils/auditRegistry.d.ts +102 -0
  226. package/lib/src/utils/auditRegistry.js +168 -0
  227. package/lib/src/utils/bip39English.d.ts +2 -0
  228. package/lib/src/utils/configEnvKeys.d.ts +68 -0
  229. package/lib/src/utils/configFiles.d.ts +74 -0
  230. package/lib/src/utils/configFiles.js +150 -0
  231. package/lib/src/utils/delegation.d.ts +48 -0
  232. package/lib/src/utils/deriveUsername.d.ts +21 -0
  233. package/lib/src/utils/explainMediaPath.d.ts +123 -0
  234. package/lib/src/utils/formerTitles.d.ts +69 -0
  235. package/lib/src/utils/frontmatterAccess.d.ts +54 -0
  236. package/lib/src/utils/headlessAdminPassword.d.ts +55 -0
  237. package/lib/src/utils/imageTransform.d.ts +52 -0
  238. package/lib/src/utils/instanceEnvSecret.d.ts +51 -0
  239. package/lib/src/utils/jobSlots.d.ts +43 -0
  240. package/lib/src/utils/keywordNormalizer.d.ts +127 -0
  241. package/lib/src/utils/logger.d.ts +70 -0
  242. package/lib/src/utils/logger.js +106 -0
  243. package/lib/src/utils/magicLinkDeviceState.d.ts +95 -0
  244. package/lib/src/utils/managerUtils.d.ts +40 -0
  245. package/lib/src/utils/migrateLegacyPrivateAttachments.d.ts +15 -0
  246. package/lib/src/utils/orgFilename.d.ts +22 -0
  247. package/lib/src/utils/pageFeature.d.ts +27 -0
  248. package/lib/src/utils/pageFrontmatter.d.ts +21 -0
  249. package/lib/src/utils/pageNotes.d.ts +150 -0
  250. package/lib/src/utils/pageTitleRule.d.ts +37 -0
  251. package/lib/src/utils/pageToArticle.d.ts +59 -0
  252. package/lib/src/utils/pageUrl.d.ts +18 -0
  253. package/lib/src/utils/passwordChange.d.ts +12 -0
  254. package/lib/src/utils/passwordHash.d.ts +60 -0
  255. package/lib/src/utils/permissionCatalog.d.ts +52 -0
  256. package/lib/src/utils/pluginFormatters.d.ts +452 -0
  257. package/lib/src/utils/pluginFormatters.js +714 -0
  258. package/lib/src/utils/privateLinkRewrite.d.ts +42 -0
  259. package/lib/src/utils/privateStoreAccess.d.ts +57 -0
  260. package/lib/src/utils/privateStoreAccess.js +65 -0
  261. package/lib/src/utils/privateStoreCatalogs.d.ts +40 -0
  262. package/lib/src/utils/privateStoreCrypto.d.ts +127 -0
  263. package/lib/src/utils/privateStoreDoor.d.ts +181 -0
  264. package/lib/src/utils/privateStoreExport.d.ts +72 -0
  265. package/lib/src/utils/privateStoreFiles.d.ts +120 -0
  266. package/lib/src/utils/privateStoreMeta.d.ts +64 -0
  267. package/lib/src/utils/privateStoreMigrations.d.ts +37 -0
  268. package/lib/src/utils/privateStorePath.d.ts +259 -0
  269. package/lib/src/utils/privateStorePath.js +436 -0
  270. package/lib/src/utils/privateStoreTakeout.d.ts +76 -0
  271. package/lib/src/utils/privateStoreUnlock.d.ts +175 -0
  272. package/lib/src/utils/proxyClaim.d.ts +59 -0
  273. package/lib/src/utils/proxyClaim.js +30 -0
  274. package/lib/src/utils/redactPrivateNames.d.ts +21 -0
  275. package/lib/src/utils/redactPrivateNames.js +89 -0
  276. package/lib/src/utils/redactSecrets.d.ts +58 -0
  277. package/lib/src/utils/redactSecrets.js +171 -0
  278. package/lib/src/utils/renameLinkRewrite.d.ts +112 -0
  279. package/lib/src/utils/roleGrants.d.ts +35 -0
  280. package/lib/src/utils/safeRedirect.d.ts +32 -0
  281. package/lib/src/utils/schedule.d.ts +54 -0
  282. package/lib/src/utils/secretFileMode.d.ts +17 -0
  283. package/lib/src/utils/seededShippedPages.d.ts +45 -0
  284. package/lib/src/utils/sensitiveValues.d.ts +59 -0
  285. package/lib/src/utils/sensitiveValues.js +106 -0
  286. package/lib/src/utils/sessionEnd.d.ts +12 -0
  287. package/lib/src/utils/sessionGeneration.d.ts +24 -0
  288. package/lib/src/utils/sessionIdle.d.ts +41 -0
  289. package/lib/src/utils/sessionLimits.d.ts +68 -0
  290. package/lib/src/utils/shareLockbox.d.ts +64 -0
  291. package/lib/src/utils/sigstoreTrustedRoot.d.ts +33 -0
  292. package/lib/src/utils/sniffMime.d.ts +21 -0
  293. package/lib/src/utils/storeSearchIndex.d.ts +75 -0
  294. package/lib/src/utils/subjectMayDo.d.ts +21 -0
  295. package/lib/src/utils/systemCategoryRules.d.ts +30 -0
  296. package/lib/src/utils/systemCategoryRules.js +41 -0
  297. package/lib/src/utils/userCreateError.d.ts +62 -0
  298. package/lib/src/utils/username.d.ts +53 -0
  299. package/lib/src/utils/vaultUrlRewrite.d.ts +27 -0
  300. package/lib/src/utils/version.d.ts +84 -0
  301. package/lib/src/utils/videoFrame.d.ts +21 -0
  302. package/package.json +54 -3
@@ -0,0 +1,403 @@
1
+ /**
2
+ * FileSystemMediaProvider - Filesystem-based implementation of BaseMediaProvider
3
+ *
4
+ * Scans configured directories for media files, extracts EXIF/IPTC/XMP metadata
5
+ * via exiftool-vendored, generates thumbnails via Sharp, and maintains a
6
+ * persistent JSON index.
7
+ *
8
+ * Dependencies:
9
+ * - exiftool-vendored — EXIF/IPTC/XMP metadata extraction
10
+ * - sharp — thumbnail generation (already installed)
11
+ * - fs-extra — filesystem helpers
12
+ *
13
+ * @module FileSystemMediaProvider
14
+ */
15
+ import { type MediaPathExplanation, type MediaSkipReport } from '../utils/explainMediaPath.js';
16
+ import BaseMediaProvider, { MediaItem, ScanResult } from './BaseMediaProvider.js';
17
+ import type { AssetMetadataPatch } from '../types/Asset.js';
18
+ /**
19
+ * Configuration for FileSystemMediaProvider.
20
+ */
21
+ export interface FileSystemMediaProviderConfig {
22
+ /** Absolute paths to the root media folders to scan */
23
+ folders: string[];
24
+ /** Directory names to skip during scan (e.g. [".dtrash", ".ts"]) */
25
+ ignoreDirs: string[];
26
+ /** Maximum directory depth to recurse into (0 = unlimited) */
27
+ maxDepth: number;
28
+ /** Absolute path to the media-index.json file */
29
+ indexFile: string;
30
+ /** Absolute path to the thumbnail cache directory */
31
+ thumbnailDir: string;
32
+ /** Comma-separated thumbnail size specs (e.g. "300x300,150x150") */
33
+ thumbnailSizes: string;
34
+ /** Metadata extraction priority order (e.g. ["EXIF", "IPTC", "XMP"]) */
35
+ metadataPriority: string[];
36
+ /** Whether the provider may write to source media folders (always false) */
37
+ readonly: boolean;
38
+ /** Set of file extensions (lowercase, no dot) to index */
39
+ extensions: Set<string>;
40
+ }
41
+ /** Default supported media file extensions — used when no config override is provided */
42
+ export declare const DEFAULT_MEDIA_EXTENSIONS: string[];
43
+ /**
44
+ * Filesystem-based media provider.
45
+ *
46
+ * Scans configured folders, extracts metadata with ExifTool, and maintains a
47
+ * persistent JSON index. Thumbnails are generated on demand via Sharp and cached
48
+ * to thumbnailDir.
49
+ */
50
+ declare class FileSystemMediaProvider extends BaseMediaProvider {
51
+ readonly id = "media-library";
52
+ readonly displayName = "Media Library";
53
+ readonly capabilities: import('../types/Asset.js').ProviderCapability[];
54
+ private readonly config;
55
+ /** In-memory index: id → MediaIndexEntry */
56
+ private index;
57
+ /** Single ExifTool worker process reused across all reads */
58
+ private readonly exiftoolInstance;
59
+ constructor(config: FileSystemMediaProviderConfig);
60
+ /**
61
+ * Load the persisted index from disk so queries work immediately
62
+ * (before the first background scan).
63
+ */
64
+ initialize(): Promise<void>;
65
+ /**
66
+ * Release the ExifTool worker process.
67
+ */
68
+ shutdown(): Promise<void>;
69
+ /**
70
+ * Verify that at least one configured media folder is accessible.
71
+ *
72
+ * Returns false when every configured folder is unreachable — e.g. a NAS or
73
+ * SLOW_STORAGE volume that has been unmounted or an SMB share that has dropped.
74
+ * A partial failure (some folders gone, others present) still returns true so
75
+ * the provider continues serving what it can; the warning log indicates which
76
+ * folders are missing.
77
+ */
78
+ healthCheck(): Promise<boolean>;
79
+ /**
80
+ * The configured folders this process cannot read (#1167): missing, unmounted
81
+ * or without read permission. Read-only — it never touches the files.
82
+ */
83
+ unreachableFolders(): Promise<string[]>;
84
+ /**
85
+ * Rebuild the media index from scratch.
86
+ *
87
+ * Clears the in-memory index and deletes the persisted index file, then
88
+ * runs a forced full scan so the result reflects only files currently on disk.
89
+ *
90
+ * @param onProgress - Optional callback invoked periodically with (processed, total).
91
+ */
92
+ rebuild(onProgress?: (processed: number, total: number) => void): Promise<ScanResult>;
93
+ /**
94
+ * Scan all configured folders, extract metadata for new/changed files,
95
+ * save the updated index, and return a summary.
96
+ *
97
+ * Phase 1: recursively collect all matching file paths (fast, no ExifTool).
98
+ * Phase 2: process files concurrently in batches of BATCH_SIZE, calling
99
+ * ExifTool for each file that needs metadata extraction.
100
+ *
101
+ * @param force - Re-process every file even if mtime is unchanged.
102
+ * @param onProgress - Optional callback invoked after each batch with (processed, total).
103
+ */
104
+ scan(force?: boolean, onProgress?: (processed: number, total: number) => void): Promise<ScanResult>;
105
+ /**
106
+ * Remove index entries whose file path is not among the primaries found in
107
+ * this scan, restricted to folders that were fully walked (#867).
108
+ *
109
+ * @param presentPaths - All primary file paths collected in this scan.
110
+ * @param prunableFolders - Folders that exist and were walked without read errors.
111
+ * @param counters - Scan counters; `removed` is incremented per pruned entry.
112
+ */
113
+ private pruneStaleEntries;
114
+ /**
115
+ * Return the list of years that have at least one item, sorted descending.
116
+ */
117
+ getYears(): Promise<number[]>;
118
+ /**
119
+ * Every item with a year, in one pass over the index (#1741).
120
+ */
121
+ getItemCount(): Promise<number>;
122
+ /**
123
+ * Retrieve a single item by id.
124
+ */
125
+ getItem(id: string): Promise<MediaItem | null>;
126
+ /**
127
+ * Return all items for a given year, sorted by filename.
128
+ */
129
+ getItemsByYear(year: number): Promise<MediaItem[]>;
130
+ /**
131
+ * Return all items whose capture timestamp falls in [after, before],
132
+ * sorted ascending by capture date (#864 — Dawarich date-window queries).
133
+ * Bounds are ISO-ish strings compared against `metadata.dateTimeOriginal`
134
+ * ("YYYY-MM-DD HH:MM:SS"); either bound may be omitted. Items without a
135
+ * capture date are never returned.
136
+ */
137
+ getItemsByDateRange(after?: string, before?: string): Promise<MediaItem[]>;
138
+ /**
139
+ * Retrieve all items whose EXIF/XMP keywords include the page name — the
140
+ * only association between a media item and a page (#1427).
141
+ */
142
+ getItemsByPage(pageName: string): Promise<MediaItem[]>;
143
+ getItemsByKeyword(keyword: string): Promise<MediaItem[]>;
144
+ /**
145
+ * #895: distinct keywords across the media index with item counts. O(n)
146
+ * over the in-memory index; scalar keyword values count as one-element
147
+ * arrays (#545 shape tolerance).
148
+ */
149
+ getAllKeywordCounts(): Promise<Record<string, number>>;
150
+ /**
151
+ * #917: library-wide leaf→path map built from every item's hierarchical
152
+ * `keywordPaths`. Keys and values are canonical-value forms; a leaf with no
153
+ * genuine hierarchy (only a root-level occurrence) is omitted. #918 uses this
154
+ * to place a newly-added keyword at its known hierarchical home.
155
+ */
156
+ getKeywordLeafPaths(): Promise<Record<string, string>>;
157
+ /**
158
+ * Find the first item whose filename (basename) exactly matches.
159
+ *
160
+ * Iterates the in-memory index; O(n) but the index is small enough that
161
+ * this is acceptable for the ad-hoc `media://` URI resolution path.
162
+ *
163
+ * @param filename - Basename to match exactly (e.g. "IMG_1234.jpg").
164
+ */
165
+ findByFilename(filename: string): Promise<MediaItem | null>;
166
+ /**
167
+ * Full-text keyword search across filename, year, title,
168
+ * description, and keywords fields.
169
+ *
170
+ * All query tokens must match (AND semantics).
171
+ */
172
+ searchItems(query: string): Promise<MediaItem[]>;
173
+ /**
174
+ * Write a metadata patch into the source file (and its alternate-format
175
+ * siblings, so e.g. a HEIC+JPG pair stays in sync), then refresh the index
176
+ * entry by re-reading the file — the index always reflects what is actually
177
+ * on disk, not what we intended to write.
178
+ *
179
+ * ExifTool's default backup behaviour is kept deliberately: the first write
180
+ * to a file leaves a `<name>_original` sibling. Those extensions are not in
181
+ * the indexable set, so scans ignore them.
182
+ *
183
+ * The re-extract records the file's new mtime, so the next scheduled scan
184
+ * sees an unchanged file and skips it (no churn). `alternates` is
185
+ * re-attached afterwards because processFile builds entries without it.
186
+ */
187
+ updateItemMetadata(id: string, patch: AssetMetadataPatch): Promise<MediaItem | null>;
188
+ /**
189
+ * Return a thumbnail buffer (webp) for the given item and size.
190
+ *
191
+ * Thumbnails are cached on disk in config.thumbnailDir. Image items run
192
+ * through Sharp directly. Video items (#722 Slice 1) have a poster frame
193
+ * extracted via ffmpeg-static at the 1-second mark, then fed through the
194
+ * same Sharp pipeline so the on-disk cache layout and `/media/thumb/:id`
195
+ * endpoint are unchanged. Other item types (audio, docs) return null and
196
+ * fall back to the generic icon in the asset-picker / media library.
197
+ *
198
+ * @param id - Item identifier.
199
+ * @param size - Size string in the form "WxH" (e.g. "300x300").
200
+ */
201
+ getThumbnailBuffer(id: string, size: string): Promise<Buffer | null>;
202
+ /**
203
+ * Group files by directory+stem and keep only the highest-priority format per group.
204
+ * Alternate paths are returned separately so they can be stored on the primary entry.
205
+ */
206
+ private deduplicateFormats;
207
+ /**
208
+ * Recursively collect all matching media file paths under dirPath.
209
+ *
210
+ * Applies ignoreDirs, maxDepth, extension filter, and .ngdpbaseignore patterns.
211
+ * Does NOT call ExifTool — that happens in Phase 2 (processFile).
212
+ */
213
+ private collectFilePaths;
214
+ /**
215
+ * Read and parse `.ngdpbaseignore` from the given directory if it exists.
216
+ * Returns an array of pattern strings (blank lines and `#` comments stripped).
217
+ */
218
+ private loadIgnorePatterns;
219
+ /**
220
+ * Test a filename against a list of .ngdpbaseignore patterns.
221
+ * Patterns ending with `/` are directory-only; all others match both files and dirs.
222
+ */
223
+ private matchesIgnorePattern;
224
+ /**
225
+ * Process a single media file: stat, EXIF read, index update.
226
+ */
227
+ private processFile;
228
+ /**
229
+ * Explain why one absolute path is, or is not, in the media index (#848).
230
+ *
231
+ * #814 reported media "often not discovered" and triage found zero indexing
232
+ * bugs — every missing file was correctly skipped by a rule that leaves no
233
+ * visible trace. This answers the question for a single path.
234
+ *
235
+ * The rule ORDER lives in `explainMediaPath`, deliberately: the scanner
236
+ * decides the same things inline as `continue` statements, which is fine for
237
+ * scanning and useless for explaining. Keeping the classifier pure also lets
238
+ * a future skipped-file report (#1056) reuse it instead of adding a third
239
+ * copy of rules that already exist in two places.
240
+ *
241
+ * Facts are gathered in two passes so the expensive ones are not paid for a
242
+ * file that is already explained: index lookups are cheap, reading
243
+ * `.ngdpbaseignore` files and EXIF is not. Only a path that survives every
244
+ * cheap rule triggers the second pass.
245
+ */
246
+ explainPath(target: string): Promise<MediaPathExplanation>;
247
+ /**
248
+ * First `.ngdpbaseignore` pattern matching the file or any directory between
249
+ * it and its scan root, or undefined.
250
+ *
251
+ * Walks root-downward because that is the order the scanner encounters the
252
+ * ignore files, so the pattern reported is the one that actually stopped it.
253
+ */
254
+ private findIgnorePatternMatch;
255
+ /** Whether the file carries the `ngdpbaseignore` EXIF/XMP keyword. */
256
+ private hasIgnoreKeyword;
257
+ /**
258
+ * Generate a stable 32-character hex ID from the file path.
259
+ */
260
+ private generateId;
261
+ /**
262
+ * Ordered capture-date field names checked for both year extraction and
263
+ * full-timestamp extraction. Order matches ExifTool's own precedence:
264
+ * `DateTimeOriginal` is the photographer's intent (image EXIF), the
265
+ * `*CreateDate` variants are the file/container creation timestamps that
266
+ * video formats use (issue #750: QuickTime:CreationDate flattens to
267
+ * `CreationDate` in exiftool-vendored's Tags shape).
268
+ */
269
+ private static readonly CAPTURE_DATE_FIELDS;
270
+ /**
271
+ * Extract the formatted capture-date timestamp ("YYYY-MM-DD HH:MM:SS") from
272
+ * EXIF/QuickTime tags, falling back through `DateTimeOriginal` →
273
+ * `CreateDate` → `MediaCreateDate` → `CreationDate`.
274
+ *
275
+ * The first three already covered images; `CreationDate` is the
276
+ * QuickTime/Apple variant that video containers populate when the camera
277
+ * didn't write `DateTimeOriginal` (#750). Without this fallback, videos
278
+ * indexed `dateTimeOriginal: null` and silently dropped out of any
279
+ * capture-date sort/filter — only the year facet worked (via `extractYear`).
280
+ *
281
+ * Also reports whether the source tag was a **partial** date — the year was
282
+ * present but the month and/or day were missing and got defaulted to `01`
283
+ * (#808). A partial date is still stored (defaulted to Jan 1, which preserves
284
+ * the year facet and gives a usable sort key), but the caller surfaces it to
285
+ * admins at WARN level — distinct from a file with no capture date at all
286
+ * (ERROR). A missing **time** component (HH:MM:SS) does NOT count as partial:
287
+ * defaulting to `00:00:00` is harmless for day-granularity sorting.
288
+ *
289
+ * Returns `null` when no field provides a usable `.year`.
290
+ */
291
+ private extractCaptureDate;
292
+ /**
293
+ * Ordered duration-tag fallback chain. Walked by `extractDuration()` until
294
+ * one yields a strictly positive value. Order is most-reliable-first.
295
+ *
296
+ * Why each field is in the chain:
297
+ * - `Duration` — container-level top tag, present in QuickTime/MP4/MOV,
298
+ * MKV, AVI, WAV, AIFF, FLAC, MPEG. Single value per file.
299
+ * - `TrackDuration` — per-track fallback when the container doesn't
300
+ * expose its own. exiftool-vendored flattens N tracks into one tag,
301
+ * keeping the last non-empty value seen.
302
+ * - `MediaDuration` — same per-track shape as TrackDuration, but often
303
+ * zero on Pixel/Android `.TS.mp4` files where track-N is metadata-only
304
+ * (this is the bug that motivated the chain — exiftool reported
305
+ * `Duration: 15.87 s` but `MediaDuration: 0 s` for the same file).
306
+ * - `AudioDuration` — audio-only fallback (rarely useful alone, but
307
+ * present in some streaming formats).
308
+ * - `GoogleTrackDuration` — Pixel-specific QuickTime extension.
309
+ * - `StreamDuration` — streaming containers (HLS chunks, etc.).
310
+ * - `TotalDuration` — MPEG-1/MPEG-2 alternative top-level tag.
311
+ *
312
+ * Excluded as not-a-playback-duration: `PreviewDuration`, `SelectionDuration`,
313
+ * `BulbDuration`, `ContrastFlowDuration`, `SampleDuration`, `BlockDuration`,
314
+ * `ClusterDuration`, `DefaultDuration`, `SlowMotionRegions*Duration*`, and
315
+ * all DICOM `*Duration` variants. Those are either codec-internal sub-sample
316
+ * markers or non-media (medical imaging, slow-mo region metadata, edit
317
+ * selection state).
318
+ */
319
+ private static readonly DURATION_FIELDS;
320
+ /**
321
+ * Extract playback duration from ExifTool's duration tags and normalise to
322
+ * ISO 8601 duration format (e.g. "PT1M30S").
323
+ *
324
+ * Walks `DURATION_FIELDS` and accepts the first tag that yields a strictly
325
+ * positive number of seconds. Zero values are skipped — Pixel `.TS.mp4`
326
+ * files set `MediaDuration: 0 s` while `Duration: 15.87 s` is the real
327
+ * length, and prior versions of this method picked up the zero via
328
+ * `??` short-circuit (#758 follow-up).
329
+ *
330
+ * Accepted raw shapes per candidate field:
331
+ * - number of seconds (most common for QuickTime / MP4)
332
+ * - string like "0:01:30" / "00:01:30" / "30" (HH:MM:SS / MM:SS / SS)
333
+ * - already-ISO string like "PT1M30S"
334
+ * - exiftool-vendored Duration object (`.seconds` property)
335
+ *
336
+ * Returns null when no candidate field yields a positive duration.
337
+ */
338
+ private extractDuration;
339
+ /**
340
+ * Extract average bitrate (bits/second) from ExifTool AvgBitrate tag.
341
+ *
342
+ * exiftool-vendored returns AvgBitrate as either:
343
+ * - a number (raw bits/second)
344
+ * - a string like "5.00 Mbps" or "192 kbps" — parse the magnitude + unit
345
+ *
346
+ * Returns null when no usable bitrate is present.
347
+ */
348
+ private extractBitrate;
349
+ /**
350
+ * Extract the four-digit year from tags, filename, path, or mtime.
351
+ *
352
+ * Priority:
353
+ * 1. EXIF/QuickTime date fields (DateTimeOriginal / CreateDate /
354
+ * MediaCreateDate / CreationDate — see CAPTURE_DATE_FIELDS)
355
+ * 2. Filename prefix YYYY- or YYYY_
356
+ * 3. Directory path component matching /^\d{4}$/
357
+ * 4. File mtime year
358
+ */
359
+ private extractYear;
360
+ /**
361
+ * Load the persisted index from disk into memory.
362
+ */
363
+ private loadIndex;
364
+ /**
365
+ * Tally every skip before the list is capped (#1056).
366
+ *
367
+ * Runs on the full list, never the truncated one — that ordering is the
368
+ * whole point. On the reference library the cap drops 93% of the entries,
369
+ * so counts derived after capping would understate `extension` by 13,714.
370
+ */
371
+ private tallySkips;
372
+ /**
373
+ * Path of the skip report, beside the index file (#1056).
374
+ *
375
+ * Null when no `indexFile` is configured — an in-memory-only provider has
376
+ * nowhere to keep it, and the report must not silently outlive the index it
377
+ * describes.
378
+ */
379
+ private get skipReportFile();
380
+ /**
381
+ * Persist the skip report for the scan that just finished (#1056).
382
+ *
383
+ * On disk rather than in memory because the question it answers — "where did
384
+ * my file go?" — is usually asked long after the scan, and often after a
385
+ * restart. An in-memory report reads as "no files were skipped" to anyone who
386
+ * did not personally trigger the last scan.
387
+ *
388
+ * Overwrites: it describes the CURRENT state of the library, so accumulating
389
+ * history would mean showing an operator files that a config change already
390
+ * un-skipped.
391
+ */
392
+ private saveSkipReport;
393
+ /**
394
+ * The skip report from the most recent scan, or null if none has been
395
+ * written (fresh install, or no `indexFile` configured).
396
+ */
397
+ getSkipReport(): Promise<MediaSkipReport | null>;
398
+ /**
399
+ * Save the in-memory index to disk.
400
+ */
401
+ private saveIndex;
402
+ }
403
+ export default FileSystemMediaProvider;
@@ -0,0 +1,280 @@
1
+ /**
2
+ * LunrSearchProvider - Full-text search provider using Lunr.js
3
+ *
4
+ * Provides client-side full-text search with stemming, stopwords, and field boosting.
5
+ * Suitable for small to medium-sized wikis (<10,000 pages).
6
+ *
7
+ * Configuration keys (all lowercase):
8
+ * - ngdpbase.search.provider.lunr.indexdir - Directory for persisted index
9
+ * - ngdpbase.search.provider.lunr.stemming - Enable/disable stemming
10
+ * - ngdpbase.search.provider.lunr.boost.title - Title field boost factor
11
+ * - ngdpbase.search.provider.lunr.boost.systemcategory - System category boost
12
+ * - ngdpbase.search.provider.lunr.boost.userkeywords - User keywords boost
13
+ * - ngdpbase.search.provider.lunr.boost.tags - Tags boost
14
+ * - ngdpbase.search.provider.lunr.maxresults - Maximum results to return
15
+ * - ngdpbase.search.provider.lunr.snippetlength - Snippet length in characters
16
+ * - ngdpbase.search.provider.lunr.flushinterval - Document persistence flush interval (ms)
17
+ *
18
+ * Related: GitHub Issue #102 - Configuration reorganization
19
+ * Related: GitHub Issue #267 - Incremental search index + document persistence
20
+ */
21
+ import BaseSearchProvider, { SearchResult, SearchOptions, SearchCriteria, SearchStatistics, BackupData, WikiEngine } from './BaseSearchProvider.js';
22
+ /**
23
+ * Document structure for indexing
24
+ */
25
+ /**
26
+ * Widen the last term of a query to a prefix match (#884).
27
+ *
28
+ * Lunr's `*` wildcard, applied only to the final term: someone mid-word wants
29
+ * completions, someone who submitted a finished query does not. Earlier terms
30
+ * are words the user has already finished typing and stay exact.
31
+ *
32
+ * Left alone when the last term already carries Lunr syntax — a wildcard, a
33
+ * field scope (`title:x`), or a presence operator (`+`/`-`). Appending `*` to
34
+ * those either duplicates an existing wildcard or corrupts the operator, and
35
+ * silently mangling a query the caller wrote deliberately is worse than not
36
+ * helping.
37
+ *
38
+ * @param query - Raw user query
39
+ * @returns The query with its last term widened, or unchanged
40
+ */
41
+ export declare function applyPrefixToLastTerm(query: string): string;
42
+ /**
43
+ * Split URLs found in page content into searchable word tokens (#884).
44
+ *
45
+ * A URL indexed as one opaque string only ever matches if the reader types it
46
+ * in full. Splitting on the separators that carry no meaning — `[/:._\-?&=#]`
47
+ * — turns `https://en.wikipedia.org/wiki/Volcano` into `en wikipedia org wiki
48
+ * volcano`, so the domain and the path words each become findable terms.
49
+ *
50
+ * Deliberately conservative about what counts as a URL: only `http(s)://`
51
+ * matches. Bare domains would drag in ordinary prose containing dots, and
52
+ * abbreviations like "e.g." would tokenise into noise.
53
+ *
54
+ * Numeric-only and single-character fragments are dropped — port numbers, path
55
+ * ids and `v2`-style noise add index weight without ever being searched for.
56
+ *
57
+ * @param content - Page body
58
+ * @returns Space-joined tokens, or '' when the page links nowhere
59
+ */
60
+ export declare function tokenizeUrls(content: string): string;
61
+ /**
62
+ * LunrSearchProvider - Full-text search using Lunr.js
63
+ */
64
+ declare class LunrSearchProvider extends BaseSearchProvider {
65
+ private searchIndex;
66
+ private persistTimer;
67
+ private documents;
68
+ private config;
69
+ private flushInterval;
70
+ private documentsPath;
71
+ constructor(engine: WikiEngine);
72
+ /**
73
+ * Initialize the Lunr search provider
74
+ * Loads configuration from ConfigurationManager
75
+ * @returns {Promise<void>}
76
+ */
77
+ initialize(): Promise<void>;
78
+ /**
79
+ * Load persisted documents from disk
80
+ */
81
+ private loadPersistedDocuments;
82
+ /**
83
+ * Is this document a private page's (#1458)? Either its name is a private
84
+ * path (#1456) or the document itself says so — a document written before
85
+ * private pages left the shared indexes has the flag and an ordinary title.
86
+ */
87
+ private static isPrivateDocument;
88
+ /**
89
+ * The documents that may be written to a shared place — `documents.json`
90
+ * and the backup that carries it off this host (#1458).
91
+ *
92
+ * Private page text sat in both in plaintext before #1456. This is the one
93
+ * rule that keeps it out, whatever put it in the map: a private page's text
94
+ * lives in its own store's search index and nowhere else.
95
+ */
96
+ private sharedDocuments;
97
+ /**
98
+ * Persist documents to disk — the shared ones only (#1458).
99
+ */
100
+ private persistDocuments;
101
+ /**
102
+ * A term as both the index and a query read it: lower-cased, stop words
103
+ * dropped, and stemmed with Lunr's English stemmer when stemming is on, so a
104
+ * word matches what it matched under Lunr (#1736).
105
+ */
106
+ private processTerm;
107
+ /**
108
+ * Build the index from the in-memory documents: at start-up and after a
109
+ * restore. A save changes one document (`updatePageInIndex`), never this.
110
+ */
111
+ private rebuildSearchIndexFromDocuments;
112
+ /** The configured field boosts, for every search. Content is the 1.0 baseline. */
113
+ private fieldBoosts;
114
+ /**
115
+ * Write `documents.json` shortly after the last change rather than on every
116
+ * save (#1736). The interval flush and `close()` still write it.
117
+ */
118
+ private schedulePersist;
119
+ /**
120
+ * Convert page data from WikiRoutes into a LunrDocument
121
+ */
122
+ private buildDocumentFromPageData;
123
+ /**
124
+ * Get provider information
125
+ * @returns {Object} Provider metadata
126
+ */
127
+ getProviderInfo(): {
128
+ name: string;
129
+ version: string;
130
+ description: string;
131
+ features: string[];
132
+ };
133
+ /**
134
+ * Build search index from all pages
135
+ * @returns {Promise<void>}
136
+ */
137
+ buildIndex(): Promise<void>;
138
+ /**
139
+ * Search for pages matching the query
140
+ * @param {string} query - Search query
141
+ * @param {SearchOptions} options - Search options
142
+ * @returns {Promise<SearchResult[]>} Search results
143
+ */
144
+ search(query: string, options?: SearchOptions): Promise<SearchResult[]>;
145
+ /**
146
+ * Private-page visibility (#731/#716, #1382). Used by both the text path in
147
+ * search() and the no-text advancedSearch branch. A private page lives in its
148
+ * owner's private container: it is found only by its owner — no role, and no
149
+ * frontmatter audience, reaches in (docs/private-stores.md, Access;
150
+ * the same rule PolicyInformationPoint applies at Tier 0).
151
+ */
152
+ private isDocVisible;
153
+ /**
154
+ * Advanced search with multiple criteria
155
+ * @param {SearchCriteria} options - Search criteria
156
+ * @returns {Promise<SearchResult[]>} Search results
157
+ */
158
+ advancedSearch(options?: SearchCriteria): Promise<SearchResult[]>;
159
+ /**
160
+ * Generate a snippet with highlighted search terms
161
+ * @param {string} content - Full content
162
+ * @param {string} query - Search query
163
+ * @returns {string} Content snippet
164
+ */
165
+ private generateSnippet;
166
+ /**
167
+ * Get search suggestions for autocomplete
168
+ * @param {string} partial - Partial search term
169
+ * @returns {Promise<string[]>} Suggested completions
170
+ */
171
+ getSuggestions(partial: string): Promise<string[]>;
172
+ /**
173
+ * Suggest similar pages based on content
174
+ * @param {string} pageName - Source page name
175
+ * @param {number} limit - Maximum suggestions
176
+ * @returns {Promise<SearchResult[]>} Suggested pages
177
+ */
178
+ suggestSimilarPages(pageName: string, limit?: number): Promise<SearchResult[]>;
179
+ /**
180
+ * Add or update a page in the search index incrementally
181
+ * @param {string} pageName - Page name
182
+ * @param {Record<string, unknown>} pageData - Page data
183
+ * @returns {Promise<void>}
184
+ */
185
+ updatePageInIndex(pageName: string, pageData: Record<string, unknown>): Promise<void>;
186
+ /**
187
+ * Remove a page from the search index
188
+ * @param {string} pageName - Page name to remove
189
+ * @returns {Promise<void>}
190
+ */
191
+ removePageFromIndex(pageName: string): Promise<void>;
192
+ /**
193
+ * True rebuild from disk — mirrors MediaManager.rebuildIndex().
194
+ *
195
+ * #724: buildIndex() has a fast path that, when this.documents is
196
+ * non-empty (always, in steady state), rebuilds Lunr from the persisted
197
+ * map WITHOUT re-reading pages from disk. That makes a deleted page's
198
+ * index entry ("ghost") unkillable — a normal reindex can never drop it.
199
+ * rebuild() is the missing "Rebuild" half (vs the "Reindex"/rescan that
200
+ * buildIndex provides): it clears the in-memory map AND deletes the
201
+ * persisted documents.json, then forces the cold disk-scan path. Pages
202
+ * that no longer exist on disk are dropped by construction.
203
+ *
204
+ * documents.json is a derived cache (regenerated here from PageManager),
205
+ * never source data — deleting it is safe and not the data/-tree rule.
206
+ */
207
+ rebuild(): Promise<void>;
208
+ /**
209
+ * Get all unique categories from indexed documents
210
+ * @returns {Promise<string[]>} List of categories
211
+ */
212
+ getAllCategories(): Promise<string[]>;
213
+ /**
214
+ * Split a document's `userKeywords` string back into keywords.
215
+ *
216
+ * #862: `buildDocumentFromPageData` joins user-keywords with commas (the
217
+ * only safe separator — keywords may contain spaces, e.g. "grow system").
218
+ * Every consumer must split on commas too; the previous whitespace splits
219
+ * meant a page with more than one keyword NEVER matched
220
+ * `searchByUserKeywords`, and multi-word keywords shattered into words.
221
+ */
222
+ private splitUserKeywords;
223
+ /**
224
+ * Get all unique user keywords from indexed documents
225
+ * @returns {Promise<string[]>} List of user keywords
226
+ */
227
+ getAllUserKeywords(): Promise<string[]>;
228
+ /**
229
+ * #893: all unique system keywords (machine bucket) from indexed documents.
230
+ * Mirrors getAllUserKeywords — same comma-join contract (#862). Previously
231
+ * ES-only; needed on Lunr so the asset-picker system-keywords facet includes
232
+ * index-derived terms like 'capture'.
233
+ */
234
+ getAllSystemKeywords(): Promise<string[]>;
235
+ /**
236
+ * Search by category only
237
+ * @param {string} category - Category to search for
238
+ * @returns {Promise<SearchResult[]>} Pages in category
239
+ */
240
+ getAllDocuments(): Promise<SearchResult[]>;
241
+ searchByCategory(category: string): Promise<SearchResult[]>;
242
+ /**
243
+ * Search by user keywords only
244
+ * @param {string} keyword - Keyword to search for
245
+ * @returns {Promise<SearchResult[]>} Pages with keyword
246
+ */
247
+ searchByUserKeywords(keyword: string): Promise<SearchResult[]>;
248
+ /**
249
+ * Get search statistics
250
+ * @returns {Promise<SearchStatistics>} Search statistics
251
+ */
252
+ getStatistics(): Promise<SearchStatistics>;
253
+ /**
254
+ * Get the total number of indexed documents
255
+ * @returns {Promise<number>} Number of documents
256
+ */
257
+ getDocumentCount(): Promise<number>;
258
+ /**
259
+ * Check if the search provider is healthy/functional
260
+ * @returns {Promise<boolean>} True if healthy
261
+ */
262
+ isHealthy(): Promise<boolean>;
263
+ /**
264
+ * Close/cleanup the search provider, flushing documents to disk
265
+ * @returns {Promise<void>}
266
+ */
267
+ close(): Promise<void>;
268
+ /**
269
+ * Backup search index and configuration
270
+ * @returns {Promise<BackupData>} Backup data
271
+ */
272
+ backup(): Promise<BackupData>;
273
+ /**
274
+ * Restore search index from backup
275
+ * @param {BackupData} backupData - Backup data
276
+ * @returns {Promise<void>}
277
+ */
278
+ restore(backupData: BackupData): Promise<void>;
279
+ }
280
+ export default LunrSearchProvider;