Added context namespace into the codegen (#472)

* Added context namespace into the codegen
This commit is contained in:
vejrj 2024-11-04 18:20:28 +01:00 коммит произвёл GitHub
Родитель 586495129b
Коммит dd33b80a0c
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
7 изменённых файлов: 142 добавлений и 231 удалений

Просмотреть файл

@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "Added context namespace into the codegen",
"packageName": "@graphitation/cli",
"email": "77059398+vejrj@users.noreply.github.com",
"dependentChangeType": "none"
}

Просмотреть файл

@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "Added context namespace into the codegen",
"packageName": "@graphitation/ts-codegen",
"email": "77059398+vejrj@users.noreply.github.com",
"dependentChangeType": "none"
}

Просмотреть файл

@ -19,7 +19,8 @@ type GenerateInterfacesOptions = {
enumMigrationJsonFile?: string;
enumMigrationExceptionsJsonFile?: string;
generateOnlyEnums?: boolean;
contextMappingFile?: string;
contextNamespaceName?: string;
contextNamespacePath?: string;
scope?: string;
};
@ -49,11 +50,15 @@ export function supermassive(): Command {
"-ci, --context-import [contextImport]",
"from where to import context",
)
.option(
"-cm, --context-mapping-file [contextMappingFile]",
"context mapping file",
)
.option("-cn, --context-name [contextName]", "Context name")
.option(
"-cm, --context-namespace-name [contextNamespaceName]",
"context namespace name",
)
.option(
"-cm, --context-namespace-path [contextNamespacePath]",
"context namespace path",
)
.option("-ei, --enums-import [enumsImport]", "from where to import enums")
.option("-l, --legacy", "generate legacy types")
.option("--legacy-models", "do not use models for object types")
@ -128,26 +133,6 @@ async function generateInterfaces(
options.outputDir ? options.outputDir : "__generated__",
);
const { contextMappingFile } = options;
let contextMappingContent: Record<string, string> | null = null;
let fullContextMappingFilePath: string;
if (contextMappingFile) {
if (path.isAbsolute(contextMappingFile)) {
fullContextMappingFilePath = contextMappingFile;
} else {
fullContextMappingFilePath = path.join(
process.cwd(),
contextMappingFile,
);
}
if (fsSync.existsSync(fullContextMappingFilePath)) {
contextMappingContent = JSON.parse(
await fs.readFile(fullContextMappingFilePath, { encoding: "utf-8" }),
);
}
}
const result = generateTS(document, {
outputPath,
documentPath: fullPath,
@ -159,7 +144,8 @@ async function generateInterfaces(
useStringUnionsInsteadOfEnums: !!options.useStringUnionsInsteadOfEnums,
generateOnlyEnums: !!options.generateOnlyEnums,
modelScope: options.scope || null,
contextMappingContent: contextMappingContent,
contextNamespaceName: options.contextNamespaceName,
contextNamespacePath: options.contextNamespacePath,
});
await fs.mkdir(outputPath, { recursive: true });

Просмотреть файл

@ -45,11 +45,8 @@ describe(generateTS, () => {
}
`,
{
contextMappingContent: {
UserStateMachine: "user-state-machine",
PostStateMachine: "post-state-machine",
IdUserStateMachine: "id-user-state-machine",
},
contextNamespaceName: "ContextNamespace",
contextNamespacePath: "context-package",
},
);
expect(enums).toMatchInlineSnapshot(`undefined`);
@ -91,9 +88,7 @@ describe(generateTS, () => {
import type { PromiseOrValue } from "@graphitation/supermassive";
import type { ResolveInfo } from "@graphitation/supermassive";
import * as Models from "./models.interface";
import type { UserStateMachine } from "user-state-machine";
import type { IdUserStateMachine } from "id-user-state-machine";
import type { PostStateMachine } from "post-state-machine";
import type { ContextNamespace } from "context-package";
export declare namespace Post {
export interface Resolvers {
readonly id?: id;
@ -104,7 +99,7 @@ describe(generateTS, () => {
export interface Resolvers {
readonly id?: id;
}
export type id = (model: Models.Message, args: {}, context: unknown, info: ResolveInfo) => PromiseOrValue<string>;
export type id = (model: Models.Message, args: {}, context: ContextNamespace.MessageStateMachine, info: ResolveInfo) => PromiseOrValue<string>;
}
export declare namespace User {
export interface Resolvers {
@ -122,19 +117,19 @@ describe(generateTS, () => {
readonly avatar?: avatar;
readonly avatarRequired?: avatarRequired;
}
export type id = (model: Models.User, args: {}, context: IdUserStateMachine, info: ResolveInfo) => PromiseOrValue<string>;
export type name = (model: Models.User, args: {}, context: UserStateMachine, info: ResolveInfo) => PromiseOrValue<string | null | undefined>;
export type messagesWithAnswersNonRequired = (model: Models.User, args: {}, context: UserStateMachine, info: ResolveInfo) => PromiseOrValue<ReadonlyArray<ReadonlyArray<Models.Message | null | undefined> | null | undefined> | null | undefined>;
export type messagesWithAnswersRequired = (model: Models.User, args: {}, context: UserStateMachine, info: ResolveInfo) => PromiseOrValue<ReadonlyArray<ReadonlyArray<Models.Message | null | undefined> | null | undefined>>;
export type messagesWithAnswersAllRequired = (model: Models.User, args: {}, context: UserStateMachine, info: ResolveInfo) => PromiseOrValue<ReadonlyArray<ReadonlyArray<Models.Message>>>;
export type messagesNonRequired = (model: Models.User, args: {}, context: UserStateMachine, info: ResolveInfo) => PromiseOrValue<ReadonlyArray<Models.Message | null | undefined> | null | undefined>;
export type messagesWithArrayRequired = (model: Models.User, args: {}, context: UserStateMachine, info: ResolveInfo) => PromiseOrValue<ReadonlyArray<Models.Message | null | undefined>>;
export type messagesRequired = (model: Models.User, args: {}, context: UserStateMachine, info: ResolveInfo) => PromiseOrValue<ReadonlyArray<Models.Message>>;
export type messagesOnlyMessageRequired = (model: Models.User, args: {}, context: UserStateMachine, info: ResolveInfo) => PromiseOrValue<ReadonlyArray<Models.Message> | null | undefined>;
export type post = (model: Models.User, args: {}, context: PostStateMachine, info: ResolveInfo) => PromiseOrValue<Models.Post | null | undefined>;
export type postRequired = (model: Models.User, args: {}, context: UserStateMachine, info: ResolveInfo) => PromiseOrValue<Models.Post>;
export type avatar = (model: Models.User, args: {}, context: UserStateMachine, info: ResolveInfo) => PromiseOrValue<Avatar | null | undefined>;
export type avatarRequired = (model: Models.User, args: {}, context: UserStateMachine, info: ResolveInfo) => PromiseOrValue<Avatar>;
export type id = (model: Models.User, args: {}, context: ContextNamespace.IdUserStateMachine, info: ResolveInfo) => PromiseOrValue<string>;
export type name = (model: Models.User, args: {}, context: ContextNamespace.UserStateMachine, info: ResolveInfo) => PromiseOrValue<string | null | undefined>;
export type messagesWithAnswersNonRequired = (model: Models.User, args: {}, context: ContextNamespace.UserStateMachine, info: ResolveInfo) => PromiseOrValue<ReadonlyArray<ReadonlyArray<Models.Message | null | undefined> | null | undefined> | null | undefined>;
export type messagesWithAnswersRequired = (model: Models.User, args: {}, context: ContextNamespace.UserStateMachine, info: ResolveInfo) => PromiseOrValue<ReadonlyArray<ReadonlyArray<Models.Message | null | undefined> | null | undefined>>;
export type messagesWithAnswersAllRequired = (model: Models.User, args: {}, context: ContextNamespace.UserStateMachine, info: ResolveInfo) => PromiseOrValue<ReadonlyArray<ReadonlyArray<Models.Message>>>;
export type messagesNonRequired = (model: Models.User, args: {}, context: ContextNamespace.UserStateMachine, info: ResolveInfo) => PromiseOrValue<ReadonlyArray<Models.Message | null | undefined> | null | undefined>;
export type messagesWithArrayRequired = (model: Models.User, args: {}, context: ContextNamespace.UserStateMachine, info: ResolveInfo) => PromiseOrValue<ReadonlyArray<Models.Message | null | undefined>>;
export type messagesRequired = (model: Models.User, args: {}, context: ContextNamespace.UserStateMachine, info: ResolveInfo) => PromiseOrValue<ReadonlyArray<Models.Message>>;
export type messagesOnlyMessageRequired = (model: Models.User, args: {}, context: ContextNamespace.UserStateMachine, info: ResolveInfo) => PromiseOrValue<ReadonlyArray<Models.Message> | null | undefined>;
export type post = (model: Models.User, args: {}, context: ContextNamespace.PostStateMachine, info: ResolveInfo) => PromiseOrValue<Models.Post | null | undefined>;
export type postRequired = (model: Models.User, args: {}, context: ContextNamespace.UserStateMachine, info: ResolveInfo) => PromiseOrValue<Models.Post>;
export type avatar = (model: Models.User, args: {}, context: ContextNamespace.UserStateMachine, info: ResolveInfo) => PromiseOrValue<Avatar | null | undefined>;
export type avatarRequired = (model: Models.User, args: {}, context: ContextNamespace.UserStateMachine, info: ResolveInfo) => PromiseOrValue<Avatar>;
}
export declare namespace Query {
export interface Resolvers {
@ -145,12 +140,12 @@ describe(generateTS, () => {
readonly requiredPost?: requiredPost;
readonly optionalPost?: optionalPost;
}
export type requiredUsers = (model: unknown, args: {}, context: UserStateMachine, info: ResolveInfo) => PromiseOrValue<ReadonlyArray<Models.User>>;
export type optionalUsers = (model: unknown, args: {}, context: UserStateMachine, info: ResolveInfo) => PromiseOrValue<ReadonlyArray<Models.User | null | undefined> | null | undefined>;
export type optionalUser = (model: unknown, args: {}, context: UserStateMachine, info: ResolveInfo) => PromiseOrValue<Models.User | null | undefined>;
export type requiredUser = (model: unknown, args: {}, context: UserStateMachine, info: ResolveInfo) => PromiseOrValue<Models.User>;
export type requiredUsers = (model: unknown, args: {}, context: unknown, info: ResolveInfo) => PromiseOrValue<ReadonlyArray<Models.User>>;
export type optionalUsers = (model: unknown, args: {}, context: unknown, info: ResolveInfo) => PromiseOrValue<ReadonlyArray<Models.User | null | undefined> | null | undefined>;
export type optionalUser = (model: unknown, args: {}, context: unknown, info: ResolveInfo) => PromiseOrValue<Models.User | null | undefined>;
export type requiredUser = (model: unknown, args: {}, context: unknown, info: ResolveInfo) => PromiseOrValue<Models.User>;
export type requiredPost = (model: unknown, args: {}, context: unknown, info: ResolveInfo) => PromiseOrValue<Models.Post>;
export type optionalPost = (model: unknown, args: {}, context: unknown, info: ResolveInfo) => PromiseOrValue<Models.Post | null | undefined>;
export type optionalPost = (model: unknown, args: {}, context: ContextNamespace.OptionalPostStateMachine, info: ResolveInfo) => PromiseOrValue<Models.Post | null | undefined>;
}
"
`);
@ -310,11 +305,8 @@ describe(generateTS, () => {
}
`,
{
contextMappingContent: {
AdminStateMachine: "admin-state-machine",
PersonaStateMachine: "persona-state-machine",
NodeStateMachine: "node-state-machine",
},
contextNamespaceName: "ContextNamespace",
contextNamespacePath: "context-package",
},
);
expect(enums).toMatchInlineSnapshot(`undefined`);
@ -344,34 +336,32 @@ describe(generateTS, () => {
"import type { PromiseOrValue } from "@graphitation/supermassive";
import type { ResolveInfo } from "@graphitation/supermassive";
import * as Models from "./models.interface";
import type { NodeStateMachine } from "node-state-machine";
import type { PersonaStateMachine } from "persona-state-machine";
import type { AdminStateMachine } from "admin-state-machine";
import type { ContextNamespace } from "context-package";
export declare namespace Node {
export interface Resolvers {
readonly __resolveType?: __resolveType;
}
export type __resolveType = (parent: unknown, context: NodeStateMachine, info: ResolveInfo) => PromiseOrValue<string | null>;
export type __resolveType = (parent: unknown, context: ContextNamespace.NodeStateMachine, info: ResolveInfo) => PromiseOrValue<string | null>;
}
export declare namespace Persona {
export interface Resolvers {
readonly __resolveType?: __resolveType;
}
export type __resolveType = (parent: unknown, context: PersonaStateMachine, info: ResolveInfo) => PromiseOrValue<string | null>;
export type __resolveType = (parent: unknown, context: ContextNamespace.PersonaStateMachine, info: ResolveInfo) => PromiseOrValue<string | null>;
}
export declare namespace User {
export interface Resolvers {
readonly __resolveType?: __resolveType;
}
export type __resolveType = (parent: unknown, context: NodeStateMachine & PersonaStateMachine, info: ResolveInfo) => PromiseOrValue<string | null>;
export type __resolveType = (parent: unknown, context: ContextNamespace.NodeStateMachine & ContextNamespace.PersonaStateMachine, info: ResolveInfo) => PromiseOrValue<string | null>;
}
export declare namespace Admin {
export interface Resolvers {
readonly id?: id;
readonly rank?: rank;
}
export type id = (model: Models.Admin, args: {}, context: AdminStateMachine, info: ResolveInfo) => PromiseOrValue<string>;
export type rank = (model: Models.Admin, args: {}, context: AdminStateMachine, info: ResolveInfo) => PromiseOrValue<number>;
export type id = (model: Models.Admin, args: {}, context: ContextNamespace.AdminStateMachine, info: ResolveInfo) => PromiseOrValue<string>;
export type rank = (model: Models.Admin, args: {}, context: ContextNamespace.AdminStateMachine, info: ResolveInfo) => PromiseOrValue<number>;
}
export declare namespace Query {
export interface Resolvers {
@ -379,7 +369,7 @@ describe(generateTS, () => {
readonly admins?: admins;
}
export type users = (model: unknown, args: {}, context: unknown, info: ResolveInfo) => PromiseOrValue<ReadonlyArray<Models.User | null | undefined> | null | undefined>;
export type admins = (model: unknown, args: {}, context: AdminStateMachine, info: ResolveInfo) => PromiseOrValue<ReadonlyArray<Models.Admin | null | undefined> | null | undefined>;
export type admins = (model: unknown, args: {}, context: ContextNamespace.AdminStateMachine, info: ResolveInfo) => PromiseOrValue<ReadonlyArray<Models.Admin | null | undefined> | null | undefined>;
}
"
`);
@ -430,9 +420,8 @@ describe(generateTS, () => {
}
`,
{
contextMappingContent: {
NodeStateMachine: "node-state-machine",
},
contextNamespaceName: "ContextNamespace",
contextNamespacePath: "context-package",
},
);
expect(enums).toMatchInlineSnapshot(`undefined`);
@ -456,20 +445,20 @@ describe(generateTS, () => {
"import type { PromiseOrValue } from "@graphitation/supermassive";
import type { ResolveInfo } from "@graphitation/supermassive";
import * as Models from "./models.interface";
import type { NodeStateMachine } from "node-state-machine";
import type { ContextNamespace } from "context-package";
export declare namespace Node {
export interface Resolvers {
readonly __resolveType?: __resolveType;
}
export type __resolveType = (parent: unknown, context: NodeStateMachine, info: ResolveInfo) => PromiseOrValue<string | null>;
export type __resolveType = (parent: unknown, context: ContextNamespace.NodeStateMachine, info: ResolveInfo) => PromiseOrValue<string | null>;
}
export declare namespace User {
export interface Resolvers {
readonly id?: id;
readonly name?: name;
}
export type id = (model: Models.User, args: {}, context: NodeStateMachine, info: ResolveInfo) => PromiseOrValue<string>;
export type name = (model: Models.User, args: {}, context: NodeStateMachine, info: ResolveInfo) => PromiseOrValue<string>;
export type id = (model: Models.User, args: {}, context: ContextNamespace.NodeStateMachine, info: ResolveInfo) => PromiseOrValue<string>;
export type name = (model: Models.User, args: {}, context: ContextNamespace.NodeStateMachine, info: ResolveInfo) => PromiseOrValue<string>;
}
export declare namespace Query {
export interface Resolvers {
@ -569,11 +558,8 @@ describe(generateTS, () => {
}
`,
{
contextMappingContent: {
WhateverStateMachine: "whatever-state-machine",
AdminStateMachine: "admin-state-machine",
CustomStateMachine: "custom-state-machine",
},
contextNamespaceName: "ContextNamespace",
contextNamespacePath: "context-package",
},
);
expect(enums).toMatchInlineSnapshot(`undefined`);
@ -601,20 +587,18 @@ describe(generateTS, () => {
"import type { PromiseOrValue } from "@graphitation/supermassive";
import type { ResolveInfo } from "@graphitation/supermassive";
import * as Models from "./models.interface";
import type { CustomStateMachine } from "custom-state-machine";
import type { AdminStateMachine } from "admin-state-machine";
import type { WhateverStateMachine } from "whatever-state-machine";
import type { ContextNamespace } from "context-package";
export declare namespace Customer {
export interface Resolvers {
readonly id?: id;
}
export type id = (model: Models.Customer, args: {}, context: CustomStateMachine, info: ResolveInfo) => PromiseOrValue<string>;
export type id = (model: Models.Customer, args: {}, context: ContextNamespace.CustomStateMachine, info: ResolveInfo) => PromiseOrValue<string>;
}
export declare namespace Admin {
export interface Resolvers {
readonly id?: id;
}
export type id = (model: Models.Admin, args: {}, context: AdminStateMachine, info: ResolveInfo) => PromiseOrValue<string>;
export type id = (model: Models.Admin, args: {}, context: ContextNamespace.AdminStateMachine, info: ResolveInfo) => PromiseOrValue<string>;
}
export declare namespace Node {
export interface Resolvers {
@ -626,7 +610,7 @@ describe(generateTS, () => {
export interface Resolvers {
readonly __resolveType?: __resolveType;
}
export type __resolveType = (parent: Models.User | Models.Admin, context: AdminStateMachine, info: ResolveInfo) => PromiseOrValue<"User" | "Admin" | null>;
export type __resolveType = (parent: Models.User | Models.Admin, context: ContextNamespace.AdminStateMachine, info: ResolveInfo) => PromiseOrValue<"User" | "Admin" | null>;
}
export declare namespace Query {
export interface Resolvers {
@ -636,10 +620,10 @@ describe(generateTS, () => {
}
export type userById = (model: unknown, args: {
readonly id: string;
}, context: WhateverStateMachine, info: ResolveInfo) => PromiseOrValue<Models.whatever | null | undefined>;
}, context: ContextNamespace.WhateverStateMachine, info: ResolveInfo) => PromiseOrValue<Models.whatever | null | undefined>;
export type userByMail = (model: unknown, args: {
readonly mail?: string | null;
}, context: unknown, info: ResolveInfo) => PromiseOrValue<Models.whatever | null | undefined>;
}, context: ContextNamespace.DifferentWhateverStateMachine, info: ResolveInfo) => PromiseOrValue<Models.whatever | null | undefined>;
export type node = (model: unknown, args: {
readonly id: string;
}, context: unknown, info: ResolveInfo) => PromiseOrValue<Models.Node | null | undefined>;
@ -665,7 +649,8 @@ function runGenerateTest(
enumNamesToMigrate?: string[];
enumNamesToKeep?: string[];
modelScope?: string;
contextMappingContent?: Record<string, string> | null;
contextNamespaceName?: string;
contextNamespacePath?: string;
} = {},
): {
enums?: string;
@ -680,7 +665,8 @@ function runGenerateTest(
enumNamesToMigrate?: string[];
enumNamesToKeep?: string[];
modelScope?: string;
contextMappingContent?: Record<string, string> | null;
contextNamespaceName?: string;
contextNamespacePath?: string;
} {
const fullOptions: {
outputPath: string;
@ -693,7 +679,8 @@ function runGenerateTest(
useStringUnionsInsteadOfEnums?: boolean;
enumNamesToMigrate?: string[];
enumNamesToKeep?: string[];
contextMappingContent?: Record<string, string> | null;
contextNamespaceName?: string;
contextNamespacePath?: string;
} = {
outputPath: "__generated__",
documentPath: "./typedef.graphql",
@ -721,7 +708,8 @@ function runGenerateTest(
enums: enums && printer.printFile(enums),
inputs: inputs && printer.printFile(inputs),
models: printer.printFile(models),
contextMappingContent: options.contextMappingContent || null,
contextNamespaceName: options.contextNamespaceName,
contextNamespacePath: options.contextNamespacePath,
resolvers: printer.printFile(resolvers),
legacyTypes: legacyTypes && printer.printFile(legacyTypes),
legacyResolvers: legacyResolvers && printer.printFile(legacyResolvers),

Просмотреть файл

@ -23,7 +23,8 @@ export function generateTS(
generateOnlyEnums,
enumNamesToMigrate,
enumNamesToKeep,
contextMappingContent,
contextNamespaceName,
contextNamespacePath,
}: {
outputPath: string;
documentPath: string;
@ -37,11 +38,12 @@ export function generateTS(
generateOnlyEnums?: boolean;
enumNamesToMigrate?: string[];
enumNamesToKeep?: string[];
contextMappingContent?: Record<string, string> | null;
contextNamespaceName?: string;
contextNamespacePath?: string;
},
): {
files: ts.SourceFile[];
contextMappingOutput: Record<string, string> | null;
contextMappingOutput: any | null;
} {
try {
const context = extractContext(
@ -57,7 +59,8 @@ export function generateTS(
modelScope,
enumNamesToMigrate,
enumNamesToKeep,
contextMappingContent,
contextNamespaceName,
contextNamespacePath,
},
document,
outputPath,

Просмотреть файл

@ -51,7 +51,8 @@ export type TsCodegenContextOptions = {
};
legacyCompat: boolean;
legacyNoModelsForObjects: boolean;
contextMappingContent?: Record<string, string> | null;
contextNamespaceName?: string;
contextNamespacePath?: string;
useStringUnionsInsteadOfEnums: boolean;
enumNamesToMigrate: string[] | null;
enumNamesToKeep: string[] | null;
@ -101,7 +102,6 @@ export class TsCodegenContext {
private typeContextMap: any;
private allRootTypeNames: Set<string>;
private typeNameToType: Map<string, Type>;
private contextMappingContent: Record<string, string> | null;
private usedEntitiesInModels: Set<string>;
private usedEntitiesInResolvers: Set<string>;
private usedEntitiesInInputs: Set<string>;
@ -113,6 +113,7 @@ export class TsCodegenContext {
private typeNameToModels: Map<string, DefinitionModel>;
private legacyInterfaces: Set<string>;
context?: { name: string; from: string };
contextNamespace?: { name: string; from: string };
hasUsedModelInInputs: boolean;
hasUsedEnumsInModels: boolean;
hasEnums: boolean;
@ -135,7 +136,13 @@ export class TsCodegenContext {
this.hasInputs = false;
this.hasEnums = Boolean(options.enumsImport);
this.hasUsedEnumsInModels = false;
this.contextMappingContent = options.contextMappingContent || null;
if (options.contextNamespaceName && options.contextNamespacePath) {
this.contextNamespace = {
name: options.contextNamespaceName,
from: options.contextNamespacePath,
};
}
if (options.context.from && options.context.name) {
this.context = {
name: options.context.name,
@ -174,29 +181,38 @@ export class TsCodegenContext {
return null;
}
public getContextMappingContent(): Record<string, string> | null {
return this.contextMappingContent;
public getContextNamespace(): { name: string; from: string } | null {
return this.contextNamespace || null;
}
public getContextTypeNode(typeNames?: string[] | null) {
if (!typeNames || !typeNames.length) {
const contextNamespace = this.contextNamespace;
if (!typeNames || !typeNames.length || !contextNamespace) {
return this.getContextType().toTypeReference();
} else if (
(typeNames.length === 1 && this.context) ||
typeNames.length > 1
) {
const typeNameWithNamespace = typeNames.map((typeName) => {
return `${contextNamespace.name}.${typeName}`;
});
return factory.createIntersectionTypeNode(
(this.context ? [this.context.name, ...typeNames] : typeNames).map(
(type: string) => {
return factory.createTypeReferenceNode(
factory.createIdentifier(type),
undefined,
);
},
),
(this.context
? [this.context.name, ...typeNameWithNamespace]
: typeNameWithNamespace
).map((type: string) => {
return factory.createTypeReferenceNode(
factory.createIdentifier(type),
undefined,
);
}),
);
} else {
return new TypeLocation(null, typeNames[0]).toTypeReference();
return new TypeLocation(
null,
`${contextNamespace.name}.${typeNames[0]}`,
).toTypeReference();
}
}
@ -664,7 +680,7 @@ export function extractContext(
...options,
};
const context = new TsCodegenContext(fullOptions);
const { contextMappingContent } = options;
const { contextNamespaceName, contextNamespacePath } = options;
visit(document, {
Directive: {
enter(node, _key, _parent, _path: any, ancestors) {
@ -694,7 +710,11 @@ export function extractContext(
}
const typeName = (typeDef as InterfaceTypeDefinitionNode).name.value;
context.addLegacyInterface(typeName);
} else if (node.name.value === "context" && contextMappingContent) {
} else if (
node.name.value === "context" &&
contextNamespaceName &&
contextNamespacePath
) {
if (
node.arguments?.length !== 1 ||
node.arguments[0].name.value !== "uses" ||
@ -711,12 +731,8 @@ export function extractContext(
return item.value;
});
const filtredDirectiveValues = directiveValues.filter(
(directiveValue) => contextMappingContent[directiveValue],
);
if (filtredDirectiveValues.length) {
context.initContextMap(ancestors, filtredDirectiveValues);
if (directiveValues.length) {
context.initContextMap(ancestors, directiveValues);
}
}
},

Просмотреть файл

@ -29,122 +29,26 @@ export function generateResolvers(context: TsCodegenContext): ts.SourceFile {
),
);
if (
Object.keys(context.getContextMap()).length &&
context.getContextMappingContent()
) {
const contextImportNames: Set<string> = new Set();
const contextNamespace = context.getContextNamespace();
for (const [, root] of Object.entries(context.getContextMap())) {
const rootValue: string[] = (root as any).__context;
if (rootValue) {
if (
rootValue.every((importName: string) =>
contextImportNames.has(importName),
)
) {
continue;
}
const imports = (rootValue as string[]).reduce<
Record<string, string[]>
>((acc: Record<string, string[]>, importName: string) => {
const importPath = context.getContextMappingContent()?.[importName];
if (importPath) {
if (!acc[importPath]) {
acc[importPath] = [];
}
acc[importPath].push(importName);
}
return acc;
}, {});
for (const [importPath, importNames] of Object.entries(imports)) {
statements.push(
factory.createImportDeclaration(
if (Object.keys(context.getContextMap()).length && contextNamespace) {
statements.push(
factory.createImportDeclaration(
undefined,
factory.createImportClause(
true,
undefined,
factory.createNamedImports([
factory.createImportSpecifier(
false,
undefined,
factory.createImportClause(
true,
undefined,
factory.createNamedImports(
importNames
.map((importName: string) => {
if (contextImportNames.has(importName)) {
return;
}
contextImportNames.add(importName);
return factory.createImportSpecifier(
false,
undefined,
factory.createIdentifier(importName),
);
})
.filter(Boolean) as ts.ImportSpecifier[],
),
),
factory.createStringLiteral(importPath),
factory.createIdentifier(contextNamespace.name),
),
);
}
}
for (const [key, value] of Object.entries(root as any)) {
if (key.startsWith("__")) {
continue;
}
if (
(value as string[]).every((importName: string) =>
contextImportNames.has(importName),
)
) {
continue;
}
const imports = (value as string[]).reduce<Record<string, string[]>>(
(acc: Record<string, string[]>, importName: string) => {
const importPath = context.getContextMappingContent()?.[importName];
if (importPath) {
if (!acc[importPath]) {
acc[importPath] = [];
}
acc[importPath].push(importName);
}
return acc;
},
{},
);
for (const [importPath, importNames] of Object.entries(imports)) {
statements.push(
factory.createImportDeclaration(
undefined,
factory.createImportClause(
true,
undefined,
factory.createNamedImports(
importNames
.map((importName: string) => {
if (contextImportNames.has(importName)) {
return;
}
contextImportNames.add(importName);
return factory.createImportSpecifier(
false,
undefined,
factory.createIdentifier(importName),
);
})
.filter(Boolean) as ts.ImportSpecifier[],
),
),
factory.createStringLiteral(importPath),
),
);
}
}
}
]),
),
factory.createStringLiteral(contextNamespace.from),
),
);
}
if (context.hasInputs) {