Repository: strapi/strapi
File: packages/plugins/graphql/server/src/services/builders/resolvers/association.ts (TypeScript)

Code before:
        const transformedArgs = transformArgs(args, {
          contentType: targetContentType,
          usePagination: true,
        });

        await strapi.contentAPI.validate.query(transformedArgs, targetContentType, {
          auth,
        });

        const sanitizedQuery = await strapi.contentAPI.sanitize.query(
          transformedArgs,
          targetContentType,
          {
            auth,
          }
        );
        const transformedQuery = strapi.get('query-params').transform(targetUID, sanitizedQuery);

        const defaultFilters = {
          where: {
            publishedAt: {
              $notNull: context.rootQueryArgs?.status
                ? // Filter by the same status as the root query if the argument is present
                  context.rootQueryArgs?.status === 'published'
                : // Otherwise fallback to the published version
                  true,
            },
          },
        };
        const dbQuery = merge(defaultFilters, transformedQuery);

        const data = await strapi.db?.query(contentTypeUID).load(parent, attributeName, dbQuery);

        const info = {
          args: sanitizedQuery,
          resourceUID: targetUID,
        };

        // If this a polymorphic association, it sanitizes & returns the raw data
        // Note: The value needs to be wrapped in a fake object that represents its parent
        // so that the sanitize util can work properly.
        if (isMorphAttribute) {
          // Helpers used for the data cleanup
          const wrapData = (dataToWrap: any) => ({ [attributeName]: dataToWrap });
          const sanitizeData = (dataToSanitize: any) => {
            return strapi.contentAPI.sanitize.output(dataToSanitize, contentType, { auth });
          };
          const unwrapData = get(attributeName);

          // Sanitizer definition
          const sanitizeMorphAttribute = async.pipe(wrapData, sanitizeData, unwrapData);

Review comment (suggestion):
I can see some users wanting to only select published items at the top level, but include the draft relations in children.

So I think we should use:

local arg if present -> rootArg if present -> published by default

Code after:
        const transformedArgs = transformArgs(args, {
          contentType: targetContentType,
          usePagination: true,
        });

        await strapi.contentAPI.validate.query(transformedArgs, targetContentType, {
          auth,
        });

        const sanitizedQuery = await strapi.contentAPI.sanitize.query(
          transformedArgs,
          targetContentType,
          {
            auth,
          }
        );
        const transformedQuery = strapi.get('query-params').transform(targetUID, sanitizedQuery);

        const isTargetDraftAndPublishContentType =
          contentTypes.hasDraftAndPublish(targetContentType);
        const defaultFilters = isTargetDraftAndPublishContentType
          ? {
              where: {
                publishedAt: {
                  $notNull: context.rootQueryArgs?.status
                    ? // Filter by the same status as the root query if the argument is present
                      context.rootQueryArgs?.status === 'published'
                    : // Otherwise fallback to the published version
                      true,
                },
              },
            }
          : {};

        const dbQuery = merge(defaultFilters, transformedQuery);
        const data = await strapi.db?.query(contentTypeUID).load(parent, attributeName, dbQuery);

        const info = {
          args: sanitizedQuery,
          resourceUID: targetUID,
        };

        // If this a polymorphic association, it sanitizes & returns the raw data
        // Note: The value needs to be wrapped in a fake object that represents its parent
        // so that the sanitize util can work properly.
        if (isMorphAttribute) {
          // Helpers used for the data cleanup
          const wrapData = (dataToWrap: any) => ({ [attributeName]: dataToWrap });
          const sanitizeData = (dataToSanitize: any) => {
            return strapi.contentAPI.sanitize.output(dataToSanitize, contentType, { auth });
          };