@jwilleke/ngdpbase-types 0.0.0 → 5.19.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 (304) 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 +427 -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 +188 -0
  71. package/lib/src/managers/DatabaseManager.js +590 -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/sqliteBackup.d.ts +128 -0
  158. package/lib/src/providers/sqliteBackup.js +365 -0
  159. package/lib/src/providers/sqliteLocation.d.ts +17 -0
  160. package/lib/src/providers/sqliteLocation.js +55 -0
  161. package/lib/src/providers/sqliteMigrations.d.ts +48 -0
  162. package/lib/src/providers/sqliteMigrations.js +72 -0
  163. package/lib/src/rendering/githubAlerts.d.ts +22 -0
  164. package/lib/src/rendering/htmlPolicy.d.ts +76 -0
  165. package/lib/src/rendering/markdownConverter.d.ts +73 -0
  166. package/lib/src/security/PolicyDecisionPoint.d.ts +245 -0
  167. package/lib/src/security/PolicyInformationPoint.d.ts +448 -0
  168. package/lib/src/security/pageActions.d.ts +40 -0
  169. package/lib/src/security/permissions.generated.d.ts +78 -0
  170. package/lib/src/types/Asset.d.ts +414 -0
  171. package/lib/src/types/Catalog.d.ts +61 -0
  172. package/lib/src/types/Comment.d.ts +11 -0
  173. package/lib/src/types/Config.d.ts +388 -0
  174. package/lib/src/types/Organization.d.ts +78 -0
  175. package/lib/src/types/OrganizationProvider.d.ts +38 -0
  176. package/lib/src/types/Page.d.ts +220 -0
  177. package/lib/src/types/Person.d.ts +56 -0
  178. package/lib/src/types/PersonProvider.d.ts +25 -0
  179. package/lib/src/types/Policy.d.ts +139 -0
  180. package/lib/src/types/Policy.js +17 -0
  181. package/lib/src/types/Provider.d.ts +810 -0
  182. package/lib/src/types/Role.d.ts +84 -0
  183. package/lib/src/types/RoleProvider.d.ts +35 -0
  184. package/lib/src/types/Schema.d.ts +425 -0
  185. package/lib/src/types/Share.d.ts +172 -0
  186. package/lib/src/types/Share.js +81 -0
  187. package/lib/src/types/User.d.ts +304 -0
  188. package/lib/src/types/Version.d.ts +189 -0
  189. package/lib/src/types/WikiEngine.d.ts +128 -0
  190. package/lib/src/types/express.d.ts +120 -0
  191. package/lib/src/types/express.js +1 -0
  192. package/lib/src/types/guards.d.ts +78 -0
  193. package/lib/src/types/heic-decode.d.ts +16 -0
  194. package/lib/src/types/index.d.ts +19 -0
  195. package/lib/src/types/linkedom.d.ts +77 -0
  196. package/lib/src/types/markdown-it-plugins.d.ts +21 -0
  197. package/lib/src/utils/DeltaStorage.d.ts +118 -0
  198. package/lib/src/utils/LocaleUtils.d.ts +105 -0
  199. package/lib/src/utils/LocaleUtils.js +294 -0
  200. package/lib/src/utils/PageNameMatcher.d.ts +98 -0
  201. package/lib/src/utils/PathPreflight.d.ts +38 -0
  202. package/lib/src/utils/PathPreflight.js +50 -0
  203. package/lib/src/utils/SectionUtils.d.ts +40 -0
  204. package/lib/src/utils/addonConfigLayer.d.ts +144 -0
  205. package/lib/src/utils/addonConfigLayer.js +382 -0
  206. package/lib/src/utils/addonDatabaseRules.d.ts +25 -0
  207. package/lib/src/utils/addonDatabaseRules.js +57 -0
  208. package/lib/src/utils/addonHost.d.ts +51 -0
  209. package/lib/src/utils/addonHost.js +72 -0
  210. package/lib/src/utils/addonInstaller.d.ts +109 -0
  211. package/lib/src/utils/addonLock.d.ts +37 -0
  212. package/lib/src/utils/addonLock.js +48 -0
  213. package/lib/src/utils/addonPageSync.d.ts +45 -0
  214. package/lib/src/utils/addonProvenance.d.ts +48 -0
  215. package/lib/src/utils/addonTarball.d.ts +41 -0
  216. package/lib/src/utils/addonsPathResolver.d.ts +76 -0
  217. package/lib/src/utils/addonsPathResolver.js +129 -0
  218. package/lib/src/utils/assetMetadataTags.d.ts +66 -0
  219. package/lib/src/utils/atomicWrite.d.ts +28 -0
  220. package/lib/src/utils/auditConfigChange.d.ts +57 -0
  221. package/lib/src/utils/auditEventNames.d.ts +50 -0
  222. package/lib/src/utils/auditEventNames.generated.d.ts +169 -0
  223. package/lib/src/utils/auditEventNames.generated.js +174 -0
  224. package/lib/src/utils/auditEventNames.js +49 -0
  225. package/lib/src/utils/auditEvents.d.ts +265 -0
  226. package/lib/src/utils/auditEvents.js +309 -0
  227. package/lib/src/utils/auditRegistry.d.ts +102 -0
  228. package/lib/src/utils/auditRegistry.js +168 -0
  229. package/lib/src/utils/bip39English.d.ts +2 -0
  230. package/lib/src/utils/configEnvKeys.d.ts +68 -0
  231. package/lib/src/utils/configFiles.d.ts +74 -0
  232. package/lib/src/utils/configFiles.js +150 -0
  233. package/lib/src/utils/delegation.d.ts +48 -0
  234. package/lib/src/utils/deriveUsername.d.ts +21 -0
  235. package/lib/src/utils/explainMediaPath.d.ts +123 -0
  236. package/lib/src/utils/formerTitles.d.ts +69 -0
  237. package/lib/src/utils/frontmatterAccess.d.ts +54 -0
  238. package/lib/src/utils/headlessAdminPassword.d.ts +55 -0
  239. package/lib/src/utils/imageTransform.d.ts +52 -0
  240. package/lib/src/utils/instanceEnvSecret.d.ts +51 -0
  241. package/lib/src/utils/jobSlots.d.ts +43 -0
  242. package/lib/src/utils/keywordNormalizer.d.ts +127 -0
  243. package/lib/src/utils/logger.d.ts +70 -0
  244. package/lib/src/utils/logger.js +106 -0
  245. package/lib/src/utils/magicLinkDeviceState.d.ts +95 -0
  246. package/lib/src/utils/managerUtils.d.ts +40 -0
  247. package/lib/src/utils/migrateLegacyPrivateAttachments.d.ts +15 -0
  248. package/lib/src/utils/orgFilename.d.ts +22 -0
  249. package/lib/src/utils/pageFeature.d.ts +27 -0
  250. package/lib/src/utils/pageFrontmatter.d.ts +21 -0
  251. package/lib/src/utils/pageNotes.d.ts +150 -0
  252. package/lib/src/utils/pageTitleRule.d.ts +37 -0
  253. package/lib/src/utils/pageToArticle.d.ts +59 -0
  254. package/lib/src/utils/pageUrl.d.ts +18 -0
  255. package/lib/src/utils/passwordChange.d.ts +12 -0
  256. package/lib/src/utils/passwordHash.d.ts +60 -0
  257. package/lib/src/utils/permissionCatalog.d.ts +52 -0
  258. package/lib/src/utils/pluginFormatters.d.ts +452 -0
  259. package/lib/src/utils/pluginFormatters.js +714 -0
  260. package/lib/src/utils/privateLinkRewrite.d.ts +42 -0
  261. package/lib/src/utils/privateStoreAccess.d.ts +57 -0
  262. package/lib/src/utils/privateStoreAccess.js +65 -0
  263. package/lib/src/utils/privateStoreCatalogs.d.ts +40 -0
  264. package/lib/src/utils/privateStoreCrypto.d.ts +127 -0
  265. package/lib/src/utils/privateStoreDoor.d.ts +181 -0
  266. package/lib/src/utils/privateStoreExport.d.ts +72 -0
  267. package/lib/src/utils/privateStoreFiles.d.ts +120 -0
  268. package/lib/src/utils/privateStoreMeta.d.ts +64 -0
  269. package/lib/src/utils/privateStoreMigrations.d.ts +37 -0
  270. package/lib/src/utils/privateStorePath.d.ts +259 -0
  271. package/lib/src/utils/privateStorePath.js +436 -0
  272. package/lib/src/utils/privateStoreTakeout.d.ts +76 -0
  273. package/lib/src/utils/privateStoreUnlock.d.ts +175 -0
  274. package/lib/src/utils/proxyClaim.d.ts +59 -0
  275. package/lib/src/utils/proxyClaim.js +30 -0
  276. package/lib/src/utils/redactPrivateNames.d.ts +21 -0
  277. package/lib/src/utils/redactPrivateNames.js +89 -0
  278. package/lib/src/utils/redactSecrets.d.ts +58 -0
  279. package/lib/src/utils/redactSecrets.js +171 -0
  280. package/lib/src/utils/renameLinkRewrite.d.ts +112 -0
  281. package/lib/src/utils/roleGrants.d.ts +35 -0
  282. package/lib/src/utils/safeRedirect.d.ts +32 -0
  283. package/lib/src/utils/schedule.d.ts +54 -0
  284. package/lib/src/utils/secretFileMode.d.ts +17 -0
  285. package/lib/src/utils/seededShippedPages.d.ts +45 -0
  286. package/lib/src/utils/sensitiveValues.d.ts +59 -0
  287. package/lib/src/utils/sensitiveValues.js +106 -0
  288. package/lib/src/utils/sessionEnd.d.ts +12 -0
  289. package/lib/src/utils/sessionGeneration.d.ts +24 -0
  290. package/lib/src/utils/sessionIdle.d.ts +41 -0
  291. package/lib/src/utils/sessionLimits.d.ts +68 -0
  292. package/lib/src/utils/shareLockbox.d.ts +64 -0
  293. package/lib/src/utils/sigstoreTrustedRoot.d.ts +33 -0
  294. package/lib/src/utils/sniffMime.d.ts +21 -0
  295. package/lib/src/utils/storeSearchIndex.d.ts +75 -0
  296. package/lib/src/utils/subjectMayDo.d.ts +21 -0
  297. package/lib/src/utils/systemCategoryRules.d.ts +30 -0
  298. package/lib/src/utils/systemCategoryRules.js +41 -0
  299. package/lib/src/utils/userCreateError.d.ts +62 -0
  300. package/lib/src/utils/username.d.ts +53 -0
  301. package/lib/src/utils/vaultUrlRewrite.d.ts +27 -0
  302. package/lib/src/utils/version.d.ts +84 -0
  303. package/lib/src/utils/videoFrame.d.ts +21 -0
  304. package/package.json +54 -3
@@ -0,0 +1,57 @@
1
+ /**
2
+ * The rules an add-on's database declaration follows (#1860), said once for
3
+ * every reader: the configuration merge, which refuses an add-on whose
4
+ * declaration breaks them, and DatabaseManager, which opens only a declared
5
+ * database.
6
+ *
7
+ * An add-on declares its database in its own `config/default-config.json`:
8
+ *
9
+ * "ngdpbase.addons.<slug>.database": { "owner": "phr", "ledgerTable": "phr_schema_migrations", "encrypt": "required" }
10
+ *
11
+ * `owner` names the file (`<owner>.db`); an add-on that depends on the owner
12
+ * declares the owner's slug and a ledger of its own. `encrypt` is `"required"`
13
+ * (never opened without `NGDPBASE_DATABASE_KEY`) or `"optional"`.
14
+ */
15
+ import { isPlainObject } from './configFiles.js';
16
+ /** A canonical add-on slug: lowercase letters and digits, single dashes. */
17
+ export const ADDON_SLUG = /^[a-z0-9]+(-[a-z0-9]+)*$/;
18
+ /** The values `encrypt` may take. */
19
+ export const DATABASE_ENCRYPT_VALUES = ['required', 'optional'];
20
+ /** The fields a declaration has; any other field is refused, so a misspelt `encrypt` is not silently dropped. */
21
+ const FIELDS = ['owner', 'ledgerTable', 'encrypt'];
22
+ /** The configuration key under which an add-on declares its database. */
23
+ export function addonDatabaseKey(slug) {
24
+ return `ngdpbase.addons.${slug}.database`;
25
+ }
26
+ /** The slug in a `ngdpbase.addons.<slug>.database` key, or null for any other key. */
27
+ export function addonDatabaseKeySlug(key) {
28
+ return /^ngdpbase\.addons\.([^.]+)\.database$/.exec(key)?.[1] ?? null;
29
+ }
30
+ /** What a ledger table of this owner must start with: the slug, dashes as underscores, then `_`. */
31
+ export function ledgerPrefix(owner) {
32
+ return `${owner.replace(/-/g, '_')}_`;
33
+ }
34
+ /** What is wrong with one declaration, one line per problem. Empty when sound. */
35
+ export function addonDatabaseProblems(value) {
36
+ if (!isPlainObject(value))
37
+ return ['the declaration must be an object { owner, ledgerTable, encrypt }'];
38
+ const problems = [];
39
+ const { owner, ledgerTable, encrypt } = value;
40
+ if (typeof owner !== 'string' || !ADDON_SLUG.test(owner)) {
41
+ problems.push(`owner must be an add-on slug (lowercase letters and digits, single dashes), got ${JSON.stringify(owner)}`);
42
+ }
43
+ if (typeof ledgerTable !== 'string') {
44
+ problems.push(`ledgerTable must be a table name, got ${JSON.stringify(ledgerTable)}`);
45
+ }
46
+ else if (typeof owner === 'string' && ADDON_SLUG.test(owner) && !ledgerTable.startsWith(ledgerPrefix(owner))) {
47
+ problems.push(`ledgerTable '${ledgerTable}' must start with '${ledgerPrefix(owner)}'`);
48
+ }
49
+ if (!DATABASE_ENCRYPT_VALUES.includes(encrypt)) {
50
+ problems.push(`encrypt must be "required" or "optional", got ${JSON.stringify(encrypt)}`);
51
+ }
52
+ for (const field of Object.keys(value)) {
53
+ if (!FIELDS.includes(field))
54
+ problems.push(`'${field}' is not a field of a database declaration`);
55
+ }
56
+ return problems;
57
+ }
@@ -0,0 +1,51 @@
1
+ /**
2
+ * What core hands an add-on: the third argument to `register` (#1813).
3
+ *
4
+ * An add-on used to reach core values by importing them from `../../dist/…`.
5
+ * That ties it to core's file layout and gives every add-on the same shared
6
+ * module objects. The host is instead built per add-on, from the running
7
+ * core's own values (imported here, never re-implemented), and frozen:
8
+ *
9
+ * - `logger` is a child tagged with the add-on's slug (`{ addon: slug }`);
10
+ * - `recordAuditEvent` and `addonAuditEventName` accept only the audit events
11
+ * this add-on declares in its own `config/default-config.json`, so one
12
+ * add-on cannot write records that look like another's or like core's;
13
+ * - the object is `Object.freeze`d, so no add-on can replace a value.
14
+ *
15
+ * Additive only: nothing here is removed or renamed without a major release.
16
+ * Anything an add-on needs that the host does not offer is added here by PR.
17
+ */
18
+ import type { Logger } from 'winston';
19
+ import { ApiContext, ApiError, sendApiError } from '../context/ApiContext.js';
20
+ import { actorOf } from '../context/ActorContext.js';
21
+ import { jobContextFromRequest, jobContextFromSystem } from '../context/JobContext.js';
22
+ import { guardedFetch } from '../http/guardedFetch.js';
23
+ import { recordAuditEvent } from './auditEvents.js';
24
+ import { addonAuditEventName } from './auditEventNames.js';
25
+ /** The values core offers an add-on, under the names they were imported as. */
26
+ export interface AddonHost {
27
+ readonly ApiContext: typeof ApiContext;
28
+ readonly ApiError: typeof ApiError;
29
+ readonly sendApiError: typeof sendApiError;
30
+ readonly recordAuditEvent: typeof recordAuditEvent;
31
+ readonly addonAuditEventName: typeof addonAuditEventName;
32
+ readonly actorOf: typeof actorOf;
33
+ readonly jobContextFromRequest: typeof jobContextFromRequest;
34
+ readonly jobContextFromSystem: typeof jobContextFromSystem;
35
+ readonly logger: Logger;
36
+ readonly guardedFetch: typeof guardedFetch;
37
+ }
38
+ /**
39
+ * The audit event names one add-on declares: the permission entries carrying
40
+ * an `audit` block, and the `ngdpbase.audit.events` entries, in that add-on's
41
+ * own `config/default-config.json` — read by the one declarations reader.
42
+ */
43
+ export declare function addonDeclaredAuditEvents(addonDefaults: Record<string, unknown>): ReadonlySet<string>;
44
+ /**
45
+ * Build the frozen host for one add-on.
46
+ *
47
+ * @param slug - The add-on's canonical slug
48
+ * @param addonDefaults - That add-on's own default-config.json, as folded into
49
+ * the configuration merge (`ConfigurationManager.getAddonDeclaredDefaults`)
50
+ */
51
+ export declare function buildAddonHost(slug: string, addonDefaults: Record<string, unknown>): AddonHost;
@@ -0,0 +1,72 @@
1
+ /**
2
+ * What core hands an add-on: the third argument to `register` (#1813).
3
+ *
4
+ * An add-on used to reach core values by importing them from `../../dist/…`.
5
+ * That ties it to core's file layout and gives every add-on the same shared
6
+ * module objects. The host is instead built per add-on, from the running
7
+ * core's own values (imported here, never re-implemented), and frozen:
8
+ *
9
+ * - `logger` is a child tagged with the add-on's slug (`{ addon: slug }`);
10
+ * - `recordAuditEvent` and `addonAuditEventName` accept only the audit events
11
+ * this add-on declares in its own `config/default-config.json`, so one
12
+ * add-on cannot write records that look like another's or like core's;
13
+ * - the object is `Object.freeze`d, so no add-on can replace a value.
14
+ *
15
+ * Additive only: nothing here is removed or renamed without a major release.
16
+ * Anything an add-on needs that the host does not offer is added here by PR.
17
+ */
18
+ import { ApiContext, ApiError, sendApiError } from '../context/ApiContext.js';
19
+ import { actorOf } from '../context/ActorContext.js';
20
+ import { jobContextFromRequest, jobContextFromSystem } from '../context/JobContext.js';
21
+ import { guardedFetch } from '../http/guardedFetch.js';
22
+ import { recordAuditEvent } from './auditEvents.js';
23
+ import { addonAuditEventName } from './auditEventNames.js';
24
+ import { auditDeclarationsFrom } from './auditRegistry.js';
25
+ import logger from './logger.js';
26
+ /**
27
+ * The audit event names one add-on declares: the permission entries carrying
28
+ * an `audit` block, and the `ngdpbase.audit.events` entries, in that add-on's
29
+ * own `config/default-config.json` — read by the one declarations reader.
30
+ */
31
+ export function addonDeclaredAuditEvents(addonDefaults) {
32
+ return new Set(Object.keys(auditDeclarationsFrom((key, fallback) => addonDefaults[key] ?? fallback)));
33
+ }
34
+ function refuseUndeclared(slug, name, declared) {
35
+ if (declared.has(name))
36
+ return;
37
+ const message = `Add-on '${slug}' may record only the audit events it declares in its config/default-config.json; ` +
38
+ `'${name}' is not one of them (declared: ${declared.size > 0 ? [...declared].sort().join(', ') : 'none'}).`;
39
+ logger.error(`[addons] ${message}`);
40
+ throw new Error(message);
41
+ }
42
+ /**
43
+ * Build the frozen host for one add-on.
44
+ *
45
+ * @param slug - The add-on's canonical slug
46
+ * @param addonDefaults - That add-on's own default-config.json, as folded into
47
+ * the configuration merge (`ConfigurationManager.getAddonDeclaredDefaults`)
48
+ */
49
+ export function buildAddonHost(slug, addonDefaults) {
50
+ const declared = addonDeclaredAuditEvents(addonDefaults);
51
+ const hostAddonAuditEventName = (name) => {
52
+ const checked = addonAuditEventName(name);
53
+ refuseUndeclared(slug, name, declared);
54
+ return checked;
55
+ };
56
+ const hostRecordAuditEvent = async (sink, event, onError) => {
57
+ refuseUndeclared(slug, event.eventType, declared);
58
+ return recordAuditEvent(sink, event, onError);
59
+ };
60
+ return Object.freeze({
61
+ ApiContext,
62
+ ApiError,
63
+ sendApiError,
64
+ recordAuditEvent: hostRecordAuditEvent,
65
+ addonAuditEventName: hostAddonAuditEventName,
66
+ actorOf,
67
+ jobContextFromRequest,
68
+ jobContextFromSystem,
69
+ logger: logger.child({ addon: slug }),
70
+ guardedFetch
71
+ });
72
+ }
@@ -0,0 +1,109 @@
1
+ /**
2
+ * The add-on installer (#1830): install the npm add-ons a site's configuration
3
+ * names into `<data>/addons/<slug>/`, pinned and verified.
4
+ *
5
+ * AddonsManager owns it and calls {@link installConfiguredAddons} at boot,
6
+ * before discovery. This module holds the mechanics only — registry, integrity,
7
+ * provenance, unpacking, the lock file — and takes its outbound HTTP, its
8
+ * provenance check and its audit hook as parameters, so the only network it
9
+ * reaches is the guarded client AddonsManager hands it (src/http, #1139).
10
+ *
11
+ * As decided on #1810:
12
+ * - An add-on already in the lock file is used from disk, after its stored
13
+ * tarball's sha512 is checked against the lock and the unpacked folder
14
+ * against that tarball. No registry call. A folder that differs from its
15
+ * tarball is rewritten from it; a tarball that fails its sha512 is not
16
+ * trusted, so the folder is set aside and the add-on is not loaded.
17
+ * - An add-on not yet installed is resolved from the registry packument: the
18
+ * highest release in the configured range whose `ngdpbase.minVersion` this
19
+ * core meets (#1757). Its tarball's sha512 must equal the packument's
20
+ * `dist.integrity`; its Sigstore provenance must be valid for that tarball
21
+ * and name the configured repository; and its own package.json must name the
22
+ * same package, version and slug (the registry metadata and the tarball are
23
+ * not trusted to agree — "manifest confusion").
24
+ * - Registry unreachable, or anything refused: that add-on is skipped with a
25
+ * reason, and the boot continues. It is tried again at the next start.
26
+ */
27
+ import { type ProvenanceResult } from './addonProvenance.js';
28
+ /** One configured add-on: `ngdpbase.addons.install.<slug>`. */
29
+ export interface InstallSpec {
30
+ package: string;
31
+ version: string;
32
+ /** The source repository its provenance must name, e.g. `github.com/jwilleke/yourphr`. */
33
+ repository: string;
34
+ }
35
+ /** The outbound GET the installer is given. Throws when the host cannot be reached. */
36
+ export type RegistryFetch = (url: string, options: {
37
+ maxBytes: number;
38
+ accept: string;
39
+ }) => Promise<{
40
+ status: number;
41
+ body: Buffer;
42
+ }>;
43
+ /** Check a release's attestations. Throws when the check cannot be made (trust root unreachable). */
44
+ export type ProvenanceCheck = (input: {
45
+ attestations: unknown;
46
+ name: string;
47
+ version: string;
48
+ sha512Hex: string;
49
+ repository: string;
50
+ }) => Promise<ProvenanceResult>;
51
+ /** What is about to be installed, for the audit record written before it is. */
52
+ export interface InstallRecord {
53
+ slug: string;
54
+ package: string;
55
+ version: string;
56
+ integrity: string;
57
+ repository: string;
58
+ /** The version this replaces, when the configuration moved it. */
59
+ previousVersion?: string;
60
+ }
61
+ export interface InstallerOptions {
62
+ /** `<data>/addons`: each add-on unpacks into a folder here. */
63
+ addonsDir: string;
64
+ /** Registry base URL, e.g. https://registry.npmjs.org */
65
+ registry: string;
66
+ /** This core's version, for `ngdpbase.minVersion`. */
67
+ coreVersion: string;
68
+ maxPackumentBytes: number;
69
+ maxTarballBytes: number;
70
+ maxUnpackedBytes: number;
71
+ fetch: RegistryFetch;
72
+ checkProvenance: ProvenanceCheck;
73
+ /**
74
+ * Called once everything is verified and before anything is written. If it
75
+ * throws (an audit record that must be written could not be), nothing is
76
+ * installed.
77
+ */
78
+ beforeInstall?: (record: InstallRecord) => Promise<void>;
79
+ now?: () => Date;
80
+ }
81
+ export type InstallStatus =
82
+ /** Installed now from the registry. */
83
+ 'installed'
84
+ /** Already installed; verified against the lock, nothing changed. */
85
+ | 'verified'
86
+ /** Already installed; the folder differed from its verified tarball and was rewritten. */
87
+ | 'repaired'
88
+ /** Not installed (and not loaded); `reason` says why. */
89
+ | 'skipped';
90
+ /** Which verification refused, for `addon-verify-failed`. */
91
+ export type FailedCheck = 'integrity' | 'provenance' | 'tarball' | 'manifest' | 'lock' | 'folder';
92
+ export interface InstallOutcome {
93
+ slug: string;
94
+ status: InstallStatus;
95
+ package?: string;
96
+ version?: string;
97
+ reason?: string;
98
+ /** Registry (or the provenance trust root) could not be reached — the case admins are told to wait out. */
99
+ registryUnreachable?: boolean;
100
+ /** Set when a verification refused, or (for `repaired`) found the folder changed. */
101
+ failedCheck?: FailedCheck;
102
+ }
103
+ /** `sha512-<base64>` of `data`. */
104
+ export declare function sha512Integrity(data: Buffer): string;
105
+ /**
106
+ * Install or verify every add-on in `specs` (`ngdpbase.addons.install`).
107
+ * Never throws for one add-on's problem: each outcome says what happened.
108
+ */
109
+ export declare function installConfiguredAddons(specs: Record<string, unknown>, opts: InstallerOptions): Promise<InstallOutcome[]>;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * The installed add-ons' lock file, `<data>/addons/addons-lock.json` (#1830).
3
+ *
4
+ * The installer (`addonInstaller.ts`) is its only writer. It is read here as
5
+ * well, synchronously and with no other dependency, because the configuration
6
+ * merge (`addonConfigLayer.ts`) runs before any manager and has to know which
7
+ * folders in `<data>/addons` are installed add-ons at all: a folder the lock
8
+ * does not name is never an add-on, whatever it contains.
9
+ */
10
+ /** What the lock records for one installed add-on. */
11
+ export interface LockEntry {
12
+ package: string;
13
+ version: string;
14
+ integrity: string;
15
+ installedAt: string;
16
+ /** The verified Sigstore provenance the install was accepted on. */
17
+ provenance: {
18
+ repository: string;
19
+ verifiedAt: string;
20
+ };
21
+ }
22
+ export interface LockFile {
23
+ lockfileVersion: 1;
24
+ addons: Record<string, LockEntry>;
25
+ }
26
+ export declare const LOCK_FILE_NAME = "addons-lock.json";
27
+ /** Verified tarballs, kept so a restart needs no registry. Dot-named: discovery skips it. */
28
+ export declare const PACKAGES_DIR_NAME = ".packages";
29
+ export declare function lockFilePath(addonsDir: string): string;
30
+ /** The lock file, or an empty one when there is none. Throws when it exists and is not JSON. */
31
+ export declare function readLockSync(addonsDir: string): LockFile;
32
+ /**
33
+ * The folders in `addonsDir` that are installed add-ons for this site: named
34
+ * in the lock file AND in the configured install map, and present on disk.
35
+ * An unreadable lock file names none.
36
+ */
37
+ export declare function lockedAddonDirsSync(addonsDir: string, configuredSlugs: Iterable<string>): string[];
@@ -0,0 +1,48 @@
1
+ /**
2
+ * The installed add-ons' lock file, `<data>/addons/addons-lock.json` (#1830).
3
+ *
4
+ * The installer (`addonInstaller.ts`) is its only writer. It is read here as
5
+ * well, synchronously and with no other dependency, because the configuration
6
+ * merge (`addonConfigLayer.ts`) runs before any manager and has to know which
7
+ * folders in `<data>/addons` are installed add-ons at all: a folder the lock
8
+ * does not name is never an add-on, whatever it contains.
9
+ */
10
+ import fs from 'fs';
11
+ import path from 'path';
12
+ export const LOCK_FILE_NAME = 'addons-lock.json';
13
+ /** Verified tarballs, kept so a restart needs no registry. Dot-named: discovery skips it. */
14
+ export const PACKAGES_DIR_NAME = '.packages';
15
+ export function lockFilePath(addonsDir) {
16
+ return path.join(addonsDir, LOCK_FILE_NAME);
17
+ }
18
+ /** The lock file, or an empty one when there is none. Throws when it exists and is not JSON. */
19
+ export function readLockSync(addonsDir) {
20
+ const file = lockFilePath(addonsDir);
21
+ if (!fs.existsSync(file))
22
+ return { lockfileVersion: 1, addons: {} };
23
+ const parsed = JSON.parse(fs.readFileSync(file, 'utf8'));
24
+ return { lockfileVersion: 1, addons: parsed.addons ?? {} };
25
+ }
26
+ /**
27
+ * The folders in `addonsDir` that are installed add-ons for this site: named
28
+ * in the lock file AND in the configured install map, and present on disk.
29
+ * An unreadable lock file names none.
30
+ */
31
+ export function lockedAddonDirsSync(addonsDir, configuredSlugs) {
32
+ let lock;
33
+ try {
34
+ lock = readLockSync(addonsDir);
35
+ }
36
+ catch {
37
+ return [];
38
+ }
39
+ const out = [];
40
+ for (const slug of configuredSlugs) {
41
+ if (!lock.addons[slug])
42
+ continue;
43
+ const dir = path.join(addonsDir, slug);
44
+ if (fs.existsSync(path.join(dir, 'package.json')))
45
+ out.push(dir);
46
+ }
47
+ return out;
48
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Stable content hash of an addon page body. Trimmed so a trailing-newline
3
+ * difference between the source file and the on-disk form does not read as a
4
+ * modification. This is the value stamped into a seeded page's
5
+ * `addon-source-hash` frontmatter.
6
+ */
7
+ export declare function pageSourceHash(content: string): string;
8
+ /**
9
+ * Frontmatter key a required page's live copy carries: `pageSourceHash` of the
10
+ * body it was seeded or synced with (#1395). The required-pages analogue of
11
+ * `addon-source-hash`, read by the same `evaluateSeededAddonPage()`.
12
+ */
13
+ export declare const REQUIRED_SOURCE_HASH_KEY = "required-source-hash";
14
+ /** Reseed status of an addon page that ALREADY exists in the instance. */
15
+ export type SeededAddonPageStatus = 'current' | 'outdated' | 'locally-modified';
16
+ /**
17
+ * Decide what should happen to an already-seeded addon page, given its source
18
+ * body, its current live body, and the `addon-source-hash` stamped at seed time.
19
+ *
20
+ * - `current` — live body already matches source; nothing to do.
21
+ * - `outdated` — source changed and the live page is unmodified since
22
+ * seed (stored hash matches live), OR the page is legacy
23
+ * (no stored hash — pre-#920 seed; treated as reseedable
24
+ * since the previous body is kept as a revertable version).
25
+ * Safe to reseed.
26
+ * - `locally-modified` — source changed but the live body differs from what was
27
+ * last seeded (⇒ operator-edited). Skip; never clobber.
28
+ */
29
+ export declare function evaluateSeededAddonPage(args: {
30
+ sourceContent: string;
31
+ liveContent: string;
32
+ storedHash: string | undefined;
33
+ }): SeededAddonPageStatus;
34
+ /**
35
+ * Default edit access for a page ngdpbase ships (#971, #1411): a `general`
36
+ * page is instance-owned and gets no stamp; any other category — system,
37
+ * documentation, addon, unclassified — is administrator-edit only. A source
38
+ * that declares its own `access` overrides this.
39
+ *
40
+ * @param category - The page's resolved `system-category`
41
+ * @returns The access object to stamp, or undefined to leave the page unprotected
42
+ */
43
+ export declare function defaultShippedPageAccess(category: unknown): {
44
+ edit: string[];
45
+ } | undefined;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Sigstore provenance of an npm add-on (#1830, decided on #1810): before an
3
+ * add-on is installed, its SLSA provenance attestation must be valid for the
4
+ * exact tarball and name the repository the site expects it to be built from.
5
+ *
6
+ * The registry serves a package's attestations at `dist.attestations.url`.
7
+ * The SLSA one is a Sigstore bundle: a DSSE envelope around an in-toto
8
+ * statement, signed with a short-lived Fulcio certificate issued to the CI
9
+ * workflow that built it, and logged in Rekor. Verification here:
10
+ *
11
+ * - the bundle verifies against the Sigstore trusted root (Fulcio chain,
12
+ * transparency log, timestamps), with `@sigstore/verify`;
13
+ * - the certificate's identity is a workflow of the expected repository
14
+ * (subject alternative name under `https://<repository>/`) and its issuer is
15
+ * that host's CI (GitHub Actions or GitLab CI);
16
+ * - the statement's subject is this package and version, and its sha512 is
17
+ * the tarball's.
18
+ *
19
+ * The trusted root is passed in: `sigstoreTrustedRoot.ts` fetches it through
20
+ * the guarded client. Nothing here opens the network.
21
+ */
22
+ export type ProvenanceResult = {
23
+ ok: true;
24
+ repository: string;
25
+ } | {
26
+ ok: false;
27
+ reason: string;
28
+ };
29
+ /**
30
+ * `github.com/owner/repo` from any of `github.com/owner/repo`,
31
+ * `https://github.com/owner/repo`, `git+https://github.com/owner/repo.git`.
32
+ * Null when it is not host/owner/repo.
33
+ */
34
+ export declare function normaliseRepository(value: string): string | null;
35
+ /** The package URL npm puts in the statement's subject. */
36
+ export declare function npmPurl(name: string, version: string): string;
37
+ /**
38
+ * Check the attestations the registry returned for `name@version` against the
39
+ * tarball's sha512 (hex) and the expected repository.
40
+ */
41
+ export declare function verifyProvenance(input: {
42
+ attestations: unknown;
43
+ name: string;
44
+ version: string;
45
+ sha512Hex: string;
46
+ repository: string;
47
+ trustedRoot: unknown;
48
+ }): ProvenanceResult;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Reading and unpacking an add-on's npm tarball safely (#1830), with `tar`.
3
+ *
4
+ * Every entry is checked in a reading pass before a byte reaches the disk:
5
+ *
6
+ * - only regular files and directories; a link (symbolic or hard), device or
7
+ * FIFO refuses the whole tarball, so nothing can point outside the add-on's
8
+ * folder;
9
+ * - a path that is absolute, holds `..`, a backslash or NUL, or is empty once
10
+ * npm's leading `package/` folder is removed, refuses the whole tarball;
11
+ * - the unpacked size is counted as the entries are read and the read is
12
+ * aborted at the cap, so a tarball that inflates enormously stops there;
13
+ * - tar runs `strict`, so a malformed header is an error, not a warning.
14
+ *
15
+ * Unpacking then runs `tar.x` into a fresh staging folder (with the same type
16
+ * filter, `strip: 1`, no preserved paths, no preserved owners), which is
17
+ * renamed into place only when it is complete.
18
+ *
19
+ * Refusing the whole tarball, not skipping the bad entry, is deliberate: a
20
+ * package that carries one is not the package its author published, and
21
+ * installing the rest of it would be a guess.
22
+ */
23
+ /** A file in the package, by its path without npm's leading `package/`. */
24
+ export type TarballFiles = Map<string, Buffer>;
25
+ /**
26
+ * The path as it will be written, relative to the add-on folder: npm's leading
27
+ * folder (normally `package/`) removed, and refused if it could reach outside.
28
+ */
29
+ export declare function safeEntryPath(raw: string): string;
30
+ /**
31
+ * Read and check every entry of the gzipped tarball. Resolves to its files;
32
+ * rejects on the first thing that is not safe or not understood.
33
+ */
34
+ export declare function readTarball(tgz: Buffer, maxUnpackedBytes: number): Promise<TarballFiles>;
35
+ /**
36
+ * Unpack the (already checked) tarball at `tgzPath` into `target`: into a
37
+ * fresh staging folder beside it, then swapped in.
38
+ */
39
+ export declare function unpackTarball(tgzPath: string, target: string): Promise<void>;
40
+ /** Whether `dir` holds exactly `files`, byte for byte, and nothing else (no links). */
41
+ export declare function folderMatches(dir: string, files: TarballFiles): Promise<boolean>;
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Shared parsing/discovery for the `ngdpbase.managers.addons-manager.addons-path`
3
+ * config value.
4
+ *
5
+ * #924: `AddonsManager` (real runtime discovery) and `ConfigurationManager`
6
+ * (the #672 boot-time "does this enabled addon exist" safety check) used to
7
+ * each carry their own copy of this logic. They drifted: `AddonsManager` was
8
+ * updated for #673's `node_modules:<glob>` packaged-addon syntax, but the
9
+ * validator's copy was not, so it resolved a `node_modules:` entry as a
10
+ * literal (non-existent) directory and treated every packaged addon as
11
+ * "unknown" — crashing boot the moment one was enabled. Consolidating the
12
+ * parsing/matching into one module removes the class of bug, not just this
13
+ * instance of it.
14
+ */
15
+ /** Prefix marking an addons-path entry as an npm-package glob rather than a directory. */
16
+ export declare const NPM_ADDON_PREFIX = "node_modules:";
17
+ export interface SplitAddonsPath {
18
+ /** Plain directory entries (bundled/drop-in), not yet resolved to absolute. */
19
+ directories: string[];
20
+ /** npm package name globs (the part after `node_modules:`), e.g. `@jwilleke/*-addon`. */
21
+ npmPatterns: string[];
22
+ }
23
+ /**
24
+ * Coerce the raw config value (string or string[]) and split it into
25
+ * filesystem directory entries vs. `node_modules:<glob>` npm patterns.
26
+ */
27
+ export declare function splitAddonsPath(raw: unknown): SplitAddonsPath;
28
+ /** The config key naming the add-ons to install (#1830). */
29
+ export declare const ADDONS_INSTALL_KEY = "ngdpbase.addons.install";
30
+ /**
31
+ * Where installed add-ons live (#1830): `<data>/addons`, one folder per slug.
32
+ * Only a folder the lock file names, for a slug still in the install map, is
33
+ * an add-on (see `addonLock.ts`); anything else there is never loaded.
34
+ */
35
+ export declare function installedAddonsDir(dataFolder: string, cwd?: string): string;
36
+ /** The slugs `ngdpbase.addons.install` names, from a merged or shipped+custom view. */
37
+ export declare function configuredInstallSlugs(config: Record<string, unknown>): string[];
38
+ /** Locate the `node_modules` directory to search for packaged addons (resolved from cwd). */
39
+ export declare function findNodeModulesDir(cwd?: string): string | null;
40
+ /**
41
+ * Expand a `@scope/glob` (or bare `glob`) npm pattern to matching package
42
+ * directories under `nmRoot`.
43
+ */
44
+ export declare function matchNpmPackageDirs(nmRoot: string, pattern: string): string[];
45
+ /**
46
+ * Best-effort addon identity for a packaged (npm) addon directory, derived
47
+ * from its package-directory name alone — no module import, matching the
48
+ * same boot-time-speed, no-module-loading design already accepted for the
49
+ * directory-scan case (see `ConfigurationManager.assertConfiguredAddonsExist`).
50
+ *
51
+ * Follows the documented packaged-addon naming convention
52
+ * (`@scope/<slug>-addon`, see docs/platform/deployment/addon-packaged.md):
53
+ * strips a trailing `-addon` suffix if present, else returns the folder name
54
+ * as-is.
55
+ *
56
+ * Caveat (same class as the existing directory-name heuristic): the addon's
57
+ * *real* identity is whatever its module exports as `name` at runtime. A
58
+ * package that doesn't follow the `-addon` naming convention, or whose
59
+ * module exports a different `name`, won't be matched precisely here — this
60
+ * is a validation-time approximation, not the source of truth.
61
+ */
62
+ export declare function deriveAddonSlugFromPackageDirName(dirName: string): string;
63
+ /**
64
+ * Canonical identity for an addon directory (#927), resolved the SAME
65
+ * import-free way in every layer (discovery, `isEnabled`, the boot-time
66
+ * validator) so the four historical identities (folder name, module `name`,
67
+ * config key, manifest slug) can no longer drift:
68
+ *
69
+ * canonicalId = package.json `ngdpbase.slug` ?? deriveAddonSlugFromPackageDirName(folder)
70
+ *
71
+ * Reads `package.json` statically — never imports the module — which is what
72
+ * lets the boot validator compute the exact id the runtime will register
73
+ * under, instead of guessing. The module's exported `name` is a display
74
+ * label validated against this at load time, not a source of identity.
75
+ */
76
+ export declare function resolveAddonSlug(addonDir: string, source: 'directory' | 'npm'): string;