Skip to content

documentsReadOnly implemented#10659

Open
ikusakov2 wants to merge 5 commits intodotansimha:masterfrom
ikusakov2:feature/documentsReadOnly
Open

documentsReadOnly implemented#10659
ikusakov2 wants to merge 5 commits intodotansimha:masterfrom
ikusakov2:feature/documentsReadOnly

Conversation

@ikusakov2
Copy link
Copy Markdown
Contributor

Description

documentsReadOnly implemented, for safe handling of fragment includes between packages in the monorepo

Related # (10658)[https://github.com//issues/10658]

Type of change

  • New feature (non-breaking change which adds functionality)

How Has This Been Tested?

  • Unit testing

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 31, 2026

🦋 Changeset detected

Latest commit: 819cf71

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 7 packages
Name Type
@graphql-codegen/testing Minor
@graphql-codegen/gql-tag-operations Minor
@graphql-codegen/visitor-plugin-common Minor
@graphql-codegen/typescript-operations Minor
@graphql-codegen/plugin-helpers Minor
@graphql-codegen/cli Minor
@graphql-codegen/client-preset Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@eddeee888 eddeee888 force-pushed the feature/documentsReadOnly branch from c88a311 to 3005df7 Compare April 3, 2026 09:14
throw error;
const readOnlyHash = JSON.stringify(readOnlyPointerMap);
const outputDocumentsReadOnly = await cache(
'documents',
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A readonly document is also just a document for hashing purposes.
This ensures there is only one document in the final merged array, because we use the hash to detect the file uniqueness


async loadDocuments(pointer: Types.OperationDocument[]): Promise<Types.DocumentFile[]> {
async loadDocuments(
pointer: UnnormalizedTypeDefPointer,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only caller of this function will be passing in UnnormalizedTypeDefPointer, and nothing else. May as well narrow the type to make it easier to code.

Comment on lines -505 to -515
function hashDocument(doc: Types.DocumentFile) {
if (doc.rawSDL) {
return hashContent(doc.rawSDL);
}
async function addHashToDocumentFiles(
documentFilesPromise: Promise<Source[]>,
type: 'standard' | 'read-only',
): Promise<Types.DocumentFile[]> {
function hashDocument(doc: Source) {
if (doc.rawSDL) {
return hashContent(doc.rawSDL);
}

if (doc.document) {
return hashContent(print(doc.document));
}
if (doc.document) {
return hashContent(print(doc.document));
}

return null;
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hashDocument is is only used by one function, so I moved it inline to avoid jumping around.

documentPointers: UnnormalizedTypeDefPointer | UnnormalizedTypeDefPointer[],
config: Types.Config,
): Promise<Types.DocumentFile[]> {
): Promise<Source[]> {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When this function finishes, we'd only get the base Source. Types.DocumentFile is what we get after processing the Source (adding hash and type)

);

return newDocuments.map((document, index) => ({
...documents[index],
Copy link
Copy Markdown
Collaborator

@eddeee888 eddeee888 Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Context for future me:

Previously we throw away hash when optimising the doc.
When we introduce type (read-only or standard), we need it for further processing, so we need to keep it like this.

Maybe we should not just add these custom Codegen meta directly to the node, since optimizeDocuments implementation may remove it in the future.

Maybe we can add a special key/value to reduce this risk e.g. __meta: { hash: 'abc', types: 'standard' } 🤔

Comment on lines +37 to +38
hash: string;
type: 'standard' | 'read-only';
Copy link
Copy Markdown
Collaborator

@eddeee888 eddeee888 Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Source is the default from parsing the docs.
DocumentFile is the "processed" source, with Codegen metadata.

We may want to group them to avoid edge cases mentioned in: https://github.com/dotansimha/graphql-code-generator/pull/10659/changes#r3032421307

- Flow documentsReadOnly to typescript-operations
- Set up documents-readonly dev-test
- Update dev-tests output
- Merge standard and read-only documents
- Fix Source vs Types.DocumentFile usage for type correctness
@eddeee888 eddeee888 force-pushed the feature/documentsReadOnly branch from 8f4ba67 to df25ba7 Compare April 3, 2026 10:55
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documents now have type being 'standard' | 'read-only'.
If we don't supply that, the plugin will generate nothing.

This utility helps by creating Types.DocumentFile with hash and type hardcoded. If we need to make the params partial with override in the future, we could,.

@eddeee888 eddeee888 force-pushed the feature/documentsReadOnly branch from 631abbd to 40f5ca8 Compare April 4, 2026 02:59
@eddeee888 eddeee888 force-pushed the feature/documentsReadOnly branch from 40f5ca8 to 819cf71 Compare April 4, 2026 02:59
Comment on lines +324 to +336
const populateDocumentPointerMap = (
allDocumentsDenormalizedPointers: Types.OperationDocument[],
): UnnormalizedTypeDefPointer => {
const pointer: UnnormalizedTypeDefPointer = {};
for (const denormalizedPtr of allDocumentsDenormalizedPointers) {
if (typeof denormalizedPtr === 'string') {
pointer[denormalizedPtr] = {};
} else if (typeof denormalizedPtr === 'object') {
Object.assign(pointer, denormalizedPtr);
}
}
return pointer;
};
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inlining populateDocumentPointerMap makes it a bit easier to read as we don't jump around the file. We could take this pure function and put it at the bottom of the file if needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants