gatsby-source-wordpress
Version:
Source data from WordPress in an efficient and scalable way.
299 lines (287 loc) • 12.3 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.default = void 0;
var _recursivelyTransformFields = _interopRequireWildcard(require("./recursively-transform-fields"));
var _buildQueryOnFieldName = require("./build-query-on-field-name");
var _store = require("../../../store");
var _helpers = require("../../create-schema-customization/helpers");
var _prettier = _interopRequireDefault(require("prettier"));
var _formatLogMessage = require("../../../utils/format-log-message");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
const recursivelyAliasFragments = field => field.inlineFragments.map(fragment => {
// for each of this inlineFragments fields
fragment.fields = fragment.fields.map(fragmentField => {
if (typeof fragmentField === `string`) {
return fragmentField;
}
// compare it against each field of each other fragment
let updatedFragmentField = fragmentField;
field.inlineFragments.forEach(possiblyConflictingFragment => {
// don't compare this fragment against itself
if (possiblyConflictingFragment.name === fragment.name) {
return;
}
possiblyConflictingFragment.fields.forEach(possiblyConflictingField => {
var _possiblyConflictingF, _fragmentField$fieldT, _possiblyConflictingF2, _fragmentField$fieldT2;
const fieldNamesMatch = fragmentField.fieldName === possiblyConflictingField.fieldName;
const fieldTypeKindsDontMatch = (possiblyConflictingField === null || possiblyConflictingField === void 0 ? void 0 : (_possiblyConflictingF = possiblyConflictingField.fieldType) === null || _possiblyConflictingF === void 0 ? void 0 : _possiblyConflictingF.kind) !== (fragmentField === null || fragmentField === void 0 ? void 0 : (_fragmentField$fieldT = fragmentField.fieldType) === null || _fragmentField$fieldT === void 0 ? void 0 : _fragmentField$fieldT.kind);
const fieldTypeNamesDontMatch = (possiblyConflictingField === null || possiblyConflictingField === void 0 ? void 0 : (_possiblyConflictingF2 = possiblyConflictingField.fieldType) === null || _possiblyConflictingF2 === void 0 ? void 0 : _possiblyConflictingF2.name) !== (fragmentField === null || fragmentField === void 0 ? void 0 : (_fragmentField$fieldT2 = fragmentField.fieldType) === null || _fragmentField$fieldT2 === void 0 ? void 0 : _fragmentField$fieldT2.name);
// if the fields have the same name but a different type kind
// alias them
if (fieldNamesMatch && (fieldTypeKindsDontMatch || fieldTypeNamesDontMatch)) {
const autoAliasedFieldName = `${fragmentField.fieldName}__typename_${fragmentField.fieldType.name}: ${fragmentField.fieldName}`;
updatedFragmentField = {
...fragmentField,
fieldName: autoAliasedFieldName
};
return;
}
});
});
// if the fields have the same name but a different type AND the field has sub fields, compare those sub fields against any fragment fields subfields where the field name matches
// if any subfields have conflicting types, alias them
if (updatedFragmentField.inlineFragments) {
updatedFragmentField.inlineFragments = recursivelyAliasFragments(updatedFragmentField);
}
return updatedFragmentField;
});
return fragment;
});
const aliasConflictingFieldFields = field => {
// we only have conflicting fields in inlineFragments
// if there are no inlineFragments, do nothing
if (!field.inlineFragments) {
return field;
}
field.inlineFragments = recursivelyAliasFragments(field);
if (field.fields) {
field.fields = aliasConflictingFields({
transformedFields: field.fields
});
}
return field;
};
const aliasConflictingFields = ({
transformedFields
}) => transformedFields.map(aliasConflictingFieldFields);
const aliasConflictingFragmentFields = ({
fragments
}) => {
for (const [fragmentKey, fragment] of Object.entries(fragments)) {
const aliasedFragment = aliasConflictingFieldFields(fragment);
fragments[fragmentKey] = aliasedFragment;
}
};
/**
* generateNodeQueriesFromIngestibleFields
*
* Takes in data from an introspection query and
* processes it to build GraphQL query strings/info
*
* @param {object} introspectionData
* @returns {Object} GraphQL query info including gql query strings
*/
const generateNodeQueriesFromIngestibleFields = async () => {
const {
remoteSchema,
gatsbyApi: {
helpers: {
reporter
},
pluginOptions: {
debug: {
graphql: {
copyNodeSourcingQueryAndExit
}
}
}
}
} = (0, _store.getStore)().getState();
const {
fieldBlacklist,
nodeListFilter,
typeMap,
ingestibles: {
nodeListRootFields
}
} = remoteSchema;
const rootFields = typeMap.get(`RootQuery`).fields;
const nodeQueries = {};
for (const {
type,
name
} of nodeListRootFields) {
if (fieldBlacklist.includes(name)) {
continue;
}
// nested fields
const fieldFields = typeMap.get(type.name).fields;
// a nested field containing a list of nodes
const nodesField = fieldFields.find(nodeListFilter);
// the type of this query
const nodesType = typeMap.get((0, _helpers.findNamedTypeName)(nodesField.type));
if (!nodesType) {
reporter.panic((0, _formatLogMessage.formatLogMessage)(`Couldn't infer node type in the remote schema from the ${name} root field.`));
}
const {
fields,
possibleTypes
} = nodesType;
const settings = (0, _helpers.getTypeSettingsByType)(nodesType);
if (settings.exclude) {
continue;
}
let nodeListQueries = [];
const singleNodeRootFieldInfo = rootFields.find(field => field.type.name === nodesType.name);
if (!singleNodeRootFieldInfo) {
// @todo handle cases where there is a nodelist field but no individual field. we can't do data updates or preview on this type.
reporter.warn((0, _formatLogMessage.formatLogMessage)(`Unable to find a single Node query for ${nodesType.name}\n\tThis type will not be available in Gatsby.\n`));
continue;
}
const fragments = {};
const singleFieldName = singleNodeRootFieldInfo === null || singleNodeRootFieldInfo === void 0 ? void 0 : singleNodeRootFieldInfo.name;
const transformedFields = (0, _recursivelyTransformFields.default)({
fields,
fragments,
parentType: type,
mainType: type
});
// we need this for node interface types on the WPGQL side
transformedFields.push(`__typename`);
let transformedInlineFragments;
if (possibleTypes) {
transformedInlineFragments = (0, _recursivelyTransformFields.transformInlineFragments)({
possibleTypes,
fragments,
parentType: nodesType,
mainType: nodesType,
debug: true,
// normally we only want the id for gatsby node fields
// but in this case we're at the top level and need to query
// these fields
buildGatsbyNodeFields: true
});
// alias conflicting inline fragment fields
transformedInlineFragments = transformedInlineFragments.map(({
fields,
...inlineFragment
}) => {
return {
...inlineFragment,
fields: aliasConflictingFields({
transformedFields: fields
})
};
});
}
// mutates the fragments..
aliasConflictingFragmentFields({
fragments
});
const aliasedTransformedFields = aliasConflictingFields({
transformedFields,
parentType: type
});
const selectionSet = (0, _buildQueryOnFieldName.buildSelectionSet)(aliasedTransformedFields, {
fieldPath: name,
fragments,
transformedInlineFragments
});
const builtFragments = (0, _buildQueryOnFieldName.generateReusableFragments)({
fragments,
selectionSet
});
const nodeQuery = (0, _buildQueryOnFieldName.buildNodeQueryOnFieldName)({
fields: transformedFields,
fieldName: singleFieldName,
settings,
builtFragments,
builtSelectionSet: selectionSet
});
const previewQuery = (0, _buildQueryOnFieldName.buildNodeQueryOnFieldName)({
fields: transformedFields,
fieldName: singleFieldName,
fieldInputArguments: `id: $id, idType: ID, asPreview: true`,
queryName: `PREVIEW_QUERY`,
settings,
builtFragments,
builtSelectionSet: selectionSet
});
const fieldVariables = settings.where ? `where: { ${settings.where} }` : ``;
if (settings.nodeListQueries && typeof settings.nodeListQueries === `function`) {
const queries = settings.nodeListQueries({
name,
fields,
selectionSet,
builtFragments,
singleFieldName,
singleNodeRootFieldInfo,
settings,
store: (0, _store.getStore)(),
fieldVariables,
remoteSchema,
transformedFields,
helpers: {
recursivelyTransformFields: _recursivelyTransformFields.default,
buildNodesQueryOnFieldName: _buildQueryOnFieldName.buildNodesQueryOnFieldName
}
});
if (queries && queries.length) {
nodeListQueries = queries;
}
}
if (!nodeListQueries || !nodeListQueries.length) {
const nodeListQuery = (0, _buildQueryOnFieldName.buildNodesQueryOnFieldName)({
fields: transformedFields,
fieldName: name,
fieldVariables,
settings,
builtFragments,
builtSelectionSet: selectionSet
});
nodeListQueries = [nodeListQuery];
}
if (process.env.NODE_ENV === `development` && nodesType.name === copyNodeSourcingQueryAndExit) {
try {
reporter.log(``);
reporter.warn((0, _formatLogMessage.formatLogMessage)(`Query debug mode. Writing node list query for the ${nodesType.name} node type to the system clipboard and exiting\n\n`));
// clipboardy is ESM-only package
const {
default: clipboardy
} = await import(`clipboardy`);
await clipboardy.write(_prettier.default.format(nodeListQueries[0], {
parser: `graphql`
}));
process.exit();
} catch (e) {
reporter.log(``);
reporter.error(e);
reporter.log(``);
reporter.warn((0, _formatLogMessage.formatLogMessage)(`Query debug mode failed. There was a failed attempt to copy the query for the ${nodesType.name} node type to your clipboard.\n\n`));
reporter.error(e);
}
}
// build a query info object containing gql query strings for fetching
// node lists or single nodes, as well as type info and plugin
// settings for this type
nodeQueries[name] = {
typeInfo: {
singularName: singleFieldName,
pluralName: name,
nodesTypeName: nodesType.name
},
nodeListQueries,
nodeQuery,
previewQuery,
selectionSet,
builtFragments,
settings
};
}
return nodeQueries;
};
var _default = generateNodeQueriesFromIngestibleFields;
exports.default = _default;
//# sourceMappingURL=generate-queries-from-ingestable-types.js.map