MCPcopy Create free account
hub / github.com/anomalyco/opencode / substitute

Function substitute

packages/opencode/src/config/variable.ts:34–91  ·  view source on GitHub ↗
(input: SubstituteInput)

Source from the content-addressed store, hash-verified

32
33/** Apply {env:VAR} and {file:path} substitutions to config text. */
34export async function substitute(input: SubstituteInput) {
35 const missing = input.missing ?? "error"
36 let text = input.text.replace(/\{env:([^}]+)\}/g, (_, varName) => {
37 return (input.env?.[varName] ?? process.env[varName]) || ""
38 })
39
40 const fileMatches = Array.from(text.matchAll(/\{file:[^}]+\}/g))
41 if (!fileMatches.length) return text
42
43 const configDir = dir(input)
44 const configSource = source(input)
45 let out = ""
46 let cursor = 0
47
48 for (const match of fileMatches) {
49 const token = match[0]
50 const index = match.index
51 out += text.slice(cursor, index)
52
53 const lineStart = text.lastIndexOf("\n", index - 1) + 1
54 const prefix = text.slice(lineStart, index).trimStart()
55 if (prefix.startsWith("//")) {
56 out += token
57 cursor = index + token.length
58 continue
59 }
60
61 let filePath = token.replace(/^\{file:/, "").replace(/\}$/, "")
62 if (filePath.startsWith("~/")) {
63 filePath = path.join(os.homedir(), filePath.slice(2))
64 }
65
66 const resolvedPath = path.isAbsolute(filePath) ? filePath : path.resolve(configDir, filePath)
67 const fileContent = (
68 await Filesystem.readText(resolvedPath).catch((error: NodeJS.ErrnoException) => {
69 if (missing === "empty") return ""
70
71 const errMsg = `bad file reference: "${token}"`
72 if (error.code === "ENOENT") {
73 throw new InvalidError(
74 {
75 path: configSource,
76 message: errMsg + ` ${resolvedPath} does not exist`,
77 },
78 { cause: error },
79 )
80 }
81 throw new InvalidError({ path: configSource, message: errMsg }, { cause: error })
82 })
83 ).trim()
84
85 out += JSON.stringify(fileContent).slice(1, -1)
86 cursor = index + token.length
87 }
88
89 out += text.slice(cursor)
90 return out
91}

Callers

nothing calls this directly

Calls 3

dirFunction · 0.70
sourceFunction · 0.70
fromMethod · 0.45

Tested by

no test coverage detected