Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions packages/graphql/src/type-maps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { UsageFlags } from "@typespec/compiler";

/**
* TypeSpec context for type mapping
* @template T - The TypeSpec type
*/
export interface TSPContext<T = any> {
Comment thread
FionaBronwen marked this conversation as resolved.
Outdated
type: T; // The TypeSpec type
usageFlag: UsageFlags; // How the type is being used (input, output, etc.)
name?: string; // Optional name override
Comment thread
FionaBronwen marked this conversation as resolved.
Outdated
metadata?: Record<string, any>; // Optional additional metadata
Comment thread
FionaBronwen marked this conversation as resolved.
Outdated
}

/**
* Base TypeMap for all GraphQL type mappings
* @template T - The TypeSpec type
* @template G - The GraphQL type
*/
export abstract class TypeMap<T, G> {
Comment thread
FionaBronwen marked this conversation as resolved.
Outdated
// Map of materialized GraphQL types
protected materializedMap = new Map<string, G>();

// Map of registration contexts
protected registrationMap = new Map<string, TSPContext<T>>();
Comment thread
FionaBronwen marked this conversation as resolved.
Outdated

/**
* Register a TypeSpec type with context for later materialization
* @param context - The TypeSpec context
* @returns The name used for registration
*/
register(context: TSPContext<T>): string {
const name = this.getNameFromContext(context);
this.registrationMap.set(name, context);
Comment thread
FionaBronwen marked this conversation as resolved.
return name;
}

/**
* Get the materialized GraphQL type
* @param name - The type name
* @returns The materialized GraphQL type or undefined
*/
get(name: string): G | undefined {
// Return already materialized type if available
if (this.materializedMap.has(name)) {
return this.materializedMap.get(name);
}

// Attempt to materialize if registered
const context = this.registrationMap.get(name);
if (context) {
const materializedType = this.materialize(context);
if (materializedType) {
Comment thread
FionaBronwen marked this conversation as resolved.
Outdated
this.materializedMap.set(name, materializedType);
return materializedType;
}
}

return undefined;
}

/**
* Check if a type is registered
*/
isRegistered(name: string): boolean {
return this.registrationMap.has(name);
}

/**
* Get all materialized types
*/
getAllMaterialized(): G[] {
return Array.from(this.materializedMap.values());
}
Comment thread
FionaBronwen marked this conversation as resolved.
Outdated

/**
* Reset the type map
*/
reset(): void {
this.materializedMap.clear();
this.registrationMap.clear();
}

/**
* Get a name from a context
*/
protected abstract getNameFromContext(context: TSPContext<T>): string;
Comment thread
FionaBronwen marked this conversation as resolved.
Outdated

/**
* Materialize a type from a context
*/
protected abstract materialize(context: TSPContext<T>): G | undefined;
Comment thread
FionaBronwen marked this conversation as resolved.
Outdated
}