Comprehensive internal utility library for Prisma's CLI operations, schema management, generator handling, and engine interactions
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
The syntax highlighting domain provides code syntax highlighting capabilities for Prisma schemas, SQL, and TypeScript/JavaScript code, enabling rich console output and improved developer experience.
highlightDatamodel(str)Applies syntax highlighting to Prisma datamodel (schema) strings with color codes for different language elements.
function highlightDatamodel(str: string): anyParameters:
str: string - Prisma datamodel string to highlightReturns: any - String with ANSI color codes for syntax highlighting
Highlighted Elements:
model, enum, type, generator, datasourceString, Int, Boolean, DateTime, Json, etc.@id, @unique, @default, @@map, etc.@relation// and /* */ commentsExample:
import { highlightDatamodel } from '@prisma/internals'
const schema = `
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
createdAt DateTime @default(now())
@@map("users")
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
authorId Int
author User @relation(fields: [authorId], references: [id])
}
`
const highlighted = highlightDatamodel(schema)
console.log(highlighted)
// Output will include color codes:
// - Blue for keywords (model, String, Int, etc.)
// - Green for attributes (@id, @unique, etc.)
// - Yellow for strings
// - Gray for commentshighlightSql(str)Applies syntax highlighting to SQL query strings with appropriate color coding for SQL elements.
function highlightSql(str: string): anyParameters:
str: string - SQL string to highlightReturns: any - String with ANSI color codes for SQL syntax highlighting
Highlighted Elements:
SELECT, FROM, WHERE, JOIN, INSERT, UPDATE, DELETECOUNT, SUM, AVG, MAX, MIN, etc.=, <>, >, <, AND, OR, NOT-- and /* */ commentsExample:
import { highlightSql } from '@prisma/internals'
const sqlQuery = `
SELECT
u.id,
u.email,
u.name,
COUNT(p.id) as post_count
FROM users u
LEFT JOIN posts p ON u.id = p.author_id
WHERE u.created_at > '2024-01-01'
AND u.email LIKE '%@example.com'
GROUP BY u.id, u.email, u.name
ORDER BY post_count DESC
LIMIT 10;
`
const highlighted = highlightSql(sqlQuery)
console.log(highlighted)
// Output will include color codes:
// - Blue for SQL keywords (SELECT, FROM, WHERE, etc.)
// - Green for functions (COUNT, etc.)
// - Yellow for string literals
// - Cyan for table/column identifiershighlightTS(str)Applies syntax highlighting to TypeScript/JavaScript code strings with color coding for language constructs.
function highlightTS(str: string): anyParameters:
str: string - TypeScript/JavaScript string to highlightReturns: any - String with ANSI color codes for TypeScript/JavaScript syntax highlighting
Highlighted Elements:
function, const, let, var, if, else, for, while, class, interface, typestring, number, boolean, object, any, void, undefined=, ===, !==, =>, &&, ||, !// and /* */ commentsconsole, Promise, Array, etc.Example:
import { highlightTS } from '@prisma/internals'
const code = `
interface User {
id: number;
email: string;
name?: string;
posts: Post[];
}
async function createUser(data: Omit<User, 'id'>): Promise<User> {
const user = await prisma.user.create({
data: {
email: data.email,
name: data.name || 'Anonymous'
},
include: {
posts: true
}
});
console.log(\`Created user: \${user.email}\`);
return user;
}
const newUser = await createUser({
email: 'john@example.com',
name: 'John Doe',
posts: []
});
`
const highlighted = highlightTS(code)
console.log(highlighted)
// Output will include color codes:
// - Purple for keywords (interface, async, function, etc.)
// - Blue for types (number, string, Promise, etc.)
// - Green for strings and template literals
// - Yellow for function names
// - Cyan for object propertiesimport {
highlightDatamodel,
highlightSql,
highlightTS
} from '@prisma/internals'
interface CodeBlock {
language: 'prisma' | 'sql' | 'typescript' | 'javascript'
code: string
title?: string
description?: string
}
class DocumentationGenerator {
/**
* Generate highlighted code block for documentation
*/
generateCodeBlock(block: CodeBlock): string {
const { language, code, title, description } = block
let highlighted: string
// Apply appropriate highlighting based on language
switch (language) {
case 'prisma':
highlighted = highlightDatamodel(code)
break
case 'sql':
highlighted = highlightSql(code)
break
case 'typescript':
case 'javascript':
highlighted = highlightTS(code)
break
default:
highlighted = code // No highlighting for unknown languages
}
// Build formatted output
let output = ''
if (title) {
output += `\n📄 ${title}\n`
output += '='.repeat(title.length + 3) + '\n'
}
if (description) {
output += `${description}\n\n`
}
output += `Language: ${language.toUpperCase()}\n`
output += '-'.repeat(40) + '\n'
output += highlighted
output += '\n' + '-'.repeat(40) + '\n'
return output
}
/**
* Generate documentation for multiple code blocks
*/
generateDocumentation(blocks: CodeBlock[]): string {
return blocks
.map(block => this.generateCodeBlock(block))
.join('\n\n')
}
}
// Usage example
const docGen = new DocumentationGenerator()
const codeBlocks: CodeBlock[] = [
{
language: 'prisma',
title: 'User Model Definition',
description: 'Defines the User model with relations to posts',
code: `
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
profile Profile?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("users")
}
`.trim()
},
{
language: 'sql',
title: 'User Analytics Query',
description: 'Retrieves user statistics with post counts',
code: `
SELECT
u.id,
u.email,
u.name,
COUNT(p.id) as total_posts,
MAX(p.created_at) as last_post_date
FROM users u
LEFT JOIN posts p ON u.id = p.author_id
GROUP BY u.id, u.email, u.name
HAVING COUNT(p.id) > 0
ORDER BY total_posts DESC;
`.trim()
},
{
language: 'typescript',
title: 'User Service Implementation',
description: 'TypeScript service for user operations',
code: `
class UserService {
constructor(private prisma: PrismaClient) {}
async createUser(data: CreateUserData): Promise<User> {
const user = await this.prisma.user.create({
data: {
email: data.email,
name: data.name,
profile: data.profile ? {
create: data.profile
} : undefined
},
include: {
profile: true,
posts: true
}
});
return user;
}
async getUserStats(userId: number): Promise<UserStats> {
const user = await this.prisma.user.findUnique({
where: { id: userId },
include: {
_count: {
select: { posts: true }
}
}
});
if (!user) {
throw new Error('User not found');
}
return {
id: user.id,
email: user.email,
postCount: user._count.posts
};
}
}
`.trim()
}
]
const documentation = docGen.generateDocumentation(codeBlocks)
console.log(documentation)import {
highlightDatamodel,
highlightSql,
highlightTS
} from '@prisma/internals'
interface ViewerOptions {
showLineNumbers?: boolean
wrapLongLines?: boolean
colorScheme?: 'dark' | 'light'
}
class InteractiveCodeViewer {
private options: ViewerOptions
constructor(options: ViewerOptions = {}) {
this.options = {
showLineNumbers: true,
wrapLongLines: true,
colorScheme: 'dark',
...options
}
}
/**
* Display code with syntax highlighting and optional line numbers
*/
displayCode(
code: string,
language: 'prisma' | 'sql' | 'typescript',
title?: string
): void {
// Apply syntax highlighting
let highlighted: string
switch (language) {
case 'prisma':
highlighted = highlightDatamodel(code)
break
case 'sql':
highlighted = highlightSql(code)
break
case 'typescript':
highlighted = highlightTS(code)
break
}
// Split into lines for processing
const lines = highlighted.split('\n')
// Display header
if (title) {
console.log(`\n🔍 ${title}`)
console.log('─'.repeat(process.stdout.columns || 80))
}
// Display code with optional line numbers
lines.forEach((line, index) => {
let output = ''
if (this.options.showLineNumbers) {
const lineNum = (index + 1).toString().padStart(3, ' ')
output += `${lineNum} │ `
}
output += line
// Handle long lines
if (this.options.wrapLongLines && output.length > (process.stdout.columns || 80)) {
// Simple wrapping - could be enhanced
console.log(output.substring(0, process.stdout.columns || 80))
console.log(' │ ' + output.substring(process.stdout.columns || 80))
} else {
console.log(output)
}
})
console.log('─'.repeat(process.stdout.columns || 80))
console.log(`Language: ${language.toUpperCase()} | Lines: ${lines.length}`)
}
/**
* Compare two code blocks side by side
*/
compareCode(
leftCode: string,
rightCode: string,
leftLanguage: 'prisma' | 'sql' | 'typescript',
rightLanguage: 'prisma' | 'sql' | 'typescript',
leftTitle = 'Before',
rightTitle = 'After'
): void {
const leftHighlighted = this.highlightByLanguage(leftCode, leftLanguage)
const rightHighlighted = this.highlightByLanguage(rightCode, rightLanguage)
const leftLines = leftHighlighted.split('\n')
const rightLines = rightHighlighted.split('\n')
const maxLines = Math.max(leftLines.length, rightLines.length)
const halfWidth = Math.floor((process.stdout.columns || 80) / 2) - 2
console.log(`\n${leftTitle.padEnd(halfWidth)} │ ${rightTitle}`)
console.log('─'.repeat(halfWidth) + '┼' + '─'.repeat(halfWidth))
for (let i = 0; i < maxLines; i++) {
const leftLine = (leftLines[i] || '').substring(0, halfWidth).padEnd(halfWidth)
const rightLine = (rightLines[i] || '').substring(0, halfWidth)
console.log(`${leftLine} │ ${rightLine}`)
}
console.log('─'.repeat(halfWidth) + '┴' + '─'.repeat(halfWidth))
}
private highlightByLanguage(
code: string,
language: 'prisma' | 'sql' | 'typescript'
): string {
switch (language) {
case 'prisma':
return highlightDatamodel(code)
case 'sql':
return highlightSql(code)
case 'typescript':
return highlightTS(code)
default:
return code
}
}
}
// Usage
const viewer = new InteractiveCodeViewer({
showLineNumbers: true,
wrapLongLines: true,
colorScheme: 'dark'
})
// Display Prisma schema
viewer.displayCode(`
model User {
id Int @id @default(autoincrement())
email String @unique
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
authorId Int
author User @relation(fields: [authorId], references: [id])
}
`, 'prisma', 'Database Schema')
// Compare SQL queries
viewer.compareCode(
`SELECT * FROM users WHERE active = true`,
`SELECT id, email, name FROM users WHERE active = true AND verified = true`,
'sql',
'sql',
'Original Query',
'Optimized Query'
)import {
highlightDatamodel,
highlightSql,
highlightTS
} from '@prisma/internals'
interface CodeIssue {
line: number
column: number
severity: 'error' | 'warning' | 'info'
message: string
rule?: string
}
interface AnalysisResult {
code: string
language: 'prisma' | 'sql' | 'typescript'
issues: CodeIssue[]
score: number
}
class CodeQualityReporter {
/**
* Generate quality report with highlighted code and issues
*/
generateReport(result: AnalysisResult): void {
const { code, language, issues, score } = result
console.log('\n📊 Code Quality Report')
console.log('═'.repeat(50))
// Overall score
const scoreColor = score >= 80 ? '🟢' : score >= 60 ? '🟡' : '🔴'
console.log(`${scoreColor} Quality Score: ${score}/100`)
console.log(`📝 Language: ${language.toUpperCase()}`)
console.log(`⚠️ Issues Found: ${issues.length}`)
console.log()
// Issue summary
const errors = issues.filter(i => i.severity === 'error').length
const warnings = issues.filter(i => i.severity === 'warning').length
const infos = issues.filter(i => i.severity === 'info').length
if (issues.length > 0) {
console.log('📋 Issue Summary:')
if (errors > 0) console.log(` 🔴 Errors: ${errors}`)
if (warnings > 0) console.log(` 🟡 Warnings: ${warnings}`)
if (infos > 0) console.log(` 🔵 Info: ${infos}`)
console.log()
}
// Highlighted code with issue markers
console.log('📄 Code with Issues:')
console.log('─'.repeat(50))
let highlighted: string
switch (language) {
case 'prisma':
highlighted = highlightDatamodel(code)
break
case 'sql':
highlighted = highlightSql(code)
break
case 'typescript':
highlighted = highlightTS(code)
break
}
const lines = highlighted.split('\n')
lines.forEach((line, index) => {
const lineNumber = index + 1
const lineIssues = issues.filter(issue => issue.line === lineNumber)
// Display line with number
const lineNumStr = lineNumber.toString().padStart(3, ' ')
let prefix = ' '
if (lineIssues.length > 0) {
const maxSeverity = lineIssues.reduce((max, issue) => {
if (issue.severity === 'error') return 'error'
if (max === 'error') return max
if (issue.severity === 'warning') return 'warning'
return issue.severity
}, 'info' as const)
switch (maxSeverity) {
case 'error':
prefix = '🔴 '
break
case 'warning':
prefix = '🟡 '
break
case 'info':
prefix = '🔵 '
break
}
}
console.log(`${prefix}${lineNumStr} │ ${line}`)
// Display issues for this line
lineIssues.forEach(issue => {
const indent = ' '.repeat(7 + issue.column)
const marker = '^'.repeat(Math.min(issue.message.length, 20))
console.log(`${indent}${marker}`)
const severityIcon = {
error: '🔴',
warning: '🟡',
info: '🔵'
}[issue.severity]
console.log(`${indent}${severityIcon} ${issue.message}`)
if (issue.rule) {
console.log(`${indent} Rule: ${issue.rule}`)
}
})
})
console.log('─'.repeat(50))
// Recommendations
if (issues.length > 0) {
console.log('\n💡 Recommendations:')
const uniqueRules = [...new Set(issues.map(i => i.rule).filter(Boolean))]
uniqueRules.forEach(rule => {
console.log(` • Review rule: ${rule}`)
})
if (errors > 0) {
console.log(' • Fix all errors before deployment')
}
if (warnings > 5) {
console.log(' • Consider addressing warnings to improve code quality')
}
} else {
console.log('\n✅ No issues found - great job!')
}
}
}
// Usage
const reporter = new CodeQualityReporter()
const analysisResult: AnalysisResult = {
code: `
model User {
id Int @id @default(autoincrement())
email String @unique
password String // Should be hashed
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
authorId Int
author User @relation(fields: [authorId], references: [id])
}
`.trim(),
language: 'prisma',
issues: [
{
line: 4,
column: 12,
severity: 'warning',
message: 'Password field should include @db.Text for longer hashes',
rule: 'password-field-type'
},
{
line: 11,
column: 3,
severity: 'info',
message: 'Consider adding cascade delete behavior',
rule: 'relation-delete-behavior'
}
],
score: 85
}
reporter.generateReport(analysisResult)Install with Tessl CLI
npx tessl i tessl/npm-prisma--internals