Merged in chore/delete-unused-files (pull request #3346)

chore: Delete unused files

* Delete unused files

Ignore design-system for now


Approved-by: Joakim Jäderberg
This commit is contained in:
Anton Gunnarsson
2025-12-12 13:56:51 +00:00
parent c14b804c03
commit c153e0db50
42 changed files with 0 additions and 1679 deletions

View File

@@ -1,150 +0,0 @@
# GraphQL to TypeScript Converter
This script converts GraphQL files (`.graphql`) to TypeScript files (`.graphql.ts`) that use the `gql` template literal from `graphql-tag`.
## Features
- Converts individual fragments and queries into separate TypeScript exports
- Handles GraphQL imports (`#import`) and converts them to TypeScript imports
- Preserves fragment references and generates proper import statements
- Groups multiple imports from the same file
- Supports fragments, queries, mutations, and subscriptions
- Handles files with multiple operations
## Usage
### Basic Conversion
Convert all GraphQL files in the project:
```bash
yarn graphql:convert
```
Convert files matching a specific pattern:
```bash
yarn graphql:convert "packages/trpc/**/*.graphql"
```
Convert a single file:
```bash
yarn graphql:convert "path/to/file.graphql"
```
### Options
- `--dry-run`: Preview what files would be converted without actually converting them
- `--delete-originals`: Delete original `.graphql` files after successful conversion
- `--help`, `-h`: Show help message
### Examples
Preview conversion:
```bash
yarn graphql:convert --dry-run
```
Convert and delete originals:
```bash
yarn graphql:convert --delete-originals
```
Convert specific directory:
```bash
yarn graphql:convert "packages/trpc/lib/graphql/Fragments/**/*.graphql"
```
## Input Format
### GraphQL Fragment
```graphql
fragment Contact on ContactBlock {
sections {
__typename
}
}
```
### GraphQL Query with Imports
```graphql
#import "../Fragments/System.graphql"
#import "../Fragments/Metadata.graphql"
query GetData($locale: String!) {
data(locale: $locale) {
...System
...Metadata
}
}
```
## Output Format
### TypeScript Fragment
```typescript
import { gql } from "graphql-tag";
export const Contact = gql`
fragment Contact on ContactBlock {
sections {
__typename
}
}
`;
```
### TypeScript Query with Imports
```typescript
import { gql } from "graphql-tag";
import { System } from "../Fragments/System.graphql";
import { Metadata } from "../Fragments/Metadata.graphql";
export const GetData = gql`
query GetData($locale: String!) {
data(locale: $locale) {
...System
...Metadata
}
}
${System}
${Metadata}
`;
```
## How It Works
1. **Parse GraphQL Files**: Reads `.graphql` files and extracts imports and operations
2. **Handle Imports**: Converts `#import` statements to TypeScript imports by:
- Reading the imported file to determine export names
- Converting paths from `.graphql` to `.graphql.ts`
- Grouping multiple imports from the same file
3. **Extract Operations**: Identifies fragments, queries, mutations, and subscriptions
4. **Generate TypeScript**: Creates TypeScript files with:
- `gql` template literals
- Proper import statements
- Named exports for each operation
## Dependencies
- `glob`: For file pattern matching
- `tsx`: For TypeScript execution
- `@types/node`: For Node.js types
- `graphql-tag`: For the `gql` template literal (runtime dependency)
## Notes
- The script preserves the original file structure and naming
- Fragment references (`...FragmentName`) are preserved in the GraphQL content
- Multiple operations in a single file are split into separate exports
- Import conflicts are avoided by using the exact export names from referenced files
- Generated files maintain the same directory structure with `.graphql.ts` extension

View File

@@ -1,373 +0,0 @@
#!/usr/bin/env tsx
import * as fs from "fs";
import * as path from "path";
import { glob } from "glob";
interface ImportInfo {
fragmentName: string;
importPath: string;
variableName: string;
}
interface GraphQLFile {
content: string;
imports: ImportInfo[];
operations: Array<{ name: string; content: string }>;
}
/**
* Extracts individual fragments/operations from GraphQL content
*/
function extractOperations(
content: string
): Array<{ name: string; content: string }> {
const operations: Array<{ name: string; content: string }> = [];
// Split content into lines for processing
const lines = content.split("\n");
let currentOperation: { name: string; content: string[] } | null = null;
let braceCount = 0;
for (const line of lines) {
const trimmedLine = line.trim();
// Check if this line starts a new operation
const fragmentMatch = trimmedLine.match(/^fragment\s+(\w+)\s+on/);
const queryMatch = trimmedLine.match(/^query\s+(\w+)\s*[({]/);
const mutationMatch = trimmedLine.match(/^mutation\s+(\w+)\s*[({]/);
const subscriptionMatch = trimmedLine.match(
/^subscription\s+(\w+)\s*[({]/
);
if (fragmentMatch || queryMatch || mutationMatch || subscriptionMatch) {
// Finish previous operation if exists
if (currentOperation && currentOperation.content.length > 0) {
operations.push({
name: currentOperation.name,
content: currentOperation.content.join("\n").trim(),
});
}
// Start new operation
const operationName = (fragmentMatch ||
queryMatch ||
mutationMatch ||
subscriptionMatch)![1];
currentOperation = {
name: operationName,
content: [line],
};
// Count braces in the current line
braceCount =
(line.match(/{/g) || []).length -
(line.match(/}/g) || []).length;
} else if (currentOperation) {
// Add line to current operation
currentOperation.content.push(line);
// Update brace count
braceCount +=
(line.match(/{/g) || []).length -
(line.match(/}/g) || []).length;
// If we've closed all braces, this operation is complete
if (braceCount === 0 && trimmedLine.includes("}")) {
operations.push({
name: currentOperation.name,
content: currentOperation.content.join("\n").trim(),
});
currentOperation = null;
}
}
}
// Handle case where file ends without closing brace
if (currentOperation && currentOperation.content.length > 0) {
operations.push({
name: currentOperation.name,
content: currentOperation.content.join("\n").trim(),
});
}
return operations;
}
/**
* Generates TypeScript content from parsed GraphQL
*/
function generateTypeScriptContent(parsedFile: GraphQLFile): string {
const { imports, operations } = parsedFile;
let output = 'import { gql } from "graphql-tag"\n';
// Add imports for fragments - group by import path to avoid duplicates
if (imports.length > 0) {
output += "\n";
const importsByPath = new Map<string, string[]>();
for (const imp of imports) {
if (!importsByPath.has(imp.importPath)) {
importsByPath.set(imp.importPath, []);
}
if (
!importsByPath.get(imp.importPath)!.includes(imp.variableName)
) {
importsByPath.get(imp.importPath)!.push(imp.variableName);
}
}
for (const [importPath, variableNames] of importsByPath) {
output += `import { ${variableNames.join(", ")} } from "${importPath}"\n`;
}
}
output += "\n";
// Generate exports for each operation
if (operations.length === 0) {
// If no operation names found, use a default export
const defaultName = "GraphQLDocument";
const fragmentSubstitutions =
imports.length > 0
? "\n" +
imports.map((imp) => `\${${imp.variableName}}`).join("\n")
: "";
output += `export const ${defaultName} = gql\`\n${parsedFile.content}${fragmentSubstitutions}\n\`\n`;
} else {
for (let i = 0; i < operations.length; i++) {
const operation = operations[i];
const fragmentSubstitutions =
imports.length > 0
? "\n" +
imports.map((imp) => `\${${imp.variableName}}`).join("\n")
: "";
output += `export const ${operation.name} = gql\`\n${operation.content}${fragmentSubstitutions}\n\`\n`;
if (i < operations.length - 1) {
output += "\n";
}
}
}
return output;
}
/**
* Converts a GraphQL import path to a TypeScript import path
*/
function convertImportPath(graphqlPath: string): string {
// Remove the .graphql extension and add .graphql
const withoutExt = graphqlPath.replace(/\.graphql$/, "");
return `${withoutExt}.graphql`;
}
/**
* Gets the export names from a GraphQL file by analyzing the fragments it contains
*/
function getExportNamesFromGraphQLFile(filePath: string): string[] {
try {
const content = fs.readFileSync(filePath, "utf-8");
const operations = extractOperations(content);
return operations.map((op) => op.name);
} catch {
// If file doesn't exist or can't be read, try to infer from path
console.warn(
`Warning: Could not read ${filePath}, inferring export name from path`
);
return [getVariableNameFromPath(filePath)];
}
}
/**
* Extracts the expected variable name from a file path
*/
function getVariableNameFromPath(filePath: string): string {
const basename = path.basename(filePath, ".graphql");
// Convert kebab-case or snake_case to PascalCase
return basename
.split(/[-_]/)
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join("");
}
/**
* Parses a GraphQL file and extracts imports and content
*/
function parseGraphQLFile(filePath: string): GraphQLFile {
const content = fs.readFileSync(filePath, "utf-8");
const lines = content.split("\n");
const imports: ImportInfo[] = [];
const contentLines: string[] = [];
for (const line of lines) {
const trimmedLine = line.trim();
if (trimmedLine.startsWith("#import")) {
// Extract import path from #import "path"
const match = trimmedLine.match(/#import\s+"([^"]+)"/);
if (match) {
const importPath = match[1];
const fullImportPath = path.resolve(
path.dirname(filePath),
importPath
);
const exportNames =
getExportNamesFromGraphQLFile(fullImportPath);
const tsImportPath = convertImportPath(importPath);
// Add all exports from the imported file
for (const exportName of exportNames) {
imports.push({
fragmentName: exportName,
importPath: tsImportPath,
variableName: exportName,
});
}
}
} else if (trimmedLine && !trimmedLine.startsWith("#")) {
contentLines.push(line);
}
}
const cleanContent = contentLines.join("\n").trim();
const operations = extractOperations(cleanContent);
return {
content: cleanContent,
imports,
operations,
};
}
/**
* Converts a single GraphQL file to TypeScript
*/
function convertFile(graphqlPath: string): void {
try {
console.log(`Converting: ${graphqlPath}`);
const parsed = parseGraphQLFile(graphqlPath);
const tsContent = generateTypeScriptContent(parsed);
const tsPath = graphqlPath.replace(/\.graphql$/, ".graphql.ts");
fs.writeFileSync(tsPath, tsContent, "utf-8");
console.log(`✓ Created: ${tsPath}`);
// Optionally remove the original .graphql file
// Uncomment the next line if you want to delete the original files
// fs.unlinkSync(graphqlPath)
} catch (error) {
console.error(`Error converting ${graphqlPath}:`, error);
}
}
/**
* Main function to convert all GraphQL files
*/
async function main() {
const args = process.argv.slice(2);
if (args.includes("--help") || args.includes("-h")) {
console.log(`
GraphQL to TypeScript Converter
Converts GraphQL files (.graphql) to TypeScript files (.graphql.ts) using gql template literals.
Usage: tsx convert-graphql-to-ts.ts [options] [pattern]
Options:
--help, -h Show this help message
--dry-run Show what files would be converted without converting them
--delete-originals Delete original .graphql files after conversion
Examples:
tsx convert-graphql-to-ts.ts # Convert all .graphql files
tsx convert-graphql-to-ts.ts "packages/trpc/**/*.graphql" # Convert specific pattern
tsx convert-graphql-to-ts.ts --dry-run # Preview conversion
tsx convert-graphql-to-ts.ts --delete-originals # Convert and delete originals
Features:
• Converts fragments, queries, mutations, and subscriptions
• Handles GraphQL imports (#import) and converts to TypeScript imports
• Preserves fragment references and generates proper import statements
• Groups multiple imports from the same file
• Splits multiple operations into separate exports
`);
return;
}
const dryRun = args.includes("--dry-run");
const deleteOriginals = args.includes("--delete-originals");
// Get the pattern from args or use default
const pattern = args.find((arg) => !arg.startsWith("--")) || "**/*.graphql";
console.log(`🔍 Searching for GraphQL files with pattern: ${pattern}`);
try {
const files = await glob(pattern, {
ignore: ["**/*.graphql.ts", "**/node_modules/**"],
});
if (files.length === 0) {
console.log("❌ No GraphQL files found.");
return;
}
console.log(`📁 Found ${files.length} GraphQL files`);
if (dryRun) {
console.log("\n📋 Files that would be converted:");
files.forEach((file, index) => {
console.log(
` ${index + 1}. ${file}${file.replace(/\.graphql$/, ".graphql.ts")}`
);
});
console.log("\n🔍 --dry-run mode: No files were converted.");
return;
}
console.log("\n🔄 Converting files...");
let successCount = 0;
let errorCount = 0;
for (let i = 0; i < files.length; i++) {
const file = files[i];
try {
console.log(
`📝 [${i + 1}/${files.length}] Converting: ${file}`
);
convertFile(file);
successCount++;
if (deleteOriginals) {
fs.unlinkSync(file);
console.log(`🗑️ Deleted: ${file}`);
}
} catch (error) {
console.error(`❌ Error converting ${file}:`, error);
errorCount++;
}
}
console.log(`\n✅ Conversion complete!`);
console.log(` 📈 Successfully converted: ${successCount} files`);
if (errorCount > 0) {
console.log(` ❌ Errors: ${errorCount} files`);
}
if (deleteOriginals && successCount > 0) {
console.log(` 🗑️ Deleted: ${successCount} original files`);
}
} catch (error) {
console.error("❌ Error:", error);
process.exit(1);
}
}
// Run the script
if (import.meta.url === `file://${process.argv[1]}`) {
main().catch(console.error);
}