(req: ScaffoldRequest)
| 184 | } |
| 185 | |
| 186 | export async function runScaffold(req: ScaffoldRequest): Promise<ScaffoldResult> { |
| 187 | let manifest: ScaffoldManifest; |
| 188 | try { |
| 189 | manifest = await loadScaffoldManifest(req.scaffoldsRoot); |
| 190 | } catch (err) { |
| 191 | const reason = err instanceof Error ? err.message : String(err); |
| 192 | return { ok: false, reason: `scaffold manifest unavailable: ${reason}` }; |
| 193 | } |
| 194 | const entry = manifest.scaffolds[req.kind]; |
| 195 | if (!entry) return { ok: false, reason: `unknown scaffold kind: ${req.kind}` }; |
| 196 | |
| 197 | const templatesRoot = path.dirname(path.resolve(req.scaffoldsRoot)); |
| 198 | let source: string; |
| 199 | try { |
| 200 | const sourceRel = path.relative(templatesRoot, path.resolve(req.scaffoldsRoot, entry.path)); |
| 201 | source = await resolveSafeChildPath(templatesRoot, sourceRel); |
| 202 | } catch (err) { |
| 203 | const reason = err instanceof Error ? err.message : String(err); |
| 204 | return { |
| 205 | ok: false, |
| 206 | reason: `scaffold source outside templates root: ${entry.path}: ${reason}`, |
| 207 | }; |
| 208 | } |
| 209 | if (!isWithinRoot(templatesRoot, source)) { |
| 210 | return { ok: false, reason: `scaffold source outside templates root: ${entry.path}` }; |
| 211 | } |
| 212 | let contents: string; |
| 213 | try { |
| 214 | contents = await readFile(source, 'utf8'); |
| 215 | } catch (err) { |
| 216 | const reason = err instanceof Error ? err.message : String(err); |
| 217 | return { |
| 218 | ok: false, |
| 219 | reason: `scaffold source not found for kind ${req.kind} (${entry.path}): ${reason}`, |
| 220 | }; |
| 221 | } |
| 222 | const normalizedContents = normalizeLegacyEditmodeBlock(contents); |
| 223 | const normalizedEditmode = normalizedContents !== null; |
| 224 | if (normalizedContents !== null) { |
| 225 | contents = normalizedContents; |
| 226 | } |
| 227 | |
| 228 | let dest: string; |
| 229 | const actualDestPath = destinationPathForSource(req.destPath, source); |
| 230 | try { |
| 231 | dest = await resolveSafeChildPath(req.workspaceRoot, actualDestPath); |
| 232 | } catch (err) { |
| 233 | const reason = err instanceof Error ? err.message : String(err); |
| 234 | return { |
| 235 | ok: false, |
| 236 | reason: reason.includes('outside root') ? 'destination outside workspace' : reason, |
| 237 | }; |
| 238 | } |
| 239 | await mkdir(path.dirname(dest), { recursive: true }); |
| 240 | await writeFile(dest, contents, 'utf8'); |
| 241 | return { |
| 242 | ok: true, |
| 243 | destPath: actualDestPath, |
no test coverage detected