reference.ts 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. export * as ConfigReferencePlugin from "./reference"
  2. import { define } from "../../plugin/internal"
  3. import path from "path"
  4. import { Effect } from "effect"
  5. import { Config } from "../../config"
  6. import { ConfigReference } from "../reference"
  7. import { Reference } from "../../reference"
  8. import { AbsolutePath } from "../../schema"
  9. import { Global } from "../../global"
  10. import { Location } from "../../location"
  11. export const Plugin = define({
  12. id: "core/config-reference",
  13. effect: Effect.fn(function* (ctx) {
  14. const config = yield* Config.Service
  15. const location = yield* Location.Service
  16. const global = yield* Global.Service
  17. yield* ctx.reference.transform(
  18. Effect.fn(function* (draft) {
  19. const entries = new Map<string, Reference.Source>()
  20. for (const doc of (yield* config.entries()).filter(
  21. (entry): entry is Config.Document => entry.type === "document",
  22. )) {
  23. const directory = doc.path ? path.dirname(doc.path) : location.directory
  24. for (const [name, entry] of Object.entries(doc.info.references ?? {})) {
  25. if (!validAlias(name)) continue
  26. const description = typeof entry === "string" ? undefined : entry.description
  27. const hidden = typeof entry === "string" ? undefined : entry.hidden
  28. entries.set(
  29. name,
  30. local(entry)
  31. ? Reference.LocalSource.make({
  32. type: "local",
  33. path: AbsolutePath.make(
  34. localPath(directory, global.home, typeof entry === "string" ? entry : entry.path),
  35. ),
  36. ...(description === undefined ? {} : { description }),
  37. ...(hidden === undefined ? {} : { hidden }),
  38. })
  39. : Reference.GitSource.make({
  40. type: "git",
  41. repository: typeof entry === "string" ? entry : entry.repository,
  42. ...(entry.branch === undefined ? {} : { branch: entry.branch }),
  43. ...(description === undefined ? {} : { description }),
  44. ...(hidden === undefined ? {} : { hidden }),
  45. }),
  46. )
  47. }
  48. }
  49. for (const [name, source] of entries) draft.add(name, source)
  50. }),
  51. )
  52. }),
  53. })
  54. function validAlias(name: string) {
  55. return name.length > 0 && !/[\/\s`,]/.test(name)
  56. }
  57. function local(entry: ConfigReference.Entry): entry is string | ConfigReference.Local {
  58. return typeof entry === "string"
  59. ? entry.startsWith(".") || entry.startsWith("/") || entry.startsWith("~")
  60. : "path" in entry
  61. }
  62. function localPath(directory: string, home: string, value: string) {
  63. if (value.startsWith("~/")) return path.join(home, value.slice(2))
  64. return path.isAbsolute(value) ? value : path.resolve(directory, value)
  65. }