Skip to content

Commit

Permalink
💡 add cli
Browse files Browse the repository at this point in the history
  • Loading branch information
fahimahammed committed Jun 24, 2024
1 parent 8adf777 commit 2afaec4
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 105 deletions.
106 changes: 106 additions & 0 deletions src/documentationGenerator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { promises as fs } from 'fs';
import path from 'path';

const PRISMA_SCHEMA_PATH = path.join(process.cwd(), 'prisma', 'schema.prisma');
const OUTPUT_DOC_PATH = path.join(process.cwd(), 'prisma-docs.md');

interface Field {
name: string;
type: string;
isRequired: boolean;
isList: boolean;
isUnique: boolean;
enumValues?: string[]; // New property to hold enum values
}

interface Model {
name: string;
fields: Field[];
}

interface EnumType {
name: string;
values: string[];
}

const parseSchema = async (): Promise<string> => {
const schema = await fs.readFile(PRISMA_SCHEMA_PATH, 'utf-8');
const modelRegex = /model (\w+) \{([^}]+)\}/g;
const fieldRegex = /(\w+)\s+(\w+)(\[\])?(!)?(\s*@unique)?/g;
const enumRegex = /enum (\w+) \{([^}]+)\}/g;

const models: Model[] = [];
const enums: EnumType[] = [];

let match: RegExpExecArray | null;
while ((match = modelRegex.exec(schema)) !== null) {
const modelName = match[1];
const fieldsBlock = match[2];

const fields: Field[] = [];
let fieldMatch: RegExpExecArray | null;
while ((fieldMatch = fieldRegex.exec(fieldsBlock)) !== null) {
const [_, name, type, isList, isRequired, isUnique] = fieldMatch;
fields.push({
name,
type,
isRequired: !type.endsWith('?'),
isList: !!isList,
isUnique: !!isUnique,
});
}

models.push({ name: modelName, fields });
}

// Parse enums
while ((match = enumRegex.exec(schema)) !== null) {
const enumName = match[1];
const valuesBlock = match[2].trim();
const enumValues = valuesBlock.split('\n').map(value => value.trim().replace(',', ''));
enums.push({ name: enumName, values: enumValues });
}

return generateMarkdown(models, enums);
};

const generateMarkdown = (models: Model[], enums: EnumType[]): string => {
let markdown = '# Prisma Schema Documentation\n\n';

// Generate documentation for models
for (const model of models) {
markdown += `## ${model.name}\n\n`;
markdown += '| Field | Type | List | Required | Unique |\n';
markdown += '|-------|------|------|----------|--------|\n';
for (const field of model.fields) {
if (field.enumValues) {
markdown += `| ${field.name} | ${field.type} | ${field.isList ? 'Yes' : 'No'} | ${field.isRequired ? 'Yes' : 'No'} | ${field.isUnique ? 'Yes' : 'No'} |\n`;
markdown += `| | **Possible Values:** ${field.enumValues.join(', ')} |\n`;
} else {
markdown += `| ${field.name} | ${field.type} | ${field.isList ? 'Yes' : 'No'} | ${field.isRequired ? 'Yes' : 'No'} | ${field.isUnique ? 'Yes' : 'No'} |\n`;
}
}
markdown += '\n';
}

// Generate documentation for enums
markdown += '## Enums\n\n';
for (const enumType of enums) {
markdown += `### ${enumType.name}\n\n`;
markdown += '---\n';
markdown += `${enumType.values.join(', ')}\n`;
markdown += '\n';
}

return markdown;
};

export const generateDocumentation = async () => {
try {
const documentation = await parseSchema();
await fs.writeFile(OUTPUT_DOC_PATH, documentation);
console.log(`Documentation generated at ${OUTPUT_DOC_PATH}`);
} catch (error) {
console.error('Error generating documentation:', error);
}
};
109 changes: 4 additions & 105 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,108 +1,7 @@
import { promises as fs } from 'fs';
import path from 'path';
import { generateDocumentation } from './documentationGenerator';

const PRISMA_SCHEMA_PATH = path.join(process.cwd(), 'prisma', 'schema.prisma');
const OUTPUT_DOC_PATH = path.join(process.cwd(), 'prisma-docs.md');

interface Field {
name: string;
type: string;
isRequired: boolean;
isList: boolean;
isUnique: boolean;
enumValues?: string[]; // New property to hold enum values
}

interface Model {
name: string;
fields: Field[];
}

interface EnumType {
name: string;
values: string[];
function main() {
generateDocumentation();
}

const parseSchema = async (): Promise<string> => {
const schema = await fs.readFile(PRISMA_SCHEMA_PATH, 'utf-8');
const modelRegex = /model (\w+) \{([^}]+)\}/g;
const fieldRegex = /(\w+)\s+(\w+)(\[\])?(!)?(\s*@unique)?/g;
const enumRegex = /enum (\w+) \{([^}]+)\}/g;

const models: Model[] = [];
const enums: EnumType[] = [];

let match: RegExpExecArray | null;
while ((match = modelRegex.exec(schema)) !== null) {
const modelName = match[1];
const fieldsBlock = match[2];

const fields: Field[] = [];
let fieldMatch: RegExpExecArray | null;
while ((fieldMatch = fieldRegex.exec(fieldsBlock)) !== null) {
const [_, name, type, isList, isRequired, isUnique] = fieldMatch;
fields.push({
name,
type,
isRequired: !type.endsWith('?'),
isList: !!isList,
isUnique: !!isUnique,
});
}

models.push({ name: modelName, fields });
}

// Parse enums
while ((match = enumRegex.exec(schema)) !== null) {
const enumName = match[1];
const valuesBlock = match[2].trim();
const enumValues = valuesBlock.split('\n').map(value => value.trim().replace(',', ''));
enums.push({ name: enumName, values: enumValues });
}

return generateMarkdown(models, enums);
};

const generateMarkdown = (models: Model[], enums: EnumType[]): string => {
let markdown = '# Prisma Schema Documentation\n\n';

// Generate documentation for models
for (const model of models) {
markdown += `## ${model.name}\n\n`;
markdown += '| Field | Type | List | Required | Unique |\n';
markdown += '|-------|------|------|----------|--------|\n';
for (const field of model.fields) {
if (field.enumValues) {
markdown += `| ${field.name} | ${field.type} | ${field.isList ? 'Yes' : 'No'} | ${field.isRequired ? 'Yes' : 'No'} | ${field.isUnique ? 'Yes' : 'No'} |\n`;
markdown += `| | **Possible Values:** ${field.enumValues.join(', ')} |\n`;
} else {
markdown += `| ${field.name} | ${field.type} | ${field.isList ? 'Yes' : 'No'} | ${field.isRequired ? 'Yes' : 'No'} | ${field.isUnique ? 'Yes' : 'No'} |\n`;
}
}
markdown += '\n';
}

// Generate documentation for enums
markdown += '## Enums\n\n';
for (const enumType of enums) {
markdown += `### ${enumType.name}\n\n`;
markdown += '---\n';
markdown += `${enumType.values.join(', ')}\n`;
markdown += '\n';
}

return markdown;
};

const generateDocumentation = async () => {
try {
const documentation = await parseSchema();
await fs.writeFile(OUTPUT_DOC_PATH, documentation);
console.log(`Documentation generated at ${OUTPUT_DOC_PATH}`);
} catch (error) {
console.error('Error generating documentation:', error);
}
};

generateDocumentation();
main();

0 comments on commit 2afaec4

Please sign in to comment.