modules.ts 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. /**
  2. * The modules a package offers a composition: how a declared `dsh.plugins`
  3. * entry is named as a row and derived into a row id, and its wire view.
  4. * @module @deepseek-ai/dsh-plugin-manager/modules
  5. */
  6. import type { PluginProbe } from '@deepseek-ai/dsh-app-boot'
  7. import type { JsonValue } from '@deepseek-ai/dsh-util-values'
  8. import { optional } from './helpers.ts'
  9. import type { PluginPackageAddableView } from './types.ts'
  10. /**
  11. * The row `name` for one declared addable module.
  12. * @param packageName - the package.
  13. * @param declared - the `dsh.plugins[].name`, `.` for the main export.
  14. * @returns the bare package for `.`, else `<package>/<subpath>`.
  15. */
  16. export function moduleSpecifier(packageName: string, declared: string): string {
  17. if (declared === '.') return packageName
  18. return `${packageName}/${declared.replace(/^\.\//, '')}`
  19. }
  20. /**
  21. * The row id derived from a package name and module: the unscoped name, then the subpath.
  22. * @param packageName - the package.
  23. * @param declared - the `dsh.plugins[].name`, `.` for the main export.
  24. * @returns the row id.
  25. */
  26. export function derivedRowId(packageName: string, declared: string): string {
  27. const base = packageName.replace(/^@/, '')
  28. return declared === '.' ? base : `${base}/${declared.replace(/^\.\//, '')}`
  29. }
  30. /**
  31. * The modules a package offers a composition: what it declares in
  32. * `dsh.plugins`, and — for a plugin module — its main export as `.`, the
  33. * implicit entry `PluginManager.addRow` accepts without a declaration.
  34. * @param packageName - the package.
  35. * @param probe - the package's probe record, when one exists.
  36. * @returns the declared modules, with `.` first for a plugin module that does not declare it.
  37. */
  38. export function addableViews(packageName: string, probe: PluginProbe | undefined): PluginPackageAddableView[] {
  39. const declared = (probe?.addable ?? []).map(entry => addableView(packageName, entry))
  40. if (probe?.kind !== 'plugin' || declared.some(entry => entry.declaredName === '.')) return declared
  41. return [{
  42. moduleName: packageName,
  43. declaredName: '.',
  44. ...optional('title', probe.title),
  45. ok: probe.ok,
  46. ...optional('error', probe.reason),
  47. ...optional('configSchema', probe.configSchema as JsonValue | undefined),
  48. }, ...declared]
  49. }
  50. /**
  51. * The wire view of one probed addable module.
  52. * @param packageName - the package.
  53. * @param entry - the probe's record of the declared module.
  54. * @returns the view.
  55. */
  56. export function addableView(packageName: string, entry: PluginProbe['addable'][number]): PluginPackageAddableView {
  57. return {
  58. moduleName: moduleSpecifier(packageName, entry.name),
  59. declaredName: entry.name,
  60. ...optional('title', entry.title),
  61. // The probe read both from JSON: a manifest field and a child's report.
  62. ...optional('config', entry.config as JsonValue | undefined),
  63. ok: entry.ok,
  64. ...optional('error', entry.error),
  65. ...optional('configSchema', entry.configSchema as JsonValue | undefined),
  66. }
  67. }