MCPcopy
hub / github.com/prisma/prisma / downloadAndExtractTemplate

Function downloadAndExtractTemplate

packages/cli/src/bootstrap/template-scaffold.ts:53–100  ·  view source on GitHub ↗
(templateName: string, targetDir: string)

Source from the content-addressed store, hash-verified

51 * is acceptable and avoids a streaming tar parser dependency.
52 */
53export async function downloadAndExtractTemplate(templateName: string, targetDir: string): Promise<void> {
54 const response = await fetch(PRISMA_EXAMPLES_TARBALL_URL, {
55 headers: { Accept: 'application/vnd.github+json', 'User-Agent': 'prisma-cli' },
56 redirect: 'follow',
57 signal: AbortSignal.timeout(120_000),
58 })
59
60 if (!response.ok || !response.body) {
61 throw new Error(`Failed to download template: HTTP ${response.status}`)
62 }
63
64 const tarBuffer = await decompressGzip(response.body as import('node:stream/web').ReadableStream)
65 const templatePrefix = `orm/${templateName}/`
66 let filesExtracted = 0
67
68 let offset = 0
69 while (offset + 512 <= tarBuffer.length) {
70 const header = parseTarHeader(tarBuffer, offset)
71 if (!header) break
72
73 offset += 512
74 const paddedSize = Math.ceil(header.size / 512) * 512
75
76 if (header.type === '0' || header.type === '') {
77 const relPath = stripFirstComponent(header.name)
78 if (relPath?.startsWith(templatePrefix)) {
79 const destPath = path.resolve(targetDir, relPath.slice(templatePrefix.length))
80 if (!destPath.startsWith(path.resolve(targetDir) + path.sep)) continue
81 fs.mkdirSync(path.dirname(destPath), { recursive: true })
82 fs.writeFileSync(destPath, tarBuffer.subarray(offset, offset + header.size))
83 filesExtracted++
84 }
85 }
86
87 offset += paddedSize
88 }
89
90 if (filesExtracted === 0) {
91 throw new Error(`Template "${templateName}" not found in prisma-examples repository`)
92 }
93
94 const packageJsonPath = path.join(targetDir, 'package.json')
95 if (!fs.existsSync(packageJsonPath)) {
96 throw new Error(
97 `Template "${templateName}" extracted ${filesExtracted} file(s) but is missing package.json — the download may be corrupted`,
98 )
99 }
100}
101
102async function decompressGzip(body: import('node:stream/web').ReadableStream): Promise<Buffer> {
103 const gunzip = createGunzip()

Callers 1

scaffoldTemplateMethod · 0.90

Calls 6

decompressGzipFunction · 0.85
parseTarHeaderFunction · 0.85
stripFirstComponentFunction · 0.85
subarrayMethod · 0.80
fetchFunction · 0.50
sliceMethod · 0.45

Tested by

no test coverage detected