"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.setFieldMappingResolverReference = exports.condenseRangeKey = exports.updateTableForConnection = exports.updateTableForReferencesConnection = void 0;
const graphql_index_transformer_1 = require("@aws-amplify/graphql-index-transformer");
const graphql_transformer_core_1 = require("@aws-amplify/graphql-transformer-core");
const cdk = __importStar(require("aws-cdk-lib"));
const graphql_transformer_common_1 = require("graphql-transformer-common");
const schema_1 = require("./schema");
const utils_1 = require("./utils");
const updateTableForReferencesConnection = (config, ctx) => {
    const { field, referenceNodes, indexName: incomingIndexName, object, references, relatedType } = config;
    const mappedObjectName = ctx.resourceHelper.getModelNameMapping(object.name.value);
    if (incomingIndexName) {
        throw new Error(`Invalid @hasMany directive on ${mappedObjectName}.${field.name.value} - indexName is not supported with DDB references.`);
    }
    if (references.length < 1 || referenceNodes.length < 1) {
        throw new Error('references should not be empty here');
    }
    const indexName = `gsi-${mappedObjectName}.${field.name.value}`;
    config.indexName = indexName;
    const relatedTable = (0, graphql_transformer_core_1.getTable)(ctx, relatedType);
    const gsis = relatedTable.globalSecondaryIndexes;
    if (gsis.some((gsi) => gsi.indexName === indexName)) {
        return;
    }
    const referenceNode = referenceNodes[0];
    const partitionKeyName = referenceNode.name.value;
    const partitionKeyType = (0, graphql_index_transformer_1.attributeTypeFromType)(referenceNode.type, ctx);
    const sortKeyReferenceNodes = referenceNodes.slice(1);
    const sortKey = getReferencesBasedDDBSortKey(sortKeyReferenceNodes, ctx);
    addGlobalSecondaryIndex(relatedTable, {
        indexName: indexName,
        partitionKey: { name: partitionKeyName, type: partitionKeyType },
        sortKey: sortKey,
        ctx: ctx,
        relatedTypeName: relatedType.name.value,
    });
};
exports.updateTableForReferencesConnection = updateTableForReferencesConnection;
const getReferencesBasedDDBSortKey = (sortKeyNodes, ctx) => {
    if (sortKeyNodes.length === 1) {
        return {
            name: sortKeyNodes[0].name.value,
            type: (0, graphql_index_transformer_1.attributeTypeFromType)(sortKeyNodes[0].type, ctx),
        };
    }
    else if (sortKeyNodes.length > 1) {
        const sortKeyFieldNames = sortKeyNodes.map((node) => node.name.value);
        return {
            name: (0, exports.condenseRangeKey)(sortKeyFieldNames),
            type: 'S',
        };
    }
    return undefined;
};
const updateTableForConnection = (config, ctx) => {
    const { fields, indexName: incomingIndexName } = config;
    if (incomingIndexName || fields.length > 0) {
        return;
    }
    const { field, object, relatedType } = config;
    const mappedObjectName = ctx.resourceHelper.getModelNameMapping(object.name.value);
    const table = (0, graphql_transformer_core_1.getTable)(ctx, relatedType);
    const gsis = table.globalSecondaryIndexes;
    const indexName = `gsi-${mappedObjectName}.${field.name.value}`;
    config.indexName = indexName;
    if (gsis.some((gsi) => gsi.indexName === indexName)) {
        return;
    }
    const respectPrimaryKeyAttributesOnConnectionField = ctx.transformParameters.respectPrimaryKeyAttributesOnConnectionField;
    const partitionKeyName = (0, utils_1.getConnectionAttributeName)(ctx.transformParameters, mappedObjectName, field.name.value, (0, utils_1.getObjectPrimaryKey)(object).name.value);
    const partitionKeyType = respectPrimaryKeyAttributesOnConnectionField
        ? (0, graphql_index_transformer_1.attributeTypeFromType)((0, utils_1.getObjectPrimaryKey)(object).type, ctx)
        : 'S';
    const sortKey = respectPrimaryKeyAttributesOnConnectionField
        ? getConnectedSortKeyAttributeDefinitionsForImplicitHasManyObject(ctx, object, field, (0, schema_1.getSortKeyFields)(ctx, object))
        : undefined;
    addGlobalSecondaryIndex(table, {
        indexName: indexName,
        partitionKey: { name: partitionKeyName, type: partitionKeyType },
        sortKey: sortKey,
        ctx: ctx,
        relatedTypeName: relatedType.name.value,
    });
};
exports.updateTableForConnection = updateTableForConnection;
const addGlobalSecondaryIndex = (table, props) => {
    const { indexName, partitionKey, sortKey, ctx, relatedTypeName } = props;
    table.addGlobalSecondaryIndex({
        indexName,
        projectionType: 'ALL',
        partitionKey: {
            name: partitionKey.name,
            type: partitionKey.type,
        },
        sortKey: sortKey
            ? {
                name: sortKey.name,
                type: sortKey.type,
            }
            : undefined,
        readCapacity: cdk.Fn.ref(graphql_transformer_common_1.ResourceConstants.PARAMETERS.DynamoDBModelTableReadIOPS),
        writeCapacity: cdk.Fn.ref(graphql_transformer_common_1.ResourceConstants.PARAMETERS.DynamoDBModelTableWriteIOPS),
    });
    const gsi = table.globalSecondaryIndexes.find((g) => g.indexName === indexName);
    const newIndex = {
        indexName,
        keySchema: gsi.keySchema,
        projection: { projectionType: 'ALL' },
        provisionedThroughput: cdk.Fn.conditionIf(graphql_transformer_common_1.ResourceConstants.CONDITIONS.ShouldUsePayPerRequestBilling, cdk.Fn.ref('AWS::NoValue'), {
            ReadCapacityUnits: cdk.Fn.ref(graphql_transformer_common_1.ResourceConstants.PARAMETERS.DynamoDBModelTableReadIOPS),
            WriteCapacityUnits: cdk.Fn.ref(graphql_transformer_common_1.ResourceConstants.PARAMETERS.DynamoDBModelTableWriteIOPS),
        }),
    };
    (0, graphql_index_transformer_1.overrideIndexAtCfnLevel)(ctx, relatedTypeName, table, newIndex);
};
const getConnectedSortKeyAttributeDefinitionsForImplicitHasManyObject = (ctx, object, hasManyField, sortKeyFields) => {
    if (!sortKeyFields.length) {
        return undefined;
    }
    const mappedObjectName = ctx.resourceHelper.getModelNameMapping(object.name.value);
    const connectedSortKeyFieldNames = sortKeyFields.map((sortKeyField) => (0, utils_1.getConnectionAttributeName)(ctx.transformParameters, mappedObjectName, hasManyField.name.value, sortKeyField.name.value));
    if (connectedSortKeyFieldNames.length === 1) {
        return {
            name: connectedSortKeyFieldNames[0],
            type: (0, graphql_index_transformer_1.attributeTypeFromType)(sortKeyFields[0].type, ctx),
        };
    }
    else if (sortKeyFields.length > 1) {
        return {
            name: (0, exports.condenseRangeKey)(connectedSortKeyFieldNames),
            type: 'S',
        };
    }
    return undefined;
};
const condenseRangeKey = (fields) => {
    return fields.join(graphql_transformer_common_1.ModelResourceIDs.ModelCompositeKeySeparator());
};
exports.condenseRangeKey = condenseRangeKey;
const setFieldMappingResolverReference = (context, mappedModelName, typeName, fieldName, isList = false) => {
    const modelFieldMap = context.resourceHelper.getModelFieldMap(mappedModelName);
    if (!modelFieldMap.getMappedFields().length) {
        return;
    }
    modelFieldMap.addResolverReference({ typeName: typeName, fieldName: fieldName, isList: isList });
};
exports.setFieldMappingResolverReference = setFieldMappingResolverReference;
//# sourceMappingURL=resolvers.js.map