From d7974f24ba36c2d0e82623e73c8acb7e98649d29 Mon Sep 17 00:00:00 2001 From: Carson Full Date: Fri, 1 Mar 2024 11:59:54 -0600 Subject: [PATCH 1/3] Adjust EdgeDB QB gen to create immutable types --- src/core/edgedb/generator/query-builder.ts | 35 ++++++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/src/core/edgedb/generator/query-builder.ts b/src/core/edgedb/generator/query-builder.ts index 8290009901..7c0ce24f07 100644 --- a/src/core/edgedb/generator/query-builder.ts +++ b/src/core/edgedb/generator/query-builder.ts @@ -1,6 +1,7 @@ import { generateQueryBuilder as runQueryBuilderGenerator } from '@edgedb/generate/dist/edgeql-js.js'; import { groupBy } from '@seedcompany/common'; -import { Directory } from 'ts-morph'; +import type { ts } from '@ts-morph/common'; +import { Directory, Node } from 'ts-morph'; import { codecs } from '../codecs'; import { customScalars } from './scalars'; import { addCustomScalarImports, GeneratorParams } from './util'; @@ -28,6 +29,7 @@ export async function generateQueryBuilder({ updateCastMapsForOurCustomScalars(qbDir); changeImplicitIDType(qbDir); allowOrderingByEnums(qbDir); + adjustToImmutableTypes(qbDir); } function addJsExtensionDeepPathsOfEdgedbLibrary(qbDir: Directory) { @@ -58,8 +60,8 @@ function changeImplicitIDType(qbDir: Directory) { // Change implicit return shapes that are just the id to be ID type. const typesystem = qbDir.addSourceFileAtPath(`typesystem.ts`); addCustomScalarImports(typesystem, [customScalars.get('ID')!]); - typesystem.replaceWithText( - typesystem.getFullText().replaceAll('{ id: string }', '{ id: ID }'), + replaceText(typesystem, (prev) => + prev.replaceAll('{ id: string }', '{ id: ID }'), ); } @@ -121,3 +123,30 @@ function allowOrderingByEnums(qbDir: Directory) { .setType('TypeSet'); file.fixMissingImports(); } + +function adjustToImmutableTypes(qbDir: Directory) { + const typesystem = qbDir.addSourceFileAtPath('typesystem.ts'); + replaceText(typesystem.getTypeAliasOrThrow('ArrayTypeToTsType'), (prev) => + prev.replace(': TsType[]', ': readonly TsType[]'), + ); + replaceText( + typesystem.getTypeAliasOrThrow('NamedTupleTypeToTsType'), + (prev) => prev.replace('[k in ', 'readonly [/* applied */ k in '), + ); + replaceText(typesystem.getTypeAliasOrThrow('computeObjectShape'), (prev) => + !prev.includes('> = typeutil') + ? prev + : prev.replaceAll('> = typeutil', '> = Readonly;', + ); + replaceText(typesystem.getTypeAliasOrThrow('computeTsTypeCard'), (prev) => + prev + .replaceAll('? T[]', '? readonly T[]') + .replaceAll('? [T, ...T[]]', '? readonly [T, ...T[]]'), + ); +} + +const replaceText = ( + node: Node, + replacer: (prevText: string) => string, +) => node.replaceWithText(replacer(node.getFullText())); From 7fcb45cc035938b2d0565f5418bd70b72639d61e Mon Sep 17 00:00:00 2001 From: Carson Full Date: Mon, 4 Mar 2024 11:22:10 -0600 Subject: [PATCH 2/3] Adjust EdgeDB query files & inline queries to create immutable types --- package.json | 4 ++-- src/core/edgedb/generator/inline-queries.ts | 3 ++- src/core/edgedb/generator/query-files.ts | 26 +++++++++++++++++++-- yarn.lock | 20 ++++++++-------- 4 files changed, 38 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 8f3bdf0e0a..f4744800b8 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "cypher-query-builder": "patch:cypher-query-builder@6.0.4#.yarn/patches/cypher-query-builder.patch", "dotenv": "^16.3.1", "dotenv-expand": "^10.0.0", - "edgedb": "^1.5.0-canary.20240301T204406", + "edgedb": "^1.5.0-canary.20240320T135030", "execa": "^8.0.1", "express": "^4.18.2", "extensionless": "^1.7.0", @@ -104,7 +104,7 @@ "yaml": "^2.3.3" }, "devDependencies": { - "@edgedb/generate": "^0.5.0-canary.20240319T205924", + "@edgedb/generate": "^0.5.0-canary.20240320T135053", "@nestjs/cli": "^10.2.1", "@nestjs/schematics": "^10.0.3", "@nestjs/testing": "^10.2.7", diff --git a/src/core/edgedb/generator/inline-queries.ts b/src/core/edgedb/generator/inline-queries.ts index b18781c5f8..456fedc9cc 100644 --- a/src/core/edgedb/generator/inline-queries.ts +++ b/src/core/edgedb/generator/inline-queries.ts @@ -4,6 +4,7 @@ import { Cardinality } from 'edgedb/dist/ifaces.js'; import { $ as $$ } from 'execa'; import { Node, SyntaxKind, VariableDeclarationKind } from 'ts-morph'; import { injectHydrators } from './inject-hydrators'; +import { analyzeQuery } from './query-files'; import { customScalars } from './scalars'; import { addCustomScalarImports, GeneratorParams } from './util'; @@ -88,7 +89,7 @@ export async function generateInlineQueries({ try { const injectedQuery = injectHydrators(query, hydrators); - types = await $.analyzeQuery(client, injectedQuery); + types = await analyzeQuery(client, injectedQuery); console.log(` ${source}`); } catch (err) { error = err as Error; diff --git a/src/core/edgedb/generator/query-files.ts b/src/core/edgedb/generator/query-files.ts index 47f2e0b3bb..f69597734f 100644 --- a/src/core/edgedb/generator/query-files.ts +++ b/src/core/edgedb/generator/query-files.ts @@ -3,7 +3,7 @@ import { generateFiles, stringifyImports, } from '@edgedb/generate/dist/queries.js'; -import { $, adapter } from 'edgedb'; +import { $, adapter, Client } from 'edgedb'; import { Directory } from 'ts-morph'; import { ScalarInfo } from '../codecs'; import { injectHydrators } from './inject-hydrators'; @@ -31,7 +31,7 @@ const generateFilesForQuery = const injectedQuery = injectHydrators(query, hydrators); - const types = await $.analyzeQuery(client, injectedQuery); + const types = await analyzeQuery(client, injectedQuery); const [{ imports, contents }] = generateFiles({ target: 'ts', path, @@ -78,3 +78,25 @@ adapter.fs.writeFile = new Proxy(adapter.fs.writeFile, { return Reflect.apply(target, thisArg, [path, content]); }, }); + +/** + * Same thing as what upstream function does, just with readonly on the output type. + */ +export async function analyzeQuery(client: Client, query: string) { + const { cardinality, in: inCodec, out: outCodec } = await client.parse(query); + const args = $.generateTSTypeFromCodec(inCodec, $.Cardinality.One, { + readonly: true, + optionalNulls: true, + }); + const result = $.generateTSTypeFromCodec(outCodec, cardinality, { + readonly: true, + optionalNulls: false, + }); + return { + result: result.type, + args: args.type, + cardinality, + query, + imports: new Set([...args.imports, ...result.imports]), + }; +} diff --git a/yarn.lock b/yarn.lock index b2e3f1549c..1f5a1f482c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1475,14 +1475,14 @@ __metadata: languageName: node linkType: hard -"@edgedb/generate@npm:^0.5.0-canary.20240319T205924": - version: 0.5.0-canary.20240319T205924 - resolution: "@edgedb/generate@npm:0.5.0-canary.20240319T205924" +"@edgedb/generate@npm:^0.5.0-canary.20240320T135053": + version: 0.5.0-canary.20240320T135053 + resolution: "@edgedb/generate@npm:0.5.0-canary.20240320T135053" peerDependencies: edgedb: ^1.4.0 bin: generate: dist/cli.js - checksum: 10c0/88ef9634e4e974a0a5c65f561d6040323cc1df7113d2fdb952da93685eaad54f619516c0dd8b02962bb2b11bb9b841c61cb26455a6188e964d0cbf1ca2f46b96 + checksum: 10c0/045a9356a7cd1a82fa20ead47ee4a65f13f2adbf779e80a12518f06be6d6196ebae20ef26285e3eade0b300b2b18fefa642b662371dba02719b1dbb6149ae3e9 languageName: node linkType: hard @@ -5311,7 +5311,7 @@ __metadata: "@apollo/subgraph": "npm:^2.5.6" "@aws-sdk/client-s3": "npm:^3.440.0" "@aws-sdk/s3-request-presigner": "npm:^3.440.0" - "@edgedb/generate": "npm:^0.5.0-canary.20240319T205924" + "@edgedb/generate": "npm:^0.5.0-canary.20240320T135053" "@faker-js/faker": "npm:^8.2.0" "@ffprobe-installer/ffprobe": "npm:^2.1.2" "@golevelup/nestjs-discovery": "npm:^4.0.0" @@ -5363,7 +5363,7 @@ __metadata: debugger-is-attached: "npm:^1.2.0" dotenv: "npm:^16.3.1" dotenv-expand: "npm:^10.0.0" - edgedb: "npm:^1.5.0-canary.20240301T204406" + edgedb: "npm:^1.5.0-canary.20240320T135030" eslint: "npm:^8.52.0" eslint-plugin-no-only-tests: "npm:^3.1.0" eslint-plugin-typescript-sort-keys: "npm:^2.3.0" @@ -5948,12 +5948,12 @@ __metadata: languageName: node linkType: hard -"edgedb@npm:^1.5.0-canary.20240301T204406": - version: 1.5.0-canary.20240301T204406 - resolution: "edgedb@npm:1.5.0-canary.20240301T204406" +"edgedb@npm:^1.5.0-canary.20240320T135030": + version: 1.5.0-canary.20240320T135030 + resolution: "edgedb@npm:1.5.0-canary.20240320T135030" bin: edgeql-js: dist/cli.js - checksum: 10c0/69de2bdc00f23ba2e4079d12a45830cd8565930de8664a5ddb273370e0707711720e454d108d889014f8cb1dba9cf357caa8cc2397b5472fe4a247d968758498 + checksum: 10c0/393d87a24c9cac4a1c5e62d5046306cd95b8520ceec70eb66047691301bb3ed729aacee1f1967b2c4ebac0380e586048c74ab140c008e806bccb4e7b554af63f languageName: node linkType: hard From b9401d8775968b02387c43cad1858f7a85ace631 Mon Sep 17 00:00:00 2001 From: Carson Full Date: Wed, 20 Mar 2024 09:17:11 -0500 Subject: [PATCH 3/3] Update inline queries gen for upstream change to map cardinality --- src/core/edgedb/generator/inline-queries.ts | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/core/edgedb/generator/inline-queries.ts b/src/core/edgedb/generator/inline-queries.ts index 456fedc9cc..75a7a2a40f 100644 --- a/src/core/edgedb/generator/inline-queries.ts +++ b/src/core/edgedb/generator/inline-queries.ts @@ -1,6 +1,5 @@ import { stripIndent } from 'common-tags'; import { $, adapter } from 'edgedb'; -import { Cardinality } from 'edgedb/dist/ifaces.js'; import { $ as $$ } from 'execa'; import { Node, SyntaxKind, VariableDeclarationKind } from 'ts-morph'; import { injectHydrators } from './inject-hydrators'; @@ -100,7 +99,7 @@ export async function generateInlineQueries({ // Save cardinality & hydrated query for use at runtime. queryMap.set(stripIndent(query), { query: injectHydrators(query, hydrators), - cardinality: cardinalityMapping[types.cardinality], + cardinality: types.cardinality, }); // Add imports to the used imports list [...types.imports].forEach((i) => imports.add(i)); @@ -143,11 +142,3 @@ export async function generateInlineQueries({ ], }); } - -const cardinalityMapping = { - [Cardinality.NO_RESULT]: $.Cardinality.Empty, - [Cardinality.AT_MOST_ONE]: $.Cardinality.AtMostOne, - [Cardinality.ONE]: $.Cardinality.One, - [Cardinality.MANY]: $.Cardinality.Many, - [Cardinality.AT_LEAST_ONE]: $.Cardinality.AtLeastOne, -};