From ffef10c1411d4360b6b72ae954724de36ccfa233 Mon Sep 17 00:00:00 2001 From: vejrj <77059398+vejrj@users.noreply.github.com> Date: Tue, 4 Mar 2025 12:38:06 +0100 Subject: [PATCH 01/12] alpha version release script --- .azure-devops/graphitation-release.yml | 1 + package.json | 4 ++-- packages/cli/package.json | 2 +- packages/ts-codegen/package.json | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.azure-devops/graphitation-release.yml b/.azure-devops/graphitation-release.yml index 720a446b0..289d753bc 100644 --- a/.azure-devops/graphitation-release.yml +++ b/.azure-devops/graphitation-release.yml @@ -1,6 +1,7 @@ pr: none trigger: - main + - jvejr/ts-codegen-subtype-alpha-release - alloy/relay-apollo-duct-tape variables: diff --git a/package.json b/package.json index 6d0c7990b..b5aef0858 100644 --- a/package.json +++ b/package.json @@ -18,10 +18,10 @@ "lint": "lage lint --continue", "lage": "lage", "ci": "yarn lage build types test lint && yarn checkchange", - "beachball": "beachball -b origin/main", + "beachball": "beachball -b origin/jvejr/ts-codegen-subtype-alpha-release", "change": "yarn beachball change", "checkchange": "yarn beachball check", - "release": "yarn beachball publish -t latest", + "release": "yarn beachball publish -t alpha", "postinstall": "patch-package" }, "devDependencies": { diff --git a/packages/cli/package.json b/packages/cli/package.json index 5ba0df816..077211a22 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,7 +1,7 @@ { "name": "@graphitation/cli", "license": "MIT", - "version": "2.0.0", + "version": "2.1.0-alpha.0", "bin": { "supermassive": "./bin/supermassive.js" }, diff --git a/packages/ts-codegen/package.json b/packages/ts-codegen/package.json index 71c0e1cce..291670c7f 100644 --- a/packages/ts-codegen/package.json +++ b/packages/ts-codegen/package.json @@ -1,7 +1,7 @@ { "name": "@graphitation/ts-codegen", "license": "MIT", - "version": "3.0.0", + "version": "3.1.0-alpha.0", "main": "./src/index.ts", "repository": { "type": "git", From 90417639c69bec75e4c8c7b8e723e1d4150feabe Mon Sep 17 00:00:00 2001 From: vejrj <77059398+vejrj@users.noreply.github.com> Date: Tue, 4 Mar 2025 14:32:39 +0100 Subject: [PATCH 02/12] ts-codegen context subtype v2 (#525) * ts-codegen context subtype v2 --- ...-ad5574b3-b0b9-48d7-946c-4c202f7d52b1.json | 7 + ...-fe93a38c-5cd5-41c4-be4f-2daf6e2b72f4.json | 7 + packages/cli/src/supermassive.ts | 56 +----- .../ts-codegen/src/__tests__/context.test.ts | 165 +++++++++++----- .../ts-codegen/src/__tests__/index.test.ts | 178 ------------------ packages/ts-codegen/src/codegen.ts | 27 +-- packages/ts-codegen/src/context/index.ts | 153 +++++++-------- packages/ts-codegen/src/context/utilities.ts | 32 +--- packages/ts-codegen/src/enums.ts | 8 +- packages/ts-codegen/src/resolvers.ts | 87 +++++---- 10 files changed, 275 insertions(+), 445 deletions(-) create mode 100644 change/@graphitation-cli-ad5574b3-b0b9-48d7-946c-4c202f7d52b1.json create mode 100644 change/@graphitation-ts-codegen-fe93a38c-5cd5-41c4-be4f-2daf6e2b72f4.json diff --git a/change/@graphitation-cli-ad5574b3-b0b9-48d7-946c-4c202f7d52b1.json b/change/@graphitation-cli-ad5574b3-b0b9-48d7-946c-4c202f7d52b1.json new file mode 100644 index 000000000..ca91cf030 --- /dev/null +++ b/change/@graphitation-cli-ad5574b3-b0b9-48d7-946c-4c202f7d52b1.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "ts-codegen context subtype v2", + "packageName": "@graphitation/cli", + "email": "77059398+vejrj@users.noreply.github.com", + "dependentChangeType": "none" +} diff --git a/change/@graphitation-ts-codegen-fe93a38c-5cd5-41c4-be4f-2daf6e2b72f4.json b/change/@graphitation-ts-codegen-fe93a38c-5cd5-41c4-be4f-2daf6e2b72f4.json new file mode 100644 index 000000000..61c240dcc --- /dev/null +++ b/change/@graphitation-ts-codegen-fe93a38c-5cd5-41c4-be4f-2daf6e2b72f4.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "ts-codegen context subtype v2", + "packageName": "@graphitation/ts-codegen", + "email": "77059398+vejrj@users.noreply.github.com", + "dependentChangeType": "none" +} diff --git a/packages/cli/src/supermassive.ts b/packages/cli/src/supermassive.ts index fa04d845b..99dfadf4d 100644 --- a/packages/cli/src/supermassive.ts +++ b/packages/cli/src/supermassive.ts @@ -16,13 +16,10 @@ type GenerateInterfacesOptions = { legacy?: boolean; legacyModels?: boolean; useStringUnionsInsteadOfEnums?: boolean; - enumMigrationJsonFile?: string; - enumMigrationExceptionsJsonFile?: string; + contextSubTypeMetadataFile?: string; generateOnlyEnums?: boolean; generateResolverMap?: boolean; mandatoryResolverTypes?: boolean; - contextSubTypeNameTemplate?: string; - contextSubTypePathTemplate?: string; defaultContextSubTypePath?: string; defaultContextSubTypeName?: string; scope?: string; @@ -63,14 +60,6 @@ export function supermassive(): Command { "-dcn, --default-context-sub-type-name [defaultContextSubTypeName]", "Default context type which will extend context sub type", ) - .option( - "-cnt, --context-sub-type-name-template [contextSubTypeNameTemplate]", - "context resource name template. You need to specify ${resourceName} in the parameter eg. `${resourceName}Context`", - ) - .option( - "-cpt, --context-sub-type-path-template [contextSubTypePathTemplate]", - "context resource path template. You need to specify ${resourceName} in the parameter eg. `@package/preffix-${resourceName}-suffix`", - ) .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") @@ -81,12 +70,8 @@ export function supermassive(): Command { .option("--generate-only-enums", "Generate only enum file") .option("--scope [scope]", "generate models only for scope") .option( - "--enum-migration-json-file [enumMigrationJsonFile]", - "File containing array of enum names, which should be migrated to string unions", - ) - .option( - "--enum-migration-exceptions-json-file [enumMigrationExceptionsJsonFile]", - "File containing array of enum names, which should remain typescript enums", + "--context-sub-type-metadata-file [contextSubTypeMetadataFile]", + "Subtype metadata file", ) .option( "--generate-resolver-map", @@ -163,42 +148,20 @@ async function generateInterfaces( path.dirname(fullPath), options.outputDir ? options.outputDir : "__generated__", ); - let enumNamesToMigrate; - let enumNamesToKeep; - if (options.enumMigrationJsonFile) { - const content = JSON.parse( - await fs.readFile( - path.join(process.cwd(), options.enumMigrationJsonFile), - { - encoding: "utf-8", - }, - ), - ); - if (!Array.isArray(content)) { - throw new Error("enumMigrationJsonFile doesn't contain an array"); - } + let contextSubTypeMetadata: Record | undefined; - enumNamesToMigrate = content as string[]; - } - - if (options.enumMigrationExceptionsJsonFile) { + if (options.contextSubTypeMetadataFile) { const content = JSON.parse( await fs.readFile( - path.join(process.cwd(), options.enumMigrationExceptionsJsonFile), + path.join(process.cwd(), options.contextSubTypeMetadataFile), { encoding: "utf-8", }, ), ); - if (!Array.isArray(content)) { - throw new Error( - "enumMigrationExceptionsJsonFile doesn't contain an array", - ); - } - - enumNamesToKeep = content as string[]; + contextSubTypeMetadata = content; } const result = generateTS(document, { @@ -207,8 +170,6 @@ async function generateInterfaces( contextTypePath: getContextPath(outputPath, options.contextTypePath) || null, contextTypeName: options.contextTypeName, - contextSubTypeNameTemplate: options.contextSubTypeNameTemplate, - contextSubTypePathTemplate: options.contextSubTypePathTemplate, defaultContextSubTypePath: getContextPath( outputPath, options.defaultContextSubTypePath, @@ -221,8 +182,7 @@ async function generateInterfaces( generateOnlyEnums: !!options.generateOnlyEnums, generateResolverMap: !!options.generateResolverMap, mandatoryResolverTypes: !!options.mandatoryResolverTypes, - enumNamesToMigrate, - enumNamesToKeep, + contextSubTypeMetadata, modelScope: options.scope || null, }); diff --git a/packages/ts-codegen/src/__tests__/context.test.ts b/packages/ts-codegen/src/__tests__/context.test.ts index a118051b5..3db40b56e 100644 --- a/packages/ts-codegen/src/__tests__/context.test.ts +++ b/packages/ts-codegen/src/__tests__/context.test.ts @@ -3,9 +3,80 @@ import { parse } from "graphql"; import { blankGraphQLTag as graphql } from "../utilities"; import { generateTS } from ".."; import { ContextMap } from "../context"; +import { SubTypeNamespace } from "../codegen"; describe(generateTS, () => { describe("Tests basic syntax GraphQL syntax", () => { + const contextSubTypeMetadata = { + managers: { + user: { + name: "user", + importTypeName: 'UserStateMachineType["user"]', + importPath: "@package/user-state-machine", + }, + whatever: { + name: "whatever", + importTypeName: 'WhateverStateMachineType["whatever"]', + importPath: "@package/whatever-state-machine", + }, + "different-whatever": { + name: "different-whatever", + importTypeName: + 'DifferentWhateverStateMachineType["different-whatever"]', + importPath: "@package/different-whatever-state-machine", + }, + post: { + name: "post", + importTypeName: 'PostStateMachineType["post"]', + importPath: "@package/post-state-machine", + }, + node: { + name: "node", + importTypeName: 'NodeStateMachineType["node"]', + importPath: "@package/node-state-machine", + }, + persona: { + name: "persona", + importTypeName: 'PersonaStateMachineType["persona"]', + importPath: "@package/persona-state-machine", + }, + admin: { + name: "admin", + importTypeName: 'AdminStateMachineType["admin"]', + importPath: "@package/admin-state-machine", + }, + message: { + name: "message", + importTypeName: 'MessageStateMachineType["message"]', + importPath: "@package/message-state-machine", + }, + customer: { + name: "customer", + importTypeName: 'CustomerStateMachineType["customer"]', + importPath: "@package/customer-state-machine", + }, + "shouldnt-apply": { + name: "shouldnt-apply", + importTypeName: 'UserStateMachineType["shouldnt-apply"]', + importPath: "@package/shouldnt-apply-state-machine", + }, + "user-or-customer": { + name: "user-or-customer", + importTypeName: 'UserStateMachineType["user-or-customer"]', + importPath: "@package/user-or-customer-state-machine", + }, + "company-or-customer": { + name: "company-or-customer", + importTypeName: 'UserStateMachineType["company-or-customer"]', + importPath: "@package/company-or-customer-state-machine", + }, + "id-user": { + name: "id-user", + importTypeName: 'UserStateMachineType["id-user"]', + importPath: "@package/id-user-state-machine", + }, + }, + }; test("all possible nullable and non-nullable combinations", () => { const { resolvers, models, enums, inputs, contextMappingOutput } = runGenerateTest( @@ -18,11 +89,11 @@ describe(generateTS, () => { } type Message { - id: ID! @context(uses: ["message"]) + id: ID! @context(uses: { managers: ["message"] }) } - type User @context(uses: ["user"]) { - id: ID! @context(uses: ["id-user"]) + type User @context(uses: { managers: ["user"] }) { + id: ID! @context(uses: { managers: ["id-user"] }) name: String messagesWithAnswersNonRequired: [[Message]] messagesWithAnswersRequired: [[Message]]! @@ -31,7 +102,7 @@ describe(generateTS, () => { messagesWithArrayRequired: [Message]! messagesRequired: [Message!]! messagesOnlyMessageRequired: [Message!] - post: Post @context(uses: ["post"]) + post: Post @context(uses: { managers: ["post"] }) postRequired: Post! avatar: Avatar avatarRequired: Avatar! @@ -47,9 +118,7 @@ describe(generateTS, () => { } `, { - contextSubTypeNameTemplate: "I${resourceName}StateMachineContext", - contextSubTypePathTemplate: - "@msteams/core-cdl-sync-${resourceName}", + contextSubTypeMetadata: contextSubTypeMetadata, }, ); expect(enums).toMatchInlineSnapshot(`undefined`); @@ -311,11 +380,11 @@ describe(generateTS, () => { const { resolvers, models, enums, inputs, contextMappingOutput } = runGenerateTest( graphql` - interface Node @context(uses: ["node"]) { + interface Node @context(uses: { managers: ["node"] }) { id: ID! } - interface Persona @context(uses: ["persona"]) { + interface Persona @context(uses: { managers: ["persona"] }) { phone: String! } @@ -324,7 +393,8 @@ describe(generateTS, () => { name: String! } - type Admin implements Node & Persona @context(uses: ["admin"]) { + type Admin implements Node & Persona + @context(uses: { managers: ["admin"] }) { id: ID! rank: Int! } @@ -335,9 +405,7 @@ describe(generateTS, () => { } `, { - contextSubTypeNameTemplate: "I${resourceName}StateMachineContext", - contextSubTypePathTemplate: - "@msteams/core-cdl-sync-${resourceName}", + contextSubTypeMetadata, }, ); expect(enums).toMatchInlineSnapshot(`undefined`); @@ -459,11 +527,12 @@ describe(generateTS, () => { const { resolvers, models, enums, inputs, contextMappingOutput } = runGenerateTest( graphql` - interface Node @context(uses: ["node"]) { + interface Node @context(uses: { managers: ["node"] }) { id: ID! } - interface Customer implements Node @context(uses: ["customer"]) { + interface Customer implements Node + @context(uses: { managers: ["customer"] }) { id: ID! name: String! } @@ -478,9 +547,7 @@ describe(generateTS, () => { } `, { - contextSubTypeNameTemplate: "I${resourceName}StateMachineContext", - contextSubTypePathTemplate: - "@msteams/core-cdl-sync-${resourceName}", + contextSubTypeMetadata, }, ); expect(enums).toMatchInlineSnapshot(`undefined`); @@ -555,22 +622,26 @@ describe(generateTS, () => { test("applying @context to enum shouldn't affect anything", () => { const { resolvers, models, enums, inputs, contextMappingOutput } = - runGenerateTest(graphql` - enum PresenceAvailability @context(uses: ["shouldnt-apply"]) { - Available - Away - Offline - } + runGenerateTest( + graphql` + enum PresenceAvailability + @context(uses: { managers: ["shouldnt-apply"] }) { + Available + Away + Offline + } - type User { - id: ID! - availability: PresenceAvailability! - } + type User { + id: ID! + availability: PresenceAvailability! + } - extend type Query { - userById(id: ID!): User - } - `); + extend type Query { + userById(id: ID!): User + } + `, + { contextSubTypeMetadata }, + ); expect(enums).toMatchInlineSnapshot(` "export enum PresenceAvailability { Available = "Available", @@ -631,11 +702,11 @@ describe(generateTS, () => { id: ID! } - type Admin @context(uses: ["admin"]) { + type Admin @context(uses: { managers: ["admin"] }) { id: ID! } - type User @context(uses: ["user"]) { + type User @context(uses: { managers: ["user"] }) { id: ID! } @@ -644,24 +715,25 @@ describe(generateTS, () => { } union UserOrAdmin = User | Admin - union UserOrCustomer @context(uses: ["user-or-customer"]) = + union UserOrCustomer + @context(uses: { managers: ["user-or-customer"] }) = User | Customer - union CompanyOrCustomer @context(uses: ["company-or-customer"]) = + union CompanyOrCustomer + @context(uses: { managers: ["company-or-customer"] }) = Company | Customer extend type Query { - userById(id: ID!): whatever @context(uses: ["whatever"]) + userById(id: ID!): whatever + @context(uses: { managers: ["whatever"] }) userByMail(mail: String): whatever - @context(uses: ["different-whatever"]) + @context(uses: { managers: ["different-whatever"] }) node(id: ID!): Node } `, { - contextSubTypeNameTemplate: "I${resourceName}StateMachineContext", - contextSubTypePathTemplate: - "@msteams/core-cdl-sync-${resourceName}", + contextSubTypeMetadata, }, ); expect(enums).toMatchInlineSnapshot(`undefined`); @@ -818,11 +890,8 @@ function runGenerateTest( enumsImport?: string; legacyNoModelsForObjects?: boolean; useStringUnionsInsteadOfEnums?: boolean; - enumNamesToMigrate?: string[]; - enumNamesToKeep?: string[]; modelScope?: string; - contextSubTypeNameTemplate?: string; - contextSubTypePathTemplate?: string; + contextSubTypeMetadata?: SubTypeNamespace; } = {}, ): { enums?: string; @@ -833,8 +902,6 @@ function runGenerateTest( legacyResolvers?: string; legacyNoModelsForObjects?: boolean; useStringUnionsInsteadOfEnums?: boolean; - enumNamesToMigrate?: string[]; - enumNamesToKeep?: string[]; modelScope?: string; contextMappingOutput: ContextMap | null; } { @@ -846,10 +913,6 @@ function runGenerateTest( legacyCompat?: boolean; legacyNoModelsForObjects?: boolean; useStringUnionsInsteadOfEnums?: boolean; - enumNamesToMigrate?: string[]; - enumNamesToKeep?: string[]; - contextSubTypeNameTemplate?: string; - contextSubTypePathTemplate?: string; } = { outputPath: "__generated__", documentPath: "./typedef.graphql", diff --git a/packages/ts-codegen/src/__tests__/index.test.ts b/packages/ts-codegen/src/__tests__/index.test.ts index 9f56376e5..e93dced12 100644 --- a/packages/ts-codegen/src/__tests__/index.test.ts +++ b/packages/ts-codegen/src/__tests__/index.test.ts @@ -1735,182 +1735,6 @@ describe(generateTS, () => { `); }); - it("generateTS with string unions instead of enums, but only Enums specified in enumNamesToMigrate will be migrated", () => { - const { models, resolvers, legacyTypes, enums, inputs } = runGenerateTest( - graphql` - interface Node { - id: ID! - } - - enum Type { - type1 - type2 - } - - enum EnumToMigrate { - type1 - type2 - } - - type User implements Node { - id: ID! - userType: Type! - } - - extend type Query { - user(id: ID!): User! - } - `, - { - useStringUnionsInsteadOfEnums: true, - enumNamesToMigrate: ["EnumToMigrate"], - }, - ); - expect(enums).toMatchInlineSnapshot(` - "export enum Type { - type1 = "type1", - type2 = "type2" - } - export type EnumToMigrate = "type1" | "type2"; - " - `); - expect(inputs).toMatchInlineSnapshot(`undefined`); - expect(models).toMatchInlineSnapshot(` - "import * as Enums from "./enums.interface"; - export * from "./enums.interface"; - // Base type for all models. Enables automatic resolution of abstract GraphQL types (interfaces, unions) - export interface BaseModel { - readonly __typename?: string; - } - export interface Node extends BaseModel { - readonly __typename?: string; - } - export interface User extends BaseModel, Node { - readonly __typename?: "User"; - readonly id: string; - readonly userType: Enums.Type; - } - " - `); - expect(resolvers).toMatchInlineSnapshot(` - "import type { PromiseOrValue } from "@graphitation/supermassive"; - import type { ResolveInfo } from "@graphitation/supermassive"; - import * as Models from "./models.interface"; - export declare namespace Node { - export interface Resolvers { - readonly __resolveType?: __resolveType; - } - export type __resolveType = (parent: unknown, context: unknown, info: ResolveInfo) => PromiseOrValue; - } - export declare namespace User { - export interface Resolvers { - readonly id?: id; - readonly userType?: userType; - } - export type id = (model: Models.User, args: {}, context: unknown, info: ResolveInfo) => PromiseOrValue; - export type userType = (model: Models.User, args: {}, context: unknown, info: ResolveInfo) => PromiseOrValue; - } - export declare namespace Query { - export interface Resolvers { - readonly user?: user; - } - export type user = (model: unknown, args: { - readonly id: string; - }, context: unknown, info: ResolveInfo) => PromiseOrValue; - } - " - `); - expect(legacyTypes).toMatchInlineSnapshot(`undefined`); - }); - - it("generateTS with string unions instead of enums, but enums specified in `enumNamesToKeep` will remain the typescript enums", () => { - const { models, resolvers, legacyTypes, enums, inputs } = runGenerateTest( - graphql` - interface Node { - id: ID! - } - - enum Type { - type1 - type2 - } - - enum EnumToKeep { - type1 - type2 - } - - type User implements Node { - id: ID! - userType: Type! - } - - extend type Query { - user(id: ID!): User! - } - `, - { - useStringUnionsInsteadOfEnums: true, - enumNamesToKeep: ["EnumToKeep"], - }, - ); - expect(enums).toMatchInlineSnapshot(` - "export type Type = "type1" | "type2"; - export enum EnumToKeep { - type1 = "type1", - type2 = "type2" - } - " - `); - expect(inputs).toMatchInlineSnapshot(`undefined`); - expect(models).toMatchInlineSnapshot(` - "import * as Enums from "./enums.interface"; - export * from "./enums.interface"; - // Base type for all models. Enables automatic resolution of abstract GraphQL types (interfaces, unions) - export interface BaseModel { - readonly __typename?: string; - } - export interface Node extends BaseModel { - readonly __typename?: string; - } - export interface User extends BaseModel, Node { - readonly __typename?: "User"; - readonly id: string; - readonly userType: Enums.Type; - } - " - `); - expect(resolvers).toMatchInlineSnapshot(` - "import type { PromiseOrValue } from "@graphitation/supermassive"; - import type { ResolveInfo } from "@graphitation/supermassive"; - import * as Models from "./models.interface"; - export declare namespace Node { - export interface Resolvers { - readonly __resolveType?: __resolveType; - } - export type __resolveType = (parent: unknown, context: unknown, info: ResolveInfo) => PromiseOrValue; - } - export declare namespace User { - export interface Resolvers { - readonly id?: id; - readonly userType?: userType; - } - export type id = (model: Models.User, args: {}, context: unknown, info: ResolveInfo) => PromiseOrValue; - export type userType = (model: Models.User, args: {}, context: unknown, info: ResolveInfo) => PromiseOrValue; - } - export declare namespace Query { - export interface Resolvers { - readonly user?: user; - } - export type user = (model: unknown, args: { - readonly id: string; - }, context: unknown, info: ResolveInfo) => PromiseOrValue; - } - " - `); - expect(legacyTypes).toMatchInlineSnapshot(`undefined`); - }); - it("legacy interfaces", () => { const { models, resolvers, enums, inputs } = runGenerateTest( graphql` @@ -2247,8 +2071,6 @@ function runGenerateTest( legacyResolvers?: string; legacyNoModelsForObjects?: boolean; useStringUnionsInsteadOfEnums?: boolean; - enumNamesToMigrate?: string[]; - enumNamesToKeep?: string[]; modelScope?: string; } { const fullOptions = { diff --git a/packages/ts-codegen/src/codegen.ts b/packages/ts-codegen/src/codegen.ts index 49a5fcf83..e989f0d13 100644 --- a/packages/ts-codegen/src/codegen.ts +++ b/packages/ts-codegen/src/codegen.ts @@ -8,6 +8,18 @@ import { generateLegacyResolvers } from "./legacyResolvers"; import { generateEnums } from "./enums"; import { generateInputs } from "./inputs"; +export type SubTypeItem = { + [name: string]: { + name: string; + importTypeName: string; + importPath: string; + }; +}; + +export type SubTypeNamespace = { + [namespace: string]: SubTypeItem; +}; + export interface GenerateTSOptions { outputPath: string; documentPath: string; @@ -19,10 +31,7 @@ export interface GenerateTSOptions { legacyNoModelsForObjects?: boolean; modelScope?: string | null; generateOnlyEnums?: boolean; - enumNamesToMigrate?: string[]; - enumNamesToKeep?: string[]; - contextSubTypeNameTemplate?: string; - contextSubTypePathTemplate?: string; + contextSubTypeMetadata?: SubTypeNamespace; defaultContextSubTypePath?: string; defaultContextSubTypeName?: string; /** @@ -77,10 +86,7 @@ export function generateTS( legacyNoModelsForObjects, modelScope, generateOnlyEnums, - enumNamesToMigrate, - enumNamesToKeep, - contextSubTypeNameTemplate, - contextSubTypePathTemplate, + contextSubTypeMetadata, defaultContextSubTypePath, defaultContextSubTypeName, generateResolverMap = false, @@ -102,10 +108,7 @@ export function generateTS( enumsImport, legacyNoModelsForObjects, modelScope, - enumNamesToMigrate, - enumNamesToKeep, - contextSubTypeNameTemplate, - contextSubTypePathTemplate, + contextSubTypeMetadata, defaultContextSubTypePath, defaultContextSubTypeName, }, diff --git a/packages/ts-codegen/src/context/index.ts b/packages/ts-codegen/src/context/index.ts index 4825b869b..d6cc55def 100644 --- a/packages/ts-codegen/src/context/index.ts +++ b/packages/ts-codegen/src/context/index.ts @@ -25,13 +25,13 @@ import ts, { import { DefinitionImport, DefinitionModel } from "../types"; import { createImportDeclaration } from "./utilities"; import { - camelCase, createListType, createNonNullableType, createNullableType, } from "../utilities"; import { IMPORT_DIRECTIVE_NAME, processImportDirective } from "./import"; import { MODEL_DIRECTIVE_NAME, processModelDirective } from "./model"; +import { SubTypeNamespace } from "../codegen"; export type TsCodegenContextOptions = { moduleRoot: string; @@ -52,13 +52,10 @@ export type TsCodegenContextOptions = { }; legacyCompat: boolean; legacyNoModelsForObjects: boolean; - contextSubTypePathTemplate?: string; - contextSubTypeNameTemplate?: string; defaultContextSubTypePath?: string; defaultContextSubTypeName?: string; useStringUnionsInsteadOfEnums: boolean; - enumNamesToMigrate: string[] | null; - enumNamesToKeep: string[] | null; + contextSubTypeMetadata?: SubTypeNamespace; modelScope: string | null; }; @@ -90,8 +87,6 @@ const TsCodegenContextDefault: TsCodegenContextOptions = { from: "@graphitation/supermassive", }, legacyCompat: false, - enumNamesToMigrate: null, - enumNamesToKeep: null, legacyNoModelsForObjects: false, useStringUnionsInsteadOfEnums: false, @@ -122,10 +117,6 @@ export class TsCodegenContext { private typeNameToModels: Map; private legacyInterfaces: Set; context?: { name: string; from: string }; - contextDefaultSubTypeTemplate?: { - nameTemplate: string; - pathTemplate: string; - }; contextDefaultSubTypeContext?: { name: string; from: string }; hasUsedModelInInputs: boolean; hasUsedEnumsInModels: boolean; @@ -151,16 +142,6 @@ export class TsCodegenContext { this.hasEnums = Boolean(options.enumsImport); this.hasUsedEnumsInModels = false; - if ( - options.contextSubTypeNameTemplate && - options.contextSubTypePathTemplate - ) { - this.contextDefaultSubTypeTemplate = { - nameTemplate: options.contextSubTypeNameTemplate, - pathTemplate: options.contextSubTypePathTemplate, - }; - } - if ( options.defaultContextSubTypeName && options.defaultContextSubTypePath @@ -192,35 +173,24 @@ export class TsCodegenContext { return null; } - public replaceTemplateWithContextName( - template: string, - contextName: string, - camelCased = true, - ) { - return template.replace( - "${resourceName}", - camelCased ? camelCase(contextName, { pascalCase: true }) : contextName, - ); + public getSubTypesMetadata() { + return this.options.contextSubTypeMetadata; } - - public getContextTemplate() { - return this.contextDefaultSubTypeTemplate || null; - } - public getContextTypeNode(typeNames?: string[] | null) { - const contextDefaultSubTypeTemplate = this.contextDefaultSubTypeTemplate; + const subTypesMetadata = this.getSubTypesMetadata(); - if (!typeNames || !typeNames.length || !contextDefaultSubTypeTemplate) { + if (!typeNames || !typeNames.length || !subTypesMetadata) { return this.getContextType().toTypeReference(); } else if ( (typeNames.length === 1 && this.contextDefaultSubTypeContext) || typeNames.length > 1 ) { const typeNameWithNamespace = typeNames.map((typeName) => { - return this.replaceTemplateWithContextName( - contextDefaultSubTypeTemplate.nameTemplate, - typeName, - ); + const [namespace, subTypeName] = typeName.split(":"); + if (!subTypesMetadata?.[namespace]?.[subTypeName]) { + throw new Error("something went really wrong"); + } + return subTypesMetadata[namespace][subTypeName].importTypeName; }); return factory.createIntersectionTypeNode( @@ -235,12 +205,14 @@ export class TsCodegenContext { }), ); } else { + const [namespace, subTypeName] = typeNames[0].split(":"); + if (!subTypesMetadata?.[namespace]?.[subTypeName]) { + throw new Error("something went really wrong"); + } + return new TypeLocation( null, - this.replaceTemplateWithContextName( - contextDefaultSubTypeTemplate.nameTemplate, - typeNames[0], - ), + subTypesMetadata[namespace][subTypeName].importTypeName, ).toTypeReference(); } } @@ -298,25 +270,30 @@ export class TsCodegenContext { } } - getSubTypeNamesFromTemplate( - subTypes: string[], - nameTemplate: string, - pathTemplate: string, - ) { + cleanSubtypeImportName(subTypeImportIdentifier: string) { + return subTypeImportIdentifier.split(/\.|\[/)[0]; + } + + getSubTypeNamesImportMap(subTypes: string[]) { + const subTypeMetadata = this.getSubTypesMetadata(); return subTypes.reduce>( (acc: Record, importName: string) => { - const importPath = this.replaceTemplateWithContextName( - pathTemplate, - importName, - false, - ); + const [namespace, subTypeName] = importName.split(":"); + const subType = subTypeMetadata?.[namespace]?.[subTypeName]; + + if (!subType) { + throw new Error( + `Critical Error: Subtype ${importName} not found in metadata`, + ); + } + + const { importPath, importTypeName } = subType; + if (importPath) { if (!acc[importPath]) { acc[importPath] = []; } - acc[importPath].push( - this.replaceTemplateWithContextName(nameTemplate, importName), - ); + acc[importPath].push(this.cleanSubtypeImportName(importTypeName)); } return acc; }, @@ -349,22 +326,6 @@ export class TsCodegenContext { return this.allTypes; } - shouldMigrateEnum(enumName: string) { - if (!this.options.enumNamesToKeep && !this.options.enumNamesToMigrate) { - return true; - } - - if (this.options.enumNamesToKeep) { - return !this.options.enumNamesToKeep.includes(enumName); - } - - if (this.options.enumNamesToMigrate) { - return this.options.enumNamesToMigrate.includes(enumName); - } - - return true; - } - getTypeReferenceFromTypeNode( node: TypeNode, markUsage?: "MODELS" | "RESOLVERS", @@ -734,7 +695,6 @@ export function extractContext( }; const context = new TsCodegenContext(fullOptions); - const { contextSubTypeNameTemplate, contextSubTypePathTemplate } = options; visit(document, { Directive: { @@ -767,26 +727,51 @@ export function extractContext( context.addLegacyInterface(typeName); } else if ( node.name.value === "context" && - contextSubTypeNameTemplate && - contextSubTypePathTemplate + options.contextSubTypeMetadata ) { + const subTypeKeys: Set = new Set(); if ( node.arguments?.length !== 1 || node.arguments[0].name.value !== "uses" || - node.arguments[0].value.kind !== "ListValue" + node.arguments[0].value.kind !== "ObjectValue" ) { throw new Error("Invalid context use"); } - const directiveValues = node.arguments[0].value.values.map((item) => { - if (item.kind !== "StringValue") { + + node.arguments[0].value.fields.forEach(({ name, value, kind }) => { + if (kind !== "ObjectField") { throw new Error("Invalid context use"); } - return item.value; + const namespace = name.value; + if (value.kind !== "ListValue") { + throw new Error(`Namespace "${name}" must be list of strings`); + } + + const namespaceValues: string[] = value.values.map((v) => { + if (v.kind !== "StringValue") { + throw new Error(`Namespace "${name}" must be list of strings`); + } + return v.value; + }); + + if (!options.contextSubTypeMetadata?.[namespace]) { + throw new Error(`Namespace "${name}" is not supported`); + } + + namespaceValues.forEach((namespaceValue) => { + if ( + !options.contextSubTypeMetadata?.[namespace]?.[namespaceValue] + ) { + throw new Error( + `Value "${namespaceValue}" in namespace "${namespace}" is not supported`, + ); + } + + subTypeKeys.add(`${namespace}:${namespaceValue}`); + }); }); - if (directiveValues.length) { - context.initContextMap(ancestors, directiveValues); - } + context.initContextMap(ancestors, Array.from(subTypeKeys)); } }, }, diff --git a/packages/ts-codegen/src/context/utilities.ts b/packages/ts-codegen/src/context/utilities.ts index 4a9805bb9..a2f9d67ca 100644 --- a/packages/ts-codegen/src/context/utilities.ts +++ b/packages/ts-codegen/src/context/utilities.ts @@ -1,36 +1,6 @@ -import ts, { factory } from "typescript"; +import { factory } from "typescript"; import path from "path"; -export function getImportIdentifierForTypenames( - importNames: string[], - importPath: string, - contextImportNames: Set, -) { - return 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), - ); -} - export function createImportDeclaration( importNames: string[], from: string, diff --git a/packages/ts-codegen/src/enums.ts b/packages/ts-codegen/src/enums.ts index 46ee9d7e5..38fb7552f 100644 --- a/packages/ts-codegen/src/enums.ts +++ b/packages/ts-codegen/src/enums.ts @@ -11,8 +11,7 @@ export function generateEnums(context: TsCodegenContext): ts.SourceFile { .map((type) => { if (type.kind === "ENUM") { const isStringUnion = - context.isUseStringUnionsInsteadOfEnumsEnabled() && - context.shouldMigrateEnum(type.name); + context.isUseStringUnionsInsteadOfEnumsEnabled(); return factory.createExportDeclaration( undefined, @@ -54,10 +53,7 @@ function createEnumTypeModel( context: TsCodegenContext, type: EnumType, ): ts.EnumDeclaration | ts.TypeAliasDeclaration { - if ( - context.isUseStringUnionsInsteadOfEnumsEnabled() && - context.shouldMigrateEnum(type.name) - ) { + if (context.isUseStringUnionsInsteadOfEnumsEnabled()) { return factory.createTypeAliasDeclaration( [factory.createToken(ts.SyntaxKind.ExportKeyword)], factory.createIdentifier(type.name), diff --git a/packages/ts-codegen/src/resolvers.ts b/packages/ts-codegen/src/resolvers.ts index 9f904d4e7..8b89bc7e7 100644 --- a/packages/ts-codegen/src/resolvers.ts +++ b/packages/ts-codegen/src/resolvers.ts @@ -13,10 +13,48 @@ import { createUnionResolveType, createInterfaceResolveType, } from "./utilities"; -import { - createImportDeclaration, - getImportIdentifierForTypenames, -} from "./context/utilities"; +import { createImportDeclaration } from "./context/utilities"; + +export function getImportIdentifierForTypenames( + imports: Record, + contextImportNames: Set, +) { + const statements = []; + + for (const [importPath, importNames] of Object.entries(imports)) { + const importIndentifiers = 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[]; + + if (!importIndentifiers.length) { + continue; + } + + statements.push( + factory.createImportDeclaration( + undefined, + factory.createImportClause( + true, + undefined, + factory.createNamedImports(importIndentifiers), + ), + factory.createStringLiteral(importPath), + ), + ); + } + + return statements; +} const getResolverTypes = (context: TsCodegenContext): ResolverType[] => { return context @@ -53,9 +91,8 @@ export function generateResolvers( ), ); - const contextTemplate = context.getContextTemplate(); - - if (Object.keys(context.getContextMap()).length && contextTemplate) { + const getSubTypesMetadata = context.getSubTypesMetadata(); + if (Object.keys(context.getContextMap()).length && getSubTypesMetadata) { if ( context.contextDefaultSubTypeContext?.from && context.contextDefaultSubTypeContext?.name @@ -79,21 +116,11 @@ export function generateResolvers( ) { continue; } - const imports = context.getSubTypeNamesFromTemplate( - rootValue, - contextTemplate.nameTemplate, - contextTemplate.pathTemplate, - ); - for (const [importPath, importNames] of Object.entries(imports)) { - statements.push( - getImportIdentifierForTypenames( - importNames, - importPath, - contextImportNames, - ), - ); - } + const imports = context.getSubTypeNamesImportMap(rootValue); + statements.push( + ...getImportIdentifierForTypenames(imports, contextImportNames), + ); } for (const [key, value] of Object.entries(root)) { if (key.startsWith("__")) { @@ -107,21 +134,11 @@ export function generateResolvers( continue; } - const imports = context.getSubTypeNamesFromTemplate( - value, - contextTemplate.nameTemplate, - contextTemplate.pathTemplate, - ); + const imports = context.getSubTypeNamesImportMap(value); - for (const [importPath, importNames] of Object.entries(imports)) { - statements.push( - getImportIdentifierForTypenames( - importNames, - importPath, - contextImportNames, - ), - ); - } + statements.push( + ...getImportIdentifierForTypenames(imports, contextImportNames), + ); } } } From fb824e93c1b429874ca72516590d566daa4a13f1 Mon Sep 17 00:00:00 2001 From: vejrj <77059398+vejrj@users.noreply.github.com> Date: Tue, 4 Mar 2025 14:40:59 +0100 Subject: [PATCH 03/12] fix --- packages/cli/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index 077211a22..a626508cb 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -24,7 +24,7 @@ }, "dependencies": { "@graphitation/supermassive-extractors": "^2.2.5", - "@graphitation/ts-codegen": "^3.0.0", + "@graphitation/ts-codegen": "^3.1.0-alpha.0", "commander": "^8.3.0", "fast-glob": "^3.2.12", "graphql": "^15.6.1" From 65cc40b800dee34e55f769469366833db5ec4088 Mon Sep 17 00:00:00 2001 From: vejrj <77059398+vejrj@users.noreply.github.com> Date: Tue, 4 Mar 2025 15:02:21 +0100 Subject: [PATCH 04/12] snapshots updatye --- .../ts-codegen/src/__tests__/context.test.ts | 109 +++++++++--------- 1 file changed, 53 insertions(+), 56 deletions(-) diff --git a/packages/ts-codegen/src/__tests__/context.test.ts b/packages/ts-codegen/src/__tests__/context.test.ts index 3db40b56e..ec33e5c77 100644 --- a/packages/ts-codegen/src/__tests__/context.test.ts +++ b/packages/ts-codegen/src/__tests__/context.test.ts @@ -126,18 +126,18 @@ describe(generateTS, () => { { "Message": { "id": [ - "message", + "managers:message", ], }, "User": { "__context": [ - "user", + "managers:user", ], "id": [ - "id-user", + "managers:id-user", ], "post": [ - "post", + "managers:post", ], }, } @@ -180,10 +180,9 @@ describe(generateTS, () => { import type { PromiseOrValue } from "@graphitation/supermassive"; import type { ResolveInfo } from "@graphitation/supermassive"; import * as Models from "./models.interface"; - import type { IMessageStateMachineContext } from "@msteams/core-cdl-sync-message"; - import type { IUserStateMachineContext } from "@msteams/core-cdl-sync-user"; - import type { IIdUserStateMachineContext } from "@msteams/core-cdl-sync-id-user"; - import type { IPostStateMachineContext } from "@msteams/core-cdl-sync-post"; + import type { MessageStateMachineType } from "@package/message-state-machine"; + import type { UserStateMachineType } from "@package/user-state-machine"; + import type { PostStateMachineType } from "@package/post-state-machine"; export declare namespace Post { export interface Resolvers { readonly id?: id; @@ -194,7 +193,7 @@ describe(generateTS, () => { export interface Resolvers { readonly id?: id; } - export type id = (model: Models.Message, args: {}, context: IMessageStateMachineContext, info: ResolveInfo) => PromiseOrValue; + export type id = (model: Models.Message, args: {}, context: MessageStateMachineType["message"], info: ResolveInfo) => PromiseOrValue; } export declare namespace User { export interface Resolvers { @@ -212,19 +211,19 @@ describe(generateTS, () => { readonly avatar?: avatar; readonly avatarRequired?: avatarRequired; } - export type id = (model: Models.User, args: {}, context: IIdUserStateMachineContext, info: ResolveInfo) => PromiseOrValue; - export type name = (model: Models.User, args: {}, context: IUserStateMachineContext, info: ResolveInfo) => PromiseOrValue; - export type messagesWithAnswersNonRequired = (model: Models.User, args: {}, context: IUserStateMachineContext, info: ResolveInfo) => PromiseOrValue | null | undefined> | null | undefined>; - export type messagesWithAnswersRequired = (model: Models.User, args: {}, context: IUserStateMachineContext, info: ResolveInfo) => PromiseOrValue | null | undefined>>; - export type messagesWithAnswersAllRequired = (model: Models.User, args: {}, context: IUserStateMachineContext, info: ResolveInfo) => PromiseOrValue>>; - export type messagesNonRequired = (model: Models.User, args: {}, context: IUserStateMachineContext, info: ResolveInfo) => PromiseOrValue | null | undefined>; - export type messagesWithArrayRequired = (model: Models.User, args: {}, context: IUserStateMachineContext, info: ResolveInfo) => PromiseOrValue>; - export type messagesRequired = (model: Models.User, args: {}, context: IUserStateMachineContext, info: ResolveInfo) => PromiseOrValue>; - export type messagesOnlyMessageRequired = (model: Models.User, args: {}, context: IUserStateMachineContext, info: ResolveInfo) => PromiseOrValue | null | undefined>; - export type post = (model: Models.User, args: {}, context: IPostStateMachineContext, info: ResolveInfo) => PromiseOrValue; - export type postRequired = (model: Models.User, args: {}, context: IUserStateMachineContext, info: ResolveInfo) => PromiseOrValue; - export type avatar = (model: Models.User, args: {}, context: IUserStateMachineContext, info: ResolveInfo) => PromiseOrValue; - export type avatarRequired = (model: Models.User, args: {}, context: IUserStateMachineContext, info: ResolveInfo) => PromiseOrValue; + export type id = (model: Models.User, args: {}, context: UserStateMachineType["id-user"], info: ResolveInfo) => PromiseOrValue; + export type name = (model: Models.User, args: {}, context: UserStateMachineType["user"], info: ResolveInfo) => PromiseOrValue; + export type messagesWithAnswersNonRequired = (model: Models.User, args: {}, context: UserStateMachineType["user"], info: ResolveInfo) => PromiseOrValue | null | undefined> | null | undefined>; + export type messagesWithAnswersRequired = (model: Models.User, args: {}, context: UserStateMachineType["user"], info: ResolveInfo) => PromiseOrValue | null | undefined>>; + export type messagesWithAnswersAllRequired = (model: Models.User, args: {}, context: UserStateMachineType["user"], info: ResolveInfo) => PromiseOrValue>>; + export type messagesNonRequired = (model: Models.User, args: {}, context: UserStateMachineType["user"], info: ResolveInfo) => PromiseOrValue | null | undefined>; + export type messagesWithArrayRequired = (model: Models.User, args: {}, context: UserStateMachineType["user"], info: ResolveInfo) => PromiseOrValue>; + export type messagesRequired = (model: Models.User, args: {}, context: UserStateMachineType["user"], info: ResolveInfo) => PromiseOrValue>; + export type messagesOnlyMessageRequired = (model: Models.User, args: {}, context: UserStateMachineType["user"], info: ResolveInfo) => PromiseOrValue | null | undefined>; + export type post = (model: Models.User, args: {}, context: PostStateMachineType["post"], info: ResolveInfo) => PromiseOrValue; + export type postRequired = (model: Models.User, args: {}, context: UserStateMachineType["user"], info: ResolveInfo) => PromiseOrValue; + export type avatar = (model: Models.User, args: {}, context: UserStateMachineType["user"], info: ResolveInfo) => PromiseOrValue; + export type avatarRequired = (model: Models.User, args: {}, context: UserStateMachineType["user"], info: ResolveInfo) => PromiseOrValue; } export declare namespace Query { export interface Resolvers { @@ -413,17 +412,17 @@ describe(generateTS, () => { { "Admin": { "__context": [ - "admin", + "managers:admin", ], }, "Node": { "__context": [ - "node", + "managers:node", ], }, "Persona": { "__context": [ - "persona", + "managers:persona", ], }, } @@ -454,20 +453,20 @@ describe(generateTS, () => { "import type { PromiseOrValue } from "@graphitation/supermassive"; import type { ResolveInfo } from "@graphitation/supermassive"; import * as Models from "./models.interface"; - import type { INodeStateMachineContext } from "@msteams/core-cdl-sync-node"; - import type { IPersonaStateMachineContext } from "@msteams/core-cdl-sync-persona"; - import type { IAdminStateMachineContext } from "@msteams/core-cdl-sync-admin"; + import type { NodeStateMachineType } from "@package/node-state-machine"; + import type { PersonaStateMachineType } from "@package/persona-state-machine"; + import type { AdminStateMachineType } from "@package/admin-state-machine"; export declare namespace Node { export interface Resolvers { readonly __resolveType?: __resolveType; } - export type __resolveType = (parent: unknown, context: INodeStateMachineContext, info: ResolveInfo) => PromiseOrValue; + export type __resolveType = (parent: unknown, context: NodeStateMachineType["node"], info: ResolveInfo) => PromiseOrValue; } export declare namespace Persona { export interface Resolvers { readonly __resolveType?: __resolveType; } - export type __resolveType = (parent: unknown, context: IPersonaStateMachineContext, info: ResolveInfo) => PromiseOrValue; + export type __resolveType = (parent: unknown, context: PersonaStateMachineType["persona"], info: ResolveInfo) => PromiseOrValue; } export declare namespace User { export interface Resolvers { @@ -480,8 +479,8 @@ describe(generateTS, () => { readonly id?: id; readonly rank?: rank; } - export type id = (model: Models.Admin, args: {}, context: IAdminStateMachineContext, info: ResolveInfo) => PromiseOrValue; - export type rank = (model: Models.Admin, args: {}, context: IAdminStateMachineContext, info: ResolveInfo) => PromiseOrValue; + export type id = (model: Models.Admin, args: {}, context: AdminStateMachineType["admin"], info: ResolveInfo) => PromiseOrValue; + export type rank = (model: Models.Admin, args: {}, context: AdminStateMachineType["admin"], info: ResolveInfo) => PromiseOrValue; } export declare namespace Query { export interface Resolvers { @@ -555,12 +554,12 @@ describe(generateTS, () => { { "Customer": { "__context": [ - "customer", + "managers:customer", ], }, "Node": { "__context": [ - "node", + "managers:node", ], }, } @@ -588,19 +587,19 @@ describe(generateTS, () => { "import type { PromiseOrValue } from "@graphitation/supermassive"; import type { ResolveInfo } from "@graphitation/supermassive"; import * as Models from "./models.interface"; - import type { INodeStateMachineContext } from "@msteams/core-cdl-sync-node"; - import type { ICustomerStateMachineContext } from "@msteams/core-cdl-sync-customer"; + import type { NodeStateMachineType } from "@package/node-state-machine"; + import type { CustomerStateMachineType } from "@package/customer-state-machine"; export declare namespace Node { export interface Resolvers { readonly __resolveType?: __resolveType; } - export type __resolveType = (parent: unknown, context: INodeStateMachineContext, info: ResolveInfo) => PromiseOrValue; + export type __resolveType = (parent: unknown, context: NodeStateMachineType["node"], info: ResolveInfo) => PromiseOrValue; } export declare namespace Customer { export interface Resolvers { readonly __resolveType?: __resolveType; } - export type __resolveType = (parent: unknown, context: ICustomerStateMachineContext, info: ResolveInfo) => PromiseOrValue; + export type __resolveType = (parent: unknown, context: CustomerStateMachineType["customer"], info: ResolveInfo) => PromiseOrValue; } export declare namespace User { export interface Resolvers { @@ -741,30 +740,30 @@ describe(generateTS, () => { { "Admin": { "__context": [ - "admin", + "managers:admin", ], }, "CompanyOrCustomer": { "__context": [ - "company-or-customer", + "managers:company-or-customer", ], }, "Query": { "userById": [ - "whatever", + "managers:whatever", ], "userByMail": [ - "different-whatever", + "managers:different-whatever", ], }, "User": { "__context": [ - "user", + "managers:user", ], }, "UserOrCustomer": { "__context": [ - "user-or-customer", + "managers:user-or-customer", ], }, } @@ -803,12 +802,10 @@ describe(generateTS, () => { "import type { PromiseOrValue } from "@graphitation/supermassive"; import type { ResolveInfo } from "@graphitation/supermassive"; import * as Models from "./models.interface"; - import type { IAdminStateMachineContext } from "@msteams/core-cdl-sync-admin"; - import type { IUserStateMachineContext } from "@msteams/core-cdl-sync-user"; - import type { IUserOrCustomerStateMachineContext } from "@msteams/core-cdl-sync-user-or-customer"; - import type { ICompanyOrCustomerStateMachineContext } from "@msteams/core-cdl-sync-company-or-customer"; - import type { IWhateverStateMachineContext } from "@msteams/core-cdl-sync-whatever"; - import type { IDifferentWhateverStateMachineContext } from "@msteams/core-cdl-sync-different-whatever"; + import type { AdminStateMachineType } from "@package/admin-state-machine"; + import type { UserStateMachineType } from "@package/user-state-machine"; + import type { WhateverStateMachineType } from "@package/whatever-state-machine"; + import type { DifferentWhateverStateMachineType } from "@package/different-whatever-state-machine"; export declare namespace Customer { export interface Resolvers { readonly id?: id; @@ -825,13 +822,13 @@ describe(generateTS, () => { export interface Resolvers { readonly id?: id; } - export type id = (model: Models.Admin, args: {}, context: IAdminStateMachineContext, info: ResolveInfo) => PromiseOrValue; + export type id = (model: Models.Admin, args: {}, context: AdminStateMachineType["admin"], info: ResolveInfo) => PromiseOrValue; } export declare namespace User { export interface Resolvers { readonly id?: id; } - export type id = (model: Models.User, args: {}, context: IUserStateMachineContext, info: ResolveInfo) => PromiseOrValue; + export type id = (model: Models.User, args: {}, context: UserStateMachineType["user"], info: ResolveInfo) => PromiseOrValue; } export declare namespace Node { export interface Resolvers { @@ -849,13 +846,13 @@ describe(generateTS, () => { export interface Resolvers { readonly __resolveType?: __resolveType; } - export type __resolveType = (parent: Models.User | Models.Customer, context: IUserOrCustomerStateMachineContext, info: ResolveInfo) => PromiseOrValue<"User" | "Customer" | null>; + export type __resolveType = (parent: Models.User | Models.Customer, context: UserStateMachineType["user-or-customer"], info: ResolveInfo) => PromiseOrValue<"User" | "Customer" | null>; } export declare namespace CompanyOrCustomer { export interface Resolvers { readonly __resolveType?: __resolveType; } - export type __resolveType = (parent: Models.Company | Models.Customer, context: ICompanyOrCustomerStateMachineContext, info: ResolveInfo) => PromiseOrValue<"Company" | "Customer" | null>; + export type __resolveType = (parent: Models.Company | Models.Customer, context: UserStateMachineType["company-or-customer"], info: ResolveInfo) => PromiseOrValue<"Company" | "Customer" | null>; } export declare namespace Query { export interface Resolvers { @@ -865,10 +862,10 @@ describe(generateTS, () => { } export type userById = (model: unknown, args: { readonly id: string; - }, context: IWhateverStateMachineContext, info: ResolveInfo) => PromiseOrValue; + }, context: WhateverStateMachineType["whatever"], info: ResolveInfo) => PromiseOrValue; export type userByMail = (model: unknown, args: { readonly mail?: string | null; - }, context: IDifferentWhateverStateMachineContext, info: ResolveInfo) => PromiseOrValue; + }, context: DifferentWhateverStateMachineType["different-whatever"], info: ResolveInfo) => PromiseOrValue; export type node = (model: unknown, args: { readonly id: string; }, context: unknown, info: ResolveInfo) => PromiseOrValue; From dd72f60e48ec38ed72107b3e7084e83871fd5f2d Mon Sep 17 00:00:00 2001 From: Graphitation Service Account Date: Tue, 4 Mar 2025 14:17:11 +0000 Subject: [PATCH 05/12] applying package updates --- ...-ad5574b3-b0b9-48d7-946c-4c202f7d52b1.json | 7 ------- ...-fe93a38c-5cd5-41c4-be4f-2daf6e2b72f4.json | 7 ------- packages/cli/CHANGELOG.json | 21 +++++++++++++++++++ packages/cli/CHANGELOG.md | 11 +++++++++- packages/cli/package.json | 4 ++-- packages/ts-codegen/CHANGELOG.json | 15 +++++++++++++ packages/ts-codegen/CHANGELOG.md | 10 ++++++++- packages/ts-codegen/package.json | 2 +- 8 files changed, 58 insertions(+), 19 deletions(-) delete mode 100644 change/@graphitation-cli-ad5574b3-b0b9-48d7-946c-4c202f7d52b1.json delete mode 100644 change/@graphitation-ts-codegen-fe93a38c-5cd5-41c4-be4f-2daf6e2b72f4.json diff --git a/change/@graphitation-cli-ad5574b3-b0b9-48d7-946c-4c202f7d52b1.json b/change/@graphitation-cli-ad5574b3-b0b9-48d7-946c-4c202f7d52b1.json deleted file mode 100644 index ca91cf030..000000000 --- a/change/@graphitation-cli-ad5574b3-b0b9-48d7-946c-4c202f7d52b1.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "type": "prerelease", - "comment": "ts-codegen context subtype v2", - "packageName": "@graphitation/cli", - "email": "77059398+vejrj@users.noreply.github.com", - "dependentChangeType": "none" -} diff --git a/change/@graphitation-ts-codegen-fe93a38c-5cd5-41c4-be4f-2daf6e2b72f4.json b/change/@graphitation-ts-codegen-fe93a38c-5cd5-41c4-be4f-2daf6e2b72f4.json deleted file mode 100644 index 61c240dcc..000000000 --- a/change/@graphitation-ts-codegen-fe93a38c-5cd5-41c4-be4f-2daf6e2b72f4.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "type": "prerelease", - "comment": "ts-codegen context subtype v2", - "packageName": "@graphitation/ts-codegen", - "email": "77059398+vejrj@users.noreply.github.com", - "dependentChangeType": "none" -} diff --git a/packages/cli/CHANGELOG.json b/packages/cli/CHANGELOG.json index 071d7fd0b..9c54886a7 100644 --- a/packages/cli/CHANGELOG.json +++ b/packages/cli/CHANGELOG.json @@ -1,6 +1,27 @@ { "name": "@graphitation/cli", "entries": [ + { + "date": "Tue, 04 Mar 2025 14:17:11 GMT", + "version": "2.1.0-alpha.1", + "tag": "@graphitation/cli_v2.1.0-alpha.1", + "comments": { + "prerelease": [ + { + "author": "77059398+vejrj@users.noreply.github.com", + "package": "@graphitation/cli", + "commit": "fb824e93c1b429874ca72516590d566daa4a13f1", + "comment": "ts-codegen context subtype v2" + }, + { + "author": "beachball", + "package": "@graphitation/cli", + "comment": "Bump @graphitation/ts-codegen to v3.1.0-alpha.1", + "commit": "not available" + } + ] + } + }, { "date": "Wed, 19 Feb 2025 14:18:14 GMT", "version": "2.0.0", diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 9d82c9a25..64ecae4ca 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,9 +1,18 @@ # Change Log - @graphitation/cli - + +## 2.1.0-alpha.1 + +Tue, 04 Mar 2025 14:17:11 GMT + +### Changes + +- ts-codegen context subtype v2 (77059398+vejrj@users.noreply.github.com) +- Bump @graphitation/ts-codegen to v3.1.0-alpha.1 + ## 2.0.0 Wed, 19 Feb 2025 14:18:14 GMT diff --git a/packages/cli/package.json b/packages/cli/package.json index a626508cb..b5f2de30a 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,7 +1,7 @@ { "name": "@graphitation/cli", "license": "MIT", - "version": "2.1.0-alpha.0", + "version": "2.1.0-alpha.1", "bin": { "supermassive": "./bin/supermassive.js" }, @@ -24,7 +24,7 @@ }, "dependencies": { "@graphitation/supermassive-extractors": "^2.2.5", - "@graphitation/ts-codegen": "^3.1.0-alpha.0", + "@graphitation/ts-codegen": "^3.1.0-alpha.1", "commander": "^8.3.0", "fast-glob": "^3.2.12", "graphql": "^15.6.1" diff --git a/packages/ts-codegen/CHANGELOG.json b/packages/ts-codegen/CHANGELOG.json index eb65f1151..f3dbc36b2 100644 --- a/packages/ts-codegen/CHANGELOG.json +++ b/packages/ts-codegen/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@graphitation/ts-codegen", "entries": [ + { + "date": "Tue, 04 Mar 2025 14:17:11 GMT", + "version": "3.1.0-alpha.1", + "tag": "@graphitation/ts-codegen_v3.1.0-alpha.1", + "comments": { + "prerelease": [ + { + "author": "77059398+vejrj@users.noreply.github.com", + "package": "@graphitation/ts-codegen", + "commit": "fb824e93c1b429874ca72516590d566daa4a13f1", + "comment": "ts-codegen context subtype v2" + } + ] + } + }, { "date": "Wed, 19 Feb 2025 11:31:28 GMT", "version": "3.0.0", diff --git a/packages/ts-codegen/CHANGELOG.md b/packages/ts-codegen/CHANGELOG.md index 945223c46..2f14e2d87 100644 --- a/packages/ts-codegen/CHANGELOG.md +++ b/packages/ts-codegen/CHANGELOG.md @@ -1,9 +1,17 @@ # Change Log - @graphitation/ts-codegen - + +## 3.1.0-alpha.1 + +Tue, 04 Mar 2025 14:17:11 GMT + +### Changes + +- ts-codegen context subtype v2 (77059398+vejrj@users.noreply.github.com) + ## 3.0.0 Wed, 19 Feb 2025 11:31:28 GMT diff --git a/packages/ts-codegen/package.json b/packages/ts-codegen/package.json index 291670c7f..3f56970ac 100644 --- a/packages/ts-codegen/package.json +++ b/packages/ts-codegen/package.json @@ -1,7 +1,7 @@ { "name": "@graphitation/ts-codegen", "license": "MIT", - "version": "3.1.0-alpha.0", + "version": "3.1.0-alpha.1", "main": "./src/index.ts", "repository": { "type": "git", From f3a78cb45a5bc94c0309dd43a2c770e062344db4 Mon Sep 17 00:00:00 2001 From: vejrj <77059398+vejrj@users.noreply.github.com> Date: Mon, 17 Mar 2025 13:57:47 +0100 Subject: [PATCH 06/12] Return namespaced type in resolvers (#526) * Return namespaced type * Change files --- ...-0e9d9d1f-8328-4460-a942-8e88949c5eeb.json | 7 + .../ts-codegen/src/__tests__/context.test.ts | 169 +++++++++++++++--- packages/ts-codegen/src/context/index.ts | 88 +++++---- 3 files changed, 205 insertions(+), 59 deletions(-) create mode 100644 change/@graphitation-ts-codegen-0e9d9d1f-8328-4460-a942-8e88949c5eeb.json diff --git a/change/@graphitation-ts-codegen-0e9d9d1f-8328-4460-a942-8e88949c5eeb.json b/change/@graphitation-ts-codegen-0e9d9d1f-8328-4460-a942-8e88949c5eeb.json new file mode 100644 index 000000000..dda14d34c --- /dev/null +++ b/change/@graphitation-ts-codegen-0e9d9d1f-8328-4460-a942-8e88949c5eeb.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "Return namespaced type", + "packageName": "@graphitation/ts-codegen", + "email": "77059398+vejrj@users.noreply.github.com", + "dependentChangeType": "none" +} diff --git a/packages/ts-codegen/src/__tests__/context.test.ts b/packages/ts-codegen/src/__tests__/context.test.ts index ec33e5c77..c0d1db41a 100644 --- a/packages/ts-codegen/src/__tests__/context.test.ts +++ b/packages/ts-codegen/src/__tests__/context.test.ts @@ -93,7 +93,7 @@ describe(generateTS, () => { } type User @context(uses: { managers: ["user"] }) { - id: ID! @context(uses: { managers: ["id-user"] }) + id: ID! @context(uses: { managers: ["id-user", "user"] }) name: String messagesWithAnswersNonRequired: [[Message]] messagesWithAnswersRequired: [[Message]]! @@ -119,6 +119,8 @@ describe(generateTS, () => { `, { contextSubTypeMetadata: contextSubTypeMetadata, + defaultContextSubTypePath: "@package/default-context", + defaultContextSubTypeName: "DefaultContextType", }, ); expect(enums).toMatchInlineSnapshot(`undefined`); @@ -135,6 +137,7 @@ describe(generateTS, () => { ], "id": [ "managers:id-user", + "managers:user", ], "post": [ "managers:post", @@ -180,6 +183,7 @@ describe(generateTS, () => { import type { PromiseOrValue } from "@graphitation/supermassive"; import type { ResolveInfo } from "@graphitation/supermassive"; import * as Models from "./models.interface"; + import type { DefaultContextType } from "@package/default-context"; import type { MessageStateMachineType } from "@package/message-state-machine"; import type { UserStateMachineType } from "@package/user-state-machine"; import type { PostStateMachineType } from "@package/post-state-machine"; @@ -193,7 +197,11 @@ describe(generateTS, () => { export interface Resolvers { readonly id?: id; } - export type id = (model: Models.Message, args: {}, context: MessageStateMachineType["message"], info: ResolveInfo) => PromiseOrValue; + export type id = (model: Models.Message, args: {}, context: DefaultContextType & { + managers: { + "message": MessageStateMachineType["message"]; + }; + }, info: ResolveInfo) => PromiseOrValue; } export declare namespace User { export interface Resolvers { @@ -211,19 +219,72 @@ describe(generateTS, () => { readonly avatar?: avatar; readonly avatarRequired?: avatarRequired; } - export type id = (model: Models.User, args: {}, context: UserStateMachineType["id-user"], info: ResolveInfo) => PromiseOrValue; - export type name = (model: Models.User, args: {}, context: UserStateMachineType["user"], info: ResolveInfo) => PromiseOrValue; - export type messagesWithAnswersNonRequired = (model: Models.User, args: {}, context: UserStateMachineType["user"], info: ResolveInfo) => PromiseOrValue | null | undefined> | null | undefined>; - export type messagesWithAnswersRequired = (model: Models.User, args: {}, context: UserStateMachineType["user"], info: ResolveInfo) => PromiseOrValue | null | undefined>>; - export type messagesWithAnswersAllRequired = (model: Models.User, args: {}, context: UserStateMachineType["user"], info: ResolveInfo) => PromiseOrValue>>; - export type messagesNonRequired = (model: Models.User, args: {}, context: UserStateMachineType["user"], info: ResolveInfo) => PromiseOrValue | null | undefined>; - export type messagesWithArrayRequired = (model: Models.User, args: {}, context: UserStateMachineType["user"], info: ResolveInfo) => PromiseOrValue>; - export type messagesRequired = (model: Models.User, args: {}, context: UserStateMachineType["user"], info: ResolveInfo) => PromiseOrValue>; - export type messagesOnlyMessageRequired = (model: Models.User, args: {}, context: UserStateMachineType["user"], info: ResolveInfo) => PromiseOrValue | null | undefined>; - export type post = (model: Models.User, args: {}, context: PostStateMachineType["post"], info: ResolveInfo) => PromiseOrValue; - export type postRequired = (model: Models.User, args: {}, context: UserStateMachineType["user"], info: ResolveInfo) => PromiseOrValue; - export type avatar = (model: Models.User, args: {}, context: UserStateMachineType["user"], info: ResolveInfo) => PromiseOrValue; - export type avatarRequired = (model: Models.User, args: {}, context: UserStateMachineType["user"], info: ResolveInfo) => PromiseOrValue; + export type id = (model: Models.User, args: {}, context: DefaultContextType & { + managers: { + "id-user": UserStateMachineType["id-user"]; + "user": UserStateMachineType["user"]; + }; + }, info: ResolveInfo) => PromiseOrValue; + export type name = (model: Models.User, args: {}, context: DefaultContextType & { + managers: { + "user": UserStateMachineType["user"]; + }; + }, info: ResolveInfo) => PromiseOrValue; + export type messagesWithAnswersNonRequired = (model: Models.User, args: {}, context: DefaultContextType & { + managers: { + "user": UserStateMachineType["user"]; + }; + }, info: ResolveInfo) => PromiseOrValue | null | undefined> | null | undefined>; + export type messagesWithAnswersRequired = (model: Models.User, args: {}, context: DefaultContextType & { + managers: { + "user": UserStateMachineType["user"]; + }; + }, info: ResolveInfo) => PromiseOrValue | null | undefined>>; + export type messagesWithAnswersAllRequired = (model: Models.User, args: {}, context: DefaultContextType & { + managers: { + "user": UserStateMachineType["user"]; + }; + }, info: ResolveInfo) => PromiseOrValue>>; + export type messagesNonRequired = (model: Models.User, args: {}, context: DefaultContextType & { + managers: { + "user": UserStateMachineType["user"]; + }; + }, info: ResolveInfo) => PromiseOrValue | null | undefined>; + export type messagesWithArrayRequired = (model: Models.User, args: {}, context: DefaultContextType & { + managers: { + "user": UserStateMachineType["user"]; + }; + }, info: ResolveInfo) => PromiseOrValue>; + export type messagesRequired = (model: Models.User, args: {}, context: DefaultContextType & { + managers: { + "user": UserStateMachineType["user"]; + }; + }, info: ResolveInfo) => PromiseOrValue>; + export type messagesOnlyMessageRequired = (model: Models.User, args: {}, context: DefaultContextType & { + managers: { + "user": UserStateMachineType["user"]; + }; + }, info: ResolveInfo) => PromiseOrValue | null | undefined>; + export type post = (model: Models.User, args: {}, context: DefaultContextType & { + managers: { + "post": PostStateMachineType["post"]; + }; + }, info: ResolveInfo) => PromiseOrValue; + export type postRequired = (model: Models.User, args: {}, context: DefaultContextType & { + managers: { + "user": UserStateMachineType["user"]; + }; + }, info: ResolveInfo) => PromiseOrValue; + export type avatar = (model: Models.User, args: {}, context: DefaultContextType & { + managers: { + "user": UserStateMachineType["user"]; + }; + }, info: ResolveInfo) => PromiseOrValue; + export type avatarRequired = (model: Models.User, args: {}, context: DefaultContextType & { + managers: { + "user": UserStateMachineType["user"]; + }; + }, info: ResolveInfo) => PromiseOrValue; } export declare namespace Query { export interface Resolvers { @@ -460,13 +521,21 @@ describe(generateTS, () => { export interface Resolvers { readonly __resolveType?: __resolveType; } - export type __resolveType = (parent: unknown, context: NodeStateMachineType["node"], info: ResolveInfo) => PromiseOrValue; + export type __resolveType = (parent: unknown, context: { + managers: { + "node": NodeStateMachineType["node"]; + }; + }, info: ResolveInfo) => PromiseOrValue; } export declare namespace Persona { export interface Resolvers { readonly __resolveType?: __resolveType; } - export type __resolveType = (parent: unknown, context: PersonaStateMachineType["persona"], info: ResolveInfo) => PromiseOrValue; + export type __resolveType = (parent: unknown, context: { + managers: { + "persona": PersonaStateMachineType["persona"]; + }; + }, info: ResolveInfo) => PromiseOrValue; } export declare namespace User { export interface Resolvers { @@ -479,8 +548,16 @@ describe(generateTS, () => { readonly id?: id; readonly rank?: rank; } - export type id = (model: Models.Admin, args: {}, context: AdminStateMachineType["admin"], info: ResolveInfo) => PromiseOrValue; - export type rank = (model: Models.Admin, args: {}, context: AdminStateMachineType["admin"], info: ResolveInfo) => PromiseOrValue; + export type id = (model: Models.Admin, args: {}, context: { + managers: { + "admin": AdminStateMachineType["admin"]; + }; + }, info: ResolveInfo) => PromiseOrValue; + export type rank = (model: Models.Admin, args: {}, context: { + managers: { + "admin": AdminStateMachineType["admin"]; + }; + }, info: ResolveInfo) => PromiseOrValue; } export declare namespace Query { export interface Resolvers { @@ -593,13 +670,21 @@ describe(generateTS, () => { export interface Resolvers { readonly __resolveType?: __resolveType; } - export type __resolveType = (parent: unknown, context: NodeStateMachineType["node"], info: ResolveInfo) => PromiseOrValue; + export type __resolveType = (parent: unknown, context: { + managers: { + "node": NodeStateMachineType["node"]; + }; + }, info: ResolveInfo) => PromiseOrValue; } export declare namespace Customer { export interface Resolvers { readonly __resolveType?: __resolveType; } - export type __resolveType = (parent: unknown, context: CustomerStateMachineType["customer"], info: ResolveInfo) => PromiseOrValue; + export type __resolveType = (parent: unknown, context: { + managers: { + "customer": CustomerStateMachineType["customer"]; + }; + }, info: ResolveInfo) => PromiseOrValue; } export declare namespace User { export interface Resolvers { @@ -822,13 +907,21 @@ describe(generateTS, () => { export interface Resolvers { readonly id?: id; } - export type id = (model: Models.Admin, args: {}, context: AdminStateMachineType["admin"], info: ResolveInfo) => PromiseOrValue; + export type id = (model: Models.Admin, args: {}, context: { + managers: { + "admin": AdminStateMachineType["admin"]; + }; + }, info: ResolveInfo) => PromiseOrValue; } export declare namespace User { export interface Resolvers { readonly id?: id; } - export type id = (model: Models.User, args: {}, context: UserStateMachineType["user"], info: ResolveInfo) => PromiseOrValue; + export type id = (model: Models.User, args: {}, context: { + managers: { + "user": UserStateMachineType["user"]; + }; + }, info: ResolveInfo) => PromiseOrValue; } export declare namespace Node { export interface Resolvers { @@ -846,13 +939,21 @@ describe(generateTS, () => { export interface Resolvers { readonly __resolveType?: __resolveType; } - export type __resolveType = (parent: Models.User | Models.Customer, context: UserStateMachineType["user-or-customer"], info: ResolveInfo) => PromiseOrValue<"User" | "Customer" | null>; + export type __resolveType = (parent: Models.User | Models.Customer, context: { + managers: { + "user-or-customer": UserStateMachineType["user-or-customer"]; + }; + }, info: ResolveInfo) => PromiseOrValue<"User" | "Customer" | null>; } export declare namespace CompanyOrCustomer { export interface Resolvers { readonly __resolveType?: __resolveType; } - export type __resolveType = (parent: Models.Company | Models.Customer, context: UserStateMachineType["company-or-customer"], info: ResolveInfo) => PromiseOrValue<"Company" | "Customer" | null>; + export type __resolveType = (parent: Models.Company | Models.Customer, context: { + managers: { + "company-or-customer": UserStateMachineType["company-or-customer"]; + }; + }, info: ResolveInfo) => PromiseOrValue<"Company" | "Customer" | null>; } export declare namespace Query { export interface Resolvers { @@ -862,10 +963,18 @@ describe(generateTS, () => { } export type userById = (model: unknown, args: { readonly id: string; - }, context: WhateverStateMachineType["whatever"], info: ResolveInfo) => PromiseOrValue; + }, context: { + managers: { + "whatever": WhateverStateMachineType["whatever"]; + }; + }, info: ResolveInfo) => PromiseOrValue; export type userByMail = (model: unknown, args: { readonly mail?: string | null; - }, context: DifferentWhateverStateMachineType["different-whatever"], info: ResolveInfo) => PromiseOrValue; + }, context: { + managers: { + "different-whatever": DifferentWhateverStateMachineType["different-whatever"]; + }; + }, info: ResolveInfo) => PromiseOrValue; export type node = (model: unknown, args: { readonly id: string; }, context: unknown, info: ResolveInfo) => PromiseOrValue; @@ -881,7 +990,8 @@ function runGenerateTest( options: { outputPath?: string; documentPath?: string; - defaultContextTypePath?: string; + defaultContextSubTypeName?: string; + defaultContextSubTypePath?: string; contextName?: string; legacyCompat?: boolean; enumsImport?: string; @@ -905,7 +1015,8 @@ function runGenerateTest( const fullOptions: { outputPath: string; documentPath: string; - defaultContextTypePath?: string | null; + defaultContextSubTypeName?: string; + defaultContextSubTypePath?: string; contextName?: string; legacyCompat?: boolean; legacyNoModelsForObjects?: boolean; diff --git a/packages/ts-codegen/src/context/index.ts b/packages/ts-codegen/src/context/index.ts index d6cc55def..3d4aa28cd 100644 --- a/packages/ts-codegen/src/context/index.ts +++ b/packages/ts-codegen/src/context/index.ts @@ -176,44 +176,72 @@ export class TsCodegenContext { public getSubTypesMetadata() { return this.options.contextSubTypeMetadata; } + + private buildContextSubTypeNamespaceObject(typeNames: string[]) { + const subTypesMetadata = this.getSubTypesMetadata(); + + return typeNames.reduce< + Record + >((acc, typeName) => { + const [namespace, subTypeName] = typeName.split(":"); + if (!acc[namespace]) { + acc[namespace] = []; + } + + if (!subTypesMetadata?.[namespace]?.[subTypeName]) { + throw new Error("something went really wrong"); + } + acc[namespace].push({ + subType: subTypesMetadata[namespace][subTypeName].importTypeName, + name: subTypeName, + }); + + return acc; + }, {}); + } + public getContextTypeNode(typeNames?: string[] | null) { const subTypesMetadata = this.getSubTypesMetadata(); if (!typeNames || !typeNames.length || !subTypesMetadata) { return this.getContextType().toTypeReference(); - } else if ( - (typeNames.length === 1 && this.contextDefaultSubTypeContext) || - typeNames.length > 1 - ) { - const typeNameWithNamespace = typeNames.map((typeName) => { - const [namespace, subTypeName] = typeName.split(":"); - if (!subTypesMetadata?.[namespace]?.[subTypeName]) { - throw new Error("something went really wrong"); - } - return subTypesMetadata[namespace][subTypeName].importTypeName; - }); + } else { + const typeNameWithNamespace = + this.buildContextSubTypeNamespaceObject(typeNames); return factory.createIntersectionTypeNode( - (this.contextDefaultSubTypeContext - ? [this.contextDefaultSubTypeContext.name, ...typeNameWithNamespace] - : typeNameWithNamespace - ).map((type: string) => { - return factory.createTypeReferenceNode( - factory.createIdentifier(type), - undefined, - ); - }), + [ + this.contextDefaultSubTypeContext?.name && + factory.createTypeReferenceNode( + factory.createIdentifier(this.contextDefaultSubTypeContext.name), + undefined, + ), + factory.createTypeLiteralNode( + Object.entries(typeNameWithNamespace).map( + ([namespace, subTypes]) => { + return factory.createPropertySignature( + undefined, + factory.createIdentifier(namespace), + undefined, + factory.createTypeLiteralNode( + subTypes.map(({ subType, name }) => { + return factory.createPropertySignature( + undefined, + factory.createIdentifier(`"${name}"`), + undefined, + factory.createTypeReferenceNode( + factory.createIdentifier(subType), + undefined, + ), + ); + }), + ), + ); + }, + ), + ), + ].filter(Boolean) as ts.TypeNode[], ); - } else { - const [namespace, subTypeName] = typeNames[0].split(":"); - if (!subTypesMetadata?.[namespace]?.[subTypeName]) { - throw new Error("something went really wrong"); - } - - return new TypeLocation( - null, - subTypesMetadata[namespace][subTypeName].importTypeName, - ).toTypeReference(); } } From 47fdea2abe8527325053e7a83260fe5272b97544 Mon Sep 17 00:00:00 2001 From: Graphitation Service Account Date: Mon, 17 Mar 2025 13:09:38 +0000 Subject: [PATCH 07/12] applying package updates --- ...egen-0e9d9d1f-8328-4460-a942-8e88949c5eeb.json | 7 ------- packages/cli/CHANGELOG.json | 15 +++++++++++++++ packages/cli/package.json | 2 +- packages/ts-codegen/CHANGELOG.json | 15 +++++++++++++++ packages/ts-codegen/CHANGELOG.md | 10 +++++++++- packages/ts-codegen/package.json | 2 +- 6 files changed, 41 insertions(+), 10 deletions(-) delete mode 100644 change/@graphitation-ts-codegen-0e9d9d1f-8328-4460-a942-8e88949c5eeb.json diff --git a/change/@graphitation-ts-codegen-0e9d9d1f-8328-4460-a942-8e88949c5eeb.json b/change/@graphitation-ts-codegen-0e9d9d1f-8328-4460-a942-8e88949c5eeb.json deleted file mode 100644 index dda14d34c..000000000 --- a/change/@graphitation-ts-codegen-0e9d9d1f-8328-4460-a942-8e88949c5eeb.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "type": "prerelease", - "comment": "Return namespaced type", - "packageName": "@graphitation/ts-codegen", - "email": "77059398+vejrj@users.noreply.github.com", - "dependentChangeType": "none" -} diff --git a/packages/cli/CHANGELOG.json b/packages/cli/CHANGELOG.json index 9c54886a7..71bae68a1 100644 --- a/packages/cli/CHANGELOG.json +++ b/packages/cli/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@graphitation/cli", "entries": [ + { + "date": "Mon, 17 Mar 2025 13:09:38 GMT", + "version": "2.1.0-alpha.1", + "tag": "@graphitation/cli_v2.1.0-alpha.1", + "comments": { + "none": [ + { + "author": "beachball", + "package": "@graphitation/cli", + "comment": "Bump @graphitation/ts-codegen to v3.1.0-alpha.2", + "commit": "not available" + } + ] + } + }, { "date": "Tue, 04 Mar 2025 14:17:11 GMT", "version": "2.1.0-alpha.1", diff --git a/packages/cli/package.json b/packages/cli/package.json index b5f2de30a..534ee1560 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -24,7 +24,7 @@ }, "dependencies": { "@graphitation/supermassive-extractors": "^2.2.5", - "@graphitation/ts-codegen": "^3.1.0-alpha.1", + "@graphitation/ts-codegen": "^3.1.0-alpha.2", "commander": "^8.3.0", "fast-glob": "^3.2.12", "graphql": "^15.6.1" diff --git a/packages/ts-codegen/CHANGELOG.json b/packages/ts-codegen/CHANGELOG.json index f3dbc36b2..74793a3d1 100644 --- a/packages/ts-codegen/CHANGELOG.json +++ b/packages/ts-codegen/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@graphitation/ts-codegen", "entries": [ + { + "date": "Mon, 17 Mar 2025 13:09:38 GMT", + "version": "3.1.0-alpha.2", + "tag": "@graphitation/ts-codegen_v3.1.0-alpha.2", + "comments": { + "prerelease": [ + { + "author": "77059398+vejrj@users.noreply.github.com", + "package": "@graphitation/ts-codegen", + "commit": "f3a78cb45a5bc94c0309dd43a2c770e062344db4", + "comment": "Return namespaced type" + } + ] + } + }, { "date": "Tue, 04 Mar 2025 14:17:11 GMT", "version": "3.1.0-alpha.1", diff --git a/packages/ts-codegen/CHANGELOG.md b/packages/ts-codegen/CHANGELOG.md index 2f14e2d87..3367c5839 100644 --- a/packages/ts-codegen/CHANGELOG.md +++ b/packages/ts-codegen/CHANGELOG.md @@ -1,9 +1,17 @@ # Change Log - @graphitation/ts-codegen - + +## 3.1.0-alpha.2 + +Mon, 17 Mar 2025 13:09:38 GMT + +### Changes + +- Return namespaced type (77059398+vejrj@users.noreply.github.com) + ## 3.1.0-alpha.1 Tue, 04 Mar 2025 14:17:11 GMT diff --git a/packages/ts-codegen/package.json b/packages/ts-codegen/package.json index 3f56970ac..9cc18ed33 100644 --- a/packages/ts-codegen/package.json +++ b/packages/ts-codegen/package.json @@ -1,7 +1,7 @@ { "name": "@graphitation/ts-codegen", "license": "MIT", - "version": "3.1.0-alpha.1", + "version": "3.1.0-alpha.2", "main": "./src/index.ts", "repository": { "type": "git", From c9e29a0d662b1e728faf43ec341453dd54060a97 Mon Sep 17 00:00:00 2001 From: vejrj <77059398+vejrj@users.noreply.github.com> Date: Mon, 17 Mar 2025 15:33:55 +0100 Subject: [PATCH 08/12] bump --- ...phitation-cli-a3bfe129-5149-4216-90f3-7c64ce6b6f8c.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 change/@graphitation-cli-a3bfe129-5149-4216-90f3-7c64ce6b6f8c.json diff --git a/change/@graphitation-cli-a3bfe129-5149-4216-90f3-7c64ce6b6f8c.json b/change/@graphitation-cli-a3bfe129-5149-4216-90f3-7c64ce6b6f8c.json new file mode 100644 index 000000000..a03f3a7d6 --- /dev/null +++ b/change/@graphitation-cli-a3bfe129-5149-4216-90f3-7c64ce6b6f8c.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "Return namespaced type", + "packageName": "@graphitation/cli", + "email": "77059398+vejrj@users.noreply.github.com", + "dependentChangeType": "none" +} From 6cf10640582b2e77fc65a28351a8e38196eec316 Mon Sep 17 00:00:00 2001 From: Graphitation Service Account Date: Mon, 17 Mar 2025 14:45:57 +0000 Subject: [PATCH 09/12] applying package updates --- ...-cli-a3bfe129-5149-4216-90f3-7c64ce6b6f8c.json | 7 ------- packages/cli/CHANGELOG.json | 15 +++++++++++++++ packages/cli/CHANGELOG.md | 10 +++++++++- packages/cli/package.json | 2 +- 4 files changed, 25 insertions(+), 9 deletions(-) delete mode 100644 change/@graphitation-cli-a3bfe129-5149-4216-90f3-7c64ce6b6f8c.json diff --git a/change/@graphitation-cli-a3bfe129-5149-4216-90f3-7c64ce6b6f8c.json b/change/@graphitation-cli-a3bfe129-5149-4216-90f3-7c64ce6b6f8c.json deleted file mode 100644 index a03f3a7d6..000000000 --- a/change/@graphitation-cli-a3bfe129-5149-4216-90f3-7c64ce6b6f8c.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "type": "prerelease", - "comment": "Return namespaced type", - "packageName": "@graphitation/cli", - "email": "77059398+vejrj@users.noreply.github.com", - "dependentChangeType": "none" -} diff --git a/packages/cli/CHANGELOG.json b/packages/cli/CHANGELOG.json index 71bae68a1..ace7eb872 100644 --- a/packages/cli/CHANGELOG.json +++ b/packages/cli/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@graphitation/cli", "entries": [ + { + "date": "Mon, 17 Mar 2025 14:45:57 GMT", + "version": "2.1.0-alpha.2", + "tag": "@graphitation/cli_v2.1.0-alpha.2", + "comments": { + "prerelease": [ + { + "author": "77059398+vejrj@users.noreply.github.com", + "package": "@graphitation/cli", + "commit": "c9e29a0d662b1e728faf43ec341453dd54060a97", + "comment": "Return namespaced type" + } + ] + } + }, { "date": "Mon, 17 Mar 2025 13:09:38 GMT", "version": "2.1.0-alpha.1", diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 64ecae4ca..80abdd323 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,9 +1,17 @@ # Change Log - @graphitation/cli - + +## 2.1.0-alpha.2 + +Mon, 17 Mar 2025 14:45:57 GMT + +### Changes + +- Return namespaced type (77059398+vejrj@users.noreply.github.com) + ## 2.1.0-alpha.1 Tue, 04 Mar 2025 14:17:11 GMT diff --git a/packages/cli/package.json b/packages/cli/package.json index 534ee1560..de5352cb8 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,7 +1,7 @@ { "name": "@graphitation/cli", "license": "MIT", - "version": "2.1.0-alpha.1", + "version": "2.1.0-alpha.2", "bin": { "supermassive": "./bin/supermassive.js" }, From 7c44b873c4fe585465bcef72b08170c2940b5432 Mon Sep 17 00:00:00 2001 From: vejrj <77059398+vejrj@users.noreply.github.com> Date: Tue, 15 Apr 2025 14:52:46 +0200 Subject: [PATCH 10/12] Context metadata dump (#550) * Context metadata dump added --- ...-b111c7b3-ca76-4254-88e9-fe4a33820bfa.json | 7 + ...-170b132f-0c5e-4fe1-907a-624aa600af07.json | 7 + packages/cli/package.json | 2 +- .../ts-codegen/src/__tests__/context.test.ts | 153 +++++++++++++----- packages/ts-codegen/src/codegen.ts | 7 +- packages/ts-codegen/src/context/index.ts | 35 +++- packages/ts-codegen/src/context/utilities.ts | 98 +++++++++++ packages/ts-codegen/src/resolvers.ts | 6 + 8 files changed, 270 insertions(+), 45 deletions(-) create mode 100644 change/@graphitation-cli-b111c7b3-ca76-4254-88e9-fe4a33820bfa.json create mode 100644 change/@graphitation-ts-codegen-170b132f-0c5e-4fe1-907a-624aa600af07.json diff --git a/change/@graphitation-cli-b111c7b3-ca76-4254-88e9-fe4a33820bfa.json b/change/@graphitation-cli-b111c7b3-ca76-4254-88e9-fe4a33820bfa.json new file mode 100644 index 000000000..83e78dfe2 --- /dev/null +++ b/change/@graphitation-cli-b111c7b3-ca76-4254-88e9-fe4a33820bfa.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "Metadata dump added", + "packageName": "@graphitation/cli", + "email": "77059398+vejrj@users.noreply.github.com", + "dependentChangeType": "none" +} diff --git a/change/@graphitation-ts-codegen-170b132f-0c5e-4fe1-907a-624aa600af07.json b/change/@graphitation-ts-codegen-170b132f-0c5e-4fe1-907a-624aa600af07.json new file mode 100644 index 000000000..7fcb4e07d --- /dev/null +++ b/change/@graphitation-ts-codegen-170b132f-0c5e-4fe1-907a-624aa600af07.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "Metadata dump added", + "packageName": "@graphitation/ts-codegen", + "email": "77059398+vejrj@users.noreply.github.com", + "dependentChangeType": "none" +} diff --git a/packages/cli/package.json b/packages/cli/package.json index de5352cb8..5ca478680 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -24,7 +24,7 @@ }, "dependencies": { "@graphitation/supermassive-extractors": "^2.2.5", - "@graphitation/ts-codegen": "^3.1.0-alpha.2", + "@graphitation/ts-codegen": "^3.1.0-alpha.3", "commander": "^8.3.0", "fast-glob": "^3.2.12", "graphql": "^15.6.1" diff --git a/packages/ts-codegen/src/__tests__/context.test.ts b/packages/ts-codegen/src/__tests__/context.test.ts index c0d1db41a..2d535b6bf 100644 --- a/packages/ts-codegen/src/__tests__/context.test.ts +++ b/packages/ts-codegen/src/__tests__/context.test.ts @@ -127,21 +127,79 @@ describe(generateTS, () => { expect(contextMappingOutput).toMatchInlineSnapshot(` { "Message": { - "id": [ - "managers:message", - ], + "id": { + "managers": [ + "message", + ], + }, }, "User": { - "__context": [ - "managers:user", - ], - "id": [ - "managers:id-user", - "managers:user", - ], - "post": [ - "managers:post", - ], + "avatar": { + "managers": [ + "user", + ], + }, + "avatarRequired": { + "managers": [ + "user", + ], + }, + "id": { + "managers": [ + "id-user", + "user", + ], + }, + "messagesNonRequired": { + "managers": [ + "user", + ], + }, + "messagesOnlyMessageRequired": { + "managers": [ + "user", + ], + }, + "messagesRequired": { + "managers": [ + "user", + ], + }, + "messagesWithAnswersAllRequired": { + "managers": [ + "user", + ], + }, + "messagesWithAnswersNonRequired": { + "managers": [ + "user", + ], + }, + "messagesWithAnswersRequired": { + "managers": [ + "user", + ], + }, + "messagesWithArrayRequired": { + "managers": [ + "user", + ], + }, + "name": { + "managers": [ + "user", + ], + }, + "post": { + "managers": [ + "post", + ], + }, + "postRequired": { + "managers": [ + "user", + ], + }, }, } `); @@ -472,18 +530,25 @@ describe(generateTS, () => { expect(contextMappingOutput).toMatchInlineSnapshot(` { "Admin": { - "__context": [ - "managers:admin", - ], + "id": { + "managers": [ + "admin", + ], + }, + "rank": { + "managers": [ + "admin", + ], + }, }, "Node": { - "__context": [ - "managers:node", + "managers": [ + "node", ], }, "Persona": { - "__context": [ - "managers:persona", + "managers": [ + "persona", ], }, } @@ -630,13 +695,13 @@ describe(generateTS, () => { expect(contextMappingOutput).toMatchInlineSnapshot(` { "Customer": { - "__context": [ - "managers:customer", + "managers": [ + "customer", ], }, "Node": { - "__context": [ - "managers:node", + "managers": [ + "node", ], }, } @@ -824,31 +889,39 @@ describe(generateTS, () => { expect(contextMappingOutput).toMatchInlineSnapshot(` { "Admin": { - "__context": [ - "managers:admin", - ], + "id": { + "managers": [ + "admin", + ], + }, }, "CompanyOrCustomer": { - "__context": [ - "managers:company-or-customer", + "managers": [ + "company-or-customer", ], }, "Query": { - "userById": [ - "managers:whatever", - ], - "userByMail": [ - "managers:different-whatever", - ], + "userById": { + "managers": [ + "whatever", + ], + }, + "userByMail": { + "managers": [ + "different-whatever", + ], + }, }, "User": { - "__context": [ - "managers:user", - ], + "id": { + "managers": [ + "user", + ], + }, }, "UserOrCustomer": { - "__context": [ - "managers:user-or-customer", + "managers": [ + "user-or-customer", ], }, } diff --git a/packages/ts-codegen/src/codegen.ts b/packages/ts-codegen/src/codegen.ts index e989f0d13..7875af4c7 100644 --- a/packages/ts-codegen/src/codegen.ts +++ b/packages/ts-codegen/src/codegen.ts @@ -1,6 +1,6 @@ import ts from "typescript"; import { DocumentNode } from "graphql"; -import { ContextMap, extractContext } from "./context/index"; +import { extractContext } from "./context/index"; import { generateResolvers } from "./resolvers"; import { generateModels } from "./models"; import { generateLegacyTypes } from "./legacyTypes"; @@ -94,7 +94,7 @@ export function generateTS( }: GenerateTSOptions, ): { files: ts.SourceFile[]; - contextMappingOutput: ContextMap | null; + contextMappingOutput: any | null; } { try { const context = extractContext( @@ -140,9 +140,10 @@ export function generateTS( result.push(generateLegacyResolvers(context)); } } + return { files: result, - contextMappingOutput: context.getContextMap(), + contextMappingOutput: context.getMetadataObject(), }; } catch (e) { console.error(e); diff --git a/packages/ts-codegen/src/context/index.ts b/packages/ts-codegen/src/context/index.ts index 3d4aa28cd..00c8b0764 100644 --- a/packages/ts-codegen/src/context/index.ts +++ b/packages/ts-codegen/src/context/index.ts @@ -23,7 +23,10 @@ import ts, { SyntaxKind, } from "typescript"; import { DefinitionImport, DefinitionModel } from "../types"; -import { createImportDeclaration } from "./utilities"; +import { + createImportDeclaration, + buildContextMetadataOutput, +} from "./utilities"; import { createListType, createNonNullableType, @@ -104,6 +107,7 @@ export type ContextMapTypeItem = { __context?: string[] } & { }; export class TsCodegenContext { private allTypes: Array; + private resolverTypeMap: any; private typeContextMap: ContextMap; private typeNameToType: Map; private usedEntitiesInModels: Set; @@ -127,6 +131,7 @@ export class TsCodegenContext { constructor(private options: TsCodegenContextOptions) { this.allTypes = []; this.typeContextMap = {}; + this.resolverTypeMap = {}; this.typeNameToType = new Map(); this.usedEntitiesInModels = new Set(); this.usedEntitiesInResolvers = new Set(); @@ -298,6 +303,34 @@ export class TsCodegenContext { } } + getMetadataObject() { + if (!this.typeContextMap || !this.resolverTypeMap) { + return null; + } + + return buildContextMetadataOutput( + this.typeContextMap, + this.resolverTypeMap, + ); + } + + setResolverTypeMapItem(typeName: string, fieldName: string | null) { + if (fieldName === null) { + this.resolverTypeMap[typeName] = null; + return; + } + + if (!this.resolverTypeMap[typeName]) { + this.resolverTypeMap[typeName] = []; + } + + this.resolverTypeMap[typeName].push(fieldName); + } + + getResolverTypeMap() { + return this.resolverTypeMap; + } + cleanSubtypeImportName(subTypeImportIdentifier: string) { return subTypeImportIdentifier.split(/\.|\[/)[0]; } diff --git a/packages/ts-codegen/src/context/utilities.ts b/packages/ts-codegen/src/context/utilities.ts index a2f9d67ca..028287bc1 100644 --- a/packages/ts-codegen/src/context/utilities.ts +++ b/packages/ts-codegen/src/context/utilities.ts @@ -53,3 +53,101 @@ export function getRelativePath( return cleanRelativePath(path.relative(outputPath, modelFullPath)); } + +type MetadataItem = { [namespace: string]: string[] }; + +type RootResolersMetadata = { + [resolver: string]: MetadataItem; +}; + +type TypeMetadata = { + [typeName: string]: { [field: string]: MetadataItem }; +}; + +type OutputMetadata = RootResolersMetadata | TypeMetadata; + +export function buildContextMetadataOutput( + contextMap: any, + resolverTypeMap: any, +) { + const metadata: OutputMetadata = {}; + + for (const [key, values] of Object.entries( + resolverTypeMap as Record, + )) { + if (!contextMap[key]) { + continue; + } + + if (values === null) { + if (contextMap[key]?.__context) { + for (const contextValue of contextMap[key].__context) { + const [namespace, subTypeName] = contextValue.split(":"); + + if (!metadata[key]) { + metadata[key] = {}; + } + + if (!metadata[key][namespace]) { + metadata[key][namespace] = []; + } + + if (!Array.isArray(metadata[key][namespace])) { + throw Error("Invalid context metadata"); + } + + if (!metadata[key][namespace].includes(subTypeName)) { + metadata[key][namespace].push(subTypeName); + } + } + continue; + } + continue; + } + + for (const value of values) { + if (contextMap[key][value]) { + for (const typeValue of contextMap[key][value]) { + buildContextMetadataOutputItem(metadata, typeValue, key, value); + } + continue; + } else if (contextMap[key].__context) { + for (const contextValue of contextMap[key].__context) { + buildContextMetadataOutputItem(metadata, contextValue, key, value); + } + continue; + } + } + } + + return metadata; +} + +function buildContextMetadataOutputItem( + metadata: OutputMetadata, + contextKey: string, + key: string, + value: string, +) { + const [namespace, subTypeName] = contextKey.split(":"); + + if (!metadata[key]) { + metadata[key] = {}; + } + + if (!metadata[key][value]) { + metadata[key][value] = {}; + } + + if (Array.isArray(metadata[key][value])) { + throw Error("Invalid context metadata"); + } + + if (!metadata[key][value][namespace]) { + metadata[key][value][namespace] = []; + } + + if (!metadata[key][value][namespace].includes(subTypeName)) { + metadata[key][value][namespace].push(subTypeName); + } +} diff --git a/packages/ts-codegen/src/resolvers.ts b/packages/ts-codegen/src/resolvers.ts index 8b89bc7e7..5c1b58f97 100644 --- a/packages/ts-codegen/src/resolvers.ts +++ b/packages/ts-codegen/src/resolvers.ts @@ -283,6 +283,8 @@ function createResolverField( } } + context.setResolverTypeMapItem(type.name, field.name); + const resolverParametersDefinitions = { parent: { name: "model", @@ -363,6 +365,8 @@ function createUnionTypeResolvers( const contextTypes = context.getContextTypes(contextRootType); + context.setResolverTypeMapItem(type.name, null); + return factory.createModuleDeclaration( [ factory.createModifier(ts.SyntaxKind.ExportKeyword), @@ -393,6 +397,8 @@ function createInterfaceTypeResolvers( const contextRootType = context.getContextMap()[type.name]; const contextTypes = context.getContextTypes(contextRootType); + context.setResolverTypeMapItem(type.name, null); + const resolversObject = factory.createInterfaceDeclaration( [factory.createModifier(ts.SyntaxKind.ExportKeyword)], factory.createIdentifier("Resolvers"), From c1442da061c6c0ab6fc76768f55c17a7a7ce9161 Mon Sep 17 00:00:00 2001 From: vejrj <77059398+vejrj@users.noreply.github.com> Date: Tue, 15 Apr 2025 15:11:04 +0200 Subject: [PATCH 11/12] fix --- ...phitation-cli-b111c7b3-ca76-4254-88e9-fe4a33820bfa.json | 7 ------- packages/cli/package.json | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) delete mode 100644 change/@graphitation-cli-b111c7b3-ca76-4254-88e9-fe4a33820bfa.json diff --git a/change/@graphitation-cli-b111c7b3-ca76-4254-88e9-fe4a33820bfa.json b/change/@graphitation-cli-b111c7b3-ca76-4254-88e9-fe4a33820bfa.json deleted file mode 100644 index 83e78dfe2..000000000 --- a/change/@graphitation-cli-b111c7b3-ca76-4254-88e9-fe4a33820bfa.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "type": "prerelease", - "comment": "Metadata dump added", - "packageName": "@graphitation/cli", - "email": "77059398+vejrj@users.noreply.github.com", - "dependentChangeType": "none" -} diff --git a/packages/cli/package.json b/packages/cli/package.json index 5ca478680..de5352cb8 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -24,7 +24,7 @@ }, "dependencies": { "@graphitation/supermassive-extractors": "^2.2.5", - "@graphitation/ts-codegen": "^3.1.0-alpha.3", + "@graphitation/ts-codegen": "^3.1.0-alpha.2", "commander": "^8.3.0", "fast-glob": "^3.2.12", "graphql": "^15.6.1" From 7488d6d7930771a2dc10ff5e4921b3033a0c7583 Mon Sep 17 00:00:00 2001 From: Graphitation Service Account Date: Tue, 15 Apr 2025 13:35:07 +0000 Subject: [PATCH 12/12] applying package updates --- ...egen-170b132f-0c5e-4fe1-907a-624aa600af07.json | 7 ------- packages/cli/CHANGELOG.json | 15 +++++++++++++++ packages/cli/package.json | 2 +- packages/ts-codegen/CHANGELOG.json | 15 +++++++++++++++ packages/ts-codegen/CHANGELOG.md | 10 +++++++++- packages/ts-codegen/package.json | 2 +- 6 files changed, 41 insertions(+), 10 deletions(-) delete mode 100644 change/@graphitation-ts-codegen-170b132f-0c5e-4fe1-907a-624aa600af07.json diff --git a/change/@graphitation-ts-codegen-170b132f-0c5e-4fe1-907a-624aa600af07.json b/change/@graphitation-ts-codegen-170b132f-0c5e-4fe1-907a-624aa600af07.json deleted file mode 100644 index 7fcb4e07d..000000000 --- a/change/@graphitation-ts-codegen-170b132f-0c5e-4fe1-907a-624aa600af07.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "type": "prerelease", - "comment": "Metadata dump added", - "packageName": "@graphitation/ts-codegen", - "email": "77059398+vejrj@users.noreply.github.com", - "dependentChangeType": "none" -} diff --git a/packages/cli/CHANGELOG.json b/packages/cli/CHANGELOG.json index ace7eb872..96ad29a6c 100644 --- a/packages/cli/CHANGELOG.json +++ b/packages/cli/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@graphitation/cli", "entries": [ + { + "date": "Tue, 15 Apr 2025 13:35:07 GMT", + "version": "2.1.0-alpha.2", + "tag": "@graphitation/cli_v2.1.0-alpha.2", + "comments": { + "none": [ + { + "author": "beachball", + "package": "@graphitation/cli", + "comment": "Bump @graphitation/ts-codegen to v3.1.0-alpha.3", + "commit": "not available" + } + ] + } + }, { "date": "Mon, 17 Mar 2025 14:45:57 GMT", "version": "2.1.0-alpha.2", diff --git a/packages/cli/package.json b/packages/cli/package.json index de5352cb8..5ca478680 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -24,7 +24,7 @@ }, "dependencies": { "@graphitation/supermassive-extractors": "^2.2.5", - "@graphitation/ts-codegen": "^3.1.0-alpha.2", + "@graphitation/ts-codegen": "^3.1.0-alpha.3", "commander": "^8.3.0", "fast-glob": "^3.2.12", "graphql": "^15.6.1" diff --git a/packages/ts-codegen/CHANGELOG.json b/packages/ts-codegen/CHANGELOG.json index 74793a3d1..c55720295 100644 --- a/packages/ts-codegen/CHANGELOG.json +++ b/packages/ts-codegen/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@graphitation/ts-codegen", "entries": [ + { + "date": "Tue, 15 Apr 2025 13:35:07 GMT", + "version": "3.1.0-alpha.3", + "tag": "@graphitation/ts-codegen_v3.1.0-alpha.3", + "comments": { + "prerelease": [ + { + "author": "77059398+vejrj@users.noreply.github.com", + "package": "@graphitation/ts-codegen", + "commit": "7c44b873c4fe585465bcef72b08170c2940b5432", + "comment": "Metadata dump added" + } + ] + } + }, { "date": "Mon, 17 Mar 2025 13:09:38 GMT", "version": "3.1.0-alpha.2", diff --git a/packages/ts-codegen/CHANGELOG.md b/packages/ts-codegen/CHANGELOG.md index 3367c5839..c3cd5a8bd 100644 --- a/packages/ts-codegen/CHANGELOG.md +++ b/packages/ts-codegen/CHANGELOG.md @@ -1,9 +1,17 @@ # Change Log - @graphitation/ts-codegen - + +## 3.1.0-alpha.3 + +Tue, 15 Apr 2025 13:35:07 GMT + +### Changes + +- Metadata dump added (77059398+vejrj@users.noreply.github.com) + ## 3.1.0-alpha.2 Mon, 17 Mar 2025 13:09:38 GMT diff --git a/packages/ts-codegen/package.json b/packages/ts-codegen/package.json index 9cc18ed33..a78de2e57 100644 --- a/packages/ts-codegen/package.json +++ b/packages/ts-codegen/package.json @@ -1,7 +1,7 @@ { "name": "@graphitation/ts-codegen", "license": "MIT", - "version": "3.1.0-alpha.2", + "version": "3.1.0-alpha.3", "main": "./src/index.ts", "repository": { "type": "git",